Merge branch 'develop'
This commit is contained in:
		
						commit
						37dc1c9a82
					
				
					 282 changed files with 3796 additions and 3553 deletions
				
			
		|  | @ -138,7 +138,7 @@ flagAsBotDescription: "このアカウントがプログラムによって運用 | |||
| flagAsCat: "Catとして設定" | ||||
| flagAsCatDescription: "このアカウントが猫であることを示す場合は、このフラグをオンにします。" | ||||
| autoAcceptFollowed: "フォロー中ユーザーからのフォロリクを自動承認" | ||||
| addAcount: "アカウント追加" | ||||
| addAccount: "アカウントを追加" | ||||
| loginFailed: "ログインに失敗しました" | ||||
| showOnRemote: "リモートで表示" | ||||
| general: "全般" | ||||
|  | @ -183,7 +183,7 @@ clearQueueConfirmTitle: "キューをクリアしますか?" | |||
| clearQueueConfirmText: "未配達の投稿は配送されなくなります。通常この操作を行う必要はありません。" | ||||
| clearCachedFiles: "キャッシュをクリア" | ||||
| clearCachedFilesConfirm: "キャッシュされたリモートファイルをすべて削除しますか?" | ||||
| blockedInstances: "インスタンスブロック" | ||||
| blockedInstances: "ブロックしたインスタンス" | ||||
| blockedInstancesDescription: "ブロックしたいインスタンスのホストを改行で区切って設定します。ブロックされたインスタンスは、このインスタンスとやり取りできなくなります。" | ||||
| muteAndBlock: "ミュートとブロック" | ||||
| mutedUsers: "ミュートしたユーザー" | ||||
|  | @ -349,7 +349,6 @@ antennaExcludeKeywords: "除外キーワード" | |||
| antennaKeywordsDescription: "スペースで区切るとAND指定になり、改行で区切るとOR指定になります" | ||||
| notifyAntenna: "新しいノートを通知する" | ||||
| withFileAntenna: "ファイルが添付されたノートのみ" | ||||
| serviceworker: "ServiceWorker" | ||||
| enableServiceworker: "ServiceWorkerを有効にする" | ||||
| antennaUsersDescription: "ユーザー名を改行で区切って指定します" | ||||
| caseSensitive: "大文字小文字を区別する" | ||||
|  | @ -453,7 +452,7 @@ category: "カテゴリ" | |||
| tags: "タグ" | ||||
| docSource: "このドキュメントのソース" | ||||
| createAccount: "アカウントを作成" | ||||
| existingAcount: "既存のアカウント" | ||||
| existingAccount: "既存のアカウント" | ||||
| regenerate: "再生成" | ||||
| fontSize: "フォントサイズ" | ||||
| noFollowRequests: "フォロー申請はありません" | ||||
|  | @ -568,7 +567,7 @@ pluginTokenRequestedDescription: "このプラグインはここで設定した | |||
| notificationType: "通知の種類" | ||||
| edit: "編集" | ||||
| useStarForReactionFallback: "リアクション絵文字が不明な場合、代わりに★を使う" | ||||
| emailConfig: "メールサーバー設定" | ||||
| emailServer: "メールサーバー" | ||||
| enableEmail: "メール配信機能を有効化する" | ||||
| emailConfigInfo: "メールアドレスの確認やパスワードリセットの際に使います" | ||||
| email: "メール" | ||||
|  | @ -728,6 +727,20 @@ hideOnlineStatusDescription: "オンライン状態を隠すと、検索など | |||
| online: "オンライン" | ||||
| active: "アクティブ" | ||||
| offline: "オフライン" | ||||
| notRecommended: "非推奨" | ||||
| botProtection: "Bot防御" | ||||
| instanceBlocking: "インスタンスブロック" | ||||
| selectAccount: "アカウントを選択" | ||||
| enabled: "有効" | ||||
| disabled: "無効" | ||||
| quickAction: "クイックアクション" | ||||
| user: "ユーザー" | ||||
| administration: "管理" | ||||
| accounts: "アカウント" | ||||
| switch: "切り替え" | ||||
| noMaintainerInformationWarning: "管理者情報が設定されていません。" | ||||
| noBotProtectionWarning: "Bot防御が設定されていません。" | ||||
| configure: "設定する" | ||||
| 
 | ||||
| _email: | ||||
|   _follow: | ||||
|  |  | |||
							
								
								
									
										10
									
								
								package.json
									
										
									
									
									
								
							
							
						
						
									
										10
									
								
								package.json
									
										
									
									
									
								
							|  | @ -1,7 +1,7 @@ | |||
