From e1a6ab91141b3b203545cde9fdd3986c57c7945a Mon Sep 17 00:00:00 2001 From: FineArchs Date: Sun, 9 Jun 2024 11:20:54 +0900 Subject: [PATCH] note collapsing methods --- locales/ja-JP.yml | 5 ++ packages/frontend/src/components/MkNote.vue | 89 +++++++++++-------- .../frontend/src/pages/settings/general.vue | 14 +++ .../pages/settings/preferences-backups.vue | 2 + packages/frontend/src/scripts/collapsed.ts | 10 ++- packages/frontend/src/store.ts | 8 ++ 6 files changed, 89 insertions(+), 39 deletions(-) diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 3ac1ce82a3..95730766f0 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -515,6 +515,11 @@ regenerate: "再生成" fontSize: "フォントサイズ" mediaListWithOneImageAppearance: "画像が1枚のみのメディアリストの高さ" limitTo: "{x}を上限に" +collapsingNoteSize: "ノートを畳む大きさ" +collapsingNoteCondition: "ノートを畳む条件" +detailedCalculation: "高精度の算出方法" +legacyCalculation: "旧式の算出方法" +seeRenderedSize: "実際の表示サイズに基づく" noFollowRequests: "フォロー申請はありません" openImageInNewTab: "画像を新しいタブで開く" dashboard: "ダッシュボード" diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue index f8764f3dea..e8bf5bf627 100644 --- a/packages/frontend/src/components/MkNote.vue +++ b/packages/frontend/src/components/MkNote.vue @@ -56,42 +56,44 @@ SPDX-License-Identifier: AGPL-3.0-only

