fix(ios): adjust bootom padding of body when keyboard toolbar existed (#11410)

Close [BS-2919](https://linear.app/affine-design/issue/BS-2919/【移动端】ios-页面底部点几,页面定位有问题,光标和浮层重叠,并且看不到新添加的-block)
Close [BS-2918](https://linear.app/affine-design/issue/BS-2918/【移动端】ios-添加标题无法展示对应-block,滑动页面也无效,光标位置也不对)

## Changes
- Fixed body padding calculation when keyboard toolbar is present
- Removed redundant position controller logic and simplified the implementation
This commit is contained in:
L-Sun
2025-04-03 01:51:57 +00:00
parent 5109ceccec
commit 80a663efe7
8 changed files with 40 additions and 33 deletions

View File

@@ -95,6 +95,6 @@ export class AffineKeyboardToolPanel extends SignalWatcher(
@property({ attribute: false }) @property({ attribute: false })
accessor context!: KeyboardToolbarContext; accessor context!: KeyboardToolbarContext;
@property({ type: Number }) @property({ attribute: false })
accessor height = 0; accessor height = 0;
} }

View File

@@ -315,7 +315,7 @@ export class AffineKeyboardToolbar extends SignalWatcher(
<affine-keyboard-tool-panel <affine-keyboard-tool-panel
.config=${this._currentPanelConfig} .config=${this._currentPanelConfig}
.context=${this._context} .context=${this._context}
height=${this.panelHeight$.value} .height=${this.panelHeight$.value}
></affine-keyboard-tool-panel> ></affine-keyboard-tool-panel>
`; `;
} }

View File

@@ -4,8 +4,6 @@ import type { BlockStdScope, ShadowlessElement } from '@blocksuite/std';
import { effect, type Signal } from '@preact/signals-core'; import { effect, type Signal } from '@preact/signals-core';
import type { ReactiveController, ReactiveControllerHost } from 'lit'; import type { ReactiveController, ReactiveControllerHost } from 'lit';
import { TOOLBAR_HEIGHT } from './styles';
/** /**
* This controller is used to control the keyboard toolbar position * This controller is used to control the keyboard toolbar position
*/ */
@@ -25,7 +23,7 @@ export class PositionController implements ReactiveController {
} }
hostConnected() { hostConnected() {
const { keyboard, panelOpened } = this.host; const { keyboard } = this.host;
this._disposables.add( this._disposables.add(
effect(() => { effect(() => {
@@ -36,20 +34,6 @@ export class PositionController implements ReactiveController {
); );
this.host.style.bottom = '0px'; this.host.style.bottom = '0px';
this._disposables.add(
effect(() => {
if (keyboard.visible$.value) {
document.body.style.paddingBottom = `${keyboard.height$.value + TOOLBAR_HEIGHT}px`;
} else if (panelOpened) {
document.body.style.paddingBottom = `${this.host.panelHeight$.peek() + TOOLBAR_HEIGHT}px`;
} else {
document.body.style.paddingBottom = '';
}
})
);
this._disposables.add(() => {
document.body.style.paddingBottom = '';
});
} }
hostDisconnected() { hostDisconnected() {

View File

@@ -2,8 +2,6 @@ import { scrollbarStyle } from '@blocksuite/affine-shared/styles';
import { unsafeCSSVarV2 } from '@blocksuite/affine-shared/theme'; import { unsafeCSSVarV2 } from '@blocksuite/affine-shared/theme';
import { css } from 'lit'; import { css } from 'lit';
export const TOOLBAR_HEIGHT = 46;
export const keyboardToolbarStyles = css` export const keyboardToolbarStyles = css`
affine-keyboard-toolbar { affine-keyboard-toolbar {
position: fixed; position: fixed;
@@ -13,7 +11,7 @@ export const keyboardToolbarStyles = css`
.keyboard-toolbar { .keyboard-toolbar {
width: 100%; width: 100%;
height: ${TOOLBAR_HEIGHT}px; height: 46px;
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
padding: 0px 8px; padding: 0px 8px;

View File

@@ -1,7 +1,7 @@
import { cssVarV2 } from '@toeverything/theme/v2'; import { cssVarV2 } from '@toeverything/theme/v2';
import { createVar, style } from '@vanilla-extract/css'; import { createVar, style } from '@vanilla-extract/css';
import { globalVars } from '../../styles/mobile.css'; import { globalVars } from '../../styles/variables.css';
export const appTabsBackground = createVar('appTabsBackground'); export const appTabsBackground = createVar('appTabsBackground');

View File

@@ -1,10 +1,12 @@
import { LiveData, Service } from '@toeverything/infra'; import { LiveData, Service } from '@toeverything/infra';
import { setElementVars } from '@vanilla-extract/dynamic';
import { distinctUntilChanged, scan } from 'rxjs';
import { globalVars } from '../../../styles/variables.css';
import type { VirtualKeyboardProvider } from '../providers/virtual-keyboard'; import type { VirtualKeyboardProvider } from '../providers/virtual-keyboard';
export class VirtualKeyboardService extends Service { export class VirtualKeyboardService extends Service {
readonly visible$ = new LiveData(false); readonly visible$ = new LiveData(false);
readonly height$ = new LiveData(0); readonly height$ = new LiveData(0);
constructor( constructor(
@@ -21,5 +23,20 @@ export class VirtualKeyboardService extends Service {
this.height$.next(info.height); this.height$.next(info.height);
}) })
); );
// record the static keyboard height to css var
const subscription = this.height$
.pipe(
scan((lastHeight, currentHeight) =>
this.visible$.value ? currentHeight : lastHeight
),
distinctUntilChanged()
)
.subscribe(height => {
setElementVars(document.body, {
[globalVars.appKeyboardHeight]: `${height}px`,
});
});
this.disposables.push(() => subscription.unsubscribe());
} }
} }

View File

@@ -1,10 +1,7 @@
import { cssVarV2 } from '@toeverything/theme/v2'; import { cssVarV2 } from '@toeverything/theme/v2';
import { createVar, globalStyle } from '@vanilla-extract/css'; import { globalStyle } from '@vanilla-extract/css';
export const globalVars = { import { globalVars } from './variables.css';
appTabHeight: createVar('appTabHeight'),
appTabSafeArea: createVar('appTabSafeArea'),
};
globalStyle(':root', { globalStyle(':root', {
vars: { vars: {
@@ -20,15 +17,19 @@ globalStyle('body', {
minHeight: '100dvh', minHeight: '100dvh',
overflowY: 'unset', overflowY: 'unset',
}); });
globalStyle('body:has(> #app-tabs)', { globalStyle('body:has(>#app-tabs):not(:has(affine-keyboard-toolbar))', {
paddingBottom: globalVars.appTabSafeArea, paddingBottom: globalVars.appTabSafeArea,
}); });
globalStyle('body:has(#app-tabs) affine-keyboard-tool-panel', { globalStyle('body:has(affine-keyboard-toolbar)', {
paddingBottom: `calc(${globalVars.appTabHeight} + env(safe-area-inset-bottom) + 8px)`, paddingBottom: `calc(${globalVars.appKeyboardHeight} + 46px)`,
}); });
globalStyle('body:has(#app-tabs) edgeless-toolbar-widget', { globalStyle('body:has(>#app-tabs) affine-keyboard-tool-panel', {
paddingBottom: `calc(${globalVars.appTabSafeArea} + 8px)`,
});
globalStyle('body:has(>#app-tabs) edgeless-toolbar-widget', {
bottom: globalVars.appTabSafeArea, bottom: globalVars.appTabSafeArea,
}); });
globalStyle('html', { globalStyle('html', {
height: '100dvh', height: '100dvh',
overflowY: 'auto', overflowY: 'auto',

View File

@@ -0,0 +1,7 @@
import { createVar } from '@vanilla-extract/css';
export const globalVars = {
appKeyboardHeight: createVar('appKeyboardHeight'),
appTabHeight: createVar('appTabHeight'),
appTabSafeArea: createVar('appTabSafeArea'),
};