chore: code cleanup according to unintroduced lints (#4488)

* chore: remove redundant arguments

* chore: remove unused constructor params

* chore: reorganize constructors

* chore: remove unnecessary awaits in returns

* chore: remove unnecessary paranthesis

* chore: add lints

* chore: clean up after merge

* chore: add sort constructors first

* chore: organize constructors in blocs

* chore: use sizedbox.shrink over empty container
This commit is contained in:
Mathias Mogensen
2024-01-25 16:37:36 +01:00
committed by GitHub
parent 747abba87f
commit acc03b8cc4
447 changed files with 3333 additions and 3412 deletions

View File

@ -2,14 +2,15 @@ import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
abstract class EditPanelContext extends Equatable {
const EditPanelContext({
required this.identifier,
required this.title,
required this.child,
});
final String identifier;
final String title;
final Widget child;
const EditPanelContext({
required this.child,
required this.identifier,
required this.title,
});
@override
List<Object> get props => [identifier];

View File

@ -1,7 +1,7 @@
import 'package:appflowy/workspace/application/edit_panel/edit_context.dart';
import 'package:dartz/dartz.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
part 'edit_panel_bloc.freezed.dart';

View File

@ -11,10 +11,20 @@ import 'favorite_listener.dart';
part 'favorite_bloc.freezed.dart';
class FavoriteBloc extends Bloc<FavoriteEvent, FavoriteState> {
FavoriteBloc() : super(FavoriteState.initial()) {
_dispatch();
}
final _service = FavoriteService();
final _listener = FavoriteListener();
FavoriteBloc() : super(FavoriteState.initial()) {
@override
Future<void> close() async {
await _listener.stop();
return super.close();
}
void _dispatch() {
on<FavoriteEvent>(
(event, emit) async {
await event.map(
@ -58,12 +68,6 @@ class FavoriteBloc extends Bloc<FavoriteEvent, FavoriteState> {
);
}
@override
Future<void> close() async {
await _listener.stop();
return super.close();
}
void _onFavoritesUpdated(
Either<FlowyError, RepeatedViewPB> favoriteOrFailed,
bool didFavorite,

View File

@ -1,22 +1,29 @@
import 'package:appflowy/user/application/user_listener.dart';
import 'package:flowy_infra/time/duration.dart';
import 'package:appflowy_backend/log.dart';
import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-folder/workspace.pb.dart'
show WorkspaceSettingPB;
import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flowy_infra/time/duration.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
part 'home_bloc.freezed.dart';
class HomeBloc extends Bloc<HomeEvent, HomeState> {
HomeBloc(WorkspaceSettingPB workspaceSetting)
: _workspaceListener = UserWorkspaceListener(),
super(HomeState.initial(workspaceSetting)) {
_dispatch(workspaceSetting);
}
final UserWorkspaceListener _workspaceListener;
HomeBloc(
UserProfilePB userProfile,
WorkspaceSettingPB workspaceSetting,
) : _workspaceListener = UserWorkspaceListener(userProfile: userProfile),
super(HomeState.initial(workspaceSetting)) {
@override
Future<void> close() async {
await _workspaceListener.stop();
return super.close();
}
void _dispatch(WorkspaceSettingPB workspaceSetting) {
on<HomeEvent>(
(event, emit) async {
await event.map(
@ -56,12 +63,6 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> {
},
);
}
@override
Future<void> close() async {
await _workspaceListener.stop();
return super.close();
}
}
enum MenuResizeType {
@ -100,6 +101,5 @@ class HomeState with _$HomeState {
factory HomeState.initial(WorkspaceSettingPB workspaceSetting) => HomeState(
isLoading: false,
workspaceSetting: workspaceSetting,
latestView: null,
);
}

View File

@ -1,9 +1,8 @@
import 'package:appflowy/user/application/user_listener.dart';
import 'package:appflowy/workspace/application/settings/appearance/appearance_cubit.dart';
import 'package:appflowy/workspace/application/edit_panel/edit_context.dart';
import 'package:appflowy/workspace/application/settings/appearance/appearance_cubit.dart';
import 'package:appflowy_backend/protobuf/flowy-folder/workspace.pb.dart'
show WorkspaceSettingPB;
import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart';
import 'package:dartz/dartz.dart';
import 'package:flowy_infra/size.dart';
import 'package:flowy_infra/time/duration.dart';
@ -13,15 +12,11 @@ import 'package:freezed_annotation/freezed_annotation.dart';
part 'home_setting_bloc.freezed.dart';
class HomeSettingBloc extends Bloc<HomeSettingEvent, HomeSettingState> {
final UserWorkspaceListener _listener;
final AppearanceSettingsCubit _appearanceSettingsCubit;
HomeSettingBloc(
UserProfilePB user,
WorkspaceSettingPB workspaceSetting,
AppearanceSettingsCubit appearanceSettingsCubit,
double screenWidthPx,
) : _listener = UserWorkspaceListener(userProfile: user),
) : _listener = UserWorkspaceListener(),
_appearanceSettingsCubit = appearanceSettingsCubit,
super(
HomeSettingState.initial(
@ -30,6 +25,19 @@ class HomeSettingBloc extends Bloc<HomeSettingEvent, HomeSettingState> {
screenWidthPx,
),
) {
_dispatch();
}
final UserWorkspaceListener _listener;
final AppearanceSettingsCubit _appearanceSettingsCubit;
@override
Future<void> close() async {
await _listener.stop();
return super.close();
}
void _dispatch() {
on<HomeSettingEvent>(
(event, emit) async {
await event.map(
@ -92,12 +100,6 @@ class HomeSettingBloc extends Bloc<HomeSettingEvent, HomeSettingState> {
},
);
}
@override
Future<void> close() async {
await _listener.stop();
return super.close();
}
}
enum MenuResizeType {

View File

@ -13,73 +13,77 @@ import 'package:freezed_annotation/freezed_annotation.dart';
part 'menu_bloc.freezed.dart';
class MenuBloc extends Bloc<MenuEvent, MenuState> {
final WorkspaceService _workspaceService;
final WorkspaceListener _listener;
final UserProfilePB user;
final String workspaceId;
MenuBloc({
required this.user,
required this.workspaceId,
}) : _workspaceService = WorkspaceService(workspaceId: workspaceId),
MenuBloc({required this.user, required this.workspaceId})
: _workspaceService = WorkspaceService(workspaceId: workspaceId),
_listener = WorkspaceListener(
user: user,
workspaceId: workspaceId,
),
super(MenuState.initial()) {
on<MenuEvent>((event, emit) async {
await event.map(
initial: (e) async {
_listener.start(appsChanged: _handleAppsOrFail);
await _fetchApps(emit);
},
createApp: (_CreateApp event) async {
final result = await _workspaceService.createApp(
name: event.name,
desc: event.desc,
index: event.index,
);
result.fold(
(app) => emit(state.copyWith(lastCreatedView: app)),
(error) {
Log.error(error);
emit(state.copyWith(successOrFailure: right(error)));
},
);
},
didReceiveApps: (e) async {
emit(
e.appsOrFail.fold(
(views) =>
state.copyWith(views: views, successOrFailure: left(unit)),
(err) => state.copyWith(successOrFailure: right(err)),
),
);
},
moveApp: (_MoveApp value) {
if (state.views.length > value.fromIndex) {
final view = state.views[value.fromIndex];
_workspaceService.moveApp(
appId: view.id,
fromIndex: value.fromIndex,
toIndex: value.toIndex,
);
final apps = List<ViewPB>.from(state.views);
apps.insert(value.toIndex, apps.removeAt(value.fromIndex));
emit(state.copyWith(views: apps));
}
},
);
});
_dispatch();
}
final WorkspaceService _workspaceService;
final WorkspaceListener _listener;
final UserProfilePB user;
final String workspaceId;
@override
Future<void> close() async {
await _listener.stop();
return super.close();
}
void _dispatch() {
on<MenuEvent>(
(event, emit) async {
await event.map(
initial: (e) async {
_listener.start(appsChanged: _handleAppsOrFail);
await _fetchApps(emit);
},
createApp: (_CreateApp event) async {
final result = await _workspaceService.createApp(
name: event.name,
desc: event.desc,
index: event.index,
);
result.fold(
(app) => emit(state.copyWith(lastCreatedView: app)),
(error) {
Log.error(error);
emit(state.copyWith(successOrFailure: right(error)));
},
);
},
didReceiveApps: (e) async {
emit(
e.appsOrFail.fold(
(views) =>
state.copyWith(views: views, successOrFailure: left(unit)),
(err) => state.copyWith(successOrFailure: right(err)),
),
);
},
moveApp: (_MoveApp value) {
if (state.views.length > value.fromIndex) {
final view = state.views[value.fromIndex];
_workspaceService.moveApp(
appId: view.id,
fromIndex: value.fromIndex,
toIndex: value.toIndex,
);
final apps = List<ViewPB>.from(state.views);
apps.insert(value.toIndex, apps.removeAt(value.fromIndex));
emit(state.copyWith(views: apps));
}
},
);
},
);
}
// ignore: unused_element
Future<void> _fetchApps(Emitter<MenuState> emit) async {
final viewsOrError = await _workspaceService.getViews();
@ -124,6 +128,5 @@ class MenuState with _$MenuState {
factory MenuState.initial() => MenuState(
views: [],
successOrFailure: left(unit),
lastCreatedView: null,
);
}

View File

@ -1,51 +1,29 @@
import 'package:appflowy/user/application/user_listener.dart';
import 'package:appflowy/user/application/user_service.dart';
import 'package:appflowy_backend/log.dart';
import 'package:appflowy_backend/protobuf/flowy-folder/workspace.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-folder/workspace.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart';
import 'package:dartz/dartz.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:dartz/dartz.dart';
part 'menu_user_bloc.freezed.dart';
class MenuUserBloc extends Bloc<MenuUserEvent, MenuUserState> {
MenuUserBloc(this.userProfile)
: _userListener = UserListener(userProfile: userProfile),
_userWorkspaceListener = UserWorkspaceListener(),
_userService = UserBackendService(userId: userProfile.id),
super(MenuUserState.initial(userProfile)) {
_dispatch();
}
final UserBackendService _userService;
final UserListener _userListener;
final UserWorkspaceListener _userWorkspaceListener;
final UserProfilePB userProfile;
MenuUserBloc(this.userProfile)
: _userListener = UserListener(userProfile: userProfile),
_userWorkspaceListener =
UserWorkspaceListener(userProfile: userProfile),
_userService = UserBackendService(userId: userProfile.id),
super(MenuUserState.initial(userProfile)) {
on<MenuUserEvent>((event, emit) async {
await event.when(
initial: () async {
_userListener.start(onProfileUpdated: _profileUpdated);
await _initUser();
},
fetchWorkspaces: () async {
//
},
didReceiveUserProfile: (UserProfilePB newUserProfile) {
emit(state.copyWith(userProfile: newUserProfile));
},
updateUserName: (String name) {
_userService.updateUserProfile(name: name).then((result) {
result.fold(
(l) => null,
(err) => Log.error(err),
);
});
},
);
});
}
@override
Future<void> close() async {
await _userListener.stop();
@ -53,6 +31,33 @@ class MenuUserBloc extends Bloc<MenuUserEvent, MenuUserState> {
super.close();
}
void _dispatch() {
on<MenuUserEvent>(
(event, emit) async {
await event.when(
initial: () async {
_userListener.start(onProfileUpdated: _profileUpdated);
await _initUser();
},
fetchWorkspaces: () async {
//
},
didReceiveUserProfile: (UserProfilePB newUserProfile) {
emit(state.copyWith(userProfile: newUserProfile));
},
updateUserName: (String name) {
_userService.updateUserProfile(name: name).then((result) {
result.fold(
(l) => null,
(err) => Log.error(err),
);
});
},
);
},
);
}
Future<void> _initUser() async {
final result = await _userService.initUser();
result.fold((l) => null, (error) => Log.error(error));

View File

@ -38,6 +38,10 @@ class NotificationActionEvent with _$NotificationActionEvent {
}
class NotificationActionState {
const NotificationActionState.initial()
: action = null,
nextActions = const [];
const NotificationActionState({
required this.action,
this.nextActions = const [],
@ -46,10 +50,6 @@ class NotificationActionState {
final NotificationAction? action;
final List<NotificationAction> nextActions;
const NotificationActionState.initial()
: action = null,
nextActions = const [];
NotificationActionState copyWith({
NotificationAction? action,
List<NotificationAction>? nextActions,

View File

@ -14,7 +14,6 @@ class NotificationService {
static Future<void> initialize() async {
await localNotifier.setup(
appName: _appName,
shortcutPolicy: ShortcutPolicy.requireCreate, // Windows Specific
);
}
}

View File

@ -10,10 +10,20 @@ import 'package:freezed_annotation/freezed_annotation.dart';
part 'recent_views_bloc.freezed.dart';
class RecentViewsBloc extends Bloc<RecentViewsEvent, RecentViewsState> {
RecentViewsBloc() : super(RecentViewsState.initial()) {
_dispatch();
}
final _service = RecentService();
final _listener = RecentViewsListener();
RecentViewsBloc() : super(RecentViewsState.initial()) {
@override
Future<void> close() async {
await _listener.stop();
return super.close();
}
void _dispatch() {
on<RecentViewsEvent>(
(event, emit) async {
await event.map(
@ -43,12 +53,6 @@ class RecentViewsBloc extends Bloc<RecentViewsEvent, RecentViewsState> {
);
}
@override
Future<void> close() async {
await _listener.stop();
return super.close();
}
void _onRecentViewsUpdated(
Either<FlowyError, RepeatedViewIdPB> result,
) {

View File

@ -26,9 +26,6 @@ part 'appearance_cubit.freezed.dart';
/// - [UserTimeFormatPB]
///
class AppearanceSettingsCubit extends Cubit<AppearanceSettingsState> {
final AppearanceSettingsPB _appearanceSettings;
final DateTimeSettingsPB _dateTimeSettings;
AppearanceSettingsCubit(
AppearanceSettingsPB appearanceSettings,
DateTimeSettingsPB dateTimeSettings,
@ -52,9 +49,7 @@ class AppearanceSettingsCubit extends Cubit<AppearanceSettingsState> {
appearanceSettings.documentSetting.cursorColor.isEmpty
? null
: Color(
int.parse(
appearanceSettings.documentSetting.cursorColor,
),
int.parse(appearanceSettings.documentSetting.cursorColor),
),
appearanceSettings.documentSetting.selectionColor.isEmpty
? null
@ -66,6 +61,9 @@ class AppearanceSettingsCubit extends Cubit<AppearanceSettingsState> {
),
);
final AppearanceSettingsPB _appearanceSettings;
final DateTimeSettingsPB _dateTimeSettings;
/// Update selected theme in the user's settings and emit an updated state
/// with the AppTheme named [themeName].
Future<void> setTheme(String themeName) async {

View File

@ -3,55 +3,62 @@ import 'package:appflowy/workspace/application/settings/cloud_setting_listener.d
import 'package:appflowy_backend/dispatch/dispatch.dart';
import 'package:appflowy_backend/log.dart';
import 'package:appflowy_backend/protobuf/flowy-user/user_setting.pb.dart';
import 'package:dartz/dartz.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:dartz/dartz.dart';
part 'appflowy_cloud_setting_bloc.freezed.dart';
class AppFlowyCloudSettingBloc
extends Bloc<AppFlowyCloudSettingEvent, AppFlowyCloudSettingState> {
final UserCloudConfigListener _listener;
AppFlowyCloudSettingBloc(CloudSettingPB setting)
: _listener = UserCloudConfigListener(),
super(AppFlowyCloudSettingState.initial(setting)) {
on<AppFlowyCloudSettingEvent>((event, emit) async {
await event.when(
initial: () async {
_listener.start(
onSettingChanged: (result) {
if (isClosed) {
return;
}
result.fold(
(setting) =>
add(AppFlowyCloudSettingEvent.didReceiveSetting(setting)),
(error) => Log.error(error),
);
},
);
},
enableSync: (isEnable) async {
final config = UpdateCloudConfigPB.create()..enableSync = isEnable;
await UserEventSetCloudConfig(config).send();
},
didReceiveSetting: (CloudSettingPB setting) {
emit(
state.copyWith(
setting: setting,
),
);
},
);
});
_dispatch();
}
final UserCloudConfigListener _listener;
@override
Future<void> close() async {
_listener.stop();
return super.close();
}
void _dispatch() {
on<AppFlowyCloudSettingEvent>(
(event, emit) async {
await event.when(
initial: () async {
_listener.start(
onSettingChanged: (result) {
if (isClosed) {
return;
}
result.fold(
(setting) =>
add(AppFlowyCloudSettingEvent.didReceiveSetting(setting)),
(error) => Log.error(error),
);
},
);
},
enableSync: (isEnable) async {
final config = UpdateCloudConfigPB.create()..enableSync = isEnable;
await UserEventSetCloudConfig(config).send();
},
didReceiveSetting: (CloudSettingPB setting) {
emit(
state.copyWith(
setting: setting,
),
);
},
);
},
);
}
}
@freezed

View File

@ -2,10 +2,10 @@ import 'package:appflowy/env/backend_env.dart';
import 'package:appflowy/env/cloud_env.dart';
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/startup/startup.dart';
import 'package:dartz/dartz.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:dartz/dartz.dart';
part 'appflowy_cloud_urls_bloc.freezed.dart';

View File

@ -10,11 +10,11 @@ import 'package:dartz/dartz.dart';
import '../../../core/notification/user_notification.dart';
class UserCloudConfigListener {
StreamSubscription<SubscribeObject>? _subscription;
void Function(Either<CloudSettingPB, FlowyError>)? _onSettingChanged;
UserCloudConfigListener();
UserNotificationParser? _userParser;
UserCloudConfigListener();
StreamSubscription<SubscribeObject>? _subscription;
void Function(Either<CloudSettingPB, FlowyError>)? _onSettingChanged;
void start({
void Function(Either<CloudSettingPB, FlowyError>)? onSettingChanged,

View File

@ -9,10 +9,6 @@ import 'package:freezed_annotation/freezed_annotation.dart';
part 'notification_settings_cubit.freezed.dart';
class NotificationSettingsCubit extends Cubit<NotificationSettingsState> {
final Completer<void> _initCompleter = Completer();
late final NotificationSettingsPB _notificationSettings;
NotificationSettingsCubit() : super(NotificationSettingsState.initial()) {
UserSettingsBackendService()
.getNotificationSettings()
@ -27,6 +23,10 @@ class NotificationSettingsCubit extends Cubit<NotificationSettingsState> {
});
}
final Completer<void> _initCompleter = Completer();
late final NotificationSettingsPB _notificationSettings;
Future<void> toggleNotificationsEnabled() async {
await _initCompleter.future;

View File

@ -2,9 +2,9 @@ import 'package:appflowy/user/application/user_listener.dart';
import 'package:appflowy_backend/log.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart';
import 'package:dartz/dartz.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:dartz/dartz.dart';
part 'settings_dialog_bloc.freezed.dart';
@ -20,33 +20,39 @@ enum SettingsPage {
class SettingsDialogBloc
extends Bloc<SettingsDialogEvent, SettingsDialogState> {
final UserListener _userListener;
final UserProfilePB userProfile;
SettingsDialogBloc(this.userProfile)
: _userListener = UserListener(userProfile: userProfile),
super(SettingsDialogState.initial(userProfile)) {
on<SettingsDialogEvent>((event, emit) async {
await event.when(
initial: () async {
_userListener.start(onProfileUpdated: _profileUpdated);
},
didReceiveUserProfile: (UserProfilePB newUserProfile) {
emit(state.copyWith(userProfile: newUserProfile));
},
setSelectedPage: (SettingsPage page) {
emit(state.copyWith(page: page));
},
);
});
_dispatch();
}
final UserProfilePB userProfile;
final UserListener _userListener;
@override
Future<void> close() async {
await _userListener.stop();
super.close();
}
void _dispatch() {
on<SettingsDialogEvent>(
(event, emit) async {
await event.when(
initial: () async {
_userListener.start(onProfileUpdated: _profileUpdated);
},
didReceiveUserProfile: (UserProfilePB newUserProfile) {
emit(state.copyWith(userProfile: newUserProfile));
},
setSelectedPage: (SettingsPage page) {
emit(state.copyWith(page: page));
},
);
},
);
}
void _profileUpdated(Either<UserProfilePB, FlowyError> userProfileOrFailed) {
userProfileOrFailed.fold(
(newUserProfile) =>

View File

@ -17,7 +17,7 @@ class ImportBackendService {
..viewLayout = importType.toLayout()
..name = name
..importType = importType;
return await FolderEventImportData(payload).send();
return FolderEventImportData(payload).send();
}
}

View File

@ -66,7 +66,7 @@ class SettingsShortcutService {
) async {
for (final shortcut in customizeShortcuts) {
final shortcutEvent = commandShortcuts.firstWhereOrNull(
(s) => (s.key == shortcut.key && s.command != shortcut.command),
(s) => s.key == shortcut.key && s.command != shortcut.command,
);
shortcutEvent?.updateCommand(command: shortcut.command);
}

View File

@ -1,21 +1,17 @@
import 'package:appflowy_editor/appflowy_editor.dart';
class EditorShortcuts {
EditorShortcuts({
required this.commandShortcuts,
});
final List<CommandShortcutModel> commandShortcuts;
factory EditorShortcuts.fromJson(Map<String, dynamic> json) =>
EditorShortcuts(
commandShortcuts: List<CommandShortcutModel>.from(
json["commandShortcuts"].map(
(x) => CommandShortcutModel.fromJson(x),
),
json["commandShortcuts"].map((x) => CommandShortcutModel.fromJson(x)),
),
);
EditorShortcuts({required this.commandShortcuts});
final List<CommandShortcutModel> commandShortcuts;
Map<String, dynamic> toJson() => {
"commandShortcuts":
List<dynamic>.from(commandShortcuts.map((x) => x.toJson())),
@ -23,20 +19,6 @@ class EditorShortcuts {
}
class CommandShortcutModel {
const CommandShortcutModel({
required this.key,
required this.command,
});
final String key;
final String command;
factory CommandShortcutModel.fromJson(Map<String, dynamic> json) =>
CommandShortcutModel(
key: json["key"],
command: (json["command"] ?? ''),
);
factory CommandShortcutModel.fromCommandEvent(
CommandShortcutEvent commandShortcutEvent,
) =>
@ -45,10 +27,18 @@ class CommandShortcutModel {
command: commandShortcutEvent.command,
);
Map<String, dynamic> toJson() => {
"key": key,
"command": command,
};
factory CommandShortcutModel.fromJson(Map<String, dynamic> json) =>
CommandShortcutModel(
key: json["key"],
command: json["command"] ?? '',
);
const CommandShortcutModel({required this.key, required this.command});
final String key;
final String command;
Map<String, dynamic> toJson() => {"key": key, "command": command};
@override
bool operator ==(Object other) =>

View File

@ -5,9 +5,9 @@ import 'package:appflowy/startup/startup.dart';
import 'package:appflowy_backend/dispatch/dispatch.dart';
import 'package:appflowy_backend/log.dart';
import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart';
import 'package:dartz/dartz.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:dartz/dartz.dart';
import 'cloud_setting_listener.dart';
@ -15,58 +15,64 @@ part 'supabase_cloud_setting_bloc.freezed.dart';
class SupabaseCloudSettingBloc
extends Bloc<SupabaseCloudSettingEvent, SupabaseCloudSettingState> {
final UserCloudConfigListener _listener;
SupabaseCloudSettingBloc({
required CloudSettingPB setting,
}) : _listener = UserCloudConfigListener(),
super(SupabaseCloudSettingState.initial(setting)) {
on<SupabaseCloudSettingEvent>((event, emit) async {
await event.when(
initial: () async {
_listener.start(
onSettingChanged: (result) {
if (isClosed) {
return;
}
result.fold(
(setting) =>
add(SupabaseCloudSettingEvent.didReceiveSetting(setting)),
(error) => Log.error(error),
);
},
);
},
enableSync: (bool enable) async {
final update = UpdateCloudConfigPB.create()..enableSync = enable;
updateCloudConfig(update);
},
didReceiveSetting: (CloudSettingPB setting) {
emit(
state.copyWith(
setting: setting,
loadingState: LoadingState.finish(left(unit)),
),
);
},
enableEncrypt: (bool enable) {
final update = UpdateCloudConfigPB.create()..enableEncrypt = enable;
updateCloudConfig(update);
emit(state.copyWith(loadingState: const LoadingState.loading()));
},
);
});
_dispatch();
}
Future<void> updateCloudConfig(UpdateCloudConfigPB setting) async {
await UserEventSetCloudConfig(setting).send();
}
final UserCloudConfigListener _listener;
@override
Future<void> close() async {
_listener.stop();
return super.close();
}
void _dispatch() {
on<SupabaseCloudSettingEvent>(
(event, emit) async {
await event.when(
initial: () async {
_listener.start(
onSettingChanged: (result) {
if (isClosed) {
return;
}
result.fold(
(setting) =>
add(SupabaseCloudSettingEvent.didReceiveSetting(setting)),
(error) => Log.error(error),
);
},
);
},
enableSync: (bool enable) async {
final update = UpdateCloudConfigPB.create()..enableSync = enable;
updateCloudConfig(update);
},
didReceiveSetting: (CloudSettingPB setting) {
emit(
state.copyWith(
setting: setting,
loadingState: LoadingState.finish(left(unit)),
),
);
},
enableEncrypt: (bool enable) {
final update = UpdateCloudConfigPB.create()..enableEncrypt = enable;
updateCloudConfig(update);
emit(state.copyWith(loadingState: const LoadingState.loading()));
},
);
},
);
}
Future<void> updateCloudConfig(UpdateCloudConfigPB setting) async {
await UserEventSetCloudConfig(setting).send();
}
}
@freezed

View File

@ -4,10 +4,10 @@ import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/startup/startup.dart';
import 'package:appflowy_backend/dispatch/dispatch.dart';
import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart';
import 'package:dartz/dartz.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:dartz/dartz.dart';
import 'appflowy_cloud_setting_bloc.dart';

View File

@ -15,40 +15,45 @@ part 'tabs_state.dart';
part 'tabs_bloc.freezed.dart';
class TabsBloc extends Bloc<TabsEvent, TabsState> {
late final MenuSharedState menuSharedState;
TabsBloc() : super(TabsState()) {
menuSharedState = getIt<MenuSharedState>();
_dispatch();
}
on<TabsEvent>((event, emit) async {
event.when(
selectTab: (int index) {
if (index != state.currentIndex &&
index >= 0 &&
index < state.pages) {
emit(state.copyWith(newIndex: index));
late final MenuSharedState menuSharedState;
void _dispatch() {
on<TabsEvent>(
(event, emit) async {
event.when(
selectTab: (int index) {
if (index != state.currentIndex &&
index >= 0 &&
index < state.pages) {
emit(state.copyWith(newIndex: index));
_setLatestOpenView();
}
},
moveTab: () {},
closeTab: (String pluginId) {
emit(state.closeView(pluginId));
_setLatestOpenView();
}
},
moveTab: () {},
closeTab: (String pluginId) {
emit(state.closeView(pluginId));
_setLatestOpenView();
},
closeCurrentTab: () {
emit(state.closeView(state.currentPageManager.plugin.id));
_setLatestOpenView();
},
openTab: (Plugin plugin, ViewPB view) {
emit(state.openView(plugin, view));
_setLatestOpenView(view);
},
openPlugin: (Plugin plugin, ViewPB? view) {
emit(state.openPlugin(plugin: plugin));
_setLatestOpenView(view);
},
);
});
},
closeCurrentTab: () {
emit(state.closeView(state.currentPageManager.plugin.id));
_setLatestOpenView();
},
openTab: (Plugin plugin, ViewPB view) {
emit(state.openView(plugin, view));
_setLatestOpenView(view);
},
openPlugin: (Plugin plugin, ViewPB? view) {
emit(state.openPlugin(plugin: plugin));
_setLatestOpenView(view);
},
);
},
);
}
void _setLatestOpenView([ViewPB? view]) {

View File

@ -1,18 +1,17 @@
part of 'tabs_bloc.dart';
class TabsState {
final int currentIndex;
final List<PageManager> _pageManagers;
int get pages => _pageManagers.length;
PageManager get currentPageManager => _pageManagers[currentIndex];
List<PageManager> get pageManagers => _pageManagers;
TabsState({
this.currentIndex = 0,
List<PageManager>? pageManagers,
}) : _pageManagers = pageManagers ?? [PageManager()];
final int currentIndex;
final List<PageManager> _pageManagers;
int get pages => _pageManagers.length;
PageManager get currentPageManager => _pageManagers[currentIndex];
List<PageManager> get pageManagers => _pageManagers;
/// This opens a new tab given a [Plugin] and a [View].
///
/// If the [Plugin.id] is already associated with an open tab,

View File

@ -10,84 +10,90 @@ import 'package:freezed_annotation/freezed_annotation.dart';
part 'settings_user_bloc.freezed.dart';
class SettingsUserViewBloc extends Bloc<SettingsUserEvent, SettingsUserState> {
final UserBackendService _userService;
final UserListener _userListener;
final UserProfilePB userProfile;
SettingsUserViewBloc(this.userProfile)
: _userListener = UserListener(userProfile: userProfile),
_userService = UserBackendService(userId: userProfile.id),
super(SettingsUserState.initial(userProfile)) {
on<SettingsUserEvent>((event, emit) async {
await event.when(
initial: () async {
_loadUserProfile();
_userListener.start(onProfileUpdated: _profileUpdated);
},
didReceiveUserProfile: (UserProfilePB newUserProfile) {
emit(state.copyWith(userProfile: newUserProfile));
},
updateUserName: (String name) {
_userService.updateUserProfile(name: name).then((result) {
result.fold(
(l) => null,
(err) => Log.error(err),
);
});
},
updateUserIcon: (String iconUrl) {
_userService.updateUserProfile(iconUrl: iconUrl).then((result) {
result.fold(
(l) => null,
(err) => Log.error(err),
);
});
},
removeUserIcon: () {
// Empty Icon URL = No icon
_userService.updateUserProfile(iconUrl: "").then((result) {
result.fold(
(l) => null,
(err) => Log.error(err),
);
});
},
updateUserOpenAIKey: (openAIKey) {
_userService.updateUserProfile(openAIKey: openAIKey).then((result) {
result.fold(
(l) => null,
(err) => Log.error(err),
);
});
},
updateUserStabilityAIKey: (stabilityAIKey) {
_userService
.updateUserProfile(stabilityAiKey: stabilityAIKey)
.then((result) {
result.fold(
(l) => null,
(err) => Log.error(err),
);
});
},
updateUserEmail: (String email) {
_userService.updateUserProfile(email: email).then((result) {
result.fold(
(l) => null,
(err) => Log.error(err),
);
});
},
);
});
_dispatch();
}
final UserBackendService _userService;
final UserListener _userListener;
final UserProfilePB userProfile;
@override
Future<void> close() async {
await _userListener.stop();
super.close();
}
void _dispatch() {
on<SettingsUserEvent>(
(event, emit) async {
await event.when(
initial: () async {
_loadUserProfile();
_userListener.start(onProfileUpdated: _profileUpdated);
},
didReceiveUserProfile: (UserProfilePB newUserProfile) {
emit(state.copyWith(userProfile: newUserProfile));
},
updateUserName: (String name) {
_userService.updateUserProfile(name: name).then((result) {
result.fold(
(l) => null,
(err) => Log.error(err),
);
});
},
updateUserIcon: (String iconUrl) {
_userService.updateUserProfile(iconUrl: iconUrl).then((result) {
result.fold(
(l) => null,
(err) => Log.error(err),
);
});
},
removeUserIcon: () {
// Empty Icon URL = No icon
_userService.updateUserProfile(iconUrl: "").then((result) {
result.fold(
(l) => null,
(err) => Log.error(err),
);
});
},
updateUserOpenAIKey: (openAIKey) {
_userService.updateUserProfile(openAIKey: openAIKey).then((result) {
result.fold(
(l) => null,
(err) => Log.error(err),
);
});
},
updateUserStabilityAIKey: (stabilityAIKey) {
_userService
.updateUserProfile(stabilityAiKey: stabilityAIKey)
.then((result) {
result.fold(
(l) => null,
(err) => Log.error(err),
);
});
},
updateUserEmail: (String email) {
_userService.updateUserProfile(email: email).then((result) {
result.fold(
(l) => null,
(err) => Log.error(err),
);
});
},
);
},
);
}
void _loadUserProfile() {
UserBackendService.getCurrentUserProfile().then((result) {
if (isClosed) {

View File

@ -18,167 +18,19 @@ import 'package:protobuf/protobuf.dart';
part 'view_bloc.freezed.dart';
class ViewBloc extends Bloc<ViewEvent, ViewState> {
final ViewBackendService viewBackendSvc;
final ViewListener listener;
final FavoriteListener favoriteListener;
final ViewPB view;
ViewBloc({
required this.view,
}) : viewBackendSvc = ViewBackendService(),
ViewBloc({required this.view})
: viewBackendSvc = ViewBackendService(),
listener = ViewListener(viewId: view.id),
favoriteListener = FavoriteListener(),
super(ViewState.init(view)) {
on<ViewEvent>((event, emit) async {
await event.map(
initial: (e) async {
listener.start(
onViewUpdated: (result) {
add(ViewEvent.viewDidUpdate(left(result)));
},
onViewChildViewsUpdated: (result) async {
final view = await _updateChildViews(result);
if (!isClosed && view != null) {
add(ViewEvent.viewUpdateChildView(view));
}
},
);
favoriteListener.start(
favoritesUpdated: (result, isFavorite) {
result.fold((error) {}, (result) {
final current =
result.items.firstWhereOrNull((v) => v.id == state.view.id);
if (current != null) {
add(ViewEvent.viewDidUpdate(left(current)));
}
});
},
);
final isExpanded = await _getViewIsExpanded(view);
emit(state.copyWith(isExpanded: isExpanded));
await _loadViewsWhenExpanded(emit, isExpanded);
},
setIsEditing: (e) {
emit(state.copyWith(isEditing: e.isEditing));
},
setIsExpanded: (e) async {
if (e.isExpanded && !state.isExpanded) {
await _loadViewsWhenExpanded(emit, true);
} else {
emit(state.copyWith(isExpanded: e.isExpanded));
}
await _setViewIsExpanded(view, e.isExpanded);
},
viewDidUpdate: (e) async {
final result = await ViewBackendService.getView(
view.id,
);
final view_ = result.fold((l) => l, (r) => null);
e.result.fold(
(view) async {
// ignore child view changes because it only contains one level
// children data.
if (_isSameViewIgnoreChildren(view, state.view)) {
// do nothing.
}
emit(
state.copyWith(
view: view_ ?? view,
successOrFailure: left(unit),
),
);
},
(error) => emit(
state.copyWith(successOrFailure: right(error)),
),
);
},
rename: (e) async {
final result = await ViewBackendService.updateView(
viewId: view.id,
name: e.newName,
);
emit(
result.fold(
(l) {
final view = state.view;
view.freeze();
final newView = view.rebuild(
(b) => b.name = e.newName,
);
return state.copyWith(
successOrFailure: left(unit),
view: newView,
);
},
(error) => state.copyWith(successOrFailure: right(error)),
),
);
},
delete: (e) async {
final result = await ViewBackendService.delete(viewId: view.id);
emit(
result.fold(
(l) => state.copyWith(successOrFailure: left(unit)),
(error) => state.copyWith(successOrFailure: right(error)),
),
);
RecentService().updateRecentViews([view.id], false);
},
duplicate: (e) async {
final result = await ViewBackendService.duplicate(view: view);
emit(
result.fold(
(l) => state.copyWith(successOrFailure: left(unit)),
(error) => state.copyWith(successOrFailure: right(error)),
),
);
},
move: (value) async {
final result = await ViewBackendService.moveViewV2(
viewId: value.from.id,
newParentId: value.newParentId,
prevViewId: value.prevId,
);
emit(
result.fold(
(l) => state.copyWith(successOrFailure: left(unit)),
(error) => state.copyWith(successOrFailure: right(error)),
),
);
},
createView: (e) async {
final result = await ViewBackendService.createView(
parentViewId: view.id,
name: e.name,
desc: '',
layoutType: e.layoutType,
initialDataBytes: null,
ext: {},
openAfterCreate: e.openAfterCreated,
);
emit(
result.fold(
(view) => state.copyWith(
lastCreatedView: view,
successOrFailure: left(unit),
),
(error) => state.copyWith(successOrFailure: right(error)),
),
);
},
viewUpdateChildView: (e) async {
emit(
state.copyWith(
view: e.result,
),
);
},
);
});
_dispatch();
}
final ViewPB view;
final ViewBackendService viewBackendSvc;
final ViewListener listener;
final FavoriteListener favoriteListener;
@override
Future<void> close() async {
await listener.stop();
@ -186,6 +38,158 @@ class ViewBloc extends Bloc<ViewEvent, ViewState> {
return super.close();
}
void _dispatch() {
on<ViewEvent>(
(event, emit) async {
await event.map(
initial: (e) async {
listener.start(
onViewUpdated: (result) {
add(ViewEvent.viewDidUpdate(left(result)));
},
onViewChildViewsUpdated: (result) async {
final view = await _updateChildViews(result);
if (!isClosed && view != null) {
add(ViewEvent.viewUpdateChildView(view));
}
},
);
favoriteListener.start(
favoritesUpdated: (result, isFavorite) {
result.fold((error) {}, (result) {
final current = result.items
.firstWhereOrNull((v) => v.id == state.view.id);
if (current != null) {
add(ViewEvent.viewDidUpdate(left(current)));
}
});
},
);
final isExpanded = await _getViewIsExpanded(view);
emit(state.copyWith(isExpanded: isExpanded));
await _loadViewsWhenExpanded(emit, isExpanded);
},
setIsEditing: (e) {
emit(state.copyWith(isEditing: e.isEditing));
},
setIsExpanded: (e) async {
if (e.isExpanded && !state.isExpanded) {
await _loadViewsWhenExpanded(emit, true);
} else {
emit(state.copyWith(isExpanded: e.isExpanded));
}
await _setViewIsExpanded(view, e.isExpanded);
},
viewDidUpdate: (e) async {
final result = await ViewBackendService.getView(
view.id,
);
final view_ = result.fold((l) => l, (r) => null);
e.result.fold(
(view) async {
// ignore child view changes because it only contains one level
// children data.
if (_isSameViewIgnoreChildren(view, state.view)) {
// do nothing.
}
emit(
state.copyWith(
view: view_ ?? view,
successOrFailure: left(unit),
),
);
},
(error) => emit(
state.copyWith(successOrFailure: right(error)),
),
);
},
rename: (e) async {
final result = await ViewBackendService.updateView(
viewId: view.id,
name: e.newName,
);
emit(
result.fold(
(l) {
final view = state.view;
view.freeze();
final newView = view.rebuild(
(b) => b.name = e.newName,
);
return state.copyWith(
successOrFailure: left(unit),
view: newView,
);
},
(error) => state.copyWith(successOrFailure: right(error)),
),
);
},
delete: (e) async {
final result = await ViewBackendService.delete(viewId: view.id);
emit(
result.fold(
(l) => state.copyWith(successOrFailure: left(unit)),
(error) => state.copyWith(successOrFailure: right(error)),
),
);
RecentService().updateRecentViews([view.id], false);
},
duplicate: (e) async {
final result = await ViewBackendService.duplicate(view: view);
emit(
result.fold(
(l) => state.copyWith(successOrFailure: left(unit)),
(error) => state.copyWith(successOrFailure: right(error)),
),
);
},
move: (value) async {
final result = await ViewBackendService.moveViewV2(
viewId: value.from.id,
newParentId: value.newParentId,
prevViewId: value.prevId,
);
emit(
result.fold(
(l) => state.copyWith(successOrFailure: left(unit)),
(error) => state.copyWith(successOrFailure: right(error)),
),
);
},
createView: (e) async {
final result = await ViewBackendService.createView(
parentViewId: view.id,
name: e.name,
desc: '',
layoutType: e.layoutType,
ext: {},
openAfterCreate: e.openAfterCreated,
);
emit(
result.fold(
(view) => state.copyWith(
lastCreatedView: view,
successOrFailure: left(unit),
),
(error) => state.copyWith(successOrFailure: right(error)),
),
);
},
viewUpdateChildView: (e) async {
emit(
state.copyWith(
view: e.result,
),
);
},
);
},
);
}
Future<void> _loadViewsWhenExpanded(
Emitter<ViewState> emit,
bool isExpanded,
@ -355,7 +359,5 @@ class ViewState with _$ViewState {
isExpanded: false,
isEditing: false,
successOrFailure: left(unit),
lastCreatedView: null,
isLoading: true,
);
}

View File

@ -44,7 +44,6 @@ extension ViewExtension on ViewPB {
};
Plugin plugin({
bool listenOnViewChanged = false,
Map<String, dynamic> arguments = const {},
}) {
switch (layout) {
@ -65,7 +64,6 @@ extension ViewExtension on ViewPB {
return DocumentPlugin(
view: this,
pluginType: pluginType,
listenOnViewChanged: listenOnViewChanged,
initialSelection: initialSelection,
);
}

View File

@ -19,6 +19,8 @@ typedef RestoreViewNotifiedValue = Either<ViewPB, FlowyError>;
typedef MoveToTrashNotifiedValue = Either<DeletedViewPB, FlowyError>;
class ViewListener {
ViewListener({required this.viewId});
StreamSubscription<SubscribeObject>? _subscription;
void Function(UpdateViewNotifiedValue)? _updatedViewNotifier;
void Function(ChildViewUpdatePB)? _updateViewChildViewsNotifier;
@ -30,10 +32,6 @@ class ViewListener {
FolderNotificationParser? _parser;
final String viewId;
ViewListener({
required this.viewId,
});
void start({
void Function(UpdateViewNotifiedValue)? onViewUpdated,
void Function(ChildViewUpdatePB)? onViewChildViewsUpdated,

View File

@ -94,7 +94,6 @@ class ViewBackendService {
layoutType: layoutType,
parentViewId: parentViewId,
name: name,
openAfterCreate: false,
ext: {
'database_id': databaseId,
},
@ -236,7 +235,7 @@ class ViewBackendService {
if (childViews != null && childViews.isNotEmpty) {
result.addAll(childViews);
final views = await Future.wait(
childViews.map((e) async => await getAllViews(e)),
childViews.map((e) async => getAllViews(e)),
);
result.addAll(views.expand((element) => element));
}

View File

@ -1,18 +1,21 @@
import 'package:appflowy/user/application/user_service.dart';
import 'package:appflowy_backend/log.dart';
import 'package:appflowy_backend/protobuf/flowy-folder/workspace.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:appflowy_backend/protobuf/flowy-folder/workspace.pb.dart';
import 'package:dartz/dartz.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
part 'workspace_bloc.freezed.dart';
class WorkspaceBloc extends Bloc<WorkspaceEvent, WorkspaceState> {
WorkspaceBloc({required this.userService}) : super(WorkspaceState.initial()) {
_dispatch();
}
final UserBackendService userService;
WorkspaceBloc({
required this.userService,
}) : super(WorkspaceState.initial()) {
void _dispatch() {
on<WorkspaceEvent>(
(event, emit) async {
await event.map(

View File

@ -14,18 +14,16 @@ typedef AppListNotifyValue = Either<List<ViewPB>, FlowyError>;
typedef WorkspaceNotifyValue = Either<WorkspacePB, FlowyError>;
class WorkspaceListener {
WorkspaceListener({required this.user, required this.workspaceId});
final UserProfilePB user;
final String workspaceId;
PublishNotifier<AppListNotifyValue>? _appsChangedNotifier = PublishNotifier();
PublishNotifier<WorkspaceNotifyValue>? _workspaceUpdatedNotifier =
PublishNotifier();
FolderNotificationListener? _listener;
final UserProfilePB user;
final String workspaceId;
WorkspaceListener({
required this.user,
required this.workspaceId,
});
void start({
void Function(AppListNotifyValue)? appsChanged,

View File

@ -8,10 +8,9 @@ import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'
import 'package:appflowy_backend/protobuf/flowy-folder/workspace.pb.dart';
class WorkspaceService {
WorkspaceService({required this.workspaceId});
final String workspaceId;
WorkspaceService({
required this.workspaceId,
});
Future<Either<ViewPB, FlowyError>> createApp({
required String name,