fix: limit URL install loading to its submit button

This commit is contained in:
Levi committed 2026-09-13 17:20:08 +08:00
1 parent 3d372f98de
commit 4802802828
2 files changed
+35 -41

No files matched your search

@@ -670,7 +670,6 @@ class _Toolbar extends StatelessWidget {
@override
Widget build(BuildContext context) {
final palette = AppPalette.of(context);
final manualInstallBusy = state.busyExtensionIds.contains(ExtensionsController.manualInstallBusyKey);
final search = AppTextField(
key: const ValueKey('extension-search-input'),
controller: searchController,
@@ -717,7 +716,6 @@ class _Toolbar extends StatelessWidget {
key: const ValueKey('load-local-extension-button'),
tooltip: context.l10n.extensionLoadLocal,
icon: Icons.folder_open_outlined,
loading: manualInstallBusy,
onPressed: onInstallFolder,
),
const SizedBox(width: 8),
@@ -728,7 +726,6 @@ class _Toolbar extends StatelessWidget {
key: const ValueKey('install-extension-button'),
tooltip: context.l10n.extensionInstallFromUrl,
icon: Icons.add_link,
loading: manualInstallBusy,
onPressed: () => onOpenInstall(buttonContext),
),
),
@@ -804,18 +801,11 @@ class _FilterBar extends StatelessWidget {
}
class _OutlineToolbarIconButton extends StatelessWidget {
const _OutlineToolbarIconButton({
super.key,
required this.tooltip,
required this.icon,
required this.onPressed,
this.loading = false,
});
const _OutlineToolbarIconButton({super.key, required this.tooltip, required this.icon, required this.onPressed});
final String tooltip;
final IconData icon;
final VoidCallback? onPressed;
final bool loading;
@override
Widget build(BuildContext context) {
@@ -823,13 +813,7 @@ class _OutlineToolbarIconButton extends StatelessWidget {
message: tooltip,
child: SizedBox.square(
dimension: 32,
child: shad.IconButton.outline(
size: shad.ButtonSize.xSmall,
onPressed: loading ? null : onPressed,
icon: loading
? const SizedBox.square(dimension: 13, child: shad.CircularProgressIndicator())
: Icon(icon, size: 17),
),
child: shad.IconButton.outline(size: shad.ButtonSize.xSmall, onPressed: onPressed, icon: Icon(icon, size: 17)),
),
);
}
+33 -23
View File
@@ -857,30 +857,37 @@ void main() {
expect(tester.takeException(), isNull);
});
testWidgets('extension install actions show progress instead of a disabled icon while busy', (
WidgetTester tester,
) async {
await _setTestSize(tester, const Size(1100, 900));
await tester.pumpWidget(
ProviderScope(
overrides: [extensionsControllerProvider.overrideWith(BusyInstallExtensionsController.new)],
child: shad.ShadcnApp(
theme: AppTheme.light(),
materialTheme: AppTheme.materialLight(),
home: const ExtensionsPage(),
testWidgets(
'URL installation leaves toolbar icons unchanged while store installation shows progress',
(WidgetTester tester) async {
await _setTestSize(tester, const Size(1100, 900));
await tester.pumpWidget(
ProviderScope(
overrides: [extensionsControllerProvider.overrideWith(BusyInstallExtensionsController.new)],
child: shad.ShadcnApp(
theme: AppTheme.light(),
materialTheme: AppTheme.materialLight(),
home: const ExtensionsPage(),
),
),
),
);
await tester.pump();
await tester.pump(const Duration(milliseconds: 100));
);
await tester.pump();
await tester.pump(const Duration(milliseconds: 100));
final manualInstall = find.byKey(const ValueKey('install-extension-button'));
final storeInstall = find.byKey(const ValueKey('install-store-extension-extension-1'));
expect(find.descendant(of: manualInstall, matching: find.byType(shad.CircularProgressIndicator)), findsOneWidget);
expect(find.descendant(of: storeInstall, matching: find.byType(shad.CircularProgressIndicator)), findsOneWidget);
expect(find.descendant(of: storeInstall, matching: find.byIcon(Icons.download)), findsNothing);
expect(tester.takeException(), isNull);
});
final manualInstall = find.byKey(const ValueKey('install-extension-button'));
final storeInstall = find.byKey(const ValueKey('install-store-extension-extension-1'));
expect(find.descendant(of: manualInstall, matching: find.byType(shad.CircularProgressIndicator)), findsNothing);
expect(find.descendant(of: manualInstall, matching: find.byIcon(Icons.add_link)), findsOneWidget);
final localInstall = find.byKey(const ValueKey('load-local-extension-button'));
expect(localInstall, findsOneWidget);
expect(find.descendant(of: localInstall, matching: find.byType(shad.CircularProgressIndicator)), findsNothing);
expect(find.descendant(of: localInstall, matching: find.byIcon(Icons.folder_open_outlined)), findsOneWidget);
expect(find.descendant(of: storeInstall, matching: find.byType(shad.CircularProgressIndicator)), findsOneWidget);
expect(find.descendant(of: storeInstall, matching: find.byIcon(Icons.download)), findsNothing);
expect(tester.takeException(), isNull);
},
variant: TargetPlatformVariant.only(TargetPlatform.macOS),
);
for (final (width, platform) in [
(320.0, TargetPlatform.android),
@@ -5301,7 +5308,10 @@ class BusyInstallExtensionsController extends FakeExtensionsController {
@override
Future<ExtensionsState> build() async {
final initial = await super.build();
return initial.copyWith(busyExtensionIds: {ExtensionsController.manualInstallBusyKey, 'extension-1'});
return initial.copyWith(
devMode: true,
busyExtensionIds: {ExtensionsController.manualInstallBusyKey, 'extension-1'},
);
}
}