Skip to content

Commit 5db1061

Browse files
authored
feat: Open URL from item description on long press (#1132)
1 parent e15147a commit 5db1061

3 files changed

Lines changed: 49 additions & 0 deletions

File tree

kitchenowl/lib/helpers/url_launcher.dart

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,12 @@ bool isValidUrl(String url) {
5757
return false;
5858
}
5959
}
60+
61+
final RegExp _urlPattern = RegExp(r'https?://\S+');
62+
63+
/// Returns the URL contained in [text] if there is exactly one, otherwise null.
64+
String? extractSingleUrl(String text) {
65+
final matches = _urlPattern.allMatches(text).map((m) => m.group(0)!).toList();
66+
67+
return matches.length == 1 ? matches.first : null;
68+
}

kitchenowl/lib/l10n/app_en.arb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@
103103
"@discover": {},
104104
"@done": {},
105105
"@dynamicAccentColor": {},
106+
"@edit": {},
106107
"@email": {},
107108
"@emailInvalid": {},
108109
"@emailNotVerified": {},
@@ -283,6 +284,7 @@
283284
}
284285
},
285286
"@onboardingTitle": {},
287+
"@openUrl": {},
286288
"@optional": {},
287289
"@or": {},
288290
"@ordering": {},
@@ -568,6 +570,7 @@
568570
"discover": "Discover",
569571
"done": "Done",
570572
"dynamicAccentColor": "Dynamic accent color",
573+
"edit": "Edit",
571574
"email": "Email",
572575
"emailInvalid": "Invalid email",
573576
"emailNotVerified": "Not verified",
@@ -671,6 +674,7 @@
671674
"onboardingLoading": "Importing language, this could take a while. Please be patient :)",
672675
"onboardingSettingsTitle": "Hi {name}, let's set up the server!",
673676
"onboardingTitle": "Let's create a user",
677+
"openUrl": "Open URL",
674678
"optional": "Optional",
675679
"or": "or",
676680
"ordering": "Ordering",

kitchenowl/lib/widgets/sliver_item_grid_list.dart

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
33
import 'package:kitchenowl/cubits/household_cubit.dart';
44
import 'package:kitchenowl/enums/update_enum.dart';
55
import 'package:kitchenowl/helpers/build_context_extension.dart';
6+
import 'package:kitchenowl/helpers/url_launcher.dart';
67
import 'package:kitchenowl/kitchenowl.dart';
78
import 'package:kitchenowl/models/category.dart';
89
import 'package:kitchenowl/models/item.dart';
@@ -88,6 +89,41 @@ class SliverItemGridList<T extends Item> extends StatelessWidget {
8889
}
8990

9091
Future<void> openMenu(BuildContext context, Item item) async {
92+
final url =
93+
item is ItemWithDescription ? extractSingleUrl(item.description) : null;
94+
if (url == null) return _openItemPage(context, item);
95+
96+
await showModalBottomSheet<void>(
97+
context: context,
98+
showDragHandle: true,
99+
builder: (ctx) => SafeArea(
100+
child: Column(
101+
mainAxisSize: MainAxisSize.min,
102+
children: [
103+
ListTile(
104+
leading: const Icon(Icons.edit_outlined),
105+
title: Text(AppLocalizations.of(ctx)!.edit),
106+
onTap: () {
107+
Navigator.of(ctx).pop();
108+
_openItemPage(context, item);
109+
},
110+
),
111+
ListTile(
112+
leading: const Icon(Icons.open_in_new_rounded),
113+
title: Text(AppLocalizations.of(ctx)!.openUrl),
114+
onTap: () {
115+
Navigator.of(ctx).pop();
116+
openUrl(context, url);
117+
},
118+
),
119+
const SizedBox(height: 8),
120+
],
121+
),
122+
),
123+
);
124+
}
125+
126+
Future<void> _openItemPage(BuildContext context, Item item) async {
91127
final res = await Navigator.of(context, rootNavigator: true)
92128
.push<UpdateValue<Item>>(
93129
MaterialPageRoute(builder: (ctx) {

0 commit comments

Comments
 (0)