timelineBackTopBehavior
This commit is contained in:
parent
9f79e494f5
commit
4785b9bfdd
7 changed files with 38 additions and 10 deletions
5
locales/index.d.ts
vendored
5
locales/index.d.ts
vendored
|
@ -1097,6 +1097,7 @@ export interface Locale {
|
|||
"doYouAgree": string;
|
||||
"beSureToReadThisAsItIsImportant": string;
|
||||
"iHaveReadXCarefullyAndAgree": string;
|
||||
"timelineBackTopBehavior": string;
|
||||
"_initialAccountSetting": {
|
||||
"accountCreated": string;
|
||||
"letsStartAccountSetup": string;
|
||||
|
@ -1637,6 +1638,10 @@ export interface Locale {
|
|||
"dialog": string;
|
||||
"quiet": string;
|
||||
};
|
||||
"_timelineBackTopBehavior": {
|
||||
"newest": string;
|
||||
"next": string;
|
||||
};
|
||||
"_channel": {
|
||||
"create": string;
|
||||
"edit": string;
|
||||
|
|
|
@ -1094,6 +1094,7 @@ expired: "期限切れ"
|
|||
doYouAgree: "同意しますか?"
|
||||
beSureToReadThisAsItIsImportant: "重要ですので必ずお読みください。"
|
||||
iHaveReadXCarefullyAndAgree: "「{x}」の内容をよく読み、同意します。"
|
||||
timelineBackTopBehavior: "タイムラインのスクロールが先頭に戻った時の挙動"
|
||||
|
||||
_initialAccountSetting:
|
||||
accountCreated: "アカウントの作成が完了しました!"
|
||||
|
@ -1555,6 +1556,10 @@ _serverDisconnectedBehavior:
|
|||
dialog: "ダイアログで警告"
|
||||
quiet: "控えめに警告"
|
||||
|
||||
_timelineBackTopBehavior:
|
||||
newest: "最新の投稿を表示"
|
||||
next: "次の投稿を遡る"
|
||||
|
||||
_channel:
|
||||
create: "チャンネルを作成"
|
||||
edit: "チャンネルを編集"
|
||||
|
|
|
@ -47,7 +47,7 @@ import MkButton from '@/components/MkButton.vue';
|
|||
import { defaultStore } from '@/store';
|
||||
import { MisskeyEntity } from '@/types/date-separated-list';
|
||||
import { i18n } from '@/i18n';
|
||||
import { UAParser } from 'ua-parser-js';
|
||||
import { isWebKit } from '@/scripts/useragent';
|
||||
|
||||
const SECOND_FETCH_LIMIT = 30;
|
||||
const TOLERANCE = 6;
|
||||
|
@ -94,8 +94,7 @@ function concatMapWithArray(map: MisskeyEntityMap, entities: MisskeyEntity[]): M
|
|||
return new Map([...map, ...arrayToEntries(entities)]);
|
||||
}
|
||||
|
||||
const ua = new UAParser(navigator.userAgent);
|
||||
const isWebKit = ua.getEngine().name === 'WebKit';
|
||||
const timelineBackTopBehavior = computed(() => isWebKit() ? 'newest' : defaultStore.reactiveState.timelineBackTopBehavior.value);
|
||||
</script>
|
||||
<script lang="ts" setup>
|
||||
import { infoImageUrl } from '@/instance';
|
||||
|
@ -200,7 +199,7 @@ watch([$$(rootEl), $$(scrollObserver)], () => {
|
|||
* weakBackedがtrue→falseになったらexecuteQueue
|
||||
*/
|
||||
watch($$(weakBacked), () => {
|
||||
if (!isWebKit && !weakBacked) {
|
||||
if (timelineBackTopBehavior.value === 'next' && !weakBacked) {
|
||||
executeQueue();
|
||||
}
|
||||
});
|
||||
|
@ -499,7 +498,7 @@ const prepend = (item: MisskeyEntity): void => {
|
|||
// かなりスクロールの先頭にいる場合
|
||||
if (items.value.has(item.id)) return; // 既にタイムラインにある場合は何もしない
|
||||
unshiftItems([item]);
|
||||
} else if (!isWebKit && !weakBacked) {
|
||||
} else if (timelineBackTopBehavior.value === 'next' && !weakBacked) {
|
||||
// ちょっと先頭にいる場合はスクロールを調整する
|
||||
prependQueue(item);
|
||||
executeQueue();
|
||||
|
@ -538,7 +537,7 @@ function concatItems(oldItems: MisskeyEntity[]) {
|
|||
async function executeQueue() {
|
||||
if (queue.value.size === 0) return;
|
||||
if (isPausingUpdateByExecutingQueue.value) return;
|
||||
if (isWebKit) {
|
||||
if (timelineBackTopBehavior === 'newest') {
|
||||
// Safariは最新のアイテムにするだけ
|
||||
const newItems = Array.from(queue.value.values()).slice(-1 * props.pagination.limit);
|
||||
unshiftItems(newItems);
|
||||
|
|
|
@ -21,10 +21,18 @@
|
|||
</MkRadios>
|
||||
|
||||
<FormSection>
|
||||
<div class="_gaps_s">
|
||||
<MkSwitch v-model="showFixedPostForm">{{ i18n.ts.showFixedPostForm }}</MkSwitch>
|
||||
<MkSwitch v-model="showFixedPostFormInChannel">{{ i18n.ts.showFixedPostFormInChannel }}</MkSwitch>
|
||||
<MkSwitch v-model="showTimelineReplies">{{ i18n.ts.flagShowTimelineReplies }}<template #caption>{{ i18n.ts.flagShowTimelineRepliesDescription }} {{ i18n.ts.reflectMayTakeTime }}</template></MkSwitch>
|
||||
<div class="_gaps_m">
|
||||
<div class="_gaps_s">
|
||||
<MkSwitch v-model="showFixedPostForm">{{ i18n.ts.showFixedPostForm }}</MkSwitch>
|
||||
<MkSwitch v-model="showFixedPostFormInChannel">{{ i18n.ts.showFixedPostFormInChannel }}</MkSwitch>
|
||||
<MkSwitch v-model="showTimelineReplies">{{ i18n.ts.flagShowTimelineReplies }}<template #caption>{{ i18n.ts.flagShowTimelineRepliesDescription }} {{ i18n.ts.reflectMayTakeTime }}</template></MkSwitch>
|
||||
</div>
|
||||
|
||||
<MkSelect v-model="timelineBackTopBehavior" :disabled="isWebKit()">
|
||||
<template #label>{{ i18n.ts.timelineBackTopBehavior }}</template>
|
||||
<option value="newest">{{ i18n.ts._timelineBackTopBehavior.newest }}</option>
|
||||
<option value="next">{{ i18n.ts._timelineBackTopBehavior.next }}</option>
|
||||
</MkSelect>
|
||||
</div>
|
||||
</FormSection>
|
||||
|
||||
|
@ -180,6 +188,7 @@ import { unisonReload } from '@/scripts/unison-reload';
|
|||
import { i18n } from '@/i18n';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata';
|
||||
import { miLocalStorage } from '@/local-storage';
|
||||
import { isWebKit } from '@/scripts/useragent';
|
||||
|
||||
const lang = ref(miLocalStorage.getItem('lang'));
|
||||
const fontSize = ref(miLocalStorage.getItem('fontSize'));
|
||||
|
@ -226,6 +235,7 @@ const mediaListWithOneImageAppearance = computed(defaultStore.makeGetterSetter('
|
|||
const notificationPosition = computed(defaultStore.makeGetterSetter('notificationPosition'));
|
||||
const notificationStackAxis = computed(defaultStore.makeGetterSetter('notificationStackAxis'));
|
||||
const showTimelineReplies = computed(defaultStore.makeGetterSetter('showTimelineReplies'));
|
||||
const timelineBackTopBehavior = computed(defaultStore.makeGetterSetter('timelineBackTopBehavior'));
|
||||
|
||||
watch(lang, () => {
|
||||
miLocalStorage.setItem('lang', lang.value as string);
|
||||
|
|
|
@ -87,6 +87,7 @@ const defaultStoreSaveKeys: (keyof typeof defaultStore['state'])[] = [
|
|||
'numberOfPageCache',
|
||||
'aiChanMode',
|
||||
'mediaListWithOneImageAppearance',
|
||||
'timelineBackTopBehavior',
|
||||
];
|
||||
const coldDeviceStorageSaveKeys: (keyof typeof ColdDeviceStorage.default)[] = [
|
||||
'lightTheme',
|
||||
|
|
3
packages/frontend/src/scripts/useragent.ts
Normal file
3
packages/frontend/src/scripts/useragent.ts
Normal file
|
@ -0,0 +1,3 @@
|
|||
import { UAParser } from 'ua-parser-js';
|
||||
const ua = new UAParser(navigator.userAgent);
|
||||
export const isWebKit = () => ua.getEngine().name === 'WebKit';
|
|
@ -1,5 +1,6 @@
|
|||
import { markRaw, ref } from 'vue';
|
||||
import { Storage } from './pizzax';
|
||||
import { isWebKit } from './scripts/useragent';
|
||||
|
||||
interface PostFormAction {
|
||||
title: string,
|
||||
|
@ -342,6 +343,10 @@ export const defaultStore = markRaw(new Storage('base', {
|
|||
where: 'device',
|
||||
default: {} as Record<string, Record<string, string[]>>,
|
||||
},
|
||||
timelineBackTopBehavior: {
|
||||
where: 'device',
|
||||
default: (isWebKit() ? 'newest' : 'next') as 'newest' | 'next',
|
||||
},
|
||||
}));
|
||||
|
||||
// TODO: 他のタブと永続化されたstateを同期
|
||||
|
|
Loading…
Reference in a new issue