feat: make navigation use native links (#973)
This commit is contained in:
@@ -60,6 +60,20 @@ const showSessions = ref(
|
||||
let mobileQuery: MediaQueryList | null = null;
|
||||
const isMobile = ref(false);
|
||||
|
||||
function sessionHref(sessionId: string) {
|
||||
const profile = sessionProfile(sessionId);
|
||||
return router.resolve({
|
||||
name: "hermes.session",
|
||||
params: { sessionId },
|
||||
query: profile ? { profile } : undefined,
|
||||
}).href;
|
||||
}
|
||||
|
||||
function openSessionInNewTab(sessionId: string) {
|
||||
if (typeof window === "undefined") return;
|
||||
window.open(sessionHref(sessionId), "_blank", "noopener,noreferrer");
|
||||
}
|
||||
|
||||
async function handleSessionClick(sessionId: string) {
|
||||
const session = chatStore.sessions.find((item) => item.id === sessionId);
|
||||
await router.push({
|
||||
@@ -442,6 +456,7 @@ const contextMenuOptions = computed(() => {
|
||||
},
|
||||
],
|
||||
})
|
||||
options.push({ label: t("chat.openSessionInNewTab"), key: "open-link" })
|
||||
options.push({ label: t("chat.copySessionLink"), key: "copy-link" })
|
||||
options.push({ label: t("chat.copySessionId"), key: "copy-id" })
|
||||
return options
|
||||
@@ -478,6 +493,8 @@ async function handleContextMenuSelect(key: string) {
|
||||
copySessionLink(contextSessionId.value);
|
||||
} else if (key === "copy-id") {
|
||||
copySessionId(contextSessionId.value);
|
||||
} else if (key === "open-link") {
|
||||
openSessionInNewTab(contextSessionId.value);
|
||||
} else if (parseExportKey(key)) {
|
||||
const { mode, ext } = parseExportKey(key)!;
|
||||
const loadingMsg = mode === "compressed" ? message.loading(t("chat.exportCompressing"), { duration: 0 }) : null;
|
||||
@@ -846,6 +863,7 @@ async function handleSessionModelCustomSubmit() {
|
||||
:selectable="isBatchMode"
|
||||
:selected="isSessionSelected(s.id)"
|
||||
:show-profile="true"
|
||||
:to="sessionHref(s.id)"
|
||||
@select="handleSessionClick(s.id)"
|
||||
@contextmenu="handleContextMenu($event, s.id)"
|
||||
@delete="handleDeleteSession(s.id)"
|
||||
@@ -867,6 +885,7 @@ async function handleSessionModelCustomSubmit() {
|
||||
:selectable="isBatchMode"
|
||||
:selected="isSessionSelected(s.id)"
|
||||
:show-profile="true"
|
||||
:to="sessionHref(s.id)"
|
||||
@select="handleSessionClick(s.id)"
|
||||
@contextmenu="handleContextMenu($event, s.id)"
|
||||
@delete="handleDeleteSession(s.id)"
|
||||
@@ -1714,6 +1733,7 @@ async function handleSessionModelCustomSubmit() {
|
||||
border-radius: $radius-sm;
|
||||
cursor: pointer;
|
||||
text-align: left;
|
||||
text-decoration: none;
|
||||
color: $text-secondary;
|
||||
transition: all $transition-fast;
|
||||
margin-bottom: 2px;
|
||||
|
||||
@@ -17,6 +17,7 @@ const props = withDefaults(defineProps<{
|
||||
selectable?: boolean
|
||||
selected?: boolean
|
||||
showProfile?: boolean
|
||||
to?: string
|
||||
}>(), {
|
||||
showProfile: true,
|
||||
})
|
||||
@@ -77,11 +78,18 @@ function onTouchMove() {
|
||||
}
|
||||
}
|
||||
|
||||
function onClick() {
|
||||
function isModifiedNavigation(event?: MouseEvent) {
|
||||
return !!event && (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey || event.button !== 0)
|
||||
}
|
||||
|
||||
function onClick(event?: MouseEvent) {
|
||||
if (longPressTriggered.value) {
|
||||
longPressTriggered.value = false
|
||||
event?.preventDefault()
|
||||
return
|
||||
}
|
||||
if (isModifiedNavigation(event)) return
|
||||
if (props.to && !props.selectable) event?.preventDefault()
|
||||
emit('select')
|
||||
}
|
||||
|
||||
@@ -91,10 +99,13 @@ onUnmounted(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<button
|
||||
<component
|
||||
:is="selectable || !to ? 'button' : 'a'"
|
||||
class="session-item"
|
||||
:class="{ active, 'batch-mode': selectable, 'missing-models': profileModelsMissing }"
|
||||
:aria-current="active ? 'page' : undefined"
|
||||
:href="!selectable ? to : undefined"
|
||||
:type="selectable || !to ? 'button' : undefined"
|
||||
@click="onClick"
|
||||
@contextmenu="emit('contextmenu', $event)"
|
||||
@touchstart="onTouchStart"
|
||||
@@ -119,7 +130,7 @@ onUnmounted(() => {
|
||||
</span>
|
||||
<NTooltip v-if="profileModelsMissing" trigger="click" placement="top">
|
||||
<template #trigger>
|
||||
<button class="session-item-warning" type="button" @click.stop>
|
||||
<button class="session-item-warning" type="button" @click.stop.prevent>
|
||||
!
|
||||
</button>
|
||||
</template>
|
||||
@@ -137,13 +148,13 @@ onUnmounted(() => {
|
||||
</div>
|
||||
<NPopconfirm v-if="canDelete && !selectable" @positive-click="emit('delete')">
|
||||
<template #trigger>
|
||||
<button class="session-item-delete" @click.stop>
|
||||
<button class="session-item-delete" @click.stop.prevent>
|
||||
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
|
||||
</button>
|
||||
</template>
|
||||
{{ t('chat.deleteSession') }}
|
||||
</NPopconfirm>
|
||||
</button>
|
||||
</component>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
Reference in New Issue
Block a user