[imp]: Better search results

Finally!
This commit is contained in:
nahnah
2026-02-14 22:24:06 +00:00
parent 4b115acf14
commit 570d8d0e0c
3 changed files with 73 additions and 35 deletions
+23 -33
View File
@@ -513,7 +513,8 @@ class AppProvider extends ChangeNotifier {
String query, {
RepositoriesProvider? repositoriesProvider,
}) async {
if (query.trim().isEmpty) {
final trimmedQuery = query.trim();
if (trimmedQuery.isEmpty) {
_searchResults = [];
_searchQuery = '';
notifyListeners();
@@ -521,55 +522,44 @@ class AppProvider extends ChangeNotifier {
}
// Prevent duplicate searches for the same query
if (_searchQuery == query && _searchState == LoadingState.loading) {
if (_searchQuery == trimmedQuery && _searchState == LoadingState.loading) {
return;
}
_searchQuery = query;
_searchQuery = trimmedQuery;
_searchState = LoadingState.loading;
_searchError = null;
notifyListeners();
try {
final combined = <String, FDroidApp>{};
// Search in custom repositories from database
final enabledRepoUrls = <String>{};
if (repositoriesProvider != null) {
if (repositoriesProvider.repositories.isEmpty &&
!repositoriesProvider.isLoading) {
await repositoriesProvider.loadRepositories();
}
// For each enabled custom repo, search in database
final customRepos = repositoriesProvider.enabledRepositories;
if (customRepos.isNotEmpty) {
// Search from database for custom repos (they should be imported there)
for (final customRepo in customRepos) {
try {
// Search in database - results should be there if repo was previously imported
final results = await _apiService.searchAppsFromRepositoryUrl(
query,
customRepo.url,
);
for (final app in results) {
combined[app.packageName] = app;
}
} catch (e) {
debugPrint('Error searching custom repo ${customRepo.name}: $e');
}
}
enabledRepoUrls.addAll(
repositoriesProvider.enabledRepositories.map((repo) => repo.url),
);
}
final dbResults = await _apiService.searchAppsDatabaseOnly(trimmedQuery);
final filteredResults = dbResults.where((app) {
if (enabledRepoUrls.isEmpty) {
return true;
}
}
// Official F-Droid search as fallback/merge
final officialResults = await _apiService.searchApps(query);
for (final app in officialResults) {
combined.putIfAbsent(app.packageName, () => app);
}
final repoUrl = app.repositoryUrl ?? '';
if (repoUrl == 'https://f-droid.org/repo') {
return true;
}
// Sort results alphabetically for stability
_searchResults = combined.values.toList()
..sort((a, b) => a.name.toLowerCase().compareTo(b.name.toLowerCase()));
return enabledRepoUrls.contains(repoUrl);
}).toList();
_searchResults = filteredResults;
_searchState = LoadingState.success;
} catch (e) {
_searchError = e.toString();
+41 -2
View File
@@ -590,6 +590,8 @@ class DatabaseService {
final searchTerm = '%${query.toLowerCase()}%';
final exactQuery = query.toLowerCase();
final startsWithTerm = '${query.toLowerCase()}%';
final normalizedQuery = query.toLowerCase().replaceAll('-', '');
final normalizedTerm = '%$normalizedQuery%';
// Search apps from this specific repository with weighted scoring
final appMaps = await db.rawQuery(
@@ -597,16 +599,21 @@ class DatabaseService {
SELECT DISTINCT a.*, r.url as repository_url,
CASE
WHEN LOWER(a.name) = ? THEN 10000
WHEN REPLACE(LOWER(a.name), '-', '') = ? THEN 9000
WHEN LOWER(a.name) LIKE ? THEN 5000
WHEN REPLACE(LOWER(a.name), '-', '') LIKE ? THEN 3000
WHEN LOWER(a.name) LIKE ? THEN 1000
WHEN LOWER(a.summary) LIKE ? THEN 100
WHEN REPLACE(LOWER(a.summary), '-', '') LIKE ? THEN 75
WHEN LOWER(a.description) LIKE ? THEN 50
WHEN REPLACE(LOWER(a.description), '-', '') LIKE ? THEN 40
WHEN EXISTS (
SELECT 1 FROM $_appCategoriesTable ac
WHERE ac.package_name = a.package_name
AND LOWER(ac.category) LIKE ?
) THEN 25
WHEN LOWER(a.package_name) LIKE ? THEN 10
WHEN REPLACE(LOWER(a.package_name), '-', '') LIKE ? THEN 8
ELSE 1
END as search_score
FROM $_appsTable a
@@ -614,25 +621,38 @@ class DatabaseService {
LEFT JOIN $_appCategoriesTable ac ON a.package_name = ac.package_name
WHERE a.repository_id = ?
AND (LOWER(a.name) LIKE ?
OR REPLACE(LOWER(a.name), '-', '') LIKE ?
OR LOWER(a.summary) LIKE ?
OR REPLACE(LOWER(a.summary), '-', '') LIKE ?
OR LOWER(a.description) LIKE ?
OR REPLACE(LOWER(a.description), '-', '') LIKE ?
OR LOWER(a.package_name) LIKE ?
OR REPLACE(LOWER(a.package_name), '-', '') LIKE ?
OR LOWER(ac.category) LIKE ?)
ORDER BY search_score DESC, a.name ASC
''',
[
exactQuery,
normalizedQuery,
startsWithTerm,
normalizedTerm,
searchTerm,
searchTerm,
normalizedTerm,
searchTerm,
normalizedTerm,
searchTerm,
searchTerm,
searchTerm,
normalizedTerm,
repositoryId,
searchTerm,
normalizedTerm,
searchTerm,
normalizedTerm,
searchTerm,
normalizedTerm,
searchTerm,
normalizedTerm,
searchTerm,
],
);
@@ -695,44 +715,63 @@ class DatabaseService {
final searchTerm = '%${query.toLowerCase()}%';
final exactQuery = query.toLowerCase();
final startsWithTerm = '${query.toLowerCase()}%';
final normalizedQuery = query.toLowerCase().replaceAll('-', '');
final normalizedTerm = '%$normalizedQuery%';
final appMaps = await db.rawQuery(
'''
SELECT DISTINCT a.*, r.url as repository_url,
CASE
WHEN LOWER(a.name) = ? THEN 10000
WHEN REPLACE(LOWER(a.name), '-', '') = ? THEN 9000
WHEN LOWER(a.name) LIKE ? THEN 5000
WHEN REPLACE(LOWER(a.name), '-', '') LIKE ? THEN 3000
WHEN LOWER(a.name) LIKE ? THEN 1000
WHEN LOWER(a.summary) LIKE ? THEN 100
WHEN REPLACE(LOWER(a.summary), '-', '') LIKE ? THEN 75
WHEN LOWER(a.description) LIKE ? THEN 50
WHEN REPLACE(LOWER(a.description), '-', '') LIKE ? THEN 40
WHEN EXISTS (
SELECT 1 FROM $_appCategoriesTable ac
WHERE ac.package_name = a.package_name
AND LOWER(ac.category) LIKE ?
) THEN 25
WHEN LOWER(a.package_name) LIKE ? THEN 10
WHEN REPLACE(LOWER(a.package_name), '-', '') LIKE ? THEN 8
ELSE 1
END as search_score
FROM $_appsTable a
LEFT JOIN $_repositoriesTable r ON a.repository_id = r.id
LEFT JOIN $_appCategoriesTable ac ON a.package_name = ac.package_name
WHERE LOWER(a.name) LIKE ?
OR REPLACE(LOWER(a.name), '-', '') LIKE ?
OR LOWER(a.summary) LIKE ?
OR REPLACE(LOWER(a.summary), '-', '') LIKE ?
OR LOWER(a.description) LIKE ?
OR REPLACE(LOWER(a.description), '-', '') LIKE ?
OR LOWER(a.package_name) LIKE ?
OR REPLACE(LOWER(a.package_name), '-', '') LIKE ?
OR LOWER(ac.category) LIKE ?
ORDER BY search_score DESC, a.name ASC
''',
[
exactQuery,
normalizedQuery,
startsWithTerm,
normalizedTerm,
searchTerm,
searchTerm,
normalizedTerm,
searchTerm,
normalizedTerm,
searchTerm,
searchTerm,
normalizedTerm,
searchTerm,
normalizedTerm,
searchTerm,
normalizedTerm,
searchTerm,
searchTerm,
normalizedTerm,
searchTerm,
searchTerm,
],
+9
View File
@@ -676,6 +676,15 @@ class FDroidApiService {
}
}
/// Searches for apps using the local database only
Future<List<FDroidApp>> searchAppsDatabaseOnly(String query) async {
try {
return await _databaseService.searchApps(query);
} catch (e) {
throw Exception('Error searching apps in database: $e');
}
}
/// Searches for apps from a specific custom repository using database
Future<List<FDroidApp>> searchAppsFromRepositoryUrl(
String query,