122 lines
3.4 KiB
Markdown
122 lines
3.4 KiB
Markdown
# Share Intake
|
|
|
|
Share intake is the app's highest-friction capture path. It should be reliable,
|
|
reviewable, and conservative about identity matching.
|
|
|
|
## Entry Points
|
|
|
|
Flutter listener:
|
|
|
|
- `lib/features/share_intake/presentation/incoming_share_listener.dart`
|
|
|
|
Native iOS:
|
|
|
|
- `ios/Share Extension/ShareViewController.swift`
|
|
- `ios/Save Action/SaveActionViewController.swift`
|
|
- `ios/Share Extension/Info.plist`
|
|
- `ios/Save Action/Info.plist`
|
|
- `ios/Runner.xcodeproj/project.pbxproj`
|
|
|
|
Android:
|
|
|
|
- `android/app/src/main/AndroidManifest.xml`
|
|
- `receive_sharing_intent` plugin integration
|
|
|
|
Developer simulation:
|
|
|
|
- Settings -> `Simulate Share Capture`
|
|
|
|
## Pipeline
|
|
|
|
```text
|
|
native share / simulation
|
|
-> IncomingShareListener
|
|
-> SharePayloadParser
|
|
-> startShareCaptureReview
|
|
-> capture to existing profile, create profile, or save to inbox
|
|
-> LocalRepositoryShareOperations
|
|
-> LocalDataState + sync queue + optional facts/dates/signals
|
|
```
|
|
|
|
## Payload Normalization
|
|
|
|
`SharePayloadParser` normalizes:
|
|
|
|
- source app labels
|
|
- text vs URL vs text-with-URL payloads
|
|
- WhatsApp sender prefixes
|
|
- Signal sender prefixes
|
|
- source-message timestamp evidence
|
|
|
|
`SharedPayload` keeps both app-side timestamps and source-message timestamps:
|
|
|
|
- `createdAt`: normalized payload creation time
|
|
- `receivedAt`: app receive/import time
|
|
- `sharedMessageDateTime`: best-effort original message time, nullable
|
|
|
|
## Source Message Timestamp Extraction
|
|
|
|
Source: `lib/features/share_intake/domain/shared_message_datetime_extractor.dart`
|
|
|
|
The extractor tries multiple metadata-like patterns:
|
|
|
|
- bracketed chat prefixes such as `[19/05/2026, 14:30] Sender: text`
|
|
- exported chat prefixes such as `5/19/26, 2:30 PM - Sender: text`
|
|
- labelled lines such as `Received at: 19 May 2026 at 14:30`
|
|
- ISO-like timestamps
|
|
- `today at HH:mm` and `yesterday at HH:mm`
|
|
- numeric and month-name date variants
|
|
|
|
It returns `null` instead of throwing. It intentionally avoids arbitrary content
|
|
dates, for example `birthday is May 20`, because those are not message receive
|
|
times.
|
|
|
|
## Identity Matching
|
|
|
|
Matching order:
|
|
|
|
1. Existing `SourceProfileLink` by source fingerprint/user/thread metadata.
|
|
2. Exact normalized display name when exactly one profile matches.
|
|
3. Near-name conflict detection.
|
|
4. Inbox when missing, ambiguous, or risky.
|
|
|
|
Do not auto-link when evidence is weak. The inbox is the safety valve.
|
|
|
|
## Inbox Resolution
|
|
|
|
Share Inbox supports:
|
|
|
|
- resolving to an existing person
|
|
- creating a person
|
|
- editing structured draft type/text/date
|
|
- reviewing conflict candidates
|
|
- saving provenance for facts and source links
|
|
|
|
Relevant files:
|
|
|
|
- `lib/features/share_intake/presentation/share_inbox_view.dart`
|
|
- `lib/features/share_intake/presentation/share_capture_review_sheet.dart`
|
|
- `lib/app/data/relationship_repository_share.dart`
|
|
|
|
## Native iOS Notes
|
|
|
|
The repository currently contains Share Extension and Save Action target entries
|
|
in the Xcode project. The iOS Podfile still only has the `Runner` target, so
|
|
verify extension build behavior after plugin updates or Pod changes.
|
|
|
|
Physical iPhone testing is required for real chat apps. Simulators are useful
|
|
for Notes/Safari-style text and URL sharing, but not enough for WhatsApp,
|
|
iMessage, or app-specific metadata behavior.
|
|
|
|
## Tests
|
|
|
|
Useful focused tests:
|
|
|
|
```bash
|
|
flutter test test/features/share_intake
|
|
flutter test test/features/local/local_repository_test.dart
|
|
```
|
|
|
|
Add parser tests for every new source format. Add repository tests when matching,
|
|
inbox, source links, facts, or signals change.
|