From 4aedde9b3fb3b35ae2301a1bf082ba5df2b52a53 Mon Sep 17 00:00:00 2001 From: RarDog Date: Sat, 5 Sep 2026 18:32:45 +0300 Subject: [PATCH] feat: desktop horizontal mouse-wheel scroll & fix PC video player blue screen (v3.6.3) --- lib/app/changelog.dart | 9 + .../artists/presentation/artists_screen.dart | 456 ++++++++++-------- .../widgets/post_media_viewer.dart | 4 +- .../presentation/settings_screen.dart | 211 ++++---- lib/main.dart | 2 + lib/shared/widgets/app_shell.dart | 2 +- pubspec.yaml | 2 +- 7 files changed, 409 insertions(+), 277 deletions(-) diff --git a/lib/app/changelog.dart b/lib/app/changelog.dart index 76dc6e6..605b0c4 100644 --- a/lib/app/changelog.dart +++ b/lib/app/changelog.dart @@ -1,4 +1,13 @@ const prismaChangelog = [ + PrismaChange( + version: '3.6.3', + title: 'Горизонтальный скролл колесиком мыши на ПК и исправление синего экрана в видеоплеере', + bullets: [ + 'Горизонтальная прокрутка колесиком мыши в настройках: верхняя панель категорий настроек теперь плавно прокручивается колесиком мыши строго при наведении курсора.', + 'Горизонтальная прокрутка колесиком мыши в авторах: полоса любимых авторов и лента их медиа теперь поддерживают быструю прокрутку колесиком мыши при наведении курсора.', + 'Устранение «синего экрана» в видеоплеере на ПК: исправлена нативная инициализация MediaKit перед запуском Flutter-движка и настроен оптимальный режим аппаратного ускорения для десктопных платформ.', + ], + ), PrismaChange( version: '3.6.2', title: 'Комплексная оптимизация памяти на телефоне и ПК, полное отключение зума колесиком', diff --git a/lib/features/artists/presentation/artists_screen.dart b/lib/features/artists/presentation/artists_screen.dart index 7e74686..d023e12 100644 --- a/lib/features/artists/presentation/artists_screen.dart +++ b/lib/features/artists/presentation/artists_screen.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'dart:convert'; import 'dart:ui'; import 'package:cached_network_image/cached_network_image.dart'; +import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; @@ -1328,7 +1329,7 @@ class _FavoriteArtistsModalState extends State<_FavoriteArtistsModal> { } } -class _FavoriteArtistsSection extends ConsumerWidget { +class _FavoriteArtistsSection extends StatefulWidget { const _FavoriteArtistsSection({ required this.favorites, required this.selectedKey, @@ -1344,8 +1345,23 @@ class _FavoriteArtistsSection extends ConsumerWidget { final ValueChanged onRemoveFavorite; @override - Widget build(BuildContext context, WidgetRef ref) { - if (favorites.isEmpty) { + State<_FavoriteArtistsSection> createState() => + _FavoriteArtistsSectionState(); +} + +class _FavoriteArtistsSectionState extends State<_FavoriteArtistsSection> { + final ScrollController _scrollController = ScrollController(); + bool _isHovered = false; + + @override + void dispose() { + _scrollController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + if (widget.favorites.isEmpty) { return Padding( padding: const EdgeInsets.fromLTRB(16, 4, 16, 8), child: _ArtistsLiquidCard( @@ -1368,9 +1384,9 @@ class _FavoriteArtistsSection extends ConsumerWidget { ); } - final selected = favorites.firstWhere( - (f) => f.key == selectedKey, - orElse: () => favorites.first, + final selected = widget.favorites.firstWhere( + (f) => f.key == widget.selectedKey, + orElse: () => widget.favorites.first, ); return Padding( @@ -1385,14 +1401,14 @@ class _FavoriteArtistsSection extends ConsumerWidget { const Icon(Icons.star_rounded, color: Colors.amber, size: 20), const SizedBox(width: 6), Text( - 'Любимые авторы (${favorites.length})', + 'Любимые авторы (${widget.favorites.length})', style: Theme.of(context).textTheme.titleSmall?.copyWith( fontWeight: FontWeight.bold, ), ), const Spacer(), TextButton( - onPressed: () => onOpenArtist(selected), + onPressed: () => widget.onOpenArtist(selected), style: TextButton.styleFrom( visualDensity: VisualDensity.compact, padding: const EdgeInsets.symmetric(horizontal: 8), @@ -1409,113 +1425,136 @@ class _FavoriteArtistsSection extends ConsumerWidget { ], ), const SizedBox(height: 8), - SizedBox( - height: 88, - child: ListView.separated( - padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 4), - scrollDirection: Axis.horizontal, - itemCount: favorites.length, - separatorBuilder: (_, __) => const SizedBox(width: 10), - itemBuilder: (context, index) { - final fav = favorites[index]; - final isSelected = fav.key == selected.key; - final sColor = _serviceColor(fav.service); - - return InkWell( - borderRadius: BorderRadius.circular(16), - onTap: () => onSelect(fav), - child: AnimatedContainer( - duration: const Duration(milliseconds: 200), - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 6), - decoration: BoxDecoration( - color: isSelected - ? Theme.of(context) - .colorScheme - .primaryContainer - .withValues(alpha: 0.45) - : Colors.transparent, - borderRadius: BorderRadius.circular(16), - border: Border.all( - color: isSelected - ? Theme.of(context).colorScheme.primary - : Colors.transparent, - width: 1.5, - ), - boxShadow: isSelected - ? [ - BoxShadow( - color: Theme.of(context) - .colorScheme - .primary - .withValues(alpha: 0.25), - blurRadius: 8, - ), - ] - : null, - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Container( - width: 44, - height: 44, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(14), - border: Border.all( - color: isSelected - ? Theme.of(context).colorScheme.primary - : sColor.withValues(alpha: 0.4), - width: 1.2, - ), - ), - child: ClipRRect( - borderRadius: BorderRadius.circular(13), - child: fav.avatarUrl != null && - fav.avatarUrl!.isNotEmpty - ? CachedNetworkImage( - imageUrl: fav.avatarUrl!, - memCacheWidth: 120, - memCacheHeight: 120, - fit: BoxFit.cover, - placeholder: (_, __) => const Icon( - Icons.person_rounded, - size: 20), - errorWidget: (_, __, ___) => const Icon( - Icons.person_rounded, - size: 20), - ) - : Center( - child: Text( - fav.name.isNotEmpty - ? fav.name[0].toUpperCase() - : '?', - style: const TextStyle( - fontWeight: FontWeight.bold), - ), - ), - ), - ), - const SizedBox(height: 4), - SizedBox( - width: 68, - child: Text( - fav.name, - maxLines: 1, - overflow: TextOverflow.ellipsis, - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 11, - fontWeight: isSelected - ? FontWeight.bold - : FontWeight.normal, - ), - ), - ), - ], - ), - ), + MouseRegion( + onEnter: (_) => _isHovered = true, + onExit: (_) => _isHovered = false, + child: Listener( + onPointerSignal: (event) { + if (!_isHovered || + event is! PointerScrollEvent || + !_scrollController.hasClients) { + return; + } + final delta = event.scrollDelta.dy != 0 + ? event.scrollDelta.dy + : event.scrollDelta.dx; + if (delta == 0) return; + final target = (_scrollController.offset + delta * 1.5).clamp( + 0.0, + _scrollController.position.maxScrollExtent, ); + _scrollController.jumpTo(target); }, + child: SizedBox( + height: 88, + child: ListView.separated( + controller: _scrollController, + padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 4), + scrollDirection: Axis.horizontal, + itemCount: widget.favorites.length, + separatorBuilder: (_, __) => const SizedBox(width: 10), + itemBuilder: (context, index) { + final fav = widget.favorites[index]; + final isSelected = fav.key == selected.key; + final sColor = _serviceColor(fav.service); + + return InkWell( + borderRadius: BorderRadius.circular(16), + onTap: () => widget.onSelect(fav), + child: AnimatedContainer( + duration: const Duration(milliseconds: 200), + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 6), + decoration: BoxDecoration( + color: isSelected + ? Theme.of(context) + .colorScheme + .primaryContainer + .withValues(alpha: 0.45) + : Colors.transparent, + borderRadius: BorderRadius.circular(16), + border: Border.all( + color: isSelected + ? Theme.of(context).colorScheme.primary + : Colors.transparent, + width: 1.5, + ), + boxShadow: isSelected + ? [ + BoxShadow( + color: Theme.of(context) + .colorScheme + .primary + .withValues(alpha: 0.25), + blurRadius: 8, + ), + ] + : null, + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + width: 44, + height: 44, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(14), + border: Border.all( + color: isSelected + ? Theme.of(context).colorScheme.primary + : sColor.withValues(alpha: 0.4), + width: 1.2, + ), + ), + child: ClipRRect( + borderRadius: BorderRadius.circular(13), + child: fav.avatarUrl != null && + fav.avatarUrl!.isNotEmpty + ? CachedNetworkImage( + imageUrl: fav.avatarUrl!, + memCacheWidth: 120, + memCacheHeight: 120, + fit: BoxFit.cover, + placeholder: (_, __) => const Icon( + Icons.person_rounded, + size: 20), + errorWidget: (_, __, ___) => const Icon( + Icons.person_rounded, + size: 20), + ) + : Center( + child: Text( + fav.name.isNotEmpty + ? fav.name[0].toUpperCase() + : '?', + style: const TextStyle( + fontWeight: FontWeight.bold), + ), + ), + ), + ), + const SizedBox(height: 4), + SizedBox( + width: 68, + child: Text( + fav.name, + maxLines: 1, + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 11, + fontWeight: isSelected + ? FontWeight.bold + : FontWeight.normal, + ), + ), + ), + ], + ), + ), + ); + }, + ), + ), ), ), const SizedBox(height: 6), @@ -1527,18 +1566,34 @@ class _FavoriteArtistsSection extends ConsumerWidget { } } -class _FavoriteArtistMediaStrip extends ConsumerWidget { +class _FavoriteArtistMediaStrip extends ConsumerStatefulWidget { const _FavoriteArtistMediaStrip({required this.artist}); final FavoriteArtistItem artist; @override - Widget build(BuildContext context, WidgetRef ref) { + ConsumerState<_FavoriteArtistMediaStrip> createState() => + _FavoriteArtistMediaStripState(); +} + +class _FavoriteArtistMediaStripState + extends ConsumerState<_FavoriteArtistMediaStrip> { + final ScrollController _scrollController = ScrollController(); + bool _isHovered = false; + + @override + void dispose() { + _scrollController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { final query = ArtistWorkQuery( - providerId: artist.providerId, - service: artist.service, - artistId: artist.id, - artistName: artist.name, + providerId: widget.artist.providerId, + service: widget.artist.service, + artistId: widget.artist.id, + artistName: widget.artist.name, ); final asyncPosts = ref.watch(artistPostsProvider(query)); @@ -1566,78 +1621,101 @@ class _FavoriteArtistMediaStrip extends ConsumerWidget { ), ); } - return SizedBox( - height: 96, - child: ListView.separated( - scrollDirection: Axis.horizontal, - itemCount: posts.length.clamp(0, 15), - separatorBuilder: (_, __) => const SizedBox(width: 8), - itemBuilder: (context, index) { - final post = posts[index]; - final isVideo = MediaUrlSelector.isVideo(post); - return InkWell( - borderRadius: BorderRadius.circular(14), - onTap: () => AppNavigator.openPost( - context, - post: post, - postsList: posts, - ), - child: Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(14), - border: Border.all( - color: Colors.white.withValues(alpha: 0.15), - width: 1.0, - ), - ), - child: ClipRRect( - borderRadius: BorderRadius.circular(13), - child: Stack( - children: [ - SizedBox( - width: 96, - height: 96, - child: CachedNetworkImage( - imageUrl: post.previewUrl.isNotEmpty - ? post.previewUrl - : post.sampleUrl, - memCacheWidth: 200, - memCacheHeight: 200, - fit: BoxFit.cover, - placeholder: (_, __) => ColoredBox( - color: Theme.of(context) - .colorScheme - .surfaceContainerHighest, - ), - errorWidget: (_, __, ___) => ColoredBox( - color: Theme.of(context) - .colorScheme - .surfaceContainerHighest, - child: const Icon(Icons.broken_image_rounded, - size: 24), - ), - ), - ), - if (isVideo) - Positioned( - bottom: 6, - right: 6, - child: Container( - padding: const EdgeInsets.all(4), - decoration: BoxDecoration( - color: Colors.black.withValues(alpha: 0.7), - shape: BoxShape.circle, - ), - child: const Icon(Icons.play_arrow_rounded, - color: Colors.white, size: 14), - ), - ), - ], - ), - ), - ), + return MouseRegion( + onEnter: (_) => _isHovered = true, + onExit: (_) => _isHovered = false, + child: Listener( + onPointerSignal: (event) { + if (!_isHovered || + event is! PointerScrollEvent || + !_scrollController.hasClients) { + return; + } + final delta = event.scrollDelta.dy != 0 + ? event.scrollDelta.dy + : event.scrollDelta.dx; + if (delta == 0) return; + final target = (_scrollController.offset + delta * 1.5).clamp( + 0.0, + _scrollController.position.maxScrollExtent, ); + _scrollController.jumpTo(target); }, + child: SizedBox( + height: 96, + child: ListView.separated( + controller: _scrollController, + scrollDirection: Axis.horizontal, + itemCount: posts.length.clamp(0, 15), + separatorBuilder: (_, __) => const SizedBox(width: 8), + itemBuilder: (context, index) { + final post = posts[index]; + final isVideo = MediaUrlSelector.isVideo(post); + return InkWell( + borderRadius: BorderRadius.circular(14), + onTap: () => AppNavigator.openPost( + context, + post: post, + postsList: posts, + ), + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(14), + border: Border.all( + color: Colors.white.withValues(alpha: 0.15), + width: 1.0, + ), + ), + child: ClipRRect( + borderRadius: BorderRadius.circular(13), + child: Stack( + children: [ + SizedBox( + width: 96, + height: 96, + child: CachedNetworkImage( + imageUrl: post.previewUrl.isNotEmpty + ? post.previewUrl + : post.sampleUrl, + memCacheWidth: 200, + memCacheHeight: 200, + fit: BoxFit.cover, + placeholder: (_, __) => ColoredBox( + color: Theme.of(context) + .colorScheme + .surfaceContainerHighest, + ), + errorWidget: (_, __, ___) => ColoredBox( + color: Theme.of(context) + .colorScheme + .surfaceContainerHighest, + child: const Icon(Icons.broken_image_rounded, + size: 24), + ), + ), + ), + if (isVideo) + Positioned( + bottom: 6, + right: 6, + child: Container( + padding: const EdgeInsets.all(4), + decoration: BoxDecoration( + color: Colors.black.withValues(alpha: 0.7), + shape: BoxShape.circle, + ), + child: const Icon(Icons.play_arrow_rounded, + color: Colors.white, size: 14), + ), + ), + ], + ), + ), + ), + ); + }, + ), + ), ), ); }, diff --git a/lib/features/post/presentation/widgets/post_media_viewer.dart b/lib/features/post/presentation/widgets/post_media_viewer.dart index 43dd533..f337791 100644 --- a/lib/features/post/presentation/widgets/post_media_viewer.dart +++ b/lib/features/post/presentation/widgets/post_media_viewer.dart @@ -448,7 +448,9 @@ class _PostMediaViewerState extends State _player!, configuration: VideoControllerConfiguration( enableHardwareAcceleration: !_softwareDecodingFallback, - hwdec: _softwareDecodingFallback ? 'no' : 'auto-safe', + hwdec: _softwareDecodingFallback + ? 'no' + : (Platform.isAndroid ? 'auto-safe' : 'auto'), ), ); _applyVolume(); diff --git a/lib/features/settings/presentation/settings_screen.dart b/lib/features/settings/presentation/settings_screen.dart index f8429d4..f4d3383 100644 --- a/lib/features/settings/presentation/settings_screen.dart +++ b/lib/features/settings/presentation/settings_screen.dart @@ -1,6 +1,7 @@ import 'dart:io'; import 'dart:ui'; +import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart' hide appBuildNumber; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -1439,7 +1440,7 @@ class _SettingsIconBadge extends StatelessWidget { } } -class _CategoryQuickNav extends StatelessWidget { +class _CategoryQuickNav extends StatefulWidget { const _CategoryQuickNav({ required this.categories, required this.onSelect, @@ -1449,103 +1450,143 @@ class _CategoryQuickNav extends StatelessWidget { categories; final ValueChanged onSelect; + @override + State<_CategoryQuickNav> createState() => _CategoryQuickNavState(); +} + +class _CategoryQuickNavState extends State<_CategoryQuickNav> { + final ScrollController _scrollController = ScrollController(); + bool _isHovered = false; + + @override + void dispose() { + _scrollController.dispose(); + super.dispose(); + } + @override Widget build(BuildContext context) { final theme = Theme.of(context); final isDark = theme.brightness == Brightness.dark; - return SizedBox( - height: 44, - child: ListView.separated( - padding: const EdgeInsets.symmetric(horizontal: 16), - scrollDirection: Axis.horizontal, - itemCount: categories.length, - separatorBuilder: (_, __) => const SizedBox(width: 8), - itemBuilder: (context, index) { - final cat = categories[index]; - return Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(22), - boxShadow: [ - BoxShadow( - color: isDark - ? Colors.black.withValues(alpha: 0.25) - : cat.color.withValues(alpha: 0.12), - blurRadius: 8, - offset: const Offset(0, 2.5), + return MouseRegion( + onEnter: (_) => _isHovered = true, + onExit: (_) => _isHovered = false, + child: Listener( + onPointerSignal: (event) { + if (!_isHovered || + event is! PointerScrollEvent || + !_scrollController.hasClients) { + return; + } + final delta = event.scrollDelta.dy != 0 + ? event.scrollDelta.dy + : event.scrollDelta.dx; + if (delta == 0) return; + final target = (_scrollController.offset + delta * 1.5).clamp( + 0.0, + _scrollController.position.maxScrollExtent, + ); + _scrollController.jumpTo(target); + }, + child: SizedBox( + height: 44, + child: ListView.separated( + controller: _scrollController, + padding: const EdgeInsets.symmetric(horizontal: 16), + scrollDirection: Axis.horizontal, + itemCount: widget.categories.length, + separatorBuilder: (_, __) => const SizedBox(width: 8), + itemBuilder: (context, index) { + final cat = widget.categories[index]; + return Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(22), + boxShadow: [ + BoxShadow( + color: isDark + ? Colors.black.withValues(alpha: 0.25) + : cat.color.withValues(alpha: 0.12), + blurRadius: 8, + offset: const Offset(0, 2.5), + ), + ], ), - ], - ), - child: ClipRRect( - borderRadius: BorderRadius.circular(22), - child: BackdropFilter( - filter: ImageFilter.blur(sigmaX: 16, sigmaY: 16), - child: Material( - color: isDark - ? theme.colorScheme.surfaceContainerHigh.withValues(alpha: 0.60) - : Colors.white.withValues(alpha: 0.82), - child: InkWell( - borderRadius: BorderRadius.circular(22), - onTap: () { - HapticFeedback.selectionClick(); - onSelect(cat.key); - }, - child: Container( - padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 7), - decoration: BoxDecoration( + child: ClipRRect( + borderRadius: BorderRadius.circular(22), + child: BackdropFilter( + filter: ImageFilter.blur(sigmaX: 16, sigmaY: 16), + child: Material( + color: isDark + ? theme.colorScheme.surfaceContainerHigh + .withValues(alpha: 0.60) + : Colors.white.withValues(alpha: 0.82), + child: InkWell( borderRadius: BorderRadius.circular(22), - border: Border.all( - color: isDark - ? Colors.white.withValues(alpha: 0.18) - : Colors.white.withValues(alpha: 0.85), - width: 1.1, - ), - ), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Container( - width: 24, - height: 24, - decoration: BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topLeft, - end: Alignment.bottomRight, - colors: [ - cat.color, - cat.color.withValues(alpha: 0.82), - ], - ), - borderRadius: BorderRadius.circular(7), - boxShadow: [ - BoxShadow( - color: cat.color.withValues(alpha: 0.35), - blurRadius: 5, - offset: const Offset(0, 1.5), + onTap: () { + HapticFeedback.selectionClick(); + widget.onSelect(cat.key); + }, + child: Container( + padding: const EdgeInsets.symmetric( + horizontal: 12, vertical: 7), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(22), + border: Border.all( + color: isDark + ? Colors.white.withValues(alpha: 0.18) + : Colors.white.withValues(alpha: 0.85), + width: 1.1, + ), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + width: 24, + height: 24, + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: [ + cat.color, + cat.color.withValues(alpha: 0.82), + ], + ), + borderRadius: BorderRadius.circular(7), + boxShadow: [ + BoxShadow( + color: cat.color.withValues(alpha: 0.35), + blurRadius: 5, + offset: const Offset(0, 1.5), + ), + ], ), - ], - ), - child: Center( - child: Icon(cat.icon, size: 14, color: Colors.white), - ), + child: Center( + child: Icon(cat.icon, + size: 14, color: Colors.white), + ), + ), + const SizedBox(width: 8), + Text( + cat.label, + style: theme.textTheme.labelLarge?.copyWith( + fontWeight: FontWeight.w600, + letterSpacing: -0.2, + ), + ), + ], ), - const SizedBox(width: 8), - Text( - cat.label, - style: theme.textTheme.labelLarge?.copyWith( - fontWeight: FontWeight.w600, - letterSpacing: -0.2, - ), - ), - ], + ), ), ), ), ), - ), - ), - ); - }, + ); + }, + ), + ), ), ); } diff --git a/lib/main.dart b/lib/main.dart index 4f1f8f7..396b019 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,10 +1,12 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:media_kit/media_kit.dart'; import 'app/app.dart'; void main() { WidgetsFlutterBinding.ensureInitialized(); + MediaKit.ensureInitialized(); // Optimize image cache to prevent memory bloat and OOM crashes PaintingBinding.instance.imageCache.maximumSizeBytes = 180 * 1024 * 1024; // 180 MB PaintingBinding.instance.imageCache.maximumSize = 120; // 120 images diff --git a/lib/shared/widgets/app_shell.dart b/lib/shared/widgets/app_shell.dart index 1e6763c..1567d35 100644 --- a/lib/shared/widgets/app_shell.dart +++ b/lib/shared/widgets/app_shell.dart @@ -580,7 +580,7 @@ class _DesktopShellState extends State<_DesktopShell> ), ), child: Text( - 'v3.6.2', + 'v3.6.3', style: TextStyle( fontSize: 10, fontWeight: diff --git a/pubspec.yaml b/pubspec.yaml index 7c0f693..f1d9676 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: gel_rule_app description: Local backend/core layer for a Flutter booru browser app. publish_to: "none" -version: 3.6.2+84 +version: 3.6.3+85 environment: sdk: ">=3.3.0 <4.0.0"