| { | ||||
| 	"name": "misskey", | ||||
| 	"author": "syuilo <syuilotan@yahoo.co.jp>", | ||||
| 	"version": "12.77.1", | ||||
| 	"version": "12.78.0", | ||||
| 	"codename": "indigo", | ||||
| 	"repository": { | ||||
| 		"type": "git", | ||||
|  | @ -39,11 +39,6 @@ | |||
| 	"dependencies": { | ||||
| 		"@babel/plugin-transform-runtime": "7.13.15", | ||||
| 		"@elastic/elasticsearch": "7.11.0", | ||||
| 		"@fortawesome/fontawesome-svg-core": "1.2.35", | ||||
| 		"@fortawesome/free-brands-svg-icons": "5.15.3", | ||||
| 		"@fortawesome/free-regular-svg-icons": "5.15.3", | ||||
| 		"@fortawesome/free-solid-svg-icons": "5.15.3", | ||||
| 		"@fortawesome/vue-fontawesome": "3.0.0-3", | ||||
| 		"@koa/cors": "3.1.0", | ||||
| 		"@koa/multer": "3.0.0", | ||||
| 		"@koa/router": "9.0.1", | ||||
|  | @ -140,7 +135,6 @@ | |||
| 		"eslint-plugin-vue": "7.9.0", | ||||
| 		"eventemitter3": "4.0.7", | ||||
| 		"feed": "4.2.2", | ||||
| 		"fibers": "5.0.0", | ||||
| 		"file-type": "16.3.0", | ||||
| 		"fluent-ffmpeg": "2.1.2", | ||||
| 		"glob": "7.1.6", | ||||
|  | @ -181,7 +175,7 @@ | |||
| 		"markdown-it": "12.0.5", | ||||
| 		"markdown-it-anchor": "7.1.0", | ||||
| 		"matter-js": "0.17.1", | ||||
| 		"mfm-js": "0.16.0", | ||||
| 		"mfm-js": "0.16.2", | ||||
| 		"mocha": "8.3.2", | ||||
| 		"moji": "0.5.1", | ||||
| 		"ms": "2.1.3", | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| <template> | ||||
| <XWindow ref="window" :initial-width="400" :initial-height="500" :can-resize="true" @closed="$emit('closed')"> | ||||
| 	<template #header> | ||||
| 		<Fa :icon="faExclamationCircle" style="margin-right: 0.5em;"/> | ||||
| 		<i class="fas fa-exclamation-circle" style="margin-right: 0.5em;"></i> | ||||
| 		<I18n :src="$ts.reportAbuseOf" tag="span"> | ||||
| 			<template #name> | ||||
| 				<b><MkAcct :user="user"/></b> | ||||
|  | @ -24,7 +24,6 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent, markRaw } from 'vue'; | ||||
| import { faExclamationCircle } from '@fortawesome/free-solid-svg-icons'; | ||||
| import XWindow from '@client/components/ui/window.vue'; | ||||
| import MkTextarea from '@client/components/ui/textarea.vue'; | ||||
| import MkButton from '@client/components/ui/button.vue'; | ||||
|  | @ -53,7 +52,6 @@ export default defineComponent({ | |||
| 	data() { | ||||
| 		return { | ||||
| 			comment: this.initialComment || '', | ||||
| 			faExclamationCircle, | ||||
| 		}; | ||||
| 	}, | ||||
| 
 | ||||
|  |  | |||
|  | @ -18,7 +18,7 @@ type Captcha = { | |||
| 	getResponse(id: string): string; | ||||
| }; | ||||
| 
 | ||||
| type CaptchaProvider = 'hcaptcha' | 'grecaptcha'; | ||||
| type CaptchaProvider = 'hcaptcha' | 'recaptcha'; | ||||
| 
 | ||||
| type CaptchaContainer = { | ||||
| 	readonly [_ in CaptchaProvider]?: Captcha; | ||||
|  | @ -57,7 +57,7 @@ export default defineComponent({ | |||
| 		src() { | ||||
| 			const endpoint = ({ | ||||
| 				hcaptcha: 'https://hcaptcha.com/1', | ||||
| 				grecaptcha: 'https://www.recaptcha.net/recaptcha', | ||||
| 				recaptcha: 'https://www.recaptcha.net/recaptcha', | ||||
| 			} as Record<PropertyKey, unknown>)[this.provider]; | ||||
| 
 | ||||
| 			return `${typeof endpoint == 'string' ? endpoint : 'about:invalid'}/api.js?render=explicit`; | ||||
|  |  | |||
|  | @ -6,21 +6,20 @@ | |||
| > | ||||
| 	<template v-if="!wait"> | ||||
| 		<template v-if="isFollowing"> | ||||
| 			<span v-if="full">{{ $ts.unfollow }}</span><Fa :icon="faMinus"/> | ||||
| 			<span v-if="full">{{ $ts.unfollow }}</span><i class="fas fa-minus"></i> | ||||
| 		</template> | ||||
| 		<template v-else> | ||||
| 			<span v-if="full">{{ $ts.follow }}</span><Fa :icon="faPlus"/> | ||||
| 			<span v-if="full">{{ $ts.follow }}</span><i class="fas fa-plus"></i> | ||||
| 		</template> | ||||
| 	</template> | ||||
| 	<template v-else> | ||||
| 		<span v-if="full">{{ $ts.processing }}</span><Fa :icon="faSpinner" pulse fixed-width/> | ||||
| 		<span v-if="full">{{ $ts.processing }}</span><i class="fas fa-spinner fa-pulse fa-fw"></i> | ||||
| 	</template> | ||||
| </button> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { faSpinner, faPlus, faMinus, } from '@fortawesome/free-solid-svg-icons'; | ||||
| import * as os from '@client/os'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
|  | @ -40,7 +39,6 @@ export default defineComponent({ | |||
| 		return { | ||||
| 			isFollowing: this.channel.isFollowing, | ||||
| 			wait: false, | ||||
| 			faSpinner, faPlus, faMinus, | ||||
| 		}; | ||||
| 	}, | ||||
| 
 | ||||
|  |  | |||
|  | @ -2,10 +2,10 @@ | |||
| <MkA :to="`/channels/${channel.id}`" class="eftoefju _panel" tabindex="-1"> | ||||
| 	<div class="banner" :style="bannerStyle"> | ||||
| 		<div class="fade"></div> | ||||
| 		<div class="name"><Fa :icon="faSatelliteDish"/> {{ channel.name }}</div> | ||||
| 		<div class="name"><i class="fas fa-satellite-dish"></i> {{ channel.name }}</div> | ||||
| 		<div class="status"> | ||||
| 			<div> | ||||
| 				<Fa :icon="faUsers" fixed-width/> | ||||
| 				<i class="fas fa-users fa-fw"></i> | ||||
| 				<I18n :src="$ts._channel.usersCount" tag="span" style="margin-left: 4px;"> | ||||
| 					<template #n> | ||||
| 						<b>{{ channel.usersCount }}</b> | ||||
|  | @ -13,7 +13,7 @@ | |||
| 				</I18n> | ||||
| 			</div> | ||||
| 			<div> | ||||
| 				<Fa :icon="faPencilAlt" fixed-width/> | ||||
| 				<i class="fas fa-pencil-alt fa-fw"></i> | ||||
| 				<I18n :src="$ts._channel.notesCount" tag="span" style="margin-left: 4px;"> | ||||
| 					<template #n> | ||||
| 						<b>{{ channel.notesCount }}</b> | ||||
|  | @ -35,7 +35,6 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { faSatelliteDish, faUsers, faPencilAlt } from '@fortawesome/free-solid-svg-icons'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	props: { | ||||
|  | @ -57,7 +56,6 @@ export default defineComponent({ | |||
| 
 | ||||
| 	data() { | ||||
| 		return { | ||||
| 			faSatelliteDish, faUsers, faPencilAlt, | ||||
| 		}; | ||||
| 	}, | ||||
| }); | ||||
|  |  | |||
|  | @ -1,7 +1,5 @@ | |||
| <script lang="ts"> | ||||
| import { defineComponent, h, TransitionGroup } from 'vue'; | ||||
| import { faAngleUp, faAngleDown } from '@fortawesome/free-solid-svg-icons'; | ||||
| import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	props: { | ||||
|  | @ -73,17 +71,15 @@ export default defineComponent({ | |||
| 					class: 'date' | ||||
| 				}, [ | ||||
| 					h('span', [ | ||||
| 						h(FontAwesomeIcon, { | ||||
| 							class: 'icon', | ||||
| 							icon: faAngleUp, | ||||
| 						h('i', { | ||||
| 							class: 'fas fa-angle-up icon', | ||||
| 						}), | ||||
| 						this.getDateText(item.createdAt) | ||||
| 					]), | ||||
| 					h('span', [ | ||||
| 						this.getDateText(this.items[i + 1].createdAt), | ||||
| 						h(FontAwesomeIcon, { | ||||
| 							class: 'icon', | ||||
| 							icon: faAngleDown, | ||||
| 						h('i', { | ||||
| 							class: 'fas fa-angle-down icon', | ||||
| 						}) | ||||
| 					]) | ||||
| 				])); | ||||
|  |  | |||
|  | @ -2,15 +2,15 @@ | |||
| <MkModal ref="modal" @click="done(true)" @closed="$emit('closed')"> | ||||
| 	<div class="mk-dialog"> | ||||
| 		<div class="icon" v-if="icon"> | ||||
| 			<Fa :icon="icon"/> | ||||
| 			<i :class="icon"></i> | ||||
| 		</div> | ||||
| 		<div class="icon" v-else-if="!input && !select" :class="type"> | ||||
| 			<Fa :icon="faCheck" v-if="type === 'success'"/> | ||||
| 			<Fa :icon="faTimesCircle" v-if="type === 'error'"/> | ||||
| 			<Fa :icon="faExclamationTriangle" v-if="type === 'warning'"/> | ||||
| 			<Fa :icon="faInfoCircle" v-if="type === 'info'"/> | ||||
| 			<Fa :icon="faQuestionCircle" v-if="type === 'question'"/> | ||||
| 			<Fa :icon="faSpinner" pulse v-if="type === 'waiting'"/> | ||||
| 			<i v-if="type === 'success'" class="fas fa-check"></i> | ||||
| 			<i v-else-if="type === 'error'" class="fas fa-times-circle"></i> | ||||
| 			<i v-else-if="type === 'warning'" class="fas fa-exclamation-triangle"></i> | ||||
| 			<i v-else-if="type === 'info'" class="fas fa-info-circle"></i> | ||||
| 			<i v-else-if="type === 'question'" class="fas fa-question-circle"></i> | ||||
| 			<i v-else-if="type === 'waiting'" class="fas fa-spinner fa-pulse"></i> | ||||
| 		</div> | ||||
| 		<header v-if="title"><Mfm :text="title"/></header> | ||||
| 		<div class="body" v-if="text"><Mfm :text="text"/></div> | ||||
|  | @ -38,8 +38,6 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { faSpinner, faInfoCircle, faExclamationTriangle, faCheck } from '@fortawesome/free-solid-svg-icons'; | ||||
| import { faTimesCircle, faQuestionCircle } from '@fortawesome/free-regular-svg-icons'; | ||||
| import MkModal from '@client/components/ui/modal.vue'; | ||||
| import MkButton from '@client/components/ui/button.vue'; | ||||
| import MkInput from '@client/components/ui/input.vue'; | ||||
|  | @ -99,7 +97,6 @@ export default defineComponent({ | |||
| 		return { | ||||
| 			inputValue: this.input && this.input.default ? this.input.default : null, | ||||
| 			selectedValue: this.select ? this.select.default ? this.select.default : this.select.items ? this.select.items[0].value : this.select.groupedItems[0].items[0].value : null, | ||||
| 			faTimesCircle, faQuestionCircle, faSpinner, faInfoCircle, faExclamationTriangle, faCheck | ||||
| 		}; | ||||
| 	}, | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,31 +1,21 @@ | |||
| <template> | ||||
| <div class="zdjebgpv" ref="thumbnail"> | ||||
| 	<ImgWithBlurhash v-if="isThumbnailAvailable" :hash="file.blurhash" :src="file.thumbnailUrl" :alt="file.name" :title="file.name" :style="`object-fit: ${ fit }`"/> | ||||
| 	<Fa :icon="faFileImage" class="icon" v-else-if="is === 'image'"/> | ||||
| 	<Fa :icon="faFileVideo" class="icon" v-else-if="is === 'video'"/> | ||||
| 	<Fa :icon="faMusic" class="icon" v-else-if="is === 'audio' || is === 'midi'"/> | ||||
| 	<Fa :icon="faFileCsv" class="icon" v-else-if="is === 'csv'"/> | ||||
| 	<Fa :icon="faFilePdf" class="icon" v-else-if="is === 'pdf'"/> | ||||
| 	<Fa :icon="faFileAlt" class="icon" v-else-if="is === 'textfile'"/> | ||||
| 	<Fa :icon="faFileArchive" class="icon" v-else-if="is === 'archive'"/> | ||||
| 	<Fa :icon="faFile" class="icon" v-else/> | ||||
| 	<Fa :icon="faFilm" class="icon-sub" v-if="isThumbnailAvailable && is === 'video'"/> | ||||
| 	<i v-else-if="is === 'image'" class="fas fa-file-image icon"></i> | ||||
| 	<i v-else-if="is === 'video'" class="fas fa-file-video icon"></i> | ||||
| 	<i v-else-if="is === 'audio' || is === 'midi'" class="fas fa-music icon"></i> | ||||
| 	<i v-else-if="is === 'csv'" class="fas fa-file-csv icon"></i> | ||||
| 	<i v-else-if="is === 'pdf'" class="fas fa-file-pdf icon"></i> | ||||
| 	<i v-else-if="is === 'textfile'" class="fas fa-file-alt icon"></i> | ||||
| 	<i v-else-if="is === 'archive'" class="fas fa-file-archive icon"></i> | ||||
| 	<i v-else class="fas fa-file icon"></i> | ||||
| 
 | ||||
| 	<i v-if="isThumbnailAvailable && is === 'video'" class="fas fa-film icon-sub"></i> | ||||
| </div> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { | ||||
| 	faFile, | ||||
| 	faFileAlt, | ||||
| 	faFileImage, | ||||
| 	faMusic, | ||||
| 	faFileVideo, | ||||
| 	faFileCsv, | ||||
| 	faFilePdf, | ||||
| 	faFileArchive, | ||||
| 	faFilm | ||||
| 	} from '@fortawesome/free-solid-svg-icons'; | ||||
| import ImgWithBlurhash from '@client/components/img-with-blurhash.vue'; | ||||
| import { ColdDeviceStorage } from '@client/store'; | ||||
| 
 | ||||
|  | @ -49,15 +39,6 @@ export default defineComponent({ | |||
| 			isContextmenuShowing: false, | ||||
| 			isDragging: false, | ||||
| 
 | ||||
| 			faFile, | ||||
| 			faFileAlt, | ||||
| 			faFileImage, | ||||
| 			faMusic, | ||||
| 			faFileVideo, | ||||
| 			faFileCsv, | ||||
| 			faFilePdf, | ||||
| 			faFileArchive, | ||||
| 			faFilm | ||||
| 		}; | ||||
| 	}, | ||||
| 	computed: { | ||||
|  |  | |||
|  | @ -32,8 +32,6 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { faEye, faEyeSlash } from '@fortawesome/free-regular-svg-icons'; | ||||
| import { faDownload, faLink, faICursor, faTrashAlt } from '@fortawesome/free-solid-svg-icons'; | ||||
| import copyToClipboard from '@client/scripts/copy-to-clipboard'; | ||||
| import MkDriveFileThumbnail from './drive-file-thumbnail.vue'; | ||||
| import bytes from '@client/filters/bytes'; | ||||
|  | @ -87,22 +85,22 @@ export default defineComponent({ | |||
| 				action: this.rename | ||||
| 			}, { | ||||
| 				text: this.file.isSensitive ? this.$ts.unmarkAsSensitive : this.$ts.markAsSensitive, | ||||
| 				icon: this.file.isSensitive ? faEye : faEyeSlash, | ||||
| 				icon: this.file.isSensitive ? 'fas fa-eye' : 'fas fa-eye-slash', | ||||
| 				action: this.toggleSensitive | ||||
| 			}, null, { | ||||
| 				text: this.$ts.copyUrl, | ||||
| 				icon: faLink, | ||||
| 				icon: 'fas fa-link', | ||||
| 				action: this.copyUrl | ||||
| 			}, { | ||||
| 				type: 'a', | ||||
| 				href: this.file.url, | ||||
| 				target: '_blank', | ||||
| 				text: this.$ts.download, | ||||
| 				icon: faDownload, | ||||
| 				icon: 'fas fa-download', | ||||
| 				download: this.file.name | ||||
| 			}, null, { | ||||
| 				text: this.$ts.delete, | ||||
| 				icon: faTrashAlt, | ||||
| 				icon: 'fas fa-trash-alt', | ||||
| 				danger: true, | ||||
| 				action: this.deleteFile | ||||
| 			}]; | ||||
|  |  | |||
|  | @ -15,8 +15,8 @@ | |||
| 	:title="title" | ||||
| > | ||||
| 	<p class="name"> | ||||
| 		<template v-if="hover"><Fa :icon="faFolderOpen" fixed-width/></template> | ||||
| 		<template v-if="!hover"><Fa :icon="faFolder" fixed-width/></template> | ||||
| 		<template v-if="hover"><i class="fas fa-folder-open fa-fw"></i></template> | ||||
| 		<template v-if="!hover"><i class="fas fa-folder fa-fw"></i></template> | ||||
| 		{{ folder.name }} | ||||
| 	</p> | ||||
| 	<p class="upload" v-if="$store.state.uploadFolder == folder.id"> | ||||
|  | @ -28,9 +28,7 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { faFolder, faFolderOpen, faTrashAlt, faWindowRestore } from '@fortawesome/free-regular-svg-icons'; | ||||
| import * as os from '@client/os'; | ||||
| import { faICursor } from '@fortawesome/free-solid-svg-icons'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	props: { | ||||
|  | @ -57,7 +55,6 @@ export default defineComponent({ | |||
| 			hover: false, | ||||
| 			draghover: false, | ||||
| 			isDragging: false, | ||||
| 			faFolder, faFolderOpen | ||||
| 		}; | ||||
| 	}, | ||||
| 
 | ||||
|  | @ -241,7 +238,7 @@ export default defineComponent({ | |||
| 		onContextmenu(e) { | ||||
| 			os.contextMenu([{ | ||||
| 				text: this.$ts.openInWindow, | ||||
| 				icon: faWindowRestore, | ||||
| 				icon: 'fas fa-window-restore', | ||||
| 				action: () => { | ||||
| 					os.popup(import('./drive-window.vue'), { | ||||
| 						initialFolder: this.folder | ||||
|  | @ -254,7 +251,7 @@ export default defineComponent({ | |||
| 				action: this.rename | ||||
| 			}, null, { | ||||
| 				text: this.$ts.delete, | ||||
| 				icon: faTrashAlt, | ||||
| 				icon: 'fas fa-trash-alt', | ||||
| 				danger: true, | ||||
| 				action: this.deleteFolder | ||||
| 			}], e); | ||||
|  | @ -312,7 +309,7 @@ export default defineComponent({ | |||
| 		font-size: 0.9em; | ||||
| 		color: var(--desktopDriveFolderFg); | ||||
| 
 | ||||
| 		> [data-icon] { | ||||
| 		> i { | ||||
| 			margin-right: 4px; | ||||
| 			margin-left: 2px; | ||||
| 			text-align: left; | ||||
|  |  | |||
|  | @ -7,14 +7,13 @@ | |||
| 	@dragleave="onDragleave" | ||||
| 	@drop.stop="onDrop" | ||||
| > | ||||
| 	<i v-if="folder == null"><Fa :icon="faCloud"/></i> | ||||
| 	<i v-if="folder == null" class="fas fa-cloud"></i> | ||||
| 	<span>{{ folder == null ? $ts.drive : folder.name }}</span> | ||||
| </div> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { faCloud } from '@fortawesome/free-solid-svg-icons'; | ||||
| import * as os from '@client/os'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
|  | @ -29,7 +28,6 @@ export default defineComponent({ | |||
| 		return { | ||||
| 			hover: false, | ||||
| 			draghover: false, | ||||
| 			faCloud | ||||
| 		}; | ||||
| 	}, | ||||
| 
 | ||||
|  |  | |||
|  | @ -4,10 +4,10 @@ | |||
| 		<div class="path" @contextmenu.prevent.stop="() => {}"> | ||||
| 			<XNavFolder :class="{ current: folder == null }"/> | ||||
| 			<template v-for="f in hierarchyFolders"> | ||||
| 				<span class="separator"><Fa :icon="faAngleRight"/></span> | ||||
| 				<span class="separator"><i class="fas fa-angle-right"></i></span> | ||||
| 				<XNavFolder :folder="f"/> | ||||
| 			</template> | ||||
| 			<span class="separator" v-if="folder != null"><Fa :icon="faAngleRight"/></span> | ||||
| 			<span class="separator" v-if="folder != null"><i class="fas fa-angle-right"></i></span> | ||||
| 			<span class="folder current" v-if="folder != null">{{ folder.name }}</span> | ||||
| 		</div> | ||||
| 	</nav> | ||||
|  | @ -47,13 +47,11 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { faAngleRight, faFolderPlus, faICursor, faLink, faUpload } from '@fortawesome/free-solid-svg-icons'; | ||||
| import XNavFolder from './drive.nav-folder.vue'; | ||||
| import XFolder from './drive.folder.vue'; | ||||
| import XFile from './drive.file.vue'; | ||||
| import MkButton from './ui/button.vue'; | ||||
| import * as os from '@client/os'; | ||||
| import { faTrashAlt } from '@fortawesome/free-regular-svg-icons'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	components: { | ||||
|  | @ -125,7 +123,6 @@ export default defineComponent({ | |||
| 			), | ||||
| 			moreFilesElement: null as Element, | ||||
| 
 | ||||
| 			faAngleRight | ||||
| 		}; | ||||
| 	}, | ||||
| 
 | ||||
|  | @ -606,11 +603,11 @@ export default defineComponent({ | |||
| 				type: 'label' | ||||
| 			}, { | ||||
| 				text: this.$ts.upload, | ||||
| 				icon: faUpload, | ||||
| 				icon: 'fas fa-upload', | ||||
| 				action: () => { this.selectLocalFile(); } | ||||
| 			}, { | ||||
| 				text: this.$ts.fromUrl, | ||||
| 				icon: faLink, | ||||
| 				icon: 'fas fa-link', | ||||
| 				action: () => { this.urlUpload(); } | ||||
| 			}, null, { | ||||
| 				text: this.folder ? this.folder.name : this.$ts.drive, | ||||
|  | @ -621,11 +618,11 @@ export default defineComponent({ | |||
| 				action: () => { this.renameFolder(this.folder); } | ||||
| 			} : undefined, this.folder ? { | ||||
| 				text: this.$ts.deleteFolder, | ||||
| 				icon: faTrashAlt, | ||||
| 				icon: 'fas fa-trash-alt', | ||||
| 				action: () => { this.deleteFolder(this.folder); } | ||||
| 			} : undefined, { | ||||
| 				text: this.$ts.createFolder, | ||||
| 				icon: faFolderPlus, | ||||
| 				icon: 'fas fa-folder-plus', | ||||
| 				action: () => { this.createFolder(); } | ||||
| 			}]; | ||||
| 		}, | ||||
|  | @ -693,7 +690,7 @@ export default defineComponent({ | |||
| 					opacity: 0.5; | ||||
| 					cursor: default; | ||||
| 
 | ||||
| 					> [data-icon] { | ||||
| 					> i { | ||||
| 						margin: 0; | ||||
| 					} | ||||
| 				} | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| <template> | ||||
| <section> | ||||
| 	<header class="_acrylic" @click="shown = !shown"> | ||||
| 		<Fa :icon="shown ? faChevronDown : faChevronUp" :key="shown" fixed-width class="toggle"/> <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> | ||||
| 	<div v-if="shown"> | ||||
| 		<button v-for="emoji in emojis" | ||||
|  | @ -17,7 +17,6 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent, markRaw } from 'vue'; | ||||
| import { faChevronUp, faChevronDown } from '@fortawesome/free-solid-svg-icons'; | ||||
| import { getStaticImageUrl } from '@client/scripts/get-static-image-url'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
|  | @ -36,7 +35,6 @@ export default defineComponent({ | |||
| 		return { | ||||
| 			getStaticImageUrl, | ||||
| 			shown: this.initialShown, | ||||
| 			faChevronUp, faChevronDown, | ||||
| 		}; | ||||
| 	}, | ||||
| 
 | ||||
|  |  | |||
|  | @ -42,7 +42,7 @@ | |||
| 			</section> | ||||
| 
 | ||||
| 			<section> | ||||
| 				<header class="_acrylic"><Fa :icon="faClock" fixed-width/> {{ $ts.recentUsed }}</header> | ||||
| 				<header class="_acrylic"><i class="far fa-clock fa-fw"></i> {{ $ts.recentUsed }}</header> | ||||
| 				<div> | ||||
| 					<button v-for="emoji in $store.state.recentlyUsedEmojis" | ||||
| 						class="_button" | ||||
|  | @ -64,10 +64,10 @@ | |||
| 		</div> | ||||
| 	</div> | ||||
| 	<div class="tabs"> | ||||
| 		<button class="_button tab" :class="{ active: tab === 'index' }" @click="tab = 'index'"><Fa :icon="faAsterisk" fixed-width/></button> | ||||
| 		<button class="_button tab" :class="{ active: tab === 'custom' }" @click="tab = 'custom'"><Fa :icon="faLaugh" fixed-width/></button> | ||||
| 		<button class="_button tab" :class="{ active: tab === 'unicode' }" @click="tab = 'unicode'"><Fa :icon="faLeaf" fixed-width/></button> | ||||
| 		<button class="_button tab" :class="{ active: tab === 'tags' }" @click="tab = 'tags'"><Fa :icon="faHashtag" fixed-width/></button> | ||||
| 		<button class="_button tab" :class="{ active: tab === 'index' }" @click="tab = 'index'"><i class="fas fa-asterisk fa-fw"></i></button> | ||||
| 		<button class="_button tab" :class="{ active: tab === 'custom' }" @click="tab = 'custom'"><i class="fas fa-laugh fa-fw"></i></button> | ||||
| 		<button class="_button tab" :class="{ active: tab === 'unicode' }" @click="tab = 'unicode'"><i class="fas fa-leaf fa-fw"></i></button> | ||||
| 		<button class="_button tab" :class="{ active: tab === 'tags' }" @click="tab = 'tags'"><i class="fas fa-hashtag fa-fw"></i></button> | ||||
| 	</div> | ||||
| </div> | ||||
| </template> | ||||
|  | @ -76,8 +76,6 @@ | |||
| import { defineComponent, markRaw } from 'vue'; | ||||
| import { emojilist } from '@/misc/emojilist'; | ||||
| import { getStaticImageUrl } from '@client/scripts/get-static-image-url'; | ||||
| import { faAsterisk, faLeaf, faUtensils, faFutbol, faCity, faDice, faGlobe, faClock, faUser, faChevronDown, faShapes, faBicycle, faHashtag } from '@fortawesome/free-solid-svg-icons'; | ||||
| import { faHeart, faFlag, faLaugh } from '@fortawesome/free-regular-svg-icons'; | ||||
| import Particle from '@client/components/particle.vue'; | ||||
| import * as os from '@client/os'; | ||||
| import { isDeviceTouch } from '@client/scripts/is-device-touch'; | ||||
|  | @ -117,7 +115,6 @@ export default defineComponent({ | |||
| 			searchResultUnicode: [], | ||||
| 			tab: 'index', | ||||
| 			categories: ['face', 'people', 'animals_and_nature', 'food_and_drink', 'activity', 'travel_and_places', 'objects', 'symbols', 'flags'], | ||||
| 			faGlobe, faClock, faChevronDown, faAsterisk, faLaugh, faUtensils, faLeaf, faShapes, faBicycle, faHashtag, | ||||
| 		}; | ||||
| 	}, | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,12 +1,11 @@ | |||
| <template> | ||||
| <span class="mk-file-type-icon"> | ||||
| 	<template v-if="kind == 'image'"><Fa :icon="faFileImage"/></template> | ||||
| 	<template v-if="kind == 'image'"><i class="fas fa-file-image"></i></template> | ||||
| </span> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { faFileImage } from '@fortawesome/free-solid-svg-icons'; | ||||
| import * as os from '@client/os'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
|  | @ -18,7 +17,6 @@ export default defineComponent({ | |||
| 	}, | ||||
| 	data() { | ||||
| 		return { | ||||
| 			faFileImage | ||||
| 		}; | ||||
| 	}, | ||||
| 	computed: { | ||||
|  |  | |||
|  | @ -6,30 +6,29 @@ | |||
| > | ||||
| 	<template v-if="!wait"> | ||||
| 		<template v-if="hasPendingFollowRequestFromYou && user.isLocked"> | ||||
| 			<span v-if="full">{{ $ts.followRequestPending }}</span><Fa :icon="faHourglassHalf"/> | ||||
| 			<span v-if="full">{{ $ts.followRequestPending }}</span><i class="fas fa-hourglass-half"></i> | ||||
| 		</template> | ||||
| 		<template v-else-if="hasPendingFollowRequestFromYou && !user.isLocked"> <!-- つまりリモートフォローの場合。 --> | ||||
| 			<span v-if="full">{{ $ts.processing }}</span><Fa :icon="faSpinner" pulse/> | ||||
| 			<span v-if="full">{{ $ts.processing }}</span><i class="fas fa-spinner fa-pulse"></i> | ||||
| 		</template> | ||||
| 		<template v-else-if="isFollowing"> | ||||
| 			<span v-if="full">{{ $ts.unfollow }}</span><Fa :icon="faMinus"/> | ||||
| 			<span v-if="full">{{ $ts.unfollow }}</span><i class="fas fa-minus"></i> | ||||
| 		</template> | ||||
| 		<template v-else-if="!isFollowing && user.isLocked"> | ||||
| 			<span v-if="full">{{ $ts.followRequest }}</span><Fa :icon="faPlus"/> | ||||
| 			<span v-if="full">{{ $ts.followRequest }}</span><i class="fas fa-plus"></i> | ||||
| 		</template> | ||||
| 		<template v-else-if="!isFollowing && !user.isLocked"> | ||||
| 			<span v-if="full">{{ $ts.follow }}</span><Fa :icon="faPlus"/> | ||||
| 			<span v-if="full">{{ $ts.follow }}</span><i class="fas fa-plus"></i> | ||||
| 		</template> | ||||
| 	</template> | ||||
| 	<template v-else> | ||||
| 		<span v-if="full">{{ $ts.processing }}</span><Fa :icon="faSpinner" pulse fixed-width/> | ||||
| 		<span v-if="full">{{ $ts.processing }}</span><i class="fas fa-spinner fa-pulse fa-fw"></i> | ||||
| 	</template> | ||||
| </button> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { faSpinner, faPlus, faMinus, faHourglassHalf } from '@fortawesome/free-solid-svg-icons'; | ||||
| import * as os from '@client/os'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
|  | @ -56,7 +55,6 @@ export default defineComponent({ | |||
| 			hasPendingFollowRequestFromYou: this.user.hasPendingFollowRequestFromYou, | ||||
| 			wait: false, | ||||
| 			connection: null, | ||||
| 			faSpinner, faPlus, faMinus, faHourglassHalf | ||||
| 		}; | ||||
| 	}, | ||||
| 
 | ||||
|  |  | |||
|  | @ -24,6 +24,8 @@ export default defineComponent({ | |||
| 	--formXPadding: 32px; | ||||
| 	--formYPadding: 32px; | ||||
| 
 | ||||
| 	--formContentHMargin: 16px; | ||||
| 
 | ||||
| 	font-size: 95%; | ||||
| 	line-height: 1.3em; | ||||
| 	background: var(--bg); | ||||
|  |  | |||
|  | @ -30,7 +30,7 @@ | |||
| 	top: var(--stickyTop, 0px); | ||||
| 	z-index: 2; | ||||
| 	margin: -8px calc(var(--formXPadding) * -1) 0 calc(var(--formXPadding) * -1); | ||||
| 	padding: 8px calc(16px + var(--formXPadding)) 8px calc(16px + var(--formXPadding)); | ||||
| 	padding: 8px calc(var(--formContentHMargin) + var(--formXPadding)) 8px calc(var(--formContentHMargin) + var(--formXPadding)); | ||||
| 	background: var(--X17); | ||||
| 	-webkit-backdrop-filter: blur(10px); | ||||
| 	backdrop-filter: blur(10px); | ||||
|  | @ -42,7 +42,7 @@ | |||
| } | ||||
| 
 | ||||
| ._formCaption { | ||||
| 	padding: 8px 16px 0 16px; | ||||
| 	padding: 8px var(--formContentHMargin) 0 var(--formContentHMargin); | ||||
| } | ||||
| 
 | ||||
| ._formItem { | ||||
|  |  | |||
|  | @ -1,8 +1,8 @@ | |||
| <template> | ||||
| <div class="fzenkabp _formItem"> | ||||
| 	<div class="_formPanel" :class="{ warn }"> | ||||
| 		<i v-if="warn"><Fa :icon="faExclamationTriangle"/></i> | ||||
| 		<i v-else><Fa :icon="faInfoCircle"/></i> | ||||
| 		<i v-if="warn" class="fas fa-exclamation-triangle"></i> | ||||
| 		<i v-else class="fas fa-info-circle"></i> | ||||
| 		<slot></slot> | ||||
| 	</div> | ||||
| </div> | ||||
|  | @ -10,7 +10,6 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { faInfoCircle, faExclamationTriangle } from '@fortawesome/free-solid-svg-icons'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	props: { | ||||
|  | @ -22,7 +21,6 @@ export default defineComponent({ | |||
| 	}, | ||||
| 	data() { | ||||
| 		return { | ||||
| 			faInfoCircle, faExclamationTriangle | ||||
| 		}; | ||||
| 	} | ||||
| }); | ||||
|  |  | |||
|  | @ -30,13 +30,12 @@ | |||
| 	</div> | ||||
| 	<template #caption><slot name="desc"></slot></template> | ||||
| 
 | ||||
| 	<FormButton v-if="manualSave && changed" @click="updated" primary><Fa :icon="faSave"/> {{ $ts.save }}</FormButton> | ||||
| 	<FormButton v-if="manualSave && changed" @click="updated" primary><i class="fas fa-save"></i> {{ $ts.save }}</FormButton> | ||||
| </FormGroup> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent, onMounted, onUnmounted, nextTick, ref, watch, computed, toRefs } from 'vue'; | ||||
| import { faExclamationCircle, faSave } from '@fortawesome/free-solid-svg-icons'; | ||||
| import './form.scss'; | ||||
| import FormButton from './button.vue'; | ||||
| import FormGroup from './group.vue'; | ||||
|  | @ -191,7 +190,6 @@ export default defineComponent({ | |||
| 			onInput, | ||||
| 			onKeydown, | ||||
| 			updated, | ||||
| 			faExclamationCircle, faSave, | ||||
| 		}; | ||||
| 	}, | ||||
| }); | ||||
|  |  | |||
|  | @ -20,7 +20,7 @@ export default defineComponent({ | |||
| .anocepby { | ||||
| 	display: flex; | ||||
| 	align-items: center; | ||||
| 	padding: 14px 16px; | ||||
| 	padding: 14px var(--formContentHMargin); | ||||
| 
 | ||||
| 	> .key { | ||||
| 		margin-right: 12px; | ||||
|  |  | |||
|  | @ -5,7 +5,7 @@ | |||
| 		<span class="text"><slot></slot></span> | ||||
| 		<span class="right"> | ||||
| 			<span class="text"><slot name="suffix"></slot></span> | ||||
| 			<Fa :icon="faExternalLinkAlt" class="icon"/> | ||||
| 			<i class="fas fa-external-link-alt icon"></i> | ||||
| 		</span> | ||||
| 	</a> | ||||
| 	<MkA class="main _button _formPanel _formClickable" :class="{ active }" :to="to" :behavior="behavior" v-else> | ||||
|  | @ -13,7 +13,7 @@ | |||
| 		<span class="text"><slot></slot></span> | ||||
| 		<span class="right"> | ||||
| 			<span class="text"><slot name="suffix"></slot></span> | ||||
| 			<Fa :icon="faChevronRight" class="icon"/> | ||||
| 			<i class="fas fa-chevron-right icon"></i> | ||||
| 		</span> | ||||
| 	</MkA> | ||||
| </div> | ||||
|  | @ -21,7 +21,6 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { faChevronRight, faExternalLinkAlt } from '@fortawesome/free-solid-svg-icons'; | ||||
| import './form.scss'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
|  | @ -45,7 +44,6 @@ export default defineComponent({ | |||
| 	}, | ||||
| 	data() { | ||||
| 		return { | ||||
| 			faChevronRight, faExternalLinkAlt | ||||
| 		}; | ||||
| 	} | ||||
| }); | ||||
|  |  | |||
|  | @ -75,7 +75,7 @@ export default defineComponent({ | |||
| 			max-width: 100%; | ||||
| 			min-height: 130px; | ||||
| 			margin: 0; | ||||
| 			padding: 16px; | ||||
| 			padding: 16px var(--formContentHMargin); | ||||
| 			box-sizing: border-box; | ||||
| 			font: inherit; | ||||
| 			font-weight: normal; | ||||
|  |  | |||
|  | @ -18,6 +18,9 @@ export default defineComponent({ | |||
| 		} | ||||
| 	}, | ||||
| 	watch: { | ||||
| 		modelValue() { | ||||
| 			this.value = this.modelValue; | ||||
| 		}, | ||||
| 		value() { | ||||
| 			this.$emit('update:modelValue', this.value); | ||||
| 		} | ||||
|  |  | |||
|  | @ -14,7 +14,7 @@ | |||
| 			<slot></slot> | ||||
| 		</select> | ||||
| 		<div class="suffix"> | ||||
| 			<Fa :icon="faChevronDown"/> | ||||
| 			<i class="fas fa-chevron-down"></i> | ||||
| 		</div> | ||||
| 	</div> | ||||
| 	<div class="_formCaption"><slot name="caption"></slot></div> | ||||
|  | @ -23,7 +23,6 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { faChevronDown } from '@fortawesome/free-solid-svg-icons'; | ||||
| import './form.scss'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
|  | @ -47,7 +46,6 @@ export default defineComponent({ | |||
| 	}, | ||||
| 	data() { | ||||
| 		return { | ||||
| 			faChevronDown, | ||||
| 		}; | ||||
| 	}, | ||||
| 	computed: { | ||||
|  |  | |||
|  | @ -5,13 +5,13 @@ | |||
| 			<MkLoading/> | ||||
| 		</div> | ||||
| 	</div> | ||||
| 	<FormGroup v-else-if="resolved" class="_formItem"> | ||||
| 	<div v-else-if="resolved" class="_formItem"> | ||||
| 		<slot :result="result"></slot> | ||||
| 	</FormGroup> | ||||
| 	</div> | ||||
| 	<div class="_formItem" v-else> | ||||
| 		<div class="_formPanel"> | ||||
| 			error! | ||||
| 			<button @click="retry">retry</button> | ||||
| 		<div class="_formPanel eiurkvay"> | ||||
| 			<div><i class="fas fa-exclamation-triangle"></i> {{ $ts.somethingHappened }}</div> | ||||
| 			<MkButton inline @click="retry" class="retry"><i class="fas fa-redo-alt"></i> {{ $ts.retry }}</MkButton> | ||||
| 		</div> | ||||
| 	</div> | ||||
| </transition> | ||||
|  | @ -20,11 +20,11 @@ | |||
| <script lang="ts"> | ||||
| import { defineComponent, PropType, ref, watch } from 'vue'; | ||||
| import './form.scss'; | ||||
| import FormGroup from './group.vue'; | ||||
| import MkButton from '@client/components/ui/button.vue'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	components: { | ||||
| 		FormGroup, | ||||
| 		MkButton | ||||
| 	}, | ||||
| 
 | ||||
| 	props: { | ||||
|  | @ -89,4 +89,13 @@ export default defineComponent({ | |||
| .fade-leave-to { | ||||
| 	opacity: 0; | ||||
| } | ||||
| 
 | ||||
| .eiurkvay { | ||||
| 	padding: 16px; | ||||
| 	text-align: center; | ||||
| 
 | ||||
| 	> .retry { | ||||
| 		margin-top: 16px; | ||||
| 	} | ||||
| } | ||||
| </style> | ||||
|  |  | |||
|  | @ -18,13 +18,12 @@ | |||
| 	</div> | ||||
| 	<template #caption><slot name="desc"></slot></template> | ||||
| 
 | ||||
| 	<FormButton v-if="manualSave && changed" @click="updated" primary><Fa :icon="faSave"/> {{ $ts.save }}</FormButton> | ||||
| 	<FormButton v-if="manualSave && changed" @click="updated" primary><i class="fas fa-save"></i> {{ $ts.save }}</FormButton> | ||||
| </FormGroup> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent, ref, toRefs, watch } from 'vue'; | ||||
| import { faSave } from '@fortawesome/free-solid-svg-icons'; | ||||
| import './form.scss'; | ||||
| import FormButton from './button.vue'; | ||||
| import FormGroup from './group.vue'; | ||||
|  | @ -106,7 +105,6 @@ export default defineComponent({ | |||
| 			changed, | ||||
| 			focus, | ||||
| 			onInput, | ||||
| 			faSave, | ||||
| 		}; | ||||
| 	} | ||||
| }); | ||||
|  |  | |||
|  | @ -6,7 +6,6 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { faExpandAlt, faColumns, faExternalLinkAlt, faLink, faWindowMaximize } from '@fortawesome/free-solid-svg-icons'; | ||||
| import * as os from '@client/os'; | ||||
| import copyToClipboard from '@client/scripts/copy-to-clipboard'; | ||||
| import { router } from '@client/router'; | ||||
|  | @ -57,31 +56,31 @@ export default defineComponent({ | |||
| 				type: 'label', | ||||
| 				text: this.to, | ||||
| 			}, { | ||||
| 				icon: faWindowMaximize, | ||||
| 				icon: 'fas fa-window-maximize', | ||||
| 				text: this.$ts.openInWindow, | ||||
| 				action: () => { | ||||
| 					os.pageWindow(this.to); | ||||
| 				} | ||||
| 			}, this.sideViewHook ? { | ||||
| 				icon: faColumns, | ||||
| 				icon: 'fas fa-columns', | ||||
| 				text: this.$ts.openInSideView, | ||||
| 				action: () => { | ||||
| 					this.sideViewHook(this.to); | ||||
| 				} | ||||
| 			} : undefined, { | ||||
| 				icon: faExpandAlt, | ||||
| 				icon: 'fas fa-expand-alt', | ||||
| 				text: this.$ts.showInPage, | ||||
| 				action: () => { | ||||
| 					this.$router.push(this.to); | ||||
| 				} | ||||
| 			}, null, { | ||||
| 				icon: faExternalLinkAlt, | ||||
| 				icon: 'fas fa-external-link-alt', | ||||
| 				text: this.$ts.openInNewTab, | ||||
| 				action: () => { | ||||
| 					window.open(this.to, '_blank'); | ||||
| 				} | ||||
| 			}, { | ||||
| 				icon: faLink, | ||||
| 				icon: 'fas fa-link', | ||||
| 				text: this.$ts.copyLink, | ||||
| 				action: () => { | ||||
| 					copyToClipboard(`${url}${this.to}`); | ||||
|  |  | |||
|  | @ -2,7 +2,7 @@ | |||
| <transition :name="$store.state.animation ? 'zoom' : ''" appear> | ||||
| 	<div class="mjndxjcg"> | ||||
| 		<img src="https://xn--931a.moe/assets/error.jpg" class="_ghost"/> | ||||
| 		<p><Fa :icon="faExclamationTriangle"/> {{ $ts.somethingHappened }}</p> | ||||
| 		<p><i class="fas fa-exclamation-triangle"></i> {{ $ts.somethingHappened }}</p> | ||||
| 		<MkButton @click="() => $emit('retry')" class="button">{{ $ts.retry }}</MkButton> | ||||
| 	</div> | ||||
| </transition> | ||||
|  | @ -10,7 +10,6 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons'; | ||||
| import MkButton from '@client/components/ui/button.vue'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
|  | @ -19,7 +18,6 @@ export default defineComponent({ | |||
| 	}, | ||||
| 	data() { | ||||
| 		return { | ||||
| 			faExclamationTriangle | ||||
| 		}; | ||||
| 	}, | ||||
| }); | ||||
|  |  | |||
|  | @ -15,13 +15,12 @@ | |||
| 	<span class="pathname" v-if="pathname != ''">{{ self ? pathname.substr(1) : pathname }}</span> | ||||
| 	<span class="query">{{ query }}</span> | ||||
| 	<span class="hash">{{ hash }}</span> | ||||
| 	<Fa :icon="faExternalLinkSquareAlt" v-if="target === '_blank'" class="icon"/> | ||||
| 	<i v-if="target === '_blank'" class="fas fa-external-link-square-alt icon"></i> | ||||
| </component> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { faExternalLinkSquareAlt } from '@fortawesome/free-solid-svg-icons'; | ||||
| import { toUnicode as decodePunycode } from 'punycode/'; | ||||
| import { url as local } from '@client/config'; | ||||
| import { isDeviceTouch } from '@client/scripts/is-device-touch'; | ||||
|  | @ -55,7 +54,6 @@ export default defineComponent({ | |||
| 			hideTimer: null, | ||||
| 			checkTimer: null, | ||||
| 			close: null, | ||||
| 			faExternalLinkSquareAlt | ||||
| 		}; | ||||
| 	}, | ||||
| 	created() { | ||||
|  |  | |||
|  | @ -1,13 +1,12 @@ | |||
| <template> | ||||
| <div class="mk-google"> | ||||
| 	<input type="search" v-model="query" :placeholder="q"> | ||||
| 	<button @click="search"><Fa :icon="faSearch"/> {{ $ts.search }}</button> | ||||
| 	<button @click="search"><i class="fas fa-search"></i> {{ $ts.search }}</button> | ||||
| </div> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { faSearch } from '@fortawesome/free-solid-svg-icons'; | ||||
| import * as os from '@client/os'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
|  | @ -15,7 +14,6 @@ export default defineComponent({ | |||
| 	data() { | ||||
| 		return { | ||||
| 			query: null, | ||||
| 			faSearch | ||||
| 		}; | ||||
| 	}, | ||||
| 	mounted() { | ||||
|  |  | |||
|  | @ -1,129 +1,40 @@ | |||
| <template> | ||||
| <div class="zbcjwnqg" v-size="{ max: [550, 1000] }"> | ||||
| 	<div class="stats" v-if="info"> | ||||
| 		<div class="_panel"> | ||||
| 			<div> | ||||
| 				<b><Fa :icon="faUser"/>{{ $ts.users }}</b> | ||||
| 				<small>{{ $ts.local }}</small> | ||||
| 			</div> | ||||
| 			<div> | ||||
| 				<dl class="total"> | ||||
| 					<dt>{{ $ts.total }}</dt> | ||||
| 					<dd>{{ number(info.originalUsersCount) }}</dd> | ||||
| 				</dl> | ||||
| 				<dl class="diff" :class="{ inc: usersLocalDoD > 0 }"> | ||||
| 					<dt>{{ $ts.dayOverDayChanges }}</dt> | ||||
| 					<dd>{{ number(usersLocalDoD) }}</dd> | ||||
| 				</dl> | ||||
| 				<dl class="diff" :class="{ inc: usersLocalWoW > 0 }"> | ||||
| 					<dt>{{ $ts.weekOverWeekChanges }}</dt> | ||||
| 					<dd>{{ number(usersLocalWoW) }}</dd> | ||||
| 				</dl> | ||||
| 			</div> | ||||
| 		</div> | ||||
| 		<div class="_panel"> | ||||
| 			<div> | ||||
| 				<b><Fa :icon="faUser"/>{{ $ts.users }}</b> | ||||
| 				<small>{{ $ts.remote }}</small> | ||||
| 			</div> | ||||
| 			<div> | ||||
| 				<dl class="total"> | ||||
| 					<dt>{{ $ts.total }}</dt> | ||||
| 					<dd>{{ number((info.usersCount - info.originalUsersCount)) }}</dd> | ||||
| 				</dl> | ||||
| 				<dl class="diff" :class="{ inc: usersRemoteDoD > 0 }"> | ||||
| 					<dt>{{ $ts.dayOverDayChanges }}</dt> | ||||
| 					<dd>{{ number(usersRemoteDoD) }}</dd> | ||||
| 				</dl> | ||||
| 				<dl class="diff" :class="{ inc: usersRemoteWoW > 0 }"> | ||||
| 					<dt>{{ $ts.weekOverWeekChanges }}</dt> | ||||
| 					<dd>{{ number(usersRemoteWoW) }}</dd> | ||||
| 				</dl> | ||||
| 			</div> | ||||
| 		</div> | ||||
| 		<div class="_panel"> | ||||
| 			<div> | ||||
| 				<b><Fa :icon="faPencilAlt"/>{{ $ts.notes }}</b> | ||||
| 				<small>{{ $ts.local }}</small> | ||||
| 			</div> | ||||
| 			<div> | ||||
| 				<dl class="total"> | ||||
| 					<dt>{{ $ts.total }}</dt> | ||||
| 					<dd>{{ number(info.originalNotesCount) }}</dd> | ||||
| 				</dl> | ||||
| 				<dl class="diff" :class="{ inc: notesLocalDoD > 0 }"> | ||||
| 					<dt>{{ $ts.dayOverDayChanges }}</dt> | ||||
| 					<dd>{{ number(notesLocalDoD) }}</dd> | ||||
| 				</dl> | ||||
| 				<dl class="diff" :class="{ inc: notesLocalWoW > 0 }"> | ||||
| 					<dt>{{ $ts.weekOverWeekChanges }}</dt> | ||||
| 					<dd>{{ number(notesLocalWoW) }}</dd> | ||||
| 				</dl> | ||||
| 			</div> | ||||
| 		</div> | ||||
| 		<div class="_panel"> | ||||
| 			<div> | ||||
| 				<b><Fa :icon="faPencilAlt"/>{{ $ts.notes }}</b> | ||||
| 				<small>{{ $ts.remote }}</small> | ||||
| 			</div> | ||||
| 			<div> | ||||
| 				<dl class="total"> | ||||
| 					<dt>{{ $ts.total }}</dt> | ||||
| 					<dd>{{ number((info.notesCount - info.originalNotesCount)) }}</dd> | ||||
| 				</dl> | ||||
| 				<dl class="diff" :class="{ inc: notesRemoteDoD > 0 }"> | ||||
| 					<dt>{{ $ts.dayOverDayChanges }}</dt> | ||||
| 					<dd>{{ number(notesRemoteDoD) }}</dd> | ||||
| 				</dl> | ||||
| 				<dl class="diff" :class="{ inc: notesRemoteWoW > 0 }"> | ||||
| 					<dt>{{ $ts.weekOverWeekChanges }}</dt> | ||||
| 					<dd>{{ number(notesRemoteWoW) }}</dd> | ||||
| 				</dl> | ||||
| 			</div> | ||||
| 		</div> | ||||
| <div class="zbcjwnqg" style="margin-top: -8px;"> | ||||
| 	<div class="selects" style="display: flex;"> | ||||
| 		<MkSelect v-model:value="chartSrc" style="margin: 0; flex: 1;"> | ||||
| 			<optgroup :label="$ts.federation"> | ||||
| 				<option value="federation-instances">{{ $ts._charts.federationInstancesIncDec }}</option> | ||||
| 				<option value="federation-instances-total">{{ $ts._charts.federationInstancesTotal }}</option> | ||||
| 			</optgroup> | ||||
| 			<optgroup :label="$ts.users"> | ||||
| 				<option value="users">{{ $ts._charts.usersIncDec }}</option> | ||||
| 				<option value="users-total">{{ $ts._charts.usersTotal }}</option> | ||||
| 				<option value="active-users">{{ $ts._charts.activeUsers }}</option> | ||||
| 			</optgroup> | ||||
| 			<optgroup :label="$ts.notes"> | ||||
| 				<option value="notes">{{ $ts._charts.notesIncDec }}</option> | ||||
| 				<option value="local-notes">{{ $ts._charts.localNotesIncDec }}</option> | ||||
| 				<option value="remote-notes">{{ $ts._charts.remoteNotesIncDec }}</option> | ||||
| 				<option value="notes-total">{{ $ts._charts.notesTotal }}</option> | ||||
| 			</optgroup> | ||||
| 			<optgroup :label="$ts.drive"> | ||||
| 				<option value="drive-files">{{ $ts._charts.filesIncDec }}</option> | ||||
| 				<option value="drive-files-total">{{ $ts._charts.filesTotal }}</option> | ||||
| 				<option value="drive">{{ $ts._charts.storageUsageIncDec }}</option> | ||||
| 				<option value="drive-total">{{ $ts._charts.storageUsageTotal }}</option> | ||||
| 			</optgroup> | ||||
| 		</MkSelect> | ||||
| 		<MkSelect v-model:value="chartSpan" style="margin: 0;"> | ||||
| 			<option value="hour">{{ $ts.perHour }}</option> | ||||
| 			<option value="day">{{ $ts.perDay }}</option> | ||||
| 		</MkSelect> | ||||
| 	</div> | ||||
| 
 | ||||
| 	<section class="_card"> | ||||
| 		<div class="_title" style="position: relative;"><Fa :icon="faChartBar"/> {{ $ts.statistics }}<button @click="fetchChart" class="_button" style="position: absolute; right: 0; bottom: 0; top: 0; padding: inherit;"><Fa :icon="faSync"/></button></div> | ||||
| 		<div class="_content" style="margin-top: -8px;"> | ||||
| 			<div class="selects" style="display: flex;"> | ||||
| 				<MkSelect v-model:value="chartSrc" style="margin: 0; flex: 1;"> | ||||
| 					<optgroup :label="$ts.federation"> | ||||
| 						<option value="federation-instances">{{ $ts._charts.federationInstancesIncDec }}</option> | ||||
| 						<option value="federation-instances-total">{{ $ts._charts.federationInstancesTotal }}</option> | ||||
| 					</optgroup> | ||||
| 					<optgroup :label="$ts.users"> | ||||
| 						<option value="users">{{ $ts._charts.usersIncDec }}</option> | ||||
| 						<option value="users-total">{{ $ts._charts.usersTotal }}</option> | ||||
| 						<option value="active-users">{{ $ts._charts.activeUsers }}</option> | ||||
| 					</optgroup> | ||||
| 					<optgroup :label="$ts.notes"> | ||||
| 						<option value="notes">{{ $ts._charts.notesIncDec }}</option> | ||||
| 						<option value="local-notes">{{ $ts._charts.localNotesIncDec }}</option> | ||||
| 						<option value="remote-notes">{{ $ts._charts.remoteNotesIncDec }}</option> | ||||
| 						<option value="notes-total">{{ $ts._charts.notesTotal }}</option> | ||||
| 					</optgroup> | ||||
| 					<optgroup :label="$ts.drive"> | ||||
| 						<option value="drive-files">{{ $ts._charts.filesIncDec }}</option> | ||||
| 						<option value="drive-files-total">{{ $ts._charts.filesTotal }}</option> | ||||
| 						<option value="drive">{{ $ts._charts.storageUsageIncDec }}</option> | ||||
| 						<option value="drive-total">{{ $ts._charts.storageUsageTotal }}</option> | ||||
| 					</optgroup> | ||||
| 				</MkSelect> | ||||
| 				<MkSelect v-model:value="chartSpan" style="margin: 0;"> | ||||
| 					<option value="hour">{{ $ts.perHour }}</option> | ||||
| 					<option value="day">{{ $ts.perDay }}</option> | ||||
| 				</MkSelect> | ||||
| 			</div> | ||||
| 			<canvas ref="chart"></canvas> | ||||
| 		</div> | ||||
| 	</section> | ||||
| 	<canvas ref="chart"></canvas> | ||||
| </div> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent, markRaw } from 'vue'; | ||||
| import { faChartBar, faUser, faPencilAlt, faSync } from '@fortawesome/free-solid-svg-icons'; | ||||
| import Chart from 'chart.js'; | ||||
| import MkSelect from './ui/select.vue'; | ||||
| import number from '@client/filters/number'; | ||||
|  | @ -159,7 +70,6 @@ export default defineComponent({ | |||
| 
 | ||||
| 	data() { | ||||
| 		return { | ||||
| 			info: null, | ||||
| 			notesLocalWoW: 0, | ||||
| 			notesLocalDoD: 0, | ||||
| 			notesRemoteWoW: 0, | ||||
|  | @ -173,7 +83,6 @@ export default defineComponent({ | |||
| 			chartInstance: null, | ||||
| 			chartSrc: 'notes', | ||||
| 			chartSpan: 'hour', | ||||
| 			faChartBar, faUser, faPencilAlt, faSync | ||||
| 		} | ||||
| 	}, | ||||
| 
 | ||||
|  | @ -218,8 +127,6 @@ export default defineComponent({ | |||
| 	}, | ||||
| 
 | ||||
| 	async created() { | ||||
| 		this.info = await os.api('stats'); | ||||
| 
 | ||||
| 		this.now = new Date(); | ||||
| 
 | ||||
| 		this.fetchChart(); | ||||
|  | @ -258,15 +165,6 @@ export default defineComponent({ | |||
| 				} | ||||
| 			}; | ||||
| 
 | ||||
| 			this.notesLocalWoW = this.info.originalNotesCount - chart.perDay.notes.local.total[7]; | ||||
| 			this.notesLocalDoD = this.info.originalNotesCount - chart.perDay.notes.local.total[1]; | ||||
| 			this.notesRemoteWoW = (this.info.notesCount - this.info.originalNotesCount) - chart.perDay.notes.remote.total[7]; | ||||
| 			this.notesRemoteDoD = (this.info.notesCount - this.info.originalNotesCount) - chart.perDay.notes.remote.total[1]; | ||||
| 			this.usersLocalWoW = this.info.originalUsersCount - chart.perDay.users.local.total[7]; | ||||
| 			this.usersLocalDoD = this.info.originalUsersCount - chart.perDay.users.local.total[1]; | ||||
| 			this.usersRemoteWoW = (this.info.usersCount - this.info.originalUsersCount) - chart.perDay.users.remote.total[7]; | ||||
| 			this.usersRemoteDoD = (this.info.usersCount - this.info.originalUsersCount) - chart.perDay.users.remote.total[1]; | ||||
| 
 | ||||
| 			this.chart = chart; | ||||
| 
 | ||||
| 			this.renderChart(); | ||||
|  | @ -302,10 +200,10 @@ export default defineComponent({ | |||
| 					aspectRatio: 2.5, | ||||
| 					layout: { | ||||
| 						padding: { | ||||
| 							left: 0, | ||||
| 							right: 0, | ||||
| 							left: 16, | ||||
| 							right: 16, | ||||
| 							top: 16, | ||||
| 							bottom: 0 | ||||
| 							bottom: 8 | ||||
| 						} | ||||
| 					}, | ||||
| 					legend: { | ||||
|  | @ -632,90 +530,8 @@ export default defineComponent({ | |||
| 
 | ||||
| <style lang="scss" scoped> | ||||
| .zbcjwnqg { | ||||
| 	&.max-width_1000px { | ||||
| 		> .stats { | ||||
| 			grid-template-columns: 1fr 1fr; | ||||
| 			grid-template-rows: 1fr 1fr; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	&.max-width_550px { | ||||
| 		> .stats { | ||||
| 			grid-template-columns: 1fr; | ||||
| 			grid-template-rows: 1fr 1fr 1fr 1fr; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	> .stats { | ||||
| 		display: grid; | ||||
| 		grid-template-columns: 1fr 1fr 1fr 1fr; | ||||
| 		grid-template-rows: 1fr; | ||||
| 		gap: var(--margin); | ||||
| 		margin-bottom: var(--margin); | ||||
| 		font-size: 90%; | ||||
| 
 | ||||
| 		> div { | ||||
| 			display: flex; | ||||
| 			box-sizing: border-box; | ||||
| 			padding: 16px 20px; | ||||
| 
 | ||||
| 			> div { | ||||
| 				width: 50%; | ||||
| 
 | ||||
| 				&:first-child { | ||||
| 					> b { | ||||
| 						display: block; | ||||
| 
 | ||||
| 						> [data-icon] { | ||||
| 							width: 16px; | ||||
| 							margin-right: 8px; | ||||
| 						} | ||||
| 					} | ||||
| 
 | ||||
| 					> small { | ||||
| 						margin-left: 16px + 8px; | ||||
| 						opacity: 0.7; | ||||
| 					} | ||||
| 				} | ||||
| 
 | ||||
| 				&:last-child { | ||||
| 					> dl { | ||||
| 						display: flex; | ||||
| 						margin: 0; | ||||
| 						line-height: 1.5em; | ||||
| 
 | ||||
| 						> dt, | ||||
| 						> dd { | ||||
| 							width: 50%; | ||||
| 							margin: 0; | ||||
| 						} | ||||
| 
 | ||||
| 						> dd { | ||||
| 							text-overflow: ellipsis; | ||||
| 							overflow: hidden; | ||||
| 							white-space: nowrap; | ||||
| 						} | ||||
| 
 | ||||
| 						&.total { | ||||
| 							> dt, | ||||
| 							> dd { | ||||
| 								font-weight: bold; | ||||
| 							} | ||||
| 						} | ||||
| 
 | ||||
| 						&.diff.inc { | ||||
| 							> dd { | ||||
| 								color: #82c11c; | ||||
| 
 | ||||
| 								&:before { | ||||
| 									content: "+"; | ||||
| 								} | ||||
| 							} | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	> .selects { | ||||
| 		padding: 8px 16px 0 16px; | ||||
| 	} | ||||
| } | ||||
| </style> | ||||
|  |  | |||
|  | @ -4,28 +4,28 @@ | |||
| 		<div class="main"> | ||||
| 			<template v-for="item in items"> | ||||
| 				<button v-if="item.action" class="_button" @click="$event => { item.action($event); close(); }"> | ||||
| 					<Fa :icon="item.icon" class="icon"/> | ||||
| 					<i class="icon" :class="item.icon"></i> | ||||
| 					<div class="text">{{ item.text }}</div> | ||||
| 					<i v-if="item.indicate"><Fa :icon="faCircle"/></i> | ||||
| 					<span v-if="item.indicate" class="indicator"><i class="fas fa-circle"></i></span> | ||||
| 				</button> | ||||
| 				<MkA v-else :to="item.to" @click.passive="close()"> | ||||
| 					<Fa :icon="item.icon" class="icon"/> | ||||
| 					<i class="icon" :class="item.icon"></i> | ||||
| 					<div class="text">{{ item.text }}</div> | ||||
| 					<i v-if="item.indicate"><Fa :icon="faCircle"/></i> | ||||
| 					<span v-if="item.indicate" class="indicator"><i class="fas fa-circle"></i></span> | ||||
| 				</MkA> | ||||
| 			</template> | ||||
| 		</div> | ||||
| 		<div class="sub"> | ||||
| 			<MkA to="/docs" @click.passive="close()"> | ||||
| 				<Fa :icon="faQuestionCircle" class="icon"/> | ||||
| 				<i class="fas fa-question-circle icon"></i> | ||||
| 				<div class="text">{{ $ts.help }}</div> | ||||
| 			</MkA> | ||||
| 			<MkA to="/about" @click.passive="close()"> | ||||
| 				<Fa :icon="faInfoCircle" class="icon"/> | ||||
| 				<i class="fas fa-info-circle icon"></i> | ||||
| 				<div class="text">{{ $t('aboutX', { x: instanceName }) }}</div> | ||||
| 			</MkA> | ||||
| 			<MkA to="/about-misskey" @click.passive="close()"> | ||||
| 				<Fa :icon="faInfoCircle" class="icon"/> | ||||
| 				<i class="fas fa-info-circle icon"></i> | ||||
| 				<div class="text">{{ $ts.aboutMisskey }}</div> | ||||
| 			</MkA> | ||||
| 		</div> | ||||
|  | @ -35,7 +35,6 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { faQuestionCircle, faInfoCircle, faCircle } from '@fortawesome/free-solid-svg-icons'; | ||||
| import MkModal from '@client/components/ui/modal.vue'; | ||||
| import { sidebarDef } from '@client/sidebar'; | ||||
| import { instanceName } from '@client/config'; | ||||
|  | @ -52,7 +51,6 @@ export default defineComponent({ | |||
| 			menuDef: sidebarDef, | ||||
| 			items: [], | ||||
| 			instanceName, | ||||
| 			faQuestionCircle, faInfoCircle, faCircle, | ||||
| 		}; | ||||
| 	}, | ||||
| 
 | ||||
|  | @ -127,7 +125,7 @@ export default defineComponent({ | |||
| 				line-height: 1.5em; | ||||
| 			} | ||||
| 
 | ||||
| 			> i { | ||||
| 			> .indicator { | ||||
| 				position: absolute; | ||||
| 				top: 32px; | ||||
| 				left: 32px; | ||||
|  |  | |||
|  | @ -5,13 +5,12 @@ | |||
| 	:title="url" | ||||
| > | ||||
| 	<slot></slot> | ||||
| 	<Fa :icon="faExternalLinkSquareAlt" v-if="target === '_blank'" class="icon"/> | ||||
| 	<i v-if="target === '_blank'" class="fas fa-external-link-square-alt icon"></i> | ||||
| </component> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { faExternalLinkSquareAlt } from '@fortawesome/free-solid-svg-icons'; | ||||
| import { url as local } from '@client/config'; | ||||
| import { isDeviceTouch } from '@client/scripts/is-device-touch'; | ||||
| import * as os from '@client/os'; | ||||
|  | @ -38,7 +37,6 @@ export default defineComponent({ | |||
| 			hideTimer: null, | ||||
| 			checkTimer: null, | ||||
| 			close: null, | ||||
| 			faExternalLinkSquareAlt | ||||
| 		}; | ||||
| 	}, | ||||
| 	methods: { | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| <template> | ||||
| <div class="mk-media-banner"> | ||||
| 	<div class="sensitive" v-if="media.isSensitive && hide" @click="hide = false"> | ||||
| 		<span class="icon"><Fa :icon="faExclamationTriangle"/></span> | ||||
| 		<span class="icon"><i class="fas fa-exclamation-triangle"></i></span> | ||||
| 		<b>{{ $ts.sensitive }}</b> | ||||
| 		<span>{{ $ts.clickToShow }}</span> | ||||
| 	</div> | ||||
|  | @ -19,7 +19,7 @@ | |||
| 		:title="media.name" | ||||
| 		:download="media.name" | ||||
| 	> | ||||
| 		<span class="icon"><Fa icon="download"/></span> | ||||
| 		<span class="icon"><i class="fas fa-download"></i></span> | ||||
| 		<b>{{ media.name }}</b> | ||||
| 	</a> | ||||
| </div> | ||||
|  | @ -27,7 +27,6 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons'; | ||||
| import * as os from '@client/os'; | ||||
| import { ColdDeviceStorage } from '@client/store'; | ||||
| 
 | ||||
|  | @ -41,7 +40,6 @@ export default defineComponent({ | |||
| 	data() { | ||||
| 		return { | ||||
| 			hide: true, | ||||
| 			faExclamationTriangle | ||||
| 		}; | ||||
| 	}, | ||||
| 	mounted() { | ||||
|  |  | |||
|  | @ -3,13 +3,13 @@ | |||
| 	<ImgWithBlurhash class="bg" :hash="image.blurhash" :title="image.name"/> | ||||
| 	<div class="text"> | ||||
| 		<div> | ||||
| 			<b><Fa :icon="faExclamationTriangle"/> {{ $ts.sensitive }}</b> | ||||
| 			<b><i class="fas fa-exclamation-triangle"></i> {{ $ts.sensitive }}</b> | ||||
| 			<span>{{ $ts.clickToShow }}</span> | ||||
| 		</div> | ||||
| 	</div> | ||||
| </div> | ||||
| <div class="gqnyydlz" :style="{ background: color }" v-else> | ||||
| 	<i><Fa :icon="faEyeSlash" @click="hide = true"/></i> | ||||
| 	<i class="fas fa-eye-slash" @click="hide = true"></i> | ||||
| 	<a | ||||
| 		:href="image.url" | ||||
| 		:title="image.name" | ||||
|  | @ -23,7 +23,6 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { faExclamationTriangle, faEyeSlash } from '@fortawesome/free-solid-svg-icons'; | ||||
| import { getStaticImageUrl } from '@client/scripts/get-static-image-url'; | ||||
| import { extractAvgColorFromBlurhash } from '@client/scripts/extract-avg-color-from-blurhash'; | ||||
| import ImageViewer from './image-viewer.vue'; | ||||
|  | @ -47,7 +46,6 @@ export default defineComponent({ | |||
| 		return { | ||||
| 			hide: true, | ||||
| 			color: null, | ||||
| 			faExclamationTriangle, faEyeSlash, | ||||
| 		}; | ||||
| 	}, | ||||
| 	computed: { | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| <template> | ||||
| <div class="icozogqfvdetwohsdglrbswgrejoxbdj" v-if="hide" @click="hide = false"> | ||||
| 	<div> | ||||
| 		<b><Fa :icon="faExclamationTriangle"/> {{ $ts.sensitive }}</b> | ||||
| 		<b><i class="fas fa-exclamation-triangle"></i> {{ $ts.sensitive }}</b> | ||||
| 		<span>{{ $ts.clickToShow }}</span> | ||||
| 	</div> | ||||
| </div> | ||||
|  | @ -18,13 +18,12 @@ | |||
| 			:type="video.type" | ||||
| 		> | ||||
| 	</video> | ||||
| 	<i><Fa :icon="faEyeSlash" @click="hide = true"/></i> | ||||
| 	<i class="fas fa-eye-slash" @click="hide = true"></i> | ||||
| </div> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { faExclamationTriangle, faEyeSlash } from '@fortawesome/free-solid-svg-icons'; | ||||
| import * as os from '@client/os'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
|  | @ -37,8 +36,6 @@ export default defineComponent({ | |||
| 	data() { | ||||
| 		return { | ||||
| 			hide: true, | ||||
| 			faExclamationTriangle, | ||||
| 			faEyeSlash | ||||
| 		}; | ||||
| 	}, | ||||
| 	created() { | ||||
|  |  | |||
|  | @ -1,13 +1,13 @@ | |||
| <template> | ||||
| <MkModal ref="modal" @click="$emit('click')" @closed="$emit('closed')"> | ||||
| 	<div class="hrmcaedk _popup _narrow_" :style="{ width: `${width}px`, height: (height ? `min(${height}px, 100%)` : '100%') }"> | ||||
| 		<div class="header"> | ||||
| 			<button class="_button" @click="back()" v-if="history.length > 0"><Fa :icon="faChevronLeft"/></button> | ||||
| 		<div class="header" @contextmenu="onContextmenu"> | ||||
| 			<button class="_button" @click="back()" v-if="history.length > 0"><i class="fas fa-chevron-left"></i></button> | ||||
| 			<button class="_button" style="pointer-events: none;" v-else><!-- マージンのバランスを取るためのダミー --></button> | ||||
| 			<span class="title"> | ||||
| 				<XHeader :info="pageInfo" :with-back="false"/> | ||||
| 			</span> | ||||
| 			<button class="_button" @click="$refs.modal.close()"><Fa :icon="faTimes"/></button> | ||||
| 			<button class="_button" @click="$refs.modal.close()"><i class="fas fa-times"></i></button> | ||||
| 		</div> | ||||
| 		<div class="body _flat_"> | ||||
| 			<keep-alive> | ||||
|  | @ -20,7 +20,6 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { faExternalLinkAlt, faExpandAlt, faLink, faChevronLeft, faColumns, faTimes } from '@fortawesome/free-solid-svg-icons'; | ||||
| import MkModal from '@client/components/ui/modal.vue'; | ||||
| import XHeader from '@client/ui/_common_/header.vue'; | ||||
| import { popout } from '@client/scripts/popout'; | ||||
|  | @ -28,6 +27,7 @@ import copyToClipboard from '@client/scripts/copy-to-clipboard'; | |||
| import { resolve } from '@client/router'; | ||||
| import { url } from '@client/config'; | ||||
| import * as symbols from '@client/symbols'; | ||||
| import * as os from '@client/os'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	components: { | ||||
|  | @ -76,7 +76,6 @@ export default defineComponent({ | |||
| 			component: this.initialComponent, | ||||
| 			props: this.initialProps, | ||||
| 			history: [], | ||||
| 			faChevronLeft, faTimes, | ||||
| 		}; | ||||
| 	}, | ||||
| 
 | ||||
|  | @ -90,29 +89,29 @@ export default defineComponent({ | |||
| 				type: 'label', | ||||
| 				text: this.path, | ||||
| 			}, { | ||||
| 				icon: faExpandAlt, | ||||
| 				icon: 'fas fa-expand-alt', | ||||
| 				text: this.$ts.showInPage, | ||||
| 				action: this.expand | ||||
| 			}, this.sideViewHook ? { | ||||
| 				icon: faColumns, | ||||
| 				icon: 'fas fa-columns', | ||||
| 				text: this.$ts.openInSideView, | ||||
| 				action: () => { | ||||
| 					this.sideViewHook(this.path); | ||||
| 					this.$refs.window.close(); | ||||
| 				} | ||||
| 			} : undefined, { | ||||
| 				icon: faExternalLinkAlt, | ||||
| 				icon: 'fas fa-external-link-alt', | ||||
| 				text: this.$ts.popout, | ||||
| 				action: this.popout | ||||
| 			}, null, { | ||||
| 				icon: faExternalLinkAlt, | ||||
| 				icon: 'fas fa-external-link-alt', | ||||
| 				text: this.$ts.openInNewTab, | ||||
| 				action: () => { | ||||
| 					window.open(this.url, '_blank'); | ||||
| 					this.$refs.window.close(); | ||||
| 				} | ||||
| 			}, { | ||||
| 				icon: faLink, | ||||
| 				icon: 'fas fa-link', | ||||
| 				text: this.$ts.copyLink, | ||||
| 				action: () => { | ||||
| 					copyToClipboard(this.url); | ||||
|  | @ -150,6 +149,10 @@ export default defineComponent({ | |||
| 			popout(this.path, this.$el); | ||||
| 			this.$refs.window.close(); | ||||
| 		}, | ||||
| 
 | ||||
| 		onContextmenu(e) { | ||||
| 			os.contextMenu(this.contextmenu, e); | ||||
| 		} | ||||
| 	}, | ||||
| }); | ||||
| </script> | ||||
|  |  | |||
|  | @ -12,7 +12,7 @@ | |||
| 	<XSub :note="appearNote.reply" class="reply-to" v-if="appearNote.reply"/> | ||||
| 	<div class="renote" v-if="isRenote"> | ||||
| 		<MkAvatar class="avatar" :user="note.user"/> | ||||
| 		<Fa :icon="faRetweet"/> | ||||
| 		<i class="fas fa-retweet"></i> | ||||
| 		<I18n :src="$ts.renotedBy" tag="span"> | ||||
| 			<template #user> | ||||
| 				<MkA class="name" :to="userPage(note.user)" v-user-preview="note.userId"> | ||||
|  | @ -22,15 +22,15 @@ | |||
| 		</I18n> | ||||
| 		<div class="info"> | ||||
| 			<button class="_button time" @click="showRenoteMenu()" ref="renoteTime"> | ||||
| 				<Fa class="dropdownIcon" v-if="isMyRenote" :icon="faEllipsisH"/> | ||||
| 				<i v-if="isMyRenote" class="fas fa-ellipsis-h dropdownIcon"></i> | ||||
| 				<MkTime :time="note.createdAt"/> | ||||
| 			</button> | ||||
| 			<span class="visibility" v-if="note.visibility !== 'public'"> | ||||
| 				<Fa v-if="note.visibility === 'home'" :icon="faHome"/> | ||||
| 				<Fa v-if="note.visibility === 'followers'" :icon="faUnlock"/> | ||||
| 				<Fa v-if="note.visibility === 'specified'" :icon="faEnvelope"/> | ||||
| 				<i v-if="note.visibility === 'home'" class="fas fa-home"></i> | ||||
| 				<i v-else-if="note.visibility === 'followers'" class="fas fa-unlock"></i> | ||||
| 				<i v-else-if="note.visibility === 'specified'" class="fas fa-envelope"></i> | ||||
| 			</span> | ||||
| 			<span class="localOnly" v-if="note.localOnly"><Fa :icon="faBiohazard"/></span> | ||||
| 			<span class="localOnly" v-if="note.localOnly"><i class="fas fa-biohazard"></i></span> | ||||
| 		</div> | ||||
| 	</div> | ||||
| 	<article class="article" @contextmenu.stop="onContextmenu"> | ||||
|  | @ -42,14 +42,14 @@ | |||
| 						<MkUserName :user="appearNote.user"/> | ||||
| 					</MkA> | ||||
| 					<span class="is-bot" v-if="appearNote.user.isBot">bot</span> | ||||
| 					<span class="admin" v-if="appearNote.user.isAdmin"><Fa :icon="faBookmark"/></span> | ||||
| 					<span class="moderator" v-if="!appearNote.user.isAdmin && appearNote.user.isModerator"><Fa :icon="farBookmark"/></span> | ||||
| 					<span class="admin" v-if="appearNote.user.isAdmin"><i class="fas fa-bookmark"></i></span> | ||||
| 					<span class="moderator" v-if="!appearNote.user.isAdmin && appearNote.user.isModerator"><i class="far fa-bookmark"></i></span> | ||||
| 					<span class="visibility" v-if="appearNote.visibility !== 'public'"> | ||||
| 						<Fa v-if="appearNote.visibility === 'home'" :icon="faHome"/> | ||||
| 						<Fa v-if="appearNote.visibility === 'followers'" :icon="faUnlock"/> | ||||
| 						<Fa v-if="appearNote.visibility === 'specified'" :icon="faEnvelope"/> | ||||
| 						<i v-if="appearNote.visibility === 'home'" class="fas fa-home"></i> | ||||
| 						<i v-else-if="appearNote.visibility === 'followers'" class="fas fa-unlock"></i> | ||||
| 						<i v-else-if="appearNote.visibility === 'specified'" class="fas fa-envelope"></i> | ||||
| 					</span> | ||||
| 					<span class="localOnly" v-if="appearNote.localOnly"><Fa :icon="faBiohazard"/></span> | ||||
| 					<span class="localOnly" v-if="appearNote.localOnly"><i class="fas fa-biohazard"></i></span> | ||||
| 				</div> | ||||
| 				<div class="username"><MkAcct :user="appearNote.user"/></div> | ||||
| 				<MkInstanceTicker v-if="showTicker" class="ticker" :instance="appearNote.user.instance"/> | ||||
|  | @ -64,7 +64,7 @@ | |||
| 				<div class="content" v-show="appearNote.cw == null || showContent"> | ||||
| 					<div class="text"> | ||||
| 						<span v-if="appearNote.isHidden" style="opacity: 0.5">({{ $ts.private }})</span> | ||||
| 						<MkA class="reply" v-if="appearNote.replyId" :to="`/notes/${appearNote.replyId}`"><Fa :icon="faReply"/></MkA> | ||||
| 						<MkA class="reply" v-if="appearNote.replyId" :to="`/notes/${appearNote.replyId}`"><i class="fas fa-reply"></i></MkA> | ||||
| 						<Mfm v-if="appearNote.text" :text="appearNote.text" :author="appearNote.user" :i="$i" :custom-emojis="appearNote.emojis"/> | ||||
| 						<a class="rp" v-if="appearNote.renote != null">RN:</a> | ||||
| 					</div> | ||||
|  | @ -75,33 +75,33 @@ | |||
| 					<MkUrlPreview v-for="url in urls" :url="url" :key="url" :compact="true" :detail="true" class="url-preview"/> | ||||
| 					<div class="renote" v-if="appearNote.renote"><XNotePreview :note="appearNote.renote"/></div> | ||||
| 				</div> | ||||
| 				<MkA v-if="appearNote.channel && !inChannel" class="channel" :to="`/channels/${appearNote.channel.id}`"><Fa :icon="faSatelliteDish"/> {{ appearNote.channel.name }}</MkA> | ||||
| 				<MkA v-if="appearNote.channel && !inChannel" class="channel" :to="`/channels/${appearNote.channel.id}`"><i class="fas fa-satellite-dish"></i> {{ appearNote.channel.name }}</MkA> | ||||
| 			</div> | ||||
| 			<footer class="footer"> | ||||
| 				<div class="info"> | ||||
| 					<span class="mobile" v-if="note.viaMobile"><Fa :icon="faMobileAlt"/></span> | ||||
| 					<span class="mobile" v-if="note.viaMobile"><i class="fas fa-mobile-alt"></i></span> | ||||
| 					<MkTime class="created-at" :time="note.createdAt" mode="detail"/> | ||||
| 				</div> | ||||
| 				<XReactionsViewer :note="appearNote" ref="reactionsViewer"/> | ||||
| 				<button @click="reply()" class="button _button"> | ||||
| 					<template v-if="appearNote.reply"><Fa :icon="faReplyAll"/></template> | ||||
| 					<template v-else><Fa :icon="faReply"/></template> | ||||
| 					<template v-if="appearNote.reply"><i class="fas fa-reply-all"></i></template> | ||||
| 					<template v-else><i class="fas fa-reply"></i></template> | ||||
| 					<p class="count" v-if="appearNote.repliesCount > 0">{{ appearNote.repliesCount }}</p> | ||||
| 				</button> | ||||
| 				<button v-if="canRenote" @click="renote()" class="button _button" ref="renoteButton"> | ||||
| 					<Fa :icon="faRetweet"/><p class="count" v-if="appearNote.renoteCount > 0">{{ appearNote.renoteCount }}</p> | ||||
| 					<i class="fas fa-retweet"></i><p class="count" v-if="appearNote.renoteCount > 0">{{ appearNote.renoteCount }}</p> | ||||
| 				</button> | ||||
| 				<button v-else class="button _button"> | ||||
| 					<Fa :icon="faBan"/> | ||||
| 					<i class="fas fa-ban"></i> | ||||
| 				</button> | ||||
| 				<button v-if="appearNote.myReaction == null" class="button _button" @click="react()" ref="reactButton"> | ||||
| 					<Fa :icon="faPlus"/> | ||||
| 					<i class="fas fa-plus"></i> | ||||
| 				</button> | ||||
| 				<button v-if="appearNote.myReaction != null" class="button _button reacted" @click="undoReact(appearNote)" ref="reactButton"> | ||||
| 					<Fa :icon="faMinus"/> | ||||
| 					<i class="fas fa-minus"></i> | ||||
| 				</button> | ||||
| 				<button class="button _button" @click="menu()" ref="menuButton"> | ||||
| 					<Fa :icon="faEllipsisH"/> | ||||
| 					<i class="fas fa-ellipsis-h"></i> | ||||
| 				</button> | ||||
| 			</footer> | ||||
| 		</div> | ||||
|  | @ -121,8 +121,6 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineAsyncComponent, defineComponent, markRaw } from 'vue'; | ||||
| import { faSatelliteDish, faBolt, faTimes, faBullhorn, faStar, faLink, faExternalLinkSquareAlt, faPlus, faMinus, faRetweet, faReply, faReplyAll, faEllipsisH, faHome, faUnlock, faEnvelope, faThumbtack, faBan, faQuoteRight, faInfoCircle, faBiohazard, faPlug, faExclamationCircle, faPaperclip, faShareAlt } from '@fortawesome/free-solid-svg-icons'; | ||||
| import { faCopy, faTrashAlt, faEdit, faEye, faEyeSlash } from '@fortawesome/free-regular-svg-icons'; | ||||
| import * as mfm from 'mfm-js'; | ||||
| import { sum } from '../../prelude/array'; | ||||
| import XSub from './note.sub.vue'; | ||||
|  | @ -143,14 +141,6 @@ import { noteActions, noteViewInterruptors } from '@client/store'; | |||
| import { reactionPicker } from '@client/scripts/reaction-picker'; | ||||
| import { extractUrlFromMfm } from '@/misc/extract-url-from-mfm'; | ||||
| 
 | ||||
| function markRawAll(...xs) { | ||||
| 	for (const x of xs) { | ||||
| 		markRaw(x); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| markRawAll(faEdit, faBolt, faTimes, faBullhorn, faPlus, faMinus, faRetweet, faReply, faReplyAll, faEllipsisH, faHome, faUnlock, faEnvelope, faThumbtack, faBan, faBiohazard, faPlug, faSatelliteDish); | ||||
| 
 | ||||
| // TODO: note.vueとほぼ同じなので共通化したい | ||||
| export default defineComponent({ | ||||
| 	components: { | ||||
|  | @ -188,7 +178,6 @@ export default defineComponent({ | |||
| 			showContent: false, | ||||
| 			isDeleted: false, | ||||
| 			muted: false, | ||||
| 			faEdit, faBolt, faTimes, faBullhorn, faPlus, faMinus, faRetweet, faReply, faReplyAll, faEllipsisH, faHome, faUnlock, faEnvelope, faThumbtack, faBan, faBiohazard, faPlug, faSatelliteDish | ||||
| 		}; | ||||
| 	}, | ||||
| 
 | ||||
|  | @ -467,7 +456,7 @@ export default defineComponent({ | |||
| 			this.blur(); | ||||
| 			os.modalMenu([{ | ||||
| 				text: this.$ts.renote, | ||||
| 				icon: faRetweet, | ||||
| 				icon: 'fas fa-retweet', | ||||
| 				action: () => { | ||||
| 					os.api('notes/create', { | ||||
| 						renoteId: this.appearNote.id | ||||
|  | @ -475,7 +464,7 @@ export default defineComponent({ | |||
| 				} | ||||
| 			}, { | ||||
| 				text: this.$ts.quote, | ||||
| 				icon: faQuoteRight, | ||||
| 				icon: 'fas fa-quote-right', | ||||
| 				action: () => { | ||||
| 					os.post({ | ||||
| 						renote: this.appearNote, | ||||
|  | @ -611,62 +600,62 @@ export default defineComponent({ | |||
| 				}); | ||||
| 
 | ||||
| 				menu = [{ | ||||
| 					icon: faCopy, | ||||
| 					icon: 'fas fa-copy', | ||||
| 					text: this.$ts.copyContent, | ||||
| 					action: this.copyContent | ||||
| 				}, { | ||||
| 					icon: faLink, | ||||
| 					icon: 'fas fa-link', | ||||
| 					text: this.$ts.copyLink, | ||||
| 					action: this.copyLink | ||||
| 				}, (this.appearNote.url || this.appearNote.uri) ? { | ||||
| 					icon: faExternalLinkSquareAlt, | ||||
| 					icon: 'fas fa-external-link-square-alt', | ||||
| 					text: this.$ts.showOnRemote, | ||||
| 					action: () => { | ||||
| 						window.open(this.appearNote.url || this.appearNote.uri, '_blank'); | ||||
| 					} | ||||
| 				} : undefined, | ||||
| 				{ | ||||
| 					icon: faShareAlt, | ||||
| 					icon: 'fas fa-share-alt', | ||||
| 					text: this.$ts.share, | ||||
| 					action: this.share | ||||
| 				}, | ||||
| 				null, | ||||
| 				statePromise.then(state => state.isFavorited ? { | ||||
| 					icon: faStar, | ||||
| 					icon: 'fas fa-star', | ||||
| 					text: this.$ts.unfavorite, | ||||
| 					action: () => this.toggleFavorite(false) | ||||
| 				} : { | ||||
| 					icon: faStar, | ||||
| 					icon: 'fas fa-star', | ||||
| 					text: this.$ts.favorite, | ||||
| 					action: () => this.toggleFavorite(true) | ||||
| 				}), | ||||
| 				{ | ||||
| 					icon: faPaperclip, | ||||
| 					icon: 'fas fa-paperclip', | ||||
| 					text: this.$ts.clip, | ||||
| 					action: () => this.clip() | ||||
| 				}, | ||||
| 				(this.appearNote.userId != this.$i.id) ? statePromise.then(state => state.isWatching ? { | ||||
| 					icon: faEyeSlash, | ||||
| 					icon: 'fas fa-eye-slash', | ||||
| 					text: this.$ts.unwatch, | ||||
| 					action: () => this.toggleWatch(false) | ||||
| 				} : { | ||||
| 					icon: faEye, | ||||
| 					icon: 'fas fa-eye', | ||||
| 					text: this.$ts.watch, | ||||
| 					action: () => this.toggleWatch(true) | ||||
| 				}) : undefined, | ||||
| 				this.appearNote.userId == this.$i.id ? (this.$i.pinnedNoteIds || []).includes(this.appearNote.id) ? { | ||||
| 					icon: faThumbtack, | ||||
| 					icon: 'fas fa-thumbtack', | ||||
| 					text: this.$ts.unpin, | ||||
| 					action: () => this.togglePin(false) | ||||
| 				} : { | ||||
| 					icon: faThumbtack, | ||||
| 					icon: 'fas fa-thumbtack', | ||||
| 					text: this.$ts.pin, | ||||
| 					action: () => this.togglePin(true) | ||||
| 				} : undefined, | ||||
| 				...(this.$i.isModerator || this.$i.isAdmin ? [ | ||||
| 					null, | ||||
| 					{ | ||||
| 						icon: faBullhorn, | ||||
| 						icon: 'fas fa-bullhorn', | ||||
| 						text: this.$ts.promote, | ||||
| 						action: this.promote | ||||
| 					}] | ||||
|  | @ -675,7 +664,7 @@ export default defineComponent({ | |||
| 				...(this.appearNote.userId != this.$i.id ? [ | ||||
| 					null, | ||||
| 					{ | ||||
| 						icon: faExclamationCircle, | ||||
| 						icon: 'fas fa-exclamation-circle', | ||||
| 						text: this.$ts.reportAbuse, | ||||
| 						action: () => { | ||||
| 							const u = `${url}/notes/${this.appearNote.id}`; | ||||
|  | @ -690,12 +679,12 @@ export default defineComponent({ | |||
| 				...(this.appearNote.userId == this.$i.id || this.$i.isModerator || this.$i.isAdmin ? [ | ||||
| 					null, | ||||
| 					this.appearNote.userId == this.$i.id ? { | ||||
| 						icon: faEdit, | ||||
| 						icon: 'fas fa-edit', | ||||
| 						text: this.$ts.deleteAndEdit, | ||||
| 						action: this.delEdit | ||||
| 					} : undefined, | ||||
| 					{ | ||||
| 						icon: faTrashAlt, | ||||
| 						icon: 'fas fa-trash-alt', | ||||
| 						text: this.$ts.delete, | ||||
| 						danger: true, | ||||
| 						action: this.del | ||||
|  | @ -705,15 +694,15 @@ export default defineComponent({ | |||
| 				.filter(x => x !== undefined); | ||||
| 			} else { | ||||
| 				menu = [{ | ||||
| 					icon: faCopy, | ||||
| 					icon: 'fas fa-copy', | ||||
| 					text: this.$ts.copyContent, | ||||
| 					action: this.copyContent | ||||
| 				}, { | ||||
| 					icon: faLink, | ||||
| 					icon: 'fas fa-link', | ||||
| 					text: this.$ts.copyLink, | ||||
| 					action: this.copyLink | ||||
| 				}, (this.appearNote.url || this.appearNote.uri) ? { | ||||
| 					icon: faExternalLinkSquareAlt, | ||||
| 					icon: 'fas fa-external-link-square-alt', | ||||
| 					text: this.$ts.showOnRemote, | ||||
| 					action: () => { | ||||
| 						window.open(this.appearNote.url || this.appearNote.uri, '_blank'); | ||||
|  | @ -724,7 +713,7 @@ export default defineComponent({ | |||
| 
 | ||||
| 			if (noteActions.length > 0) { | ||||
| 				menu = menu.concat([null, ...noteActions.map(action => ({ | ||||
| 					icon: faPlug, | ||||
| 					icon: 'fas fa-plug', | ||||
| 					text: action.title, | ||||
| 					action: () => { | ||||
| 						action.handler(this.appearNote); | ||||
|  | @ -763,7 +752,7 @@ export default defineComponent({ | |||
| 			if (!this.isMyRenote) return; | ||||
| 			os.modalMenu([{ | ||||
| 				text: this.$ts.unrenote, | ||||
| 				icon: faTrashAlt, | ||||
| 				icon: 'fas fa-trash-alt', | ||||
| 				danger: true, | ||||
| 				action: () => { | ||||
| 					os.api('notes/delete', { | ||||
|  | @ -806,7 +795,7 @@ export default defineComponent({ | |||
| 		async clip() { | ||||
| 			const clips = await os.api('clips/list'); | ||||
| 			os.modalMenu([{ | ||||
| 				icon: faPlus, | ||||
| 				icon: 'fas fa-plus', | ||||
| 				text: this.$ts.createNew, | ||||
| 				action: async () => { | ||||
| 					const { canceled, result } = await os.form(this.$ts.createNewClip, { | ||||
|  | @ -943,7 +932,7 @@ export default defineComponent({ | |||
| 			border-radius: 6px; | ||||
| 		} | ||||
| 
 | ||||
| 		> [data-icon] { | ||||
| 		> i { | ||||
| 			margin-right: 4px; | ||||
| 		} | ||||
| 
 | ||||
|  |  | |||
|  | @ -5,27 +5,25 @@ | |||
| 	</MkA> | ||||
| 	<span class="is-bot" v-if="note.user.isBot">bot</span> | ||||
| 	<span class="username"><MkAcct :user="note.user"/></span> | ||||
| 	<span class="admin" v-if="note.user.isAdmin"><Fa :icon="faBookmark"/></span> | ||||
| 	<span class="moderator" v-if="!note.user.isAdmin && note.user.isModerator"><Fa :icon="farBookmark"/></span> | ||||
| 	<span class="admin" v-if="note.user.isAdmin"><i class="fas fa-bookmark"></i></span> | ||||
| 	<span class="moderator" v-if="!note.user.isAdmin && note.user.isModerator"><i class="far fa-bookmark"></i></span> | ||||
| 	<div class="info"> | ||||
| 		<span class="mobile" v-if="note.viaMobile"><Fa :icon="faMobileAlt"/></span> | ||||
| 		<span class="mobile" v-if="note.viaMobile"><i class="fas fa-mobile-alt"></i></span> | ||||
| 		<MkA class="created-at" :to="notePage(note)"> | ||||
| 			<MkTime :time="note.createdAt"/> | ||||
| 		</MkA> | ||||
| 		<span class="visibility" v-if="note.visibility !== 'public'"> | ||||
| 			<Fa v-if="note.visibility === 'home'" :icon="faHome"/> | ||||
| 			<Fa v-if="note.visibility === 'followers'" :icon="faUnlock"/> | ||||
| 			<Fa v-if="note.visibility === 'specified'" :icon="faEnvelope"/> | ||||
| 			<i v-if="note.visibility === 'home'" class="fas fa-home"></i> | ||||
| 			<i v-else-if="note.visibility === 'followers'" class="fas fa-unlock"></i> | ||||
| 			<i v-else-if="note.visibility === 'specified'" class="fas fa-envelope"></i> | ||||
| 		</span> | ||||
| 		<span class="localOnly" v-if="note.localOnly"><Fa :icon="faBiohazard"/></span> | ||||
| 		<span class="localOnly" v-if="note.localOnly"><i class="fas fa-biohazard"></i></span> | ||||
| 	</div> | ||||
| </header> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { faHome, faUnlock, faEnvelope, faMobileAlt, faBookmark, faBiohazard } from '@fortawesome/free-solid-svg-icons'; | ||||
| import { faBookmark as farBookmark } from '@fortawesome/free-regular-svg-icons'; | ||||
| import notePage from '../filters/note'; | ||||
| import { userPage } from '../filters/user'; | ||||
| import * as os from '@client/os'; | ||||
|  | @ -40,7 +38,6 @@ export default defineComponent({ | |||
| 
 | ||||
| 	data() { | ||||
| 		return { | ||||
| 			faHome, faUnlock, faEnvelope, faMobileAlt, faBookmark, farBookmark, faBiohazard | ||||
| 		}; | ||||
| 	}, | ||||
| 
 | ||||
|  |  | |||
|  | @ -9,12 +9,12 @@ | |||
| 	v-size="{ max: [500, 450, 350, 300] }" | ||||
| > | ||||
| 	<XSub :note="appearNote.reply" class="reply-to" v-if="appearNote.reply"/> | ||||
| 	<div class="info" v-if="pinned"><Fa :icon="faThumbtack"/> {{ $ts.pinnedNote }}</div> | ||||
| 	<div class="info" v-if="appearNote._prId_"><Fa :icon="faBullhorn"/> {{ $ts.promotion }}<button class="_textButton hide" @click="readPromo()">{{ $ts.hideThisNote }} <Fa :icon="faTimes"/></button></div> | ||||
| 	<div class="info" v-if="appearNote._featuredId_"><Fa :icon="faBolt"/> {{ $ts.featured }}</div> | ||||
| 	<div class="info" v-if="pinned"><i class="fas fa-thumbtack"></i> {{ $ts.pinnedNote }}</div> | ||||
| 	<div class="info" v-if="appearNote._prId_"><i class="fas fa-bullhorn"></i> {{ $ts.promotion }}<button class="_textButton hide" @click="readPromo()">{{ $ts.hideThisNote }} <i class="fas fa-times"></i></button></div> | ||||
| 	<div class="info" v-if="appearNote._featuredId_"><i class="fas fa-bolt"></i> {{ $ts.featured }}</div> | ||||
| 	<div class="renote" v-if="isRenote"> | ||||
| 		<MkAvatar class="avatar" :user="note.user"/> | ||||
| 		<Fa :icon="faRetweet"/> | ||||
| 		<i class="fas fa-retweet"></i> | ||||
| 		<I18n :src="$ts.renotedBy" tag="span"> | ||||
| 			<template #user> | ||||
| 				<MkA class="name" :to="userPage(note.user)" v-user-preview="note.userId"> | ||||
|  | @ -24,15 +24,15 @@ | |||
| 		</I18n> | ||||
| 		<div class="info"> | ||||
| 			<button class="_button time" @click="showRenoteMenu()" ref="renoteTime"> | ||||
| 				<Fa class="dropdownIcon" v-if="isMyRenote" :icon="faEllipsisH"/> | ||||
| 				<i v-if="isMyRenote" class="fas fa-ellipsis-h dropdownIcon"></i> | ||||
| 				<MkTime :time="note.createdAt"/> | ||||
| 			</button> | ||||
| 			<span class="visibility" v-if="note.visibility !== 'public'"> | ||||
| 				<Fa v-if="note.visibility === 'home'" :icon="faHome"/> | ||||
| 				<Fa v-if="note.visibility === 'followers'" :icon="faUnlock"/> | ||||
| 				<Fa v-if="note.visibility === 'specified'" :icon="faEnvelope"/> | ||||
| 				<i v-if="note.visibility === 'home'" class="fas fa-home"></i> | ||||
| 				<i v-else-if="note.visibility === 'followers'" class="fas fa-unlock"></i> | ||||
| 				<i v-else-if="note.visibility === 'specified'" class="fas fa-envelope"></i> | ||||
| 			</span> | ||||
| 			<span class="localOnly" v-if="note.localOnly"><Fa :icon="faBiohazard"/></span> | ||||
| 			<span class="localOnly" v-if="note.localOnly"><i class="fas fa-biohazard"></i></span> | ||||
| 		</div> | ||||
| 	</div> | ||||
| 	<article class="article" @contextmenu.stop="onContextmenu"> | ||||
|  | @ -48,7 +48,7 @@ | |||
| 				<div class="content" :class="{ collapsed }" v-show="appearNote.cw == null || showContent"> | ||||
| 					<div class="text"> | ||||
| 						<span v-if="appearNote.isHidden" style="opacity: 0.5">({{ $ts.private }})</span> | ||||
| 						<MkA class="reply" v-if="appearNote.replyId" :to="`/notes/${appearNote.replyId}`"><Fa :icon="faReply"/></MkA> | ||||
| 						<MkA class="reply" v-if="appearNote.replyId" :to="`/notes/${appearNote.replyId}`"><i class="fas fa-reply"></i></MkA> | ||||
| 						<Mfm v-if="appearNote.text" :text="appearNote.text" :author="appearNote.user" :i="$i" :custom-emojis="appearNote.emojis"/> | ||||
| 						<a class="rp" v-if="appearNote.renote != null">RN:</a> | ||||
| 					</div> | ||||
|  | @ -62,29 +62,29 @@ | |||
| 						<span>{{ $ts.showMore }}</span> | ||||
| 					</button> | ||||
| 				</div> | ||||
| 				<MkA v-if="appearNote.channel && !inChannel" class="channel" :to="`/channels/${appearNote.channel.id}`"><Fa :icon="faSatelliteDish"/> {{ appearNote.channel.name }}</MkA> | ||||
| 				<MkA v-if="appearNote.channel && !inChannel" class="channel" :to="`/channels/${appearNote.channel.id}`"><i class="fas fa-satellite-dish"></i> {{ appearNote.channel.name }}</MkA> | ||||
| 			</div> | ||||
| 			<footer class="footer"> | ||||
| 				<XReactionsViewer :note="appearNote" ref="reactionsViewer"/> | ||||
| 				<button @click="reply()" class="button _button"> | ||||
| 					<template v-if="appearNote.reply"><Fa :icon="faReplyAll"/></template> | ||||
| 					<template v-else><Fa :icon="faReply"/></template> | ||||
| 					<template v-if="appearNote.reply"><i class="fas fa-reply-all"></i></template> | ||||
| 					<template v-else><i class="fas fa-reply"></i></template> | ||||
| 					<p class="count" v-if="appearNote.repliesCount > 0">{{ appearNote.repliesCount }}</p> | ||||
| 				</button> | ||||
| 				<button v-if="canRenote" @click="renote()" class="button _button" ref="renoteButton"> | ||||
| 					<Fa :icon="faRetweet"/><p class="count" v-if="appearNote.renoteCount > 0">{{ appearNote.renoteCount }}</p> | ||||
| 					<i class="fas fa-retweet"></i><p class="count" v-if="appearNote.renoteCount > 0">{{ appearNote.renoteCount }}</p> | ||||
| 				</button> | ||||
| 				<button v-else class="button _button"> | ||||
| 					<Fa :icon="faBan"/> | ||||
| 					<i class="fas fa-ban"></i> | ||||
| 				</button> | ||||
| 				<button v-if="appearNote.myReaction == null" class="button _button" @click="react()" ref="reactButton"> | ||||
| 					<Fa :icon="faPlus"/> | ||||
| 					<i class="fas fa-plus"></i> | ||||
| 				</button> | ||||
| 				<button v-if="appearNote.myReaction != null" class="button _button reacted" @click="undoReact(appearNote)" ref="reactButton"> | ||||
| 					<Fa :icon="faMinus"/> | ||||
| 					<i class="fas fa-minus"></i> | ||||
| 				</button> | ||||
| 				<button class="button _button" @click="menu()" ref="menuButton"> | ||||
| 					<Fa :icon="faEllipsisH"/> | ||||
| 					<i class="fas fa-ellipsis-h"></i> | ||||
| 				</button> | ||||
| 			</footer> | ||||
| 		</div> | ||||
|  | @ -103,8 +103,6 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineAsyncComponent, defineComponent, markRaw } from 'vue'; | ||||
| import { faSatelliteDish, faBolt, faTimes, faBullhorn, faStar, faLink, faExternalLinkSquareAlt, faPlus, faMinus, faRetweet, faReply, faReplyAll, faEllipsisH, faHome, faUnlock, faEnvelope, faThumbtack, faBan, faQuoteRight, faInfoCircle, faBiohazard, faPlug, faExclamationCircle, faPaperclip, faShareAlt } from '@fortawesome/free-solid-svg-icons'; | ||||
| import { faCopy, faTrashAlt, faEdit, faEye, faEyeSlash } from '@fortawesome/free-regular-svg-icons'; | ||||
| import * as mfm from 'mfm-js'; | ||||
| import { sum } from '../../prelude/array'; | ||||
| import XSub from './note.sub.vue'; | ||||
|  | @ -125,14 +123,6 @@ import { noteActions, noteViewInterruptors } from '@client/store'; | |||
| import { reactionPicker } from '@client/scripts/reaction-picker'; | ||||
| import { extractUrlFromMfm } from '@/misc/extract-url-from-mfm'; | ||||
| 
 | ||||
| function markRawAll(...xs) { | ||||
| 	for (const x of xs) { | ||||
| 		markRaw(x); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| markRawAll(faEdit, faBolt, faTimes, faBullhorn, faPlus, faMinus, faRetweet, faReply, faReplyAll, faEllipsisH, faHome, faUnlock, faEnvelope, faThumbtack, faBan, faBiohazard, faPlug, faSatelliteDish); | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	components: { | ||||
| 		XSub, | ||||
|  | @ -174,7 +164,6 @@ export default defineComponent({ | |||
| 			collapsed: false, | ||||
| 			isDeleted: false, | ||||
| 			muted: false, | ||||
| 			faEdit, faBolt, faTimes, faBullhorn, faPlus, faMinus, faRetweet, faReply, faReplyAll, faEllipsisH, faHome, faUnlock, faEnvelope, faThumbtack, faBan, faBiohazard, faPlug, faSatelliteDish | ||||
| 		}; | ||||
| 	}, | ||||
| 
 | ||||
|  | @ -442,7 +431,7 @@ export default defineComponent({ | |||
| 			this.blur(); | ||||
| 			os.modalMenu([{ | ||||
| 				text: this.$ts.renote, | ||||
| 				icon: faRetweet, | ||||
| 				icon: 'fas fa-retweet', | ||||
| 				action: () => { | ||||
| 					os.api('notes/create', { | ||||
| 						renoteId: this.appearNote.id | ||||
|  | @ -450,7 +439,7 @@ export default defineComponent({ | |||
| 				} | ||||
| 			}, { | ||||
| 				text: this.$ts.quote, | ||||
| 				icon: faQuoteRight, | ||||
| 				icon: 'fas fa-quote-right', | ||||
| 				action: () => { | ||||
| 					os.post({ | ||||
| 						renote: this.appearNote, | ||||
|  | @ -586,62 +575,62 @@ export default defineComponent({ | |||
| 				}); | ||||
| 
 | ||||
| 				menu = [{ | ||||
| 					icon: faCopy, | ||||
| 					icon: 'fas fa-copy', | ||||
| 					text: this.$ts.copyContent, | ||||
| 					action: this.copyContent | ||||
| 				}, { | ||||
| 					icon: faLink, | ||||
| 					icon: 'fas fa-link', | ||||
| 					text: this.$ts.copyLink, | ||||
| 					action: this.copyLink | ||||
| 				}, (this.appearNote.url || this.appearNote.uri) ? { | ||||
| 					icon: faExternalLinkSquareAlt, | ||||
| 					icon: 'fas fa-external-link-square-alt', | ||||
| 					text: this.$ts.showOnRemote, | ||||
| 					action: () => { | ||||
| 						window.open(this.appearNote.url || this.appearNote.uri, '_blank'); | ||||
| 					} | ||||
| 				} : undefined, | ||||
| 				{ | ||||
| 					icon: faShareAlt, | ||||
| 					icon: 'fas fa-share-alt', | ||||
| 					text: this.$ts.share, | ||||
| 					action: this.share | ||||
| 				}, | ||||
| 				null, | ||||
| 				statePromise.then(state => state.isFavorited ? { | ||||
| 					icon: faStar, | ||||
| 					icon: 'fas fa-star', | ||||
| 					text: this.$ts.unfavorite, | ||||
| 					action: () => this.toggleFavorite(false) | ||||
| 				} : { | ||||
| 					icon: faStar, | ||||
| 					icon: 'fas fa-star', | ||||
| 					text: this.$ts.favorite, | ||||
| 					action: () => this.toggleFavorite(true) | ||||
| 				}), | ||||
| 				{ | ||||
| 					icon: faPaperclip, | ||||
| 					icon: 'fas fa-paperclip', | ||||
| 					text: this.$ts.clip, | ||||
| 					action: () => this.clip() | ||||
| 				}, | ||||
| 				(this.appearNote.userId != this.$i.id) ? statePromise.then(state => state.isWatching ? { | ||||
| 					icon: faEyeSlash, | ||||
| 					icon: 'fas fa-eye-slash', | ||||
| 					text: this.$ts.unwatch, | ||||
| 					action: () => this.toggleWatch(false) | ||||
| 				} : { | ||||
| 					icon: faEye, | ||||
| 					icon: 'fas fa-eye', | ||||
| 					text: this.$ts.watch, | ||||
| 					action: () => this.toggleWatch(true) | ||||
| 				}) : undefined, | ||||
| 				this.appearNote.userId == this.$i.id ? (this.$i.pinnedNoteIds || []).includes(this.appearNote.id) ? { | ||||
| 					icon: faThumbtack, | ||||
| 					icon: 'fas fa-thumbtack', | ||||
| 					text: this.$ts.unpin, | ||||
| 					action: () => this.togglePin(false) | ||||
| 				} : { | ||||
| 					icon: faThumbtack, | ||||
| 					icon: 'fas fa-thumbtack', | ||||
| 					text: this.$ts.pin, | ||||
| 					action: () => this.togglePin(true) | ||||
| 				} : undefined, | ||||
| 				...(this.$i.isModerator || this.$i.isAdmin ? [ | ||||
| 					null, | ||||
| 					{ | ||||
| 						icon: faBullhorn, | ||||
| 						icon: 'fas fa-bullhorn', | ||||
| 						text: this.$ts.promote, | ||||
| 						action: this.promote | ||||
| 					}] | ||||
|  | @ -650,7 +639,7 @@ export default defineComponent({ | |||
| 				...(this.appearNote.userId != this.$i.id ? [ | ||||
| 					null, | ||||
| 					{ | ||||
| 						icon: faExclamationCircle, | ||||
| 						icon: 'fas fa-exclamation-circle', | ||||
| 						text: this.$ts.reportAbuse, | ||||
| 						action: () => { | ||||
| 							const u = `${url}/notes/${this.appearNote.id}`; | ||||
|  | @ -665,12 +654,12 @@ export default defineComponent({ | |||
| 				...(this.appearNote.userId == this.$i.id || this.$i.isModerator || this.$i.isAdmin ? [ | ||||
| 					null, | ||||
| 					this.appearNote.userId == this.$i.id ? { | ||||
| 						icon: faEdit, | ||||
| 						icon: 'fas fa-edit', | ||||
| 						text: this.$ts.deleteAndEdit, | ||||
| 						action: this.delEdit | ||||
| 					} : undefined, | ||||
| 					{ | ||||
| 						icon: faTrashAlt, | ||||
| 						icon: 'fas fa-trash-alt', | ||||
| 						text: this.$ts.delete, | ||||
| 						danger: true, | ||||
| 						action: this.del | ||||
|  | @ -680,15 +669,15 @@ export default defineComponent({ | |||
| 				.filter(x => x !== undefined); | ||||
| 			} else { | ||||
| 				menu = [{ | ||||
| 					icon: faCopy, | ||||
| 					icon: 'fas fa-copy', | ||||
| 					text: this.$ts.copyContent, | ||||
| 					action: this.copyContent | ||||
| 				}, { | ||||
| 					icon: faLink, | ||||
| 					icon: 'fas fa-link', | ||||
| 					text: this.$ts.copyLink, | ||||
| 					action: this.copyLink | ||||
| 				}, (this.appearNote.url || this.appearNote.uri) ? { | ||||
| 					icon: faExternalLinkSquareAlt, | ||||
| 					icon: 'fas fa-external-link-square-alt', | ||||
| 					text: this.$ts.showOnRemote, | ||||
| 					action: () => { | ||||
| 						window.open(this.appearNote.url || this.appearNote.uri, '_blank'); | ||||
|  | @ -699,7 +688,7 @@ export default defineComponent({ | |||
| 
 | ||||
| 			if (noteActions.length > 0) { | ||||
| 				menu = menu.concat([null, ...noteActions.map(action => ({ | ||||
| 					icon: faPlug, | ||||
| 					icon: 'fas fa-plug', | ||||
| 					text: action.title, | ||||
| 					action: () => { | ||||
| 						action.handler(this.appearNote); | ||||
|  | @ -738,7 +727,7 @@ export default defineComponent({ | |||
| 			if (!this.isMyRenote) return; | ||||
| 			os.modalMenu([{ | ||||
| 				text: this.$ts.unrenote, | ||||
| 				icon: faTrashAlt, | ||||
| 				icon: 'fas fa-trash-alt', | ||||
| 				danger: true, | ||||
| 				action: () => { | ||||
| 					os.api('notes/delete', { | ||||
|  | @ -781,7 +770,7 @@ export default defineComponent({ | |||
| 		async clip() { | ||||
| 			const clips = await os.api('clips/list'); | ||||
| 			os.modalMenu([{ | ||||
| 				icon: faPlus, | ||||
| 				icon: 'fas fa-plus', | ||||
| 				text: this.$ts.createNew, | ||||
| 				action: async () => { | ||||
| 					const { canceled, result } = await os.form(this.$ts.createNewClip, { | ||||
|  | @ -909,7 +898,7 @@ export default defineComponent({ | |||
| 		white-space: pre; | ||||
| 		color: #d28a3f; | ||||
| 
 | ||||
| 		> [data-icon] { | ||||
| 		> i { | ||||
| 			margin-right: 4px; | ||||
| 		} | ||||
| 
 | ||||
|  | @ -945,7 +934,7 @@ export default defineComponent({ | |||
| 			border-radius: 6px; | ||||
| 		} | ||||
| 
 | ||||
| 		> [data-icon] { | ||||
| 		> i { | ||||
| 			margin-right: 4px; | ||||
| 		} | ||||
| 
 | ||||
|  |  | |||
|  | @ -4,15 +4,15 @@ | |||
| 		<MkAvatar v-if="notification.user" class="icon" :user="notification.user"/> | ||||
| 		<img v-else-if="notification.icon" class="icon" :src="notification.icon" alt=""/> | ||||
| 		<div class="sub-icon" :class="notification.type"> | ||||
| 			<Fa :icon="faPlus" v-if="notification.type === 'follow'"/> | ||||
| 			<Fa :icon="faClock" v-else-if="notification.type === 'receiveFollowRequest'"/> | ||||
| 			<Fa :icon="faCheck" v-else-if="notification.type === 'followRequestAccepted'"/> | ||||
| 			<Fa :icon="faIdCardAlt" v-else-if="notification.type === 'groupInvited'"/> | ||||
| 			<Fa :icon="faRetweet" v-else-if="notification.type === 'renote'"/> | ||||
| 			<Fa :icon="faReply" v-else-if="notification.type === 'reply'"/> | ||||
| 			<Fa :icon="faAt" v-else-if="notification.type === 'mention'"/> | ||||
| 			<Fa :icon="faQuoteLeft" v-else-if="notification.type === 'quote'"/> | ||||
| 			<Fa :icon="faPollH" v-else-if="notification.type === 'pollVote'"/> | ||||
| 			<i v-if="notification.type === 'follow'" class="fas fa-plus"></i> | ||||
| 			<i v-else-if="notification.type === 'receiveFollowRequest'" class="fas fa-clock"></i> | ||||
| 			<i v-else-if="notification.type === 'followRequestAccepted'" class="fas fa-check"></i> | ||||
| 			<i v-else-if="notification.type === 'groupInvited'" class="fas fa-id-card-alt"></i> | ||||
| 			<i v-else-if="notification.type === 'renote'" class="fas fa-retweet"></i> | ||||
| 			<i v-else-if="notification.type === 'reply'" class="fas fa-reply"></i> | ||||
| 			<i v-else-if="notification.type === 'mention'" class="fas fa-at"></i> | ||||
| 			<i v-else-if="notification.type === 'quote'" class="fas fa-quote-left"></i> | ||||
| 			<i v-else-if="notification.type === 'pollVote'" class="fas fa-poll-h"></i> | ||||
| 			<XReactionIcon v-else-if="notification.type === 'reaction'" :reaction="notification.reaction" :custom-emojis="notification.note.emojis" :no-style="true"/> | ||||
| 		</div> | ||||
| 	</div> | ||||
|  | @ -23,14 +23,14 @@ | |||
| 			<MkTime :time="notification.createdAt" v-if="withTime" class="time"/> | ||||
| 		</header> | ||||
| 		<MkA v-if="notification.type === 'reaction'" class="text" :to="notePage(notification.note)" :title="getNoteSummary(notification.note)"> | ||||
| 			<Fa :icon="faQuoteLeft"/> | ||||
| 			<i class="fas fa-quote-left"></i> | ||||
| 			<Mfm :text="getNoteSummary(notification.note)" :plain="true" :nowrap="!full" :custom-emojis="notification.note.emojis"/> | ||||
| 			<Fa :icon="faQuoteRight"/> | ||||
| 			<i class="fas fa-quote-right"></i> | ||||
| 		</MkA> | ||||
| 		<MkA v-if="notification.type === 'renote'" class="text" :to="notePage(notification.note)" :title="getNoteSummary(notification.note.renote)"> | ||||
| 			<Fa :icon="faQuoteLeft"/> | ||||
| 			<i class="fas fa-quote-left"></i> | ||||
| 			<Mfm :text="getNoteSummary(notification.note.renote)" :plain="true" :nowrap="!full" :custom-emojis="notification.note.renote.emojis"/> | ||||
| 			<Fa :icon="faQuoteRight"/> | ||||
| 			<i class="fas fa-quote-right"></i> | ||||
| 		</MkA> | ||||
| 		<MkA v-if="notification.type === 'reply'" class="text" :to="notePage(notification.note)" :title="getNoteSummary(notification.note)"> | ||||
| 			<Mfm :text="getNoteSummary(notification.note)" :plain="true" :nowrap="!full" :custom-emojis="notification.note.emojis"/> | ||||
|  | @ -42,9 +42,9 @@ | |||
| 			<Mfm :text="getNoteSummary(notification.note)" :plain="true" :nowrap="!full" :custom-emojis="notification.note.emojis"/> | ||||
| 		</MkA> | ||||
| 		<MkA v-if="notification.type === 'pollVote'" class="text" :to="notePage(notification.note)" :title="getNoteSummary(notification.note)"> | ||||
| 			<Fa :icon="faQuoteLeft"/> | ||||
| 			<i class="fas fa-quote-left"></i> | ||||
| 			<Mfm :text="getNoteSummary(notification.note)" :plain="true" :nowrap="!full" :custom-emojis="notification.note.emojis"/> | ||||
| 			<Fa :icon="faQuoteRight"/> | ||||
| 			<i class="fas fa-quote-right"></i> | ||||
| 		</MkA> | ||||
| 		<span v-if="notification.type === 'follow'" class="text" style="opacity: 0.6;">{{ $ts.youGotNewFollower }}<div v-if="full"><MkFollowButton :user="notification.user" :full="true"/></div></span> | ||||
| 		<span v-if="notification.type === 'followRequestAccepted'" class="text" style="opacity: 0.6;">{{ $ts.followRequestAccepted }}</span> | ||||
|  | @ -59,8 +59,6 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { faIdCardAlt, faPlus, faQuoteLeft, faQuoteRight, faRetweet, faReply, faAt, faCheck, faPollH } from '@fortawesome/free-solid-svg-icons'; | ||||
| import { faClock } from '@fortawesome/free-regular-svg-icons'; | ||||
| import { getNoteSummary } from '@/misc/get-note-summary'; | ||||
| import XReactionIcon from './reaction-icon.vue'; | ||||
| import MkFollowButton from './follow-button.vue'; | ||||
|  | @ -96,7 +94,6 @@ export default defineComponent({ | |||
| 			groupInviteDone: false, | ||||
| 			connection: null, | ||||
| 			readObserver: null, | ||||
| 			faIdCardAlt, faPlus, faQuoteLeft, faQuoteRight, faRetweet, faReply, faAt, faClock, faCheck, faPollH | ||||
| 		}; | ||||
| 	}, | ||||
| 
 | ||||
|  | @ -271,17 +268,17 @@ export default defineComponent({ | |||
| 			overflow: hidden; | ||||
| 			text-overflow: ellipsis; | ||||
| 
 | ||||
| 			> [data-icon] { | ||||
| 			> i { | ||||
| 				vertical-align: super; | ||||
| 				font-size: 50%; | ||||
| 				opacity: 0.5; | ||||
| 			} | ||||
| 
 | ||||
| 			> [data-icon]:first-child { | ||||
| 			> i:first-child { | ||||
| 				margin-right: 4px; | ||||
| 			} | ||||
| 
 | ||||
| 			> [data-icon]:last-child { | ||||
| 			> i:last-child { | ||||
| 				margin-left: 4px; | ||||
| 			} | ||||
| 		} | ||||
|  |  | |||
|  | @ -11,7 +11,7 @@ | |||
| 		<XHeader :info="pageInfo" :with-back="false"/> | ||||
| 	</template> | ||||
| 	<template #buttons> | ||||
| 		<button class="_button" @click="back()" v-if="history.length > 0"><Fa :icon="faChevronLeft"/></button> | ||||
| 		<button class="_button" @click="back()" v-if="history.length > 0"><i class="fas fa-chevron-left"></i></button> | ||||
| 		<button class="_button" style="pointer-events: none;" v-else><!-- マージンのバランスを取るためのダミー --></button> | ||||
| 	</template> | ||||
| 	<div class="yrolvcoq _flat_"> | ||||
|  | @ -22,7 +22,6 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { faExternalLinkAlt, faExpandAlt, faLink, faChevronLeft, faColumns } from '@fortawesome/free-solid-svg-icons'; | ||||
| import XWindow from '@client/components/ui/window.vue'; | ||||
| import XHeader from '@client/ui/_common_/header.vue'; | ||||
| import { popout } from '@client/scripts/popout'; | ||||
|  | @ -76,7 +75,6 @@ export default defineComponent({ | |||
| 			component: this.initialComponent, | ||||
| 			props: this.initialProps, | ||||
| 			history: [], | ||||
| 			faChevronLeft, | ||||
| 		}; | ||||
| 	}, | ||||
| 
 | ||||
|  | @ -90,29 +88,29 @@ export default defineComponent({ | |||
| 				type: 'label', | ||||
| 				text: this.path, | ||||
| 			}, { | ||||
| 				icon: faExpandAlt, | ||||
| 				icon: 'fas fa-expand-alt', | ||||
| 				text: this.$ts.showInPage, | ||||
| 				action: this.expand | ||||
| 			}, this.sideViewHook ? { | ||||
| 				icon: faColumns, | ||||
| 				icon: 'fas fa-columns', | ||||
| 				text: this.$ts.openInSideView, | ||||
| 				action: () => { | ||||
| 					this.sideViewHook(this.path); | ||||
| 					this.$refs.window.close(); | ||||
| 				} | ||||
| 			} : undefined, { | ||||
| 				icon: faExternalLinkAlt, | ||||
| 				icon: 'fas fa-external-link-alt', | ||||
| 				text: this.$ts.popout, | ||||
| 				action: this.popout | ||||
| 			}, null, { | ||||
| 				icon: faExternalLinkAlt, | ||||
| 				icon: 'fas fa-external-link-alt', | ||||
| 				text: this.$ts.openInNewTab, | ||||
| 				action: () => { | ||||
| 					window.open(this.url, '_blank'); | ||||
| 					this.$refs.window.close(); | ||||
| 				} | ||||
| 			}, { | ||||
| 				icon: faLink, | ||||
| 				icon: 'fas fa-link', | ||||
| 				text: this.$ts.copyLink, | ||||
| 				action: () => { | ||||
| 					copyToClipboard(this.url); | ||||
|  |  | |||
|  | @ -1,13 +1,15 @@ | |||
| <template> | ||||
| <div class="ngbfujlo"> | ||||
| 	<MkTextarea :value="text" readonly style="margin: 0;"></MkTextarea> | ||||
| 	<MkButton class="button" primary @click="post()" :disabled="posting || posted"><Fa v-if="posted" :icon="faCheck"/><Fa v-else :icon="faPaperPlane"/></MkButton> | ||||
| 	<MkButton class="button" primary @click="post()" :disabled="posting || posted"> | ||||
| 		<i v-if="posted" class="fas fa-check"></i> | ||||
| 		<i v-else class="fas fa-paper-plane"></i> | ||||
| 	</MkButton> | ||||
| </div> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent, PropType } from 'vue'; | ||||
| import { faCheck, faPaperPlane } from '@fortawesome/free-solid-svg-icons'; | ||||
| import MkTextarea from '../ui/textarea.vue'; | ||||
| import MkButton from '../ui/button.vue'; | ||||
| import { apiUrl } from '@client/config'; | ||||
|  | @ -35,7 +37,6 @@ export default defineComponent({ | |||
| 			text: this.hpml.interpolate(this.block.text), | ||||
| 			posted: false, | ||||
| 			posting: false, | ||||
| 			faCheck, faPaperPlane | ||||
| 		}; | ||||
| 	}, | ||||
| 	watch: { | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| <template> | ||||
| <div class="zmdxowus"> | ||||
| 	<p class="caution" v-if="choices.length < 2"> | ||||
| 		<Fa :icon="faExclamationTriangle"/>{{ $ts._poll.noOnlyOneChoice }} | ||||
| 		<i class="fas fa-exclamation-triangle"></i>{{ $ts._poll.noOnlyOneChoice }} | ||||
| 	</p> | ||||
| 	<ul ref="choices"> | ||||
| 		<li v-for="(choice, i) in choices" :key="i"> | ||||
|  | @ -9,7 +9,7 @@ | |||
| 				<span>{{ $t('_poll.choiceN', { n: i + 1 }) }}</span> | ||||
| 			</MkInput> | ||||
| 			<button @click="remove(i)" class="_button"> | ||||
| 				<Fa :icon="faTimes"/> | ||||
| 				<i class="fas fa-times"></i> | ||||
| 			</button> | ||||
| 		</li> | ||||
| 	</ul> | ||||
|  | @ -50,7 +50,6 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { faExclamationTriangle, faTimes } from '@fortawesome/free-solid-svg-icons'; | ||||
| import { addTime } from '../../prelude/time'; | ||||
| import { formatDateTimeString } from '@/misc/format-time-string'; | ||||
| import MkInput from './ui/input.vue'; | ||||
|  | @ -84,7 +83,6 @@ export default defineComponent({ | |||
| 			atTime: '00:00', | ||||
| 			after: 0, | ||||
| 			unit: 'second', | ||||
| 			faExclamationTriangle, faTimes | ||||
| 		}; | ||||
| 	}, | ||||
| 
 | ||||
|  | @ -190,7 +188,7 @@ export default defineComponent({ | |||
| 		font-size: 0.8em; | ||||
| 		color: #f00; | ||||
| 
 | ||||
| 		> [data-icon] { | ||||
| 		> i { | ||||
| 			margin-right: 4px; | ||||
| 		} | ||||
| 	} | ||||
|  |  | |||
|  | @ -4,7 +4,7 @@ | |||
| 		<li v-for="(choice, i) in poll.choices" :key="i" @click="vote(i)" :class="{ voted: choice.voted }"> | ||||
| 			<div class="backdrop" :style="{ 'width': `${showResult ? (choice.votes / total * 100) : 0}%` }"></div> | ||||
| 			<span> | ||||
| 				<template v-if="choice.isVoted"><Fa :icon="faCheck"/></template> | ||||
| 				<template v-if="choice.isVoted"><i class="fas fa-check"></i></template> | ||||
| 				<Mfm :text="choice.text" :plain="true" :custom-emojis="note.emojis"/> | ||||
| 				<span class="votes" v-if="showResult">({{ $t('_poll.votesCount', { n: choice.votes }) }})</span> | ||||
| 			</span> | ||||
|  | @ -23,7 +23,6 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { faCheck } from '@fortawesome/free-solid-svg-icons'; | ||||
| import { sum } from '../../prelude/array'; | ||||
| import * as os from '@client/os'; | ||||
| 
 | ||||
|  | @ -38,7 +37,6 @@ export default defineComponent({ | |||
| 		return { | ||||
| 			remaining: -1, | ||||
| 			showResult: false, | ||||
| 			faCheck | ||||
| 		}; | ||||
| 	}, | ||||
| 	computed: { | ||||
|  | @ -135,7 +133,7 @@ export default defineComponent({ | |||
| 			> span { | ||||
| 				position: relative; | ||||
| 
 | ||||
| 				> [data-icon] { | ||||
| 				> i { | ||||
| 					margin-right: 4px; | ||||
| 				} | ||||
| 
 | ||||
|  |  | |||
|  | @ -5,7 +5,7 @@ | |||
| 			<div @click="showFileMenu(element, $event)" @contextmenu.prevent="showFileMenu(element, $event)"> | ||||
| 				<MkDriveFileThumbnail :data-id="element.id" class="thumbnail" :file="element" fit="cover"/> | ||||
| 				<div class="sensitive" v-if="element.isSensitive"> | ||||
| 					<Fa class="icon" :icon="faExclamationTriangle"/> | ||||
| 					<i class="fas fa-exclamation-triangle icon"></i> | ||||
| 				</div> | ||||
| 			</div> | ||||
| 		</template> | ||||
|  | @ -16,8 +16,6 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent, defineAsyncComponent } from 'vue'; | ||||
| import { faTimesCircle, faEye, faEyeSlash } from '@fortawesome/free-regular-svg-icons'; | ||||
| import { faExclamationTriangle, faICursor } from '@fortawesome/free-solid-svg-icons'; | ||||
| import MkDriveFileThumbnail from './drive-file-thumbnail.vue' | ||||
| import * as os from '@client/os'; | ||||
| 
 | ||||
|  | @ -44,7 +42,6 @@ export default defineComponent({ | |||
| 		return { | ||||
| 			menu: null as Promise<null> | null, | ||||
| 
 | ||||
| 			faExclamationTriangle | ||||
| 		}; | ||||
| 	}, | ||||
| 
 | ||||
|  | @ -100,11 +97,11 @@ export default defineComponent({ | |||
| 				action: () => { this.rename(file) } | ||||
| 			}, { | ||||
| 				text: file.isSensitive ? this.$ts.unmarkAsSensitive : this.$ts.markAsSensitive, | ||||
| 				icon: file.isSensitive ? faEyeSlash : faEye, | ||||
| 				icon: file.isSensitive ? 'fas fa-eye-slash' : 'fas fa-eye', | ||||
| 				action: () => { this.toggleSensitive(file) } | ||||
| 			}, { | ||||
| 				text: this.$ts.attachCancel, | ||||
| 				icon: faTimesCircle, | ||||
| 				icon: 'fas fa-times-circle', | ||||
| 				action: () => { this.detachMedia(file.id) } | ||||
| 			}], ev.currentTarget || ev.target).then(() => this.menu = null); | ||||
| 		} | ||||
|  |  | |||
|  | @ -7,31 +7,31 @@ | |||
| 	@drop.stop="onDrop" | ||||
| > | ||||
| 	<header> | ||||
| 		<button v-if="!fixed" class="cancel _button" @click="cancel"><Fa :icon="faTimes"/></button> | ||||
| 		<button v-if="!fixed" class="cancel _button" @click="cancel"><i class="fas fa-times"></i></button> | ||||
| 		<div> | ||||
| 			<span class="text-count" :class="{ over: textLength > max }">{{ max - textLength }}</span> | ||||
| 			<span class="local-only" v-if="localOnly"><Fa :icon="faBiohazard"/></span> | ||||
| 			<span class="local-only" v-if="localOnly"><i class="fas fa-biohazard"></i></span> | ||||
| 			<button class="_button visibility" @click="setVisibility" ref="visibilityButton" v-tooltip="$ts.visibility" :disabled="channel != null"> | ||||
| 				<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> | ||||
| 				<span v-if="visibility === 'public'"><i class="fas fa-globe"></i></span> | ||||
| 				<span v-if="visibility === 'home'"><i class="fas fa-home"></i></span> | ||||
| 				<span v-if="visibility === 'followers'"><i class="fas fa-unlock"></i></span> | ||||
| 				<span v-if="visibility === 'specified'"><i class="fas fa-envelope"></i></span> | ||||
| 			</button> | ||||
| 			<button class="submit _buttonPrimary" :disabled="!canPost" @click="post">{{ submitText }}<Fa :icon="reply ? faReply : renote ? faQuoteRight : faPaperPlane"/></button> | ||||
| 			<button class="submit _buttonPrimary" :disabled="!canPost" @click="post">{{ submitText }}<i :class="reply ? 'fas fa-reply' : renote ? 'fas fa-quote-right' : 'fas fa-paper-plane'"></i></button> | ||||
| 		</div> | ||||
| 	</header> | ||||
| 	<div class="form" :class="{ fixed }"> | ||||
| 		<XNotePreview class="preview" v-if="reply" :note="reply"/> | ||||
| 		<XNotePreview class="preview" v-if="renote" :note="renote"/> | ||||
| 		<div class="with-quote" v-if="quoteId"><Fa icon="quote-left"/> {{ $ts.quoteAttached }}<button @click="quoteId = null"><Fa icon="times"/></button></div> | ||||
| 		<div class="with-quote" v-if="quoteId"><i class="fas fa-quote-left"></i> {{ $ts.quoteAttached }}<button @click="quoteId = null"><i class="fas fa-times"></i></button></div> | ||||
| 		<div v-if="visibility === 'specified'" class="to-specified"> | ||||
| 			<span style="margin-right: 8px;">{{ $ts.recipient }}</span> | ||||
| 			<div class="visibleUsers"> | ||||
| 				<span v-for="u in visibleUsers" :key="u.id"> | ||||
| 					<MkAcct :user="u"/> | ||||
| 					<button class="_button" @click="removeVisibleUser(u)"><Fa :icon="faTimes"/></button> | ||||
| 					<button class="_button" @click="removeVisibleUser(u)"><i class="fas fa-times"></i></button> | ||||
| 				</span> | ||||
| 				<button @click="addVisibleUser" class="_buttonPrimary"><Fa :icon="faPlus" fixed-width/></button> | ||||
| 				<button @click="addVisibleUser" class="_buttonPrimary"><i class="fas fa-plus fa-fw"></i></button> | ||||
| 			</div> | ||||
| 		</div> | ||||
| 		<MkInfo warn v-if="hasNotSpecifiedMentions" class="hasNotSpecifiedMentions">{{ $ts.notSpecifiedMentionWarning }} - <button class="_textButton" @click="addMissingMention()">{{ $ts.add }}</button></MkInfo> | ||||
|  | @ -40,12 +40,12 @@ | |||
| 		<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> | ||||
| 			<button class="_button" @click="chooseFileFrom" v-tooltip="$ts.attachFile"><Fa :icon="faPhotoVideo"/></button> | ||||
| 			<button class="_button" @click="togglePoll" :class="{ active: poll }" v-tooltip="$ts.poll"><Fa :icon="faPollH"/></button> | ||||
| 			<button class="_button" @click="useCw = !useCw" :class="{ active: useCw }" v-tooltip="$ts.useCw"><Fa :icon="faEyeSlash"/></button> | ||||
| 			<button class="_button" @click="insertMention" v-tooltip="$ts.mention"><Fa :icon="faAt"/></button> | ||||
| 			<button class="_button" @click="insertEmoji" v-tooltip="$ts.emoji"><Fa :icon="faLaughSquint"/></button> | ||||
| 			<button class="_button" @click="showActions" v-tooltip="$ts.plugin" v-if="postFormActions.length > 0"><Fa :icon="faPlug"/></button> | ||||
| 			<button class="_button" @click="chooseFileFrom" v-tooltip="$ts.attachFile"><i class="fas fa-photo-video"></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="insertMention" v-tooltip="$ts.mention"><i class="fas fa-at"></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> | ||||
| 	</div> | ||||
| </div> | ||||
|  | @ -53,8 +53,6 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent, defineAsyncComponent } from 'vue'; | ||||
| import { faReply, faQuoteRight, faPaperPlane, faTimes, faUpload, faPollH, faGlobe, faHome, faUnlock, faEnvelope, faPlus, faPhotoVideo, faAt, faBiohazard, faPlug } from '@fortawesome/free-solid-svg-icons'; | ||||
| import { faEyeSlash, faLaughSquint } from '@fortawesome/free-regular-svg-icons'; | ||||
| import insertTextAtCursor from 'insert-text-at-cursor'; | ||||
| import { length } from 'stringz'; | ||||
| import { toASCII } from 'punycode/'; | ||||
|  | @ -155,7 +153,6 @@ export default defineComponent({ | |||
| 				} | ||||
| 			}), | ||||
| 			postFormActions, | ||||
| 			faReply, faQuoteRight, faPaperPlane, faTimes, faUpload, faPollH, faGlobe, faHome, faUnlock, faEnvelope, faEyeSlash, faLaughSquint, faPlus, faPhotoVideo, faAt, faBiohazard, faPlug | ||||
| 		}; | ||||
| 	}, | ||||
| 
 | ||||
|  | @ -724,7 +721,7 @@ export default defineComponent({ | |||
| 					opacity: 0.7; | ||||
| 				} | ||||
| 
 | ||||
| 				> [data-icon] { | ||||
| 				> i { | ||||
| 					margin-left: 6px; | ||||
| 				} | ||||
| 			} | ||||
|  |  | |||
|  | @ -1,10 +1,9 @@ | |||
| <template> | ||||
| <div class="jmgmzlwq _block"><Fa :icon="faExclamationTriangle" style="margin-right: 8px;"/>{{ $ts.remoteUserCaution }}<a :href="href" rel="nofollow noopener" target="_blank">{{ $ts.showOnRemote }}</a></div> | ||||
| <div class="jmgmzlwq _block"><i class="fas fa-exclamation-triangle" style="margin-right: 8px;"></i>{{ $ts.remoteUserCaution }}<a :href="href" rel="nofollow noopener" target="_blank">{{ $ts.showOnRemote }}</a></div> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons'; | ||||
| import * as os from '@client/os'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
|  | @ -16,7 +15,6 @@ export default defineComponent({ | |||
| 	}, | ||||
| 	data() { | ||||
| 		return { | ||||
| 			faExclamationTriangle | ||||
| 		}; | ||||
| 	} | ||||
| }); | ||||
|  |  | |||
|  | @ -10,7 +10,7 @@ | |||
| 			</MkInput> | ||||
| 			<MkInput v-model:value="password" type="password" :with-password-toggle="true" v-if="!user || user && !user.usePasswordLessLogin" required> | ||||
| 				<span>{{ $ts.password }}</span> | ||||
| 				<template #prefix><Fa :icon="faLock"/></template> | ||||
| 				<template #prefix><i class="fas fa-lock"></i></template> | ||||
| 			</MkInput> | ||||
| 			<MkButton type="submit" primary :disabled="signing" style="margin: 0 auto;">{{ signing ? $ts.loggingIn : $ts.login }}</MkButton> | ||||
| 		</div> | ||||
|  | @ -28,20 +28,20 @@ | |||
| 				<p style="margin-bottom:0;">{{ $ts.twoStepAuthentication }}</p> | ||||
| 				<MkInput v-model:value="password" type="password" :with-password-toggle="true" v-if="user && user.usePasswordLessLogin" required> | ||||
| 					<span>{{ $ts.password }}</span> | ||||
| 					<template #prefix><Fa :icon="faLock"/></template> | ||||
| 					<template #prefix><i class="fas fa-lock"></i></template> | ||||
| 				</MkInput> | ||||
| 				<MkInput v-model:value="token" type="text" pattern="^[0-9]{6}$" autocomplete="off" spellcheck="false" required> | ||||
| 					<span>{{ $ts.token }}</span> | ||||
| 					<template #prefix><Fa :icon="faGavel"/></template> | ||||
| 					<template #prefix><i class="fas fa-gavel"></i></template> | ||||
| 				</MkInput> | ||||
| 				<MkButton type="submit" :disabled="signing" primary style="margin: 0 auto;">{{ signing ? $ts.loggingIn : $ts.login }}</MkButton> | ||||
| 			</div> | ||||
| 		</div> | ||||
| 	</div> | ||||
| 	<div class="social _section"> | ||||
| 		<a class="_borderButton _gap" v-if="meta && meta.enableTwitterIntegration" :href="`${apiUrl}/signin/twitter`"><Fa :icon="faTwitter" style="margin-right: 4px;"/>{{ $t('signinWith', { x: 'Twitter' }) }}</a> | ||||
| 		<a class="_borderButton _gap" v-if="meta && meta.enableGithubIntegration" :href="`${apiUrl}/signin/github`"><Fa :icon="faGithub" style="margin-right: 4px;"/>{{ $t('signinWith', { x: 'GitHub' }) }}</a> | ||||
| 		<a class="_borderButton _gap" v-if="meta && meta.enableDiscordIntegration" :href="`${apiUrl}/signin/discord`"><Fa :icon="faDiscord" style="margin-right: 4px;"/>{{ $t('signinWith', { x: 'Discord' }) }}</a> | ||||
| 		<a class="_borderButton _gap" v-if="meta && meta.enableTwitterIntegration" :href="`${apiUrl}/signin/twitter`"><i class="fab fa-twitter" style="margin-right: 4px;"></i>{{ $t('signinWith', { x: 'Twitter' }) }}</a> | ||||
| 		<a class="_borderButton _gap" v-if="meta && meta.enableGithubIntegration" :href="`${apiUrl}/signin/github`"><i class="fab fa-github" style="margin-right: 4px;"></i>{{ $t('signinWith', { x: 'GitHub' }) }}</a> | ||||
| 		<a class="_borderButton _gap" v-if="meta && meta.enableDiscordIntegration" :href="`${apiUrl}/signin/discord`"><i class="fab fa-discord" style="margin-right: 4px;"></i>{{ $t('signinWith', { x: 'Discord' }) }}</a> | ||||
| 	</div> | ||||
| </form> | ||||
| </template> | ||||
|  | @ -49,8 +49,6 @@ | |||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { toUnicode } from 'punycode/'; | ||||
| import { faLock, faGavel } from '@fortawesome/free-solid-svg-icons'; | ||||
| import { faTwitter, faDiscord, faGithub } from '@fortawesome/free-brands-svg-icons'; | ||||
| import MkButton from './ui/button.vue'; | ||||
| import MkInput from './ui/input.vue'; | ||||
| import { apiUrl, host } from '@client/config'; | ||||
|  | @ -92,7 +90,6 @@ export default defineComponent({ | |||
| 			credential: null, | ||||
| 			challengeData: null, | ||||
| 			queryingKey: false, | ||||
| 			faLock, faGavel, faTwitter, faDiscord, faGithub | ||||
| 		}; | ||||
| 	}, | ||||
| 
 | ||||
|  |  | |||
|  | @ -3,37 +3,37 @@ | |||
| 	<template v-if="meta"> | ||||
| 		<MkInput v-if="meta.disableRegistration" v-model:value="invitationCode" type="text" :autocomplete="Math.random()" spellcheck="false" required> | ||||
| 			<span>{{ $ts.invitationCode }}</span> | ||||
| 			<template #prefix><Fa :icon="faKey"/></template> | ||||
| 			<template #prefix><i class="fas fa-key"></i></template> | ||||
| 		</MkInput> | ||||
| 		<MkInput v-model:value="username" type="text" pattern="^[a-zA-Z0-9_]{1,20}$" :autocomplete="Math.random()" spellcheck="false" required @update:value="onChangeUsername"> | ||||
| 			<span>{{ $ts.username }}</span> | ||||
| 			<template #prefix>@</template> | ||||
| 			<template #suffix>@{{ host }}</template> | ||||
| 			<template #desc> | ||||
| 				<span v-if="usernameState == 'wait'" style="color:#999"><Fa :icon="faSpinner" pulse fixed-width/> {{ $ts.checking }}</span> | ||||
| 				<span v-if="usernameState == 'ok'" style="color:#3CB7B5"><Fa :icon="faCheck" fixed-width/> {{ $ts.available }}</span> | ||||
| 				<span v-if="usernameState == 'unavailable'" style="color:#FF1161"><Fa :icon="faExclamationTriangle" fixed-width/> {{ $ts.unavailable }}</span> | ||||
| 				<span v-if="usernameState == 'error'" style="color:#FF1161"><Fa :icon="faExclamationTriangle" fixed-width/> {{ $ts.error }}</span> | ||||
| 				<span v-if="usernameState == 'invalid-format'" style="color:#FF1161"><Fa :icon="faExclamationTriangle" fixed-width/> {{ $ts.usernameInvalidFormat }}</span> | ||||
| 				<span v-if="usernameState == 'min-range'" style="color:#FF1161"><Fa :icon="faExclamationTriangle" fixed-width/> {{ $ts.tooShort }}</span> | ||||
| 				<span v-if="usernameState == 'max-range'" style="color:#FF1161"><Fa :icon="faExclamationTriangle" fixed-width/> {{ $ts.tooLong }}</span> | ||||
| 				<span v-if="usernameState == 'wait'" style="color:#999"><i class="fas fa-spinner fa-pulse fa-fw"></i> {{ $ts.checking }}</span> | ||||
| 				<span v-if="usernameState == 'ok'" style="color:#3CB7B5"><i class="fas fa-check fa-fw"></i> {{ $ts.available }}</span> | ||||
| 				<span v-if="usernameState == 'unavailable'" style="color:#FF1161"><i class="fas fa-exclamation-triangle fa-fw"></i> {{ $ts.unavailable }}</span> | ||||
| 				<span v-if="usernameState == 'error'" style="color:#FF1161"><i class="fas fa-exclamation-triangle fa-fw"></i> {{ $ts.error }}</span> | ||||
| 				<span v-if="usernameState == 'invalid-format'" style="color:#FF1161"><i class="fas fa-exclamation-triangle fa-fw"></i> {{ $ts.usernameInvalidFormat }}</span> | ||||
| 				<span v-if="usernameState == 'min-range'" style="color:#FF1161"><i class="fas fa-exclamation-triangle fa-fw"></i> {{ $ts.tooShort }}</span> | ||||
| 				<span v-if="usernameState == 'max-range'" style="color:#FF1161"><i class="fas fa-exclamation-triangle fa-fw"></i> {{ $ts.tooLong }}</span> | ||||
| 			</template> | ||||
| 		</MkInput> | ||||
| 		<MkInput v-model:value="password" type="password" :autocomplete="Math.random()" required @update:value="onChangePassword"> | ||||
| 			<span>{{ $ts.password }}</span> | ||||
| 			<template #prefix><Fa :icon="faLock"/></template> | ||||
| 			<template #prefix><i class="fas fa-lock"></i></template> | ||||
| 			<template #desc> | ||||
| 				<p v-if="passwordStrength == 'low'" style="color:#FF1161"><Fa :icon="faExclamationTriangle" fixed-width/> {{ $ts.weakPassword }}</p> | ||||
| 				<p v-if="passwordStrength == 'medium'" style="color:#3CB7B5"><Fa :icon="faCheck" fixed-width/> {{ $ts.normalPassword }}</p> | ||||
| 				<p v-if="passwordStrength == 'high'" style="color:#3CB7B5"><Fa :icon="faCheck" fixed-width/> {{ $ts.strongPassword }}</p> | ||||
| 				<p v-if="passwordStrength == 'low'" style="color:#FF1161"><i class="fas fa-exclamation-triangle fa-fw"></i> {{ $ts.weakPassword }}</p> | ||||
| 				<p v-if="passwordStrength == 'medium'" style="color:#3CB7B5"><i class="fas fa-check fa-fw"></i> {{ $ts.normalPassword }}</p> | ||||
| 				<p v-if="passwordStrength == 'high'" style="color:#3CB7B5"><i class="fas fa-check fa-fw"></i> {{ $ts.strongPassword }}</p> | ||||
| 			</template> | ||||
| 		</MkInput> | ||||
| 		<MkInput v-model:value="retypedPassword" type="password" :autocomplete="Math.random()" required @update:value="onChangePasswordRetype"> | ||||
| 			<span>{{ $ts.password }} ({{ $ts.retype }})</span> | ||||
| 			<template #prefix><Fa :icon="faLock"/></template> | ||||
| 			<template #prefix><i class="fas fa-lock"></i></template> | ||||
| 			<template #desc> | ||||
| 				<p v-if="passwordRetypeState == 'match'" style="color:#3CB7B5"><Fa :icon="faCheck" fixed-width/> {{ $ts.passwordMatched }}</p> | ||||
| 				<p v-if="passwordRetypeState == 'not-match'" style="color:#FF1161"><Fa :icon="faExclamationTriangle" fixed-width/> {{ $ts.passwordNotMatched }}</p> | ||||
| 				<p v-if="passwordRetypeState == 'match'" style="color:#3CB7B5"><i class="fas fa-check fa-fw"></i> {{ $ts.passwordMatched }}</p> | ||||
| 				<p v-if="passwordRetypeState == 'not-match'" style="color:#FF1161"><i class="fas fa-exclamation-triangle fa-fw"></i> {{ $ts.passwordNotMatched }}</p> | ||||
| 			</template> | ||||
| 		</MkInput> | ||||
| 		<label v-if="meta.tosUrl" class="tou"> | ||||
|  | @ -45,7 +45,7 @@ | |||
| 			</I18n> | ||||
| 		</label> | ||||
| 		<captcha v-if="meta.enableHcaptcha" class="captcha" provider="hcaptcha" ref="hcaptcha" v-model:value="hCaptchaResponse" :sitekey="meta.hcaptchaSiteKey"/> | ||||
| 		<captcha v-if="meta.enableRecaptcha" class="captcha" provider="grecaptcha" ref="recaptcha" v-model:value="reCaptchaResponse" :sitekey="meta.recaptchaSiteKey"/> | ||||
| 		<captcha v-if="meta.enableRecaptcha" class="captcha" provider="recaptcha" ref="recaptcha" v-model:value="reCaptchaResponse" :sitekey="meta.recaptchaSiteKey"/> | ||||
| 		<MkButton type="submit" :disabled="shouldDisableSubmitting" primary>{{ $ts.start }}</MkButton> | ||||
| 	</template> | ||||
| </form> | ||||
|  | @ -53,7 +53,6 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent, defineAsyncComponent } from 'vue'; | ||||
| import { faLock, faExclamationTriangle, faSpinner, faCheck, faKey } from '@fortawesome/free-solid-svg-icons'; | ||||
| const getPasswordStrength = require('syuilo-password-strength'); | ||||
| import { toUnicode } from 'punycode/'; | ||||
| import { host, url } from '@client/config'; | ||||
|  | @ -96,7 +95,6 @@ export default defineComponent({ | |||
| 			ToSAgreement: false, | ||||
| 			hCaptchaResponse: null, | ||||
| 			reCaptchaResponse: null, | ||||
| 			faLock, faExclamationTriangle, faSpinner, faCheck, faKey | ||||
| 		} | ||||
| 	}, | ||||
| 
 | ||||
|  |  | |||
|  | @ -3,7 +3,7 @@ | |||
| 	<div class="body"> | ||||
| 		<span v-if="note.isHidden" style="opacity: 0.5">({{ $ts.private }})</span> | ||||
| 		<span v-if="note.deletedAt" style="opacity: 0.5">({{ $ts.deleted }})</span> | ||||
| 		<MkA class="reply" v-if="note.replyId" :to="`/notes/${note.replyId}`"><Fa :icon="faReply"/></MkA> | ||||
| 		<MkA class="reply" v-if="note.replyId" :to="`/notes/${note.replyId}`"><i class="fas fa-reply"></i></MkA> | ||||
| 		<Mfm v-if="note.text" :text="note.text" :author="note.user" :i="$i" :custom-emojis="note.emojis"/> | ||||
| 		<MkA class="rp" v-if="note.renoteId" :to="`/notes/${note.renoteId}`">RN: ...</MkA> | ||||
| 	</div> | ||||
|  | @ -20,7 +20,6 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { faReply } from '@fortawesome/free-solid-svg-icons'; | ||||
| import XPoll from './poll.vue'; | ||||
| import XMediaList from './media-list.vue'; | ||||
| import * as os from '@client/os'; | ||||
|  | @ -38,7 +37,6 @@ export default defineComponent({ | |||
| 	}, | ||||
| 	data() { | ||||
| 		return { | ||||
| 			faReply | ||||
| 		}; | ||||
| 	} | ||||
| }); | ||||
|  |  | |||
|  | @ -29,6 +29,7 @@ export default defineComponent({ | |||
| <style lang="scss"> | ||||
| .pxhvhrfw { | ||||
| 	display: flex; | ||||
| 	font-size: 90%; | ||||
| 
 | ||||
| 	> button { | ||||
| 		flex: 1; | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| <template> | ||||
| <XWindow ref="window" :initial-width="650" :initial-height="420" :can-resize="true" @closed="$emit('closed')"> | ||||
| 	<template #header> | ||||
| 		<Fa :icon="faTerminal" style="margin-right: 0.5em;"/>Task Manager | ||||
| 		<i class="fas fa-terminal" style="margin-right: 0.5em;"></i>Task Manager | ||||
| 	</template> | ||||
| 	<div class="qljqmnzj _monospace"> | ||||
| 		<MkTab v-model:value="tab" style="border-bottom: solid 0.5px var(--divider);"> | ||||
|  | @ -78,7 +78,6 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent, markRaw, onBeforeUnmount, ref, shallowRef } from 'vue'; | ||||
| import { faTerminal } from '@fortawesome/free-solid-svg-icons'; | ||||
| import XWindow from '@client/components/ui/window.vue'; | ||||
| import MkTab from '@client/components/tab.vue'; | ||||
| import MkButton from '@client/components/ui/button.vue'; | ||||
|  | @ -139,7 +138,6 @@ export default defineComponent({ | |||
| 			pools, | ||||
| 			killPopup, | ||||
| 			showReq, | ||||
| 			faTerminal, | ||||
| 		}; | ||||
| 	}, | ||||
| }); | ||||
|  |  | |||
|  | @ -5,8 +5,8 @@ | |||
| 		<div class="sub"> | ||||
| 			<slot name="func"></slot> | ||||
| 			<button class="_button" v-if="foldable" @click="() => showBody = !showBody"> | ||||
| 				<template v-if="showBody"><Fa :icon="faAngleUp"/></template> | ||||
| 				<template v-else><Fa :icon="faAngleDown"/></template> | ||||
| 				<template v-if="showBody"><i class="fas fa-angle-up"></i></template> | ||||
| 				<template v-else><i class="fas fa-angle-down"></i></template> | ||||
| 			</button> | ||||
| 		</div> | ||||
| 	</header> | ||||
|  | @ -28,7 +28,6 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { faAngleUp, faAngleDown } from '@fortawesome/free-solid-svg-icons'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	props: { | ||||
|  | @ -68,7 +67,6 @@ export default defineComponent({ | |||
| 			showBody: this.expanded, | ||||
| 			omitted: null, | ||||
| 			ignoreOmit: false, | ||||
| 			faAngleUp, faAngleDown | ||||
| 		}; | ||||
| 	}, | ||||
| 	mounted() { | ||||
|  | @ -169,7 +167,7 @@ export default defineComponent({ | |||
| 			margin: 0; | ||||
| 			padding: 12px 16px; | ||||
| 
 | ||||
| 			> ::v-deep([data-icon]) { | ||||
| 			> ::v-deep(i) { | ||||
| 				margin-right: 6px; | ||||
| 			} | ||||
| 
 | ||||
|  |  | |||
|  | @ -4,8 +4,8 @@ | |||
| 		<div class="title"><slot name="header"></slot></div> | ||||
| 		<div class="divider"></div> | ||||
| 		<button class="_button"> | ||||
| 			<template v-if="showBody"><Fa :icon="faAngleUp"/></template> | ||||
| 			<template v-else><Fa :icon="faAngleDown"/></template> | ||||
| 			<template v-if="showBody"><i class="fas fa-angle-up"></i></template> | ||||
| 			<template v-else><i class="fas fa-angle-down"></i></template> | ||||
| 		</button> | ||||
| 	</header> | ||||
| 	<transition name="folder-toggle" | ||||
|  | @ -23,7 +23,6 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { faAngleUp, faAngleDown } from '@fortawesome/free-solid-svg-icons'; | ||||
| 
 | ||||
| const localStoragePrefix = 'ui:folder:'; | ||||
| 
 | ||||
|  | @ -43,7 +42,6 @@ export default defineComponent({ | |||
| 	data() { | ||||
| 		return { | ||||
| 			showBody: (this.persistKey && localStorage.getItem(localStoragePrefix + this.persistKey)) ? localStorage.getItem(localStoragePrefix + this.persistKey) === 't' : this.expanded, | ||||
| 			faAngleUp, faAngleDown | ||||
| 		}; | ||||
| 	}, | ||||
| 	watch: { | ||||
|  | @ -109,7 +107,7 @@ export default defineComponent({ | |||
| 			margin: 0; | ||||
| 			padding: 12px 16px 12px 0; | ||||
| 
 | ||||
| 			> [data-icon] { | ||||
| 			> i { | ||||
| 				margin-right: 6px; | ||||
| 			} | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,14 +1,13 @@ | |||
| <template> | ||||
| <div class="fpezltsf" :class="{ warn }"> | ||||
| 	<i v-if="warn"><Fa :icon="faExclamationTriangle"/></i> | ||||
| 	<i v-else><Fa :icon="faInfoCircle"/></i> | ||||
| 	<i v-if="warn" class="fas fa-exclamation-triangle"></i> | ||||
| 	<i v-else class="fas fa-info-circle"></i> | ||||
| 	<slot></slot> | ||||
| </div> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { faInfoCircle, faExclamationTriangle } from '@fortawesome/free-solid-svg-icons'; | ||||
| import * as os from '@client/os'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
|  | @ -21,7 +20,6 @@ export default defineComponent({ | |||
| 	}, | ||||
| 	data() { | ||||
| 		return { | ||||
| 			faInfoCircle, faExclamationTriangle | ||||
| 		}; | ||||
| 	} | ||||
| }); | ||||
|  |  | |||
|  | @ -5,7 +5,7 @@ | |||
| 		<span class="label" ref="labelEl"><slot></slot></span> | ||||
| 		<span class="title" ref="title"> | ||||
| 			<slot name="title"></slot> | ||||
| 			<span class="warning" v-if="invalid"><Fa :icon="faExclamationCircle"/>{{ $refs.input.validationMessage }}</span> | ||||
| 			<span class="warning" v-if="invalid"><i class="fas fa-exclamation-circle"></i>{{ $refs.input.validationMessage }}</span> | ||||
| 		</span> | ||||
| 		<div class="prefix" ref="prefixEl"><slot name="prefix"></slot></div> | ||||
| 		<input v-if="debounce" ref="inputEl" | ||||
|  | @ -56,7 +56,6 @@ | |||
| <script lang="ts"> | ||||
| import { defineComponent, onMounted, onUnmounted, nextTick, ref, watch, computed, toRefs } from 'vue'; | ||||
| import debounce from 'v-debounce'; | ||||
| import { faExclamationCircle } from '@fortawesome/free-solid-svg-icons'; | ||||
| import * as os from '@client/os'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
|  | @ -205,7 +204,6 @@ export default defineComponent({ | |||
| 			focus, | ||||
| 			onInput, | ||||
| 			onKeydown, | ||||
| 			faExclamationCircle, | ||||
| 		}; | ||||
| 	}, | ||||
| }); | ||||
|  |  | |||
|  | @ -13,25 +13,25 @@ | |||
| 			<span><MkEllipsis/></span> | ||||
| 		</span> | ||||
| 		<MkA v-else-if="item.type === 'link'" :to="item.to" @click.passive="close()" :tabindex="i" class="_button item"> | ||||
| 			<Fa v-if="item.icon" :icon="item.icon" fixed-width/> | ||||
| 			<i v-if="item.icon" class="fa-fw" :class="item.icon"></i> | ||||
| 			<MkAvatar v-if="item.avatar" :user="item.avatar" class="avatar"/> | ||||
| 			<span>{{ item.text }}</span> | ||||
| 			<i v-if="item.indicate"><Fa :icon="faCircle"/></i> | ||||
| 			<span v-if="item.indicate" class="indicator"><i class="fas fa-circle"></i></span> | ||||
| 		</MkA> | ||||
| 		<a v-else-if="item.type === 'a'" :href="item.href" :target="item.target" :download="item.download" @click="close()" :tabindex="i" class="_button item"> | ||||
| 			<Fa v-if="item.icon" :icon="item.icon" fixed-width/> | ||||
| 			<i v-if="item.icon" class="fa-fw" :class="item.icon"></i> | ||||
| 			<span>{{ item.text }}</span> | ||||
| 			<i v-if="item.indicate"><Fa :icon="faCircle"/></i> | ||||
| 			<span v-if="item.indicate" class="indicator"><i class="fas fa-circle"></i></span> | ||||
| 		</a> | ||||
| 		<button v-else-if="item.type === 'user'" @click="clicked(item.action, $event)" :tabindex="i" class="_button item"> | ||||
| 			<MkAvatar :user="item.user" class="avatar"/><MkUserName :user="item.user"/> | ||||
| 			<i v-if="item.indicate"><Fa :icon="faCircle"/></i> | ||||
| 			<span v-if="item.indicate" class="indicator"><i class="fas fa-circle"></i></span> | ||||
| 		</button> | ||||
| 		<button v-else @click="clicked(item.action, $event)" :tabindex="i" class="_button item" :class="{ danger: item.danger }"> | ||||
| 			<Fa v-if="item.icon" :icon="item.icon" fixed-width/> | ||||
| 			<i v-if="item.icon" class="fa-fw" :class="item.icon"></i> | ||||
| 			<MkAvatar v-if="item.avatar" :user="item.avatar" class="avatar"/> | ||||
| 			<span>{{ item.text }}</span> | ||||
| 			<i v-if="item.indicate"><Fa :icon="faCircle"/></i> | ||||
| 			<span v-if="item.indicate" class="indicator"><i class="fas fa-circle"></i></span> | ||||
| 		</button> | ||||
| 	</template> | ||||
| 	<span v-if="_items.length === 0" class="none item"> | ||||
|  | @ -42,7 +42,6 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent, ref } from 'vue'; | ||||
| import { faCircle } from '@fortawesome/free-solid-svg-icons'; | ||||
| import { focusPrev, focusNext } from '@client/scripts/focus'; | ||||
| import contains from '@client/scripts/contains'; | ||||
| 
 | ||||
|  | @ -65,7 +64,6 @@ export default defineComponent({ | |||
| 	data() { | ||||
| 		return { | ||||
| 			_items: [], | ||||
| 			faCircle, | ||||
| 		}; | ||||
| 	}, | ||||
| 	computed: { | ||||
|  | @ -207,7 +205,7 @@ export default defineComponent({ | |||
| 			opacity: 0.7; | ||||
| 		} | ||||
| 
 | ||||
| 		> [data-icon] { | ||||
| 		> i { | ||||
| 			margin-right: 4px; | ||||
| 			width: 20px; | ||||
| 		} | ||||
|  | @ -218,7 +216,7 @@ export default defineComponent({ | |||
| 			height: 20px; | ||||
| 		} | ||||
| 
 | ||||
| 		> i { | ||||
| 		> .indicator { | ||||
| 			position: absolute; | ||||
| 			top: 5px; | ||||
| 			left: 13px; | ||||
|  |  | |||
|  | @ -2,12 +2,12 @@ | |||
| <MkModal ref="modal" @click="$emit('click')" @closed="$emit('closed')"> | ||||
| 	<div class="ebkgoccj _popup _narrow_" @keydown="onKeydown" :style="{ width: `${width}px`, height: scroll ? (height ? `${height}px` : null) :  (height ? `min(${height}px, 100%)` : '100%') }"> | ||||
| 		<div class="header"> | ||||
| 			<button class="_button" v-if="withOkButton" @click="$emit('close')"><Fa :icon="faTimes"/></button> | ||||
| 			<button class="_button" v-if="withOkButton" @click="$emit('close')"><i class="fas fa-times"></i></button> | ||||
| 			<span class="title"> | ||||
| 				<slot name="header"></slot> | ||||
| 			</span> | ||||
| 			<button class="_button" v-if="!withOkButton" @click="$emit('close')"><Fa :icon="faTimes"/></button> | ||||
| 			<button class="_button" v-if="withOkButton" @click="$emit('ok')" :disabled="okButtonDisabled"><Fa :icon="faCheck"/></button> | ||||
| 			<button class="_button" v-if="!withOkButton" @click="$emit('close')"><i class="fas fa-times"></i></button> | ||||
| 			<button class="_button" v-if="withOkButton" @click="$emit('ok')" :disabled="okButtonDisabled"><i class="fas fa-check"></i></button> | ||||
| 		</div> | ||||
| 		<div class="body" v-if="padding"> | ||||
| 			<div class="_section"> | ||||
|  | @ -23,7 +23,6 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { faTimes, faCheck } from '@fortawesome/free-solid-svg-icons'; | ||||
| import MkModal from './modal.vue'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
|  | @ -72,7 +71,6 @@ export default defineComponent({ | |||
| 
 | ||||
| 	data() { | ||||
| 		return { | ||||
| 			faTimes, faCheck | ||||
| 		}; | ||||
| 	}, | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,16 +1,23 @@ | |||
| <template> | ||||
| <div class="cxiknjgy"> | ||||
| 	<slot :items="items"></slot> | ||||
| 	<div class="empty" v-if="empty" key="_empty_"> | ||||
| <transition name="fade" mode="out-in"> | ||||
| 	<MkLoading v-if="fetching"/> | ||||
| 
 | ||||
| 	<MkError v-else-if="error" @retry="init()"/> | ||||
| 
 | ||||
| 	<div class="empty" v-else-if="empty" key="_empty_"> | ||||
| 		<slot name="empty"></slot> | ||||
| 	</div> | ||||
| 	<div class="more" v-show="more" key="_more_"> | ||||
| 		<MkButton class="button" v-appear="$store.state.enableInfiniteScroll ? fetchMore : null" @click="fetchMore" :disabled="moreFetching" :style="{ cursor: moreFetching ? 'wait' : 'pointer' }" primary> | ||||
| 			<template v-if="!moreFetching">{{ $ts.loadMore }}</template> | ||||
| 			<template v-if="moreFetching"><MkLoading inline/></template> | ||||
| 		</MkButton> | ||||
| 
 | ||||
| 	<div v-else class="cxiknjgy"> | ||||
| 		<slot :items="items"></slot> | ||||
| 		<div class="more" v-show="more" key="_more_"> | ||||
| 			<MkButton class="button" v-appear="$store.state.enableInfiniteScroll ? fetchMore : null" @click="fetchMore" :disabled="moreFetching" :style="{ cursor: moreFetching ? 'wait' : 'pointer' }" primary> | ||||
| 				<template v-if="!moreFetching">{{ $ts.loadMore }}</template> | ||||
| 				<template v-if="moreFetching"><MkLoading inline/></template> | ||||
| 			</MkButton> | ||||
| 		</div> | ||||
| 	</div> | ||||
| </div> | ||||
| </transition> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
|  | @ -36,6 +43,15 @@ export default defineComponent({ | |||
| </script> | ||||
| 
 | ||||
| <style lang="scss" scoped> | ||||
| .fade-enter-active, | ||||
| .fade-leave-active { | ||||
| 	transition: opacity 0.125s ease; | ||||
| } | ||||
| .fade-enter-from, | ||||
| .fade-leave-to { | ||||
| 	opacity: 0; | ||||
| } | ||||
| 
 | ||||
| .cxiknjgy { | ||||
| 	> .more > .button { | ||||
| 		margin-left: auto; | ||||
|  |  | |||
|  | @ -15,7 +15,7 @@ | |||
| 		</select> | ||||
| 		<div class="suffix"> | ||||
| 			<slot name="suffix"> | ||||
| 				<Fa :icon="faChevronDown"/> | ||||
| 				<i class="fas fa-chevron-down"></i> | ||||
| 			</slot> | ||||
| 		</div> | ||||
| 	</div> | ||||
|  | @ -25,7 +25,6 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { faChevronDown } from '@fortawesome/free-solid-svg-icons'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	props: { | ||||
|  | @ -49,7 +48,6 @@ export default defineComponent({ | |||
| 	data() { | ||||
| 		return { | ||||
| 			focused: false, | ||||
| 			faChevronDown, | ||||
| 		}; | ||||
| 	}, | ||||
| 	computed: { | ||||
|  |  | |||
|  | @ -4,13 +4,13 @@ | |||
| 		<div class="body _popup _shadow _narrow_" @mousedown="onBodyMousedown" @keydown="onKeydown"> | ||||
| 			<div class="header" :class="{ mini }" @contextmenu.prevent.stop="onContextmenu"> | ||||
| 				<slot v-if="closeRight" name="buttons"><button class="_button" style="pointer-events: none;"></button></slot> | ||||
| 				<button v-else class="_button" @click="close()"><Fa :icon="faTimes"/></button> | ||||
| 				<button v-else class="_button" @click="close()"><i class="fas fa-times"></i></button> | ||||
| 
 | ||||
| 				<span class="title" @mousedown.prevent="onHeaderMousedown" @touchstart.prevent="onHeaderMousedown"> | ||||
| 					<slot name="header"></slot> | ||||
| 				</span> | ||||
| 
 | ||||
| 				<button v-if="closeRight" class="_button" @click="close()"><Fa :icon="faTimes"/></button> | ||||
| 				<button v-if="closeRight" class="_button" @click="close()"><i class="fas fa-times"></i></button> | ||||
| 				<slot v-else name="buttons"><button class="_button" style="pointer-events: none;"></button></slot> | ||||
| 			</div> | ||||
| 			<div class="body" v-if="padding"> | ||||
|  | @ -38,7 +38,6 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { faTimes, faCheck } from '@fortawesome/free-solid-svg-icons'; | ||||
| import contains from '@client/scripts/contains'; | ||||
| import * as os from '@client/os'; | ||||
| 
 | ||||
|  | @ -114,7 +113,6 @@ export default defineComponent({ | |||
| 		return { | ||||
| 			showing: true, | ||||
| 			id: Math.random().toString(), // TODO: UUIDとかにする | ||||
| 			faTimes | ||||
| 		}; | ||||
| 	}, | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| <template> | ||||
| <div v-if="playerEnabled" class="player" :style="`padding: ${(player.height || 0) / (player.width || 1) * 100}% 0 0`"> | ||||
| 	<button class="disablePlayer" @click="playerEnabled = false" :title="$ts.disablePlayer"><Fa icon="times"/></button> | ||||
| 	<button class="disablePlayer" @click="playerEnabled = false" :title="$ts.disablePlayer"><i class="fas fa-times"></i></button> | ||||
| 	<iframe :src="player.url + (player.url.match(/\?/) ? '&autoplay=1&auto_play=1' : '?autoplay=1&auto_play=1')" :width="player.width || '100%'" :heigth="player.height || 250" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen /> | ||||
| </div> | ||||
| <div v-else-if="tweetId && tweetExpanded" class="twitter" ref="twitter"> | ||||
|  | @ -10,7 +10,7 @@ | |||
| 	<transition name="zoom" mode="out-in"> | ||||
| 		<component :is="self ? 'MkA' : 'a'" :class="{ compact }" :[attr]="self ? url.substr(local.length) : url" rel="nofollow noopener" :target="target" :title="url" v-if="!fetching"> | ||||
| 			<div class="thumbnail" v-if="thumbnail" :style="`background-image: url('${thumbnail}')`"> | ||||
| 				<button class="_button" v-if="!playerEnabled && player.url" @click.prevent="playerEnabled = true" :title="$ts.enablePlayer"><Fa :icon="faPlayCircle"/></button> | ||||
| 				<button class="_button" v-if="!playerEnabled && player.url" @click.prevent="playerEnabled = true" :title="$ts.enablePlayer"><i class="fas fa-play-circle"></i></button> | ||||
| 			</div> | ||||
| 			<article> | ||||
| 				<header> | ||||
|  | @ -26,7 +26,7 @@ | |||
| 	</transition> | ||||
| 	<div class="expandTweet" v-if="tweetId"> | ||||
| 		<a @click="tweetExpanded = true"> | ||||
| 			<Fa :icon="faTwitter"/> {{ $ts.expandTweet }} | ||||
| 			<i class="fab fa-twitter"></i> {{ $ts.expandTweet }} | ||||
| 		</a> | ||||
| 	</div> | ||||
| </div> | ||||
|  | @ -34,8 +34,6 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { faPlayCircle } from '@fortawesome/free-regular-svg-icons'; | ||||
| import { faTwitter } from '@fortawesome/free-brands-svg-icons';  | ||||
| import { url as local, lang } from '@client/config'; | ||||
| import * as os from '@client/os'; | ||||
| 
 | ||||
|  | @ -83,7 +81,6 @@ export default defineComponent({ | |||
| 			self: self, | ||||
| 			attr: self ? 'to' : 'href', | ||||
| 			target: self ? null : '_blank', | ||||
| 			faPlayCircle, faTwitter | ||||
| 		}; | ||||
| 	}, | ||||
| 
 | ||||
|  |  | |||
|  | @ -9,7 +9,7 @@ | |||
| 		<MkUserInfo class="user" v-for="user in users" :user="user" :key="user.id"/> | ||||
| 	</div> | ||||
| 	<button class="more" v-appear="$store.state.enableInfiniteScroll ? fetchMore : null" @click="fetchMore" :class="{ fetching: moreFetching }" v-show="more" :disabled="moreFetching"> | ||||
| 		<template v-if="moreFetching"><Fa icon="spinner" pulse fixed-width/></template>{{ moreFetching ? $ts.loading : $ts.loadMore }} | ||||
| 		<template v-if="moreFetching"><i class="fas fa-spinner fa-pulse fa-fw"></i></template>{{ moreFetching ? $ts.loading : $ts.loadMore }} | ||||
| 	</button> | ||||
| </div> | ||||
| </template> | ||||
|  | @ -83,7 +83,7 @@ export default defineComponent({ | |||
| 			cursor: wait; | ||||
| 		} | ||||
| 
 | ||||
| 		> [data-icon] { | ||||
| 		> i { | ||||
| 			margin-right: 4px; | ||||
| 		} | ||||
| 	} | ||||
|  |  | |||
|  | @ -29,7 +29,7 @@ export default defineComponent({ | |||
| <style lang="scss" scoped> | ||||
| .fzgwjkgc { | ||||
| 	box-shadow: 0 0 0 3px var(--panel); | ||||
| 	border-radius: 100%; | ||||
| 	border-radius: 120%; // Blinkのバグか知らんけど、100%ぴったりにすると何故か若干楕円でレンダリングされる | ||||
| 
 | ||||
| 	&.online { | ||||
| 		background: #58d4c9; | ||||
|  |  | |||
|  | @ -44,7 +44,6 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { faTimes, faCheck } from '@fortawesome/free-solid-svg-icons'; | ||||
| import MkInput from './ui/input.vue'; | ||||
| import XModalWindow from '@client/components/ui/modal-window.vue'; | ||||
| import * as os from '@client/os'; | ||||
|  | @ -67,7 +66,6 @@ export default defineComponent({ | |||
| 			recentUsers: [], | ||||
| 			users: [], | ||||
| 			selected: null, | ||||
| 			faTimes, faCheck | ||||
| 		}; | ||||
| 	}, | ||||
| 
 | ||||
|  |  | |||
|  | @ -2,7 +2,7 @@ | |||
| <div class="mk-users-dialog"> | ||||
| 	<div class="header"> | ||||
| 		<span>{{ title }}</span> | ||||
| 		<button class="_button" @click="close()"><Fa :icon="faTimes"/></button> | ||||
| 		<button class="_button" @click="close()"><i class="fas fa-times"></i></button> | ||||
| 	</div> | ||||
| 
 | ||||
| 	<div class="users"> | ||||
|  | @ -16,7 +16,7 @@ | |||
| 	</div> | ||||
| 	<button class="more _button" v-appear="$store.state.enableInfiniteScroll ? fetchMore : null" @click="fetchMore" v-show="more" :disabled="moreFetching"> | ||||
| 		<template v-if="!moreFetching">{{ $ts.loadMore }}</template> | ||||
| 		<template v-if="moreFetching"><Fa :icon="faSpinner" pulse fixed-width/></template> | ||||
| 		<template v-if="moreFetching"><i class="fas fa-spinner fa-pulse fa-fw"></i></template> | ||||
| 	</button> | ||||
| 
 | ||||
| 	<p class="empty" v-if="empty">{{ $ts.noUsers }}</p> | ||||
|  | @ -27,7 +27,6 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { faTimes } from '@fortawesome/free-solid-svg-icons'; | ||||
| import paging from '@client/scripts/paging'; | ||||
| import { userPage } from '../filters/user'; | ||||
| 
 | ||||
|  | @ -50,7 +49,6 @@ export default defineComponent({ | |||
| 
 | ||||
| 	data() { | ||||
| 		return { | ||||
| 			faTimes | ||||
| 		}; | ||||
| 	}, | ||||
| 
 | ||||
|  |  | |||
|  | @ -2,28 +2,28 @@ | |||
| <MkModal ref="modal" :src="src" @click="$refs.modal.close()" @closed="$emit('closed')"> | ||||
| 	<div class="gqyayizv _popup"> | ||||
| 		<button class="_button" @click="choose('public')" :class="{ active: v == 'public' }" data-index="1" key="public"> | ||||
| 			<div><Fa :icon="faGlobe"/></div> | ||||
| 			<div><i class="fas fa-globe"></i></div> | ||||
| 			<div> | ||||
| 				<span>{{ $ts._visibility.public }}</span> | ||||
| 				<span>{{ $ts._visibility.publicDescription }}</span> | ||||
| 			</div> | ||||
| 		</button> | ||||
| 		<button class="_button" @click="choose('home')" :class="{ active: v == 'home' }" data-index="2" key="home"> | ||||
| 			<div><Fa :icon="faHome"/></div> | ||||
| 			<div><i class="fas fa-home"></i></div> | ||||
| 			<div> | ||||
| 				<span>{{ $ts._visibility.home }}</span> | ||||
| 				<span>{{ $ts._visibility.homeDescription }}</span> | ||||
| 			</div> | ||||
| 		</button> | ||||
| 		<button class="_button" @click="choose('followers')" :class="{ active: v == 'followers' }" data-index="3" key="followers"> | ||||
| 			<div><Fa :icon="faUnlock"/></div> | ||||
| 			<div><i class="fas fa-unlock"></i></div> | ||||
| 			<div> | ||||
| 				<span>{{ $ts._visibility.followers }}</span> | ||||
| 				<span>{{ $ts._visibility.followersDescription }}</span> | ||||
| 			</div> | ||||
| 		</button> | ||||
| 		<button :disabled="localOnly" class="_button" @click="choose('specified')" :class="{ active: v == 'specified' }" data-index="4" key="specified"> | ||||
| 			<div><Fa :icon="faEnvelope"/></div> | ||||
| 			<div><i class="fas fa-envelope"></i></div> | ||||
| 			<div> | ||||
| 				<span>{{ $ts._visibility.specified }}</span> | ||||
| 				<span>{{ $ts._visibility.specifiedDescription }}</span> | ||||
|  | @ -31,12 +31,12 @@ | |||
| 		</button> | ||||
| 		<div class="divider"></div> | ||||
| 		<button class="_button localOnly" @click="localOnly = !localOnly" :class="{ active: localOnly }" data-index="5" key="localOnly"> | ||||
| 			<div><Fa :icon="faBiohazard"/></div> | ||||
| 			<div><i class="fas fa-biohazard"></i></div> | ||||
| 			<div> | ||||
| 				<span>{{ $ts._visibility.localOnly }}</span> | ||||
| 				<span>{{ $ts._visibility.localOnlyDescription }}</span> | ||||
| 			</div> | ||||
| 			<div><Fa :icon="localOnly ? faToggleOn : faToggleOff" :key="localOnly"/></div> | ||||
| 			<div><i :class="localOnly ? 'fas fa-toggle-on' : 'fas fa-toggle-off'"></i></div> | ||||
| 		</button> | ||||
| 	</div> | ||||
| </MkModal> | ||||
|  | @ -44,8 +44,6 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { faGlobe, faUnlock, faHome, faBiohazard, faToggleOn, faToggleOff } from '@fortawesome/free-solid-svg-icons'; | ||||
| import { faEnvelope } from '@fortawesome/free-regular-svg-icons'; | ||||
| import MkModal from '@client/components/ui/modal.vue'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
|  | @ -70,7 +68,6 @@ export default defineComponent({ | |||
| 		return { | ||||
| 			v: this.currentVisibility, | ||||
| 			localOnly: this.currentLocalOnly, | ||||
| 			faGlobe, faUnlock, faEnvelope, faHome, faBiohazard, faToggleOn, faToggleOff | ||||
| 		} | ||||
| 	}, | ||||
| 	watch: { | ||||
|  |  | |||
|  | @ -1,8 +1,8 @@ | |||
| <template> | ||||
| <MkModal ref="modal" @click="success ? done() : () => {}" @closed="$emit('closed')"> | ||||
| 	<div class="iuyakobc" :class="{ iconOnly: (text == null) || success }"> | ||||
| 		<Fa class="icon success" v-if="success" :icon="faCheck"/> | ||||
| 		<Fa class="icon waiting" v-else :icon="faSpinner" pulse/> | ||||
| 		<i v-if="success" class="fas fa-check icon success"></i> | ||||
| 		<i v-else class="fas fa-spinner fa-pulse icon waiting"></i> | ||||
| 		<div class="text" v-if="text && !success">{{ text }}<MkEllipsis/></div> | ||||
| 	</div> | ||||
| </MkModal> | ||||
|  | @ -10,7 +10,6 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { faCheck, faSpinner } from '@fortawesome/free-solid-svg-icons'; | ||||
| import MkModal from '@client/components/ui/modal.vue'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
|  | @ -37,7 +36,6 @@ export default defineComponent({ | |||
| 
 | ||||
| 	data() { | ||||
| 		return { | ||||
| 			faCheck, faSpinner, | ||||
| 		}; | ||||
| 	}, | ||||
| 
 | ||||
|  | @ -70,10 +68,9 @@ export default defineComponent({ | |||
| 		padding: 0; | ||||
| 		width: 96px; | ||||
| 		height: 96px; | ||||
| 
 | ||||
| 		> .icon { | ||||
| 			height: 100%; | ||||
| 		} | ||||
| 		display: flex; | ||||
| 		align-items: center; | ||||
| 		justify-content: center; | ||||
| 	} | ||||
| 
 | ||||
| 	> .icon { | ||||
|  |  | |||
|  | @ -6,7 +6,7 @@ | |||
| 				<template #label>{{ $ts.selectWidget }}</template> | ||||
| 				<option v-for="widget in widgetDefs" :value="widget" :key="widget">{{ $t(`_widgets.${widget}`) }}</option> | ||||
| 			</MkSelect> | ||||
| 			<MkButton inline @click="addWidget" primary><Fa :icon="faPlus"/> {{ $ts.add }}</MkButton> | ||||
| 			<MkButton inline @click="addWidget" primary><i class="fas fa-plus"></i> {{ $ts.add }}</MkButton> | ||||
| 			<MkButton inline @click="$emit('exit')">{{ $ts.close }}</MkButton> | ||||
| 		</header> | ||||
| 		<XDraggable | ||||
|  | @ -16,8 +16,8 @@ | |||
| 		> | ||||
| 			<template #item="{element}"> | ||||
| 				<div class="customize-container"> | ||||
| 					<button class="config _button" @click.prevent.stop="configWidget(element.id)"><Fa :icon="faCog"/></button> | ||||
| 					<button class="remove _button" @click.prevent.stop="removeWidget(element)"><Fa :icon="faTimes"/></button> | ||||
| 					<button class="config _button" @click.prevent.stop="configWidget(element.id)"><i class="fas fa-cog"></i></button> | ||||
| 					<button class="remove _button" @click.prevent.stop="removeWidget(element)"><i class="fas fa-times"></i></button> | ||||
| 					<component :is="`mkw-${element.name}`" :widget="element" :setting-callback="setting => settings[element.id] = setting" :column="column" @updateProps="updateWidget(element.id, $event)"/> | ||||
| 				</div> | ||||
| 			</template> | ||||
|  | @ -30,7 +30,6 @@ | |||
| <script lang="ts"> | ||||
| import { defineComponent, defineAsyncComponent } from 'vue'; | ||||
| import { v4 as uuid } from 'uuid'; | ||||
| import { faTimes, faCog, faPlus } from '@fortawesome/free-solid-svg-icons'; | ||||
| import MkSelect from '@client/components/ui/select.vue'; | ||||
| import MkButton from '@client/components/ui/button.vue'; | ||||
| import { widgets as widgetDefs } from '@client/widgets'; | ||||
|  | @ -59,7 +58,6 @@ export default defineComponent({ | |||
| 			widgetAdderSelected: null, | ||||
| 			widgetDefs, | ||||
| 			settings: {}, | ||||
| 			faTimes, faPlus, faCog | ||||
| 		}; | ||||
| 	}, | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										22
									
								
								src/client/directives/click-anime.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/client/directives/click-anime.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,22 @@ | |||
| import { Directive } from 'vue'; | ||||
| 
 | ||||
| export default { | ||||
| 	mounted(el, binding, vn) { | ||||
| 		el.addEventListener('mousedown', () => { | ||||
| 			el.classList.add('_anime_bounce_ready'); | ||||
| 
 | ||||
| 			el.addEventListener('mouseleave', () => { | ||||
| 				el.classList.remove('_anime_bounce_ready'); | ||||
| 			}); | ||||
| 		}); | ||||
| 
 | ||||
| 		el.addEventListener('click', () => { | ||||
| 			el.classList.add('_anime_bounce'); | ||||
| 		}); | ||||
| 
 | ||||
| 		el.addEventListener('animationend', () => { | ||||
| 			el.classList.remove('_anime_bounce_ready'); | ||||
| 			el.classList.remove('_anime_bounce'); | ||||
| 		}); | ||||
| 	} | ||||
| } as Directive; | ||||
|  | @ -8,6 +8,7 @@ import hotkey from './hotkey'; | |||
| import appear from './appear'; | ||||
| import anim from './anim'; | ||||
| import stickyContainer from './sticky-container'; | ||||
| import clickAnime from './click-anime'; | ||||
| 
 | ||||
| export default function(app: App) { | ||||
| 	app.directive('userPreview', userPreview); | ||||
|  | @ -18,5 +19,6 @@ export default function(app: App) { | |||
| 	app.directive('hotkey', hotkey); | ||||
| 	app.directive('appear', appear); | ||||
| 	app.directive('anim', anim); | ||||
| 	app.directive('click-anime', clickAnime); | ||||
| 	app.directive('sticky-container', stickyContainer); | ||||
| } | ||||
|  |  | |||
|  | @ -7,7 +7,6 @@ import '@client/style.scss'; | |||
| import * as Sentry from '@sentry/browser'; | ||||
| import { Integrations } from '@sentry/tracing'; | ||||
| import { computed, createApp, watch } from 'vue'; | ||||
| import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'; | ||||
| 
 | ||||
| import widgets from '@client/widgets'; | ||||
| import directives from '@client/directives'; | ||||
|  | @ -41,6 +40,11 @@ if ((typeof ColdDeviceStorage.get('lightTheme') === 'string') || (typeof ColdDev | |||
| 	ColdDeviceStorage.set('lightTheme', require('@client/themes/l-light.json5')); | ||||
| 	ColdDeviceStorage.set('darkTheme', require('@client/themes/d-dark.json5')); | ||||
| } | ||||
| const link = document.createElement('link'); | ||||
| link.rel = 'stylesheet'; | ||||
| link.href = 'https://use.fontawesome.com/releases/v5.15.3/css/all.css'; | ||||
| document.head.appendChild(link); | ||||
| // TODOここまで
 | ||||
| 
 | ||||
| if (_DEV_) { | ||||
| 	console.warn('Development mode!!!'); | ||||
|  | @ -184,8 +188,6 @@ app.config.globalProperties = { | |||
| }; | ||||
| 
 | ||||
| app.use(router); | ||||
| // eslint-disable-next-line vue/component-definition-name-casing
 | ||||
| app.component('Fa', FontAwesomeIcon); | ||||
| 
 | ||||
| widgets(app); | ||||
| directives(app); | ||||
|  |  | |||
|  | @ -3,7 +3,7 @@ | |||
| 	<div class="_section"> | ||||
| 		<div class="mjndxjch _content"> | ||||
| 			<img src="https://xn--931a.moe/assets/error.jpg" class="_ghost"/> | ||||
| 			<p><Fa :icon="faExclamationTriangle"/> {{ $ts.pageLoadError }}</p> | ||||
| 			<p><i class="fas fa-exclamation-triangle"></i> {{ $ts.pageLoadError }}</p> | ||||
| 			<p>{{ $ts.pageLoadErrorDescription }}</p> | ||||
| 		</div> | ||||
| 	</div> | ||||
|  | @ -12,7 +12,6 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons'; | ||||
| import MkButton from '@client/components/ui/button.vue'; | ||||
| import * as symbols from '@client/symbols'; | ||||
| 
 | ||||
|  | @ -24,9 +23,8 @@ export default defineComponent({ | |||
| 		return { | ||||
| 			[symbols.PAGE_INFO]: { | ||||
| 				title: this.$ts.error, | ||||
| 				icon: faExclamationTriangle | ||||
| 				icon: 'fas fa-exclamation-triangle' | ||||
| 			}, | ||||
| 			faExclamationTriangle | ||||
| 		}; | ||||
| 	}, | ||||
| }); | ||||
|  |  | |||
|  | @ -15,17 +15,17 @@ | |||
| 		</section> | ||||
| 		<FormGroup> | ||||
| 			<FormLink to="https://github.com/misskey-dev/misskey" external> | ||||
| 				<template #icon><Fa :icon="faCode"/></template> | ||||
| 				<template #icon><i class="fas fa-code"></i></template> | ||||
| 				{{ $ts._aboutMisskey.source }} | ||||
| 				<template #suffix>GitHub</template> | ||||
| 			</FormLink> | ||||
| 			<FormLink to="https://crowdin.com/project/misskey" external> | ||||
| 				<template #icon><Fa :icon="faLanguage"/></template> | ||||
| 				<template #icon><i class="fas fa-language"></i></template> | ||||
| 				{{ $ts._aboutMisskey.translation }} | ||||
| 				<template #suffix>Crowdin</template> | ||||
| 			</FormLink> | ||||
| 			<FormLink to="https://www.patreon.com/syuilo" external> | ||||
| 				<template #icon><Fa :icon="faHandHoldingMedical"/></template> | ||||
| 				<template #icon><i class="fas fa-hand-holding-medical"></i></template> | ||||
| 				{{ $ts._aboutMisskey.donate }} | ||||
| 				<template #suffix>Patreon</template> | ||||
| 			</FormLink> | ||||
|  | @ -54,7 +54,6 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { faInfoCircle, faCode, faLanguage, faHandHoldingMedical, } from '@fortawesome/free-solid-svg-icons'; | ||||
| import VanillaTilt from 'vanilla-tilt'; | ||||
| import { version } from '@client/config'; | ||||
| import FormLink from '@client/components/form/link.vue'; | ||||
|  | @ -125,7 +124,6 @@ export default defineComponent({ | |||
| 			easterEggReady: false, | ||||
| 			easterEggEmojis: [], | ||||
| 			easterEggEngine: null, | ||||
| 			faInfoCircle, faCode, faLanguage, faHandHoldingMedical, | ||||
| 		} | ||||
| 	}, | ||||
| 
 | ||||
|  |  | |||
|  | @ -40,7 +40,6 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { faInfoCircle } from '@fortawesome/free-solid-svg-icons'; | ||||
| import { version, instanceName } from '@client/config'; | ||||
| import FormLink from '@client/components/form/link.vue'; | ||||
| import FormBase from '@client/components/form/base.vue'; | ||||
|  | @ -62,12 +61,11 @@ export default defineComponent({ | |||
| 		return { | ||||
| 			[symbols.PAGE_INFO]: { | ||||
| 				title: this.$ts.instanceInfo, | ||||
| 				icon: faInfoCircle | ||||
| 				icon: 'fas fa-info-circle' | ||||
| 			}, | ||||
| 			version, | ||||
| 			instanceName, | ||||
| 			stats: null, | ||||
| 			faInfoCircle | ||||
| 		} | ||||
| 	}, | ||||
| 
 | ||||
|  |  | |||
|  | @ -34,7 +34,7 @@ | |||
| 						</div> | ||||
| 						<div> | ||||
| 							<div class="type" @click="chooseType($event, i)"> | ||||
| 								{{ getTypeOf(v) }} <Fa :icon="faChevronDown"/> | ||||
| 								{{ getTypeOf(v) }} <i class="fas fa-chevron-down"></i> | ||||
| 							</div> | ||||
| 							<!-- default --> | ||||
| 							<div v-if="v === null" v-text="baseProps[k]" class="default-value" /> | ||||
|  | @ -92,7 +92,6 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { faPalette, faChevronDown, faKeyboard } from '@fortawesome/free-solid-svg-icons'; | ||||
| import * as JSON5 from 'json5'; | ||||
| import { toUnicode } from 'punycode/'; | ||||
| 
 | ||||
|  | @ -125,7 +124,7 @@ export default defineComponent({ | |||
| 		return { | ||||
| 			[symbols.PAGE_INFO]: { | ||||
| 				title: this.$ts.themeEditor, | ||||
| 				icon: faPalette, | ||||
| 				icon: 'fas fa-palette', | ||||
| 			}, | ||||
| 			theme: [] as ThemeViewModel, | ||||
| 			name: '', | ||||
|  | @ -135,7 +134,6 @@ export default defineComponent({ | |||
| 			themeToImport: '', | ||||
| 			changed: false, | ||||
| 			lightTheme, darkTheme, themeProps, | ||||
| 			faPalette, faChevronDown, faKeyboard, | ||||
| 		} | ||||
| 	}, | ||||
| 
 | ||||
|  |  | |||
|  | @ -8,7 +8,7 @@ | |||
| 				<img v-if="announcement.imageUrl" :src="announcement.imageUrl"/> | ||||
| 			</div> | ||||
| 			<div class="_footer" v-if="$i && !announcement.isRead"> | ||||
| 				<MkButton @click="read(items, announcement, i)" primary><Fa :icon="faCheck"/> {{ $ts.gotIt }}</MkButton> | ||||
| 				<MkButton @click="read(items, announcement, i)" primary><i class="fas fa-check"></i> {{ $ts.gotIt }}</MkButton> | ||||
| 			</div> | ||||
| 		</section> | ||||
| 	</MkPagination> | ||||
|  | @ -17,7 +17,6 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { faCheck, faBroadcastTower } from '@fortawesome/free-solid-svg-icons'; | ||||
| import MkPagination from '@client/components/ui/pagination.vue'; | ||||
| import MkButton from '@client/components/ui/button.vue'; | ||||
| import * as os from '@client/os'; | ||||
|  | @ -33,13 +32,12 @@ export default defineComponent({ | |||
| 		return { | ||||
| 			[symbols.PAGE_INFO]: { | ||||
| 				title: this.$ts.announcements, | ||||
| 				icon: faBroadcastTower | ||||
| 				icon: 'fas fa-broadcast-tower' | ||||
| 			}, | ||||
| 			pagination: { | ||||
| 				endpoint: 'announcements', | ||||
| 				limit: 10, | ||||
| 			}, | ||||
| 			faCheck, | ||||
| 		}; | ||||
| 	}, | ||||
| 
 | ||||
|  |  | |||
|  | @ -12,7 +12,7 @@ | |||
| 		</MkSwitch> | ||||
| 		<MkButton primary full @click="send" :disabled="sending"> | ||||
| 			<template v-if="sending"><MkEllipsis/></template> | ||||
| 			<template v-else><Fa :icon="faPaperPlane"/> Send</template> | ||||
| 			<template v-else><i class="fas fa-paper-plane"></i> Send</template> | ||||
| 		</MkButton> | ||||
| 	</div> | ||||
| 	<div v-if="res" class="_block" style="padding: 24px;"> | ||||
|  | @ -25,7 +25,6 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { faTerminal, faPaperPlane } from '@fortawesome/free-solid-svg-icons'; | ||||
| import * as JSON5 from 'json5'; | ||||
| import MkButton from '@client/components/ui/button.vue'; | ||||
| import MkInput from '@client/components/ui/input.vue'; | ||||
|  | @ -43,7 +42,7 @@ export default defineComponent({ | |||
| 		return { | ||||
| 			[symbols.PAGE_INFO]: { | ||||
| 				title: 'API console', | ||||
| 				icon: faTerminal | ||||
| 				icon: 'fas fa-terminal' | ||||
| 			}, | ||||
| 
 | ||||
| 			endpoint: '', | ||||
|  | @ -53,7 +52,6 @@ export default defineComponent({ | |||
| 			endpoints: [], | ||||
| 			withCredential: true, | ||||
| 
 | ||||
| 			faPaperPlane | ||||
| 		}; | ||||
| 	}, | ||||
| 
 | ||||
|  |  | |||
|  | @ -7,15 +7,15 @@ | |||
| 			<MkTextarea v-model:value="description">{{ $ts.description }}</MkTextarea> | ||||
| 
 | ||||
| 			<div class="banner"> | ||||
| 				<MkButton v-if="bannerId == null" @click="setBannerImage"><Fa :icon="faPlus"/> {{ $ts._channel.setBanner }}</MkButton> | ||||
| 				<MkButton v-if="bannerId == null" @click="setBannerImage"><i class="fas fa-plus"></i> {{ $ts._channel.setBanner }}</MkButton> | ||||
| 				<div v-else-if="bannerUrl"> | ||||
| 					<img :src="bannerUrl" style="width: 100%;"/> | ||||
| 					<MkButton @click="removeBannerImage()"><Fa :icon="faTrashAlt"/> {{ $ts._channel.removeBanner }}</MkButton> | ||||
| 					<MkButton @click="removeBannerImage()"><i class="fas fa-trash-alt"></i> {{ $ts._channel.removeBanner }}</MkButton> | ||||
| 				</div> | ||||
| 			</div> | ||||
| 		</div> | ||||
| 		<div class="_footer"> | ||||
| 			<MkButton @click="save()" primary><Fa :icon="faSave"/> {{ channelId ? $ts.save : $ts.create }}</MkButton> | ||||
| 			<MkButton @click="save()" primary><i class="fas fa-save"></i> {{ channelId ? $ts.save : $ts.create }}</MkButton> | ||||
| 		</div> | ||||
| 	</div> | ||||
| </div> | ||||
|  | @ -23,8 +23,6 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { computed, defineComponent } from 'vue'; | ||||
| import { faPlus, faSatelliteDish } from '@fortawesome/free-solid-svg-icons'; | ||||
| import { faSave, faTrashAlt } from '@fortawesome/free-regular-svg-icons'; | ||||
| import MkTextarea from '@client/components/ui/textarea.vue'; | ||||
| import MkButton from '@client/components/ui/button.vue'; | ||||
| import MkInput from '@client/components/ui/input.vue'; | ||||
|  | @ -48,17 +46,16 @@ export default defineComponent({ | |||
| 		return { | ||||
| 			[symbols.PAGE_INFO]: computed(() => this.channelId ? { | ||||
| 				title: this.$ts._channel.edit, | ||||
| 				icon: faSatelliteDish, | ||||
| 				icon: 'fas fa-satellite-dish', | ||||
| 			} : { | ||||
| 				title: this.$ts._channel.create, | ||||
| 				icon: faSatelliteDish, | ||||
| 				icon: 'fas fa-satellite-dish', | ||||
| 			}), | ||||
| 			channel: null, | ||||
| 			name: null, | ||||
| 			description: null, | ||||
| 			bannerUrl: null, | ||||
| 			bannerId: null, | ||||
| 			faSave, faTrashAlt, faPlus,faSatelliteDish, | ||||
| 		}; | ||||
| 	}, | ||||
| 
 | ||||
|  |  | |||
|  | @ -3,15 +3,15 @@ | |||
| 	<div class="wpgynlbz _content _panel _gap" :class="{ hide: !showBanner }"> | ||||
| 		<XChannelFollowButton :channel="channel" :full="true" class="subscribe"/> | ||||
| 		<button class="_button toggle" @click="() => showBanner = !showBanner"> | ||||
| 			<template v-if="showBanner"><Fa :icon="faAngleUp"/></template> | ||||
| 			<template v-else><Fa :icon="faAngleDown"/></template> | ||||
| 			<template v-if="showBanner"><i class="fas fa-angle-up"></i></template> | ||||
| 			<template v-else><i class="fas fa-angle-down"></i></template> | ||||
| 		</button> | ||||
| 		<div class="hideOverlay" v-if="!showBanner"> | ||||
| 		</div> | ||||
| 		<div :style="{ backgroundImage: channel.bannerUrl ? `url(${channel.bannerUrl})` : null }" class="banner"> | ||||
| 			<div class="status"> | ||||
| 				<div><Fa :icon="faUsers" fixed-width/><I18n :src="$ts._channel.usersCount" tag="span" style="margin-left: 4px;"><template #n><b>{{ channel.usersCount }}</b></template></I18n></div> | ||||
| 				<div><Fa :icon="faPencilAlt" fixed-width/><I18n :src="$ts._channel.notesCount" tag="span" style="margin-left: 4px;"><template #n><b>{{ channel.notesCount }}</b></template></I18n></div> | ||||
| 				<div><i class="fas fa-users fa-fw"></i><I18n :src="$ts._channel.usersCount" tag="span" style="margin-left: 4px;"><template #n><b>{{ channel.usersCount }}</b></template></I18n></div> | ||||
| 				<div><i class="fas fa-pencil-alt fa-fw"></i><I18n :src="$ts._channel.notesCount" tag="span" style="margin-left: 4px;"><template #n><b>{{ channel.notesCount }}</b></template></I18n></div> | ||||
| 			</div> | ||||
| 			<div class="fade"></div> | ||||
| 		</div> | ||||
|  | @ -28,8 +28,6 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { computed, defineComponent } from 'vue'; | ||||
| import { faSatelliteDish, faUsers, faPencilAlt, faAngleUp, faAngleDown } from '@fortawesome/free-solid-svg-icons'; | ||||
| import {  } from '@fortawesome/free-regular-svg-icons'; | ||||
| import MkContainer from '@client/components/ui/container.vue'; | ||||
| import XPostForm from '@client/components/post-form.vue'; | ||||
| import XTimeline from '@client/components/timeline.vue'; | ||||
|  | @ -56,7 +54,7 @@ export default defineComponent({ | |||
| 		return { | ||||
| 			[symbols.PAGE_INFO]: computed(() => this.channel ? { | ||||
| 				title: this.channel.name, | ||||
| 				icon: faSatelliteDish, | ||||
| 				icon: 'fas fa-satellite-dish', | ||||
| 			} : null), | ||||
| 			channel: null, | ||||
| 			showBanner: true, | ||||
|  | @ -67,7 +65,6 @@ export default defineComponent({ | |||
| 					channelId: this.channelId, | ||||
| 				}) | ||||
| 			}, | ||||
| 			faSatelliteDish, faUsers, faPencilAlt, faAngleUp, faAngleDown, | ||||
| 		}; | ||||
| 	}, | ||||
| 
 | ||||
|  | @ -111,7 +108,7 @@ export default defineComponent({ | |||
| 		background: rgba(0, 0, 0, 0.5); | ||||
| 		border-radius: 100%; | ||||
| 		 | ||||
| 		> [data-icon] { | ||||
| 		> i { | ||||
| 			vertical-align: middle; | ||||
| 		} | ||||
| 	} | ||||
|  |  | |||
|  | @ -2,9 +2,9 @@ | |||
| <div> | ||||
| 	<div class="_section" style="padding: 0;" v-if="$i"> | ||||
| 		<MkTab class="_content" v-model:value="tab"> | ||||
| 			<option value="featured"><Fa :icon="faFireAlt"/> {{ $ts._channel.featured }}</option> | ||||
| 			<option value="following"><Fa :icon="faHeart"/> {{ $ts._channel.following }}</option> | ||||
| 			<option value="owned"><Fa :icon="faEdit"/> {{ $ts._channel.owned }}</option> | ||||
| 			<option value="featured"><i class="fas fa-fire-alt"></i> {{ $ts._channel.featured }}</option> | ||||
| 			<option value="following"><i class="fas fa-heart"></i> {{ $ts._channel.following }}</option> | ||||
| 			<option value="owned"><i class="fas fa-edit"></i> {{ $ts._channel.owned }}</option> | ||||
| 		</MkTab> | ||||
| 	</div> | ||||
| 
 | ||||
|  | @ -22,7 +22,7 @@ | |||
| 		</div> | ||||
| 
 | ||||
| 		<div class="_content grwlizim owned" v-if="tab === 'owned'"> | ||||
| 			<MkButton class="new" @click="create()"><Fa :icon="faPlus"/></MkButton> | ||||
| 			<MkButton class="new" @click="create()"><i class="fas fa-plus"></i></MkButton> | ||||
| 			<MkPagination :pagination="ownedPagination" #default="{items}"> | ||||
| 				<MkChannelPreview v-for="channel in items" class="_gap" :channel="channel" :key="channel.id"/> | ||||
| 			</MkPagination> | ||||
|  | @ -33,8 +33,6 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { faSatelliteDish, faPlus, faEdit, faFireAlt } from '@fortawesome/free-solid-svg-icons'; | ||||
| import { faHeart } from '@fortawesome/free-regular-svg-icons'; | ||||
| import MkChannelPreview from '@client/components/channel-preview.vue'; | ||||
| import MkPagination from '@client/components/ui/pagination.vue'; | ||||
| import MkButton from '@client/components/ui/button.vue'; | ||||
|  | @ -49,9 +47,9 @@ export default defineComponent({ | |||
| 		return { | ||||
| 			[symbols.PAGE_INFO]: { | ||||
| 				title: this.$ts.channel, | ||||
| 				icon: faSatelliteDish, | ||||
| 				icon: 'fas fa-satellite-dish', | ||||
| 				action: { | ||||
| 					icon: faPlus, | ||||
| 					icon: 'fas fa-plus', | ||||
| 					handler: this.create | ||||
| 				} | ||||
| 			}, | ||||
|  | @ -68,7 +66,6 @@ export default defineComponent({ | |||
| 				endpoint: 'channels/owned', | ||||
| 				limit: 5, | ||||
| 			}, | ||||
| 			faSatelliteDish, faPlus, faEdit, faHeart, faFireAlt | ||||
| 		}; | ||||
| 	}, | ||||
| 	methods: { | ||||
|  |  | |||
|  | @ -15,7 +15,6 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { computed, defineComponent } from 'vue'; | ||||
| import { faEllipsisH, faPaperclip, faPencilAlt, faTrashAlt } from '@fortawesome/free-solid-svg-icons'; | ||||
| import MkContainer from '@client/components/ui/container.vue'; | ||||
| import XPostForm from '@client/components/post-form.vue'; | ||||
| import XNotes from '@client/components/notes.vue'; | ||||
|  | @ -40,9 +39,9 @@ export default defineComponent({ | |||
| 		return { | ||||
| 			[symbols.PAGE_INFO]: computed(() => this.clip ? { | ||||
| 				title: this.clip.name, | ||||
| 				icon: faPaperclip, | ||||
| 				icon: 'fas fa-paperclip', | ||||
| 				action: { | ||||
| 					icon: faEllipsisH, | ||||
| 					icon: 'fas fa-ellipsis-h', | ||||
| 					handler: this.menu | ||||
| 				} | ||||
| 			} : null), | ||||
|  | @ -81,7 +80,7 @@ export default defineComponent({ | |||
| 	methods: { | ||||
| 		menu(ev) { | ||||
| 			os.modalMenu([this.isOwned ? { | ||||
| 				icon: faPencilAlt, | ||||
| 				icon: 'fas fa-pencil-alt', | ||||
| 				text: this.$ts.edit, | ||||
| 				action: async () => { | ||||
| 					const { canceled, result } = await os.form(this.clip.name, { | ||||
|  | @ -111,7 +110,7 @@ export default defineComponent({ | |||
| 					}); | ||||
| 				} | ||||
| 			} : undefined, this.isOwned ? { | ||||
| 				icon: faTrashAlt, | ||||
| 				icon: 'fas fa-trash-alt', | ||||
| 				text: this.$ts.delete, | ||||
| 				danger: true, | ||||
| 				action: async () => { | ||||
|  |  | |||
|  | @ -10,7 +10,6 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { computed, defineComponent } from 'vue'; | ||||
| import { faQuestionCircle } from '@fortawesome/free-solid-svg-icons' | ||||
| import MarkdownIt from 'markdown-it'; | ||||
| import MarkdownItAnchor from 'markdown-it-anchor'; | ||||
| import { url, lang } from '@client/config'; | ||||
|  | @ -41,7 +40,7 @@ export default defineComponent({ | |||
| 		return { | ||||
| 			[symbols.PAGE_INFO]: computed(() => this.title ? { | ||||
| 				title: this.title, | ||||
| 				icon: faQuestionCircle, | ||||
| 				icon: 'fas fa-question-circle', | ||||
| 			} : null), | ||||
| 			title: null, | ||||
| 			body: null, | ||||
|  |  | |||
|  | @ -14,7 +14,6 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { faQuestionCircle } from '@fortawesome/free-solid-svg-icons' | ||||
| import { url, lang } from '@client/config'; | ||||
| import * as symbols from '@client/symbols'; | ||||
| 
 | ||||
|  | @ -23,10 +22,9 @@ export default defineComponent({ | |||
| 		return { | ||||
| 			[symbols.PAGE_INFO]: { | ||||
| 				title: this.$ts.help, | ||||
| 				icon: faQuestionCircle | ||||
| 				icon: 'fas fa-question-circle' | ||||
| 			}, | ||||
| 			docs: [], | ||||
| 			faQuestionCircle | ||||
| 		} | ||||
| 	}, | ||||
| 
 | ||||
|  |  | |||
|  | @ -6,7 +6,6 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { computed, defineComponent } from 'vue'; | ||||
| import { faCloud } from '@fortawesome/free-solid-svg-icons'; | ||||
| import XDrive from '@client/components/drive.vue'; | ||||
| import * as os from '@client/os'; | ||||
| import * as symbols from '@client/symbols'; | ||||
|  | @ -20,7 +19,7 @@ export default defineComponent({ | |||
| 		return { | ||||
| 			[symbols.PAGE_INFO]: { | ||||
| 				title: computed(() => this.folder ? this.folder.name : this.$ts.drive), | ||||
| 				icon: faCloud, | ||||
| 				icon: 'fas fa-cloud', | ||||
| 				menu: () => this.$refs.drive.getMenu() | ||||
| 			}, | ||||
| 			folder: null, | ||||
|  |  | |||
|  | @ -2,7 +2,7 @@ | |||
| <div class="lznhrdub _root"> | ||||
| 	<div> | ||||
| 		<div class="_isolated"> | ||||
| 			<MkInput v-model:value="query" :debounce="true" type="search"><template #icon><Fa :icon="faSearch"/></template><span>{{ $ts.searchUser }}</span></MkInput> | ||||
| 			<MkInput v-model:value="query" :debounce="true" type="search"><template #icon><i class="fas fa-search"></i></template><span>{{ $ts.searchUser }}</span></MkInput> | ||||
| 		</div> | ||||
| 
 | ||||
| 		<XUserList v-if="query" class="_gap" :pagination="searchPagination" ref="search"/> | ||||
|  | @ -14,19 +14,19 @@ | |||
| 
 | ||||
| 		<template v-if="tag == null"> | ||||
| 			<MkFolder class="_gap" persist-key="explore-pinned-users"> | ||||
| 				<template #header><Fa :icon="faBookmark" fixed-width style="margin-right: 0.5em;"/>{{ $ts.pinnedUsers }}</template> | ||||
| 				<template #header><i class="fas fa-bookmark fa-fw" style="margin-right: 0.5em;"></i>{{ $ts.pinnedUsers }}</template> | ||||
| 				<XUserList :pagination="pinnedUsers"/> | ||||
| 			</MkFolder> | ||||
| 			<MkFolder class="_gap" persist-key="explore-popular-users"> | ||||
| 				<template #header><Fa :icon="faChartLine" fixed-width style="margin-right: 0.5em;"/>{{ $ts.popularUsers }}</template> | ||||
| 				<template #header><i class="fas fa-chart-line fa-fw" style="margin-right: 0.5em;"></i>{{ $ts.popularUsers }}</template> | ||||
| 				<XUserList :pagination="popularUsers"/> | ||||
| 			</MkFolder> | ||||
| 			<MkFolder class="_gap" persist-key="explore-recently-updated-users"> | ||||
| 				<template #header><Fa :icon="faCommentAlt" fixed-width style="margin-right: 0.5em;"/>{{ $ts.recentlyUpdatedUsers }}</template> | ||||
| 				<template #header><i class="fas fa-comment-alt fa-fw" style="margin-right: 0.5em;"></i>{{ $ts.recentlyUpdatedUsers }}</template> | ||||
| 				<XUserList :pagination="recentlyUpdatedUsers"/> | ||||
| 			</MkFolder> | ||||
| 			<MkFolder class="_gap" persist-key="explore-recently-registered-users"> | ||||
| 				<template #header><Fa :icon="faPlus" fixed-width style="margin-right: 0.5em;"/>{{ $ts.recentlyRegisteredUsers }}</template> | ||||
| 				<template #header><i class="fas fa-plus fa-fw" style="margin-right: 0.5em;"></i>{{ $ts.recentlyRegisteredUsers }}</template> | ||||
| 				<XUserList :pagination="recentlyRegisteredUsers"/> | ||||
| 			</MkFolder> | ||||
| 		</template> | ||||
|  | @ -37,7 +37,7 @@ | |||
| 		</div> | ||||
| 
 | ||||
| 		<MkFolder :foldable="true" :expanded="false" ref="tags" class="_gap"> | ||||
| 			<template #header><Fa :icon="faHashtag" fixed-width style="margin-right: 0.5em;"/>{{ $ts.popularTags }}</template> | ||||
| 			<template #header><i class="fas fa-hashtag fa-fw" style="margin-right: 0.5em;"></i>{{ $ts.popularTags }}</template> | ||||
| 
 | ||||
| 			<div class="vxjfqztj"> | ||||
| 				<MkA v-for="tag in tagsLocal" :to="`/explore/tags/${tag.tag}`" :key="'local:' + tag.tag" class="local">{{ tag.tag }}</MkA> | ||||
|  | @ -46,21 +46,21 @@ | |||
| 		</MkFolder> | ||||
| 
 | ||||
| 		<MkFolder v-if="tag != null" :key="`${tag}`" class="_gap"> | ||||
| 			<template #header><Fa :icon="faHashtag" fixed-width style="margin-right: 0.5em;"/>{{ tag }}</template> | ||||
| 			<template #header><i class="fas fa-hashtag fa-fw" style="margin-right: 0.5em;"></i>{{ tag }}</template> | ||||
| 			<XUserList :pagination="tagUsers"/> | ||||
| 		</MkFolder> | ||||
| 
 | ||||
| 		<template v-if="tag == null"> | ||||
| 			<MkFolder class="_gap"> | ||||
| 				<template #header><Fa :icon="faChartLine" fixed-width style="margin-right: 0.5em;"/>{{ $ts.popularUsers }}</template> | ||||
| 				<template #header><i class="fas fa-chart-line fa-fw" style="margin-right: 0.5em;"></i>{{ $ts.popularUsers }}</template> | ||||
| 				<XUserList :pagination="popularUsersF"/> | ||||
| 			</MkFolder> | ||||
| 			<MkFolder class="_gap"> | ||||
| 				<template #header><Fa :icon="faCommentAlt" fixed-width style="margin-right: 0.5em;"/>{{ $ts.recentlyUpdatedUsers }}</template> | ||||
| 				<template #header><i class="fas fa-comment-alt fa-fw" style="margin-right: 0.5em;"></i>{{ $ts.recentlyUpdatedUsers }}</template> | ||||
| 				<XUserList :pagination="recentlyUpdatedUsersF"/> | ||||
| 			</MkFolder> | ||||
| 			<MkFolder class="_gap"> | ||||
| 				<template #header><Fa :icon="faRocket" fixed-width style="margin-right: 0.5em;"/>{{ $ts.recentlyDiscoveredUsers }}</template> | ||||
| 				<template #header><i class="fas fa-rocket fa-fw" style="margin-right: 0.5em;"></i>{{ $ts.recentlyDiscoveredUsers }}</template> | ||||
| 				<XUserList :pagination="recentlyRegisteredUsersF"/> | ||||
| 			</MkFolder> | ||||
| 		</template> | ||||
|  | @ -70,8 +70,6 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { computed, defineComponent } from 'vue'; | ||||
| import { faChartLine, faPlus, faHashtag, faRocket, faSearch } from '@fortawesome/free-solid-svg-icons'; | ||||
| import { faBookmark, faCommentAlt } from '@fortawesome/free-regular-svg-icons'; | ||||
| import XUserList from '@client/components/user-list.vue'; | ||||
| import MkFolder from '@client/components/ui/folder.vue'; | ||||
| import MkInput from '@client/components/ui/input.vue'; | ||||
|  | @ -97,7 +95,7 @@ export default defineComponent({ | |||
| 		return { | ||||
| 			[symbols.PAGE_INFO]: { | ||||
| 				title: this.$ts.explore, | ||||
| 				icon: faHashtag | ||||
| 				icon: 'fas fa-hashtag' | ||||
| 			}, | ||||
| 			pinnedUsers: { endpoint: 'pinned-users' }, | ||||
| 			popularUsers: { endpoint: 'users', limit: 10, noPaging: true, params: { | ||||
|  | @ -139,7 +137,6 @@ export default defineComponent({ | |||
| 			stats: null, | ||||
| 			query: null, | ||||
| 			num: number, | ||||
| 			faBookmark, faChartLine, faCommentAlt, faPlus, faHashtag, faRocket, faSearch, | ||||
| 		}; | ||||
| 	}, | ||||
| 
 | ||||
|  |  | |||
|  | @ -6,7 +6,6 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { faStar } from '@fortawesome/free-solid-svg-icons'; | ||||
| import Progress from '@client/scripts/loading'; | ||||
| import XNotes from '@client/components/notes.vue'; | ||||
| import * as os from '@client/os'; | ||||
|  | @ -21,7 +20,7 @@ export default defineComponent({ | |||
| 		return { | ||||
| 			[symbols.PAGE_INFO]: { | ||||
| 				title: this.$ts.favorites, | ||||
| 				icon: faStar | ||||
| 				icon: 'fas fa-star' | ||||
| 			}, | ||||
| 			pagination: { | ||||
| 				endpoint: 'i/favorites', | ||||
|  |  | |||
|  | @ -6,7 +6,6 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { faFireAlt } from '@fortawesome/free-solid-svg-icons'; | ||||
| import Progress from '@client/scripts/loading'; | ||||
| import XNotes from '@client/components/notes.vue'; | ||||
| import * as symbols from '@client/symbols'; | ||||
|  | @ -20,14 +19,13 @@ export default defineComponent({ | |||
| 		return { | ||||
| 			[symbols.PAGE_INFO]: { | ||||
| 				title: this.$ts.featured, | ||||
| 				icon: faFireAlt | ||||
| 				icon: 'fas fa-fire-alt' | ||||
| 			}, | ||||
| 			pagination: { | ||||
| 				endpoint: 'notes/featured', | ||||
| 				limit: 10, | ||||
| 				offsetMode: true | ||||
| 			}, | ||||
| 			faFireAlt | ||||
| 		}; | ||||
| 	}, | ||||
| 
 | ||||
|  |  | |||
|  | @ -19,8 +19,8 @@ | |||
| 						<Mfm :text="req.follower.description" :is-note="false" :author="req.follower" :i="$i" :custom-emojis="req.follower.emojis" :plain="true" :nowrap="true"/> | ||||
| 					</div> | ||||
| 					<div class="actions"> | ||||
| 						<button class="_button" @click="accept(req.follower)"><Fa :icon="faCheck"/></button> | ||||
| 						<button class="_button" @click="reject(req.follower)"><Fa :icon="faTimes"/></button> | ||||
| 						<button class="_button" @click="accept(req.follower)"><i class="fas fa-check"></i></button> | ||||
| 						<button class="_button" @click="reject(req.follower)"><i class="fas fa-times"></i></button> | ||||
| 					</div> | ||||
| 				</div> | ||||
| 			</div> | ||||
|  | @ -31,7 +31,6 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { faUserClock, faCheck, faTimes } from '@fortawesome/free-solid-svg-icons'; | ||||
| import MkPagination from '@client/components/ui/pagination.vue'; | ||||
| import { userPage, acct } from '../filters/user'; | ||||
| import * as os from '@client/os'; | ||||
|  | @ -46,13 +45,12 @@ export default defineComponent({ | |||
| 		return { | ||||
| 			[symbols.PAGE_INFO]: { | ||||
| 				title: this.$ts.followRequests, | ||||
| 				icon: faUserClock, | ||||
| 				icon: 'fas fa-user-clock', | ||||
| 			}, | ||||
| 			pagination: { | ||||
| 				endpoint: 'following/requests/list', | ||||
| 				limit: 10, | ||||
| 			}, | ||||
| 			faCheck, faTimes, faUserClock | ||||
| 		}; | ||||
| 	}, | ||||
| 
 | ||||
|  |  | |||
|  | @ -99,9 +99,12 @@ | |||
| 			<span>Raw</span> | ||||
| 		</FormObjectView> | ||||
| 		<FormGroup> | ||||
| 			<template #label>Well-known resources</template> | ||||
| 			<FormLink :to="`https://${host}/.well-known/host-meta`" external>host-meta</FormLink> | ||||
| 			<FormLink :to="`https://${host}/.well-known/host-meta.json`" external>host-meta.json</FormLink> | ||||
| 			<FormLink :to="`https://${host}/.well-known/nodeinfo`" external>nodeinfo</FormLink> | ||||
| 			<FormLink :to="`https://${host}/robots.txt`" external>robots.txt</FormLink> | ||||
| 			<FormLink :to="`https://${host}/manifest.json`" external>manifest.json</FormLink> | ||||
| 		</FormGroup> | ||||
| 		<FormSuspense :p="dnsPromiseFactory" v-slot="{ result: dns }"> | ||||
| 			<FormGroup> | ||||
|  | @ -130,7 +133,6 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineAsyncComponent, defineComponent } from 'vue'; | ||||
| import { faExternalLinkAlt, faInfoCircle } from '@fortawesome/free-solid-svg-icons'; | ||||
| import Chart from 'chart.js'; | ||||
| import FormObjectView from '@client/components/form/object-view.vue'; | ||||
| import FormTextarea from '@client/components/form/textarea.vue'; | ||||
|  | @ -182,10 +184,10 @@ export default defineComponent({ | |||
| 		return { | ||||
| 			[symbols.PAGE_INFO]: { | ||||
| 				title: this.$ts.instanceInfo, | ||||
| 				icon: faInfoCircle, | ||||
| 				icon: 'fas fa-info-circle', | ||||
| 				actions: [{ | ||||
| 					text: `https://${this.host}`, | ||||
| 					icon: faExternalLinkAlt, | ||||
| 					icon: 'fas fa-external-link-alt', | ||||
| 					handler: () => { | ||||
| 						window.open(`https://${this.host}`, '_blank'); | ||||
| 					} | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| <template> | ||||
| <div class=""> | ||||
| <div class="lcixvhis"> | ||||
| 	<div class="_section reports"> | ||||
| 		<div class="_content"> | ||||
| 			<div class="inputs" style="display: flex;"> | ||||
|  | @ -63,8 +63,6 @@ | |||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { faPlus, faUsers, faSearch, faBookmark, faMicrophoneSlash, faExclamationCircle } from '@fortawesome/free-solid-svg-icons'; | ||||
| import { faSnowflake, faBookmark as farBookmark } from '@fortawesome/free-regular-svg-icons'; | ||||
| import parseAcct from '@/misc/acct/parse'; | ||||
| import MkButton from '@client/components/ui/button.vue'; | ||||
| import MkInput from '@client/components/ui/input.vue'; | ||||
|  | @ -82,11 +80,13 @@ export default defineComponent({ | |||
| 		MkPagination, | ||||
| 	}, | ||||
| 
 | ||||
| 	emits: ['info'], | ||||
| 
 | ||||
| 	data() { | ||||
| 		return { | ||||
| 			[symbols.PAGE_INFO]: { | ||||
| 				title: this.$ts.abuseReports, | ||||
| 				icon: faExclamationCircle | ||||
| 				icon: 'fas fa-exclamation-circle' | ||||
| 			}, | ||||
| 			searchUsername: '', | ||||
| 			searchHost: '', | ||||
|  | @ -102,7 +102,6 @@ export default defineComponent({ | |||
| 					targetUserOrigin: this.targetUserOrigin, | ||||
| 				}), | ||||
| 			}, | ||||
| 			faPlus, faUsers, faSearch, faBookmark, farBookmark, faMicrophoneSlash, faSnowflake | ||||
| 		} | ||||
| 	}, | ||||
| 
 | ||||
|  | @ -120,6 +119,10 @@ export default defineComponent({ | |||
| 		}, | ||||
| 	}, | ||||
| 
 | ||||
| 	mounted() { | ||||
| 		this.$emit('info', this[symbols.PAGE_INFO]); | ||||
| 	}, | ||||
| 
 | ||||
| 	methods: { | ||||
| 		acct, | ||||
| 
 | ||||
|  | @ -135,6 +138,10 @@ export default defineComponent({ | |||
| </script> | ||||
| 
 | ||||
| <style lang="scss" scoped> | ||||
| .lcixvhis { | ||||
| 	margin: var(--margin); | ||||
| } | ||||
| 
 | ||||
| .bcekxzvu { | ||||
| 	> .target { | ||||
| 		display: flex; | ||||
|  |  | |||
|  | @ -1,35 +1,29 @@ | |||
| <template> | ||||
| <div class="ztgjmzrw"> | ||||
| 	<div class="_section"> | ||||
| 		<div class="_content"> | ||||
| 			<MkButton @click="add()" primary style="margin: 0 auto 16px auto;"><Fa :icon="faPlus"/> {{ $ts.add }}</MkButton> | ||||
| 			<section class="_card _gap announcements" v-for="announcement in announcements"> | ||||
| 				<div class="_content announcement"> | ||||
| 					<MkInput v-model:value="announcement.title"> | ||||
| 						<span>{{ $ts.title }}</span> | ||||
| 					</MkInput> | ||||
| 					<MkTextarea v-model:value="announcement.text"> | ||||
| 						<span>{{ $ts.text }}</span> | ||||
| 					</MkTextarea> | ||||
| 					<MkInput v-model:value="announcement.imageUrl"> | ||||
| 						<span>{{ $ts.imageUrl }}</span> | ||||
| 					</MkInput> | ||||
| 					<p v-if="announcement.reads">{{ $t('nUsersRead', { n: announcement.reads }) }}</p> | ||||
| 					<div class="buttons"> | ||||
| 						<MkButton class="button" inline @click="save(announcement)" primary><Fa :icon="faSave"/> {{ $ts.save }}</MkButton> | ||||
| 						<MkButton class="button" inline @click="remove(announcement)"><Fa :icon="faTrashAlt"/> {{ $ts.remove }}</MkButton> | ||||
| 					</div> | ||||
| 				</div> | ||||
| 			</section> | ||||
| 	<MkButton @click="add()" primary style="margin: 0 auto 16px auto;"><i class="fas fa-plus"></i> {{ $ts.add }}</MkButton> | ||||
| 	<section class="_card _gap announcements" v-for="announcement in announcements"> | ||||
| 		<div class="_content announcement"> | ||||
| 			<MkInput v-model:value="announcement.title"> | ||||
| 				<span>{{ $ts.title }}</span> | ||||
| 			</MkInput> | ||||
| 			<MkTextarea v-model:value="announcement.text"> | ||||
| 				<span>{{ $ts.text }}</span> | ||||
| 			</MkTextarea> | ||||
| 			<MkInput v-model:value="announcement.imageUrl"> | ||||
| 				<span>{{ $ts.imageUrl }}</span> | ||||
| 			</MkInput> | ||||
| 			<p v-if="announcement.reads">{{ $t('nUsersRead', { n: announcement.reads }) }}</p> | ||||
| 			<div class="buttons"> | ||||
| 				<MkButton class="button" inline @click="save(announcement)" primary><i class="fas fa-save"></i> {{ $ts.save }}</MkButton> | ||||
| 				<MkButton class="button" inline @click="remove(announcement)"><i class="fas fa-trash-alt"></i> {{ $ts.remove }}</MkButton> | ||||
| 			</div> | ||||
| 		</div> | ||||
| 	</div> | ||||
| 	</section> | ||||
| </div> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { faBroadcastTower, faPlus } from '@fortawesome/free-solid-svg-icons'; | ||||
| import { faSave, faTrashAlt } from '@fortawesome/free-regular-svg-icons'; | ||||
| import MkButton from '@client/components/ui/button.vue'; | ||||
| import MkInput from '@client/components/ui/input.vue'; | ||||
| import MkTextarea from '@client/components/ui/textarea.vue'; | ||||
|  | @ -43,14 +37,15 @@ export default defineComponent({ | |||
| 		MkTextarea, | ||||
| 	}, | ||||
| 
 | ||||
| 	emits: ['info'], | ||||
| 
 | ||||
| 	data() { | ||||
| 		return { | ||||
| 			[symbols.PAGE_INFO]: { | ||||
| 				title: this.$ts.announcements, | ||||
| 				icon: faBroadcastTower | ||||
| 				icon: 'fas fa-broadcast-tower' | ||||
| 			}, | ||||
| 			announcements: [], | ||||
| 			faBroadcastTower, faSave, faTrashAlt, faPlus | ||||
| 		} | ||||
| 	}, | ||||
| 
 | ||||
|  | @ -60,6 +55,10 @@ export default defineComponent({ | |||
| 		}); | ||||
| 	}, | ||||
| 
 | ||||
| 	mounted() { | ||||
| 		this.$emit('info', this[symbols.PAGE_INFO]); | ||||
| 	}, | ||||
| 
 | ||||
| 	methods: { | ||||
| 		add() { | ||||
| 			this.announcements.unshift({ | ||||
|  | @ -112,3 +111,9 @@ export default defineComponent({ | |||
| 	} | ||||
| }); | ||||
| </script> | ||||
| 
 | ||||
| <style lang="scss" scoped> | ||||
| .ztgjmzrw { | ||||
| 	margin: var(--margin); | ||||
| } | ||||
| </style> | ||||
|  |  | |||
							
								
								
									
										138
									
								
								src/client/pages/instance/bot-protection.vue
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										138
									
								
								src/client/pages/instance/bot-protection.vue
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,138 @@ | |||
| <template> | ||||
| <FormBase> | ||||
| 	<FormSuspense :p="init"> | ||||
| 		<FormRadios v-model="provider"> | ||||
| 			<template #desc><i class="fas fa-shield-alt"></i> {{ $ts.botProtection }}</template> | ||||
| 			<option :value="null">{{ $ts.none }} ({{ $ts.notRecommended }})</option> | ||||
| 			<option value="hcaptcha">hCaptcha</option> | ||||
| 			<option value="recaptcha">reCAPTCHA</option> | ||||
| 		</FormRadios> | ||||
| 
 | ||||
| 		<template v-if="provider === 'hcaptcha'"> | ||||
| 			<div class="_formItem _formNoConcat" v-sticky-container> | ||||
| 				<div class="_formLabel">hCaptcha</div> | ||||
| 				<div class="main"> | ||||
| 					<FormInput v-model:value="hcaptchaSiteKey"> | ||||
| 						<template #prefix><i class="fas fa-key"></i></template> | ||||
| 						<span>{{ $ts.hcaptchaSiteKey }}</span> | ||||
| 					</FormInput> | ||||
| 					<FormInput v-model:value="hcaptchaSecretKey"> | ||||
| 						<template #prefix><i class="fas fa-key"></i></template> | ||||
| 						<span>{{ $ts.hcaptchaSecretKey }}</span> | ||||
| 					</FormInput> | ||||
| 				</div> | ||||
| 			</div> | ||||
| 			<div class="_formItem _formNoConcat" v-sticky-container> | ||||
| 				<div class="_formLabel">{{ $ts.preview }}</div> | ||||
| 				<div class="_formPanel" style="padding: var(--formContentHMargin);"> | ||||
| 					<MkCaptcha provider="hcaptcha" :sitekey="hcaptchaSiteKey || '10000000-ffff-ffff-ffff-000000000001'"/> | ||||
| 				</div> | ||||
| 			</div> | ||||
| 		</template> | ||||
| 		<template v-else-if="provider === 'recaptcha'"> | ||||
| 			<div class="_formItem _formNoConcat" v-sticky-container> | ||||
| 				<div class="_formLabel">reCAPTCHA</div> | ||||
| 				<div class="main"> | ||||
| 					<FormInput v-model:value="recaptchaSiteKey"> | ||||
| 						<template #prefix><i class="fas fa-key"></i></template> | ||||
| 						<span>{{ $ts.recaptchaSiteKey }}</span> | ||||
| 					</FormInput> | ||||
| 					<FormInput v-model:value="recaptchaSecretKey"> | ||||
| 						<template #prefix><i class="fas fa-key"></i></template> | ||||
| 						<span>{{ $ts.recaptchaSecretKey }}</span> | ||||
| 					</FormInput> | ||||
| 				</div> | ||||
| 			</div> | ||||
| 			<div v-if="recaptchaSiteKey" class="_formItem _formNoConcat" v-sticky-container> | ||||
| 				<div class="_formLabel">{{ $ts.preview }}</div> | ||||
| 				<div class="_formPanel" style="padding: var(--formContentHMargin);"> | ||||
| 					<MkCaptcha provider="recaptcha" :sitekey="recaptchaSiteKey"/> | ||||
| 				</div> | ||||
| 			</div> | ||||
| 		</template> | ||||
| 
 | ||||
| 		<FormButton @click="save" primary><i class="fas fa-save"></i> {{ $ts.save }}</FormButton> | ||||
| 	</FormSuspense> | ||||
| </FormBase> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineAsyncComponent, defineComponent } from 'vue'; | ||||
| import FormRadios from '@client/components/form/radios.vue'; | ||||
| import FormInput from '@client/components/form/input.vue'; | ||||
| import FormButton from '@client/components/form/button.vue'; | ||||
| import FormBase from '@client/components/form/base.vue'; | ||||
| import FormGroup from '@client/components/form/group.vue'; | ||||
| import FormInfo from '@client/components/form/info.vue'; | ||||
| import FormSuspense from '@client/components/form/suspense.vue'; | ||||
| import * as os from '@client/os'; | ||||
| import * as symbols from '@client/symbols'; | ||||
| import { fetchInstance } from '@client/instance'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	components: { | ||||
| 		FormRadios, | ||||
| 		FormInput, | ||||
| 		FormBase, | ||||
| 		FormGroup, | ||||
| 		FormButton, | ||||
| 		FormInfo, | ||||
| 		FormSuspense, | ||||
| 		MkCaptcha: defineAsyncComponent(() => import('@client/components/captcha.vue')), | ||||
| 	}, | ||||
| 
 | ||||
| 	emits: ['info'], | ||||
| 
 | ||||
| 	data() { | ||||
| 		return { | ||||
| 			[symbols.PAGE_INFO]: { | ||||
| 				title: this.$ts.botProtection, | ||||
| 				icon: 'fas fa-shield-alt' | ||||
| 			}, | ||||
| 			provider: null, | ||||
| 			enableHcaptcha: false, | ||||
| 			hcaptchaSiteKey: null, | ||||
| 			hcaptchaSecretKey: null, | ||||
| 			enableRecaptcha: false, | ||||
| 			recaptchaSiteKey: null, | ||||
| 			recaptchaSecretKey: null, | ||||
| 		} | ||||
| 	}, | ||||
| 
 | ||||
| 	async mounted() { | ||||
| 		this.$emit('info', this[symbols.PAGE_INFO]); | ||||
| 	}, | ||||
| 
 | ||||
| 	methods: { | ||||
| 		async init() { | ||||
| 			const meta = await os.api('meta', { detail: true }); | ||||
| 			this.enableHcaptcha = meta.enableHcaptcha; | ||||
| 			this.hcaptchaSiteKey = meta.hcaptchaSiteKey; | ||||
| 			this.hcaptchaSecretKey = meta.hcaptchaSecretKey; | ||||
| 			this.enableRecaptcha = meta.enableRecaptcha; | ||||
| 			this.recaptchaSiteKey = meta.recaptchaSiteKey; | ||||
| 			this.recaptchaSecretKey = meta.recaptchaSecretKey; | ||||
| 
 | ||||
| 			this.provider = this.enableHcaptcha ? 'hcaptcha' : this.enableRecaptcha ? 'recaptcha' : null; | ||||
| 
 | ||||
| 			this.$watch(() => this.provider, () => { | ||||
| 				this.enableHcaptcha = this.provider === 'hcaptcha'; | ||||
| 				this.enableRecaptcha = this.provider === 'recaptcha'; | ||||
| 			}); | ||||
| 		}, | ||||
| 	 | ||||
| 		save() { | ||||
| 			os.apiWithDialog('admin/update-meta', { | ||||
| 				enableHcaptcha: this.enableHcaptcha, | ||||
| 				hcaptchaSiteKey: this.hcaptchaSiteKey, | ||||
| 				hcaptchaSecretKey: this.hcaptchaSecretKey, | ||||
| 				enableRecaptcha: this.enableRecaptcha, | ||||
| 				recaptchaSiteKey: this.recaptchaSiteKey, | ||||
| 				recaptchaSecretKey: this.recaptchaSecretKey, | ||||
| 			}).then(() => { | ||||
| 				fetchInstance(); | ||||
| 			}); | ||||
| 		} | ||||
| 	} | ||||
| }); | ||||
| </script> | ||||
							
								
								
									
										60
									
								
								src/client/pages/instance/database.vue
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								src/client/pages/instance/database.vue
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,60 @@ | |||
| <template> | ||||
| <FormBase> | ||||
| 	<FormSuspense :p="databasePromiseFactory" v-slot="{ result: database }"> | ||||
| 		<FormGroup v-for="table in database" :key="table[0]"> | ||||
| 			<template #label>{{ table[0] }}</template> | ||||
| 			<FormKeyValueView> | ||||
| 				<template #key>Size</template> | ||||
| 				<template #value>{{ bytes(table[1].size) }}</template> | ||||
| 			</FormKeyValueView> | ||||
| 			<FormKeyValueView> | ||||
| 				<template #key>Records</template> | ||||
| 				<template #value>{{ number(table[1].count) }}</template> | ||||
| 			</FormKeyValueView> | ||||
| 		</FormGroup> | ||||
| 	</FormSuspense> | ||||
| </FormBase> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import FormSuspense from '@client/components/form/suspense.vue'; | ||||
| import FormKeyValueView from '@client/components/form/key-value-view.vue'; | ||||
| import FormLink from '@client/components/form/link.vue'; | ||||
| import FormBase from '@client/components/form/base.vue'; | ||||
| import FormGroup from '@client/components/form/group.vue'; | ||||
| import * as os from '@client/os'; | ||||
| import * as symbols from '@client/symbols'; | ||||
| import bytes from '@client/filters/bytes'; | ||||
| import number from '@client/filters/number'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	components: { | ||||
| 		FormSuspense, | ||||
| 		FormKeyValueView, | ||||
| 		FormBase, | ||||
| 		FormGroup, | ||||
| 		FormLink, | ||||
| 	}, | ||||
| 
 | ||||
| 	emits: ['info'], | ||||
| 
 | ||||
| 	data() { | ||||
| 		return { | ||||
| 			[symbols.PAGE_INFO]: { | ||||
| 				title: this.$ts.database, | ||||
| 				icon: 'fas fa-database' | ||||
| 			}, | ||||
| 			databasePromiseFactory: () => os.api('admin/get-table-stats', {}).then(res => Object.entries(res).sort((a, b) => b[1].size - a[1].size)), | ||||
| 		} | ||||
| 	}, | ||||
| 
 | ||||
| 	mounted() { | ||||
| 		this.$emit('info', this[symbols.PAGE_INFO]); | ||||
| 	}, | ||||
| 
 | ||||
| 	methods: { | ||||
| 		bytes, number, | ||||
| 	} | ||||
| }); | ||||
| </script> | ||||
							
								
								
									
										127
									
								
								src/client/pages/instance/email-settings.vue
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										127
									
								
								src/client/pages/instance/email-settings.vue
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,127 @@ | |||
| <template> | ||||
| <FormBase> | ||||
| 	<FormSuspense :p="init"> | ||||
| 		<FormSwitch v-model:value="enableEmail">{{ $ts.enableEmail }}<template #desc>{{ $ts.emailConfigInfo }}</template></FormSwitch> | ||||
| 
 | ||||
| 		<template v-if="enableEmail"> | ||||
| 			<FormInput v-model:value="email" type="email"> | ||||
| 				<span>{{ $ts.emailAddress }}</span> | ||||
| 			</FormInput> | ||||
| 
 | ||||
| 			<div class="_formItem _formNoConcat" v-sticky-container> | ||||
| 				<div class="_formLabel">{{ $ts.smtpConfig }}</div> | ||||
| 				<div class="main"> | ||||
| 					<FormInput v-model:value="smtpHost"> | ||||
| 						<span>{{ $ts.smtpHost }}</span> | ||||
| 					</FormInput> | ||||
| 					<FormInput v-model:value="smtpPort" type="number"> | ||||
| 						<span>{{ $ts.smtpPort }}</span> | ||||
| 					</FormInput> | ||||
| 					<FormInput v-model:value="smtpUser"> | ||||
| 						<span>{{ $ts.smtpUser }}</span> | ||||
| 					</FormInput> | ||||
| 					<FormInput v-model:value="smtpPass" type="password"> | ||||
| 						<span>{{ $ts.smtpPass }}</span> | ||||
| 					</FormInput> | ||||
| 					<FormInfo>{{ $ts.emptyToDisableSmtpAuth }}</FormInfo> | ||||
| 					<FormSwitch v-model:value="smtpSecure">{{ $ts.smtpSecure }}<template #desc>{{ $ts.smtpSecureInfo }}</template></FormSwitch> | ||||
| 				</div> | ||||
| 			</div> | ||||
| 
 | ||||
| 			<FormButton @click="testEmail">{{ $ts.testEmail }}</FormButton> | ||||
| 		</template> | ||||
| 
 | ||||
| 		<FormButton @click="save" primary><i class="fas fa-save"></i> {{ $ts.save }}</FormButton> | ||||
| 	</FormSuspense> | ||||
| </FormBase> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import FormSwitch from '@client/components/form/switch.vue'; | ||||
| import FormInput from '@client/components/form/input.vue'; | ||||
| import FormButton from '@client/components/form/button.vue'; | ||||
| import FormBase from '@client/components/form/base.vue'; | ||||
| import FormGroup from '@client/components/form/group.vue'; | ||||
| import FormInfo from '@client/components/form/info.vue'; | ||||
| import FormSuspense from '@client/components/form/suspense.vue'; | ||||
| import * as os from '@client/os'; | ||||
| import * as symbols from '@client/symbols'; | ||||
| import { fetchInstance } from '@client/instance'; | ||||
| 
 | ||||
| export default defineComponent({ | ||||
| 	components: { | ||||
| 		FormSwitch, | ||||
| 		FormInput, | ||||
| 		FormBase, | ||||
| 		FormGroup, | ||||
| 		FormButton, | ||||
| 		FormInfo, | ||||
| 		FormSuspense, | ||||
| 	}, | ||||
| 
 | ||||
| 	emits: ['info'], | ||||
| 
 | ||||
| 	data() { | ||||
| 		return { | ||||
| 			[symbols.PAGE_INFO]: { | ||||
| 				title: this.$ts.emailServer, | ||||
| 				icon: 'fas fa-envelope' | ||||
| 			}, | ||||
| 			enableEmail: false, | ||||
| 			email: null, | ||||
| 			smtpSecure: false, | ||||
| 			smtpHost: '', | ||||
| 			smtpPort: 0, | ||||
| 			smtpUser: '', | ||||
| 			smtpPass: '', | ||||
| 		} | ||||
| 	}, | ||||
| 
 | ||||
| 	async mounted() { | ||||
| 		this.$emit('info', this[symbols.PAGE_INFO]); | ||||
| 	}, | ||||
| 
 | ||||
| 	methods: { | ||||
| 		async init() { | ||||
| 			const meta = await os.api('meta', { detail: true }); | ||||
| 			this.enableEmail = meta.enableEmail; | ||||
| 			this.email = meta.email; | ||||
| 			this.smtpSecure = meta.smtpSecure; | ||||
| 			this.smtpHost = meta.smtpHost; | ||||
| 			this.smtpPort = meta.smtpPort; | ||||
| 			this.smtpUser = meta.smtpUser; | ||||
| 			this.smtpPass = meta.smtpPass; | ||||
| 		}, | ||||
| 
 | ||||
| 		async testEmail() { | ||||
| 			const { canceled, result: destination } = await os.dialog({ | ||||
| 				title: this.$ts.destination, | ||||
| 				input: { | ||||
| 					placeholder: this.$instance.maintainerEmail | ||||
| 				} | ||||
| 			}); | ||||
| 			if (canceled) return; | ||||
| 			os.apiWithDialog('admin/send-email', { | ||||
| 				to: destination, | ||||
| 				subject: 'Test email', | ||||
| 				text: 'Yo' | ||||
| 			}); | ||||
| 		}, | ||||
| 
 | ||||
| 		save() { | ||||
| 			os.apiWithDialog('admin/update-meta', { | ||||
| 				enableEmail: this.enableEmail, | ||||
| 				email: this.email, | ||||
| 				smtpSecure: this.smtpSecure, | ||||
| 				smtpHost: this.smtpHost, | ||||
| 				smtpPort: this.smtpPort, | ||||
| 				smtpUser: this.smtpUser, | ||||
| 				smtpPass: this.smtpPass, | ||||
| 			}).then(() => { | ||||
| 				fetchInstance(); | ||||
| 			}); | ||||
| 		} | ||||
| 	} | ||||
| }); | ||||
| </script> | ||||
|  | @ -8,22 +8,23 @@ | |||
| > | ||||
| 	<template #header>:{{ emoji.name }}:</template> | ||||
| 
 | ||||
| 	<div class="yigymqpb _section"> | ||||
| 		<img :src="emoji.url" class="img"/> | ||||
| 		<MkInput v-model:value="name"><span>{{ $ts.name }}</span></MkInput> | ||||
| 		<MkInput v-model:value="category" :datalist="categories"><span>{{ $ts.category }}</span></MkInput> | ||||
| 		<MkInput v-model:value="aliases"> | ||||
| 			<span>{{ $ts.tags }}</span> | ||||
| 			<template #desc>{{ $ts.setMultipleBySeparatingWithSpace }}</template> | ||||
| 		</MkInput> | ||||
| 		<MkButton danger @click="del()"><Fa :icon="faTrashAlt"/> {{ $ts.delete }}</MkButton> | ||||
| 	<div class="_monolithic_"> | ||||
| 		<div class="yigymqpb _section"> | ||||
| 			<img :src="emoji.url" class="img"/> | ||||
| 			<MkInput v-model:value="name"><span>{{ $ts.name }}</span></MkInput> | ||||
| 			<MkInput v-model:value="category" :datalist="categories"><span>{{ $ts.category }}</span></MkInput> | ||||
| 			<MkInput v-model:value="aliases"> | ||||
| 				<span>{{ $ts.tags }}</span> | ||||
| 				<template #desc>{{ $ts.setMultipleBySeparatingWithSpace }}</template> | ||||
| 			</MkInput> | ||||
| 			<MkButton danger @click="del()"><i class="fas fa-trash-alt"></i> {{ $ts.delete }}</MkButton> | ||||
| 		</div> | ||||
| 	</div> | ||||
| </XModalWindow> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import { defineComponent } from 'vue'; | ||||
| import { faTrashAlt } from '@fortawesome/free-regular-svg-icons'; | ||||
| import XModalWindow from '@client/components/ui/modal-window.vue'; | ||||
| import MkButton from '@client/components/ui/button.vue'; | ||||
| import MkInput from '@client/components/ui/input.vue'; | ||||
|  | @ -51,7 +52,6 @@ export default defineComponent({ | |||
| 			category: this.emoji.category, | ||||
| 			aliases: this.emoji.aliases?.join(' '), | ||||
| 			categories: [], | ||||
| 			faTrashAlt, | ||||
| 		} | ||||
| 	}, | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,58 +1,52 @@ | |||
| <template> | ||||
| <div class="mk-instance-emojis"> | ||||
| 	<div class="_section" style="padding: 0;"> | ||||
| 		<MkTab v-model:value="tab"> | ||||
| 			<option value="local">{{ $ts.local }}</option> | ||||
| 			<option value="remote">{{ $ts.remote }}</option> | ||||
| 		</MkTab> | ||||
| <div class="ogwlenmc"> | ||||
| 	<MkTab v-model:value="tab"> | ||||
| 		<option value="local">{{ $ts.local }}</option> | ||||
| 		<option value="remote">{{ $ts.remote }}</option> | ||||
| 	</MkTab> | ||||
| 
 | ||||
| 	<div class="local" v-if="tab === 'local'"> | ||||
| 		<MkButton primary @click="add" style="margin: var(--margin) auto;"><i class="fas fa-plus"></i> {{ $ts.addEmoji }}</MkButton> | ||||
| 		<MkInput v-model:value="query" :debounce="true" type="search" style="margin: var(--margin);"><template #icon><i class="fas fa-search"></i></template><span>{{ $ts.search }}</span></MkInput> | ||||
| 		<MkPagination :pagination="pagination" ref="emojis"> | ||||
| 			<template #empty><span>{{ $ts.noCustomEmojis }}</span></template> | ||||
| 			<template #default="{items}"> | ||||
| 				<div class="ldhfsamy"> | ||||
| 					<button class="emoji _panel _button" v-for="emoji in items" :key="emoji.id" @click="edit(emoji)"> | ||||
| 						<img :src="emoji.url" class="img" :alt="emoji.name"/> | ||||
| 						<div class="body"> | ||||
| 							<div class="name _monospace">{{ emoji.name }}</div> | ||||
| 							<div class="info">{{ emoji.category }}</div> | ||||
| 						</div> | ||||
| 					</button> | ||||
| 				</div> | ||||
| 			</template> | ||||
| 		</MkPagination> | ||||
| 	</div> | ||||
| 
 | ||||
| 	<div class="_section"> | ||||
| 		<div class="local" v-if="tab === 'local'"> | ||||
| 			<MkButton primary @click="add" style="margin: 0 auto var(--margin) auto;"><Fa :icon="faPlus"/> {{ $ts.addEmoji }}</MkButton> | ||||
| 			<MkInput v-model:value="query" :debounce="true" type="search"><template #icon><Fa :icon="faSearch"/></template><span>{{ $ts.search }}</span></MkInput> | ||||
| 			<MkPagination :pagination="pagination" ref="emojis"> | ||||
| 				<template #empty><span>{{ $ts.noCustomEmojis }}</span></template> | ||||
| 				<template #default="{items}"> | ||||
| 					<div class="emojis"> | ||||
| 						<button class="emoji _panel _button" v-for="emoji in items" :key="emoji.id" @click="edit(emoji)"> | ||||
| 							<img :src="emoji.url" class="img" :alt="emoji.name"/> | ||||
| 							<div class="body"> | ||||
| 								<div class="name">{{ emoji.name }}</div> | ||||
| 								<div class="info">{{ emoji.category }}</div> | ||||
| 							</div> | ||||
| 						</button> | ||||
| 					</div> | ||||
| 				</template> | ||||
| 			</MkPagination> | ||||
| 		</div> | ||||
| 
 | ||||
| 		<div class="remote" v-else-if="tab === 'remote'"> | ||||
| 			<MkInput v-model:value="queryRemote" :debounce="true" type="search"><template #icon><Fa :icon="faSearch"/></template><span>{{ $ts.search }}</span></MkInput> | ||||
| 			<MkInput v-model:value="host" :debounce="true"><span>{{ $ts.host }}</span></MkInput> | ||||
| 			<MkPagination :pagination="remotePagination" ref="remoteEmojis"> | ||||
| 				<template #empty><span>{{ $ts.noCustomEmojis }}</span></template> | ||||
| 				<template #default="{items}"> | ||||
| 					<div class="emojis"> | ||||
| 						<div class="emoji _panel _button" v-for="emoji in items" :key="emoji.id" @click="remoteMenu(emoji, $event)"> | ||||
| 							<img :src="emoji.url" class="img" :alt="emoji.name"/> | ||||
| 							<div class="body"> | ||||
| 								<div class="name">{{ emoji.name }}</div> | ||||
| 								<div class="info">{{ emoji.host }}</div> | ||||
| 							</div> | ||||
| 	<div class="remote" v-else-if="tab === 'remote'"> | ||||
| 		<MkInput v-model:value="queryRemote" :debounce="true" type="search" style="margin: var(--margin);"><template #icon><i class="fas fa-search"></i></template><span>{{ $ts.search }}</span></MkInput> | ||||
| 		<MkInput v-model:value="host" :debounce="true" style="margin: var(--margin);"><span>{{ $ts.host }}</span></MkInput> | ||||
| 		<MkPagination :pagination="remotePagination" ref="remoteEmojis"> | ||||
| 			<template #empty><span>{{ $ts.noCustomEmojis }}</span></template> | ||||
| 			<template #default="{items}"> | ||||
| 				<div class="ldhfsamy"> | ||||
| 					<div class="emoji _panel _button" v-for="emoji in items" :key="emoji.id" @click="remoteMenu(emoji, $event)"> | ||||
| 						<img :src="emoji.url" class="img" :alt="emoji.name"/> | ||||
| 						<div class="body"> | ||||
| 							<div class="name _monospace">{{ emoji.name }}</div> | ||||
| 							<div class="info">{{ emoji.host }}</div> | ||||
| 						</div> | ||||
| 					</div> | ||||
| 				</template> | ||||
| 			</MkPagination> | ||||
| 		</div> | ||||
| 				</div> | ||||
| 			</template> | ||||
| 		</MkPagination> | ||||
| 	</div> | ||||
| </div> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts"> | ||||
| import { computed, defineComponent } from 'vue'; | ||||
| import { faPlus, faSave, faSearch } from '@fortawesome/free-solid-svg-icons'; | ||||
| import { faTrashAlt, faLaugh } from '@fortawesome/free-regular-svg-icons'; | ||||
| import MkButton from '@client/components/ui/button.vue'; | ||||
| import MkInput from '@client/components/ui/input.vue'; | ||||
| import MkPagination from '@client/components/ui/pagination.vue'; | ||||
|  | @ -69,13 +63,15 @@ export default defineComponent({ | |||
| 		MkPagination, | ||||
| 	}, | ||||
| 
 | ||||
| 	emits: ['info'], | ||||
| 
 | ||||
| 	data() { | ||||
| 		return { | ||||
| 			[symbols.PAGE_INFO]: { | ||||
| 				title: this.$ts.customEmojis, | ||||
| 				icon: faLaugh, | ||||
| 				icon: 'fas fa-laugh', | ||||
| 				action: { | ||||
| 					icon: faPlus, | ||||
| 					icon: 'fas fa-plus', | ||||
| 					handler: this.add | ||||
| 				} | ||||
| 			}, | ||||
|  | @ -98,10 +94,13 @@ export default defineComponent({ | |||
| 					host: (this.host && this.host !== '') ? this.host : null | ||||
| 				})) | ||||
| 			}, | ||||
| 			faTrashAlt, faPlus, faLaugh, faSave, faSearch, | ||||
| 		} | ||||
| 	}, | ||||
| 
 | ||||
| 	async mounted() { | ||||
| 		this.$emit('info', this[symbols.PAGE_INFO]); | ||||
| 	}, | ||||
| 
 | ||||
| 	methods: { | ||||
| 		async add(e) { | ||||
| 			const files = await selectFile(e.currentTarget || e.target, null, true); | ||||
|  | @ -144,7 +143,7 @@ export default defineComponent({ | |||
| 				text: ':' + emoji.name + ':', | ||||
| 			}, { | ||||
| 				text: this.$ts.import, | ||||
| 				icon: faPlus, | ||||
| 				icon: 'fas fa-plus', | ||||
| 				action: () => { this.im(emoji) } | ||||
| 			}], ev.currentTarget || ev.target); | ||||
| 		} | ||||
|  | @ -153,85 +152,86 @@ export default defineComponent({ | |||
| </script> | ||||
| 
 | ||||
| <style lang="scss" scoped> | ||||
| .mk-instance-emojis { | ||||
| 	> ._section { | ||||
| 		> .local { | ||||
| 			.emojis { | ||||
| 				display: grid; | ||||
| 				grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); | ||||
| 				grid-gap: var(--margin); | ||||
| 		 | ||||
| 				> .emoji { | ||||
| 					display: flex; | ||||
| 					align-items: center; | ||||
| 					padding: 12px; | ||||
| 					text-align: left; | ||||
| .ogwlenmc { | ||||
| 	> .local { | ||||
| 		.ldhfsamy { | ||||
| 			display: grid; | ||||
| 			grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); | ||||
| 			grid-gap: 12px; | ||||
| 			margin: var(--margin); | ||||
| 	 | ||||
| 			> .emoji { | ||||
| 				display: flex; | ||||
| 				align-items: center; | ||||
| 				padding: 12px; | ||||
| 				text-align: left; | ||||
| 
 | ||||
| 					&:hover { | ||||
| 						color: var(--accent); | ||||
| 					} | ||||
| 				&:hover { | ||||
| 					color: var(--accent); | ||||
| 				} | ||||
| 
 | ||||
| 					> .img { | ||||
| 						width: 42px; | ||||
| 						height: 42px; | ||||
| 					} | ||||
| 				> .img { | ||||
| 					width: 42px; | ||||
| 					height: 42px; | ||||
| 				} | ||||
| 
 | ||||
| 					> .body { | ||||
| 						padding: 0 0 0 8px; | ||||
| 						white-space: nowrap; | ||||
| 				> .body { | ||||
| 					padding: 0 0 0 8px; | ||||
| 					white-space: nowrap; | ||||
| 					overflow: hidden; | ||||
| 
 | ||||
| 					> .name { | ||||
| 						text-overflow: ellipsis; | ||||
| 						overflow: hidden; | ||||
| 					} | ||||
| 
 | ||||
| 						> .name { | ||||
| 							text-overflow: ellipsis; | ||||
| 							overflow: hidden; | ||||
| 						} | ||||
| 
 | ||||
| 						> .info { | ||||
| 							opacity: 0.5; | ||||
| 							text-overflow: ellipsis; | ||||
| 							overflow: hidden; | ||||
| 						} | ||||
| 					> .info { | ||||
| 						opacity: 0.5; | ||||
| 						text-overflow: ellipsis; | ||||
| 						overflow: hidden; | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 		> .remote { | ||||
| 			.emojis { | ||||
| 				display: grid; | ||||
| 				grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); | ||||
| 				grid-gap: var(--margin); | ||||
| 	> .remote { | ||||
| 		.ldhfsamy { | ||||
| 			display: grid; | ||||
| 			grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); | ||||
| 			grid-gap: 12px; | ||||
| 			margin: var(--margin); | ||||
| 
 | ||||
| 				> .emoji { | ||||
| 					display: flex; | ||||
| 					align-items: center; | ||||
| 					padding: 12px; | ||||
| 					text-align: left; | ||||
| 			> .emoji { | ||||
| 				display: flex; | ||||
| 				align-items: center; | ||||
| 				padding: 12px; | ||||
| 				text-align: left; | ||||
| 
 | ||||
| 					&:hover { | ||||
| 						color: var(--accent); | ||||
| 					} | ||||
| 				&:hover { | ||||
| 					color: var(--accent); | ||||
| 				} | ||||
| 
 | ||||
| 					> .img { | ||||
| 						width: 32px; | ||||
| 						height: 32px; | ||||
| 					} | ||||
| 				> .img { | ||||
| 					width: 32px; | ||||
| 					height: 32px; | ||||
| 				} | ||||
| 
 | ||||
| 					> .body { | ||||
| 						padding: 0 0 0 8px; | ||||
| 						white-space: nowrap; | ||||
| 				> .body { | ||||
| 					padding: 0 0 0 8px; | ||||
| 					white-space: nowrap; | ||||
| 					overflow: hidden; | ||||
| 
 | ||||
| 					> .name { | ||||
| 						text-overflow: ellipsis; | ||||
| 						overflow: hidden; | ||||
| 					} | ||||
| 
 | ||||
| 						> .name { | ||||
| 							text-overflow: ellipsis; | ||||
| 							overflow: hidden; | ||||
| 						} | ||||
| 
 | ||||
| 						> .info { | ||||
| 							opacity: 0.5; | ||||
| 							text-overflow: ellipsis; | ||||
| 							overflow: hidden; | ||||
| 						} | ||||
| 					> .info { | ||||
| 						opacity: 0.5; | ||||
| 						font-size: 90%; | ||||
| 						text-overflow: ellipsis; | ||||
| 						overflow: hidden; | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
|  |  | |||
Some files were not shown because too many files have changed in this diff Show more
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue