[imp]: Better search results
Finally!
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -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,
|
||||
],
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user