refactor coordinators

This commit is contained in:
pa
2026-03-10 11:54:09 +09:00
parent 648fcde085
commit 2fffadfbcf
16 changed files with 1068 additions and 1257 deletions
+83 -79
View File
@@ -1,88 +1,92 @@
import { getWorldName, parseLocation } from '../shared/utils';
import { runUpdateFriendshipsFlow } from './friendRelationshipCoordinator';
import { useAuthStore } from '../stores/auth';
import { useAvatarStore } from '../stores/avatar';
import { useFriendStore } from '../stores/friend';
import { useGameStore } from '../stores/game';
import { useGroupStore } from '../stores/group';
import { useInstanceStore } from '../stores/instance';
import { useUserStore } from '../stores/user';
/**
* @param {object} deps Coordinator dependencies.
* @returns {object} User session coordinator methods.
* Runs avatar transition side effects for current user updates.
* @param {object} args Avatar transition context.
* @param {object} args.json Current user payload.
* @param {object} args.ref Current user state reference.
* @param {boolean} args.isLoggedIn Whether current user is already logged in.
* @param {object} [options] Test seams.
* @param {function} [options.now] Timestamp provider.
*/
export function createUserSessionCoordinator(deps) {
const {
avatarStore,
gameStore,
groupStore,
instanceStore,
friendStore,
authStore,
cachedUsers,
currentUser,
userDialog,
getWorldName,
parseLocation,
now
} = deps;
export function runAvatarSwapFlow(
{ json, ref, isLoggedIn },
{ now = Date.now } = {}
) {
const avatarStore = useAvatarStore();
const gameStore = useGameStore();
/**
* Runs avatar transition side effects for current user updates.
* @param {object} args Avatar transition context.
* @param {object} args.json Current user payload.
* @param {object} args.ref Current user state reference.
* @param {boolean} args.isLoggedIn Whether current user is already logged in.
*/
function runAvatarSwapFlow({ json, ref, isLoggedIn }) {
if (!isLoggedIn) {
return;
}
if (json.currentAvatar !== ref.currentAvatar) {
avatarStore.addAvatarToHistory(json.currentAvatar);
if (gameStore.isGameRunning) {
avatarStore.addAvatarWearTime(ref.currentAvatar);
ref.$previousAvatarSwapTime = now();
}
}
if (!isLoggedIn) {
return;
}
/**
* Runs one-time side effects for first current-user hydration after login.
* @param {object} ref Current user state reference.
*/
function runFirstLoginFlow(ref) {
if (json.currentAvatar !== ref.currentAvatar) {
avatarStore.addAvatarToHistory(json.currentAvatar);
if (gameStore.isGameRunning) {
avatarStore.addAvatarWearTime(ref.currentAvatar);
ref.$previousAvatarSwapTime = now();
}
cachedUsers.clear(); // clear before running applyUser
currentUser.value = ref;
authStore.loginComplete();
}
/**
* Runs cross-store synchronization after current-user data is applied.
* @param {object} ref Current user state reference.
*/
function runPostApplySyncFlow(ref) {
groupStore.applyPresenceGroups(ref);
instanceStore.applyQueuedInstance(ref.queuedInstance);
friendStore.updateUserCurrentStatus(ref);
friendStore.updateFriendships(ref);
}
/**
* Syncs home location derived state and visible dialog display name.
* @param {object} ref Current user state reference.
*/
function runHomeLocationSyncFlow(ref) {
if (ref.homeLocation === ref.$homeLocation?.tag) {
return;
}
ref.$homeLocation = parseLocation(ref.homeLocation);
// apply home location name to user dialog
if (userDialog.value.visible && userDialog.value.id === ref.id) {
getWorldName(currentUser.value.homeLocation).then((worldName) => {
userDialog.value.$homeLocationName = worldName;
});
}
}
return {
runAvatarSwapFlow,
runFirstLoginFlow,
runPostApplySyncFlow,
runHomeLocationSyncFlow
};
}
/**
* Runs one-time side effects for first current-user hydration after login.
* @param {object} ref Current user state reference.
* @param {object} [options] Test seams.
* @param {function} [options.now] Timestamp provider.
*/
export function runFirstLoginFlow(ref, { now = Date.now } = {}) {
const gameStore = useGameStore();
const authStore = useAuthStore();
const userStore = useUserStore();
if (gameStore.isGameRunning) {
ref.$previousAvatarSwapTime = now();
}
userStore.cachedUsers.clear(); // clear before running applyUser
userStore.currentUser = ref;
authStore.loginComplete();
}
/**
* Runs cross-store synchronization after current-user data is applied.
* @param {object} ref Current user state reference.
*/
export function runPostApplySyncFlow(ref) {
const groupStore = useGroupStore();
const instanceStore = useInstanceStore();
const friendStore = useFriendStore();
groupStore.applyPresenceGroups(ref);
instanceStore.applyQueuedInstance(ref.queuedInstance);
friendStore.updateUserCurrentStatus(ref);
if (typeof ref.friends !== 'undefined') {
runUpdateFriendshipsFlow(ref);
}
}
/**
* Syncs home location derived state and visible dialog display name.
* @param {object} ref Current user state reference.
*/
export function runHomeLocationSyncFlow(ref) {
const userStore = useUserStore();
if (ref.homeLocation === ref.$homeLocation?.tag) {
return;
}
ref.$homeLocation = parseLocation(ref.homeLocation);
// apply home location name to user dialog
if (userStore.userDialog.visible && userStore.userDialog.id === ref.id) {
getWorldName(userStore.currentUser.homeLocation).then((worldName) => {
userStore.userDialog.$homeLocationName = worldName;
});
}
}