This commit is contained in:
Eric Bailey
2025-02-04 10:39:55 -06:00
parent aeafb14fb4
commit b8c804fe84
5 changed files with 94 additions and 2 deletions
+26
View File
@@ -0,0 +1,26 @@
const MAX_FLAGS = 300
const FLAGS_PER_CHAR = 6
export function pack(flags: Record<string, boolean>) {
const values = Object.values(flags)
if (values.length > MAX_FLAGS) {
throw new Error(`Too many flags. Maximum supported is ${MAX_FLAGS}`)
}
const compacted = values.map(value => value ? '1' : '0').join('')
// split into chunks of 6 values
const encoded = (compacted.match(/.{1,6}/g) || [])
.map(chunk => String.fromCharCode(parseInt(chunk.padEnd(6, '0'), 2)))
.join('')
return encoded
}
export function unpack<K extends string>(encoded: string, keys: K[]) {
const binary = encoded.split('')
.map(char => char.charCodeAt(0).toString(2).padEnd(6, '0'))
.join('')
return keys.reduce((obj, key, i) => {
obj[key] = binary[i] === '1'
return obj
}, {} as Record<K, boolean>)
}
+21
View File
@@ -0,0 +1,21 @@
export enum Group {
Wayfinding = 'wayfinding',
Composer = 'composer',
}
export type Flags = {
'wayfinding:settings': boolean
'wayfinding:settings:moderation': boolean
'composer:threadgate_20250204': boolean
}
export type Flag = keyof Flags
// existing users?
export const flags: Flags = {
'wayfinding:settings': true,
'wayfinding:settings:moderation': true,
'composer:threadgate_20250204': false,
}
export const flagKeys = Object.keys(flags) as (keyof typeof flags)[]
+36
View File
@@ -0,0 +1,36 @@
import {useMemo, useCallback} from 'react'
import {flags, flagKeys, Flag} from '#/state/queries/nudges/flags'
import {pack, unpack} from '#/state/queries/nudges/compression'
const TEST = pack(flags)
export function useNudges() {
const data = TEST // TODO
return useMemo(() => {
return data ? unpack(data, flagKeys) : flags
}, [data])
}
export function useNudgesGroup() {
// TODO
}
export function useNudge(flag: Flag) {
const nudges = useNudges()
const nudge = nudges[flag]
const complete = useCallback(() => {
const next = {...nudges}
next[flag] = true
const data = pack(next)
// TODO update
}, [nudge])
const reset = useCallback(() => {
const next = {...nudges}
next[flag] = false
const data = pack(next)
// TODO update
}, [nudge])
return useMemo(() => ({
}), [nudge, complete, reset])
}
+8 -1
View File
@@ -7,7 +7,6 @@ export enum Nux {
ExploreInterestsCard = 'ExploreInterestsCard',
InitialVerificationAnnouncement = 'InitialVerificationAnnouncement',
}
export const nuxNames = new Set(Object.values(Nux))
export type AppNux = BaseNux<
@@ -25,6 +24,14 @@ export type AppNux = BaseNux<
}
>
/**
* Nuxes that have been retired and should be cleared from storage.
*/
export enum RetiredNux {
NeueTypography = 'NeueTypography',
}
export const retiredNuxNames = Object.values(RetiredNux)
export const NuxSchemas: Record<Nux, zod.ZodObject<any> | undefined> = {
[Nux.NeueTypography]: undefined,
[Nux.ExploreInterestsCard]: undefined,
+3 -1
View File
@@ -1,6 +1,6 @@
import {useMutation, useQueryClient} from '@tanstack/react-query'
import {AppNux, Nux} from '#/state/queries/nuxs/definitions'
import {AppNux, Nux, retiredNuxNames} from '#/state/queries/nuxs/definitions'
import {parseAppNux, serializeAppNux} from '#/state/queries/nuxs/util'
import {
preferencesQueryKey,
@@ -93,6 +93,8 @@ export function useSaveNux() {
await queryClient.invalidateQueries({
queryKey: preferencesQueryKey,
})
// do not await, just cleaning up
agent.bskyAppRemoveNuxs(retiredNuxNames).catch(() => {})
},
})
}