mirror of
https://github.com/elk-zone/elk.git
synced 2024-11-22 01:15:25 +03:00
fix: type errors (#802)
This commit is contained in:
parent
272fb4a13d
commit
acdb94de62
24 changed files with 113 additions and 74 deletions
|
@ -1,4 +1,6 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
// type used in <template>
|
||||||
|
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
|
||||||
import type { Account } from 'masto'
|
import type { Account } from 'masto'
|
||||||
|
|
||||||
defineProps<{
|
defineProps<{
|
||||||
|
@ -14,8 +16,9 @@ defineProps<{
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div flex>
|
<div flex>
|
||||||
<NuxtLink :to="getAccountRoute(account.moved as any)">
|
<!-- type error of masto.js -->
|
||||||
<AccountInfo :account="account.moved" />
|
<NuxtLink :to="getAccountRoute(account.moved as unknown as Account)">
|
||||||
|
<AccountInfo :account="account.moved as unknown as Account" />
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
<div flex-auto />
|
<div flex-auto />
|
||||||
<div flex items-center>
|
<div flex items-center>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { SearchResult as SearchResultType } from '@/components/search/types'
|
import type { AccountResult, HashTagResult, SearchResult as SearchResultType } from '@/components/search/types'
|
||||||
import type { CommandScope, QueryResult, QueryResultItem } from '@/composables/command'
|
import type { CommandScope, QueryResult, QueryResultItem } from '@/composables/command'
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
|
@ -37,11 +37,23 @@ const searchResult = $computed<QueryResult>(() => {
|
||||||
if (query.length === 0 || loading.value)
|
if (query.length === 0 || loading.value)
|
||||||
return { length: 0, items: [], grouped: {} as any }
|
return { length: 0, items: [], grouped: {} as any }
|
||||||
|
|
||||||
|
// TODO extract this scope
|
||||||
|
// duplicate in SearchWidget.vue
|
||||||
const hashtagList = hashtags.value.slice(0, 3)
|
const hashtagList = hashtags.value.slice(0, 3)
|
||||||
.map<SearchResultType>(hashtag => ({ type: 'hashtag', hashtag, to: `/tags/${hashtag.name}` }))
|
.map<HashTagResult>(hashtag => ({
|
||||||
|
type: 'hashtag',
|
||||||
|
id: hashtag.id,
|
||||||
|
hashtag,
|
||||||
|
to: getTagRoute(hashtag.name),
|
||||||
|
}))
|
||||||
.map(toSearchQueryResultItem)
|
.map(toSearchQueryResultItem)
|
||||||
const accountList = accounts.value
|
const accountList = accounts.value
|
||||||
.map<SearchResultType>(account => ({ type: 'account', account, to: `/@${account.acct}` }))
|
.map<AccountResult>(account => ({
|
||||||
|
type: 'account',
|
||||||
|
id: account.id,
|
||||||
|
account,
|
||||||
|
to: getAccountRoute(account),
|
||||||
|
}))
|
||||||
.map(toSearchQueryResultItem)
|
.map(toSearchQueryResultItem)
|
||||||
|
|
||||||
const grouped: QueryResult['grouped'] = new Map()
|
const grouped: QueryResult['grouped'] = new Map()
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
import { decode } from 'blurhash'
|
import { decode } from 'blurhash'
|
||||||
|
|
||||||
const { blurhash, src, srcset } = defineProps<{
|
const { blurhash, src, srcset } = defineProps<{
|
||||||
blurhash: string
|
blurhash?: string | null | undefined
|
||||||
src: string
|
src: string
|
||||||
srcset?: string
|
srcset?: string
|
||||||
}>()
|
}>()
|
||||||
|
@ -11,8 +11,13 @@ defineOptions({
|
||||||
inheritAttrs: false,
|
inheritAttrs: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
const placeholderSrc = ref<string>()
|
|
||||||
const isLoaded = ref(false)
|
const isLoaded = ref(false)
|
||||||
|
const placeholderSrc = $computed(() => {
|
||||||
|
if (!blurhash)
|
||||||
|
return ''
|
||||||
|
const pixels = decode(blurhash, 32, 32)
|
||||||
|
return getDataUrlFromArr(pixels, 32, 32)
|
||||||
|
})
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
const img = document.createElement('img')
|
const img = document.createElement('img')
|
||||||
|
@ -29,11 +34,6 @@ onMounted(() => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
isLoaded.value = true
|
isLoaded.value = true
|
||||||
}, 3_000)
|
}, 3_000)
|
||||||
|
|
||||||
if (blurhash) {
|
|
||||||
const pixels = decode(blurhash, 32, 32)
|
|
||||||
placeholderSrc.value = getDataUrlFromArr(pixels, 32, 32)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ import 'vue-advanced-cropper/dist/style.css'
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
/** Images to be cropped */
|
/** Images to be cropped */
|
||||||
modelValue?: File
|
modelValue?: File | null
|
||||||
/** Crop frame aspect ratio (width/height), default 1/1 */
|
/** Crop frame aspect ratio (width/height), default 1/1 */
|
||||||
stencilAspectRatio?: number
|
stencilAspectRatio?: number
|
||||||
/** The ratio of the longest edge of the cut box to the length of the cut screen, default 0.9, not more than 1 */
|
/** The ratio of the longest edge of the cut box to the length of the cut screen, default 0.9, not more than 1 */
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { fileOpen } from 'browser-fs-access'
|
||||||
import type { FileWithHandle } from 'browser-fs-access'
|
import type { FileWithHandle } from 'browser-fs-access'
|
||||||
|
|
||||||
const props = withDefaults(defineProps<{
|
const props = withDefaults(defineProps<{
|
||||||
modelValue?: FileWithHandle
|
modelValue?: FileWithHandle | null
|
||||||
/** The image src before change */
|
/** The image src before change */
|
||||||
original?: string
|
original?: string
|
||||||
/** Allowed file types */
|
/** Allowed file types */
|
||||||
|
|
|
@ -53,6 +53,7 @@ const handlePublishClose = () => {
|
||||||
>
|
>
|
||||||
<!-- This `w-0` style is used to avoid overflow problems in flex layouts,so don't remove it unless you know what you're doing -->
|
<!-- This `w-0` style is used to avoid overflow problems in flex layouts,so don't remove it unless you know what you're doing -->
|
||||||
<PublishWidget
|
<PublishWidget
|
||||||
|
v-if="dialogDraftKey"
|
||||||
:draft-key="dialogDraftKey" expanded flex-1 w-0
|
:draft-key="dialogDraftKey" expanded flex-1 w-0
|
||||||
@published="handlePublished"
|
@published="handlePublished"
|
||||||
/>
|
/>
|
||||||
|
@ -65,7 +66,7 @@ const handlePublishClose = () => {
|
||||||
<ModalMediaPreview v-if="isMediaPreviewOpen" @close="closeMediaPreview()" />
|
<ModalMediaPreview v-if="isMediaPreviewOpen" @close="closeMediaPreview()" />
|
||||||
</ModalDialog>
|
</ModalDialog>
|
||||||
<ModalDialog v-model="isEditHistoryDialogOpen" max-w-125>
|
<ModalDialog v-model="isEditHistoryDialogOpen" max-w-125>
|
||||||
<StatusEditPreview :edit="statusEdit" />
|
<StatusEditPreview v-if="statusEdit" :edit="statusEdit" />
|
||||||
</ModalDialog>
|
</ModalDialog>
|
||||||
<ModalDialog v-model="isCommandPanelOpen" max-w-fit flex>
|
<ModalDialog v-model="isCommandPanelOpen" max-w-fit flex>
|
||||||
<CommandPanel @close="closeCommandPanel()" />
|
<CommandPanel @close="closeCommandPanel()" />
|
||||||
|
|
|
@ -1,5 +1,11 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
// type used in <template>
|
||||||
|
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
|
||||||
import type { Notification, Paginator, WsEvents } from 'masto'
|
import type { Notification, Paginator, WsEvents } from 'masto'
|
||||||
|
// type used in <template>
|
||||||
|
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
|
||||||
|
import type { GroupedLikeNotifications } from '~/types'
|
||||||
|
|
||||||
import type { GroupedAccountLike, NotificationSlot } from '~/types'
|
import type { GroupedAccountLike, NotificationSlot } from '~/types'
|
||||||
|
|
||||||
const { paginator, stream } = defineProps<{
|
const { paginator, stream } = defineProps<{
|
||||||
|
@ -118,12 +124,12 @@ const { formatNumber } = useHumanReadableNumber()
|
||||||
/>
|
/>
|
||||||
<NotificationGroupedLikes
|
<NotificationGroupedLikes
|
||||||
v-else-if="item.type === 'grouped-reblogs-and-favourites'"
|
v-else-if="item.type === 'grouped-reblogs-and-favourites'"
|
||||||
:group="item"
|
:group="item as GroupedLikeNotifications"
|
||||||
border="b base"
|
border="b base"
|
||||||
/>
|
/>
|
||||||
<NotificationCard
|
<NotificationCard
|
||||||
v-else
|
v-else
|
||||||
:notification="item"
|
:notification="item as Notification"
|
||||||
hover:bg-active
|
hover:bg-active
|
||||||
border="b base"
|
border="b base"
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -269,7 +269,7 @@ defineExpose({
|
||||||
<PublishAttachment
|
<PublishAttachment
|
||||||
v-for="(att, idx) in draft.attachments" :key="att.id"
|
v-for="(att, idx) in draft.attachments" :key="att.id"
|
||||||
:attachment="att"
|
:attachment="att"
|
||||||
:dialog-labelled-by="dialogLabelledBy ?? (draft.editingStatus ? 'state-editing' : null)"
|
:dialog-labelled-by="dialogLabelledBy ?? (draft.editingStatus ? 'state-editing' : undefined)"
|
||||||
@remove="removeAttachment(idx)"
|
@remove="removeAttachment(idx)"
|
||||||
@set-description="setDescription(att, $event)"
|
@set-description="setDescription(att, $event)"
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { SearchResult } from './types'
|
import type { SearchResult } from './types'
|
||||||
defineProps<{ result: SearchResult; active: boolean }>()
|
|
||||||
|
defineProps<{
|
||||||
|
result: SearchResult
|
||||||
|
active: boolean
|
||||||
|
}>()
|
||||||
|
|
||||||
const onActivate = () => {
|
const onActivate = () => {
|
||||||
(document.activeElement as HTMLElement).blur()
|
(document.activeElement as HTMLElement).blur()
|
||||||
|
@ -10,10 +14,10 @@ const onActivate = () => {
|
||||||
<template>
|
<template>
|
||||||
<CommonScrollIntoView as="RouterLink" :active="active" :to="result.to" py2 block px2 :aria-selected="active" :class="{ 'bg-active': active }" hover:bg-active @click="() => onActivate()">
|
<CommonScrollIntoView as="RouterLink" :active="active" :to="result.to" py2 block px2 :aria-selected="active" :class="{ 'bg-active': active }" hover:bg-active @click="() => onActivate()">
|
||||||
<SearchHashtagInfo v-if="result.type === 'hashtag'" :hashtag="result.hashtag" />
|
<SearchHashtagInfo v-if="result.type === 'hashtag'" :hashtag="result.hashtag" />
|
||||||
<AccountInfo v-else-if="result.type === 'account'" :account="result.account" />
|
<AccountInfo v-else-if="result.type === 'account' && result.account" :account="result.account" />
|
||||||
<StatusCard v-else-if="result.type === 'status'" :status="result.status" :actions="false" :show-reply-to="false" />
|
<StatusCard v-else-if="result.type === 'status' && result.status" :status="result.status" :actions="false" :show-reply-to="false" />
|
||||||
<div v-else-if="result.type === 'action'" text-center>
|
<!-- <div v-else-if="result.type === 'action'" text-center>
|
||||||
{{ result.action!.label }}
|
{{ result.action!.label }}
|
||||||
</div>
|
</div> -->
|
||||||
</CommonScrollIntoView>
|
</CommonScrollIntoView>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import type { AccountResult, HashTagResult, StatusResult } from './types'
|
||||||
|
|
||||||
const query = ref('')
|
const query = ref('')
|
||||||
const { accounts, hashtags, loading, statuses } = useSearch(query)
|
const { accounts, hashtags, loading, statuses } = useSearch(query)
|
||||||
const index = ref(0)
|
const index = ref(0)
|
||||||
|
@ -13,9 +15,24 @@ const results = computed(() => {
|
||||||
return []
|
return []
|
||||||
|
|
||||||
const results = [
|
const results = [
|
||||||
...hashtags.value.slice(0, 3).map(hashtag => ({ type: 'hashtag', hashtag, to: getTagRoute(hashtag.name) })),
|
...hashtags.value.slice(0, 3).map<HashTagResult>(hashtag => ({
|
||||||
...accounts.value.map(account => ({ type: 'account', account, to: getAccountRoute(account) })),
|
type: 'hashtag',
|
||||||
...statuses.value.map(status => ({ type: 'status', status, to: getStatusRoute(status) })),
|
id: hashtag.id,
|
||||||
|
hashtag,
|
||||||
|
to: getTagRoute(hashtag.name),
|
||||||
|
})),
|
||||||
|
...accounts.value.map<AccountResult>(account => ({
|
||||||
|
type: 'account',
|
||||||
|
id: account.id,
|
||||||
|
account,
|
||||||
|
to: getAccountRoute(account),
|
||||||
|
})),
|
||||||
|
...statuses.value.map<StatusResult>(status => ({
|
||||||
|
type: 'status',
|
||||||
|
id: status.id,
|
||||||
|
status,
|
||||||
|
to: getStatusRoute(status),
|
||||||
|
})),
|
||||||
|
|
||||||
// Disable until search page is implemented
|
// Disable until search page is implemented
|
||||||
// {
|
// {
|
||||||
|
@ -79,7 +96,12 @@ const activate = () => {
|
||||||
{{ t('search.search_desc') }}
|
{{ t('search.search_desc') }}
|
||||||
</span>
|
</span>
|
||||||
<template v-if="!loading">
|
<template v-if="!loading">
|
||||||
<SearchResult v-for="(result, i) in results" :key="result.to" :active="index === parseInt(i.toString())" :result="result" :tabindex="focused ? 0 : -1" />
|
<SearchResult
|
||||||
|
v-for="(result, i) in results" :key="result.id"
|
||||||
|
:active="index === parseInt(i.toString())"
|
||||||
|
:result="result"
|
||||||
|
:tabindex="focused ? 0 : -1"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
<div v-else>
|
<div v-else>
|
||||||
<SearchResultSkeleton />
|
<SearchResultSkeleton />
|
||||||
|
|
|
@ -1,13 +1,17 @@
|
||||||
import type { Account, Status } from 'masto'
|
import type { Account, Status } from 'masto'
|
||||||
|
import type { RouteLocation } from 'vue-router'
|
||||||
|
|
||||||
export interface SearchResult {
|
export type BuildResult<K extends keyof any, T> = {
|
||||||
type: 'account' | 'hashtag' | 'action' | 'status'
|
[P in K]: T
|
||||||
to: string
|
} & {
|
||||||
label?: string
|
id: string
|
||||||
account?: Account
|
type: K
|
||||||
status?: Status
|
to: RouteLocation & {
|
||||||
hashtag?: any
|
href: string
|
||||||
action?: {
|
|
||||||
label: string
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
export type HashTagResult = BuildResult<'hashtag', any>
|
||||||
|
export type AccountResult = BuildResult<'account', Account>
|
||||||
|
export type StatusResult = BuildResult<'status', Status>
|
||||||
|
|
||||||
|
export type SearchResult = HashTagResult | AccountResult | StatusResult
|
||||||
|
|
|
@ -64,7 +64,7 @@ const reply = () => {
|
||||||
color="text-green" hover="text-green" group-hover="bg-green/10"
|
color="text-green" hover="text-green" group-hover="bg-green/10"
|
||||||
icon="i-ri:repeat-line"
|
icon="i-ri:repeat-line"
|
||||||
active-icon="i-ri:repeat-fill"
|
active-icon="i-ri:repeat-fill"
|
||||||
:active="status.reblogged"
|
:active="!!status.reblogged"
|
||||||
:disabled="isLoading.reblogged"
|
:disabled="isLoading.reblogged"
|
||||||
:command="command"
|
:command="command"
|
||||||
@click="toggleReblog()"
|
@click="toggleReblog()"
|
||||||
|
@ -88,7 +88,7 @@ const reply = () => {
|
||||||
color="text-rose" hover="text-rose" group-hover="bg-rose/10"
|
color="text-rose" hover="text-rose" group-hover="bg-rose/10"
|
||||||
icon="i-ri:heart-3-line"
|
icon="i-ri:heart-3-line"
|
||||||
active-icon="i-ri:heart-3-fill"
|
active-icon="i-ri:heart-3-fill"
|
||||||
:active="status.favourited"
|
:active="!!status.favourited"
|
||||||
:disabled="isLoading.favourited"
|
:disabled="isLoading.favourited"
|
||||||
:command="command"
|
:command="command"
|
||||||
@click="toggleFavourite()"
|
@click="toggleFavourite()"
|
||||||
|
@ -111,7 +111,7 @@ const reply = () => {
|
||||||
color="text-yellow" hover="text-yellow" group-hover="bg-yellow/10"
|
color="text-yellow" hover="text-yellow" group-hover="bg-yellow/10"
|
||||||
icon="i-ri:bookmark-line"
|
icon="i-ri:bookmark-line"
|
||||||
active-icon="i-ri:bookmark-fill"
|
active-icon="i-ri:bookmark-fill"
|
||||||
:active="status.bookmarked"
|
:active="!!status.bookmarked"
|
||||||
:disabled="isLoading.bookmarked"
|
:disabled="isLoading.bookmarked"
|
||||||
:command="command"
|
:command="command"
|
||||||
@click="toggleBookmark()"
|
@click="toggleBookmark()"
|
||||||
|
|
|
@ -186,9 +186,8 @@ async function editStatus() {
|
||||||
@click="toggleMute()"
|
@click="toggleMute()"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<NuxtLink :to="status.url" external target="_blank">
|
<NuxtLink v-if="status.url" :to="status.url" external target="_blank">
|
||||||
<CommonDropdownItem
|
<CommonDropdownItem
|
||||||
v-if="status.url"
|
|
||||||
:text="$t('menu.open_in_original_site')"
|
:text="$t('menu.open_in_original_site')"
|
||||||
icon="i-ri:arrow-right-up-line"
|
icon="i-ri:arrow-right-up-line"
|
||||||
:command="command"
|
:command="command"
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { Status } from 'masto'
|
import type { Status, StatusEdit } from 'masto'
|
||||||
|
|
||||||
const { status, withAction = true } = defineProps<{
|
const { status, withAction = true } = defineProps<{
|
||||||
status: Status
|
status: Status | StatusEdit
|
||||||
withAction?: boolean
|
withAction?: boolean
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const { translation } = useTranslation(status)
|
const { translation } = useTranslation(status)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -15,7 +16,7 @@ const { translation } = useTranslation(status)
|
||||||
class="line-compact"
|
class="line-compact"
|
||||||
:content="status.content"
|
:content="status.content"
|
||||||
:emojis="status.emojis"
|
:emojis="status.emojis"
|
||||||
:lang="status.language"
|
:lang="'language' in status && status.language"
|
||||||
/>
|
/>
|
||||||
<div v-else />
|
<div v-else />
|
||||||
<template v-if="translation.visible">
|
<template v-if="translation.visible">
|
||||||
|
|
|
@ -113,7 +113,7 @@ const isDM = $computed(() => status.visibility === 'direct')
|
||||||
</div>
|
</div>
|
||||||
<div v-else />
|
<div v-else />
|
||||||
</slot>
|
</slot>
|
||||||
<StatusReplyingTo v-if="!directReply && !collapseReplyingTo" :status="status" :simplified="simplifyReplyingTo" :class="faded ? 'text-secondary-light' : ''" pt1 />
|
<StatusReplyingTo v-if="!directReply && !collapseReplyingTo" :status="status" :simplified="!!simplifyReplyingTo" :class="faded ? 'text-secondary-light' : ''" pt1 />
|
||||||
</div>
|
</div>
|
||||||
<div flex gap-3 :class="{ 'text-secondary': faded }">
|
<div flex gap-3 :class="{ 'text-secondary': faded }">
|
||||||
<div relative>
|
<div relative>
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { Status } from 'masto'
|
import type { Status, StatusEdit } from 'masto'
|
||||||
|
|
||||||
const { status } = defineProps<{
|
const { status } = defineProps<{
|
||||||
status: Status
|
status: Status | StatusEdit
|
||||||
fullSize?: boolean
|
fullSize?: boolean
|
||||||
}>()
|
}>()
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -22,10 +22,7 @@ const { edit } = defineProps<{
|
||||||
{{ edit.spoilerText }}
|
{{ edit.spoilerText }}
|
||||||
</template>
|
</template>
|
||||||
<StatusBody :status="edit" />
|
<StatusBody :status="edit" />
|
||||||
<StatusMedia
|
<StatusMedia v-if="edit.mediaAttachments.length" :status="edit" />
|
||||||
v-if="edit.mediaAttachments.length"
|
|
||||||
:status="edit"
|
|
||||||
/>
|
|
||||||
</StatusSpoiler>
|
</StatusSpoiler>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -24,7 +24,6 @@ export const useImageGesture = (
|
||||||
|
|
||||||
const { set } = useSpring(motionProperties as Partial<PermissiveMotionProperties>)
|
const { set } = useSpring(motionProperties as Partial<PermissiveMotionProperties>)
|
||||||
|
|
||||||
// @ts-expect-error we need to fix types: just suppress it for now
|
|
||||||
const handlers: Handlers = {
|
const handlers: Handlers = {
|
||||||
onPinch({ offset: [d] }) {
|
onPinch({ offset: [d] }) {
|
||||||
set({ scale: 1 + d / 200 })
|
set({ scale: 1 + d / 200 })
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import type { Status } from 'masto'
|
import type { Status, StatusEdit } from 'masto'
|
||||||
|
|
||||||
export interface TranslationResponse {
|
export interface TranslationResponse {
|
||||||
translatedText: string
|
translatedText: string
|
||||||
|
@ -24,15 +24,18 @@ export async function translateText(text: string, from?: string | null, to?: str
|
||||||
return translatedText
|
return translatedText
|
||||||
}
|
}
|
||||||
|
|
||||||
const translations = new WeakMap<Status, { visible: boolean; text: string }>()
|
const translations = new WeakMap<Status | StatusEdit, { visible: boolean; text: string }>()
|
||||||
|
|
||||||
export function useTranslation(status: Status) {
|
export function useTranslation(status: Status | StatusEdit) {
|
||||||
if (!translations.has(status))
|
if (!translations.has(status))
|
||||||
translations.set(status, reactive({ visible: false, text: '' }))
|
translations.set(status, reactive({ visible: false, text: '' }))
|
||||||
|
|
||||||
const translation = translations.get(status)!
|
const translation = translations.get(status)!
|
||||||
|
|
||||||
async function toggle() {
|
async function toggle() {
|
||||||
|
if (!('language' in status))
|
||||||
|
return
|
||||||
|
|
||||||
if (!translation.text)
|
if (!translation.text)
|
||||||
translation.text = await translateText(status.content, status.language)
|
translation.text = await translateText(status.content, status.language)
|
||||||
|
|
||||||
|
|
13
html.d.ts
vendored
13
html.d.ts
vendored
|
@ -1,13 +0,0 @@
|
||||||
// for UnoCSS attributify mode compact in Volar
|
|
||||||
// refer: https://github.com/johnsoncodehk/volar/issues/1077#issuecomment-1145361472
|
|
||||||
declare module '@vue/runtime-dom' {
|
|
||||||
interface HTMLAttributes {
|
|
||||||
[key: string]: any
|
|
||||||
}
|
|
||||||
}
|
|
||||||
declare module '@vue/runtime-core' {
|
|
||||||
interface AllowedComponentProps {
|
|
||||||
[key: string]: any
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export {}
|
|
|
@ -1,5 +1,4 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { Status } from 'masto'
|
|
||||||
import type { ComponentPublicInstance } from 'vue'
|
import type { ComponentPublicInstance } from 'vue'
|
||||||
|
|
||||||
definePageMeta({
|
definePageMeta({
|
||||||
|
@ -93,7 +92,7 @@ onReactivated(() => {
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<StatusNotFound v-else :account="route.params.account" :status="id" />
|
<StatusNotFound v-else :account="route.params.account as string" :status="id" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<StatusCardSkeleton v-else border="b base" />
|
<StatusCardSkeleton v-else border="b base" />
|
||||||
|
|
|
@ -16,7 +16,7 @@ if (account) {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<template v-if="account">
|
<template v-if="paginator">
|
||||||
<AccountPaginator :paginator="paginator" />
|
<AccountPaginator :paginator="paginator" />
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -16,7 +16,7 @@ if (account) {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<template v-if="account">
|
<template v-if="paginator">
|
||||||
<AccountPaginator :paginator="paginator" />
|
<AccountPaginator :paginator="paginator" />
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -32,8 +32,10 @@ onReactivated(() => {
|
||||||
<span text-lg font-bold>#{{ tagName }}</span>
|
<span text-lg font-bold>#{{ tagName }}</span>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-if="typeof tag?.following === 'boolean'" #actions>
|
<template #actions>
|
||||||
<TagActionButton :tag="tag" @change="refresh()" />
|
<template v-if="typeof tag?.following === 'boolean'">
|
||||||
|
<TagActionButton :tag="tag" @change="refresh()" />
|
||||||
|
</template>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<slot>
|
<slot>
|
||||||
|
|
Loading…
Reference in a new issue