diff --git a/html/src/app.js b/html/src/app.js index e303f152..21cc024b 100644 --- a/html/src/app.js +++ b/html/src/app.js @@ -19542,7 +19542,7 @@ speechSynthesis.getVoices(); D.isQuest = false; D.isIos = false; D.hasImposter = false; - D.isFavorite = API.cachedFavoritesByObjectId.has(avatarId); + D.isFavorite = API.cachedFavoritesByObjectId.has(avatarId) || (this.isLocalUserVrcplusSupporter() && this.localAvatarFavoritesList.includes(avatarId)); D.isBlocked = API.cachedAvatarModerations.has(avatarId); this.ignoreAvatarMemoSave = true; D.memo = ''; @@ -19639,6 +19639,28 @@ speechSynthesis.getVoices(); }); }; + $app.methods.selectAvatarWithConfirmation = function (id) { + this.$confirm(`Continue? Select Avatar`, 'Confirm', { + confirmButtonText: 'Confirm', + cancelButtonText: 'Cancel', + type: 'info', + callback: (action) => { + if (action !== 'confirm') { + return; + } + API.selectAvatar({ + avatarId: id + }).then((args) => { + this.$message({ + message: 'Avatar changed', + type: 'success' + }); + return args; + }); + } + }); + } + $app.methods.avatarDialogCommand = function (command) { var D = this.avatarDialog; if (D.visible === false) { @@ -28153,6 +28175,316 @@ speechSynthesis.getVoices(); this.worldFavoriteSearchResults = results; }; + // #endregion + // #region | App: Local Avatar Favorites + + $app.methods.isLocalUserVrcplusSupporter = function () { + return API.currentUser.$isVRCPlus; + } + + $app.data.localAvatarFavoriteGroups = []; + $app.data.localAvatarFavoritesList = []; + $app.data.localAvatarFavorites = {}; + + $app.methods.addLocalAvatarFavorite = function (avatarId, group) { + if (this.hasLocalAvatarFavorite(avatarId, group)) { + return; + } + var ref = API.cachedAvatars.get(avatarId); + if (typeof ref === 'undefined') { + return; + } + if (!this.localAvatarFavoritesList.includes(avatarId)) { + this.localAvatarFavoritesList.push(avatarId); + } + if (!this.localAvatarFavorites[group]) { + this.localAvatarFavorites[group] = []; + } + if (!this.localAvatarFavoriteGroups.includes(group)) { + this.localAvatarFavoriteGroups.push(group); + } + this.localAvatarFavorites[group].unshift(ref); + database.addAvatarToCache(ref); + database.addAvatarToFavorites(avatarId, group); + if ( + this.favoriteDialog.visible && + this.favoriteDialog.objectId === avatarId + ) { + this.updateFavoriteDialog(avatarId); + } + if (this.avatarDialog.visible && this.avatarDialog.id === avatarId) { + this.avatarDialog.isFavorite = true; + } + }; + + $app.methods.removeLocalAvatarFavorite = function (avatarId, group) { + var favoriteGroup = this.localAvatarFavorites[group]; + for (var i = 0; i < favoriteGroup.length; ++i) { + if (favoriteGroup[i].id === avatarId) { + favoriteGroup.splice(i, 1); + } + } + + // remove from cache if no longer in favorites + var avatarInFavorites = false; + for (var i = 0; i < this.localAvatarFavoriteGroups.length; ++i) { + var groupName = this.localAvatarFavoriteGroups[i]; + if (!this.localAvatarFavorites[groupName] || group === groupName) { + continue; + } + for ( + var j = 0; + j < this.localAvatarFavorites[groupName].length; + ++j + ) { + var id = this.localAvatarFavorites[groupName][j].id; + if (id === avatarId) { + avatarInFavorites = true; + break; + } + } + } + if (!avatarInFavorites) { + removeFromArray(this.localAvatarFavoritesList, avatarId); + database.removeAvatarFromCache(avatarId); + } + database.removeAvatarFromFavorites(avatarId, group); + if ( + this.favoriteDialog.visible && + this.favoriteDialog.objectId === avatarId + ) { + this.updateFavoriteDialog(avatarId); + } + if (this.avatarDialog.visible && this.avatarDialog.id === avatarId) { + this.avatarDialog.isFavorite = + API.cachedFavoritesByObjectId.has(avatarId); + } + + // update UI + this.sortLocalAvatarFavorites(); + }; + + API.$on('AVATAR', function (args) { + if ($app.localAvatarFavoritesList.includes(args.ref.id)) { + // update db cache + database.addAvatarToCache(args.ref); + } + }); + + API.$on('LOGIN', function () { + $app.getLocalAvatarFavorites(); + }); + + $app.methods.getLocalAvatarFavorites = async function () { + this.localAvatarFavoriteGroups = []; + this.localAvatarFavoritesList = []; + this.localAvatarFavorites = {}; + var avatarCache = await database.getAvatarCache(); + for (var i = 0; i < avatarCache.length; ++i) { + var ref = avatarCache[i]; + if (!API.cachedAvatars.has(ref.id)) { + API.applyAvatar(ref); + } + } + var favorites = await database.getAvatarFavorites(); + for (var i = 0; i < favorites.length; ++i) { + var favorite = favorites[i]; + if (!this.localAvatarFavoritesList.includes(favorite.avatarId)) { + this.localAvatarFavoritesList.push(favorite.avatarId); + } + if (!this.localAvatarFavorites[favorite.groupName]) { + this.localAvatarFavorites[favorite.groupName] = []; + } + if (!this.localAvatarFavoriteGroups.includes(favorite.groupName)) { + this.localAvatarFavoriteGroups.push(favorite.groupName); + } + var ref = API.cachedAvatars.get(favorite.avatarId); + if (typeof ref === 'undefined') { + ref = { + id: favorite.avatarId + }; + } + this.localAvatarFavorites[favorite.groupName].unshift(ref); + } + if (this.localAvatarFavoriteGroups.length === 0) { + // default group + this.localAvatarFavorites.Favorites = []; + this.localAvatarFavoriteGroups.push('Favorites'); + } + this.sortLocalAvatarFavorites(); + }; + + $app.methods.hasLocalAvatarFavorite = function (avatarId, group) { + var favoriteGroup = this.localAvatarFavorites[group]; + if (!favoriteGroup) { + return false; + } + for (var i = 0; i < favoriteGroup.length; ++i) { + if (favoriteGroup[i].id === avatarId) { + return true; + } + } + return false; + }; + + $app.methods.getLocalAvatarFavoriteGroupLength = function (group) { + var favoriteGroup = this.localAvatarFavorites[group]; + if (!favoriteGroup) { + return 0; + } + return favoriteGroup.length; + }; + + $app.methods.promptNewLocalAvatarFavoriteGroup = function () { + this.$prompt( + $t('prompt.new_local_favorite_group.description'), + $t('prompt.new_local_favorite_group.header'), + { + distinguishCancelAndClose: true, + confirmButtonText: $t('prompt.new_local_favorite_group.ok'), + cancelButtonText: $t('prompt.new_local_favorite_group.cancel'), + inputPattern: /\S+/, + inputErrorMessage: $t( + 'prompt.new_local_favorite_group.input_error' + ), + callback: (action, instance) => { + if (action === 'confirm' && instance.inputValue) { + this.newLocalAvatarFavoriteGroup(instance.inputValue); + } + } + } + ); + }; + + $app.methods.newLocalAvatarFavoriteGroup = function (group) { + if (this.localAvatarFavoriteGroups.includes(group)) { + $app.$message({ + message: $t('prompt.new_local_favorite_group.message.error', { + name: group + }), + type: 'error' + }); + return; + } + if (!this.localAvatarFavorites[group]) { + this.localAvatarFavorites[group] = []; + } + if (!this.localAvatarFavoriteGroups.includes(group)) { + this.localAvatarFavoriteGroups.push(group); + } + this.sortLocalAvatarFavorites(); + }; + + $app.methods.promptLocalAvatarFavoriteGroupRename = function (group) { + this.$prompt( + $t('prompt.local_favorite_group_rename.description'), + $t('prompt.local_favorite_group_rename.header'), + { + distinguishCancelAndClose: true, + confirmButtonText: $t( + 'prompt.local_favorite_group_rename.save' + ), + cancelButtonText: $t( + 'prompt.local_favorite_group_rename.cancel' + ), + inputPattern: /\S+/, + inputErrorMessage: $t( + 'prompt.local_favorite_group_rename.input_error' + ), + inputValue: group, + callback: (action, instance) => { + if (action === 'confirm' && instance.inputValue) { + this.renameLocalAvatarFavoriteGroup( + instance.inputValue, + group + ); + } + } + } + ); + }; + + $app.methods.renameLocalAvatarFavoriteGroup = function (newName, group) { + if (this.localAvatarFavoriteGroups.includes(newName)) { + $app.$message({ + message: $t( + 'prompt.local_favorite_group_rename.message.error', + { name: newName } + ), + type: 'error' + }); + return; + } + this.localAvatarFavoriteGroups.push(newName); + this.localAvatarFavorites[newName] = this.localAvatarFavorites[group]; + + removeFromArray(this.localAvatarFavoriteGroups, group); + delete this.localAvatarFavorites[group]; + database.renameAvatarFavoriteGroup(newName, group); + this.sortLocalAvatarFavorites(); + }; + + $app.methods.promptLocalAvatarFavoriteGroupDelete = function (group) { + this.$confirm(`Delete Group? ${group}`, 'Confirm', { + confirmButtonText: 'Confirm', + cancelButtonText: 'Cancel', + type: 'info', + callback: (action) => { + if (action === 'confirm') { + this.deleteLocalAvatarFavoriteGroup(group); + } + } + }); + }; + + $app.methods.sortLocalAvatarFavorites = function () { + this.localAvatarFavoriteGroups.sort(); + if (!this.sortFavorites) { + for (var i = 0; i < this.localAvatarFavoriteGroups.length; ++i) { + var group = this.localAvatarFavoriteGroups[i]; + if (this.localAvatarFavorites[group]) { + this.localAvatarFavorites[group].sort(compareByName); + } + } + } + }; + + $app.methods.deleteLocalAvatarFavoriteGroup = function (group) { + // remove from cache if no longer in favorites + var avatarIdRemoveList = new Set(); + var favoriteGroup = this.localAvatarFavorites[group]; + for (var i = 0; i < favoriteGroup.length; ++i) { + avatarIdRemoveList.add(favoriteGroup[i].id); + } + + removeFromArray(this.localAvatarFavoriteGroups, group); + delete this.localAvatarFavorites[group]; + database.deleteAvatarFavoriteGroup(group); + + for (var i = 0; i < this.localAvatarFavoriteGroups.length; ++i) { + var groupName = this.localAvatarFavoriteGroups[i]; + if (!this.localAvatarFavorites[groupName]) { + continue; + } + for ( + var j = 0; + j < this.localAvatarFavorites[groupName].length; + ++j + ) { + var avatarId = this.localAvatarFavorites[groupName][j].id; + if (avatarIdRemoveList.has(avatarId)) { + avatarIdRemoveList.delete(avatarId); + break; + } + } + } + + avatarIdRemoveList.forEach((id) => { + removeFromArray(this.localAvatarFavoritesList, id); + database.removeAvatarFromCache(id); + }); + }; + // #endregion // #region | Local Favorite Friends diff --git a/html/src/index.pug b/html/src/index.pug index e41d9187..6fc68106 100644 --- a/html/src/index.pug +++ b/html/src/index.pug @@ -877,7 +877,7 @@ html div(style="flex:none;margin-left:10px") el-tooltip(v-if="avatarDialog.inCache" placement="top" :content="$t('dialog.avatar.actions.delete_cache_tooltip')" :disabled="hideTooltips") el-button(icon="el-icon-delete" circle @click="deleteVRChatCache(avatarDialog.ref)" :disabled="isGameRunning && avatarDialog.cacheLocked") - el-tooltip(v-if="avatarDialog.isFavorite" placement="top" :content="$t('dialog.avatar.actions.unfavorite_tooltip')" :disabled="hideTooltips") + el-tooltip(v-if="avatarDialog.isFavorite" placement="top" :content="$t('dialog.avatar.actions.favorite_tooltip')" :disabled="hideTooltips") el-button(type="warning" icon="el-icon-star-on" circle @click="avatarDialogCommand('Add Favorite')" style="margin-left:5px") el-tooltip(v-else placement="top" :content="$t('dialog.avatar.actions.favorite_tooltip')" :disabled="hideTooltips") el-button(type="default" icon="el-icon-star-off" circle @click="avatarDialogCommand('Add Favorite')" style="margin-left:5px") @@ -1312,6 +1312,11 @@ html template(v-for="group in localWorldFavoriteGroups" :key="group") el-button(v-if="hasLocalWorldFavorite(favoriteDialog.objectId, group)" style="display:block;width:100%;margin:10px 0" @click="removeLocalWorldFavorite(favoriteDialog.objectId, group)") #[i.el-icon-check] {{ group }} ({{ getLocalWorldFavoriteGroupLength(group) }}) el-button(v-else style="display:block;width:100%;margin:10px 0" @click="addLocalWorldFavorite(favoriteDialog.objectId, group)") {{ group }} ({{ getLocalWorldFavoriteGroupLength(group) }}) + div(v-if="favoriteDialog.visible && favoriteDialog.type === 'avatar'" style="margin-top:20px") + span(style="display:block;text-align:center") {{ $t('dialog.favorite.local_avatar_favorites') }} + template(v-for="group in localAvatarFavoriteGroups" :key="group") + el-button(v-if="hasLocalAvatarFavorite(favoriteDialog.objectId, group)" style="display:block;width:100%;margin:10px 0" @click="removeLocalAvatarFavorite(favoriteDialog.objectId, group)") #[i.el-icon-check] {{ group }} ({{ getLocalAvatarFavoriteGroupLength(group) }}) + el-button(v-else-if="isLocalUserVrcplusSupporter()" style="display:block;width:100%;margin:10px 0" @click="addLocalAvatarFavorite(favoriteDialog.objectId, group)") {{ group }} ({{ getLocalAvatarFavoriteGroupLength(group) }}) //- dialog: invite el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" ref="inviteDialog" :visible.sync="inviteDialog.visible" :title="$t('dialog.invite.header')" width="500px") diff --git a/html/src/localization/en/en.json b/html/src/localization/en/en.json index 796c96e1..5dcb79fd 100644 --- a/html/src/localization/en/en.json +++ b/html/src/localization/en/en.json @@ -93,7 +93,9 @@ "new_group": "New Group" }, "avatars": { - "header": "Avatars" + "header": "Avatars", + "local_favorites": "Local Favorites (VRC+ exclusive)", + "new_group": "New Group" }, "bulk_unfavorite_mode": "Bulk Unfavorite Mode", "bulk_unfavorite_selection": "Bulk Unfavorite Selection", @@ -108,7 +110,8 @@ "delete_tooltip": "Delete", "unavailable_tooltip": "Unavailable", "private": "Private", - "sort_by": "Sort By" + "sort_by": "Sort By", + "select_avatar_tooltip": "Select Avatar" }, "friend_log": { "filter_placeholder": "Filter", @@ -774,7 +777,7 @@ }, "actions": { "delete_cache_tooltip": "Delete avatar from cache", - "favorite_tooltip": "Add to favorites", + "favorite_tooltip": "Favorites", "unfavorite_tooltip": "Remove from favorites", "refresh": "Refresh", "select": "Select Avatar", @@ -912,7 +915,8 @@ "favorite": { "header": "Choose Group", "vrchat_favorites": "VRChat Favorites", - "local_favorites": "Local Favorites" + "local_favorites": "Local Favorites", + "local_avatar_favorites": "Local Favorites (VRC+ exclusive)" }, "invite": { "header": "Invite", diff --git a/html/src/localization/es/en.json b/html/src/localization/es/en.json index df417aac..b0074f45 100644 --- a/html/src/localization/es/en.json +++ b/html/src/localization/es/en.json @@ -770,7 +770,7 @@ }, "actions": { "delete_cache_tooltip": "Eliminar avatar de la caché", - "favorite_tooltip": "Añadir a favoritos", + "favorite_tooltip": "Favoritos", "unfavorite_tooltip": "Quitar de favoritos", "refresh": "Refrescar", "select": "Seleccionar avatar", diff --git a/html/src/localization/fr/en.json b/html/src/localization/fr/en.json index f73cf825..4b7a301f 100644 --- a/html/src/localization/fr/en.json +++ b/html/src/localization/fr/en.json @@ -774,7 +774,7 @@ }, "actions": { "delete_cache_tooltip": "Supprimer l'avatar du cache", - "favorite_tooltip": "Ajouter aux favoris", + "favorite_tooltip": "Favoris", "unfavorite_tooltip": "Supprimer des favoris", "refresh": "Actualiser", "select": "Sélectionner un avatar", diff --git a/html/src/localization/ja/en.json b/html/src/localization/ja/en.json index b10b7b33..b0ba5d69 100644 --- a/html/src/localization/ja/en.json +++ b/html/src/localization/ja/en.json @@ -739,7 +739,7 @@ }, "actions": { "delete_cache_tooltip": "キャッシュからアバターを削除", - "favorite_tooltip": "お気に入りに追加", + "favorite_tooltip": "お気に入り", "unfavorite_tooltip": "お気に入りから削除", "refresh": "更新", "select": "アバターを使用", diff --git a/html/src/localization/pl/en.json b/html/src/localization/pl/en.json index cd1e2d36..8abbae5b 100644 --- a/html/src/localization/pl/en.json +++ b/html/src/localization/pl/en.json @@ -739,7 +739,7 @@ }, "actions": { "delete_cache_tooltip": "Usuń świat z pamięci", - "favorite_tooltip": "Dodaj do ulubionych", + "favorite_tooltip": "Ulubione", "unfavorite_tooltip": "Usuń z ulubionych", "refresh": "Odśwież", "select": "Wybierz awatar", diff --git a/html/src/localization/ru/en.json b/html/src/localization/ru/en.json index 751404e0..8bb8a8da 100644 --- a/html/src/localization/ru/en.json +++ b/html/src/localization/ru/en.json @@ -770,7 +770,7 @@ }, "actions": { "delete_cache_tooltip": "Удалить аватар из кэша", - "favorite_tooltip": "Добавить в избранное", + "favorite_tooltip": "Избранное", "unfavorite_tooltip": "Убрать из Избранного", "refresh": "Обновить", "select": "Выбрать аватар", diff --git a/html/src/localization/vi/en.json b/html/src/localization/vi/en.json index 7f094493..66e1457f 100644 --- a/html/src/localization/vi/en.json +++ b/html/src/localization/vi/en.json @@ -734,7 +734,7 @@ }, "actions": { "delete_cache_tooltip": "Xóa avatar trong cache", - "favorite_tooltip": "Thêm vào yêu thích", + "favorite_tooltip": "Yêu thích", "unfavorite_tooltip": "Bỏ khỏi yêu thích", "refresh": "Làm mới", "select": "Chọn Avatar", diff --git a/html/src/localization/zh-CN/en.json b/html/src/localization/zh-CN/en.json index 40984762..51ba5af2 100644 --- a/html/src/localization/zh-CN/en.json +++ b/html/src/localization/zh-CN/en.json @@ -766,7 +766,7 @@ }, "actions": { "delete_cache_tooltip": "从缓存中删除模型", - "favorite_tooltip": "添加到我的收藏", + "favorite_tooltip": "收藏此世界", "unfavorite_tooltip": "从我的收藏中移除", "refresh": "刷新", "select": "选择模型", diff --git a/html/src/localization/zh-TW/en.json b/html/src/localization/zh-TW/en.json index f8e6cf7a..e1a41b74 100644 --- a/html/src/localization/zh-TW/en.json +++ b/html/src/localization/zh-TW/en.json @@ -734,7 +734,7 @@ }, "actions": { "delete_cache_tooltip": "從快取中刪除角色", - "favorite_tooltip": "新增到我的收藏", + "favorite_tooltip": "最愛欄", "unfavorite_tooltip": "從我的收藏中移除", "refresh": "重新整理", "select": "選擇角色", diff --git a/html/src/mixins/tabs/favorites.pug b/html/src/mixins/tabs/favorites.pug index 8b51f0b6..92df51b7 100644 --- a/html/src/mixins/tabs/favorites.pug +++ b/html/src/mixins/tabs/favorites.pug @@ -182,6 +182,8 @@ mixin favoritesTab() i.el-icon-warning(style="color:#f56c6c;margin-left:5px") el-tooltip(v-if="favorite.ref.releaseStatus === 'private'" placement="left" :content="$t('view.favorite.private')") i.el-icon-warning(style="color:#e6a23c;margin-left:5px") + el-tooltip(v-if="favorite.ref.releaseStatus !== 'private' && !favorite.deleted" placement="right" :content="$t('view.favorite.select_avatar_tooltip')" :disabled="hideTooltips") + el-button(@click.stop="selectAvatarWithConfirmation(favorite.id)" :disabled="API.currentUser.currentAvatar === favorite.id" size="mini" icon="el-icon-check" circle style="margin-left:5px") el-tooltip(placement="left" :content="$t('view.favorite.move_tooltip')" :disabled="hideTooltips") el-dropdown(trigger="click" @click.native.stop size="mini" style="margin-left:5px") el-button(type="default" icon="el-icon-back" size="mini" circle) @@ -209,9 +211,39 @@ mixin favoritesTab() .detail span.name(v-text="favorite.name") span.extra(v-text="favorite.authorName") + el-tooltip(placement="right" :content="$t('view.favorite.select_avatar_tooltip')" :disabled="hideTooltips") + el-button(@click.stop="selectAvatarWithConfirmation(favorite.id)" :disabled="API.currentUser.currentAvatar === favorite.id" size="mini" icon="el-icon-check" circle style="margin-left:5px") 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) + span(style="display:block;margin-top:20px") {{ $t('view.favorite.avatars.local_favorites') }} + el-button(size="small" :disabled="!isLocalUserVrcplusSupporter()" @click="promptNewLocalAvatarFavoriteGroup" style="display:block;margin-top:10px") {{ $t('view.favorite.avatars.new_group') }} + el-collapse-item(v-for="group in localAvatarFavoriteGroups" v-if="localAvatarFavorites[group]" :key="group") + template(slot="title") + span(v-text="group" style="font-weight:bold;font-size:14px;margin-left:10px") + span(style="color:#909399;font-size:12px;margin-left:10px") {{ getLocalAvatarFavoriteGroupLength(group) }} + el-tooltip(placement="top" :content="$t('view.favorite.rename_tooltip')" :disabled="hideTooltips") + el-button(@click.stop="promptLocalAvatarFavoriteGroupRename(group)" size="mini" icon="el-icon-edit" circle style="margin-left:10px") + el-tooltip(placement="right" :content="$t('view.favorite.delete_tooltip')" :disabled="hideTooltips") + el-button(@click.stop="promptLocalAvatarFavoriteGroupDelete(group)" size="mini" icon="el-icon-delete" circle style="margin-left:5px") + .x-friend-list(style="margin-top:10px") + div(style="display:inline-block;width:300px;margin-right:15px" v-for="favorite in localAvatarFavorites[group]" :key="favorite.id" @click="showAvatarDialog(favorite.id)") + .x-friend-item + template(v-if="favorite.name") + .avatar + img(v-lazy="favorite.thumbnailImageUrl") + .detail + span.name(v-text="favorite.name") + span.extra(v-text="favorite.authorName") + el-tooltip(placement="right" :content="$t('view.favorite.select_avatar_tooltip')" :disabled="hideTooltips") + el-button(@click.stop="selectAvatarWithConfirmation(favorite.id)" :disabled="API.currentUser.currentAvatar === favorite.id" size="mini" icon="el-icon-check" circle style="margin-left:5px") + el-tooltip(placement="right" :content="$t('view.favorite.unfavorite_tooltip')" :disabled="hideTooltips") + el-button(@click.stop="removeLocalAvatarFavorite(favorite.id, group)" size="mini" icon="el-icon-delete" circle style="margin-left:5px") + template(v-else) + .avatar + .detail + span(v-text="favorite.id") + el-button(type="text" icon="el-icon-close" size="mini" @click.stop="removeLocalAvatarFavorite(favorite.id, group)" style="margin-left:5px") diff --git a/html/src/repository/database.js b/html/src/repository/database.js index 90b3b4ef..d51c0a45 100644 --- a/html/src/repository/database.js +++ b/html/src/repository/database.js @@ -80,6 +80,9 @@ class Database { await sqliteService.executeNonQuery( `CREATE TABLE IF NOT EXISTS favorite_world (id INTEGER PRIMARY KEY, created_at TEXT, world_id TEXT, group_name TEXT)` ); + await sqliteService.executeNonQuery( + `CREATE TABLE IF NOT EXISTS favorite_avatar (id INTEGER PRIMARY KEY, created_at TEXT, avatar_id TEXT, group_name TEXT)` + ); } async getFeedDatabase() { @@ -2216,6 +2219,110 @@ class Database { sqliteService.executeNonQuery('DELETE FROM cache_avatar'); } + addAvatarToFavorites(avatarId, groupName) { + sqliteService.executeNonQuery( + 'INSERT OR REPLACE INTO favorite_avatar (avatar_id, group_name, created_at) VALUES (@avatar_id, @group_name, @created_at)', + { + '@avatar_id': avatarId, + '@group_name': groupName, + '@created_at': new Date().toJSON() + } + ); + } + + renameAvatarFavoriteGroup(newGroupName, groupName) { + sqliteService.executeNonQuery( + `UPDATE favorite_avatar SET group_name = @new_group_name WHERE group_name = @group_name`, + { + '@new_group_name': newGroupName, + '@group_name': groupName + } + ); + } + + deleteAvatarFavoriteGroup(groupName) { + sqliteService.executeNonQuery( + `DELETE FROM favorite_avatar WHERE group_name = @group_name`, + { + '@group_name': groupName + } + ); + } + + removeAvatarFromFavorites(avatarId, groupName) { + sqliteService.executeNonQuery( + `DELETE FROM favorite_avatar WHERE avatar_id = @avatar_id AND group_name = @group_name`, + { + '@avatar_id': avatarId, + '@group_name': groupName + } + ); + } + + async getAvatarFavorites() { + var data = []; + await sqliteService.execute((dbRow) => { + var row = { + created_at: dbRow[1], + avatarId: dbRow[2], + groupName: dbRow[3] + }; + data.push(row); + }, 'SELECT * FROM favorite_avatar'); + return data; + } + + removeAvatarFromCache(avatarId) { + sqliteService.executeNonQuery( + `DELETE FROM cache_avatar WHERE id = @avatar_id`, + { + '@avatar_id': avatarId + } + ); + } + + 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 + } + ); + } + + async getAvatarCache() { + var data = []; + await sqliteService.execute((dbRow) => { + var row = { + id: dbRow[0], + // added_at: dbRow[1], + authorId: dbRow[2], + authorName: dbRow[3], + created_at: dbRow[4], + description: dbRow[5], + imageUrl: dbRow[6], + name: dbRow[7], + releaseStatus: dbRow[8], + thumbnailImageUrl: dbRow[9], + updated_at: dbRow[10], + version: dbRow[11] + }; + data.push(row); + }, 'SELECT * FROM cache_avatar'); + return data; + } + addWorldToCache(entry) { sqliteService.executeNonQuery( `INSERT OR REPLACE INTO cache_world (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)`, @@ -2276,15 +2383,6 @@ class Database { ); } - removeWorldFromCache(worldId) { - sqliteService.executeNonQuery( - `DELETE FROM cache_world WHERE id = @world_id`, - { - '@world_id': worldId - } - ); - } - async getWorldFavorites() { var data = []; await sqliteService.execute((dbRow) => { @@ -2298,6 +2396,15 @@ class Database { return data; } + removeWorldFromCache(worldId) { + sqliteService.executeNonQuery( + `DELETE FROM cache_world WHERE id = @world_id`, + { + '@world_id': worldId + } + ); + } + async getWorldCache() { var data = []; await sqliteService.execute((dbRow) => {