From 726db742bdcadf2f47db835ddb7081e32bef342a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20A=C3=9Fmus?= Date: Sat, 5 Apr 2014 23:24:52 +0200 Subject: [PATCH] HaikuDepot: Implemented simple icon-cache. * In a first round, icons are trying to be loaded from the icon cache. * In a second round, the cached icons are updated from the server, unless the icons files have been modified within the last hour. The web-app does support headers for checking if the resource has been modified since a certain date, however, with hvif being so small and the time it takes to connect to the server per individual icon being so relatively long, it doesn't seem worth it just yet to optimize for not actually getting the icon data in response. --- src/apps/haikudepot/Model.cpp | 53 ++++++++++++++++++++++++++++++++--- src/apps/haikudepot/Model.h | 5 ++-- 2 files changed, 52 insertions(+), 6 deletions(-) diff --git a/src/apps/haikudepot/Model.cpp b/src/apps/haikudepot/Model.cpp index 1cee127531..440907f35d 100644 --- a/src/apps/haikudepot/Model.cpp +++ b/src/apps/haikudepot/Model.cpp @@ -6,11 +6,18 @@ #include "Model.h" +#include #include #include +#include #include #include +#include +#include +#include +#include +#include #include "WebAppInterface.h" @@ -564,13 +571,14 @@ int32 Model::_PopulateAllPackagesEntry(void* cookie) { Model* model = static_cast(cookie); - model->_PopulateAllPackagesThread(); + model->_PopulateAllPackagesThread(true); + model->_PopulateAllPackagesThread(false); return 0; } void -Model::_PopulateAllPackagesThread() +Model::_PopulateAllPackagesThread(bool fromCacheOnly) { int32 depotIndex = 0; int32 packageIndex = 0; @@ -601,7 +609,7 @@ Model::_PopulateAllPackagesThread() if (package.Get() == NULL) continue; - _PopulatePackageIcon(package); + _PopulatePackageIcon(package, fromCacheOnly); // TODO: Average user rating. It needs to be shown in the // list view, so without the user clicking the package. } @@ -609,8 +617,41 @@ Model::_PopulateAllPackagesThread() void -Model::_PopulatePackageIcon(const PackageInfoRef& package) +Model::_PopulatePackageIcon(const PackageInfoRef& package, bool fromCacheOnly) { + // See if there is a cached icon file + BFile iconFile; + BPath iconCachePath; + bool fileExists = false; + BString iconName(package->Title()); + iconName << ".hvif"; + time_t modifiedTime; + if (find_directory(B_USER_SETTINGS_DIRECTORY, &iconCachePath) == B_OK + && iconCachePath.Append("HaikuDepot/IconCache") == B_OK + && create_directory(iconCachePath.Path(), 0777) == B_OK + && iconCachePath.Append(iconName) == B_OK) { + // Try opening the file in read-only mode, which will fail if its + // not a file or does not exist. + fileExists = iconFile.SetTo(iconCachePath.Path(), B_READ_ONLY) == B_OK; + if (fileExists) + iconFile.GetModificationTime(&modifiedTime); + } + + if (fileExists) { + time_t now; + time(&now); + if (fromCacheOnly || now - modifiedTime < 60 * 60) { + // Cache file is recent enough, just use it and return. + BitmapRef bitmapRef(new(std::nothrow)SharedBitmap(iconFile), true); + package->SetIcon(bitmapRef); + return; + } + } + + if (fromCacheOnly) + return; + + // Retrieve icon from web-app WebAppInterface interface; BMallocIO buffer; @@ -618,5 +659,9 @@ Model::_PopulatePackageIcon(const PackageInfoRef& package) if (status == B_OK) { BitmapRef bitmapRef(new(std::nothrow)SharedBitmap(buffer), true); package->SetIcon(bitmapRef); + if (iconFile.SetTo(iconCachePath.Path(), + B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE) == B_OK) { + iconFile.Write(buffer.Buffer(), buffer.BufferLength()); + } } } diff --git a/src/apps/haikudepot/Model.h b/src/apps/haikudepot/Model.h index a03b667196..6a4041fd0e 100644 --- a/src/apps/haikudepot/Model.h +++ b/src/apps/haikudepot/Model.h @@ -91,10 +91,11 @@ public: private: static int32 _PopulateAllPackagesEntry(void* cookie); - void _PopulateAllPackagesThread(); + void _PopulateAllPackagesThread(bool fromCacheOnly); void _PopulatePackageIcon( - const PackageInfoRef& package); + const PackageInfoRef& package, + bool fromCacheOnly); private: BLocker fLock;