improvements

This commit is contained in:
Myzel394 2022-08-14 16:38:49 +02:00
parent 83f3ac8674
commit da2d658557
9 changed files with 105 additions and 28 deletions

View File

@ -1,3 +1,5 @@
import 'dart:math';
import 'package:property_change_notifier/property_change_notifier.dart'; import 'package:property_change_notifier/property_change_notifier.dart';
class MemorySlideController extends PropertyChangeNotifier<String> { class MemorySlideController extends PropertyChangeNotifier<String> {
@ -39,6 +41,11 @@ class MemorySlideController extends PropertyChangeNotifier<String> {
} }
} }
void previous() {
_index = max(_index - 1, 0);
notifyListeners();
}
void reset() { void reset() {
_completed = false; _completed = false;
_paused = false; _paused = false;

View File

@ -1,3 +1,4 @@
import 'package:path/path.dart';
import 'package:share_location/enums.dart'; import 'package:share_location/enums.dart';
class Memory { class Memory {
@ -25,6 +26,8 @@ class Memory {
); );
} }
String get filename => basename(location);
MemoryType get type => MemoryType get type =>
location.split('.').last == 'jpg' ? MemoryType.photo : MemoryType.video; filename.split('.').last == 'jpg' ? MemoryType.photo : MemoryType.video;
} }

View File

@ -1,4 +1,5 @@
import 'dart:typed_data'; import 'dart:typed_data';
import 'dart:ui';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:share_location/constants/spacing.dart'; import 'package:share_location/constants/spacing.dart';
@ -20,6 +21,7 @@ enum MemoryFetchStatus {
class MemoryView extends StatefulWidget { class MemoryView extends StatefulWidget {
final String location; final String location;
final DateTime creationDate; final DateTime creationDate;
final String filename;
final bool loopVideo; final bool loopVideo;
final void Function(VideoPlayerController)? onVideoControllerInitialized; final void Function(VideoPlayerController)? onVideoControllerInitialized;
final VoidCallback? onFileDownloaded; final VoidCallback? onFileDownloaded;
@ -28,6 +30,7 @@ class MemoryView extends StatefulWidget {
Key? key, Key? key,
required this.location, required this.location,
required this.creationDate, required this.creationDate,
required this.filename,
this.loopVideo = false, this.loopVideo = false,
this.onVideoControllerInitialized, this.onVideoControllerInitialized,
this.onFileDownloaded, this.onFileDownloaded,
@ -131,11 +134,30 @@ class _MemoryViewState extends AuthRequiredState<MemoryView> {
} }
if (status == MemoryFetchStatus.done) { if (status == MemoryFetchStatus.done) {
return RawMemoryDisplay( return Stack(
fit: StackFit.expand,
alignment: Alignment.center,
children: <Widget>[
if (type == MemoryType.photo)
ImageFiltered(
imageFilter: ImageFilter.blur(sigmaX: 10, sigmaY: 10),
child: RawMemoryDisplay(
filename: widget.filename,
data: data!, data: data!,
type: type!, type: type!,
loopVideo: widget.loopVideo, loopVideo: widget.loopVideo,
fit: BoxFit.cover,
),
),
RawMemoryDisplay(
filename: widget.filename,
data: data!,
type: type!,
fit: BoxFit.contain,
loopVideo: widget.loopVideo,
onVideoControllerInitialized: widget.onVideoControllerInitialized, onVideoControllerInitialized: widget.onVideoControllerInitialized,
),
],
); );
} }

View File

@ -71,6 +71,7 @@ class _MemorySlideState extends State<MemorySlide>
child: MemoryView( child: MemoryView(
creationDate: widget.memory.creationDate, creationDate: widget.memory.creationDate,
location: widget.memory.location, location: widget.memory.location,
filename: widget.memory.filename,
loopVideo: false, loopVideo: false,
onFileDownloaded: () { onFileDownloaded: () {
if (widget.memory.type == MemoryType.photo) { if (widget.memory.type == MemoryType.photo) {

View File

@ -12,12 +12,14 @@ class RawMemoryDisplay extends StatefulWidget {
final bool loopVideo; final bool loopVideo;
final String? filename; final String? filename;
final void Function(VideoPlayerController)? onVideoControllerInitialized; final void Function(VideoPlayerController)? onVideoControllerInitialized;
final BoxFit? fit;
const RawMemoryDisplay({ const RawMemoryDisplay({
Key? key, Key? key,
required this.data, required this.data,
required this.type, required this.type,
this.loopVideo = false, this.loopVideo = false,
this.fit = BoxFit.cover,
this.filename, this.filename,
this.onVideoControllerInitialized, this.onVideoControllerInitialized,
}) : super(key: key); }) : super(key: key);
@ -41,14 +43,15 @@ class _RawMemoryDisplayState extends State<RawMemoryDisplay> {
Future<File> createTempVideo() async { Future<File> createTempVideo() async {
final tempDirectory = await getTemporaryDirectory(); final tempDirectory = await getTemporaryDirectory();
final path = '${tempDirectory.path}/${widget.filename ?? 'video.mp4'}'; final path = '${tempDirectory.path}/${widget.filename ?? 'video.mp4'}';
final file = File(path);
if (widget.filename != null) { if (await file.exists()) {
// File already exists, so just return the path // File already exists, so just return it
return File(path); return file;
} }
// File needs to be created // File needs to be created
final file = await File(path).create(); await file.create();
await file.writeAsBytes(widget.data); await file.writeAsBytes(widget.data);
return file; return file;
@ -82,17 +85,27 @@ class _RawMemoryDisplayState extends State<RawMemoryDisplay> {
case MemoryType.photo: case MemoryType.photo:
return Image.memory( return Image.memory(
widget.data, widget.data,
fit: BoxFit.cover, fit: widget.fit,
); );
case MemoryType.video: case MemoryType.video:
if (videoController == null) { if (videoController == null) {
return const SizedBox(); return const SizedBox();
} }
switch (widget.fit) {
case BoxFit.contain:
return Align(
child: AspectRatio(
aspectRatio: videoController!.value.aspectRatio,
child: VideoPlayer(videoController!),
),
);
default:
return AspectRatio( return AspectRatio(
aspectRatio: videoController!.value.aspectRatio, aspectRatio: videoController!.value.aspectRatio,
child: VideoPlayer(videoController!), child: VideoPlayer(videoController!),
); );
}
default: default:
throw Exception('Unknown memory type: ${widget.type}'); throw Exception('Unknown memory type: ${widget.type}');
} }

View File

@ -5,13 +5,13 @@ import 'package:share_location/controllers/memory_slide_controller.dart';
import 'package:share_location/foreign_types/memory.dart'; import 'package:share_location/foreign_types/memory.dart';
import 'package:share_location/widgets/memory_slide.dart'; import 'package:share_location/widgets/memory_slide.dart';
class MemoryPage extends StatefulWidget { class TimelinePage extends StatefulWidget {
final DateTime date; final DateTime date;
final List<Memory> memories; final List<Memory> memories;
final VoidCallback onPreviousTimeline; final VoidCallback onPreviousTimeline;
final VoidCallback onNextTimeline; final VoidCallback onNextTimeline;
const MemoryPage({ const TimelinePage({
Key? key, Key? key,
required this.date, required this.date,
required this.memories, required this.memories,
@ -20,10 +20,11 @@ class MemoryPage extends StatefulWidget {
}) : super(key: key); }) : super(key: key);
@override @override
State<MemoryPage> createState() => _MemoryPageState(); State<TimelinePage> createState() => _TimelinePageState();
} }
class _MemoryPageState extends State<MemoryPage> { class _TimelinePageState extends State<TimelinePage> {
final pageController = PageController();
late final MemorySlideController controller; late final MemorySlideController controller;
@override @override
@ -34,8 +35,11 @@ class _MemoryPageState extends State<MemoryPage> {
controller.addListener(() { controller.addListener(() {
if (controller.done) { if (controller.done) {
controller.next(); controller.next();
// Force UI update
setState(() {}); pageController.nextPage(
duration: const Duration(milliseconds: 200),
curve: Curves.linearToEaseOut,
);
} }
}, ['done']); }, ['done']);
controller.addListener(() { controller.addListener(() {
@ -61,14 +65,40 @@ class _MemoryPageState extends State<MemoryPage> {
onTapUp: (_) { onTapUp: (_) {
controller.setPaused(false); controller.setPaused(false);
}, },
onTapCancel: () {
controller.setPaused(false);
},
onHorizontalDragEnd: (details) {
if (details.primaryVelocity! < 0) {
controller.next();
pageController.nextPage(
duration: const Duration(milliseconds: 200),
curve: Curves.linearToEaseOut,
);
} else if (details.primaryVelocity! > 0) {
controller.previous();
pageController.previousPage(
duration: const Duration(milliseconds: 200),
curve: Curves.linearToEaseOut,
);
}
},
child: Stack( child: Stack(
fit: StackFit.expand, fit: StackFit.expand,
children: <Widget>[ children: <Widget>[
MemorySlide( PageView.builder(
controller: pageController,
physics: const NeverScrollableScrollPhysics(),
scrollDirection: Axis.horizontal,
itemBuilder: (_, __) => MemorySlide(
key: Key(controller.index.toString()), key: Key(controller.index.toString()),
controller: controller, controller: controller,
memory: widget.memories[controller.index], memory: widget.memories[controller.index],
), ),
itemCount: widget.memories.length,
),
Padding( Padding(
padding: const EdgeInsets.only( padding: const EdgeInsets.only(
top: LARGE_SPACE, left: MEDIUM_SPACE, right: MEDIUM_SPACE), top: LARGE_SPACE, left: MEDIUM_SPACE, right: MEDIUM_SPACE),

View File

@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:share_location/foreign_types/memory.dart'; import 'package:share_location/foreign_types/memory.dart';
import 'package:share_location/utils/loadable.dart'; import 'package:share_location/utils/loadable.dart';
import 'package:share_location/widgets/memory_page.dart'; import 'package:share_location/widgets/timeline_page.dart';
import 'package:supabase_flutter/supabase_flutter.dart'; import 'package:supabase_flutter/supabase_flutter.dart';
final supabase = Supabase.instance.client; final supabase = Supabase.instance.client;
@ -71,7 +71,7 @@ class _TimelineScrollState extends State<TimelineScroll> with Loadable {
controller: pageController, controller: pageController,
scrollDirection: Axis.vertical, scrollDirection: Axis.vertical,
itemCount: timeline.length, itemCount: timeline.length,
itemBuilder: (_, index) => MemoryPage( itemBuilder: (_, index) => TimelinePage(
date: DateTime.parse(timeline.keys.toList()[index]), date: DateTime.parse(timeline.keys.toList()[index]),
memories: timeline.values.toList()[index], memories: timeline.values.toList()[index],
onNextTimeline: () { onNextTimeline: () {

View File

@ -311,7 +311,7 @@ packages:
source: hosted source: hosted
version: "1.0.2" version: "1.0.2"
path: path:
dependency: transitive dependency: "direct main"
description: description:
name: path name: path
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"

View File

@ -44,6 +44,7 @@ dependencies:
path_provider: ^2.0.11 path_provider: ^2.0.11
intl: ^0.17.0 intl: ^0.17.0
property_change_notifier: ^0.3.0 property_change_notifier: ^0.3.0
path: ^1.8.1
dev_dependencies: dev_dependencies:
flutter_test: flutter_test: