Compare commits

...

103 commits

Author SHA1 Message Date
b217b4dc25
Merge branch 'pull-v0.13.2'
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/tag/woodpecker Pipeline was successful
2024-04-07 14:35:26 +02:00
f2edec194f
feat(config): switch default instance
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/pr/woodpecker Pipeline was successful
ci/woodpecker/pull_request_closed/woodpecker Pipeline was successful
set fedi.femby.page as default instance
2024-04-07 14:31:19 +02:00
087f8cc992
fix(ci): add missing docker pushes 2024-04-07 14:29:15 +02:00
6efbf8768b
fix(ci): add secrets 2024-04-07 14:29:15 +02:00
cd934fcd55
fix(ci): docker login 2024-04-07 14:29:15 +02:00
7f1e97a37c
fix(ci): remove docker login 2024-04-07 14:29:15 +02:00
58c84b2f9b
fix(ci): add docker login 2024-04-07 14:29:14 +02:00
322ffeef12
feat(ci): add docker push test 2024-04-07 14:29:14 +02:00
4a8110a52e
fix(ci): add missing flags docker buildx 2024-04-07 14:29:14 +02:00
d481c0ae7a
fix(ci): added missing flag for cut 2024-04-07 14:29:14 +02:00
68ffb627e7
fix(ci): deleted sh uncompatible line 2024-04-07 14:29:14 +02:00
b221687139
feat(ci): Made ci sh compatible (hopefully^^) 2024-04-07 14:29:14 +02:00
7b10620cca
feat(ci): Add build tags 2024-04-07 14:29:13 +02:00
498face3cf
test(ci): 2024-04-07 14:29:13 +02:00
672ff46072
test(ci): add git to image 2024-04-07 14:29:13 +02:00
81b5f8b8e7
test(ci): another syntax test 2024-04-07 14:29:13 +02:00
721e55be06
test(ci): another syntax test 2024-04-07 14:29:13 +02:00
eba4cc0757
test(ci): another syntax test 2024-04-07 14:29:13 +02:00
80818ed52d
test(ci): syntax test 2024-04-07 14:28:32 +02:00
patak-dev
25fb7c1c97 chore: release v0.13.2 2024-04-05 18:29:15 +02:00
TAKAHASHI Shuuji
839aa52e86
fix: adjust background spacing in direct message (#2764) 2024-04-05 16:23:52 +00:00
TAKAHASHI Shuuji
9ff55289ea
ci(ci.yml): limit maximum execution time of ci test (#2763) 2024-04-05 16:19:53 +00:00
Joaquín Sánchez
73293fbcd3
chore: update nuxt to 3.11.2 (#2755) 2024-04-05 14:34:42 +00:00
TAKAHASHI Shuuji
a27c218802
chore: update github avatar images (#2762) 2024-04-05 14:34:19 +00:00
Emanuel Pina
f8fc0efadc
feat(i18n): Update portuguese from Portugal translation (#2756) 2024-04-05 09:16:30 +00:00
Joaquín Sánchez
618a5b2df3
chore(ui): use full width in settings toggle items (#2754) 2024-04-05 09:16:11 +00:00
lazzzis
1146dca5f6
fix(ui): media preview card is misaligned (#2751) 2024-04-05 09:15:44 +00:00
Joaquín Sánchez
f86e856ee6
feat(i18n): add missing spanish translations (gifs, docs and contributing) (#2753) 2024-04-04 18:36:03 +00:00
renovate[bot]
6d13d61227
chore(deps): update devdependencies (#2725)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: TAKAHASHI Shuuji <shuuji3@gmail.com>
2024-04-04 16:47:27 +00:00
Francesco
0de9825bf2
feat(i18n): Update it-IT locale (#2750) 2024-04-04 13:25:09 +00:00
Joaquín Sánchez
3f0b234cc4
feat(ui): add max. file size check before upload attachment (#2709)
Co-authored-by: TAKAHASHI Shuuji <shuuji3@gmail.com>
2024-04-04 10:28:18 +00:00
lazzzis
8f04ea8eee
feat(ui): improve gif support (#2752) 2024-04-04 10:27:52 +00:00
Emanuel Pina
7dcafa3fe0
feat(i18n): Update portuguese from Portugal translation (#2747) 2024-04-04 05:17:03 +00:00
Joaquín Sánchez
bead2183b2
fix(ui): don't scroll on settings item click when external or _blank target link (#2742) 2024-04-03 13:59:42 +00:00
patak
59dda09cd4
fix: notifications in update timeline (#2740) 2024-04-03 13:59:24 +00:00
lazzzis
d0b115751f
feat(ui): style blockquote (#2744) 2024-04-03 04:17:52 +00:00
lazzzis
c6787aae3f
fix(ui): clicking on custom emoji does not navigate to status detail (#2743) 2024-04-03 04:17:30 +00:00
patak
9025416ab3
feat: update info dialog (#2741) 2024-04-02 03:17:45 +00:00
TAKAHASHI Shuuji
aa28257754
feat: add "Documentation" link to "About" page (#2734) 2024-04-01 14:57:11 +00:00
TAKAHASHI Shuuji
d807e06fa0
refactor: various typo fixes (#2735) 2024-04-01 14:56:30 +00:00
TAKAHASHI Shuuji
611d556936
feat: put sign-in icon to default "Sign in" button (#2736) 2024-04-01 14:55:31 +00:00
Xabi
4313002950
feat(i18n): update eu-ES.json (#2737) 2024-04-01 14:54:37 +00:00
TAKAHASHI Shuuji
de11a60b17
feat: add "How to contribute?" link next to language status (#2733) 2024-04-01 05:27:47 +00:00
TAKAHASHI Shuuji
5064b269e7
feat: show background color for direct post to reduce mistake (#2732) 2024-04-01 05:26:51 +00:00
TAKAHASHI Shuuji
d8d9975756
fix: hide duplicated status actions items on details page in zen mode (#2731) 2024-04-01 05:25:53 +00:00
TAKAHASHI Shuuji
eee671cdc3
fix: improve keyboard operability especially on search page and editor (#2730)
Co-authored-by: patak <583075+patak-dev@users.noreply.github.com>
2024-04-01 05:24:42 +00:00
lazzzis
587c063aba
fix(ui): remove a duplicated command (#2718) 2024-03-30 04:19:22 +00:00
lazzzis
28514e956d
fix(ui): wrong polls are removed (#2720) 2024-03-30 04:18:33 +00:00
lazzzis
42aeb8fa35
fix(ui): prevent from navigating to search page when opening command panel (#2719) 2024-03-30 04:15:58 +00:00
Joaquín Sánchez
f6f50a582e
fix(ui): change status actions title (#2717) 2024-03-29 20:04:55 +00:00
patak-dev
f86818867b chore: release v0.13.1 2024-03-29 16:37:28 +01:00
Sma11X
82d962a54b
fix: add missing notification event type (#2714) 2024-03-29 15:31:53 +00:00
renovate[bot]
1b189043e4
chore(deps): update devdependencies (major) (#2400)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-26 08:51:07 +00:00
renovate[bot]
a4867566d9
chore(deps): update devdependencies (#2697)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-26 08:34:06 +00:00
renovate[bot]
0757db69b2
chore(deps): update dependency @types/prettier to v3 (#2712)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-26 08:33:11 +00:00
renovate[bot]
f0de25c992
chore(deps): update dependency @antfu/eslint-config to ^2.9.0 (#2711)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-26 08:32:33 +00:00
TAKAHASHI Shuuji
660549b08b
chore: update masto to v6.7.0 (#2708) 2024-03-21 15:18:53 +00:00
Joaquín Sánchez
7807730118
feat(i18n): add missing spanish mute duration dialog entries (#2696) 2024-03-21 12:37:57 +00:00
Joaquín Sánchez
b526db0860
chore: update i18n module to 8.2.0 (#2703) 2024-03-21 12:13:28 +00:00
Sma11X
0133324ded
fix: correct local timeline stream (#2707) 2024-03-21 10:08:51 +00:00
TAKAHASHI Shuuji
e9ab0cd40b
fix: prevent showing notification errors for dev for known emoji reaction types (#2704) 2024-03-19 15:04:16 +00:00
Joaquín Sánchez
9251ec496b
chore: add ofetch to typescript.hoist (#2693)
Co-authored-by: Daniel Roe <daniel@roe.dev>
2024-03-19 12:56:14 +00:00
renovate[bot]
bd4cd02b2b
chore(deps): update pnpm to v8.15.5 (#2698)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-19 12:40:13 +00:00
Joaquín Sánchez
74ccfece5d
chore: update nuxt to 3.11.1 (#2702) 2024-03-19 12:36:25 +00:00
35b4c80311
fix(ci): add missing docker pushes
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/tag/woodpecker Pipeline was successful
2024-03-18 14:50:56 +01:00
f6a081d199 Merge pull request 'feat-add-woodpecker' (#1) from feat-add-woodpecker into main
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
Reviewed-on: #1
2024-03-18 13:42:55 +00:00
5e419045ed
fix(ci): add secrets
All checks were successful
ci/woodpecker/pr/woodpecker Pipeline was successful
ci/woodpecker/pull_request_closed/woodpecker Pipeline was successful
2024-03-18 14:24:49 +01:00
cfdbb66b96
fix(ci): docker login 2024-03-18 14:16:41 +01:00
c717aace86
fix(ci): remove docker login 2024-03-18 14:10:31 +01:00
6713329a5e
fix(ci): add docker login 2024-03-18 14:00:02 +01:00
7470468077
feat(ci): add docker push test 2024-03-18 13:53:05 +01:00
9044b3bcad
fix(ci): add missing flags docker buildx 2024-03-18 13:41:39 +01:00
5bd9dce91e
fix(ci): added missing flag for cut 2024-03-18 13:39:40 +01:00
12e14cfc05
fix(ci): deleted sh uncompatible line 2024-03-18 13:37:51 +01:00
1ea4399765
feat(ci): Made ci sh compatible (hopefully^^) 2024-03-18 13:34:44 +01:00
991cb812da
feat(ci): Add build tags 2024-03-18 13:26:08 +01:00
Sma11X
c89e499f96
fix: pre tag overwritten by default style (#2699) 2024-03-18 11:34:03 +00:00
Dohány Tamás
89e3582dd7
feat(i18n): Update hu-HU.json (#2694) 2024-03-17 19:11:42 +00:00
TAKAHASHI Shuuji
48c013709a
ci(docker.yml): support linux/arm64 container (#2691) 2024-03-17 15:15:04 +00:00
renovate[bot]
f90f0a2e61
chore(deps): update pnpm to v8.15.4 (#2627)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-17 15:14:19 +00:00
renovate[bot]
c58b585855
chore(deps): update lint (#2399)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-17 15:14:04 +00:00
Joaquín Sánchez
ded2e0f3d7
chore: update nuxt to 3.11.0 (#2692) 2024-03-17 14:32:02 +00:00
9b77efe1d7
test(ci): 2024-03-16 15:52:25 +01:00
aec670a903
test(ci): add git to image 2024-03-16 15:48:38 +01:00
1218f92133
test(ci): another syntax test 2024-03-16 15:45:13 +01:00
7c0986a005
test(ci): another syntax test 2024-03-16 15:42:49 +01:00
ac01207283
test(ci): another syntax test 2024-03-16 15:37:04 +01:00
ef169d682f
test(ci): syntax test 2024-03-16 15:33:04 +01:00
Joaquín Sánchez
21d5633233
chore: bump to eslint-config to 2.8.1 (#2685) 2024-03-13 06:39:28 +00:00
Joaquín Sánchez
7703565c75
fix(ui): hashtags not working when composing (#2686) 2024-03-12 20:47:05 +00:00
cuithon
5a9546ec0a
chore: fix typo (#2681)
Signed-off-by: cuithon <dscs@outlook.com>
2024-03-12 07:58:20 +00:00
patak
bc30a8bd82 chore: release v0.13.0 2024-03-11 12:08:52 +01:00
Duy
c432c2bd0d
feat(i18n): Update vi-VN.json (#2664) 2024-03-11 10:55:18 +00:00
Francesco
364fbd350b
feat(i18n): Update it-IT locale (#2666) 2024-03-11 10:55:05 +00:00
Xabi
c64580f782
feat(i18n): update eu-ES.json (#2670) 2024-03-11 10:54:53 +00:00
Emanuel Pina
e7dfdafd59
feat(i18n): Update portuguese from Portugal translation (#2671) 2024-03-11 10:54:38 +00:00
Ayo Ayco
b06ec9356d
feat(i18n): update Tagalog translations (#2677) 2024-03-11 10:54:20 +00:00
TAKAHASHI Shuuji
3b1a66c93c
fix: fix vue/no-ref-as-operand and vue/return-in-computed-property ESLint errors (#2679) 2024-03-11 10:53:25 +00:00
TAKAHASHI Shuuji
ed8a1811cc
chore: upgrade @vueuse/core from 10.8.0 to 10.9.0 (#2674) 2024-03-10 18:38:37 +00:00
TAKAHASHI Shuuji
dfbe2e080d
fix: prevent empty search keyword to send invalid request (#2676) 2024-03-10 18:37:32 +00:00
TAKAHASHI Shuuji
0fd9374e8c
fix: fix incorrect follow status on followers and following pages (#2669) 2024-03-09 19:31:40 +00:00
TAKAHASHI Shuuji
1c8e48bee4
fix: show loading spinner on follow button while fetching account relationship (#2667)
Co-authored-by: patak <583075+patak-dev@users.noreply.github.com>
2024-03-09 18:44:44 +00:00
TAKAHASHI Shuuji
3448335356
feat: allow to set mute duration and notifications mute option (#2665) 2024-03-09 09:52:41 +00:00
83 changed files with 3704 additions and 2723 deletions

View file

@ -32,6 +32,7 @@ jobs:
- name: 🧪 Test project
run: pnpm test:ci
timeout-minutes: 10
- name: 📝 Lint
run: pnpm lint

View file

@ -38,7 +38,7 @@ jobs:
uses: docker/build-push-action@v5
with:
context: .
platforms: linux/amd64
platforms: linux/amd64,linux/arm64
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.metal.outputs.tags }}
labels: ${{ steps.metal.outputs.labels }}

22
.woodpecker.yml Normal file
View file

@ -0,0 +1,22 @@
steps:
- name: build docker
image: docker:25-cli
secrets: [user, pass]
commands:
- apk add git
- REPO=$(echo "$CI_REPO" | tr '[:upper:]' '[:lower:]')
- REGISTRY="dev.cat-enby.club"
- MAJOR=$(echo ${CI_COMMIT_TAG} | cut -d '.' -f 1 | tr -d 'v')
- MINOR=$(echo ${CI_COMMIT_TAG} | cut -d '.' -f 2)
- PATCH=$(echo ${CI_COMMIT_TAG} | cut -d '.' -f 3 | cut -d '-' -f 1)
- docker buildx build -t $${REGISTRY}/$${REPO}:v$${MAJOR:-0}.$${MINOR:-0}.$${PATCH-0} -t $${REGISTRY}/$${REPO}:v$${MAJOR:-0}.$${MINOR} -t $${REGISTRY}/$$REPO:v$${MAJOR:-0} -t $${REGISTRY}/$$REPO:latest .
- docker login --username $USER --password $PASS $${REGISTRY}
- docker push $${REGISTRY}/$${REPO}:v$${MAJOR:-0}.$${MINOR:-0}.$${PATCH-0}
- docker push $${REGISTRY}/$${REPO}:v$${MAJOR:-0}.$${MINOR}
- docker push $${REGISTRY}/$${REPO}:v$${MAJOR:-0}
- docker push $${REGISTRY}/$${REPO}:latest
volumes:
- /var/run/docker.sock:/var/run/docker.sock
when:
- repo: nikurasu:elk-test-ci
- event: tag

View file

@ -83,7 +83,7 @@ Simple approach used by most websites of relying on direction set in HTML elemen
We've added some `UnoCSS` utilities styles to help you with that:
- Do not use `left/right` padding and margin: for example `pl-1`. Use `padding-inline-start/end` instead. So `pl-1` should be `ps-1`, `pr-1` should be `pe-1`. The same rules apply to margin.
- Do not use `rtl-` classes, such as `rtl-left-0`.
- For icons that should be rotated for RTL, add `class="rtl-flip"`. This can only be used for icons outside of elements with `dir="auto"`, such as timeline, and is the only exception from the rule above. For icons inside the timeline, it might not work as expected.
- For icons that should be rotated for RTL, add `class="rtl-flip"`. This can only be used for icons outside of elements with `dir="auto"`, such as timeline, and is the only exception to the rule above. For icons inside the timeline, it might not work as expected.
- For absolute positioned elements, don't use `left/right`: for example `left-0`. Use `inset-inline-start/end` instead. `UnoCSS` shortcuts are `inset-is` for `inset-inline-start` and `inset-ie` for `inset-inline-end`. Example: `left-0` should be replaced with `inset-is-0`.
- If you need to change the border radius for an entire left or right side, use `border-inline-start/end`. `UnoCSS` shortcuts are `rounded-is` for left side, `rounded-ie` for right side. Example: `rounded-l-5` should be replaced with `rounded-ie-5`.
- If you need to change the border radius for one corner, use `border-start-end-radius` and similar rules. `UnoCSS` shortcuts are `rounded` + top/bottom as either `-bs` (top) or `-be` (bottom) + left/right as either `-is` (left) or `-ie` (right). Example: `rounded-tl-0` should be replaced with `rounded-bs-is-0`.

View file

@ -13,6 +13,7 @@ const { t } = useI18n()
const isSelf = useSelfAccount(() => account)
const enable = computed(() => !isSelf.value && currentUser.value)
const relationship = computed(() => props.relationship || useRelationship(account).value)
const isLoading = computed(() => relationship.value === undefined)
const { client } = useMasto()
@ -62,6 +63,10 @@ const buttonStyle = computed(() => {
if (relationship.value ? relationship.value.following : context === 'following')
return `text-base ${relationship.value?.followedBy ? 'border-strong' : 'border-base'}`
// If loading, use a plain style
if (isLoading.value)
return 'text-base border-base'
// If not following, use a button style
return 'text-inverted bg-primary border-primary'
})
@ -77,28 +82,33 @@ const buttonStyle = computed(() => {
:hover="!relationship?.blocking && !relationship?.muting && relationship?.following ? 'border-red text-red' : 'bg-base border-primary text-primary'"
@click="relationship?.blocking ? unblock() : relationship?.muting ? unmute() : toggleFollowAccount(relationship!, account)"
>
<template v-if="relationship?.blocking">
<span elk-group-hover="hidden">{{ $t('account.blocking') }}</span>
<span hidden elk-group-hover="inline">{{ $t('account.unblock') }}</span>
</template>
<template v-if="relationship?.muting">
<span elk-group-hover="hidden">{{ $t('account.muting') }}</span>
<span hidden elk-group-hover="inline">{{ $t('account.unmute') }}</span>
</template>
<template v-else-if="relationship ? relationship.following : context === 'following'">
<span elk-group-hover="hidden">{{ relationship?.followedBy ? $t('account.mutuals') : $t('account.following') }}</span>
<span hidden elk-group-hover="inline">{{ $t('account.unfollow') }}</span>
</template>
<template v-else-if="relationship?.requested">
<span elk-group-hover="hidden">{{ $t('account.follow_requested') }}</span>
<span hidden elk-group-hover="inline">{{ $t('account.withdraw_follow_request') }}</span>
</template>
<template v-else-if="relationship ? relationship.followedBy : context === 'followedBy'">
<span elk-group-hover="hidden">{{ $t('account.follows_you') }}</span>
<span hidden elk-group-hover="inline">{{ account.locked ? $t('account.request_follow') : $t('account.follow_back') }}</span>
<template v-if="isLoading">
<span i-svg-spinners-180-ring-with-bg />
</template>
<template v-else>
<span>{{ account.locked ? $t('account.request_follow') : $t('account.follow') }}</span>
<template v-if="relationship?.blocking">
<span elk-group-hover="hidden">{{ $t('account.blocking') }}</span>
<span hidden elk-group-hover="inline">{{ $t('account.unblock') }}</span>
</template>
<template v-if="relationship?.muting">
<span elk-group-hover="hidden">{{ $t('account.muting') }}</span>
<span hidden elk-group-hover="inline">{{ $t('account.unmute') }}</span>
</template>
<template v-else-if="relationship ? relationship.following : context === 'following'">
<span elk-group-hover="hidden">{{ relationship?.followedBy ? $t('account.mutuals') : $t('account.following') }}</span>
<span hidden elk-group-hover="inline">{{ $t('account.unfollow') }}</span>
</template>
<template v-else-if="relationship?.requested">
<span elk-group-hover="hidden">{{ $t('account.follow_requested') }}</span>
<span hidden elk-group-hover="inline">{{ $t('account.withdraw_follow_request') }}</span>
</template>
<template v-else-if="relationship ? relationship.followedBy : context === 'followedBy'">
<span elk-group-hover="hidden">{{ $t('account.follows_you') }}</span>
<span hidden elk-group-hover="inline">{{ account.locked ? $t('account.request_follow') : $t('account.follow_back') }}</span>
</template>
<template v-else>
<span>{{ account.locked ? $t('account.request_follow') : $t('account.follow') }}</span>
</template>
</template>
</button>
</template>

View file

@ -25,13 +25,16 @@ function shareAccount() {
}
async function toggleReblogs() {
if (!relationship.value!.showingReblogs && await openConfirmDialog({
title: t('confirm.show_reblogs.title'),
description: t('confirm.show_reblogs.description', [account.acct]),
confirm: t('confirm.show_reblogs.confirm'),
cancel: t('confirm.show_reblogs.cancel'),
}) !== 'confirm')
return
if (!relationship.value!.showingReblogs) {
const dialogChoice = await openConfirmDialog({
title: t('confirm.show_reblogs.title'),
description: t('confirm.show_reblogs.description', [account.acct]),
confirm: t('confirm.show_reblogs.confirm'),
cancel: t('confirm.show_reblogs.cancel'),
})
if (dialogChoice.choice !== 'confirm')
return
}
const showingReblogs = !relationship.value?.showingReblogs
relationship.value = await client.value.v1.accounts.$select(account.id).follow({ reblogs: showingReblogs })

View file

@ -22,7 +22,7 @@ onMounted(() => {
const commandMode = computed(() => input.value.startsWith('>'))
const query = computed(() => commandMode ? '' : input.value.trim())
const query = computed(() => commandMode.value ? '' : input.value.trim())
const { accounts, hashtags, loading } = useSearch(query)
@ -61,7 +61,7 @@ const searchResult = computed<QueryResult>(() => {
}
})
const result = computed<QueryResult>(() => commandMode
const result = computed<QueryResult>(() => commandMode.value
? registry.query(scopes.value.map(s => s.id).join('.'), input.value.slice(1).trim())
: searchResult.value,
)

View file

@ -4,6 +4,8 @@ defineProps<{
hover?: boolean
iconChecked?: string
iconUnchecked?: string
checkedIconColor?: string
prependCheckbox?: boolean
}>()
const modelValue = defineModel<boolean | null>()
</script>
@ -15,9 +17,12 @@ const modelValue = defineModel<boolean | null>()
v-bind="$attrs"
@click.prevent="modelValue = !modelValue"
>
<span v-if="label" flex-1 ms-2 pointer-events-none>{{ label }}</span>
<span v-if="label && !prependCheckbox" flex-1 ms-2 pointer-events-none>{{ label }}</span>
<span
:class="modelValue ? (iconChecked ?? 'i-ri:checkbox-line') : (iconUnchecked ?? 'i-ri:checkbox-blank-line')"
:class="[
modelValue ? (iconChecked ?? 'i-ri:checkbox-line') : (iconUnchecked ?? 'i-ri:checkbox-blank-line'),
modelValue && checkedIconColor,
]"
text-lg
aria-hidden="true"
/>
@ -26,6 +31,7 @@ const modelValue = defineModel<boolean | null>()
type="checkbox"
sr-only
>
<span v-if="label && prependCheckbox" flex-1 ms-2 pointer-events-none>{{ label }}</span>
</label>
</template>

View file

@ -8,6 +8,7 @@ import type { UnwrapRef } from 'vue'
const {
paginator,
stream,
eventType,
keyProp = 'id',
virtualScroller = false,
preprocess,
@ -17,6 +18,7 @@ const {
keyProp?: keyof T
virtualScroller?: boolean
stream?: mastodon.streaming.Subscription
eventType?: 'update' | 'notification'
preprocess?: (items: (U | T)[]) => U[]
endMessage?: boolean | string
}>()
@ -44,7 +46,7 @@ defineSlots<{
const { t } = useI18n()
const nuxtApp = useNuxtApp()
const { items, prevItems, update, state, endAnchor, error } = usePaginator(paginator, toRef(() => stream), preprocess)
const { items, prevItems, update, state, endAnchor, error } = usePaginator(paginator, toRef(() => stream), eventType, preprocess)
nuxtApp.hook('elk-logo:click', () => {
update()

View file

@ -19,8 +19,8 @@ const tabs = computed(() => {
})
})
function toValidName(otpion: string) {
return otpion.toLowerCase().replace(/[^a-zA-Z0-9]/g, '-')
function toValidName(option: string) {
return option.toLowerCase().replace(/[^a-zA-Z0-9]/g, '-')
}
useCommands(() => command

View file

@ -30,10 +30,12 @@ const vAutoFocus = (el: HTMLElement) => el.focus()
</NuxtLink>
{{ $t('help.desc_para6') }}
</p>
{{ $t('help.desc_para3') }}
<p flex="~ gap-2 wrap" mxa>
<NuxtLink hover:text-primary href="https://github.com/sponsors/elk-zone" target="_blank">
{{ $t('help.desc_para3') }}
</NuxtLink>
<p flex="~ gap-2 wrap justify-center" mxa>
<template v-for="team of elkTeamMembers" :key="team.github">
<NuxtLink :href="`https://github.com/sponsors/${team.github}`" target="_blank" external rounded-full transition duration-300 border="~ transparent" hover="scale-105 border-primary">
<NuxtLink :href="team.link" target="_blank" external rounded-full transition duration-300 border="~ transparent" hover="scale-105 border-primary">
<img :src="`/avatars/${team.github}-100x100.png`" :alt="team.display" rounded-full w-15 h-15 height="60" width="60">
</NuxtLink>
</template>

View file

@ -68,7 +68,7 @@ async function removeList() {
actionError.value = undefined
await nextTick()
if (confirmDelete === 'confirm') {
if (confirmDelete.choice === 'confirm') {
await nextTick()
try {
await client.v1.lists.$select(list.value.id).remove()
@ -92,7 +92,7 @@ async function removeList() {
async function clearError() {
actionError.value = undefined
await nextTick()
if (isEditing)
if (isEditing.value)
input.value?.focus()
else
deleteBtn.value?.focus()

View file

@ -0,0 +1,45 @@
<script setup lang="ts">
const model = defineModel<number>()
const isValid = defineModel<boolean>('isValid')
const days = ref<number | ''>(0)
const hours = ref<number | ''>(1)
const minutes = ref<number | ''>(0)
watchEffect(() => {
if (days.value === '' || hours.value === '' || minutes.value === '') {
isValid.value = false
return
}
const duration
= days.value * 24 * 60 * 60
+ hours.value * 60 * 60
+ minutes.value * 60
if (duration <= 0) {
isValid.value = false
return
}
isValid.value = true
model.value = duration
})
</script>
<template>
<div flex flex-grow-0 gap-2>
<label flex items-center gap-2>
<input v-model="days" type="number" min="0" max="1999" input-base :class="!isValid ? 'input-error' : null">
{{ $t('confirm.mute_account.days', days === '' ? 0 : days) }}
</label>
<label flex items-center gap-2>
<input v-model="hours" type="number" min="0" max="24" input-base :class="!isValid ? 'input-error' : null">
{{ $t('confirm.mute_account.hours', hours === '' ? 0 : hours) }}
</label>
<label flex items-center gap-2>
<input v-model="minutes" type="number" min="0" max="59" step="5" input-base :class="!isValid ? 'input-error' : null">
{{ $t('confirm.mute_account.minute', minutes === '' ? 0 : minutes) }}
</label>
</div>
</template>

View file

@ -1,11 +1,34 @@
<script setup lang="ts">
import type { ConfirmDialogChoice, ConfirmDialogLabel } from '~/types'
import type { ConfirmDialogChoice, ConfirmDialogOptions } from '~/types'
import DurationPicker from '~/components/modal/DurationPicker.vue'
defineProps<ConfirmDialogLabel>()
const props = defineProps<ConfirmDialogOptions>()
const emit = defineEmits<{
(evt: 'choice', choice: ConfirmDialogChoice): void
}>()
const hasDuration = ref(false)
const isValidDuration = ref(true)
const duration = ref(60 * 60) // default to 1 hour
const shouldMuteNotifications = ref(true)
const isMute = computed(() => props.extraOptionType === 'mute')
function handleChoice(choice: ConfirmDialogChoice['choice']) {
const dialogChoice = {
choice,
...isMute.value && {
extraOptions: {
mute: {
duration: hasDuration.value ? duration.value : 0,
notifications: shouldMuteNotifications.value,
},
},
},
}
emit('choice', dialogChoice)
}
</script>
<template>
@ -16,11 +39,17 @@ const emit = defineEmits<{
<div v-if="description">
{{ description }}
</div>
<div v-if="isMute" flex-col flex gap-4>
<CommonCheckbox v-model="hasDuration" :label="$t('confirm.mute_account.specify_duration')" prepend-checkbox checked-icon-color="text-primary" />
<DurationPicker v-if="hasDuration" v-model="duration" v-model:is-valid="isValidDuration" />
<CommonCheckbox v-model="shouldMuteNotifications" :label="$t('confirm.mute_account.notifications')" prepend-checkbox checked-icon-color="text-primary" />
</div>
<div flex justify-end gap-2>
<button btn-text @click="emit('choice', 'cancel')">
<button btn-text @click="handleChoice('cancel')">
{{ cancel || $t('confirm.common.cancel') }}
</button>
<button btn-solid @click="emit('choice', 'confirm')">
<button btn-solid :disabled="!isValidDuration" @click="handleChoice('confirm')">
{{ confirm || $t('confirm.common.confirm') }}
</button>
</div>

View file

@ -37,7 +37,7 @@ onUnmounted(() => locked.value = false)
</script>
<template>
<div relative h-full w-full flex pt-12 w-100vh @click="onClick">
<div relative h-full w-full flex pt-12 @click="onClick">
<button
v-if="hasNext" pointer-events-auto btn-action-icon bg="black/20" :aria-label="$t('action.previous')"
hover:bg="black/40" dark:bg="white/30" dark-hover:bg="white/20" absolute top="1/2" right-1 z5

View file

@ -15,7 +15,7 @@ const emit = defineEmits<{
const modelValue = defineModel<number>({ required: true })
const slideGap = 20
const doubleTapTreshold = 250
const doubleTapThreshold = 250
const view = ref()
const slider = ref()
@ -36,6 +36,8 @@ const isPinching = ref(false)
const maxZoomOut = ref(1)
const isZoomedIn = computed(() => scale.value > 1)
const enableAutoplay = usePreferences('enableAutoplay')
function goToFocusedSlide() {
scale.value = 1
x.value = slide.value[modelValue.value].offsetLeft * scale.value
@ -147,7 +149,7 @@ function handleLastDrag(tap: boolean, swipe: Vector2, movement: Vector2, positio
let lastTapAt = 0
function handleTap([positionX, positionY]: Vector2) {
const now = Date.now()
const isDoubleTap = now - lastTapAt < doubleTapTreshold
const isDoubleTap = now - lastTapAt < doubleTapThreshold
lastTapAt = now
if (!isDoubleTap)
@ -218,7 +220,7 @@ function handleZoomDrag([deltaX, deltaY]: Vector2) {
function handleSlideDrag([movementX, movementY]: Vector2) {
goToFocusedSlide()
if (Math.abs(movementY) > Math.abs(movementX)) // vertical movement is more then horizontal
if (Math.abs(movementY) > Math.abs(movementX)) // vertical movement is more than horizontal
y.value -= movementY / scale.value
else
x.value -= movementX / scale.value
@ -264,8 +266,12 @@ const imageStyle = computed(() => ({
items-center
justify-center
>
<img
<component
:is="item.type === 'gifv' ? 'video' : 'img'"
ref="image"
:autoplay="enableAutoplay"
controls
loop
select-none
max-w-full
max-h-full
@ -273,7 +279,7 @@ const imageStyle = computed(() => ({
:draggable="false"
:src="item.url || item.previewUrl"
:alt="item.description || ''"
>
/>
</div>
</div>
</div>

View file

@ -34,7 +34,13 @@ const { busy, oauth, singleInstanceServer } = useSignIn()
<strong>{{ currentServer }}</strong>
</i18n-t>
</button>
<button v-else btn-solid text-sm px-2 py-1 text-center xl:hidden @click="openSigninDialog()">
<button
v-else
flex="~ row"
gap-x-1 items-center justify-center btn-solid text-sm px-2 py-1 xl:hidden
@click="openSigninDialog()"
>
<span aria-hidden="true" block i-ri:login-circle-line class="rtl-flip" />
{{ $t('action.sign_in') }}
</button>
</template>

View file

@ -4,6 +4,13 @@ import type { mastodon } from 'masto'
const { notification } = defineProps<{
notification: mastodon.v1.Notification
}>()
const { t } = useI18n()
// well-known emoji reactions types Elk does not support yet
const unsupportedEmojiReactionTypes = ['pleroma:emoji_reaction', 'reaction']
if (unsupportedEmojiReactionTypes.includes(notification.type))
console.warn(`[DEV] ${t('notification.missing_type')} '${notification.type}' (notification.id: ${notification.id})`)
</script>
<template>
@ -88,7 +95,8 @@ const { notification } = defineProps<{
<template v-else-if="notification.type === 'mention' || notification.type === 'poll' || notification.type === 'status'">
<StatusCard :status="notification.status!" />
</template>
<template v-else>
<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 }}'

View file

@ -25,7 +25,7 @@ function includeNotificationsForStatusCard({ type, status }: mastodon.v1.Notific
// Group by type (and status when applicable)
function groupId(item: mastodon.v1.Notification): string {
// If the update is related to an status, group notifications from the same account (boost + favorite the same status)
// If the update is related to a status, group notifications from the same account (boost + favorite the same status)
const id = item.status
? {
status: item.status?.id,
@ -171,6 +171,7 @@ const { formatNumber } = useHumanReadableNumber()
:paginator="paginator"
:preprocess="preprocess"
:stream="stream"
eventType="notification"
:virtualScroller="virtualScroller"
>
<template #updater="{ number, update }">

View file

@ -87,7 +87,9 @@ function editPollOptionDraft(event: Event, index: number) {
}
function deletePollOption(index: number) {
draft.value.params.poll!.options = draft.value.params.poll!.options.slice().splice(index, 1)
const newPollOptions = draft.value.params.poll!.options.slice()
newPollOptions.splice(index, 1)
draft.value.params.poll!.options = newPollOptions
trimPollOptions()
}
@ -138,7 +140,7 @@ const characterCount = computed(() => {
length -= fullMatch.length - (before + username).length - 1 // - 1 for the @
if (draft.value.mentions) {
// + 1 is needed as mentions always need a space seperator at the end
// + 1 is needed as mentions always need a space separator at the end
length += draft.value.mentions.map((mention) => {
const [handle] = mention.split('@')
return `@${handle}`
@ -156,6 +158,8 @@ const isExceedingCharacterLimit = computed(() => {
const postLanguageDisplay = computed(() => languagesNameList.find(i => i.code === (draft.value.params.language || preferredLanguage))?.nativeName)
const isDM = computed(() => draft.value.params.visibility === 'direct')
async function handlePaste(evt: ClipboardEvent) {
const files = evt.clipboardData?.files
if (!files || files.length === 0)
@ -275,12 +279,16 @@ onDeactivated(() => {
</ol>
</CommonErrorMessage>
<div relative flex-1 flex flex-col>
<div relative flex-1 flex flex-col min-h-30>
<EditorContent
:editor="editor"
flex max-w-full
:class="shouldExpanded ? 'min-h-30 md:max-h-[calc(100vh-200px)] sm:max-h-[calc(100vh-400px)] max-h-35 of-y-auto overscroll-contain' : ''"
:class="{
'md:max-h-[calc(100vh-200px)] sm:max-h-[calc(100vh-400px)] max-h-35 of-y-auto overscroll-contain': shouldExpanded,
'py2 px3.5 bg-dm rounded-4 me--1 ms--1 mt--1': isDM,
}"
@keydown="stopQuestionMarkPropagation"
@keydown.esc.prevent="editor?.commands.blur()"
/>
</div>

View file

@ -82,6 +82,7 @@ function activate() {
placeholder-text-secondary
@keydown.down.prevent="shift(1)"
@keydown.up.prevent="shift(-1)"
@keydown.esc.prevent="input?.blur()"
@keypress.enter="activate"
>
<button v-if="query.length" btn-action-icon text-secondary @click="query = ''; input?.focus()">

View file

@ -10,9 +10,11 @@ const props = defineProps<{
external?: true
large?: true
match?: boolean
target?: string
}>()
const router = useRouter()
const scrollOnClick = computed(() => props.to && !(props.target === '_blank' || props.external))
useCommand({
scope: 'Settings',
@ -39,11 +41,12 @@ useCommand({
:disabled="disabled"
:to="to"
:external="external"
:target="target"
exact-active-class="text-primary"
:class="disabled ? 'op25 pointer-events-none ' : match ? 'text-primary' : ''"
block w-full group focus:outline-none
:tabindex="disabled ? -1 : null"
@click="to ? $scrollToTop() : undefined"
@click="scrollOnClick ? $scrollToTop() : undefined"
>
<div
w-full flex px5 py3 md:gap2 gap4 items-center

View file

@ -16,7 +16,7 @@ const { disabled = false } = defineProps<{
:class="disabled ? 'opacity-50 cursor-not-allowed' : ''"
>
<div
w-full flex w-fit px5 py3 md:gap2 gap4 items-center
w-full flex px5 py3 md:gap2 gap4 items-center
transition-250
:class="disabled ? '' : 'group-hover:bg-active'"
group-focus-visible:ring="2 current"

View file

@ -55,7 +55,7 @@ function reply() {
<div flex-1>
<StatusActionButton
:content="$t('action.boost')"
:content="$t(status.reblogged ? 'action.boosted' : 'action.boost')"
:text="!getPreferences(userSettings, 'hideBoostCount') && status.reblogsCount ? status.reblogsCount : ''"
color="text-green" hover="text-green" elk-group-hover="bg-green/10"
icon="i-ri:repeat-line"
@ -77,7 +77,7 @@ function reply() {
<div flex-1>
<StatusActionButton
:content="$t('action.favourite')"
:content="$t(status.favourited ? 'action.favourited' : 'action.favourite')"
:text="!getPreferences(userSettings, 'hideFavoriteCount') && status.favouritesCount ? status.favouritesCount : ''"
:color="useStarFavoriteIcon ? 'text-yellow' : 'text-rose'"
:hover="useStarFavoriteIcon ? 'text-yellow' : 'text-rose'"
@ -100,7 +100,7 @@ function reply() {
<div flex-none>
<StatusActionButton
:content="$t('action.bookmark')"
:content="$t(status.bookmarked ? 'action.bookmarked' : 'action.bookmark')"
:color="useStarFavoriteIcon ? 'text-rose' : 'text-yellow'"
:hover="useStarFavoriteIcon ? 'text-rose' : 'text-yellow'"
:elk-group-hover="useStarFavoriteIcon ? 'bg-rose/10' : 'bg-yellow/10' "

View file

@ -62,12 +62,13 @@ async function shareLink(status: mastodon.v1.Status) {
}
async function deleteStatus() {
if (await openConfirmDialog({
const confirmDelete = await openConfirmDialog({
title: t('confirm.delete_posts.title'),
description: t('confirm.delete_posts.description'),
confirm: t('confirm.delete_posts.confirm'),
cancel: t('confirm.delete_posts.cancel'),
}) !== 'confirm')
})
if (confirmDelete.choice !== 'confirm')
return
removeCachedStatus(status.value.id)
@ -80,12 +81,13 @@ async function deleteStatus() {
}
async function deleteAndRedraft() {
if (await openConfirmDialog({
const confirmDelete = await openConfirmDialog({
title: t('confirm.delete_posts.title'),
description: t('confirm.delete_posts.description'),
confirm: t('confirm.delete_posts.confirm'),
cancel: t('confirm.delete_posts.cancel'),
}) !== 'confirm')
})
if (confirmDelete.choice !== 'confirm')
return
if (import.meta.dev) {
@ -142,7 +144,7 @@ function showFavoritedAndBoostedBy() {
<template #popper>
<div flex="~ col">
<template v-if="getPreferences(userSettings, 'zenMode')">
<template v-if="getPreferences(userSettings, 'zenMode') && !details">
<CommonDropdownItem
:text="$t('action.reply')"
icon="i-ri:chat-1-line"

View file

@ -68,6 +68,7 @@ const video = ref<HTMLVideoElement | undefined>()
const prefersReducedMotion = usePreferredReducedMotion()
const isAudio = computed(() => attachment.type === 'audio')
const isVideo = computed(() => attachment.type === 'video')
const isGif = computed(() => attachment.type === 'gifv')
const enableAutoplay = usePreferences('enableAutoplay')
@ -164,7 +165,7 @@ watch(shouldLoadAttachment, () => {
<button
type="button"
relative
@click="!shouldLoadAttachment ? loadAttachment() : null"
@click="!shouldLoadAttachment ? loadAttachment() : openMediaPreview(attachments ? attachments : [attachment], attachments?.indexOf(attachment) || 0)"
>
<video
ref="video"
@ -248,12 +249,13 @@ watch(shouldLoadAttachment, () => {
</button>
</template>
<div
v-if="attachment.description && !getPreferences(userSettings, 'hideAltIndicatorOnPosts')" :class="isAudio ? [] : [
:class="isAudio ? [] : [
'absolute left-2',
isVideo ? 'top-2' : 'bottom-2',
]"
flex gap-col-2
>
<VDropdown :distance="6" placement="bottom-start">
<VDropdown v-if="attachment.description && !getPreferences(userSettings, 'hideAltIndicatorOnPosts')" :distance="6" placement="bottom-start">
<button
font-bold text-sm
:class="isAudio
@ -281,6 +283,14 @@ watch(shouldLoadAttachment, () => {
</div>
</template>
</VDropdown>
<div v-if="isGif && !getPreferences(userSettings, 'hideGifIndicatorOnPosts')">
<button
aria-hidden font-bold text-sm
rounded-1 bg-black:65 text-white px1.2 py0.2 pointer-events-none
>
{{ $t('status.gif') }}
</button>
</div>
</div>
</div>
</template>

View file

@ -37,7 +37,7 @@ const allowEmbeddedMedia = computed(() => status.card?.html && embeddedMediaPref
<div
space-y-3
:class="{
'pt2 pb0.5 px3.5 bg-dm rounded-4 me--1': isDM,
'py2 px3.5 bg-dm rounded-4 me--1': isDM,
'ms--3.5 mt--1 ms--1': isDM && context !== 'details',
}"
>
@ -68,7 +68,6 @@ const allowEmbeddedMedia = computed(() => status.card?.html && embeddedMediaPref
:status="status.reblog" border="~ rounded"
:actions="false"
/>
<div v-if="isDM" />
</StatusSpoiler>
</div>
</template>

View file

@ -31,7 +31,7 @@ useHydratedHead({
<template>
<div :id="`status-${status.id}`" flex flex-col gap-2 pt2 pb1 ps-3 pe-4 relative :lang="status.language ?? undefined" aria-roledescription="status-details">
<StatusActionsMore :status="status" absolute inset-ie-2 top-2 @after-edit="$emit('refetchStatus')" />
<StatusActionsMore :status="status" :details="true" absolute inset-ie-2 top-2 @after-edit="$emit('refetchStatus')" />
<NuxtLink :to="getAccountRoute(status.account)" rounded-full hover:bg-active transition-100 pe5 me-a>
<AccountHoverWrapper :account="status.account">
<AccountInfo :account="status.account" />

View file

@ -14,7 +14,8 @@ function onclick(evt: MouseEvent | KeyboardEvent) {
const path = evt.composedPath() as HTMLElement[]
const el = path.find(el => ['A', 'BUTTON', 'IMG', 'VIDEO'].includes(el.tagName?.toUpperCase()))
const text = window.getSelection()?.toString()
if (!el && !text)
const isCustomEmoji = el?.parentElement?.classList.contains('custom-emoji')
if ((!el && !text) || isCustomEmoji)
go(evt)
}

View file

@ -1,6 +1,6 @@
<script setup lang="ts">
const paginator = useMastoClient().v1.timelines.public.list({ limit: 30, local: true })
const stream = useStreaming(client => client.direct.subscribe())
const stream = useStreaming(client => client.public.local.subscribe())
</script>
<template>

View file

@ -72,7 +72,7 @@ function onEnter(e: KeyboardEvent) {
}
function escapeAutocomplete(evt: KeyboardEvent) {
if (!autocompleteShow)
if (!autocompleteShow.value)
return
autocompleteShow.value = false
evt.stopPropagation()

View file

@ -3,8 +3,10 @@ import type { BuildInfo } from '~~/types'
export interface Team {
github: string
display: string
twitter: string
twitter?: string
mastodon: string
link: string
sponsors?: string
}
export const elkTeamMembers: Team[] = [
@ -13,24 +15,43 @@ export const elkTeamMembers: Team[] = [
display: 'Anthony Fu',
twitter: 'antfu7',
mastodon: 'antfu@webtoo.ls',
link: '/m.webtoo.ls/@antfu',
},
{
github: 'patak-dev',
display: 'Patak',
twitter: 'patak_dev',
mastodon: 'patak@webtoo.ls',
link: '/m.webtoo.ls/@patak',
},
{
github: 'danielroe',
display: 'Daniel Roe',
twitter: 'danielcroe',
mastodon: 'daniel@roe.dev',
link: '/mastodon.roe.dev/@daniel',
},
{
github: 'sxzz',
display: '三咲智子 Kevin Deng',
twitter: 'sanxiaozhizi',
mastodon: 'sxzz@webtoo.ls',
link: '/m.webtoo.ls/@sxzz',
},
{
github: 'userquin',
display: 'Joaquín Sánchez',
twitter: 'userquin',
mastodon: 'userquin@webtoo.ls',
link: '/m.webtoo.ls/@userquin',
sponsors: 'elk-zone', // sponsors/userquin isn't enabled
},
{
github: 'shuuji3',
display: 'TAKAHASHI Shuuji',
mastodon: 'shuuji3@webtoo.ls',
link: '/m.webtoo.ls/@shuuji3',
sponsors: 'elk-zone', // sponsors/shuuji3 isn't enabled
},
].sort(() => Math.random() - 0.5)

View file

@ -245,24 +245,12 @@ export function useCommands(cmds: () => CommandProvider[]) {
export function provideGlobalCommands() {
const { locale, t } = useI18n()
const { locales } = useI18n() as { locales: ComputedRef<LocaleObject[]> }
const router = useRouter()
const users = useUsers()
const masto = useMasto()
const colorMode = useColorMode()
const userSettings = useUserSettings()
const { singleInstanceServer, oauth } = useSignIn()
useCommand({
scope: 'Navigation',
name: () => t('nav.settings'),
icon: 'i-ri:settings-3-line',
onActivate() {
router.push('/settings')
},
})
useCommand({
scope: 'Preferences',

View file

@ -623,7 +623,7 @@ function transformCollapseMentions(status?: mastodon.v1.Status, inReplyToStatus?
// We have a special case for single mentions that are part of a reply.
// We already have the replying to badge in this case or the status is connected to the previous one.
// This is needed because the status doesn't included the in Reply to handle, only the account id.
// This is needed because the status doesn't include the in Reply to handle, only the account id.
// But this covers the majority of cases.
const showMentions = !(contextualMentionsCount === 0 || (mentionsCount === 1 && status?.inReplyToAccountId))
const grouped = contextualMentionsCount > 2

View file

@ -1,9 +1,9 @@
import type { mastodon } from 'masto'
import type { ConfirmDialogChoice, ConfirmDialogLabel, Draft, ErrorDialogData } from '~/types'
import type { ConfirmDialogChoice, ConfirmDialogOptions, Draft, ErrorDialogData } from '~/types'
import { STORAGE_KEY_FIRST_VISIT } from '~/constants'
export const confirmDialogChoice = ref<ConfirmDialogChoice>()
export const confirmDialogLabel = ref<ConfirmDialogLabel>()
export const confirmDialogLabel = ref<ConfirmDialogOptions>()
export const errorDialogData = ref<ErrorDialogData>()
export const mediaPreviewList = ref<mastodon.v1.MediaAttachment[]>([])
@ -39,7 +39,7 @@ export function openSigninDialog() {
isSigninDialogOpen.value = true
}
export async function openConfirmDialog(label: ConfirmDialogLabel | string): Promise<ConfirmDialogChoice> {
export async function openConfirmDialog(label: ConfirmDialogOptions | string): Promise<ConfirmDialogChoice> {
confirmDialogLabel.value = typeof label === 'string' ? { title: label } : label
confirmDialogChoice.value = undefined
isConfirmDialogOpen.value = true

View file

@ -77,3 +77,32 @@ export function useTimeAgoOptions(short = false): UseTimeAgoOptions<false> {
},
}
}
export function useFileSizeFormatter() {
const { locale } = useI18n()
const formatters = computed(() => ([
Intl.NumberFormat(locale.value, {
style: 'unit',
unit: 'megabyte',
unitDisplay: 'narrow',
maximumFractionDigits: 0,
}),
Intl.NumberFormat(locale.value, {
style: 'unit',
unit: 'kilobyte',
unitDisplay: 'narrow',
maximumFractionDigits: 0,
}),
]))
const megaByte = 1024 * 1024
function formatFileSize(size: number) {
return size >= megaByte
? formatters.value[0].format(size / megaByte)
: formatters.value[1].format(size / 1024)
}
return { formatFileSize }
}

View file

@ -155,6 +155,7 @@ export type MediaAttachmentUploadError = [filename: string, message: string]
export function useUploadMediaAttachment(draft: Ref<Draft>) {
const { client } = useMasto()
const { t } = useI18n()
const { formatFileSize } = useFileSizeFormatter()
const isUploading = ref<boolean>(false)
const isExceedingAttachmentLimit = ref<boolean>(false)
@ -224,8 +225,32 @@ export function useUploadMediaAttachment(draft: Ref<Draft>) {
// TODO: display some kind of message if too many media are selected
// DONE
const limit = currentInstance.value!.configuration?.statuses.maxMediaAttachments || 4
const maxVideoSize = currentInstance.value!.configuration?.mediaAttachments.videoSizeLimit || 0
const maxImageSize = currentInstance.value!.configuration?.mediaAttachments.imageSizeLimit || 0
for (const file of files.slice(0, limit)) {
if (draft.value.attachments.length < limit) {
if (file.type.startsWith('image/')) {
if (maxImageSize > 0 && file.size > maxImageSize) {
failedAttachments.value = [...failedAttachments.value, [file.name, t('state.attachments_limit_image_error', [formatFileSize(maxImageSize)])]]
continue
}
}
else {
if (maxVideoSize > 0 && file.size > maxVideoSize) {
const key
= file.type.startsWith('audio/')
? 'state.attachments_limit_audio_error'
: file.type.startsWith('video/')
? 'state.attachments_limit_video_error'
: 'state.attachments_limit_unknown_error'
const errorMessage = t(key, [formatFileSize(maxVideoSize)])
failedAttachments.value = [
...failedAttachments.value,
[file.name, errorMessage],
]
continue
}
}
isExceedingAttachmentLimit.value = false
try {
const attachment = await client.value.v1.media.create({

View file

@ -11,9 +11,12 @@ let timeoutHandle: NodeJS.Timeout | undefined
export function useRelationship(account: mastodon.v1.Account): Ref<mastodon.v1.Relationship | undefined> {
if (!currentUser.value)
return ref()
let relationship = requestedRelationships.get(account.id)
if (relationship)
return relationship
// allow batch relationship requests
relationship = ref<mastodon.v1.Relationship | undefined>()
requestedRelationships.set(account.id, relationship)
if (timeoutHandle)
@ -22,14 +25,19 @@ export function useRelationship(account: mastodon.v1.Account): Ref<mastodon.v1.R
timeoutHandle = undefined
fetchRelationships()
}, 100)
return relationship
}
async function fetchRelationships() {
const requested = Array.from(requestedRelationships.entries()).filter(([, r]) => !r.value)
const relationships = await useMastoClient().v1.accounts.relationships.fetch({ id: requested.map(([id]) => id) })
for (let i = 0; i < requested.length; i++)
requested[i][1].value = relationships[i]
for (const relationship of relationships) {
const requestedToUpdate = requested.find(([id]) => id === relationship.id)
if (!requestedToUpdate)
continue
requestedToUpdate[1].value = relationship
}
}
export async function toggleFollowAccount(relationship: mastodon.v1.Relationship, account: mastodon.v1.Account) {
@ -39,12 +47,13 @@ export async function toggleFollowAccount(relationship: mastodon.v1.Relationship
const unfollow = relationship!.following || relationship!.requested
if (unfollow) {
if (await openConfirmDialog({
const confirmUnfollow = await openConfirmDialog({
title: i18n.t('confirm.unfollow.title'),
description: i18n.t('confirm.unfollow.description', [`@${account.acct}`]),
confirm: i18n.t('confirm.unfollow.confirm'),
cancel: i18n.t('confirm.unfollow.cancel'),
}) !== 'confirm')
})
if (confirmUnfollow.choice !== 'confirm')
return
}
@ -66,18 +75,28 @@ export async function toggleMuteAccount(relationship: mastodon.v1.Relationship,
const { client } = useMasto()
const i18n = useNuxtApp().$i18n
if (!relationship!.muting && await openConfirmDialog({
title: i18n.t('confirm.mute_account.title'),
description: i18n.t('confirm.mute_account.description', [account.acct]),
confirm: i18n.t('confirm.mute_account.confirm'),
cancel: i18n.t('confirm.mute_account.cancel'),
}) !== 'confirm')
return
let duration = 0 // default 0 == indefinite
let notifications = true // default true = mute notifications
if (!relationship!.muting) {
const confirmMute = await openConfirmDialog({
title: i18n.t('confirm.mute_account.title'),
description: i18n.t('confirm.mute_account.description', [account.acct]),
confirm: i18n.t('confirm.mute_account.confirm'),
cancel: i18n.t('confirm.mute_account.cancel'),
extraOptionType: 'mute',
})
if (confirmMute.choice !== 'confirm')
return
duration = confirmMute.extraOptions!.mute.duration
notifications = confirmMute.extraOptions!.mute.notifications
}
relationship!.muting = !relationship!.muting
relationship = relationship!.muting
? await client.value.v1.accounts.$select(account.id).mute({
// TODO support more options
duration,
notifications,
})
: await client.value.v1.accounts.$select(account.id).unmute()
}
@ -86,13 +105,16 @@ export async function toggleBlockAccount(relationship: mastodon.v1.Relationship,
const { client } = useMasto()
const i18n = useNuxtApp().$i18n
if (!relationship!.blocking && await openConfirmDialog({
title: i18n.t('confirm.block_account.title'),
description: i18n.t('confirm.block_account.description', [account.acct]),
confirm: i18n.t('confirm.block_account.confirm'),
cancel: i18n.t('confirm.block_account.cancel'),
}) !== 'confirm')
return
if (!relationship!.blocking) {
const confirmBlock = await openConfirmDialog({
title: i18n.t('confirm.block_account.title'),
description: i18n.t('confirm.block_account.description', [account.acct]),
confirm: i18n.t('confirm.block_account.confirm'),
cancel: i18n.t('confirm.block_account.cancel'),
})
if (confirmBlock.choice !== 'confirm')
return
}
relationship!.blocking = !relationship!.blocking
relationship = await client.value.v1.accounts.$select(account.id)[relationship!.blocking ? 'block' : 'unblock']()
@ -102,13 +124,16 @@ export async function toggleBlockDomain(relationship: mastodon.v1.Relationship,
const { client } = useMasto()
const i18n = useNuxtApp().$i18n
if (!relationship!.domainBlocking && await openConfirmDialog({
title: i18n.t('confirm.block_domain.title'),
description: i18n.t('confirm.block_domain.description', [getServerName(account)]),
confirm: i18n.t('confirm.block_domain.confirm'),
cancel: i18n.t('confirm.block_domain.cancel'),
}) !== 'confirm')
return
if (!relationship!.domainBlocking) {
const confirmDomainBlock = await openConfirmDialog({
title: i18n.t('confirm.block_domain.title'),
description: i18n.t('confirm.block_domain.description', [getServerName(account)]),
confirm: i18n.t('confirm.block_domain.confirm'),
cancel: i18n.t('confirm.block_domain.cancel'),
})
if (confirmDomainBlock.choice !== 'confirm')
return
}
relationship!.domainBlocking = !relationship!.domainBlocking
await client.value.v1.domainBlocks[relationship!.domainBlocking ? 'create' : 'remove']({ domain: getServerName(account) })

View file

@ -59,11 +59,11 @@ export function useSearch(query: MaybeRefOrGetter<string>, options: UseSearchOpt
}
watch(() => resolveUnref(query), () => {
loading.value = !!(q && isHydrated.value)
loading.value = !!(q.value && isHydrated.value)
})
debouncedWatch(() => resolveUnref(query), async () => {
if (!q || !isHydrated.value)
if (!q.value || !isHydrated.value)
return
loading.value = true
@ -87,7 +87,7 @@ export function useSearch(query: MaybeRefOrGetter<string>, options: UseSearchOpt
}, { debounce: 300 })
const next = async () => {
if (!q || !isHydrated.value || !paginator)
if (!q.value || !isHydrated.value || !paginator)
return
loading.value = true

View file

@ -5,6 +5,7 @@ import type { PaginatorState } from '~/types'
export function usePaginator<T, P, U = T>(
_paginator: mastodon.Paginator<T[], P>,
stream: Ref<mastodon.streaming.Subscription | undefined>,
eventType: 'update' | 'notification' = 'update',
preprocess: (items: (T | U)[]) => U[] = items => items as unknown as U[],
buffer = 10,
) {
@ -34,10 +35,10 @@ export function usePaginator<T, P, U = T>(
return
for await (const entry of stream) {
if (entry.event === 'update') {
if (entry.event === eventType) {
const status = entry.payload
if ('uri' in entry)
if ('uri' in status)
cacheStatus(status, undefined, true)
const index = prevItems.value.findIndex((i: any) => i.id === status.id)

View file

@ -64,7 +64,7 @@ export function usePushManager() {
policy?: mastodon.v1.WebPushSubscriptionPolicy,
force?: boolean,
): Promise<SubscriptionResult> => {
if (!isSupported)
if (!isSupported.value)
return 'not-supported'
if (!currentUser.value)
@ -112,7 +112,7 @@ export function usePushManager() {
}
const unsubscribe = async () => {
if (!isSupported || !isSubscribed || !currentUser.value)
if (!isSupported.value || !isSubscribed.value || !currentUser.value)
return false
await removePushNotifications(currentUser.value)

View file

@ -9,6 +9,7 @@ export type ColorMode = 'light' | 'dark' | 'system'
export interface PreferencesSettings {
hideAltIndicatorOnPosts: boolean
hideGifIndicatorOnPosts: boolean
hideBoostCount: boolean
hideReplyCount: boolean
hideFavoriteCount: boolean
@ -64,6 +65,7 @@ export function getDefaultLanguage(languages: string[]) {
export const DEFAULT__PREFERENCES_SETTINGS: PreferencesSettings = {
hideAltIndicatorOnPosts: false,
hideGifIndicatorOnPosts: false,
hideBoostCount: false,
hideReplyCount: false,
hideFavoriteCount: false,

View file

@ -63,6 +63,9 @@ export function useTiptap(options: UseTiptapOptions) {
Mention
.extend({ name: 'hashtag' })
.configure({
renderHTML({ options, node }) {
return ['span', { 'data-type': 'hashtag', 'data-id': node.attrs.id }, `${options.suggestion.char}${node.attrs.label ?? node.attrs.id}`]
},
suggestion: TiptapHashtagSuggestion,
}),
Mention

View file

@ -44,7 +44,7 @@ When you are ready to submit work back to the main Elk repo, create a PR.
- base branch should be **main**
- Head repository should be your fork
- Compare branch should be your working branch you want to submit
If you don't see four drop downs, be sure you are comparing across forks.
If you don't see four drop-downs, be sure you are comparing across forks.
10. Add a description of the changes your request makes
11. Select **Add Pull Request**
@ -65,7 +65,7 @@ Avoid screenshots until Elk reaches a stable release.
### Standards
Write in **American English** using spelling as found in [Merriam Webster](https://www.merriam-webster.com).
Write in **American English** using spelling as found in [Merriam-Webster](https://www.merriam-webster.com).
Translation and localization will be handled separately as/when availability or necessity allow.
Use [**semantic linefeeds**](https://rhodesmill.org/brandon/2012/one-sentence-per-line/) with no more than one sentence per line.

View file

@ -1,6 +1,6 @@
<script>
export default {
name: 'ToogleIcon',
name: 'ToggleIcon',
props: { up: Boolean },
}
</script>

View file

@ -116,7 +116,7 @@ async function copyToClipboard() {
>
<td :class="[{ expandable: !isSource }]">
<div>
<ToogleIcon v-if="!isSource" :up="hidden || key !== locale" />
<ToggleIcon v-if="!isSource" :up="hidden || key !== locale" />
{{ title }}
</div>
</td>

View file

@ -56,6 +56,6 @@ On your project page open the Deploys tab, click on "Trigger deploy" and "Deploy
## Use a custom domain
If you want to use a custom domain, go to "Domain settings" on your Netlify project page, and press "Add custom domain". If your domain is not bought from Netlify, it will ask you to add a CNAME record. Do that.
Once the custom domain is added, you'll need to add an SSL/TLS certificate. At the bottom of the page press "Verify DNS configuration" and if it succeeds, press "Provision certificate". If that fails, you may need to wait some time until your DNS propagetes.
Once the custom domain is added, you'll need to add an SSL/TLS certificate. At the bottom of the page press "Verify DNS configuration" and if it succeeds, press "Provision certificate". If that fails, you may need to wait some time until your DNS propagates.
And that's it! Enjoy your instance's Elk!

View file

@ -1,3 +1,8 @@
export default defineNuxtConfig({
extends: '@nuxt-themes/docus',
vite: {
optimizeDeps: {
include: ['scule'],
},
},
})

View file

@ -13,6 +13,6 @@
},
"devDependencies": {
"@nuxt-themes/docus": "^1.15.0",
"nuxt": "^3.10.3"
"nuxt": "^3.11.2"
}
}

View file

@ -149,7 +149,12 @@
"mute_account": {
"cancel": "Cancel",
"confirm": "Mute",
"days": "days|day|days",
"description": "Are you sure you want to mute {0}?",
"hours": "hours|hour|hours",
"minute": "minutes|minute|minutes",
"notifications": "Mute notifications",
"specify_duration": "Specify mute duration",
"title": "Mute account"
},
"show_reblogs": {
@ -191,14 +196,14 @@
"title": "Preview deploy"
},
"desc_highlight": "Expect some bugs and missing features here and there.",
"desc_para1": "Thanks for your interest in trying out Elk, our work-in-progress Mastodon web client!",
"desc_para2": "we are working hard on the development and improving it over time.",
"desc_para1": "Elk is a nimble Mastodon web client. You can login to your Mastodon account and use it to interact with the fediverse.",
"desc_para2": "Elk is Open Source and we're actively improving it as a community project. Join us and let's build it together!",
"desc_para3": "To boost development, you can sponsor the Team through GitHub Sponsors. We hope you enjoy Elk!",
"desc_para4": "Elk is Open Source. If you'd like to help with testing, giving feedback, or contributing,",
"desc_para4": "If you'd like to report a bug, help us testing, give feedback, or contribute,",
"desc_para5": "reach out to us on GitHub",
"desc_para6": "and get involved.",
"footer_team": "The Elk Team",
"title": "Elk is in Preview!"
"title": "Welcome to Elk!"
},
"language": {
"search": "Search"
@ -301,6 +306,7 @@
"built_at": "Built {0}",
"compose": "Compose",
"conversations": "Conversations",
"docs": "Documentation",
"explore": "Explore",
"favourites": "Favorites",
"federated": "Federated",
@ -454,6 +460,7 @@
},
"language": {
"display_language": "Display Language",
"how_to_contribute": "How to contribute?",
"label": "Language",
"post_language": "Posting Language",
"status": "Translation status: {0}/{1} ({2}%)",
@ -535,6 +542,7 @@
"hide_boost_count": "Hide boost count",
"hide_favorite_count": "Hide favorite count",
"hide_follower_count": "Hide following/follower count",
"hide_gif_indi_on_posts": "Hide gif indicator on posts",
"hide_news": "Hide news",
"hide_reply_count": "Hide reply count",
"hide_tag_hover_card": "Hide tag hover card",
@ -586,7 +594,11 @@
},
"state": {
"attachments_exceed_server_limit": "The number of attachments exceeded the limit per post.",
"attachments_limit_audio_error": "Maximum audio size exceeded: {0}",
"attachments_limit_error": "Limit per post exceeded",
"attachments_limit_image_error": "Maximum image size exceeded: {0}",
"attachments_limit_unknown_error": "Maximum file size exceeded: {0}",
"attachments_limit_video_error": "Maximum video size exceeded: {0}",
"edited": "(Edited)",
"editing": "Editing",
"loading": "Loading...",
@ -607,6 +619,7 @@
"favourited_by": "Favorited By",
"filter_hidden_phrase": "Filtered by",
"filter_show_anyway": "Show anyway",
"gif": "GIF",
"img_alt": {
"ALT": "ALT",
"desc": "Description",

View file

@ -184,6 +184,9 @@
"label": "Usuarios en línea"
}
},
"state": {
"attachments_limit_video_error": "Tamaño máximo de video excedido: {0}"
},
"status": {
"spoiler_show_less": "Menos"
},

View file

@ -149,7 +149,12 @@
"mute_account": {
"cancel": "Cancelar",
"confirm": "Silenciar",
"days": "días|día|días",
"description": "¿Estás seguro que quieres silenciar a {0}?",
"hours": "horas|hora|horas",
"minute": "minutos|minuto|minutos",
"notifications": "Silenciar notificaciones",
"specify_duration": "Especificar la duración del silenciado",
"title": "Silenciar cuenta"
},
"show_reblogs": {
@ -301,6 +306,7 @@
"built_at": "Compilado {0}",
"compose": "Redactar",
"conversations": "Conversaciones",
"docs": "Documentación",
"explore": "Explorar",
"favourites": "Favoritas",
"federated": "Federados",
@ -454,6 +460,7 @@
},
"language": {
"display_language": "Idioma de pantalla",
"how_to_contribute": "¿Cómo contribuir?",
"label": "Idioma",
"post_language": "Idioma de publicación",
"status": "Estado traducción: {0}/{1} ({2}%)",
@ -535,6 +542,7 @@
"hide_boost_count": "Ocultar contador de retoots",
"hide_favorite_count": "Ocultar número de publicaciones favoritas",
"hide_follower_count": "Ocultar número de seguidores",
"hide_gif_indi_on_posts": "Ocultar indicador de gif en publicaciones",
"hide_news": "Ocultar noticias",
"hide_reply_count": "Ocultar número de respuestas",
"hide_tag_hover_card": "Ocultar tarjeta flotante de etiqueta",
@ -586,7 +594,11 @@
},
"state": {
"attachments_exceed_server_limit": "Número máximo de archivos adjuntos por publicación excedido.",
"attachments_limit_audio_error": "Tamaño máximo de audio excedido: {0}",
"attachments_limit_error": "Límite por publicación excedido",
"attachments_limit_image_error": "Tamaño máximo de imagen excedido: {0}",
"attachments_limit_unknown_error": "Tamaño máximo de archivo excedido: {0}",
"attachments_limit_video_error": "Tamaño máximo de vídeo excedido: {0}",
"edited": "(Editado)",
"editing": "Editando",
"loading": "Cargando...",
@ -607,6 +619,7 @@
"favourited_by": "Marcado como favorita por",
"filter_hidden_phrase": "Filtrado por",
"filter_show_anyway": "Mostrar de todas formas",
"gif": "GIF",
"img_alt": {
"ALT": "ALT",
"desc": "Descripción",
@ -703,7 +716,7 @@
"tooltip": {
"add_content_warning": "Añadir advertencia de contenido",
"add_emojis": "Agregar emojis",
"add_media": "Añadir imágenes, video o audio",
"add_media": "Añadir imágenes, vídeo o audio",
"add_publishable_content": "Publicar contenido",
"change_content_visibility": "Cambiar visibilidad de contenido",
"change_language": "Cambiar idioma",

View file

@ -149,7 +149,12 @@
"mute_account": {
"cancel": "Utzi",
"confirm": "Mututu",
"days": "egun|egun|egun",
"description": "Ziur {0} mututu nahi duzula?",
"hours": "ordu|ordu|ordu",
"minute": "minutu|minutu|minutu",
"notifications": "Mututu jakinarazpenak",
"specify_duration": "Zehaztu mututzearen iraupena",
"title": "Mututu kontua"
},
"show_reblogs": {
@ -228,16 +233,27 @@
"compose": "Idatzi",
"favourite": "Egin gogoko",
"search": "Bilatu",
"show_new_items": "Erakutsi elementu berriak",
"title": "Ekintzak"
},
"media": {
"title": "Multimedia"
},
"navigation": {
"go_to_bookmarks": "Laster-markak",
"go_to_conversations": "Elkarrizketak",
"go_to_explore": "Arakatu",
"go_to_favourites": "Gogokoak",
"go_to_federated": "Federatua",
"go_to_home": "Hasiera",
"go_to_lists": "Zerrendak",
"go_to_local": "Lokala",
"go_to_notifications": "Jakinarazpenak",
"next_status": "Hurrengo egoera",
"previous_status": "Aurreko egoera",
"go_to_profile": "Profila",
"go_to_search": "Bilatu",
"go_to_settings": "Ezarpenak",
"next_status": "Hurrengo bidalketa",
"previous_status": "Aurreko bidalketa",
"shortcut_help": "Laster-teklak",
"title": "Nabigazioa"
}
@ -293,6 +309,7 @@
"explore": "Arakatu",
"favourites": "Gogokoak",
"federated": "Federatua",
"hashtags": "Traolak",
"home": "Hasiera",
"list": "Zerrenda",
"lists": "Zerrendak",
@ -304,22 +321,22 @@
"search": "Bilaketa",
"select_feature_flags": "Aldatu ezaugarrien adierazleak (Toggle Feature Flags)",
"select_font_size": "Letra-tipoaren tamaina",
"select_language": "Hizkuntza",
"select_language": "Interfazearen hizkuntza",
"settings": "Ezarpenak",
"show_intro": "Erakutsi aurkezpena",
"toggle_theme": "Gai argia/iluna",
"zen_mode": "ZEN modua"
},
"notification": {
"favourited_post": "zure bidalketa gogoko egin du",
"favourited_post": "(e)k zure bidalketa gogoko egin du",
"followed_you": "(e)k jarraitu dizu",
"followed_you_count": "{0} pertsonak jarraitu dizute|pertsona {0}ek jarraitu dizu|{0} pertsonak jarraitu dizute",
"missing_type": "MISSING notification.type:",
"reblogged_post": "zure bidalketari bultzada eman dio",
"reblogged_post": "(e)k zure bidalketari bultzada eman dio",
"reported": "{0}(e)k {1} salatu du",
"request_to_follow": "jarraipen-eskaera bidali dizu",
"signed_up": "izena eman du",
"update_status": "bidalketa eguneratu du"
"request_to_follow": "(e)k jarraipen-eskaera bidali dizu",
"signed_up": "(e)k izena eman du",
"update_status": "(e)k bidalketa eguneratu du"
},
"placeholder": {
"content_warning": "Idatzi oharra hemen",
@ -374,7 +391,7 @@
}
},
"report": {
"additional_comments": "Ohar gehigarriak",
"additional_comments": "Iruzkin gehigarriak",
"another_server": "Salatzen ari zaren erabiltzailea beste zerbitzari batekoa da",
"anything_else": "Ba al dago jakin beharko genukeen beste ezer?",
"block_desc": "Ez duzu erabiltzaile honen bidalketarik ikusiko. Ezin izango ditu zure bidalketak ikusi edo zuri jarraitu. Blokeatu duzula jakingo du.",
@ -395,10 +412,10 @@
"limiting": "Mugatu {0}",
"mute_desc": "Ez duzu erabiltzaile honen bidalketarik ikusiko. Zure bidalketak ikusi eta zuri jarraitu diezazuke. Ez du jakingo mututu duzunik.",
"other": "Beste zerbait da",
"other_desc": "Arazoa ez da beste kategorietan sartzen",
"other_desc": "Arazoa ez dator bat beste kategoriekin",
"reporting": "{0} salatzen",
"select_many": "Hautatu bat datozen guztiak:",
"select_one": "Aukeratu hobekien datorrena:",
"select_many": "Hautatu dagozkion guztiak:",
"select_one": "Aukeratu hobekien doakiona:",
"select_posts": "Salaketa hau sostengatzen duen bidalketarik al dago?",
"select_posts_other": "Ba al dago salaketa sostengatzen duen beste bidalketarik?",
"spam": "Spama da",
@ -441,9 +458,10 @@
"theme_color": "Gaiaren kolorea"
},
"language": {
"display_language": "Hizkuntza",
"display_language": "Interfazearen hizkuntza",
"how_to_contribute": "Nola lagun dezaket?",
"label": "Hizkuntza",
"post_language": "Argitalpenaren hizkuntza",
"post_language": "Bidalketen hizkuntza",
"status": "Itzulpenaren egoera: {1} kateetatik {0} itzulita (%{2}a)",
"translations": {
"add": "Gehitu",
@ -518,13 +536,14 @@
"github_cards": "GitHub txartelak",
"github_cards_description": "GitHub-eko esteka argitaratzean, HTML txartel irisgarri bat erakusten du gizarte-grafikoaren metadatuak erabiliz, irudi sozialaren ordez.",
"grayscale_mode": "Gris modua",
"hide_account_hover_card": "Ezkutatu kontuaren geruza (Hide account hover card)",
"hide_account_hover_card": "Ezkutatu kontuen aurrebista-txartelak sagua gainetik pasatzean",
"hide_alt_indi_on_posts": "Ezkutatu ALT adierazlea bidalketetan",
"hide_boost_count": "Ezkutatu bultzaden kopurua",
"hide_favorite_count": "Ezkutatu gogokoen kopurua",
"hide_follower_count": "Ezkutatu jarraitzaile kopurua",
"hide_news": "Ezkutatu berriak",
"hide_reply_count": "Ezkutatu erantzunen kopurua",
"hide_tag_hover_card": "Ezkutatu traolen aurrebista-txartelak sagua gainetik pasatzean",
"hide_translation": "Ezkutatu itzulpenak",
"hide_username_emojis": "Ezkutatu emojiak erabiltzaile izenetan",
"hide_username_emojis_description": "Denbora-lerroetan erabiltzaile izenetako emojiak ezkutatzen ditu. Emojiak ikusgai egoten jarraituko dute euren profiletan.",
@ -537,7 +556,7 @@
"virtual_scroll": "Korritze birtuala",
"virtual_scroll_description": "Zerrenda birtual bat erabiltzen du denbora-lerroetan, item kopuru handiagoa modu eraginkorrean erakutsi ahal izateko.",
"wellbeing": "Ongizatea",
"zen_mode": "Zen modua",
"zen_mode": "ZEN modua",
"zen_mode_description": "Aldamenetako elementuak ezkutatzen ditu xagua gainean jarri arte. Denbora-lerroko elementu batzuk ere ezkutatzen ditu."
},
"profile": {
@ -585,7 +604,7 @@
},
"status": {
"account": {
"suspended_message": "Argitalpen honen egileari zigorra jarri zaio.",
"suspended_message": "Bidalketa honen egileari zigorra jarri zaio.",
"suspended_show": "Erakutsi edukia hala ere?"
},
"boosted_by": "Bultzatu dute:",

View file

@ -27,6 +27,7 @@
"follows_you": "Követ téged",
"go_to_profile": "Ugrás a profilhoz",
"joined": "Csatlakozott",
"lock": "Zárolt",
"moved_title": "jelezte, hogy az új fiók mostantól:",
"muted_users": "Némított felhasználók",
"muting": "Némított",
@ -79,7 +80,7 @@
"save": "Ment",
"save_changes": "Változások mentése",
"sign_in": "Bejelentkezés",
"sign_in_to": "Bejelentkezés: {0}",
"sign_in_to": "Bejelentkezve: {0}",
"switch_account": "Fiók váltás",
"vote": "Szavazás"
},
@ -94,6 +95,7 @@
"activate": "Aktivál",
"complete": "Befejez",
"compose_desc": "Új bejegyzés írása",
"n_people_in_the_past_n_days": "{0} ember az elmúlt {1} napban",
"select_lang": "Nyelv kiválasztása",
"sign_in_desc": "Létező fiók hozzáadása",
"switch_account": "Váltás: {0}",
@ -119,12 +121,14 @@
"block_account": {
"cancel": "Mégsem",
"confirm": "Blokkol",
"description": "Biztosan blokkolja? {0}"
"description": "Biztosan blokkolja? {0}",
"title": "Hozzáférés blokkolása"
},
"block_domain": {
"cancel": "Mégsem",
"confirm": "Blokkol",
"description": "Biztosan blokkolja? {0}"
"description": "Biztosan blokkolja? {0}",
"title": "Domain blokkolása"
},
"common": {
"cancel": "Mégsem",
@ -133,27 +137,37 @@
"delete_list": {
"cancel": "Mégsem",
"confirm": "Töröl",
"description": "Biztosan törli a listát? \"{0}\""
"description": "Biztosan törli a listát? \"{0}\"",
"title": "Lista törlése"
},
"delete_posts": {
"cancel": "Mégsem",
"confirm": "Töröl",
"description": "Biztosan törli a bejegyzést?"
"description": "Biztosan törli a bejegyzést?",
"title": "Bejegyzés törlése"
},
"mute_account": {
"cancel": "Mégsem",
"confirm": "Némít",
"description": "Biztosan némítja? {0}"
"days": "napok|nap|napok",
"description": "Biztosan némítja? {0}",
"hours": "órák|óra|órák",
"minute": "perc|perc|perc",
"notifications": "Értesítések némítása",
"specify_duration": "Határozzon meg némítási időtartamot",
"title": "Hozzáférés némítása"
},
"show_reblogs": {
"cancel": "Mégsem",
"confirm": "Mutat",
"description": "Biztosan megjeleníti a Turbót tőle? {0}"
"description": "Biztosan megjeleníti a Kiemelést tőle? {0}",
"title": "Kiemelés megjenítése"
},
"unfollow": {
"cancel": "Mégsem",
"confirm": "Követés leállítása",
"description": "Biztosan leállítja a követését?"
"description": "Biztosan leállítja a követését?",
"title": "Követés elállítása"
}
},
"conversation": {
@ -168,6 +182,7 @@
},
"error": {
"account_not_found": "Fiók {0} nem található",
"explore_list_empty": "Nincs most semmi érdekes. Térj vissza később!",
"file_size_cannot_exceed_n_mb": "A fájl mérete nem haladhatja meg a {0}MB-ot",
"sign_in_error": "Nem lehetséges a csatlakozás.",
"status_not_found": "A bejegyzés nem található",
@ -218,14 +233,25 @@
"compose": "Közzétesz",
"favourite": "Kedvenc",
"search": "Keresés",
"show_new_items": "Új elemek mutatása",
"title": "Műveletek"
},
"media": {
"title": "Média"
},
"navigation": {
"go_to_bookmarks": "Könyvjelzők",
"go_to_conversations": "Párbeszédek",
"go_to_explore": "Felfedez",
"go_to_favourites": "Kedvencek",
"go_to_federated": "Összesített",
"go_to_home": "Otthon",
"go_to_lists": "Listák",
"go_to_local": "Helyi",
"go_to_notifications": "Értesítések",
"go_to_profile": "Profil",
"go_to_search": "Keresés",
"go_to_settings": "Beállítások",
"next_status": "Következő bejegyzés",
"previous_status": "Előző bejegyzés",
"shortcut_help": "Gyors segítség",
@ -283,6 +309,7 @@
"explore": "Felfedezés",
"favourites": "Kedvencek",
"federated": "Összesített",
"hashtags": "Címkék",
"home": "Otthon",
"list": "Lista",
"lists": "Listák",
@ -314,7 +341,7 @@
"placeholder": {
"content_warning": "Írja ide figyelmeztetését",
"default_1": "Mi jár a fejedben?",
"reply_to_account": "Válasz: {0}",
"reply_to_account": "Válasz erre: {0}",
"replying": "Válaszol"
},
"polls": {
@ -515,10 +542,12 @@
"hide_follower_count": "Követők/Követések számláló elrejtése",
"hide_news": "Hírek elrejtése",
"hide_reply_count": "Visszajelzések számláló elrejtése",
"hide_tag_hover_card": "Lebegő kártya elrejtése",
"hide_translation": "Fordítás elrejtése",
"hide_username_emojis": "Felhasználói emoji elrejtése",
"hide_username_emojis_description": "Elrejti a hangulatjeleket a felhasználónevek elől az idővonalakban. A hangulatjelek továbbra is láthatók lesznek a profiljukban.",
"label": "Preferenciák",
"optimize_for_low_performance_device": "Alacsony teljesítményre optimalizálás",
"title": "Kísérleti képességek",
"use_star_favorite_icon": "Használja a csillag favikont",
"user_picker": "Felhasználók váltása",
@ -555,6 +584,11 @@
"label": "Bejelentkezett felhasználók"
}
},
"share_target": {
"description": "Az Elk konfigurálható úgy, hogy más alkalmazásokból is megoszthasson tartalmat, egyszerűen telepítse az Elket eszközére vagy számítógépére, és jelentkezzen be.",
"hint": "A tartalom megosztásához telepíteni kell az Elket, és be kell jelentkeznie.",
"title": "Oszd meg Elkkel"
},
"state": {
"attachments_exceed_server_limit": "A mellékletek száma meghaladta a bejegyzésenkénti korlátot.",
"attachments_limit_error": "Túllépte a bejegyzésenkénti korlátot",

View file

@ -121,13 +121,13 @@
"block_account": {
"cancel": "Annulla",
"confirm": "Blocca",
"description": "Confermi di voler bloccare {0}?",
"description": "Bloccare {0}?",
"title": "Blocca account"
},
"block_domain": {
"cancel": "Annulla",
"confirm": "Blocca",
"description": "Confermi di voler bloccare {0}?",
"description": "Bloccare {0}?",
"title": "Blocca dominio"
},
"common": {
@ -137,31 +137,36 @@
"delete_list": {
"cancel": "Annulla",
"confirm": "Elimina",
"description": "Confermi di voler eliminare la lista \"{0}\"?",
"description": "Eliminare la lista \"{0}\"?",
"title": "Elimina lista"
},
"delete_posts": {
"cancel": "Annulla",
"confirm": "Elimina",
"description": "Confermi di voler eliminare questo post?",
"description": "Eliminare questo post?",
"title": "Elimina post"
},
"mute_account": {
"cancel": "Annulla",
"confirm": "Silenzia",
"description": "Confermi di voler silenziare {0}?",
"days": "giorni|giorno|giorni",
"description": "Silenziare {0}?",
"hours": "ore|ora|ore",
"minute": "minuti|minuto|minuti",
"notifications": "Silenzia notifiche",
"specify_duration": "Specifica durata silenziamento",
"title": "Silenzia account"
},
"show_reblogs": {
"cancel": "Annulla",
"confirm": "Mostra",
"description": "Confermi di voler mostrare i post potenziati da {0}?",
"description": "Mostrare i post potenziati da {0}?",
"title": "Mostra potenziamenti"
},
"unfollow": {
"cancel": "Annulla",
"confirm": "Smetti di seguire",
"description": "Confermi di voler smettere di seguire?",
"description": "Smettere di seguire?",
"title": "Smetti di seguire"
}
},
@ -301,6 +306,7 @@
"built_at": "Sviluppato {0}",
"compose": "Componi",
"conversations": "Conversazioni",
"docs": "Documentazione",
"explore": "Esplora",
"favourites": "Preferiti",
"federated": "Federata",
@ -454,6 +460,7 @@
},
"language": {
"display_language": "Lingua interfaccia",
"how_to_contribute": "Come posso contribuire?",
"label": "Lingua",
"post_language": "Lingua di pubblicazione",
"status": "Stato traduzione: {0}/{1} ({2}%)",

View file

@ -149,7 +149,12 @@
"mute_account": {
"cancel": "Cancelar",
"confirm": "Silenciar",
"days": "dias|dia|dias",
"description": "Tem a certeza que pretende silenciar {0}?",
"hours": "horas|hora|horas",
"minute": "minutos|minuto|minutos",
"notifications": "Silenciar notificações",
"specify_duration": "Especificar duração do silêncio",
"title": "Silenciar conta"
},
"show_reblogs": {
@ -191,10 +196,10 @@
"title": "Produção de pré-visualização"
},
"desc_highlight": "Espere alguns problemas e funcionalidades em falta.",
"desc_para1": "Obrigado pelo seu interesse em experimentar o Elk, a nossa aplicação web para o Mastodon, ainda em construção!",
"desc_para2": "Estamos a trabalhar arduamente no seu desenvolvimento e melhoria ao longo do tempo.",
"desc_para1": "O Elk é uma ágil aplicação web para o Mastodon. Pode iniciar sessão com a sua conta Mastodon e utilizá-la para interagir com o fediverso.",
"desc_para2": "O Elk é software de código aberto e estamos a aperfeiçoá-lo ativamente como um projeto comunitário. Junte-se a nós e vamos construí-lo juntos!",
"desc_para3": "Para ajudar a impulsionar o desenvolvimento, pode patrocinar a Equipa através do GitHub Sponsors. Esperamos que aprecie o Elk!",
"desc_para4": "Elk é um software de código aberto. Se quiser ajudar a testar a aplicação, dando o seu feedback ou contributo,",
"desc_para4": "Se quiser comunicar um erro, ajudar-nos a testar, dar feedback ou contribuir,",
"desc_para5": "pode encontrar-nos no GitHub",
"desc_para6": "e participar.",
"footer_team": "A Equipa do Elk",
@ -301,6 +306,7 @@
"built_at": "Produzido {0}",
"compose": "Compor",
"conversations": "Conversas",
"docs": "Documentação",
"explore": "Explorar",
"favourites": "Favoritos",
"federated": "Federada",
@ -454,6 +460,7 @@
},
"language": {
"display_language": "Idioma de Apresentação",
"how_to_contribute": "Como contribuir?",
"label": "Idioma",
"post_language": "Idioma de Publicação",
"status": "Estado da tradução: {0}/{1} ({2}%)",
@ -535,6 +542,7 @@
"hide_boost_count": "Esconder contagem de partilhas",
"hide_favorite_count": "Esconder contagem de favoritos",
"hide_follower_count": "Esconder contagem de seguidores",
"hide_gif_indi_on_posts": "Esconder indicador gif nas publicações",
"hide_news": "Esconder notícias",
"hide_reply_count": "Esconder contagem de respostas",
"hide_tag_hover_card": "Esconder cartão flutuante de hashtag",
@ -586,7 +594,11 @@
},
"state": {
"attachments_exceed_server_limit": "O número de anexos excedeu o limite permitido por publicação.",
"attachments_limit_audio_error": "Tamanho máximo para áudio excedido: {0}",
"attachments_limit_error": "Limite permitido por publicação excedido",
"attachments_limit_image_error": "Tamanho máximo para imagem excedido: {0}",
"attachments_limit_unknown_error": "Tamanho máximo para ficheiro excedido: {0}",
"attachments_limit_video_error": "Tamanho máximo para video excedido: {0}",
"edited": "(Editado)",
"editing": "Editando",
"loading": "Carregando...",
@ -607,6 +619,7 @@
"favourited_by": "Adicionada Aos Favoritos Por",
"filter_hidden_phrase": "Filtrada por",
"filter_show_anyway": "Mostrar mesmo assim",
"gif": "GIF",
"img_alt": {
"ALT": "ALT",
"desc": "Descrição",

View file

@ -7,6 +7,8 @@
"route_loaded": "Naloload na ang pahina {0}"
},
"account": {
"authorize": "Pahintulutan na sumunod",
"authorized": "Pinahintulutan mo ang kahilingan",
"avatar_description": "Avatar ni {0}",
"blocked_by": "Ika'y na-block ng user na ito.",
"blocked_domains": "Mga naka-block na domain",
@ -25,6 +27,7 @@
"follows_you": "Sinusundan ka",
"go_to_profile": "Pumunta sa profile",
"joined": "Sumali",
"lock": "Ikandado",
"moved_title": "nagpahiwatig na ang kanilang bagong account ay:",
"muted_users": "Mga naka-mute na user",
"muting": "Naka-mute",
@ -37,36 +40,42 @@
"profile_description": "Header ng profile ni {0}",
"profile_personal_note": "Personal na Tala",
"profile_unavailable": "Hindi magamit ang profile",
"reject": "Tanggihan na sumunod",
"rejected": "Tinanggihan mo ang kahilingan",
"request_follow": "Humiling ng pagsunod",
"requested": "{0} ay humiling na sundan ka",
"unblock": "Tanggalin ang pagka-block",
"unfollow": "Huminto sa pagsunod",
"unmute": "Tanggalin ang pagka-mute",
"view_other_followers": "Ang mga tagasunod mula sa ibang mga instance ay hindi maipapakita.",
"view_other_following": "Ang mga sinusundan mula sa ibang mga instance ay hindi maipapakita."
"view_other_following": "Ang mga sinusundan mula sa ibang mga instance ay hindi maipapakita.",
"withdraw_follow_request": "Bawiin ang kahilingan na sumunod"
},
"action": {
"apply": "Mag-apply",
"bookmark": "I-bookmark",
"bookmarked": "Nai-bookmark na",
"boost": "I-boost",
"boost_count": "{0} ang nag-boost",
"boost_count": "{0} nag-boost",
"boosted": "Nai-boost na",
"clear_publish_failed": "Tanggalin ang mga error sa pag-publish",
"clear_upload_failed": "Tanggalin ang mga error sa pag-upload ng file",
"clear_publish_failed": "I-clear ang mga error sa pag-publish",
"clear_save_failed": "I-clear ang mga error sa pag-save",
"clear_upload_failed": "I-clear ang mga error sa pag-upload ng file",
"close": "Isara",
"compose": "Mag-compose",
"confirm": "Kumpirmahin",
"done": "Tapos na",
"edit": "I-edit",
"enter_app": "Tumuloy sa App",
"favourite": "I-favorite",
"favourite_count": "{0} ang nag-favorite",
"favourite_count": "{0} nag-favorite",
"favourited": "Nai-favorite na",
"more": "Iba pa",
"next": "Susunod",
"prev": "Nakaraan",
"publish": "I-publish",
"reply": "Sumagot",
"reply_count": "{0} ang sumagot",
"reply_count": "{0} sumagot",
"reset": "I-reset",
"save": "I-save",
"save_changes": "I-save ang mga pagbabago",
@ -99,6 +108,8 @@
"error": "ERROR",
"fetching": "Kumukuha...",
"in": "sa",
"no_bookmarks": "Wala pang naka-bookmark na mga post",
"no_favourites": "Wala pang ni-like na post",
"not_found": "404 Hindi Nakita",
"offline_desc": "Mukhang offline ka. Mangyaring suriin ang iyong koneksyon sa network."
},
@ -110,12 +121,14 @@
"block_account": {
"cancel": "Kanselahin",
"confirm": "I-block",
"description": "Sigurado ka bang gusto mong i-block si {0}?"
"description": "Sigurado ka bang gusto mong i-block si {0}?",
"title": "I-block ang account"
},
"block_domain": {
"cancel": "Kanselahin",
"confirm": "I-block",
"description": "Sigurado ka bang gusto mong i-block ang {0}?"
"description": "Sigurado ka bang gusto mong i-block ang {0}?",
"title": "I-block ang domain"
},
"common": {
"cancel": "Hindi",
@ -124,27 +137,37 @@
"delete_list": {
"cancel": "Kanselahin",
"confirm": "Burahin",
"description": "Sigurado ka bang gusto mong burahin ang listahan na \"{0}\"?"
"description": "Sigurado ka bang gusto mong burahin ang listahan na \"{0}\"?",
"title": "I-delete ang list"
},
"delete_posts": {
"cancel": "Kanselahin",
"confirm": "Burahin",
"description": "Sigurado ka bang gusto mong burahin ang post na ito?"
"description": "Sigurado ka bang gusto mong burahin ang post na ito?",
"title": "I-delete post"
},
"mute_account": {
"cancel": "Kanselahin",
"confirm": "I-mute",
"description": "Sigurado ka bang gusto mong i-mute si {0}?"
"days": "mga araw|araw|mga araw",
"description": "Sigurado ka bang gusto mong i-mute si {0}?",
"hours": "mga oras|oras|mga oras",
"minute": "mga minuto|minuto|mga minuto",
"notifications": "I-mute ang notifications",
"specify_duration": "Tukuyin ang tagal ng pag-mute",
"title": "I-mute ang account"
},
"show_reblogs": {
"cancel": "Kanselahin",
"confirm": "Ipakita",
"description": "Sigurado ka bang gusto mong ipakita ang mga boosts mula kay {0}?"
"description": "Sigurado ka bang gusto mong ipakita ang mga boosts mula kay {0}?",
"title": "Ipakita ang boosts"
},
"unfollow": {
"cancel": "Kanselahin",
"confirm": "Huminto sa pagsunod",
"description": "Sigurado ka bang gusto mong huminto sa pagsunod?"
"confirm": "Itigil ang pagsunod",
"description": "Sigurado ka bang gusto mong huminto sa pagsunod?",
"title": "Itigil ang pagsunod"
}
},
"conversation": {
@ -196,7 +219,7 @@
"edit_error": "Mayroong error sa pag-update ng listahan",
"error": "Mayroong error sa paglikha ng listahan",
"error_prefix": "Error: ",
"list_title_placeholder": "Pamagat ng listahan",
"list_title_placeholder": "Pangalan ng listahan",
"modify_account": "Baguhin ang mga listahan sa account",
"remove_account": "Tanggalin ang account sa listahan",
"save": "I-save ang mga pagbabago"
@ -209,24 +232,36 @@
"command_mode": "Mode ng Command",
"compose": "Mag-compose",
"favourite": "Paborito",
"search": "Hanapin",
"show_new_items": "Ipakita ang mga bagong item",
"title": "Mga aksyon"
},
"media": {
"title": "Media"
},
"navigation": {
"go_to_bookmarks": "Mga Tandang-Pahina",
"go_to_conversations": "Mga Usapang Pribado",
"go_to_explore": "Mag-Explore",
"go_to_favourites": "Mga Paborito",
"go_to_federated": "Pederal",
"go_to_home": "Tungo sa Home",
"go_to_lists": "Mga Listahan",
"go_to_local": "Lokal",
"go_to_notifications": "Tungo sa mga Abiso",
"go_to_profile": "Profile",
"go_to_search": "Hanapin",
"go_to_settings": "Mga Setting",
"next_status": "Susunod na status",
"previous_status": "Nakaraang status",
"shortcut_help": "Tulong sa shortcut",
"title": "Pag-navigate"
}
},
"sequence_then": "pagkatapos"
"sequence_then": "tapos"
},
"menu": {
"add_personal_note": "Magdagdag ng personal na note sa {0}",
"add_personal_note": "Sumulat ng personal na tala",
"block_account": "I-block si {0}",
"block_domain": "I-block ang domain ng {0}",
"copy_link_to_post": "Kopyahin ang link",
@ -236,12 +271,14 @@
"direct_message_account": "I-message ng direkta si {0}",
"edit": "I-edit",
"hide_reblogs": "Itago ang mga boost mula kay {0}",
"mention_account": "Banggitin si {0}",
"mention_account": "Tumugon kay {0}",
"mute_account": "I-mute si {0}",
"mute_conversation": "I-mute ang post na ito",
"open_in_original_site": "Buksan sa orihinal na site",
"pin_on_profile": "I-pin sa profile",
"remove_personal_note": "Tanggalin ang personal na note sa {0}",
"remove_personal_note": "Tanggalin ang personal na tala",
"report_account": "I-report si {0}",
"share_account": "I-share si {0}",
"share_post": "I-share ang post na ito",
"show_favourited_and_boosted_by": "Ipakita ang mga nag-favorite at nag-boost",
"show_reblogs": "Ipakita ang mga boost mula kay {0}",
@ -253,6 +290,7 @@
"translate_post": "I-translate ang post",
"unblock_account": "I-unblock ang {0}",
"unblock_domain": "I-unblock ang domain ng {0}",
"unfollow_account": "Unfollow {0}",
"unmute_account": "I-unmute si {0}",
"unmute_conversation": "I-unmute ang post na ito",
"unpin_on_profile": "I-unpin sa profile"
@ -265,12 +303,13 @@
"blocked_domains": "Mga Naka-Block na Domain",
"blocked_users": "Mga Naka-Block na Users",
"bookmarks": "Mga Tandang-Pahina",
"built_at": "Ginawa noong {0}",
"built_at": "Build version mula noong {0}",
"compose": "Lumikha ng Mensahe",
"conversations": "Mga Usapang Pribado",
"explore": "Mag-Explore",
"favourites": "Mga Paborito",
"federated": "Pederal",
"hashtags": "Mga Hashtags",
"home": "Tahanan",
"list": "Listahan",
"lists": "Mga Listahan",
@ -304,10 +343,26 @@
"reply_to_account": "Sagot kay {0}",
"replying": "Sumasagot"
},
"polls": {
"allow_multiple": "Payagan ang maramihang pagboto",
"cancel": "Kanselahin",
"create": "Likhain ang poll",
"disallow_multiple": "Huwag payagan ang maramihang pagboto",
"expiration": "Katapusan ng pagboto",
"hide_votes": "Itago ang bilang ng mga boto hanggang sa katapusan",
"option_placeholder": "Poll choice {current}/{max}",
"remove_option": "Remove choice",
"settings": "Poll options",
"show_votes": "Always show vote totals"
},
"pwa": {
"dismiss": "I-dismiss",
"install": "I-install",
"install_title": "I-install ang Elk",
"screenshots": {
"dark": "Screenshot of Elk running in dark mode",
"light": "Screenshot of Elk running in light mode"
},
"title": "May bagong update para sa Elk!",
"update": "I-update",
"update_available_short": "I-update ang Elk",
@ -334,6 +389,42 @@
}
}
},
"report": {
"additional_comments": "Karagdagang mga komento",
"another_server": "Ang user na iyong inire-report ay mula sa ibang server",
"anything_else": "May iba pa ba kaming kailangan malaman?",
"block_desc": "Hindi mo na makikita ang mga post mula sa user na ito. Hindi rin nila masusundan ang iyong account o makikita ang iyong mga post. Malalaman nilang naka-block sila.",
"dontlike": "Hindi ko ito gusto",
"dontlike_desc": "Hindi mo ito gustong makita",
"forward": "Oo, ipasa ang report na ito sa {0}",
"forward_question": "Gusto mo bang magpadala din ng anonymous na kopya ng report na ito sa server na iyon?",
"further_actions": {
"limit": {
"description": "Narito ang iyong mga pwedeng gawin upang ma-control iyong nakikita:",
"title": "Ayaw mong makita ito?"
},
"report": {
"description": "Habang sinusuri namin ang iyong report, narito ang mga maaari mong gawin:",
"title": "Salamat sa pag-report, titingnan namin ito"
}
},
"limiting": "Inili-limit {0}",
"mute_desc": "Hindi mo na makikita ang mga post mula sa user na ito. Maaari ka pa rin nilang sundan at makita ang iyong mga post. Hindi nila malalaman na sila ay naka-mute",
"other": "Iba ang aking dahilan",
"other_desc": "Ang isyu ay hindi umaangkop sa mga nabanggit na kategorya",
"reporting": "Pag-report si {0}",
"select_many": "Piliin ang lahat ng tugma:",
"select_one": "Piliin ang pinaka-tugma:",
"select_posts": "Mayroon bang mga post na nagba-back up sa report na ito?",
"select_posts_other": "Mayroon pa bang mga post na nagba-back up sa report na ito?",
"spam": "Ito ay spam",
"spam_desc": "May mga malicious na link, pekeng engagement, o paulit-ulit na reply",
"submit": "I-sumite ang report",
"unfollow_desc": "Hindi mo na makikita ang mga post mula sa user na ito sa iyong feed na Tahanan. Maaari ka pa ring makakita ng mga post mula sa kanila sa ibang lugar.",
"violation": "Lumalabag ito sa mga rules ng server",
"whats_wrong_account": "Sabihin sa amin kung ano ang mali sa account na ito",
"whats_wrong_post": "Sabihin sa amin kung ano ang mali sa post na ito"
},
"search": {
"search_desc": "Maghanap ng mga tao at hashtag",
"search_empty": "Walang nahanap para sa mga terminong ito"
@ -368,6 +459,7 @@
"language": {
"display_language": "Ipakita ang Wika",
"label": "Wika",
"post_language": "Posting Language",
"status": "Kalagayan ng Pagsasalin: {0}/{1} ({2}%)",
"translations": {
"add": "Magdagdag",
@ -386,7 +478,7 @@
"alerts": {
"favourite": "Mga Paborito",
"follow": "Mga Bagong Tagasunod",
"mention": "Mga Mention",
"mention": "Mga Tugon",
"poll": "Mga Poll",
"reblog": "Mga Reblog ng iyong Post",
"title": "Anong mga abiso ang nais mong matanggap?"
@ -433,25 +525,33 @@
},
"notifications_settings": "Mga Notification",
"preferences": {
"embedded_media": "Naka-Embed na Media Player",
"embedded_media_description": "Magpakita ng naka-embed na player sa halip na preview card para sa mga post na may media streaming.",
"enable_autoplay": "Paganahin ang Autoplay",
"enable_data_saving": "Paganahin ang pag-save ng data",
"enable_data_saving_description": "I-save ang data sa pamamagitan ng pagpigil sa mga attachment na auto-loading.",
"enable_pinch_to_zoom": "Paganahin ang pinch-to-zoom",
"github_cards": "Mga Card ng GitHub",
"github_cards_description": "Kapag may post na GitHub link, ipakita ang isang HTML preview card na naglalaman ng social graph meta sa halip na ang social image.",
"grayscale_mode": "Grayscale mode",
"hide_account_hover_card": "Itago ang account hover card",
"hide_alt_indi_on_posts": "Itago ang alt indicator sa mga post",
"hide_boost_count": "Itago ang boost count",
"hide_favorite_count": "Itago ang favorite count",
"hide_follower_count": "Itago ang following/follower count",
"hide_news": "Itago ang mga balita",
"hide_reply_count": "Itago ang reply count",
"hide_tag_hover_card": "Itago ang tag hover card",
"hide_translation": "Itago ang translation",
"hide_username_emojis": "Itago ang username emojis",
"hide_username_emojis_description": "Itinatago ang mga emojis mula sa mga usernames sa timelines. Makikita pa rin ang mga emojis sa kanilang mga profile.",
"label": "Mga Nais",
"optimize_for_low_performance_device": "I-optimize para sa device na mabagal",
"title": "Mga Experimental na Tampok",
"user_picker": "User Picker",
"virtual_scroll": "Virtual Scrolling",
"use_star_favorite_icon": "Gumamit ng star na icon para sa pag-paborito",
"user_picker": "Pagpipilian na mga Account",
"user_picker_description": "Ipakita ang mga avatar ng mga naka-login na account sa kaliwang ibaba para makalipat sa mga ito.",
"virtual_scroll": "Virtual na Scrolling",
"wellbeing": "Kalusugan at Kagalingan",
"zen_mode": "Modong Zen",
"zen_mode_description": "Itago ang ibang mga elemento sa timeline at mga asides maliban kung naka-focus ang mouse cursor sa kanila."
@ -495,6 +595,7 @@
"loading": "Nagloload...",
"publish_failed": "Nabigo sa pagpapaskil",
"publishing": "Nagpapaskil",
"save_failed": "Nabigo ang pag-save",
"upload_failed": "Nabigo sa pag-upload",
"uploading": "Naguuupload..."
},
@ -503,8 +604,9 @@
"suspended_message": "Ang account ng status na ito ay nakasuspinde.",
"suspended_show": "Ipakita pa rin ang nilalaman?"
},
"boosted_by": "Binuhay muli ni",
"boosted_by": "Ini-boost ni",
"edited": "Naedit {0}",
"embedded_warning": "Ang pag-play nito ay maaaring magbunyag ng iyong IP address sa iba.",
"favourited_by": "Pumaborito si",
"filter_hidden_phrase": "Nakafilter dahil sa",
"filter_show_anyway": "Ipakita pa rin",
@ -539,8 +641,20 @@
"list": "Listahan",
"media": "Media",
"news": "Balita",
"notifications_admin": {
"report": "Mga Report",
"sign_up": "Mga Sign-Up"
},
"notifications_all": "Lahat",
"notifications_mention": "Mention",
"notifications_favourite": "Mga Paborito",
"notifications_follow": "Mga Pagsunod",
"notifications_follow_request": "Mga Hiling ng Pagsunod",
"notifications_mention": "Mga Tugon",
"notifications_more_tooltip": "I-filter ang mga notification ayon sa uri",
"notifications_poll": "Mga Poll",
"notifications_reblog": "Mga Boost",
"notifications_status": "Mga Sinusundang Status",
"notifications_update": "Mga Update",
"posts": "Mga Post",
"posts_with_replies": "Mga Post at Mga Tugon"
},

View file

@ -95,7 +95,7 @@
"activate": "Kích hoạt",
"complete": "Hoàn thành",
"compose_desc": "Soạn tút mới",
"n_people_in_the_past_n_days": "{0} người nhắc đến trong {1} ngày gần đây",
"n_people_in_the_past_n_days": "{0} người dùng trong {1} ngày qua",
"select_lang": "Chọn ngôn ngữ",
"sign_in_desc": "Thêm một tài khoản khác",
"switch_account": "Chuyển sang {0}",
@ -149,7 +149,12 @@
"mute_account": {
"cancel": "Hủy bỏ",
"confirm": "Ẩn",
"days": "ngày|ngày|ngày",
"description": "Bạn có chắc muốn ẩn {0}?",
"hours": "giờ|giờ|giờ",
"minute": "phút|phút|phút",
"notifications": "Ẩn thông báo",
"specify_duration": "Thời hạn ẩn cụ thể",
"title": "Ẩn người"
},
"show_reblogs": {
@ -228,14 +233,25 @@
"compose": "Soạn",
"favourite": "Thích",
"search": "Tìm kiếm",
"show_new_items": "Hiện những tút mới",
"title": "Hành động"
},
"media": {
"title": "Media"
},
"navigation": {
"go_to_bookmarks": "Tút đã lưu",
"go_to_conversations": "Nhắn riêng",
"go_to_explore": "Khám phá",
"go_to_favourites": "Lượt thích",
"go_to_federated": "Liên hợp",
"go_to_home": "Trang chủ",
"go_to_lists": "Danh sách",
"go_to_local": "Máy chủ",
"go_to_notifications": "Thông báo",
"go_to_profile": "Hồ sơ",
"go_to_search": "Tìm kiếm",
"go_to_settings": "Cài đặt",
"next_status": "Tút tiếp theo",
"previous_status": "Tút trước đó",
"shortcut_help": "Trợ giúp phím tắt",
@ -264,7 +280,7 @@
"report_account": "Báo cáo {0}",
"share_account": "Chia sẻ {0}",
"share_post": "Chia sẻ tút",
"show_favourited_and_boosted_by": "Xem lượt thích đăng lại",
"show_favourited_and_boosted_by": "Xem lượt thích & đăng lại",
"show_reblogs": "Xem đăng lại từ {0}",
"show_untranslated": "Xem bản chưa dịch",
"toggle_theme": {
@ -293,6 +309,7 @@
"explore": "Khám phá",
"favourites": "Lượt thích",
"federated": "Liên hợp",
"hashtags": "Hashtag",
"home": "Trang chủ",
"list": "Danh sách",
"lists": "Danh sách",
@ -525,6 +542,7 @@
"hide_follower_count": "Ẩn số lượt người theo dõi/đang theo dõi",
"hide_news": "Ẩn tin tức",
"hide_reply_count": "Ẩn số lượt trả lời",
"hide_tag_hover_card": "Ẩn xem trước hashtag",
"hide_translation": "Ẩn chức năng dịch",
"hide_username_emojis": "Ẩn emoji trong tên người dùng",
"hide_username_emojis_description": "Ẩn emoji khỏi tên người dùng, emoji vẫn sẽ hiển thị trong mô tả của họ.",

View file

@ -162,7 +162,7 @@ export default defineNuxtConfig({
// our default translation server #76
translateApi: '',
// Use the instance where Elk has its Mastodon account as the default
defaultServer: 'm.webtoo.ls',
defaultServer: 'fedi.femby.page',
singleInstance: false,
},
storage: {
@ -197,17 +197,17 @@ export default defineNuxtConfig({
},
publicAssets: [
{
dir: '~/public/avatars',
dir: resolve('./public/avatars'),
maxAge: 24 * 60 * 60 * 30, // 30 days
baseURL: '/avatars',
},
{
dir: '~/public/emojis',
dir: resolve('./public/emojis'),
maxAge: 24 * 60 * 60 * 15, // 15 days, matching service worker
baseURL: '/emojis',
},
{
dir: '~/public/fonts',
dir: resolve('./public/fonts'),
maxAge: 24 * 60 * 60 * 365, // 1 year (versioned)
baseURL: '/fonts',
},

View file

@ -1,8 +1,8 @@
{
"name": "@elk-zone/elk",
"type": "module",
"version": "0.12.1",
"packageManager": "pnpm@8.15.3",
"version": "0.13.2",
"packageManager": "pnpm@8.15.5",
"license": "MIT",
"homepage": "https://elk.zone/",
"main": "./nuxt.config.ts",
@ -38,9 +38,9 @@
"@iconify/json": "^2.2.170",
"@iconify/utils": "^2.1.22",
"@nuxt/devtools": "^1.0.8",
"@nuxt/test-utils": "^3.11.0",
"@nuxt/test-utils": "^3.12.0",
"@nuxtjs/color-mode": "^3.3.2",
"@nuxtjs/i18n": "^8.1.1",
"@nuxtjs/i18n": "^8.2.0",
"@pinia/nuxt": "^0.5.1",
"@tiptap/core": "2.2.4",
"@tiptap/extension-bold": "2.2.4",
@ -56,11 +56,11 @@
"@tiptap/starter-kit": "2.2.4",
"@tiptap/suggestion": "2.2.4",
"@tiptap/vue-3": "2.2.4",
"@unocss/nuxt": "^0.58.5",
"@unocss/nuxt": "^0.58.9",
"@upstash/redis": "^1.27.1",
"@vercel/kv": "^1.0.1",
"@vue-macros/nuxt": "^1.6.0",
"@vueuse/core": "^10.8.0",
"@vueuse/core": "^10.9.0",
"@vueuse/gesture": "^2.0.0",
"@vueuse/integrations": "^10.8.0",
"@vueuse/math": "^10.8.0",
@ -82,7 +82,7 @@
"iso-639-1": "^3.0.0",
"js-yaml": "^4.1.0",
"lru-cache": "^10.0.0",
"masto": "^6.5.2",
"masto": "^6.7.0",
"node-emoji": "^2.1.3",
"nuxt-security": "^0.13.1",
"page-lifecycle": "^0.1.2",
@ -94,14 +94,14 @@
"simple-git": "^3.19.1",
"slimeform": "^0.9.1",
"stale-dep": "^0.7.0",
"std-env": "^3.3.3",
"std-env": "^3.7.0",
"string-length": "^5.0.1",
"tauri-plugin-log-api": "github:tauri-apps/tauri-plugin-log",
"tauri-plugin-store-api": "github:tauri-apps/tauri-plugin-store",
"theme-vitesse": "^0.7.2",
"tiny-decode": "^0.1.3",
"tippy.js": "^6.3.7",
"ufo": "^1.4.0",
"ufo": "^1.5.3",
"ultrahtml": "^1.5.3",
"unimport": "^3.7.1",
"vite-plugin-pwa": "^0.19.2",
@ -112,48 +112,47 @@
"ws": "^8.15.1"
},
"devDependencies": {
"@antfu/eslint-config": "^2.8.0",
"@antfu/eslint-config": "^2.9.0",
"@antfu/ni": "^0.21.12",
"@types/chroma-js": "^2.4.4",
"@types/file-saver": "^2.0.7",
"@types/flat": "^5.0.5",
"@types/fnando__sparkline": "^0.3.7",
"@types/fs-extra": "^11.0.4",
"@types/js-yaml": "^4.0.9",
"@types/prettier": "^2.7.3",
"@types/wicg-file-system-access": "^2020.9.8",
"@types/prettier": "^3.0.0",
"@types/wicg-file-system-access": "^2023.10.5",
"@types/ws": "^8.5.10",
"@unlazy/nuxt": "^0.11.1",
"@unocss/eslint-config": "^0.58.5",
"@vue/test-utils": "^2.4.4",
"@unlazy/nuxt": "^0.11.2",
"@unocss/eslint-config": "^0.58.9",
"@vue/test-utils": "2.4.5",
"bumpp": "^9.4.0",
"consola": "^3.2.3",
"eslint": "^8.57.0",
"eslint-plugin-format": "^0.1.0",
"flat": "^5.0.2",
"flat": "^6.0.1",
"fs-extra": "^11.2.0",
"lint-staged": "^14.0.1",
"nuxt": "^3.10.3",
"prettier": "^3.0.3",
"sharp": "^0.33.2",
"lint-staged": "^15.2.2",
"nuxt": "^3.11.2",
"prettier": "^3.2.5",
"sharp": "^0.33.3",
"sharp-ico": "^0.1.5",
"simple-git-hooks": "^2.10.0",
"tsx": "^4.7.1",
"typescript": "^5.3.3",
"vitest": "1.3.1",
"vue-tsc": "^1.8.27"
"simple-git-hooks": "^2.11.1",
"tsx": "^4.7.2",
"typescript": "^5.4.4",
"vitest": "1.4.0",
"vue-tsc": "^2.0.10"
},
"pnpm": {
"overrides": {
"unstorage": "^1.10.1"
"unstorage": "^1.10.2"
},
"patchedDependencies": {
"nuxt-security@0.13.1": "patches/nuxt-security@0.13.1.patch"
}
},
"resolutions": {
"vitest": "1.3.1",
"vue": "^3.4.19"
"vitest": "1.4.0",
"vue": "^3.4.21"
},
"simple-git-hooks": {
"pre-commit": "pnpm lint-staged"

View file

@ -21,7 +21,7 @@ const { data: status, pending, refresh: refreshStatus } = useAsyncData(
)
const { client } = useMasto()
const { data: context, pending: pendingContext, refresh: refreshContext } = useAsyncData(
`context:${id}`,
`context:${id.value}`,
async () => client.value.v1.statuses.$select(id.value).context.fetch(),
{ watch: [isHydrated], immediate: isHydrated.value, lazy: true, default: () => shallowRef() },
)

View file

@ -1,18 +1,25 @@
<script setup lang="ts">
const keys = useMagicKeys()
const { t } = useI18n()
useHydratedHead({
title: () => t('nav.search'),
})
const search = ref<{ input?: HTMLInputElement }>()
watchEffect(() => {
if (search.value?.input)
search.value?.input?.focus()
})
onActivated(() =>
search.value?.input?.focus(),
)
onActivated(() => search.value?.input?.focus())
onDeactivated(() => search.value?.input?.blur())
watch(keys['/'], (v) => {
// focus on input when '/' is up to avoid '/' being typed
if (!v)
search.value?.input?.focus()
})
</script>
<template>

View file

@ -32,6 +32,8 @@ const filter = computed<mastodon.v1.NotificationType | undefined>(() => {
const actualFilter = Array.isArray(rawFilter) ? rawFilter[0] : rawFilter
if (isNotificationFilter(actualFilter))
return actualFilter
return undefined
})
const filterIconMap: Record<mastodon.v1.NotificationType, string> = {

View file

@ -12,6 +12,8 @@ const filter = computed<mastodon.v1.NotificationType | undefined>(() => {
const actualFilter = Array.isArray(rawFilter) ? rawFilter[0] : rawFilter
if (isNotification(actualFilter))
return actualFilter
return undefined
})
useHydratedHead({

View file

@ -58,6 +58,13 @@ function handleShowCommit() {
@click="openPreviewHelp"
/>
<SettingsItem
:text="$t('nav.docs')"
icon="i-ri:book-open-line"
to="https://docs.elk.zone/"
large target="_blank"
/>
<SettingsItem
text="Mastodon"
icon="i-ri:mastodon-line"
@ -117,7 +124,7 @@ function handleShowCommit() {
<SettingsItem
v-for="team in elkTeamMembers" :key="team.github"
:text="team.display"
:to="`https://github.com/sponsors/${team.github}`"
:to="team.link"
external target="_blank"
>
<template #icon>

View file

@ -26,8 +26,18 @@ const status = computed(() => {
<h2 py2 font-bold text-xl flex="~ gap-1" items-center>
{{ $t('settings.language.display_language') }}
</h2>
<div>{{ status }}</div>
<div>
{{ status }}
</div>
<SettingsLanguage select-settings />
<NuxtLink
href="https://docs.elk.zone/guide/contributing"
target="_blank"
hover:underline text-primary inline-flex items-center gap-1
>
<span inline-block i-ri:information-line />
{{ $t('settings.language.how_to_contribute') }}
</NuxtLink>
</div>
<div mt4>
<h2 font-bold text-xl flex="~ gap-1" items-center>

View file

@ -21,6 +21,12 @@ const userSettings = useUserSettings()
>
{{ $t('settings.preferences.hide_alt_indi_on_posts') }}
</SettingsToggleItem>
<SettingsToggleItem
:checked="getPreferences(userSettings, 'hideGifIndicatorOnPosts')"
@click="togglePreferences('hideGifIndicatorOnPosts')"
>
{{ $t('settings.preferences.hide_gif_indi_on_posts') }}
</SettingsToggleItem>
<SettingsToggleItem
:checked="getPreferences(userSettings, 'hideAccountHoverCard')"
@click="togglePreferences('hideAccountHoverCard')"

View file

@ -49,7 +49,7 @@ export default defineNuxtPlugin(({ $scrollToTop }) => {
whenever(logicAnd(isAuthenticated, notUsingInput, useMagicSequence(['g', 'i'])), () => navigateTo('/lists'))
whenever(logicAnd(notUsingInput, useMagicSequence(['g', 's'])), () => navigateTo('/settings'))
whenever(logicAnd(isAuthenticated, notUsingInput, useMagicSequence(['g', 'p'])), () => navigateTo(`/${instanceDomain}/@${currentUser.value?.account.username}`))
whenever(logicAnd(notUsingInput, keys['/']), () => navigateTo('/search'))
whenever(logicAnd(notUsingInput, computed(() => keys.current.size === 1), keys['/']), () => navigateTo('/search'))
const toggleFavouriteActiveStatus = () => {
// TODO: find a better solution than clicking buttons...

File diff suppressed because it is too large Load diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 489 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 344 B

View file

@ -9,9 +9,6 @@ const avatarsDir = resolve('./public/avatars/')
const sizes = [60, 100]
async function download(url: string, fileName: string) {
if (fs.existsSync(fileName))
return
console.log('downloading', fileName)
try {
const image = await ofetch(url, { responseType: 'arrayBuffer' })

View file

@ -1,5 +1,5 @@
import { Buffer } from 'node:buffer'
import flatten from 'flat'
import { flatten, unflatten } from 'flat'
import { createResolver } from '@nuxt/kit'
import fs from 'fs-extra'
import { currentLocales } from '../config/i18n'
@ -51,7 +51,7 @@ async function removeOutdatedTranslations() {
delete targetTranslations[key]
}
const unflattened = flatten.unflatten(targetTranslations)
const unflattened = unflatten(targetTranslations)
await fs.writeFile(
path,

View file

@ -1,5 +1,5 @@
import { Buffer } from 'node:buffer'
import flatten from 'flat'
import { flatten } from 'flat'
import { createResolver } from '@nuxt/kit'
import fs from 'fs-extra'
import { countryLocaleVariants, currentLocales } from '../config/i18n'

View file

@ -60,6 +60,8 @@ export function createNotificationOptions(
icon,
lang: preferred_locale,
tag: notification_id,
// eslint-disable-next-line ts/prefer-ts-expect-error
// @ts-ignore error missing type, just ignore
timestamp: new Date().getTime(),
}
@ -70,10 +72,13 @@ export function createNotificationOptions(
if (notification.account.avatar_static)
notificationOptions.icon = notification.account.avatar_static
*/
if (notification.created_at)
if (notification.created_at) {
// eslint-disable-next-line ts/prefer-ts-expect-error
// @ts-ignore error missing type, just ignore
notificationOptions.timestamp = new Date(notification.created_at).getTime()
}
/* TODO: add spolier when actions available, checking also notification type
/* TODO: add spoiler when actions available, checking also notification type
if (notification.status && (notification.status.spoilerText || notification.status.sensitive)) {
if (notification.status.spoilerText)
notificationOptions.body = notification.status.spoilerText
@ -83,8 +88,11 @@ export function createNotificationOptions(
*/
if (notification.status) {
// notificationOptions.body = htmlToPlainText(notification.status.content)
if (notification.status.media_attachments && notification.status.media_attachments.length > 0 && notification.status.media_attachments[0].preview_url)
if (notification.status.media_attachments && notification.status.media_attachments.length > 0 && notification.status.media_attachments[0].preview_url) {
// eslint-disable-next-line ts/prefer-ts-expect-error
// @ts-ignore error missing type, just ignore
notificationOptions.image = notification.status.media_attachments[0].preview_url
}
if (notification.type === 'favourite' || notification.type === 'reblog' || notification.type === 'mention')
notificationOptions.data.url = `${user.server}/@${user.account.username}/${notification.status.id}`

View file

@ -85,6 +85,9 @@ em-emoji-picker {
p:last-child {
--at-apply: mb-1;
}
pre {
--at-apply: whitespace-pre-wrap;
}
code {
--at-apply: bg-code text-code px1 py0.5 rounded text-0.875em leading-0.8em;
}
@ -109,6 +112,9 @@ em-emoji-picker {
ul > li {
--at-apply: pl-2;
}
blockquote {
--at-apply: border-primary border-l-4 border-solid pl-3 my-3 text-secondary;
}
.code-block {
--at-apply: bg-code text-0.875em p3 mt-2 rounded overflow-auto
leading-1.6em;

View file

@ -56,13 +56,22 @@ export interface Draft {
export type DraftMap = Record<string, Draft>
export interface ConfirmDialogLabel {
export interface ConfirmDialogOptions {
title: string
description?: string
confirm?: string
cancel?: string
extraOptionType?: 'mute'
}
export interface ConfirmDialogChoice {
choice: 'confirm' | 'cancel'
extraOptions?: {
mute: {
duration: number
notifications: boolean
}
}
}
export type ConfirmDialogChoice = 'confirm' | 'cancel'
export interface CommonRouteTabOption {
to: RouteLocationRaw