Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 | 38x 38x 38x 38x 38x 38x 38x 38x 1x 38x 38x 38x 4x 3x 2x 2x 12x 12x 7x 2x 2x 38x 38x 167x 3x 3x 3x 191x 1x 1x 1x 1x 1x 1x 112x 112x 672x 672x 672x 112x | import type { ColorScheme, CustomFaceColors } from '../adapters/three/faceColors';
export type { ColorScheme };
export type CubeFace = 'U' | 'L' | 'F' | 'R' | 'B' | 'D';
export type CustomColorScheme = Record<CubeFace, string>;
export const CUBE_FACES: readonly CubeFace[] = ['U', 'L', 'F', 'R', 'B', 'D'] as const;
export const DEFAULT_CUSTOM_COLOR_SCHEME: Readonly<CustomColorScheme> = {
U: '#ffffff',
L: '#ff8a2a',
F: '#78ed3e',
R: '#ff3131',
B: '#3568ff',
D: '#fff34a',
};
const STORAGE_KEY = 'regrip-color-scheme';
const CUSTOM_STORAGE_KEY = 'regrip-custom-color-scheme';
function isColorScheme(value: string | null): value is ColorScheme {
return value === 'western' || value === 'japanese' || value === 'custom';
}
function loadInitialColorScheme(): ColorScheme {
try {
const stored = localStorage.getItem(STORAGE_KEY);
return isColorScheme(stored) ? stored : 'western';
} catch {
return 'western';
}
}
function loadInitialCustomColorScheme(): CustomColorScheme {
try {
const stored = localStorage.getItem(CUSTOM_STORAGE_KEY);
if (!stored) return { ...DEFAULT_CUSTOM_COLOR_SCHEME };
const parsed = JSON.parse(stored) as unknown;
if (typeof parsed !== 'object' || parsed === null) return { ...DEFAULT_CUSTOM_COLOR_SCHEME };
const scheme: CustomColorScheme = { ...DEFAULT_CUSTOM_COLOR_SCHEME };
for (const face of CUBE_FACES) {
const val = (parsed as Record<string, unknown>)[face];
if (typeof val === 'string' && /^#[0-9a-fA-F]{6}$/.test(val)) {
scheme[face] = val.toLowerCase();
}
}
return scheme;
} catch {
return { ...DEFAULT_CUSTOM_COLOR_SCHEME };
}
}
let current: ColorScheme = loadInitialColorScheme();
let currentCustom: CustomColorScheme = loadInitialCustomColorScheme();
export function getColorScheme(): ColorScheme {
return current;
}
export function setColorScheme(scheme: ColorScheme): void {
current = scheme;
try {
localStorage.setItem(STORAGE_KEY, scheme);
} catch {
// Private browsing or a full quota still keeps the in-memory selection.
}
}
export function getCustomColorScheme(): CustomColorScheme {
return { ...currentCustom };
}
export function setCustomColorScheme(updates: Partial<CustomColorScheme>): void {
currentCustom = { ...currentCustom, ...updates };
try {
localStorage.setItem(CUSTOM_STORAGE_KEY, JSON.stringify(currentCustom));
} catch {
// Keep in-memory selection.
}
}
export function resetCustomColorScheme(): void {
currentCustom = { ...DEFAULT_CUSTOM_COLOR_SCHEME };
try {
localStorage.removeItem(CUSTOM_STORAGE_KEY);
} catch {
// Keep in-memory selection.
}
}
export function customColorsToNumeric(custom: CustomColorScheme): CustomFaceColors {
const result: Record<string, number> = {};
for (const face of CUBE_FACES) {
const hex = custom[face];
if (hex) {
result[face] = parseInt(hex.replace('#', ''), 16);
}
}
return result;
}
|