mirror of
https://github.com/immich-app/immich.git
synced 2026-03-22 11:09:21 +03:00
feat(mobile): open in browser (#26369)
* feat(mobile): open in browser * chore: open in browser instead of webview * chore: allow archived asset * fix: moved openinbrowser above unstack * feat: deeplink into favorites, trash & archived * fix: use remoteId (for tests to succeed) --------- Co-authored-by: Alex <alex.tran1502@gmail.com>
This commit is contained in:
@@ -1651,6 +1651,7 @@
|
|||||||
"only_favorites": "Only favorites",
|
"only_favorites": "Only favorites",
|
||||||
"open": "Open",
|
"open": "Open",
|
||||||
"open_calendar": "Open calendar",
|
"open_calendar": "Open calendar",
|
||||||
|
"open_in_browser": "Open in browser",
|
||||||
"open_in_map_view": "Open in map view",
|
"open_in_map_view": "Open in map view",
|
||||||
"open_in_openstreetmap": "Open in OpenStreetMap",
|
"open_in_openstreetmap": "Open in OpenStreetMap",
|
||||||
"open_the_search_filters": "Open the search filters",
|
"open_the_search_filters": "Open the search filters",
|
||||||
|
|||||||
@@ -0,0 +1,61 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:immich_mobile/domain/models/store.model.dart';
|
||||||
|
import 'package:immich_mobile/domain/services/timeline.service.dart';
|
||||||
|
import 'package:immich_mobile/entities/store.entity.dart';
|
||||||
|
import 'package:immich_mobile/extensions/translate_extensions.dart';
|
||||||
|
import 'package:immich_mobile/presentation/widgets/action_buttons/base_action_button.widget.dart';
|
||||||
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
|
||||||
|
class OpenInBrowserActionButton extends ConsumerWidget {
|
||||||
|
final String remoteId;
|
||||||
|
final TimelineOrigin origin;
|
||||||
|
final bool iconOnly;
|
||||||
|
final bool menuItem;
|
||||||
|
final Color? iconColor;
|
||||||
|
|
||||||
|
const OpenInBrowserActionButton({
|
||||||
|
super.key,
|
||||||
|
required this.remoteId,
|
||||||
|
required this.origin,
|
||||||
|
this.iconOnly = false,
|
||||||
|
this.menuItem = false,
|
||||||
|
this.iconColor,
|
||||||
|
});
|
||||||
|
|
||||||
|
void _onTap() async {
|
||||||
|
final serverEndpoint = Store.get(StoreKey.serverEndpoint).replaceFirst('/api', '');
|
||||||
|
|
||||||
|
String originPath = '';
|
||||||
|
switch (origin) {
|
||||||
|
case TimelineOrigin.favorite:
|
||||||
|
originPath = '/favorites';
|
||||||
|
break;
|
||||||
|
case TimelineOrigin.trash:
|
||||||
|
originPath = '/trash';
|
||||||
|
break;
|
||||||
|
case TimelineOrigin.archive:
|
||||||
|
originPath = '/archive';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
final url = '$serverEndpoint$originPath/photos/$remoteId';
|
||||||
|
if (await canLaunchUrl(Uri.parse(url))) {
|
||||||
|
await launchUrl(Uri.parse(url), mode: LaunchMode.externalApplication);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
return BaseActionButton(
|
||||||
|
label: 'open_in_browser'.t(context: context),
|
||||||
|
iconData: Icons.open_in_browser,
|
||||||
|
iconColor: iconColor,
|
||||||
|
iconOnly: iconOnly,
|
||||||
|
menuItem: menuItem,
|
||||||
|
onPressed: _onTap,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,6 +18,7 @@ import 'package:immich_mobile/presentation/widgets/action_buttons/delete_permane
|
|||||||
import 'package:immich_mobile/presentation/widgets/action_buttons/download_action_button.widget.dart';
|
import 'package:immich_mobile/presentation/widgets/action_buttons/download_action_button.widget.dart';
|
||||||
import 'package:immich_mobile/presentation/widgets/action_buttons/like_activity_action_button.widget.dart';
|
import 'package:immich_mobile/presentation/widgets/action_buttons/like_activity_action_button.widget.dart';
|
||||||
import 'package:immich_mobile/presentation/widgets/action_buttons/move_to_lock_folder_action_button.widget.dart';
|
import 'package:immich_mobile/presentation/widgets/action_buttons/move_to_lock_folder_action_button.widget.dart';
|
||||||
|
import 'package:immich_mobile/presentation/widgets/action_buttons/open_in_browser_action_button.widget.dart';
|
||||||
import 'package:immich_mobile/presentation/widgets/action_buttons/remove_from_album_action_button.widget.dart';
|
import 'package:immich_mobile/presentation/widgets/action_buttons/remove_from_album_action_button.widget.dart';
|
||||||
import 'package:immich_mobile/presentation/widgets/action_buttons/remove_from_lock_folder_action_button.widget.dart';
|
import 'package:immich_mobile/presentation/widgets/action_buttons/remove_from_lock_folder_action_button.widget.dart';
|
||||||
import 'package:immich_mobile/presentation/widgets/action_buttons/set_album_cover.widget.dart';
|
import 'package:immich_mobile/presentation/widgets/action_buttons/set_album_cover.widget.dart';
|
||||||
@@ -75,6 +76,7 @@ enum ActionButtonType {
|
|||||||
viewInTimeline,
|
viewInTimeline,
|
||||||
download,
|
download,
|
||||||
upload,
|
upload,
|
||||||
|
openInBrowser,
|
||||||
unstack,
|
unstack,
|
||||||
archive,
|
archive,
|
||||||
unarchive,
|
unarchive,
|
||||||
@@ -149,6 +151,7 @@ enum ActionButtonType {
|
|||||||
context.isOwner && //
|
context.isOwner && //
|
||||||
!context.isInLockedView && //
|
!context.isInLockedView && //
|
||||||
context.isStacked,
|
context.isStacked,
|
||||||
|
ActionButtonType.openInBrowser => context.asset.hasRemote && !context.isInLockedView,
|
||||||
ActionButtonType.likeActivity =>
|
ActionButtonType.likeActivity =>
|
||||||
!context.isInLockedView &&
|
!context.isInLockedView &&
|
||||||
context.currentAlbum != null &&
|
context.currentAlbum != null &&
|
||||||
@@ -236,6 +239,13 @@ enum ActionButtonType {
|
|||||||
),
|
),
|
||||||
ActionButtonType.likeActivity => LikeActivityActionButton(iconOnly: iconOnly, menuItem: menuItem),
|
ActionButtonType.likeActivity => LikeActivityActionButton(iconOnly: iconOnly, menuItem: menuItem),
|
||||||
ActionButtonType.unstack => UnStackActionButton(source: context.source, iconOnly: iconOnly, menuItem: menuItem),
|
ActionButtonType.unstack => UnStackActionButton(source: context.source, iconOnly: iconOnly, menuItem: menuItem),
|
||||||
|
ActionButtonType.openInBrowser => OpenInBrowserActionButton(
|
||||||
|
remoteId: context.asset.remoteId!,
|
||||||
|
origin: context.timelineOrigin,
|
||||||
|
iconOnly: iconOnly,
|
||||||
|
menuItem: menuItem,
|
||||||
|
iconColor: context.originalTheme?.iconTheme.color,
|
||||||
|
),
|
||||||
ActionButtonType.similarPhotos => SimilarPhotosActionButton(
|
ActionButtonType.similarPhotos => SimilarPhotosActionButton(
|
||||||
assetId: (context.asset as RemoteAsset).id,
|
assetId: (context.asset as RemoteAsset).id,
|
||||||
iconOnly: iconOnly,
|
iconOnly: iconOnly,
|
||||||
|
|||||||
Reference in New Issue
Block a user