From 4a2ea2fde326d992705d3d8f518ad44cf0ebe746 Mon Sep 17 00:00:00 2001 From: Natsumi Date: Sat, 14 Sep 2024 21:07:24 +1200 Subject: [PATCH] Sidebar sorting dropdown --- html/src/app.js | 211 ++++++++++++++++++------------ html/src/index.pug | 5 +- html/src/localization/en/en.json | 28 ++-- html/src/mixins/tabs/settings.pug | 62 +++++---- 4 files changed, 175 insertions(+), 131 deletions(-) diff --git a/html/src/app.js b/html/src/app.js index b97593ac..8bc47cc8 100644 --- a/html/src/app.js +++ b/html/src/app.js @@ -2011,7 +2011,7 @@ speechSynthesis.getVoices(); $online_for: Date.now(), $travelingToTime: Date.now(), $offline_for: '', - $active_for: '', + $active_for: Date.now(), $isVRCPlus: false, $isModerator: false, $isTroll: false, @@ -9759,6 +9759,9 @@ speechSynthesis.getVoices(); if (typeof a.ref === 'undefined' || typeof b.ref === 'undefined') { return 0; } + if (a.state !== 'online' || b.state !== 'online') { + return 0; + } return a.ref.location.localeCompare(b.ref.location); } @@ -9779,56 +9782,57 @@ speechSynthesis.getVoices(); return 0; } - // online for - var compareByOnlineFor = function (a, b) { - return compareByActivityField(a, b, "$online_for"); - } + // last active + var compareByLastActive = function (a, b) { + if (a.state === 'online' && b.state === 'online') { + if ( + a.ref?.$online_for && + b.ref?.$online_for && + a.ref.$online_for === b.ref.$online_for + ) { + compareByActivityField(a, b, 'last_login'); + } + return compareByActivityField(a, b, '$online_for'); + } - // offline for - var compareByOfflineFor = function (a, b) { - return compareByActivityField(a, b, "$offline_for"); - } - - // active for - var compareByActiveFor = function (a, b) { - return compareByActivityField(a, b, "$active_for"); - } + return compareByActivityField(a, b, 'last_activity'); + }; var getFriendsSortFunction = function (sortMethods) { const sorts = []; for (const sortMethod of sortMethods) { switch (sortMethod) { - case "Sort Private to Bottom": + case 'Sort Alphabetically': + sorts.push(compareByName); + break; + case 'Sort Private to Bottom': sorts.push(compareByPrivate); break; - case "Sort by Status": + case 'Sort by Status': sorts.push(compareByStatus); break; - case "Sort by Name": - sorts.push(compareByStatusAndPrivate); + case 'Sort by Last Active': + sorts.push(compareByLastActive); break; - case "Sort by Online For": - sorts.push(compareByOnlineFor); - break; - case "Sort by Offline For": - sorts.push(compareByOfflineFor); - break; - case "Sort by Active For": - sorts.push(compareByActiveFor); - break; - case "Sort by Time in Instance": + case 'Sort by Time in Instance': sorts.push((a, b) => { - if (typeof a.ref === 'undefined' || typeof b.ref === 'undefined') { + if ( + typeof a.ref === 'undefined' || + typeof b.ref === 'undefined' + ) { + return 0; + } + if (a.state !== 'online' || b.state !== 'online') { return 0; } - return compareByLocationAt(a.ref, b.ref); + return compareByLocationAt(b.ref, a.ref); }); break; - case "Sort by Location": + case 'Sort by Location': sorts.push(compareByLocation); break; - case "None": + case 'None': sorts.push(() => 0); break; } @@ -9843,8 +9847,8 @@ speechSynthesis.getVoices(); } } return res; - } - } + }; + }; // VIP friends $app.computed.vipFriends = function () { @@ -9853,7 +9857,7 @@ speechSynthesis.getVoices(); } this.sortVIPFriends = false; - this.vipFriends_.sort(getFriendsSortFunction(this.vipFriendsSortMethod)); + this.vipFriends_.sort(getFriendsSortFunction(this.sidebarSortMethods)); return this.vipFriends_; }; @@ -9864,7 +9868,9 @@ speechSynthesis.getVoices(); } this.sortOnlineFriends = false; - this.onlineFriends_.sort(getFriendsSortFunction(this.onlineFriendsSortMethod)); + this.onlineFriends_.sort( + getFriendsSortFunction(this.sidebarSortMethods) + ); return this.onlineFriends_; }; @@ -9876,7 +9882,9 @@ speechSynthesis.getVoices(); } this.sortActiveFriends = false; - this.activeFriends_.sort(getFriendsSortFunction(this.activeFriendsSortMethod)); + this.activeFriends_.sort( + getFriendsSortFunction(this.sidebarSortMethods) + ); return this.activeFriends_; }; @@ -9888,7 +9896,9 @@ speechSynthesis.getVoices(); } this.sortOfflineFriends = false; - this.offlineFriends_.sort(getFriendsSortFunction(this.offlineFriendsSortMethod)); + this.offlineFriends_.sort( + getFriendsSortFunction(this.sidebarSortMethods) + ); return this.offlineFriends_; }; @@ -16040,72 +16050,104 @@ speechSynthesis.getVoices(); this.vrcRegistryAutoBackup ); }; - // TODO: FIX DEFAULTS BEFORE MEGNING PLS - $app.data.vipFriendsSortMethod = JSON.parse(await configRepository.getString( - 'vipFriendsSortMethod', - '["Default"]' - )); - $app.data.onlineFriendsSortMethod = JSON.parse(await configRepository.getString( - 'onlineFriendsSortMethod', - '["Default"]' - )); - $app.data.activeFriendsSortMethod = JSON.parse(await configRepository.getString( - 'activeFriendsSortMethod', - '["Default"]' - )); - $app.data.offlineFriendsSortMethod = JSON.parse(await configRepository.getString( - 'offlineFriendsSortMethod', - '["Default"]' - )); + $app.data.sidebarSortMethod1 = ''; + $app.data.sidebarSortMethod2 = ''; + $app.data.sidebarSortMethod3 = ''; + $app.data.sidebarSortMethods = JSON.parse( + await configRepository.getString( + 'VRCX_sidebarSortMethods', + JSON.stringify(['', '', '']) + ) + ); + if ($app.data.sidebarSortMethods?.length === 3) { + $app.data.sidebarSortMethod1 = $app.data.sidebarSortMethods[0]; + $app.data.sidebarSortMethod2 = $app.data.sidebarSortMethods[1]; + $app.data.sidebarSortMethod3 = $app.data.sidebarSortMethods[2]; + } // Migrate old settings // Assume all exist if one does - - // TODO: FIX THIS BEFORE MERGING PLS const orderFriendsGroupPrivate = await configRepository.getBool( 'orderFriendGroupPrivate' ); if (orderFriendsGroupPrivate !== null) { await configRepository.remove('orderFriendGroupPrivate'); + const orderFriendsGroupStatus = await configRepository.getBool( 'orderFriendsGroupStatus' ); await configRepository.remove('orderFriendsGroupStatus'); + const orderFriendsGroupGPS = await configRepository.getBool( 'orderFriendGroupGPS' ); await configRepository.remove('orderFriendGroupGPS'); - if (orderFriendsGroupGPS) { - $app.data.onlineAndVIPFriendsSortMethod = "Sort by Location"; - } else if (orderFriendsGroupPrivate && orderFriendsGroupStatus) { - $app.data.onlineAndVIPFriendsSortMethod = "Sort by Status and Private to Bottom"; - } else if (orderFriendsGroupPrivate) { - $app.data.onlineAndVIPFriendsSortMethod = "Sort Private to Bottom"; - } else if (orderFriendsGroupStatus) { - $app.data.onlineAndVIPFriendsSortMethod = "Sort by Status" + const orderOnlineFor = + await configRepository.getBool('orderFriendGroup0'); + await configRepository.remove('orderFriendGroup0'); + await configRepository.remove('orderFriendGroup1'); + await configRepository.remove('orderFriendGroup2'); + await configRepository.remove('orderFriendGroup3'); + + var sortOrder = []; + if (orderFriendsGroupPrivate) { + sortOrder.push('Sort Private to Bottom'); } + if (orderFriendsGroupStatus) { + sortOrder.push('Sort by Status'); + } + if (orderOnlineFor && orderFriendsGroupGPS) { + sortOrder.push('Sort by Time in Instance'); + } + if (!orderOnlineFor) { + sortOrder.push('Sort Alphabetically'); + } + + if (sortOrder.length > 0) { + while (sortOrder.length < 3) { + sortOrder.push(''); + } + $app.data.sidebarSortMethods = sortOrder; + $app.data.sidebarSortMethod1 = sortOrder[0]; + $app.data.sidebarSortMethod2 = sortOrder[1]; + $app.data.sidebarSortMethod3 = sortOrder[2]; + } + await configRepository.setString( + 'VRCX_sidebarSortMethods', + JSON.stringify(sortOrder) + ); } - $app.methods.saveOrderFriendGroup = async function () { + $app.methods.saveSidebarSortOrder = async function () { + if (this.sidebarSortMethod1 === this.sidebarSortMethod2) { + this.sidebarSortMethod2 = ''; + } + if (this.sidebarSortMethod1 === this.sidebarSortMethod3) { + this.sidebarSortMethod3 = ''; + } + if (this.sidebarSortMethod2 === this.sidebarSortMethod3) { + this.sidebarSortMethod3 = ''; + } + if (!this.sidebarSortMethod1) { + this.sidebarSortMethod2 = ''; + } + if (!this.sidebarSortMethod2) { + this.sidebarSortMethod3 = ''; + } + this.sidebarSortMethods = [ + this.sidebarSortMethod1, + this.sidebarSortMethod2, + this.sidebarSortMethod3 + ]; await configRepository.setString( - 'vipFriendsSortMethod', - JSON.stringify(this.vipFriendsSortMethod) - ); - await configRepository.setString( - 'onlineFriendsSortMethod', - JSON.stringify(this.onlineFriendsSortMethod) - ); - await configRepository.setString( - 'activeFriendsSortMethod', - JSON.stringify(this.activeFriendsSortMethod) - ); - await configRepository.setString( - 'offlineFriendsSortMethod', - JSON.stringify(this.offlineFriendsSortMethod) + 'VRCX_sidebarSortMethods', + JSON.stringify(this.sidebarSortMethods) ); this.sortVIPFriends = true; this.sortOnlineFriends = true; + this.sortActiveFriends = true; + this.sortOfflineFriends = true; }; $app.data.discordActive = await configRepository.getBool( 'discordActive', @@ -17867,8 +17909,10 @@ speechSynthesis.getVoices(); if (!D.dateFriended) { if (ref2.type === 'Unfriend') { D.unFriended = true; - D.dateFriended = - ref2.created_at; + if (!this.hideUnfriends) { + D.dateFriended = + ref2.created_at; + } } if (ref2.type === 'Friend') { D.unFriended = false; @@ -17878,7 +17922,8 @@ speechSynthesis.getVoices(); } if ( ref2.type === 'Friend' || - ref2.type === 'Unfriend' + (ref2.type === 'Unfriend' && + !this.hideUnfriends) ) { D.dateFriendedInfo.push(ref2); } diff --git a/html/src/index.pug b/html/src/index.pug index a42983be..fa053dad 100644 --- a/html/src/index.pug +++ b/html/src/index.pug @@ -460,14 +460,13 @@ html template(#content v-else) span - .detail - span.name(v-if="userDialog.unFriended && !hideUnfriends") {{ $t('dialog.user.info.unfriended') }} + span.name(v-if="userDialog.unFriended") {{ $t('dialog.user.info.unfriended') }} el-tooltip(v-if="!hideTooltips" placement="top" style="margin-left:5px" :content="$t('dialog.user.info.accuracy_notice')") i.el-icon-warning span.name(v-else) {{ $t('dialog.user.info.friended') }} el-tooltip(v-if="!hideTooltips" placement="top" style="margin-left:5px" :content="$t('dialog.user.info.accuracy_notice')") i.el-icon-warning - span.extra(v-if="!hideUnfriends") {{ userDialog.dateFriended | formatDate('long') }} - span.extra(v-else) - + span.extra {{ userDialog.dateFriended | formatDate('long') }} template(v-if="API.currentUser.id === userDialog.id") .x-friend-item(@click="toggleAvatarCopying") .detail diff --git a/html/src/localization/en/en.json b/html/src/localization/en/en.json index 08acd2b6..59e5a2cd 100644 --- a/html/src/localization/en/en.json +++ b/html/src/localization/en/en.json @@ -292,24 +292,16 @@ "side_panel": { "header": "Side Panel", "sorting": { - "header": "Sorting", - "sort_default": "Default", - "sort_private_to_bottom": "Sort Private to bottom", - "sort_by_status": "Sort by Status", - "sort_by_status_and_private_to_bottom": "Sort by Status and Private to Bottom", - "sort_by_location": "Sort by Location", - "sort_favorite_by": "Sort Favorites by", - "sort_favorite_by_alphabet": "alphabetical", - "sort_favorite_by_online_time": "online for", - "sort_online_by": "Sort Online by", - "sort_online_by_alphabet": "alphabetical", - "sort_online_by_online_time": "online for", - "sort_active_by": "Sort Active by", - "sort_active_by_alphabet": "alphabetical", - "sort_active_by_online_time": "online for", - "sort_offline_by": "Sort Offline by", - "sort_offline_by_alphabet": "alphabetical", - "sort_offline_by_offline_time": "offline for" + "header": "Sort Order", + "alphabetical": "Alphabetical", + "private_to_bottom": "Private to Bottom", + "status": "Status", + "status_and_private_to_bottom": "Status and Private to Bottom", + "location": "Location", + "last_active": "Last Active", + "time_in_instance": "Time in Instance", + "placeholder": "Sort Order", + "dropdown_header": "Choose Sort Order" }, "width": "Width" }, diff --git a/html/src/mixins/tabs/settings.pug b/html/src/mixins/tabs/settings.pug index d3d1d216..8dc31efb 100644 --- a/html/src/mixins/tabs/settings.pug +++ b/html/src/mixins/tabs/settings.pug @@ -197,29 +197,37 @@ mixin settingsTab() div.options-container span.header {{ $t('view.settings.appearance.side_panel.header') }} br - span.sub-header {{ $t('view.settings.appearance.side_panel.sorting.header') }} div.options-container-item - el-radio-group(v-model="onlineAndVIPFriendsSortMethod" @change="saveOrderFriendGroup" size="mini") - el-radio-button(label="Default") {{ $t('view.settings.appearance.side_panel.sorting.sort_default') }} - el-radio-button(label="Sort Private to Bottom") {{ $t('view.settings.appearance.side_panel.sorting.sort_private_to_bottom') }} - el-radio-button(label="Sort by Status") {{ $t('view.settings.appearance.side_panel.sorting.sort_by_status') }} - el-radio-button(label="Sort by Status and Private to Bottom") {{ $t('view.settings.appearance.side_panel.sorting.sort_by_status_and_private_to_bottom') }} - el-radio-button(label="Sort by Location") {{ $t('view.settings.appearance.side_panel.sorting.sort_by_location') }} + span.name {{ $t('view.settings.appearance.side_panel.sorting.header') }} + el-select(v-model="sidebarSortMethod1" style="width:170px" :placeholder="$t('view.settings.appearance.side_panel.sorting.placeholder')" @change="saveSidebarSortOrder") + el-option-group(:label="$t('view.settings.appearance.side_panel.sorting.dropdown_header')") + el-option.x-friend-item(:label="$t('view.settings.appearance.side_panel.sorting.alphabetical')" value="Sort Alphabetically") + el-option.x-friend-item(:label="$t('view.settings.appearance.side_panel.sorting.status')" value="Sort by Status") + el-option.x-friend-item(:label="$t('view.settings.appearance.side_panel.sorting.private_to_bottom')" value="Sort Private to Bottom") + el-option.x-friend-item(:label="$t('view.settings.appearance.side_panel.sorting.last_active')" value="Sort by Last Active") + el-option.x-friend-item(:label="$t('view.settings.appearance.side_panel.sorting.time_in_instance')" value="Sort by Time in Instance") + el-option.x-friend-item(:label="$t('view.settings.appearance.side_panel.sorting.location')" value="Sort by Location") + i.el-icon-arrow-right(style="margin:16px 5px") + el-select(v-model="sidebarSortMethod2" :disabled="!sidebarSortMethod1" style="width:170px" clearable :placeholder="$t('view.settings.appearance.side_panel.sorting.placeholder')" @change="saveSidebarSortOrder") + el-option-group(:label="$t('view.settings.appearance.side_panel.sorting.dropdown_header')") + el-option.x-friend-item(:label="$t('view.settings.appearance.side_panel.sorting.alphabetical')" value="Sort Alphabetically") + el-option.x-friend-item(:label="$t('view.settings.appearance.side_panel.sorting.status')" value="Sort by Status") + el-option.x-friend-item(:label="$t('view.settings.appearance.side_panel.sorting.private_to_bottom')" value="Sort Private to Bottom") + el-option.x-friend-item(:label="$t('view.settings.appearance.side_panel.sorting.last_active')" value="Sort by Last Active") + el-option.x-friend-item(:label="$t('view.settings.appearance.side_panel.sorting.time_in_instance')" value="Sort by Time in Instance") + el-option.x-friend-item(:label="$t('view.settings.appearance.side_panel.sorting.location')" value="Sort by Location") + i.el-icon-arrow-right(style="margin:16px 5px") + el-select(v-model="sidebarSortMethod3" :disabled="!sidebarSortMethod2" style="width:170px" clearable :placeholder="$t('view.settings.appearance.side_panel.sorting.placeholder')" @change="saveSidebarSortOrder") + el-option-group(:label="$t('view.settings.appearance.side_panel.sorting.dropdown_header')") + el-option.x-friend-item(:label="$t('view.settings.appearance.side_panel.sorting.alphabetical')" value="Sort Alphabetically") + el-option.x-friend-item(:label="$t('view.settings.appearance.side_panel.sorting.status')" value="Sort by Status") + el-option.x-friend-item(:label="$t('view.settings.appearance.side_panel.sorting.private_to_bottom')" value="Sort Private to Bottom") + el-option.x-friend-item(:label="$t('view.settings.appearance.side_panel.sorting.last_active')" value="Sort by Last Active") + el-option.x-friend-item(:label="$t('view.settings.appearance.side_panel.sorting.time_in_instance')" value="Sort by Time in Instance") + el-option.x-friend-item(:label="$t('view.settings.appearance.side_panel.sorting.location')" value="Sort by Location") div.options-container-item - span.name {{ $t('view.settings.appearance.side_panel.sorting.sort_favorite_by') }} - el-switch(v-model="orderVIPFriends" :inactive-text="$t('view.settings.appearance.side_panel.sorting.sort_favorite_by_alphabet')" :active-text="$t('view.settings.appearance.side_panel.sorting.sort_favorite_by_online_time')" @change="saveOrderFriendGroup") - div.options-container-item - span.name {{ $t('view.settings.appearance.side_panel.sorting.sort_online_by') }} - el-switch(v-model="orderOnlineFriends" :inactive-text="$t('view.settings.appearance.side_panel.sorting.sort_online_by_alphabet')" :active-text="$t('view.settings.appearance.side_panel.sorting.sort_online_by_online_time')" @change="saveOrderFriendGroup") - div.options-container-item - span.name {{ $t('view.settings.appearance.side_panel.sorting.sort_active_by') }} - el-switch(v-model="orderActiveFriends" :inactive-text="$t('view.settings.appearance.side_panel.sorting.sort_active_by_alphabet')" :active-text="$t('view.settings.appearance.side_panel.sorting.sort_active_by_online_time')" @change="saveOrderFriendGroup") - div.options-container-item - span.name {{ $t('view.settings.appearance.side_panel.sorting.sort_offline_by') }} - el-switch(v-model="orderOfflineFriends" :inactive-text="$t('view.settings.appearance.side_panel.sorting.sort_offline_by_alphabet')" :active-text="$t('view.settings.appearance.side_panel.sorting.sort_offline_by_offline_time')" @change="saveOrderFriendGroup") - span.sub-header {{ $t('view.settings.appearance.side_panel.width') }} - div.options-container-item - el-slider(v-model="asideWidth" @input="setAsideWidth" :show-tooltip="false" :marks="{300: ''}" :min="200" :max="500" style="width:300px") + span.name(style="vertical-align:top;padding-top:10px") {{ $t('view.settings.appearance.side_panel.width') }} + el-slider(v-model="asideWidth" @input="setAsideWidth" :show-tooltip="false" :marks="{300: ''}" :min="200" :max="500" style="display:inline-block;width:300px") //- Appearance | User Dialog div.options-container span.header {{ $t('view.settings.appearance.user_dialog.header') }} @@ -233,6 +241,12 @@ mixin settingsTab() span.name {{ $t('view.settings.appearance.user_dialog.export_vrcx_memos_into_vrchat_notes') }} br el-button(size="small" icon="el-icon-document-copy" @click="showNoteExportDialog") {{ $t('view.settings.appearance.user_dialog.export_notes') }} + //- Appearance | Friend Log + div.options-container + span.header {{ $t('view.settings.appearance.friend_log.header') }} + div.options-container-item + span.name {{ $t('view.settings.appearance.friend_log.hide_unfriends') }} + el-switch(v-model="hideUnfriends" @change="saveFriendLogOptions") //- Appearance | User Colors div.options-container span.header {{ $t('view.settings.appearance.user_colors.header') }} @@ -261,12 +275,6 @@ mixin settingsTab() div el-color-picker(v-model="trustColor.troll" @change="updatetrustColor" size="mini" :predefine="['#782f2f']") span.color-picker(slot="trigger" class="x-tag-troll") Nuisance - //- Appearance | Friend Log - div.options-container - span.header {{ $t('view.settings.appearance.friend_log.header') }} - div.options-container-item - span.name {{ $t('view.settings.appearance.friend_log.hide_unfriends') }} - el-switch(v-model="hideUnfriends" @change="saveFriendLogOptions") //- Notifications Tab el-tab-pane(:label="$t('view.settings.category.notifications')") //- Notifications | Notifications