Improve UI

This commit is contained in:
2025-01-15 18:24:38 +08:00
parent d874920c88
commit 399b9abaee
9 changed files with 358 additions and 227 deletions

View File

@@ -1,5 +1,27 @@
part of 'components.dart'; part of 'components.dart';
ImageProvider? _findImageProvider(Comic comic) {
ImageProvider image;
if (comic is LocalComic) {
image = LocalComicImageProvider(comic);
} else if (comic is History) {
image = HistoryImageProvider(comic);
} else if (comic.sourceKey == 'local') {
var localComic = LocalManager().find(comic.id, ComicType.local);
if (localComic == null) {
return null;
}
image = FileImage(localComic.coverFile);
} else {
image = CachedImageProvider(
comic.cover,
sourceKey: comic.sourceKey,
cid: comic.id,
);
}
return image;
}
class ComicTile extends StatelessWidget { class ComicTile extends StatelessWidget {
const ComicTile( const ComicTile(
{super.key, {super.key,
@@ -27,8 +49,14 @@ class ComicTile extends StatelessWidget {
onTap!(); onTap!();
return; return;
} }
App.mainNavigatorKey?.currentContext App.mainNavigatorKey?.currentContext?.to(
?.to(() => ComicPage(id: comic.id, sourceKey: comic.sourceKey)); () => ComicPage(
id: comic.id,
sourceKey: comic.sourceKey,
cover: comic.cover,
title: comic.title,
),
);
} }
void _onLongPressed(context) { void _onLongPressed(context) {
@@ -61,8 +89,14 @@ class ComicTile extends StatelessWidget {
icon: Icons.chrome_reader_mode_outlined, icon: Icons.chrome_reader_mode_outlined,
text: 'Details'.tl, text: 'Details'.tl,
onClick: () { onClick: () {
App.mainNavigatorKey?.currentContext App.mainNavigatorKey?.currentContext?.to(
?.to(() => ComicPage(id: comic.id, sourceKey: comic.sourceKey)); () => ComicPage(
id: comic.id,
sourceKey: comic.sourceKey,
cover: comic.cover,
title: comic.title,
),
);
}, },
), ),
MenuEntry( MenuEntry(
@@ -161,23 +195,9 @@ class ComicTile extends StatelessWidget {
} }
Widget buildImage(BuildContext context) { Widget buildImage(BuildContext context) {
ImageProvider image; var image = _findImageProvider(comic);
if (comic is LocalComic) { if (image == null) {
image = LocalComicImageProvider(comic as LocalComic); return const SizedBox();
} else if (comic is History) {
image = HistoryImageProvider(comic as History);
} else if (comic.sourceKey == 'local') {
var localComic = LocalManager().find(comic.id, ComicType.local);
if (localComic == null) {
return const SizedBox();
}
image = FileImage(localComic.coverFile);
} else {
image = CachedImageProvider(
comic.cover,
sourceKey: comic.sourceKey,
cid: comic.id,
);
} }
return AnimatedImage( return AnimatedImage(
image: image, image: image,
@@ -199,15 +219,25 @@ class ComicTile extends StatelessWidget {
padding: const EdgeInsets.fromLTRB(16, 8, 24, 8), padding: const EdgeInsets.fromLTRB(16, 8, 24, 8),
child: Row( child: Row(
children: [ children: [
Container( Hero(
width: height * 0.68, tag: "cover${comic.id}${comic.sourceKey}",
height: double.infinity, child: Container(
decoration: BoxDecoration( width: height * 0.68,
color: Theme.of(context).colorScheme.secondaryContainer, height: double.infinity,
borderRadius: BorderRadius.circular(8), decoration: BoxDecoration(
color: Theme.of(context).colorScheme.secondaryContainer,
borderRadius: BorderRadius.circular(8),
boxShadow: [
BoxShadow(
color: context.colorScheme.outlineVariant,
blurRadius: 1,
offset: const Offset(0, 1),
),
],
),
clipBehavior: Clip.antiAlias,
child: buildImage(context),
), ),
clipBehavior: Clip.antiAlias,
child: buildImage(context),
), ),
SizedBox.fromSize( SizedBox.fromSize(
size: const Size(16, 5), size: const Size(16, 5),
@@ -248,20 +278,23 @@ class ComicTile extends StatelessWidget {
child: Stack( child: Stack(
children: [ children: [
Positioned.fill( Positioned.fill(
child: Container( child: Hero(
decoration: BoxDecoration( tag: "cover${comic.id}${comic.sourceKey}",
color: context.colorScheme.secondaryContainer, child: Container(
borderRadius: BorderRadius.circular(8), decoration: BoxDecoration(
boxShadow: [ color: context.colorScheme.secondaryContainer,
BoxShadow( borderRadius: BorderRadius.circular(8),
color: Colors.black.toOpacity(0.2), boxShadow: [
blurRadius: 2, BoxShadow(
offset: const Offset(0, 2), color: Colors.black.toOpacity(0.2),
), blurRadius: 2,
], offset: const Offset(0, 2),
),
],
),
clipBehavior: Clip.antiAlias,
child: buildImage(context),
), ),
clipBehavior: Clip.antiAlias,
child: buildImage(context),
), ),
), ),
Align( Align(
@@ -1400,7 +1433,7 @@ class _RatingWidgetState extends State<RatingWidget> {
} }
if (full < widget.count) { if (full < widget.count) {
children.add(ClipRect( children.add(ClipRect(
clipper: SMClipper(rating: star() * widget.size), clipper: _SMClipper(rating: star() * widget.size),
child: Icon( child: Icon(
Icons.star, Icons.star,
size: widget.size, size: widget.size,
@@ -1449,10 +1482,10 @@ class _RatingWidgetState extends State<RatingWidget> {
} }
} }
class SMClipper extends CustomClipper<Rect> { class _SMClipper extends CustomClipper<Rect> {
final double rating; final double rating;
SMClipper({required this.rating}); _SMClipper({required this.rating});
@override @override
Rect getClip(Size size) { Rect getClip(Size size) {
@@ -1460,7 +1493,52 @@ class SMClipper extends CustomClipper<Rect> {
} }
@override @override
bool shouldReclip(SMClipper oldClipper) { bool shouldReclip(_SMClipper oldClipper) {
return rating != oldClipper.rating; return rating != oldClipper.rating;
} }
} }
class SimpleComicTile extends StatelessWidget {
const SimpleComicTile({super.key, required this.comic, this.onTap});
final Comic comic;
final void Function()? onTap;
@override
Widget build(BuildContext context) {
var image = _findImageProvider(comic);
var child = image == null
? const SizedBox()
: AnimatedImage(
image: image,
width: double.infinity,
height: double.infinity,
fit: BoxFit.cover,
filterQuality: FilterQuality.medium,
);
return AnimatedTapRegion(
borderRadius: 8,
onTap: onTap ?? () {
context.to(
() => ComicPage(
id: comic.id,
sourceKey: comic.sourceKey,
),
);
},
child: Container(
width: 92,
height: 114,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
color: Theme.of(context).colorScheme.secondaryContainer,
),
clipBehavior: Clip.antiAlias,
child: child,
),
);
}
}

View File

@@ -41,39 +41,44 @@ class AnimatedTapRegion extends StatefulWidget {
} }
class _AnimatedTapRegionState extends State<AnimatedTapRegion> { class _AnimatedTapRegionState extends State<AnimatedTapRegion> {
bool isScaled = false;
bool isHovered = false; bool isHovered = false;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return MouseRegion( return MouseRegion(
onEnter: (_) { onEnter: (_) {
isHovered = true; setState(() {
if (!isScaled) { isHovered = true;
Future.delayed(const Duration(milliseconds: 100), () { });
if (isHovered) {
setState(() => isScaled = true);
}
});
}
}, },
onExit: (_) { onExit: (_) {
isHovered = false; setState(() {
if(isScaled) { isHovered = false;
setState(() => isScaled = false); });
}
}, },
child: GestureDetector( child: GestureDetector(
onTap: widget.onTap, onTap: widget.onTap,
child: ClipRRect( child: AnimatedContainer(
borderRadius: BorderRadius.circular(widget.borderRadius), duration: _fastAnimationDuration,
clipBehavior: Clip.antiAlias, decoration: BoxDecoration(
child: AnimatedScale( borderRadius: BorderRadius.circular(widget.borderRadius),
duration: _fastAnimationDuration, boxShadow: isHovered
scale: isScaled ? 1.1 : 1, ? [
child: widget.child, BoxShadow(
color: context.colorScheme.outline,
blurRadius: 2,
offset: const Offset(0, 2),
),
]
: [
BoxShadow(
color: context.colorScheme.outlineVariant,
blurRadius: 1,
offset: const Offset(0, 1),
),
],
), ),
child: widget.child,
), ),
), ),
); );

View File

@@ -200,15 +200,17 @@ class NaviPaneState extends State<NaviPane>
} }
Widget buildMainView() { Widget buildMainView() {
return Navigator( return HeroControllerScope(
observers: [widget.observer], controller: MaterialApp.createMaterialHeroController(),
key: widget.navigatorKey, child: Navigator(
onGenerateRoute: (settings) => AppPageRoute( observers: [widget.observer],
preventRebuild: false, key: widget.navigatorKey,
isRootRoute: true, onGenerateRoute: (settings) => AppPageRoute(
builder: (context) { preventRebuild: false,
return _NaviMainView(state: this); builder: (context) {
}, return _NaviMainView(state: this);
},
),
), ),
); );
} }
@@ -362,16 +364,14 @@ class _SideNaviWidget extends StatelessWidget {
color: enabled ? colorScheme.primaryContainer : null, color: enabled ? colorScheme.primaryContainer : null,
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
), ),
child: showTitle ? Row( child: showTitle
children: [ ? Row(
icon, children: [icon, const SizedBox(width: 12), Text(entry.label)],
const SizedBox(width: 12), )
Text(entry.label) : Align(
], alignment: Alignment.centerLeft,
) : Align( child: icon,
alignment: Alignment.centerLeft, ),
child: icon,
),
), ),
).paddingVertical(4); ).paddingVertical(4);
} }
@@ -395,16 +395,14 @@ class _PaneActionWidget extends StatelessWidget {
duration: const Duration(milliseconds: 180), duration: const Duration(milliseconds: 180),
padding: const EdgeInsets.symmetric(horizontal: 12), padding: const EdgeInsets.symmetric(horizontal: 12),
height: 38, height: 38,
child: showTitle ? Row( child: showTitle
children: [ ? Row(
icon, children: [icon, const SizedBox(width: 12), Text(entry.label)],
const SizedBox(width: 12), )
Text(entry.label) : Align(
], alignment: Alignment.centerLeft,
) : Align( child: icon,
alignment: Alignment.centerLeft, ),
child: icon,
),
), ),
).paddingVertical(4); ).paddingVertical(4);
} }

View File

@@ -19,7 +19,6 @@ class AppPageRoute<T> extends PageRoute<T> with _AppRouteTransitionMixin{
super.barrierDismissible = false, super.barrierDismissible = false,
this.enableIOSGesture = true, this.enableIOSGesture = true,
this.preventRebuild = true, this.preventRebuild = true,
this.isRootRoute = false,
}) { }) {
assert(opaque); assert(opaque);
} }
@@ -50,9 +49,6 @@ class AppPageRoute<T> extends PageRoute<T> with _AppRouteTransitionMixin{
@override @override
final bool preventRebuild; final bool preventRebuild;
@override
final bool isRootRoute;
} }
mixin _AppRouteTransitionMixin<T> on PageRoute<T> { mixin _AppRouteTransitionMixin<T> on PageRoute<T> {
@@ -79,8 +75,6 @@ mixin _AppRouteTransitionMixin<T> on PageRoute<T> {
bool get preventRebuild; bool get preventRebuild;
bool get isRootRoute;
Widget? _child; Widget? _child;
@override @override
@@ -121,22 +115,6 @@ mixin _AppRouteTransitionMixin<T> on PageRoute<T> {
@override @override
Widget buildTransitions(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) { Widget buildTransitions(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) {
if(isRootRoute) {
return FadeTransition(
opacity: Tween<double>(begin: 0, end: 1.0).animate(CurvedAnimation(
parent: animation,
curve: Curves.ease
)),
child: FadeTransition(
opacity: Tween<double>(begin: 1.0, end: 0).animate(CurvedAnimation(
parent: secondaryAnimation,
curve: Curves.ease
)),
child: child,
),
);
}
return SlidePageTransitionBuilder().buildTransitions( return SlidePageTransitionBuilder().buildTransitions(
this, this,
context, context,

View File

@@ -1,14 +1,11 @@
import "package:flutter/material.dart"; import "package:flutter/material.dart";
import "package:shimmer/shimmer.dart"; import 'package:shimmer_animation/shimmer_animation.dart';
import "package:venera/components/components.dart"; import "package:venera/components/components.dart";
import "package:venera/foundation/app.dart"; import "package:venera/foundation/app.dart";
import "package:venera/foundation/comic_source/comic_source.dart"; import "package:venera/foundation/comic_source/comic_source.dart";
import "package:venera/foundation/image_provider/cached_image.dart";
import "package:venera/pages/search_result_page.dart"; import "package:venera/pages/search_result_page.dart";
import "package:venera/utils/translations.dart"; import "package:venera/utils/translations.dart";
import "comic_page.dart";
class AggregatedSearchPage extends StatefulWidget { class AggregatedSearchPage extends StatefulWidget {
const AggregatedSearchPage({super.key, required this.keyword}); const AggregatedSearchPage({super.key, required this.keyword});
@@ -73,9 +70,9 @@ class _SliverSearchResultState extends State<_SliverSearchResult>
with AutomaticKeepAliveClientMixin { with AutomaticKeepAliveClientMixin {
bool isLoading = true; bool isLoading = true;
static const _kComicHeight = 144.0; static const _kComicHeight = 132.0;
get _comicWidth => _kComicHeight * 0.72; get _comicWidth => _kComicHeight * 0.7;
static const _kLeftPadding = 16.0; static const _kLeftPadding = 16.0;
@@ -123,28 +120,9 @@ class _SliverSearchResultState extends State<_SliverSearchResult>
} }
Widget buildComic(Comic c) { Widget buildComic(Comic c) {
return AnimatedTapRegion( return SimpleComicTile(comic: c)
borderRadius: 8, .paddingLeft(_kLeftPadding)
onTap: () { .paddingBottom(2);
context.to(() => ComicPage(
id: c.id,
sourceKey: c.sourceKey,
));
},
child: Container(
height: _kComicHeight,
width: _comicWidth,
decoration: BoxDecoration(
color: context.colorScheme.surfaceContainerLow,
),
child: AnimatedImage(
width: _comicWidth,
height: _kComicHeight,
fit: BoxFit.cover,
image: CachedImageProvider(c.cover),
),
),
).paddingLeft(_kLeftPadding);
} }
@override @override
@@ -169,10 +147,7 @@ class _SliverSearchResultState extends State<_SliverSearchResult>
SizedBox( SizedBox(
height: _kComicHeight, height: _kComicHeight,
width: double.infinity, width: double.infinity,
child: Shimmer.fromColors( child: Shimmer(
baseColor: context.colorScheme.surfaceContainerLow,
highlightColor: context.colorScheme.surfaceContainer,
direction: ShimmerDirection.ltr,
child: LayoutBuilder(builder: (context, constrains) { child: LayoutBuilder(builder: (context, constrains) {
var itemWidth = _comicWidth + _kLeftPadding; var itemWidth = _comicWidth + _kLeftPadding;
var items = (constrains.maxWidth / itemWidth).ceil(); var items = (constrains.maxWidth / itemWidth).ceil();

View File

@@ -1,5 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:shimmer_animation/shimmer_animation.dart';
import 'package:sliver_tools/sliver_tools.dart'; import 'package:sliver_tools/sliver_tools.dart';
import 'package:url_launcher/url_launcher_string.dart'; import 'package:url_launcher/url_launcher_string.dart';
import 'package:venera/components/components.dart'; import 'package:venera/components/components.dart';
@@ -26,12 +27,22 @@ import 'dart:math' as math;
import 'comments_page.dart'; import 'comments_page.dart';
class ComicPage extends StatefulWidget { class ComicPage extends StatefulWidget {
const ComicPage({super.key, required this.id, required this.sourceKey}); const ComicPage({
super.key,
required this.id,
required this.sourceKey,
this.cover,
this.title,
});
final String id; final String id;
final String sourceKey; final String sourceKey;
final String? cover;
final String? title;
@override @override
State<ComicPage> createState() => _ComicPageState(); State<ComicPage> createState() => _ComicPageState();
} }
@@ -55,13 +66,11 @@ class _ComicPageState extends LoadingState<ComicPage, ComicDetails>
@override @override
Widget buildLoading() { Widget buildLoading() {
return Column( return _ComicPageLoadingPlaceHolder(
children: [ cover: widget.cover,
const Appbar(title: Text("")), title: widget.title,
Expanded( sourceKey: widget.sourceKey,
child: super.buildLoading(), cid: widget.id,
),
],
); );
} }
@@ -201,21 +210,32 @@ class _ComicPageState extends LoadingState<ComicPage, ComicDetails>
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
const SizedBox(width: 16), const SizedBox(width: 16),
Container( Hero(
decoration: BoxDecoration( tag: "cover${comic.id}${comic.sourceKey}",
color: context.colorScheme.primaryContainer, child: Container(
borderRadius: BorderRadius.circular(8), decoration: BoxDecoration(
), color: context.colorScheme.primaryContainer,
height: 144, borderRadius: BorderRadius.circular(8),
width: 144 * 0.72, boxShadow: [
clipBehavior: Clip.antiAlias, BoxShadow(
child: AnimatedImage( color: context.colorScheme.outlineVariant,
image: CachedImageProvider( blurRadius: 1,
comic.cover, offset: const Offset(0, 1),
sourceKey: comic.sourceKey, ),
],
),
height: 144,
width: 144 * 0.72,
clipBehavior: Clip.antiAlias,
child: AnimatedImage(
image: CachedImageProvider(
widget.cover ?? comic.cover,
sourceKey: comic.sourceKey,
cid: comic.id,
),
width: double.infinity,
height: double.infinity,
), ),
width: double.infinity,
height: double.infinity,
), ),
), ),
const SizedBox(width: 16), const SizedBox(width: 16),
@@ -1946,3 +1966,124 @@ class _CommentWidget extends StatelessWidget {
); );
} }
} }
class _ComicPageLoadingPlaceHolder extends StatelessWidget {
const _ComicPageLoadingPlaceHolder({
this.cover,
this.title,
required this.sourceKey,
required this.cid,
});
final String? cover;
final String? title;
final String sourceKey;
final String cid;
@override
Widget build(BuildContext context) {
Widget buildContainer(double? width, double? height,
{Color? color, double? radius}) {
return Container(
height: height,
width: width,
decoration: BoxDecoration(
color: color ?? context.colorScheme.surfaceContainerLow,
borderRadius: BorderRadius.circular(radius ?? 4),
),
);
}
return Shimmer(
child: Column(
children: [
Appbar(title: Text(""), backgroundColor: context.colorScheme.surface),
const SizedBox(height: 8),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(width: 16),
buildImage(context),
const SizedBox(width: 16),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (title != null)
Text(title ?? "", style: ts.s18)
else
buildContainer(200, 25),
const SizedBox(height: 8),
buildContainer(80, 20),
],
),
),
],
),
const SizedBox(height: 8),
if (context.width < changePoint)
Row(
children: [
Expanded(
child: buildContainer(null, 36, radius: 18),
),
const SizedBox(width: 16),
Expanded(
child: buildContainer(null, 36, radius: 18),
),
],
).paddingHorizontal(16),
const Divider(),
const SizedBox(height: 8),
Center(
child: CircularProgressIndicator(
strokeWidth: 2.4,
).fixHeight(24).fixWidth(24),
)
],
),
);
}
Widget buildImage(BuildContext context) {
Widget child;
if (cover != null) {
child = AnimatedImage(
image: CachedImageProvider(
cover!,
sourceKey: sourceKey,
cid: cid,
),
width: double.infinity,
height: double.infinity,
fit: BoxFit.cover,
);
} else {
child = const SizedBox();
}
return Hero(
tag: "cover$cid$sourceKey",
child: Container(
decoration: BoxDecoration(
color: context.colorScheme.primaryContainer,
borderRadius: BorderRadius.circular(8),
boxShadow: [
BoxShadow(
color: context.colorScheme.outlineVariant,
blurRadius: 1,
offset: const Offset(0, 1),
),
],
),
height: 144,
width: 144 * 0.72,
clipBehavior: Clip.antiAlias,
child: child,
),
);
}
}

View File

@@ -6,8 +6,6 @@ import 'package:venera/foundation/comic_source/comic_source.dart';
import 'package:venera/foundation/consts.dart'; import 'package:venera/foundation/consts.dart';
import 'package:venera/foundation/favorites.dart'; import 'package:venera/foundation/favorites.dart';
import 'package:venera/foundation/history.dart'; import 'package:venera/foundation/history.dart';
import 'package:venera/foundation/image_provider/history_image_provider.dart';
import 'package:venera/foundation/image_provider/local_comic_image.dart';
import 'package:venera/foundation/local.dart'; import 'package:venera/foundation/local.dart';
import 'package:venera/foundation/log.dart'; import 'package:venera/foundation/log.dart';
import 'package:venera/pages/accounts_page.dart'; import 'package:venera/pages/accounts_page.dart';
@@ -267,8 +265,8 @@ class _HistoryState extends State<_History> {
scrollDirection: Axis.horizontal, scrollDirection: Axis.horizontal,
itemCount: history.length, itemCount: history.length,
itemBuilder: (context, index) { itemBuilder: (context, index) {
return AnimatedTapRegion( return SimpleComicTile(
borderRadius: 8, comic: history[index],
onTap: () { onTap: () {
context.to( context.to(
() => ComicPage( () => ComicPage(
@@ -277,25 +275,7 @@ class _HistoryState extends State<_History> {
), ),
); );
}, },
child: Container( ).paddingHorizontal(8).paddingVertical(2);
width: 92,
height: 114,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
color: Theme.of(context)
.colorScheme
.secondaryContainer,
),
clipBehavior: Clip.antiAlias,
child: AnimatedImage(
image: HistoryImageProvider(history[index]),
width: 96,
height: 128,
fit: BoxFit.cover,
filterQuality: FilterQuality.medium,
),
),
).paddingHorizontal(8);
}, },
), ),
).paddingHorizontal(8).paddingBottom(16), ).paddingHorizontal(8).paddingBottom(16),
@@ -388,32 +368,8 @@ class _LocalState extends State<_Local> {
scrollDirection: Axis.horizontal, scrollDirection: Axis.horizontal,
itemCount: local.length, itemCount: local.length,
itemBuilder: (context, index) { itemBuilder: (context, index) {
return AnimatedTapRegion( return SimpleComicTile(comic: local[index])
onTap: () { .paddingHorizontal(8);
local[index].read();
},
borderRadius: 8,
child: Container(
width: 92,
height: 114,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
color: Theme.of(context)
.colorScheme
.secondaryContainer,
),
clipBehavior: Clip.antiAlias,
child: AnimatedImage(
image: LocalComicImageProvider(
local[index],
),
width: 96,
height: 128,
fit: BoxFit.cover,
filterQuality: FilterQuality.medium,
),
),
).paddingHorizontal(8);
}, },
), ),
).paddingHorizontal(8), ).paddingHorizontal(8),

View File

@@ -867,14 +867,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "5.0.2" version: "5.0.2"
shimmer: shimmer_animation:
dependency: "direct main" dependency: "direct main"
description: description:
name: shimmer name: shimmer_animation
sha256: "5f88c883a22e9f9f299e5ba0e4f7e6054857224976a5d9f839d4ebdc94a14ac9" sha256: "9357080b7dd892aae837d569e1fbbcbe7f9a02ca994e558561d90e35e92f1101"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.0" version: "2.2.2"
sky_engine: sky_engine:
dependency: transitive dependency: transitive
description: flutter description: flutter
@@ -1147,4 +1147,4 @@ packages:
version: "0.0.6" version: "0.0.6"
sdks: sdks:
dart: ">=3.6.0 <4.0.0" dart: ">=3.6.0 <4.0.0"
flutter: ">=3.27.1" flutter: ">=3.27.1"

View File

@@ -69,7 +69,7 @@ dependencies:
ref: 7637b8b67d0a831f3cd7e702b8173e300880d32e ref: 7637b8b67d0a831f3cd7e702b8173e300880d32e
pdf: ^3.11.1 pdf: ^3.11.1
dynamic_color: ^1.7.0 dynamic_color: ^1.7.0
shimmer: ^3.0.0 shimmer_animation: ^2.1.0
flutter_memory_info: ^0.0.1 flutter_memory_info: ^0.0.1
syntax_highlight: ^0.4.0 syntax_highlight: ^0.4.0
text_scroll: ^0.2.0 text_scroll: ^0.2.0