长按图片调整位置,新增毛玻璃详情

This commit is contained in:
DelLevin-Home
2026-06-19 15:50:19 +08:00
parent 67b77f14e0
commit 631c532269
6 changed files with 1250 additions and 389 deletions

View File

@@ -1,5 +1,7 @@
import 'dart:io'; import 'dart:io';
import 'dart:ui' as ui;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../../widgets/fade_in_local_image.dart'; import '../../widgets/fade_in_local_image.dart';
import 'package:share_plus/share_plus.dart'; import 'package:share_plus/share_plus.dart';
@@ -7,6 +9,7 @@ import 'package:cross_file/cross_file.dart';
import '../../providers/app_provider.dart'; import '../../providers/app_provider.dart';
import '../../models/data_models.dart'; import '../../models/data_models.dart';
import '../../utils/toast_util.dart'; import '../../utils/toast_util.dart';
import '../../utils/user_prefs.dart';
import 'book_reviews_page.dart'; import 'book_reviews_page.dart';
import 'book_excerpts_page.dart'; import 'book_excerpts_page.dart';
import 'book_share_page.dart'; import 'book_share_page.dart';
@@ -22,6 +25,25 @@ class BookDetailPage extends StatefulWidget {
} }
class _BookDetailPageState extends State<BookDetailPage> { class _BookDetailPageState extends State<BookDetailPage> {
late int _detailStyle;
final ValueNotifier<double> _coverOffset = ValueNotifier(0.0);
double _coverDragStartOffset = 0.0;
bool _draggingCover = false;
final GlobalKey _coverImageKey = GlobalKey();
double _coverImageHeight = 0.0;
@override
void dispose() {
_coverOffset.dispose();
super.dispose();
}
@override
void initState() {
super.initState();
_detailStyle = UserPrefs().detailPageStyle;
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final colors = Theme.of(context).colorScheme; final colors = Theme.of(context).colorScheme;
@@ -29,46 +51,194 @@ class _BookDetailPageState extends State<BookDetailPage> {
.where((b) => b.id == widget.book.id) .where((b) => b.id == widget.book.id)
.firstOrNull ?? widget.book; .firstOrNull ?? widget.book;
if (_detailStyle == 1) {
return _buildOverlayStyle(book, colors);
}
return _buildStandardStyle(book, colors);
}
/// 标准样式
Widget _buildStandardStyle(Book book, ColorScheme colors) {
final topSafe = MediaQuery.of(context).padding.top;
return Scaffold( return Scaffold(
backgroundColor: colors.surface, backgroundColor: colors.surface,
body: Stack( body: Stack(
children: [ children: [
CustomScrollView( // 图片从导航栏下方开始,固定在顶部
slivers: [ Column(
_buildSliverAppBar(book), children: [
SliverToBoxAdapter( SizedBox(height: topSafe + 48),
SizedBox(
height: 320,
width: double.infinity,
child: _buildCoverSection(book),
),
],
),
// 可滚动内容区域从图片底部开始
Positioned(
top: topSafe + 48 + 320,
left: 0, right: 0, bottom: 0,
child: SingleChildScrollView(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
_buildBasicInfo(book), _buildBasicInfo(book),
Divider(height: 0.5, thickness: 0.5, color: colors.outline), Divider(height: 0.5, thickness: 0.5, color: colors.outline),
_buildAuthorsSection(book), _buildAuthorsSection(book),
if (book.genres.isNotEmpty) if (book.genres.isNotEmpty) _buildGenresSection(book),
_buildGenresSection(book), if (book.isbn != null && book.isbn!.isNotEmpty) _buildIsbnSection(book),
if (book.isbn != null && book.isbn!.isNotEmpty) if (book.publisher != null && book.publisher!.isNotEmpty) _buildPublisherSection(book),
_buildIsbnSection(book), if (book.publishDate != null) _buildPublishDateSection(book),
if (book.publisher != null && book.publisher!.isNotEmpty)
_buildPublisherSection(book),
if (book.publishDate != null)
_buildPublishDateSection(book),
Divider(height: 0.5, thickness: 0.5, color: colors.outline), Divider(height: 0.5, thickness: 0.5, color: colors.outline),
if (book.summary != null && book.summary!.isNotEmpty) if (book.summary != null && book.summary!.isNotEmpty) _buildSummarySection(book),
_buildSummarySection(book),
Divider(height: 0.5, thickness: 0.5, color: colors.outline), Divider(height: 0.5, thickness: 0.5, color: colors.outline),
_buildExtraSections(book), _buildExtraSections(book),
const SizedBox(height: 120), const SizedBox(height: 120),
], ],
), ),
), ),
),
_buildStandardTopBar(book.title, colors),
Positioned(right: 16, bottom: 24, child: _buildFloatingActionButtons(book)),
], ],
), ),
Positioned( );
right: 16, }
bottom: 24,
child: _buildFloatingActionButtons(book), /// 毛玻璃层叠样式:海报背景 + 毛玻璃 + 内容
Widget _buildOverlayStyle(Book book, ColorScheme colors) {
final screenH = MediaQuery.of(context).size.height;
final hasCover = book.coverPath != null && book.coverPath!.isNotEmpty;
return Scaffold(
body: Stack(
children: [
// 海报背景(高度不够时重复拼接)
if (hasCover)
Positioned.fill(
child: Image(
image: FileImage(File(book.coverPath!)),
fit: BoxFit.cover,
width: double.infinity,
height: screenH,
repeat: ImageRepeat.repeatY,
),
)
else
Container(color: colors.surfaceContainerHighest),
// 毛玻璃层
ClipRect(
child: BackdropFilter(
filter: ui.ImageFilter.blur(sigmaX: 25, sigmaY: 25),
child: Container(color: Colors.black.withValues(alpha: 0.3)),
),
),
// 内容
SafeArea(
child: Column(
children: [
// 顶部栏
SizedBox(
height: 48,
child: Row(children: [
const SizedBox(width: 4),
IconButton(
icon: const Icon(Icons.arrow_back_ios_new, color: Colors.white, size: 18),
onPressed: () => Navigator.pop(context),
),
const Spacer(),
Text(book.title, style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Colors.white),
maxLines: 1, overflow: TextOverflow.ellipsis),
const Spacer(),
_buildStyleButton(),
]),
),
// 可滚动内容
Expanded(
child: SingleChildScrollView(
padding: const EdgeInsets.fromLTRB(16, 8, 16, 100),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// 封面缩略图 + 标题
_buildOverlayHeader(book),
const SizedBox(height: 20),
// 信息区块:无毛玻璃
_buildAuthorsSection(book),
if (book.isbn != null && book.isbn!.isNotEmpty) _buildIsbnSection(book),
if (book.publisher != null && book.publisher!.isNotEmpty) _buildPublisherSection(book),
if (book.publishDate != null) _buildPublishDateSection(book),
// 类型标签毛玻璃
if (book.genres.isNotEmpty) _buildGenresSection(book),
// 简介:内部已有毛玻璃卡片
if (book.summary != null && book.summary!.isNotEmpty) ...[
const SizedBox(height: 12),
_buildSummarySection(book),
],
const SizedBox(height: 12),
// 书评、书摘毛玻璃
_buildExtraSectionsOverlay(book),
],
),
),
), ),
], ],
), ),
),
Positioned(right: 16, bottom: 24, child: _buildFloatingActionButtons(book)),
],
),
);
}
/// 叠层模式顶部:封面小图 + 标题/评分
Widget _buildOverlayHeader(Book book) {
final hasCover = book.coverPath != null && book.coverPath!.isNotEmpty;
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// 封面缩略图
Container(
width: 100, height: 140,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
boxShadow: [BoxShadow(color: Colors.black.withValues(alpha: 0.3), blurRadius: 12, offset: const Offset(0, 4))],
),
clipBehavior: Clip.antiAlias,
child: hasCover
? FadeInLocalImage(path: book.coverPath, fit: BoxFit.cover)
: Container(color: Colors.white24, child: const Icon(Icons.menu_book, color: Colors.white38, size: 32)),
),
const SizedBox(width: 16),
// 标题 + 信息
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(height: 4),
Text(book.title, style: const TextStyle(fontSize: 22, fontWeight: FontWeight.bold, color: Colors.white)),
if (book.authors.isNotEmpty) ...[
const SizedBox(height: 6),
Text(book.authors.join(' / '), style: TextStyle(fontSize: 14, color: Colors.white.withValues(alpha: 0.6))),
],
const SizedBox(height: 12),
Row(children: [
if (book.rating != null && book.rating! > 0) ...[
const Icon(Icons.star, size: 16, color: Color(0xFFFFB800)),
const SizedBox(width: 4),
Text(book.rating!.toStringAsFixed(1), style: const TextStyle(fontSize: 15, fontWeight: FontWeight.w600, color: Color(0xFFFFB800))),
const SizedBox(width: 16),
],
_statusChip(book.status),
]),
],
),
),
],
); );
} }
@@ -137,52 +307,130 @@ class _BookDetailPageState extends State<BookDetailPage> {
); );
} }
Widget _buildBackButton() { /// 固定在顶部的导航栏(纯色,与主体一致)
return Container( Widget _buildStandardTopBar(String title, ColorScheme colors) {
margin: const EdgeInsets.symmetric(horizontal: 4, vertical: 8), final topPadding = MediaQuery.of(context).padding.top;
decoration: BoxDecoration( return Positioned(
color: Colors.black.withOpacity(0.3), top: 0, left: 0, right: 0,
borderRadius: BorderRadius.circular(8),
),
child: Material(
color: Colors.transparent,
child: InkWell(
onTap: () => Navigator.pop(context),
borderRadius: BorderRadius.circular(8),
child: Container( child: Container(
padding: const EdgeInsets.all(8), padding: EdgeInsets.only(top: topPadding),
child: const Icon( color: colors.surface,
Icons.arrow_back, child: SizedBox(
color: Colors.white, height: 48,
size: 22, child: Row(children: [
const SizedBox(width: 4),
IconButton(
icon: Icon(Icons.arrow_back_ios_new, color: colors.onSurface, size: 18),
onPressed: () => Navigator.pop(context),
), ),
const SizedBox(width: 4),
Expanded(
child: Text(title,
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: colors.onSurface),
maxLines: 1, overflow: TextOverflow.ellipsis),
), ),
_buildStyleButton(color: colors.onSurface),
]),
), ),
), ),
); );
} }
Widget _buildSliverAppBar(Book book) {
final colors = Theme.of(context).colorScheme;
return SliverAppBar(
expandedHeight: 320,
pinned: true,
backgroundColor: colors.surfaceContainerHighest,
leading: _buildBackButton(),
flexibleSpace: FlexibleSpaceBar(
background: _buildCoverSection(book),
),
);
}
Widget _buildCoverSection(Book book) { Widget _buildCoverSection(Book book) {
return SizedBox.expand( final colors = Theme.of(context).colorScheme;
child: book.coverPath != null && book.coverPath!.isNotEmpty final hasCover = book.coverPath != null && book.coverPath!.isNotEmpty;
? FadeInLocalImage( return LayoutBuilder(
builder: (context, constraints) {
final containerH = constraints.maxHeight;
return GestureDetector(
onLongPressStart: hasCover ? (_) {
HapticFeedback.mediumImpact();
final ctx = _coverImageKey.currentContext;
if (ctx != null) {
final box = ctx.findRenderObject() as RenderBox?;
if (box != null) _coverImageHeight = box.size.height;
}
setState(() => _draggingCover = true);
_coverDragStartOffset = _coverOffset.value;
} : null,
onLongPressMoveUpdate: hasCover ? (d) {
final raw = _coverDragStartOffset + d.offsetFromOrigin.dy;
final imgH = _coverImageHeight > 0 ? _coverImageHeight : containerH;
final minOffset = -(imgH - containerH).clamp(0, double.infinity);
_coverOffset.value = (raw.clamp(minOffset, 0.0) as double);
} : null,
onLongPressEnd: hasCover ? (_) {
setState(() => _draggingCover = false);
} : null,
child: ValueListenableBuilder<double>(
valueListenable: _coverOffset,
builder: (context, offset, _) {
return Stack(
fit: StackFit.expand,
children: [
if (hasCover)
ClipRect(
child: Stack(
children: [
Positioned(
top: offset,
left: 0, right: 0,
child: FadeInLocalImage(
key: _coverImageKey,
path: book.coverPath, path: book.coverPath,
fit: BoxFit.cover, fit: BoxFit.fitWidth,
width: constraints.maxWidth,
),
),
],
),
) )
: _buildCoverPlaceholder(), else
_buildCoverPlaceholder(),
if (!_draggingCover)
Positioned(
left: 0, right: 0, bottom: 0,
child: IgnorePointer(
child: Container(
height: 60,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
colors.surface.withValues(alpha: 0),
colors.surface,
],
),
),
),
),
),
if (_draggingCover) ...[
Positioned.fill(
child: Container(color: Colors.black.withValues(alpha: 0.3)),
),
Positioned(
left: 0, right: 0, bottom: 20,
child: Center(
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
decoration: BoxDecoration(
color: Colors.black.withValues(alpha: 0.6),
borderRadius: BorderRadius.circular(20),
),
child: const Text('上下滑动调整图片位置',
style: TextStyle(fontSize: 13, color: Colors.white70)),
),
),
),
],
],
);
},
),
);
},
); );
} }
@@ -210,6 +458,66 @@ class _BookDetailPageState extends State<BookDetailPage> {
); );
} }
/// 样式选择按钮
Widget _buildStyleButton({Color color = Colors.white}) {
return IconButton(
icon: Icon(Icons.tune, color: color, size: 20),
tooltip: '切换样式',
onPressed: _showStylePicker,
);
}
void _showStylePicker() {
final colors = Theme.of(context).colorScheme;
const names = ['默认样式', '毛玻璃层叠'];
showModalBottomSheet(
context: context,
backgroundColor: colors.surface,
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.vertical(top: Radius.circular(16))),
builder: (ctx) => Padding(
padding: const EdgeInsets.fromLTRB(20, 16, 20, 24),
child: Column(mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [
Text('详情页样式', style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: colors.onSurface)),
const SizedBox(height: 16),
Wrap(spacing: 10, runSpacing: 10, children: List.generate(names.length, (i) {
final selected = _detailStyle == i;
return GestureDetector(
onTap: () { setState(() => _detailStyle = i); UserPrefs().setDetailPageStyle(i); Navigator.pop(ctx); },
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 18, vertical: 10),
decoration: BoxDecoration(
color: selected ? colors.primary : colors.surfaceContainerHighest,
borderRadius: BorderRadius.circular(8),
border: Border.all(color: selected ? colors.primary : colors.outline, width: 0.5),
),
child: Text(names[i], style: TextStyle(
fontSize: 14, fontWeight: selected ? FontWeight.w600 : FontWeight.w400,
color: selected ? colors.onPrimary : colors.onSurface.withValues(alpha: 0.6),
)),
),
);
})),
]),
),
);
}
Widget _statusChip(String status) {
final colors = Theme.of(context).colorScheme;
final (label, bg, fg) = switch (status) {
'read' => ('已读', colors.primary, colors.onPrimary),
'reading' => ('在读', colors.outlineVariant, colors.onSurface.withValues(alpha: 0.6)),
'want_to_read' => ('想读', colors.surfaceContainerHighest, colors.onSurface.withValues(alpha: 0.4)),
_ => ('', colors.surfaceContainerHighest, colors.onSurface.withValues(alpha: 0.3)),
};
if (label.isEmpty) return const SizedBox.shrink();
return Container(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
decoration: BoxDecoration(color: bg, borderRadius: BorderRadius.circular(12)),
child: Text(label, style: TextStyle(fontSize: 12, fontWeight: FontWeight.w600, color: fg)),
);
}
Widget _buildBasicInfo(Book book) { Widget _buildBasicInfo(Book book) {
final colors = Theme.of(context).colorScheme; final colors = Theme.of(context).colorScheme;
return Padding( return Padding(
@@ -318,6 +626,7 @@ class _BookDetailPageState extends State<BookDetailPage> {
} }
Widget _buildAuthorsSection(Book book) { Widget _buildAuthorsSection(Book book) {
final isOverlay = _detailStyle == 1;
final colors = Theme.of(context).colorScheme; final colors = Theme.of(context).colorScheme;
return Padding( return Padding(
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16), padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
@@ -330,7 +639,7 @@ class _BookDetailPageState extends State<BookDetailPage> {
'作者', '作者',
style: TextStyle( style: TextStyle(
fontSize: 13, fontSize: 13,
color: colors.onSurface.withValues(alpha: 0.4), color: isOverlay ? const Color(0x66FFFFFF) : colors.onSurface.withValues(alpha: 0.4),
), ),
), ),
), ),
@@ -339,7 +648,7 @@ class _BookDetailPageState extends State<BookDetailPage> {
book.authors.join(''), book.authors.join(''),
style: TextStyle( style: TextStyle(
fontSize: 15, fontSize: 15,
color: colors.onSurface, color: isOverlay ? Colors.white : colors.onSurface,
height: 1.5, height: 1.5,
), ),
), ),
@@ -350,6 +659,7 @@ class _BookDetailPageState extends State<BookDetailPage> {
} }
Widget _buildIsbnSection(Book book) { Widget _buildIsbnSection(Book book) {
final isOverlay = _detailStyle == 1;
final colors = Theme.of(context).colorScheme; final colors = Theme.of(context).colorScheme;
return Padding( return Padding(
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16), padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
@@ -362,7 +672,7 @@ class _BookDetailPageState extends State<BookDetailPage> {
'ISBN', 'ISBN',
style: TextStyle( style: TextStyle(
fontSize: 13, fontSize: 13,
color: colors.onSurface.withValues(alpha: 0.4), color: isOverlay ? const Color(0x66FFFFFF) : colors.onSurface.withValues(alpha: 0.4),
), ),
), ),
), ),
@@ -371,7 +681,7 @@ class _BookDetailPageState extends State<BookDetailPage> {
book.isbn!, book.isbn!,
style: TextStyle( style: TextStyle(
fontSize: 15, fontSize: 15,
color: colors.onSurface, color: isOverlay ? Colors.white : colors.onSurface,
height: 1.5, height: 1.5,
), ),
), ),
@@ -382,6 +692,7 @@ class _BookDetailPageState extends State<BookDetailPage> {
} }
Widget _buildPublisherSection(Book book) { Widget _buildPublisherSection(Book book) {
final isOverlay = _detailStyle == 1;
final colors = Theme.of(context).colorScheme; final colors = Theme.of(context).colorScheme;
return Padding( return Padding(
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16), padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
@@ -394,7 +705,7 @@ class _BookDetailPageState extends State<BookDetailPage> {
'出版社', '出版社',
style: TextStyle( style: TextStyle(
fontSize: 13, fontSize: 13,
color: colors.onSurface.withValues(alpha: 0.4), color: isOverlay ? const Color(0x66FFFFFF) : colors.onSurface.withValues(alpha: 0.4),
), ),
), ),
), ),
@@ -403,7 +714,7 @@ class _BookDetailPageState extends State<BookDetailPage> {
book.publisher!, book.publisher!,
style: TextStyle( style: TextStyle(
fontSize: 15, fontSize: 15,
color: colors.onSurface, color: isOverlay ? Colors.white : colors.onSurface,
height: 1.5, height: 1.5,
), ),
), ),
@@ -414,6 +725,7 @@ class _BookDetailPageState extends State<BookDetailPage> {
} }
Widget _buildPublishDateSection(Book book) { Widget _buildPublishDateSection(Book book) {
final isOverlay = _detailStyle == 1;
final colors = Theme.of(context).colorScheme; final colors = Theme.of(context).colorScheme;
return Padding( return Padding(
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16), padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
@@ -426,7 +738,7 @@ class _BookDetailPageState extends State<BookDetailPage> {
'出版时间', '出版时间',
style: TextStyle( style: TextStyle(
fontSize: 13, fontSize: 13,
color: colors.onSurface.withValues(alpha: 0.4), color: isOverlay ? const Color(0x66FFFFFF) : colors.onSurface.withValues(alpha: 0.4),
), ),
), ),
), ),
@@ -435,7 +747,7 @@ class _BookDetailPageState extends State<BookDetailPage> {
'${book.publishDate!.year}${book.publishDate!.month.toString().padLeft(2, '0')}', '${book.publishDate!.year}${book.publishDate!.month.toString().padLeft(2, '0')}',
style: TextStyle( style: TextStyle(
fontSize: 15, fontSize: 15,
color: colors.onSurface, color: isOverlay ? Colors.white : colors.onSurface,
height: 1.5, height: 1.5,
), ),
), ),
@@ -446,42 +758,21 @@ class _BookDetailPageState extends State<BookDetailPage> {
} }
Widget _buildGenresSection(Book book) { Widget _buildGenresSection(Book book) {
final colors = Theme.of(context).colorScheme; final isOverlay = _detailStyle == 1;
return Padding( return Padding(
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16), padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
child: Row( child: Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
SizedBox( SizedBox(
width: 64, width: 48,
child: Text( child: Text('类型', style: TextStyle(fontSize: 13,
'类型', color: isOverlay ? const Color(0x66FFFFFF) : Theme.of(context).colorScheme.onSurface.withValues(alpha: 0.4))),
style: TextStyle(
fontSize: 13,
color: colors.onSurface.withValues(alpha: 0.4),
),
),
), ),
Expanded( Expanded(
child: Wrap( child: Wrap(
spacing: 8, spacing: 8, runSpacing: 8,
runSpacing: 8, children: book.genres.map((g) => _buildGenreChip(g, isOverlay)).toList(),
children: book.genres.map((genre) {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
decoration: BoxDecoration(
color: colors.surfaceContainerHighest,
borderRadius: BorderRadius.circular(4),
),
child: Text(
genre,
style: TextStyle(
fontSize: 13,
color: colors.onSurface.withValues(alpha: 0.6),
),
),
);
}).toList(),
), ),
), ),
], ],
@@ -489,7 +780,36 @@ class _BookDetailPageState extends State<BookDetailPage> {
); );
} }
Widget _buildGenreChip(String label, bool isOverlay) {
if (isOverlay) {
return ClipRRect(
borderRadius: BorderRadius.circular(16),
child: BackdropFilter(
filter: ui.ImageFilter.blur(sigmaX: 10, sigmaY: 10),
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
decoration: BoxDecoration(
color: Colors.white.withValues(alpha: 0.12),
borderRadius: BorderRadius.circular(16),
),
child: Text(label, style: TextStyle(fontSize: 13, color: Colors.white.withValues(alpha: 0.85))),
),
),
);
}
final colors = Theme.of(context).colorScheme;
return Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
decoration: BoxDecoration(
color: colors.surfaceContainerHighest,
borderRadius: BorderRadius.circular(16),
),
child: Text(label, style: TextStyle(fontSize: 13, color: colors.onSurface.withValues(alpha: 0.6))),
);
}
Widget _buildSummarySection(Book book) { Widget _buildSummarySection(Book book) {
final isOverlay = _detailStyle == 1;
final colors = Theme.of(context).colorScheme; final colors = Theme.of(context).colorScheme;
return Padding( return Padding(
padding: const EdgeInsets.all(24), padding: const EdgeInsets.all(24),
@@ -502,7 +822,7 @@ class _BookDetailPageState extends State<BookDetailPage> {
width: 4, width: 4,
height: 16, height: 16,
decoration: BoxDecoration( decoration: BoxDecoration(
color: colors.onSurface, color: isOverlay ? Colors.white : colors.onSurface,
borderRadius: BorderRadius.circular(2), borderRadius: BorderRadius.circular(2),
), ),
), ),
@@ -512,27 +832,33 @@ class _BookDetailPageState extends State<BookDetailPage> {
style: TextStyle( style: TextStyle(
fontSize: 15, fontSize: 15,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: colors.onSurface, color: isOverlay ? Colors.white : colors.onSurface,
), ),
), ),
], ],
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
Container( ClipRRect(
borderRadius: BorderRadius.circular(12),
child: BackdropFilter(
filter: ui.ImageFilter.blur(sigmaX: 15, sigmaY: 15),
child: Container(
padding: const EdgeInsets.all(20), padding: const EdgeInsets.all(20),
decoration: BoxDecoration( decoration: BoxDecoration(
color: colors.surfaceContainerHigh, color: Colors.white.withValues(alpha: 0.08),
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
), ),
child: Text( child: Text(
book.summary!, book.summary!,
style: TextStyle( style: TextStyle(
fontSize: 15, fontSize: 15,
color: colors.onSurface, color: isOverlay ? Colors.white : colors.onSurface,
height: 1.8, height: 1.8,
), ),
), ),
), ),
),
),
], ],
), ),
); );
@@ -589,6 +915,85 @@ class _BookDetailPageState extends State<BookDetailPage> {
); );
} }
/// 叠层模式:书评、摘抄各自独立毛玻璃卡片
Widget _buildExtraSectionsOverlay(Book book) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 24),
child: Column(
children: [
_buildFrostedExtraItem(
icon: Icons.rate_review_outlined,
title: '书评',
subtitleFuture: context.read<AppProvider>().getBookReviewCount(book.id),
emptyText: '暂无书评',
unit: '条书评',
onTap: () => _navigateToReviews(book),
),
const SizedBox(height: 12),
_buildFrostedExtraItem(
icon: Icons.format_quote_outlined,
title: '摘抄',
subtitleFuture: context.read<AppProvider>().getBookExcerptCount(book.id),
emptyText: '暂无摘抄',
unit: '条摘抄',
onTap: () => _navigateToExcerpts(book),
),
],
),
);
}
/// 毛玻璃书评/摘抄卡片
Widget _buildFrostedExtraItem({
required IconData icon,
required String title,
required Future<int> subtitleFuture,
required String emptyText,
required String unit,
required VoidCallback onTap,
}) {
return ClipRRect(
borderRadius: BorderRadius.circular(12),
child: BackdropFilter(
filter: ui.ImageFilter.blur(sigmaX: 15, sigmaY: 15),
child: Container(
decoration: BoxDecoration(
color: Colors.white.withValues(alpha: 0.08),
borderRadius: BorderRadius.circular(12),
),
child: Material(
color: Colors.transparent,
child: InkWell(
onTap: onTap,
borderRadius: BorderRadius.circular(12),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14),
child: Row(children: [
Icon(icon, size: 20, color: Colors.white.withValues(alpha: 0.7)),
const SizedBox(width: 12),
Expanded(
child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
Text(title, style: const TextStyle(fontSize: 15, fontWeight: FontWeight.w600, color: Colors.white)),
FutureBuilder<int>(
future: subtitleFuture,
builder: (ctx, snap) {
final count = snap.data ?? 0;
return Text(count > 0 ? '$count $unit' : emptyText,
style: TextStyle(fontSize: 12, color: Colors.white.withValues(alpha: 0.5)));
},
),
]),
),
Icon(Icons.chevron_right, size: 16, color: Colors.white.withValues(alpha: 0.3)),
]),
),
),
),
),
),
);
}
Widget _buildExtraSectionItem({ Widget _buildExtraSectionItem({
required IconData icon, required IconData icon,
required String title, required String title,

View File

@@ -1,5 +1,7 @@
import 'dart:io'; import 'dart:io';
import 'dart:ui' as ui;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:path_provider/path_provider.dart'; import 'package:path_provider/path_provider.dart';
import 'package:path/path.dart' as path; import 'package:path/path.dart' as path;
@@ -27,11 +29,18 @@ class MovieDetailPage extends StatefulWidget {
class _MovieDetailPageState extends State<MovieDetailPage> { class _MovieDetailPageState extends State<MovieDetailPage> {
late bool _showExactDate; late bool _showExactDate;
late int _detailStyle;
final ValueNotifier<double> _posterOffset = ValueNotifier(0.0);
double _posterDragStartOffset = 0.0;
bool _draggingPoster = false;
final GlobalKey _posterImageKey = GlobalKey();
double _posterImageHeight = 0.0;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_showExactDate = UserPrefs().showExactReleaseDate; _showExactDate = UserPrefs().showExactReleaseDate;
_detailStyle = UserPrefs().detailPageStyle;
} }
void _toggleDateDisplay() { void _toggleDateDisplay() {
@@ -46,14 +55,34 @@ class _MovieDetailPageState extends State<MovieDetailPage> {
.where((m) => m.id == widget.movie.id) .where((m) => m.id == widget.movie.id)
.firstOrNull ?? widget.movie; .firstOrNull ?? widget.movie;
return _detailStyle == 1
? _buildOverlayStyle(movie, colors)
: _buildStandardStyle(movie, colors);
}
/// 标准样式
Widget _buildStandardStyle(Movie movie, ColorScheme colors) {
final topSafe = MediaQuery.of(context).padding.top;
return Scaffold( return Scaffold(
backgroundColor: colors.surface, backgroundColor: colors.surface,
body: Stack( body: Stack(
children: [ children: [
CustomScrollView( // 图片从导航栏下方开始,固定在顶部
slivers: [ Column(
_buildSliverAppBar(movie), children: [
SliverToBoxAdapter( SizedBox(height: topSafe + 48),
SizedBox(
height: 320,
width: double.infinity,
child: _buildPosterSection(movie),
),
],
),
// 可滚动内容区域从图片底部开始
Positioned(
top: topSafe + 48 + 320,
left: 0, right: 0, bottom: 0,
child: SingleChildScrollView(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@@ -76,7 +105,31 @@ class _MovieDetailPageState extends State<MovieDetailPage> {
], ],
), ),
), ),
], ),
// 导航栏
Positioned(
top: 0, left: 0, right: 0,
child: Container(
padding: EdgeInsets.only(top: topSafe),
color: colors.surface,
child: SizedBox(
height: 48,
child: Row(children: [
const SizedBox(width: 4),
IconButton(
icon: Icon(Icons.arrow_back_ios_new, color: colors.onSurface, size: 18),
onPressed: () => Navigator.pop(context),
),
const SizedBox(width: 4),
Expanded(
child: Text(movie.title,
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: colors.onSurface),
maxLines: 1, overflow: TextOverflow.ellipsis),
),
_buildStyleButton(color: colors.onSurface),
]),
),
),
), ),
Positioned( Positioned(
right: 16, right: 16,
@@ -88,6 +141,201 @@ class _MovieDetailPageState extends State<MovieDetailPage> {
); );
} }
/// 毛玻璃层叠样式
Widget _buildOverlayStyle(Movie movie, ColorScheme colors) {
final screenH = MediaQuery.of(context).size.height;
final hasPoster = movie.posterPath != null && movie.posterPath!.isNotEmpty;
return Scaffold(
body: Stack(
children: [
// 海报背景
if (hasPoster)
Positioned.fill(
child: Image(
image: FileImage(File(movie.posterPath!)),
fit: BoxFit.cover, width: double.infinity, height: screenH,
repeat: ImageRepeat.repeatY,
),
)
else
Container(color: colors.surfaceContainerHighest),
// 毛玻璃
ClipRect(
child: BackdropFilter(
filter: ui.ImageFilter.blur(sigmaX: 25, sigmaY: 25),
child: Container(color: Colors.black.withValues(alpha: 0.4)),
),
),
// 内容
SafeArea(
child: Column(children: [
SizedBox(
height: 48,
child: Row(children: [
const SizedBox(width: 4),
IconButton(
icon: const Icon(Icons.arrow_back_ios_new, color: Colors.white, size: 18),
onPressed: () => Navigator.pop(context),
),
const Spacer(),
Text(movie.title, style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Colors.white),
maxLines: 1, overflow: TextOverflow.ellipsis),
const Spacer(),
_buildStyleButton(),
]),
),
Expanded(
child: SingleChildScrollView(
padding: const EdgeInsets.fromLTRB(16, 8, 16, 100),
child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
_buildOverlayHeader(movie),
const SizedBox(height: 20),
// 信息区块:无毛玻璃
if (movie.directors.isNotEmpty) _buildDirectorsSection(movie),
if (movie.writers.isNotEmpty) _buildWritersSection(movie),
if (movie.actors.isNotEmpty) _buildActorsSection(movie),
// 类型标签毛玻璃
if (movie.genres.isNotEmpty) ...[
const SizedBox(height: 12),
_buildGenresSection(movie),
],
// 简介:内部已有毛玻璃卡片
if (movie.summary != null && movie.summary!.isNotEmpty) ...[
const SizedBox(height: 12),
_buildSummarySection(movie),
],
const SizedBox(height: 12),
// 影评、海报墙毛玻璃
_buildExtraSectionsOverlay(movie),
]),
),
),
]),
),
Positioned(right: 16, bottom: 24, child: _buildFloatingActionButtons(movie)),
],
),
);
}
/// 叠层模式:封面小图 + 标题/评分(毛玻璃卡片)
Widget _buildOverlayHeader(Movie movie) {
final hasPoster = movie.posterPath != null && movie.posterPath!.isNotEmpty;
return ClipRRect(
borderRadius: BorderRadius.circular(16),
child: BackdropFilter(
filter: ui.ImageFilter.blur(sigmaX: 15, sigmaY: 15),
child: Container(
width: double.infinity,
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.white.withValues(alpha: 0.08),
borderRadius: BorderRadius.circular(16),
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
width: 100, height: 140,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
boxShadow: [BoxShadow(color: Colors.black.withValues(alpha: 0.3), blurRadius: 12, offset: const Offset(0, 4))],
),
clipBehavior: Clip.antiAlias,
child: hasPoster
? FadeInLocalImage(path: movie.posterPath, fit: BoxFit.cover)
: Container(color: Colors.white24, child: const Icon(Icons.movie_outlined, color: Colors.white38, size: 32)),
),
const SizedBox(width: 16),
Expanded(
child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
const SizedBox(height: 4),
Text(movie.title, style: const TextStyle(fontSize: 22, fontWeight: FontWeight.bold, color: Colors.white)),
if (movie.directors.isNotEmpty) ...[
const SizedBox(height: 6),
Text('导演:${movie.directors.join(' / ')}', style: TextStyle(fontSize: 14, color: Colors.white.withValues(alpha: 0.6))),
],
const SizedBox(height: 12),
Row(children: [
if (movie.rating != null && movie.rating! > 0) ...[
const Icon(Icons.star, size: 16, color: Color(0xFFFFB800)),
const SizedBox(width: 4),
Text(movie.rating!.toStringAsFixed(1), style: const TextStyle(fontSize: 15, fontWeight: FontWeight.w600, color: Color(0xFFFFB800))),
const SizedBox(width: 16),
],
_statusChip(movie.status),
]),
]),
),
],
),
),
),
);
}
Widget _statusChip(String status) {
final (label, bg, fg) = switch (status) {
'watched' => ('已看', const Color(0xFF1A1A1A), Colors.white),
'watching' => ('在看', const Color(0xFF666666), Colors.white),
'want_to_watch' => ('想看', const Color(0xFF999999), Colors.white),
_ => ('', const Color(0xFF999999), Colors.white),
};
if (label.isEmpty) return const SizedBox.shrink();
return Container(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
decoration: BoxDecoration(color: bg, borderRadius: BorderRadius.circular(12)),
child: Text(label, style: TextStyle(fontSize: 12, fontWeight: FontWeight.w600, color: fg)),
);
}
Widget _buildStyleButton({Color color = Colors.white}) {
return IconButton(
icon: Icon(Icons.tune, color: color, size: 20),
tooltip: '切换样式',
onPressed: _showStylePicker,
);
}
void _showStylePicker() {
final colors = Theme.of(context).colorScheme;
const names = ['默认样式', '毛玻璃层叠'];
showModalBottomSheet(
context: context,
backgroundColor: colors.surface,
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.vertical(top: Radius.circular(16))),
builder: (ctx) => Padding(
padding: const EdgeInsets.fromLTRB(20, 16, 20, 24),
child: Column(mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [
Text('详情页样式', style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: colors.onSurface)),
const SizedBox(height: 16),
Wrap(spacing: 10, runSpacing: 10, children: List.generate(names.length, (i) {
final selected = _detailStyle == i;
return GestureDetector(
onTap: () { setState(() => _detailStyle = i); UserPrefs().setDetailPageStyle(i); Navigator.pop(ctx); },
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 18, vertical: 10),
decoration: BoxDecoration(
color: selected ? colors.primary : colors.surfaceContainerHighest,
borderRadius: BorderRadius.circular(8),
border: Border.all(color: selected ? colors.primary : colors.outline, width: 0.5),
),
child: Text(names[i], style: TextStyle(
fontSize: 14, fontWeight: selected ? FontWeight.w600 : FontWeight.w400,
color: selected ? colors.onPrimary : colors.onSurface.withValues(alpha: 0.6),
)),
),
);
})),
]),
),
);
}
Widget _buildFloatingActionButtons(Movie movie) { Widget _buildFloatingActionButtons(Movie movie) {
final colors = Theme.of(context).colorScheme; final colors = Theme.of(context).colorScheme;
return Column( return Column(
@@ -153,52 +401,105 @@ class _MovieDetailPageState extends State<MovieDetailPage> {
); );
} }
Widget _buildBackButton() {
return Container(
margin: const EdgeInsets.symmetric(horizontal: 4, vertical: 8),
decoration: BoxDecoration(
color: Colors.black.withOpacity(0.3),
borderRadius: BorderRadius.circular(8),
),
child: Material(
color: Colors.transparent,
child: InkWell(
onTap: () => Navigator.pop(context),
borderRadius: BorderRadius.circular(8),
child: Container(
padding: const EdgeInsets.all(8),
child: const Icon(
Icons.arrow_back,
color: Colors.white,
size: 22,
),
),
),
),
);
}
Widget _buildSliverAppBar(Movie movie) {
final colors = Theme.of(context).colorScheme;
return SliverAppBar(
expandedHeight: 320,
pinned: true,
backgroundColor: colors.surfaceContainerHighest,
leading: _buildBackButton(),
flexibleSpace: FlexibleSpaceBar(
background: _buildPosterSection(movie),
),
);
}
Widget _buildPosterSection(Movie movie) { Widget _buildPosterSection(Movie movie) {
return SizedBox.expand( final colors = Theme.of(context).colorScheme;
child: movie.posterPath != null && movie.posterPath!.isNotEmpty final hasPoster = movie.posterPath != null && movie.posterPath!.isNotEmpty;
? FadeInLocalImage( return LayoutBuilder(
builder: (context, constraints) {
final containerH = constraints.maxHeight;
return GestureDetector(
onLongPressStart: hasPoster ? (_) {
HapticFeedback.mediumImpact();
// 测量图片渲染高度
final ctx = _posterImageKey.currentContext;
if (ctx != null) {
final box = ctx.findRenderObject() as RenderBox?;
if (box != null) _posterImageHeight = box.size.height;
}
setState(() => _draggingPoster = true);
_posterDragStartOffset = _posterOffset.value;
} : null,
onLongPressMoveUpdate: hasPoster ? (d) {
// 实时钳制:图片顶部不超过容器顶部(offset<=0),图片底部不低于容器底部(offset+H>=containerH)
final raw = _posterDragStartOffset + d.offsetFromOrigin.dy;
final imgH = _posterImageHeight > 0 ? _posterImageHeight : containerH;
final minOffset = -(imgH - containerH).clamp(0, double.infinity); // 图片底部不能高于容器底部
_posterOffset.value = (raw.clamp(minOffset, 0.0) as double);
} : null,
onLongPressEnd: hasPoster ? (_) {
setState(() => _draggingPoster = false);
} : null,
child: ValueListenableBuilder<double>(
valueListenable: _posterOffset,
builder: (context, offset, _) {
return Stack(
fit: StackFit.expand,
children: [
if (hasPoster)
ClipRect(
child: Stack(
children: [
Positioned(
top: offset,
left: 0, right: 0,
child: FadeInLocalImage(
key: _posterImageKey,
path: movie.posterPath, path: movie.posterPath,
fit: BoxFit.cover, fit: BoxFit.fitWidth,
width: constraints.maxWidth,
),
),
],
),
) )
: _buildPosterPlaceholder(), else
_buildPosterPlaceholder(),
// 底部白色渐变过渡(拖动时隐藏)
if (!_draggingPoster)
Positioned(
left: 0, right: 0, bottom: 0,
child: IgnorePointer(
child: Container(
height: 60,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
colors.surface.withValues(alpha: 0),
colors.surface,
],
),
),
),
),
),
// 长按拖动时的遮罩 + 提示
if (_draggingPoster) ...[
Positioned.fill(
child: Container(color: Colors.black.withValues(alpha: 0.3)),
),
Positioned(
left: 0, right: 0, bottom: 20,
child: Center(
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
decoration: BoxDecoration(
color: Colors.black.withValues(alpha: 0.6),
borderRadius: BorderRadius.circular(20),
),
child: const Text('上下滑动调整图片位置',
style: TextStyle(fontSize: 13, color: Colors.white70)),
),
),
),
],
],
);
},
),
);
},
); );
} }
@@ -356,6 +657,7 @@ class _MovieDetailPageState extends State<MovieDetailPage> {
} }
Widget _buildDirectorsSection(Movie movie) { Widget _buildDirectorsSection(Movie movie) {
final isOverlay = _detailStyle == 1;
final colors = Theme.of(context).colorScheme; final colors = Theme.of(context).colorScheme;
return Padding( return Padding(
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16), padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
@@ -368,7 +670,7 @@ class _MovieDetailPageState extends State<MovieDetailPage> {
'导演', '导演',
style: TextStyle( style: TextStyle(
fontSize: 13, fontSize: 13,
color: colors.onSurface.withValues(alpha: 0.4), color: isOverlay ? const Color(0x66FFFFFF) : colors.onSurface.withValues(alpha: 0.4),
), ),
), ),
), ),
@@ -377,7 +679,7 @@ class _MovieDetailPageState extends State<MovieDetailPage> {
movie.directors.join(''), movie.directors.join(''),
style: TextStyle( style: TextStyle(
fontSize: 15, fontSize: 15,
color: colors.onSurface, color: isOverlay ? Colors.white : colors.onSurface,
height: 1.5, height: 1.5,
), ),
), ),
@@ -388,6 +690,7 @@ class _MovieDetailPageState extends State<MovieDetailPage> {
} }
Widget _buildWritersSection(Movie movie) { Widget _buildWritersSection(Movie movie) {
final isOverlay = _detailStyle == 1;
final colors = Theme.of(context).colorScheme; final colors = Theme.of(context).colorScheme;
return Padding( return Padding(
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16), padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
@@ -400,7 +703,7 @@ class _MovieDetailPageState extends State<MovieDetailPage> {
'编剧', '编剧',
style: TextStyle( style: TextStyle(
fontSize: 13, fontSize: 13,
color: colors.onSurface.withValues(alpha: 0.4), color: isOverlay ? const Color(0x66FFFFFF) : colors.onSurface.withValues(alpha: 0.4),
), ),
), ),
), ),
@@ -409,7 +712,7 @@ class _MovieDetailPageState extends State<MovieDetailPage> {
movie.writers.join(''), movie.writers.join(''),
style: TextStyle( style: TextStyle(
fontSize: 15, fontSize: 15,
color: colors.onSurface, color: isOverlay ? Colors.white : colors.onSurface,
height: 1.5, height: 1.5,
), ),
), ),
@@ -420,6 +723,7 @@ class _MovieDetailPageState extends State<MovieDetailPage> {
} }
Widget _buildActorsSection(Movie movie) { Widget _buildActorsSection(Movie movie) {
final isOverlay = _detailStyle == 1;
final colors = Theme.of(context).colorScheme; final colors = Theme.of(context).colorScheme;
return Padding( return Padding(
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16), padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
@@ -432,7 +736,7 @@ class _MovieDetailPageState extends State<MovieDetailPage> {
'主演', '主演',
style: TextStyle( style: TextStyle(
fontSize: 13, fontSize: 13,
color: colors.onSurface.withValues(alpha: 0.4), color: isOverlay ? const Color(0x66FFFFFF) : colors.onSurface.withValues(alpha: 0.4),
), ),
), ),
), ),
@@ -441,7 +745,7 @@ class _MovieDetailPageState extends State<MovieDetailPage> {
movie.actors.join(''), movie.actors.join(''),
style: TextStyle( style: TextStyle(
fontSize: 15, fontSize: 15,
color: colors.onSurface, color: isOverlay ? Colors.white : colors.onSurface,
height: 1.5, height: 1.5,
), ),
), ),
@@ -452,7 +756,7 @@ class _MovieDetailPageState extends State<MovieDetailPage> {
} }
Widget _buildGenresSection(Movie movie) { Widget _buildGenresSection(Movie movie) {
final colors = Theme.of(context).colorScheme; final isOverlay = _detailStyle == 1;
return Padding( return Padding(
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16), padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
child: Row( child: Row(
@@ -460,34 +764,13 @@ class _MovieDetailPageState extends State<MovieDetailPage> {
children: [ children: [
SizedBox( SizedBox(
width: 48, width: 48,
child: Text( child: Text('类型', style: TextStyle(fontSize: 13,
'类型', color: isOverlay ? const Color(0x66FFFFFF) : Theme.of(context).colorScheme.onSurface.withValues(alpha: 0.4))),
style: TextStyle(
fontSize: 13,
color: colors.onSurface.withValues(alpha: 0.4),
),
),
), ),
Expanded( Expanded(
child: Wrap( child: Wrap(
spacing: 8, spacing: 8, runSpacing: 8,
runSpacing: 8, children: movie.genres.map((g) => _buildGenreChip(g, isOverlay)).toList(),
children: movie.genres.map((genre) {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
decoration: BoxDecoration(
color: colors.surfaceContainerHighest,
borderRadius: BorderRadius.circular(4),
),
child: Text(
genre,
style: TextStyle(
fontSize: 13,
color: colors.onSurface.withValues(alpha: 0.6),
),
),
);
}).toList(),
), ),
), ),
], ],
@@ -495,7 +778,36 @@ class _MovieDetailPageState extends State<MovieDetailPage> {
); );
} }
Widget _buildGenreChip(String label, bool isOverlay) {
if (isOverlay) {
return ClipRRect(
borderRadius: BorderRadius.circular(16),
child: BackdropFilter(
filter: ui.ImageFilter.blur(sigmaX: 10, sigmaY: 10),
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
decoration: BoxDecoration(
color: Colors.white.withValues(alpha: 0.12),
borderRadius: BorderRadius.circular(16),
),
child: Text(label, style: TextStyle(fontSize: 13, color: Colors.white.withValues(alpha: 0.85))),
),
),
);
}
final colors = Theme.of(context).colorScheme;
return Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
decoration: BoxDecoration(
color: colors.surfaceContainerHighest,
borderRadius: BorderRadius.circular(16),
),
child: Text(label, style: TextStyle(fontSize: 13, color: colors.onSurface.withValues(alpha: 0.6))),
);
}
Widget _buildSummarySection(Movie movie) { Widget _buildSummarySection(Movie movie) {
final isOverlay = _detailStyle == 1;
final colors = Theme.of(context).colorScheme; final colors = Theme.of(context).colorScheme;
return Padding( return Padding(
padding: const EdgeInsets.all(24), padding: const EdgeInsets.all(24),
@@ -508,7 +820,7 @@ class _MovieDetailPageState extends State<MovieDetailPage> {
width: 4, width: 4,
height: 16, height: 16,
decoration: BoxDecoration( decoration: BoxDecoration(
color: colors.onSurface, color: isOverlay ? Colors.white : colors.onSurface,
borderRadius: BorderRadius.circular(2), borderRadius: BorderRadius.circular(2),
), ),
), ),
@@ -518,27 +830,33 @@ class _MovieDetailPageState extends State<MovieDetailPage> {
style: TextStyle( style: TextStyle(
fontSize: 15, fontSize: 15,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: colors.onSurface, color: isOverlay ? Colors.white : colors.onSurface,
), ),
), ),
], ],
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
Container( ClipRRect(
borderRadius: BorderRadius.circular(12),
child: BackdropFilter(
filter: ui.ImageFilter.blur(sigmaX: 15, sigmaY: 15),
child: Container(
padding: const EdgeInsets.all(20), padding: const EdgeInsets.all(20),
decoration: BoxDecoration( decoration: BoxDecoration(
color: colors.surfaceContainerHigh, color: Colors.white.withValues(alpha: 0.08),
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
), ),
child: Text( child: Text(
movie.summary!, movie.summary!,
style: TextStyle( style: TextStyle(
fontSize: 15, fontSize: 15,
color: colors.onSurface, color: isOverlay ? Colors.white : colors.onSurface,
height: 1.8, height: 1.8,
), ),
), ),
), ),
),
),
], ],
), ),
); );
@@ -595,6 +913,85 @@ class _MovieDetailPageState extends State<MovieDetailPage> {
); );
} }
/// 叠层模式:影评、海报墙各自独立毛玻璃卡片
Widget _buildExtraSectionsOverlay(Movie movie) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 24),
child: Column(
children: [
_buildFrostedExtraItem(
icon: Icons.rate_review_outlined,
title: '影评',
subtitleFuture: context.read<AppProvider>().getMovieReviewCount(movie.id),
emptyText: '暂无影评',
unit: '条影评',
onTap: () => _navigateToReviews(movie),
),
const SizedBox(height: 12),
_buildFrostedExtraItem(
icon: Icons.photo_library_outlined,
title: '海报墙',
subtitleFuture: context.read<AppProvider>().getMoviePosterCount(movie.id),
emptyText: '暂无海报',
unit: '张海报',
onTap: () => _navigateToPosters(movie),
),
],
),
);
}
/// 毛玻璃影评/海报卡片
Widget _buildFrostedExtraItem({
required IconData icon,
required String title,
required Future<int> subtitleFuture,
required String emptyText,
required String unit,
required VoidCallback onTap,
}) {
return ClipRRect(
borderRadius: BorderRadius.circular(12),
child: BackdropFilter(
filter: ui.ImageFilter.blur(sigmaX: 15, sigmaY: 15),
child: Container(
decoration: BoxDecoration(
color: Colors.white.withValues(alpha: 0.08),
borderRadius: BorderRadius.circular(12),
),
child: Material(
color: Colors.transparent,
child: InkWell(
onTap: onTap,
borderRadius: BorderRadius.circular(12),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14),
child: Row(children: [
Icon(icon, size: 20, color: Colors.white.withValues(alpha: 0.7)),
const SizedBox(width: 12),
Expanded(
child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
Text(title, style: const TextStyle(fontSize: 15, fontWeight: FontWeight.w600, color: Colors.white)),
FutureBuilder<int>(
future: subtitleFuture,
builder: (ctx, snap) {
final count = snap.data ?? 0;
return Text(count > 0 ? '$count $unit' : emptyText,
style: TextStyle(fontSize: 12, color: Colors.white.withValues(alpha: 0.5)));
},
),
]),
),
Icon(Icons.chevron_right, size: 16, color: Colors.white.withValues(alpha: 0.3)),
]),
),
),
),
),
),
);
}
Widget _buildExtraSectionItem({ Widget _buildExtraSectionItem({
required IconData icon, required IconData icon,
required String title, required String title,

View File

@@ -1,5 +1,6 @@
import 'dart:math' as math; import 'dart:math' as math;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:fl_chart/fl_chart.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../providers/app_provider.dart'; import '../providers/app_provider.dart';
import '../models/data_models.dart'; import '../models/data_models.dart';
@@ -247,22 +248,29 @@ class _StatisticsPageState extends State<StatisticsPage> {
final avg = allRatings.reduce((a, b) => a + b) / allRatings.length; final avg = allRatings.reduce((a, b) => a + b) / allRatings.length;
// 按区间统计 (0-2, 2-4, 4-6, 6-8, 8-10) // 按 1-10 分统计
final ranges = ['0-2', '2-4', '4-6', '6-8', '8-10']; final counts = List.filled(10, 0);
final counts = [0, 0, 0, 0, 0];
for (final r in allRatings) { for (final r in allRatings) {
if (r < 2) counts[0]++; final idx = (r.round()).clamp(1, 10) - 1;
else if (r < 4) counts[1]++; counts[idx]++;
else if (r < 6) counts[2]++;
else if (r < 8) counts[3]++;
else counts[4]++;
} }
final maxCount = counts.isEmpty ? 1 : counts.reduce((a, b) => a > b ? a : b); final maxCount = counts.reduce((a, b) => a > b ? a : b).toDouble();
if (maxCount == 0) return const SizedBox.shrink();
// 渐变色:低分灰色 → 高分金色
const barColors = [
Color(0xFFBDBDBD), Color(0xFFBDBDBD), // 1-2 灰
Color(0xFFFFCC80), Color(0xFFFFCC80), // 3-4 橙黄
Color(0xFFFFB74D), Color(0xFFFFB74D), // 5-6 橙
Color(0xFFFFA726), Color(0xFFFFA726), // 7-8 深橙
Color(0xFFFFB800), Color(0xFFFFB800), // 9-10 金
];
return _buildCard( return _buildCard(
title: title, title: title,
child: Column( child: Column(
children: [ children: [
// 平均评分
Row( Row(
children: [ children: [
Text('平均评分', style: TextStyle(fontSize: 13, color: colors.onSurface.withValues(alpha: 0.6))), Text('平均评分', style: TextStyle(fontSize: 13, color: colors.onSurface.withValues(alpha: 0.6))),
@@ -271,32 +279,71 @@ class _StatisticsPageState extends State<StatisticsPage> {
Text(' / 10', style: TextStyle(fontSize: 13, color: colors.onSurface.withValues(alpha: 0.3))), Text(' / 10', style: TextStyle(fontSize: 13, color: colors.onSurface.withValues(alpha: 0.3))),
], ],
), ),
const SizedBox(height: 16), const SizedBox(height: 20),
...List.generate(5, (i) => Padding( // 柱状图
padding: const EdgeInsets.only(bottom: 8),
child: Row(
children: [
SizedBox( SizedBox(
width: 28, height: 160,
child: Text(ranges[i], style: TextStyle(fontSize: 11, color: colors.onSurface.withValues(alpha: 0.4))), child: BarChart(
), BarChartData(
const SizedBox(width: 8), alignment: BarChartAlignment.spaceAround,
Expanded( maxY: maxCount * 1.2,
child: ClipRRect( minY: 0,
borderRadius: BorderRadius.circular(2), barTouchData: BarTouchData(
child: LinearProgressIndicator( touchTooltipData: BarTouchTooltipData(
value: maxCount > 0 ? counts[i] / maxCount : 0.0, getTooltipColor: (_) => colors.inverseSurface,
backgroundColor: colors.outlineVariant, getTooltipItem: (group, groupIndex, rod, rodIndex) {
color: colors.primary, return BarTooltipItem(
minHeight: 6, '${group.x + 1}${rod.toY.toInt()}',
TextStyle(color: colors.onInverseSurface, fontSize: 12, fontWeight: FontWeight.w600),
);
},
), ),
), ),
titlesData: FlTitlesData(
show: true,
bottomTitles: AxisTitles(
sideTitles: SideTitles(
showTitles: true,
getTitlesWidget: (value, meta) {
return Padding(
padding: const EdgeInsets.only(top: 6),
child: Text('${value.toInt() + 1}', style: TextStyle(
fontSize: 10, color: colors.onSurface.withValues(alpha: 0.5))),
);
},
reservedSize: 24,
),
),
leftTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)),
topTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)),
rightTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)),
),
borderData: FlBorderData(show: false),
gridData: const FlGridData(show: false),
barGroups: List.generate(10, (i) {
return BarChartGroupData(
x: i,
barRods: [
BarChartRodData(
toY: counts[i].toDouble(),
color: barColors[i],
width: 20,
borderRadius: const BorderRadius.vertical(top: Radius.circular(4)),
backDrawRodData: BackgroundBarChartRodData(
show: true,
toY: maxCount * 1.2,
color: colors.outlineVariant.withValues(alpha: 0.3),
),
), ),
const SizedBox(width: 8),
Text('${counts[i]}', style: TextStyle(fontSize: 12, fontWeight: FontWeight.w600, color: colors.onSurface)),
], ],
);
}),
), ),
)), ),
),
const SizedBox(height: 8),
// 底部标签
Text('星级评分', style: TextStyle(fontSize: 11, color: colors.onSurface.withValues(alpha: 0.3))),
], ],
), ),
); );

