Files
viberoom-web/src/entities/plan/model/usePlanTier.ts

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,
};
};