Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 16 additions & 64 deletions packages/app_center/lib/manage/local_snap_providers.dart
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import 'package:app_center/manage/updates_model.dart';
import 'package:app_center/providers/installed_snaps_provider.dart';
import 'package:app_center/snapd/snapd.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:snapd/snapd.dart';
import 'package:ubuntu_service/ubuntu_service.dart';

part 'local_snap_providers.g.dart';

Expand All @@ -13,70 +12,23 @@ final localSnapSortOrderProvider =
StateProvider<SnapSortOrder>((_) => SnapSortOrder.alphabeticalAsc);

@riverpod
class FilteredLocalSnaps extends _$FilteredLocalSnaps {
late final _snapd = getService<SnapdService>();
Future<SnapListState> filteredLocalSnaps(Ref ref) async {
final installedState = await ref.watch(installedSnapsProvider.future);

@override
Future<SnapListState> build() async {
final snapListState = await connectionCheck(_snapd.getSnaps, ref);
final snaps = snapListState.snaps;
final refreshableSnaps =
(await ref.read(updatesModelProvider.future)).snaps.map((s) => s.name);
final nonRefreshableSnaps =
snaps.where((s) => !refreshableSnaps.contains(s.name));
void refreshFunction(_, __) => _refreshWithFilters(nonRefreshableSnaps);
ref.listen(localSnapFilterProvider, refreshFunction);
ref.listen(showLocalSystemAppsProvider, refreshFunction);
ref.listen(localSnapSortOrderProvider, refreshFunction);
return snapListState.copyWith(
snaps: _refreshWithFilters(nonRefreshableSnaps, updateState: false),
);
}
final filter = ref.watch(localSnapFilterProvider).toLowerCase();
final showSystemApps = ref.watch(showLocalSystemAppsProvider);
final sortOrder = ref.watch(localSnapSortOrderProvider);

/// Used to add a snap from the list without reloading the whole provider.
/// Should be used when a snap is uninstalled directly from the manage page
/// list for example.
Future<void> addToList(Snap snap) async {
if (!state.hasValue) return;
final localSnap = await _snapd.getSnap(snap.name);
_refreshWithFilters([...state.value!.snaps, localSnap]);
}
final updates = await ref.watch(updatesModelProvider.future);
final updateNames = updates.snaps.map((s) => s.name).toSet();

/// Used to remove a snap from the list without reloading the whole provider.
/// Should be used when a snap is uninstalled directly from the manage page
/// list for example.
void removeFromList(String snapName) {
if (!state.hasValue) return;
state = AsyncData(
state.value!.copyWith(
snaps: state.value!.snaps.where((s) => s.name != snapName),
),
);
}
final filteredSnaps = installedState.snaps
.where((s) => !updateNames.contains(s.name))
.where((s) =>
s.titleOrName.toLowerCase().contains(filter) &&
(showSystemApps || s.apps.isNotEmpty))
.toSet()
.sortedSnaps(sortOrder);

Iterable<Snap> _refreshWithFilters(
Iterable<Snap> nonRefreshableSnaps, {
bool updateState = true,
}) {
final filter = ref.read(localSnapFilterProvider).toLowerCase();
final showSystemApps = ref.read(showLocalSystemAppsProvider);
final sortOrder = ref.read(localSnapSortOrderProvider);
final filteredSnaps = nonRefreshableSnaps
.where(
(snap) =>
snap.titleOrName.toLowerCase().contains(filter) &&
(showSystemApps || snap.apps.isNotEmpty),
)
.toSet()
.sortedSnaps(sortOrder);
if (updateState) {
state = AsyncData(
SnapListState(
snaps: filteredSnaps,
hasInternet: state.value?.hasInternet ?? true,
),
);
}
return filteredSnaps;
}
return installedState.copyWith(snaps: filteredSnaps);
}
42 changes: 42 additions & 0 deletions packages/app_center/lib/providers/installed_snaps_provider.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import 'package:app_center/manage/updates_model.dart';
import 'package:app_center/snapd/snapd_service.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:snapd/snapd.dart';
import 'package:ubuntu_service/ubuntu_service.dart';

part 'installed_snaps_provider.g.dart';

@riverpod
class InstalledSnaps extends _$InstalledSnaps {
late final _snapd = getService<SnapdService>();

@override
Future<SnapListState> build() async {
return connectionCheck(_snapd.getSnaps, ref);
}

// Used to add a snap from the list without reloading the whole provider.
// Should be used when a snap is uninstalled directly from the manage page
// list for example.
Future<void> addToList(Snap snap) async {
if (!state.hasValue) return;
final localSnap = await _snapd.getSnap(snap.name);
state = AsyncData(
state.value!.copyWith(
snaps: [...state.value!.snaps, localSnap],
),
);
}

// Used to remove a snap from the list without reloading the whole provider.
// Should be used when a snap is uninstalled directly from the manage page
// list for example.
void removeFromList(String snapName) {
if (!state.hasValue) return;
state = AsyncData(
state.value!.copyWith(
snaps: state.value!.snaps.where((s) => s.name != snapName),
),
);
}
}
8 changes: 8 additions & 0 deletions packages/app_center/lib/search/search_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'package:app_center/appstream/appstream.dart';
import 'package:app_center/error/error.dart';
import 'package:app_center/l10n.dart';
import 'package:app_center/layout.dart';
import 'package:app_center/providers/installed_snaps_provider.dart';
import 'package:app_center/search/search.dart';
import 'package:app_center/snapd/multisnap_model.dart';
import 'package:app_center/snapd/snapd.dart';
Expand Down Expand Up @@ -271,11 +272,18 @@ class _SnapSearchResults extends ConsumerWidget {
),
),
);

