Files
RecipesCam/src/utils/entitlement.ts
T
admin 42756ac7c3 Cap LITE at one FAVORITED recipe
Freeing the FAVORITED tab for LITE put no ceiling on the list, and a list
of your own picks is what PRO is selling. One star is free, the second
names the build; un-starring stays open so the list can always come back
under the limit.
2026-09-14 21:20:56 +07:00

59 lines
2.4 KiB
TypeScript

import { FrameId } from '../types';
import { IS_PRO_BUILD } from '../provariant';
// LITE (free) vs PRO (the paid build). The two are separate apks built from this
// one tree: the tier is fixed at build time by src/provariant.ts (rewritten by
// tools/set-variant.mjs, `npm run apk:lite|apk:pro`) and nothing in a LITE apk
// can change it afterwards — no key, no server, no stored flag.
// Constant for the life of the build, so every `!IS_PRO` branch below is dead
// code the bundler is free to drop.
export const IS_PRO = IS_PRO_BUILD;
// The gate is on the FILE, not on the preview: a LITE user composes with any
// look and compares it before/after — only the render/export of a PRO look is
// held back, and every LITE export carries the mark below.
//
// What LITE owns outright: the eight film sims, the bundled recipes, its own
// recipes up to LITE_RECIPE_LIMIT, its own watermark text (in one face), the
// plain frames, one favorite and every parameter. What needs PRO: the three
// printed frames, the GPS stamp, the platform's other fonts, the next recipe
// past the limit, and the second favorite.
// Frames on the LITE side: the plain export only. The three printed looks are
// PRO (the artwork/card geometry is the paid half of the FRAME tab).
export const PRO_FRAMES: FrameId[] = ['classic-white', 'polaroid', 'wallframe'];
// LITE may store its own recipes, up to this many: creating and editing them is
// free, deleting one is PRO — so a LITE list only ever grows to this size.
export const LITE_RECIPE_LIMIT = 3;
// FAVORITED is a LITE feature, but only one deep: the first star is free, the
// second needs PRO. Un-starring is always free, so the list can always come
// back under the limit.
export const LITE_FAVORITE_LIMIT = 1;
// Burned into every LITE export, bottom-right of the photo/frame area. Fractions
// of the stamp canvas, same space the custom mark uses. The user's own mark is
// free on top of it.
export const LITE_MARK = {
text: 'RECIPESCAM',
x: 0.55,
y: 0.94,
color: '#ffffff',
size: 0.8,
};
export interface Look {
frame: FrameId;
gpsWm: boolean;
}
// The first PRO feature a look is using, or null when it is LITE-clean. One
// string, so the caller can name it back to the user in the alert.
export function proLookInUse(look: Look): string | null {
if (PRO_FRAMES.includes(look.frame)) return 'A PRO frame';
if (look.gpsWm) return 'The GPS watermark';
return null;
}