mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
[flutter]: customize home topbar action widget
This commit is contained in:
parent
05f9f7b4a1
commit
b1668bfe6c
@ -24,7 +24,7 @@ class _$MenuEventTearOff {
|
||||
return const Collapse();
|
||||
}
|
||||
|
||||
OpenPage openPage(HomeStackContext<dynamic> context) {
|
||||
OpenPage openPage(HomeStackContext<dynamic, dynamic> context) {
|
||||
return OpenPage(
|
||||
context,
|
||||
);
|
||||
@ -53,7 +53,8 @@ mixin _$MenuEvent {
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function() initial,
|
||||
required TResult Function() collapse,
|
||||
required TResult Function(HomeStackContext<dynamic> context) openPage,
|
||||
required TResult Function(HomeStackContext<dynamic, dynamic> context)
|
||||
openPage,
|
||||
required TResult Function(String name, String? desc) createApp,
|
||||
required TResult Function(Either<List<App>, WorkspaceError> appsOrFail)
|
||||
didReceiveApps,
|
||||
@ -63,7 +64,7 @@ mixin _$MenuEvent {
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function()? initial,
|
||||
TResult Function()? collapse,
|
||||
TResult Function(HomeStackContext<dynamic> context)? openPage,
|
||||
TResult Function(HomeStackContext<dynamic, dynamic> context)? openPage,
|
||||
TResult Function(String name, String? desc)? createApp,
|
||||
TResult Function(Either<List<App>, WorkspaceError> appsOrFail)?
|
||||
didReceiveApps,
|
||||
@ -145,7 +146,8 @@ class _$_Initial implements _Initial {
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function() initial,
|
||||
required TResult Function() collapse,
|
||||
required TResult Function(HomeStackContext<dynamic> context) openPage,
|
||||
required TResult Function(HomeStackContext<dynamic, dynamic> context)
|
||||
openPage,
|
||||
required TResult Function(String name, String? desc) createApp,
|
||||
required TResult Function(Either<List<App>, WorkspaceError> appsOrFail)
|
||||
didReceiveApps,
|
||||
@ -158,7 +160,7 @@ class _$_Initial implements _Initial {
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function()? initial,
|
||||
TResult Function()? collapse,
|
||||
TResult Function(HomeStackContext<dynamic> context)? openPage,
|
||||
TResult Function(HomeStackContext<dynamic, dynamic> context)? openPage,
|
||||
TResult Function(String name, String? desc)? createApp,
|
||||
TResult Function(Either<List<App>, WorkspaceError> appsOrFail)?
|
||||
didReceiveApps,
|
||||
@ -242,7 +244,8 @@ class _$Collapse implements Collapse {
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function() initial,
|
||||
required TResult Function() collapse,
|
||||
required TResult Function(HomeStackContext<dynamic> context) openPage,
|
||||
required TResult Function(HomeStackContext<dynamic, dynamic> context)
|
||||
openPage,
|
||||
required TResult Function(String name, String? desc) createApp,
|
||||
required TResult Function(Either<List<App>, WorkspaceError> appsOrFail)
|
||||
didReceiveApps,
|
||||
@ -255,7 +258,7 @@ class _$Collapse implements Collapse {
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function()? initial,
|
||||
TResult Function()? collapse,
|
||||
TResult Function(HomeStackContext<dynamic> context)? openPage,
|
||||
TResult Function(HomeStackContext<dynamic, dynamic> context)? openPage,
|
||||
TResult Function(String name, String? desc)? createApp,
|
||||
TResult Function(Either<List<App>, WorkspaceError> appsOrFail)?
|
||||
didReceiveApps,
|
||||
@ -304,7 +307,7 @@ abstract class Collapse implements MenuEvent {
|
||||
abstract class $OpenPageCopyWith<$Res> {
|
||||
factory $OpenPageCopyWith(OpenPage value, $Res Function(OpenPage) then) =
|
||||
_$OpenPageCopyWithImpl<$Res>;
|
||||
$Res call({HomeStackContext<dynamic> context});
|
||||
$Res call({HomeStackContext<dynamic, dynamic> context});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@ -324,7 +327,7 @@ class _$OpenPageCopyWithImpl<$Res> extends _$MenuEventCopyWithImpl<$Res>
|
||||
context == freezed
|
||||
? _value.context
|
||||
: context // ignore: cast_nullable_to_non_nullable
|
||||
as HomeStackContext<dynamic>,
|
||||
as HomeStackContext<dynamic, dynamic>,
|
||||
));
|
||||
}
|
||||
}
|
||||
@ -335,7 +338,7 @@ class _$OpenPage implements OpenPage {
|
||||
const _$OpenPage(this.context);
|
||||
|
||||
@override
|
||||
final HomeStackContext<dynamic> context;
|
||||
final HomeStackContext<dynamic, dynamic> context;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
@ -364,7 +367,8 @@ class _$OpenPage implements OpenPage {
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function() initial,
|
||||
required TResult Function() collapse,
|
||||
required TResult Function(HomeStackContext<dynamic> context) openPage,
|
||||
required TResult Function(HomeStackContext<dynamic, dynamic> context)
|
||||
openPage,
|
||||
required TResult Function(String name, String? desc) createApp,
|
||||
required TResult Function(Either<List<App>, WorkspaceError> appsOrFail)
|
||||
didReceiveApps,
|
||||
@ -377,7 +381,7 @@ class _$OpenPage implements OpenPage {
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function()? initial,
|
||||
TResult Function()? collapse,
|
||||
TResult Function(HomeStackContext<dynamic> context)? openPage,
|
||||
TResult Function(HomeStackContext<dynamic, dynamic> context)? openPage,
|
||||
TResult Function(String name, String? desc)? createApp,
|
||||
TResult Function(Either<List<App>, WorkspaceError> appsOrFail)?
|
||||
didReceiveApps,
|
||||
@ -419,9 +423,11 @@ class _$OpenPage implements OpenPage {
|
||||
}
|
||||
|
||||
abstract class OpenPage implements MenuEvent {
|
||||
const factory OpenPage(HomeStackContext<dynamic> context) = _$OpenPage;
|
||||
const factory OpenPage(HomeStackContext<dynamic, dynamic> context) =
|
||||
_$OpenPage;
|
||||
|
||||
HomeStackContext<dynamic> get context => throw _privateConstructorUsedError;
|
||||
HomeStackContext<dynamic, dynamic> get context =>
|
||||
throw _privateConstructorUsedError;
|
||||
@JsonKey(ignore: true)
|
||||
$OpenPageCopyWith<OpenPage> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
@ -502,7 +508,8 @@ class _$CreateApp implements CreateApp {
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function() initial,
|
||||
required TResult Function() collapse,
|
||||
required TResult Function(HomeStackContext<dynamic> context) openPage,
|
||||
required TResult Function(HomeStackContext<dynamic, dynamic> context)
|
||||
openPage,
|
||||
required TResult Function(String name, String? desc) createApp,
|
||||
required TResult Function(Either<List<App>, WorkspaceError> appsOrFail)
|
||||
didReceiveApps,
|
||||
@ -515,7 +522,7 @@ class _$CreateApp implements CreateApp {
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function()? initial,
|
||||
TResult Function()? collapse,
|
||||
TResult Function(HomeStackContext<dynamic> context)? openPage,
|
||||
TResult Function(HomeStackContext<dynamic, dynamic> context)? openPage,
|
||||
TResult Function(String name, String? desc)? createApp,
|
||||
TResult Function(Either<List<App>, WorkspaceError> appsOrFail)?
|
||||
didReceiveApps,
|
||||
@ -633,7 +640,8 @@ class _$ReceiveApps implements ReceiveApps {
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function() initial,
|
||||
required TResult Function() collapse,
|
||||
required TResult Function(HomeStackContext<dynamic> context) openPage,
|
||||
required TResult Function(HomeStackContext<dynamic, dynamic> context)
|
||||
openPage,
|
||||
required TResult Function(String name, String? desc) createApp,
|
||||
required TResult Function(Either<List<App>, WorkspaceError> appsOrFail)
|
||||
didReceiveApps,
|
||||
@ -646,7 +654,7 @@ class _$ReceiveApps implements ReceiveApps {
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function()? initial,
|
||||
TResult Function()? collapse,
|
||||
TResult Function(HomeStackContext<dynamic> context)? openPage,
|
||||
TResult Function(HomeStackContext<dynamic, dynamic> context)? openPage,
|
||||
TResult Function(String name, String? desc)? createApp,
|
||||
TResult Function(Either<List<App>, WorkspaceError> appsOrFail)?
|
||||
didReceiveApps,
|
||||
@ -706,7 +714,7 @@ class _$MenuStateTearOff {
|
||||
{required bool isCollapse,
|
||||
required Option<List<App>> apps,
|
||||
required Either<Unit, WorkspaceError> successOrFailure,
|
||||
required HomeStackContext<dynamic> context}) {
|
||||
required HomeStackContext<dynamic, dynamic> context}) {
|
||||
return _MenuState(
|
||||
isCollapse: isCollapse,
|
||||
apps: apps,
|
||||
@ -725,7 +733,8 @@ mixin _$MenuState {
|
||||
Option<List<App>> get apps => throw _privateConstructorUsedError;
|
||||
Either<Unit, WorkspaceError> get successOrFailure =>
|
||||
throw _privateConstructorUsedError;
|
||||
HomeStackContext<dynamic> get context => throw _privateConstructorUsedError;
|
||||
HomeStackContext<dynamic, dynamic> get context =>
|
||||
throw _privateConstructorUsedError;
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
$MenuStateCopyWith<MenuState> get copyWith =>
|
||||
@ -740,7 +749,7 @@ abstract class $MenuStateCopyWith<$Res> {
|
||||
{bool isCollapse,
|
||||
Option<List<App>> apps,
|
||||
Either<Unit, WorkspaceError> successOrFailure,
|
||||
HomeStackContext<dynamic> context});
|
||||
HomeStackContext<dynamic, dynamic> context});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@ -774,7 +783,7 @@ class _$MenuStateCopyWithImpl<$Res> implements $MenuStateCopyWith<$Res> {
|
||||
context: context == freezed
|
||||
? _value.context
|
||||
: context // ignore: cast_nullable_to_non_nullable
|
||||
as HomeStackContext<dynamic>,
|
||||
as HomeStackContext<dynamic, dynamic>,
|
||||
));
|
||||
}
|
||||
}
|
||||
@ -789,7 +798,7 @@ abstract class _$MenuStateCopyWith<$Res> implements $MenuStateCopyWith<$Res> {
|
||||
{bool isCollapse,
|
||||
Option<List<App>> apps,
|
||||
Either<Unit, WorkspaceError> successOrFailure,
|
||||
HomeStackContext<dynamic> context});
|
||||
HomeStackContext<dynamic, dynamic> context});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@ -824,7 +833,7 @@ class __$MenuStateCopyWithImpl<$Res> extends _$MenuStateCopyWithImpl<$Res>
|
||||
context: context == freezed
|
||||
? _value.context
|
||||
: context // ignore: cast_nullable_to_non_nullable
|
||||
as HomeStackContext<dynamic>,
|
||||
as HomeStackContext<dynamic, dynamic>,
|
||||
));
|
||||
}
|
||||
}
|
||||
@ -845,7 +854,7 @@ class _$_MenuState implements _MenuState {
|
||||
@override
|
||||
final Either<Unit, WorkspaceError> successOrFailure;
|
||||
@override
|
||||
final HomeStackContext<dynamic> context;
|
||||
final HomeStackContext<dynamic, dynamic> context;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
@ -887,7 +896,7 @@ abstract class _MenuState implements MenuState {
|
||||
{required bool isCollapse,
|
||||
required Option<List<App>> apps,
|
||||
required Either<Unit, WorkspaceError> successOrFailure,
|
||||
required HomeStackContext<dynamic> context}) = _$_MenuState;
|
||||
required HomeStackContext<dynamic, dynamic> context}) = _$_MenuState;
|
||||
|
||||
@override
|
||||
bool get isCollapse => throw _privateConstructorUsedError;
|
||||
@ -897,7 +906,8 @@ abstract class _MenuState implements MenuState {
|
||||
Either<Unit, WorkspaceError> get successOrFailure =>
|
||||
throw _privateConstructorUsedError;
|
||||
@override
|
||||
HomeStackContext<dynamic> get context => throw _privateConstructorUsedError;
|
||||
HomeStackContext<dynamic, dynamic> get context =>
|
||||
throw _privateConstructorUsedError;
|
||||
@override
|
||||
@JsonKey(ignore: true)
|
||||
_$MenuStateCopyWith<_MenuState> get copyWith =>
|
||||
|
@ -25,12 +25,14 @@ enum HomeStackType {
|
||||
|
||||
List<HomeStackType> pages = HomeStackType.values.toList();
|
||||
|
||||
abstract class HomeStackContext<T> with NavigationItem {
|
||||
abstract class HomeStackContext<T, S> with NavigationItem {
|
||||
List<NavigationItem> get navigationItems;
|
||||
|
||||
@override
|
||||
Widget get naviTitle;
|
||||
|
||||
Widget? Function(BuildContext context) get buildNavigationActions;
|
||||
|
||||
@override
|
||||
String get identifier;
|
||||
|
||||
|
@ -11,6 +11,9 @@ class BlankStackContext extends HomeStackContext {
|
||||
@override
|
||||
Widget get naviTitle => const FlowyText.medium('Blank page', fontSize: 12);
|
||||
|
||||
@override
|
||||
Widget? Function(BuildContext context) get buildNavigationActions => (_) => null;
|
||||
|
||||
@override
|
||||
HomeStackType get type => HomeStackType.blank;
|
||||
|
||||
|
@ -2,13 +2,18 @@ import 'package:app_flowy/startup/startup.dart';
|
||||
import 'package:app_flowy/workspace/domain/i_view.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/pop_up_action.dart';
|
||||
import 'package:flowy_infra/size.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/text.dart';
|
||||
import 'package:flowy_infra_ui/widget/rounded_button.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_create.pb.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:dartz/dartz.dart' as dartz;
|
||||
|
||||
import 'doc_page.dart';
|
||||
|
||||
class DocStackContext extends HomeStackContext {
|
||||
class DocStackContext extends HomeStackContext<String, ShareActionWrapper> {
|
||||
View _view;
|
||||
late IViewListener _listener;
|
||||
final ValueNotifier<String> _isUpdated = ValueNotifier<String>("");
|
||||
@ -29,15 +34,18 @@ class DocStackContext extends HomeStackContext {
|
||||
|
||||
@override
|
||||
Widget get naviTitle => FlowyText.medium(_view.name, fontSize: 12);
|
||||
|
||||
@override
|
||||
Widget? Function(BuildContext context) get buildNaviAction => _buildNaviAction;
|
||||
|
||||
@override
|
||||
String get identifier => _view.id;
|
||||
|
||||
@override
|
||||
HomeStackType get type => _view.stackType();
|
||||
|
||||
@override
|
||||
Widget buildWidget() {
|
||||
return DocStackPage(_view, key: ValueKey(_view.id));
|
||||
}
|
||||
Widget buildWidget() => DocStackPage(_view, key: ValueKey(_view.id));
|
||||
|
||||
@override
|
||||
List<NavigationItem> get navigationItems => _makeNavigationItems();
|
||||
@ -50,15 +58,52 @@ class DocStackContext extends HomeStackContext {
|
||||
// }).toList();
|
||||
|
||||
List<NavigationItem> _makeNavigationItems() {
|
||||
return [
|
||||
this,
|
||||
];
|
||||
return [this];
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_listener.stop();
|
||||
}
|
||||
|
||||
Widget _buildNaviAction(BuildContext context) {
|
||||
return const DocShareButton();
|
||||
}
|
||||
}
|
||||
|
||||
class DocShareButton extends StatelessWidget {
|
||||
const DocShareButton({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
double buttonWidth = 60;
|
||||
return RoundedTextButton(
|
||||
title: 'Share',
|
||||
height: 30,
|
||||
width: buttonWidth,
|
||||
fontSize: 12,
|
||||
borderRadius: Corners.s6Border,
|
||||
color: Colors.lightBlue,
|
||||
onPressed: () {
|
||||
final actionList = ShareActions(onSelected: (result) {
|
||||
result.fold(() {}, (action) {
|
||||
switch (action) {
|
||||
case ShareAction.markdown:
|
||||
break;
|
||||
case ShareAction.copyLink:
|
||||
break;
|
||||
}
|
||||
});
|
||||
});
|
||||
actionList.show(
|
||||
context,
|
||||
context,
|
||||
anchorDirection: AnchorDirection.bottomWithCenterAligned,
|
||||
anchorOffset: Offset(-(buttonWidth / 2), 10),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class DocStackPage extends StatefulWidget {
|
||||
@ -90,3 +135,70 @@ class _DocStackPageState extends State<DocStackPage> {
|
||||
super.didUpdateWidget(oldWidget);
|
||||
}
|
||||
}
|
||||
|
||||
class ShareActions with ActionList<ShareActionWrapper> implements FlowyOverlayDelegate {
|
||||
final Function(dartz.Option<ShareAction>) onSelected;
|
||||
final _items = ShareAction.values.map((action) => ShareActionWrapper(action)).toList();
|
||||
|
||||
ShareActions({
|
||||
required this.onSelected,
|
||||
});
|
||||
|
||||
@override
|
||||
double get maxWidth => 130;
|
||||
|
||||
@override
|
||||
double get itemHeight => 22;
|
||||
|
||||
@override
|
||||
List<ShareActionWrapper> get items => _items;
|
||||
|
||||
@override
|
||||
void Function(dartz.Option<ShareActionWrapper> p1) get selectCallback => (result) {
|
||||
result.fold(
|
||||
() => onSelected(dartz.none()),
|
||||
(wrapper) => onSelected(
|
||||
dartz.some(wrapper.inner),
|
||||
),
|
||||
);
|
||||
};
|
||||
|
||||
@override
|
||||
FlowyOverlayDelegate? get delegate => this;
|
||||
|
||||
@override
|
||||
void didRemove() {
|
||||
onSelected(dartz.none());
|
||||
}
|
||||
|
||||
@override
|
||||
ListOverlayFooter? get footer => null;
|
||||
}
|
||||
|
||||
enum ShareAction {
|
||||
markdown,
|
||||
copyLink,
|
||||
}
|
||||
|
||||
class ShareActionWrapper extends ActionItem {
|
||||
final ShareAction inner;
|
||||
|
||||
ShareActionWrapper(this.inner);
|
||||
|
||||
@override
|
||||
Widget? get icon => null;
|
||||
|
||||
@override
|
||||
String get name => inner.name;
|
||||
}
|
||||
|
||||
extension QuestionBubbleExtension on ShareAction {
|
||||
String get name {
|
||||
switch (this) {
|
||||
case ShareAction.markdown:
|
||||
return "Markdown";
|
||||
case ShareAction.copyLink:
|
||||
return "Copy Link";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ import 'package:app_flowy/workspace/application/trash/trash_bloc.dart';
|
||||
import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart';
|
||||
import 'package:app_flowy/workspace/presentation/stack_page/trash/widget/sizes.dart';
|
||||
import 'package:app_flowy/workspace/presentation/stack_page/trash/widget/trash_cell.dart';
|
||||
import 'package:app_flowy/workspace/presentation/widgets/home_top_bar.dart';
|
||||
import 'package:flowy_infra/image.dart';
|
||||
import 'package:flowy_infra/theme.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart';
|
||||
@ -27,6 +28,9 @@ class TrashStackContext extends HomeStackContext {
|
||||
@override
|
||||
Widget get naviTitle => const FlowyText.medium('Trash', fontSize: 12);
|
||||
|
||||
@override
|
||||
Widget? Function(BuildContext context) get buildNavigationActions => (_) => null;
|
||||
|
||||
@override
|
||||
HomeStackType get type => HomeStackType.trash;
|
||||
|
||||
|
@ -22,21 +22,21 @@ class QuestionBubble extends StatelessWidget {
|
||||
height: 30,
|
||||
child: FlowyTextButton(
|
||||
'?',
|
||||
tooltip: QuestionBubbleAction.values.map((action) => action.name).toList().join(','),
|
||||
tooltip: BubbleAction.values.map((action) => action.name).toList().join(','),
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w600,
|
||||
fillColor: theme.selector,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
radius: BorderRadius.circular(10),
|
||||
onPressed: () {
|
||||
final actionList = QuestionBubbleActions(onSelected: (result) {
|
||||
final actionList = QuestionBubbleActionSheet(onSelected: (result) {
|
||||
result.fold(() {}, (action) {
|
||||
switch (action) {
|
||||
case QuestionBubbleAction.whatsNews:
|
||||
case BubbleAction.whatsNews:
|
||||
// TODO: annie replace the URL with real ones
|
||||
_launchURL("https://www.appflowy.io/whatsnew");
|
||||
break;
|
||||
case QuestionBubbleAction.help:
|
||||
case BubbleAction.help:
|
||||
// TODO: annie replace the URL with real ones
|
||||
_launchURL("https://discord.gg/9Q2xaN37tV");
|
||||
break;
|
||||
@ -63,11 +63,11 @@ class QuestionBubble extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
class QuestionBubbleActions with ActionList<QuestionBubbleActionWrapper> implements FlowyOverlayDelegate {
|
||||
final Function(dartz.Option<QuestionBubbleAction>) onSelected;
|
||||
final _items = QuestionBubbleAction.values.map((action) => QuestionBubbleActionWrapper(action)).toList();
|
||||
class QuestionBubbleActionSheet with ActionList<BubbleActionWrapper> implements FlowyOverlayDelegate {
|
||||
final Function(dartz.Option<BubbleAction>) onSelected;
|
||||
final _items = BubbleAction.values.map((action) => BubbleActionWrapper(action)).toList();
|
||||
|
||||
QuestionBubbleActions({
|
||||
QuestionBubbleActionSheet({
|
||||
required this.onSelected,
|
||||
});
|
||||
|
||||
@ -78,10 +78,10 @@ class QuestionBubbleActions with ActionList<QuestionBubbleActionWrapper> impleme
|
||||
double get itemHeight => 22;
|
||||
|
||||
@override
|
||||
List<QuestionBubbleActionWrapper> get items => _items;
|
||||
List<BubbleActionWrapper> get items => _items;
|
||||
|
||||
@override
|
||||
void Function(dartz.Option<QuestionBubbleActionWrapper> p1) get selectCallback => (result) {
|
||||
void Function(dartz.Option<BubbleActionWrapper> p1) get selectCallback => (result) {
|
||||
result.fold(
|
||||
() => onSelected(dartz.none()),
|
||||
(wrapper) => onSelected(
|
||||
@ -145,15 +145,15 @@ class FlowyVersionDescription extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
enum QuestionBubbleAction {
|
||||
enum BubbleAction {
|
||||
whatsNews,
|
||||
help,
|
||||
}
|
||||
|
||||
class QuestionBubbleActionWrapper extends ActionItemData {
|
||||
final QuestionBubbleAction inner;
|
||||
class BubbleActionWrapper extends ActionItem {
|
||||
final BubbleAction inner;
|
||||
|
||||
QuestionBubbleActionWrapper(this.inner);
|
||||
BubbleActionWrapper(this.inner);
|
||||
@override
|
||||
Widget? get icon => inner.emoji;
|
||||
|
||||
@ -161,21 +161,21 @@ class QuestionBubbleActionWrapper extends ActionItemData {
|
||||
String get name => inner.name;
|
||||
}
|
||||
|
||||
extension QuestionBubbleExtension on QuestionBubbleAction {
|
||||
extension QuestionBubbleExtension on BubbleAction {
|
||||
String get name {
|
||||
switch (this) {
|
||||
case QuestionBubbleAction.whatsNews:
|
||||
case BubbleAction.whatsNews:
|
||||
return "What's new?";
|
||||
case QuestionBubbleAction.help:
|
||||
case BubbleAction.help:
|
||||
return "Help & Support";
|
||||
}
|
||||
}
|
||||
|
||||
Widget get emoji {
|
||||
switch (this) {
|
||||
case QuestionBubbleAction.whatsNews:
|
||||
case BubbleAction.whatsNews:
|
||||
return const Text('⭐️', style: TextStyle(fontSize: 12));
|
||||
case QuestionBubbleAction.help:
|
||||
case BubbleAction.help:
|
||||
return const Text('👥', style: TextStyle(fontSize: 12));
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,14 @@
|
||||
import 'package:app_flowy/workspace/domain/image.dart';
|
||||
import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart';
|
||||
import 'package:app_flowy/workspace/presentation/home/home_sizes.dart';
|
||||
import 'package:app_flowy/workspace/presentation/home/navigation.dart';
|
||||
import 'package:flowy_infra/size.dart';
|
||||
import 'package:flowy_infra_ui/widget/rounded_button.dart';
|
||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_create.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace-infra/view_create.pbenum.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/extension.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/text.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class HomeTopBar extends StatelessWidget {
|
||||
const HomeTopBar({Key? key}) : super(key: key);
|
||||
@ -22,8 +22,14 @@ class HomeTopBar extends StatelessWidget {
|
||||
children: [
|
||||
const FlowyNavigation(),
|
||||
const Spacer(),
|
||||
_renderShareButton(),
|
||||
// _renderMoreButton(),
|
||||
ChangeNotifierProvider.value(
|
||||
value: Provider.of<HomeStackNotifier>(context, listen: false),
|
||||
child: Consumer(
|
||||
builder: (BuildContext context, HomeStackNotifier notifier, Widget? child) {
|
||||
return notifier.stackContext.buildNavigationActions(context) ?? const SizedBox();
|
||||
},
|
||||
),
|
||||
) // _renderMoreButton(),
|
||||
],
|
||||
)
|
||||
.padding(
|
||||
@ -32,20 +38,6 @@ class HomeTopBar extends StatelessWidget {
|
||||
.bottomBorder(color: Colors.grey.shade300),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _renderShareButton() {
|
||||
return RoundedTextButton(
|
||||
title: 'Share',
|
||||
height: 30,
|
||||
width: 60,
|
||||
fontSize: 12,
|
||||
borderRadius: Corners.s6Border,
|
||||
color: Colors.lightBlue,
|
||||
onPressed: () {
|
||||
debugPrint('share page');
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class HomeTitle extends StatelessWidget {
|
||||
|
@ -5,7 +5,6 @@ import 'package:flowy_infra/flowy_icon_data_icons.dart';
|
||||
import 'package:flowy_infra/theme.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/text.dart';
|
||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-workspace-infra/app_create.pb.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
@ -79,7 +78,7 @@ class MenuAppHeader extends StatelessWidget {
|
||||
behavior: HitTestBehavior.opaque,
|
||||
onTap: () => ExpandableController.of(context, rebuildOnChange: false, required: true)?.toggle(),
|
||||
onSecondaryTap: () {
|
||||
final actionList = AppDisclosureActions(onSelected: (action) => _handleAction(context, action));
|
||||
final actionList = AppDisclosureActionSheet(onSelected: (action) => _handleAction(context, action));
|
||||
actionList.show(
|
||||
context,
|
||||
context,
|
||||
|
@ -4,19 +4,19 @@ import 'package:dartz/dartz.dart' as dartz;
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class AppDisclosureActions with ActionList<AppDisclosureActionWrapper> implements FlowyOverlayDelegate {
|
||||
class AppDisclosureActionSheet with ActionList<DisclosureActionWrapper> implements FlowyOverlayDelegate {
|
||||
final Function(dartz.Option<AppDisclosureAction>) onSelected;
|
||||
final _items = AppDisclosureAction.values.map((action) => AppDisclosureActionWrapper(action)).toList();
|
||||
final _items = AppDisclosureAction.values.map((action) => DisclosureActionWrapper(action)).toList();
|
||||
|
||||
AppDisclosureActions({
|
||||
AppDisclosureActionSheet({
|
||||
required this.onSelected,
|
||||
});
|
||||
|
||||
@override
|
||||
List<AppDisclosureActionWrapper> get items => _items;
|
||||
List<DisclosureActionWrapper> get items => _items;
|
||||
|
||||
@override
|
||||
void Function(dartz.Option<AppDisclosureActionWrapper> p1) get selectCallback => (result) {
|
||||
void Function(dartz.Option<DisclosureActionWrapper> p1) get selectCallback => (result) {
|
||||
result.fold(
|
||||
() => onSelected(dartz.none()),
|
||||
(wrapper) => onSelected(
|
||||
@ -37,10 +37,10 @@ class AppDisclosureActions with ActionList<AppDisclosureActionWrapper> implement
|
||||
ListOverlayFooter? get footer => null;
|
||||
}
|
||||
|
||||
class AppDisclosureActionWrapper extends ActionItemData {
|
||||
class DisclosureActionWrapper extends ActionItem {
|
||||
final AppDisclosureAction inner;
|
||||
|
||||
AppDisclosureActionWrapper(this.inner);
|
||||
DisclosureActionWrapper(this.inner);
|
||||
@override
|
||||
Widget? get icon => inner.icon;
|
||||
|
||||
|
@ -57,7 +57,7 @@ class ViewDisclosureButton extends StatelessWidget
|
||||
ListOverlayFooter? get footer => null;
|
||||
}
|
||||
|
||||
class ViewDisclosureActionWrapper extends ActionItemData {
|
||||
class ViewDisclosureActionWrapper extends ActionItem {
|
||||
final ViewDisclosureAction inner;
|
||||
|
||||
ViewDisclosureActionWrapper(this.inner);
|
||||
|
@ -8,7 +8,7 @@ import 'package:provider/provider.dart';
|
||||
import 'package:styled_widget/styled_widget.dart';
|
||||
import 'package:dartz/dartz.dart' as dartz;
|
||||
|
||||
abstract class ActionList<T extends ActionItemData> {
|
||||
abstract class ActionList<T extends ActionItem> {
|
||||
List<T> get items;
|
||||
|
||||
String get identifier => toString();
|
||||
@ -31,7 +31,7 @@ abstract class ActionList<T extends ActionItemData> {
|
||||
}) {
|
||||
final widgets = items
|
||||
.map(
|
||||
(action) => ActionItem<T>(
|
||||
(action) => ActionCell<T>(
|
||||
action: action,
|
||||
itemHeight: itemHeight,
|
||||
onSelected: (action) {
|
||||
@ -58,7 +58,7 @@ abstract class ActionList<T extends ActionItemData> {
|
||||
}
|
||||
}
|
||||
|
||||
abstract class ActionItemData {
|
||||
abstract class ActionItem {
|
||||
Widget? get icon;
|
||||
String get name;
|
||||
}
|
||||
@ -69,11 +69,11 @@ class ActionListSizes {
|
||||
static double padding = 6;
|
||||
}
|
||||
|
||||
class ActionItem<T extends ActionItemData> extends StatelessWidget {
|
||||
class ActionCell<T extends ActionItem> extends StatelessWidget {
|
||||
final T action;
|
||||
final Function(T) onSelected;
|
||||
final double itemHeight;
|
||||
const ActionItem({
|
||||
const ActionCell({
|
||||
Key? key,
|
||||
required this.action,
|
||||
required this.onSelected,
|
||||
|
@ -17,7 +17,7 @@ use crate::{
|
||||
};
|
||||
use flowy_dispatch::prelude::{data_result, Data, DataResult, Unit};
|
||||
use flowy_document::entities::doc::DocDelta;
|
||||
use flowy_workspace_infra::entities::share::{ExportParams, ExportRequest};
|
||||
use flowy_workspace_infra::entities::share::{ExportData, ExportParams, ExportRequest};
|
||||
use std::{convert::TryInto, sync::Arc};
|
||||
|
||||
pub(crate) async fn create_view_handler(
|
||||
@ -112,8 +112,8 @@ pub(crate) async fn duplicate_view_handler(
|
||||
pub(crate) async fn export_handler(
|
||||
data: Data<ExportRequest>,
|
||||
controller: Unit<Arc<ViewController>>,
|
||||
) -> Result<(), WorkspaceError> {
|
||||
) -> DataResult<ExportData, WorkspaceError> {
|
||||
let params: ExportParams = data.into_inner().try_into()?;
|
||||
let _ = controller.export_doc(params.into()).await?;
|
||||
Ok(())
|
||||
let data = controller.export_doc(params.into()).await?;
|
||||
data_result(data)
|
||||
}
|
||||
|
@ -139,9 +139,15 @@ impl ViewController {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(self), err)]
|
||||
pub(crate) async fn export_doc(&self, _params: ExportParams) -> Result<ExportData, WorkspaceError> {
|
||||
unimplemented!()
|
||||
#[tracing::instrument(level = "debug", skip(self, params), err)]
|
||||
pub(crate) async fn export_doc(&self, params: ExportParams) -> Result<ExportData, WorkspaceError> {
|
||||
let doc_identifier: DocIdentifier = params.doc_id.into();
|
||||
let doc = self
|
||||
.document
|
||||
.read_document_data(doc_identifier, self.database.db_pool()?)
|
||||
.await?;
|
||||
|
||||
Ok(ExportData { data: doc.data })
|
||||
}
|
||||
|
||||
// belong_to_id will be the app_id or view_id.
|
||||
|
Loading…
Reference in New Issue
Block a user