-
-
- ({{ i18n.ts.private }}) - - -
- -
- {{ i18n.tsx.translatedFrom({ x: translation.sourceLang }) }}: - +
+
+
+ ({{ i18n.ts.private }}) + + +
+ +
+ {{ i18n.tsx.translatedFrom({ x: translation.sourceLang }) }}: + +
+
+ +
+ +
+ +
+
+ +
-
- -
- -
- -
-
- -
{{ appearNote.channel.name }}
@@ -196,7 +198,7 @@ import { getNoteSummary } from '@/scripts/get-note-summary.js'; import { MenuItem } from '@/types/menu.js'; import MkRippleEffect from '@/components/MkRippleEffect.vue'; import { showMovedDialog } from '@/scripts/show-moved-dialog.js'; -import { shouldCollapsed } from '@/scripts/collapsed.js'; +import { shouldCollapsedLegacy, shouldCollapsed } from '@/scripts/collapsed.js'; import { isEnabledUrlPreview } from '@/instance.js'; const props = withDefaults(defineProps<{ @@ -260,8 +262,22 @@ const isMyRenote = $i && ($i.id === note.value.userId); const showContent = ref(false); const parsed = computed(() => appearNote.value.text ? mfm.parse(appearNote.value.text) : null); const urls = computed(() => parsed.value ? extractUrlFromMfm(parsed.value).filter((url) => appearNote.value.renote?.url !== url && appearNote.value.renote?.uri !== url) : null); -const isLong = shouldCollapsed(appearNote.value, parsed.value, urls.value ?? []); -const collapsed = ref(appearNote.value.cw == null && isLong); +const collapsibleArea = ref(null); +const collapseSize = computed(() => ({ + small: 9, + medium: 13.5, + large: 18, +})[defaultStore.state.collapsingNoteSize]); +const isLong = computed(() => { + switch (defaultStore.state.collapsingNoteCondition) { + case 'detailedCalculation': return shouldCollapsed(appearNote.value, collapseSize.value, parsed.value, urls.value ?? []); + case 'seeRenderedSize': return collapsibleArea.value == null ? false : collapsibleInner.value.clientHeight > collapseSize.value * parseFloat(getComputedStyle(collapsibleInner.value).fontSize); + // fail safe + case 'legacyCalculation': + default: return shouldCollapsedLegacy(appearNote.value, urls.value ?? []); + } +}); +const collapsed = ref(appearNote.value.cw == null && isLong.value); const isDeleted = ref(false); const muted = ref(checkMute(appearNote.value, $i?.mutedWords)); const hardMuted = ref(props.withHardMute && checkMute(appearNote.value, $i?.hardMutedWords, true)); @@ -808,7 +824,6 @@ function emitUpdReaction(emoji: string, delta: number) { .contentCollapsed { position: relative; - max-height: 9em; overflow: clip; } diff --git a/packages/frontend/src/pages/settings/general.vue b/packages/frontend/src/pages/settings/general.vue index cfc63f2a08..69104165cc 100644 --- a/packages/frontend/src/pages/settings/general.vue +++ b/packages/frontend/src/pages/settings/general.vue @@ -92,6 +92,18 @@ SPDX-License-Identifier: AGPL-3.0-only + + + + + + + + + + + +
@@ -306,6 +318,8 @@ const useReactionPickerForContextMenu = computed(defaultStore.makeGetterSetter(' const squareAvatars = computed(defaultStore.makeGetterSetter('squareAvatars')); const showAvatarDecorations = computed(defaultStore.makeGetterSetter('showAvatarDecorations')); const mediaListWithOneImageAppearance = computed(defaultStore.makeGetterSetter('mediaListWithOneImageAppearance')); +const collapsingNoteSize = computed(defaultStore.makeGetterSetter('collapsingNoteSize')); +const collapsingNoteCondition = computed(defaultStore.makeGetterSetter('collapsingNoteCondition')); const notificationPosition = computed(defaultStore.makeGetterSetter('notificationPosition')); const notificationStackAxis = computed(defaultStore.makeGetterSetter('notificationStackAxis')); const keepScreenOn = computed(defaultStore.makeGetterSetter('keepScreenOn')); diff --git a/packages/frontend/src/pages/settings/preferences-backups.vue b/packages/frontend/src/pages/settings/preferences-backups.vue index b6f1043154..31e7c189e4 100644 --- a/packages/frontend/src/pages/settings/preferences-backups.vue +++ b/packages/frontend/src/pages/settings/preferences-backups.vue @@ -102,6 +102,8 @@ const defaultStoreSaveKeys: (keyof typeof defaultStore['state'])[] = [ 'aiChanMode', 'devMode', 'mediaListWithOneImageAppearance', + 'collapsingNoteSize', + 'collapsingNoteCondition', 'notificationPosition', 'notificationStackAxis', 'enableCondensedLineForAcct', diff --git a/packages/frontend/src/scripts/collapsed.ts b/packages/frontend/src/scripts/collapsed.ts index 4724bfee58..47d90465d4 100644 --- a/packages/frontend/src/scripts/collapsed.ts +++ b/packages/frontend/src/scripts/collapsed.ts @@ -23,7 +23,7 @@ export function shouldCollapsedLegacy(note: Misskey.entities.Note, urls: string[ return collapsed; } -export function shouldCollapsed(note: Misskey.entities.Note, ast?: mfm.MfmNode[] | null, urls?: string[]): boolean { +export function shouldCollapsed(note: Misskey.entities.Note, limitY: number, ast?: mfm.MfmNode[] | null, urls?: string[]): boolean { if (note.cw != null) return false; if (note.text == null) return false; if (note.files && note.files.length >= 5) return true; @@ -34,7 +34,7 @@ export function shouldCollapsed(note: Misskey.entities.Note, ast?: mfm.MfmNode[] // しきい値(X方向の文字数は半角換算) const limitX = 55; - const limitY = 13.5; + // const limitY = 13.5; let forceCollapsed = false; @@ -171,6 +171,12 @@ export function shouldCollapsed(note: Misskey.entities.Note, ast?: mfm.MfmNode[] break; } + case 'border': { + const width = safeParseFloat(node.props.args.width) ?? 1; + addHeightsInline(getHeightForEachLine(node.children, depth + 1).map(l => l + (width * 2))); + break; + } + default: { addHeightsInline(getHeightForEachLine(node.children, depth + 1)); break; diff --git a/packages/frontend/src/store.ts b/packages/frontend/src/store.ts index e8eb5a1ed7..15521c14c3 100644 --- a/packages/frontend/src/store.ts +++ b/packages/frontend/src/store.ts @@ -382,6 +382,14 @@ export const defaultStore = markRaw(new Storage('base', { where: 'device', default: 'expand' as 'expand' | '16_9' | '1_1' | '2_3', }, + collapsingNoteSize: { + where: 'device', + default: 'medium' as 'small' | 'medium' | 'large', + }, + collapsingNoteCondition: { + where: 'device', + default: 'detailedCalculation' as 'detailedCalculation' | 'legacyCalculation' | 'seeRenderedSize', + }, notificationPosition: { where: 'device', default: 'rightBottom' as 'leftTop' | 'leftBottom' | 'rightTop' | 'rightBottom',