Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b116b5f9b5 |
@@ -6,8 +6,40 @@ import 'package:drift/native.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
|
||||
import 'package:sharedinbox/core/models/email.dart';
|
||||
|
||||
part 'database.g.dart';
|
||||
|
||||
// ── TypeConverters ────────────────────────────────────────────────────────────
|
||||
|
||||
class EmailAddressListConverter
|
||||
extends TypeConverter<List<EmailAddress>, String> {
|
||||
const EmailAddressListConverter();
|
||||
|
||||
@override
|
||||
List<EmailAddress> fromSql(String fromDb) {
|
||||
final list = jsonDecode(fromDb) as List<dynamic>;
|
||||
return list
|
||||
.map((e) => EmailAddress.fromJson(e as Map<String, dynamic>))
|
||||
.toList();
|
||||
}
|
||||
|
||||
@override
|
||||
String toSql(List<EmailAddress> value) =>
|
||||
jsonEncode(value.map((e) => e.toJson()).toList());
|
||||
}
|
||||
|
||||
class StringListConverter extends TypeConverter<List<String>, String> {
|
||||
const StringListConverter();
|
||||
|
||||
@override
|
||||
List<String> fromSql(String fromDb) =>
|
||||
List<String>.from(jsonDecode(fromDb) as List);
|
||||
|
||||
@override
|
||||
String toSql(List<String> value) => jsonEncode(value);
|
||||
}
|
||||
|
||||
// ── Tables ────────────────────────────────────────────────────────────────────
|
||||
|
||||
class Accounts extends Table {
|
||||
@@ -123,11 +155,14 @@ class Threads extends Table {
|
||||
IntColumn get messageCount => integer().withDefault(const Constant(1))();
|
||||
BoolColumn get hasUnread => boolean().withDefault(const Constant(false))();
|
||||
BoolColumn get isFlagged => boolean().withDefault(const Constant(false))();
|
||||
// JSON-encoded List<{name,email}>
|
||||
TextColumn get participantsJson => text().withDefault(const Constant('[]'))();
|
||||
TextColumn get participantsJson => text()
|
||||
.withDefault(const Constant('[]'))
|
||||
.map(const EmailAddressListConverter())();
|
||||
TextColumn get preview => text().nullable()();
|
||||
TextColumn get latestEmailId => text()();
|
||||
TextColumn get emailIdsJson => text().withDefault(const Constant('[]'))();
|
||||
TextColumn get emailIdsJson => text()
|
||||
.withDefault(const Constant('[]'))
|
||||
.map(const StringListConverter())();
|
||||
|
||||
@override
|
||||
Set<Column> get primaryKey => {accountId, mailboxPath, id};
|
||||
@@ -411,10 +446,18 @@ class AppDatabase extends _$AppDatabase {
|
||||
preview: Value(latest.preview),
|
||||
latestEmailId: latest.id,
|
||||
emailIdsJson: Value(
|
||||
jsonEncode(threadEmails.map((e) => e.id).toList()),
|
||||
threadEmails.map((e) => e.id).toList(),
|
||||
),
|
||||
participantsJson: Value(
|
||||
latest.fromJson,
|
||||
(jsonDecode(latest.fromJson) as List<dynamic>)
|
||||
.map(
|
||||
(e) => EmailAddress(
|
||||
name:
|
||||
(e as Map<String, dynamic>)['name'] as String?,
|
||||
email: e['email'] as String,
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
), // Good enough for migration
|
||||
),
|
||||
);
|
||||
|
||||
@@ -92,18 +92,6 @@ class EmailRepositoryImpl implements EmailRepository {
|
||||
}
|
||||
|
||||
model.EmailThread _threadRowToModel(ThreadRow row) {
|
||||
List<model.EmailAddress> parseAddresses(String json) {
|
||||
final list = jsonDecode(json) as List<dynamic>;
|
||||
return list
|
||||
.map(
|
||||
(e) => model.EmailAddress(
|
||||
name: (e as Map<String, dynamic>)['name'] as String?,
|
||||
email: e['email'] as String,
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
}
|
||||
|
||||
return model.EmailThread(
|
||||
threadId: row.id,
|
||||
accountId: row.accountId,
|
||||
@@ -113,10 +101,10 @@ class EmailRepositoryImpl implements EmailRepository {
|
||||
messageCount: row.messageCount,
|
||||
hasUnread: row.hasUnread,
|
||||
isFlagged: row.isFlagged,
|
||||
participants: parseAddresses(row.participantsJson),
|
||||
participants: row.participantsJson,
|
||||
preview: row.preview,
|
||||
latestEmailId: row.latestEmailId,
|
||||
emailIds: List<String>.from(jsonDecode(row.emailIdsJson) as List),
|
||||
emailIds: row.emailIdsJson,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -156,13 +144,11 @@ class EmailRepositoryImpl implements EmailRepository {
|
||||
|
||||
// Collect unique participants across the whole thread.
|
||||
final seen = <String>{};
|
||||
final participants = <Map<String, dynamic>>[];
|
||||
final participants = <model.EmailAddress>[];
|
||||
for (final e in threadEmails) {
|
||||
final from = jsonDecode(e.fromJson) as List<dynamic>;
|
||||
for (final a in from.cast<Map<String, dynamic>>()) {
|
||||
final email = a['email'] as String;
|
||||
if (seen.add(email)) {
|
||||
participants.add({'name': a['name'], 'email': email});
|
||||
for (final a in _parseAddresses(e.fromJson)) {
|
||||
if (seen.add(a.email)) {
|
||||
participants.add(a);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -177,12 +163,10 @@ class EmailRepositoryImpl implements EmailRepository {
|
||||
messageCount: Value(threadEmails.length),
|
||||
hasUnread: Value(threadEmails.any((e) => !e.isSeen)),
|
||||
isFlagged: Value(threadEmails.any((e) => e.isFlagged)),
|
||||
participantsJson: Value(jsonEncode(participants)),
|
||||
participantsJson: Value(participants),
|
||||
preview: Value(latest.preview),
|
||||
latestEmailId: latest.id,
|
||||
emailIdsJson: Value(
|
||||
jsonEncode(threadEmails.map((e) => e.id).toList()),
|
||||
),
|
||||
emailIdsJson: Value(threadEmails.map((e) => e.id).toList()),
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -2708,18 +2692,6 @@ class EmailRepositoryImpl implements EmailRepository {
|
||||
}
|
||||
|
||||
model.Email _toModel(Email row) {
|
||||
List<model.EmailAddress> parseAddresses(String json) {
|
||||
final list = jsonDecode(json) as List<dynamic>;
|
||||
return list
|
||||
.map(
|
||||
(e) => model.EmailAddress(
|
||||
name: (e as Map<String, dynamic>)['name'] as String?,
|
||||
email: e['email'] as String,
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
}
|
||||
|
||||
return model.Email(
|
||||
id: row.id,
|
||||
accountId: row.accountId,
|
||||
@@ -2728,9 +2700,9 @@ class EmailRepositoryImpl implements EmailRepository {
|
||||
subject: row.subject,
|
||||
sentAt: row.sentAt,
|
||||
receivedAt: row.receivedAt,
|
||||
from: parseAddresses(row.fromJson),
|
||||
to: parseAddresses(row.toAddresses),
|
||||
cc: parseAddresses(row.ccJson),
|
||||
from: _parseAddresses(row.fromJson),
|
||||
to: _parseAddresses(row.toAddresses),
|
||||
cc: _parseAddresses(row.ccJson),
|
||||
preview: row.preview,
|
||||
isSeen: row.isSeen,
|
||||
isFlagged: row.isFlagged,
|
||||
@@ -2766,6 +2738,18 @@ class EmailRepositoryImpl implements EmailRepository {
|
||||
}
|
||||
}
|
||||
|
||||
List<model.EmailAddress> _parseAddresses(String json) {
|
||||
final list = jsonDecode(json) as List<dynamic>;
|
||||
return list
|
||||
.map(
|
||||
(e) => model.EmailAddress(
|
||||
name: (e as Map<String, dynamic>)['name'] as String?,
|
||||
email: e['email'] as String,
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
}
|
||||
|
||||
List<model.EmailAttachment> _parseAttachments(String json) {
|
||||
final list = jsonDecode(json) as List<dynamic>;
|
||||
return list
|
||||
|
||||
@@ -332,7 +332,7 @@ void main() {
|
||||
messageCount: const Value(2),
|
||||
hasUnread: const Value(true),
|
||||
latestEmailId: 'acc-1:2',
|
||||
emailIdsJson: const Value('["acc-1:1", "acc-1:2"]'),
|
||||
emailIdsJson: const Value(['acc-1:1', 'acc-1:2']),
|
||||
),
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user