78 lines
1.6 KiB
TypeScript
78 lines
1.6 KiB
TypeScript
'use client';
|
|
|
|
import { useCallback, useSyncExternalStore } from 'react';
|
|
import type { PlanTier } from './types';
|
|
|
|
const PLAN_TIER_STORAGE_KEY = 'viberoom:plan-tier:v1';
|
|
const planTierSubscribers = new Set<() => void>();
|
|
|
|
const normalizePlanTier = (value: unknown): PlanTier => {
|
|
return value === 'pro' ? 'pro' : 'normal';
|
|
};
|
|
|
|
const notifyPlanTierSubscribers = () => {
|
|
for (const subscriber of planTierSubscribers) {
|
|
subscriber();
|
|
}
|
|
};
|
|
|
|
const subscribeToPlanTier = (onStoreChange: () => void) => {
|
|
if (typeof window === 'undefined') {
|
|
return () => {};
|
|
}
|
|
|
|
const handleStorage = (event: StorageEvent) => {
|
|
if (event.key !== PLAN_TIER_STORAGE_KEY) {
|
|
return;
|
|
}
|
|
|
|
onStoreChange();
|
|
};
|
|
|
|
planTierSubscribers.add(onStoreChange);
|
|
window.addEventListener('storage', handleStorage);
|
|
|
|
return () => {
|
|
planTierSubscribers.delete(onStoreChange);
|
|
window.removeEventListener('storage', handleStorage);
|
|
};
|
|
};
|
|
|
|
export const readStoredPlanTier = (): PlanTier => {
|
|
if (typeof window === 'undefined') {
|
|
return 'normal';
|
|
}
|
|
|
|
try {
|
|
return normalizePlanTier(window.localStorage.getItem(PLAN_TIER_STORAGE_KEY));
|
|
} catch {
|
|
return 'normal';
|
|
}
|
|
};
|
|
|
|
export const usePlanTier = () => {
|
|
const plan = useSyncExternalStore<PlanTier>(
|
|
subscribeToPlanTier,
|
|
readStoredPlanTier,
|
|
() => 'normal',
|
|
);
|
|
|
|
const setPlan = useCallback((nextPlan: PlanTier) => {
|
|
if (typeof window === 'undefined') {
|
|
return;
|
|
}
|
|
|
|
try {
|
|
window.localStorage.setItem(PLAN_TIER_STORAGE_KEY, nextPlan);
|
|
} finally {
|
|
notifyPlanTierSubscribers();
|
|
}
|
|
}, []);
|
|
|
|
return {
|
|
plan,
|
|
isPro: plan === 'pro',
|
|
setPlan,
|
|
};
|
|
};
|