Skip to content

Commit

Permalink
chore: merge branch 'upstream/main' into feat/file-progress
Browse files Browse the repository at this point in the history
  • Loading branch information
Xazin committed Nov 12, 2024
2 parents d30097b + eed3f48 commit f12c9f7
Show file tree
Hide file tree
Showing 47 changed files with 970 additions and 502 deletions.
40 changes: 22 additions & 18 deletions .github/workflows/ios_ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -97,21 +97,25 @@ jobs:
cargo make --profile development-ios-arm64-sim appflowy-core-dev-ios
cargo make --profile development-ios-arm64-sim code_generation
# - uses: futureware-tech/simulator-action@v3
# id: simulator-action
# with:
# model: "iPhone 15"
# shutdown_after_job: false

# - name: Run AppFlowy on simulator
# working-directory: frontend/appflowy_flutter
# run: |
# flutter run -d ${{ steps.simulator-action.outputs.udid }} &
# pid=$!
# sleep 500
# kill $pid
# continue-on-error: true

# - name: Run integration tests
# working-directory: frontend/appflowy_flutter
# run: flutter test integration_test/runner.dart -d ${{ steps.simulator-action.outputs.udid }}
- uses: futureware-tech/simulator-action@v3
id: simulator-action
with:
model: "iPhone 15"
shutdown_after_job: false

- name: Run AppFlowy on simulator
working-directory: frontend/appflowy_flutter
run: |
flutter run -d ${{ steps.simulator-action.outputs.udid }} &
pid=$!
sleep 500
kill $pid
continue-on-error: true

- name: Run integration tests
working-directory: frontend/appflowy_flutter
# The integration tests are flaky and sometimes fail with "Connection timed out":
# Don't block the CI. If the tests fail, the CI will still pass.
# Instead, we're using Code Magic to re-run the tests to check if they pass.
continue-on-error: true
run: flutter test integration_test/runner.dart -d ${{ steps.simulator-action.outputs.udid }}
82 changes: 82 additions & 0 deletions .github/workflows/mobile_ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
name: Mobile-CI

on:
workflow_dispatch:
inputs:
branch:
description: "Branch to build"
required: true
default: "main"
workflow_id:
description: "Codemagic workflow ID"
required: true
default: "ios-workflow"
type: choice
options:
- ios-workflow
- android-workflow

env:
CODEMAGIC_API_TOKEN: ${{ secrets.CODEMAGIC_API_TOKEN }}
APP_ID: "6731d2f427e7c816080c3674"

