mirror of
https://github.com/immich-app/immich
synced 2025-10-17 18:19:27 +00:00
feat: open asset from activities page on list tile tap
feat: remove autofocus on activity page open feat: made only activity tile thumbnail image tappable
This commit is contained in:
parent
8fe54a4de1
commit
aa7027bb95
2 changed files with 76 additions and 17 deletions
|
|
@ -13,24 +13,25 @@ class ActivityTextField extends HookConsumerWidget {
|
||||||
final String? likeId;
|
final String? likeId;
|
||||||
final Function(String) onSubmit;
|
final Function(String) onSubmit;
|
||||||
|
|
||||||
const ActivityTextField({required this.onSubmit, this.isEnabled = true, this.likeId, super.key});
|
const ActivityTextField({
|
||||||
|
required this.onSubmit,
|
||||||
|
this.isEnabled = true,
|
||||||
|
this.likeId,
|
||||||
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final album = ref.watch(currentAlbumProvider)!;
|
final album = ref.watch(currentAlbumProvider)!;
|
||||||
final asset = ref.watch(currentAssetProvider);
|
final asset = ref.watch(currentAssetProvider);
|
||||||
final activityNotifier = ref.read(albumActivityProvider(album.remoteId!, asset?.remoteId).notifier);
|
final activityNotifier = ref.read(
|
||||||
|
albumActivityProvider(album.remoteId!, asset?.remoteId).notifier,
|
||||||
|
);
|
||||||
final user = ref.watch(currentUserProvider);
|
final user = ref.watch(currentUserProvider);
|
||||||
final inputController = useTextEditingController();
|
final inputController = useTextEditingController();
|
||||||
final inputFocusNode = useFocusNode();
|
final inputFocusNode = useFocusNode();
|
||||||
final liked = likeId != null;
|
final liked = likeId != null;
|
||||||
|
|
||||||
// Show keyboard immediately on activities open
|
|
||||||
useEffect(() {
|
|
||||||
inputFocusNode.requestFocus();
|
|
||||||
return null;
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
// Pass text to callback and reset controller
|
// Pass text to callback and reset controller
|
||||||
void onEditingComplete() {
|
void onEditingComplete() {
|
||||||
onSubmit(inputController.text);
|
onSubmit(inputController.text);
|
||||||
|
|
@ -68,13 +69,21 @@ class ActivityTextField extends HookConsumerWidget {
|
||||||
suffixIcon: Padding(
|
suffixIcon: Padding(
|
||||||
padding: const EdgeInsets.only(right: 10),
|
padding: const EdgeInsets.only(right: 10),
|
||||||
child: IconButton(
|
child: IconButton(
|
||||||
icon: Icon(liked ? Icons.favorite_rounded : Icons.favorite_border_rounded),
|
icon: Icon(
|
||||||
|
liked ? Icons.favorite_rounded : Icons.favorite_border_rounded,
|
||||||
|
),
|
||||||
onPressed: liked ? removeLike : addLike,
|
onPressed: liked ? removeLike : addLike,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
suffixIconColor: liked ? Colors.red[700] : null,
|
suffixIconColor: liked ? Colors.red[700] : null,
|
||||||
hintText: !isEnabled ? 'shared_album_activities_input_disable'.tr() : 'say_something'.tr(),
|
hintText: !isEnabled
|
||||||
hintStyle: TextStyle(fontWeight: FontWeight.normal, fontSize: 14, color: Colors.grey[600]),
|
? 'shared_album_activities_input_disable'.tr()
|
||||||
|
: 'say_something'.tr(),
|
||||||
|
hintStyle: TextStyle(
|
||||||
|
fontWeight: FontWeight.normal,
|
||||||
|
fontSize: 14,
|
||||||
|
color: Colors.grey[600],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
onEditingComplete: onEditingComplete,
|
onEditingComplete: onEditingComplete,
|
||||||
onTapOutside: (_) => inputFocusNode.unfocus(),
|
onTapOutside: (_) => inputFocusNode.unfocus(),
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,15 @@
|
||||||
|
import 'package:auto_route/auto_route.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||||
import 'package:immich_mobile/extensions/datetime_extensions.dart';
|
import 'package:immich_mobile/extensions/datetime_extensions.dart';
|
||||||
import 'package:immich_mobile/models/activities/activity.model.dart';
|
import 'package:immich_mobile/models/activities/activity.model.dart';
|
||||||
import 'package:immich_mobile/providers/image/immich_remote_thumbnail_provider.dart';
|
|
||||||
import 'package:immich_mobile/providers/asset_viewer/current_asset.provider.dart';
|
import 'package:immich_mobile/providers/asset_viewer/current_asset.provider.dart';
|
||||||
|
import 'package:immich_mobile/providers/asset_viewer/show_controls.provider.dart';
|
||||||
|
import 'package:immich_mobile/providers/image/immich_remote_thumbnail_provider.dart';
|
||||||
|
import 'package:immich_mobile/repositories/asset.repository.dart';
|
||||||
|
import 'package:immich_mobile/routing/router.dart';
|
||||||
|
import 'package:immich_mobile/widgets/asset_grid/asset_grid_data_structure.dart';
|
||||||
import 'package:immich_mobile/widgets/common/user_circle_avatar.dart';
|
import 'package:immich_mobile/widgets/common/user_circle_avatar.dart';
|
||||||
|
|
||||||
class ActivityTile extends HookConsumerWidget {
|
class ActivityTile extends HookConsumerWidget {
|
||||||
|
|
@ -14,6 +19,36 @@ class ActivityTile extends HookConsumerWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
Future<void> onTap() async {
|
||||||
|
if (activity.assetId == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final asset = await ref
|
||||||
|
.read(assetRepositoryProvider)
|
||||||
|
.getByRemoteId(activity.assetId!);
|
||||||
|
if (asset == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final renderList = await RenderList.fromAssets([
|
||||||
|
asset,
|
||||||
|
], GroupAssetsBy.none);
|
||||||
|
final assetNotifier = ref.read(currentAssetProvider.notifier);
|
||||||
|
assetNotifier.set(asset);
|
||||||
|
if (asset.isVideo) {
|
||||||
|
ref.read(showControlsProvider.notifier).show = false;
|
||||||
|
}
|
||||||
|
await context.pushRoute(
|
||||||
|
GalleryViewerRoute(
|
||||||
|
initialIndex: 0,
|
||||||
|
heroOffset: 0,
|
||||||
|
renderList: renderList,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
assetNotifier.set(null);
|
||||||
|
}
|
||||||
|
|
||||||
final asset = ref.watch(currentAssetProvider);
|
final asset = ref.watch(currentAssetProvider);
|
||||||
final isLike = activity.type == ActivityType.like;
|
final isLike = activity.type == ActivityType.like;
|
||||||
// Asset thumbnail is displayed when we are accessing activities from the album page
|
// Asset thumbnail is displayed when we are accessing activities from the album page
|
||||||
|
|
@ -35,8 +70,15 @@ class ActivityTile extends HookConsumerWidget {
|
||||||
leftAlign: isLike || showAssetThumbnail,
|
leftAlign: isLike || showAssetThumbnail,
|
||||||
),
|
),
|
||||||
// No subtitle for like, so center title
|
// No subtitle for like, so center title
|
||||||
titleAlignment: !isLike ? ListTileTitleAlignment.top : ListTileTitleAlignment.center,
|
titleAlignment: !isLike
|
||||||
trailing: showAssetThumbnail ? _ActivityAssetThumbnail(activity.assetId!) : null,
|
? ListTileTitleAlignment.top
|
||||||
|
: ListTileTitleAlignment.center,
|
||||||
|
trailing: showAssetThumbnail
|
||||||
|
? GestureDetector(
|
||||||
|
onTap: onTap,
|
||||||
|
child: _ActivityAssetThumbnail(activity.assetId!),
|
||||||
|
)
|
||||||
|
: null,
|
||||||
subtitle: !isLike ? Text(activity.comment!) : null,
|
subtitle: !isLike ? Text(activity.comment!) : null,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -47,15 +89,23 @@ class _ActivityTitle extends StatelessWidget {
|
||||||
final String createdAt;
|
final String createdAt;
|
||||||
final bool leftAlign;
|
final bool leftAlign;
|
||||||
|
|
||||||
const _ActivityTitle({required this.userName, required this.createdAt, required this.leftAlign});
|
const _ActivityTitle({
|
||||||
|
required this.userName,
|
||||||
|
required this.createdAt,
|
||||||
|
required this.leftAlign,
|
||||||
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final textColor = context.isDarkTheme ? Colors.white : Colors.black;
|
final textColor = context.isDarkTheme ? Colors.white : Colors.black;
|
||||||
final textStyle = context.textTheme.bodyMedium?.copyWith(color: textColor.withValues(alpha: 0.6));
|
final textStyle = context.textTheme.bodyMedium?.copyWith(
|
||||||
|
color: textColor.withValues(alpha: 0.6),
|
||||||
|
);
|
||||||
|
|
||||||
return Row(
|
return Row(
|
||||||
mainAxisAlignment: leftAlign ? MainAxisAlignment.start : MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: leftAlign
|
||||||
|
? MainAxisAlignment.start
|
||||||
|
: MainAxisAlignment.spaceBetween,
|
||||||
mainAxisSize: leftAlign ? MainAxisSize.min : MainAxisSize.max,
|
mainAxisSize: leftAlign ? MainAxisSize.min : MainAxisSize.max,
|
||||||
children: [
|
children: [
|
||||||
Text(userName, style: textStyle, overflow: TextOverflow.ellipsis),
|
Text(userName, style: textStyle, overflow: TextOverflow.ellipsis),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue