chore(client): rendering performance tweak a bit
This commit is contained in:
parent
f882e0b6b6
commit
bc73ad2e56
5 changed files with 85 additions and 84 deletions
|
@ -1,15 +1,17 @@
|
||||||
<template>
|
<template>
|
||||||
|
<!-- このコンポーネントの要素のclassは親から利用されるのでむやみに弄らないこと -->
|
||||||
<section>
|
<section>
|
||||||
<header class="_acrylic" @click="shown = !shown">
|
<header class="_acrylic" @click="shown = !shown">
|
||||||
<i class="toggle fa-fw" :class="shown ? 'fas fa-chevron-down' : 'fas fa-chevron-up'"></i> <slot></slot> ({{ emojis.length }})
|
<i class="toggle fa-fw" :class="shown ? 'fas fa-chevron-down' : 'fas fa-chevron-up'"></i> <slot></slot> ({{ emojis.length }})
|
||||||
</header>
|
</header>
|
||||||
<div v-if="shown">
|
<div v-if="shown" class="body">
|
||||||
<button v-for="emoji in emojis"
|
<button
|
||||||
|
v-for="emoji in emojis"
|
||||||
:key="emoji"
|
:key="emoji"
|
||||||
class="_button"
|
class="_button item"
|
||||||
@click="emit('chosen', emoji, $event)"
|
@click="emit('chosen', emoji, $event)"
|
||||||
>
|
>
|
||||||
<MkEmoji :emoji="emoji" :normal="true"/>
|
<MkEmoji class="emoji" :emoji="emoji" :normal="true"/>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
@ -3,63 +3,67 @@
|
||||||
<input ref="search" v-model.trim="q" class="search" data-prevent-emoji-insert :class="{ filled: q != null && q != '' }" :placeholder="i18n.ts.search" type="search" @paste.stop="paste" @keyup.enter="done()">
|
<input ref="search" v-model.trim="q" class="search" data-prevent-emoji-insert :class="{ filled: q != null && q != '' }" :placeholder="i18n.ts.search" type="search" @paste.stop="paste" @keyup.enter="done()">
|
||||||
<div ref="emojis" class="emojis">
|
<div ref="emojis" class="emojis">
|
||||||
<section class="result">
|
<section class="result">
|
||||||
<div v-if="searchResultCustom.length > 0">
|
<div v-if="searchResultCustom.length > 0" class="body">
|
||||||
<button v-for="emoji in searchResultCustom"
|
<button
|
||||||
|
v-for="emoji in searchResultCustom"
|
||||||
:key="emoji.id"
|
:key="emoji.id"
|
||||||
class="_button"
|
class="_button item"
|
||||||
:title="emoji.name"
|
:title="emoji.name"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
@click="chosen(emoji, $event)"
|
@click="chosen(emoji, $event)"
|
||||||
>
|
>
|
||||||
<!--<MkEmoji v-if="emoji.char != null" :emoji="emoji.char"/>-->
|
<!--<MkEmoji v-if="emoji.char != null" :emoji="emoji.char"/>-->
|
||||||
<img :src="disableShowingAnimatedImages ? getStaticImageUrl(emoji.url) : emoji.url"/>
|
<img class="emoji" :src="disableShowingAnimatedImages ? getStaticImageUrl(emoji.url) : emoji.url"/>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="searchResultUnicode.length > 0">
|
<div v-if="searchResultUnicode.length > 0" class="body">
|
||||||
<button v-for="emoji in searchResultUnicode"
|
<button
|
||||||
|
v-for="emoji in searchResultUnicode"
|
||||||
:key="emoji.name"
|
:key="emoji.name"
|
||||||
class="_button"
|
class="_button item"
|
||||||
:title="emoji.name"
|
:title="emoji.name"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
@click="chosen(emoji, $event)"
|
@click="chosen(emoji, $event)"
|
||||||
>
|
>
|
||||||
<MkEmoji :emoji="emoji.char"/>
|
<MkEmoji class="emoji" :emoji="emoji.char"/>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<div v-if="tab === 'index'" class="index">
|
<div v-if="tab === 'index'" class="group index">
|
||||||
<section v-if="showPinned">
|
<section v-if="showPinned">
|
||||||
<div>
|
<div class="body">
|
||||||
<button v-for="emoji in pinned"
|
<button
|
||||||
|
v-for="emoji in pinned"
|
||||||
:key="emoji"
|
:key="emoji"
|
||||||
class="_button"
|
class="_button item"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
@click="chosen(emoji, $event)"
|
@click="chosen(emoji, $event)"
|
||||||
>
|
>
|
||||||
<MkEmoji :emoji="emoji" :normal="true"/>
|
<MkEmoji class="emoji" :emoji="emoji" :normal="true"/>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
<header class="_acrylic"><i class="far fa-clock fa-fw"></i> {{ i18n.ts.recentUsed }}</header>
|
<header class="_acrylic"><i class="far fa-clock fa-fw"></i> {{ i18n.ts.recentUsed }}</header>
|
||||||
<div>
|
<div class="body">
|
||||||
<button v-for="emoji in recentlyUsedEmojis"
|
<button
|
||||||
|
v-for="emoji in recentlyUsedEmojis"
|
||||||
:key="emoji"
|
:key="emoji"
|
||||||
class="_button"
|
class="_button item"
|
||||||
@click="chosen(emoji, $event)"
|
@click="chosen(emoji, $event)"
|
||||||
>
|
>
|
||||||
<MkEmoji :emoji="emoji" :normal="true"/>
|
<MkEmoji class="emoji" :emoji="emoji" :normal="true"/>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div class="group">
|
||||||
<header class="_acrylic">{{ i18n.ts.customEmojis }}</header>
|
<header class="_acrylic">{{ i18n.ts.customEmojis }}</header>
|
||||||
<XSection v-for="category in customEmojiCategories" :key="'custom:' + category" :initial-shown="false" :emojis="customEmojis.filter(e => e.category === category).map(e => ':' + e.name + ':')" @chosen="chosen">{{ category || i18n.ts.other }}</XSection>
|
<XSection v-for="category in customEmojiCategories" :key="'custom:' + category" :initial-shown="false" :emojis="customEmojis.filter(e => e.category === category).map(e => ':' + e.name + ':')" @chosen="chosen">{{ category || i18n.ts.other }}</XSection>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div class="group">
|
||||||
<header class="_acrylic">{{ i18n.ts.emoji }}</header>
|
<header class="_acrylic">{{ i18n.ts.emoji }}</header>
|
||||||
<XSection v-for="category in categories" :key="category" :emojis="emojilist.filter(e => e.category === category).map(e => e.char)" @chosen="chosen">{{ category }}</XSection>
|
<XSection v-for="category in categories" :key="category" :emojis="emojilist.filter(e => e.category === category).map(e => e.char)" @chosen="chosen">{{ category }}</XSection>
|
||||||
</div>
|
</div>
|
||||||
|
@ -76,6 +80,7 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, computed, watch, onMounted } from 'vue';
|
import { ref, computed, watch, onMounted } from 'vue';
|
||||||
import * as Misskey from 'misskey-js';
|
import * as Misskey from 'misskey-js';
|
||||||
|
import XSection from './emoji-picker.section.vue';
|
||||||
import { emojilist, UnicodeEmojiDef, unicodeEmojiCategories as categories } from '@/scripts/emojilist';
|
import { emojilist, UnicodeEmojiDef, unicodeEmojiCategories as categories } from '@/scripts/emojilist';
|
||||||
import { getStaticImageUrl } from '@/scripts/get-static-image-url';
|
import { getStaticImageUrl } from '@/scripts/get-static-image-url';
|
||||||
import Ripple from '@/components/ripple.vue';
|
import Ripple from '@/components/ripple.vue';
|
||||||
|
@ -83,7 +88,6 @@ import * as os from '@/os';
|
||||||
import { isTouchUsing } from '@/scripts/touch';
|
import { isTouchUsing } from '@/scripts/touch';
|
||||||
import { deviceKind } from '@/scripts/device-kind';
|
import { deviceKind } from '@/scripts/device-kind';
|
||||||
import { emojiCategories, instance } from '@/instance';
|
import { emojiCategories, instance } from '@/instance';
|
||||||
import XSection from './emoji-picker.section.vue';
|
|
||||||
import { i18n } from '@/i18n';
|
import { i18n } from '@/i18n';
|
||||||
import { defaultStore } from '@/store';
|
import { defaultStore } from '@/store';
|
||||||
|
|
||||||
|
@ -266,7 +270,7 @@ watch(q, () => {
|
||||||
function focus() {
|
function focus() {
|
||||||
if (!['smartphone', 'tablet'].includes(deviceKind) && !isTouchUsing) {
|
if (!['smartphone', 'tablet'].includes(deviceKind) && !isTouchUsing) {
|
||||||
search.value?.focus({
|
search.value?.focus({
|
||||||
preventScroll: true
|
preventScroll: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -415,19 +419,16 @@ defineExpose({
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
> div {
|
> .body {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: var(--columns);
|
grid-template-columns: var(--columns);
|
||||||
|
font-size: 30px;
|
||||||
|
|
||||||
> button {
|
> .item {
|
||||||
aspect-ratio: 1 / 1;
|
aspect-ratio: 1 / 1;
|
||||||
width: auto;
|
width: auto;
|
||||||
height: auto;
|
height: auto;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
|
|
||||||
> * {
|
|
||||||
font-size: 30px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -478,7 +479,7 @@ defineExpose({
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
> div {
|
> .group {
|
||||||
&:not(.index) {
|
&:not(.index) {
|
||||||
padding: 4px 0 8px 0;
|
padding: 4px 0 8px 0;
|
||||||
border-top: solid 0.5px var(--divider);
|
border-top: solid 0.5px var(--divider);
|
||||||
|
@ -513,16 +514,18 @@ defineExpose({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
> div {
|
> .body {
|
||||||
position: relative;
|
position: relative;
|
||||||
padding: $pad;
|
padding: $pad;
|
||||||
|
|
||||||
> button {
|
> .item {
|
||||||
position: relative;
|
position: relative;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
width: var(--eachSize);
|
width: var(--eachSize);
|
||||||
height: var(--eachSize);
|
height: var(--eachSize);
|
||||||
|
contain: strict;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
|
font-size: 24px;
|
||||||
|
|
||||||
&:focus-visible {
|
&:focus-visible {
|
||||||
outline: solid 2px var(--focus);
|
outline: solid 2px var(--focus);
|
||||||
|
@ -538,8 +541,7 @@ defineExpose({
|
||||||
box-shadow: inset 0 0.15em 0.3em rgba(27, 31, 35, 0.15);
|
box-shadow: inset 0 0.15em 0.3em rgba(27, 31, 35, 0.15);
|
||||||
}
|
}
|
||||||
|
|
||||||
> * {
|
> .emoji {
|
||||||
font-size: 24px;
|
|
||||||
height: 1.25em;
|
height: 1.25em;
|
||||||
vertical-align: -.25em;
|
vertical-align: -.25em;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
|
|
@ -2,9 +2,9 @@
|
||||||
<div v-if="hide" class="qjewsnkg" @click="hide = false">
|
<div v-if="hide" class="qjewsnkg" @click="hide = false">
|
||||||
<ImgWithBlurhash class="bg" :hash="image.blurhash" :title="image.comment" :alt="image.comment"/>
|
<ImgWithBlurhash class="bg" :hash="image.blurhash" :title="image.comment" :alt="image.comment"/>
|
||||||
<div class="text">
|
<div class="text">
|
||||||
<div>
|
<div class="wrapper">
|
||||||
<b><i class="fas fa-exclamation-triangle"></i> {{ $ts.sensitive }}</b>
|
<b style="display: block;"><i class="fas fa-exclamation-triangle"></i> {{ $ts.sensitive }}</b>
|
||||||
<span>{{ $ts.clickToShow }}</span>
|
<span style="display: block;">{{ $ts.clickToShow }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -37,8 +37,8 @@ let hide = $ref(true);
|
||||||
const url = (props.raw || defaultStore.state.loadRawImages)
|
const url = (props.raw || defaultStore.state.loadRawImages)
|
||||||
? props.image.url
|
? props.image.url
|
||||||
: defaultStore.state.disableShowingAnimatedImages
|
: defaultStore.state.disableShowingAnimatedImages
|
||||||
? getStaticImageUrl(props.image.thumbnailUrl)
|
? getStaticImageUrl(props.image.thumbnailUrl)
|
||||||
: props.image.thumbnailUrl;
|
: props.image.thumbnailUrl;
|
||||||
|
|
||||||
// Plugin:register_note_view_interruptor を使って書き換えられる可能性があるためwatchする
|
// Plugin:register_note_view_interruptor を使って書き換えられる可能性があるためwatchする
|
||||||
watch(() => props.image, () => {
|
watch(() => props.image, () => {
|
||||||
|
@ -68,15 +68,11 @@ watch(() => props.image, () => {
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
> div {
|
> .wrapper {
|
||||||
display: table-cell;
|
display: table-cell;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 0.8em;
|
font-size: 0.8em;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
|
|
||||||
> * {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<div v-show="files.length != 0" class="skeikyzd">
|
<div v-show="files.length != 0" class="skeikyzd">
|
||||||
<XDraggable v-model="_files" class="files" item-key="id" animation="150" delay="100" delay-on-touch-only="true">
|
<XDraggable v-model="_files" class="files" item-key="id" animation="150" delay="100" delay-on-touch-only="true">
|
||||||
<template #item="{element}">
|
<template #item="{element}">
|
||||||
<div @click="showFileMenu(element, $event)" @contextmenu.prevent="showFileMenu(element, $event)">
|
<div class="file" @click="showFileMenu(element, $event)" @contextmenu.prevent="showFileMenu(element, $event)">
|
||||||
<MkDriveFileThumbnail :data-id="element.id" class="thumbnail" :file="element" fit="cover"/>
|
<MkDriveFileThumbnail :data-id="element.id" class="thumbnail" :file="element" fit="cover"/>
|
||||||
<div v-if="element.isSensitive" class="sensitive">
|
<div v-if="element.isSensitive" class="sensitive">
|
||||||
<i class="fas fa-exclamation-triangle icon"></i>
|
<i class="fas fa-exclamation-triangle icon"></i>
|
||||||
|
@ -22,18 +22,18 @@ import * as os from '@/os';
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
XDraggable: defineAsyncComponent(() => import('vuedraggable').then(x => x.default)),
|
XDraggable: defineAsyncComponent(() => import('vuedraggable').then(x => x.default)),
|
||||||
MkDriveFileThumbnail
|
MkDriveFileThumbnail,
|
||||||
},
|
},
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
files: {
|
files: {
|
||||||
type: Array,
|
type: Array,
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
detachMediaFn: {
|
detachMediaFn: {
|
||||||
type: Function,
|
type: Function,
|
||||||
required: false
|
required: false,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
emits: ['updated', 'detach', 'changeSensitive', 'changeName'],
|
emits: ['updated', 'detach', 'changeSensitive', 'changeName'],
|
||||||
|
@ -51,8 +51,8 @@ export default defineComponent({
|
||||||
},
|
},
|
||||||
set(value) {
|
set(value) {
|
||||||
this.$emit('updated', value);
|
this.$emit('updated', value);
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -66,7 +66,7 @@ export default defineComponent({
|
||||||
toggleSensitive(file) {
|
toggleSensitive(file) {
|
||||||
os.api('drive/files/update', {
|
os.api('drive/files/update', {
|
||||||
fileId: file.id,
|
fileId: file.id,
|
||||||
isSensitive: !file.isSensitive
|
isSensitive: !file.isSensitive,
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
this.$emit('changeSensitive', file, !file.isSensitive);
|
this.$emit('changeSensitive', file, !file.isSensitive);
|
||||||
});
|
});
|
||||||
|
@ -75,12 +75,12 @@ export default defineComponent({
|
||||||
const { canceled, result } = await os.inputText({
|
const { canceled, result } = await os.inputText({
|
||||||
title: this.$ts.enterFileName,
|
title: this.$ts.enterFileName,
|
||||||
default: file.name,
|
default: file.name,
|
||||||
allowEmpty: false
|
allowEmpty: false,
|
||||||
});
|
});
|
||||||
if (canceled) return;
|
if (canceled) return;
|
||||||
os.api('drive/files/update', {
|
os.api('drive/files/update', {
|
||||||
fileId: file.id,
|
fileId: file.id,
|
||||||
name: result
|
name: result,
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
this.$emit('changeName', file, result);
|
this.$emit('changeName', file, result);
|
||||||
file.name = result;
|
file.name = result;
|
||||||
|
@ -88,13 +88,13 @@ export default defineComponent({
|
||||||
},
|
},
|
||||||
|
|
||||||
async describe(file) {
|
async describe(file) {
|
||||||
os.popup(defineAsyncComponent(() => import("@/components/media-caption.vue")), {
|
os.popup(defineAsyncComponent(() => import('@/components/media-caption.vue')), {
|
||||||
title: this.$ts.describeFile,
|
title: this.$ts.describeFile,
|
||||||
input: {
|
input: {
|
||||||
placeholder: this.$ts.inputNewDescription,
|
placeholder: this.$ts.inputNewDescription,
|
||||||
default: file.comment !== null ? file.comment : "",
|
default: file.comment !== null ? file.comment : '',
|
||||||
},
|
},
|
||||||
image: file
|
image: file,
|
||||||
}, {
|
}, {
|
||||||
done: result => {
|
done: result => {
|
||||||
if (!result || result.canceled) return;
|
if (!result || result.canceled) return;
|
||||||
|
@ -105,7 +105,7 @@ export default defineComponent({
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
file.comment = comment;
|
file.comment = comment;
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
}, 'closed');
|
}, 'closed');
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -114,22 +114,22 @@ export default defineComponent({
|
||||||
this.menu = os.popupMenu([{
|
this.menu = os.popupMenu([{
|
||||||
text: this.$ts.renameFile,
|
text: this.$ts.renameFile,
|
||||||
icon: 'fas fa-i-cursor',
|
icon: 'fas fa-i-cursor',
|
||||||
action: () => { this.rename(file); }
|
action: () => { this.rename(file); },
|
||||||
}, {
|
}, {
|
||||||
text: file.isSensitive ? this.$ts.unmarkAsSensitive : this.$ts.markAsSensitive,
|
text: file.isSensitive ? this.$ts.unmarkAsSensitive : this.$ts.markAsSensitive,
|
||||||
icon: file.isSensitive ? 'fas fa-eye-slash' : 'fas fa-eye',
|
icon: file.isSensitive ? 'fas fa-eye-slash' : 'fas fa-eye',
|
||||||
action: () => { this.toggleSensitive(file); }
|
action: () => { this.toggleSensitive(file); },
|
||||||
}, {
|
}, {
|
||||||
text: this.$ts.describeFile,
|
text: this.$ts.describeFile,
|
||||||
icon: 'fas fa-i-cursor',
|
icon: 'fas fa-i-cursor',
|
||||||
action: () => { this.describe(file); }
|
action: () => { this.describe(file); },
|
||||||
}, {
|
}, {
|
||||||
text: this.$ts.attachCancel,
|
text: this.$ts.attachCancel,
|
||||||
icon: 'fas fa-times-circle',
|
icon: 'fas fa-times-circle',
|
||||||
action: () => { this.detachMedia(file.id); }
|
action: () => { this.detachMedia(file.id); },
|
||||||
}], ev.currentTarget ?? ev.target).then(() => this.menu = null);
|
}], ev.currentTarget ?? ev.target).then(() => this.menu = null);
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -142,7 +142,7 @@ export default defineComponent({
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
|
||||||
> div {
|
> .file {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 64px;
|
width: 64px;
|
||||||
height: 64px;
|
height: 64px;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div v-size="{ max: [310, 500] }" class="gafaadew"
|
<div
|
||||||
|
v-size="{ max: [310, 500] }" class="gafaadew"
|
||||||
:class="{ modal, _popup: modal }"
|
:class="{ modal, _popup: modal }"
|
||||||
@dragover.stop="onDragover"
|
@dragover.stop="onDragover"
|
||||||
@dragenter="onDragenter"
|
@dragenter="onDragenter"
|
||||||
|
@ -11,7 +12,7 @@
|
||||||
<button v-click-anime v-tooltip="i18n.ts.switchAccount" class="account _button" @click="openAccountMenu">
|
<button v-click-anime v-tooltip="i18n.ts.switchAccount" class="account _button" @click="openAccountMenu">
|
||||||
<MkAvatar :user="postAccount ?? $i" class="avatar"/>
|
<MkAvatar :user="postAccount ?? $i" class="avatar"/>
|
||||||
</button>
|
</button>
|
||||||
<div>
|
<div class="right">
|
||||||
<span class="text-count" :class="{ over: textLength > maxTextLength }">{{ maxTextLength - textLength }}</span>
|
<span class="text-count" :class="{ over: textLength > maxTextLength }">{{ maxTextLength - textLength }}</span>
|
||||||
<span v-if="localOnly" class="local-only"><i class="fas fa-biohazard"></i></span>
|
<span v-if="localOnly" class="local-only"><i class="fas fa-biohazard"></i></span>
|
||||||
<button ref="visibilityButton" v-tooltip="i18n.ts.visibility" class="_button visibility" :disabled="channel != null" @click="setVisibility">
|
<button ref="visibilityButton" v-tooltip="i18n.ts.visibility" class="_button visibility" :disabled="channel != null" @click="setVisibility">
|
||||||
|
@ -68,6 +69,8 @@ import * as misskey from 'misskey-js';
|
||||||
import insertTextAtCursor from 'insert-text-at-cursor';
|
import insertTextAtCursor from 'insert-text-at-cursor';
|
||||||
import { length } from 'stringz';
|
import { length } from 'stringz';
|
||||||
import { toASCII } from 'punycode/';
|
import { toASCII } from 'punycode/';
|
||||||
|
import * as Acct from 'misskey-js/built/acct';
|
||||||
|
import { throttle } from 'throttle-debounce';
|
||||||
import XNoteSimple from './note-simple.vue';
|
import XNoteSimple from './note-simple.vue';
|
||||||
import XNotePreview from './note-preview.vue';
|
import XNotePreview from './note-preview.vue';
|
||||||
import XPostFormAttaches from './post-form-attaches.vue';
|
import XPostFormAttaches from './post-form-attaches.vue';
|
||||||
|
@ -75,14 +78,12 @@ import XPollEditor from './poll-editor.vue';
|
||||||
import { host, url } from '@/config';
|
import { host, url } from '@/config';
|
||||||
import { erase, unique } from '@/scripts/array';
|
import { erase, unique } from '@/scripts/array';
|
||||||
import { extractMentions } from '@/scripts/extract-mentions';
|
import { extractMentions } from '@/scripts/extract-mentions';
|
||||||
import * as Acct from 'misskey-js/built/acct';
|
|
||||||
import { formatTimeString } from '@/scripts/format-time-string';
|
import { formatTimeString } from '@/scripts/format-time-string';
|
||||||
import { Autocomplete } from '@/scripts/autocomplete';
|
import { Autocomplete } from '@/scripts/autocomplete';
|
||||||
import * as os from '@/os';
|
import * as os from '@/os';
|
||||||
import { stream } from '@/stream';
|
import { stream } from '@/stream';
|
||||||
import { selectFiles } from '@/scripts/select-file';
|
import { selectFiles } from '@/scripts/select-file';
|
||||||
import { defaultStore, notePostInterruptors, postFormActions } from '@/store';
|
import { defaultStore, notePostInterruptors, postFormActions } from '@/store';
|
||||||
import { throttle } from 'throttle-debounce';
|
|
||||||
import MkInfo from '@/components/ui/info.vue';
|
import MkInfo from '@/components/ui/info.vue';
|
||||||
import { i18n } from '@/i18n';
|
import { i18n } from '@/i18n';
|
||||||
import { instance } from '@/instance';
|
import { instance } from '@/instance';
|
||||||
|
@ -181,7 +182,7 @@ const placeholder = $computed((): string => {
|
||||||
i18n.ts._postForm._placeholders.c,
|
i18n.ts._postForm._placeholders.c,
|
||||||
i18n.ts._postForm._placeholders.d,
|
i18n.ts._postForm._placeholders.d,
|
||||||
i18n.ts._postForm._placeholders.e,
|
i18n.ts._postForm._placeholders.e,
|
||||||
i18n.ts._postForm._placeholders.f
|
i18n.ts._postForm._placeholders.f,
|
||||||
];
|
];
|
||||||
return xs[Math.floor(Math.random() * xs.length)];
|
return xs[Math.floor(Math.random() * xs.length)];
|
||||||
}
|
}
|
||||||
|
@ -238,10 +239,10 @@ if (props.reply && props.reply.text != null) {
|
||||||
|
|
||||||
for (const x of extractMentions(ast)) {
|
for (const x of extractMentions(ast)) {
|
||||||
const mention = x.host ?
|
const mention = x.host ?
|
||||||
`@${x.username}@${toASCII(x.host)}` :
|
`@${x.username}@${toASCII(x.host)}` :
|
||||||
(otherHost == null || otherHost === host) ?
|
(otherHost == null || otherHost === host) ?
|
||||||
`@${x.username}` :
|
`@${x.username}` :
|
||||||
`@${x.username}@${toASCII(otherHost)}`;
|
`@${x.username}@${toASCII(otherHost)}`;
|
||||||
|
|
||||||
// 自分は除外
|
// 自分は除外
|
||||||
if ($i.username === x.username && (x.host == null || x.host === host)) continue;
|
if ($i.username === x.username && (x.host == null || x.host === host)) continue;
|
||||||
|
@ -263,7 +264,7 @@ if (props.reply && ['home', 'followers', 'specified'].includes(props.reply.visib
|
||||||
visibility = props.reply.visibility;
|
visibility = props.reply.visibility;
|
||||||
if (props.reply.visibility === 'specified') {
|
if (props.reply.visibility === 'specified') {
|
||||||
os.api('users/show', {
|
os.api('users/show', {
|
||||||
userIds: props.reply.visibleUserIds.filter(uid => uid !== $i.id && uid !== props.reply.userId)
|
userIds: props.reply.visibleUserIds.filter(uid => uid !== $i.id && uid !== props.reply.userId),
|
||||||
}).then(users => {
|
}).then(users => {
|
||||||
users.forEach(pushVisibleUser);
|
users.forEach(pushVisibleUser);
|
||||||
});
|
});
|
||||||
|
@ -399,7 +400,7 @@ function setVisibility() {
|
||||||
if (defaultStore.state.rememberNoteVisibility) {
|
if (defaultStore.state.rememberNoteVisibility) {
|
||||||
defaultStore.set('localOnly', localOnly);
|
defaultStore.set('localOnly', localOnly);
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}, 'closed');
|
}, 'closed');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -522,8 +523,8 @@ function saveDraft() {
|
||||||
visibility: visibility,
|
visibility: visibility,
|
||||||
localOnly: localOnly,
|
localOnly: localOnly,
|
||||||
files: files,
|
files: files,
|
||||||
poll: poll
|
poll: poll,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
localStorage.setItem('drafts', JSON.stringify(draftData));
|
localStorage.setItem('drafts', JSON.stringify(draftData));
|
||||||
|
@ -612,11 +613,11 @@ function showActions(ev) {
|
||||||
text: action.title,
|
text: action.title,
|
||||||
action: () => {
|
action: () => {
|
||||||
action.handler({
|
action.handler({
|
||||||
text: text
|
text: text,
|
||||||
}, (key, value) => {
|
}, (key, value) => {
|
||||||
if (key === 'text') { text = value; }
|
if (key === 'text') { text = value; }
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
})), ev.currentTarget ?? ev.target);
|
})), ev.currentTarget ?? ev.target);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -726,7 +727,7 @@ onMounted(() => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
> div {
|
> .right {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
|
@ -924,7 +925,7 @@ onMounted(() => {
|
||||||
line-height: 50px;
|
line-height: 50px;
|
||||||
}
|
}
|
||||||
|
|
||||||
> div {
|
> .right {
|
||||||
> .text-count {
|
> .text-count {
|
||||||
line-height: 50px;
|
line-height: 50px;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue