mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
chore: bump version 0.3.0 (#3252)
This commit is contained in:
16
CHANGELOG.md
16
CHANGELOG.md
@ -1,5 +1,21 @@
|
|||||||
# Release Notes
|
# Release Notes
|
||||||
|
|
||||||
|
## Version 0.3.0 - 08/22/2023
|
||||||
|
|
||||||
|
### New Features
|
||||||
|
|
||||||
|
- Improve paste features:
|
||||||
|
- Paste HTML content from website.
|
||||||
|
- Paste image from clipboard.
|
||||||
|
|
||||||
|
- Support Group by Date in Kanban Board.
|
||||||
|
- Notarize the macOS package, which is now verified by Apple.
|
||||||
|
- Add Persian language translations.
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
||||||
|
- Some UI issues
|
||||||
|
|
||||||
## Version 0.2.9 - 08/08/2023
|
## Version 0.2.9 - 08/08/2023
|
||||||
|
|
||||||
### New Features
|
### New Features
|
||||||
|
@ -24,7 +24,7 @@ CARGO_MAKE_EXTEND_WORKSPACE_MAKEFILE = true
|
|||||||
CARGO_MAKE_CRATE_FS_NAME = "dart_ffi"
|
CARGO_MAKE_CRATE_FS_NAME = "dart_ffi"
|
||||||
CARGO_MAKE_CRATE_NAME = "dart-ffi"
|
CARGO_MAKE_CRATE_NAME = "dart-ffi"
|
||||||
LIB_NAME = "dart_ffi"
|
LIB_NAME = "dart_ffi"
|
||||||
CURRENT_APP_VERSION = "0.2.9"
|
CURRENT_APP_VERSION = "0.3.0"
|
||||||
FLUTTER_DESKTOP_FEATURES = "dart,rev-sqlite"
|
FLUTTER_DESKTOP_FEATURES = "dart,rev-sqlite"
|
||||||
PRODUCT_NAME = "AppFlowy"
|
PRODUCT_NAME = "AppFlowy"
|
||||||
# CRATE_TYPE: https://doc.rust-lang.org/reference/linkage.html
|
# CRATE_TYPE: https://doc.rust-lang.org/reference/linkage.html
|
||||||
|
@ -245,7 +245,7 @@ extension on WidgetTester {
|
|||||||
await beforeTest?.call(editor.getCurrentEditorState());
|
await beforeTest?.call(editor.getCurrentEditorState());
|
||||||
|
|
||||||
// mock the clipboard
|
// mock the clipboard
|
||||||
getIt<ClipboardService>().setData(
|
await getIt<ClipboardService>().setData(
|
||||||
ClipboardServiceData(
|
ClipboardServiceData(
|
||||||
plainText: plainText,
|
plainText: plainText,
|
||||||
html: html,
|
html: html,
|
||||||
|
@ -52,6 +52,7 @@ class _AppFlowyEditorPageState extends State<AppFlowyEditorPage> {
|
|||||||
...codeBlockCommands,
|
...codeBlockCommands,
|
||||||
customCopyCommand,
|
customCopyCommand,
|
||||||
customPasteCommand,
|
customPasteCommand,
|
||||||
|
customCutCommand,
|
||||||
...standardCommandShortcutEvents,
|
...standardCommandShortcutEvents,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ final inAppJsonFormat = CustomValueFormat<String>(
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
|
onEncode: (value, platformType) => utf8.encode(value),
|
||||||
);
|
);
|
||||||
|
|
||||||
class ClipboardServiceData {
|
class ClipboardServiceData {
|
||||||
|
@ -0,0 +1,24 @@
|
|||||||
|
import 'package:appflowy/plugins/document/presentation/editor_plugins/copy_and_paste/editor_state_paste_node_extension.dart';
|
||||||
|
import 'package:appflowy/plugins/document/presentation/editor_plugins/plugins.dart';
|
||||||
|
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
/// cut.
|
||||||
|
///
|
||||||
|
/// - support
|
||||||
|
/// - desktop
|
||||||
|
/// - web
|
||||||
|
/// - mobile
|
||||||
|
///
|
||||||
|
final CommandShortcutEvent customCutCommand = CommandShortcutEvent(
|
||||||
|
key: 'cut the selected content',
|
||||||
|
command: 'ctrl+x',
|
||||||
|
macOSCommand: 'cmd+x',
|
||||||
|
handler: _cutCommandHandler,
|
||||||
|
);
|
||||||
|
|
||||||
|
CommandShortcutEventHandler _cutCommandHandler = (editorState) {
|
||||||
|
customCopyCommand.execute(editorState);
|
||||||
|
editorState.deleteSelectionIfNeeded();
|
||||||
|
return KeyEventResult.handled;
|
||||||
|
};
|
@ -14,25 +14,29 @@ extension PasteNodes on EditorState {
|
|||||||
final transaction = this.transaction;
|
final transaction = this.transaction;
|
||||||
final insertedDelta = insertedNode.delta;
|
final insertedDelta = insertedNode.delta;
|
||||||
// if the node is empty, replace it with the inserted node.
|
// if the node is empty, replace it with the inserted node.
|
||||||
if (delta.isEmpty || insertedDelta == null) {
|
if (delta.isEmpty) {
|
||||||
transaction.insertNode(
|
transaction.insertNode(
|
||||||
selection.end.path.next,
|
selection.end.path.next,
|
||||||
node.copyWith(
|
insertedDelta == null
|
||||||
type: node.type,
|
? node.copyWith(
|
||||||
attributes: {
|
type: node.type,
|
||||||
...node.attributes,
|
attributes: {
|
||||||
...insertedNode.attributes,
|
...node.attributes,
|
||||||
},
|
...insertedNode.attributes,
|
||||||
),
|
},
|
||||||
|
)
|
||||||
|
: insertedNode,
|
||||||
);
|
);
|
||||||
transaction.deleteNode(node);
|
transaction.deleteNode(node);
|
||||||
|
final path = calculatePath(selection.end.path, [insertedNode]);
|
||||||
|
final offset = calculateLength([insertedNode]);
|
||||||
transaction.afterSelection = Selection.collapsed(
|
transaction.afterSelection = Selection.collapsed(
|
||||||
Position(
|
Position(
|
||||||
path: selection.end.path,
|
path: path,
|
||||||
offset: insertedDelta?.length ?? 0,
|
offset: offset,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
} else {
|
} else if (insertedDelta != null) {
|
||||||
// if the node is not empty, insert the delta from inserted node after the selection.
|
// if the node is not empty, insert the delta from inserted node after the selection.
|
||||||
transaction.insertTextDelta(node, selection.endIndex, insertedDelta);
|
transaction.insertTextDelta(node, selection.endIndex, insertedDelta);
|
||||||
}
|
}
|
||||||
@ -53,7 +57,7 @@ extension PasteNodes on EditorState {
|
|||||||
}
|
}
|
||||||
final transaction = this.transaction;
|
final transaction = this.transaction;
|
||||||
|
|
||||||
final lastNodeLength = nodes.last.delta?.length ?? 0;
|
final lastNodeLength = calculateLength(nodes);
|
||||||
// merge the current selected node delta into the nodes.
|
// merge the current selected node delta into the nodes.
|
||||||
if (delta.isNotEmpty) {
|
if (delta.isNotEmpty) {
|
||||||
nodes.first.insertDelta(
|
nodes.first.insertDelta(
|
||||||
@ -86,13 +90,10 @@ extension PasteNodes on EditorState {
|
|||||||
// delete the current node.
|
// delete the current node.
|
||||||
transaction.deleteNode(node);
|
transaction.deleteNode(node);
|
||||||
|
|
||||||
var path = selection.end.path;
|
final path = calculatePath(selection.start.path, nodes);
|
||||||
for (var i = 0; i < nodes.length; i++) {
|
|
||||||
path = path.next;
|
|
||||||
}
|
|
||||||
transaction.afterSelection = Selection.collapsed(
|
transaction.afterSelection = Selection.collapsed(
|
||||||
Position(
|
Position(
|
||||||
path: path.previous, // because a node is deleted.
|
path: path,
|
||||||
offset: lastNodeLength,
|
offset: lastNodeLength,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -116,6 +117,28 @@ extension PasteNodes on EditorState {
|
|||||||
assert(this.selection?.isCollapsed == true);
|
assert(this.selection?.isCollapsed == true);
|
||||||
return this.selection;
|
return this.selection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Path calculatePath(Path start, List<Node> nodes) {
|
||||||
|
var path = start;
|
||||||
|
for (var i = 0; i < nodes.length; i++) {
|
||||||
|
path = path.next;
|
||||||
|
}
|
||||||
|
path = path.previous;
|
||||||
|
if (nodes.last.children.isNotEmpty) {
|
||||||
|
return [
|
||||||
|
...path,
|
||||||
|
...calculatePath([0], nodes.last.children.toList())
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
int calculateLength(List<Node> nodes) {
|
||||||
|
if (nodes.last.children.isNotEmpty) {
|
||||||
|
return calculateLength(nodes.last.children.toList());
|
||||||
|
}
|
||||||
|
return nodes.last.delta?.length ?? 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension on Node {
|
extension on Node {
|
||||||
|
@ -4,6 +4,7 @@ export 'callout/callout_block_component.dart';
|
|||||||
export 'code_block/code_block_component.dart';
|
export 'code_block/code_block_component.dart';
|
||||||
export 'code_block/code_block_shortcut_event.dart';
|
export 'code_block/code_block_shortcut_event.dart';
|
||||||
export 'copy_and_paste/custom_copy_command.dart';
|
export 'copy_and_paste/custom_copy_command.dart';
|
||||||
|
export 'copy_and_paste/custom_cut_command.dart';
|
||||||
export 'copy_and_paste/custom_paste_command.dart';
|
export 'copy_and_paste/custom_paste_command.dart';
|
||||||
export 'database/database_view_block_component.dart';
|
export 'database/database_view_block_component.dart';
|
||||||
export 'database/inline_database_menu_item.dart';
|
export 'database/inline_database_menu_item.dart';
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import 'dart:convert';
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:appflowy/env/env.dart';
|
import 'package:appflowy/env/env.dart';
|
||||||
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
||||||
@ -65,7 +65,7 @@ class SettingsUserView extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Renders either a login or logout button based on the user's authentication status.
|
/// Renders either a login or logout button based on the user's authentication status, or nothing if Supabase is not enabled.
|
||||||
///
|
///
|
||||||
/// This function checks the current user's authentication type and Supabase
|
/// This function checks the current user's authentication type and Supabase
|
||||||
/// configuration to determine whether to render a third-party login button
|
/// configuration to determine whether to render a third-party login button
|
||||||
@ -74,14 +74,17 @@ class SettingsUserView extends StatelessWidget {
|
|||||||
BuildContext context,
|
BuildContext context,
|
||||||
SettingsUserState state,
|
SettingsUserState state,
|
||||||
) {
|
) {
|
||||||
if (isSupabaseEnabled) {
|
if (!isSupabaseEnabled) {
|
||||||
// If the user is logged in locally, render a third-party login button.
|
return const SizedBox.shrink();
|
||||||
if (state.userProfile.authType == AuthTypePB.Local) {
|
|
||||||
return SettingThirdPartyLogin(
|
|
||||||
didLogin: didLogin,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the user is logged in locally, render a third-party login button.
|
||||||
|
if (state.userProfile.authType == AuthTypePB.Local) {
|
||||||
|
return SettingThirdPartyLogin(
|
||||||
|
didLogin: didLogin,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return SettingLogoutButton(user: user, didLogout: didLogout);
|
return SettingLogoutButton(user: user, didLogout: didLogout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,8 +54,8 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
path: "."
|
path: "."
|
||||||
ref: "56474e8b"
|
ref: f4db21c
|
||||||
resolved-ref: "56474e8bd9f08be7090495c255eea20a694ab1f3"
|
resolved-ref: f4db21c3678290d133ae6cffa015d3d79920bf84
|
||||||
url: "https://github.com/AppFlowy-IO/appflowy-editor.git"
|
url: "https://github.com/AppFlowy-IO/appflowy-editor.git"
|
||||||
source: git
|
source: git
|
||||||
version: "1.2.3"
|
version: "1.2.3"
|
||||||
@ -1451,18 +1451,18 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: super_clipboard
|
name: super_clipboard
|
||||||
sha256: "204284b1a721d33a65bcab077b191a3b7379b46a231f05688d17220153338ede"
|
sha256: ba484eb42ce621b69241d18d2a8494109589e8796eb6a3399e6c8f9cdaab8303
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.6.0"
|
version: "0.6.3"
|
||||||
super_native_extensions:
|
super_native_extensions:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: super_native_extensions
|
name: super_native_extensions
|
||||||
sha256: "1f15e9b1adb0bc59cf9b889a0b248f3c192fa17e2d5c923aeeec6d4fa2eeffd6"
|
sha256: dfe0a1c74430db946be973878da3f8611b8f124137f1dcbdf883e4605db40bd8
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.6.0"
|
version: "0.6.3"
|
||||||
sync_http:
|
sync_http:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -15,7 +15,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
|
|||||||
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
|
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
|
||||||
# Read more about iOS versioning at
|
# Read more about iOS versioning at
|
||||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||||
version: 0.2.9
|
version: 0.3.0
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=3.0.0 <4.0.0"
|
sdk: ">=3.0.0 <4.0.0"
|
||||||
@ -48,7 +48,7 @@ dependencies:
|
|||||||
appflowy_editor:
|
appflowy_editor:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/AppFlowy-IO/appflowy-editor.git
|
url: https://github.com/AppFlowy-IO/appflowy-editor.git
|
||||||
ref: 56474e8b
|
ref: f4db21c
|
||||||
appflowy_popover:
|
appflowy_popover:
|
||||||
path: packages/appflowy_popover
|
path: packages/appflowy_popover
|
||||||
|
|
||||||
@ -107,7 +107,7 @@ dependencies:
|
|||||||
url_protocol:
|
url_protocol:
|
||||||
hive: ^2.2.3
|
hive: ^2.2.3
|
||||||
hive_flutter: ^1.1.0
|
hive_flutter: ^1.1.0
|
||||||
super_clipboard: ^0.6.0
|
super_clipboard: ^0.6.3
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_lints: ^2.0.1
|
flutter_lints: ^2.0.1
|
||||||
|
Reference in New Issue
Block a user