WIP
This commit is contained in:
@@ -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>)
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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)[]
|
||||||
@@ -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])
|
||||||
|
}
|
||||||
@@ -7,7 +7,6 @@ export enum Nux {
|
|||||||
ExploreInterestsCard = 'ExploreInterestsCard',
|
ExploreInterestsCard = 'ExploreInterestsCard',
|
||||||
InitialVerificationAnnouncement = 'InitialVerificationAnnouncement',
|
InitialVerificationAnnouncement = 'InitialVerificationAnnouncement',
|
||||||
}
|
}
|
||||||
|
|
||||||
export const nuxNames = new Set(Object.values(Nux))
|
export const nuxNames = new Set(Object.values(Nux))
|
||||||
|
|
||||||
export type AppNux = BaseNux<
|
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> = {
|
export const NuxSchemas: Record<Nux, zod.ZodObject<any> | undefined> = {
|
||||||
[Nux.NeueTypography]: undefined,
|
[Nux.NeueTypography]: undefined,
|
||||||
[Nux.ExploreInterestsCard]: undefined,
|
[Nux.ExploreInterestsCard]: undefined,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import {useMutation, useQueryClient} from '@tanstack/react-query'
|
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 {parseAppNux, serializeAppNux} from '#/state/queries/nuxs/util'
|
||||||
import {
|
import {
|
||||||
preferencesQueryKey,
|
preferencesQueryKey,
|
||||||
@@ -93,6 +93,8 @@ export function useSaveNux() {
|
|||||||
await queryClient.invalidateQueries({
|
await queryClient.invalidateQueries({
|
||||||
queryKey: preferencesQueryKey,
|
queryKey: preferencesQueryKey,
|
||||||
})
|
})
|
||||||
|
// do not await, just cleaning up
|
||||||
|
agent.bskyAppRemoveNuxs(retiredNuxNames).catch(() => {})
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user