feat: implement some api; add md editor to app; login and signup logic.
This commit is contained in:
@@ -1,10 +1,9 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
|
||||
/// [UOS设计指南](https://docs.uniontech.com/zh/content/t_dbG3kBK9iDf9B963ok)
|
||||
|
||||
const double localManagerPanelWidth = 260;
|
||||
|
||||
const double marketPanelWidth = 300;
|
||||
const double marketOrMePanelWidth = 300;
|
||||
|
||||
const shortDuration = const Duration(milliseconds: 100);
|
||||
|
||||
@@ -39,5 +38,5 @@ const List<String> builtInCommands = [
|
||||
|
||||
enum PanelType {
|
||||
local_manager,
|
||||
market,
|
||||
market_or_me,
|
||||
}
|
||||
|
||||
@@ -2,4 +2,7 @@ class SPKeys {
|
||||
static final String brightnessMode = 'BRIGHTNESS_MODE';
|
||||
static final String appliedSchemeId = 'APPLIED_SCHEME_ID';
|
||||
static final String userLanguage = 'USER_LANGUAGE';
|
||||
static final String accessToken = 'USER_ACCESS_TOKEN';
|
||||
static final String loginEmail = 'USER_LOGIN_EMAIL';
|
||||
static final String ignoredUpdateVersion = 'IGNORED_UPDATE_VERSION';
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
extension StringNotNull on String? {
|
||||
bool get notNull => this != null && this != '';
|
||||
|
||||
bool get isNull => !notNull;
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:dde_gesture_manager/constants/sp_keys.dart';
|
||||
import 'package:dde_gesture_manager/extensions.dart';
|
||||
import 'package:dde_gesture_manager/utils/helper.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:http/http.dart' as http;
|
||||
|
||||
typedef T BeanBuilder<T>(Map res);
|
||||
|
||||
typedef T HandleRespBuild<T>(http.Response resp);
|
||||
|
||||
getStatusCodeFunc<int>(Map resp) => resp["statusCode"];
|
||||
|
||||
class HttpErrorCode extends Error {
|
||||
int statusCode;
|
||||
|
||||
HttpErrorCode(this.statusCode, {this.message});
|
||||
|
||||
String? message;
|
||||
|
||||
@override
|
||||
String toString() => '[$statusCode] $message';
|
||||
}
|
||||
|
||||
class Api {
|
||||
static _handleHttpError(e) {
|
||||
if (e is SocketException) {
|
||||
Notificator.error(
|
||||
H().topContext,
|
||||
title: LocaleKeys.info_server_error_title.tr(),
|
||||
description: LocaleKeys.info_server_error_description.tr(),
|
||||
);
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
static HandleRespBuild<T> _handleRespBuild<T>(BeanBuilder<T> builder) => (http.Response resp) {
|
||||
if (builder == getStatusCodeFunc) return builder({"statusCode": resp.statusCode});
|
||||
T res;
|
||||
try {
|
||||
res = builder(json.decode(resp.body));
|
||||
} catch (e) {
|
||||
throw HttpErrorCode(resp.statusCode, message: resp.body);
|
||||
}
|
||||
return res;
|
||||
};
|
||||
|
||||
static Future<T> _get<T>(
|
||||
String path,
|
||||
BeanBuilder<T> builder, {
|
||||
Map<String, dynamic>? queryParams,
|
||||
bool ignoreToken = false,
|
||||
bool ignoreErrorHandle = false,
|
||||
}) =>
|
||||
http
|
||||
.get(
|
||||
Uri(
|
||||
scheme: Apis.apiScheme,
|
||||
host: Apis.apiHost,
|
||||
port: Apis.apiPort,
|
||||
queryParameters: queryParams,
|
||||
path: path,
|
||||
),
|
||||
headers: <String, String>{
|
||||
HttpHeaders.contentTypeHeader: ContentType.json.value,
|
||||
}..addAll(
|
||||
ignoreToken ? {} : {HttpHeaders.authorizationHeader: 'Bearer ${H().sp.getString(SPKeys.accessToken)}'}),
|
||||
)
|
||||
.then(
|
||||
_handleRespBuild<T>(builder),
|
||||
onError: (e) {
|
||||
if (ignoreErrorHandle)
|
||||
throw e;
|
||||
else
|
||||
return _handleHttpError(e);
|
||||
},
|
||||
);
|
||||
|
||||
static Future<T> _post<T>(
|
||||
String path,
|
||||
BeanBuilder<T> builder, {
|
||||
Map<String, dynamic>? body,
|
||||
bool ignoreToken = false,
|
||||
bool ignoreErrorHandle = false,
|
||||
}) =>
|
||||
http
|
||||
.post(
|
||||
Uri(
|
||||
scheme: Apis.apiScheme,
|
||||
host: Apis.apiHost,
|
||||
port: Apis.apiPort,
|
||||
path: path,
|
||||
),
|
||||
body: jsonEncode(body),
|
||||
headers: <String, String>{
|
||||
HttpHeaders.contentTypeHeader: ContentType.json.value,
|
||||
}..addAll(
|
||||
ignoreToken ? {} : {HttpHeaders.authorizationHeader: 'Bearer ${H().sp.getString(SPKeys.accessToken)}'}),
|
||||
)
|
||||
.then(
|
||||
_handleRespBuild<T>(builder),
|
||||
onError: (e) {
|
||||
if (ignoreErrorHandle)
|
||||
throw e;
|
||||
else
|
||||
return _handleHttpError(e);
|
||||
},
|
||||
);
|
||||
|
||||
static Future<LoginSuccess?> loginOrSignup({
|
||||
required String email,
|
||||
required String password,
|
||||
}) =>
|
||||
_post<LoginSuccess?>(
|
||||
Apis.auth.loginOrSignup,
|
||||
LoginSuccessSerializer.fromMap,
|
||||
body: {
|
||||
UserFields.email: email,
|
||||
UserFields.password: password,
|
||||
},
|
||||
ignoreToken: true,
|
||||
);
|
||||
|
||||
static Future<AppVersion?> checkAppVersion({ignoreErrorHandle = false}) => _get<AppVersion?>(
|
||||
Apis.system.appVersion,
|
||||
AppVersionSerializer.fromMap,
|
||||
ignoreToken: true,
|
||||
ignoreErrorHandle: ignoreErrorHandle,
|
||||
);
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:dde_gesture_manager/builder/provider_annotation.dart';
|
||||
import 'package:dde_gesture_manager/constants/sp_keys.dart';
|
||||
import 'package:dde_gesture_manager/extensions.dart';
|
||||
import 'package:dde_gesture_manager/utils/helper.dart';
|
||||
|
||||
enum BrightnessMode {
|
||||
@@ -14,11 +15,49 @@ class Configs {
|
||||
BrightnessMode? brightnessMode;
|
||||
|
||||
@ProviderModelProp()
|
||||
String? appliedSchemeId;
|
||||
String? get appliedSchemeId => _appliedSchemeId;
|
||||
|
||||
set appliedSchemeId(String? schemeId) {
|
||||
_appliedSchemeId = schemeId;
|
||||
if (schemeId.notNull)
|
||||
H().sp.updateString(SPKeys.appliedSchemeId, schemeId!);
|
||||
else
|
||||
H().sp.remove(SPKeys.appliedSchemeId);
|
||||
}
|
||||
|
||||
String? _appliedSchemeId;
|
||||
|
||||
@ProviderModelProp()
|
||||
String? get accessToken => _accessToken;
|
||||
|
||||
set accessToken(String? token) {
|
||||
_accessToken = token;
|
||||
if (token.notNull)
|
||||
H().sp.updateString(SPKeys.accessToken, token!);
|
||||
else
|
||||
H().sp.remove(SPKeys.accessToken);
|
||||
}
|
||||
|
||||
String? _accessToken;
|
||||
|
||||
@ProviderModelProp()
|
||||
String? get email => _email;
|
||||
|
||||
set email(String? emailAddress) {
|
||||
_email = emailAddress;
|
||||
if (emailAddress.notNull)
|
||||
H().sp.updateString(SPKeys.loginEmail, emailAddress!);
|
||||
else
|
||||
H().sp.remove(SPKeys.loginEmail);
|
||||
}
|
||||
|
||||
String? _email;
|
||||
|
||||
Configs() {
|
||||
this.brightnessMode =
|
||||
BrightnessMode.values[H().sp.getInt(SPKeys.brightnessMode)?.clamp(0, BrightnessMode.values.length - 1) ?? 0];
|
||||
this.appliedSchemeId = H().sp.getString(SPKeys.appliedSchemeId);
|
||||
this.accessToken = H().sp.getString(SPKeys.accessToken);
|
||||
this.email = H().sp.getString(SPKeys.loginEmail);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,5 +6,10 @@ class ContentLayout {
|
||||
bool? localManagerOpened;
|
||||
|
||||
@ProviderModelProp()
|
||||
bool? marketOpened;
|
||||
bool? marketOrMeOpened;
|
||||
|
||||
@ProviderModelProp()
|
||||
bool? currentIsMarket = true;
|
||||
|
||||
bool get isMarket => currentIsMarket ?? true;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import 'package:dde_gesture_manager/models/content_layout.provider.dart';
|
||||
import 'package:dde_gesture_manager/models/scheme.provider.dart';
|
||||
import 'package:dde_gesture_manager/pages/gesture_editor.dart';
|
||||
import 'package:dde_gesture_manager/pages/local_manager.dart';
|
||||
import 'package:dde_gesture_manager/pages/market.dart';
|
||||
import 'package:dde_gesture_manager/pages/market_or_me.dart';
|
||||
import 'package:dde_gesture_manager/utils/helper.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
@@ -31,7 +31,7 @@ class _ContentState extends State<Content> {
|
||||
ChangeNotifierProvider(
|
||||
create: (context) => ContentLayoutProvider()
|
||||
..localManagerOpened = preferredPanelsStatus.localManagerPanelOpened
|
||||
..marketOpened = preferredPanelsStatus.marketPanelOpened,
|
||||
..marketOrMeOpened = preferredPanelsStatus.marketOrMePanelOpened,
|
||||
),
|
||||
ChangeNotifierProvider(
|
||||
create: (context) => CopiedGesturePropProvider.empty(),
|
||||
@@ -42,7 +42,7 @@ class _ContentState extends State<Content> {
|
||||
Future.microtask(
|
||||
() => context.read<ContentLayoutProvider>().setProps(
|
||||
localManagerOpened: preferredPanelsStatus.localManagerPanelOpened,
|
||||
marketOpened: preferredPanelsStatus.marketPanelOpened,
|
||||
marketOrMeOpened: preferredPanelsStatus.marketOrMePanelOpened,
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -52,7 +52,7 @@ class _ContentState extends State<Content> {
|
||||
children: [
|
||||
LocalManager(),
|
||||
GestureEditor(),
|
||||
Market(),
|
||||
MarketOrMe(),
|
||||
],
|
||||
);
|
||||
},
|
||||
|
||||
@@ -68,12 +68,12 @@ class GestureEditor extends StatelessWidget {
|
||||
),
|
||||
).tr(),
|
||||
Visibility(
|
||||
visible: layoutProvider.marketOpened == false,
|
||||
visible: layoutProvider.marketOrMeOpened == false,
|
||||
child: DButton(
|
||||
width: defaultButtonHeight,
|
||||
onTap: () => H.openPanel(context, PanelType.market),
|
||||
onTap: () => H.openPanel(context, PanelType.market_or_me),
|
||||
child: Icon(
|
||||
CupertinoIcons.cart,
|
||||
layoutProvider.isMarket ? CupertinoIcons.cart : CupertinoIcons.person,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:dde_gesture_manager/constants/constants.dart';
|
||||
import 'package:dde_gesture_manager/constants/sp_keys.dart';
|
||||
import 'package:dde_gesture_manager/extensions.dart';
|
||||
import 'package:dde_gesture_manager/models/configs.provider.dart';
|
||||
import 'package:dde_gesture_manager/models/content_layout.provider.dart';
|
||||
@@ -9,7 +8,6 @@ import 'package:dde_gesture_manager/models/local_schemes_provider.dart';
|
||||
import 'package:dde_gesture_manager/models/scheme.dart';
|
||||
import 'package:dde_gesture_manager/models/scheme.provider.dart';
|
||||
import 'package:dde_gesture_manager/models/settings.provider.dart';
|
||||
import 'package:dde_gesture_manager/utils/helper.dart';
|
||||
import 'package:dde_gesture_manager/widgets/dde_button.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@@ -247,7 +245,6 @@ class _LocalManagerState extends State<LocalManager> {
|
||||
var appliedId =
|
||||
localSchemes.firstWhere((ele) => ele.path == _selectedItemPath).scheme.id!;
|
||||
appliedId.sout();
|
||||
H().sp.updateString(SPKeys.appliedSchemeId, appliedId);
|
||||
context.read<ConfigsProvider>().setProps(appliedSchemeId: appliedId);
|
||||
},
|
||||
),
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
import 'package:dde_gesture_manager/constants/constants.dart';
|
||||
import 'package:dde_gesture_manager/extensions.dart';
|
||||
import 'package:dde_gesture_manager/models/content_layout.provider.dart';
|
||||
import 'package:dde_gesture_manager/widgets/dde_button.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class Market extends StatelessWidget {
|
||||
const Market({
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var isOpen = context.watch<ContentLayoutProvider>().marketOpened == true;
|
||||
return AnimatedContainer(
|
||||
duration: mediumDuration,
|
||||
curve: Curves.easeInOut,
|
||||
width: isOpen ? marketPanelWidth : 0,
|
||||
child: OverflowBox(
|
||||
alignment: Alignment.centerLeft,
|
||||
maxWidth: marketPanelWidth,
|
||||
minWidth: marketPanelWidth,
|
||||
child: Material(
|
||||
color: context.t.backgroundColor,
|
||||
elevation: isOpen ? 10 : 0,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
DButton(
|
||||
width: defaultButtonHeight - 2,
|
||||
height: defaultButtonHeight - 2,
|
||||
onTap: () => context.read<ContentLayoutProvider>().setProps(marketOpened: !isOpen),
|
||||
child: Icon(
|
||||
CupertinoIcons.chevron_right_2,
|
||||
size: 20,
|
||||
),
|
||||
),
|
||||
Flexible(
|
||||
child: Center(
|
||||
child: Text(
|
||||
LocaleKeys.market_title,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
).tr(),
|
||||
),
|
||||
),
|
||||
Container(width: defaultButtonHeight),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
import 'package:auto_size_text/auto_size_text.dart';
|
||||
import 'package:dde_gesture_manager/constants/constants.dart';
|
||||
import 'package:dde_gesture_manager/extensions.dart';
|
||||
import 'package:dde_gesture_manager/models/configs.provider.dart';
|
||||
import 'package:dde_gesture_manager/models/content_layout.provider.dart';
|
||||
import 'package:dde_gesture_manager/widgets/dde_button.dart';
|
||||
import 'package:dde_gesture_manager/widgets/login.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class MarketOrMe extends StatelessWidget {
|
||||
const MarketOrMe({
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var layoutProvider = context.watch<ContentLayoutProvider>();
|
||||
bool isOpen = layoutProvider.marketOrMeOpened == true;
|
||||
bool isMarket = layoutProvider.isMarket;
|
||||
bool showLogin = context.watch<ConfigsProvider>().accessToken.isNull && !isMarket;
|
||||
return AnimatedContainer(
|
||||
duration: mediumDuration,
|
||||
curve: Curves.easeInOut,
|
||||
width: isOpen ? marketOrMePanelWidth * (showLogin ? 1.5 : 1) : 0,
|
||||
child: OverflowBox(
|
||||
alignment: Alignment.centerLeft,
|
||||
maxWidth: marketOrMePanelWidth * (showLogin ? 1.5 : 1),
|
||||
minWidth: marketOrMePanelWidth * (showLogin ? 1.5 : 1),
|
||||
child: Material(
|
||||
color: context.t.backgroundColor,
|
||||
elevation: isOpen ? 10 : 0,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
DButton(
|
||||
width: defaultButtonHeight - 2,
|
||||
height: defaultButtonHeight - 2,
|
||||
onTap: () => context.read<ContentLayoutProvider>().setProps(marketOrMeOpened: !isOpen),
|
||||
child: Icon(
|
||||
CupertinoIcons.chevron_right_2,
|
||||
size: 20,
|
||||
),
|
||||
),
|
||||
Flexible(
|
||||
child: Center(
|
||||
child: Text(
|
||||
isMarket ? LocaleKeys.market_title : LocaleKeys.me_title,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
).tr(),
|
||||
),
|
||||
),
|
||||
DButton(
|
||||
width: defaultButtonHeight - 2,
|
||||
height: defaultButtonHeight - 2,
|
||||
onTap: () => context.read<ContentLayoutProvider>().setProps(currentIsMarket: !isMarket),
|
||||
child: Icon(
|
||||
!isMarket ? CupertinoIcons.cart : CupertinoIcons.person,
|
||||
size: 20,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
if (isMarket) buildMarketContent(context),
|
||||
if (!isMarket) buildMeContent(context),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildMeContent(BuildContext context) {
|
||||
var accessToken = context.watch<ConfigsProvider>().accessToken;
|
||||
if (accessToken.isNull) return LoginWidget();
|
||||
|
||||
return Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 10),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Icon(Icons.person, size: defaultButtonHeight),
|
||||
Flexible(
|
||||
child: AutoSizeText(
|
||||
context.watch<ConfigsProvider>().email ?? '',
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
),
|
||||
maxLines: 1,
|
||||
),
|
||||
),
|
||||
DButton.logout(
|
||||
enabled: true,
|
||||
onTap: () => context.read<ConfigsProvider>().setProps(accessToken: '', email: ''),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildMarketContent(BuildContext context) {
|
||||
return Container();
|
||||
}
|
||||
}
|
||||
+19
-11
@@ -29,34 +29,42 @@ class H {
|
||||
initSharedPreference() async {
|
||||
_sp = await SharedPreferences.getInstance();
|
||||
}
|
||||
|
||||
late BuildContext _topContext;
|
||||
|
||||
BuildContext get topContext => _topContext;
|
||||
|
||||
initTopContext(BuildContext context) {
|
||||
_topContext = context;
|
||||
}
|
||||
|
||||
static void openPanel(BuildContext context, PanelType panelType) {
|
||||
var windowWidth = MediaQuery.of(context).size.width;
|
||||
if (windowWidth < minWindowSize.width + localManagerPanelWidth + marketPanelWidth) {
|
||||
if (windowWidth < minWindowSize.width + localManagerPanelWidth + marketOrMePanelWidth) {
|
||||
context.read<ContentLayoutProvider>().setProps(
|
||||
localManagerOpened: panelType == PanelType.local_manager,
|
||||
marketOpened: panelType == PanelType.market,
|
||||
marketOrMeOpened: panelType == PanelType.market_or_me,
|
||||
);
|
||||
} else {
|
||||
switch (panelType) {
|
||||
case PanelType.local_manager:
|
||||
return context.read<ContentLayoutProvider>().setProps(localManagerOpened: true);
|
||||
case PanelType.market:
|
||||
return context.read<ContentLayoutProvider>().setProps(marketOpened: true);
|
||||
case PanelType.market_or_me:
|
||||
return context.read<ContentLayoutProvider>().setProps(marketOrMeOpened: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static PreferredPanelsStatus getPreferredPanelsStatus(double windowWidth) {
|
||||
var preferredPanelsStatus = PreferredPanelsStatus(localManagerPanelOpened: true, marketPanelOpened: true);
|
||||
if (windowWidth > minWindowSize.width + localManagerPanelWidth + marketPanelWidth)
|
||||
var preferredPanelsStatus = PreferredPanelsStatus(localManagerPanelOpened: true, marketOrMePanelOpened: true);
|
||||
if (windowWidth > minWindowSize.width + localManagerPanelWidth + marketOrMePanelWidth)
|
||||
return preferredPanelsStatus;
|
||||
else if (windowWidth < minWindowSize.width + localManagerPanelWidth)
|
||||
return preferredPanelsStatus
|
||||
..marketPanelOpened = false
|
||||
..marketOrMePanelOpened = false
|
||||
..localManagerPanelOpened = false;
|
||||
else
|
||||
return preferredPanelsStatus..marketPanelOpened = false;
|
||||
return preferredPanelsStatus..marketOrMePanelOpened = false;
|
||||
}
|
||||
|
||||
static Gesture getGestureByName(String gestureName) => Gesture.values.findByName(gestureName) ?? Gesture.swipe;
|
||||
@@ -108,15 +116,15 @@ class H {
|
||||
|
||||
class PreferredPanelsStatus {
|
||||
bool localManagerPanelOpened;
|
||||
bool marketPanelOpened;
|
||||
bool marketOrMePanelOpened;
|
||||
|
||||
PreferredPanelsStatus({
|
||||
required this.localManagerPanelOpened,
|
||||
required this.marketPanelOpened,
|
||||
required this.marketOrMePanelOpened,
|
||||
});
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'PreferredPanelsStatus{localManagerPanelOpened: $localManagerPanelOpened, marketPanelOpened: $marketPanelOpened}';
|
||||
return 'PreferredPanelsStatus{localManagerPanelOpened: $localManagerPanelOpened, marketOrMePanelOpened: $marketOrMePanelOpened}';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,13 +3,22 @@ import 'package:dde_gesture_manager/constants/sp_keys.dart';
|
||||
import 'package:dde_gesture_manager/constants/supported_locales.dart';
|
||||
import 'package:dde_gesture_manager/extensions.dart';
|
||||
import 'package:dde_gesture_manager/generated/codegen_loader.g.dart';
|
||||
import 'package:dde_gesture_manager/http/api.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:dde_gesture_manager_api/apis.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_platform_alert/flutter_platform_alert.dart';
|
||||
import 'package:gsettings/gsettings.dart';
|
||||
import 'package:package_info_plus/package_info_plus.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
import 'package:window_manager/window_manager.dart';
|
||||
|
||||
bool _updateChecked = false;
|
||||
|
||||
Future<void> initEvents(BuildContext context) async {
|
||||
H().initTopContext(context);
|
||||
var isDark = MediaQuery.of(context).platformBrightness == Brightness.dark;
|
||||
if (isDark) {
|
||||
context.read<SettingsProvider>().setProps(isDarkMode: isDark);
|
||||
@@ -39,6 +48,32 @@ Future<void> initEvents(BuildContext context) async {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (!_updateChecked)
|
||||
Api.checkAppVersion(ignoreErrorHandle: true).then((value) async {
|
||||
_updateChecked = true;
|
||||
var info = await PackageInfo.fromPlatform();
|
||||
var _buildNumber = int.parse(info.buildNumber);
|
||||
var _newVersionCode = value?.versionCode ?? 0;
|
||||
var _ignoredVersionCode = H().sp.getInt(SPKeys.ignoredUpdateVersion) ?? 0;
|
||||
if (_buildNumber < _newVersionCode && _ignoredVersionCode < _newVersionCode) {
|
||||
Notificator.showConfirm(
|
||||
title: LocaleKeys.info_new_version_title.tr(namedArgs: {'version': '${value?.versionName}'}),
|
||||
description: LocaleKeys.info_new_version_description_for_startup.tr(namedArgs: {
|
||||
'yes': LocaleKeys.str_yes.tr(),
|
||||
'no': LocaleKeys.str_no.tr(),
|
||||
}),
|
||||
).then((confirmed) async {
|
||||
if (confirmed == CustomButton.positiveButton) {
|
||||
if (await canLaunch(Apis.appNewVersionUrl)) {
|
||||
await launch(Apis.appNewVersionUrl);
|
||||
}
|
||||
} else if (confirmed == CustomButton.negativeButton) {
|
||||
H().sp.updateInt(SPKeys.ignoredUpdateVersion, value?.versionCode ?? 0);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> initConfigs() async {
|
||||
|
||||
@@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
Future<void> initEvents(BuildContext context) async {
|
||||
H().initTopContext(context);
|
||||
var isDark = MediaQuery.of(context).platformBrightness == Brightness.dark;
|
||||
context.read<SettingsProvider>().setProps(isDarkMode: isDark);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:cherry_toast/cherry_toast.dart';
|
||||
import 'package:cherry_toast/resources/arrays.dart';
|
||||
import 'package:dde_gesture_manager/extensions.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_platform_alert/flutter_platform_alert.dart';
|
||||
|
||||
@@ -27,8 +28,8 @@ class Notificator {
|
||||
return AlertImpl().showConfirm(
|
||||
windowTitle: title,
|
||||
text: description,
|
||||
positiveButtonTitle: positiveButtonTitle,
|
||||
negativeButtonTitle: negativeButtonTitle,
|
||||
positiveButtonTitle: positiveButtonTitle ?? LocaleKeys.str_yes.tr(),
|
||||
negativeButtonTitle: negativeButtonTitle ?? LocaleKeys.str_no.tr(),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user