improvements

This commit is contained in:
Myzel394 2022-08-14 21:59:29 +02:00
parent 8409939825
commit 13ea760cb8
4 changed files with 161 additions and 75 deletions

68
lib/models/timeline.dart Normal file
View File

@ -0,0 +1,68 @@
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:share_location/foreign_types/memory.dart';
import 'package:share_location/models/memory_pack.dart';
class TimelineModel extends ChangeNotifier {
final Map<String, MemoryPack> _timeline;
TimelineModel({
Map<String, MemoryPack>? timeline,
}) : _timeline = timeline ?? {};
Map<String, MemoryPack> get values => _timeline;
static TimelineModel fromMemoriesList(
final List<Memory> memories,
) {
final map = <String, List<Memory>>{};
for (final memory in memories) {
final date = DateFormat('yyyy-MM-dd').format(memory.creationDate);
if (map.containsKey(date)) {
map[date]!.add(memory);
} else {
map[date] = [memory];
}
}
final data = Map.fromEntries(
map.entries.map(
(entry) => MapEntry<String, MemoryPack>(
entry.key,
MemoryPack(entry.value),
),
),
);
return TimelineModel(
timeline: data,
);
}
@override
void dispose() {
_timeline.values.forEach((memoryPack) {
memoryPack.dispose();
});
super.dispose();
}
void removeEmptyDates() {
final previousLength = _timeline.length;
_timeline.removeWhere((key, value) => value.memories.isEmpty);
final newLength = _timeline.length;
if (previousLength != newLength) {
notifyListeners();
}
}
DateTime dateAtIndex(final int index) =>
DateTime.parse(_timeline.keys.elementAt(index));
MemoryPack atIndex(final int index) => _timeline.values.elementAt(index);
}

View File

@ -3,6 +3,7 @@ import 'package:provider/provider.dart';
import 'package:share_location/controllers/status_controller.dart';
import 'package:share_location/enums.dart';
import 'package:share_location/foreign_types/memory.dart';
import 'package:share_location/models/memory_pack.dart';
import 'package:share_location/models/timeline_overlay.dart';
import 'package:share_location/widgets/status.dart';
@ -59,6 +60,7 @@ class _MemorySlideState extends State<MemorySlide>
void initializeAnimation(final Duration duration) {
final timelineOverlay = context.read<TimelineOverlay>();
final memoryPack = context.read<MemoryPack>();
this.duration = duration;
@ -72,7 +74,8 @@ class _MemorySlideState extends State<MemorySlide>
}
if (controller!.done) {
timelineOverlay.setState(TimelineState.completed);
timelineOverlay.reset();
memoryPack.next();
}
}, ['done']);
@ -81,10 +84,10 @@ class _MemorySlideState extends State<MemorySlide>
@override
Widget build(BuildContext context) {
return Consumer<TimelineOverlay>(
builder: (context, overlayController, _) => Status(
return Consumer<MemoryPack>(
builder: (context, memoryPack, _) => Status(
controller: controller,
disabled: !overlayController.showOverlay,
disabled: memoryPack.paused,
child: MemoryView(
creationDate: widget.memory.creationDate,
location: widget.memory.location,
@ -99,17 +102,17 @@ class _MemorySlideState extends State<MemorySlide>
if (mounted) {
initializeAnimation(controller.value.duration);
overlayController.addListener(() {
memoryPack.addListener(() {
if (!mounted) {
return;
}
if (overlayController.state == TimelineState.playing) {
controller.play();
} else {
if (memoryPack.paused) {
controller.pause();
} else {
controller.play();
}
}, ['state']);
}, ['paused']);
}
},
),

View File

@ -13,12 +13,14 @@ class TimelinePage extends StatefulWidget {
final DateTime date;
final VoidCallback onPreviousTimeline;
final VoidCallback onNextTimeline;
final VoidCallback onMemoryRemoved;
const TimelinePage({
Key? key,
required this.date,
required this.onPreviousTimeline,
required this.onNextTimeline,
required this.onMemoryRemoved,
}) : super(key: key);
@override
@ -48,6 +50,18 @@ class _TimelinePageState extends State<TimelinePage> {
}
}, ['state']);
memoryPack.addListener(() {
if (!mounted) {
return;
}
if (memoryPack.paused) {
timelineOverlayController.hideOverlay();
} else {
timelineOverlayController.restoreOverlay();
}
}, ['state']);
memoryPack.addListener(() {
if (!mounted) {
return;
@ -81,7 +95,6 @@ class _TimelinePageState extends State<TimelinePage> {
final memoryPack = context.read<MemoryPack>();
memoryPack.pause();
timelineOverlayController.hideOverlay();
await showModalBottomSheet(
context: context,
@ -98,16 +111,15 @@ class _TimelinePageState extends State<TimelinePage> {
memoryPack.removeCurrentMemory();
memoryPack.resume();
timelineOverlayController.restoreOverlay();
widget.onMemoryRemoved();
},
onTapDown: (_) {
final memoryPack = context.read<MemoryPack>();
memoryPack.pause();
overlayRemover = Timer(
const Duration(milliseconds: 200),
timelineOverlayController.hideOverlay,
memoryPack.pause,
);
},
onTapUp: (_) {
@ -115,14 +127,11 @@ class _TimelinePageState extends State<TimelinePage> {
overlayRemover?.cancel();
memoryPack.resume();
timelineOverlayController.restoreOverlay();
},
onTapCancel: () {
final memoryPack = context.read<MemoryPack>();
overlayRemover?.cancel();
timelineOverlayController.restoreOverlay();
memoryPack.resume();
},
onHorizontalDragEnd: (details) {
@ -146,12 +155,11 @@ class _TimelinePageState extends State<TimelinePage> {
},
child: ChangeNotifierProvider<TimelineOverlay>(
create: (_) => timelineOverlayController,
child: Stack(
child: Consumer<MemoryPack>(
builder: (_, memoryPack, __) => Stack(
fit: StackFit.expand,
children: <Widget>[
Consumer<MemoryPack>(
builder: (_, memoryPack, __) {
return PageView.builder(
PageView.builder(
controller: pageController,
physics: const NeverScrollableScrollPhysics(),
scrollDirection: Axis.horizontal,
@ -160,8 +168,6 @@ class _TimelinePageState extends State<TimelinePage> {
memory: memoryPack.memories[index],
),
itemCount: memoryPack.memories.length,
);
},
),
Padding(
padding: const EdgeInsets.only(
@ -169,11 +175,10 @@ class _TimelinePageState extends State<TimelinePage> {
left: MEDIUM_SPACE,
right: MEDIUM_SPACE,
),
child: Consumer<TimelineOverlay>(
builder: (context, overlayController, _) => AnimatedOpacity(
child: AnimatedOpacity(
duration: const Duration(milliseconds: 500),
curve: Curves.linearToEaseOut,
opacity: overlayController.showOverlay ? 1.0 : 0.0,
opacity: memoryPack.paused ? 0.0 : 1.0,
child: Text(
DateFormat('dd. MMMM yyyy').format(widget.date),
textAlign: TextAlign.center,
@ -181,10 +186,28 @@ class _TimelinePageState extends State<TimelinePage> {
),
),
),
Positioned(
right: SMALL_SPACE,
bottom: SMALL_SPACE * 2,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: SMALL_SPACE),
child: AnimatedOpacity(
duration: const Duration(milliseconds: 500),
curve: Curves.linearToEaseOut,
opacity: memoryPack.paused ? 0.0 : 1.0,
child: Consumer<MemoryPack>(
builder: (_, memoryPack, __) => Text(
'${memoryPack.currentMemoryIndex + 1}/${memoryPack.memories.length}',
style: Theme.of(context).textTheme.titleSmall,
),
),
),
),
),
],
),
),
),
);
}
}

View File

@ -1,8 +1,7 @@
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:provider/provider.dart';
import 'package:share_location/foreign_types/memory.dart';
import 'package:share_location/models/memory_pack.dart';
import 'package:share_location/models/timeline.dart';
import 'package:share_location/utils/loadable.dart';
import 'package:share_location/widgets/timeline_page.dart';
import 'package:supabase_flutter/supabase_flutter.dart';
@ -20,7 +19,7 @@ class TimelineScroll extends StatefulWidget {
class _TimelineScrollState extends State<TimelineScroll> with Loadable {
final pageController = PageController();
Map<String, MemoryPack>? timeline;
TimelineModel? timeline;
@override
initState() {
@ -28,7 +27,18 @@ class _TimelineScrollState extends State<TimelineScroll> with Loadable {
loadTimeline();
}
@override
dispose() {
pageController.dispose();
timeline?.dispose();
super.dispose();
}
Future<void> loadTimeline() async {
timeline?.dispose();
final response = await supabase
.from('memories')
.select()
@ -36,35 +46,16 @@ class _TimelineScrollState extends State<TimelineScroll> with Loadable {
.execute();
final memories = List<Memory>.from(
List<Map<String, dynamic>>.from(response.data).map(Memory.parse));
final timelineMapped = convertMemoriesToTimeline(memories);
setState(() {
timeline = timelineMapped;
timeline = TimelineModel.fromMemoriesList(memories);
});
}
static Map<String, MemoryPack> convertMemoriesToTimeline(
final List<Memory> memories,
) {
final map = <String, List<Memory>>{};
for (final memory in memories) {
final date = DateFormat('yyyy-MM-dd').format(memory.creationDate);
if (map.containsKey(date)) {
map[date]!.add(memory);
} else {
map[date] = [memory];
timeline!.addListener(() {
if (mounted) {
setState(() {});
}
}
return Map.fromEntries(
map.entries.map(
(entry) => MapEntry<String, MemoryPack>(
entry.key,
MemoryPack(entry.value),
),
),
);
});
}
@override
@ -79,11 +70,12 @@ class _TimelineScrollState extends State<TimelineScroll> with Loadable {
body: PageView.builder(
controller: pageController,
scrollDirection: Axis.vertical,
itemCount: timeline!.length,
itemBuilder: (_, index) => ChangeNotifierProvider<MemoryPack>(
create: (_) => timeline!.values.elementAt(index),
itemCount: timeline!.values.length,
itemBuilder: (_, index) => ChangeNotifierProvider.value(
value: timeline!.atIndex(index),
child: TimelinePage(
date: DateTime.parse(timeline!.keys.toList()[index]),
date: timeline!.dateAtIndex(index),
onMemoryRemoved: () => timeline!.removeEmptyDates(),
onNextTimeline: () {
pageController.nextPage(
duration: const Duration(milliseconds: 500),