The web studio grew a CLASSIC VIVIDIPES sim (Classic Chrome's blue row spliced to Velvia's red and green) and an FX MONOCHROME switch; both are written up here with the exact matrices, anchors and the checks they have to pass before they count as ported.
5.7 KiB
Ghi chú port web → Android: sim CLASSIC VIVIDIPES + chip FX MONOCHROME
Nguồn: web studio docker/frontend (nhánh recipes-web), commit d7d7be2 (sim mới) và
4d0d441 (chip FX). Việc dưới đây là port sang app Android (src/, nhánh này).
Đối chiếu: src/ giữa recipes-web và feat/vision-camera-v5 chỉ khác
src/components/RecipeCreateModal.tsx (+9 dòng) — nên port gần như là chép y nguyên.
Số dòng dưới đây tính theo nhánh này.
1. Sim mới CLASSIC VIVIDIPES
Ghép tại dòng blue: giữ nguyên dòng blue của classic-chrome, lấy dòng R/G của velvia.
Sửa 4 file:
src/types/index.ts:65—BaseFilter: thêm'classic-vivid'.src/utils/colorUtils.ts— thêm nhánh ngay sau nhánhclassic-chrome(dòng 111):} else if (baseFilter === 'classic-vivid') { // Classic Vivid: the Classic Chrome blue row kept verbatim — skies stay the // same muted teal/cyan — with the red and green rows taken from Velvia, so // everything that is not blue reads loud. matrix = [ 1.3895, -0.2540, -0.0256, 0, -0.0550, // R — velvia -0.0772, 1.2355, -0.0261, 0, -0.0661, // G — velvia 0.0652, 0.3973, 0.5575, 0, -0.0100, // B — classic-chrome (nguyên bản) 0, 0, 0, 1, 0, ];src/utils/defaultRecipes.ts:43—FILM_SIMS, thêm ngay sausim-classic-chrome:{ id: 'sim-classic-vivid', name: 'CLASSIC VIVIDIPES', baseFilter: 'classic-vivid', adjustments: { ...DEFAULT_ADJUSTMENTS } },src/utils/toneShader.ts:190—FILM_TONE, cạnh'classic-chrome':(Dìm shadow thuộc về stock chứ không thuộc dòng ma trận → đi kèm. Bỏ dòng này nếu muốn VIVIDIPES không dìm shadow.)'classic-vivid': { sh: -0.28 },
Không phải sửa gì thêm: chip PHOTO STYLE (AdjustmentPanel.tsx groupDefs.style), TopBar
(activeRecipe.name) và picker trong RecipeCreateModal.tsx đều map từ FILM_SIMS.
Kiểm chứng: strip PHOTO STYLE có 10 sim; chọn CLASSIC VIVIDIPES → look khác cả
CLASSIC CHRIPES lẫn VELVIPES; CLASSIC CHRIPES vẫn nguyên vẹn cạnh nó.
2. Chip MONOCHROME ở tab FX (filters)
Đây là công tắc, không phải một look: bật thì đổi baseFilter sang monochrome, tắt thì
trả lại đúng cái ảnh đang mặc (kể cả tên sim). Không được đụng adjustments — knob chỉnh
trong lúc đang bật phải sống sót.
Web: docker/frontend/src/App.tsx — monoPrev ref + toggleMono, chip mono đứng đầu
case 'fx', active: monoOn với monoOn = recipe.baseFilter === 'monochrome'.
Android cần 2 chỗ:
a. src/components/AdjustmentPanel.tsx — case 'filters' (dòng 888):
case 'filters':
return chipRow([
{ key: 'mono', label: 'MONOCHROME', active: monoOn, amberValue: monoOn, onPress: onToggleMono },
...paramChips(paramDefs.filters),
]);
- thêm 2 prop vào
interface AdjustmentPanelProps:monoOn: boolean;vàonToggleMono: () => void; - truyền từ
App.tsxchỗ render<AdjustmentPanel … />(App.tsx:1929cócurrentBaseFilter,onSelectRecipe— đặt cạnh đó).
b. App.tsx — Android giữ adjustments là state riêng (không nằm trong selectedRecipe),
nên công tắc chỉ chạm selectedRecipe:
// FX's MONOCHROME switch: not a look of its own — it swaps the base filter for
// the mono stock and swaps right back. Adjustments are never touched.
const monoOn = selectedRecipe?.baseFilter === 'monochrome';
const monoPrevRef = useRef<Recipe | null>(null);
const handleToggleMono = () => {
commit(true, () => {
if (selectedRecipe?.baseFilter === 'monochrome') {
const back = monoPrevRef.current ?? filmSimToRecipe(FILM_SIMS.find((f) => f.id === 'sim-provia')!);
setSelectedRecipe(back);
} else {
monoPrevRef.current = selectedRecipe;
setSelectedRecipe({
...(selectedRecipe ?? filmSimToRecipe(FILM_SIMS[0])),
id: 'mono',
name: 'MONOCHROME',
baseFilter: 'monochrome',
});
}
});
};
Lưu ý:
commit(true, …)(dòng 739) để công tắc vào undo stack như mọi edit khác —handleResetAlldùng đúng cách này.Lookđã córecipe→ UNDO tự trả lại đúngbaseFiltercũ, không cần state phụ nào khác.id: 'mono'không trùng sim nào nên khi bật, chip PHOTO STYLE không còn sáng tên sim cũ (groupDefs.style.valuetính từcurrentRecipeIdso vớiFILM_SIMS).- Tắt khi
monoPrevRefrỗng (ví dụ vào monochrome bằng cách chọn sim ACRIPES, không qua công tắc) → rơi về PROVIA, tức là "tắt là có màu", không phải về đen trắng.
Kiểm chứng: bật → ảnh xám (mọi pixel R=G=B; chỉ lệch khi WB khác 5500K hoặc tint khác 0);
tắt → ảnh trở lại y hệt trước khi bật (so hash pixel); đổi CONTRAST trong lúc bật/tắt →
giá trị vẫn giữ; UNDO một nhịp → về màu, chip trở lại trạng thái tắt.
3. Test web đã chạy (tham chiếu — nằm trong scratchpad của agent, không nằm trong repo)
sim-vivid-test.cjs— 9/0: chip có mặt, strip đủ 10 sim, chọn được, render khác cả CHRIPES lẫn VELVIPES.fx-mono-test.cjs— 15/0: đo trực tiếp kênh màu trên pixel preview (spread>25khi màu,<=6khi mono), hash quay lại y hệt khi tắt, CONTRAST sống sót, UNDO gỡ mono.- Regression web quanh 2 thay đổi:
panel,layout,fonts 27/0,create 52/0,share 22/0,photo-save 19/0,redo 30/0,accent-brand— tất cả xanh.