♻️ Refactored drawer nav

This commit is contained in:
LittleSheep 2025-03-22 18:14:36 +08:00
parent 71b41d470a
commit 237abe564d
11 changed files with 360 additions and 136 deletions

@ -881,5 +881,11 @@
"appInitUserDirectory": "Initializing User Directory", "appInitUserDirectory": "Initializing User Directory",
"appInitRealm": "Initializing Realms", "appInitRealm": "Initializing Realms",
"appInitChat": "Initializing Chat", "appInitChat": "Initializing Chat",
"appInitDone": "Completed" "appInitDone": "Completed",
"community": "Community",
"realmCommunity": "{}'s Community",
"postTotalCount": {
"one": "Total {} post",
"other": "Total {} posts"
}
} }

@ -879,5 +879,11 @@
"appInitUserDirectory": "正在初始化用户目录", "appInitUserDirectory": "正在初始化用户目录",
"appInitRealm": "正在初始化领域信息", "appInitRealm": "正在初始化领域信息",
"appInitChat": "正在初始化聊天", "appInitChat": "正在初始化聊天",
"appInitDone": "完成" "appInitDone": "完成",
"community": "社区",
"realmCommunity": "{}的社区",
"postTotalCount": {
"zero": "没有帖子",
"one": "共 {} 条帖子"
}
} }

@ -232,6 +232,8 @@ PODS:
- sqlite3/common - sqlite3/common
- sqlite3/fts5 (3.49.1): - sqlite3/fts5 (3.49.1):
- sqlite3/common - sqlite3/common
- sqlite3/math (3.49.1):
- sqlite3/common
- sqlite3/perf-threadsafe (3.49.1): - sqlite3/perf-threadsafe (3.49.1):
- sqlite3/common - sqlite3/common
- sqlite3/rtree (3.49.1): - sqlite3/rtree (3.49.1):
@ -242,6 +244,7 @@ PODS:
- sqlite3 (~> 3.49.1) - sqlite3 (~> 3.49.1)
- sqlite3/dbstatvtab - sqlite3/dbstatvtab
- sqlite3/fts5 - sqlite3/fts5
- sqlite3/math
- sqlite3/perf-threadsafe - sqlite3/perf-threadsafe
- sqlite3/rtree - sqlite3/rtree
- SwiftyGif (5.4.5) - SwiftyGif (5.4.5)
@ -457,7 +460,7 @@ SPEC CHECKSUMS:
shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78 shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78
sqflite_darwin: 5a7236e3b501866c1c9befc6771dfd73ffb8702d sqflite_darwin: 5a7236e3b501866c1c9befc6771dfd73ffb8702d
sqlite3: fc1400008a9b3525f5914ed715a5d1af0b8f4983 sqlite3: fc1400008a9b3525f5914ed715a5d1af0b8f4983
sqlite3_flutter_libs: cc304edcb8e1d8c595d1b08c7aeb46a47691d9db sqlite3_flutter_libs: 487032b9008b28de37c72a3aa66849ef3745f3e6
SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4 SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4
url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe
video_compress: fce97e4fb1dfd88175aa07d2ffc8a2f297f87fbe video_compress: fce97e4fb1dfd88175aa07d2ffc8a2f297f87fbe

