timelineBackTopBehavior

This commit is contained in:
tamaina 2023-07-26 12:22:26 +00:00
parent 9f79e494f5
commit 4785b9bfdd
7 changed files with 38 additions and 10 deletions

5
locales/index.d.ts vendored
View file

@ -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;

View file

@ -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: "チャンネルを編集"

View file

@ -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がtruefalseになったら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);

View file

@ -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);

View file

@ -87,6 +87,7 @@ const defaultStoreSaveKeys: (keyof typeof defaultStore['state'])[] = [
'numberOfPageCache',
'aiChanMode',
'mediaListWithOneImageAppearance',
'timelineBackTopBehavior',
];
const coldDeviceStorageSaveKeys: (keyof typeof ColdDeviceStorage.default)[] = [
'lightTheme',

View file

@ -0,0 +1,3 @@
import { UAParser } from 'ua-parser-js';
const ua = new UAParser(navigator.userAgent);
export const isWebKit = () => ua.getEngine().name === 'WebKit';

View file

@ -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を同期