feat: toggleable feature flags (#209)

This commit is contained in:
Shinigami 2022-11-28 23:57:27 +01:00 committed by GitHub
parent f08777f629
commit 69d009d02a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 111 additions and 12 deletions

View file

@ -18,6 +18,7 @@ const buildTimeAgo = useTimeAgo(buildTime)
/> />
</CommonTooltip> </CommonTooltip>
<NavSelectLanguage /> <NavSelectLanguage />
<NavSelectFeatureFlags v-if="currentUser" />
</div> </div>
<div> <div>
<button cursor-pointer hover:underline @click="openPreviewHelp"> <button cursor-pointer hover:underline @click="openPreviewHelp">

View file

@ -0,0 +1,24 @@
<script setup lang="ts">
const { t } = useI18n()
const featureFlags = useFeatureFlags()
</script>
<template>
<CommonTooltip :content="t('nav_footer.select_feature_flags')">
<CommonDropdown>
<button flex>
<div i-ri:flag-line text-lg />
</button>
<template #popper>
<CommonDropdownItem
:checked="featureFlags.experimentalVirtualScroll"
@click="toggleFeatureFlag('experimentalVirtualScroll')"
>
{{ t('feature_flag.virtual_scroll') }}
</CommonDropdownItem>
</template>
</CommonDropdown>
</CommonTooltip>
</template>

View file

@ -10,7 +10,7 @@ const { locales } = useI18n() as { locales: ComputedRef<LocaleObject[]> }
</script> </script>
<template> <template>
<CommonTooltip placement="bottom" :content="t('nav_footer.select_language')"> <CommonTooltip :content="t('nav_footer.select_language')">
<CommonDropdown> <CommonDropdown>
<button flex> <button flex>
<div i-ri:earth-line text-lg /> <div i-ri:earth-line text-lg />

View file

@ -7,23 +7,27 @@ const { paginator, stream } = defineProps<{
paginator: Paginator<any, Status[]> paginator: Paginator<any, Status[]>
stream?: WsEvents stream?: WsEvents
}>() }>()
const virtualScroller = $(computedEager(() => useFeatureFlags().experimentalVirtualScroll))
</script> </script>
<template> <template>
<CommonPaginator v-bind="{ paginator, stream }" virtual-scroller> <CommonPaginator v-bind="{ paginator, stream }" :virtual-scroller="virtualScroller">
<template #updater="{ number, update }"> <template #updater="{ number, update }">
<button py-4 border="b base" flex="~ col" p-3 w-full text-primary font-bold @click="update"> <button py-4 border="b base" flex="~ col" p-3 w-full text-primary font-bold @click="update">
Show {{ number }} new items Show {{ number }} new items
</button> </button>
</template> </template>
<template #default="{ item, active }"> <template #default="{ item, active }">
<template v-if="virtualScroller">
<DynamicScrollerItem :item="item" :active="active" tag="article"> <DynamicScrollerItem :item="item" :active="active" tag="article">
<StatusCard <StatusCard :status="item" border="b base" py-3 />
:status="item"
border="b base" py-3
/>
</DynamicScrollerItem> </DynamicScrollerItem>
</template> </template>
<template v-else>
<StatusCard :status="item" border="b base" py-3 />
</template>
</template>
<template #loading> <template #loading>
<StatusCardSkeleton border="b base" py-3 /> <StatusCardSkeleton border="b base" py-3 />
<StatusCardSkeleton border="b base" py-3 op50 /> <StatusCardSkeleton border="b base" py-3 op50 />

View file

