diff --git a/app/src/components/game/ControlPalette.vue b/app/src/components/game/ControlPalette.vue index bd2bbf7..b423112 100644 --- a/app/src/components/game/ControlPalette.vue +++ b/app/src/components/game/ControlPalette.vue @@ -1,13 +1,14 @@ diff --git a/app/src/components/header/GameHeaderComponents.vue b/app/src/components/header/GameHeaderComponents.vue index c497807..ef9a685 100644 --- a/app/src/components/header/GameHeaderComponents.vue +++ b/app/src/components/header/GameHeaderComponents.vue @@ -4,10 +4,11 @@ import { useRouter } from 'vue-router' import { useToast } from 'vue-toastification' import { logout } from '../../utils/auth' import { bugReportUrl, surveyUrl } from '../../config' -import { reset } from '../../store/session' +import useSession from '../../store/session' import useUserProfile from '../../store/userProfile' -const store = useUserProfile() +const userStore = useUserProfile() +const sessionStore = useSession() const router = useRouter() const toast = useToast() @@ -15,8 +16,8 @@ const toast = useToast() const handleLogout = async () => { try { await logout() - store.resetUserProfile() - reset() + userStore.resetUserProfile() + sessionStore.reset() router.push({ name: 'login' }) } catch (err) { toast.error('登出失敗') @@ -26,7 +27,7 @@ const handleLogout = async () => { onMounted(async () => { try { - await store.loadUserProfile() + await userStore.loadUserProfile() } catch (err) { toast.error('無法讀取使用者資料') console.error(err) @@ -57,7 +58,7 @@ onMounted(async () => { class="text-text inline-block whitespace-nowrap px-1.5" style="font-size: 2vh" > - {{ store.username }} + {{ userStore.username }}
({ - session: newSession(), - questId: '', - quest: null, +const useSession = defineStore('session', { + state: (): Store => ({ + session: { + _id: '', + status: 'inactive', + graph: new FileGraph({ + path: '/', + type: 'folder', + discovered: false, + }), + pwd: '', + hints: [], + tasks: [], + responses: [], + }, + questId: '', + quest: null, + }), + actions: { + async setQuest(questId: string) { + this.quest = await getQuest(questId) + this.questId = questId + }, + async setSession(session: Session) { + this.session = session + this.session.graph = new FileGraph(session.graph) + term.reset() + await socket.connect(session) + term.focus() + }, + async createSession() { + const session = await createSession(this.questId) + this.setSession(session) + }, + async getActiveSession() { + const sessions = await getSessions({ + questId: this.questId, + limit: 1, + order: 'desc', + status: 'active', + }) + if (sessions.length > 0) { + this.setSession(sessions[0]) + return true + } + return false + }, + updateGraph(event: { discover?: FileObject[]; pwd?: string }) { + if (event.discover) { + this.session.graph.discover(event.discover) + } + if (event.pwd) { + this.session.pwd = event.pwd + } + }, + newResponse(response: StageResponse) { + this.session.responses.push(response.responses) + this.session.hints.push(response.hints) + this.session.tasks = response.tasks + this.session.status = response.status + }, + reset() { + socket.reset() + term.reset() + this.$reset() + }, + setup() { + socket.on('terminal', (data: string) => { + term.write(data) + }) + term.onData((data: string) => { + socket.emit('terminal', data) + }) + socket.on('graph', (event: { discover: FileObject[]; pwd: string }) => { + this.updateGraph(event) + }) + socket.on('response', (response: StageResponse) => { + this.newResponse(response) + }) + }, + }, }) -const socket = new Socket() -const term = new SocketTerminal(40, 80) - -export function setQuest(questId: string) { - return api.get(`/quests/${questId}`).then((res) => { - store.questId = res.data._id - store.quest = res.data - }) -} - -async function setSession(session: Session) { - try { - console.log('Setting session...', session) - store.session = session - store.session.graph = new FileGraph(session.graph) - term.reset() - await socket.connect(session) - term.focus() - } catch (err: any) { - console.error(err) - if (err instanceof Error) { - toast.error(err.message) - } else { - toast.error('Failed to connect to the session. Please try again later.') - } - throw err - } -} - -export async function createSession() { - try { - console.log('Creating a new session...') - const res = await api.post('/sessions', { questId: store.questId }) - const { data } = res - await setSession(data) - socket.emit('terminal', 'echo start') - } catch (err) { - console.error(err) - toast.error('Failed to create a new session. Please try again later.') - } -} - -export async function getActiveSession(questId: string) { - try { - // const res = await api.post('/sessions/active', { questId }) - const res = await api.get(`/sessions/${questId}`, { - params: { status: 'active' }, - }) - await setSession(res.data) - } catch (err) { - console.error(err) - throw new LoadSessionError('Failed to load session', questId) - // toast.warning('Failed to connect previous session. Creating a new one...') - // await createSession() - } -} - -function updateGraph(event: { discover: FileObject[]; pwd: string }) { - if (event.discover) { - store.session.graph.discover(event.discover) - } - if (event.pwd) { - store.session.pwd = event.pwd - } -} - -function newResponse(response: StageResponse) { - console.log('newResponse', response, 'session', store.session) - store.session.responses.push(response.responses) - store.session.hints.push(response.hints) - store.session.tasks = response.tasks - store.session.status = response.status -} - export function useTerminal() { return term } -export function reset() { - socket.reset() - term.reset() - store.session = newSession() - store.quest = null -} - // export async function init(questId: string) { // if (!questId) throw new Error('No quest ID provided') // reset() @@ -141,21 +119,4 @@ export function reset() { // } // } -function setup() { - socket.on('terminal', (data: string) => { - term.write(data) - }) - term.onData((data: string) => { - socket.emit('terminal', data) - }) - socket.on('graph', (event: { discover: FileObject[]; pwd: string }) => { - updateGraph(event) - }) - socket.on('response', (response: StageResponse) => { - newResponse(response) - }) -} - -setup() - -export default store +export default useSession diff --git a/app/src/utils/api.ts b/app/src/utils/api.ts index f298863..a5808ac 100644 --- a/app/src/utils/api.ts +++ b/app/src/utils/api.ts @@ -1,4 +1,7 @@ import axios from 'axios' +import { IQuest } from '@linux-odyssey/models' +import { GetSessionsRequest } from '@linux-odyssey/constants' +import { Session } from '../types' import { UserProfile } from '../store/userProfile' const api = axios.create({ @@ -14,3 +17,20 @@ export async function getUserProfile(): Promise