feat: 노트를 클릭하여 자세히 볼 수 있음

This commit is contained in:
NoriDev 2023-11-30 16:46:06 +09:00
parent 123b7a6668
commit d6fa889c93
13 changed files with 51 additions and 16 deletions

View file

@ -40,6 +40,7 @@ Misskey의 전체 변경 사항을 확인하려면, [CHANGELOG.md#2023xx](CHANGE
- 위치 조정 - 위치 조정
- 크기 조정 - 크기 조정
- 불투명도 조정 - 불투명도 조정
- Feat: 노트를 클릭하여 자세히 볼 수 있음
- Revert: 사용자 통계 표시 기능 제거 ([MisskeyIO/misskey@114c7fe6](https://github.com/MisskeyIO/misskey/commit/114c7fe6b37dd6bddbcd9d92406f8b13bf688e8b)) - Revert: 사용자 통계 표시 기능 제거 ([MisskeyIO/misskey@114c7fe6](https://github.com/MisskeyIO/misskey/commit/114c7fe6b37dd6bddbcd9d92406f8b13bf688e8b))
### Client ### Client

View file

@ -1317,6 +1317,8 @@ _cherrypick:
postFormVisibilityHotkeyDescription: "When writing a note, press Ctrl(control) + Shift to switch the visibility range. The hotkey to make it Local only is Ctrl(command or control) + Alt(option)." postFormVisibilityHotkeyDescription: "When writing a note, press Ctrl(control) + Shift to switch the visibility range. The hotkey to make it Local only is Ctrl(command or control) + Alt(option)."
showRenoteConfirmPopup: "Show confirmation popup when renote" showRenoteConfirmPopup: "Show confirmation popup when renote"
showRenoteConfirmPopupDescription: "This setting must have the \"General - Show renote and quote buttons separately\" setting turned on." showRenoteConfirmPopupDescription: "This setting must have the \"General - Show renote and quote buttons separately\" setting turned on."
expandOnNoteClick: "Open note on click"
expandOnNoteClickDescription: "If disabled, you can still open 'Details' in the notes menu or by clicking the timestamp."
displayHeaderNavBarWhenScroll: "Show elements when scrolling (header, floating buttons, navigation bar)" displayHeaderNavBarWhenScroll: "Show elements when scrolling (header, floating buttons, navigation bar)"
_displayHeaderNavBarWhenScroll: _displayHeaderNavBarWhenScroll:
all: "Display all" all: "Display all"

2
locales/index.d.ts vendored
View file

@ -1330,6 +1330,8 @@ export interface Locale {
"postFormVisibilityHotkeyDescription": string; "postFormVisibilityHotkeyDescription": string;
"showRenoteConfirmPopup": string; "showRenoteConfirmPopup": string;
"showRenoteConfirmPopupDescription": string; "showRenoteConfirmPopupDescription": string;
"expandOnNoteClick": string;
"expandOnNoteClickDescription": string;
"displayHeaderNavBarWhenScroll": string; "displayHeaderNavBarWhenScroll": string;
"_displayHeaderNavBarWhenScroll": { "_displayHeaderNavBarWhenScroll": {
"all": string; "all": string;

View file

@ -1328,6 +1328,8 @@ _cherrypick:
postFormVisibilityHotkeyDescription: "ートを作成する際、Ctrl(control) + Shiftキーを押すと公開範囲を切り替えることができます。ローカルのみショートカットキーは、Ctrl(commandまたはcontrol) + Alt(option)キーです。" postFormVisibilityHotkeyDescription: "ートを作成する際、Ctrl(control) + Shiftキーを押すと公開範囲を切り替えることができます。ローカルのみショートカットキーは、Ctrl(commandまたはcontrol) + Alt(option)キーです。"
showRenoteConfirmPopup: "Renoteするときに確認ポップアップを表示" showRenoteConfirmPopup: "Renoteするときに確認ポップアップを表示"
showRenoteConfirmPopupDescription: "この設定は「全般 - リノートと引用ボタンを分けて表示する」設定がオンになっている必要があります。" showRenoteConfirmPopupDescription: "この設定は「全般 - リノートと引用ボタンを分けて表示する」設定がオンになっている必要があります。"
expandOnNoteClick: "クリックでノートの詳細を開く"
expandOnNoteClickDescription: "オフの場合、ノートメニューの[詳細]をクリックするか、日付をクリックして開けます。"
displayHeaderNavBarWhenScroll: "スクロール時の要素表示(ヘッダー、フローティングボタン、ナビゲーションバー)" displayHeaderNavBarWhenScroll: "スクロール時の要素表示(ヘッダー、フローティングボタン、ナビゲーションバー)"
_displayHeaderNavBarWhenScroll: _displayHeaderNavBarWhenScroll:
all: "全て表示" all: "全て表示"

View file

@ -1313,6 +1313,8 @@ _cherrypick:
postFormVisibilityHotkeyDescription: "노트를 작성할 때, Ctrl(control) + Shift 키를 누르면 공개 범위를 전환할 수 있어요. 로컬에만 보이게 하는 단축키는 Ctrl(command 또는 control) + Alt(option) 키에요." postFormVisibilityHotkeyDescription: "노트를 작성할 때, Ctrl(control) + Shift 키를 누르면 공개 범위를 전환할 수 있어요. 로컬에만 보이게 하는 단축키는 Ctrl(command 또는 control) + Alt(option) 키에요."
showRenoteConfirmPopup: "리노트할 때 확인 팝업 표시" showRenoteConfirmPopup: "리노트할 때 확인 팝업 표시"
showRenoteConfirmPopupDescription: "이 설정은 '일반 - 리노트와 인용 버튼을 분리해서 표시하기' 설정이 켜져 있어야 해요." showRenoteConfirmPopupDescription: "이 설정은 '일반 - 리노트와 인용 버튼을 분리해서 표시하기' 설정이 켜져 있어야 해요."
expandOnNoteClick: "노트를 클릭하여 자세히 표시"
expandOnNoteClickDescription: "비활성화한 경우에도 노트 메뉴에서 '자세히'를 클릭하거나 타임스탬프를 클릭하여 열 수 있어요."
displayHeaderNavBarWhenScroll: "스크롤 시 요소 표시 (헤더, 플로팅 버튼, 탐색 모음)" displayHeaderNavBarWhenScroll: "스크롤 시 요소 표시 (헤더, 플로팅 버튼, 탐색 모음)"
_displayHeaderNavBarWhenScroll: _displayHeaderNavBarWhenScroll:
all: "모두 표시" all: "모두 표시"

View file

@ -57,7 +57,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkAvatar v-if="!defaultStore.state.hideAvatarsInNote" :class="$style.collapsedRenoteTargetAvatar" :user="appearNote.user" link preview/> <MkAvatar v-if="!defaultStore.state.hideAvatarsInNote" :class="$style.collapsedRenoteTargetAvatar" :user="appearNote.user" link preview/>
<Mfm :text="getNoteSummary(appearNote)" :plain="true" :nowrap="true" :author="appearNote.user" :nyaize="'respect'" :class="$style.collapsedRenoteTargetText" @click="renoteCollapsed = false"/> <Mfm :text="getNoteSummary(appearNote)" :plain="true" :nowrap="true" :author="appearNote.user" :nyaize="'respect'" :class="$style.collapsedRenoteTargetText" @click="renoteCollapsed = false"/>
</div> </div>
<article v-else :class="$style.article" @contextmenu.stop="onContextmenu"> <article v-else :class="$style.article" :style="{ cursor: expandOnNoteClick ? 'pointer' : '' }" @click="noteClick" @contextmenu.stop="onContextmenu">
<div style="display: flex; padding-bottom: 10px;"> <div style="display: flex; padding-bottom: 10px;">
<div v-if="appearNote.channel" :class="$style.colorBar" :style="{ background: appearNote.channel.color }"></div> <div v-if="appearNote.channel" :class="$style.colorBar" :style="{ background: appearNote.channel.color }"></div>
<MkAvatar v-if="!defaultStore.state.hideAvatarsInNote" :class="[$style.avatar, { [$style.avatarReplyTo]: appearNote.reply, [$style.showEl]: !appearNote.reply && (showEl && ['hideHeaderOnly', 'hideHeaderFloatBtn', 'hide'].includes(<string>defaultStore.state.displayHeaderNavBarWhenScroll)) && mainRouter.currentRoute.value.name === 'index', [$style.showElTab]: !appearNote.reply && (showEl && ['hideHeaderOnly', 'hideHeaderFloatBtn', 'hide'].includes(<string>defaultStore.state.displayHeaderNavBarWhenScroll)) && mainRouter.currentRoute.value.name !== 'index' }]" :user="appearNote.user" :link="!mock" :preview="!mock"/> <MkAvatar v-if="!defaultStore.state.hideAvatarsInNote" :class="[$style.avatar, { [$style.avatarReplyTo]: appearNote.reply, [$style.showEl]: !appearNote.reply && (showEl && ['hideHeaderOnly', 'hideHeaderFloatBtn', 'hide'].includes(<string>defaultStore.state.displayHeaderNavBarWhenScroll)) && mainRouter.currentRoute.value.name === 'index', [$style.showElTab]: !appearNote.reply && (showEl && ['hideHeaderOnly', 'hideHeaderFloatBtn', 'hide'].includes(<string>defaultStore.state.displayHeaderNavBarWhenScroll)) && mainRouter.currentRoute.value.name !== 'index' }]" :user="appearNote.user" :link="!mock" :preview="!mock"/>
@ -112,13 +112,13 @@ SPDX-License-Identifier: AGPL-3.0-only
</div> </div>
<MkPoll v-if="appearNote.poll" :note="appearNote" :class="$style.poll"/> <MkPoll v-if="appearNote.poll" :note="appearNote" :class="$style.poll"/>
<MkUrlPreview v-for="url in urls" :key="url" :url="url" :compact="true" :detail="false" :class="$style.urlPreview"/> <MkUrlPreview v-for="url in urls" :key="url" :url="url" :compact="true" :detail="false" :class="$style.urlPreview"/>
<button v-if="(isLong || (isMFM && defaultStore.state.collapseDefault) || (appearNote.files.length > 0 && defaultStore.state.allMediaNoteCollapse)) && collapsed" v-vibrate="defaultStore.state.vibrateSystem ? 5 : []" :class="$style.collapsed" class="_button" @click="collapsed = false"> <button v-if="(isLong || (isMFM && defaultStore.state.collapseDefault) || (appearNote.files.length > 0 && defaultStore.state.allMediaNoteCollapse)) && collapsed" v-vibrate="defaultStore.state.vibrateSystem ? 5 : []" :class="$style.collapsed" class="_button" @click.stop="collapsed = false">
<span :class="$style.collapsedLabel"> <span :class="$style.collapsedLabel">
{{ i18n.ts.showMore }} {{ i18n.ts.showMore }}
<span v-if="appearNote.files.length > 0" :class="$style.label">({{ collapseLabel }})</span> <span v-if="appearNote.files.length > 0" :class="$style.label">({{ collapseLabel }})</span>
</span> </span>
</button> </button>
<button v-else-if="(isLong || (isMFM && defaultStore.state.collapseDefault) || (appearNote.files.length > 0 && defaultStore.state.allMediaNoteCollapse)) && !collapsed" v-vibrate="defaultStore.state.vibrateSystem ? 5 : []" :class="$style.showLess" class="_button" @click="collapsed = true"> <button v-else-if="(isLong || (isMFM && defaultStore.state.collapseDefault) || (appearNote.files.length > 0 && defaultStore.state.allMediaNoteCollapse)) && !collapsed" v-vibrate="defaultStore.state.vibrateSystem ? 5 : []" :class="$style.showLess" class="_button" @click.stop="collapsed = true">
<span :class="$style.showLessLabel">{{ i18n.ts.showLess }}</span> <span :class="$style.showLessLabel">{{ i18n.ts.showLess }}</span>
</button> </button>
</div> </div>
@ -132,7 +132,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</template> </template>
</MkReactionsViewer> </MkReactionsViewer>
<footer :class="$style.footer"> <footer :class="$style.footer">
<button v-if="!note.isHidden" v-vibrate="defaultStore.state.vibrateSystem ? 5 : []" v-tooltip="i18n.ts.reply" :class="$style.footerButton" class="_button" @click="reply()"> <button v-if="!note.isHidden" v-vibrate="defaultStore.state.vibrateSystem ? 5 : []" v-tooltip="i18n.ts.reply" :class="$style.footerButton" class="_button" @click.stop="reply()">
<i class="ti ti-arrow-back-up"></i> <i class="ti ti-arrow-back-up"></i>
<p v-if="appearNote.repliesCount > 0" :class="$style.footerButtonCount">{{ appearNote.repliesCount }}</p> <p v-if="appearNote.repliesCount > 0" :class="$style.footerButtonCount">{{ appearNote.repliesCount }}</p>
</button> </button>
@ -161,10 +161,10 @@ SPDX-License-Identifier: AGPL-3.0-only
<i v-if="appearNote.myReaction == null" v-tooltip="i18n.ts.reaction" class="ti ti-mood-plus"></i> <i v-if="appearNote.myReaction == null" v-tooltip="i18n.ts.reaction" class="ti ti-mood-plus"></i>
<i v-else v-tooltip="i18n.ts.editReaction" class="ti ti-mood-edit"></i> <i v-else v-tooltip="i18n.ts.editReaction" class="ti ti-mood-edit"></i>
</button> </button>
<button v-if="appearNote.myReaction != null && appearNote.reactionAcceptance == 'likeOnly'" ref="reactButton" v-vibrate="defaultStore.state.vibrateSystem ? [30, 50, 50] : []" v-tooltip="i18n.ts.removeReaction" :class="$style.footerButton" class="_button" @click="undoReact(appearNote)"> <button v-if="appearNote.myReaction != null && appearNote.reactionAcceptance == 'likeOnly'" ref="reactButton" v-vibrate="defaultStore.state.vibrateSystem ? [30, 50, 50] : []" v-tooltip="i18n.ts.removeReaction" :class="$style.footerButton" class="_button" @click.stop="undoReact(appearNote)">
<i class="ti ti-heart-minus"></i> <i class="ti ti-heart-minus"></i>
</button> </button>
<button v-if="canRenote && defaultStore.state.renoteQuoteButtonSeparation" v-vibrate="defaultStore.state.vibrateSystem ? 5 : []" v-tooltip="i18n.ts.quote" class="_button" :class="$style.footerButton" @click="quote()"> <button v-if="canRenote && defaultStore.state.renoteQuoteButtonSeparation" v-vibrate="defaultStore.state.vibrateSystem ? 5 : []" v-tooltip="i18n.ts.quote" class="_button" :class="$style.footerButton" @click.stop="quote()">
<i class="ti ti-quote"></i> <i class="ti ti-quote"></i>
</button> </button>
<button v-if="defaultStore.state.showClipButtonInNoteFooter" ref="clipButton" v-vibrate="defaultStore.state.vibrateSystem ? 5 : []" v-tooltip="i18n.ts.clip" :class="$style.footerButton" class="_button" @mousedown="clip()"> <button v-if="defaultStore.state.showClipButtonInNoteFooter" ref="clipButton" v-vibrate="defaultStore.state.vibrateSystem ? 5 : []" v-tooltip="i18n.ts.clip" :class="$style.footerButton" class="_button" @mousedown="clip()">
@ -233,7 +233,7 @@ import MkRippleEffect from '@/components/MkRippleEffect.vue';
import { showMovedDialog } from '@/scripts/show-moved-dialog.js'; import { showMovedDialog } from '@/scripts/show-moved-dialog.js';
import { shouldCollapsed, shouldMfmCollapsed } from '@/scripts/collapsed.js'; import { shouldCollapsed, shouldMfmCollapsed } from '@/scripts/collapsed.js';
import { globalEvents } from '@/events.js'; import { globalEvents } from '@/events.js';
import { mainRouter } from '@/router.js'; import { mainRouter, useRouter } from '@/router.js';
import { notePage } from '@/filters/note.js'; import { notePage } from '@/filters/note.js';
import { miLocalStorage } from '@/local-storage.js'; import { miLocalStorage } from '@/local-storage.js';
import { instance } from '@/instance.js'; import { instance } from '@/instance.js';
@ -315,6 +315,8 @@ const translating = ref(false);
const viewTextSource = ref(false); const viewTextSource = ref(false);
const noNyaize = ref(false); const noNyaize = ref(false);
const canRenote = computed(() => ['public', 'home'].includes(appearNote.visibility) || (appearNote.visibility === 'followers' && appearNote.userId === $i.id)); const canRenote = computed(() => ['public', 'home'].includes(appearNote.visibility) || (appearNote.visibility === 'followers' && appearNote.userId === $i.id));
const expandOnNoteClick = defaultStore.state.expandOnNoteClick;
const router = useRouter();
let renoteCollapsed = $ref(defaultStore.state.collapseRenotes && isRenote && (($i && ($i.id === note.userId || $i.id === appearNote.userId)) || (appearNote.myReaction != null))); let renoteCollapsed = $ref(defaultStore.state.collapseRenotes && isRenote && (($i && ($i.id === note.userId || $i.id === appearNote.userId)) || (appearNote.myReaction != null)));
const collapseLabel = computed(() => { const collapseLabel = computed(() => {
@ -389,6 +391,11 @@ if (!props.mock) {
}); });
} }
function noteClick(ev: MouseEvent) {
if (document.getSelection().type === 'Range' || !expandOnNoteClick) ev.stopPropagation();
else router.push(notePage(appearNote));
}
function renote(viaKeyboard = false) { function renote(viaKeyboard = false) {
pleaseLogin(); pleaseLogin();
showMovedDialog(); showMovedDialog();

View file

@ -9,7 +9,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<div :class="$style.main"> <div :class="$style.main">
<div v-if="note.channel" :class="$style.colorBar" :style="{ background: note.channel.color }"></div> <div v-if="note.channel" :class="$style.colorBar" :style="{ background: note.channel.color }"></div>
<MkAvatar v-if="!defaultStore.state.hideAvatarsInNote" :class="$style.avatar" :user="note.user" link preview/> <MkAvatar v-if="!defaultStore.state.hideAvatarsInNote" :class="$style.avatar" :user="note.user" link preview/>
<div :class="$style.body"> <div :class="$style.body" :style="{ cursor: expandOnNoteClick ? 'pointer' : '' }" @click="noteClick">
<MkNoteHeader :class="$style.header" :note="note" :mini="true"/> <MkNoteHeader :class="$style.header" :note="note" :mini="true"/>
<div> <div>
<MkEvent v-if="note.event" :note="note"/> <MkEvent v-if="note.event" :note="note"/>
@ -55,6 +55,7 @@ import { $i } from '@/account.js';
import { userPage } from '@/filters/user.js'; import { userPage } from '@/filters/user.js';
import { checkWordMute } from '@/scripts/check-word-mute.js'; import { checkWordMute } from '@/scripts/check-word-mute.js';
import { defaultStore } from '@/store.js'; import { defaultStore } from '@/store.js';
import { useRouter } from '@/router.js';
let hideLine = $ref(false); let hideLine = $ref(false);
@ -70,6 +71,9 @@ const props = withDefaults(defineProps<{
const muted = ref($i ? checkWordMute(props.note, $i, $i.mutedWords) : false); const muted = ref($i ? checkWordMute(props.note, $i, $i.mutedWords) : false);
const expandOnNoteClick = defaultStore.state.expandOnNoteClick;
const router = useRouter();
let showContent = $ref(false); let showContent = $ref(false);
let replies: Misskey.entities.Note[] = $ref([]); let replies: Misskey.entities.Note[] = $ref([]);
@ -82,6 +86,11 @@ if (props.detail) {
hideLine = true; hideLine = true;
}); });
} }
function noteClick(ev: MouseEvent) {
if (document.getSelection().type === 'Range' || !expandOnNoteClick) ev.stopPropagation();
else router.push(notePage(props.note));
}
</script> </script>
<style lang="scss" module> <style lang="scss" module>

View file

@ -10,7 +10,7 @@ SPDX-License-Identifier: AGPL-3.0-only
v-vibrate="defaultStore.state.vibrateSystem ? [10, 30, 40] : []" v-vibrate="defaultStore.state.vibrateSystem ? [10, 30, 40] : []"
class="_button" class="_button"
:class="[$style.root, { [$style.reacted]: note.myReaction == reaction, [$style.canToggle]: (canToggle || alternative), [$style.small]: defaultStore.state.reactionsDisplaySize === 'small', [$style.large]: defaultStore.state.reactionsDisplaySize === 'large' }]" :class="[$style.root, { [$style.reacted]: note.myReaction == reaction, [$style.canToggle]: (canToggle || alternative), [$style.small]: defaultStore.state.reactionsDisplaySize === 'small', [$style.large]: defaultStore.state.reactionsDisplaySize === 'large' }]"
@click="toggleReaction()" @click.stop="toggleReaction()"
> >
<MkReactionIcon :class="defaultStore.state.limitWidthOfReaction ? $style.limitWidth : ''" :reaction="reaction" :emojiUrl="note.reactionEmojis[reaction.substring(1, reaction.length - 1)]"/> <MkReactionIcon :class="defaultStore.state.limitWidthOfReaction ? $style.limitWidth : ''" :reaction="reaction" :emojiUrl="note.reactionEmojis[reaction.substring(1, reaction.length - 1)]"/>
<span :class="$style.count">{{ count }}</span> <span :class="$style.count">{{ count }}</span>

View file

@ -50,13 +50,13 @@ SPDX-License-Identifier: AGPL-3.0-only
</div> </div>
</div> </div>
</div> </div>
<button v-if="(isLong || (isMFM && defaultStore.state.collapseDefault) || note.files.length > 0 || note.poll) && collapsed" v-vibrate="defaultStore.state.vibrateSystem ? 5 : []" :class="$style.fade" class="_button" @click="collapsed = false;"> <button v-if="(isLong || (isMFM && defaultStore.state.collapseDefault) || note.files.length > 0 || note.poll) && collapsed" v-vibrate="defaultStore.state.vibrateSystem ? 5 : []" :class="$style.fade" class="_button" @click.stop="collapsed = false;">
<span :class="$style.fadeLabel"> <span :class="$style.fadeLabel">
{{ i18n.ts.showMore }} {{ i18n.ts.showMore }}
<span v-if="note.files.length > 0" :class="$style.label">({{ collapseLabel }})</span> <span v-if="note.files.length > 0" :class="$style.label">({{ collapseLabel }})</span>
</span> </span>
</button> </button>
<button v-else-if="(isLong || (isMFM && defaultStore.state.collapseDefault) || note.files.length > 0 || note.poll) && !collapsed" v-vibrate="defaultStore.state.vibrateSystem ? 5 : []" :class="$style.showLess" class="_button" @click="collapsed = true;"> <button v-else-if="(isLong || (isMFM && defaultStore.state.collapseDefault) || note.files.length > 0 || note.poll) && !collapsed" v-vibrate="defaultStore.state.vibrateSystem ? 5 : []" :class="$style.showLess" class="_button" @click.stop="collapsed = true;">
<span :class="$style.showLessLabel">{{ i18n.ts.showLess }}</span> <span :class="$style.showLessLabel">{{ i18n.ts.showLess }}</span>
</button> </button>
<div v-if="showSubNoteFooterButton"> <div v-if="showSubNoteFooterButton">
@ -66,7 +66,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</template> </template>
</MkReactionsViewer> </MkReactionsViewer>
<footer :class="$style.footer"> <footer :class="$style.footer">
<button v-if="!note.isHidden" v-vibrate="defaultStore.state.vibrateSystem ? 5 : []" v-tooltip="i18n.ts.reply" :class="$style.footerButton" class="_button" @click="reply()"> <button v-if="!note.isHidden" v-vibrate="defaultStore.state.vibrateSystem ? 5 : []" v-tooltip="i18n.ts.reply" :class="$style.footerButton" class="_button" @click.stop="reply()">
<i class="ti ti-arrow-back-up"></i> <i class="ti ti-arrow-back-up"></i>
<p v-if="note.repliesCount > 0" :class="$style.footerButtonCount">{{ note.repliesCount }}</p> <p v-if="note.repliesCount > 0" :class="$style.footerButtonCount">{{ note.repliesCount }}</p>
</button> </button>
@ -95,10 +95,10 @@ SPDX-License-Identifier: AGPL-3.0-only
<i v-if="note.myReaction == null" v-tooltip="i18n.ts.reaction" class="ti ti-mood-plus"></i> <i v-if="note.myReaction == null" v-tooltip="i18n.ts.reaction" class="ti ti-mood-plus"></i>
<i v-else v-tooltip="i18n.ts.editReaction" class="ti ti-mood-edit"></i> <i v-else v-tooltip="i18n.ts.editReaction" class="ti ti-mood-edit"></i>
</button> </button>
<button v-if="note.myReaction != null && note.reactionAcceptance == 'likeOnly'" ref="reactButton" v-vibrate="defaultStore.state.vibrateSystem ? [30, 50, 50] : []" v-tooltip="i18n.ts.removeReaction" :class="$style.footerButton" class="_button" @click="undoReact(note)"> <button v-if="note.myReaction != null && note.reactionAcceptance == 'likeOnly'" ref="reactButton" v-vibrate="defaultStore.state.vibrateSystem ? [30, 50, 50] : []" v-tooltip="i18n.ts.removeReaction" :class="$style.footerButton" class="_button" @click.stop="undoReact(note)">
<i class="ti ti-heart-minus"></i> <i class="ti ti-heart-minus"></i>
</button> </button>
<button v-if="canRenote && defaultStore.state.renoteQuoteButtonSeparation" v-vibrate="defaultStore.state.vibrateSystem ? 5 : []" v-tooltip="i18n.ts.quote" class="_button" :class="$style.footerButton" @click="quote()"> <button v-if="canRenote && defaultStore.state.renoteQuoteButtonSeparation" v-vibrate="defaultStore.state.vibrateSystem ? 5 : []" v-tooltip="i18n.ts.quote" class="_button" :class="$style.footerButton" @click.stop="quote()">
<i class="ti ti-quote"></i> <i class="ti ti-quote"></i>
</button> </button>
<button v-if="defaultStore.state.showClipButtonInNoteFooter" ref="clipButton" v-vibrate="defaultStore.state.vibrateSystem ? 5 : []" v-tooltip="i18n.ts.clip" :class="$style.footerButton" class="_button" @mousedown="clip()"> <button v-if="defaultStore.state.showClipButtonInNoteFooter" ref="clipButton" v-vibrate="defaultStore.state.vibrateSystem ? 5 : []" v-tooltip="i18n.ts.clip" :class="$style.footerButton" class="_button" @mousedown="clip()">

View file

@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
--> -->
<template> <template>
<a v-vibrate="defaultStore.state.vibrateSystem ? 5 : []" :href="to" :class="active ? activeClass : null" @click.prevent="nav" @contextmenu.prevent.stop="onContextmenu"> <a v-vibrate="defaultStore.state.vibrateSystem ? 5 : []" :href="to" :class="active ? activeClass : null" @click.prevent.stop="nav" @contextmenu.prevent.stop="onContextmenu">
<slot></slot> <slot></slot>
</a> </a>
</template> </template>

View file

@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
--> -->
<template> <template>
<component :is="link ? MkA : 'span'" v-user-preview="preview ? user.id : undefined" v-bind="bound" class="_noSelect" :class="[$style.root, { [$style.animation]: animation, [$style.cat]: user.isCat, [$style.square]: squareAvatars }]" :style="{ color }" :title="acct(user)" @click="onClick"> <component :is="link ? MkA : 'span'" v-user-preview="preview ? user.id : undefined" v-bind="bound" class="_noSelect" :class="[$style.root, { [$style.animation]: animation, [$style.cat]: user.isCat, [$style.square]: squareAvatars }]" :style="{ color }" :title="acct(user)" @click.stop="onClick">
<MkImgWithBlurhash <MkImgWithBlurhash
:class="$style.inner" :class="$style.inner"
:src="url" :src="url"

View file

@ -28,6 +28,10 @@ SPDX-License-Identifier: AGPL-3.0-only
<template #label>{{ i18n.ts._cherrypick.showRenoteConfirmPopup }}</template> <template #label>{{ i18n.ts._cherrypick.showRenoteConfirmPopup }}</template>
<template #caption>{{ i18n.ts._cherrypick.showRenoteConfirmPopupDescription }}</template> <template #caption>{{ i18n.ts._cherrypick.showRenoteConfirmPopupDescription }}</template>
</MkSwitch> </MkSwitch>
<MkSwitch v-model="expandOnNoteClick">
<template #label>{{ i18n.ts._cherrypick.expandOnNoteClick }}</template>
<template #caption>{{ i18n.ts._cherrypick.expandOnNoteClickDescription }}</template>
</MkSwitch>
</div> </div>
<div> <div>
@ -96,6 +100,7 @@ const nicknameEnabled = computed(defaultStore.makeGetterSetter('nicknameEnabled'
const useEnterToSend = computed(defaultStore.makeGetterSetter('useEnterToSend')); const useEnterToSend = computed(defaultStore.makeGetterSetter('useEnterToSend'));
const postFormVisibilityHotkey = computed(defaultStore.makeGetterSetter('postFormVisibilityHotkey')); const postFormVisibilityHotkey = computed(defaultStore.makeGetterSetter('postFormVisibilityHotkey'));
const showRenoteConfirmPopup = computed(defaultStore.makeGetterSetter('showRenoteConfirmPopup')); const showRenoteConfirmPopup = computed(defaultStore.makeGetterSetter('showRenoteConfirmPopup'));
const expandOnNoteClick = computed(defaultStore.makeGetterSetter('expandOnNoteClick'));
const displayHeaderNavBarWhenScroll = computed(defaultStore.makeGetterSetter('displayHeaderNavBarWhenScroll')); const displayHeaderNavBarWhenScroll = computed(defaultStore.makeGetterSetter('displayHeaderNavBarWhenScroll'));
const reactableRemoteReactionEnabled = computed(defaultStore.makeGetterSetter('reactableRemoteReactionEnabled')); const reactableRemoteReactionEnabled = computed(defaultStore.makeGetterSetter('reactableRemoteReactionEnabled'));
const showFollowingMessageInsteadOfButtonEnabled = computed(defaultStore.makeGetterSetter('showFollowingMessageInsteadOfButtonEnabled')); const showFollowingMessageInsteadOfButtonEnabled = computed(defaultStore.makeGetterSetter('showFollowingMessageInsteadOfButtonEnabled'));
@ -113,6 +118,7 @@ watch([
}); });
watch([ watch([
expandOnNoteClick,
reactableRemoteReactionEnabled, reactableRemoteReactionEnabled,
mobileHeaderChange, mobileHeaderChange,
renameTheButtonInPostFormToNya, renameTheButtonInPostFormToNya,

View file

@ -618,6 +618,10 @@ export const defaultStore = markRaw(new Storage('base', {
where: 'device', where: 'device',
default: true, default: true,
}, },
expandOnNoteClick: {
where: 'device',
default: true,
},
displayHeaderNavBarWhenScroll: { displayHeaderNavBarWhenScroll: {
where: 'device', where: 'device',
default: 'hideHeaderFloatBtn' as 'all' | 'hideHeaderOnly' | 'hideHeaderFloatBtn' | 'hideFloatBtnOnly' | 'hideFloatBtnNavBar' | 'hide', default: 'hideHeaderFloatBtn' as 'all' | 'hideHeaderOnly' | 'hideHeaderFloatBtn' | 'hideFloatBtnOnly' | 'hideFloatBtnNavBar' | 'hide',