123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245 |
- import 'dart:convert';
- import 'package:appflowy/core/config/kv.dart';
- import 'package:appflowy/core/config/kv_keys.dart';
- import 'package:appflowy/startup/startup.dart';
- import 'package:appflowy/workspace/application/view/view_listener.dart';
- import 'package:appflowy/workspace/application/view/view_service.dart';
- import 'package:dartz/dartz.dart';
- import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
- import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
- import 'package:flutter_bloc/flutter_bloc.dart';
- import 'package:freezed_annotation/freezed_annotation.dart';
- part 'view_bloc.freezed.dart';
- class ViewBloc extends Bloc<ViewEvent, ViewState> {
- final ViewBackendService viewBackendSvc;
- final ViewListener listener;
- final ViewPB view;
- ViewBloc({
- required this.view,
- }) : viewBackendSvc = ViewBackendService(),
- listener = ViewListener(viewId: view.id),
- 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 ViewBackendService.getView(
- result.parentViewId,
- );
- view.fold(
- (view) => add(ViewEvent.viewDidUpdate(left(view))),
- (error) => add(ViewEvent.viewDidUpdate(right(error))),
- );
- },
- );
- final isExpanded = await _getViewIsExpanded(view);
- await _loadViewsWhenExpanded(emit, isExpanded);
- },
- setIsEditing: (e) {
- emit(state.copyWith(isEditing: e.isEditing));
- },
- setIsExpanded: (e) async {
- if (e.isExpanded) {
- await _loadViewsWhenExpanded(emit, true);
- } else {
- emit(state.copyWith(isExpanded: e.isExpanded));
- }
- await _setViewIsExpanded(view, e.isExpanded);
- },
- viewDidUpdate: (e) {
- e.result.fold(
- (view) => emit(
- state.copyWith(
- view: view,
- childViews: view.childViews,
- 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) => state.copyWith(successOrFailure: left(unit)),
- (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)),
- ),
- );
- },
- 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)),
- ),
- );
- },
- );
- });
- }
- @override
- Future<void> close() async {
- await listener.stop();
- return super.close();
- }
- Future<void> _loadViewsWhenExpanded(
- Emitter<ViewState> emit,
- bool isExpanded,
- ) async {
- if (!isExpanded) {
- return;
- }
- if (state.childViews.isNotEmpty) {
- // notify the old child views
- emit(
- state.copyWith(
- childViews: state.childViews,
- isExpanded: true,
- ),
- );
- }
- final viewsOrFailed =
- await ViewBackendService.getChildViews(viewId: state.view.id);
- viewsOrFailed.fold(
- (childViews) => emit(
- state.copyWith(
- childViews: childViews,
- isExpanded: true,
- ),
- ),
- (error) => emit(
- state.copyWith(
- successOrFailure: right(error),
- isExpanded: true,
- ),
- ),
- );
- }
- Future<void> _setViewIsExpanded(ViewPB view, bool isExpanded) async {
- final result = await getIt<KeyValueStorage>().get(KVKeys.expandedViews);
- final map = result.fold(
- (l) => {},
- (r) => jsonDecode(r),
- );
- if (isExpanded) {
- map[view.id] = true;
- } else {
- map.remove(view.id);
- }
- await getIt<KeyValueStorage>().set(KVKeys.expandedViews, jsonEncode(map));
- }
- Future<bool> _getViewIsExpanded(ViewPB view) {
- return getIt<KeyValueStorage>().get(KVKeys.expandedViews).then((result) {
- return result.fold((l) => false, (r) {
- final map = jsonDecode(r);
- return map[view.id] ?? false;
- });
- });
- }
- }
- @freezed
- class ViewEvent with _$ViewEvent {
- const factory ViewEvent.initial() = Initial;
- const factory ViewEvent.setIsEditing(bool isEditing) = SetEditing;
- const factory ViewEvent.setIsExpanded(bool isExpanded) = SetIsExpanded;
- const factory ViewEvent.rename(String newName) = Rename;
- const factory ViewEvent.delete() = Delete;
- const factory ViewEvent.duplicate() = Duplicate;
- const factory ViewEvent.move(
- ViewPB from,
- String newParentId,
- String? prevId,
- ) = Move;
- const factory ViewEvent.createView(
- String name,
- ViewLayoutPB layoutType, {
- /// open the view after created
- @Default(true) bool openAfterCreated,
- }) = CreateView;
- const factory ViewEvent.viewDidUpdate(Either<ViewPB, FlowyError> result) =
- ViewDidUpdate;
- }
- @freezed
- class ViewState with _$ViewState {
- const factory ViewState({
- required ViewPB view,
- required List<ViewPB> childViews,
- required bool isEditing,
- required bool isExpanded,
- required Either<Unit, FlowyError> successOrFailure,
- @Default(null) ViewPB? lastCreatedView,
- }) = _ViewState;
- factory ViewState.init(ViewPB view) => ViewState(
- view: view,
- childViews: view.childViews,
- isExpanded: false,
- isEditing: false,
- successOrFailure: left(unit),
- lastCreatedView: null,
- );
- }
|