mirror of
https://github.com/Myzel394/quid_faciam_hodie.git
synced 2025-06-19 15:45:26 +02:00
improved memory handling
This commit is contained in:
parent
2339fd27a0
commit
8409939825
@ -19,6 +19,8 @@ class MemorySlideController extends PropertyChangeNotifier<String> {
|
|||||||
int get index => _index;
|
int get index => _index;
|
||||||
bool get completed => _completed;
|
bool get completed => _completed;
|
||||||
|
|
||||||
|
bool get isLast => _index == memoryLength - 1;
|
||||||
|
|
||||||
void setPaused(bool paused) {
|
void setPaused(bool paused) {
|
||||||
_paused = paused;
|
_paused = paused;
|
||||||
notifyListeners('paused');
|
notifyListeners('paused');
|
||||||
@ -30,7 +32,7 @@ class MemorySlideController extends PropertyChangeNotifier<String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void next() {
|
void next() {
|
||||||
if (_index == memoryLength - 1) {
|
if (isLast) {
|
||||||
_completed = true;
|
_completed = true;
|
||||||
notifyListeners('completed');
|
notifyListeners('completed');
|
||||||
} else {
|
} else {
|
||||||
|
@ -95,4 +95,20 @@ class FileManager {
|
|||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Future<void> deleteFile(final String path) async {
|
||||||
|
final response =
|
||||||
|
await supabase.from('memories').delete().eq('location', path).execute();
|
||||||
|
|
||||||
|
if (response.error != null) {
|
||||||
|
throw Exception('Error deleting file: ${response.error!.message}');
|
||||||
|
}
|
||||||
|
|
||||||
|
final storageResponse =
|
||||||
|
await supabase.storage.from('memories').remove([path]);
|
||||||
|
|
||||||
|
if (storageResponse.error != null) {
|
||||||
|
throw Exception('Error deleting file: ${storageResponse.error!.message}');
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
61
lib/models/memory_pack.dart
Normal file
61
lib/models/memory_pack.dart
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
import 'dart:math';
|
||||||
|
|
||||||
|
import 'package:property_change_notifier/property_change_notifier.dart';
|
||||||
|
import 'package:share_location/foreign_types/memory.dart';
|
||||||
|
|
||||||
|
class MemoryPack extends PropertyChangeNotifier<String> {
|
||||||
|
final List<Memory> _memories;
|
||||||
|
int _currentMemoryIndex = 0;
|
||||||
|
bool _paused = false;
|
||||||
|
bool _completed = false;
|
||||||
|
|
||||||
|
MemoryPack(this._memories);
|
||||||
|
|
||||||
|
List<Memory> get memories => [..._memories];
|
||||||
|
int get currentMemoryIndex => _currentMemoryIndex;
|
||||||
|
Memory get currentMemory => _memories[_currentMemoryIndex];
|
||||||
|
bool get paused => _paused;
|
||||||
|
bool get completed => _completed;
|
||||||
|
bool get isLast => _currentMemoryIndex == _memories.length - 1;
|
||||||
|
|
||||||
|
void setPaused(bool paused) {
|
||||||
|
_paused = paused;
|
||||||
|
notifyListeners('paused');
|
||||||
|
}
|
||||||
|
|
||||||
|
void next() {
|
||||||
|
if (isLast) {
|
||||||
|
_completed = true;
|
||||||
|
notifyListeners('completed');
|
||||||
|
} else {
|
||||||
|
_paused = false;
|
||||||
|
_completed = false;
|
||||||
|
_currentMemoryIndex++;
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void previous() {
|
||||||
|
_currentMemoryIndex = max(_currentMemoryIndex - 1, 0);
|
||||||
|
_paused = false;
|
||||||
|
_completed = false;
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset() {
|
||||||
|
_completed = false;
|
||||||
|
_paused = false;
|
||||||
|
_currentMemoryIndex = 0;
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeMemory(int index) {
|
||||||
|
_memories.removeAt(index);
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeCurrentMemory() => removeMemory(_currentMemoryIndex);
|
||||||
|
|
||||||
|
void pause() => setPaused(true);
|
||||||
|
void resume() => setPaused(false);
|
||||||
|
}
|
@ -1,15 +1,35 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:property_change_notifier/property_change_notifier.dart';
|
||||||
|
|
||||||
class TimelineOverlay extends ChangeNotifier {
|
enum TimelineState {
|
||||||
|
loading,
|
||||||
|
paused,
|
||||||
|
playing,
|
||||||
|
completed,
|
||||||
|
}
|
||||||
|
|
||||||
|
class TimelineOverlay extends PropertyChangeNotifier<String> {
|
||||||
bool _showOverlay = true;
|
bool _showOverlay = true;
|
||||||
|
TimelineState _state = TimelineState.loading;
|
||||||
|
|
||||||
bool get showOverlay => _showOverlay;
|
bool get showOverlay => _showOverlay;
|
||||||
|
TimelineState get state => _state;
|
||||||
|
|
||||||
void hideOverlay() => setShowOverlay(false);
|
void hideOverlay() => setShowOverlay(false);
|
||||||
void restoreOverlay() => setShowOverlay(true);
|
void restoreOverlay() => setShowOverlay(true);
|
||||||
|
|
||||||
void setShowOverlay(bool showOverlay) {
|
void setShowOverlay(bool showOverlay) {
|
||||||
_showOverlay = showOverlay;
|
_showOverlay = showOverlay;
|
||||||
|
notifyListeners('showOverlay');
|
||||||
|
}
|
||||||
|
|
||||||
|
void setState(TimelineState state) {
|
||||||
|
_state = state;
|
||||||
|
notifyListeners('state');
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset() {
|
||||||
|
_showOverlay = true;
|
||||||
|
_state = TimelineState.loading;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
53
lib/widgets/memory_sheet.dart
Normal file
53
lib/widgets/memory_sheet.dart
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:share_location/constants/spacing.dart';
|
||||||
|
import 'package:share_location/foreign_types/memory.dart';
|
||||||
|
import 'package:share_location/managers/file_manager.dart';
|
||||||
|
import 'package:share_location/utils/loadable.dart';
|
||||||
|
import 'package:share_location/widgets/modal_sheet.dart';
|
||||||
|
|
||||||
|
class MemorySheet extends StatefulWidget {
|
||||||
|
final Memory memory;
|
||||||
|
|
||||||
|
const MemorySheet({
|
||||||
|
Key? key,
|
||||||
|
required this.memory,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<MemorySheet> createState() => _MemorySheetState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _MemorySheetState extends State<MemorySheet> with Loadable {
|
||||||
|
Future<void> deleteFile() => FileManager.deleteFile(widget.memory.location);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final theme = Theme.of(context);
|
||||||
|
|
||||||
|
return ModalSheet(
|
||||||
|
child: Column(
|
||||||
|
children: <Widget>[
|
||||||
|
Text(
|
||||||
|
'Edit Memory',
|
||||||
|
style: theme.textTheme.headline1,
|
||||||
|
),
|
||||||
|
const SizedBox(height: MEDIUM_SPACE),
|
||||||
|
ListTile(
|
||||||
|
leading: Icon(Icons.delete_forever_sharp),
|
||||||
|
title: Text('Delete Memory'),
|
||||||
|
onTap: isLoading
|
||||||
|
? null
|
||||||
|
: () async {
|
||||||
|
await callWithLoading(deleteFile);
|
||||||
|
|
||||||
|
if (mounted) {
|
||||||
|
Navigator.pop(context);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
trailing: isLoading ? const CircularProgressIndicator() : null,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:share_location/controllers/memory_slide_controller.dart';
|
|
||||||
import 'package:share_location/controllers/status_controller.dart';
|
import 'package:share_location/controllers/status_controller.dart';
|
||||||
import 'package:share_location/enums.dart';
|
import 'package:share_location/enums.dart';
|
||||||
import 'package:share_location/foreign_types/memory.dart';
|
import 'package:share_location/foreign_types/memory.dart';
|
||||||
@ -14,12 +13,10 @@ const DEFAULT_IMAGE_DURATION = Duration(seconds: 5);
|
|||||||
|
|
||||||
class MemorySlide extends StatefulWidget {
|
class MemorySlide extends StatefulWidget {
|
||||||
final Memory memory;
|
final Memory memory;
|
||||||
final MemorySlideController controller;
|
|
||||||
|
|
||||||
const MemorySlide({
|
const MemorySlide({
|
||||||
Key? key,
|
Key? key,
|
||||||
required this.memory,
|
required this.memory,
|
||||||
required this.controller,
|
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -36,15 +33,19 @@ class _MemorySlideState extends State<MemorySlide>
|
|||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
|
||||||
widget.controller.addListener(() {
|
final timelineOverlay = context.read<TimelineOverlay>();
|
||||||
|
|
||||||
|
timelineOverlay.addListener(() {
|
||||||
if (!mounted) {
|
if (!mounted) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (widget.controller.paused) {
|
switch (timelineOverlay.state) {
|
||||||
controller?.stop();
|
case TimelineState.playing:
|
||||||
} else {
|
controller?.start();
|
||||||
controller?.start();
|
break;
|
||||||
|
default:
|
||||||
|
controller?.stop();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -57,11 +58,23 @@ class _MemorySlideState extends State<MemorySlide>
|
|||||||
}
|
}
|
||||||
|
|
||||||
void initializeAnimation(final Duration duration) {
|
void initializeAnimation(final Duration duration) {
|
||||||
|
final timelineOverlay = context.read<TimelineOverlay>();
|
||||||
|
|
||||||
this.duration = duration;
|
this.duration = duration;
|
||||||
|
|
||||||
controller = StatusController(
|
controller = StatusController(
|
||||||
duration: duration,
|
duration: duration,
|
||||||
)..addListener(widget.controller.setDone, ['done']);
|
);
|
||||||
|
|
||||||
|
controller!.addListener(() {
|
||||||
|
if (!mounted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (controller!.done) {
|
||||||
|
timelineOverlay.setState(TimelineState.completed);
|
||||||
|
}
|
||||||
|
}, ['done']);
|
||||||
|
|
||||||
setState(() {});
|
setState(() {});
|
||||||
}
|
}
|
||||||
@ -86,17 +99,17 @@ class _MemorySlideState extends State<MemorySlide>
|
|||||||
if (mounted) {
|
if (mounted) {
|
||||||
initializeAnimation(controller.value.duration);
|
initializeAnimation(controller.value.duration);
|
||||||
|
|
||||||
widget.controller.addListener(() {
|
overlayController.addListener(() {
|
||||||
if (!mounted) {
|
if (!mounted) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (widget.controller.paused) {
|
if (overlayController.state == TimelineState.playing) {
|
||||||
controller.pause();
|
|
||||||
} else {
|
|
||||||
controller.play();
|
controller.play();
|
||||||
|
} else {
|
||||||
|
controller.pause();
|
||||||
}
|
}
|
||||||
});
|
}, ['state']);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
39
lib/widgets/modal_sheet.dart
Normal file
39
lib/widgets/modal_sheet.dart
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:share_location/constants/spacing.dart';
|
||||||
|
|
||||||
|
class ModalSheet extends StatelessWidget {
|
||||||
|
final Widget child;
|
||||||
|
|
||||||
|
const ModalSheet({
|
||||||
|
Key? key,
|
||||||
|
required this.child,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final theme = Theme.of(context);
|
||||||
|
|
||||||
|
return Wrap(
|
||||||
|
crossAxisAlignment: WrapCrossAlignment.center,
|
||||||
|
children: <Widget>[
|
||||||
|
Padding(
|
||||||
|
padding:
|
||||||
|
EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
|
||||||
|
child: Container(
|
||||||
|
width: double.infinity,
|
||||||
|
padding: const EdgeInsets.all(MEDIUM_SPACE),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: theme.bottomSheetTheme.modalBackgroundColor ??
|
||||||
|
theme.bottomAppBarColor,
|
||||||
|
borderRadius: const BorderRadius.only(
|
||||||
|
topLeft: Radius.circular(LARGE_SPACE),
|
||||||
|
topRight: Radius.circular(LARGE_SPACE),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: child,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -4,21 +4,19 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:share_location/constants/spacing.dart';
|
import 'package:share_location/constants/spacing.dart';
|
||||||
import 'package:share_location/controllers/memory_slide_controller.dart';
|
import 'package:share_location/models/memory_pack.dart';
|
||||||
import 'package:share_location/foreign_types/memory.dart';
|
|
||||||
import 'package:share_location/models/timeline_overlay.dart';
|
import 'package:share_location/models/timeline_overlay.dart';
|
||||||
|
import 'package:share_location/widgets/memory_sheet.dart';
|
||||||
import 'package:share_location/widgets/memory_slide.dart';
|
import 'package:share_location/widgets/memory_slide.dart';
|
||||||
|
|
||||||
class TimelinePage extends StatefulWidget {
|
class TimelinePage extends StatefulWidget {
|
||||||
final DateTime date;
|
final DateTime date;
|
||||||
final List<Memory> memories;
|
|
||||||
final VoidCallback onPreviousTimeline;
|
final VoidCallback onPreviousTimeline;
|
||||||
final VoidCallback onNextTimeline;
|
final VoidCallback onNextTimeline;
|
||||||
|
|
||||||
const TimelinePage({
|
const TimelinePage({
|
||||||
Key? key,
|
Key? key,
|
||||||
required this.date,
|
required this.date,
|
||||||
required this.memories,
|
|
||||||
required this.onPreviousTimeline,
|
required this.onPreviousTimeline,
|
||||||
required this.onNextTimeline,
|
required this.onNextTimeline,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
@ -30,7 +28,6 @@ class TimelinePage extends StatefulWidget {
|
|||||||
class _TimelinePageState extends State<TimelinePage> {
|
class _TimelinePageState extends State<TimelinePage> {
|
||||||
final timelineOverlayController = TimelineOverlay();
|
final timelineOverlayController = TimelineOverlay();
|
||||||
final pageController = PageController();
|
final pageController = PageController();
|
||||||
late final MemorySlideController controller;
|
|
||||||
|
|
||||||
Timer? overlayRemover;
|
Timer? overlayRemover;
|
||||||
|
|
||||||
@ -38,37 +35,75 @@ class _TimelinePageState extends State<TimelinePage> {
|
|||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
|
||||||
controller = MemorySlideController(memoryLength: widget.memories.length);
|
final memoryPack = context.read<MemoryPack>();
|
||||||
controller.addListener(() {
|
|
||||||
if (controller.done) {
|
|
||||||
controller.next();
|
|
||||||
|
|
||||||
pageController.nextPage(
|
timelineOverlayController.addListener(() {
|
||||||
duration: const Duration(milliseconds: 200),
|
if (!mounted) {
|
||||||
curve: Curves.linearToEaseOut,
|
return;
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}, ['done']);
|
|
||||||
controller.addListener(() {
|
if (timelineOverlayController.state == TimelineState.completed) {
|
||||||
if (controller.completed) {
|
timelineOverlayController.reset();
|
||||||
|
memoryPack.next();
|
||||||
|
}
|
||||||
|
}, ['state']);
|
||||||
|
|
||||||
|
memoryPack.addListener(() {
|
||||||
|
if (!mounted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (memoryPack.completed) {
|
||||||
widget.onNextTimeline();
|
widget.onNextTimeline();
|
||||||
|
memoryPack.reset();
|
||||||
}
|
}
|
||||||
}, ['completed']);
|
}, ['completed']);
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
memoryPack.addListener(() {
|
||||||
void dispose() {
|
if (!mounted) {
|
||||||
controller.dispose();
|
return;
|
||||||
timelineOverlayController.dispose();
|
}
|
||||||
|
|
||||||
super.dispose();
|
if (memoryPack.currentMemoryIndex != pageController.page) {
|
||||||
|
pageController.animateToPage(
|
||||||
|
memoryPack.currentMemoryIndex,
|
||||||
|
duration: const Duration(milliseconds: 300),
|
||||||
|
curve: Curves.easeOutQuad,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
|
onDoubleTap: () async {
|
||||||
|
final memoryPack = context.read<MemoryPack>();
|
||||||
|
|
||||||
|
memoryPack.pause();
|
||||||
|
timelineOverlayController.hideOverlay();
|
||||||
|
|
||||||
|
await showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
|
isScrollControlled: true,
|
||||||
|
builder: (_) => MemorySheet(
|
||||||
|
memory: memoryPack.currentMemory,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!mounted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memoryPack.removeCurrentMemory();
|
||||||
|
memoryPack.resume();
|
||||||
|
timelineOverlayController.restoreOverlay();
|
||||||
|
},
|
||||||
onTapDown: (_) {
|
onTapDown: (_) {
|
||||||
controller.setPaused(true);
|
final memoryPack = context.read<MemoryPack>();
|
||||||
|
|
||||||
|
memoryPack.pause();
|
||||||
|
|
||||||
overlayRemover = Timer(
|
overlayRemover = Timer(
|
||||||
const Duration(milliseconds: 200),
|
const Duration(milliseconds: 200),
|
||||||
@ -76,28 +111,32 @@ class _TimelinePageState extends State<TimelinePage> {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
onTapUp: (_) {
|
onTapUp: (_) {
|
||||||
|
final memoryPack = context.read<MemoryPack>();
|
||||||
|
|
||||||
overlayRemover?.cancel();
|
overlayRemover?.cancel();
|
||||||
|
memoryPack.resume();
|
||||||
controller.setPaused(false);
|
|
||||||
|
|
||||||
timelineOverlayController.restoreOverlay();
|
timelineOverlayController.restoreOverlay();
|
||||||
},
|
},
|
||||||
onTapCancel: () {
|
onTapCancel: () {
|
||||||
|
final memoryPack = context.read<MemoryPack>();
|
||||||
|
|
||||||
overlayRemover?.cancel();
|
overlayRemover?.cancel();
|
||||||
|
|
||||||
timelineOverlayController.restoreOverlay();
|
timelineOverlayController.restoreOverlay();
|
||||||
controller.setPaused(false);
|
memoryPack.resume();
|
||||||
},
|
},
|
||||||
onHorizontalDragEnd: (details) {
|
onHorizontalDragEnd: (details) {
|
||||||
|
final memoryPack = context.read<MemoryPack>();
|
||||||
|
|
||||||
if (details.primaryVelocity! < 0) {
|
if (details.primaryVelocity! < 0) {
|
||||||
controller.next();
|
memoryPack.next();
|
||||||
|
|
||||||
pageController.nextPage(
|
pageController.nextPage(
|
||||||
duration: const Duration(milliseconds: 200),
|
duration: const Duration(milliseconds: 200),
|
||||||
curve: Curves.linearToEaseOut,
|
curve: Curves.linearToEaseOut,
|
||||||
);
|
);
|
||||||
} else if (details.primaryVelocity! > 0) {
|
} else if (details.primaryVelocity! > 0) {
|
||||||
controller.previous();
|
memoryPack.previous();
|
||||||
|
|
||||||
pageController.previousPage(
|
pageController.previousPage(
|
||||||
duration: const Duration(milliseconds: 200),
|
duration: const Duration(milliseconds: 200),
|
||||||
@ -110,16 +149,19 @@ class _TimelinePageState extends State<TimelinePage> {
|
|||||||
child: Stack(
|
child: Stack(
|
||||||
fit: StackFit.expand,
|
fit: StackFit.expand,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
PageView.builder(
|
Consumer<MemoryPack>(
|
||||||
controller: pageController,
|
builder: (_, memoryPack, __) {
|
||||||
physics: const NeverScrollableScrollPhysics(),
|
return PageView.builder(
|
||||||
scrollDirection: Axis.horizontal,
|
controller: pageController,
|
||||||
itemBuilder: (_, __) => MemorySlide(
|
physics: const NeverScrollableScrollPhysics(),
|
||||||
key: Key(controller.index.toString()),
|
scrollDirection: Axis.horizontal,
|
||||||
controller: controller,
|
itemBuilder: (_, index) => MemorySlide(
|
||||||
memory: widget.memories[controller.index],
|
key: Key(memoryPack.memories[index].filename),
|
||||||
),
|
memory: memoryPack.memories[index],
|
||||||
itemCount: widget.memories.length,
|
),
|
||||||
|
itemCount: memoryPack.memories.length,
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(
|
padding: const EdgeInsets.only(
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
import 'package:share_location/foreign_types/memory.dart';
|
import 'package:share_location/foreign_types/memory.dart';
|
||||||
|
import 'package:share_location/models/memory_pack.dart';
|
||||||
import 'package:share_location/utils/loadable.dart';
|
import 'package:share_location/utils/loadable.dart';
|
||||||
import 'package:share_location/widgets/timeline_page.dart';
|
import 'package:share_location/widgets/timeline_page.dart';
|
||||||
import 'package:supabase_flutter/supabase_flutter.dart';
|
import 'package:supabase_flutter/supabase_flutter.dart';
|
||||||
@ -18,7 +20,7 @@ class TimelineScroll extends StatefulWidget {
|
|||||||
|
|
||||||
class _TimelineScrollState extends State<TimelineScroll> with Loadable {
|
class _TimelineScrollState extends State<TimelineScroll> with Loadable {
|
||||||
final pageController = PageController();
|
final pageController = PageController();
|
||||||
dynamic timeline;
|
Map<String, MemoryPack>? timeline;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
initState() {
|
initState() {
|
||||||
@ -41,7 +43,7 @@ class _TimelineScrollState extends State<TimelineScroll> with Loadable {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static Map<String, List<Memory>> convertMemoriesToTimeline(
|
static Map<String, MemoryPack> convertMemoriesToTimeline(
|
||||||
final List<Memory> memories,
|
final List<Memory> memories,
|
||||||
) {
|
) {
|
||||||
final map = <String, List<Memory>>{};
|
final map = <String, List<Memory>>{};
|
||||||
@ -55,7 +57,14 @@ class _TimelineScrollState extends State<TimelineScroll> with Loadable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return map;
|
return Map.fromEntries(
|
||||||
|
map.entries.map(
|
||||||
|
(entry) => MapEntry<String, MemoryPack>(
|
||||||
|
entry.key,
|
||||||
|
MemoryPack(entry.value),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -70,22 +79,24 @@ class _TimelineScrollState extends State<TimelineScroll> with Loadable {
|
|||||||
body: PageView.builder(
|
body: PageView.builder(
|
||||||
controller: pageController,
|
controller: pageController,
|
||||||
scrollDirection: Axis.vertical,
|
scrollDirection: Axis.vertical,
|
||||||
itemCount: timeline.length,
|
itemCount: timeline!.length,
|
||||||
itemBuilder: (_, index) => TimelinePage(
|
itemBuilder: (_, index) => ChangeNotifierProvider<MemoryPack>(
|
||||||
date: DateTime.parse(timeline.keys.toList()[index]),
|
create: (_) => timeline!.values.elementAt(index),
|
||||||
memories: timeline.values.toList()[index],
|
child: TimelinePage(
|
||||||
onNextTimeline: () {
|
date: DateTime.parse(timeline!.keys.toList()[index]),
|
||||||
pageController.nextPage(
|
onNextTimeline: () {
|
||||||
duration: const Duration(milliseconds: 500),
|
pageController.nextPage(
|
||||||
curve: Curves.ease,
|
duration: const Duration(milliseconds: 500),
|
||||||
);
|
curve: Curves.ease,
|
||||||
},
|
);
|
||||||
onPreviousTimeline: () {
|
},
|
||||||
pageController.previousPage(
|
onPreviousTimeline: () {
|
||||||
duration: const Duration(milliseconds: 500),
|
pageController.previousPage(
|
||||||
curve: Curves.ease,
|
duration: const Duration(milliseconds: 500),
|
||||||
);
|
curve: Curves.ease,
|
||||||
},
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user