Release RuleGel 1.0.1 with Realbooru

This commit is contained in:
2026-05-25 14:33:59 +03:00
parent 16e86fb9d5
commit ea39cf8567
28 changed files with 1217 additions and 263 deletions
@@ -9,6 +9,7 @@ import 'package:media_kit_video/media_kit_video.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:webview_windows/webview_windows.dart';
import '../../../../app/motion.dart';
import '../../../../backend/backend.dart';
final Map<String, VideoPlaybackSnapshot> _playbackMemory =
@@ -1010,10 +1011,10 @@ class _VideoSurface extends StatelessWidget {
final playing = snapshot.data ?? false;
return AnimatedScale(
scale: controlsVisible || !playing ? 1 : 0.85,
duration: const Duration(milliseconds: 160),
duration: AppMotion.duration(context, 160),
child: AnimatedOpacity(
opacity: controlsVisible || !playing ? 1 : 0,
duration: const Duration(milliseconds: 160),
duration: AppMotion.duration(context, 160),
child: Center(
child: DecoratedBox(
decoration: BoxDecoration(
@@ -1051,7 +1052,7 @@ class _VideoSurface extends StatelessWidget {
ignoring: !controlsVisible || errorMessage != null,
child: AnimatedOpacity(
opacity: controlsVisible || errorMessage != null ? 1 : 0,
duration: const Duration(milliseconds: 180),
duration: AppMotion.duration(context, 180),
child: _VideoControls(
player: player,
muted: muted,
@@ -1176,7 +1177,7 @@ class _RoundControlButton extends StatelessWidget {
onTap: onPressed,
radius: emphasized ? 23 : 21,
child: AnimatedContainer(
duration: const Duration(milliseconds: 140),
duration: AppMotion.duration(context, 140),
width: emphasized ? 38 : 34,
height: emphasized ? 38 : 34,
decoration: BoxDecoration(
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:flutter/gestures.dart';
import 'package:go_router/go_router.dart';
import '../../../../backend/backend.dart';
@@ -23,17 +24,9 @@ class PostTagsPanel extends StatelessWidget {
style: Theme.of(context).textTheme.labelLarge,
),
),
Wrap(
spacing: 8,
runSpacing: 8,
children: [
for (final tag in entry.value.take(80))
TagChip(
tag: tag,
onTap: () =>
context.go('/?q=${Uri.encodeQueryComponent(tag)}'),
),
],
_HorizontalTagRow(
tags: entry.value.take(120).toList(),
onTap: (tag) => context.go('/?q=${Uri.encodeQueryComponent(tag)}'),
),
],
],
@@ -74,3 +67,53 @@ class PostTagsPanel extends StatelessWidget {
};
}
}
class _HorizontalTagRow extends StatefulWidget {
const _HorizontalTagRow({
required this.tags,
required this.onTap,
});
final List<String> tags;
final ValueChanged<String> onTap;
@override
State<_HorizontalTagRow> createState() => _HorizontalTagRowState();
}
class _HorizontalTagRowState extends State<_HorizontalTagRow> {
final _controller = ScrollController();
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return SizedBox(
height: 36,
child: Listener(
onPointerSignal: (event) {
if (event is! PointerScrollEvent || !_controller.hasClients) return;
final target = (_controller.offset + event.scrollDelta.dy)
.clamp(0.0, _controller.position.maxScrollExtent)
.toDouble();
_controller.jumpTo(target);
},
child: ListView.separated(
controller: _controller,
scrollDirection: Axis.horizontal,
primary: false,
itemCount: widget.tags.length,
separatorBuilder: (_, __) => const SizedBox(width: 8),
itemBuilder: (context, index) => TagChip(
tag: widget.tags[index],
onTap: () => widget.onTap(widget.tags[index]),
),
),
),
);
}
}