Skip to content

Commit

Permalink
Merge branch 'main' into shuuji3/feat/line-height
Browse files Browse the repository at this point in the history
  • Loading branch information
shuuji3 authored Dec 19, 2024
2 parents b24b53c + 4c63f6b commit 66d13f7
Show file tree
Hide file tree
Showing 50 changed files with 4,388 additions and 3,110 deletions.
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ We've added some `UnoCSS` utilities styles to help you with that:

## 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.

Expand Down
17 changes: 11 additions & 6 deletions components/account/AccountAvatar.vue
Original file line number Diff line number Diff line change
@@ -1,27 +1,32 @@
<script setup lang="ts">
import type { mastodon } from 'masto'
defineProps<{
const props = defineProps<{
account: mastodon.v1.Account
square?: boolean
}>()
const loaded = 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>

<template>
<img
:key="account.avatar"
:key="props.account.avatar"
width="400"
height="400"
select-none
:src="(error || !loaded) ? 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7' : account.avatar"
:alt="$t('account.avatar_description', [account.username])"
:src="(error || !loaded) ? 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7' : accountAvatarSrc"
:alt="$t('account.avatar_description', [props.account.username])"
loading="lazy"
class="account-avatar"
:class="(loaded ? 'bg-base' : 'bg-gray:10') + (square ? ' ' : ' rounded-full')"
:style="{ 'clip-path': square ? `url(#avatar-mask)` : 'none' }"
:class="(loaded ? 'bg-base' : 'bg-gray:10') + (props.square ? ' ' : ' rounded-full')"
:style="{ 'clip-path': props.square ? `url(#avatar-mask)` : 'none' }"
v-bind="$attrs"
@load="loaded = true"
@error="error = true"
Expand Down
10 changes: 5 additions & 5 deletions components/common/CommonRouteTabs.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ const router = useRouter()
useCommands(() => command
? options.map(tab => ({
scope: 'Tabs',
name: tab.display,
icon: tab.icon ?? 'i-ri:file-list-2-line',
onActivate: () => router.replace(tab.to),
}))
scope: 'Tabs',
name: tab.display,
icon: tab.icon ?? 'i-ri:file-list-2-line',
onActivate: () => router.replace(tab.to),
}))
: [])
</script>

Expand Down
10 changes: 5 additions & 5 deletions components/common/CommonTabs.vue
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ function toValidName(option: string) {
useCommands(() => command
? tabs.value.map(tab => ({
scope: 'Tabs',
scope: 'Tabs',
name: tab.display,
icon: tab.icon ?? 'i-ri:file-list-2-line',
name: tab.display,
icon: tab.icon ?? 'i-ri:file-list-2-line',
onActivate: () => modelValue.value = tab.name,
}))
onActivate: () => modelValue.value = tab.name,
}))
: [])
</script>

