use reload button to cancel load if available
This commit is contained in:
+38
-8
@@ -34,6 +34,8 @@ import 'package:weblibre/features/geckoview/domain/repositories/tab.dart';
|
|||||||
import 'package:weblibre/features/geckoview/features/bookmarks/domain/repositories/bookmarks.dart';
|
import 'package:weblibre/features/geckoview/features/bookmarks/domain/repositories/bookmarks.dart';
|
||||||
import 'package:weblibre/features/geckoview/features/bookmarks/domain/utils/bookmark_tree_utils.dart';
|
import 'package:weblibre/features/geckoview/features/bookmarks/domain/utils/bookmark_tree_utils.dart';
|
||||||
import 'package:weblibre/features/geckoview/features/browser/domain/entities/font_size_constants.dart';
|
import 'package:weblibre/features/geckoview/features/browser/domain/entities/font_size_constants.dart';
|
||||||
|
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/data/providers/toolbar_button_configs.dart';
|
||||||
|
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/domain/entities/toolbar_button_id.dart';
|
||||||
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/domain/entities/toolbar_button_spec.dart';
|
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/domain/entities/toolbar_button_spec.dart';
|
||||||
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/presentation/models/contextual_toolbar_scope.dart';
|
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/presentation/models/contextual_toolbar_scope.dart';
|
||||||
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/presentation/widgets/contextual_bar_buttons.dart';
|
import 'package:weblibre/features/geckoview/features/browser/features/contextual_toolbar/presentation/widgets/contextual_bar_buttons.dart';
|
||||||
@@ -83,14 +85,31 @@ class ToolbarButtonDefinition {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Whether a reload button is currently configured visible in the contextual
|
||||||
|
/// toolbar. Used to decide whether the back button should fall back to acting
|
||||||
|
/// as a stop-loading control (see issue #351).
|
||||||
|
bool _isReloadButtonVisible(WidgetRef ref) {
|
||||||
|
return ref
|
||||||
|
.read(effectiveToolbarButtonConfigsProvider)
|
||||||
|
.value
|
||||||
|
.any(
|
||||||
|
(config) =>
|
||||||
|
config.buttonId == ToolbarButtonId.reload.name && config.isVisible,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
final List<ToolbarButtonDefinition> toolbarButtonRegistry = [
|
final List<ToolbarButtonDefinition> toolbarButtonRegistry = [
|
||||||
ToolbarButtonDefinition(
|
ToolbarButtonDefinition(
|
||||||
spec: backToolbarButtonSpec,
|
spec: backToolbarButtonSpec,
|
||||||
label: 'Back',
|
label: 'Back',
|
||||||
icon: Icons.arrow_back,
|
icon: Icons.arrow_back,
|
||||||
isPrimaryAvailable: (scope, ref) =>
|
isPrimaryAvailable: (scope, ref) {
|
||||||
scope.tabState?.historyState.canGoBack == true ||
|
final canGoBack = scope.tabState?.historyState.canGoBack == true;
|
||||||
scope.tabState?.isLoading == true,
|
final isLoading = scope.tabState?.isLoading == true;
|
||||||
|
// The back button only doubles as a stop-loading control when no
|
||||||
|
// dedicated reload button is present to take over that role.
|
||||||
|
return canGoBack || (isLoading && !_isReloadButtonVisible(ref));
|
||||||
|
},
|
||||||
longPressActions: ['History Menu (Previous pages)'],
|
longPressActions: ['History Menu (Previous pages)'],
|
||||||
builder: (scope, context, ref) {
|
builder: (scope, context, ref) {
|
||||||
if (scope.isPreview) {
|
if (scope.isPreview) {
|
||||||
@@ -104,6 +123,7 @@ final List<ToolbarButtonDefinition> toolbarButtonRegistry = [
|
|||||||
return NavigateBackButton(
|
return NavigateBackButton(
|
||||||
selectedTabId: scope.selectedTabId,
|
selectedTabId: scope.selectedTabId,
|
||||||
isLoading: scope.tabState?.isLoading ?? false,
|
isLoading: scope.tabState?.isLoading ?? false,
|
||||||
|
stopLoadingFallback: !_isReloadButtonVisible(ref),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@@ -616,6 +636,7 @@ class _ReloadToolbarButton extends HookConsumerWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final menuController = useMemoized(MenuController.new);
|
final menuController = useMemoized(MenuController.new);
|
||||||
|
final isLoading = scope.tabState?.isLoading ?? false;
|
||||||
|
|
||||||
return MenuAnchor(
|
return MenuAnchor(
|
||||||
controller: menuController,
|
controller: menuController,
|
||||||
@@ -640,12 +661,21 @@ class _ReloadToolbarButton extends HookConsumerWidget {
|
|||||||
: () async {
|
: () async {
|
||||||
final tabId = scope.selectedTabId;
|
final tabId = scope.selectedTabId;
|
||||||
if (tabId != null) {
|
if (tabId != null) {
|
||||||
await ref
|
final controller = ref.read(
|
||||||
.read(tabSessionProvider(tabId: tabId).notifier)
|
tabSessionProvider(tabId: tabId).notifier,
|
||||||
.reload();
|
);
|
||||||
|
// While loading the button acts as a stop control; otherwise
|
||||||
|
// it reloads the page.
|
||||||
|
if (isLoading) {
|
||||||
|
await controller.stopLoading();
|
||||||
|
} else {
|
||||||
|
await controller.reload();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onLongPress: scope.isPreview
|
// Hard Refresh is meaningless mid-load, so disable the long-press menu
|
||||||
|
// while the stop action is active.
|
||||||
|
onLongPress: (scope.isPreview || isLoading)
|
||||||
? null
|
? null
|
||||||
: () {
|
: () {
|
||||||
if (menuController.isOpen) {
|
if (menuController.isOpen) {
|
||||||
@@ -654,7 +684,7 @@ class _ReloadToolbarButton extends HookConsumerWidget {
|
|||||||
menuController.open();
|
menuController.open();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
icon: const Icon(Icons.refresh),
|
icon: Icon(isLoading ? Icons.close : Icons.refresh),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
+19
-4
@@ -52,21 +52,30 @@ class NavigateBackButtonView extends StatelessWidget {
|
|||||||
super.key,
|
super.key,
|
||||||
required this.canGoBack,
|
required this.canGoBack,
|
||||||
required this.isLoading,
|
required this.isLoading,
|
||||||
|
this.stopLoadingFallback = true,
|
||||||
this.onPressed,
|
this.onPressed,
|
||||||
this.onLongPress,
|
this.onLongPress,
|
||||||
});
|
});
|
||||||
|
|
||||||
final bool canGoBack;
|
final bool canGoBack;
|
||||||
final bool isLoading;
|
final bool isLoading;
|
||||||
|
|
||||||
|
/// When `true` (default), the button doubles as a stop-loading control while
|
||||||
|
/// [isLoading] (shows a close icon, taps cancel the load). When `false` it
|
||||||
|
/// stays a plain back button even during loading — used when a dedicated
|
||||||
|
/// reload/stop button is present elsewhere in the toolbar.
|
||||||
|
final bool stopLoadingFallback;
|
||||||
final VoidCallback? onPressed;
|
final VoidCallback? onPressed;
|
||||||
final VoidCallback? onLongPress;
|
final VoidCallback? onLongPress;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final showStop = isLoading && stopLoadingFallback;
|
||||||
|
|
||||||
return IconButton(
|
return IconButton(
|
||||||
onPressed: (canGoBack || isLoading) ? onPressed : null,
|
onPressed: (canGoBack || showStop) ? onPressed : null,
|
||||||
onLongPress: (canGoBack && !isLoading) ? onLongPress : null,
|
onLongPress: (canGoBack && !showStop) ? onLongPress : null,
|
||||||
icon: isLoading ? const Icon(Icons.close) : const Icon(Icons.arrow_back),
|
icon: showStop ? const Icon(Icons.close) : const Icon(Icons.arrow_back),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -118,18 +127,23 @@ class NavigateBackButton extends HookConsumerWidget {
|
|||||||
super.key,
|
super.key,
|
||||||
required this.selectedTabId,
|
required this.selectedTabId,
|
||||||
required this.isLoading,
|
required this.isLoading,
|
||||||
|
this.stopLoadingFallback = true,
|
||||||
this.menuControllerToClose,
|
this.menuControllerToClose,
|
||||||
this.canGoBack = true,
|
this.canGoBack = true,
|
||||||
});
|
});
|
||||||
|
|
||||||
final String? selectedTabId;
|
final String? selectedTabId;
|
||||||
final bool isLoading;
|
final bool isLoading;
|
||||||
|
|
||||||
|
/// See [NavigateBackButtonView.stopLoadingFallback].
|
||||||
|
final bool stopLoadingFallback;
|
||||||
final MenuController? menuControllerToClose;
|
final MenuController? menuControllerToClose;
|
||||||
final bool canGoBack;
|
final bool canGoBack;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final historyMenuController = useMenuController();
|
final historyMenuController = useMenuController();
|
||||||
|
final showStop = isLoading && stopLoadingFallback;
|
||||||
|
|
||||||
return HistoryMenu(
|
return HistoryMenu(
|
||||||
selectedTabId: selectedTabId,
|
selectedTabId: selectedTabId,
|
||||||
@@ -138,6 +152,7 @@ class NavigateBackButton extends HookConsumerWidget {
|
|||||||
child: NavigateBackButtonView(
|
child: NavigateBackButtonView(
|
||||||
canGoBack: canGoBack,
|
canGoBack: canGoBack,
|
||||||
isLoading: isLoading,
|
isLoading: isLoading,
|
||||||
|
stopLoadingFallback: stopLoadingFallback,
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
final controller = ref.read(
|
final controller = ref.read(
|
||||||
tabSessionProvider(tabId: selectedTabId).notifier,
|
tabSessionProvider(tabId: selectedTabId).notifier,
|
||||||
@@ -149,7 +164,7 @@ class NavigateBackButton extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (isLoading) {
|
if (showStop) {
|
||||||
await controller.stopLoading();
|
await controller.stopLoading();
|
||||||
} else if (isReaderActive) {
|
} else if (isReaderActive) {
|
||||||
await ref
|
await ref
|
||||||
|
|||||||
Reference in New Issue
Block a user