From 0c87b714c424cf9efc956d359b1530c3f6bf91d6 Mon Sep 17 00:00:00 2001 From: debuggerx Date: Mon, 21 Feb 2022 14:42:18 +0800 Subject: [PATCH] feat: add startup bulletin; switch to edit mode when click text on md preview. --- api/lib/apis.dart | 3 ++ app/3rd_party/markdown_core/lib/builder.dart | 3 ++ app/3rd_party/markdown_core/lib/markdown.dart | 4 ++ .../markdown_editor_ot/lib/src/preview.dart | 4 ++ app/build_web.sh | 3 ++ app/lib/constants/sp_keys.dart | 1 + app/lib/http/api.dart | 52 ++++++++++++++----- app/lib/main.dart | 13 +++++ app/lib/widgets/dde_markdown_field.dart | 17 +++--- app/web/bulletin.json | 6 +++ 10 files changed, 86 insertions(+), 20 deletions(-) create mode 100644 app/web/bulletin.json diff --git a/api/lib/apis.dart b/api/lib/apis.dart index f0a58f3..e17dc0f 100644 --- a/api/lib/apis.dart +++ b/api/lib/apis.dart @@ -5,6 +5,9 @@ class Apis { static const appNewVersionUrl = 'https://www.debuggerx.com/2022/01/21/dgm-changelog?from=app'; + static appBulletinUrl(bool isWeb) => + 'https://www.debuggerx.com/dgm_web/bulletin.json?from=app_${isWeb ? 'web' : 'linux'}'; + static appManualUrl(bool isWeb) => 'https://www.debuggerx.com/2022/01/21/dgm-manual?from=app_${isWeb ? 'web' : 'linux'}'; diff --git a/app/3rd_party/markdown_core/lib/builder.dart b/app/3rd_party/markdown_core/lib/builder.dart index cff6d8e..cb1c732 100644 --- a/app/3rd_party/markdown_core/lib/builder.dart +++ b/app/3rd_party/markdown_core/lib/builder.dart @@ -19,6 +19,7 @@ class MarkdownBuilder implements md.NodeVisitor { this.defaultTextStyle, { this.tagTextStyle = defaultTagTextStyle, required this.onCodeCopied, + this.richTap, }); final _widgets = []; @@ -30,6 +31,7 @@ class MarkdownBuilder implements md.NodeVisitor { final BuildContext context; final LinkTap linkTap; + final VoidCallback? richTap; final WidgetImage widgetImage; final double maxWidth; final Function onCodeCopied; @@ -125,6 +127,7 @@ class MarkdownBuilder implements md.NodeVisitor { children: last.textSpans, style: last.textStyle, ), + onTap: richTap, ); } } diff --git a/app/3rd_party/markdown_core/lib/markdown.dart b/app/3rd_party/markdown_core/lib/markdown.dart index 5da7aad..82270ef 100644 --- a/app/3rd_party/markdown_core/lib/markdown.dart +++ b/app/3rd_party/markdown_core/lib/markdown.dart @@ -14,6 +14,7 @@ class Markdown extends StatefulWidget { required this.onCodeCopied, this.maxWidth, this.textStyle, + this.richTap, }) : super(key: key); final String data; @@ -28,6 +29,8 @@ class Markdown extends StatefulWidget { final Function onCodeCopied; + final VoidCallback? richTap; + @override MarkdownState createState() => MarkdownState(); } @@ -62,6 +65,7 @@ class MarkdownState extends State { widget.maxWidth ?? MediaQuery.of(context).size.width, widget.textStyle ?? defaultTextStyle(context), onCodeCopied: widget.onCodeCopied, + richTap: widget.richTap, ).build(nodes); } } diff --git a/app/3rd_party/markdown_editor_ot/lib/src/preview.dart b/app/3rd_party/markdown_editor_ot/lib/src/preview.dart index d93ca16..c822d0b 100644 --- a/app/3rd_party/markdown_editor_ot/lib/src/preview.dart +++ b/app/3rd_party/markdown_editor_ot/lib/src/preview.dart @@ -11,6 +11,7 @@ class MdPreview extends StatefulWidget { required this.widgetImage, required this.onCodeCopied, this.textStyle, + this.richTap, }) : super(key: key); final String text; @@ -24,6 +25,8 @@ class MdPreview extends StatefulWidget { /// If [onTapLink] is null,it will open the link with your default browser. final TapLinkCallback? onTapLink; + final VoidCallback? richTap; + @override State createState() => MdPreviewState(); } @@ -50,6 +53,7 @@ class MdPreviewState extends State image: widget.widgetImage, textStyle: widget.textStyle, onCodeCopied: widget.onCodeCopied, + richTap: widget.richTap, ); }, ), diff --git a/app/build_web.sh b/app/build_web.sh index c0e94fb..e4fc23d 100755 --- a/app/build_web.sh +++ b/app/build_web.sh @@ -12,3 +12,6 @@ sed -i -e "s!$wasmLocation!.!" \ -e "s!https://fonts.googleapis.com/css2?family=Noto+Sans+Symbols!./assets/assets/css/Noto-Sans-Symbols.css!" \ -e "s!https://fonts.googleapis.com/css2?family=Noto+Color+Emoji+Compat!./assets/assets/css/Noto-Color-Emoji-Compat.css!" \ build/web/main.dart.js + + +# git init && git add . && git commit -m 'update' && git remote add origin git@github.com:debuggerx01/dgm_web.git && git push --set-upstream origin master -f \ No newline at end of file diff --git a/app/lib/constants/sp_keys.dart b/app/lib/constants/sp_keys.dart index aac5a36..890d91e 100644 --- a/app/lib/constants/sp_keys.dart +++ b/app/lib/constants/sp_keys.dart @@ -5,4 +5,5 @@ class SPKeys { static final String accessToken = 'USER_ACCESS_TOKEN'; static final String loginEmail = 'USER_LOGIN_EMAIL'; static final String ignoredUpdateVersion = 'IGNORED_UPDATE_VERSION'; + static final String readBulletinId = 'READ_BULLETIN_ID'; } diff --git a/app/lib/http/api.dart b/app/lib/http/api.dart index 6103ba8..c14ac1a 100644 --- a/app/lib/http/api.dart +++ b/app/lib/http/api.dart @@ -63,6 +63,8 @@ class Api { return res; }; + static final _fullPathRegExp = RegExp('http(s?)://'); + static Future _get( String path, BeanBuilder builder, { @@ -72,13 +74,15 @@ class Api { }) => http .get( - Uri( - scheme: Apis.apiScheme, - host: Apis.apiHost, - port: Apis.apiPort, - queryParameters: queryParams, - path: path, - ), + path.startsWith(_fullPathRegExp) + ? Uri.parse(path) + : Uri( + scheme: Apis.apiScheme, + host: Apis.apiHost, + port: Apis.apiPort, + queryParameters: queryParams, + path: path, + ), headers: { HttpHeaders.contentTypeHeader: ContentType.json.toString(), }..addAll( @@ -103,12 +107,14 @@ class Api { }) => http .post( - Uri( - scheme: Apis.apiScheme, - host: Apis.apiHost, - port: Apis.apiPort, - path: path, - ), + path.startsWith(_fullPathRegExp) + ? Uri.parse(path) + : Uri( + scheme: Apis.apiScheme, + host: Apis.apiHost, + port: Apis.apiPort, + path: path, + ), body: jsonEncode(body), headers: { HttpHeaders.contentTypeHeader: ContentType.json.toString(), @@ -199,6 +205,26 @@ class Api { Apis.scheme.userLikes, (e) => (e['list'] as List).cast(), ); + + static Future checkBulletin(bool isWeb) => _get( + Apis.appBulletinUrl(isWeb), + AppBulletinResp.fromMap, + ignoreErrorHandle: true, + ignoreToken: true, + ).catchError((_) {}); +} + +class AppBulletinResp { + int? id; + bool? once; + String? title; + String? content; + + AppBulletinResp.fromMap(Map map) + : id = map['id'], + once = map['once'], + title = map['title'], + content = map['content']; } class MarketSchemeTransMetaDataResp { diff --git a/app/lib/main.dart b/app/lib/main.dart index 086a468..aaa8584 100644 --- a/app/lib/main.dart +++ b/app/lib/main.dart @@ -11,6 +11,7 @@ import 'package:dde_gesture_manager/themes/dark.dart'; import 'package:dde_gesture_manager/themes/light.dart'; import 'package:dde_gesture_manager/utils/helper.dart'; import 'package:dde_gesture_manager/utils/init.dart'; +import 'package:dde_gesture_manager/utils/notificator.dart'; import 'package:dde_gesture_manager/utils/simple_throttle.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -89,6 +90,7 @@ class MyApp extends StatelessWidget { Sentry.captureMessage, timeout: const Duration(days: 1), )?.call('App launched'); + SimpleThrottle.throttledFunc(_checkBulletin, timeout: const Duration(days: 1))?.call(context); }); return Container(); }), @@ -112,3 +114,14 @@ void _checkAuthStatus(BuildContext context) { H().lastCheckAuthStatusTime = DateTime.now(); } } + +void _checkBulletin(BuildContext context) { + Api.checkBulletin(kIsWeb).then((value) { + if (value != null && value.id != null) { + if (value.once == false || (H().sp.getInt(SPKeys.readBulletinId) ?? 0) < value.id!) { + Notificator.showAlert(title: value.title ?? '', description: value.content ?? ''); + } + H().sp.setInt(SPKeys.readBulletinId, value.id!); + } + }); +} diff --git a/app/lib/widgets/dde_markdown_field.dart b/app/lib/widgets/dde_markdown_field.dart index ff53ac2..cf96416 100644 --- a/app/lib/widgets/dde_markdown_field.dart +++ b/app/lib/widgets/dde_markdown_field.dart @@ -46,6 +46,14 @@ class _DMarkdownFieldState extends State { super.didUpdateWidget(oldWidget); } + VoidCallback? get _onMdPreviewTap => widget.readOnly + ? null + : () { + setState(() { + _previewText = null; + }); + }; + @override Widget build(BuildContext context) { return Focus( @@ -62,19 +70,14 @@ class _DMarkdownFieldState extends State { ), child: isPreview ? GestureDetector( - onTap: widget.readOnly - ? null - : () { - setState(() { - _previewText = null; - }); - }, + onTap: _onMdPreviewTap, child: MouseRegion( cursor: widget.readOnly ? SystemMouseCursors.basic : SystemMouseCursors.text, child: MdPreview( text: _previewText ?? '', padding: EdgeInsets.only(left: 15), onTapLink: H.launchURL, + richTap: _onMdPreviewTap, textStyle: context.t.textTheme.bodyText2, onCodeCopied: () { Notificator.success( diff --git a/app/web/bulletin.json b/app/web/bulletin.json new file mode 100644 index 0000000..8efd1c5 --- /dev/null +++ b/app/web/bulletin.json @@ -0,0 +1,6 @@ +{ + "id": 1, + "once": true, + "title": "欢迎", + "content": "感谢使用本工具,使用前建议先点击右下角阅读使用说明哦~" +} \ No newline at end of file