Expand Down
2 changes: 1 addition & 1 deletion components/modal/ModalContainer.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<script setup lang="ts">
import type { mastodon } from 'masto'
import type { ConfirmDialogChoice } from '~/types'
import {
isCommandPanelOpen,
isConfirmDialogOpen,
Expand All @@ -13,7 +14,6 @@ import {
isReportDialogOpen,
isSigninDialogOpen,
} from '~/composables/dialog'
import type { ConfirmDialogChoice } from '~/types'
const isMac = useIsMac()
Expand Down
3 changes: 3 additions & 0 deletions components/nav/NavLogo.vue
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
<script setup lang="ts">
</script>

<template>
<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
Expand Down
4 changes: 2 additions & 2 deletions components/nav/button/MoreMenu.vue
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<script setup lang="ts">
defineModel<boolean>()
const model = defineModel<boolean>()
</script>

<template>
<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
>
<button
Expand Down
46 changes: 39 additions & 7 deletions components/notification/NotificationCard.vue
Original file line number Diff line number Diff line change
@@ -1,16 +1,38 @@
<script setup lang="ts">
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<{
notification: mastodon.v1.Notification
notification: Notification
}>()
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
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})`)
}
</script>

<template>
Expand Down Expand Up @@ -95,11 +117,21 @@ if (unsupportedEmojiReactionTypes.includes(notification.type))
<template v-else-if="notification.type === 'mention' || notification.type === 'poll' || notification.type === 'status'">
<StatusCard :status="notification.status!" />
</template>
<template v-else-if="!unsupportedEmojiReactionTypes.includes(notification.type)">
<!-- prevent showing errors for dev for known emoji reaction types -->
<!-- type 'favourite' and 'reblog' should always rendered by NotificationGroupedLikes -->
<div text-red font-bold>
[DEV] {{ $t('notification.missing_type') }} '{{ notification.type }}'
<template v-else-if="notification.type === 'annual_report'">
<div flex p4 items-center bg-shaded>
<div i-mdi:party-popper text-xl me-4 color-purple />
<div class="content-rich">
<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>
</template>
</article>
Expand Down
2 changes: 1 addition & 1 deletion components/notification/NotificationPaginator.vue
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<script setup lang="ts">
import type { mastodon } from 'masto'
import type { GroupedAccountLike, NotificationSlot } from '~/types'
// @ts-expect-error missing types
import { DynamicScrollerItem } from 'vue-virtual-scroller'
import type { GroupedAccountLike, NotificationSlot } from '~/types'
const { paginator, stream } = defineProps<{
paginator: mastodon.Paginator<mastodon.v1.Notification[], mastodon.rest.v1.ListNotificationsParams>
Expand Down
3 changes: 2 additions & 1 deletion components/publish/PublishWidget.vue
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<script setup lang="ts">
import type { mastodon } from 'masto'
import type { DraftItem } from '~/types'
import { EditorContent } from '@tiptap/vue-3'
import stringLength from 'string-length'
import type { DraftItem } from '~/types'
const {
threadComposer,
Expand Down Expand Up @@ -522,6 +522,7 @@ function stopQuestionMarkPropagation(e: KeyboardEvent) {
v-if="!threadIsActive || isFinalItemOfThread"
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"
:disabled="isPublishDisabled || isExceedingCharacterLimit"
@click="publish"
>
<span v-if="isSending" block animate-spin preserve-3d>
Expand Down
2 changes: 1 addition & 1 deletion components/publish/PublishWidgetFull.client.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script setup lang="ts">
import { formatTimeAgo } from '@vueuse/core'
import type { DraftItem } from '~/types'
import { formatTimeAgo } from '@vueuse/core'
const route = useRoute()
const { formatNumber } = useHumanReadableNumber()
Expand Down
2 changes: 1 addition & 1 deletion components/settings/SettingsBottomNav.vue
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const defaultSelectedNavButtonNames = computed<NavButtonName[]>(() =>
: ['explore', 'local', 'federated', 'moreMenu'],
)
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[]>(() =>
selectedNavButtonNames.value.map(name =>
Expand Down
43 changes: 38 additions & 5 deletions components/settings/SettingsThemeColors.vue
Original file line number Diff line number Diff line change
@@ -1,10 +1,42 @@
<script setup lang="ts">
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 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) {
settings.value.themeColors = theme
Expand All @@ -18,10 +50,11 @@ function updateTheme(theme: ThemeColors) {
</h2>
<div flex="~ gap4 wrap" p2 role="group" aria-labelledby="interface-tc">
<button
v-for="[key, theme] in themes" :key="key"
v-for="[key, theme] in useThemes" :key="key"
:style="{
'background': key,
'--local-ring-color': key,
'--rgb-primary': theme['--rgb-primary'],
'background': theme['--c-primary'],
'--local-ring-color': theme['--c-primary'],
}"
type="button"
:class="currentTheme === theme['--theme-color-name'] ? 'ring-2' : 'scale-90'"
Expand Down
7 changes: 6 additions & 1 deletion components/timeline/TimelinePublicLocal.vue
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
<script setup lang="ts">
import type { mastodon } from 'masto'
const paginator = useMastoClient().v1.timelines.public.list({ limit: 30, local: true })
const stream = useStreaming(client => client.public.local.subscribe())
function reorderAndFilter(items: mastodon.v1.Status[]) {
return reorderedTimeline(items, 'public')
}
</script>

<template>
<div>
<TimelinePaginator v-bind="{ paginator, stream }" context="public" />
<TimelinePaginator v-bind="{ paginator, stream }" :preprocess="reorderAndFilter" context="public" />
</div>
</template>
4 changes: 2 additions & 2 deletions components/tiptap/TiptapEmojiList.vue
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<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 { 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'
const { items, command } = defineProps<{
Expand Down
2 changes: 1 addition & 1 deletion composables/command.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import type { LocaleObject } from '@nuxtjs/i18n'
import type { ComputedRef } from 'vue'
import type { SearchResult } from '~/composables/masto/search'
import Fuse from 'fuse.js'
import { defineStore } from 'pinia'
import type { SearchResult } from '~/composables/masto/search'

// @unocss-include

Expand Down
5 changes: 5 additions & 0 deletions composables/content-parse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,11 @@ export function parseMastodonHTML(
inReplyToStatus,
} = options

// remove newline before Tags
html = html.replace(/\n(<[^>]+>)/g, (_1, raw) => {
return raw
})

if (markdown) {
// Handle code blocks
html = html
Expand Down
2 changes: 1 addition & 1 deletion composables/dialog.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { mastodon } from 'masto'
import { STORAGE_KEY_FIRST_VISIT } from '~/constants'
import type { ConfirmDialogChoice, ConfirmDialogOptions, DraftItem, ErrorDialogData } from '~/types'
import { STORAGE_KEY_FIRST_VISIT } from '~/constants'

export const confirmDialogChoice = ref<ConfirmDialogChoice>()
export const confirmDialogLabel = ref<ConfirmDialogOptions>()
Expand Down
2 changes: 1 addition & 1 deletion composables/masto/masto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import type { Pausable } from '@vueuse/core'
import type { mastodon } from 'masto'
import type { Ref } from 'vue'
import type { ElkInstance } from '../users'
import { createRestAPIClient, createStreamingAPIClient } from 'masto'
import type { UserLogin } from '~/types'
import { createRestAPIClient, createStreamingAPIClient } from 'masto'

export function createMasto() {
return {
Expand Down
2 changes: 1 addition & 1 deletion composables/masto/publish.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { DraftItem } from '~~/types'
import type { mastodon } from 'masto'
import type { Ref } from 'vue'
import type { DraftItem } from '~~/types'
import { fileOpen } from 'browser-fs-access'

export function usePublish(options: {
Expand Down
2 changes: 1 addition & 1 deletion composables/masto/statusDrafts.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import type { mastodon } from 'masto'
import type { ComputedRef, Ref } from 'vue'
import { STORAGE_KEY_DRAFTS } from '~/constants'
import type { DraftItem, DraftMap } from '~/types'
import type { Mutable } from '~/types/utils'
import { STORAGE_KEY_DRAFTS } from '~/constants'

export const currentUserDrafts = (import.meta.server || process.test)
? computed<DraftMap>(() => ({}))
Expand Down
6 changes: 3 additions & 3 deletions composables/users.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ import type { MaybeRefOrGetter, RemovableRef } from '@vueuse/core'
import type { mastodon } from 'masto'
import type { EffectScope, Ref } from 'vue'
import type { ElkMasto } from './masto/masto'
import { withoutProtocol } from 'ufo'
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 {
DEFAULT_POST_CHARS_LIMIT,
STORAGE_KEY_CURRENT_USER_HANDLE,
Expand All @@ -12,8 +14,6 @@ import {
STORAGE_KEY_NOTIFICATION_POLICY,
STORAGE_KEY_SERVERS,
} from '~/constants'
import type { UserLogin } from '~/types'
import type { Overwrite } from '~/types/utils'

const mock = process.mock

Expand Down
Loading

0 comments on commit 66d13f7

Please sign in to comment.