diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/android/app/src/main/res/mipmap-hdpi/ic_launcher.webp index c56eb44..b323786 100644 Binary files a/android/app/src/main/res/mipmap-hdpi/ic_launcher.webp and b/android/app/src/main/res/mipmap-hdpi/ic_launcher.webp differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/android/app/src/main/res/mipmap-mdpi/ic_launcher.webp index 237437e..6dfa492 100644 Binary files a/android/app/src/main/res/mipmap-mdpi/ic_launcher.webp and b/android/app/src/main/res/mipmap-mdpi/ic_launcher.webp differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.webp index 1b26758..ab1bba6 100644 Binary files a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.webp and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.webp differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp index 1cb028f..004e65b 100644 Binary files a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp index b4e4fbe..870d804 100644 Binary files a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/100.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/100.png index 9a00ea0..05c6678 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/100.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/100.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/102.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/102.png index 21f1a5b..bc47860 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/102.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/102.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/1024.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/1024.png index 1f3637a..5b33580 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/1024.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/1024.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/108.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/108.png index c71a2ce..1c430ec 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/108.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/108.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/114.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/114.png index 8c660eb..5122377 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/114.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/114.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/120.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/120.png index 8873c95..5d52d3c 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/120.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/120.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/128.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/128.png index 135639e..8af083c 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/128.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/128.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/144.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/144.png index 91c6465..b425946 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/144.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/144.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/152.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/152.png index fc0f199..1e7b60d 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/152.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/152.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/16.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/16.png index 2c81760..72d944f 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/16.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/16.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/167.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/167.png index f5edfee..c098e7e 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/167.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/167.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/172.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/172.png index 97507b3..3e11b21 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/172.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/172.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/180.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/180.png index b2210d2..8d17772 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/180.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/180.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/196.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/196.png index 3bc52a3..7dcd953 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/196.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/196.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/20.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/20.png index b0d03d8..1b06d84 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/20.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/20.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/216.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/216.png index 9b8b2fb..efe0d18 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/216.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/216.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/234.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/234.png index 05d2dea..a583803 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/234.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/234.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/256.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/256.png index dec6af3..c4a9338 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/256.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/256.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/258.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/258.png index f1069f2..78220b0 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/258.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/258.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/29.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/29.png index ea08e94..cf04648 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/29.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/29.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/32.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/32.png index 83375bf..deaa65f 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/32.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/32.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/40.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/40.png index 6bd51f3..7b33003 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/40.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/40.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/48.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/48.png index 25c2a81..8e3a0af 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/48.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/48.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/50.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/50.png index 1684db2..eaeae6c 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/50.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/50.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/512.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/512.png index a152a73..1ff02ae 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/512.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/512.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/55.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/55.png index 8be28b3..b0068d0 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/55.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/55.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/57.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/57.png index 37e33f0..ab013b0 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/57.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/57.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/58.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/58.png index d89f607..81993c7 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/58.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/58.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/60.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/60.png index cf3c61d..560d15c 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/60.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/60.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/64.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/64.png index a44e260..ee5768d 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/64.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/64.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/66.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/66.png index 711af18..b569fc5 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/66.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/66.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/72.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/72.png index dc964c1..cc309a6 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/72.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/72.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/76.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/76.png index 2b7a2d2..9d24125 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/76.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/76.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/80.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/80.png index 35841e7..526c578 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/80.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/80.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/87.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/87.png index 7a6c512..d87619e 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/87.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/87.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/88.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/88.png index 4158a2a..1ff9358 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/88.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/88.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/92.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/92.png index 2a30e07..0c2c7b1 100644 Binary files a/ios/Runner/Assets.xcassets/AppIcon.appiconset/92.png and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/92.png differ diff --git a/lib/main.dart b/lib/main.dart index 9e91f64..f341241 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -15,6 +15,7 @@ class F0ckApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( + debugShowCheckedModeBanner: false, theme: ThemeData( scaffoldBackgroundColor: const Color.fromARGB(255, 23, 23, 23), ), diff --git a/lib/mediagrid.dart b/lib/mediagrid.dart index 2363c24..cbfe0a6 100644 --- a/lib/mediagrid.dart +++ b/lib/mediagrid.dart @@ -13,7 +13,7 @@ class MediaGrid extends StatefulWidget { class _MediaGridState extends State { final ScrollController _scrollController = ScrollController(); - final String _version = '1.0.15'; + final String _version = '1.0.17'; List mediaItems = []; bool isLoading = false; Timer? _debounceTimer; diff --git a/lib/screens/detailview.dart b/lib/screens/detailview.dart index 74edb68..856e7c5 100644 --- a/lib/screens/detailview.dart +++ b/lib/screens/detailview.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:f0ckapp/models/mediaitem.dart'; import 'package:f0ckapp/services/api.dart'; import 'package:f0ckapp/widgets/video_widget.dart'; +import 'package:f0ckapp/utils/SmartRefreshIndicator.dart'; class DetailView extends StatefulWidget { final int initialItemId; @@ -26,33 +27,32 @@ class DetailView extends StatefulWidget { class _DetailViewState extends State { late PageController _pageController; late List mediaItems; - final List _modes = ["sfw", "nsfw", "untagged", "all"]; int currentItemId = 0; bool isLoading = false; @override void initState() { super.initState(); - mediaItems = widget.mediaItems; final initialIndex = mediaItems.indexWhere( (item) => item.id == widget.initialItemId, ); _pageController = PageController(initialPage: initialIndex); - currentItemId = mediaItems[initialIndex].id; - _pageController.addListener(() { - final newIndex = _pageController.page?.round(); - if (newIndex != null && newIndex < mediaItems.length) { - setState(() => currentItemId = mediaItems[newIndex].id); - } + _pageController.addListener(_onPageScroll); + } - if (_pageController.position.pixels >= - _pageController.position.maxScrollExtent - 100) { - _loadMoreMedia(); - } - }); + void _onPageScroll() { + final newIndex = _pageController.page?.round(); + if (newIndex != null && newIndex < mediaItems.length) { + setState(() => currentItemId = mediaItems[newIndex].id); + } + + if (_pageController.position.pixels >= + _pageController.position.maxScrollExtent - 100) { + _loadMoreMedia(); + } } Future _loadMoreMedia() async { @@ -66,15 +66,11 @@ class _DetailViewState extends State { mode: widget.mode, random: widget.random, ); - if (mounted) { + if (mounted && newMedia.isNotEmpty) { setState(() => mediaItems.addAll(newMedia)); } } catch (e) { - if (mounted) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text('Fehler beim Laden weiterer Medien: $e')), - ); - } + _showError("Fehler beim Laden weiterer Medien: $e"); } finally { setState(() => isLoading = false); } @@ -84,21 +80,21 @@ class _DetailViewState extends State { try { final updatedItem = await fetchMediaDetail(currentItemId); if (mounted) { - setState(() { - final index = mediaItems.indexWhere( - (item) => item.id == currentItemId, - ); - if (index != -1) { - mediaItems[index] = updatedItem; - } - }); + final index = mediaItems.indexWhere((item) => item.id == currentItemId); + if (index != -1) { + setState(() => mediaItems[index] = updatedItem); + } } } catch (e) { - if (mounted) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text('Fehler beim Aktualisieren des Items: $e')), - ); - } + _showError("Fehler beim Aktualisieren des Items: $e"); + } + } + + void _showError(String message) { + if (mounted) { + ScaffoldMessenger.of( + context, + ).showSnackBar(SnackBar(content: Text(message))); } } @@ -109,70 +105,60 @@ class _DetailViewState extends State { appBar: AppBar( backgroundColor: const Color(0xFF2B2B2B), foregroundColor: Colors.white, - title: Text( - 'f0ck #$currentItemId (${widget.type}, ${_modes[widget.mode]})', - ), + title: Text('f0ck #$currentItemId (${widget.type})'), centerTitle: true, ), - body: RefreshIndicator( - onRefresh: _refreshMediaItem, - child: SingleChildScrollView( - child: Column( - children: [ - SizedBox( - height: MediaQuery.of(context).size.height, - child: PageView.builder( - controller: _pageController, - itemCount: mediaItems.length, - itemBuilder: (context, index) { - final item = mediaItems[index]; - return Column( - children: [ - if (item.mime.startsWith('image')) - Image.network(item.mediaUrl, fit: BoxFit.contain) - else - VideoWidget(details: item), - const SizedBox(height: 20), - Text( - item.mime, - style: const TextStyle( - color: Colors.white, - fontSize: 18, - ), - ), - const SizedBox(height: 10), - Wrap( - alignment: WrapAlignment.center, - spacing: 5.0, - children: item.tags.map((tag) { - Color tagColor; - switch (tag.id) { - case 1: - tagColor = Colors.green; - break; - case 2: - tagColor = Colors.red; - break; - default: - tagColor = const Color(0xFF090909); - } - - return Chip( - label: Text(tag.tag), - backgroundColor: tagColor, - labelStyle: const TextStyle(color: Colors.white), - ); - }).toList(), - ), - const SizedBox(height: 40), - ], - ); - }, - ), + body: PageView.builder( + controller: _pageController, + itemCount: mediaItems.length, + itemBuilder: (context, index) { + final MediaItem item = mediaItems[index]; + return Scaffold( + body: SafeArea( + child: SmartRefreshIndicator( + onRefresh: _refreshMediaItem, + child: _buildMediaItem(item) ), - ], + ), + ); + }, + ), + ); + } + + Widget _buildMediaItem(MediaItem item) { + return SingleChildScrollView( + child: Column( + children: [ + if (item.mime.startsWith('image')) + Image.network( + item.mediaUrl, + fit: BoxFit.contain, + ) + else + VideoWidget(details: item), + const SizedBox(height: 20), + Text( + item.mime, + style: const TextStyle(color: Colors.white, fontSize: 18), ), - ), + const SizedBox(height: 10), + Wrap( + alignment: WrapAlignment.center, + spacing: 5.0, + children: item.tags.map((tag) { + return Chip( + label: Text(tag.tag), + backgroundColor: { + 1: Colors.green, + 2: Colors.red + }[tag.id] ?? const Color(0xFF090909), + labelStyle: const TextStyle(color: Colors.white), + ); + }).toList(), + ), + const SizedBox(height: 20), + ], ), ); } diff --git a/lib/utils/SmartRefreshIndicator.dart b/lib/utils/SmartRefreshIndicator.dart new file mode 100644 index 0000000..cb654c0 --- /dev/null +++ b/lib/utils/SmartRefreshIndicator.dart @@ -0,0 +1,28 @@ +import 'package:flutter/material.dart'; + +class SmartRefreshIndicator extends StatelessWidget { + final Future Function() onRefresh; + final Widget child; + + const SmartRefreshIndicator({ + super.key, + required this.onRefresh, + required this.child, + }); + + @override + Widget build(context) { + return LayoutBuilder( + builder: (context, constraints) => RefreshIndicator( + onRefresh: onRefresh, + child: SingleChildScrollView( + physics: const AlwaysScrollableScrollPhysics(), + child: ConstrainedBox( + constraints: BoxConstraints(minHeight: constraints.maxHeight), + child: child, + ), + ), + ), + ); + } +} diff --git a/lib/widgets/video_widget.dart b/lib/widgets/video_widget.dart index 4738fb4..32fc514 100644 --- a/lib/widgets/video_widget.dart +++ b/lib/widgets/video_widget.dart @@ -52,7 +52,9 @@ class _VideoWidgetState extends State { mainAxisSize: MainAxisSize.min, children: [ AspectRatio( - aspectRatio: isAudio ? 1.0 : _controller.value.aspectRatio, + aspectRatio: _controller.value.isInitialized + ? _controller.value.aspectRatio + : 9 / 16, child: Stack( alignment: Alignment.center, children: [ @@ -66,104 +68,108 @@ class _VideoWidgetState extends State { }, child: isAudio ? Image.network(widget.details.coverUrl, fit: BoxFit.cover) - : VideoPlayer(_controller), + : _controller.value.isInitialized + ? VideoPlayer(_controller) + : Center(child: CircularProgressIndicator()), ), - Align( - alignment: Alignment.bottomCenter, - child: Stack( + if (_controller.value.isInitialized) + Align( + alignment: Alignment.bottomCenter, + child: Stack( + children: [ + SizedBox( + height: 10, + child: VideoProgressIndicator( + _controller, + allowScrubbing: true, + padding: EdgeInsets.only(bottom: 0), + colors: VideoProgressColors( + playedColor: Colors.red, + bufferedColor: Colors.grey, + backgroundColor: Colors.black.withAlpha(128), + ), + ), + ), + Positioned( + left: + (_controller.value.position.inMilliseconds / + _controller.value.duration.inMilliseconds) * + MediaQuery.of(context).size.width - + 6, + bottom: -1, + child: Container( + width: 12, + height: 12, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.white, + border: Border.all(color: Colors.red, width: 2), + ), + ), + ), + ], + ), + ), + ], + ), + ), + if (_controller.value.isInitialized) + SizedBox( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + _formatDuration(_controller.value.position), + style: const TextStyle(color: Colors.white), + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, children: [ - SizedBox( - height: 10, - child: VideoProgressIndicator( - _controller, - allowScrubbing: true, - padding: EdgeInsets.only(bottom: 0), - colors: VideoProgressColors( - playedColor: Colors.red, - bufferedColor: Colors.grey, - backgroundColor: Colors.black.withValues(alpha: 0.5), - ), - ), + IconButton( + icon: const Icon(Icons.replay_10), + color: Colors.white, + onPressed: () { + _controller.seekTo( + _controller.value.position - + const Duration(seconds: 10), + ); + }, ), - Positioned( - left: - (_controller.value.position.inMilliseconds / - _controller.value.duration.inMilliseconds) * - MediaQuery.of(context).size.width - - 6, - bottom: -1, - child: Container( - width: 12, - height: 12, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: Colors.white, - border: Border.all(color: Colors.red, width: 2), - ), + IconButton( + color: Colors.white, + icon: Icon( + _controller.value.isPlaying + ? Icons.pause + : Icons.play_arrow, ), + onPressed: () { + setState(() { + _controller.value.isPlaying + ? _controller.pause() + : _controller.play(); + }); + }, + ), + IconButton( + color: Colors.white, + icon: const Icon(Icons.forward_10), + onPressed: () { + _controller.seekTo( + _controller.value.position + + const Duration(seconds: 10), + ); + }, ), ], ), - ), - ], + Text( + _formatDuration(_controller.value.duration), + style: const TextStyle(color: Colors.white), + ), + ], + ), ), - ), - SizedBox( - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - _formatDuration(_controller.value.position), - style: const TextStyle(color: Colors.white), - ), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - IconButton( - icon: const Icon(Icons.replay_10), - color: Colors.white, - onPressed: () { - _controller.seekTo( - _controller.value.position - - const Duration(seconds: 10), - ); - }, - ), - IconButton( - color: Colors.white, - icon: Icon( - _controller.value.isPlaying - ? Icons.pause - : Icons.play_arrow, - ), - onPressed: () { - setState(() { - _controller.value.isPlaying - ? _controller.pause() - : _controller.play(); - }); - }, - ), - IconButton( - color: Colors.white, - icon: const Icon(Icons.forward_10), - onPressed: () { - _controller.seekTo( - _controller.value.position + - const Duration(seconds: 10), - ); - }, - ), - ], - ), - Text( - _formatDuration(_controller.value.duration), - style: const TextStyle(color: Colors.white), - ), - ], - ), - ), ], ); } diff --git a/pubspec.yaml b/pubspec.yaml index d37cd99..58f670e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 1.0.15 +version: 1.0.17 environment: sdk: ^3.9.0-172.0.dev