jobs:
trigger-mobile-build:
runs-on: ubuntu-latest
steps:
- name: Trigger Codemagic Build
id: trigger_build
run: |
RESPONSE=$(curl -X POST \
--header "Content-Type: application/json" \
--header "x-auth-token: $CODEMAGIC_API_TOKEN" \
--data '{
"appId": "${{ env.APP_ID }}",
"workflowId": "${{ github.event.inputs.workflow_id }}",
"branch": "${{ github.event.inputs.branch }}"
}' \
https://api.codemagic.io/builds)
BUILD_ID=$(echo $RESPONSE | jq -r '.buildId')
echo "build_id=$BUILD_ID" >> $GITHUB_OUTPUT
echo "build_id=$BUILD_ID"
- name: Wait for build and check status
id: check_status
run: |
while true; do
RESPONSE=$(curl -X GET \
--header "Content-Type: application/json" \
--header "x-auth-token: $CODEMAGIC_API_TOKEN" \
https://api.codemagic.io/builds/${{ steps.trigger_build.outputs.build_id }})
STATUS=$(echo $RESPONSE | jq -r '.build.status')
if [ "$STATUS" = "finished" ]; then
SUCCESS=$(echo $RESPONSE | jq -r '.success')
BUILD_URL=$(echo $RESPONSE | jq -r '.buildUrl')
echo "status=$STATUS" >> $GITHUB_OUTPUT
echo "success=$SUCCESS" >> $GITHUB_OUTPUT
echo "build_url=$BUILD_URL" >> $GITHUB_OUTPUT
break
elif [ "$STATUS" = "failed" ]; then
echo "status=failed" >> $GITHUB_OUTPUT
break
fi
sleep 60
done
- name: Slack Notification
uses: 8398a7/action-slack@v3
if: always()
with:
status: ${{ steps.check_status.outputs.success == 'true' && 'success' || 'failure' }}
fields: repo,message,commit,author,action,eventName,ref,workflow,job,took
text: |
Mobile CI Build Result
Branch: ${{ github.event.inputs.branch }}
Workflow: ${{ github.event.inputs.workflow_id }}
Build URL: ${{ steps.check_status.outputs.build_url }}
env:
SLACK_WEBHOOK_URL: ${{ secrets.RELEASE_SLACK_WEBHOOK }}
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,18 @@
# Release Notes
## Version 0.7.3 - 07/11/2024
### New Features
- Enable custom URLs for published pages
- Support toggling headings
- Create a subpage by typing in the document
- Turn selected blocks into a subpage
- Add a manual date picker for the Date property

### Bug Fixes
- Fixed an issue where the workspace owner was unable to delete spaces created by others
- Fixed cursor height inconsistencies with text height
- Fixed editing issues in Kanban cards
- Fixed an issue preventing images or files from being dropped into empty paragraphs

## Version 0.7.2 - 22/10/2024
### New Features
- Copy link to block
Expand Down
47 changes: 47 additions & 0 deletions codemagic.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
workflows:
ios-workflow:
name: iOS Workflow
instance_type: mac_mini_m2
max_build_duration: 30
environment:
flutter: 3.22.3
xcode: latest
cocoapods: default

scripts:
- name: Build Flutter
script: |
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
source "$HOME/.cargo/env"
rustc --version
cargo --version
cd frontend
rustup target install aarch64-apple-ios-sim
cargo install --force cargo-make
cargo install --force duckscript_cli
cargo install --force cargo-lipo
cargo make appflowy-flutter-deps-tools
cargo make --profile development-ios-arm64-sim appflowy-core-dev-ios
cargo make --profile development-ios-arm64-sim code_generation
- name: iOS integration tests
script: |
cd frontend/appflowy_flutter
flutter emulators --launch apple_ios_simulator
flutter -d iPhone test integration_test/runner.dart
artifacts:
- build/ios/ipa/*.ipa
- /tmp/xcodebuild_logs/*.log
- flutter_drive.log

publishing:
email:
recipients:
- lucas.xu@appflowy.io
notify:
success: true
failure: true
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';

import '../../shared/util.dart';

void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();

group('Block option interaction tests', () {
testWidgets('has correct block selection on tap option button',
(tester) async {
await tester.initializeAppFlowy();
await tester.tapAnonymousSignInButton();

// We edit the document by entering some characters, to ensure the document has focus
await tester.editor.updateSelection(
Selection.collapsed(Position(path: [2])),
);

// Insert character 'a' three times - easy to identify
await tester.ime.insertText('aaa');
await tester.pumpAndSettle();

final editorState = tester.editor.getCurrentEditorState();
final node = editorState.getNodeAtPath([2]);
expect(node?.delta?.toPlainText(), startsWith('aaa'));

final multiSelection = Selection(
start: Position(path: [2], offset: 3),
end: Position(path: [4], offset: 40),
);

// Select multiple items
await tester.editor.updateSelection(multiSelection);
await tester.pumpAndSettle();

// Press the block option menu
await tester.editor.hoverAndClickOptionMenuButton([2]);
await tester.pumpAndSettle();

// Expect the selection to be Block type and not have changed
expect(editorState.selectionType, SelectionType.block);
expect(editorState.selection, multiSelection);
});
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import 'document_with_file_test.dart' as document_with_file_test;
import 'document_with_image_block_test.dart' as document_with_image_block_test;
import 'document_with_multi_image_block_test.dart'
as document_with_multi_image_block_test;
import 'document_block_option_test.dart' as document_block_option_test;

void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
Expand All @@ -19,7 +20,5 @@ void main() {
document_more_actions_test.main();
document_with_file_test.main();
document_shortcuts_test.main();

// Disable subPage test temporarily, enable it in version 0.7.2
// document_sub_page_test.main();
document_block_option_test.main();
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ import '../../shared/util.dart';
void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();

group('document page style', () {
group('document page style:', () {
double getCurrentEditorFontSize() {
final editorPage = find
.byType(AppFlowyEditorPage)
Expand All @@ -57,11 +57,9 @@ void main() {
.single
.widget as AppFlowyEditorPage;
return editorPage.styleCustomizer
.style()
.textStyleConfiguration
.text
.height ??
PageStyleLineHeightLayout.normal.lineHeight;
.style()
.textStyleConfiguration
.lineHeight;
}

testWidgets('change font size in page style settings', (tester) async {
Expand All @@ -87,20 +85,24 @@ void main() {
await tester.openPage(gettingStarted);
// click the layout button
await tester.tapButton(find.byType(MobileViewPageLayoutButton));
var lineHeight = getCurrentEditorLineHeight();
expect(
getCurrentEditorLineHeight(),
lineHeight,
PageStyleLineHeightLayout.normal.lineHeight,
);
// change line height from normal to large
await tester.tapSvgButton(FlowySvgs.m_layout_large_s);
await tester.pumpAndSettle();
lineHeight = getCurrentEditorLineHeight();
expect(
getCurrentEditorLineHeight(),
lineHeight,
PageStyleLineHeightLayout.large.lineHeight,
);
// change line height from large to small
await tester.tapSvgButton(FlowySvgs.m_layout_small_s);
lineHeight = getCurrentEditorLineHeight();
expect(
getCurrentEditorLineHeight(),
lineHeight,
PageStyleLineHeightLayout.small.lineHeight,
);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,18 @@ import '../../shared/util.dart';
void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();

group('create new page', () {
group('create new page in home page:', () {
testWidgets('create document', (tester) async {
await tester.initializeAppFlowy(
cloudType: AuthenticatorType.local,
);
await tester.launchInAnonymousMode();

// tap the create page button
final createPageButton = find.byWidgetPredicate(
(widget) =>
widget is FlowySvg &&
widget.svg.path == FlowySvgs.m_home_unselected_m.path,
widget.svg.path == FlowySvgs.m_home_add_m.path,
);
await tester.tapButton(createPageButton);
await tester.pumpAndSettle();
expect(find.byType(MobileDocumentScreen), findsOneWidget);
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ import '../../shared/util.dart';
void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();

group('anonymous sign in on mobile', () {
group('anonymous sign in on mobile:', () {
testWidgets('anon user and then sign in', (tester) async {
await tester.initializeAppFlowy();
await tester.launchInAnonymousMode();

// expect to see the home page
expect(find.byType(MobileHomeScreen), findsOneWidget);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,13 @@ import 'mobile/document/page_style_test.dart' as page_style_test;
import 'mobile/home_page/create_new_page_test.dart' as create_new_page_test;
import 'mobile/sign_in/anonymous_sign_in_test.dart' as anonymous_sign_in_test;

Future<void> runIntegrationOnMobile() async {
Future<void> main() async {
Log.shared.disableLog = true;

await runIntegration1OnMobile();
}

Future<void> runIntegration1OnMobile() async {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();

anonymous_sign_in_test.main();
Expand Down
4 changes: 2 additions & 2 deletions frontend/appflowy_flutter/integration_test/runner.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import 'desktop_runner_5.dart';
import 'desktop_runner_6.dart';
import 'desktop_runner_7.dart';
import 'desktop_runner_8.dart';
import 'mobile_runner.dart';
import 'mobile_runner_1.dart';

/// The main task runner for all integration tests in AppFlowy.
///
Expand All @@ -28,7 +28,7 @@ Future<void> main() async {
await runIntegration7OnDesktop();
await runIntegration8OnDesktop();
} else if (Platform.isIOS || Platform.isAndroid) {
await runIntegrationOnMobile();
await runIntegration1OnMobile();
} else {
throw Exception('Unsupported platform');
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,10 @@ class _MobileViewPageState extends State<MobileViewPage> {
@override
void dispose() {
_appBarOpacity.dispose();
_scrollNotificationObserver?.removeListener(_onScrollNotification);

// there's no need to remove the listener, because the observer will be disposed when the widget is unmounted.
// inside the observer, the listener will be removed automatically.
// _scrollNotificationObserver?.removeListener(_onScrollNotification);
_scrollNotificationObserver = null;

super.dispose();
Expand Down
Loading

0 comments on commit f12c9f7

Please sign in to comment.