refactor queryRequest

This commit is contained in:
pa
2026-03-09 21:28:45 +09:00
parent c1a35223d4
commit 58b9bdc1c5
60 changed files with 1134 additions and 883 deletions
+1 -34
View File
@@ -2,7 +2,6 @@ import { beforeEach, describe, expect, test, vi } from 'vitest';
const mockRequest = vi.fn(); const mockRequest = vi.fn();
const mockPatchAndRefetchActiveQuery = vi.fn(() => Promise.resolve()); const mockPatchAndRefetchActiveQuery = vi.fn(() => Promise.resolve());
const mockFetchWithEntityPolicy = vi.fn();
const mockApplyCurrentUser = vi.fn((json) => ({ id: json.id || 'usr_me', ...json })); const mockApplyCurrentUser = vi.fn((json) => ({ id: json.id || 'usr_me', ...json }));
const mockApplyUser = vi.fn((json) => ({ ...json })); const mockApplyUser = vi.fn((json) => ({ ...json }));
@@ -24,22 +23,12 @@ vi.mock('../../stores', () => ({
})); }));
vi.mock('../../queries', () => ({ vi.mock('../../queries', () => ({
entityQueryPolicies: {
user: { staleTime: 20000, gcTime: 90000, retry: 1, refetchOnWindowFocus: false },
avatar: { staleTime: 60000, gcTime: 300000, retry: 1, refetchOnWindowFocus: false },
world: { staleTime: 60000, gcTime: 300000, retry: 1, refetchOnWindowFocus: false },
worldCollection: { staleTime: 60000, gcTime: 300000, retry: 1, refetchOnWindowFocus: false },
instance: { staleTime: 0, gcTime: 10000, retry: 0, refetchOnWindowFocus: false }
},
fetchWithEntityPolicy: (...args) => mockFetchWithEntityPolicy(...args),
patchAndRefetchActiveQuery: (...args) => patchAndRefetchActiveQuery: (...args) =>
mockPatchAndRefetchActiveQuery(...args), mockPatchAndRefetchActiveQuery(...args),
queryKeys: { queryKeys: {
user: (userId) => ['user', userId], user: (userId) => ['user', userId],
avatar: (avatarId) => ['avatar', avatarId], avatar: (avatarId) => ['avatar', avatarId],
world: (worldId) => ['world', worldId], world: (worldId) => ['world', worldId]
worldsByUser: (params) => ['worlds', 'user', params.userId, params],
instance: (worldId, instanceId) => ['instance', worldId, instanceId]
} }
})); }));
@@ -88,26 +77,4 @@ describe('entity mutation query sync', () => {
); );
}); });
test('getCachedWorlds uses policy wrapper for world list data', async () => {
mockFetchWithEntityPolicy.mockResolvedValue({
data: {
json: [{ id: 'wrld_1' }],
params: { userId: 'usr_me', n: 50, offset: 0 }
},
cache: true
});
const args = await worldRequest.getCachedWorlds({
userId: 'usr_me',
n: 50,
offset: 0,
sort: 'updated',
order: 'descending',
user: 'me',
releaseStatus: 'all'
});
expect(mockFetchWithEntityPolicy).toHaveBeenCalled();
expect(args.cache).toBe(true);
});
}); });
@@ -1,7 +1,6 @@
import { beforeEach, describe, expect, test, vi } from 'vitest'; import { beforeEach, describe, expect, test, vi } from 'vitest';
const mockRequest = vi.fn(); const mockRequest = vi.fn();
const mockFetchWithEntityPolicy = vi.fn();
const mockInvalidateQueries = vi.fn().mockResolvedValue(); const mockInvalidateQueries = vi.fn().mockResolvedValue();
const mockHandleFavoriteAdd = vi.fn(); const mockHandleFavoriteAdd = vi.fn();
const mockHandleFavoriteDelete = vi.fn(); const mockHandleFavoriteDelete = vi.fn();
@@ -24,24 +23,8 @@ vi.mock('../../stores', () => ({
})); }));
vi.mock('../../queries', () => ({ vi.mock('../../queries', () => ({
entityQueryPolicies: {
favoriteCollection: {
staleTime: 60000,
gcTime: 300000,
retry: 1,
refetchOnWindowFocus: false
}
},
fetchWithEntityPolicy: (...args) => mockFetchWithEntityPolicy(...args),
queryClient: { queryClient: {
invalidateQueries: (...args) => mockInvalidateQueries(...args) invalidateQueries: (...args) => mockInvalidateQueries(...args)
},
queryKeys: {
favoriteLimits: () => ['favorite', 'limits'],
favorites: (params) => ['favorite', 'items', params],
favoriteGroups: (params) => ['favorite', 'groups', params],
favoriteWorlds: (params) => ['favorite', 'worlds', params],
favoriteAvatars: (params) => ['favorite', 'avatars', params]
} }
})); }));
@@ -52,21 +35,6 @@ describe('favorite query sync', () => {
vi.clearAllMocks(); vi.clearAllMocks();
}); });
test('cached favorite reads go through fetchWithEntityPolicy', async () => {
mockFetchWithEntityPolicy.mockResolvedValue({
data: { json: [], params: { n: 300, offset: 0 } },
cache: true
});
const args = await favoriteRequest.getCachedFavorites({
n: 300,
offset: 0
});
expect(mockFetchWithEntityPolicy).toHaveBeenCalled();
expect(args.cache).toBe(true);
});
test('favorite mutations invalidate active favorite queries', async () => { test('favorite mutations invalidate active favorite queries', async () => {
mockRequest.mockResolvedValue({ ok: true }); mockRequest.mockResolvedValue({ ok: true });
-29
View File
@@ -1,7 +1,6 @@
import { beforeEach, describe, expect, test, vi } from 'vitest'; import { beforeEach, describe, expect, test, vi } from 'vitest';
const mockRequest = vi.fn(); const mockRequest = vi.fn();
const mockFetchWithEntityPolicy = vi.fn();
const mockInvalidateQueries = vi.fn().mockResolvedValue(); const mockInvalidateQueries = vi.fn().mockResolvedValue();
const mockApplyUser = vi.fn((json) => json); const mockApplyUser = vi.fn((json) => json);
@@ -16,20 +15,8 @@ vi.mock('../../stores/user', () => ({
})); }));
vi.mock('../../queries', () => ({ vi.mock('../../queries', () => ({
entityQueryPolicies: {
friendList: {
staleTime: 20000,
gcTime: 90000,
retry: 1,
refetchOnWindowFocus: false
}
},
fetchWithEntityPolicy: (...args) => mockFetchWithEntityPolicy(...args),
queryClient: { queryClient: {
invalidateQueries: (...args) => mockInvalidateQueries(...args) invalidateQueries: (...args) => mockInvalidateQueries(...args)
},
queryKeys: {
friends: (params) => ['friends', params]
} }
})); }));
@@ -40,22 +27,6 @@ describe('friend query sync', () => {
vi.clearAllMocks(); vi.clearAllMocks();
}); });
test('getCachedFriends uses query policy wrapper', async () => {
mockFetchWithEntityPolicy.mockResolvedValue({
data: {
json: [{ id: 'usr_1', displayName: 'A' }],
params: { n: 50, offset: 0 }
},
cache: true
});
const args = await friendRequest.getCachedFriends({ n: 50, offset: 0 });
expect(mockFetchWithEntityPolicy).toHaveBeenCalled();
expect(args.cache).toBe(true);
expect(args.json[0].id).toBe('usr_1');
});
test('friend mutations invalidate active friends queries', async () => { test('friend mutations invalidate active friends queries', async () => {
mockRequest.mockResolvedValue({ ok: true }); mockRequest.mockResolvedValue({ ok: true });
-48
View File
@@ -1,7 +1,6 @@
import { beforeEach, describe, expect, test, vi } from 'vitest'; import { beforeEach, describe, expect, test, vi } from 'vitest';
const mockRequest = vi.fn(); const mockRequest = vi.fn();
const mockFetchWithEntityPolicy = vi.fn();
const mockInvalidateQueries = vi.fn().mockResolvedValue(); const mockInvalidateQueries = vi.fn().mockResolvedValue();
const mockApplyGroup = vi.fn((json) => json); const mockApplyGroup = vi.fn((json) => json);
@@ -19,32 +18,8 @@ vi.mock('../../stores', () => ({
})); }));
vi.mock('../../queries', () => ({ vi.mock('../../queries', () => ({
entityQueryPolicies: {
group: {
staleTime: 60000,
gcTime: 300000,
retry: 1,
refetchOnWindowFocus: false
},
groupCollection: {
staleTime: 60000,
gcTime: 300000,
retry: 1,
refetchOnWindowFocus: false
}
},
fetchWithEntityPolicy: (...args) => mockFetchWithEntityPolicy(...args),
queryClient: { queryClient: {
invalidateQueries: (...args) => mockInvalidateQueries(...args) invalidateQueries: (...args) => mockInvalidateQueries(...args)
},
queryKeys: {
group: (groupId, includeRoles) => ['group', groupId, Boolean(includeRoles)],
groupPosts: (params) => ['group', params.groupId, 'posts', params],
groupMember: (params) => ['group', params.groupId, 'member', params.userId],
groupMembers: (params) => ['group', params.groupId, 'members', params],
groupGallery: (params) => ['group', params.groupId, 'gallery', params.galleryId, params],
groupCalendar: (groupId) => ['group', groupId, 'calendar'],
groupCalendarEvent: (params) => ['group', params.groupId, 'calendarEvent', params.eventId]
} }
})); }));
@@ -55,29 +30,6 @@ describe('group query sync', () => {
vi.clearAllMocks(); vi.clearAllMocks();
}); });
test('cached group resources use fetchWithEntityPolicy', async () => {
mockFetchWithEntityPolicy.mockResolvedValue({
data: { json: [], params: { groupId: 'grp_1', n: 100, offset: 0 } },
cache: true
});
const a = await groupRequest.getCachedGroupMembers({
groupId: 'grp_1',
n: 100,
offset: 0,
sort: 'joinedAt:desc'
});
const b = await groupRequest.getCachedGroupGallery({
groupId: 'grp_1',
galleryId: 'gal_1',
n: 100,
offset: 0
});
expect(mockFetchWithEntityPolicy).toHaveBeenCalledTimes(2);
expect(a.cache && b.cache).toBe(true);
});
test('group mutations invalidate scoped active group queries', async () => { test('group mutations invalidate scoped active group queries', async () => {
mockRequest.mockResolvedValue({ ok: true }); mockRequest.mockResolvedValue({ ok: true });
-42
View File
@@ -1,7 +1,6 @@
import { beforeEach, describe, expect, test, vi } from 'vitest'; import { beforeEach, describe, expect, test, vi } from 'vitest';
const mockRequest = vi.fn(); const mockRequest = vi.fn();
const mockFetchWithEntityPolicy = vi.fn();
const mockInvalidateQueries = vi.fn().mockResolvedValue(); const mockInvalidateQueries = vi.fn().mockResolvedValue();
const mockRemoveQueries = vi.fn(); const mockRemoveQueries = vi.fn();
@@ -16,27 +15,6 @@ vi.mock('../../stores', () => ({
})); }));
vi.mock('../../queries', () => ({ vi.mock('../../queries', () => ({
entityQueryPolicies: {
galleryCollection: {
staleTime: 60000,
gcTime: 300000,
retry: 1,
refetchOnWindowFocus: false
},
inventoryCollection: {
staleTime: 20000,
gcTime: 120000,
retry: 1,
refetchOnWindowFocus: false
},
fileObject: {
staleTime: 60000,
gcTime: 300000,
retry: 1,
refetchOnWindowFocus: false
}
},
fetchWithEntityPolicy: (...args) => mockFetchWithEntityPolicy(...args),
queryClient: { queryClient: {
invalidateQueries: (...args) => mockInvalidateQueries(...args), invalidateQueries: (...args) => mockInvalidateQueries(...args),
removeQueries: (...args) => mockRemoveQueries(...args) removeQueries: (...args) => mockRemoveQueries(...args)
@@ -51,7 +29,6 @@ vi.mock('../../queries', () => ({
} }
})); }));
import inventoryRequest from '../inventory';
import miscRequest from '../misc'; import miscRequest from '../misc';
import vrcPlusIconRequest from '../vrcPlusIcon'; import vrcPlusIconRequest from '../vrcPlusIcon';
import vrcPlusImageRequest from '../vrcPlusImage'; import vrcPlusImageRequest from '../vrcPlusImage';
@@ -61,25 +38,6 @@ describe('media and inventory query sync', () => {
vi.clearAllMocks(); vi.clearAllMocks();
}); });
test('cached media/inventory reads go through fetchWithEntityPolicy', async () => {
mockFetchWithEntityPolicy.mockResolvedValue({
data: { json: [], params: {} },
cache: true
});
const a = await vrcPlusIconRequest.getCachedFileList({ tag: 'icon', n: 100 });
const b = await vrcPlusImageRequest.getCachedPrints({ n: 100 });
const c = await inventoryRequest.getCachedInventoryItems({
n: 100,
offset: 0,
order: 'newest'
});
const d = await miscRequest.getCachedFile({ fileId: 'file_1' });
expect(mockFetchWithEntityPolicy).toHaveBeenCalledTimes(4);
expect(a.cache && b.cache && c.cache && d.cache).toBe(true);
});
test('media mutations invalidate gallery queries and file delete removes file query', async () => { test('media mutations invalidate gallery queries and file delete removes file query', async () => {
mockRequest.mockResolvedValue({ ok: true }); mockRequest.mockResolvedValue({ ok: true });
+174
View File
@@ -0,0 +1,174 @@
import { beforeEach, describe, expect, test, vi } from 'vitest';
const mockFetchWithEntityPolicy = vi.fn();
const mockGetUser = vi.fn();
const mockGetWorlds = vi.fn();
const mockGetGroupCalendar = vi.fn();
vi.mock('../../queries', () => ({
entityQueryPolicies: {
user: { staleTime: 20000, gcTime: 90000, retry: 1, refetchOnWindowFocus: false },
worldCollection: { staleTime: 60000, gcTime: 300000, retry: 1, refetchOnWindowFocus: false },
groupCollection: { staleTime: 60000, gcTime: 300000, retry: 1, refetchOnWindowFocus: false },
avatar: { staleTime: 60000, gcTime: 300000, retry: 1, refetchOnWindowFocus: false },
world: { staleTime: 60000, gcTime: 300000, retry: 1, refetchOnWindowFocus: false },
group: { staleTime: 60000, gcTime: 300000, retry: 1, refetchOnWindowFocus: false },
friendList: { staleTime: 20000, gcTime: 90000, retry: 1, refetchOnWindowFocus: false },
favoriteCollection: { staleTime: 60000, gcTime: 300000, retry: 1, refetchOnWindowFocus: false },
galleryCollection: { staleTime: 60000, gcTime: 300000, retry: 1, refetchOnWindowFocus: false },
inventoryCollection: { staleTime: 20000, gcTime: 120000, retry: 1, refetchOnWindowFocus: false },
fileObject: { staleTime: 60000, gcTime: 300000, retry: 1, refetchOnWindowFocus: false }
},
fetchWithEntityPolicy: (...args) => mockFetchWithEntityPolicy(...args),
queryKeys: {
user: (userId) => ['user', userId],
worldsByUser: (params) => ['worlds', 'user', params.userId, params],
groupCalendar: (groupId) => ['group', groupId, 'calendar'],
avatar: (avatarId) => ['avatar', avatarId],
world: (worldId) => ['world', worldId],
group: (groupId, includeRoles) => ['group', groupId, Boolean(includeRoles)],
groupPosts: (params) => ['group', params.groupId, 'posts', params],
groupMember: (params) => ['group', params.groupId, 'member', params.userId],
groupMembers: (params) => ['group', params.groupId, 'members', params],
groupGallery: (params) => ['group', params.groupId, 'gallery', params.galleryId, params],
groupCalendarEvent: (params) => ['group', params.groupId, 'calendarEvent', params.eventId],
friends: (params) => ['friends', params],
favoriteLimits: () => ['favorite', 'limits'],
favorites: (params) => ['favorite', 'items', params],
favoriteGroups: (params) => ['favorite', 'groups', params],
favoriteWorlds: (params) => ['favorite', 'worlds', params],
favoriteAvatars: (params) => ['favorite', 'avatars', params],
galleryFiles: (params) => ['gallery', 'files', params],
prints: (params) => ['gallery', 'prints', params],
print: (printId) => ['gallery', 'print', printId],
userInventoryItem: (params) => ['inventory', 'item', params.userId, params.inventoryId],
inventoryItems: (params) => ['inventory', 'items', params],
file: (fileId) => ['file', fileId]
}
}));
vi.mock('../user', () => ({
default: {
getUser: (...args) => mockGetUser(...args)
}
}));
vi.mock('../world', () => ({
default: {
getWorlds: (...args) => mockGetWorlds(...args),
getWorld: vi.fn()
}
}));
vi.mock('../group', () => ({
default: {
getGroupCalendar: (...args) => mockGetGroupCalendar(...args),
getGroup: vi.fn(),
getGroupPosts: vi.fn(),
getGroupMember: vi.fn(),
getGroupMembers: vi.fn(),
getGroupGallery: vi.fn(),
getGroupCalendarEvent: vi.fn()
}
}));
vi.mock('../avatar', () => ({ default: { getAvatar: vi.fn() } }));
vi.mock('../friend', () => ({ default: { getFriends: vi.fn() } }));
vi.mock('../favorite', () => ({
default: {
getFavoriteLimits: vi.fn(),
getFavorites: vi.fn(),
getFavoriteGroups: vi.fn(),
getFavoriteWorlds: vi.fn(),
getFavoriteAvatars: vi.fn()
}
}));
vi.mock('../vrcPlusIcon', () => ({ default: { getFileList: vi.fn() } }));
vi.mock('../vrcPlusImage', () => ({
default: { getPrints: vi.fn(), getPrint: vi.fn() }
}));
vi.mock('../inventory', () => ({
default: { getUserInventoryItem: vi.fn(), getInventoryItems: vi.fn() }
}));
vi.mock('../misc', () => ({ default: { getFile: vi.fn() } }));
import queryRequest from '../queryRequest';
describe('queryRequest', () => {
beforeEach(() => {
vi.clearAllMocks();
});
test('routes user fetch through policy wrapper and returns cache marker', async () => {
const data = { json: { id: 'usr_1' }, params: { userId: 'usr_1' } };
mockGetUser.mockResolvedValue(data);
mockFetchWithEntityPolicy.mockImplementation(async ({ queryFn }) => ({
data: await queryFn(),
cache: true
}));
const args = await queryRequest.fetch('user', { userId: 'usr_1' });
expect(mockFetchWithEntityPolicy).toHaveBeenCalledWith(
expect.objectContaining({
queryKey: ['user', 'usr_1']
})
);
expect(args.cache).toBe(true);
expect(args.json.id).toBe('usr_1');
});
test('supports worldsByUser option routing', async () => {
const params = {
userId: 'usr_me',
n: 50,
offset: 0,
sort: 'updated',
order: 'descending',
user: 'me',
releaseStatus: 'all',
option: 'featured'
};
mockGetWorlds.mockResolvedValue({ json: [], params });
mockFetchWithEntityPolicy.mockImplementation(async ({ queryFn }) => ({
data: await queryFn(),
cache: false
}));
await queryRequest.fetch('worldsByUser', params);
expect(mockGetWorlds).toHaveBeenCalledWith(params, 'featured');
expect(mockFetchWithEntityPolicy).toHaveBeenCalledWith(
expect.objectContaining({
queryKey: ['worlds', 'user', 'usr_me', params]
})
);
});
test('supports groupCalendar resource shape', async () => {
mockGetGroupCalendar.mockResolvedValue({
json: { results: [] },
params: { groupId: 'grp_1' }
});
mockFetchWithEntityPolicy.mockImplementation(async ({ queryFn }) => ({
data: await queryFn(),
cache: false
}));
await queryRequest.fetch('groupCalendar', { groupId: 'grp_1' });
expect(mockGetGroupCalendar).toHaveBeenCalledWith('grp_1');
expect(mockFetchWithEntityPolicy).toHaveBeenCalledWith(
expect.objectContaining({
queryKey: ['group', 'grp_1', 'calendar']
})
);
});
test('throws on unknown resource', async () => {
await expect(
// @ts-expect-error verifying runtime guard
queryRequest.fetch('missing_resource', {})
).rejects.toThrow('Unknown query resource');
});
});
+9 -25
View File
@@ -1,11 +1,6 @@
import { patchAndRefetchActiveQuery, queryKeys } from '../queries';
import { request } from '../service/request'; import { request } from '../service/request';
import { useUserStore } from '../stores'; import { useUserStore } from '../stores';
import {
entityQueryPolicies,
fetchWithEntityPolicy,
patchAndRefetchActiveQuery,
queryKeys
} from '../queries';
const avatarReq = { const avatarReq = {
/** /**
@@ -23,22 +18,6 @@ const avatarReq = {
}); });
}, },
/**
* Fetch avatar from query cache if fresh. Otherwise, calls API.
* @param {{avatarId: string}} params
* @returns {Promise<{json: any, ref?: any, cache?: boolean, params: {avatarId: string}}>}
*/
getCachedAvatar(params) {
return fetchWithEntityPolicy({
queryKey: queryKeys.avatar(params.avatarId),
policy: entityQueryPolicies.avatar,
queryFn: () => avatarReq.getAvatar(params)
}).then(({ data, cache }) => ({
...data,
cache
}));
},
/** /**
* @type {import('../types/api/avatar').GetAvatars} * @type {import('../types/api/avatar').GetAvatars}
*/ */
@@ -72,7 +51,10 @@ const avatarReq = {
queryKey: queryKeys.avatar(params.id), queryKey: queryKeys.avatar(params.id),
nextData: args nextData: args
}).catch((err) => { }).catch((err) => {
console.error('Failed to refresh avatar query after mutation:', err); console.error(
'Failed to refresh avatar query after mutation:',
err
);
}); });
return args; return args;
}); });
@@ -112,7 +94,7 @@ const avatarReq = {
/** /**
* @param {{ avatarId: string }} params * @param {{ avatarId: string }} params
* @return { Promise<{json: any, params}> } * @returns { Promise<{json: any, params}> }
*/ */
selectFallbackAvatar(params) { selectFallbackAvatar(params) {
const userStore = useUserStore(); const userStore = useUserStore();
@@ -144,7 +126,7 @@ const avatarReq = {
/** /**
* @param {{ avatarId: string }} params * @param {{ avatarId: string }} params
* @return { Promise<{json: any, params}> } * @returns { Promise<{json: any, params}> }
*/ */
deleteAvatar(params) { deleteAvatar(params) {
return request(`avatars/${params.avatarId}`, { return request(`avatars/${params.avatarId}`, {
@@ -247,6 +229,8 @@ const avatarReq = {
/** /**
* @param {{ imageData: string, avatarId: string }} * @param {{ imageData: string, avatarId: string }}
* @param imageData
* @param avatarId
* @returns {Promise<{json: any, params}>} * @returns {Promise<{json: any, params}>}
*/ */
uploadAvatarGalleryImage(imageData, avatarId) { uploadAvatarGalleryImage(imageData, avatarId) {
+11 -65
View File
@@ -1,16 +1,17 @@
import { useFavoriteStore, useUserStore } from '../stores'; import { useFavoriteStore, useUserStore } from '../stores';
import { queryClient } from '../queries';
import { request } from '../service/request'; import { request } from '../service/request';
import {
entityQueryPolicies,
fetchWithEntityPolicy,
queryClient,
queryKeys
} from '../queries';
/**
*
*/
function getCurrentUserId() { function getCurrentUserId() {
return useUserStore().currentUser.id; return useUserStore().currentUser.id;
} }
/**
*
*/
function refetchActiveFavoriteQueries() { function refetchActiveFavoriteQueries() {
queryClient queryClient
.invalidateQueries({ .invalidateQueries({
@@ -34,17 +35,6 @@ const favoriteReq = {
}); });
}, },
getCachedFavoriteLimits() {
return fetchWithEntityPolicy({
queryKey: queryKeys.favoriteLimits(),
policy: entityQueryPolicies.favoriteCollection,
queryFn: () => favoriteReq.getFavoriteLimits()
}).then(({ data, cache }) => ({
...data,
cache
}));
},
/** /**
* @type {import('../types/api/favorite').GetFavorites} * @type {import('../types/api/favorite').GetFavorites}
*/ */
@@ -61,17 +51,6 @@ const favoriteReq = {
}); });
}, },
getCachedFavorites(params) {
return fetchWithEntityPolicy({
queryKey: queryKeys.favorites(params),
policy: entityQueryPolicies.favoriteCollection,
queryFn: () => favoriteReq.getFavorites(params)
}).then(({ data, cache }) => ({
...data,
cache
}));
},
/** /**
* @type {import('../types/api/favorite').AddFavorite} * @type {import('../types/api/favorite').AddFavorite}
*/ */
@@ -92,7 +71,7 @@ const favoriteReq = {
/** /**
* @param {{ objectId: string }} params * @param {{ objectId: string }} params
* @return { Promise<{json: any, params}> } * @returns { Promise<{json: any, params}> }
*/ */
deleteFavorite(params) { deleteFavorite(params) {
return request(`favorites/${params.objectId}`, { return request(`favorites/${params.objectId}`, {
@@ -110,7 +89,7 @@ const favoriteReq = {
/** /**
* @param {{ n: number, offset: number, type: string }} params * @param {{ n: number, offset: number, type: string }} params
* @return { Promise<{json: any, params}> } * @returns { Promise<{json: any, params}> }
*/ */
getFavoriteGroups(params) { getFavoriteGroups(params) {
return request('favorite/groups', { return request('favorite/groups', {
@@ -125,21 +104,10 @@ const favoriteReq = {
}); });
}, },
getCachedFavoriteGroups(params) {
return fetchWithEntityPolicy({
queryKey: queryKeys.favoriteGroups(params),
policy: entityQueryPolicies.favoriteCollection,
queryFn: () => favoriteReq.getFavoriteGroups(params)
}).then(({ data, cache }) => ({
...data,
cache
}));
},
/** /**
* *
* @param {{ type: string, group: string, displayName?: string, visibility?: string }} params group is a name * @param {{ type: string, group: string, displayName?: string, visibility?: string }} params group is a name
* @return { Promise<{json: any, params}> } * @returns { Promise<{json: any, params}> }
*/ */
saveFavoriteGroup(params) { saveFavoriteGroup(params) {
return request( return request(
@@ -163,7 +131,7 @@ const favoriteReq = {
* type: string, * type: string,
* group: string * group: string
* }} params * }} params
* @return { Promise<{json: any, params}> } * @returns { Promise<{json: any, params}> }
*/ */
clearFavoriteGroup(params) { clearFavoriteGroup(params) {
return request( return request(
@@ -199,17 +167,6 @@ const favoriteReq = {
}); });
}, },
getCachedFavoriteWorlds(params) {
return fetchWithEntityPolicy({
queryKey: queryKeys.favoriteWorlds(params),
policy: entityQueryPolicies.favoriteCollection,
queryFn: () => favoriteReq.getFavoriteWorlds(params)
}).then(({ data, cache }) => ({
...data,
cache
}));
},
/** /**
* @type {import('../types/api/favorite').GetFavoriteAvatars} * @type {import('../types/api/favorite').GetFavoriteAvatars}
*/ */
@@ -224,17 +181,6 @@ const favoriteReq = {
}; };
return args; return args;
}); });
},
getCachedFavoriteAvatars(params) {
return fetchWithEntityPolicy({
queryKey: queryKeys.favoriteAvatars(params),
policy: entityQueryPolicies.favoriteCollection,
queryFn: () => favoriteReq.getFavoriteAvatars(params)
}).then(({ data, cache }) => ({
...data,
cache
}));
} }
}; };
+5 -22
View File
@@ -1,12 +1,10 @@
import { queryClient } from '../queries';
import { request } from '../service/request'; import { request } from '../service/request';
import { useUserStore } from '../stores/user'; import { useUserStore } from '../stores/user';
import {
entityQueryPolicies,
fetchWithEntityPolicy,
queryClient,
queryKeys
} from '../queries';
/**
*
*/
function refetchActiveFriendListQueries() { function refetchActiveFriendListQueries() {
queryClient queryClient
.invalidateQueries({ .invalidateQueries({
@@ -44,22 +42,6 @@ const friendReq = {
}); });
}, },
/**
* Fetch friends from query cache if still fresh. Otherwise, calls API.
* @param {{ n: number, offset: number, offline?: boolean }} params
* @returns {Promise<{json: any, params: { n: number, offset: number, offline?: boolean }, cache?: boolean}>}
*/
getCachedFriends(params) {
return fetchWithEntityPolicy({
queryKey: queryKeys.friends(params),
policy: entityQueryPolicies.friendList,
queryFn: () => friendReq.getFriends(params)
}).then(({ data, cache }) => ({
...data,
cache
}));
},
/** /**
* @param {{ userId: string }} params * @param {{ userId: string }} params
* @returns {Promise<{json: any, params: { userId: string }}>} * @returns {Promise<{json: any, params: { userId: string }}>}
@@ -96,6 +78,7 @@ const friendReq = {
/** /**
* @param {{ userId: string }} params * @param {{ userId: string }} params
* @param customMsg
* @returns {Promise<{json: any, params: { userId: string }}>} * @returns {Promise<{json: any, params: { userId: string }}>}
*/ */
deleteFriend(params, customMsg) { deleteFriend(params, customMsg) {
+43 -116
View File
@@ -1,16 +1,18 @@
import { useGroupStore, useUserStore } from '../stores'; import { useGroupStore, useUserStore } from '../stores';
import { queryClient } from '../queries';
import { request } from '../service/request'; import { request } from '../service/request';
import {
entityQueryPolicies,
fetchWithEntityPolicy,
queryClient,
queryKeys
} from '../queries';
/**
*
*/
function getCurrentUserId() { function getCurrentUserId() {
return useUserStore().currentUser.id; return useUserStore().currentUser.id;
} }
/**
*
* @param groupId
*/
function refetchActiveGroupScope(groupId) { function refetchActiveGroupScope(groupId) {
if (!groupId) { if (!groupId) {
return; return;
@@ -47,7 +49,7 @@ const groupReq = {
/** /**
* @param {{ groupId: string }} params * @param {{ groupId: string }} params
* @return { Promise<{json: any, params}> } * @returns { Promise<{json: any, params}> }
*/ */
cancelGroupRequest(params) { cancelGroupRequest(params) {
return request(`groups/${params.groupId}/requests`, { return request(`groups/${params.groupId}/requests`, {
@@ -63,7 +65,7 @@ const groupReq = {
/** /**
* @param {{ groupId: string, postId: string }} params * @param {{ groupId: string, postId: string }} params
* @return { Promise<{json: any, params}> } * @returns { Promise<{json: any, params}> }
*/ */
deleteGroupPost(params) { deleteGroupPost(params) {
return request(`groups/${params.groupId}/posts/${params.postId}`, { return request(`groups/${params.groupId}/posts/${params.postId}`, {
@@ -87,35 +89,18 @@ const groupReq = {
includeRoles: params.includeRoles || false includeRoles: params.includeRoles || false
} }
}).then((json) => { }).then((json) => {
const groupStore = useGroupStore();
const args = { const args = {
json, json,
params params
}; };
args.ref = groupStore.applyGroup(json);
return args; return args;
}); });
}, },
/**
*
* @param {{ groupId: string }} params
* @return { Promise<{json: any, ref: any, cache?: boolean, params}> }
*/
getCachedGroup(params) {
return fetchWithEntityPolicy({
queryKey: queryKeys.group(params.groupId, params.includeRoles),
policy: entityQueryPolicies.group,
queryFn: () => groupReq.getGroup(params).then((args) => {
const groupStore = useGroupStore();
args.ref = groupStore.applyGroup(args.json);
return args;
})
}).then(({ data, cache }) => ({
...data,
cache
}));
},
/** /**
* @param {{ userId: string }} params * @param {{ userId: string }} params
* @return { Promise<{json: any, params}> } * @returns { Promise<{json: any, params}> }
*/ */
getRepresentedGroup(params) { getRepresentedGroup(params) {
return request(`users/${params.userId}/groups/represented`, { return request(`users/${params.userId}/groups/represented`, {
@@ -130,7 +115,7 @@ const groupReq = {
}, },
/** /**
* @param {{ userId: string }} params * @param {{ userId: string }} params
* @return { Promise<{json: any, params}> } * @returns { Promise<{json: any, params}> }
*/ */
getGroups(params) { getGroups(params) {
return request(`users/${params.userId}/groups`, { return request(`users/${params.userId}/groups`, {
@@ -145,7 +130,7 @@ const groupReq = {
}, },
/** /**
* @param {{ groupId: string }} params * @param {{ groupId: string }} params
* @return { Promise<{json: any, params}> } * @returns { Promise<{json: any, params}> }
*/ */
joinGroup(params) { joinGroup(params) {
return request(`groups/${params.groupId}/join`, { return request(`groups/${params.groupId}/join`, {
@@ -161,7 +146,7 @@ const groupReq = {
}, },
/** /**
* @param {{ groupId: string }} params * @param {{ groupId: string }} params
* @return { Promise<{json: any, params}> } * @returns { Promise<{json: any, params}> }
*/ */
leaveGroup(params) { leaveGroup(params) {
return request(`groups/${params.groupId}/leave`, { return request(`groups/${params.groupId}/leave`, {
@@ -177,7 +162,7 @@ const groupReq = {
}, },
/** /**
* @param {{ query: string }} params * @param {{ query: string }} params
* @return { Promise<{json: any, params}> } * @returns { Promise<{json: any, params}> }
*/ */
groupStrictsearch(params) { groupStrictsearch(params) {
return request(`groups/strictsearch`, { return request(`groups/strictsearch`, {
@@ -199,7 +184,10 @@ const groupReq = {
isSubscribedToAnnouncements: bool, isSubscribedToAnnouncements: bool,
managerNotes: string managerNotes: string
} }
*/ * @param userId
* @param groupId
* @param params
*/
setGroupMemberProps(userId, groupId, params) { setGroupMemberProps(userId, groupId, params) {
return request(`groups/${groupId}/members/${userId}`, { return request(`groups/${groupId}/members/${userId}`, {
method: 'PUT', method: 'PUT',
@@ -221,7 +209,7 @@ const groupReq = {
* groupId: string, * groupId: string,
* roleId: string * roleId: string
* }} params * }} params
* @return { Promise<{json: any, params}> } * @returns { Promise<{json: any, params}> }
*/ */
addGroupMemberRole(params) { addGroupMemberRole(params) {
return request( return request(
@@ -244,7 +232,7 @@ const groupReq = {
* groupId: string, * groupId: string,
* roleId: string * roleId: string
* }} params * }} params
* @return { Promise<{json: any, params}> } * @returns { Promise<{json: any, params}> }
*/ */
removeGroupMemberRole(params) { removeGroupMemberRole(params) {
return request( return request(
@@ -278,7 +266,7 @@ const groupReq = {
n: number, n: number,
offset: number offset: number
}} params }} params
* @return { Promise<{json: any, params}> } * @returns { Promise<{json: any, params}> }
*/ */
getGroupPosts(params) { getGroupPosts(params) {
return request(`groups/${params.groupId}/posts`, { return request(`groups/${params.groupId}/posts`, {
@@ -292,16 +280,6 @@ const groupReq = {
return args; return args;
}); });
}, },
getCachedGroupPosts(params) {
return fetchWithEntityPolicy({
queryKey: queryKeys.groupPosts(params),
policy: entityQueryPolicies.groupCollection,
queryFn: () => groupReq.getGroupPosts(params)
}).then(({ data, cache }) => ({
...data,
cache
}));
},
editGroupPost(params) { editGroupPost(params) {
return request(`groups/${params.groupId}/posts/${params.postId}`, { return request(`groups/${params.groupId}/posts/${params.postId}`, {
method: 'PUT', method: 'PUT',
@@ -333,7 +311,7 @@ const groupReq = {
* groupId: string, * groupId: string,
* userId: string * userId: string
* }} params * }} params
* @return { Promise<{json: any, params, ref?: any}> } * @returns { Promise<{json: any, params, ref?: any}> }
*/ */
getGroupMember(params) { getGroupMember(params) {
return request(`groups/${params.groupId}/members/${params.userId}`, { return request(`groups/${params.groupId}/members/${params.userId}`, {
@@ -346,23 +324,13 @@ const groupReq = {
return args; return args;
}); });
}, },
getCachedGroupMember(params) {
return fetchWithEntityPolicy({
queryKey: queryKeys.groupMember(params),
policy: entityQueryPolicies.groupCollection,
queryFn: () => groupReq.getGroupMember(params)
}).then(({ data, cache }) => ({
...data,
cache
}));
},
/** /**
* @param {{ * @param {{
* groupId: string, * groupId: string,
* n: number, * n: number,
* offset: number * offset: number
* }} params * }} params
* @return { Promise<{json: any, params}> } * @returns { Promise<{json: any, params}> }
*/ */
getGroupMembers(params) { getGroupMembers(params) {
return request(`groups/${params.groupId}/members`, { return request(`groups/${params.groupId}/members`, {
@@ -376,16 +344,6 @@ const groupReq = {
return args; return args;
}); });
}, },
getCachedGroupMembers(params) {
return fetchWithEntityPolicy({
queryKey: queryKeys.groupMembers(params),
policy: entityQueryPolicies.groupCollection,
queryFn: () => groupReq.getGroupMembers(params)
}).then(({ data, cache }) => ({
...data,
cache
}));
},
/** /**
* @param {{ * @param {{
* groupId: string, * groupId: string,
@@ -393,7 +351,7 @@ const groupReq = {
* n: number, * n: number,
* offset: number * offset: number
* }} params * }} params
* @return { Promise<{json: any, params}> } * @returns { Promise<{json: any, params}> }
*/ */
getGroupMembersSearch(params) { getGroupMembersSearch(params) {
return request(`groups/${params.groupId}/members/search`, { return request(`groups/${params.groupId}/members/search`, {
@@ -411,7 +369,7 @@ const groupReq = {
* @param {{ * @param {{
* groupId: string * groupId: string
* }} params * }} params
* @return { Promise<{json: any, params}> } * @returns { Promise<{json: any, params}> }
*/ */
blockGroup(params) { blockGroup(params) {
return request(`groups/${params.groupId}/block`, { return request(`groups/${params.groupId}/block`, {
@@ -430,7 +388,7 @@ const groupReq = {
* groupId: string, * groupId: string,
* userId: string * userId: string
* }} params * }} params
* @return { Promise<{json: any, params}> } * @returns { Promise<{json: any, params}> }
*/ */
unblockGroup(params) { unblockGroup(params) {
return request(`groups/${params.groupId}/members/${params.userId}`, { return request(`groups/${params.groupId}/members/${params.userId}`, {
@@ -449,7 +407,7 @@ const groupReq = {
* groupId: string, * groupId: string,
* userId: string * userId: string
* }} params * }} params
* @return { Promise<{json: any, params}> } * @returns { Promise<{json: any, params}> }
*/ */
sendGroupInvite(params) { sendGroupInvite(params) {
return request(`groups/${params.groupId}/invites`, { return request(`groups/${params.groupId}/invites`, {
@@ -470,7 +428,7 @@ const groupReq = {
* groupId: string, * groupId: string,
* userId: string * userId: string
* }} params * }} params
* @return { Promise<{json: any, params}> } * @returns { Promise<{json: any, params}> }
*/ */
kickGroupMember(params) { kickGroupMember(params) {
return request(`groups/${params.groupId}/members/${params.userId}`, { return request(`groups/${params.groupId}/members/${params.userId}`, {
@@ -486,7 +444,7 @@ const groupReq = {
}, },
/** /**
* @param {{ groupId: string, userId: string }} params * @param {{ groupId: string, userId: string }} params
* @return { Promise<{json: any, params}> } * @returns { Promise<{json: any, params}> }
*/ */
banGroupMember(params) { banGroupMember(params) {
return request(`groups/${params.groupId}/bans`, { return request(`groups/${params.groupId}/bans`, {
@@ -517,7 +475,7 @@ const groupReq = {
}, },
/** /**
* @param {{ groupId: string, userId: string }} params * @param {{ groupId: string, userId: string }} params
* @return { Promise<{json: any, params}> } * @returns { Promise<{json: any, params}> }
*/ */
deleteSentGroupInvite(params) { deleteSentGroupInvite(params) {
return request(`groups/${params.groupId}/invites/${params.userId}`, { return request(`groups/${params.groupId}/invites/${params.userId}`, {
@@ -601,7 +559,7 @@ const groupReq = {
}, },
/** /**
* @param {{ groupId: string }} params * @param {{ groupId: string }} params
* @return { Promise<{json: any, params}> } * @returns { Promise<{json: any, params}> }
*/ */
getGroupAuditLogTypes(params) { getGroupAuditLogTypes(params) {
return request(`groups/${params.groupId}/auditLogTypes`, { return request(`groups/${params.groupId}/auditLogTypes`, {
@@ -615,8 +573,8 @@ const groupReq = {
}); });
}, },
/** /**
* @param {{ groupId: string, n: number, offset: number, eventTypes?: array }} params * @param {{groupId: string, n: number, offset: number, eventTypes?: Array}} params
* @return { Promise<{json: any, params}> } * @returns { Promise<{json: any, params}> }
*/ */
getGroupLogs(params) { getGroupLogs(params) {
return request(`groups/${params.groupId}/auditLogs`, { return request(`groups/${params.groupId}/auditLogs`, {
@@ -632,7 +590,7 @@ const groupReq = {
}, },
/** /**
* @param {{ groupId: string }} params * @param {{ groupId: string }} params
* @return { Promise<{json: any, params}> } * @returns { Promise<{json: any, params}> }
*/ */
getGroupInvites(params) { getGroupInvites(params) {
return request(`groups/${params.groupId}/invites`, { return request(`groups/${params.groupId}/invites`, {
@@ -648,7 +606,7 @@ const groupReq = {
}, },
/** /**
* @param {{ groupId: string }} params * @param {{ groupId: string }} params
* @return { Promise<{json: any, params}> } * @returns { Promise<{json: any, params}> }
*/ */
getGroupJoinRequests(params) { getGroupJoinRequests(params) {
return request(`groups/${params.groupId}/requests`, { return request(`groups/${params.groupId}/requests`, {
@@ -664,7 +622,7 @@ const groupReq = {
}, },
/** /**
* @param {{ groupId: string }} params * @param {{ groupId: string }} params
* @return { Promise<{json: any, params}> } * @returns { Promise<{json: any, params}> }
*/ */
getGroupInstances(params) { getGroupInstances(params) {
return request( return request(
@@ -682,7 +640,7 @@ const groupReq = {
}, },
/** /**
* @param {{ groupId: string }} params * @param {{ groupId: string }} params
* @return { Promise<{json: any, params}> } * @returns { Promise<{json: any, params}> }
*/ */
getGroupRoles(params) { getGroupRoles(params) {
return request(`groups/${params.groupId}/roles`, { return request(`groups/${params.groupId}/roles`, {
@@ -715,7 +673,7 @@ const groupReq = {
order: string, order: string,
sortBy: string sortBy: string
}} params }} params
* @return { Promise<{json: any, params}> } * @returns { Promise<{json: any, params}> }
*/ */
groupSearch(params) { groupSearch(params) {
return request(`groups`, { return request(`groups`, {
@@ -736,7 +694,7 @@ const groupReq = {
n: number, n: number,
offset: number offset: number
}} params }} params
* @return { Promise<{json: any, params}> } * @returns { Promise<{json: any, params}> }
*/ */
getGroupGallery(params) { getGroupGallery(params) {
return request( return request(
@@ -756,16 +714,6 @@ const groupReq = {
return args; return args;
}); });
}, },
getCachedGroupGallery(params) {
return fetchWithEntityPolicy({
queryKey: queryKeys.groupGallery(params),
policy: entityQueryPolicies.groupCollection,
queryFn: () => groupReq.getGroupGallery(params)
}).then(({ data, cache }) => ({
...data,
cache
}));
},
getGroupCalendar(groupId) { getGroupCalendar(groupId) {
return request(`calendar/${groupId}`, { return request(`calendar/${groupId}`, {
@@ -780,23 +728,13 @@ const groupReq = {
return args; return args;
}); });
}, },
getCachedGroupCalendar(groupId) {
return fetchWithEntityPolicy({
queryKey: queryKeys.groupCalendar(groupId),
policy: entityQueryPolicies.groupCollection,
queryFn: () => groupReq.getGroupCalendar(groupId)
}).then(({ data, cache }) => ({
...data,
cache
}));
},
/** /**
* @param {{ * @param {{
groupId: string, groupId: string,
eventId: string eventId: string
}} params }} params
* @return { Promise<{json: any, params}> } * @returns { Promise<{json: any, params}> }
*/ */
getGroupCalendarEvent(params) { getGroupCalendarEvent(params) {
return request(`calendar/${params.groupId}/${params.eventId}`, { return request(`calendar/${params.groupId}/${params.eventId}`, {
@@ -809,17 +747,6 @@ const groupReq = {
return args; return args;
}); });
}, },
getCachedGroupCalendarEvent(params) {
return fetchWithEntityPolicy({
queryKey: queryKeys.groupCalendarEvent(params),
policy: entityQueryPolicies.groupCollection,
queryFn: () => groupReq.getGroupCalendarEvent(params)
}).then(({ data, cache }) => ({
...data,
cache
}));
},
/** /**
* @type {import('../types/api/group').GetCalendars} * @type {import('../types/api/group').GetCalendars}
*/ */
+5 -2
View File
@@ -19,6 +19,7 @@ import miscRequest from './misc';
import notificationRequest from './notification'; import notificationRequest from './notification';
import playerModerationRequest from './playerModeration'; import playerModerationRequest from './playerModeration';
import propRequest from './prop'; import propRequest from './prop';
import queryRequest from './queryRequest';
import userRequest from './user'; import userRequest from './user';
import vrcPlusIconRequest from './vrcPlusIcon'; import vrcPlusIconRequest from './vrcPlusIcon';
import vrcPlusImageRequest from './vrcPlusImage'; import vrcPlusImageRequest from './vrcPlusImage';
@@ -43,7 +44,8 @@ window.request = {
groupRequest, groupRequest,
inventoryRequest, inventoryRequest,
propRequest, propRequest,
imageRequest imageRequest,
queryRequest
}; };
export { export {
@@ -65,5 +67,6 @@ export {
groupRequest, groupRequest,
inventoryRequest, inventoryRequest,
propRequest, propRequest,
imageRequest imageRequest,
queryRequest
}; };
-39
View File
@@ -3,12 +3,6 @@ import { toast } from 'vue-sonner';
import { i18n } from '../plugin/i18n'; import { i18n } from '../plugin/i18n';
import { request } from '../service/request'; import { request } from '../service/request';
import { useInstanceStore } from '../stores'; import { useInstanceStore } from '../stores';
import {
entityQueryPolicies,
fetchWithEntityPolicy,
patchAndRefetchActiveQuery,
queryKeys
} from '../queries';
const instanceReq = { const instanceReq = {
/** /**
@@ -28,21 +22,6 @@ const instanceReq = {
}); });
}, },
/**
* @param {{worldId: string, instanceId: string}} params
* @returns {Promise<{json: any, ref: any, cache?: boolean, params}>}
*/
getCachedInstance(params) {
return fetchWithEntityPolicy({
queryKey: queryKeys.instance(params.worldId, params.instanceId),
policy: entityQueryPolicies.instance,
queryFn: () => instanceReq.getInstance(params)
}).then(({ data, cache }) => ({
...data,
cache
}));
},
/** /**
* @type {import('../types/api/instance').CreateInstance} * @type {import('../types/api/instance').CreateInstance}
*/ */
@@ -57,15 +36,6 @@ const instanceReq = {
params params
}; };
args.ref = instanceStore.applyInstance(json); args.ref = instanceStore.applyInstance(json);
patchAndRefetchActiveQuery({
queryKey: queryKeys.instance(args.ref.worldId, args.ref.instanceId),
nextData: args
}).catch((err) => {
console.error(
'Failed to refresh instance query after instance creation:',
err
);
});
return args; return args;
}); });
}, },
@@ -108,15 +78,6 @@ const instanceReq = {
params params
}; };
args.ref = instanceStore.applyInstance(json); args.ref = instanceStore.applyInstance(json);
patchAndRefetchActiveQuery({
queryKey: queryKeys.instance(args.ref.worldId, args.ref.instanceId),
nextData: args
}).catch((err) => {
console.error(
'Failed to refresh instance query after short-name resolve:',
err
);
});
return args; return args;
}); });
}, },
+4 -28
View File
@@ -1,11 +1,9 @@
import { queryClient } from '../queries';
import { request } from '../service/request'; import { request } from '../service/request';
import {
entityQueryPolicies,
fetchWithEntityPolicy,
queryClient,
queryKeys
} from '../queries';
/**
*
*/
function refetchActiveInventoryQueries() { function refetchActiveInventoryQueries() {
queryClient queryClient
.invalidateQueries({ .invalidateQueries({
@@ -37,17 +35,6 @@ const inventoryReq = {
}); });
}, },
getCachedUserInventoryItem(params) {
return fetchWithEntityPolicy({
queryKey: queryKeys.userInventoryItem(params),
policy: entityQueryPolicies.inventoryCollection,
queryFn: () => inventoryReq.getUserInventoryItem(params)
}).then(({ data, cache }) => ({
...data,
cache
}));
},
/** /**
* @param {{ inventoryId: string }} params * @param {{ inventoryId: string }} params
* @returns {Promise<{json: any, params}>} * @returns {Promise<{json: any, params}>}
@@ -82,17 +69,6 @@ const inventoryReq = {
}); });
}, },
getCachedInventoryItems(params) {
return fetchWithEntityPolicy({
queryKey: queryKeys.inventoryItems(params),
policy: entityQueryPolicies.inventoryCollection,
queryFn: () => inventoryReq.getInventoryItems(params)
}).then(({ data, cache }) => ({
...data,
cache
}));
},
/** /**
* @param {{ inventoryId: string }} params * @param {{ inventoryId: string }} params
* @returns {Promise<{json: any, params}>} * @returns {Promise<{json: any, params}>}
+7 -19
View File
@@ -1,12 +1,10 @@
import { queryClient, queryKeys } from '../queries';
import { request } from '../service/request'; import { request } from '../service/request';
import { useUserStore } from '../stores'; import { useUserStore } from '../stores';
import {
entityQueryPolicies,
fetchWithEntityPolicy,
queryClient,
queryKeys
} from '../queries';
/**
*
*/
function getCurrentUserId() { function getCurrentUserId() {
return useUserStore().currentUser.id; return useUserStore().currentUser.id;
} }
@@ -24,17 +22,6 @@ const miscReq = {
}); });
}, },
getCachedFile(params) {
return fetchWithEntityPolicy({
queryKey: queryKeys.file(params.fileId),
policy: entityQueryPolicies.fileObject,
queryFn: () => miscReq.getFile(params)
}).then(({ data, cache }) => ({
...data,
cache
}));
},
saveNote(params) { saveNote(params) {
return request('userNotes', { return request('userNotes', {
method: 'POST', method: 'POST',
@@ -55,7 +42,7 @@ const miscReq = {
* reason: string, * reason: string,
* type: string * type: string
* }} params * }} params
* @return { Promise<{json: any, params}> } * @returns { Promise<{json: any, params}> }
*/ */
reportUser(params) { reportUser(params) {
return request(`feedback/${params.userId}/user`, { return request(`feedback/${params.userId}/user`, {
@@ -80,7 +67,7 @@ const miscReq = {
* version: number, * version: number,
* variant: string * variant: string
* }} params * }} params
* @return { Promise<{json: any, params}> } * @returns { Promise<{json: any, params}> }
*/ */
getFileAnalysis(params) { getFileAnalysis(params) {
return request( return request(
@@ -218,6 +205,7 @@ const miscReq = {
}, },
/** /**
* @param params
* @params {{ * @params {{
userId: string, userId: string,
emojiId: string emojiId: string
+163
View File
@@ -0,0 +1,163 @@
import {
entityQueryPolicies,
fetchWithEntityPolicy,
queryKeys
} from '../queries';
import avatarRequest from './avatar';
import favoriteRequest from './favorite';
import friendRequest from './friend';
import groupRequest from './group';
import inventoryRequest from './inventory';
import miscRequest from './misc';
import userRequest from './user';
import vrcPlusIconRequest from './vrcPlusIcon';
import vrcPlusImageRequest from './vrcPlusImage';
import worldRequest from './world';
const registry = Object.freeze({
user: {
key: (params) => queryKeys.user(params.userId),
policy: entityQueryPolicies.user,
queryFn: (params) => userRequest.getUser(params)
},
avatar: {
key: (params) => queryKeys.avatar(params.avatarId),
policy: entityQueryPolicies.avatar,
queryFn: (params) => avatarRequest.getAvatar(params)
},
world: {
key: (params) => queryKeys.world(params.worldId),
policy: entityQueryPolicies.world,
queryFn: (params) => worldRequest.getWorld(params)
},
worldsByUser: {
key: (params) => queryKeys.worldsByUser(params),
policy: entityQueryPolicies.worldCollection,
queryFn: (params) =>
worldRequest.getWorlds(params, params.option || undefined)
},
group: {
key: (params) => queryKeys.group(params.groupId, params.includeRoles),
policy: entityQueryPolicies.group,
queryFn: (params) => groupRequest.getGroup(params)
},
groupPosts: {
key: (params) => queryKeys.groupPosts(params),
policy: entityQueryPolicies.groupCollection,
queryFn: (params) => groupRequest.getGroupPosts(params)
},
groupMember: {
key: (params) => queryKeys.groupMember(params),
policy: entityQueryPolicies.groupCollection,
queryFn: (params) => groupRequest.getGroupMember(params)
},
groupMembers: {
key: (params) => queryKeys.groupMembers(params),
policy: entityQueryPolicies.groupCollection,
queryFn: (params) => groupRequest.getGroupMembers(params)
},
groupGallery: {
key: (params) => queryKeys.groupGallery(params),
policy: entityQueryPolicies.groupCollection,
queryFn: (params) => groupRequest.getGroupGallery(params)
},
groupCalendar: {
key: (params) => queryKeys.groupCalendar(params.groupId),
policy: entityQueryPolicies.groupCollection,
queryFn: (params) => groupRequest.getGroupCalendar(params.groupId)
},
groupCalendarEvent: {
key: (params) => queryKeys.groupCalendarEvent(params),
policy: entityQueryPolicies.groupCollection,
queryFn: (params) => groupRequest.getGroupCalendarEvent(params)
},
friends: {
key: (params) => queryKeys.friends(params),
policy: entityQueryPolicies.friendList,
queryFn: (params) => friendRequest.getFriends(params)
},
favoriteLimits: {
key: () => queryKeys.favoriteLimits(),
policy: entityQueryPolicies.favoriteCollection,
queryFn: () => favoriteRequest.getFavoriteLimits()
},
favorites: {
key: (params) => queryKeys.favorites(params),
policy: entityQueryPolicies.favoriteCollection,
queryFn: (params) => favoriteRequest.getFavorites(params)
},
favoriteGroups: {
key: (params) => queryKeys.favoriteGroups(params),
policy: entityQueryPolicies.favoriteCollection,
queryFn: (params) => favoriteRequest.getFavoriteGroups(params)
},
favoriteWorlds: {
key: (params) => queryKeys.favoriteWorlds(params),
policy: entityQueryPolicies.favoriteCollection,
queryFn: (params) => favoriteRequest.getFavoriteWorlds(params)
},
favoriteAvatars: {
key: (params) => queryKeys.favoriteAvatars(params),
policy: entityQueryPolicies.favoriteCollection,
queryFn: (params) => favoriteRequest.getFavoriteAvatars(params)
},
galleryFiles: {
key: (params) => queryKeys.galleryFiles(params),
policy: entityQueryPolicies.galleryCollection,
queryFn: (params) => vrcPlusIconRequest.getFileList(params)
},
prints: {
key: (params) => queryKeys.prints(params),
policy: entityQueryPolicies.galleryCollection,
queryFn: (params) => vrcPlusImageRequest.getPrints(params)
},
print: {
key: (params) => queryKeys.print(params.printId),
policy: entityQueryPolicies.galleryCollection,
queryFn: (params) => vrcPlusImageRequest.getPrint(params)
},
userInventoryItem: {
key: (params) => queryKeys.userInventoryItem(params),
policy: entityQueryPolicies.inventoryCollection,
queryFn: (params) => inventoryRequest.getUserInventoryItem(params)
},
inventoryItems: {
key: (params) => queryKeys.inventoryItems(params),
policy: entityQueryPolicies.inventoryCollection,
queryFn: (params) => inventoryRequest.getInventoryItems(params)
},
file: {
key: (params) => queryKeys.file(params.fileId),
policy: entityQueryPolicies.fileObject,
queryFn: (params) => miscRequest.getFile(params)
}
});
const queryRequest = {
/**
* @template T
* @param {keyof typeof registry} resource
* @param {any} [params]
* @returns {Promise<T & {cache: boolean}>}
*/
async fetch(resource, params = {}) {
const entry = registry[resource];
if (!entry) {
throw new Error(`Unknown query resource: ${String(resource)}`);
}
const { data, cache } = await fetchWithEntityPolicy({
queryKey: entry.key(params),
policy: entry.policy,
queryFn: () => entry.queryFn(params)
});
return {
...data,
cache
};
}
};
export default queryRequest;
+5 -22
View File
@@ -1,11 +1,6 @@
import { patchAndRefetchActiveQuery, queryKeys } from '../queries';
import { request } from '../service/request'; import { request } from '../service/request';
import { useUserStore } from '../stores'; import { useUserStore } from '../stores';
import {
entityQueryPolicies,
fetchWithEntityPolicy,
patchAndRefetchActiveQuery,
queryKeys
} from '../queries';
/** /**
* @returns {string} * @returns {string}
@@ -40,21 +35,6 @@ const userReq = {
}); });
}, },
/**
* Fetch user from cache if they're in it. Otherwise, calls API.
* @type {import('../types/api/user').GetCachedUser}
*/
getCachedUser(params) {
return fetchWithEntityPolicy({
queryKey: queryKeys.user(params.userId),
policy: entityQueryPolicies.user,
queryFn: () => userReq.getUser(params)
}).then(({ data, cache }) => ({
...data,
cache
}));
},
/** /**
* @type {import('../types/api/user').GetUsers} * @type {import('../types/api/user').GetUsers}
*/ */
@@ -147,7 +127,10 @@ const userReq = {
queryKey: queryKeys.user(args.ref.id), queryKey: queryKeys.user(args.ref.id),
nextData: args nextData: args
}).catch((err) => { }).catch((err) => {
console.error('Failed to refresh user query after mutation:', err); console.error(
'Failed to refresh user query after mutation:',
err
);
}); });
return args; return args;
}); });
+4 -17
View File
@@ -1,11 +1,9 @@
import { queryClient } from '../queries';
import { request } from '../service/request'; import { request } from '../service/request';
import {
entityQueryPolicies,
fetchWithEntityPolicy,
queryClient,
queryKeys
} from '../queries';
/**
*
*/
function refetchActiveGalleryQueries() { function refetchActiveGalleryQueries() {
queryClient queryClient
.invalidateQueries({ .invalidateQueries({
@@ -31,17 +29,6 @@ const VRCPlusIconsReq = {
}); });
}, },
getCachedFileList(params) {
return fetchWithEntityPolicy({
queryKey: queryKeys.galleryFiles(params),
policy: entityQueryPolicies.galleryCollection,
queryFn: () => VRCPlusIconsReq.getFileList(params)
}).then(({ data, cache }) => ({
...data,
cache
}));
},
deleteFile(fileId) { deleteFile(fileId) {
return request(`file/${fileId}`, { return request(`file/${fileId}`, {
method: 'DELETE' method: 'DELETE'
+7 -28
View File
@@ -1,16 +1,17 @@
import { queryClient } from '../queries';
import { request } from '../service/request'; import { request } from '../service/request';
import { useUserStore } from '../stores'; import { useUserStore } from '../stores';
import {
entityQueryPolicies,
fetchWithEntityPolicy,
queryClient,
queryKeys
} from '../queries';
/**
*
*/
function getCurrentUserId() { function getCurrentUserId() {
return useUserStore().currentUser.id; return useUserStore().currentUser.id;
} }
/**
*
*/
function refetchActiveGalleryQueries() { function refetchActiveGalleryQueries() {
queryClient queryClient
.invalidateQueries({ .invalidateQueries({
@@ -70,17 +71,6 @@ const vrcPlusImageReq = {
}); });
}, },
getCachedPrints(params) {
return fetchWithEntityPolicy({
queryKey: queryKeys.prints(params),
policy: entityQueryPolicies.galleryCollection,
queryFn: () => vrcPlusImageReq.getPrints(params)
}).then(({ data, cache }) => ({
...data,
cache
}));
},
deletePrint(printId) { deletePrint(printId) {
return request(`prints/${printId}`, { return request(`prints/${printId}`, {
method: 'DELETE' method: 'DELETE'
@@ -122,17 +112,6 @@ const vrcPlusImageReq = {
}); });
}, },
getCachedPrint(params) {
return fetchWithEntityPolicy({
queryKey: queryKeys.print(params.printId),
policy: entityQueryPolicies.galleryCollection,
queryFn: () => vrcPlusImageReq.getPrint(params)
}).then(({ data, cache }) => ({
...data,
cache
}));
},
uploadEmoji(imageData, params) { uploadEmoji(imageData, params) {
return request('file/image', { return request('file/image', {
uploadImage: true, uploadImage: true,
+13 -42
View File
@@ -1,11 +1,6 @@
import { patchAndRefetchActiveQuery, queryKeys } from '../queries';
import { request } from '../service/request'; import { request } from '../service/request';
import { useWorldStore } from '../stores'; import { useWorldStore } from '../stores';
import {
entityQueryPolicies,
fetchWithEntityPolicy,
patchAndRefetchActiveQuery,
queryKeys
} from '../queries';
const worldReq = { const worldReq = {
/** /**
@@ -25,21 +20,6 @@ const worldReq = {
}); });
}, },
/**
* @param {{worldId: string}} params
* @returns {Promise<{json: any, ref: any, cache?: boolean, params}>}
*/
getCachedWorld(params) {
return fetchWithEntityPolicy({
queryKey: queryKeys.world(params.worldId),
policy: entityQueryPolicies.world,
queryFn: () => worldReq.getWorld(params)
}).then(({ data, cache }) => ({
...data,
cache
}));
},
/** /**
* @type {import('../types/api/world').GetWorlds} * @type {import('../types/api/world').GetWorlds}
*/ */
@@ -64,24 +44,6 @@ const worldReq = {
return args; return args;
}); });
}, },
/**
* @param {object} params
* @param {string} [option]
* @returns {Promise<{json: any, cache?: boolean, params: any, option?: string}>}
*/
getCachedWorlds(params, option) {
return fetchWithEntityPolicy({
queryKey: queryKeys.worldsByUser({
...params,
option: option || ''
}),
policy: entityQueryPolicies.worldCollection,
queryFn: () => worldReq.getWorlds(params, option)
}).then(({ data, cache }) => ({
...data,
cache
}));
},
/** /**
* @param {{worldId: string}} params * @param {{worldId: string}} params
* @returns {Promise<{json: any, params}>} * @returns {Promise<{json: any, params}>}
@@ -116,7 +78,10 @@ const worldReq = {
queryKey: queryKeys.world(args.ref.id), queryKey: queryKeys.world(args.ref.id),
nextData: args nextData: args
}).catch((err) => { }).catch((err) => {
console.error('Failed to refresh world query after mutation:', err); console.error(
'Failed to refresh world query after mutation:',
err
);
}); });
return args; return args;
}); });
@@ -141,7 +106,10 @@ const worldReq = {
queryKey: queryKeys.world(args.ref.id), queryKey: queryKeys.world(args.ref.id),
nextData: args nextData: args
}).catch((err) => { }).catch((err) => {
console.error('Failed to refresh world query after publish:', err); console.error(
'Failed to refresh world query after publish:',
err
);
}); });
return args; return args;
}); });
@@ -166,7 +134,10 @@ const worldReq = {
queryKey: queryKeys.world(args.ref.id), queryKey: queryKeys.world(args.ref.id),
nextData: args nextData: args
}).catch((err) => { }).catch((err) => {
console.error('Failed to refresh world query after unpublish:', err); console.error(
'Failed to refresh world query after unpublish:',
err
);
}); });
return args; return args;
}); });
+8 -2
View File
@@ -5,8 +5,8 @@
<script setup> <script setup>
import { ref, watch } from 'vue'; import { ref, watch } from 'vue';
import { queryRequest } from '../api';
import { useUserStore } from '../stores'; import { useUserStore } from '../stores';
import { userRequest } from '../api';
const userStore = useUserStore(); const userStore = useUserStore();
@@ -22,18 +22,24 @@
const username = ref(props.userid); const username = ref(props.userid);
/**
*
*/
async function parse() { async function parse() {
username.value = props.userid; username.value = props.userid;
if (props.hint) { if (props.hint) {
username.value = props.hint; username.value = props.hint;
} else if (props.userid) { } else if (props.userid) {
const args = await userRequest.getCachedUser({ userId: props.userid }); const args = await queryRequest.fetch('user', { userId: props.userid });
if (args?.json?.displayName) { if (args?.json?.displayName) {
username.value = args.json.displayName; username.value = args.json.displayName;
} }
} }
} }
/**
*
*/
function showUserDialog() { function showUserDialog() {
userStore.showUserDialog(props.userid); userStore.showUserDialog(props.userid);
} }
@@ -407,9 +407,9 @@
removeFromArray removeFromArray
} from '../../../shared/utils'; } from '../../../shared/utils';
import { useGalleryStore, useGroupStore, useModalStore, useUserStore } from '../../../stores'; import { useGalleryStore, useGroupStore, useModalStore, useUserStore } from '../../../stores';
import { groupRequest, queryRequest } from '../../../api';
import { Badge } from '../../ui/badge'; import { Badge } from '../../ui/badge';
import { formatJsonVars } from '../../../shared/utils/base/ui'; import { formatJsonVars } from '../../../shared/utils/base/ui';
import { groupRequest } from '../../../api';
import DialogJsonTab from '../DialogJsonTab.vue'; import DialogJsonTab from '../DialogJsonTab.vue';
import GroupDialogInfoTab from './GroupDialogInfoTab.vue'; import GroupDialogInfoTab from './GroupDialogInfoTab.vue';
@@ -796,7 +796,7 @@
selectedImageUrl: post.imageUrl selectedImageUrl: post.imageUrl
}; };
} }
groupRequest.getCachedGroup({ groupId }).then((args) => { queryRequest.fetch('group', { groupId }).then((args) => {
D.groupRef = args.ref; D.groupRef = args.ref;
}); });
D.visible = true; D.visible = true;
@@ -84,10 +84,8 @@ vi.mock('../../../../service/request', () => ({
failedGetRequests: new Map() failedGetRequests: new Map()
})); }));
vi.mock('../../../../api', () => ({ vi.mock('../../../../api', () => ({
groupRequest: { queryRequest: {
getCachedGroupGallery: vi fetch: vi.fn().mockResolvedValue({ json: [], params: {} })
.fn()
.mockResolvedValue({ json: [], params: {} })
}, },
userRequest: {} userRequest: {}
})); }));
@@ -2,13 +2,13 @@ import { describe, expect, test, vi, beforeEach } from 'vitest';
import { ref } from 'vue'; import { ref } from 'vue';
vi.mock('../../../../api', () => ({ vi.mock('../../../../api', () => ({
groupRequest: { queryRequest: {
getCachedGroupGallery: vi.fn() fetch: vi.fn()
} }
})); }));
import { useGroupGalleries } from '../useGroupGalleries'; import { useGroupGalleries } from '../useGroupGalleries';
import { groupRequest } from '../../../../api'; import { queryRequest } from '../../../../api';
function createGroupDialog(overrides = {}) { function createGroupDialog(overrides = {}) {
return ref({ return ref({
@@ -120,7 +120,7 @@ describe('useGroupGalleries', () => {
galleries: [{ id: 'g1', name: 'Gallery' }] galleries: [{ id: 'g1', name: 'Gallery' }]
} }
}); });
groupRequest.getCachedGroupGallery.mockResolvedValue({ queryRequest.fetch.mockResolvedValue({
json: [], json: [],
params: { groupId: 'grp_1' } params: { groupId: 'grp_1' }
}); });
@@ -145,7 +145,7 @@ describe('useGroupGalleries', () => {
] ]
} }
}); });
groupRequest.getCachedGroupGallery.mockResolvedValue({ queryRequest.fetch.mockResolvedValue({
json: [], json: [],
params: { groupId: 'grp_1' } params: { groupId: 'grp_1' }
}); });
@@ -153,7 +153,7 @@ describe('useGroupGalleries', () => {
const { getGroupGalleries } = useGroupGalleries(groupDialog); const { getGroupGalleries } = useGroupGalleries(groupDialog);
await getGroupGalleries(); await getGroupGalleries();
expect(groupRequest.getCachedGroupGallery).toHaveBeenCalledTimes(2); expect(queryRequest.fetch).toHaveBeenCalledTimes(2);
}); });
}); });
@@ -162,7 +162,7 @@ describe('useGroupGalleries', () => {
const groupDialog = createGroupDialog(); const groupDialog = createGroupDialog();
const { getGroupGallery } = useGroupGalleries(groupDialog); const { getGroupGallery } = useGroupGalleries(groupDialog);
groupRequest.getCachedGroupGallery.mockResolvedValueOnce({ queryRequest.fetch.mockResolvedValueOnce({
json: [ json: [
{ {
groupId: 'grp_1', groupId: 'grp_1',
@@ -190,7 +190,7 @@ describe('useGroupGalleries', () => {
const groupDialog = createGroupDialog(); const groupDialog = createGroupDialog();
const { getGroupGallery } = useGroupGalleries(groupDialog); const { getGroupGallery } = useGroupGalleries(groupDialog);
groupRequest.getCachedGroupGallery.mockResolvedValueOnce({ queryRequest.fetch.mockResolvedValueOnce({
json: [ json: [
{ {
groupId: 'grp_other', groupId: 'grp_other',
@@ -211,7 +211,7 @@ describe('useGroupGalleries', () => {
const groupDialog = createGroupDialog(); const groupDialog = createGroupDialog();
const { getGroupGallery } = useGroupGalleries(groupDialog); const { getGroupGallery } = useGroupGalleries(groupDialog);
groupRequest.getCachedGroupGallery.mockResolvedValueOnce({ queryRequest.fetch.mockResolvedValueOnce({
json: Array.from({ length: 50 }, (_, i) => ({ json: Array.from({ length: 50 }, (_, i) => ({
groupId: 'grp_1', groupId: 'grp_1',
galleryId: 'g1', galleryId: 'g1',
@@ -223,7 +223,7 @@ describe('useGroupGalleries', () => {
await getGroupGallery('grp_1', 'g1'); await getGroupGallery('grp_1', 'g1');
expect(groupRequest.getCachedGroupGallery).toHaveBeenCalledTimes(1); expect(queryRequest.fetch).toHaveBeenCalledTimes(1);
}); });
test('handles API errors gracefully', async () => { test('handles API errors gracefully', async () => {
@@ -233,7 +233,7 @@ describe('useGroupGalleries', () => {
.spyOn(console, 'error') .spyOn(console, 'error')
.mockImplementation(() => {}); .mockImplementation(() => {});
groupRequest.getCachedGroupGallery.mockRejectedValueOnce( queryRequest.fetch.mockRejectedValueOnce(
new Error('API Error') new Error('API Error')
); );
@@ -3,9 +3,10 @@ import { ref } from 'vue';
vi.mock('../../../../api', () => ({ vi.mock('../../../../api', () => ({
groupRequest: { groupRequest: {
getGroupMembersSearch: vi.fn(), getGroupMembersSearch: vi.fn()
getCachedGroupMember: vi.fn(), },
getCachedGroupMembers: vi.fn() queryRequest: {
fetch: vi.fn()
}, },
userRequest: {} userRequest: {}
})); }));
@@ -94,7 +95,7 @@ vi.mock('worker-timers', () => ({
})); }));
import { useGroupMembers } from '../useGroupMembers'; import { useGroupMembers } from '../useGroupMembers';
import { groupRequest } from '../../../../api'; import { groupRequest, queryRequest } from '../../../../api';
import { groupDialogFilterOptions } from '../../../../shared/constants'; import { groupDialogFilterOptions } from '../../../../shared/constants';
/** /**
@@ -133,7 +134,7 @@ function createDeps(overrides = {}) {
describe('useGroupMembers', () => { describe('useGroupMembers', () => {
beforeEach(() => { beforeEach(() => {
vi.clearAllMocks(); vi.clearAllMocks();
groupRequest.getCachedGroupMembers.mockReset(); queryRequest.fetch.mockReset();
}); });
describe('groupDialogMemberSortValue', () => { describe('groupDialogMemberSortValue', () => {
@@ -316,7 +317,7 @@ describe('useGroupMembers', () => {
await loadMoreGroupMembers(); await loadMoreGroupMembers();
expect(groupRequest.getCachedGroupMembers).not.toHaveBeenCalled(); expect(queryRequest.fetch).not.toHaveBeenCalled();
}); });
test('does not load when already loading', async () => { test('does not load when already loading', async () => {
@@ -327,12 +328,12 @@ describe('useGroupMembers', () => {
await loadMoreGroupMembers(); await loadMoreGroupMembers();
expect(groupRequest.getCachedGroupMembers).not.toHaveBeenCalled(); expect(queryRequest.fetch).not.toHaveBeenCalled();
}); });
test('marks done when fewer than n results returned', async () => { test('marks done when fewer than n results returned', async () => {
const groupDialog = createGroupDialog(); const groupDialog = createGroupDialog();
groupRequest.getCachedGroupMembers.mockResolvedValue({ queryRequest.fetch.mockResolvedValue({
json: [{ userId: 'usr_1' }], json: [{ userId: 'usr_1' }],
params: { groupId: 'grp_1', n: 100, offset: 0 } params: { groupId: 'grp_1', n: 100, offset: 0 }
}); });
@@ -359,7 +360,7 @@ describe('useGroupMembers', () => {
const groupDialog = createGroupDialog({ const groupDialog = createGroupDialog({
members: [{ userId: 'existing' }] members: [{ userId: 'existing' }]
}); });
groupRequest.getCachedGroupMembers.mockResolvedValue({ queryRequest.fetch.mockResolvedValue({
json: [{ userId: 'usr_new' }], json: [{ userId: 'usr_new' }],
params: { groupId: 'grp_1', n: 100, offset: 0 } params: { groupId: 'grp_1', n: 100, offset: 0 }
}); });
@@ -384,7 +385,7 @@ describe('useGroupMembers', () => {
const groupDialog = createGroupDialog({ const groupDialog = createGroupDialog({
members: [{ userId: 'usr_me' }] members: [{ userId: 'usr_me' }]
}); });
groupRequest.getCachedGroupMembers.mockResolvedValue({ queryRequest.fetch.mockResolvedValue({
json: [{ userId: 'usr_me' }, { userId: 'usr_2' }], json: [{ userId: 'usr_me' }, { userId: 'usr_2' }],
params: { groupId: 'grp_1', n: 100, offset: 0 } params: { groupId: 'grp_1', n: 100, offset: 0 }
}); });
@@ -408,7 +409,7 @@ describe('useGroupMembers', () => {
test('marks done on error', async () => { test('marks done on error', async () => {
const groupDialog = createGroupDialog(); const groupDialog = createGroupDialog();
groupRequest.getCachedGroupMembers.mockRejectedValue( queryRequest.fetch.mockRejectedValue(
new Error('fail') new Error('fail')
); );
@@ -442,7 +443,7 @@ describe('useGroupMembers', () => {
await setGroupMemberSortOrder({ value: 'joinedAt:desc' }); await setGroupMemberSortOrder({ value: 'joinedAt:desc' });
expect(groupRequest.getCachedGroupMembers).not.toHaveBeenCalled(); expect(queryRequest.fetch).not.toHaveBeenCalled();
}); });
}); });
@@ -460,7 +461,7 @@ describe('useGroupMembers', () => {
await setGroupMemberFilter(filter); await setGroupMemberFilter(filter);
expect(groupRequest.getCachedGroupMembers).not.toHaveBeenCalled(); expect(queryRequest.fetch).not.toHaveBeenCalled();
}); });
}); });
}); });
@@ -83,10 +83,14 @@ vi.mock('../../../../service/request', () => ({
})); }));
vi.mock('../../../../api', () => ({ vi.mock('../../../../api', () => ({
groupRequest: {}, groupRequest: {},
userRequest: {} userRequest: {},
queryRequest: {
fetch: vi.fn()
}
})); }));
import { useGroupModerationData } from '../useGroupModerationData'; import { useGroupModerationData } from '../useGroupModerationData';
import { queryRequest } from '../../../../api';
function createTables() { function createTables() {
return { return {
@@ -124,9 +128,6 @@ function createDeps(overrides = {}) {
getGroupMembers: vi.fn(), getGroupMembers: vi.fn(),
getGroupMembersSearch: vi.fn() getGroupMembersSearch: vi.fn()
}, },
userRequest: {
getCachedUser: vi.fn()
},
...overrides ...overrides
}; };
} }
@@ -134,6 +135,7 @@ function createDeps(overrides = {}) {
describe('useGroupModerationData', () => { describe('useGroupModerationData', () => {
beforeEach(() => { beforeEach(() => {
vi.clearAllMocks(); vi.clearAllMocks();
queryRequest.fetch.mockReset();
}); });
describe('getAllGroupBans', () => { describe('getAllGroupBans', () => {
@@ -343,7 +345,7 @@ describe('useGroupModerationData', () => {
await addGroupMemberToSelection('usr_1'); await addGroupMemberToSelection('usr_1');
expect(deps.selection.setSelectedUsers).toHaveBeenCalledWith('usr_1', member); expect(deps.selection.setSelectedUsers).toHaveBeenCalledWith('usr_1', member);
expect(deps.userRequest.getCachedUser).not.toHaveBeenCalled(); expect(queryRequest.fetch).not.toHaveBeenCalled();
}); });
test('falls back to user API when member has no user object', async () => { test('falls back to user API when member has no user object', async () => {
@@ -353,14 +355,14 @@ describe('useGroupModerationData', () => {
params: {} params: {}
}); });
deps.applyGroupMember.mockReturnValue({ userId: 'usr_1' }); deps.applyGroupMember.mockReturnValue({ userId: 'usr_1' });
deps.userRequest.getCachedUser.mockResolvedValue({ queryRequest.fetch.mockResolvedValue({
json: { id: 'usr_1', displayName: 'Alice' } json: { id: 'usr_1', displayName: 'Alice' }
}); });
const { addGroupMemberToSelection } = useGroupModerationData(deps); const { addGroupMemberToSelection } = useGroupModerationData(deps);
await addGroupMemberToSelection('usr_1'); await addGroupMemberToSelection('usr_1');
expect(deps.userRequest.getCachedUser).toHaveBeenCalledWith({ userId: 'usr_1' }); expect(queryRequest.fetch).toHaveBeenCalledWith('user', { userId: 'usr_1' });
expect(deps.selection.setSelectedUsers).toHaveBeenCalledWith('usr_1', expect.objectContaining({ expect(deps.selection.setSelectedUsers).toHaveBeenCalledWith('usr_1', expect.objectContaining({
userId: 'usr_1', userId: 'usr_1',
displayName: 'Alice' displayName: 'Alice'
@@ -1,9 +1,9 @@
import { computed, ref } from 'vue'; import { computed, ref } from 'vue';
import { groupRequest } from '../../../api';
import { queryRequest } from '../../../api';
/** /**
* Composable for managing group gallery loading and display state. * Composable for managing group gallery loading and display state.
*
* @param {import('vue').Ref} groupDialog - reactive ref to the group dialog state * @param {import('vue').Ref} groupDialog - reactive ref to the group dialog state
* @returns {{ * @returns {{
* isGroupGalleryLoading: import('vue').Ref<boolean>, * isGroupGalleryLoading: import('vue').Ref<boolean>,
@@ -26,7 +26,7 @@ export function useGroupGalleries(groupDialog) {
); );
/** /**
* @param {Object} gallery * @param {object} gallery
*/ */
function groupGalleryStatus(gallery) { function groupGalleryStatus(gallery) {
const style = {}; const style = {};
@@ -42,6 +42,7 @@ export function useGroupGalleries(groupDialog) {
/** /**
* *
* @param obj
*/ */
function updateGroupDialogData(obj) { function updateGroupDialogData(obj) {
groupDialog.value = { groupDialog.value = {
@@ -79,7 +80,7 @@ export function useGroupGalleries(groupDialog) {
}; };
const count = 50; // 5000 max const count = 50; // 5000 max
for (let i = 0; i < count; i++) { for (let i = 0; i < count; i++) {
const args = await groupRequest.getCachedGroupGallery(params); const args = await queryRequest.fetch('groupGallery', params);
if (args) { if (args) {
for (const json of args.json) { for (const json of args.json) {
if (groupDialog.value.id === json.groupId) { if (groupDialog.value.id === json.groupId) {
@@ -1,22 +1,23 @@
import { computed, ref } from 'vue'; import { computed, ref } from 'vue';
import { debounce } from '../../../shared/utils';
import { import {
groupDialogFilterOptions, groupDialogFilterOptions,
groupDialogSortingOptions groupDialogSortingOptions
} from '../../../shared/constants'; } from '../../../shared/constants';
import { groupRequest } from '../../../api'; import { groupRequest, queryRequest } from '../../../api';
import { debounce } from '../../../shared/utils';
import * as workerTimers from 'worker-timers'; import * as workerTimers from 'worker-timers';
/** /**
* Composable for managing group member loading, searching, sorting, and filtering. * Composable for managing group member loading, searching, sorting, and filtering.
*
* @param {import('vue').Ref} groupDialog - reactive ref to the group dialog state * @param {import('vue').Ref} groupDialog - reactive ref to the group dialog state
* @param {Object} deps - external dependencies * @param {object} deps - external dependencies
* @param {import('vue').Ref} deps.currentUser - reactive ref to the current user * @param {import('vue').Ref} deps.currentUser - reactive ref to the current user
* @param {Function} deps.applyGroupMember - function to apply group member data * @param {Function} deps.applyGroupMember - function to apply group member data
* @param {Function} deps.handleGroupMember - function to handle group member updates * @param {Function} deps.handleGroupMember - function to handle group member updates
* @param {Function} deps.t - i18n translation function * @param {Function} deps.t - i18n translation function
* @returns {Object} members composable API * @returns {object} members composable API
*/ */
export function useGroupMembers( export function useGroupMembers(
groupDialog, groupDialog,
@@ -185,8 +186,8 @@ export function useGroupMembers(
loadMoreGroupMembersParams.value.roleId = D.memberFilter.id; loadMoreGroupMembersParams.value.roleId = D.memberFilter.id;
} }
if (D.inGroup) { if (D.inGroup) {
await groupRequest await queryRequest
.getCachedGroupMember({ .fetch('groupMember', {
groupId: D.id, groupId: D.id,
userId: currentUser.value.id userId: currentUser.value.id
}) })
@@ -219,8 +220,8 @@ export function useGroupMembers(
} }
D.memberSearch = ''; D.memberSearch = '';
isGroupMembersLoading.value = true; isGroupMembersLoading.value = true;
await groupRequest await queryRequest
.getCachedGroupMembers(params) .fetch('groupMembers', params)
.finally(() => { .finally(() => {
isGroupMembersLoading.value = false; isGroupMembersLoading.value = false;
}) })
@@ -278,7 +279,7 @@ export function useGroupMembers(
} }
/** /**
* @param {Object} sortOrder * @param {object} sortOrder
*/ */
async function setGroupMemberSortOrder(sortOrder) { async function setGroupMemberSortOrder(sortOrder) {
const D = groupDialog.value; const D = groupDialog.value;
@@ -290,7 +291,7 @@ export function useGroupMembers(
} }
/** /**
* @param {Object} filter * @param {object} filter
*/ */
async function setGroupMemberFilter(filter) { async function setGroupMemberFilter(filter) {
const D = groupDialog.value; const D = groupDialog.value;
@@ -1,12 +1,14 @@
import { ref } from 'vue'; import { ref } from 'vue';
import { toast } from 'vue-sonner'; import { toast } from 'vue-sonner';
import { debounce } from '../../../shared/utils'; import { debounce } from '../../../shared/utils';
import { queryRequest } from '../../../api';
import * as workerTimers from 'worker-timers'; import * as workerTimers from 'worker-timers';
/** /**
* Composable for group moderation data fetching, member management, * Composable for group moderation data fetching, member management,
* searching, sorting and filtering. * searching, sorting and filtering.
*
* @param {object} deps * @param {object} deps
* @param {import('vue').Ref} deps.groupMemberModeration - store ref * @param {import('vue').Ref} deps.groupMemberModeration - store ref
* @param {import('vue').Ref} deps.currentUser - store ref * @param {import('vue').Ref} deps.currentUser - store ref
@@ -23,7 +25,6 @@ import * as workerTimers from 'worker-timers';
* @param {object} deps.selection.selectedUsers * @param {object} deps.selection.selectedUsers
* @param {Function} deps.selection.setSelectedUsers * @param {Function} deps.selection.setSelectedUsers
* @param {object} deps.groupRequest - API module * @param {object} deps.groupRequest - API module
* @param {object} deps.userRequest - API module
*/ */
export function useGroupModerationData(deps) { export function useGroupModerationData(deps) {
const { const {
@@ -33,8 +34,7 @@ export function useGroupModerationData(deps) {
handleGroupMember, handleGroupMember,
tables, tables,
selection, selection,
groupRequest, groupRequest
userRequest
} = deps; } = deps;
const isGroupMembersLoading = ref(false); const isGroupMembersLoading = ref(false);
@@ -60,6 +60,9 @@ export function useGroupModerationData(deps) {
// ── Members ────────────────────────────────────────────────── // ── Members ──────────────────────────────────────────────────
/**
*
*/
async function getGroupMembers() { async function getGroupMembers() {
members.value = []; members.value = [];
isGroupMembersDone.value = false; isGroupMembersDone.value = false;
@@ -94,6 +97,9 @@ export function useGroupModerationData(deps) {
await loadMoreGroupMembers(); await loadMoreGroupMembers();
} }
/**
*
*/
async function loadMoreGroupMembers() { async function loadMoreGroupMembers() {
if (isGroupMembersDone.value || isGroupMembersLoading.value) { if (isGroupMembersDone.value || isGroupMembersLoading.value) {
return; return;
@@ -119,7 +125,10 @@ export function useGroupModerationData(deps) {
for (let i = 0; i < args.json.length; i++) { for (let i = 0; i < args.json.length; i++) {
const member = args.json[i]; const member = args.json[i];
if (member.userId === currentUser.value.id) { if (member.userId === currentUser.value.id) {
if (members.value.length > 0 && members.value[0].userId === currentUser.value.id) { if (
members.value.length > 0 &&
members.value[0].userId === currentUser.value.id
) {
members.value.splice(0, 1); members.value.splice(0, 1);
} }
break; break;
@@ -142,12 +151,18 @@ export function useGroupModerationData(deps) {
}); });
} }
/**
*
*/
async function loadAllGroupMembers() { async function loadAllGroupMembers() {
if (isGroupMembersLoading.value) { if (isGroupMembersLoading.value) {
return; return;
} }
await getGroupMembers(); await getGroupMembers();
while (groupMemberModeration.value.visible && !isGroupMembersDone.value) { while (
groupMemberModeration.value.visible &&
!isGroupMembersDone.value
) {
isGroupMembersLoading.value = true; isGroupMembersLoading.value = true;
await new Promise((resolve) => { await new Promise((resolve) => {
workerTimers.setTimeout(resolve, 1000); workerTimers.setTimeout(resolve, 1000);
@@ -157,6 +172,10 @@ export function useGroupModerationData(deps) {
} }
} }
/**
*
* @param sortOrder
*/
async function setGroupMemberSortOrder(sortOrder) { async function setGroupMemberSortOrder(sortOrder) {
if (memberSortOrder.value === sortOrder) { if (memberSortOrder.value === sortOrder) {
return; return;
@@ -165,6 +184,10 @@ export function useGroupModerationData(deps) {
await getGroupMembers(); await getGroupMembers();
} }
/**
*
* @param filter
*/
async function setGroupMemberFilter(filter) { async function setGroupMemberFilter(filter) {
if (memberFilter.value === filter) { if (memberFilter.value === filter) {
return; return;
@@ -173,6 +196,9 @@ export function useGroupModerationData(deps) {
await getGroupMembers(); await getGroupMembers();
} }
/**
*
*/
function groupMembersSearch() { function groupMembersSearch() {
if (memberSearch.value.length < 3) { if (memberSearch.value.length < 3) {
tables.members.data = []; tables.members.data = [];
@@ -183,6 +209,9 @@ export function useGroupModerationData(deps) {
debounce(groupMembersSearchDebounced, 200)(); debounce(groupMembersSearchDebounced, 200)();
} }
/**
*
*/
function groupMembersSearchDebounced() { function groupMembersSearchDebounced() {
const groupId = groupMemberModeration.value.id; const groupId = groupMemberModeration.value.id;
const search = memberSearch.value; const search = memberSearch.value;
@@ -208,7 +237,9 @@ export function useGroupModerationData(deps) {
if (groupId === args.params.groupId) { if (groupId === args.params.groupId) {
tables.members.data = args.json.results.map((member) => ({ tables.members.data = args.json.results.map((member) => ({
...member, ...member,
$selected: Boolean(selection.selectedUsers[member.userId]) $selected: Boolean(
selection.selectedUsers[member.userId]
)
})); }));
} }
}) })
@@ -219,6 +250,10 @@ export function useGroupModerationData(deps) {
// ── Bans ───────────────────────────────────────────────────── // ── Bans ─────────────────────────────────────────────────────
/**
*
* @param groupId
*/
async function getAllGroupBans(groupId) { async function getAllGroupBans(groupId) {
tables.bans.data = []; tables.bans.data = [];
const params = { groupId, n: 100, offset: 0 }; const params = { groupId, n: 100, offset: 0 };
@@ -229,7 +264,9 @@ export function useGroupModerationData(deps) {
for (let i = 0; i < count; i++) { for (let i = 0; i < count; i++) {
const args = await groupRequest.getGroupBans(params); const args = await groupRequest.getGroupBans(params);
if (args && args.json) { if (args && args.json) {
if (groupMemberModeration.value.id !== args.params.groupId) { if (
groupMemberModeration.value.id !== args.params.groupId
) {
continue; continue;
} }
args.json.forEach((json) => { args.json.forEach((json) => {
@@ -257,6 +294,10 @@ export function useGroupModerationData(deps) {
// ── Invites / Join Requests / Blocked ──────────────────────── // ── Invites / Join Requests / Blocked ────────────────────────
/**
*
* @param groupId
*/
async function getAllGroupInvites(groupId) { async function getAllGroupInvites(groupId) {
tables.invites.data = []; tables.invites.data = [];
const params = { groupId, n: 100, offset: 0 }; const params = { groupId, n: 100, offset: 0 };
@@ -267,7 +308,9 @@ export function useGroupModerationData(deps) {
for (let i = 0; i < count; i++) { for (let i = 0; i < count; i++) {
const args = await groupRequest.getGroupInvites(params); const args = await groupRequest.getGroupInvites(params);
if (args) { if (args) {
if (groupMemberModeration.value.id !== args.params.groupId) { if (
groupMemberModeration.value.id !== args.params.groupId
) {
return; return;
} }
for (const json of args.json) { for (const json of args.json) {
@@ -291,6 +334,10 @@ export function useGroupModerationData(deps) {
} }
} }
/**
*
* @param groupId
*/
async function getAllGroupJoinRequests(groupId) { async function getAllGroupJoinRequests(groupId) {
tables.joinRequests.data = []; tables.joinRequests.data = [];
const params = { groupId, n: 100, offset: 0, blocked: false }; const params = { groupId, n: 100, offset: 0, blocked: false };
@@ -323,6 +370,10 @@ export function useGroupModerationData(deps) {
} }
} }
/**
*
* @param groupId
*/
async function getAllGroupBlockedRequests(groupId) { async function getAllGroupBlockedRequests(groupId) {
tables.blocked.data = []; tables.blocked.data = [];
const params = { groupId, n: 100, offset: 0, blocked: true }; const params = { groupId, n: 100, offset: 0, blocked: true };
@@ -355,6 +406,10 @@ export function useGroupModerationData(deps) {
} }
} }
/**
*
* @param groupId
*/
async function getAllGroupInvitesAndJoinRequests(groupId) { async function getAllGroupInvitesAndJoinRequests(groupId) {
try { try {
await Promise.all([ await Promise.all([
@@ -369,6 +424,11 @@ export function useGroupModerationData(deps) {
// ── Logs ───────────────────────────────────────────────────── // ── Logs ─────────────────────────────────────────────────────
/**
*
* @param groupId
* @param eventTypes
*/
async function getAllGroupLogs(groupId, eventTypes = []) { async function getAllGroupLogs(groupId, eventTypes = []) {
tables.logs.data = []; tables.logs.data = [];
const params = { groupId, n: 100, offset: 0 }; const params = { groupId, n: 100, offset: 0 };
@@ -382,11 +442,15 @@ export function useGroupModerationData(deps) {
for (let i = 0; i < count; i++) { for (let i = 0; i < count; i++) {
const args = await groupRequest.getGroupLogs(params); const args = await groupRequest.getGroupLogs(params);
if (args) { if (args) {
if (groupMemberModeration.value.id !== args.params.groupId) { if (
groupMemberModeration.value.id !== args.params.groupId
) {
continue; continue;
} }
for (const json of args.json.results) { for (const json of args.json.results) {
const existsInData = newData.some((dataItem) => dataItem.id === json.id); const existsInData = newData.some(
(dataItem) => dataItem.id === json.id
);
if (!existsInData) { if (!existsInData) {
newData.push(json); newData.push(json);
} }
@@ -410,10 +474,17 @@ export function useGroupModerationData(deps) {
// ── User Selection ─────────────────────────────────────────── // ── User Selection ───────────────────────────────────────────
/**
*
* @param userId
*/
async function addGroupMemberToSelection(userId) { async function addGroupMemberToSelection(userId) {
const D = groupMemberModeration.value; const D = groupMemberModeration.value;
let member = {}; let member = {};
const memberArgs = await groupRequest.getGroupMember({ groupId: D.id, userId }); const memberArgs = await groupRequest.getGroupMember({
groupId: D.id,
userId
});
if (memberArgs && memberArgs.json) { if (memberArgs && memberArgs.json) {
member = applyGroupMember(memberArgs.json); member = applyGroupMember(memberArgs.json);
} }
@@ -421,16 +492,21 @@ export function useGroupModerationData(deps) {
selection.setSelectedUsers(member.userId, member); selection.setSelectedUsers(member.userId, member);
return; return;
} }
const userArgs = await userRequest.getCachedUser({ userId }); const userArgs = await queryRequest.fetch('user', { userId });
member.userId = userArgs.json.id; member.userId = userArgs.json.id;
member.user = userArgs.json; member.user = userArgs.json;
member.displayName = userArgs.json.displayName; member.displayName = userArgs.json.displayName;
selection.setSelectedUsers(member.userId, member); selection.setSelectedUsers(member.userId, member);
} }
/**
*
* @param userIdInput
*/
async function selectGroupMemberUserId(userIdInput) { async function selectGroupMemberUserId(userIdInput) {
if (!userIdInput) return; if (!userIdInput) return;
const regexUserId = /usr_[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}/g; const regexUserId =
/usr_[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}/g;
let match; let match;
const userIdList = new Set(); const userIdList = new Set();
while ((match = regexUserId.exec(userIdInput)) !== null) { while ((match = regexUserId.exec(userIdInput)) !== null) {
@@ -448,6 +524,9 @@ export function useGroupModerationData(deps) {
// ── Reset ──────────────────────────────────────────────────── // ── Reset ────────────────────────────────────────────────────
/**
*
*/
function resetData() { function resetData() {
tables.members.data = []; tables.members.data = [];
tables.bans.data = []; tables.bans.data = [];
+6 -6
View File
@@ -98,7 +98,7 @@
import { hasGroupPermission, userImage, userStatusClass } from '../../shared/utils'; import { hasGroupPermission, userImage, userStatusClass } from '../../shared/utils';
import { useFriendStore, useGroupStore, useModalStore } from '../../stores'; import { useFriendStore, useGroupStore, useModalStore } from '../../stores';
import { groupRequest, userRequest } from '../../api'; import { groupRequest, queryRequest } from '../../api';
import { VirtualCombobox } from '../ui/virtual-combobox'; import { VirtualCombobox } from '../ui/virtual-combobox';
import configRepository from '../../service/config'; import configRepository from '../../service/config';
@@ -224,8 +224,8 @@
inviteGroupDialog.value.groupName = ''; inviteGroupDialog.value.groupName = '';
return; return;
} }
groupRequest queryRequest
.getCachedGroup({ groupId }) .fetch('group', { groupId })
.then((args) => { .then((args) => {
inviteGroupDialog.value.groupName = args.ref.name; inviteGroupDialog.value.groupName = args.ref.name;
}) })
@@ -242,8 +242,8 @@
function initDialog() { function initDialog() {
const D = inviteGroupDialog.value; const D = inviteGroupDialog.value;
if (D.groupId) { if (D.groupId) {
groupRequest queryRequest
.getCachedGroup({ .fetch('group', {
groupId: D.groupId groupId: D.groupId
}) })
.then((args) => { .then((args) => {
@@ -256,7 +256,7 @@
} }
if (D.userId) { if (D.userId) {
userRequest.getCachedUser({ userId: D.userId }).then((args) => { queryRequest.fetch('user', { userId: D.userId }).then((args) => {
D.userObject = args.ref; D.userObject = args.ref;
D.userIds = [D.userId]; D.userIds = [D.userId];
}); });
+47 -3
View File
@@ -162,7 +162,7 @@
useModalStore useModalStore
} from '../../stores'; } from '../../stores';
import { checkCanInvite, getLaunchURL, isRealInstance, parseLocation } from '../../shared/utils'; import { checkCanInvite, getLaunchURL, isRealInstance, parseLocation } from '../../shared/utils';
import { instanceRequest, worldRequest } from '../../api'; import { instanceRequest, queryRequest } from '../../api';
import InviteDialog from './InviteDialog/InviteDialog.vue'; import InviteDialog from './InviteDialog/InviteDialog.vue';
import configRepository from '../../service/config'; import configRepository from '../../service/config';
@@ -230,16 +230,23 @@
getConfig(); getConfig();
/**
*
*/
function closeInviteDialog() { function closeInviteDialog() {
inviteDialog.value.visible = false; inviteDialog.value.visible = false;
} }
/**
*
* @param tag
*/
function showInviteDialog(tag) { function showInviteDialog(tag) {
if (!isRealInstance(tag)) { if (!isRealInstance(tag)) {
return; return;
} }
const L = parseLocation(tag); const L = parseLocation(tag);
worldRequest queryRequest
.getCachedWorld({ .fetch('world', {
worldId: L.worldId worldId: L.worldId
}) })
.then((args) => { .then((args) => {
@@ -259,6 +266,12 @@
D.visible = true; D.visible = true;
}); });
} }
/**
*
* @param location
* @param shortName
* @param desktop
*/
function handleLaunchGame(location, shortName, desktop) { function handleLaunchGame(location, shortName, desktop) {
if (isGameRunning.value) { if (isGameRunning.value) {
modalStore modalStore
@@ -280,10 +293,21 @@
isVisible.value = false; isVisible.value = false;
} }
/**
*
* @param location
* @param shortName
*/
function handleLaunchDefault(location, shortName) { function handleLaunchDefault(location, shortName) {
handleLaunchGame(location, shortName, launchDialog.value.desktop); handleLaunchGame(location, shortName, launchDialog.value.desktop);
} }
/**
*
* @param command
* @param location
* @param shortName
*/
function handleLaunchCommand(command, location, shortName) { function handleLaunchCommand(command, location, shortName) {
const desktop = command === 'desktop'; const desktop = command === 'desktop';
configRepository.setBool('launchAsDesktop', desktop); configRepository.setBool('launchAsDesktop', desktop);
@@ -293,10 +317,20 @@
launchDialog.value.desktop = desktop; launchDialog.value.desktop = desktop;
}, 500); }, 500);
} }
/**
*
* @param location
* @param shortName
*/
function handleAttachGame(location, shortName) { function handleAttachGame(location, shortName) {
tryOpenInstanceInVrc(location, shortName); tryOpenInstanceInVrc(location, shortName);
isVisible.value = false; isVisible.value = false;
} }
/**
*
* @param location
* @param shortName
*/
function selfInvite(location, shortName) { function selfInvite(location, shortName) {
const L = parseLocation(location); const L = parseLocation(location);
if (!L.isRealInstance) { if (!L.isRealInstance) {
@@ -314,9 +348,15 @@
}); });
} }
/**
*
*/
function getConfig() { function getConfig() {
configRepository.getBool('launchAsDesktop').then((value) => (launchDialog.value.desktop = value)); configRepository.getBool('launchAsDesktop').then((value) => (launchDialog.value.desktop = value));
} }
/**
*
*/
async function initLaunchDialog() { async function initLaunchDialog() {
const { tag, shortName } = launchDialogData.value; const { tag, shortName } = launchDialogData.value;
if (!isRealInstance(tag)) { if (!isRealInstance(tag)) {
@@ -361,6 +401,10 @@
} }
} }
} }
/**
*
* @param input
*/
async function copyInstanceMessage(input) { async function copyInstanceMessage(input) {
try { try {
await navigator.clipboard.writeText(input); await navigator.clipboard.writeText(input);
@@ -63,9 +63,9 @@
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { groupRequest, userRequest } from '../../api';
import { hasGroupModerationPermission, userImage } from '../../shared/utils'; import { hasGroupModerationPermission, userImage } from '../../shared/utils';
import { VirtualCombobox } from '../ui/virtual-combobox'; import { VirtualCombobox } from '../ui/virtual-combobox';
import { queryRequest } from '../../api';
import { useGroupStore } from '../../stores'; import { useGroupStore } from '../../stores';
const { currentUserGroups, moderateGroupDialog } = storeToRefs(useGroupStore()); const { currentUserGroups, moderateGroupDialog } = storeToRefs(useGroupStore());
@@ -114,8 +114,8 @@
function initDialog() { function initDialog() {
const D = moderateGroupDialog.value; const D = moderateGroupDialog.value;
if (D.groupId) { if (D.groupId) {
groupRequest queryRequest
.getCachedGroup({ .fetch('group', {
groupId: D.groupId groupId: D.groupId
}) })
.then((args) => { .then((args) => {
@@ -127,7 +127,7 @@
} }
if (D.userId) { if (D.userId) {
userRequest.getCachedUser({ userId: D.userId }).then((args) => { queryRequest.fetch('user', { userId: D.userId }).then((args) => {
D.userObject = args.ref; D.userObject = args.ref;
}); });
} }
+3 -3
View File
@@ -580,7 +580,7 @@
useUserStore useUserStore
} from '../../stores'; } from '../../stores';
import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from '../ui/select'; import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from '../ui/select';
import { groupRequest, instanceRequest, worldRequest } from '../../api'; import { groupRequest, instanceRequest, queryRequest } from '../../api';
import { ToggleGroup, ToggleGroupItem } from '../ui/toggle-group'; import { ToggleGroup, ToggleGroupItem } from '../ui/toggle-group';
import { VirtualCombobox } from '../ui/virtual-combobox'; import { VirtualCombobox } from '../ui/virtual-combobox';
@@ -797,8 +797,8 @@
return; return;
} }
const L = parseLocation(tag); const L = parseLocation(tag);
worldRequest queryRequest
.getCachedWorld({ .fetch('world', {
worldId: L.worldId worldId: L.worldId
}) })
.then((args) => { .then((args) => {
+2 -2
View File
@@ -75,7 +75,7 @@
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { miscRequest, notificationRequest, userRequest } from '../../api'; import { miscRequest, notificationRequest, queryRequest } from '../../api';
import { useGalleryStore, useNotificationStore, useUserStore } from '../../stores'; import { useGalleryStore, useNotificationStore, useUserStore } from '../../stores';
import { VirtualCombobox } from '../ui/virtual-combobox'; import { VirtualCombobox } from '../ui/virtual-combobox';
import { photonEmojis } from '../../shared/constants/photon.js'; import { photonEmojis } from '../../shared/constants/photon.js';
@@ -99,7 +99,7 @@
(visible) => { (visible) => {
if (visible) { if (visible) {
displayName.value = ''; displayName.value = '';
userRequest.getCachedUser({ userId: sendBoopDialog.value.userId }).then((user) => { queryRequest.fetch('user', { userId: sendBoopDialog.value.userId }).then((user) => {
displayName.value = user.ref.displayName; displayName.value = user.ref.displayName;
}); });
} }
@@ -76,7 +76,7 @@
import DeprecationAlert from '@/components/DeprecationAlert.vue'; import DeprecationAlert from '@/components/DeprecationAlert.vue';
import { useFavoriteStore, useUserStore, useWorldStore } from '../../../stores'; import { useFavoriteStore, useUserStore, useWorldStore } from '../../../stores';
import { favoriteRequest } from '../../../api'; import { queryRequest } from '../../../api';
const { t } = useI18n(); const { t } = useI18n();
@@ -121,7 +121,7 @@
favoriteWorldsTab.value = '0'; favoriteWorldsTab.value = '0';
userDialog.value.userFavoriteWorlds = []; userDialog.value.userFavoriteWorlds = [];
const worldLists = []; const worldLists = [];
const groupArgs = await favoriteRequest.getCachedFavoriteGroups({ const groupArgs = await queryRequest.fetch('favoriteGroups', {
ownerId: userId, ownerId: userId,
n: 100, n: 100,
offset: 0 offset: 0
@@ -145,7 +145,7 @@
tag: list.name tag: list.name
}; };
try { try {
const args = await favoriteRequest.getCachedFavoriteWorlds(params); const args = await queryRequest.fetch('favoriteWorlds', params);
handleFavoriteWorldList(args); handleFavoriteWorldList(args);
return [list.displayName, list.visibility, args.json]; return [list.displayName, list.visibility, args.json];
} catch (err) { } catch (err) {
@@ -87,8 +87,8 @@
import { useUserStore, useWorldStore } from '../../../stores'; import { useUserStore, useWorldStore } from '../../../stores';
import { userDialogWorldOrderOptions, userDialogWorldSortingOptions } from '../../../shared/constants/'; import { userDialogWorldOrderOptions, userDialogWorldSortingOptions } from '../../../shared/constants/';
import { queryRequest } from '../../../api';
import { useOptionKeySelect } from '../../../composables/useOptionKeySelect'; import { useOptionKeySelect } from '../../../composables/useOptionKeySelect';
import { worldRequest } from '../../../api';
const { t } = useI18n(); const { t } = useI18n();
@@ -141,7 +141,7 @@
try { try {
let offset = 0; let offset = 0;
while (true) { while (true) {
const args = await worldRequest.getCachedWorlds({ const args = await queryRequest.fetch('worldsByUser', {
...params, ...params,
offset offset
}); });
@@ -6,7 +6,7 @@ import {
miscRequest, miscRequest,
notificationRequest, notificationRequest,
playerModerationRequest, playerModerationRequest,
worldRequest queryRequest
} from '../../../api'; } from '../../../api';
import { copyToClipboard, parseLocation } from '../../../shared/utils'; import { copyToClipboard, parseLocation } from '../../../shared/utils';
import { database } from '../../../service/database'; import { database } from '../../../service/database';
@@ -259,8 +259,8 @@ export function useUserDialogCommands(
}, },
'Invite Message': () => { 'Invite Message': () => {
const L = parseLocation(lastLocation.value.location); const L = parseLocation(lastLocation.value.location);
worldRequest queryRequest
.getCachedWorld({ .fetch('world', {
worldId: L.worldId worldId: L.worldId
}) })
.then((args) => { .then((args) => {
@@ -288,8 +288,8 @@ export function useUserDialogCommands(
currentLocation = lastLocationDestination.value; currentLocation = lastLocationDestination.value;
} }
const L = parseLocation(currentLocation); const L = parseLocation(currentLocation);
worldRequest queryRequest
.getCachedWorld({ .fetch('world', {
worldId: L.worldId worldId: L.worldId
}) })
.then((args) => { .then((args) => {
+51
View File
@@ -4,6 +4,7 @@ import {
_entityCacheInternals, _entityCacheInternals,
fetchWithEntityPolicy, fetchWithEntityPolicy,
patchAndRefetchActiveQuery, patchAndRefetchActiveQuery,
patchUserFromEvent,
patchQueryDataWithRecency patchQueryDataWithRecency
} from '../entityCache'; } from '../entityCache';
import { queryClient } from '../client'; import { queryClient } from '../client';
@@ -130,4 +131,54 @@ describe('entity query cache helpers', () => {
false false
); );
}); });
test('internal completeness guard requires params + entity identifier', () => {
expect(_entityCacheInternals.hasCompleteEntityData(undefined)).toBe(
false
);
expect(_entityCacheInternals.hasCompleteEntityData({})).toBe(false);
expect(
_entityCacheInternals.hasCompleteEntityData({
params: {}
})
).toBe(false);
expect(
_entityCacheInternals.hasCompleteEntityData({
params: { userId: 'usr_1' }
})
).toBe(true);
});
test('patchUserFromEvent skips placeholder cache entries', () => {
const queryKey = ['user', 'usr_1'];
queryClient.setQueryData(queryKey, {
params: {}
});
patchUserFromEvent({
id: 'usr_1',
displayName: 'Alice'
});
expect(queryClient.getQueryData(queryKey)).toEqual({
params: {}
});
});
test('patchUserFromEvent patches when query has complete data', () => {
const queryKey = ['user', 'usr_1'];
queryClient.setQueryData(queryKey, {
params: { userId: 'usr_1' },
ref: { id: 'usr_1', displayName: 'Old' },
json: { id: 'usr_1', displayName: 'Old' }
});
patchUserFromEvent({
id: 'usr_1',
displayName: 'New'
});
const data = queryClient.getQueryData(queryKey);
expect(data.ref.displayName).toBe('New');
});
}); });
-10
View File
@@ -50,13 +50,6 @@ describe('query policy configuration', () => {
refetchOnWindowFocus: false refetchOnWindowFocus: false
}); });
expect(entityQueryPolicies.instance).toMatchObject({
staleTime: 0,
gcTime: 10000,
retry: 0,
refetchOnWindowFocus: false
});
expect(entityQueryPolicies.friendList).toMatchObject({ expect(entityQueryPolicies.friendList).toMatchObject({
staleTime: 20000, staleTime: 20000,
gcTime: 90000, gcTime: 90000,
@@ -104,9 +97,6 @@ describe('query policy configuration', () => {
expect(getEntityQueryPolicy('worldCollection')).toBe( expect(getEntityQueryPolicy('worldCollection')).toBe(
entityQueryPolicies.worldCollection entityQueryPolicies.worldCollection
); );
expect(getEntityQueryPolicy('instance')).toBe(
entityQueryPolicies.instance
);
expect(getEntityQueryPolicy('friendList')).toBe( expect(getEntityQueryPolicy('friendList')).toBe(
entityQueryPolicies.friendList entityQueryPolicies.friendList
); );
+57 -28
View File
@@ -15,6 +15,10 @@ const RECENCY_FIELDS = [
'createdAt' 'createdAt'
]; ];
/**
*
* @param data
*/
function getComparableEntity(data) { function getComparableEntity(data) {
if (!data || typeof data !== 'object') { if (!data || typeof data !== 'object') {
return null; return null;
@@ -32,6 +36,10 @@ function getComparableEntity(data) {
return data; return data;
} }
/**
*
* @param value
*/
function parseTimestamp(value) { function parseTimestamp(value) {
if (typeof value === 'number' && Number.isFinite(value)) { if (typeof value === 'number' && Number.isFinite(value)) {
return value; return value;
@@ -45,6 +53,10 @@ function parseTimestamp(value) {
return null; return null;
} }
/**
*
* @param data
*/
function getRecencyTimestamp(data) { function getRecencyTimestamp(data) {
const comparable = getComparableEntity(data); const comparable = getComparableEntity(data);
if (!comparable) { if (!comparable) {
@@ -61,6 +73,11 @@ function getRecencyTimestamp(data) {
return null; return null;
} }
/**
*
* @param currentData
* @param nextData
*/
function shouldReplaceCurrent(currentData, nextData) { function shouldReplaceCurrent(currentData, nextData) {
if (typeof currentData === 'undefined') { if (typeof currentData === 'undefined') {
return true; return true;
@@ -80,6 +97,35 @@ function shouldReplaceCurrent(currentData, nextData) {
return true; return true;
} }
/**
*
* @param data
*/
function hasCompleteEntityData(data) {
if (!data || typeof data !== 'object') {
return false;
}
const params = data.params;
if (!params || typeof params !== 'object') {
return false;
}
const hasEntityId = Boolean(
data?.ref?.id ||
data?.json?.id ||
params.userId ||
params.avatarId ||
params.worldId ||
params.groupId ||
params.fileId ||
params.printId ||
params.inventoryId
);
return hasEntityId;
}
/** /**
* @param {{queryKey: unknown[], nextData: any}} options * @param {{queryKey: unknown[], nextData: any}} options
*/ */
@@ -142,7 +188,8 @@ export async function patchAndRefetchActiveQuery({ queryKey, nextData }) {
export function patchUserFromEvent(ref) { export function patchUserFromEvent(ref) {
if (!ref?.id) return; if (!ref?.id) return;
const queryKey = queryKeys.user(ref.id); const queryKey = queryKeys.user(ref.id);
if (!queryClient.getQueryData(queryKey)) return; const existing = queryClient.getQueryData(queryKey);
if (!hasCompleteEntityData(existing)) return;
patchQueryDataWithRecency({ patchQueryDataWithRecency({
queryKey, queryKey,
nextData: { nextData: {
@@ -160,7 +207,8 @@ export function patchUserFromEvent(ref) {
export function patchAvatarFromEvent(ref) { export function patchAvatarFromEvent(ref) {
if (!ref?.id) return; if (!ref?.id) return;
const queryKey = queryKeys.avatar(ref.id); const queryKey = queryKeys.avatar(ref.id);
if (!queryClient.getQueryData(queryKey)) return; const existing = queryClient.getQueryData(queryKey);
if (!hasCompleteEntityData(existing)) return;
patchQueryDataWithRecency({ patchQueryDataWithRecency({
queryKey, queryKey,
nextData: { nextData: {
@@ -178,7 +226,8 @@ export function patchAvatarFromEvent(ref) {
export function patchWorldFromEvent(ref) { export function patchWorldFromEvent(ref) {
if (!ref?.id) return; if (!ref?.id) return;
const queryKey = queryKeys.world(ref.id); const queryKey = queryKeys.world(ref.id);
if (!queryClient.getQueryData(queryKey)) return; const existing = queryClient.getQueryData(queryKey);
if (!hasCompleteEntityData(existing)) return;
patchQueryDataWithRecency({ patchQueryDataWithRecency({
queryKey, queryKey,
nextData: { nextData: {
@@ -204,7 +253,8 @@ export function patchGroupFromEvent(ref) {
}; };
const keyFalse = queryKeys.group(ref.id, false); const keyFalse = queryKeys.group(ref.id, false);
if (queryClient.getQueryData(keyFalse)) { const existingFalse = queryClient.getQueryData(keyFalse);
if (hasCompleteEntityData(existingFalse)) {
patchQueryDataWithRecency({ patchQueryDataWithRecency({
queryKey: keyFalse, queryKey: keyFalse,
nextData nextData
@@ -212,7 +262,8 @@ export function patchGroupFromEvent(ref) {
} }
const keyTrue = queryKeys.group(ref.id, true); const keyTrue = queryKeys.group(ref.id, true);
if (queryClient.getQueryData(keyTrue)) { const existingTrue = queryClient.getQueryData(keyTrue);
if (hasCompleteEntityData(existingTrue)) {
patchQueryDataWithRecency({ patchQueryDataWithRecency({
queryKey: keyTrue, queryKey: keyTrue,
nextData nextData
@@ -220,30 +271,8 @@ export function patchGroupFromEvent(ref) {
} }
} }
/**
* @param {object} ref
*/
export function patchInstanceFromEvent(ref) {
if (!ref?.id) return;
const [worldId, instanceId] = String(ref.id).split(':');
if (!worldId || !instanceId) return;
const queryKey = queryKeys.instance(worldId, instanceId);
if (!queryClient.getQueryData(queryKey)) return;
patchQueryDataWithRecency({
queryKey,
nextData: {
cache: false,
json: ref,
params: { worldId, instanceId },
ref
}
});
}
export const _entityCacheInternals = { export const _entityCacheInternals = {
hasCompleteEntityData,
getRecencyTimestamp, getRecencyTimestamp,
shouldReplaceCurrent shouldReplaceCurrent
}; };
+5 -2
View File
@@ -1,6 +1,10 @@
export { queryClient } from './client'; export { queryClient } from './client';
export { queryKeys } from './keys'; export { queryKeys } from './keys';
export { entityQueryPolicies, getEntityQueryPolicy, toQueryOptions } from './policies'; export {
entityQueryPolicies,
getEntityQueryPolicy,
toQueryOptions
} from './policies';
export { export {
fetchWithEntityPolicy, fetchWithEntityPolicy,
patchAndRefetchActiveQuery, patchAndRefetchActiveQuery,
@@ -9,6 +13,5 @@ export {
patchAvatarFromEvent, patchAvatarFromEvent,
patchWorldFromEvent, patchWorldFromEvent,
patchGroupFromEvent, patchGroupFromEvent,
patchInstanceFromEvent,
refetchActiveEntityQuery refetchActiveEntityQuery
} from './entityCache'; } from './entityCache';
+38 -7
View File
@@ -2,7 +2,11 @@ export const queryKeys = Object.freeze({
user: (userId) => ['user', userId], user: (userId) => ['user', userId],
avatar: (avatarId) => ['avatar', avatarId], avatar: (avatarId) => ['avatar', avatarId],
world: (worldId) => ['world', worldId], world: (worldId) => ['world', worldId],
group: (groupId, includeRoles = false) => ['group', groupId, Boolean(includeRoles)], group: (groupId, includeRoles = false) => [
'group',
groupId,
Boolean(includeRoles)
],
groupPosts: ({ groupId, n = 100, offset = 0 } = {}) => [ groupPosts: ({ groupId, n = 100, offset = 0 } = {}) => [
'group', 'group',
groupId, groupId,
@@ -12,8 +16,19 @@ export const queryKeys = Object.freeze({
offset: Number(offset) offset: Number(offset)
} }
], ],
groupMember: ({ groupId, userId } = {}) => ['group', groupId, 'member', userId], groupMember: ({ groupId, userId } = {}) => [
groupMembers: ({ groupId, n = 100, offset = 0, sort = '', roleId = '' } = {}) => [ 'group',
groupId,
'member',
userId
],
groupMembers: ({
groupId,
n = 100,
offset = 0,
sort = '',
roleId = ''
} = {}) => [
'group', 'group',
groupId, groupId,
'members', 'members',
@@ -41,7 +56,6 @@ export const queryKeys = Object.freeze({
'calendarEvent', 'calendarEvent',
eventId eventId
], ],
instance: (worldId, instanceId) => ['instance', worldId, instanceId],
worldsByUser: ({ worldsByUser: ({
userId, userId,
n = 50, n = 50,
@@ -91,7 +105,13 @@ export const queryKeys = Object.freeze({
type: String(type || '') type: String(type || '')
} }
], ],
favoriteWorlds: ({ n = 300, offset = 0, ownerId = '', userId = '', tag = '' } = {}) => [ favoriteWorlds: ({
n = 300,
offset = 0,
ownerId = '',
userId = '',
tag = ''
} = {}) => [
'favorite', 'favorite',
'worlds', 'worlds',
{ {
@@ -102,7 +122,13 @@ export const queryKeys = Object.freeze({
tag: String(tag || '') tag: String(tag || '')
} }
], ],
favoriteAvatars: ({ n = 300, offset = 0, tag = '', ownerId = '', userId = '' } = {}) => [ favoriteAvatars: ({
n = 300,
offset = 0,
tag = '',
ownerId = '',
userId = ''
} = {}) => [
'favorite', 'favorite',
'avatars', 'avatars',
{ {
@@ -129,7 +155,12 @@ export const queryKeys = Object.freeze({
} }
], ],
print: (printId) => ['gallery', 'print', printId], print: (printId) => ['gallery', 'print', printId],
inventoryItems: ({ n = 100, offset = 0, order = 'newest', types = '' } = {}) => [ inventoryItems: ({
n = 100,
offset = 0,
order = 'newest',
types = ''
} = {}) => [
'inventory', 'inventory',
'items', 'items',
{ {
+1 -7
View File
@@ -37,12 +37,6 @@ export const entityQueryPolicies = Object.freeze({
retry: 1, retry: 1,
refetchOnWindowFocus: false refetchOnWindowFocus: false
}), }),
instance: Object.freeze({
staleTime: 0,
gcTime: 10 * SECOND,
retry: 0,
refetchOnWindowFocus: false
}),
friendList: Object.freeze({ friendList: Object.freeze({
staleTime: 20 * SECOND, staleTime: 20 * SECOND,
gcTime: 90 * SECOND, gcTime: 90 * SECOND,
@@ -76,7 +70,7 @@ export const entityQueryPolicies = Object.freeze({
}); });
/** /**
* @param {'user'|'avatar'|'world'|'group'|'groupCollection'|'worldCollection'|'instance'|'friendList'|'favoriteCollection'|'galleryCollection'|'inventoryCollection'|'fileObject'} entity * @param {'user'|'avatar'|'world'|'group'|'groupCollection'|'worldCollection'|'friendList'|'favoriteCollection'|'galleryCollection'|'inventoryCollection'|'fileObject'} entity
* @returns {{staleTime: number, gcTime: number, retry: number, refetchOnWindowFocus: boolean}} * @returns {{staleTime: number, gcTime: number, retry: number, refetchOnWindowFocus: boolean}}
*/ */
export function getEntityQueryPolicy(entity) { export function getEntityQueryPolicy(entity) {
+23 -12
View File
@@ -1,9 +1,14 @@
import { useQuery } from '@tanstack/vue-query'; import { useQuery } from '@tanstack/vue-query';
import { avatarRequest, groupRequest, instanceRequest, userRequest, worldRequest } from '../api'; import { avatarRequest, groupRequest, userRequest, worldRequest } from '../api';
import { queryKeys } from './keys';
import { entityQueryPolicies, toQueryOptions } from './policies'; import { entityQueryPolicies, toQueryOptions } from './policies';
import { queryKeys } from './keys';
/**
*
* @param userId
* @param options
*/
export function useUserQuery(userId, options = {}) { export function useUserQuery(userId, options = {}) {
return useQuery({ return useQuery({
...options, ...options,
@@ -14,6 +19,11 @@ export function useUserQuery(userId, options = {}) {
}); });
} }
/**
*
* @param avatarId
* @param options
*/
export function useAvatarQuery(avatarId, options = {}) { export function useAvatarQuery(avatarId, options = {}) {
return useQuery({ return useQuery({
...options, ...options,
@@ -24,6 +34,11 @@ export function useAvatarQuery(avatarId, options = {}) {
}); });
} }
/**
*
* @param worldId
* @param options
*/
export function useWorldQuery(worldId, options = {}) { export function useWorldQuery(worldId, options = {}) {
return useQuery({ return useQuery({
...options, ...options,
@@ -34,6 +49,12 @@ export function useWorldQuery(worldId, options = {}) {
}); });
} }
/**
*
* @param groupId
* @param includeRoles
* @param options
*/
export function useGroupQuery(groupId, includeRoles = false, options = {}) { export function useGroupQuery(groupId, includeRoles = false, options = {}) {
return useQuery({ return useQuery({
...options, ...options,
@@ -43,13 +64,3 @@ export function useGroupQuery(groupId, includeRoles = false, options = {}) {
...toQueryOptions(entityQueryPolicies.group) ...toQueryOptions(entityQueryPolicies.group)
}); });
} }
export function useInstanceQuery(worldId, instanceId, options = {}) {
return useQuery({
...options,
queryKey: queryKeys.instance(worldId, instanceId),
queryFn: () => instanceRequest.getInstance({ worldId, instanceId }),
enabled: Boolean(worldId && instanceId),
...toQueryOptions(entityQueryPolicies.instance)
});
}
+2 -2
View File
@@ -1,5 +1,5 @@
import { groupRequest } from '../../api';
import { parseLocation } from './location'; import { parseLocation } from './location';
import { queryRequest } from '../../api';
/** /**
* *
@@ -59,7 +59,7 @@ async function getGroupName(data) {
} }
} }
try { try {
const args = await groupRequest.getCachedGroup({ const args = await queryRequest.fetch('group', {
groupId groupId
}); });
groupName = args.ref.name; groupName = args.ref.name;
+2 -2
View File
@@ -1,6 +1,6 @@
import { parseLocation } from './location'; import { parseLocation } from './location';
import { queryRequest } from '../../api';
import { rpcWorlds } from '../constants'; import { rpcWorlds } from '../constants';
import { worldRequest } from '../../api';
/** /**
* *
@@ -13,7 +13,7 @@ async function getWorldName(location) {
const L = parseLocation(location); const L = parseLocation(location);
if (L.isRealInstance && L.worldId) { if (L.isRealInstance && L.worldId) {
try { try {
const args = await worldRequest.getCachedWorld({ const args = await queryRequest.fetch('world', {
worldId: L.worldId worldId: L.worldId
}); });
worldName = args.ref.name; worldName = args.ref.name;
+8 -8
View File
@@ -19,8 +19,8 @@ import { createOverlayDispatch } from '../notification/overlayDispatch';
function makeDeps(overrides = {}) { function makeDeps(overrides = {}) {
return { return {
getUserIdFromNoty: vi.fn(() => ''), getUserIdFromNoty: vi.fn(() => ''),
userRequest: { queryRequest: {
getCachedUser: vi.fn().mockResolvedValue({ json: null }) fetch: vi.fn().mockResolvedValue({ json: null })
}, },
notificationsSettingsStore: { notificationsSettingsStore: {
notificationTimeout: 5000 notificationTimeout: 5000
@@ -66,7 +66,7 @@ describe('notyGetImage', () => {
test('looks up user currentAvatarThumbnailImageUrl when no image URLs', async () => { test('looks up user currentAvatarThumbnailImageUrl when no image URLs', async () => {
deps.getUserIdFromNoty.mockReturnValue('usr_abc'); deps.getUserIdFromNoty.mockReturnValue('usr_abc');
deps.userRequest.getCachedUser.mockResolvedValue({ deps.queryRequest.fetch.mockResolvedValue({
json: { json: {
currentAvatarThumbnailImageUrl: 'https://avatar.jpg' currentAvatarThumbnailImageUrl: 'https://avatar.jpg'
} }
@@ -80,7 +80,7 @@ describe('notyGetImage', () => {
test('returns profilePicOverride when available', async () => { test('returns profilePicOverride when available', async () => {
deps.getUserIdFromNoty.mockReturnValue('usr_abc'); deps.getUserIdFromNoty.mockReturnValue('usr_abc');
deps.userRequest.getCachedUser.mockResolvedValue({ deps.queryRequest.fetch.mockResolvedValue({
json: { json: {
profilePicOverride: 'https://profile.jpg', profilePicOverride: 'https://profile.jpg',
currentAvatarThumbnailImageUrl: 'https://avatar.jpg' currentAvatarThumbnailImageUrl: 'https://avatar.jpg'
@@ -95,7 +95,7 @@ describe('notyGetImage', () => {
test('returns userIcon when displayVRCPlusIconsAsAvatar is enabled', async () => { test('returns userIcon when displayVRCPlusIconsAsAvatar is enabled', async () => {
deps.getUserIdFromNoty.mockReturnValue('usr_abc'); deps.getUserIdFromNoty.mockReturnValue('usr_abc');
deps.appearanceSettingsStore.displayVRCPlusIconsAsAvatar = true; deps.appearanceSettingsStore.displayVRCPlusIconsAsAvatar = true;
deps.userRequest.getCachedUser.mockResolvedValue({ deps.queryRequest.fetch.mockResolvedValue({
json: { json: {
userIcon: 'https://icon.jpg', userIcon: 'https://icon.jpg',
profilePicOverride: 'https://profile.jpg', profilePicOverride: 'https://profile.jpg',
@@ -114,12 +114,12 @@ describe('notyGetImage', () => {
const result = await dispatch.notyGetImage({}); const result = await dispatch.notyGetImage({});
expect(result).toBe(''); expect(result).toBe('');
expect(deps.userRequest.getCachedUser).not.toHaveBeenCalled(); expect(deps.queryRequest.fetch).not.toHaveBeenCalled();
}); });
test('returns empty string when user lookup fails', async () => { test('returns empty string when user lookup fails', async () => {
deps.getUserIdFromNoty.mockReturnValue('usr_abc'); deps.getUserIdFromNoty.mockReturnValue('usr_abc');
deps.userRequest.getCachedUser.mockRejectedValue( deps.queryRequest.fetch.mockRejectedValue(
new Error('Network error') new Error('Network error')
); );
dispatch = createOverlayDispatch(deps); dispatch = createOverlayDispatch(deps);
@@ -130,7 +130,7 @@ describe('notyGetImage', () => {
test('returns empty string when user has no json', async () => { test('returns empty string when user has no json', async () => {
deps.getUserIdFromNoty.mockReturnValue('usr_abc'); deps.getUserIdFromNoty.mockReturnValue('usr_abc');
deps.userRequest.getCachedUser.mockResolvedValue({ json: null }); deps.queryRequest.fetch.mockResolvedValue({ json: null });
dispatch = createOverlayDispatch(deps); dispatch = createOverlayDispatch(deps);
const result = await dispatch.notyGetImage({}); const result = await dispatch.notyGetImage({});
+5 -2
View File
@@ -14,7 +14,7 @@ import {
sanitizeEntityJson, sanitizeEntityJson,
storeAvatarImage storeAvatarImage
} from '../shared/utils'; } from '../shared/utils';
import { avatarRequest, miscRequest } from '../api'; import { avatarRequest, miscRequest, queryRequest } from '../api';
import { AppDebug } from '../service/appConfig'; import { AppDebug } from '../service/appConfig';
import { database } from '../service/database'; import { database } from '../service/database';
import { patchAvatarFromEvent } from '../queries'; import { patchAvatarFromEvent } from '../queries';
@@ -174,7 +174,7 @@ export const useAvatarStore = defineStore('Avatar', () => {
} }
const loadAvatarRequest = forceRefresh const loadAvatarRequest = forceRefresh
? avatarRequest.getAvatar({ avatarId }) ? avatarRequest.getAvatar({ avatarId })
: avatarRequest.getCachedAvatar({ avatarId }); : queryRequest.fetch('avatar', { avatarId });
loadAvatarRequest loadAvatarRequest
.then((args) => { .then((args) => {
const ref = applyAvatar(args.json); const ref = applyAvatar(args.json);
@@ -312,6 +312,9 @@ export const useAvatarStore = defineStore('Avatar', () => {
return ref; return ref;
} }
/**
*
*/
function resetCachedAvatarModerations() { function resetCachedAvatarModerations() {
cachedAvatarModerations.clear(); cachedAvatarModerations.clear();
} }
+4 -4
View File
@@ -10,7 +10,7 @@ import {
removeFromArray, removeFromArray,
replaceReactiveObject replaceReactiveObject
} from '../shared/utils'; } from '../shared/utils';
import { avatarRequest, favoriteRequest } from '../api'; import { avatarRequest, favoriteRequest, queryRequest } from '../api';
import { database } from '../service/database'; import { database } from '../service/database';
import { processBulk } from '../service/request'; import { processBulk } from '../service/request';
import { useAppearanceSettingsStore } from './settings/appearance'; import { useAppearanceSettingsStore } from './settings/appearance';
@@ -771,7 +771,7 @@ export const useFavoriteStore = defineStore('Favorite', () => {
} }
isFavoriteLoading.value = true; isFavoriteLoading.value = true;
try { try {
const args = await favoriteRequest.getCachedFavoriteLimits(); const args = await queryRequest.fetch('favoriteLimits');
favoriteLimits.value = { favoriteLimits.value = {
...favoriteLimits.value, ...favoriteLimits.value,
...args.json ...args.json
@@ -781,7 +781,7 @@ export const useFavoriteStore = defineStore('Favorite', () => {
} }
let newFavoriteSortOrder = []; let newFavoriteSortOrder = [];
processBulk({ processBulk({
fn: favoriteRequest.getCachedFavorites, fn: (params) => queryRequest.fetch('favorites', params),
N: -1, N: -1,
params: { params: {
n: 300, n: 300,
@@ -884,7 +884,7 @@ export const useFavoriteStore = defineStore('Favorite', () => {
offset: 0, offset: 0,
tag tag
}; };
const args = await favoriteRequest.getCachedFavoriteAvatars(params); const args = await queryRequest.fetch('favoriteAvatars', params);
handleFavoriteAvatarList(args); handleFavoriteAvatarList(args);
} }
+90 -3
View File
@@ -16,7 +16,7 @@ import {
isRealInstance, isRealInstance,
migrateMemos migrateMemos
} from '../shared/utils'; } from '../shared/utils';
import { friendRequest, userRequest } from '../api'; import { friendRequest, queryRequest, userRequest } from '../api';
import { AppDebug } from '../service/appConfig'; import { AppDebug } from '../service/appConfig';
import { createFriendPresenceCoordinator } from './coordinators/friendPresenceCoordinator'; import { createFriendPresenceCoordinator } from './coordinators/friendPresenceCoordinator';
import { createFriendRelationshipCoordinator } from './coordinators/friendRelationshipCoordinator'; import { createFriendRelationshipCoordinator } from './coordinators/friendRelationshipCoordinator';
@@ -259,6 +259,9 @@ export const useFriendStore = defineStore('Friend', () => {
{ flush: 'sync' } { flush: 'sync' }
); );
/**
*
*/
async function init() { async function init() {
const friendLogTableFiltersValue = JSON.parse( const friendLogTableFiltersValue = JSON.parse(
await configRepository.getString('VRCX_friendLogTableFilters', '[]') await configRepository.getString('VRCX_friendLogTableFilters', '[]')
@@ -268,6 +271,10 @@ export const useFriendStore = defineStore('Friend', () => {
init(); init();
/**
*
* @param ref
*/
function updateUserCurrentStatus(ref) { function updateUserCurrentStatus(ref) {
if (watchState.isFriendsLoaded) { if (watchState.isFriendsLoaded) {
refreshFriendsStatus(ref); refreshFriendsStatus(ref);
@@ -281,6 +288,10 @@ export const useFriendStore = defineStore('Friend', () => {
} }
} }
/**
*
* @param args
*/
function handleFriendStatus(args) { function handleFriendStatus(args) {
const D = userStore.userDialog; const D = userStore.userDialog;
if (D.visible === false || D.id !== args.params.userId) { if (D.visible === false || D.id !== args.params.userId) {
@@ -292,6 +303,10 @@ export const useFriendStore = defineStore('Friend', () => {
D.outgoingRequest = json.outgoingRequest; D.outgoingRequest = json.outgoingRequest;
} }
/**
*
* @param args
*/
function handleFriendDelete(args) { function handleFriendDelete(args) {
const D = userStore.userDialog; const D = userStore.userDialog;
if (D.visible === false || D.id !== args.params.userId) { if (D.visible === false || D.id !== args.params.userId) {
@@ -302,11 +317,19 @@ export const useFriendStore = defineStore('Friend', () => {
deleteFriend(args.params.userId); deleteFriend(args.params.userId);
} }
/**
*
* @param args
*/
function handleFriendAdd(args) { function handleFriendAdd(args) {
addFriendship(args.params.userId); addFriendship(args.params.userId);
addFriend(args.params.userId); addFriend(args.params.userId);
} }
/**
*
* @param ref
*/
function userOnFriend(ref) { function userOnFriend(ref) {
updateFriendship(ref); updateFriendship(ref);
if ( if (
@@ -337,6 +360,9 @@ export const useFriendStore = defineStore('Friend', () => {
return ''; return '';
} }
/**
*
*/
function updateLocalFavoriteFriends() { function updateLocalFavoriteFriends() {
const favoriteStore = useFavoriteStore(); const favoriteStore = useFavoriteStore();
localFavoriteFriends.clear(); localFavoriteFriends.clear();
@@ -365,6 +391,9 @@ export const useFriendStore = defineStore('Friend', () => {
updateSidebarFavorites(); updateSidebarFavorites();
} }
/**
*
*/
function updateSidebarFavorites() { function updateSidebarFavorites() {
for (const ctx of friends.values()) { for (const ctx of friends.values()) {
const isVIP = localFavoriteFriends.has(ctx.id); const isVIP = localFavoriteFriends.has(ctx.id);
@@ -383,6 +412,9 @@ export const useFriendStore = defineStore('Friend', () => {
friendPresenceCoordinator.runUpdateFriendFlow(id, stateInput); friendPresenceCoordinator.runUpdateFriendFlow(id, stateInput);
} }
/**
*
*/
async function pendingOfflineWorkerFunction() { async function pendingOfflineWorkerFunction() {
pendingOfflineWorker = workerTimers.setInterval(() => { pendingOfflineWorker = workerTimers.setInterval(() => {
friendPresenceCoordinator.runPendingOfflineTickFlow(); friendPresenceCoordinator.runPendingOfflineTickFlow();
@@ -510,7 +542,7 @@ export const useFriendStore = defineStore('Friend', () => {
} }
/** /**
* @param {Object} args * @param {object} args
* @returns {Promise<*[]>} * @returns {Promise<*[]>}
*/ */
async function bulkRefreshFriends(args) { async function bulkRefreshFriends(args) {
@@ -528,10 +560,14 @@ export const useFriendStore = defineStore('Friend', () => {
intervalMs: 60_000 intervalMs: 60_000
}); });
/**
*
* @param offset
*/
async function fetchPage(offset) { async function fetchPage(offset) {
const result = await executeWithBackoff( const result = await executeWithBackoff(
async () => { async () => {
const { json } = await friendRequest.getCachedFriends({ const { json } = await queryRequest.fetch('friends', {
...args, ...args,
n: PAGE_SIZE, n: PAGE_SIZE,
offset offset
@@ -553,6 +589,9 @@ export const useFriendStore = defineStore('Friend', () => {
let stopFlag = false; let stopFlag = false;
const friends = []; const friends = [];
/**
*
*/
function getNextOffset() { function getNextOffset() {
if (stopFlag) return null; if (stopFlag) return null;
const cur = nextOffset; const cur = nextOffset;
@@ -561,6 +600,9 @@ export const useFriendStore = defineStore('Friend', () => {
return cur; return cur;
} }
/**
*
*/
async function worker() { async function worker() {
while (true) { while (true) {
const offset = getNextOffset(); const offset = getNextOffset();
@@ -660,6 +702,10 @@ export const useFriendStore = defineStore('Friend', () => {
await friendSyncCoordinator.runRefreshFriendsListFlow(); await friendSyncCoordinator.runRefreshFriendsListFlow();
} }
/**
*
* @param forceUpdate
*/
function updateOnlineFriendCounter(forceUpdate = false) { function updateOnlineFriendCounter(forceUpdate = false) {
const onlineFriendCounts = const onlineFriendCounts =
vipFriends.value.length + onlineFriends.value.length; vipFriends.value.length + onlineFriends.value.length;
@@ -672,6 +718,9 @@ export const useFriendStore = defineStore('Friend', () => {
} }
} }
/**
*
*/
async function getAllUserStats() { async function getAllUserStats() {
let ref; let ref;
let item; let item;
@@ -741,6 +790,9 @@ export const useFriendStore = defineStore('Friend', () => {
} }
} }
/**
*
*/
async function getAllUserMutualCount() { async function getAllUserMutualCount() {
const mutualCountMap = await database.getMutualCountForAllUsers(); const mutualCountMap = await database.getMutualCountForAllUsers();
for (const [userId, mutualCount] of mutualCountMap.entries()) { for (const [userId, mutualCount] of mutualCountMap.entries()) {
@@ -1027,6 +1079,9 @@ export const useFriendStore = defineStore('Friend', () => {
} }
} }
/**
*
*/
async function initFriendLogHistoryTable() { async function initFriendLogHistoryTable() {
friendLogTable.value.loading = true; friendLogTable.value.loading = true;
friendLogTable.value.data = await database.getFriendLogHistory(); friendLogTable.value.data = await database.getFriendLogHistory();
@@ -1052,6 +1107,9 @@ export const useFriendStore = defineStore('Friend', () => {
} }
} }
/**
*
*/
async function tryApplyFriendOrder() { async function tryApplyFriendOrder() {
const lastUpdate = await configRepository.getString( const lastUpdate = await configRepository.getString(
`VRCX_lastStoreTime_${userStore.currentUser.id}` `VRCX_lastStoreTime_${userStore.currentUser.id}`
@@ -1135,6 +1193,9 @@ export const useFriendStore = defineStore('Friend', () => {
); );
} }
/**
*
*/
async function restoreFriendNumber() { async function restoreFriendNumber() {
let message; let message;
let storedData = null; let storedData = null;
@@ -1186,6 +1247,9 @@ export const useFriendStore = defineStore('Friend', () => {
return true; return true;
} }
/**
*
*/
function applyFriendLogFriendOrderInReverse() { function applyFriendLogFriendOrderInReverse() {
state.friendNumber = friends.size + 1; state.friendNumber = friends.size + 1;
const friendLogTable = getFriendLogFriendOrder(); const friendLogTable = getFriendLogFriendOrder();
@@ -1210,6 +1274,9 @@ export const useFriendStore = defineStore('Friend', () => {
console.log('Applied friend order from friendLog'); console.log('Applied friend order from friendLog');
} }
/**
*
*/
function getFriendLogFriendOrder() { function getFriendLogFriendOrder() {
const result = []; const result = [];
for (let i = 0; i < friendLogTable.value.data.length; i++) { for (let i = 0; i < friendLogTable.value.data.length; i++) {
@@ -1235,6 +1302,12 @@ export const useFriendStore = defineStore('Friend', () => {
return result; return result;
} }
/**
*
* @param friendLogTable
* @param created_at
* @param backupUserIds
*/
function parseFriendOrderBackup(friendLogTable, created_at, backupUserIds) { function parseFriendOrderBackup(friendLogTable, created_at, backupUserIds) {
let i; let i;
const backupTable = []; const backupTable = [];
@@ -1296,6 +1369,10 @@ export const useFriendStore = defineStore('Friend', () => {
}; };
} }
/**
*
* @param userIdOrder
*/
function applyFriendOrderBackup(userIdOrder) { function applyFriendOrderBackup(userIdOrder) {
for (let i = 0; i < userIdOrder.length; i++) { for (let i = 0; i < userIdOrder.length; i++) {
const userId = userIdOrder[i]; const userId = userIdOrder[i];
@@ -1316,6 +1393,9 @@ export const useFriendStore = defineStore('Friend', () => {
} }
} }
/**
*
*/
function applyFriendLogFriendOrder() { function applyFriendLogFriendOrder() {
const friendLogTable = getFriendLogFriendOrder(); const friendLogTable = getFriendLogFriendOrder();
if (state.friendNumber === 0) { if (state.friendNumber === 0) {
@@ -1339,6 +1419,10 @@ export const useFriendStore = defineStore('Friend', () => {
} }
} }
/**
*
* @param id
*/
function confirmDeleteFriend(id) { function confirmDeleteFriend(id) {
modalStore modalStore
.confirm({ .confirm({
@@ -1355,6 +1439,9 @@ export const useFriendStore = defineStore('Friend', () => {
.catch(() => {}); .catch(() => {});
} }
/**
*
*/
async function initFriendsList() { async function initFriendsList() {
await friendSyncCoordinator.runInitFriendsListFlow(); await friendSyncCoordinator.runInitFriendsListFlow();
} }
+97 -26
View File
@@ -9,12 +9,7 @@ import {
getPrintLocalDate, getPrintLocalDate,
openExternalLink openExternalLink
} from '../shared/utils'; } from '../shared/utils';
import { import { queryRequest, vrcPlusImageRequest } from '../api';
inventoryRequest,
userRequest,
vrcPlusIconRequest,
vrcPlusImageRequest
} from '../api';
import { AppDebug } from '../service/appConfig'; import { AppDebug } from '../service/appConfig';
import { handleImageUploadInput } from '../shared/utils/imageUpload'; import { handleImageUploadInput } from '../shared/utils/imageUpload';
import { router } from '../plugin/router'; import { router } from '../plugin/router';
@@ -22,8 +17,6 @@ import { useAdvancedSettingsStore } from './settings/advanced';
import { useModalStore } from './modal'; import { useModalStore } from './modal';
import { watchState } from '../service/watchState'; import { watchState } from '../service/watchState';
import miscReq from '../api/misc';
import * as workerTimers from 'worker-timers'; import * as workerTimers from 'worker-timers';
export const useGalleryStore = defineStore('Gallery', () => { export const useGalleryStore = defineStore('Gallery', () => {
@@ -100,6 +93,10 @@ export const useGalleryStore = defineStore('Gallery', () => {
{ flush: 'sync' } { flush: 'sync' }
); );
/**
*
* @param args
*/
function handleFilesList(args) { function handleFilesList(args) {
if (args.params.tag === 'gallery') { if (args.params.tag === 'gallery') {
galleryTable.value = args.json.reverse(); galleryTable.value = args.json.reverse();
@@ -117,12 +114,19 @@ export const useGalleryStore = defineStore('Gallery', () => {
} }
} }
/**
*
* @param args
*/
function handleGalleryImageAdd(args) { function handleGalleryImageAdd(args) {
if (Object.keys(galleryTable.value).length !== 0) { if (Object.keys(galleryTable.value).length !== 0) {
galleryTable.value.unshift(args.json); galleryTable.value.unshift(args.json);
} }
} }
/**
*
*/
function showGalleryPage() { function showGalleryPage() {
galleryDialogVisible.value = true; galleryDialogVisible.value = true;
if (router.currentRoute.value?.name === 'gallery') { if (router.currentRoute.value?.name === 'gallery') {
@@ -132,6 +136,9 @@ export const useGalleryStore = defineStore('Gallery', () => {
router.push({ name: 'gallery' }); router.push({ name: 'gallery' });
} }
/**
*
*/
function loadGalleryData() { function loadGalleryData() {
refreshGalleryTable(); refreshGalleryTable();
refreshVRCPlusIconsTable(); refreshVRCPlusIconsTable();
@@ -141,14 +148,17 @@ export const useGalleryStore = defineStore('Gallery', () => {
getInventory(); getInventory();
} }
/**
*
*/
function refreshGalleryTable() { function refreshGalleryTable() {
galleryDialogGalleryLoading.value = true; galleryDialogGalleryLoading.value = true;
const params = { const params = {
n: 100, n: 100,
tag: 'gallery' tag: 'gallery'
}; };
vrcPlusIconRequest queryRequest
.getCachedFileList(params) .fetch('galleryFiles', params)
.then((args) => handleFilesList(args)) .then((args) => handleFilesList(args))
.catch((error) => { .catch((error) => {
console.error('Error fetching gallery files:', error); console.error('Error fetching gallery files:', error);
@@ -158,14 +168,17 @@ export const useGalleryStore = defineStore('Gallery', () => {
}); });
} }
/**
*
*/
function refreshVRCPlusIconsTable() { function refreshVRCPlusIconsTable() {
galleryDialogIconsLoading.value = true; galleryDialogIconsLoading.value = true;
const params = { const params = {
n: 100, n: 100,
tag: 'icon' tag: 'icon'
}; };
vrcPlusIconRequest queryRequest
.getCachedFileList(params) .fetch('galleryFiles', params)
.then((args) => handleFilesList(args)) .then((args) => handleFilesList(args))
.catch((error) => { .catch((error) => {
console.error('Error fetching VRC Plus icons:', error); console.error('Error fetching VRC Plus icons:', error);
@@ -175,6 +188,10 @@ export const useGalleryStore = defineStore('Gallery', () => {
}); });
} }
/**
*
* @param e
*/
function inviteImageUpload(e) { function inviteImageUpload(e) {
const { file } = handleImageUploadInput(e, { const { file } = handleImageUploadInput(e, {
inputSelector: null, inputSelector: null,
@@ -192,6 +209,9 @@ export const useGalleryStore = defineStore('Gallery', () => {
r.readAsBinaryString(file); r.readAsBinaryString(file);
} }
/**
*
*/
function clearInviteImageUpload() { function clearInviteImageUpload() {
const buttonList = document.querySelectorAll( const buttonList = document.querySelectorAll(
'.inviteImageUploadButton' '.inviteImageUploadButton'
@@ -200,14 +220,17 @@ export const useGalleryStore = defineStore('Gallery', () => {
uploadImage.value = ''; uploadImage.value = '';
} }
/**
*
*/
function refreshStickerTable() { function refreshStickerTable() {
galleryDialogStickersLoading.value = true; galleryDialogStickersLoading.value = true;
const params = { const params = {
n: 100, n: 100,
tag: 'sticker' tag: 'sticker'
}; };
vrcPlusIconRequest queryRequest
.getCachedFileList(params) .fetch('galleryFiles', params)
.then((args) => handleFilesList(args)) .then((args) => handleFilesList(args))
.catch((error) => { .catch((error) => {
console.error('Error fetching stickers:', error); console.error('Error fetching stickers:', error);
@@ -217,12 +240,22 @@ export const useGalleryStore = defineStore('Gallery', () => {
}); });
} }
/**
*
* @param args
*/
function handleStickerAdd(args) { function handleStickerAdd(args) {
if (Object.keys(stickerTable.value).length !== 0) { if (Object.keys(stickerTable.value).length !== 0) {
stickerTable.value.unshift(args.json); stickerTable.value.unshift(args.json);
} }
} }
/**
*
* @param displayName
* @param userId
* @param inventoryId
*/
async function trySaveStickerToFile(displayName, userId, inventoryId) { async function trySaveStickerToFile(displayName, userId, inventoryId) {
if (instanceStickersCache.value.includes(inventoryId)) { if (instanceStickersCache.value.includes(inventoryId)) {
return; return;
@@ -231,7 +264,7 @@ export const useGalleryStore = defineStore('Gallery', () => {
if (instanceStickersCache.value.length > 100) { if (instanceStickersCache.value.length > 100) {
instanceStickersCache.value.shift(); instanceStickersCache.value.shift();
} }
const args = await inventoryRequest.getCachedUserInventoryItem({ const args = await queryRequest.fetch('userInventoryItem', {
inventoryId, inventoryId,
userId userId
}); });
@@ -262,13 +295,16 @@ export const useGalleryStore = defineStore('Gallery', () => {
} }
} }
/**
*
*/
async function refreshPrintTable() { async function refreshPrintTable() {
galleryDialogPrintsLoading.value = true; galleryDialogPrintsLoading.value = true;
const params = { const params = {
n: 100 n: 100
}; };
try { try {
const args = await vrcPlusImageRequest.getCachedPrints(params); const args = await queryRequest.fetch('prints', params);
args.json.sort((a, b) => { args.json.sort((a, b) => {
return ( return (
new Date(b.timestamp).getTime() - new Date(b.timestamp).getTime() -
@@ -283,6 +319,10 @@ export const useGalleryStore = defineStore('Gallery', () => {
} }
} }
/**
*
* @param printId
*/
function queueSavePrintToFile(printId) { function queueSavePrintToFile(printId) {
if (state.printCache.includes(printId)) { if (state.printCache.includes(printId)) {
return; return;
@@ -304,8 +344,12 @@ export const useGalleryStore = defineStore('Gallery', () => {
} }
} }
/**
*
* @param printId
*/
async function trySavePrintToFile(printId) { async function trySavePrintToFile(printId) {
const args = await vrcPlusImageRequest.getCachedPrint({ printId }); const args = await queryRequest.fetch('print', { printId });
const imageUrl = args.json?.files?.image; const imageUrl = args.json?.files?.image;
if (!imageUrl) { if (!imageUrl) {
console.error('Print image URL is missing', args); console.error('Print image URL is missing', args);
@@ -314,7 +358,7 @@ export const useGalleryStore = defineStore('Gallery', () => {
const print = args.json; const print = args.json;
const createdAt = getPrintLocalDate(print); const createdAt = getPrintLocalDate(print);
try { try {
const owner = await userRequest.getCachedUser({ const owner = await queryRequest.fetch('user', {
userId: print.ownerId userId: print.ownerId
}); });
console.log( console.log(
@@ -349,14 +393,17 @@ export const useGalleryStore = defineStore('Gallery', () => {
// #endregion // #endregion
// #region | Emoji // #region | Emoji
/**
*
*/
function refreshEmojiTable() { function refreshEmojiTable() {
galleryDialogEmojisLoading.value = true; galleryDialogEmojisLoading.value = true;
const params = { const params = {
n: 100, n: 100,
tag: 'emoji' tag: 'emoji'
}; };
vrcPlusIconRequest queryRequest
.getCachedFileList(params) .fetch('galleryFiles', params)
.then((args) => handleFilesList(args)) .then((args) => handleFilesList(args))
.catch((error) => { .catch((error) => {
console.error('Error fetching emojis:', error); console.error('Error fetching emojis:', error);
@@ -366,6 +413,9 @@ export const useGalleryStore = defineStore('Gallery', () => {
}); });
} }
/**
*
*/
async function getInventory() { async function getInventory() {
inventoryTable.value = []; inventoryTable.value = [];
advancedSettingsStore.currentUserInventory.clear(); advancedSettingsStore.currentUserInventory.clear();
@@ -378,8 +428,7 @@ export const useGalleryStore = defineStore('Gallery', () => {
try { try {
for (let i = 0; i < 100; i++) { for (let i = 0; i < 100; i++) {
params.offset = i * params.n; params.offset = i * params.n;
const args = const args = await queryRequest.fetch('inventoryItems', params);
await inventoryRequest.getCachedInventoryItems(params);
for (const item of args.json.data) { for (const item of args.json.data) {
advancedSettingsStore.currentUserInventory.set( advancedSettingsStore.currentUserInventory.set(
item.id, item.id,
@@ -400,6 +449,9 @@ export const useGalleryStore = defineStore('Gallery', () => {
} }
} }
/**
*
*/
async function tryDeleteOldPrints() { async function tryDeleteOldPrints() {
if (!advancedSettingsStore.autoDeleteOldPrints) { if (!advancedSettingsStore.autoDeleteOldPrints) {
return; return;
@@ -435,6 +487,11 @@ export const useGalleryStore = defineStore('Gallery', () => {
await refreshPrintTable(); await refreshPrintTable();
} }
/**
*
* @param imageUrl
* @param fileName
*/
function showFullscreenImageDialog(imageUrl, fileName) { function showFullscreenImageDialog(imageUrl, fileName) {
if (!imageUrl) { if (!imageUrl) {
return; return;
@@ -445,6 +502,11 @@ export const useGalleryStore = defineStore('Gallery', () => {
D.visible = true; D.visible = true;
} }
/**
*
* @param inventoryId
* @param userId
*/
function queueCheckInstanceInventory(inventoryId, userId) { function queueCheckInstanceInventory(inventoryId, userId) {
if ( if (
state.instanceInventoryCache.includes(inventoryId) || state.instanceInventoryCache.includes(inventoryId) ||
@@ -472,8 +534,13 @@ export const useGalleryStore = defineStore('Gallery', () => {
} }
} }
/**
*
* @param inventoryId
* @param userId
*/
async function trySaveEmojiToFile(inventoryId, userId) { async function trySaveEmojiToFile(inventoryId, userId) {
const args = await inventoryRequest.getCachedUserInventoryItem({ const args = await queryRequest.fetch('userInventoryItem', {
inventoryId, inventoryId,
userId userId
}); });
@@ -486,7 +553,7 @@ export const useGalleryStore = defineStore('Gallery', () => {
return; return;
} }
const userArgs = await userRequest.getCachedUser({ const userArgs = await queryRequest.fetch('user', {
userId: args.json.holderId userId: args.json.holderId
}); });
const displayName = userArgs.json?.displayName ?? ''; const displayName = userArgs.json?.displayName ?? '';
@@ -537,6 +604,10 @@ export const useGalleryStore = defineStore('Gallery', () => {
} }
} }
/**
*
* @param fileId
*/
async function getCachedEmoji(fileId) { async function getCachedEmoji(fileId) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let ref = cachedEmoji.get(fileId); let ref = cachedEmoji.get(fileId);
@@ -544,8 +615,8 @@ export const useGalleryStore = defineStore('Gallery', () => {
resolve(ref); resolve(ref);
return; return;
} }
miscReq queryRequest
.getCachedFile({ fileId }) .fetch('file', { fileId })
.then((args) => { .then((args) => {
cachedEmoji.set(fileId, args.json); cachedEmoji.set(fileId, args.json);
resolve(args.json); resolve(args.json);
+15 -20
View File
@@ -10,12 +10,7 @@ import {
replaceBioSymbols, replaceBioSymbols,
sanitizeEntityJson sanitizeEntityJson
} from '../shared/utils'; } from '../shared/utils';
import { import { groupRequest, instanceRequest, queryRequest } from '../api';
groupRequest,
instanceRequest,
userRequest,
worldRequest
} from '../api';
import { database } from '../service/database'; import { database } from '../service/database';
import { groupDialogFilterOptions } from '../shared/constants/'; import { groupDialogFilterOptions } from '../shared/constants/';
import { patchGroupFromEvent } from '../queries'; import { patchGroupFromEvent } from '../queries';
@@ -195,8 +190,8 @@ export const useGroupStore = defineStore('Group', () => {
D.ownerDisplayName = ref.ownerId; D.ownerDisplayName = ref.ownerId;
D.visible = true; D.visible = true;
D.loading = false; D.loading = false;
userRequest queryRequest
.getCachedUser({ .fetch('user', {
userId: ref.ownerId userId: ref.ownerId
}) })
.then((args1) => { .then((args1) => {
@@ -221,10 +216,10 @@ export const useGroupStore = defineStore('Group', () => {
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
async function groupOwnerChange(ref, oldUserId, newUserId) { async function groupOwnerChange(ref, oldUserId, newUserId) {
const oldUser = await userRequest.getCachedUser({ const oldUser = await queryRequest.fetch('user', {
userId: oldUserId userId: oldUserId
}); });
const newUser = await userRequest.getCachedUser({ const newUser = await queryRequest.fetch('user', {
userId: newUserId userId: newUserId
}); });
const oldDisplayName = oldUser?.ref?.displayName; const oldDisplayName = oldUser?.ref?.displayName;
@@ -422,7 +417,7 @@ export const useGroupStore = defineStore('Group', () => {
let total = Infinity; let total = Infinity;
let pages = 0; let pages = 0;
do { do {
const args = await groupRequest.getCachedGroupPosts({ const args = await queryRequest.fetch('groupPosts', {
groupId: params.groupId, groupId: params.groupId,
n, n,
offset offset
@@ -466,8 +461,8 @@ export const useGroupStore = defineStore('Group', () => {
const refPromise = existingRef const refPromise = existingRef
? Promise.resolve({ ref: existingRef }) ? Promise.resolve({ ref: existingRef })
: groupRequest : queryRequest
.getCachedGroup({ groupId, includeRoles: true }) .fetch('group', { groupId, includeRoles: true })
.then((args) => ({ ref: applyGroup(args.json), args })); .then((args) => ({ ref: applyGroup(args.json), args }));
return refPromise return refPromise
@@ -507,8 +502,8 @@ export const useGroupStore = defineStore('Group', () => {
} }
for (const json of args.json.instances) { for (const json of args.json.instances) {
instanceStore.applyInstance(json); instanceStore.applyInstance(json);
worldRequest queryRequest
.getCachedWorld({ .fetch('world', {
worldId: json.world.id worldId: json.world.id
}) })
.then((args1) => { .then((args1) => {
@@ -521,16 +516,16 @@ export const useGroupStore = defineStore('Group', () => {
}); });
} }
}); });
groupRequest queryRequest
.getCachedGroupCalendar(groupId) .fetch('groupCalendar', { groupId })
.then((args) => { .then((args) => {
if (groupDialog.value.id === args.params.groupId) { if (groupDialog.value.id === args.params.groupId) {
D.calendar = args.json.results; D.calendar = args.json.results;
for (const event of D.calendar) { for (const event of D.calendar) {
applyGroupEvent(event); applyGroupEvent(event);
// fetch again for isFollowing // fetch again for isFollowing
groupRequest queryRequest
.getCachedGroupCalendarEvent({ .fetch('groupCalendarEvent', {
groupId, groupId,
eventId: event.id eventId: event.id
}) })
@@ -1175,7 +1170,7 @@ export const useGroupStore = defineStore('Group', () => {
D.groupRef = {}; D.groupRef = {};
D.auditLogTypes = []; D.auditLogTypes = [];
groupRequest.getCachedGroup({ groupId }).then((args) => { queryRequest.fetch('group', { groupId }).then((args) => {
D.groupRef = args.ref; D.groupRef = args.ref;
if (hasGroupPermission(D.groupRef, 'group-audit-view')) { if (hasGroupPermission(D.groupRef, 'group-audit-view')) {
groupRequest.getGroupAuditLogTypes({ groupId }).then((args) => { groupRequest.getGroupAuditLogTypes({ groupId }).then((args) => {
+11 -13
View File
@@ -23,8 +23,8 @@ import {
replaceBioSymbols replaceBioSymbols
} from '../shared/utils'; } from '../shared/utils';
import { import {
groupRequest,
instanceRequest, instanceRequest,
queryRequest,
userRequest, userRequest,
worldRequest worldRequest
} from '../api'; } from '../api';
@@ -33,7 +33,6 @@ import {
instanceContentSettings instanceContentSettings
} from '../shared/constants'; } from '../shared/constants';
import { database } from '../service/database'; import { database } from '../service/database';
import { patchInstanceFromEvent } from '../queries';
import { resolveRef } from '../shared/utils/resolveRef'; import { resolveRef } from '../shared/utils/resolveRef';
import { useAppearanceSettingsStore } from './settings/appearance'; import { useAppearanceSettingsStore } from './settings/appearance';
import { useFriendStore } from './friend'; import { useFriendStore } from './friend';
@@ -246,7 +245,7 @@ export const useInstanceStore = defineStore('Instance', () => {
emptyDefault: { id: '', displayName: '' }, emptyDefault: { id: '', displayName: '' },
idAlias: 'userId', idAlias: 'userId',
nameKey: 'displayName', nameKey: 'displayName',
fetchFn: (id) => userRequest.getCachedUser({ userId: id }) fetchFn: (id) => queryRequest.fetch('user', { userId: id })
}); });
} }
@@ -259,7 +258,7 @@ export const useInstanceStore = defineStore('Instance', () => {
emptyDefault: { id: '', name: '' }, emptyDefault: { id: '', name: '' },
idAlias: 'worldId', idAlias: 'worldId',
nameKey: 'name', nameKey: 'name',
fetchFn: (id) => worldRequest.getCachedWorld({ worldId: id }) fetchFn: (id) => queryRequest.fetch('world', { worldId: id })
}); });
} }
@@ -272,7 +271,7 @@ export const useInstanceStore = defineStore('Instance', () => {
emptyDefault: { id: '', name: '' }, emptyDefault: { id: '', name: '' },
idAlias: 'groupId', idAlias: 'groupId',
nameKey: 'name', nameKey: 'name',
fetchFn: (id) => groupRequest.getCachedGroup({ groupId: id }) fetchFn: (id) => queryRequest.fetch('group', { groupId: id })
}); });
} }
@@ -340,8 +339,8 @@ export const useInstanceStore = defineStore('Instance', () => {
location.worldId && location.worldId &&
!worldStore.cachedWorlds.get(location.worldId)?.name !worldStore.cachedWorlds.get(location.worldId)?.name
) { ) {
worldRequest queryRequest
.getCachedWorld({ worldId: location.worldId }) .fetch('world', { worldId: location.worldId })
.then((args) => { .then((args) => {
uiStore.setDialogCrumbLabel( uiStore.setDialogCrumbLabel(
'previous-instances-info', 'previous-instances-info',
@@ -467,8 +466,8 @@ export const useInstanceStore = defineStore('Instance', () => {
console.error('Error fetching world data:', error); console.error('Error fetching world data:', error);
}); });
} else { } else {
worldRequest queryRequest
.getCachedWorld({ .fetch('world', {
worldId: currentInstanceLocation.value.worldId worldId: currentInstanceLocation.value.worldId
}) })
.then((args) => { .then((args) => {
@@ -537,8 +536,8 @@ export const useInstanceStore = defineStore('Instance', () => {
} }
ref.$location = parseLocation(ref.location); ref.$location = parseLocation(ref.location);
if (ref.world?.id) { if (ref.world?.id) {
worldRequest queryRequest
.getCachedWorld({ .fetch('world', {
worldId: ref.world.id worldId: ref.world.id
}) })
.then((args) => { .then((args) => {
@@ -577,7 +576,6 @@ export const useInstanceStore = defineStore('Instance', () => {
} }
} }
lastInstanceApplied.value = ref.id; lastInstanceApplied.value = ref.id;
patchInstanceFromEvent(ref);
return ref; return ref;
} }
@@ -591,7 +589,7 @@ export const useInstanceStore = defineStore('Instance', () => {
const L = parseLocation(location); const L = parseLocation(location);
if (L.isRealInstance && L.worldId && L.instanceId) { if (L.isRealInstance && L.worldId && L.instanceId) {
try { try {
const args = await instanceRequest.getCachedInstance({ const args = await instanceRequest.getInstance({
worldId: L.worldId, worldId: L.worldId,
instanceId: L.instanceId instanceId: L.instanceId
}); });
+10 -8
View File
@@ -23,8 +23,7 @@ import {
friendRequest, friendRequest,
instanceRequest, instanceRequest,
notificationRequest, notificationRequest,
userRequest, queryRequest
worldRequest
} from '../../api'; } from '../../api';
import { import {
getNotificationMessage, getNotificationMessage,
@@ -216,7 +215,7 @@ export const useNotificationStore = defineStore('Notification', () => {
// get instance name for invite // get instance name for invite
const L = parseLocation(ref.details.worldId); const L = parseLocation(ref.details.worldId);
if (L.isRealInstance) { if (L.isRealInstance) {
instanceRequest.getCachedInstance({ instanceRequest.getInstance({
worldId: L.worldId, worldId: L.worldId,
instanceId: L.instanceId instanceId: L.instanceId
}); });
@@ -350,8 +349,8 @@ export const useNotificationStore = defineStore('Notification', () => {
} }
const L = parseLocation(currentLocation); const L = parseLocation(currentLocation);
worldRequest queryRequest
.getCachedWorld({ .fetch('world', {
worldId: L.worldId worldId: L.worldId
}) })
.then((args1) => { .then((args1) => {
@@ -401,6 +400,9 @@ export const useNotificationStore = defineStore('Notification', () => {
notificationInitStatus.value = value; notificationInitStatus.value = value;
} }
/**
*
*/
function clearUnseenNotifications() { function clearUnseenNotifications() {
unseenNotifications.value = []; unseenNotifications.value = [];
} }
@@ -996,7 +998,7 @@ export const useNotificationStore = defineStore('Notification', () => {
displayOvrtNotification displayOvrtNotification
} = createOverlayDispatch({ } = createOverlayDispatch({
getUserIdFromNoty, getUserIdFromNoty,
userRequest, queryRequest,
notificationsSettingsStore, notificationsSettingsStore,
advancedSettingsStore, advancedSettingsStore,
appearanceSettingsStore appearanceSettingsStore
@@ -1285,8 +1287,8 @@ export const useNotificationStore = defineStore('Notification', () => {
currentLocation = userStore.currentUser?.$locationTag; currentLocation = userStore.currentUser?.$locationTag;
} }
const L = parseLocation(currentLocation); const L = parseLocation(currentLocation);
worldRequest queryRequest
.getCachedWorld({ worldId: L.worldId }) .fetch('world', { worldId: L.worldId })
.then((args) => { .then((args) => {
notificationRequest notificationRequest
.sendInvite( .sendInvite(
+18 -5
View File
@@ -6,10 +6,9 @@ import {
/** /**
* Creates the overlay dispatch functions for the Notification store. * Creates the overlay dispatch functions for the Notification store.
*
* @param {object} deps * @param {object} deps
* @param {Function} deps.getUserIdFromNoty * @param {Function} deps.getUserIdFromNoty
* @param {object} deps.userRequest * @param {object} deps.queryRequest
* @param {object} deps.notificationsSettingsStore * @param {object} deps.notificationsSettingsStore
* @param {object} deps.advancedSettingsStore * @param {object} deps.advancedSettingsStore
* @param {object} deps.appearanceSettingsStore * @param {object} deps.appearanceSettingsStore
@@ -17,7 +16,7 @@ import {
*/ */
export function createOverlayDispatch({ export function createOverlayDispatch({
getUserIdFromNoty, getUserIdFromNoty,
userRequest, queryRequest,
notificationsSettingsStore, notificationsSettingsStore,
advancedSettingsStore, advancedSettingsStore,
appearanceSettingsStore appearanceSettingsStore
@@ -54,6 +53,12 @@ export function createOverlayDispatch({
return imageLocation; return imageLocation;
} }
/**
*
* @param noty
* @param message
* @param image
*/
function displayDesktopToast(noty, message, image) { function displayDesktopToast(noty, message, image) {
const result = getNotificationMessage(noty, message); const result = getNotificationMessage(noty, message);
if (result) { if (result) {
@@ -100,6 +105,14 @@ export function createOverlayDispatch({
AppApi.XSNotification('VRCX', text, timeout, opacity, image); AppApi.XSNotification('VRCX', text, timeout, opacity, image);
} }
/**
*
* @param playOvrtHudNotifications
* @param playOvrtWristNotifications
* @param noty
* @param message
* @param image
*/
function displayOvrtNotification( function displayOvrtNotification(
playOvrtHudNotifications, playOvrtHudNotifications,
playOvrtWristNotifications, playOvrtWristNotifications,
@@ -146,8 +159,8 @@ export function createOverlayDispatch({
} else if (noty.imageUrl) { } else if (noty.imageUrl) {
imageUrl = noty.imageUrl; imageUrl = noty.imageUrl;
} else if (userId && !userId.startsWith('grp_')) { } else if (userId && !userId.startsWith('grp_')) {
imageUrl = await userRequest imageUrl = await queryRequest
.getCachedUser({ .fetch('user', {
userId userId
}) })
.catch((err) => { .catch((err) => {
+2 -2
View File
@@ -19,12 +19,12 @@ import {
ActivityType, ActivityType,
StatusDisplayType StatusDisplayType
} from '../../shared/constants/discord'; } from '../../shared/constants/discord';
import { queryRequest } from '../../api';
import { useGameLogStore } from '../gameLog'; import { useGameLogStore } from '../gameLog';
import { useGameStore } from '../game'; import { useGameStore } from '../game';
import { useLocationStore } from '../location'; import { useLocationStore } from '../location';
import { useUpdateLoopStore } from '../updateLoop'; import { useUpdateLoopStore } from '../updateLoop';
import { useUserStore } from '../user'; import { useUserStore } from '../user';
import { worldRequest } from '../../api';
import configRepository from '../../service/config'; import configRepository from '../../service/config';
@@ -221,7 +221,7 @@ export const useDiscordPresenceSettingsStore = defineStore(
groupAccessName: '' groupAccessName: ''
}; };
try { try {
const args = await worldRequest.getCachedWorld({ const args = await queryRequest.fetch('world', {
worldId: L.worldId worldId: L.worldId
}); });
state.lastLocationDetails.worldName = args.ref.name; state.lastLocationDetails.worldName = args.ref.name;
+3 -2
View File
@@ -29,6 +29,7 @@ import {
avatarRequest, avatarRequest,
groupRequest, groupRequest,
instanceRequest, instanceRequest,
queryRequest,
userRequest userRequest
} from '../api'; } from '../api';
import { processBulk, request } from '../service/request'; import { processBulk, request } from '../service/request';
@@ -715,8 +716,8 @@ export const useUserStore = defineStore('User', () => {
}); });
} }
AppApi.SendIpc('ShowUserDialog', userId); AppApi.SendIpc('ShowUserDialog', userId);
userRequest queryRequest
.getCachedUser({ .fetch('user', {
userId userId
}) })
.catch((err) => { .catch((err) => {
+2 -2
View File
@@ -9,7 +9,7 @@ import {
SEARCH_LIMIT_MAX, SEARCH_LIMIT_MAX,
SEARCH_LIMIT_MIN SEARCH_LIMIT_MIN
} from '../shared/constants'; } from '../shared/constants';
import { avatarRequest, worldRequest } from '../api'; import { avatarRequest, queryRequest } from '../api';
import { import {
clearPiniaActionTrail, clearPiniaActionTrail,
getPiniaActionTrail getPiniaActionTrail
@@ -684,7 +684,7 @@ export const useVrcxStore = defineStore('Vrcx', () => {
toast.error('Invalid local favorite world command'); toast.error('Invalid local favorite world command');
break; break;
} }
worldRequest.getCachedWorld({ worldId: id }).then(() => { queryRequest.fetch('world', { worldId: id }).then(() => {
searchStore.directAccessWorld(id); searchStore.directAccessWorld(id);
favoriteStore.addLocalWorldFavorite(id, group); favoriteStore.addLocalWorldFavorite(id, group);
}); });
@@ -77,7 +77,7 @@
import { isRealInstance, parseLocation, userImage, userStatusClass } from '../../../shared/utils'; import { isRealInstance, parseLocation, userImage, userStatusClass } from '../../../shared/utils';
import { useGameStore, useLaunchStore, useLocationStore, useUserStore } from '../../../stores'; import { useGameStore, useLaunchStore, useLocationStore, useUserStore } from '../../../stores';
import { instanceRequest, notificationRequest, worldRequest } from '../../../api'; import { instanceRequest, notificationRequest, queryRequest } from '../../../api';
import { checkCanInvite, checkCanInviteSelf } from '../../../shared/utils/invite.js'; import { checkCanInvite, checkCanInviteSelf } from '../../../shared/utils/invite.js';
import Location from '../../../components/Location.vue'; import Location from '../../../components/Location.vue';
@@ -186,7 +186,7 @@
currentLocation = lastLocationDestination.value; currentLocation = lastLocationDestination.value;
} }
const L = parseLocation(currentLocation); const L = parseLocation(currentLocation);
worldRequest.getCachedWorld({ worldId: L.worldId }).then((args) => { queryRequest.fetch('world', { worldId: L.worldId }).then((args) => {
notificationRequest notificationRequest
.sendInvite( .sendInvite(
{ {
@@ -94,14 +94,12 @@ const {
mockSendRequestInvite, mockSendRequestInvite,
mockSendInvite, mockSendInvite,
mockSelfInvite, mockSelfInvite,
mockGetCachedWorld mockQueryFetch
} = vi.hoisted(() => ({ } = vi.hoisted(() => ({
mockSendRequestInvite: vi.fn().mockResolvedValue({}), mockSendRequestInvite: vi.fn().mockResolvedValue({}),
mockSendInvite: vi.fn().mockResolvedValue({}), mockSendInvite: vi.fn().mockResolvedValue({}),
mockSelfInvite: vi.fn().mockResolvedValue({}), mockSelfInvite: vi.fn().mockResolvedValue({}),
mockGetCachedWorld: vi mockQueryFetch: vi.fn().mockResolvedValue({ ref: { name: 'Test World' } })
.fn()
.mockResolvedValue({ ref: { name: 'Test World' } })
})); }));
vi.mock('../../../../api', () => { vi.mock('../../../../api', () => {
@@ -116,9 +114,7 @@ vi.mock('../../../../api', () => {
return { return {
request: p(), request: p(),
userRequest: p(), userRequest: p(),
worldRequest: p({ worldRequest: p(),
getCachedWorld: (...args) => mockGetCachedWorld(...args)
}),
instanceRequest: p({ instanceRequest: p({
selfInvite: (...args) => mockSelfInvite(...args) selfInvite: (...args) => mockSelfInvite(...args)
}), }),
@@ -139,7 +135,10 @@ vi.mock('../../../../api', () => {
groupRequest: p(), groupRequest: p(),
inventoryRequest: p(), inventoryRequest: p(),
propRequest: p(), propRequest: p(),
imageRequest: p() imageRequest: p(),
queryRequest: p({
fetch: (...args) => mockQueryFetch(...args)
})
}; };
}); });
@@ -205,7 +205,7 @@
} from '../../../stores'; } from '../../../stores';
import { buildFriendRow, buildInstanceHeaderRow, buildToggleRow, estimateRowSize } from '../friendsSidebarUtils'; import { buildFriendRow, buildInstanceHeaderRow, buildToggleRow, estimateRowSize } from '../friendsSidebarUtils';
import { getFriendsSortFunction, isRealInstance, userImage, userStatusClass } from '../../../shared/utils'; import { getFriendsSortFunction, isRealInstance, userImage, userStatusClass } from '../../../shared/utils';
import { instanceRequest, notificationRequest, userRequest, worldRequest } from '../../../api'; import { instanceRequest, notificationRequest, queryRequest, userRequest } from '../../../api';
import { checkCanInvite, checkCanInviteSelf } from '../../../shared/utils/invite.js'; import { checkCanInvite, checkCanInviteSelf } from '../../../shared/utils/invite.js';
import { getFriendsLocations } from '../../../shared/utils/location.js'; import { getFriendsLocations } from '../../../shared/utils/location.js';
import { parseLocation } from '../../../shared/utils'; import { parseLocation } from '../../../shared/utils';
@@ -753,7 +753,7 @@
currentLocation = lastLocationDestination.value; currentLocation = lastLocationDestination.value;
} }
const L = parseLocation(currentLocation); const L = parseLocation(currentLocation);
worldRequest.getCachedWorld({ worldId: L.worldId }).then((args) => { queryRequest.fetch('world', { worldId: L.worldId }).then((args) => {
notificationRequest notificationRequest
.sendInvite( .sendInvite(
{ {