|
@@ -2,6 +2,7 @@ import 'dart:async';
|
|
import 'package:app_flowy/generated/locale_keys.g.dart';
|
|
import 'package:app_flowy/generated/locale_keys.g.dart';
|
|
import 'package:app_flowy/plugins/grid/application/cell/url_cell_bloc.dart';
|
|
import 'package:app_flowy/plugins/grid/application/cell/url_cell_bloc.dart';
|
|
import 'package:app_flowy/workspace/presentation/home/toast.dart';
|
|
import 'package:app_flowy/workspace/presentation/home/toast.dart';
|
|
|
|
+import 'package:appflowy_popover/popover.dart';
|
|
import 'package:easy_localization/easy_localization.dart';
|
|
import 'package:easy_localization/easy_localization.dart';
|
|
import 'package:flowy_infra/image.dart';
|
|
import 'package:flowy_infra/image.dart';
|
|
import 'package:flowy_infra/theme.dart';
|
|
import 'package:flowy_infra/theme.dart';
|
|
@@ -48,27 +49,37 @@ class GridURLCell extends GridCellWidget {
|
|
@override
|
|
@override
|
|
GridCellState<GridURLCell> createState() => _GridURLCellState();
|
|
GridCellState<GridURLCell> createState() => _GridURLCellState();
|
|
|
|
|
|
- GridCellAccessory accessoryFromType(
|
|
|
|
|
|
+ GridCellAccessoryBuilder accessoryFromType(
|
|
GridURLCellAccessoryType ty, GridCellAccessoryBuildContext buildContext) {
|
|
GridURLCellAccessoryType ty, GridCellAccessoryBuildContext buildContext) {
|
|
switch (ty) {
|
|
switch (ty) {
|
|
case GridURLCellAccessoryType.edit:
|
|
case GridURLCellAccessoryType.edit:
|
|
final cellController =
|
|
final cellController =
|
|
cellControllerBuilder.build() as GridURLCellController;
|
|
cellControllerBuilder.build() as GridURLCellController;
|
|
- return _EditURLAccessory(
|
|
|
|
|
|
+ return GridCellAccessoryBuilder(
|
|
|
|
+ builder: (Key key) => _EditURLAccessory(
|
|
|
|
+ key: key,
|
|
cellContext: cellController,
|
|
cellContext: cellController,
|
|
- anchorContext: buildContext.anchorContext);
|
|
|
|
|
|
+ anchorContext: buildContext.anchorContext,
|
|
|
|
+ ),
|
|
|
|
+ );
|
|
|
|
|
|
case GridURLCellAccessoryType.copyURL:
|
|
case GridURLCellAccessoryType.copyURL:
|
|
final cellContext =
|
|
final cellContext =
|
|
cellControllerBuilder.build() as GridURLCellController;
|
|
cellControllerBuilder.build() as GridURLCellController;
|
|
- return _CopyURLAccessory(cellContext: cellContext);
|
|
|
|
|
|
+ return GridCellAccessoryBuilder(
|
|
|
|
+ builder: (Key key) => _CopyURLAccessory(
|
|
|
|
+ key: key,
|
|
|
|
+ cellContext: cellContext,
|
|
|
|
+ ),
|
|
|
|
+ );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@override
|
|
@override
|
|
- List<GridCellAccessory> Function(GridCellAccessoryBuildContext buildContext)
|
|
|
|
|
|
+ List<GridCellAccessoryBuilder> Function(
|
|
|
|
+ GridCellAccessoryBuildContext buildContext)
|
|
get accessoryBuilder => (buildContext) {
|
|
get accessoryBuilder => (buildContext) {
|
|
- final List<GridCellAccessory> accessories = [];
|
|
|
|
|
|
+ final List<GridCellAccessoryBuilder> accessories = [];
|
|
if (cellStyle != null) {
|
|
if (cellStyle != null) {
|
|
accessories.addAll(cellStyle!.accessoryTypes.map((ty) {
|
|
accessories.addAll(cellStyle!.accessoryTypes.map((ty) {
|
|
return accessoryFromType(ty, buildContext);
|
|
return accessoryFromType(ty, buildContext);
|
|
@@ -86,6 +97,8 @@ class GridURLCell extends GridCellWidget {
|
|
}
|
|
}
|
|
|
|
|
|
class _GridURLCellState extends GridCellState<GridURLCell> {
|
|
class _GridURLCellState extends GridCellState<GridURLCell> {
|
|
|
|
+ final _popoverController = PopoverController();
|
|
|
|
+ GridURLCellController? _cellContext;
|
|
late URLCellBloc _cellBloc;
|
|
late URLCellBloc _cellBloc;
|
|
|
|
|
|
@override
|
|
@override
|
|
@@ -116,14 +129,28 @@ class _GridURLCellState extends GridCellState<GridURLCell> {
|
|
),
|
|
),
|
|
);
|
|
);
|
|
|
|
|
|
- return SizedBox.expand(
|
|
|
|
|
|
+ return Popover(
|
|
|
|
+ controller: _popoverController,
|
|
|
|
+ direction: PopoverDirection.bottomWithLeftAligned,
|
|
|
|
+ offset: const Offset(0, 20),
|
|
|
|
+ child: SizedBox.expand(
|
|
child: GestureDetector(
|
|
child: GestureDetector(
|
|
- child: Align(alignment: Alignment.centerLeft, child: richText),
|
|
|
|
- onTap: () async {
|
|
|
|
- final url = context.read<URLCellBloc>().state.url;
|
|
|
|
- await _openUrlOrEdit(url);
|
|
|
|
|
|
+ child: Align(alignment: Alignment.centerLeft, child: richText),
|
|
|
|
+ onTap: () async {
|
|
|
|
+ final url = context.read<URLCellBloc>().state.url;
|
|
|
|
+ await _openUrlOrEdit(url);
|
|
|
|
+ },
|
|
|
|
+ ),
|
|
|
|
+ ),
|
|
|
|
+ popupBuilder: (BuildContext popoverContext) {
|
|
|
|
+ return URLEditorPopover(
|
|
|
|
+ cellController: _cellContext!,
|
|
|
|
+ );
|
|
|
|
+ },
|
|
|
|
+ onClose: () {
|
|
|
|
+ widget.onCellEditing.value = false;
|
|
},
|
|
},
|
|
- ));
|
|
|
|
|
|
+ );
|
|
},
|
|
},
|
|
),
|
|
),
|
|
);
|
|
);
|
|
@@ -140,12 +167,10 @@ class _GridURLCellState extends GridCellState<GridURLCell> {
|
|
if (url.isNotEmpty && await canLaunchUrl(uri)) {
|
|
if (url.isNotEmpty && await canLaunchUrl(uri)) {
|
|
await launchUrl(uri);
|
|
await launchUrl(uri);
|
|
} else {
|
|
} else {
|
|
- final cellContext =
|
|
|
|
|
|
+ _cellContext =
|
|
widget.cellControllerBuilder.build() as GridURLCellController;
|
|
widget.cellControllerBuilder.build() as GridURLCellController;
|
|
widget.onCellEditing.value = true;
|
|
widget.onCellEditing.value = true;
|
|
- URLCellEditor.show(context, cellContext, () {
|
|
|
|
- widget.onCellEditing.value = false;
|
|
|
|
- });
|
|
|
|
|
|
+ _popoverController.show();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -163,7 +188,7 @@ class _GridURLCellState extends GridCellState<GridURLCell> {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-class _EditURLAccessory extends StatelessWidget with GridCellAccessory {
|
|
|
|
|
|
+class _EditURLAccessory extends StatefulWidget {
|
|
final GridURLCellController cellContext;
|
|
final GridURLCellController cellContext;
|
|
final BuildContext anchorContext;
|
|
final BuildContext anchorContext;
|
|
const _EditURLAccessory({
|
|
const _EditURLAccessory({
|
|
@@ -172,24 +197,55 @@ class _EditURLAccessory extends StatelessWidget with GridCellAccessory {
|
|
Key? key,
|
|
Key? key,
|
|
}) : super(key: key);
|
|
}) : super(key: key);
|
|
|
|
|
|
|
|
+ @override
|
|
|
|
+ State<StatefulWidget> createState() => _EditURLAccessoryState();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+class _EditURLAccessoryState extends State<_EditURLAccessory>
|
|
|
|
+ with GridCellAccessoryState {
|
|
|
|
+ late PopoverController _popoverController;
|
|
|
|
+
|
|
|
|
+ @override
|
|
|
|
+ void initState() {
|
|
|
|
+ _popoverController = PopoverController();
|
|
|
|
+ super.initState();
|
|
|
|
+ }
|
|
|
|
+
|
|
@override
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
Widget build(BuildContext context) {
|
|
final theme = context.watch<AppTheme>();
|
|
final theme = context.watch<AppTheme>();
|
|
- return svgWidget("editor/edit", color: theme.iconColor);
|
|
|
|
|
|
+ return Popover(
|
|
|
|
+ controller: _popoverController,
|
|
|
|
+ direction: PopoverDirection.bottomWithLeftAligned,
|
|
|
|
+ triggerActions: PopoverTriggerActionFlags.click,
|
|
|
|
+ offset: const Offset(0, 20),
|
|
|
|
+ child: svgWidget("editor/edit", color: theme.iconColor),
|
|
|
|
+ popupBuilder: (BuildContext popoverContext) {
|
|
|
|
+ return URLEditorPopover(
|
|
|
|
+ cellController: widget.cellContext.clone(),
|
|
|
|
+ );
|
|
|
|
+ },
|
|
|
|
+ );
|
|
}
|
|
}
|
|
|
|
|
|
@override
|
|
@override
|
|
void onTap() {
|
|
void onTap() {
|
|
- URLCellEditor.show(anchorContext, cellContext, () {});
|
|
|
|
|
|
+ _popoverController.show();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-class _CopyURLAccessory extends StatelessWidget with GridCellAccessory {
|
|
|
|
|
|
+class _CopyURLAccessory extends StatefulWidget {
|
|
final GridURLCellController cellContext;
|
|
final GridURLCellController cellContext;
|
|
const _CopyURLAccessory({required this.cellContext, Key? key})
|
|
const _CopyURLAccessory({required this.cellContext, Key? key})
|
|
: super(key: key);
|
|
: super(key: key);
|
|
|
|
|
|
@override
|
|
@override
|
|
|
|
+ State<StatefulWidget> createState() => _CopyURLAccessoryState();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+class _CopyURLAccessoryState extends State<_CopyURLAccessory>
|
|
|
|
+ with GridCellAccessoryState {
|
|
|
|
+ @override
|
|
Widget build(BuildContext context) {
|
|
Widget build(BuildContext context) {
|
|
final theme = context.watch<AppTheme>();
|
|
final theme = context.watch<AppTheme>();
|
|
return svgWidget("editor/copy", color: theme.iconColor);
|
|
return svgWidget("editor/copy", color: theme.iconColor);
|
|
@@ -198,7 +254,7 @@ class _CopyURLAccessory extends StatelessWidget with GridCellAccessory {
|
|
@override
|
|
@override
|
|
void onTap() {
|
|
void onTap() {
|
|
final content =
|
|
final content =
|
|
- cellContext.getCellData(loadIfNotExist: false)?.content ?? "";
|
|
|
|
|
|
+ widget.cellContext.getCellData(loadIfNotExist: false)?.content ?? "";
|
|
Clipboard.setData(ClipboardData(text: content));
|
|
Clipboard.setData(ClipboardData(text: content));
|
|
showMessageToast(LocaleKeys.grid_row_copyProperty.tr());
|
|
showMessageToast(LocaleKeys.grid_row_copyProperty.tr());
|
|
}
|
|
}
|