@ -39,6 +39,7 @@ import 'package:surface/screens/post/post_shuffle.dart';
import 'package:surface/screens/post/publisher_page.dart'; import 'package:surface/screens/post/publisher_page.dart';
import 'package:surface/screens/post/post_search.dart'; import 'package:surface/screens/post/post_search.dart';
import 'package:surface/screens/realm.dart'; import 'package:surface/screens/realm.dart';
import 'package:surface/screens/realm/community.dart';
import 'package:surface/screens/realm/manage.dart'; import 'package:surface/screens/realm/manage.dart';
import 'package:surface/screens/realm/realm_detail.dart'; import 'package:surface/screens/realm/realm_detail.dart';
import 'package:surface/screens/realm/realm_discovery.dart'; import 'package:surface/screens/realm/realm_discovery.dart';
@ -259,6 +260,13 @@ final _appRoutes = [
child: const RealmScreen(), child: const RealmScreen(),
), ),
routes: [ routes: [
GoRoute(
path: '/:alias/community',
name: 'realmCommunity',
builder: (context, state) => RealmCommunityScreen(
alias: state.pathParameters['alias']!,
),
),
GoRoute( GoRoute(
path: '/manage', path: '/manage',
name: 'realmManage', name: 'realmManage',

@ -45,12 +45,14 @@ class PostEditorExtra {
final String? title; final String? title;
final String? description; final String? description;
final List<PostWriteMedia>? attachments; final List<PostWriteMedia>? attachments;
final SnRealm? realm;
const PostEditorExtra({ const PostEditorExtra({
this.text, this.text,
this.title, this.title,
this.description, this.description,
this.attachments, this.attachments,
this.realm,
}); });
} }
@ -263,6 +265,7 @@ class _PostEditorScreenState extends State<PostEditorScreen>
_writeController.descriptionController.text = _writeController.descriptionController.text =
widget.extraProps!.description ?? ''; widget.extraProps!.description ?? '';
_writeController.addAttachments(widget.extraProps!.attachments ?? []); _writeController.addAttachments(widget.extraProps!.attachments ?? []);
_writeController.setRealm(widget.extraProps!.realm);
} }
} }

@ -0,0 +1,149 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:material_symbols_icons/symbols.dart';
import 'package:provider/provider.dart';
import 'package:styled_widget/styled_widget.dart';
import 'package:surface/providers/post.dart';
import 'package:surface/providers/sn_network.dart';
import 'package:surface/screens/post/post_editor.dart';
import 'package:surface/types/post.dart';
import 'package:surface/types/realm.dart';
import 'package:surface/widgets/dialog.dart';
import 'package:surface/widgets/navigation/app_scaffold.dart';
import 'package:surface/widgets/post/post_item.dart';
import 'package:very_good_infinite_list/very_good_infinite_list.dart';
class RealmCommunityScreen extends StatefulWidget {
final String alias;
const RealmCommunityScreen({super.key, required this.alias});
@override
State<RealmCommunityScreen> createState() => _RealmCommunityScreenState();
}
class _RealmCommunityScreenState extends State<RealmCommunityScreen> {
SnRealm? _realm;
Future<void> _fetchRealm() async {
try {
final sn = context.read<SnNetworkProvider>();
final resp = await sn.client.get('/cgi/id/realms/${widget.alias}');
_realm = SnRealm.fromJson(resp.data);
} catch (err) {
if (!mounted) return;
context.showErrorDialog(err);
rethrow;
} finally {
setState(() {});
}
}
bool _isBusy = false;
int? _totalCount;
final List<SnPost> _posts = List.empty(growable: true);
Future<void> _fetchPosts() async {
setState(() => _isBusy = true);
try {
final pt = context.read<SnPostContentProvider>();
final out = await pt.listPosts(
take: 10,
offset: _posts.length,
realm: _realm?.id.toString(),
);
_totalCount = out.$2;
_posts.addAll(out.$1);
} catch (err) {
if (!mounted) return;
context.showErrorDialog(err);
} finally {
setState(() => _isBusy = false);
}
}
@override
void initState() {
super.initState();
_fetchRealm();
}
@override
Widget build(BuildContext context) {
return AppScaffold(
appBar: AppBar(
title: Text(_realm?.name ?? 'loading'.tr()),
),
floatingActionButton: _realm != null
? FloatingActionButton(
child: const Icon(Symbols.edit),
onPressed: () {
GoRouter.of(context).pushNamed(
'postEditor',
extra: PostEditorExtra(realm: _realm!),
);
},
)
: null,
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (_realm == null)
Expanded(
child: Center(
child: CircularProgressIndicator().center(),
),
),
if (_realm != null)
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('realmCommunity'.tr(args: [_realm!.name]))
.fontSize(17)
.padding(horizontal: 20, bottom: 4),
Text('postTotalCount'.plural(_totalCount ?? 0))
.fontSize(13)
.opacity(0.8)
.padding(horizontal: 20, bottom: 4),
],
).padding(horizontal: 20, vertical: 16),
const Divider(height: 1),
if (_realm != null)
Expanded(
child: MediaQuery.removePadding(
context: context,
removeTop: true,
child: RefreshIndicator(
onRefresh: _fetchPosts,
child: InfiniteList(
padding: const EdgeInsets.only(top: 8),
itemCount: _posts.length,
isLoading: _isBusy,
hasReachedMax:
_totalCount != null && _posts.length >= _totalCount!,
onFetchData: _fetchPosts,
itemBuilder: (context, idx) {
final post = _posts[idx];
return OpenablePostItem(
data: post,
maxWidth: 640,
onChanged: (data) {
setState(() => _posts[idx] = data);
},
onDeleted: () {
setState(() => _posts.removeAt(idx));
},
);
},
separatorBuilder: (_, __) =>
const Divider().padding(vertical: 2),
),
),
),
),
],
),
);
}
}

