f655adfbea
Migrate app code into canonical feature slices, add phone-only AI digest scheduling and review, wire local notification/background task support, and cover the flow with tests.
73 lines
1.8 KiB
Dart
73 lines
1.8 KiB
Dart
class SignalSharePayload {
|
|
const SignalSharePayload({
|
|
required this.messageText,
|
|
this.sourceDisplayName,
|
|
this.sourceUserId,
|
|
this.sourceThreadId,
|
|
});
|
|
|
|
final String messageText;
|
|
final String? sourceDisplayName;
|
|
final String? sourceUserId;
|
|
final String? sourceThreadId;
|
|
}
|
|
|
|
/// Parses raw shared text from Signal into normalized sender/message fields.
|
|
class SignalShareParser {
|
|
const SignalShareParser._();
|
|
|
|
static final RegExp _namePrefixPattern = RegExp(
|
|
r'^([^:\n]{2,80}):\s*(.+)$',
|
|
dotAll: true,
|
|
);
|
|
|
|
static SignalSharePayload parse(String raw) {
|
|
final String input = raw.trim();
|
|
if (input.isEmpty) {
|
|
return const SignalSharePayload(messageText: '');
|
|
}
|
|
|
|
final RegExpMatch? match = _namePrefixPattern.firstMatch(input);
|
|
if (match == null) {
|
|
return SignalSharePayload(messageText: input);
|
|
}
|
|
|
|
final String? senderName = _cleanSender(match.group(1));
|
|
final String messageText = match.group(2)?.trim() ?? input;
|
|
return SignalSharePayload(
|
|
messageText: messageText,
|
|
sourceDisplayName: senderName,
|
|
sourceUserId: _normalizedKey(senderName),
|
|
sourceThreadId: null,
|
|
);
|
|
}
|
|
|
|
static bool looksLikeSignalMessage(String raw) {
|
|
final String input = raw.trim();
|
|
if (input.isEmpty) {
|
|
return false;
|
|
}
|
|
return _namePrefixPattern.hasMatch(input);
|
|
}
|
|
|
|
static String? _cleanSender(String? input) {
|
|
if (input == null) {
|
|
return null;
|
|
}
|
|
final String cleaned = input.trim();
|
|
return cleaned.isEmpty ? null : cleaned;
|
|
}
|
|
|
|
static String? _normalizedKey(String? input) {
|
|
if (input == null) {
|
|
return null;
|
|
}
|
|
final String key = input
|
|
.toLowerCase()
|
|
.replaceAll(RegExp(r'[^a-z0-9]+'), ' ')
|
|
.trim()
|
|
.replaceAll(RegExp(r'\s+'), ' ');
|
|
return key.isEmpty ? null : 'signal:$key';
|
|
}
|
|
}
|