forked from BRETT/BRETT
Shorten thread route from /thread to /t
All internal links (tiles, prev/next nav, comments, notifications, breadcrumb, dropzone route check) point to /t/<id>. A global route middleware permanently redirects old /thread/<id> URLs including query string and comment anchor. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
@@ -47,7 +47,7 @@ const mergedComments = computed(() => {
|
|||||||
<NuxtLink
|
<NuxtLink
|
||||||
v-for="comment in mergedComments"
|
v-for="comment in mergedComments"
|
||||||
:key="comment.id"
|
:key="comment.id"
|
||||||
:to="`/thread/${comment.uploadId}#comment-${comment.id}`"
|
:to="`/t/${comment.uploadId}#comment-${comment.id}`"
|
||||||
class="block rounded-md border border-sidebar-border/60 bg-sidebar px-3 py-2.5 text-sm transition-colors hover:border-sidebar-border hover:bg-sidebar-accent"
|
class="block rounded-md border border-sidebar-border/60 bg-sidebar px-3 py-2.5 text-sm transition-colors hover:border-sidebar-border hover:bg-sidebar-accent"
|
||||||
>
|
>
|
||||||
<div class="flex items-center gap-2 text-xs text-muted-foreground">
|
<div class="flex items-center gap-2 text-xs text-muted-foreground">
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ const uploading = ref(false)
|
|||||||
|
|
||||||
// In Threads gilt die Zone nur für die obere Bildschirmhälfte —
|
// In Threads gilt die Zone nur für die obere Bildschirmhälfte —
|
||||||
// die untere Hälfte gehört den Kommentaren (dort Anhänge, sonst nichts)
|
// die untere Hälfte gehört den Kommentaren (dort Anhänge, sonst nichts)
|
||||||
const topHalfOnly = computed(() => route.path.startsWith('/thread/'))
|
const topHalfOnly = computed(() => route.path.startsWith('/t/'))
|
||||||
const pointerY = ref(0)
|
const pointerY = ref(0)
|
||||||
const inTopHalf = computed(() => !topHalfOnly.value || pointerY.value < (import.meta.client ? window.innerHeight : 0) / 2)
|
const inTopHalf = computed(() => !topHalfOnly.value || pointerY.value < (import.meta.client ? window.innerHeight : 0) / 2)
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ const timeAgo = useTimeAgo()
|
|||||||
async function goTo(n: AppNotification) {
|
async function goTo(n: AppNotification) {
|
||||||
open.value = false
|
open.value = false
|
||||||
await markRead(n.id)
|
await markRead(n.id)
|
||||||
await navigateTo(`/thread/${n.uploadId}#comment-${n.commentId}`)
|
await navigateTo(`/t/${n.uploadId}#comment-${n.commentId}`)
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ const crumbs = computed<Crumb[]>(() => {
|
|||||||
const list: Crumb[] = [{ label: t('palette.home'), to: '/' }]
|
const list: Crumb[] = [{ label: t('palette.home'), to: '/' }]
|
||||||
const p = route.path
|
const p = route.path
|
||||||
if (p === '/') return []
|
if (p === '/') return []
|
||||||
if (p.startsWith('/thread/')) list.push({ label: t('nav.thread') })
|
if (p.startsWith('/t/')) list.push({ label: t('nav.thread') })
|
||||||
else if (p === '/users') list.push({ label: t('nav.users') })
|
else if (p === '/users') list.push({ label: t('nav.users') })
|
||||||
else if (p.startsWith('/user/')) {
|
else if (p.startsWith('/user/')) {
|
||||||
list.push({ label: t('nav.users'), to: '/users' }, { label: t('nav.profile') })
|
list.push({ label: t('nav.users'), to: '/users' }, { label: t('nav.profile') })
|
||||||
|
|||||||
@@ -120,14 +120,14 @@ async function openUpload(e: MouseEvent) {
|
|||||||
|
|
||||||
// Die eigentliche Navigation macht der NuxtLink bereits beim Klick —
|
// Die eigentliche Navigation macht der NuxtLink bereits beim Klick —
|
||||||
// dieser Push ist nur noch Fallback und bei gleicher Route ein No-Op
|
// dieser Push ist nur noch Fallback und bei gleicher Route ein No-Op
|
||||||
await router.push(`/thread/${props.upload.id}`)
|
await router.push(`/t/${props.upload.id}`)
|
||||||
navigating.value = false
|
navigating.value = false
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<NuxtLink
|
<NuxtLink
|
||||||
:to="`/thread/${upload.id}`"
|
:to="`/t/${upload.id}`"
|
||||||
class="upload-tile group block"
|
class="upload-tile group block"
|
||||||
:class="[spanClass, navigating ? 'opacity-80' : '']"
|
:class="[spanClass, navigating ? 'opacity-80' : '']"
|
||||||
@click.capture="captureClick"
|
@click.capture="captureClick"
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
// Alter Thread-Pfad — /thread/<id> leitet dauerhaft auf /t/<id> um
|
||||||
|
export default defineNuxtRouteMiddleware((to) => {
|
||||||
|
if (to.path.startsWith('/thread/')) {
|
||||||
|
return navigateTo({ path: to.path.replace(/^\/thread\//, '/t/'), query: to.query, hash: to.hash }, { redirectCode: 301 })
|
||||||
|
}
|
||||||
|
})
|
||||||
@@ -598,7 +598,7 @@ async function deleteComment(commentId: number) {
|
|||||||
class="absolute left-2 top-1/2 -translate-y-1/2 shadow opacity-80 hover:opacity-100"
|
class="absolute left-2 top-1/2 -translate-y-1/2 shadow opacity-80 hover:opacity-100"
|
||||||
as-child
|
as-child
|
||||||
>
|
>
|
||||||
<NuxtLink :to="`/thread/${data.newerId}`" :aria-label="$t('thread.newer')">
|
<NuxtLink :to="`/t/${data.newerId}`" :aria-label="$t('thread.newer')">
|
||||||
<Icon name="ph:caret-left-fill" class="size-5" />
|
<Icon name="ph:caret-left-fill" class="size-5" />
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
</Button>
|
</Button>
|
||||||
@@ -609,7 +609,7 @@ async function deleteComment(commentId: number) {
|
|||||||
class="absolute right-2 top-1/2 -translate-y-1/2 shadow opacity-80 hover:opacity-100"
|
class="absolute right-2 top-1/2 -translate-y-1/2 shadow opacity-80 hover:opacity-100"
|
||||||
as-child
|
as-child
|
||||||
>
|
>
|
||||||
<NuxtLink :to="`/thread/${data.olderId}`" :aria-label="$t('thread.older')">
|
<NuxtLink :to="`/t/${data.olderId}`" :aria-label="$t('thread.older')">
|
||||||
<Icon name="ph:caret-right-fill" class="size-5" />
|
<Icon name="ph:caret-right-fill" class="size-5" />
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
</Button>
|
</Button>
|
||||||
@@ -313,7 +313,7 @@ const timeAgo = useTimeAgo()
|
|||||||
<NuxtLink
|
<NuxtLink
|
||||||
v-for="comment in comments.items"
|
v-for="comment in comments.items"
|
||||||
:key="comment.id"
|
:key="comment.id"
|
||||||
:to="`/thread/${comment.uploadId}#comment-${comment.id}`"
|
:to="`/t/${comment.uploadId}#comment-${comment.id}`"
|
||||||
class="flex items-center gap-3 px-3 py-2.5 text-sm transition-colors hover:bg-accent"
|
class="flex items-center gap-3 px-3 py-2.5 text-sm transition-colors hover:bg-accent"
|
||||||
>
|
>
|
||||||
<NuxtImg
|
<NuxtImg
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ export default defineNuxtPlugin(() => {
|
|||||||
description: n.content?.slice(0, 80) || undefined,
|
description: n.content?.slice(0, 80) || undefined,
|
||||||
action: {
|
action: {
|
||||||
label: $i18n.t('notifications.view'),
|
label: $i18n.t('notifications.view'),
|
||||||
onClick: () => navigateTo(`/thread/${n.uploadId}#comment-${n.commentId}`),
|
onClick: () => navigateTo(`/t/${n.uploadId}#comment-${n.commentId}`),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user