Skip to content

Commit 83c393f

Browse files
committed
[FIX] Spreadsheet: fix scroll on ios
When opening a spreadsheet and scrolling towards the bottom of the sheet, the "default" behaviour of ios which is to have some sort of wobble when we scrolled all the way down, is triggered. It should not occur when scrolling inside the grid. closes #7470 Task: 5270869 Signed-off-by: Pierre Rousseau (pro) <pro@odoo.com>
1 parent 948c51e commit 83c393f

File tree

5 files changed

+56
-19
lines changed

5 files changed

+56
-19
lines changed

src/components/dashboard/dashboard.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,19 @@ export class SpreadsheetDashboard extends Component<Props, SpreadsheetChildEnv>
6363
});
6464
this.cellPopovers = useStore(CellPopoverStore);
6565

66-
useTouchScroll(this.gridRef, this.moveCanvas.bind(this), () => {
67-
const { scrollY } = this.env.model.getters.getActiveSheetScrollInfo();
68-
return scrollY > 0;
69-
});
66+
useTouchScroll(
67+
this.gridRef,
68+
this.moveCanvas.bind(this),
69+
() => {
70+
const { scrollY } = this.env.model.getters.getActiveSheetScrollInfo();
71+
return scrollY > 0;
72+
},
73+
() => {
74+
const { maxOffsetY } = this.env.model.getters.getMaximumSheetOffset();
75+
const { scrollY } = this.env.model.getters.getActiveSheetScrollInfo();
76+
return scrollY < maxOffsetY;
77+
}
78+
);
7079
}
7180

7281
get gridContainer() {

src/components/grid/grid.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -196,10 +196,19 @@ export class Grid extends Component<Props, SpreadsheetChildEnv> {
196196
() => [this.sidePanel.isMainPanelOpen, this.sidePanel.isSecondaryPanelOpen]
197197
);
198198

199-
useTouchScroll(this.gridRef, this.moveCanvas.bind(this), () => {
200-
const { scrollY } = this.env.model.getters.getActiveSheetScrollInfo();
201-
return scrollY > 0;
202-
});
199+
useTouchScroll(
200+
this.gridRef,
201+
this.moveCanvas.bind(this),
202+
() => {
203+
const { scrollY } = this.env.model.getters.getActiveSheetScrollInfo();
204+
return scrollY > 0;
205+
},
206+
() => {
207+
const { maxOffsetY } = this.env.model.getters.getMaximumSheetOffset();
208+
const { scrollY } = this.env.model.getters.getActiveSheetScrollInfo();
209+
return scrollY < maxOffsetY;
210+
}
211+
);
203212
}
204213

205214
get highlights() {

src/components/helpers/touch_scroll_hook.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,9 @@ export const resetTimeoutDuration = 100;
1010

1111
export function useTouchScroll(
1212
ref: Ref<HTMLElement>,
13-
1413
updateScroll: (offsetX: number, offsetY: number) => void,
15-
16-
canMoveUp: () => boolean
14+
canMoveUp: () => boolean,
15+
canMoveDown: () => boolean
1716
) {
1817
let lastX = 0;
1918
let lastY = 0;
@@ -57,13 +56,13 @@ export function useTouchScroll(
5756
lastX = clientX;
5857
lastY = clientY;
5958
lastTime = currentTime;
60-
61-
if (canMoveUp()) {
59+
if ((deltaY < 0 && canMoveUp()) || (deltaY > 0 && canMoveDown())) {
6260
if (event.cancelable) {
6361
event.preventDefault();
6462
}
6563
event.stopPropagation();
6664
}
65+
6766
resetTimeout = setTimeout(() => {
6867
velocityX = 0;
6968
velocityY = 0;

src/plugins/ui_stateful/sheetview.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ export class SheetViewPlugin extends UIPlugin {
109109
"getFigureUI",
110110
"getPositionAnchorOffset",
111111
"getGridOffset",
112+
"getMaximumSheetOffset",
112113
] as const;
113114

114115
private viewports: Record<UID, SheetViewports | undefined> = {};
@@ -396,7 +397,7 @@ export class SheetViewPlugin extends UIPlugin {
396397
return { x, y, width, height };
397398
}
398399

399-
private getMaximumSheetOffset(): { maxOffsetX: Pixel; maxOffsetY: Pixel } {
400+
getMaximumSheetOffset(): { maxOffsetX: Pixel; maxOffsetY: Pixel } {
400401
const sheetId = this.getters.getActiveSheetId();
401402
const { width, height } = this.getMainViewportRect();
402403
const viewport = this.getMainInternalViewport(sheetId);

tests/grid/grid_component.test.ts

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ describe("Grid component", () => {
263263
expect(getVerticalScroll()).toBe(50);
264264
});
265265

266-
test("Event is stopped if not at the top", async () => {
266+
test("Event is stopped if not at the top when scrolling upwards", async () => {
267267
const grid = fixture.querySelector(".o-grid-overlay")!;
268268
expect(getHorizontalScroll()).toBe(0);
269269
expect(getVerticalScroll()).toBe(0);
@@ -272,16 +272,35 @@ describe("Grid component", () => {
272272
fixture.addEventListener("touchmove", mockCallback);
273273

274274
triggerTouchEvent(grid, "touchstart", { clientX: 0, clientY: 150, identifier: 1 });
275-
// move down; we are at the top: ev not prevented
275+
// move down; we are at the top: ev is prevented
276276
triggerTouchEvent(grid, "touchmove", { clientX: 0, clientY: 120, identifier: 2 });
277-
expect(mockCallback).toBeCalledTimes(1);
277+
expect(mockCallback).toBeCalledTimes(0);
278278
jest.advanceTimersByTime(10);
279279
// move up:; we are not at the top: ev prevented
280280
triggerTouchEvent(grid, "touchmove", { clientX: 0, clientY: 150, identifier: 3 });
281-
expect(mockCallback).toBeCalledTimes(1);
281+
expect(mockCallback).toBeCalledTimes(0);
282282
// move up again but we are at the stop: ev not prevented
283283
triggerTouchEvent(grid, "touchmove", { clientX: 0, clientY: 150, identifier: 4 });
284-
expect(mockCallback).toBeCalledTimes(2);
284+
expect(mockCallback).toBeCalledTimes(1);
285+
});
286+
287+
test("Event is stopped if not at the top when scrolling downwards", async () => {
288+
const grid = fixture.querySelector(".o-grid-overlay")!;
289+
const { maxOffsetY } = model.getters.getMaximumSheetOffset();
290+
expect(getHorizontalScroll()).toBe(0);
291+
expect(getVerticalScroll()).toBe(0);
292+
293+
const mockCallback = jest.fn(() => {});
294+
fixture.addEventListener("touchmove", mockCallback);
295+
296+
triggerTouchEvent(grid, "touchstart", { clientX: 0, clientY: maxOffsetY + 10, identifier: 1 });
297+
// move down, to scroll all the way down; ev is prevented
298+
triggerTouchEvent(grid, "touchmove", { clientX: 0, clientY: 10, identifier: 2 });
299+
expect(mockCallback).toBeCalledTimes(0);
300+
jest.advanceTimersByTime(10);
301+
// move down again, we are at the bottom: ev prevented
302+
triggerTouchEvent(grid, "touchmove", { clientX: 0, clientY: 0, identifier: 3 });
303+
expect(mockCallback).toBeCalledTimes(1);
285304
});
286305

287306
test("Double clicking only opens composer when actually targetting grid overlay", async () => {

0 commit comments

Comments
 (0)