diff --git a/locales/en-US.yml b/locales/en-US.yml index 133df1abb..22d30a871 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -1071,6 +1071,7 @@ thisPostIsMissingAltTextIgnore: "Post anyway" thisPostIsMissingAltText: "One of the files attached to this post is missing alt text. Please ensure all the attachments have alt text." collapseRenotes: "Collapse boosts you've already seen" collapseRenotesDescription: "Collapse boosts that you have boosted or reacted to" +collapseNotesRepliedTo: "Collapse notes replied to" collapseFiles: "Collapse files" autoloadConversation: "Load conversation on replies" internalServerError: "Internal Server Error" diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue index ba9705015..fe85307a5 100644 --- a/packages/frontend/src/components/MkNote.vue +++ b/packages/frontend/src/components/MkNote.vue @@ -12,7 +12,14 @@ SPDX-License-Identifier: AGPL-3.0-only :class="[$style.root, { [$style.showActionsOnlyHover]: defaultStore.state.showNoteActionsOnlyHover }]" :tabindex="!isDeleted ? '-1' : undefined" > - +
+ + + + : + +
+
{{ i18n.ts.pinnedNote }}
@@ -44,7 +51,7 @@ SPDX-License-Identifier: AGPL-3.0-only
- +
@@ -316,6 +323,7 @@ const renoteCollapsed = ref( (appearNote.value.myReaction != null) ), ); +const inReplyToCollapsed = ref(defaultStore.state.collapseNotesRepliedTo); const defaultLike = computed(() => defaultStore.state.like ? defaultStore.state.like : null); const animated = computed(() => parsed.value ? checkAnimationFromMfm(parsed.value) : null); const allowAnim = ref(defaultStore.state.advancedMfm && defaultStore.state.animatedMfm ? true : false); @@ -959,7 +967,7 @@ function emitUpdReaction(emoji: string, delta: number) { margin-right: 4px; } -.collapsedRenoteTarget { +.collapsedRenoteTarget, .collapsedInReplyTo { display: flex; align-items: center; line-height: 28px; @@ -967,7 +975,12 @@ function emitUpdReaction(emoji: string, delta: number) { padding: 0 32px 18px; } -.collapsedRenoteTargetAvatar { +.collapsedInReplyTo { + padding: 28px 32px 0; + opacity: 0.7; +} + +.collapsedRenoteTargetAvatar, .collapsedInReplyToAvatar { flex-shrink: 0; display: inline-block; width: 28px; @@ -976,12 +989,15 @@ function emitUpdReaction(emoji: string, delta: number) { } .collapsedRenoteTargetText { + opacity: 0.7; +} + +.collapsedRenoteTargetText, .collapsedInReplyToText { overflow: hidden; flex-shrink: 1; text-overflow: ellipsis; white-space: nowrap; font-size: 90%; - opacity: 0.7; cursor: pointer; &:hover { @@ -1194,6 +1210,10 @@ function emitUpdReaction(emoji: string, delta: number) { margin-top: 4px; } + .collapsedInReplyTo { + padding: 14px 16px 0; + } + .article { padding: 14px 16px; } diff --git a/packages/frontend/src/components/SkNote.vue b/packages/frontend/src/components/SkNote.vue index 7cfa3542c..a193df432 100644 --- a/packages/frontend/src/components/SkNote.vue +++ b/packages/frontend/src/components/SkNote.vue @@ -12,7 +12,15 @@ SPDX-License-Identifier: AGPL-3.0-only :class="[$style.root, { [$style.showActionsOnlyHover]: defaultStore.state.showNoteActionsOnlyHover }]" :tabindex="!isDeleted ? '-1' : undefined" > - + +
+
+ + + + : + +
{{ i18n.ts.pinnedNote }}
@@ -44,7 +52,7 @@ SPDX-License-Identifier: AGPL-3.0-only
- +
@@ -315,6 +323,7 @@ const renoteCollapsed = ref( (appearNote.value.myReaction != null) ) ); +const inReplyToCollapsed = ref(defaultStore.state.collapseNotesRepliedTo); const defaultLike = computed(() => defaultStore.state.like ? defaultStore.state.like : null); const animated = computed(() => parsed.value ? checkAnimationFromMfm(parsed.value) : null); const allowAnim = ref(defaultStore.state.advancedMfm && defaultStore.state.animatedMfm ? true : false); @@ -974,7 +983,7 @@ function emitUpdReaction(emoji: string, delta: number) { margin-right: 4px; } -.collapsedRenoteTarget { +.collapsedRenoteTarget, .collapsedInReplyTo { display: flex; align-items: center; line-height: 28px; @@ -982,7 +991,11 @@ function emitUpdReaction(emoji: string, delta: number) { padding: 8px 38px 24px; } -.collapsedRenoteTargetAvatar { +.collapsedInReplyTo { + padding: 28px 44px 0; +} + +.collapsedRenoteTargetAvatar, .collapsedInReplyToAvatar { flex-shrink: 0; display: inline-block; width: 28px; @@ -990,7 +1003,7 @@ function emitUpdReaction(emoji: string, delta: number) { margin: 0 8px 0 0; } -.collapsedRenoteTargetText { +.collapsedRenoteTargetText, .collapsedInReplyToText { overflow: hidden; flex-shrink: 1; text-overflow: ellipsis; @@ -1004,6 +1017,15 @@ function emitUpdReaction(emoji: string, delta: number) { } } +.collapsedInReplyToLine { + position: absolute; + left: calc(32px + .5 * var(--avatar)); + // using solid instead of dotted, stylelistic choice + border-left: var(--thread-width) solid var(--thread); + top: calc(28px + 28px); // 28px of .root padding, plus 28px of avatar height (see SkNote) + height: 28px; +} + .article { position: relative; padding: 28px 32px; @@ -1182,6 +1204,14 @@ function emitUpdReaction(emoji: string, delta: number) { padding: 8px 26px 24px; } + .collapsedInReplyTo { + padding: 28px 35px 0; + } + + .collapsedInReplyToLine { + left: calc(26px + .5 * var(--avatar)); + } + .article { padding: 24px 26px; } @@ -1199,6 +1229,10 @@ function emitUpdReaction(emoji: string, delta: number) { .footer { margin-bottom: -8px; } + + .collapsedInReplyToLine { + left: calc(25px + .5 * var(--avatar)); + } } @container (max-width: 500px) { @@ -1229,6 +1263,15 @@ function emitUpdReaction(emoji: string, delta: number) { margin-top: 4px; } + .collapsedInReplyTo { + padding: 22px 33px 0; + } + + .collapsedInReplyToLine { + left: calc(24px + .5 * var(--avatar)); + top: calc(22px + 28px); // 22px of .root padding, plus 28px of avatar height + } + .article { padding: 22px 24px; } diff --git a/packages/frontend/src/pages/settings/general.vue b/packages/frontend/src/pages/settings/general.vue index ab4f518d9..18ac6d1a5 100644 --- a/packages/frontend/src/pages/settings/general.vue +++ b/packages/frontend/src/pages/settings/general.vue @@ -50,10 +50,13 @@ SPDX-License-Identifier: AGPL-3.0-only
+ {{ i18n.ts.showNoteActionsOnlyHover }} + {{ i18n.ts.showClipButtonInNoteFooter }} + {{ i18n.ts.collapseNotesRepliedTo }} {{ i18n.ts.collapseFiles }} Uncollapse CWs on notes Always expand long notes @@ -351,6 +354,7 @@ const showClipButtonInNoteFooter = computed(defaultStore.makeGetterSetter('showC const reactionsDisplaySize = computed(defaultStore.makeGetterSetter('reactionsDisplaySize')); const limitWidthOfReaction = computed(defaultStore.makeGetterSetter('limitWidthOfReaction')); const collapseRenotes = computed(defaultStore.makeGetterSetter('collapseRenotes')); +const collapseNotesRepliedTo = computed(defaultStore.makeGetterSetter('collapseNotesRepliedTo')); const clickToOpen = computed(defaultStore.makeGetterSetter('clickToOpen')); // copied from src/pages/timeline.vue const showBots = computed({ diff --git a/packages/frontend/src/pages/settings/preferences-backups.vue b/packages/frontend/src/pages/settings/preferences-backups.vue index 5390f1223..b99e1e03e 100644 --- a/packages/frontend/src/pages/settings/preferences-backups.vue +++ b/packages/frontend/src/pages/settings/preferences-backups.vue @@ -56,6 +56,7 @@ const { t, ts } = i18n; const defaultStoreSaveKeys: (keyof typeof defaultStore['state'])[] = [ 'collapseRenotes', + 'collapseNotesRepliedTo', 'menu', 'visibility', 'localOnly', diff --git a/packages/frontend/src/store.ts b/packages/frontend/src/store.ts index e97543945..13f544e58 100644 --- a/packages/frontend/src/store.ts +++ b/packages/frontend/src/store.ts @@ -89,6 +89,10 @@ export const defaultStore = markRaw(new Storage('base', { where: 'account', default: false, }, + collapseNotesRepliedTo: { + where: 'account', + default: false, + }, collapseFiles: { where: 'account', default: false,