|
@@ -1,194 +1,17 @@
|
|
import "dart:io";
|
|
import "dart:io";
|
|
|
|
|
|
import "package:flutter/cupertino.dart";
|
|
import "package:flutter/cupertino.dart";
|
|
-import 'package:flutter/material.dart';
|
|
|
|
-import "package:photos/generated/l10n.dart";
|
|
|
|
-import 'package:photos/models/memory.dart';
|
|
|
|
-import 'package:photos/services/memories_service.dart';
|
|
|
|
-import "package:photos/theme/ente_theme.dart";
|
|
|
|
|
|
+import "package:flutter/material.dart";
|
|
|
|
+import "package:photos/models/memory.dart";
|
|
|
|
+import "package:photos/services/memories_service.dart";
|
|
import "package:photos/theme/text_style.dart";
|
|
import "package:photos/theme/text_style.dart";
|
|
import "package:photos/ui/actions/file/file_actions.dart";
|
|
import "package:photos/ui/actions/file/file_actions.dart";
|
|
import "package:photos/ui/extents_page_view.dart";
|
|
import "package:photos/ui/extents_page_view.dart";
|
|
-import 'package:photos/ui/viewer/file/file_widget.dart';
|
|
|
|
-import 'package:photos/ui/viewer/file/thumbnail_widget.dart';
|
|
|
|
-import 'package:photos/utils/date_time_util.dart';
|
|
|
|
-import 'package:photos/utils/file_util.dart';
|
|
|
|
-import 'package:photos/utils/navigation_util.dart';
|
|
|
|
-import 'package:photos/utils/share_util.dart';
|
|
|
|
-import 'package:step_progress_indicator/step_progress_indicator.dart';
|
|
|
|
-
|
|
|
|
-class MemoriesWidget extends StatelessWidget {
|
|
|
|
- const MemoriesWidget({Key? key}) : super(key: key);
|
|
|
|
-
|
|
|
|
- @override
|
|
|
|
- Widget build(BuildContext context) {
|
|
|
|
- return FutureBuilder<List<Memory>>(
|
|
|
|
- future: MemoriesService.instance.getMemories(),
|
|
|
|
- builder: (context, snapshot) {
|
|
|
|
- if (snapshot.hasError || !snapshot.hasData || snapshot.data!.isEmpty) {
|
|
|
|
- return const SizedBox.shrink();
|
|
|
|
- } else {
|
|
|
|
- return Column(
|
|
|
|
- crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
|
- children: [
|
|
|
|
- _buildMemories(snapshot.data!),
|
|
|
|
- const Divider(),
|
|
|
|
- ],
|
|
|
|
- );
|
|
|
|
- }
|
|
|
|
- },
|
|
|
|
- );
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- Widget _buildMemories(List<Memory> memories) {
|
|
|
|
- final collatedMemories = _collateMemories(memories);
|
|
|
|
- final List<Widget> memoryWidgets = [];
|
|
|
|
- for (final memories in collatedMemories) {
|
|
|
|
- memoryWidgets.add(MemoryWidget(memories: memories));
|
|
|
|
- }
|
|
|
|
- return SingleChildScrollView(
|
|
|
|
- scrollDirection: Axis.horizontal,
|
|
|
|
- child: Row(children: memoryWidgets),
|
|
|
|
- );
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- List<List<Memory>> _collateMemories(List<Memory> memories) {
|
|
|
|
- final List<Memory> yearlyMemories = [];
|
|
|
|
- final List<List<Memory>> collatedMemories = [];
|
|
|
|
- for (int index = 0; index < memories.length; index++) {
|
|
|
|
- if (index > 0 &&
|
|
|
|
- !_areMemoriesFromSameYear(memories[index - 1], memories[index])) {
|
|
|
|
- final List<Memory> collatedYearlyMemories = [];
|
|
|
|
- collatedYearlyMemories.addAll(yearlyMemories);
|
|
|
|
- collatedMemories.add(collatedYearlyMemories);
|
|
|
|
- yearlyMemories.clear();
|
|
|
|
- }
|
|
|
|
- yearlyMemories.add(memories[index]);
|
|
|
|
- }
|
|
|
|
- if (yearlyMemories.isNotEmpty) {
|
|
|
|
- collatedMemories.add(yearlyMemories);
|
|
|
|
- }
|
|
|
|
- return collatedMemories.reversed.toList();
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- bool _areMemoriesFromSameYear(Memory first, Memory second) {
|
|
|
|
- final firstDate =
|
|
|
|
- DateTime.fromMicrosecondsSinceEpoch(first.file.creationTime!);
|
|
|
|
- final secondDate =
|
|
|
|
- DateTime.fromMicrosecondsSinceEpoch(second.file.creationTime!);
|
|
|
|
- return firstDate.year == secondDate.year;
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-class MemoryWidget extends StatefulWidget {
|
|
|
|
- const MemoryWidget({
|
|
|
|
- Key? key,
|
|
|
|
- required this.memories,
|
|
|
|
- }) : super(key: key);
|
|
|
|
-
|
|
|
|
- final List<Memory> memories;
|
|
|
|
-
|
|
|
|
- @override
|
|
|
|
- State<MemoryWidget> createState() => _MemoryWidgetState();
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-class _MemoryWidgetState extends State<MemoryWidget> {
|
|
|
|
- @override
|
|
|
|
- Widget build(BuildContext context) {
|
|
|
|
- final index = _getNextMemoryIndex();
|
|
|
|
- final title = _getTitle(widget.memories[index]);
|
|
|
|
- return GestureDetector(
|
|
|
|
- onTap: () async {
|
|
|
|
- await routeToPage(
|
|
|
|
- context,
|
|
|
|
- FullScreenMemory(title, widget.memories, index),
|
|
|
|
- forceCustomPageRoute: true,
|
|
|
|
- );
|
|
|
|
- setState(() {});
|
|
|
|
- },
|
|
|
|
- child: Expanded(
|
|
|
|
- child: Padding(
|
|
|
|
- padding: const EdgeInsets.all(8.0),
|
|
|
|
- child: Column(
|
|
|
|
- children: [
|
|
|
|
- _buildMemoryItem(context, index),
|
|
|
|
- const Padding(padding: EdgeInsets.all(4)),
|
|
|
|
- Hero(
|
|
|
|
- tag: title,
|
|
|
|
- child: Material(
|
|
|
|
- type: MaterialType.transparency,
|
|
|
|
- child: Text(
|
|
|
|
- title,
|
|
|
|
- style: getEnteTextTheme(context).mini,
|
|
|
|
- textAlign: TextAlign.center,
|
|
|
|
- ),
|
|
|
|
- ),
|
|
|
|
- ),
|
|
|
|
- ],
|
|
|
|
- ),
|
|
|
|
- ),
|
|
|
|
- ),
|
|
|
|
- );
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- Container _buildMemoryItem(BuildContext context, int index) {
|
|
|
|
- final colorScheme = getEnteColorScheme(context);
|
|
|
|
- final memory = widget.memories[index];
|
|
|
|
- final isSeen = memory.isSeen();
|
|
|
|
- return Container(
|
|
|
|
- decoration: BoxDecoration(
|
|
|
|
- border: Border.all(
|
|
|
|
- color: isSeen ? colorScheme.strokeFaint : colorScheme.primary500,
|
|
|
|
- width: 2,
|
|
|
|
- ),
|
|
|
|
- borderRadius: BorderRadius.circular(40),
|
|
|
|
- ),
|
|
|
|
- child: ClipOval(
|
|
|
|
- child: SizedBox(
|
|
|
|
- width: 56,
|
|
|
|
- height: 56,
|
|
|
|
- child: Hero(
|
|
|
|
- tag: "memories" + memory.file.tag,
|
|
|
|
- child: ThumbnailWidget(
|
|
|
|
- memory.file,
|
|
|
|
- shouldShowSyncStatus: false,
|
|
|
|
- key: Key("memories" + memory.file.tag),
|
|
|
|
- ),
|
|
|
|
- ),
|
|
|
|
- ),
|
|
|
|
- ),
|
|
|
|
- );
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // Returns either the first unseen memory or the memory that succeeds the
|
|
|
|
- // last seen memory
|
|
|
|
- int _getNextMemoryIndex() {
|
|
|
|
- int lastSeenIndex = 0;
|
|
|
|
- int lastSeenTimestamp = 0;
|
|
|
|
- for (var index = 0; index < widget.memories.length; index++) {
|
|
|
|
- final memory = widget.memories[index];
|
|
|
|
- if (!memory.isSeen()) {
|
|
|
|
- return index;
|
|
|
|
- } else {
|
|
|
|
- if (memory.seenTime() > lastSeenTimestamp) {
|
|
|
|
- lastSeenIndex = index;
|
|
|
|
- lastSeenTimestamp = memory.seenTime();
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- if (lastSeenIndex == widget.memories.length - 1) {
|
|
|
|
- return 0;
|
|
|
|
- }
|
|
|
|
- return lastSeenIndex + 1;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- String _getTitle(Memory memory) {
|
|
|
|
- final present = DateTime.now();
|
|
|
|
- final then = DateTime.fromMicrosecondsSinceEpoch(memory.file.creationTime!);
|
|
|
|
- final diffInYears = present.year - then.year;
|
|
|
|
- return S.of(context).yearsAgo(diffInYears);
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
|
|
+import "package:photos/ui/viewer/file/file_widget.dart";
|
|
|
|
+import "package:photos/utils/date_time_util.dart";
|
|
|
|
+import "package:photos/utils/file_util.dart";
|
|
|
|
+import "package:photos/utils/share_util.dart";
|
|
|
|
+import "package:step_progress_indicator/step_progress_indicator.dart";
|
|
|
|
|
|
class FullScreenMemory extends StatefulWidget {
|
|
class FullScreenMemory extends StatefulWidget {
|
|
final String title;
|
|
final String title;
|