From aa7536d51603e88a05a9377dba06655d9fce076a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A3=B9=E9=9B=B6?= Date: Wed, 29 May 2024 11:47:00 +0800 Subject: [PATCH] chore: remove some codes --- lib/llm/editor/components/article_item.dart | 74 ++++++ .../components/load_article_dialog.dart | 77 ++++++ lib/llm/editor/compose_screen.dart | 85 ++++++- .../editor/notifiers/article_notifier.dart | 31 +++ lib/llm/template_editor/template_editor.dart | 230 ++++-------------- pubspec.yaml | 2 +- 6 files changed, 310 insertions(+), 189 deletions(-) create mode 100644 lib/llm/editor/components/article_item.dart create mode 100644 lib/llm/editor/components/load_article_dialog.dart create mode 100644 lib/llm/editor/notifiers/article_notifier.dart diff --git a/lib/llm/editor/components/article_item.dart b/lib/llm/editor/components/article_item.dart new file mode 100644 index 0000000..f02d944 --- /dev/null +++ b/lib/llm/editor/components/article_item.dart @@ -0,0 +1,74 @@ +import 'package:all_in_one/isar/article.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +typedef OnArticleSelected = void Function(Article); + +class ArticleItem extends ConsumerStatefulWidget { + const ArticleItem( + {super.key, required this.article, required this.onArticleSelected}); + final Article article; + final OnArticleSelected onArticleSelected; + + @override + ConsumerState createState() => _ArticleItemState(); +} + +class _ArticleItemState extends ConsumerState { + bool isHovering = false; + + @override + Widget build(BuildContext context) { + return MouseRegion( + cursor: SystemMouseCursors.click, + onEnter: (event) { + setState(() { + isHovering = true; + }); + }, + onExit: (event) { + setState(() { + isHovering = false; + }); + }, + child: GestureDetector( + onTap: () { + widget.onArticleSelected(widget.article); + }, + child: Container( + height: 40, + decoration: BoxDecoration( + color: isHovering + ? const Color.fromARGB(255, 197, 195, 227).withAlpha(100) + : Colors.transparent, + borderRadius: BorderRadius.circular(5)), + child: Row( + children: [ + Expanded( + flex: 1, + child: Text( + widget.article.title, + maxLines: 1, + softWrap: true, + overflow: TextOverflow.ellipsis, + ), + ), + Expanded( + flex: 1, + child: Text( + DateTime.fromMillisecondsSinceEpoch(widget.article.createAt) + .toString() + .split(".") + .first, + maxLines: 1, + softWrap: true, + overflow: TextOverflow.ellipsis, + ), + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/llm/editor/components/load_article_dialog.dart b/lib/llm/editor/components/load_article_dialog.dart new file mode 100644 index 0000000..4a57390 --- /dev/null +++ b/lib/llm/editor/components/load_article_dialog.dart @@ -0,0 +1,77 @@ +import 'package:all_in_one/llm/editor/components/article_item.dart'; +import 'package:all_in_one/llm/editor/notifiers/article_notifier.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +class LoadArticleDialog extends ConsumerStatefulWidget { + const LoadArticleDialog({super.key}); + + @override + ConsumerState createState() => _LoadArticleDialogState(); +} + +class _LoadArticleDialogState extends ConsumerState { + @override + Widget build(BuildContext context) { + final state = ref.watch(articleProvider); + + return Material( + elevation: 10, + borderRadius: BorderRadius.circular(20), + child: Container( + padding: const EdgeInsets.all(20), + width: MediaQuery.of(context).size.width * 0.8, + height: MediaQuery.of(context).size.height * 0.8, + decoration: BoxDecoration(borderRadius: BorderRadius.circular(20)), + child: state.when( + data: (v) { + if (v.isEmpty) { + return const Center( + child: Text("There is no template created."), + ); + } + + return Column( + children: [ + const SizedBox( + height: 50, + child: Row( + children: [ + Expanded( + flex: 1, + child: Text("name"), + ), + Expanded( + flex: 1, + child: Text("create at"), + ) + ], + ), + ), + Expanded( + child: ListView.builder( + itemBuilder: (c, i) { + return ArticleItem( + article: v[i], + onArticleSelected: (p0) { + Navigator.of(context).pop(p0); + }, + ); + }, + itemCount: v.length, + )), + ], + ); + }, + error: (_, s) { + return Center( + child: Text(s.toString()), + ); + }, + loading: () => const Center( + child: CircularProgressIndicator(), + )), + ), + ); + } +} diff --git a/lib/llm/editor/compose_screen.dart b/lib/llm/editor/compose_screen.dart index 8e053fc..62c70d9 100644 --- a/lib/llm/editor/compose_screen.dart +++ b/lib/llm/editor/compose_screen.dart @@ -4,10 +4,13 @@ import 'dart:convert'; import 'package:all_in_one/common/toast_utils.dart'; +import 'package:all_in_one/isar/article.dart'; import 'package:all_in_one/isar/llm_history.dart'; import 'package:all_in_one/isar/llm_template.dart'; import 'package:all_in_one/llm/ai_client.dart'; +import 'package:all_in_one/llm/editor/components/load_article_dialog.dart'; import 'package:all_in_one/llm/editor/models/datasource.dart'; +import 'package:all_in_one/llm/editor/notifiers/article_notifier.dart'; import 'package:all_in_one/llm/global/components/load_template_dialog.dart'; import 'package:all_in_one/llm/global/components/loading_dialog.dart'; import 'package:all_in_one/llm/global/components/sidemenu.dart'; @@ -93,12 +96,90 @@ class _ComposeScreenState extends ConsumerState { SidemenuButton( icon: Icons.file_open_outlined, title: "Load last", - onTap: () {}, + onTap: () async { + final Article? article = + await ref.read(articleProvider.notifier).getLast(); + if (article != null) { + setState(() { + _widgetBuilder = (context) => Editor( + // jsonString: Future(() => _jsonString), + datasource: Datasource( + type: DatasourceType.json, content: ""), + onEditorStateChange: (editorState) { + _editorState = editorState; + }, + showTemplateFeatures: false, + ); + isTemplateLoaded = true; + }); + + Future.delayed(const Duration(milliseconds: 200)).then( + (value) { + setState(() { + _widgetBuilder = (context) => Editor( + // jsonString: Future(() => _jsonString), + datasource: Datasource( + type: DatasourceType.json, + content: article.content), + onEditorStateChange: (editorState) { + _editorState = editorState; + }, + showTemplateFeatures: false, + ); + isTemplateLoaded = true; + }); + }, + ); + } + }, ), SidemenuButton( icon: Icons.file_open, title: "Load article...", - onTap: () {}, + onTap: () async { + final Article? article = await showGeneralDialog( + barrierColor: Colors.transparent, + barrierDismissible: true, + barrierLabel: "load-article", + context: context, + pageBuilder: (c, _, __) { + return const Center( + child: LoadArticleDialog(), + ); + }); + if (article != null) { + setState(() { + _widgetBuilder = (context) => Editor( + // jsonString: Future(() => _jsonString), + datasource: Datasource( + type: DatasourceType.json, content: ""), + onEditorStateChange: (editorState) { + _editorState = editorState; + }, + showTemplateFeatures: false, + ); + isTemplateLoaded = true; + }); + + Future.delayed(const Duration(milliseconds: 200)).then( + (value) { + setState(() { + _widgetBuilder = (context) => Editor( + // jsonString: Future(() => _jsonString), + datasource: Datasource( + type: DatasourceType.json, + content: article.content), + onEditorStateChange: (editorState) { + _editorState = editorState; + }, + showTemplateFeatures: false, + ); + isTemplateLoaded = true; + }); + }, + ); + } + }, ), SidemenuDivider(), SidemenuLabel(title: "Template"), diff --git a/lib/llm/editor/notifiers/article_notifier.dart b/lib/llm/editor/notifiers/article_notifier.dart new file mode 100644 index 0000000..595ff3d --- /dev/null +++ b/lib/llm/editor/notifiers/article_notifier.dart @@ -0,0 +1,31 @@ +import 'dart:async'; + +import 'package:all_in_one/isar/article.dart'; +import 'package:all_in_one/isar/database.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:isar/isar.dart'; + +class ArticleNotifier extends AutoDisposeAsyncNotifier> { + final IsarDatabase isarDatabase = IsarDatabase(); + + @override + FutureOr> build() async { + final articles = await isarDatabase.isar!.articles + .where() + .sortByCreateAtDesc() + .findAll(); + return articles; + } + + Future getLast() async { + return await isarDatabase.isar!.articles + .where() + .sortByCreateAtDesc() + .findFirst(); + } +} + +final articleProvider = + AutoDisposeAsyncNotifierProvider>(() { + return ArticleNotifier(); +}); diff --git a/lib/llm/template_editor/template_editor.dart b/lib/llm/template_editor/template_editor.dart index 144b21b..d821238 100644 --- a/lib/llm/template_editor/template_editor.dart +++ b/lib/llm/template_editor/template_editor.dart @@ -4,6 +4,7 @@ import 'dart:convert'; import 'package:all_in_one/common/toast_utils.dart'; import 'package:all_in_one/isar/llm_template.dart'; +import 'package:all_in_one/llm/global/components/load_template_dialog.dart'; import 'package:all_in_one/llm/global/components/sidemenu.dart'; import 'package:all_in_one/llm/global/components/sidemenu_widget.dart'; import 'package:all_in_one/llm/langchain/notifiers/tool_notifier.dart'; @@ -82,30 +83,6 @@ class _TemplateEditorState extends ConsumerState { }, showTemplateFeatures: true, ); - - /// FIXME - /// 返回的都是全文, - /// 如果是stream的返回方式 - /// 最好每次只返回最后的内容,不需要全文返回 - // stream.listen((event) { - // // print(event.response); - // for (final i in _editorState.document.root.children) { - // if ((i.attributes['delta'] as List).isNotEmpty) { - // // Node? existsNode = null; - // Map? map = null; - // for (int j = 0; j < i.attributes['delta'].length; j++) { - // if (i.attributes['delta'][j]["insert"] != null && - // i.attributes['delta'][j]["insert"].contains(event.prompt)) { - // map = i.attributes; - // map['delta'][j]['insert'] = event.prompt + event.response; - // } - // } - // if (map != null) { - // i.updateAttributes(map); - // } - // } - // } - // }); } final GlobalKey key = GlobalKey(); @@ -116,167 +93,6 @@ class _TemplateEditorState extends ConsumerState { return Scaffold( key: key, endDrawer: const ChainFlow(), - // floatingActionButtonLocation: ExpandableFab.location, - // floatingActionButton: ExpandableFab( - // distance: 50, - // type: ExpandableFabType.side, - // children: [ - // FloatingActionButton.small( - // tooltip: "chain viewer", - // heroTag: "", - // onPressed: () { - // if (ref.read(chainFlowProvider).items.flowItems.isEmpty) { - // return; - // } - - // if (key.currentState!.isEndDrawerOpen) { - // key.currentState!.closeEndDrawer(); - // } else { - // key.currentState!.openEndDrawer(); - // } - // }, - // child: const Icon(Bootstrap.view_list), - // ), - // FloatingActionButton.small( - // tooltip: "chain designer", - // heroTag: "", - // onPressed: () { - // ref - // .read(chainFlowProvider.notifier) - // .changeContent(jsonEncode(_editorState.document.toJson())); - - // showGeneralDialog( - // context: context, - // barrierColor: Colors.transparent, - // barrierLabel: "chain-flow", - // barrierDismissible: true, - // pageBuilder: (c, _, __) { - // return const Center( - // child: ChainFlowDesigner(), - // ); - // }); - // }, - // child: const Icon(Bootstrap.magic), - // ), - // FloatingActionButton.small( - // tooltip: "save template", - // heroTag: "", - // onPressed: () async { - // // print(_editorState.document.toJson()); - // final String? r = await showGeneralDialog( - // context: context, - // barrierDismissible: true, - // barrierColor: Colors.transparent, - // barrierLabel: "new-template", - // pageBuilder: (c, _, __) { - // return const Center( - // child: NewTemplateDialog(), - // ); - // }); - - // if (r != null) { - // ref - // .read(templateNotifierProvider.notifier) - // .addTemplate(LlmTemplate() - // ..template = jsonEncode(_editorState.document.toJson()) - // ..name = r); - // } - // }, - // child: const Icon(Bootstrap.download), - // ), - // FloatingActionButton.small( - // tooltip: "load template", - // heroTag: "", - // onPressed: () async {}, - // child: const Icon(Bootstrap.files), - // ), - // // FloatingActionButton.small( - // // tooltip: "generate from template", - // // heroTag: null, - // // child: const Icon(Bootstrap.file_word), - // // onPressed: () async { - // // if (widget.enablePlugin) { - // // // 存一份数据 - // // RecordUtils.putNewMessage( - // // MessageType.query, _editorState.toStr()); - // // } - // // ref - // // .read(chainFlowProvider.notifier) - // // .changeContent(jsonEncode(_editorState.document.toJson())); - // // final l = await ref.read(chainFlowProvider.notifier).toRust(); - - // // showGeneralDialog( - // // barrierDismissible: false, - // // barrierColor: Colors.transparent, - // // // ignore: use_build_context_synchronously - // // context: context, - // // pageBuilder: (c, _, __) { - // // return const LoadingDialog(); - // // }).then((_) async { - // // if (widget.enablePlugin) { - // // // 存一份数据 - // // RecordUtils.putNewMessage( - // // MessageType.response, _editorState.toStr()); - // // } - // // }); - - // // generateFromTemplate(v: l, enablePlugin: true) - // // .then((value) async { - // // final md = await optimizeDoc(s: _editorState.toStr()); - // // setState( - // // () { - // // _widgetBuilder = (context) => Editor( - // // datasource: Datasource( - // // type: DatasourceType.markdown, - // // content: md, - // // ), - // // onEditorStateChange: (editorState) { - // // _editorState = editorState; - // // }, - // // showTemplateFeatures: true, - // // ); - // // }, - // // ); - // // }); - // // }, - // // ), - // // FloatingActionButton.small( - // // tooltip: "test-chain", - // // heroTag: null, - // // child: const Icon(Bootstrap.activity), - // // onPressed: () async { - // // String s = jsonEncode(_editorState.document.toJson()); - // // if (widget.enablePlugin) { - // // // 存一份数据 - // // RecordUtils.putNewMessage( - // // MessageType.query, _editorState.toStr()); - // // } - // // final res = await templateRenderer(template: s); - // // if (res != null) { - // // _jsonString = jsonEncode(jsonDecode(res)); - - // // setState(() { - // // _editorState = - // // EditorState(document: Document.fromJson(jsonDecode(res))); - // // }); - // // if (widget.enablePlugin) { - // // // 存一份数据 - // // RecordUtils.putNewMessage( - // // MessageType.response, _editorState.toStr()); - // // } - // // } - // // }, - // // ), - // FloatingActionButton.small( - // tooltip: "back", - // heroTag: "", - // onPressed: () { - // ref.read(toolProvider.notifier).jumpTo(0); - // }, - // child: const Icon(Icons.chevron_left), - // ), - // ], - // ), extendBodyBehindAppBar: PlatformExtension.isDesktopOrWeb, body: SafeArea( child: Row( @@ -287,7 +103,49 @@ class _TemplateEditorState extends ConsumerState { SidemenuButton( icon: EvaIcons.file_text, title: "Load Template", - onTap: () {}, + onTap: () async { + final LlmTemplate? template = await showGeneralDialog( + barrierColor: Colors.transparent, + barrierDismissible: true, + barrierLabel: "load-template", + context: context, + pageBuilder: (c, _, __) { + return const Center( + child: LoadTemplateDialog(), + ); + }); + + if (template != null) { + setState(() { + _widgetBuilder = (context) => Editor( + // jsonString: Future(() => _jsonString), + datasource: Datasource( + type: DatasourceType.json, content: ""), + onEditorStateChange: (editorState) { + _editorState = editorState; + }, + showTemplateFeatures: true, + ); + }); + + Future.delayed(const Duration(milliseconds: 200)).then( + (value) { + setState(() { + _widgetBuilder = (context) => Editor( + // jsonString: Future(() => _jsonString), + datasource: Datasource( + type: DatasourceType.json, + content: template.template), + onEditorStateChange: (editorState) { + _editorState = editorState; + }, + showTemplateFeatures: true, + ); + }); + }, + ); + } + }, ), SidemenuButton( icon: EvaIcons.save, diff --git a/pubspec.yaml b/pubspec.yaml index b64f23e..a447ab2 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -2,7 +2,7 @@ name: all_in_one description: "A new Flutter project." publish_to: 'none' # Remove this line if you wish to publish to pub.dev -version: 0.0.9 +version: 0.0.10 environment: sdk: '>=3.3.0 <4.0.0'