Skip to content

Commit

Permalink
refactor: Make more tooltip to use shared tooltip to reduce memory usage
Browse files Browse the repository at this point in the history
  • Loading branch information
ci010 committed Nov 20, 2024
1 parent 07dbc9e commit 9d5ad54
Show file tree
Hide file tree
Showing 7 changed files with 176 additions and 182 deletions.
27 changes: 26 additions & 1 deletion xmcl-keystone-ui/src/components/AppSharedTooltip.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,28 @@
:right="cached.right"
:bottom="cached.bottom"
>
{{ cached?.text }}
{{ cached.text }}
<div v-if="cached.items">
<template v-for="r of cached.items">
<v-avatar
:key="r.icon + 'icon'"
size="28"
>
<img :src="r.icon">
</v-avatar>
{{ r.text }}
</template>
</div>
<template v-if="cached.list">
<ul>
<li
v-for="i in cached.list"
:key="i"
>
{{ i }}
</li>
</ul>
</template>
</v-tooltip>
</template>

Expand All @@ -32,6 +53,8 @@ watch(cur, (v) => {
bottom: v.direction === 'bottom',
color: v.color,
text: v.text,
items: v.items,
list: v.list,
}
cached.value = newValue
}
Expand All @@ -46,6 +69,8 @@ const cached = shallowRef({
bottom: false,
color: '',
text: '',
items: [] as ({ icon: string; text: string }[]) | undefined,
list: [] as string[] | undefined,
})
</script>
2 changes: 1 addition & 1 deletion xmcl-keystone-ui/src/components/MarketItem.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<template>
<v-list-item
v-context-menu="getContextMenuItems"
v-shared-tooltip="[tooltip, hasUpdate ? 'primary' : 'black']"
v-shared-tooltip="{ text: tooltip, color: hasUpdate ? 'primary' : 'black' }"
:style="{
minHeight: height ? height + 'px' : undefined,
maxHeight: height ? height + 'px' : undefined
Expand Down
4 changes: 2 additions & 2 deletions xmcl-keystone-ui/src/composables/sharedTooltip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ export interface SharedTooltipData {
x: number
y: number
color: string
items: Array<{ text: string; icon: string }> | undefined
list: Array<string> | undefined
}

const data = shallowRef(undefined as SharedTooltipData | undefined)

