feat: add image block on mobile (#4230)

This commit is contained in:
Lucas.Xu 2023-12-28 20:39:18 +08:00 committed by GitHub
parent 0b3c904984
commit 30a28b12d1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 73 additions and 5 deletions

View File

@ -47,4 +47,9 @@
</application>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<queries>
<intent>
<action android:name="android.support.customtabs.action.CustomTabsService" />
</intent>
</queries>
</manifest>

View File

@ -67,6 +67,9 @@ class MobileBlockActionButtons extends StatelessWidget {
}
void _showBottomSheet(BuildContext context) {
// close the keyboard
editorState.updateSelectionWithReason(null, extraInfo: {});
showMobileBottomSheet(
context,
showHeader: true,

View File

@ -104,6 +104,7 @@ class ImagePlaceholderState extends State<ImagePlaceholder> {
} else {
return GestureDetector(
onTap: () {
editorState.updateSelectionWithReason(null, extraInfo: {});
showUploadImageMenu();
},
child: child,

View File

@ -59,6 +59,7 @@ extension InsertImage on EditorState {
offset: 0,
),
);
transaction.selectionExtraInfo = {};
return apply(transaction);
}

View File

@ -1,16 +1,18 @@
import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_toolbar_theme.dart';
import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/util.dart';
import 'package:appflowy/plugins/document/presentation/editor_plugins/plugins.dart';
import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:flutter/material.dart';
class IndentAndOutdentItems extends StatelessWidget {
const IndentAndOutdentItems({
super.key,
required this.service,
required this.editorState,
});
final EditorState editorState;
final AppFlowyMobileToolbarWidgetService service;
@override
Widget build(BuildContext context) {
@ -28,6 +30,7 @@ class IndentAndOutdentItems extends StatelessWidget {
iconPadding: const EdgeInsets.symmetric(vertical: 14.0),
backgroundColor: theme.toolbarMenuItemBackgroundColor,
onTap: () {
service.closeItemMenu();
outdentCommand.execute(editorState);
},
),
@ -42,6 +45,7 @@ class IndentAndOutdentItems extends StatelessWidget {
iconPadding: const EdgeInsets.symmetric(vertical: 14.0),
backgroundColor: theme.toolbarMenuItemBackgroundColor,
onTap: () {
service.closeItemMenu();
indentCommand.execute(editorState);
},
),

View File

@ -106,6 +106,7 @@ class _TextDecorationMenuState extends State<_TextDecorationMenu> {
),
const Spacer(),
IndentAndOutdentItems(
service: widget.service,
editorState: editorState,
),
],

View File

@ -1,6 +1,7 @@
import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet.dart';
import 'package:appflowy/plugins/document/presentation/editor_plugins/image/image_placeholder.dart';
import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_item/mobile_add_block_toolbar_item.dart';
import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_toolbar_theme.dart';
import 'package:appflowy/plugins/document/presentation/editor_plugins/plugins.dart';
@ -184,7 +185,7 @@ class _AddBlockMenu extends StatelessWidget {
onTap: () => _insertBlock(quoteNode()),
),
// divider,
// divider
_AddBlockMenuItemData(
blockType: DividerBlockKeys.type,
backgroundColor: const Color(0xFF98F4CD),
@ -197,6 +198,25 @@ class _AddBlockMenu extends StatelessWidget {
});
},
),
// image
_AddBlockMenuItemData(
blockType: DividerBlockKeys.type,
backgroundColor: const Color(0xFF98F4CD),
text: LocaleKeys.editor_image.tr(),
icon: FlowySvgs.m_toolbar_imae_lg,
onTap: () async {
AppGlobals.rootNavKey.currentContext?.pop(true);
Future.delayed(const Duration(milliseconds: 400), () async {
final imagePlaceholderKey = GlobalKey<ImagePlaceholderState>();
await editorState.insertEmptyImageBlock(imagePlaceholderKey);
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
imagePlaceholderKey.currentState?.controller.show();
});
});
},
),
];
@override
@ -257,7 +277,7 @@ class _AddBlockMenuItem extends StatelessWidget {
borderRadius: BorderRadius.circular(20),
),
),
padding: const EdgeInsets.all(24),
padding: EdgeInsets.all(20 * context.scale),
child: FlowySvg(
data.icon,
color: Colors.black,
@ -266,7 +286,7 @@ class _AddBlockMenuItem extends StatelessWidget {
const VSpace(4),
FlowyText(
data.text,
fontSize: 13.0,
fontSize: 12.0,
),
],
),

View File

@ -540,7 +540,8 @@ class _ToolbarItemListViewState extends State<_ToolbarItemListView> {
}
final toolbarItems = widget.toolbarItems;
final alignment = selection.isCollapsed ? 0.0 : -1.0;
// use -0.4 to make sure the pilot is in the front of the toolbar item
final alignment = selection.isCollapsed ? 0.0 : -0.4;
final index = toolbarItems.indexWhere(
(element) => selection.isCollapsed
? element.pilotAtCollapsedSelection

View File

@ -1,3 +1,4 @@
import 'package:appflowy/startup/tasks/prelude.dart';
import 'package:keyboard_height_plugin/keyboard_height_plugin.dart';
typedef KeyboardHeightCallback = void Function(double height);
@ -32,6 +33,12 @@ class KeyboardHeightObserver {
}
void notify(double height) {
// the keyboard height will notify twice with the same value on Android 14
if (DeviceInfoTask.androidSDKVersion == 34) {
if (height == 0 && currentKeyboardHeight == 0) {
return;
}
}
for (final listener in _listeners) {
listener(height);
}

View File

@ -103,6 +103,7 @@ class FlowyRunner {
// there's a flag named _enable in memory_leak_detector.dart. If it's false, the task will be ignored.
MemoryLeakDetectorTask(),
const DebugTask(),
const DeviceInfoTask(),
// localization
const InitLocalizationTask(),
// init the app window

View File

@ -0,0 +1,23 @@
import 'dart:io';
import 'package:device_info_plus/device_info_plus.dart';
import '../startup.dart';
class DeviceInfoTask extends LaunchTask {
const DeviceInfoTask();
static int androidSDKVersion = -1;
@override
Future<void> initialize(LaunchContext context) async {
final DeviceInfoPlugin deviceInfoPlugin = DeviceInfoPlugin();
if (Platform.isAndroid) {
final androidInfo = await deviceInfoPlugin.androidInfo;
androidSDKVersion = androidInfo.version.sdkInt;
}
}
@override
Future<void> dispose() async {}
}

View File

@ -1,6 +1,7 @@
export 'app_widget.dart';
export 'appflowy_cloud_task.dart';
export 'debug_task.dart';
export 'device_info_task.dart';
export 'generate_router.dart';
export 'hot_key.dart';
export 'load_plugin.dart';