View File

@@ -55,6 +55,18 @@ class UserPrefs {
bool get isFirstLaunch => prefs.getBool('isFirstLaunch') ?? true; bool get isFirstLaunch => prefs.getBool('isFirstLaunch') ?? true;
Future<bool> setFirstLaunch(bool value) => prefs.setBool('isFirstLaunch', value); Future<bool> setFirstLaunch(bool value) => prefs.setBool('isFirstLaunch', value);
// ========== 详情页样式 ==========
/// 详情页展示样式: 0=标准(封面顶部), 1=叠层(封面+毛玻璃卡片)
int get detailPageStyle => prefs.getInt('detailPageStyle') ?? 0;
Future<bool> setDetailPageStyle(int value) => prefs.setInt('detailPageStyle', value);
// ========== 封面位置 ==========
/// 获取封面偏移量(-1.0 到 1.00 = 居中)
double getCoverOffset(String itemId) => prefs.getDouble('coverOffset_$itemId') ?? 0.0;
Future<bool> setCoverOffset(String itemId, double value) => prefs.setDouble('coverOffset_$itemId', value);
// ========== 主界面显示设置 ========== // ========== 主界面显示设置 ==========
/// 是否启用底部导航栏滚动隐藏(默认开启) /// 是否启用底部导航栏滚动隐藏(默认开启)

View File

@@ -6,7 +6,7 @@ packages:
description: description:
name: archive name: archive
sha256: cb6a278ef2dbb298455e1a713bda08524a175630ec643a242c399c932a0a1f7d sha256: cb6a278ef2dbb298455e1a713bda08524a175630ec643a242c399c932a0a1f7d
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "3.6.1" version: "3.6.1"
args: args:
@@ -14,7 +14,7 @@ packages:
description: description:
name: args name: args
sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04 sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "2.7.0" version: "2.7.0"
async: async:
@@ -22,7 +22,7 @@ packages:
description: description:
name: async name: async
sha256: e2eb0491ba5ddb6177742d2da23904574082139b07c1e33b8503b9f46f3e1a37 sha256: e2eb0491ba5ddb6177742d2da23904574082139b07c1e33b8503b9f46f3e1a37
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "2.13.1" version: "2.13.1"
boolean_selector: boolean_selector:
@@ -30,7 +30,7 @@ packages:
description: description:
name: boolean_selector name: boolean_selector
sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.2" version: "2.1.2"
characters: characters:
@@ -38,7 +38,7 @@ packages:
description: description:
name: characters name: characters
sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "1.4.1" version: "1.4.1"
checked_yaml: checked_yaml:
@@ -46,7 +46,7 @@ packages:
description: description:
name: checked_yaml name: checked_yaml
sha256: "959525d3162f249993882720d52b7e0c833978df229be20702b33d48d91de70f" sha256: "959525d3162f249993882720d52b7e0c833978df229be20702b33d48d91de70f"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.4" version: "2.0.4"
cli_util: cli_util:
@@ -54,7 +54,7 @@ packages:
description: description:
name: cli_util name: cli_util
sha256: ff6785f7e9e3c38ac98b2fb035701789de90154024a75b6cb926445e83197d1c sha256: ff6785f7e9e3c38ac98b2fb035701789de90154024a75b6cb926445e83197d1c
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "0.4.2" version: "0.4.2"
clock: clock:
@@ -62,7 +62,7 @@ packages:
description: description:
name: clock name: clock
sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "1.1.2" version: "1.1.2"
code_assets: code_assets:
@@ -70,7 +70,7 @@ packages:
description: description:
name: code_assets name: code_assets
sha256: bf394f466ba9205f1812a0433b392d6af280f155f56651eda7c18cc32ed493b8 sha256: bf394f466ba9205f1812a0433b392d6af280f155f56651eda7c18cc32ed493b8
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "1.2.1" version: "1.2.1"
collection: collection:
@@ -78,7 +78,7 @@ packages:
description: description:
name: collection name: collection
sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "1.19.1" version: "1.19.1"
cross_file: cross_file:
@@ -86,7 +86,7 @@ packages:
description: description:
name: cross_file name: cross_file
sha256: "28bb3ae56f117b5aec029d702a90f57d285cd975c3c5c281eaca38dbc47c5937" sha256: "28bb3ae56f117b5aec029d702a90f57d285cd975c3c5c281eaca38dbc47c5937"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "0.3.5+2" version: "0.3.5+2"
crypto: crypto:
@@ -94,7 +94,7 @@ packages:
description: description:
name: crypto name: crypto
sha256: c8ea0233063ba03258fbcf2ca4d6dadfefe14f02fab57702265467a19f27fadf sha256: c8ea0233063ba03258fbcf2ca4d6dadfefe14f02fab57702265467a19f27fadf
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.7" version: "3.0.7"
cupertino_icons: cupertino_icons:
@@ -102,7 +102,7 @@ packages:
description: description:
name: cupertino_icons name: cupertino_icons
sha256: "41e005c33bd814be4d3096aff55b1908d419fde52ca656c8c47719ec745873cd" sha256: "41e005c33bd814be4d3096aff55b1908d419fde52ca656c8c47719ec745873cd"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.9" version: "1.0.9"
equatable: equatable:
@@ -110,7 +110,7 @@ packages:
description: description:
name: equatable name: equatable
sha256: "3e0141505477fd8ad55d6eb4e7776d3fe8430be8e497ccb1521370c3f21a3e2b" sha256: "3e0141505477fd8ad55d6eb4e7776d3fe8430be8e497ccb1521370c3f21a3e2b"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.8" version: "2.0.8"
extended_text_field: extended_text_field:
@@ -118,7 +118,7 @@ packages:
description: description:
name: extended_text_field name: extended_text_field
sha256: "3996195c117c6beb734026a7bc0ba80d7e4e84e4edd4728caa544d8209ab4d7d" sha256: "3996195c117c6beb734026a7bc0ba80d7e4e84e4edd4728caa544d8209ab4d7d"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "16.0.2" version: "16.0.2"
extended_text_library: extended_text_library:
@@ -126,7 +126,7 @@ packages:
description: description:
name: extended_text_library name: extended_text_library
sha256: "13d99f8a10ead472d5e2cf4770d3d047203fe5054b152e9eb5dc692a71befbba" sha256: "13d99f8a10ead472d5e2cf4770d3d047203fe5054b152e9eb5dc692a71befbba"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "12.0.1" version: "12.0.1"
fake_async: fake_async:
@@ -134,7 +134,7 @@ packages:
description: description:
name: fake_async name: fake_async
sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "1.3.3" version: "1.3.3"
ffi: ffi:
@@ -142,7 +142,7 @@ packages:
description: description:
name: ffi name: ffi
sha256: "6d7fd89431262d8f3125e81b50d3847a091d846eafcd4fdb88dd06f36d705a45" sha256: "6d7fd89431262d8f3125e81b50d3847a091d846eafcd4fdb88dd06f36d705a45"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "2.2.0" version: "2.2.0"
file: file:
@@ -150,7 +150,7 @@ packages:
description: description:
name: file name: file
sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "7.0.1" version: "7.0.1"
file_picker: file_picker:
@@ -158,7 +158,7 @@ packages:
description: description:
name: file_picker name: file_picker
sha256: ab13ae8ef5580a411c458d6207b6774a6c237d77ac37011b13994879f68a8810 sha256: ab13ae8ef5580a411c458d6207b6774a6c237d77ac37011b13994879f68a8810
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "8.3.7" version: "8.3.7"
file_selector_linux: file_selector_linux:
@@ -166,7 +166,7 @@ packages:
description: description:
name: file_selector_linux name: file_selector_linux
sha256: "2567f398e06ac72dcf2e98a0c95df2a9edd03c2c2e0cacd4780f20cdf56263a0" sha256: "2567f398e06ac72dcf2e98a0c95df2a9edd03c2c2e0cacd4780f20cdf56263a0"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "0.9.4" version: "0.9.4"
file_selector_macos: file_selector_macos:
@@ -174,7 +174,7 @@ packages:
description: description:
name: file_selector_macos name: file_selector_macos
sha256: "5e0bbe9c312416f1787a68259ea1505b52f258c587f12920422671807c4d618a" sha256: "5e0bbe9c312416f1787a68259ea1505b52f258c587f12920422671807c4d618a"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "0.9.5" version: "0.9.5"
file_selector_platform_interface: file_selector_platform_interface:
@@ -182,7 +182,7 @@ packages:
description: description:
name: file_selector_platform_interface name: file_selector_platform_interface
sha256: "35e0bd61ebcdb91a3505813b055b09b79dfdc7d0aee9c09a7ba59ae4bb13dc85" sha256: "35e0bd61ebcdb91a3505813b055b09b79dfdc7d0aee9c09a7ba59ae4bb13dc85"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "2.7.0" version: "2.7.0"
file_selector_windows: file_selector_windows:
@@ -190,7 +190,7 @@ packages:
description: description:
name: file_selector_windows name: file_selector_windows
sha256: "62197474ae75893a62df75939c777763d39c2bc5f73ce5b88497208bc269abfd" sha256: "62197474ae75893a62df75939c777763d39c2bc5f73ce5b88497208bc269abfd"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "0.9.3+5" version: "0.9.3+5"
fixnum: fixnum:
@@ -198,7 +198,7 @@ packages:
description: description:
name: fixnum name: fixnum
sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "1.1.1" version: "1.1.1"
fl_chart: fl_chart:
@@ -206,7 +206,7 @@ packages:
description: description:
name: fl_chart name: fl_chart
sha256: "74959b99b92b9eebeed1a4049426fd67c4abc3c5a0f4d12e2877097d6a11ae08" sha256: "74959b99b92b9eebeed1a4049426fd67c4abc3c5a0f4d12e2877097d6a11ae08"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "0.69.2" version: "0.69.2"
flutter: flutter:
@@ -219,7 +219,7 @@ packages:
description: description:
name: flutter_launcher_icons name: flutter_launcher_icons
sha256: "526faf84284b86a4cb36d20a5e45147747b7563d921373d4ee0559c54fcdbcea" sha256: "526faf84284b86a4cb36d20a5e45147747b7563d921373d4ee0559c54fcdbcea"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "0.13.1" version: "0.13.1"
flutter_lints: flutter_lints:
@@ -227,7 +227,7 @@ packages:
description: description:
name: flutter_lints name: flutter_lints
sha256: "3f41d009ba7172d5ff9be5f6e6e6abb4300e263aab8866d2a0842ed2a70f8f0c" sha256: "3f41d009ba7172d5ff9be5f6e6e6abb4300e263aab8866d2a0842ed2a70f8f0c"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "4.0.0" version: "4.0.0"
flutter_localizations: flutter_localizations:
@@ -240,7 +240,7 @@ packages:
description: description:
name: flutter_markdown_plus name: flutter_markdown_plus
sha256: "039177906850278e8fb1cd364115ee0a46281135932fa8ecea8455522166d2de" sha256: "039177906850278e8fb1cd364115ee0a46281135932fa8ecea8455522166d2de"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.7" version: "1.0.7"
flutter_plugin_android_lifecycle: flutter_plugin_android_lifecycle:
@@ -248,7 +248,7 @@ packages:
description: description:
name: flutter_plugin_android_lifecycle name: flutter_plugin_android_lifecycle
sha256: "3854fe5e3bff0b113c658f260b90c95dea17c92db0f2addeac2e343dd9969785" sha256: "3854fe5e3bff0b113c658f260b90c95dea17c92db0f2addeac2e343dd9969785"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.35" version: "2.0.35"
flutter_staggered_grid_view: flutter_staggered_grid_view:
@@ -256,7 +256,7 @@ packages:
description: description:
name: flutter_staggered_grid_view name: flutter_staggered_grid_view
sha256: "19e7abb550c96fbfeb546b23f3ff356ee7c59a019a651f8f102a4ba9b7349395" sha256: "19e7abb550c96fbfeb546b23f3ff356ee7c59a019a651f8f102a4ba9b7349395"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "0.7.0" version: "0.7.0"
flutter_test: flutter_test:
@@ -274,7 +274,7 @@ packages:
description: description:
name: hooks name: hooks
sha256: "9a62a50b50b769a737bc0a8ff381f333529df3ab746b2f6b02e83760231455ba" sha256: "9a62a50b50b769a737bc0a8ff381f333529df3ab746b2f6b02e83760231455ba"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.2" version: "2.0.2"
http: http:
@@ -282,7 +282,7 @@ packages:
description: description:
name: http name: http
sha256: "87721a4a50b19c7f1d49001e51409bddc46303966ce89a65af4f4e6004896412" sha256: "87721a4a50b19c7f1d49001e51409bddc46303966ce89a65af4f4e6004896412"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "1.6.0" version: "1.6.0"
http_parser: http_parser:
@@ -290,7 +290,7 @@ packages:
description: description:
name: http_parser name: http_parser
sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "4.1.2" version: "4.1.2"
image: image:
@@ -298,7 +298,7 @@ packages:
description: description:
name: image name: image
sha256: f31d52537dc417fdcde36088fdf11d191026fd5e4fae742491ebd40e5a8bea7d sha256: f31d52537dc417fdcde36088fdf11d191026fd5e4fae742491ebd40e5a8bea7d
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "4.3.0" version: "4.3.0"
image_picker: image_picker:
@@ -306,7 +306,7 @@ packages:
description: description:
name: image_picker name: image_picker
sha256: "91c025426c2881c551100bce834e201c835a170151545f58d17da5180ca7d9ac" sha256: "91c025426c2881c551100bce834e201c835a170151545f58d17da5180ca7d9ac"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "1.2.2" version: "1.2.2"
image_picker_android: image_picker_android:
@@ -314,7 +314,7 @@ packages:
description: description:
name: image_picker_android name: image_picker_android
sha256: d5b3e1774af29c9ab00103afb0d4614070f924d2e0057ac867ec98800114793f sha256: d5b3e1774af29c9ab00103afb0d4614070f924d2e0057ac867ec98800114793f
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "0.8.13+17" version: "0.8.13+17"
image_picker_for_web: image_picker_for_web:
@@ -322,7 +322,7 @@ packages:
description: description:
name: image_picker_for_web name: image_picker_for_web
sha256: "66257a3191ab360d23a55c8241c91a6e329d31e94efa7be9cf7a212e65850214" sha256: "66257a3191ab360d23a55c8241c91a6e329d31e94efa7be9cf7a212e65850214"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "3.1.1" version: "3.1.1"
image_picker_ios: image_picker_ios:
@@ -330,7 +330,7 @@ packages:
description: description:
name: image_picker_ios name: image_picker_ios
sha256: b9c4a438a9ff4f60808c9cf0039b93a42bb6c2211ef6ebb647394b2b3fa84588 sha256: b9c4a438a9ff4f60808c9cf0039b93a42bb6c2211ef6ebb647394b2b3fa84588
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "0.8.13+6" version: "0.8.13+6"
image_picker_linux: image_picker_linux:
@@ -338,7 +338,7 @@ packages:
description: description:
name: image_picker_linux name: image_picker_linux
sha256: "1f81c5f2046b9ab724f85523e4af65be1d47b038160a8c8deed909762c308ed4" sha256: "1f81c5f2046b9ab724f85523e4af65be1d47b038160a8c8deed909762c308ed4"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "0.2.2" version: "0.2.2"
image_picker_macos: image_picker_macos:
@@ -346,7 +346,7 @@ packages:
description: description:
name: image_picker_macos name: image_picker_macos
sha256: "86f0f15a309de7e1a552c12df9ce5b59fe927e71385329355aec4776c6a8ec91" sha256: "86f0f15a309de7e1a552c12df9ce5b59fe927e71385329355aec4776c6a8ec91"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "0.2.2+1" version: "0.2.2+1"
image_picker_platform_interface: image_picker_platform_interface:
@@ -354,7 +354,7 @@ packages:
description: description:
name: image_picker_platform_interface name: image_picker_platform_interface
sha256: "567e056716333a1647c64bb6bd873cff7622233a5c3f694be28a583d4715690c" sha256: "567e056716333a1647c64bb6bd873cff7622233a5c3f694be28a583d4715690c"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "2.11.1" version: "2.11.1"
image_picker_windows: image_picker_windows:
@@ -362,7 +362,7 @@ packages:
description: description:
name: image_picker_windows name: image_picker_windows
sha256: d248c86554a72b5495a31c56f060cf73a41c7ff541689327b1a7dbccc33adfae sha256: d248c86554a72b5495a31c56f060cf73a41c7ff541689327b1a7dbccc33adfae
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "0.2.2" version: "0.2.2"
intl: intl:
@@ -370,7 +370,7 @@ packages:
description: description:
name: intl name: intl
sha256: "3df61194eb431efc39c4ceba583b95633a403f46c9fd341e550ce0bfa50e9aa5" sha256: "3df61194eb431efc39c4ceba583b95633a403f46c9fd341e550ce0bfa50e9aa5"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "0.20.2" version: "0.20.2"
jni: jni:
@@ -378,7 +378,7 @@ packages:
description: description:
name: jni name: jni
sha256: c2230682d5bc2362c1c9e8d3c7f406d9cbba23ab3f2e203a025dd47e0fb2e68f sha256: c2230682d5bc2362c1c9e8d3c7f406d9cbba23ab3f2e203a025dd47e0fb2e68f
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.0" version: "1.0.0"
jni_flutter: jni_flutter:
@@ -386,7 +386,7 @@ packages:
description: description:
name: jni_flutter name: jni_flutter
sha256: "8b59e590786050b1cd866677dddaf76b1ade5e7bc751abe04b86e84d379d3ba6" sha256: "8b59e590786050b1cd866677dddaf76b1ade5e7bc751abe04b86e84d379d3ba6"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.1" version: "1.0.1"
json_annotation: json_annotation:
@@ -394,7 +394,7 @@ packages:
description: description:
name: json_annotation name: json_annotation
sha256: "2a743920d81b7910627f68ee2c9ac1fc0bfee32b9fc3403587d7c6791ca12f80" sha256: "2a743920d81b7910627f68ee2c9ac1fc0bfee32b9fc3403587d7c6791ca12f80"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "4.12.0" version: "4.12.0"
leak_tracker: leak_tracker:
@@ -402,7 +402,7 @@ packages:
description: description:
name: leak_tracker name: leak_tracker
sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de" sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "11.0.2" version: "11.0.2"
leak_tracker_flutter_testing: leak_tracker_flutter_testing:
@@ -410,7 +410,7 @@ packages:
description: description:
name: leak_tracker_flutter_testing name: leak_tracker_flutter_testing
sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.10" version: "3.0.10"
leak_tracker_testing: leak_tracker_testing:
@@ -418,7 +418,7 @@ packages:
description: description:
name: leak_tracker_testing name: leak_tracker_testing
sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.2" version: "3.0.2"
lints: lints:
@@ -426,7 +426,7 @@ packages:
description: description:
name: lints name: lints
sha256: "976c774dd944a42e83e2467f4cc670daef7eed6295b10b36ae8c85bcbf828235" sha256: "976c774dd944a42e83e2467f4cc670daef7eed6295b10b36ae8c85bcbf828235"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "4.0.0" version: "4.0.0"
logging: logging:
@@ -434,7 +434,7 @@ packages:
description: description:
name: logging name: logging
sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61 sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "1.3.0" version: "1.3.0"
markdown: markdown:
@@ -442,7 +442,7 @@ packages:
description: description:
name: markdown name: markdown
sha256: ee85086ad7698b42522c6ad42fe195f1b9898e4d974a1af4576c1a3a176cada9 sha256: ee85086ad7698b42522c6ad42fe195f1b9898e4d974a1af4576c1a3a176cada9
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "7.3.1" version: "7.3.1"
matcher: matcher:
@@ -450,7 +450,7 @@ packages:
description: description:
name: matcher name: matcher
sha256: dc0b7dc7651697ea4ff3e69ef44b0407ea32c487a39fff6a4004fa585e901861 sha256: dc0b7dc7651697ea4ff3e69ef44b0407ea32c487a39fff6a4004fa585e901861
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "0.12.19" version: "0.12.19"
material_color_utilities: material_color_utilities:
@@ -458,7 +458,7 @@ packages:
description: description:
name: material_color_utilities name: material_color_utilities
sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b" sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "0.13.0" version: "0.13.0"
meta: meta:
@@ -466,7 +466,7 @@ packages:
description: description:
name: meta name: meta
sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394" sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "1.17.0" version: "1.17.0"
mime: mime:
@@ -474,7 +474,7 @@ packages:
description: description:
name: mime name: mime
sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6" sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.0" version: "2.0.0"
nested: nested:
@@ -482,7 +482,7 @@ packages:
description: description:
name: nested name: nested
sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.0" version: "1.0.0"
objective_c: objective_c:
@@ -490,7 +490,7 @@ packages:
description: description:
name: objective_c name: objective_c
sha256: "6cb691c686fa2838c6deb34980d426145c2a5d537491cb83d463c33cdbc726ed" sha256: "6cb691c686fa2838c6deb34980d426145c2a5d537491cb83d463c33cdbc726ed"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "9.4.1" version: "9.4.1"
package_config: package_config:
@@ -498,7 +498,7 @@ packages:
description: description:
name: package_config name: package_config
sha256: f096c55ebb7deb7e384101542bfba8c52696c1b56fca2eb62827989ef2353bbc sha256: f096c55ebb7deb7e384101542bfba8c52696c1b56fca2eb62827989ef2353bbc
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "2.2.0" version: "2.2.0"
package_info_plus: package_info_plus:
@@ -506,7 +506,7 @@ packages:
description: description:
name: package_info_plus name: package_info_plus
sha256: "16eee997588c60225bda0488b6dcfac69280a6b7a3cf02c741895dd370a02968" sha256: "16eee997588c60225bda0488b6dcfac69280a6b7a3cf02c741895dd370a02968"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "8.3.1" version: "8.3.1"
package_info_plus_platform_interface: package_info_plus_platform_interface:
@@ -514,7 +514,7 @@ packages:
description: description:
name: package_info_plus_platform_interface name: package_info_plus_platform_interface
sha256: "202a487f08836a592a6bd4f901ac69b3a8f146af552bbd14407b6b41e1c3f086" sha256: "202a487f08836a592a6bd4f901ac69b3a8f146af552bbd14407b6b41e1c3f086"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "3.2.1" version: "3.2.1"
path: path:
@@ -522,7 +522,7 @@ packages:
description: description:
name: path name: path
sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "1.9.1" version: "1.9.1"
path_provider: path_provider:
@@ -530,7 +530,7 @@ packages:
description: description:
name: path_provider name: path_provider
sha256: a7f4874f987173da295a61c181b8ee71dab59b332a486b391babf26a1b884825 sha256: a7f4874f987173da295a61c181b8ee71dab59b332a486b391babf26a1b884825
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.6" version: "2.1.6"
path_provider_android: path_provider_android:
@@ -538,7 +538,7 @@ packages:
description: description:
name: path_provider_android name: path_provider_android
sha256: "69cbd515a62b94d32a7944f086b2f82b4ac40a1d45bebfc00813a430ab2dabcd" sha256: "69cbd515a62b94d32a7944f086b2f82b4ac40a1d45bebfc00813a430ab2dabcd"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.1" version: "2.3.1"
path_provider_foundation: path_provider_foundation:
@@ -546,7 +546,7 @@ packages:
description: description:
name: path_provider_foundation name: path_provider_foundation
sha256: "2a376b7d6392d80cd3705782d2caa734ca4727776db0b6ec36ef3f1855197699" sha256: "2a376b7d6392d80cd3705782d2caa734ca4727776db0b6ec36ef3f1855197699"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "2.6.0" version: "2.6.0"
path_provider_linux: path_provider_linux:
@@ -554,7 +554,7 @@ packages:
description: description:
name: path_provider_linux name: path_provider_linux
sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "2.2.1" version: "2.2.1"
path_provider_platform_interface: path_provider_platform_interface:
@@ -562,7 +562,7 @@ packages:
description: description:
name: path_provider_platform_interface name: path_provider_platform_interface
sha256: "484838772624c3a4b94f1e44a3e19897fee738f2d5c4ce448443b0417f7c9dda" sha256: "484838772624c3a4b94f1e44a3e19897fee738f2d5c4ce448443b0417f7c9dda"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.3" version: "2.1.3"
path_provider_windows: path_provider_windows:
@@ -570,7 +570,7 @@ packages:
description: description:
name: path_provider_windows name: path_provider_windows
sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7 sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.0" version: "2.3.0"
permission_handler: permission_handler:
@@ -578,7 +578,7 @@ packages:
description: description:
name: permission_handler name: permission_handler
sha256: "59adad729136f01ea9e35a48f5d1395e25cba6cea552249ddbe9cf950f5d7849" sha256: "59adad729136f01ea9e35a48f5d1395e25cba6cea552249ddbe9cf950f5d7849"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "11.4.0" version: "11.4.0"
permission_handler_android: permission_handler_android:
@@ -586,7 +586,7 @@ packages:
description: description:
name: permission_handler_android name: permission_handler_android
sha256: d3971dcdd76182a0c198c096b5db2f0884b0d4196723d21a866fc4cdea057ebc sha256: d3971dcdd76182a0c198c096b5db2f0884b0d4196723d21a866fc4cdea057ebc
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "12.1.0" version: "12.1.0"
permission_handler_apple: permission_handler_apple:
@@ -594,7 +594,7 @@ packages:
description: description:
name: permission_handler_apple name: permission_handler_apple
sha256: "79dfa1df734798aa3cfdad166d3a3698c206d8813de13516ea1071b5d7e2f420" sha256: "79dfa1df734798aa3cfdad166d3a3698c206d8813de13516ea1071b5d7e2f420"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "9.4.10" version: "9.4.10"
permission_handler_html: permission_handler_html:
@@ -602,7 +602,7 @@ packages:
description: description:
name: permission_handler_html name: permission_handler_html
sha256: "38f000e83355abb3392140f6bc3030660cfaef189e1f87824facb76300b4ff24" sha256: "38f000e83355abb3392140f6bc3030660cfaef189e1f87824facb76300b4ff24"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "0.1.3+5" version: "0.1.3+5"
permission_handler_platform_interface: permission_handler_platform_interface:
@@ -610,7 +610,7 @@ packages:
description: description:
name: permission_handler_platform_interface name: permission_handler_platform_interface
sha256: eb99b295153abce5d683cac8c02e22faab63e50679b937fa1bf67d58bb282878 sha256: eb99b295153abce5d683cac8c02e22faab63e50679b937fa1bf67d58bb282878
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "4.3.0" version: "4.3.0"
permission_handler_windows: permission_handler_windows:
@@ -618,7 +618,7 @@ packages:
description: description:
name: permission_handler_windows name: permission_handler_windows
sha256: "1a790728016f79a41216d88672dbc5df30e686e811ad4e698bfc51f76ad91f1e" sha256: "1a790728016f79a41216d88672dbc5df30e686e811ad4e698bfc51f76ad91f1e"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "0.2.1" version: "0.2.1"
petitparser: petitparser:
@@ -626,7 +626,7 @@ packages:
description: description:
name: petitparser name: petitparser
sha256: "91bd59303e9f769f108f8df05e371341b15d59e995e6806aefab827b58336675" sha256: "91bd59303e9f769f108f8df05e371341b15d59e995e6806aefab827b58336675"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "7.0.2" version: "7.0.2"
platform: platform:
@@ -634,7 +634,7 @@ packages:
description: description:
name: platform name: platform
sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "3.1.6" version: "3.1.6"
plugin_platform_interface: plugin_platform_interface:
@@ -642,7 +642,7 @@ packages:
description: description:
name: plugin_platform_interface name: plugin_platform_interface
sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.8" version: "2.1.8"
provider: provider:
@@ -650,7 +650,7 @@ packages:
description: description:
name: provider name: provider
sha256: "4e82183fa20e5ca25703ead7e05de9e4cceed1fbd1eadc1ac3cb6f565a09f272" sha256: "4e82183fa20e5ca25703ead7e05de9e4cceed1fbd1eadc1ac3cb6f565a09f272"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "6.1.5+1" version: "6.1.5+1"
pub_semver: pub_semver:
@@ -658,7 +658,7 @@ packages:
description: description:
name: pub_semver name: pub_semver
sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585" sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "2.2.0" version: "2.2.0"
record_use: record_use:
@@ -666,7 +666,7 @@ packages:
description: description:
name: record_use name: record_use
sha256: "2551bd8eecfe95d14ae75f6021ad0248be5c27f138c2ec12fcb52b500b3ba1ed" sha256: "2551bd8eecfe95d14ae75f6021ad0248be5c27f138c2ec12fcb52b500b3ba1ed"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "0.6.0" version: "0.6.0"
share_plus: share_plus:
@@ -674,7 +674,7 @@ packages:
description: description:
name: share_plus name: share_plus
sha256: fce43200aa03ea87b91ce4c3ac79f0cecd52e2a7a56c7a4185023c271fbfa6da sha256: fce43200aa03ea87b91ce4c3ac79f0cecd52e2a7a56c7a4185023c271fbfa6da
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "10.1.4" version: "10.1.4"
share_plus_platform_interface: share_plus_platform_interface:
@@ -682,7 +682,7 @@ packages:
description: description:
name: share_plus_platform_interface name: share_plus_platform_interface
sha256: cc012a23fc2d479854e6c80150696c4a5f5bb62cb89af4de1c505cf78d0a5d0b sha256: cc012a23fc2d479854e6c80150696c4a5f5bb62cb89af4de1c505cf78d0a5d0b
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "5.0.2" version: "5.0.2"
shared_preferences: shared_preferences:
@@ -690,7 +690,7 @@ packages:
description: description:
name: shared_preferences name: shared_preferences
sha256: c3025c5534b01739267eb7d76959bbc25a6d10f6988e1c2a3036940133dd10bf sha256: c3025c5534b01739267eb7d76959bbc25a6d10f6988e1c2a3036940133dd10bf
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "2.5.5" version: "2.5.5"
shared_preferences_android: shared_preferences_android:
@@ -698,7 +698,7 @@ packages:
description: description:
name: shared_preferences_android name: shared_preferences_android
sha256: e8d4762b1e2e8578fc4d0fd548cebf24afd24f49719c08974df92834565e2c53 sha256: e8d4762b1e2e8578fc4d0fd548cebf24afd24f49719c08974df92834565e2c53
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "2.4.23" version: "2.4.23"
shared_preferences_foundation: shared_preferences_foundation:
@@ -706,7 +706,7 @@ packages:
description: description:
name: shared_preferences_foundation name: shared_preferences_foundation
sha256: "4e7eaffc2b17ba398759f1151415869a34771ba11ebbccd1b0145472a619a64f" sha256: "4e7eaffc2b17ba398759f1151415869a34771ba11ebbccd1b0145472a619a64f"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "2.5.6" version: "2.5.6"
shared_preferences_linux: shared_preferences_linux:
@@ -714,7 +714,7 @@ packages:
description: description:
name: shared_preferences_linux name: shared_preferences_linux
sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f" sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "2.4.1" version: "2.4.1"
shared_preferences_platform_interface: shared_preferences_platform_interface:
@@ -722,7 +722,7 @@ packages:
description: description:
name: shared_preferences_platform_interface name: shared_preferences_platform_interface
sha256: "649dc798a33931919ea356c4305c2d1f81619ea6e92244070b520187b5140ef9" sha256: "649dc798a33931919ea356c4305c2d1f81619ea6e92244070b520187b5140ef9"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "2.4.2" version: "2.4.2"
shared_preferences_web: shared_preferences_web:
@@ -730,7 +730,7 @@ packages:
description: description:
name: shared_preferences_web name: shared_preferences_web
sha256: c49bd060261c9a3f0ff445892695d6212ff603ef3115edbb448509d407600019 sha256: c49bd060261c9a3f0ff445892695d6212ff603ef3115edbb448509d407600019
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "2.4.3" version: "2.4.3"
shared_preferences_windows: shared_preferences_windows:
@@ -738,7 +738,7 @@ packages:
description: description:
name: shared_preferences_windows name: shared_preferences_windows
sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1" sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "2.4.1" version: "2.4.1"
sky_engine: sky_engine:
@@ -751,7 +751,7 @@ packages:
description: description:
name: source_span name: source_span
sha256: "56a02f1f4cd1a2d96303c0144c93bd6d909eea6bee6bf5a0e0b685edbd4c47ab" sha256: "56a02f1f4cd1a2d96303c0144c93bd6d909eea6bee6bf5a0e0b685edbd4c47ab"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "1.10.2" version: "1.10.2"
sqflite: sqflite:
@@ -759,7 +759,7 @@ packages:
description: description:
name: sqflite name: sqflite
sha256: "564cfed0746fe53140c23b70b308e045c3b31f17778f2f326ccb7d804ea0250a" sha256: "564cfed0746fe53140c23b70b308e045c3b31f17778f2f326ccb7d804ea0250a"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "2.4.2+1" version: "2.4.2+1"
sqflite_android: sqflite_android:
@@ -767,7 +767,7 @@ packages:
description: description:
name: sqflite_android name: sqflite_android
sha256: "881e28efdcc9950fd8e9bb42713dcf1103e62a2e7168f23c9338d82db13dec40" sha256: "881e28efdcc9950fd8e9bb42713dcf1103e62a2e7168f23c9338d82db13dec40"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "2.4.2+3" version: "2.4.2+3"
sqflite_common: sqflite_common:
@@ -775,7 +775,7 @@ packages:
description: description:
name: sqflite_common name: sqflite_common
sha256: "1581ffbf7a0e333b380d6a30737d78516b826cb35beb7fb0bf8a3ea0c678b465" sha256: "1581ffbf7a0e333b380d6a30737d78516b826cb35beb7fb0bf8a3ea0c678b465"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "2.5.8" version: "2.5.8"
sqflite_darwin: sqflite_darwin:
@@ -783,7 +783,7 @@ packages:
description: description:
name: sqflite_darwin name: sqflite_darwin
sha256: "279832e5cde3fe99e8571879498c9211f3ca6391b0d818df4e17d9fff5c6ccb3" sha256: "279832e5cde3fe99e8571879498c9211f3ca6391b0d818df4e17d9fff5c6ccb3"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "2.4.2" version: "2.4.2"
sqflite_platform_interface: sqflite_platform_interface:
@@ -791,7 +791,7 @@ packages:
description: description:
name: sqflite_platform_interface name: sqflite_platform_interface
sha256: "8dd4515c7bdcae0a785b0062859336de775e8c65db81ae33dd5445f35be61920" sha256: "8dd4515c7bdcae0a785b0062859336de775e8c65db81ae33dd5445f35be61920"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "2.4.0" version: "2.4.0"
stack_trace: stack_trace:
@@ -799,7 +799,7 @@ packages:
description: description:
name: stack_trace name: stack_trace
sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "1.12.1" version: "1.12.1"
stream_channel: stream_channel:
@@ -807,7 +807,7 @@ packages:
description: description:
name: stream_channel name: stream_channel
sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.4" version: "2.1.4"
string_scanner: string_scanner:
@@ -815,7 +815,7 @@ packages:
description: description:
name: string_scanner name: string_scanner
sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "1.4.1" version: "1.4.1"
synchronized: synchronized:
@@ -823,7 +823,7 @@ packages:
description: description:
name: synchronized name: synchronized
sha256: "63896c27e81b28f8cb4e69ead0d3e8f03f1d1e5fc531a3e579cabed6a2c7c9e5" sha256: "63896c27e81b28f8cb4e69ead0d3e8f03f1d1e5fc531a3e579cabed6a2c7c9e5"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "3.4.0+1" version: "3.4.0+1"
term_glyph: term_glyph:
@@ -831,7 +831,7 @@ packages:
description: description:
name: term_glyph name: term_glyph
sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "1.2.2" version: "1.2.2"
test_api: test_api:
@@ -839,7 +839,7 @@ packages:
description: description:
name: test_api name: test_api
sha256: "8161c84903fd860b26bfdefb7963b3f0b68fee7adea0f59ef805ecca346f0c7a" sha256: "8161c84903fd860b26bfdefb7963b3f0b68fee7adea0f59ef805ecca346f0c7a"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "0.7.10" version: "0.7.10"
typed_data: typed_data:
@@ -847,7 +847,7 @@ packages:
description: description:
name: typed_data name: typed_data
sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "1.4.0" version: "1.4.0"
url_launcher: url_launcher:
@@ -855,7 +855,7 @@ packages:
description: description:
name: url_launcher name: url_launcher
sha256: f6a7e5c4835bb4e3026a04793a4199ca2d14c739ec378fdfe23fc8075d0439f8 sha256: f6a7e5c4835bb4e3026a04793a4199ca2d14c739ec378fdfe23fc8075d0439f8
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "6.3.2" version: "6.3.2"
url_launcher_android: url_launcher_android:
@@ -863,7 +863,7 @@ packages:
description: description:
name: url_launcher_android name: url_launcher_android
sha256: "17bc677f0b301615530dd1d67e0a9828cafa2d0b6b6eae4cd3679b7eac4a273c" sha256: "17bc677f0b301615530dd1d67e0a9828cafa2d0b6b6eae4cd3679b7eac4a273c"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "6.3.30" version: "6.3.30"
url_launcher_ios: url_launcher_ios:
@@ -871,7 +871,7 @@ packages:
description: description:
name: url_launcher_ios name: url_launcher_ios
sha256: "580fe5dfb51671ae38191d316e027f6b76272b026370708c2d898799750a02b0" sha256: "580fe5dfb51671ae38191d316e027f6b76272b026370708c2d898799750a02b0"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "6.4.1" version: "6.4.1"
url_launcher_linux: url_launcher_linux:
@@ -879,7 +879,7 @@ packages:
description: description:
name: url_launcher_linux name: url_launcher_linux
sha256: d5e14138b3bc193a0f63c10a53c94b91d399df0512b1f29b94a043db7482384a sha256: d5e14138b3bc193a0f63c10a53c94b91d399df0512b1f29b94a043db7482384a
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "3.2.2" version: "3.2.2"
url_launcher_macos: url_launcher_macos:
@@ -887,7 +887,7 @@ packages:
description: description:
name: url_launcher_macos name: url_launcher_macos
sha256: "368adf46f71ad3c21b8f06614adb38346f193f3a59ba8fe9a2fd74133070ba18" sha256: "368adf46f71ad3c21b8f06614adb38346f193f3a59ba8fe9a2fd74133070ba18"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "3.2.5" version: "3.2.5"
url_launcher_platform_interface: url_launcher_platform_interface:
@@ -895,7 +895,7 @@ packages:
description: description:
name: url_launcher_platform_interface name: url_launcher_platform_interface
sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029" sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.2" version: "2.3.2"
url_launcher_web: url_launcher_web:
@@ -903,7 +903,7 @@ packages:
description: description:
name: url_launcher_web name: url_launcher_web
sha256: "85c81589622fbc87c1c683aaea164d3604a7777495a79d91e39ffcdec39ddb34" sha256: "85c81589622fbc87c1c683aaea164d3604a7777495a79d91e39ffcdec39ddb34"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "2.4.3" version: "2.4.3"
url_launcher_windows: url_launcher_windows:
@@ -911,7 +911,7 @@ packages:
description: description:
name: url_launcher_windows name: url_launcher_windows
sha256: "712c70ab1b99744ff066053cbe3e80c73332b38d46e5e945c98689b2e66fc15f" sha256: "712c70ab1b99744ff066053cbe3e80c73332b38d46e5e945c98689b2e66fc15f"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "3.1.5" version: "3.1.5"
uuid: uuid:
@@ -919,7 +919,7 @@ packages:
description: description:
name: uuid name: uuid
sha256: "1fef9e8e11e2991bb773070d4656b7bd5d850967a2456cfc83cf47925ba79489" sha256: "1fef9e8e11e2991bb773070d4656b7bd5d850967a2456cfc83cf47925ba79489"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "4.5.3" version: "4.5.3"
vector_math: vector_math:
@@ -927,7 +927,7 @@ packages:
description: description:
name: vector_math name: vector_math
sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "2.2.0" version: "2.2.0"
vm_service: vm_service:
@@ -935,7 +935,7 @@ packages:
description: description:
name: vm_service name: vm_service
sha256: "0016aef94fc66495ac78af5859181e3f3bf2026bd8eecc72b9565601e19ab360" sha256: "0016aef94fc66495ac78af5859181e3f3bf2026bd8eecc72b9565601e19ab360"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "15.2.0" version: "15.2.0"
web: web:
@@ -943,7 +943,7 @@ packages:
description: description:
name: web name: web
sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a" sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "1.1.1" version: "1.1.1"
webview_flutter: webview_flutter:
@@ -951,7 +951,7 @@ packages:
description: description:
name: webview_flutter name: webview_flutter
sha256: e4d3474277c5043f5f3100ed27d94ad693abfd5c602b0221c719a4497e4ba1e4 sha256: e4d3474277c5043f5f3100ed27d94ad693abfd5c602b0221c719a4497e4ba1e4
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "4.14.0" version: "4.14.0"
webview_flutter_android: webview_flutter_android:
@@ -959,7 +959,7 @@ packages:
description: description:
name: webview_flutter_android name: webview_flutter_android
sha256: ad5182eff9a550925330cb9f0cb038eddfdd5712aba8b77aa0f0400e50f6e688 sha256: ad5182eff9a550925330cb9f0cb038eddfdd5712aba8b77aa0f0400e50f6e688
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "4.12.0" version: "4.12.0"
webview_flutter_platform_interface: webview_flutter_platform_interface:
@@ -967,7 +967,7 @@ packages:
description: description:
name: webview_flutter_platform_interface name: webview_flutter_platform_interface
sha256: "1221c1b12f5278791042f2ec2841743784cf25c5a644e23d6680e5d718824f04" sha256: "1221c1b12f5278791042f2ec2841743784cf25c5a644e23d6680e5d718824f04"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "2.15.1" version: "2.15.1"
webview_flutter_wkwebview: webview_flutter_wkwebview:
@@ -975,7 +975,7 @@ packages:
description: description:
name: webview_flutter_wkwebview name: webview_flutter_wkwebview
sha256: "82648217f537573e1ca9ae9952d3eacedca6ab5aee69dc84445fc763766dcea2" sha256: "82648217f537573e1ca9ae9952d3eacedca6ab5aee69dc84445fc763766dcea2"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "3.25.1" version: "3.25.1"
win32: win32:
@@ -983,7 +983,7 @@ packages:
description: description:
name: win32 name: win32
sha256: d7cb55e04cd34096cd3a79b3330245f54cb96a370a1c27adb3c84b917de8b08e sha256: d7cb55e04cd34096cd3a79b3330245f54cb96a370a1c27adb3c84b917de8b08e
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "5.15.0" version: "5.15.0"
xdg_directories: xdg_directories:
@@ -991,7 +991,7 @@ packages:
description: description:
name: xdg_directories name: xdg_directories
sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15" sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "1.1.0" version: "1.1.0"
xml: xml:
@@ -999,7 +999,7 @@ packages:
description: description:
name: xml name: xml
sha256: "971043b3a0d3da28727e40ed3e0b5d18b742fa5a68665cca88e74b7876d5e025" sha256: "971043b3a0d3da28727e40ed3e0b5d18b742fa5a68665cca88e74b7876d5e025"
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "6.6.1" version: "6.6.1"
yaml: yaml:
@@ -1007,7 +1007,7 @@ packages:
description: description:
name: yaml name: yaml
sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce
url: "https://pub.flutter-io.cn" url: "https://pub.dev"
source: hosted source: hosted
version: "3.1.3" version: "3.1.3"
sdks: sdks:

View File

@@ -1,7 +1,7 @@
name: mooknote name: mooknote
description: "app for tracking movies, books, and notes" description: "app for tracking movies, books, and notes"
publish_to: 'none' publish_to: 'none'
version: 0.1.9 version: 0.2.0
environment: environment:
sdk: ^3.5.0 sdk: ^3.5.0