diff --git a/app/lib/features/geckoview/features/browser/domain/services/browser_addon.g.dart b/app/lib/features/geckoview/features/browser/domain/services/browser_addon.g.dart index 69203de3..879d2a97 100644 --- a/app/lib/features/geckoview/features/browser/domain/services/browser_addon.g.dart +++ b/app/lib/features/geckoview/features/browser/domain/services/browser_addon.g.dart @@ -42,7 +42,7 @@ final class BrowserAddonServiceProvider } String _$browserAddonServiceHash() => - r'6f07d93576a0816bf1b9e1b36397b89b7cacf43f'; + r'1485fd056ce32e142e342e920affb82a5c77a370'; abstract class _$BrowserAddonService extends $Notifier { void build(); diff --git a/app/lib/features/geckoview/features/browser/presentation/widgets/browser_modules/app_bar_title.dart b/app/lib/features/geckoview/features/browser/presentation/widgets/browser_modules/app_bar_title.dart index ba8ff83d..f52b81ad 100644 --- a/app/lib/features/geckoview/features/browser/presentation/widgets/browser_modules/app_bar_title.dart +++ b/app/lib/features/geckoview/features/browser/presentation/widgets/browser_modules/app_bar_title.dart @@ -18,6 +18,7 @@ * along with this program. If not, see . */ import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_material_design_icons/flutter_material_design_icons.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:skeletonizer/skeletonizer.dart'; @@ -64,6 +65,7 @@ class CompactAppBarTitle extends ConsumerWidget { isTabTunneled: isTabTuneledAsync.hasValue && isTabTuneledAsync.value == true, showSiteSettingsBadge: showSiteSettingsBadge, + longPressUrlCopy: settings.tabBarLongPressUrlCopy, onSiteSettingsTap: () { ref .read(bottomSheetControllerProvider.notifier) @@ -89,6 +91,7 @@ class CompactAppBarTitleView extends StatelessWidget { required this.onSiteSettingsTap, required this.onTitleTap, this.tabIcon, + this.longPressUrlCopy = true, }); final TabState tabState; @@ -97,6 +100,7 @@ class CompactAppBarTitleView extends StatelessWidget { final VoidCallback onSiteSettingsTap; final VoidCallback onTitleTap; final Widget? tabIcon; + final bool longPressUrlCopy; @override Widget build(BuildContext context) { @@ -168,6 +172,13 @@ class CompactAppBarTitleView extends StatelessWidget { style: theme.textTheme.bodyMedium?.copyWith( color: theme.colorScheme.onSurface, ), + onTooltipTriggered: longPressUrlCopy + ? () async { + await Clipboard.setData( + ClipboardData(text: tabState.url.toString()), + ); + } + : null, ), ), ], @@ -209,6 +220,7 @@ class AppBarTitle extends ConsumerWidget { isTabTunneled: isTabTuneledAsync.hasValue && isTabTuneledAsync.value == true, showSiteSettingsBadge: showSiteSettingsBadge, + longPressUrlCopy: settings.tabBarLongPressUrlCopy, onSiteSettingsTap: () { ref .read(bottomSheetControllerProvider.notifier) @@ -233,6 +245,7 @@ class AppBarTitleView extends StatelessWidget { required this.showSiteSettingsBadge, required this.onSiteSettingsTap, required this.onTitleTap, + required this.longPressUrlCopy, this.tabIcon, }); @@ -242,6 +255,7 @@ class AppBarTitleView extends StatelessWidget { final VoidCallback onSiteSettingsTap; final VoidCallback onTitleTap; final Widget? tabIcon; + final bool longPressUrlCopy; @override Widget build(BuildContext context) { @@ -333,6 +347,13 @@ class AppBarTitleView extends StatelessWidget { style: theme.textTheme.bodyMedium?.copyWith( color: theme.colorScheme.onSurface, ), + onTooltipTriggered: longPressUrlCopy + ? () async { + await Clipboard.setData( + ClipboardData(text: tabState.url.toString()), + ); + } + : null, ), ), ], diff --git a/app/lib/features/settings/presentation/widgets/toolbar_layout_content.dart b/app/lib/features/settings/presentation/widgets/toolbar_layout_content.dart index b2a978b3..32e0b217 100644 --- a/app/lib/features/settings/presentation/widgets/toolbar_layout_content.dart +++ b/app/lib/features/settings/presentation/widgets/toolbar_layout_content.dart @@ -37,6 +37,7 @@ class ToolbarLayoutContent extends StatelessWidget { _TabBarPositionSection(), _TabBarLayoutModeSection(), _AutoHideTabBarTile(), + _TabBarLongPressUrlCopyTile(), SettingSection(name: 'Contextual Toolbar'), _ShowContextualTabBarTile(), _CustomizeToolbarButtonsTile(), @@ -423,6 +424,36 @@ class _BottomSheetTabViewTile extends HookConsumerWidget { } } +class _TabBarLongPressUrlCopyTile extends HookConsumerWidget { + const _TabBarLongPressUrlCopyTile(); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final tabBarLongPressUrlCopy = ref.watch( + generalSettingsWithDefaultsProvider.select( + (s) => s.tabBarLongPressUrlCopy, + ), + ); + + return SwitchListTile.adaptive( + title: const Text('Long Press URL to Copy'), + subtitle: const Text( + 'Copy the page URL to clipboard when long pressing the address bar', + ), + secondary: const Icon(MdiIcons.contentCopy), + value: tabBarLongPressUrlCopy, + onChanged: (value) async { + await ref + .read(saveGeneralSettingsControllerProvider.notifier) + .save( + (currentSettings) => + currentSettings.copyWith.tabBarLongPressUrlCopy(value), + ); + }, + ); + } +} + class _TabListShowFaviconsTile extends HookConsumerWidget { const _TabListShowFaviconsTile(); diff --git a/app/lib/features/settings/presentation/widgets/toolbar_preview.dart b/app/lib/features/settings/presentation/widgets/toolbar_preview.dart index cb8ab203..846ecf14 100644 --- a/app/lib/features/settings/presentation/widgets/toolbar_preview.dart +++ b/app/lib/features/settings/presentation/widgets/toolbar_preview.dart @@ -355,6 +355,7 @@ class _RegularPreviewTitle extends StatelessWidget { onSiteSettingsTap: _noop, onTitleTap: _noop, tabIcon: const Icon(MdiIcons.web, size: 24), + longPressUrlCopy: false, ); } } diff --git a/app/lib/features/small_web/presentation/controllers/small_web_session_controller.g.dart b/app/lib/features/small_web/presentation/controllers/small_web_session_controller.g.dart index 2f045ea7..e496d0a2 100644 --- a/app/lib/features/small_web/presentation/controllers/small_web_session_controller.g.dart +++ b/app/lib/features/small_web/presentation/controllers/small_web_session_controller.g.dart @@ -224,7 +224,7 @@ final class SmallWebSessionControllerProvider } String _$smallWebSessionControllerHash() => - r'90680807b38de577e3322941b47792952d66428a'; + r'ee57d24b33b5a7dffe668fe3ddd2b77d84f58eae'; abstract class _$SmallWebSessionController extends $Notifier> { diff --git a/app/lib/features/user/data/models/general_settings.dart b/app/lib/features/user/data/models/general_settings.dart index 4645aa24..6d04452a 100644 --- a/app/lib/features/user/data/models/general_settings.dart +++ b/app/lib/features/user/data/models/general_settings.dart @@ -115,6 +115,7 @@ class GeneralSettings with FastEquatable { final int? urlCleanerLastCheckEpochMs; final bool urlCleanerLastUpdateWasAuto; final TabType smallWebTabType; + final bool tabBarLongPressUrlCopy; final bool unshortenerEnabled; final String unshortenerToken; @@ -164,6 +165,7 @@ class GeneralSettings with FastEquatable { required this.urlCleanerLastCheckEpochMs, required this.urlCleanerLastUpdateWasAuto, required this.smallWebTabType, + required this.tabBarLongPressUrlCopy, required this.unshortenerEnabled, required this.unshortenerToken, }); @@ -214,6 +216,7 @@ class GeneralSettings with FastEquatable { this.urlCleanerLastCheckEpochMs, bool? urlCleanerLastUpdateWasAuto, TabType? smallWebTabType, + bool? tabBarLongPressUrlCopy, bool? unshortenerEnabled, String? unshortenerToken, }) : themeMode = themeMode ?? ThemeMode.dark, @@ -271,6 +274,7 @@ class GeneralSettings with FastEquatable { urlCleanerAutoUpdate = urlCleanerAutoUpdate ?? false, urlCleanerLastUpdateWasAuto = urlCleanerLastUpdateWasAuto ?? false, smallWebTabType = smallWebTabType ?? TabType.private, + tabBarLongPressUrlCopy = tabBarLongPressUrlCopy ?? true, unshortenerEnabled = unshortenerEnabled ?? false, unshortenerToken = unshortenerToken ?? ''; @@ -341,6 +345,7 @@ class GeneralSettings with FastEquatable { urlCleanerLastCheckEpochMs, urlCleanerLastUpdateWasAuto, smallWebTabType, + tabBarLongPressUrlCopy, unshortenerEnabled, unshortenerToken, ]; diff --git a/app/lib/features/user/data/models/general_settings.g.dart b/app/lib/features/user/data/models/general_settings.g.dart index 1952add0..4f872d9b 100644 --- a/app/lib/features/user/data/models/general_settings.g.dart +++ b/app/lib/features/user/data/models/general_settings.g.dart @@ -115,6 +115,8 @@ abstract class _$GeneralSettingsCWProxy { GeneralSettings smallWebTabType(TabType smallWebTabType); + GeneralSettings tabBarLongPressUrlCopy(bool tabBarLongPressUrlCopy); + GeneralSettings unshortenerEnabled(bool unshortenerEnabled); GeneralSettings unshortenerToken(String unshortenerToken); @@ -172,6 +174,7 @@ abstract class _$GeneralSettingsCWProxy { int? urlCleanerLastCheckEpochMs, bool urlCleanerLastUpdateWasAuto, TabType smallWebTabType, + bool tabBarLongPressUrlCopy, bool unshortenerEnabled, String unshortenerToken, }); @@ -376,6 +379,10 @@ class _$GeneralSettingsCWProxyImpl implements _$GeneralSettingsCWProxy { GeneralSettings smallWebTabType(TabType smallWebTabType) => call(smallWebTabType: smallWebTabType); + @override + GeneralSettings tabBarLongPressUrlCopy(bool tabBarLongPressUrlCopy) => + call(tabBarLongPressUrlCopy: tabBarLongPressUrlCopy); + @override GeneralSettings unshortenerEnabled(bool unshortenerEnabled) => call(unshortenerEnabled: unshortenerEnabled); @@ -439,6 +446,7 @@ class _$GeneralSettingsCWProxyImpl implements _$GeneralSettingsCWProxy { Object? urlCleanerLastCheckEpochMs = const $CopyWithPlaceholder(), Object? urlCleanerLastUpdateWasAuto = const $CopyWithPlaceholder(), Object? smallWebTabType = const $CopyWithPlaceholder(), + Object? tabBarLongPressUrlCopy = const $CopyWithPlaceholder(), Object? unshortenerEnabled = const $CopyWithPlaceholder(), Object? unshortenerToken = const $CopyWithPlaceholder(), }) { @@ -707,6 +715,12 @@ class _$GeneralSettingsCWProxyImpl implements _$GeneralSettingsCWProxy { ? _value.smallWebTabType // ignore: cast_nullable_to_non_nullable : smallWebTabType as TabType, + tabBarLongPressUrlCopy: + tabBarLongPressUrlCopy == const $CopyWithPlaceholder() || + tabBarLongPressUrlCopy == null + ? _value.tabBarLongPressUrlCopy + // ignore: cast_nullable_to_non_nullable + : tabBarLongPressUrlCopy as bool, unshortenerEnabled: unshortenerEnabled == const $CopyWithPlaceholder() || unshortenerEnabled == null @@ -826,6 +840,7 @@ GeneralSettings _$GeneralSettingsFromJson( _$TabTypeEnumMap, json['smallWebTabType'], ), + tabBarLongPressUrlCopy: json['tabBarLongPressUrlCopy'] as bool?, unshortenerEnabled: json['unshortenerEnabled'] as bool?, unshortenerToken: json['unshortenerToken'] as String?, ); @@ -889,6 +904,7 @@ Map _$GeneralSettingsToJson( 'urlCleanerLastCheckEpochMs': instance.urlCleanerLastCheckEpochMs, 'urlCleanerLastUpdateWasAuto': instance.urlCleanerLastUpdateWasAuto, 'smallWebTabType': _$TabTypeEnumMap[instance.smallWebTabType]!, + 'tabBarLongPressUrlCopy': instance.tabBarLongPressUrlCopy, 'unshortenerEnabled': instance.unshortenerEnabled, 'unshortenerToken': instance.unshortenerToken, }; diff --git a/app/lib/features/user/domain/providers.g.dart b/app/lib/features/user/domain/providers.g.dart index 9f621e21..c14f4c22 100644 --- a/app/lib/features/user/domain/providers.g.dart +++ b/app/lib/features/user/domain/providers.g.dart @@ -200,4 +200,4 @@ final class BackupListProvider } } -String _$backupListHash() => r'cdce1b5f195f0c9b72132f7da0c9d173dfc119eb'; +String _$backupListHash() => r'527bfdab7b537b08764ff77dd69de14d38846d41'; diff --git a/app/lib/features/user/domain/repositories/general_settings.dart b/app/lib/features/user/domain/repositories/general_settings.dart index 1c602865..f8fd8104 100644 --- a/app/lib/features/user/domain/repositories/general_settings.dart +++ b/app/lib/features/user/domain/repositories/general_settings.dart @@ -217,6 +217,10 @@ class GeneralSettingsRepository extends _$GeneralSettingsRepository { DriftSqlType.string, db.typeMapping, ), + 'tabBarLongPressUrlCopy': settings['tabBarLongPressUrlCopy']?.readAs( + DriftSqlType.bool, + db.typeMapping, + ), 'unshortenerEnabled': settings['unshortenerEnabled']?.readAs( DriftSqlType.bool, db.typeMapping, diff --git a/app/lib/features/user/domain/services/user_backup.g.dart b/app/lib/features/user/domain/services/user_backup.g.dart index 9ce1b419..06600ab3 100644 --- a/app/lib/features/user/domain/services/user_backup.g.dart +++ b/app/lib/features/user/domain/services/user_backup.g.dart @@ -41,7 +41,7 @@ final class UserBackupServiceProvider } } -String _$userBackupServiceHash() => r'74cd6fd9818a8350a91b1225d904e23f48bc9e30'; +String _$userBackupServiceHash() => r'3746ae59d490e25a44815c125f30cd0981de555d'; abstract class _$UserBackupService extends $Notifier { void build(); diff --git a/app/lib/presentation/widgets/uri_breadcrumb.dart b/app/lib/presentation/widgets/uri_breadcrumb.dart index 25334eda..b396c8bb 100644 --- a/app/lib/presentation/widgets/uri_breadcrumb.dart +++ b/app/lib/presentation/widgets/uri_breadcrumb.dart @@ -25,13 +25,21 @@ class UriBreadcrumb extends StatelessWidget { final Uri uri; final Widget? icon; final TextStyle? style; + final void Function()? onTooltipTriggered; - const UriBreadcrumb({super.key, required this.uri, this.icon, this.style}); + const UriBreadcrumb({ + super.key, + required this.uri, + this.icon, + this.style, + this.onTooltipTriggered, + }); @override Widget build(BuildContext context) { return Tooltip( message: uri.toString(), + onTriggered: onTooltipTriggered, child: DefaultTextStyle( style: style ?? DefaultTextStyle.of(context).style, child: FadingScroll(