Skip to content

Commit

Permalink
Merge pull request #1538 from codinesh/managepage-update-snap
Browse files Browse the repository at this point in the history
feat: manage page - Individual update buttons
  • Loading branch information
BLKKKBVSIK authored Dec 28, 2023
2 parents 513aefd + 52e65a0 commit 510a4d9
Show file tree
Hide file tree
Showing 3 changed files with 194 additions and 37 deletions.
178 changes: 143 additions & 35 deletions packages/app_center/lib/src/manage/manage_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ class _ManageView extends ConsumerWidget {
: index == 0
? ManageTilePosition.first
: ManageTilePosition.middle,
showUpdateButton: true,
),
),
SliverList.list(children: [
Expand Down Expand Up @@ -314,10 +315,12 @@ class _ManageSnapTile extends ConsumerWidget {
const _ManageSnapTile({
required this.snap,
this.position = ManageTilePosition.middle,
this.showUpdateButton = false,
});

final Snap snap;
final ManageTilePosition position;
final bool showUpdateButton;

@override
Widget build(BuildContext context, WidgetRef ref) {
Expand Down Expand Up @@ -438,43 +441,148 @@ class _ManageSnapTile extends ConsumerWidget {
)
],
),
trailing: ButtonBar(
mainAxisSize: MainAxisSize.min,
children: [
Visibility(
maintainSize: true,
maintainAnimation: true,
maintainState: true,
visible: snapLauncher.isLaunchable,
child: OutlinedButton(
onPressed: snapLauncher.open,
child: Text(l10n.snapActionOpenLabel),
trailing: showUpdateButton
? buildButtonBarForUpdate(ref, l10n, snapLauncher, context)
: buildButtonBarForOpen(ref, l10n, snapLauncher, context),
);
}

ButtonBar buildButtonBarForUpdate(WidgetRef ref, AppLocalizations l10n,
SnapLauncher snapLauncher, BuildContext context) {
return ButtonBar(
mainAxisSize: MainAxisSize.min,
children: [
Consumer(
builder: (context, ref, child) {
final snapModel = ref.watch(snapModelProvider(snap.name));
final updatesModel = ref.watch(updatesModelProvider);

return PushButton.outlined(
onPressed: updatesModel.activeChangeId != null
? null
: () {
ref.read(snapModelProvider(snap.name)).refresh();
},
child: snapModel.activeChangeId != null
? Consumer(
builder: (context, ref, child) {
final change = ref
.watch(changeProvider(snapModel.activeChangeId))
.whenOrNull(data: (data) => data);
return Row(
children: [
SizedBox.square(
dimension: 16,
child: YaruCircularProgressIndicator(
value: change?.progress,
strokeWidth: 2,
),
),
if (change != null) ...[
const SizedBox(width: 8),
Flexible(
child: Text(
change.localize(l10n) ?? '',
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
),
]
],
);
},
)
: Row(
mainAxisSize: MainAxisSize.min,
children: [
const Icon(YaruIcons.download),
const SizedBox(width: 8),
Flexible(
child: Text(
l10n.snapActionUpdateLabel,
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
),
],
),
);
},
),
MenuAnchor(
menuChildren: [
Visibility(
maintainSize: true,
maintainAnimation: true,
maintainState: true,
visible: snapLauncher.isLaunchable,
child: MenuItemButton(
onPressed: snapLauncher.open,
child: Text(l10n.snapActionOpenLabel),
),
),
MenuItemButton(
onPressed: () =>
StoreNavigator.pushSnap(context, name: snap.name),
child: Text(
l10n.managePageShowDetailsLabel,
style: Theme.of(context).textTheme.bodyMedium,
),
)
],
builder: (context, controller, child) => YaruOptionButton(
onPressed: () {
if (controller.isOpen) {
controller.close();
} else {
controller.open();
}
},
child: const Icon(YaruIcons.view_more_horizontal),
),
MenuAnchor(
menuChildren: [
MenuItemButton(
onPressed: () =>
StoreNavigator.pushSnap(context, name: snap.name),
child: Text(
l10n.managePageShowDetailsLabel,
style: Theme.of(context).textTheme.bodyMedium,
),
)
],
builder: (context, controller, child) => YaruOptionButton(
onPressed: () {
if (controller.isOpen) {
controller.close();
} else {
controller.open();
}
},
child: const Icon(YaruIcons.view_more_horizontal),
),
)
],
),
)
],
);
}

ButtonBar buildButtonBarForOpen(WidgetRef ref, AppLocalizations l10n,
SnapLauncher snapLauncher, BuildContext context) {
return ButtonBar(
mainAxisSize: MainAxisSize.min,
children: [
Visibility(
maintainSize: true,
maintainAnimation: true,
maintainState: true,
visible: snapLauncher.isLaunchable,
child: OutlinedButton(
onPressed: snapLauncher.open,
child: Text(l10n.snapActionOpenLabel),
),
),
MenuAnchor(
menuChildren: [
MenuItemButton(
onPressed: () =>
StoreNavigator.pushSnap(context, name: snap.name),
child: Text(
l10n.managePageShowDetailsLabel,
style: Theme.of(context).textTheme.bodyMedium,
),
)
],
builder: (context, controller, child) => YaruOptionButton(
onPressed: () {
if (controller.isOpen) {
controller.close();
} else {
controller.open();
}
},
child: const Icon(YaruIcons.view_more_horizontal),
),
)
],
);
}
}
1 change: 1 addition & 0 deletions packages/app_center/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,4 @@ flutter:
generate: true
assets:
- assets/

52 changes: 50 additions & 2 deletions packages/app_center/test/manage_page_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@ void main() {
channel: 'latest/stable',
),
];

final snapModel = createMockSnapModel(
hasUpdate: true,
localSnap: refreshableSnaps[0],
storeSnap: refreshableSnaps[0],
);

testWidgets('list installed snaps', (tester) async {
await tester.pumpApp(
(_) => ProviderScope(
Expand Down Expand Up @@ -126,7 +133,8 @@ void main() {
),
),
showLocalSystemAppsProvider.overrideWith((ref) => true),
updatesModelProvider.overrideWith((_) => mockUpdatesModel)
updatesModelProvider.overrideWith((_) => mockUpdatesModel),
snapModelProvider.overrideWith((_, __) => snapModel)
],
child: const ManagePage(),
),
Expand All @@ -143,6 +151,44 @@ void main() {
verify(mockUpdatesModel.updateAll()).called(1);
});

testWidgets('refresh individual snap', (tester) async {
final mockUpdatesModel = createMockUpdatesModel(
refreshableSnapNames: refreshableSnaps.map((snap) => snap.name));

final snapModel = createMockSnapModel(
hasUpdate: true,
localSnap: refreshableSnaps[0],
storeSnap: refreshableSnaps[0],
);

await tester.pumpApp(
(_) => ProviderScope(
overrides: [
launchProvider.overrideWith((_, __) => createMockSnapLauncher()),
snapModelProvider.overrideWith((ref, arg) => snapModel),
manageModelProvider.overrideWith(
(_) => createMockManageModel(
refreshableSnaps: refreshableSnaps,
),
),
showLocalSystemAppsProvider.overrideWith((ref) => true),
updatesModelProvider.overrideWith((_) => mockUpdatesModel)
],
child: const ManagePage(),
),
);

final testTile = find.snapTile('Snap with an update');
expect(testTile, findsOneWidget);
expect(find.descendant(of: testTile, matching: find.text('2.0')),
findsOneWidget);
expect(find.descendant(of: testTile, matching: find.text('latest/stable')),
findsOneWidget);

await tester.tap(find.text(tester.l10n.snapActionUpdateLabel));
verify(snapModel.refresh()).called(1);
});

testWidgets('refreshing all', (tester) async {
final mockUpdatesModel = createMockUpdatesModel(
refreshableSnapNames: refreshableSnaps.map((snap) => snap.name),
Expand All @@ -166,6 +212,7 @@ void main() {
updatesModelProvider.overrideWith((_) => mockUpdatesModel),
changeProvider
.overrideWith((_, __) => Stream.fromIterable([mockChange])),
snapModelProvider.overrideWith((_, __) => snapModel)
],
child: const ManagePage(),
),
Expand Down Expand Up @@ -209,7 +256,8 @@ void main() {
),
),
),
)
),
snapModelProvider.overrideWith((_, __) => snapModel)
],
child: const ManagePage(),
),
Expand Down

0 comments on commit 510a4d9

Please sign in to comment.