mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-08-01 01:29:31 +08:00
fix(ios): stabilize keyboard toolbar, image picker, and scrolling (#15182)
## Summary - keep the editor active when iOS keyboard toolbar interactions move focus into range-sync excluded widgets - use the native iOS image picker/source sheet and sync native presentation with the app theme - pin `ListViewKit` to `1.1.6` so the iOS workspace resolves with Xcode 16.3 - restore vertical scrolling in the iOS `WKWebView` by removing the global `contentOffset` reset while preserving zoom prevention ## Test plan - [x] `yarn vitest --run --config \"vitest.config.ts\" --browser.enabled=false \"src/__tests__/inline/active.unit.spec.ts\"` - [x] `LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 xcodebuild -resolvePackageDependencies -workspace \"packages/frontend/apps/ios/App/App.xcworkspace\" -scheme \"App\"` - [x] `xcodebuild -workspace \"App.xcworkspace\" -scheme \"App\" -destination \"generic/platform=iOS Simulator\" build CODE_SIGNING_ALLOWED=NO ONLY_ACTIVE_ARCH=YES ARCHS=arm64` - [x] Xcode build validation for the updated PR branch
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* @vitest-environment happy-dom
|
||||
*/
|
||||
import { afterEach, describe, expect, test } from 'vitest';
|
||||
|
||||
import { shouldDeactivateEditorOnFocusOut } from '../../inline/range/active.js';
|
||||
import { RANGE_SYNC_EXCLUDE_ATTR } from '../../inline/range/consts.js';
|
||||
|
||||
afterEach(() => {
|
||||
document.body.replaceChildren();
|
||||
});
|
||||
|
||||
describe('editor active helpers', () => {
|
||||
test('keeps editor active when focus moves into an excluded widget', () => {
|
||||
const host = document.createElement('editor-host');
|
||||
const paragraph = document.createElement('div');
|
||||
host.append(paragraph);
|
||||
|
||||
const widgetRoot = document.createElement('div');
|
||||
widgetRoot.setAttribute(RANGE_SYNC_EXCLUDE_ATTR, 'true');
|
||||
const widgetButton = document.createElement('button');
|
||||
widgetRoot.append(widgetButton);
|
||||
|
||||
document.body.append(host, widgetRoot);
|
||||
|
||||
expect(shouldDeactivateEditorOnFocusOut(host, widgetButton)).toBe(false);
|
||||
});
|
||||
|
||||
test('keeps editor active when focus stays inside the editor host', () => {
|
||||
const host = document.createElement('editor-host');
|
||||
const input = document.createElement('input');
|
||||
host.append(input);
|
||||
document.body.append(host);
|
||||
|
||||
expect(shouldDeactivateEditorOnFocusOut(host, input)).toBe(false);
|
||||
});
|
||||
|
||||
test('deactivates editor when focus moves to a regular external control', () => {
|
||||
const host = document.createElement('editor-host');
|
||||
const paragraph = document.createElement('div');
|
||||
host.append(paragraph);
|
||||
|
||||
const externalButton = document.createElement('button');
|
||||
document.body.append(host, externalButton);
|
||||
|
||||
expect(shouldDeactivateEditorOnFocusOut(host, externalButton)).toBe(true);
|
||||
});
|
||||
|
||||
test('keeps editor active on focusout when related target is null', () => {
|
||||
// Focus leaving to nowhere (e.g. block-level selection) must not deactivate
|
||||
// the editor via `focusout`; the host `blur` handler owns that case.
|
||||
const host = document.createElement('editor-host');
|
||||
document.body.append(host);
|
||||
|
||||
expect(shouldDeactivateEditorOnFocusOut(host, null)).toBe(false);
|
||||
});
|
||||
|
||||
test('keeps editor active when the related target is not a DOM node', () => {
|
||||
const host = document.createElement('editor-host');
|
||||
document.body.append(host);
|
||||
|
||||
expect(shouldDeactivateEditorOnFocusOut(host, new EventTarget())).toBe(
|
||||
false
|
||||
);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user