parent
							
								
									9f9d7325fd
								
							
						
					
					
						commit
						ebb53e87f3
					
				
					 3 changed files with 37 additions and 4 deletions
				
			
		|  | @ -768,6 +768,7 @@ squareAvatars: "アイコンを四角形で表示" | ||||||
| sent: "送信" | sent: "送信" | ||||||
| received: "受信" | received: "受信" | ||||||
| searchResult: "検索結果" | searchResult: "検索結果" | ||||||
|  | hashtags: "ハッシュタグ" | ||||||
| 
 | 
 | ||||||
| _docs:  | _docs:  | ||||||
|   continueReading: "続きを読む" |   continueReading: "続きを読む" | ||||||
|  |  | ||||||
|  | @ -37,6 +37,7 @@ | ||||||
| 		<MkInfo warn v-if="hasNotSpecifiedMentions" class="hasNotSpecifiedMentions">{{ $ts.notSpecifiedMentionWarning }} - <button class="_textButton" @click="addMissingMention()">{{ $ts.add }}</button></MkInfo> | 		<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"> | 		<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" /> | 		<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"/> | 		<XPostFormAttaches class="attaches" :files="files" @updated="updateFiles" @detach="detachFile" @changeSensitive="updateFileSensitive" @changeName="updateFileName"/> | ||||||
| 		<XPollEditor v-if="poll" :poll="poll" @destroyed="poll = null" @updated="onPollUpdate"/> | 		<XPollEditor v-if="poll" :poll="poll" @destroyed="poll = null" @updated="onPollUpdate"/> | ||||||
| 		<footer> | 		<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="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="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="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="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> | 			<button class="_button" @click="showActions" v-tooltip="$ts.plugin" v-if="postFormActions.length > 0"><i class="fas fa-plug"></i></button> | ||||||
| 		</footer> | 		</footer> | ||||||
|  | 		<datalist id="hashtags"> | ||||||
|  | 			<option v-for="hashtag in recentHashtags" :value="hashtag" :key="hashtag"/> | ||||||
|  | 		</datalist> | ||||||
| 	</div> | 	</div> | ||||||
| </div> | </div> | ||||||
| </template> | </template> | ||||||
|  | @ -67,10 +72,11 @@ import { Autocomplete } from '@client/scripts/autocomplete'; | ||||||
| import { noteVisibilities } from '../../types'; | import { noteVisibilities } from '../../types'; | ||||||
| import * as os from '@client/os'; | import * as os from '@client/os'; | ||||||
| import { selectFile } from '@client/scripts/select-file'; | 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 { isMobile } from '@client/scripts/is-mobile'; | ||||||
| import { throttle } from 'throttle-debounce'; | import { throttle } from 'throttle-debounce'; | ||||||
| import MkInfo from '@client/components/ui/info.vue'; | import MkInfo from '@client/components/ui/info.vue'; | ||||||
|  | import { defaultStore } from '@client/store'; | ||||||
| 
 | 
 | ||||||
| export default defineComponent({ | export default defineComponent({ | ||||||
| 	components: { | 	components: { | ||||||
|  | @ -212,7 +218,10 @@ export default defineComponent({ | ||||||
| 
 | 
 | ||||||
| 		max(): number { | 		max(): number { | ||||||
| 			return this.$instance ? this.$instance.maxNoteTextLength : 1000; | 			return this.$instance ? this.$instance.maxNoteTextLength : 1000; | ||||||
| 		} | 		}, | ||||||
|  | 
 | ||||||
|  | 		withHashtags: defaultStore.makeGetterSetter('postFormWithHashtags'), | ||||||
|  | 		hashtags: defaultStore.makeGetterSetter('postFormHashtags'), | ||||||
| 	}, | 	}, | ||||||
| 
 | 
 | ||||||
| 	watch: { | 	watch: { | ||||||
|  | @ -303,6 +312,7 @@ export default defineComponent({ | ||||||
| 		// TODO: detach when unmount | 		// TODO: detach when unmount | ||||||
| 		new Autocomplete(this.$refs.text, this, { model: 'text' }); | 		new Autocomplete(this.$refs.text, this, { model: 'text' }); | ||||||
| 		new Autocomplete(this.$refs.cw, this, { model: 'cw' }); | 		new Autocomplete(this.$refs.cw, this, { model: 'cw' }); | ||||||
|  | 		new Autocomplete(this.$refs.hashtags, this, { model: 'hashtags' }); | ||||||
| 
 | 
 | ||||||
| 		this.$nextTick(() => { | 		this.$nextTick(() => { | ||||||
| 			// 書きかけの投稿を復元 | 			// 書きかけの投稿を復元 | ||||||
|  | @ -605,6 +615,11 @@ export default defineComponent({ | ||||||
| 				viaMobile: isMobile | 				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 | 			// plugin | ||||||
| 			if (notePostInterruptors.length > 0) { | 			if (notePostInterruptors.length > 0) { | ||||||
| 				for (const interruptor of notePostInterruptors) { | 				for (const interruptor of notePostInterruptors) { | ||||||
|  | @ -618,8 +633,8 @@ export default defineComponent({ | ||||||
| 				this.$nextTick(() => { | 				this.$nextTick(() => { | ||||||
| 					this.deleteDraft(); | 					this.deleteDraft(); | ||||||
| 					this.$emit('posted'); | 					this.$emit('posted'); | ||||||
| 					if (this.text && this.text != '') { | 					if (data.text && data.text != '') { | ||||||
| 						const hashtags = mfm.parse(this.text).filter(x => x.type === 'hashtag').map(x => x.props.hashtag); | 						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[]; | 						const history = JSON.parse(localStorage.getItem('hashtags') || '[]') as string[]; | ||||||
| 						localStorage.setItem('hashtags', JSON.stringify(unique(hashtags.concat(history)))); | 						localStorage.setItem('hashtags', JSON.stringify(unique(hashtags.concat(history)))); | ||||||
| 					} | 					} | ||||||
|  | @ -785,6 +800,7 @@ export default defineComponent({ | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		> .cw, | 		> .cw, | ||||||
|  | 		> .hashtags, | ||||||
| 		> .text { | 		> .text { | ||||||
| 			display: block; | 			display: block; | ||||||
| 			box-sizing: border-box; | 			box-sizing: border-box; | ||||||
|  | @ -813,6 +829,13 @@ export default defineComponent({ | ||||||
| 			border-bottom: solid 0.5px var(--divider); | 			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 { | 		> .text { | ||||||
| 			max-width: 100%; | 			max-width: 100%; | ||||||
| 			min-width: 100%; | 			min-width: 100%; | ||||||
|  | @ -872,6 +895,7 @@ export default defineComponent({ | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			> .cw, | 			> .cw, | ||||||
|  | 			> .hashtags, | ||||||
| 			> .text { | 			> .text { | ||||||
| 				padding: 0 16px; | 				padding: 0 16px; | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
|  | @ -198,6 +198,14 @@ export const defaultStore = markRaw(new Storage('base', { | ||||||
| 		where: 'device', | 		where: 'device', | ||||||
| 		default: false | 		default: false | ||||||
| 	}, | 	}, | ||||||
|  | 	postFormWithHashtags: { | ||||||
|  | 		where: 'device', | ||||||
|  | 		default: false | ||||||
|  | 	}, | ||||||
|  | 	postFormHashtags: { | ||||||
|  | 		where: 'device', | ||||||
|  | 		default: '' | ||||||
|  | 	}, | ||||||
| })); | })); | ||||||
| 
 | 
 | ||||||
| // TODO: 他のタブと永続化されたstateを同期
 | // TODO: 他のタブと永続化されたstateを同期
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue