[flutter]: open the view automatically after create it

This commit is contained in:
appflowy 2021-10-29 14:43:10 +08:00
parent 17f5a6ac9d
commit 941c99ecd1
11 changed files with 177 additions and 155 deletions

View File

@ -25,10 +25,16 @@ class AppBloc extends Bloc<AppEvent, AppState> {
},
createView: (CreateView value) async* {
final viewOrFailed = await appManager.createView(name: value.name, desc: value.desc, viewType: value.viewType);
yield viewOrFailed.fold((view) => state, (error) {
Log.error(error);
return state.copyWith(successOrFailure: right(error));
});
yield viewOrFailed.fold(
(view) => state.copyWith(
selectedView: view,
successOrFailure: left(unit),
),
(error) {
Log.error(error);
return state.copyWith(successOrFailure: right(error));
},
);
},
didReceiveViews: (e) async* {
yield state.copyWith(views: e.views);
@ -75,12 +81,14 @@ class AppState with _$AppState {
const factory AppState({
required bool isLoading,
required List<View>? views,
View? selectedView,
required Either<Unit, WorkspaceError> successOrFailure,
}) = _AppState;
factory AppState.initial() => AppState(
isLoading: false,
views: null,
selectedView: null,
successOrFailure: left(unit),
);
}

View File

@ -447,10 +447,12 @@ class _$AppStateTearOff {
_AppState call(
{required bool isLoading,
required List<View>? views,
View? selectedView,
required Either<Unit, WorkspaceError> successOrFailure}) {
return _AppState(
isLoading: isLoading,
views: views,
selectedView: selectedView,
successOrFailure: successOrFailure,
);
}
@ -463,6 +465,7 @@ const $AppState = _$AppStateTearOff();
mixin _$AppState {
bool get isLoading => throw _privateConstructorUsedError;
List<View>? get views => throw _privateConstructorUsedError;
View? get selectedView => throw _privateConstructorUsedError;
Either<Unit, WorkspaceError> get successOrFailure =>
throw _privateConstructorUsedError;
@ -478,6 +481,7 @@ abstract class $AppStateCopyWith<$Res> {
$Res call(
{bool isLoading,
List<View>? views,
View? selectedView,
Either<Unit, WorkspaceError> successOrFailure});
}
@ -493,6 +497,7 @@ class _$AppStateCopyWithImpl<$Res> implements $AppStateCopyWith<$Res> {
$Res call({
Object? isLoading = freezed,
Object? views = freezed,
Object? selectedView = freezed,
Object? successOrFailure = freezed,
}) {
return _then(_value.copyWith(
@ -504,6 +509,10 @@ class _$AppStateCopyWithImpl<$Res> implements $AppStateCopyWith<$Res> {
? _value.views
: views // ignore: cast_nullable_to_non_nullable
as List<View>?,
selectedView: selectedView == freezed
? _value.selectedView
: selectedView // ignore: cast_nullable_to_non_nullable
as View?,
successOrFailure: successOrFailure == freezed
? _value.successOrFailure
: successOrFailure // ignore: cast_nullable_to_non_nullable
@ -520,6 +529,7 @@ abstract class _$AppStateCopyWith<$Res> implements $AppStateCopyWith<$Res> {
$Res call(
{bool isLoading,
List<View>? views,
View? selectedView,
Either<Unit, WorkspaceError> successOrFailure});
}
@ -536,6 +546,7 @@ class __$AppStateCopyWithImpl<$Res> extends _$AppStateCopyWithImpl<$Res>
$Res call({
Object? isLoading = freezed,
Object? views = freezed,
Object? selectedView = freezed,
Object? successOrFailure = freezed,
}) {
return _then(_AppState(
@ -547,6 +558,10 @@ class __$AppStateCopyWithImpl<$Res> extends _$AppStateCopyWithImpl<$Res>
? _value.views
: views // ignore: cast_nullable_to_non_nullable
as List<View>?,
selectedView: selectedView == freezed
? _value.selectedView
: selectedView // ignore: cast_nullable_to_non_nullable
as View?,
successOrFailure: successOrFailure == freezed
? _value.successOrFailure
: successOrFailure // ignore: cast_nullable_to_non_nullable
@ -561,6 +576,7 @@ class _$_AppState implements _AppState {
const _$_AppState(
{required this.isLoading,
required this.views,
this.selectedView,
required this.successOrFailure});
@override
@ -568,11 +584,13 @@ class _$_AppState implements _AppState {
@override
final List<View>? views;
@override
final View? selectedView;
@override
final Either<Unit, WorkspaceError> successOrFailure;
@override
String toString() {
return 'AppState(isLoading: $isLoading, views: $views, successOrFailure: $successOrFailure)';
return 'AppState(isLoading: $isLoading, views: $views, selectedView: $selectedView, successOrFailure: $successOrFailure)';
}
@override
@ -584,6 +602,9 @@ class _$_AppState implements _AppState {
.equals(other.isLoading, isLoading)) &&
(identical(other.views, views) ||
const DeepCollectionEquality().equals(other.views, views)) &&
(identical(other.selectedView, selectedView) ||
const DeepCollectionEquality()
.equals(other.selectedView, selectedView)) &&
(identical(other.successOrFailure, successOrFailure) ||
const DeepCollectionEquality()
.equals(other.successOrFailure, successOrFailure)));
@ -594,6 +615,7 @@ class _$_AppState implements _AppState {
runtimeType.hashCode ^
const DeepCollectionEquality().hash(isLoading) ^
const DeepCollectionEquality().hash(views) ^
const DeepCollectionEquality().hash(selectedView) ^
const DeepCollectionEquality().hash(successOrFailure);
@JsonKey(ignore: true)
@ -606,6 +628,7 @@ abstract class _AppState implements AppState {
const factory _AppState(
{required bool isLoading,
required List<View>? views,
View? selectedView,
required Either<Unit, WorkspaceError> successOrFailure}) = _$_AppState;
@override
@ -613,6 +636,8 @@ abstract class _AppState implements AppState {
@override
List<View>? get views => throw _privateConstructorUsedError;
@override
View? get selectedView => throw _privateConstructorUsedError;
@override
Either<Unit, WorkspaceError> get successOrFailure =>
throw _privateConstructorUsedError;
@override

View File

@ -24,7 +24,7 @@ class _$MenuEventTearOff {
return const Collapse();
}
OpenPage openPage(HomeStackContext context) {
OpenPage openPage(HomeStackContext<dynamic> context) {
return OpenPage(
context,
);
@ -53,7 +53,7 @@ mixin _$MenuEvent {
TResult when<TResult extends Object?>({
required TResult Function() initial,
required TResult Function() collapse,
required TResult Function(HomeStackContext context) openPage,
required TResult Function(HomeStackContext<dynamic> context) openPage,
required TResult Function(String name, String? desc) createApp,
required TResult Function(Either<List<App>, WorkspaceError> appsOrFail)
didReceiveApps,
@ -63,7 +63,7 @@ mixin _$MenuEvent {
TResult maybeWhen<TResult extends Object?>({
TResult Function()? initial,
TResult Function()? collapse,
TResult Function(HomeStackContext context)? openPage,
TResult Function(HomeStackContext<dynamic> context)? openPage,
TResult Function(String name, String? desc)? createApp,
TResult Function(Either<List<App>, WorkspaceError> appsOrFail)?
didReceiveApps,
@ -145,7 +145,7 @@ class _$_Initial implements _Initial {
TResult when<TResult extends Object?>({
required TResult Function() initial,
required TResult Function() collapse,
required TResult Function(HomeStackContext context) openPage,
required TResult Function(HomeStackContext<dynamic> context) openPage,
required TResult Function(String name, String? desc) createApp,
required TResult Function(Either<List<App>, WorkspaceError> appsOrFail)
didReceiveApps,
@ -158,7 +158,7 @@ class _$_Initial implements _Initial {
TResult maybeWhen<TResult extends Object?>({
TResult Function()? initial,
TResult Function()? collapse,
TResult Function(HomeStackContext context)? openPage,
TResult Function(HomeStackContext<dynamic> context)? openPage,
TResult Function(String name, String? desc)? createApp,
TResult Function(Either<List<App>, WorkspaceError> appsOrFail)?
didReceiveApps,
@ -242,7 +242,7 @@ class _$Collapse implements Collapse {
TResult when<TResult extends Object?>({
required TResult Function() initial,
required TResult Function() collapse,
required TResult Function(HomeStackContext context) openPage,
required TResult Function(HomeStackContext<dynamic> context) openPage,
required TResult Function(String name, String? desc) createApp,
required TResult Function(Either<List<App>, WorkspaceError> appsOrFail)
didReceiveApps,
@ -255,7 +255,7 @@ class _$Collapse implements Collapse {
TResult maybeWhen<TResult extends Object?>({
TResult Function()? initial,
TResult Function()? collapse,
TResult Function(HomeStackContext context)? openPage,
TResult Function(HomeStackContext<dynamic> context)? openPage,
TResult Function(String name, String? desc)? createApp,
TResult Function(Either<List<App>, WorkspaceError> appsOrFail)?
didReceiveApps,
@ -304,7 +304,7 @@ abstract class Collapse implements MenuEvent {
abstract class $OpenPageCopyWith<$Res> {
factory $OpenPageCopyWith(OpenPage value, $Res Function(OpenPage) then) =
_$OpenPageCopyWithImpl<$Res>;
$Res call({HomeStackContext context});
$Res call({HomeStackContext<dynamic> context});
}
/// @nodoc
@ -324,7 +324,7 @@ class _$OpenPageCopyWithImpl<$Res> extends _$MenuEventCopyWithImpl<$Res>
context == freezed
? _value.context
: context // ignore: cast_nullable_to_non_nullable
as HomeStackContext,
as HomeStackContext<dynamic>,
));
}
}
@ -335,7 +335,7 @@ class _$OpenPage implements OpenPage {
const _$OpenPage(this.context);
@override
final HomeStackContext context;
final HomeStackContext<dynamic> context;
@override
String toString() {
@ -364,7 +364,7 @@ class _$OpenPage implements OpenPage {
TResult when<TResult extends Object?>({
required TResult Function() initial,
required TResult Function() collapse,
required TResult Function(HomeStackContext context) openPage,
required TResult Function(HomeStackContext<dynamic> context) openPage,
required TResult Function(String name, String? desc) createApp,
required TResult Function(Either<List<App>, WorkspaceError> appsOrFail)
didReceiveApps,
@ -377,7 +377,7 @@ class _$OpenPage implements OpenPage {
TResult maybeWhen<TResult extends Object?>({
TResult Function()? initial,
TResult Function()? collapse,
TResult Function(HomeStackContext context)? openPage,
TResult Function(HomeStackContext<dynamic> context)? openPage,
TResult Function(String name, String? desc)? createApp,
TResult Function(Either<List<App>, WorkspaceError> appsOrFail)?
didReceiveApps,
@ -419,9 +419,9 @@ class _$OpenPage implements OpenPage {
}
abstract class OpenPage implements MenuEvent {
const factory OpenPage(HomeStackContext context) = _$OpenPage;
const factory OpenPage(HomeStackContext<dynamic> context) = _$OpenPage;
HomeStackContext get context => throw _privateConstructorUsedError;
HomeStackContext<dynamic> get context => throw _privateConstructorUsedError;
@JsonKey(ignore: true)
$OpenPageCopyWith<OpenPage> get copyWith =>
throw _privateConstructorUsedError;
@ -502,7 +502,7 @@ class _$CreateApp implements CreateApp {
TResult when<TResult extends Object?>({
required TResult Function() initial,
required TResult Function() collapse,
required TResult Function(HomeStackContext context) openPage,
required TResult Function(HomeStackContext<dynamic> context) openPage,
required TResult Function(String name, String? desc) createApp,
required TResult Function(Either<List<App>, WorkspaceError> appsOrFail)
didReceiveApps,
@ -515,7 +515,7 @@ class _$CreateApp implements CreateApp {
TResult maybeWhen<TResult extends Object?>({
TResult Function()? initial,
TResult Function()? collapse,
TResult Function(HomeStackContext context)? openPage,
TResult Function(HomeStackContext<dynamic> context)? openPage,
TResult Function(String name, String? desc)? createApp,
TResult Function(Either<List<App>, WorkspaceError> appsOrFail)?
didReceiveApps,
@ -633,7 +633,7 @@ class _$ReceiveApps implements ReceiveApps {
TResult when<TResult extends Object?>({
required TResult Function() initial,
required TResult Function() collapse,
required TResult Function(HomeStackContext context) openPage,
required TResult Function(HomeStackContext<dynamic> context) openPage,
required TResult Function(String name, String? desc) createApp,
required TResult Function(Either<List<App>, WorkspaceError> appsOrFail)
didReceiveApps,
@ -646,7 +646,7 @@ class _$ReceiveApps implements ReceiveApps {
TResult maybeWhen<TResult extends Object?>({
TResult Function()? initial,
TResult Function()? collapse,
TResult Function(HomeStackContext context)? openPage,
TResult Function(HomeStackContext<dynamic> context)? openPage,
TResult Function(String name, String? desc)? createApp,
TResult Function(Either<List<App>, WorkspaceError> appsOrFail)?
didReceiveApps,
@ -706,7 +706,7 @@ class _$MenuStateTearOff {
{required bool isCollapse,
required Option<List<App>> apps,
required Either<Unit, WorkspaceError> successOrFailure,
required HomeStackContext context}) {
required HomeStackContext<dynamic> context}) {
return _MenuState(
isCollapse: isCollapse,
apps: apps,
@ -725,7 +725,7 @@ mixin _$MenuState {
Option<List<App>> get apps => throw _privateConstructorUsedError;
Either<Unit, WorkspaceError> get successOrFailure =>
throw _privateConstructorUsedError;
HomeStackContext get context => throw _privateConstructorUsedError;
HomeStackContext<dynamic> get context => throw _privateConstructorUsedError;
@JsonKey(ignore: true)
$MenuStateCopyWith<MenuState> get copyWith =>
@ -740,7 +740,7 @@ abstract class $MenuStateCopyWith<$Res> {
{bool isCollapse,
Option<List<App>> apps,
Either<Unit, WorkspaceError> successOrFailure,
HomeStackContext context});
HomeStackContext<dynamic> context});
}
/// @nodoc
@ -774,7 +774,7 @@ class _$MenuStateCopyWithImpl<$Res> implements $MenuStateCopyWith<$Res> {
context: context == freezed
? _value.context
: context // ignore: cast_nullable_to_non_nullable
as HomeStackContext,
as HomeStackContext<dynamic>,
));
}
}
@ -789,7 +789,7 @@ abstract class _$MenuStateCopyWith<$Res> implements $MenuStateCopyWith<$Res> {
{bool isCollapse,
Option<List<App>> apps,
Either<Unit, WorkspaceError> successOrFailure,
HomeStackContext context});
HomeStackContext<dynamic> context});
}
/// @nodoc
@ -824,7 +824,7 @@ class __$MenuStateCopyWithImpl<$Res> extends _$MenuStateCopyWithImpl<$Res>
context: context == freezed
? _value.context
: context // ignore: cast_nullable_to_non_nullable
as HomeStackContext,
as HomeStackContext<dynamic>,
));
}
}
@ -845,7 +845,7 @@ class _$_MenuState implements _MenuState {
@override
final Either<Unit, WorkspaceError> successOrFailure;
@override
final HomeStackContext context;
final HomeStackContext<dynamic> context;
@override
String toString() {
@ -887,7 +887,7 @@ abstract class _MenuState implements MenuState {
{required bool isCollapse,
required Option<List<App>> apps,
required Either<Unit, WorkspaceError> successOrFailure,
required HomeStackContext context}) = _$_MenuState;
required HomeStackContext<dynamic> context}) = _$_MenuState;
@override
bool get isCollapse => throw _privateConstructorUsedError;
@ -897,7 +897,7 @@ abstract class _MenuState implements MenuState {
Either<Unit, WorkspaceError> get successOrFailure =>
throw _privateConstructorUsedError;
@override
HomeStackContext get context => throw _privateConstructorUsedError;
HomeStackContext<dynamic> get context => throw _privateConstructorUsedError;
@override
@JsonKey(ignore: true)
_$MenuStateCopyWith<_MenuState> get copyWith =>

View File

@ -1,4 +1,3 @@
import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:app_flowy/startup/startup.dart';

View File

@ -5,5 +5,6 @@ class TrashSizes {
static double get lashModifyWidth => 230 * scale;
static double get createTimeWidth => 230 * scale;
static double get padding => 100 * scale;
static double get totalWidth => TrashSizes.fileNameWidth + TrashSizes.lashModifyWidth + TrashSizes.createTimeWidth;
static double get totalWidth =>
TrashSizes.fileNameWidth + TrashSizes.lashModifyWidth + TrashSizes.createTimeWidth + TrashSizes.padding;
}

View File

@ -54,7 +54,7 @@ class _CreateTextFieldDialog extends State<TextFieldDialog> {
],
FlowyFormTextInput(
hintText: widget.value,
textStyle: const TextStyle(fontSize: 28, fontWeight: FontWeight.w400),
textStyle: const TextStyle(fontSize: 24, fontWeight: FontWeight.w400),
autoFocus: true,
onChanged: (text) {
newValue = text;

View File

@ -2,7 +2,6 @@ import 'package:app_flowy/workspace/presentation/widgets/menu/widget/top_bar.dar
import 'package:dartz/dartz.dart';
import 'package:flowy_infra/size.dart';
import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart';
import 'package:flowy_infra_ui/widget/error_page.dart';
import 'package:flowy_infra_ui/widget/spacing.dart';
import 'package:flowy_sdk/protobuf/flowy-user/user_profile.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-workspace/app_create.pb.dart';

View File

@ -3,19 +3,10 @@ import 'package:app_flowy/workspace/presentation/widgets/dialogs.dart';
import 'package:flowy_infra/image.dart';
import 'package:flowy_infra/size.dart';
import 'package:flowy_infra_ui/style_widget/button.dart';
import 'package:flowy_infra_ui/style_widget/text.dart';
import 'package:flutter/material.dart';
import 'package:styled_widget/styled_widget.dart';
import 'package:flowy_infra_ui/widget/dialog/styled_dialogs.dart';
import 'package:flowy_infra_ui/style_widget/extension.dart';
import 'package:app_flowy/startup/tasks/application_task.dart';
import 'package:flowy_infra/text_style.dart';
import 'package:flowy_infra/theme.dart';
import 'package:flowy_infra_ui/style_widget/text_input.dart';
import 'package:flowy_infra_ui/widget/spacing.dart';
// ignore: implementation_imports
import 'package:provider/src/provider.dart';
import 'package:textstyle_extensions/textstyle_extensions.dart';
class NewAppButton extends StatelessWidget {
final Function(String)? press;
@ -41,64 +32,14 @@ class NewAppButton extends StatelessWidget {
}
Future<void> _showCreateAppDialog(BuildContext context) async {
await CreateAppDialog(
confirm: (appName) {
if (appName.isNotEmpty && press != null) {
press!(appName);
return TextFieldDialog(
title: 'New App',
value: "",
confirm: (newValue) {
if (newValue.isNotEmpty && press != null) {
press!(newValue);
}
},
).show(context);
}
}
class CreateAppDialog extends StatefulWidget {
final void Function()? cancel;
final void Function(String) confirm;
const CreateAppDialog({required this.confirm, this.cancel, Key? key}) : super(key: key);
@override
State<CreateAppDialog> createState() => _CreateAppDialogState();
}
class _CreateAppDialogState extends State<CreateAppDialog> {
String appName = "";
@override
Widget build(BuildContext context) {
final theme = context.watch<AppTheme>();
return StyledDialog(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
...[
Text('Create App'.toUpperCase(), style: TextStyles.T1.textColor(theme.shader4)),
VSpace(Insets.sm * 1.5),
// Container(color: theme.greyWeak.withOpacity(.35), height: 1),
VSpace(Insets.m * 1.5),
],
FlowyFormTextInput(
hintText: "App name",
onChanged: (text) {
appName = text;
},
),
SizedBox(height: Insets.l),
SizedBox(
height: 40,
child: OkCancelButton(
onOkPressed: () {
widget.confirm(appName);
},
onCancelPressed: () {
if (widget.cancel != null) {
widget.cancel!();
}
},
),
)
],
),
);
}
}

View File

@ -1,6 +1,7 @@
import 'package:app_flowy/workspace/presentation/widgets/menu/widget/app/header.dart';
import 'package:expandable/expandable.dart';
import 'package:flowy_sdk/protobuf/flowy-workspace/app_create.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-workspace/view_create.pb.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:app_flowy/startup/startup.dart';
@ -9,23 +10,6 @@ import 'package:app_flowy/workspace/presentation/widgets/menu/menu.dart';
import 'package:provider/provider.dart';
import 'package:styled_widget/styled_widget.dart';
import 'section/section.dart';
class MenuAppSizes {
static double expandedIconSize = 16;
static double expandedIconPadding = 6;
static double scale = 1;
static double get expandedPadding => expandedIconSize * scale + expandedIconPadding;
}
class MenuAppContext {
final App app;
final viewList = ViewListNotifier();
MenuAppContext(this.app);
Key valueKey() => ValueKey("${app.id}${app.version}");
}
// [[diagram: MenuApp]]
//
// AppBloc
@ -61,18 +45,25 @@ class MenuApp extends MenuItem {
Widget build(BuildContext context) {
return MultiBlocProvider(
providers: [
BlocProvider<AppBloc>(create: (context) {
final appBloc = getIt<AppBloc>(param1: appCtx.app.id);
appBloc.add(const AppEvent.initial());
return appBloc;
}),
BlocProvider<AppBloc>(
create: (context) {
final appBloc = getIt<AppBloc>(param1: appCtx.app.id);
appBloc.add(const AppEvent.initial());
return appBloc;
},
),
],
child: BlocBuilder<AppBloc, AppState>(
builder: (context, state) {
appCtx.viewList.items = state.views ?? List.empty(growable: false);
final child = _renderViewSection(appCtx.viewList);
return expandableWrapper(context, child);
},
child: BlocListener<AppBloc, AppState>(
listenWhen: (p, c) => p.selectedView != c.selectedView,
listener: (context, state) => appCtx.viewList.selectView = state.selectedView,
child: BlocBuilder<AppBloc, AppState>(
buildWhen: (p, c) => p.views != c.views,
builder: (context, state) {
appCtx.viewList.views = state.views;
final child = _renderViewSection(appCtx.viewList);
return expandableWrapper(context, child);
},
),
),
);
}
@ -109,7 +100,7 @@ class MenuApp extends MenuItem {
ChangeNotifierProvider.value(value: viewListNotifier),
],
child: Consumer(builder: (context, ViewListNotifier notifier, child) {
return ViewSection(notifier.items).padding(vertical: 8);
return const ViewSection().padding(vertical: 8);
}),
);
}
@ -117,3 +108,39 @@ class MenuApp extends MenuItem {
@override
MenuItemType get type => MenuItemType.app;
}
class MenuAppSizes {
static double expandedIconSize = 16;
static double expandedIconPadding = 6;
static double scale = 1;
static double get expandedPadding => expandedIconSize * scale + expandedIconPadding;
}
class ViewListNotifier extends ChangeNotifier {
List<View> _views = [];
View? _selectedView;
ViewListNotifier();
set views(List<View>? items) {
_views = items ?? List.empty(growable: false);
notifyListeners();
}
set selectView(View? view) {
_selectedView = view;
notifyListeners();
}
get selectedView => _selectedView;
List<View> get views => _views;
}
class MenuAppContext {
final App app;
final viewList = ViewListNotifier();
MenuAppContext(this.app);
Key valueKey() => ValueKey("${app.id}${app.version}");
}

View File

@ -45,10 +45,7 @@ class ViewSectionItem extends StatelessWidget {
child: BlocBuilder<ViewBloc, ViewState>(
builder: (context, state) {
return InkWell(
onTap: () {
onSelected(context.read<ViewBloc>().state.view);
getIt<HomeStackManager>().setStack(state.view.stackContext());
},
onTap: () => onSelected(context.read<ViewBloc>().state.view),
child: FlowyHover(
config: HoverDisplayConfig(hoverColor: theme.bg3),
builder: (_, onHover) => _render(context, onHover, state),

View File

@ -1,3 +1,7 @@
import 'package:app_flowy/startup/startup.dart';
import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart';
import 'package:app_flowy/workspace/domain/view_ext.dart';
import 'package:app_flowy/workspace/presentation/widgets/menu/widget/app/menu_app.dart';
import 'package:flowy_sdk/protobuf/flowy-workspace/view_create.pb.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
@ -5,50 +9,69 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:provider/provider.dart';
import 'package:styled_widget/styled_widget.dart';
import 'item.dart';
class ViewListNotifier extends ChangeNotifier {
List<View>? views;
ViewListNotifier();
set items(List<View> items) {
views = items;
notifyListeners();
}
List<View> get items => views ?? [];
}
import 'package:async/async.dart';
class ViewSectionNotifier with ChangeNotifier {
List<View> innerViews;
View? _selectedView;
CancelableOperation? _notifyListenerOperation;
ViewSectionNotifier(this.innerViews);
set views(List<View> views) => innerViews = views;
List<View> get views => innerViews;
set setViews(List<View> views) {
if (innerViews != views) {
innerViews = views;
_notifyListeners();
}
}
void setSelectedView(View view) {
_selectedView = view;
notifyListeners();
set selectView(View? view) {
if (_selectedView == view) {
return;
}
if (view != null) {
_selectedView = view;
WidgetsBinding.instance?.addPostFrameCallback((_) {
getIt<HomeStackManager>().setStack(view.stackContext());
});
_notifyListeners();
} else {
// WidgetsBinding.instance?.addPostFrameCallback((_) {
// getIt<HomeStackManager>().setStack(BlankStackContext());
// });
}
}
View? get selectedView => _selectedView;
void update(ViewListNotifier notifier) {
innerViews = notifier.items;
notifyListeners();
setViews = notifier.views;
selectView = notifier.selectedView;
}
void _notifyListeners() {
_notifyListenerOperation?.cancel();
_notifyListenerOperation = CancelableOperation.fromFuture(
Future.delayed(const Duration(milliseconds: 30), () {}),
).then((_) {
notifyListeners();
});
}
}
class ViewSection extends StatelessWidget {
final List<View> views;
const ViewSection(this.views, {Key? key}) : super(key: key);
const ViewSection({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
// The ViewListNotifier will be updated after ViewListData changed passed by parent widget
return ChangeNotifierProxyProvider<ViewListNotifier, ViewSectionNotifier>(
create: (_) {
final views = Provider.of<ViewListNotifier>(context, listen: false).items;
final views = Provider.of<ViewListNotifier>(context, listen: false).views;
return ViewSectionNotifier(views);
},
update: (_, notifier, controller) => controller!..update(notifier),
@ -63,7 +86,9 @@ class ViewSection extends StatelessWidget {
(view) => ViewSectionItem(
view: view,
isSelected: _isViewSelected(context, view.id),
onSelected: (view) => context.read<ViewSectionNotifier>().setSelectedView(view),
onSelected: (view) {
context.read<ViewSectionNotifier>().selectView = view;
},
).padding(vertical: 4),
);