diff --git a/html/src/app.js b/html/src/app.js
index 607f2212..8c7b1a61 100644
--- a/html/src/app.js
+++ b/html/src/app.js
@@ -1255,6 +1255,9 @@ speechSynthesis.getVoices();
API.applyCurrentUser = function (json) {
var ref = this.currentUser;
if (this.isLoggedIn) {
+ if (json.currentAvatar !== ref.currentAvatar) {
+ $app.addAvatarToHistory(json.currentAvatar);
+ }
Object.assign(ref, json);
if (ref.homeLocation !== ref.$homeLocation.tag) {
ref.$homeLocation = this.parseLocation(ref.homeLocation);
@@ -18949,7 +18952,8 @@ speechSynthesis.getVoices();
API.cachedAvatars.forEach((ref, id) => {
if (
!API.cachedFavoritesByObjectId.has(id) &&
- ref.authorId !== API.currentUser.id
+ ref.authorId !== API.currentUser.id &&
+ !$app.avatarHistory.has(id)
) {
API.cachedAvatars.delete(id);
}
@@ -19660,6 +19664,71 @@ speechSynthesis.getVoices();
API.currentUser.$travelingToTime = this.lastLocationDestinationTime;
};
+ $app.data.avatarHistory = new Set();
+ $app.data.avatarHistoryArray = [];
+
+ API.$on('LOGIN', async function () {
+ $app.avatarHistory = new Set();
+ var historyArray = await database.getAvatarHistory();
+ $app.avatarHistoryArray = historyArray;
+ for (var i = 0; i < historyArray.length; i++) {
+ $app.avatarHistory.add(historyArray[i].id);
+ this.applyAvatar(historyArray[i]);
+ }
+ });
+
+ $app.methods.addAvatarToHistory = function (avatarId) {
+ var historyArray = $app.avatarHistoryArray;
+ for (var i = 0; i < historyArray.length; ++i) {
+ if (historyArray[i].id === avatarId) {
+ historyArray.splice(i, 1);
+ }
+ }
+ this.avatarHistory.delete(avatarId);
+ this.avatarHistory.add(avatarId);
+ database.addAvatarToHistory(avatarId);
+ API.getAvatar({avatarId});
+ };
+
+ API.$on('AVATAR', function (args) {
+ var ref = args.json;
+ // if in history add/update cache
+ if ($app.avatarHistory.has(ref.id)) {
+ database.addAvatarToCache(ref);
+
+ // only add to array if not in array
+ var inArray = false;
+ var historyArray = $app.avatarHistoryArray;
+ for (var i = 0; i < historyArray.length; ++i) {
+ if (historyArray[i].id === ref.id) {
+ inArray = true;
+ }
+ }
+ if (!inArray) {
+ $app.avatarHistoryArray.unshift(ref);
+ }
+ }
+ });
+
+ $app.methods.promptClearAvatarHistory = function () {
+ this.$confirm('Continue? Clear Avatar History', 'Confirm', {
+ confirmButtonText: 'Confirm',
+ cancelButtonText: 'Cancel',
+ type: 'info',
+ callback: (action) => {
+ if (action === 'confirm') {
+ this.clearAvatarHistory();
+ }
+ }
+ });
+ };
+
+ $app.methods.clearAvatarHistory = function () {
+ this.avatarHistory = new Set();
+ this.avatarHistoryArray = [];
+ database.clearAvatarHistory();
+ };
+
$app = new Vue($app);
window.$app = $app;
})();
diff --git a/html/src/index.pug b/html/src/index.pug
index b96ef683..b625faa6 100644
--- a/html/src/index.pug
+++ b/html/src/index.pug
@@ -603,6 +603,26 @@ html
.detail
span.name(v-text="favorite.name || favorite.id")
el-button(type="text" icon="el-icon-close" size="mini" @click.stop="deleteFavorite(favorite.id)" style="margin-left:5px")
+ el-collapse-item
+ template(slot="title")
+ span(style="font-weight:bold;font-size:14px;margin-left:10px") Local History
+ span(style="color:#909399;font-size:12px;margin-left:10px") {{ avatarHistoryArray.length }}/100
+ el-tooltip(placement="right" content="Clear" :disabled="hideTooltips")
+ el-button(@click.stop="promptClearAvatarHistory" size="mini" icon="el-icon-delete" circle style="margin-left:5px")
+ .x-friend-list(v-if="avatarHistoryArray.length" style="margin-top:10px")
+ div(style="display:inline-block;width:300px;margin-right:15px" v-for="favorite in avatarHistoryArray" :key="favorite.id" @click="showAvatarDialog(favorite.id)")
+ .x-friend-item
+ .avatar
+ img(v-lazy="favorite.thumbnailImageUrl")
+ .detail
+ span.name(v-text="favorite.name")
+ span.extra(v-text="favorite.authorName")
+ template(v-if="API.cachedFavoritesByObjectId.has(favorite.id)")
+ el-tooltip(placement="left" content="Unfavorite" :disabled="hideTooltips")
+ el-button(@click.stop="deleteFavorite(favorite.id)" type="default" icon="el-icon-star-on" size="mini" circle)
+ template(v-else)
+ el-tooltip(placement="left" content="Favorite" :disabled="hideTooltips")
+ el-button(@click.stop="showFavoriteDialog('avatar', favorite.id)" type="default" icon="el-icon-star-off" size="mini" circle)
//- friendLog
.x-container(v-show="$refs.menu && $refs.menu.activeIndex === 'friendLog'" v-if="$refs.menu && $refs.menu.activeIndex === 'friendLog'")
diff --git a/html/src/repository/database.js b/html/src/repository/database.js
index 568cc201..f63a47f6 100644
--- a/html/src/repository/database.js
+++ b/html/src/repository/database.js
@@ -32,6 +32,9 @@ class Database {
await sqliteService.executeNonQuery(
`CREATE TABLE IF NOT EXISTS ${Database.userPrefix}_moderation (user_id TEXT PRIMARY KEY, updated_at TEXT, display_name TEXT, block INTEGER, mute INTEGER)`
);
+ await sqliteService.executeNonQuery(
+ `CREATE TABLE IF NOT EXISTS ${Database.userPrefix}_avatar_history (avatar_id TEXT PRIMARY KEY, created_at TEXT)`
+ );
await sqliteService.executeNonQuery(
`CREATE TABLE IF NOT EXISTS memos (user_id TEXT PRIMARY KEY, edited_at TEXT, memo TEXT)`
);
@@ -53,6 +56,9 @@ class Database {
await sqliteService.executeNonQuery(
`CREATE TABLE IF NOT EXISTS gamelog_event (id INTEGER PRIMARY KEY, created_at TEXT, data TEXT, UNIQUE(created_at, data))`
);
+ await sqliteService.executeNonQuery(
+ `CREATE TABLE IF NOT EXISTS cache_avatar (id TEXT PRIMARY KEY, added_at TEXT, author_id TEXT, author_name TEXT, created_at TEXT, description TEXT, image_url TEXT, name TEXT, release_status TEXT, thumbnail_image_url TEXT, updated_at TEXT, version INTEGER)`
+ );
}
async getFeedDatabase() {
@@ -1426,6 +1432,64 @@ class Database {
AND ((trust_level = 'Veteran User' AND previous_trust_level = 'Trusted User') OR (trust_level = 'Trusted User' AND previous_trust_level = 'Veteran User'))`
);
}
+
+ addAvatarToCache(entry) {
+ sqliteService.executeNonQuery(
+ `INSERT OR REPLACE INTO cache_avatar (id, added_at, author_id, author_name, created_at, description, image_url, name, release_status, thumbnail_image_url, updated_at, version) VALUES (@id, @added_at, @author_id, @author_name, @created_at, @description, @image_url, @name, @release_status, @thumbnail_image_url, @updated_at, @version)`,
+ {
+ '@id': entry.id,
+ '@added_at': new Date().toJSON(),
+ '@author_id': entry.authorId,
+ '@author_name': entry.authorName,
+ '@created_at': entry.created_at,
+ '@description': entry.description,
+ '@image_url': entry.imageUrl,
+ '@name': entry.name,
+ '@release_status': entry.releaseStatus,
+ '@thumbnail_image_url': entry.thumbnailImageUrl,
+ '@updated_at': entry.updated_at,
+ '@version': entry.version
+ }
+ );
+ }
+
+ addAvatarToHistory(avatarId) {
+ sqliteService.executeNonQuery(
+ `INSERT OR REPLACE INTO ${Database.userPrefix}_avatar_history (avatar_id, created_at) VALUES (@avatar_id, @created_at)`,
+ {
+ '@avatar_id': avatarId,
+ '@created_at': new Date().toJSON()
+ }
+ );
+ }
+
+ async getAvatarHistory() {
+ var data = [];
+ await sqliteService.execute((dbRow) => {
+ var row = {
+ id: dbRow[0],
+ authorId: dbRow[4],
+ authorName: dbRow[5],
+ created_at: dbRow[6],
+ description: dbRow[7],
+ imageUrl: dbRow[8],
+ name: dbRow[9],
+ releaseStatus: dbRow[10],
+ thumbnailImageUrl: dbRow[11],
+ updated_at: dbRow[12],
+ version: dbRow[13]
+ };
+ data.unshift(row);
+ }, `SELECT * FROM ${Database.userPrefix}_avatar_history INNER JOIN cache_avatar ON cache_avatar.id = ${Database.userPrefix}_avatar_history.avatar_id LIMIT 100`);
+ return data;
+ }
+
+ clearAvatarHistory() {
+ sqliteService.executeNonQuery(
+ `DELETE FROM ${Database.userPrefix}_avatar_history`
+ );
+ sqliteService.executeNonQuery('DELETE FROM cache_avatar');
+ }
}
var self = new Database();