chore: merge main

This commit is contained in:
appflowy 2022-03-01 21:09:52 +08:00
commit b16b61f46c
46 changed files with 495 additions and 415 deletions

View File

@ -27,7 +27,7 @@ jobs:
- id: rust_toolchain
uses: actions-rs/toolchain@v1
with:
toolchain: stable
toolchain: 'stable-2022-01-20'
- id: flutter
uses: subosito/flutter-action@v2
@ -47,7 +47,8 @@ jobs:
with:
path: |
frontend/rust-lib/target
key: ${{ runner.os }}-rust-${{ steps.rust_toolchain.outputs.rustc_hash }}-${{ hashFiles('./frontend/rust-lib/Cargo.toml') }}
shared-lib/target
key: ${{ runner.os }}-rust-rust-lib-share-lib-${{ steps.rust_toolchain.outputs.rustc_hash }}-${{ hashFiles('./frontend/rust-lib/Cargo.toml') }}
- name: Setup Environment
run: |

View File

@ -2,9 +2,12 @@ name: Unit test(Flutter)
on:
push:
branches: [ main ]
branches:
- 'main'
pull_request:
branches: [ main ]
branches:
- 'main'
env:
CARGO_TERM_COLOR: always
@ -13,36 +16,56 @@ jobs:
tests:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- uses: subosito/flutter-action@v1
with:
channel: "stable"
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
toolchain: stable
toolchain: 'stable-2022-01-20'
- uses: subosito/flutter-action@v2
with:
channel: 'stable'
cache: true
- name: Cache Cargo
uses: actions/cache@v2
with:
path: |
~/.cargo
key: ${{ runner.os }}-cargo-${{ steps.rust_toolchain.outputs.rustc_hash }}-${{ hashFiles('./frontend/rust-lib/Cargo.toml') }}
- name: Cache Rust
uses: actions/cache@v2
with:
path: |
frontend/rust-lib/target
shared-lib/target
key: ${{ runner.os }}-rust-rust-lib-share-lib-${{ steps.rust_toolchain.outputs.rustc_hash }}-${{ hashFiles('./frontend/rust-lib/Cargo.toml') }}
- name: Deps Flutter
working-directory: frontend/app_flowy
run: |
flutter config --enable-linux-desktop
flutter doctor
working-directory: frontend/app_flowy
- name: Deps Rust
working-directory: frontend
run: |
cargo install --force cargo-make
cargo install --force duckscript_cli
cargo install cargo-make
cargo install duckscript_cli
cargo make flowy_dev
echo PATH="$PATH":"$HOME/.pub-cache/bin" >> $GITHUB_PATH
- name: Code Generation
working-directory: frontend/app_flowy
run: |
flutter packages pub get
flutter packages pub run easy_localization:generate -S ./assets/translations -f keys -O lib/generated -o locale_keys.g.dart
flutter packages pub run build_runner build --delete-conflicting-outputs
- name: Build FlowySDK
working-directory: frontend
run: |
cargo make --profile development-linux-x86 flowy-sdk-dev
- name: Run bloc tests
working-directory: frontend/app_flowy
run: |

View File

@ -44,7 +44,7 @@ jobs:
- name: Setup environment - Rust and Cargo
uses: actions-rs/toolchain@v1
with:
toolchain: stable
toolchain: 'stable-2022-01-20'
- name: Setup environment - Flutter
uses: subosito/flutter-action@v2
@ -92,7 +92,7 @@ jobs:
- name: Setup environment - Rust and Cargo
uses: actions-rs/toolchain@v1
with:
toolchain: stable
toolchain: 'stable-2022-01-20'
- name: Setup environment - Flutter
uses: subosito/flutter-action@v2

View File

@ -24,7 +24,7 @@ jobs:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
toolchain: stable
toolchain: 'stable-2022-01-20'
override: true
- run: rustup component add rustfmt
working-directory: frontend/rust-lib
@ -39,7 +39,7 @@ jobs:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
toolchain: stable
toolchain: 'stable-2022-01-20'
override: true
- run: rustup component add clippy
working-directory: frontend/rust-lib

View File

@ -2,12 +2,14 @@ name: Unit test(Rust)
on:
push:
branches: [ main ]
branches:
- 'main'
paths:
- 'frontend/rust-lib'
- 'shared-lib'
pull_request:
branches: [ main ]
branches:
- 'main'
paths:
- 'frontend/rust-lib'
- 'shared-lib'
@ -21,19 +23,35 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Install Rust
run: |
curl \
--proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
source $HOME/.cargo/env
rustup toolchain install stable
rustup default stable
- id: rust_toolchain
uses: actions-rs/toolchain@v1
with:
toolchain: 'stable-2022-01-20'
- name: Cache Cargo
uses: actions/cache@v2
with:
path: |
~/.cargo
key: ${{ runner.os }}-cargo-${{ steps.rust_toolchain.outputs.rustc_hash }}-${{ hashFiles('./frontend/rust-lib/Cargo.toml') }}
- name: Cache Rust
uses: actions/cache@v2
with:
path: |
frontend/rust-lib/target
shared-lib/target
key: ${{ runner.os }}-rust-rust-lib-share-lib-${{ steps.rust_toolchain.outputs.rustc_hash }}-${{ hashFiles('./frontend/rust-lib/Cargo.toml') }}
- name: Install cargo-make
run: cargo install --force cargo-make
working-directory: frontend
run: cargo install cargo-make
- name: Run rust-lib tests
run: cargo test --no-default-features
working-directory: frontend/rust-lib
- name: Run shared-lib tests
run: cargo test --no-default-features
- name: Run shared-lib tests
working-directory: shared-lib
run: cargo test --no-default-features

View File

