From 91d238bc2f340cf5307ddd9baf68c04acf2518ec Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Sun, 24 Mar 2024 22:57:12 +0800 Subject: [PATCH] :sparkles: Post details :lipstick: Somewhere optimization --- lib/router.dart | 14 +++++- lib/screens/explore.dart | 2 +- lib/screens/posts/screen.dart | 64 +++++++++++++++++++++++++ lib/screens/publish/comment_editor.dart | 4 +- lib/screens/publish/moment_editor.dart | 4 +- lib/widgets/feed.dart | 33 +++++++++---- lib/widgets/posts/comments.dart | 2 +- lib/widgets/posts/content/article.dart | 31 ++++++++++-- lib/widgets/posts/content/moment.dart | 4 +- pubspec.lock | 2 +- pubspec.yaml | 1 + 11 files changed, 139 insertions(+), 22 deletions(-) create mode 100644 lib/screens/posts/screen.dart diff --git a/lib/router.dart b/lib/router.dart index c416d69..10bbba5 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -3,6 +3,7 @@ import 'package:solaragent/models/feed.dart'; import 'package:solaragent/screens/account.dart'; import 'package:solaragent/screens/explore.dart'; import 'package:solaragent/screens/notifications.dart'; +import 'package:solaragent/screens/posts/screen.dart'; import 'package:solaragent/screens/publish/comment_editor.dart'; import 'package:solaragent/screens/publish/moment_editor.dart'; @@ -20,14 +21,23 @@ final router = GoRouter( path: '/account', builder: (context, state) => const AccountScreen(), ), + GoRoute( - path: '/post/moments', + path: '/post/new/moments', builder: (context, state) => const MomentEditorScreen(), ), GoRoute( - path: '/post/comments', + path: '/post/new/comments', builder: (context, state) => CommentEditorScreen(parent: state.extra as Feed), ), + + GoRoute( + path: '/post/:modelType/:alias', + builder: (context, state) => PostScreen( + modelType: state.pathParameters['modelType'] as String, + alias: state.pathParameters['alias'] as String, + ), + ), ], ); diff --git a/lib/screens/explore.dart b/lib/screens/explore.dart index 50ba177..c1589b2 100644 --- a/lib/screens/explore.dart +++ b/lib/screens/explore.dart @@ -83,7 +83,7 @@ class _ExploreScreenState extends State { return FloatingActionButton( child: const Icon(Icons.edit), onPressed: () { - router.push("/post/moments").then((value) { + router.push("/post/new/moments").then((value) { if (value == true) paginationController.refresh(); }); }, diff --git a/lib/screens/posts/screen.dart b/lib/screens/posts/screen.dart new file mode 100644 index 0000000..43bf5ba --- /dev/null +++ b/lib/screens/posts/screen.dart @@ -0,0 +1,64 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:http/http.dart'; +import 'package:solaragent/models/feed.dart'; +import 'package:solaragent/widgets/feed.dart'; + +class PostScreen extends StatefulWidget { + final Client client = Client(); + + final String modelType; + final String alias; + + PostScreen({super.key, required this.modelType, required this.alias}); + + @override + State createState() => _PostScreenState(); +} + +class _PostScreenState extends State { + Future pullPost(BuildContext context) async { + var uri = Uri.parse( + "https://co.solsynth.dev/api/p/${widget.modelType}s/${widget.alias}", + ); + var res = await widget.client.get(uri); + if (res.statusCode != 200) { + var err = utf8.decode(res.bodyBytes); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text("Something went wrong... $err")), + ); + return null; + } else { + return Feed.fromJson(jsonDecode(utf8.decode(res.bodyBytes))); + } + } + + Widget buildItem(BuildContext context, Feed item) { + return FeedItem( + item: item, + brief: false, + ); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text("Post")), + body: FutureBuilder( + future: pullPost(context), + builder: (context, snapshot) { + if (snapshot.hasData && snapshot.data != null) { + return SingleChildScrollView( + child: buildItem(context, snapshot.data!), + ); + } else { + return const Center( + child: CircularProgressIndicator(), + ); + } + }, + ), + ); + } +} diff --git a/lib/screens/publish/comment_editor.dart b/lib/screens/publish/comment_editor.dart index 91b5d6f..ec472b6 100644 --- a/lib/screens/publish/comment_editor.dart +++ b/lib/screens/publish/comment_editor.dart @@ -132,7 +132,9 @@ class _CommentEditorScreenState extends State { child: const Text('OPEN'), onPressed: () async { await launchUrl( - Uri.parse("https://co.solsynth.dev")); + Uri.parse("https://co.solsynth.dev"), + mode: LaunchMode.externalApplication, + ); }, ), TextButton( diff --git a/lib/screens/publish/moment_editor.dart b/lib/screens/publish/moment_editor.dart index 5f456ee..6d89aba 100644 --- a/lib/screens/publish/moment_editor.dart +++ b/lib/screens/publish/moment_editor.dart @@ -154,7 +154,9 @@ class _MomentEditorScreenState extends State { child: const Text('OPEN'), onPressed: () async { await launchUrl( - Uri.parse("https://co.solsynth.dev")); + Uri.parse("https://co.solsynth.dev"), + mode: LaunchMode.externalApplication, + ); }, ), TextButton( diff --git a/lib/widgets/feed.dart b/lib/widgets/feed.dart index e5f5ebc..357c2d9 100644 --- a/lib/widgets/feed.dart +++ b/lib/widgets/feed.dart @@ -1,7 +1,9 @@ import 'package:flutter/material.dart'; import 'package:flutter_carousel_widget/flutter_carousel_widget.dart'; import 'package:flutter_markdown/flutter_markdown.dart'; +import 'package:go_router/go_router.dart'; import 'package:solaragent/models/feed.dart'; +import 'package:solaragent/router.dart'; import 'package:solaragent/widgets/image.dart'; import 'package:solaragent/widgets/posts/comments.dart'; import 'package:solaragent/widgets/posts/content/article.dart'; @@ -65,19 +67,11 @@ class _FeedItemState extends State { case "article": return ArticleContent(item: widget.item, brief: widget.brief ?? false); default: - return MomentContent(item: widget.item); + return MomentContent(item: widget.item, brief: widget.brief ?? false); } } - @override - void initState() { - reactionCount = widget.item.reactionCount; - reactionList = widget.item.reactionList ?? {}; - super.initState(); - } - - @override - Widget build(BuildContext context) { + Widget buildItem(BuildContext context) { return Column( children: [ Container( @@ -161,4 +155,23 @@ class _FeedItemState extends State { ], ); } + + @override + void initState() { + reactionCount = widget.item.reactionCount; + reactionList = widget.item.reactionList ?? {}; + super.initState(); + } + + @override + Widget build(BuildContext context) { + return (widget.brief ?? false) + ? GestureDetector( + child: buildItem(context), + onTap: () => router.push( + "/post/${widget.item.modelType}/${widget.item.alias}", + ), + ) + : buildItem(context); + } } diff --git a/lib/widgets/posts/comments.dart b/lib/widgets/posts/comments.dart index 88e036c..8255bd4 100644 --- a/lib/widgets/posts/comments.dart +++ b/lib/widgets/posts/comments.dart @@ -93,7 +93,7 @@ class _CommentListState extends State { label: const Text("LEAVE COMMENT"), onPressed: () { router - .push("/post/comments", extra: widget.parent) + .push("/post/new/comments", extra: widget.parent) .then((value) { if (value == true) paginationController.refresh(); }); diff --git a/lib/widgets/posts/content/article.dart b/lib/widgets/posts/content/article.dart index 0f8c17d..acafe56 100644 --- a/lib/widgets/posts/content/article.dart +++ b/lib/widgets/posts/content/article.dart @@ -1,6 +1,9 @@ import 'package:flutter/material.dart'; import 'package:flutter_markdown/flutter_markdown.dart'; import 'package:solaragent/models/feed.dart'; +import 'package:markdown/markdown.dart' as md; +import 'package:url_launcher/url_launcher.dart'; +import 'package:url_launcher/url_launcher_string.dart'; class ArticleContent extends StatelessWidget { final Feed item; @@ -15,10 +18,30 @@ class ArticleContent extends StatelessWidget { title: Text(item.title), subtitle: Text(item.description), ) - : Markdown( - data: item.content, - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), + : Column( + children: [ + ListTile( + title: Text(item.title), + subtitle: Text(item.description), + ), + const Divider(color: Color(0xffefefef)), + Markdown( + selectable: !brief, + data: item.content, + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + extensionSet: md.ExtensionSet( + md.ExtensionSet.gitHubFlavored.blockSyntaxes, + md.ExtensionSet.gitHubFlavored.inlineSyntaxes, + ), + onTapLink: (text, href, title) async { + if (href == null) return; + await launchUrlString( + href, + mode: LaunchMode.externalApplication, + ); + }), + ], ); } } diff --git a/lib/widgets/posts/content/moment.dart b/lib/widgets/posts/content/moment.dart index bc004d8..43a7564 100644 --- a/lib/widgets/posts/content/moment.dart +++ b/lib/widgets/posts/content/moment.dart @@ -4,12 +4,14 @@ import 'package:solaragent/models/feed.dart'; class MomentContent extends StatelessWidget { final Feed item; + final bool brief; - const MomentContent({super.key, required this.item}); + const MomentContent({super.key, required this.brief, required this.item}); @override Widget build(BuildContext context) { return Markdown( + selectable: !brief, data: item.content, shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), diff --git a/pubspec.lock b/pubspec.lock index 2519c0e..58cefad 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -449,7 +449,7 @@ packages: source: hosted version: "1.2.0" markdown: - dependency: transitive + dependency: "direct main" description: name: markdown sha256: ef2a1298144e3f985cc736b22e0ccdaf188b5b3970648f2d9dc13efd1d9df051 diff --git a/pubspec.yaml b/pubspec.yaml index 7c026c1..bab413c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -50,6 +50,7 @@ dependencies: sentry_flutter: ^7.18.0 crypto: ^3.0.3 file_picker: ^8.0.0+1 + markdown: ^7.2.2 dev_dependencies: flutter_test: