feat: add new database on mobile platform (#3788)

* chore: downgrade clipboard package

* fix: update i18n in the favorite page

* fix: update the favorite icon

* feat: support add new database

* chore: disable cache in unit test

* chore: bump version 0.3.7
This commit is contained in:
Lucas.Xu 2023-10-26 11:57:14 +08:00 committed by GitHub
parent 8c3984d21a
commit 9416ba1bfc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 324 additions and 70 deletions

View File

@ -181,17 +181,12 @@ jobs:
fi
shell: bash
- uses: actions/download-artifact@v3
with:
name: ${{ github.run_id }}-${{ matrix.os }}
- name: Uncompress appflowy_flutter
run: tar -xf appflowy_flutter.tar.gz
- name: Run Flutter unit tests
working-directory: frontend
run: |
if [ "$RUNNER_OS" == "macOS" ]; then
flutter config --enable-macos-desktop
cargo make --profile ${{ matrix.flutter_profile }} appflowy-dev
cargo make dart_unit_test
else
cargo make dart_unit_test_no_build

View File

@ -25,7 +25,7 @@ CARGO_MAKE_EXTEND_WORKSPACE_MAKEFILE = true
CARGO_MAKE_CRATE_FS_NAME = "dart_ffi"
CARGO_MAKE_CRATE_NAME = "dart-ffi"
LIB_NAME = "dart_ffi"
CURRENT_APP_VERSION = "0.3.6"
CURRENT_APP_VERSION = "0.3.7"
FLUTTER_DESKTOP_FEATURES = "dart,rev-sqlite"
PRODUCT_NAME = "AppFlowy"
# CRATE_TYPE: https://doc.rust-lang.org/reference/linkage.html

View File

@ -1,6 +1,7 @@
import 'package:appflowy/mobile/presentation/bottom_sheet/mobile_bottom_sheet_body.dart';
import 'package:appflowy/mobile/presentation/bottom_sheet/mobile_bottom_sheet_rename_widget.dart';
import 'package:appflowy/mobile/presentation/bottom_sheet/mobile_bottom_sheet_view_item_header.dart';
import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet_drag_handler.dart';
import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet_rename_widget.dart';
import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet_view_item_body.dart';
import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet_view_item_header.dart';
import 'package:appflowy/workspace/application/favorite/favorite_bloc.dart';
import 'package:appflowy/workspace/application/view/view_bloc.dart';
import 'package:appflowy_backend/protobuf/flowy-folder2/protobuf.dart';
@ -36,11 +37,11 @@ enum MobileBottomSheetType {
class MobileViewItemBottomSheet extends StatefulWidget {
const MobileViewItemBottomSheet({
super.key,
this.view,
required this.view,
this.defaultType = MobileBottomSheetType.view,
});
final ViewPB? view;
final ViewPB view;
final MobileBottomSheetType defaultType;
@override
@ -56,11 +57,6 @@ class _MobileViewItemBottomSheetState extends State<MobileViewItemBottomSheet> {
super.initState();
type = widget.defaultType;
if ([MobileBottomSheetType.view, MobileBottomSheetType.rename]
.contains(type)) {
assert(widget.view != null);
}
}
@override
@ -69,17 +65,7 @@ class _MobileViewItemBottomSheetState extends State<MobileViewItemBottomSheet> {
mainAxisSize: MainAxisSize.min,
children: [
// drag handler
Padding(
padding: const EdgeInsets.only(top: 12, bottom: 12.0),
child: Container(
width: 64,
height: 4,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(2.0),
color: Colors.grey,
),
),
),
const MobileBottomSheetDragHandler(),
// header
_buildHeader(),
@ -100,7 +86,7 @@ class _MobileViewItemBottomSheetState extends State<MobileViewItemBottomSheet> {
// header
return MobileViewItemBottomSheetHeader(
showBackButton: type != MobileBottomSheetType.view,
view: widget.view!,
view: widget.view,
onBack: () {
setState(() {
type = MobileBottomSheetType.view;
@ -114,7 +100,7 @@ class _MobileViewItemBottomSheetState extends State<MobileViewItemBottomSheet> {
switch (type) {
case MobileBottomSheetType.view:
return MobileViewItemBottomSheetBody(
isFavorite: widget.view!.isFavorite,
isFavorite: widget.view.isFavorite,
onAction: (action) {
switch (action) {
case MobileViewItemBottomSheetBodyAction.rename:
@ -138,7 +124,7 @@ class _MobileViewItemBottomSheetState extends State<MobileViewItemBottomSheet> {
case MobileViewItemBottomSheetBodyAction.removeFromFavorites:
context
.read<FavoriteBloc>()
.add(FavoriteEvent.toggle(widget.view!));
.add(FavoriteEvent.toggle(widget.view));
context.pop();
break;
}
@ -146,9 +132,9 @@ class _MobileViewItemBottomSheetState extends State<MobileViewItemBottomSheet> {
);
case MobileBottomSheetType.rename:
return MobileBottomSheetRenameWidget(
name: widget.view!.name,
name: widget.view.name,
onRename: (name) {
if (name != widget.view!.name) {
if (name != widget.view.name) {
context.read<ViewBloc>().add(ViewEvent.rename(name));
}
context.pop();

View File

@ -0,0 +1,105 @@
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_action_widget.dart';
import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet_drag_handler.dart';
import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet_view_item_header.dart';
import 'package:appflowy_backend/protobuf/flowy-folder2/protobuf.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flutter/material.dart';
class AddNewPageWidgetBottomSheet extends StatelessWidget {
const AddNewPageWidgetBottomSheet({
super.key,
required this.view,
required this.onAction,
});
final ViewPB view;
final void Function(ViewLayoutPB layout) onAction;
@override
Widget build(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
// drag handler
const MobileBottomSheetDragHandler(),
// header
MobileViewItemBottomSheetHeader(
showBackButton: false,
view: view,
onBack: () {},
),
const VSpace(8.0),
const Divider(),
// body
_AddNewPageBody(
onAction: onAction,
),
const VSpace(24.0),
],
);
}
}
class _AddNewPageBody extends StatelessWidget {
const _AddNewPageBody({
required this.onAction,
});
final void Function(ViewLayoutPB layout) onAction;
@override
Widget build(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
// rename, duplicate
Row(
mainAxisSize: MainAxisSize.min,
children: [
Expanded(
child: BottomSheetActionWidget(
svg: FlowySvgs.documents_s,
text: LocaleKeys.newDocumentText.tr(),
onTap: () => onAction(ViewLayoutPB.Document),
),
),
Expanded(
child: BottomSheetActionWidget(
svg: FlowySvgs.grid_s,
text: LocaleKeys.newGridText.tr(),
onTap: () => onAction(ViewLayoutPB.Grid),
),
),
],
),
// share, delete
Row(
mainAxisSize: MainAxisSize.min,
children: [
Expanded(
child: BottomSheetActionWidget(
svg: FlowySvgs.board_s,
text: LocaleKeys.newBoardText.tr(),
onTap: () => onAction(ViewLayoutPB.Board),
),
),
Expanded(
child: BottomSheetActionWidget(
svg: FlowySvgs.date_s,
text: LocaleKeys.newCalendarText.tr(),
onTap: () => onAction(ViewLayoutPB.Calendar),
),
),
],
),
],
);
}
}

View File

@ -0,0 +1,20 @@
import 'package:flutter/material.dart';
class MobileBottomSheetDragHandler extends StatelessWidget {
const MobileBottomSheetDragHandler({super.key});
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(top: 12, bottom: 12.0),
child: Container(
width: 64,
height: 4,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(2.0),
color: Colors.grey,
),
),
);
}
}

View File

@ -0,0 +1,126 @@
import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet_drag_handler.dart';
import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet_rename_widget.dart';
import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet_view_item_body.dart';
import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet_view_item_header.dart';
import 'package:appflowy/workspace/application/favorite/favorite_bloc.dart';
import 'package:appflowy/workspace/application/view/view_bloc.dart';
import 'package:appflowy_backend/protobuf/flowy-folder2/protobuf.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart' hide WidgetBuilder;
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:go_router/go_router.dart';
enum MobileBottomSheetType {
view,
rename,
}
class MobileViewItemBottomSheet extends StatefulWidget {
const MobileViewItemBottomSheet({
super.key,
required this.view,
this.defaultType = MobileBottomSheetType.view,
});
final ViewPB view;
final MobileBottomSheetType defaultType;
@override
State<MobileViewItemBottomSheet> createState() =>
_MobileViewItemBottomSheetState();
}
class _MobileViewItemBottomSheetState extends State<MobileViewItemBottomSheet> {
MobileBottomSheetType type = MobileBottomSheetType.view;
@override
initState() {
super.initState();
type = widget.defaultType;
}
@override
Widget build(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
// drag handler
const MobileBottomSheetDragHandler(),
// header
_buildHeader(),
const VSpace(8.0),
const Divider(),
// body
_buildBody(),
const VSpace(24.0),
],
);
}
Widget _buildHeader() {
switch (type) {
case MobileBottomSheetType.view:
case MobileBottomSheetType.rename:
// header
return MobileViewItemBottomSheetHeader(
showBackButton: type != MobileBottomSheetType.view,
view: widget.view,
onBack: () {
setState(() {
type = MobileBottomSheetType.view;
});
},
);
}
}
Widget _buildBody() {
switch (type) {
case MobileBottomSheetType.view:
return MobileViewItemBottomSheetBody(
isFavorite: widget.view.isFavorite,
onAction: (action) {
switch (action) {
case MobileViewItemBottomSheetBodyAction.rename:
setState(() {
type = MobileBottomSheetType.rename;
});
break;
case MobileViewItemBottomSheetBodyAction.duplicate:
context.read<ViewBloc>().add(const ViewEvent.duplicate());
context.pop();
break;
case MobileViewItemBottomSheetBodyAction.share:
// unimplemented
context.pop();
break;
case MobileViewItemBottomSheetBodyAction.delete:
context.read<ViewBloc>().add(const ViewEvent.delete());
context.pop();
break;
case MobileViewItemBottomSheetBodyAction.addToFavorites:
case MobileViewItemBottomSheetBodyAction.removeFromFavorites:
context
.read<FavoriteBloc>()
.add(FavoriteEvent.toggle(widget.view));
context.pop();
break;
}
},
);
case MobileBottomSheetType.rename:
return MobileBottomSheetRenameWidget(
name: widget.view.name,
onRename: (name) {
if (name != widget.view.name) {
context.read<ViewBloc>().add(ViewEvent.rename(name));
}
context.pop();
},
);
}
}
}

View File

@ -1,6 +1,6 @@
import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/mobile/presentation/bottom_sheet/mobile_bottom_sheet_action_widget.dart';
import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet_action_widget.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';

View File

@ -1,5 +1,5 @@
import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy/mobile/presentation/bottom_sheet/mobile_bottom_sheet.dart';
import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet.dart';
import 'package:appflowy/mobile/presentation/page_item/mobile_slide_action_button.dart';
import 'package:appflowy/workspace/application/favorite/favorite_bloc.dart';
import 'package:appflowy/workspace/application/view/view_bloc.dart';

View File

@ -1,9 +1,12 @@
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/mobile/application/mobile_router.dart';
import 'package:appflowy/mobile/presentation/error/error_page.dart';
import 'package:appflowy/mobile/presentation/home/favorite_folder/mobile_home_favorite_folder.dart';
import 'package:appflowy/workspace/application/favorite/favorite_bloc.dart';
import 'package:appflowy/workspace/application/menu/menu_bloc.dart';
import 'package:appflowy_backend/protobuf/flowy-folder2/protobuf.dart';
import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
@ -46,9 +49,13 @@ class MobileFavoritePageFolder extends StatelessWidget {
builder: (context) {
final favoriteState = context.watch<FavoriteBloc>().state;
if (favoriteState.views.isEmpty) {
return const Center(
// todo: i18n
child: FlowyText('No favorite pages'),
return MobileErrorPage(
header: const FlowyText.semibold(
'😁',
fontSize: 50,
),
title: LocaleKeys.favorite_noFavorite.tr(),
message: LocaleKeys.favorite_noFavoriteHintText.tr(),
);
}
return SlidableAutoCloseBehavior(

View File

@ -3,6 +3,7 @@ import 'package:appflowy/mobile/presentation/bottom_sheet/default_mobile_action_
import 'package:appflowy/mobile/presentation/home/favorite_folder/mobile_home_favorite_folder_header.dart';
import 'package:appflowy/mobile/presentation/page_item/mobile_view_item.dart';
import 'package:appflowy/workspace/application/sidebar/folder/folder_bloc.dart';
import 'package:appflowy/workspace/application/view/view_bloc.dart';
import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flutter/material.dart';
@ -66,7 +67,9 @@ class MobileFavoriteFolder extends StatelessWidget {
await context.pushView(view);
},
endActionPane: (context) => buildEndActionPane(context, [
MobilePaneActionType.removeFromFavorites,
context.read<ViewBloc>().view.isFavorite
? MobilePaneActionType.removeFromFavorites
: MobilePaneActionType.addToFavorites,
MobilePaneActionType.more,
]),
),

View File

@ -1,8 +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/mobile_bottom_sheet_action_widget.dart';
import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet_action_widget.dart';
import 'package:appflowy/mobile/presentation/widgets/show_flowy_mobile_bottom_sheet.dart';
import 'package:appflowy/plugins/trash/application/prelude.dart';
import 'package:appflowy/startup/startup.dart';
import 'package:easy_localization/easy_localization.dart';

View File

@ -1,5 +1,7 @@
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/mobile/application/mobile_router.dart';
import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet.dart';
import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet_add_new_page.dart';
import 'package:appflowy/mobile/presentation/page_item/mobile_view_item_add_button.dart';
import 'package:appflowy/workspace/application/sidebar/folder/folder_bloc.dart';
import 'package:appflowy/workspace/application/view/view_bloc.dart';
@ -11,6 +13,7 @@ import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_slidable/flutter_slidable.dart';
import 'package:go_router/go_router.dart';
typedef ViewItemOnSelected = void Function(ViewPB);
typedef ActionPaneBuilder = ActionPane Function(BuildContext context);
@ -359,7 +362,7 @@ class _SingleMobileInnerViewItemState extends State<SingleMobileInnerViewItem> {
return GestureDetector(
child: AnimatedRotation(
duration: const Duration(milliseconds: 200),
duration: const Duration(milliseconds: 300),
turns: widget.isExpanded ? 0 : -0.25,
child: const Icon(
Icons.keyboard_arrow_down_rounded,
@ -378,12 +381,27 @@ class _SingleMobileInnerViewItemState extends State<SingleMobileInnerViewItem> {
Widget _buildViewAddButton(BuildContext context) {
return MobileViewAddButton(
onPressed: () {
context.read<ViewBloc>().add(
ViewEvent.createView(
LocaleKeys.menuAppHeader_defaultNewPageName.tr(),
ViewLayoutPB.Document,
),
);
showMobileBottomSheet(
context: context,
builder: (_) => AddNewPageWidgetBottomSheet(
view: widget.view,
onAction: (layout) {
context.pop();
context.read<ViewBloc>().add(
ViewEvent.createView(
LocaleKeys.menuAppHeader_defaultNewPageName.tr(),
layout,
),
);
},
),
);
// context.read<ViewBloc>().add(
// ViewEvent.createView(
// LocaleKeys.menuAppHeader_defaultNewPageName.tr(),
// ViewLayoutPB.Document,
// ),
// );
},
);
}

View File

@ -748,10 +748,10 @@ packages:
dependency: transitive
description:
name: irondash_engine_context
sha256: f66a1af95756d5fece5034d357853d0127e09b9e4ef58be1f022ca47e11c6f7e
sha256: fea21bff36d44a5955beba90619f54b9169884014128ae75f50eba2db03c24a0
url: "https://pub.dev"
source: hosted
version: "0.4.0"
version: "0.3.1"
irondash_message_channel:
dependency: transitive
description:
@ -1429,14 +1429,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.9.1"
sprintf:
dependency: transitive
description:
name: sprintf
sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23"
url: "https://pub.dev"
source: hosted
version: "7.0.0"
stack_trace:
dependency: transitive
description:
@ -1514,18 +1506,18 @@ packages:
dependency: "direct main"
description:
name: super_clipboard
sha256: "67496ce89d45e63960541b4907557e7138ee80d1c68a59d87e4d67310eeadbb6"
sha256: "548642d62d691d2ba00850efe0f7a11ce5696e59111658abd4c6cb76b49aa61d"
url: "https://pub.dev"
source: hosted
version: "0.7.1"
version: "0.6.4"
super_native_extensions:
dependency: transitive
description:
name: super_native_extensions
sha256: e9ff692aa13c3d489220c9be3c85653fb8b1c7e39ba5fe4c8dcee7f97c0e4337
sha256: "3bbb95899f848617b819eec1fa00c80a617f1bd469a480b1f0c4dd383da4c5ec"
url: "https://pub.dev"
source: hosted
version: "0.7.1"
version: "0.6.4"
sync_http:
dependency: transitive
description:
@ -1728,13 +1720,13 @@ packages:
source: git
version: "1.0.0"
uuid:
dependency: "direct overridden"
dependency: transitive
description:
name: uuid
sha256: b715b8d3858b6fa9f68f87d20d98830283628014750c2b09b6f516c1da4af2a7
sha256: "648e103079f7c64a36dc7d39369cabb358d377078a051d6ae2ad3aa539519313"
url: "https://pub.dev"
source: hosted
version: "4.1.0"
version: "3.0.7"
vector_graphics:
dependency: transitive
description:

View File

@ -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.
# Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 0.3.6
version: 0.3.7
environment:
sdk: ">=3.0.0 <4.0.0"
@ -103,7 +103,7 @@ dependencies:
url_protocol:
hive: ^2.2.3
hive_flutter: ^1.1.0
super_clipboard: ^0.7.1
super_clipboard: ^0.6.3
go_router: ^10.1.2
string_validator: ^1.0.0
unsplash_client: ^2.1.1
@ -134,7 +134,6 @@ dev_dependencies:
dependency_overrides:
http: ^1.0.0
uuid: ^4.1.0
supabase_flutter:
git:

View File

@ -1005,5 +1005,9 @@
"colClear": "Clear Content",
"rowClear": "Clear Content",
"slashPlaceHolder": "Enter a / to insert a block, or start typing"
},
"favorite": {
"noFavorite": "No favorite page",
"noFavoriteHintText": "slide the page to the left to add it to favorites"
}
}

View File

@ -28,7 +28,7 @@ script = [
rustup show
if [ "${BUILD_FLAG}" == "debug" ]; then
echo "🚀 🚀 🚀 Building for debug"
cargo lipo --targets ${RUST_COMPILE_TARGET} --features "${FLUTTER_DESKTOP_FEATURES} --package=dart-ffi "
cargo lipo --targets ${RUST_COMPILE_TARGET} --features "${FLUTTER_DESKTOP_FEATURES}" --package=dart-ffi
else
echo "🚀 🚀 🚀 Building for release"
cargo lipo --release --targets ${RUST_COMPILE_TARGET} --features "${FLUTTER_DESKTOP_FEATURES}" --package=dart-ffi