Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: update upstream v1.13.0 #15

Merged
merged 19 commits into from
Mar 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
8786c83
fix: remember last accessed notification tab (#2654)
shuuji3 Mar 6, 2024
d579977
feat(i18n): update Ukrainian translations (#2660)
Demivan Mar 7, 2024
0f583ec
feat: remember last accessed explore tab (#2658)
shuuji3 Mar 7, 2024
df165f0
fix(pwa): wrong web manifest colors (#2659)
userquin Mar 7, 2024
efa17ca
fix: consistent hover highlight styling in mobile bottom navigation m…
shuuji3 Mar 7, 2024
4954473
chore: extract bg and theme colors to constants (#2662)
userquin Mar 7, 2024
3448335
feat: allow to set mute duration and notifications mute option (#2665)
shuuji3 Mar 9, 2024
1c8e48b
fix: show loading spinner on follow button while fetching account rel…
shuuji3 Mar 9, 2024
0fd9374
fix: fix incorrect follow status on followers and following pages (#2…
shuuji3 Mar 9, 2024
dfbe2e0
fix: prevent empty search keyword to send invalid request (#2676)
shuuji3 Mar 10, 2024
ed8a181
chore: upgrade `@vueuse/core` from `10.8.0` to `10.9.0` (#2674)
shuuji3 Mar 10, 2024
3b1a66c
fix: fix `vue/no-ref-as-operand` and `vue/return-in-computed-property…
shuuji3 Mar 11, 2024
b06ec93
feat(i18n): update Tagalog translations (#2677)
ayoayco Mar 11, 2024
e7dfdaf
feat(i18n): Update portuguese from Portugal translation (#2671)
emanuelpina Mar 11, 2024
c64580f
feat(i18n): update eu-ES.json (#2670)
xabirequejo Mar 11, 2024
364fbd3
feat(i18n): Update it-IT locale (#2666)
katullo11 Mar 11, 2024
c432c2b
feat(i18n): Update vi-VN.json (#2664)
mastoduy Mar 11, 2024
bc30a8b
chore: release v0.13.0
patak-dev Mar 11, 2024
b04c025
Merge branch 'elk-zone:main' into update-from-elk
maybeanerd Mar 11, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 30 additions & 20 deletions components/account/AccountFollowButton.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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()

Expand Down Expand Up @@ -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'
})
Expand All @@ -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>
17 changes: 10 additions & 7 deletions components/account/AccountMoreButton.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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 })
Expand Down
4 changes: 2 additions & 2 deletions components/command/CommandPanel.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -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,
)
Expand Down
10 changes: 8 additions & 2 deletions components/common/CommonCheckbox.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ defineProps<{
hover?: boolean
iconChecked?: string
iconUnchecked?: string
checkedIconColor?: string
prependCheckbox?: boolean
}>()
const modelValue = defineModel<boolean | null>()
</script>
Expand All @@ -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"
/>
Expand All @@ -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>

Expand Down
4 changes: 2 additions & 2 deletions components/list/ListEntry.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -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()
Expand Down
45 changes: 45 additions & 0 deletions components/modal/DurationPicker.vue
Original file line number Diff line number Diff line change
@@ -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>
37 changes: 33 additions & 4 deletions components/modal/ModalConfirm.vue
Original file line number Diff line number Diff line change
@@ -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>
Expand All @@ -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>
Expand Down
8 changes: 6 additions & 2 deletions components/nav/NavBottom.vue
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
<script setup lang="ts">
// only one icon can be lit up at the same time
import { STORAGE_KEY_LAST_ACCESSED_EXPLORE_ROUTE, STORAGE_KEY_LAST_ACCESSED_NOTIFICATION_ROUTE } from '~/constants'

const moreMenuVisible = ref(false)

const { notifications } = useNotifications()
const lastAccessedNotificationRoute = useLocalStorage(STORAGE_KEY_LAST_ACCESSED_NOTIFICATION_ROUTE, '')
const lastAccessedExploreRoute = useLocalStorage(STORAGE_KEY_LAST_ACCESSED_EXPLORE_ROUTE, '')
</script>

<template>
Expand All @@ -19,7 +23,7 @@ const { notifications } = useNotifications()
<NuxtLink to="/search" :aria-label="$t('nav.search')" :active-class="moreMenuVisible ? '' : 'text-primary'" flex flex-row items-center place-content-center h-full flex-1 class="coarse-pointer:select-none" @click="$scrollToTop">
<div i-ri:search-line />
</NuxtLink>
<NuxtLink to="/notifications" :aria-label="$t('nav.notifications')" :active-class="moreMenuVisible ? '' : 'text-primary'" flex flex-row items-center place-content-center h-full flex-1 class="coarse-pointer:select-none" @click="$scrollToTop">
<NuxtLink :to="`/notifications/${lastAccessedNotificationRoute}`" :aria-label="$t('nav.notifications')" :active-class="moreMenuVisible ? '' : 'text-primary'" flex flex-row items-center place-content-center h-full flex-1 class="coarse-pointer:select-none" @click="$scrollToTop">
<div flex relative>
<div class="i-ri:notification-4-line" text-xl />
<div v-if="notifications" class="top-[-0.3rem] right-[-0.3rem]" absolute font-bold rounded-full h-4 w-4 text-xs bg-primary text-inverted flex items-center justify-center>
Expand All @@ -32,7 +36,7 @@ const { notifications } = useNotifications()
</NuxtLink>
</template>
<template v-else>
<NuxtLink :to="`/${currentServer}/explore`" :aria-label="$t('nav.explore')" :active-class="moreMenuVisible ? '' : 'text-primary'" flex flex-row items-center place-content-center h-full flex-1 class="coarse-pointer:select-none" @click="$scrollToTop">
<NuxtLink :to="`/${currentServer}/explore/${lastAccessedExploreRoute}`" :aria-label="$t('nav.explore')" :active-class="moreMenuVisible ? '' : 'text-primary'" flex flex-row items-center place-content-center h-full flex-1 class="coarse-pointer:select-none" @click="$scrollToTop">
<div i-ri:compass-3-line />
</NuxtLink>
<NuxtLink group :to="`/${currentServer}/public/local`" :aria-label="$t('nav.local')" :active-class="moreMenuVisible ? '' : 'text-primary'" flex flex-row items-center place-content-center h-full flex-1 class="coarse-pointer:select-none" @click="$scrollToTop">
Expand Down
8 changes: 6 additions & 2 deletions components/nav/NavSide.vue
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
<script setup lang="ts">
import { STORAGE_KEY_LAST_ACCESSED_EXPLORE_ROUTE, STORAGE_KEY_LAST_ACCESSED_NOTIFICATION_ROUTE } from '~/constants'

const { command } = defineProps<{
command?: boolean
}>()
const { notifications } = useNotifications()
const useStarFavoriteIcon = usePreferences('useStarFavoriteIcon')
const lastAccessedNotificationRoute = useLocalStorage(STORAGE_KEY_LAST_ACCESSED_NOTIFICATION_ROUTE, '')
const lastAccessedExploreRoute = useLocalStorage(STORAGE_KEY_LAST_ACCESSED_EXPLORE_ROUTE, '')
</script>

<template>
Expand All @@ -12,7 +16,7 @@ const useStarFavoriteIcon = usePreferences('useStarFavoriteIcon')

<div class="spacer" shrink xl:hidden />
<NavSideItem :text="$t('nav.home')" to="/home" icon="i-ri:home-5-line" user-only :command="command" />
<NavSideItem :text="$t('nav.notifications')" to="/notifications" icon="i-ri:notification-4-line" user-only :command="command">
<NavSideItem :text="$t('nav.notifications')" :to="`/notifications/${lastAccessedNotificationRoute}`" icon="i-ri:notification-4-line" user-only :command="command">
<template #icon>
<div flex relative>
<div class="i-ri:notification-4-line" text-xl />
Expand All @@ -30,7 +34,7 @@ const useStarFavoriteIcon = usePreferences('useStarFavoriteIcon')
<NavSideItem :text="$t('action.compose')" to="/compose" icon="i-ri:quill-pen-line" user-only :command="command" />

<div class="spacer" shrink hidden sm:block />
<NavSideItem :text="$t('nav.explore')" :to="isHydrated ? `/${currentServer}/explore` : '/explore'" icon="i-ri:compass-3-line" :command="command" />
<NavSideItem :text="$t('nav.explore')" :to="isHydrated ? `/${currentServer}/explore/${lastAccessedExploreRoute}` : `/explore/${lastAccessedExploreRoute}`" icon="i-ri:compass-3-line" :command="command" />
<NavSideItem :text="$t('nav.local')" :to="isHydrated ? `/${currentServer}/public/local` : '/public/local'" icon="i-ri:group-2-line " :command="command" />
<NavSideItem :text="$t('nav.federated')" :to="isHydrated ? `/${currentServer}/public` : '/public'" icon="i-ri:earth-line" :command="command" />
<NavSideItem :text="$t('nav.lists')" :to="isHydrated ? `/${currentServer}/lists` : '/lists'" icon="i-ri:list-check" user-only :command="command" />
Expand Down
18 changes: 14 additions & 4 deletions components/nav/NavSideItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,21 @@ const noUserVisual = computed(() => isHydrated.value && props.userOnly && !curre
<div
class="item"
flex items-center gap4
w-fit rounded-3
px2 mx3 sm:mxa
xl="ml0 mr5 px5 w-auto"
transition-100
elk-group-hover="bg-active" group-focus-visible:ring="2 current"
:class="isSmallScreen
? `
w-full
px5 sm:mxa
transition-colors duration-200 transform
hover-bg-gray-100 hover-dark:(bg-gray-700 text-white)
` : `
w-fit rounded-3
px2 mx3 sm:mxa
transition-100
elk-group-hover-bg-active
group-focus-visible:ring-2
group-focus-visible:ring-current
`"
>
<slot name="icon">
<div :class="icon" text-xl />
Expand Down
10 changes: 6 additions & 4 deletions components/status/StatusActionsMore.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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) {
Expand Down
Loading