Skip to content

Commit

Permalink
feat: Move the user switching to the system bar
Browse files Browse the repository at this point in the history
  • Loading branch information
ci010 committed May 3, 2023
1 parent fec74d8 commit e848ab1
Show file tree
Hide file tree
Showing 22 changed files with 617 additions and 516 deletions.
5 changes: 3 additions & 2 deletions xmcl-keystone-ui/src/components/SharedTooltip.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
:position-x="x"
:position-y="y"
class="z-100"
top
:top="!left"
:left="left"
>
{{ currentTooltip }}
</v-tooltip>
Expand All @@ -15,5 +16,5 @@
<script lang="ts" setup>
import { useSharedTooltipData } from '@/composables/sharedTooltip'
const { currentTooltip, x, y, isShown, color } = useSharedTooltipData()
const { currentTooltip, x, y, isShown, color, left } = useSharedTooltipData()
</script>
61 changes: 37 additions & 24 deletions xmcl-keystone-ui/src/components/SkinView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const props = withDefaults(defineProps<{
slim?: boolean
name?: string
animation?: 'walking' | 'none' | 'idle' | 'running'
paused?: boolean
}>(), {
width: 210,
height: 400,
Expand Down Expand Up @@ -45,59 +46,71 @@ const animationObject = computed(() => {
})
onUnmounted(() => {
data.disposed = true
viewer?.dispose()
})
const emit = defineEmits(['model', 'dragover', 'drop'])
let lastLoad = Promise.resolve()
let lastCapeLoad = Promise.resolve()
let viewer: SkinViewer
onMounted(() => {
const viewer = new SkinViewer({
viewer = new SkinViewer({
canvas: canvasRef.value!,
width: props.width,
height: props.height,
nameTag: props.name,
fov: 45,
zoom: 0.5,
})
viewer.animation = animationObject.value
watch(animationObject, (v) => {
viewer.animation = v
})
viewer.animation = animationObject.value
lastLoad = viewer.loadSkin(props.skin || steveSkin, { model: typeof props.slim === 'undefined' ? 'auto-detect' : props.slim ? 'slim' : 'default' }).finally(() => {
emit('model', viewer.playerObject.skin.modelType)
})
if (props.cape) {
lastCapeLoad = viewer.loadCape(props.cape)
}
})
watch(() => props.skin, (v) => {
lastLoad = lastLoad.finally(() => {
return viewer.loadSkin(v || steveSkin, { model: typeof props.slim === 'undefined' ? 'auto-detect' : props.slim ? 'slim' : 'default' }).finally(() => {
emit('model', viewer.playerObject.skin.modelType)
})
})
})
watch(() => props.cape, (v) => {
if (v) {
lastCapeLoad = lastCapeLoad.finally(() => viewer.loadCape(v))
} else {
viewer.resetCape()
}
})
watch(animationObject, (v) => {
viewer.animation = v
})
watch(() => props.slim, (v) => {
viewer.loadSkin(props.skin || steveSkin, { model: typeof v === 'undefined' ? 'auto-detect' : v ? 'slim' : 'default' }).finally(() => {
watch(() => props.skin, (v) => {
lastLoad = lastLoad.finally(() => {
return viewer.loadSkin(v || steveSkin, { model: typeof props.slim === 'undefined' ? 'auto-detect' : props.slim ? 'slim' : 'default' }).finally(() => {
emit('model', viewer.playerObject.skin.modelType)
})
})
})
watch(() => props.name, (v) => {
viewer.nameTag = v
watch(() => props.cape, (v) => {
if (v) {
lastCapeLoad = lastCapeLoad.finally(() => viewer.loadCape(v))
} else {
viewer.resetCape()
}
})
watch(() => props.slim, (v) => {
viewer.loadSkin(props.skin || steveSkin, { model: typeof v === 'undefined' ? 'auto-detect' : v ? 'slim' : 'default' }).finally(() => {
emit('model', viewer.playerObject.skin.modelType)
})
})
watch(() => props.name, (v) => {
viewer.nameTag = v
})
watch(() => props.paused, (paused) => {
if (paused) {
viewer.renderPaused = true
} else {
viewer.renderPaused = false
}
})
</script>
11 changes: 9 additions & 2 deletions xmcl-keystone-ui/src/composables/sharedTooltip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ const x = ref(0)
const y = ref(0)
const color = ref('black')
const isShown = ref(false)
const left = ref(false)

export function useSharedTooltipData() {
return {
currentTooltip,
left,
x,
y,
color,
Expand All @@ -19,8 +21,13 @@ export function useSharedTooltip<T>(getTooltip: (v: T) => string) {
const onEnter = async (e: MouseEvent, val: T) => {
const target = e.target as HTMLElement
const rect = target.getBoundingClientRect()
x.value = rect.x + rect.width / 2
y.value = rect.y - 0
if (!left.value) {
x.value = rect.x + rect.width / 2
y.value = rect.y - 0
} else {
x.value = rect.x
y.value = rect.y + rect.width / 2
}
currentTooltip.value = getTooltip(val)
isShown.value = true
}
Expand Down
3 changes: 3 additions & 0 deletions xmcl-keystone-ui/src/composables/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ export function useUsers() {
const users = computed(() => Object.values(state.users))
return { users }
}
export function useUserExpired(user: Ref<UserProfile | undefined>) {
return computed(() => !user.value || user.value?.invalidated || user.value.expiredAt < Date.now())
}

export function useLoginValidation(isOffline: Ref<boolean>) {
const { t } = useI18n()
Expand Down
1 change: 1 addition & 0 deletions xmcl-keystone-ui/src/composables/userSkin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,4 @@ export function useUserSkin(userId: Ref<string>, gameProfile: Ref<GameProfileAnd
export const UserSkinModel: InjectionKey<ReturnType<typeof useUserSkin>> = Symbol('UserSkinModel')
export const PlayerCapeModel: InjectionKey<Ref<string | undefined>> = Symbol('PlayerCapeModel')
export const PlayerNameModel: InjectionKey<Ref<string>> = Symbol('PlayerNameModel')
export const UserSkinRenderPaused: InjectionKey<Ref<boolean>> = Symbol('UserSkinRenderPaused')
17 changes: 14 additions & 3 deletions xmcl-keystone-ui/src/directives/sharedTooltip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,22 @@ import { useSharedTooltipData } from '@/composables/sharedTooltip'
import { FunctionDirective } from 'vue'

export const vSharedTooltip: FunctionDirective<HTMLElement, string> = (el, bindings) => {
const { currentTooltip, x, y, color, isShown } = useSharedTooltipData()
const { currentTooltip, x, y, color, left, isShown } = useSharedTooltipData()
el.addEventListener('mouseenter', (e) => {
const target = e.target as HTMLElement
const rect = target.getBoundingClientRect()
x.value = rect.x + rect.width / 2
y.value = rect.y - 0
if (bindings.modifiers.left) {
left.value = true
} else {
left.value = false
}
if (!left.value) {
x.value = rect.x + rect.width / 2
y.value = rect.y - 0
} else {
x.value = rect.x
y.value = rect.y + rect.width / 2
}
currentTooltip.value = bindings.value
isShown.value = true
})
Expand All @@ -18,6 +28,7 @@ export const vSharedTooltip: FunctionDirective<HTMLElement, string> = (el, bindi
isShown.value = false
})
el.addEventListener('DOMNodeRemoved', (e) => {
left.value = false
isShown.value = false
})
}
104 changes: 76 additions & 28 deletions xmcl-keystone-ui/src/views/AppSideBar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -34,48 +34,37 @@
right
>
<template #activator="{ on: tooltip }">
<v-list-item-avatar
size="48"
class="hover:rounded-xl transition-all duration-300"
large
@click="navToMe"
v-on="tooltip"
>
<PlayerAvatar
:src="gameProfile.textures.SKIN.url"
:dimension="48"
/>
</v-list-item-avatar>
<v-list-item-icon v-on="tooltip">
<v-icon> widgets </v-icon>
</v-list-item-icon>
</template>
{{ t('myStuff') }}
</v-tooltip>
</template>

<v-tooltip
:close-delay="0"
color="black"
transition="scroll-x-transition"
:close-delay="0"
right
>
<template #activator="{ on: tooltip }">
<v-list-item
link
push
to="/user"
to="/version-setting"
class="non-moveable"
v-on="tooltip"
>
<v-list-item-icon>
<v-icon>
manage_accounts
</v-icon>
<v-icon> power </v-icon>
</v-list-item-icon>

<v-list-item-title v-text="'Text'" />
</v-list-item>
</template>
{{ t('user.info') }}
{{ t('localVersion.title') }}
</v-tooltip>

<v-tooltip
color="black"
transition="scroll-x-transition"
Expand All @@ -86,43 +75,98 @@
<v-list-item
link
push
to="/version-setting"
to="/modpack-setting"
class="non-moveable"
v-on="tooltip"
>
<v-list-item-icon>
<v-icon> power </v-icon>
<v-icon> inventory </v-icon>
</v-list-item-icon>
<v-list-item-title v-text="'Text'" />
</v-list-item>
</template>
{{ t('localVersion.title') }}
{{ t('modpack.name', 2) }}
</v-tooltip>

<v-tooltip
v-if="sideBarShowCurseforge"
color="black"
transition="scroll-x-transition"
:close-delay="0"
right
>
<template #activator="{ on: tooltip }">
<v-list-item
push
link
class="non-moveable"
to="/curseforge/mc-mods"
v-on="tooltip"
>
<v-list-item-icon>
<v-icon>
$vuetify.icons.curseforge
</v-icon>
</v-list-item-icon>
<v-list-item-title>Curseforge</v-list-item-title>
</v-list-item>
</template>
Curseforge
</v-tooltip>

<v-tooltip
v-if="sideBarShowModrinth"
color="black"
transition="scroll-x-transition"
:close-delay="0"
right
>
<template #activator="{ on: tooltip }">
<v-list-item
push
link
class="non-moveable"
to="/modrinth"
v-on="tooltip"
>
<v-list-item-icon>
<v-icon>
$vuetify.icons.modrinth
</v-icon>
</v-list-item-icon>
<v-list-item-title>Modrinth</v-list-item-title>
</v-list-item>
</template>
Modrinth
</v-tooltip>

<v-tooltip
v-if="sideBarShowFtb"
color="black"
transition="scroll-x-transition"
:close-delay="0"
right
>
<template #activator="{ on: tooltip }">
<v-list-item
push
to="/modpack-setting"
link
class="non-moveable"
to="/ftb"
v-on="tooltip"
>
<v-list-item-icon>
<v-icon> inventory </v-icon>
<v-icon>
$vuetify.icons.ftb
</v-icon>
</v-list-item-icon>
<v-list-item-title v-text="'Text'" />
<v-list-item-title>FTB</v-list-item-title>
</v-list-item>
</template>
{{ t('modpack.name', 2) }}
Feed the Beast
</v-tooltip>
<v-divider />
</v-list-group>
<v-divider />
</v-list>

<AppSideBarContentFocus v-if="useFocus" />
Expand Down Expand Up @@ -201,6 +245,7 @@

<script lang=ts setup>
import { useService } from '@/composables'
import { useLocalStorageCacheBool } from '@/composables/cache'
import { injection } from '@/util/inject'
import { BaseServiceKey } from '@xmcl/runtime-api'
import PlayerAvatar from '../components/PlayerAvatar.vue'
Expand All @@ -212,11 +257,14 @@ import AppSideBarContentFocus from './AppSideBarContentFocus.vue'
import AppSideBarContentNext from './AppSideBarContentNext.vue'
const { state } = useService(BaseServiceKey)
const { gameProfile } = useCurrentUser()
const { blurSidebar } = useBarBlur()
const layout = injection(kUILayout)
const useFocus = computed(() => layout.value === 'focus')
const sideBarShowCurseforge = useLocalStorageCacheBool('sideBarShowCurseforge', true)
const sideBarShowModrinth = useLocalStorageCacheBool('sideBarShowModrinth', true)
const sideBarShowFtb = useLocalStorageCacheBool('sideBarShowFtb', true)
const { t } = useI18n()
const { sideBarColor } = injection(kColorTheme)
const { push, back, currentRoute } = useRouter()
Expand Down

0 comments on commit e848ab1

Please sign in to comment.