mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
feat:IInline math equation (#2949)
This commit is contained in:
parent
4c17298432
commit
ff9b3c56c5
2
.github/workflows/flutter_ci.yaml
vendored
2
.github/workflows/flutter_ci.yaml
vendored
@ -134,6 +134,6 @@ jobs:
|
|||||||
fail_ci_if_error: true
|
fail_ci_if_error: true
|
||||||
verbose: true
|
verbose: true
|
||||||
os: ${{ matrix.os }}
|
os: ${{ matrix.os }}
|
||||||
attempt_limit: 5
|
attempt_limit: 20
|
||||||
attempt_delay: 10000
|
attempt_delay: 10000
|
||||||
|
|
||||||
|
37
.github/workflows/integration_test.yml
vendored
37
.github/workflows/integration_test.yml
vendored
@ -29,25 +29,31 @@ concurrency:
|
|||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
tests:
|
build:
|
||||||
if: github.event.pull_request.draft != true
|
if: github.event.pull_request.draft != true
|
||||||
strategy:
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-latest, windows-latest]
|
os: [ubuntu-latest, windows-latest]
|
||||||
|
include:
|
||||||
|
- os: ubuntu-latest
|
||||||
|
flutter_profile: development-linux-x86_64
|
||||||
|
target: x86_64-unknown-linux-gnu
|
||||||
|
- os: windows-latest
|
||||||
|
flutter_profile: development-windows-x86
|
||||||
|
target: x86_64-pc-windows-msvc
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- name: Checkout source code
|
||||||
- uses: actions-rs/toolchain@v1
|
uses: actions/checkout@v2
|
||||||
with:
|
|
||||||
toolchain: "stable-2022-04-07"
|
|
||||||
|
|
||||||
- name: Install Rust toolchain
|
- name: Install Rust toolchain
|
||||||
id: rust_toolchain
|
id: rust_toolchain
|
||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
toolchain: ${{ env.RUST_TOOLCHAIN }}
|
toolchain: ${{ env.RUST_TOOLCHAIN }}
|
||||||
|
target: ${{ matrix.target }}
|
||||||
override: true
|
override: true
|
||||||
profile: minimal
|
profile: minimal
|
||||||
|
|
||||||
@ -64,6 +70,7 @@ jobs:
|
|||||||
prefix-key: ${{ matrix.os }}
|
prefix-key: ${{ matrix.os }}
|
||||||
workspaces: |
|
workspaces: |
|
||||||
frontend/rust-lib
|
frontend/rust-lib
|
||||||
|
cache-all-crates: true
|
||||||
|
|
||||||
- uses: davidB/rust-cargo-make@v1
|
- uses: davidB/rust-cargo-make@v1
|
||||||
with:
|
with:
|
||||||
@ -87,30 +94,24 @@ jobs:
|
|||||||
cargo make appflowy-flutter-deps-tools
|
cargo make appflowy-flutter-deps-tools
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
||||||
- name: Config Flutter
|
- name: Enable Flutter Desktop
|
||||||
run: |
|
run: |
|
||||||
if [ "$RUNNER_OS" == "Linux" ]; then
|
if [ "$RUNNER_OS" == "Linux" ]; then
|
||||||
flutter config --enable-linux-desktop
|
flutter config --enable-linux-desktop
|
||||||
elif [ "$RUNNER_OS" == "macOS" ]; then
|
elif [ "$RUNNER_OS" == "macOS" ]; then
|
||||||
flutter config --enable-macos-desktop
|
flutter config --enable-macos-desktop
|
||||||
elif [ "$RUNNER_OS" == "Windows" ]; then
|
elif [ "$RUNNER_OS" == "Windows" ]; then
|
||||||
|
git config --system core.longpaths true
|
||||||
flutter config --enable-windows-desktop
|
flutter config --enable-windows-desktop
|
||||||
fi
|
fi
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
||||||
- name: Build Test lib
|
- name: Build AppFlowy
|
||||||
working-directory: frontend
|
working-directory: frontend
|
||||||
run: |
|
run: |
|
||||||
if [ "$RUNNER_OS" == "Linux" ]; then
|
cargo make --profile ${{ matrix.flutter_profile }} appflowy-dev
|
||||||
cargo make --profile development-linux-x86_64 appflowy-dev
|
|
||||||
elif [ "$RUNNER_OS" == "macOS" ]; then
|
|
||||||
cargo make --profile development-mac-x86_64 appflowy-dev
|
|
||||||
elif [ "$RUNNER_OS" == "Windows" ]; then
|
|
||||||
cargo make --profile development-windows-x86 appflowy-dev
|
|
||||||
fi
|
|
||||||
shell: bash
|
|
||||||
|
|
||||||
- name: Run AppFlowy tests
|
- name: Run Flutter integration tests
|
||||||
working-directory: frontend/appflowy_flutter
|
working-directory: frontend/appflowy_flutter
|
||||||
run: |
|
run: |
|
||||||
if [ "$RUNNER_OS" == "Linux" ]; then
|
if [ "$RUNNER_OS" == "Linux" ]; then
|
||||||
@ -135,5 +136,5 @@ jobs:
|
|||||||
fail_ci_if_error: true
|
fail_ci_if_error: true
|
||||||
verbose: true
|
verbose: true
|
||||||
os: ${{ matrix.os }}
|
os: ${{ matrix.os }}
|
||||||
attempt_limit: 5
|
attempt_limit: 20
|
||||||
attempt_delay: 10000
|
attempt_delay: 10000
|
1
frontend/appflowy_flutter/assets/images/editor/math.svg
Normal file
1
frontend/appflowy_flutter/assets/images/editor/math.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30" style="width: 16px; height: 16px; display: block; fill: inherit; flex-shrink: 0; backface-visibility: hidden;" width="30" height="30" ><path d="M6.04883 27.3232C7.24219 27.3232 7.86426 26.4854 8.20703 25.3936L13.9834 6.79492H27.5039C28.2275 6.79492 28.7227 6.35059 28.7227 5.65234C28.7227 4.97949 28.2275 4.53516 27.5039 4.53516H13.958C12.6631 4.53516 12.0791 5.01758 11.7363 6.13477L6.18848 24.3525H5.97266L3.58594 15.9355C3.38281 15.2373 3.00195 14.9072 2.40527 14.9072C1.73242 14.9072 1.2373 15.3896 1.2373 16.0117C1.2373 16.2656 1.30078 16.4941 1.35156 16.6846L4.04297 25.5332C4.36035 26.5615 4.93164 27.3232 6.04883 27.3232ZM16.3955 24.7334C16.8652 24.7334 17.1064 24.5684 17.4619 24.0732L20.4707 19.8203H20.5215L23.5049 24.0732C23.873 24.5684 24.1143 24.7334 24.5713 24.7334C25.2061 24.7334 25.6758 24.3018 25.6758 23.7051C25.6758 23.4258 25.6123 23.1973 25.4219 22.9561L21.9307 18.208L25.4473 13.4346C25.6377 13.168 25.7139 12.9395 25.7139 12.6855C25.7139 12.127 25.2568 11.6953 24.6475 11.6953C24.2031 11.6953 23.9365 11.8477 23.6064 12.3174L20.7246 16.5957H20.6611L17.6904 12.3047C17.373 11.8477 17.0938 11.6953 16.624 11.6953C16.0146 11.6953 15.5068 12.165 15.5068 12.7363C15.5068 13.0537 15.583 13.2568 15.8115 13.5488L19.1504 18.1445L15.6084 23.0322C15.418 23.2861 15.3672 23.4639 15.3672 23.7559C15.3672 24.3018 15.8115 24.7334 16.3955 24.7334Z" fill="#2F3030"></path></svg>
|
After Width: | Height: | Size: 1.5 KiB |
@ -426,6 +426,7 @@
|
|||||||
"smartEditCouldNotFetchKey": "Could not fetch OpenAI key",
|
"smartEditCouldNotFetchKey": "Could not fetch OpenAI key",
|
||||||
"smartEditDisabled": "Connect OpenAI in Settings",
|
"smartEditDisabled": "Connect OpenAI in Settings",
|
||||||
"discardResponse": "Do you want to discard the AI responses?",
|
"discardResponse": "Do you want to discard the AI responses?",
|
||||||
|
"createInlineMathEquation": "Create equation",
|
||||||
"cover": {
|
"cover": {
|
||||||
"changeCover": "Change Cover",
|
"changeCover": "Change Cover",
|
||||||
"colors": "Colors",
|
"colors": "Colors",
|
||||||
|
@ -107,7 +107,7 @@ void main() {
|
|||||||
|
|
||||||
// Make sure that the event is edited
|
// Make sure that the event is edited
|
||||||
tester.assertNumberOfEventsInCalendar(1, title: 'hello world');
|
tester.assertNumberOfEventsInCalendar(1, title: 'hello world');
|
||||||
tester.assertNumberofEventsOnSpecificDay(2, DateTime.now());
|
tester.assertNumberOfEventsOnSpecificDay(2, DateTime.now());
|
||||||
|
|
||||||
// Click on the event
|
// Click on the event
|
||||||
await tester.openCalendarEvent(index: 1);
|
await tester.openCalendarEvent(index: 1);
|
||||||
@ -119,7 +119,7 @@ void main() {
|
|||||||
|
|
||||||
// Check that there are 2 events
|
// Check that there are 2 events
|
||||||
tester.assertNumberOfEventsInCalendar(2, title: 'hello world');
|
tester.assertNumberOfEventsInCalendar(2, title: 'hello world');
|
||||||
tester.assertNumberofEventsOnSpecificDay(3, DateTime.now());
|
tester.assertNumberOfEventsOnSpecificDay(3, DateTime.now());
|
||||||
|
|
||||||
// Delete an event
|
// Delete an event
|
||||||
await tester.openCalendarEvent(index: 1);
|
await tester.openCalendarEvent(index: 1);
|
||||||
@ -127,7 +127,7 @@ void main() {
|
|||||||
|
|
||||||
// Check that there is 1 event
|
// Check that there is 1 event
|
||||||
tester.assertNumberOfEventsInCalendar(1, title: 'hello world');
|
tester.assertNumberOfEventsInCalendar(1, title: 'hello world');
|
||||||
tester.assertNumberofEventsOnSpecificDay(2, DateTime.now());
|
tester.assertNumberOfEventsOnSpecificDay(2, DateTime.now());
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('rescheduling events', (tester) async {
|
testWidgets('rescheduling events', (tester) async {
|
||||||
@ -150,7 +150,7 @@ void main() {
|
|||||||
// Make sure that the event has been rescheduled to the new date
|
// Make sure that the event has been rescheduled to the new date
|
||||||
final sameDayNextWeek = firstOfThisMonth.add(const Duration(days: 7));
|
final sameDayNextWeek = firstOfThisMonth.add(const Duration(days: 7));
|
||||||
tester.assertNumberOfEventsInCalendar(1);
|
tester.assertNumberOfEventsInCalendar(1);
|
||||||
tester.assertNumberofEventsOnSpecificDay(1, sameDayNextWeek);
|
tester.assertNumberOfEventsOnSpecificDay(1, sameDayNextWeek);
|
||||||
|
|
||||||
// Delete the event
|
// Delete the event
|
||||||
await tester.openCalendarEvent(index: 0, date: sameDayNextWeek);
|
await tester.openCalendarEvent(index: 0, date: sameDayNextWeek);
|
||||||
@ -162,7 +162,7 @@ void main() {
|
|||||||
await tester.dismissRowDetailPage();
|
await tester.dismissRowDetailPage();
|
||||||
|
|
||||||
// Make sure that the event is today
|
// Make sure that the event is today
|
||||||
tester.assertNumberofEventsOnSpecificDay(1, today);
|
tester.assertNumberOfEventsOnSpecificDay(1, today);
|
||||||
|
|
||||||
// Click on the event
|
// Click on the event
|
||||||
await tester.openCalendarEvent(index: 0);
|
await tester.openCalendarEvent(index: 0);
|
||||||
@ -183,7 +183,7 @@ void main() {
|
|||||||
|
|
||||||
// Make sure that the event is edited
|
// Make sure that the event is edited
|
||||||
tester.assertNumberOfEventsInCalendar(1);
|
tester.assertNumberOfEventsInCalendar(1);
|
||||||
tester.assertNumberofEventsOnSpecificDay(1, newDate);
|
tester.assertNumberOfEventsOnSpecificDay(1, newDate);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -172,9 +172,10 @@ void main() {
|
|||||||
// Focus on the editor
|
// Focus on the editor
|
||||||
final textBlock = find.byType(TextBlockComponentWidget);
|
final textBlock = find.byType(TextBlockComponentWidget);
|
||||||
await tester.tapAt(tester.getCenter(textBlock));
|
await tester.tapAt(tester.getCenter(textBlock));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
// Input some text
|
// Input some text
|
||||||
const inputText = 'Hello world';
|
const inputText = 'Hello World';
|
||||||
await tester.ime.insertText(inputText);
|
await tester.ime.insertText(inputText);
|
||||||
expect(
|
expect(
|
||||||
find.textContaining(inputText, findRichText: true),
|
find.textContaining(inputText, findRichText: true),
|
||||||
|
@ -10,6 +10,8 @@ void main() {
|
|||||||
group('database', () {
|
group('database', () {
|
||||||
testWidgets('import v0.2.0 database data', (tester) async {
|
testWidgets('import v0.2.0 database data', (tester) async {
|
||||||
await tester.openV020database();
|
await tester.openV020database();
|
||||||
|
// wait the database data is loaded
|
||||||
|
await tester.pumpAndSettle(const Duration(microseconds: 500));
|
||||||
|
|
||||||
// check the text cell
|
// check the text cell
|
||||||
final textCells = <String>['A', 'B', 'C', 'D', 'E', '', '', '', '', ''];
|
final textCells = <String>['A', 'B', 'C', 'D', 'E', '', '', '', '', ''];
|
||||||
|
@ -9,7 +9,7 @@ import '../util/util.dart';
|
|||||||
void main() {
|
void main() {
|
||||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||||
|
|
||||||
group('document', () {
|
group('create and delete the document', () {
|
||||||
testWidgets('create a new document when launching app in first time',
|
testWidgets('create a new document when launching app in first time',
|
||||||
(tester) async {
|
(tester) async {
|
||||||
await tester.initializeAppFlowy();
|
await tester.initializeAppFlowy();
|
@ -0,0 +1,22 @@
|
|||||||
|
import 'package:integration_test/integration_test.dart';
|
||||||
|
|
||||||
|
import 'document_create_and_delete_test.dart'
|
||||||
|
as document_create_and_delete_test;
|
||||||
|
import 'document_with_cover_image_test.dart' as document_with_cover_image_test;
|
||||||
|
import 'document_with_database_test.dart' as document_with_database_test;
|
||||||
|
import 'document_with_inline_math_equation_test.dart'
|
||||||
|
as document_with_inline_math_equation_test;
|
||||||
|
import 'document_with_inline_page_test.dart' as document_with_inline_page_test;
|
||||||
|
import 'edit_document_test.dart' as document_edit_test;
|
||||||
|
|
||||||
|
void startTesting() {
|
||||||
|
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||||
|
|
||||||
|
// Document integration tests
|
||||||
|
document_create_and_delete_test.main();
|
||||||
|
document_edit_test.main();
|
||||||
|
document_with_database_test.main();
|
||||||
|
document_with_inline_page_test.main();
|
||||||
|
document_with_inline_math_equation_test.main();
|
||||||
|
document_with_cover_image_test.main();
|
||||||
|
}
|
@ -0,0 +1,65 @@
|
|||||||
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
|
import 'package:appflowy/plugins/document/presentation/editor_plugins/plugins.dart';
|
||||||
|
import 'package:appflowy_backend/protobuf/flowy-folder2/protobuf.dart';
|
||||||
|
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:flowy_infra_ui/style_widget/button.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
import 'package:integration_test/integration_test.dart';
|
||||||
|
|
||||||
|
import '../util/ime.dart';
|
||||||
|
import '../util/util.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||||
|
TestWidgetsFlutterBinding.ensureInitialized();
|
||||||
|
|
||||||
|
group('inline math equation in document', () {
|
||||||
|
testWidgets('insert an inline math equation', (tester) async {
|
||||||
|
await tester.initializeAppFlowy();
|
||||||
|
await tester.tapGoButton();
|
||||||
|
|
||||||
|
// create a new document
|
||||||
|
await tester.createNewPageWithName(
|
||||||
|
ViewLayoutPB.Document,
|
||||||
|
LocaleKeys.document_plugins_createInlineMathEquation.tr(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// tap the first line of the document
|
||||||
|
await tester.editor.tapLineOfEditorAt(0);
|
||||||
|
// insert a inline page
|
||||||
|
const formula = 'E = MC ^ 2';
|
||||||
|
await tester.ime.insertText(formula);
|
||||||
|
await tester.editor.updateSelection(
|
||||||
|
Selection.single(path: [0], startOffset: 0, endOffset: formula.length),
|
||||||
|
);
|
||||||
|
|
||||||
|
// tap the inline math equation button
|
||||||
|
final inlineMathEquationButton = find.byTooltip(
|
||||||
|
LocaleKeys.document_plugins_createInlineMathEquation.tr(),
|
||||||
|
);
|
||||||
|
await tester.tapButton(inlineMathEquationButton);
|
||||||
|
|
||||||
|
// expect to see the math equation block
|
||||||
|
final inlineMathEquation = find.byType(InlineMathEquation);
|
||||||
|
expect(inlineMathEquation, findsOneWidget);
|
||||||
|
|
||||||
|
// tap it and update the content
|
||||||
|
await tester.tapButton(inlineMathEquation);
|
||||||
|
final textFormField = find.descendant(
|
||||||
|
of: find.byType(MathInputTextField),
|
||||||
|
matching: find.byType(TextFormField),
|
||||||
|
);
|
||||||
|
const newFormula = 'E = MC ^ 3';
|
||||||
|
await tester.enterText(textFormField, newFormula);
|
||||||
|
await tester.tapButton(
|
||||||
|
find.descendant(
|
||||||
|
of: find.byType(MathInputTextField),
|
||||||
|
matching: find.byType(FlowyButton),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
Binary file not shown.
After Width: | Height: | Size: 7.1 KiB |
Binary file not shown.
After Width: | Height: | Size: 7.0 KiB |
@ -1,23 +1,19 @@
|
|||||||
import 'package:integration_test/integration_test.dart';
|
import 'package:integration_test/integration_test.dart';
|
||||||
|
|
||||||
import 'switch_folder_test.dart' as switch_folder_test;
|
import 'database_calendar_test.dart' as database_calendar_test;
|
||||||
import 'document/document_test.dart' as document_test;
|
|
||||||
import 'document/cover_image_test.dart' as cover_image_test;
|
|
||||||
import 'share_markdown_test.dart' as share_markdown_test;
|
|
||||||
import 'import_files_test.dart' as import_files_test;
|
|
||||||
import 'document/document_with_database_test.dart'
|
|
||||||
as document_with_database_test;
|
|
||||||
import 'document/edit_document_test.dart' as edit_document_test;
|
|
||||||
import 'database_cell_test.dart' as database_cell_test;
|
import 'database_cell_test.dart' as database_cell_test;
|
||||||
import 'database_field_test.dart' as database_field_test;
|
import 'database_field_test.dart' as database_field_test;
|
||||||
import 'database_share_test.dart' as database_share_test;
|
import 'database_filter_test.dart' as database_filter_test;
|
||||||
import 'database_row_page_test.dart' as database_row_page_test;
|
import 'database_row_page_test.dart' as database_row_page_test;
|
||||||
import 'database_row_test.dart' as database_row_test;
|
import 'database_row_test.dart' as database_row_test;
|
||||||
import 'database_setting_test.dart' as database_setting_test;
|
import 'database_setting_test.dart' as database_setting_test;
|
||||||
import 'database_filter_test.dart' as database_filter_test;
|
import 'database_share_test.dart' as database_share_test;
|
||||||
import 'database_view_test.dart' as database_view_test;
|
|
||||||
import 'database_calendar_test.dart' as database_calendar_test;
|
|
||||||
import 'database_sort_test.dart' as database_sort_test;
|
import 'database_sort_test.dart' as database_sort_test;
|
||||||
|
import 'database_view_test.dart' as database_view_test;
|
||||||
|
import 'document/document_test_runner.dart' as document_test_runner;
|
||||||
|
import 'import_files_test.dart' as import_files_test;
|
||||||
|
import 'share_markdown_test.dart' as share_markdown_test;
|
||||||
|
import 'switch_folder_test.dart' as switch_folder_test;
|
||||||
|
|
||||||
/// The main task runner for all integration tests in AppFlowy.
|
/// The main task runner for all integration tests in AppFlowy.
|
||||||
///
|
///
|
||||||
@ -33,10 +29,7 @@ void main() {
|
|||||||
import_files_test.main();
|
import_files_test.main();
|
||||||
|
|
||||||
// Document integration tests
|
// Document integration tests
|
||||||
cover_image_test.main();
|
document_test_runner.startTesting();
|
||||||
document_test.main();
|
|
||||||
document_with_database_test.main();
|
|
||||||
edit_document_test.main();
|
|
||||||
|
|
||||||
// Database integration tests
|
// Database integration tests
|
||||||
database_cell_test.main();
|
database_cell_test.main();
|
||||||
|
@ -10,6 +10,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
|
import 'package:path/path.dart' as p;
|
||||||
|
|
||||||
class FlowyTestContext {
|
class FlowyTestContext {
|
||||||
FlowyTestContext({
|
FlowyTestContext({
|
||||||
@ -23,7 +24,10 @@ extension AppFlowyTestBase on WidgetTester {
|
|||||||
Future<FlowyTestContext> initializeAppFlowy({
|
Future<FlowyTestContext> initializeAppFlowy({
|
||||||
// use to append after the application data directory
|
// use to append after the application data directory
|
||||||
String? pathExtension,
|
String? pathExtension,
|
||||||
|
Size windowsSize = const Size(1600, 1200),
|
||||||
}) async {
|
}) async {
|
||||||
|
binding.setSurfaceSize(windowsSize);
|
||||||
|
|
||||||
mockHotKeyManagerHandlers();
|
mockHotKeyManagerHandlers();
|
||||||
final directory = await mockApplicationDataStorage(
|
final directory = await mockApplicationDataStorage(
|
||||||
pathExtension: pathExtension,
|
pathExtension: pathExtension,
|
||||||
@ -60,7 +64,7 @@ extension AppFlowyTestBase on WidgetTester {
|
|||||||
final dir = await getTemporaryDirectory();
|
final dir = await getTemporaryDirectory();
|
||||||
|
|
||||||
// Use a random uuid to avoid conflict.
|
// Use a random uuid to avoid conflict.
|
||||||
String path = '${dir.path}/appflowy_integration_test/${uuid()}';
|
String path = p.join(dir.path, 'appflowy_integration_test', uuid());
|
||||||
if (pathExtension != null && pathExtension.isNotEmpty) {
|
if (pathExtension != null && pathExtension.isNotEmpty) {
|
||||||
path = '$path/$pathExtension';
|
path = '$path/$pathExtension';
|
||||||
}
|
}
|
||||||
@ -78,7 +82,7 @@ extension AppFlowyTestBase on WidgetTester {
|
|||||||
Finder finder, {
|
Finder finder, {
|
||||||
int? pointer,
|
int? pointer,
|
||||||
int buttons = kPrimaryButton,
|
int buttons = kPrimaryButton,
|
||||||
bool warnIfMissed = true,
|
bool warnIfMissed = false,
|
||||||
int milliseconds = 500,
|
int milliseconds = 500,
|
||||||
}) async {
|
}) async {
|
||||||
await tap(
|
await tap(
|
||||||
@ -123,6 +127,18 @@ extension AppFlowyTestBase on WidgetTester {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> doubleTapAt(
|
||||||
|
Offset location, {
|
||||||
|
int? pointer,
|
||||||
|
int buttons = kPrimaryButton,
|
||||||
|
int milliseconds = 500,
|
||||||
|
}) async {
|
||||||
|
await tapAt(location, pointer: pointer, buttons: buttons);
|
||||||
|
await pump(kDoubleTapMinTime);
|
||||||
|
await tapAt(location, pointer: pointer, buttons: buttons);
|
||||||
|
await pumpAndSettle(Duration(milliseconds: milliseconds));
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> doubleTapButton(
|
Future<void> doubleTapButton(
|
||||||
Finder finder, {
|
Finder finder, {
|
||||||
int? pointer,
|
int? pointer,
|
||||||
@ -130,20 +146,22 @@ extension AppFlowyTestBase on WidgetTester {
|
|||||||
bool warnIfMissed = true,
|
bool warnIfMissed = true,
|
||||||
int milliseconds = 500,
|
int milliseconds = 500,
|
||||||
}) async {
|
}) async {
|
||||||
await tapButton(
|
await tap(
|
||||||
finder,
|
finder,
|
||||||
pointer: pointer,
|
pointer: pointer,
|
||||||
buttons: buttons,
|
buttons: buttons,
|
||||||
warnIfMissed: warnIfMissed,
|
warnIfMissed: warnIfMissed,
|
||||||
milliseconds: kDoubleTapMinTime.inMilliseconds,
|
|
||||||
);
|
);
|
||||||
await tapButton(
|
|
||||||
|
await pump(kDoubleTapMinTime);
|
||||||
|
|
||||||
|
await tap(
|
||||||
finder,
|
finder,
|
||||||
pointer: pointer,
|
|
||||||
buttons: buttons,
|
buttons: buttons,
|
||||||
|
pointer: pointer,
|
||||||
warnIfMissed: warnIfMissed,
|
warnIfMissed: warnIfMissed,
|
||||||
milliseconds: milliseconds,
|
|
||||||
);
|
);
|
||||||
|
await pumpAndSettle(Duration(milliseconds: milliseconds));
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> wait(int milliseconds) async {
|
Future<void> wait(int milliseconds) async {
|
||||||
|
@ -453,8 +453,15 @@ extension AppFlowyDatabaseTest on WidgetTester {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> dismissRowDetailPage() async {
|
Future<void> dismissRowDetailPage() async {
|
||||||
await sendKeyEvent(LogicalKeyboardKey.escape);
|
// use tap empty area instead of clicking ESC to dismiss the row detail page
|
||||||
|
// sometimes, the ESC key is not working.
|
||||||
|
await simulateKeyEvent(LogicalKeyboardKey.escape);
|
||||||
await pumpAndSettle();
|
await pumpAndSettle();
|
||||||
|
final findRowDetailPage = find.byType(RowDetailPage);
|
||||||
|
if (findRowDetailPage.evaluate().isNotEmpty) {
|
||||||
|
await tapAt(const Offset(0, 0));
|
||||||
|
await pumpAndSettle();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> editTitleInRowDetailPage(String title) async {
|
Future<void> editTitleInRowDetailPage(String title) async {
|
||||||
@ -1031,7 +1038,7 @@ extension AppFlowyDatabaseTest on WidgetTester {
|
|||||||
expect(findEvents, findsNWidgets(number));
|
expect(findEvents, findsNWidgets(number));
|
||||||
}
|
}
|
||||||
|
|
||||||
void assertNumberofEventsOnSpecificDay(
|
void assertNumberOfEventsOnSpecificDay(
|
||||||
int number,
|
int number,
|
||||||
DateTime date, {
|
DateTime date, {
|
||||||
String? title,
|
String? title,
|
||||||
@ -1058,8 +1065,8 @@ extension AppFlowyDatabaseTest on WidgetTester {
|
|||||||
final todayCell = find.byWidgetPredicate(
|
final todayCell = find.byWidgetPredicate(
|
||||||
(widget) => widget is CalendarDayCard && isSameDay(date, widget.date),
|
(widget) => widget is CalendarDayCard && isSameDay(date, widget.date),
|
||||||
);
|
);
|
||||||
|
final location = getTopLeft(todayCell).translate(10, 10);
|
||||||
await doubleTapButton(todayCell);
|
await doubleTapAt(location);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> openCalendarEvent({required index, DateTime? date}) async {
|
Future<void> openCalendarEvent({required index, DateTime? date}) async {
|
||||||
|
@ -165,4 +165,14 @@ class EditorOperations {
|
|||||||
);
|
);
|
||||||
await tester.tapButton(atMenuItem);
|
await tester.tapButton(atMenuItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Update the editor's selection
|
||||||
|
Future<void> updateSelection(Selection selection) async {
|
||||||
|
final editorState = getCurrentEditorState();
|
||||||
|
editorState.updateSelectionWithReason(
|
||||||
|
selection,
|
||||||
|
reason: SelectionUpdateReason.uiEvent,
|
||||||
|
);
|
||||||
|
await tester.pumpAndSettle(const Duration(milliseconds: 200));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -49,9 +49,10 @@ class _AppFlowyEditorPageState extends State<AppFlowyEditorPage> {
|
|||||||
quoteItem,
|
quoteItem,
|
||||||
bulletedListItem,
|
bulletedListItem,
|
||||||
numberedListItem,
|
numberedListItem,
|
||||||
|
inlineMathEquationItem,
|
||||||
linkItem,
|
linkItem,
|
||||||
textColorItem,
|
buildTextColorItem(),
|
||||||
highlightColorItem,
|
buildHighlightColorItem(),
|
||||||
];
|
];
|
||||||
|
|
||||||
late final List<SelectionMenuItem> slashMenuItems;
|
late final List<SelectionMenuItem> slashMenuItems;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/plugins.dart';
|
import 'package:appflowy/plugins/document/presentation/editor_plugins/plugins.dart';
|
||||||
import 'package:appflowy/workspace/presentation/widgets/pop_up_action.dart';
|
import 'package:appflowy/workspace/presentation/widgets/pop_up_action.dart';
|
||||||
import 'package:appflowy_editor/appflowy_editor.dart' hide FlowySvg;
|
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
import 'package:appflowy_popover/appflowy_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';
|
||||||
|
@ -2,7 +2,7 @@ import 'dart:io';
|
|||||||
|
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/workspace/presentation/widgets/emoji_picker/emoji_picker.dart';
|
import 'package:appflowy/workspace/presentation/widgets/emoji_picker/emoji_picker.dart';
|
||||||
import 'package:appflowy_editor/appflowy_editor.dart' hide FlowySvg;
|
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
import 'package:appflowy_popover/appflowy_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';
|
||||||
@ -43,20 +43,6 @@ enum CoverType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class DocumentHeaderNodeWidgetBuilder implements NodeWidgetBuilder {
|
|
||||||
@override
|
|
||||||
Widget build(NodeWidgetContext<Node> context) {
|
|
||||||
return DocumentHeaderNodeWidget(
|
|
||||||
key: context.node.key,
|
|
||||||
node: context.node,
|
|
||||||
editorState: context.editorState,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
NodeValidator<Node> get nodeValidator => (_) => true;
|
|
||||||
}
|
|
||||||
|
|
||||||
class DocumentHeaderNodeWidget extends StatefulWidget {
|
class DocumentHeaderNodeWidget extends StatefulWidget {
|
||||||
const DocumentHeaderNodeWidget({
|
const DocumentHeaderNodeWidget({
|
||||||
required this.node,
|
required this.node,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/workspace/presentation/widgets/emoji_picker/emoji_picker.dart';
|
import 'package:appflowy/workspace/presentation/widgets/emoji_picker/emoji_picker.dart';
|
||||||
import 'package:appflowy_editor/appflowy_editor.dart' hide FlowySvg;
|
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flowy_infra_ui/style_widget/button.dart';
|
import 'package:flowy_infra_ui/style_widget/button.dart';
|
||||||
import 'package:flowy_infra_ui/style_widget/text.dart';
|
import 'package:flowy_infra_ui/style_widget/text.dart';
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy_editor/appflowy_editor.dart' hide FlowySvg;
|
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
import 'package:appflowy_popover/appflowy_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';
|
||||||
|
@ -0,0 +1,173 @@
|
|||||||
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
|
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||||
|
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||||
|
import 'package:flowy_infra_ui/style_widget/text_input.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_math_fork/flutter_math.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
class InlineMathEquationKeys {
|
||||||
|
const InlineMathEquationKeys._();
|
||||||
|
|
||||||
|
static const formula = 'formula';
|
||||||
|
}
|
||||||
|
|
||||||
|
class InlineMathEquation extends StatefulWidget {
|
||||||
|
const InlineMathEquation({
|
||||||
|
super.key,
|
||||||
|
required this.formula,
|
||||||
|
required this.node,
|
||||||
|
required this.index,
|
||||||
|
this.textStyle,
|
||||||
|
});
|
||||||
|
|
||||||
|
final Node node;
|
||||||
|
final int index;
|
||||||
|
final String formula;
|
||||||
|
final TextStyle? textStyle;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<InlineMathEquation> createState() => _InlineMathEquationState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _InlineMathEquationState extends State<InlineMathEquation> {
|
||||||
|
final popoverController = PopoverController();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final theme = Theme.of(context);
|
||||||
|
return _IgnoreParentPointer(
|
||||||
|
child: AppFlowyPopover(
|
||||||
|
controller: popoverController,
|
||||||
|
direction: PopoverDirection.bottomWithLeftAligned,
|
||||||
|
popupBuilder: (_) {
|
||||||
|
return MathInputTextField(
|
||||||
|
initialText: widget.formula,
|
||||||
|
onSubmit: (value) async {
|
||||||
|
popoverController.close();
|
||||||
|
if (value == widget.formula) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final editorState = context.read<EditorState>();
|
||||||
|
final transaction = editorState.transaction
|
||||||
|
..formatText(widget.node, widget.index, 1, {
|
||||||
|
InlineMathEquationKeys.formula: value,
|
||||||
|
});
|
||||||
|
await editorState.apply(transaction);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
offset: const Offset(0, 10),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 8.0),
|
||||||
|
child: MouseRegion(
|
||||||
|
cursor: SystemMouseCursors.click,
|
||||||
|
child: Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
const HSpace(2),
|
||||||
|
Math.tex(
|
||||||
|
widget.formula,
|
||||||
|
options: MathOptions(
|
||||||
|
style: MathStyle.text,
|
||||||
|
mathFontOptions: const FontOptions(
|
||||||
|
fontShape: FontStyle.italic,
|
||||||
|
),
|
||||||
|
fontSize: 14.0,
|
||||||
|
color: widget.textStyle?.color ??
|
||||||
|
theme.colorScheme.onBackground,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const HSpace(2),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MathInputTextField extends StatefulWidget {
|
||||||
|
const MathInputTextField({
|
||||||
|
super.key,
|
||||||
|
required this.initialText,
|
||||||
|
required this.onSubmit,
|
||||||
|
});
|
||||||
|
|
||||||
|
final String initialText;
|
||||||
|
final void Function(String value) onSubmit;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<MathInputTextField> createState() => _MathInputTextFieldState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _MathInputTextFieldState extends State<MathInputTextField> {
|
||||||
|
late final TextEditingController textEditingController;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
|
||||||
|
textEditingController = TextEditingController(
|
||||||
|
text: widget.initialText,
|
||||||
|
);
|
||||||
|
textEditingController.selection = TextSelection(
|
||||||
|
baseOffset: 0,
|
||||||
|
extentOffset: widget.initialText.length,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return SizedBox(
|
||||||
|
width: 240,
|
||||||
|
child: Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: FlowyFormTextInput(
|
||||||
|
autoFocus: true,
|
||||||
|
textAlign: TextAlign.left,
|
||||||
|
controller: textEditingController,
|
||||||
|
contentPadding: const EdgeInsets.symmetric(
|
||||||
|
vertical: 8.0,
|
||||||
|
horizontal: 4.0,
|
||||||
|
),
|
||||||
|
onEditingComplete: () =>
|
||||||
|
widget.onSubmit(textEditingController.text),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const HSpace(4.0),
|
||||||
|
FlowyButton(
|
||||||
|
text: FlowyText(LocaleKeys.button_Done.tr()),
|
||||||
|
useIntrinsicWidth: true,
|
||||||
|
onTap: () => widget.onSubmit(textEditingController.text),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _IgnoreParentPointer extends StatelessWidget {
|
||||||
|
const _IgnoreParentPointer({
|
||||||
|
required this.child,
|
||||||
|
});
|
||||||
|
|
||||||
|
final Widget child;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return GestureDetector(
|
||||||
|
behavior: HitTestBehavior.opaque,
|
||||||
|
onTap: () {},
|
||||||
|
onTapDown: (_) {},
|
||||||
|
onDoubleTap: () {},
|
||||||
|
onLongPress: () {},
|
||||||
|
child: child,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
|
import 'package:appflowy/plugins/document/presentation/editor_plugins/plugins.dart';
|
||||||
|
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:flowy_infra/image.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
final ToolbarItem inlineMathEquationItem = ToolbarItem(
|
||||||
|
id: 'editor.inline_math_equation',
|
||||||
|
group: 2,
|
||||||
|
isActive: onlyShowInSingleSelectionAndTextType,
|
||||||
|
builder: (context, editorState) {
|
||||||
|
final selection = editorState.selection!;
|
||||||
|
final nodes = editorState.getNodesInSelection(selection);
|
||||||
|
final isHighlight = nodes.allSatisfyInSelection(selection, (delta) {
|
||||||
|
return delta.everyAttributes(
|
||||||
|
(attributes) => attributes[InlineMathEquationKeys.formula] != null,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
return IconItemWidget(
|
||||||
|
iconBuilder: (_) => svgWidget(
|
||||||
|
'editor/math',
|
||||||
|
size: const Size.square(16),
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
isHighlight: isHighlight,
|
||||||
|
tooltip: LocaleKeys.document_plugins_createInlineMathEquation.tr(),
|
||||||
|
onPressed: () async {
|
||||||
|
final selection = editorState.selection;
|
||||||
|
if (selection == null || selection.isCollapsed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final node = editorState.getNodeAtPath(selection.start.path);
|
||||||
|
if (node == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final text = editorState.getTextInSelection(selection).join();
|
||||||
|
final transaction = editorState.transaction
|
||||||
|
..replaceText(
|
||||||
|
node,
|
||||||
|
selection.startIndex,
|
||||||
|
selection.length,
|
||||||
|
'\$',
|
||||||
|
attributes: {
|
||||||
|
InlineMathEquationKeys.formula: text,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
await editorState.apply(transaction);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
@ -24,8 +24,6 @@ class MentionBlockKeys {
|
|||||||
static const mention = 'mention';
|
static const mention = 'mention';
|
||||||
static const type = 'type'; // MentionType, String
|
static const type = 'type'; // MentionType, String
|
||||||
static const pageId = 'page_id';
|
static const pageId = 'page_id';
|
||||||
static const pageType = 'page_type';
|
|
||||||
static const pageName = 'page_name';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class InlinePageReferenceService {
|
class InlinePageReferenceService {
|
||||||
|
@ -1,22 +1,24 @@
|
|||||||
|
export 'actions/block_action_list.dart';
|
||||||
|
export 'actions/option_action.dart';
|
||||||
export 'callout/callout_block_component.dart';
|
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 'header/cover_editor_bloc.dart';
|
export 'database/database_view_block_component.dart';
|
||||||
export 'header/document_header_node_widget.dart';
|
|
||||||
export 'header/custom_cover_picker.dart';
|
|
||||||
export 'emoji_picker/emoji_menu_item.dart';
|
|
||||||
export 'extensions/flowy_tint_extension.dart';
|
|
||||||
export 'database/inline_database_menu_item.dart';
|
export 'database/inline_database_menu_item.dart';
|
||||||
export 'database/referenced_database_menu_item.dart';
|
export 'database/referenced_database_menu_item.dart';
|
||||||
export 'database/database_view_block_component.dart';
|
export 'emoji_picker/emoji_menu_item.dart';
|
||||||
|
export 'extensions/flowy_tint_extension.dart';
|
||||||
|
export 'header/cover_editor_bloc.dart';
|
||||||
|
export 'header/custom_cover_picker.dart';
|
||||||
|
export 'header/document_header_node_widget.dart';
|
||||||
|
export 'image/image_menu.dart';
|
||||||
|
export 'image/image_selection_menu.dart';
|
||||||
|
export 'inline_math_equation/inline_math_equation.dart';
|
||||||
|
export 'inline_math_equation/inline_math_equation_toolbar_item.dart';
|
||||||
export 'math_equation/math_equation_block_component.dart';
|
export 'math_equation/math_equation_block_component.dart';
|
||||||
export 'openai/widgets/auto_completion_node_widget.dart';
|
export 'openai/widgets/auto_completion_node_widget.dart';
|
||||||
export 'openai/widgets/smart_edit_node_widget.dart';
|
export 'openai/widgets/smart_edit_node_widget.dart';
|
||||||
export 'openai/widgets/smart_edit_toolbar_item.dart';
|
export 'openai/widgets/smart_edit_toolbar_item.dart';
|
||||||
|
export 'outline/outline_block_component.dart';
|
||||||
export 'toggle/toggle_block_component.dart';
|
export 'toggle/toggle_block_component.dart';
|
||||||
export 'toggle/toggle_block_shortcut_event.dart';
|
export 'toggle/toggle_block_shortcut_event.dart';
|
||||||
export 'outline/outline_block_component.dart';
|
|
||||||
export 'image/image_menu.dart';
|
|
||||||
export 'image/image_selection_menu.dart';
|
|
||||||
export 'actions/option_action.dart';
|
|
||||||
export 'actions/block_action_list.dart';
|
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
|
import 'package:appflowy/plugins/document/presentation/editor_plugins/inline_math_equation/inline_math_equation.dart';
|
||||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/inline_page/inline_page_reference.dart';
|
import 'package:appflowy/plugins/document/presentation/editor_plugins/inline_page/inline_page_reference.dart';
|
||||||
import 'package:appflowy/plugins/document/presentation/editor_plugins/mention/mention_block.dart';
|
import 'package:appflowy/plugins/document/presentation/editor_plugins/mention/mention_block.dart';
|
||||||
import 'package:appflowy/plugins/document/presentation/more/cubit/document_appearance_cubit.dart';
|
import 'package:appflowy/plugins/document/presentation/more/cubit/document_appearance_cubit.dart';
|
||||||
import 'package:appflowy_editor/appflowy_editor.dart' hide FlowySvg, Log;
|
import 'package:appflowy_editor/appflowy_editor.dart' hide Log;
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
@ -173,13 +174,17 @@ class EditorStyleCustomizer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
InlineSpan customizeAttributeDecorator(
|
InlineSpan customizeAttributeDecorator(
|
||||||
TextInsert textInsert,
|
Node node,
|
||||||
|
int index,
|
||||||
|
TextInsert text,
|
||||||
TextSpan textSpan,
|
TextSpan textSpan,
|
||||||
) {
|
) {
|
||||||
final attributes = textInsert.attributes;
|
final attributes = text.attributes;
|
||||||
if (attributes == null) {
|
if (attributes == null) {
|
||||||
return textSpan;
|
return textSpan;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// customize the inline mention block, like inline page
|
||||||
final mention = attributes[MentionBlockKeys.mention] as Map?;
|
final mention = attributes[MentionBlockKeys.mention] as Map?;
|
||||||
if (mention != null) {
|
if (mention != null) {
|
||||||
final type = mention[MentionBlockKeys.type];
|
final type = mention[MentionBlockKeys.type];
|
||||||
@ -193,6 +198,21 @@ class EditorStyleCustomizer {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// customize the inline math equation block
|
||||||
|
final formula = attributes[InlineMathEquationKeys.formula] as String?;
|
||||||
|
if (formula != null) {
|
||||||
|
return WidgetSpan(
|
||||||
|
alignment: PlaceholderAlignment.middle,
|
||||||
|
child: InlineMathEquation(
|
||||||
|
node: node,
|
||||||
|
index: index,
|
||||||
|
formula: formula,
|
||||||
|
textStyle: style().textStyleConfiguration.text,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return textSpan;
|
return textSpan;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,8 +46,9 @@ class FlowyRunner {
|
|||||||
final launcher = getIt<AppLauncher>();
|
final launcher = getIt<AppLauncher>();
|
||||||
launcher.addTasks(
|
launcher.addTasks(
|
||||||
[
|
[
|
||||||
// handle platform errors.
|
// this task should be first task, for handling platform errors.
|
||||||
const PlatformErrorCatcherTask(),
|
// don't catch errors in test mode
|
||||||
|
if (!mode.isUnitTest) const PlatformErrorCatcherTask(),
|
||||||
// localization
|
// localization
|
||||||
const InitLocalizationTask(),
|
const InitLocalizationTask(),
|
||||||
// init the app window
|
// init the app window
|
||||||
|
@ -19,17 +19,14 @@ class InitAppWindowTask extends LaunchTask with WindowListener {
|
|||||||
@override
|
@override
|
||||||
Future<void> initialize(LaunchContext context) async {
|
Future<void> initialize(LaunchContext context) async {
|
||||||
// Don't initialize on mobile or web.
|
// Don't initialize on mobile or web.
|
||||||
if (!defaultTargetPlatform.isDesktop) {
|
if (!defaultTargetPlatform.isDesktop || context.env.isIntegrationTest) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await windowManager.ensureInitialized();
|
await windowManager.ensureInitialized();
|
||||||
windowManager.addListener(this);
|
windowManager.addListener(this);
|
||||||
|
|
||||||
Size windowSize = await WindowSizeManager().getSize();
|
final windowSize = await WindowSizeManager().getSize();
|
||||||
if (context.env.isIntegrationTest) {
|
|
||||||
windowSize = const Size(1600, 1200);
|
|
||||||
}
|
|
||||||
|
|
||||||
final windowOptions = WindowOptions(
|
final windowOptions = WindowOptions(
|
||||||
size: windowSize,
|
size: windowSize,
|
||||||
|
@ -96,7 +96,7 @@ class SplashScreen extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _registerIfNeeded() async {
|
Future<void> _registerIfNeeded() async {
|
||||||
final result = await UserEventCheckUser().send();
|
final result = await UserEventGetUserProfile().send();
|
||||||
if (!result.isLeft()) {
|
if (!result.isLeft()) {
|
||||||
await getIt<AuthService>().signUpAsGuest();
|
await getIt<AuthService>().signUpAsGuest();
|
||||||
}
|
}
|
||||||
|
@ -98,6 +98,7 @@ class MockApplicationDataStorage extends ApplicationDataStorage {
|
|||||||
final path = initialPath;
|
final path = initialPath;
|
||||||
if (path != null) {
|
if (path != null) {
|
||||||
initialPath = null;
|
initialPath = null;
|
||||||
|
await super.setPath(path);
|
||||||
return Future.value(path);
|
return Future.value(path);
|
||||||
}
|
}
|
||||||
return super.getPath();
|
return super.getPath();
|
||||||
|
@ -5,16 +5,23 @@ import 'package:flutter_svg/flutter_svg.dart';
|
|||||||
///
|
///
|
||||||
/// Get the hover color from ThemeData
|
/// Get the hover color from ThemeData
|
||||||
class FlowySvg extends StatelessWidget {
|
class FlowySvg extends StatelessWidget {
|
||||||
const FlowySvg({super.key, this.size, required this.name});
|
const FlowySvg({
|
||||||
|
super.key,
|
||||||
|
required this.name,
|
||||||
|
this.size,
|
||||||
|
this.color,
|
||||||
|
});
|
||||||
|
|
||||||
final String name;
|
final String name;
|
||||||
final Size? size;
|
final Size? size;
|
||||||
|
final Color? color;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return svgWidget(
|
return svgWidget(
|
||||||
name,
|
name,
|
||||||
size: size,
|
size: size,
|
||||||
color: Theme.of(context).iconTheme.color,
|
color: color ?? Theme.of(context).iconTheme.color,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,11 +53,11 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
path: "."
|
path: "."
|
||||||
ref: "572a174"
|
ref: c5b5e64
|
||||||
resolved-ref: "572a174892267e2f78f9c3d7f1fe4ca71c9be0db"
|
resolved-ref: c5b5e641fe11ae634f02db112e71f40a119e9c44
|
||||||
url: "https://github.com/AppFlowy-IO/appflowy-editor.git"
|
url: "https://github.com/AppFlowy-IO/appflowy-editor.git"
|
||||||
source: git
|
source: git
|
||||||
version: "1.0.4"
|
version: "1.1.0"
|
||||||
appflowy_popover:
|
appflowy_popover:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@ -46,7 +46,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: 572a174
|
ref: c5b5e64
|
||||||
appflowy_popover:
|
appflowy_popover:
|
||||||
path: packages/appflowy_popover
|
path: packages/appflowy_popover
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ mod init;
|
|||||||
mod notification;
|
mod notification;
|
||||||
mod request;
|
mod request;
|
||||||
|
|
||||||
use flowy_notification::register_notification_sender;
|
use flowy_notification::{register_notification_sender, unregister_all_notification_sender};
|
||||||
use init::*;
|
use init::*;
|
||||||
use notification::*;
|
use notification::*;
|
||||||
use request::*;
|
use request::*;
|
||||||
@ -22,6 +22,8 @@ fn main() {
|
|||||||
.on_menu_event(|_menu| {})
|
.on_menu_event(|_menu| {})
|
||||||
.on_page_load(|window, _payload| {
|
.on_page_load(|window, _payload| {
|
||||||
let app_handler = window.app_handle();
|
let app_handler = window.app_handle();
|
||||||
|
// Make sure hot reload won't register the notification sender twice
|
||||||
|
unregister_all_notification_sender();
|
||||||
register_notification_sender(TSNotificationSender::new(app_handler.clone()));
|
register_notification_sender(TSNotificationSender::new(app_handler.clone()));
|
||||||
// tauri::async_runtime::spawn(async move {});
|
// tauri::async_runtime::spawn(async move {});
|
||||||
window.listen_global(AF_EVENT, move |event| {
|
window.listen_global(AF_EVENT, move |event| {
|
||||||
|
10
frontend/rust-lib/Cargo.lock
generated
10
frontend/rust-lib/Cargo.lock
generated
@ -85,6 +85,7 @@ checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8"
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "appflowy-integrate"
|
name = "appflowy-integrate"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=2134c0#2134c0f27b8a9f3077e25ae928f2420c926506cc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"collab",
|
"collab",
|
||||||
@ -896,6 +897,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "collab"
|
name = "collab"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=2134c0#2134c0f27b8a9f3077e25ae928f2420c926506cc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bytes",
|
"bytes",
|
||||||
@ -913,6 +915,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "collab-client-ws"
|
name = "collab-client-ws"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=2134c0#2134c0f27b8a9f3077e25ae928f2420c926506cc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"collab-sync",
|
"collab-sync",
|
||||||
@ -930,6 +933,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "collab-database"
|
name = "collab-database"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=2134c0#2134c0f27b8a9f3077e25ae928f2420c926506cc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
@ -956,6 +960,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "collab-derive"
|
name = "collab-derive"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=2134c0#2134c0f27b8a9f3077e25ae928f2420c926506cc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -967,6 +972,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "collab-document"
|
name = "collab-document"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=2134c0#2134c0f27b8a9f3077e25ae928f2420c926506cc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"collab",
|
"collab",
|
||||||
@ -985,6 +991,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "collab-folder"
|
name = "collab-folder"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=2134c0#2134c0f27b8a9f3077e25ae928f2420c926506cc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"chrono",
|
"chrono",
|
||||||
@ -1004,6 +1011,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "collab-persistence"
|
name = "collab-persistence"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=2134c0#2134c0f27b8a9f3077e25ae928f2420c926506cc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bincode",
|
"bincode",
|
||||||
"chrono",
|
"chrono",
|
||||||
@ -1023,6 +1031,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "collab-plugins"
|
name = "collab-plugins"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=2134c0#2134c0f27b8a9f3077e25ae928f2420c926506cc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
@ -1056,6 +1065,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "collab-sync"
|
name = "collab-sync"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=2134c0#2134c0f27b8a9f3077e25ae928f2420c926506cc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"collab",
|
"collab",
|
||||||
|
@ -6,7 +6,7 @@ use lazy_static::lazy_static;
|
|||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
|
|
||||||
use flowy_core::*;
|
use flowy_core::*;
|
||||||
use flowy_notification::register_notification_sender;
|
use flowy_notification::{register_notification_sender, unregister_all_notification_sender};
|
||||||
use lib_dispatch::prelude::ToBytes;
|
use lib_dispatch::prelude::ToBytes;
|
||||||
use lib_dispatch::prelude::*;
|
use lib_dispatch::prelude::*;
|
||||||
|
|
||||||
@ -90,6 +90,8 @@ pub extern "C" fn sync_event(input: *const u8, len: usize) -> *const u8 {
|
|||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn set_stream_port(port: i64) -> i32 {
|
pub extern "C" fn set_stream_port(port: i64) -> i32 {
|
||||||
|
// Make sure hot reload won't register the notification sender twice
|
||||||
|
unregister_all_notification_sender();
|
||||||
register_notification_sender(DartNotificationSender::new(port));
|
register_notification_sender(DartNotificationSender::new(port));
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,10 @@ lazy_static! {
|
|||||||
static ref NOTIFICATION_SENDER: RwLock<Vec<Box<dyn NotificationSender>>> = RwLock::new(vec![]);
|
static ref NOTIFICATION_SENDER: RwLock<Vec<Box<dyn NotificationSender>>> = RwLock::new(vec![]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Register a notification sender. The sender will be alive until the process exits.
|
||||||
|
/// Flutter integration test or Tauri hot reload might cause register multiple times.
|
||||||
|
/// So before register a new sender, you might need to unregister the old one. Currently,
|
||||||
|
/// Just remove all senders by calling `unregister_all_notification_sender`.
|
||||||
pub fn register_notification_sender<T: NotificationSender>(sender: T) {
|
pub fn register_notification_sender<T: NotificationSender>(sender: T) {
|
||||||
let box_sender = Box::new(sender);
|
let box_sender = Box::new(sender);
|
||||||
match NOTIFICATION_SENDER.write() {
|
match NOTIFICATION_SENDER.write() {
|
||||||
@ -22,6 +26,13 @@ pub fn register_notification_sender<T: NotificationSender>(sender: T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn unregister_all_notification_sender() {
|
||||||
|
match NOTIFICATION_SENDER.write() {
|
||||||
|
Ok(mut write_guard) => write_guard.clear(),
|
||||||
|
Err(err) => tracing::error!("Failed to remove all notification senders: {:?}", err),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub trait NotificationSender: Send + Sync + 'static {
|
pub trait NotificationSender: Send + Sync + 'static {
|
||||||
fn send_subject(&self, subject: SubscribeObject) -> Result<(), String>;
|
fn send_subject(&self, subject: SubscribeObject) -> Result<(), String>;
|
||||||
}
|
}
|
||||||
|
7
frontend/scripts/code_generation/freezed/generate_freezed.sh
Normal file → Executable file
7
frontend/scripts/code_generation/freezed/generate_freezed.sh
Normal file → Executable file
@ -10,7 +10,9 @@ cd ../../../appflowy_flutter
|
|||||||
|
|
||||||
# Navigate to the appflowy_flutter directory and generate files
|
# Navigate to the appflowy_flutter directory and generate files
|
||||||
echo "Generating files for appflowy_flutter"
|
echo "Generating files for appflowy_flutter"
|
||||||
flutter clean >/dev/null 2>&1 && flutter packages pub get >/dev/null 2>&1 && dart run build_runner clean && dart run build_runner build -d
|
# flutter clean >/dev/null 2>&1 && flutter packages pub get >/dev/null 2>&1 && dart run build_runner clean &&
|
||||||
|
flutter packages pub get >/dev/null 2>&1
|
||||||
|
dart run build_runner build -d
|
||||||
echo "Done generating files for appflowy_flutter"
|
echo "Done generating files for appflowy_flutter"
|
||||||
|
|
||||||
echo "Generating files for packages"
|
echo "Generating files for packages"
|
||||||
@ -23,7 +25,8 @@ for d in */ ; do
|
|||||||
if [ -f "pubspec.yaml" ]; then
|
if [ -f "pubspec.yaml" ]; then
|
||||||
echo "Generating freezed files in $d..."
|
echo "Generating freezed files in $d..."
|
||||||
echo "Please wait while we clean the project and fetch the dependencies."
|
echo "Please wait while we clean the project and fetch the dependencies."
|
||||||
flutter clean >/dev/null 2>&1 && flutter packages pub get >/dev/null 2>&1 && dart run build_runner clean && dart run build_runner build -d
|
flutter packages pub get >/dev/null 2>&1
|
||||||
|
dart run build_runner build -d
|
||||||
echo "Done running build command in $d"
|
echo "Done running build command in $d"
|
||||||
else
|
else
|
||||||
echo "No pubspec.yaml found in $d, it can\'t be a Dart project. Skipping."
|
echo "No pubspec.yaml found in $d, it can\'t be a Dart project. Skipping."
|
||||||
|
0
frontend/scripts/code_generation/generate.sh
Normal file → Executable file
0
frontend/scripts/code_generation/generate.sh
Normal file → Executable file
@ -10,8 +10,6 @@ cd /d "%~dp0"
|
|||||||
|
|
||||||
cd ..\..\..\appflowy_flutter
|
cd ..\..\..\appflowy_flutter
|
||||||
|
|
||||||
call flutter clean
|
|
||||||
|
|
||||||
call flutter packages pub get
|
call flutter packages pub get
|
||||||
|
|
||||||
echo Specifying source directory for AppFlowy Localizations.
|
echo Specifying source directory for AppFlowy Localizations.
|
||||||
|
2
frontend/scripts/code_generation/language_files/generate_language_files.sh
Normal file → Executable file
2
frontend/scripts/code_generation/language_files/generate_language_files.sh
Normal file → Executable file
@ -10,8 +10,6 @@ cd "$(dirname "$0")"
|
|||||||
# Navigate to the project root
|
# Navigate to the project root
|
||||||
cd ../../../appflowy_flutter
|
cd ../../../appflowy_flutter
|
||||||
|
|
||||||
flutter clean
|
|
||||||
|
|
||||||
flutter packages pub get
|
flutter packages pub get
|
||||||
|
|
||||||
echo "Specifying source directory for AppFlowy Localizations."
|
echo "Specifying source directory for AppFlowy Localizations."
|
||||||
|
@ -167,7 +167,6 @@ script = [
|
|||||||
[tasks.flutter-build]
|
[tasks.flutter-build]
|
||||||
script = ["""
|
script = ["""
|
||||||
cd appflowy_flutter/
|
cd appflowy_flutter/
|
||||||
flutter clean
|
|
||||||
flutter pub get
|
flutter pub get
|
||||||
flutter build ${TARGET_OS} --${BUILD_FLAG}
|
flutter build ${TARGET_OS} --${BUILD_FLAG}
|
||||||
"""]
|
"""]
|
||||||
@ -176,7 +175,6 @@ script_runner = "@shell"
|
|||||||
[tasks.flutter-build.windows]
|
[tasks.flutter-build.windows]
|
||||||
script = ["""
|
script = ["""
|
||||||
cd appflowy_flutter
|
cd appflowy_flutter
|
||||||
exec cmd.exe /c flutter clean
|
|
||||||
exec cmd.exe /c flutter pub get
|
exec cmd.exe /c flutter pub get
|
||||||
exec cmd.exe /c flutter build ${TARGET_OS} --${BUILD_FLAG} --build-name=${APP_VERSION}
|
exec cmd.exe /c flutter build ${TARGET_OS} --${BUILD_FLAG} --build-name=${APP_VERSION}
|
||||||
"""]
|
"""]
|
||||||
@ -186,16 +184,15 @@ script_runner = "@duckscript"
|
|||||||
script_runner = "@shell"
|
script_runner = "@shell"
|
||||||
script = [
|
script = [
|
||||||
"""
|
"""
|
||||||
chmod +x scripts/code_generation/generate.sh
|
sh scripts/code_generation/generate.sh
|
||||||
""",
|
"""
|
||||||
"scripts/code_generation/generate.sh"
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[tasks.code_generation.windows]
|
[tasks.code_generation.windows]
|
||||||
script_runner = "@duckscript"
|
script_runner = "@duckscript"
|
||||||
script = [
|
script = [
|
||||||
"""
|
"""
|
||||||
exec "scripts/code_generation/generate.cmd"
|
exec scripts/code_generation/generate.cmd
|
||||||
""",
|
""",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user