mirror of
				https://codeberg.org/yeentown/barkey.git
				synced 2025-10-26 19:14:12 +00:00 
			
		
		
		
	feat(client): 投稿フォームのボタンの説明を表示するように (#6408)
* Add title attr with buttons on the post form * fix * tooltip * missing ; * remove title attr * fix bug * Update reactions-viewer.details.vue * help wip * ok! * i18n Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
This commit is contained in:
		
							parent
							
								
									f2964101d1
								
							
						
					
					
						commit
						111eb43fd9
					
				
					 13 changed files with 207 additions and 105 deletions
				
			
		|  | @ -45,6 +45,7 @@ loadMore: "もっと見る" | |||
| youGotNewFollower: "フォローされました" | ||||
| receiveFollowRequest: "フォローリクエストされました" | ||||
| followRequestAccepted: "フォローが承認されました" | ||||
| mention: "メンション" | ||||
| mentions: "あなた宛て" | ||||
| directNotes: "ダイレクト投稿" | ||||
| importAndExport: "インポートとエクスポート" | ||||
|  | @ -104,6 +105,7 @@ suspendConfirm: "凍結しますか?" | |||
| unsuspendConfirm: "解凍しますか?" | ||||
| selectList: "リストを選択" | ||||
| customEmojis: "カスタム絵文字" | ||||
| emoji: "絵文字" | ||||
| emojiName: "絵文字名" | ||||
| emojiUrl: "絵文字画像URL" | ||||
| addEmoji: "絵文字を追加" | ||||
|  | @ -510,6 +512,9 @@ serviceworkerInfo: "プッシュ通知を行うには有効する必要があり | |||
| deletedNote: "削除された投稿" | ||||
| invisibleNote: "非公開の投稿" | ||||
| enableInfiniteScroll: "自動でもっと見る" | ||||
| visibility: "公開範囲" | ||||
| poll: "アンケート" | ||||
| useCw: "内容を隠す" | ||||
| 
 | ||||
| _theme: | ||||
|   explore: "テーマを探す" | ||||
|  | @ -648,7 +653,6 @@ _cw: | |||
|   show: "もっと見る" | ||||
|   chars: "{count}文字" | ||||
|   files: "{count}ファイル" | ||||
|   poll: "アンケート" | ||||
| 
 | ||||
| _poll: | ||||
|   noOnlyOneChoice: "選択肢は最低2つ必要です" | ||||
|  | @ -1119,3 +1123,4 @@ _notification: | |||
|   youReceivedFollowRequest: "フォローリクエストが来ました" | ||||
|   yourFollowRequestAccepted: "フォローリクエストが承認されました" | ||||
|   youWereInvitedToGroup: "グループに招待されました" | ||||
| 
 | ||||
|  |  | |||
|  | @ -27,7 +27,7 @@ export default Vue.extend({ | |||
| 			return concat([ | ||||
| 				this.note.text ? [this.$t('_cw.chars', { count: length(this.note.text) })] : [], | ||||
| 				this.note.files && this.note.files.length !== 0 ? [this.$t('_cw.files', { count: this.note.files.length }) ] : [], | ||||
| 				this.note.poll != null ? [this.$t('_cw.poll')] : [] | ||||
| 				this.note.poll != null ? [this.$t('poll')] : [] | ||||
| 			] as string[][]).join(' / '); | ||||
| 		} | ||||
| 	}, | ||||
|  |  | |||
|  | @ -62,13 +62,13 @@ export default Vue.extend({ | |||
| 			} | ||||
| 		}, | ||||
| 		onMouseover() { | ||||
| 			if (isDeviceTouch()) return; | ||||
| 			if (isDeviceTouch) return; | ||||
| 			clearTimeout(this.showTimer); | ||||
| 			clearTimeout(this.hideTimer); | ||||
| 			this.showTimer = setTimeout(this.showPreview, 500); | ||||
| 		}, | ||||
| 		onMouseleave() { | ||||
| 			if (isDeviceTouch()) return; | ||||
| 			if (isDeviceTouch) return; | ||||
| 			clearTimeout(this.showTimer); | ||||
| 			clearTimeout(this.hideTimer); | ||||
| 			this.hideTimer = setTimeout(this.closePreview, 500); | ||||
|  |  | |||
|  | @ -9,13 +9,13 @@ | |||
| 		<button v-if="!fixed" class="cancel _button" @click="cancel"><fa :icon="faTimes"/></button> | ||||
| 		<div> | ||||
| 			<span class="text-count" :class="{ over: trimmedLength(text) > max }">{{ max - trimmedLength(text) }}</span> | ||||
| 			<button class="_button visibility" @click="setVisibility" ref="visibilityButton"> | ||||
| 			<button class="_button visibility" @click="setVisibility" ref="visibilityButton" v-tooltip="$t('visibility')"> | ||||
| 				<span v-if="visibility === 'public'"><fa :icon="faGlobe"/></span> | ||||
| 				<span v-if="visibility === 'home'"><fa :icon="faHome"/></span> | ||||
| 				<span v-if="visibility === 'followers'"><fa :icon="faUnlock"/></span> | ||||
| 				<span v-if="visibility === 'specified'"><fa :icon="faEnvelope"/></span> | ||||
| 			</button> | ||||
| 			<button class="_button localOnly" v-if="visibility !== 'specified'" @click="localOnly = !localOnly" :class="{ active: localOnly }"><fa :icon="faBiohazard"/></button> | ||||
| 			<button class="_button localOnly" v-if="visibility !== 'specified'" @click="localOnly = !localOnly" :class="{ active: localOnly }" v-tooltip="$t('_visibility.localOnly')"><fa :icon="faBiohazard"/></button> | ||||
| 			<button class="submit _buttonPrimary" :disabled="!canPost" @click="post">{{ submitText }}<fa :icon="reply ? faReply : renote ? faQuoteRight : faPaperPlane"/></button> | ||||
| 		</div> | ||||
| 	</header> | ||||
|  | @ -26,7 +26,7 @@ | |||
| 		<div v-if="visibility === 'specified'" class="to-specified"> | ||||
| 			<span style="margin-right: 8px;">{{ $t('recipient') }}</span> | ||||
| 			<div class="visibleUsers"> | ||||
| 				<span v-for="u in visibleUsers"> | ||||
| 				<span v-for="u in visibleUsers" :key="u.id"> | ||||
| 					<mk-acct :user="u"/> | ||||
| 					<button class="_button" @click="removeVisibleUser(u)"><fa :icon="faTimes"/></button> | ||||
| 				</span> | ||||
|  | @ -39,11 +39,11 @@ | |||
| 		<x-poll-editor v-if="poll" ref="poll" @destroyed="poll = false" @updated="onPollUpdate()"/> | ||||
| 		<x-uploader ref="uploader" @uploaded="attachMedia" @change="onChangeUploadings"/> | ||||
| 		<footer> | ||||
| 			<button class="_button" @click="chooseFileFrom"><fa :icon="faPhotoVideo"/></button> | ||||
| 			<button class="_button" @click="poll = !poll" :class="{ active: poll }"><fa :icon="faPollH"/></button> | ||||
| 			<button class="_button" @click="useCw = !useCw" :class="{ active: useCw }"><fa :icon="faEyeSlash"/></button> | ||||
| 			<button class="_button" @click="insertMention"><fa :icon="faAt"/></button> | ||||
| 			<button class="_button" @click="insertEmoji"><fa :icon="faLaughSquint"/></button> | ||||
| 			<button class="_button" @click="chooseFileFrom" v-tooltip="$t('attachFile')"><fa :icon="faPhotoVideo"/></button> | ||||
| 			<button class="_button" @click="poll = !poll" :class="{ active: poll }" v-tooltip="$t('poll')"><fa :icon="faPollH"/></button> | ||||
| 			<button class="_button" @click="useCw = !useCw" :class="{ active: useCw }" v-tooltip="$t('useCw')"><fa :icon="faEyeSlash"/></button> | ||||
| 			<button class="_button" @click="insertMention" v-tooltip="$t('mention')"><fa :icon="faAt"/></button> | ||||
| 			<button class="_button" @click="insertEmoji" v-tooltip="$t('emoji')"><fa :icon="faLaughSquint"/></button> | ||||
| 		</footer> | ||||
| 		<input ref="file" class="file _button" type="file" multiple="multiple" @change="onChangeFile"/> | ||||
| 	</div> | ||||
|  | @ -576,7 +576,7 @@ export default Vue.extend({ | |||
| 				insertTextAtCursor(this.$refs.text, emoji); | ||||
| 				vm.close(); | ||||
| 			}); | ||||
| 		} | ||||
| 		}, | ||||
| 	} | ||||
| }); | ||||
| </script> | ||||
|  |  | |||
|  | @ -1,27 +1,29 @@ | |||
| <template> | ||||
| <transition name="zoom-in-top"> | ||||
| 	<div class="buebdbiu" ref="popover" v-if="show"> | ||||
| 		<template v-if="users.length <= 10"> | ||||
| 			<b v-for="u in users" :key="u.id" style="margin-right: 12px;"> | ||||
| 				<mk-avatar :user="u" style="width: 24px; height: 24px; margin-right: 2px;"/> | ||||
| 				<mk-user-name :user="u" :nowrap="false" style="line-height: 24px;"/> | ||||
| 			</b> | ||||
| 		</template> | ||||
| 		<template v-if="10 < users.length"> | ||||
| 			<b v-for="u in users" :key="u.id" style="margin-right: 12px;"> | ||||
| 				<mk-avatar :user="u" style="width: 24px; height: 24px; margin-right: 2px;"/> | ||||
| 				<mk-user-name :user="u" :nowrap="false" style="line-height: 24px;"/> | ||||
| 			</b> | ||||
| 			<span slot="omitted">+{{ count - 10 }}</span> | ||||
| 		</template> | ||||
| 	</div> | ||||
| </transition> | ||||
| <mk-tooltip :source="source" ref="tooltip"> | ||||
| 	<template v-if="users.length <= 10"> | ||||
| 		<b v-for="u in users" :key="u.id" style="margin-right: 12px;"> | ||||
| 			<mk-avatar :user="u" style="width: 24px; height: 24px; margin-right: 2px;"/> | ||||
| 			<mk-user-name :user="u" :nowrap="false" style="line-height: 24px;"/> | ||||
| 		</b> | ||||
| 	</template> | ||||
| 	<template v-if="10 < users.length"> | ||||
| 		<b v-for="u in users" :key="u.id" style="margin-right: 12px;"> | ||||
| 			<mk-avatar :user="u" style="width: 24px; height: 24px; margin-right: 2px;"/> | ||||
| 			<mk-user-name :user="u" :nowrap="false" style="line-height: 24px;"/> | ||||
| 		</b> | ||||
| 		<span slot="omitted">+{{ count - 10 }}</span> | ||||
| 	</template> | ||||
| </mk-tooltip> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| import MkTooltip from './ui/tooltip.vue'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	components: { | ||||
| 		MkTooltip | ||||
| 	}, | ||||
| 	props: { | ||||
| 		reaction: { | ||||
| 			type: String, | ||||
|  | @ -39,77 +41,11 @@ export default Vue.extend({ | |||
| 			required: true, | ||||
| 		} | ||||
| 	}, | ||||
| 	data() { | ||||
| 		return { | ||||
| 			show: false | ||||
| 		}; | ||||
| 	}, | ||||
| 	mounted() { | ||||
| 		this.show = true; | ||||
| 
 | ||||
| 		this.$nextTick(() => { | ||||
| 			const popover = this.$refs.popover as any; | ||||
| 
 | ||||
| 			if (this.source == null) { | ||||
| 				this.destroyDom(); | ||||
| 				return; | ||||
| 			} | ||||
| 			const rect = this.source.getBoundingClientRect(); | ||||
| 
 | ||||
| 			const x = rect.left + window.pageXOffset + (this.source.offsetWidth / 2); | ||||
| 			const y = rect.top + window.pageYOffset + this.source.offsetHeight; | ||||
| 			popover.style.left = (x - 28) + 'px'; | ||||
| 			popover.style.top = (y + 16) + 'px'; | ||||
| 		}); | ||||
| 	} | ||||
| 	methods: { | ||||
| 		close() { | ||||
| 			this.show = false; | ||||
| 			setTimeout(this.destroyDom, 300); | ||||
| 			this.$refs.tooltip.close(); | ||||
| 		} | ||||
| 	} | ||||
| }) | ||||
| </script> | ||||
| 
 | ||||
