From 714cbb2d0f9493e0465e3da95b2691dba74f2459 Mon Sep 17 00:00:00 2001 From: guozhigq Date: Sat, 24 Jun 2023 23:47:05 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E5=8A=A8=E6=80=81?= =?UTF-8?q?=E9=A1=B5=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- assets/images/play.png | Bin 0 -> 2367 bytes lib/http/api.dart | 2 + lib/http/dynamics.dart | 29 ++ lib/models/dynamics/result.dart | 415 ++++++++++++++++++ lib/pages/dynamics/controller.dart | 27 ++ lib/pages/dynamics/index.dart | 4 + lib/pages/dynamics/view.dart | 78 ++++ lib/pages/dynamics/widgets/dynamic_panel.dart | 272 ++++++++++++ lib/pages/main/controller.dart | 24 +- lib/router/app_pages.dart | 5 +- 10 files changed, 844 insertions(+), 12 deletions(-) create mode 100644 assets/images/play.png create mode 100644 lib/http/dynamics.dart create mode 100644 lib/models/dynamics/result.dart create mode 100644 lib/pages/dynamics/controller.dart create mode 100644 lib/pages/dynamics/index.dart create mode 100644 lib/pages/dynamics/view.dart create mode 100644 lib/pages/dynamics/widgets/dynamic_panel.dart diff --git a/assets/images/play.png b/assets/images/play.png new file mode 100644 index 0000000000000000000000000000000000000000..b5d0299c5861828310407147445d868a3cb1efd7 GIT binary patch literal 2367 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 literal 0 HcmV?d00001 diff --git a/lib/http/api.dart b/lib/http/api.dart index ba12b485..d54eb0f9 100644 --- a/lib/http/api.dart +++ b/lib/http/api.dart @@ -135,6 +135,8 @@ class Api { // https://api.bilibili.com/x/polymer/web-dynamic/v1/portal // 关注的up动态 + // https://api.bilibili.com/x/polymer/web-dynamic/v1/feed/all + static const String followDynamic = '/x/polymer/web-dynamic/v1/feed/all'; // 获取稍后再看 static const String seeYouLater = '/x/v2/history/toview'; diff --git a/lib/http/dynamics.dart b/lib/http/dynamics.dart new file mode 100644 index 00000000..56bc1174 --- /dev/null +++ b/lib/http/dynamics.dart @@ -0,0 +1,29 @@ +import 'package:pilipala/http/index.dart'; +import 'package:pilipala/models/dynamics/result.dart'; + +class DynamicsHttp { + static Future followDynamic({ + String? type, + int? page, + String? offset, + }) async { + var res = await Request().get(Api.followDynamic, data: { + 'type': type ?? 'all', + 'page': page ?? 1, + 'offest': page == 1 ? '' : offset, + 'features': 'itemOpusStyle' + }); + if (res.data['code'] == 0) { + return { + 'status': true, + 'data': DynamicsDataModel.fromJson(res.data['data']), + }; + } else { + return { + 'status': false, + 'data': [], + 'msg': '请求错误 🙅', + }; + } + } +} diff --git a/lib/models/dynamics/result.dart b/lib/models/dynamics/result.dart new file mode 100644 index 00000000..fdc2ae8c --- /dev/null +++ b/lib/models/dynamics/result.dart @@ -0,0 +1,415 @@ +class DynamicsDataModel { + DynamicsDataModel({ + this.hasMore, + this.items, + this.offset, + }); + bool? hasMore; + List? items; + String? offset; + + DynamicsDataModel.fromJson(Map json) { + hasMore = json['has_more']; + items = json['items'] + .map((e) => DynamicItemModel.fromJson(e)) + .toList(); + offset = json['offset']; + } +} + +// 单个动态 +class DynamicItemModel { + DynamicItemModel({ + // this.basic, + this.idStr, + this.modules, + this.orig, + this.type, + this.visible, + }); + + // Map? basic; + String? idStr; + ItemModulesModel? modules; + ItemOrigModel? orig; + String? type; + bool? visible; + + DynamicItemModel.fromJson(Map json) { + // basic = json['basic']; + idStr = json['id_str']; + modules = ItemModulesModel.fromJson(json['modules']); + orig = json['orig'] != null ? ItemOrigModel.fromJson(json['orig']) : null; + type = json['type']; + visible = json['visible']; + } +} + +class ItemOrigModel { + ItemOrigModel({ + this.basic, + this.isStr, + this.modules, + this.type, + this.visible, + }); + + Map? basic; + String? isStr; + ItemModulesModel? modules; + String? type; + bool? visible; + + ItemOrigModel.fromJson(Map json) { + basic = json['basic']; + isStr = json['is_str']; + modules = ItemModulesModel.fromJson(json['modules']); + type = json['type']; + visible = json['visible']; + } +} + +// 单个动态详情 +class ItemModulesModel { + ItemModulesModel({ + this.moduleAuthor, + this.moduleDynamic, + // this.moduleInter, + this.moduleStat, + }); + + ModuleAuthorModel? moduleAuthor; + ModuleDynamicModel? moduleDynamic; + // ModuleInterModel? moduleInter; + ModuleStatModel? moduleStat; + + ItemModulesModel.fromJson(Map json) { + moduleAuthor = json['module_author'] != null + ? ModuleAuthorModel.fromJson(json['module_author']) + : null; + moduleDynamic = json['module_dynamic'] != null + ? ModuleDynamicModel.fromJson(json['module_dynamic']) + : null; + // moduleInter = ModuleInterModel.fromJson(json['module_interaction']); + moduleStat = json['module_stat'] != null + ? ModuleStatModel.fromJson(json['module_stat']) + : null; + } +} + +// 单个动态详情 - 作者信息 +class ModuleAuthorModel { + ModuleAuthorModel({ + // this.avatar, + // this.decorate, + this.face, + this.following, + this.jumpUrl, + this.label, + this.mid, + this.name, + // this.officialVerify, + // this.pandant, + this.pubAction, + // this.pubLocationText, + this.pubTime, + this.pubTs, + this.type, + // this.vip, + }); + + String? face; + bool? following; + String? jumpUrl; + String? label; + int? mid; + String? name; + String? pubAction; + String? pubTime; + int? pubTs; + String? type; + + ModuleAuthorModel.fromJson(Map json) { + face = json['face']; + following = json['following']; + jumpUrl = json['jump_url']; + label = json['label']; + mid = json['mid']; + name = json['name']; + pubAction = json['pub_action']; + pubTime = json['pub_time']; + pubTs = json['pub_ts']; + type = json['type']; + } +} + +// 单个动态详情 - 动态信息 +class ModuleDynamicModel { + ModuleDynamicModel({ + // this.additional, + this.desc, + this.major, + this.topic, + }); + + String? additional; + DynamicDescModel? desc; + DynamicMajorModel? major; + Map? topic; + + ModuleDynamicModel.fromJson(Map json) { + desc = + json['desc'] != null ? DynamicDescModel.fromJson(json['desc']) : null; + if (json['major'] != null) { + major = DynamicMajorModel.fromJson(json['major']); + } + topic = json['topic']; + } +} + +// 单个动态详情 - 评论?信息 +// class ModuleInterModel { +// ModuleInterModel({ + +// }); + +// ModuleInterModel.fromJson(Map json) { + +// } +// } + +class DynamicDescModel { + DynamicDescModel({ + this.richTextNode, + this.text, + }); + + List? richTextNode; + String? text; + + DynamicDescModel.fromJson(Map json) { + richTextNode = json['rich_text_nodes']; + text = json['text']; + } +} + +// +class DynamicMajorModel { + DynamicMajorModel({ + this.archive, + this.draw, + this.type, + }); + + DynamicArchiveModel? archive; + DynamicDrawModel? draw; + DynamicOpusModel? opus; + // MAJOR_TYPE_DRAW 图片 + // MAJOR_TYPE_ARCHIVE 视频 + // MAJOR_TYPE_OPUS 图文/文章 + String? type; + + DynamicMajorModel.fromJson(Map json) { + archive = json['archive'] != null + ? DynamicArchiveModel.fromJson(json['archive']) + : null; + draw = + json['draw'] != null ? DynamicDrawModel.fromJson(json['draw']) : null; + opus = + json['opus'] != null ? DynamicOpusModel.fromJson(json['opus']) : null; + type = json['type']; + } +} + +class DynamicArchiveModel { + DynamicArchiveModel({ + this.aid, + this.badge, + this.bvid, + this.cover, + this.desc, + this.disablePreview, + this.durationText, + this.jumpUrl, + this.stat, + this.title, + this.type, + }); + + String? aid; + Map? badge; + String? bvid; + String? cover; + String? desc; + int? disablePreview; + String? durationText; + String? jumpUrl; + Stat? stat; + String? title; + int? type; + + DynamicArchiveModel.fromJson(Map json) { + aid = json['aid']; + badge = json['badge']; + bvid = json['bvid']; + cover = json['cover']; + disablePreview = json['disable_preview']; + durationText = json['duration_text']; + jumpUrl = json['jump_url']; + stat = Stat.fromJson(json['stat']); + title = json['title']; + type = json['type']; + } +} + +class DynamicDrawModel { + DynamicDrawModel({ + this.id, + this.item, + }); + + int? id; + List? item; + + DynamicDrawModel.fromJson(Map json) { + id = json['id']; + // ignore: prefer_null_aware_operators + item = json['item'] != null + ? json['item'] + .map((e) => DynamicDrawItemModel.fromJson(e)) + .toList() + : null; + } +} + +class DynamicOpusModel { + DynamicOpusModel({ + this.jumpUrl, + this.pics, + this.summary, + this.title, + }); + + String? jumpUrl; + List? pics; + Map? summary; + String? title; + DynamicOpusModel.fromJson(Map json) { + jumpUrl = json['jump_url']; + pics = json['pics']; + summary = json['summary']; + title = json['title']; + } +} + +class OpusPicsModel { + OpusPicsModel({ + this.width, + this.height, + this.size, + this.src, + }); + + int? width; + int? height; + int? size; + String? src; + + OpusPicsModel.fromJson(Map json) { + width = json['width']; + height = json['height']; + size = json['size']; + src = json['src']; + } +} + +class DynamicDrawItemModel { + DynamicDrawItemModel({ + this.height, + this.size, + this.src, + this.tags, + this.width, + }); + int? height; + int? size; + String? src; + List? tags; + int? width; + DynamicDrawItemModel.fromJson(Map json) { + height = json['height']; + size = json['size']; + src = json['src']; + tags = json['tags']; + width = json['width']; + } +} + +// 动态状态 转发、评论、点赞 +class ModuleStatModel { + ModuleStatModel({ + this.comment, + this.forward, + this.like, + }); + + Comment? comment; + Map? forward; + Like? like; + + ModuleStatModel.fromJson(Map json) { + comment = Comment.fromJson(json['comment']); + forward = json['forward']; + like = Like.fromJson(json['like']); + } +} + +// 动态状态 评论 +class Comment { + Comment({ + this.count, + this.forbidden, + }); + + String? count; + bool? forbidden; + + Comment.fromJson(Map json) { + count = json['count'].toString(); + forbidden = json['forbidden']; + } +} + +// 动态状态 点赞 +class Like { + Like({ + this.count, + this.forbidden, + this.status, + }); + + String? count; + bool? forbidden; + bool? status; + + Like.fromJson(Map json) { + count = json['count'].toString(); + forbidden = json['forbidden']; + status = json['status']; + } +} + +class Stat { + Stat({ + this.danmaku, + this.play, + }); + + String? danmaku; + String? play; + + Stat.fromJson(Map json) { + danmaku = json['danmaku']; + play = json['play']; + } +} diff --git a/lib/pages/dynamics/controller.dart b/lib/pages/dynamics/controller.dart new file mode 100644 index 00000000..438198b0 --- /dev/null +++ b/lib/pages/dynamics/controller.dart @@ -0,0 +1,27 @@ +import 'package:get/get.dart'; +import 'package:pilipala/http/dynamics.dart'; +import 'package:pilipala/models/dynamics/result.dart'; + +class DynamicsController extends GetxController { + int page = 1; + String reqType = 'all'; + String? offset; + RxList? dynamicsList = [DynamicItemModel()].obs; + + Future queryFollowDynamic({type = 'init'}) async { + var res = await DynamicsHttp.followDynamic( + page: page, + type: reqType, + offset: offset, + ); + if (res['status']) { + if (type == 'init') { + dynamicsList!.value = res['data'].items; + } else { + dynamicsList!.addAll(res['data'].items); + } + offset = res['data'].offset; + } + return res; + } +} diff --git a/lib/pages/dynamics/index.dart b/lib/pages/dynamics/index.dart new file mode 100644 index 00000000..810610e1 --- /dev/null +++ b/lib/pages/dynamics/index.dart @@ -0,0 +1,4 @@ +library dynamics; + +export './controller.dart'; +export './view.dart'; diff --git a/lib/pages/dynamics/view.dart b/lib/pages/dynamics/view.dart new file mode 100644 index 00000000..80a9d3cf --- /dev/null +++ b/lib/pages/dynamics/view.dart @@ -0,0 +1,78 @@ +import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:get/get.dart'; +import 'package:pilipala/common/skeleton/video_card_h.dart'; +import 'package:pilipala/common/widgets/http_error.dart'; +import 'package:pilipala/models/dynamics/result.dart'; + +import 'controller.dart'; +import 'widgets/dynamic_panel.dart'; + +class DynamicsPage extends StatefulWidget { + const DynamicsPage({super.key}); + + @override + State createState() => _DynamicsPageState(); +} + +class _DynamicsPageState extends State { + DynamicsController _dynamicsController = Get.put(DynamicsController()); + Future? _futureBuilderFuture; + + @override + void initState() { + super.initState(); + _futureBuilderFuture = _dynamicsController.queryFollowDynamic(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + centerTitle: false, + title: const Text('动态'), + actions: [ + IconButton(onPressed: () {}, icon: const Icon(Icons.more_horiz)), + const SizedBox(width: 10) + ], + ), + body: FutureBuilder( + future: _dynamicsController.queryFollowDynamic(), + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.done) { + Map data = snapshot.data; + if (data['status']) { + List list = _dynamicsController.dynamicsList!; + return Obx( + () => ListView.builder( + shrinkWrap: true, + itemCount: list.length, + itemBuilder: (BuildContext context, index) { + return DynamicPanel(item: list[index]); + }, + ), + ); + } else { + return CustomScrollView( + slivers: [ + HttpError( + errMsg: data['msg'], + fn: () => setState(() {}), + ) + ], + ); + } + } else { + // 骨架屏 + // return SliverList( + // delegate: SliverChildBuilderDelegate((context, index) { + // return const VideoCardHSkeleton(); + // }, childCount: 10), + // ); + return Text('加载中'); + } + }, + ), + ); + } +} diff --git a/lib/pages/dynamics/widgets/dynamic_panel.dart b/lib/pages/dynamics/widgets/dynamic_panel.dart new file mode 100644 index 00000000..3eb1487c --- /dev/null +++ b/lib/pages/dynamics/widgets/dynamic_panel.dart @@ -0,0 +1,272 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:pilipala/common/constants.dart'; +import 'package:pilipala/common/widgets/network_img_layer.dart'; +import 'package:pilipala/common/widgets/stat/danmu.dart'; +import 'package:pilipala/common/widgets/stat/view.dart'; +import 'package:pilipala/models/dynamics/result.dart'; + +class DynamicPanel extends StatelessWidget { + DynamicItemModel? item; + DynamicPanel({this.item, Key? key}); + + @override + Widget build(BuildContext context) { + return Container( + decoration: BoxDecoration( + border: Border( + top: BorderSide( + width: 8, + color: Theme.of(context).dividerColor.withOpacity(0.05), + ), + ), + ), + child: Material( + elevation: 0, + clipBehavior: Clip.hardEdge, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(0), + ), + child: InkWell( + onTap: () {}, + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + author(item, context), + if (item!.modules!.moduleDynamic!.desc != null) + content(item, context), + Padding( + padding: EdgeInsets.zero, + // padding: const EdgeInsets.only(left: 15, right: 15), + child: forWard(item, context), + ), + action(item, context), + ], + ), + ), + ), + ); + } + + Widget author(item, context) { + return Container( + padding: const EdgeInsets.fromLTRB(12, 10, 12, 10), + child: Row( + children: [ + NetworkImgLayer( + width: 40, + height: 40, + type: 'avatar', + src: item.modules.moduleAuthor.face, + ), + const SizedBox(width: 10), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(item.modules.moduleAuthor.name), + Text( + item.modules.moduleAuthor.pubTime + + (item.modules.moduleAuthor.pubAction != '' + ? ' - ${item.modules.moduleAuthor.pubAction}' + : ''), + style: TextStyle( + color: Theme.of(context).colorScheme.outline, + fontSize: Theme.of(context).textTheme.labelSmall!.fontSize), + ) + ], + ) + ], + ), + ); + } + + // 内容 + Widget content(item, context) { + return Container( + width: double.infinity, + padding: const EdgeInsets.fromLTRB(15, 0, 15, 10), + child: Text( + item!.modules!.moduleDynamic!.desc!.text!, + maxLines: 5, + overflow: TextOverflow.ellipsis, + ), + ); + } + + // 转发 + Widget forWard(item, context, {floor = 1}) { + switch (item.type) { + // 图文 + case 'DYNAMIC_TYPE_DRAW': + return const Text('DYNAMIC_TYPE_DRAW'); + // 视频 + case 'DYNAMIC_TYPE_AV': + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (floor == 2) ...[ + Text('@' + item.modules.moduleAuthor.name), + const SizedBox(height: 8), + ], + GestureDetector( + onTap: () {}, + child: LayoutBuilder(builder: (context, box) { + double width = box.maxWidth; + return Stack( + children: [ + NetworkImgLayer( + type: floor == 1 ? 'emote' : null, + width: width, + height: width / StyleString.aspectRatio, + src: item.modules.moduleDynamic.major.archive.cover, + ), + Positioned( + left: 0, + right: 0, + bottom: 0, + child: Container( + padding: const EdgeInsets.fromLTRB(12, 22, 10, 15), + clipBehavior: Clip.hardEdge, + decoration: BoxDecoration( + gradient: const LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + Colors.transparent, + Colors.black87, + ], + tileMode: TileMode.mirror, + ), + borderRadius: floor == 1 + ? null + : const BorderRadius.all(Radius.circular(6))), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Row( + children: [ + Text( + item.modules.moduleDynamic.major.archive + .durationText, + style: TextStyle( + fontSize: Theme.of(context) + .textTheme + .labelMedium! + .fontSize, + color: Colors.white), + ), + const SizedBox(width: 10), + Text( + item.modules.moduleDynamic.major.archive + .stat.play, + style: TextStyle( + fontSize: Theme.of(context) + .textTheme + .labelMedium! + .fontSize, + color: Colors.white), + ), + const SizedBox(width: 10), + Text( + item.modules.moduleDynamic.major.archive + .stat.danmaku, + style: TextStyle( + fontSize: Theme.of(context) + .textTheme + .labelMedium! + .fontSize, + color: Colors.white), + ) + ], + ), + Image.asset( + 'assets/images/play.png', + width: 70, + height: 70, + ), + ], + ), + )), + ], + ); + }), + ), + const SizedBox(height: 6), + Padding( + padding: floor == 1 + ? const EdgeInsets.only(left: 12, right: 12) + : EdgeInsets.zero, + child: Text( + item.modules.moduleDynamic.major.archive.title, + maxLines: 1, + style: const TextStyle(fontWeight: FontWeight.bold), + overflow: TextOverflow.ellipsis, + ), + ), + const SizedBox(height: 4), + ], + ); + // 文章 + case 'DYNAMIC_TYPE_ARTICLE': + return const Text('DYNAMIC_TYPE_ARTICLE'); + // 转发 + case 'DYNAMIC_TYPE_FORWARD': + // return const Text('DYNAMIC_TYPE_FORWARD'); + switch (item.orig.type) { + // 递归 + case 'DYNAMIC_TYPE_AV': + return Container( + padding: const EdgeInsets.only( + left: 15, top: 10, right: 15, bottom: 10), + color: Theme.of(context).dividerColor.withOpacity(0.08), + child: forWard(item.orig, context, floor: 2), + ); + default: + return const Text('渲染出错了'); + } + // 直播 + case 'DYNAMIC_TYPE_LIVE_RCMD': + return const Text('DYNAMIC_TYPE_LIVE_RCMD'); + // 合集 + case 'DYNAMIC_TYPE_UGC_SEASON': + return const Text('DYNAMIC_TYPE_UGC_SEASON'); + default: + return const Text('渲染出错了'); + } + } + + // 操作栏 + Widget action(item, context) { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + TextButton.icon( + onPressed: () {}, + icon: const Icon( + FontAwesomeIcons.shareFromSquare, + size: 16, + ), + label: const Text('转发'), + ), + TextButton.icon( + onPressed: () {}, + icon: const Icon( + FontAwesomeIcons.comment, + size: 16, + ), + label: Text(item.modules.moduleStat.comment.count), + ), + TextButton.icon( + onPressed: () {}, + icon: const Icon( + FontAwesomeIcons.thumbsUp, + size: 16, + ), + label: Text(item.modules.moduleStat.like.count), + ) + ], + ); + } +} diff --git a/lib/pages/main/controller.dart b/lib/pages/main/controller.dart index 8a2ce2aa..32ebfd5b 100644 --- a/lib/pages/main/controller.dart +++ b/lib/pages/main/controller.dart @@ -3,6 +3,7 @@ import 'package:get/get.dart'; import 'package:flutter/material.dart'; import 'package:hive/hive.dart'; import 'package:pilipala/common/widgets/network_img_layer.dart'; +import 'package:pilipala/pages/dynamics/index.dart'; import 'package:pilipala/pages/home/view.dart'; import 'package:pilipala/pages/hot/view.dart'; import 'package:pilipala/pages/media/index.dart'; @@ -13,6 +14,7 @@ class MainController extends GetxController { List pages = [ const HomePage(), const HotPage(), + const DynamicsPage(), const MediaPage(), ]; RxList navigationBars = [ @@ -42,17 +44,17 @@ class MainController extends GetxController { ), 'label': "热门", }, - // { - // 'icon': const Icon( - // CupertinoIcons.person, - // size: 21, - // ), - // 'selectedIcon': const Icon( - // CupertinoIcons.person_fill, - // size: 21, - // ), - // 'label': "我的", - // }, + { + 'icon': const Icon( + CupertinoIcons.camera_on_rectangle, + size: 21, + ), + 'selectedIcon': const Icon( + CupertinoIcons.camera_on_rectangle_fill, + size: 21, + ), + 'label': "动态", + }, { // 'icon': const Icon(Icons.person_outline), // 'selectedIcon': const Icon(Icons.person), diff --git a/lib/router/app_pages.dart b/lib/router/app_pages.dart index 6055997f..14fae6b1 100644 --- a/lib/router/app_pages.dart +++ b/lib/router/app_pages.dart @@ -1,4 +1,5 @@ import 'package:get/get.dart'; +import 'package:pilipala/pages/dynamics/view.dart'; import 'package:pilipala/pages/fav/index.dart'; import 'package:pilipala/pages/favDetail/index.dart'; import 'package:pilipala/pages/history/index.dart'; @@ -47,6 +48,8 @@ class Routes { // 搜索页面 GetPage(name: '/search', page: () => const SearchPage()), // 搜索结果 - GetPage(name: '/searchResult', page: () => const SearchResultPage()) + GetPage(name: '/searchResult', page: () => const SearchResultPage()), + // + GetPage(name: '/dynamics', page: () => const DynamicsPage()) ]; }