diff --git a/html/src/app.js b/html/src/app.js index a1896da8..42c546ba 100644 --- a/html/src/app.js +++ b/html/src/app.js @@ -11713,27 +11713,51 @@ speechSynthesis.getVoices(); }); }; - $app.methods.addFavoriteWorld = function (ref, group) { + $app.methods.addFavoriteWorld = function (ref, group, message) { return API.addFavorite({ type: 'world', favoriteId: ref.id, tags: group.name + }).then((args) => { + if (message) { + this.$message({ + message: 'World added to favorites', + type: 'success' + }); + } + return args; }); }; - $app.methods.addFavoriteAvatar = function (ref, group) { + $app.methods.addFavoriteAvatar = function (ref, group, message) { return API.addFavorite({ type: 'avatar', favoriteId: ref.id, tags: group.name + }).then((args) => { + if (message) { + this.$message({ + message: 'Avatar added to favorites', + type: 'success' + }); + } + return args; }); }; - $app.methods.addFavoriteUser = function (ref, group) { + $app.methods.addFavoriteUser = function (ref, group, message) { return API.addFavorite({ type: 'friend', favoriteId: ref.id, tags: group.name + }).then((args) => { + if (message) { + this.$message({ + message: 'Friend added to favorites', + type: 'success' + }); + } + return args; }); }; @@ -18737,7 +18761,8 @@ speechSynthesis.getVoices(); if (D.worldImportFavoriteGroup) { await this.addFavoriteWorld( ref, - D.worldImportFavoriteGroup + D.worldImportFavoriteGroup, + false ); } else if (D.worldImportLocalFavoriteGroup) { this.addLocalWorldFavorite( @@ -18976,7 +19001,8 @@ speechSynthesis.getVoices(); if (D.avatarImportFavoriteGroup) { await this.addFavoriteAvatar( ref, - D.avatarImportFavoriteGroup + D.avatarImportFavoriteGroup, + false ); } else if (D.avatarImportLocalFavoriteGroup) { this.addLocalAvatarFavorite( @@ -19205,7 +19231,11 @@ speechSynthesis.getVoices(); break; } var ref = data[i]; - await this.addFavoriteUser(ref, D.friendImportFavoriteGroup); + await this.addFavoriteUser( + ref, + D.friendImportFavoriteGroup, + false + ); $app.removeFromArray(this.friendImportTable.data, ref); D.userIdList.delete(ref.id); D.importProgress++; @@ -19505,7 +19535,7 @@ speechSynthesis.getVoices(); // #endregion // #region | App: bulk unfavorite - $app.data.bulkUnfavoriteMode = false; + $app.data.editFavoritesMode = false; $app.methods.showBulkUnfavoriteSelectionConfirm = function () { var elementsTicked = []; @@ -19551,7 +19581,65 @@ speechSynthesis.getVoices(); objectId: id }); } - this.bulkUnfavoriteMode = false; + this.editFavoritesMode = false; + }; + + $app.methods.bulkCopyFavoriteSelection = function () { + var idList = ''; + var type = ''; + for (var ctx of this.favoriteFriends) { + if (ctx.$selected) { + idList += ctx.id + '\n'; + type = 'friend'; + } + } + for (var ctx of this.favoriteWorlds) { + if (ctx.$selected) { + idList += ctx.id + '\n'; + type = 'world'; + } + } + for (var ctx of this.favoriteAvatars) { + if (ctx.$selected) { + idList += ctx.id + '\n'; + type = 'avatar'; + } + } + switch (type) { + case 'friend': + this.showFriendImportDialog(); + this.friendImportDialog.input = idList; + this.processFriendImportList(); + break; + + case 'world': + this.showWorldImportDialog(); + this.worldImportDialog.input = idList; + this.processWorldImportList(); + break; + + case 'avatar': + this.showAvatarImportDialog(); + this.avatarImportDialog.input = idList; + this.processAvatarImportList(); + break; + + default: + break; + } + console.log('Favorite selection\n', idList); + }; + + $app.methods.clearBulkFavoriteSelection = function () { + for (var ctx of this.favoriteFriends) { + ctx.$selected = false; + } + for (var ctx of this.favoriteWorlds) { + ctx.$selected = false; + } + for (var ctx of this.favoriteAvatars) { + ctx.$selected = false; + } }; // #endregion diff --git a/html/src/localization/en/en.json b/html/src/localization/en/en.json index d64b8d4f..8f90c744 100644 --- a/html/src/localization/en/en.json +++ b/html/src/localization/en/en.json @@ -103,12 +103,15 @@ "refresh": "Refresh", "cancel_refresh": "Cancel Refresh" }, - "bulk_unfavorite_mode": "Bulk Unfavorite Mode", - "bulk_unfavorite_selection": "Bulk Unfavorite Selection", + "edit_mode": "Edit Mode", + "copy": "Copy", + "clear": "Clear", + "bulk_unfavorite": "Bulk Unfavorite", "refresh_tooltip": "Refresh all favorites", "export": "Export", "import": "Import", "move_tooltip": "Move", + "copy_tooltip": "Copy", "unfavorite_tooltip": "Unfavorite", "visibility_tooltip": "Change Visibility", "rename_tooltip": "Rename", diff --git a/html/src/mixins/tabs/favorites.pug b/html/src/mixins/tabs/favorites.pug index 1693ce95..6614f335 100644 --- a/html/src/mixins/tabs/favorites.pug +++ b/html/src/mixins/tabs/favorites.pug @@ -1,11 +1,13 @@ mixin favoritesTab() .x-container(v-show="$refs.menu && $refs.menu.activeIndex === 'favorite'") div(style="font-size:13px;position:absolute;right:0;z-index:1") - div(v-if="bulkUnfavoriteMode" style="display:inline-block;margin-right:10px") - el-button(size="small" @click="showBulkUnfavoriteSelectionConfirm") {{ $t('view.favorite.bulk_unfavorite_selection') }} + div(v-if="editFavoritesMode" style="display:inline-block;margin-right:10px") + el-button(size="small" @click="clearBulkFavoriteSelection ") {{ $t('view.favorite.clear') }} + el-button(size="small" @click="bulkCopyFavoriteSelection") {{ $t('view.favorite.copy') }} + el-button(size="small" @click="showBulkUnfavoriteSelectionConfirm") {{ $t('view.favorite.bulk_unfavorite') }} div(style="display:inline-block;margin-right:10px") - span.name {{ $t('view.favorite.bulk_unfavorite_mode') }} - el-switch(v-model="bulkUnfavoriteMode" style="margin-left:5px") + span.name {{ $t('view.favorite.edit_mode') }} + el-switch(v-model="editFavoritesMode" style="margin-left:5px") el-tooltip(placement="bottom" :content="$t('view.favorite.refresh_tooltip')" :disabled="hideTooltips") el-button(type="default" :loading="API.isFavoriteLoading" @click="API.refreshFavorites(); getLocalWorldFavorites()" size="small" icon="el-icon-refresh" circle) el-tabs(ref="favoriteTabRef" type="card" v-loading="API.isFavoriteLoading" style="height:100%") @@ -34,18 +36,18 @@ mixin favoritesTab() span.name(v-text="favorite.ref.displayName" :style="{'color':favorite.ref.$userColour}") location.extra(v-if="favorite.ref.location !== 'offline'" :location="favorite.ref.location" :traveling="favorite.ref.travelingToLocation" :link="false") span(v-else v-text="favorite.ref.statusDescription") - template(v-if="bulkUnfavoriteMode") - el-button(type="text" size="mini" @click.stop style="margin-left:5px") - el-checkbox(v-model="favorite.$selected") - template(v-else-if="favorite.ref") - 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) - el-dropdown-menu(#default="dropdown") - template(v-if="groupAPI.name !== group.name" v-for="groupAPI in API.favoriteFriendGroups" :key="groupAPI.name") - el-dropdown-item(style="display:block;margin:10px 0" @click.native="moveFavorite(favorite.ref, groupAPI, 'friend')" :disabled="groupAPI.count >= groupAPI.capacity") {{ groupAPI.displayName }} ({{ groupAPI.count }} / {{ groupAPI.capacity }}) - el-tooltip(placement="right" :content="$t('view.favorite.unfavorite_tooltip')" :disabled="hideTooltips") - el-button(@click.stop="deleteFavorite(favorite.id)" size="mini" icon="el-icon-delete" circle style="margin-left:5px") + template(v-if="editFavoritesMode") + 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) + el-dropdown-menu(#default="dropdown") + template(v-if="groupAPI.name !== group.name" v-for="groupAPI in API.favoriteFriendGroups" :key="groupAPI.name") + el-dropdown-item(style="display:block;margin:10px 0" @click.native="moveFavorite(favorite.ref, groupAPI, 'friend')" :disabled="groupAPI.count >= groupAPI.capacity") {{ groupAPI.displayName }} ({{ groupAPI.count }} / {{ groupAPI.capacity }}) + el-button(type="text" size="mini" @click.stop style="margin-left:5px") + el-checkbox(v-model="favorite.$selected") + template(v-else) + el-tooltip(placement="right" :content="$t('view.favorite.unfavorite_tooltip')" :disabled="hideTooltips") + el-button(@click.stop="deleteFavorite(favorite.id)" size="mini" icon="el-icon-delete" circle style="margin-left:5px") template(v-else) .avatar .detail @@ -100,22 +102,22 @@ mixin favoritesTab() span.name(v-text="favorite.ref.name") span.extra(v-if="favorite.ref.occupants") {{ favorite.ref.authorName }} ({{ favorite.ref.occupants }}) span.extra(v-else v-text="favorite.ref.authorName") - template(v-if="bulkUnfavoriteMode") - el-button(type="text" size="mini" @click.stop style="margin-left:5px") - el-checkbox(v-model="favorite.$selected") - template(v-else-if="favorite.ref") - el-tooltip(v-if="favorite.deleted" placement="left" :content="$t('view.favorite.unavailable_tooltip')") - 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(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) - el-dropdown-menu(#default="dropdown") - template(v-if="groupAPI.name !== group.name" v-for="groupAPI in API.favoriteWorldGroups" :key="groupAPI.name") - el-dropdown-item(style="display:block;margin:10px 0" @click.native="moveFavorite(favorite.ref, groupAPI, 'world')" :disabled="groupAPI.count >= groupAPI.capacity") {{ groupAPI.displayName }} ({{ groupAPI.count }} / {{ groupAPI.capacity }}) - el-tooltip(placement="right" :content="$t('view.favorite.unfavorite_tooltip')" :disabled="hideTooltips") - el-button(@click.stop="deleteFavorite(favorite.id)" size="mini" icon="el-icon-delete" circle style="margin-left:5px") + template(v-if="editFavoritesMode") + 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) + el-dropdown-menu(#default="dropdown") + template(v-if="groupAPI.name !== group.name" v-for="groupAPI in API.favoriteWorldGroups" :key="groupAPI.name") + el-dropdown-item(style="display:block;margin:10px 0" @click.native="moveFavorite(favorite.ref, groupAPI, 'world')" :disabled="groupAPI.count >= groupAPI.capacity") {{ groupAPI.displayName }} ({{ groupAPI.count }} / {{ groupAPI.capacity }}) + el-button(type="text" size="mini" @click.stop style="margin-left:5px") + el-checkbox(v-model="favorite.$selected") + template(v-else) + el-tooltip(v-if="favorite.deleted" placement="left" :content="$t('view.favorite.unavailable_tooltip')") + 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(placement="right" :content="$t('view.favorite.unfavorite_tooltip')" :disabled="hideTooltips") + el-button(@click.stop="deleteFavorite(favorite.id)" size="mini" icon="el-icon-delete" circle style="margin-left:5px") template(v-else) .avatar .detail @@ -148,6 +150,13 @@ mixin favoritesTab() span.name(v-text="favorite.name") span.extra(v-if="favorite.occupants") {{ favorite.authorName }} ({{ favorite.occupants }}) span.extra(v-else v-text="favorite.authorName") + template(v-if="editFavoritesMode") + el-tooltip(placement="left" :content="$t('view.favorite.copy_tooltip')" :disabled="hideTooltips") + el-dropdown(trigger="click" @click.native.stop size="mini" style="margin-left:5px") + el-button(type="default" icon="el-icon-s-order" size="mini" circle) + el-dropdown-menu(#default="dropdown") + template(v-for="groupAPI in API.favoriteWorldGroups" :key="groupAPI.name") + el-dropdown-item(style="display:block;margin:10px 0" @click.native="addFavoriteWorld(favorite, groupAPI, true)" :disabled="groupAPI.count >= groupAPI.capacity") {{ groupAPI.displayName }} ({{ groupAPI.count }} / {{ groupAPI.capacity }}) el-tooltip(placement="right" :content="$t('view.favorite.unfavorite_tooltip')" :disabled="hideTooltips") el-button(@click.stop="removeLocalWorldFavorite(favorite.id, group)" size="mini" icon="el-icon-delete" circle style="margin-left:5px") template(v-else) @@ -196,24 +205,24 @@ mixin favoritesTab() .detail span.name(v-text="favorite.ref.name") span.extra(v-text="favorite.ref.authorName") - template(v-if="bulkUnfavoriteMode") - el-button(type="text" size="mini" @click.stop style="margin-left:5px") - el-checkbox(v-model="favorite.$selected") - template(v-else-if="favorite.ref") - el-tooltip(v-if="favorite.deleted" placement="left" :content="$t('view.favorite.unavailable_tooltip')") - 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="left" :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="top" :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) - el-dropdown-menu(#default="dropdown") - template(v-if="groupAPI.name !== group.name" v-for="groupAPI in API.favoriteAvatarGroups" :key="groupAPI.name") - el-dropdown-item(style="display:block;margin:10px 0" @click.native="moveFavorite(favorite.ref, groupAPI, 'avatar')" :disabled="groupAPI.count >= groupAPI.capacity") {{ groupAPI.displayName }} ({{ groupAPI.count }} / {{ groupAPI.capacity }}) - el-tooltip(placement="right" :content="$t('view.favorite.unfavorite_tooltip')" :disabled="hideTooltips") - el-button(@click.stop="deleteFavorite(favorite.id)" size="mini" icon="el-icon-delete" circle style="margin-left:5px") + template(v-if="editFavoritesMode") + el-tooltip(placement="top" :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) + el-dropdown-menu(#default="dropdown") + template(v-if="groupAPI.name !== group.name" v-for="groupAPI in API.favoriteAvatarGroups" :key="groupAPI.name") + el-dropdown-item(style="display:block;margin:10px 0" @click.native="moveFavorite(favorite.ref, groupAPI, 'avatar')" :disabled="groupAPI.count >= groupAPI.capacity") {{ groupAPI.displayName }} ({{ groupAPI.count }} / {{ groupAPI.capacity }}) + el-button(type="text" size="mini" @click.stop style="margin-left:5px") + el-checkbox(v-model="favorite.$selected") + template(v-else) + el-tooltip(v-if="favorite.deleted" placement="left" :content="$t('view.favorite.unavailable_tooltip')") + 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="left" :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="deleteFavorite(favorite.id)" size="mini" icon="el-icon-delete" circle style="margin-left:5px") template(v-else) .avatar .detail @@ -265,8 +274,16 @@ mixin favoritesTab() .detail span.name(v-text="favorite.name") span.extra(v-text="favorite.authorName") - el-tooltip(placement="left" :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="editFavoritesMode") + el-tooltip(placement="left" :content="$t('view.favorite.copy_tooltip')" :disabled="hideTooltips") + el-dropdown(trigger="click" @click.native.stop size="mini" style="margin-left:5px") + el-button(type="default" icon="el-icon-s-order" size="mini" circle) + el-dropdown-menu(#default="dropdown") + template(v-for="groupAPI in API.favoriteAvatarGroups" :key="groupAPI.name") + el-dropdown-item(style="display:block;margin:10px 0" @click.native="addFavoriteAvatar(favorite, groupAPI, true)" :disabled="groupAPI.count >= groupAPI.capacity") {{ groupAPI.displayName }} ({{ groupAPI.count }} / {{ groupAPI.capacity }}) + template(v-else) + el-tooltip(placement="left" :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)