| <style lang="scss" scoped> | ||||
| .buebdbiu { | ||||
| 	z-index: 10000; | ||||
| 	display: block; | ||||
| 	position: absolute; | ||||
| 	max-width: 240px; | ||||
| 	font-size: 0.8em; | ||||
| 	padding: 6px 8px; | ||||
| 	background: var(--panel); | ||||
| 	text-align: center; | ||||
| 	border-radius: 4px; | ||||
| 	box-shadow: 0 2px 8px rgba(0,0,0,0.25); | ||||
| 	pointer-events: none; | ||||
| 	transform-origin: center -16px; | ||||
| 
 | ||||
| 	&:before { | ||||
| 		content: ""; | ||||
| 		pointer-events: none; | ||||
| 		display: block; | ||||
| 		position: absolute; | ||||
| 		top: -28px; | ||||
| 		left: 12px; | ||||
| 		border-top: solid 14px transparent; | ||||
| 		border-right: solid 14px transparent; | ||||
| 		border-bottom: solid 14px rgba(0,0,0,0.1); | ||||
| 		border-left: solid 14px transparent; | ||||
| 	} | ||||
| 
 | ||||
| 	&:after { | ||||
| 		content: ""; | ||||
| 		pointer-events: none; | ||||
| 		display: block; | ||||
| 		position: absolute; | ||||
| 		top: -27px; | ||||
| 		left: 12px; | ||||
| 		border-top: solid 14px transparent; | ||||
| 		border-right: solid 14px transparent; | ||||
| 		border-bottom: solid 14px var(--panel); | ||||
| 		border-left: solid 14px transparent; | ||||
| 	} | ||||
| } | ||||
| </style> | ||||
|  |  | |||
|  | @ -4,8 +4,10 @@ | |||
| 	:class="{ reacted: note.myReaction == reaction, canToggle }" | ||||
| 	@click="toggleReaction(reaction)" | ||||
| 	v-if="count > 0" | ||||
| 	@touchstart="onMouseover" | ||||
| 	@mouseover="onMouseover" | ||||
| 	@mouseleave="onMouseleave" | ||||
| 	@touchend="onMouseleave" | ||||
| 	ref="reaction" | ||||
| 	v-particle | ||||
| > | ||||
|  | @ -90,16 +92,17 @@ export default Vue.extend({ | |||
| 			} | ||||
| 		}, | ||||
| 		onMouseover() { | ||||
| 			if (this.isHovering) return; | ||||
| 			this.isHovering = true; | ||||
| 			this.detailsTimeoutId = setTimeout(this.openDetails, 300); | ||||
| 		}, | ||||
| 		onMouseleave() { | ||||
| 			if (!this.isHovering) return; | ||||
| 			this.isHovering = false; | ||||
| 			clearTimeout(this.detailsTimeoutId); | ||||
| 			this.closeDetails(); | ||||
| 		}, | ||||
| 		openDetails() { | ||||
| 			if (this.$root.isMobile) return; | ||||
| 			this.$root.api('notes/reactions', { | ||||
| 				noteId: this.note.id, | ||||
| 				type: this.reaction, | ||||
|  |  | |||
							
								
								
									
										96
									
								
								src/client/components/ui/tooltip.vue
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								src/client/components/ui/tooltip.vue
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,96 @@ | |||
| <template> | ||||
| <transition name="zoom-in-top" appear> | ||||
| 	<div class="buebdbiu" v-if="show"> | ||||
| 		<slot>{{ text }}</slot> | ||||
| 	</div> | ||||
| </transition> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import Vue from 'vue'; | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
| 	props: { | ||||
| 		source: { | ||||
| 			required: true, | ||||
| 		}, | ||||
| 		text: { | ||||
| 			type: String, | ||||
| 			required: false | ||||
| 		} | ||||
| 	}, | ||||
| 
 | ||||
| 	data() { | ||||
| 		return { | ||||
| 			show: false | ||||
| 		}; | ||||
| 	}, | ||||
| 
 | ||||
| 	mounted() { | ||||
| 		this.show = true; | ||||
| 
 | ||||
| 		this.$nextTick(() => { | ||||
| 			if (this.source == null) { | ||||
| 				this.destroyDom(); | ||||
| 				return; | ||||
| 			} | ||||
| 			const rect = this.source.getBoundingClientRect(); | ||||
| 
 | ||||
| 			const x = rect.left + window.pageXOffset + (this.source.offsetWidth / 2); | ||||
| 			const y = rect.top + window.pageYOffset + this.source.offsetHeight; | ||||
| 			this.$el.style.left = (x - 28) + 'px'; | ||||
| 			this.$el.style.top = (y + 16) + 'px'; | ||||
| 		}); | ||||
| 	}, | ||||
| 
 | ||||
| 	methods: { | ||||
| 		close() { | ||||
| 			this.show = false; | ||||
| 			setTimeout(this.destroyDom, 300); | ||||
| 		} | ||||
| 	} | ||||
| }) | ||||
| </script> | ||||
| 
 | ||||
| <style lang="scss" scoped> | ||||
| .buebdbiu { | ||||
| 	z-index: 11000; | ||||
| 	display: block; | ||||
| 	position: absolute; | ||||
| 	max-width: 240px; | ||||
| 	font-size: 0.8em; | ||||
| 	padding: 6px 8px; | ||||
| 	background: var(--panel); | ||||
| 	text-align: center; | ||||
| 	border-radius: 4px; | ||||
| 	box-shadow: 0 2px 8px rgba(0,0,0,0.25); | ||||
| 	pointer-events: none; | ||||
| 	transform-origin: center -16px; | ||||
| 
 | ||||
| 	&:before { | ||||
| 		content: ""; | ||||
| 		pointer-events: none; | ||||
| 		display: block; | ||||
| 		position: absolute; | ||||
| 		top: -28px; | ||||
| 		left: 12px; | ||||
| 		border-top: solid 14px transparent; | ||||
| 		border-right: solid 14px transparent; | ||||
| 		border-bottom: solid 14px rgba(0,0,0,0.1); | ||||
| 		border-left: solid 14px transparent; | ||||
| 	} | ||||
| 
 | ||||
| 	&:after { | ||||
| 		content: ""; | ||||
| 		pointer-events: none; | ||||
| 		display: block; | ||||
| 		position: absolute; | ||||
| 		top: -27px; | ||||
| 		left: 12px; | ||||
| 		border-top: solid 14px transparent; | ||||
| 		border-right: solid 14px transparent; | ||||
| 		border-bottom: solid 14px var(--panel); | ||||
| 		border-left: solid 14px transparent; | ||||
| 	} | ||||
| } | ||||
| </style> | ||||
|  | @ -93,13 +93,13 @@ export default Vue.extend({ | |||
| 			} | ||||
| 		}, | ||||
| 		onMouseover() { | ||||
| 			if (isDeviceTouch()) return; | ||||
| 			if (isDeviceTouch) return; | ||||
| 			clearTimeout(this.showTimer); | ||||
| 			clearTimeout(this.hideTimer); | ||||
| 			this.showTimer = setTimeout(this.showPreview, 500); | ||||
| 		}, | ||||
| 		onMouseleave() { | ||||
| 			if (isDeviceTouch()) return; | ||||
| 			if (isDeviceTouch) return; | ||||
| 			clearTimeout(this.showTimer); | ||||
| 			clearTimeout(this.hideTimer); | ||||
| 			this.hideTimer = setTimeout(this.closePreview, 500); | ||||
|  |  | |||
|  | @ -4,9 +4,11 @@ import userPreview from './user-preview'; | |||
| import autocomplete from './autocomplete'; | ||||
| import size from './size'; | ||||
| import particle from './particle'; | ||||
| import tooltip from './tooltip'; | ||||
| 
 | ||||
| Vue.directive('autocomplete', autocomplete); | ||||
| Vue.directive('userPreview', userPreview); | ||||
| Vue.directive('user-preview', userPreview); | ||||
| Vue.directive('size', size); | ||||
| Vue.directive('particle', particle); | ||||
| Vue.directive('tooltip', tooltip); | ||||
|  |  | |||
							
								
								
									
										62
									
								
								src/client/directives/tooltip.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								src/client/directives/tooltip.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,62 @@ | |||
| import MkTooltip from '../components/ui/tooltip.vue'; | ||||
| import { isDeviceTouch } from '../scripts/is-device-touch'; | ||||
| 
 | ||||
| const start = isDeviceTouch ? 'touchstart' : 'mouseover'; | ||||
| const end = isDeviceTouch ? 'touchend' : 'mouseleave'; | ||||
| 
 | ||||
| export default { | ||||
| 	bind(el: HTMLElement, binding, vn) { | ||||
| 		const self = (el as any)._tooltipDirective_ = {} as any; | ||||
| 
 | ||||
| 		self.text = binding.value as string; | ||||
| 		self.tag = null; | ||||
| 		self.showTimer = null; | ||||
| 		self.hideTimer = null; | ||||
| 		self.checkTimer = null; | ||||
| 
 | ||||
| 		self.close = () => { | ||||
| 			if (self.tag) { | ||||
| 				clearInterval(self.checkTimer); | ||||
| 				self.tag.close(); | ||||
| 				self.tag = null; | ||||
| 			} | ||||
| 		}; | ||||
| 
 | ||||
| 		const show = e => { | ||||
| 			if (!document.body.contains(el)) return; | ||||
| 			if (self.tag) return; | ||||
| 
 | ||||
| 			self.tag = new MkTooltip({ | ||||
| 				parent: vn.context, | ||||
| 				propsData: { | ||||
| 					text: self.text, | ||||
| 					source: el | ||||
| 				} | ||||
| 			}).$mount(); | ||||
| 
 | ||||
| 			document.body.appendChild(self.tag.$el); | ||||
| 		}; | ||||
| 
 | ||||
| 		el.addEventListener(start, () => { | ||||
| 			clearTimeout(self.showTimer); | ||||
| 			clearTimeout(self.hideTimer); | ||||
| 			self.showTimer = setTimeout(show, 300); | ||||
| 		}); | ||||
| 
 | ||||
| 		el.addEventListener(end, () => { | ||||
| 			clearTimeout(self.showTimer); | ||||
| 			clearTimeout(self.hideTimer); | ||||
| 			self.hideTimer = setTimeout(self.close, 300); | ||||
| 		}); | ||||
| 
 | ||||
| 		el.addEventListener('click', () => { | ||||
| 			clearTimeout(self.showTimer); | ||||
| 			self.close(); | ||||
| 		}); | ||||
| 	}, | ||||
| 
 | ||||
| 	unbind(el, binding, vn) { | ||||
| 		const self = el._tooltipDirective_; | ||||
| 		clearInterval(self.checkTimer); | ||||
| 	}, | ||||
| }; | ||||
|  | @ -5,7 +5,7 @@ import { clientDb, get, bulkGet } from '../db'; | |||
| const getTranslation = (text: string): Promise<string> => get(text, clientDb.i18n); | ||||
| 
 | ||||
| export default async function(type, data): Promise<[string, NotificationOptions]> { | ||||
| 	const contexts = ['deletedNote', 'invisibleNote', 'withNFiles', '_cw.poll']; | ||||
| 	const contexts = ['deletedNote', 'invisibleNote', 'withNFiles', 'poll']; | ||||
| 	const locale = Object.fromEntries(await bulkGet(contexts, clientDb.i18n) as [string, string][]); | ||||
| 
 | ||||
| 	switch (type) { | ||||
|  |  | |||
|  | @ -1,3 +1 @@ | |||
| export function isDeviceTouch(): boolean { | ||||
| 	return 'maxTouchPoints' in navigator && navigator.maxTouchPoints > 0; | ||||
| } | ||||
| export const isDeviceTouch = 'maxTouchPoints' in navigator && navigator.maxTouchPoints > 0; | ||||
|  |  | |||
|  | @ -27,7 +27,7 @@ const summarize = (note: any, locale: any): string => { | |||
| 
 | ||||
| 	// 投票が添付されているとき
 | ||||
| 	if (note.poll) { | ||||
| 		summary += ` (${locale._cw?.poll || locale['_cw.poll']})`; | ||||
| 		summary += ` (${locale['poll']})`; | ||||
| 	} | ||||
| 
 | ||||
| 	// 返信のとき
 | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue