feat: swipeable media pager, favorite artists, optimized video preview, Gitea updates and v2.0.2 release
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import 'dart:ui';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
@@ -39,12 +40,14 @@ class PostDetailsScreen extends ConsumerWidget {
|
||||
required this.providerId,
|
||||
required this.postId,
|
||||
this.initialPost,
|
||||
this.postsList,
|
||||
super.key,
|
||||
});
|
||||
|
||||
final String providerId;
|
||||
final String postId;
|
||||
final Post? initialPost;
|
||||
final List<Post>? postsList;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
@@ -57,8 +60,9 @@ class PostDetailsScreen extends ConsumerWidget {
|
||||
final settings =
|
||||
ref.watch(appSettingsProvider).value ?? AppSettings.defaults;
|
||||
final strings = ref.watch(appStringsProvider);
|
||||
final feedPosts =
|
||||
ref.watch(feedControllerProvider).value?.posts ?? const <Post>[];
|
||||
final feedPosts = postsList ??
|
||||
ref.watch(feedControllerProvider).value?.posts ??
|
||||
const <Post>[];
|
||||
final favoriteKeys = ref.watch(favoriteKeysProvider).value ?? <String>{};
|
||||
return AdaptiveScaffold(
|
||||
title: strings.post,
|
||||
@@ -698,17 +702,26 @@ class _MobilePostPagerState extends State<_MobilePostPager> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return PageView.builder(
|
||||
controller: _controller,
|
||||
physics: _mediaGestureLocked
|
||||
? const NeverScrollableScrollPhysics()
|
||||
: const PageScrollPhysics(),
|
||||
itemCount: widget.posts.length,
|
||||
onPageChanged: (index) {
|
||||
_prefetchAround(index);
|
||||
},
|
||||
itemBuilder: (context, index) {
|
||||
final initialPost = widget.posts[index];
|
||||
return ScrollConfiguration(
|
||||
behavior: ScrollConfiguration.of(context).copyWith(
|
||||
dragDevices: {
|
||||
PointerDeviceKind.touch,
|
||||
PointerDeviceKind.mouse,
|
||||
PointerDeviceKind.trackpad,
|
||||
PointerDeviceKind.stylus,
|
||||
},
|
||||
),
|
||||
child: PageView.builder(
|
||||
controller: _controller,
|
||||
physics: _mediaGestureLocked
|
||||
? const NeverScrollableScrollPhysics()
|
||||
: const PageScrollPhysics(),
|
||||
itemCount: widget.posts.length,
|
||||
onPageChanged: (index) {
|
||||
_prefetchAround(index);
|
||||
},
|
||||
itemBuilder: (context, index) {
|
||||
final initialPost = widget.posts[index];
|
||||
return Consumer(
|
||||
builder: (context, ref, _) {
|
||||
final args = PostDetailsArgs(
|
||||
@@ -735,8 +748,9 @@ class _MobilePostPagerState extends State<_MobilePostPager> {
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _setMediaGestureLocked(bool locked) {
|
||||
if (_mediaGestureLocked == locked) return;
|
||||
|
||||
@@ -219,9 +219,54 @@ class _PostMediaViewerState extends State<PostMediaViewer>
|
||||
);
|
||||
},
|
||||
);
|
||||
final child = _ZoomableImage(
|
||||
onGestureLockChanged: widget.onMediaGestureLockChanged,
|
||||
child: image,
|
||||
final child = Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
_ZoomableImage(
|
||||
onGestureLockChanged: widget.onMediaGestureLockChanged,
|
||||
child: image,
|
||||
),
|
||||
if (_imageUrls.length > 1)
|
||||
Positioned(
|
||||
bottom: 14,
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.black.withValues(alpha: 0.65),
|
||||
borderRadius: BorderRadius.circular(14),
|
||||
border: Border.all(color: Colors.white24, width: 0.8),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (_imageIndex > 0)
|
||||
GestureDetector(
|
||||
onTap: () => setState(() => _imageIndex--),
|
||||
child: const Icon(Icons.chevron_left_rounded,
|
||||
size: 20, color: Colors.white),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
child: Text(
|
||||
'${_imageIndex + 1} / ${_imageUrls.length}',
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (_imageIndex < _imageUrls.length - 1)
|
||||
GestureDetector(
|
||||
onTap: () => setState(() => _imageIndex++),
|
||||
child: const Icon(Icons.chevron_right_rounded,
|
||||
size: 20, color: Colors.white),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
return LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
|
||||
Reference in New Issue
Block a user