null
11a4c7deda
feat(chat): RichContentTextField for keyboard GIF/sticker/Bitmoji insertion, tap-to-enlarge images
...
- RichContentTextField: AppCompatEditText wrapper with OnReceiveContentListener for image/* MIME types, enables Gboard GIF/sticker/Bitmoji tabs
- ChatComponents: replace OutlinedTextField with RichContentTextField, remove ExperimentalFoundationApi opt-in, add tap-to-enlarge full-screen image viewer with aspect-ratio sizing
2026-06-24 17:37:13 -05:00
null
dbf7ae662b
chore(config): coil-gif dependency, RECORD_AUDIO permission, firestore rules allow voice type
...
- build.gradle.kts: add coil-gif 2.7.0 for animated GIF/WebP support
- AndroidManifest: RECORD_AUDIO permission + microphone feature (optional)
- firestore.rules: messages create allows 'voice' type alongside 'image', accepts durationMs field
2026-06-24 16:34:53 -05:00
null
3ad725ca8a
feat(voice+media): voice recording/playback UI, GIF/sticker support, keyboard content receiver
...
- ChatComponents: voice recording bar (mic → record → send/cancel), voice playback with MediaPlayer, GIF/WebP via coil-gif + ImageDecoderDecoder, keyboard content receiver for stickers/Bitmoji
- ConversationViewModel: sendVoice wired through
- ConversationScreen: onSendVoice passed to ChatComposer
2026-06-24 16:34:48 -05:00
null
c20745e82a
feat(voice): data layer — voice message model, sendVoiceMessage, durationMs field
...
- QuestionMessage: add durationMs, isVoice, type supports 'voice'
- ConversationRepository: sendVoiceMessage(audioBytes, durationMs)
- FirestoreConversationDataSource: sendVoiceMessage encrypts + uploads audio, decrypts durationMs
- ConversationRepositoryImpl: delegates sendVoiceMessage
2026-06-24 16:34:38 -05:00
null
e4cdbac7b1
refactor(notifications): questionId → conversationId across bubble, deep link routing, FCM handling
...
- ActiveThreadMonitor: activeQuestionId → activeConversationId, enter/leave use conversationId
- MessageBubbleController: IncomingMessageBubble uses conversationId, show/dismissFor updated
- PartnerNotificationManager: CHAT_MESSAGE routes to conversation, payload includes conversationId
- MessageBubbleOverlay: onOpen passes conversationId, pointerInput keys on conversationId
- AppMessagingService: chat_message type reads conversation_id, bubble show uses conversationId
- MainActivity: deepLinkRouteFromIntent reads conversation_id from FCM extras
2026-06-24 16:14:07 -05:00
null
c85e55a790
feat(nav): Messages replaces Question Packs in bottom bar, conversation route with deep link, Play Hub hosts Packs
...
- AppNavigation: MESSAGES + CONVERSATION composable routes, bottom bar swaps Packs for Messages
- AppRoute: MESSAGES + CONVERSATION route constants, conversation() helper, bottom nav list updated
- PlayHubScreen: Question Packs card added (moved from bottom bar)
- AnswerRevealScreen: discuss button navigates to conversation route
- DailyQuestionScreen: discuss button navigates to conversation route
2026-06-24 16:13:58 -05:00
null
33baf220e4
feat(conversations): UI — Messages inbox, conversation screen, view models, chat components
...
- MessagesInboxScreen: list of conversations with last-message preview, tap to open
- MessagesInboxViewModel: observes conversations from Firestore
- ConversationScreen: E2E-encrypted messaging with send/receive, image support
- ConversationViewModel: send message, observe messages, active conversation tracking
- ChatComponents: reusable message bubble, input bar, encrypted image rendering
2026-06-24 16:13:52 -05:00
null
db5b8a5f8a
feat(conversations): data layer — domain model, Firestore data source, repository, DI bindings
...
- Conversation model with id, type (couple_chat/question_discussion), questionId, lastMessage fields
- FirestoreConversationDataSource: create, sendMessage, observeConversations, observeMessages
- ConversationRepositoryImpl: wraps data source
- RepositoryModule: bind ConversationRepository
- FirestoreCollections: CONVERSATIONS subcollection constants
2026-06-24 16:13:45 -05:00
null
4e2c3fdf0d
fix: rate limiter bump (20/day, 100/week), firestore rules for image messages, storage rules for chat_media, gitignore ClaudeReport
...
- NotificationRateLimiter: 20 partner/day, 100/week (was 2/4 — too tight for game activity)
- firestore.rules: messages create allows type=image with mediaUrl or type=text with ciphertext
- storage.rules: chat_media path with 15MB cap
- .gitignore: ClaudeReport.md, docs/img
2026-06-24 15:20:44 -05:00
null
608ddcfc5b
feat(bubble): drag-to-dismiss zone, no auto-timeout, dismiss on conversation enter
...
- MessageBubbleOverlay: drag-to-dismiss target at bottom-center, no 12s auto-timeout (persists until read)
- MessageBubbleController: dismissFor clears bubble when its conversation is opened
- ActiveThreadMonitor: calls dismissFor on enter, clearing the bubble for that thread
2026-06-24 15:20:38 -05:00
null
adb61715fe
feat(home): partner photoUrl loaded and displayed in identity card
...
- PartnerHomeViewModel: loads partner photoUrl alongside name
- PartnerIdentityCard: shows AsyncImage when photoUrl available, fallback to initial letter
2026-06-24 15:20:32 -05:00
null
a8fbbaa286
feat(notifications): deep link routing from FCM data extras, onMessageWritten includes author name + photo
...
- MainActivity: deepLinkRouteFromIntent resolves FCM data extras to navigation routes; pendingDeepLink state for onNewIntent
- AppNavigation: LaunchedEffect waits for HOME route before navigating deep link (fixes race with onboarding)
- onMessageWritten: includes author displayName + photoUrl in notification payload
2026-06-24 15:20:24 -05:00
null
06e4d609f2
feat(chat): image picker (gallery + camera), encrypted image rendering, messenger-style avatars on consecutive bubbles
...
- QuestionDiscussionThread: gallery picker via PickVisualMedia, camera capture via FileProvider, EncryptedChatImage composable decrypts + renders, MessageAvatar with partner photo
- QuestionThreadViewModel: sendImage, loadDecryptedMedia, dailyRevealed skip for already-revealed daily questions, partner photo loading
- QuestionThreadScreen: pass loadDecryptedMedia to discussion thread
- LocalQuestionContent: pass partnerPhotoUrl to discussion thread
- file_paths.xml: cache-path for camera capture
2026-06-24 15:20:18 -05:00
null
c9aa5f1e12
feat(chat): encrypted image messages — Storage upload/download, Firestore send/load, domain model with type+mediaUrl
2026-06-24 15:20:11 -05:00
null
609ced4095
feat(notifications): FCM token registration on auth, Android 13 permission request, in-app chat bubble overlay, game results notification copy
...
- MainActivity: request POST_NOTIFICATIONS on TIRAMISU+, register FCM token when user signs in
- AppMessagingService: foreground chat messages show draggable bubble instead of OS notification
- MessageBubbleController/Overlay: new in-app chat-head that drifts over all screens, tap to open
- PartnerNotificationManager: GAME_RESULTS_READY type with proper copy, partner_finished_game maps to it
- onGameSessionUpdate: notify BOTH partners on completion (not just the non-starter), fix starter name in notification
2026-06-24 11:47:49 -05:00
null
0cb3d44f0d
fix(reveal): partner option labels, release-key read rules, thread status uppercase, session id propagation, notification deep links, and re-open guard
...
- Firestore rules: partner can read user doc (name/photo), sender can read own release key
- QuestionThread: status stored UPPERCASE to match rules (lowercase broke discussion)
- GameSessionManager: propagate auto-generated session id (empty id crashed game start)
- AnswerReveal: decrypt partner's selectedOptionTexts from option IDs (showed raw ids)
- FirestoreAnswerDataSource: tolerate Timestamp/Date in updatedAt (serverTimestamp crash)
- FirestoreReleaseKeyDataSource: tolerate PERMISSION_DENIED on existence check (sender can't read)
- QuestionThreadRepository: runCatching status update (legacy lowercase status blocked submit)
- PartnerNotificationManager: suppress notification for active thread, deep link to thread
- ActiveThreadMonitor: new class tracks which thread user is reading (suppresses own notifs)
- DesireSync/HowWell/ThisOrThat: re-open guard skips INTRO if already answered; blank sessionId guard
- AppNavigation: deep link pattern for chat notification
2026-06-24 10:02:54 -05:00
null
77208ff1e6
fix(daily-question): deterministic per-day offset replaces RANDOM(); shared DailyQuestionResolver; auth profile fallback
2026-06-23 22:55:55 -05:00
null
6d74c6acec
feat(brand): primaryMessage constant + rotator holds flagship slogan 3x longer
2026-06-23 22:39:31 -05:00
null
7923835861
docs(brand): update privacy slogan in CloserBrandCopy
2026-06-23 22:21:25 -05:00
null
9269a769be
docs(readme): update privacy slogan
2026-06-23 22:17:42 -05:00
null
06e09da596
docs(readme): add privacy slogan to header
2026-06-23 22:14:36 -05:00
null
e5c05abe90
fix(settings): partner card visual states — paired vs unpaired colors, border, avatar fallback
2026-06-23 19:35:35 -05:00
null
272c8997d0
refactor(ui): celebration overlay polish, activity screen layout, home screen streak dialog, pairing success cleanup
2026-06-23 19:26:41 -05:00
null
17d7489dd8
feat(engagement): streak milestones, celebration overlays, Together screen, avatar in notifications
2026-06-23 18:23:49 -05:00
null
d4b20a9845
feat(e2ee): encrypt date plan content; live answer observation; own-thread-answer decrypt; strict rules
2026-06-23 17:47:07 -05:00
null
039752d691
refactor(e2ee): remove v0/v1 migration paths, fail-closed decrypt, strict-only rules
2026-06-23 17:06:23 -05:00
null
17c7ed60b9
fix(nav): tab-switch routing prevents stacking tabs; fix(crash): runCatching around getUser/getCoupleForUser across 6 screens
2026-06-23 14:35:01 -05:00
null
fe1808b36c
refactor(theme): full dark mode pass — CloserPalette, Theme, Color, and all surface screens
2026-06-23 13:56:27 -05:00
null
7d3b47b3ba
fix(firestore): handle Timestamp type for lastAnsweredAt/createdAt in Android + Cloud Function
2026-06-23 12:40:00 -05:00
null
424ef0e4ab
refactor(theme): replace hardcoded colors with Material3 theme-aware composables + adaptive iOS surface color
2026-06-23 12:31:59 -05:00
null
e5c13b6b6d
feat(app-check): stable debug token via BuildConfig; feat(firestore): indexes for questions + bucket_list
2026-06-23 12:17:17 -05:00
null
6977db7600
fix(wheel-reveal): error state with retry, null-safe uid/couple, close on snapshot error
2026-06-23 11:34:46 -05:00
null
acaa8e635c
fix(challenges): null-safe activeChallenge guard; feat(this-or-that): skip question button
2026-06-23 11:31:17 -05:00
null
b854c0b391
feat(history): tappable challenge/capsule cards, deep-link to capsule detail, emoji per game type, dedicated error card; feat(nav): MEMORY_LANE_CAPSULE route
2026-06-23 11:19:14 -05:00
null
015ac8eefe
feat(challenges): abandon challenge flow; fix(play): premium lock on history; fix(memory-lane): null-safe detail state
2026-06-23 10:51:14 -05:00
null
58be8ed021
fix(game-history): disable replay on unsupported game types, clean up session title/route
2026-06-23 10:32:49 -05:00
null
755077c7ba
feat(memory-lane): edit/delete capsules, custom unlock date picker, error snackbar
2026-06-23 10:11:25 -05:00
null
9710bbc438
fix(challenges): error state snackbar, CTA routing for BOTH_COMPLETED/CHALLENGE_COMPLETE, README prem tiers
2026-06-23 10:04:53 -05:00
null
c97371a12e
feat: challenge state machine, game screen updates, state machine tests
2026-06-22 22:02:39 -05:00
null
c56dd53edd
feat: capsule/challenge data sources, game screens, wheel history + viewmodel
2026-06-22 21:38:18 -05:00
null
17403b1a75
feat: challenges, desire sync, how well, memory lane, this or that screens
2026-06-22 21:24:02 -05:00
null
3f5d7a5cc1
feat: nav, capsule data source, challenges, desire sync, question category, wheel history + viewmodel
2026-06-22 21:19:19 -05:00
null
2108d48914
feat: challenges, desire sync, how well, memory lane, play hub + viewmodel, this or that, wheel history
2026-06-22 20:46:40 -05:00
null
7db075d195
feat: navigation, answer history screen + viewmodel, answer reveal, iOS navigation & question views
2026-06-22 19:44:44 -05:00
null
125a24eb85
feat: answer reveal, auth screens, challenges, onboarding, pairing, paywall, wheel, settings, components
2026-06-22 19:18:49 -05:00
null
42706b4dc6
feat: settings screen + iOS settings views
2026-06-22 18:14:55 -05:00
null
5d3ab8385d
feat: daily questions, answer reveal, home screens, auth, analytics, DB, repositories
2026-06-22 17:45:51 -05:00
null
174e56c5a0
feat: local question content, question header, daily question illustration, iOS question/wheel views
2026-06-22 13:57:09 -05:00
null
f350c91b55
feat: question pack library screen, pack art assets, iOS question views
2026-06-22 13:45:48 -05:00
null
d96221c5c8
feat: home screen + iOS pairing views
2026-06-22 12:52:33 -05:00
null
bb119b054b
feat: home screen update, pairing views, activation illustrations
2026-06-22 11:25:21 -05:00
null
d307904ff8
feat: home screen + viewmodel, iOS home & pairing views
2026-06-22 11:14:19 -05:00
null
7d5fc11366
feat: nav routes, play hub, spin wheel screen + viewmodel, firestore rules
2026-06-22 10:53:05 -05:00
null
ecc41a77d2
feat: wheel screen, play hub, storage data source, iOS wheel/play views
2026-06-22 10:25:58 -05:00
null
b29280ba87
feat: invite flow improvements, pairing success screen, iOS pairing updates
2026-06-22 09:06:40 -05:00
null
5e16177eb2
feat: code push -- notifications, cloud functions, iOS updates
2026-06-22 08:53:23 -05:00
null
9166721282
feat: notification improvements + daily question reminder cloud function
2026-06-22 08:34:15 -05:00
null
893c88d774
feat(auth): remove anonymous sign-in, add email verification flow (batch 0.3.0)
2026-06-21 21:18:30 -05:00
null
8f47593cf5
fix: user repository cleanup, settings VM, iOS app init + settings parity
2026-06-21 17:44:56 -05:00
null
6b50e84f60
fix: onboarding flow, settings screen polish, iOS settings parity
2026-06-21 17:37:14 -05:00
null
e2fd65f070
feat: security screen, theme polish, settings navigation, build config
2026-06-21 17:25:39 -05:00
null
b720f0cf14
feat: pending invite store, iOS subscription illustration, settings theme polish
2026-06-21 17:04:40 -05:00
null
b19fc0934c
feat: paywall illustrations, subscription polish, recovery store, settings cleanup
2026-06-21 16:27:55 -05:00
null
720b52a33b
chore: firebase config, gitignore updates, build tweaks
2026-06-21 16:07:19 -05:00
null
af70280daa
feat: E2EE recovery flow, iOS parity updates, onboarding + pairing polish
2026-06-21 11:20:48 -05:00
null
62d99505c9
feat: subscription screen with clear pricing, restore, cancel instructions
2026-06-21 09:54:59 -05:00
null
dff86eb089
feat: settings polish, privacy strings, home partner state, proguard rules
2026-06-21 09:49:02 -05:00
null
26419ce08d
feat: remove email invite screen, add accept-invite rate limiting, clean up iOS pairing (v0.2.2)
2026-06-21 08:55:43 -05:00
null
a5aad4f0bf
fix(outcomes): use AutoMirrored.TrendingUp to resolve icon import/type mismatch
2026-06-21 00:07:52 -05:00
null
b70463274f
fix(home): resolve OutcomeDay import for outcome dialogs
2026-06-21 00:03:02 -05:00
null
57a3e35359
feat(outcomes): add 30/60/90 day check-in flow with baseline + reminders
2026-06-20 23:59:24 -05:00
null
535c0ce668
feat(home): surface couple streak count on Home dashboard
2026-06-20 23:47:55 -05:00
null
bc3317c65a
feat(home): add "5-minute check-in" time budget framing to daily question card
2026-06-20 23:46:28 -05:00
null
2a1e5fad10
feat(functions): add createInviteCallable and tighten invite rules
2026-06-20 23:28:20 -05:00
null
8967fd23cd
fix(crypto): define single source of truth for encryptionVersion and document v0/v2 drift risk
...
- Add EncryptionVersion.kt with constants PLAINTEXT(0), MIGRATING(1), STRICT(2)
- Route CoupleEncryptionManager through the new constants and add explicit v2 branch
- Comment acceptInviteCallable.ts:91 explaining the version and sync contract
- Add TODO in iOS FirestoreService.swift warning that iOS MVP creates v0 couples
Fixes Risk #2 from review.md.
2026-06-20 22:29:43 -05:00
null
bdd2bf27c0
feat(settings): add appearance screen with theme picker, refactor settings nav
2026-06-20 18:45:44 -05:00
null
1f777e827d
feat: add onMessageWritten cloud function, notification settings screen, user repo cleanup
2026-06-20 18:25:05 -05:00
null
4dad0e774e
refactor: update crypto, invite flow, and account screen patterns
2026-06-20 18:09:46 -05:00
null
09a2480359
refactor(android): update question thread and answer mapping patterns
2026-06-20 18:02:21 -05:00
null
2a5cd28397
refactor(android): update question flow and navigation patterns (batch 6)
2026-06-20 17:17:51 -05:00
null
38aedab962
chore: update README, screenshots, answer data source cleanup (batch v1.0.21)
2026-06-20 02:01:42 -05:00
null
9c1fbf60a0
fix: reveal screen UX and rules hardening (batch v1.0.20)
2026-06-20 01:51:02 -05:00
null
737514d18f
fix: sealed reveal flow fixes (batch v1.0.19)
2026-06-20 01:40:24 -05:00
null
8de5990230
fix: add Tink dependency, release key cleanup, rules hardening (batch v1.0.17)
2026-06-20 01:10:20 -05:00
null
84eab1825b
feat: add thread sealed answers, release key cleanup, rules hardening (batch v1.0.16)
2026-06-20 00:41:48 -05:00
null
a3993d08df
feat: implement partner-proof sealed answers (batches 1-8)
...
- UserKeyManager: per-user keypair stored in Android Keystore
- SealedAnswerEncryptor: one-time answer key, sealed:v1 ciphertext
- PendingAnswerKeyStore: local EncryptedSharedPreferences storage
- ReleaseKeyEncryptor: keybox:v1 encrypted to recipient public key
- SealedRevealManager: full reveal flow with mutual key release
- AnswerCommitment: SHA-256 commitment hash over canonical payload
- FirestoreDeviceKeyDataSource: public key CRUD
- FirestoreReleaseKeyDataSource: release key CRUD
- FirestoreAnswerDataSource: sealed answer writes with schemaVersion=3
- FirestoreCollections: sealed answer and release key paths
- firestore.rules: ownership, immutability, timing, prefix enforcement
- HomeViewModel: sealed answer state integration
- AnswerRevealScreen/ViewModel: sealed reveal flow with UX states
- CloserApp: initialize UserKeyManager on startup
- LocalAnswer model: schemaVersion field
- Unit tests: SealedAnswerEncryptor, ReleaseKeyEncryptor, AnswerCommitment
- Crypto test vectors: docs/crypto/sealed-answer-test-vectors.json
- .gitignore: add partner-proof build plan
2026-06-20 00:23:58 -05:00
null
521989ec44
fix: remove duplicate comparison in StreakCalculator (batch v1.0.14)
2026-06-19 23:53:50 -05:00
null
195dfb5a0a
refactor: replace PendingActionCard.action lambda with HomeActionTarget (batch v1.0.13)
...
- PendingActionCard now uses target enum instead of lambda
- HomeScreen routes pending actions through toActionHandler
- Remove onPendingAction callback, simplify HomeCallbacks
- Fix WeeklyRecapGenerator filter logic (remove always-true || true)
2026-06-19 23:51:47 -05:00
null
0e75b3b536
feat: add gentle reminder callable and wire into HomeViewModel (batch v1.0.12)
...
- GENTLE_REMINDER notification type with warm copy
- sendGentleReminderCallable Cloud Function
- HomeViewModel.sendGentleReminder() calls function, shows snackbar
- Snackbar event consumed after display
2026-06-19 23:47:01 -05:00
null
7dc14af627
feat: wire retention signals into HomeViewModel (batch v1.0.11)
...
- Replace TODO placeholders with real data source calls
- Add hasWaitingGame, hasActiveChallenge, hasUpcomingDatePlan, hasUnlockedCapsule, weeklyRecapReady
- Parallel async fetches in loadHome(), failures default to false
- FirestoreCapsuleDataSource.getCapsules() for capsule status checks
2026-06-19 23:42:54 -05:00
null
89213445b9
fix: add coEvery import and re-set settings flow in PartnerNotificationManagerTest (batch v1.0.10)
2026-06-19 22:52:27 -05:00
null
fa501089f2
test: add unit tests for retention features (batch v1.0.10)
...
- PartnerNotificationManagerTest: notification creation, type mapping, deep links
- build.gradle.kts: enable Robolectric and default return values for unit tests
- AppRoute: fix NPE in asRouteArg when android.net.Uri is stubbed on test classpath
2026-06-19 22:51:08 -05:00
null
5698e5436a
feat: add memory capsule generator for saving meaningful moments (batch v1.0.9)
2026-06-19 22:47:36 -05:00
null
a500b86621
chore: update UI copy to match retention tone guidelines (batch v1.0.9)
2026-06-19 22:46:07 -05:00
null
3575af1b6f
feat: add date suggestion engine for date planning loop (batch v1.0.8)
2026-06-19 22:44:33 -05:00
null
9db3c35f8d
feat: add follow-up prompts after reveals (batch v1.0.7)
2026-06-19 22:43:40 -05:00
null
9040b97eb2
feat: add challenge loop state machine with 6 states and copy (batch v1.0.6)
...
- ChallengeState data model with 6 states: not started, started, waiting, both complete, missed, complete
- ChallengeStateMachine: pure Kotlin, configurable missed-day behavior
- 12 unit tests covering all states and edge cases
- Fix pre-existing missing import in AnswerRevealViewModel
2026-06-19 22:41:43 -05:00
null
b1b35891c9
feat: add HomePriorityEngine and weekly recap generator (batch v1.0.5)
...
- HomePriorityEngine: 13-level priority system, primary + secondary CTA
- HomeScreen: add onNavigate to HomeContent, fix compile error
- WeeklyRecapGenerator: pure logic, counts, favorite category, suggested pack
- Privacy: hidden answers excluded from recap counts
- Unit tests for both engine and recap generator
2026-06-19 22:37:47 -05:00
null
935aee5ec5
feat: add partner-trigger notifications with rate limits and quiet hours (batch v1.0.4)
...
- PartnerNotificationManager: 6 notification types, static copy only
- NotificationRateLimiter: max 2 partner/day, 1 reminder/day, 4/week
- QuietHoursManager: default 10pm-8am, user-configurable
- NotificationChannelSetup: partner-actions channel (HIGH importance)
- PartnerNotificationScheduler: routes FCM events through manager
- AppMessagingService: safe static copy, drops unknown types
- Deep link navigation for all notification targets
- 3 test files covering quiet hours, rate limits, notification types
2026-06-19 22:34:42 -05:00
null
9828e73171
feat: add 'Waiting for you' unfinished business dashboard (batch v1.0.3)
...
- PendingActionCard data class with priority-ordered cards
- 6 card types: reveal ready, partner answered, game, challenge, date, capsule
- Max 3 cards, highest priority first, deep link to correct screen
- Placeholder guards for game/challenge/date/capsule (wired in later batches)
- Compact cards with purple/pink palette, no private text leaked
2026-06-19 22:31:11 -05:00