mirror of
https://github.com/immich-app/immich
synced 2025-11-07 17:27:20 +00:00
feat(mobile): Change the UI of asset activity list to bottom sheet (#23075)
* init of activities bottom sheet * reverse list order, padding bottom... * chore: remove scrolling * chore: clean up * chore --------- Co-authored-by: Alex <alex.tran1502@gmail.com>
This commit is contained in:
parent
05f174a180
commit
becb56e1b1
8 changed files with 243 additions and 27 deletions
|
|
@ -7,6 +7,7 @@ import 'package:immich_mobile/widgets/common/user_circle_avatar.dart';
|
||||||
|
|
||||||
class DriftActivityTextField extends ConsumerStatefulWidget {
|
class DriftActivityTextField extends ConsumerStatefulWidget {
|
||||||
final bool isEnabled;
|
final bool isEnabled;
|
||||||
|
final bool isBottomSheet;
|
||||||
final String? likeId;
|
final String? likeId;
|
||||||
final Function(String) onSubmit;
|
final Function(String) onSubmit;
|
||||||
final Function()? onKeyboardFocus;
|
final Function()? onKeyboardFocus;
|
||||||
|
|
@ -16,6 +17,7 @@ class DriftActivityTextField extends ConsumerStatefulWidget {
|
||||||
this.isEnabled = true,
|
this.isEnabled = true,
|
||||||
this.likeId,
|
this.likeId,
|
||||||
this.onKeyboardFocus,
|
this.onKeyboardFocus,
|
||||||
|
this.isBottomSheet = false,
|
||||||
super.key,
|
super.key,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -34,7 +36,9 @@ class _DriftActivityTextFieldState extends ConsumerState<DriftActivityTextField>
|
||||||
inputController = TextEditingController();
|
inputController = TextEditingController();
|
||||||
inputFocusNode = FocusNode();
|
inputFocusNode = FocusNode();
|
||||||
|
|
||||||
inputFocusNode.requestFocus();
|
if (!widget.isBottomSheet) {
|
||||||
|
inputFocusNode.requestFocus();
|
||||||
|
}
|
||||||
|
|
||||||
inputFocusNode.addListener(() {
|
inputFocusNode.addListener(() {
|
||||||
if (inputFocusNode.hasFocus) {
|
if (inputFocusNode.hasFocus) {
|
||||||
|
|
@ -72,7 +76,7 @@ class _DriftActivityTextFieldState extends ConsumerState<DriftActivityTextField>
|
||||||
}
|
}
|
||||||
|
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
padding: EdgeInsets.symmetric(vertical: widget.isBottomSheet ? 0 : 10),
|
||||||
child: TextField(
|
child: TextField(
|
||||||
controller: inputController,
|
controller: inputController,
|
||||||
enabled: widget.isEnabled,
|
enabled: widget.isEnabled,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,95 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||||
|
import 'package:immich_mobile/extensions/asyncvalue_extensions.dart';
|
||||||
|
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||||
|
import 'package:immich_mobile/presentation/widgets/album/drift_activity_text_field.dart';
|
||||||
|
import 'package:immich_mobile/presentation/widgets/bottom_sheet/base_bottom_sheet.widget.dart';
|
||||||
|
import 'package:immich_mobile/providers/activity.provider.dart';
|
||||||
|
import 'package:immich_mobile/providers/infrastructure/asset_viewer/current_asset.provider.dart';
|
||||||
|
import 'package:immich_mobile/providers/infrastructure/current_album.provider.dart';
|
||||||
|
import 'package:immich_mobile/providers/user.provider.dart';
|
||||||
|
import 'package:immich_mobile/widgets/activities/activity_tile.dart';
|
||||||
|
import 'package:immich_mobile/widgets/activities/dismissible_activity.dart';
|
||||||
|
|
||||||
|
class ActivitiesBottomSheet extends HookConsumerWidget {
|
||||||
|
final DraggableScrollableController controller;
|
||||||
|
final double initialChildSize;
|
||||||
|
final bool scrollToBottomInitially;
|
||||||
|
|
||||||
|
const ActivitiesBottomSheet({
|
||||||
|
required this.controller,
|
||||||
|
this.initialChildSize = 0.35,
|
||||||
|
this.scrollToBottomInitially = true,
|
||||||
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final album = ref.watch(currentRemoteAlbumProvider)!;
|
||||||
|
final asset = ref.watch(currentAssetNotifier) as RemoteAsset?;
|
||||||
|
final user = ref.watch(currentUserProvider);
|
||||||
|
|
||||||
|
final activityNotifier = ref.read(albumActivityProvider(album.id, asset?.id).notifier);
|
||||||
|
final activities = ref.watch(albumActivityProvider(album.id, asset?.id));
|
||||||
|
|
||||||
|
Future<void> onAddComment(String comment) async {
|
||||||
|
await activityNotifier.addComment(comment);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget buildActivitiesSliver() {
|
||||||
|
return activities.widgetWhen(
|
||||||
|
onLoading: () => const SliverToBoxAdapter(child: SizedBox.shrink()),
|
||||||
|
onData: (data) {
|
||||||
|
return SliverList(
|
||||||
|
delegate: SliverChildBuilderDelegate((context, index) {
|
||||||
|
if (index == data.length) {
|
||||||
|
return const SizedBox.shrink();
|
||||||
|
}
|
||||||
|
final activity = data[data.length - 1 - index];
|
||||||
|
final canDelete = activity.user.id == user?.id || album.ownerId == user?.id;
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 1),
|
||||||
|
child: DismissibleActivity(
|
||||||
|
activity.id,
|
||||||
|
ActivityTile(activity, isBottomSheet: true),
|
||||||
|
onDismiss: canDelete
|
||||||
|
? (activityId) async => await activityNotifier.removeActivity(activity.id)
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}, childCount: data.length + 1),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return BaseBottomSheet(
|
||||||
|
actions: [],
|
||||||
|
slivers: [buildActivitiesSliver()],
|
||||||
|
footer: Padding(
|
||||||
|
// TODO: avoid fixed padding, use context.padding.bottom
|
||||||
|
padding: const EdgeInsets.only(bottom: 32),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
const Divider(indent: 16, endIndent: 16),
|
||||||
|
DriftActivityTextField(
|
||||||
|
isEnabled: album.isActivityEnabled,
|
||||||
|
isBottomSheet: true,
|
||||||
|
// likeId: likedId,
|
||||||
|
onSubmit: onAddComment,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
controller: controller,
|
||||||
|
initialChildSize: initialChildSize,
|
||||||
|
minChildSize: 0.1,
|
||||||
|
maxChildSize: 0.88,
|
||||||
|
expand: false,
|
||||||
|
shouldCloseOnMinExtent: false,
|
||||||
|
resizeOnScroll: false,
|
||||||
|
backgroundColor: context.isDarkTheme ? Colors.black : Colors.white,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -20,6 +20,7 @@ import 'package:immich_mobile/presentation/widgets/asset_viewer/bottom_bar.widge
|
||||||
import 'package:immich_mobile/presentation/widgets/asset_viewer/bottom_sheet.widget.dart';
|
import 'package:immich_mobile/presentation/widgets/asset_viewer/bottom_sheet.widget.dart';
|
||||||
import 'package:immich_mobile/presentation/widgets/asset_viewer/top_app_bar.widget.dart';
|
import 'package:immich_mobile/presentation/widgets/asset_viewer/top_app_bar.widget.dart';
|
||||||
import 'package:immich_mobile/presentation/widgets/asset_viewer/video_viewer.widget.dart';
|
import 'package:immich_mobile/presentation/widgets/asset_viewer/video_viewer.widget.dart';
|
||||||
|
import 'package:immich_mobile/presentation/widgets/asset_viewer/activities_bottom_sheet.widget.dart';
|
||||||
import 'package:immich_mobile/presentation/widgets/images/image_provider.dart';
|
import 'package:immich_mobile/presentation/widgets/images/image_provider.dart';
|
||||||
import 'package:immich_mobile/presentation/widgets/images/thumbnail.widget.dart';
|
import 'package:immich_mobile/presentation/widgets/images/thumbnail.widget.dart';
|
||||||
import 'package:immich_mobile/providers/asset_viewer/is_motion_video_playing.provider.dart';
|
import 'package:immich_mobile/providers/asset_viewer/is_motion_video_playing.provider.dart';
|
||||||
|
|
@ -418,7 +419,7 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
|
||||||
|
|
||||||
if (event is ViewerOpenBottomSheetEvent) {
|
if (event is ViewerOpenBottomSheetEvent) {
|
||||||
final extent = _kBottomSheetMinimumExtent + 0.3;
|
final extent = _kBottomSheetMinimumExtent + 0.3;
|
||||||
_openBottomSheet(scaffoldContext!, extent: extent);
|
_openBottomSheet(scaffoldContext!, extent: extent, activitiesMode: event.activitiesMode);
|
||||||
final offset = _getVerticalOffsetForBottomSheet(extent);
|
final offset = _getVerticalOffsetForBottomSheet(extent);
|
||||||
viewController?.position = Offset(0, -offset);
|
viewController?.position = Offset(0, -offset);
|
||||||
return;
|
return;
|
||||||
|
|
@ -460,7 +461,7 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void _openBottomSheet(BuildContext ctx, {double extent = _kBottomSheetMinimumExtent}) {
|
void _openBottomSheet(BuildContext ctx, {double extent = _kBottomSheetMinimumExtent, bool activitiesMode = false}) {
|
||||||
ref.read(assetViewerProvider.notifier).setBottomSheet(true);
|
ref.read(assetViewerProvider.notifier).setBottomSheet(true);
|
||||||
initialScale = viewController?.scale;
|
initialScale = viewController?.scale;
|
||||||
// viewController?.updateMultiple(scale: (viewController?.scale ?? 1.0) + 0.01);
|
// viewController?.updateMultiple(scale: (viewController?.scale ?? 1.0) + 0.01);
|
||||||
|
|
@ -474,7 +475,9 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
|
||||||
builder: (_) {
|
builder: (_) {
|
||||||
return NotificationListener<Notification>(
|
return NotificationListener<Notification>(
|
||||||
onNotification: _onNotification,
|
onNotification: _onNotification,
|
||||||
child: AssetDetailBottomSheet(controller: bottomSheetController, initialChildSize: extent),
|
child: activitiesMode
|
||||||
|
? ActivitiesBottomSheet(controller: bottomSheetController, initialChildSize: extent)
|
||||||
|
: AssetDetailBottomSheet(controller: bottomSheetController, initialChildSize: extent),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,8 @@ import 'package:immich_mobile/providers/asset_viewer/video_player_controls_provi
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
|
||||||
class ViewerOpenBottomSheetEvent extends Event {
|
class ViewerOpenBottomSheetEvent extends Event {
|
||||||
const ViewerOpenBottomSheetEvent();
|
final bool activitiesMode;
|
||||||
|
const ViewerOpenBottomSheetEvent({this.activitiesMode = false});
|
||||||
}
|
}
|
||||||
|
|
||||||
class ViewerReloadAssetEvent extends Event {
|
class ViewerReloadAssetEvent extends Event {
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ import 'package:immich_mobile/presentation/widgets/action_buttons/favorite_actio
|
||||||
import 'package:immich_mobile/presentation/widgets/action_buttons/motion_photo_action_button.widget.dart';
|
import 'package:immich_mobile/presentation/widgets/action_buttons/motion_photo_action_button.widget.dart';
|
||||||
import 'package:immich_mobile/presentation/widgets/action_buttons/unfavorite_action_button.widget.dart';
|
import 'package:immich_mobile/presentation/widgets/action_buttons/unfavorite_action_button.widget.dart';
|
||||||
import 'package:immich_mobile/presentation/widgets/asset_viewer/asset_viewer.state.dart';
|
import 'package:immich_mobile/presentation/widgets/asset_viewer/asset_viewer.state.dart';
|
||||||
|
import 'package:immich_mobile/providers/activity.provider.dart';
|
||||||
import 'package:immich_mobile/providers/cast.provider.dart';
|
import 'package:immich_mobile/providers/cast.provider.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/asset_viewer/current_asset.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/asset_viewer/current_asset.provider.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/current_album.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/current_album.provider.dart';
|
||||||
|
|
@ -53,6 +54,10 @@ class ViewerTopAppBar extends ConsumerWidget implements PreferredSizeWidget {
|
||||||
int opacity = ref.watch(assetViewerProvider.select((state) => state.backgroundOpacity));
|
int opacity = ref.watch(assetViewerProvider.select((state) => state.backgroundOpacity));
|
||||||
final showControls = ref.watch(assetViewerProvider.select((s) => s.showingControls));
|
final showControls = ref.watch(assetViewerProvider.select((s) => s.showingControls));
|
||||||
|
|
||||||
|
if (album != null && album.isActivityEnabled && album.isShared && asset is RemoteAsset) {
|
||||||
|
ref.watch(albumActivityProvider(album.id, asset.id));
|
||||||
|
}
|
||||||
|
|
||||||
if (!showControls) {
|
if (!showControls) {
|
||||||
opacity = 0;
|
opacity = 0;
|
||||||
}
|
}
|
||||||
|
|
@ -66,7 +71,7 @@ class ViewerTopAppBar extends ConsumerWidget implements PreferredSizeWidget {
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: const Icon(Icons.chat_outlined),
|
icon: const Icon(Icons.chat_outlined),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
context.navigateTo(const DriftActivitiesRoute());
|
EventStream.shared.emit(const ViewerOpenBottomSheetEvent(activitiesMode: true));
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
if (showViewInTimelineButton)
|
if (showViewInTimelineButton)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,92 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||||
|
import 'package:immich_mobile/extensions/asyncvalue_extensions.dart';
|
||||||
|
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||||
|
import 'package:immich_mobile/presentation/widgets/album/drift_activity_text_field.dart';
|
||||||
|
import 'package:immich_mobile/providers/activity.provider.dart';
|
||||||
|
import 'package:immich_mobile/providers/infrastructure/asset_viewer/current_asset.provider.dart';
|
||||||
|
import 'package:immich_mobile/providers/infrastructure/current_album.provider.dart';
|
||||||
|
import 'package:immich_mobile/providers/user.provider.dart';
|
||||||
|
import 'package:immich_mobile/widgets/activities/activity_tile.dart';
|
||||||
|
import 'package:immich_mobile/widgets/activities/dismissible_activity.dart';
|
||||||
|
import 'base_bottom_sheet.widget.dart';
|
||||||
|
|
||||||
|
class ActivitiesBottomSheet extends HookConsumerWidget {
|
||||||
|
final DraggableScrollableController controller;
|
||||||
|
final double initialChildSize;
|
||||||
|
final bool scrollToBottomInitially;
|
||||||
|
|
||||||
|
const ActivitiesBottomSheet({
|
||||||
|
required this.controller,
|
||||||
|
this.initialChildSize = 0.35,
|
||||||
|
this.scrollToBottomInitially = true,
|
||||||
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final album = ref.watch(currentRemoteAlbumProvider)!;
|
||||||
|
final asset = ref.watch(currentAssetNotifier) as RemoteAsset?;
|
||||||
|
final user = ref.watch(currentUserProvider);
|
||||||
|
|
||||||
|
final activityNotifier = ref.read(albumActivityProvider(album.id, asset?.id).notifier);
|
||||||
|
final activities = ref.watch(albumActivityProvider(album.id, asset?.id));
|
||||||
|
|
||||||
|
Future<void> onAddComment(String comment) async {
|
||||||
|
await activityNotifier.addComment(comment);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget buildActivitiesSliver() {
|
||||||
|
return activities.widgetWhen(
|
||||||
|
onLoading: () => const SliverToBoxAdapter(child: SizedBox.shrink()),
|
||||||
|
onData: (data) {
|
||||||
|
return SliverList(
|
||||||
|
delegate: SliverChildBuilderDelegate((context, index) {
|
||||||
|
if (index == data.length) {
|
||||||
|
// return const SizedBox(height: 5);
|
||||||
|
return const SizedBox.shrink();
|
||||||
|
}
|
||||||
|
final activity = data[index];
|
||||||
|
final canDelete = activity.user.id == user?.id || album.ownerId == user?.id;
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 1),
|
||||||
|
child: DismissibleActivity(
|
||||||
|
activity.id,
|
||||||
|
ActivityTile(activity),
|
||||||
|
onDismiss: canDelete
|
||||||
|
? (activityId) async => await activityNotifier.removeActivity(activity.id)
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}, childCount: data.length + 1),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return BaseBottomSheet(
|
||||||
|
actions: [],
|
||||||
|
slivers: [buildActivitiesSliver()],
|
||||||
|
footer: Column(
|
||||||
|
children: [
|
||||||
|
const Divider(indent: 16, endIndent: 16),
|
||||||
|
DriftActivityTextField(
|
||||||
|
isEnabled: album.isActivityEnabled,
|
||||||
|
isBottomSheet: true,
|
||||||
|
// likeId: likedId,
|
||||||
|
onSubmit: onAddComment,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
controller: controller,
|
||||||
|
initialChildSize: initialChildSize,
|
||||||
|
minChildSize: 0.1,
|
||||||
|
maxChildSize: 0.88,
|
||||||
|
expand: false,
|
||||||
|
shouldCloseOnMinExtent: false,
|
||||||
|
resizeOnScroll: false,
|
||||||
|
backgroundColor: context.isDarkTheme ? Colors.black : Colors.white,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -8,6 +8,7 @@ class BaseBottomSheet extends ConsumerStatefulWidget {
|
||||||
final List<Widget> actions;
|
final List<Widget> actions;
|
||||||
final DraggableScrollableController? controller;
|
final DraggableScrollableController? controller;
|
||||||
final List<Widget>? slivers;
|
final List<Widget>? slivers;
|
||||||
|
final Widget? footer;
|
||||||
final double initialChildSize;
|
final double initialChildSize;
|
||||||
final double minChildSize;
|
final double minChildSize;
|
||||||
final double maxChildSize;
|
final double maxChildSize;
|
||||||
|
|
@ -20,6 +21,7 @@ class BaseBottomSheet extends ConsumerStatefulWidget {
|
||||||
super.key,
|
super.key,
|
||||||
required this.actions,
|
required this.actions,
|
||||||
this.slivers,
|
this.slivers,
|
||||||
|
this.footer,
|
||||||
this.controller,
|
this.controller,
|
||||||
this.initialChildSize = 0.35,
|
this.initialChildSize = 0.35,
|
||||||
double? minChildSize,
|
double? minChildSize,
|
||||||
|
|
@ -73,24 +75,35 @@ class _BaseDraggableScrollableSheetState extends ConsumerState<BaseBottomSheet>
|
||||||
elevation: 3.0,
|
elevation: 3.0,
|
||||||
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.vertical(top: Radius.circular(18))),
|
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.vertical(top: Radius.circular(18))),
|
||||||
margin: const EdgeInsets.symmetric(horizontal: 0),
|
margin: const EdgeInsets.symmetric(horizontal: 0),
|
||||||
child: CustomScrollView(
|
child: Column(
|
||||||
controller: scrollController,
|
children: [
|
||||||
slivers: [
|
Expanded(
|
||||||
const SliverPersistentHeader(delegate: _DragHandleDelegate(), pinned: true),
|
child: CustomScrollView(
|
||||||
if (widget.actions.isNotEmpty)
|
controller: scrollController,
|
||||||
SliverToBoxAdapter(
|
slivers: [
|
||||||
child: Column(
|
const SliverPersistentHeader(delegate: _DragHandleDelegate(), pinned: true),
|
||||||
children: [
|
if (widget.actions.isNotEmpty)
|
||||||
SizedBox(
|
SliverToBoxAdapter(
|
||||||
height: 115,
|
child: Column(
|
||||||
child: ListView(shrinkWrap: true, scrollDirection: Axis.horizontal, children: widget.actions),
|
children: [
|
||||||
|
SizedBox(
|
||||||
|
height: 115,
|
||||||
|
child: ListView(
|
||||||
|
shrinkWrap: true,
|
||||||
|
scrollDirection: Axis.horizontal,
|
||||||
|
children: widget.actions,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Divider(indent: 16, endIndent: 16),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
const Divider(indent: 16, endIndent: 16),
|
if (widget.slivers != null) ...widget.slivers!,
|
||||||
const SizedBox(height: 16),
|
],
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
if (widget.slivers != null) ...widget.slivers!,
|
),
|
||||||
|
if (widget.footer != null) widget.footer!,
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,9 @@ import 'package:immich_mobile/widgets/common/user_circle_avatar.dart';
|
||||||
|
|
||||||
class ActivityTile extends HookConsumerWidget {
|
class ActivityTile extends HookConsumerWidget {
|
||||||
final Activity activity;
|
final Activity activity;
|
||||||
|
final bool isBottomSheet;
|
||||||
|
|
||||||
const ActivityTile(this.activity, {super.key});
|
const ActivityTile(this.activity, {super.key, this.isBottomSheet = false});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
|
@ -18,21 +19,23 @@ class ActivityTile extends HookConsumerWidget {
|
||||||
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
|
||||||
// currentAssetProvider will not be set until we open the gallery viewer
|
// currentAssetProvider will not be set until we open the gallery viewer
|
||||||
final showAssetThumbnail = asset == null && activity.assetId != null;
|
final showAssetThumbnail = asset == null && activity.assetId != null && !isBottomSheet;
|
||||||
|
|
||||||
return ListTile(
|
return ListTile(
|
||||||
minVerticalPadding: 15,
|
minVerticalPadding: 15,
|
||||||
leading: isLike
|
leading: isLike
|
||||||
? Container(
|
? Container(
|
||||||
width: 44,
|
width: isBottomSheet ? 30 : 44,
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
child: Icon(Icons.favorite_rounded, color: Colors.red[700]),
|
child: Icon(Icons.favorite_rounded, color: Colors.red[700]),
|
||||||
)
|
)
|
||||||
|
: isBottomSheet
|
||||||
|
? UserCircleAvatar(user: activity.user, size: 30, radius: 15)
|
||||||
: UserCircleAvatar(user: activity.user),
|
: UserCircleAvatar(user: activity.user),
|
||||||
title: _ActivityTitle(
|
title: _ActivityTitle(
|
||||||
userName: activity.user.name,
|
userName: activity.user.name,
|
||||||
createdAt: activity.createdAt.timeAgo(),
|
createdAt: activity.createdAt.timeAgo(),
|
||||||
leftAlign: isLike || showAssetThumbnail,
|
leftAlign: isBottomSheet ? false : (isLike || showAssetThumbnail),
|
||||||
),
|
),
|
||||||
// No subtitle for like, so center title
|
// No subtitle for like, so center title
|
||||||
titleAlignment: !isLike ? ListTileTitleAlignment.top : ListTileTitleAlignment.center,
|
titleAlignment: !isLike ? ListTileTitleAlignment.top : ListTileTitleAlignment.center,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue