[flutter]: config ui of left menu

This commit is contained in:
appflowy 2021-10-09 16:43:56 +08:00
parent d46e5aa0b9
commit ece353b6b1
41 changed files with 312 additions and 169 deletions

View File

@ -1,4 +1,16 @@
{ {
"[dart]": {
"editor.formatOnSave": true,
"editor.formatOnType": true,
"editor.rulers": [
120
],
"editor.selectionHighlight": false,
"editor.suggest.snippetsPreventQuickSuggestions": false,
"editor.suggestSelection": "first",
"editor.tabCompletion": "onlySnippets",
"editor.wordBasedSuggestions": false
},
"svgviewer.enableautopreview": true, "svgviewer.enableautopreview": true,
"svgviewer.previewcolumn": "Active", "svgviewer.previewcolumn": "Active",
"svgviewer.showzoominout": true, "svgviewer.showzoominout": true,

View File

@ -0,0 +1,25 @@
<svg width="92" height="17" viewBox="0 0 92 17" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0)">
<path d="M32.7324 4.84144H34.892V5.63601C35.4179 5.08166 36.4132 4.63818 37.5212 4.63818C39.8498 4.63818 41.3709 6.4121 41.3709 8.88818C41.3709 11.4197 39.6057 13.3969 36.8827 13.3969C36.1315 13.3969 35.3991 13.2675 34.9108 12.9904V16.9078H32.7512V4.84144H32.7324ZM34.9108 7.53927V10.9208C35.493 11.2904 35.9812 11.4012 36.6949 11.4012C38.1972 11.4012 39.0611 10.3295 39.0611 8.94362C39.0611 7.61318 38.2723 6.65231 36.8451 6.65231C36.1127 6.63384 35.4366 6.96644 34.9108 7.53927Z" fill="black"/>
<path d="M27.3804 4.6748C24.6573 4.6748 22.8921 6.6335 22.8921 9.1835C22.8921 11.6596 24.3944 13.4335 26.7419 13.4335C27.8311 13.4335 28.8264 12.99 29.371 12.4357V13.2302H31.5306V6.22698C29.9156 5.02589 28.1315 4.6748 27.3804 4.6748ZM29.3522 10.5324C28.8264 11.1052 28.1503 11.4378 27.4179 11.4378C25.9907 11.4378 25.2019 10.477 25.2019 9.14654C25.2019 7.76067 26.0658 6.67046 27.5681 6.67046C28.2818 6.67046 28.77 6.78133 29.3522 7.15089V10.5324Z" fill="black"/>
<path d="M42.291 4.84144H44.4506V5.63601C44.9765 5.08166 45.9718 4.63818 47.0797 4.63818C49.4084 4.63818 50.9295 6.4121 50.9295 8.88818C50.9295 11.4197 49.1642 13.3969 46.4412 13.3969C45.6901 13.3969 44.9577 13.2675 44.4694 12.9904V16.9078H42.3098V4.84144H42.291ZM44.4694 7.53927V10.9208C45.0516 11.2904 45.5398 11.4012 46.2535 11.4012C47.7558 11.4012 48.6196 10.3295 48.6196 8.94362C48.6196 7.61318 47.8309 6.65231 46.4037 6.65231C45.6713 6.63384 44.9952 6.96644 44.4694 7.53927Z" fill="black"/>
<path d="M57.2019 2.43913C56.8826 2.21739 56.3756 1.99565 55.8685 1.99565C54.892 1.99565 54.3849 2.49457 54.3849 3.64022V4.82283H55.9061V6.83696H54.3849V13.175H52.2065V3.49239C52.2065 1.18261 53.3333 0 55.23 0C56.0939 0 56.8826 0.203261 57.446 0.554348H59.3615V10.0152C59.3615 10.9576 59.6056 11.3641 60.0939 11.3641C60.4507 11.3641 60.7324 11.2163 60.9953 11.0315L61.446 12.6576C60.9577 13.0457 60.2253 13.3598 59.2112 13.3598C57.9155 13.3598 57.2019 12.5837 57.2019 10.8837V2.43913Z" fill="black"/>
<path d="M66.0846 4.63818C68.9015 4.63818 70.7043 6.50449 70.7043 9.01753C70.7043 11.5121 68.9015 13.3969 66.0846 13.3969C63.2677 13.3969 61.4648 11.5306 61.4648 9.01753C61.4648 6.50449 63.2864 4.63818 66.0846 4.63818ZM66.0846 11.4012C67.4179 11.4012 68.3944 10.4588 68.3944 9.01753C68.3944 7.61318 67.3991 6.65231 66.0846 6.65231C64.8076 6.65231 63.7935 7.57623 63.7935 9.01753C63.7935 10.4034 64.77 11.4012 66.0846 11.4012Z" fill="black"/>
<path d="M81.4271 13.2307H79.4928L77.69 8.59264C77.5586 8.27851 77.5022 7.92742 77.4083 7.61329C77.3332 7.98286 77.2393 8.29699 77.1079 8.6296L75.305 13.2307H73.4647L70.7041 4.84155H73.014L74.3661 9.38721C74.4975 9.79373 74.5351 10.1079 74.6102 10.4959C74.7041 10.1448 74.7604 9.84916 74.9295 9.38721L76.5069 4.84155H78.4224L80.0562 9.36873C80.1877 9.73829 80.2816 10.1263 80.3755 10.5144C80.4506 10.1263 80.5445 9.71981 80.6384 9.31329L81.8778 4.84155H84.0562L81.4271 13.2307Z" fill="black"/>
<path d="M88.6574 13.1936C87.4179 16.187 86.6292 16.9077 85.371 16.9077C84.601 16.9077 84.0377 16.612 83.5494 16.2609L84.2442 14.6533C84.4696 14.7827 84.7888 14.949 85.1269 14.949C85.6715 14.949 86.0658 14.524 86.4226 13.6555L86.6104 13.212L82.6855 4.85986H85.2959L87.2677 9.42399C87.4367 9.83052 87.5494 10.2186 87.6808 10.6251C87.756 10.237 87.8311 9.83052 87.9813 9.40552L89.5024 4.85986H91.9625L88.6574 13.1936Z" fill="black"/>
<path d="M17.0142 10.4033C16.5259 13.0088 14.3851 15.2816 11.925 16.5566C11.6245 16.7229 11.2677 16.8153 10.9297 16.8338H16.1503C16.6574 16.8338 17.0142 16.4642 17.0142 16.0022V10.4033Z" fill="#F7931E"/>
<path d="M6.57258 5.37743C6.49746 5.43286 6.42235 5.4883 6.34723 5.54373C5.07023 6.43069 1.20169 9.27634 0.319059 8.0383C-0.544791 6.83721 0.375397 3.43721 2.59136 1.79264C2.62892 1.75569 2.68526 1.73721 2.72281 1.70025C5.14535 0.0187313 6.94817 0.258949 7.8308 1.47851C8.65709 2.62417 7.7369 4.43504 6.57258 5.37743Z" fill="#8427E0"/>
<path d="M16.0373 8.02043C14.8354 8.85195 12.9575 7.89108 12.0185 6.69C11.981 6.63456 11.9434 6.59761 11.9059 6.54217C11.0045 5.28565 8.11244 1.47913 9.35188 0.629126C10.5913 -0.239352 14.1782 0.703039 15.812 2.99434C15.8495 3.04978 15.8871 3.08674 15.9246 3.14217C17.5021 5.45195 17.258 7.17043 16.0373 8.02043Z" fill="#00B5FF"/>
<path d="M14.4226 15.5219C14.385 15.5589 14.3475 15.5773 14.2911 15.6143C11.8686 17.2958 10.0658 17.0556 9.18315 15.836C8.35686 14.6904 9.27705 12.8795 10.4414 11.9371C10.5165 11.8817 10.5916 11.8263 10.6667 11.7708C11.9437 10.9023 15.8123 8.03821 16.6761 9.27625C17.5587 10.4773 16.6573 13.8773 14.4226 15.5219Z" fill="#FFBD00"/>
<path d="M7.66182 16.6859C6.42238 17.5544 2.85431 16.612 1.22051 14.3207C1.18295 14.2838 1.14539 14.2283 1.12661 14.1914C-0.469635 11.8816 -0.206725 10.1446 1.01393 9.31311C2.21581 8.48159 4.09374 9.44246 5.03271 10.6435C5.07027 10.699 5.10783 10.7359 5.14539 10.7914C6.02802 12.0294 8.92004 15.8359 7.66182 16.6859Z" fill="#E3006D"/>
<path d="M6.57283 5.37743C4.84513 6.13504 1.16438 7.68721 0.619779 6.43069C0.150295 5.37743 1.01415 3.23395 2.59161 1.79264C2.62917 1.75569 2.68551 1.73721 2.72307 1.70025C5.1456 0.0187312 6.94842 0.258949 7.83105 1.47851C8.65734 2.62417 7.73715 4.43504 6.57283 5.37743Z" fill="#9327FF"/>
<path d="M16.0374 8.01967C14.8355 8.8512 12.9576 7.89033 12.0186 6.68924C11.2487 4.9338 9.76511 1.47837 11.0045 0.960978C12.1313 0.480543 14.4599 1.44141 15.9435 3.14141C17.5022 5.4512 17.2581 7.16967 16.0374 8.01967Z" fill="#00C8FF"/>
<path d="M14.4226 15.5217C14.385 15.5586 14.3475 15.5771 14.2911 15.6141C11.8686 17.2956 10.0658 17.0554 9.18315 15.8358C8.35686 14.6901 9.27705 12.8793 10.4414 11.9369C12.1691 11.1793 15.8498 9.6271 16.3944 10.8836C16.8827 11.9369 16.0188 14.0804 14.4226 15.5217Z" fill="#FFCE00"/>
<path d="M6.0468 16.3533C4.92004 16.8338 2.5914 15.8914 1.12661 14.1914C-0.469635 11.8816 -0.206725 10.1446 1.01393 9.31311C2.21581 8.48159 4.09374 9.44246 5.03271 10.6435C5.80266 12.3805 7.28623 15.8359 6.0468 16.3533Z" fill="#FB006D"/>
</g>
<defs>
<clipPath id="clip0">
<rect width="92" height="17" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 6.0 KiB

View File

Before

Width:  |  Height:  |  Size: 216 B

After

Width:  |  Height:  |  Size: 216 B

View File

Before

Width:  |  Height:  |  Size: 216 B

After

Width:  |  Height:  |  Size: 216 B

View File

Before

Width:  |  Height:  |  Size: 316 B

After

Width:  |  Height:  |  Size: 316 B

View File

Before

Width:  |  Height:  |  Size: 322 B

After

Width:  |  Height:  |  Size: 322 B

View File

Before

Width:  |  Height:  |  Size: 494 B

After

Width:  |  Height:  |  Size: 494 B

View File

@ -0,0 +1,5 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="16" height="16" rx="8" fill="#00BCF0"/>
<rect x="7.5" y="4" width="1" height="8" rx="0.5" fill="white"/>
<rect x="12" y="7.5" width="1" height="8" rx="0.5" transform="rotate(90 12 7.5)" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 317 B

Binary file not shown.

View File

@ -21,16 +21,24 @@ class SignInBloc extends Bloc<SignInEvent, SignInState> {
); );
}, },
emailChanged: (EmailChanged value) async* { emailChanged: (EmailChanged value) async* {
yield state.copyWith(email: value.email, successOrFail: none()); yield state.copyWith(
email: value.email, emailError: none(), successOrFail: none());
}, },
passwordChanged: (PasswordChanged value) async* { passwordChanged: (PasswordChanged value) async* {
yield state.copyWith(password: value.password, successOrFail: none()); yield state.copyWith(
password: value.password,
passwordError: none(),
successOrFail: none());
}, },
); );
} }
Stream<SignInState> _performActionOnSignIn(SignInState state) async* { Stream<SignInState> _performActionOnSignIn(SignInState state) async* {
yield state.copyWith(isSubmitting: true); yield state.copyWith(
isSubmitting: true,
emailError: none(),
passwordError: none(),
successOrFail: none());
final result = await authImpl.signIn(state.email, state.password); final result = await authImpl.signIn(state.email, state.password);
yield result.fold( yield result.fold(

View File

@ -17,18 +17,25 @@ class SignUpBloc extends Bloc<SignUpEvent, SignUpState> {
yield* event.map(signUpWithUserEmailAndPassword: (e) async* { yield* event.map(signUpWithUserEmailAndPassword: (e) async* {
yield* _performActionOnSignUp(); yield* _performActionOnSignUp();
}, emailChanged: (EmailChanged value) async* { }, emailChanged: (EmailChanged value) async* {
yield state.copyWith(email: value.email, successOrFail: none()); yield state.copyWith(
email: value.email, emailError: none(), successOrFail: none());
}, passwordChanged: (PasswordChanged value) async* { }, passwordChanged: (PasswordChanged value) async* {
yield state.copyWith(password: value.password, successOrFail: none()); yield state.copyWith(
password: value.password,
passwordError: none(),
successOrFail: none());
}, repeatPasswordChanged: (RepeatPasswordChanged value) async* { }, repeatPasswordChanged: (RepeatPasswordChanged value) async* {
yield state.copyWith( yield state.copyWith(
repeatedPassword: value.password, successOrFail: none()); repeatedPassword: value.password,
repeatPasswordError: none(),
successOrFail: none());
}); });
} }
Stream<SignUpState> _performActionOnSignUp() async* { Stream<SignUpState> _performActionOnSignUp() async* {
yield state.copyWith( yield state.copyWith(
isSubmitting: true, isSubmitting: true,
successOrFail: none(),
); );
final password = state.password; final password = state.password;
@ -83,12 +90,16 @@ class SignUpBloc extends Bloc<SignUpEvent, SignUpState> {
return state.copyWith( return state.copyWith(
isSubmitting: false, isSubmitting: false,
emailError: some(error.msg), emailError: some(error.msg),
passwordError: none()); passwordError: none(),
successOrFail: none(),
);
case ErrorCode.PasswordFormatInvalid: case ErrorCode.PasswordFormatInvalid:
return state.copyWith( return state.copyWith(
isSubmitting: false, isSubmitting: false,
passwordError: some(error.msg), passwordError: some(error.msg),
emailError: none()); emailError: none(),
successOrFail: none(),
);
default: default:
return state.copyWith( return state.copyWith(
isSubmitting: false, successOrFail: some(right(error))); isSubmitting: false, successOrFail: some(right(error)));

View File

@ -6,6 +6,7 @@ import 'package:flowy_infra/theme.dart';
import 'package:flowy_infra_ui/widget/rounded_button.dart'; import 'package:flowy_infra_ui/widget/rounded_button.dart';
import 'package:flowy_infra_ui/widget/rounded_input_field.dart'; import 'package:flowy_infra_ui/widget/rounded_input_field.dart';
import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flowy_infra_ui/widget/spacing.dart';
import 'package:flowy_infra_ui/style_widget/snap_bar.dart';
import 'package:flowy_sdk/protobuf/flowy-user/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-user/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-user/user_profile.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-user/user_profile.pb.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -39,15 +40,7 @@ class SignInScreen extends StatelessWidget {
Either<UserProfile, UserError> result, BuildContext context) { Either<UserProfile, UserError> result, BuildContext context) {
result.fold( result.fold(
(user) => router.pushWelcomeScreen(context, user), (user) => router.pushWelcomeScreen(context, user),
(error) => _showErrorMessage(context, error.msg), (error) => showSnapBar(context, error.msg),
);
}
void _showErrorMessage(BuildContext context, String msg) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(msg),
),
); );
} }
} }
@ -179,8 +172,8 @@ class PasswordTextField extends StatelessWidget {
return RoundedInputField( return RoundedInputField(
obscureText: true, obscureText: true,
fontSize: 14, fontSize: 14,
obscureIcon: svgWidgetWithName("home/Hide.svg"), obscureIcon: svg("home/Hide"),
obscureHideIcon: svgWidgetWithName("home/Show.svg"), obscureHideIcon: svg("home/Show"),
hintText: 'Password', hintText: 'Password',
normalBorderColor: theme.shader4, normalBorderColor: theme.shader4,
highlightBorderColor: theme.red, highlightBorderColor: theme.red,

View File

@ -8,6 +8,7 @@ import 'package:flowy_infra_ui/widget/rounded_input_field.dart';
import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flowy_infra_ui/widget/spacing.dart';
import 'package:flowy_sdk/protobuf/flowy-user/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-user/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-user/user_profile.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-user/user_profile.pb.dart';
import 'package:flowy_infra_ui/style_widget/snap_bar.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:dartz/dartz.dart'; import 'package:dartz/dartz.dart';
@ -37,11 +38,7 @@ class SignUpScreen extends StatelessWidget {
BuildContext context, Either<UserProfile, UserError> result) { BuildContext context, Either<UserProfile, UserError> result) {
result.fold( result.fold(
(user) => router.pushWelcomeScreen(context, user), (user) => router.pushWelcomeScreen(context, user),
(error) => ScaffoldMessenger.of(context).showSnackBar( (error) => showSnapBar(context, error.msg),
SnackBar(
content: Text(error.msg),
),
),
); );
} }
} }
@ -140,8 +137,8 @@ class PasswordTextField extends StatelessWidget {
builder: (context, state) { builder: (context, state) {
return RoundedInputField( return RoundedInputField(
obscureText: true, obscureText: true,
obscureIcon: svgWidgetWithName("home/Hide.svg"), obscureIcon: svg("home/Hide"),
obscureHideIcon: svgWidgetWithName("home/Show.svg"), obscureHideIcon: svg("home/Show"),
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
hintText: "Password", hintText: "Password",
@ -175,8 +172,8 @@ class RepeatPasswordTextField extends StatelessWidget {
builder: (context, state) { builder: (context, state) {
return RoundedInputField( return RoundedInputField(
obscureText: true, obscureText: true,
obscureIcon: svgWidgetWithName("home/Hide.svg"), obscureIcon: svg("home/Hide"),
obscureHideIcon: svgWidgetWithName("home/Show.svg"), obscureHideIcon: svg("home/Show"),
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
hintText: "Repeate password", hintText: "Repeate password",

View File

@ -44,7 +44,7 @@ class AuthFormTitle extends StatelessWidget {
children: [ children: [
SizedBox.fromSize( SizedBox.fromSize(
size: const Size.square(40), size: const Size.square(40),
child: svgWidgetWithName("flowy_logo.svg"), child: svg("flowy_logo"),
), ),
const VSpace(30), const VSpace(30),
Text( Text(

View File

@ -7,18 +7,17 @@ AssetImage assetImageForViewType(ViewType type) {
return AssetImage('assets/images/$imageName'); return AssetImage('assets/images/$imageName');
} }
Widget svgImageForViewType(ViewType type) { Widget svgForViewType(ViewType type) {
final imageName = imageNameForViewType(type); final imageName = imageNameForViewType(type);
final Widget svg = svgWidgetWithName(imageName); final Widget widget = svg(imageName);
return widget;
return svg;
} }
String imageNameForViewType(ViewType type) { String imageNameForViewType(ViewType type) {
switch (type) { switch (type) {
case ViewType.Doc: case ViewType.Doc:
return "file_icon.svg"; return "file_icon";
default: default:
return "file_icon.svg"; return "file_icon";
} }
} }

View File

@ -1,7 +1,11 @@
import 'package:app_flowy/workspace/application/app/app_bloc.dart'; import 'package:app_flowy/workspace/application/app/app_bloc.dart';
import 'package:expandable/expandable.dart'; import 'package:expandable/expandable.dart';
import 'package:flowy_infra/image.dart';
import 'package:flowy_infra/theme.dart';
import 'package:flowy_infra_ui/style_widget/text.dart';
import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flowy_infra_ui/widget/spacing.dart';
import 'package:flowy_infra_ui/style_widget/text_button.dart'; import 'package:flowy_infra_ui/style_widget/text_button.dart';
import 'package:flowy_infra/flowy_icon_data_icons.dart';
import 'package:flowy_sdk/protobuf/flowy-workspace/app_create.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace/app_create.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-workspace/view_create.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-workspace/view_create.pb.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -18,8 +22,9 @@ class AppHeader extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final theme = context.watch<AppTheme>();
return Row( return Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
InkWell( InkWell(
@ -30,9 +35,9 @@ class AppHeader extends StatelessWidget {
}, },
child: ExpandableIcon( child: ExpandableIcon(
theme: ExpandableThemeData( theme: ExpandableThemeData(
expandIcon: Icons.arrow_drop_up, expandIcon: FlowyIconData.drop_down_show,
collapseIcon: Icons.arrow_drop_down, collapseIcon: FlowyIconData.drop_down_hide,
iconColor: Colors.black, iconColor: theme.shader1,
iconSize: AppPageSize.expandedIconSize, iconSize: AppPageSize.expandedIconSize,
iconPadding: EdgeInsets.zero, iconPadding: EdgeInsets.zero,
hasIcon: false, hasIcon: false,
@ -41,13 +46,18 @@ class AppHeader extends StatelessWidget {
), ),
HSpace(AppPageSize.expandedIconRightSpace), HSpace(AppPageSize.expandedIconRightSpace),
Expanded( Expanded(
child: FlowyTextButton( child: GestureDetector(
app.name, onTapDown: (_) {
onPressed: () { ExpandableController.of(context,
debugPrint('show app'); rebuildOnChange: false, required: true)
?.toggle();
}, },
child: FlowyText(
app.name,
fontSize: 12,
), ),
), )),
// FlowyIconButton( // FlowyIconButton(
// icon: const Icon(Icons.add), // icon: const Icon(Icons.add),
// onPressed: () { // onPressed: () {
@ -57,9 +67,9 @@ class AppHeader extends StatelessWidget {
// }, // },
// ), // ),
PopupMenuButton( PopupMenuButton(
iconSize: 20, iconSize: 16,
tooltip: 'create new view', tooltip: 'create new view',
icon: const Icon(Icons.add), icon: svg("home/add"),
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
onSelected: (viewType) => onSelected: (viewType) =>
_createView(viewType as ViewType, context), _createView(viewType as ViewType, context),

View File

@ -15,8 +15,8 @@ import 'package:styled_widget/styled_widget.dart';
import 'app_header.dart'; import 'app_header.dart';
class AppPageSize { class AppPageSize {
static double expandedIconSize = 24; static double expandedIconSize = 20;
static double expandedIconRightSpace = 8; static double expandedIconRightSpace = 6;
static double scale = 1; static double scale = 1;
static double get expandedPadding => static double get expandedPadding =>
expandedIconSize * scale + expandedIconRightSpace; expandedIconSize * scale + expandedIconRightSpace;

View File

@ -47,7 +47,7 @@ class ViewPage extends StatelessWidget {
SizedBox( SizedBox(
width: width, width: width,
height: width, height: width,
child: svgImageForViewType(viewCtx.view.viewType)), child: svgForViewType(viewCtx.view.viewType)),
const HSpace(6), const HSpace(6),
Text( Text(
viewCtx.view.name, viewCtx.view.name,

View File

@ -28,7 +28,13 @@ class MenuList extends StatelessWidget {
child: Expanded( child: Expanded(
child: ListView.separated( child: ListView.separated(
itemCount: menuItems.length, itemCount: menuItems.length,
separatorBuilder: (context, index) => const VSpace(10), separatorBuilder: (context, index) {
if (index == 0) {
return const VSpace(29);
} else {
return const VSpace(9);
}
},
physics: const BouncingScrollPhysics(), physics: const BouncingScrollPhysics(),
itemBuilder: (BuildContext context, int index) { itemBuilder: (BuildContext context, int index) {
return menuItems[index]; return menuItems[index];

View File

@ -1,9 +1,13 @@
import 'package:app_flowy/workspace/presentation/home/home_sizes.dart'; import 'package:app_flowy/workspace/presentation/home/home_sizes.dart';
import 'package:app_flowy/workspace/presentation/widgets/menu/create_app_dialog.dart'; import 'package:app_flowy/workspace/presentation/widgets/menu/create_app_dialog.dart';
import 'package:flowy_infra/image.dart';
import 'package:flowy_infra/size.dart'; import 'package:flowy_infra/size.dart';
import 'package:flowy_infra/theme.dart';
import 'package:flowy_infra_ui/style_widget/text.dart';
import 'package:flowy_infra_ui/widget/dialog/styled_dialogs.dart'; import 'package:flowy_infra_ui/widget/dialog/styled_dialogs.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flowy_infra_ui/style_widget/extension.dart'; import 'package:flowy_infra_ui/style_widget/extension.dart';
import 'package:provider/provider.dart';
class NewAppButton extends StatelessWidget { class NewAppButton extends StatelessWidget {
final Function(String)? press; final Function(String)? press;
@ -11,21 +15,18 @@ class NewAppButton extends StatelessWidget {
const NewAppButton({this.press, Key? key}) : super(key: key); const NewAppButton({this.press, Key? key}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final theme = context.watch<AppTheme>();
return SizedBox( return SizedBox(
height: HomeSizes.menuAddButtonHeight, height: HomeSizes.menuAddButtonHeight,
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
children: [ children: [
const Icon(Icons.add_circle_rounded, size: 30), svgWithSize("home/new_app", const Size(16, 16)),
TextButton( TextButton(
onPressed: () async => await _showCreateAppDialog(context), onPressed: () async => await _showCreateAppDialog(context),
child: const Text( child: const FlowyText(
'New App', 'New App',
style: TextStyle( fontSize: 12,
color: Colors.black,
fontWeight: FontWeight.bold,
fontSize: 20,
),
), ),
) )
], ],

View File

@ -1,5 +1,5 @@
import 'package:app_flowy/workspace/application/menu/menu_bloc.dart'; import 'package:app_flowy/workspace/application/menu/menu_bloc.dart';
import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flowy_infra/image.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
@ -11,19 +11,11 @@ class MenuTopBar extends StatelessWidget {
builder: (context, state) { builder: (context, state) {
return Row( return Row(
children: [ children: [
const Image( svgWithSize("flowy_logo_with_text", const Size(92, 17)),
fit: BoxFit.cover,
width: 25,
height: 25,
image: AssetImage('assets/images/app_flowy_logo.jpg')),
const HSpace(8),
const Text(
'AppFlowy',
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20),
),
const Spacer(), const Spacer(),
IconButton( IconButton(
icon: const Icon(Icons.arrow_left), iconSize: 16,
icon: svg("home/hide_menu"),
alignment: Alignment.centerRight, alignment: Alignment.centerRight,
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
onPressed: () => onPressed: () =>

View File

@ -1,6 +1,7 @@
import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/startup/startup.dart';
import 'package:app_flowy/workspace/application/menu/menu_user_bloc.dart'; import 'package:app_flowy/workspace/application/menu/menu_user_bloc.dart';
import 'package:app_flowy/workspace/presentation/widgets/menu/menu_list.dart'; import 'package:app_flowy/workspace/presentation/widgets/menu/menu_list.dart';
import 'package:flowy_infra/image.dart';
import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flowy_infra_ui/widget/spacing.dart';
import 'package:flowy_sdk/protobuf/flowy-user/user_profile.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-user/user_profile.pb.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -18,23 +19,27 @@ class MenuUser extends MenuItem {
create: (context) => create: (context) =>
getIt<MenuUserBloc>(param1: user)..add(const MenuUserEvent.initial()), getIt<MenuUserBloc>(param1: user)..add(const MenuUserEvent.initial()),
child: BlocBuilder<MenuUserBloc, MenuUserState>( child: BlocBuilder<MenuUserBloc, MenuUserState>(
builder: (context, state) => Row(children: [ builder: (context, state) => Row(
children: [
_renderAvatar(context), _renderAvatar(context),
const HSpace(10), const HSpace(12),
_renderUserName(context), _renderUserName(context),
const HSpace(10), const HSpace(4),
_renderDropButton(context), _renderDropButton(context),
]), ],
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
),
), ),
); );
} }
Widget _renderAvatar(BuildContext context) { Widget _renderAvatar(BuildContext context) {
return SizedBox( return SizedBox(
width: 30, width: 20,
height: 30, height: 20,
child: ClipRRect( child: ClipRRect(
borderRadius: BorderRadius.circular(10), borderRadius: BorderRadius.circular(4),
child: const Image(image: AssetImage('assets/images/avatar.jpg')), child: const Image(image: AssetImage('assets/images/avatar.jpg')),
), ),
); );
@ -46,15 +51,15 @@ class MenuUser extends MenuItem {
name = context.read<MenuUserBloc>().state.user.email; name = context.read<MenuUserBloc>().state.user.email;
} }
return Flexible( return Flexible(
child: FlowyText(name, fontSize: 18), child: FlowyText(name, fontSize: 12),
); );
} }
Widget _renderDropButton(BuildContext context) { Widget _renderDropButton(BuildContext context) {
return FlowyIconButton( return FlowyIconButton(
width: 30, width: 20,
iconRatio: 0.8, iconRatio: 1.0,
icon: const Icon(Icons.arrow_drop_down), icon: svg("home/drop_down_show"),
onPressed: () { onPressed: () {
debugPrint('show user profile'); debugPrint('show user profile');
}, },

View File

@ -0,0 +1,30 @@
/// Flutter icons FlowyIconData
/// Copyright (C) 2021 by original authors @ fluttericon.com, fontello.com
/// This font was generated by FlutterIcon.com, which is derived from Fontello.
///
/// To use this font, place it in your fonts/ directory and include the
/// following in your pubspec.yaml
///
/// flutter:
/// fonts:
/// - family: FlowyIconData
/// fonts:
/// - asset: fonts/FlowyIconData.ttf
///
///
///
// ignore_for_file: constant_identifier_names
import 'package:flutter/widgets.dart';
class FlowyIconData {
FlowyIconData._();
static const _kFontFam = 'FlowyIconData';
static const String? _kFontPkg = null;
static const IconData drop_down_hide =
IconData(0xe800, fontFamily: _kFontFam, fontPackage: _kFontPkg);
static const IconData drop_down_show =
IconData(0xe801, fontFamily: _kFontFam, fontPackage: _kFontPkg);
}

View File

@ -1,10 +1,17 @@
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
Widget svgWidgetWithName(String name) { Widget svg(String name) {
final Widget svg = SvgPicture.asset( final Widget svg = SvgPicture.asset(
'assets/images/$name', 'assets/images/$name.svg',
); );
return svg; return svg;
} }
Widget svgWithSize(String name, Size size) {
return SizedBox.fromSize(
size: size,
child: svg(name),
);
}

View File

@ -118,7 +118,6 @@ class AppTheme {
var t = ThemeData( var t = ThemeData(
textTheme: (isDark ? ThemeData.dark() : ThemeData.light()).textTheme, textTheme: (isDark ? ThemeData.dark() : ThemeData.light()).textTheme,
textSelectionTheme: TextSelectionThemeData(cursorColor: main1), textSelectionTheme: TextSelectionThemeData(cursorColor: main1),
visualDensity: VisualDensity.adaptivePlatformDensity,
colorScheme: ColorScheme( colorScheme: ColorScheme(
brightness: isDark ? Brightness.dark : Brightness.light, brightness: isDark ? Brightness.dark : Brightness.light,
primary: main1, primary: main1,

View File

@ -4,7 +4,7 @@ class FlowyIconButton extends StatelessWidget {
final double width; final double width;
final double? height; final double? height;
final double iconRatio; final double iconRatio;
final Icon icon; final Widget icon;
final VoidCallback? onPressed; final VoidCallback? onPressed;
const FlowyIconButton({ const FlowyIconButton({

View File

@ -0,0 +1,25 @@
import 'package:flutter/material.dart';
void showSnapBar(BuildContext context, String title) {
ScaffoldMessenger.of(context).clearSnackBars();
ScaffoldMessenger.of(context)
.showSnackBar(
SnackBar(
content: WillPopScope(
onWillPop: () async {
ScaffoldMessenger.of(context).removeCurrentSnackBar();
return true;
},
child: Text(
title,
style: const TextStyle(
color: Colors.black,
),
),
),
),
)
.closed
.then((value) => null);
}

View File

@ -1,4 +1,6 @@
import 'package:flowy_infra/theme.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:provider/provider.dart';
class FlowyText extends StatelessWidget { class FlowyText extends StatelessWidget {
final String title; final String title;
@ -13,11 +15,14 @@ class FlowyText extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Text( final theme = context.watch<AppTheme>();
title, return Text(title,
overflow: overflow, overflow: overflow,
softWrap: false, softWrap: false,
style: TextStyle(fontSize: fontSize), style: TextStyle(
); color: theme.shader1,
fontWeight: FontWeight.w500,
fontSize: fontSize + 2,
));
} }
} }

View File

@ -24,6 +24,7 @@ class ErrorCode extends $pb.ProtobufEnum {
static const ErrorCode UserIdInvalid = ErrorCode._(23, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserIdInvalid'); static const ErrorCode UserIdInvalid = ErrorCode._(23, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserIdInvalid');
static const ErrorCode UserUnauthorized = ErrorCode._(24, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserUnauthorized'); static const ErrorCode UserUnauthorized = ErrorCode._(24, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserUnauthorized');
static const ErrorCode UserNotExist = ErrorCode._(25, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserNotExist'); static const ErrorCode UserNotExist = ErrorCode._(25, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserNotExist');
static const ErrorCode ServerOffline = ErrorCode._(26, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ServerOffline');
static const ErrorCode InternalError = ErrorCode._(100, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'InternalError'); static const ErrorCode InternalError = ErrorCode._(100, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'InternalError');
static const $core.List<ErrorCode> values = <ErrorCode> [ static const $core.List<ErrorCode> values = <ErrorCode> [
@ -41,6 +42,7 @@ class ErrorCode extends $pb.ProtobufEnum {
UserIdInvalid, UserIdInvalid,
UserUnauthorized, UserUnauthorized,
UserNotExist, UserNotExist,
ServerOffline,
InternalError, InternalError,
]; ];

View File

@ -26,12 +26,13 @@ const ErrorCode$json = const {
const {'1': 'UserIdInvalid', '2': 23}, const {'1': 'UserIdInvalid', '2': 23},
const {'1': 'UserUnauthorized', '2': 24}, const {'1': 'UserUnauthorized', '2': 24},
const {'1': 'UserNotExist', '2': 25}, const {'1': 'UserNotExist', '2': 25},
const {'1': 'ServerOffline', '2': 26},
const {'1': 'InternalError', '2': 100}, const {'1': 'InternalError', '2': 100},
], ],
}; };
/// Descriptor for `ErrorCode`. Decode as a `google.protobuf.EnumDescriptorProto`. /// Descriptor for `ErrorCode`. Decode as a `google.protobuf.EnumDescriptorProto`.
final $typed_data.Uint8List errorCodeDescriptor = $convert.base64Decode('CglFcnJvckNvZGUSEAoMRW1haWxJc0VtcHR5EAASFgoSRW1haWxGb3JtYXRJbnZhbGlkEAESFgoSRW1haWxBbHJlYWR5RXhpc3RzEAISEwoPUGFzc3dvcmRJc0VtcHR5EAoSEwoPUGFzc3dvcmRUb29Mb25nEAsSJAogUGFzc3dvcmRDb250YWluc0ZvcmJpZENoYXJhY3RlcnMQDBIZChVQYXNzd29yZEZvcm1hdEludmFsaWQQDRIUChBQYXNzd29yZE5vdE1hdGNoEA4SEwoPVXNlck5hbWVUb29Mb25nEBQSJgoiVXNlck5hbWVDb250YWluRm9yYmlkZGVuQ2hhcmFjdGVycxAVEhMKD1VzZXJOYW1lSXNFbXB0eRAWEhEKDVVzZXJJZEludmFsaWQQFxIUChBVc2VyVW5hdXRob3JpemVkEBgSEAoMVXNlck5vdEV4aXN0EBkSEQoNSW50ZXJuYWxFcnJvchBk'); final $typed_data.Uint8List errorCodeDescriptor = $convert.base64Decode('CglFcnJvckNvZGUSEAoMRW1haWxJc0VtcHR5EAASFgoSRW1haWxGb3JtYXRJbnZhbGlkEAESFgoSRW1haWxBbHJlYWR5RXhpc3RzEAISEwoPUGFzc3dvcmRJc0VtcHR5EAoSEwoPUGFzc3dvcmRUb29Mb25nEAsSJAogUGFzc3dvcmRDb250YWluc0ZvcmJpZENoYXJhY3RlcnMQDBIZChVQYXNzd29yZEZvcm1hdEludmFsaWQQDRIUChBQYXNzd29yZE5vdE1hdGNoEA4SEwoPVXNlck5hbWVUb29Mb25nEBQSJgoiVXNlck5hbWVDb250YWluRm9yYmlkZGVuQ2hhcmFjdGVycxAVEhMKD1VzZXJOYW1lSXNFbXB0eRAWEhEKDVVzZXJJZEludmFsaWQQFxIUChBVc2VyVW5hdXRob3JpemVkEBgSEAoMVXNlck5vdEV4aXN0EBkSEQoNU2VydmVyT2ZmbGluZRAaEhEKDUludGVybmFsRXJyb3IQZA==');
@$core.Deprecated('Use userErrorDescriptor instead') @$core.Deprecated('Use userErrorDescriptor instead')
const UserError$json = const { const UserError$json = const {
'1': 'UserError', '1': 'UserError',

View File

@ -89,6 +89,11 @@ flutter:
# the material Icons class. # the material Icons class.
uses-material-design: true uses-material-design: true
fonts:
- family: FlowyIconData
fonts:
- asset: fonts/FlowyIconData.ttf
# To add assets to your application, add an assets section, like this: # To add assets to your application, add an assets section, like this:
assets: assets:
- assets/images/ - assets/images/

View File

@ -4,38 +4,29 @@ use crate::{
services::doc::{ services::doc::{
edit::{ edit::{
message::{DocumentMsg, TransformDeltas}, message::{DocumentMsg, TransformDeltas},
DocId,
}, },
Document, Document,
}, },
}; };
use async_stream::stream; use async_stream::stream;
use flowy_database::ConnectionPool;
use flowy_ot::core::{Delta, OperationTransformable}; use flowy_ot::core::{Delta, OperationTransformable};
use futures::stream::StreamExt; use futures::stream::StreamExt;
use std::{convert::TryFrom, sync::Arc}; use std::{convert::TryFrom, sync::Arc};
use tokio::sync::{mpsc, RwLock}; use tokio::sync::{mpsc, RwLock};
pub struct DocumentActor { pub struct DocumentActor {
doc_id: DocId,
document: Arc<RwLock<Document>>, document: Arc<RwLock<Document>>,
pool: Arc<ConnectionPool>,
receiver: Option<mpsc::UnboundedReceiver<DocumentMsg>>, receiver: Option<mpsc::UnboundedReceiver<DocumentMsg>>,
} }
impl DocumentActor { impl DocumentActor {
pub fn new( pub fn new(
doc_id: &str,
delta: Delta, delta: Delta,
pool: Arc<ConnectionPool>,
receiver: mpsc::UnboundedReceiver<DocumentMsg>, receiver: mpsc::UnboundedReceiver<DocumentMsg>,
) -> Self { ) -> Self {
let doc_id = doc_id.to_string();
let document = Arc::new(RwLock::new(Document::from_delta(delta))); let document = Arc::new(RwLock::new(Document::from_delta(delta)));
Self { Self {
doc_id,
document, document,
pool,
receiver: Some(receiver), receiver: Some(receiver),
} }
} }

View File

@ -33,7 +33,6 @@ pub struct ClientEditDoc {
rev_manager: Arc<RevisionManager>, rev_manager: Arc<RevisionManager>,
document: UnboundedSender<DocumentMsg>, document: UnboundedSender<DocumentMsg>,
ws: Arc<dyn DocumentWebSocket>, ws: Arc<dyn DocumentWebSocket>,
pool: Arc<ConnectionPool>,
user: Arc<dyn DocumentUser>, user: Arc<dyn DocumentUser>,
} }
@ -57,7 +56,6 @@ impl ClientEditDoc {
doc_id, doc_id,
rev_manager, rev_manager,
document, document,
pool,
ws, ws,
user, user,
}; };
@ -323,9 +321,9 @@ async fn save_document(document: UnboundedSender<DocumentMsg>, rev_id: RevId) ->
result result
} }
fn spawn_doc_edit_actor(doc_id: &str, delta: Delta, pool: Arc<ConnectionPool>) -> UnboundedSender<DocumentMsg> { fn spawn_doc_edit_actor(_doc_id: &str, delta: Delta, _pool: Arc<ConnectionPool>) -> UnboundedSender<DocumentMsg> {
let (sender, receiver) = mpsc::unbounded_channel::<DocumentMsg>(); let (sender, receiver) = mpsc::unbounded_channel::<DocumentMsg>();
let actor = DocumentActor::new(&doc_id, delta, pool.clone(), receiver); let actor = DocumentActor::new(delta, receiver);
tokio::spawn(actor.run()); tokio::spawn(actor.run());
sender sender
} }

View File

@ -9,12 +9,6 @@ use flowy_ot::core::{Delta, OperationTransformable};
use std::sync::Arc; use std::sync::Arc;
use tokio::sync::mpsc; use tokio::sync::mpsc;
pub struct DocRevision {
pub base_rev_id: RevId,
pub rev_id: RevId,
pub delta: Delta,
}
pub trait RevisionServer: Send + Sync { pub trait RevisionServer: Send + Sync {
fn fetch_document_from_remote(&self, doc_id: &str) -> ResultFuture<Doc, DocError>; fn fetch_document_from_remote(&self, doc_id: &str) -> ResultFuture<Doc, DocError>;
} }

View File

@ -6,7 +6,7 @@ use crate::{
use async_stream::stream; use async_stream::stream;
use flowy_database::ConnectionPool; use flowy_database::ConnectionPool;
use flowy_infra::future::ResultFuture; use flowy_infra::future::ResultFuture;
use futures::{stream::StreamExt, TryFutureExt}; use futures::{stream::StreamExt};
use std::{sync::Arc, time::Duration}; use std::{sync::Arc, time::Duration};
use tokio::sync::{broadcast, mpsc}; use tokio::sync::{broadcast, mpsc};
@ -39,7 +39,7 @@ impl PendingRevId {
if self.rev_id > rev_id { if self.rev_id > rev_id {
false false
} else { } else {
self.sender.send(self.rev_id); let _ = self.sender.send(self.rev_id);
true true
} }
} }
@ -137,7 +137,7 @@ impl PendingRevisionStream {
match self.revisions.next().await? { match self.revisions.next().await? {
None => Ok(()), None => Ok(()),
Some(revision) => { Some(revision) => {
self.next_revision.send(revision).map_err(internal_error); let _ = self.next_revision.send(revision).map_err(internal_error);
let _ = tokio::time::timeout(Duration::from_millis(2000), ret.recv()).await; let _ = tokio::time::timeout(Duration::from_millis(2000), ret.recv()).await;
Ok(()) Ok(())
}, },

View File

@ -12,10 +12,9 @@ use dashmap::DashMap;
use flowy_database::ConnectionPool; use flowy_database::ConnectionPool;
use flowy_infra::future::ResultFuture; use flowy_infra::future::ResultFuture;
use flowy_ot::core::{Delta, OperationTransformable}; use flowy_ot::core::{Delta, OperationTransformable};
use futures::{stream::StreamExt, TryFutureExt};
use std::{collections::VecDeque, sync::Arc, time::Duration}; use std::{collections::VecDeque, sync::Arc, time::Duration};
use tokio::{ use tokio::{
sync::{broadcast, mpsc, oneshot, RwLock}, sync::{broadcast, mpsc, RwLock},
task::{spawn_blocking, JoinHandle}, task::{spawn_blocking, JoinHandle},
}; };

View File

@ -104,6 +104,7 @@ impl RevTableSql {
Ok(revisions) Ok(revisions)
} }
#[allow(dead_code)]
pub(crate) fn delete_rev_table( pub(crate) fn delete_rev_table(
&self, &self,
doc_id_s: &str, doc_id_s: &str,

View File

@ -39,8 +39,8 @@ impl UserError {
pub(crate) fn code(code: ErrorCode) -> Self { pub(crate) fn code(code: ErrorCode) -> Self {
Self { Self {
msg: format!("{}", &code),
code, code,
msg: "".to_owned(),
} }
} }
@ -97,6 +97,9 @@ pub enum ErrorCode {
#[display(fmt = "User not exist")] #[display(fmt = "User not exist")]
UserNotExist = 25, UserNotExist = 25,
#[display(fmt = "Server is offline, try again later")]
ServerOffline = 26,
#[display(fmt = "Internal error")] #[display(fmt = "Internal error")]
InternalError = 100, InternalError = 100,
} }
@ -139,18 +142,26 @@ impl std::convert::From<flowy_sqlite::Error> for UserError {
impl std::convert::From<flowy_net::errors::ServerError> for UserError { impl std::convert::From<flowy_net::errors::ServerError> for UserError {
fn from(error: flowy_net::errors::ServerError) -> Self { fn from(error: flowy_net::errors::ServerError) -> Self {
let code = server_error_to_user_error(error.code); let (code, msg) = server_error_to_user_error(error);
UserError::new(code, &error.msg) UserError::new(code, &msg)
} }
} }
use flowy_net::errors::ErrorCode as ServerErrorCode; use flowy_net::errors::ErrorCode as ServerErrorCode;
fn server_error_to_user_error(code: ServerErrorCode) -> ErrorCode { fn server_error_to_user_error(error: flowy_net::errors::ServerError) -> (ErrorCode, String) {
match code { let code = match error.code {
ServerErrorCode::UserUnauthorized => ErrorCode::UserUnauthorized, ServerErrorCode::UserUnauthorized => ErrorCode::UserUnauthorized,
ServerErrorCode::PasswordNotMatch => ErrorCode::PasswordNotMatch, ServerErrorCode::PasswordNotMatch => ErrorCode::PasswordNotMatch,
ServerErrorCode::RecordNotFound => ErrorCode::UserNotExist, ServerErrorCode::RecordNotFound => ErrorCode::UserNotExist,
ServerErrorCode::ConnectRefused | ServerErrorCode::ConnectTimeout | ServerErrorCode::ConnectClose => ErrorCode::ServerOffline,
_ => ErrorCode::InternalError, _ => ErrorCode::InternalError,
};
if code != ErrorCode::InternalError {
let msg = format!("{}", &code);
(code, msg)
} else {
(code, error.msg)
} }
} }

View File

@ -229,6 +229,7 @@ pub enum ErrorCode {
UserIdInvalid = 23, UserIdInvalid = 23,
UserUnauthorized = 24, UserUnauthorized = 24,
UserNotExist = 25, UserNotExist = 25,
ServerOffline = 26,
InternalError = 100, InternalError = 100,
} }
@ -253,6 +254,7 @@ impl ::protobuf::ProtobufEnum for ErrorCode {
23 => ::std::option::Option::Some(ErrorCode::UserIdInvalid), 23 => ::std::option::Option::Some(ErrorCode::UserIdInvalid),
24 => ::std::option::Option::Some(ErrorCode::UserUnauthorized), 24 => ::std::option::Option::Some(ErrorCode::UserUnauthorized),
25 => ::std::option::Option::Some(ErrorCode::UserNotExist), 25 => ::std::option::Option::Some(ErrorCode::UserNotExist),
26 => ::std::option::Option::Some(ErrorCode::ServerOffline),
100 => ::std::option::Option::Some(ErrorCode::InternalError), 100 => ::std::option::Option::Some(ErrorCode::InternalError),
_ => ::std::option::Option::None _ => ::std::option::Option::None
} }
@ -274,6 +276,7 @@ impl ::protobuf::ProtobufEnum for ErrorCode {
ErrorCode::UserIdInvalid, ErrorCode::UserIdInvalid,
ErrorCode::UserUnauthorized, ErrorCode::UserUnauthorized,
ErrorCode::UserNotExist, ErrorCode::UserNotExist,
ErrorCode::ServerOffline,
ErrorCode::InternalError, ErrorCode::InternalError,
]; ];
values values
@ -305,7 +308,7 @@ impl ::protobuf::reflect::ProtobufValue for ErrorCode {
static file_descriptor_proto_data: &'static [u8] = b"\ static file_descriptor_proto_data: &'static [u8] = b"\
\n\x0cerrors.proto\"=\n\tUserError\x12\x1e\n\x04code\x18\x01\x20\x01(\ \n\x0cerrors.proto\"=\n\tUserError\x12\x1e\n\x04code\x18\x01\x20\x01(\
\x0e2\n.ErrorCodeR\x04code\x12\x10\n\x03msg\x18\x02\x20\x01(\tR\x03msg*\ \x0e2\n.ErrorCodeR\x04code\x12\x10\n\x03msg\x18\x02\x20\x01(\tR\x03msg*\
\xee\x02\n\tErrorCode\x12\x10\n\x0cEmailIsEmpty\x10\0\x12\x16\n\x12Email\ \x81\x03\n\tErrorCode\x12\x10\n\x0cEmailIsEmpty\x10\0\x12\x16\n\x12Email\
FormatInvalid\x10\x01\x12\x16\n\x12EmailAlreadyExists\x10\x02\x12\x13\n\ FormatInvalid\x10\x01\x12\x16\n\x12EmailAlreadyExists\x10\x02\x12\x13\n\
\x0fPasswordIsEmpty\x10\n\x12\x13\n\x0fPasswordTooLong\x10\x0b\x12$\n\ \x0fPasswordIsEmpty\x10\n\x12\x13\n\x0fPasswordTooLong\x10\x0b\x12$\n\
\x20PasswordContainsForbidCharacters\x10\x0c\x12\x19\n\x15PasswordFormat\ \x20PasswordContainsForbidCharacters\x10\x0c\x12\x19\n\x15PasswordFormat\
@ -313,46 +316,48 @@ static file_descriptor_proto_data: &'static [u8] = b"\
eTooLong\x10\x14\x12&\n\"UserNameContainForbiddenCharacters\x10\x15\x12\ eTooLong\x10\x14\x12&\n\"UserNameContainForbiddenCharacters\x10\x15\x12\
\x13\n\x0fUserNameIsEmpty\x10\x16\x12\x11\n\rUserIdInvalid\x10\x17\x12\ \x13\n\x0fUserNameIsEmpty\x10\x16\x12\x11\n\rUserIdInvalid\x10\x17\x12\
\x14\n\x10UserUnauthorized\x10\x18\x12\x10\n\x0cUserNotExist\x10\x19\x12\ \x14\n\x10UserUnauthorized\x10\x18\x12\x10\n\x0cUserNotExist\x10\x19\x12\
\x11\n\rInternalError\x10dJ\x97\x06\n\x06\x12\x04\0\0\x16\x01\n\x08\n\ \x11\n\rServerOffline\x10\x1a\x12\x11\n\rInternalError\x10dJ\xc0\x06\n\
\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\x04\0\x12\x04\x02\0\x05\x01\n\n\n\x03\ \x06\x12\x04\0\0\x17\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\x04\0\
\x04\0\x01\x12\x03\x02\x08\x11\n\x0b\n\x04\x04\0\x02\0\x12\x03\x03\x04\ \x12\x04\x02\0\x05\x01\n\n\n\x03\x04\0\x01\x12\x03\x02\x08\x11\n\x0b\n\
\x17\n\x0c\n\x05\x04\0\x02\0\x06\x12\x03\x03\x04\r\n\x0c\n\x05\x04\0\x02\ \x04\x04\0\x02\0\x12\x03\x03\x04\x17\n\x0c\n\x05\x04\0\x02\0\x06\x12\x03\
\0\x01\x12\x03\x03\x0e\x12\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x03\x15\ \x03\x04\r\n\x0c\n\x05\x04\0\x02\0\x01\x12\x03\x03\x0e\x12\n\x0c\n\x05\
\x16\n\x0b\n\x04\x04\0\x02\x01\x12\x03\x04\x04\x13\n\x0c\n\x05\x04\0\x02\ \x04\0\x02\0\x03\x12\x03\x03\x15\x16\n\x0b\n\x04\x04\0\x02\x01\x12\x03\
\x01\x05\x12\x03\x04\x04\n\n\x0c\n\x05\x04\0\x02\x01\x01\x12\x03\x04\x0b\ \x04\x04\x13\n\x0c\n\x05\x04\0\x02\x01\x05\x12\x03\x04\x04\n\n\x0c\n\x05\
\x0e\n\x0c\n\x05\x04\0\x02\x01\x03\x12\x03\x04\x11\x12\n\n\n\x02\x05\0\ \x04\0\x02\x01\x01\x12\x03\x04\x0b\x0e\n\x0c\n\x05\x04\0\x02\x01\x03\x12\
\x12\x04\x06\0\x16\x01\n\n\n\x03\x05\0\x01\x12\x03\x06\x05\x0e\n\x0b\n\ \x03\x04\x11\x12\n\n\n\x02\x05\0\x12\x04\x06\0\x17\x01\n\n\n\x03\x05\0\
\x04\x05\0\x02\0\x12\x03\x07\x04\x15\n\x0c\n\x05\x05\0\x02\0\x01\x12\x03\ \x01\x12\x03\x06\x05\x0e\n\x0b\n\x04\x05\0\x02\0\x12\x03\x07\x04\x15\n\
\x07\x04\x10\n\x0c\n\x05\x05\0\x02\0\x02\x12\x03\x07\x13\x14\n\x0b\n\x04\ \x0c\n\x05\x05\0\x02\0\x01\x12\x03\x07\x04\x10\n\x0c\n\x05\x05\0\x02\0\
\x05\0\x02\x01\x12\x03\x08\x04\x1b\n\x0c\n\x05\x05\0\x02\x01\x01\x12\x03\ \x02\x12\x03\x07\x13\x14\n\x0b\n\x04\x05\0\x02\x01\x12\x03\x08\x04\x1b\n\
\x08\x04\x16\n\x0c\n\x05\x05\0\x02\x01\x02\x12\x03\x08\x19\x1a\n\x0b\n\ \x0c\n\x05\x05\0\x02\x01\x01\x12\x03\x08\x04\x16\n\x0c\n\x05\x05\0\x02\
\x04\x05\0\x02\x02\x12\x03\t\x04\x1b\n\x0c\n\x05\x05\0\x02\x02\x01\x12\ \x01\x02\x12\x03\x08\x19\x1a\n\x0b\n\x04\x05\0\x02\x02\x12\x03\t\x04\x1b\
\x03\t\x04\x16\n\x0c\n\x05\x05\0\x02\x02\x02\x12\x03\t\x19\x1a\n\x0b\n\ \n\x0c\n\x05\x05\0\x02\x02\x01\x12\x03\t\x04\x16\n\x0c\n\x05\x05\0\x02\
\x04\x05\0\x02\x03\x12\x03\n\x04\x19\n\x0c\n\x05\x05\0\x02\x03\x01\x12\ \x02\x02\x12\x03\t\x19\x1a\n\x0b\n\x04\x05\0\x02\x03\x12\x03\n\x04\x19\n\
\x03\n\x04\x13\n\x0c\n\x05\x05\0\x02\x03\x02\x12\x03\n\x16\x18\n\x0b\n\ \x0c\n\x05\x05\0\x02\x03\x01\x12\x03\n\x04\x13\n\x0c\n\x05\x05\0\x02\x03\
\x04\x05\0\x02\x04\x12\x03\x0b\x04\x19\n\x0c\n\x05\x05\0\x02\x04\x01\x12\ \x02\x12\x03\n\x16\x18\n\x0b\n\x04\x05\0\x02\x04\x12\x03\x0b\x04\x19\n\
\x03\x0b\x04\x13\n\x0c\n\x05\x05\0\x02\x04\x02\x12\x03\x0b\x16\x18\n\x0b\ \x0c\n\x05\x05\0\x02\x04\x01\x12\x03\x0b\x04\x13\n\x0c\n\x05\x05\0\x02\
\n\x04\x05\0\x02\x05\x12\x03\x0c\x04*\n\x0c\n\x05\x05\0\x02\x05\x01\x12\ \x04\x02\x12\x03\x0b\x16\x18\n\x0b\n\x04\x05\0\x02\x05\x12\x03\x0c\x04*\
\x03\x0c\x04$\n\x0c\n\x05\x05\0\x02\x05\x02\x12\x03\x0c')\n\x0b\n\x04\ \n\x0c\n\x05\x05\0\x02\x05\x01\x12\x03\x0c\x04$\n\x0c\n\x05\x05\0\x02\
\x05\0\x02\x06\x12\x03\r\x04\x1f\n\x0c\n\x05\x05\0\x02\x06\x01\x12\x03\r\ \x05\x02\x12\x03\x0c')\n\x0b\n\x04\x05\0\x02\x06\x12\x03\r\x04\x1f\n\x0c\
\x04\x19\n\x0c\n\x05\x05\0\x02\x06\x02\x12\x03\r\x1c\x1e\n\x0b\n\x04\x05\ \n\x05\x05\0\x02\x06\x01\x12\x03\r\x04\x19\n\x0c\n\x05\x05\0\x02\x06\x02\
\0\x02\x07\x12\x03\x0e\x04\x1a\n\x0c\n\x05\x05\0\x02\x07\x01\x12\x03\x0e\ \x12\x03\r\x1c\x1e\n\x0b\n\x04\x05\0\x02\x07\x12\x03\x0e\x04\x1a\n\x0c\n\
\x04\x14\n\x0c\n\x05\x05\0\x02\x07\x02\x12\x03\x0e\x17\x19\n\x0b\n\x04\ \x05\x05\0\x02\x07\x01\x12\x03\x0e\x04\x14\n\x0c\n\x05\x05\0\x02\x07\x02\
\x05\0\x02\x08\x12\x03\x0f\x04\x19\n\x0c\n\x05\x05\0\x02\x08\x01\x12\x03\ \x12\x03\x0e\x17\x19\n\x0b\n\x04\x05\0\x02\x08\x12\x03\x0f\x04\x19\n\x0c\
\x0f\x04\x13\n\x0c\n\x05\x05\0\x02\x08\x02\x12\x03\x0f\x16\x18\n\x0b\n\ \n\x05\x05\0\x02\x08\x01\x12\x03\x0f\x04\x13\n\x0c\n\x05\x05\0\x02\x08\
\x04\x05\0\x02\t\x12\x03\x10\x04,\n\x0c\n\x05\x05\0\x02\t\x01\x12\x03\ \x02\x12\x03\x0f\x16\x18\n\x0b\n\x04\x05\0\x02\t\x12\x03\x10\x04,\n\x0c\
\x10\x04&\n\x0c\n\x05\x05\0\x02\t\x02\x12\x03\x10)+\n\x0b\n\x04\x05\0\ \n\x05\x05\0\x02\t\x01\x12\x03\x10\x04&\n\x0c\n\x05\x05\0\x02\t\x02\x12\
\x02\n\x12\x03\x11\x04\x19\n\x0c\n\x05\x05\0\x02\n\x01\x12\x03\x11\x04\ \x03\x10)+\n\x0b\n\x04\x05\0\x02\n\x12\x03\x11\x04\x19\n\x0c\n\x05\x05\0\
\x13\n\x0c\n\x05\x05\0\x02\n\x02\x12\x03\x11\x16\x18\n\x0b\n\x04\x05\0\ \x02\n\x01\x12\x03\x11\x04\x13\n\x0c\n\x05\x05\0\x02\n\x02\x12\x03\x11\
\x02\x0b\x12\x03\x12\x04\x17\n\x0c\n\x05\x05\0\x02\x0b\x01\x12\x03\x12\ \x16\x18\n\x0b\n\x04\x05\0\x02\x0b\x12\x03\x12\x04\x17\n\x0c\n\x05\x05\0\
\x04\x11\n\x0c\n\x05\x05\0\x02\x0b\x02\x12\x03\x12\x14\x16\n\x0b\n\x04\ \x02\x0b\x01\x12\x03\x12\x04\x11\n\x0c\n\x05\x05\0\x02\x0b\x02\x12\x03\
\x05\0\x02\x0c\x12\x03\x13\x04\x1a\n\x0c\n\x05\x05\0\x02\x0c\x01\x12\x03\ \x12\x14\x16\n\x0b\n\x04\x05\0\x02\x0c\x12\x03\x13\x04\x1a\n\x0c\n\x05\
\x13\x04\x14\n\x0c\n\x05\x05\0\x02\x0c\x02\x12\x03\x13\x17\x19\n\x0b\n\ \x05\0\x02\x0c\x01\x12\x03\x13\x04\x14\n\x0c\n\x05\x05\0\x02\x0c\x02\x12\
\x04\x05\0\x02\r\x12\x03\x14\x04\x16\n\x0c\n\x05\x05\0\x02\r\x01\x12\x03\ \x03\x13\x17\x19\n\x0b\n\x04\x05\0\x02\r\x12\x03\x14\x04\x16\n\x0c\n\x05\
\x14\x04\x10\n\x0c\n\x05\x05\0\x02\r\x02\x12\x03\x14\x13\x15\n\x0b\n\x04\ \x05\0\x02\r\x01\x12\x03\x14\x04\x10\n\x0c\n\x05\x05\0\x02\r\x02\x12\x03\
\x05\0\x02\x0e\x12\x03\x15\x04\x18\n\x0c\n\x05\x05\0\x02\x0e\x01\x12\x03\ \x14\x13\x15\n\x0b\n\x04\x05\0\x02\x0e\x12\x03\x15\x04\x17\n\x0c\n\x05\
\x15\x04\x11\n\x0c\n\x05\x05\0\x02\x0e\x02\x12\x03\x15\x14\x17b\x06proto\ \x05\0\x02\x0e\x01\x12\x03\x15\x04\x11\n\x0c\n\x05\x05\0\x02\x0e\x02\x12\
3\ \x03\x15\x14\x16\n\x0b\n\x04\x05\0\x02\x0f\x12\x03\x16\x04\x18\n\x0c\n\
\x05\x05\0\x02\x0f\x01\x12\x03\x16\x04\x11\n\x0c\n\x05\x05\0\x02\x0f\x02\
\x12\x03\x16\x14\x17b\x06proto3\
"; ";
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;

View File

@ -19,5 +19,6 @@ enum ErrorCode {
UserIdInvalid = 23; UserIdInvalid = 23;
UserUnauthorized = 24; UserUnauthorized = 24;
UserNotExist = 25; UserNotExist = 25;
ServerOffline = 26;
InternalError = 100; InternalError = 100;
} }

View File

@ -300,7 +300,12 @@ impl UserSession {
WsState::Init => {}, WsState::Init => {},
WsState::Connected(_) => {}, WsState::Connected(_) => {},
WsState::Disconnected(_) => { WsState::Disconnected(_) => {
ws_controller.retry().await; match ws_controller.retry().await {
Ok(_) => {},
Err(e) => {
log::error!("Retry websocket connect failed: {:?}", e);
}
}
}, },
} }
}, },