mirror of
https://github.com/paricafe/misskey.git
synced 2025-02-17 12:27:29 -06:00
insertNewNotes
This commit is contained in:
parent
5813b499b4
commit
76a69d3a6b
7 changed files with 83 additions and 15 deletions
|
@ -63,7 +63,7 @@ copyFileId: "Copy file ID"
|
|||
copyFolderId: "Copy folder ID"
|
||||
copyProfileUrl: "Copy profile URL"
|
||||
searchUser: "Search for a user"
|
||||
searchThisUsersNotes: "Search this user’s notes"
|
||||
searchThisUsersNotes: "Search this user's notes"
|
||||
reply: "Reply"
|
||||
loadMore: "Load more"
|
||||
showMore: "Show more"
|
||||
|
@ -856,7 +856,7 @@ administration: "Management"
|
|||
accounts: "Accounts"
|
||||
switch: "Switch"
|
||||
noMaintainerInformationWarning: "Maintainer information is not configured."
|
||||
noInquiryUrlWarning: "Inquiry URL isn’t set"
|
||||
noInquiryUrlWarning: "Inquiry URL isn't set"
|
||||
noBotProtectionWarning: "Bot protection is not configured."
|
||||
configure: "Configure"
|
||||
postToGallery: "Create new gallery post"
|
||||
|
@ -2796,7 +2796,7 @@ _urlPreviewSetting:
|
|||
title: "URL preview settings"
|
||||
enable: "Enable URL preview"
|
||||
timeout: "Time out when getting preview (ms)"
|
||||
timeoutDescription: "If it takes longer than this value to get the preview, the preview won’t be generated."
|
||||
timeoutDescription: "If it takes longer than this value to get the preview, the preview won't be generated."
|
||||
maximumContentLength: "Maximum Content-Length (bytes)"
|
||||
maximumContentLengthDescription: "If Content-Length is higher than this value, the preview won't be generated."
|
||||
requireContentLength: "Generate the preview only if you could get Content-Length"
|
||||
|
@ -2829,9 +2829,11 @@ _embedCodeGen:
|
|||
generateCode: "Generate embed code"
|
||||
codeGenerated: "The code has been generated"
|
||||
codeGeneratedDescription: "Paste the generated code into your website to embed the content."
|
||||
_selfXssPrevention:
|
||||
_selfXssPrevention:
|
||||
warning: "WARNING"
|
||||
title: "Any request to 'paste something into this screen' is a scam."
|
||||
description1: "Pasting content here could allow malicious users to hijack your account or steal your personal information."
|
||||
description2: "If you don't fully understand what you're about to paste, %cplease stop immediately and close this window."
|
||||
description3: "For more information, please check here: {link}"
|
||||
insertNewNotes: "Insert new notes at current position"
|
||||
insertNewNotesDescription: "When receiving new notes while scrolling timeline, insert them at current viewing position. If disabled, show notification as usual."
|
||||
|
|
|
@ -147,7 +147,7 @@ renoteMute: "リノートをミュート"
|
|||
renoteUnmute: "リノートのミュートを解除"
|
||||
block: "ブロック"
|
||||
unblock: "ブロック解除"
|
||||
suspend: "凍結"
|
||||
suspend: "凍<EFBFBD><EFBFBD>"
|
||||
unsuspend: "解凍"
|
||||
blockConfirm: "ブロックしますか?"
|
||||
unblockConfirm: "ブロック解除しますか?"
|
||||
|
@ -454,7 +454,7 @@ totpDescription: "認証アプリを使ってワンタイムパスワードを
|
|||
moderator: "モデレーター"
|
||||
moderation: "モデレーション"
|
||||
moderationNote: "モデレーションノート"
|
||||
moderationNoteDescription: "モデレーター間でだけ共有されるメモを記入することができます。"
|
||||
moderationNoteDescription: "モ<EFBFBD><EFBFBD>レーター間でだけ共有されるメモを記入することができます。"
|
||||
addModerationNote: "モデレーションノートを追加する"
|
||||
moderationLogs: "モデログ"
|
||||
nUsersMentioned: "{n}人が投稿"
|
||||
|
@ -537,7 +537,7 @@ fontSize: "フォントサイズ"
|
|||
mediaListWithOneImageAppearance: "画像が1枚のみのメディアリストの高さ"
|
||||
limitTo: "{x}を上限に"
|
||||
noFollowRequests: "フォロー申請はありません"
|
||||
openImageInNewTab: "画像を新しいタブで開く"
|
||||
openImageInNewTab: "画像<EFBFBD><EFBFBD>新しいタブで開く"
|
||||
dashboard: "ダッシュボード"
|
||||
local: "ローカル"
|
||||
remote: "リモート"
|
||||
|
@ -681,7 +681,7 @@ smtpUser: "ユーザー名"
|
|||
smtpPass: "パスワード"
|
||||
emptyToDisableSmtpAuth: "ユーザー名とパスワードを空欄にすることで、SMTP認証を無効化出来ます"
|
||||
smtpSecure: "SMTP 接続に暗黙的なSSL/TLSを使用する"
|
||||
smtpSecureInfo: "STARTTLS使用時はオフにします。"
|
||||
smtpSecureInfo: "STARTTLS使用時はオフに<EFBFBD><EFBFBD><EFBFBD>ます。"
|
||||
testEmail: "配信テスト"
|
||||
wordMute: "ワードミュート"
|
||||
hardWordMute: "ハードワードミュート"
|
||||
|
@ -1052,7 +1052,7 @@ thisPostMayBeAnnoyingCancel: "やめる"
|
|||
thisPostMayBeAnnoyingIgnore: "このまま投稿"
|
||||
collapseRenotes: "リノートのスマート省略"
|
||||
collapseRenotesDescription: "リアクションやリノートをしたことがあるノートをたたんで表示します。"
|
||||
internalServerError: "サーバー内部エラー"
|
||||
internalServerError: "サーバー<EFBFBD><EFBFBD><EFBFBD>部エラー"
|
||||
internalServerErrorDescription: "サーバー内部で予期しないエラーが発生しました。"
|
||||
copyErrorInfo: "エラー情報をコピー"
|
||||
joinThisServer: "このサーバーに登録する"
|
||||
|
@ -1228,7 +1228,7 @@ detachAll: "全て外す"
|
|||
angle: "角度"
|
||||
flip: "反転"
|
||||
showAvatarDecorations: "アイコンのデコレーションを表示"
|
||||
releaseToRefresh: "離してリロード"
|
||||
releaseToRefresh: "離して<EFBFBD><EFBFBD>ロード"
|
||||
refreshing: "リロード中"
|
||||
pullDownToRefresh: "引っ張ってリロード"
|
||||
disableStreamingTimeline: "タイムラインのリアルタイム更新を無効にする"
|
||||
|
@ -1366,7 +1366,7 @@ _announcement:
|
|||
_initialAccountSetting:
|
||||
accountCreated: "アカウントの作成が完了しました!"
|
||||
letsStartAccountSetup: "さっそくアカウントの初期設定を行いましょう。"
|
||||
letsFillYourProfile: "まずはあなたのプロフィールを設定しましょう。"
|
||||
letsFillYourProfile: "まずはあなたのプロフィールを設定しまし<EFBFBD><EFBFBD><EFBFBD>う。"
|
||||
profileSetting: "プロフィール設定"
|
||||
privacySetting: "プライバシー設定"
|
||||
theseSettingsCanEditLater: "これらの設定は後から変更できます。"
|
||||
|
@ -1517,7 +1517,7 @@ _achievements:
|
|||
title: "ノートノートノート"
|
||||
description: "ノートを30,000回投稿した"
|
||||
_notes40000:
|
||||
title: "ノート工場"
|
||||
title: "ノート工<EFBFBD><EFBFBD><EFBFBD>"
|
||||
description: "ノートを40,000回投稿した"
|
||||
_notes50000:
|
||||
title: "ノートの惑星"
|
||||
|
@ -2011,7 +2011,7 @@ _theme:
|
|||
darken: "暗さ"
|
||||
lighten: "明るさ"
|
||||
inputConstantName: "定数名を入力してください"
|
||||
importInfo: "ここにテーマコードを貼り付けて、エディターにインポートできます"
|
||||
importInfo: "ここにテーマ<EFBFBD><EFBFBD>ードを貼り付けて、エディターにインポートできます"
|
||||
deleteConstantConfirm: "定数 {const} を削除しても良いですか?"
|
||||
|
||||
keys:
|
||||
|
@ -2221,7 +2221,7 @@ _auth:
|
|||
permissionAsk: "このアプリは次の権限を要求しています"
|
||||
pleaseGoBack: "アプリケーションに戻ってやっていってください"
|
||||
callback: "アプリケーションに戻っています"
|
||||
accepted: "アクセスを許可しました"
|
||||
accepted: "アク<EFBFBD><EFBFBD>スを許可しました"
|
||||
denied: "アクセスを拒否しました"
|
||||
scopeUser: "以下のユーザーとして操作しています"
|
||||
pleaseLogin: "アプリケーションにアクセス許可を与えるには、ログインが必要です。"
|
||||
|
@ -2821,3 +2821,6 @@ _selfXssPrevention:
|
|||
description1: "ここに何かを貼り付けると、悪意のあるユーザーにアカウントを乗っ取られたり、個人情報を盗まれたりする可能性があります。"
|
||||
description2: "貼り付けようとしているものが何なのかを正確に理解していない場合は、%c今すぐ作業を中止してこのウィンドウを閉じてください。"
|
||||
description3: "詳しくはこちらをご確認ください。 {link}"
|
||||
|
||||
insertNewNotes: "新着ノートを表示位置に挿入"
|
||||
insertNewNotesDescription: "タイムラインをスクロール中に新着ノートを受信した場合、現在の表示位置に挿入します。オフの場合は従来通り通知を表示します。"
|
||||
|
|
|
@ -9,6 +9,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
v-show="!isDeleted"
|
||||
ref="rootEl"
|
||||
v-hotkey="keymap"
|
||||
:data-note-id="note.id"
|
||||
:class="[$style.root, { [$style.showActionsOnlyHover]: defaultStore.state.showNoteActionsOnlyHover, [$style.skipRender]: defaultStore.state.skipNoteRender || defaultStore.state.enableRenderingOptimization }]"
|
||||
:tabindex="isDeleted ? '-1' : '0'"
|
||||
>
|
||||
|
|
|
@ -478,6 +478,54 @@ onBeforeUnmount(() => {
|
|||
scrollObserver.value?.disconnect();
|
||||
});
|
||||
|
||||
// 添加新的方法
|
||||
const insertNote = (item: MisskeyEntity): void => {
|
||||
if (items.value.size === 0) {
|
||||
items.value.set(item.id, item);
|
||||
fetching.value = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果在顶部,直接添加到顶部
|
||||
if (isTop() && !isPausingUpdate) {
|
||||
unshiftItems([item]);
|
||||
} else {
|
||||
// 不在顶部时,根据设置决定行为
|
||||
if (defaultStore.state.insertNewNotes) {
|
||||
// 插入到当前可见位置
|
||||
const entries = Array.from(items.value.entries());
|
||||
const visibleIndex = findFirstVisibleNoteIndex(entries);
|
||||
if (visibleIndex !== -1) {
|
||||
entries.splice(visibleIndex, 0, [item.id, item]);
|
||||
items.value = new Map(entries);
|
||||
} else {
|
||||
// 如果找不到可见的帖文,添加到队列
|
||||
prependQueue(item);
|
||||
}
|
||||
} else {
|
||||
// 保持原有行为
|
||||
prependQueue(item);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 添加辅助方法来找到第一个可见的帖文
|
||||
function findFirstVisibleNoteIndex(entries: [string, MisskeyEntity][]): number {
|
||||
if (!rootEl.value) return -1;
|
||||
|
||||
const notes = rootEl.value.querySelectorAll('[data-note-id]');
|
||||
for (let i = 0; i < notes.length; i++) {
|
||||
const note = notes[i];
|
||||
const rect = note.getBoundingClientRect();
|
||||
if (rect.top >= 0 && rect.bottom <= window.innerHeight) {
|
||||
// 找到对应的 entry index
|
||||
const noteId = note.getAttribute('data-note-id');
|
||||
return entries.findIndex(([id]) => id === noteId);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
items,
|
||||
queue,
|
||||
|
@ -488,6 +536,7 @@ defineExpose({
|
|||
append: appendItem,
|
||||
removeItem,
|
||||
updateItem,
|
||||
insertNote,
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
|
@ -82,7 +82,11 @@ function prepend(note) {
|
|||
note._shouldInsertAd_ = true;
|
||||
}
|
||||
|
||||
tlComponent.value.pagingComponent?.prepend(note);
|
||||
if (defaultStore.state.insertNewNotes) {
|
||||
tlComponent.value.pagingComponent?.insertNote(note);
|
||||
} else {
|
||||
tlComponent.value.pagingComponent?.prepend(note);
|
||||
}
|
||||
|
||||
emit('note');
|
||||
|
||||
|
|
|
@ -75,6 +75,10 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<MkSwitch v-model="disableReactionsViewer">{{ i18n.ts.disableReactionsViewer }}</MkSwitch>
|
||||
<MkSwitch v-model="collapsedUnexpectedLangs">{{ i18n.ts.collapsedUnexpectedLangs }}</MkSwitch>
|
||||
<MkSwitch v-model="emojiAutoSpacing">{{ i18n.ts.emojiAutoSpacing }}</MkSwitch>
|
||||
<MkSwitch v-model="insertNewNotes">
|
||||
<template #label>{{ i18n.ts.insertNewNotes }}</template>
|
||||
<template #caption>{{ i18n.ts.insertNewNotesDescription }}</template>
|
||||
</MkSwitch>
|
||||
<MkSelect v-model="autoSpacingBehaviour">
|
||||
<template #label>{{ i18n.ts.autoSpacing }}</template>
|
||||
<option :value="null">{{ i18n.ts.disabled }}</option>
|
||||
|
@ -132,6 +136,7 @@ const collapseNotesRepliedTo = computed(defaultStore.makeGetterSetter('collapseN
|
|||
const disableReactionsViewer = computed(defaultStore.makeGetterSetter('disableReactionsViewer'));
|
||||
const collapsedUnexpectedLangs = computed(defaultStore.makeGetterSetter('collapsedUnexpectedLangs'));
|
||||
const emojiAutoSpacing = computed(defaultStore.makeGetterSetter('emojiAutoSpacing'));
|
||||
const insertNewNotes = computed(defaultStore.makeGetterSetter('insertNewNotes'));
|
||||
|
||||
definePageMetadata(() => ({
|
||||
title: 'Pari Plus!',
|
||||
|
|
|
@ -559,6 +559,10 @@ export const defaultStore = markRaw(new Storage('base', {
|
|||
where: 'device',
|
||||
default: true,
|
||||
},
|
||||
insertNewNotes: {
|
||||
where: 'device',
|
||||
default: false,
|
||||
},
|
||||
}));
|
||||
|
||||
// TODO: 他のタブと永続化されたstateを同期
|
||||
|
|
Loading…
Add table
Reference in a new issue