diff --git a/components/account/AccountPostsFollowers.vue b/components/account/AccountPostsFollowers.vue index 98dcd4c2..d647bd62 100644 --- a/components/account/AccountPostsFollowers.vue +++ b/components/account/AccountPostsFollowers.vue @@ -40,7 +40,7 @@ const userSettings = useUserSettings() </template> </NuxtLink> <NuxtLink - v-if="!getWellnessSetting(userSettings, 'hideFollowerCount')" + v-if="!getPreferences(userSettings, 'hideFollowerCount')" :to="getAccountFollowersRoute(account)" replace text-secondary exact-active-class="text-primary" diff --git a/components/status/StatusActions.vue b/components/status/StatusActions.vue index 44c16dad..6b761d05 100644 --- a/components/status/StatusActions.vue +++ b/components/status/StatusActions.vue @@ -55,7 +55,7 @@ const reply = () => { <div flex-1> <StatusActionButton :content="$t('action.boost')" - :text="!getWellnessSetting(userSettings, 'hideBoostCount') && status.reblogsCount ? status.reblogsCount : ''" + :text="!getPreferences(userSettings, 'hideBoostCount') && status.reblogsCount ? status.reblogsCount : ''" color="text-green" hover="text-green" group-hover="bg-green/10" icon="i-ri:repeat-line" active-icon="i-ri:repeat-fill" @@ -64,7 +64,7 @@ const reply = () => { :command="command" @click="toggleReblog()" > - <template v-if="status.reblogsCount && !getWellnessSetting(userSettings, 'hideBoostCount')" #text> + <template v-if="status.reblogsCount && !getPreferences(userSettings, 'hideBoostCount')" #text> <CommonLocalizedNumber keypath="action.boost_count" :count="status.reblogsCount" @@ -76,7 +76,7 @@ const reply = () => { <div flex-1> <StatusActionButton :content="$t('action.favourite')" - :text="!getWellnessSetting(userSettings, 'hideFavoriteCount') && status.favouritesCount ? status.favouritesCount : ''" + :text="!getPreferences(userSettings, 'hideFavoriteCount') && status.favouritesCount ? status.favouritesCount : ''" color="text-rose" hover="text-rose" group-hover="bg-rose/10" icon="i-ri:heart-3-line" active-icon="i-ri:heart-3-fill" @@ -85,7 +85,7 @@ const reply = () => { :command="command" @click="toggleFavourite()" > - <template v-if="status.favouritesCount && !getWellnessSetting(userSettings, 'hideFavoriteCount')" #text> + <template v-if="status.favouritesCount && !getPreferences(userSettings, 'hideFavoriteCount')" #text> <CommonLocalizedNumber keypath="action.favourite_count" :count="status.favouritesCount" diff --git a/components/status/StatusPreviewCard.vue b/components/status/StatusPreviewCard.vue index 94192428..2b0cdb8c 100644 --- a/components/status/StatusPreviewCard.vue +++ b/components/status/StatusPreviewCard.vue @@ -21,7 +21,7 @@ const isSquare = $computed(() => ( )) const providerName = $computed(() => props.card.providerName ? props.card.providerName : new URL(props.card.url).hostname) -const gitHubCards = $(useFeatureFlag('experimentalGitHubCards')) +const gitHubCards = $(usePreferences('experimentalGitHubCards')) // TODO: handle card.type: 'photo' | 'video' | 'rich'; const cardTypeIconMap: Record<mastodon.v1.PreviewCardType, string> = { diff --git a/components/timeline/TimelinePaginator.vue b/components/timeline/TimelinePaginator.vue index 723fa1b2..7a1c0a16 100644 --- a/components/timeline/TimelinePaginator.vue +++ b/components/timeline/TimelinePaginator.vue @@ -14,7 +14,7 @@ const { paginator, stream, account, buffer = 10 } = defineProps<{ }>() const { formatNumber } = useHumanReadableNumber() -const virtualScroller = $(useFeatureFlag('experimentalVirtualScroller')) +const virtualScroller = $(usePreferences('experimentalVirtualScroller')) const showOriginSite = $computed(() => account && account.id !== currentUser.value?.account.id && getServerName(account) !== currentServer.value, diff --git a/composables/settings/definition.ts b/composables/settings/definition.ts index 131bf986..ae7cde93 100644 --- a/composables/settings/definition.ts +++ b/composables/settings/definition.ts @@ -3,21 +3,17 @@ import { DEFAULT_FONT_SIZE } from '~/constants' export type FontSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl' export type ColorMode = 'light' | 'dark' | 'system' -export interface FeatureFlags { +export interface PreferencesSettings { + hideBoostCount: boolean + hideFavoriteCount: boolean + hideFollowerCount: boolean experimentalVirtualScroller: boolean experimentalGitHubCards: boolean experimentalUserPicker: boolean } -export interface WellnessSettings { - hideBoostCount: boolean - hideFavoriteCount: boolean - hideFollowerCount: boolean -} - export interface UserSettings { - featureFlags: Partial<FeatureFlags> - wellnessSettings: Partial<WellnessSettings> + preferences: Partial<PreferencesSettings> colorMode?: ColorMode fontSize: FontSize language: string @@ -35,18 +31,14 @@ export function getDefaultUserSettings(locales: string[]): UserSettings { language: getDefaultLanguage(locales), fontSize: DEFAULT_FONT_SIZE, zenMode: false, - featureFlags: {}, - wellnessSettings: {}, + preferences: {}, } } -export const DEFAULT_WELLNESS_SETTINGS: WellnessSettings = { +export const DEFAULT__PREFERENCES_SETTINGS: PreferencesSettings = { hideBoostCount: false, hideFavoriteCount: false, hideFollowerCount: false, -} - -export const DEFAULT_FEATURE_FLAGS: FeatureFlags = { experimentalVirtualScroller: true, experimentalGitHubCards: true, experimentalUserPicker: true, diff --git a/composables/settings/storage.ts b/composables/settings/storage.ts index ae0ad0ed..559c0405 100644 --- a/composables/settings/storage.ts +++ b/composables/settings/storage.ts @@ -1,7 +1,7 @@ import type { Ref } from 'vue' import type { VueI18n } from 'vue-i18n' import type { LocaleObject } from 'vue-i18n-routing' -import type { FeatureFlags, UserSettings, WellnessSettings } from './definition' +import type { PreferencesSettings, UserSettings } from './definition' import { STORAGE_KEY_SETTINGS } from '~/constants' export function useUserSettings() { @@ -13,44 +13,23 @@ export function useUserSettings() { // TODO: refactor & simplify this -export function useWellnessSetting<T extends keyof WellnessSettings>(name: T): Ref<WellnessSettings[T]> { +export function usePreferences<T extends keyof PreferencesSettings>(name: T): Ref<PreferencesSettings[T]> { const userSettings = useUserSettings() return computed({ get() { - return getWellnessSetting(userSettings.value, name) + return getPreferences(userSettings.value, name) }, set(value) { - userSettings.value.wellnessSettings[name] = value + userSettings.value.preferences[name] = value }, }) } -export function getWellnessSetting<T extends keyof WellnessSettings>(userSettings: UserSettings, name: T): WellnessSettings[T] { - return userSettings?.wellnessSettings?.[name] ?? DEFAULT_WELLNESS_SETTINGS[name] +export function getPreferences<T extends keyof PreferencesSettings>(userSettings: UserSettings, name: T): PreferencesSettings[T] { + return userSettings?.preferences?.[name] ?? DEFAULT__PREFERENCES_SETTINGS[name] } -export function toggleWellnessSetting(key: keyof WellnessSettings) { - const flag = useWellnessSetting(key) - flag.value = !flag.value -} - -export function useFeatureFlag<T extends keyof FeatureFlags>(name: T): Ref<FeatureFlags[T]> { - const userSettings = useUserSettings() - return computed({ - get() { - return getFeatureFlag(userSettings.value, name) - }, - set(value) { - userSettings.value.featureFlags[name] = value - }, - }) -} - -export function getFeatureFlag<T extends keyof FeatureFlags>(userSettings: UserSettings, name: T): FeatureFlags[T] { - return userSettings?.featureFlags?.[name] ?? DEFAULT_FEATURE_FLAGS[name] -} - -export function toggleFeatureFlag(key: keyof FeatureFlags) { - const flag = useFeatureFlag(key) +export function togglePreferences(key: keyof PreferencesSettings) { + const flag = usePreferences(key) flag.value = !flag.value } diff --git a/layouts/default.vue b/layouts/default.vue index bce515ff..31af5879 100644 --- a/layouts/default.vue +++ b/layouts/default.vue @@ -1,5 +1,5 @@ <script lang="ts" setup> -import { useFeatureFlag } from '~/composables/settings' +import { usePreferences } from '~/composables/settings' const route = useRoute() const userSettings = useUserSettings() @@ -7,7 +7,7 @@ const userSettings = useUserSettings() const wideLayout = computed(() => route.meta.wideLayout ?? false) const showUserPicker = logicAnd( - useFeatureFlag('experimentalUserPicker'), + usePreferences('experimentalUserPicker'), () => useUsers().value.length > 1, ) </script> diff --git a/locales/ar-EG.json b/locales/ar-EG.json index 0e28c2af..b6cdec01 100644 --- a/locales/ar-EG.json +++ b/locales/ar-EG.json @@ -240,12 +240,6 @@ "description": "قم بتحرير إعدادات حسابك في موقع Mastodon الأصلي", "label": "إعدادت الحساب" }, - "feature_flags": { - "github_cards": "GitHub بطاقات", - "title": "الميزات التجريبية", - "user_picker": "الشريط الجانبي لمبدل المستخدم", - "virtual_scroll": "التمرير الافتراضي" - }, "interface": { "color_mode": "وضع اللون", "dark_mode": "الوضع الداكن", @@ -315,7 +309,14 @@ }, "notifications_settings": "التنبيهات", "preferences": { - "label": "التفضيلات" + "github_cards": "GitHub بطاقات", + "hide_boost_count": "إخفاء عدد المشاركات", + "hide_favorite_count": "إخفاء عدد المفضلة", + "hide_follower_count": "إخفاء عدد المتابعين", + "label": "التفضيلات", + "title": "الميزات التجريبية", + "user_picker": "الشريط الجانبي لمبدل المستخدم", + "virtual_scroll": "التمرير الافتراضي" }, "profile": { "appearance": { @@ -338,14 +339,6 @@ "export": "Export User Tokens", "import": "Import User Tokens", "label": "المستخدمون المسجلون" - }, - "wellness": { - "feature": { - "hide_boost_count": "إخفاء عدد المشاركات", - "hide_favorite_count": "إخفاء عدد المفضلة", - "hide_follower_count": "إخفاء عدد المتابعين" - }, - "label": "صحة النفس" } }, "state": { diff --git a/locales/en-US.json b/locales/en-US.json index 903d59b6..b313f102 100644 --- a/locales/en-US.json +++ b/locales/en-US.json @@ -251,12 +251,6 @@ "description": "Edit your account settings in Mastodon UI", "label": "Account settings" }, - "feature_flags": { - "github_cards": "GitHub Cards", - "title": "Experimental Features", - "user_picker": "User Picker", - "virtual_scroll": "Virtual Scrolling" - }, "interface": { "color_mode": "Color Mode", "dark_mode": "Dark Mode", @@ -328,7 +322,14 @@ }, "notifications_settings": "Notifications", "preferences": { - "label": "Preferences" + "github_cards": "GitHub Cards", + "hide_boost_count": "Hide boost count", + "hide_favorite_count": "Hide favorite count", + "hide_follower_count": "Hide follower count", + "label": "Preferences", + "title": "Experimental Features", + "user_picker": "User Picker", + "virtual_scroll": "Virtual Scrolling" }, "profile": { "appearance": { @@ -351,14 +352,6 @@ "export": "Export User Tokens", "import": "Import User Tokens", "label": "Logged in users" - }, - "wellness": { - "feature": { - "hide_boost_count": "Hide boost count", - "hide_favorite_count": "Hide favorite count", - "hide_follower_count": "Hide follower count" - }, - "label": "Wellness" } }, "share-target": { diff --git a/locales/es-ES.json b/locales/es-ES.json index 3c60de8b..47307a5f 100644 --- a/locales/es-ES.json +++ b/locales/es-ES.json @@ -247,12 +247,6 @@ "description": "Edita los ajustes de tu cuenta en la interfaz de Mastodon", "label": "Ajustes de cuenta" }, - "feature_flags": { - "github_cards": "Tarjetas GitHub", - "title": "Funcionalidades experimentales", - "user_picker": "Selector de usuarios", - "virtual_scroll": "Desplazamiento virtual" - }, "interface": { "color_mode": "Modos de color", "dark_mode": "Modo oscuro", @@ -323,7 +317,14 @@ }, "notifications_settings": "Notificaciones", "preferences": { - "label": "Preferencias" + "github_cards": "Tarjetas GitHub", + "hide_boost_count": "Ocultar contador de retoots", + "hide_favorite_count": "Ocultar contador de favoritas", + "hide_follower_count": "Ocultar contador de seguidores", + "label": "Preferencias", + "title": "Funcionalidades experimentales", + "user_picker": "Selector de usuarios", + "virtual_scroll": "Desplazamiento virtual" }, "profile": { "appearance": { @@ -346,14 +347,6 @@ "export": "Exportar tokens de usuario", "import": "Importar tokens de usuario", "label": "Usuarios conectados" - }, - "wellness": { - "feature": { - "hide_boost_count": "Ocultar contador de retoots", - "hide_favorite_count": "Ocultar contador de favoritas", - "hide_follower_count": "Ocultar contador de seguidores" - }, - "label": "Bienestar" } }, "share-target": { diff --git a/locales/fr-FR.json b/locales/fr-FR.json index 60dcd2d4..ef7bc03e 100644 --- a/locales/fr-FR.json +++ b/locales/fr-FR.json @@ -244,12 +244,6 @@ "description": "Modifiez les paramètres de votre compte dans l'interface de Mastodon", "label": "Paramètres de compte" }, - "feature_flags": { - "github_cards": "GitHub Cards", - "title": "Fonctionnalités expérimentales", - "user_picker": "User Picker", - "virtual_scroll": "Défilement virtuel" - }, "interface": { "color_mode": "Couleur de thème", "dark_mode": "Mode sombre", @@ -320,7 +314,14 @@ }, "notifications_settings": "Notifications", "preferences": { - "label": "Préférences" + "github_cards": "GitHub Cards", + "hide_boost_count": "Cacher les compteurs de partages", + "hide_favorite_count": "Cacher les compteurs de favoris", + "hide_follower_count": "Cacher les compteurs d'abonné·e·s", + "label": "Préférences", + "title": "Fonctionnalités expérimentales", + "user_picker": "User Picker", + "virtual_scroll": "Défilement virtuel" }, "profile": { "appearance": { @@ -343,14 +344,6 @@ "export": "Exporter les tokens d'utilisateur·ice", "import": "Importer des tokens d'utilisateur·ice", "label": "Utilisateur·ice·s connecté·e·s" - }, - "wellness": { - "feature": { - "hide_boost_count": "Cacher les compteurs de partages", - "hide_favorite_count": "Cacher les compteurs de favoris", - "hide_follower_count": "Cacher les compteurs d'abonné·e·s" - }, - "label": "Bien-être" } }, "state": { diff --git a/locales/tr-TR.json b/locales/tr-TR.json index 7c80aece..30aadd0d 100644 --- a/locales/tr-TR.json +++ b/locales/tr-TR.json @@ -247,12 +247,6 @@ "description": "Mastodon UI'da hesap ayarlarını değiştir", "label": "Hesap ayarları" }, - "feature_flags": { - "github_cards": "GitHub Cards", - "title": "Deneysel Özellikler", - "user_picker": "Kullanıcı Seçici", - "virtual_scroll": "Görsel Kaydırma" - }, "interface": { "color_mode": "Renk Modu", "dark_mode": "Karanlık Mod", @@ -324,7 +318,14 @@ }, "notifications_settings": "Bildirimler", "preferences": { - "label": "Ayarlar" + "github_cards": "GitHub Cards", + "hide_boost_count": "Boost sayısını gizle", + "hide_favorite_count": "Favori sayısını gizle", + "hide_follower_count": "Takipçi sayısını gizle", + "label": "Ayarlar", + "title": "Deneysel Özellikler", + "user_picker": "Kullanıcı Seçici", + "virtual_scroll": "Görsel Kaydırma" }, "profile": { "appearance": { @@ -347,14 +348,6 @@ "export": "Kullanıcı Tokenlerini Dışa Aktar", "import": "Kullanıcı Tokenlerini İçe Aktar", "label": "Giriş yapılan kullanıcılar" - }, - "wellness": { - "feature": { - "hide_boost_count": "Boost sayısını gizle", - "hide_favorite_count": "Favori sayısını gizle", - "hide_follower_count": "Takipçi sayısını gizle" - }, - "label": "Sağlık" } }, "state": { diff --git a/locales/zh-CN.json b/locales/zh-CN.json index 9f69ca8c..4f0aad8e 100644 --- a/locales/zh-CN.json +++ b/locales/zh-CN.json @@ -240,12 +240,6 @@ "description": "在 Mastodon UI 中编辑你的账号设置", "label": "账号设置" }, - "feature_flags": { - "github_cards": "GitHub 卡片", - "title": "实验功能", - "user_picker": "用户选择器", - "virtual_scroll": "虚拟滚动" - }, "interface": { "color_mode": "颜色", "dark_mode": "深色模式", @@ -316,7 +310,14 @@ }, "notifications_settings": "通知", "preferences": { - "label": "首选项" + "github_cards": "GitHub 卡片", + "hide_boost_count": "隐藏转发数", + "hide_favorite_count": "隐藏收藏数", + "hide_follower_count": "隐藏关注者数", + "label": "首选项", + "title": "实验功能", + "user_picker": "用户选择器", + "virtual_scroll": "虚拟滚动" }, "profile": { "appearance": { diff --git a/locales/zh-TW.json b/locales/zh-TW.json index 9fefe3fe..54558de1 100644 --- a/locales/zh-TW.json +++ b/locales/zh-TW.json @@ -250,12 +250,6 @@ "description": "在 Mastodon UI 中編輯你的帳號設定", "label": "帳號設定" }, - "feature_flags": { - "github_cards": "GitHub 卡片", - "title": "實驗功能", - "user_picker": "使用者選擇器", - "virtual_scroll": "虛擬滾動" - }, "interface": { "color_mode": "顏色", "dark_mode": "深色模式", @@ -327,7 +321,14 @@ }, "notifications_settings": "通知", "preferences": { - "label": "喜好設定" + "github_cards": "GitHub 卡片", + "hide_boost_count": "隱藏轉發數", + "hide_favorite_count": "隱藏收藏數", + "hide_follower_count": "隱藏關注者數", + "label": "喜好設定", + "title": "實驗功能", + "user_picker": "使用者選擇器", + "virtual_scroll": "虛擬滾動" }, "profile": { "appearance": { @@ -350,14 +351,6 @@ "export": "導出使用者令牌", "import": "導入使用者令牌", "label": "當前使用者" - }, - "wellness": { - "feature": { - "hide_boost_count": "隱藏轉發數", - "hide_favorite_count": "隱藏收藏數", - "hide_follower_count": "隱藏關注者數" - }, - "label": "健康設定" } }, "state": { diff --git a/pages/settings.vue b/pages/settings.vue index 9f339f8e..db03ce53 100644 --- a/pages/settings.vue +++ b/pages/settings.vue @@ -39,12 +39,6 @@ const isRootPath = computedEager(() => route.name === 'settings') :text="$t('settings.interface.label')" to="/settings/interface" /> - <SettingsItem - command - icon="i-ri-leaf-line" - :text="$t('settings.wellness.label')" - to="/settings/wellness" - /> <SettingsItem v-if="isHydrated && currentUser" command diff --git a/pages/settings/preferences/index.vue b/pages/settings/preferences/index.vue index 45b87813..4cc3b69e 100644 --- a/pages/settings/preferences/index.vue +++ b/pages/settings/preferences/index.vue @@ -10,6 +10,24 @@ const userSettings = useUserSettings() <template> <MainContent back-on-small-screen> + <SettingsToggleItem + :checked="getPreferences(userSettings, 'hideBoostCount')" + @click="togglePreferences('hideBoostCount')" + > + {{ $t('settings.preferences.hide_boost_count') }} + </SettingsToggleItem> + <SettingsToggleItem + :checked="getPreferences(userSettings, 'hideFavoriteCount')" + @click="togglePreferences('hideFavoriteCount')" + > + {{ $t('settings.preferences.hide_favorite_count') }} + </SettingsToggleItem> + <SettingsToggleItem + :checked="getPreferences(userSettings, 'hideFollowerCount')" + @click="togglePreferences('hideFollowerCount')" + > + {{ $t('settings.preferences.hide_follower_count') }} + </SettingsToggleItem> <template #title> <div text-lg font-bold flex items-center gap-2 @click="$scrollToTop"> <span>{{ $t('settings.preferences.label') }}</span> @@ -17,25 +35,25 @@ const userSettings = useUserSettings() </template> <h3 px6 py4 mt2 font-bold text-xl flex="~ gap-1" items-center> <div i-ri-flask-line /> - {{ $t('settings.feature_flags.title') }} + {{ $t('settings.preferences.title') }} </h3> <SettingsToggleItem - :checked="getFeatureFlag(userSettings, 'experimentalVirtualScroller')" - @click="toggleFeatureFlag('experimentalVirtualScroller')" + :checked="getPreferences(userSettings, 'experimentalVirtualScroller')" + @click="togglePreferences('experimentalVirtualScroller')" > - {{ $t('settings.feature_flags.virtual_scroll') }} + {{ $t('settings.preferences.virtual_scroll') }} </SettingsToggleItem> <SettingsToggleItem - :checked="getFeatureFlag(userSettings, 'experimentalGitHubCards')" - @click="toggleFeatureFlag('experimentalGitHubCards')" + :checked="getPreferences(userSettings, 'experimentalGitHubCards')" + @click="togglePreferences('experimentalGitHubCards')" > - {{ $t('settings.feature_flags.github_cards') }} + {{ $t('settings.preferences.github_cards') }} </SettingsToggleItem> <SettingsToggleItem - :checked="getFeatureFlag(userSettings, 'experimentalUserPicker')" - @click="toggleFeatureFlag('experimentalUserPicker')" + :checked="getPreferences(userSettings, 'experimentalUserPicker')" + @click="togglePreferences('experimentalUserPicker')" > - {{ $t('settings.feature_flags.user_picker') }} + {{ $t('settings.preferences.user_picker') }} </SettingsToggleItem> </MainContent> </template> diff --git a/pages/settings/wellness/index.vue b/pages/settings/wellness/index.vue deleted file mode 100644 index 546dbb93..00000000 --- a/pages/settings/wellness/index.vue +++ /dev/null @@ -1,37 +0,0 @@ -<script setup lang="ts"> -const { t } = useI18n() - -useHeadFixed({ - title: () => `${t('settings.wellness.label')} | ${t('nav.settings')}`, -}) - -const userSettings = useUserSettings() -</script> - -<template> - <MainContent back-on-small-screen> - <template #title> - <div text-lg font-bold flex items-center gap-2 @click="$scrollToTop"> - <span>{{ $t('settings.wellness.label') }}</span> - </div> - </template> - <SettingsToggleItem - :checked="getWellnessSetting(userSettings, 'hideBoostCount')" - @click="toggleWellnessSetting('hideBoostCount')" - > - {{ $t('settings.wellness.feature.hide_boost_count') }} - </SettingsToggleItem> - <SettingsToggleItem - :checked="getWellnessSetting(userSettings, 'hideFavoriteCount')" - @click="toggleWellnessSetting('hideFavoriteCount')" - > - {{ $t('settings.wellness.feature.hide_favorite_count') }} - </SettingsToggleItem> - <SettingsToggleItem - :checked="getWellnessSetting(userSettings, 'hideFollowerCount')" - @click="toggleWellnessSetting('hideFollowerCount')" - > - {{ $t('settings.wellness.feature.hide_follower_count') }} - </SettingsToggleItem> - </MainContent> -</template>