公開範囲に色付け(localonly)

This commit is contained in:
mattyatea 2023-09-26 10:54:46 +09:00
parent bc12bba97d
commit dd7b6f92df
2 changed files with 206 additions and 157 deletions

View File

@ -9,7 +9,13 @@ SPDX-License-Identifier: AGPL-3.0-only
v-show="!isDeleted" v-show="!isDeleted"
ref="el" ref="el"
v-hotkey="keymap" v-hotkey="keymap"
:class="[$style.root, { [$style.showActionsOnlyHover]: defaultStore.state.showNoteActionsOnlyHover } ,{[$style.home] : defaultStore.state.showVisibilityColor && note.visibility === 'home',[$style.followers] : defaultStore.state.showVisibilityColor && note.visibility === 'followers',[$style.specified] : defaultStore.state.showVisibilityColor && note.visibility === 'specified'}]" :class="[$style.root,
{ [$style.showActionsOnlyHover]: defaultStore.state.showNoteActionsOnlyHover } ,
{[$style.home] : defaultStore.state.showVisibilityColor && note.visibility === 'home'
,[$style.followers] : defaultStore.state.showVisibilityColor && note.visibility === 'followers'
,[$style.specified] : defaultStore.state.showVisibilityColor && note.visibility === 'specified'
},{[$style.localonly] : defaultStore.state.showVisibilityColor && note.localOnly }
]"
:tabindex="!isDeleted ? '-1' : undefined" :tabindex="!isDeleted ? '-1' : undefined"
> >
@ -33,18 +39,21 @@ SPDX-License-Identifier: AGPL-3.0-only
<i class="ti ti-dots" :class="$style.renoteMenu"></i> <i class="ti ti-dots" :class="$style.renoteMenu"></i>
<MkTime :time="note.createdAt"/> <MkTime :time="note.createdAt"/>
</button> </button>
<span v-if="note.visibility !== 'public'" style="margin-left: 0.5em;" :title="i18n.ts._visibility[note.visibility]"> <span v-if="note.visibility !== 'public'" style="margin-left: 0.5em;"
:title="i18n.ts._visibility[note.visibility]">
<i v-if="note.visibility === 'home'" class="ti ti-home"></i> <i v-if="note.visibility === 'home'" class="ti ti-home"></i>
<i v-else-if="note.visibility === 'followers'" class="ti ti-lock"></i> <i v-else-if="note.visibility === 'followers'" class="ti ti-lock"></i>
<i v-else-if="note.visibility === 'specified'" ref="specified" class="ti ti-mail"></i> <i v-else-if="note.visibility === 'specified'" ref="specified" class="ti ti-mail"></i>
</span> </span>
<span v-if="note.localOnly" style="margin-left: 0.5em;" :title="i18n.ts._visibility['disableFederation']"><i class="ti ti-rocket-off"></i></span> <span v-if="note.localOnly" style="margin-left: 0.5em;" :title="i18n.ts._visibility['disableFederation']"><i
class="ti ti-rocket-off"></i></span>
<span v-if="note.channel" style="margin-left: 0.5em;" :title="note.channel.name"><i class="ti ti-device-tv"></i></span> <span v-if="note.channel" style="margin-left: 0.5em;" :title="note.channel.name"><i class="ti ti-device-tv"></i></span>
</div> </div>
</div> </div>
<div v-if="renoteCollapsed" :class="$style.collapsedRenoteTarget"> <div v-if="renoteCollapsed" :class="$style.collapsedRenoteTarget">
<MkAvatar :class="$style.collapsedRenoteTargetAvatar" :user="appearNote.user" link preview/> <MkAvatar :class="$style.collapsedRenoteTargetAvatar" :user="appearNote.user" link preview/>
<Mfm :text="getNoteSummary(appearNote)" :plain="true" :nowrap="true" :author="appearNote.user" :class="$style.collapsedRenoteTargetText" @click="renoteCollapsed = false"/> <Mfm :text="getNoteSummary(appearNote)" :plain="true" :nowrap="true" :author="appearNote.user"
:class="$style.collapsedRenoteTargetText" @click="renoteCollapsed = false"/>
</div> </div>
<article v-else :class="$style.article" @contextmenu.stop="onContextmenu"> <article v-else :class="$style.article" @contextmenu.stop="onContextmenu">
<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>
@ -54,14 +63,17 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkInstanceTicker v-if="showTicker" :instance="appearNote.user.instance"/> <MkInstanceTicker v-if="showTicker" :instance="appearNote.user.instance"/>
<div style="container-type: inline-size;"> <div style="container-type: inline-size;">
<p v-if="appearNote.cw != null" :class="$style.cw"> <p v-if="appearNote.cw != null" :class="$style.cw">
<Mfm v-if="appearNote.cw != ''" style="margin-right: 8px;" :text="appearNote.cw" :author="appearNote.user" :i="$i"/> <Mfm v-if="appearNote.cw != ''" style="margin-right: 8px;" :text="appearNote.cw" :author="appearNote.user"
:i="$i"/>
<MkCwButton v-model="showContent" :note="appearNote"/> <MkCwButton v-model="showContent" :note="appearNote"/>
</p> </p>
<div v-show="appearNote.cw == null || showContent" :class="[{ [$style.contentCollapsed]: collapsed }]"> <div v-show="appearNote.cw == null || showContent" :class="[{ [$style.contentCollapsed]: collapsed }]">
<div :class="$style.text"> <div :class="$style.text">
<span v-if="appearNote.isHidden" style="opacity: 0.5">({{ i18n.ts.private }})</span> <span v-if="appearNote.isHidden" style="opacity: 0.5">({{ i18n.ts.private }})</span>
<MkA v-if="appearNote.replyId" :class="$style.replyIcon" :to="`/notes/${appearNote.replyId}`"><i class="ti ti-arrow-back-up"></i></MkA> <MkA v-if="appearNote.replyId" :class="$style.replyIcon" :to="`/notes/${appearNote.replyId}`"><i
<Mfm v-if="appearNote.text" :text="appearNote.text" :author="appearNote.user" :i="$i" :emojiUrls="appearNote.emojis"/> class="ti ti-arrow-back-up"></i></MkA>
<Mfm v-if="appearNote.text" :text="appearNote.text" :author="appearNote.user" :i="$i"
:emojiUrls="appearNote.emojis"/>
<div v-if="translating || translation" :class="$style.translation"> <div v-if="translating || translation" :class="$style.translation">
<MkLoading v-if="translating" mini/> <MkLoading v-if="translating" mini/>
<div v-else> <div v-else>
@ -74,8 +86,11 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkMediaList :mediaList="appearNote.files"/> <MkMediaList :mediaList="appearNote.files"/>
</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"
<div v-if="appearNote.renote" :class="$style.quote"><MkNoteSimple :note="appearNote.renote" :class="$style.quoteNote"/></div> :class="$style.urlPreview"/>
<div v-if="appearNote.renote" :class="$style.quote">
<MkNoteSimple :note="appearNote.renote" :class="$style.quoteNote"/>
</div>
<button v-if="isLong && collapsed" :class="$style.collapsed" class="_button" @click="collapsed = false"> <button v-if="isLong && collapsed" :class="$style.collapsed" class="_button" @click="collapsed = false">
<span :class="$style.collapsedLabel">{{ i18n.ts.showMore }}</span> <span :class="$style.collapsedLabel">{{ i18n.ts.showMore }}</span>
</button> </button>
@ -83,7 +98,9 @@ SPDX-License-Identifier: AGPL-3.0-only
<span :class="$style.showLessLabel">{{ i18n.ts.showLess }}</span> <span :class="$style.showLessLabel">{{ i18n.ts.showLess }}</span>
</button> </button>
</div> </div>
<MkA v-if="appearNote.channel && !inChannel" :class="$style.channel" :to="`/channels/${appearNote.channel.id}`"><i class="ti ti-device-tv"></i> {{ appearNote.channel.name }}</MkA> <MkA v-if="appearNote.channel && !inChannel" :class="$style.channel"
:to="`/channels/${appearNote.channel.id}`"><i class="ti ti-device-tv"></i> {{ appearNote.channel.name }}
</MkA>
</div> </div>
<MkReactionsViewer :note="appearNote" :maxNumber="16"> <MkReactionsViewer :note="appearNote" :maxNumber="16">
<template #more> <template #more>
@ -108,14 +125,17 @@ SPDX-License-Identifier: AGPL-3.0-only
<button v-else :class="$style.footerButton" class="_button" disabled> <button v-else :class="$style.footerButton" class="_button" disabled>
<i class="ti ti-ban"></i> <i class="ti ti-ban"></i>
</button> </button>
<button v-if="appearNote.myReaction == null" ref="reactButton" :class="$style.footerButton" class="_button" @mousedown="react()"> <button v-if="appearNote.myReaction == null" ref="reactButton" :class="$style.footerButton" class="_button"
@mousedown="react()">
<i v-if="appearNote.reactionAcceptance === 'likeOnly'" class="ti ti-heart"></i> <i v-if="appearNote.reactionAcceptance === 'likeOnly'" class="ti ti-heart"></i>
<i v-else class="ti ti-plus"></i> <i v-else class="ti ti-plus"></i>
</button> </button>
<button v-if="appearNote.myReaction != null" ref="reactButton" :class="$style.footerButton" class="_button" @click="undoReact(appearNote)"> <button v-if="appearNote.myReaction != null" ref="reactButton" :class="$style.footerButton" class="_button"
@click="undoReact(appearNote)">
<i class="ti ti-minus"></i> <i class="ti ti-minus"></i>
</button> </button>
<button v-if="defaultStore.state.showClipButtonInNoteFooter" ref="clipButton" :class="$style.footerButton" class="_button" @mousedown="clip()"> <button v-if="defaultStore.state.showClipButtonInNoteFooter" ref="clipButton" :class="$style.footerButton"
class="_button" @mousedown="clip()">
<i class="ti ti-paperclip"></i> <i class="ti ti-paperclip"></i>
</button> </button>
<button ref="menuButton" :class="$style.footerButton" class="_button" @mousedown="menu()"> <button ref="menuButton" :class="$style.footerButton" class="_button" @mousedown="menu()">
@ -177,7 +197,8 @@ const props = defineProps<{
}>(); }>();
const inChannel = inject('inChannel', null); const inChannel = inject('inChannel', null);
const currentClip = inject<Ref<Misskey.entities.Clip> | null>('currentClip', null);; const currentClip = inject<Ref<Misskey.entities.Clip> | null>('currentClip', null);
;
let note = $ref(deepClone(props.note)); let note = $ref(deepClone(props.note));
// plugin // plugin
@ -412,20 +433,38 @@ function onContextmenu(ev: MouseEvent): void {
ev.preventDefault(); ev.preventDefault();
react(); react();
} else { } else {
const { menu, cleanup } = getNoteMenu({ note: note, translating, translation, menuButton, isDeleted, currentClip: currentClip?.value }); const {menu, cleanup} = getNoteMenu({
note: note,
translating,
translation,
menuButton,
isDeleted,
currentClip: currentClip?.value
});
os.contextMenu(menu, ev).then(focus).finally(cleanup); os.contextMenu(menu, ev).then(focus).finally(cleanup);
} }
} }
function menu(viaKeyboard = false): void { function menu(viaKeyboard = false): void {
const { menu, cleanup } = getNoteMenu({ note: note, translating, translation, menuButton, isDeleted, currentClip: currentClip?.value }); const {menu, cleanup} = getNoteMenu({
note: note,
translating,
translation,
menuButton,
isDeleted,
currentClip: currentClip?.value
});
os.popupMenu(menu, menuButton.value, { os.popupMenu(menu, menuButton.value, {
viaKeyboard, viaKeyboard,
}).then(focus).finally(cleanup); }).then(focus).finally(cleanup);
} }
async function clip() { async function clip() {
os.popupMenu(await getNoteClipMenu({ note: note, isDeleted, currentClip: currentClip?.value }), clipButton.value).then(focus); os.popupMenu(await getNoteClipMenu({
note: note,
isDeleted,
currentClip: currentClip?.value
}), clipButton.value).then(focus);
} }
function showRenoteMenu(viaKeyboard = false): void { function showRenoteMenu(viaKeyboard = false): void {
@ -481,7 +520,6 @@ function focusAfter() {
} }
function readPromo() { function readPromo() {
os.api('promo/read', { os.api('promo/read', {
noteId: appearNote.id, noteId: appearNote.id,
@ -498,15 +536,21 @@ function readPromo() {
font-size: 1.05em; font-size: 1.05em;
overflow: clip; overflow: clip;
contain: content; contain: content;
&.home { &.home {
background-color: rgba(var(--homeColor), 0.20) !important; background-color: rgba(var(--homeColor), 0.20) !important;
} }
&.followers { &.followers {
background-color: rgba(var(--followerColor), 0.20) !important; background-color: rgba(var(--followerColor), 0.20) !important;
} }
&.specified { &.specified {
background-color: rgba(var(--specifiedColor), 0.20) !important; background-color: rgba(var(--specifiedColor), 0.20) !important;
} }
&.localonly {
background-color: rgba(var(--localOnlyColor), 0.20) !important;
}
// //
// //
// contain-intrinsic-size // contain-intrinsic-size
@ -951,6 +995,7 @@ function readPromo() {
padding: 0 6px; padding: 0 6px;
opacity: .8; opacity: .8;
} }
.root:has(.ti-home) { .root:has(.ti-home) {
background-color: rgba(255, 255, 100, 0.10) !important; background-color: rgba(255, 255, 100, 0.10) !important;
} }

View File

@ -57,6 +57,9 @@ SPDX-License-Identifier: AGPL-3.0-only
</MkColorInput> </MkColorInput>
<MkColorInput v-if="showVisibilityColor" v-model="specifiedColor"> <MkColorInput v-if="showVisibilityColor" v-model="specifiedColor">
<template #label>{{ i18n.ts._visibility.specified }}</template> <template #label>{{ i18n.ts._visibility.specified }}</template>
</MkColorInput>
<MkColorInput v-if="showVisibilityColor" v-model="localOnlyColor">
<template #label>{{ i18n.ts.localOnly }}</template>
</MkColorInput> </MkColorInput>
<MkSwitch v-model="advancedMfm">{{ i18n.ts.enableAdvancedMfm }}</MkSwitch> <MkSwitch v-model="advancedMfm">{{ i18n.ts.enableAdvancedMfm }}</MkSwitch>
<MkSwitch v-if="advancedMfm" v-model="animatedMfm">{{ i18n.ts.enableAnimatedMfm }}</MkSwitch> <MkSwitch v-if="advancedMfm" v-model="animatedMfm">{{ i18n.ts.enableAnimatedMfm }}</MkSwitch>
@ -269,6 +272,7 @@ const numberOfGamingSpeed = computed(defaultStore.makeGetterSetter('numberOfGami
const homeColor = computed(defaultStore.makeGetterSetter('homeColor')); const homeColor = computed(defaultStore.makeGetterSetter('homeColor'));
const followerColor = computed(defaultStore.makeGetterSetter('followerColor')); const followerColor = computed(defaultStore.makeGetterSetter('followerColor'));
const specifiedColor = computed(defaultStore.makeGetterSetter('specifiedColor')); const specifiedColor = computed(defaultStore.makeGetterSetter('specifiedColor'));
const localOnlyColor = computed(defaultStore.makeGetterSetter('localOnlyColor'));
const instanceTicker = computed(defaultStore.makeGetterSetter('instanceTicker')); const instanceTicker = computed(defaultStore.makeGetterSetter('instanceTicker'));
const enableInfiniteScroll = computed(defaultStore.makeGetterSetter('enableInfiniteScroll')); const enableInfiniteScroll = computed(defaultStore.makeGetterSetter('enableInfiniteScroll'));
const useReactionPickerForContextMenu = computed(defaultStore.makeGetterSetter('useReactionPickerForContextMenu')); const useReactionPickerForContextMenu = computed(defaultStore.makeGetterSetter('useReactionPickerForContextMenu'));