mirror of
https://github.com/MrUnknownDE/VRCX.git
synced 2026-05-02 21:16:07 +02:00
f4f78bb5ec
* refactor: frontend * Fix avatar gallery sort * Update .NET dependencies * Update npm dependencies electron v37.1.0 * bulkRefreshFriends * fix dark theme * Remove crowdin * Fix config.json dialog not updating * VRCX log file fixes & add Cef log * Remove SharedVariable, fix startup * Revert init theme change * Logging date not working? Fix WinformThemer designer error * Add Cef request hander, no more escaping main page * clean * fix * fix * clean * uh * Apply thememode at startup, fixes random user colours * Split database into files * Instance info remove empty lines * Open external VRC links with VRCX * Electron fixes * fix userdialog style * ohhhh * fix store * fix store * fix: load all group members after kicking a user * fix: world dialog favorite button style * fix: Clear VRCX Cache Timer input value * clean * Fix VR overlay * Fix VR overlay 2 * Fix Discord discord rich presence for RPC worlds * Clean up age verified user tags * Fix playerList being occupied after program reload * no `this` * Fix login stuck loading * writable: false * Hide dialogs on logout * add flush sync option * rm LOGIN event * rm LOGOUT event * remove duplicate event listeners * remove duplicate event listeners * clean * remove duplicate event listeners * clean * fix theme style * fix t * clearable * clean * fix ipcEvent * Small changes * Popcorn Palace support * Remove checkActiveFriends * Clean up * Fix dragEnterCef * Block API requests when not logged in * Clear state on login & logout * Fix worldDialog instances not updating * use <script setup> * Fix avatar change event, CheckGameRunning at startup * Fix image dragging * fix * Remove PWI * fix updateLoop * add webpack-dev-server to dev environment * rm unnecessary chunks * use <script setup> * webpack-dev-server changes * use <script setup> * use <script setup> * Fix UGC text size * Split login event * t * use <script setup> * fix * Update .gitignore and enable checkJs in jsconfig * fix i18n t * use <script setup> * use <script setup> * clean * global types * fix * use checkJs for debugging * Add watchState for login watchers * fix .vue template * type fixes * rm Vue.filter * Cef v138.0.170, VC++ 2022 * Settings fixes * Remove 'USER:CURRENT' * clean up 2FA callbacks * remove userApply * rm i18n import * notification handling to use notification store methods * refactor favorite handling to use favorite store methods and clean up event emissions * refactor moderation handling to use dedicated functions for player moderation events * refactor friend handling to use dedicated functions for friend events * Fix program startup, move lang init * Fix friend state * Fix status change error * Fix user notes diff * fix * rm group event * rm auth event * rm avatar event * clean * clean * getUser * getFriends * getFavoriteWorlds, getFavoriteAvatars * AvatarGalleryUpload btn style & package.json update * Fix friend requests * Apply user * Apply world * Fix note diff * Fix VR overlay * Fixes * Update build scripts * Apply avatar * Apply instance * Apply group * update hidden VRC+ badge * Fix sameInstance "private" * fix 502/504 API errors * fix 502/504 API errors * clean * Fix friend in same instance on orange showing twice in friends list * Add back in broken friend state repair methods * add types --------- Co-authored-by: Natsumi <cmcooper123@hotmail.com>
1999 lines
63 KiB
JavaScript
1999 lines
63 KiB
JavaScript
import { defineStore } from 'pinia';
|
|
import { computed, reactive, watch } from 'vue';
|
|
import { favoriteRequest } from '../api';
|
|
import { $app } from '../app';
|
|
import { database } from '../service/database';
|
|
import { processBulk } from '../service/request';
|
|
import { watchState } from '../service/watchState';
|
|
import { compareByName, removeFromArray } from '../shared/utils';
|
|
import { useAvatarStore } from './avatar';
|
|
import { useFriendStore } from './friend';
|
|
import { useAppearanceSettingsStore } from './settings/appearance';
|
|
import { useGeneralSettingsStore } from './settings/general';
|
|
import { useUserStore } from './user';
|
|
import { useWorldStore } from './world';
|
|
import { useI18n } from 'vue-i18n-bridge';
|
|
|
|
export const useFavoriteStore = defineStore('Favorite', () => {
|
|
const appearanceSettingsStore = useAppearanceSettingsStore();
|
|
const friendStore = useFriendStore();
|
|
const generalSettingsStore = useGeneralSettingsStore();
|
|
const avatarStore = useAvatarStore();
|
|
const worldStore = useWorldStore();
|
|
const userStore = useUserStore();
|
|
|
|
const { t } = useI18n();
|
|
|
|
const state = reactive({
|
|
isFavoriteGroupLoading: false,
|
|
favoriteFriendGroups: [],
|
|
cachedFavoriteGroups: new Map(),
|
|
favoriteLimits: {
|
|
maxFavoriteGroups: {
|
|
avatar: 6,
|
|
friend: 3,
|
|
world: 4
|
|
},
|
|
maxFavoritesPerGroup: {
|
|
avatar: 50,
|
|
friend: 150,
|
|
world: 100
|
|
}
|
|
},
|
|
cachedFavoriteGroupsByTypeName: new Map(),
|
|
cachedFavorites: new Map(),
|
|
favoriteWorldGroups: [],
|
|
favoriteAvatarGroups: [],
|
|
isFavoriteLoading: false,
|
|
friendImportDialogInput: '',
|
|
worldImportDialogInput: '',
|
|
avatarImportDialogInput: '',
|
|
worldImportDialogVisible: false,
|
|
avatarImportDialogVisible: false,
|
|
friendImportDialogVisible: false,
|
|
localWorldFavorites: {},
|
|
localAvatarFavorites: {},
|
|
localAvatarFavoritesList: [],
|
|
localAvatarFavoriteGroups: [],
|
|
favoriteDialog: {
|
|
visible: false,
|
|
loading: false,
|
|
type: '',
|
|
objectId: '',
|
|
currentGroup: {}
|
|
},
|
|
favoriteObjects: new Map(),
|
|
localWorldFavoriteGroups: [],
|
|
localWorldFavoritesList: [],
|
|
favoriteFriends_: [],
|
|
favoriteFriendsSorted: [],
|
|
favoriteWorlds_: [],
|
|
favoriteWorldsSorted: [],
|
|
favoriteAvatars_: [],
|
|
favoriteAvatarsSorted: [],
|
|
sortFavoriteFriends: false,
|
|
sortFavoriteWorlds: false,
|
|
sortFavoriteAvatars: false,
|
|
cachedFavoritesByObjectId: new Map()
|
|
});
|
|
|
|
const favoriteFriends = computed(() => {
|
|
if (state.sortFavoriteFriends) {
|
|
state.sortFavoriteFriends = false;
|
|
state.favoriteFriendsSorted.sort(compareByName);
|
|
}
|
|
if (appearanceSettingsStore.sortFavorites) {
|
|
return state.favoriteFriends_;
|
|
}
|
|
return state.favoriteFriendsSorted;
|
|
});
|
|
|
|
const favoriteWorlds = computed(() => {
|
|
if (state.sortFavoriteWorlds) {
|
|
state.sortFavoriteWorlds = false;
|
|
state.favoriteWorldsSorted.sort(compareByName);
|
|
}
|
|
if (appearanceSettingsStore.sortFavorites) {
|
|
return state.favoriteWorlds_;
|
|
}
|
|
return state.favoriteWorldsSorted;
|
|
});
|
|
|
|
const favoriteAvatars = computed(() => {
|
|
if (state.sortFavoriteAvatars) {
|
|
state.sortFavoriteAvatars = false;
|
|
state.favoriteAvatarsSorted.sort(compareByName);
|
|
}
|
|
if (appearanceSettingsStore.sortFavorites) {
|
|
return state.favoriteAvatars_;
|
|
}
|
|
return state.favoriteAvatarsSorted;
|
|
});
|
|
|
|
const isFavoriteGroupLoading = computed({
|
|
get() {
|
|
return state.isFavoriteGroupLoading;
|
|
},
|
|
set(value) {
|
|
state.isFavoriteGroupLoading = value;
|
|
}
|
|
});
|
|
|
|
const favoriteFriendGroups = computed({
|
|
get() {
|
|
return state.favoriteFriendGroups;
|
|
},
|
|
set(value) {
|
|
state.favoriteFriendGroups = value;
|
|
}
|
|
});
|
|
const favoriteWorldGroups = computed({
|
|
get() {
|
|
return state.favoriteWorldGroups;
|
|
},
|
|
set(value) {
|
|
state.favoriteWorldGroups = value;
|
|
}
|
|
});
|
|
const favoriteAvatarGroups = computed({
|
|
get() {
|
|
return state.favoriteAvatarGroups;
|
|
},
|
|
set(value) {
|
|
state.favoriteAvatarGroups = value;
|
|
}
|
|
});
|
|
|
|
const cachedFavoriteGroups = state.cachedFavoriteGroups;
|
|
const cachedFavoriteGroupsByTypeName = state.cachedFavoriteGroupsByTypeName;
|
|
const cachedFavorites = state.cachedFavorites;
|
|
|
|
const favoriteLimits = computed({
|
|
get() {
|
|
return state.favoriteLimits;
|
|
},
|
|
set(value) {
|
|
state.favoriteLimits = value;
|
|
}
|
|
});
|
|
|
|
const isFavoriteLoading = computed({
|
|
get() {
|
|
return state.isFavoriteLoading;
|
|
},
|
|
set(value) {
|
|
state.isFavoriteLoading = value;
|
|
}
|
|
});
|
|
|
|
const friendImportDialogInput = computed({
|
|
get() {
|
|
return state.friendImportDialogInput;
|
|
},
|
|
set(value) {
|
|
state.friendImportDialogInput = value;
|
|
}
|
|
});
|
|
|
|
const worldImportDialogInput = computed({
|
|
get() {
|
|
return state.worldImportDialogInput;
|
|
},
|
|
set(value) {
|
|
state.worldImportDialogInput = value;
|
|
}
|
|
});
|
|
|
|
const avatarImportDialogInput = computed({
|
|
get() {
|
|
return state.avatarImportDialogInput;
|
|
},
|
|
set(value) {
|
|
state.avatarImportDialogInput = value;
|
|
}
|
|
});
|
|
|
|
const worldImportDialogVisible = computed({
|
|
get() {
|
|
return state.worldImportDialogVisible;
|
|
},
|
|
set(value) {
|
|
state.worldImportDialogVisible = value;
|
|
}
|
|
});
|
|
|
|
const avatarImportDialogVisible = computed({
|
|
get() {
|
|
return state.avatarImportDialogVisible;
|
|
},
|
|
set(value) {
|
|
state.avatarImportDialogVisible = value;
|
|
}
|
|
});
|
|
|
|
const friendImportDialogVisible = computed({
|
|
get() {
|
|
return state.friendImportDialogVisible;
|
|
},
|
|
set(value) {
|
|
state.friendImportDialogVisible = value;
|
|
}
|
|
});
|
|
|
|
const localWorldFavorites = computed({
|
|
get() {
|
|
return state.localWorldFavorites;
|
|
},
|
|
set(value) {
|
|
state.localWorldFavorites = value;
|
|
}
|
|
});
|
|
|
|
const localAvatarFavorites = computed({
|
|
get() {
|
|
return state.localAvatarFavorites;
|
|
},
|
|
set(value) {
|
|
state.localAvatarFavorites = value;
|
|
}
|
|
});
|
|
|
|
const localAvatarFavoritesList = computed({
|
|
get() {
|
|
return state.localAvatarFavoritesList;
|
|
},
|
|
set(value) {
|
|
state.localAvatarFavoritesList = value;
|
|
}
|
|
});
|
|
|
|
const localAvatarFavoriteGroups = computed({
|
|
get() {
|
|
return state.localAvatarFavoriteGroups;
|
|
},
|
|
set(value) {
|
|
state.localAvatarFavoriteGroups = value;
|
|
}
|
|
});
|
|
|
|
const favoriteDialog = computed({
|
|
get() {
|
|
return state.favoriteDialog;
|
|
},
|
|
set(value) {
|
|
state.favoriteDialog = value;
|
|
}
|
|
});
|
|
|
|
const favoriteObjects = computed({
|
|
get() {
|
|
return state.favoriteObjects;
|
|
},
|
|
set(value) {
|
|
state.favoriteObjects = value;
|
|
}
|
|
});
|
|
|
|
const localWorldFavoritesList = computed({
|
|
get() {
|
|
return state.localWorldFavoritesList;
|
|
},
|
|
set(value) {
|
|
state.localWorldFavoritesList = value;
|
|
}
|
|
});
|
|
|
|
const favoriteFriends_ = computed({
|
|
get() {
|
|
return state.favoriteFriends_;
|
|
},
|
|
set(value) {
|
|
state.favoriteFriends_ = value;
|
|
}
|
|
});
|
|
|
|
const favoriteFriendsSorted = computed({
|
|
get() {
|
|
return state.favoriteFriendsSorted;
|
|
},
|
|
set(value) {
|
|
state.favoriteFriendsSorted = value;
|
|
}
|
|
});
|
|
|
|
const favoriteWorlds_ = computed({
|
|
get() {
|
|
return state.favoriteWorlds_;
|
|
},
|
|
set(value) {
|
|
state.favoriteWorlds_ = value;
|
|
}
|
|
});
|
|
|
|
const favoriteWorldsSorted = computed({
|
|
get() {
|
|
return state.favoriteWorldsSorted;
|
|
},
|
|
set(value) {
|
|
state.favoriteWorldsSorted = value;
|
|
}
|
|
});
|
|
|
|
const favoriteAvatars_ = computed({
|
|
get() {
|
|
return state.favoriteAvatars_;
|
|
},
|
|
set(value) {
|
|
state.favoriteAvatars_ = value;
|
|
}
|
|
});
|
|
|
|
const favoriteAvatarsSorted = computed({
|
|
get() {
|
|
return state.favoriteAvatarsSorted;
|
|
},
|
|
set(value) {
|
|
state.favoriteAvatarsSorted = value;
|
|
}
|
|
});
|
|
|
|
const sortFavoriteFriends = computed({
|
|
get() {
|
|
return state.sortFavoriteFriends;
|
|
},
|
|
set(value) {
|
|
state.sortFavoriteFriends = value;
|
|
}
|
|
});
|
|
|
|
const sortFavoriteWorlds = computed({
|
|
get() {
|
|
return state.sortFavoriteWorlds;
|
|
},
|
|
set(value) {
|
|
state.sortFavoriteWorlds = value;
|
|
}
|
|
});
|
|
|
|
const sortFavoriteAvatars = computed({
|
|
get() {
|
|
return state.sortFavoriteAvatars;
|
|
},
|
|
set(value) {
|
|
state.sortFavoriteAvatars = value;
|
|
}
|
|
});
|
|
|
|
const cachedFavoritesByObjectId = computed({
|
|
get() {
|
|
return state.cachedFavoritesByObjectId;
|
|
},
|
|
set(value) {
|
|
state.cachedFavoritesByObjectId = value;
|
|
}
|
|
});
|
|
|
|
const localWorldFavoriteGroups = computed({
|
|
get() {
|
|
return state.localWorldFavoriteGroups;
|
|
},
|
|
set(value) {
|
|
state.localWorldFavoriteGroups = value;
|
|
}
|
|
});
|
|
|
|
const groupedByGroupKeyFavoriteFriends = computed(() => {
|
|
const groupedByGroupKeyFavoriteFriends = {};
|
|
favoriteFriends.value.forEach((friend) => {
|
|
if (friend.groupKey) {
|
|
if (!groupedByGroupKeyFavoriteFriends[friend.groupKey]) {
|
|
groupedByGroupKeyFavoriteFriends[friend.groupKey] = [];
|
|
}
|
|
groupedByGroupKeyFavoriteFriends[friend.groupKey].push(friend);
|
|
}
|
|
});
|
|
return groupedByGroupKeyFavoriteFriends;
|
|
});
|
|
|
|
watch(
|
|
() => watchState.isLoggedIn,
|
|
(isLoggedIn) => {
|
|
friendStore.localFavoriteFriends.clear();
|
|
state.cachedFavorites.clear();
|
|
state.cachedFavoritesByObjectId.clear();
|
|
state.cachedFavoriteGroups.clear();
|
|
state.cachedFavoriteGroupsByTypeName.clear();
|
|
state.favoriteFriendGroups = [];
|
|
state.favoriteWorldGroups = [];
|
|
state.favoriteAvatarGroups = [];
|
|
state.isFavoriteLoading = false;
|
|
state.isFavoriteGroupLoading = false;
|
|
state.favoriteObjects.clear();
|
|
state.favoriteFriends_ = [];
|
|
state.favoriteFriendsSorted = [];
|
|
state.favoriteWorlds_ = [];
|
|
state.favoriteWorldsSorted = [];
|
|
state.favoriteAvatars_ = [];
|
|
state.favoriteAvatarsSorted = [];
|
|
state.sortFavoriteFriends = false;
|
|
state.sortFavoriteWorlds = false;
|
|
state.sortFavoriteAvatars = false;
|
|
state.localAvatarFavoriteGroups = [];
|
|
state.localAvatarFavoritesList = [];
|
|
state.localAvatarFavorites = {};
|
|
state.favoriteDialog.visible = false;
|
|
state.worldImportDialogVisible = false;
|
|
state.avatarImportDialogVisible = false;
|
|
state.friendImportDialogVisible = false;
|
|
if (isLoggedIn) {
|
|
initFavorites();
|
|
}
|
|
},
|
|
{ flush: 'sync' }
|
|
);
|
|
|
|
function handleFavoriteAdd(args) {
|
|
handleFavorite({
|
|
json: args.json,
|
|
params: {
|
|
favoriteId: args.json.id
|
|
},
|
|
sortTop: true
|
|
});
|
|
|
|
if (
|
|
args.params.type === 'avatar' &&
|
|
!avatarStore.cachedAvatars.has(args.params.favoriteId)
|
|
) {
|
|
refreshFavoriteAvatars(args.params.tags);
|
|
}
|
|
|
|
if (
|
|
args.params.type === 'friend' &&
|
|
generalSettingsStore.localFavoriteFriendsGroups.includes(
|
|
'friend:' + args.params.tags
|
|
)
|
|
) {
|
|
friendStore.updateLocalFavoriteFriends();
|
|
}
|
|
updateFavoriteDialog(args.params.objectId);
|
|
}
|
|
|
|
function handleFavorite(args) {
|
|
const fav = applyFavoriteCached(args.json);
|
|
if (!fav.$isDeleted) {
|
|
args.ref = fav;
|
|
}
|
|
applyFavorite(args.ref.type, args.ref.favoriteId, args.sortTop);
|
|
friendStore.updateFriend(args.ref.favoriteId);
|
|
const { ref } = args;
|
|
const userDialog = userStore.userDialog;
|
|
if (
|
|
!(
|
|
userDialog.visible === false ||
|
|
ref.$isDeleted ||
|
|
ref.favoriteId !== userDialog.id
|
|
)
|
|
) {
|
|
userDialog.isFavorite = true;
|
|
}
|
|
|
|
const worldDialog = worldStore.worldDialog;
|
|
if (
|
|
!(
|
|
worldDialog.visible === false ||
|
|
ref.$isDeleted ||
|
|
ref.favoriteId !== worldDialog.id
|
|
)
|
|
) {
|
|
worldDialog.isFavorite = true;
|
|
}
|
|
|
|
const avatarDialog = avatarStore.avatarDialog;
|
|
if (
|
|
!(
|
|
avatarDialog.visible === false ||
|
|
ref.$isDeleted ||
|
|
ref.favoriteId !== avatarDialog.id
|
|
)
|
|
) {
|
|
avatarDialog.isFavorite = true;
|
|
}
|
|
}
|
|
|
|
function handleFavoriteDelete(args) {
|
|
const ref = state.cachedFavoritesByObjectId.get(args.params.objectId);
|
|
if (typeof ref === 'undefined') {
|
|
return;
|
|
}
|
|
state.cachedFavoritesByObjectId.delete(args.params.objectId);
|
|
friendStore.localFavoriteFriends.delete(args.params.objectId);
|
|
friendStore.updateSidebarFriendsList();
|
|
if (ref.$isDeleted) {
|
|
return;
|
|
}
|
|
args.ref = ref;
|
|
ref.$isDeleted = true;
|
|
handleFavoriteAtDelete({
|
|
ref,
|
|
params: {
|
|
favoriteId: ref.id
|
|
}
|
|
});
|
|
}
|
|
|
|
function handleFavoriteGroup(args) {
|
|
const ref = applyFavoriteGroup(args.json);
|
|
if (ref.$isDeleted) {
|
|
return;
|
|
}
|
|
args.ref = ref;
|
|
if (ref.$groupRef !== null) {
|
|
ref.$groupRef.displayName = ref.displayName;
|
|
ref.$groupRef.visibility = ref.visibility;
|
|
}
|
|
}
|
|
|
|
function handleFavoriteGroupClear(args) {
|
|
const key = `${args.params.type}:${args.params.group}`;
|
|
for (const ref of state.cachedFavorites.values()) {
|
|
if (ref.$isDeleted || ref.$groupKey !== key) {
|
|
continue;
|
|
}
|
|
state.cachedFavoritesByObjectId.delete(ref.favoriteId);
|
|
friendStore.localFavoriteFriends.delete(ref.favoriteId);
|
|
friendStore.updateSidebarFriendsList();
|
|
ref.$isDeleted = true;
|
|
handleFavoriteAtDelete({
|
|
ref,
|
|
params: {
|
|
favoriteId: ref.id
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
function handleFavoriteWorldList(args) {
|
|
for (const json of args.json) {
|
|
if (json.id === '???') {
|
|
continue;
|
|
}
|
|
worldStore.applyWorld(json);
|
|
}
|
|
}
|
|
|
|
function handleFavoriteAvatarList(args) {
|
|
for (const json of args.json) {
|
|
if (json.releaseStatus === 'hidden') {
|
|
continue;
|
|
}
|
|
avatarStore.applyAvatar(json);
|
|
}
|
|
}
|
|
|
|
function expireFavorites() {
|
|
friendStore.localFavoriteFriends.clear();
|
|
state.cachedFavorites.clear();
|
|
state.cachedFavoritesByObjectId.clear();
|
|
state.favoriteObjects.clear();
|
|
state.favoriteFriends_ = [];
|
|
state.favoriteFriendsSorted = [];
|
|
state.favoriteWorlds_ = [];
|
|
state.favoriteWorldsSorted = [];
|
|
state.favoriteAvatars_ = [];
|
|
state.favoriteAvatarsSorted = [];
|
|
}
|
|
|
|
function handleFavoriteAtDelete(args) {
|
|
const { ref } = args;
|
|
if (ref.$groupRef !== null) {
|
|
--ref.$groupRef.count;
|
|
}
|
|
applyFavorite(args.ref.type, args.ref.favoriteId);
|
|
friendStore.updateFriend(args.ref.favoriteId);
|
|
const userDialog = userStore.userDialog;
|
|
if (
|
|
!(
|
|
userDialog.visible === false ||
|
|
userDialog.id !== args.ref.favoriteId
|
|
)
|
|
) {
|
|
userDialog.isFavorite = false;
|
|
}
|
|
|
|
const favoriteStore = useFavoriteStore();
|
|
const worldDialog = worldStore.worldDialog;
|
|
if (
|
|
!(
|
|
worldDialog.visible === false ||
|
|
worldDialog.id !== args.ref.favoriteId
|
|
)
|
|
) {
|
|
worldDialog.isFavorite =
|
|
favoriteStore.localWorldFavoritesList.includes(worldDialog.id);
|
|
}
|
|
|
|
const avatarDialog = avatarStore.avatarDialog;
|
|
if (
|
|
!(
|
|
avatarDialog.visible === false ||
|
|
avatarDialog.id !== args.ref.favoriteId
|
|
)
|
|
) {
|
|
avatarDialog.isFavorite = false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* aka: `$app.methods.applyFavorite`
|
|
* @param {'friend' | 'world' | 'avatar'} type
|
|
* @param {string} objectId
|
|
* @param {boolean} sortTop
|
|
* @returns {Promise<void>}
|
|
*/
|
|
async function applyFavorite(type, objectId, sortTop = false) {
|
|
let ref;
|
|
const favorite = state.cachedFavoritesByObjectId.get(objectId);
|
|
let ctx = state.favoriteObjects.get(objectId);
|
|
if (typeof favorite !== 'undefined') {
|
|
let isTypeChanged = false;
|
|
if (typeof ctx === 'undefined') {
|
|
ctx = {
|
|
id: objectId,
|
|
type,
|
|
groupKey: favorite.$groupKey,
|
|
ref: null,
|
|
name: '',
|
|
$selected: false
|
|
};
|
|
state.favoriteObjects.set(objectId, ctx);
|
|
if (type === 'friend') {
|
|
ref = userStore.cachedUsers.get(objectId);
|
|
if (typeof ref === 'undefined') {
|
|
ref = friendStore.friendLog.get(objectId);
|
|
if (typeof ref !== 'undefined' && ref.displayName) {
|
|
ctx.name = ref.displayName;
|
|
}
|
|
} else {
|
|
ctx.ref = ref;
|
|
ctx.name = ref.displayName;
|
|
}
|
|
} else if (type === 'world') {
|
|
ref = worldStore.cachedWorlds.get(objectId);
|
|
if (typeof ref !== 'undefined') {
|
|
ctx.ref = ref;
|
|
ctx.name = ref.name;
|
|
}
|
|
} else if (type === 'avatar') {
|
|
ref = avatarStore.cachedAvatars.get(objectId);
|
|
if (typeof ref !== 'undefined') {
|
|
ctx.ref = ref;
|
|
ctx.name = ref.name;
|
|
}
|
|
}
|
|
isTypeChanged = true;
|
|
} else {
|
|
if (ctx.type !== type) {
|
|
// WTF???
|
|
isTypeChanged = true;
|
|
if (type === 'friend') {
|
|
removeFromArray(state.favoriteFriends_, ctx);
|
|
removeFromArray(state.favoriteFriendsSorted, ctx);
|
|
} else if (type === 'world') {
|
|
removeFromArray(state.favoriteWorlds_, ctx);
|
|
removeFromArray(state.favoriteWorldsSorted, ctx);
|
|
} else if (type === 'avatar') {
|
|
removeFromArray(state.favoriteAvatars_, ctx);
|
|
removeFromArray(state.favoriteAvatarsSorted, ctx);
|
|
}
|
|
}
|
|
if (type === 'friend') {
|
|
ref = userStore.cachedUsers.get(objectId);
|
|
if (typeof ref !== 'undefined') {
|
|
if (ctx.ref !== ref) {
|
|
ctx.ref = ref;
|
|
}
|
|
if (ctx.name !== ref.displayName) {
|
|
ctx.name = ref.displayName;
|
|
state.sortFavoriteFriends = true;
|
|
}
|
|
}
|
|
// else too bad
|
|
} else if (type === 'world') {
|
|
ref = worldStore.cachedWorlds.get(objectId);
|
|
if (typeof ref !== 'undefined') {
|
|
if (ctx.ref !== ref) {
|
|
ctx.ref = ref;
|
|
}
|
|
if (ctx.name !== ref.name) {
|
|
ctx.name = ref.name;
|
|
state.sortFavoriteWorlds = true;
|
|
}
|
|
} else {
|
|
// try fetch from local world favorites
|
|
const world =
|
|
await database.getCachedWorldById(objectId);
|
|
if (world) {
|
|
ctx.ref = world;
|
|
ctx.name = world.name;
|
|
ctx.deleted = true;
|
|
state.sortFavoriteWorlds = true;
|
|
}
|
|
if (!world) {
|
|
// try fetch from local world history
|
|
const worldName =
|
|
await database.getGameLogWorldNameByWorldId(
|
|
objectId
|
|
);
|
|
if (worldName) {
|
|
ctx.name = worldName;
|
|
ctx.deleted = true;
|
|
state.sortFavoriteWorlds = true;
|
|
}
|
|
}
|
|
}
|
|
} else if (type === 'avatar') {
|
|
ref = avatarStore.cachedAvatars.get(objectId);
|
|
if (typeof ref !== 'undefined') {
|
|
if (ctx.ref !== ref) {
|
|
ctx.ref = ref;
|
|
}
|
|
if (ctx.name !== ref.name) {
|
|
ctx.name = ref.name;
|
|
state.sortFavoriteAvatars = true;
|
|
}
|
|
} else {
|
|
// try fetch from local avatar history
|
|
const avatar =
|
|
await database.getCachedAvatarById(objectId);
|
|
if (avatar) {
|
|
ctx.ref = avatar;
|
|
ctx.name = avatar.name;
|
|
ctx.deleted = true;
|
|
state.sortFavoriteAvatars = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (isTypeChanged) {
|
|
if (sortTop) {
|
|
if (type === 'friend') {
|
|
state.favoriteFriends_.unshift(ctx);
|
|
state.favoriteFriendsSorted.push(ctx);
|
|
state.sortFavoriteFriends = true;
|
|
} else if (type === 'world') {
|
|
state.favoriteWorlds_.unshift(ctx);
|
|
state.favoriteWorldsSorted.push(ctx);
|
|
state.sortFavoriteWorlds = true;
|
|
} else if (type === 'avatar') {
|
|
state.favoriteAvatars_.unshift(ctx);
|
|
state.favoriteAvatarsSorted.push(ctx);
|
|
state.sortFavoriteAvatars = true;
|
|
}
|
|
} else if (type === 'friend') {
|
|
state.favoriteFriends_.push(ctx);
|
|
state.favoriteFriendsSorted.push(ctx);
|
|
state.sortFavoriteFriends = true;
|
|
} else if (type === 'world') {
|
|
state.favoriteWorlds_.push(ctx);
|
|
state.favoriteWorldsSorted.push(ctx);
|
|
state.sortFavoriteWorlds = true;
|
|
} else if (type === 'avatar') {
|
|
state.favoriteAvatars_.push(ctx);
|
|
state.favoriteAvatarsSorted.push(ctx);
|
|
state.sortFavoriteAvatars = true;
|
|
}
|
|
}
|
|
} else if (typeof ctx !== 'undefined') {
|
|
state.favoriteObjects.delete(objectId);
|
|
if (type === 'friend') {
|
|
removeFromArray(state.favoriteFriends_, ctx);
|
|
removeFromArray(state.favoriteFriendsSorted, ctx);
|
|
} else if (type === 'world') {
|
|
removeFromArray(state.favoriteWorlds_, ctx);
|
|
removeFromArray(state.favoriteWorldsSorted, ctx);
|
|
} else if (type === 'avatar') {
|
|
removeFromArray(state.favoriteAvatars_, ctx);
|
|
removeFromArray(state.favoriteAvatarsSorted, ctx);
|
|
}
|
|
}
|
|
}
|
|
|
|
function refreshFavoriteGroups() {
|
|
if (state.isFavoriteGroupLoading) {
|
|
return;
|
|
}
|
|
state.isFavoriteGroupLoading = true;
|
|
expireFavoriteGroups();
|
|
processBulk({
|
|
fn: favoriteRequest.getFavoriteGroups,
|
|
N: -1,
|
|
params: {
|
|
n: 50,
|
|
offset: 0
|
|
},
|
|
handle: (args) => {
|
|
for (const json of args.json) {
|
|
handleFavoriteGroup({
|
|
json,
|
|
params: {
|
|
favoriteGroupId: json.id
|
|
}
|
|
});
|
|
}
|
|
},
|
|
done(ok) {
|
|
if (ok) {
|
|
deleteExpiredFavoriteGroups();
|
|
buildFavoriteGroups();
|
|
}
|
|
state.isFavoriteGroupLoading = false;
|
|
}
|
|
});
|
|
}
|
|
|
|
function expireFavoriteGroups() {
|
|
for (const ref of state.cachedFavoriteGroups.values()) {
|
|
ref.$isExpired = true;
|
|
}
|
|
}
|
|
|
|
function deleteExpiredFavoriteGroups() {
|
|
for (const ref of state.cachedFavoriteGroups.values()) {
|
|
if (ref.$isDeleted || ref.$isExpired === false) {
|
|
continue;
|
|
}
|
|
ref.$isDeleted = true;
|
|
}
|
|
}
|
|
|
|
function buildFavoriteGroups() {
|
|
let group;
|
|
let groups;
|
|
let ref;
|
|
let i;
|
|
// 450 = ['group_0', 'group_1', 'group_2'] x 150
|
|
state.favoriteFriendGroups = [];
|
|
for (i = 0; i < state.favoriteLimits.maxFavoriteGroups.friend; ++i) {
|
|
state.favoriteFriendGroups.push({
|
|
assign: false,
|
|
key: `friend:group_${i}`,
|
|
type: 'friend',
|
|
name: `group_${i}`,
|
|
displayName: `Group ${i + 1}`,
|
|
capacity: state.favoriteLimits.maxFavoritesPerGroup.friend,
|
|
count: 0,
|
|
visibility: 'private'
|
|
});
|
|
}
|
|
// 400 = ['worlds1', 'worlds2', 'worlds3', 'worlds4'] x 100
|
|
state.favoriteWorldGroups = [];
|
|
for (i = 0; i < state.favoriteLimits.maxFavoriteGroups.world; ++i) {
|
|
state.favoriteWorldGroups.push({
|
|
assign: false,
|
|
key: `world:worlds${i + 1}`,
|
|
type: 'world',
|
|
name: `worlds${i + 1}`,
|
|
displayName: `Group ${i + 1}`,
|
|
capacity: state.favoriteLimits.maxFavoritesPerGroup.world,
|
|
count: 0,
|
|
visibility: 'private'
|
|
});
|
|
}
|
|
// 350 = ['avatars1', ...] x 50
|
|
// Favorite Avatars (0/50)
|
|
// VRC+ Group 1..5 (0/50)
|
|
state.favoriteAvatarGroups = [];
|
|
for (i = 0; i < state.favoriteLimits.maxFavoriteGroups.avatar; ++i) {
|
|
state.favoriteAvatarGroups.push({
|
|
assign: false,
|
|
key: `avatar:avatars${i + 1}`,
|
|
type: 'avatar',
|
|
name: `avatars${i + 1}`,
|
|
displayName: `Group ${i + 1}`,
|
|
capacity: state.favoriteLimits.maxFavoritesPerGroup.avatar,
|
|
count: 0,
|
|
visibility: 'private'
|
|
});
|
|
}
|
|
const types = {
|
|
friend: state.favoriteFriendGroups,
|
|
world: state.favoriteWorldGroups,
|
|
avatar: state.favoriteAvatarGroups
|
|
};
|
|
const assigns = new Set();
|
|
// assign the same name first
|
|
for (ref of state.cachedFavoriteGroups.values()) {
|
|
if (ref.$isDeleted) {
|
|
continue;
|
|
}
|
|
groups = types[ref.type];
|
|
if (typeof groups === 'undefined') {
|
|
continue;
|
|
}
|
|
for (group of groups) {
|
|
if (group.assign === false && group.name === ref.name) {
|
|
group.assign = true;
|
|
if (ref.displayName) {
|
|
group.displayName = ref.displayName;
|
|
}
|
|
group.visibility = ref.visibility;
|
|
ref.$groupRef = group;
|
|
assigns.add(ref.id);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (ref of state.cachedFavoriteGroups.values()) {
|
|
if (ref.$isDeleted || assigns.has(ref.id)) {
|
|
continue;
|
|
}
|
|
groups = types[ref.type];
|
|
if (typeof groups === 'undefined') {
|
|
continue;
|
|
}
|
|
for (group of groups) {
|
|
if (group.assign === false) {
|
|
group.assign = true;
|
|
group.key = `${group.type}:${ref.name}`;
|
|
group.name = ref.name;
|
|
group.displayName = ref.displayName;
|
|
ref.$groupRef = group;
|
|
assigns.add(ref.id);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
// update favorites
|
|
state.cachedFavoriteGroupsByTypeName.clear();
|
|
for (const type in types) {
|
|
for (group of types[type]) {
|
|
state.cachedFavoriteGroupsByTypeName.set(group.key, group);
|
|
}
|
|
}
|
|
for (ref of state.cachedFavorites.values()) {
|
|
ref.$groupRef = null;
|
|
if (ref.$isDeleted) {
|
|
continue;
|
|
}
|
|
group = state.cachedFavoriteGroupsByTypeName.get(ref.$groupKey);
|
|
if (typeof group === 'undefined') {
|
|
continue;
|
|
}
|
|
ref.$groupRef = group;
|
|
++group.count;
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @returns {Promise<void>}
|
|
*/
|
|
async function refreshFavorites() {
|
|
if (state.isFavoriteLoading) {
|
|
return;
|
|
}
|
|
state.isFavoriteLoading = true;
|
|
try {
|
|
const args = await favoriteRequest.getFavoriteLimits();
|
|
state.favoriteLimits = {
|
|
...state.favoriteLimits,
|
|
...args.json
|
|
};
|
|
} catch (err) {
|
|
console.error(err);
|
|
}
|
|
expireFavorites();
|
|
state.cachedFavoriteGroupsByTypeName.clear();
|
|
processBulk({
|
|
fn: favoriteRequest.getFavorites,
|
|
N: -1,
|
|
params: {
|
|
n: 50,
|
|
offset: 0
|
|
},
|
|
handle(args) {
|
|
for (const json of args.json) {
|
|
handleFavorite({
|
|
json,
|
|
params: {
|
|
favoriteId: json.id
|
|
},
|
|
sortTop: false
|
|
});
|
|
}
|
|
},
|
|
done(ok) {
|
|
if (ok) {
|
|
deleteExpiredFavorites();
|
|
}
|
|
refreshFavoriteItems();
|
|
refreshFavoriteGroups();
|
|
friendStore.updateLocalFavoriteFriends();
|
|
state.isFavoriteLoading = false;
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param json
|
|
* @returns {any}
|
|
*/
|
|
function applyFavoriteGroup(json) {
|
|
let ref = state.cachedFavoriteGroups.get(json.id);
|
|
if (typeof ref === 'undefined') {
|
|
ref = {
|
|
id: '',
|
|
ownerId: '',
|
|
ownerDisplayName: '',
|
|
name: '',
|
|
displayName: '',
|
|
type: '',
|
|
visibility: '',
|
|
tags: [],
|
|
// VRCX
|
|
$isDeleted: false,
|
|
$isExpired: false,
|
|
$groupRef: null,
|
|
//
|
|
...json
|
|
};
|
|
state.cachedFavoriteGroups.set(ref.id, ref);
|
|
} else {
|
|
Object.assign(ref, json);
|
|
ref.$isExpired = false;
|
|
}
|
|
return ref;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param json
|
|
* @returns {any}
|
|
*/
|
|
function applyFavoriteCached(json) {
|
|
let ref = state.cachedFavorites.get(json.id);
|
|
if (typeof ref === 'undefined') {
|
|
ref = {
|
|
id: '',
|
|
type: '',
|
|
favoriteId: '',
|
|
tags: [],
|
|
// VRCX
|
|
$isDeleted: false,
|
|
$isExpired: false,
|
|
$groupKey: '',
|
|
$groupRef: null,
|
|
//
|
|
...json
|
|
};
|
|
state.cachedFavorites.set(ref.id, ref);
|
|
state.cachedFavoritesByObjectId.set(ref.favoriteId, ref);
|
|
if (
|
|
ref.type === 'friend' &&
|
|
(generalSettingsStore.localFavoriteFriendsGroups.length === 0 ||
|
|
generalSettingsStore.localFavoriteFriendsGroups.includes(
|
|
ref.groupKey
|
|
))
|
|
) {
|
|
friendStore.localFavoriteFriends.add(ref.favoriteId);
|
|
friendStore.updateSidebarFriendsList();
|
|
}
|
|
} else {
|
|
Object.assign(ref, json);
|
|
ref.$isExpired = false;
|
|
}
|
|
ref.$groupKey = `${ref.type}:${String(ref.tags[0])}`;
|
|
|
|
if (ref.$isDeleted === false && ref.$groupRef === null) {
|
|
const group = state.cachedFavoriteGroupsByTypeName.get(
|
|
ref.$groupKey
|
|
);
|
|
if (typeof group !== 'undefined') {
|
|
ref.$groupRef = group;
|
|
++group.count;
|
|
}
|
|
}
|
|
return ref;
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
function deleteExpiredFavorites() {
|
|
for (const ref of state.cachedFavorites.values()) {
|
|
if (ref.$isDeleted || ref.$isExpired === false) {
|
|
continue;
|
|
}
|
|
ref.$isDeleted = true;
|
|
handleFavoriteAtDelete({
|
|
ref,
|
|
params: {
|
|
favoriteId: ref.id
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param tag
|
|
*/
|
|
async function refreshFavoriteAvatars(tag) {
|
|
const n = Math.floor(Math.random() * (50 + 1)) + 50;
|
|
const params = {
|
|
n,
|
|
offset: 0,
|
|
tag
|
|
};
|
|
const args = await favoriteRequest.getFavoriteAvatars(params);
|
|
handleFavoriteAvatarList(args);
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
function refreshFavoriteItems() {
|
|
const types = {
|
|
world: [0, favoriteRequest.getFavoriteWorlds],
|
|
avatar: [0, favoriteRequest.getFavoriteAvatars]
|
|
};
|
|
const tags = [];
|
|
for (const ref of state.cachedFavorites.values()) {
|
|
if (ref.$isDeleted) {
|
|
continue;
|
|
}
|
|
const type = types[ref.type];
|
|
if (typeof type === 'undefined') {
|
|
continue;
|
|
}
|
|
if (ref.type === 'avatar' && !tags.includes(ref.tags[0])) {
|
|
tags.push(ref.tags[0]);
|
|
}
|
|
++type[0];
|
|
}
|
|
for (const type in types) {
|
|
const [N, fn] = types[type];
|
|
if (N > 0) {
|
|
if (type === 'avatar') {
|
|
for (const tag of tags) {
|
|
const n = Math.floor(Math.random() * (50 + 1)) + 50;
|
|
processBulk({
|
|
fn,
|
|
N,
|
|
handle: (args) => handleFavoriteAvatarList(args),
|
|
params: {
|
|
n,
|
|
offset: 0,
|
|
tag
|
|
}
|
|
});
|
|
}
|
|
} else {
|
|
const n = Math.floor(Math.random() * (36 + 1)) + 64;
|
|
processBulk({
|
|
fn,
|
|
N,
|
|
handle: (args) => handleFavoriteWorldList(args),
|
|
params: {
|
|
n,
|
|
offset: 0
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* aka: `$app.methods.bulkCopyFavoriteSelection`
|
|
* @param {'friend'|'world'|'avatar'} type
|
|
*/
|
|
function bulkCopyFavoriteSelection(type) {
|
|
let idList = '';
|
|
switch (type) {
|
|
case 'friend':
|
|
for (const ctx of state.favoriteFriends) {
|
|
if (ctx.$selected) {
|
|
idList += `${ctx.id}\n`;
|
|
}
|
|
}
|
|
state.friendImportDialogInput = idList;
|
|
showFriendImportDialog();
|
|
break;
|
|
|
|
case 'world':
|
|
for (const ctx of state.favoriteWorlds) {
|
|
if (ctx.$selected) {
|
|
idList += `${ctx.id}\n`;
|
|
}
|
|
}
|
|
state.worldImportDialogInput = idList;
|
|
showWorldImportDialog();
|
|
break;
|
|
|
|
case 'avatar':
|
|
for (const ctx of state.favoriteAvatars) {
|
|
if (ctx.$selected) {
|
|
idList += `${ctx.id}\n`;
|
|
}
|
|
}
|
|
state.avatarImportDialogInput = idList;
|
|
showAvatarImportDialog();
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
console.log('Favorite selection\n', idList);
|
|
}
|
|
|
|
/**
|
|
* aka: `$app.methods.clearBulkFavoriteSelection`
|
|
*/
|
|
function clearBulkFavoriteSelection() {
|
|
let ctx;
|
|
for (ctx of state.favoriteFriends) {
|
|
ctx.$selected = false;
|
|
}
|
|
for (ctx of state.favoriteWorlds) {
|
|
ctx.$selected = false;
|
|
}
|
|
for (ctx of state.favoriteAvatars) {
|
|
ctx.$selected = false;
|
|
}
|
|
}
|
|
|
|
function showWorldImportDialog() {
|
|
state.worldImportDialogVisible = true;
|
|
}
|
|
|
|
function showAvatarImportDialog() {
|
|
state.avatarImportDialogVisible = true;
|
|
}
|
|
|
|
function showFriendImportDialog() {
|
|
state.friendImportDialogVisible = true;
|
|
}
|
|
|
|
/**
|
|
* aka: `$app.methods.getLocalWorldFavoriteGroupLength`
|
|
* @param {string} group
|
|
* @returns {*|number}
|
|
*/
|
|
function getLocalWorldFavoriteGroupLength(group) {
|
|
const favoriteGroup = state.localWorldFavorites[group];
|
|
if (!favoriteGroup) {
|
|
return 0;
|
|
}
|
|
return favoriteGroup.length;
|
|
}
|
|
|
|
/**
|
|
* aka: `$app.methods.addLocalWorldFavorite`
|
|
* @param {string} worldId
|
|
* @param {string} group
|
|
*/
|
|
function addLocalWorldFavorite(worldId, group) {
|
|
if (hasLocalWorldFavorite(worldId, group)) {
|
|
return;
|
|
}
|
|
const ref = worldStore.cachedWorlds.get(worldId);
|
|
if (typeof ref === 'undefined') {
|
|
return;
|
|
}
|
|
if (!state.localWorldFavoritesList.includes(worldId)) {
|
|
state.localWorldFavoritesList.push(worldId);
|
|
}
|
|
if (!state.localWorldFavorites[group]) {
|
|
state.localWorldFavorites[group] = [];
|
|
}
|
|
if (!state.localWorldFavoriteGroups.includes(group)) {
|
|
state.localWorldFavoriteGroups.push(group);
|
|
}
|
|
state.localWorldFavorites[group].unshift(ref);
|
|
database.addWorldToCache(ref);
|
|
database.addWorldToFavorites(worldId, group);
|
|
if (
|
|
state.favoriteDialog.visible &&
|
|
state.favoriteDialog.objectId === worldId
|
|
) {
|
|
updateFavoriteDialog(worldId);
|
|
}
|
|
if (
|
|
worldStore.worldDialog.visible &&
|
|
worldStore.worldDialog.id === worldId
|
|
) {
|
|
worldStore.worldDialog.isFavorite = true;
|
|
}
|
|
|
|
// update UI
|
|
sortLocalWorldFavorites();
|
|
}
|
|
|
|
/**
|
|
* aka: `$app.methods.hasLocalWorldFavorite`
|
|
* @param {string} worldId
|
|
* @param {string} group
|
|
* @returns {boolean}
|
|
*/
|
|
function hasLocalWorldFavorite(worldId, group) {
|
|
const favoriteGroup = state.localWorldFavorites[group];
|
|
if (!favoriteGroup) {
|
|
return false;
|
|
}
|
|
for (let i = 0; i < favoriteGroup.length; ++i) {
|
|
if (favoriteGroup[i].id === worldId) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* aka: `$app.methods.addLocalAvatarFavorite`
|
|
* @param {string} avatarId
|
|
* @param {string} group
|
|
*/
|
|
function addLocalAvatarFavorite(avatarId, group) {
|
|
if (hasLocalAvatarFavorite(avatarId, group)) {
|
|
return;
|
|
}
|
|
const ref = avatarStore.cachedAvatars.get(avatarId);
|
|
if (typeof ref === 'undefined') {
|
|
return;
|
|
}
|
|
if (!state.localAvatarFavoritesList.includes(avatarId)) {
|
|
state.localAvatarFavoritesList.push(avatarId);
|
|
}
|
|
if (!state.localAvatarFavorites[group]) {
|
|
state.localAvatarFavorites[group] = [];
|
|
}
|
|
if (!state.localAvatarFavoriteGroups.includes(group)) {
|
|
state.localAvatarFavoriteGroups.push(group);
|
|
}
|
|
state.localAvatarFavorites[group].unshift(ref);
|
|
database.addAvatarToCache(ref);
|
|
database.addAvatarToFavorites(avatarId, group);
|
|
if (
|
|
state.favoriteDialog.visible &&
|
|
state.favoriteDialog.objectId === avatarId
|
|
) {
|
|
updateFavoriteDialog(avatarId);
|
|
}
|
|
if (
|
|
avatarStore.avatarDialog.visible &&
|
|
avatarStore.avatarDialog.id === avatarId
|
|
) {
|
|
avatarStore.avatarDialog.isFavorite = true;
|
|
}
|
|
|
|
// update UI
|
|
sortLocalAvatarFavorites();
|
|
}
|
|
|
|
/**
|
|
* aka: `$app.methods.hasLocalAvatarFavorite`
|
|
* @param {string} avatarId
|
|
* @param {string} group
|
|
* @returns {boolean}
|
|
*/
|
|
function hasLocalAvatarFavorite(avatarId, group) {
|
|
const favoriteGroup = state.localAvatarFavorites[group];
|
|
if (!favoriteGroup) {
|
|
return false;
|
|
}
|
|
for (let i = 0; i < favoriteGroup.length; ++i) {
|
|
if (favoriteGroup[i].id === avatarId) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* aka: `$app.methods.getLocalAvatarFavoriteGroupLength`
|
|
* @param {string} group
|
|
* @returns {*|number}
|
|
*/
|
|
function getLocalAvatarFavoriteGroupLength(group) {
|
|
const favoriteGroup = state.localAvatarFavorites[group];
|
|
if (!favoriteGroup) {
|
|
return 0;
|
|
}
|
|
return favoriteGroup.length;
|
|
}
|
|
|
|
function updateFavoriteDialog(objectId) {
|
|
const D = state.favoriteDialog;
|
|
if (!D.visible || D.objectId !== objectId) {
|
|
return;
|
|
}
|
|
D.currentGroup = {};
|
|
const favorite = state.favoriteObjects.get(objectId);
|
|
if (favorite) {
|
|
let group;
|
|
for (group of state.favoriteWorldGroups) {
|
|
if (favorite.groupKey === group.key) {
|
|
D.currentGroup = group;
|
|
return;
|
|
}
|
|
}
|
|
for (group of state.favoriteAvatarGroups) {
|
|
if (favorite.groupKey === group.key) {
|
|
D.currentGroup = group;
|
|
return;
|
|
}
|
|
}
|
|
for (group of state.favoriteFriendGroups) {
|
|
if (favorite.groupKey === group.key) {
|
|
D.currentGroup = group;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* aka: `$app.methods.deleteLocalAvatarFavoriteGroup`
|
|
* @param {string} group
|
|
*/
|
|
function deleteLocalAvatarFavoriteGroup(group) {
|
|
let i;
|
|
// remove from cache if no longer in favorites
|
|
const avatarIdRemoveList = new Set();
|
|
const favoriteGroup = state.localAvatarFavorites[group];
|
|
for (i = 0; i < favoriteGroup.length; ++i) {
|
|
avatarIdRemoveList.add(favoriteGroup[i].id);
|
|
}
|
|
|
|
removeFromArray(state.localAvatarFavoriteGroups, group);
|
|
delete state.localAvatarFavorites[group];
|
|
database.deleteAvatarFavoriteGroup(group);
|
|
|
|
for (i = 0; i < state.localAvatarFavoriteGroups.length; ++i) {
|
|
const groupName = state.localAvatarFavoriteGroups[i];
|
|
if (!state.localAvatarFavorites[groupName]) {
|
|
continue;
|
|
}
|
|
for (
|
|
let j = 0;
|
|
j < state.localAvatarFavorites[groupName].length;
|
|
++j
|
|
) {
|
|
const avatarId = state.localAvatarFavorites[groupName][j].id;
|
|
if (avatarIdRemoveList.has(avatarId)) {
|
|
avatarIdRemoveList.delete(avatarId);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
avatarIdRemoveList.forEach((id) => {
|
|
// remove from cache if no longer in favorites
|
|
let avatarInFavorites = false;
|
|
loop: for (
|
|
let i = 0;
|
|
i < state.localAvatarFavoriteGroups.length;
|
|
++i
|
|
) {
|
|
const groupName = state.localAvatarFavoriteGroups[i];
|
|
if (
|
|
!state.localAvatarFavorites[groupName] ||
|
|
group === groupName
|
|
) {
|
|
continue loop;
|
|
}
|
|
for (
|
|
let j = 0;
|
|
j < state.localAvatarFavorites[groupName].length;
|
|
++j
|
|
) {
|
|
const avatarId =
|
|
state.localAvatarFavorites[groupName][j].id;
|
|
if (id === avatarId) {
|
|
avatarInFavorites = true;
|
|
break loop;
|
|
}
|
|
}
|
|
}
|
|
if (!avatarInFavorites) {
|
|
removeFromArray(state.localAvatarFavoritesList, id);
|
|
if (!avatarStore.avatarHistory.has(id)) {
|
|
database.removeAvatarFromCache(id);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* aka: `$app.methods.sortLocalAvatarFavorites`
|
|
*/
|
|
function sortLocalAvatarFavorites() {
|
|
state.localAvatarFavoriteGroups.sort();
|
|
if (!appearanceSettingsStore.sortFavorites) {
|
|
for (let i = 0; i < state.localAvatarFavoriteGroups.length; ++i) {
|
|
const group = state.localAvatarFavoriteGroups[i];
|
|
if (state.localAvatarFavorites[group]) {
|
|
state.localAvatarFavorites[group].sort(compareByName);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* aka: `$app.methods.renameLocalAvatarFavoriteGroup`
|
|
* @param {string} newName
|
|
* @param {string} group
|
|
*/
|
|
function renameLocalAvatarFavoriteGroup(newName, group) {
|
|
if (state.localAvatarFavoriteGroups.includes(newName)) {
|
|
$app.$message({
|
|
message: t('prompt.local_favorite_group_rename.message.error', {
|
|
name: newName
|
|
}),
|
|
type: 'error'
|
|
});
|
|
return;
|
|
}
|
|
state.localAvatarFavoriteGroups.push(newName);
|
|
state.localAvatarFavorites[newName] = state.localAvatarFavorites[group];
|
|
|
|
removeFromArray(state.localAvatarFavoriteGroups, group);
|
|
delete state.localAvatarFavorites[group];
|
|
database.renameAvatarFavoriteGroup(newName, group);
|
|
sortLocalAvatarFavorites();
|
|
}
|
|
|
|
/**
|
|
* aka: `$app.methods.newLocalAvatarFavoriteGroup`
|
|
* @param {string} group
|
|
*/
|
|
function newLocalAvatarFavoriteGroup(group) {
|
|
if (state.localAvatarFavoriteGroups.includes(group)) {
|
|
$app.$message({
|
|
message: t('prompt.new_local_favorite_group.message.error', {
|
|
name: group
|
|
}),
|
|
type: 'error'
|
|
});
|
|
return;
|
|
}
|
|
if (!state.localAvatarFavorites[group]) {
|
|
state.localAvatarFavorites[group] = [];
|
|
}
|
|
if (!state.localAvatarFavoriteGroups.includes(group)) {
|
|
state.localAvatarFavoriteGroups.push(group);
|
|
}
|
|
sortLocalAvatarFavorites();
|
|
}
|
|
|
|
/**
|
|
* aka: `$app.methods.getLocalAvatarFavorites`
|
|
* @returns {Promise<void>}
|
|
*/
|
|
async function getLocalAvatarFavorites() {
|
|
let ref;
|
|
let i;
|
|
state.localAvatarFavoriteGroups = [];
|
|
state.localAvatarFavoritesList = [];
|
|
state.localAvatarFavorites = {};
|
|
const avatarCache = await database.getAvatarCache();
|
|
for (i = 0; i < avatarCache.length; ++i) {
|
|
ref = avatarCache[i];
|
|
if (!avatarStore.cachedAvatars.has(ref.id)) {
|
|
avatarStore.applyAvatar(ref);
|
|
}
|
|
}
|
|
const favorites = await database.getAvatarFavorites();
|
|
for (i = 0; i < favorites.length; ++i) {
|
|
const favorite = favorites[i];
|
|
if (!state.localAvatarFavoritesList.includes(favorite.avatarId)) {
|
|
state.localAvatarFavoritesList.push(favorite.avatarId);
|
|
}
|
|
if (!state.localAvatarFavorites[favorite.groupName]) {
|
|
state.localAvatarFavorites[favorite.groupName] = [];
|
|
}
|
|
if (!state.localAvatarFavoriteGroups.includes(favorite.groupName)) {
|
|
state.localAvatarFavoriteGroups.push(favorite.groupName);
|
|
}
|
|
ref = avatarStore.cachedAvatars.get(favorite.avatarId);
|
|
if (typeof ref === 'undefined') {
|
|
ref = {
|
|
id: favorite.avatarId
|
|
};
|
|
}
|
|
state.localAvatarFavorites[favorite.groupName].unshift(ref);
|
|
}
|
|
if (state.localAvatarFavoriteGroups.length === 0) {
|
|
// default group
|
|
state.localAvatarFavorites.Favorites = [];
|
|
state.localAvatarFavoriteGroups.push('Favorites');
|
|
}
|
|
sortLocalAvatarFavorites();
|
|
}
|
|
|
|
/**
|
|
* aka: `$app.methods.removeLocalAvatarFavorite`
|
|
* @param {string} avatarId
|
|
* @param {string} group
|
|
*/
|
|
function removeLocalAvatarFavorite(avatarId, group) {
|
|
let i;
|
|
const favoriteGroup = state.localAvatarFavorites[group];
|
|
for (i = 0; i < favoriteGroup.length; ++i) {
|
|
if (favoriteGroup[i].id === avatarId) {
|
|
favoriteGroup.splice(i, 1);
|
|
}
|
|
}
|
|
|
|
// remove from cache if no longer in favorites
|
|
let avatarInFavorites = false;
|
|
for (i = 0; i < state.localAvatarFavoriteGroups.length; ++i) {
|
|
const groupName = state.localAvatarFavoriteGroups[i];
|
|
if (!state.localAvatarFavorites[groupName] || group === groupName) {
|
|
continue;
|
|
}
|
|
for (
|
|
let j = 0;
|
|
j < state.localAvatarFavorites[groupName].length;
|
|
++j
|
|
) {
|
|
const id = state.localAvatarFavorites[groupName][j].id;
|
|
if (id === avatarId) {
|
|
avatarInFavorites = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (!avatarInFavorites) {
|
|
removeFromArray(state.localAvatarFavoritesList, avatarId);
|
|
if (!avatarStore.avatarHistory.has(avatarId)) {
|
|
database.removeAvatarFromCache(avatarId);
|
|
}
|
|
}
|
|
database.removeAvatarFromFavorites(avatarId, group);
|
|
if (
|
|
state.favoriteDialog.visible &&
|
|
state.favoriteDialog.objectId === avatarId
|
|
) {
|
|
updateFavoriteDialog(avatarId);
|
|
}
|
|
if (
|
|
avatarStore.avatarDialog.visible &&
|
|
avatarStore.avatarDialog.id === avatarId
|
|
) {
|
|
avatarStore.avatarDialog.isFavorite =
|
|
state.cachedFavoritesByObjectId.has(avatarId);
|
|
}
|
|
|
|
// update UI
|
|
sortLocalAvatarFavorites();
|
|
}
|
|
|
|
/**
|
|
* aka: `$app.methods.deleteLocalWorldFavoriteGroup`
|
|
* @param {string} group
|
|
*/
|
|
function deleteLocalWorldFavoriteGroup(group) {
|
|
let i;
|
|
// remove from cache if no longer in favorites
|
|
const worldIdRemoveList = new Set();
|
|
const favoriteGroup = state.localWorldFavorites[group];
|
|
for (i = 0; i < favoriteGroup.length; ++i) {
|
|
worldIdRemoveList.add(favoriteGroup[i].id);
|
|
}
|
|
|
|
removeFromArray(state.localWorldFavoriteGroups, group);
|
|
delete state.localWorldFavorites[group];
|
|
database.deleteWorldFavoriteGroup(group);
|
|
|
|
for (i = 0; i < state.localWorldFavoriteGroups.length; ++i) {
|
|
const groupName = state.localWorldFavoriteGroups[i];
|
|
if (!state.localWorldFavorites[groupName]) {
|
|
continue;
|
|
}
|
|
for (
|
|
let j = 0;
|
|
j < state.localWorldFavorites[groupName].length;
|
|
++j
|
|
) {
|
|
const worldId = state.localWorldFavorites[groupName][j].id;
|
|
if (worldIdRemoveList.has(worldId)) {
|
|
worldIdRemoveList.delete(worldId);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
worldIdRemoveList.forEach((id) => {
|
|
removeFromArray(state.localWorldFavoritesList, id);
|
|
database.removeWorldFromCache(id);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* aka: `$app.methods.sortLocalWorldFavorites`
|
|
*/
|
|
function sortLocalWorldFavorites() {
|
|
state.localWorldFavoriteGroups.sort();
|
|
if (!appearanceSettingsStore.sortFavorites) {
|
|
for (let i = 0; i < state.localWorldFavoriteGroups.length; ++i) {
|
|
const group = state.localWorldFavoriteGroups[i];
|
|
if (state.localWorldFavorites[group]) {
|
|
state.localWorldFavorites[group].sort(compareByName);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* aka: `$app.methods.renameLocalWorldFavoriteGroup`
|
|
* @param {string} newName
|
|
* @param {string} group
|
|
*/
|
|
function renameLocalWorldFavoriteGroup(newName, group) {
|
|
if (state.localWorldFavoriteGroups.includes(newName)) {
|
|
$app.$message({
|
|
message: t('prompt.local_favorite_group_rename.message.error', {
|
|
name: newName
|
|
}),
|
|
type: 'error'
|
|
});
|
|
return;
|
|
}
|
|
state.localWorldFavoriteGroups.push(newName);
|
|
state.localWorldFavorites[newName] = state.localWorldFavorites[group];
|
|
|
|
removeFromArray(state.localWorldFavoriteGroups, group);
|
|
delete state.localWorldFavorites[group];
|
|
database.renameWorldFavoriteGroup(newName, group);
|
|
sortLocalWorldFavorites();
|
|
}
|
|
|
|
/**
|
|
* aka: `$app.methods.removeLocalWorldFavorite`
|
|
* @param {string} worldId
|
|
* @param {string} group
|
|
*/
|
|
function removeLocalWorldFavorite(worldId, group) {
|
|
let i;
|
|
const favoriteGroup = state.localWorldFavorites[group];
|
|
for (i = 0; i < favoriteGroup.length; ++i) {
|
|
if (favoriteGroup[i].id === worldId) {
|
|
favoriteGroup.splice(i, 1);
|
|
}
|
|
}
|
|
|
|
// remove from cache if no longer in favorites
|
|
let worldInFavorites = false;
|
|
for (i = 0; i < state.localWorldFavoriteGroups.length; ++i) {
|
|
const groupName = state.localWorldFavoriteGroups[i];
|
|
if (!state.localWorldFavorites[groupName] || group === groupName) {
|
|
continue;
|
|
}
|
|
for (
|
|
let j = 0;
|
|
j < state.localWorldFavorites[groupName].length;
|
|
++j
|
|
) {
|
|
const id = state.localWorldFavorites[groupName][j].id;
|
|
if (id === worldId) {
|
|
worldInFavorites = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (!worldInFavorites) {
|
|
removeFromArray(state.localWorldFavoritesList, worldId);
|
|
database.removeWorldFromCache(worldId);
|
|
}
|
|
database.removeWorldFromFavorites(worldId, group);
|
|
if (
|
|
state.favoriteDialog.visible &&
|
|
state.favoriteDialog.objectId === worldId
|
|
) {
|
|
updateFavoriteDialog(worldId);
|
|
}
|
|
if (
|
|
worldStore.worldDialog.visible &&
|
|
worldStore.worldDialog.id === worldId
|
|
) {
|
|
worldStore.worldDialog.isFavorite =
|
|
state.cachedFavoritesByObjectId.has(worldId);
|
|
}
|
|
|
|
// update UI
|
|
sortLocalWorldFavorites();
|
|
}
|
|
|
|
/**
|
|
* aka: `$app.methods.getLocalWorldFavorites`
|
|
* @returns {Promise<void>}
|
|
*/
|
|
async function getLocalWorldFavorites() {
|
|
state.localWorldFavoriteGroups = [];
|
|
state.localWorldFavoritesList = [];
|
|
state.localWorldFavorites = {};
|
|
const worldCache = await database.getWorldCache();
|
|
for (let i = 0; i < worldCache.length; ++i) {
|
|
const ref = worldCache[i];
|
|
if (!worldStore.cachedWorlds.has(ref.id)) {
|
|
worldStore.applyWorld(ref);
|
|
}
|
|
}
|
|
const favorites = await database.getWorldFavorites();
|
|
for (let i = 0; i < favorites.length; ++i) {
|
|
const favorite = favorites[i];
|
|
if (!state.localWorldFavoritesList.includes(favorite.worldId)) {
|
|
state.localWorldFavoritesList.push(favorite.worldId);
|
|
}
|
|
if (!state.localWorldFavorites[favorite.groupName]) {
|
|
state.localWorldFavorites[favorite.groupName] = [];
|
|
}
|
|
if (!state.localWorldFavoriteGroups.includes(favorite.groupName)) {
|
|
state.localWorldFavoriteGroups.push(favorite.groupName);
|
|
}
|
|
let ref = worldStore.cachedWorlds.get(favorite.worldId);
|
|
if (typeof ref === 'undefined') {
|
|
ref = {
|
|
id: favorite.worldId
|
|
};
|
|
}
|
|
state.localWorldFavorites[favorite.groupName].unshift(ref);
|
|
}
|
|
if (state.localWorldFavoriteGroups.length === 0) {
|
|
// default group
|
|
state.localWorldFavorites.Favorites = [];
|
|
state.localWorldFavoriteGroups.push('Favorites');
|
|
}
|
|
sortLocalWorldFavorites();
|
|
}
|
|
|
|
/**
|
|
* aka: `$app.methods.newLocalWorldFavoriteGroup`
|
|
* @param {string} group
|
|
*/
|
|
function newLocalWorldFavoriteGroup(group) {
|
|
if (state.localWorldFavoriteGroups.includes(group)) {
|
|
$app.$message({
|
|
message: t('prompt.new_local_favorite_group.message.error', {
|
|
name: group
|
|
}),
|
|
type: 'error'
|
|
});
|
|
return;
|
|
}
|
|
if (!state.localWorldFavorites[group]) {
|
|
state.localWorldFavorites[group] = [];
|
|
}
|
|
if (!state.localWorldFavoriteGroups.includes(group)) {
|
|
state.localWorldFavoriteGroups.push(group);
|
|
}
|
|
sortLocalWorldFavorites();
|
|
}
|
|
|
|
/**
|
|
* aka: `$app.methods.deleteFavoriteNoConfirm`
|
|
* @param {string} objectId
|
|
*/
|
|
function deleteFavoriteNoConfirm(objectId) {
|
|
if (!objectId) {
|
|
return;
|
|
}
|
|
state.favoriteDialog.visible = true;
|
|
favoriteRequest
|
|
.deleteFavorite({
|
|
objectId
|
|
})
|
|
.then(() => {
|
|
state.favoriteDialog.visible = false;
|
|
})
|
|
.finally(() => {
|
|
state.favoriteDialog.loading = false;
|
|
});
|
|
}
|
|
|
|
function showFavoriteDialog(type, objectId) {
|
|
const D = state.favoriteDialog;
|
|
D.type = type;
|
|
D.objectId = objectId;
|
|
D.visible = true;
|
|
updateFavoriteDialog(objectId);
|
|
}
|
|
|
|
async function saveSortFavoritesOption() {
|
|
getLocalWorldFavorites();
|
|
appearanceSettingsStore.setSortFavorites();
|
|
}
|
|
|
|
async function initFavorites() {
|
|
refreshFavorites();
|
|
getLocalWorldFavorites();
|
|
getLocalAvatarFavorites();
|
|
}
|
|
|
|
return {
|
|
state,
|
|
|
|
favoriteFriends,
|
|
favoriteWorlds,
|
|
favoriteAvatars,
|
|
isFavoriteGroupLoading,
|
|
favoriteFriendGroups,
|
|
cachedFavoriteGroups,
|
|
cachedFavoriteGroupsByTypeName,
|
|
favoriteLimits,
|
|
cachedFavorites,
|
|
favoriteWorldGroups,
|
|
favoriteAvatarGroups,
|
|
isFavoriteLoading,
|
|
friendImportDialogInput,
|
|
worldImportDialogInput,
|
|
avatarImportDialogInput,
|
|
worldImportDialogVisible,
|
|
avatarImportDialogVisible,
|
|
friendImportDialogVisible,
|
|
localWorldFavorites,
|
|
localAvatarFavorites,
|
|
localAvatarFavoritesList,
|
|
localAvatarFavoriteGroups,
|
|
favoriteDialog,
|
|
favoriteObjects,
|
|
localWorldFavoritesList,
|
|
favoriteFriends_,
|
|
favoriteFriendsSorted,
|
|
favoriteWorlds_,
|
|
favoriteWorldsSorted,
|
|
favoriteAvatars_,
|
|
favoriteAvatarsSorted,
|
|
sortFavoriteFriends,
|
|
sortFavoriteWorlds,
|
|
sortFavoriteAvatars,
|
|
cachedFavoritesByObjectId,
|
|
localWorldFavoriteGroups,
|
|
groupedByGroupKeyFavoriteFriends,
|
|
|
|
initFavorites,
|
|
applyFavorite,
|
|
refreshFavoriteGroups,
|
|
refreshFavorites,
|
|
applyFavoriteGroup,
|
|
applyFavoriteCached,
|
|
refreshFavoriteAvatars,
|
|
clearBulkFavoriteSelection,
|
|
showWorldImportDialog,
|
|
showAvatarImportDialog,
|
|
showFriendImportDialog,
|
|
bulkCopyFavoriteSelection,
|
|
getLocalWorldFavoriteGroupLength,
|
|
addLocalWorldFavorite,
|
|
hasLocalWorldFavorite,
|
|
hasLocalAvatarFavorite,
|
|
addLocalAvatarFavorite,
|
|
getLocalAvatarFavoriteGroupLength,
|
|
updateFavoriteDialog,
|
|
deleteLocalAvatarFavoriteGroup,
|
|
renameLocalAvatarFavoriteGroup,
|
|
newLocalAvatarFavoriteGroup,
|
|
getLocalAvatarFavorites,
|
|
removeLocalAvatarFavorite,
|
|
deleteLocalWorldFavoriteGroup,
|
|
sortLocalWorldFavorites,
|
|
renameLocalWorldFavoriteGroup,
|
|
removeLocalWorldFavorite,
|
|
getLocalWorldFavorites,
|
|
newLocalWorldFavoriteGroup,
|
|
deleteFavoriteNoConfirm,
|
|
showFavoriteDialog,
|
|
saveSortFavoritesOption,
|
|
handleFavoriteWorldList,
|
|
handleFavoriteGroupClear,
|
|
handleFavoriteGroup,
|
|
handleFavoriteDelete,
|
|
handleFavoriteAdd
|
|
};
|
|
});
|