mirror of
https://github.com/immich-app/immich.git
synced 2026-05-18 03:10:24 +03:00
fix: remove toggle and the exisitng style based on review feedback
This commit is contained in:
@@ -398,8 +398,6 @@
|
|||||||
"admin_password": "Admin Password",
|
"admin_password": "Admin Password",
|
||||||
"administration": "Administration",
|
"administration": "Administration",
|
||||||
"advanced": "Advanced",
|
"advanced": "Advanced",
|
||||||
"advanced_settings_beta_activities_style_subtitle": "Enable chat-style layout for album activities.",
|
|
||||||
"advanced_settings_beta_activities_style_title": "New activities style",
|
|
||||||
"advanced_settings_enable_alternate_media_filter_subtitle": "Use this option to filter media during sync based on alternate criteria. Only try this if you have issues with the app detecting all albums.",
|
"advanced_settings_enable_alternate_media_filter_subtitle": "Use this option to filter media during sync based on alternate criteria. Only try this if you have issues with the app detecting all albums.",
|
||||||
"advanced_settings_enable_alternate_media_filter_title": "[EXPERIMENTAL] Use alternate device album sync filter",
|
"advanced_settings_enable_alternate_media_filter_title": "[EXPERIMENTAL] Use alternate device album sync filter",
|
||||||
"advanced_settings_log_level_title": "Log level: {level}",
|
"advanced_settings_log_level_title": "Log level: {level}",
|
||||||
|
|||||||
@@ -81,8 +81,7 @@ enum StoreKey<T> {
|
|||||||
useWifiForUploadPhotos<bool>._(1005),
|
useWifiForUploadPhotos<bool>._(1005),
|
||||||
needBetaMigration<bool>._(1006),
|
needBetaMigration<bool>._(1006),
|
||||||
// TODO: Remove this after patching open-api
|
// TODO: Remove this after patching open-api
|
||||||
shouldResetSync<bool>._(1007),
|
shouldResetSync<bool>._(1007);
|
||||||
betaActivitiesStyle<bool>._(1008);
|
|
||||||
|
|
||||||
const StoreKey._(this.id);
|
const StoreKey._(this.id);
|
||||||
final int id;
|
final int id;
|
||||||
|
|||||||
@@ -1,20 +1,22 @@
|
|||||||
import 'package:auto_route/auto_route.dart';
|
import 'package:auto_route/auto_route.dart';
|
||||||
import 'package:collection/collection.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart' hide Store;
|
import 'package:flutter_hooks/flutter_hooks.dart' hide Store;
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:immich_mobile/domain/models/asset/base_asset.model.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/asyncvalue_extensions.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/models/activities/activity.model.dart';
|
import 'package:immich_mobile/models/activities/activity.model.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/album/drift_activity_text_field.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/activity.provider.dart';
|
||||||
|
import 'package:immich_mobile/providers/activity_service.provider.dart';
|
||||||
|
import 'package:immich_mobile/providers/image/immich_remote_thumbnail_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';
|
||||||
import 'package:immich_mobile/providers/user.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 'package:immich_mobile/widgets/activities/dismissible_activity.dart';
|
||||||
|
import 'package:immich_mobile/widgets/common/user_circle_avatar.dart';
|
||||||
|
|
||||||
@RoutePage()
|
@RoutePage()
|
||||||
class DriftActivitiesPage extends HookConsumerWidget {
|
class DriftActivitiesPage extends HookConsumerWidget {
|
||||||
@@ -24,18 +26,13 @@ class DriftActivitiesPage extends HookConsumerWidget {
|
|||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final album = ref.watch(currentRemoteAlbumProvider)!;
|
final album = ref.watch(currentRemoteAlbumProvider)!;
|
||||||
final asset = ref.read(currentAssetNotifier) as RemoteAsset?;
|
final asset = ref.read(currentAssetNotifier) as RemoteAsset?;
|
||||||
final user = ref.watch(currentUserProvider);
|
|
||||||
|
|
||||||
final activityNotifier = ref.read(albumActivityProvider(album.id, asset?.id).notifier);
|
final activityNotifier = ref.read(albumActivityProvider(album.id, asset?.id).notifier);
|
||||||
final activities = ref.watch(albumActivityProvider(album.id, asset?.id));
|
final activities = ref.watch(albumActivityProvider(album.id, asset?.id));
|
||||||
final listViewScrollController = useScrollController();
|
final listViewScrollController = useScrollController();
|
||||||
|
|
||||||
void scrollToBottom() {
|
void scrollToBottom() {
|
||||||
listViewScrollController.animateTo(
|
listViewScrollController.animateTo(0, duration: const Duration(milliseconds: 300), curve: Curves.fastOutSlowIn);
|
||||||
listViewScrollController.position.maxScrollExtent + 80,
|
|
||||||
duration: const Duration(milliseconds: 600),
|
|
||||||
curve: Curves.fastOutSlowIn,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> onAddComment(String comment) async {
|
Future<void> onAddComment(String comment) async {
|
||||||
@@ -51,33 +48,24 @@ class DriftActivitiesPage extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
body: activities.widgetWhen(
|
body: activities.widgetWhen(
|
||||||
onData: (data) {
|
onData: (data) {
|
||||||
final liked = data.firstWhereOrNull(
|
final List<Widget> activityWidgets = [];
|
||||||
(a) => a.type == ActivityType.like && a.user.id == user?.id && a.assetId == asset?.id,
|
for (final activity in data.reversed) {
|
||||||
);
|
activityWidgets.add(
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 6),
|
||||||
|
child: _CommentBubble(activity: activity),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return SafeArea(
|
return SafeArea(
|
||||||
child: Stack(
|
child: Stack(
|
||||||
children: [
|
children: [
|
||||||
ListView.builder(
|
ListView(
|
||||||
controller: listViewScrollController,
|
controller: listViewScrollController,
|
||||||
itemCount: data.length + 1,
|
padding: const EdgeInsets.only(top: 8, bottom: 80),
|
||||||
itemBuilder: (context, index) {
|
reverse: true,
|
||||||
if (index == data.length) {
|
children: activityWidgets,
|
||||||
return const SizedBox(height: 80);
|
|
||||||
}
|
|
||||||
final activity = data[index];
|
|
||||||
final canDelete = activity.user.id == user?.id || album.ownerId == user?.id;
|
|
||||||
return Padding(
|
|
||||||
padding: const EdgeInsets.all(5),
|
|
||||||
child: DismissibleActivity(
|
|
||||||
activity.id,
|
|
||||||
ActivityTile(activity),
|
|
||||||
onDismiss: canDelete
|
|
||||||
? (activityId) async => await activityNotifier.removeActivity(activity.id)
|
|
||||||
: null,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
Align(
|
Align(
|
||||||
alignment: Alignment.bottomCenter,
|
alignment: Alignment.bottomCenter,
|
||||||
@@ -86,11 +74,7 @@ class DriftActivitiesPage extends HookConsumerWidget {
|
|||||||
color: context.scaffoldBackgroundColor,
|
color: context.scaffoldBackgroundColor,
|
||||||
border: Border(top: BorderSide(color: context.colorScheme.secondaryContainer, width: 1)),
|
border: Border(top: BorderSide(color: context.colorScheme.secondaryContainer, width: 1)),
|
||||||
),
|
),
|
||||||
child: DriftActivityTextField(
|
child: DriftActivityTextField(isEnabled: album.isActivityEnabled, onSubmit: onAddComment),
|
||||||
isEnabled: album.isActivityEnabled,
|
|
||||||
likeId: liked?.id,
|
|
||||||
onSubmit: onAddComment,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -102,3 +86,127 @@ class DriftActivitiesPage extends HookConsumerWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _CommentBubble extends ConsumerWidget {
|
||||||
|
final Activity activity;
|
||||||
|
|
||||||
|
const _CommentBubble({required this.activity});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final user = ref.watch(currentUserProvider);
|
||||||
|
final album = ref.watch(currentRemoteAlbumProvider)!;
|
||||||
|
final isOwn = activity.user.id == user?.id;
|
||||||
|
final canDelete = isOwn || album.ownerId == user?.id;
|
||||||
|
final hasAsset = activity.assetId != null && activity.assetId!.isNotEmpty;
|
||||||
|
final isLike = activity.type == ActivityType.like;
|
||||||
|
final bgColor = isOwn ? context.colorScheme.primaryContainer : context.colorScheme.surfaceContainer;
|
||||||
|
|
||||||
|
final activityNotifier = ref.read(albumActivityProvider(album.id, activity.assetId).notifier);
|
||||||
|
|
||||||
|
Future<void> openAssetViewer() async {
|
||||||
|
final activityService = ref.read(activityServiceProvider);
|
||||||
|
final route = await activityService.buildAssetViewerRoute(activity.assetId!, ref);
|
||||||
|
if (route != null) await context.pushRoute(route);
|
||||||
|
}
|
||||||
|
|
||||||
|
// avatar (hidden for own messages)
|
||||||
|
Widget avatar() => isOwn ? const SizedBox.shrink() : UserCircleAvatar(user: activity.user, size: 28, radius: 14);
|
||||||
|
|
||||||
|
// Thumbnail with tappable behavior and optional heart overlay
|
||||||
|
Widget? thumbnail() {
|
||||||
|
if (!hasAsset) return null;
|
||||||
|
return ConstrainedBox(
|
||||||
|
constraints: const BoxConstraints(maxWidth: 150, maxHeight: 150),
|
||||||
|
child: Stack(
|
||||||
|
children: [
|
||||||
|
GestureDetector(
|
||||||
|
onTap: openAssetViewer,
|
||||||
|
child: ClipRRect(
|
||||||
|
borderRadius: const BorderRadius.all(Radius.circular(10)),
|
||||||
|
child: Image(
|
||||||
|
image: ImmichRemoteThumbnailProvider(assetId: activity.assetId!),
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (isLike)
|
||||||
|
Positioned(
|
||||||
|
right: 6,
|
||||||
|
bottom: 6,
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.all(4),
|
||||||
|
decoration: BoxDecoration(color: Colors.white.withValues(alpha: 0.7), shape: BoxShape.circle),
|
||||||
|
child: Icon(Icons.favorite, color: Colors.red[600], size: 18),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Heart-only widget (for likes without asset)
|
||||||
|
Widget? likedToAlbum() {
|
||||||
|
if (!isLike || hasAsset) return null;
|
||||||
|
return Container(
|
||||||
|
padding: const EdgeInsets.all(8),
|
||||||
|
decoration: BoxDecoration(color: Colors.white.withValues(alpha: 0.7), shape: BoxShape.circle),
|
||||||
|
child: Icon(Icons.favorite, color: Colors.red[600], size: 18),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Comment bubble; for comment-only we constrain width to ~50%.
|
||||||
|
Widget? commentBubble() {
|
||||||
|
if (activity.comment == null || activity.comment!.isEmpty) return null;
|
||||||
|
return ConstrainedBox(
|
||||||
|
constraints: BoxConstraints(maxWidth: MediaQuery.of(context).size.width * 0.5),
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.all(10),
|
||||||
|
decoration: BoxDecoration(color: bgColor, borderRadius: const BorderRadius.all(Radius.circular(12))),
|
||||||
|
child: Text(
|
||||||
|
activity.comment ?? '',
|
||||||
|
style: context.textTheme.bodyMedium?.copyWith(color: context.colorScheme.onSurface),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Combined content: optional thumbnail, optional heart-only, optional comment
|
||||||
|
final List<Widget> contentChildren = [thumbnail(), likedToAlbum(), commentBubble()].whereType<Widget>().toList();
|
||||||
|
|
||||||
|
return DismissibleActivity(
|
||||||
|
onDismiss: canDelete ? (id) async => await activityNotifier.removeActivity(id) : null,
|
||||||
|
activity.id,
|
||||||
|
Align(
|
||||||
|
alignment: isOwn ? Alignment.centerRight : Alignment.centerLeft,
|
||||||
|
child: ConstrainedBox(
|
||||||
|
constraints: BoxConstraints(maxWidth: MediaQuery.of(context).size.width * 0.86),
|
||||||
|
child: Container(
|
||||||
|
margin: const EdgeInsets.symmetric(vertical: 6, horizontal: 10),
|
||||||
|
child: Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
if (!isOwn) ...[avatar(), const SizedBox(width: 8)],
|
||||||
|
// Content column
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: isOwn ? CrossAxisAlignment.end : CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
...contentChildren.map((w) => Padding(padding: const EdgeInsets.only(bottom: 8.0), child: w)),
|
||||||
|
Text(
|
||||||
|
'${activity.user.name} • ${activity.createdAt.timeAgo()}',
|
||||||
|
style: context.textTheme.labelSmall?.copyWith(
|
||||||
|
color: context.colorScheme.onSurface.withValues(alpha: 0.6),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
if (isOwn) const SizedBox(width: 8),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,212 +0,0 @@
|
|||||||
import 'package:auto_route/auto_route.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_hooks/flutter_hooks.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/extensions/datetime_extensions.dart';
|
|
||||||
import 'package:immich_mobile/models/activities/activity.model.dart';
|
|
||||||
import 'package:immich_mobile/presentation/widgets/action_buttons/like_activity_action_button.widget.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/activity_service.provider.dart';
|
|
||||||
import 'package:immich_mobile/providers/image/immich_remote_thumbnail_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/dismissible_activity.dart';
|
|
||||||
import 'package:immich_mobile/widgets/common/user_circle_avatar.dart';
|
|
||||||
|
|
||||||
@RoutePage()
|
|
||||||
class DriftBetaActivitiesPage extends HookConsumerWidget {
|
|
||||||
const DriftBetaActivitiesPage({super.key});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
|
||||||
final album = ref.watch(currentRemoteAlbumProvider)!;
|
|
||||||
final asset = ref.read(currentAssetNotifier) as RemoteAsset?;
|
|
||||||
|
|
||||||
final activityNotifier = ref.read(albumActivityProvider(album.id, asset?.id).notifier);
|
|
||||||
final activities = ref.watch(albumActivityProvider(album.id, asset?.id));
|
|
||||||
final listViewScrollController = useScrollController();
|
|
||||||
|
|
||||||
void scrollToBottom() {
|
|
||||||
listViewScrollController.animateTo(0, duration: const Duration(milliseconds: 300), curve: Curves.fastOutSlowIn);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> onAddComment(String comment) async {
|
|
||||||
await activityNotifier.addComment(comment);
|
|
||||||
scrollToBottom();
|
|
||||||
}
|
|
||||||
|
|
||||||
return Scaffold(
|
|
||||||
appBar: AppBar(
|
|
||||||
title: asset == null ? Text(album.name) : null,
|
|
||||||
actions: [const LikeActivityActionButton(menuItem: true)],
|
|
||||||
actionsPadding: const EdgeInsets.only(right: 8),
|
|
||||||
),
|
|
||||||
body: activities.widgetWhen(
|
|
||||||
onData: (data) {
|
|
||||||
final List<Widget> activityWidgets = [];
|
|
||||||
for (final activity in data.reversed) {
|
|
||||||
activityWidgets.add(
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 6),
|
|
||||||
child: _CommentBubble(activity: activity),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return SafeArea(
|
|
||||||
child: Stack(
|
|
||||||
children: [
|
|
||||||
ListView(
|
|
||||||
controller: listViewScrollController,
|
|
||||||
padding: const EdgeInsets.only(top: 8, bottom: 80),
|
|
||||||
reverse: true,
|
|
||||||
children: activityWidgets,
|
|
||||||
),
|
|
||||||
Align(
|
|
||||||
alignment: Alignment.bottomCenter,
|
|
||||||
child: Container(
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: context.scaffoldBackgroundColor,
|
|
||||||
border: Border(top: BorderSide(color: context.colorScheme.secondaryContainer, width: 1)),
|
|
||||||
),
|
|
||||||
child: DriftActivityTextField(isEnabled: album.isActivityEnabled, onSubmit: onAddComment),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
resizeToAvoidBottomInset: true,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _CommentBubble extends ConsumerWidget {
|
|
||||||
final Activity activity;
|
|
||||||
|
|
||||||
const _CommentBubble({required this.activity});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
|
||||||
final user = ref.watch(currentUserProvider);
|
|
||||||
final album = ref.watch(currentRemoteAlbumProvider)!;
|
|
||||||
final isOwn = activity.user.id == user?.id;
|
|
||||||
final canDelete = isOwn || album.ownerId == user?.id;
|
|
||||||
final hasAsset = activity.assetId != null && activity.assetId!.isNotEmpty;
|
|
||||||
final isLike = activity.type == ActivityType.like;
|
|
||||||
final bgColor = isOwn ? context.colorScheme.primaryContainer : context.colorScheme.surfaceContainer;
|
|
||||||
|
|
||||||
final activityNotifier = ref.read(albumActivityProvider(album.id, activity.assetId).notifier);
|
|
||||||
|
|
||||||
Future<void> openAssetViewer() async {
|
|
||||||
final activityService = ref.read(activityServiceProvider);
|
|
||||||
final route = await activityService.buildAssetViewerRoute(activity.assetId!, ref);
|
|
||||||
if (route != null) await context.pushRoute(route);
|
|
||||||
}
|
|
||||||
|
|
||||||
// avatar (hidden for own messages)
|
|
||||||
Widget avatar() => isOwn ? const SizedBox.shrink() : UserCircleAvatar(user: activity.user, size: 28, radius: 14);
|
|
||||||
|
|
||||||
// Thumbnail with tappable behavior and optional heart overlay
|
|
||||||
Widget? thumbnail() {
|
|
||||||
if (!hasAsset) return null;
|
|
||||||
return ConstrainedBox(
|
|
||||||
constraints: const BoxConstraints(maxWidth: 150, maxHeight: 150),
|
|
||||||
child: Stack(
|
|
||||||
children: [
|
|
||||||
GestureDetector(
|
|
||||||
onTap: openAssetViewer,
|
|
||||||
child: ClipRRect(
|
|
||||||
borderRadius: const BorderRadius.all(Radius.circular(10)),
|
|
||||||
child: Image(
|
|
||||||
image: ImmichRemoteThumbnailProvider(assetId: activity.assetId!),
|
|
||||||
fit: BoxFit.cover,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (isLike)
|
|
||||||
Positioned(
|
|
||||||
right: 6,
|
|
||||||
bottom: 6,
|
|
||||||
child: Container(
|
|
||||||
padding: const EdgeInsets.all(4),
|
|
||||||
decoration: BoxDecoration(color: Colors.white.withValues(alpha: 0.7), shape: BoxShape.circle),
|
|
||||||
child: Icon(Icons.favorite, color: Colors.red[600], size: 18),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Heart-only widget (for likes without asset)
|
|
||||||
Widget? likedToAlbum() {
|
|
||||||
if (!isLike || hasAsset) return null;
|
|
||||||
return Container(
|
|
||||||
padding: const EdgeInsets.all(8),
|
|
||||||
decoration: BoxDecoration(color: Colors.white.withValues(alpha: 0.7), shape: BoxShape.circle),
|
|
||||||
child: Icon(Icons.favorite, color: Colors.red[600], size: 18),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comment bubble; for comment-only we constrain width to ~50%.
|
|
||||||
Widget? commentBubble() {
|
|
||||||
if (activity.comment == null || activity.comment!.isEmpty) return null;
|
|
||||||
return ConstrainedBox(
|
|
||||||
constraints: BoxConstraints(maxWidth: MediaQuery.of(context).size.width * 0.5),
|
|
||||||
child: Container(
|
|
||||||
padding: const EdgeInsets.all(10),
|
|
||||||
decoration: BoxDecoration(color: bgColor, borderRadius: const BorderRadius.all(Radius.circular(12))),
|
|
||||||
child: Text(
|
|
||||||
activity.comment ?? '',
|
|
||||||
style: context.textTheme.bodyMedium?.copyWith(color: context.colorScheme.onSurface),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Combined content: optional thumbnail, optional heart-only, optional comment
|
|
||||||
final List<Widget> contentChildren = [thumbnail(), likedToAlbum(), commentBubble()].whereType<Widget>().toList();
|
|
||||||
|
|
||||||
return DismissibleActivity(
|
|
||||||
onDismiss: canDelete ? (id) async => await activityNotifier.removeActivity(id) : null,
|
|
||||||
activity.id,
|
|
||||||
Align(
|
|
||||||
alignment: isOwn ? Alignment.centerRight : Alignment.centerLeft,
|
|
||||||
child: ConstrainedBox(
|
|
||||||
constraints: BoxConstraints(maxWidth: MediaQuery.of(context).size.width * 0.86),
|
|
||||||
child: Container(
|
|
||||||
margin: const EdgeInsets.symmetric(vertical: 6, horizontal: 10),
|
|
||||||
child: Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
if (!isOwn) ...[avatar(), const SizedBox(width: 8)],
|
|
||||||
// Content column
|
|
||||||
Column(
|
|
||||||
crossAxisAlignment: isOwn ? CrossAxisAlignment.end : CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
...contentChildren.map((w) => Padding(padding: const EdgeInsets.only(bottom: 8.0), child: w)),
|
|
||||||
Text(
|
|
||||||
'${activity.user.name} • ${activity.createdAt.timeAgo()}',
|
|
||||||
style: context.textTheme.labelSmall?.copyWith(
|
|
||||||
color: context.colorScheme.onSurface.withValues(alpha: 0.6),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
if (isOwn) const SizedBox(width: 8),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -4,8 +4,6 @@ import 'package:flutter/services.dart';
|
|||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:immich_mobile/domain/models/album/album.model.dart';
|
import 'package:immich_mobile/domain/models/album/album.model.dart';
|
||||||
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||||
import 'package:immich_mobile/domain/models/store.model.dart';
|
|
||||||
import 'package:immich_mobile/entities/store.entity.dart';
|
|
||||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||||
import 'package:immich_mobile/extensions/translate_extensions.dart';
|
import 'package:immich_mobile/extensions/translate_extensions.dart';
|
||||||
import 'package:immich_mobile/presentation/widgets/bottom_sheet/remote_album_bottom_sheet.widget.dart';
|
import 'package:immich_mobile/presentation/widgets/bottom_sheet/remote_album_bottom_sheet.widget.dart';
|
||||||
@@ -168,10 +166,6 @@ class _RemoteAlbumPageState extends ConsumerState<RemoteAlbumPage> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> showActivity(BuildContext context) async {
|
Future<void> showActivity(BuildContext context) async {
|
||||||
if (Store.get(StoreKey.betaActivitiesStyle, false)) {
|
|
||||||
context.pushRoute(const DriftBetaActivitiesRoute());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
context.pushRoute(const DriftActivitiesRoute());
|
context.pushRoute(const DriftActivitiesRoute());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -78,7 +78,6 @@ import 'package:immich_mobile/pages/search/recently_taken.page.dart';
|
|||||||
import 'package:immich_mobile/pages/search/search.page.dart';
|
import 'package:immich_mobile/pages/search/search.page.dart';
|
||||||
import 'package:immich_mobile/pages/settings/sync_status.page.dart';
|
import 'package:immich_mobile/pages/settings/sync_status.page.dart';
|
||||||
import 'package:immich_mobile/pages/share_intent/share_intent.page.dart';
|
import 'package:immich_mobile/pages/share_intent/share_intent.page.dart';
|
||||||
import 'package:immich_mobile/presentation/pages/drift_beta_activities.page.dart';
|
|
||||||
import 'package:immich_mobile/presentation/pages/dev/feat_in_development.page.dart';
|
import 'package:immich_mobile/presentation/pages/dev/feat_in_development.page.dart';
|
||||||
import 'package:immich_mobile/presentation/pages/dev/main_timeline.page.dart';
|
import 'package:immich_mobile/presentation/pages/dev/main_timeline.page.dart';
|
||||||
import 'package:immich_mobile/presentation/pages/dev/media_stat.page.dart';
|
import 'package:immich_mobile/presentation/pages/dev/media_stat.page.dart';
|
||||||
@@ -345,7 +344,6 @@ class AppRouter extends RootStackRouter {
|
|||||||
AutoRoute(page: DriftCropImageRoute.page),
|
AutoRoute(page: DriftCropImageRoute.page),
|
||||||
AutoRoute(page: DriftFilterImageRoute.page),
|
AutoRoute(page: DriftFilterImageRoute.page),
|
||||||
AutoRoute(page: DriftActivitiesRoute.page, guards: [_authGuard, _duplicateGuard]),
|
AutoRoute(page: DriftActivitiesRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||||
AutoRoute(page: DriftBetaActivitiesRoute.page, guards: [_authGuard, _duplicateGuard]),
|
|
||||||
AutoRoute(page: DriftBackupAssetDetailRoute.page, guards: [_authGuard, _duplicateGuard]),
|
AutoRoute(page: DriftBackupAssetDetailRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||||
AutoRoute(page: AssetTroubleshootRoute.page, guards: [_authGuard, _duplicateGuard]),
|
AutoRoute(page: AssetTroubleshootRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||||
AutoRoute(page: DownloadInfoRoute.page, guards: [_authGuard, _duplicateGuard]),
|
AutoRoute(page: DownloadInfoRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||||
|
|||||||
@@ -881,22 +881,6 @@ class DriftBackupRoute extends PageRouteInfo<void> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// generated route for
|
|
||||||
/// [DriftBetaActivitiesPage]
|
|
||||||
class DriftBetaActivitiesRoute extends PageRouteInfo<void> {
|
|
||||||
const DriftBetaActivitiesRoute({List<PageRouteInfo>? children})
|
|
||||||
: super(DriftBetaActivitiesRoute.name, initialChildren: children);
|
|
||||||
|
|
||||||
static const String name = 'DriftBetaActivitiesRoute';
|
|
||||||
|
|
||||||
static PageInfo page = PageInfo(
|
|
||||||
name,
|
|
||||||
builder: (data) {
|
|
||||||
return const DriftBetaActivitiesPage();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [DriftCreateAlbumPage]
|
/// [DriftCreateAlbumPage]
|
||||||
class DriftCreateAlbumRoute extends PageRouteInfo<void> {
|
class DriftCreateAlbumRoute extends PageRouteInfo<void> {
|
||||||
|
|||||||
@@ -48,7 +48,6 @@ enum AppSettingsEnum<T> {
|
|||||||
autoEndpointSwitching<bool>(StoreKey.autoEndpointSwitching, null, false),
|
autoEndpointSwitching<bool>(StoreKey.autoEndpointSwitching, null, false),
|
||||||
photoManagerCustomFilter<bool>(StoreKey.photoManagerCustomFilter, null, true),
|
photoManagerCustomFilter<bool>(StoreKey.photoManagerCustomFilter, null, true),
|
||||||
betaTimeline<bool>(StoreKey.betaTimeline, null, true),
|
betaTimeline<bool>(StoreKey.betaTimeline, null, true),
|
||||||
betaActivitiesStyle<bool>(StoreKey.betaActivitiesStyle, null, false),
|
|
||||||
enableBackup<bool>(StoreKey.enableBackup, null, false),
|
enableBackup<bool>(StoreKey.enableBackup, null, false),
|
||||||
useCellularForUploadVideos<bool>(StoreKey.useWifiForUploadVideos, null, false),
|
useCellularForUploadVideos<bool>(StoreKey.useWifiForUploadVideos, null, false),
|
||||||
useCellularForUploadPhotos<bool>(StoreKey.useWifiForUploadPhotos, null, false),
|
useCellularForUploadPhotos<bool>(StoreKey.useWifiForUploadPhotos, null, false),
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ class AdvancedSettings extends HookConsumerWidget {
|
|||||||
final allowSelfSignedSSLCert = useAppSettingsState(AppSettingsEnum.allowSelfSignedSSLCert);
|
final allowSelfSignedSSLCert = useAppSettingsState(AppSettingsEnum.allowSelfSignedSSLCert);
|
||||||
final useAlternatePMFilter = useAppSettingsState(AppSettingsEnum.photoManagerCustomFilter);
|
final useAlternatePMFilter = useAppSettingsState(AppSettingsEnum.photoManagerCustomFilter);
|
||||||
final readonlyModeEnabled = useAppSettingsState(AppSettingsEnum.readonlyModeEnabled);
|
final readonlyModeEnabled = useAppSettingsState(AppSettingsEnum.readonlyModeEnabled);
|
||||||
final betaActivitiesStyle = useAppSettingsState(AppSettingsEnum.betaActivitiesStyle);
|
|
||||||
|
|
||||||
final logLevel = Level.LEVELS[levelId.value].name;
|
final logLevel = Level.LEVELS[levelId.value].name;
|
||||||
|
|
||||||
@@ -129,11 +128,6 @@ class AdvancedSettings extends HookConsumerWidget {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
SettingsSwitchListTile(
|
|
||||||
valueNotifier: betaActivitiesStyle,
|
|
||||||
title: "advanced_settings_beta_activities_style_title".tr(),
|
|
||||||
subtitle: "advanced_settings_beta_activities_style_subtitle".tr(),
|
|
||||||
),
|
|
||||||
];
|
];
|
||||||
|
|
||||||
return SettingsSubPageScaffold(settings: advancedSettings);
|
return SettingsSubPageScaffold(settings: advancedSettings);
|
||||||
|
|||||||
Reference in New Issue
Block a user