Program-wide avatar cache

Add a program-wide avatar cache― whenever a contact or user's avatar has
changed, it gets cached in ~/config/settings/Caya/Cache/$account/People
(for contacts) or $account/Users (for everyone else).

ImageCache is now used, only for caching the kPersonIcon resource image―
it might be useful later for other commonly used images (status
indicators, etc).

Fixes #4
This commit is contained in:
Jaidyn Ann 2021-06-13 17:34:30 -05:00
parent b2489a5551
commit 6c43311982
8 changed files with 151 additions and 51 deletions

View File

@ -117,11 +117,9 @@ CayaCachePath()
BPath path; BPath path;
if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK) if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
return NULL; return NULL;
path.Append("Caya/Cache"); path.Append("Caya/Cache");
if (create_directory(path.Path(), 0755) != B_OK) if (create_directory(path.Path(), 0755) != B_OK)
return NULL; return NULL;
return path.Path(); return path.Path();
} }
@ -133,7 +131,6 @@ CayaAccountCachePath(const char* accountName)
if (path.InitCheck() != B_OK) if (path.InitCheck() != B_OK)
return NULL; return NULL;
path.Append(accountName); path.Append(accountName);
if (create_directory(path.Path(), 0755) != B_OK) if (create_directory(path.Path(), 0755) != B_OK)
return NULL; return NULL;
return path.Path(); return path.Path();
@ -147,7 +144,6 @@ CayaRoomsCachePath(const char* accountName)
if (path.InitCheck() != B_OK) if (path.InitCheck() != B_OK)
return NULL; return NULL;
path.Append("Rooms"); path.Append("Rooms");
if (create_directory(path.Path(), 0755) != B_OK) if (create_directory(path.Path(), 0755) != B_OK)
return NULL; return NULL;
return path.Path(); return path.Path();
@ -158,13 +154,36 @@ const char*
CayaRoomCachePath(const char* accountName, const char* roomIdentifier) CayaRoomCachePath(const char* accountName, const char* roomIdentifier)
{ {
BPath path(CayaRoomsCachePath(accountName)); BPath path(CayaRoomsCachePath(accountName));
if (path.InitCheck() != B_OK) if (path.InitCheck() != B_OK) return NULL;
return NULL;
path.Append(roomIdentifier); path.Append(roomIdentifier);
return path.Path(); return path.Path();
} }
const char*
CayaUserCachePath(const char* accountName, const char* userIdentifier)
{
BPath path(CayaAccountCachePath(accountName));
if (path.InitCheck() != B_OK) return NULL;
path.Append("Users");
if (create_directory(path.Path(), 0755) != B_OK) return NULL;
path.Append(userIdentifier);
return path.Path();
}
const char*
CayaContactCachePath(const char* accountName, const char* userIdentifier)
{
BPath path(CayaAccountCachePath(accountName));
if (path.InitCheck() != B_OK) return NULL;
path.Append("People");
if (create_directory(path.Path(), 0755) != B_OK) return NULL;
path.Append(userIdentifier);
return path.Path();
}
rgb_color rgb_color
CayaTintColor(rgb_color color, int severity) CayaTintColor(rgb_color color, int severity)
{ {

View File

@ -27,6 +27,8 @@ const char* CayaCachePath();
const char* CayaAccountCachePath(const char* accountName); const char* CayaAccountCachePath(const char* accountName);
const char* CayaRoomsCachePath(const char* accountName); const char* CayaRoomsCachePath(const char* accountName);
const char* CayaRoomCachePath(const char* accountName, const char* roomIdentifier); const char* CayaRoomCachePath(const char* accountName, const char* roomIdentifier);
const char* CayaUserCachePath(const char* accountName, const char* userIdentifier);
const char* CayaContactCachePath(const char* accountName, const char* userIdentifier);
rgb_color CayaTintColor(rgb_color color, int severity); rgb_color CayaTintColor(rgb_color color, int severity);
rgb_color CayaForegroundColor(rgb_color background); rgb_color CayaForegroundColor(rgb_color background);

View File

@ -9,6 +9,8 @@
*/ */
#include "Contact.h" #include "Contact.h"
#include "CayaUtils.h"
#include "ProtocolLooper.h"
#include "RosterItem.h" #include "RosterItem.h"
@ -37,3 +39,13 @@ Contact::SetNotifyAvatarBitmap(BBitmap* bitmap)
} }
void
Contact::_EnsureCachePath()
{
if (fCachePath.InitCheck() == B_OK)
return;
fCachePath.SetTo(CayaContactCachePath(fLooper->Protocol()->GetName(),
fID.String()));
}