@ -318,7 +318,7 @@ class _RealmPostListWidgetState extends State<_RealmPostListWidget> {
}, },
); );
}, },
separatorBuilder: (_, __) => const Gap(8), separatorBuilder: (_, __) => const Divider().padding(vertical: 2),
), ),
), ),
).padding(top: 8); ).padding(top: 8);

@ -89,6 +89,7 @@ Future<ThemeData> createAppTheme(
}, },
), ),
progressIndicatorTheme: ProgressIndicatorThemeData(year2023: false), progressIndicatorTheme: ProgressIndicatorThemeData(year2023: false),
sliderTheme: SliderThemeData(year2023: false),
); );
} }

@ -76,7 +76,10 @@ class _LoadingIndicatorState extends State<LoadingIndicator>
const SizedBox( const SizedBox(
height: 16, height: 16,
width: 16, width: 16,
child: CircularProgressIndicator(strokeWidth: 2.5), child: CircularProgressIndicator(
strokeWidth: 2.5,
padding: EdgeInsets.zero,
),
), ),
const Gap(16), const Gap(16),
Text('loading').tr(), Text('loading').tr(),

@ -10,6 +10,7 @@ import 'package:go_router/go_router.dart';
import 'package:material_symbols_icons/symbols.dart'; import 'package:material_symbols_icons/symbols.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:styled_widget/styled_widget.dart'; import 'package:styled_widget/styled_widget.dart';
import 'package:surface/providers/channel.dart';
import 'package:surface/providers/config.dart'; import 'package:surface/providers/config.dart';
import 'package:surface/providers/navigation.dart'; import 'package:surface/providers/navigation.dart';
import 'package:surface/providers/sn_network.dart'; import 'package:surface/providers/sn_network.dart';
@ -42,10 +43,8 @@ class _AppNavigationDrawerState extends State<AppNavigationDrawer> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final ua = context.read<UserProvider>(); final ua = context.read<UserProvider>();
final sn = context.read<SnNetworkProvider>();
final nav = context.watch<NavigationProvider>(); final nav = context.watch<NavigationProvider>();
final cfg = context.watch<ConfigProvider>(); final cfg = context.watch<ConfigProvider>();
final rel = context.read<SnRealmProvider>();
final backgroundColor = cfg.drawerIsExpanded ? Colors.transparent : null; final backgroundColor = cfg.drawerIsExpanded ? Colors.transparent : null;
@ -77,111 +76,7 @@ class _AppNavigationDrawerState extends State<AppNavigationDrawer> {
), ),
Gap(MediaQuery.of(context).padding.top), Gap(MediaQuery.of(context).padding.top),
Expanded( Expanded(
child: PageTransitionSwitcher( child: _DrawerContentList(),
duration: const Duration(milliseconds: 300),
transitionBuilder: (Widget child,
Animation<double> primaryAnimation,
Animation<double> secondaryAnimation) {
return SharedAxisTransition(
animation: primaryAnimation,
secondaryAnimation: secondaryAnimation,
fillColor: Colors.transparent,
transitionType: SharedAxisTransitionType.horizontal,
child: child,
);
},
child: nav.focusedRealm == null
? ListView(
key: const Key('realm-list-view'),
padding: EdgeInsets.zero,
children: [
Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Solar Network').bold(),
AppVersionLabel(),
],
).padding(
horizontal: 32,
vertical: 12,
),
...rel.availableRealms.map((ele) {
return ListTile(
minTileHeight: 48,
contentPadding:
EdgeInsets.symmetric(horizontal: 24),
leading: AccountImage(
content: ele.avatar,
radius: 16,
),
title: Text(ele.name),
onTap: () {
if (Scaffold.of(context).isDrawerOpen) {
GoRouter.of(context).goNamed(
'realmDetail',
pathParameters: {
'alias': ele.alias,
},
);
Scaffold.of(context).closeDrawer();
}
nav.setFocusedRealm(ele);
},
);
}),
],
)
: ListView(
key: ValueKey(nav.focusedRealm),
padding: EdgeInsets.zero,
children: [
if (nav.focusedRealm!.banner != null)
AspectRatio(
aspectRatio: 16 / 9,
child: AutoResizeUniversalImage(
sn.getAttachmentUrl(
nav.focusedRealm!.banner!,
),
fit: BoxFit.cover,
),
),
ListTile(
minTileHeight: 48,
tileColor: Theme.of(context)
.colorScheme
.surfaceContainer,
contentPadding: EdgeInsets.only(
left: 24,
right: 16,
),
leading: AccountImage(
content: nav.focusedRealm!.avatar,
radius: 16,
),
trailing: IconButton(
icon: const Icon(Symbols.close),
padding: EdgeInsets.zero,
constraints: const BoxConstraints(),
visualDensity: VisualDensity.compact,
onPressed: () {
nav.setFocusedRealm(null);
},
),
title: Text(nav.focusedRealm!.name),
onTap: () {
GoRouter.of(context).pushNamed(
'realmDetail',
pathParameters: {
'alias': nav.focusedRealm!.alias,
},
);
Scaffold.of(context).closeDrawer();
},
),
],
),
),
), ),
Row( Row(
spacing: 8, spacing: 8,
@ -249,3 +144,153 @@ class _AppNavigationDrawerState extends State<AppNavigationDrawer> {
); );
} }
} }
class _DrawerContentList extends StatelessWidget {
const _DrawerContentList();
@override
Widget build(BuildContext context) {
final ct = context.read<ChatChannelProvider>();
final sn = context.read<SnNetworkProvider>();
final nav = context.watch<NavigationProvider>();
final rel = context.read<SnRealmProvider>();
return PageTransitionSwitcher(
duration: const Duration(milliseconds: 300),
transitionBuilder: (Widget child, Animation<double> primaryAnimation,
Animation<double> secondaryAnimation) {
return SharedAxisTransition(
animation: primaryAnimation,
secondaryAnimation: secondaryAnimation,
fillColor: Colors.transparent,
transitionType: SharedAxisTransitionType.horizontal,
child: child,
);
},
child: nav.focusedRealm == null
? ListView(
key: const Key('realm-list-view'),
padding: EdgeInsets.zero,
children: [
Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Solar Network').bold(),
AppVersionLabel(),
],
).padding(
horizontal: 32,
vertical: 12,
),
...rel.availableRealms.map((ele) {
return ListTile(
minTileHeight: 48,
contentPadding: EdgeInsets.symmetric(horizontal: 24),
leading: AccountImage(
content: ele.avatar,
radius: 16,
),
title: Text(ele.name),
onTap: () {
nav.setFocusedRealm(ele);
},
);
}),
],
)
: ListView(
key: ValueKey(nav.focusedRealm),
padding: EdgeInsets.zero,
children: [
if (nav.focusedRealm!.banner != null)
AspectRatio(
aspectRatio: 16 / 9,
child: AutoResizeUniversalImage(
sn.getAttachmentUrl(
nav.focusedRealm!.banner!,
),
fit: BoxFit.cover,
),
),
ListTile(
minTileHeight: 48,
tileColor: Theme.of(context).colorScheme.surfaceContainer,
contentPadding: EdgeInsets.only(
left: 24,
right: 16,
),
leading: AccountImage(
content: nav.focusedRealm!.avatar,
radius: 16,
),
trailing: IconButton(
icon: const Icon(Symbols.close),
padding: EdgeInsets.zero,
constraints: const BoxConstraints(),
visualDensity: VisualDensity.compact,
onPressed: () {
nav.setFocusedRealm(null);
},
),
title: Text(nav.focusedRealm!.name),
onTap: () {
GoRouter.of(context).pushNamed(
'realmDetail',
pathParameters: {
'alias': nav.focusedRealm!.alias,
},
);
Scaffold.of(context).closeDrawer();
},
),
ListTile(
minTileHeight: 48,
contentPadding: EdgeInsets.only(
left: 28,
right: 8,
),
leading: const Icon(Symbols.globe),
title: Text('community').tr(),
onTap: () {
GoRouter.of(context).pushNamed(
'realmCommunity',
pathParameters: {
'alias': nav.focusedRealm!.alias,
},
);
Scaffold.of(context).closeDrawer();
},
),
if (ct.availableChannels
.where((ele) => ele.realmId == nav.focusedRealm?.id)
.isNotEmpty)
const Divider(height: 1),
...(ct.availableChannels
.where((ele) => ele.realmId == nav.focusedRealm?.id)
.map((ele) {
return ListTile(
minTileHeight: 48,
contentPadding: EdgeInsets.only(
left: 28,
right: 8,
),
leading: const Icon(Symbols.tag),
title: Text(ele.name),
onTap: () {
GoRouter.of(context).pushNamed(
'chatRoom',
pathParameters: {
'scope': ele.realm?.alias ?? 'global',
'alias': ele.alias,
},
);
Scaffold.of(context).closeDrawer();
},
);
}))
],
),
);
}
}

