long press copy link text
This commit is contained in:
@@ -36,6 +36,13 @@ extension HitResultJson on HitResult {
|
||||
}
|
||||
|
||||
extension HitResultX on HitResult {
|
||||
String? getLinkText() {
|
||||
return switch (this) {
|
||||
UnknownHitResult(linkText: final linkText) => linkText,
|
||||
_ => null,
|
||||
};
|
||||
}
|
||||
|
||||
Uri? tryGetLink() {
|
||||
const maxTitleLength = 2500;
|
||||
|
||||
@@ -91,6 +98,8 @@ extension HitResultX on HitResult {
|
||||
|
||||
bool get hasLink => tryGetLink() != null;
|
||||
|
||||
bool get hasLinkText => getLinkText()?.isNotEmpty == true;
|
||||
|
||||
bool isImage() {
|
||||
return (this is ImageHitResult || this is ImageSrcHitResult) && hasSrc;
|
||||
}
|
||||
@@ -131,7 +140,10 @@ extension HitResultX on HitResult {
|
||||
|
||||
HitResult withCleanedLink(String cleanedUrl) {
|
||||
return switch (this) {
|
||||
UnknownHitResult() => UnknownHitResult(src: cleanedUrl),
|
||||
UnknownHitResult(:final linkText) => UnknownHitResult(
|
||||
src: cleanedUrl,
|
||||
linkText: linkText,
|
||||
),
|
||||
ImageSrcHitResult(:final src) => ImageSrcHitResult(
|
||||
src: src,
|
||||
uri: cleanedUrl,
|
||||
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 2024-2026 Fabian Freund.
|
||||
*
|
||||
* This file is part of WebLibre
|
||||
* (see https://weblibre.eu).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_material_design_icons/flutter_material_design_icons.dart';
|
||||
import 'package:flutter_mozilla_components/flutter_mozilla_components.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:nullability/nullability.dart';
|
||||
import 'package:weblibre/features/geckoview/features/contextmenu/extensions/hit_result.dart';
|
||||
|
||||
class CopyLinkText extends HookConsumerWidget {
|
||||
final HitResult hitResult;
|
||||
|
||||
const CopyLinkText({super.key, required this.hitResult});
|
||||
|
||||
static bool isSupported(HitResult hitResult) {
|
||||
return hitResult.isUri() && hitResult.hasLinkText;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
return ListTile(
|
||||
leading: const Icon(MdiIcons.textShort),
|
||||
title: const Text('Copy link text'),
|
||||
onTap: () async {
|
||||
await hitResult.getLinkText().mapNotNull((linkText) async {
|
||||
await Clipboard.setData(ClipboardData(text: linkText));
|
||||
|
||||
if (context.mounted) {
|
||||
context.pop();
|
||||
}
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,7 @@ import 'package:weblibre/features/geckoview/features/contextmenu/presentation/ca
|
||||
import 'package:weblibre/features/geckoview/features/contextmenu/presentation/candidates/copy_image.dart';
|
||||
import 'package:weblibre/features/geckoview/features/contextmenu/presentation/candidates/copy_image_location.dart';
|
||||
import 'package:weblibre/features/geckoview/features/contextmenu/presentation/candidates/copy_link.dart';
|
||||
import 'package:weblibre/features/geckoview/features/contextmenu/presentation/candidates/copy_link_text.dart';
|
||||
import 'package:weblibre/features/geckoview/features/contextmenu/presentation/candidates/launch_external.dart';
|
||||
import 'package:weblibre/features/geckoview/features/contextmenu/presentation/candidates/open_image_new_tab.dart';
|
||||
import 'package:weblibre/features/geckoview/features/contextmenu/presentation/candidates/open_in_container.dart';
|
||||
@@ -112,6 +113,8 @@ class ContextMenuDialog extends HookConsumerWidget {
|
||||
if (showContainerUi && OpenInContainer.isSupported(effective))
|
||||
OpenInContainer(hitResult: effective),
|
||||
if (CopyLink.isSupported(effective)) CopyLink(hitResult: effective),
|
||||
if (CopyLinkText.isSupported(effective))
|
||||
CopyLinkText(hitResult: effective),
|
||||
if (SaveFile.isSupported(effective)) SaveFile(hitResult: effective),
|
||||
if (ShareLink.isSupported(effective)) ShareLink(hitResult: effective),
|
||||
if (ShareImage.isSupported(effective)) ShareImage(hitResult: effective),
|
||||
|
||||
Reference in New Issue
Block a user