@ -1,23 +1,29 @@
import 'package:app_flowy/user/application/user_listener.dart';
import 'package:app_flowy/user/application/user_service.dart';
import 'package:app_flowy/workspace/application/app/app_bloc.dart';
import 'package:app_flowy/workspace/application/app/app_listener.dart';
import 'package:app_flowy/workspace/application/app/app_service.dart';
import 'package:app_flowy/workspace/application/doc/doc_bloc.dart';
import 'package:app_flowy/workspace/application/doc/doc_service.dart';
import 'package:app_flowy/workspace/application/doc/share_bloc.dart';
import 'package:app_flowy/workspace/application/doc/share_service.dart';
import 'package:app_flowy/workspace/application/home/home_listen_bloc.dart';
import 'package:app_flowy/workspace/application/menu/menu_bloc.dart';
import 'package:app_flowy/workspace/application/menu/menu_user_bloc.dart';
import 'package:app_flowy/workspace/application/trash/trash_bloc.dart';
import 'package:app_flowy/workspace/application/trash/trash_listener.dart';
import 'package:app_flowy/workspace/application/trash/trash_service.dart';
import 'package:app_flowy/workspace/application/view/view_bloc.dart';
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/workspace/welcome_bloc.dart';
import 'package:app_flowy/workspace/infrastructure/repos/app_repo.dart';
import 'package:app_flowy/workspace/infrastructure/repos/trash_repo.dart';
import 'package:app_flowy/workspace/infrastructure/repos/user_repo.dart';
import 'package:app_flowy/workspace/infrastructure/repos/view_repo.dart';
import 'package:app_flowy/workspace/infrastructure/repos/workspace_repo.dart';
import 'package:app_flowy/workspace/application/workspace/workspace_listener.dart';
import 'package:app_flowy/workspace/application/workspace/workspace_service.dart';
import 'package:app_flowy/workspace/presentation/home/home_stack.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-user-data-model/user_profile.pb.dart';
import 'package:get_it/get_it.dart';
import 'repos/share_repo.dart';
class HomeDepsResolver {
static Future<void> resolve(GetIt getIt) async {
@ -33,23 +39,24 @@ class HomeDepsResolver {
getIt.registerLazySingleton<HomeStackManager>(() => HomeStackManager());
getIt.registerFactoryParam<WelcomeBloc, UserProfile, void>(
(user, _) => WelcomeBloc(
repo: UserRepo(user: user),
listener: getIt<UserListener>(param1: user),
userService: UserService(),
userListener: getIt<UserListener>(param1: user),
),
);
//workspace
getIt.registerFactoryParam<WorkspaceListener, UserProfile, String>(
(user, workspaceId) => WorkspaceListener(repo: WorkspaceListenerRepo(user: user, workspaceId: workspaceId)));
getIt.registerFactoryParam<WorkspaceListener, UserProfile, String>((user, workspaceId) =>
WorkspaceListener(service: WorkspaceListenerService(user: user, workspaceId: workspaceId)));
// View
getIt.registerFactoryParam<ViewListener, View, void>(
(view, _) => ViewListener(view: view),
);
getIt.registerFactoryParam<ViewMenuBloc, View, void>(
(view, _) => ViewMenuBloc(
repo: ViewRepository(view: view),
getIt.registerFactoryParam<ViewBloc, View, void>(
(view, _) => ViewBloc(
view: view,
service: ViewService(),
listener: getIt<ViewListener>(param1: view),
),
);
@ -57,14 +64,16 @@ class HomeDepsResolver {
//Menu Bloc
getIt.registerFactoryParam<MenuBloc, UserProfile, String>(
(user, workspaceId) => MenuBloc(
repo: WorkspaceRepo(user: user, workspaceId: workspaceId),
workspaceId: workspaceId,
service: WorkspaceService(),
listener: getIt<WorkspaceListener>(param1: user, param2: workspaceId),
),
);
getIt.registerFactoryParam<MenuUserBloc, UserProfile, void>(
(user, _) => MenuUserBloc(
UserRepo(user: user),
user,
UserService(),
getIt<UserListener>(param1: user),
),
);
@ -73,7 +82,7 @@ class HomeDepsResolver {
getIt.registerFactoryParam<AppBloc, App, void>(
(app, _) => AppBloc(
app: app,
repo: AppRepository(appId: app.id),
service: AppService(),
listener: AppListener(appId: app.id),
),
);
@ -81,25 +90,26 @@ class HomeDepsResolver {
// Doc
getIt.registerFactoryParam<DocumentBloc, View, void>(
(view, _) => DocumentBloc(
repo: ViewRepository(view: view),
view: view,
service: DocumentService(),
listener: getIt<ViewListener>(param1: view),
trashRepo: getIt<TrashRepo>(),
trashService: getIt<TrashService>(),
),
);
// trash
getIt.registerLazySingleton<TrashRepo>(() => TrashRepo());
getIt.registerLazySingleton<TrashService>(() => TrashService());
getIt.registerLazySingleton<TrashListener>(() => TrashListener());
getIt.registerFactory<TrashBloc>(
() => TrashBloc(
repo: getIt<TrashRepo>(),
service: getIt<TrashService>(),
listener: getIt<TrashListener>(),
),
);
// share
getIt.registerLazySingleton<ShareRepo>(() => ShareRepo());
getIt.registerLazySingleton<ShareService>(() => ShareService());
getIt.registerFactoryParam<DocShareBloc, View, void>(
(view, _) => DocShareBloc(view: view, repo: getIt<ShareRepo>()));
(view, _) => DocShareBloc(view: view, service: getIt<ShareService>()));
}
}

View File

@ -5,7 +5,7 @@ import 'package:app_flowy/startup/tasks/prelude.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:get_it/get_it.dart';
import 'package:app_flowy/workspace/infrastructure/deps_resolver.dart';
import 'package:app_flowy/startup/deps_resolver.dart';
import 'package:app_flowy/user/infrastructure/deps_resolver.dart';
import 'package:flowy_sdk/flowy_sdk.dart';

View File

@ -1,74 +1,17 @@
import 'dart:async';
import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/dispatch/dispatch.dart';
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/workspace.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'dart:typed_data';
import 'package:app_flowy/workspace/infrastructure/repos/helper.dart';
import 'package:app_flowy/core/helper.dart';
import 'package:flowy_infra/notifier.dart';
import 'package:flowy_sdk/protobuf/dart-notify/protobuf.dart';
import 'package:flowy_sdk/protobuf/flowy-folder/dart_notification.pb.dart';
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:flowy_sdk/protobuf/flowy-user/errors.pb.dart' as user_error;
import 'package:flowy_sdk/protobuf/flowy-user/dart_notification.pb.dart' as user;
import 'package:flowy_sdk/rust_stream.dart';
class UserRepo {
final UserProfile user;
UserRepo({
required this.user,
});
Future<Either<UserProfile, FlowyError>> fetchUserProfile({required String userId}) {
return UserEventGetUserProfile().send();
}
Future<Either<Unit, FlowyError>> deleteWorkspace({required String workspaceId}) {
throw UnimplementedError();
}
Future<Either<Unit, FlowyError>> signOut() {
return UserEventSignOut().send();
}
Future<Either<Unit, FlowyError>> initUser() async {
return UserEventInitUser().send();
}
Future<Either<List<Workspace>, FlowyError>> getWorkspaces() {
final request = WorkspaceId.create();
return FolderEventReadWorkspaces(request).send().then((result) {
return result.fold(
(workspaces) => left(workspaces.items),
(error) => right(error),
);
});
}
Future<Either<Workspace, FlowyError>> openWorkspace(String workspaceId) {
final request = WorkspaceId.create()..value = workspaceId;
return FolderEventOpenWorkspace(request).send().then((result) {
return result.fold(
(workspace) => left(workspace),
(error) => right(error),
);
});
}
Future<Either<Workspace, FlowyError>> createWorkspace(String name, String desc) {
final request = CreateWorkspacePayload.create()
..name = name
..desc = desc;
return FolderEventCreateWorkspace(request).send().then((result) {
return result.fold(
(workspace) => left(workspace),
(error) => right(error),
);
});
}
}
typedef UserProfileUpdatedNotifierValue = Either<UserProfile, FlowyError>;
typedef AuthNotifierValue = Either<Unit, FlowyError>;

View File

@ -0,0 +1,57 @@
import 'dart:async';
import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/dispatch/dispatch.dart';
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/workspace.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-user-data-model/user_profile.pb.dart';
class UserService {
Future<Either<UserProfile, FlowyError>> fetchUserProfile({required String userId}) {
return UserEventGetUserProfile().send();
}
Future<Either<Unit, FlowyError>> deleteWorkspace({required String workspaceId}) {
throw UnimplementedError();
}
Future<Either<Unit, FlowyError>> signOut() {
return UserEventSignOut().send();
}
Future<Either<Unit, FlowyError>> initUser() async {
return UserEventInitUser().send();
}
Future<Either<List<Workspace>, FlowyError>> getWorkspaces() {
final request = WorkspaceId.create();
return FolderEventReadWorkspaces(request).send().then((result) {
return result.fold(
(workspaces) => left(workspaces.items),
(error) => right(error),
);
});
}
Future<Either<Workspace, FlowyError>> openWorkspace(String workspaceId) {
final request = WorkspaceId.create()..value = workspaceId;
return FolderEventOpenWorkspace(request).send().then((result) {
return result.fold(
(workspace) => left(workspace),
(error) => right(error),
);
});
}
Future<Either<Workspace, FlowyError>> createWorkspace(String name, String desc) {
final request = CreateWorkspacePayload.create()
..name = name
..desc = desc;
return FolderEventCreateWorkspace(request).send().then((result) {
return result.fold(
(workspace) => left(workspace),
(error) => right(error),
);
});
}
}

View File

@ -4,7 +4,6 @@ import 'package:app_flowy/user/presentation/sign_in_screen.dart';
import 'package:app_flowy/user/presentation/sign_up_screen.dart';
import 'package:app_flowy/user/presentation/skip_log_in_screen.dart';
import 'package:app_flowy/user/presentation/welcome_screen.dart';
import 'package:app_flowy/workspace/infrastructure/repos/user_repo.dart';
import 'package:app_flowy/workspace/presentation/home/home_screen.dart';
import 'package:flowy_infra/time/duration.dart';
import 'package:flowy_infra_ui/widget/route/animation.dart';
@ -38,9 +37,8 @@ class AuthRouter {
}
class SplashRoute {
Future<void> pushWelcomeScreen(BuildContext context, UserProfile user) async {
final repo = UserRepo(user: user);
final screen = WelcomeScreen(repo: repo);
Future<void> pushWelcomeScreen(BuildContext context, UserProfile userProfile) async {
final screen = WelcomeScreen(userProfile: userProfile);
final workspaceId = await Navigator.of(context).push(
PageRoutes.fade(
() => screen,
@ -48,7 +46,7 @@ class SplashRoute {
),
);
pushHomeScreen(context, repo.user, workspaceId);
pushHomeScreen(context, userProfile, workspaceId);
}
void pushHomeScreen(BuildContext context, UserProfile userProfile, CurrentWorkspaceSetting workspaceSetting) {

View File

@ -1,7 +1,7 @@
import 'package:app_flowy/user/application/user_listener.dart';
import 'package:app_flowy/user/infrastructure/router.dart';
import 'package:app_flowy/user/infrastructure/repos/auth_repo.dart';
import 'package:app_flowy/user/presentation/widgets/background.dart';
import 'package:app_flowy/workspace/infrastructure/repos/user_repo.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra/size.dart';
import 'package:flowy_infra/theme.dart';

View File

@ -6,22 +6,22 @@ import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart';
import 'package:flowy_infra_ui/style_widget/button.dart';
import 'package:flowy_infra_ui/widget/error_page.dart';
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/workspace.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-user-data-model/user_profile.pb.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:app_flowy/workspace/infrastructure/repos/user_repo.dart';
import 'package:app_flowy/generated/locale_keys.g.dart';
class WelcomeScreen extends StatelessWidget {
final UserRepo repo;
final UserProfile userProfile;
const WelcomeScreen({
Key? key,
required this.repo,
required this.userProfile,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (_) => getIt<WelcomeBloc>(param1: repo.user)..add(const WelcomeEvent.initial()),
create: (_) => getIt<WelcomeBloc>(param1: userProfile)..add(const WelcomeEvent.initial()),
child: BlocBuilder<WelcomeBloc, WelcomeState>(
builder: (context, state) {
return Scaffold(

View File

@ -1,5 +1,6 @@
import 'package:app_flowy/plugin/plugin.dart';
import 'package:app_flowy/workspace/infrastructure/repos/app_repo.dart';
import 'package:app_flowy/workspace/application/app/app_listener.dart';
import 'package:app_flowy/workspace/application/app/app_service.dart';
import 'package:flowy_sdk/log.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';
@ -11,9 +12,11 @@ import 'package:dartz/dartz.dart';
part 'app_bloc.freezed.dart';
class AppBloc extends Bloc<AppEvent, AppState> {
final AppRepository repo;
final App app;
final AppService service;
final AppListener listener;
AppBloc({required App app, required this.repo, required this.listener}) : super(AppState.initial(app)) {
AppBloc({required this.app, required this.service, required this.listener}) : super(AppState.initial(app)) {
on<AppEvent>((event, emit) async {
await event.map(initial: (e) async {
listener.startListening(
@ -22,7 +25,8 @@ class AppBloc extends Bloc<AppEvent, AppState> {
);
await _fetchViews(emit);
}, createView: (CreateView value) async {
final viewOrFailed = await repo.createView(
final viewOrFailed = await service.createView(
appId: app.id,
name: value.name,
desc: value.desc,
dataType: value.dataType,
@ -41,13 +45,13 @@ class AppBloc extends Bloc<AppEvent, AppState> {
}, didReceiveViews: (e) async {
await handleDidReceiveViews(e.views, emit);
}, delete: (e) async {
final result = await repo.delete();
final result = await service.delete(appId: app.id);
result.fold(
(unit) => emit(state.copyWith(successOrFailure: left(unit))),
(error) => emit(state.copyWith(successOrFailure: right(error))),
);
}, rename: (e) async {
final result = await repo.updateApp(name: e.newName);
final result = await service.updateApp(appId: app.id, name: e.newName);
result.fold(
(l) => emit(state.copyWith(successOrFailure: left(unit))),
(error) => emit(state.copyWith(successOrFailure: right(error))),
@ -87,7 +91,7 @@ class AppBloc extends Bloc<AppEvent, AppState> {
}
Future<void> _fetchViews(Emitter<AppState> emit) async {
final viewsOrFailed = await repo.getViews();
final viewsOrFailed = await service.getViews(appId: app.id);
viewsOrFailed.fold(
(apps) => emit(state.copyWith(views: apps)),
(error) {

View File

@ -1,70 +1,14 @@
import 'dart:async';
import 'dart:typed_data';
import 'package:app_flowy/plugin/plugin.dart';
import 'package:dartz/dartz.dart';
import 'package:app_flowy/core/helper.dart';
import 'package:flowy_sdk/log.dart';
import 'package:flowy_sdk/dispatch/dispatch.dart';
import 'package:flowy_sdk/protobuf/dart-notify/subject.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.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-error/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-folder/dart_notification.pb.dart';
import 'package:flowy_sdk/rust_stream.dart';
import 'helper.dart';
class AppRepository {
String appId;
AppRepository({
required this.appId,
});
Future<Either<App, FlowyError>> getAppDesc() {
final request = AppId.create()..value = appId;
return FolderEventReadApp(request).send();
}
Future<Either<View, FlowyError>> createView({
required String name,
required String desc,
required PluginDataType dataType,
required PluginType pluginType,
}) {
final request = CreateViewPayload.create()
..belongToId = appId
..name = name
..desc = desc
..dataType = dataType
..pluginType = pluginType;
return FolderEventCreateView(request).send();
}
Future<Either<List<View>, FlowyError>> getViews() {
final request = AppId.create()..value = appId;
return FolderEventReadApp(request).send().then((result) {
return result.fold(
(app) => left(app.belongings.items),
(error) => right(error),
);
});
}
Future<Either<Unit, FlowyError>> delete() {
final request = AppId.create()..value = appId;
return FolderEventDeleteApp(request).send();
}
Future<Either<Unit, FlowyError>> updateApp({String? name}) {
UpdateAppPayload request = UpdateAppPayload.create()..appId = appId;
if (name != null) {
request.name = name;
}
return FolderEventUpdateApp(request).send();
}
}
typedef AppDidUpdateCallback = void Function(App app);
typedef ViewsDidChangeCallback = void Function(Either<List<View>, FlowyError> viewsOrFailed);

View File

@ -0,0 +1,57 @@
import 'dart:async';
import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/dispatch/dispatch.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-error/errors.pb.dart';
import 'package:app_flowy/plugin/plugin.dart';
class AppService {
Future<Either<App, FlowyError>> getAppDesc({required String appId}) {
final request = AppId.create()..value = appId;
return FolderEventReadApp(request).send();
}
Future<Either<View, FlowyError>> createView({
required String appId,
required String name,
required String desc,
required PluginDataType dataType,
required PluginType pluginType,
}) {
final request = CreateViewPayload.create()
..belongToId = appId
..name = name
..desc = desc
..dataType = dataType
..pluginType = pluginType;
return FolderEventCreateView(request).send();
}
Future<Either<List<View>, FlowyError>> getViews({required String appId}) {
final request = AppId.create()..value = appId;
return FolderEventReadApp(request).send().then((result) {
return result.fold(
(app) => left(app.belongings.items),
(error) => right(error),
);
});
}
Future<Either<Unit, FlowyError>> delete({required String appId}) {
final request = AppId.create()..value = appId;
return FolderEventDeleteApp(request).send();
}
Future<Either<Unit, FlowyError>> updateApp({required String appId, String? name}) {
UpdateAppPayload request = UpdateAppPayload.create()..appId = appId;
if (name != null) {
request.name = name;
}
return FolderEventUpdateApp(request).send();
}
}

View File

@ -1,29 +1,35 @@
import 'dart:convert';
import 'package:app_flowy/workspace/infrastructure/repos/trash_repo.dart';
import 'package:app_flowy/workspace/infrastructure/repos/view_repo.dart';
import 'package:app_flowy/workspace/application/doc/doc_service.dart';
import 'package:app_flowy/workspace/application/trash/trash_service.dart';
import 'package:app_flowy/workspace/application/view/view_listener.dart';
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/trash.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
import 'package:flutter_quill/flutter_quill.dart' show Document, Delta;
import 'package:flowy_sdk/log.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:dartz/dartz.dart';
import 'dart:async';
part 'doc_bloc.freezed.dart';
typedef FlutterQuillDocument = Document;
class DocumentBloc extends Bloc<DocumentEvent, DocumentState> {
final ViewRepository repo;
final View view;
final DocumentService service;
final ViewListener listener;
final TrashRepo trashRepo;
final TrashService trashService;
late FlutterQuillDocument document;
StreamSubscription? _subscription;
DocumentBloc({
required this.repo,
required this.view,
required this.service,
required this.listener,
required this.trashRepo,
required this.trashService,
}) : super(DocumentState.initial()) {
on<DocumentEvent>((event, emit) async {
await event.map(
@ -37,12 +43,13 @@ class DocumentBloc extends Bloc<DocumentEvent, DocumentState> {
emit(state.copyWith(isDeleted: false));
},
deletePermanently: (DeletePermanently value) async {
final result = await trashRepo.deleteViews([Tuple2(repo.view.id, TrashType.TrashView)]);
final result = await trashService.deleteViews([Tuple2(view.id, TrashType.TrashView)]);
final newState = result.fold((l) => state.copyWith(forceClose: true), (r) => state);
emit(newState);
},
restorePage: (RestorePage value) async {
final result = await trashRepo.putback(repo.view.id);
final result = await trashService.putback(view.id);
final newState = result.fold((l) => state.copyWith(isDeleted: false), (r) => state);
emit(newState);
},
@ -58,7 +65,7 @@ class DocumentBloc extends Bloc<DocumentEvent, DocumentState> {
await _subscription?.cancel();
}
repo.closeDocument();
service.closeDocument(docId: view.id);
return super.close();
}
@ -78,7 +85,7 @@ class DocumentBloc extends Bloc<DocumentEvent, DocumentState> {
});
listener.start();
final result = await repo.openDocument();
final result = await service.openDocument(docId: view.id);
result.fold(
(block) {
document = _decodeJsonToDocument(block.deltaJson);
@ -103,8 +110,8 @@ class DocumentBloc extends Bloc<DocumentEvent, DocumentState> {
void _composeDelta(Delta composedDelta, Delta documentDelta) async {
final json = jsonEncode(composedDelta.toJson());
Log.debug("doc_id: $repo.view.id - Send json: $json");
final result = await repo.composeDelta(data: json);
Log.debug("doc_id: $view.id - Send json: $json");
final result = await service.composeDelta(docId: view.id, data: json);
result.fold((rustDoc) {
// final json = utf8.decode(doc.data);

View File

@ -0,0 +1,24 @@
import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/dispatch/dispatch.dart';
import 'package:flowy_sdk/protobuf/flowy-collaboration/document_info.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
class DocumentService {
Future<Either<BlockDelta, FlowyError>> openDocument({required String docId}) {
final request = ViewId(value: docId);
return FolderEventOpenView(request).send();
}
Future<Either<BlockDelta, FlowyError>> composeDelta({required String docId, required String data}) {
final request = BlockDelta.create()
..blockId = docId
..deltaJson = data;
return FolderEventApplyDocDelta(request).send();
}
Future<Either<Unit, FlowyError>> closeDocument({required String docId}) {
final request = ViewId(value: docId);
return FolderEventCloseView(request).send();
}
}

View File

@ -1,5 +1,5 @@
import 'package:app_flowy/workspace/infrastructure/markdown/delta_markdown.dart';
import 'package:app_flowy/workspace/infrastructure/repos/share_repo.dart';
import 'package:app_flowy/workspace/application/doc/share_service.dart';
import 'package:app_flowy/workspace/application/markdown/delta_markdown.dart';
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/share.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
@ -9,13 +9,13 @@ import 'package:dartz/dartz.dart';
part 'share_bloc.freezed.dart';
class DocShareBloc extends Bloc<DocShareEvent, DocShareState> {
ShareRepo repo;
ShareService service;
View view;
DocShareBloc({required this.view, required this.repo}) : super(const DocShareState.initial()) {
DocShareBloc({required this.view, required this.service}) : super(const DocShareState.initial()) {
on<DocShareEvent>((event, emit) async {
await event.map(
shareMarkdown: (ShareMarkdown value) async {
await repo.exportMarkdown(view.id).then((result) {
await service.exportMarkdown(view.id).then((result) {
result.fold(
(value) => emit(DocShareState.finish(left(_convertDeltaToMarkdown(value)))),
(error) => emit(DocShareState.finish(right(error))),

View File

@ -4,7 +4,7 @@ import 'package:flowy_sdk/dispatch/dispatch.dart';
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/protobuf.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
class ShareRepo {
class ShareService {
Future<Either<ExportData, FlowyError>> export(String docId, ExportType type) {
final request = ExportPayload.create()
..viewId = docId

View File

@ -1,4 +1,4 @@
import 'package:app_flowy/workspace/infrastructure/repos/user_repo.dart';
import 'package:app_flowy/user/application/user_listener.dart';
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:freezed_annotation/freezed_annotation.dart';

View File

@ -1,7 +1,8 @@
import 'dart:async';
import 'package:app_flowy/plugin/plugin.dart';
import 'package:app_flowy/startup/tasks/load_plugin.dart';
import 'package:app_flowy/workspace/infrastructure/repos/workspace_repo.dart';
import 'package:app_flowy/workspace/application/workspace/workspace_listener.dart';
import 'package:app_flowy/workspace/application/workspace/workspace_service.dart';
import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/log.dart';
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/app.pb.dart';
@ -12,9 +13,11 @@ import 'package:flutter_bloc/flutter_bloc.dart';
part 'menu_bloc.freezed.dart';
class MenuBloc extends Bloc<MenuEvent, MenuState> {
final WorkspaceRepo repo;
final WorkspaceService service;
final WorkspaceListener listener;
MenuBloc({required this.repo, required this.listener}) : super(MenuState.initial()) {
final String workspaceId;
MenuBloc({required this.workspaceId, required this.service, required this.listener}) : super(MenuState.initial()) {
on<MenuEvent>((event, emit) async {
await event.map(
initial: (e) async {
@ -48,7 +51,7 @@ class MenuBloc extends Bloc<MenuEvent, MenuState> {
}
Future<void> _performActionOnCreateApp(CreateApp event, Emitter<MenuState> emit) async {
final result = await repo.createApp(event.name, event.desc ?? "");
final result = await service.createApp(workspaceId: workspaceId, name: event.name, desc: event.desc ?? "");
result.fold(
(app) => {},
(error) {
@ -60,7 +63,7 @@ class MenuBloc extends Bloc<MenuEvent, MenuState> {
// ignore: unused_element
Future<void> _fetchApps(Emitter<MenuState> emit) async {
final appsOrFail = await repo.getApps();
final appsOrFail = await service.getApps(workspaceId: workspaceId);
emit(appsOrFail.fold(
(apps) => state.copyWith(apps: some(apps)),
(error) {

View File

@ -1,4 +1,5 @@
import 'package:app_flowy/workspace/infrastructure/repos/user_repo.dart';
import 'package:app_flowy/user/application/user_listener.dart';
import 'package:app_flowy/user/application/user_service.dart';
import 'package:flowy_sdk/log.dart';
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/workspace.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
@ -10,16 +11,17 @@ import 'package:dartz/dartz.dart';
part 'menu_user_bloc.freezed.dart';
class MenuUserBloc extends Bloc<MenuUserEvent, MenuUserState> {
final UserRepo repo;
final UserListener listener;
final UserService userService;
final UserListener userListener;
final UserProfile userProfile;
MenuUserBloc(this.repo, this.listener) : super(MenuUserState.initial(repo.user)) {
MenuUserBloc(this.userProfile, this.userService, this.userListener) : super(MenuUserState.initial(userProfile)) {
on<MenuUserEvent>((event, emit) async {
await event.map(
initial: (_) async {
listener.profileUpdatedNotifier.addPublishListener(_profileUpdated);
listener.workspaceUpdatedNotifier.addPublishListener(_workspacesUpdated);
listener.start();
userListener.profileUpdatedNotifier.addPublishListener(_profileUpdated);
userListener.workspaceUpdatedNotifier.addPublishListener(_workspacesUpdated);
userListener.start();
await _initUser();
},
fetchWorkspaces: (_FetchWorkspaces value) async {},
@ -29,12 +31,12 @@ class MenuUserBloc extends Bloc<MenuUserEvent, MenuUserState> {
@override
Future<void> close() async {
await listener.stop();
await userListener.stop();
super.close();
}
Future<void> _initUser() async {
final result = await repo.initUser();
final result = await userService.initUser();
result.fold((l) => null, (error) => Log.error(error));
}

View File

@ -1,20 +1,21 @@
import 'package:app_flowy/workspace/infrastructure/repos/trash_repo.dart';
import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/log.dart';
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/trash.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:app_flowy/workspace/application/trash/trash_service.dart';
import 'package:app_flowy/workspace/application/trash/trash_listener.dart';
part 'trash_bloc.freezed.dart';
class TrashBloc extends Bloc<TrashEvent, TrashState> {
final TrashRepo repo;
final TrashService service;
final TrashListener listener;
TrashBloc({required this.repo, required this.listener}) : super(TrashState.init()) {
TrashBloc({required this.service, required this.listener}) : super(TrashState.init()) {
on<TrashEvent>((event, emit) async {
await event.map(initial: (e) async {
listener.startListening(trashUpdated: _listenTrashUpdated);
final result = await repo.readTrash();
final result = await service.readTrash();
emit(result.fold(
(object) => state.copyWith(objects: object.items, successOrFailure: left(unit)),
(error) => state.copyWith(successOrFailure: right(error)),
@ -22,16 +23,16 @@ class TrashBloc extends Bloc<TrashEvent, TrashState> {
}, didReceiveTrash: (e) async {
emit(state.copyWith(objects: e.trash));
}, putback: (e) async {
final result = await repo.putback(e.trashId);
final result = await service.putback(e.trashId);
await _handleResult(result, emit);
}, delete: (e) async {
final result = await repo.deleteViews([Tuple2(e.trash.id, e.trash.ty)]);
final result = await service.deleteViews([Tuple2(e.trash.id, e.trash.ty)]);
await _handleResult(result, emit);
}, deleteAll: (e) async {
final result = await repo.deleteAll();
final result = await service.deleteAll();
await _handleResult(result, emit);
}, restoreAll: (e) async {
final result = await repo.restoreAll();
final result = await service.restoreAll();
await _handleResult(result, emit);
});
});

View File

@ -1,45 +1,13 @@
import 'dart:async';
import 'dart:typed_data';
import 'package:app_flowy/workspace/infrastructure/repos/helper.dart';
import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/dispatch/dispatch.dart';
import 'package:app_flowy/core/helper.dart';
import 'package:flowy_sdk/protobuf/dart-notify/subject.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-folder/dart_notification.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/trash.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-folder/dart_notification.pb.dart';
import 'package:flowy_sdk/rust_stream.dart';
class TrashRepo {
Future<Either<RepeatedTrash, FlowyError>> readTrash() {
return FolderEventReadTrash().send();
}
Future<Either<Unit, FlowyError>> putback(String trashId) {
final id = TrashId.create()..id = trashId;
return FolderEventPutbackTrash(id).send();
}
Future<Either<Unit, FlowyError>> deleteViews(List<Tuple2<String, TrashType>> trashList) {
final items = trashList.map((trash) {
return TrashId.create()
..id = trash.value1
..ty = trash.value2;
});
final ids = RepeatedTrashId(items: items);
return FolderEventDeleteTrash(ids).send();
}
Future<Either<Unit, FlowyError>> restoreAll() {
return FolderEventRestoreAllTrash().send();
}
Future<Either<Unit, FlowyError>> deleteAll() {
return FolderEventDeleteAllTrash().send();
}
}
typedef TrashUpdatedCallback = void Function(Either<List<Trash>, FlowyError> trashOrFailed);
class TrashListener {

View File

@ -0,0 +1,37 @@
import 'dart:async';
import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/dispatch/dispatch.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/trash.pb.dart';
class TrashService {
Future<Either<RepeatedTrash, FlowyError>> readTrash() {
return FolderEventReadTrash().send();
}
Future<Either<Unit, FlowyError>> putback(String trashId) {
final id = TrashId.create()..id = trashId;
return FolderEventPutbackTrash(id).send();
}
Future<Either<Unit, FlowyError>> deleteViews(List<Tuple2<String, TrashType>> trashList) {
final items = trashList.map((trash) {
return TrashId.create()
..id = trash.value1
..ty = trash.value2;
});
final ids = RepeatedTrashId(items: items);
return FolderEventDeleteTrash(ids).send();
}
Future<Either<Unit, FlowyError>> restoreAll() {
return FolderEventRestoreAllTrash().send();
}
Future<Either<Unit, FlowyError>> deleteAll() {
return FolderEventDeleteAllTrash().send();
}
}

View File

@ -1,4 +1,5 @@
import 'package:app_flowy/workspace/infrastructure/repos/view_repo.dart';
import 'package:app_flowy/workspace/application/view/view_listener.dart';
import 'package:app_flowy/workspace/application/view/view_service.dart';
import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
@ -7,18 +8,20 @@ import 'package:freezed_annotation/freezed_annotation.dart';
part 'view_bloc.freezed.dart';
class ViewMenuBloc extends Bloc<ViewEvent, ViewState> {
final ViewRepository repo;
class ViewBloc extends Bloc<ViewEvent, ViewState> {
final ViewService service;
final ViewListener listener;
final View view;
ViewMenuBloc({
required this.repo,
ViewBloc({
required this.view,
required this.service,
required this.listener,
}) : super(ViewState.init(repo.view)) {
}) : super(ViewState.init(view)) {
on<ViewEvent>((event, emit) async {
await event.map(
initial: (e) {
// TODO: Listener can be refctored to a stream.
// TODO: Listener can be refactored to a stream.
listener.updatedNotifier.addPublishListener((result) {
// emit.forEach(stream, onData: onData)
add(ViewEvent.viewDidUpdate(result));
@ -36,7 +39,7 @@ class ViewMenuBloc extends Bloc<ViewEvent, ViewState> {
);
},
rename: (e) async {
final result = await repo.updateView(name: e.newName);
final result = await service.updateView(viewId: view.id, name: e.newName);
emit(
result.fold(
(l) => state.copyWith(successOrFailure: left(unit)),
@ -45,7 +48,7 @@ class ViewMenuBloc extends Bloc<ViewEvent, ViewState> {
);
},
delete: (e) async {
final result = await repo.delete();
final result = await service.delete(viewId: view.id);
emit(
result.fold(
(l) => state.copyWith(successOrFailure: left(unit)),
@ -54,7 +57,7 @@ class ViewMenuBloc extends Bloc<ViewEvent, ViewState> {
);
},
duplicate: (e) async {
final result = await repo.duplicate();
final result = await service.duplicate(viewId: view.id);
emit(
result.fold(
(l) => state.copyWith(successOrFailure: left(unit)),

View File

@ -1,70 +1,14 @@
import 'dart:async';
import 'dart:typed_data';
import 'package:app_flowy/core/helper.dart';
import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/dispatch/dispatch.dart';
import 'package:flowy_sdk/protobuf/dart-notify/subject.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-collaboration/document_info.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-folder/dart_notification.pb.dart';
import 'package:flowy_sdk/rust_stream.dart';
import 'package:flowy_infra/notifier.dart';
import 'helper.dart';
class ViewRepository {
View view;
ViewRepository({
required this.view,
});
Future<Either<View, FlowyError>> readView() {
final request = ViewId(value: view.id);
return FolderEventReadView(request).send();
}
Future<Either<View, FlowyError>> updateView({String? name, String? desc}) {
final request = UpdateViewPayload.create()..viewId = view.id;
if (name != null) {
request.name = name;
}
if (desc != null) {
request.desc = desc;
}
return FolderEventUpdateView(request).send();
}
Future<Either<Unit, FlowyError>> delete() {
final request = RepeatedViewId.create()..items.add(view.id);
return FolderEventDeleteView(request).send();
}
Future<Either<Unit, FlowyError>> duplicate() {
final request = ViewId(value: view.id);
return FolderEventDuplicateView(request).send();
}
Future<Either<BlockDelta, FlowyError>> openDocument() {
final request = ViewId(value: view.id);
return FolderEventOpenView(request).send();
}
Future<Either<BlockDelta, FlowyError>> composeDelta({required String data}) {
final request = BlockDelta.create()
..blockId = view.id
..deltaJson = data;
return FolderEventApplyDocDelta(request).send();
}
Future<Either<Unit, FlowyError>> closeDocument() {
final request = ViewId(value: view.id);
return FolderEventCloseView(request).send();
}
}
typedef DeleteNotifierValue = Either<View, FlowyError>;
typedef UpdateNotifierValue = Either<View, FlowyError>;
typedef RestoreNotifierValue = Either<View, FlowyError>;

View File

@ -0,0 +1,36 @@
import 'dart:async';
import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/dispatch/dispatch.dart';
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
class ViewService {
Future<Either<View, FlowyError>> readView({required String viewId}) {
final request = ViewId(value: viewId);
return FolderEventReadView(request).send();
}
Future<Either<View, FlowyError>> updateView({required String viewId, String? name, String? desc}) {
final request = UpdateViewPayload.create()..viewId = viewId;
if (name != null) {
request.name = name;
}
if (desc != null) {
request.desc = desc;
}
return FolderEventUpdateView(request).send();
}
Future<Either<Unit, FlowyError>> delete({required String viewId}) {
final request = RepeatedViewId.create()..items.add(viewId);
return FolderEventDeleteView(request).send();
}
Future<Either<Unit, FlowyError>> duplicate({required String viewId}) {
final request = ViewId(value: viewId);
return FolderEventDuplicateView(request).send();
}
}

View File

@ -1,4 +1,5 @@
import 'package:app_flowy/workspace/infrastructure/repos/user_repo.dart';
import 'package:app_flowy/user/application/user_listener.dart';
import 'package:app_flowy/user/application/user_service.dart';
import 'package:flowy_sdk/log.dart';
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/workspace.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
@ -9,14 +10,14 @@ import 'package:dartz/dartz.dart';
part 'welcome_bloc.freezed.dart';
class WelcomeBloc extends Bloc<WelcomeEvent, WelcomeState> {
final UserRepo repo;
final UserListener listener;
WelcomeBloc({required this.repo, required this.listener}) : super(WelcomeState.initial()) {
final UserService userService;
final UserListener userListener;
WelcomeBloc({required this.userService, required this.userListener}) : super(WelcomeState.initial()) {
on<WelcomeEvent>(
(event, emit) async {
await event.map(initial: (e) async {
listener.workspaceUpdatedNotifier.addPublishListener(_workspacesUpdated);
listener.start();
userListener.workspaceUpdatedNotifier.addPublishListener(_workspacesUpdated);
userListener.start();
//
await _fetchWorkspaces(emit);
}, openWorkspace: (e) async {
@ -35,12 +36,12 @@ class WelcomeBloc extends Bloc<WelcomeEvent, WelcomeState> {
@override
Future<void> close() async {
await listener.stop();
await userListener.stop();
super.close();
}
Future<void> _fetchWorkspaces(Emitter<WelcomeState> emit) async {
final workspacesOrFailed = await repo.getWorkspaces();
final workspacesOrFailed = await userService.getWorkspaces();
emit(workspacesOrFailed.fold(
(workspaces) => state.copyWith(workspaces: workspaces, successOrFailure: left(unit)),
(error) {
@ -51,7 +52,7 @@ class WelcomeBloc extends Bloc<WelcomeEvent, WelcomeState> {
}
Future<void> _openWorkspace(Workspace workspace, Emitter<WelcomeState> emit) async {
final result = await repo.openWorkspace(workspace.id);
final result = await userService.openWorkspace(workspace.id);
emit(result.fold(
(workspaces) => state.copyWith(successOrFailure: left(unit)),
(error) {
@ -62,7 +63,7 @@ class WelcomeBloc extends Bloc<WelcomeEvent, WelcomeState> {
}
Future<void> _createWorkspace(String name, String desc, Emitter<WelcomeState> emit) async {
final result = await repo.createWorkspace(name, desc);
final result = await userService.createWorkspace(name, desc);
emit(result.fold(
(workspace) {
return state.copyWith(successOrFailure: left(unit));

View File

@ -1,10 +1,9 @@
import 'dart:async';
import 'dart:typed_data';
import 'package:app_flowy/core/helper.dart';
import 'package:dartz/dartz.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_sdk/log.dart';
import 'package:flowy_sdk/dispatch/dispatch.dart';
import 'package:flowy_sdk/protobuf/dart-notify/subject.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-user-data-model/protobuf.dart' show UserProfile;
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/app.pb.dart';
@ -12,56 +11,28 @@ import 'package:flowy_sdk/protobuf/flowy-folder-data-model/workspace.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-folder/dart_notification.pb.dart';
import 'package:flowy_sdk/rust_stream.dart';
import 'package:app_flowy/generated/locale_keys.g.dart';
import 'helper.dart';
class WorkspaceRepo {
UserProfile user;
String workspaceId;
WorkspaceRepo({
required this.user,
required this.workspaceId,
typedef WorkspaceAppsChangedCallback = void Function(Either<List<App>, FlowyError> appsOrFail);
typedef WorkspaceUpdatedCallback = void Function(String name, String desc);
class WorkspaceListener {
WorkspaceListenerService service;
WorkspaceListener({
required this.service,
});
Future<Either<App, FlowyError>> createApp(String name, String desc) {
final request = CreateAppPayload.create()
..name = name
..workspaceId = workspaceId
..desc = desc;
return FolderEventCreateApp(request).send();
void start({WorkspaceAppsChangedCallback? addAppCallback, WorkspaceUpdatedCallback? updatedCallback}) {
service.startListening(appsChanged: addAppCallback, update: updatedCallback);
}
Future<Either<Workspace, FlowyError>> getWorkspace() {
final request = WorkspaceId.create()..value = workspaceId;
return FolderEventReadWorkspaces(request).send().then((result) {
return result.fold(
(workspaces) {
assert(workspaces.items.length == 1);
if (workspaces.items.isEmpty) {
return right(FlowyError.create()..msg = LocaleKeys.workspace_notFoundError.tr());
} else {
return left(workspaces.items[0]);
}
},
(error) => right(error),
);
});
}
Future<Either<List<App>, FlowyError>> getApps() {
final request = WorkspaceId.create()..value = workspaceId;
return FolderEventReadWorkspaceApps(request).send().then((result) {
return result.fold(
(apps) => left(apps.items),
(error) => right(error),
);
});
Future<void> stop() async {
await service.close();
}
}
class WorkspaceListenerRepo {
class WorkspaceListenerService {
StreamSubscription<SubscribeObject>? _subscription;
WorkspaceAppsChangedCallback? _appsChanged;
WorkspaceUpdatedCallback? _update;
@ -69,7 +40,7 @@ class WorkspaceListenerRepo {
final UserProfile user;
final String workspaceId;
WorkspaceListenerRepo({
WorkspaceListenerService({
required this.user,
required this.workspaceId,
});
@ -125,22 +96,3 @@ class WorkspaceListenerRepo {
// _update = null;
}
}
typedef WorkspaceAppsChangedCallback = void Function(Either<List<App>, FlowyError> appsOrFail);
typedef WorkspaceUpdatedCallback = void Function(String name, String desc);
class WorkspaceListener {
WorkspaceListenerRepo repo;
WorkspaceListener({
required this.repo,
});
void start({WorkspaceAppsChangedCallback? addAppCallback, WorkspaceUpdatedCallback? updatedCallback}) {
repo.startListening(appsChanged: addAppCallback, update: updatedCallback);
}
Future<void> stop() async {
await repo.close();
}
}

View File

@ -0,0 +1,46 @@
import 'dart:async';
import 'package:dartz/dartz.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_sdk/dispatch/dispatch.dart';
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/app.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/workspace.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
import 'package:app_flowy/generated/locale_keys.g.dart';
class WorkspaceService {
Future<Either<App, FlowyError>> createApp({required String workspaceId, required String name, required String desc}) {
final request = CreateAppPayload.create()
..name = name
..workspaceId = workspaceId
..desc = desc;
return FolderEventCreateApp(request).send();
}
Future<Either<Workspace, FlowyError>> getWorkspace({required String workspaceId}) {
final request = WorkspaceId.create()..value = workspaceId;
return FolderEventReadWorkspaces(request).send().then((result) {
return result.fold(
(workspaces) {
assert(workspaces.items.length == 1);
if (workspaces.items.isEmpty) {
return right(FlowyError.create()..msg = LocaleKeys.workspace_notFoundError.tr());
} else {
return left(workspaces.items[0]);
}
},
(error) => right(error),
);
});
}
Future<Either<List<App>, FlowyError>> getApps({required String workspaceId}) {
final request = WorkspaceId.create()..value = workspaceId;
return FolderEventReadWorkspaceApps(request).send().then((result) {
return result.fold(
(apps) => left(apps.items),
(error) => right(error),
);
});
}
}

View File

@ -36,12 +36,12 @@ class ViewSectionItem extends StatelessWidget {
final theme = context.watch<AppTheme>();
return MultiBlocProvider(
providers: [
BlocProvider(create: (ctx) => getIt<ViewMenuBloc>(param1: view)..add(const ViewEvent.initial())),
BlocProvider(create: (ctx) => getIt<ViewBloc>(param1: view)..add(const ViewEvent.initial())),
],
child: BlocBuilder<ViewMenuBloc, ViewState>(
child: BlocBuilder<ViewBloc, ViewState>(
builder: (context, state) {
return InkWell(
onTap: () => onSelected(context.read<ViewMenuBloc>().state.view),
onTap: () => onSelected(context.read<ViewBloc>().state.view),
child: FlowyHover(
config: HoverDisplayConfig(hoverColor: theme.bg3),
builder: (_, onHover) => _render(context, onHover, state, theme.iconColor),
@ -63,9 +63,9 @@ class ViewSectionItem extends StatelessWidget {
if (onHover || state.isEditing) {
children.add(
ViewDisclosureButton(
onTap: () => context.read<ViewMenuBloc>().add(const ViewEvent.setIsEditing(true)),
onTap: () => context.read<ViewBloc>().add(const ViewEvent.setIsEditing(true)),
onSelected: (action) {
context.read<ViewMenuBloc>().add(const ViewEvent.setIsEditing(false));
context.read<ViewBloc>().add(const ViewEvent.setIsEditing(false));
_handleAction(context, action);
},
),
@ -87,18 +87,18 @@ class ViewSectionItem extends StatelessWidget {
case ViewDisclosureAction.rename:
TextFieldDialog(
title: LocaleKeys.disclosureAction_rename.tr(),
value: context.read<ViewMenuBloc>().state.view.name,
value: context.read<ViewBloc>().state.view.name,
confirm: (newValue) {
context.read<ViewMenuBloc>().add(ViewEvent.rename(newValue));
context.read<ViewBloc>().add(ViewEvent.rename(newValue));
},
).show(context);
break;
case ViewDisclosureAction.delete:
context.read<ViewMenuBloc>().add(const ViewEvent.delete());
context.read<ViewBloc>().add(const ViewEvent.delete());
break;
case ViewDisclosureAction.duplicate:
context.read<ViewMenuBloc>().add(const ViewEvent.duplicate());
context.read<ViewBloc>().add(const ViewEvent.duplicate());
break;
}
});

View File

@ -10,7 +10,8 @@ import 'package:app_flowy/startup/startup.dart';
import 'package:app_flowy/startup/tasks/load_plugin.dart';
import 'package:app_flowy/workspace/application/appearance.dart';
import 'package:app_flowy/workspace/application/doc/share_bloc.dart';
import 'package:app_flowy/workspace/infrastructure/repos/view_repo.dart';
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/presentation/home/home_stack.dart';
import 'package:app_flowy/workspace/presentation/widgets/dialogs.dart';
import 'package:app_flowy/workspace/presentation/widgets/pop_up_action.dart';
@ -128,11 +129,11 @@ class DocumentLeftBarItem extends StatefulWidget {
class _DocumentLeftBarItemState extends State<DocumentLeftBarItem> {
final _controller = TextEditingController();
final _focusNode = FocusNode();
late ViewRepository repo;
late ViewService service;
@override
void initState() {
repo = ViewRepository(view: widget.view);
service = ViewService(/*view: widget.view*/);
_focusNode.addListener(_handleFocusChanged);
super.initState();
}
@ -179,7 +180,7 @@ class _DocumentLeftBarItemState extends State<DocumentLeftBarItem> {
}
if (_controller.text != widget.view.name) {
repo.updateView(name: _controller.text);
service.updateView(viewId: widget.view.id, name: _controller.text);
}
}
}