@ -213,10 +213,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: chalkdart name: chalkdart
sha256: e7cfcc9a9d9546843304c1ff87fe0696c7eb82ee70e6df63f555f321b15a40d8 sha256: "82dfa884e3cf97641eb0742a3b9ffd41490666b9ece548b2e32cbfefe540bf86"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.3" version: "2.4.0"
characters: characters:
dependency: transitive dependency: transitive
description: description:
@ -517,10 +517,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: fast_rsa name: fast_rsa
sha256: "205a36c0412b9fabebf3e18ccb5221d819cc28cfb3da988c0bf7b646368d0270" sha256: a26ad752734dc52fd51abd55248df868d7480e68d8cc8dd12413b0124bba0a7e
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.8.0" version: "3.8.1"
ffi: ffi:
dependency: transitive dependency: transitive
description: description:
@ -541,10 +541,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: file_picker name: file_picker
sha256: ee11ce89f8937c39181bc88d57a455972f7545b86150d8f287d0d9cf95bcdf0a sha256: "8d938fd5c11dc81bf1acd4f7f0486c683fe9e79a0b13419e27730f9ce4d8a25b"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "9.1.0" version: "9.2.1"
file_saver: file_saver:
dependency: "direct main" dependency: "direct main"
description: description:
@ -746,10 +746,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: flutter_expandable_fab name: flutter_expandable_fab
sha256: "85275279d19faf4fbe5639dc1f139b4555b150e079d056f085601a45688af12c" sha256: b14caf78720a48f650e6e1a38d724e33b1f5348d646fa1c266570c31a7f87ef3
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.0" version: "2.4.0"
flutter_highlight: flutter_highlight:
dependency: "direct main" dependency: "direct main"
description: description:
@ -953,10 +953,10 @@ packages:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: freezed name: freezed
sha256: a6274c34d61b3d68082f2b0e9a641a3ec197e525d269f35b82f62d5b2c6d9f75 sha256: "7ed2ddaa47524976d5f2aa91432a79da36a76969edd84170777ac5bea82d797c"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.3" version: "3.0.4"
freezed_annotation: freezed_annotation:
dependency: "direct main" dependency: "direct main"
description: description:
@ -1177,10 +1177,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: image_picker_linux name: image_picker_linux
sha256: "4ed1d9bb36f7cd60aa6e6cd479779cc56a4cb4e4de8f49d487b1aaad831300fa" sha256: "34a65f6740df08bbbeb0a1abd8e6d32107941fd4868f67a507b25601651022c9"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.2.1+1" version: "0.2.1+2"
image_picker_macos: image_picker_macos:
dependency: transitive dependency: transitive
description: description:
@ -1385,10 +1385,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: material_symbols_icons name: material_symbols_icons
sha256: db745002d0323c32097f5bc23711c02b0fb36ef616011a38c8c1798d5684d368 sha256: "99d5b0e7c65232dfe1247e0ac67eeeee2cab9da2d860748fc495d34f5e9e6397"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.2810.0" version: "4.2811.0"
media_kit: media_kit:
dependency: "direct main" dependency: "direct main"
description: description:
@ -2102,10 +2102,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: sqlite3_flutter_libs name: sqlite3_flutter_libs
sha256: "7adb4cc96dc08648a5eb1d80a7619070796ca6db03901ff2b6dcb15ee30468f3" sha256: "1a96b59227828d9eb1463191d684b37a27d66ee5ed7597fcf42eee6452c88a14"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.5.31" version: "0.5.32"
sqlparser: sqlparser:
dependency: transitive dependency: transitive
description: description:
@ -2174,34 +2174,34 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: talker name: talker
sha256: a074e0a2c1db1b09c1856050c5284a14ff64faea003403409871ab8335738d08 sha256: "45abef5b92f9b9bd42c3f20133ad4b20ab12e1da2aa206fc0a40ea874bed7c5d"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.7.0" version: "4.7.1"
talker_dio_logger: talker_dio_logger:
dependency: "direct main" dependency: "direct main"
description: description:
name: talker_dio_logger name: talker_dio_logger
sha256: "6d713d26bdf90c7440222758a4e02ebfbdb3b323cdbdb50b78082db720f69427" sha256: "52c1b554cccedec6073637a6d4f6a3e267dd4451c1545fe57e1b26897a560ccb"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.7.0" version: "4.7.1"
talker_flutter: talker_flutter:
dependency: "direct main" dependency: "direct main"
description: description:
name: talker_flutter name: talker_flutter
sha256: "25a9faa98a0dcbab8d1ec366f19b3e91d422ede523461ec6e26e198b280cb98d" sha256: "77458ca11638dfefb651e898a26101ee54e60dc0b168ad7481a05b1c97ce2680"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.7.0" version: "4.7.1"
talker_logger: talker_logger:
dependency: transitive dependency: transitive
description: description:
name: talker_logger name: talker_logger
sha256: "0a1a295a9d036a3416e89c7155eaaca9ca6e3e0abb5401a40597f98b9cfc8fe6" sha256: ed9b20b8c09efff9f6b7c63fc6630ee2f84aa92661ae09e5ba04e77272bf2ad2
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.7.0" version: "4.7.1"
term_glyph: term_glyph:
dependency: transitive dependency: transitive
description: description: