fix: type errors (#802)

zio/stable
三咲智子 Kevin Deng 2023-01-06 00:48:20 +08:00 committed by GitHub
parent 272fb4a13d
commit acdb94de62
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 113 additions and 74 deletions

View File

@ -1,4 +1,6 @@
<script setup lang="ts">
// type used in <template>
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
import type { Account } from 'masto'
defineProps<{
@ -14,8 +16,9 @@ defineProps<{
</div>
<div flex>
<NuxtLink :to="getAccountRoute(account.moved as any)">
<AccountInfo :account="account.moved" />
<!-- type error of masto.js -->
<NuxtLink :to="getAccountRoute(account.moved as unknown as Account)">
<AccountInfo :account="account.moved as unknown as Account" />
</NuxtLink>
<div flex-auto />
<div flex items-center>

View File

@ -1,5 +1,5 @@
<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'
const emit = defineEmits<{
@ -37,11 +37,23 @@ const searchResult = $computed<QueryResult>(() => {
if (query.length === 0 || loading.value)
return { length: 0, items: [], grouped: {} as any }
// TODO extract this scope
// duplicate in SearchWidget.vue
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)
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)
const grouped: QueryResult['grouped'] = new Map()

View File

@ -2,7 +2,7 @@
import { decode } from 'blurhash'
const { blurhash, src, srcset } = defineProps<{
blurhash: string
blurhash?: string | null | undefined
src: string
srcset?: string
}>()
@ -11,8 +11,13 @@ defineOptions({
inheritAttrs: false,
})
const placeholderSrc = ref<string>()
const isLoaded = ref(false)
const placeholderSrc = $computed(() => {
if (!blurhash)
return ''
const pixels = decode(blurhash, 32, 32)
return getDataUrlFromArr(pixels, 32, 32)
})
onMounted(() => {
const img = document.createElement('img')
@ -29,11 +34,6 @@ onMounted(() => {
setTimeout(() => {
isLoaded.value = true
}, 3_000)
if (blurhash) {
const pixels = decode(blurhash, 32, 32)
placeholderSrc.value = getDataUrlFromArr(pixels, 32, 32)
}
})
</script>

View File

@ -5,7 +5,7 @@ import 'vue-advanced-cropper/dist/style.css'
export interface Props {
/** Images to be cropped */
modelValue?: File
modelValue?: File | null
/** Crop frame aspect ratio (width/height), default 1/1 */
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 */

View File

@ -3,7 +3,7 @@ import { fileOpen } from 'browser-fs-access'
import type { FileWithHandle } from 'browser-fs-access'
const props = withDefaults(defineProps<{
modelValue?: FileWithHandle
modelValue?: FileWithHandle | null
/** The image src before change */
original?: string
/** Allowed file types */

View File

@ -53,6 +53,7 @@ const handlePublishClose = () => {
>
<!-- This `w-0` style is used to avoid overflow problems in flex layoutsso don't remove it unless you know what you're doing -->
<PublishWidget
v-if="dialogDraftKey"
:draft-key="dialogDraftKey" expanded flex-1 w-0
@published="handlePublished"
/>
@ -65,7 +66,7 @@ const handlePublishClose = () => {
<ModalMediaPreview v-if="isMediaPreviewOpen" @close="closeMediaPreview()" />
</ModalDialog>
<ModalDialog v-model="isEditHistoryDialogOpen" max-w-125>
<StatusEditPreview :edit="statusEdit" />
<StatusEditPreview v-if="statusEdit" :edit="statusEdit" />
</ModalDialog>
<ModalDialog v-model="isCommandPanelOpen" max-w-fit flex>
<CommandPanel @close="closeCommandPanel()" />

View File

@ -1,5 +1,11 @@
<script setup lang="ts">
// type used in <template>
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
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'
const { paginator, stream } = defineProps<{
@ -118,12 +124,12 @@ const { formatNumber } = useHumanReadableNumber()
/>
<NotificationGroupedLikes
v-else-if="item.type === 'grouped-reblogs-and-favourites'"
:group="item"
:group="item as GroupedLikeNotifications"
border="b base"
/>
<NotificationCard
v-else
:notification="item"
:notification="item as Notification"
hover:bg-active
border="b base"
/>

View File

@ -269,7 +269,7 @@ defineExpose({
<PublishAttachment
v-for="(att, idx) in draft.attachments" :key="att.id"
:attachment="att"
:dialog-labelled-by="dialogLabelledBy ?? (draft.editingStatus ? 'state-editing' : null)"
:dialog-labelled-by="dialogLabelledBy ?? (draft.editingStatus ? 'state-editing' : undefined)"
@remove="removeAttachment(idx)"
@set-description="setDescription(att, $event)"
/>

View File

@ -1,6 +1,10 @@
<script setup lang="ts">
import type { SearchResult } from './types'
defineProps<{ result: SearchResult; active: boolean }>()
defineProps<{
result: SearchResult
active: boolean
}>()
const onActivate = () => {
(document.activeElement as HTMLElement).blur()
@ -10,10 +14,10 @@ const onActivate = () => {
<template>
<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" />
<AccountInfo v-else-if="result.type === 'account'" :account="result.account" />
<StatusCard v-else-if="result.type === 'status'" :status="result.status" :actions="false" :show-reply-to="false" />
<div v-else-if="result.type === 'action'" text-center>
<AccountInfo v-else-if="result.type === 'account' && result.account" :account="result.account" />
<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>
{{ result.action!.label }}
</div>
</div> -->
</CommonScrollIntoView>
</template>

View File

@ -1,4 +1,6 @@
<script setup lang="ts">
import type { AccountResult, HashTagResult, StatusResult } from './types'
const query = ref('')
const { accounts, hashtags, loading, statuses } = useSearch(query)
const index = ref(0)
@ -13,9 +15,24 @@ const results = computed(() => {
return []
const results = [
...hashtags.value.slice(0, 3).map(hashtag => ({ type: 'hashtag', hashtag, to: getTagRoute(hashtag.name) })),
...accounts.value.map(account => ({ type: 'account', account, to: getAccountRoute(account) })),
...statuses.value.map(status => ({ type: 'status', status, to: getStatusRoute(status) })),
...hashtags.value.slice(0, 3).map<HashTagResult>(hashtag => ({
type: 'hashtag',
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
// {
@ -79,7 +96,12 @@ const activate = () => {
{{ t('search.search_desc') }}
</span>
<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>
<div v-else>
<SearchResultSkeleton />

View File

@ -1,13 +1,17 @@
import type { Account, Status } from 'masto'
import type { RouteLocation } from 'vue-router'
export interface SearchResult {
type: 'account' | 'hashtag' | 'action' | 'status'
to: string
label?: string
account?: Account
status?: Status
hashtag?: any
action?: {
label: string
export type BuildResult<K extends keyof any, T> = {
[P in K]: T
} & {
id: string
type: K
to: RouteLocation & {
href: 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

View File

@ -64,7 +64,7 @@ const reply = () => {
color="text-green" hover="text-green" group-hover="bg-green/10"
icon="i-ri:repeat-line"
active-icon="i-ri:repeat-fill"
:active="status.reblogged"
:active="!!status.reblogged"
:disabled="isLoading.reblogged"
:command="command"
@click="toggleReblog()"
@ -88,7 +88,7 @@ const reply = () => {
color="text-rose" hover="text-rose" group-hover="bg-rose/10"
icon="i-ri:heart-3-line"
active-icon="i-ri:heart-3-fill"
:active="status.favourited"
:active="!!status.favourited"
:disabled="isLoading.favourited"
:command="command"
@click="toggleFavourite()"
@ -111,7 +111,7 @@ const reply = () => {
color="text-yellow" hover="text-yellow" group-hover="bg-yellow/10"
icon="i-ri:bookmark-line"
active-icon="i-ri:bookmark-fill"
:active="status.bookmarked"
:active="!!status.bookmarked"
:disabled="isLoading.bookmarked"
:command="command"
@click="toggleBookmark()"

View File

@ -186,9 +186,8 @@ async function editStatus() {
@click="toggleMute()"
/>
<NuxtLink :to="status.url" external target="_blank">
<NuxtLink v-if="status.url" :to="status.url" external target="_blank">
<CommonDropdownItem
v-if="status.url"
:text="$t('menu.open_in_original_site')"
icon="i-ri:arrow-right-up-line"
:command="command"

View File

@ -1,10 +1,11 @@
<script setup lang="ts">
import type { Status } from 'masto'
import type { Status, StatusEdit } from 'masto'
const { status, withAction = true } = defineProps<{
status: Status
status: Status | StatusEdit
withAction?: boolean
}>()
const { translation } = useTranslation(status)
</script>
@ -15,7 +16,7 @@ const { translation } = useTranslation(status)
class="line-compact"
:content="status.content"
:emojis="status.emojis"
:lang="status.language"
:lang="'language' in status && status.language"
/>
<div v-else />
<template v-if="translation.visible">

View File

@ -113,7 +113,7 @@ const isDM = $computed(() => status.visibility === 'direct')
</div>
<div v-else />
</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 flex gap-3 :class="{ 'text-secondary': faded }">
<div relative>

View File

@ -1,8 +1,8 @@
<script setup lang="ts">
import type { Status } from 'masto'
import type { Status, StatusEdit } from 'masto'
const { status } = defineProps<{
status: Status
status: Status | StatusEdit
fullSize?: boolean
}>()
</script>

View File

@ -22,10 +22,7 @@ const { edit } = defineProps<{
{{ edit.spoilerText }}
</template>
<StatusBody :status="edit" />
<StatusMedia
v-if="edit.mediaAttachments.length"
:status="edit"
/>
<StatusMedia v-if="edit.mediaAttachments.length" :status="edit" />
</StatusSpoiler>
</div>
</template>

View File

@ -24,7 +24,6 @@ export const useImageGesture = (
const { set } = useSpring(motionProperties as Partial<PermissiveMotionProperties>)
// @ts-expect-error we need to fix types: just suppress it for now
const handlers: Handlers = {
onPinch({ offset: [d] }) {
set({ scale: 1 + d / 200 })

View File

@ -1,4 +1,4 @@
import type { Status } from 'masto'
import type { Status, StatusEdit } from 'masto'
export interface TranslationResponse {
translatedText: string
@ -24,15 +24,18 @@ export async function translateText(text: string, from?: string | null, to?: str
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))
translations.set(status, reactive({ visible: false, text: '' }))
const translation = translations.get(status)!
async function toggle() {
if (!('language' in status))
return
if (!translation.text)
translation.text = await translateText(status.content, status.language)

13
html.d.ts vendored
View File

@ -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 {}

View File

@ -1,5 +1,4 @@
<script setup lang="ts">
import type { Status } from 'masto'
import type { ComponentPublicInstance } from 'vue'
definePageMeta({
@ -93,7 +92,7 @@ onReactivated(() => {
</template>
</div>
<StatusNotFound v-else :account="route.params.account" :status="id" />
<StatusNotFound v-else :account="route.params.account as string" :status="id" />
</template>
<StatusCardSkeleton v-else border="b base" />

View File

@ -16,7 +16,7 @@ if (account) {
</script>
<template>
<template v-if="account">
<template v-if="paginator">
<AccountPaginator :paginator="paginator" />
</template>
</template>

View File

@ -16,7 +16,7 @@ if (account) {
</script>
<template>
<template v-if="account">
<template v-if="paginator">
<AccountPaginator :paginator="paginator" />
</template>
</template>

View File

@ -32,8 +32,10 @@ onReactivated(() => {
<span text-lg font-bold>#{{ tagName }}</span>
</template>
<template v-if="typeof tag?.following === 'boolean'" #actions>
<TagActionButton :tag="tag" @change="refresh()" />
<template #actions>
<template v-if="typeof tag?.following === 'boolean'">
<TagActionButton :tag="tag" @change="refresh()" />
</template>
</template>
<slot>