mirror of
https://github.com/immich-app/immich
synced 2026-08-29 13:15:45 +00:00
* wip web memories view * paginate searchMemories * improve memories ui * feat(mobile): memories view * improve memories web ui * fix(web): avoid unnecessary memory refreshes * refactor(web): move timline memory manager filter * fix(web): memories infinitely loading on 0 results * fix(web): memories resetting * feat(web): animated memory previews * feat(web): memory page dark styling * chore(mobile): fix failing memory lane tests * chore(mobile): remove old import * chore(e2e): fix failing memory lane tests * chore(server): revert searchMemories changes * chore(server): lint * chore(mobile): fix bad merge * chore(e2e): fix memory ui tests * chore(web): rename /memory to /memories * chore(mobile): linting * chore(web): linting * fix(web): prevent duplicate memory page loading * fix(web): lint * fix(web): memories page improvements * chore(mobile): lint * fix(mobile): fix translations * fix(mobile): build errors * fix(web): prevent memories from infinitely loading * chore(e2e)): fix failng memory viewer test * chore(web): clean up types in memory manager * chore(web): lint * feat: update list and detail memory page layouts * onlyFavorites through drift * rename to get all * mobile: use widgetWhen in memory list page * remove redundant check * fix: e2e --------- Co-authored-by: Timon <mail@timonrieger.de> Co-authored-by: Jason Rasmussen <jason@rasm.me> Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
87 lines
2.9 KiB
Dart
87 lines
2.9 KiB
Dart
import 'dart:async';
|
|
|
|
import 'package:auto_route/auto_route.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
|
import 'package:immich_mobile/domain/models/memory.model.dart';
|
|
import 'package:immich_mobile/generated/translations.g.dart';
|
|
import 'package:immich_mobile/presentation/pages/drift_memory.page.dart';
|
|
import 'package:immich_mobile/presentation/widgets/images/thumbnail.widget.dart';
|
|
import 'package:immich_mobile/providers/haptic_feedback.provider.dart';
|
|
import 'package:immich_mobile/providers/infrastructure/memory.provider.dart';
|
|
import 'package:immich_mobile/routing/router.dart';
|
|
|
|
class DriftMemoryLane extends ConsumerWidget {
|
|
const DriftMemoryLane({super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context, WidgetRef ref) {
|
|
final memoryLaneProvider = ref.watch(driftMemoryLaneProvider);
|
|
final memories = memoryLaneProvider.value ?? const [];
|
|
if (memories.isEmpty) {
|
|
return const SizedBox.shrink();
|
|
}
|
|
|
|
return ConstrainedBox(
|
|
constraints: const BoxConstraints(maxHeight: 200),
|
|
child: CarouselView(
|
|
itemExtent: 145.0,
|
|
shrinkExtent: 1.0,
|
|
elevation: 2,
|
|
backgroundColor: Colors.black,
|
|
overlayColor: WidgetStateProperty.all(Colors.white.withValues(alpha: 0.1)),
|
|
onTap: (index) {
|
|
ref.read(hapticFeedbackProvider.notifier).heavyImpact();
|
|
if (memories[index].assets.isNotEmpty) {
|
|
DriftMemoryPage.setMemory(ref, memories[index]);
|
|
}
|
|
unawaited(context.pushRoute(DriftMemoryRoute(memories: memories, memoryIndex: index)));
|
|
},
|
|
children: memories
|
|
.map((memory) => DriftMemoryCard(key: Key(memory.id), memory: memory))
|
|
.toList(growable: false),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class DriftMemoryCard extends StatelessWidget {
|
|
const DriftMemoryCard({super.key, required this.memory});
|
|
|
|
final DriftMemory memory;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final yearsAgo = DateTime.now().year - memory.data.year;
|
|
final title = context.t.years_ago(years: yearsAgo);
|
|
return Center(
|
|
child: Stack(
|
|
children: [
|
|
ColorFiltered(
|
|
colorFilter: ColorFilter.mode(Colors.black.withValues(alpha: 0.2), BlendMode.darken),
|
|
child: SizedBox(
|
|
width: 205,
|
|
height: 200,
|
|
child: Thumbnail.remote(
|
|
remoteId: memory.assets[0].id,
|
|
thumbhash: memory.assets[0].thumbHash ?? "",
|
|
fit: BoxFit.cover,
|
|
),
|
|
),
|
|
),
|
|
Positioned(
|
|
bottom: 16,
|
|
left: 16,
|
|
child: ConstrainedBox(
|
|
constraints: const BoxConstraints(maxWidth: 114),
|
|
child: Text(
|
|
title,
|
|
style: const TextStyle(fontWeight: FontWeight.w600, color: Colors.white, fontSize: 15),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|