mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
Merge pull request #485 from AppFlowy-IO/fix_0.0.4_beta3
Fix 0.0.4 beta3
This commit is contained in:
commit
cb0a86893b
@ -181,6 +181,7 @@
|
|||||||
"textPlaceholder": "Empty"
|
"textPlaceholder": "Empty"
|
||||||
},
|
},
|
||||||
"selectOption": {
|
"selectOption": {
|
||||||
|
"create": "Create",
|
||||||
"purpleColor": "Purple",
|
"purpleColor": "Purple",
|
||||||
"pinkColor": "Pink",
|
"pinkColor": "Pink",
|
||||||
"lightPinkColor": "Light Pink",
|
"lightPinkColor": "Light Pink",
|
||||||
|
@ -7,9 +7,7 @@ import 'package:app_flowy/workspace/application/grid/prelude.dart';
|
|||||||
import 'package:app_flowy/workspace/application/trash/prelude.dart';
|
import 'package:app_flowy/workspace/application/trash/prelude.dart';
|
||||||
import 'package:app_flowy/workspace/application/workspace/prelude.dart';
|
import 'package:app_flowy/workspace/application/workspace/prelude.dart';
|
||||||
import 'package:app_flowy/workspace/application/edit_pannel/edit_pannel_bloc.dart';
|
import 'package:app_flowy/workspace/application/edit_pannel/edit_pannel_bloc.dart';
|
||||||
import 'package:app_flowy/workspace/application/home/home_bloc.dart';
|
|
||||||
import 'package:app_flowy/workspace/application/view/prelude.dart';
|
import 'package:app_flowy/workspace/application/view/prelude.dart';
|
||||||
import 'package:app_flowy/workspace/application/home/prelude.dart';
|
|
||||||
import 'package:app_flowy/workspace/application/menu/prelude.dart';
|
import 'package:app_flowy/workspace/application/menu/prelude.dart';
|
||||||
import 'package:app_flowy/user/application/prelude.dart';
|
import 'package:app_flowy/user/application/prelude.dart';
|
||||||
import 'package:app_flowy/user/presentation/router.dart';
|
import 'package:app_flowy/user/presentation/router.dart';
|
||||||
@ -17,6 +15,7 @@ import 'package:app_flowy/workspace/presentation/home/home_stack.dart';
|
|||||||
import 'package:app_flowy/workspace/presentation/home/menu/menu.dart';
|
import 'package:app_flowy/workspace/presentation/home/menu/menu.dart';
|
||||||
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/app.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/app.pb.dart';
|
||||||
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
|
||||||
|
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' show EditFieldContext;
|
||||||
import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option.pb.dart';
|
||||||
import 'package:flowy_sdk/protobuf/flowy-grid/number_type_option.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-grid/number_type_option.pb.dart';
|
||||||
import 'package:flowy_sdk/protobuf/flowy-user-data-model/user_profile.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-user-data-model/user_profile.pb.dart';
|
||||||
@ -44,7 +43,6 @@ void _resolveUserDeps(GetIt getIt) {
|
|||||||
getIt.registerFactory<SignUpBloc>(() => SignUpBloc(getIt<AuthService>()));
|
getIt.registerFactory<SignUpBloc>(() => SignUpBloc(getIt<AuthService>()));
|
||||||
|
|
||||||
getIt.registerFactory<SplashRoute>(() => SplashRoute());
|
getIt.registerFactory<SplashRoute>(() => SplashRoute());
|
||||||
getIt.registerFactory<HomeBloc>(() => HomeBloc());
|
|
||||||
getIt.registerFactory<EditPannelBloc>(() => EditPannelBloc());
|
getIt.registerFactory<EditPannelBloc>(() => EditPannelBloc());
|
||||||
getIt.registerFactory<SplashBloc>(() => SplashBloc());
|
getIt.registerFactory<SplashBloc>(() => SplashBloc());
|
||||||
getIt.registerLazySingleton<NetworkListener>(() => NetworkListener());
|
getIt.registerLazySingleton<NetworkListener>(() => NetworkListener());
|
||||||
@ -57,10 +55,6 @@ void _resolveHomeDeps(GetIt getIt) {
|
|||||||
(user, _) => UserListener(user: user),
|
(user, _) => UserListener(user: user),
|
||||||
);
|
);
|
||||||
|
|
||||||
getIt.registerFactoryParam<HomeListenBloc, UserProfile, void>(
|
|
||||||
(user, _) => HomeListenBloc(getIt<UserListener>(param1: user)),
|
|
||||||
);
|
|
||||||
|
|
||||||
//
|
//
|
||||||
getIt.registerLazySingleton<HomeStackManager>(() => HomeStackManager());
|
getIt.registerLazySingleton<HomeStackManager>(() => HomeStackManager());
|
||||||
|
|
||||||
@ -201,8 +195,8 @@ void _resolveGridDeps(GetIt getIt) {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
getIt.registerFactoryParam<FieldSwitcherBloc, SwitchFieldContext, void>(
|
getIt.registerFactoryParam<FieldEditorPannelBloc, EditFieldContext, void>(
|
||||||
(context, _) => FieldSwitcherBloc(context),
|
(context, _) => FieldEditorPannelBloc(context),
|
||||||
);
|
);
|
||||||
|
|
||||||
getIt.registerFactoryParam<DateTypeOptionBloc, DateTypeOption, void>(
|
getIt.registerFactoryParam<DateTypeOptionBloc, DateTypeOption, void>(
|
||||||
|
@ -12,26 +12,55 @@ import 'package:flowy_sdk/protobuf/flowy-user-data-model/user_profile.pb.dart';
|
|||||||
import 'package:flowy_sdk/protobuf/flowy-user/dart_notification.pb.dart' as user;
|
import 'package:flowy_sdk/protobuf/flowy-user/dart_notification.pb.dart' as user;
|
||||||
import 'package:flowy_sdk/rust_stream.dart';
|
import 'package:flowy_sdk/rust_stream.dart';
|
||||||
|
|
||||||
typedef UserProfileUpdatedNotifierValue = Either<UserProfile, FlowyError>;
|
typedef UserProfileNotifyValue = Either<UserProfile, FlowyError>;
|
||||||
typedef AuthNotifierValue = Either<Unit, FlowyError>;
|
typedef AuthNotifyValue = Either<Unit, FlowyError>;
|
||||||
typedef WorkspaceUpdatedNotifierValue = Either<List<Workspace>, FlowyError>;
|
typedef WorkspaceListNotifyValue = Either<List<Workspace>, FlowyError>;
|
||||||
|
typedef WorkspaceSettingNotifyValue = Either<CurrentWorkspaceSetting, FlowyError>;
|
||||||
|
|
||||||
class UserListener {
|
class UserListener {
|
||||||
StreamSubscription<SubscribeObject>? _subscription;
|
StreamSubscription<SubscribeObject>? _subscription;
|
||||||
final profileUpdatedNotifier = PublishNotifier<UserProfileUpdatedNotifierValue>();
|
final _profileNotifier = PublishNotifier<UserProfileNotifyValue>();
|
||||||
final authDidChangedNotifier = PublishNotifier<AuthNotifierValue>();
|
final _authNotifier = PublishNotifier<AuthNotifyValue>();
|
||||||
final workspaceUpdatedNotifier = PublishNotifier<WorkspaceUpdatedNotifierValue>();
|
final _workspaceListNotifier = PublishNotifier<WorkspaceListNotifyValue>();
|
||||||
|
final _workSettingNotifier = PublishNotifier<WorkspaceSettingNotifyValue>();
|
||||||
|
|
||||||
FolderNotificationParser? _workspaceParser;
|
FolderNotificationParser? _workspaceParser;
|
||||||
UserNotificationParser? _userParser;
|
UserNotificationParser? _userParser;
|
||||||
late UserProfile _user;
|
final UserProfile _user;
|
||||||
UserListener({
|
UserListener({
|
||||||
required UserProfile user,
|
required UserProfile user,
|
||||||
}) {
|
}) : _user = user;
|
||||||
_user = user;
|
|
||||||
}
|
void start({
|
||||||
|
void Function(AuthNotifyValue)? onAuthChanged,
|
||||||
|
void Function(UserProfileNotifyValue)? onProfileUpdated,
|
||||||
|
void Function(WorkspaceListNotifyValue)? onWorkspaceListUpdated,
|
||||||
|
void Function(WorkspaceSettingNotifyValue)? onWorkspaceSettingUpdated,
|
||||||
|
}) {
|
||||||
|
if (onAuthChanged != null) {
|
||||||
|
_authNotifier.addListener(() {
|
||||||
|
onAuthChanged(_authNotifier.currentValue!);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (onProfileUpdated != null) {
|
||||||
|
_profileNotifier.addListener(() {
|
||||||
|
onProfileUpdated(_profileNotifier.currentValue!);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (onWorkspaceListUpdated != null) {
|
||||||
|
_workspaceListNotifier.addListener(() {
|
||||||
|
onWorkspaceListUpdated(_workspaceListNotifier.currentValue!);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (onWorkspaceSettingUpdated != null) {
|
||||||
|
_workSettingNotifier.addListener(() {
|
||||||
|
onWorkspaceSettingUpdated(_workSettingNotifier.currentValue!);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void start() {
|
|
||||||
_workspaceParser = FolderNotificationParser(id: _user.token, callback: _notificationCallback);
|
_workspaceParser = FolderNotificationParser(id: _user.token, callback: _notificationCallback);
|
||||||
_userParser = UserNotificationParser(id: _user.token, callback: _userNotificationCallback);
|
_userParser = UserNotificationParser(id: _user.token, callback: _userNotificationCallback);
|
||||||
_subscription = RustStreamReceiver.listen((observable) {
|
_subscription = RustStreamReceiver.listen((observable) {
|
||||||
@ -44,9 +73,9 @@ class UserListener {
|
|||||||
_workspaceParser = null;
|
_workspaceParser = null;
|
||||||
_userParser = null;
|
_userParser = null;
|
||||||
await _subscription?.cancel();
|
await _subscription?.cancel();
|
||||||
profileUpdatedNotifier.dispose();
|
_profileNotifier.dispose();
|
||||||
authDidChangedNotifier.dispose();
|
_authNotifier.dispose();
|
||||||
workspaceUpdatedNotifier.dispose();
|
_workspaceListNotifier.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _notificationCallback(FolderNotification ty, Either<Uint8List, FlowyError> result) {
|
void _notificationCallback(FolderNotification ty, Either<Uint8List, FlowyError> result) {
|
||||||
@ -55,16 +84,23 @@ class UserListener {
|
|||||||
case FolderNotification.UserDeleteWorkspace:
|
case FolderNotification.UserDeleteWorkspace:
|
||||||
case FolderNotification.WorkspaceListUpdated:
|
case FolderNotification.WorkspaceListUpdated:
|
||||||
result.fold(
|
result.fold(
|
||||||
(payload) => workspaceUpdatedNotifier.value = left(RepeatedWorkspace.fromBuffer(payload).items),
|
(payload) => _workspaceListNotifier.value = left(RepeatedWorkspace.fromBuffer(payload).items),
|
||||||
(error) => workspaceUpdatedNotifier.value = right(error),
|
(error) => _workspaceListNotifier.value = right(error),
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case FolderNotification.WorkspaceSetting:
|
||||||
|
result.fold(
|
||||||
|
(payload) => _workSettingNotifier.value = left(CurrentWorkspaceSetting.fromBuffer(payload)),
|
||||||
|
(error) => _workSettingNotifier.value = right(error),
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case FolderNotification.UserUnauthorized:
|
case FolderNotification.UserUnauthorized:
|
||||||
result.fold(
|
result.fold(
|
||||||
(_) {},
|
(_) {},
|
||||||
(error) => authDidChangedNotifier.value = right(FlowyError.create()..code = ErrorCode.UserUnauthorized.value),
|
(error) => _authNotifier.value = right(FlowyError.create()..code = ErrorCode.UserUnauthorized.value),
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -74,8 +110,8 @@ class UserListener {
|
|||||||
switch (ty) {
|
switch (ty) {
|
||||||
case user.UserNotification.UserUnauthorized:
|
case user.UserNotification.UserUnauthorized:
|
||||||
result.fold(
|
result.fold(
|
||||||
(payload) => profileUpdatedNotifier.value = left(UserProfile.fromBuffer(payload)),
|
(payload) => _profileNotifier.value = left(UserProfile.fromBuffer(payload)),
|
||||||
(error) => profileUpdatedNotifier.value = right(error),
|
(error) => _profileNotifier.value = right(error),
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -41,7 +41,7 @@ class AppBloc extends Bloc<AppEvent, AppState> {
|
|||||||
|
|
||||||
void _startListening() {
|
void _startListening() {
|
||||||
appListener.start(
|
appListener.start(
|
||||||
viewsChanged: (result) {
|
onViewsChanged: (result) {
|
||||||
result.fold(
|
result.fold(
|
||||||
(views) {
|
(views) {
|
||||||
if (!isClosed) {
|
if (!isClosed) {
|
||||||
@ -51,7 +51,7 @@ class AppBloc extends Bloc<AppEvent, AppState> {
|
|||||||
(error) => Log.error(error),
|
(error) => Log.error(error),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
appUpdated: (app) {
|
onAppUpdated: (app) {
|
||||||
if (!isClosed) {
|
if (!isClosed) {
|
||||||
add(AppEvent.appDidUpdate(app));
|
add(AppEvent.appDidUpdate(app));
|
||||||
}
|
}
|
||||||
@ -97,7 +97,7 @@ class AppBloc extends Bloc<AppEvent, AppState> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> close() async {
|
Future<void> close() async {
|
||||||
await appListener.close();
|
await appListener.stop();
|
||||||
return super.close();
|
return super.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,9 +24,9 @@ class AppListener {
|
|||||||
required this.appId,
|
required this.appId,
|
||||||
});
|
});
|
||||||
|
|
||||||
void start({ViewsDidChangeCallback? viewsChanged, AppDidUpdateCallback? appUpdated}) {
|
void start({ViewsDidChangeCallback? onViewsChanged, AppDidUpdateCallback? onAppUpdated}) {
|
||||||
_viewsChanged = viewsChanged;
|
_viewsChanged = onViewsChanged;
|
||||||
_updated = appUpdated;
|
_updated = onAppUpdated;
|
||||||
_parser = FolderNotificationParser(id: appId, callback: _bservableCallback);
|
_parser = FolderNotificationParser(id: appId, callback: _bservableCallback);
|
||||||
_subscription = RustStreamReceiver.listen((observable) => _parser?.parse(observable));
|
_subscription = RustStreamReceiver.listen((observable) => _parser?.parse(observable));
|
||||||
}
|
}
|
||||||
@ -60,7 +60,7 @@ class AppListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> close() async {
|
Future<void> stop() async {
|
||||||
_parser = null;
|
_parser = null;
|
||||||
await _subscription?.cancel();
|
await _subscription?.cancel();
|
||||||
_viewsChanged = null;
|
_viewsChanged = null;
|
||||||
|
@ -59,7 +59,7 @@ class DocumentBloc extends Bloc<DocumentEvent, DocumentState> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> close() async {
|
Future<void> close() async {
|
||||||
await listener.close();
|
await listener.stop();
|
||||||
|
|
||||||
if (_subscription != null) {
|
if (_subscription != null) {
|
||||||
await _subscription?.cancel();
|
await _subscription?.cancel();
|
||||||
@ -70,21 +70,20 @@ class DocumentBloc extends Bloc<DocumentEvent, DocumentState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _initial(Initial value, Emitter<DocumentState> emit) async {
|
Future<void> _initial(Initial value, Emitter<DocumentState> emit) async {
|
||||||
listener.deletedNotifier.addPublishListener((result) {
|
listener.start(
|
||||||
result.fold(
|
onViewDeleted: (result) {
|
||||||
(view) => add(const DocumentEvent.deleted()),
|
result.fold(
|
||||||
(error) {},
|
(view) => add(const DocumentEvent.deleted()),
|
||||||
);
|
(error) {},
|
||||||
});
|
);
|
||||||
|
},
|
||||||
listener.restoredNotifier.addPublishListener((result) {
|
onViewRestored: (result) {
|
||||||
result.fold(
|
result.fold(
|
||||||
(view) => add(const DocumentEvent.restore()),
|
(view) => add(const DocumentEvent.restore()),
|
||||||
(error) {},
|
(error) {},
|
||||||
);
|
);
|
||||||
});
|
},
|
||||||
|
);
|
||||||
listener.start();
|
|
||||||
final result = await service.openDocument(docId: view.id);
|
final result = await service.openDocument(docId: view.id);
|
||||||
result.fold(
|
result.fold(
|
||||||
(block) {
|
(block) {
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
import 'package:app_flowy/workspace/application/grid/cell/cell_service.dart';
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:dartz/dartz.dart';
|
||||||
import 'package:flowy_sdk/log.dart';
|
import 'package:flowy_sdk/log.dart';
|
||||||
import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
import 'dart:async';
|
|
||||||
|
import 'package:app_flowy/workspace/application/grid/cell/cell_service.dart';
|
||||||
|
|
||||||
import 'select_option_service.dart';
|
import 'select_option_service.dart';
|
||||||
|
|
||||||
part 'selection_editor_bloc.freezed.dart';
|
part 'selection_editor_bloc.freezed.dart';
|
||||||
@ -24,14 +28,19 @@ class SelectOptionEditorBloc extends Bloc<SelectOptionEditorEvent, SelectOptionE
|
|||||||
_startListening();
|
_startListening();
|
||||||
},
|
},
|
||||||
didReceiveOptions: (_DidReceiveOptions value) {
|
didReceiveOptions: (_DidReceiveOptions value) {
|
||||||
|
final result = _makeOptions(state.filter, value.options);
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(
|
||||||
allOptions: value.options,
|
allOptions: value.options,
|
||||||
options: _makeOptions(state.filter, value.options),
|
options: result.options,
|
||||||
|
createOption: result.createOption,
|
||||||
selectedOptions: value.selectedOptions,
|
selectedOptions: value.selectedOptions,
|
||||||
));
|
));
|
||||||
},
|
},
|
||||||
newOption: (_NewOption value) {
|
newOption: (_NewOption value) {
|
||||||
_createOption(value.optionName);
|
_createOption(value.optionName);
|
||||||
|
emit(state.copyWith(
|
||||||
|
filter: none(),
|
||||||
|
));
|
||||||
},
|
},
|
||||||
deleteOption: (_DeleteOption value) {
|
deleteOption: (_DeleteOption value) {
|
||||||
_deleteOption(value.option);
|
_deleteOption(value.option);
|
||||||
@ -91,16 +100,37 @@ class SelectOptionEditorBloc extends Bloc<SelectOptionEditorEvent, SelectOptionE
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _filterOption(String optionName, Emitter<SelectOptionEditorState> emit) {
|
void _filterOption(String optionName, Emitter<SelectOptionEditorState> emit) {
|
||||||
emit(state.copyWith(filter: optionName, options: _makeOptions(optionName, state.allOptions)));
|
final _MakeOptionResult result = _makeOptions(Some(optionName), state.allOptions);
|
||||||
|
emit(state.copyWith(
|
||||||
|
filter: Some(optionName),
|
||||||
|
options: result.options,
|
||||||
|
createOption: result.createOption,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
List<SelectOption> _makeOptions(String filter, List<SelectOption> allOptions) {
|
_MakeOptionResult _makeOptions(Option<String> filter, List<SelectOption> allOptions) {
|
||||||
final List<SelectOption> options = List.from(allOptions);
|
final List<SelectOption> options = List.from(allOptions);
|
||||||
if (filter.isNotEmpty) {
|
Option<String> createOption = filter;
|
||||||
options.retainWhere((option) => option.name.toLowerCase().contains(filter.toLowerCase()));
|
|
||||||
}
|
|
||||||
|
|
||||||
return options;
|
filter.foldRight(null, (filter, previous) {
|
||||||
|
if (filter.isNotEmpty) {
|
||||||
|
options.retainWhere((option) {
|
||||||
|
final name = option.name.toLowerCase();
|
||||||
|
final lFilter = filter.toLowerCase();
|
||||||
|
|
||||||
|
if (name == lFilter) {
|
||||||
|
createOption = none();
|
||||||
|
}
|
||||||
|
|
||||||
|
return name.contains(lFilter);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return _MakeOptionResult(
|
||||||
|
options: options,
|
||||||
|
createOption: createOption,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _startListening() {
|
void _startListening() {
|
||||||
@ -135,7 +165,8 @@ class SelectOptionEditorState with _$SelectOptionEditorState {
|
|||||||
required List<SelectOption> options,
|
required List<SelectOption> options,
|
||||||
required List<SelectOption> allOptions,
|
required List<SelectOption> allOptions,
|
||||||
required List<SelectOption> selectedOptions,
|
required List<SelectOption> selectedOptions,
|
||||||
required String filter,
|
required Option<String> createOption,
|
||||||
|
required Option<String> filter,
|
||||||
}) = _SelectOptionEditorState;
|
}) = _SelectOptionEditorState;
|
||||||
|
|
||||||
factory SelectOptionEditorState.initial(GridSelectOptionCellContext context) {
|
factory SelectOptionEditorState.initial(GridSelectOptionCellContext context) {
|
||||||
@ -144,7 +175,18 @@ class SelectOptionEditorState with _$SelectOptionEditorState {
|
|||||||
options: data?.options ?? [],
|
options: data?.options ?? [],
|
||||||
allOptions: data?.options ?? [],
|
allOptions: data?.options ?? [],
|
||||||
selectedOptions: data?.selectOptions ?? [],
|
selectedOptions: data?.selectOptions ?? [],
|
||||||
filter: "",
|
createOption: none(),
|
||||||
|
filter: none(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _MakeOptionResult {
|
||||||
|
List<SelectOption> options;
|
||||||
|
Option<String> createOption;
|
||||||
|
|
||||||
|
_MakeOptionResult({
|
||||||
|
required this.options,
|
||||||
|
required this.createOption,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
@ -6,6 +6,7 @@ import 'package:freezed_annotation/freezed_annotation.dart';
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'field_service.dart';
|
import 'field_service.dart';
|
||||||
import 'package:dartz/dartz.dart';
|
import 'package:dartz/dartz.dart';
|
||||||
|
import 'package:protobuf/protobuf.dart';
|
||||||
|
|
||||||
part 'field_editor_bloc.freezed.dart';
|
part 'field_editor_bloc.freezed.dart';
|
||||||
|
|
||||||
@ -25,10 +26,13 @@ class FieldEditorBloc extends Bloc<FieldEditorEvent, FieldEditorState> {
|
|||||||
await _getEditFieldContext(emit);
|
await _getEditFieldContext(emit);
|
||||||
},
|
},
|
||||||
updateName: (_UpdateName value) {
|
updateName: (_UpdateName value) {
|
||||||
emit(state.copyWith(fieldName: value.name));
|
final newContext = _updateEditContext(name: value.name);
|
||||||
|
emit(state.copyWith(editFieldContext: newContext));
|
||||||
},
|
},
|
||||||
switchField: (_SwitchField value) {
|
updateField: (_UpdateField value) {
|
||||||
emit(state.copyWith(field: Some(value.field), typeOptionData: value.typeOptionData));
|
final newContext = _updateEditContext(field: value.field, typeOptionData: value.typeOptionData);
|
||||||
|
|
||||||
|
emit(state.copyWith(editFieldContext: newContext));
|
||||||
},
|
},
|
||||||
done: (_Done value) async {
|
done: (_Done value) async {
|
||||||
await _saveField(emit);
|
await _saveField(emit);
|
||||||
@ -43,14 +47,49 @@ class FieldEditorBloc extends Bloc<FieldEditorEvent, FieldEditorState> {
|
|||||||
return super.close();
|
return super.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Option<EditFieldContext> _updateEditContext({
|
||||||
|
String? name,
|
||||||
|
Field? field,
|
||||||
|
List<int>? typeOptionData,
|
||||||
|
}) {
|
||||||
|
return state.editFieldContext.fold(
|
||||||
|
() => none(),
|
||||||
|
(context) {
|
||||||
|
context.freeze();
|
||||||
|
final newContext = context.rebuild((newContext) {
|
||||||
|
newContext.gridField.rebuild((newField) {
|
||||||
|
if (name != null) {
|
||||||
|
newField.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
newContext.gridField = newField;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (field != null) {
|
||||||
|
newContext.gridField = field;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeOptionData != null) {
|
||||||
|
newContext.typeOptionData = typeOptionData;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
service.insertField(
|
||||||
|
field: newContext.gridField,
|
||||||
|
typeOptionData: newContext.typeOptionData,
|
||||||
|
);
|
||||||
|
|
||||||
|
return Some(newContext);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> _saveField(Emitter<FieldEditorState> emit) async {
|
Future<void> _saveField(Emitter<FieldEditorState> emit) async {
|
||||||
await state.field.fold(
|
await state.editFieldContext.fold(
|
||||||
() async => null,
|
() async => null,
|
||||||
(field) async {
|
(context) async {
|
||||||
field.name = state.fieldName;
|
|
||||||
final result = await service.insertField(
|
final result = await service.insertField(
|
||||||
field: field,
|
field: context.gridField,
|
||||||
typeOptionData: state.typeOptionData,
|
typeOptionData: context.typeOptionData,
|
||||||
);
|
);
|
||||||
result.fold((l) => null, (r) => null);
|
result.fold((l) => null, (r) => null);
|
||||||
},
|
},
|
||||||
@ -60,11 +99,9 @@ class FieldEditorBloc extends Bloc<FieldEditorEvent, FieldEditorState> {
|
|||||||
Future<void> _getEditFieldContext(Emitter<FieldEditorState> emit) async {
|
Future<void> _getEditFieldContext(Emitter<FieldEditorState> emit) async {
|
||||||
final result = await _loader.load();
|
final result = await _loader.load();
|
||||||
result.fold(
|
result.fold(
|
||||||
(editContext) {
|
(context) {
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(
|
||||||
field: Some(editContext.gridField),
|
editFieldContext: Some(context),
|
||||||
typeOptionData: editContext.typeOptionData,
|
|
||||||
fieldName: editContext.gridField.name,
|
|
||||||
));
|
));
|
||||||
},
|
},
|
||||||
(err) => Log.error(err),
|
(err) => Log.error(err),
|
||||||
@ -76,25 +113,21 @@ class FieldEditorBloc extends Bloc<FieldEditorEvent, FieldEditorState> {
|
|||||||
class FieldEditorEvent with _$FieldEditorEvent {
|
class FieldEditorEvent with _$FieldEditorEvent {
|
||||||
const factory FieldEditorEvent.initial() = _InitialField;
|
const factory FieldEditorEvent.initial() = _InitialField;
|
||||||
const factory FieldEditorEvent.updateName(String name) = _UpdateName;
|
const factory FieldEditorEvent.updateName(String name) = _UpdateName;
|
||||||
const factory FieldEditorEvent.switchField(Field field, Uint8List typeOptionData) = _SwitchField;
|
const factory FieldEditorEvent.updateField(Field field, Uint8List typeOptionData) = _UpdateField;
|
||||||
const factory FieldEditorEvent.done() = _Done;
|
const factory FieldEditorEvent.done() = _Done;
|
||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
class FieldEditorState with _$FieldEditorState {
|
class FieldEditorState with _$FieldEditorState {
|
||||||
const factory FieldEditorState({
|
const factory FieldEditorState({
|
||||||
required String fieldName,
|
|
||||||
required String gridId,
|
required String gridId,
|
||||||
required String errorText,
|
required String errorText,
|
||||||
required Option<Field> field,
|
required Option<EditFieldContext> editFieldContext,
|
||||||
required List<int> typeOptionData,
|
|
||||||
}) = _FieldEditorState;
|
}) = _FieldEditorState;
|
||||||
|
|
||||||
factory FieldEditorState.initial(String gridId) => FieldEditorState(
|
factory FieldEditorState.initial(String gridId) => FieldEditorState(
|
||||||
gridId: gridId,
|
gridId: gridId,
|
||||||
fieldName: '',
|
editFieldContext: none(),
|
||||||
field: none(),
|
|
||||||
errorText: '',
|
errorText: '',
|
||||||
typeOptionData: List<int>.empty(),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,53 @@
|
|||||||
|
import 'dart:typed_data';
|
||||||
|
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
part 'field_editor_pannel_bloc.freezed.dart';
|
||||||
|
|
||||||
|
class FieldEditorPannelBloc extends Bloc<FieldEditorPannelEvent, FieldEditorPannelState> {
|
||||||
|
FieldEditorPannelBloc(EditFieldContext editContext) : super(FieldEditorPannelState.initial(editContext)) {
|
||||||
|
on<FieldEditorPannelEvent>(
|
||||||
|
(event, emit) async {
|
||||||
|
await event.map(
|
||||||
|
toFieldType: (_ToFieldType value) async {
|
||||||
|
emit(state.copyWith(
|
||||||
|
field: value.field,
|
||||||
|
typeOptionData: Uint8List.fromList(value.typeOptionData),
|
||||||
|
));
|
||||||
|
},
|
||||||
|
didUpdateTypeOptionData: (_DidUpdateTypeOptionData value) {
|
||||||
|
emit(state.copyWith(typeOptionData: value.typeOptionData));
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> close() async {
|
||||||
|
return super.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
class FieldEditorPannelEvent with _$FieldEditorPannelEvent {
|
||||||
|
const factory FieldEditorPannelEvent.toFieldType(Field field, List<int> typeOptionData) = _ToFieldType;
|
||||||
|
const factory FieldEditorPannelEvent.didUpdateTypeOptionData(Uint8List typeOptionData) = _DidUpdateTypeOptionData;
|
||||||
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
class FieldEditorPannelState with _$FieldEditorPannelState {
|
||||||
|
const factory FieldEditorPannelState({
|
||||||
|
required String gridId,
|
||||||
|
required Field field,
|
||||||
|
required Uint8List typeOptionData,
|
||||||
|
}) = _FieldEditorPannelState;
|
||||||
|
|
||||||
|
factory FieldEditorPannelState.initial(EditFieldContext context) => FieldEditorPannelState(
|
||||||
|
gridId: context.gridId,
|
||||||
|
field: context.gridField,
|
||||||
|
typeOptionData: Uint8List.fromList(context.typeOptionData),
|
||||||
|
);
|
||||||
|
}
|
@ -1,61 +0,0 @@
|
|||||||
import 'dart:typed_data';
|
|
||||||
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
||||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
|
||||||
import 'dart:async';
|
|
||||||
|
|
||||||
part 'field_switch_bloc.freezed.dart';
|
|
||||||
|
|
||||||
class FieldSwitcherBloc extends Bloc<FieldSwitchEvent, FieldSwitchState> {
|
|
||||||
FieldSwitcherBloc(SwitchFieldContext editContext) : super(FieldSwitchState.initial(editContext)) {
|
|
||||||
on<FieldSwitchEvent>(
|
|
||||||
(event, emit) async {
|
|
||||||
await event.map(
|
|
||||||
toFieldType: (_ToFieldType value) async {
|
|
||||||
emit(state.copyWith(
|
|
||||||
field: value.field,
|
|
||||||
typeOptionData: Uint8List.fromList(value.typeOptionData),
|
|
||||||
));
|
|
||||||
},
|
|
||||||
didUpdateTypeOptionData: (_DidUpdateTypeOptionData value) {
|
|
||||||
emit(state.copyWith(typeOptionData: value.typeOptionData));
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> close() async {
|
|
||||||
return super.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@freezed
|
|
||||||
class FieldSwitchEvent with _$FieldSwitchEvent {
|
|
||||||
const factory FieldSwitchEvent.toFieldType(Field field, List<int> typeOptionData) = _ToFieldType;
|
|
||||||
const factory FieldSwitchEvent.didUpdateTypeOptionData(Uint8List typeOptionData) = _DidUpdateTypeOptionData;
|
|
||||||
}
|
|
||||||
|
|
||||||
@freezed
|
|
||||||
class FieldSwitchState with _$FieldSwitchState {
|
|
||||||
const factory FieldSwitchState({
|
|
||||||
required String gridId,
|
|
||||||
required Field field,
|
|
||||||
required Uint8List typeOptionData,
|
|
||||||
}) = _FieldSwitchState;
|
|
||||||
|
|
||||||
factory FieldSwitchState.initial(SwitchFieldContext switchContext) => FieldSwitchState(
|
|
||||||
gridId: switchContext.gridId,
|
|
||||||
field: switchContext.field,
|
|
||||||
typeOptionData: Uint8List.fromList(switchContext.typeOptionData),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
class SwitchFieldContext {
|
|
||||||
final String gridId;
|
|
||||||
final Field field;
|
|
||||||
final List<int> typeOptionData;
|
|
||||||
|
|
||||||
SwitchFieldContext(this.gridId, this.field, this.typeOptionData);
|
|
||||||
}
|
|
@ -8,7 +8,7 @@ export 'grid_header_bloc.dart';
|
|||||||
export 'field/field_service.dart';
|
export 'field/field_service.dart';
|
||||||
export 'field/field_action_sheet_bloc.dart';
|
export 'field/field_action_sheet_bloc.dart';
|
||||||
export 'field/field_editor_bloc.dart';
|
export 'field/field_editor_bloc.dart';
|
||||||
export 'field/field_switch_bloc.dart';
|
export 'field/field_editor_pannel_bloc.dart';
|
||||||
|
|
||||||
// Field Type Option
|
// Field Type Option
|
||||||
export 'field/type_option/date_bloc.dart';
|
export 'field/type_option/date_bloc.dart';
|
||||||
|
@ -1,13 +1,36 @@
|
|||||||
|
import 'package:app_flowy/user/application/user_listener.dart';
|
||||||
import 'package:app_flowy/workspace/application/edit_pannel/edit_context.dart';
|
import 'package:app_flowy/workspace/application/edit_pannel/edit_context.dart';
|
||||||
|
import 'package:flowy_sdk/log.dart';
|
||||||
|
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
|
||||||
|
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/workspace.pb.dart' show CurrentWorkspaceSetting;
|
||||||
|
import 'package:flowy_sdk/protobuf/flowy-user-data-model/errors.pb.dart';
|
||||||
|
import 'package:flowy_sdk/protobuf/flowy-user-data-model/user_profile.pb.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
import 'package:dartz/dartz.dart';
|
import 'package:dartz/dartz.dart';
|
||||||
part 'home_bloc.freezed.dart';
|
part 'home_bloc.freezed.dart';
|
||||||
|
|
||||||
class HomeBloc extends Bloc<HomeEvent, HomeState> {
|
class HomeBloc extends Bloc<HomeEvent, HomeState> {
|
||||||
HomeBloc() : super(HomeState.initial()) {
|
final UserListener _listener;
|
||||||
|
|
||||||
|
HomeBloc(UserProfile user, CurrentWorkspaceSetting workspaceSetting)
|
||||||
|
: _listener = UserListener(user: user),
|
||||||
|
super(HomeState.initial(workspaceSetting)) {
|
||||||
on<HomeEvent>((event, emit) async {
|
on<HomeEvent>((event, emit) async {
|
||||||
await event.map(
|
await event.map(
|
||||||
|
initial: (_Initial value) {
|
||||||
|
_listener.start(
|
||||||
|
onAuthChanged: (result) {
|
||||||
|
_authDidChanged(result);
|
||||||
|
},
|
||||||
|
onWorkspaceSettingUpdated: (result) {
|
||||||
|
result.fold(
|
||||||
|
(setting) => add(HomeEvent.didReceiveWorkspaceSetting(setting)),
|
||||||
|
(r) => Log.error(r),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
showLoading: (e) async {
|
showLoading: (e) async {
|
||||||
emit(state.copyWith(isLoading: e.isLoading));
|
emit(state.copyWith(isLoading: e.isLoading));
|
||||||
},
|
},
|
||||||
@ -20,22 +43,40 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> {
|
|||||||
forceCollapse: (e) async {
|
forceCollapse: (e) async {
|
||||||
emit(state.copyWith(forceCollapse: e.forceCollapse));
|
emit(state.copyWith(forceCollapse: e.forceCollapse));
|
||||||
},
|
},
|
||||||
|
didReceiveWorkspaceSetting: (_DidReceiveWorkspaceSetting value) {
|
||||||
|
emit(state.copyWith(workspaceSetting: value.setting));
|
||||||
|
},
|
||||||
|
unauthorized: (_Unauthorized value) {
|
||||||
|
emit(state.copyWith(unauthorized: true));
|
||||||
|
},
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> close() {
|
Future<void> close() async {
|
||||||
|
await _listener.stop();
|
||||||
return super.close();
|
return super.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _authDidChanged(Either<Unit, FlowyError> errorOrNothing) {
|
||||||
|
errorOrNothing.fold((_) {}, (error) {
|
||||||
|
if (error.code == ErrorCode.UserUnauthorized.value) {
|
||||||
|
add(HomeEvent.unauthorized(error.msg));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
class HomeEvent with _$HomeEvent {
|
class HomeEvent with _$HomeEvent {
|
||||||
|
const factory HomeEvent.initial() = _Initial;
|
||||||
const factory HomeEvent.showLoading(bool isLoading) = _ShowLoading;
|
const factory HomeEvent.showLoading(bool isLoading) = _ShowLoading;
|
||||||
const factory HomeEvent.forceCollapse(bool forceCollapse) = _ForceCollapse;
|
const factory HomeEvent.forceCollapse(bool forceCollapse) = _ForceCollapse;
|
||||||
const factory HomeEvent.setEditPannel(EditPannelContext editContext) = _ShowEditPannel;
|
const factory HomeEvent.setEditPannel(EditPannelContext editContext) = _ShowEditPannel;
|
||||||
const factory HomeEvent.dismissEditPannel() = _DismissEditPannel;
|
const factory HomeEvent.dismissEditPannel() = _DismissEditPannel;
|
||||||
|
const factory HomeEvent.didReceiveWorkspaceSetting(CurrentWorkspaceSetting setting) = _DidReceiveWorkspaceSetting;
|
||||||
|
const factory HomeEvent.unauthorized(String msg) = _Unauthorized;
|
||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
@ -44,11 +85,15 @@ class HomeState with _$HomeState {
|
|||||||
required bool isLoading,
|
required bool isLoading,
|
||||||
required bool forceCollapse,
|
required bool forceCollapse,
|
||||||
required Option<EditPannelContext> pannelContext,
|
required Option<EditPannelContext> pannelContext,
|
||||||
|
required CurrentWorkspaceSetting workspaceSetting,
|
||||||
|
required bool unauthorized,
|
||||||
}) = _HomeState;
|
}) = _HomeState;
|
||||||
|
|
||||||
factory HomeState.initial() => HomeState(
|
factory HomeState.initial(CurrentWorkspaceSetting workspaceSetting) => HomeState(
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
forceCollapse: false,
|
forceCollapse: false,
|
||||||
pannelContext: none(),
|
pannelContext: none(),
|
||||||
|
workspaceSetting: workspaceSetting,
|
||||||
|
unauthorized: false,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,54 +0,0 @@
|
|||||||
import 'package:app_flowy/user/application/user_listener.dart';
|
|
||||||
import 'package:flowy_sdk/protobuf/error-code/error_code.pbenum.dart';
|
|
||||||
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
|
|
||||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
||||||
import 'package:dartz/dartz.dart';
|
|
||||||
part 'home_listen_bloc.freezed.dart';
|
|
||||||
|
|
||||||
class HomeListenBloc extends Bloc<HomeListenEvent, HomeListenState> {
|
|
||||||
final UserListener listener;
|
|
||||||
HomeListenBloc(this.listener) : super(const HomeListenState.loading()) {
|
|
||||||
on<HomeListenEvent>((event, emit) async {
|
|
||||||
await event.map(
|
|
||||||
started: (_) async {
|
|
||||||
listener.authDidChangedNotifier.addPublishListener((result) {
|
|
||||||
_authDidChanged(result);
|
|
||||||
});
|
|
||||||
listener.start();
|
|
||||||
},
|
|
||||||
stop: (_) async {},
|
|
||||||
unauthorized: (e) async {
|
|
||||||
emit(HomeListenState.unauthorized(e.msg));
|
|
||||||
},
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> close() async {
|
|
||||||
await listener.stop();
|
|
||||||
super.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
void _authDidChanged(Either<Unit, FlowyError> errorOrNothing) {
|
|
||||||
errorOrNothing.fold((_) {}, (error) {
|
|
||||||
if (error.code == ErrorCode.UserUnauthorized.value) {
|
|
||||||
add(HomeListenEvent.unauthorized(error.msg));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@freezed
|
|
||||||
class HomeListenEvent with _$HomeListenEvent {
|
|
||||||
const factory HomeListenEvent.started() = _Started;
|
|
||||||
const factory HomeListenEvent.stop() = _Stop;
|
|
||||||
const factory HomeListenEvent.unauthorized(String msg) = _Unauthorized;
|
|
||||||
}
|
|
||||||
|
|
||||||
@freezed
|
|
||||||
class HomeListenState with _$HomeListenState {
|
|
||||||
const factory HomeListenState.loading() = Loading;
|
|
||||||
const factory HomeListenState.unauthorized(String msg) = Unauthorized;
|
|
||||||
}
|
|
@ -1 +1 @@
|
|||||||
export 'home_listen_bloc.dart';
|
|
||||||
|
@ -19,9 +19,10 @@ class MenuUserBloc extends Bloc<MenuUserEvent, MenuUserState> {
|
|||||||
on<MenuUserEvent>((event, emit) async {
|
on<MenuUserEvent>((event, emit) async {
|
||||||
await event.map(
|
await event.map(
|
||||||
initial: (_) async {
|
initial: (_) async {
|
||||||
userListener.profileUpdatedNotifier.addPublishListener(_profileUpdated);
|
userListener.start(
|
||||||
userListener.workspaceUpdatedNotifier.addPublishListener(_workspacesUpdated);
|
onProfileUpdated: _profileUpdated,
|
||||||
userListener.start();
|
onWorkspaceListUpdated: _workspaceListUpdated,
|
||||||
|
);
|
||||||
await _initUser();
|
await _initUser();
|
||||||
},
|
},
|
||||||
fetchWorkspaces: (_FetchWorkspaces value) async {},
|
fetchWorkspaces: (_FetchWorkspaces value) async {},
|
||||||
@ -41,7 +42,7 @@ class MenuUserBloc extends Bloc<MenuUserEvent, MenuUserState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _profileUpdated(Either<UserProfile, FlowyError> userOrFailed) {}
|
void _profileUpdated(Either<UserProfile, FlowyError> userOrFailed) {}
|
||||||
void _workspacesUpdated(Either<List<Workspace>, FlowyError> workspacesOrFailed) {
|
void _workspaceListUpdated(Either<List<Workspace>, FlowyError> workspacesOrFailed) {
|
||||||
// fetch workspaces
|
// fetch workspaces
|
||||||
// iUserImpl.fetchWorkspaces().then((result) {
|
// iUserImpl.fetchWorkspaces().then((result) {
|
||||||
// result.fold(
|
// result.fold(
|
||||||
|
@ -21,12 +21,9 @@ class ViewBloc extends Bloc<ViewEvent, ViewState> {
|
|||||||
on<ViewEvent>((event, emit) async {
|
on<ViewEvent>((event, emit) async {
|
||||||
await event.map(
|
await event.map(
|
||||||
initial: (e) {
|
initial: (e) {
|
||||||
// TODO: Listener can be refactored to a stream.
|
listener.start(onViewUpdated: (result) {
|
||||||
listener.updatedNotifier.addPublishListener((result) {
|
|
||||||
// emit.forEach(stream, onData: onData)
|
|
||||||
add(ViewEvent.viewDidUpdate(result));
|
add(ViewEvent.viewDidUpdate(result));
|
||||||
});
|
});
|
||||||
listener.start();
|
|
||||||
emit(state);
|
emit(state);
|
||||||
},
|
},
|
||||||
setIsEditing: (e) {
|
setIsEditing: (e) {
|
||||||
@ -34,14 +31,12 @@ class ViewBloc extends Bloc<ViewEvent, ViewState> {
|
|||||||
},
|
},
|
||||||
viewDidUpdate: (e) {
|
viewDidUpdate: (e) {
|
||||||
e.result.fold(
|
e.result.fold(
|
||||||
(view) =>
|
(view) => emit(state.copyWith(view: view, successOrFailure: left(unit))),
|
||||||
emit(state.copyWith(view: view, successOrFailure: left(unit))),
|
|
||||||
(error) => emit(state.copyWith(successOrFailure: right(error))),
|
(error) => emit(state.copyWith(successOrFailure: right(error))),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
rename: (e) async {
|
rename: (e) async {
|
||||||
final result =
|
final result = await service.updateView(viewId: view.id, name: e.newName);
|
||||||
await service.updateView(viewId: view.id, name: e.newName);
|
|
||||||
emit(
|
emit(
|
||||||
result.fold(
|
result.fold(
|
||||||
(l) => state.copyWith(successOrFailure: left(unit)),
|
(l) => state.copyWith(successOrFailure: left(unit)),
|
||||||
@ -74,7 +69,7 @@ class ViewBloc extends Bloc<ViewEvent, ViewState> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> close() async {
|
Future<void> close() async {
|
||||||
await listener.close();
|
await listener.stop();
|
||||||
return super.close();
|
return super.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -86,8 +81,7 @@ class ViewEvent with _$ViewEvent {
|
|||||||
const factory ViewEvent.rename(String newName) = Rename;
|
const factory ViewEvent.rename(String newName) = Rename;
|
||||||
const factory ViewEvent.delete() = Delete;
|
const factory ViewEvent.delete() = Delete;
|
||||||
const factory ViewEvent.duplicate() = Duplicate;
|
const factory ViewEvent.duplicate() = Duplicate;
|
||||||
const factory ViewEvent.viewDidUpdate(Either<View, FlowyError> result) =
|
const factory ViewEvent.viewDidUpdate(Either<View, FlowyError> result) = ViewDidUpdate;
|
||||||
ViewDidUpdate;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
|
@ -15,9 +15,9 @@ typedef RestoreViewNotifiedValue = Either<View, FlowyError>;
|
|||||||
|
|
||||||
class ViewListener {
|
class ViewListener {
|
||||||
StreamSubscription<SubscribeObject>? _subscription;
|
StreamSubscription<SubscribeObject>? _subscription;
|
||||||
PublishNotifier<UpdateViewNotifiedValue> updatedNotifier = PublishNotifier<UpdateViewNotifiedValue>();
|
final PublishNotifier<UpdateViewNotifiedValue> _updatedViewNotifier = PublishNotifier();
|
||||||
PublishNotifier<DeleteViewNotifyValue> deletedNotifier = PublishNotifier<DeleteViewNotifyValue>();
|
final PublishNotifier<DeleteViewNotifyValue> _deletedNotifier = PublishNotifier();
|
||||||
PublishNotifier<RestoreViewNotifiedValue> restoredNotifier = PublishNotifier<RestoreViewNotifiedValue>();
|
final PublishNotifier<RestoreViewNotifiedValue> _restoredNotifier = PublishNotifier();
|
||||||
FolderNotificationParser? _parser;
|
FolderNotificationParser? _parser;
|
||||||
View view;
|
View view;
|
||||||
|
|
||||||
@ -25,7 +25,29 @@ class ViewListener {
|
|||||||
required this.view,
|
required this.view,
|
||||||
});
|
});
|
||||||
|
|
||||||
void start() {
|
void start({
|
||||||
|
void Function(UpdateViewNotifiedValue)? onViewUpdated,
|
||||||
|
void Function(DeleteViewNotifyValue)? onViewDeleted,
|
||||||
|
void Function(RestoreViewNotifiedValue)? onViewRestored,
|
||||||
|
}) {
|
||||||
|
if (onViewUpdated != null) {
|
||||||
|
_updatedViewNotifier.addListener(() {
|
||||||
|
onViewUpdated(_updatedViewNotifier.currentValue!);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (onViewDeleted != null) {
|
||||||
|
_deletedNotifier.addListener(() {
|
||||||
|
onViewDeleted(_deletedNotifier.currentValue!);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (onViewRestored != null) {
|
||||||
|
_restoredNotifier.addListener(() {
|
||||||
|
onViewRestored(_restoredNotifier.currentValue!);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
_parser = FolderNotificationParser(
|
_parser = FolderNotificationParser(
|
||||||
id: view.id,
|
id: view.id,
|
||||||
callback: (ty, result) {
|
callback: (ty, result) {
|
||||||
@ -40,20 +62,20 @@ class ViewListener {
|
|||||||
switch (ty) {
|
switch (ty) {
|
||||||
case FolderNotification.ViewUpdated:
|
case FolderNotification.ViewUpdated:
|
||||||
result.fold(
|
result.fold(
|
||||||
(payload) => updatedNotifier.value = left(View.fromBuffer(payload)),
|
(payload) => _updatedViewNotifier.value = left(View.fromBuffer(payload)),
|
||||||
(error) => updatedNotifier.value = right(error),
|
(error) => _updatedViewNotifier.value = right(error),
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case FolderNotification.ViewDeleted:
|
case FolderNotification.ViewDeleted:
|
||||||
result.fold(
|
result.fold(
|
||||||
(payload) => deletedNotifier.value = left(View.fromBuffer(payload)),
|
(payload) => _deletedNotifier.value = left(View.fromBuffer(payload)),
|
||||||
(error) => deletedNotifier.value = right(error),
|
(error) => _deletedNotifier.value = right(error),
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case FolderNotification.ViewRestored:
|
case FolderNotification.ViewRestored:
|
||||||
result.fold(
|
result.fold(
|
||||||
(payload) => restoredNotifier.value = left(View.fromBuffer(payload)),
|
(payload) => _restoredNotifier.value = left(View.fromBuffer(payload)),
|
||||||
(error) => restoredNotifier.value = right(error),
|
(error) => _restoredNotifier.value = right(error),
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -61,11 +83,11 @@ class ViewListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> close() async {
|
Future<void> stop() async {
|
||||||
_parser = null;
|
_parser = null;
|
||||||
await _subscription?.cancel();
|
await _subscription?.cancel();
|
||||||
updatedNotifier.dispose();
|
_updatedViewNotifier.dispose();
|
||||||
deletedNotifier.dispose();
|
_deletedNotifier.dispose();
|
||||||
restoredNotifier.dispose();
|
_restoredNotifier.dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,8 +16,9 @@ class WelcomeBloc extends Bloc<WelcomeEvent, WelcomeState> {
|
|||||||
on<WelcomeEvent>(
|
on<WelcomeEvent>(
|
||||||
(event, emit) async {
|
(event, emit) async {
|
||||||
await event.map(initial: (e) async {
|
await event.map(initial: (e) async {
|
||||||
userListener.workspaceUpdatedNotifier.addPublishListener(_workspacesUpdated);
|
userListener.start(
|
||||||
userListener.start();
|
onWorkspaceListUpdated: (result) => add(WelcomeEvent.workspacesReveived(result)),
|
||||||
|
);
|
||||||
//
|
//
|
||||||
await _fetchWorkspaces(emit);
|
await _fetchWorkspaces(emit);
|
||||||
}, openWorkspace: (e) async {
|
}, openWorkspace: (e) async {
|
||||||
@ -74,10 +75,6 @@ class WelcomeBloc extends Bloc<WelcomeEvent, WelcomeState> {
|
|||||||
},
|
},
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
void _workspacesUpdated(Either<List<Workspace>, FlowyError> workspacesOrFail) {
|
|
||||||
add(WelcomeEvent.workspacesReveived(workspacesOrFail));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import 'package:app_flowy/plugin/plugin.dart';
|
import 'package:app_flowy/plugin/plugin.dart';
|
||||||
import 'package:app_flowy/workspace/application/home/home_bloc.dart';
|
import 'package:app_flowy/workspace/application/home/home_bloc.dart';
|
||||||
import 'package:app_flowy/workspace/application/home/home_listen_bloc.dart';
|
|
||||||
import 'package:app_flowy/workspace/presentation/widgets/edit_pannel/pannel_animation.dart';
|
import 'package:app_flowy/workspace/presentation/widgets/edit_pannel/pannel_animation.dart';
|
||||||
import 'package:app_flowy/workspace/presentation/widgets/float_bubble/question_bubble.dart';
|
import 'package:app_flowy/workspace/presentation/widgets/float_bubble/question_bubble.dart';
|
||||||
import 'package:app_flowy/startup/startup.dart';
|
import 'package:app_flowy/startup/startup.dart';
|
||||||
@ -46,22 +45,20 @@ class _HomeScreenState extends State<HomeScreen> {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return MultiBlocProvider(
|
return MultiBlocProvider(
|
||||||
providers: [
|
providers: [
|
||||||
BlocProvider<HomeListenBloc>(
|
BlocProvider<HomeBloc>(
|
||||||
create: (context) => getIt<HomeListenBloc>(param1: widget.user)..add(const HomeListenEvent.started()),
|
create: (context) {
|
||||||
|
return HomeBloc(widget.user, widget.workspaceSetting)..add(const HomeEvent.initial());
|
||||||
|
},
|
||||||
),
|
),
|
||||||
BlocProvider<HomeBloc>(create: (context) => getIt<HomeBloc>()),
|
|
||||||
],
|
],
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
key: HomeScreen.scaffoldKey,
|
key: HomeScreen.scaffoldKey,
|
||||||
body: BlocListener<HomeListenBloc, HomeListenState>(
|
body: BlocListener<HomeBloc, HomeState>(
|
||||||
|
listenWhen: (p, c) => p.unauthorized != c.unauthorized,
|
||||||
listener: (context, state) {
|
listener: (context, state) {
|
||||||
state.map(
|
if (state.unauthorized) {
|
||||||
loading: (_) {},
|
Log.error("Push to login screen when user token was invalid");
|
||||||
unauthorized: (unauthorized) {
|
}
|
||||||
// TODO: push to login screen when user token was invalid
|
|
||||||
Log.error("Push to login screen when user token was invalid");
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
child: BlocBuilder<HomeBloc, HomeState>(
|
child: BlocBuilder<HomeBloc, HomeState>(
|
||||||
buildWhen: (previous, current) => previous != current,
|
buildWhen: (previous, current) => previous != current,
|
||||||
@ -73,7 +70,7 @@ class _HomeScreenState extends State<HomeScreen> {
|
|||||||
return FlowyContainer(
|
return FlowyContainer(
|
||||||
Theme.of(context).colorScheme.surface,
|
Theme.of(context).colorScheme.surface,
|
||||||
// Colors.white,
|
// Colors.white,
|
||||||
child: _buildBody(state, context.read<HomeBloc>().state.forceCollapse),
|
child: _buildBody(state),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -82,14 +79,15 @@ class _HomeScreenState extends State<HomeScreen> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildBody(HomeState state, bool forceCollapse) {
|
Widget _buildBody(HomeState state) {
|
||||||
return LayoutBuilder(
|
return LayoutBuilder(
|
||||||
builder: (BuildContext context, BoxConstraints constraints) {
|
builder: (BuildContext context, BoxConstraints constraints) {
|
||||||
final layout = HomeLayout(context, constraints, forceCollapse);
|
final layout = HomeLayout(context, constraints, state.forceCollapse);
|
||||||
const homeStack = HomeStack();
|
const homeStack = HomeStack();
|
||||||
final menu = _buildHomeMenu(
|
final menu = _buildHomeMenu(
|
||||||
layout: layout,
|
layout: layout,
|
||||||
context: context,
|
context: context,
|
||||||
|
state: state,
|
||||||
);
|
);
|
||||||
final editPannel = _buildEditPannel(
|
final editPannel = _buildEditPannel(
|
||||||
homeState: state,
|
homeState: state,
|
||||||
@ -108,20 +106,21 @@ class _HomeScreenState extends State<HomeScreen> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildHomeMenu({required HomeLayout layout, required BuildContext context}) {
|
Widget _buildHomeMenu({required HomeLayout layout, required BuildContext context, required HomeState state}) {
|
||||||
if (initialView == null && widget.workspaceSetting.hasLatestView()) {
|
final workspaceSetting = state.workspaceSetting;
|
||||||
initialView = widget.workspaceSetting.latestView;
|
if (initialView == null && workspaceSetting.hasLatestView()) {
|
||||||
|
initialView = workspaceSetting.latestView;
|
||||||
final plugin = makePlugin(pluginType: initialView!.pluginType, data: initialView);
|
final plugin = makePlugin(pluginType: initialView!.pluginType, data: initialView);
|
||||||
getIt<HomeStackManager>().setPlugin(plugin);
|
getIt<HomeStackManager>().setPlugin(plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
HomeMenu homeMenu = HomeMenu(
|
HomeMenu homeMenu = HomeMenu(
|
||||||
user: widget.user,
|
user: widget.user,
|
||||||
workspaceSetting: widget.workspaceSetting,
|
workspaceSetting: workspaceSetting,
|
||||||
collapsedNotifier: getIt<HomeStackManager>().collapsedNotifier,
|
collapsedNotifier: getIt<HomeStackManager>().collapsedNotifier,
|
||||||
);
|
);
|
||||||
|
|
||||||
final latestView = widget.workspaceSetting.hasLatestView() ? widget.workspaceSetting.latestView : null;
|
final latestView = workspaceSetting.hasLatestView() ? workspaceSetting.latestView : null;
|
||||||
getIt<MenuSharedState>().latestOpenView = latestView;
|
getIt<MenuSharedState>().latestOpenView = latestView;
|
||||||
|
|
||||||
return FocusTraversalGroup(child: RepaintBoundary(child: homeMenu));
|
return FocusTraversalGroup(child: RepaintBoundary(child: homeMenu));
|
||||||
|
@ -60,7 +60,7 @@ class DocumentPlugin implements Plugin {
|
|||||||
DocumentPlugin({required PluginType pluginType, required View view, Key? key}) : _view = view {
|
DocumentPlugin({required PluginType pluginType, required View view, Key? key}) : _view = view {
|
||||||
_pluginType = pluginType;
|
_pluginType = pluginType;
|
||||||
_listener = getIt<ViewListener>(param1: view);
|
_listener = getIt<ViewListener>(param1: view);
|
||||||
_listener?.updatedNotifier.addPublishListener((result) {
|
_listener?.start(onViewUpdated: (result) {
|
||||||
result.fold(
|
result.fold(
|
||||||
(newView) {
|
(newView) {
|
||||||
_view = newView;
|
_view = newView;
|
||||||
@ -69,12 +69,11 @@ class DocumentPlugin implements Plugin {
|
|||||||
(error) {},
|
(error) {},
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
_listener?.start();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_listener?.close();
|
_listener?.stop();
|
||||||
_listener = null;
|
_listener = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ GridCellWidget buildGridCellWidget(GridCell gridCell, GridCellCache cellCache, {
|
|||||||
case FieldType.Checkbox:
|
case FieldType.Checkbox:
|
||||||
return CheckboxCell(cellContextBuilder: cellContextBuilder, key: key);
|
return CheckboxCell(cellContextBuilder: cellContextBuilder, key: key);
|
||||||
case FieldType.DateTime:
|
case FieldType.DateTime:
|
||||||
return DateCell(cellContextBuilder: cellContextBuilder, key: key);
|
return DateCell(cellContextBuilder: cellContextBuilder, key: key, style: style);
|
||||||
case FieldType.SingleSelect:
|
case FieldType.SingleSelect:
|
||||||
return SingleSelectCell(cellContextBuilder: cellContextBuilder, style: style, key: key);
|
return SingleSelectCell(cellContextBuilder: cellContextBuilder, style: style, key: key);
|
||||||
case FieldType.MultiSelect:
|
case FieldType.MultiSelect:
|
||||||
|
@ -8,6 +8,12 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
|||||||
import 'package:table_calendar/table_calendar.dart';
|
import 'package:table_calendar/table_calendar.dart';
|
||||||
import 'cell_builder.dart';
|
import 'cell_builder.dart';
|
||||||
|
|
||||||
|
class DateCellStyle extends GridCellStyle {
|
||||||
|
Alignment alignment;
|
||||||
|
|
||||||
|
DateCellStyle({this.alignment = Alignment.center});
|
||||||
|
}
|
||||||
|
|
||||||
abstract class GridCellDelegate {
|
abstract class GridCellDelegate {
|
||||||
void onFocus(bool isFocus);
|
void onFocus(bool isFocus);
|
||||||
GridCellDelegate get delegate;
|
GridCellDelegate get delegate;
|
||||||
@ -15,11 +21,19 @@ abstract class GridCellDelegate {
|
|||||||
|
|
||||||
class DateCell extends GridCellWidget {
|
class DateCell extends GridCellWidget {
|
||||||
final GridCellContextBuilder cellContextBuilder;
|
final GridCellContextBuilder cellContextBuilder;
|
||||||
|
late final DateCellStyle? cellStyle;
|
||||||
|
|
||||||
DateCell({
|
DateCell({
|
||||||
|
GridCellStyle? style,
|
||||||
required this.cellContextBuilder,
|
required this.cellContextBuilder,
|
||||||
Key? key,
|
Key? key,
|
||||||
}) : super(key: key);
|
}) : super(key: key) {
|
||||||
|
if (style != null) {
|
||||||
|
cellStyle = (style as DateCellStyle);
|
||||||
|
} else {
|
||||||
|
cellStyle = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<DateCell> createState() => _DateCellState();
|
State<DateCell> createState() => _DateCellState();
|
||||||
@ -37,6 +51,7 @@ class _DateCellState extends State<DateCell> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final alignment = widget.cellStyle != null ? widget.cellStyle!.alignment : Alignment.center;
|
||||||
return BlocProvider.value(
|
return BlocProvider.value(
|
||||||
value: _cellBloc,
|
value: _cellBloc,
|
||||||
child: BlocBuilder<DateCellBloc, DateCellState>(
|
child: BlocBuilder<DateCellBloc, DateCellState>(
|
||||||
@ -57,7 +72,7 @@ class _DateCellState extends State<DateCell> {
|
|||||||
child: MouseRegion(
|
child: MouseRegion(
|
||||||
opaque: false,
|
opaque: false,
|
||||||
cursor: SystemMouseCursors.click,
|
cursor: SystemMouseCursors.click,
|
||||||
child: Center(child: FlowyText.medium(state.content, fontSize: 12)),
|
child: Align(alignment: alignment, child: FlowyText.medium(state.content, fontSize: 12)),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -60,17 +60,35 @@ extension SelectOptionColorExtension on SelectOptionColor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class SelectOptionTag extends StatelessWidget {
|
class SelectOptionTag extends StatelessWidget {
|
||||||
final SelectOption option;
|
final String name;
|
||||||
|
final Color color;
|
||||||
final bool isSelected;
|
final bool isSelected;
|
||||||
const SelectOptionTag({required this.option, this.isSelected = false, Key? key}) : super(key: key);
|
const SelectOptionTag({
|
||||||
|
required this.name,
|
||||||
|
required this.color,
|
||||||
|
this.isSelected = false,
|
||||||
|
Key? key,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
factory SelectOptionTag.fromSelectOption({
|
||||||
|
required BuildContext context,
|
||||||
|
required SelectOption option,
|
||||||
|
bool isSelected = false,
|
||||||
|
}) {
|
||||||
|
return SelectOptionTag(
|
||||||
|
name: option.name,
|
||||||
|
color: option.color.make(context),
|
||||||
|
isSelected: isSelected,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return ChoiceChip(
|
return ChoiceChip(
|
||||||
pressElevation: 1,
|
pressElevation: 1,
|
||||||
label: FlowyText.medium(option.name, fontSize: 12),
|
label: FlowyText.medium(name, fontSize: 12),
|
||||||
selectedColor: option.color.make(context),
|
selectedColor: color,
|
||||||
backgroundColor: option.color.make(context),
|
backgroundColor: color,
|
||||||
labelPadding: const EdgeInsets.symmetric(horizontal: 6),
|
labelPadding: const EdgeInsets.symmetric(horizontal: 6),
|
||||||
selected: true,
|
selected: true,
|
||||||
onSelected: (_) {},
|
onSelected: (_) {},
|
||||||
|
@ -150,7 +150,14 @@ class _SelectOptionCell extends StatelessWidget {
|
|||||||
child: FlowyText.medium(cellStyle!.placeholder, fontSize: 14, color: theme.shader3),
|
child: FlowyText.medium(cellStyle!.placeholder, fontSize: 14, color: theme.shader3),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
final tags = selectOptions.map((option) => SelectOptionTag(option: option)).toList();
|
final tags = selectOptions
|
||||||
|
.map(
|
||||||
|
(option) => SelectOptionTag.fromSelectOption(
|
||||||
|
context: context,
|
||||||
|
option: option,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toList();
|
||||||
child = Align(
|
child = Align(
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
child: Wrap(children: tags, spacing: 4, runSpacing: 4),
|
child: Wrap(children: tags, spacing: 4, runSpacing: 4),
|
||||||
|
@ -104,9 +104,18 @@ class _OptionList extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocBuilder<SelectOptionEditorBloc, SelectOptionEditorState>(
|
return BlocBuilder<SelectOptionEditorBloc, SelectOptionEditorState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
final cells = state.options.map((option) {
|
List<Widget> cells = [];
|
||||||
|
cells.addAll(state.options.map((option) {
|
||||||
return _SelectOptionCell(option, state.selectedOptions.contains(option));
|
return _SelectOptionCell(option, state.selectedOptions.contains(option));
|
||||||
}).toList();
|
}).toList());
|
||||||
|
|
||||||
|
state.createOption.fold(
|
||||||
|
() => null,
|
||||||
|
(createOption) {
|
||||||
|
cells.add(_CreateOptionCell(name: createOption));
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
final list = ListView.separated(
|
final list = ListView.separated(
|
||||||
shrinkWrap: true,
|
shrinkWrap: true,
|
||||||
controller: ScrollController(),
|
controller: ScrollController(),
|
||||||
@ -119,7 +128,11 @@ class _OptionList extends StatelessWidget {
|
|||||||
return cells[index];
|
return cells[index];
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
return list;
|
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.all(3.0),
|
||||||
|
child: list,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -177,6 +190,30 @@ class _Title extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _CreateOptionCell extends StatelessWidget {
|
||||||
|
final String name;
|
||||||
|
const _CreateOptionCell({required this.name, Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final theme = context.watch<AppTheme>();
|
||||||
|
return Row(
|
||||||
|
children: [
|
||||||
|
FlowyText.medium(
|
||||||
|
LocaleKeys.grid_selectOption_create.tr(),
|
||||||
|
fontSize: 12,
|
||||||
|
color: theme.shader3,
|
||||||
|
),
|
||||||
|
const HSpace(10),
|
||||||
|
SelectOptionTag(
|
||||||
|
name: name,
|
||||||
|
color: theme.shader6,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class _SelectOptionCell extends StatelessWidget {
|
class _SelectOptionCell extends StatelessWidget {
|
||||||
final SelectOption option;
|
final SelectOption option;
|
||||||
final bool isSelected;
|
final bool isSelected;
|
||||||
@ -206,7 +243,11 @@ class _SelectOptionCell extends StatelessWidget {
|
|||||||
style: HoverStyle(hoverColor: theme.hover),
|
style: HoverStyle(hoverColor: theme.hover),
|
||||||
builder: (_, onHover) {
|
builder: (_, onHover) {
|
||||||
List<Widget> children = [
|
List<Widget> children = [
|
||||||
SelectOptionTag(option: option, isSelected: isSelected),
|
SelectOptionTag(
|
||||||
|
name: option.name,
|
||||||
|
color: option.color.make(context),
|
||||||
|
isSelected: isSelected,
|
||||||
|
),
|
||||||
const Spacer(),
|
const Spacer(),
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -223,10 +264,7 @@ class _SelectOptionCell extends StatelessWidget {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
return Padding(
|
return Row(children: children);
|
||||||
padding: const EdgeInsets.all(3.0),
|
|
||||||
child: Row(children: children),
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,7 @@ class SelectOptionTextField extends StatelessWidget {
|
|||||||
borderRadius: Corners.s10Border,
|
borderRadius: Corners.s10Border,
|
||||||
),
|
),
|
||||||
isDense: true,
|
isDense: true,
|
||||||
prefixIcon: _renderTags(sc),
|
prefixIcon: _renderTags(context, sc),
|
||||||
hintText: LocaleKeys.grid_selectOption_searchOption.tr(),
|
hintText: LocaleKeys.grid_selectOption_searchOption.tr(),
|
||||||
prefixIconConstraints: BoxConstraints(maxWidth: distanceToText),
|
prefixIconConstraints: BoxConstraints(maxWidth: distanceToText),
|
||||||
focusedBorder: OutlineInputBorder(
|
focusedBorder: OutlineInputBorder(
|
||||||
@ -90,12 +90,14 @@ class SelectOptionTextField extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget? _renderTags(ScrollController sc) {
|
Widget? _renderTags(BuildContext context, ScrollController sc) {
|
||||||
if (selectedOptionMap.isEmpty) {
|
if (selectedOptionMap.isEmpty) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
final children = selectedOptionMap.values.map((option) => SelectOptionTag(option: option)).toList();
|
final children = selectedOptionMap.values
|
||||||
|
.map((option) => SelectOptionTag.fromSelectOption(context: context, option: option))
|
||||||
|
.toList();
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(8.0),
|
||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
|
@ -1,18 +1,15 @@
|
|||||||
import 'package:app_flowy/startup/startup.dart';
|
import 'package:app_flowy/startup/startup.dart';
|
||||||
import 'package:app_flowy/workspace/application/grid/field/field_editor_bloc.dart';
|
import 'package:app_flowy/workspace/application/grid/field/field_editor_bloc.dart';
|
||||||
import 'package:app_flowy/workspace/application/grid/field/field_service.dart';
|
import 'package:app_flowy/workspace/application/grid/field/field_service.dart';
|
||||||
import 'package:app_flowy/workspace/application/grid/field/field_switch_bloc.dart';
|
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
import 'package:flowy_infra_ui/style_widget/text.dart';
|
import 'package:flowy_infra_ui/style_widget/text.dart';
|
||||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||||
import 'package:flowy_sdk/log.dart';
|
|
||||||
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' show Field;
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:app_flowy/generated/locale_keys.g.dart';
|
import 'package:app_flowy/generated/locale_keys.g.dart';
|
||||||
import 'field_name_input.dart';
|
import 'field_name_input.dart';
|
||||||
import 'field_switcher.dart';
|
import 'field_editor_pannel.dart';
|
||||||
|
|
||||||
class FieldEditor extends FlowyOverlayDelegate {
|
class FieldEditor extends FlowyOverlayDelegate {
|
||||||
final String gridId;
|
final String gridId;
|
||||||
@ -30,7 +27,6 @@ class FieldEditor extends FlowyOverlayDelegate {
|
|||||||
BuildContext context, {
|
BuildContext context, {
|
||||||
AnchorDirection anchorDirection = AnchorDirection.bottomWithLeftAligned,
|
AnchorDirection anchorDirection = AnchorDirection.bottomWithLeftAligned,
|
||||||
}) {
|
}) {
|
||||||
Log.trace("Show $identifier()");
|
|
||||||
FlowyOverlay.of(context).remove(identifier());
|
FlowyOverlay.of(context).remove(identifier());
|
||||||
FlowyOverlay.of(context).insertWithAnchor(
|
FlowyOverlay.of(context).insertWithAnchor(
|
||||||
widget: OverlayContainer(
|
widget: OverlayContainer(
|
||||||
@ -69,16 +65,24 @@ class _FieldEditorWidget extends StatelessWidget {
|
|||||||
value: editorBloc,
|
value: editorBloc,
|
||||||
child: BlocBuilder<FieldEditorBloc, FieldEditorState>(
|
child: BlocBuilder<FieldEditorBloc, FieldEditorState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
return state.field.fold(
|
return state.editFieldContext.fold(
|
||||||
() => const SizedBox(),
|
() => const SizedBox(),
|
||||||
(field) => ListView(
|
(editFieldContext) => ListView(
|
||||||
shrinkWrap: true,
|
shrinkWrap: true,
|
||||||
children: [
|
children: [
|
||||||
FlowyText.medium(LocaleKeys.grid_field_editProperty.tr(), fontSize: 12),
|
FlowyText.medium(LocaleKeys.grid_field_editProperty.tr(), fontSize: 12),
|
||||||
const VSpace(10),
|
const VSpace(10),
|
||||||
const _FieldNameTextField(),
|
const _FieldNameTextField(),
|
||||||
const VSpace(10),
|
const VSpace(10),
|
||||||
_renderSwitchButton(context, field, state),
|
FieldEditorPannel(
|
||||||
|
editFieldContext: editFieldContext,
|
||||||
|
onSwitchToField: (fieldId, fieldType) {
|
||||||
|
return fieldContextLoader.switchToField(fieldId, fieldType);
|
||||||
|
},
|
||||||
|
onUpdated: (field, typeOptionData) {
|
||||||
|
context.read<FieldEditorBloc>().add(FieldEditorEvent.updateField(field, typeOptionData));
|
||||||
|
},
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -86,18 +90,6 @@ class _FieldEditorWidget extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _renderSwitchButton(BuildContext context, Field field, FieldEditorState state) {
|
|
||||||
return FieldSwitcher(
|
|
||||||
switchContext: SwitchFieldContext(state.gridId, field, state.typeOptionData),
|
|
||||||
onSwitchToField: (fieldId, fieldType) {
|
|
||||||
return fieldContextLoader.switchToField(fieldId, fieldType);
|
|
||||||
},
|
|
||||||
onUpdated: (field, typeOptionData) {
|
|
||||||
context.read<FieldEditorBloc>().add(FieldEditorEvent.switchField(field, typeOptionData));
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class _FieldNameTextField extends StatelessWidget {
|
class _FieldNameTextField extends StatelessWidget {
|
||||||
@ -105,11 +97,16 @@ class _FieldNameTextField extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocBuilder<FieldEditorBloc, FieldEditorState>(
|
return BlocSelector<FieldEditorBloc, FieldEditorState, String>(
|
||||||
buildWhen: (previous, current) => previous.fieldName != current.fieldName,
|
selector: (state) {
|
||||||
builder: (context, state) {
|
return state.editFieldContext.fold(
|
||||||
|
() => "",
|
||||||
|
(editFieldContext) => editFieldContext.gridField.name,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
builder: (context, name) {
|
||||||
return FieldNameTextField(
|
return FieldNameTextField(
|
||||||
name: state.fieldName,
|
name: name,
|
||||||
errorText: context.read<FieldEditorBloc>().state.errorText,
|
errorText: context.read<FieldEditorBloc>().state.errorText,
|
||||||
onNameChanged: (newName) {
|
onNameChanged: (newName) {
|
||||||
context.read<FieldEditorBloc>().add(FieldEditorEvent.updateName(newName));
|
context.read<FieldEditorBloc>().add(FieldEditorEvent.updateName(newName));
|
||||||
|
@ -30,30 +30,30 @@ typedef SwitchToFieldCallback = Future<Either<EditFieldContext, FlowyError>> Fun
|
|||||||
FieldType fieldType,
|
FieldType fieldType,
|
||||||
);
|
);
|
||||||
|
|
||||||
class FieldSwitcher extends StatefulWidget {
|
class FieldEditorPannel extends StatefulWidget {
|
||||||
final SwitchFieldContext switchContext;
|
final EditFieldContext editFieldContext;
|
||||||
final UpdateFieldCallback onUpdated;
|
final UpdateFieldCallback onUpdated;
|
||||||
final SwitchToFieldCallback onSwitchToField;
|
final SwitchToFieldCallback onSwitchToField;
|
||||||
|
|
||||||
const FieldSwitcher({
|
const FieldEditorPannel({
|
||||||
required this.switchContext,
|
required this.editFieldContext,
|
||||||
required this.onUpdated,
|
required this.onUpdated,
|
||||||
required this.onSwitchToField,
|
required this.onSwitchToField,
|
||||||
Key? key,
|
Key? key,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<FieldSwitcher> createState() => _FieldSwitcherState();
|
State<FieldEditorPannel> createState() => _FieldEditorPannelState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _FieldSwitcherState extends State<FieldSwitcher> {
|
class _FieldEditorPannelState extends State<FieldEditorPannel> {
|
||||||
String? currentOverlayIdentifier;
|
String? currentOverlayIdentifier;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
create: (context) => getIt<FieldSwitcherBloc>(param1: widget.switchContext),
|
create: (context) => getIt<FieldEditorPannelBloc>(param1: widget.editFieldContext),
|
||||||
child: BlocConsumer<FieldSwitcherBloc, FieldSwitchState>(
|
child: BlocConsumer<FieldEditorPannelBloc, FieldEditorPannelState>(
|
||||||
listener: (context, state) {
|
listener: (context, state) {
|
||||||
widget.onUpdated(state.field, state.typeOptionData);
|
widget.onUpdated(state.field, state.typeOptionData);
|
||||||
},
|
},
|
||||||
@ -87,8 +87,8 @@ class _FieldSwitcherState extends State<FieldSwitcher> {
|
|||||||
widget.onSwitchToField(field.id, newFieldType).then((result) {
|
widget.onSwitchToField(field.id, newFieldType).then((result) {
|
||||||
result.fold(
|
result.fold(
|
||||||
(editFieldContext) {
|
(editFieldContext) {
|
||||||
context.read<FieldSwitcherBloc>().add(
|
context.read<FieldEditorPannelBloc>().add(
|
||||||
FieldSwitchEvent.toFieldType(
|
FieldEditorPannelEvent.toFieldType(
|
||||||
editFieldContext.gridField,
|
editFieldContext.gridField,
|
||||||
editFieldContext.typeOptionData,
|
editFieldContext.typeOptionData,
|
||||||
),
|
),
|
||||||
@ -108,7 +108,7 @@ class _FieldSwitcherState extends State<FieldSwitcher> {
|
|||||||
|
|
||||||
Widget? _typeOptionWidget({
|
Widget? _typeOptionWidget({
|
||||||
required BuildContext context,
|
required BuildContext context,
|
||||||
required FieldSwitchState state,
|
required FieldEditorPannelState state,
|
||||||
}) {
|
}) {
|
||||||
final overlayDelegate = TypeOptionOverlayDelegate(
|
final overlayDelegate = TypeOptionOverlayDelegate(
|
||||||
showOverlay: _showOverlay,
|
showOverlay: _showOverlay,
|
||||||
@ -116,7 +116,7 @@ class _FieldSwitcherState extends State<FieldSwitcher> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
final dataDelegate = TypeOptionDataDelegate(didUpdateTypeOptionData: (data) {
|
final dataDelegate = TypeOptionDataDelegate(didUpdateTypeOptionData: (data) {
|
||||||
context.read<FieldSwitcherBloc>().add(FieldSwitchEvent.didUpdateTypeOptionData(data));
|
context.read<FieldEditorPannelBloc>().add(FieldEditorPannelEvent.didUpdateTypeOptionData(data));
|
||||||
});
|
});
|
||||||
|
|
||||||
final typeOptionContext = TypeOptionContext(
|
final typeOptionContext = TypeOptionContext(
|
@ -1,7 +1,7 @@
|
|||||||
import 'package:app_flowy/startup/startup.dart';
|
import 'package:app_flowy/startup/startup.dart';
|
||||||
import 'package:app_flowy/workspace/application/grid/field/type_option/date_bloc.dart';
|
import 'package:app_flowy/workspace/application/grid/field/type_option/date_bloc.dart';
|
||||||
import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart';
|
import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart';
|
||||||
import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_switcher.dart';
|
import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart' hide DateFormat;
|
import 'package:easy_localization/easy_localization.dart' hide DateFormat;
|
||||||
import 'package:app_flowy/generated/locale_keys.g.dart';
|
import 'package:app_flowy/generated/locale_keys.g.dart';
|
||||||
import 'package:flowy_infra/image.dart';
|
import 'package:flowy_infra/image.dart';
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import 'package:app_flowy/workspace/application/grid/field/type_option/field_option_pannel_bloc.dart';
|
import 'package:app_flowy/workspace/application/grid/field/type_option/field_option_pannel_bloc.dart';
|
||||||
import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart';
|
import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart';
|
||||||
import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/common/text_field.dart';
|
import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/common/text_field.dart';
|
||||||
import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_switcher.dart';
|
import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart';
|
||||||
import 'package:flowy_infra/image.dart';
|
import 'package:flowy_infra/image.dart';
|
||||||
import 'package:flowy_infra/theme.dart';
|
import 'package:flowy_infra/theme.dart';
|
||||||
import 'package:flowy_infra_ui/style_widget/button.dart';
|
import 'package:flowy_infra_ui/style_widget/button.dart';
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import 'package:app_flowy/workspace/application/grid/field/type_option/multi_select_bloc.dart';
|
import 'package:app_flowy/workspace/application/grid/field/type_option/multi_select_bloc.dart';
|
||||||
import 'package:app_flowy/workspace/application/grid/field/type_option/type_option_service.dart';
|
import 'package:app_flowy/workspace/application/grid/field/type_option/type_option_service.dart';
|
||||||
import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_switcher.dart';
|
import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ import 'package:app_flowy/workspace/application/grid/field/type_option/number_bl
|
|||||||
import 'package:app_flowy/workspace/application/grid/field/type_option/number_format_bloc.dart';
|
import 'package:app_flowy/workspace/application/grid/field/type_option/number_format_bloc.dart';
|
||||||
import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart';
|
import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart';
|
||||||
import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/common/text_field.dart';
|
import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/common/text_field.dart';
|
||||||
import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_switcher.dart';
|
import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart';
|
||||||
import 'package:flowy_infra/image.dart';
|
import 'package:flowy_infra/image.dart';
|
||||||
import 'package:flowy_infra/theme.dart';
|
import 'package:flowy_infra/theme.dart';
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import 'package:app_flowy/workspace/application/grid/field/type_option/single_select_bloc.dart';
|
import 'package:app_flowy/workspace/application/grid/field/type_option/single_select_bloc.dart';
|
||||||
import 'package:app_flowy/workspace/application/grid/field/type_option/type_option_service.dart';
|
import 'package:app_flowy/workspace/application/grid/field/type_option/type_option_service.dart';
|
||||||
import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_switcher.dart';
|
import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_editor_pannel.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'field_option_pannel.dart';
|
import 'field_option_pannel.dart';
|
||||||
|
@ -6,9 +6,11 @@ import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.d
|
|||||||
import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/cell/prelude.dart';
|
import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/cell/prelude.dart';
|
||||||
import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_cell.dart';
|
import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_cell.dart';
|
||||||
import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_editor.dart';
|
import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/field_editor.dart';
|
||||||
|
import 'package:flowy_infra/image.dart';
|
||||||
import 'package:flowy_infra/theme.dart';
|
import 'package:flowy_infra/theme.dart';
|
||||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
import 'package:flowy_infra_ui/style_widget/hover.dart';
|
import 'package:flowy_infra_ui/style_widget/hover.dart';
|
||||||
|
import 'package:flowy_infra_ui/style_widget/icon_button.dart';
|
||||||
import 'package:flowy_infra_ui/style_widget/scrolling/styled_scroll_bar.dart';
|
import 'package:flowy_infra_ui/style_widget/scrolling/styled_scroll_bar.dart';
|
||||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||||
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' show FieldType;
|
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' show FieldType;
|
||||||
@ -66,12 +68,36 @@ class _RowDetailPageState extends State<RowDetailPage> {
|
|||||||
},
|
},
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 80, vertical: 40),
|
padding: const EdgeInsets.symmetric(horizontal: 80, vertical: 40),
|
||||||
child: _PropertyList(cellCache: widget.cellCache),
|
child: Column(
|
||||||
|
children: [
|
||||||
|
SizedBox(
|
||||||
|
height: 40,
|
||||||
|
child: Row(
|
||||||
|
children: const [Spacer(), _CloseButton()],
|
||||||
|
)),
|
||||||
|
Expanded(child: _PropertyList(cellCache: widget.cellCache)),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _CloseButton extends StatelessWidget {
|
||||||
|
const _CloseButton({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final theme = context.watch<AppTheme>();
|
||||||
|
return FlowyIconButton(
|
||||||
|
width: 24,
|
||||||
|
onPressed: () => FlowyOverlay.of(context).remove(RowDetailPage.identifier()),
|
||||||
|
iconPadding: const EdgeInsets.fromLTRB(2, 2, 2, 2),
|
||||||
|
icon: svgWidget("home/close", color: theme.iconColor),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class _PropertyList extends StatelessWidget {
|
class _PropertyList extends StatelessWidget {
|
||||||
final GridCellCache cellCache;
|
final GridCellCache cellCache;
|
||||||
final ScrollController _scrollController;
|
final ScrollController _scrollController;
|
||||||
@ -165,7 +191,9 @@ GridCellStyle? _buildCellStyle(AppTheme theme, FieldType fieldType) {
|
|||||||
case FieldType.Checkbox:
|
case FieldType.Checkbox:
|
||||||
return null;
|
return null;
|
||||||
case FieldType.DateTime:
|
case FieldType.DateTime:
|
||||||
return null;
|
return DateCellStyle(
|
||||||
|
alignment: Alignment.centerLeft,
|
||||||
|
);
|
||||||
case FieldType.MultiSelect:
|
case FieldType.MultiSelect:
|
||||||
return SelectOptionCellStyle(
|
return SelectOptionCellStyle(
|
||||||
placeholder: LocaleKeys.grid_row_textPlaceholder.tr(),
|
placeholder: LocaleKeys.grid_row_textPlaceholder.tr(),
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
|
import 'package:app_flowy/workspace/application/view/view_listener.dart';
|
||||||
import 'package:app_flowy/workspace/application/view/view_service.dart';
|
import 'package:app_flowy/workspace/application/view/view_service.dart';
|
||||||
import 'package:flowy_infra/theme.dart';
|
import 'package:flowy_infra/theme.dart';
|
||||||
|
import 'package:flowy_sdk/log.dart';
|
||||||
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
@ -16,12 +18,26 @@ class ViewLeftBarItem extends StatefulWidget {
|
|||||||
class _ViewLeftBarItemState extends State<ViewLeftBarItem> {
|
class _ViewLeftBarItemState extends State<ViewLeftBarItem> {
|
||||||
final _controller = TextEditingController();
|
final _controller = TextEditingController();
|
||||||
final _focusNode = FocusNode();
|
final _focusNode = FocusNode();
|
||||||
late ViewService serviceService;
|
late ViewService _viewService;
|
||||||
|
late ViewListener _viewListener;
|
||||||
|
late View view;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
serviceService = ViewService(/*view: widget.view*/);
|
view = widget.view;
|
||||||
|
_viewService = ViewService();
|
||||||
_focusNode.addListener(_handleFocusChanged);
|
_focusNode.addListener(_handleFocusChanged);
|
||||||
|
_viewListener = ViewListener(view: widget.view);
|
||||||
|
_viewListener.start(onViewUpdated: (result) {
|
||||||
|
result.fold(
|
||||||
|
(updatedView) {
|
||||||
|
if (mounted) {
|
||||||
|
setState(() => view = updatedView);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
(err) => Log.error(err),
|
||||||
|
);
|
||||||
|
});
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,12 +46,13 @@ class _ViewLeftBarItemState extends State<ViewLeftBarItem> {
|
|||||||
_controller.dispose();
|
_controller.dispose();
|
||||||
_focusNode.removeListener(_handleFocusChanged);
|
_focusNode.removeListener(_handleFocusChanged);
|
||||||
_focusNode.dispose();
|
_focusNode.dispose();
|
||||||
|
_viewListener.stop();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
_controller.text = widget.view.name;
|
_controller.text = view.name;
|
||||||
|
|
||||||
final theme = context.watch<AppTheme>();
|
final theme = context.watch<AppTheme>();
|
||||||
return IntrinsicWidth(
|
return IntrinsicWidth(
|
||||||
@ -63,12 +80,12 @@ class _ViewLeftBarItemState extends State<ViewLeftBarItem> {
|
|||||||
|
|
||||||
void _handleFocusChanged() {
|
void _handleFocusChanged() {
|
||||||
if (_controller.text.isEmpty) {
|
if (_controller.text.isEmpty) {
|
||||||
_controller.text = widget.view.name;
|
_controller.text = view.name;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_controller.text != widget.view.name) {
|
if (_controller.text != view.name) {
|
||||||
serviceService.updateView(viewId: widget.view.id, name: _controller.text);
|
_viewService.updateView(viewId: view.id, name: _controller.text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -176,7 +176,6 @@ class FlowyOverlayState extends State<FlowyOverlay> {
|
|||||||
FlowyOverlayStyle? style,
|
FlowyOverlayStyle? style,
|
||||||
Offset? anchorOffset,
|
Offset? anchorOffset,
|
||||||
}) {
|
}) {
|
||||||
debugPrint("Show overlay: $identifier");
|
|
||||||
this.style = style ?? FlowyOverlayStyle();
|
this.style = style ?? FlowyOverlayStyle();
|
||||||
|
|
||||||
_showOverlay(
|
_showOverlay(
|
||||||
@ -245,6 +244,7 @@ class FlowyOverlayState extends State<FlowyOverlay> {
|
|||||||
OverlapBehaviour? overlapBehaviour,
|
OverlapBehaviour? overlapBehaviour,
|
||||||
FlowyOverlayDelegate? delegate,
|
FlowyOverlayDelegate? delegate,
|
||||||
}) {
|
}) {
|
||||||
|
debugPrint("Show overlay: $identifier");
|
||||||
Widget overlay = widget;
|
Widget overlay = widget;
|
||||||
final offset = anchorOffset ?? Offset.zero;
|
final offset = anchorOffset ?? Offset.zero;
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@ class FolderNotification extends $pb.ProtobufEnum {
|
|||||||
static const FolderNotification WorkspaceUpdated = FolderNotification._(12, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'WorkspaceUpdated');
|
static const FolderNotification WorkspaceUpdated = FolderNotification._(12, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'WorkspaceUpdated');
|
||||||
static const FolderNotification WorkspaceListUpdated = FolderNotification._(13, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'WorkspaceListUpdated');
|
static const FolderNotification WorkspaceListUpdated = FolderNotification._(13, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'WorkspaceListUpdated');
|
||||||
static const FolderNotification WorkspaceAppsChanged = FolderNotification._(14, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'WorkspaceAppsChanged');
|
static const FolderNotification WorkspaceAppsChanged = FolderNotification._(14, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'WorkspaceAppsChanged');
|
||||||
|
static const FolderNotification WorkspaceSetting = FolderNotification._(15, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'WorkspaceSetting');
|
||||||
static const FolderNotification AppUpdated = FolderNotification._(21, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'AppUpdated');
|
static const FolderNotification AppUpdated = FolderNotification._(21, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'AppUpdated');
|
||||||
static const FolderNotification AppViewsChanged = FolderNotification._(24, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'AppViewsChanged');
|
static const FolderNotification AppViewsChanged = FolderNotification._(24, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'AppViewsChanged');
|
||||||
static const FolderNotification ViewUpdated = FolderNotification._(31, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ViewUpdated');
|
static const FolderNotification ViewUpdated = FolderNotification._(31, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ViewUpdated');
|
||||||
@ -31,6 +32,7 @@ class FolderNotification extends $pb.ProtobufEnum {
|
|||||||
WorkspaceUpdated,
|
WorkspaceUpdated,
|
||||||
WorkspaceListUpdated,
|
WorkspaceListUpdated,
|
||||||
WorkspaceAppsChanged,
|
WorkspaceAppsChanged,
|
||||||
|
WorkspaceSetting,
|
||||||
AppUpdated,
|
AppUpdated,
|
||||||
AppViewsChanged,
|
AppViewsChanged,
|
||||||
ViewUpdated,
|
ViewUpdated,
|
||||||
|
@ -18,6 +18,7 @@ const FolderNotification$json = const {
|
|||||||
const {'1': 'WorkspaceUpdated', '2': 12},
|
const {'1': 'WorkspaceUpdated', '2': 12},
|
||||||
const {'1': 'WorkspaceListUpdated', '2': 13},
|
const {'1': 'WorkspaceListUpdated', '2': 13},
|
||||||
const {'1': 'WorkspaceAppsChanged', '2': 14},
|
const {'1': 'WorkspaceAppsChanged', '2': 14},
|
||||||
|
const {'1': 'WorkspaceSetting', '2': 15},
|
||||||
const {'1': 'AppUpdated', '2': 21},
|
const {'1': 'AppUpdated', '2': 21},
|
||||||
const {'1': 'AppViewsChanged', '2': 24},
|
const {'1': 'AppViewsChanged', '2': 24},
|
||||||
const {'1': 'ViewUpdated', '2': 31},
|
const {'1': 'ViewUpdated', '2': 31},
|
||||||
@ -29,4 +30,4 @@ const FolderNotification$json = const {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// Descriptor for `FolderNotification`. Decode as a `google.protobuf.EnumDescriptorProto`.
|
/// Descriptor for `FolderNotification`. Decode as a `google.protobuf.EnumDescriptorProto`.
|
||||||
final $typed_data.Uint8List folderNotificationDescriptor = $convert.base64Decode('ChJGb2xkZXJOb3RpZmljYXRpb24SCwoHVW5rbm93bhAAEhcKE1VzZXJDcmVhdGVXb3Jrc3BhY2UQChIXChNVc2VyRGVsZXRlV29ya3NwYWNlEAsSFAoQV29ya3NwYWNlVXBkYXRlZBAMEhgKFFdvcmtzcGFjZUxpc3RVcGRhdGVkEA0SGAoUV29ya3NwYWNlQXBwc0NoYW5nZWQQDhIOCgpBcHBVcGRhdGVkEBUSEwoPQXBwVmlld3NDaGFuZ2VkEBgSDwoLVmlld1VwZGF0ZWQQHxIPCgtWaWV3RGVsZXRlZBAgEhAKDFZpZXdSZXN0b3JlZBAhEhQKEFVzZXJVbmF1dGhvcml6ZWQQZBIRCgxUcmFzaFVwZGF0ZWQQ6Ac=');
|
final $typed_data.Uint8List folderNotificationDescriptor = $convert.base64Decode('ChJGb2xkZXJOb3RpZmljYXRpb24SCwoHVW5rbm93bhAAEhcKE1VzZXJDcmVhdGVXb3Jrc3BhY2UQChIXChNVc2VyRGVsZXRlV29ya3NwYWNlEAsSFAoQV29ya3NwYWNlVXBkYXRlZBAMEhgKFFdvcmtzcGFjZUxpc3RVcGRhdGVkEA0SGAoUV29ya3NwYWNlQXBwc0NoYW5nZWQQDhIUChBXb3Jrc3BhY2VTZXR0aW5nEA8SDgoKQXBwVXBkYXRlZBAVEhMKD0FwcFZpZXdzQ2hhbmdlZBAYEg8KC1ZpZXdVcGRhdGVkEB8SDwoLVmlld0RlbGV0ZWQQIBIQCgxWaWV3UmVzdG9yZWQQIRIUChBVc2VyVW5hdXRob3JpemVkEGQSEQoMVHJhc2hVcGRhdGVkEOgH');
|
||||||
|
@ -10,6 +10,7 @@ pub(crate) enum FolderNotification {
|
|||||||
WorkspaceUpdated = 12,
|
WorkspaceUpdated = 12,
|
||||||
WorkspaceListUpdated = 13,
|
WorkspaceListUpdated = 13,
|
||||||
WorkspaceAppsChanged = 14,
|
WorkspaceAppsChanged = 14,
|
||||||
|
WorkspaceSetting = 15,
|
||||||
AppUpdated = 21,
|
AppUpdated = 21,
|
||||||
AppViewsChanged = 24,
|
AppViewsChanged = 24,
|
||||||
ViewUpdated = 31,
|
ViewUpdated = 31,
|
||||||
|
@ -31,6 +31,7 @@ pub enum FolderNotification {
|
|||||||
WorkspaceUpdated = 12,
|
WorkspaceUpdated = 12,
|
||||||
WorkspaceListUpdated = 13,
|
WorkspaceListUpdated = 13,
|
||||||
WorkspaceAppsChanged = 14,
|
WorkspaceAppsChanged = 14,
|
||||||
|
WorkspaceSetting = 15,
|
||||||
AppUpdated = 21,
|
AppUpdated = 21,
|
||||||
AppViewsChanged = 24,
|
AppViewsChanged = 24,
|
||||||
ViewUpdated = 31,
|
ViewUpdated = 31,
|
||||||
@ -53,6 +54,7 @@ impl ::protobuf::ProtobufEnum for FolderNotification {
|
|||||||
12 => ::std::option::Option::Some(FolderNotification::WorkspaceUpdated),
|
12 => ::std::option::Option::Some(FolderNotification::WorkspaceUpdated),
|
||||||
13 => ::std::option::Option::Some(FolderNotification::WorkspaceListUpdated),
|
13 => ::std::option::Option::Some(FolderNotification::WorkspaceListUpdated),
|
||||||
14 => ::std::option::Option::Some(FolderNotification::WorkspaceAppsChanged),
|
14 => ::std::option::Option::Some(FolderNotification::WorkspaceAppsChanged),
|
||||||
|
15 => ::std::option::Option::Some(FolderNotification::WorkspaceSetting),
|
||||||
21 => ::std::option::Option::Some(FolderNotification::AppUpdated),
|
21 => ::std::option::Option::Some(FolderNotification::AppUpdated),
|
||||||
24 => ::std::option::Option::Some(FolderNotification::AppViewsChanged),
|
24 => ::std::option::Option::Some(FolderNotification::AppViewsChanged),
|
||||||
31 => ::std::option::Option::Some(FolderNotification::ViewUpdated),
|
31 => ::std::option::Option::Some(FolderNotification::ViewUpdated),
|
||||||
@ -72,6 +74,7 @@ impl ::protobuf::ProtobufEnum for FolderNotification {
|
|||||||
FolderNotification::WorkspaceUpdated,
|
FolderNotification::WorkspaceUpdated,
|
||||||
FolderNotification::WorkspaceListUpdated,
|
FolderNotification::WorkspaceListUpdated,
|
||||||
FolderNotification::WorkspaceAppsChanged,
|
FolderNotification::WorkspaceAppsChanged,
|
||||||
|
FolderNotification::WorkspaceSetting,
|
||||||
FolderNotification::AppUpdated,
|
FolderNotification::AppUpdated,
|
||||||
FolderNotification::AppViewsChanged,
|
FolderNotification::AppViewsChanged,
|
||||||
FolderNotification::ViewUpdated,
|
FolderNotification::ViewUpdated,
|
||||||
@ -107,14 +110,15 @@ impl ::protobuf::reflect::ProtobufValue for FolderNotification {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static file_descriptor_proto_data: &'static [u8] = b"\
|
static file_descriptor_proto_data: &'static [u8] = b"\
|
||||||
\n\x17dart_notification.proto*\x9f\x02\n\x12FolderNotification\x12\x0b\n\
|
\n\x17dart_notification.proto*\xb5\x02\n\x12FolderNotification\x12\x0b\n\
|
||||||
\x07Unknown\x10\0\x12\x17\n\x13UserCreateWorkspace\x10\n\x12\x17\n\x13Us\
|
\x07Unknown\x10\0\x12\x17\n\x13UserCreateWorkspace\x10\n\x12\x17\n\x13Us\
|
||||||
erDeleteWorkspace\x10\x0b\x12\x14\n\x10WorkspaceUpdated\x10\x0c\x12\x18\
|
erDeleteWorkspace\x10\x0b\x12\x14\n\x10WorkspaceUpdated\x10\x0c\x12\x18\
|
||||||
\n\x14WorkspaceListUpdated\x10\r\x12\x18\n\x14WorkspaceAppsChanged\x10\
|
\n\x14WorkspaceListUpdated\x10\r\x12\x18\n\x14WorkspaceAppsChanged\x10\
|
||||||
\x0e\x12\x0e\n\nAppUpdated\x10\x15\x12\x13\n\x0fAppViewsChanged\x10\x18\
|
\x0e\x12\x14\n\x10WorkspaceSetting\x10\x0f\x12\x0e\n\nAppUpdated\x10\x15\
|
||||||
\x12\x0f\n\x0bViewUpdated\x10\x1f\x12\x0f\n\x0bViewDeleted\x10\x20\x12\
|
\x12\x13\n\x0fAppViewsChanged\x10\x18\x12\x0f\n\x0bViewUpdated\x10\x1f\
|
||||||
\x10\n\x0cViewRestored\x10!\x12\x14\n\x10UserUnauthorized\x10d\x12\x11\n\
|
\x12\x0f\n\x0bViewDeleted\x10\x20\x12\x10\n\x0cViewRestored\x10!\x12\x14\
|
||||||
\x0cTrashUpdated\x10\xe8\x07b\x06proto3\
|
\n\x10UserUnauthorized\x10d\x12\x11\n\x0cTrashUpdated\x10\xe8\x07b\x06pr\
|
||||||
|
oto3\
|
||||||
";
|
";
|
||||||
|
|
||||||
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;
|
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;
|
||||||
|
@ -7,6 +7,7 @@ enum FolderNotification {
|
|||||||
WorkspaceUpdated = 12;
|
WorkspaceUpdated = 12;
|
||||||
WorkspaceListUpdated = 13;
|
WorkspaceListUpdated = 13;
|
||||||
WorkspaceAppsChanged = 14;
|
WorkspaceAppsChanged = 14;
|
||||||
|
WorkspaceSetting = 15;
|
||||||
AppUpdated = 21;
|
AppUpdated = 21;
|
||||||
AppViewsChanged = 24;
|
AppViewsChanged = 24;
|
||||||
ViewUpdated = 31;
|
ViewUpdated = 31;
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use crate::services::AppController;
|
use crate::manager::FolderManager;
|
||||||
|
use crate::services::{notify_workspace_setting_did_change, AppController};
|
||||||
use crate::{
|
use crate::{
|
||||||
entities::{
|
entities::{
|
||||||
trash::Trash,
|
trash::Trash,
|
||||||
@ -69,10 +70,12 @@ pub(crate) async fn delete_view_handler(
|
|||||||
|
|
||||||
pub(crate) async fn set_latest_view_handler(
|
pub(crate) async fn set_latest_view_handler(
|
||||||
data: Data<ViewId>,
|
data: Data<ViewId>,
|
||||||
|
folder: AppData<Arc<FolderManager>>,
|
||||||
controller: AppData<Arc<ViewController>>,
|
controller: AppData<Arc<ViewController>>,
|
||||||
) -> Result<(), FlowyError> {
|
) -> Result<(), FlowyError> {
|
||||||
let view_id: ViewId = data.into_inner();
|
let view_id: ViewId = data.into_inner();
|
||||||
let _ = controller.set_latest_view(&view_id.value)?;
|
let _ = controller.set_latest_view(&view_id.value)?;
|
||||||
|
let _ = notify_workspace_setting_did_change(&folder, &view_id).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use crate::manager::FolderManager;
|
||||||
use crate::{
|
use crate::{
|
||||||
dart_notification::*,
|
dart_notification::*,
|
||||||
errors::*,
|
errors::*,
|
||||||
@ -190,6 +191,44 @@ impl WorkspaceController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn notify_workspace_setting_did_change(
|
||||||
|
folder_manager: &Arc<FolderManager>,
|
||||||
|
view_id: &str,
|
||||||
|
) -> FlowyResult<()> {
|
||||||
|
let user_id = folder_manager.user.user_id()?;
|
||||||
|
let token = folder_manager.user.token()?;
|
||||||
|
let workspace_id = get_current_workspace()?;
|
||||||
|
|
||||||
|
let workspace_setting = folder_manager
|
||||||
|
.persistence
|
||||||
|
.begin_transaction(|transaction| {
|
||||||
|
let workspace = folder_manager.workspace_controller.read_local_workspace(
|
||||||
|
workspace_id.clone(),
|
||||||
|
&user_id,
|
||||||
|
&transaction,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let setting = match transaction.read_view(view_id) {
|
||||||
|
Ok(latest_view) => CurrentWorkspaceSetting {
|
||||||
|
workspace,
|
||||||
|
latest_view: Some(latest_view),
|
||||||
|
},
|
||||||
|
Err(_) => CurrentWorkspaceSetting {
|
||||||
|
workspace,
|
||||||
|
latest_view: None,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(setting)
|
||||||
|
})
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
send_dart_notification(&token, FolderNotification::WorkspaceSetting)
|
||||||
|
.payload(workspace_setting)
|
||||||
|
.send();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
const CURRENT_WORKSPACE_ID: &str = "current_workspace_id";
|
const CURRENT_WORKSPACE_ID: &str = "current_workspace_id";
|
||||||
|
|
||||||
pub fn set_current_workspace(workspace_id: &str) {
|
pub fn set_current_workspace(workspace_id: &str) {
|
||||||
|
@ -85,7 +85,17 @@ impl CellDataOperation for NumberTypeOption {
|
|||||||
|
|
||||||
let cell_data = type_option_cell_data.data;
|
let cell_data = type_option_cell_data.data;
|
||||||
match self.format {
|
match self.format {
|
||||||
NumberFormat::Number => cell_data.parse::<i64>().map_or(String::new(), |v| v.to_string()),
|
NumberFormat::Number => {
|
||||||
|
if let Ok(v) = cell_data.parse::<f64>() {
|
||||||
|
return v.to_string();
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Ok(v) = cell_data.parse::<i64>() {
|
||||||
|
return v.to_string();
|
||||||
|
}
|
||||||
|
|
||||||
|
return String::new();
|
||||||
|
}
|
||||||
NumberFormat::Percent => cell_data.parse::<f64>().map_or(String::new(), |v| v.to_string()),
|
NumberFormat::Percent => cell_data.parse::<f64>().map_or(String::new(), |v| v.to_string()),
|
||||||
_ => self.money_from_str(&cell_data),
|
_ => self.money_from_str(&cell_data),
|
||||||
}
|
}
|
||||||
@ -100,10 +110,13 @@ impl CellDataOperation for NumberTypeOption {
|
|||||||
_cell_meta: Option<CellMeta>,
|
_cell_meta: Option<CellMeta>,
|
||||||
) -> Result<String, FlowyError> {
|
) -> Result<String, FlowyError> {
|
||||||
let changeset = changeset.into();
|
let changeset = changeset.into();
|
||||||
let data = self.strip_symbol(changeset);
|
let mut data = changeset.trim().to_string();
|
||||||
|
|
||||||
if !data.chars().all(char::is_numeric) {
|
if self.format != NumberFormat::Number {
|
||||||
return Err(FlowyError::invalid_data().context("Should only contain numbers"));
|
data = self.strip_symbol(data);
|
||||||
|
if !data.chars().all(char::is_numeric) {
|
||||||
|
return Err(FlowyError::invalid_data().context("Should only contain numbers"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(TypeOptionCellData::new(&data, self.field_type()).json())
|
Ok(TypeOptionCellData::new(&data, self.field_type()).json())
|
||||||
@ -157,7 +170,7 @@ impl NumberTypeOption {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, EnumIter, Serialize, Deserialize, ProtoBuf_Enum)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, EnumIter, Serialize, Deserialize, ProtoBuf_Enum)]
|
||||||
pub enum NumberFormat {
|
pub enum NumberFormat {
|
||||||
Number = 0,
|
Number = 0,
|
||||||
USD = 1,
|
USD = 1,
|
||||||
|
@ -316,7 +316,11 @@ impl ClientGridEditor {
|
|||||||
|
|
||||||
let cell_data_changeset = changeset.data.unwrap();
|
let cell_data_changeset = changeset.data.unwrap();
|
||||||
let cell_meta = self.get_cell_meta(&changeset.row_id, &changeset.field_id).await?;
|
let cell_meta = self.get_cell_meta(&changeset.row_id, &changeset.field_id).await?;
|
||||||
tracing::trace!("{}: {:?}", &changeset.field_id, cell_meta);
|
tracing::trace!(
|
||||||
|
"field changeset: id:{} / value:{}",
|
||||||
|
&changeset.field_id,
|
||||||
|
cell_data_changeset
|
||||||
|
);
|
||||||
match self.grid_pad.read().await.get_field_meta(&changeset.field_id) {
|
match self.grid_pad.read().await.get_field_meta(&changeset.field_id) {
|
||||||
None => {
|
None => {
|
||||||
let msg = format!("Field not found with id: {}", &changeset.field_id);
|
let msg = format!("Field not found with id: {}", &changeset.field_id);
|
||||||
|
@ -201,6 +201,14 @@ impl std::convert::From<&str> for ViewId {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl std::ops::Deref for ViewId {
|
||||||
|
type Target = str;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default, ProtoBuf)]
|
#[derive(Default, ProtoBuf)]
|
||||||
pub struct RepeatedViewId {
|
pub struct RepeatedViewId {
|
||||||
#[pb(index = 1)]
|
#[pb(index = 1)]
|
||||||
|
Loading…
Reference in New Issue
Block a user