feat: implement some api; add md editor to app; login and signup logic.

This commit is contained in:
2021-12-30 20:04:00 +08:00
parent 1a0e8f8de7
commit 853132f1a8
61 changed files with 3205 additions and 149 deletions
+17
View File
@@ -107,6 +107,23 @@ class DButton extends StatefulWidget {
message: LocaleKeys.operation_paste.tr(),
));
factory DButton.logout({
Key? key,
required enabled,
GestureTapCallback? onTap,
height = defaultButtonHeight,
width = defaultButtonHeight,
}) =>
DButton(
key: key,
width: width,
height: height,
onTap: enabled ? onTap : null,
child: Tooltip(
child: Opacity(opacity: enabled ? 1 : 0.4, child: const Icon(Icons.logout_rounded, size: 20)),
message: LocaleKeys.operation_logout.tr(),
));
factory DButton.dropdown({
Key? key,
width = 60.0,
+9 -1
View File
@@ -2,6 +2,7 @@ import 'package:cached_network_image/cached_network_image.dart';
import 'package:dde_gesture_manager/constants/constants.dart';
import 'package:dde_gesture_manager/extensions.dart';
import 'package:dde_gesture_manager/models/settings.provider.dart';
import 'package:dde_gesture_manager/utils/notificator.dart';
import 'package:flutter/material.dart';
import 'package:markdown_editor_ot/markdown_editor.dart';
import 'package:url_launcher/url_launcher.dart';
@@ -77,11 +78,18 @@ class _DMarkdownFieldState extends State<DMarkdownField> {
});
},
child: MouseRegion(
cursor: widget.readOnly ? SystemMouseCursors.basic : SystemMouseCursors.click,
cursor: widget.readOnly ? SystemMouseCursors.basic : SystemMouseCursors.text,
child: MdPreview(
text: _previewText ?? '',
padding: EdgeInsets.only(left: 15),
onTapLink: _launchURL,
onCodeCopied: () {
Notificator.success(
context,
title: LocaleKeys.info_code_copied_titte.tr(),
description: LocaleKeys.info_code_copied_description.tr(),
);
},
widgetImage: (imageUrl) => CachedNetworkImage(
imageUrl: imageUrl,
placeholder: (context, url) => const SizedBox(
+102
View File
@@ -0,0 +1,102 @@
import 'dart:io';
import 'package:dde_gesture_manager/constants/sp_keys.dart';
import 'package:dde_gesture_manager/extensions.dart';
import 'package:dde_gesture_manager/http/api.dart';
import 'package:dde_gesture_manager/models/configs.provider.dart';
import 'package:dde_gesture_manager/models/settings.provider.dart';
import 'package:dde_gesture_manager/utils/helper.dart';
import 'package:dde_gesture_manager/utils/notificator.dart';
import 'package:flutter/material.dart';
import 'package:flutter_login/flutter_login.dart';
class LoginWidget extends StatefulWidget {
const LoginWidget({
Key? key,
}) : super(key: key);
@override
_LoginWidgetState createState() => _LoginWidgetState();
}
class _LoginWidgetState extends State<LoginWidget> {
ValueKey<int> _key = ValueKey(0);
@override
Widget build(BuildContext context) {
return Expanded(
child: OverflowBox(
alignment: Alignment.topCenter,
child: Container(
child: ScrollConfiguration(
behavior: const ScrollBehavior().copyWith(
physics: const NeverScrollableScrollPhysics(),
),
child: FlutterLogin(
key: _key,
onLogin: (loginData) async {
try {
var res = await Api.loginOrSignup(email: loginData.name, password: loginData.password);
if (res != null && res.token.notNull)
context.read<ConfigsProvider>().setProps(accessToken: res.token, email: loginData.name);
} catch (e) {
if (!(e is HttpErrorCode)) return;
var code = e.statusCode;
if (code == HttpStatus.unauthorized)
Notificator.error(
context,
title: LocaleKeys.info_login_failed_title.tr(),
description: LocaleKeys.info_login_failed_description.tr(),
);
else if (code == HttpStatus.notFound)
Notificator.info(
context,
title: LocaleKeys.info_sign_up_hint_title.tr(),
description: LocaleKeys.info_sign_up_hint_description.tr(),
);
else
throw e;
}
},
onSubmitAnimationCompleted: () {
var token = H().sp.getString(SPKeys.accessToken);
if (token.isNull)
setState(() {
_key = ValueKey(_key.value + 1);
});
else if (context.read<ConfigsProvider>().accessToken != token)
context
.read<ConfigsProvider>()
.setProps(accessToken: token, email: H().sp.getString(SPKeys.loginEmail));
},
onRecoverPassword: (_) {},
hideForgotPasswordButton: true,
disableCustomPageTransformer: true,
messages: LoginMessages(
userHint: LocaleKeys.me_login_email_hint.tr(),
passwordHint: LocaleKeys.me_login_password_hint.tr(),
loginButton: LocaleKeys.me_login_login_or_signup.tr(),
),
userValidator: (value) {
if (FlutterLogin.defaultEmailValidator(value) != null) {
return LocaleKeys.me_login_email_error_hint.tr();
}
},
passwordValidator: (value) {
if (value!.isEmpty || value.length < 8 || value.length > 16) {
return LocaleKeys.me_login_password_hint.tr();
}
},
theme: LoginTheme(
pageColorDark: Colors.transparent,
pageColorLight: Colors.transparent,
primaryColor: context.watch<SettingsProvider>().currentActiveColor,
footerBackgroundColor: Colors.transparent,
),
),
),
),
),
);
}
}
+31 -19
View File
@@ -1,11 +1,12 @@
import 'dart:convert';
import 'package:dde_gesture_manager/extensions.dart';
import 'package:flutter/material.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:http/http.dart' as http;
import 'package:dde_gesture_manager/http/api.dart';
import 'package:dde_gesture_manager/utils/notificator.dart';
import 'package:dde_gesture_manager_api/apis.dart';
import 'package:dde_gesture_manager_api/models.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_platform_alert/flutter_platform_alert.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:url_launcher/url_launcher.dart';
class VersionChecker extends StatelessWidget {
const VersionChecker({Key? key}) : super(key: key);
@@ -22,20 +23,31 @@ class VersionChecker extends StatelessWidget {
Text(
'${LocaleKeys.version_current.tr()} : ${snapshot.data?.version ?? ''}',
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 3),
child: TextButton(
child: Text(LocaleKeys.version_check_update).tr(),
onPressed: () {
http.get(Uri.parse('http://127.0.0.1:3000' + Apis.system.appVersion)).then((value) {
var appVersion = AppVersionSerializer.fromMap(json.decode(value.body));
appVersion.versionName.sout();
appVersion.versionCode.sout();
appVersion.sout();
});
},
if (!kIsWeb)
Padding(
padding: const EdgeInsets.symmetric(horizontal: 3),
child: TextButton(
child: Text(LocaleKeys.version_check_update).tr(),
onPressed: () {
Api.checkAppVersion().then((value) {
if (value != null && (value.versionCode ?? 0) > int.parse(snapshot.data?.buildNumber ?? '0')) {
Notificator.showConfirm(
title: LocaleKeys.info_new_version_title.tr(namedArgs: {'version': '${value.versionName}'}),
description: LocaleKeys.info_new_version_description_for_manual.tr(),
).then((value) async {
if (value == CustomButton.positiveButton) {
if (await canLaunch(Apis.appNewVersionUrl)) {
await launch(Apis.appNewVersionUrl);
}
}
});
} else {
Notificator.info(context, title: LocaleKeys.info_new_version_title_already_latest.tr());
}
});
},
),
),
),
],
),
);