Skip to content

Commit

Permalink
UI for SPX version selector
Browse files Browse the repository at this point in the history
  • Loading branch information
nighca committed Nov 20, 2024
1 parent 4dd56e1 commit 5ae6bf8
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 27 deletions.
53 changes: 51 additions & 2 deletions spx-gui/src/components/navbar/NavbarProfile.vue
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@
{{ $t({ en: 'Projects', zh: '项目列表' }) }}
</UIMenuItem>
</UIMenuGroup>
<UIMenuGroup>
<UIMenuItem v-if="spxVersion === 'v2'" @click="handleUseSpxV1">
{{ $t({ en: 'Use default SPX', zh: '使用默认 SPX' }) }}
</UIMenuItem>
<UIMenuItem v-if="spxVersion === 'v1'" @click="handleUseSpxV2">
{{ $t({ en: 'Use new SPX (in beta)', zh: '启用新 SPX(测试中)' }) }}
</UIMenuItem>
</UIMenuGroup>
<UIMenuGroup>
<UIMenuItem @click="handleSignOut">{{ $t({ en: 'Sign out', zh: '登出' }) }}</UIMenuItem>
</UIMenuGroup>
Expand All @@ -32,12 +40,15 @@
</template>

<script setup lang="ts">
import { computed } from 'vue'
import { useRouter } from 'vue-router'
import { useNetwork } from '@/utils/network'
import { useSpxVersion } from '@/utils/utils'
import { useI18n } from '@/utils/i18n'
import { useMessageHandle } from '@/utils/exception'
import { getUserPageRoute } from '@/router'
import { useUserStore } from '@/stores/user'
import { UIButton, UIDropdown, UIMenu, UIMenuGroup, UIMenuItem } from '@/components/ui'
import { computed } from 'vue'
import { UIButton, UIDropdown, UIMenu, UIMenuGroup, UIMenuItem, useConfirmDialog } from '@/components/ui'
const userStore = useUserStore()
const { isOnline } = useNetwork()
Expand All @@ -53,6 +64,44 @@ function handleProjects() {
router.push(getUserPageRoute(userInfo.value!.name, 'projects'))
}
const spxVersion = useSpxVersion()
const handleUseSpxV1 = useMessageHandle(
async () => {
spxVersion.value = 'v1'
},
undefined,
{
en: 'Back to the default version of SPX',
zh: '已切换回默认版本 SPX'
}
).fn
const i18n = useI18n()
const withConfirm = useConfirmDialog()
const handleUseSpxV2 = useMessageHandle(
async () => {
await withConfirm({
type: 'info',
title: i18n.t({
en: 'Use new version of SPX',
zh: '启用新版本 SPX'
}),
content: i18n.t({
en: 'The new version of SPX is still in beta. You can switch back to the default version anytime if you encounter issues.',
zh: '新版本 SPX 还在测试中,如果遇到问题可以随时退回到默认版本。'
})
})
spxVersion.value = 'v2'
},
undefined,
{
en: 'Now using the new version of SPX',
zh: '已启用新版本 SPX'
}
).fn
function handleSignOut() {
userStore.signOut()
router.go(0) // Reload the page to trigger navigation guards.
Expand Down
6 changes: 2 additions & 4 deletions spx-gui/src/components/project/runner/ProjectRunner.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script setup lang="ts">
import { ref } from 'vue'
import { getSpxVersion, useLocalStorage } from '@/utils/utils'
import { useSpxVersion } from '@/utils/utils'
import type { Project } from '@/models/project'
import ProjectRunnerV1 from './v1/ProjectRunnerV1.vue'
import ProjectRunnerV2 from './v2/ProjectRunnerV2.vue'
Expand All @@ -17,9 +17,7 @@ function handleConsole(type: 'log' | 'warn', args: unknown[]) {
emit('console', type, args)
}
const version = useLocalStorage('spx-gui-runner', 'v1')
const specifiedVersion = getSpxVersion()
if (specifiedVersion != null) version.value = specifiedVersion
const version = useSpxVersion()
defineExpose({
run() {
Expand Down
56 changes: 35 additions & 21 deletions spx-gui/src/utils/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { memoize } from 'lodash'
import dayjs from 'dayjs'
import { ref, shallowReactive, shallowRef, watch, watchEffect, type WatchSource } from 'vue'
import { ref, shallowReactive, shallowRef, watch, watchEffect, type ShallowRef, type WatchSource, computed } from 'vue'
import { useI18n, type LocaleMessage } from './i18n'

export const isImage = (url: string): boolean => {
Expand All @@ -25,14 +25,9 @@ export function isAddPublicLibraryEnabled() {
return /\blibrary\b/.test(window.location.search)
}

/**
* Get user specified spx version.
* Currently spx v2 is not production ready, so we provide a way to specify spx version by adding `?spx=(v2|v1)` in URL query.
* This is an informal & temporary behavior.
*/
export function getSpxVersion() {
const matched = /\bspx=(\w+)\b/.exec(window.location.search)
return matched?.[1]
/** Manage spx version. */
export function useSpxVersion(): ShallowRef<'v1' | 'v2'> {
return useLocalStorage<'v1' | 'v2'>('spx-gui-runner', 'v1')
}

export function useAsyncComputed<T>(getter: () => Promise<T>) {
Expand Down Expand Up @@ -70,20 +65,39 @@ export function computedShallowReactive<T extends object>(getter: () => T) {
return r
}

const lsSyncer = shallowReactive(new Map<string, number>())

function watchLSChange(key: string) {
lsSyncer.get(key)
}

function fireLSChange(key: string) {
const val = lsSyncer.get(key) ?? 0
lsSyncer.set(key, val + 1)
}

/**
* Manipulate data stored in localStorage.
* Changes will be synchronized within the same document.
*/
export function useLocalStorage<T>(key: string, initialValue: T) {
const ref = shallowRef<T>(initialValue)
const storedValue = localStorage.getItem(key)
if (storedValue != null) {
ref.value = JSON.parse(storedValue)
}
watch(ref, (newValue) => {
if (newValue === initialValue) {
// Remove the key if the value is the initial value.
// NOTE: this may be unexpected for some special use cases
localStorage.removeItem(key)
return
const ref = computed<T>({
get() {
watchLSChange(key)
const storedValue = localStorage.getItem(key)
if (storedValue == null) return initialValue
return JSON.parse(storedValue)
},
set(newValue) {
if (newValue === initialValue) {
// Remove the key if the value is the initial value.
// NOTE: this may be unexpected for some special use cases
localStorage.removeItem(key)
} else {
localStorage.setItem(key, JSON.stringify(newValue))
}
fireLSChange(key)
}
localStorage.setItem(key, JSON.stringify(newValue))
})
return ref
}
Expand Down

0 comments on commit 5ae6bf8

Please sign in to comment.