Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import 'package:immich_mobile/widgets/common/user_circle_avatar.dart';

class DriftActivityTextField extends ConsumerStatefulWidget {
final bool isEnabled;
final bool isBottomSheet;
final String? likeId;
final Function(String) onSubmit;
final Function()? onKeyboardFocus;
Expand All @@ -16,6 +17,7 @@ class DriftActivityTextField extends ConsumerStatefulWidget {
this.isEnabled = true,
this.likeId,
this.onKeyboardFocus,
this.isBottomSheet = false,
super.key,
});

Expand All @@ -34,7 +36,9 @@ class _DriftActivityTextFieldState extends ConsumerState<DriftActivityTextField>
inputController = TextEditingController();
inputFocusNode = FocusNode();

inputFocusNode.requestFocus();
if (!widget.isBottomSheet) {
inputFocusNode.requestFocus();
}

inputFocusNode.addListener(() {
if (inputFocusNode.hasFocus) {
Expand Down Expand Up @@ -72,7 +76,7 @@ class _DriftActivityTextFieldState extends ConsumerState<DriftActivityTextField>
}

return Padding(
padding: const EdgeInsets.symmetric(vertical: 10),
padding: EdgeInsets.symmetric(vertical: widget.isBottomSheet ? 0 : 10),
child: TextField(
controller: inputController,
enabled: widget.isEnabled,
Expand Down
Original file line number Diff line number Diff line change
@@ -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,
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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/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/activities_bottom_sheet.widget.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/providers/asset_viewer/is_motion_video_playing.provider.dart';
Expand Down Expand Up @@ -418,7 +419,7 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {

if (event is ViewerOpenBottomSheetEvent) {
final extent = _kBottomSheetMinimumExtent + 0.3;
_openBottomSheet(scaffoldContext!, extent: extent);
_openBottomSheet(scaffoldContext!, extent: extent, activitiesMode: event.activitiesMode);
final offset = _getVerticalOffsetForBottomSheet(extent);
viewController?.position = Offset(0, -offset);
return;
Expand Down Expand Up @@ -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);
initialScale = viewController?.scale;
// viewController?.updateMultiple(scale: (viewController?.scale ?? 1.0) + 0.01);
Expand All @@ -474,7 +475,9 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
builder: (_) {
return NotificationListener<Notification>(
onNotification: _onNotification,
child: AssetDetailBottomSheet(controller: bottomSheetController, initialChildSize: extent),
child: activitiesMode
? ActivitiesBottomSheet(controller: bottomSheetController, initialChildSize: extent)
: AssetDetailBottomSheet(controller: bottomSheetController, initialChildSize: extent),
);
},
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import 'package:immich_mobile/providers/asset_viewer/video_player_controls_provi
import 'package:riverpod_annotation/riverpod_annotation.dart';

class ViewerOpenBottomSheetEvent extends Event {
const ViewerOpenBottomSheetEvent();
final bool activitiesMode;
const ViewerOpenBottomSheetEvent({this.activitiesMode = false});
}

class ViewerReloadAssetEvent extends Event {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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/unfavorite_action_button.widget.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/infrastructure/asset_viewer/current_asset.provider.dart';
import 'package:immich_mobile/providers/infrastructure/current_album.provider.dart';
Expand Down Expand Up @@ -53,6 +54,10 @@ class ViewerTopAppBar extends ConsumerWidget implements PreferredSizeWidget {
int opacity = ref.watch(assetViewerProvider.select((state) => state.backgroundOpacity));
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) {
opacity = 0;
}
Expand All @@ -66,7 +71,7 @@ class ViewerTopAppBar extends ConsumerWidget implements PreferredSizeWidget {
IconButton(
icon: const Icon(Icons.chat_outlined),
onPressed: () {
context.navigateTo(const DriftActivitiesRoute());
EventStream.shared.emit(const ViewerOpenBottomSheetEvent(activitiesMode: true));
},
),
if (showViewInTimelineButton)
Expand Down
Original file line number Diff line number Diff line change
@@ -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,
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ class BaseBottomSheet extends ConsumerStatefulWidget {
final List<Widget> actions;
final DraggableScrollableController? controller;
final List<Widget>? slivers;
final Widget? footer;
final double initialChildSize;
final double minChildSize;
final double maxChildSize;
Expand All @@ -20,6 +21,7 @@ class BaseBottomSheet extends ConsumerStatefulWidget {
super.key,
required this.actions,
this.slivers,
this.footer,
this.controller,
this.initialChildSize = 0.35,
double? minChildSize,
Expand Down Expand Up @@ -73,24 +75,35 @@ class _BaseDraggableScrollableSheetState extends ConsumerState<BaseBottomSheet>
elevation: 3.0,
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.vertical(top: Radius.circular(18))),
margin: const EdgeInsets.symmetric(horizontal: 0),
child: CustomScrollView(
controller: scrollController,
slivers: [
const SliverPersistentHeader(delegate: _DragHandleDelegate(), pinned: true),
if (widget.actions.isNotEmpty)
SliverToBoxAdapter(
child: Column(
children: [
SizedBox(
height: 115,
child: ListView(shrinkWrap: true, scrollDirection: Axis.horizontal, children: widget.actions),
child: Column(
children: [
Expanded(
child: CustomScrollView(
controller: scrollController,
slivers: [
const SliverPersistentHeader(delegate: _DragHandleDelegate(), pinned: true),
if (widget.actions.isNotEmpty)
SliverToBoxAdapter(
child: Column(
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),
const SizedBox(height: 16),
],
),
if (widget.slivers != null) ...widget.slivers!,
],
),
if (widget.slivers != null) ...widget.slivers!,
),
if (widget.footer != null) widget.footer!,
],
),
);
Expand Down
Loading
Loading