View File

@ -9,6 +9,7 @@
#include <String.h> #include <String.h>
#include <Message.h> #include <Message.h>
#include <Messenger.h> #include <Messenger.h>
#include <Path.h>
#include "CayaConstants.h" #include "CayaConstants.h"
#include "User.h" #include "User.h"
@ -28,6 +29,8 @@ public:
void SetNotifyAvatarBitmap(BBitmap* bitmap); void SetNotifyAvatarBitmap(BBitmap* bitmap);
private: private:
virtual void _EnsureCachePath();
RosterItem* fRosterItem; RosterItem* fRosterItem;
}; };

View File

@ -1,5 +1,6 @@
/* /*
* Copyright 2009-2011, Andrea Anzani. All rights reserved. * Copyright 2009-2011, Andrea Anzani. All rights reserved.
* Copyright 2021, Jaidyn Levesque. All rights reserved.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
@ -11,13 +12,21 @@
#include <AppDefs.h> #include <AppDefs.h>
#include <Bitmap.h> #include <Bitmap.h>
#include <Debug.h> #include <Debug.h>
#include <Resources.h>
#include <TranslationUtils.h> #include <TranslationUtils.h>
#include <libinterface/BitmapUtils.h>
#include "CayaResources.h"
#include "CayaUtils.h"
ImageCache* ImageCache::fInstance = NULL; ImageCache* ImageCache::fInstance = NULL;
ImageCache::ImageCache() ImageCache::ImageCache()
{ {
_LoadResource(kPersonIcon, "kPersonIcon");
} }
@ -30,24 +39,25 @@ ImageCache::~ImageCache()
} }
BBitmap* ImageCache*
ImageCache::GetImage(BString which, BString name) ImageCache::Get()
{ {
if (fInstance == NULL) if (fInstance == NULL) {
fInstance = new ImageCache(); fInstance = new ImageCache();
}
return fInstance;
}
BBitmap*
ImageCache::GetImage(const char* keyName)
{
// Loads the bitmap if found // Loads the bitmap if found
bool found; bool found;
BBitmap* bitmap = fInstance->fBitmaps.ValueFor(name, &found); BBitmap* bitmap = fBitmaps.ValueFor(BString(keyName), &found);
if (!found) { if (found == true)
bitmap = LoadImage(which.String(), name.String());
if (bitmap)
fInstance->fBitmaps.AddItem(name, bitmap);
return bitmap; return bitmap;
} else
return bitmap;
return NULL; return NULL;
} }
@ -55,22 +65,16 @@ ImageCache::GetImage(BString which, BString name)
void void
ImageCache::AddImage(BString name, BBitmap* which) ImageCache::AddImage(BString name, BBitmap* which)
{ {
if (fInstance == NULL) fBitmaps.AddItem(name, which);
fInstance = new ImageCache();
fInstance->fBitmaps.AddItem(name, which);
} }
void void
ImageCache::DeleteImage(BString name) ImageCache::DeleteImage(BString name)
{ {
if (fInstance == NULL) BBitmap* bitmap = fBitmaps.ValueFor(name);
fInstance = new ImageCache();
BBitmap* bitmap = fInstance->fBitmaps.ValueFor(name);
if (bitmap) { if (bitmap) {
fInstance->fBitmaps.RemoveItemFor(name); fBitmaps.RemoveItemFor(name);
delete bitmap; delete bitmap;
} }
} }
@ -86,14 +90,13 @@ ImageCache::Release()
} }
BBitmap* void
ImageCache::LoadImage(const char* fullName, const char* shortName) ImageCache::_LoadResource(int identifier, const char* key)
{ {
BBitmap* bitmap = BTranslationUtils::GetBitmap(fullName); BResources* res = CayaResources();
if (!bitmap) BBitmap* bitmap = IconFromResources(res, identifier, B_LARGE_ICON);
bitmap = BTranslationUtils::GetBitmap('PNG ', shortName); if (bitmap != NULL && bitmap->IsValid() == true)
fBitmaps.AddItem(BString(key), bitmap);
if (!bitmap)
printf("ImageCache: Can't load bitmap! %s\n", fullName);
return bitmap;
} }

View File

@ -14,12 +14,13 @@ class BBitmap;
class ImageCache { class ImageCache {
public: public:
/* Returns the image corresponding to the which constant */ static ImageCache* Get();
static BBitmap* GetImage(BString fullPath,
BString symbolicName);
static void AddImage(BString name, BBitmap* which); /* Returns the image corresponding to the which constant */
static void DeleteImage(BString name); BBitmap* GetImage(const char* keyName);
void AddImage(BString name, BBitmap* which);
void DeleteImage(BString name);
/* Frees the singleton instance of the cache, must be /* Frees the singleton instance of the cache, must be
* called when the application quits. * called when the application quits.
@ -31,11 +32,12 @@ protected:
~ImageCache(); ~ImageCache();
private: private:
static BBitmap* LoadImage(const char* resourceName, void _LoadResource(int identifier, const char* key);
const char*);
static ImageCache* fInstance; static ImageCache* fInstance;
KeyMap<BString, BBitmap*> fBitmaps; KeyMap<BString, BBitmap*> fBitmaps;
}; };
#endif // _IMAGE_CACHE_H #endif // _IMAGE_CACHE_H

View File

@ -1,6 +1,7 @@
/* /*
* Copyright 2009-2011, Andrea Anzani. All rights reserved. * Copyright 2009-2011, Andrea Anzani. All rights reserved.
* Copyright 2012, Dario Casalinuovo. All rights reserved. * Copyright 2012, Dario Casalinuovo. All rights reserved.
* Copyright 2021, Jaidyn Levesque. All rights reserved.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
@ -9,12 +10,16 @@
*/ */
#include "User.h" #include "User.h"
#include <libinterface/BitmapUtils.h> #include <Bitmap.h>
#include <BitmapStream.h>
#include <TranslationUtils.h>
#include <TranslatorRoster.h>
#include "CayaProtocolAddOn.h" #include "CayaProtocolAddOn.h"
#include "CayaResources.h" #include "CayaResources.h"
#include "CayaUtils.h" #include "CayaUtils.h"
#include "Conversation.h" #include "Conversation.h"
#include "ImageCache.h"
#include "NotifyMessage.h" #include "NotifyMessage.h"
#include "ProtocolLooper.h" #include "ProtocolLooper.h"
#include "ProtocolManager.h" #include "ProtocolManager.h"
@ -31,6 +36,7 @@ User::User(BString id, BMessenger msgn)
fListItem(NULL), fListItem(NULL),
fItemColor(CayaForegroundColor(ui_color(B_LIST_BACKGROUND_COLOR))), fItemColor(CayaForegroundColor(ui_color(B_LIST_BACKGROUND_COLOR))),
fStatus(CAYA_OFFLINE), fStatus(CAYA_OFFLINE),
fAvatarBitmap(NULL),
fPopUp(NULL) fPopUp(NULL)
{ {
} }
@ -125,6 +131,8 @@ User::GetName() const
BBitmap* BBitmap*
User::AvatarBitmap() const User::AvatarBitmap() const
{ {
if (fAvatarBitmap == NULL)
return ImageCache::Get()->GetImage("kPersonIcon");
return fAvatarBitmap; return fAvatarBitmap;
} }
@ -168,15 +176,13 @@ User::GetNotifyPersonalStatus() const
void void
User::SetProtocolLooper(ProtocolLooper* looper) User::SetProtocolLooper(ProtocolLooper* looper)
{ {
if (looper) { if (looper != NULL) {
fLooper = looper; fLooper = looper;
BBitmap* avatar = _GetCachedAvatar();
// By default we use the Person icon as avatar icon if (avatar != NULL && avatar->IsValid()) {
BResources* res = CayaResources(); fAvatarBitmap = avatar;
BBitmap* bitmap = IconFromResources(res, NotifyPointer(PTR_AVATAR_BITMAP, (void*)avatar);
kPersonIcon, B_LARGE_ICON); }
SetNotifyAvatarBitmap(bitmap);
} }
} }
@ -196,6 +202,7 @@ User::SetNotifyAvatarBitmap(BBitmap* bitmap)
{ {
if ((fAvatarBitmap != bitmap) && (bitmap != NULL)) { if ((fAvatarBitmap != bitmap) && (bitmap != NULL)) {
fAvatarBitmap = bitmap; fAvatarBitmap = bitmap;
_SetCachedAvatar(bitmap);
NotifyPointer(PTR_AVATAR_BITMAP, (void*)bitmap); NotifyPointer(PTR_AVATAR_BITMAP, (void*)bitmap);
} }
} }
@ -228,3 +235,47 @@ User::Conversations()
} }
void
User::_EnsureCachePath()
{
if (fCachePath.InitCheck() == B_OK)
return;
fCachePath.SetTo(CayaUserCachePath(fLooper->Protocol()->GetName(),
fID.String()));
}
BBitmap*
User::_GetCachedAvatar()
{
_EnsureCachePath();
// Try loading cached avatar
BFile cacheFile(fCachePath.Path(), B_READ_ONLY);
BBitmap* bitmap = BTranslationUtils::GetBitmap(&cacheFile);
if (bitmap != NULL && bitmap->IsValid() == true)
return bitmap;
return NULL;
}
void
User::_SetCachedAvatar(BBitmap* bitmap)
{
_EnsureCachePath();
BFile cacheFile(fCachePath.Path(), B_WRITE_ONLY | B_CREATE_FILE);
BBitmapStream* stream = new BBitmapStream(bitmap);
BTranslatorRoster* roster = BTranslatorRoster::Default();
int32 format_count;
translator_info info;
const translation_format* formats = NULL;
roster->Identify(stream, new BMessage(), &info, 0, "image");
roster->GetOutputFormats(info.translator, &formats, &format_count);
roster->Translate(info.translator, stream, new BMessage(), &cacheFile,
formats[0].type);
}

View File

@ -1,6 +1,7 @@
/* /*
* Copyright 2009-2011, Andrea Anzani. All rights reserved. * Copyright 2009-2011, Andrea Anzani. All rights reserved.
* Copyright 2012, Dario Casalinuovo. All rights reserved. * Copyright 2012, Dario Casalinuovo. All rights reserved.
* Copyright 2021, Jaidyn Levesque. All rights reserved.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#ifndef USER_H #ifndef USER_H
@ -10,6 +11,7 @@
#include <Message.h> #include <Message.h>
#include <Messenger.h> #include <Messenger.h>
#include <ObjectList.h> #include <ObjectList.h>
#include <Path.h>
#include <libsupport/KeyMap.h> #include <libsupport/KeyMap.h>
@ -66,6 +68,11 @@ public:
rgb_color fItemColor; rgb_color fItemColor;
protected: protected:
virtual void _EnsureCachePath();
BBitmap* _GetCachedAvatar();
void _SetCachedAvatar(BBitmap* avatar);
BMessenger fMessenger; BMessenger fMessenger;
ProtocolLooper* fLooper; ProtocolLooper* fLooper;
@ -76,6 +83,7 @@ protected:
BString fName; BString fName;
BString fPersonalStatus; BString fPersonalStatus;
BBitmap* fAvatarBitmap; BBitmap* fAvatarBitmap;
BPath fCachePath;
CayaStatus fStatus; CayaStatus fStatus;
UserPopUp* fPopUp; UserPopUp* fPopUp;
ChatMap fConversations; ChatMap fConversations;