diff --git a/CHANGELOG.md b/CHANGELOG.md index ba9fb8cbcd..12796b00f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,12 +30,13 @@ - Fix: サーバー情報画面(`/instance-info/{domain}`)でブロックができないのを修正 - Fix: 未読のお知らせの「わかった」をクリック・タップしてもその場で「わかった」が消えない問題を修正 - Fix: iOSで画面を回転させるとテキストサイズが変わる問題を修正 +- Fix: タイムラインを下にスクロールしてノート画面に移動して再び戻ったら以前のスクロール位置を失う問題を修正 ### Server - cacheRemoteFilesの初期値はfalseになりました -- 一部のfeatured noteを照会できない問題を修正 - ファイルアップロード時等にファイル名の拡張子を修正する関数(correctFilename)の挙動を改善 -- fix: muteがapiからのuser list timeline取得で機能しない問題を修正 +- Fix: 一部のfeatured noteを照会できない問題を修正 +- Fix: muteがapiからのuser list timeline取得で機能しない問題を修正 ## 13.14.2 diff --git a/packages/frontend/src/scripts/scroll.ts b/packages/frontend/src/scripts/scroll.ts index b2b2c41dcf..7338de62b6 100644 --- a/packages/frontend/src/scripts/scroll.ts +++ b/packages/frontend/src/scripts/scroll.ts @@ -30,7 +30,7 @@ export function getScrollPosition(el: HTMLElement | null): number { export function onScrollTop(el: HTMLElement, cb: () => unknown, tolerance = 1, once = false) { // とりあえず評価してみる - if (isTopVisible(el)) { + if (el.isConnected && isTopVisible(el)) { cb(); if (once) return null; } @@ -54,7 +54,7 @@ export function onScrollBottom(el: HTMLElement, cb: () => unknown, tolerance = 1 const container = getScrollContainer(el); // とりあえず評価してみる - if (isBottomVisible(el, tolerance, container)) { + if (el.isConnected && isBottomVisible(el, tolerance, container)) { cb(); if (once) return null; } diff --git a/packages/frontend/test/scroll.test.ts b/packages/frontend/test/scroll.test.ts new file mode 100644 index 0000000000..3fa740b11c --- /dev/null +++ b/packages/frontend/test/scroll.test.ts @@ -0,0 +1,64 @@ +/* + * SPDX-FileCopyrightText: syuilo and other misskey contributors + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { describe, test, assert, afterEach } from 'vitest'; +import { Window } from 'happy-dom'; +import { onScrollBottom, onScrollTop } from '@/scripts/scroll'; + +describe('Scroll', () => { + describe('onScrollTop', () => { + test('Initial onScrollTop callback for connected elements', () => { + const { document } = new Window(); + const div = document.createElement('div'); + assert.strictEqual(div.scrollTop, 0); + + document.body.append(div); + + let called = false; + onScrollTop(div as any as HTMLElement, () => called = true); + + assert.ok(called); + }); + + test('No onScrollTop callback for disconnected elements', () => { + const { document } = new Window(); + const div = document.createElement('div'); + assert.strictEqual(div.scrollTop, 0); + + let called = false; + onScrollTop(div as any as HTMLElement, () => called = true); + + assert.ok(!called); + }); + }); + + describe('onScrollBottom', () => { + test('Initial onScrollBottom callback for connected elements', () => { + const { document } = new Window(); + const div = document.createElement('div'); + assert.strictEqual(div.scrollTop, 0); + (div as any).scrollHeight = 100; // happy-dom has no scrollHeight + + document.body.append(div); + + let called = false; + onScrollBottom(div as any as HTMLElement, () => called = true); + + assert.ok(called); + }); + + test('No onScrollBottom callback for disconnected elements', () => { + const { document } = new Window(); + const div = document.createElement('div'); + assert.strictEqual(div.scrollTop, 0); + (div as any).scrollHeight = 100; // happy-dom has no scrollHeight + + let called = false; + onScrollBottom(div as any as HTMLElement, () => called = true); + + assert.ok(!called); + }); + }); +});