diff --git a/browser/components/places/public/nsINavHistoryService.idl b/browser/components/places/public/nsINavHistoryService.idl index 1f69b01b824e..0682ecb56477 100644 --- a/browser/components/places/public/nsINavHistoryService.idl +++ b/browser/components/places/public/nsINavHistoryService.idl @@ -247,12 +247,6 @@ interface nsINavHistoryResult : nsINavHistoryResultNode */ void recursiveSort(in PRUint32 aSortingMode); - /** - * Controls whether the day appears when time columns are requested - * through the tree interface. True is the default, meaning the date is shown - */ - attribute boolean timesIncludeDates; - /** * Controls whether duplicate adjacent elements are collapsed into a single * item in the tree. This prevents you from seeing multiple entries for diff --git a/browser/components/places/src/nsNavHistory.h b/browser/components/places/src/nsNavHistory.h index 9d933dc18b54..4c4e28b60cb8 100644 --- a/browser/components/places/src/nsNavHistory.h +++ b/browser/components/places/src/nsNavHistory.h @@ -207,6 +207,9 @@ public: OnPageChanged(aURI, aWhat, aValue)); } + // current time optimization + PRTime GetNow(); + // well-known annotations used by the history and bookmarks systems static const char kAnnotationPreviousEncoding[]; @@ -273,7 +276,6 @@ protected: PRTime mLastNow; PRBool mNowValid; nsCOMPtr mExpireNowTimer; - PRTime GetNow(); static void expireNowTimerCallback(nsITimer* aTimer, void* aClosure); PRTime NormalizeTime(PRUint32 aRelative, PRTime aOffset); diff --git a/browser/components/places/src/nsNavHistoryResult.cpp b/browser/components/places/src/nsNavHistoryResult.cpp index cfb00ec002a7..56fe023179a3 100755 --- a/browser/components/places/src/nsNavHistoryResult.cpp +++ b/browser/components/places/src/nsNavHistoryResult.cpp @@ -1071,7 +1071,6 @@ nsNavHistoryResult::nsNavHistoryResult(nsNavHistory* aHistoryService, nsNavHistoryQueryOptions* aOptions) : mBundle(aHistoryBundle), mHistoryService(aHistoryService), mCollapseDuplicates(PR_TRUE), - mTimesIncludeDates(PR_TRUE), mCurrentSort(nsINavHistoryQueryOptions::SORT_BY_NONE) { NS_ASSERTION(aOptions, "must have options!"); @@ -1220,20 +1219,6 @@ nsNavHistoryResult::RecursiveSort(PRUint32 aSortingMode) } -// nsNavHistoryResult::Get/SetTimesIncludeDates - -NS_IMETHODIMP nsNavHistoryResult::SetTimesIncludeDates(PRBool aValue) -{ - mTimesIncludeDates = aValue; - return NS_OK; -} -NS_IMETHODIMP nsNavHistoryResult::GetTimesIncludeDates(PRBool* aValue) -{ - *aValue = mTimesIncludeDates; - return NS_OK; -} - - // nsNavHistoryResult::Get/SetCollapseDuplicates NS_IMETHODIMP nsNavHistoryResult::SetCollapseDuplicates(PRBool aValue) @@ -1591,6 +1576,85 @@ PRInt32 PR_CALLBACK nsNavHistoryResult::SortComparison_VisitCountGreater( } +// nsNavHistoryResult::FormatFriendlyTime + +nsresult +nsNavHistoryResult::FormatFriendlyTime(PRTime aTime, nsAString& aResult) +{ + // use navHistory's GetNow function for performance + nsNavHistory* history = nsNavHistory::GetHistoryService(); + NS_ENSURE_TRUE(history, NS_ERROR_OUT_OF_MEMORY); + PRTime now = history->GetNow(); + + const PRInt64 ago = now - aTime; + + /* + * This code generates strings like "X minutes ago" when the time is very + * recent. This looks much nicer, but we will have to redraw the list + * periodically. I also found it a little strange watching the numbers in + * the list change as I browse. For now, I'll leave this commented out, + * perhaps we can revisit whether it is a good idea to do this and put in + * the proper auto-refresh code so the numbers stay correct. + * + * To enable, you'll need to put these in places.properties: + * 0MinutesAgo=<1 minute ago + * 1MinutesAgo=1 minute ago + * XMinutesAgo=%s minutes ago + + static const PRInt64 minuteThreshold = (PRInt64)1000000 * 60 * 60; + if (ago > -10000000 && ago < minuteThreshold) { + // show "X minutes ago" + PRInt64 minutesAgo = NSToIntFloor( + NS_STATIC_CAST(float, (ago / 1000000)) / 60.0); + + nsXPIDLString resultString; + if (minutesAgo == 0) { + nsresult rv = mBundle->GetStringFromName( + NS_LITERAL_STRING("0MinutesAgo").get(), getter_Copies(resultString)); + NS_ENSURE_SUCCESS(rv, rv); + } else if (minutesAgo == 1) { + nsresult rv = mBundle->GetStringFromName( + NS_LITERAL_STRING("1MinutesAgo").get(), getter_Copies(resultString)); + NS_ENSURE_SUCCESS(rv, rv); + } else { + nsAutoString minutesAgoString; + minutesAgoString.AppendInt(minutesAgo); + const PRUnichar* stringPtr = minutesAgoString.get(); + nsresult rv = mBundle->FormatStringFromName( + NS_LITERAL_STRING("XMinutesAgo").get(), + &stringPtr, 1, getter_Copies(resultString)); + NS_ENSURE_SUCCESS(rv, rv); + } + aResult = resultString; + return NS_OK; + } */ + + // Check if it is today and only display the time. Only bother checking for + // today if it's within the last 24 hours, since computing midnight is not + // really cheap. Sometimes we may get dates in the future, so always show + // those. Note the 10s slop in case the cached GetNow value in NavHistory is + // out-of-date. + nsDateFormatSelector dateFormat = nsIScriptableDateFormat::dateFormatShort; + if (ago > -10000000 && ago < (PRInt64)1000000 * 24 * 60 * 60) { + PRExplodedTime explodedTime; + PR_ExplodeTime(aTime, PR_LocalTimeParameters, &explodedTime); + explodedTime.tm_min = + explodedTime.tm_hour = + explodedTime.tm_sec = + explodedTime.tm_usec = 0; + PRTime midnight = PR_ImplodeTime(&explodedTime); + if (aTime > midnight) + dateFormat = nsIScriptableDateFormat::dateFormatNone; + } + nsAutoString resultString; + mDateFormatter->FormatPRTime(mLocale, dateFormat, + nsIScriptableDateFormat::timeFormatNoSeconds, + aTime, resultString); + aResult = resultString; + return NS_OK; +} + + // nsNavHistoryResult::FillTreeStats // // This basically does a recursive depth-first traversal of the tree to fill @@ -2074,16 +2138,7 @@ NS_IMETHODIMP nsNavHistoryResult::GetCellText(PRInt32 rowIndex, // information I know how to use. Only show this for URLs and visits _retval.Truncate(0); } else { - nsDateFormatSelector dateFormat; - if (mTimesIncludeDates) - dateFormat = nsIScriptableDateFormat::dateFormatShort; - else - dateFormat = nsIScriptableDateFormat::dateFormatNone; - nsAutoString realString; // stupid function won't take an nsAString - mDateFormatter->FormatPRTime(mLocale, dateFormat, - nsIScriptableDateFormat::timeFormatNoSeconds, - elt->mTime, realString); - _retval = realString; + return FormatFriendlyTime(elt->mTime, _retval); } break; } diff --git a/browser/components/places/src/nsNavHistoryResult.h b/browser/components/places/src/nsNavHistoryResult.h index e86c1c19763c..729938a58373 100644 --- a/browser/components/places/src/nsNavHistoryResult.h +++ b/browser/components/places/src/nsNavHistoryResult.h @@ -286,7 +286,6 @@ private: nsCOMPtr mLocale; nsCOMPtr mCollation; nsCOMPtr mDateFormatter; - PRBool mTimesIncludeDates; // this is the flattened version of the hierarchy containing everything nsVoidArray mAllElements; @@ -344,6 +343,8 @@ private: nsNavHistoryResultNode* a, nsNavHistoryResultNode* b, void* closure); PR_STATIC_CALLBACK(int) SortComparison_VisitCountGreater( nsNavHistoryResultNode* a, nsNavHistoryResultNode* b, void* closure); + + nsresult FormatFriendlyTime(PRTime aTime, nsAString& aResult); }; #endif // nsNavHistoryResult_h_