feat: recent searches history in SearchScreen (U3) (#47)

This commit was merged in pull request #47.
This commit is contained in:
Bot of Thomas Güttler
2026-05-14 10:51:28 +02:00
parent efd5a1fc17
commit 132b6aeb9a
12 changed files with 236 additions and 24 deletions
+12 -1
View File
@@ -234,6 +234,13 @@ class Drafts extends Table {
TextColumn get imapServerId => text().nullable()();
}
@DataClassName('SearchHistoryRow')
class SearchHistoryEntries extends Table {
IntColumn get id => integer().autoIncrement()();
TextColumn get query => text()();
DateTimeColumn get searchedAt => dateTime()();
}
@DataClassName('UndoActionRow')
class UndoActions extends Table {
TextColumn get id => text()();
@@ -263,13 +270,14 @@ class UndoActions extends Table {
SyncLogMailboxes,
SyncHealth,
UndoActions,
SearchHistoryEntries,
],
)
class AppDatabase extends _$AppDatabase {
AppDatabase([QueryExecutor? executor]) : super(executor ?? _openConnection());
@override
int get schemaVersion => 26;
int get schemaVersion => 27;
Future<void> _createEmailFts() async {
await customStatement('''
@@ -492,6 +500,9 @@ class AppDatabase extends _$AppDatabase {
SELECT rowid, subject, preview, from_json FROM emails
''');
}
if (from < 27) {
await m.createTable(searchHistoryEntries);
}
},
);
}
@@ -0,0 +1,57 @@
import 'package:drift/drift.dart';
import 'package:sharedinbox/core/repositories/search_history_repository.dart';
import 'package:sharedinbox/data/db/database.dart';
class SearchHistoryRepositoryImpl implements SearchHistoryRepository {
SearchHistoryRepositoryImpl(this._db);
final AppDatabase _db;
static const _maxEntries = 10;
@override
Future<List<String>> getRecentSearches() async {
final rows = await (_db.select(_db.searchHistoryEntries)
..orderBy([(t) => OrderingTerm.desc(t.searchedAt)])
..limit(_maxEntries))
.get();
return rows.map((r) => r.query).toList();
}
@override
Future<void> saveSearch(String query) async {
final trimmed = query.trim();
if (trimmed.isEmpty) return;
await _db.transaction(() async {
// Remove existing entry for same query (deduplication).
await (_db.delete(_db.searchHistoryEntries)
..where((t) => t.query.equals(trimmed)))
.go();
await _db.into(_db.searchHistoryEntries).insert(
SearchHistoryEntriesCompanion.insert(
query: trimmed,
searchedAt: DateTime.now(),
),
);
// Prune to the most recent _maxEntries.
final keepIds = await (_db.select(_db.searchHistoryEntries)
..orderBy([(t) => OrderingTerm.desc(t.searchedAt)])
..limit(_maxEntries))
.map((r) => r.id)
.get();
if (keepIds.isNotEmpty) {
await (_db.delete(_db.searchHistoryEntries)
..where((t) => t.id.isNotIn(keepIds)))
.go();
}
});
}
@override
Future<void> clearHistory() async {
await _db.delete(_db.searchHistoryEntries).go();
}
}