@ -0,0 +1,57 @@
import type { Account } from 'masto'
import { STORAGE_KEY_FEATURE_FLAGS } from '~/constants'
export interface FeatureFlags {
experimentalVirtualScroll: boolean
}
export type FeatureFlagsMap = Record<string, FeatureFlags>
export const allFeatureFlags = useLocalStorage<FeatureFlagsMap>(STORAGE_KEY_FEATURE_FLAGS, {}, { deep: true })
export function getDefaultFeatureFlags(): FeatureFlags {
return {
experimentalVirtualScroll: false,
}
}
export const currentUserFeatureFlags = computed(() => {
if (!currentUser.value?.account.id)
return {} as FeatureFlags
const id = `${currentUser.value.account.acct}@${currentUser.value.server}`
if (!allFeatureFlags.value[id])
allFeatureFlags.value[id] = getDefaultFeatureFlags()
return allFeatureFlags.value[id] as FeatureFlags
})
export function useFeatureFlags() {
const featureFlags = currentUserFeatureFlags.value
return featureFlags
}
export function toggleFeatureFlag(key: keyof FeatureFlags) {
const featureFlags = currentUserFeatureFlags.value
if (featureFlags[key])
featureFlags[key] = !featureFlags[key]
else
featureFlags[key] = true
}
export function clearUserFeatureFlags(account?: Account) {
if (!account)
account = currentUser.value?.account
if (!account)
return
const id = `${account.acct}@${currentUser.value?.server}`
if (!allFeatureFlags.value[id])
return
delete allFeatureFlags.value[id]
}

View file

@ -73,6 +73,7 @@ export async function signout() {
// Clear stale data // Clear stale data
delete servers.value[_currentUserId] delete servers.value[_currentUserId]
clearUserDrafts() clearUserDrafts()
clearUserFeatureFlags()
// Remove the current user from the users // Remove the current user from the users
users.value.splice(index, 1) users.value.splice(index, 1)

View file

@ -11,4 +11,4 @@ export const STORAGE_KEY_NOTIFY_TAB = 'elk-notify-tab'
export const STORAGE_KEY_FIRST_VISIT = 'elk-first-visit' export const STORAGE_KEY_FIRST_VISIT = 'elk-first-visit'
export const STORAGE_KEY_ZEN_MODE = 'elk-zenmode' export const STORAGE_KEY_ZEN_MODE = 'elk-zenmode'
export const STORAGE_KEY_LANG = 'elk-lang' export const STORAGE_KEY_LANG = 'elk-lang'
export const STORAGE_KEY_FEATURE_FLAGS = 'elk-feature-flags'

View file

@ -11,7 +11,8 @@
"profile": "Profil" "profile": "Profil"
}, },
"nav_footer": { "nav_footer": {
"select_language": "Sprache auswählen" "select_language": "Sprache auswählen",
"select_feature_flags": "Feature-Flags umschalten"
}, },
"timeline": "Timeline", "timeline": "Timeline",
"title": { "title": {
@ -22,5 +23,8 @@
"posts": "{0} Beiträge", "posts": "{0} Beiträge",
"following": "{0} Folge ich", "following": "{0} Folge ich",
"followers": "{0} Follower" "followers": "{0} Follower"
},
"feature_flag": {
"virtual_scroll": "Virtuelles Scrollen"
} }
} }

View file

@ -11,7 +11,8 @@
"profile": "Profile" "profile": "Profile"
}, },
"nav_footer": { "nav_footer": {
"select_language": "Select Language" "select_language": "Select Language",
"select_feature_flags": "Toggle Feature Flags"
}, },
"timeline": "Timeline", "timeline": "Timeline",
"title": { "title": {
@ -22,5 +23,8 @@
"posts": "{0} Posts", "posts": "{0} Posts",
"following": "{0} Following", "following": "{0} Following",
"followers": "{0} Followers" "followers": "{0} Followers"
},
"feature_flag": {
"virtual_scroll": "Virtual Scrolling"
} }
} }

View file

@ -11,7 +11,8 @@
"profile": "个人资料" "profile": "个人资料"
}, },
"nav_footer": { "nav_footer": {
"select_language": "选择语言" "select_language": "选择语言",
"select_feature_flags": "切换功能标志"
}, },
"timeline": "时间轴", "timeline": "时间轴",
"title": { "title": {
@ -22,5 +23,8 @@
"followers": "被 {0} 人关注", "followers": "被 {0} 人关注",
"following": "正在关注 {0} 人", "following": "正在关注 {0} 人",
"posts": "{0} 条帖文" "posts": "{0} 条帖文"
},
"feature_flag": {
"virtual_scroll": "虚拟滚动"
} }
} }