final installedSnapsModel = ref.watch(installedSnapsProvider);

final installedSnapsIds =
installedSnapsModel.value?.snaps.map((s) => s.id).toList() ?? [];

return results.when(
data: (data) => data.isNotEmpty
? ResponsiveLayoutScrollView(
slivers: [
AppCardGrid.fromSnaps(
installedIds: installedSnapsIds,
snaps: data,
onTap: (snap) => StoreNavigator.pushSearchSnap(
context,
Expand Down
8 changes: 4 additions & 4 deletions packages/app_center/lib/snapd/snap_model.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import 'dart:async';

import 'package:app_center/manage/local_snap_providers.dart';
import 'package:app_center/manage/updates_model.dart';
import 'package:app_center/providers/installed_snaps_provider.dart';
import 'package:app_center/snapd/currently_installing_model.dart';
import 'package:app_center/snapd/snapd.dart';
import 'package:app_center/snapd/snapd_cache.dart';
Expand Down Expand Up @@ -97,7 +97,7 @@ class SnapModel extends _$SnapModel {
_updateChangeId(changeId);
await _listenUntilDone(changeId, ref);
unawaited(
ref.read(filteredLocalSnapsProvider.notifier).addToList(storeSnap),
ref.read(installedSnapsProvider.notifier).addToList(storeSnap),
);
}

Expand Down Expand Up @@ -140,7 +140,7 @@ class SnapModel extends _$SnapModel {
if (removeFromList && completedSuccessfully) {
ref.read(updatesModelProvider.notifier).removeFromList(snapData.name);
ref
.read(filteredLocalSnapsProvider.notifier)
.read(installedSnapsProvider.notifier)
.addToList(snapData.localSnap!);
}
return completedSuccessfully;
Expand All @@ -154,7 +154,7 @@ class SnapModel extends _$SnapModel {
_updateChangeId(changeId);
await _listenUntilDone(changeId, ref);
ref.read(updatesModelProvider.notifier).removeFromList(snapName);
ref.read(filteredLocalSnapsProvider.notifier).removeFromList(snapName);
ref.read(installedSnapsProvider.notifier).removeFromList(snapName);
}

Future<void> revert() async {
Expand Down
3 changes: 2 additions & 1 deletion packages/app_center/lib/src/l10n/app_de.arb
Original file line number Diff line number Diff line change
Expand Up @@ -478,5 +478,6 @@
"debPageDocumentationLinkLabel": "Erfahren Sie mehr über die Verwaltung von Debian-Paketen",
"@debPageDocumentationLinkLabel": {},
"managePageDocumentationLinkLabel": "In der Dokumentation erfahren Sie, wie Sie Debian-Pakete verwalten können.",
"@managePageDocumentationLinkLabel": {}
"@managePageDocumentationLinkLabel": {},
"installedLabel": "Installiert"
}
3 changes: 2 additions & 1 deletion packages/app_center/lib/src/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -369,5 +369,6 @@
"codecPageTitle": "Missing media codecs",
"codecPageDescription": "You need to install the following codecs for handling certain video and audio formats:",
"codecProprietaryDisclaimer": "Some of the recommended codecs could be proprietary.",
"codecInstallAllButton": "Install recommended codecs"
"codecInstallAllButton": "Install recommended codecs",
"installedLabel": "Installed"
}
Loading
Loading