hogar compartido: colaboracion entre cuentas sobre Firestore

CloudKit sincroniza la base privada de un Apple ID: ni llega a Android ni deja
que dos cuentas editen el mismo plan (CKShare sigue sin existir en SwiftData).
El contenido de un hogar pasa por tanto a Firestore, y un dispositivo que entra
en un hogar construye el store local sin CloudKit — dos espejos escribiendo los
mismos objetos se pelean, que es justo lo que ya obligó a apagar el sync por
iCloud KV.

SwiftData sigue siendo el store local y el modo offline; HouseholdSyncService es
lo unico que habla con la red. Detecta cambios comparando una huella del
contenido de cada documento con la ultima sincronizada (el "shadow"), asi que no
hace falta instrumentar con updatedAt las treinta vistas que mutan modelos. Los
borrados van como tombstone: un borrado duro volveria desde cualquier miembro
que estuviera sin conexion.

Semanas y slots usan id derivado del contenido (2026-09-14, 5-dinner) para que
dos miembros que abren la misma semana escriban el mismo documento en vez de
crear dos, y para que los conflictos se resuelvan por slot y no por semana.

Incluye reglas de seguridad (solo miembros; los codigos de invitacion se pueden
leer por id pero no listar), pantalla de hogar en Ajustes con Sign in with Apple,
invitacion por codigo de 6 caracteres sin vocales ni 0/O/1/I, y la eleccion al
unirse entre llevarse los platos propios o adoptar los del hogar.

Fuera de esta fase: fotos de platos (necesitan Storage) y el cliente Android.

Refs #33

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013su1ttRiMeMYxkZJ1Y3246
This commit is contained in:
alexandrev-tibco
2026-09-12 13:00:38 +02:00
parent 66128e7a5c
commit 163fd6026a
22 changed files with 2261 additions and 8 deletions
@@ -478,3 +478,40 @@
"week_schedule_warning_confirm" = "Remove anyway";
"toast_week_schedule_updated" = "Week updated";
"toast_week_schedule_reset" = "Week back to your general settings";
/* Hogar compartido (2.2) */
"household_title" = "Shared household";
"household_section" = "Household";
"household_settings_footer" = "Plan the week together, each person from their own account. Works from Android too.";
"household_intro" = "A household lets several people plan the same week, sharing dishes and the shopping list.";
"household_sign_in_footer" = "Signing in is what makes sharing possible. Your dishes stay yours: nobody outside your household sees them.";
"household_create_section" = "Create a household";
"household_create" = "Create household";
"household_name_placeholder" = "Household name (e.g. Home)";
"household_create_footer" = "Your current dishes, tags and weeks become the household's starting point.";
"household_create_premium_footer" = "Creating a household is Premium. Whoever you invite doesn't have to pay.";
"household_join_section" = "Join a household";
"household_join" = "Join with code";
"household_code_placeholder" = "Invite code";
"household_join_footer" = "Ask whoever created the household for the code. It expires after 7 days.";
"household_join_choice_title" = "What about your dishes?";
"household_join_choice_message" = "You can bring the dishes and weeks you already have into this household, or start with the household's own.";
"household_join_choice_merge" = "Bring my dishes";
"household_join_choice_replace" = "Use the household's only";
"household_members_section" = "Members";
"household_member_you" = "you";
"household_member_unnamed" = "Unnamed";
"household_invite_section" = "Invitation";
"household_invite_footer" = "Share this code with whoever you want planning with you.";
"household_invite_share" = "Join my MealMood household with the code %@ — https://mealmood.app";
"household_invite_expires" = "Expires on %@";
"household_invite_regenerate" = "Generate a new code";
"household_leave" = "Leave household";
"household_leave_confirm_title" = "Leave the household?";
"household_leave_confirm_message" = "You'll stop seeing and editing the household's dishes and weeks on this device.";
"household_leave_confirm_confirm" = "Leave";
"household_relaunch_needed" = "Quit and reopen MealMood to finish the change.";
"household_error_not_signed_in" = "Sign in before creating or joining a household.";
"household_error_no_household" = "This device doesn't belong to a household.";
"household_error_invalid_code" = "That code doesn't exist.";
"household_error_expired_code" = "That code has expired. Ask for a new one.";