mirror of
https://github.com/hotomoe/hotomoe
synced 2024-11-28 23:08:17 +09:00
parent
9f9d7325fd
commit
ebb53e87f3
@ -768,6 +768,7 @@ squareAvatars: "アイコンを四角形で表示"
|
||||
sent: "送信"
|
||||
received: "受信"
|
||||
searchResult: "検索結果"
|
||||
hashtags: "ハッシュタグ"
|
||||
|
||||
_docs:
|
||||
continueReading: "続きを読む"
|
||||
|
@ -37,6 +37,7 @@
|
||||
<MkInfo warn v-if="hasNotSpecifiedMentions" class="hasNotSpecifiedMentions">{{ $ts.notSpecifiedMentionWarning }} - <button class="_textButton" @click="addMissingMention()">{{ $ts.add }}</button></MkInfo>
|
||||
<input v-show="useCw" ref="cw" class="cw" v-model="cw" :placeholder="$ts.annotation" @keydown="onKeydown">
|
||||
<textarea v-model="text" class="text" :class="{ withCw: useCw }" ref="text" :disabled="posting" :placeholder="placeholder" @keydown="onKeydown" @paste="onPaste" @compositionupdate="onCompositionUpdate" @compositionend="onCompositionEnd" />
|
||||
<input v-show="withHashtags" ref="hashtags" class="hashtags" v-model="hashtags" :placeholder="$ts.hashtags" list="hashtags">
|
||||
<XPostFormAttaches class="attaches" :files="files" @updated="updateFiles" @detach="detachFile" @changeSensitive="updateFileSensitive" @changeName="updateFileName"/>
|
||||
<XPollEditor v-if="poll" :poll="poll" @destroyed="poll = null" @updated="onPollUpdate"/>
|
||||
<footer>
|
||||
@ -44,9 +45,13 @@
|
||||
<button class="_button" @click="togglePoll" :class="{ active: poll }" v-tooltip="$ts.poll"><i class="fas fa-poll-h"></i></button>
|
||||
<button class="_button" @click="useCw = !useCw" :class="{ active: useCw }" v-tooltip="$ts.useCw"><i class="fas fa-eye-slash"></i></button>
|
||||
<button class="_button" @click="insertMention" v-tooltip="$ts.mention"><i class="fas fa-at"></i></button>
|
||||
<button class="_button" @click="withHashtags = !withHashtags" v-tooltip="$ts.hashtags"><i class="fas fa-hashtag"></i></button>
|
||||
<button class="_button" @click="insertEmoji" v-tooltip="$ts.emoji"><i class="fas fa-laugh-squint"></i></button>
|
||||
<button class="_button" @click="showActions" v-tooltip="$ts.plugin" v-if="postFormActions.length > 0"><i class="fas fa-plug"></i></button>
|
||||
</footer>
|
||||
<datalist id="hashtags">
|
||||
<option v-for="hashtag in recentHashtags" :value="hashtag" :key="hashtag"/>
|
||||
</datalist>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@ -67,10 +72,11 @@ import { Autocomplete } from '@client/scripts/autocomplete';
|
||||
import { noteVisibilities } from '../../types';
|
||||
import * as os from '@client/os';
|
||||
import { selectFile } from '@client/scripts/select-file';
|
||||
import { notePostInterruptors, postFormActions } from '@client/store';
|
||||
import { defaultStore, notePostInterruptors, postFormActions } from '@client/store';
|
||||
import { isMobile } from '@client/scripts/is-mobile';
|
||||
import { throttle } from 'throttle-debounce';
|
||||
import MkInfo from '@client/components/ui/info.vue';
|
||||
import { defaultStore } from '@client/store';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
@ -212,7 +218,10 @@ export default defineComponent({
|
||||
|
||||
max(): number {
|
||||
return this.$instance ? this.$instance.maxNoteTextLength : 1000;
|
||||
}
|
||||
},
|
||||
|
||||
withHashtags: defaultStore.makeGetterSetter('postFormWithHashtags'),
|
||||
hashtags: defaultStore.makeGetterSetter('postFormHashtags'),
|
||||
},
|
||||
|
||||
watch: {
|
||||
@ -303,6 +312,7 @@ export default defineComponent({
|
||||
// TODO: detach when unmount
|
||||
new Autocomplete(this.$refs.text, this, { model: 'text' });
|
||||
new Autocomplete(this.$refs.cw, this, { model: 'cw' });
|
||||
new Autocomplete(this.$refs.hashtags, this, { model: 'hashtags' });
|
||||
|
||||
this.$nextTick(() => {
|
||||
// 書きかけの投稿を復元
|
||||
@ -605,6 +615,11 @@ export default defineComponent({
|
||||
viaMobile: isMobile
|
||||
};
|
||||
|
||||
if (this.withHashtags) {
|
||||
const hashtags = this.hashtags.trim().split(' ').map(x => x.startsWith('#') ? x : '#' + x).join(' ');
|
||||
data.text = data.text ? `${data.text} ${hashtags}` : hashtags;
|
||||
}
|
||||
|
||||
// plugin
|
||||
if (notePostInterruptors.length > 0) {
|
||||
for (const interruptor of notePostInterruptors) {
|
||||
@ -618,8 +633,8 @@ export default defineComponent({
|
||||
this.$nextTick(() => {
|
||||
this.deleteDraft();
|
||||
this.$emit('posted');
|
||||
if (this.text && this.text != '') {
|
||||
const hashtags = mfm.parse(this.text).filter(x => x.type === 'hashtag').map(x => x.props.hashtag);
|
||||
if (data.text && data.text != '') {
|
||||
const hashtags = mfm.parse(data.text).filter(x => x.type === 'hashtag').map(x => x.props.hashtag);
|
||||
const history = JSON.parse(localStorage.getItem('hashtags') || '[]') as string[];
|
||||
localStorage.setItem('hashtags', JSON.stringify(unique(hashtags.concat(history))));
|
||||
}
|
||||
@ -785,6 +800,7 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
> .cw,
|
||||
> .hashtags,
|
||||
> .text {
|
||||
display: block;
|
||||
box-sizing: border-box;
|
||||
@ -813,6 +829,13 @@ export default defineComponent({
|
||||
border-bottom: solid 0.5px var(--divider);
|
||||
}
|
||||
|
||||
> .hashtags {
|
||||
z-index: 1;
|
||||
padding-top: 8px;
|
||||
padding-bottom: 8px;
|
||||
border-top: solid 0.5px var(--divider);
|
||||
}
|
||||
|
||||
> .text {
|
||||
max-width: 100%;
|
||||
min-width: 100%;
|
||||
@ -872,6 +895,7 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
> .cw,
|
||||
> .hashtags,
|
||||
> .text {
|
||||
padding: 0 16px;
|
||||
}
|
||||
|
@ -198,6 +198,14 @@ export const defaultStore = markRaw(new Storage('base', {
|
||||
where: 'device',
|
||||
default: false
|
||||
},
|
||||
postFormWithHashtags: {
|
||||
where: 'device',
|
||||
default: false
|
||||
},
|
||||
postFormHashtags: {
|
||||
where: 'device',
|
||||
default: ''
|
||||
},
|
||||
}));
|
||||
|
||||
// TODO: 他のタブと永続化されたstateを同期
|
||||
|
Loading…
Reference in New Issue
Block a user