mirror of
https://github.com/elk-zone/elk.git
synced 2024-12-30 00:18:16 +03:00
Merge branch 'main' into shuuji3/feat/emoji-reactions
This commit is contained in:
commit
abf1b05695
53 changed files with 4588 additions and 3282 deletions
|
@ -90,7 +90,7 @@ We've added some `UnoCSS` utilities styles to help you with that:
|
||||||
|
|
||||||
## Internationalization
|
## Internationalization
|
||||||
|
|
||||||
We are using [vue-i18n](https://vue-i18n.intlify.dev/) via [nuxt-i18n](https://v8.i18n.nuxtjs.org/) to handle internationalization.
|
We are using [vue-i18n](https://vue-i18n.intlify.dev/) via [nuxt-i18n](https://i18n.nuxtjs.org/) to handle internationalization.
|
||||||
|
|
||||||
You can check the current [translation status](https://docs.elk.zone/docs/guide/contributing#translation-status): more instructions on the table caption.
|
You can check the current [translation status](https://docs.elk.zone/docs/guide/contributing#translation-status): more instructions on the table caption.
|
||||||
|
|
||||||
|
|
|
@ -1,27 +1,32 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { mastodon } from 'masto'
|
import type { mastodon } from 'masto'
|
||||||
|
|
||||||
defineProps<{
|
const props = defineProps<{
|
||||||
account: mastodon.v1.Account
|
account: mastodon.v1.Account
|
||||||
square?: boolean
|
square?: boolean
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const loaded = ref(false)
|
const loaded = ref(false)
|
||||||
const error = ref(false)
|
const error = ref(false)
|
||||||
|
|
||||||
|
const preferredMotion = usePreferredReducedMotion()
|
||||||
|
const accountAvatarSrc = computed(() => {
|
||||||
|
return preferredMotion.value === 'reduce' ? (props.account?.avatarStatic ?? props.account.avatar) : props.account.avatar
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<img
|
<img
|
||||||
:key="account.avatar"
|
:key="props.account.avatar"
|
||||||
width="400"
|
width="400"
|
||||||
height="400"
|
height="400"
|
||||||
select-none
|
select-none
|
||||||
:src="(error || !loaded) ? 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7' : account.avatar"
|
:src="(error || !loaded) ? 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7' : accountAvatarSrc"
|
||||||
:alt="$t('account.avatar_description', [account.username])"
|
:alt="$t('account.avatar_description', [props.account.username])"
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
class="account-avatar"
|
class="account-avatar"
|
||||||
:class="(loaded ? 'bg-base' : 'bg-gray:10') + (square ? ' ' : ' rounded-full')"
|
:class="(loaded ? 'bg-base' : 'bg-gray:10') + (props.square ? ' ' : ' rounded-full')"
|
||||||
:style="{ 'clip-path': square ? `url(#avatar-mask)` : 'none' }"
|
:style="{ 'clip-path': props.square ? `url(#avatar-mask)` : 'none' }"
|
||||||
v-bind="$attrs"
|
v-bind="$attrs"
|
||||||
@load="loaded = true"
|
@load="loaded = true"
|
||||||
@error="error = true"
|
@error="error = true"
|
||||||
|
|
|
@ -14,11 +14,11 @@ const router = useRouter()
|
||||||
|
|
||||||
useCommands(() => command
|
useCommands(() => command
|
||||||
? options.map(tab => ({
|
? options.map(tab => ({
|
||||||
scope: 'Tabs',
|
scope: 'Tabs',
|
||||||
name: tab.display,
|
name: tab.display,
|
||||||
icon: tab.icon ?? 'i-ri:file-list-2-line',
|
icon: tab.icon ?? 'i-ri:file-list-2-line',
|
||||||
onActivate: () => router.replace(tab.to),
|
onActivate: () => router.replace(tab.to),
|
||||||
}))
|
}))
|
||||||
: [])
|
: [])
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -25,13 +25,13 @@ function toValidName(option: string) {
|
||||||
|
|
||||||
useCommands(() => command
|
useCommands(() => command
|
||||||
? tabs.value.map(tab => ({
|
? tabs.value.map(tab => ({
|
||||||
scope: 'Tabs',
|
scope: 'Tabs',
|
||||||
|
|
||||||
name: tab.display,
|
name: tab.display,
|
||||||
icon: tab.icon ?? 'i-ri:file-list-2-line',
|
icon: tab.icon ?? 'i-ri:file-list-2-line',
|
||||||
|
|
||||||
onActivate: () => modelValue.value = tab.name,
|
onActivate: () => modelValue.value = tab.name,
|
||||||
}))
|
}))
|
||||||
: [])
|
: [])
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { mastodon } from 'masto'
|
import type { mastodon } from 'masto'
|
||||||
|
import type { ConfirmDialogChoice } from '~/types'
|
||||||
import {
|
import {
|
||||||
isCommandPanelOpen,
|
isCommandPanelOpen,
|
||||||
isConfirmDialogOpen,
|
isConfirmDialogOpen,
|
||||||
|
@ -13,7 +14,6 @@ import {
|
||||||
isReportDialogOpen,
|
isReportDialogOpen,
|
||||||
isSigninDialogOpen,
|
isSigninDialogOpen,
|
||||||
} from '~/composables/dialog'
|
} from '~/composables/dialog'
|
||||||
import type { ConfirmDialogChoice } from '~/types'
|
|
||||||
|
|
||||||
const isMac = useIsMac()
|
const isMac = useIsMac()
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<span shrink-0 aspect="1/1" sm:h-8 xl:h-10 class="rtl-flip"><svg
|
<span shrink-0 aspect="1/1" sm:h-8 xl:h-10 class="rtl-flip"><svg
|
||||||
xmlns="http://www.w3.org/2000/svg" w-full
|
xmlns="http://www.w3.org/2000/svg" w-full
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
defineModel<boolean>()
|
const model = defineModel<boolean>()
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<NavBottomMoreMenu
|
<NavBottomMoreMenu
|
||||||
v-slot="{ toggleVisible, show }" v-model="modelValue!" flex flex-row items-center
|
v-slot="{ toggleVisible, show }" v-model="model!" flex flex-row items-center
|
||||||
place-content-center h-full flex-1 cursor-pointer
|
place-content-center h-full flex-1 cursor-pointer
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
|
|
|
@ -1,16 +1,38 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { mastodon } from 'masto'
|
import type { mastodon } from 'masto'
|
||||||
|
|
||||||
|
// Add undocumented 'annual_report' type introduced in v4.3
|
||||||
|
// ref. https://github.com/mastodon/documentation/issues/1211#:~:text=api/v1/annual_reports
|
||||||
|
type NotificationType = mastodon.v1.Notification['type'] | 'annual_report'
|
||||||
|
type Notification = Omit<mastodon.v1.Notification, 'type'> & { type: NotificationType }
|
||||||
|
|
||||||
const { notification } = defineProps<{
|
const { notification } = defineProps<{
|
||||||
notification: mastodon.v1.Notification
|
notification: Notification
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
|
|
||||||
|
// list of notification types Elk currently implemented
|
||||||
|
// type 'favourite' and 'reblog' should always rendered by NotificationGroupedLikes
|
||||||
|
const supportedNotificationTypes: NotificationType[] = [
|
||||||
|
'follow',
|
||||||
|
'admin.sign_up',
|
||||||
|
'admin.report',
|
||||||
|
'follow_request',
|
||||||
|
'update',
|
||||||
|
'mention',
|
||||||
|
'poll',
|
||||||
|
'update',
|
||||||
|
'status',
|
||||||
|
'annual_report',
|
||||||
|
]
|
||||||
|
|
||||||
// well-known emoji reactions types Elk does not support yet
|
// well-known emoji reactions types Elk does not support yet
|
||||||
const unsupportedEmojiReactionTypes = ['pleroma:emoji_reaction', 'reaction']
|
const unsupportedEmojiReactionTypes = ['pleroma:emoji_reaction', 'reaction']
|
||||||
if (unsupportedEmojiReactionTypes.includes(notification.type))
|
|
||||||
|
if (unsupportedEmojiReactionTypes.includes(notification.type) || !supportedNotificationTypes.includes(notification.type)) {
|
||||||
console.warn(`[DEV] ${t('notification.missing_type')} '${notification.type}' (notification.id: ${notification.id})`)
|
console.warn(`[DEV] ${t('notification.missing_type')} '${notification.type}' (notification.id: ${notification.id})`)
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -95,11 +117,21 @@ if (unsupportedEmojiReactionTypes.includes(notification.type))
|
||||||
<template v-else-if="notification.type === 'mention' || notification.type === 'poll' || notification.type === 'status'">
|
<template v-else-if="notification.type === 'mention' || notification.type === 'poll' || notification.type === 'status'">
|
||||||
<StatusCard :status="notification.status!" />
|
<StatusCard :status="notification.status!" />
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="!unsupportedEmojiReactionTypes.includes(notification.type)">
|
<template v-else-if="notification.type === 'annual_report'">
|
||||||
<!-- prevent showing errors for dev for known emoji reaction types -->
|
<div flex p4 items-center bg-shaded>
|
||||||
<!-- type 'favourite' and 'reblog' should always rendered by NotificationGroupedLikes -->
|
<div i-mdi:party-popper text-xl me-4 color-purple />
|
||||||
<div text-red font-bold>
|
<div class="content-rich">
|
||||||
[DEV] {{ $t('notification.missing_type') }} '{{ notification.type }}'
|
<p>
|
||||||
|
Your 2024 <NuxtLink to="/tags/Wrapstodon">
|
||||||
|
#Wrapstodon
|
||||||
|
</NuxtLink> awaits! Unveil your year's highlights and memorable moments on Mastodon!
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<NuxtLink :to="`https://${currentServer}/notifications`" target="_blank">
|
||||||
|
View #Wrapstodon on Mastodon
|
||||||
|
</NuxtLink>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</article>
|
</article>
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { mastodon } from 'masto'
|
import type { mastodon } from 'masto'
|
||||||
|
import type { GroupedAccountLike, NotificationSlot } from '~/types'
|
||||||
// @ts-expect-error missing types
|
// @ts-expect-error missing types
|
||||||
import { DynamicScrollerItem } from 'vue-virtual-scroller'
|
import { DynamicScrollerItem } from 'vue-virtual-scroller'
|
||||||
import type { GroupedAccountLike, NotificationSlot } from '~/types'
|
|
||||||
|
|
||||||
const { paginator, stream } = defineProps<{
|
const { paginator, stream } = defineProps<{
|
||||||
paginator: mastodon.Paginator<mastodon.v1.Notification[], mastodon.rest.v1.ListNotificationsParams>
|
paginator: mastodon.Paginator<mastodon.v1.Notification[], mastodon.rest.v1.ListNotificationsParams>
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { mastodon } from 'masto'
|
import type { mastodon } from 'masto'
|
||||||
|
import type { DraftItem } from '~/types'
|
||||||
import { EditorContent } from '@tiptap/vue-3'
|
import { EditorContent } from '@tiptap/vue-3'
|
||||||
import stringLength from 'string-length'
|
import stringLength from 'string-length'
|
||||||
import type { DraftItem } from '~/types'
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
threadComposer,
|
threadComposer,
|
||||||
|
@ -522,6 +522,7 @@ function stopQuestionMarkPropagation(e: KeyboardEvent) {
|
||||||
v-if="!threadIsActive || isFinalItemOfThread"
|
v-if="!threadIsActive || isFinalItemOfThread"
|
||||||
btn-solid rounded-3 text-sm w-full flex="~ gap1" items-center md:w-fit class="publish-button"
|
btn-solid rounded-3 text-sm w-full flex="~ gap1" items-center md:w-fit class="publish-button"
|
||||||
:aria-disabled="isPublishDisabled || isExceedingCharacterLimit" aria-describedby="publish-tooltip"
|
:aria-disabled="isPublishDisabled || isExceedingCharacterLimit" aria-describedby="publish-tooltip"
|
||||||
|
:disabled="isPublishDisabled || isExceedingCharacterLimit"
|
||||||
@click="publish"
|
@click="publish"
|
||||||
>
|
>
|
||||||
<span v-if="isSending" block animate-spin preserve-3d>
|
<span v-if="isSending" block animate-spin preserve-3d>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { formatTimeAgo } from '@vueuse/core'
|
|
||||||
import type { DraftItem } from '~/types'
|
import type { DraftItem } from '~/types'
|
||||||
|
import { formatTimeAgo } from '@vueuse/core'
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const { formatNumber } = useHumanReadableNumber()
|
const { formatNumber } = useHumanReadableNumber()
|
||||||
|
|
|
@ -30,7 +30,7 @@ const defaultSelectedNavButtonNames = computed<NavButtonName[]>(() =>
|
||||||
: ['explore', 'local', 'federated', 'moreMenu'],
|
: ['explore', 'local', 'federated', 'moreMenu'],
|
||||||
)
|
)
|
||||||
const navButtonNamesSetting = useLocalStorage<NavButtonName[]>(STORAGE_KEY_BOTTOM_NAV_BUTTONS, defaultSelectedNavButtonNames.value)
|
const navButtonNamesSetting = useLocalStorage<NavButtonName[]>(STORAGE_KEY_BOTTOM_NAV_BUTTONS, defaultSelectedNavButtonNames.value)
|
||||||
const selectedNavButtonNames = ref<NavButtonName[]>([])
|
const selectedNavButtonNames = ref<NavButtonName[]>(navButtonNamesSetting.value)
|
||||||
|
|
||||||
const selectedNavButtons = computed<NavButton[]>(() =>
|
const selectedNavButtons = computed<NavButton[]>(() =>
|
||||||
selectedNavButtonNames.value.map(name =>
|
selectedNavButtonNames.value.map(name =>
|
||||||
|
|
|
@ -1,10 +1,42 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { ThemeColors } from '~/composables/settings'
|
import type { ThemeColors } from '~/composables/settings'
|
||||||
|
import { THEME_COLORS } from '~/constants'
|
||||||
|
|
||||||
|
const themes = await import('~/constants/themes.json').then((r) => {
|
||||||
|
const map = new Map<'dark' | 'light', [string, ThemeColors][]>([['dark', []], ['light', []]])
|
||||||
|
const themes = r.default as [string, ThemeColors][]
|
||||||
|
for (const [key, theme] of themes) {
|
||||||
|
map.get('dark')!.push([key, theme])
|
||||||
|
map.get('light')!.push([key, {
|
||||||
|
...theme,
|
||||||
|
'--c-primary': `color-mix(in srgb, ${theme['--c-primary']}, black 25%)`,
|
||||||
|
}])
|
||||||
|
}
|
||||||
|
return map
|
||||||
|
})
|
||||||
|
|
||||||
const themes = await import('~/constants/themes.json').then(r => r.default) as [string, ThemeColors][]
|
|
||||||
const settings = useUserSettings()
|
const settings = useUserSettings()
|
||||||
|
|
||||||
const currentTheme = computed(() => settings.value.themeColors?.['--theme-color-name'] || themes[0][1]['--theme-color-name'])
|
const media = useMediaQuery('(prefers-color-scheme: dark)')
|
||||||
|
|
||||||
|
const colorMode = useColorMode()
|
||||||
|
|
||||||
|
const useThemes = shallowRef<[string, ThemeColors][]>([])
|
||||||
|
|
||||||
|
watch(() => colorMode.preference, (cm) => {
|
||||||
|
const dark = cm === 'dark' || (cm === 'system' && media.value)
|
||||||
|
const newThemes = dark ? themes.get('dark')! : themes.get('light')!
|
||||||
|
const key = settings.value.themeColors?.['--theme-color-name'] || THEME_COLORS.defaultTheme
|
||||||
|
for (const [k, theme] of newThemes) {
|
||||||
|
if (k === key) {
|
||||||
|
settings.value.themeColors = theme
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
useThemes.value = newThemes
|
||||||
|
}, { immediate: true, flush: 'post' })
|
||||||
|
|
||||||
|
const currentTheme = computed(() => settings.value.themeColors?.['--theme-color-name'] || THEME_COLORS.defaultTheme)
|
||||||
|
|
||||||
function updateTheme(theme: ThemeColors) {
|
function updateTheme(theme: ThemeColors) {
|
||||||
settings.value.themeColors = theme
|
settings.value.themeColors = theme
|
||||||
|
@ -18,10 +50,11 @@ function updateTheme(theme: ThemeColors) {
|
||||||
</h2>
|
</h2>
|
||||||
<div flex="~ gap4 wrap" p2 role="group" aria-labelledby="interface-tc">
|
<div flex="~ gap4 wrap" p2 role="group" aria-labelledby="interface-tc">
|
||||||
<button
|
<button
|
||||||
v-for="[key, theme] in themes" :key="key"
|
v-for="[key, theme] in useThemes" :key="key"
|
||||||
:style="{
|
:style="{
|
||||||
'background': key,
|
'--rgb-primary': theme['--rgb-primary'],
|
||||||
'--local-ring-color': key,
|
'background': theme['--c-primary'],
|
||||||
|
'--local-ring-color': theme['--c-primary'],
|
||||||
}"
|
}"
|
||||||
type="button"
|
type="button"
|
||||||
:class="currentTheme === theme['--theme-color-name'] ? 'ring-2' : 'scale-90'"
|
:class="currentTheme === theme['--theme-color-name'] ? 'ring-2' : 'scale-90'"
|
||||||
|
|
|
@ -62,6 +62,7 @@ const timeago = useTimeAgo(() => status.value.createdAt, timeAgoOptions)
|
||||||
const isSelfReply = computed(() => status.value.inReplyToAccountId === status.value.account.id)
|
const isSelfReply = computed(() => status.value.inReplyToAccountId === status.value.account.id)
|
||||||
const collapseRebloggedBy = computed(() => rebloggedBy.value?.id === status.value.account.id)
|
const collapseRebloggedBy = computed(() => rebloggedBy.value?.id === status.value.account.id)
|
||||||
const isDM = computed(() => status.value.visibility === 'direct')
|
const isDM = computed(() => status.value.visibility === 'direct')
|
||||||
|
const isPinned = computed(() => status.value.pinned)
|
||||||
|
|
||||||
const showUpperBorder = computed(() => props.newer && !directReply.value)
|
const showUpperBorder = computed(() => props.newer && !directReply.value)
|
||||||
const showReplyTo = computed(() => !replyToMain.value && !directReply.value)
|
const showReplyTo = computed(() => !replyToMain.value && !directReply.value)
|
||||||
|
@ -75,6 +76,19 @@ const forceShow = ref(false)
|
||||||
<div :h="showUpperBorder ? '1px' : '0'" w-auto bg-border mb-1 z--1 />
|
<div :h="showUpperBorder ? '1px' : '0'" w-auto bg-border mb-1 z--1 />
|
||||||
|
|
||||||
<slot name="meta">
|
<slot name="meta">
|
||||||
|
<!-- Pinned status -->
|
||||||
|
<div flex="~ col" justify-between>
|
||||||
|
<div
|
||||||
|
v-if="isPinned"
|
||||||
|
flex="~ gap2" items-center h-auto text-sm text-orange
|
||||||
|
m="is-5" p="t-1 is-5"
|
||||||
|
relative text-secondary ws-nowrap
|
||||||
|
>
|
||||||
|
<div i-ri:pushpin-line />
|
||||||
|
<span>{{ $t('status.pinned') }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Line connecting to previous status -->
|
<!-- Line connecting to previous status -->
|
||||||
<template v-if="status.inReplyToAccountId">
|
<template v-if="status.inReplyToAccountId">
|
||||||
<StatusReplyingTo
|
<StatusReplyingTo
|
||||||
|
|
|
@ -1,10 +1,15 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import type { mastodon } from 'masto'
|
||||||
|
|
||||||
const paginator = useMastoClient().v1.timelines.public.list({ limit: 30, local: true })
|
const paginator = useMastoClient().v1.timelines.public.list({ limit: 30, local: true })
|
||||||
const stream = useStreaming(client => client.public.local.subscribe())
|
const stream = useStreaming(client => client.public.local.subscribe())
|
||||||
|
function reorderAndFilter(items: mastodon.v1.Status[]) {
|
||||||
|
return reorderedTimeline(items, 'public')
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<TimelinePaginator v-bind="{ paginator, stream }" context="public" />
|
<TimelinePaginator v-bind="{ paginator, stream }" :preprocess="reorderAndFilter" context="public" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { getEmojiMatchesInText } from '@iconify/utils/lib/emoji/replace/find'
|
|
||||||
import { emojiFilename, emojiPrefix, emojiRegEx } from '~~/config/emojis'
|
|
||||||
import type { CommandHandler } from '~/composables/command'
|
import type { CommandHandler } from '~/composables/command'
|
||||||
import type { CustomEmoji, Emoji } from '~/composables/tiptap/suggestion'
|
import type { CustomEmoji, Emoji } from '~/composables/tiptap/suggestion'
|
||||||
|
import { getEmojiMatchesInText } from '@iconify/utils/lib/emoji/replace/find'
|
||||||
|
import { emojiFilename, emojiPrefix, emojiRegEx } from '~~/config/emojis'
|
||||||
import { isCustomEmoji } from '~/composables/tiptap/suggestion'
|
import { isCustomEmoji } from '~/composables/tiptap/suggestion'
|
||||||
|
|
||||||
const { items, command } = defineProps<{
|
const { items, command } = defineProps<{
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import type { LocaleObject } from '@nuxtjs/i18n'
|
import type { LocaleObject } from '@nuxtjs/i18n'
|
||||||
import type { ComputedRef } from 'vue'
|
import type { ComputedRef } from 'vue'
|
||||||
|
import type { SearchResult } from '~/composables/masto/search'
|
||||||
import Fuse from 'fuse.js'
|
import Fuse from 'fuse.js'
|
||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
import type { SearchResult } from '~/composables/masto/search'
|
|
||||||
|
|
||||||
// @unocss-include
|
// @unocss-include
|
||||||
|
|
||||||
|
|
|
@ -90,6 +90,11 @@ export function parseMastodonHTML(
|
||||||
inReplyToStatus,
|
inReplyToStatus,
|
||||||
} = options
|
} = options
|
||||||
|
|
||||||
|
// remove newline before Tags
|
||||||
|
html = html.replace(/\n(<[^>]+>)/g, (_1, raw) => {
|
||||||
|
return raw
|
||||||
|
})
|
||||||
|
|
||||||
if (markdown) {
|
if (markdown) {
|
||||||
// Handle code blocks
|
// Handle code blocks
|
||||||
html = html
|
html = html
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import type { mastodon } from 'masto'
|
import type { mastodon } from 'masto'
|
||||||
import { STORAGE_KEY_FIRST_VISIT } from '~/constants'
|
|
||||||
import type { ConfirmDialogChoice, ConfirmDialogOptions, DraftItem, ErrorDialogData } from '~/types'
|
import type { ConfirmDialogChoice, ConfirmDialogOptions, DraftItem, ErrorDialogData } from '~/types'
|
||||||
|
import { STORAGE_KEY_FIRST_VISIT } from '~/constants'
|
||||||
|
|
||||||
export const confirmDialogChoice = ref<ConfirmDialogChoice>()
|
export const confirmDialogChoice = ref<ConfirmDialogChoice>()
|
||||||
export const confirmDialogLabel = ref<ConfirmDialogOptions>()
|
export const confirmDialogLabel = ref<ConfirmDialogOptions>()
|
||||||
|
|
|
@ -2,8 +2,8 @@ import type { Pausable } from '@vueuse/core'
|
||||||
import type { mastodon } from 'masto'
|
import type { mastodon } from 'masto'
|
||||||
import type { Ref } from 'vue'
|
import type { Ref } from 'vue'
|
||||||
import type { ElkInstance } from '../users'
|
import type { ElkInstance } from '../users'
|
||||||
import { createRestAPIClient, createStreamingAPIClient } from 'masto'
|
|
||||||
import type { UserLogin } from '~/types'
|
import type { UserLogin } from '~/types'
|
||||||
|
import { createRestAPIClient, createStreamingAPIClient } from 'masto'
|
||||||
|
|
||||||
export function createMasto() {
|
export function createMasto() {
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import type { DraftItem } from '~~/types'
|
|
||||||
import type { mastodon } from 'masto'
|
import type { mastodon } from 'masto'
|
||||||
import type { Ref } from 'vue'
|
import type { Ref } from 'vue'
|
||||||
|
import type { DraftItem } from '~~/types'
|
||||||
import { fileOpen } from 'browser-fs-access'
|
import { fileOpen } from 'browser-fs-access'
|
||||||
|
|
||||||
export function usePublish(options: {
|
export function usePublish(options: {
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import type { mastodon } from 'masto'
|
import type { mastodon } from 'masto'
|
||||||
import type { ComputedRef, Ref } from 'vue'
|
import type { ComputedRef, Ref } from 'vue'
|
||||||
import { STORAGE_KEY_DRAFTS } from '~/constants'
|
|
||||||
import type { DraftItem, DraftMap } from '~/types'
|
import type { DraftItem, DraftMap } from '~/types'
|
||||||
import type { Mutable } from '~/types/utils'
|
import type { Mutable } from '~/types/utils'
|
||||||
|
import { STORAGE_KEY_DRAFTS } from '~/constants'
|
||||||
|
|
||||||
export const currentUserDrafts = (import.meta.server || process.test)
|
export const currentUserDrafts = (import.meta.server || process.test)
|
||||||
? computed<DraftMap>(() => ({}))
|
? computed<DraftMap>(() => ({}))
|
||||||
|
|
|
@ -2,8 +2,10 @@ import type { MaybeRefOrGetter, RemovableRef } from '@vueuse/core'
|
||||||
import type { mastodon } from 'masto'
|
import type { mastodon } from 'masto'
|
||||||
import type { EffectScope, Ref } from 'vue'
|
import type { EffectScope, Ref } from 'vue'
|
||||||
import type { ElkMasto } from './masto/masto'
|
import type { ElkMasto } from './masto/masto'
|
||||||
import { withoutProtocol } from 'ufo'
|
|
||||||
import type { PushNotificationPolicy, PushNotificationRequest } from '~/composables/push-notifications/types'
|
import type { PushNotificationPolicy, PushNotificationRequest } from '~/composables/push-notifications/types'
|
||||||
|
import type { UserLogin } from '~/types'
|
||||||
|
import type { Overwrite } from '~/types/utils'
|
||||||
|
import { withoutProtocol } from 'ufo'
|
||||||
import {
|
import {
|
||||||
DEFAULT_POST_CHARS_LIMIT,
|
DEFAULT_POST_CHARS_LIMIT,
|
||||||
STORAGE_KEY_CURRENT_USER_HANDLE,
|
STORAGE_KEY_CURRENT_USER_HANDLE,
|
||||||
|
@ -12,8 +14,6 @@ import {
|
||||||
STORAGE_KEY_NOTIFICATION_POLICY,
|
STORAGE_KEY_NOTIFICATION_POLICY,
|
||||||
STORAGE_KEY_SERVERS,
|
STORAGE_KEY_SERVERS,
|
||||||
} from '~/constants'
|
} from '~/constants'
|
||||||
import type { UserLogin } from '~/types'
|
|
||||||
import type { Overwrite } from '~/types/utils'
|
|
||||||
|
|
||||||
const mock = process.mock
|
const mock = process.mock
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import type { EmojiRegexMatch } from '@iconify/utils/lib/emoji/replace/find'
|
import type { EmojiRegexMatch } from '@iconify/utils/lib/emoji/replace/find'
|
||||||
import { getEmojiMatchesInText } from '@iconify/utils/lib/emoji/replace/find'
|
|
||||||
// @unimport-disabled
|
// @unimport-disabled
|
||||||
import { emojiFilename, emojiPrefix, emojiRegEx } from '@iconify-emoji/twemoji'
|
import { emojiFilename, emojiPrefix, emojiRegEx } from '@iconify-emoji/twemoji'
|
||||||
|
import { getEmojiMatchesInText } from '@iconify/utils/lib/emoji/replace/find'
|
||||||
|
|
||||||
// Re-export everything from package
|
// Re-export everything from package
|
||||||
export * from '@iconify-emoji/twemoji'
|
export * from '@iconify-emoji/twemoji'
|
||||||
|
|
|
@ -75,11 +75,13 @@ export const countryLocaleVariants: Record<string, (LocaleObjectData & { country
|
||||||
|
|
||||||
const locales: LocaleObjectData[] = [
|
const locales: LocaleObjectData[] = [
|
||||||
{
|
{
|
||||||
|
// @ts-expect-error en used as placeholder
|
||||||
code: 'en',
|
code: 'en',
|
||||||
file: 'en.json',
|
file: 'en.json',
|
||||||
name: 'English',
|
name: 'English',
|
||||||
},
|
},
|
||||||
({
|
({
|
||||||
|
// @ts-expect-error ar used as placeholder
|
||||||
code: 'ar',
|
code: 'ar',
|
||||||
file: 'ar.json',
|
file: 'ar.json',
|
||||||
name: 'العربية',
|
name: 'العربية',
|
||||||
|
@ -110,6 +112,7 @@ const locales: LocaleObjectData[] = [
|
||||||
},
|
},
|
||||||
} satisfies LocaleObjectData),
|
} satisfies LocaleObjectData),
|
||||||
{
|
{
|
||||||
|
// @ts-expect-error ca used as placeholder
|
||||||
code: 'ca',
|
code: 'ca',
|
||||||
file: 'ca.json',
|
file: 'ca.json',
|
||||||
name: 'Català',
|
name: 'Català',
|
||||||
|
@ -150,6 +153,7 @@ const locales: LocaleObjectData[] = [
|
||||||
name: 'Nederlands',
|
name: 'Nederlands',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
// @ts-expect-error es used as placeholder
|
||||||
code: 'es',
|
code: 'es',
|
||||||
file: 'es.json',
|
file: 'es.json',
|
||||||
name: 'Español',
|
name: 'Español',
|
||||||
|
@ -203,6 +207,7 @@ const locales: LocaleObjectData[] = [
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
// @ts-expect-error pt used as placeholder
|
||||||
code: 'pt',
|
code: 'pt',
|
||||||
file: 'pt.json',
|
file: 'pt.json',
|
||||||
name: 'Português',
|
name: 'Português',
|
||||||
|
|
|
@ -31,6 +31,7 @@ export const HANDLED_MASTO_URLS = /^(https?:\/\/)?([\w\-]+\.)+\w+\/(@[@\w\-.]+)(
|
||||||
export const NOTIFICATION_FILTER_TYPES: mastodon.v1.NotificationType[] = ['status', 'reblog', 'follow', 'follow_request', 'favourite', 'poll', 'update', 'admin.sign_up', 'admin.report']
|
export const NOTIFICATION_FILTER_TYPES: mastodon.v1.NotificationType[] = ['status', 'reblog', 'follow', 'follow_request', 'favourite', 'poll', 'update', 'admin.sign_up', 'admin.report']
|
||||||
|
|
||||||
export const THEME_COLORS = {
|
export const THEME_COLORS = {
|
||||||
|
defaultTheme: '#cc7d24',
|
||||||
themeDark: '#111111',
|
themeDark: '#111111',
|
||||||
themeLight: '#fafafa',
|
themeLight: '#fafafa',
|
||||||
backgroundDark: '#fafafa',
|
backgroundDark: '#fafafa',
|
||||||
|
|
|
@ -4,7 +4,7 @@ export default defineAppConfig({
|
||||||
description: 'A nimble Mastodon web client.',
|
description: 'A nimble Mastodon web client.',
|
||||||
image: 'https://docs.elk.zone/elk-screenshot.png',
|
image: 'https://docs.elk.zone/elk-screenshot.png',
|
||||||
socials: {
|
socials: {
|
||||||
twitter: 'elk_zone',
|
// twitter: 'elk_zone',
|
||||||
github: 'elk-zone/elk',
|
github: 'elk-zone/elk',
|
||||||
mastodon: {
|
mastodon: {
|
||||||
label: 'Mastodon',
|
label: 'Mastodon',
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
export default defineNuxtConfig({
|
export default defineNuxtConfig({
|
||||||
extends: '@nuxt-themes/docus',
|
extends: '@nuxt-themes/docus',
|
||||||
|
|
||||||
vite: {
|
vite: {
|
||||||
optimizeDeps: {
|
optimizeDeps: {
|
||||||
include: ['scule'],
|
include: ['scule'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
compatibilityDate: '2024-11-07',
|
||||||
})
|
})
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
"theme-colors": "^0.1.0"
|
"theme-colors": "^0.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@nuxt-themes/docus": "^1.15.0",
|
"@nuxt-themes/docus": "^1.15.1",
|
||||||
"nuxt": "^3.13.2"
|
"nuxt": "^3.14.1592"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,17 @@
|
||||||
import { defineTheme } from 'pinceau'
|
import { defineTheme } from 'pinceau'
|
||||||
import { getColors } from 'theme-colors'
|
import { getColors } from 'theme-colors'
|
||||||
|
|
||||||
|
const light = getColors('#995e1b')
|
||||||
|
const primary = Object
|
||||||
|
.entries(getColors('#d98018'))
|
||||||
|
.reduce((acc, [key, value]) => {
|
||||||
|
acc[key] = {
|
||||||
|
initial: light[key]!,
|
||||||
|
dark: value,
|
||||||
|
}
|
||||||
|
return acc
|
||||||
|
}, {} as Record<string | number, { initial: string, dark: string }>)
|
||||||
|
|
||||||
export default defineTheme({
|
export default defineTheme({
|
||||||
color: {
|
color: { primary },
|
||||||
primary: getColors('#d98018'),
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
|
|
211
locales/ca.json
211
locales/ca.json
|
@ -7,6 +7,8 @@
|
||||||
"route_loaded": "S'ha carregat la pàgina {0}"
|
"route_loaded": "S'ha carregat la pàgina {0}"
|
||||||
},
|
},
|
||||||
"account": {
|
"account": {
|
||||||
|
"authorize": "Autoritza seguiment",
|
||||||
|
"authorized": "Has autoritzat la sol·licitud",
|
||||||
"avatar_description": "Avatar de {0}",
|
"avatar_description": "Avatar de {0}",
|
||||||
"blocked_by": "Estàs bloquejat per aquest usuari.",
|
"blocked_by": "Estàs bloquejat per aquest usuari.",
|
||||||
"blocked_domains": "Dominis bloquejats",
|
"blocked_domains": "Dominis bloquejats",
|
||||||
|
@ -25,6 +27,7 @@
|
||||||
"follows_you": "Et segueix",
|
"follows_you": "Et segueix",
|
||||||
"go_to_profile": "Vés al perfil",
|
"go_to_profile": "Vés al perfil",
|
||||||
"joined": "S'ha unit",
|
"joined": "S'ha unit",
|
||||||
|
"lock": "Compte privat",
|
||||||
"moved_title": "ha indicat que el seu nou compte és ara:",
|
"moved_title": "ha indicat que el seu nou compte és ara:",
|
||||||
"muted_users": "Usuaris silenciats",
|
"muted_users": "Usuaris silenciats",
|
||||||
"muting": "Silenciat",
|
"muting": "Silenciat",
|
||||||
|
@ -35,26 +38,34 @@
|
||||||
"posts": "Publicacions",
|
"posts": "Publicacions",
|
||||||
"posts_count": "{0} Publicacions|{0} Publicació|{0} Publicacions",
|
"posts_count": "{0} Publicacions|{0} Publicació|{0} Publicacions",
|
||||||
"profile_description": "Capçalera del perfil de {0}",
|
"profile_description": "Capçalera del perfil de {0}",
|
||||||
|
"profile_personal_note": "Nota Personal",
|
||||||
"profile_unavailable": "Perfil no disponible",
|
"profile_unavailable": "Perfil no disponible",
|
||||||
|
"reject": "rebutja seguiment",
|
||||||
|
"rejected": "Has rebutjat la sol·licitud",
|
||||||
"request_follow": "Sol·licitud de seguiment",
|
"request_follow": "Sol·licitud de seguiment",
|
||||||
|
"requested": "{0} ha sol·licitat seguir-te",
|
||||||
"unblock": "Desbloqueja",
|
"unblock": "Desbloqueja",
|
||||||
"unfollow": "Deixa de seguir",
|
"unfollow": "Deixa de seguir",
|
||||||
"unmute": "Activa el so",
|
"unmute": "Activa el so",
|
||||||
"view_other_followers": "És possible que no es mostrin els seguidors d'altres instàncies.",
|
"view_other_followers": "És possible que no es mostrin els seguidors d'altres instàncies.",
|
||||||
"view_other_following": "És possible que no es mostrin els seguits d'altres instàncies."
|
"view_other_following": "És possible que no es mostrin els seguits d'altres instàncies.",
|
||||||
|
"withdraw follow request": "Retira la sol·licitud de seguiment"
|
||||||
},
|
},
|
||||||
"action": {
|
"action": {
|
||||||
"apply": "Aplicar",
|
"apply": "Aplicar",
|
||||||
"bookmark": "Afegir marcador",
|
"bookmark": "Afegir marcador",
|
||||||
"bookmarked": "Afegit a marcadors",
|
"bookmarked": "Afegit a marcadors",
|
||||||
"boost": "Estímul",
|
"boost": "Impel·lir",
|
||||||
"boost_count": "{0}",
|
"boost_count": "{0}",
|
||||||
"boosted": "Potenciat",
|
"boosted": "Impel·lit",
|
||||||
|
"clear": "Esborrar",
|
||||||
"clear_publish_failed": "Esborra els errors de publicació",
|
"clear_publish_failed": "Esborra els errors de publicació",
|
||||||
|
"clear_save_failed": "Esborra els errors de desar",
|
||||||
"clear_upload_failed": "Esborra els errors de càrrega de fitxers",
|
"clear_upload_failed": "Esborra els errors de càrrega de fitxers",
|
||||||
"close": "Tanca",
|
"close": "Tanca",
|
||||||
"compose": "Redactar",
|
"compose": "Redactar",
|
||||||
"confirm": "Confirmeu",
|
"confirm": "Confirmeu",
|
||||||
|
"done": "Fet",
|
||||||
"edit": "Edita",
|
"edit": "Edita",
|
||||||
"enter_app": "Entra a l'aplicació",
|
"enter_app": "Entra a l'aplicació",
|
||||||
"favourite": "Favorit",
|
"favourite": "Favorit",
|
||||||
|
@ -62,8 +73,10 @@
|
||||||
"favourited": "Favorit",
|
"favourited": "Favorit",
|
||||||
"more": "Més",
|
"more": "Més",
|
||||||
"next": "Següent",
|
"next": "Següent",
|
||||||
|
"open_image_preview_dialog": "Obrir diàleg de vista prèvia de la imatge",
|
||||||
"prev": "Anterior",
|
"prev": "Anterior",
|
||||||
"publish": "Publicar",
|
"publish": "Publicar",
|
||||||
|
"publish_thread": "Publicar fil",
|
||||||
"reply": "Respon",
|
"reply": "Respon",
|
||||||
"reply_count": "{0}",
|
"reply_count": "{0}",
|
||||||
"reset": "Restableix",
|
"reset": "Restableix",
|
||||||
|
@ -98,6 +111,8 @@
|
||||||
"error": "ERROR",
|
"error": "ERROR",
|
||||||
"fetching": "S'està recuperant...",
|
"fetching": "S'està recuperant...",
|
||||||
"in": "en",
|
"in": "en",
|
||||||
|
"no_bookmarks": "Encara no hi ha cap publicacions marcades",
|
||||||
|
"no_favourites": "Encara no hi ha cap publicacions preferides",
|
||||||
"not_found": "404 No trobat",
|
"not_found": "404 No trobat",
|
||||||
"offline_desc": "Sembla que estàs fora de línia. Comproveu la vostra connexió de xarxa."
|
"offline_desc": "Sembla que estàs fora de línia. Comproveu la vostra connexió de xarxa."
|
||||||
},
|
},
|
||||||
|
@ -109,12 +124,14 @@
|
||||||
"block_account": {
|
"block_account": {
|
||||||
"cancel": "Cancel·lar",
|
"cancel": "Cancel·lar",
|
||||||
"confirm": "Bloc",
|
"confirm": "Bloc",
|
||||||
"description": "Confirmes que vols bloquejar {0}?"
|
"description": "Confirmes que vols bloquejar {0}?",
|
||||||
|
"title": "Bloquejar el compte"
|
||||||
},
|
},
|
||||||
"block_domain": {
|
"block_domain": {
|
||||||
"cancel": "Cancel·lar",
|
"cancel": "Cancel·lar",
|
||||||
"confirm": "Bloc",
|
"confirm": "Bloc",
|
||||||
"description": "Confirmes que vols bloquejar {0}?"
|
"description": "Confirmes que vols bloquejar {0}?",
|
||||||
|
"title": "Bloquejar el domini"
|
||||||
},
|
},
|
||||||
"common": {
|
"common": {
|
||||||
"cancel": "No",
|
"cancel": "No",
|
||||||
|
@ -123,27 +140,37 @@
|
||||||
"delete_list": {
|
"delete_list": {
|
||||||
"cancel": "Cancel·lar",
|
"cancel": "Cancel·lar",
|
||||||
"confirm": "Suprimeix",
|
"confirm": "Suprimeix",
|
||||||
"description": "Esteu segur que voleu suprimir la llista \"{0}\"?"
|
"description": "Confirmes que vols la llista \"{0}\"?",
|
||||||
|
"title": "Suprimir la llista"
|
||||||
},
|
},
|
||||||
"delete_posts": {
|
"delete_posts": {
|
||||||
"cancel": "Cancel·lar",
|
"cancel": "Cancel·lar",
|
||||||
"confirm": "Suprimeix",
|
"confirm": "Suprimeix",
|
||||||
"description": "Esteu segur que voleu suprimir aquesta publicació?"
|
"description": "Confirmes que vols suprimir aquesta publicació?",
|
||||||
|
"title": "Suprimir la publicació"
|
||||||
},
|
},
|
||||||
"mute_account": {
|
"mute_account": {
|
||||||
"cancel": "Cancel·lar",
|
"cancel": "Cancel·lar",
|
||||||
"confirm": "Silenciar",
|
"confirm": "Silencia",
|
||||||
"description": "Confirmes que vols silenciar {0}?"
|
"days": "dies|dia|dies",
|
||||||
|
"description": "Confirmes que vols silenciar {0}?",
|
||||||
|
"hours": "hores|hora|hores",
|
||||||
|
"minute": "minuts|minut|minuts",
|
||||||
|
"notifications": "Silenciar notificacions",
|
||||||
|
"specify_duration": "Especificar la durada del silenciat",
|
||||||
|
"title": "Silenciar el compte"
|
||||||
},
|
},
|
||||||
"show_reblogs": {
|
"show_reblogs": {
|
||||||
"cancel": "Cancel·lar",
|
"cancel": "Cancel·lar",
|
||||||
"confirm": "Espectacle",
|
"confirm": "Mostra",
|
||||||
"description": "Confirmes que vols mostrar els augments de {0}?"
|
"description": "Confirmes que vols mostrar els impulsos de {0}?",
|
||||||
|
"title": "Mostrar els impulsos"
|
||||||
},
|
},
|
||||||
"unfollow": {
|
"unfollow": {
|
||||||
"cancel": "Cancel·lar",
|
"cancel": "Cancel·lar",
|
||||||
"confirm": "Deixa de seguir",
|
"confirm": "Deixa de seguir",
|
||||||
"description": "Estàs segur que vols deixar de seguir?"
|
"description": "Estàs segur que vols deixar de seguir?",
|
||||||
|
"title": "Deixar de seguir"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"conversation": {
|
"conversation": {
|
||||||
|
@ -196,11 +223,49 @@
|
||||||
"error": "S'ha produït un error en crear la llista",
|
"error": "S'ha produït un error en crear la llista",
|
||||||
"error_prefix": "Error:",
|
"error_prefix": "Error:",
|
||||||
"list_title_placeholder": "Títol de la llista",
|
"list_title_placeholder": "Títol de la llista",
|
||||||
|
"manage": "Gestionar les llistes",
|
||||||
"modify_account": "Modificar llistes amb compte",
|
"modify_account": "Modificar llistes amb compte",
|
||||||
"remove_account": "Elimina el compte de la llista",
|
"remove_account": "Elimina el compte de la llista",
|
||||||
"save": "Desa els canvis"
|
"save": "Desa els canvis"
|
||||||
},
|
},
|
||||||
|
"magic_keys": {
|
||||||
|
"dialog_header": "Dreceres de teclat",
|
||||||
|
"groups": {
|
||||||
|
"actions": {
|
||||||
|
"boost": "Impel·lir",
|
||||||
|
"command_mode": "Mode de comanda",
|
||||||
|
"compose": "Redactar",
|
||||||
|
"favourite": "Preferit",
|
||||||
|
"search": "Cerca",
|
||||||
|
"show_new_items": "Mostrar noves publicacions",
|
||||||
|
"title": "Accions"
|
||||||
|
},
|
||||||
|
"media": {
|
||||||
|
"title": "Multimèdia"
|
||||||
|
},
|
||||||
|
"navigation": {
|
||||||
|
"go_to_bookmarks": "Marcadors",
|
||||||
|
"go_to_conversations": "Converses",
|
||||||
|
"go_to_explore": "Explorar",
|
||||||
|
"go_to_favourites": "Preferits",
|
||||||
|
"go_to_federated": "Federats",
|
||||||
|
"go_to_home": "Inici",
|
||||||
|
"go_to_lists": "Llistes",
|
||||||
|
"go_to_local": "Local",
|
||||||
|
"go_to_notifications": "Notificacions",
|
||||||
|
"go_to_profile": "Perfil",
|
||||||
|
"go_to_search": "Cercar",
|
||||||
|
"go_to_settings": "Configuració",
|
||||||
|
"next_status": "Estat següent",
|
||||||
|
"previous_status": "Estat anterior",
|
||||||
|
"shortcut_help": "Drecera d'ajuda",
|
||||||
|
"title": "Navegació"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sequence_then": "seguit de"
|
||||||
|
},
|
||||||
"menu": {
|
"menu": {
|
||||||
|
"add_personal_note": "Afegeix una nota personal a {0}",
|
||||||
"block_account": "Bloqueja {0}",
|
"block_account": "Bloqueja {0}",
|
||||||
"block_domain": "Bloqueja el domini {0}",
|
"block_domain": "Bloqueja el domini {0}",
|
||||||
"copy_link_to_post": "Copia l'enllaç a aquesta publicació",
|
"copy_link_to_post": "Copia l'enllaç a aquesta publicació",
|
||||||
|
@ -209,15 +274,18 @@
|
||||||
"delete_and_redraft": "Esborra i torna a redactar",
|
"delete_and_redraft": "Esborra i torna a redactar",
|
||||||
"direct_message_account": "Missatge directe {0}",
|
"direct_message_account": "Missatge directe {0}",
|
||||||
"edit": "Edita",
|
"edit": "Edita",
|
||||||
"hide_reblogs": "Amaga els augments de {0}",
|
"hide_reblogs": "Amaga els impulsos de {0}",
|
||||||
"mention_account": "Esmenta {0}",
|
"mention_account": "Esmenta {0}",
|
||||||
"mute_account": "Silencia {0}",
|
"mute_account": "Silencia {0}",
|
||||||
"mute_conversation": "Silencia aquesta publicació",
|
"mute_conversation": "Silencia aquesta publicació",
|
||||||
"open_in_original_site": "Obre al lloc original",
|
"open_in_original_site": "Obre al lloc original",
|
||||||
"pin_on_profile": "Fixa al perfil",
|
"pin_on_profile": "Fixa al perfil",
|
||||||
|
"remove_personal_note": "Elimina nota personal de {0}",
|
||||||
|
"report_account": "Denuncia {0}",
|
||||||
|
"share_account": "Comparteix {0}",
|
||||||
"share_post": "Comparteix aquesta publicació",
|
"share_post": "Comparteix aquesta publicació",
|
||||||
"show_favourited_and_boosted_by": "Mostra qui ha fet favorits i qui ha augmentat",
|
"show_favourited_and_boosted_by": "Mostra qui ha fet favorits i qui ha impel·lit",
|
||||||
"show_reblogs": "Mostra els augments de {0}",
|
"show_reblogs": "Mostra els impulsos de {0}",
|
||||||
"show_untranslated": "Mostra sense traduir",
|
"show_untranslated": "Mostra sense traduir",
|
||||||
"toggle_theme": {
|
"toggle_theme": {
|
||||||
"dark": "Canvia a mode fosc",
|
"dark": "Canvia a mode fosc",
|
||||||
|
@ -226,10 +294,14 @@
|
||||||
"translate_post": "Tradueix",
|
"translate_post": "Tradueix",
|
||||||
"unblock_account": "Desbloqueja {0}",
|
"unblock_account": "Desbloqueja {0}",
|
||||||
"unblock_domain": "Desbloqueja el domini {0}",
|
"unblock_domain": "Desbloqueja el domini {0}",
|
||||||
|
"unfollow_account": "Deixa de seguir {0}",
|
||||||
"unmute_account": "Deixa de silenciar {0}",
|
"unmute_account": "Deixa de silenciar {0}",
|
||||||
"unmute_conversation": "Deixa de silenciar aquesta publicació",
|
"unmute_conversation": "Deixa de silenciar aquesta publicació",
|
||||||
"unpin_on_profile": "No fixis al perfil"
|
"unpin_on_profile": "No fixis al perfil"
|
||||||
},
|
},
|
||||||
|
"modals": {
|
||||||
|
"aria_label_close": "Tanca"
|
||||||
|
},
|
||||||
"nav": {
|
"nav": {
|
||||||
"back": "Torna",
|
"back": "Torna",
|
||||||
"blocked_domains": "Dominis bloquejats",
|
"blocked_domains": "Dominis bloquejats",
|
||||||
|
@ -238,13 +310,16 @@
|
||||||
"built_at": "Construït {0}",
|
"built_at": "Construït {0}",
|
||||||
"compose": "Redactar",
|
"compose": "Redactar",
|
||||||
"conversations": "Converses",
|
"conversations": "Converses",
|
||||||
|
"docs": "Documentació",
|
||||||
"explore": "Explora",
|
"explore": "Explora",
|
||||||
"favourites": "Preferits",
|
"favourites": "Preferits",
|
||||||
"federated": "Federat",
|
"federated": "Federat",
|
||||||
|
"hashtags": "Etiquetes",
|
||||||
"home": "Inici",
|
"home": "Inici",
|
||||||
"list": "Llista",
|
"list": "Llista",
|
||||||
"lists": "Llistes",
|
"lists": "Llistes",
|
||||||
"local": "Local",
|
"local": "Local",
|
||||||
|
"more_menu": "Més opcions",
|
||||||
"muted_users": "Usuaris silenciats",
|
"muted_users": "Usuaris silenciats",
|
||||||
"notifications": "Notificacions",
|
"notifications": "Notificacions",
|
||||||
"privacy": "Privadesa",
|
"privacy": "Privadesa",
|
||||||
|
@ -264,6 +339,7 @@
|
||||||
"followed_you_count": "{0} persones us han seguit|{0} persones us han seguit|{0} persones us han seguit",
|
"followed_you_count": "{0} persones us han seguit|{0} persones us han seguit|{0} persones us han seguit",
|
||||||
"missing_type": "FALTA notificació.tipus:",
|
"missing_type": "FALTA notificació.tipus:",
|
||||||
"reblogged_post": "ha reblogjat la teva publicació",
|
"reblogged_post": "ha reblogjat la teva publicació",
|
||||||
|
"reported": "{0} va denunciar {1}",
|
||||||
"request_to_follow": "demanat que us segueixi",
|
"request_to_follow": "demanat que us segueixi",
|
||||||
"signed_up": "registrat",
|
"signed_up": "registrat",
|
||||||
"update_status": "ha actualitzat la seva publicació"
|
"update_status": "ha actualitzat la seva publicació"
|
||||||
|
@ -274,10 +350,26 @@
|
||||||
"reply_to_account": "Respon a {0}",
|
"reply_to_account": "Respon a {0}",
|
||||||
"replying": "Responent"
|
"replying": "Responent"
|
||||||
},
|
},
|
||||||
|
"polls": {
|
||||||
|
"allow_multiple": "Permit múltiples opcions",
|
||||||
|
"cancel": "Cancel·lar",
|
||||||
|
"create": "Crear enquesta",
|
||||||
|
"disallow_multiple": "No permetre múltiples opcions",
|
||||||
|
"expiration": "Caducitat de l'enquesta",
|
||||||
|
"hide_votes": "Amaga el total de vots fins al final de l'enquesta",
|
||||||
|
"option_placeholder": "Opció de l'enquesta {current}/{max}",
|
||||||
|
"remove_option": "Elimina opció",
|
||||||
|
"settings": "Opcions de l'enquesta",
|
||||||
|
"show_votes": "Mostra sempre el total de vots"
|
||||||
|
},
|
||||||
"pwa": {
|
"pwa": {
|
||||||
"dismiss": "Descartar",
|
"dismiss": "Descartar",
|
||||||
"install": "Instal·lar",
|
"install": "Instal·lar",
|
||||||
"install_title": "Instal·leu Elk",
|
"install_title": "Instal·lar Elk",
|
||||||
|
"screenshots": {
|
||||||
|
"dark": "Captura de pantalla d'Elk funcionant en mode fosc",
|
||||||
|
"light": "Captura de pantalla d'Elk funcionant en mode clar"
|
||||||
|
},
|
||||||
"title": "Nova actualització d'Elk disponible!",
|
"title": "Nova actualització d'Elk disponible!",
|
||||||
"update": "Actualització",
|
"update": "Actualització",
|
||||||
"update_available_short": "Actualitza Elk",
|
"update_available_short": "Actualitza Elk",
|
||||||
|
@ -304,6 +396,42 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"report": {
|
||||||
|
"additional_comments": "Comentaris addicionals",
|
||||||
|
"another_server": "L'usuari que estàs denunciant pertany a un altre servidor",
|
||||||
|
"anything_else": "Hi ha alguna cosa més que penses que hem de saber?",
|
||||||
|
"block_desc": "No podràs veure més publicacions d'aquest usuari. No podran veure les teves publicacions ni seguir-te. Els indicarà que estan bloquejats.",
|
||||||
|
"dontlike": "No m'agrada",
|
||||||
|
"dontlike_desc": "No és alguna cosa que vulguis veure",
|
||||||
|
"forward": "Sí, continuar amb la denúncia a {0}",
|
||||||
|
"forward_question": "Vols enviar també una còpia anònima d'aquesta denúncia a aquest servidor?",
|
||||||
|
"further_actions": {
|
||||||
|
"limit": {
|
||||||
|
"description": "Aquestes són les opcions per controlar allò que veus:",
|
||||||
|
"title": "No vols veure això?"
|
||||||
|
},
|
||||||
|
"report": {
|
||||||
|
"description": "Mentre ho revisem, aquestes són les accions que pots prendre:",
|
||||||
|
"title": "Gràcies per denunciar-ho, ho investigarem."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"limiting": "Limitar a {0}",
|
||||||
|
"mute_desc": "No podràs veure més publicacions d'aquest usuari. Encara poden seguir-te i veure les teves publicacions. No sabran que estan silenciats.",
|
||||||
|
"other": "És una altra cosa",
|
||||||
|
"other_desc": "La novetat no encaixa en altres categories.",
|
||||||
|
"reporting": "Denunciant a {0}",
|
||||||
|
"select_many": "Selecciona totes les que corresponguin:",
|
||||||
|
"select_one": "Selecciona l'opció més adequada:",
|
||||||
|
"select_posts": "Hi ha alguna publicació de suport per a aquesta denúncia?",
|
||||||
|
"select_posts_other": "Hi ha alguna altra publicació de suport per a aquesta denúncia?",
|
||||||
|
"spam": "És spam",
|
||||||
|
"spam_desc": "Enllaços maliciosos, interaccions falses o respostes repetitives",
|
||||||
|
"submit": "Enviar denúncia",
|
||||||
|
"unfollow_desc": "Ja no veuràs les publicacions d'aquest usuari a la teva línia de temps. És possible que encara vegis les seves publicacions en altres llocs.",
|
||||||
|
"violation": "Viola una o més regles del servidor.",
|
||||||
|
"whats_wrong_account": "Explica'ns què passa amb aquest compte",
|
||||||
|
"whats_wrong_post": "Explica'ns què passa amb aquesta publicació."
|
||||||
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"search_desc": "Cerca persones i hashtags",
|
"search_desc": "Cerca persones i hashtags",
|
||||||
"search_empty": "No s'ha pogut trobar res per a aquests termes de cerca"
|
"search_empty": "No s'ha pogut trobar res per a aquests termes de cerca"
|
||||||
|
@ -326,6 +454,8 @@
|
||||||
"label": "Configuració del compte"
|
"label": "Configuració del compte"
|
||||||
},
|
},
|
||||||
"interface": {
|
"interface": {
|
||||||
|
"bottom_nav": "Navegació inferior",
|
||||||
|
"bottom_nav_instructions": "Tria els teus botons de navegació preferits, fins a cinc per a la navegació inferior. Has d'incloure el botó \"Més opcions\".",
|
||||||
"color_mode": "Mode de color",
|
"color_mode": "Mode de color",
|
||||||
"dark_mode": "Fosc",
|
"dark_mode": "Fosc",
|
||||||
"default": "(per defecte)",
|
"default": "(per defecte)",
|
||||||
|
@ -337,7 +467,9 @@
|
||||||
},
|
},
|
||||||
"language": {
|
"language": {
|
||||||
"display_language": "Idioma de visualització",
|
"display_language": "Idioma de visualització",
|
||||||
|
"how_to_contribute": "Com puc contribuir?",
|
||||||
"label": "Idioma",
|
"label": "Idioma",
|
||||||
|
"post_language": "Idioma de publicació",
|
||||||
"status": "Estat de la traducció: {0}/{1} ({2}%)",
|
"status": "Estat de la traducció: {0}/{1} ({2}%)",
|
||||||
"translations": {
|
"translations": {
|
||||||
"add": "Afegeix",
|
"add": "Afegeix",
|
||||||
|
@ -403,26 +535,38 @@
|
||||||
},
|
},
|
||||||
"notifications_settings": "Notificacions",
|
"notifications_settings": "Notificacions",
|
||||||
"preferences": {
|
"preferences": {
|
||||||
|
"embedded_media": "Reproductor multimèdia incrustat",
|
||||||
|
"embedded_media_description": "Mostrar un reproductor incrustat en lloc de la targeta de vista prèvia normal en expandir enllaços compartits de transmissió multimèdia.",
|
||||||
"enable_autoplay": "Activa la reproducció automàtica",
|
"enable_autoplay": "Activa la reproducció automàtica",
|
||||||
"enable_data_saving": "Activa l'emmagatzematge de dades",
|
"enable_data_saving": "Activa l'emmagatzematge de dades",
|
||||||
"enable_data_saving_description": "Deseu les dades evitant que els fitxers adjunts es carreguin automàticament.",
|
"enable_data_saving_description": "Deseu les dades evitant que els fitxers adjunts es carreguin automàticament.",
|
||||||
"enable_pinch_to_zoom": "Activa el pessic per fer zoom",
|
"enable_pinch_to_zoom": "Activa el pessic per fer zoom",
|
||||||
"github_cards": "Targetes GitHub",
|
"github_cards": "Targetes GitHub",
|
||||||
|
"github_cards_description": "Quan es publica un enllaç de GitHub, es mostra una targeta HTML accessible que utilitza el meta del gràfic social en lloc de la imatge social.",
|
||||||
"grayscale_mode": "Mode d'escala de grisos",
|
"grayscale_mode": "Mode d'escala de grisos",
|
||||||
"hide_account_hover_card": "Amaga la targeta de desplaçament del compte",
|
"hide_account_hover_card": "Amaga la targeta de desplaçament del compte",
|
||||||
"hide_alt_indi_on_posts": "Amaga l'indicador alt a les publicacions",
|
"hide_alt_indi_on_posts": "Amaga l'indicador alt a les publicacions",
|
||||||
"hide_boost_count": "Amaga el recompte d'impulsos",
|
"hide_boost_count": "Amaga el recompte d'impulsos",
|
||||||
"hide_favorite_count": "Amaga el recompte de favorits",
|
"hide_favorite_count": "Amaga el recompte de favorits",
|
||||||
"hide_follower_count": "Amaga el recompte de seguidors",
|
"hide_follower_count": "Amaga el recompte de seguidors",
|
||||||
|
"hide_gif_indi_on_posts": "Amaga l'indicador de gif a les publicacions",
|
||||||
|
"hide_news": "Amaga les notícies",
|
||||||
"hide_reply_count": "Amaga el recompte de respostes",
|
"hide_reply_count": "Amaga el recompte de respostes",
|
||||||
|
"hide_tag_hover_card": "Amaga la targeta flotant de l'etiqueta",
|
||||||
"hide_translation": "Amaga la traducció",
|
"hide_translation": "Amaga la traducció",
|
||||||
"hide_username_emojis": "Amaga els emojis del nom d'usuari",
|
"hide_username_emojis": "Amaga els emojis del nom d'usuari",
|
||||||
"hide_username_emojis_description": "Amaga els emojis dels noms d'usuari a les línies de temps. Els emojis encara seran visibles als seus perfils.",
|
"hide_username_emojis_description": "Amaga els emojis dels noms d'usuari a les línies de temps. Els emojis encara seran visibles als seus perfils.",
|
||||||
"label": "Preferències",
|
"label": "Preferències",
|
||||||
|
"optimize_for_low_performance_device": "Optimitza per a dispositius de baix rendiment",
|
||||||
"title": "Característiques experimentals",
|
"title": "Característiques experimentals",
|
||||||
|
"use_star_favorite_icon": "Utiliza l'icona d'estrella per a favorits",
|
||||||
"user_picker": "Selector d'usuaris",
|
"user_picker": "Selector d'usuaris",
|
||||||
|
"user_picker_description": "Mostra tots els avatars dels comptes registrats a la part inferior esquerra perquè puguis canviar ràpidament entre ells.",
|
||||||
"virtual_scroll": "Desplaçament virtual",
|
"virtual_scroll": "Desplaçament virtual",
|
||||||
"wellbeing": "Benestar"
|
"virtual_scroll_description": "Utilitza una llista virtual a les línies de temps, de manera que es pugui representar una quantitat més gran d'elements de manera eficaç.",
|
||||||
|
"wellbeing": "Benestar",
|
||||||
|
"zen_mode": "Mode Zen",
|
||||||
|
"zen_mode_description": "Amaga les seccions laterals de la interfície tret que el cursor del ratolí estigui sobre elles. També amaga alguns elements de les línies de temps."
|
||||||
},
|
},
|
||||||
"profile": {
|
"profile": {
|
||||||
"appearance": {
|
"appearance": {
|
||||||
|
@ -457,21 +601,32 @@
|
||||||
},
|
},
|
||||||
"state": {
|
"state": {
|
||||||
"attachments_exceed_server_limit": "El nombre de fitxers adjunts ha superat el límit per missatge.",
|
"attachments_exceed_server_limit": "El nombre de fitxers adjunts ha superat el límit per missatge.",
|
||||||
|
"attachments_limit_audio_error": "S'ha superat la mida màxima d'àudio: {0}",
|
||||||
"attachments_limit_error": "S'ha superat el límit per publicació",
|
"attachments_limit_error": "S'ha superat el límit per publicació",
|
||||||
|
"attachments_limit_image_error": "S'ha superat la mida màxima d'imatge: {0}",
|
||||||
|
"attachments_limit_unknown_error": "S'ha superat la mida màxima de fitxer: {0}",
|
||||||
|
"attachments_limit_video_error": "S'ha superat la mida màxima de vídeo: {0}",
|
||||||
"edited": "(Edit)",
|
"edited": "(Edit)",
|
||||||
"editing": "Edició",
|
"editing": "Edició",
|
||||||
"loading": "Carregant...",
|
"loading": "Carregant...",
|
||||||
"publish_failed": "No s'ha pogut publicar",
|
"publish_failed": "No s'ha pogut publicar",
|
||||||
"publishing": "Publicació",
|
"publishing": "Publicació",
|
||||||
|
"save_failed": "Error de desar",
|
||||||
"upload_failed": "La càrrega ha fallat",
|
"upload_failed": "La càrrega ha fallat",
|
||||||
"uploading": "S'està carregant..."
|
"uploading": "S'està carregant..."
|
||||||
},
|
},
|
||||||
"status": {
|
"status": {
|
||||||
|
"account": {
|
||||||
|
"suspended_message": "El compte d'aquest missatge ha estat suspès.",
|
||||||
|
"suspended_show": "Mostrar contingut igualment?"
|
||||||
|
},
|
||||||
"boosted_by": "Impulsat per",
|
"boosted_by": "Impulsat per",
|
||||||
"edited": "Editat {0}",
|
"edited": "Editat {0}",
|
||||||
|
"embedded_warning": "Reproduir això pot revelar la teva adreça IP a altres persones.",
|
||||||
"favourited_by": "Favorit per",
|
"favourited_by": "Favorit per",
|
||||||
"filter_hidden_phrase": "Filtrat per",
|
"filter_hidden_phrase": "Filtrat per",
|
||||||
"filter_show_anyway": "Mostra de totes maneres",
|
"filter_show_anyway": "Mostra de totes maneres",
|
||||||
|
"gif": "GIF",
|
||||||
"img_alt": {
|
"img_alt": {
|
||||||
"ALT": "ALT",
|
"ALT": "ALT",
|
||||||
"desc": "Descripció",
|
"desc": "Descripció",
|
||||||
|
@ -486,6 +641,7 @@
|
||||||
"replying_to": "Responent a {0}",
|
"replying_to": "Responent a {0}",
|
||||||
"show_full_thread": "Mostra el fil complet",
|
"show_full_thread": "Mostra el fil complet",
|
||||||
"someone": "algú",
|
"someone": "algú",
|
||||||
|
"spoiler_media_hidden": "Multimèdia amagada",
|
||||||
"spoiler_show_less": "Mostra menys",
|
"spoiler_show_less": "Mostra menys",
|
||||||
"spoiler_show_more": "Mostra més",
|
"spoiler_show_more": "Mostra més",
|
||||||
"thread": "Fil",
|
"thread": "Fil",
|
||||||
|
@ -502,10 +658,22 @@
|
||||||
"list": "Llista",
|
"list": "Llista",
|
||||||
"media": "Mitjans de comunicació",
|
"media": "Mitjans de comunicació",
|
||||||
"news": "Notícies",
|
"news": "Notícies",
|
||||||
"notifications_all": "Tots",
|
"notifications_admin": {
|
||||||
"notifications_mention": "Esmenta",
|
"report": "Informes",
|
||||||
|
"sign_up": "Inscripcions"
|
||||||
|
},
|
||||||
|
"notifications_all": "Totes",
|
||||||
|
"notifications_favourite": "Preferides",
|
||||||
|
"notifications_follow": "T'han seguit",
|
||||||
|
"notifications_follow_request": "Sol·licituds de seguiment",
|
||||||
|
"notifications_mention": "Esmentes",
|
||||||
|
"notifications_more_tooltip": "Filtrar notificacions per tipus",
|
||||||
|
"notifications_poll": "Enquestes",
|
||||||
|
"notifications_reblog": "Impulsos",
|
||||||
|
"notifications_status": "Publicacions",
|
||||||
|
"notifications_update": "Actualitzacions",
|
||||||
"posts": "Publicacions",
|
"posts": "Publicacions",
|
||||||
"posts_with_replies": "Publicacions"
|
"posts_with_replies": "Publicacions i respostes"
|
||||||
},
|
},
|
||||||
"tag": {
|
"tag": {
|
||||||
"follow": "Seguiu",
|
"follow": "Seguiu",
|
||||||
|
@ -557,6 +725,7 @@
|
||||||
"add_emojis": "Afegeix emojis",
|
"add_emojis": "Afegeix emojis",
|
||||||
"add_media": "Afegiu imatges, un vídeo o un fitxer d'àudio",
|
"add_media": "Afegiu imatges, un vídeo o un fitxer d'àudio",
|
||||||
"add_publishable_content": "Afegeix contingut per publicar",
|
"add_publishable_content": "Afegeix contingut per publicar",
|
||||||
|
"add_thread_item": "Afegeix publicació al fil",
|
||||||
"change_content_visibility": "Canvia la visibilitat del contingut",
|
"change_content_visibility": "Canvia la visibilitat del contingut",
|
||||||
"change_language": "Canviar d'idioma",
|
"change_language": "Canviar d'idioma",
|
||||||
"emoji": "Emoji",
|
"emoji": "Emoji",
|
||||||
|
@ -566,6 +735,8 @@
|
||||||
"open_editor_tools": "Eines de l'editor",
|
"open_editor_tools": "Eines de l'editor",
|
||||||
"pick_an_icon": "Trieu una icona",
|
"pick_an_icon": "Trieu una icona",
|
||||||
"publish_failed": "Tanca els missatges fallits a la part superior de l'editor per tornar a publicar publicacions",
|
"publish_failed": "Tanca els missatges fallits a la part superior de l'editor per tornar a publicar publicacions",
|
||||||
|
"remove_thread_item": "Elimina publicació del fil",
|
||||||
|
"start_thread": "Comença un fil",
|
||||||
"toggle_bold": "Commuta la negreta",
|
"toggle_bold": "Commuta la negreta",
|
||||||
"toggle_code_block": "Commuta el bloc de codi",
|
"toggle_code_block": "Commuta el bloc de codi",
|
||||||
"toggle_italic": "Canvia la cursiva"
|
"toggle_italic": "Canvia la cursiva"
|
||||||
|
|
|
@ -633,6 +633,7 @@
|
||||||
"dismiss": "Dismiss",
|
"dismiss": "Dismiss",
|
||||||
"read": "Read {0} description"
|
"read": "Read {0} description"
|
||||||
},
|
},
|
||||||
|
"pinned": "Pinned post",
|
||||||
"poll": {
|
"poll": {
|
||||||
"count": "{0} votes|{0} vote|{0} votes",
|
"count": "{0} votes|{0} vote|{0} votes",
|
||||||
"ends": "ends {0}",
|
"ends": "ends {0}",
|
||||||
|
|
|
@ -49,7 +49,7 @@
|
||||||
"unmute": "Dejar de silenciar",
|
"unmute": "Dejar de silenciar",
|
||||||
"view_other_followers": "Puede que no se muestren los seguidores de otras instancias.",
|
"view_other_followers": "Puede que no se muestren los seguidores de otras instancias.",
|
||||||
"view_other_following": "Puede que no se muestren los seguidos de otras instancias.",
|
"view_other_following": "Puede que no se muestren los seguidos de otras instancias.",
|
||||||
"withdraw_follow_request": "Retirar solitud de seguimiento"
|
"withdraw_follow_request": "Retirar solicitud de seguimiento"
|
||||||
},
|
},
|
||||||
"action": {
|
"action": {
|
||||||
"apply": "Aplicar",
|
"apply": "Aplicar",
|
||||||
|
|
|
@ -713,6 +713,7 @@
|
||||||
"year_past": "0 évvel ezelőtt|múlt évben|{n} évvel ezelőtt"
|
"year_past": "0 évvel ezelőtt|múlt évben|{n} évvel ezelőtt"
|
||||||
},
|
},
|
||||||
"timeline": {
|
"timeline": {
|
||||||
|
"no_posts": "Itt nincsenek bejegyzések.",
|
||||||
"show_new_items": "{v} új elem megjelenítése|{v} új elem megjelenítése|{v} új elem megjelenítése",
|
"show_new_items": "{v} új elem megjelenítése|{v} új elem megjelenítése|{v} új elem megjelenítése",
|
||||||
"view_older_posts": "Előfordulhat, hogy más instancekről származó régebbi bejegyzések nem jelennek meg."
|
"view_older_posts": "Előfordulhat, hogy más instancekről származó régebbi bejegyzések nem jelennek meg."
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
|
import type { BuildInfo } from '~/types'
|
||||||
import { createResolver, defineNuxtModule } from '@nuxt/kit'
|
import { createResolver, defineNuxtModule } from '@nuxt/kit'
|
||||||
import { isCI } from 'std-env'
|
import { isCI } from 'std-env'
|
||||||
import type { BuildInfo } from '~/types'
|
|
||||||
import { getEnv, version } from '../config/env'
|
import { getEnv, version } from '../config/env'
|
||||||
|
|
||||||
const { resolve } = createResolver(import.meta.url)
|
const { resolve } = createResolver(import.meta.url)
|
||||||
|
|
|
@ -2,6 +2,9 @@
|
||||||
publish = "dist"
|
publish = "dist"
|
||||||
command = "pnpm run build"
|
command = "pnpm run build"
|
||||||
|
|
||||||
|
[build.environment]
|
||||||
|
NODE_OPTIONS = '--max-old-space-size=4096'
|
||||||
|
|
||||||
# Redirect to Discord server
|
# Redirect to Discord server
|
||||||
[[redirects]]
|
[[redirects]]
|
||||||
from = "https://chat.elk.zone"
|
from = "https://chat.elk.zone"
|
||||||
|
|
|
@ -311,9 +311,16 @@ export default defineNuxtConfig({
|
||||||
lazy: true,
|
lazy: true,
|
||||||
strategy: 'no_prefix',
|
strategy: 'no_prefix',
|
||||||
detectBrowserLanguage: false,
|
detectBrowserLanguage: false,
|
||||||
langDir: 'locales',
|
// relative to i18n dir on rootDir: not yet v4 compat layout
|
||||||
|
langDir: '../locales',
|
||||||
defaultLocale: 'en-US',
|
defaultLocale: 'en-US',
|
||||||
|
experimental: {
|
||||||
|
generatedLocaleFilePathFormat: 'relative',
|
||||||
|
},
|
||||||
vueI18n: './config/i18n.config.ts',
|
vueI18n: './config/i18n.config.ts',
|
||||||
|
bundle: {
|
||||||
|
optimizeTranslationDirective: false,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
pwa,
|
pwa,
|
||||||
staleDep: {
|
staleDep: {
|
||||||
|
|
62
package.json
62
package.json
|
@ -2,7 +2,7 @@
|
||||||
"name": "@elk-zone/elk",
|
"name": "@elk-zone/elk",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"version": "0.15.1",
|
"version": "0.15.1",
|
||||||
"packageManager": "pnpm@9.12.3",
|
"packageManager": "pnpm@9.15.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"homepage": "https://elk.zone/",
|
"homepage": "https://elk.zone/",
|
||||||
"main": "./nuxt.config.ts",
|
"main": "./nuxt.config.ts",
|
||||||
|
@ -16,6 +16,7 @@
|
||||||
"start": "PORT=5314 node .output/server/index.mjs",
|
"start": "PORT=5314 node .output/server/index.mjs",
|
||||||
"start:https": "PORT=5314 node ./https-dev-config/local-https-server.mjs",
|
"start:https": "PORT=5314 node ./https-dev-config/local-https-server.mjs",
|
||||||
"lint": "eslint --cache .",
|
"lint": "eslint --cache .",
|
||||||
|
"lint:fix": "eslint --cache --fix .",
|
||||||
"typecheck": "stale-dep && nuxi typecheck",
|
"typecheck": "stale-dep && nuxi typecheck",
|
||||||
"prepare": "ignore-dependency-scripts \"tsx scripts/prepare.ts\"",
|
"prepare": "ignore-dependency-scripts \"tsx scripts/prepare.ts\"",
|
||||||
"generate": "nuxi generate",
|
"generate": "nuxi generate",
|
||||||
|
@ -40,8 +41,8 @@
|
||||||
"@nuxt/devtools": "^1.5.2",
|
"@nuxt/devtools": "^1.5.2",
|
||||||
"@nuxt/test-utils": "^3.14.3",
|
"@nuxt/test-utils": "^3.14.3",
|
||||||
"@nuxtjs/color-mode": "^3.4.4",
|
"@nuxtjs/color-mode": "^3.4.4",
|
||||||
"@nuxtjs/i18n": "^8.5.3",
|
"@nuxtjs/i18n": "^9.1.1",
|
||||||
"@pinia/nuxt": "^0.5.4",
|
"@pinia/nuxt": "^0.9.0",
|
||||||
"@tiptap/core": "2.2.4",
|
"@tiptap/core": "2.2.4",
|
||||||
"@tiptap/extension-bold": "2.2.4",
|
"@tiptap/extension-bold": "2.2.4",
|
||||||
"@tiptap/extension-character-count": "2.2.4",
|
"@tiptap/extension-character-count": "2.2.4",
|
||||||
|
@ -56,9 +57,9 @@
|
||||||
"@tiptap/starter-kit": "2.2.4",
|
"@tiptap/starter-kit": "2.2.4",
|
||||||
"@tiptap/suggestion": "2.2.4",
|
"@tiptap/suggestion": "2.2.4",
|
||||||
"@tiptap/vue-3": "2.2.4",
|
"@tiptap/vue-3": "2.2.4",
|
||||||
"@unocss/nuxt": "^0.63.6",
|
"@unocss/nuxt": "^0.65.0",
|
||||||
"@upstash/redis": "^1.27.1",
|
"@upstash/redis": "^1.27.1",
|
||||||
"@vercel/kv": "^2.0.0",
|
"@vercel/kv": "^3.0.0",
|
||||||
"@vue-macros/nuxt": "^1.11.12",
|
"@vue-macros/nuxt": "^1.11.12",
|
||||||
"@vueuse/core": "^11.0.3",
|
"@vueuse/core": "^11.0.3",
|
||||||
"@vueuse/gesture": "^2.0.0",
|
"@vueuse/gesture": "^2.0.0",
|
||||||
|
@ -85,15 +86,15 @@
|
||||||
"lru-cache": "^11.0.0",
|
"lru-cache": "^11.0.0",
|
||||||
"masto": "^6.10.1",
|
"masto": "^6.10.1",
|
||||||
"node-emoji": "^2.1.3",
|
"node-emoji": "^2.1.3",
|
||||||
"nuxt-security": "^1.4.3",
|
"nuxt-security": "^2.0.0",
|
||||||
"page-lifecycle": "^0.1.2",
|
"page-lifecycle": "^0.1.2",
|
||||||
"pinia": "^2.2.2",
|
"pinia": "^2.2.6",
|
||||||
"postcss-nested": "^6.0.1",
|
"postcss-nested": "^7.0.0",
|
||||||
"prosemirror-highlight": "^0.9.0",
|
"prosemirror-highlight": "^0.11.0",
|
||||||
"rollup-plugin-node-polyfills": "^0.2.1",
|
"rollup-plugin-node-polyfills": "^0.2.1",
|
||||||
"shiki": "^1.0.0",
|
"shiki": "^1.22.2",
|
||||||
"simple-git": "^3.19.1",
|
"simple-git": "^3.19.1",
|
||||||
"slimeform": "^0.9.1",
|
"slimeform": "^0.10.0",
|
||||||
"stale-dep": "^0.7.0",
|
"stale-dep": "^0.7.0",
|
||||||
"std-env": "^3.7.0",
|
"std-env": "^3.7.0",
|
||||||
"string-length": "^5.0.1",
|
"string-length": "^5.0.1",
|
||||||
|
@ -105,7 +106,7 @@
|
||||||
"ufo": "^1.5.3",
|
"ufo": "^1.5.3",
|
||||||
"ultrahtml": "^1.5.3",
|
"ultrahtml": "^1.5.3",
|
||||||
"unimport": "^3.10.0",
|
"unimport": "^3.10.0",
|
||||||
"vite-plugin-pwa": "^0.20.5",
|
"vite-plugin-pwa": "^0.21.0",
|
||||||
"vue-advanced-cropper": "^2.8.9",
|
"vue-advanced-cropper": "^2.8.9",
|
||||||
"vue-virtual-scroller": "2.0.0-beta.8",
|
"vue-virtual-scroller": "2.0.0-beta.8",
|
||||||
"workbox-build": "^7.1.1",
|
"workbox-build": "^7.1.1",
|
||||||
|
@ -113,48 +114,45 @@
|
||||||
"ws": "^8.15.1"
|
"ws": "^8.15.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@antfu/eslint-config": "^3.7.3",
|
"@antfu/eslint-config": "^3.12.0",
|
||||||
"@antfu/ni": "^0.23.0",
|
"@antfu/ni": "^0.23.1",
|
||||||
|
"@nuxt/schema": "^3.14.1592",
|
||||||
"@types/chroma-js": "^2.4.4",
|
"@types/chroma-js": "^2.4.4",
|
||||||
"@types/file-saver": "^2.0.7",
|
"@types/file-saver": "^2.0.7",
|
||||||
"@types/fnando__sparkline": "^0.3.7",
|
"@types/fnando__sparkline": "^0.3.7",
|
||||||
"@types/fs-extra": "^11.0.4",
|
"@types/fs-extra": "^11.0.4",
|
||||||
"@types/js-yaml": "^4.0.9",
|
"@types/js-yaml": "^4.0.9",
|
||||||
"@types/wicg-file-system-access": "^2023.10.5",
|
"@types/wicg-file-system-access": "^2023.10.5",
|
||||||
"@types/ws": "^8.5.12",
|
"@types/ws": "^8.5.13",
|
||||||
"@unlazy/nuxt": "^0.11.3",
|
"@unlazy/nuxt": "^0.12.1",
|
||||||
"@unocss/eslint-config": "^0.63.6",
|
"@unocss/eslint-config": "^0.65.1",
|
||||||
"@vue/test-utils": "2.4.6",
|
"@vue/test-utils": "2.4.6",
|
||||||
"bumpp": "^9.7.1",
|
"bumpp": "^9.9.1",
|
||||||
"consola": "^3.2.3",
|
"consola": "^3.2.3",
|
||||||
"eslint": "^9.12.0",
|
"eslint": "^9.17.0",
|
||||||
"eslint-plugin-format": "^0.1.2",
|
"eslint-plugin-format": "^0.1.3",
|
||||||
"flat": "^6.0.1",
|
"flat": "^6.0.1",
|
||||||
"fs-extra": "^11.2.0",
|
"fs-extra": "^11.2.0",
|
||||||
"lint-staged": "^15.2.10",
|
"lint-staged": "^15.2.11",
|
||||||
"nuxt": "^3.13.2",
|
"nuxt": "^3.14.1592",
|
||||||
"prettier": "^3.3.3",
|
"prettier": "^3.4.2",
|
||||||
"sharp": "^0.33.5",
|
"sharp": "^0.33.5",
|
||||||
"sharp-ico": "^0.1.5",
|
"sharp-ico": "^0.1.5",
|
||||||
"simple-git-hooks": "^2.11.1",
|
"simple-git-hooks": "^2.11.1",
|
||||||
"tsx": "^4.19.2",
|
"tsx": "^4.19.2",
|
||||||
"typescript": "^5.4.4",
|
"typescript": "^5.4.4",
|
||||||
"vitest": "2.1.3",
|
"vitest": "2.1.8",
|
||||||
"vue-tsc": "^2.1.6"
|
"vue-tsc": "^2.1.6"
|
||||||
},
|
},
|
||||||
"pnpm": {
|
"pnpm": {
|
||||||
"patchedDependencies": {
|
"patchedDependencies": {
|
||||||
"@vueuse/motion": "patches/@vueuse__motion.patch",
|
"pinceau": "patches/pinceau.patch"
|
||||||
"pinceau": "patches/pinceau.patch",
|
|
||||||
"vue-i18n": "patches/vue-i18n.patch",
|
|
||||||
"nuxt-security": "patches/nuxt-security.patch",
|
|
||||||
"nuxt": "patches/nuxt.patch"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"resolutions": {
|
"resolutions": {
|
||||||
"nuxt-component-meta": "0.8.2",
|
"nuxt-component-meta": "0.9.0",
|
||||||
"unstorage": "^1.12.0",
|
"unstorage": "^1.13.1",
|
||||||
"vitest": "2.1.3",
|
"vitest": "2.1.8",
|
||||||
"vue": "^3.5.4"
|
"vue": "^3.5.4"
|
||||||
},
|
},
|
||||||
"simple-git-hooks": {
|
"simple-git-hooks": {
|
||||||
|
|
|
@ -10,11 +10,21 @@ const { t } = useI18n()
|
||||||
|
|
||||||
const account = await fetchAccountByHandle(handle.value)
|
const account = await fetchAccountByHandle(handle.value)
|
||||||
|
|
||||||
|
// we need to ensure `pinned === true` on status
|
||||||
|
// because this prop is appeared only on current account's posts
|
||||||
|
function applyPinned(statuses: mastodon.v1.Status[]) {
|
||||||
|
return statuses.map((status) => {
|
||||||
|
status.pinned = true
|
||||||
|
return status
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
function reorderAndFilter(items: mastodon.v1.Status[]) {
|
function reorderAndFilter(items: mastodon.v1.Status[]) {
|
||||||
return reorderedTimeline(items, 'account')
|
return reorderedTimeline(items, 'account')
|
||||||
}
|
}
|
||||||
|
|
||||||
const paginator = useMastoClient().v1.accounts.$select(account.id).statuses.list({ limit: 30, excludeReplies: true })
|
const pinnedPaginator = useMastoClient().v1.accounts.$select(account.id).statuses.list({ pinned: true })
|
||||||
|
const postPaginator = useMastoClient().v1.accounts.$select(account.id).statuses.list({ limit: 30, excludeReplies: true })
|
||||||
|
|
||||||
if (account) {
|
if (account) {
|
||||||
useHydratedHead({
|
useHydratedHead({
|
||||||
|
@ -26,6 +36,9 @@ if (account) {
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<AccountTabs />
|
<AccountTabs />
|
||||||
<TimelinePaginator :paginator="paginator" :preprocess="reorderAndFilter" context="account" :account="account" />
|
<TimelinePaginator :paginator="pinnedPaginator" :preprocess="applyPinned" context="account" :account="account" :end-message="false" />
|
||||||
|
<!-- Upper border -->
|
||||||
|
<div h="1px" w-auto bg-border mb-1 />
|
||||||
|
<TimelinePaginator :paginator="postPaginator" :preprocess="reorderAndFilter" context="account" :account="account" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { mastodon } from 'masto'
|
import type { mastodon } from 'masto'
|
||||||
import { NOTIFICATION_FILTER_TYPES } from '~/constants'
|
|
||||||
import type { CommonRouteTabMoreOption, CommonRouteTabOption } from '~/types'
|
import type { CommonRouteTabMoreOption, CommonRouteTabOption } from '~/types'
|
||||||
|
import { NOTIFICATION_FILTER_TYPES } from '~/constants'
|
||||||
|
|
||||||
definePageMeta({
|
definePageMeta({
|
||||||
middleware: 'auth',
|
middleware: 'auth',
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
/* eslint-disable no-alert */
|
/* eslint-disable no-alert */
|
||||||
import { fileOpen } from 'browser-fs-access'
|
|
||||||
import type { UserLogin } from '~/types'
|
import type { UserLogin } from '~/types'
|
||||||
|
import { fileOpen } from 'browser-fs-access'
|
||||||
|
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
|
|
||||||
|
|
|
@ -1,39 +0,0 @@
|
||||||
diff --git a/dist/shared/motion.6686175e.d.cts b/dist/shared/motion.6686175e.d.cts
|
|
||||||
index d118e42ad332997dd203623a8a2bd5109ecdd04f..6ec3bad16555148ec11461e90e2a68116bf1d887 100644
|
|
||||||
--- a/dist/shared/motion.6686175e.d.cts
|
|
||||||
+++ b/dist/shared/motion.6686175e.d.cts
|
|
||||||
@@ -594,7 +594,7 @@ interface SpringControls {
|
|
||||||
values: MotionProperties;
|
|
||||||
}
|
|
||||||
type MotionInstanceBindings<T extends string, V extends MotionVariants<T>> = Record<string, MotionInstance<T, V>>;
|
|
||||||
-declare module '@vue/runtime-core' {
|
|
||||||
+declare module 'vue' {
|
|
||||||
interface ComponentCustomProperties {
|
|
||||||
$motions?: MotionInstanceBindings<any, any>;
|
|
||||||
}
|
|
||||||
diff --git a/dist/shared/motion.6686175e.d.mts b/dist/shared/motion.6686175e.d.mts
|
|
||||||
index d118e42ad332997dd203623a8a2bd5109ecdd04f..6ec3bad16555148ec11461e90e2a68116bf1d887 100644
|
|
||||||
--- a/dist/shared/motion.6686175e.d.mts
|
|
||||||
+++ b/dist/shared/motion.6686175e.d.mts
|
|
||||||
@@ -594,7 +594,7 @@ interface SpringControls {
|
|
||||||
values: MotionProperties;
|
|
||||||
}
|
|
||||||
type MotionInstanceBindings<T extends string, V extends MotionVariants<T>> = Record<string, MotionInstance<T, V>>;
|
|
||||||
-declare module '@vue/runtime-core' {
|
|
||||||
+declare module 'vue' {
|
|
||||||
interface ComponentCustomProperties {
|
|
||||||
$motions?: MotionInstanceBindings<any, any>;
|
|
||||||
}
|
|
||||||
diff --git a/dist/shared/motion.6686175e.d.ts b/dist/shared/motion.6686175e.d.ts
|
|
||||||
index d118e42ad332997dd203623a8a2bd5109ecdd04f..6ec3bad16555148ec11461e90e2a68116bf1d887 100644
|
|
||||||
--- a/dist/shared/motion.6686175e.d.ts
|
|
||||||
+++ b/dist/shared/motion.6686175e.d.ts
|
|
||||||
@@ -594,7 +594,7 @@ interface SpringControls {
|
|
||||||
values: MotionProperties;
|
|
||||||
}
|
|
||||||
type MotionInstanceBindings<T extends string, V extends MotionVariants<T>> = Record<string, MotionInstance<T, V>>;
|
|
||||||
-declare module '@vue/runtime-core' {
|
|
||||||
+declare module 'vue' {
|
|
||||||
interface ComponentCustomProperties {
|
|
||||||
$motions?: MotionInstanceBindings<any, any>;
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
diff --git a/dist/runtime/nitro/plugins/40-preprocessHtml.mjs b/dist/runtime/nitro/plugins/40-preprocessHtml.mjs
|
|
||||||
index ce2df85b5951ac48adb0f3ecbfa9daaff5e4d6cf..cb47bd2858e46f141e75e6ebccf44079687968b7 100644
|
|
||||||
--- a/dist/runtime/nitro/plugins/40-preprocessHtml.mjs
|
|
||||||
+++ b/dist/runtime/nitro/plugins/40-preprocessHtml.mjs
|
|
||||||
@@ -1,5 +1,5 @@
|
|
||||||
import { defineNitroPlugin } from "#imports";
|
|
||||||
-import * as cheerio from "cheerio/lib/slim";
|
|
||||||
+import * as cheerio from "cheerio/slim";
|
|
||||||
import { resolveSecurityRules } from "../utils/index.mjs";
|
|
||||||
export default defineNitroPlugin((nitroApp) => {
|
|
||||||
nitroApp.hooks.hook("render:html", (html, { event }) => {
|
|
|
@ -1,12 +0,0 @@
|
||||||
diff --git a/dist/index.mjs b/dist/index.mjs
|
|
||||||
index a5c61adc0c21b5df5b1a3ffcf81d2469c7f96873..9241cf294b398b43a4a5555f39746a6c844d0b0f 100644
|
|
||||||
--- a/dist/index.mjs
|
|
||||||
+++ b/dist/index.mjs
|
|
||||||
@@ -2183,6 +2183,7 @@ function createTransformPlugin(nuxt, getComponents, mode) {
|
|
||||||
}
|
|
||||||
return createUnplugin(() => ({
|
|
||||||
name: "nuxt:components:imports",
|
|
||||||
+ enforce: "post",
|
|
||||||
transformInclude(id) {
|
|
||||||
id = normalize(id);
|
|
||||||
return id.startsWith("virtual:") || id.startsWith("\0virtual:") || id.startsWith(nuxt.options.buildDir) || !isIgnored(id);
|
|
|
@ -1,13 +0,0 @@
|
||||||
diff --git a/dist/vue-i18n.d.ts b/dist/vue-i18n.d.ts
|
|
||||||
index 8d5c4fc0e551ab3beccfcaa67764818a2c4c6756..0cee95f214e03add239d3df5e91ad2a8a154ac1e 100644
|
|
||||||
--- a/dist/vue-i18n.d.ts
|
|
||||||
+++ b/dist/vue-i18n.d.ts
|
|
||||||
@@ -3125,7 +3125,7 @@ export declare type WarnHtmlInMessageLevel = 'off' | 'warn' | 'error';
|
|
||||||
|
|
||||||
export { }
|
|
||||||
|
|
||||||
-declare module '@vue/runtime-core' {
|
|
||||||
+declare module 'vue' {
|
|
||||||
/**
|
|
||||||
* Component Custom Options for Vue I18n
|
|
||||||
*
|
|
|
@ -1,6 +1,6 @@
|
||||||
|
import type { UserLogin } from '~/types'
|
||||||
import { useAsyncIDBKeyval } from '~/composables/idb'
|
import { useAsyncIDBKeyval } from '~/composables/idb'
|
||||||
import { STORAGE_KEY_USERS } from '~/constants'
|
import { STORAGE_KEY_USERS } from '~/constants'
|
||||||
import type { UserLogin } from '~/types'
|
|
||||||
|
|
||||||
const mock = process.mock
|
const mock = process.mock
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import type { Locale } from '#i18n'
|
||||||
|
|
||||||
export default defineNuxtPlugin(async (nuxt) => {
|
export default defineNuxtPlugin(async (nuxt) => {
|
||||||
const t = nuxt.vueApp.config.globalProperties.$t
|
const t = nuxt.vueApp.config.globalProperties.$t
|
||||||
const d = nuxt.vueApp.config.globalProperties.$d
|
const d = nuxt.vueApp.config.globalProperties.$d
|
||||||
|
@ -11,14 +13,14 @@ export default defineNuxtPlugin(async (nuxt) => {
|
||||||
const i18n = useNuxtApp().$i18n
|
const i18n = useNuxtApp().$i18n
|
||||||
const { setLocale, locales } = i18n
|
const { setLocale, locales } = i18n
|
||||||
const userSettings = useUserSettings()
|
const userSettings = useUserSettings()
|
||||||
const lang = computed(() => userSettings.value.language)
|
const lang = computed(() => userSettings.value.language as Locale)
|
||||||
|
|
||||||
const supportLanguages = unref(locales).map(locale => locale.code)
|
const supportLanguages = unref(locales).map(locale => locale.code)
|
||||||
if (!supportLanguages.includes(lang.value))
|
if (!supportLanguages.includes(lang.value))
|
||||||
userSettings.value.language = getDefaultLanguage(supportLanguages)
|
userSettings.value.language = getDefaultLanguage(supportLanguages)
|
||||||
|
|
||||||
if (lang.value !== i18n.locale)
|
if (lang.value !== i18n.locale)
|
||||||
await setLocale(userSettings.value.language)
|
await setLocale(userSettings.value.language as Locale)
|
||||||
|
|
||||||
watch([lang, isHydrated], () => {
|
watch([lang, isHydrated], () => {
|
||||||
if (isHydrated.value && lang.value !== i18n.locale)
|
if (isHydrated.value && lang.value !== i18n.locale)
|
||||||
|
|
7216
pnpm-lock.yaml
7216
pnpm-lock.yaml
File diff suppressed because it is too large
Load diff
|
@ -1,5 +1,5 @@
|
||||||
import chroma from 'chroma-js'
|
|
||||||
import type { ThemeColors } from '~/composables/settings'
|
import type { ThemeColors } from '~/composables/settings'
|
||||||
|
import chroma from 'chroma-js'
|
||||||
|
|
||||||
// #cc7d24 -> hcl(67.14,62.19,59.56)
|
// #cc7d24 -> hcl(67.14,62.19,59.56)
|
||||||
export const themesColor = Array.from(
|
export const themesColor = Array.from(
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import type { LocaleEntry } from '../docs/types'
|
import type { LocaleEntry } from '../docs/types'
|
||||||
|
import type { ElkTranslationStatus } from '~/types/translation-status'
|
||||||
import { Buffer } from 'node:buffer'
|
import { Buffer } from 'node:buffer'
|
||||||
import { readFile, writeFile } from 'node:fs/promises'
|
import { readFile, writeFile } from 'node:fs/promises'
|
||||||
import { createResolver } from '@nuxt/kit'
|
import { createResolver } from '@nuxt/kit'
|
||||||
import { flatten } from 'flat'
|
import { flatten } from 'flat'
|
||||||
import type { ElkTranslationStatus } from '~/types/translation-status'
|
|
||||||
import { countryLocaleVariants, currentLocales } from '../config/i18n'
|
import { countryLocaleVariants, currentLocales } from '../config/i18n'
|
||||||
|
|
||||||
export const localeData: [code: string, file: string[], title: string][]
|
export const localeData: [code: string, file: string[], title: string][]
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
import { stringifyQuery } from 'ufo'
|
import { stringifyQuery } from 'ufo'
|
||||||
|
|
||||||
|
import { defaultUserAgent } from '~/server/utils/shared'
|
||||||
|
|
||||||
export default defineEventHandler(async (event) => {
|
export default defineEventHandler(async (event) => {
|
||||||
let { server, origin } = getRouterParams(event)
|
let { server, origin } = getRouterParams(event)
|
||||||
server = server.toLocaleLowerCase().trim()
|
server = server.toLocaleLowerCase().trim()
|
||||||
|
@ -24,6 +26,9 @@ export default defineEventHandler(async (event) => {
|
||||||
try {
|
try {
|
||||||
const result: any = await $fetch(`https://${server}/oauth/token`, {
|
const result: any = await $fetch(`https://${server}/oauth/token`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'user-agent': defaultUserAgent,
|
||||||
|
},
|
||||||
body: {
|
body: {
|
||||||
client_id: app.client_id,
|
client_id: app.client_id,
|
||||||
client_secret: app.client_secret,
|
client_secret: app.client_secret,
|
||||||
|
|
|
@ -1,20 +1,21 @@
|
||||||
|
import type { AppInfo } from '~/types'
|
||||||
|
// @ts-expect-error virtual import
|
||||||
|
import { env } from '#build-info'
|
||||||
|
// @ts-expect-error virtual import
|
||||||
|
import { driver } from '#storage-config'
|
||||||
import { $fetch } from 'ofetch'
|
import { $fetch } from 'ofetch'
|
||||||
|
|
||||||
import kv from 'unstorage/drivers/cloudflare-kv-http'
|
import kv from 'unstorage/drivers/cloudflare-kv-http'
|
||||||
|
|
||||||
import fs from 'unstorage/drivers/fs'
|
import fs from 'unstorage/drivers/fs'
|
||||||
|
|
||||||
import memory from 'unstorage/drivers/memory'
|
import memory from 'unstorage/drivers/memory'
|
||||||
|
|
||||||
import vercelKVDriver from 'unstorage/drivers/vercel-kv'
|
import vercelKVDriver from 'unstorage/drivers/vercel-kv'
|
||||||
|
|
||||||
import cached from '../cache-driver'
|
import { version } from '~/config/env'
|
||||||
|
|
||||||
// @ts-expect-error virtual import
|
|
||||||
import { env } from '#build-info'
|
|
||||||
|
|
||||||
// @ts-expect-error virtual import
|
|
||||||
import { driver } from '#storage-config'
|
|
||||||
|
|
||||||
import { APP_NAME } from '~/constants'
|
import { APP_NAME } from '~/constants'
|
||||||
import type { AppInfo } from '~/types'
|
import cached from '../cache-driver'
|
||||||
|
|
||||||
const storage = useStorage<AppInfo>()
|
const storage = useStorage<AppInfo>()
|
||||||
|
|
||||||
|
@ -48,9 +49,14 @@ export function getRedirectURI(origin: string, server: string) {
|
||||||
return `${origin}/api/${server}/oauth/${encodeURIComponent(origin)}`
|
return `${origin}/api/${server}/oauth/${encodeURIComponent(origin)}`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const defaultUserAgent = `${APP_NAME}/${version}`
|
||||||
|
|
||||||
async function fetchAppInfo(origin: string, server: string) {
|
async function fetchAppInfo(origin: string, server: string) {
|
||||||
const app: AppInfo = await $fetch(`https://${server}/api/v1/apps`, {
|
const app: AppInfo = await $fetch(`https://${server}/api/v1/apps`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'user-agent': defaultUserAgent,
|
||||||
|
},
|
||||||
body: {
|
body: {
|
||||||
client_name: APP_NAME + (env !== 'release' ? ` (${env})` : ''),
|
client_name: APP_NAME + (env !== 'release' ? ` (${env})` : ''),
|
||||||
website: 'https://elk.zone',
|
website: 'https://elk.zone',
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
|
import type { ContentParseOptions } from '~/composables/content-parse'
|
||||||
import { format } from 'prettier'
|
import { format } from 'prettier'
|
||||||
import { render as renderTree } from 'ultrahtml'
|
import { render as renderTree } from 'ultrahtml'
|
||||||
import { describe, expect, it } from 'vitest'
|
import { describe, expect, it } from 'vitest'
|
||||||
import type { ContentParseOptions } from '~/composables/content-parse'
|
|
||||||
|
|
||||||
describe('html-parse', () => {
|
describe('html-parse', () => {
|
||||||
it('empty', async () => {
|
it('empty', async () => {
|
||||||
|
|
Loading…
Reference in a new issue