export function useSharedTooltipData() {
return {
isShown,
Expand Down
29 changes: 24 additions & 5 deletions xmcl-keystone-ui/src/directives/sharedTooltip.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
import { SharedTooltipData, useSharedTooltipData } from '@/composables/sharedTooltip'
import { FunctionDirective } from 'vue'

export const vSharedTooltip: FunctionDirective<HTMLElement, ((v?: any) => string) | string | [string, string]> = (el, bindings, node, prevNode) => {
export type VSharedTooltipParam = {
text: string
items?: Array<{ icon: string; text: string }>
color?: string
list?: Array<string>
} | string

export const vSharedTooltip: FunctionDirective<HTMLElement, ((v?: any) => VSharedTooltipParam) | VSharedTooltipParam> = (el, bindings, node, prevNode) => {
if (prevNode.tag) return
const { blocked, isShown, stack, setValue } = useSharedTooltipData()
el.addEventListener('mouseenter', (e) => {
Expand All @@ -15,6 +22,8 @@ export const vSharedTooltip: FunctionDirective<HTMLElement, ((v?: any) => string
x: 0,
y: 0,
color: 'black',
items: undefined,
list: undefined,
}
if (bindings.modifiers.left) {
newData.direction = 'left'
Expand All @@ -40,14 +49,24 @@ export const vSharedTooltip: FunctionDirective<HTMLElement, ((v?: any) => string
newData.y = rect.y + rect.width / 2
}

function assign(val: VSharedTooltipParam) {
if (typeof val === 'string') {
newData.text = val
} else {
newData.text = val.text || ''
newData.items = val.items
newData.color = val.color || ''
newData.list = val.list
}
}

const val = bindings.value
if (typeof val === 'string') {
newData.text = val
} else if (val instanceof Array) {
newData.text = val[0]
newData.color = val[1]
} else if (typeof val === 'object') {
assign(val)
} else if (typeof val === 'function') {
newData.text = val()
assign(val())
}

stack.value = [...stack.value, markRaw(newData)]
Expand Down
41 changes: 16 additions & 25 deletions xmcl-keystone-ui/src/views/AppSideBarContentNext.vue
Original file line number Diff line number Diff line change
Expand Up @@ -36,27 +36,17 @@
class="non-moveable"
@click="showAddInstance()"
>
<v-tooltip
:close-delay="0"
color="black"
transition="scroll-x-transition"
right
<v-list-item-avatar
id="create-instance-button"
v-shared-tooltip.right="_ => t('instances.add')"
size="48"
class="bg-[rgba(80,80,80,0.4)] transition-all duration-300 hover:rounded-xl hover:bg-green-500"
large
>
<template #activator="{ on: tooltip }">
<v-list-item-avatar
id="create-instance-button"
size="48"
class="bg-[rgba(80,80,80,0.4)] transition-all duration-300 hover:rounded-xl hover:bg-green-500"
large
v-on="tooltip"
>
<v-icon class="text-3xl">
add
</v-icon>
</v-list-item-avatar>
</template>
{{ t('instances.add') }}
</v-tooltip>
<v-icon class="text-3xl">
add
</v-icon>
</v-list-item-avatar>

<v-list-item-title>Instance</v-list-item-title>
</v-list-item>
Expand All @@ -80,19 +70,20 @@
import SimpleDialog from '@/components/SimpleDialog.vue'
import { useService } from '@/composables'
import { useDialog } from '@/composables/dialog'
import { useInstanceGroup, useInstanceGroupDefaultColor } from '@/composables/instanceGroup'
import { AddInstanceDialogKey } from '@/composables/instanceTemplates'
import { kInstances } from '@/composables/instances'
import { injection } from '@/util/inject'
import { InstanceSavesServiceKey, InstanceServiceKey } from '@xmcl/runtime-api'
import AppSideBarInstanceItem from './AppSideBarInstanceItem.vue'
import { useNotifier } from '@/composables/notifier'
import { useInstanceGroup, useInstanceGroupDefaultColor } from '@/composables/instanceGroup'
import { vSharedTooltip } from '@/directives/sharedTooltip'
import { injection } from '@/util/inject'
import { InstanceSavesServiceKey } from '@xmcl/runtime-api'
import AppSideBarGroupItem from './AppSideBarGroupItem.vue'
import AppSideBarGroupSettingDialog from './AppSideBarGroupSettingDialog.vue'
import AppSideBarInstanceItem from './AppSideBarInstanceItem.vue'
const { t } = useI18n()
const { instances, isValidating } = injection(kInstances)
const { isValidating } = injection(kInstances)
const { show: showAddInstance } = useDialog(AddInstanceDialogKey)
Expand Down
141 changes: 60 additions & 81 deletions xmcl-keystone-ui/src/views/AppSideBarGroupItem.vue
Original file line number Diff line number Diff line change
@@ -1,90 +1,68 @@
<template>
<v-tooltip
:close-delay="0"
color="black"
transition="scroll-x-transition"
right
<v-sheet
class="relative rounded-xl hover:rounded-lg! transition-all"
:color="color"
>
<template #activator="{ on: tooltip }">
<v-sheet
class="relative rounded-xl hover:rounded-lg! transition-all"
:color="color"
<AppSideBarGroupItemIndicator :state="overState" />
<v-list-item
v-context-menu="getItems"
v-shared-tooltip.right="() => group.name ? group.name : { list: instances.map(instance => instance.name || `Minecraft ${instance.runtime.minecraft}`) }"
push
link
draggable
class="non-moveable sidebar-item flex-1 flex-grow-0 px-2"
@click="onClick"
@dragover.prevent
@dragstart="onDragStart"
@dragend="onDragEnd"
@dragover="onDragOver"
@dragenter="onDragEnter"
@dragleave="onDragLeave"
@drop="onDrop"
>
<v-list-item-avatar
size="48"
class="transition-all duration-300 rounded"
large
>
<AppSideBarGroupItemIndicator :state="overState" />
<v-list-item
v-context-menu="getItems"
push
link
draggable
class="non-moveable sidebar-item flex-1 flex-grow-0 px-2"
v-on="tooltip"
@click="onClick"
@dragover.prevent
@dragstart="onDragStart"
@dragend="onDragEnd"
@dragover="onDragOver"
@dragenter="onDragEnter"
@dragleave="onDragLeave"
@drop="onDrop"
<Transition
name="scroll-y-reverse-transition"
mode="out-in"
>
<v-list-item-avatar
size="48"
class="transition-all duration-300 rounded"
large
>
<Transition
name="scroll-y-reverse-transition"
mode="out-in"
>
<v-skeleton-loader
v-if="dragging"
type="avatar"
/>
<div
v-else-if="!expanded"
class="grid cols-2 rows-2 gap-[2px] p-[2px] rounded-xl"
>
<v-img
v-for="i in instances.slice(0, 4)"
:key="i.path"
:style="{ maxHeight: '20px', maxWidth: '20px' }"
:src="getInstanceIcon(i, i.server ? undefined : undefined)"
@dragenter="onDragEnter"
@dragleave="onDragLeave"
/>
</div>
<v-icon v-else>
folder
</v-icon>
</Transition>
</v-list-item-avatar>
<v-list-item-title>123</v-list-item-title>
</v-list-item>
<template v-if="expanded">
<AppSideBarInstanceItem
v-for="(instance, index) in group.instances"
:key="instance + index"
:path="instance"
inside
@arrange="emit('arrange', { ...$event, toPath: instance })"
<v-skeleton-loader
v-if="dragging"
type="avatar"
/>
</template>
</v-sheet>
</template>
<template v-if="group.name">
{{ group.name }}
</template>
<template v-else>
<ul>
<li
v-for="instance in instances"
:key="instance.path"
>
{{ instance.name || `Minecraft ${instance.runtime.minecraft}` }}
</li>
</ul>
<div
v-else-if="!expanded"
class="grid cols-2 rows-2 gap-[2px] p-[2px] rounded-xl"
>
<v-img
v-for="i in instances.slice(0, 4)"
:key="i.path"
:style="{ maxHeight: '20px', maxWidth: '20px' }"
:src="getInstanceIcon(i, i.server ? undefined : undefined)"
@dragenter="onDragEnter"
@dragleave="onDragLeave"
/>
</div>
<v-icon v-else>
folder
</v-icon>
</Transition>
</v-list-item-avatar>
<v-list-item-title>123</v-list-item-title>
</v-list-item>
<template v-if="expanded">
<AppSideBarInstanceItem
v-for="(instance, index) in group.instances"
:key="instance + index"
:path="instance"
inside
@arrange="emit('arrange', { ...$event, toPath: instance })"
/>
</template>
</v-tooltip>
</v-sheet>
</template>
<script lang="ts" setup>
import { InstanceGroupData, useGroupDragDropState } from '@/composables/instanceGroup'
Expand All @@ -97,6 +75,7 @@ import { notNullish } from '@vueuse/core'
import { vContextMenu } from '@/directives/contextMenu'
import { ContextMenuItem } from '@/composables/contextMenu'
import { useDialog } from '@/composables/dialog'
import { vSharedTooltip } from '@/directives/sharedTooltip'
const props = defineProps<{ group: InstanceGroupData; color: string }>()
const emit = defineEmits(['arrange', 'drop-save', 'group'])
Expand Down
Loading

0 comments on commit 9d5ad54

Please sign in to comment.