mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
merge master
This commit is contained in:
commit
cc17529977
@ -10,7 +10,7 @@ CARGO_MAKE_CRATE_NAME = "dart-ffi"
|
||||
DEV = true
|
||||
LIB_OUT_DIR = "debug"
|
||||
RELEASE = false
|
||||
TARGET_OS = "unknown"
|
||||
#TARGET_OS = "unknown"
|
||||
|
||||
[tasks.setup-crate-type]
|
||||
private = true
|
||||
|
3
app_flowy/.vscode/launch.json
vendored
3
app_flowy/.vscode/launch.json
vendored
@ -9,7 +9,8 @@
|
||||
"request": "launch",
|
||||
"program": "${workspaceRoot}/lib/main.dart",
|
||||
"type": "dart",
|
||||
// "preLaunchTask": "build rust sdk"
|
||||
"preLaunchTask": "build_flowy_sdk",
|
||||
"cwd": "${workspaceRoot}"
|
||||
},
|
||||
{
|
||||
"name": "app_flowy (profile mode)",
|
||||
|
23
app_flowy/.vscode/tasks.json
vendored
23
app_flowy/.vscode/tasks.json
vendored
@ -1,8 +1,6 @@
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
// https://code.visualstudio.com/docs/editor/tasks
|
||||
// https://code.visualstudio.com/docs/editor/tasks
|
||||
//https://gist.github.com/deadalusai/9e13e36d61ec7fb72148
|
||||
|
||||
// ${workspaceRoot}: the root folder of the team
|
||||
@ -11,9 +9,22 @@
|
||||
// ${fileDirname}: the current opened file's dirname
|
||||
// ${fileExtname}: the current opened file's extension
|
||||
// ${cwd}: the current working directory of the spawned process
|
||||
|
||||
"tasks": [
|
||||
{
|
||||
"type": "shell",
|
||||
"command": "sh ${workspaceFolder}/../scripts/build_sdk.sh",
|
||||
"command": "sh ./scripts/build_sdk.sh",
|
||||
"group": "build",
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}/../"
|
||||
},
|
||||
// "problemMatcher": [
|
||||
// "$rustc"
|
||||
// ],
|
||||
"label": "build_flowy_sdk"
|
||||
},
|
||||
{
|
||||
"type": "shell",
|
||||
"command": "sh ./scripts/code_gen.sh",
|
||||
"group": "build",
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}/../"
|
||||
@ -21,7 +32,7 @@
|
||||
"problemMatcher": [
|
||||
"$rustc"
|
||||
],
|
||||
"label": "build rust sdk"
|
||||
"label": "generate events"
|
||||
}
|
||||
]
|
||||
}
|
@ -15,7 +15,7 @@ analyzer:
|
||||
- "**/*.g.dart"
|
||||
- "**/*.freezed.dart"
|
||||
- "packages/flowy_editor/**"
|
||||
- "packages/flowy_infra_ui/**"
|
||||
# - "packages/flowy_infra_ui/**"
|
||||
|
||||
linter:
|
||||
# The lint rules applied to this project can be customized in the
|
||||
|
BIN
app_flowy/assets/images/app_flowy_logo.jpg
Normal file
BIN
app_flowy/assets/images/app_flowy_logo.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 30 KiB |
BIN
app_flowy/assets/images/avatar.jpg
Normal file
BIN
app_flowy/assets/images/avatar.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.6 KiB |
BIN
app_flowy/assets/images/file_icon.jpg
Normal file
BIN
app_flowy/assets/images/file_icon.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
@ -15,7 +15,7 @@ Future<void> initGetIt(
|
||||
getIt.registerLazySingleton<FlowySDK>(() => const FlowySDK());
|
||||
getIt.registerLazySingleton<AppLauncher>(() => AppLauncher(env, getIt));
|
||||
|
||||
await WelcomeDepsResolver.resolve(getIt);
|
||||
await UserDepsResolver.resolve(getIt);
|
||||
await WelcomeDepsResolver.resolve(getIt);
|
||||
await HomeDepsResolver.resolve(getIt);
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ class ApplicationBlocObserver extends BlocObserver {
|
||||
@override
|
||||
// ignore: unnecessary_overrides
|
||||
void onTransition(Bloc bloc, Transition transition) {
|
||||
// Log.debug(transition);
|
||||
Log.debug(transition);
|
||||
super.onTransition(bloc, transition);
|
||||
}
|
||||
|
||||
@ -50,9 +50,3 @@ class ApplicationBlocObserver extends BlocObserver {
|
||||
super.onError(bloc, error, stackTrace);
|
||||
}
|
||||
}
|
||||
|
||||
class EngineBlocConfig {
|
||||
static void setup() {
|
||||
Bloc.observer = ApplicationBlocObserver();
|
||||
}
|
||||
}
|
||||
|
@ -22,10 +22,10 @@ class SignInBloc extends Bloc<SignInEvent, SignInState> {
|
||||
);
|
||||
},
|
||||
emailChanged: (EmailChanged value) async* {
|
||||
yield state.copyWith(email: value.email, signInFailure: none());
|
||||
yield state.copyWith(email: value.email, successOrFail: none());
|
||||
},
|
||||
passwordChanged: (PasswordChanged value) async* {
|
||||
yield state.copyWith(password: value.password, signInFailure: none());
|
||||
yield state.copyWith(password: value.password, successOrFail: none());
|
||||
},
|
||||
);
|
||||
}
|
||||
@ -36,17 +36,34 @@ class SignInBloc extends Bloc<SignInEvent, SignInState> {
|
||||
final result = await authImpl.signIn(state.email, state.password);
|
||||
yield result.fold(
|
||||
(userDetail) => state.copyWith(
|
||||
isSubmitting: false, signInFailure: some(left(userDetail))),
|
||||
(s) => state.copyWith(isSubmitting: false, signInFailure: some(right(s))),
|
||||
isSubmitting: false, successOrFail: some(left(userDetail))),
|
||||
(error) => stateFromCode(error),
|
||||
);
|
||||
}
|
||||
|
||||
SignInState stateFromCode(UserError error) {
|
||||
switch (error.code) {
|
||||
case UserErrCode.EmailInvalid:
|
||||
return state.copyWith(
|
||||
isSubmitting: false,
|
||||
emailError: some(error.msg),
|
||||
passwordError: none());
|
||||
case UserErrCode.PasswordInvalid:
|
||||
return state.copyWith(
|
||||
isSubmitting: false,
|
||||
passwordError: some(error.msg),
|
||||
emailError: none());
|
||||
default:
|
||||
return state.copyWith(
|
||||
isSubmitting: false, successOrFail: some(right(error)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@freezed
|
||||
abstract class SignInEvent with _$SignInEvent {
|
||||
const factory SignInEvent.signedInWithUserEmailAndPassword() =
|
||||
SignedInWithUserEmailAndPassword;
|
||||
|
||||
const factory SignInEvent.emailChanged(String email) = EmailChanged;
|
||||
const factory SignInEvent.passwordChanged(String password) = PasswordChanged;
|
||||
}
|
||||
@ -57,11 +74,15 @@ abstract class SignInState with _$SignInState {
|
||||
String? email,
|
||||
String? password,
|
||||
required bool isSubmitting,
|
||||
required Option<Either<UserDetail, UserError>> signInFailure,
|
||||
required Option<String> passwordError,
|
||||
required Option<String> emailError,
|
||||
required Option<Either<UserDetail, UserError>> successOrFail,
|
||||
}) = _SignInState;
|
||||
|
||||
factory SignInState.initial() => SignInState(
|
||||
isSubmitting: false,
|
||||
signInFailure: none(),
|
||||
passwordError: none(),
|
||||
emailError: none(),
|
||||
successOrFail: none(),
|
||||
);
|
||||
}
|
||||
|
@ -438,12 +438,16 @@ class _$SignInStateTearOff {
|
||||
{String? email,
|
||||
String? password,
|
||||
required bool isSubmitting,
|
||||
required Option<Either<UserDetail, UserError>> signInFailure}) {
|
||||
required Option<String> passwordError,
|
||||
required Option<String> emailError,
|
||||
required Option<Either<UserDetail, UserError>> successOrFail}) {
|
||||
return _SignInState(
|
||||
email: email,
|
||||
password: password,
|
||||
isSubmitting: isSubmitting,
|
||||
signInFailure: signInFailure,
|
||||
passwordError: passwordError,
|
||||
emailError: emailError,
|
||||
successOrFail: successOrFail,
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -456,7 +460,9 @@ mixin _$SignInState {
|
||||
String? get email => throw _privateConstructorUsedError;
|
||||
String? get password => throw _privateConstructorUsedError;
|
||||
bool get isSubmitting => throw _privateConstructorUsedError;
|
||||
Option<Either<UserDetail, UserError>> get signInFailure =>
|
||||
Option<String> get passwordError => throw _privateConstructorUsedError;
|
||||
Option<String> get emailError => throw _privateConstructorUsedError;
|
||||
Option<Either<UserDetail, UserError>> get successOrFail =>
|
||||
throw _privateConstructorUsedError;
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@ -473,7 +479,9 @@ abstract class $SignInStateCopyWith<$Res> {
|
||||
{String? email,
|
||||
String? password,
|
||||
bool isSubmitting,
|
||||
Option<Either<UserDetail, UserError>> signInFailure});
|
||||
Option<String> passwordError,
|
||||
Option<String> emailError,
|
||||
Option<Either<UserDetail, UserError>> successOrFail});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@ -489,7 +497,9 @@ class _$SignInStateCopyWithImpl<$Res> implements $SignInStateCopyWith<$Res> {
|
||||
Object? email = freezed,
|
||||
Object? password = freezed,
|
||||
Object? isSubmitting = freezed,
|
||||
Object? signInFailure = freezed,
|
||||
Object? passwordError = freezed,
|
||||
Object? emailError = freezed,
|
||||
Object? successOrFail = freezed,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
email: email == freezed
|
||||
@ -504,9 +514,17 @@ class _$SignInStateCopyWithImpl<$Res> implements $SignInStateCopyWith<$Res> {
|
||||
? _value.isSubmitting
|
||||
: isSubmitting // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
signInFailure: signInFailure == freezed
|
||||
? _value.signInFailure
|
||||
: signInFailure // ignore: cast_nullable_to_non_nullable
|
||||
passwordError: passwordError == freezed
|
||||
? _value.passwordError
|
||||
: passwordError // ignore: cast_nullable_to_non_nullable
|
||||
as Option<String>,
|
||||
emailError: emailError == freezed
|
||||
? _value.emailError
|
||||
: emailError // ignore: cast_nullable_to_non_nullable
|
||||
as Option<String>,
|
||||
successOrFail: successOrFail == freezed
|
||||
? _value.successOrFail
|
||||
: successOrFail // ignore: cast_nullable_to_non_nullable
|
||||
as Option<Either<UserDetail, UserError>>,
|
||||
));
|
||||
}
|
||||
@ -523,7 +541,9 @@ abstract class _$SignInStateCopyWith<$Res>
|
||||
{String? email,
|
||||
String? password,
|
||||
bool isSubmitting,
|
||||
Option<Either<UserDetail, UserError>> signInFailure});
|
||||
Option<String> passwordError,
|
||||
Option<String> emailError,
|
||||
Option<Either<UserDetail, UserError>> successOrFail});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@ -541,7 +561,9 @@ class __$SignInStateCopyWithImpl<$Res> extends _$SignInStateCopyWithImpl<$Res>
|
||||
Object? email = freezed,
|
||||
Object? password = freezed,
|
||||
Object? isSubmitting = freezed,
|
||||
Object? signInFailure = freezed,
|
||||
Object? passwordError = freezed,
|
||||
Object? emailError = freezed,
|
||||
Object? successOrFail = freezed,
|
||||
}) {
|
||||
return _then(_SignInState(
|
||||
email: email == freezed
|
||||
@ -556,9 +578,17 @@ class __$SignInStateCopyWithImpl<$Res> extends _$SignInStateCopyWithImpl<$Res>
|
||||
? _value.isSubmitting
|
||||
: isSubmitting // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
signInFailure: signInFailure == freezed
|
||||
? _value.signInFailure
|
||||
: signInFailure // ignore: cast_nullable_to_non_nullable
|
||||
passwordError: passwordError == freezed
|
||||
? _value.passwordError
|
||||
: passwordError // ignore: cast_nullable_to_non_nullable
|
||||
as Option<String>,
|
||||
emailError: emailError == freezed
|
||||
? _value.emailError
|
||||
: emailError // ignore: cast_nullable_to_non_nullable
|
||||
as Option<String>,
|
||||
successOrFail: successOrFail == freezed
|
||||
? _value.successOrFail
|
||||
: successOrFail // ignore: cast_nullable_to_non_nullable
|
||||
as Option<Either<UserDetail, UserError>>,
|
||||
));
|
||||
}
|
||||
@ -571,7 +601,9 @@ class _$_SignInState implements _SignInState {
|
||||
{this.email,
|
||||
this.password,
|
||||
required this.isSubmitting,
|
||||
required this.signInFailure});
|
||||
required this.passwordError,
|
||||
required this.emailError,
|
||||
required this.successOrFail});
|
||||
|
||||
@override
|
||||
final String? email;
|
||||
@ -580,11 +612,15 @@ class _$_SignInState implements _SignInState {
|
||||
@override
|
||||
final bool isSubmitting;
|
||||
@override
|
||||
final Option<Either<UserDetail, UserError>> signInFailure;
|
||||
final Option<String> passwordError;
|
||||
@override
|
||||
final Option<String> emailError;
|
||||
@override
|
||||
final Option<Either<UserDetail, UserError>> successOrFail;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SignInState(email: $email, password: $password, isSubmitting: $isSubmitting, signInFailure: $signInFailure)';
|
||||
return 'SignInState(email: $email, password: $password, isSubmitting: $isSubmitting, passwordError: $passwordError, emailError: $emailError, successOrFail: $successOrFail)';
|
||||
}
|
||||
|
||||
@override
|
||||
@ -599,9 +635,15 @@ class _$_SignInState implements _SignInState {
|
||||
(identical(other.isSubmitting, isSubmitting) ||
|
||||
const DeepCollectionEquality()
|
||||
.equals(other.isSubmitting, isSubmitting)) &&
|
||||
(identical(other.signInFailure, signInFailure) ||
|
||||
(identical(other.passwordError, passwordError) ||
|
||||
const DeepCollectionEquality()
|
||||
.equals(other.signInFailure, signInFailure)));
|
||||
.equals(other.passwordError, passwordError)) &&
|
||||
(identical(other.emailError, emailError) ||
|
||||
const DeepCollectionEquality()
|
||||
.equals(other.emailError, emailError)) &&
|
||||
(identical(other.successOrFail, successOrFail) ||
|
||||
const DeepCollectionEquality()
|
||||
.equals(other.successOrFail, successOrFail)));
|
||||
}
|
||||
|
||||
@override
|
||||
@ -610,7 +652,9 @@ class _$_SignInState implements _SignInState {
|
||||
const DeepCollectionEquality().hash(email) ^
|
||||
const DeepCollectionEquality().hash(password) ^
|
||||
const DeepCollectionEquality().hash(isSubmitting) ^
|
||||
const DeepCollectionEquality().hash(signInFailure);
|
||||
const DeepCollectionEquality().hash(passwordError) ^
|
||||
const DeepCollectionEquality().hash(emailError) ^
|
||||
const DeepCollectionEquality().hash(successOrFail);
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
@ -623,7 +667,9 @@ abstract class _SignInState implements SignInState {
|
||||
{String? email,
|
||||
String? password,
|
||||
required bool isSubmitting,
|
||||
required Option<Either<UserDetail, UserError>> signInFailure}) =
|
||||
required Option<String> passwordError,
|
||||
required Option<String> emailError,
|
||||
required Option<Either<UserDetail, UserError>> successOrFail}) =
|
||||
_$_SignInState;
|
||||
|
||||
@override
|
||||
@ -633,7 +679,11 @@ abstract class _SignInState implements SignInState {
|
||||
@override
|
||||
bool get isSubmitting => throw _privateConstructorUsedError;
|
||||
@override
|
||||
Option<Either<UserDetail, UserError>> get signInFailure =>
|
||||
Option<String> get passwordError => throw _privateConstructorUsedError;
|
||||
@override
|
||||
Option<String> get emailError => throw _privateConstructorUsedError;
|
||||
@override
|
||||
Option<Either<UserDetail, UserError>> get successOrFail =>
|
||||
throw _privateConstructorUsedError;
|
||||
@override
|
||||
@JsonKey(ignore: true)
|
||||
|
@ -1,5 +1,6 @@
|
||||
import 'package:flowy_sdk/protobuf/flowy-user/protobuf.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
abstract class IAuth {
|
||||
Future<Either<UserDetail, UserError>> signIn(String? email, String? password);
|
||||
@ -8,3 +9,9 @@ abstract class IAuth {
|
||||
|
||||
Future<Either<Unit, UserError>> signOut();
|
||||
}
|
||||
|
||||
abstract class IAuthRouter {
|
||||
void showHomeScreen(BuildContext context, UserDetail user);
|
||||
void showSignUpScreen(BuildContext context);
|
||||
void showForgetPasswordScreen(BuildContext context);
|
||||
}
|
||||
|
@ -6,10 +6,11 @@ import 'package:get_it/get_it.dart';
|
||||
|
||||
class UserDepsResolver {
|
||||
static Future<void> resolve(GetIt getIt) async {
|
||||
getIt.registerLazySingleton<AuthRepository>(() => AuthRepository());
|
||||
getIt.registerFactory<AuthRepository>(() => AuthRepository());
|
||||
|
||||
//Interface implementation
|
||||
getIt.registerFactory<IAuth>(() => AuthImpl(repo: getIt<AuthRepository>()));
|
||||
getIt.registerFactory<IAuthRouter>(() => AuthRouterImpl());
|
||||
|
||||
//Bloc
|
||||
getIt.registerFactory<SignInBloc>(() => SignInBloc(getIt<IAuth>()));
|
||||
|
@ -1,7 +1,10 @@
|
||||
import 'package:app_flowy/workspace/presentation/home/home_screen.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:flowy_infra_ui/widget/route/animation.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-user/protobuf.dart';
|
||||
import 'package:app_flowy/user/domain/i_auth.dart';
|
||||
import 'package:app_flowy/user/infrastructure/repos/auth_repo.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class AuthImpl extends IAuth {
|
||||
AuthRepository repo;
|
||||
@ -26,3 +29,20 @@ class AuthImpl extends IAuth {
|
||||
return repo.signOut();
|
||||
}
|
||||
}
|
||||
|
||||
class AuthRouterImpl extends IAuthRouter {
|
||||
@override
|
||||
void showForgetPasswordScreen(BuildContext context) {
|
||||
// TODO: implement showForgetPasswordScreen
|
||||
}
|
||||
|
||||
@override
|
||||
void showHomeScreen(BuildContext context, UserDetail user) {
|
||||
Navigator.of(context).push(PageRoutes.fade(() => HomeScreen(user)));
|
||||
}
|
||||
|
||||
@override
|
||||
void showSignUpScreen(BuildContext context) {
|
||||
// TODO: implement showSignUpScreen
|
||||
}
|
||||
}
|
||||
|
@ -1,19 +1,217 @@
|
||||
import 'package:app_flowy/startup/startup.dart';
|
||||
import 'package:app_flowy/user/application/sign_in/sign_in_bloc.dart';
|
||||
import 'package:app_flowy/user/presentation/sign_in/widgets/body.dart';
|
||||
import 'package:app_flowy/user/domain/i_auth.dart';
|
||||
import 'package:app_flowy/user/presentation/sign_in/widgets/background.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/spacing.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-user/errors.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-user/user_detail.pb.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
|
||||
class SignInScreen extends StatelessWidget {
|
||||
const SignInScreen({Key? key}) : super(key: key);
|
||||
final IAuthRouter router;
|
||||
const SignInScreen({Key? key, required this.router}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocProvider(
|
||||
create: (context) => getIt<SignInBloc>(),
|
||||
child: const Scaffold(
|
||||
body: Body(),
|
||||
child: BlocListener<SignInBloc, SignInState>(
|
||||
listener: (context, state) {
|
||||
state.successOrFail.fold(
|
||||
() => null,
|
||||
(result) => _handleSuccessOrFail(result, context),
|
||||
);
|
||||
},
|
||||
child: Scaffold(
|
||||
body: SignInForm(router: router),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _handleSuccessOrFail(
|
||||
Either<UserDetail, UserError> result, BuildContext context) {
|
||||
result.fold(
|
||||
(user) => router.showHomeScreen(context, user),
|
||||
(error) => _showErrorMessage(context, error.msg),
|
||||
);
|
||||
}
|
||||
|
||||
void _showErrorMessage(BuildContext context, String msg) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(msg),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class SignInForm extends StatelessWidget {
|
||||
final IAuthRouter router;
|
||||
const SignInForm({
|
||||
Key? key,
|
||||
required this.router,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Align(
|
||||
alignment: Alignment.center,
|
||||
child: SignInFormContainer(
|
||||
children: [
|
||||
const SignInTitle(
|
||||
title: 'Login to Appflowy',
|
||||
logoSize: Size(60, 60),
|
||||
),
|
||||
const VSpace(30),
|
||||
const EmailTextField(),
|
||||
const PasswordTextField(),
|
||||
ForgetPasswordButton(router: router),
|
||||
const LoginButton(),
|
||||
const VSpace(10),
|
||||
SignUpPrompt(router: router),
|
||||
if (context.read<SignInBloc>().state.isSubmitting) ...[
|
||||
const SizedBox(height: 8),
|
||||
const LinearProgressIndicator(value: null),
|
||||
]
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class SignUpPrompt extends StatelessWidget {
|
||||
const SignUpPrompt({
|
||||
Key? key,
|
||||
required this.router,
|
||||
}) : super(key: key);
|
||||
|
||||
final IAuthRouter router;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
children: [
|
||||
const Text("Dont't have an account",
|
||||
style: TextStyle(color: Colors.blueGrey, fontSize: 12)),
|
||||
TextButton(
|
||||
style: TextButton.styleFrom(
|
||||
textStyle: const TextStyle(fontSize: 12),
|
||||
),
|
||||
onPressed: () => router.showSignUpScreen(context),
|
||||
child: const Text(
|
||||
'Sign Up',
|
||||
style: TextStyle(color: Colors.lightBlue),
|
||||
),
|
||||
),
|
||||
],
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class LoginButton extends StatelessWidget {
|
||||
const LoginButton({
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return RoundedTextButton(
|
||||
title: 'Login',
|
||||
height: 45,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
color: Colors.lightBlue,
|
||||
press: () {
|
||||
context
|
||||
.read<SignInBloc>()
|
||||
.add(const SignInEvent.signedInWithUserEmailAndPassword());
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ForgetPasswordButton extends StatelessWidget {
|
||||
const ForgetPasswordButton({
|
||||
Key? key,
|
||||
required this.router,
|
||||
}) : super(key: key);
|
||||
|
||||
final IAuthRouter router;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return TextButton(
|
||||
style: TextButton.styleFrom(
|
||||
textStyle: const TextStyle(fontSize: 12),
|
||||
),
|
||||
onPressed: () => router.showForgetPasswordScreen(context),
|
||||
child: const Text(
|
||||
'Forgot Password?',
|
||||
style: TextStyle(color: Colors.lightBlue),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class PasswordTextField extends StatelessWidget {
|
||||
const PasswordTextField({
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocBuilder<SignInBloc, SignInState>(
|
||||
buildWhen: (previous, current) =>
|
||||
previous.passwordError != current.passwordError,
|
||||
builder: (context, state) {
|
||||
return RoundedInputField(
|
||||
obscureText: true,
|
||||
hintText: 'password',
|
||||
normalBorderColor: Colors.green,
|
||||
highlightBorderColor: Colors.red,
|
||||
errorText: context
|
||||
.read<SignInBloc>()
|
||||
.state
|
||||
.passwordError
|
||||
.fold(() => "", (error) => error),
|
||||
onChanged: (value) => context
|
||||
.read<SignInBloc>()
|
||||
.add(SignInEvent.passwordChanged(value)),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class EmailTextField extends StatelessWidget {
|
||||
const EmailTextField({
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocBuilder<SignInBloc, SignInState>(
|
||||
buildWhen: (previous, current) =>
|
||||
previous.emailError != current.emailError,
|
||||
builder: (context, state) {
|
||||
return RoundedInputField(
|
||||
hintText: 'email',
|
||||
normalBorderColor: Colors.green,
|
||||
highlightBorderColor: Colors.red,
|
||||
errorText: context
|
||||
.read<SignInBloc>()
|
||||
.state
|
||||
.emailError
|
||||
.fold(() => "", (error) => error),
|
||||
onChanged: (value) =>
|
||||
context.read<SignInBloc>().add(SignInEvent.emailChanged(value)),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,29 +1,57 @@
|
||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class SignInBackground extends StatelessWidget {
|
||||
final Widget child;
|
||||
const SignInBackground({
|
||||
class SignInFormContainer extends StatelessWidget {
|
||||
final List<Widget> children;
|
||||
const SignInFormContainer({
|
||||
Key? key,
|
||||
required this.child,
|
||||
required this.children,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var size = MediaQuery.of(context).size;
|
||||
final size = MediaQuery.of(context).size;
|
||||
return SizedBox(
|
||||
height: size.height,
|
||||
width: double.infinity,
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
Image(
|
||||
fit: BoxFit.cover,
|
||||
width: size.width,
|
||||
height: size.height,
|
||||
image: const AssetImage(
|
||||
'assets/images/appflowy_launch_splash.jpg')),
|
||||
child,
|
||||
],
|
||||
));
|
||||
width: size.width * 0.3,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: children,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class SignInTitle extends StatelessWidget {
|
||||
final String title;
|
||||
final Size logoSize;
|
||||
const SignInTitle({
|
||||
Key? key,
|
||||
required this.title,
|
||||
required this.logoSize,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SizedBox(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Image(
|
||||
fit: BoxFit.cover,
|
||||
width: logoSize.width,
|
||||
height: logoSize.height,
|
||||
image: const AssetImage('assets/images/app_flowy_logo.jpg')),
|
||||
const VSpace(30),
|
||||
Text(
|
||||
title,
|
||||
style: const TextStyle(
|
||||
color: Colors.black,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 20,
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,125 +0,0 @@
|
||||
import 'package:app_flowy/startup/startup.dart';
|
||||
import 'package:app_flowy/user/application/sign_in/sign_in_bloc.dart';
|
||||
import 'package:app_flowy/user/presentation/sign_in/widgets/background.dart';
|
||||
import 'package:app_flowy/workspace/presentation/home/home_screen.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:flowy_infra_ui/widget/rounded_button.dart';
|
||||
import 'package:flowy_infra_ui/widget/rounded_input_field.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-user/protobuf.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
class Body extends StatelessWidget {
|
||||
const Body({Key? key}) : super(key: key);
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocProvider(
|
||||
create: (context) => getIt<SignInBloc>(),
|
||||
child: const SignInBackground(
|
||||
child: SignInForm(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class SignInForm extends StatelessWidget {
|
||||
const SignInForm({
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocConsumer<SignInBloc, SignInState>(
|
||||
listenWhen: (p, c) => p != c,
|
||||
listener: (context, state) {
|
||||
state.signInFailure.fold(
|
||||
() {},
|
||||
(result) => _handleStateErrors(result, context),
|
||||
);
|
||||
},
|
||||
builder: (context, state) {
|
||||
return SignInFormBackground(
|
||||
children: [
|
||||
const SizedBox(height: 30),
|
||||
RoundedInputField(
|
||||
icon: Icons.person,
|
||||
hintText: 'email',
|
||||
onChanged: (value) => context
|
||||
.read<SignInBloc>()
|
||||
.add(SignInEvent.emailChanged(value)),
|
||||
),
|
||||
RoundedInputField(
|
||||
icon: Icons.lock,
|
||||
obscureText: true,
|
||||
hintText: 'password',
|
||||
onChanged: (value) => context
|
||||
.read<SignInBloc>()
|
||||
.add(SignInEvent.passwordChanged(value)),
|
||||
),
|
||||
RoundedButton(
|
||||
title: 'LOGIN',
|
||||
press: () {
|
||||
context
|
||||
.read<SignInBloc>()
|
||||
.add(const SignInEvent.signedInWithUserEmailAndPassword());
|
||||
},
|
||||
),
|
||||
if (state.isSubmitting) ...[
|
||||
const SizedBox(height: 8),
|
||||
const LinearProgressIndicator(value: null),
|
||||
]
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void _handleStateErrors(
|
||||
Either<UserDetail, UserError> some, BuildContext context) {
|
||||
some.fold(
|
||||
(userDetail) => showHomeScreen(context, userDetail),
|
||||
(result) => _showErrorMessage(context, result.msg),
|
||||
);
|
||||
}
|
||||
|
||||
void _showErrorMessage(BuildContext context, String msg) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(msg),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void showHomeScreen(BuildContext context, UserDetail userDetail) {
|
||||
Navigator.pushReplacement(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) {
|
||||
return HomeScreen(userDetail);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class SignInFormBackground extends StatelessWidget {
|
||||
final List<Widget> children;
|
||||
const SignInFormBackground({
|
||||
Key? key,
|
||||
required this.children,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final size = MediaQuery.of(context).size;
|
||||
|
||||
return Container(
|
||||
width: size.width * 0.4,
|
||||
alignment: Alignment.center,
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center, children: children),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -13,7 +13,7 @@ class WelcomeBloc extends Bloc<WelcomeEvent, WelcomeState> {
|
||||
Stream<WelcomeState> mapEventToState(WelcomeEvent event) async* {
|
||||
yield* event.map(
|
||||
getUser: (val) async* {
|
||||
final authState = await authImpl.currentUserState();
|
||||
final authState = await authImpl.currentUserDetail();
|
||||
yield state.copyWith(auth: authState);
|
||||
},
|
||||
);
|
||||
|
@ -4,7 +4,7 @@ import 'package:flutter/widgets.dart';
|
||||
import 'auth_state.dart';
|
||||
|
||||
abstract class IWelcomeAuth {
|
||||
Future<AuthState> currentUserState();
|
||||
Future<AuthState> currentUserDetail();
|
||||
}
|
||||
|
||||
abstract class IWelcomeRoute {
|
||||
|
@ -1,3 +1,5 @@
|
||||
import 'package:app_flowy/startup/startup.dart';
|
||||
import 'package:app_flowy/user/domain/i_auth.dart';
|
||||
import 'package:app_flowy/user/presentation/sign_in/sign_in_screen.dart';
|
||||
import 'package:app_flowy/welcome/domain/auth_state.dart';
|
||||
import 'package:app_flowy/welcome/domain/i_welcome.dart';
|
||||
@ -11,7 +13,7 @@ export 'package:app_flowy/welcome/domain/i_welcome.dart';
|
||||
|
||||
class WelcomeAuthImpl implements IWelcomeAuth {
|
||||
@override
|
||||
Future<AuthState> currentUserState() {
|
||||
Future<AuthState> currentUserDetail() {
|
||||
final result = UserEventGetStatus().send();
|
||||
return result.then((result) {
|
||||
return result.fold(
|
||||
@ -34,6 +36,6 @@ class WelcomeRoute implements IWelcomeRoute {
|
||||
|
||||
@override
|
||||
Widget pushSignInScreen() {
|
||||
return const SignInScreen();
|
||||
return SignInScreen(router: getIt<IAuthRouter>());
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,6 @@ class DocBloc extends Bloc<DocEvent, DocState> {
|
||||
Stream<DocState> mapEventToState(DocEvent event) async* {
|
||||
yield* event.map(
|
||||
initial: (e) async* {},
|
||||
save: (Save value) async* {},
|
||||
close: (Close value) async* {},
|
||||
);
|
||||
}
|
||||
@ -23,7 +22,6 @@ class DocBloc extends Bloc<DocEvent, DocState> {
|
||||
@freezed
|
||||
abstract class DocEvent with _$DocEvent {
|
||||
const factory DocEvent.initial() = Initial;
|
||||
const factory DocEvent.save(String jsonStr) = Save;
|
||||
const factory DocEvent.close() = Close;
|
||||
}
|
||||
|
||||
|
@ -20,12 +20,6 @@ class _$DocEventTearOff {
|
||||
return const Initial();
|
||||
}
|
||||
|
||||
Save save(String jsonStr) {
|
||||
return Save(
|
||||
jsonStr,
|
||||
);
|
||||
}
|
||||
|
||||
Close close() {
|
||||
return const Close();
|
||||
}
|
||||
@ -39,14 +33,12 @@ mixin _$DocEvent {
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function() initial,
|
||||
required TResult Function(String jsonStr) save,
|
||||
required TResult Function() close,
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function()? initial,
|
||||
TResult Function(String jsonStr)? save,
|
||||
TResult Function()? close,
|
||||
required TResult orElse(),
|
||||
}) =>
|
||||
@ -54,14 +46,12 @@ mixin _$DocEvent {
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>({
|
||||
required TResult Function(Initial value) initial,
|
||||
required TResult Function(Save value) save,
|
||||
required TResult Function(Close value) close,
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>({
|
||||
TResult Function(Initial value)? initial,
|
||||
TResult Function(Save value)? save,
|
||||
TResult Function(Close value)? close,
|
||||
required TResult orElse(),
|
||||
}) =>
|
||||
@ -121,7 +111,6 @@ class _$Initial implements Initial {
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function() initial,
|
||||
required TResult Function(String jsonStr) save,
|
||||
required TResult Function() close,
|
||||
}) {
|
||||
return initial();
|
||||
@ -131,7 +120,6 @@ class _$Initial implements Initial {
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function()? initial,
|
||||
TResult Function(String jsonStr)? save,
|
||||
TResult Function()? close,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
@ -145,7 +133,6 @@ class _$Initial implements Initial {
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>({
|
||||
required TResult Function(Initial value) initial,
|
||||
required TResult Function(Save value) save,
|
||||
required TResult Function(Close value) close,
|
||||
}) {
|
||||
return initial(this);
|
||||
@ -155,7 +142,6 @@ class _$Initial implements Initial {
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>({
|
||||
TResult Function(Initial value)? initial,
|
||||
TResult Function(Save value)? save,
|
||||
TResult Function(Close value)? close,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
@ -170,122 +156,6 @@ abstract class Initial implements DocEvent {
|
||||
const factory Initial() = _$Initial;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $SaveCopyWith<$Res> {
|
||||
factory $SaveCopyWith(Save value, $Res Function(Save) then) =
|
||||
_$SaveCopyWithImpl<$Res>;
|
||||
$Res call({String jsonStr});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$SaveCopyWithImpl<$Res> extends _$DocEventCopyWithImpl<$Res>
|
||||
implements $SaveCopyWith<$Res> {
|
||||
_$SaveCopyWithImpl(Save _value, $Res Function(Save) _then)
|
||||
: super(_value, (v) => _then(v as Save));
|
||||
|
||||
@override
|
||||
Save get _value => super._value as Save;
|
||||
|
||||
@override
|
||||
$Res call({
|
||||
Object? jsonStr = freezed,
|
||||
}) {
|
||||
return _then(Save(
|
||||
jsonStr == freezed
|
||||
? _value.jsonStr
|
||||
: jsonStr // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$Save implements Save {
|
||||
const _$Save(this.jsonStr);
|
||||
|
||||
@override
|
||||
final String jsonStr;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'DocEvent.save(jsonStr: $jsonStr)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(dynamic other) {
|
||||
return identical(this, other) ||
|
||||
(other is Save &&
|
||||
(identical(other.jsonStr, jsonStr) ||
|
||||
const DeepCollectionEquality().equals(other.jsonStr, jsonStr)));
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
runtimeType.hashCode ^ const DeepCollectionEquality().hash(jsonStr);
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
$SaveCopyWith<Save> get copyWith =>
|
||||
_$SaveCopyWithImpl<Save>(this, _$identity);
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function() initial,
|
||||
required TResult Function(String jsonStr) save,
|
||||
required TResult Function() close,
|
||||
}) {
|
||||
return save(jsonStr);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function()? initial,
|
||||
TResult Function(String jsonStr)? save,
|
||||
TResult Function()? close,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (save != null) {
|
||||
return save(jsonStr);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>({
|
||||
required TResult Function(Initial value) initial,
|
||||
required TResult Function(Save value) save,
|
||||
required TResult Function(Close value) close,
|
||||
}) {
|
||||
return save(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>({
|
||||
TResult Function(Initial value)? initial,
|
||||
TResult Function(Save value)? save,
|
||||
TResult Function(Close value)? close,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (save != null) {
|
||||
return save(this);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
}
|
||||
|
||||
abstract class Save implements DocEvent {
|
||||
const factory Save(String jsonStr) = _$Save;
|
||||
|
||||
String get jsonStr => throw _privateConstructorUsedError;
|
||||
@JsonKey(ignore: true)
|
||||
$SaveCopyWith<Save> get copyWith => throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $CloseCopyWith<$Res> {
|
||||
factory $CloseCopyWith(Close value, $Res Function(Close) then) =
|
||||
@ -324,7 +194,6 @@ class _$Close implements Close {
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function() initial,
|
||||
required TResult Function(String jsonStr) save,
|
||||
required TResult Function() close,
|
||||
}) {
|
||||
return close();
|
||||
@ -334,7 +203,6 @@ class _$Close implements Close {
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function()? initial,
|
||||
TResult Function(String jsonStr)? save,
|
||||
TResult Function()? close,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
@ -348,7 +216,6 @@ class _$Close implements Close {
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>({
|
||||
required TResult Function(Initial value) initial,
|
||||
required TResult Function(Save value) save,
|
||||
required TResult Function(Close value) close,
|
||||
}) {
|
||||
return close(this);
|
||||
@ -358,7 +225,6 @@ class _$Close implements Close {
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>({
|
||||
TResult Function(Initial value)? initial,
|
||||
TResult Function(Save value)? save,
|
||||
TResult Function(Close value)? close,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
|
@ -40,9 +40,7 @@ class MenuBloc extends Bloc<MenuEvent, MenuState> {
|
||||
}
|
||||
|
||||
Stream<MenuState> _performActionOnCreateApp(CreateApp event) async* {
|
||||
await iWorkspaceImpl
|
||||
.createApp(name: event.name, desc: event.desc)
|
||||
.then((result) async* {
|
||||
iWorkspaceImpl.createApp(name: event.name, desc: event.desc).then((result) {
|
||||
result.fold(
|
||||
(app) => {},
|
||||
(error) async* {
|
||||
|
60
app_flowy/lib/workspace/application/menu/menu_user_bloc.dart
Normal file
60
app_flowy/lib/workspace/application/menu/menu_user_bloc.dart
Normal file
@ -0,0 +1,60 @@
|
||||
import 'package:app_flowy/workspace/domain/i_user.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-user/user_detail.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace/workspace_create.pb.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
|
||||
part 'menu_user_bloc.freezed.dart';
|
||||
|
||||
class MenuUserBloc extends Bloc<MenuUserEvent, MenuUserState> {
|
||||
final IUser iUserImpl;
|
||||
|
||||
MenuUserBloc(this.iUserImpl) : super(MenuUserState.initial(iUserImpl.user));
|
||||
|
||||
@override
|
||||
Stream<MenuUserState> mapEventToState(MenuUserEvent event) async* {
|
||||
yield* event.map(
|
||||
initial: (_) async* {
|
||||
// fetch workspaces
|
||||
iUserImpl.fetchWorkspaces().then((result) {
|
||||
result.fold(
|
||||
(workspaces) async* {
|
||||
yield state.copyWith(workspaces: some(workspaces));
|
||||
},
|
||||
(error) async* {
|
||||
yield state.copyWith(successOrFailure: right(error.msg));
|
||||
},
|
||||
);
|
||||
});
|
||||
},
|
||||
fetchWorkspaces: (_FetchWorkspaces value) async* {},
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> close() async {
|
||||
super.close();
|
||||
}
|
||||
}
|
||||
|
||||
@freezed
|
||||
class MenuUserEvent with _$MenuUserEvent {
|
||||
const factory MenuUserEvent.initial() = _Initial;
|
||||
const factory MenuUserEvent.fetchWorkspaces() = _FetchWorkspaces;
|
||||
}
|
||||
|
||||
@freezed
|
||||
class MenuUserState with _$MenuUserState {
|
||||
const factory MenuUserState({
|
||||
required UserDetail user,
|
||||
required Option<List<Workspace>> workspaces,
|
||||
required Either<Unit, String> successOrFailure,
|
||||
}) = _MenuUserState;
|
||||
|
||||
factory MenuUserState.initial(UserDetail user) => MenuUserState(
|
||||
user: user,
|
||||
workspaces: none(),
|
||||
successOrFailure: left(unit),
|
||||
);
|
||||
}
|
@ -0,0 +1,432 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides
|
||||
|
||||
part of 'menu_user_bloc.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
final _privateConstructorUsedError = UnsupportedError(
|
||||
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more informations: https://github.com/rrousselGit/freezed#custom-getters-and-methods');
|
||||
|
||||
/// @nodoc
|
||||
class _$MenuUserEventTearOff {
|
||||
const _$MenuUserEventTearOff();
|
||||
|
||||
_Initial initial() {
|
||||
return const _Initial();
|
||||
}
|
||||
|
||||
_FetchWorkspaces fetchWorkspaces() {
|
||||
return const _FetchWorkspaces();
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
const $MenuUserEvent = _$MenuUserEventTearOff();
|
||||
|
||||
/// @nodoc
|
||||
mixin _$MenuUserEvent {
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function() initial,
|
||||
required TResult Function() fetchWorkspaces,
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function()? initial,
|
||||
TResult Function()? fetchWorkspaces,
|
||||
required TResult orElse(),
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>({
|
||||
required TResult Function(_Initial value) initial,
|
||||
required TResult Function(_FetchWorkspaces value) fetchWorkspaces,
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>({
|
||||
TResult Function(_Initial value)? initial,
|
||||
TResult Function(_FetchWorkspaces value)? fetchWorkspaces,
|
||||
required TResult orElse(),
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $MenuUserEventCopyWith<$Res> {
|
||||
factory $MenuUserEventCopyWith(
|
||||
MenuUserEvent value, $Res Function(MenuUserEvent) then) =
|
||||
_$MenuUserEventCopyWithImpl<$Res>;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$MenuUserEventCopyWithImpl<$Res>
|
||||
implements $MenuUserEventCopyWith<$Res> {
|
||||
_$MenuUserEventCopyWithImpl(this._value, this._then);
|
||||
|
||||
final MenuUserEvent _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function(MenuUserEvent) _then;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$InitialCopyWith<$Res> {
|
||||
factory _$InitialCopyWith(_Initial value, $Res Function(_Initial) then) =
|
||||
__$InitialCopyWithImpl<$Res>;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$InitialCopyWithImpl<$Res> extends _$MenuUserEventCopyWithImpl<$Res>
|
||||
implements _$InitialCopyWith<$Res> {
|
||||
__$InitialCopyWithImpl(_Initial _value, $Res Function(_Initial) _then)
|
||||
: super(_value, (v) => _then(v as _Initial));
|
||||
|
||||
@override
|
||||
_Initial get _value => super._value as _Initial;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$_Initial implements _Initial {
|
||||
const _$_Initial();
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'MenuUserEvent.initial()';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(dynamic other) {
|
||||
return identical(this, other) || (other is _Initial);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => runtimeType.hashCode;
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function() initial,
|
||||
required TResult Function() fetchWorkspaces,
|
||||
}) {
|
||||
return initial();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function()? initial,
|
||||
TResult Function()? fetchWorkspaces,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (initial != null) {
|
||||
return initial();
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>({
|
||||
required TResult Function(_Initial value) initial,
|
||||
required TResult Function(_FetchWorkspaces value) fetchWorkspaces,
|
||||
}) {
|
||||
return initial(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>({
|
||||
TResult Function(_Initial value)? initial,
|
||||
TResult Function(_FetchWorkspaces value)? fetchWorkspaces,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (initial != null) {
|
||||
return initial(this);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _Initial implements MenuUserEvent {
|
||||
const factory _Initial() = _$_Initial;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$FetchWorkspacesCopyWith<$Res> {
|
||||
factory _$FetchWorkspacesCopyWith(
|
||||
_FetchWorkspaces value, $Res Function(_FetchWorkspaces) then) =
|
||||
__$FetchWorkspacesCopyWithImpl<$Res>;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$FetchWorkspacesCopyWithImpl<$Res>
|
||||
extends _$MenuUserEventCopyWithImpl<$Res>
|
||||
implements _$FetchWorkspacesCopyWith<$Res> {
|
||||
__$FetchWorkspacesCopyWithImpl(
|
||||
_FetchWorkspaces _value, $Res Function(_FetchWorkspaces) _then)
|
||||
: super(_value, (v) => _then(v as _FetchWorkspaces));
|
||||
|
||||
@override
|
||||
_FetchWorkspaces get _value => super._value as _FetchWorkspaces;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$_FetchWorkspaces implements _FetchWorkspaces {
|
||||
const _$_FetchWorkspaces();
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'MenuUserEvent.fetchWorkspaces()';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(dynamic other) {
|
||||
return identical(this, other) || (other is _FetchWorkspaces);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => runtimeType.hashCode;
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function() initial,
|
||||
required TResult Function() fetchWorkspaces,
|
||||
}) {
|
||||
return fetchWorkspaces();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function()? initial,
|
||||
TResult Function()? fetchWorkspaces,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (fetchWorkspaces != null) {
|
||||
return fetchWorkspaces();
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>({
|
||||
required TResult Function(_Initial value) initial,
|
||||
required TResult Function(_FetchWorkspaces value) fetchWorkspaces,
|
||||
}) {
|
||||
return fetchWorkspaces(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>({
|
||||
TResult Function(_Initial value)? initial,
|
||||
TResult Function(_FetchWorkspaces value)? fetchWorkspaces,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (fetchWorkspaces != null) {
|
||||
return fetchWorkspaces(this);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _FetchWorkspaces implements MenuUserEvent {
|
||||
const factory _FetchWorkspaces() = _$_FetchWorkspaces;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$MenuUserStateTearOff {
|
||||
const _$MenuUserStateTearOff();
|
||||
|
||||
_MenuUserState call(
|
||||
{required UserDetail user,
|
||||
required Option<List<Workspace>> workspaces,
|
||||
required Either<Unit, String> successOrFailure}) {
|
||||
return _MenuUserState(
|
||||
user: user,
|
||||
workspaces: workspaces,
|
||||
successOrFailure: successOrFailure,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
const $MenuUserState = _$MenuUserStateTearOff();
|
||||
|
||||
/// @nodoc
|
||||
mixin _$MenuUserState {
|
||||
UserDetail get user => throw _privateConstructorUsedError;
|
||||
Option<List<Workspace>> get workspaces => throw _privateConstructorUsedError;
|
||||
Either<Unit, String> get successOrFailure =>
|
||||
throw _privateConstructorUsedError;
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
$MenuUserStateCopyWith<MenuUserState> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $MenuUserStateCopyWith<$Res> {
|
||||
factory $MenuUserStateCopyWith(
|
||||
MenuUserState value, $Res Function(MenuUserState) then) =
|
||||
_$MenuUserStateCopyWithImpl<$Res>;
|
||||
$Res call(
|
||||
{UserDetail user,
|
||||
Option<List<Workspace>> workspaces,
|
||||
Either<Unit, String> successOrFailure});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$MenuUserStateCopyWithImpl<$Res>
|
||||
implements $MenuUserStateCopyWith<$Res> {
|
||||
_$MenuUserStateCopyWithImpl(this._value, this._then);
|
||||
|
||||
final MenuUserState _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function(MenuUserState) _then;
|
||||
|
||||
@override
|
||||
$Res call({
|
||||
Object? user = freezed,
|
||||
Object? workspaces = freezed,
|
||||
Object? successOrFailure = freezed,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
user: user == freezed
|
||||
? _value.user
|
||||
: user // ignore: cast_nullable_to_non_nullable
|
||||
as UserDetail,
|
||||
workspaces: workspaces == freezed
|
||||
? _value.workspaces
|
||||
: workspaces // ignore: cast_nullable_to_non_nullable
|
||||
as Option<List<Workspace>>,
|
||||
successOrFailure: successOrFailure == freezed
|
||||
? _value.successOrFailure
|
||||
: successOrFailure // ignore: cast_nullable_to_non_nullable
|
||||
as Either<Unit, String>,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$MenuUserStateCopyWith<$Res>
|
||||
implements $MenuUserStateCopyWith<$Res> {
|
||||
factory _$MenuUserStateCopyWith(
|
||||
_MenuUserState value, $Res Function(_MenuUserState) then) =
|
||||
__$MenuUserStateCopyWithImpl<$Res>;
|
||||
@override
|
||||
$Res call(
|
||||
{UserDetail user,
|
||||
Option<List<Workspace>> workspaces,
|
||||
Either<Unit, String> successOrFailure});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$MenuUserStateCopyWithImpl<$Res>
|
||||
extends _$MenuUserStateCopyWithImpl<$Res>
|
||||
implements _$MenuUserStateCopyWith<$Res> {
|
||||
__$MenuUserStateCopyWithImpl(
|
||||
_MenuUserState _value, $Res Function(_MenuUserState) _then)
|
||||
: super(_value, (v) => _then(v as _MenuUserState));
|
||||
|
||||
@override
|
||||
_MenuUserState get _value => super._value as _MenuUserState;
|
||||
|
||||
@override
|
||||
$Res call({
|
||||
Object? user = freezed,
|
||||
Object? workspaces = freezed,
|
||||
Object? successOrFailure = freezed,
|
||||
}) {
|
||||
return _then(_MenuUserState(
|
||||
user: user == freezed
|
||||
? _value.user
|
||||
: user // ignore: cast_nullable_to_non_nullable
|
||||
as UserDetail,
|
||||
workspaces: workspaces == freezed
|
||||
? _value.workspaces
|
||||
: workspaces // ignore: cast_nullable_to_non_nullable
|
||||
as Option<List<Workspace>>,
|
||||
successOrFailure: successOrFailure == freezed
|
||||
? _value.successOrFailure
|
||||
: successOrFailure // ignore: cast_nullable_to_non_nullable
|
||||
as Either<Unit, String>,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$_MenuUserState implements _MenuUserState {
|
||||
const _$_MenuUserState(
|
||||
{required this.user,
|
||||
required this.workspaces,
|
||||
required this.successOrFailure});
|
||||
|
||||
@override
|
||||
final UserDetail user;
|
||||
@override
|
||||
final Option<List<Workspace>> workspaces;
|
||||
@override
|
||||
final Either<Unit, String> successOrFailure;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'MenuUserState(user: $user, workspaces: $workspaces, successOrFailure: $successOrFailure)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(dynamic other) {
|
||||
return identical(this, other) ||
|
||||
(other is _MenuUserState &&
|
||||
(identical(other.user, user) ||
|
||||
const DeepCollectionEquality().equals(other.user, user)) &&
|
||||
(identical(other.workspaces, workspaces) ||
|
||||
const DeepCollectionEquality()
|
||||
.equals(other.workspaces, workspaces)) &&
|
||||
(identical(other.successOrFailure, successOrFailure) ||
|
||||
const DeepCollectionEquality()
|
||||
.equals(other.successOrFailure, successOrFailure)));
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
runtimeType.hashCode ^
|
||||
const DeepCollectionEquality().hash(user) ^
|
||||
const DeepCollectionEquality().hash(workspaces) ^
|
||||
const DeepCollectionEquality().hash(successOrFailure);
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
_$MenuUserStateCopyWith<_MenuUserState> get copyWith =>
|
||||
__$MenuUserStateCopyWithImpl<_MenuUserState>(this, _$identity);
|
||||
}
|
||||
|
||||
abstract class _MenuUserState implements MenuUserState {
|
||||
const factory _MenuUserState(
|
||||
{required UserDetail user,
|
||||
required Option<List<Workspace>> workspaces,
|
||||
required Either<Unit, String> successOrFailure}) = _$_MenuUserState;
|
||||
|
||||
@override
|
||||
UserDetail get user => throw _privateConstructorUsedError;
|
||||
@override
|
||||
Option<List<Workspace>> get workspaces => throw _privateConstructorUsedError;
|
||||
@override
|
||||
Either<Unit, String> get successOrFailure =>
|
||||
throw _privateConstructorUsedError;
|
||||
@override
|
||||
@JsonKey(ignore: true)
|
||||
_$MenuUserStateCopyWith<_MenuUserState> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
18
app_flowy/lib/workspace/domain/i_user.dart
Normal file
18
app_flowy/lib/workspace/domain/i_user.dart
Normal file
@ -0,0 +1,18 @@
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-user/errors.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-user/user_detail.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace/workspace_create.pb.dart';
|
||||
|
||||
export 'package:flowy_sdk/protobuf/flowy-workspace/workspace_create.pb.dart';
|
||||
export 'package:flowy_sdk/protobuf/flowy-user/errors.pb.dart';
|
||||
export 'package:flowy_sdk/protobuf/flowy-user/user_detail.pb.dart';
|
||||
export 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart';
|
||||
|
||||
abstract class IUser {
|
||||
UserDetail get user;
|
||||
Future<Either<UserDetail, UserError>> fetchUserDetail(String userId);
|
||||
Future<Either<List<Workspace>, WorkspaceError>> fetchWorkspaces();
|
||||
Future<Either<Unit, WorkspaceError>> deleteWorkspace(String workspaceId);
|
||||
Future<Either<Unit, UserError>> signOut();
|
||||
}
|
16
app_flowy/lib/workspace/domain/image.dart
Normal file
16
app_flowy/lib/workspace/domain/image.dart
Normal file
@ -0,0 +1,16 @@
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace/view_create.pb.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
AssetImage assetImageForViewType(ViewType type) {
|
||||
final imageName = imageNameForViewType(type);
|
||||
return AssetImage('assets/images/$imageName');
|
||||
}
|
||||
|
||||
String imageNameForViewType(ViewType type) {
|
||||
switch (type) {
|
||||
case ViewType.Doc:
|
||||
return "file_icon.jpg";
|
||||
default:
|
||||
return "file_icon.jpg";
|
||||
}
|
||||
}
|
@ -23,7 +23,8 @@ class HomePageStack {
|
||||
}
|
||||
|
||||
void setStackView(HomeStackView? stackView) {
|
||||
_bloc.add(PageStackEvent.setStackView(stackView ?? const BlankStackView()));
|
||||
_bloc.add(PageStackEvent.setStackView(
|
||||
stackView ?? const AnnouncementStackView()));
|
||||
}
|
||||
|
||||
Widget stackTopBar() {
|
||||
@ -32,7 +33,7 @@ class HomePageStack {
|
||||
child: BlocBuilder<PageStackBloc, PageStackState>(
|
||||
builder: (context, state) {
|
||||
return HomeTopBar(
|
||||
title: state.stackView.title,
|
||||
view: state.stackView,
|
||||
);
|
||||
},
|
||||
),
|
||||
@ -61,14 +62,17 @@ List<Widget> _buildStackWidget(HomeStackView stackView) {
|
||||
if (viewType == stackView.type) {
|
||||
switch (stackView.type) {
|
||||
case ViewType.Blank:
|
||||
return BlankPage(stackView: stackView as BlankStackView);
|
||||
return AnnouncementPage(
|
||||
stackView: stackView as AnnouncementStackView);
|
||||
case ViewType.Doc:
|
||||
return DocPage(stackView: stackView as DocPageStackView);
|
||||
final docView = stackView as DocPageStackView;
|
||||
return DocPage(key: ValueKey(docView.view.id), stackView: docView);
|
||||
default:
|
||||
return BlankPage(stackView: stackView as BlankStackView);
|
||||
return AnnouncementPage(
|
||||
stackView: stackView as AnnouncementStackView);
|
||||
}
|
||||
} else {
|
||||
return const BlankPage(stackView: BlankStackView());
|
||||
return const AnnouncementPage(stackView: AnnouncementStackView());
|
||||
}
|
||||
}).toList();
|
||||
}
|
||||
@ -76,11 +80,11 @@ List<Widget> _buildStackWidget(HomeStackView stackView) {
|
||||
HomeStackView stackViewFromView(View view) {
|
||||
switch (view.viewType) {
|
||||
case ViewType.Blank:
|
||||
return const BlankStackView();
|
||||
return const AnnouncementStackView();
|
||||
case ViewType.Doc:
|
||||
return DocPageStackView(view);
|
||||
default:
|
||||
return const BlankStackView();
|
||||
return const AnnouncementStackView();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,6 @@ abstract class PageStackState implements _$PageStackState {
|
||||
}) = _PageStackState;
|
||||
|
||||
factory PageStackState.initial() => const PageStackState(
|
||||
stackView: BlankStackView(),
|
||||
stackView: AnnouncementStackView(),
|
||||
);
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ import 'package:app_flowy/workspace/application/app/app_bloc.dart';
|
||||
import 'package:app_flowy/workspace/application/app/app_watch_bloc.dart';
|
||||
import 'package:app_flowy/workspace/application/doc/doc_bloc.dart';
|
||||
import 'package:app_flowy/workspace/application/menu/menu_bloc.dart';
|
||||
import 'package:app_flowy/workspace/application/menu/menu_user_bloc.dart';
|
||||
import 'package:app_flowy/workspace/application/menu/menu_watch.dart';
|
||||
import 'package:app_flowy/workspace/application/view/doc_watch_bloc.dart';
|
||||
import 'package:app_flowy/workspace/application/view/view_bloc.dart';
|
||||
@ -15,8 +16,11 @@ import 'package:app_flowy/workspace/infrastructure/repos/app_repo.dart';
|
||||
import 'package:app_flowy/workspace/infrastructure/repos/doc_repo.dart';
|
||||
import 'package:app_flowy/workspace/infrastructure/repos/view_repo.dart';
|
||||
import 'package:app_flowy/workspace/infrastructure/repos/workspace_repo.dart';
|
||||
import 'package:flowy_editor/flowy_editor.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-user/user_detail.pb.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
|
||||
import 'i_user_impl.dart';
|
||||
import 'i_view_impl.dart';
|
||||
|
||||
class HomeDepsResolver {
|
||||
@ -31,10 +35,10 @@ class HomeDepsResolver {
|
||||
(appId, _) => IAppWatchImpl(repo: AppWatchRepository(appId: appId)));
|
||||
|
||||
//workspace
|
||||
getIt.registerFactoryParam<IWorkspace, String, void>((workspaceId, _) =>
|
||||
IWorkspaceImpl(repo: WorkspaceRepo(workspaceId: workspaceId)));
|
||||
getIt.registerFactoryParam<IWorkspaceWatch, String, void>((workspacId, _) =>
|
||||
IWorkspaceWatchImpl(repo: WorkspaceWatchRepo(workspaceId: workspacId)));
|
||||
getIt.registerFactoryParam<IWorkspace, UserDetail, void>(
|
||||
(user, _) => IWorkspaceImpl(repo: WorkspaceRepo(user: user)));
|
||||
getIt.registerFactoryParam<IWorkspaceWatch, UserDetail, void>(
|
||||
(user, _) => IWorkspaceWatchImpl(repo: WorkspaceWatchRepo(user: user)));
|
||||
|
||||
// View
|
||||
getIt.registerFactoryParam<IView, String, void>(
|
||||
@ -46,12 +50,20 @@ class HomeDepsResolver {
|
||||
getIt.registerFactoryParam<IDoc, String, void>(
|
||||
(docId, _) => IDocImpl(repo: DocRepository(docId: docId)));
|
||||
|
||||
//Bloc
|
||||
getIt.registerFactoryParam<MenuBloc, String, void>(
|
||||
(workspaceId, _) => MenuBloc(getIt<IWorkspace>(param1: workspaceId)));
|
||||
getIt.registerFactoryParam<MenuWatchBloc, String, void>((workspaceId, _) =>
|
||||
MenuWatchBloc(getIt<IWorkspaceWatch>(param1: workspaceId)));
|
||||
// User
|
||||
getIt.registerFactoryParam<IUser, UserDetail, void>(
|
||||
(user, _) => IUserImpl(repo: UserRepo(user: user)));
|
||||
|
||||
//Menu Bloc
|
||||
getIt.registerFactoryParam<MenuBloc, UserDetail, void>(
|
||||
(user, _) => MenuBloc(getIt<IWorkspace>(param1: user)));
|
||||
getIt.registerFactoryParam<MenuWatchBloc, UserDetail, void>(
|
||||
(user, _) => MenuWatchBloc(getIt<IWorkspaceWatch>(param1: user)));
|
||||
|
||||
getIt.registerFactoryParam<MenuUserBloc, UserDetail, void>(
|
||||
(user, _) => MenuUserBloc(getIt<IUser>(param1: user)));
|
||||
|
||||
//
|
||||
getIt.registerFactoryParam<AppBloc, String, void>(
|
||||
(appId, _) => AppBloc(getIt<IApp>(param1: appId)));
|
||||
getIt.registerFactoryParam<AppWatchBloc, String, void>(
|
||||
@ -66,6 +78,9 @@ class HomeDepsResolver {
|
||||
getIt.registerFactoryParam<DocBloc, String, void>(
|
||||
(docId, _) => DocBloc(getIt<IDoc>(param1: docId)));
|
||||
|
||||
// editor
|
||||
getIt.registerFactoryParam<EditorPersistence, String, void>(
|
||||
(docId, _) => EditorPersistenceImpl(repo: DocRepository(docId: docId)));
|
||||
// getIt.registerFactoryParam<ViewBloc, String, void>(
|
||||
// (viewId, _) => ViewBloc(iViewImpl: getIt<IView>(param1: viewId)));
|
||||
}
|
||||
|
@ -35,8 +35,7 @@ class IAppImpl extends IApp {
|
||||
final result = await docRepo.createDoc(
|
||||
name: view.name, desc: "", text: "[{\"insert\":\"\\n\"}]");
|
||||
return result.fold((l) => left(view), (r) {
|
||||
return right(
|
||||
WorkspaceError(code: WorkspaceErrorCode.Unknown, msg: r.msg));
|
||||
return right(WorkspaceError(code: WsErrCode.Unknown, msg: r.msg));
|
||||
});
|
||||
default:
|
||||
return left(view);
|
||||
|
@ -1,10 +1,11 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:flowy_editor/flowy_editor.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-editor/errors.pb.dart';
|
||||
|
||||
import 'package:app_flowy/workspace/domain/i_doc.dart';
|
||||
import 'package:app_flowy/workspace/infrastructure/repos/doc_repo.dart';
|
||||
import 'package:flowy_editor/flowy_editor.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-editor/errors.pb.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
|
||||
class IDocImpl extends IDoc {
|
||||
DocRepository repo;
|
||||
@ -49,3 +50,21 @@ class IDocImpl extends IDoc {
|
||||
return document;
|
||||
}
|
||||
}
|
||||
|
||||
class EditorPersistenceImpl extends EditorPersistence {
|
||||
DocRepository repo;
|
||||
EditorPersistenceImpl({
|
||||
required this.repo,
|
||||
});
|
||||
|
||||
@override
|
||||
Future<bool> save(List<dynamic> jsonList) async {
|
||||
final json = jsonEncode(jsonList);
|
||||
return repo.updateDoc(text: json).then((result) {
|
||||
return result.fold(
|
||||
(l) => true,
|
||||
(r) => false,
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
36
app_flowy/lib/workspace/infrastructure/i_user_impl.dart
Normal file
36
app_flowy/lib/workspace/infrastructure/i_user_impl.dart
Normal file
@ -0,0 +1,36 @@
|
||||
import 'package:dartz/dartz.dart';
|
||||
|
||||
import 'package:app_flowy/workspace/domain/i_user.dart';
|
||||
import 'package:app_flowy/workspace/infrastructure/repos/user_repo.dart';
|
||||
export 'package:app_flowy/workspace/domain/i_user.dart';
|
||||
export 'package:app_flowy/workspace/infrastructure/repos/user_repo.dart';
|
||||
|
||||
class IUserImpl extends IUser {
|
||||
UserRepo repo;
|
||||
IUserImpl({
|
||||
required this.repo,
|
||||
});
|
||||
|
||||
@override
|
||||
Future<Either<Unit, WorkspaceError>> deleteWorkspace(String workspaceId) {
|
||||
return repo.deleteWorkspace(workspaceId: workspaceId);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Either<UserDetail, UserError>> fetchUserDetail(String userId) {
|
||||
return repo.fetchUserDetail(userId: userId);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Either<Unit, UserError>> signOut() {
|
||||
return repo.signOut();
|
||||
}
|
||||
|
||||
@override
|
||||
UserDetail get user => repo.user;
|
||||
|
||||
@override
|
||||
Future<Either<List<Workspace>, WorkspaceError>> fetchWorkspaces() {
|
||||
return repo.fetchWorkspaces();
|
||||
}
|
||||
}
|
36
app_flowy/lib/workspace/infrastructure/repos/user_repo.dart
Normal file
36
app_flowy/lib/workspace/infrastructure/repos/user_repo.dart
Normal file
@ -0,0 +1,36 @@
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:flowy_sdk/dispatch/dispatch.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-user/errors.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-user/user_detail.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace/workspace_create.pb.dart';
|
||||
|
||||
class UserRepo {
|
||||
final UserDetail user;
|
||||
UserRepo({
|
||||
required this.user,
|
||||
});
|
||||
|
||||
Future<Either<UserDetail, UserError>> fetchUserDetail(
|
||||
{required String userId}) {
|
||||
return UserEventGetStatus().send();
|
||||
}
|
||||
|
||||
Future<Either<Unit, WorkspaceError>> deleteWorkspace(
|
||||
{required String workspaceId}) {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
Future<Either<Unit, UserError>> signOut() {
|
||||
return UserEventSignOut().send();
|
||||
}
|
||||
|
||||
Future<Either<List<Workspace>, WorkspaceError>> fetchWorkspaces() {
|
||||
return WorkspaceEventReadAllWorkspace().send().then((result) {
|
||||
return result.fold(
|
||||
(workspaces) => left(workspaces.items),
|
||||
(r) => right(r),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
@ -5,6 +5,7 @@ import 'package:dartz/dartz.dart';
|
||||
import 'package:flowy_infra/flowy_logger.dart';
|
||||
import 'package:flowy_sdk/dispatch/dispatch.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-observable/subject.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-user/user_detail.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace/app_create.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace/observable.pb.dart';
|
||||
@ -13,9 +14,9 @@ import 'package:flowy_sdk/protobuf/flowy-workspace/workspace_query.pb.dart';
|
||||
import 'package:flowy_sdk/rust_stream.dart';
|
||||
|
||||
class WorkspaceRepo {
|
||||
String workspaceId;
|
||||
UserDetail user;
|
||||
WorkspaceRepo({
|
||||
required this.workspaceId,
|
||||
required this.user,
|
||||
});
|
||||
|
||||
Future<Either<App, WorkspaceError>> createApp(String appName, String desc) {
|
||||
@ -38,7 +39,7 @@ class WorkspaceRepo {
|
||||
Future<Either<Workspace, WorkspaceError>> getWorkspace(
|
||||
{bool readApps = false}) {
|
||||
final request = QueryWorkspaceRequest.create()
|
||||
..workspaceId = workspaceId
|
||||
..workspaceId = user.workspace
|
||||
..readApps = readApps;
|
||||
|
||||
return WorkspaceEventGetWorkspace(request).send().then((result) {
|
||||
@ -54,13 +55,13 @@ class WorkspaceWatchRepo {
|
||||
StreamSubscription<ObservableSubject>? _subscription;
|
||||
WorkspaceAddAppCallback? _addAppCallback;
|
||||
WorkspaceUpdatedCallback? _updatedCallback;
|
||||
final String workspaceId;
|
||||
final UserDetail user;
|
||||
late WorkspaceRepo _repo;
|
||||
|
||||
WorkspaceWatchRepo({
|
||||
required this.workspaceId,
|
||||
required this.user,
|
||||
}) {
|
||||
_repo = WorkspaceRepo(workspaceId: workspaceId);
|
||||
_repo = WorkspaceRepo(user: user);
|
||||
}
|
||||
|
||||
void startWatching(
|
||||
@ -70,7 +71,7 @@ class WorkspaceWatchRepo {
|
||||
_updatedCallback = updatedCallback;
|
||||
|
||||
_subscription = RustStreamReceiver.listen((observable) {
|
||||
if (observable.subjectId != workspaceId) {
|
||||
if (observable.subjectId != user.workspace) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1,20 +1,32 @@
|
||||
import 'package:app_flowy/workspace/application/app/app_bloc.dart';
|
||||
import 'package:app_flowy/workspace/application/app/app_watch_bloc.dart';
|
||||
import 'package:app_flowy/workspace/presentation/app/view_list.dart';
|
||||
import 'package:app_flowy/workspace/presentation/widgets/menu/menu_size.dart';
|
||||
import 'package:app_flowy/workspace/presentation/widgets/menu/menu_list.dart';
|
||||
import 'package:app_flowy/startup/startup.dart';
|
||||
import 'package:expandable/expandable.dart';
|
||||
import 'package:flowy_infra/size.dart';
|
||||
import 'package:flowy_infra_ui/widget/error_page.dart';
|
||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/styled_text_button.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/styled_icon_button.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:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
|
||||
class AppWidget extends StatelessWidget {
|
||||
class AppWidgetSize {
|
||||
static double expandedIconSize = 24;
|
||||
static double expandedIconRightSpace = 8;
|
||||
|
||||
static double scale = 1;
|
||||
|
||||
static double get expandedPadding =>
|
||||
expandedIconSize * scale + expandedIconRightSpace;
|
||||
}
|
||||
|
||||
class AppWidget extends MenuItem {
|
||||
final App app;
|
||||
const AppWidget(this.app, {Key? key}) : super(key: key);
|
||||
AppWidget(this.app, {Key? key}) : super(key: ValueKey(app.id));
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@ -35,11 +47,9 @@ class AppWidget extends StatelessWidget {
|
||||
builder: (context, state) {
|
||||
final child = state.map(
|
||||
initial: (_) => BlocBuilder<AppBloc, AppState>(
|
||||
builder: (context, state) {
|
||||
return ViewList(state.views);
|
||||
},
|
||||
builder: (context, state) => _renderViewList(state.views),
|
||||
),
|
||||
loadViews: (s) => ViewList(some(s.views)),
|
||||
loadViews: (s) => _renderViewList(some(s.views)),
|
||||
loadFail: (s) => FlowyErrorPage(s.error.toString()),
|
||||
);
|
||||
|
||||
@ -54,31 +64,36 @@ class AppWidget extends StatelessWidget {
|
||||
child: ScrollOnExpand(
|
||||
scrollOnExpand: true,
|
||||
scrollOnCollapse: false,
|
||||
child: Card(
|
||||
clipBehavior: Clip.antiAlias,
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
ExpandablePanel(
|
||||
theme: const ExpandableThemeData(
|
||||
headerAlignment: ExpandablePanelHeaderAlignment.center,
|
||||
tapBodyToExpand: false,
|
||||
tapBodyToCollapse: false,
|
||||
iconPadding: EdgeInsets.zero,
|
||||
hasIcon: false,
|
||||
),
|
||||
header: AppHeader(app),
|
||||
expanded: Padding(
|
||||
padding: EdgeInsets.only(left: Sizes.iconMed),
|
||||
child: child,
|
||||
),
|
||||
collapsed: const SizedBox(),
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
ExpandablePanel(
|
||||
theme: const ExpandableThemeData(
|
||||
headerAlignment: ExpandablePanelHeaderAlignment.center,
|
||||
tapBodyToExpand: false,
|
||||
tapBodyToCollapse: false,
|
||||
tapHeaderToExpand: false,
|
||||
iconPadding: EdgeInsets.zero,
|
||||
hasIcon: false,
|
||||
),
|
||||
],
|
||||
),
|
||||
header: AppHeader(app),
|
||||
expanded: child,
|
||||
collapsed: const SizedBox(),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _renderViewList(Option<List<View>> views) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||
child: ViewList(views),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
MenuItemType get type => MenuItemType.app;
|
||||
}
|
||||
|
||||
class AppHeader extends StatelessWidget {
|
||||
@ -90,46 +105,53 @@ class AppHeader extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
color: Colors.white,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: Insets.m),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
ExpandableIcon(
|
||||
theme: ExpandableThemeData(
|
||||
expandIcon: Icons.arrow_right,
|
||||
collapseIcon: Icons.arrow_drop_down,
|
||||
iconColor: Colors.black,
|
||||
iconSize: HomeMenuSize.collapseIconSize,
|
||||
iconPadding: EdgeInsets.zero,
|
||||
hasIcon: false,
|
||||
),
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
InkWell(
|
||||
onTap: () {
|
||||
ExpandableController.of(context,
|
||||
rebuildOnChange: false, required: true)
|
||||
?.toggle();
|
||||
},
|
||||
child: ExpandableIcon(
|
||||
theme: ExpandableThemeData(
|
||||
expandIcon: Icons.arrow_drop_up,
|
||||
collapseIcon: Icons.arrow_drop_down,
|
||||
iconColor: Colors.black,
|
||||
iconSize: AppWidgetSize.expandedIconSize,
|
||||
iconPadding: EdgeInsets.zero,
|
||||
hasIcon: false,
|
||||
),
|
||||
Expanded(
|
||||
child: Text(app.name),
|
||||
),
|
||||
SizedBox(
|
||||
height: HomeMenuSize.createViewButtonSize,
|
||||
child: createViewPopupMenu(context),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
HSpace(AppWidgetSize.expandedIconRightSpace),
|
||||
Expanded(
|
||||
child: StyledTextButton(
|
||||
app.name,
|
||||
onPressed: () {
|
||||
debugPrint('show app document');
|
||||
},
|
||||
),
|
||||
),
|
||||
StyledIconButton(
|
||||
icon: const Icon(Icons.add),
|
||||
onPressed: () {
|
||||
debugPrint('add view');
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget createViewPopupMenu(BuildContext context) {
|
||||
return PopupMenuButton(
|
||||
iconSize: 24,
|
||||
tooltip: 'create new view',
|
||||
icon: const Icon(Icons.add),
|
||||
padding: EdgeInsets.zero,
|
||||
onSelected: (viewType) => _createView(viewType as ViewType, context),
|
||||
itemBuilder: (context) => menuItemBuilder());
|
||||
}
|
||||
// return PopupMenuButton(
|
||||
// iconSize: 20,
|
||||
// tooltip: 'create new view',
|
||||
// icon: const Icon(Icons.add),
|
||||
// padding: EdgeInsets.zero,
|
||||
// onSelected: (viewType) => _createView(viewType as ViewType, context),
|
||||
// itemBuilder: (context) => menuItemBuilder());
|
||||
|
||||
List<PopupMenuEntry> menuItemBuilder() {
|
||||
return ViewType.values
|
||||
|
@ -1,11 +1,9 @@
|
||||
import 'package:app_flowy/workspace/presentation/view/view_widget.dart';
|
||||
import 'package:flowy_infra/flowy_logger.dart';
|
||||
import 'package:flowy_infra/size.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace/view_create.pb.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:styled_widget/styled_widget.dart';
|
||||
|
||||
class ViewList extends StatelessWidget {
|
||||
final Option<List<View>> views;
|
||||
@ -15,24 +13,24 @@ class ViewList extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
Log.info('ViewList build');
|
||||
return views.fold(
|
||||
() => const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
() => const SizedBox(),
|
||||
(views) {
|
||||
return Column(
|
||||
children: buildViewWidgets(views),
|
||||
).padding(vertical: Insets.sm);
|
||||
children: _renderViews(views),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
List<ViewWidget> buildViewWidgets(List<View> views) {
|
||||
List<Widget> _renderViews(List<View> views) {
|
||||
var targetViews = views.map((view) {
|
||||
return ViewWidget(
|
||||
icon: const Icon(Icons.file_copy),
|
||||
view: view,
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 2),
|
||||
child: ViewWidget(
|
||||
view: view,
|
||||
),
|
||||
);
|
||||
}).toList(growable: true);
|
||||
}).toList(growable: false);
|
||||
return targetViews;
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,7 @@ import 'package:flowy_infra_ui/widget/error_page.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace/view_create.pb.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/styled_progress_indicator.dart';
|
||||
|
||||
class DocPage extends HomeStackWidget {
|
||||
const DocPage({Key? key, required DocPageStackView stackView})
|
||||
@ -29,13 +30,28 @@ class _DocPageState extends State<DocPage> {
|
||||
BlocBuilder<DocWatchBloc, DocWatchState>(builder: (context, state) {
|
||||
assert(widget.stackView is DocPageStackView);
|
||||
return state.map(
|
||||
loading: (_) => const CircularProgressIndicator.adaptive(),
|
||||
loading: (_) => const StyledProgressIndicator(),
|
||||
loadDoc: (s) => EditorWdiget(doc: s.doc),
|
||||
loadFail: (s) => FlowyErrorPage(s.error.toString()),
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void deactivate() {
|
||||
super.deactivate();
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(covariant DocPage oldWidget) {
|
||||
super.didUpdateWidget(oldWidget);
|
||||
}
|
||||
}
|
||||
|
||||
class DocPageStackView extends HomeStackView {
|
||||
|
@ -16,6 +16,7 @@ class EditorWdiget extends StatelessWidget {
|
||||
controller = EditorController(
|
||||
document: doc.data,
|
||||
selection: const TextSelection.collapsed(offset: 0),
|
||||
persistence: getIt<EditorPersistence>(param1: doc.info.id),
|
||||
);
|
||||
}
|
||||
|
||||
@ -23,12 +24,16 @@ class EditorWdiget extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
return BlocProvider(
|
||||
create: (context) => getIt<DocBloc>(param1: doc.info.id),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
_renderEditor(controller),
|
||||
_renderToolbar(controller),
|
||||
],
|
||||
child: BlocBuilder<DocBloc, DocState>(
|
||||
builder: (ctx, state) {
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
_renderEditor(controller),
|
||||
_renderToolbar(controller),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
@ -45,7 +50,9 @@ class EditorWdiget extends StatelessWidget {
|
||||
scrollBottomInset: 0,
|
||||
scrollController: ScrollController(),
|
||||
);
|
||||
return Expanded(child: editor);
|
||||
return Expanded(
|
||||
child: Padding(padding: const EdgeInsets.all(10), child: editor),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _renderToolbar(EditorController controller) {
|
||||
|
@ -23,7 +23,7 @@ class HomeLayout {
|
||||
|
||||
showEditPannel = homeBlocState.editContext.isSome();
|
||||
|
||||
menuWidth = Sizes.sideBarSm;
|
||||
menuWidth = Sizes.sideBarMed;
|
||||
if (context.widthPx >= PageBreaks.desktop) {
|
||||
menuWidth = Sizes.sideBarLg;
|
||||
}
|
||||
|
@ -14,8 +14,8 @@ import 'home_layout.dart';
|
||||
|
||||
class HomeScreen extends StatelessWidget {
|
||||
static GlobalKey<ScaffoldState> scaffoldKey = GlobalKey();
|
||||
final UserDetail userDetail;
|
||||
const HomeScreen(this.userDetail, {Key? key}) : super(key: key);
|
||||
final UserDetail user;
|
||||
const HomeScreen(this.user, {Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@ -31,7 +31,8 @@ class HomeScreen extends StatelessWidget {
|
||||
buildWhen: (previous, current) => previous != current,
|
||||
builder: (context, state) {
|
||||
return StyledContainer(
|
||||
Theme.of(context).colorScheme.background,
|
||||
Theme.of(context).colorScheme.surface,
|
||||
// Colors.white,
|
||||
child: _buildBody(
|
||||
state, context.read<HomeBloc>().state.forceCollapse),
|
||||
);
|
||||
@ -74,7 +75,7 @@ class HomeScreen extends StatelessWidget {
|
||||
isCollapseChanged: (isCollapse) {
|
||||
homeBloc.add(HomeEvent.forceCollapse(isCollapse));
|
||||
},
|
||||
workspaceId: userDetail.workspace,
|
||||
user: user,
|
||||
);
|
||||
homeMenu = RepaintBoundary(child: homeMenu);
|
||||
homeMenu = FocusTraversalGroup(child: homeMenu);
|
||||
|
@ -1,32 +1,67 @@
|
||||
import 'package:app_flowy/startup/startup.dart';
|
||||
import 'package:app_flowy/workspace/domain/image.dart';
|
||||
import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart';
|
||||
import 'package:app_flowy/workspace/presentation/app/app_widget.dart';
|
||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace/view_create.pb.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/styled_icon_button.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/styled_hover.dart';
|
||||
|
||||
class ViewWidget extends StatelessWidget {
|
||||
final View view;
|
||||
final Widget icon;
|
||||
const ViewWidget({Key? key, required this.view, required this.icon})
|
||||
: super(key: key);
|
||||
const ViewWidget({Key? key, required this.view}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return InkWell(onTap: _openView(context), child: buildContent());
|
||||
return InkWell(
|
||||
onTap: _openView(context),
|
||||
child: StyledHover(
|
||||
color: Colors.grey.shade300,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
builder: (context, onHover) => _render(context, onHover),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Row buildContent() {
|
||||
return Row(
|
||||
children: [
|
||||
icon,
|
||||
const SizedBox(
|
||||
width: 4,
|
||||
Widget _render(BuildContext context, bool onHover) {
|
||||
const double width = 20;
|
||||
List<Widget> children = [
|
||||
Image(
|
||||
fit: BoxFit.cover,
|
||||
width: width,
|
||||
height: width,
|
||||
image: assetImageForViewType(view.viewType)),
|
||||
const HSpace(6),
|
||||
Text(
|
||||
view.name,
|
||||
textAlign: TextAlign.start,
|
||||
style: const TextStyle(fontSize: 15),
|
||||
),
|
||||
];
|
||||
|
||||
if (onHover) {
|
||||
children.add(const Spacer());
|
||||
|
||||
children.add(Align(
|
||||
alignment: Alignment.center,
|
||||
child: StyledMore(
|
||||
width: width,
|
||||
onPressed: () {},
|
||||
),
|
||||
Text(
|
||||
view.name,
|
||||
textAlign: TextAlign.start,
|
||||
style: const TextStyle(fontSize: 15),
|
||||
)
|
||||
],
|
||||
));
|
||||
}
|
||||
|
||||
final padding = EdgeInsets.only(
|
||||
left: AppWidgetSize.expandedPadding,
|
||||
top: 5,
|
||||
bottom: 5,
|
||||
right: 5,
|
||||
);
|
||||
|
||||
return Padding(
|
||||
padding: padding,
|
||||
child: Row(children: children),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -2,30 +2,30 @@ import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace/view_create.pb.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class BlankStackView extends HomeStackView {
|
||||
const BlankStackView() : super(type: ViewType.Blank, title: 'Blank');
|
||||
class AnnouncementStackView extends HomeStackView {
|
||||
const AnnouncementStackView() : super(type: ViewType.Blank, title: 'Blank');
|
||||
|
||||
@override
|
||||
List<Object> get props => [];
|
||||
}
|
||||
|
||||
class BlankPage extends HomeStackWidget {
|
||||
const BlankPage({Key? key, required BlankStackView stackView})
|
||||
class AnnouncementPage extends HomeStackWidget {
|
||||
const AnnouncementPage({Key? key, required AnnouncementStackView stackView})
|
||||
: super(key: key, stackView: stackView);
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _BlankPageState();
|
||||
State<StatefulWidget> createState() => _AnnouncementPage();
|
||||
}
|
||||
|
||||
class _BlankPageState extends State<BlankPage> {
|
||||
class _AnnouncementPage extends State<AnnouncementPage> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
child: const Center(
|
||||
child: Text(
|
||||
'Hello AppFlowy',
|
||||
style: TextStyle(fontSize: 60),
|
||||
return SizedBox.expand(
|
||||
child: Container(
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: Container(),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@ -1,49 +1,91 @@
|
||||
import 'package:app_flowy/workspace/domain/image.dart';
|
||||
import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart';
|
||||
import 'package:app_flowy/workspace/presentation/home/home_sizes.dart';
|
||||
import 'package:flowy_infra_ui/widget/rounded_button.dart';
|
||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace/view_create.pbenum.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/styled_icon_button.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/styled_text.dart';
|
||||
|
||||
class HomeTopBar extends StatelessWidget {
|
||||
final String title;
|
||||
const HomeTopBar({Key? key, required this.title}) : super(key: key);
|
||||
final HomeStackView view;
|
||||
const HomeTopBar({Key? key, required this.view}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: HomeInsets.topBarTitlePadding),
|
||||
return SizedBox(
|
||||
height: HomeSizes.topBarHeight,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
HomeTitle(title: title),
|
||||
],
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
border: Border(
|
||||
bottom: BorderSide(width: 0.5, color: Colors.grey.shade300),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding:
|
||||
EdgeInsets.symmetric(horizontal: HomeInsets.topBarTitlePadding),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
HomeTitle(title: view.title, type: view.type),
|
||||
const Spacer(),
|
||||
_renderShareButton(),
|
||||
_renderMoreButton(),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _renderShareButton() {
|
||||
return RoundedTextButton(
|
||||
title: 'Share',
|
||||
height: 30,
|
||||
width: 60,
|
||||
fontSize: 12,
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
color: Colors.lightBlue,
|
||||
press: () {
|
||||
debugPrint('share page');
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget _renderMoreButton() {
|
||||
return StyledMore(
|
||||
width: 24,
|
||||
onPressed: () {
|
||||
debugPrint('show more');
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class HomeTitle extends StatelessWidget {
|
||||
final String title;
|
||||
final _editingController = TextEditingController(
|
||||
text: '',
|
||||
);
|
||||
final ViewType type;
|
||||
|
||||
HomeTitle({
|
||||
const HomeTitle({
|
||||
Key? key,
|
||||
required this.title,
|
||||
required this.type,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
_editingController.text = title;
|
||||
|
||||
return Expanded(
|
||||
child: TextField(
|
||||
controller: _editingController,
|
||||
textAlign: TextAlign.left,
|
||||
style: const TextStyle(fontSize: 28.0),
|
||||
decoration: const InputDecoration(
|
||||
hintText: 'Name the view',
|
||||
border: UnderlineInputBorder(borderSide: BorderSide.none),
|
||||
),
|
||||
return Flexible(
|
||||
child: Row(
|
||||
children: [
|
||||
Image(
|
||||
fit: BoxFit.scaleDown,
|
||||
width: 15,
|
||||
height: 15,
|
||||
image: assetImageForViewType(type)),
|
||||
const HSpace(6),
|
||||
StyledText(title, fontSize: 16),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -1,29 +0,0 @@
|
||||
import 'package:app_flowy/workspace/presentation/app/app_widget.dart';
|
||||
import 'package:expandable/expandable.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace/app_create.pb.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
|
||||
class AppList extends StatelessWidget {
|
||||
final Option<List<App>> apps;
|
||||
const AppList({required this.apps, Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return apps.fold(() {
|
||||
return const Expanded(child: Text('You have no apps, create one?'));
|
||||
}, (apps) {
|
||||
return ExpandableTheme(
|
||||
data: const ExpandableThemeData(
|
||||
iconColor: Colors.blue,
|
||||
useInkWell: true,
|
||||
),
|
||||
child: Expanded(
|
||||
child: ListView(
|
||||
physics: const BouncingScrollPhysics(),
|
||||
children: apps.map((app) => AppWidget(app)).toList(),
|
||||
),
|
||||
));
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
import 'package:app_flowy/startup/tasks/application_task.dart';
|
||||
import 'package:flowy_infra/size.dart';
|
||||
import 'package:flowy_infra/text_style.dart';
|
||||
import 'package:flowy_infra/theme.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/styled_text_input.dart';
|
||||
import 'package:flowy_infra_ui/widget/buttons/ok_cancel_button.dart';
|
||||
import 'package:flowy_infra_ui/widget/dialog/dialog_context.dart';
|
||||
import 'package:flowy_infra_ui/widget/dialog/styled_dialogs.dart';
|
||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
// ignore: implementation_imports
|
||||
import 'package:provider/src/provider.dart';
|
||||
import 'package:textstyle_extensions/textstyle_extensions.dart';
|
||||
|
||||
// ignore: must_be_immutable
|
||||
class CreateAppDialogContext extends DialogContext {
|
||||
String appName;
|
||||
final Function(String)? confirm;
|
||||
|
||||
CreateAppDialogContext({this.appName = "", this.confirm})
|
||||
: super(identifier: 'CreateAppDialogContext');
|
||||
|
||||
@override
|
||||
Widget buildWiget(BuildContext context) {
|
||||
final theme = context.watch<AppTheme>();
|
||||
return StyledDialog(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
...[
|
||||
Text('Create App'.toUpperCase(),
|
||||
style: TextStyles.T1.textColor(theme.bg1)),
|
||||
VSpace(Insets.sm * 1.5),
|
||||
// Container(color: theme.greyWeak.withOpacity(.35), height: 1),
|
||||
VSpace(Insets.m * 1.5),
|
||||
],
|
||||
StyledFormTextInput(
|
||||
hintText: "App name",
|
||||
onChanged: (text) {
|
||||
appName = text;
|
||||
},
|
||||
),
|
||||
SizedBox(height: Insets.l),
|
||||
OkCancelButton(
|
||||
onOkPressed: () {
|
||||
if (confirm != null) {
|
||||
confirm!(appName);
|
||||
AppGlobals.nav.pop();
|
||||
}
|
||||
},
|
||||
onCancelPressed: () {
|
||||
AppGlobals.nav.pop();
|
||||
},
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
List<Object> get props => [identifier];
|
||||
|
||||
@override
|
||||
bool get barrierDismissable => false;
|
||||
}
|
@ -1,34 +1,34 @@
|
||||
import 'package:app_flowy/workspace/application/menu/menu_bloc.dart';
|
||||
import 'package:app_flowy/workspace/application/menu/menu_watch.dart';
|
||||
import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart';
|
||||
import 'package:app_flowy/startup/startup.dart';
|
||||
import 'package:app_flowy/startup/tasks/application_task.dart';
|
||||
import 'package:app_flowy/workspace/presentation/home/home_sizes.dart';
|
||||
import 'package:app_flowy/workspace/presentation/widgets/menu/menu_new_app.dart';
|
||||
import 'package:app_flowy/workspace/presentation/widgets/menu/menu_top_bar.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:flowy_infra/size.dart';
|
||||
import 'package:flowy_infra/text_style.dart';
|
||||
import 'package:flowy_infra/theme.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/styled_text_input.dart';
|
||||
import 'package:flowy_infra_ui/widget/buttons/ok_cancel_button.dart';
|
||||
import 'package:flowy_infra_ui/widget/dialog/styled_dialogs.dart';
|
||||
import 'package:flowy_infra_ui/widget/error_page.dart';
|
||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-user/user_detail.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace/app_create.pb.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:styled_widget/styled_widget.dart';
|
||||
import 'package:textstyle_extensions/textstyle_extensions.dart';
|
||||
import 'app_list.dart';
|
||||
|
||||
import 'package:app_flowy/startup/startup.dart';
|
||||
import 'package:app_flowy/workspace/application/menu/menu_bloc.dart';
|
||||
import 'package:app_flowy/workspace/application/menu/menu_watch.dart';
|
||||
import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart';
|
||||
import 'package:app_flowy/workspace/presentation/app/app_widget.dart';
|
||||
import 'package:app_flowy/workspace/presentation/home/home_sizes.dart';
|
||||
import 'package:app_flowy/workspace/presentation/widgets/menu/menu_user.dart';
|
||||
|
||||
import 'menu_list.dart';
|
||||
|
||||
class HomeMenu extends StatelessWidget {
|
||||
final Function(HomeStackView?) pageContextChanged;
|
||||
final Function(bool) isCollapseChanged;
|
||||
final String workspaceId;
|
||||
final UserDetail user;
|
||||
|
||||
const HomeMenu(
|
||||
{Key? key,
|
||||
required this.pageContextChanged,
|
||||
required this.isCollapseChanged,
|
||||
required this.workspaceId})
|
||||
required this.user})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
@ -36,10 +36,10 @@ class HomeMenu extends StatelessWidget {
|
||||
return MultiBlocProvider(
|
||||
providers: [
|
||||
BlocProvider<MenuBloc>(
|
||||
create: (context) => getIt<MenuBloc>(param1: workspaceId)
|
||||
..add(const MenuEvent.initial())),
|
||||
create: (context) =>
|
||||
getIt<MenuBloc>(param1: user)..add(const MenuEvent.initial())),
|
||||
BlocProvider(
|
||||
create: (context) => getIt<MenuWatchBloc>(param1: workspaceId)
|
||||
create: (context) => getIt<MenuWatchBloc>(param1: user)
|
||||
..add(const MenuWatchEvent.started())),
|
||||
],
|
||||
child: MultiBlocListener(
|
||||
@ -61,161 +61,82 @@ class HomeMenu extends StatelessWidget {
|
||||
}
|
||||
|
||||
Widget _renderBody(BuildContext context) {
|
||||
// nested cloumn: https://siddharthmolleti.com/flutter-box-constraints-nested-column-s-row-s-3dfacada7361
|
||||
return Container(
|
||||
color: Theme.of(context).colorScheme.primaryVariant,
|
||||
color: Theme.of(context).colorScheme.background,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
const MenuTopBar(),
|
||||
_renderAppList(context),
|
||||
_renderNewButton(context),
|
||||
Expanded(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
_renderTopBar(context),
|
||||
_renderMenuList(context),
|
||||
],
|
||||
).padding(horizontal: Insets.l),
|
||||
),
|
||||
_renderNewAppButton(context),
|
||||
],
|
||||
).padding(horizontal: Insets.sm),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _renderAppList(BuildContext context) {
|
||||
return BlocBuilder<MenuWatchBloc, MenuWatchState>(
|
||||
builder: (context, state) => state.map(
|
||||
initial: (_) => BlocBuilder<MenuBloc, MenuState>(
|
||||
builder: (context, state) {
|
||||
return AppList(apps: state.apps);
|
||||
},
|
||||
),
|
||||
loadApps: (s) => AppList(apps: some(s.apps)),
|
||||
loadFail: (s) => FlowyErrorPage(s.error.toString()),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _renderNewButton(BuildContext context) {
|
||||
return NewAppButton(
|
||||
createAppCallback: (appName) =>
|
||||
context.read<MenuBloc>().add(MenuEvent.createApp(appName, desc: "")),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class MenuTopBar extends StatelessWidget {
|
||||
const MenuTopBar({Key? key}) : super(key: key);
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocBuilder<MenuBloc, MenuState>(
|
||||
Widget _renderMenuList(BuildContext context) {
|
||||
return BlocBuilder<MenuWatchBloc, MenuWatchState>(
|
||||
builder: (context, state) {
|
||||
return SizedBox(
|
||||
height: HomeSizes.menuTopBarHeight,
|
||||
child: Row(
|
||||
children: [
|
||||
const Text(
|
||||
'AppFlowy',
|
||||
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20),
|
||||
).constrained(minWidth: 100),
|
||||
const Spacer(),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.arrow_left),
|
||||
onPressed: () =>
|
||||
context.read<MenuBloc>().add(const MenuEvent.collapse()),
|
||||
),
|
||||
],
|
||||
return state.map(
|
||||
initial: (_) => MenuList(
|
||||
menuItems: menuItemsWithApps(context.read<MenuBloc>().state.apps),
|
||||
),
|
||||
loadApps: (s) => MenuList(
|
||||
menuItems: menuItemsWithApps(some(s.apps)),
|
||||
),
|
||||
loadFail: (s) => FlowyErrorPage(s.error.toString()),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class NewAppButton extends StatelessWidget {
|
||||
final Function(String)? createAppCallback;
|
||||
Widget _renderNewAppButton(BuildContext context) {
|
||||
return NewAppButton(
|
||||
press: (appName) =>
|
||||
context.read<MenuBloc>().add(MenuEvent.createApp(appName, desc: "")),
|
||||
);
|
||||
}
|
||||
|
||||
const NewAppButton({this.createAppCallback, Key? key}) : super(key: key);
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Widget _renderTopBar(BuildContext context) {
|
||||
return SizedBox(
|
||||
height: HomeSizes.menuAddButtonHeight,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
const Icon(Icons.add),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () async => await _showCreateAppDialog(context),
|
||||
child: _buttonTitle(),
|
||||
)
|
||||
],
|
||||
),
|
||||
height: HomeSizes.menuTopBarHeight,
|
||||
child: const MenuTopBar(),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buttonTitle() {
|
||||
return const Text('New App',
|
||||
style: TextStyle(
|
||||
color: Colors.black,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 20,
|
||||
));
|
||||
}
|
||||
|
||||
Future<void> _showCreateAppDialog(BuildContext context) async {
|
||||
await Dialogs.showWithContext(CreateAppDialogContext(
|
||||
confirm: (appName) {
|
||||
if (appName.isNotEmpty && createAppCallback != null) {
|
||||
createAppCallback!(appName);
|
||||
}
|
||||
},
|
||||
), context);
|
||||
List<MenuItem> menuItemsWithApps(Option<List<App>> someApps) {
|
||||
return MenuItemBuilder().withUser(user).withApps(someApps).build();
|
||||
}
|
||||
}
|
||||
|
||||
//ignore: must_be_immutable
|
||||
class CreateAppDialogContext extends DialogContext {
|
||||
String appName;
|
||||
final Function(String)? confirm;
|
||||
class MenuItemBuilder {
|
||||
List<MenuItem> items = [];
|
||||
|
||||
CreateAppDialogContext({this.appName = "", this.confirm})
|
||||
: super(identifier: 'CreateAppDialogContext');
|
||||
MenuItemBuilder();
|
||||
|
||||
@override
|
||||
Widget buildWiget(BuildContext context) {
|
||||
final theme = context.watch<AppTheme>();
|
||||
return StyledDialog(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
...[
|
||||
Text('Create App'.toUpperCase(),
|
||||
style: TextStyles.T1.textColor(theme.accent1Darker)),
|
||||
VSpace(Insets.sm * 1.5),
|
||||
// Container(color: theme.greyWeak.withOpacity(.35), height: 1),
|
||||
VSpace(Insets.m * 1.5),
|
||||
],
|
||||
StyledFormTextInput(
|
||||
hintText: "App name",
|
||||
onChanged: (text) {
|
||||
appName = text;
|
||||
},
|
||||
),
|
||||
SizedBox(height: Insets.l),
|
||||
OkCancelButton(
|
||||
onOkPressed: () {
|
||||
if (confirm != null) {
|
||||
confirm!(appName);
|
||||
AppGlobals.nav.pop();
|
||||
}
|
||||
},
|
||||
onCancelPressed: () {
|
||||
AppGlobals.nav.pop();
|
||||
},
|
||||
)
|
||||
],
|
||||
),
|
||||
MenuItemBuilder withUser(UserDetail user) {
|
||||
items.add(MenuUser(user));
|
||||
return this;
|
||||
}
|
||||
|
||||
MenuItemBuilder withApps(Option<List<App>> someApps) {
|
||||
List<MenuItem> appWidgets = someApps.foldRight(
|
||||
[],
|
||||
(apps, _) => apps.map((app) => AppWidget(app)).toList(),
|
||||
);
|
||||
items.addAll(appWidgets);
|
||||
return this;
|
||||
}
|
||||
|
||||
@override
|
||||
List<Object> get props => [identifier];
|
||||
|
||||
@override
|
||||
bool get barrierDismissable => false;
|
||||
List<MenuItem> build() {
|
||||
return items;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,40 @@
|
||||
import 'package:expandable/expandable.dart';
|
||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||
import 'package:flowy_infra/time/duration.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
enum MenuItemType {
|
||||
userProfile,
|
||||
dashboard,
|
||||
favorites,
|
||||
app,
|
||||
}
|
||||
|
||||
abstract class MenuItem extends StatelessWidget {
|
||||
const MenuItem({Key? key}) : super(key: key);
|
||||
|
||||
MenuItemType get type;
|
||||
}
|
||||
|
||||
class MenuList extends StatelessWidget {
|
||||
final List<MenuItem> menuItems;
|
||||
const MenuList({required this.menuItems, Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ExpandableTheme(
|
||||
data: ExpandableThemeData(
|
||||
useInkWell: true, animationDuration: Durations.medium),
|
||||
child: Expanded(
|
||||
child: ListView.separated(
|
||||
itemCount: menuItems.length,
|
||||
separatorBuilder: (context, index) => const VSpace(10),
|
||||
physics: const BouncingScrollPhysics(),
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
return menuItems[index];
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
import 'package:app_flowy/workspace/presentation/home/home_sizes.dart';
|
||||
import 'package:app_flowy/workspace/presentation/widgets/menu/create_app_dialog.dart';
|
||||
import 'package:flowy_infra/size.dart';
|
||||
import 'package:flowy_infra_ui/widget/dialog/styled_dialogs.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:styled_widget/styled_widget.dart';
|
||||
|
||||
class NewAppButton extends StatelessWidget {
|
||||
final Function(String)? press;
|
||||
|
||||
const NewAppButton({this.press, Key? key}) : super(key: key);
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
border: Border(
|
||||
top: BorderSide(width: 1, color: Colors.grey.shade300),
|
||||
),
|
||||
),
|
||||
height: HomeSizes.menuAddButtonHeight,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
const Icon(Icons.add_circle_rounded, size: 30),
|
||||
TextButton(
|
||||
onPressed: () async => await _showCreateAppDialog(context),
|
||||
child: const Text(
|
||||
'New App',
|
||||
style: TextStyle(
|
||||
color: Colors.black,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 20,
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
).padding(horizontal: Insets.l),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _showCreateAppDialog(BuildContext context) async {
|
||||
await Dialogs.showWithContext(CreateAppDialogContext(
|
||||
confirm: (appName) {
|
||||
if (appName.isNotEmpty && press != null) {
|
||||
press!(appName);
|
||||
}
|
||||
},
|
||||
), context);
|
||||
}
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
class HomeMenuSize {
|
||||
static double get createViewButtonSize => 30;
|
||||
static double get collapseIconSize => 24;
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
import 'package:app_flowy/workspace/application/menu/menu_bloc.dart';
|
||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
class MenuTopBar extends StatelessWidget {
|
||||
const MenuTopBar({Key? key}) : super(key: key);
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocBuilder<MenuBloc, MenuState>(
|
||||
builder: (context, state) {
|
||||
return Row(
|
||||
children: [
|
||||
const Image(
|
||||
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(),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.arrow_left),
|
||||
alignment: Alignment.centerRight,
|
||||
padding: EdgeInsets.zero,
|
||||
onPressed: () =>
|
||||
context.read<MenuBloc>().add(const MenuEvent.collapse()),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
import 'package:app_flowy/startup/startup.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:flowy_infra_ui/widget/spacing.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-user/user_detail.pb.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/styled_text.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/styled_icon_button.dart';
|
||||
|
||||
class MenuUser extends MenuItem {
|
||||
final UserDetail user;
|
||||
MenuUser(this.user, {Key? key}) : super(key: ValueKey(user.id));
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocProvider<MenuUserBloc>(
|
||||
create: (context) =>
|
||||
getIt<MenuUserBloc>(param1: user)..add(const MenuUserEvent.initial()),
|
||||
child: BlocBuilder<MenuUserBloc, MenuUserState>(
|
||||
builder: (context, state) => Row(children: [
|
||||
_renderAvatar(context),
|
||||
const HSpace(10),
|
||||
_renderUserName(context),
|
||||
const HSpace(10),
|
||||
_renderDropButton(context),
|
||||
]),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _renderAvatar(BuildContext context) {
|
||||
return SizedBox(
|
||||
width: 30,
|
||||
height: 30,
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
child: const Image(image: AssetImage('assets/images/avatar.jpg')),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _renderUserName(BuildContext context) {
|
||||
String name = context.read<MenuUserBloc>().state.user.name;
|
||||
if (name.isEmpty) {
|
||||
name = context.read<MenuUserBloc>().state.user.email;
|
||||
}
|
||||
return Flexible(
|
||||
child: StyledText(name, fontSize: 18),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _renderDropButton(BuildContext context) {
|
||||
return StyledIconButton(
|
||||
width: 30,
|
||||
iconRatio: 0.8,
|
||||
icon: const Icon(Icons.arrow_drop_down),
|
||||
onPressed: () {
|
||||
debugPrint('show user profile');
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
MenuItemType get type => MenuItemType.userProfile;
|
||||
}
|
@ -1,2 +1 @@
|
||||
export 'menu.dart';
|
||||
export 'menu_size.dart';
|
||||
|
@ -49,4 +49,4 @@ SPEC CHECKSUMS:
|
||||
|
||||
PODFILE CHECKSUM: 6eac6b3292e5142cfc23bdeb71848a40ec51c14c
|
||||
|
||||
COCOAPODS: 1.9.3
|
||||
COCOAPODS: 1.10.1
|
||||
|
@ -10,10 +10,16 @@ import '../model/document/document.dart';
|
||||
import '../model/document/style.dart';
|
||||
import '../model/document/node/embed.dart';
|
||||
|
||||
abstract class EditorPersistence {
|
||||
Future<bool> save(List<dynamic> jsonList);
|
||||
}
|
||||
|
||||
class EditorController extends ChangeNotifier {
|
||||
final EditorPersistence? persistence;
|
||||
EditorController({
|
||||
required this.document,
|
||||
required this.selection,
|
||||
this.persistence,
|
||||
});
|
||||
|
||||
factory EditorController.basic() {
|
||||
@ -38,7 +44,8 @@ class EditorController extends ChangeNotifier {
|
||||
);
|
||||
|
||||
Style getSelectionStyle() =>
|
||||
document.collectStyle(selection.start, selection.end - selection.start)..mergeAll(toggledStyle);
|
||||
document.collectStyle(selection.start, selection.end - selection.start)
|
||||
..mergeAll(toggledStyle);
|
||||
|
||||
bool get hasUndo => document.hasUndo;
|
||||
|
||||
@ -58,10 +65,10 @@ class EditorController extends ChangeNotifier {
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> save() async {
|
||||
document.toDelta().toJson();
|
||||
// TODO: vedon - Save document to database
|
||||
return true;
|
||||
void save() {
|
||||
if (persistence != null) {
|
||||
persistence!.save(document.toDelta().toJson());
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
@ -80,7 +87,9 @@ class EditorController extends ChangeNotifier {
|
||||
}
|
||||
|
||||
void formatText(int index, int length, Attribute? attribute) {
|
||||
if (length == 0 && attribute!.isInline && attribute.key != Attribute.link.key) {
|
||||
if (length == 0 &&
|
||||
attribute!.isInline &&
|
||||
attribute.key != Attribute.link.key) {
|
||||
toggledStyle = toggledStyle.put(attribute);
|
||||
}
|
||||
|
||||
@ -95,16 +104,25 @@ class EditorController extends ChangeNotifier {
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void replaceText(int index, int length, Object? data, TextSelection? textSelection) {
|
||||
void replaceText(
|
||||
int index, int length, Object? data, TextSelection? textSelection) {
|
||||
assert(data is String || data is Embeddable);
|
||||
|
||||
Delta? delta;
|
||||
if (length > 0 || data is! String || data.isNotEmpty) {
|
||||
delta = document.replace(index, length, data);
|
||||
var shouldRetainDelta = toggledStyle.isNotEmpty && delta.isNotEmpty && delta.length <= 2 && delta.last.isInsert;
|
||||
if (shouldRetainDelta && toggledStyle.isNotEmpty && delta.length == 2 && delta.last.data == '\n') {
|
||||
print(delta);
|
||||
var shouldRetainDelta = toggledStyle.isNotEmpty &&
|
||||
delta.isNotEmpty &&
|
||||
delta.length <= 2 &&
|
||||
delta.last.isInsert;
|
||||
if (shouldRetainDelta &&
|
||||
toggledStyle.isNotEmpty &&
|
||||
delta.length == 2 &&
|
||||
delta.last.data == '\n') {
|
||||
// if all attributes are inline, shouldRetainDelta should be false
|
||||
final anyAttributeNotInline = toggledStyle.values.any((attr) => !attr.isInline);
|
||||
final anyAttributeNotInline =
|
||||
toggledStyle.values.any((attr) => !attr.isInline);
|
||||
shouldRetainDelta &= anyAttributeNotInline;
|
||||
}
|
||||
if (shouldRetainDelta) {
|
||||
@ -146,7 +164,8 @@ class EditorController extends ChangeNotifier {
|
||||
|
||||
textSelection = selection.copyWith(
|
||||
baseOffset: delta.transformPosition(selection.baseOffset, force: false),
|
||||
extentOffset: delta.transformPosition(selection.extentOffset, force: false),
|
||||
extentOffset:
|
||||
delta.transformPosition(selection.extentOffset, force: false),
|
||||
);
|
||||
if (selection != textSelection) {
|
||||
_updateSelection(textSelection, source);
|
||||
|
@ -60,7 +60,8 @@ class RawEditor extends StatefulWidget {
|
||||
this.embedBuilder,
|
||||
) : assert(maxHeight == null || maxHeight > 0, 'maxHeight cannot be null'),
|
||||
assert(minHeight == null || minHeight >= 0, 'minHeight cannot be null'),
|
||||
assert(maxHeight == null || minHeight == null || maxHeight >= minHeight),
|
||||
assert(
|
||||
maxHeight == null || minHeight == null || maxHeight >= minHeight),
|
||||
showCursor = showCursor ?? true,
|
||||
super(key: key);
|
||||
|
||||
@ -111,7 +112,10 @@ abstract class EditorState extends State<RawEditor> {
|
||||
}
|
||||
|
||||
class _RawEditorState extends EditorState
|
||||
with AutomaticKeepAliveClientMixin<RawEditor>, WidgetsBindingObserver, TickerProviderStateMixin<RawEditor>
|
||||
with
|
||||
AutomaticKeepAliveClientMixin<RawEditor>,
|
||||
WidgetsBindingObserver,
|
||||
TickerProviderStateMixin<RawEditor>
|
||||
implements TextSelectionDelegate, TextInputClient {
|
||||
final GlobalKey _editorKey = GlobalKey();
|
||||
final List<TextEditingValue> _sentRemoteValues = [];
|
||||
@ -129,7 +133,8 @@ class _RawEditorState extends EditorState
|
||||
bool _didAutoFocus = false;
|
||||
bool _keyboardVisible = false;
|
||||
DefaultStyles? _styles;
|
||||
final ClipboardStatusNotifier? _clipboardStatus = kIsWeb ? null : ClipboardStatusNotifier();
|
||||
final ClipboardStatusNotifier? _clipboardStatus =
|
||||
kIsWeb ? null : ClipboardStatusNotifier();
|
||||
final LayerLink _toolbarLayerLink = LayerLink();
|
||||
final LayerLink _startHandleLayerLink = LayerLink();
|
||||
final LayerLink _endHandleLayerLink = LayerLink();
|
||||
@ -177,57 +182,78 @@ class _RawEditorState extends EditorState
|
||||
downKey = key == LogicalKeyboardKey.arrowDown;
|
||||
|
||||
if ((rightKey || leftKey) && !(rightKey && leftKey)) {
|
||||
newSelection =
|
||||
_jumpToBeginOrEndOfWord(newSelection, wordModifier, leftKey, rightKey, plainText, lineModifier, shift);
|
||||
newSelection = _jumpToBeginOrEndOfWord(newSelection, wordModifier,
|
||||
leftKey, rightKey, plainText, lineModifier, shift);
|
||||
}
|
||||
|
||||
if (downKey || upKey) {
|
||||
newSelection = _handleMovingCursorVertically(upKey, downKey, shift, selection, newSelection, plainText);
|
||||
newSelection = _handleMovingCursorVertically(
|
||||
upKey, downKey, shift, selection, newSelection, plainText);
|
||||
}
|
||||
|
||||
if (!shift) {
|
||||
newSelection = _placeCollapsedSelection(selection, newSelection, leftKey, rightKey);
|
||||
newSelection =
|
||||
_placeCollapsedSelection(selection, newSelection, leftKey, rightKey);
|
||||
}
|
||||
|
||||
widget.controller.updateSelection(newSelection, ChangeSource.LOCAL);
|
||||
}
|
||||
|
||||
TextSelection _placeCollapsedSelection(
|
||||
TextSelection selection, TextSelection newSelection, bool leftKey, bool rightKey) {
|
||||
TextSelection _placeCollapsedSelection(TextSelection selection,
|
||||
TextSelection newSelection, bool leftKey, bool rightKey) {
|
||||
var newOffset = newSelection.extentOffset;
|
||||
if (!selection.isCollapsed) {
|
||||
if (leftKey) {
|
||||
newOffset =
|
||||
newSelection.baseOffset < newSelection.extentOffset ? newSelection.baseOffset : newSelection.extentOffset;
|
||||
newOffset = newSelection.baseOffset < newSelection.extentOffset
|
||||
? newSelection.baseOffset
|
||||
: newSelection.extentOffset;
|
||||
} else if (rightKey) {
|
||||
newOffset =
|
||||
newSelection.baseOffset > newSelection.extentOffset ? newSelection.baseOffset : newSelection.extentOffset;
|
||||
newOffset = newSelection.baseOffset > newSelection.extentOffset
|
||||
? newSelection.baseOffset
|
||||
: newSelection.extentOffset;
|
||||
}
|
||||
}
|
||||
return TextSelection.fromPosition(TextPosition(offset: newOffset));
|
||||
}
|
||||
|
||||
TextSelection _handleMovingCursorVertically(
|
||||
bool upKey, bool downKey, bool shift, TextSelection selection, TextSelection newSelection, String plainText) {
|
||||
final originPosition = TextPosition(offset: upKey ? selection.baseOffset : selection.extentOffset);
|
||||
bool upKey,
|
||||
bool downKey,
|
||||
bool shift,
|
||||
TextSelection selection,
|
||||
TextSelection newSelection,
|
||||
String plainText) {
|
||||
final originPosition = TextPosition(
|
||||
offset: upKey ? selection.baseOffset : selection.extentOffset);
|
||||
|
||||
final child = getRenderEditor()!.childAtPosition(originPosition);
|
||||
final localPosition = TextPosition(offset: originPosition.offset - child.container.documentOffset);
|
||||
final localPosition = TextPosition(
|
||||
offset: originPosition.offset - child.container.documentOffset);
|
||||
|
||||
var position = upKey ? child.getPositionAbove(localPosition) : child.getPositionBelow(localPosition);
|
||||
var position = upKey
|
||||
? child.getPositionAbove(localPosition)
|
||||
: child.getPositionBelow(localPosition);
|
||||
|
||||
if (position == null) {
|
||||
final sibling = upKey ? getRenderEditor()!.childBefore(child) : getRenderEditor()!.childAfter(child);
|
||||
final sibling = upKey
|
||||
? getRenderEditor()!.childBefore(child)
|
||||
: getRenderEditor()!.childAfter(child);
|
||||
if (sibling == null) {
|
||||
position = TextPosition(offset: upKey ? 0 : plainText.length - 1);
|
||||
} else {
|
||||
final finalOffset = Offset(child.getOffsetForCaret(localPosition).dx,
|
||||
sibling.getOffsetForCaret(TextPosition(offset: upKey ? sibling.container.length - 1 : 0)).dy);
|
||||
final finalOffset = Offset(
|
||||
child.getOffsetForCaret(localPosition).dx,
|
||||
sibling
|
||||
.getOffsetForCaret(TextPosition(
|
||||
offset: upKey ? sibling.container.length - 1 : 0))
|
||||
.dy);
|
||||
final siblingPosition = sibling.getPositionForOffset(finalOffset);
|
||||
position = TextPosition(offset: sibling.container.documentOffset + siblingPosition.offset);
|
||||
position = TextPosition(
|
||||
offset: sibling.container.documentOffset + siblingPosition.offset);
|
||||
}
|
||||
} else {
|
||||
position = TextPosition(offset: child.container.documentOffset + position.offset);
|
||||
position = TextPosition(
|
||||
offset: child.container.documentOffset + position.offset);
|
||||
}
|
||||
|
||||
if (position.offset == newSelection.extentOffset) {
|
||||
@ -250,33 +276,47 @@ class _RawEditorState extends EditorState
|
||||
return newSelection;
|
||||
}
|
||||
|
||||
TextSelection _jumpToBeginOrEndOfWord(TextSelection newSelection, bool wordModifier, bool leftKey, bool rightKey,
|
||||
String plainText, bool lineModifier, bool shift) {
|
||||
TextSelection _jumpToBeginOrEndOfWord(
|
||||
TextSelection newSelection,
|
||||
bool wordModifier,
|
||||
bool leftKey,
|
||||
bool rightKey,
|
||||
String plainText,
|
||||
bool lineModifier,
|
||||
bool shift) {
|
||||
if (wordModifier) {
|
||||
if (leftKey) {
|
||||
final textSelection = getRenderEditor()!.selectWordAtPosition(
|
||||
TextPosition(offset: _previousCharacter(newSelection.extentOffset, plainText, false)));
|
||||
TextPosition(
|
||||
offset: _previousCharacter(
|
||||
newSelection.extentOffset, plainText, false)));
|
||||
return newSelection.copyWith(extentOffset: textSelection.baseOffset);
|
||||
}
|
||||
final textSelection = getRenderEditor()!
|
||||
.selectWordAtPosition(TextPosition(offset: _nextCharacter(newSelection.extentOffset, plainText, false)));
|
||||
final textSelection = getRenderEditor()!.selectWordAtPosition(
|
||||
TextPosition(
|
||||
offset:
|
||||
_nextCharacter(newSelection.extentOffset, plainText, false)));
|
||||
return newSelection.copyWith(extentOffset: textSelection.extentOffset);
|
||||
} else if (lineModifier) {
|
||||
if (leftKey) {
|
||||
final textSelection = getRenderEditor()!.selectLineAtPosition(
|
||||
TextPosition(offset: _previousCharacter(newSelection.extentOffset, plainText, false)));
|
||||
TextPosition(
|
||||
offset: _previousCharacter(
|
||||
newSelection.extentOffset, plainText, false)));
|
||||
return newSelection.copyWith(extentOffset: textSelection.baseOffset);
|
||||
}
|
||||
final startPoint = newSelection.extentOffset;
|
||||
if (startPoint < plainText.length) {
|
||||
final textSelection = getRenderEditor()!.selectLineAtPosition(TextPosition(offset: startPoint));
|
||||
final textSelection = getRenderEditor()!
|
||||
.selectLineAtPosition(TextPosition(offset: startPoint));
|
||||
return newSelection.copyWith(extentOffset: textSelection.extentOffset);
|
||||
}
|
||||
return newSelection;
|
||||
}
|
||||
|
||||
if (rightKey && newSelection.extentOffset < plainText.length) {
|
||||
final nextExtent = _nextCharacter(newSelection.extentOffset, plainText, true);
|
||||
final nextExtent =
|
||||
_nextCharacter(newSelection.extentOffset, plainText, true);
|
||||
final distance = nextExtent - newSelection.extentOffset;
|
||||
newSelection = newSelection.copyWith(extentOffset: nextExtent);
|
||||
if (shift) {
|
||||
@ -286,7 +326,8 @@ class _RawEditorState extends EditorState
|
||||
}
|
||||
|
||||
if (leftKey && newSelection.extentOffset > 0) {
|
||||
final previousExtent = _previousCharacter(newSelection.extentOffset, plainText, true);
|
||||
final previousExtent =
|
||||
_previousCharacter(newSelection.extentOffset, plainText, true);
|
||||
final distance = newSelection.extentOffset - previousExtent;
|
||||
newSelection = newSelection.copyWith(extentOffset: previousExtent);
|
||||
if (shift) {
|
||||
@ -326,7 +367,9 @@ class _RawEditorState extends EditorState
|
||||
var count = 0;
|
||||
int? lastNonWhitespace;
|
||||
for (final currentString in string.characters) {
|
||||
if (!includeWhitespace && !WHITE_SPACE.contains(currentString.characters.first.toString().codeUnitAt(0))) {
|
||||
if (!includeWhitespace &&
|
||||
!WHITE_SPACE.contains(
|
||||
currentString.characters.first.toString().codeUnitAt(0))) {
|
||||
lastNonWhitespace = count;
|
||||
}
|
||||
if (count + currentString.length >= index) {
|
||||
@ -337,7 +380,8 @@ class _RawEditorState extends EditorState
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool get hasConnection => _textInputConnection != null && _textInputConnection!.attached;
|
||||
bool get hasConnection =>
|
||||
_textInputConnection != null && _textInputConnection!.attached;
|
||||
|
||||
void openConnectionIfNeeded() {
|
||||
if (!shouldCreateInputConnection) {
|
||||
@ -388,7 +432,8 @@ class _RawEditorState extends EditorState
|
||||
return;
|
||||
}
|
||||
|
||||
final shouldRemember = textEditingValue.text != _lastKnownRemoteTextEditingValue!.text;
|
||||
final shouldRemember =
|
||||
textEditingValue.text != _lastKnownRemoteTextEditingValue!.text;
|
||||
_lastKnownRemoteTextEditingValue = actualValue;
|
||||
_textInputConnection!.setEditingState(actualValue);
|
||||
if (shouldRemember) {
|
||||
@ -397,7 +442,8 @@ class _RawEditorState extends EditorState
|
||||
}
|
||||
|
||||
@override
|
||||
TextEditingValue? get currentTextEditingValue => _lastKnownRemoteTextEditingValue;
|
||||
TextEditingValue? get currentTextEditingValue =>
|
||||
_lastKnownRemoteTextEditingValue;
|
||||
|
||||
@override
|
||||
AutofillScope? get currentAutofillScope => null;
|
||||
@ -429,7 +475,8 @@ class _RawEditorState extends EditorState
|
||||
final text = value.text;
|
||||
final cursorPosition = value.selection.extentOffset;
|
||||
final diff = getDiff(oldText, text, cursorPosition);
|
||||
widget.controller.replaceText(diff.start, diff.deleted.length, diff.inserted, value.selection);
|
||||
widget.controller.replaceText(
|
||||
diff.start, diff.deleted.length, diff.inserted, value.selection);
|
||||
}
|
||||
|
||||
@override
|
||||
@ -479,8 +526,11 @@ class _RawEditorState extends EditorState
|
||||
super.build(context);
|
||||
|
||||
var _doc = widget.controller.document;
|
||||
if (_doc.isEmpty() && !widget.focusNode.hasFocus && widget.placeholder != null) {
|
||||
_doc = Document.fromJson(jsonDecode('[{"attributes":{"placeholder":true},"insert":"${widget.placeholder}\\n"}]'));
|
||||
if (_doc.isEmpty() &&
|
||||
!widget.focusNode.hasFocus &&
|
||||
widget.placeholder != null) {
|
||||
_doc = Document.fromJson(jsonDecode(
|
||||
'[{"attributes":{"placeholder":true},"insert":"${widget.placeholder}\\n"}]'));
|
||||
}
|
||||
|
||||
Widget child = CompositedTransformTarget(
|
||||
@ -503,7 +553,8 @@ class _RawEditorState extends EditorState
|
||||
);
|
||||
|
||||
if (widget.scrollable) {
|
||||
final baselinePadding = EdgeInsets.only(top: _styles!.paragraph!.verticalSpacing.item1);
|
||||
final baselinePadding =
|
||||
EdgeInsets.only(top: _styles!.paragraph!.verticalSpacing.item1);
|
||||
child = BaselineProxy(
|
||||
textStyle: _styles!.paragraph!.style,
|
||||
padding: baselinePadding,
|
||||
@ -534,7 +585,8 @@ class _RawEditorState extends EditorState
|
||||
);
|
||||
}
|
||||
|
||||
void _handleSelectionChanged(TextSelection selection, SelectionChangedCause cause) {
|
||||
void _handleSelectionChanged(
|
||||
TextSelection selection, SelectionChangedCause cause) {
|
||||
widget.controller.updateSelection(selection, ChangeSource.LOCAL);
|
||||
|
||||
_selectionOverlay?.handlesVisible = _shouldShowSelectionHandles();
|
||||
@ -563,7 +615,9 @@ class _RawEditorState extends EditorState
|
||||
_styles,
|
||||
widget.enableInteractiveSelection,
|
||||
_hasFocus,
|
||||
attrs.containsKey(Attribute.codeBlock.key) ? const EdgeInsets.all(16) : null,
|
||||
attrs.containsKey(Attribute.codeBlock.key)
|
||||
? const EdgeInsets.all(16)
|
||||
: null,
|
||||
widget.embedBuilder,
|
||||
_cursorController,
|
||||
indentLevelCounts);
|
||||
@ -575,7 +629,8 @@ class _RawEditorState extends EditorState
|
||||
return result;
|
||||
}
|
||||
|
||||
EditableTextLine _getEditableTextLineFromNode(Line node, BuildContext context) {
|
||||
EditableTextLine _getEditableTextLineFromNode(
|
||||
Line node, BuildContext context) {
|
||||
final textLine = TextLine(
|
||||
line: node,
|
||||
textDirection: _textDirection,
|
||||
@ -598,7 +653,8 @@ class _RawEditorState extends EditorState
|
||||
return editableTextLine;
|
||||
}
|
||||
|
||||
Tuple2<double, double> _getVerticalSpacingForLine(Line line, DefaultStyles? defaultStyles) {
|
||||
Tuple2<double, double> _getVerticalSpacingForLine(
|
||||
Line line, DefaultStyles? defaultStyles) {
|
||||
final attrs = line.style.attributes;
|
||||
if (attrs.containsKey(Attribute.header.key)) {
|
||||
final int? level = attrs[Attribute.header.key]!.value;
|
||||
@ -623,7 +679,8 @@ class _RawEditorState extends EditorState
|
||||
return defaultStyles!.paragraph!.verticalSpacing;
|
||||
}
|
||||
|
||||
Tuple2<double, double> _getVerticalSpacingForBlock(Block node, DefaultStyles? defaultStyles) {
|
||||
Tuple2<double, double> _getVerticalSpacingForBlock(
|
||||
Block node, DefaultStyles? defaultStyles) {
|
||||
final attrs = node.style.attributes;
|
||||
if (attrs.containsKey(Attribute.quoteBlock.key)) {
|
||||
return defaultStyles!.quote!.verticalSpacing;
|
||||
@ -666,7 +723,8 @@ class _RawEditorState extends EditorState
|
||||
} else {
|
||||
_keyboardVisibilityController = KeyboardVisibilityController();
|
||||
_keyboardVisible = _keyboardVisibilityController!.isVisible;
|
||||
_keyboardVisibilitySubscription = _keyboardVisibilityController?.onChange.listen((visible) {
|
||||
_keyboardVisibilitySubscription =
|
||||
_keyboardVisibilityController?.onChange.listen((visible) {
|
||||
_keyboardVisible = visible;
|
||||
if (visible) {
|
||||
_onChangeTextEditingValue();
|
||||
@ -689,7 +747,9 @@ class _RawEditorState extends EditorState
|
||||
super.didChangeDependencies();
|
||||
final parentStyles = EditorStyles.getStyles(context, true);
|
||||
final defaultStyles = DefaultStyles.getInstance(context);
|
||||
_styles = (parentStyles != null) ? defaultStyles.merge(parentStyles) : defaultStyles;
|
||||
_styles = (parentStyles != null)
|
||||
? defaultStyles.merge(parentStyles)
|
||||
: defaultStyles;
|
||||
|
||||
if (widget.customStyles != null) {
|
||||
_styles = _styles!.merge(widget.customStyles!);
|
||||
@ -749,7 +809,8 @@ class _RawEditorState extends EditorState
|
||||
}
|
||||
|
||||
bool _shouldShowSelectionHandles() {
|
||||
return widget.showSelectionHandles && !widget.controller.selection.isCollapsed;
|
||||
return widget.showSelectionHandles &&
|
||||
!widget.controller.selection.isCollapsed;
|
||||
}
|
||||
|
||||
void handleDelete(bool forward) {
|
||||
@ -760,7 +821,8 @@ class _RawEditorState extends EditorState
|
||||
var textAfter = selection.textAfter(plainText);
|
||||
if (selection.isCollapsed) {
|
||||
if (!forward && textBefore.isNotEmpty) {
|
||||
final characterBoundary = _previousCharacter(textBefore.length, textBefore, true);
|
||||
final characterBoundary =
|
||||
_previousCharacter(textBefore.length, textBefore, true);
|
||||
textBefore = textBefore.substring(0, characterBoundary);
|
||||
cursorPosition = characterBoundary;
|
||||
}
|
||||
@ -784,15 +846,13 @@ class _RawEditorState extends EditorState
|
||||
final selection = widget.controller.selection;
|
||||
final plainText = textEditingValue.text;
|
||||
if (shortcut == InputShortcut.SAVE) {
|
||||
bool saved = await widget.controller.save();
|
||||
if (!saved) {
|
||||
log('Unabled to save document.');
|
||||
}
|
||||
widget.controller.save();
|
||||
return;
|
||||
}
|
||||
if (shortcut == InputShortcut.COPY) {
|
||||
if (!selection.isCollapsed) {
|
||||
await Clipboard.setData(ClipboardData(text: selection.textInside(plainText)));
|
||||
await Clipboard.setData(
|
||||
ClipboardData(text: selection.textInside(plainText)));
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -809,7 +869,8 @@ class _RawEditorState extends EditorState
|
||||
);
|
||||
|
||||
textEditingValue = TextEditingValue(
|
||||
text: selection.textBefore(plainText) + selection.textAfter(plainText),
|
||||
text:
|
||||
selection.textBefore(plainText) + selection.textAfter(plainText),
|
||||
selection: TextSelection.collapsed(offset: selection.start),
|
||||
);
|
||||
}
|
||||
@ -827,7 +888,8 @@ class _RawEditorState extends EditorState
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (shortcut == InputShortcut.SELECT_ALL && widget.enableInteractiveSelection) {
|
||||
if (shortcut == InputShortcut.SELECT_ALL &&
|
||||
widget.enableInteractiveSelection) {
|
||||
widget.controller.updateSelection(
|
||||
selection.copyWith(
|
||||
baseOffset: 0,
|
||||
@ -881,14 +943,16 @@ class _RawEditorState extends EditorState
|
||||
void _onChangeTextEditingValue() {
|
||||
_showCaretOnScreen();
|
||||
updateRemoteValueIfNeeded();
|
||||
_cursorController.startOrStopCursorTimerIfNeeded(_hasFocus, widget.controller.selection);
|
||||
_cursorController.startOrStopCursorTimerIfNeeded(
|
||||
_hasFocus, widget.controller.selection);
|
||||
if (hasConnection) {
|
||||
_cursorController
|
||||
..stopCursorTimer(resetCharTicks: false)
|
||||
..startCursorTimer();
|
||||
}
|
||||
|
||||
SchedulerBinding.instance!.addPostFrameCallback((_) => _updateOrDisposeSelectionOverlayIfNeeded());
|
||||
SchedulerBinding.instance!.addPostFrameCallback(
|
||||
(_) => _updateOrDisposeSelectionOverlayIfNeeded());
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
// Use widget.controller.value in build()
|
||||
@ -931,7 +995,8 @@ class _RawEditorState extends EditorState
|
||||
|
||||
void _handleFocusChanged() {
|
||||
openOrCloseConnection();
|
||||
_cursorController.startOrStopCursorTimerIfNeeded(_hasFocus, widget.controller.selection);
|
||||
_cursorController.startOrStopCursorTimerIfNeeded(
|
||||
_hasFocus, widget.controller.selection);
|
||||
_updateOrDisposeSelectionOverlayIfNeeded();
|
||||
if (_hasFocus) {
|
||||
WidgetsBinding.instance!.addObserver(this);
|
||||
@ -962,7 +1027,8 @@ class _RawEditorState extends EditorState
|
||||
_showCaretOnScreenScheduled = false;
|
||||
|
||||
final viewport = RenderAbstractViewport.of(getRenderEditor())!;
|
||||
final editorOffset = getRenderEditor()!.localToGlobal(const Offset(0, 0), ancestor: viewport);
|
||||
final editorOffset = getRenderEditor()!
|
||||
.localToGlobal(const Offset(0, 0), ancestor: viewport);
|
||||
final offsetInViewport = _scrollController!.offset + editorOffset.dy;
|
||||
|
||||
final offset = getRenderEditor()!.getOffsetToRevealCursor(
|
||||
@ -1045,7 +1111,8 @@ class _RawEditorState extends EditorState
|
||||
final value = textEditingValue;
|
||||
final data = await Clipboard.getData(Clipboard.kTextPlain);
|
||||
if (data != null) {
|
||||
final length = textEditingValue.selection.end - textEditingValue.selection.start;
|
||||
final length =
|
||||
textEditingValue.selection.end - textEditingValue.selection.start;
|
||||
widget.controller.replaceText(
|
||||
value.selection.start,
|
||||
length,
|
||||
@ -1054,7 +1121,9 @@ class _RawEditorState extends EditorState
|
||||
);
|
||||
// move cursor to the end of pasted text selection
|
||||
widget.controller.updateSelection(
|
||||
TextSelection.collapsed(offset: value.selection.start + data.text!.length), ChangeSource.LOCAL);
|
||||
TextSelection.collapsed(
|
||||
offset: value.selection.start + data.text!.length),
|
||||
ChangeSource.LOCAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1064,7 +1133,8 @@ class _RawEditorState extends EditorState
|
||||
if (data == null) {
|
||||
return false;
|
||||
}
|
||||
return textEditingValue.text.length - value.text.length == data.text!.length;
|
||||
return textEditingValue.text.length - value.text.length ==
|
||||
data.text!.length;
|
||||
}
|
||||
|
||||
@override
|
||||
@ -1097,7 +1167,8 @@ class _RawEditorState extends EditorState
|
||||
}
|
||||
|
||||
@override
|
||||
void userUpdateTextEditingValue(TextEditingValue value, SelectionChangedCause cause) {
|
||||
void userUpdateTextEditingValue(
|
||||
TextEditingValue value, SelectionChangedCause cause) {
|
||||
// TODO: implement userUpdateTextEditingValue
|
||||
}
|
||||
}
|
||||
@ -1147,7 +1218,8 @@ class _Editor extends MultiChildRenderObjectWidget {
|
||||
}
|
||||
|
||||
@override
|
||||
void updateRenderObject(BuildContext context, covariant RenderEditor renderObject) {
|
||||
void updateRenderObject(
|
||||
BuildContext context, covariant RenderEditor renderObject) {
|
||||
renderObject
|
||||
..document = document
|
||||
..container = document.root
|
||||
|
@ -54,7 +54,7 @@ class Sizes {
|
||||
|
||||
static double get sideBarSm => 200 * hitScale;
|
||||
|
||||
static double get sideBarMed => 220 * hitScale;
|
||||
static double get sideBarMed => 240 * hitScale;
|
||||
|
||||
static double get sideBarLg => 290 * hitScale;
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ class AppTheme {
|
||||
switch (t) {
|
||||
case ThemeType.light:
|
||||
return AppTheme(isDark: false)
|
||||
..bg1 = const Color(0xfff1f7f0)
|
||||
..bg1 = const Color.fromARGB(255, 247, 248, 252)
|
||||
..bg2 = const Color(0xffc1dcbc)
|
||||
..surface = Colors.white
|
||||
..accent1 = const Color(0xff00a086)
|
||||
|
@ -13,4 +13,5 @@ class Durations {
|
||||
|
||||
class RouteDurations {
|
||||
static Duration get slow => .7.seconds;
|
||||
static Duration get medium => .35.seconds;
|
||||
}
|
||||
|
@ -156,6 +156,13 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
loading_indicator:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: loading_indicator
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.0.1"
|
||||
logger:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -296,4 +303,4 @@ packages:
|
||||
version: "2.1.0"
|
||||
sdks:
|
||||
dart: ">=2.12.0 <3.0.0"
|
||||
flutter: ">=1.20.0"
|
||||
flutter: ">=2.0.0"
|
||||
|
@ -0,0 +1,57 @@
|
||||
import 'package:flutter/material.dart';
|
||||
// ignore: unused_import
|
||||
import 'package:flowy_infra/time/duration.dart';
|
||||
|
||||
typedef HoverBuilder = Widget Function(BuildContext context, bool onHover);
|
||||
|
||||
class StyledHover extends StatefulWidget {
|
||||
final Color color;
|
||||
final Color borderColor;
|
||||
final double borderWidth;
|
||||
final BorderRadius borderRadius;
|
||||
final HoverBuilder builder;
|
||||
|
||||
const StyledHover({
|
||||
Key? key,
|
||||
required this.color,
|
||||
this.borderColor = Colors.transparent,
|
||||
this.borderWidth = 0,
|
||||
this.borderRadius = BorderRadius.zero,
|
||||
required this.builder,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<StyledHover> createState() => _StyledHoverState();
|
||||
}
|
||||
|
||||
class _StyledHoverState extends State<StyledHover> {
|
||||
bool _onHover = false;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final hoverColor =
|
||||
_onHover ? widget.color : Theme.of(context).colorScheme.background;
|
||||
|
||||
final hoverBorder = Border.all(
|
||||
color: widget.borderColor,
|
||||
width: widget.borderWidth,
|
||||
);
|
||||
|
||||
return MouseRegion(
|
||||
cursor: SystemMouseCursors.click,
|
||||
onEnter: (p) => setOnHover(true),
|
||||
onExit: (p) => setOnHover(false),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
border: hoverBorder,
|
||||
color: hoverColor,
|
||||
borderRadius: widget.borderRadius,
|
||||
),
|
||||
// duration: .1.seconds,
|
||||
child: widget.builder(context, _onHover),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void setOnHover(bool value) => setState(() => _onHover = value);
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class StyledIconButton extends StatelessWidget {
|
||||
final double width;
|
||||
final double? height;
|
||||
final double iconRatio;
|
||||
final Icon icon;
|
||||
final VoidCallback? onPressed;
|
||||
|
||||
const StyledIconButton({
|
||||
Key? key,
|
||||
this.height,
|
||||
this.onPressed,
|
||||
this.width = 30,
|
||||
required this.icon,
|
||||
this.iconRatio = 0.5,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SizedBox(
|
||||
width: width,
|
||||
height: height ?? width,
|
||||
child: IconButton(
|
||||
icon: icon,
|
||||
padding: EdgeInsets.zero,
|
||||
iconSize: width * iconRatio,
|
||||
alignment: Alignment.center,
|
||||
onPressed: onPressed,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class StyledMore extends StatelessWidget {
|
||||
final double width;
|
||||
final double? height;
|
||||
final VoidCallback? onPressed;
|
||||
|
||||
const StyledMore({
|
||||
Key? key,
|
||||
this.height,
|
||||
this.onPressed,
|
||||
required this.width,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return StyledIconButton(
|
||||
width: width,
|
||||
height: height,
|
||||
icon: const Icon(Icons.more_vert),
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,107 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
typedef NaviAction = void Function(String);
|
||||
|
||||
abstract class NaviItem {
|
||||
String get identifier;
|
||||
NaviAction get action;
|
||||
}
|
||||
|
||||
class StyledNavigationController extends ChangeNotifier {
|
||||
List<NaviItem> naviItems;
|
||||
StyledNavigationController({this.naviItems = const []});
|
||||
}
|
||||
|
||||
class StyledNavigationList extends StatelessWidget {
|
||||
const StyledNavigationList({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MultiProvider(
|
||||
providers: [
|
||||
ChangeNotifierProvider(create: (_) => StyledNavigationController()),
|
||||
],
|
||||
child: Consumer(builder: (ctx, StyledNavigationController ctrl, child) {
|
||||
return Row(
|
||||
children: _buildNaviItemWidget(ctrl.naviItems),
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
List<Widget> _buildNaviItemWidget(List<NaviItem> items) {
|
||||
if (items.isEmpty) {
|
||||
return [];
|
||||
}
|
||||
|
||||
List<NaviItem> newItems = _selectNaviItem(items);
|
||||
Widget last = NaviItemWidget(newItems.removeLast());
|
||||
|
||||
List<Widget> widgets = newItems
|
||||
.map(
|
||||
(item) => NaviItemDivider(
|
||||
child: NaviItemWidget(item),
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
|
||||
widgets.add(last);
|
||||
|
||||
return widgets;
|
||||
}
|
||||
|
||||
List<NaviItem> _selectNaviItem(List<NaviItem> items) {
|
||||
final length = items.length;
|
||||
if (length > 4) {
|
||||
final ellipsisItems = items.getRange(1, length - 2).toList();
|
||||
return [
|
||||
items[0],
|
||||
EllipsisNaviItem(items: ellipsisItems),
|
||||
items[length - 2],
|
||||
items[length - 1]
|
||||
];
|
||||
} else {
|
||||
return items;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class NaviItemWidget extends StatelessWidget {
|
||||
final NaviItem item;
|
||||
const NaviItemWidget(this.item, {Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
child: null,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class NaviItemDivider extends StatelessWidget {
|
||||
final Widget child;
|
||||
const NaviItemDivider({Key? key, required this.child}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
children: [child, const Text('/')],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class EllipsisNaviItem extends NaviItem {
|
||||
final List<NaviItem> items;
|
||||
EllipsisNaviItem({
|
||||
required this.items,
|
||||
});
|
||||
|
||||
@override
|
||||
// TODO: implement action
|
||||
NaviAction get action => throw UnimplementedError();
|
||||
|
||||
@override
|
||||
// TODO: implement identifier
|
||||
String get identifier => throw UnimplementedError();
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:loading_indicator/loading_indicator.dart';
|
||||
|
||||
List<Color> _kDefaultRainbowColors = const [
|
||||
Colors.red,
|
||||
Colors.orange,
|
||||
Colors.yellow,
|
||||
Colors.green,
|
||||
Colors.blue,
|
||||
Colors.indigo,
|
||||
Colors.purple,
|
||||
];
|
||||
|
||||
// CircularProgressIndicator()
|
||||
class StyledProgressIndicator extends StatelessWidget {
|
||||
const StyledProgressIndicator({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SizedBox.expand(
|
||||
child: Center(
|
||||
child: SizedBox(
|
||||
width: 60,
|
||||
child: LoadingIndicator(
|
||||
indicatorType: Indicator.pacman,
|
||||
colors: _kDefaultRainbowColors,
|
||||
strokeWidth: 4.0,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
class StyledText extends StatelessWidget {
|
||||
final String title;
|
||||
final TextOverflow overflow;
|
||||
final double fontSize;
|
||||
const StyledText(
|
||||
this.title, {
|
||||
Key? key,
|
||||
this.overflow = TextOverflow.ellipsis,
|
||||
this.fontSize = 16,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Text(
|
||||
title,
|
||||
overflow: overflow,
|
||||
softWrap: false,
|
||||
style: TextStyle(fontSize: fontSize),
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
import 'package:flowy_infra_ui/style_widget/styled_hover.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/styled_text.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
class StyledTextButton extends StatelessWidget {
|
||||
final String text;
|
||||
final double fontSize;
|
||||
final VoidCallback? onPressed;
|
||||
final EdgeInsets padding;
|
||||
const StyledTextButton(this.text,
|
||||
{Key? key,
|
||||
this.onPressed,
|
||||
this.fontSize = 16,
|
||||
this.padding = const EdgeInsets.symmetric(horizontal: 8, vertical: 6)})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return InkWell(
|
||||
onTap: onPressed,
|
||||
child: StyledHover(
|
||||
color: Colors.grey.shade300,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
builder: (context, onHover) => _render(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _render() {
|
||||
return Padding(
|
||||
padding: padding,
|
||||
child: Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: StyledText(text, fontSize: fontSize),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
// return TextButton(
|
||||
// style: ButtonStyle(
|
||||
// textStyle: MaterialStateProperty.all(TextStyle(fontSize: fontSize)),
|
||||
// alignment: Alignment.centerLeft,
|
||||
// foregroundColor: MaterialStateProperty.all(Colors.black),
|
||||
// padding: MaterialStateProperty.all<EdgeInsets>(
|
||||
// const EdgeInsets.symmetric(horizontal: 2)),
|
||||
// ),
|
||||
// onPressed: onPressed,
|
||||
// child: Text(
|
||||
// text,
|
||||
// overflow: TextOverflow.ellipsis,
|
||||
// softWrap: false,
|
||||
// ),
|
||||
// );
|
@ -1,7 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
|
||||
typedef HoverBuilder = Widget Function(BuildContext context, bool isHovering);
|
||||
typedef HoverBuilder = Widget Function(BuildContext context, bool onHover);
|
||||
|
||||
class MouseHoverBuilder extends StatefulWidget {
|
||||
final bool isClickable;
|
||||
@ -15,17 +15,17 @@ class MouseHoverBuilder extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _MouseHoverBuilderState extends State<MouseHoverBuilder> {
|
||||
bool isOver = false;
|
||||
bool _onHover = false;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MouseRegion(
|
||||
cursor: widget.isClickable ? SystemMouseCursors.click : SystemMouseCursors.basic,
|
||||
onEnter: (p) => setOver(true),
|
||||
onExit: (p) => setOver(false),
|
||||
child: widget.builder(context, isOver),
|
||||
onEnter: (p) => setOnHover(true),
|
||||
onExit: (p) => setOnHover(false),
|
||||
child: widget.builder(context, _onHover),
|
||||
);
|
||||
}
|
||||
|
||||
void setOver(bool value) => setState(() => isOver = value);
|
||||
void setOnHover(bool value) => setState(() => _onHover = value);
|
||||
}
|
||||
|
@ -1,33 +1,90 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class RoundedButton extends StatelessWidget {
|
||||
class RoundedTextButton extends StatelessWidget {
|
||||
final VoidCallback? press;
|
||||
final String? title;
|
||||
final Size? size;
|
||||
final double? width;
|
||||
final double? height;
|
||||
final BorderRadius borderRadius;
|
||||
final Color borderColor;
|
||||
final Color color;
|
||||
final Color textColor;
|
||||
final double fontSize;
|
||||
|
||||
const RoundedButton({
|
||||
const RoundedTextButton({
|
||||
Key? key,
|
||||
this.press,
|
||||
this.title,
|
||||
this.size,
|
||||
this.width,
|
||||
this.height,
|
||||
this.borderRadius = BorderRadius.zero,
|
||||
this.borderColor = Colors.transparent,
|
||||
this.color = Colors.transparent,
|
||||
this.textColor = Colors.white,
|
||||
this.fontSize = 16,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
minWidth: 100,
|
||||
maxWidth: size?.width ?? double.infinity,
|
||||
minHeight: 50,
|
||||
maxHeight: size?.height ?? double.infinity,
|
||||
minWidth: 10,
|
||||
maxWidth: width ?? double.infinity,
|
||||
minHeight: 10,
|
||||
maxHeight: height ?? 60,
|
||||
),
|
||||
child: Container(
|
||||
margin: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: TextButton(
|
||||
child: Text(title ?? ''),
|
||||
onPressed: press,
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: borderColor),
|
||||
borderRadius: borderRadius,
|
||||
color: color,
|
||||
),
|
||||
child: SizedBox.expand(
|
||||
child: TextButton(
|
||||
child: Text(
|
||||
title ?? '',
|
||||
style: TextStyle(color: textColor, fontSize: fontSize),
|
||||
),
|
||||
onPressed: press,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class RoundedImageButton extends StatelessWidget {
|
||||
final VoidCallback? press;
|
||||
final double size;
|
||||
final BorderRadius borderRadius;
|
||||
final Color borderColor;
|
||||
final Color color;
|
||||
final Widget child;
|
||||
|
||||
const RoundedImageButton({
|
||||
Key? key,
|
||||
this.press,
|
||||
required this.size,
|
||||
this.borderRadius = BorderRadius.zero,
|
||||
this.borderColor = Colors.transparent,
|
||||
this.color = Colors.transparent,
|
||||
required this.child,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SizedBox(
|
||||
width: size,
|
||||
height: size,
|
||||
child: TextButton(
|
||||
onPressed: press,
|
||||
style: ButtonStyle(
|
||||
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
|
||||
RoundedRectangleBorder(
|
||||
borderRadius: borderRadius,
|
||||
))),
|
||||
child: child,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,35 +1,96 @@
|
||||
import 'package:flowy_infra_ui/widget/rounded_button.dart';
|
||||
import 'package:flowy_infra_ui/widget/text_field_container.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flowy_infra/time/duration.dart';
|
||||
|
||||
class RoundedInputField extends StatelessWidget {
|
||||
// ignore: must_be_immutable
|
||||
class RoundedInputField extends StatefulWidget {
|
||||
final String? hintText;
|
||||
final IconData? icon;
|
||||
final bool obscureText;
|
||||
final Color normalBorderColor;
|
||||
final Color highlightBorderColor;
|
||||
final String errorText;
|
||||
final ValueChanged<String>? onChanged;
|
||||
late bool enableObscure;
|
||||
|
||||
const RoundedInputField({
|
||||
RoundedInputField({
|
||||
Key? key,
|
||||
this.hintText,
|
||||
this.icon = Icons.person,
|
||||
this.icon,
|
||||
this.obscureText = false,
|
||||
this.onChanged,
|
||||
}) : super(key: key);
|
||||
this.normalBorderColor = Colors.transparent,
|
||||
this.highlightBorderColor = Colors.transparent,
|
||||
this.errorText = "",
|
||||
}) : super(key: key) {
|
||||
enableObscure = obscureText;
|
||||
}
|
||||
|
||||
@override
|
||||
State<RoundedInputField> createState() => _RoundedInputFieldState();
|
||||
}
|
||||
|
||||
class _RoundedInputFieldState extends State<RoundedInputField> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return TextFieldContainer(
|
||||
final Icon? newIcon = widget.icon == null
|
||||
? null
|
||||
: Icon(
|
||||
widget.icon!,
|
||||
color: const Color(0xFF6F35A5),
|
||||
);
|
||||
|
||||
var borderColor = widget.normalBorderColor;
|
||||
if (widget.errorText.isNotEmpty) {
|
||||
borderColor = widget.highlightBorderColor;
|
||||
}
|
||||
|
||||
List<Widget> children = [
|
||||
TextFieldContainer(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
borderColor: borderColor,
|
||||
child: TextFormField(
|
||||
onChanged: onChanged,
|
||||
cursorColor: const Color(0xFF6F35A5),
|
||||
obscureText: obscureText,
|
||||
decoration: InputDecoration(
|
||||
icon: Icon(
|
||||
icon,
|
||||
color: const Color(0xFF6F35A5),
|
||||
onChanged: widget.onChanged,
|
||||
cursorColor: const Color(0xFF6F35A5),
|
||||
obscureText: widget.enableObscure,
|
||||
decoration: InputDecoration(
|
||||
icon: newIcon,
|
||||
hintText: widget.hintText,
|
||||
border: InputBorder.none,
|
||||
suffixIcon: suffixIcon(),
|
||||
),
|
||||
),
|
||||
hintText: hintText,
|
||||
border: InputBorder.none,
|
||||
),
|
||||
));
|
||||
];
|
||||
|
||||
if (widget.errorText.isNotEmpty) {
|
||||
children.add(Text(
|
||||
widget.errorText,
|
||||
style: TextStyle(color: widget.highlightBorderColor),
|
||||
));
|
||||
}
|
||||
|
||||
return AnimatedSize(
|
||||
duration: .4.seconds,
|
||||
curve: Curves.easeInOut,
|
||||
child: Column(
|
||||
children: children,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget? suffixIcon() {
|
||||
if (widget.obscureText == false) {
|
||||
return null;
|
||||
}
|
||||
return RoundedImageButton(
|
||||
size: 20,
|
||||
press: () {
|
||||
widget.enableObscure = !widget.enableObscure;
|
||||
setState(() {});
|
||||
},
|
||||
child: const Icon(Icons.password, size: 15),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -3,21 +3,32 @@ import 'package:flutter/material.dart';
|
||||
|
||||
class TextFieldContainer extends StatelessWidget {
|
||||
final Widget child;
|
||||
final BorderRadius borderRadius;
|
||||
final Color borderColor;
|
||||
final double? height;
|
||||
final double? width;
|
||||
const TextFieldContainer({
|
||||
Key? key,
|
||||
required this.child,
|
||||
this.borderRadius = BorderRadius.zero,
|
||||
this.borderColor = Colors.white,
|
||||
this.height,
|
||||
this.width,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
margin: const EdgeInsets.symmetric(vertical: 10),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 15),
|
||||
height: height,
|
||||
width: width,
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: borderColor),
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(30),
|
||||
borderRadius: borderRadius,
|
||||
),
|
||||
child: child,
|
||||
child: Align(alignment: Alignment.center, child: child),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,7 @@ packages:
|
||||
name: async
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.7.0"
|
||||
version: "2.6.1"
|
||||
boolean_selector:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -35,7 +35,7 @@ packages:
|
||||
name: charcode
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.3.1"
|
||||
version: "1.2.0"
|
||||
clock:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -142,6 +142,13 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
loading_indicator:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: loading_indicator
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.0.1"
|
||||
logger:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -162,7 +169,7 @@ packages:
|
||||
name: meta
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.7.0"
|
||||
version: "1.3.0"
|
||||
nested:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -244,7 +251,7 @@ packages:
|
||||
name: test_api
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.4.1"
|
||||
version: "0.3.0"
|
||||
textstyle_extensions:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -282,4 +289,4 @@ packages:
|
||||
version: "2.1.0"
|
||||
sdks:
|
||||
dart: ">=2.12.0 <3.0.0"
|
||||
flutter: ">=1.20.0"
|
||||
flutter: ">=2.0.0"
|
||||
|
@ -19,6 +19,7 @@ dependencies:
|
||||
styled_widget: '>=0.3.1'
|
||||
equatable: '>=2.0.2'
|
||||
animations: ^2.0.0
|
||||
loading_indicator: ^3.0.1
|
||||
|
||||
# Federated Platform Interface
|
||||
flowy_infra_ui_platform_interface:
|
||||
|
@ -118,6 +118,20 @@ class WorkspaceEventGetWorkspace {
|
||||
}
|
||||
}
|
||||
|
||||
class WorkspaceEventReadAllWorkspace {
|
||||
WorkspaceEventReadAllWorkspace();
|
||||
|
||||
Future<Either<Workspaces, WorkspaceError>> send() {
|
||||
final request = FFIRequest.create()
|
||||
..event = WorkspaceEvent.ReadAllWorkspace.toString();
|
||||
|
||||
return Dispatch.asyncRequest(request).then((bytesResult) => bytesResult.fold(
|
||||
(okBytes) => left(Workspaces.fromBuffer(okBytes)),
|
||||
(errBytes) => right(WorkspaceError.fromBuffer(errBytes)),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
class WorkspaceEventCreateApp {
|
||||
CreateAppRequest request;
|
||||
WorkspaceEventCreateApp(this.request);
|
||||
|
@ -15,14 +15,14 @@ export 'errors.pbenum.dart';
|
||||
|
||||
class UserError extends $pb.GeneratedMessage {
|
||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'UserError', createEmptyInstance: create)
|
||||
..e<UserErrorCode>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'code', $pb.PbFieldType.OE, defaultOrMaker: UserErrorCode.Unknown, valueOf: UserErrorCode.valueOf, enumValues: UserErrorCode.values)
|
||||
..e<UserErrCode>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'code', $pb.PbFieldType.OE, defaultOrMaker: UserErrCode.Unknown, valueOf: UserErrCode.valueOf, enumValues: UserErrCode.values)
|
||||
..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'msg')
|
||||
..hasRequiredFields = false
|
||||
;
|
||||
|
||||
UserError._() : super();
|
||||
factory UserError({
|
||||
UserErrorCode? code,
|
||||
UserErrCode? code,
|
||||
$core.String? msg,
|
||||
}) {
|
||||
final _result = create();
|
||||
@ -56,9 +56,9 @@ class UserError extends $pb.GeneratedMessage {
|
||||
static UserError? _defaultInstance;
|
||||
|
||||
@$pb.TagNumber(1)
|
||||
UserErrorCode get code => $_getN(0);
|
||||
UserErrCode get code => $_getN(0);
|
||||
@$pb.TagNumber(1)
|
||||
set code(UserErrorCode v) { setField(1, v); }
|
||||
set code(UserErrCode v) { setField(1, v); }
|
||||
@$pb.TagNumber(1)
|
||||
$core.bool hasCode() => $_has(0);
|
||||
@$pb.TagNumber(1)
|
||||
|
@ -9,26 +9,26 @@
|
||||
import 'dart:core' as $core;
|
||||
import 'package:protobuf/protobuf.dart' as $pb;
|
||||
|
||||
class UserErrorCode extends $pb.ProtobufEnum {
|
||||
static const UserErrorCode Unknown = UserErrorCode._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Unknown');
|
||||
static const UserErrorCode UserDatabaseInitFailed = UserErrorCode._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserDatabaseInitFailed');
|
||||
static const UserErrorCode UserDatabaseWriteLocked = UserErrorCode._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserDatabaseWriteLocked');
|
||||
static const UserErrorCode UserDatabaseReadLocked = UserErrorCode._(3, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserDatabaseReadLocked');
|
||||
static const UserErrorCode UserDatabaseDidNotMatch = UserErrorCode._(4, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserDatabaseDidNotMatch');
|
||||
static const UserErrorCode UserDatabaseInternalError = UserErrorCode._(5, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserDatabaseInternalError');
|
||||
static const UserErrorCode SqlInternalError = UserErrorCode._(6, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'SqlInternalError');
|
||||
static const UserErrorCode UserNotLoginYet = UserErrorCode._(10, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserNotLoginYet');
|
||||
static const UserErrorCode ReadCurrentIdFailed = UserErrorCode._(11, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ReadCurrentIdFailed');
|
||||
static const UserErrorCode WriteCurrentIdFailed = UserErrorCode._(12, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'WriteCurrentIdFailed');
|
||||
static const UserErrorCode EmailInvalid = UserErrorCode._(20, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'EmailInvalid');
|
||||
static const UserErrorCode PasswordInvalid = UserErrorCode._(21, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'PasswordInvalid');
|
||||
static const UserErrorCode UserNameInvalid = UserErrorCode._(22, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserNameInvalid');
|
||||
static const UserErrorCode UserWorkspaceInvalid = UserErrorCode._(23, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserWorkspaceInvalid');
|
||||
static const UserErrorCode UserIdInvalid = UserErrorCode._(24, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserIdInvalid');
|
||||
static const UserErrorCode CreateDefaultWorkspaceFailed = UserErrorCode._(25, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateDefaultWorkspaceFailed');
|
||||
static const UserErrorCode DefaultWorkspaceAlreadyExist = UserErrorCode._(26, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DefaultWorkspaceAlreadyExist');
|
||||
class UserErrCode extends $pb.ProtobufEnum {
|
||||
static const UserErrCode Unknown = UserErrCode._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Unknown');
|
||||
static const UserErrCode UserDatabaseInitFailed = UserErrCode._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserDatabaseInitFailed');
|
||||
static const UserErrCode UserDatabaseWriteLocked = UserErrCode._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserDatabaseWriteLocked');
|
||||
static const UserErrCode UserDatabaseReadLocked = UserErrCode._(3, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserDatabaseReadLocked');
|
||||
static const UserErrCode UserDatabaseDidNotMatch = UserErrCode._(4, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserDatabaseDidNotMatch');
|
||||
static const UserErrCode UserDatabaseInternalError = UserErrCode._(5, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserDatabaseInternalError');
|
||||
static const UserErrCode SqlInternalError = UserErrCode._(6, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'SqlInternalError');
|
||||
static const UserErrCode UserNotLoginYet = UserErrCode._(10, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserNotLoginYet');
|
||||
static const UserErrCode ReadCurrentIdFailed = UserErrCode._(11, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ReadCurrentIdFailed');
|
||||
static const UserErrCode WriteCurrentIdFailed = UserErrCode._(12, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'WriteCurrentIdFailed');
|
||||
static const UserErrCode EmailInvalid = UserErrCode._(20, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'EmailInvalid');
|
||||
static const UserErrCode PasswordInvalid = UserErrCode._(21, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'PasswordInvalid');
|
||||
static const UserErrCode UserNameInvalid = UserErrCode._(22, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserNameInvalid');
|
||||
static const UserErrCode UserWorkspaceInvalid = UserErrCode._(23, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserWorkspaceInvalid');
|
||||
static const UserErrCode UserIdInvalid = UserErrCode._(24, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserIdInvalid');
|
||||
static const UserErrCode CreateDefaultWorkspaceFailed = UserErrCode._(25, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateDefaultWorkspaceFailed');
|
||||
static const UserErrCode DefaultWorkspaceAlreadyExist = UserErrCode._(26, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DefaultWorkspaceAlreadyExist');
|
||||
|
||||
static const $core.List<UserErrorCode> values = <UserErrorCode> [
|
||||
static const $core.List<UserErrCode> values = <UserErrCode> [
|
||||
Unknown,
|
||||
UserDatabaseInitFailed,
|
||||
UserDatabaseWriteLocked,
|
||||
@ -48,9 +48,9 @@ class UserErrorCode extends $pb.ProtobufEnum {
|
||||
DefaultWorkspaceAlreadyExist,
|
||||
];
|
||||
|
||||
static final $core.Map<$core.int, UserErrorCode> _byValue = $pb.ProtobufEnum.initByValue(values);
|
||||
static UserErrorCode? valueOf($core.int value) => _byValue[value];
|
||||
static final $core.Map<$core.int, UserErrCode> _byValue = $pb.ProtobufEnum.initByValue(values);
|
||||
static UserErrCode? valueOf($core.int value) => _byValue[value];
|
||||
|
||||
const UserErrorCode._($core.int v, $core.String n) : super(v, n);
|
||||
const UserErrCode._($core.int v, $core.String n) : super(v, n);
|
||||
}
|
||||
|
||||
|
@ -8,9 +8,9 @@
|
||||
import 'dart:core' as $core;
|
||||
import 'dart:convert' as $convert;
|
||||
import 'dart:typed_data' as $typed_data;
|
||||
@$core.Deprecated('Use userErrorCodeDescriptor instead')
|
||||
const UserErrorCode$json = const {
|
||||
'1': 'UserErrorCode',
|
||||
@$core.Deprecated('Use userErrCodeDescriptor instead')
|
||||
const UserErrCode$json = const {
|
||||
'1': 'UserErrCode',
|
||||
'2': const [
|
||||
const {'1': 'Unknown', '2': 0},
|
||||
const {'1': 'UserDatabaseInitFailed', '2': 1},
|
||||
@ -32,16 +32,16 @@ const UserErrorCode$json = const {
|
||||
],
|
||||
};
|
||||
|
||||
/// Descriptor for `UserErrorCode`. Decode as a `google.protobuf.EnumDescriptorProto`.
|
||||
final $typed_data.Uint8List userErrorCodeDescriptor = $convert.base64Decode('Cg1Vc2VyRXJyb3JDb2RlEgsKB1Vua25vd24QABIaChZVc2VyRGF0YWJhc2VJbml0RmFpbGVkEAESGwoXVXNlckRhdGFiYXNlV3JpdGVMb2NrZWQQAhIaChZVc2VyRGF0YWJhc2VSZWFkTG9ja2VkEAMSGwoXVXNlckRhdGFiYXNlRGlkTm90TWF0Y2gQBBIdChlVc2VyRGF0YWJhc2VJbnRlcm5hbEVycm9yEAUSFAoQU3FsSW50ZXJuYWxFcnJvchAGEhMKD1VzZXJOb3RMb2dpbllldBAKEhcKE1JlYWRDdXJyZW50SWRGYWlsZWQQCxIYChRXcml0ZUN1cnJlbnRJZEZhaWxlZBAMEhAKDEVtYWlsSW52YWxpZBAUEhMKD1Bhc3N3b3JkSW52YWxpZBAVEhMKD1VzZXJOYW1lSW52YWxpZBAWEhgKFFVzZXJXb3Jrc3BhY2VJbnZhbGlkEBcSEQoNVXNlcklkSW52YWxpZBAYEiAKHENyZWF0ZURlZmF1bHRXb3Jrc3BhY2VGYWlsZWQQGRIgChxEZWZhdWx0V29ya3NwYWNlQWxyZWFkeUV4aXN0EBo=');
|
||||
/// Descriptor for `UserErrCode`. Decode as a `google.protobuf.EnumDescriptorProto`.
|
||||
final $typed_data.Uint8List userErrCodeDescriptor = $convert.base64Decode('CgtVc2VyRXJyQ29kZRILCgdVbmtub3duEAASGgoWVXNlckRhdGFiYXNlSW5pdEZhaWxlZBABEhsKF1VzZXJEYXRhYmFzZVdyaXRlTG9ja2VkEAISGgoWVXNlckRhdGFiYXNlUmVhZExvY2tlZBADEhsKF1VzZXJEYXRhYmFzZURpZE5vdE1hdGNoEAQSHQoZVXNlckRhdGFiYXNlSW50ZXJuYWxFcnJvchAFEhQKEFNxbEludGVybmFsRXJyb3IQBhITCg9Vc2VyTm90TG9naW5ZZXQQChIXChNSZWFkQ3VycmVudElkRmFpbGVkEAsSGAoUV3JpdGVDdXJyZW50SWRGYWlsZWQQDBIQCgxFbWFpbEludmFsaWQQFBITCg9QYXNzd29yZEludmFsaWQQFRITCg9Vc2VyTmFtZUludmFsaWQQFhIYChRVc2VyV29ya3NwYWNlSW52YWxpZBAXEhEKDVVzZXJJZEludmFsaWQQGBIgChxDcmVhdGVEZWZhdWx0V29ya3NwYWNlRmFpbGVkEBkSIAocRGVmYXVsdFdvcmtzcGFjZUFscmVhZHlFeGlzdBAa');
|
||||
@$core.Deprecated('Use userErrorDescriptor instead')
|
||||
const UserError$json = const {
|
||||
'1': 'UserError',
|
||||
'2': const [
|
||||
const {'1': 'code', '3': 1, '4': 1, '5': 14, '6': '.UserErrorCode', '10': 'code'},
|
||||
const {'1': 'code', '3': 1, '4': 1, '5': 14, '6': '.UserErrCode', '10': 'code'},
|
||||
const {'1': 'msg', '3': 2, '4': 1, '5': 9, '10': 'msg'},
|
||||
],
|
||||
};
|
||||
|
||||
/// Descriptor for `UserError`. Decode as a `google.protobuf.DescriptorProto`.
|
||||
final $typed_data.Uint8List userErrorDescriptor = $convert.base64Decode('CglVc2VyRXJyb3ISIgoEY29kZRgBIAEoDjIOLlVzZXJFcnJvckNvZGVSBGNvZGUSEAoDbXNnGAIgASgJUgNtc2c=');
|
||||
final $typed_data.Uint8List userErrorDescriptor = $convert.base64Decode('CglVc2VyRXJyb3ISIAoEY29kZRgBIAEoDjIMLlVzZXJFcnJDb2RlUgRjb2RlEhAKA21zZxgCIAEoCVIDbXNn');
|
||||
|
@ -15,14 +15,14 @@ export 'errors.pbenum.dart';
|
||||
|
||||
class WorkspaceError extends $pb.GeneratedMessage {
|
||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'WorkspaceError', createEmptyInstance: create)
|
||||
..e<WorkspaceErrorCode>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'code', $pb.PbFieldType.OE, defaultOrMaker: WorkspaceErrorCode.Unknown, valueOf: WorkspaceErrorCode.valueOf, enumValues: WorkspaceErrorCode.values)
|
||||
..e<WsErrCode>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'code', $pb.PbFieldType.OE, defaultOrMaker: WsErrCode.Unknown, valueOf: WsErrCode.valueOf, enumValues: WsErrCode.values)
|
||||
..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'msg')
|
||||
..hasRequiredFields = false
|
||||
;
|
||||
|
||||
WorkspaceError._() : super();
|
||||
factory WorkspaceError({
|
||||
WorkspaceErrorCode? code,
|
||||
WsErrCode? code,
|
||||
$core.String? msg,
|
||||
}) {
|
||||
final _result = create();
|
||||
@ -56,9 +56,9 @@ class WorkspaceError extends $pb.GeneratedMessage {
|
||||
static WorkspaceError? _defaultInstance;
|
||||
|
||||
@$pb.TagNumber(1)
|
||||
WorkspaceErrorCode get code => $_getN(0);
|
||||
WsErrCode get code => $_getN(0);
|
||||
@$pb.TagNumber(1)
|
||||
set code(WorkspaceErrorCode v) { setField(1, v); }
|
||||
set code(WsErrCode v) { setField(1, v); }
|
||||
@$pb.TagNumber(1)
|
||||
$core.bool hasCode() => $_has(0);
|
||||
@$pb.TagNumber(1)
|
||||
|
@ -9,23 +9,23 @@
|
||||
import 'dart:core' as $core;
|
||||
import 'package:protobuf/protobuf.dart' as $pb;
|
||||
|
||||
class WorkspaceErrorCode extends $pb.ProtobufEnum {
|
||||
static const WorkspaceErrorCode Unknown = WorkspaceErrorCode._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Unknown');
|
||||
static const WorkspaceErrorCode WorkspaceNameInvalid = WorkspaceErrorCode._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'WorkspaceNameInvalid');
|
||||
static const WorkspaceErrorCode WorkspaceIdInvalid = WorkspaceErrorCode._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'WorkspaceIdInvalid');
|
||||
static const WorkspaceErrorCode AppColorStyleInvalid = WorkspaceErrorCode._(3, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'AppColorStyleInvalid');
|
||||
static const WorkspaceErrorCode AppIdInvalid = WorkspaceErrorCode._(10, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'AppIdInvalid');
|
||||
static const WorkspaceErrorCode AppNameInvalid = WorkspaceErrorCode._(11, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'AppNameInvalid');
|
||||
static const WorkspaceErrorCode ViewNameInvalid = WorkspaceErrorCode._(20, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ViewNameInvalid');
|
||||
static const WorkspaceErrorCode ViewThumbnailInvalid = WorkspaceErrorCode._(21, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ViewThumbnailInvalid');
|
||||
static const WorkspaceErrorCode ViewIdInvalid = WorkspaceErrorCode._(22, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ViewIdInvalid');
|
||||
static const WorkspaceErrorCode ViewDescInvalid = WorkspaceErrorCode._(23, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ViewDescInvalid');
|
||||
static const WorkspaceErrorCode DatabaseConnectionFail = WorkspaceErrorCode._(100, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DatabaseConnectionFail');
|
||||
static const WorkspaceErrorCode WorkspaceDatabaseError = WorkspaceErrorCode._(101, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'WorkspaceDatabaseError');
|
||||
static const WorkspaceErrorCode UserInternalError = WorkspaceErrorCode._(102, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserInternalError');
|
||||
static const WorkspaceErrorCode UserNotLoginYet = WorkspaceErrorCode._(103, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserNotLoginYet');
|
||||
class WsErrCode extends $pb.ProtobufEnum {
|
||||
static const WsErrCode Unknown = WsErrCode._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Unknown');
|
||||
static const WsErrCode WorkspaceNameInvalid = WsErrCode._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'WorkspaceNameInvalid');
|
||||
static const WsErrCode WorkspaceIdInvalid = WsErrCode._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'WorkspaceIdInvalid');
|
||||
static const WsErrCode AppColorStyleInvalid = WsErrCode._(3, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'AppColorStyleInvalid');
|
||||
static const WsErrCode AppIdInvalid = WsErrCode._(10, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'AppIdInvalid');
|
||||
static const WsErrCode AppNameInvalid = WsErrCode._(11, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'AppNameInvalid');
|
||||
static const WsErrCode ViewNameInvalid = WsErrCode._(20, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ViewNameInvalid');
|
||||
static const WsErrCode ViewThumbnailInvalid = WsErrCode._(21, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ViewThumbnailInvalid');
|
||||
static const WsErrCode ViewIdInvalid = WsErrCode._(22, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ViewIdInvalid');
|
||||
static const WsErrCode ViewDescInvalid = WsErrCode._(23, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ViewDescInvalid');
|
||||
static const WsErrCode DatabaseConnectionFail = WsErrCode._(100, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DatabaseConnectionFail');
|
||||
static const WsErrCode WorkspaceDatabaseError = WsErrCode._(101, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'WorkspaceDatabaseError');
|
||||
static const WsErrCode UserInternalError = WsErrCode._(102, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserInternalError');
|
||||
static const WsErrCode UserNotLoginYet = WsErrCode._(103, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UserNotLoginYet');
|
||||
|
||||
static const $core.List<WorkspaceErrorCode> values = <WorkspaceErrorCode> [
|
||||
static const $core.List<WsErrCode> values = <WsErrCode> [
|
||||
Unknown,
|
||||
WorkspaceNameInvalid,
|
||||
WorkspaceIdInvalid,
|
||||
@ -42,9 +42,9 @@ class WorkspaceErrorCode extends $pb.ProtobufEnum {
|
||||
UserNotLoginYet,
|
||||
];
|
||||
|
||||
static final $core.Map<$core.int, WorkspaceErrorCode> _byValue = $pb.ProtobufEnum.initByValue(values);
|
||||
static WorkspaceErrorCode? valueOf($core.int value) => _byValue[value];
|
||||
static final $core.Map<$core.int, WsErrCode> _byValue = $pb.ProtobufEnum.initByValue(values);
|
||||
static WsErrCode? valueOf($core.int value) => _byValue[value];
|
||||
|
||||
const WorkspaceErrorCode._($core.int v, $core.String n) : super(v, n);
|
||||
const WsErrCode._($core.int v, $core.String n) : super(v, n);
|
||||
}
|
||||
|
||||
|
@ -8,9 +8,9 @@
|
||||
import 'dart:core' as $core;
|
||||
import 'dart:convert' as $convert;
|
||||
import 'dart:typed_data' as $typed_data;
|
||||
@$core.Deprecated('Use workspaceErrorCodeDescriptor instead')
|
||||
const WorkspaceErrorCode$json = const {
|
||||
'1': 'WorkspaceErrorCode',
|
||||
@$core.Deprecated('Use wsErrCodeDescriptor instead')
|
||||
const WsErrCode$json = const {
|
||||
'1': 'WsErrCode',
|
||||
'2': const [
|
||||
const {'1': 'Unknown', '2': 0},
|
||||
const {'1': 'WorkspaceNameInvalid', '2': 1},
|
||||
@ -29,16 +29,16 @@ const WorkspaceErrorCode$json = const {
|
||||
],
|
||||
};
|
||||
|
||||
/// Descriptor for `WorkspaceErrorCode`. Decode as a `google.protobuf.EnumDescriptorProto`.
|
||||
final $typed_data.Uint8List workspaceErrorCodeDescriptor = $convert.base64Decode('ChJXb3Jrc3BhY2VFcnJvckNvZGUSCwoHVW5rbm93bhAAEhgKFFdvcmtzcGFjZU5hbWVJbnZhbGlkEAESFgoSV29ya3NwYWNlSWRJbnZhbGlkEAISGAoUQXBwQ29sb3JTdHlsZUludmFsaWQQAxIQCgxBcHBJZEludmFsaWQQChISCg5BcHBOYW1lSW52YWxpZBALEhMKD1ZpZXdOYW1lSW52YWxpZBAUEhgKFFZpZXdUaHVtYm5haWxJbnZhbGlkEBUSEQoNVmlld0lkSW52YWxpZBAWEhMKD1ZpZXdEZXNjSW52YWxpZBAXEhoKFkRhdGFiYXNlQ29ubmVjdGlvbkZhaWwQZBIaChZXb3Jrc3BhY2VEYXRhYmFzZUVycm9yEGUSFQoRVXNlckludGVybmFsRXJyb3IQZhITCg9Vc2VyTm90TG9naW5ZZXQQZw==');
|
||||
/// Descriptor for `WsErrCode`. Decode as a `google.protobuf.EnumDescriptorProto`.
|
||||
final $typed_data.Uint8List wsErrCodeDescriptor = $convert.base64Decode('CglXc0VyckNvZGUSCwoHVW5rbm93bhAAEhgKFFdvcmtzcGFjZU5hbWVJbnZhbGlkEAESFgoSV29ya3NwYWNlSWRJbnZhbGlkEAISGAoUQXBwQ29sb3JTdHlsZUludmFsaWQQAxIQCgxBcHBJZEludmFsaWQQChISCg5BcHBOYW1lSW52YWxpZBALEhMKD1ZpZXdOYW1lSW52YWxpZBAUEhgKFFZpZXdUaHVtYm5haWxJbnZhbGlkEBUSEQoNVmlld0lkSW52YWxpZBAWEhMKD1ZpZXdEZXNjSW52YWxpZBAXEhoKFkRhdGFiYXNlQ29ubmVjdGlvbkZhaWwQZBIaChZXb3Jrc3BhY2VEYXRhYmFzZUVycm9yEGUSFQoRVXNlckludGVybmFsRXJyb3IQZhITCg9Vc2VyTm90TG9naW5ZZXQQZw==');
|
||||
@$core.Deprecated('Use workspaceErrorDescriptor instead')
|
||||
const WorkspaceError$json = const {
|
||||
'1': 'WorkspaceError',
|
||||
'2': const [
|
||||
const {'1': 'code', '3': 1, '4': 1, '5': 14, '6': '.WorkspaceErrorCode', '10': 'code'},
|
||||
const {'1': 'code', '3': 1, '4': 1, '5': 14, '6': '.WsErrCode', '10': 'code'},
|
||||
const {'1': 'msg', '3': 2, '4': 1, '5': 9, '10': 'msg'},
|
||||
],
|
||||
};
|
||||
|
||||
/// Descriptor for `WorkspaceError`. Decode as a `google.protobuf.DescriptorProto`.
|
||||
final $typed_data.Uint8List workspaceErrorDescriptor = $convert.base64Decode('Cg5Xb3Jrc3BhY2VFcnJvchInCgRjb2RlGAEgASgOMhMuV29ya3NwYWNlRXJyb3JDb2RlUgRjb2RlEhAKA21zZxgCIAEoCVIDbXNn');
|
||||
final $typed_data.Uint8List workspaceErrorDescriptor = $convert.base64Decode('Cg5Xb3Jrc3BhY2VFcnJvchIeCgRjb2RlGAEgASgOMgouV3NFcnJDb2RlUgRjb2RlEhAKA21zZxgCIAEoCVIDbXNn');
|
||||
|
@ -13,6 +13,7 @@ class WorkspaceEvent extends $pb.ProtobufEnum {
|
||||
static const WorkspaceEvent CreateWorkspace = WorkspaceEvent._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateWorkspace');
|
||||
static const WorkspaceEvent GetCurWorkspace = WorkspaceEvent._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetCurWorkspace');
|
||||
static const WorkspaceEvent GetWorkspace = WorkspaceEvent._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetWorkspace');
|
||||
static const WorkspaceEvent ReadAllWorkspace = WorkspaceEvent._(3, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ReadAllWorkspace');
|
||||
static const WorkspaceEvent CreateApp = WorkspaceEvent._(101, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateApp');
|
||||
static const WorkspaceEvent GetApp = WorkspaceEvent._(102, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetApp');
|
||||
static const WorkspaceEvent CreateView = WorkspaceEvent._(201, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateView');
|
||||
@ -23,6 +24,7 @@ class WorkspaceEvent extends $pb.ProtobufEnum {
|
||||
CreateWorkspace,
|
||||
GetCurWorkspace,
|
||||
GetWorkspace,
|
||||
ReadAllWorkspace,
|
||||
CreateApp,
|
||||
GetApp,
|
||||
CreateView,
|
||||
|
@ -15,6 +15,7 @@ const WorkspaceEvent$json = const {
|
||||
const {'1': 'CreateWorkspace', '2': 0},
|
||||
const {'1': 'GetCurWorkspace', '2': 1},
|
||||
const {'1': 'GetWorkspace', '2': 2},
|
||||
const {'1': 'ReadAllWorkspace', '2': 3},
|
||||
const {'1': 'CreateApp', '2': 101},
|
||||
const {'1': 'GetApp', '2': 102},
|
||||
const {'1': 'CreateView', '2': 201},
|
||||
@ -24,4 +25,4 @@ const WorkspaceEvent$json = const {
|
||||
};
|
||||
|
||||
/// Descriptor for `WorkspaceEvent`. Decode as a `google.protobuf.EnumDescriptorProto`.
|
||||
final $typed_data.Uint8List workspaceEventDescriptor = $convert.base64Decode('Cg5Xb3Jrc3BhY2VFdmVudBITCg9DcmVhdGVXb3Jrc3BhY2UQABITCg9HZXRDdXJXb3Jrc3BhY2UQARIQCgxHZXRXb3Jrc3BhY2UQAhINCglDcmVhdGVBcHAQZRIKCgZHZXRBcHAQZhIPCgpDcmVhdGVWaWV3EMkBEg0KCFJlYWRWaWV3EMoBEg8KClVwZGF0ZVZpZXcQywE=');
|
||||
final $typed_data.Uint8List workspaceEventDescriptor = $convert.base64Decode('Cg5Xb3Jrc3BhY2VFdmVudBITCg9DcmVhdGVXb3Jrc3BhY2UQABITCg9HZXRDdXJXb3Jrc3BhY2UQARIQCgxHZXRXb3Jrc3BhY2UQAhIUChBSZWFkQWxsV29ya3NwYWNlEAMSDQoJQ3JlYXRlQXBwEGUSCgoGR2V0QXBwEGYSDwoKQ3JlYXRlVmlldxDJARINCghSZWFkVmlldxDKARIPCgpVcGRhdGVWaWV3EMsB');
|
||||
|
@ -10,17 +10,25 @@ import 'dart:core' as $core;
|
||||
import 'package:protobuf/protobuf.dart' as $pb;
|
||||
|
||||
class ViewType extends $pb.ProtobufEnum {
|
||||
static const ViewType Blank = ViewType._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Blank');
|
||||
static const ViewType Doc = ViewType._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Doc');
|
||||
static const ViewType Blank = ViewType._(
|
||||
0,
|
||||
const $core.bool.fromEnvironment('protobuf.omit_enum_names')
|
||||
? ''
|
||||
: 'Blank');
|
||||
static const ViewType Doc = ViewType._(
|
||||
1,
|
||||
const $core.bool.fromEnvironment('protobuf.omit_enum_names')
|
||||
? ''
|
||||
: 'Doc');
|
||||
|
||||
static const $core.List<ViewType> values = <ViewType> [
|
||||
static const $core.List<ViewType> values = <ViewType>[
|
||||
Blank,
|
||||
Doc,
|
||||
];
|
||||
|
||||
static final $core.Map<$core.int, ViewType> _byValue = $pb.ProtobufEnum.initByValue(values);
|
||||
static final $core.Map<$core.int, ViewType> _byValue =
|
||||
$pb.ProtobufEnum.initByValue(values);
|
||||
static ViewType? valueOf($core.int value) => _byValue[value];
|
||||
|
||||
const ViewType._($core.int v, $core.String n) : super(v, n);
|
||||
}
|
||||
|
||||
|
@ -163,3 +163,44 @@ class Workspace extends $pb.GeneratedMessage {
|
||||
$0.RepeatedApp ensureApps() => $_ensure(3);
|
||||
}
|
||||
|
||||
class Workspaces extends $pb.GeneratedMessage {
|
||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'Workspaces', createEmptyInstance: create)
|
||||
..pc<Workspace>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'items', $pb.PbFieldType.PM, subBuilder: Workspace.create)
|
||||
..hasRequiredFields = false
|
||||
;
|
||||
|
||||
Workspaces._() : super();
|
||||
factory Workspaces({
|
||||
$core.Iterable<Workspace>? items,
|
||||
}) {
|
||||
final _result = create();
|
||||
if (items != null) {
|
||||
_result.items.addAll(items);
|
||||
}
|
||||
return _result;
|
||||
}
|
||||
factory Workspaces.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
|
||||
factory Workspaces.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
|
||||
'Will be removed in next major version')
|
||||
Workspaces clone() => Workspaces()..mergeFromMessage(this);
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
|
||||
'Will be removed in next major version')
|
||||
Workspaces copyWith(void Function(Workspaces) updates) => super.copyWith((message) => updates(message as Workspaces)) as Workspaces; // ignore: deprecated_member_use
|
||||
$pb.BuilderInfo get info_ => _i;
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static Workspaces create() => Workspaces._();
|
||||
Workspaces createEmptyInstance() => create();
|
||||
static $pb.PbList<Workspaces> createRepeated() => $pb.PbList<Workspaces>();
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static Workspaces getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<Workspaces>(create);
|
||||
static Workspaces? _defaultInstance;
|
||||
|
||||
@$pb.TagNumber(1)
|
||||
$core.List<Workspace> get items => $_getList(0);
|
||||
}
|
||||
|
||||
|
@ -32,3 +32,13 @@ const Workspace$json = const {
|
||||
|
||||
/// Descriptor for `Workspace`. Decode as a `google.protobuf.DescriptorProto`.
|
||||
final $typed_data.Uint8List workspaceDescriptor = $convert.base64Decode('CglXb3Jrc3BhY2USDgoCaWQYASABKAlSAmlkEhIKBG5hbWUYAiABKAlSBG5hbWUSEgoEZGVzYxgDIAEoCVIEZGVzYxIgCgRhcHBzGAQgASgLMgwuUmVwZWF0ZWRBcHBSBGFwcHM=');
|
||||
@$core.Deprecated('Use workspacesDescriptor instead')
|
||||
const Workspaces$json = const {
|
||||
'1': 'Workspaces',
|
||||
'2': const [
|
||||
const {'1': 'items', '3': 1, '4': 3, '5': 11, '6': '.Workspace', '10': 'items'},
|
||||
],
|
||||
};
|
||||
|
||||
/// Descriptor for `Workspaces`. Decode as a `google.protobuf.DescriptorProto`.
|
||||
final $typed_data.Uint8List workspacesDescriptor = $convert.base64Decode('CgpXb3Jrc3BhY2VzEiAKBWl0ZW1zGAEgAygLMgouV29ya3NwYWNlUgVpdGVtcw==');
|
||||
|
@ -5,231 +5,231 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: _fe_analyzer_shared
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "22.0.0"
|
||||
version: "23.0.0"
|
||||
analyzer:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: analyzer
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.7.1"
|
||||
version: "2.0.0"
|
||||
animations:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: animations
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
args:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: args
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
version: "2.2.0"
|
||||
async:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: async
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.6.1"
|
||||
version: "2.7.0"
|
||||
bloc:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: bloc
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "7.0.0"
|
||||
boolean_selector:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: boolean_selector
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
build:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: build
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.0.3"
|
||||
build_config:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: build_config
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
build_daemon:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: build_daemon
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "3.0.0"
|
||||
build_resolvers:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: build_resolvers
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.0.4"
|
||||
build_runner:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: build_runner
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.0.6"
|
||||
build_runner_core:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: build_runner_core
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "7.0.1"
|
||||
built_collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: built_collection
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "5.1.0"
|
||||
built_value:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: built_value
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "8.1.1"
|
||||
characters:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: characters
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
charcode:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: charcode
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
version: "1.3.1"
|
||||
checked_yaml:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: checked_yaml
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
cli_util:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: cli_util
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "0.3.3"
|
||||
clock:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: clock
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
code_builder:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: code_builder
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "4.0.0"
|
||||
version: "4.1.0"
|
||||
collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: collection
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.15.0"
|
||||
convert:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: convert
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "3.0.1"
|
||||
crypto:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: crypto
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "3.0.1"
|
||||
cupertino_icons:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: cupertino_icons
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.0.3"
|
||||
dart_style:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: dart_style
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.0.2"
|
||||
version: "2.0.3"
|
||||
dartz:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: dartz
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "0.10.0-nullsafety.2"
|
||||
equatable:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: equatable
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.0.3"
|
||||
expandable:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: expandable
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "5.0.1"
|
||||
fake_async:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: fake_async
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
ffi:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: ffi
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.1.2"
|
||||
file:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "6.1.2"
|
||||
fixnum:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: fixnum
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
flowy_editor:
|
||||
@ -283,42 +283,42 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_bloc
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "7.0.1"
|
||||
flutter_colorpicker:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_colorpicker
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "0.5.0"
|
||||
flutter_keyboard_visibility:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_keyboard_visibility
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "5.0.2"
|
||||
version: "5.0.3"
|
||||
flutter_keyboard_visibility_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_keyboard_visibility_platform_interface
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
flutter_keyboard_visibility_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_keyboard_visibility_web
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
flutter_lints:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: flutter_lints
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
flutter_test:
|
||||
@ -335,196 +335,203 @@ packages:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: freezed
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "0.14.2"
|
||||
version: "0.14.3"
|
||||
freezed_annotation:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: freezed_annotation
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "0.14.2"
|
||||
version: "0.14.3"
|
||||
frontend_server_client:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: frontend_server_client
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
get_it:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: get_it
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "7.2.0"
|
||||
glob:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: glob
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
graphs:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: graphs
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
http_multi_server:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: http_multi_server
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "3.0.1"
|
||||
http_parser:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: http_parser
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "4.0.0"
|
||||
io:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: io
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.0.3"
|
||||
isolates:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: isolates
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "3.0.3+8"
|
||||
js:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: js
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "0.6.3"
|
||||
json_annotation:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: json_annotation
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "4.0.1"
|
||||
version: "4.1.0"
|
||||
lint:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: lint
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.5.3"
|
||||
lints:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: lints
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
loading_indicator:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: loading_indicator
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "3.0.1"
|
||||
logger:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: logger
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
logging:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: logging
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
matcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: matcher
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "0.12.10"
|
||||
meta:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.3.0"
|
||||
version: "1.7.0"
|
||||
mime:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: mime
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
nested:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: nested
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
package_config:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: package_config
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
path:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.8.0"
|
||||
path_provider:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: path_provider
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.0.2"
|
||||
path_provider_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_linux
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
path_provider_macos:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_macos
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
path_provider_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_platform_interface
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
path_provider_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_windows
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
pedantic:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pedantic
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.11.1"
|
||||
photo_view:
|
||||
@ -540,91 +547,91 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: platform
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "3.0.0"
|
||||
plugin_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: plugin_platform_interface
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
pool:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pool
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.5.0"
|
||||
process:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: process
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "4.2.1"
|
||||
version: "4.2.3"
|
||||
protobuf:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: protobuf
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
provider:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: provider
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "5.0.0"
|
||||
pub_semver:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pub_semver
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
pubspec_parse:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pubspec_parse
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
quiver:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: quiver
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "3.0.1"
|
||||
quiver_hashcode:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: quiver_hashcode
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
shelf:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shelf
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
shelf_web_socket:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shelf_web_socket
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
sized_context:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: sized_context
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.0.0+1"
|
||||
sky_engine:
|
||||
@ -636,189 +643,189 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: source_gen
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.0.3"
|
||||
version: "1.0.5"
|
||||
source_span:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: source_span
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.8.1"
|
||||
stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stack_trace
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.10.0"
|
||||
stream_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stream_channel
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
stream_transform:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stream_transform
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
string_scanner:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: string_scanner
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
string_validator:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: string_validator
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "0.3.0"
|
||||
styled_widget:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: styled_widget
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "0.3.1+2"
|
||||
term_glyph:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: term_glyph
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
test_api:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "0.3.0"
|
||||
version: "0.4.1"
|
||||
textstyle_extensions:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: textstyle_extensions
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.0.0-nullsafety"
|
||||
time:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: time
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
timing:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: timing
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
tuple:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: tuple
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: typed_data
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.3.0"
|
||||
universal_platform:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: universal_platform
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.0.0+1"
|
||||
url_launcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "6.0.9"
|
||||
url_launcher_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_linux
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
url_launcher_macos:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_macos
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
url_launcher_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_platform_interface
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.0.4"
|
||||
url_launcher_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_web
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
url_launcher_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_windows
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
uuid:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: uuid
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "3.0.4"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vector_math
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
watcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: watcher
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
web_socket_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web_socket_channel
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
win32:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: win32
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "2.2.5"
|
||||
window_size:
|
||||
@ -834,14 +841,14 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: xdg_directories
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "0.2.0"
|
||||
yaml:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: yaml
|
||||
url: "https://pub.dartlang.org"
|
||||
url: "https://pub.flutter-io.cn"
|
||||
source: hosted
|
||||
version: "3.1.0"
|
||||
sdks:
|
||||
|
@ -9,7 +9,7 @@ use crate::{
|
||||
};
|
||||
use flowy_dispatch::prelude::*;
|
||||
use flowy_sdk::*;
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
use std::{ffi::CStr, os::raw::c_char};
|
||||
|
||||
#[no_mangle]
|
||||
|
@ -1,5 +1,5 @@
|
||||
use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
|
||||
use flowy_dispatch::prelude::{DispatchError, EventResponse, Payload, StatusCode};
|
||||
use flowy_dispatch::prelude::{EventResponse, Payload, StatusCode};
|
||||
|
||||
#[derive(ProtoBuf_Enum, Clone, Copy)]
|
||||
pub enum FFIStatusCode {
|
||||
|
@ -33,6 +33,7 @@ pub fn category_from_str(type_str: &str) -> TypeCategory {
|
||||
| "UpdateWorkspaceRequest"
|
||||
| "CreateWorkspaceRequest"
|
||||
| "Workspace"
|
||||
| "Workspaces"
|
||||
| "QueryWorkspaceRequest"
|
||||
| "CurrentWorkspace"
|
||||
| "UpdateViewRequest"
|
||||
@ -56,12 +57,12 @@ pub fn category_from_str(type_str: &str) -> TypeCategory {
|
||||
| "EditorErrorCode"
|
||||
| "ViewType"
|
||||
| "WorkspaceEvent"
|
||||
| "WorkspaceErrorCode"
|
||||
| "WsErrCode"
|
||||
| "WorkspaceObservable"
|
||||
| "FFIStatusCode"
|
||||
| "UserStatus"
|
||||
| "UserEvent"
|
||||
| "UserErrorCode"
|
||||
| "UserErrCode"
|
||||
=> TypeCategory::Enum,
|
||||
|
||||
"Option" => TypeCategory::Opt,
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::{
|
||||
byte_trait::FromBytes,
|
||||
request::EventRequest,
|
||||
response::{EventResponse, ResponseBuilder, StatusCode},
|
||||
response::{EventResponse, ResponseBuilder},
|
||||
};
|
||||
use dyn_clone::DynClone;
|
||||
use serde::{Serialize, Serializer};
|
||||
|
@ -1,5 +1,4 @@
|
||||
use crate::{
|
||||
errors::DispatchError,
|
||||
request::Payload,
|
||||
response::{EventResponse, StatusCode},
|
||||
};
|
||||
|
@ -4,7 +4,7 @@ use crate::{
|
||||
services::{doc_controller::DocController, file_manager::FileManager},
|
||||
};
|
||||
use flowy_dispatch::prelude::*;
|
||||
use std::{convert::TryInto, path::Path, sync::Arc};
|
||||
use std::{convert::TryInto, path::Path};
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
#[tracing::instrument(name = "create_doc", skip(data, controller, manager))]
|
||||
@ -67,7 +67,8 @@ pub async fn update_doc(
|
||||
manager
|
||||
.write()
|
||||
.await
|
||||
.save(Path::new(&doc_desc.path), &s, params.id.clone());
|
||||
.save(Path::new(&doc_desc.path), &s, params.id.clone())
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
if params.name.is_some() || params.desc.is_some() {
|
||||
|
@ -2,10 +2,7 @@ use crate::{
|
||||
errors::EditorError,
|
||||
event::EditorEvent,
|
||||
handlers::*,
|
||||
services::{
|
||||
doc_controller::DocController,
|
||||
file_manager::{create_dir_if_not_exist, FileManager},
|
||||
},
|
||||
services::{doc_controller::DocController, file_manager::FileManager},
|
||||
};
|
||||
use flowy_database::DBConnection;
|
||||
use flowy_dispatch::prelude::*;
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::{
|
||||
entities::doc::{CreateDocParams, DocData, DocInfo, QueryDocParams, UpdateDocParams},
|
||||
entities::doc::{CreateDocParams, DocInfo, UpdateDocParams},
|
||||
errors::EditorError,
|
||||
module::EditorDatabase,
|
||||
sql_tables::doc::{DocTable, DocTableChangeset, DocTableSql},
|
||||
|
@ -6,7 +6,6 @@ use std::{
|
||||
io::{Read, Write},
|
||||
path::{Path, PathBuf},
|
||||
str,
|
||||
sync::atomic::{AtomicUsize, Ordering},
|
||||
time::SystemTime,
|
||||
};
|
||||
|
||||
@ -117,6 +116,7 @@ pub(crate) fn try_decode(
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn create_dir_if_not_exist(dir: &str) -> Result<(), io::Error> {
|
||||
let _ = fs::create_dir_all(dir)?;
|
||||
Ok(())
|
||||
|
@ -1,9 +1,8 @@
|
||||
use crate::{module::EditorUser, services::file_manager::*};
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
io,
|
||||
path::{Path, PathBuf},
|
||||
sync::{Arc, PoisonError, RwLock, RwLockReadGuard},
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
pub struct FileManager {
|
||||
@ -49,6 +48,7 @@ impl FileManager {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn close<T>(&mut self, id: T)
|
||||
where
|
||||
T: Into<FileId>,
|
||||
@ -71,12 +71,15 @@ impl FileManager {
|
||||
Ok(path)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn get_info(&self, id: &FileId) -> Option<&FileInfo> { self.file_info.get(id) }
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn get_file_id(&self, path: &Path) -> Option<FileId> {
|
||||
self.open_files.get(path).cloned()
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn check_file(&mut self, path: &Path, id: &FileId) -> bool {
|
||||
if let Some(info) = self.file_info.get_mut(&id) {
|
||||
let modified_time = get_modified_time(path);
|
||||
|
@ -36,5 +36,5 @@ impl DocTableSql {
|
||||
Ok(doc_table)
|
||||
}
|
||||
|
||||
pub(crate) fn delete_doc(&self, view_id: &str) -> Result<(), EditorError> { unimplemented!() }
|
||||
pub(crate) fn delete_doc(&self, _view_id: &str) -> Result<(), EditorError> { unimplemented!() }
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
use crate::entities::doc::{CreateDocParams, DocInfo, UpdateDocParams};
|
||||
use flowy_database::schema::doc_table;
|
||||
use flowy_infra::{timestamp, uuid};
|
||||
use std::convert::TryInto;
|
||||
use flowy_infra::timestamp;
|
||||
|
||||
#[derive(PartialEq, Clone, Debug, Queryable, Identifiable, Insertable, Associations)]
|
||||
#[table_name = "doc_table"]
|
||||
|
@ -1,5 +1,5 @@
|
||||
mod doc_sql;
|
||||
mod doc_table;
|
||||
|
||||
pub use doc_sql::*;
|
||||
pub use doc_table::*;
|
||||
pub(crate) use doc_sql::*;
|
||||
pub(crate) use doc_table::*;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user