From b6c1c9e57f52e547bf48ed1fa653f0283da1be84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A4=8F=E6=B2=AB=E8=8A=B1=E7=81=ABzzz=F0=9F=8C=99?= Date: Sun, 15 Sep 2024 00:48:47 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B2=A1=E6=9C=89=E4=BB=BB=E4=BD=95=E8=BD=AF?= =?UTF-8?q?=E7=94=A8=E7=9A=84=E6=90=9C=E7=B4=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/models/search_data.dart | 14 +++ lib/ui/home.dart | 13 +-- lib/ui/models/navigation_bar.dart | 12 +-- lib/ui/models/search_dialog.dart | 149 +++++++++++++++++++++++++++++ lib/ui/paragraph.dart | 2 +- lib/ui/settings.dart | 2 +- lib/ui/settings/about.dart | 2 +- lib/ui/settings/render.dart | 2 +- lib/ui/settings/rss_subscribe.dart | 2 +- lib/ui/settings/theme.dart | 2 +- pubspec.lock | 16 ++++ pubspec.yaml | 1 + 12 files changed, 194 insertions(+), 23 deletions(-) create mode 100644 lib/models/search_data.dart create mode 100644 lib/ui/models/search_dialog.dart diff --git a/lib/models/search_data.dart b/lib/models/search_data.dart new file mode 100644 index 0000000..005c4ce --- /dev/null +++ b/lib/models/search_data.dart @@ -0,0 +1,14 @@ +class SearchData { + SearchData({ + required this.matchTitle, + required this.matchContent, + this.title, + this.contentMatched, + }); + + final bool matchTitle; + final bool matchContent; + + final String? title; + final List? contentMatched; +} diff --git a/lib/ui/home.dart b/lib/ui/home.dart index db0de6e..587f354 100644 --- a/lib/ui/home.dart +++ b/lib/ui/home.dart @@ -4,6 +4,7 @@ import 'package:miofeed/controllers/navigator_controller.dart'; import 'package:miofeed/models/universal_feed.dart'; import 'package:miofeed/models/universal_item.dart'; import 'package:miofeed/tasks/subscribe_update.dart'; +import 'package:miofeed/ui/models/search_dialog.dart'; import 'package:miofeed/ui/paragraph.dart'; import 'package:miofeed/utils/after_layout.dart'; import 'package:miofeed/utils/paragraph_utils.dart'; @@ -38,15 +39,7 @@ class HomeUI extends StatelessWidget { ), IconButton( onPressed: () async { - Get.dialog( - const SimpleDialog( - children: [ - Center( - child: Text('Comming soon'), - ) - ], - ), - ); + Get.dialog(searchDialog(context)); }, icon: const Icon(Icons.search), ) @@ -161,7 +154,7 @@ class HomeUI extends StatelessWidget { ), ), ), - bottomNavigationBar: NavigationBarX().build(), + bottomNavigationBar: navigationBar(), ); } diff --git a/lib/ui/models/navigation_bar.dart b/lib/ui/models/navigation_bar.dart index 41e65fc..c988547 100644 --- a/lib/ui/models/navigation_bar.dart +++ b/lib/ui/models/navigation_bar.dart @@ -3,14 +3,13 @@ import 'package:get/get.dart'; import '../../controllers/navigator_controller.dart'; -class NavigationBarX { - final NavigatorController nctr = Get.put(NavigatorController()); + final NavigatorController _nCtr = Get.put(NavigatorController()); - build() => NavigationBar( - selectedIndex: nctr.currentPage.value, + navigationBar() => NavigationBar( + selectedIndex: _nCtr.currentPage.value, onDestinationSelected: (index) async { - nctr.currentPage.value = index; - nctr.subCurrentPage.value = 0; + _nCtr.currentPage.value = index; + _nCtr.subCurrentPage.value = 0; switch (index) { case 0: // 首页 @@ -26,4 +25,3 @@ class NavigationBarX { NavigationDestination(icon: Icon(Icons.settings), label: "设置"), ], ); -} diff --git a/lib/ui/models/search_dialog.dart b/lib/ui/models/search_dialog.dart new file mode 100644 index 0000000..705c15d --- /dev/null +++ b/lib/ui/models/search_dialog.dart @@ -0,0 +1,149 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_markdown/flutter_markdown.dart'; +import 'package:get/get.dart'; +import 'package:miofeed/models/search_data.dart'; +import 'package:miofeed/models/universal_item.dart'; +import 'package:miofeed/utils/rss/rss_utils.dart'; + +searchDialog(BuildContext context) { + final controller = Get.put(_SearchController()); + final dataParagraph = RssUtils.allRssParagraph; + controller.searchData.clear(); + return SimpleDialog( + children: [ + Container( + margin: const EdgeInsets.symmetric(horizontal: 10), + child: Column( + children: [ + SearchBar( + onChanged: (value) async { + controller.hasSearch.value = true; + controller.searchData.clear(); + if (value != '') { + for (var paraData in dataParagraph) { + final UniversalItem item = paraData['item']; + final String title = item.title; + final String description = item.content + .replaceAll(RegExp(r'<[^>]*>|&[^;]+;'), ' ') + .replaceAll(RegExp(r'\n{2,}'), ' ') + .replaceAll(RegExp(r'\r{2,}'), ' ') + .replaceAll(RegExp(r' {2,}'), ' ') + .trim(); + bool matchTitle = false; + String? outputTitle; + bool matchContent = false; + List? outputContent; + if (title.contains(value)) { + matchTitle = true; + outputTitle = title.replaceAll(value, " **$value** "); + print(outputTitle); + } + + if (description.contains(value)) { + matchContent = true; + // 使用正则表达式匹配 value + RegExp regExp = RegExp( + '(.{0,17}$value.{0,17})', + unicode: true, // 确保处理中文字符 + ); + description.replaceAll(value, " **$value** "); + Iterable matches = + regExp.allMatches(description); + outputContent = []; + for (var match in matches) { + if (match.group(0) != null) { + outputContent.add(match.group(0)!); + } + } + print(outputContent); + controller.searchData.add( + SearchData( + matchTitle: matchTitle, + matchContent: matchContent, + title: outputTitle, + contentMatched: outputContent, + ), + ); + } + } + print(controller.searchData.length); + } else { + controller.hasSearch.value = false; + controller.searchData.clear(); + } + }, + ), + SizedBox( + width: MediaQuery.of(context).size.width - 20, + height: MediaQuery.of(context).size.height - 20, + child: Obx( + () => controller.hasSearch.value + ? ListView.builder( + itemCount: controller.searchData.length, + itemBuilder: (BuildContext context, int i) { + final item = controller.searchData[i]; + List contents = []; + + if (item.matchContent) { + for (var c in item.contentMatched!) { + contents.add(MarkdownBody(data: c)); + } + } + + return controller.searchData.isNotEmpty + ? item.matchTitle + ? ListTile( + title: MarkdownBody(data: item.title!), + subtitle: contents.isNotEmpty + ? Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: contents, + ) + : null, + ) + : ListTile( + title: contents.isNotEmpty + ? Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: contents, + ) + : null, + ) + : Center( + child: Container( + margin: const EdgeInsets.only(top: 40), + child: const Text('什么也没搜到...'), + ), + ); + }) + : Center( + child: Container( + margin: const EdgeInsets.only(top: 40), + child: const Text('来搜点什么吧...'), + ), + ), + // child: ListView( + // children: [ + // Center( + // child: Container( + // margin: const EdgeInsets.only(top: 40), + // child: const Text('来搜点什么吧...'), + // ), + // ) + // ], + // ), + ), + ), + ], + ), + ), + ], + ); +} + +class _SearchController extends GetxController { + var hasSearch = false.obs; + var searchData = [].obs; +} diff --git a/lib/ui/paragraph.dart b/lib/ui/paragraph.dart index fbf16ca..37a78db 100644 --- a/lib/ui/paragraph.dart +++ b/lib/ui/paragraph.dart @@ -162,7 +162,7 @@ class ParagraphUI extends StatelessWidget { ), ], ), - bottomNavigationBar: NavigationBarX().build(), + bottomNavigationBar: navigationBar(), ); } diff --git a/lib/ui/settings.dart b/lib/ui/settings.dart index 1520182..078d053 100644 --- a/lib/ui/settings.dart +++ b/lib/ui/settings.dart @@ -68,7 +68,7 @@ class SettingsUI extends StatelessWidget { ), ], ), - bottomNavigationBar: NavigationBarX().build(), + bottomNavigationBar: navigationBar(), ); } } diff --git a/lib/ui/settings/about.dart b/lib/ui/settings/about.dart index 809bcd0..e8fb2b9 100644 --- a/lib/ui/settings/about.dart +++ b/lib/ui/settings/about.dart @@ -72,7 +72,7 @@ class AboutUI extends StatelessWidget { ), ], ), - bottomNavigationBar: NavigationBarX().build(), + bottomNavigationBar: navigationBar(), ); } } diff --git a/lib/ui/settings/render.dart b/lib/ui/settings/render.dart index d7a6d18..babc33c 100644 --- a/lib/ui/settings/render.dart +++ b/lib/ui/settings/render.dart @@ -27,7 +27,7 @@ class RenderSettingUI extends StatelessWidget { body: const Center( child: Text('Coming soon'), ), - bottomNavigationBar: NavigationBarX().build(), + bottomNavigationBar: navigationBar(), ); } } diff --git a/lib/ui/settings/rss_subscribe.dart b/lib/ui/settings/rss_subscribe.dart index 0688eea..04fa52c 100644 --- a/lib/ui/settings/rss_subscribe.dart +++ b/lib/ui/settings/rss_subscribe.dart @@ -74,7 +74,7 @@ class _RssSubSettingState extends State { ), ], ), - bottomNavigationBar: NavigationBarX().build(), + bottomNavigationBar: navigationBar(), ); } } diff --git a/lib/ui/settings/theme.dart b/lib/ui/settings/theme.dart index 2d0039c..d09e152 100644 --- a/lib/ui/settings/theme.dart +++ b/lib/ui/settings/theme.dart @@ -120,7 +120,7 @@ class ThemeSettingUI extends StatelessWidget { ], ), ), - bottomNavigationBar: NavigationBarX().build(), + bottomNavigationBar: navigationBar(), ); } diff --git a/pubspec.lock b/pubspec.lock index db52504..df7fd84 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -254,6 +254,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.0" + flutter_markdown: + dependency: "direct main" + description: + name: flutter_markdown + sha256: a23c41ee57573e62fc2190a1f36a0480c4d90bde3a8a8d7126e5d5992fb53fb7 + url: "https://pub.dev" + source: hosted + version: "0.7.3+1" flutter_svg: dependency: transitive description: @@ -456,6 +464,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.0" + markdown: + dependency: transitive + description: + name: markdown + sha256: ef2a1298144e3f985cc736b22e0ccdaf188b5b3970648f2d9dc13efd1d9df051 + url: "https://pub.dev" + source: hosted + version: "7.2.2" matcher: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 3d1de58..b77e421 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -48,6 +48,7 @@ dependencies: dynamic_color: ^1.7.0 background_fetch: ^1.3.5 package_info_plus: ^8.0.2 + flutter_markdown: ^0.7.3+1 dev_dependencies: flutter_test: