diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 989edcda2dc96bfa5a18b27de3c2bb46a2702394..3824d437fe90a09a1fc5583d8610f2fc275f09bc 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -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: diff --git a/package.json b/package.json index f3a4930cc1a68831ad2d405ad10b35e3c77714a6..860a1e149e48a223a80237c9373e91170d82407a 100644 --- a/package.json +++ b/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", diff --git a/src/client/components/abuse-report-window.vue b/src/client/components/abuse-report-window.vue index df5b594c0b10dd08a1017354fa88d89f971aa4f0..d9e1c3966bd6457d31d181f5da3a134f4f186542 100644 --- a/src/client/components/abuse-report-window.vue +++ b/src/client/components/abuse-report-window.vue @@ -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, }; }, diff --git a/src/client/components/captcha.vue b/src/client/components/captcha.vue index 710fcd616922bd0fd4b226ee9342c2aa944fb103..26215df09dbb8b5f63d2be3e5be93a6a02067633 100644 --- a/src/client/components/captcha.vue +++ b/src/client/components/captcha.vue @@ -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`; diff --git a/src/client/components/channel-follow-button.vue b/src/client/components/channel-follow-button.vue index dc0c0faa1f9b4ba7e0641f4304d9de7fdf71091a..6f9405b97f75bed1b1025882ee2753fe49129cd1 100644 --- a/src/client/components/channel-follow-button.vue +++ b/src/client/components/channel-follow-button.vue @@ -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, }; }, diff --git a/src/client/components/channel-preview.vue b/src/client/components/channel-preview.vue index 4dc633bcb7867fbfdd9daa4ddea0f6bdd4c577e6..eb00052a78c8da536263fc79978214b7f7634ad2 100644 --- a/src/client/components/channel-preview.vue +++ b/src/client/components/channel-preview.vue @@ -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, }; }, }); diff --git a/src/client/components/date-separated-list.vue b/src/client/components/date-separated-list.vue index 0f2823d3924dc0c4e3fec7a6b7a149df0509e526..2a861adb0910554bdf0743e357f5054f0471fd26 100644 --- a/src/client/components/date-separated-list.vue +++ b/src/client/components/date-separated-list.vue @@ -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', }) ]) ])); diff --git a/src/client/components/dialog.vue b/src/client/components/dialog.vue index ef30715343d86bb0dc9503dac78378a611cf123b..a673e827d612289e9cbecf840a7ae143af23c485 100644 --- a/src/client/components/dialog.vue +++ b/src/client/components/dialog.vue @@ -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 }; }, diff --git a/src/client/components/drive-file-thumbnail.vue b/src/client/components/drive-file-thumbnail.vue index aadf22ed77cc28a96788738faa38ea68bb75630e..2cb1d986182969c6b35099ef5c0bf830fdd28bf7 100644 --- a/src/client/components/drive-file-thumbnail.vue +++ b/src/client/components/drive-file-thumbnail.vue @@ -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: { diff --git a/src/client/components/drive.file.vue b/src/client/components/drive.file.vue index fb8b50d25a5f6d361893d18eb002876ae6726eb8..293465e42854b4158ab959bd75132e8e5b4922ea 100644 --- a/src/client/components/drive.file.vue +++ b/src/client/components/drive.file.vue @@ -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 }]; diff --git a/src/client/components/drive.folder.vue b/src/client/components/drive.folder.vue index 2822c85680a192e562ee2ca558319e91674e0b7e..6ddd392527d5a1f0c99d74cbec44e40b448da138 100644 --- a/src/client/components/drive.folder.vue +++ b/src/client/components/drive.folder.vue @@ -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; diff --git a/src/client/components/drive.nav-folder.vue b/src/client/components/drive.nav-folder.vue index 89a267b19f1b6bc390de3979c68547b80ba0adc0..913a1b5f927431f7bb5219310e3ca1a7e0a1970f 100644 --- a/src/client/components/drive.nav-folder.vue +++ b/src/client/components/drive.nav-folder.vue @@ -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 }; }, diff --git a/src/client/components/drive.vue b/src/client/components/drive.vue index 103ae9c11ed3782ea2ee7e0004dcad93c86ae3c6..bd5bd8008bcddb30a17d320897570e5b89913767 100644 --- a/src/client/components/drive.vue +++ b/src/client/components/drive.vue @@ -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; } } diff --git a/src/client/components/emoji-picker.section.vue b/src/client/components/emoji-picker.section.vue index 944c507bdcfe03b0e1db8487fdea0bed1f11bace..0ea3761429562ebf2b9b0a50405644cac5f71678 100644 --- a/src/client/components/emoji-picker.section.vue +++ b/src/client/components/emoji-picker.section.vue @@ -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, }; }, diff --git a/src/client/components/emoji-picker.vue b/src/client/components/emoji-picker.vue index a212c150497aa53d451a9d92e6f862ca0c22000c..9bec319af205cabc83a1992e9eb9f105f2a94de2 100644 --- a/src/client/components/emoji-picker.vue +++ b/src/client/components/emoji-picker.vue @@ -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, }; }, diff --git a/src/client/components/file-type-icon.vue b/src/client/components/file-type-icon.vue index 2da9ba0cbda55bf52d9e8fe85bab7f9729e8f870..95200b98c2e89a01db3e266e6c5540e592b0c71f 100644 --- a/src/client/components/file-type-icon.vue +++ b/src/client/components/file-type-icon.vue @@ -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: { diff --git a/src/client/components/follow-button.vue b/src/client/components/follow-button.vue index d2dc9223bdf6314a34ff0a6a329c733374341c00..7199183c6693154be45ae4491f93306161c8797b 100644 --- a/src/client/components/follow-button.vue +++ b/src/client/components/follow-button.vue @@ -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 }; }, diff --git a/src/client/components/form/base.vue b/src/client/components/form/base.vue index 34deb39465f7e05aa552b82af291c7b63c9feaea..132942d527e002b1d244333911f66efc680dd709 100644 --- a/src/client/components/form/base.vue +++ b/src/client/components/form/base.vue @@ -24,6 +24,8 @@ export default defineComponent({ --formXPadding: 32px; --formYPadding: 32px; + --formContentHMargin: 16px; + font-size: 95%; line-height: 1.3em; background: var(--bg); diff --git a/src/client/components/form/form.scss b/src/client/components/form/form.scss index 8c01fad7277f43b4512ec12cb3df252a97ef1956..05994ae65092825b93e16cac29b52cb3c5ad43dc 100644 --- a/src/client/components/form/form.scss +++ b/src/client/components/form/form.scss @@ -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 { diff --git a/src/client/components/form/info.vue b/src/client/components/form/info.vue index a9224c7e6591cff0ab7ffe5c74eea28f550dd10c..9fdcbdca627bd1ac9e878454b4f89558ff5bd897 100644 --- a/src/client/components/form/info.vue +++ b/src/client/components/form/info.vue @@ -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 }; } }); diff --git a/src/client/components/form/input.vue b/src/client/components/form/input.vue index c0fa3e716e4417f1adb91068789c263451a06e3c..942ac4dfd2af17d14ee05cbba63b42d7ed368d5a 100644 --- a/src/client/components/form/input.vue +++ b/src/client/components/form/input.vue @@ -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, }; }, }); diff --git a/src/client/components/form/key-value-view.vue b/src/client/components/form/key-value-view.vue index 85f4febef9d7e083777101caca0f8ece02216a82..ca4c09867fba8ffde40eb7440c640e8fe46a8d93 100644 --- a/src/client/components/form/key-value-view.vue +++ b/src/client/components/form/key-value-view.vue @@ -20,7 +20,7 @@ export default defineComponent({ .anocepby { display: flex; align-items: center; - padding: 14px 16px; + padding: 14px var(--formContentHMargin); > .key { margin-right: 12px; diff --git a/src/client/components/form/link.vue b/src/client/components/form/link.vue index af36bcf22c826b6057a8aa3ce1cce363ce8ddfb8..e1d13c64316b863c921a6086a0063ddca39391cd 100644 --- a/src/client/components/form/link.vue +++ b/src/client/components/form/link.vue @@ -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 }; } }); diff --git a/src/client/components/form/object-view.vue b/src/client/components/form/object-view.vue index cbd4186e56d4f39f6d591f310893edd91633ee8b..59fb62b5e695e2d787f2de05e8fdeb76cba46cbc 100644 --- a/src/client/components/form/object-view.vue +++ b/src/client/components/form/object-view.vue @@ -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; diff --git a/src/client/components/form/radios.vue b/src/client/components/form/radios.vue index 3daa7e5bbdeff5762383304d2b5538ba3a657be9..4cfb7c247e9453f10537a67ef3a745f14d213bad 100644 --- a/src/client/components/form/radios.vue +++ b/src/client/components/form/radios.vue @@ -18,6 +18,9 @@ export default defineComponent({ } }, watch: { + modelValue() { + this.value = this.modelValue; + }, value() { this.$emit('update:modelValue', this.value); } diff --git a/src/client/components/form/select.vue b/src/client/components/form/select.vue index 01f28587dc3032ad492863501a84f5c19209058f..1c5a4734510c891597ae5273bd71f03386e8c486 100644 --- a/src/client/components/form/select.vue +++ b/src/client/components/form/select.vue @@ -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: { diff --git a/src/client/components/form/suspense.vue b/src/client/components/form/suspense.vue index 6a8282733fd0d0b913be792907c8b84e1627bfd4..d04dc07624a235460b06931d89b4b0cb3b9ba9fc 100644 --- a/src/client/components/form/suspense.vue +++ b/src/client/components/form/suspense.vue @@ -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> diff --git a/src/client/components/form/textarea.vue b/src/client/components/form/textarea.vue index 135e16c259184b6600caffe417aba74e238a7268..8f42581a9b1a4a916ca0da100db8a36bb1fdcff7 100644 --- a/src/client/components/form/textarea.vue +++ b/src/client/components/form/textarea.vue @@ -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, }; } }); diff --git a/src/client/components/global/a.vue b/src/client/components/global/a.vue index 7ad62a731044b158595cc72de57c1b58604bc0cf..952dfb1841d36162b71279ae71fc17cdd374f3e6 100644 --- a/src/client/components/global/a.vue +++ b/src/client/components/global/a.vue @@ -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}`); diff --git a/src/client/components/global/error.vue b/src/client/components/global/error.vue index af989b1c57419d288e333167f166badff7e650c8..05a508a65391026b2b196f47fa0767141227e74a 100644 --- a/src/client/components/global/error.vue +++ b/src/client/components/global/error.vue @@ -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 }; }, }); diff --git a/src/client/components/global/url.vue b/src/client/components/global/url.vue index f68a3c00beac31ea797c5c7ed2ab2223e95868a3..e633a57bd85b657eecc1ef96c4dcd31e42d200b2 100644 --- a/src/client/components/global/url.vue +++ b/src/client/components/global/url.vue @@ -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() { diff --git a/src/client/components/google.vue b/src/client/components/google.vue index 20dc1f825a72cff999abbcdc926d5b2b39784466..6d8ae0b5bf6ebbfaf8509bca695c0c728da30e49 100644 --- a/src/client/components/google.vue +++ b/src/client/components/google.vue @@ -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() { diff --git a/src/client/components/instance-stats.vue b/src/client/components/instance-stats.vue index 75abefc2fe69168cfbe7b37c82013f048e006363..432c9a1bb986df202a60b0fd3ea0df86b7f294eb 100644 --- a/src/client/components/instance-stats.vue +++ b/src/client/components/instance-stats.vue @@ -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> diff --git a/src/client/components/launch-pad.vue b/src/client/components/launch-pad.vue index 7610b44eb57040bb09b296526ce8f45a6255fde8..e3d24c70f25f3e1584162f21c1b6f035a50b9b25 100644 --- a/src/client/components/launch-pad.vue +++ b/src/client/components/launch-pad.vue @@ -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; diff --git a/src/client/components/link.vue b/src/client/components/link.vue index cc7db8c2f57e9824cf95243c17bba0ac04f451d7..9712c778a9ef241565b4c31be483de44687e98b0 100644 --- a/src/client/components/link.vue +++ b/src/client/components/link.vue @@ -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: { diff --git a/src/client/components/media-banner.vue b/src/client/components/media-banner.vue index 29d7c727f600dcde52c3a7803dd8417ee0961c54..34065557bf43967af218730046984611bf4bf6ee 100644 --- a/src/client/components/media-banner.vue +++ b/src/client/components/media-banner.vue @@ -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() { diff --git a/src/client/components/media-image.vue b/src/client/components/media-image.vue index 57604661384ef5eefb25eb7b7596a4e1cee5a7f3..0573b2592d352df91c500c21aee2877d44740df0 100644 --- a/src/client/components/media-image.vue +++ b/src/client/components/media-image.vue @@ -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: { diff --git a/src/client/components/media-video.vue b/src/client/components/media-video.vue index b6f63cb65d1f8fa8c87d5c22a203bbaad8e01315..020b5e93a80777f5860b196d038c6f7d48a36836 100644 --- a/src/client/components/media-video.vue +++ b/src/client/components/media-video.vue @@ -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() { diff --git a/src/client/components/modal-page-window.vue b/src/client/components/modal-page-window.vue index 474a67f98543102ee4a9c7bb89de7475fafc0f53..7be4045a849f2186de9e7b21db85c975beb3da88 100644 --- a/src/client/components/modal-page-window.vue +++ b/src/client/components/modal-page-window.vue @@ -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> diff --git a/src/client/components/note-detailed.vue b/src/client/components/note-detailed.vue index 50e76e5299b7dc6559676392889bc3d6a3b71de0..6040ad378f712006dc0ec740f7c8a3076e6612cc 100644 --- a/src/client/components/note-detailed.vue +++ b/src/client/components/note-detailed.vue @@ -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; } diff --git a/src/client/components/note-header.vue b/src/client/components/note-header.vue index ab40c5fd4a57c641f9fd925d3fca2850aba597a9..1cd6463f9bfea9b54268e28434635b2e2f5d83e7 100644 --- a/src/client/components/note-header.vue +++ b/src/client/components/note-header.vue @@ -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 }; }, diff --git a/src/client/components/note.vue b/src/client/components/note.vue index 0e153033ca01af1ee053365843a07fa35c4e1ac9..504d07c0eb53c0ebfcf0771542293a369dd8a2a4 100644 --- a/src/client/components/note.vue +++ b/src/client/components/note.vue @@ -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; } diff --git a/src/client/components/notification.vue b/src/client/components/notification.vue index 2b8b440ced0b09942a9cbfa2013a333a3e8a8883..9badd7a70864327b1acdec5155d2819f68df5127 100644 --- a/src/client/components/notification.vue +++ b/src/client/components/notification.vue @@ -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; } } diff --git a/src/client/components/page-window.vue b/src/client/components/page-window.vue index 1afde255010129dbe561c5257dcfdd38d1028908..26499f7054b29164f3d8b2283570839a829acbc6 100644 --- a/src/client/components/page-window.vue +++ b/src/client/components/page-window.vue @@ -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); diff --git a/src/client/components/page/page.post.vue b/src/client/components/page/page.post.vue index 926d06ae808d473a919b331d841c55b2098a7f13..1dfb506d5f8f8ff622e847ceaf95cf9e7d451f81 100644 --- a/src/client/components/page/page.post.vue +++ b/src/client/components/page/page.post.vue @@ -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: { diff --git a/src/client/components/poll-editor.vue b/src/client/components/poll-editor.vue index 3503d3df7165edd0a7caf86acdadca016ef70eb3..0ade2c3ba0d83378f6e8c47556b0723c3df25cc2 100644 --- a/src/client/components/poll-editor.vue +++ b/src/client/components/poll-editor.vue @@ -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; } } diff --git a/src/client/components/poll.vue b/src/client/components/poll.vue index 6cf6a8e9180877a998252bf7be8cb69a2e9b6d9a..463ddab7211806ae1760f3ce55fbfc50461c517f 100644 --- a/src/client/components/poll.vue +++ b/src/client/components/poll.vue @@ -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; } diff --git a/src/client/components/post-form-attaches.vue b/src/client/components/post-form-attaches.vue index f2eed304419527d0bfc86855ca726247752e9c17..eba7e7af366cbc606b593b5defb6aa1f402026cf 100644 --- a/src/client/components/post-form-attaches.vue +++ b/src/client/components/post-form-attaches.vue @@ -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); } diff --git a/src/client/components/post-form.vue b/src/client/components/post-form.vue index 4c6a9ebc95239e74ccc396b587a577f47e2b125d..c5186577f37c2a58c54c3b78b5d2c79f2ebb752f 100644 --- a/src/client/components/post-form.vue +++ b/src/client/components/post-form.vue @@ -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; } } diff --git a/src/client/components/remote-caution.vue b/src/client/components/remote-caution.vue index c9c5ceea4c1f8948e83c9a2c37fbe11ad0900ff2..985ae446942f6e85be96fe824f39928131533fdc 100644 --- a/src/client/components/remote-caution.vue +++ b/src/client/components/remote-caution.vue @@ -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 }; } }); diff --git a/src/client/components/signin.vue b/src/client/components/signin.vue index 1cd79bac1d697579e85c184f2d758121a71940ce..2c883e0c32c0cf07c77984b57e6161ec3b6ad946 100755 --- a/src/client/components/signin.vue +++ b/src/client/components/signin.vue @@ -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 }; }, diff --git a/src/client/components/signup.vue b/src/client/components/signup.vue index 66d01213bc8fbef8a678e8590224d442e24ae5c2..671642b2915b289976d6be6372b5f315392818db 100644 --- a/src/client/components/signup.vue +++ b/src/client/components/signup.vue @@ -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 } }, diff --git a/src/client/components/sub-note-content.vue b/src/client/components/sub-note-content.vue index 384bcb4563c0f53c1017c3d80e7f018216898ae7..ff89a9887b1ee02a3f85845977de12d0e380e921 100644 --- a/src/client/components/sub-note-content.vue +++ b/src/client/components/sub-note-content.vue @@ -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 }; } }); diff --git a/src/client/components/tab.vue b/src/client/components/tab.vue index aca4d32a220f47fa9fcf2416abf41cbd30ef8c63..96cbe50fb194ae5db5f1683b78eb73918b95c000 100644 --- a/src/client/components/tab.vue +++ b/src/client/components/tab.vue @@ -29,6 +29,7 @@ export default defineComponent({ <style lang="scss"> .pxhvhrfw { display: flex; + font-size: 90%; > button { flex: 1; diff --git a/src/client/components/taskmanager.vue b/src/client/components/taskmanager.vue index 1339e2e35291538bc00770b5f7129ea9664889c6..cb8cb7874871ed9bc30a73eff90ef7cbc34c7d1b 100644 --- a/src/client/components/taskmanager.vue +++ b/src/client/components/taskmanager.vue @@ -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, }; }, }); diff --git a/src/client/components/ui/container.vue b/src/client/components/ui/container.vue index ecd48876e826b84d47ad354a9287cc57c6bfd151..cfd928518e45e59e47aeddae825d4a46138acbc5 100644 --- a/src/client/components/ui/container.vue +++ b/src/client/components/ui/container.vue @@ -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; } diff --git a/src/client/components/ui/folder.vue b/src/client/components/ui/folder.vue index aee3c0ccaa392ab317cdd4a769fed67cf7386a6d..4281ec77788cfa73bc44c0061100ef207db3d4c9 100644 --- a/src/client/components/ui/folder.vue +++ b/src/client/components/ui/folder.vue @@ -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; } diff --git a/src/client/components/ui/info.vue b/src/client/components/ui/info.vue index ad1b9ebb5855ffce2c289b5bc9113636a6204212..513682ef55ce224e9dd2cf0079c25aabc3536b53 100644 --- a/src/client/components/ui/info.vue +++ b/src/client/components/ui/info.vue @@ -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 }; } }); diff --git a/src/client/components/ui/input.vue b/src/client/components/ui/input.vue index 302d96d026899beaac99f70e4b50950f08d2ac65..7415d9896b93c5b43c275bd6b63d9554c8e2a3ae 100644 --- a/src/client/components/ui/input.vue +++ b/src/client/components/ui/input.vue @@ -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, }; }, }); diff --git a/src/client/components/ui/menu.vue b/src/client/components/ui/menu.vue index 1550fe40c7361b0dc8cc7be5ee2b41826baabaac..eb9645077429f6ce59ef6f398ced0c012169a723 100644 --- a/src/client/components/ui/menu.vue +++ b/src/client/components/ui/menu.vue @@ -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; diff --git a/src/client/components/ui/modal-window.vue b/src/client/components/ui/modal-window.vue index 90b803801da4d61dca2390331f28bc7101e5a423..2d2b587662b057b1547533fdab3aa9311cf8a8fc 100644 --- a/src/client/components/ui/modal-window.vue +++ b/src/client/components/ui/modal-window.vue @@ -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 }; }, diff --git a/src/client/components/ui/pagination.vue b/src/client/components/ui/pagination.vue index 13181d39e23ec96ab15dff81cabab15922de73fe..ac8ed01e1272f51ec6ee5d27da0fb17c527b55ce 100644 --- a/src/client/components/ui/pagination.vue +++ b/src/client/components/ui/pagination.vue @@ -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; diff --git a/src/client/components/ui/select.vue b/src/client/components/ui/select.vue index d9250a62cd500aa7a479d815eb10d6f7eb6b1e7b..e78c44fe0d542fb3c59cf897068df8f7a25a06f2 100644 --- a/src/client/components/ui/select.vue +++ b/src/client/components/ui/select.vue @@ -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: { diff --git a/src/client/components/ui/window.vue b/src/client/components/ui/window.vue index 70676cdaf5f6cb70ad3e17c0cebb15fda5495431..ce621ac6fd383aed887ed2223bc5cbdaba2f538c 100644 --- a/src/client/components/ui/window.vue +++ b/src/client/components/ui/window.vue @@ -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 }; }, diff --git a/src/client/components/url-preview.vue b/src/client/components/url-preview.vue index 7495da6f24745a6e74e76c9adee7b0d6249c879d..1d44b045784543eaab6f0f63949e824e1c3b473e 100644 --- a/src/client/components/url-preview.vue +++ b/src/client/components/url-preview.vue @@ -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 }; }, diff --git a/src/client/components/user-list.vue b/src/client/components/user-list.vue index 38d9df63bb00940ef5efb616976490369b8eaee6..a7162ddcc259b79d7cd16215be6e377ba6cbcc58 100644 --- a/src/client/components/user-list.vue +++ b/src/client/components/user-list.vue @@ -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; } } diff --git a/src/client/components/user-online-indicator.vue b/src/client/components/user-online-indicator.vue index bb98978bba89eb5161807f720b1b080b3f6877c7..afaf0e8736d4e70b0aae0a87efecb512181f9e40 100644 --- a/src/client/components/user-online-indicator.vue +++ b/src/client/components/user-online-indicator.vue @@ -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; diff --git a/src/client/components/user-select-dialog.vue b/src/client/components/user-select-dialog.vue index a243e182e8a7002847aa6a3c90c0e868509fea80..620c8eee280a7e952a3cee4bdb40f28880799a7e 100644 --- a/src/client/components/user-select-dialog.vue +++ b/src/client/components/user-select-dialog.vue @@ -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 }; }, diff --git a/src/client/components/users-dialog.vue b/src/client/components/users-dialog.vue index ebf867f702ffd5cbac249c63fc632886448f6ea8..90cd926f0c88d2528a8f655f19dc4eadbc3e7f68 100644 --- a/src/client/components/users-dialog.vue +++ b/src/client/components/users-dialog.vue @@ -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 }; }, diff --git a/src/client/components/visibility-picker.vue b/src/client/components/visibility-picker.vue index caa2b116a6fb0fb6ffdb842f13094a7a7709dbb8..492ec092e3d58d84b1d42be5c54bfb902e406712 100644 --- a/src/client/components/visibility-picker.vue +++ b/src/client/components/visibility-picker.vue @@ -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: { diff --git a/src/client/components/waiting-dialog.vue b/src/client/components/waiting-dialog.vue index c3a265af9cf3e9aebe9fa03b6e0bad4c270b3e09..ea9f6756b29b595f843a81656071ebfdb45411e9 100644 --- a/src/client/components/waiting-dialog.vue +++ b/src/client/components/waiting-dialog.vue @@ -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 { diff --git a/src/client/components/widgets.vue b/src/client/components/widgets.vue index 993b843cb1a4c317def1f65bdfa96677b41a6ede..790ca5611230982e9e4b49310e6376641ae1245c 100644 --- a/src/client/components/widgets.vue +++ b/src/client/components/widgets.vue @@ -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 }; }, diff --git a/src/client/directives/click-anime.ts b/src/client/directives/click-anime.ts new file mode 100644 index 0000000000000000000000000000000000000000..864155f076681b14f1c70212400bdd9f35f8bf25 --- /dev/null +++ b/src/client/directives/click-anime.ts @@ -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; diff --git a/src/client/directives/index.ts b/src/client/directives/index.ts index 6513350e0dd5186594734f91d6a7ffe77373a822..f0a0123771e3060e2509bec1965dc050872ffd24 100644 --- a/src/client/directives/index.ts +++ b/src/client/directives/index.ts @@ -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); } diff --git a/src/client/init.ts b/src/client/init.ts index daedce4aee4b0fde5944783c909381cb4210fa60..a4465d75c3dc91c33c718bd444dabd6c5d24e92a 100644 --- a/src/client/init.ts +++ b/src/client/init.ts @@ -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); diff --git a/src/client/pages/_error_.vue b/src/client/pages/_error_.vue index 67c1a1991c426df1fb5834ae8c42d23e3ed13f6d..6caecd6eaf61e4694656e778c842384ba99e1f2e 100644 --- a/src/client/pages/_error_.vue +++ b/src/client/pages/_error_.vue @@ -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 }; }, }); diff --git a/src/client/pages/about-misskey.vue b/src/client/pages/about-misskey.vue index aae8a7052a0081d87dca24007205ea77fa65b5ae..1d57c80810eb79878b49dbc3a51320c7177df12c 100644 --- a/src/client/pages/about-misskey.vue +++ b/src/client/pages/about-misskey.vue @@ -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, } }, diff --git a/src/client/pages/about.vue b/src/client/pages/about.vue index 4084256cf4f6b4f7ff609bbfdb80685a1f5b277d..4f70998eeec145089ee0392becf0d76f165a3fbd 100644 --- a/src/client/pages/about.vue +++ b/src/client/pages/about.vue @@ -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 } }, diff --git a/src/client/pages/advanced-theme-editor.vue b/src/client/pages/advanced-theme-editor.vue index fff525a32ded0614f17cb1faf9a1155303a74f03..b40d9808ca337b059e2a3cd6c7a5f47cab0f21a1 100644 --- a/src/client/pages/advanced-theme-editor.vue +++ b/src/client/pages/advanced-theme-editor.vue @@ -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, } }, diff --git a/src/client/pages/announcements.vue b/src/client/pages/announcements.vue index 4e5f0e7f9cb384c9b994945f2a2bd72c4265fa8e..a7ccb0358867ce06296bd47ae890dda4c1598a67 100644 --- a/src/client/pages/announcements.vue +++ b/src/client/pages/announcements.vue @@ -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, }; }, diff --git a/src/client/pages/api-console.vue b/src/client/pages/api-console.vue index 669e8147786ce42d767a824122d80424040bfbe1..b153d10396f56731f6cf30c0ee1bb7fab04d3af4 100644 --- a/src/client/pages/api-console.vue +++ b/src/client/pages/api-console.vue @@ -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 }; }, diff --git a/src/client/pages/channel-editor.vue b/src/client/pages/channel-editor.vue index 7216aaec4a7b71ed5571180d4b19c95fbe83aa50..bc772d34faa6af474f47f057649308e146d12bb4 100644 --- a/src/client/pages/channel-editor.vue +++ b/src/client/pages/channel-editor.vue @@ -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, }; }, diff --git a/src/client/pages/channel.vue b/src/client/pages/channel.vue index f98bb41a38988e8f6c1a26d0bfaac1517351c06c..1504264af56a15469bf5053bfd530529a6c8b814 100644 --- a/src/client/pages/channel.vue +++ b/src/client/pages/channel.vue @@ -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; } } diff --git a/src/client/pages/channels.vue b/src/client/pages/channels.vue index ebf1e7b87118ce60d03ac0e3f9275e00edfdeb96..7e3302959b9898282427b425add303941bdf8fce 100644 --- a/src/client/pages/channels.vue +++ b/src/client/pages/channels.vue @@ -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: { diff --git a/src/client/pages/clip.vue b/src/client/pages/clip.vue index ca3e051d517ef05d73da1a6e9ca9c97d94c77ca9..8777975557dba038f6461e95674dbe035f0aa79c 100644 --- a/src/client/pages/clip.vue +++ b/src/client/pages/clip.vue @@ -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 () => { diff --git a/src/client/pages/doc.vue b/src/client/pages/doc.vue index cf3628dafbfa1c6e3d745a0bc3fea3d984f7bff6..a4cf25033e0160df7210cb170424fe3c8ce6bf7e 100644 --- a/src/client/pages/doc.vue +++ b/src/client/pages/doc.vue @@ -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, diff --git a/src/client/pages/docs.vue b/src/client/pages/docs.vue index 92eab86716e021a55b12a2fead2a42f85b41961e..e51528f83da6c150a79ca90b663ad7a27bd3596b 100644 --- a/src/client/pages/docs.vue +++ b/src/client/pages/docs.vue @@ -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 } }, diff --git a/src/client/pages/drive.vue b/src/client/pages/drive.vue index 33bbfbc50ff13aa5cee64dbcef378de47f06470b..753114f725c3f6bc721fd77c394c7ada35aeec10 100644 --- a/src/client/pages/drive.vue +++ b/src/client/pages/drive.vue @@ -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, diff --git a/src/client/pages/explore.vue b/src/client/pages/explore.vue index dc0803237b0716dd090fdc804ca5d21f385b737b..7bcb09d8c5e742a0d59f3ddeb618b8b4cf292de5 100644 --- a/src/client/pages/explore.vue +++ b/src/client/pages/explore.vue @@ -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, }; }, diff --git a/src/client/pages/favorites.vue b/src/client/pages/favorites.vue index 7ecd3271378a82ffafae53833d25d2191828d394..408ab222b57971af8e61649ad0747e707d9b7cc4 100644 --- a/src/client/pages/favorites.vue +++ b/src/client/pages/favorites.vue @@ -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', diff --git a/src/client/pages/featured.vue b/src/client/pages/featured.vue index cd7343f5831707824782b422d91f2540d5d38821..21818ba617d81d94a26fc6c71b753f3187ac4ac7 100644 --- a/src/client/pages/featured.vue +++ b/src/client/pages/featured.vue @@ -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 }; }, diff --git a/src/client/pages/follow-requests.vue b/src/client/pages/follow-requests.vue index 31c00d63cd4d5c1bc2cd93a3afab28e05ce2ff59..9f27a6baa864da238f0935576a3dd0428fd4438f 100644 --- a/src/client/pages/follow-requests.vue +++ b/src/client/pages/follow-requests.vue @@ -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 }; }, diff --git a/src/client/pages/instance-info.vue b/src/client/pages/instance-info.vue index a3cd4029938e12de96fb899ce5c77b81f0b48d72..662b82ddb1a47e3bbebad0c7508b5c2af5685cb0 100644 --- a/src/client/pages/instance-info.vue +++ b/src/client/pages/instance-info.vue @@ -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'); } diff --git a/src/client/pages/instance/abuses.vue b/src/client/pages/instance/abuses.vue index c8355b068365ae2a0a77dd8ab6eb624a96427d94..73196027dc1b041da829a5581ca1acf402ec0f23 100644 --- a/src/client/pages/instance/abuses.vue +++ b/src/client/pages/instance/abuses.vue @@ -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; diff --git a/src/client/pages/instance/announcements.vue b/src/client/pages/instance/announcements.vue index f9d58a29c48cd3684d07396940f1134907e67809..ac0e9d51357c7a82e6f48c320dca7ef59f2c6b13 100644 --- a/src/client/pages/instance/announcements.vue +++ b/src/client/pages/instance/announcements.vue @@ -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> diff --git a/src/client/pages/instance/bot-protection.vue b/src/client/pages/instance/bot-protection.vue new file mode 100644 index 0000000000000000000000000000000000000000..449b8a233d252020a0d7835434ec83f10bd96b9a --- /dev/null +++ b/src/client/pages/instance/bot-protection.vue @@ -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> diff --git a/src/client/pages/instance/database.vue b/src/client/pages/instance/database.vue new file mode 100644 index 0000000000000000000000000000000000000000..a41d61ce2b11dc9a308e9c870dfdc998b43fb6fb --- /dev/null +++ b/src/client/pages/instance/database.vue @@ -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> diff --git a/src/client/pages/instance/email-settings.vue b/src/client/pages/instance/email-settings.vue new file mode 100644 index 0000000000000000000000000000000000000000..9965a1420fb0567ac12525a95924f6df6fe5dcb2 --- /dev/null +++ b/src/client/pages/instance/email-settings.vue @@ -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> diff --git a/src/client/pages/instance/emoji-edit-dialog.vue b/src/client/pages/instance/emoji-edit-dialog.vue index 34eca47b4e18147595510db3d1e23bfe1db38189..f7a36715845305845bbd2609fe9ecd8cd6f39565 100644 --- a/src/client/pages/instance/emoji-edit-dialog.vue +++ b/src/client/pages/instance/emoji-edit-dialog.vue @@ -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, } }, diff --git a/src/client/pages/instance/emojis.vue b/src/client/pages/instance/emojis.vue index 722ed0063f7a2eb5ed1da937cb69a501a4add1e5..fd641703cb90f9a5effb23ae17c9f14d844c6ca4 100644 --- a/src/client/pages/instance/emojis.vue +++ b/src/client/pages/instance/emojis.vue @@ -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; - - &:hover { - color: var(--accent); - } +.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); + } - > .img { - width: 42px; - height: 42px; - } + > .img { + width: 42px; + height: 42px; + } - > .body { - padding: 0 0 0 8px; - white-space: nowrap; - overflow: hidden; + > .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; + + &:hover { + color: var(--accent); + } - > .emoji { - display: flex; - align-items: center; - padding: 12px; - text-align: left; + > .img { + width: 32px; + height: 32px; + } - &:hover { - color: var(--accent); - } + > .body { + padding: 0 0 0 8px; + white-space: nowrap; + overflow: hidden; - > .img { - width: 32px; - height: 32px; + > .name { + text-overflow: ellipsis; + overflow: hidden; } - > .body { - padding: 0 0 0 8px; - white-space: nowrap; + > .info { + opacity: 0.5; + font-size: 90%; + text-overflow: ellipsis; overflow: hidden; - - > .name { - text-overflow: ellipsis; - overflow: hidden; - } - - > .info { - opacity: 0.5; - text-overflow: ellipsis; - overflow: hidden; - } } } } diff --git a/src/client/pages/instance/federation.vue b/src/client/pages/instance/federation.vue index 2a820e5baf4e4568013e5d9954491ed82ec950f0..96f72fed44ba748eb749232e509f904df17236cb 100644 --- a/src/client/pages/instance/federation.vue +++ b/src/client/pages/instance/federation.vue @@ -1,66 +1,60 @@ <template> -<div> - <div class="_section"> - <div class="_content"> - <MkInput v-model:value="host" :debounce="true"><span>{{ $ts.host }}</span></MkInput> - <div class="inputs" style="display: flex;"> - <MkSelect v-model:value="state" style="margin: 0; flex: 1;"> - <template #label>{{ $ts.state }}</template> - <option value="all">{{ $ts.all }}</option> - <option value="federating">{{ $ts.federating }}</option> - <option value="subscribing">{{ $ts.subscribing }}</option> - <option value="publishing">{{ $ts.publishing }}</option> - <option value="suspended">{{ $ts.suspended }}</option> - <option value="blocked">{{ $ts.blocked }}</option> - <option value="notResponding">{{ $ts.notResponding }}</option> - </MkSelect> - <MkSelect v-model:value="sort" style="margin: 0; flex: 1;"> - <template #label>{{ $ts.sort }}</template> - <option value="+pubSub">{{ $ts.pubSub }} ({{ $ts.descendingOrder }})</option> - <option value="-pubSub">{{ $ts.pubSub }} ({{ $ts.ascendingOrder }})</option> - <option value="+notes">{{ $ts.notes }} ({{ $ts.descendingOrder }})</option> - <option value="-notes">{{ $ts.notes }} ({{ $ts.ascendingOrder }})</option> - <option value="+users">{{ $ts.users }} ({{ $ts.descendingOrder }})</option> - <option value="-users">{{ $ts.users }} ({{ $ts.ascendingOrder }})</option> - <option value="+following">{{ $ts.following }} ({{ $ts.descendingOrder }})</option> - <option value="-following">{{ $ts.following }} ({{ $ts.ascendingOrder }})</option> - <option value="+followers">{{ $ts.followers }} ({{ $ts.descendingOrder }})</option> - <option value="-followers">{{ $ts.followers }} ({{ $ts.ascendingOrder }})</option> - <option value="+caughtAt">{{ $ts.caughtAt }} ({{ $ts.descendingOrder }})</option> - <option value="-caughtAt">{{ $ts.caughtAt }} ({{ $ts.ascendingOrder }})</option> - <option value="+lastCommunicatedAt">{{ $ts.lastCommunicatedAt }} ({{ $ts.descendingOrder }})</option> - <option value="-lastCommunicatedAt">{{ $ts.lastCommunicatedAt }} ({{ $ts.ascendingOrder }})</option> - <option value="+driveUsage">{{ $ts.driveUsage }} ({{ $ts.descendingOrder }})</option> - <option value="-driveUsage">{{ $ts.driveUsage }} ({{ $ts.ascendingOrder }})</option> - <option value="+driveFiles">{{ $ts.driveFiles }} ({{ $ts.descendingOrder }})</option> - <option value="-driveFiles">{{ $ts.driveFiles }} ({{ $ts.ascendingOrder }})</option> - </MkSelect> - </div> +<div class="enuoauvw"> + <div class="query"> + <MkInput v-model:value="host" :debounce="true"><span>{{ $ts.host }}</span></MkInput> + <div class="inputs" style="display: flex;"> + <MkSelect v-model:value="state" style="margin: 0; flex: 1;"> + <template #label>{{ $ts.state }}</template> + <option value="all">{{ $ts.all }}</option> + <option value="federating">{{ $ts.federating }}</option> + <option value="subscribing">{{ $ts.subscribing }}</option> + <option value="publishing">{{ $ts.publishing }}</option> + <option value="suspended">{{ $ts.suspended }}</option> + <option value="blocked">{{ $ts.blocked }}</option> + <option value="notResponding">{{ $ts.notResponding }}</option> + </MkSelect> + <MkSelect v-model:value="sort" style="margin: 0; flex: 1;"> + <template #label>{{ $ts.sort }}</template> + <option value="+pubSub">{{ $ts.pubSub }} ({{ $ts.descendingOrder }})</option> + <option value="-pubSub">{{ $ts.pubSub }} ({{ $ts.ascendingOrder }})</option> + <option value="+notes">{{ $ts.notes }} ({{ $ts.descendingOrder }})</option> + <option value="-notes">{{ $ts.notes }} ({{ $ts.ascendingOrder }})</option> + <option value="+users">{{ $ts.users }} ({{ $ts.descendingOrder }})</option> + <option value="-users">{{ $ts.users }} ({{ $ts.ascendingOrder }})</option> + <option value="+following">{{ $ts.following }} ({{ $ts.descendingOrder }})</option> + <option value="-following">{{ $ts.following }} ({{ $ts.ascendingOrder }})</option> + <option value="+followers">{{ $ts.followers }} ({{ $ts.descendingOrder }})</option> + <option value="-followers">{{ $ts.followers }} ({{ $ts.ascendingOrder }})</option> + <option value="+caughtAt">{{ $ts.caughtAt }} ({{ $ts.descendingOrder }})</option> + <option value="-caughtAt">{{ $ts.caughtAt }} ({{ $ts.ascendingOrder }})</option> + <option value="+lastCommunicatedAt">{{ $ts.lastCommunicatedAt }} ({{ $ts.descendingOrder }})</option> + <option value="-lastCommunicatedAt">{{ $ts.lastCommunicatedAt }} ({{ $ts.ascendingOrder }})</option> + <option value="+driveUsage">{{ $ts.driveUsage }} ({{ $ts.descendingOrder }})</option> + <option value="-driveUsage">{{ $ts.driveUsage }} ({{ $ts.ascendingOrder }})</option> + <option value="+driveFiles">{{ $ts.driveFiles }} ({{ $ts.descendingOrder }})</option> + <option value="-driveFiles">{{ $ts.driveFiles }} ({{ $ts.ascendingOrder }})</option> + </MkSelect> </div> </div> - <div class="_section"> - <div class="_content"> - <MkPagination :pagination="pagination" #default="{items}" ref="instances" :key="host + state"> - <div class="ppgwaixt _panel" v-for="instance in items" :key="instance.id" @click="info(instance)"> - <div class="host"><Fa :icon="faCircle" class="indicator" :class="getStatus(instance)"/><b>{{ instance.host }}</b></div> - <div class="status"> - <span class="sub" v-if="instance.followersCount > 0"><Fa :icon="faCaretDown" class="icon"/>Sub</span> - <span class="sub" v-else><Fa :icon="faCaretDown" class="icon"/>-</span> - <span class="pub" v-if="instance.followingCount > 0"><Fa :icon="faCaretUp" class="icon"/>Pub</span> - <span class="pub" v-else><Fa :icon="faCaretUp" class="icon"/>-</span> - <span class="lastCommunicatedAt"><Fa :icon="faExchangeAlt" class="icon"/><MkTime :time="instance.lastCommunicatedAt"/></span> - <span class="latestStatus"><Fa :icon="faTrafficLight" class="icon"/>{{ instance.latestStatus || '-' }}</span> - </div> - </div> - </MkPagination> + + <MkPagination :pagination="pagination" #default="{items}" ref="instances" :key="host + state"> + <div class="ppgwaixt _block" v-for="instance in items" :key="instance.id" @click="info(instance)"> + <div class="host"><i class="fas fa-circle indicator" :class="getStatus(instance)"></i><b>{{ instance.host }}</b></div> + <div class="status"> + <span class="sub" v-if="instance.followersCount > 0"><i class="fas fa-caret-down icon"></i>Sub</span> + <span class="sub" v-else><i class="fas fa-caret-down icon"></i>-</span> + <span class="pub" v-if="instance.followingCount > 0"><i class="fas fa-caret-up icon"></i>Pub</span> + <span class="pub" v-else><i class="fas fa-caret-up icon"></i>-</span> + <span class="lastCommunicatedAt"><i class="fas fa-exchange-alt icon"></i><MkTime :time="instance.lastCommunicatedAt"/></span> + <span class="latestStatus"><i class="fas fa-traffic-light icon"></i>{{ instance.latestStatus || '-' }}</span> + </div> </div> - </div> + </MkPagination> </div> </template> <script lang="ts"> import { defineComponent } from 'vue'; -import { faGlobe, faCircle, faExchangeAlt, faCaretDown, faCaretUp, faTrafficLight } from '@fortawesome/free-solid-svg-icons'; import MkButton from '@client/components/ui/button.vue'; import MkInput from '@client/components/ui/input.vue'; import MkSelect from '@client/components/ui/select.vue'; @@ -77,11 +71,13 @@ export default defineComponent({ MkPagination, }, + emits: ['info'], + data() { return { [symbols.PAGE_INFO]: { title: this.$ts.federation, - icon: faGlobe + icon: 'fas fa-globe' }, host: '', state: 'federating', @@ -103,7 +99,6 @@ export default defineComponent({ {}) }) }, - faGlobe, faCircle, faExchangeAlt, faCaretDown, faCaretUp, faTrafficLight } }, @@ -116,6 +111,10 @@ export default defineComponent({ } }, + mounted() { + this.$emit('info', this[symbols.PAGE_INFO]); + }, + methods: { getStatus(instance) { if (instance.isSuspended) return 'off'; @@ -133,6 +132,12 @@ export default defineComponent({ </script> <style lang="scss" scoped> +.enuoauvw { + > .query { + margin: var(--margin); + } +} + .ppgwaixt { cursor: pointer; padding: 16px; diff --git a/src/client/pages/instance/file-dialog.vue b/src/client/pages/instance/file-dialog.vue index 85c03e3dcea58f41710f471d7c34939e44ce6790..74a755fa15dac5c79ae49adc5793d43e56b1201f 100644 --- a/src/client/pages/instance/file-dialog.vue +++ b/src/client/pages/instance/file-dialog.vue @@ -21,8 +21,8 @@ </div> <div class="_section"> <div class="_content"> - <MkButton full @click="showUser"><Fa :icon="faExternalLinkSquareAlt"/> {{ $ts.user }}</MkButton> - <MkButton full danger @click="del"><Fa :icon="faTrashAlt"/> {{ $ts.delete }}</MkButton> + <MkButton full @click="showUser"><i class="fas fa-external-link-square-alt"></i> {{ $ts.user }}</MkButton> + <MkButton full danger @click="del"><i class="fas fa-trash-alt"></i> {{ $ts.delete }}</MkButton> </div> </div> <div class="_section" v-if="info"> @@ -36,8 +36,6 @@ <script lang="ts"> import { computed, defineComponent } from 'vue'; -import { faTimes, faBookmark, faKey, faSync, faMicrophoneSlash, faExternalLinkSquareAlt } from '@fortawesome/free-solid-svg-icons'; -import { faSnowflake, faTrashAlt, faBookmark as farBookmark } from '@fortawesome/free-regular-svg-icons'; import MkButton from '@client/components/ui/button.vue'; import MkSwitch from '@client/components/ui/switch.vue'; import XModalWindow from '@client/components/ui/modal-window.vue'; @@ -67,7 +65,6 @@ export default defineComponent({ file: null, info: null, isSensitive: false, - faTimes, faBookmark, farBookmark, faKey, faSync, faMicrophoneSlash, faSnowflake, faTrashAlt, faExternalLinkSquareAlt }; }, @@ -85,9 +82,7 @@ export default defineComponent({ }, showUser() { - os.popup(import('./user-dialog.vue'), { - userId: this.file.userId - }, {}, 'closed'); + os.pageWindow(`/user-info/${this.file.userId}`); }, async del() { diff --git a/src/client/pages/instance/files-settings.vue b/src/client/pages/instance/files-settings.vue new file mode 100644 index 0000000000000000000000000000000000000000..614c7d4dbbbe859ec0ede98d207084ebf117f18d --- /dev/null +++ b/src/client/pages/instance/files-settings.vue @@ -0,0 +1,92 @@ +<template> +<FormBase> + <FormSuspense :p="init"> + <FormSwitch v-model:value="cacheRemoteFiles"> + {{ $ts.cacheRemoteFiles }} + <template #desc>{{ $ts.cacheRemoteFilesDescription }}</template> + </FormSwitch> + + <FormSwitch v-model:value="proxyRemoteFiles"> + {{ $ts.proxyRemoteFiles }} + <template #desc>{{ $ts.proxyRemoteFilesDescription }}</template> + </FormSwitch> + + <FormInput v-model:value="localDriveCapacityMb" type="number"> + <span>{{ $ts.driveCapacityPerLocalAccount }}</span> + <template #suffix>MB</template> + <template #desc>{{ $ts.inMb }}</template> + </FormInput> + + <FormInput v-model:value="remoteDriveCapacityMb" type="number" :disabled="!cacheRemoteFiles"> + <span>{{ $ts.driveCapacityPerRemoteAccount }}</span> + <template #suffix>MB</template> + <template #desc>{{ $ts.inMb }}</template> + </FormInput> + + <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 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, + FormSuspense, + }, + + emits: ['info'], + + data() { + return { + [symbols.PAGE_INFO]: { + title: this.$ts.files, + icon: 'fas fa-cloud' + }, + cacheRemoteFiles: false, + proxyRemoteFiles: false, + localDriveCapacityMb: 0, + remoteDriveCapacityMb: 0, + } + }, + + async mounted() { + this.$emit('info', this[symbols.PAGE_INFO]); + }, + + methods: { + async init() { + const meta = await os.api('meta', { detail: true }); + this.cacheRemoteFiles = meta.cacheRemoteFiles; + this.proxyRemoteFiles = meta.proxyRemoteFiles; + this.localDriveCapacityMb = meta.driveCapacityPerLocalUserMb; + this.remoteDriveCapacityMb = meta.driveCapacityPerRemoteUserMb; + }, + save() { + os.apiWithDialog('admin/update-meta', { + cacheRemoteFiles: this.cacheRemoteFiles, + proxyRemoteFiles: this.proxyRemoteFiles, + localDriveCapacityMb: parseInt(this.localDriveCapacityMb, 10), + remoteDriveCapacityMb: parseInt(this.remoteDriveCapacityMb, 10), + }).then(() => { + fetchInstance(); + }); + } + } +}); +</script> diff --git a/src/client/pages/instance/files.vue b/src/client/pages/instance/files.vue index e7de050df8a481d8d575b87002d1272924e59b04..427c5b411ae968598f252e597983ff99307116b1 100644 --- a/src/client/pages/instance/files.vue +++ b/src/client/pages/instance/files.vue @@ -2,17 +2,17 @@ <div class="xrmjdkdw"> <div class="_section"> <div class="_content"> - <MkButton primary @click="clear()"><Fa :icon="faTrashAlt"/> {{ $ts.clearCachedFiles }}</MkButton> + <MkButton primary @click="clear()"><i class="fas fa-trash-alt"></i> {{ $ts.clearCachedFiles }}</MkButton> </div> </div> <div class="_section lookup"> - <div class="_title"><Fa :icon="faSearch"/> {{ $ts.lookup }}</div> + <div class="_title"><i class="fas fa-search"></i> {{ $ts.lookup }}</div> <div class="_content"> <MkInput class="target" v-model:value="q" type="text" @enter="find()"> <span>{{ $ts.fileIdOrUrl }}</span> </MkInput> - <MkButton @click="find()" primary><Fa :icon="faSearch"/> {{ $ts.lookup }}</MkButton> + <MkButton @click="find()" primary><i class="fas fa-search"></i> {{ $ts.lookup }}</MkButton> </div> </div> @@ -62,8 +62,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faCloud, faSearch } from '@fortawesome/free-solid-svg-icons'; -import { faTrashAlt } from '@fortawesome/free-regular-svg-icons'; import MkButton from '@client/components/ui/button.vue'; import MkInput from '@client/components/ui/input.vue'; import MkSelect from '@client/components/ui/select.vue'; @@ -82,11 +80,13 @@ export default defineComponent({ MkDriveFileThumbnail, }, + emits: ['info'], + data() { return { [symbols.PAGE_INFO]: { title: this.$ts.files, - icon: faCloud + icon: 'fas fa-cloud' }, q: null, origin: 'local', @@ -101,7 +101,6 @@ export default defineComponent({ hostname: (this.hostname && this.hostname !== '') ? this.hostname : null, }), }, - faTrashAlt, faCloud, faSearch, } }, @@ -117,6 +116,10 @@ export default defineComponent({ }, }, + mounted() { + this.$emit('info', this[symbols.PAGE_INFO]); + }, + methods: { clear() { os.dialog({ @@ -156,6 +159,8 @@ export default defineComponent({ <style lang="scss" scoped> .xrmjdkdw { + margin: var(--margin); + .urempief { margin-top: var(--margin); diff --git a/src/client/pages/instance/index.vue b/src/client/pages/instance/index.vue index 731acd8f00d9fe800d65a3a5de0c84d660611a68..5972a02de0c3c7016dd2532a9ef04a7e495d76b8 100644 --- a/src/client/pages/instance/index.vue +++ b/src/client/pages/instance/index.vue @@ -1,173 +1,243 @@ <template> -<div v-if="meta" v-show="page === 'index'" class="xhexznfu _section"> - <MkFolder> - <template #header><Fa :icon="faTachometerAlt"/> {{ $ts.overview }}</template> - - <div class="sboqnrfi" :style="{ gridTemplateRows: overviewHeight }"> - <MkInstanceStats :chart-limit="300" :detailed="true" class="_gap" ref="stats"/> - - <MkContainer :foldable="true" class="_gap"> - <template #header><Fa :icon="faInfoCircle"/>{{ $ts.instanceInfo }}</template> - - <div class="_content"> - <div class="_keyValue"><b>Misskey</b><span>v{{ version }}</span></div> - </div> - <div class="_content" v-if="serverInfo"> - <div class="_keyValue"><b>Node.js</b><span>{{ serverInfo.node }}</span></div> - <div class="_keyValue"><b>PostgreSQL</b><span>v{{ serverInfo.psql }}</span></div> - <div class="_keyValue"><b>Redis</b><span>v{{ serverInfo.redis }}</span></div> +<div class="hiyeyicy" :class="{ wide: !narrow }" ref="el"> + <div class="nav" v-if="!narrow || page == null"> + <FormBase> + <FormGroup> + <div class="_formItem"> + <div class="_formPanel lxpfedzu"> + <img :src="$instance.iconUrl || '/favicon.ico'" alt="" class="icon"/> + </div> </div> - </MkContainer> - - <MkContainer :foldable="true" :scrollable="true" class="_gap" style="height: 300px;"> - <template #header><Fa :icon="faDatabase"/>{{ $ts.database }}</template> - - <div class="_content" v-if="dbInfo"> - <table style="border-collapse: collapse; width: 100%;"> - <tr style="opacity: 0.7;"> - <th style="text-align: left; padding: 0 8px 8px 0;">Table</th> - <th style="text-align: left; padding: 0 8px 8px 0;">Records</th> - <th style="text-align: left; padding: 0 0 8px 0;">Size</th> - </tr> - <tr v-for="table in dbInfo" :key="table[0]"> - <th style="text-align: left; padding: 0 8px 0 0; word-break: break-all;">{{ table[0] }}</th> - <td style="padding: 0 8px 0 0;">{{ number(table[1].count) }}</td> - <td style="padding: 0; opacity: 0.7;">{{ bytes(table[1].size) }}</td> - </tr> - </table> - </div> - </MkContainer> - </div> - </MkFolder> -</div> -<div v-if="page === 'logs'" class="_section"> - <MkFolder> - <template #header><Fa :icon="faStream"/> {{ $ts.logs }}</template> - - <div class="_keyValue" v-for="log in modLogs"> - <b>{{ log.type }}</b><span>by {{ log.user.username }}</span><MkTime :time="log.createdAt" style="opacity: 0.7;"/> - </div> - </MkFolder> -</div> -<div v-if="page === 'metrics'"> - <XMetrics/> + <FormLink :active="page === 'overview'" replace to="/instance/overview"><template #icon><i class="fas fa-tachometer-alt"></i></template>{{ $ts.overview }}</FormLink> + </FormGroup> + <FormGroup> + <template #label>{{ $ts.quickAction }}</template> + <FormButton @click="lookup"><i class="fas fa-search"></i> {{ $ts.lookup }}</FormButton> + <FormButton v-if="$instance.disableRegistration" @click="invite"><i class="fas fa-user"></i> {{ $ts.invite }}</FormButton> + </FormGroup> + <FormGroup> + <template #label>{{ $ts.administration }}</template> + <FormLink :active="page === 'users'" replace to="/instance/users"><template #icon><i class="fas fa-users"></i></template>{{ $ts.users }}</FormLink> + <FormLink :active="page === 'emojis'" replace to="/instance/emojis"><template #icon><i class="fas fa-laugh"></i></template>{{ $ts.customEmojis }}</FormLink> + <FormLink :active="page === 'federation'" replace to="/instance/federation"><template #icon><i class="fas fa-globe"></i></template>{{ $ts.federation }}</FormLink> + <FormLink :active="page === 'queue'" replace to="/instance/queue"><template #icon><i class="fas fa-clipboard-list"></i></template>{{ $ts.jobQueue }}</FormLink> + <FormLink :active="page === 'files'" replace to="/instance/files"><template #icon><i class="fas fa-cloud"></i></template>{{ $ts.files }}</FormLink> + <FormLink :active="page === 'announcements'" replace to="/instance/announcements"><template #icon><i class="fas fa-broadcast-tower"></i></template>{{ $ts.announcements }}</FormLink> + <FormLink :active="page === 'abuses'" replace to="/instance/abuses"><template #icon><i class="fas fa-exclamation-circle"></i></template>{{ $ts.abuseReports }}</FormLink> + </FormGroup> + <FormGroup> + <template #label>{{ $ts.settings }}</template> + <FormLink :active="page === 'settings'" replace to="/instance/settings"><template #icon><i class="fas fa-cog"></i></template>{{ $ts.general }}</FormLink> + <FormLink :active="page === 'files-settings'" replace to="/instance/files-settings"><template #icon><i class="fas fa-cloud"></i></template>{{ $ts.files }}</FormLink> + <FormLink :active="page === 'email-settings'" replace to="/instance/email-settings"><template #icon><i class="fas fa-envelope"></i></template>{{ $ts.emailServer }}</FormLink> + <FormLink :active="page === 'object-storage'" replace to="/instance/object-storage"><template #icon><i class="fas fa-cloud"></i></template>{{ $ts.objectStorage }}</FormLink> + <FormLink :active="page === 'security'" replace to="/instance/security"><template #icon><i class="fas fa-lock"></i></template>{{ $ts.security }}</FormLink> + <FormLink :active="page === 'service-worker'" replace to="/instance/service-worker"><template #icon><i class="fas fa-bolt"></i></template>ServiceWorker</FormLink> + <FormLink :active="page === 'relays'" replace to="/instance/relays"><template #icon><i class="fas fa-globe"></i></template>{{ $ts.relays }}</FormLink> + <FormLink :active="page === 'integrations'" replace to="/instance/integrations"><template #icon><i class="fas fa-share-alt"></i></template>{{ $ts.integration }}</FormLink> + <FormLink :active="page === 'instance-block'" replace to="/instance/instance-block"><template #icon><i class="fas fa-ban"></i></template>{{ $ts.instanceBlocking }}</FormLink> + <FormLink :active="page === 'proxy-account'" replace to="/instance/proxy-account"><template #icon><i class="fas fa-ghost"></i></template>{{ $ts.proxyAccount }}</FormLink> + <FormLink :active="page === 'other-settings'" replace to="/instance/other-settings"><template #icon><i class="fas fa-cogs"></i></template>{{ $ts.other }}</FormLink> + </FormGroup> + <FormGroup> + <template #label>{{ $ts.info }}</template> + <FormLink :active="page === 'database'" replace to="/instance/database"><template #icon><i class="fas fa-database"></i></template>{{ $ts.database }}</FormLink> + </FormGroup> + </FormBase> + </div> + <div class="main"> + <component :is="component" :key="page" @info="onInfo" v-bind="pageProps"/> + </div> </div> </template> <script lang="ts"> -import { computed, defineComponent, markRaw } from 'vue'; -import { faPlay, faPause, faDatabase, faServer, faExchangeAlt, faMicrochip, faHdd, faStream, faTrashAlt, faInfoCircle, faExclamationTriangle, faTachometerAlt, faHeartbeat, faClipboardList } from '@fortawesome/free-solid-svg-icons'; -import VueJsonPretty from 'vue-json-pretty'; -import MkInstanceStats from '@client/components/instance-stats.vue'; -import MkButton from '@client/components/ui/button.vue'; -import MkSelect from '@client/components/ui/select.vue'; -import MkInput from '@client/components/ui/input.vue'; -import MkContainer from '@client/components/ui/container.vue'; -import MkFolder from '@client/components/ui/folder.vue'; -import { version, url } from '@client/config'; -import bytes from '../../filters/bytes'; -import number from '../../filters/number'; -import MkInstanceInfo from './instance.vue'; -import XMetrics from './index.metrics.vue'; -import * as os from '@client/os'; +import { computed, defineAsyncComponent, defineComponent, nextTick, onMounted, reactive, ref, watch } from 'vue'; +import { i18n } from '@client/i18n'; +import FormLink from '@client/components/form/link.vue'; +import FormGroup from '@client/components/form/group.vue'; +import FormBase from '@client/components/form/base.vue'; +import FormButton from '@client/components/form/button.vue'; +import { scroll } from '@client/scripts/scroll'; import * as symbols from '@client/symbols'; +import * as os from '@client/os'; +import { lookupUser } from '@client/scripts/lookup-user'; export default defineComponent({ components: { - MkInstanceStats, - MkButton, - MkSelect, - MkInput, - MkContainer, - MkFolder, - XMetrics, - VueJsonPretty, + FormBase, + FormLink, + FormGroup, + FormButton, }, - data() { - return { - [symbols.PAGE_INFO]: { - tabs: [{ - id: 'index', - title: null, - tooltip: this.$ts.instance, - icon: faServer, - onClick: () => { this.page = 'index'; }, - selected: computed(() => this.page === 'index') - }, { - id: 'metrics', - title: null, - tooltip: this.$ts.metrics, - icon: faHeartbeat, - onClick: () => { this.page = 'metrics'; }, - selected: computed(() => this.page === 'metrics') - }, { - id: 'logs', - title: null, - tooltip: this.$ts.logs, - icon: faStream, - onClick: () => { this.page = 'logs'; }, - selected: computed(() => this.page === 'logs') - }] - }, - page: 'index', - version, - url, - stats: null, - serverInfo: null, - modLogs: [], - dbInfo: null, - faPlay, faPause, faDatabase, faServer, faExchangeAlt, faMicrochip, faHdd, faStream, faTrashAlt, faInfoCircle, faExclamationTriangle, faTachometerAlt, faHeartbeat, faClipboardList, + props: { + initialPage: { + type: String, + required: false } }, - computed: { - meta() { - return this.$instance; - }, - }, + setup(props, context) { + const indexInfo = { + title: i18n.locale.instance, + icon: 'fas fa-cog' + }; + const INFO = ref(indexInfo); + const page = ref(props.initialPage); + const narrow = ref(false); + const view = ref(null); + const el = ref(null); + const onInfo = (viewInfo) => { + INFO.value = viewInfo; + }; + const pageProps = ref({}); + const component = computed(() => { + if (page.value == null) return null; + switch (page.value) { + case 'overview': return defineAsyncComponent(() => import('./overview.vue')); + case 'users': return defineAsyncComponent(() => import('./users.vue')); + case 'emojis': return defineAsyncComponent(() => import('./emojis.vue')); + case 'federation': return defineAsyncComponent(() => import('./federation.vue')); + case 'queue': return defineAsyncComponent(() => import('./queue.vue')); + case 'files': return defineAsyncComponent(() => import('./files.vue')); + case 'announcements': return defineAsyncComponent(() => import('./announcements.vue')); + case 'database': return defineAsyncComponent(() => import('./database.vue')); + case 'abuses': return defineAsyncComponent(() => import('./abuses.vue')); + case 'settings': return defineAsyncComponent(() => import('./settings.vue')); + case 'files-settings': return defineAsyncComponent(() => import('./files-settings.vue')); + case 'email-settings': return defineAsyncComponent(() => import('./email-settings.vue')); + case 'object-storage': return defineAsyncComponent(() => import('./object-storage.vue')); + case 'security': return defineAsyncComponent(() => import('./security.vue')); + case 'bot-protection': return defineAsyncComponent(() => import('./bot-protection.vue')); + case 'service-worker': return defineAsyncComponent(() => import('./service-worker.vue')); + case 'relays': return defineAsyncComponent(() => import('./relays.vue')); + case 'integrations': return defineAsyncComponent(() => import('./integrations.vue')); + case 'integrations/twitter': return defineAsyncComponent(() => import('./integrations-twitter.vue')); + case 'integrations/github': return defineAsyncComponent(() => import('./integrations-github.vue')); + case 'integrations/discord': return defineAsyncComponent(() => import('./integrations-discord.vue')); + case 'instance-block': return defineAsyncComponent(() => import('./instance-block.vue')); + case 'proxy-account': return defineAsyncComponent(() => import('./proxy-account.vue')); + case 'other-settings': return defineAsyncComponent(() => import('./other-settings.vue')); + } + }); - mounted() { - this.fetchJobs(); - this.fetchModLogs(); + watch(component, () => { + pageProps.value = {}; - os.api('admin/server-info', {}).then(res => { - this.serverInfo = res; + nextTick(() => { + scroll(el.value, 0); + }); + }, { immediate: true }); + + watch(() => props.initialPage, () => { + if (props.initialPage == null && !narrow.value) { + page.value = 'overview'; + } else { + page.value = props.initialPage; + if (props.initialPage == null) { + INFO.value = indexInfo; + } + } }); - os.api('admin/get-table-stats', {}).then(res => { - this.dbInfo = Object.entries(res).sort((a, b) => b[1].size - a[1].size); + onMounted(() => { + narrow.value = el.value.offsetWidth < 800; + if (!narrow.value) { + page.value = 'overview'; + } }); - }, - methods: { - async showInstanceInfo(q) { - let instance = q; - if (typeof q === 'string') { - instance = await os.api('federation/show-instance', { - host: q + const invite = () => { + os.api('admin/invite').then(x => { + os.dialog({ + type: 'info', + text: x.code + }); + }).catch(e => { + os.dialog({ + type: 'error', + text: e }); - } - os.popup(MkInstanceInfo, { - instance: instance - }, {}, 'closed'); - }, - - fetchJobs() { - os.api('admin/queue/deliver-delayed', {}).then(jobs => { - this.jobs = jobs; }); - }, + }; + + const lookup = (ev) => { + os.modalMenu([{ + text: i18n.locale.user, + icon: 'fas fa-user', + action: () => { + lookupUser(); + } + }, { + text: i18n.locale.note, + icon: 'fas fa-pencil-alt', + action: () => { + alert('TODO'); + } + }, { + text: i18n.locale.file, + icon: 'fas fa-cloud', + action: () => { + alert('TODO'); + } + }, { + text: i18n.locale.instance, + icon: 'fas fa-globe', + action: () => { + alert('TODO'); + } + }], ev.currentTarget || ev.target); + }; - fetchModLogs() { - os.api('admin/show-moderation-logs', {}).then(logs => { - this.modLogs = logs; - }); - }, + return { + [symbols.PAGE_INFO]: INFO, + page, + narrow, + view, + el, + onInfo, + pageProps, + component, + invite, + lookup, + }; + }, +}); +</script> - bytes, +<style lang="scss" scoped> +.hiyeyicy { + &.wide { + display: flex; + max-width: 1100px; + margin: 0 auto; + height: 100%; + + > .nav { + width: 32%; + box-sizing: border-box; + border-right: solid 0.5px var(--divider); + overflow: auto; + } - number, + > .main { + flex: 1; + min-width: 0; + overflow: auto; + --baseContentWidth: 100%; + } } -}); -</script> +} + +.lxpfedzu { + padding: 16px; + + > .icon { + display: block; + margin: auto; + height: 42px; + border-radius: 8px; + } +} +</style> diff --git a/src/client/pages/instance/instance-block.vue b/src/client/pages/instance/instance-block.vue new file mode 100644 index 0000000000000000000000000000000000000000..ed5740f33982121b4d66bf50f3938aa7dc57caf0 --- /dev/null +++ b/src/client/pages/instance/instance-block.vue @@ -0,0 +1,71 @@ +<template> +<FormBase> + <FormSuspense :p="init"> + <FormTextarea v-model:value="blockedHosts"> + <span>{{ $ts.blockedInstances }}</span> + <template #desc>{{ $ts.blockedInstancesDescription }}</template> + </FormTextarea> + + <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 FormTextarea from '@client/components/form/textarea.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, + FormTextarea, + FormInfo, + FormSuspense, + }, + + emits: ['info'], + + data() { + return { + [symbols.PAGE_INFO]: { + title: this.$ts.instanceBlocking, + icon: 'fas fa-ban' + }, + blockedHosts: '', + } + }, + + async mounted() { + this.$emit('info', this[symbols.PAGE_INFO]); + }, + + methods: { + async init() { + const meta = await os.api('meta', { detail: true }); + this.blockedHosts = meta.blockedHosts.join('\n'); + }, + + save() { + os.apiWithDialog('admin/update-meta', { + blockedHosts: this.blockedHosts.split('\n') || [], + }).then(() => { + fetchInstance(); + }); + } + } +}); +</script> diff --git a/src/client/pages/instance/instance.vue b/src/client/pages/instance/instance.vue index 1adb3ab9d2e046b75dbb5f2aaba3fce394741d63..f52e5d866b15914dc71cfbe522f33d36b63aebb5 100644 --- a/src/client/pages/instance/instance.vue +++ b/src/client/pages/instance/instance.vue @@ -106,11 +106,11 @@ <MkSwitch :value="isBlocked" class="switch" @update:value="changeBlock">{{ $ts.blockThisInstance }}</MkSwitch> <details> <summary>{{ $ts.deleteAllFiles }}</summary> - <MkButton @click="deleteAllFiles()" style="margin: 0.5em 0 0.5em 0;"><Fa :icon="faTrashAlt"/> {{ $ts.deleteAllFiles }}</MkButton> + <MkButton @click="deleteAllFiles()" style="margin: 0.5em 0 0.5em 0;"><i class="fas fa-trash-alt"></i> {{ $ts.deleteAllFiles }}</MkButton> </details> <details> <summary>{{ $ts.removeAllFollowing }}</summary> - <MkButton @click="removeAllFollowing()" style="margin: 0.5em 0 0.5em 0;"><Fa :icon="faMinusCircle"/> {{ $ts.removeAllFollowing }}</MkButton> + <MkButton @click="removeAllFollowing()" style="margin: 0.5em 0 0.5em 0;"><i class="fas fa-minus-circle"></i> {{ $ts.removeAllFollowing }}</MkButton> <MkInfo warn>{{ $t('removeAllFollowingDescription', { host: instance.host }) }}</MkInfo> </details> </div> @@ -125,7 +125,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; import Chart from 'chart.js'; -import { faTimes, faCrosshairs, faCloudDownloadAlt, faCloudUploadAlt, faUsers, faPencilAlt, faFileImage, faDatabase, faTrafficLight, faLongArrowAltUp, faLongArrowAltDown, faMinusCircle, faTrashAlt } from '@fortawesome/free-solid-svg-icons'; import XModalWindow from '@client/components/ui/modal-window.vue'; import MkUsersDialog from '@client/components/users-dialog.vue'; import MkSelect from '@client/components/ui/select.vue'; @@ -174,7 +173,6 @@ export default defineComponent({ chartInstance: null, chartSrc: 'requests', chartSpan: 'hour', - faTimes, faCrosshairs, faCloudDownloadAlt, faCloudUploadAlt, faUsers, faPencilAlt, faFileImage, faDatabase, faTrafficLight, faLongArrowAltUp, faLongArrowAltDown, faMinusCircle, faTrashAlt }; }, diff --git a/src/client/pages/instance/integrations-discord.vue b/src/client/pages/instance/integrations-discord.vue new file mode 100644 index 0000000000000000000000000000000000000000..c7508918f8d3d2b22f565dc08554069b5dd27e65 --- /dev/null +++ b/src/client/pages/instance/integrations-discord.vue @@ -0,0 +1,85 @@ +<template> +<FormBase> + <FormSuspense :p="init"> + <FormSwitch v-model:value="enableDiscordIntegration"> + {{ $ts.enable }} + </FormSwitch> + + <template v-if="enableDiscordIntegration"> + <FormInfo>Callback URL: {{ `${url}/api/dc/cb` }}</FormInfo> + + <FormInput v-model:value="discordClientId"> + <template #prefix><i class="fas fa-key"></i></template> + Client ID + </FormInput> + + <FormInput v-model:value="discordClientSecret"> + <template #prefix><i class="fas fa-key"></i></template> + Client Secret + </FormInput> + </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 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, + FormInfo, + FormButton, + FormSuspense, + }, + + emits: ['info'], + + data() { + return { + [symbols.PAGE_INFO]: { + title: 'Discord', + icon: 'fab fa-discord' + }, + enableDiscordIntegration: false, + discordClientId: null, + discordClientSecret: null, + } + }, + + async mounted() { + this.$emit('info', this[symbols.PAGE_INFO]); + }, + + methods: { + async init() { + const meta = await os.api('meta', { detail: true }); + this.enableDiscordIntegration = meta.enableDiscordIntegration; + this.discordClientId = meta.discordClientId; + this.discordClientSecret = meta.discordClientSecret; + }, + save() { + os.apiWithDialog('admin/update-meta', { + enableDiscordIntegration: this.enableDiscordIntegration, + discordClientId: this.discordClientId, + discordClientSecret: this.discordClientSecret, + }).then(() => { + fetchInstance(); + }); + } + } +}); +</script> diff --git a/src/client/pages/instance/integrations-github.vue b/src/client/pages/instance/integrations-github.vue new file mode 100644 index 0000000000000000000000000000000000000000..16586b15b4e79c49631adaf4e8f38c78e21d8c67 --- /dev/null +++ b/src/client/pages/instance/integrations-github.vue @@ -0,0 +1,85 @@ +<template> +<FormBase> + <FormSuspense :p="init"> + <FormSwitch v-model:value="enableGithubIntegration"> + {{ $ts.enable }} + </FormSwitch> + + <template v-if="enableGithubIntegration"> + <FormInfo>Callback URL: {{ `${url}/api/gh/cb` }}</FormInfo> + + <FormInput v-model:value="githubClientId"> + <template #prefix><i class="fas fa-key"></i></template> + Client ID + </FormInput> + + <FormInput v-model:value="githubClientSecret"> + <template #prefix><i class="fas fa-key"></i></template> + Client Secret + </FormInput> + </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 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, + FormInfo, + FormButton, + FormSuspense, + }, + + emits: ['info'], + + data() { + return { + [symbols.PAGE_INFO]: { + title: 'GitHub', + icon: 'fab fa-github' + }, + enableGithubIntegration: false, + githubClientId: null, + githubClientSecret: null, + } + }, + + async mounted() { + this.$emit('info', this[symbols.PAGE_INFO]); + }, + + methods: { + async init() { + const meta = await os.api('meta', { detail: true }); + this.enableGithubIntegration = meta.enableGithubIntegration; + this.githubClientId = meta.githubClientId; + this.githubClientSecret = meta.githubClientSecret; + }, + save() { + os.apiWithDialog('admin/update-meta', { + enableGithubIntegration: this.enableGithubIntegration, + githubClientId: this.githubClientId, + githubClientSecret: this.githubClientSecret, + }).then(() => { + fetchInstance(); + }); + } + } +}); +</script> diff --git a/src/client/pages/instance/integrations-twitter.vue b/src/client/pages/instance/integrations-twitter.vue new file mode 100644 index 0000000000000000000000000000000000000000..b08b7f40a55fccf605aac2f723eb3c99c687ebb2 --- /dev/null +++ b/src/client/pages/instance/integrations-twitter.vue @@ -0,0 +1,85 @@ +<template> +<FormBase> + <FormSuspense :p="init"> + <FormSwitch v-model:value="enableTwitterIntegration"> + {{ $ts.enable }} + </FormSwitch> + + <template v-if="enableTwitterIntegration"> + <FormInfo>Callback URL: {{ `${url}/api/tw/cb` }}</FormInfo> + + <FormInput v-model:value="twitterConsumerKey"> + <template #prefix><i class="fas fa-key"></i></template> + Consumer Key + </FormInput> + + <FormInput v-model:value="twitterConsumerSecret"> + <template #prefix><i class="fas fa-key"></i></template> + Consumer Secret + </FormInput> + </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 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, + FormInfo, + FormButton, + FormSuspense, + }, + + emits: ['info'], + + data() { + return { + [symbols.PAGE_INFO]: { + title: 'Twitter', + icon: 'fab fa-twitter' + }, + enableTwitterIntegration: false, + twitterConsumerKey: null, + twitterConsumerSecret: null, + } + }, + + async mounted() { + this.$emit('info', this[symbols.PAGE_INFO]); + }, + + methods: { + async init() { + const meta = await os.api('meta', { detail: true }); + this.enableTwitterIntegration = meta.enableTwitterIntegration; + this.twitterConsumerKey = meta.twitterConsumerKey; + this.twitterConsumerSecret = meta.twitterConsumerSecret; + }, + save() { + os.apiWithDialog('admin/update-meta', { + enableTwitterIntegration: this.enableTwitterIntegration, + twitterConsumerKey: this.twitterConsumerKey, + twitterConsumerSecret: this.twitterConsumerSecret, + }).then(() => { + fetchInstance(); + }); + } + } +}); +</script> diff --git a/src/client/pages/instance/integrations.vue b/src/client/pages/instance/integrations.vue new file mode 100644 index 0000000000000000000000000000000000000000..7debedc367ab6d822972d6bfa1f0575b103363ac --- /dev/null +++ b/src/client/pages/instance/integrations.vue @@ -0,0 +1,73 @@ +<template> +<FormBase> + <FormSuspense :p="init"> + <FormLink to="/instance/integrations/twitter"> + <i class="fab fa-twitter"></i> Twitter + <template #suffix>{{ enableTwitterIntegration ? $ts.enabled : $ts.disabled }}</template> + </FormLink> + <FormLink to="/instance/integrations/github"> + <i class="fab fa-github"></i> GitHub + <template #suffix>{{ enableGithubIntegration ? $ts.enabled : $ts.disabled }}</template> + </FormLink> + <FormLink to="/instance/integrations/discord"> + <i class="fab fa-discord"></i> Discord + <template #suffix>{{ enableDiscordIntegration ? $ts.enabled : $ts.disabled }}</template> + </FormLink> + </FormSuspense> +</FormBase> +</template> + +<script lang="ts"> +import { defineComponent } from 'vue'; +import FormLink from '@client/components/form/link.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 FormTextarea from '@client/components/form/textarea.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: { + FormLink, + FormInput, + FormBase, + FormGroup, + FormButton, + FormTextarea, + FormInfo, + FormSuspense, + }, + + emits: ['info'], + + data() { + return { + [symbols.PAGE_INFO]: { + title: this.$ts.integration, + icon: 'fas fa-share-alt' + }, + enableTwitterIntegration: false, + enableGithubIntegration: false, + enableDiscordIntegration: false, + } + }, + + async mounted() { + this.$emit('info', this[symbols.PAGE_INFO]); + }, + + methods: { + async init() { + const meta = await os.api('meta', { detail: true }); + this.enableTwitterIntegration = meta.enableTwitterIntegration; + this.enableGithubIntegration = meta.enableGithubIntegration; + this.enableDiscordIntegration = meta.enableDiscordIntegration; + }, + } +}); +</script> diff --git a/src/client/pages/instance/logs.vue b/src/client/pages/instance/logs.vue index f27546a40116e79d2f7f4cddd92ff582dac959ff..7b634259d357e97719934827b8fdc2a87af86b6f 100644 --- a/src/client/pages/instance/logs.vue +++ b/src/client/pages/instance/logs.vue @@ -24,14 +24,12 @@ </code> </div> - <MkButton @click="deleteAllLogs()" primary><Fa :icon="faTrashAlt"/> {{ $ts.deleteAll }}</MkButton> + <MkButton @click="deleteAllLogs()" primary><i class="fas fa-trash-alt"></i> {{ $ts.deleteAll }}</MkButton> </div> </template> <script lang="ts"> import { defineComponent } from 'vue'; -import { faStream } from '@fortawesome/free-solid-svg-icons'; -import { faTrashAlt } from '@fortawesome/free-regular-svg-icons'; import MkButton from '@client/components/ui/button.vue'; import MkInput from '@client/components/ui/input.vue'; import MkSelect from '@client/components/ui/select.vue'; @@ -51,12 +49,11 @@ export default defineComponent({ return { [symbols.PAGE_INFO]: { title: this.$ts.serverLogs, - icon: faStream + icon: 'fas fa-stream' }, logs: [], logLevel: 'all', logDomain: '', - faTrashAlt, } }, diff --git a/src/client/pages/instance/index.metrics.vue b/src/client/pages/instance/metrics.vue similarity index 59% rename from src/client/pages/instance/index.metrics.vue rename to src/client/pages/instance/metrics.vue index 17ebf5d0d668e557202aceddac24cebbbd25abe6..18cfe5eee2f2aee13ab5916914f8b72ed925707a 100644 --- a/src/client/pages/instance/index.metrics.vue +++ b/src/client/pages/instance/metrics.vue @@ -1,107 +1,57 @@ <template> -<div> - <MkFolder> - <template #header><Fa :icon="faHeartbeat"/> {{ $ts.metrics }}</template> - <div class="_section" style="padding: 0 var(--margin);"> - <div class="_content"> - <MkContainer :foldable="false" class="_gap"> - <template #header><Fa :icon="faMicrochip"/>{{ $ts.cpuAndMemory }}</template> - <!-- - <template #func> - <button class="_button" @click="resume" :disabled="!paused"><Fa :icon="faPlay"/></button> - <button class="_button" @click="pause" :disabled="paused"><Fa :icon="faPause"/></button> - </template> - --> - - <div class="_content" style="margin-top: -8px; margin-bottom: -12px;"> - <canvas :ref="cpumem"></canvas> - </div> - <div class="_content" v-if="serverInfo"> - <div class="_table"> - <div class="_row"> - <div class="_cell"><div class="_label">MEM total</div>{{ bytes(serverInfo.mem.total) }}</div> - <div class="_cell"><div class="_label">MEM used</div>{{ bytes(memUsage) }} ({{ (memUsage / serverInfo.mem.total * 100).toFixed(0) }}%)</div> - <div class="_cell"><div class="_label">MEM free</div>{{ bytes(serverInfo.mem.total - memUsage) }} ({{ ((serverInfo.mem.total - memUsage) / serverInfo.mem.total * 100).toFixed(0) }}%)</div> - </div> - </div> - </div> - </MkContainer> - - <MkContainer :foldable="false" class="_gap"> - <template #header><Fa :icon="faHdd"/> {{ $ts.disk }}</template> - <!-- - <template #func> - <button class="_button" @click="resume" :disabled="!paused"><Fa :icon="faPlay"/></button> - <button class="_button" @click="pause" :disabled="paused"><Fa :icon="faPause"/></button> - </template> - --> - - <div class="_content" style="margin-top: -8px; margin-bottom: -12px;"> - <canvas :ref="disk"></canvas> - </div> - <div class="_content" v-if="serverInfo"> - <div class="_table"> - <div class="_row"> - <div class="_cell"><div class="_label">Disk total</div>{{ bytes(serverInfo.fs.total) }}</div> - <div class="_cell"><div class="_label">Disk used</div>{{ bytes(serverInfo.fs.used) }} ({{ (serverInfo.fs.used / serverInfo.fs.total * 100).toFixed(0) }}%)</div> - <div class="_cell"><div class="_label">Disk free</div>{{ bytes(serverInfo.fs.total - serverInfo.fs.used) }} ({{ ((serverInfo.fs.total - serverInfo.fs.used) / serverInfo.fs.total * 100).toFixed(0) }}%)</div> - </div> - </div> - </div> - </MkContainer> - - <MkContainer :foldable="false" class="_gap"> - <template #header><Fa :icon="faExchangeAlt"/> {{ $ts.network }}</template> - <!-- - <template #func> - <button class="_button" @click="resume" :disabled="!paused"><Fa :icon="faPlay"/></button> - <button class="_button" @click="pause" :disabled="paused"><Fa :icon="faPause"/></button> - </template> - --> - - <div class="_content" style="margin-top: -8px; margin-bottom: -12px;"> - <canvas :ref="net"></canvas> - </div> - <div class="_content" v-if="serverInfo"> - <div class="_table"> - <div class="_row"> - <div class="_cell"><div class="_label">Interface</div>{{ serverInfo.net.interface }}</div> - </div> - </div> - </div> - </MkContainer> +<div class="_formItem"> + <div class="_formLabel"><i class="fas fa-microchip"></i> {{ $ts.cpuAndMemory }}</div> + <div class="_formPanel xhexznfu"> + <div> + <canvas :ref="cpumem"></canvas> + </div> + <div v-if="serverInfo"> + <div class="_table"> + <div class="_row"> + <div class="_cell"><div class="_label">MEM total</div>{{ bytes(serverInfo.mem.total) }}</div> + <div class="_cell"><div class="_label">MEM used</div>{{ bytes(memUsage) }} ({{ (memUsage / serverInfo.mem.total * 100).toFixed(0) }}%)</div> + <div class="_cell"><div class="_label">MEM free</div>{{ bytes(serverInfo.mem.total - memUsage) }} ({{ ((serverInfo.mem.total - memUsage) / serverInfo.mem.total * 100).toFixed(0) }}%)</div> + </div> </div> </div> - </MkFolder> - - <MkFolder> - <template #header><Fa :icon="faClipboardList"/> {{ $ts.jobQueue }}</template> - - <div class="vkyrmkwb" :style="{ gridTemplateRows: queueHeight }"> - <MkContainer :foldable="false" :scrollable="true" :resize-base-el="() => $el"> - <template #header><Fa :icon="faExclamationTriangle"/> {{ $ts.delayed }}</template> - - <div class="_content"> - <div class="_keyValue" v-for="job in jobs" :key="job[0]"> - <button class="_button" @click="showInstanceInfo(job[0])">{{ job[0] }}</button> - <div style="text-align: right;">{{ number(job[1]) }} jobs</div> - </div> + </div> +</div> +<div class="_formItem"> + <div class="_formLabel"><i class="fas fa-hdd"></i> {{ $ts.disk }}</div> + <div class="_formPanel xhexznfu"> + <div> + <canvas :ref="disk"></canvas> + </div> + <div v-if="serverInfo"> + <div class="_table"> + <div class="_row"> + <div class="_cell"><div class="_label">Disk total</div>{{ bytes(serverInfo.fs.total) }}</div> + <div class="_cell"><div class="_label">Disk used</div>{{ bytes(serverInfo.fs.used) }} ({{ (serverInfo.fs.used / serverInfo.fs.total * 100).toFixed(0) }}%)</div> + <div class="_cell"><div class="_label">Disk free</div>{{ bytes(serverInfo.fs.total - serverInfo.fs.used) }} ({{ ((serverInfo.fs.total - serverInfo.fs.used) / serverInfo.fs.total * 100).toFixed(0) }}%)</div> </div> - </MkContainer> - <XQueue :connection="queueConnection" domain="inbox" ref="queue" class="queue"> - <template #title><Fa :icon="faExchangeAlt"/> In</template> - </XQueue> - <XQueue :connection="queueConnection" domain="deliver" class="queue"> - <template #title><Fa :icon="faExchangeAlt"/> Out</template> - </XQueue> + </div> + </div> + </div> +</div> +<div class="_formItem"> + <div class="_formLabel"><i class="fas fa-exchange-alt"></i> {{ $ts.network }}</div> + <div class="_formPanel xhexznfu"> + <div> + <canvas :ref="net"></canvas> + </div> + <div v-if="serverInfo"> + <div class="_table"> + <div class="_row"> + <div class="_cell"><div class="_label">Interface</div>{{ serverInfo.net.interface }}</div> + </div> + </div> </div> - </MkFolder> + </div> </div> </template> <script lang="ts"> import { defineComponent, markRaw } from 'vue'; -import { faPlay, faPause, faDatabase, faServer, faExchangeAlt, faMicrochip, faHdd, faStream, faTrashAlt, faInfoCircle, faExclamationTriangle, faTachometerAlt, faHeartbeat, faClipboardList } from '@fortawesome/free-solid-svg-icons'; import Chart from 'chart.js'; import MkButton from '@client/components/ui/button.vue'; import MkSelect from '@client/components/ui/select.vue'; @@ -153,7 +103,6 @@ export default defineComponent({ overviewHeight: '1fr', queueHeight: '1fr', paused: false, - faPlay, faPause, faDatabase, faServer, faExchangeAlt, faMicrochip, faHdd, faStream, faTrashAlt, faInfoCircle, faExclamationTriangle, faTachometerAlt, faHeartbeat, faClipboardList, } }, @@ -190,9 +139,11 @@ export default defineComponent({ }, beforeUnmount() { - this.connection.off('stats', this.onStats); - this.connection.off('statsLog', this.onStatsLog); - this.connection.dispose(); + if (this.connection) { + this.connection.off('stats', this.onStats); + this.connection.off('statsLog', this.onStatsLog); + this.connection.dispose(); + } this.queueConnection.dispose(); }, @@ -234,9 +185,9 @@ export default defineComponent({ aspectRatio: 3, layout: { padding: { - left: 0, - right: 0, - top: 8, + left: 16, + right: 16, + top: 16, bottom: 0 } }, @@ -306,9 +257,9 @@ export default defineComponent({ aspectRatio: 3, layout: { padding: { - left: 0, - right: 0, - top: 8, + left: 16, + right: 16, + top: 16, bottom: 0 } }, @@ -377,9 +328,9 @@ export default defineComponent({ aspectRatio: 3, layout: { padding: { - left: 0, - right: 0, - top: 8, + left: 16, + right: 16, + top: 16, bottom: 0 } }, @@ -496,81 +447,9 @@ export default defineComponent({ <style lang="scss" scoped> .xhexznfu { - &.min-width_1000px { - .sboqnrfi { - display: grid; - grid-template-columns: 3.2fr 1fr; - grid-template-rows: 1fr; - gap: 16px 16px; - - > .stats { - height: min-content; - } - - > .column { - display: flex; - flex-direction: column; - - > .info { - flex-shrink: 0; - flex-grow: 0; - } - - > .db { - flex: 1; - flex-grow: 0; - height: 100%; - } - - > .fed { - flex: 1; - flex-grow: 0; - height: 100%; - } - - > *:not(:last-child) { - margin-bottom: var(--margin); - } - } - } - - .segusily { - display: grid; - grid-template-columns: 1fr 1fr 1fr; - grid-template-rows: 1fr; - gap: 16px 16px; - padding: 0 16px; - } - - .vkyrmkwb { - display: grid; - grid-template-columns: 0.5fr 1fr 1fr; - grid-template-rows: 1fr; - gap: 16px 16px; - margin-bottom: var(--margin); - - > .queue { - height: min-content; - } - - > * { - margin-bottom: 0; - } - } - - .uwuemslx { - display: grid; - grid-template-columns: 2fr 3fr; - grid-template-rows: 1fr; - gap: 16px 16px; - height: 400px; - } - } - - .vkyrmkwb { - > * { - margin-bottom: var(--margin); - } + > div:nth-child(2) { + padding: 16px; + border-top: solid 0.5px var(--divider); } } </style> diff --git a/src/client/pages/instance/object-storage.vue b/src/client/pages/instance/object-storage.vue new file mode 100644 index 0000000000000000000000000000000000000000..814aeb6e48667b41b779c8987fb4ee8ef5142603 --- /dev/null +++ b/src/client/pages/instance/object-storage.vue @@ -0,0 +1,154 @@ +<template> +<FormBase> + <FormSuspense :p="init"> + <FormSwitch v-model:value="useObjectStorage">{{ $ts.useObjectStorage }}</FormSwitch> + + <template v-if="useObjectStorage"> + <FormInput v-model:value="objectStorageBaseUrl"> + <span>{{ $ts.objectStorageBaseUrl }}</span> + <template #desc>{{ $ts.objectStorageBaseUrlDesc }}</template> + </FormInput> + + <FormInput v-model:value="objectStorageBucket"> + <span>{{ $ts.objectStorageBucket }}</span> + <template #desc>{{ $ts.objectStorageBucketDesc }}</template> + </FormInput> + + <FormInput v-model:value="objectStoragePrefix"> + <span>{{ $ts.objectStoragePrefix }}</span> + <template #desc>{{ $ts.objectStoragePrefixDesc }}</template> + </FormInput> + + <FormInput v-model:value="objectStorageEndpoint"> + <span>{{ $ts.objectStorageEndpoint }}</span> + <template #desc>{{ $ts.objectStorageEndpointDesc }}</template> + </FormInput> + + <FormInput v-model:value="objectStorageRegion"> + <span>{{ $ts.objectStorageRegion }}</span> + <template #desc>{{ $ts.objectStorageRegionDesc }}</template> + </FormInput> + + <FormInput v-model:value="objectStorageAccessKey"> + <template #prefix><i class="fas fa-key"></i></template> + <span>Access key</span> + </FormInput> + + <FormInput v-model:value="objectStorageSecretKey"> + <template #prefix><i class="fas fa-key"></i></template> + <span>Secret key</span> + </FormInput> + + <FormSwitch v-model:value="objectStorageUseSSL"> + {{ $ts.objectStorageUseSSL }} + <template #desc>{{ $ts.objectStorageUseSSLDesc }}</template> + </FormSwitch> + + <FormSwitch v-model:value="objectStorageUseProxy"> + {{ $ts.objectStorageUseProxy }} + <template #desc>{{ $ts.objectStorageUseProxyDesc }}</template> + </FormSwitch> + + <FormSwitch v-model:value="objectStorageSetPublicRead"> + {{ $ts.objectStorageSetPublicRead }} + </FormSwitch> + + <FormSwitch v-model:value="objectStorageS3ForcePathStyle"> + s3ForcePathStyle + </FormSwitch> + </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 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, + FormSuspense, + }, + + emits: ['info'], + + data() { + return { + [symbols.PAGE_INFO]: { + title: this.$ts.objectStorage, + icon: 'fas fa-cloud' + }, + useObjectStorage: false, + objectStorageBaseUrl: null, + objectStorageBucket: null, + objectStoragePrefix: null, + objectStorageEndpoint: null, + objectStorageRegion: null, + objectStoragePort: null, + objectStorageAccessKey: null, + objectStorageSecretKey: null, + objectStorageUseSSL: false, + objectStorageUseProxy: false, + objectStorageSetPublicRead: false, + objectStorageS3ForcePathStyle: true, + } + }, + + async mounted() { + this.$emit('info', this[symbols.PAGE_INFO]); + }, + + methods: { + async init() { + const meta = await os.api('meta', { detail: true }); + this.useObjectStorage = meta.useObjectStorage; + this.objectStorageBaseUrl = meta.objectStorageBaseUrl; + this.objectStorageBucket = meta.objectStorageBucket; + this.objectStoragePrefix = meta.objectStoragePrefix; + this.objectStorageEndpoint = meta.objectStorageEndpoint; + this.objectStorageRegion = meta.objectStorageRegion; + this.objectStoragePort = meta.objectStoragePort; + this.objectStorageAccessKey = meta.objectStorageAccessKey; + this.objectStorageSecretKey = meta.objectStorageSecretKey; + this.objectStorageUseSSL = meta.objectStorageUseSSL; + this.objectStorageUseProxy = meta.objectStorageUseProxy; + this.objectStorageSetPublicRead = meta.objectStorageSetPublicRead; + this.objectStorageS3ForcePathStyle = meta.objectStorageS3ForcePathStyle; + }, + save() { + os.apiWithDialog('admin/update-meta', { + useObjectStorage: this.useObjectStorage, + objectStorageBaseUrl: this.objectStorageBaseUrl ? this.objectStorageBaseUrl : null, + objectStorageBucket: this.objectStorageBucket ? this.objectStorageBucket : null, + objectStoragePrefix: this.objectStoragePrefix ? this.objectStoragePrefix : null, + objectStorageEndpoint: this.objectStorageEndpoint ? this.objectStorageEndpoint : null, + objectStorageRegion: this.objectStorageRegion ? this.objectStorageRegion : null, + objectStoragePort: this.objectStoragePort ? this.objectStoragePort : null, + objectStorageAccessKey: this.objectStorageAccessKey ? this.objectStorageAccessKey : null, + objectStorageSecretKey: this.objectStorageSecretKey ? this.objectStorageSecretKey : null, + objectStorageUseSSL: this.objectStorageUseSSL, + objectStorageUseProxy: this.objectStorageUseProxy, + objectStorageSetPublicRead: this.objectStorageSetPublicRead, + objectStorageS3ForcePathStyle: this.objectStorageS3ForcePathStyle, + }).then(() => { + fetchInstance(); + }); + } + } +}); +</script> diff --git a/src/client/pages/instance/other-settings.vue b/src/client/pages/instance/other-settings.vue new file mode 100644 index 0000000000000000000000000000000000000000..b3954149a823e9d856c711cdd2ece8ecf0f56644 --- /dev/null +++ b/src/client/pages/instance/other-settings.vue @@ -0,0 +1,68 @@ +<template> +<FormBase> + <FormSuspense :p="init"> + <FormGroup> + <FormInput v-model:value="summalyProxy"> + <template #prefix><i class="fas fa-link"></i></template> + Summaly Proxy URL + </FormInput> + </FormGroup> + + <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 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, + FormSuspense, + }, + + emits: ['info'], + + data() { + return { + [symbols.PAGE_INFO]: { + title: this.$ts.other, + icon: 'fas fa-cogs' + }, + summalyProxy: '', + } + }, + + async mounted() { + this.$emit('info', this[symbols.PAGE_INFO]); + }, + + methods: { + async init() { + const meta = await os.api('meta', { detail: true }); + this.summalyProxy = meta.summalyProxy; + }, + save() { + os.apiWithDialog('admin/update-meta', { + summalyProxy: this.summalyProxy, + }).then(() => { + fetchInstance(); + }); + } + } +}); +</script> diff --git a/src/client/pages/instance/overview.vue b/src/client/pages/instance/overview.vue new file mode 100644 index 0000000000000000000000000000000000000000..dca2529e1bbe8875539004314dad65d091b9f428 --- /dev/null +++ b/src/client/pages/instance/overview.vue @@ -0,0 +1,135 @@ +<template> +<FormBase> + <FormSuspense :p="init"> + <FormInfo v-if="noMaintainerInformation" warn>{{ $ts.noMaintainerInformationWarning }} <MkA to="/instance/settings" class="_link">{{ $ts.configure }}</MkA></FormInfo> + <FormInfo v-if="noBotProtection" warn>{{ $ts.noBotProtectionWarning }} <MkA to="/instance/bot-protection" class="_link">{{ $ts.configure }}</MkA></FormInfo> + + <FormSuspense :p="fetchStats" v-slot="{ result: stats }"> + <FormGroup> + <FormKeyValueView> + <template #key>Users</template> + <template #value>{{ number(stats.originalUsersCount) }}</template> + </FormKeyValueView> + <FormKeyValueView> + <template #key>Notes</template> + <template #value>{{ number(stats.originalNotesCount) }}</template> + </FormKeyValueView> + </FormGroup> + </FormSuspense> + + <div class="_formItem"> + <div class="_formPanel"> + <MkInstanceStats :chart-limit="300" :detailed="true"/> + </div> + </div> + + <XMetrics/> + + <FormSuspense :p="fetchServerInfo" v-slot="{ result: serverInfo }"> + <FormGroup> + <FormKeyValueView> + <template #key>Node.js</template> + <template #value>{{ serverInfo.node }}</template> + </FormKeyValueView> + <FormKeyValueView> + <template #key>PostgreSQL</template> + <template #value>{{ serverInfo.psql }}</template> + </FormKeyValueView> + <FormKeyValueView> + <template #key>Redis</template> + <template #value>{{ serverInfo.redis }}</template> + </FormKeyValueView> + </FormGroup> + </FormSuspense> + </FormSuspense> +</FormBase> +</template> + +<script lang="ts"> +import { computed, defineComponent, markRaw } from 'vue'; +import FormKeyValueView from '@client/components/form/key-value-view.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 FormTextarea from '@client/components/form/textarea.vue'; +import FormInfo from '@client/components/form/info.vue'; +import FormSuspense from '@client/components/form/suspense.vue'; +import MkInstanceStats from '@client/components/instance-stats.vue'; +import MkButton from '@client/components/ui/button.vue'; +import MkSelect from '@client/components/ui/select.vue'; +import MkInput from '@client/components/ui/input.vue'; +import MkContainer from '@client/components/ui/container.vue'; +import MkFolder from '@client/components/ui/folder.vue'; +import { version, url } from '@client/config'; +import bytes from '../../filters/bytes'; +import number from '../../filters/number'; +import MkInstanceInfo from './instance.vue'; +import XMetrics from './metrics.vue'; +import * as os from '@client/os'; +import * as symbols from '@client/symbols'; + +export default defineComponent({ + components: { + FormBase, + FormSuspense, + FormGroup, + FormInfo, + FormKeyValueView, + MkInstanceStats, + XMetrics, + }, + + emits: ['info'], + + data() { + return { + [symbols.PAGE_INFO]: { + title: this.$ts.overview, + icon: 'fas fa-tachometer-alt' + }, + page: 'index', + version, + url, + stats: null, + fetchStats: () => os.api('stats', {}), + fetchServerInfo: () => os.api('admin/server-info', {}), + fetchJobs: () => os.api('admin/queue/deliver-delayed', {}), + fetchModLogs: () => os.api('admin/show-moderation-logs', {}), + noMaintainerInformation: false, + noBotProtection: false, + } + }, + + async mounted() { + this.$emit('info', this[symbols.PAGE_INFO]); + }, + + methods: { + async init() { + this.meta = await os.api('meta', { detail: true }); + + const isEmpty = (x: any) => x == null || x == ''; + + this.noMaintainerInformation = isEmpty(this.meta.maintainerName) || isEmpty(this.meta.maintainerEmail); + this.noBotProtection = !this.meta.enableHcaptcha && !this.meta.enableRecaptcha; + }, + + async showInstanceInfo(q) { + let instance = q; + if (typeof q === 'string') { + instance = await os.api('federation/show-instance', { + host: q + }); + } + os.popup(MkInstanceInfo, { + instance: instance + }, {}, 'closed'); + }, + + bytes, + + number, + } +}); +</script> diff --git a/src/client/pages/instance/proxy-account.vue b/src/client/pages/instance/proxy-account.vue new file mode 100644 index 0000000000000000000000000000000000000000..3e2df8dcb4ee8435c7b39fc2fcdd667610c7a89b --- /dev/null +++ b/src/client/pages/instance/proxy-account.vue @@ -0,0 +1,86 @@ +<template> +<FormBase> + <FormSuspense :p="init"> + <FormGroup> + <FormKeyValueView> + <template #key>{{ $ts.proxyAccount }}</template> + <template #value>{{ proxyAccount ? `@${proxyAccount.username}` : $ts.none }}</template> + </FormKeyValueView> + <template #caption>{{ $ts.proxyAccountDescription }}</template> + </FormGroup> + + <FormButton @click="chooseProxyAccount" primary>{{ $ts.selectAccount }}</FormButton> + </FormSuspense> +</FormBase> +</template> + +<script lang="ts"> +import { defineComponent } from 'vue'; +import FormKeyValueView from '@client/components/form/key-value-view.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 FormTextarea from '@client/components/form/textarea.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: { + FormKeyValueView, + FormInput, + FormBase, + FormGroup, + FormButton, + FormTextarea, + FormInfo, + FormSuspense, + }, + + emits: ['info'], + + data() { + return { + [symbols.PAGE_INFO]: { + title: this.$ts.proxyAccount, + icon: 'fas fa-ghost' + }, + proxyAccount: null, + proxyAccountId: null, + } + }, + + async mounted() { + this.$emit('info', this[symbols.PAGE_INFO]); + }, + + methods: { + async init() { + const meta = await os.api('meta', { detail: true }); + this.proxyAccountId = meta.proxyAccountId; + if (this.proxyAccountId) { + this.proxyAccount = await os.api('users/show', { userId: this.proxyAccountId }); + } + }, + + chooseProxyAccount() { + os.selectUser().then(user => { + this.proxyAccount = user; + this.proxyAccountId = user.id; + this.save(); + }); + }, + + save() { + os.apiWithDialog('admin/update-meta', { + proxyAccountId: this.proxyAccountId, + }).then(() => { + fetchInstance(); + }); + } + } +}); +</script> diff --git a/src/client/pages/instance/queue.chart.vue b/src/client/pages/instance/queue.chart.vue index 0eb70debfba8ce117df9875616f3427375f40e66..446c979209f39e08606afbecd70c05f551de1196 100644 --- a/src/client/pages/instance/queue.chart.vue +++ b/src/client/pages/instance/queue.chart.vue @@ -1,27 +1,29 @@ <template> -<section class="_section"> - <div class="_title"><slot name="title"></slot></div> - <div class="_content _table"> - <div class="_row"> - <div class="_cell"><div class="_label">Process</div>{{ number(activeSincePrevTick) }}</div> - <div class="_cell"><div class="_label">Active</div>{{ number(active) }}</div> - <div class="_cell"><div class="_label">Waiting</div>{{ number(waiting) }}</div> - <div class="_cell"><div class="_label">Delayed</div>{{ number(delayed) }}</div> +<div class="_formItem"> + <div class="_formLabel"><slot name="title"></slot></div> + <div class="_formPanel pumxzjhg"> + <div class="_table status"> + <div class="_row"> + <div class="_cell"><div class="_label">Process</div>{{ number(activeSincePrevTick) }}</div> + <div class="_cell"><div class="_label">Active</div>{{ number(active) }}</div> + <div class="_cell"><div class="_label">Waiting</div>{{ number(waiting) }}</div> + <div class="_cell"><div class="_label">Delayed</div>{{ number(delayed) }}</div> + </div> </div> - </div> - <div class="_content" style="margin-bottom: -8px;"> - <canvas ref="chart"></canvas> - </div> - <div class="_content" style="max-height: 180px; overflow: auto;"> - <div v-if="jobs.length > 0"> - <div v-for="job in jobs" :key="job[0]"> - <span>{{ job[0] }}</span> - <span style="margin-left: 8px; opacity: 0.7;">({{ number(job[1]) }} jobs)</span> + <div class=""> + <canvas ref="chart"></canvas> + </div> + <div class="jobs"> + <div v-if="jobs.length > 0"> + <div v-for="job in jobs" :key="job[0]"> + <span>{{ job[0] }}</span> + <span style="margin-left: 8px; opacity: 0.7;">({{ number(job[1]) }} jobs)</span> + </div> </div> + <span v-else style="opacity: 0.5;">{{ $ts.noJobs }}</span> </div> - <span v-else style="opacity: 0.5;">{{ $ts.noJobs }}</span> </div> -</section> +</div> </template> <script lang="ts"> @@ -110,10 +112,10 @@ export default defineComponent({ aspectRatio: 3, layout: { padding: { - left: 0, - right: 0, - top: 8, - bottom: 0 + left: 16, + right: 16, + top: 16, + bottom: 12 } }, legend: { @@ -198,3 +200,19 @@ export default defineComponent({ } }); </script> + +<style lang="scss" scoped> +.pumxzjhg { + > .status { + padding: 16px; + border-bottom: solid 0.5px var(--divider); + } + + > .jobs { + padding: 16px; + border-top: solid 0.5px var(--divider); + max-height: 180px; + overflow: auto; + } +} +</style> diff --git a/src/client/pages/instance/queue.vue b/src/client/pages/instance/queue.vue index 249babcf4108072c79505e3ed9a289b6e90d8e62..2dccf48d315012062b85d71691aac60449c200bf 100644 --- a/src/client/pages/instance/queue.vue +++ b/src/client/pages/instance/queue.vue @@ -1,46 +1,47 @@ <template> -<div> +<FormBase> <XQueue :connection="connection" domain="inbox"> - <template #title><Fa :icon="faExchangeAlt"/> In</template> + <template #title>In</template> </XQueue> <XQueue :connection="connection" domain="deliver"> - <template #title><Fa :icon="faExchangeAlt"/> Out</template> + <template #title>Out</template> </XQueue> - <section class="_section"> - <div class="_content"> - <MkButton @click="clear()"><Fa :icon="faTrashAlt"/> {{ $ts.clearQueue }}</MkButton> - </div> - </section> -</div> + <FormButton @click="clear()" danger><i class="fas fa-trash-alt"></i> {{ $ts.clearQueue }}</FormButton> +</FormBase> </template> <script lang="ts"> import { defineComponent } from 'vue'; -import { faExchangeAlt } from '@fortawesome/free-solid-svg-icons'; -import { faTrashAlt } from '@fortawesome/free-regular-svg-icons'; import MkButton from '@client/components/ui/button.vue'; import XQueue from './queue.chart.vue'; +import FormBase from '@client/components/form/base.vue'; +import FormButton from '@client/components/form/button.vue'; import * as os from '@client/os'; import * as symbols from '@client/symbols'; export default defineComponent({ components: { + FormBase, + FormButton, MkButton, XQueue, }, + emits: ['info'], + data() { return { [symbols.PAGE_INFO]: { title: this.$ts.jobQueue, - icon: faExchangeAlt, + icon: 'fas fa-clipboard-list', }, connection: os.stream.useSharedConnection('queueStats'), - faExchangeAlt, faTrashAlt } }, mounted() { + this.$emit('info', this[symbols.PAGE_INFO]); + this.$nextTick(() => { this.connection.send('requestLog', { id: Math.random().toString().substr(2, 8), diff --git a/src/client/pages/instance/relays.vue b/src/client/pages/instance/relays.vue index d97a07cbb22255785362b31d3a196e5294513e94..a3e4e7d1da16b53cb5ee82ab444b40f35667a5c4 100644 --- a/src/client/pages/instance/relays.vue +++ b/src/client/pages/instance/relays.vue @@ -1,50 +1,44 @@ <template> -<div class="relaycxt"> - <section class="_section add"> - <div class="_title"><Fa :icon="faPlus"/> {{ $ts.addRelay }}</div> - <div class="_content"> - <MkInput v-model:value="inbox"> - <span>{{ $ts.inboxUrl }}</span> - </MkInput> - <MkButton @click="add(inbox)" primary><Fa :icon="faPlus"/> {{ $ts.add }}</MkButton> - </div> - </section> +<FormBase class="relaycxt"> + <FormButton @click="addRelay" primary><i class="fas fa-plus"></i> {{ $ts.addRelay }}</FormButton> - <section class="_section relays"> - <div class="_title"><Fa :icon="faProjectDiagram"/> {{ $ts.addedRelays }}</div> - <div class="_content relay" v-for="relay in relays" :key="relay.inbox"> + <div class="_formItem" v-for="relay in relays" :key="relay.inbox"> + <div class="_formPanel" style="padding: 16px;"> <div>{{ relay.inbox }}</div> <div>{{ $t(`_relayStatus.${relay.status}`) }}</div> - <MkButton class="button" inline @click="remove(relay.inbox)"><Fa :icon="faTrashAlt"/> {{ $ts.remove }}</MkButton> + <MkButton class="button" inline danger @click="remove(relay.inbox)"><i class="fas fa-trash-alt"></i> {{ $ts.remove }}</MkButton> </div> - </section> -</div> + </div> +</FormBase> </template> <script lang="ts"> import { defineComponent } from 'vue'; -import { faPlus, faProjectDiagram } 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 FormBase from '@client/components/form/base.vue'; +import FormButton from '@client/components/form/button.vue'; import * as os from '@client/os'; import * as symbols from '@client/symbols'; export default defineComponent({ components: { + FormBase, + FormButton, MkButton, MkInput, }, + emits: ['info'], + data() { return { [symbols.PAGE_INFO]: { title: this.$ts.relays, - icon: faProjectDiagram, + icon: 'fas fa-globe', }, relays: [], inbox: '', - faPlus, faProjectDiagram, faSave, faTrashAlt } }, @@ -52,8 +46,19 @@ export default defineComponent({ this.refresh(); }, + mounted() { + this.$emit('info', this[symbols.PAGE_INFO]); + }, + methods: { - add(inbox: string) { + async addRelay() { + const { canceled, result: inbox } = await os.dialog({ + title: this.$ts.addRelay, + input: { + placeholder: this.$ts.inboxUrl + } + }); + if (canceled) return; os.api('admin/relays/add', { inbox }).then((relay: any) => { @@ -89,9 +94,5 @@ export default defineComponent({ </script> <style lang="scss" scoped> -._content.relay { - div { - margin: 0.5em 0; - } -} + </style> diff --git a/src/client/pages/instance/security.vue b/src/client/pages/instance/security.vue new file mode 100644 index 0000000000000000000000000000000000000000..e3397a113bafac857cf921b1d11b7d9088d4c404 --- /dev/null +++ b/src/client/pages/instance/security.vue @@ -0,0 +1,77 @@ +<template> +<FormBase> + <FormSuspense :p="init"> + <FormLink to="/instance/bot-protection"> + <i class="fas fa-shield-alt"></i> {{ $ts.botProtection }} + <template #suffix v-if="enableHcaptcha">hCaptcha</template> + <template #suffix v-else-if="enableRecaptcha">reCAPTCHA</template> + <template #suffix v-else>{{ $ts.none }} ({{ $ts.notRecommended }})</template> + </FormLink> + + <FormSwitch v-model:value="enableRegistration">{{ $ts.enableRegistration }}</FormSwitch> + + <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 FormLink from '@client/components/form/link.vue'; +import FormSwitch from '@client/components/form/switch.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: { + FormLink, + FormSwitch, + FormBase, + FormGroup, + FormButton, + FormInfo, + FormSuspense, + }, + + emits: ['info'], + + data() { + return { + [symbols.PAGE_INFO]: { + title: this.$ts.security, + icon: 'fas fa-lock' + }, + enableHcaptcha: false, + enableRecaptcha: false, + enableRegistration: false, + } + }, + + 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.enableRecaptcha = meta.enableRecaptcha; + this.enableRegistration = !meta.disableRegistration; + }, + + save() { + os.apiWithDialog('admin/update-meta', { + disableRegistration: !this.enableRegistration, + }).then(() => { + fetchInstance(); + }); + } + } +}); +</script> diff --git a/src/client/pages/instance/service-worker.vue b/src/client/pages/instance/service-worker.vue new file mode 100644 index 0000000000000000000000000000000000000000..a52932bb75c9099baa464b98281b0445dcd2da95 --- /dev/null +++ b/src/client/pages/instance/service-worker.vue @@ -0,0 +1,84 @@ +<template> +<FormBase> + <FormSuspense :p="init"> + <FormSwitch v-model:value="enableServiceWorker"> + {{ $ts.enableServiceworker }} + <template #desc>{{ $ts.serviceworkerInfo }}</template> + </FormSwitch> + + <template v-if="enableServiceWorker"> + <FormInput v-model:value="swPublicKey"> + <template #prefix><i class="fas fa-key"></i></template> + Public key + </FormInput> + + <FormInput v-model:value="swPrivateKey"> + <template #prefix><i class="fas fa-key"></i></template> + Private key + </FormInput> + </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 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, + FormSuspense, + }, + + emits: ['info'], + + data() { + return { + [symbols.PAGE_INFO]: { + title: 'ServiceWorker', + icon: 'fas fa-bolt' + }, + enableServiceWorker: false, + swPublicKey: null, + swPrivateKey: null, + } + }, + + async mounted() { + this.$emit('info', this[symbols.PAGE_INFO]); + }, + + methods: { + async init() { + const meta = await os.api('meta', { detail: true }); + this.enableServiceWorker = meta.enableServiceWorker; + this.swPublicKey = meta.swPublickey; + this.swPrivateKey = meta.swPrivateKey; + }, + save() { + os.apiWithDialog('admin/update-meta', { + enableServiceWorker: this.enableServiceWorker, + swPublicKey: this.swPublicKey, + swPrivateKey: this.swPrivateKey, + }).then(() => { + fetchInstance(); + }); + } + } +}); +</script> diff --git a/src/client/pages/instance/settings.vue b/src/client/pages/instance/settings.vue index 038ecfd5ac1bf5bccc0af0dc47fd82e8719dc5fb..66f01c42c77e79ef91fc83460066da8a61e55a9d 100644 --- a/src/client/pages/instance/settings.vue +++ b/src/client/pages/instance/settings.vue @@ -1,585 +1,132 @@ <template> -<div v-if="meta" class="_section"> - <section class="_card _gap"> - <div class="_title"><Fa :icon="faInfoCircle"/> {{ $ts.basicInfo }}</div> - <div class="_content"> - <MkInput v-model:value="name">{{ $ts.instanceName }}</MkInput> - <MkTextarea v-model:value="description">{{ $ts.instanceDescription }}</MkTextarea> - <MkInput v-model:value="iconUrl"><template #icon><Fa :icon="faLink"/></template>{{ $ts.iconUrl }}</MkInput> - <MkInput v-model:value="bannerUrl"><template #icon><Fa :icon="faLink"/></template>{{ $ts.bannerUrl }}</MkInput> - <MkInput v-model:value="backgroundImageUrl"><template #icon><Fa :icon="faLink"/></template>{{ $ts.backgroundImageUrl }}</MkInput> - <MkInput v-model:value="logoImageUrl"><template #icon><Fa :icon="faLink"/></template>{{ $ts.logoImageUrl }}</MkInput> - <MkInput v-model:value="tosUrl"><template #icon><Fa :icon="faLink"/></template>{{ $ts.tosUrl }}</MkInput> - <MkInput v-model:value="maintainerName">{{ $ts.maintainerName }}</MkInput> - <MkInput v-model:value="maintainerEmail" type="email"><template #icon><Fa :icon="faEnvelope"/></template>{{ $ts.maintainerEmail }}</MkInput> - </div> - <div class="_footer"> - <MkButton primary @click="save(true)"><Fa :icon="faSave"/> {{ $ts.save }}</MkButton> - </div> - </section> - - <MkInput v-model:value="pinnedClipId">{{ $ts.pinnedClipId }}</MkInput> - - <section class="_card _gap"> - <div class="_content"> - <MkInput v-model:value="maxNoteTextLength" type="number" :save="() => save()"><template #icon><Fa :icon="faPencilAlt"/></template>{{ $ts.maxNoteTextLength }}</MkInput> - </div> - <div class="_content"> - <MkSwitch v-model:value="enableLocalTimeline" @update:value="save()">{{ $ts.enableLocalTimeline }}</MkSwitch> - <MkSwitch v-model:value="enableGlobalTimeline" @update:value="save()">{{ $ts.enableGlobalTimeline }}</MkSwitch> - <MkInfo>{{ $ts.disablingTimelinesInfo }}</MkInfo> - </div> - <div class="_content"> - <MkSwitch v-model:value="useStarForReactionFallback" @update:value="save()">{{ $ts.useStarForReactionFallback }}</MkSwitch> - </div> - </section> - - <section class="_card _gap"> - <div class="_title"><Fa :icon="faUser"/> {{ $ts.registration }}</div> - <div class="_content"> - <MkSwitch v-model:value="enableRegistration" @update:value="save()">{{ $ts.enableRegistration }}</MkSwitch> - <MkButton v-if="!enableRegistration" @click="invite">{{ $ts.invite }}</MkButton> - </div> - </section> - - <section class="_card _gap"> - <div class="_title"><Fa :icon="faShieldAlt"/> {{ $ts.hcaptcha }}</div> - <div class="_content"> - <MkSwitch v-model:value="enableHcaptcha">{{ $ts.enableHcaptcha }}</MkSwitch> - <template v-if="enableHcaptcha"> - <MkInput v-model:value="hcaptchaSiteKey" :disabled="!enableHcaptcha"><template #icon><Fa :icon="faKey"/></template>{{ $ts.hcaptchaSiteKey }}</MkInput> - <MkInput v-model:value="hcaptchaSecretKey" :disabled="!enableHcaptcha"><template #icon><Fa :icon="faKey"/></template>{{ $ts.hcaptchaSecretKey }}</MkInput> - </template> - </div> - <div class="_content" v-if="enableHcaptcha"> - <header>{{ $ts.preview }}</header> - <captcha v-if="enableHcaptcha" provider="hcaptcha" :sitekey="hcaptchaSiteKey || '10000000-ffff-ffff-ffff-000000000001'"/> - </div> - <div class="_footer"> - <MkButton primary @click="save(true)"><Fa :icon="faSave"/> {{ $ts.save }}</MkButton> - </div> - </section> - - <section class="_card _gap"> - <div class="_title"><Fa :icon="faShieldAlt"/> {{ $ts.recaptcha }}</div> - <div class="_content"> - <MkSwitch v-model:value="enableRecaptcha" ref="enableRecaptcha">{{ $ts.enableRecaptcha }}</MkSwitch> - <template v-if="enableRecaptcha"> - <MkInput v-model:value="recaptchaSiteKey" :disabled="!enableRecaptcha"><template #icon><Fa :icon="faKey"/></template>{{ $ts.recaptchaSiteKey }}</MkInput> - <MkInput v-model:value="recaptchaSecretKey" :disabled="!enableRecaptcha"><template #icon><Fa :icon="faKey"/></template>{{ $ts.recaptchaSecretKey }}</MkInput> - </template> - </div> - <div class="_content" v-if="enableRecaptcha && recaptchaSiteKey"> - <header>{{ $ts.preview }}</header> - <captcha v-if="enableRecaptcha" provider="grecaptcha" :sitekey="recaptchaSiteKey"/> - </div> - <div class="_footer"> - <MkButton primary @click="save(true)"><Fa :icon="faSave"/> {{ $ts.save }}</MkButton> - </div> - </section> - - <section class="_card _gap"> - <div class="_title"><Fa :icon="faEnvelope" /> {{ $ts.emailConfig }}</div> - <div class="_content"> - <MkSwitch v-model:value="enableEmail" @update:value="save()">{{ $ts.enableEmail }}<template #desc>{{ $ts.emailConfigInfo }}</template></MkSwitch> - <MkInput v-model:value="email" type="email" :disabled="!enableEmail">{{ $ts.email }}</MkInput> - <div><b>{{ $ts.smtpConfig }}</b></div> - <div class="_inputs"> - <MkInput v-model:value="smtpHost" :disabled="!enableEmail">{{ $ts.smtpHost }}</MkInput> - <MkInput v-model:value="smtpPort" type="number" :disabled="!enableEmail">{{ $ts.smtpPort }}</MkInput> - </div> - <div class="_inputs"> - <MkInput v-model:value="smtpUser" :disabled="!enableEmail">{{ $ts.smtpUser }}</MkInput> - <MkInput v-model:value="smtpPass" type="password" :disabled="!enableEmail">{{ $ts.smtpPass }}</MkInput> - </div> - <MkInfo>{{ $ts.emptyToDisableSmtpAuth }}</MkInfo> - <MkSwitch v-model:value="smtpSecure" :disabled="!enableEmail">{{ $ts.smtpSecure }}<template #desc>{{ $ts.smtpSecureInfo }}</template></MkSwitch> - <div> - <MkButton :disabled="!enableEmail" primary inline @click="save(true)"><Fa :icon="faSave"/> {{ $ts.save }}</MkButton> - <MkButton :disabled="!enableEmail" inline @click="testEmail()">{{ $ts.testEmail }}</MkButton> - </div> - </div> - </section> - - <section class="_card _gap"> - <div class="_title"><Fa :icon="faBolt"/> {{ $ts.serviceworker }}</div> - <div class="_content"> - <MkSwitch v-model:value="enableServiceWorker">{{ $ts.enableServiceworker }}<template #desc>{{ $ts.serviceworkerInfo }}</template></MkSwitch> - <template v-if="enableServiceWorker"> - <div class="_inputs"> - <MkInput v-model:value="swPublicKey" :disabled="!enableServiceWorker"><template #icon><Fa :icon="faKey"/></template>Public key</MkInput> - <MkInput v-model:value="swPrivateKey" :disabled="!enableServiceWorker"><template #icon><Fa :icon="faKey"/></template>Private key</MkInput> - </div> - </template> - </div> - <div class="_footer"> - <MkButton primary @click="save(true)"><Fa :icon="faSave"/> {{ $ts.save }}</MkButton> - </div> - </section> - - <section class="_card _gap"> - <div class="_title"><Fa :icon="faThumbtack"/> {{ $ts.pinnedUsers }}</div> - <div class="_content"> - <MkTextarea v-model:value="pinnedUsers"> - <template #desc>{{ $ts.pinnedUsersDescription }} <button class="_textButton" @click="addPinUser">{{ $ts.addUser }}</button></template> - </MkTextarea> - </div> - <div class="_footer"> - <MkButton primary @click="save(true)"><Fa :icon="faSave"/> {{ $ts.save }}</MkButton> - </div> - </section> - - <section class="_card _gap"> - <div class="_title"><Fa :icon="faThumbtack"/> {{ $ts.pinnedPages }}</div> - <div class="_content"> - <MkTextarea v-model:value="pinnedPages"> - <template #desc>{{ $ts.pinnedPagesDescription }}</template> - </MkTextarea> - </div> - <div class="_footer"> - <MkButton primary @click="save(true)"><Fa :icon="faSave"/> {{ $ts.save }}</MkButton> - </div> - </section> - - <section class="_card _gap"> - <div class="_title"><Fa :icon="faCloud"/> {{ $ts.files }}</div> - <div class="_content"> - <MkSwitch v-model:value="cacheRemoteFiles">{{ $ts.cacheRemoteFiles }}<template #desc>{{ $ts.cacheRemoteFilesDescription }}</template></MkSwitch> - <MkSwitch v-model:value="proxyRemoteFiles">{{ $ts.proxyRemoteFiles }}<template #desc>{{ $ts.proxyRemoteFilesDescription }}</template></MkSwitch> - <MkInput v-model:value="localDriveCapacityMb" type="number">{{ $ts.driveCapacityPerLocalAccount }}<template #suffix>MB</template><template #desc>{{ $ts.inMb }}</template></MkInput> - <MkInput v-model:value="remoteDriveCapacityMb" type="number" :disabled="!cacheRemoteFiles">{{ $ts.driveCapacityPerRemoteAccount }}<template #suffix>MB</template><template #desc>{{ $ts.inMb }}</template></MkInput> - </div> - <div class="_footer"> - <MkButton primary @click="save(true)"><Fa :icon="faSave"/> {{ $ts.save }}</MkButton> - </div> - </section> - - <section class="_card _gap"> - <div class="_title"><Fa :icon="faCloud"/> {{ $ts.objectStorage }}</div> - <div class="_content"> - <MkSwitch v-model:value="useObjectStorage">{{ $ts.useObjectStorage }}</MkSwitch> - <template v-if="useObjectStorage"> - <MkInput v-model:value="objectStorageBaseUrl" :disabled="!useObjectStorage">{{ $ts.objectStorageBaseUrl }}<template #desc>{{ $ts.objectStorageBaseUrlDesc }}</template></MkInput> - <div class="_inputs"> - <MkInput v-model:value="objectStorageBucket" :disabled="!useObjectStorage">{{ $ts.objectStorageBucket }}<template #desc>{{ $ts.objectStorageBucketDesc }}</template></MkInput> - <MkInput v-model:value="objectStoragePrefix" :disabled="!useObjectStorage">{{ $ts.objectStoragePrefix }}<template #desc>{{ $ts.objectStoragePrefixDesc }}</template></MkInput> - </div> - <MkInput v-model:value="objectStorageEndpoint" :disabled="!useObjectStorage">{{ $ts.objectStorageEndpoint }}<template #desc>{{ $ts.objectStorageEndpointDesc }}</template></MkInput> - <div class="_inputs"> - <MkInput v-model:value="objectStorageRegion" :disabled="!useObjectStorage">{{ $ts.objectStorageRegion }}<template #desc>{{ $ts.objectStorageRegionDesc }}</template></MkInput> - </div> - <div class="_inputs"> - <MkInput v-model:value="objectStorageAccessKey" :disabled="!useObjectStorage"><template #icon><Fa :icon="faKey"/></template>Access key</MkInput> - <MkInput v-model:value="objectStorageSecretKey" :disabled="!useObjectStorage"><template #icon><Fa :icon="faKey"/></template>Secret key</MkInput> - </div> - <MkSwitch v-model:value="objectStorageUseSSL" :disabled="!useObjectStorage">{{ $ts.objectStorageUseSSL }}<template #desc>{{ $ts.objectStorageUseSSLDesc }}</template></MkSwitch> - <MkSwitch v-model:value="objectStorageUseProxy" :disabled="!useObjectStorage">{{ $ts.objectStorageUseProxy }}<template #desc>{{ $ts.objectStorageUseProxyDesc }}</template></MkSwitch> - <MkSwitch v-model:value="objectStorageSetPublicRead" :disabled="!useObjectStorage">{{ $ts.objectStorageSetPublicRead }}</MkSwitch> - <MkSwitch v-model:value="objectStorageS3ForcePathStyle" :disabled="!useObjectStorage">s3ForcePathStyle</MkSwitch> - </template> - </div> - <div class="_footer"> - <MkButton primary @click="save(true)"><Fa :icon="faSave"/> {{ $ts.save }}</MkButton> - </div> - </section> - - <section class="_card _gap"> - <div class="_title"><Fa :icon="faGhost"/> {{ $ts.proxyAccount }}</div> - <div class="_content"> - <MkInput :value="proxyAccount ? proxyAccount.username : null" disabled><template #prefix>@</template>{{ $ts.proxyAccount }}<template #desc>{{ $ts.proxyAccountDescription }}</template></MkInput> - <MkButton primary @click="chooseProxyAccount">{{ $ts.chooseProxyAccount }}</MkButton> - </div> - </section> - - <section class="_card _gap"> - <div class="_title"><Fa :icon="faBan"/> {{ $ts.blockedInstances }}</div> - <div class="_content"> - <MkTextarea v-model:value="blockedHosts"> - <template #desc>{{ $ts.blockedInstancesDescription }}</template> - </MkTextarea> - </div> - <div class="_footer"> - <MkButton primary @click="save(true)"><Fa :icon="faSave"/> {{ $ts.save }}</MkButton> - </div> - </section> - - <section class="_card _gap"> - <div class="_title"><Fa :icon="faShareAlt"/> {{ $ts.integration }}</div> - <div class="_content"> - <header><Fa :icon="faTwitter"/> Twitter</header> - <MkSwitch v-model:value="enableTwitterIntegration">{{ $ts.enable }}</MkSwitch> - <template v-if="enableTwitterIntegration"> - <MkInfo>Callback URL: {{ `${url}/api/tw/cb` }}</MkInfo> - <MkInput v-model:value="twitterConsumerKey" :disabled="!enableTwitterIntegration"><template #icon><Fa :icon="faKey"/></template>Consumer Key</MkInput> - <MkInput v-model:value="twitterConsumerSecret" :disabled="!enableTwitterIntegration"><template #icon><Fa :icon="faKey"/></template>Consumer Secret</MkInput> - </template> - </div> - <div class="_content"> - <header><Fa :icon="faGithub"/> GitHub</header> - <MkSwitch v-model:value="enableGithubIntegration">{{ $ts.enable }}</MkSwitch> - <template v-if="enableGithubIntegration"> - <MkInfo>Callback URL: {{ `${url}/api/gh/cb` }}</MkInfo> - <MkInput v-model:value="githubClientId" :disabled="!enableGithubIntegration"><template #icon><Fa :icon="faKey"/></template>Client ID</MkInput> - <MkInput v-model:value="githubClientSecret" :disabled="!enableGithubIntegration"><template #icon><Fa :icon="faKey"/></template>Client Secret</MkInput> - </template> - </div> - <div class="_content"> - <header><Fa :icon="faDiscord"/> Discord</header> - <MkSwitch v-model:value="enableDiscordIntegration">{{ $ts.enable }}</MkSwitch> - <template v-if="enableDiscordIntegration"> - <MkInfo>Callback URL: {{ `${url}/api/dc/cb` }}</MkInfo> - <MkInput v-model:value="discordClientId" :disabled="!enableDiscordIntegration"><template #icon><Fa :icon="faKey"/></template>Client ID</MkInput> - <MkInput v-model:value="discordClientSecret" :disabled="!enableDiscordIntegration"><template #icon><Fa :icon="faKey"/></template>Client Secret</MkInput> - </template> - </div> - <div class="_footer"> - <MkButton primary @click="save(true)"><Fa :icon="faSave"/> {{ $ts.save }}</MkButton> - </div> - </section> - - <section class="_card _gap"> - <div class="_title"><Fa :icon="faArchway" /> Summaly Proxy</div> - <div class="_content"> - <MkInput v-model:value="summalyProxy">URL</MkInput> - <MkButton primary @click="save(true)"><Fa :icon="faSave"/> {{ $ts.save }}</MkButton> - </div> - </section> -</div> +<FormBase> + <FormSuspense :p="init"> + <FormInput v-model:value="name"> + <span>{{ $ts.instanceName }}</span> + </FormInput> + + <FormTextarea v-model:value="description"> + <span>{{ $ts.instanceDescription }}</span> + </FormTextarea> + + <FormInput v-model:value="iconUrl"> + <template #prefix><i class="fas fa-link"></i></template> + <span>{{ $ts.iconUrl }}</span> + </FormInput> + + <FormInput v-model:value="bannerUrl"> + <template #prefix><i class="fas fa-link"></i></template> + <span>{{ $ts.bannerUrl }}</span> + </FormInput> + + <FormInput v-model:value="tosUrl"> + <template #prefix><i class="fas fa-link"></i></template> + <span>{{ $ts.tosUrl }}</span> + </FormInput> + + <FormInput v-model:value="maintainerName"> + <span>{{ $ts.maintainerName }}</span> + </FormInput> + + <FormInput v-model:value="maintainerEmail" type="email"> + <template #prefix><i class="fas fa-envelope"></i></template> + <span>{{ $ts.maintainerEmail }}</span> + </FormInput> + + <FormInput v-model:value="maxNoteTextLength" type="number"> + <template #prefix><i class="fas fa-pencil-alt"></i></template> + <span>{{ $ts.maxNoteTextLength }}</span> + </FormInput> + + <FormSwitch v-model:value="enableLocalTimeline">{{ $ts.enableLocalTimeline }}</FormSwitch> + <FormSwitch v-model:value="enableGlobalTimeline">{{ $ts.enableGlobalTimeline }}</FormSwitch> + <FormInfo>{{ $ts.disablingTimelinesInfo }}</FormInfo> + + <FormButton @click="save" primary><i class="fas fa-save"></i> {{ $ts.save }}</FormButton> + </FormSuspense> +</FormBase> </template> <script lang="ts"> -import { defineComponent, defineAsyncComponent } from 'vue'; -import { faPencilAlt, faShareAlt, faGhost, faCog, faPlus, faCloud, faInfoCircle, faBan, faSave, faServer, faLink, faThumbtack, faUser, faShieldAlt, faKey, faBolt, faArchway } from '@fortawesome/free-solid-svg-icons'; -import { faTrashAlt, faEnvelope } from '@fortawesome/free-regular-svg-icons'; -import { faTwitter, faDiscord, faGithub } from '@fortawesome/free-brands-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'; -import MkSwitch from '@client/components/ui/switch.vue'; -import MkInfo from '@client/components/ui/info.vue'; -import { url } from '@client/config'; -import getAcct from '@/misc/acct/render'; +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 FormTextarea from '@client/components/form/textarea.vue'; +import FormInfo from '@client/components/form/info.vue'; +import FormSuspense from '@client/components/form/suspense.vue'; import * as os from '@client/os'; -import { fetchInstance } from '@client/instance'; import * as symbols from '@client/symbols'; +import { fetchInstance } from '@client/instance'; export default defineComponent({ components: { - MkButton, - MkInput, - MkTextarea, - MkSwitch, - MkInfo, - Captcha: defineAsyncComponent(() => import('@client/components/captcha.vue')), + FormSwitch, + FormInput, + FormBase, + FormGroup, + FormButton, + FormTextarea, + FormInfo, + FormSuspense, }, + emits: ['info'], + data() { return { [symbols.PAGE_INFO]: { - title: this.$ts.instance, - icon: faCog, + title: this.$ts.general, + icon: 'fas fa-cog' }, - meta: null, - url, - proxyAccount: null, - proxyAccountId: null, - cacheRemoteFiles: false, - proxyRemoteFiles: false, - localDriveCapacityMb: 0, - remoteDriveCapacityMb: 0, - blockedHosts: '', - pinnedUsers: '', - pinnedPages: '', - pinnedClipId: null, - maintainerName: null, - maintainerEmail: null, name: null, description: null, tosUrl: null as string | null, - enableEmail: false, - email: null, - bannerUrl: null, + maintainerName: null, + maintainerEmail: null, iconUrl: null, - logoImageUrl: null, - backgroundImageUrl: null, + bannerUrl: null, maxNoteTextLength: 0, - enableRegistration: false, enableLocalTimeline: false, enableGlobalTimeline: false, - enableHcaptcha: false, - hcaptchaSiteKey: null, - hcaptchaSecretKey: null, - enableRecaptcha: false, - recaptchaSiteKey: null, - recaptchaSecretKey: null, - enableServiceWorker: false, - swPublicKey: null, - swPrivateKey: null, - useObjectStorage: false, - objectStorageBaseUrl: null, - objectStorageBucket: null, - objectStoragePrefix: null, - objectStorageEndpoint: null, - objectStorageRegion: null, - objectStoragePort: null, - objectStorageAccessKey: null, - objectStorageSecretKey: null, - objectStorageUseSSL: false, - objectStorageUseProxy: false, - objectStorageSetPublicRead: false, - objectStorageS3ForcePathStyle: true, - enableTwitterIntegration: false, - twitterConsumerKey: null, - twitterConsumerSecret: null, - enableGithubIntegration: false, - githubClientId: null, - githubClientSecret: null, - enableDiscordIntegration: false, - discordClientId: null, - discordClientSecret: null, - useStarForReactionFallback: false, - smtpSecure: false, - smtpHost: '', - smtpPort: 0, - smtpUser: '', - smtpPass: '', - summalyProxy: '', - faPencilAlt, faTwitter, faDiscord, faGithub, faShareAlt, faTrashAlt, faGhost, faCog, faPlus, faCloud, faInfoCircle, faBan, faSave, faServer, faLink, faEnvelope, faThumbtack, faUser, faShieldAlt, faKey, faBolt, faArchway } }, - async created() { - this.meta = await os.api('meta', { detail: true }); - - this.name = this.meta.name; - this.description = this.meta.description; - this.tosUrl = this.meta.tosUrl; - this.bannerUrl = this.meta.bannerUrl; - this.iconUrl = this.meta.iconUrl; - this.logoImageUrl = this.meta.logoImageUrl; - this.backgroundImageUrl = this.meta.backgroundImageUrl; - this.enableEmail = this.meta.enableEmail; - this.email = this.meta.email; - this.maintainerName = this.meta.maintainerName; - this.maintainerEmail = this.meta.maintainerEmail; - this.maxNoteTextLength = this.meta.maxNoteTextLength; - this.enableRegistration = !this.meta.disableRegistration; - this.enableLocalTimeline = !this.meta.disableLocalTimeline; - this.enableGlobalTimeline = !this.meta.disableGlobalTimeline; - this.enableHcaptcha = this.meta.enableHcaptcha; - this.hcaptchaSiteKey = this.meta.hcaptchaSiteKey; - this.hcaptchaSecretKey = this.meta.hcaptchaSecretKey; - this.enableRecaptcha = this.meta.enableRecaptcha; - this.recaptchaSiteKey = this.meta.recaptchaSiteKey; - this.recaptchaSecretKey = this.meta.recaptchaSecretKey; - this.proxyAccountId = this.meta.proxyAccountId; - this.cacheRemoteFiles = this.meta.cacheRemoteFiles; - this.proxyRemoteFiles = this.meta.proxyRemoteFiles; - this.localDriveCapacityMb = this.meta.driveCapacityPerLocalUserMb; - this.remoteDriveCapacityMb = this.meta.driveCapacityPerRemoteUserMb; - this.blockedHosts = this.meta.blockedHosts.join('\n'); - this.pinnedUsers = this.meta.pinnedUsers.join('\n'); - this.pinnedPages = this.meta.pinnedPages.join('\n'); - this.pinnedClipId = this.meta.pinnedClipId; - this.enableServiceWorker = this.meta.enableServiceWorker; - this.swPublicKey = this.meta.swPublickey; - this.swPrivateKey = this.meta.swPrivateKey; - this.useObjectStorage = this.meta.useObjectStorage; - this.objectStorageBaseUrl = this.meta.objectStorageBaseUrl; - this.objectStorageBucket = this.meta.objectStorageBucket; - this.objectStoragePrefix = this.meta.objectStoragePrefix; - this.objectStorageEndpoint = this.meta.objectStorageEndpoint; - this.objectStorageRegion = this.meta.objectStorageRegion; - this.objectStoragePort = this.meta.objectStoragePort; - this.objectStorageAccessKey = this.meta.objectStorageAccessKey; - this.objectStorageSecretKey = this.meta.objectStorageSecretKey; - this.objectStorageUseSSL = this.meta.objectStorageUseSSL; - this.objectStorageUseProxy = this.meta.objectStorageUseProxy; - this.objectStorageSetPublicRead = this.meta.objectStorageSetPublicRead; - this.objectStorageS3ForcePathStyle = this.meta.objectStorageS3ForcePathStyle; - this.enableTwitterIntegration = this.meta.enableTwitterIntegration; - this.twitterConsumerKey = this.meta.twitterConsumerKey; - this.twitterConsumerSecret = this.meta.twitterConsumerSecret; - this.enableGithubIntegration = this.meta.enableGithubIntegration; - this.githubClientId = this.meta.githubClientId; - this.githubClientSecret = this.meta.githubClientSecret; - this.enableDiscordIntegration = this.meta.enableDiscordIntegration; - this.discordClientId = this.meta.discordClientId; - this.discordClientSecret = this.meta.discordClientSecret; - this.useStarForReactionFallback = this.meta.useStarForReactionFallback; - this.smtpSecure = this.meta.smtpSecure; - this.smtpHost = this.meta.smtpHost; - this.smtpPort = this.meta.smtpPort; - this.smtpUser = this.meta.smtpUser; - this.smtpPass = this.meta.smtpPass; - this.summalyProxy = this.meta.summalyProxy; - - if (this.proxyAccountId) { - os.api('users/show', { userId: this.proxyAccountId }).then(proxyAccount => { - this.proxyAccount = proxyAccount; - }); - } - }, - - mounted() { - this.$watch('enableHcaptcha', () => { - if (this.enableHcaptcha && this.enableRecaptcha) { - os.dialog({ - type: 'question', // warning ã ã¨é–“é•ã£ã¦ cancel ã™ã‚‹ã‹ã‚‚ã—ã‚Œãªã„ - showCancelButton: true, - title: this.$ts.settingGuide, - text: this.$ts.avoidMultiCaptchaConfirm, - }).then(({ canceled }) => { - if (canceled) { - return; - } - - this.enableRecaptcha = false; - }); - } - }); - - this.$watch('enableRecaptcha', () => { - if (this.enableRecaptcha && this.enableHcaptcha) { - os.dialog({ - type: 'question', // warning ã ã¨é–“é•ã£ã¦ cancel ã™ã‚‹ã‹ã‚‚ã—ã‚Œãªã„ - showCancelButton: true, - title: this.$ts.settingGuide, - text: this.$ts.avoidMultiCaptchaConfirm, - }).then(({ canceled }) => { - if (canceled) { - return; - } - - this.enableHcaptcha = false; - }); - } - }); + async mounted() { + this.$emit('info', this[symbols.PAGE_INFO]); }, methods: { - invite() { - os.api('admin/invite').then(x => { - os.dialog({ - type: 'info', - text: x.code - }); - }).catch(e => { - os.dialog({ - type: 'error', - text: e - }); - }); + async init() { + const meta = await os.api('meta', { detail: true }); + this.name = meta.name; + this.description = meta.description; + this.tosUrl = meta.tosUrl; + this.iconUrl = meta.iconUrl; + this.bannerUrl = meta.bannerUrl; + this.maintainerName = meta.maintainerName; + this.maintainerEmail = meta.maintainerEmail; + this.maxNoteTextLength = meta.maxNoteTextLength; + this.enableLocalTimeline = !meta.disableLocalTimeline; + this.enableGlobalTimeline = !meta.disableGlobalTimeline; }, - addPinUser() { - os.selectUser().then(user => { - this.pinnedUsers = this.pinnedUsers.trim(); - this.pinnedUsers += '\n@' + getAcct(user); - this.pinnedUsers = this.pinnedUsers.trim(); - }); - }, - - chooseProxyAccount() { - os.selectUser().then(user => { - this.proxyAccount = user; - this.proxyAccountId = user.id; - this.save(true); - }); - }, - - async testEmail() { - os.api('admin/send-email', { - to: this.maintainerEmail, - subject: 'Test email', - text: 'Yo' - }).then(x => { - os.dialog({ - type: 'success', - splash: true - }); - }).catch(e => { - os.dialog({ - type: 'error', - text: e - }); - }); - }, - - save(withDialog = false) { - os.api('admin/update-meta', { + save() { + os.apiWithDialog('admin/update-meta', { name: this.name, description: this.description, tosUrl: this.tosUrl, - bannerUrl: this.bannerUrl, iconUrl: this.iconUrl, - logoImageUrl: this.logoImageUrl, - backgroundImageUrl: this.backgroundImageUrl, + bannerUrl: this.bannerUrl, maintainerName: this.maintainerName, maintainerEmail: this.maintainerEmail, maxNoteTextLength: this.maxNoteTextLength, - disableRegistration: !this.enableRegistration, disableLocalTimeline: !this.enableLocalTimeline, disableGlobalTimeline: !this.enableGlobalTimeline, - enableHcaptcha: this.enableHcaptcha, - hcaptchaSiteKey: this.hcaptchaSiteKey, - hcaptchaSecretKey: this.hcaptchaSecretKey, - enableRecaptcha: this.enableRecaptcha, - recaptchaSiteKey: this.recaptchaSiteKey, - recaptchaSecretKey: this.recaptchaSecretKey, - proxyAccountId: this.proxyAccountId, - cacheRemoteFiles: this.cacheRemoteFiles, - proxyRemoteFiles: this.proxyRemoteFiles, - localDriveCapacityMb: parseInt(this.localDriveCapacityMb, 10), - remoteDriveCapacityMb: parseInt(this.remoteDriveCapacityMb, 10), - blockedHosts: this.blockedHosts.split('\n') || [], - pinnedUsers: this.pinnedUsers ? this.pinnedUsers.split('\n') : [], - pinnedPages: this.pinnedPages ? this.pinnedPages.split('\n') : [], - pinnedClipId: (this.pinnedClipId && this.pinnedClipId) != '' ? this.pinnedClipId : null, - enableServiceWorker: this.enableServiceWorker, - swPublicKey: this.swPublicKey, - swPrivateKey: this.swPrivateKey, - useObjectStorage: this.useObjectStorage, - objectStorageBaseUrl: this.objectStorageBaseUrl ? this.objectStorageBaseUrl : null, - objectStorageBucket: this.objectStorageBucket ? this.objectStorageBucket : null, - objectStoragePrefix: this.objectStoragePrefix ? this.objectStoragePrefix : null, - objectStorageEndpoint: this.objectStorageEndpoint ? this.objectStorageEndpoint : null, - objectStorageRegion: this.objectStorageRegion ? this.objectStorageRegion : null, - objectStoragePort: this.objectStoragePort ? this.objectStoragePort : null, - objectStorageAccessKey: this.objectStorageAccessKey ? this.objectStorageAccessKey : null, - objectStorageSecretKey: this.objectStorageSecretKey ? this.objectStorageSecretKey : null, - objectStorageUseSSL: this.objectStorageUseSSL, - objectStorageUseProxy: this.objectStorageUseProxy, - objectStorageSetPublicRead: this.objectStorageSetPublicRead, - objectStorageS3ForcePathStyle: this.objectStorageS3ForcePathStyle, - enableTwitterIntegration: this.enableTwitterIntegration, - twitterConsumerKey: this.twitterConsumerKey, - twitterConsumerSecret: this.twitterConsumerSecret, - enableGithubIntegration: this.enableGithubIntegration, - githubClientId: this.githubClientId, - githubClientSecret: this.githubClientSecret, - enableDiscordIntegration: this.enableDiscordIntegration, - discordClientId: this.discordClientId, - discordClientSecret: this.discordClientSecret, - enableEmail: this.enableEmail, - email: this.email, - smtpSecure: this.smtpSecure, - smtpHost: this.smtpHost, - smtpPort: this.smtpPort, - smtpUser: this.smtpUser, - smtpPass: this.smtpPass, - summalyProxy: this.summalyProxy, - useStarForReactionFallback: this.useStarForReactionFallback, }).then(() => { fetchInstance(); - if (withDialog) { - os.success(); - } - }).catch(e => { - os.dialog({ - type: 'error', - text: e - }); }); } } diff --git a/src/client/pages/instance/user-dialog.vue b/src/client/pages/instance/user-dialog.vue deleted file mode 100644 index a6bab5ecb812280354342067825e8b6186e59f46..0000000000000000000000000000000000000000 --- a/src/client/pages/instance/user-dialog.vue +++ /dev/null @@ -1,233 +0,0 @@ -<template> -<XModalWindow ref="dialog" - :width="370" - @close="$refs.dialog.close()" - @closed="$emit('closed')" -> - <template #header v-if="user"><MkUserName class="name" :user="user"/></template> - <div class="vrcsvlkm" v-if="user && info"> - <div class="_section"> - <div class="banner" :style="bannerStyle"> - <MkAvatar class="avatar" :user="user" :show-indicator="true"/> - </div> - </div> - <div class="_section"> - <div class="title"> - <span class="acct">@{{ acct(user) }}</span> - </div> - <div class="status"> - <span class="staff" v-if="user.isAdmin"><Fa :icon="faBookmark"/></span> - <span class="staff" v-if="user.isModerator"><Fa :icon="farBookmark"/></span> - <span class="punished" v-if="user.isSilenced"><Fa :icon="faMicrophoneSlash"/></span> - <span class="punished" v-if="user.isSuspended"><Fa :icon="faSnowflake"/></span> - </div> - </div> - <div class="_section"> - <div class="_content"> - <MkSwitch v-if="user.host == null && $i.isAdmin && (moderator || !user.isAdmin)" @update:value="toggleModerator" v-model:value="moderator">{{ $ts.moderator }}</MkSwitch> - <MkSwitch @update:value="toggleSilence" v-model:value="silenced">{{ $ts.silence }}</MkSwitch> - <MkSwitch @update:value="toggleSuspend" v-model:value="suspended">{{ $ts.suspend }}</MkSwitch> - </div> - </div> - <div class="_section"> - <div class="_content"> - <MkButton full @click="openProfile"><Fa :icon="faExternalLinkSquareAlt"/> {{ $ts.profile }}</MkButton> - <MkButton full v-if="user.host != null" @click="updateRemoteUser"><Fa :icon="faSync"/> {{ $ts.updateRemoteUser }}</MkButton> - <MkButton full @click="resetPassword"><Fa :icon="faKey"/> {{ $ts.resetPassword }}</MkButton> - <MkButton full @click="deleteAllFiles" danger><Fa :icon="faTrashAlt"/> {{ $ts.deleteAllFiles }}</MkButton> - </div> - </div> - <div class="_section"> - <details class="_content rawdata"> - <pre><code>{{ JSON.stringify(info, null, 2) }}</code></pre> - </details> - </div> - </div> -</XModalWindow> -</template> - -<script lang="ts"> -import { computed, defineComponent } from 'vue'; -import { faTimes, faBookmark, faKey, faSync, faMicrophoneSlash, faExternalLinkSquareAlt } from '@fortawesome/free-solid-svg-icons'; -import { faSnowflake, faTrashAlt, faBookmark as farBookmark } from '@fortawesome/free-regular-svg-icons'; -import MkButton from '@client/components/ui/button.vue'; -import MkSwitch from '@client/components/ui/switch.vue'; -import XModalWindow from '@client/components/ui/modal-window.vue'; -import Progress from '@client/scripts/loading'; -import { acct, userPage } from '../../filters/user'; -import * as os from '@client/os'; - -export default defineComponent({ - components: { - MkButton, - MkSwitch, - XModalWindow, - }, - - props: { - userId: { - required: true, - } - }, - - emits: ['closed'], - - data() { - return { - user: null, - info: null, - moderator: false, - silenced: false, - suspended: false, - faTimes, faBookmark, farBookmark, faKey, faSync, faMicrophoneSlash, faSnowflake, faTrashAlt, faExternalLinkSquareAlt - }; - }, - - computed: { - bannerStyle(): any { - if (this.user.bannerUrl == null) return {}; - return { - backgroundImage: `url(${ this.user.bannerUrl })` - }; - }, - }, - - created() { - this.fetch(); - }, - - methods: { - async fetch() { - Progress.start(); - this.user = await os.api('users/show', { userId: this.userId }); - this.info = await os.api('admin/show-user', { userId: this.userId }); - this.moderator = this.info.isModerator; - this.silenced = this.info.isSilenced; - this.suspended = this.info.isSuspended; - Progress.done(); - }, - - /** 処ç†å¯¾è±¡ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®æƒ…å ±ã‚’æ›´æ–°ã™ã‚‹ */ - async refreshUser() { - this.user = await os.api('users/show', { userId: this.user.id }); - this.info = await os.api('admin/show-user', { userId: this.user.id }); - }, - - openProfile() { - window.open(userPage(this.user, null, true), '_blank'); - }, - - async updateRemoteUser() { - await os.api('admin/update-remote-user', { userId: this.user.id }).then(res => { - os.success(); - }); - await this.refreshUser(); - }, - - async resetPassword() { - os.apiWithDialog('admin/reset-password', { - userId: this.user.id, - }, undefined, ({ password }) => { - os.dialog({ - type: 'success', - text: this.$t('newPasswordIs', { password }) - }); - }); - }, - - async toggleSilence(v) { - const confirm = await os.dialog({ - type: 'warning', - showCancelButton: true, - text: v ? this.$ts.silenceConfirm : this.$ts.unsilenceConfirm, - }); - if (confirm.canceled) { - this.silenced = !v; - } else { - await os.api(v ? 'admin/silence-user' : 'admin/unsilence-user', { userId: this.user.id }); - await this.refreshUser(); - } - }, - - async toggleSuspend(v) { - const confirm = await os.dialog({ - type: 'warning', - showCancelButton: true, - text: v ? this.$ts.suspendConfirm : this.$ts.unsuspendConfirm, - }); - if (confirm.canceled) { - this.suspended = !v; - } else { - await os.api(v ? 'admin/suspend-user' : 'admin/unsuspend-user', { userId: this.user.id }); - await this.refreshUser(); - } - }, - - async toggleModerator(v) { - await os.api(v ? 'admin/moderators/add' : 'admin/moderators/remove', { userId: this.user.id }); - await this.refreshUser(); - }, - - async deleteAllFiles() { - const confirm = await os.dialog({ - type: 'warning', - showCancelButton: true, - text: this.$ts.deleteAllFilesConfirm, - }); - if (confirm.canceled) return; - const process = async () => { - await os.api('admin/delete-all-files-of-a-user', { userId: this.user.id }); - os.success(); - }; - await process().catch(e => { - os.dialog({ - type: 'error', - text: e.toString() - }); - }); - await this.refreshUser(); - }, - - acct - } -}); -</script> - -<style lang="scss" scoped> -.vrcsvlkm { - > ._section { - > .banner { - position: relative; - height: 100px; - background-color: #4c5e6d; - background-size: cover; - background-position: center; - border-radius: 8px; - - > .avatar { - position: absolute; - top: 60px; - width: 64px; - height: 64px; - left: 0; - right: 0; - margin: 0 auto; - border: solid 4px var(--panel); - } - } - - > .title { - text-align: center; - } - - > .status { - text-align: center; - margin-top: 8px; - } - - > .rawdata { - overflow: auto; - } - } -} -</style> diff --git a/src/client/pages/instance/users.vue b/src/client/pages/instance/users.vue index ea09b1bda09ccb1f7fd734662bf486b92dee0ed3..2808b70fba6ca8b2936297f4155ebfdd098b69c3 100644 --- a/src/client/pages/instance/users.vue +++ b/src/client/pages/instance/users.vue @@ -1,88 +1,71 @@ <template> -<div class="mk-instance-users"> - <div class="_section"> - <div class="_content"> - <MkButton inline primary @click="addUser()"><Fa :icon="faPlus"/> {{ $ts.addUser }}</MkButton> - </div> +<div class="lknzcolw"> + <div class="actions"> + <MkButton inline primary @click="addUser()"><i class="fas fa-plus"></i> {{ $ts.addUser }}</MkButton> + <MkButton inline primary @click="lookupUser()"><i class="fas fa-search"></i> {{ $ts.lookup }}</MkButton> </div> - <div class="_section lookup"> - <div class="_title"><Fa :icon="faSearch"/> {{ $ts.lookup }}</div> - <div class="_content"> - <MkInput class="target" v-model:value="target" type="text" @enter="showUser()"> - <span>{{ $ts.usernameOrUserId }}</span> + <div class="users"> + <div class="inputs" style="display: flex;"> + <MkSelect v-model:value="sort" style="margin: 0; flex: 1;"> + <template #label>{{ $ts.sort }}</template> + <option value="-createdAt">{{ $ts.registeredDate }} ({{ $ts.ascendingOrder }})</option> + <option value="+createdAt">{{ $ts.registeredDate }} ({{ $ts.descendingOrder }})</option> + <option value="-updatedAt">{{ $ts.lastUsed }} ({{ $ts.ascendingOrder }})</option> + <option value="+updatedAt">{{ $ts.lastUsed }} ({{ $ts.descendingOrder }})</option> + </MkSelect> + <MkSelect v-model:value="state" style="margin: 0; flex: 1;"> + <template #label>{{ $ts.state }}</template> + <option value="all">{{ $ts.all }}</option> + <option value="available">{{ $ts.normal }}</option> + <option value="admin">{{ $ts.administrator }}</option> + <option value="moderator">{{ $ts.moderator }}</option> + <option value="silenced">{{ $ts.silence }}</option> + <option value="suspended">{{ $ts.suspend }}</option> + </MkSelect> + <MkSelect v-model:value="origin" style="margin: 0; flex: 1;"> + <template #label>{{ $ts.instance }}</template> + <option value="combined">{{ $ts.all }}</option> + <option value="local">{{ $ts.local }}</option> + <option value="remote">{{ $ts.remote }}</option> + </MkSelect> + </div> + <div class="inputs" style="display: flex; padding-top: 1.2em;"> + <MkInput v-model:value="searchUsername" style="margin: 0; flex: 1;" type="text" spellcheck="false" @update:value="$refs.users.reload()"> + <span>{{ $ts.username }}</span> + </MkInput> + <MkInput v-model:value="searchHost" style="margin: 0; flex: 1;" type="text" spellcheck="false" @update:value="$refs.users.reload()" :disabled="pagination.params().origin === 'local'"> + <span>{{ $ts.host }}</span> </MkInput> - <MkButton @click="showUser()" primary><Fa :icon="faSearch"/> {{ $ts.lookup }}</MkButton> </div> - </div> - <div class="_section users"> - <div class="_title"><Fa :icon="faUsers"/> {{ $ts.users }}</div> - <div class="_content"> - <div class="inputs" style="display: flex;"> - <MkSelect v-model:value="sort" style="margin: 0; flex: 1;"> - <template #label>{{ $ts.sort }}</template> - <option value="-createdAt">{{ $ts.registeredDate }} ({{ $ts.ascendingOrder }})</option> - <option value="+createdAt">{{ $ts.registeredDate }} ({{ $ts.descendingOrder }})</option> - <option value="-updatedAt">{{ $ts.lastUsed }} ({{ $ts.ascendingOrder }})</option> - <option value="+updatedAt">{{ $ts.lastUsed }} ({{ $ts.descendingOrder }})</option> - </MkSelect> - <MkSelect v-model:value="state" style="margin: 0; flex: 1;"> - <template #label>{{ $ts.state }}</template> - <option value="all">{{ $ts.all }}</option> - <option value="available">{{ $ts.normal }}</option> - <option value="admin">{{ $ts.administrator }}</option> - <option value="moderator">{{ $ts.moderator }}</option> - <option value="silenced">{{ $ts.silence }}</option> - <option value="suspended">{{ $ts.suspend }}</option> - </MkSelect> - <MkSelect v-model:value="origin" style="margin: 0; flex: 1;"> - <template #label>{{ $ts.instance }}</template> - <option value="combined">{{ $ts.all }}</option> - <option value="local">{{ $ts.local }}</option> - <option value="remote">{{ $ts.remote }}</option> - </MkSelect> - </div> - <div class="inputs" style="display: flex; padding-top: 1.2em;"> - <MkInput v-model:value="searchUsername" style="margin: 0; flex: 1;" type="text" spellcheck="false" @update:value="$refs.users.reload()"> - <span>{{ $ts.username }}</span> - </MkInput> - <MkInput v-model:value="searchHost" style="margin: 0; flex: 1;" type="text" spellcheck="false" @update:value="$refs.users.reload()" :disabled="pagination.params().origin === 'local'"> - <span>{{ $ts.host }}</span> - </MkInput> - </div> - - <MkPagination :pagination="pagination" #default="{items}" class="users" ref="users"> - <button class="user _panel _button _gap" v-for="user in items" :key="user.id" @click="show(user)"> - <MkAvatar class="avatar" :user="user" :disable-link="true" :show-indicator="true"/> - <div class="body"> - <header> - <MkUserName class="name" :user="user"/> - <span class="acct">@{{ acct(user) }}</span> - <span class="staff" v-if="user.isAdmin"><Fa :icon="faBookmark"/></span> - <span class="staff" v-if="user.isModerator"><Fa :icon="farBookmark"/></span> - <span class="punished" v-if="user.isSilenced"><Fa :icon="faMicrophoneSlash"/></span> - <span class="punished" v-if="user.isSuspended"><Fa :icon="faSnowflake"/></span> - </header> - <div> - <span>{{ $ts.lastUsed }}: <MkTime v-if="user.updatedAt" :time="user.updatedAt" mode="detail"/></span> - </div> - <div> - <span>{{ $ts.registeredDate }}: <MkTime :time="user.createdAt" mode="detail"/></span> - </div> + <MkPagination :pagination="pagination" #default="{items}" class="users" ref="users"> + <button class="user _panel _button _gap" v-for="user in items" :key="user.id" @click="show(user)"> + <MkAvatar class="avatar" :user="user" :disable-link="true" :show-indicator="true"/> + <div class="body"> + <header> + <MkUserName class="name" :user="user"/> + <span class="acct">@{{ acct(user) }}</span> + <span class="staff" v-if="user.isAdmin"><i class="fas fa-bookmark"></i></span> + <span class="staff" v-if="user.isModerator"><i class="far fa-bookmark"></i></span> + <span class="punished" v-if="user.isSilenced"><i class="fas fa-microphone-slash"></i></span> + <span class="punished" v-if="user.isSuspended"><i class="fas fa-snowflake"></i></span> + </header> + <div> + <span>{{ $ts.lastUsed }}: <MkTime v-if="user.updatedAt" :time="user.updatedAt" mode="detail"/></span> </div> - </button> - </MkPagination> - </div> + <div> + <span>{{ $ts.registeredDate }}: <MkTime :time="user.createdAt" mode="detail"/></span> + </div> + </div> + </button> + </MkPagination> </div> </div> </template> <script lang="ts"> import { defineComponent } from 'vue'; -import { faPlus, faUsers, faSearch, faBookmark, faMicrophoneSlash } 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'; import MkSelect from '@client/components/ui/select.vue'; @@ -90,6 +73,7 @@ import MkPagination from '@client/components/ui/pagination.vue'; import { acct } from '../../filters/user'; import * as os from '@client/os'; import * as symbols from '@client/symbols'; +import { lookupUser } from '@client/scripts/lookup-user'; export default defineComponent({ components: { @@ -99,17 +83,18 @@ export default defineComponent({ MkPagination, }, + emits: ['info'], + data() { return { [symbols.PAGE_INFO]: { title: this.$ts.users, - icon: faUsers, + icon: 'fas fa-users', action: { - icon: faSearch, + icon: 'fas fa-search', handler: this.searchUser } }, - target: '', sort: '+createdAt', state: 'all', origin: 'local', @@ -127,7 +112,6 @@ export default defineComponent({ }), offsetMode: true }, - faPlus, faUsers, faSearch, faBookmark, farBookmark, faMicrophoneSlash, faSnowflake } }, @@ -143,40 +127,12 @@ export default defineComponent({ }, }, - methods: { - /** テã‚ストエリアã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’解決ã™ã‚‹ */ - fetchUser() { - return new Promise((res) => { - const usernamePromise = os.api('users/show', parseAcct(this.target)); - const idPromise = os.api('users/show', { userId: this.target }); - let _notFound = false; - const notFound = () => { - if (_notFound) { - os.dialog({ - type: 'error', - text: this.$ts.noSuchUser - }); - } else { - _notFound = true; - } - }; - usernamePromise.then(res).catch(e => { - if (e.code === 'NO_SUCH_USER') { - notFound(); - } - }); - idPromise.then(res).catch(e => { - notFound(); - }); - }); - }, + async mounted() { + this.$emit('info', this[symbols.PAGE_INFO]); + }, - /** テã‚ストエリアã‹ã‚‰å‡¦ç†å¯¾è±¡ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’è¨å®šã™ã‚‹ */ - async showUser() { - const user = await this.fetchUser(); - this.show(user); - this.target = ''; - }, + methods: { + lookupUser, searchUser() { os.selectUser().then(user => { @@ -206,9 +162,7 @@ export default defineComponent({ }, show(user) { - os.popup(import('./user-dialog.vue'), { - userId: user.id - }, {}, 'closed'); + os.pageWindow(`/user-info/${user.id}`); }, acct @@ -217,57 +171,61 @@ export default defineComponent({ </script> <style lang="scss" scoped> -.mk-instance-users { +.lknzcolw { + > .actions { + margin: var(--margin); + } + > .users { - > ._content { - > .users { - margin-top: var(--margin); + margin: var(--margin); + + > .users { + margin-top: var(--margin); + + > .user { + display: flex; + width: 100%; + box-sizing: border-box; + text-align: left; + align-items: center; + padding: 16px; + + &:hover { + color: var(--accent); + } - > .user { - display: flex; - width: 100%; - box-sizing: border-box; - text-align: left; - align-items: center; - padding: 16px; + > .avatar { + width: 60px; + height: 60px; + } - &:hover { - color: var(--accent); - } + > .body { + margin-left: 0.3em; + padding: 0 8px; + flex: 1; - > .avatar { - width: 60px; - height: 60px; + @media (max-width: 500px) { + font-size: 14px; } - > .body { - margin-left: 0.3em; - padding: 0 8px; - flex: 1; - - @media (max-width: 500px) { - font-size: 14px; + > header { + > .name { + font-weight: bold; } - > header { - > .name { - font-weight: bold; - } - - > .acct { - margin-left: 8px; - opacity: 0.7; - } + > .acct { + margin-left: 8px; + opacity: 0.7; + } - > .staff { - margin-left: 0.5em; - color: var(--badge); - } + > .staff { + margin-left: 0.5em; + color: var(--badge); + } - > .punished { - margin-left: 0.5em; - color: #4dabf7; - } + > .punished { + margin-left: 0.5em; + color: #4dabf7; } } } diff --git a/src/client/pages/mentions.vue b/src/client/pages/mentions.vue index 042c3a498be8a28cef42cee268a4bdac54be3fbc..a12993ebb814f54eec2f0e4b594d1b90adc19166 100644 --- a/src/client/pages/mentions.vue +++ b/src/client/pages/mentions.vue @@ -6,7 +6,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faAt } 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,7 +19,7 @@ export default defineComponent({ return { [symbols.PAGE_INFO]: { title: this.$ts.mentions, - icon: faAt + icon: 'fas fa-at' }, pagination: { endpoint: 'notes/mentions', diff --git a/src/client/pages/messages.vue b/src/client/pages/messages.vue index 09d92e51ba25bc0c758f817893db8317b602d3ef..6ac9746d4e86e3d3dac516508716ecff7ccdca0e 100644 --- a/src/client/pages/messages.vue +++ b/src/client/pages/messages.vue @@ -6,7 +6,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faEnvelope } 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,7 +19,7 @@ export default defineComponent({ return { [symbols.PAGE_INFO]: { title: this.$ts.directNotes, - icon: faEnvelope + icon: 'fas fa-envelope' }, pagination: { endpoint: 'notes/mentions', @@ -29,7 +28,6 @@ export default defineComponent({ visibility: 'specified' }) }, - faEnvelope }; }, diff --git a/src/client/pages/messaging/index.vue b/src/client/pages/messaging/index.vue index 1e316e9090021bdb8f156971e25573aece44cf66..9f3323f629d6c8ae048c48eb8aa83e9cff7dd244 100644 --- a/src/client/pages/messaging/index.vue +++ b/src/client/pages/messaging/index.vue @@ -1,6 +1,6 @@ <template> <div class="yweeujhr _root" v-size="{ max: [400] }"> - <MkButton @click="start" primary class="start"><Fa :icon="faPlus"/> {{ $ts.startMessaging }}</MkButton> + <MkButton @click="start" primary class="start"><i class="fas fa-plus"></i> {{ $ts.startMessaging }}</MkButton> <div class="history" v-if="messages.length > 0"> <MkA v-for="(message, i) in messages" @@ -38,7 +38,6 @@ <script lang="ts"> import { defineAsyncComponent, defineComponent } from 'vue'; -import { faUser, faUsers, faComments, faPlus } from '@fortawesome/free-solid-svg-icons'; import getAcct from '@/misc/acct/render'; import MkButton from '@client/components/ui/button.vue'; import { acct } from '../../filters/user'; @@ -54,13 +53,12 @@ export default defineComponent({ return { [symbols.PAGE_INFO]: { title: this.$ts.messaging, - icon: faComments + icon: 'fas fa-comments' }, fetching: true, moreFetching: false, messages: [], connection: null, - faUser, faUsers, faComments, faPlus }; }, @@ -120,11 +118,11 @@ export default defineComponent({ start(ev) { os.modalMenu([{ text: this.$ts.messagingWithUser, - icon: faUser, + icon: 'fas fa-user', action: () => { this.startUser() } }, { text: this.$ts.messagingWithGroup, - icon: faUsers, + icon: 'fas fa-users', action: () => { this.startGroup() } }], ev.currentTarget || ev.target); }, diff --git a/src/client/pages/messaging/messaging-room.form.vue b/src/client/pages/messaging/messaging-room.form.vue index c547e18850425e441b59ef39244c6ddfdc72c024..31c42e4ab39be6f4b76dfab746467d41a4077b1c 100644 --- a/src/client/pages/messaging/messaging-room.form.vue +++ b/src/client/pages/messaging/messaging-room.form.vue @@ -13,17 +13,16 @@ ></textarea> <div class="file" @click="file = null" v-if="file">{{ file.name }}</div> <button class="send _button" @click="send" :disabled="!canSend || sending" :title="$ts.send"> - <template v-if="!sending"><Fa :icon="faPaperPlane"/></template><template v-if="sending"><Fa icon="spinner .spin"/></template> + <template v-if="!sending"><i class="fas fa-paper-plane"></i></template><template v-if="sending"><i class="fas fa-spinner fa-pulse fa-fw"></i></template> </button> - <button class="_button" @click="chooseFile"><Fa :icon="faPhotoVideo"/></button> - <button class="_button" @click="insertEmoji"><Fa :icon="faLaughSquint"/></button> + <button class="_button" @click="chooseFile"><i class="fas fa-photo-video"></i></button> + <button class="_button" @click="insertEmoji"><i class="fas fa-laugh-squint"></i></button> <input ref="file" type="file" @change="onChangeFile"/> </div> </template> <script lang="ts"> import { defineComponent, defineAsyncComponent } from 'vue'; -import { faPaperPlane, faPhotoVideo, faLaughSquint } from '@fortawesome/free-solid-svg-icons'; import insertTextAtCursor from 'insert-text-at-cursor'; import * as autosize from 'autosize'; import { formatTimeString } from '@/misc/format-time-string'; @@ -51,7 +50,6 @@ export default defineComponent({ typing: throttle(3000, () => { os.stream.send('typingOnMessaging', this.user ? { partner: this.user.id } : { group: this.group.id }); }), - faPaperPlane, faPhotoVideo, faLaughSquint }; }, computed: { diff --git a/src/client/pages/messaging/messaging-room.message.vue b/src/client/pages/messaging/messaging-room.message.vue index 1228baff68e35783ca608f9102aeeda11f36db7b..dfac83ad6a3776b52cf43e7d4120f529c34972e0 100644 --- a/src/client/pages/messaging/messaging-room.message.vue +++ b/src/client/pages/messaging/messaging-room.message.vue @@ -29,7 +29,7 @@ <span class="read" v-if="isMe && message.isRead">{{ $ts.messageRead }}</span> </template> <MkTime :time="message.createdAt"/> - <template v-if="message.is_edited"><Fa icon="pencil-alt"/></template> + <template v-if="message.is_edited"><i class="fas fa-pencil-alt"></i></template> </footer> </div> </div> @@ -221,7 +221,7 @@ export default defineComponent({ margin: 0 8px; } - > [data-icon] { + > i { margin-left: 4px; } } diff --git a/src/client/pages/messaging/messaging-room.vue b/src/client/pages/messaging/messaging-room.vue index dae4590213b8c9633fb1812a893a359bae8b8ccc..44bfd6c51dc7229867b180bd3c9e6e21238bc37b 100644 --- a/src/client/pages/messaging/messaging-room.vue +++ b/src/client/pages/messaging/messaging-room.vue @@ -6,10 +6,10 @@ <div class="_content mk-messaging-room"> <div class="body"> <MkLoading v-if="fetching"/> - <p class="empty" v-if="!fetching && messages.length == 0"><Fa :icon="faInfoCircle"/>{{ $ts.noMessagesYet }}</p> - <p class="no-history" v-if="!fetching && messages.length > 0 && !existMoreMessages"><Fa :icon="faFlag"/>{{ $ts.noMoreHistory }}</p> + <p class="empty" v-if="!fetching && messages.length == 0"><i class="fas fa-info-circle"></i>{{ $ts.noMessagesYet }}</p> + <p class="no-history" v-if="!fetching && messages.length > 0 && !existMoreMessages"><i class="fas fa-flag"></i>{{ $ts.noMoreHistory }}</p> <button class="more _button" ref="loadMore" :class="{ fetching: fetchingMoreMessages }" v-show="existMoreMessages" @click="fetchMoreMessages" :disabled="fetchingMoreMessages"> - <template v-if="fetchingMoreMessages"><Fa icon="spinner" pulse fixed-width/></template>{{ fetchingMoreMessages ? $ts.loading : $ts.loadMore }} + <template v-if="fetchingMoreMessages"><i class="fas fa-spinner fa-pulse fa-fw"></i></template>{{ fetchingMoreMessages ? $ts.loading : $ts.loadMore }} </button> <XList class="messages" :items="messages" v-slot="{ item: message }" direction="up" reversed> <XMessage :message="message" :is-group="group != null" :key="message.id"/> @@ -26,7 +26,7 @@ </div> <transition name="fade"> <div class="new-message" v-show="showIndicator"> - <button class="_buttonPrimary" @click="onIndicatorClick"><i><Fa :icon="faArrowCircleDown"/></i>{{ $ts.newMessageExists }}</button> + <button class="_buttonPrimary" @click="onIndicatorClick"><i class="fas fa-arrow-circle-down"></i>{{ $ts.newMessageExists }}</button> </div> </transition> <XForm v-if="!fetching" :user="user" :group="group" ref="form"/> @@ -37,8 +37,6 @@ <script lang="ts"> import { computed, defineComponent } from 'vue'; -import { faArrowCircleDown, faFlag, faUsers, faInfoCircle, faEllipsisH, faExternalLinkAlt } from '@fortawesome/free-solid-svg-icons'; -import { faWindowMaximize } from '@fortawesome/free-regular-svg-icons'; import XList from '@client/components/date-separated-list.vue'; import XMessage from './messaging-room.message.vue'; import XForm from './messaging-room.form.vue'; @@ -75,14 +73,14 @@ const Component = defineComponent({ userName: this.user, avatar: this.user, action: { - icon: faEllipsisH, + icon: 'fas fa-ellipsis-h', handler: this.menu, }, } : { title: this.group.name, - icon: faUsers, + icon: 'fas fa-users', action: { - icon: faEllipsisH, + icon: 'fas fa-ellipsis-h', handler: this.menu, }, } : null), @@ -103,7 +101,6 @@ const Component = defineComponent({ && this.existMoreMessages && this.fetchMoreMessages() ), - faArrowCircleDown, faFlag, faInfoCircle }; }, @@ -325,14 +322,14 @@ const Component = defineComponent({ os.modalMenu([this.inWindow ? undefined : { text: this.$ts.openInWindow, - icon: faWindowMaximize, + icon: 'fas fa-window-maximize', action: () => { os.pageWindow(path); this.$router.back(); }, }, this.inWindow ? undefined : { text: this.$ts.popout, - icon: faExternalLinkAlt, + icon: 'fas fa-external-link-alt', action: () => { popout(path); this.$router.back(); @@ -356,7 +353,7 @@ export default Component; font-size: 0.8em; opacity: 0.5; - [data-icon] { + i { margin-right: 4px; } } @@ -370,7 +367,7 @@ export default Component; color: var(--messagingRoomInfo); opacity: 0.5; - [data-icon] { + i { margin-right: 4px; } } @@ -396,7 +393,7 @@ export default Component; cursor: wait; } - > [data-icon] { + > i { margin-right: 4px; } } diff --git a/src/client/pages/mfm-cheat-sheet.vue b/src/client/pages/mfm-cheat-sheet.vue index 36f40dbcab10972de3a35a648ce62927fc13041e..52278552362fc629928277c46d4cb7d860714e49 100644 --- a/src/client/pages/mfm-cheat-sheet.vue +++ b/src/client/pages/mfm-cheat-sheet.vue @@ -266,7 +266,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faQuestionCircle } from '@fortawesome/free-regular-svg-icons'; import MkTextarea from '@client/components/ui/textarea.vue'; import * as symbols from '@client/symbols'; @@ -279,7 +278,7 @@ export default defineComponent({ return { [symbols.PAGE_INFO]: { title: this.$ts._mfm.cheatSheet, - icon: faQuestionCircle, + icon: 'fas fa-question-circle', }, preview_mention: '@example', preview_hashtag: '#test', diff --git a/src/client/pages/my-antennas/index.antenna.vue b/src/client/pages/my-antennas/index.antenna.vue index d7050d08c46217be5e87180790d9ae304b08021c..8cad6fa5538f1d7315d0e189badb106df7bb8b7d 100644 --- a/src/client/pages/my-antennas/index.antenna.vue +++ b/src/client/pages/my-antennas/index.antenna.vue @@ -39,15 +39,14 @@ <MkSwitch v-model:value="notify">{{ $ts.notifyAntenna }}</MkSwitch> </div> <div class="_footer"> - <MkButton inline @click="saveAntenna()" primary><Fa :icon="faSave"/> {{ $ts.save }}</MkButton> - <MkButton inline @click="deleteAntenna()" v-if="antenna.id != null"><Fa :icon="faTrash"/> {{ $ts.delete }}</MkButton> + <MkButton inline @click="saveAntenna()" primary><i class="fas fa-save"></i> {{ $ts.save }}</MkButton> + <MkButton inline @click="deleteAntenna()" v-if="antenna.id != null"><i class="fas fa-trash"></i> {{ $ts.delete }}</MkButton> </div> </div> </template> <script lang="ts"> import { defineComponent } from 'vue'; -import { faSave, faTrash } from '@fortawesome/free-solid-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'; @@ -83,7 +82,6 @@ export default defineComponent({ notify: false, userLists: null, userGroups: null, - faSave, faTrash }; }, diff --git a/src/client/pages/my-antennas/index.vue b/src/client/pages/my-antennas/index.vue index dfb752b831ab1d4b73e00dfb93e9ada1a892cc91..57c55cefddae0b9eda635bd35b1b0dbf86184e46 100644 --- a/src/client/pages/my-antennas/index.vue +++ b/src/client/pages/my-antennas/index.vue @@ -1,6 +1,6 @@ <template> <div class="ieepwinx _section"> - <MkButton @click="create" primary class="add"><Fa :icon="faPlus"/> {{ $ts.add }}</MkButton> + <MkButton @click="create" primary class="add"><i class="fas fa-plus"></i> {{ $ts.add }}</MkButton> <div class="_content"> <XAntenna v-if="draft" :antenna="draft" @created="onAntennaCreated" style="margin-bottom: var(--margin);"/> @@ -14,7 +14,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faSatellite, faPlus } from '@fortawesome/free-solid-svg-icons'; import MkPagination from '@client/components/ui/pagination.vue'; import MkButton from '@client/components/ui/button.vue'; import XAntenna from './index.antenna.vue'; @@ -31,9 +30,9 @@ export default defineComponent({ return { [symbols.PAGE_INFO]: { title: this.$ts.manageAntennas, - icon: faSatellite, + icon: 'fas fa-satellite', action: { - icon: faPlus, + icon: 'fas fa-plus', handler: this.create } }, @@ -42,7 +41,6 @@ export default defineComponent({ limit: 10, }, draft: null, - faSatellite, faPlus }; }, diff --git a/src/client/pages/my-clips/index.vue b/src/client/pages/my-clips/index.vue index 09cd7f828af0bbdc8b326fafbac57edaf0189a12..c4ca474748b3518372d4be7ce8a32214cfe69b0f 100644 --- a/src/client/pages/my-clips/index.vue +++ b/src/client/pages/my-clips/index.vue @@ -1,6 +1,6 @@ <template> <div class="_section qtcaoidl"> - <MkButton @click="create" primary class="add"><Fa :icon="faPlus"/> {{ $ts.add }}</MkButton> + <MkButton @click="create" primary class="add"><i class="fas fa-plus"></i> {{ $ts.add }}</MkButton> <div class="_content"> <MkPagination :pagination="pagination" #default="{items}" ref="list" class="list"> @@ -15,7 +15,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faPlus, faPaperclip } 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'; @@ -31,9 +30,9 @@ export default defineComponent({ return { [symbols.PAGE_INFO]: { title: this.$ts.clip, - icon: faPaperclip, + icon: 'fas fa-paperclip', action: { - icon: faPlus, + icon: 'fas fa-plus', handler: this.create } }, @@ -42,7 +41,6 @@ export default defineComponent({ limit: 10, }, draft: null, - faPlus }; }, diff --git a/src/client/pages/my-groups/group.vue b/src/client/pages/my-groups/group.vue index 90a60e5e2b159298edde03d39b45cc0575b04025..bd5537cbfa3c113b91b686ac879d63c4a0a7b41b 100644 --- a/src/client/pages/my-groups/group.vue +++ b/src/client/pages/my-groups/group.vue @@ -23,7 +23,7 @@ <MkAcct :user="user" class="acct"/> </div> <div class="action"> - <button class="_button" @click="removeUser(user)"><Fa :icon="faTimes"/></button> + <button class="_button" @click="removeUser(user)"><i class="fas fa-times"></i></button> </div> </div> </div> @@ -35,7 +35,6 @@ <script lang="ts"> import { computed, defineComponent } from 'vue'; -import { faTimes, faUsers } from '@fortawesome/free-solid-svg-icons'; import Progress from '@client/scripts/loading'; import MkButton from '@client/components/ui/button.vue'; import * as os from '@client/os'; @@ -57,11 +56,10 @@ export default defineComponent({ return { [symbols.PAGE_INFO]: computed(() => this.group ? { title: this.group.name, - icon: faUsers, + icon: 'fas fa-users', } : null), group: null, users: [], - faTimes, faUsers }; }, diff --git a/src/client/pages/my-groups/index.vue b/src/client/pages/my-groups/index.vue index 5125ce3f4fb5cebfb9c46cc57e76f1c2294a853c..9f153ff9ccf4d3acd5748d73d29f61f4fe4bf0fb 100644 --- a/src/client/pages/my-groups/index.vue +++ b/src/client/pages/my-groups/index.vue @@ -4,13 +4,13 @@ <MkTab v-model:value="tab"> <option value="owned">{{ $ts.ownedGroups }}</option> <option value="joined">{{ $ts.joinedGroups }}</option> - <option value="invites"><Fa :icon="faEnvelopeOpenText"/> {{ $ts.invites }}</option> + <option value="invites"><i class="fas fa-envelope-open-text"></i> {{ $ts.invites }}</option> </MkTab> </div> <div class="_section"> <div class="_content" v-if="tab === 'owned'"> - <MkButton @click="create" primary style="margin: 0 auto var(--margin) auto;"><Fa :icon="faPlus"/> {{ $ts.createGroup }}</MkButton> + <MkButton @click="create" primary style="margin: 0 auto var(--margin) auto;"><i class="fas fa-plus"></i> {{ $ts.createGroup }}</MkButton> <MkPagination :pagination="ownedPagination" #default="{items}" ref="owned"> <div class="_card" v-for="group in items" :key="group.id"> @@ -35,8 +35,8 @@ <div class="_title">{{ invitation.group.name }}</div> <div class="_content"><MkAvatars :user-ids="invitation.group.userIds"/></div> <div class="_footer"> - <MkButton @click="acceptInvite(invitation)" primary inline><Fa :icon="faCheck"/> {{ $ts.accept }}</MkButton> - <MkButton @click="rejectInvite(invitation)" primary inline><Fa :icon="faBan"/> {{ $ts.reject }}</MkButton> + <MkButton @click="acceptInvite(invitation)" primary inline><i class="fas fa-check"></i> {{ $ts.accept }}</MkButton> + <MkButton @click="rejectInvite(invitation)" primary inline><i class="fas fa-ban"></i> {{ $ts.reject }}</MkButton> </div> </div> </MkPagination> @@ -47,7 +47,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faUsers, faPlus, faEnvelopeOpenText } from '@fortawesome/free-solid-svg-icons'; import MkPagination from '@client/components/ui/pagination.vue'; import MkButton from '@client/components/ui/button.vue'; import MkContainer from '@client/components/ui/container.vue'; @@ -69,7 +68,7 @@ export default defineComponent({ return { [symbols.PAGE_INFO]: { title: this.$ts.groups, - icon: faUsers + icon: 'fas fa-users' }, tab: 'owned', ownedPagination: { @@ -84,7 +83,6 @@ export default defineComponent({ endpoint: 'i/user-group-invites', limit: 10, }, - faUsers, faPlus, faEnvelopeOpenText }; }, diff --git a/src/client/pages/my-lists/index.vue b/src/client/pages/my-lists/index.vue index e680b90d1aed59b6e09c156c14699be953d97a66..2b60917060703a4ae4bd593a5a9767467fe0a3c2 100644 --- a/src/client/pages/my-lists/index.vue +++ b/src/client/pages/my-lists/index.vue @@ -1,6 +1,6 @@ <template> <div class="qkcjvfiv _section"> - <MkButton @click="create" primary class="add"><Fa :icon="faPlus"/> {{ $ts.createList }}</MkButton> + <MkButton @click="create" primary class="add"><i class="fas fa-plus"></i> {{ $ts.createList }}</MkButton> <MkPagination :pagination="pagination" #default="{items}" class="lists _content" ref="list"> <div class="list _panel" v-for="(list, i) in items" :key="list.id"> @@ -12,7 +12,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faListUl, faPlus } 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'; @@ -28,9 +27,9 @@ export default defineComponent({ return { [symbols.PAGE_INFO]: { title: this.$ts.manageLists, - icon: faListUl, + icon: 'fas fa-list-ul', action: { - icon: faPlus, + icon: 'fas fa-plus', handler: this.create } }, @@ -38,7 +37,6 @@ export default defineComponent({ endpoint: 'users/lists/list', limit: 10, }, - faListUl, faPlus }; }, diff --git a/src/client/pages/my-lists/list.vue b/src/client/pages/my-lists/list.vue index 2892150ffec079b7e8db534e399f623f32afa96a..049d370b4efb2d3b65dab2cfbf75c05eb5c47927 100644 --- a/src/client/pages/my-lists/list.vue +++ b/src/client/pages/my-lists/list.vue @@ -22,7 +22,7 @@ <MkAcct :user="user" class="acct"/> </div> <div class="action"> - <button class="_button" @click="removeUser(user)"><Fa :icon="faTimes"/></button> + <button class="_button" @click="removeUser(user)"><i class="fas fa-times"></i></button> </div> </div> </div> @@ -34,7 +34,6 @@ <script lang="ts"> import { computed, defineComponent } from 'vue'; -import { faTimes, faListUl } from '@fortawesome/free-solid-svg-icons'; import Progress from '@client/scripts/loading'; import MkButton from '@client/components/ui/button.vue'; import * as os from '@client/os'; @@ -49,11 +48,10 @@ export default defineComponent({ return { [symbols.PAGE_INFO]: computed(() => this.list ? { title: this.list.name, - icon: faListUl, + icon: 'fas fa-list-ul', } : null), list: null, users: [], - faTimes, faListUl }; }, diff --git a/src/client/pages/not-found.vue b/src/client/pages/not-found.vue index b13bdac2b8a7e4144be53946199267a1277d23b0..5e7fe17f7534e05f872bf367d1b430f3fa88262b 100644 --- a/src/client/pages/not-found.vue +++ b/src/client/pages/not-found.vue @@ -9,7 +9,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons'; import * as os from '@client/os'; import * as symbols from '@client/symbols'; @@ -18,7 +17,7 @@ export default defineComponent({ return { [symbols.PAGE_INFO]: { title: this.$ts.notFound, - icon: faExclamationTriangle + icon: 'fas fa-exclamation-triangle' }, } }, diff --git a/src/client/pages/note.vue b/src/client/pages/note.vue index 279dd9666114b8287a3e5f356372d349079d80be..ce4af4eb4e81f332044e66920cec0561486a78e7 100644 --- a/src/client/pages/note.vue +++ b/src/client/pages/note.vue @@ -7,7 +7,7 @@ </div> <div class="main _gap"> - <MkButton v-if="!showNext && hasNext" class="load next" @click="showNext = true"><Fa :icon="faChevronUp"/></MkButton> + <MkButton v-if="!showNext && hasNext" class="load next" @click="showNext = true"><i class="fas fa-chevron-up"></i></MkButton> <div class="_content _gap"> <MkRemoteCaution v-if="note.user.host != null" :href="note.url || note.uri" class="_gap"/> <XNoteDetailed v-model:note="note" :key="note.id" class="_gap"/> @@ -22,7 +22,7 @@ </div> </MkA> </div> - <MkButton v-if="!showPrev && hasPrev" class="load prev" @click="showPrev = true"><Fa :icon="faChevronDown"/></MkButton> + <MkButton v-if="!showPrev && hasPrev" class="load prev" @click="showPrev = true"><i class="fas fa-chevron-down"></i></MkButton> </div> <div class="_gap" v-if="showPrev"> @@ -37,7 +37,6 @@ <script lang="ts"> import { computed, defineComponent } from 'vue'; -import { faChevronUp, faChevronDown } from '@fortawesome/free-solid-svg-icons'; import XNote from '@client/components/note.vue'; import XNoteDetailed from '@client/components/note-detailed.vue'; import XNotes from '@client/components/notes.vue'; @@ -95,7 +94,6 @@ export default defineComponent({ sinceId: this.note.id, }) }, - faChevronUp, faChevronDown }; }, watch: { diff --git a/src/client/pages/notifications.vue b/src/client/pages/notifications.vue index 25605988edc7748c707ff5e9fa59b544c53a9f24..38797d746e1693f8013352275911ec27e693c4a0 100644 --- a/src/client/pages/notifications.vue +++ b/src/client/pages/notifications.vue @@ -6,7 +6,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faBell, faCheck } from '@fortawesome/free-solid-svg-icons'; import Progress from '@client/scripts/loading'; import XNotifications from '@client/components/notifications.vue'; import * as os from '@client/os'; @@ -21,10 +20,10 @@ export default defineComponent({ return { [symbols.PAGE_INFO]: { title: this.$ts.notifications, - icon: faBell, + icon: 'fas fa-bell', actions: [{ text: this.$ts.markAllAsRead, - icon: faCheck, + icon: 'fas fa-check', handler: () => { os.apiWithDialog('notifications/mark-all-as-read'); } diff --git a/src/client/pages/page-editor/els/page-editor.el.button.vue b/src/client/pages/page-editor/els/page-editor.el.button.vue index 1515187676e24da4e50a0ad7cda6a33dc944a616..6e9036faac0105c36da963d4498aa669c1ddc7bf 100644 --- a/src/client/pages/page-editor/els/page-editor.el.button.vue +++ b/src/client/pages/page-editor/els/page-editor.el.button.vue @@ -1,6 +1,6 @@ <template> <XContainer @remove="() => $emit('remove')" :draggable="true"> - <template #header><Fa :icon="faBolt"/> {{ $ts._pages.blocks.button }}</template> + <template #header><i class="fas fa-bolt"></i> {{ $ts._pages.blocks.button }}</template> <section class="xfhsjczc"> <MkInput v-model:value="value.text"><span>{{ $ts._pages.blocks._button.text }}</span></MkInput> @@ -39,7 +39,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faBolt } from '@fortawesome/free-solid-svg-icons'; import XContainer from '../page-editor.container.vue'; import MkSelect from '@client/components/ui/select.vue'; import MkInput from '@client/components/ui/input.vue'; @@ -62,7 +61,6 @@ export default defineComponent({ data() { return { - faBolt }; }, diff --git a/src/client/pages/page-editor/els/page-editor.el.canvas.vue b/src/client/pages/page-editor/els/page-editor.el.canvas.vue index 9d4b4c76d2699b1cc23197c34d4d6a2dd26cba12..59d29b9b71ba312d1bee2dc3c013f25b635380cc 100644 --- a/src/client/pages/page-editor/els/page-editor.el.canvas.vue +++ b/src/client/pages/page-editor/els/page-editor.el.canvas.vue @@ -1,9 +1,9 @@ <template> <XContainer @remove="() => $emit('remove')" :draggable="true"> - <template #header><Fa :icon="faPaintBrush"/> {{ $ts._pages.blocks.canvas }}</template> + <template #header><i class="fas fa-paint-brush"></i> {{ $ts._pages.blocks.canvas }}</template> <section style="padding: 0 16px 0 16px;"> - <MkInput v-model:value="value.name"><template #prefix><Fa :icon="faMagic"/></template><span>{{ $ts._pages.blocks._canvas.id }}</span></MkInput> + <MkInput v-model:value="value.name"><template #prefix><i class="fas fa-magic"></i></template><span>{{ $ts._pages.blocks._canvas.id }}</span></MkInput> <MkInput v-model:value="value.width" type="number"><span>{{ $ts._pages.blocks._canvas.width }}</span><template #suffix>px</template></MkInput> <MkInput v-model:value="value.height" type="number"><span>{{ $ts._pages.blocks._canvas.height }}</span><template #suffix>px</template></MkInput> </section> @@ -12,7 +12,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faPaintBrush, faMagic } from '@fortawesome/free-solid-svg-icons'; import XContainer from '../page-editor.container.vue'; import MkInput from '@client/components/ui/input.vue'; import * as os from '@client/os'; @@ -30,7 +29,6 @@ export default defineComponent({ data() { return { - faPaintBrush, faMagic }; }, diff --git a/src/client/pages/page-editor/els/page-editor.el.counter.vue b/src/client/pages/page-editor/els/page-editor.el.counter.vue index e16962aee92845d5d7798a58cae6e64fd27cb912..3394817b53031b726b32559e8b9c5ca55a2db3bb 100644 --- a/src/client/pages/page-editor/els/page-editor.el.counter.vue +++ b/src/client/pages/page-editor/els/page-editor.el.counter.vue @@ -1,9 +1,9 @@ <template> <XContainer @remove="() => $emit('remove')" :draggable="true"> - <template #header><Fa :icon="faBolt"/> {{ $ts._pages.blocks.counter }}</template> + <template #header><i class="fas fa-bolt"></i> {{ $ts._pages.blocks.counter }}</template> <section style="padding: 0 16px 0 16px;"> - <MkInput v-model:value="value.name"><template #prefix><Fa :icon="faMagic"/></template><span>{{ $ts._pages.blocks._counter.name }}</span></MkInput> + <MkInput v-model:value="value.name"><template #prefix><i class="fas fa-magic"></i></template><span>{{ $ts._pages.blocks._counter.name }}</span></MkInput> <MkInput v-model:value="value.text"><span>{{ $ts._pages.blocks._counter.text }}</span></MkInput> <MkInput v-model:value="value.inc" type="number"><span>{{ $ts._pages.blocks._counter.inc }}</span></MkInput> </section> @@ -12,7 +12,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faBolt, faMagic } from '@fortawesome/free-solid-svg-icons'; import XContainer from '../page-editor.container.vue'; import MkInput from '@client/components/ui/input.vue'; import * as os from '@client/os'; @@ -30,7 +29,6 @@ export default defineComponent({ data() { return { - faBolt, faMagic }; }, diff --git a/src/client/pages/page-editor/els/page-editor.el.if.vue b/src/client/pages/page-editor/els/page-editor.el.if.vue index 0cbfaa7eb859dc30fd3efbaa956a597ecec24873..7f4ed458aa2c1cd516c446ca82935cff2d63f5a8 100644 --- a/src/client/pages/page-editor/els/page-editor.el.if.vue +++ b/src/client/pages/page-editor/els/page-editor.el.if.vue @@ -1,9 +1,9 @@ <template> <XContainer @remove="() => $emit('remove')" :draggable="true"> - <template #header><Fa :icon="faQuestion"/> {{ $ts._pages.blocks.if }}</template> + <template #header><i class="fas fa-question"></i> {{ $ts._pages.blocks.if }}</template> <template #func> <button @click="add()" class="_button"> - <Fa :icon="faPlus"/> + <i class="fas fa-plus"></i> </button> </template> @@ -27,7 +27,6 @@ <script lang="ts"> import { defineComponent, defineAsyncComponent } from 'vue'; import { v4 as uuid } from 'uuid'; -import { faPlus, faQuestion } from '@fortawesome/free-solid-svg-icons'; import XContainer from '../page-editor.container.vue'; import MkSelect from '@client/components/ui/select.vue'; import * as os from '@client/os'; @@ -51,7 +50,6 @@ export default defineComponent({ data() { return { - faPlus, faQuestion }; }, diff --git a/src/client/pages/page-editor/els/page-editor.el.image.vue b/src/client/pages/page-editor/els/page-editor.el.image.vue index 1a96e42679e873d1d5e2ecf11c0846618f113abb..d96879f50d41e9689daba2fbb0dd68b1b8a53814 100644 --- a/src/client/pages/page-editor/els/page-editor.el.image.vue +++ b/src/client/pages/page-editor/els/page-editor.el.image.vue @@ -1,9 +1,9 @@ <template> <XContainer @remove="() => $emit('remove')" :draggable="true"> - <template #header><Fa :icon="faImage"/> {{ $ts._pages.blocks.image }}</template> + <template #header><i class="fas fa-image"></i> {{ $ts._pages.blocks.image }}</template> <template #func> <button @click="choose()"> - <Fa :icon="faFolderOpen"/> + <i class="fas fa-folder-open"></i> </button> </template> @@ -15,8 +15,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faPencilAlt } from '@fortawesome/free-solid-svg-icons'; -import { faImage, faFolderOpen } from '@fortawesome/free-regular-svg-icons'; import XContainer from '../page-editor.container.vue'; import MkDriveFileThumbnail from '@client/components/drive-file-thumbnail.vue'; import * as os from '@client/os'; @@ -35,7 +33,6 @@ export default defineComponent({ data() { return { file: null, - faPencilAlt, faImage, faFolderOpen }; }, diff --git a/src/client/pages/page-editor/els/page-editor.el.note.vue b/src/client/pages/page-editor/els/page-editor.el.note.vue index 3f7eaf7572984cf48752bf4f688e98e1fbfa76da..d4801f30591510f23a68fb824c381e6ff41d5fa9 100644 --- a/src/client/pages/page-editor/els/page-editor.el.note.vue +++ b/src/client/pages/page-editor/els/page-editor.el.note.vue @@ -1,6 +1,6 @@ <template> <XContainer @remove="() => $emit('remove')" :draggable="true"> - <template #header><Fa :icon="faStickyNote"/> {{ $ts._pages.blocks.note }}</template> + <template #header><i class="fas fa-sticky-note"></i> {{ $ts._pages.blocks.note }}</template> <section style="padding: 0 16px 0 16px;"> <MkInput v-model:value="id"> @@ -17,7 +17,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faStickyNote } from '@fortawesome/free-solid-svg-icons'; import XContainer from '../page-editor.container.vue'; import MkInput from '@client/components/ui/input.vue'; import MkSwitch from '@client/components/ui/switch.vue'; @@ -40,7 +39,6 @@ export default defineComponent({ return { id: this.value.note, note: null, - faStickyNote }; }, diff --git a/src/client/pages/page-editor/els/page-editor.el.number-input.vue b/src/client/pages/page-editor/els/page-editor.el.number-input.vue index 76c35d4406fb15d4ec2e77ee678d6cc8ae8df228..8058d941c18731151a33295a5eb2aaf0778b080d 100644 --- a/src/client/pages/page-editor/els/page-editor.el.number-input.vue +++ b/src/client/pages/page-editor/els/page-editor.el.number-input.vue @@ -1,9 +1,9 @@ <template> <XContainer @remove="() => $emit('remove')" :draggable="true"> - <template #header><Fa :icon="faBolt"/> {{ $ts._pages.blocks.numberInput }}</template> + <template #header><i class="fas fa-bolt"></i> {{ $ts._pages.blocks.numberInput }}</template> <section style="padding: 0 16px 0 16px;"> - <MkInput v-model:value="value.name"><template #prefix><Fa :icon="faMagic"/></template><span>{{ $ts._pages.blocks._numberInput.name }}</span></MkInput> + <MkInput v-model:value="value.name"><template #prefix><i class="fas fa-magic"></i></template><span>{{ $ts._pages.blocks._numberInput.name }}</span></MkInput> <MkInput v-model:value="value.text"><span>{{ $ts._pages.blocks._numberInput.text }}</span></MkInput> <MkInput v-model:value="value.default" type="number"><span>{{ $ts._pages.blocks._numberInput.default }}</span></MkInput> </section> @@ -12,7 +12,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faBolt, faMagic } from '@fortawesome/free-solid-svg-icons'; import XContainer from '../page-editor.container.vue'; import MkInput from '@client/components/ui/input.vue'; import * as os from '@client/os'; @@ -30,7 +29,6 @@ export default defineComponent({ data() { return { - faBolt, faMagic }; }, diff --git a/src/client/pages/page-editor/els/page-editor.el.post.vue b/src/client/pages/page-editor/els/page-editor.el.post.vue index 51c5481d54ac0c854174b5800a2a5ab76ed43d50..1ed7f860c88aa1c2b2701ecfbd511bac9224fe03 100644 --- a/src/client/pages/page-editor/els/page-editor.el.post.vue +++ b/src/client/pages/page-editor/els/page-editor.el.post.vue @@ -1,6 +1,6 @@ <template> <XContainer @remove="() => $emit('remove')" :draggable="true"> - <template #header><Fa :icon="faPaperPlane"/> {{ $ts._pages.blocks.post }}</template> + <template #header><i class="fas fa-paper-plane"></i> {{ $ts._pages.blocks.post }}</template> <section style="padding: 16px;"> <MkTextarea v-model:value="value.text">{{ $ts._pages.blocks._post.text }}</MkTextarea> @@ -12,7 +12,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faPaperPlane } from '@fortawesome/free-regular-svg-icons'; import XContainer from '../page-editor.container.vue'; import MkTextarea from '@client/components/ui/textarea.vue'; import MkInput from '@client/components/ui/input.vue'; @@ -32,7 +31,6 @@ export default defineComponent({ data() { return { - faPaperPlane }; }, diff --git a/src/client/pages/page-editor/els/page-editor.el.radio-button.vue b/src/client/pages/page-editor/els/page-editor.el.radio-button.vue index 82b09a62901be83c52e667e7fab92d000d2ff814..97715ed69c591ec6d2524041afa079966b5d380c 100644 --- a/src/client/pages/page-editor/els/page-editor.el.radio-button.vue +++ b/src/client/pages/page-editor/els/page-editor.el.radio-button.vue @@ -1,9 +1,9 @@ <template> <XContainer @remove="() => $emit('remove')" :draggable="true"> - <template #header><Fa :icon="faBolt"/> {{ $ts._pages.blocks.radioButton }}</template> + <template #header><i class="fas fa-bolt"></i> {{ $ts._pages.blocks.radioButton }}</template> <section style="padding: 0 16px 16px 16px;"> - <MkInput v-model:value="value.name"><template #prefix><Fa :icon="faMagic"/></template><span>{{ $ts._pages.blocks._radioButton.name }}</span></MkInput> + <MkInput v-model:value="value.name"><template #prefix><i class="fas fa-magic"></i></template><span>{{ $ts._pages.blocks._radioButton.name }}</span></MkInput> <MkInput v-model:value="value.title"><span>{{ $ts._pages.blocks._radioButton.title }}</span></MkInput> <MkTextarea v-model:value="values"><span>{{ $ts._pages.blocks._radioButton.values }}</span></MkTextarea> <MkInput v-model:value="value.default"><span>{{ $ts._pages.blocks._radioButton.default }}</span></MkInput> @@ -13,7 +13,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faBolt, faMagic } from '@fortawesome/free-solid-svg-icons'; import XContainer from '../page-editor.container.vue'; import MkTextarea from '@client/components/ui/textarea.vue'; import MkInput from '@client/components/ui/input.vue'; @@ -31,7 +30,6 @@ export default defineComponent({ data() { return { values: '', - faBolt, faMagic }; }, watch: { diff --git a/src/client/pages/page-editor/els/page-editor.el.section.vue b/src/client/pages/page-editor/els/page-editor.el.section.vue index 96f468b13aa8e789cee5b28227c659402fd0502f..16ef2598f9ec18911a516a2a23f78d8d15913fb8 100644 --- a/src/client/pages/page-editor/els/page-editor.el.section.vue +++ b/src/client/pages/page-editor/els/page-editor.el.section.vue @@ -1,12 +1,12 @@ <template> <XContainer @remove="() => $emit('remove')" :draggable="true"> - <template #header><Fa :icon="faStickyNote"/> {{ value.title }}</template> + <template #header><i class="fas fa-sticky-note"></i> {{ value.title }}</template> <template #func> <button @click="rename()" class="_button"> - <Fa :icon="faPencilAlt"/> + <i class="fas fa-pencil-alt"></i> </button> <button @click="add()" class="_button"> - <Fa :icon="faPlus"/> + <i class="fas fa-plus"></i> </button> </template> @@ -19,8 +19,6 @@ <script lang="ts"> import { defineComponent, defineAsyncComponent } from 'vue'; import { v4 as uuid } from 'uuid'; -import { faPlus, faPencilAlt } from '@fortawesome/free-solid-svg-icons'; -import { faStickyNote } from '@fortawesome/free-regular-svg-icons'; import XContainer from '../page-editor.container.vue'; import * as os from '@client/os'; @@ -43,7 +41,6 @@ export default defineComponent({ data() { return { - faStickyNote, faPlus, faPencilAlt }; }, diff --git a/src/client/pages/page-editor/els/page-editor.el.switch.vue b/src/client/pages/page-editor/els/page-editor.el.switch.vue index 56b9f1561cbed15961e4e12b855808c830874377..564d5e22c34ce4feec8aabac4344c42a57dfde93 100644 --- a/src/client/pages/page-editor/els/page-editor.el.switch.vue +++ b/src/client/pages/page-editor/els/page-editor.el.switch.vue @@ -1,9 +1,9 @@ <template> <XContainer @remove="() => $emit('remove')" :draggable="true"> - <template #header><Fa :icon="faBolt"/> {{ $ts._pages.blocks.switch }}</template> + <template #header><i class="fas fa-bolt"></i> {{ $ts._pages.blocks.switch }}</template> <section class="kjuadyyj"> - <MkInput v-model:value="value.name"><template #prefix><Fa :icon="faMagic"/></template><span>{{ $ts._pages.blocks._switch.name }}</span></MkInput> + <MkInput v-model:value="value.name"><template #prefix><i class="fas fa-magic"></i></template><span>{{ $ts._pages.blocks._switch.name }}</span></MkInput> <MkInput v-model:value="value.text"><span>{{ $ts._pages.blocks._switch.text }}</span></MkInput> <MkSwitch v-model:value="value.default"><span>{{ $ts._pages.blocks._switch.default }}</span></MkSwitch> </section> @@ -12,7 +12,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faBolt, faMagic } from '@fortawesome/free-solid-svg-icons'; import XContainer from '../page-editor.container.vue'; import MkSwitch from '@client/components/ui/switch.vue'; import MkInput from '@client/components/ui/input.vue'; @@ -31,7 +30,6 @@ export default defineComponent({ data() { return { - faBolt, faMagic }; }, diff --git a/src/client/pages/page-editor/els/page-editor.el.text-input.vue b/src/client/pages/page-editor/els/page-editor.el.text-input.vue index cb8cb83aa71ac399c044beb1563a9fc5762f113e..4435d9b841ae1411e9ad9481687ff3b3dccc96db 100644 --- a/src/client/pages/page-editor/els/page-editor.el.text-input.vue +++ b/src/client/pages/page-editor/els/page-editor.el.text-input.vue @@ -1,9 +1,9 @@ <template> <XContainer @remove="() => $emit('remove')" :draggable="true"> - <template #header><Fa :icon="faBolt"/> {{ $ts._pages.blocks.textInput }}</template> + <template #header><i class="fas fa-bolt"></i> {{ $ts._pages.blocks.textInput }}</template> <section style="padding: 0 16px 0 16px;"> - <MkInput v-model:value="value.name"><template #prefix><Fa :icon="faMagic"/></template><span>{{ $ts._pages.blocks._textInput.name }}</span></MkInput> + <MkInput v-model:value="value.name"><template #prefix><i class="fas fa-magic"></i></template><span>{{ $ts._pages.blocks._textInput.name }}</span></MkInput> <MkInput v-model:value="value.text"><span>{{ $ts._pages.blocks._textInput.text }}</span></MkInput> <MkInput v-model:value="value.default" type="text"><span>{{ $ts._pages.blocks._textInput.default }}</span></MkInput> </section> @@ -12,7 +12,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faBolt, faMagic } from '@fortawesome/free-solid-svg-icons'; import XContainer from '../page-editor.container.vue'; import MkInput from '@client/components/ui/input.vue'; import * as os from '@client/os'; @@ -30,7 +29,6 @@ export default defineComponent({ data() { return { - faBolt, faMagic }; }, diff --git a/src/client/pages/page-editor/els/page-editor.el.text.vue b/src/client/pages/page-editor/els/page-editor.el.text.vue index bd2c9c46dc3ecbb36eb6f052bfbdaf5ed6b542f5..668dd5f52debe8d3c17f88021b496121e27a1a37 100644 --- a/src/client/pages/page-editor/els/page-editor.el.text.vue +++ b/src/client/pages/page-editor/els/page-editor.el.text.vue @@ -1,6 +1,6 @@ <template> <XContainer @remove="() => $emit('remove')" :draggable="true"> - <template #header><Fa :icon="faAlignLeft"/> {{ $ts._pages.blocks.text }}</template> + <template #header><i class="fas fa-align-left"></i> {{ $ts._pages.blocks.text }}</template> <section class="vckmsadr"> <textarea v-model="value.text"></textarea> @@ -10,7 +10,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faAlignLeft } from '@fortawesome/free-solid-svg-icons'; import XContainer from '../page-editor.container.vue'; import * as os from '@client/os'; @@ -27,7 +26,6 @@ export default defineComponent({ data() { return { - faAlignLeft, }; }, diff --git a/src/client/pages/page-editor/els/page-editor.el.textarea-input.vue b/src/client/pages/page-editor/els/page-editor.el.textarea-input.vue index 8c4ff234089ca633862c7e13ee5b6f11d4b11b15..cf3b9f93f4590eb34014596dfa065e147513d2bd 100644 --- a/src/client/pages/page-editor/els/page-editor.el.textarea-input.vue +++ b/src/client/pages/page-editor/els/page-editor.el.textarea-input.vue @@ -1,9 +1,9 @@ <template> <XContainer @remove="() => $emit('remove')" :draggable="true"> - <template #header><Fa :icon="faBolt"/> {{ $ts._pages.blocks.textareaInput }}</template> + <template #header><i class="fas fa-bolt"></i> {{ $ts._pages.blocks.textareaInput }}</template> <section style="padding: 0 16px 16px 16px;"> - <MkInput v-model:value="value.name"><template #prefix><Fa :icon="faMagic"/></template><span>{{ $ts._pages.blocks._textareaInput.name }}</span></MkInput> + <MkInput v-model:value="value.name"><template #prefix><i class="fas fa-magic"></i></template><span>{{ $ts._pages.blocks._textareaInput.name }}</span></MkInput> <MkInput v-model:value="value.text"><span>{{ $ts._pages.blocks._textareaInput.text }}</span></MkInput> <MkTextarea v-model:value="value.default"><span>{{ $ts._pages.blocks._textareaInput.default }}</span></MkTextarea> </section> @@ -12,7 +12,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faBolt, faMagic } from '@fortawesome/free-solid-svg-icons'; import XContainer from '../page-editor.container.vue'; import MkTextarea from '@client/components/ui/textarea.vue'; import MkInput from '@client/components/ui/input.vue'; @@ -31,7 +30,6 @@ export default defineComponent({ data() { return { - faBolt, faMagic }; }, diff --git a/src/client/pages/page-editor/els/page-editor.el.textarea.vue b/src/client/pages/page-editor/els/page-editor.el.textarea.vue index 042b2837315f315c32a0474c5715d049f7755d43..a29d5bd3f2665f763401cae0fc2669fb2de2ab03 100644 --- a/src/client/pages/page-editor/els/page-editor.el.textarea.vue +++ b/src/client/pages/page-editor/els/page-editor.el.textarea.vue @@ -1,6 +1,6 @@ <template> <XContainer @remove="() => $emit('remove')" :draggable="true"> - <template #header><Fa :icon="faAlignLeft"/> {{ $ts._pages.blocks.textarea }}</template> + <template #header><i class="fas fa-align-left"></i> {{ $ts._pages.blocks.textarea }}</template> <section class="ihymsbbe"> <textarea v-model="value.text"></textarea> @@ -10,7 +10,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faAlignLeft } from '@fortawesome/free-solid-svg-icons'; import XContainer from '../page-editor.container.vue'; import * as os from '@client/os'; @@ -27,7 +26,6 @@ export default defineComponent({ data() { return { - faAlignLeft, }; }, diff --git a/src/client/pages/page-editor/page-editor.container.vue b/src/client/pages/page-editor/page-editor.container.vue index 46e2dca1570fd5ac31f22939284ece8af319cd02..afd261fac7664a6f387755f5826b92c7b5f952d9 100644 --- a/src/client/pages/page-editor/page-editor.container.vue +++ b/src/client/pages/page-editor/page-editor.container.vue @@ -5,14 +5,14 @@ <div class="buttons"> <slot name="func"></slot> <button v-if="removable" @click="remove()" class="_button"> - <Fa :icon="faTrashAlt"/> + <i class="fas fa-trash-alt"></i> </button> <button v-if="draggable" class="drag-handle _button"> - <Fa :icon="faBars"/> + <i class="fas fa-bars"></i> </button> <button @click="toggleContent(!showBody)" 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> </div> </header> @@ -26,8 +26,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faBars, faAngleUp, faAngleDown } from '@fortawesome/free-solid-svg-icons'; -import { faTrashAlt } from '@fortawesome/free-regular-svg-icons'; export default defineComponent({ props: { @@ -56,7 +54,6 @@ export default defineComponent({ data() { return { showBody: this.expanded, - faTrashAlt, faBars, faAngleUp, faAngleDown }; }, methods: { @@ -105,7 +102,7 @@ export default defineComponent({ font-weight: bold; box-shadow: 0 1px rgba(#000, 0.07); - > [data-icon] { + > i { margin-right: 6px; } diff --git a/src/client/pages/page-editor/page-editor.script-block.vue b/src/client/pages/page-editor/page-editor.script-block.vue index 10d5311cde3858a8d3ff9458fd2bffdf90c6677c..65ac731e47fb67f74e20aad24839f55de35107ff 100644 --- a/src/client/pages/page-editor/page-editor.script-block.vue +++ b/src/client/pages/page-editor/page-editor.script-block.vue @@ -1,9 +1,9 @@ <template> <XContainer :removable="removable" @remove="() => $emit('remove')" :error="error" :warn="warn" :draggable="draggable"> - <template #header><Fa v-if="icon" :icon="icon"/> <template v-if="title">{{ title }} <span class="turmquns" v-if="typeText">({{ typeText }})</span></template><template v-else-if="typeText">{{ typeText }}</template></template> + <template #header><i v-if="icon" :class="icon"></i> <template v-if="title">{{ title }} <span class="turmquns" v-if="typeText">({{ typeText }})</span></template><template v-else-if="typeText">{{ typeText }}</template></template> <template #func> <button @click="changeType()" class="_button"> - <Fa :icon="faPencilAlt"/> + <i class="fas fa-pencil-alt"></i> </button> </template> @@ -57,7 +57,6 @@ <script lang="ts"> import { defineAsyncComponent, defineComponent } from 'vue'; -import { faPencilAlt, faPlug } from '@fortawesome/free-solid-svg-icons'; import { v4 as uuid } from 'uuid'; import XContainer from './page-editor.container.vue'; import MkTextarea from '@client/components/ui/textarea.vue'; @@ -109,14 +108,13 @@ export default defineComponent({ error: null, warn: null, slots: '', - faPencilAlt }; }, computed: { icon(): any { if (this.value.type === null) return null; - if (this.value.type.startsWith('fn:')) return faPlug; + if (this.value.type.startsWith('fn:')) return 'fas fa-plug'; return blockDefs.find(x => x.type === this.value.type).icon; }, typeText(): any { diff --git a/src/client/pages/page-editor/page-editor.vue b/src/client/pages/page-editor/page-editor.vue index 4583863a1c8e91462b05a773633a6ad1550c87ac..e96e1faaf2752b65b57f5b0b83965a676a94e6d0 100644 --- a/src/client/pages/page-editor/page-editor.vue +++ b/src/client/pages/page-editor/page-editor.vue @@ -1,15 +1,15 @@ <template> <div class="_root"> - <MkA class="view" v-if="pageId" :to="`/@${ author.username }/pages/${ currentName }`"><Fa :icon="faExternalLinkSquareAlt"/> {{ $ts._pages.viewPage }}</MkA> + <MkA class="view" v-if="pageId" :to="`/@${ author.username }/pages/${ currentName }`"><i class="fas fa-external-link-square-alt"></i> {{ $ts._pages.viewPage }}</MkA> <div class="buttons" style="margin: 16px;"> - <MkButton inline @click="save" primary class="save" v-if="!readonly"><Fa :icon="faSave"/> {{ $ts.save }}</MkButton> - <MkButton inline @click="duplicate" class="duplicate" v-if="pageId"><Fa :icon="faCopy"/> {{ $ts.duplicate }}</MkButton> - <MkButton inline @click="del" class="delete" v-if="pageId && !readonly"><Fa :icon="faTrashAlt"/> {{ $ts.delete }}</MkButton> + <MkButton inline @click="save" primary class="save" v-if="!readonly"><i class="fas fa-save"></i> {{ $ts.save }}</MkButton> + <MkButton inline @click="duplicate" class="duplicate" v-if="pageId"><i class="fas fa-copy"></i> {{ $ts.duplicate }}</MkButton> + <MkButton inline @click="del" class="delete" v-if="pageId && !readonly"><i class="fas fa-trash-alt"></i> {{ $ts.delete }}</MkButton> </div> <MkContainer :foldable="true" :expanded="true" class="_gap"> - <template #header><Fa :icon="faCog"/> {{ $ts._pages.pageSetting }}</template> + <template #header><i class="fas fa-cog"></i> {{ $ts._pages.pageSetting }}</template> <div style="padding: 16px;"> <MkInput v-model:value="title"> <span>{{ $ts._pages.title }}</span> @@ -35,26 +35,26 @@ <MkSwitch v-model:value="hideTitleWhenPinned">{{ $ts._pages.hideTitleWhenPinned }}</MkSwitch> <div class="eyeCatch"> - <MkButton v-if="eyeCatchingImageId == null && !readonly" @click="setEyeCatchingImage"><Fa :icon="faPlus"/> {{ $ts._pages.eyeCatchingImageSet }}</MkButton> + <MkButton v-if="eyeCatchingImageId == null && !readonly" @click="setEyeCatchingImage"><i class="fas fa-plus"></i> {{ $ts._pages.eyeCatchingImageSet }}</MkButton> <div v-else-if="eyeCatchingImage"> <img :src="eyeCatchingImage.url" :alt="eyeCatchingImage.name" style="max-width: 100%;"/> - <MkButton @click="removeEyeCatchingImage()" v-if="!readonly"><Fa :icon="faTrashAlt"/> {{ $ts._pages.eyeCatchingImageRemove }}</MkButton> + <MkButton @click="removeEyeCatchingImage()" v-if="!readonly"><i class="fas fa-trash-alt"></i> {{ $ts._pages.eyeCatchingImageRemove }}</MkButton> </div> </div> </div> </MkContainer> <MkContainer :foldable="true" :expanded="true" class="_gap"> - <template #header><Fa :icon="faStickyNote"/> {{ $ts._pages.contents }}</template> + <template #header><i class="fas fa-sticky-note"></i> {{ $ts._pages.contents }}</template> <div style="padding: 16px;"> <XBlocks class="content" v-model:value="content" :hpml="hpml"/> - <MkButton @click="add()" v-if="!readonly"><Fa :icon="faPlus"/></MkButton> + <MkButton @click="add()" v-if="!readonly"><i class="fas fa-plus"></i></MkButton> </div> </MkContainer> <MkContainer :foldable="true" class="_gap"> - <template #header><Fa :icon="faMagic"/> {{ $ts._pages.variables }}</template> + <template #header><i class="fas fa-magic"></i> {{ $ts._pages.variables }}</template> <div class="qmuvgica"> <XDraggable tag="div" class="variables" v-show="variables.length > 0" v-model="variables" item-key="name" handle=".drag-handle" :group="{ name: 'variables' }" animation="150" swap-threshold="0.5"> <template #item="{element}"> @@ -70,12 +70,12 @@ </template> </XDraggable> - <MkButton @click="addVariable()" class="add" v-if="!readonly"><Fa :icon="faPlus"/></MkButton> + <MkButton @click="addVariable()" class="add" v-if="!readonly"><i class="fas fa-plus"></i></MkButton> </div> </MkContainer> <MkContainer :foldable="true" :expanded="true" class="_gap"> - <template #header><Fa :icon="faCode"/> {{ $ts.script }}</template> + <template #header><i class="fas fa-code"></i> {{ $ts.script }}</template> <div> <MkTextarea class="_code" v-model:value="script"/> </div> @@ -91,8 +91,6 @@ import 'prismjs/components/prism-clike'; import 'prismjs/components/prism-javascript'; import 'prismjs/themes/prism-okaidia.css'; import 'vue-prism-editor/dist/prismeditor.min.css'; -import { faICursor, faPlus, faMagic, faCog, faCode, faExternalLinkSquareAlt, faPencilAlt, faCopy } from '@fortawesome/free-solid-svg-icons'; -import { faSave, faStickyNote, faTrashAlt } from '@fortawesome/free-regular-svg-icons'; import { v4 as uuid } from 'uuid'; import XVariable from './page-editor.script-block.vue'; import XBlocks from './page-editor.blocks.vue'; @@ -143,7 +141,7 @@ export default defineComponent({ } return { title: title, - icon: faPencilAlt, + icon: 'fas fa-pencil-alt', }; }), author: this.$i, @@ -164,7 +162,6 @@ export default defineComponent({ hpml: null, script: '', url, - faPlus, faICursor, faSave, faStickyNote, faMagic, faCog, faTrashAlt, faExternalLinkSquareAlt, faCode, faCopy }; }, @@ -471,7 +468,7 @@ export default defineComponent({ font-weight: bold; box-shadow: 0 1px rgba(#000, 0.07); - > [data-icon] { + > i { margin-right: 6px; } diff --git a/src/client/pages/page.vue b/src/client/pages/page.vue index d7b570e5f4ed86e2f74843252cb704d3ad516e99..f25ed511841f6aa406505a7de46b9901cc194556 100644 --- a/src/client/pages/page.vue +++ b/src/client/pages/page.vue @@ -14,8 +14,8 @@ <small style="display: block; opacity: 0.7; margin-top: 1em;">@{{ page.user.username }}</small> </div> <div class="like"> - <MkButton class="button" @click="unlike()" v-if="page.isLiked" v-tooltip="$ts._pages.unlike" primary><Fa :icon="faHeartS"/><span class="count" v-if="page.likedCount > 0">{{ page.likedCount }}</span></MkButton> - <MkButton class="button" @click="like()" v-else v-tooltip="$ts._pages.like"><Fa :icon="faHeartR"/><span class="count" v-if="page.likedCount > 0">{{ page.likedCount }}</span></MkButton> + <MkButton class="button" @click="unlike()" v-if="page.isLiked" v-tooltip="$ts._pages.unlike" primary><i class="fas fa-heart"></i><span class="count" v-if="page.likedCount > 0">{{ page.likedCount }}</span></MkButton> + <MkButton class="button" @click="like()" v-else v-tooltip="$ts._pages.like"><i class="far fa-heart"></i><span class="count" v-if="page.likedCount > 0">{{ page.likedCount }}</span></MkButton> </div> <div class="links"> <MkA :to="`/@${username}/pages/${pageName}/view-source`" class="link">{{ $ts._pages.viewSource }}</MkA> @@ -27,16 +27,14 @@ </div> </div> <div class="footer"> - <div><Fa :icon="faClock"/> {{ $ts.createdAt }}: <MkTime :time="page.createdAt" mode="detail"/></div> - <div v-if="page.createdAt != page.updatedAt"><Fa :icon="faClock"/> {{ $ts.updatedAt }}: <MkTime :time="page.updatedAt" mode="detail"/></div> + <div><i class="far fa-clock"></i> {{ $ts.createdAt }}: <MkTime :time="page.createdAt" mode="detail"/></div> + <div v-if="page.createdAt != page.updatedAt"><i class="far fa-clock"></i> {{ $ts.updatedAt }}: <MkTime :time="page.updatedAt" mode="detail"/></div> </div> </div> </template> <script lang="ts"> import { computed, defineComponent } from 'vue'; -import { faHeart as faHeartS } from '@fortawesome/free-solid-svg-icons'; -import { faHeart as faHeartR, faClock } from '@fortawesome/free-regular-svg-icons'; import XPage from '@client/components/page/page.vue'; import MkButton from '@client/components/ui/button.vue'; import * as os from '@client/os'; @@ -71,7 +69,6 @@ export default defineComponent({ }, } : null), page: null, - faHeartS, faHeartR, faClock, }; }, diff --git a/src/client/pages/pages.vue b/src/client/pages/pages.vue index 8aea7e6b95346249499e2f9788b4cb4d6f9e46ce..52a860be13a5e414a350017019fce7c5389b6625 100644 --- a/src/client/pages/pages.vue +++ b/src/client/pages/pages.vue @@ -1,9 +1,9 @@ <template> <div> <MkTab v-model:value="tab" v-if="$i"> - <option value="featured"><Fa :icon="faFireAlt"/> {{ $ts._pages.featured }}</option> - <option value="my"><Fa :icon="faEdit"/> {{ $ts._pages.my }}</option> - <option value="liked"><Fa :icon="faHeart"/> {{ $ts._pages.liked }}</option> + <option value="featured"><i class="fas fa-fire-alt"></i> {{ $ts._pages.featured }}</option> + <option value="my"><i class="fas fa-edit"></i> {{ $ts._pages.my }}</option> + <option value="liked"><i class="fas fa-heart"></i> {{ $ts._pages.liked }}</option> </MkTab> <div class="_section"> @@ -14,7 +14,7 @@ </div> <div class="rknalgpo _content my" v-if="tab === 'my'"> - <MkButton class="new" @click="create()"><Fa :icon="faPlus"/></MkButton> + <MkButton class="new" @click="create()"><i class="fas fa-plus"></i></MkButton> <MkPagination :pagination="myPagesPagination" #default="{items}"> <MkPagePreview v-for="page in items" class="ckltabjg" :page="page" :key="page.id"/> </MkPagination> @@ -31,8 +31,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faPlus, faEdit, faFireAlt } from '@fortawesome/free-solid-svg-icons'; -import { faStickyNote, faHeart } from '@fortawesome/free-regular-svg-icons'; import MkPagePreview from '@client/components/page-preview.vue'; import MkPagination from '@client/components/ui/pagination.vue'; import MkButton from '@client/components/ui/button.vue'; @@ -47,9 +45,9 @@ export default defineComponent({ return { [symbols.PAGE_INFO]: { title: this.$ts.pages, - icon: faStickyNote, + icon: 'fas fa-sticky-note', actions: [{ - icon: faPlus, + icon: 'fas fa-plus', text: this.$ts.create, handler: this.create }] @@ -67,7 +65,6 @@ export default defineComponent({ endpoint: 'i/page-likes', limit: 5, }, - faStickyNote, faPlus, faEdit, faHeart, faFireAlt }; }, methods: { diff --git a/src/client/pages/preview.vue b/src/client/pages/preview.vue index bd4e08db62907456cc43df9d55ce44619bc3eb86..3df446e67696f9f109c93b9aa97918753d81fd71 100644 --- a/src/client/pages/preview.vue +++ b/src/client/pages/preview.vue @@ -6,7 +6,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faEye } from '@fortawesome/free-solid-svg-icons'; import MkSample from '@client/components/sample.vue'; import * as symbols from '@client/symbols'; @@ -19,7 +18,7 @@ export default defineComponent({ return { [symbols.PAGE_INFO]: { title: this.$ts.preview, - icon: faEye, + icon: 'fas fa-eye', }, } }, diff --git a/src/client/pages/reversi/game.board.vue b/src/client/pages/reversi/game.board.vue index a466527c012e6280a930ae16037e4db63f08ee3d..78bcf0341352cd94dcd853396e59d365760670e3 100644 --- a/src/client/pages/reversi/game.board.vue +++ b/src/client/pages/reversi/game.board.vue @@ -40,8 +40,8 @@ <img v-if="stone === false" :src="whiteUser.avatarUrl" alt="white"> </template> <template v-else> - <fa v-if="stone === true" :icon="fasCircle"/> - <fa v-if="stone === false" :icon="farCircle"/> + <i v-if="stone === true" class="fas fa-circle"></i> + <i v-if="stone === false" class="far fa-circle"></i> </template> </div> </div> @@ -63,12 +63,12 @@ <div class="player" v-if="game.isEnded"> <span>{{ logPos }} / {{ logs.length }}</span> <div class="buttons" v-if="!autoplaying"> - <MkButton inline @click="logPos = 0" :disabled="logPos == 0"><fa :icon="faAngleDoubleLeft"/></MkButton> - <MkButton inline @click="logPos--" :disabled="logPos == 0"><fa :icon="faAngleLeft"/></MkButton> - <MkButton inline @click="logPos++" :disabled="logPos == logs.length"><fa :icon="faAngleRight"/></MkButton> - <MkButton inline @click="logPos = logs.length" :disabled="logPos == logs.length"><fa :icon="faAngleDoubleRight"/></MkButton> + <MkButton inline @click="logPos = 0" :disabled="logPos == 0"><i class="fas fa-angle-double-left"></i></MkButton> + <MkButton inline @click="logPos--" :disabled="logPos == 0"><i class="fas fa-angle-left"></i></MkButton> + <MkButton inline @click="logPos++" :disabled="logPos == logs.length"><i class="fas fa-angle-right"></i></MkButton> + <MkButton inline @click="logPos = logs.length" :disabled="logPos == logs.length"><i class="fas fa-angle-double-right"></i></MkButton> </div> - <MkButton @click="autoplay()" :disabled="autoplaying" style="margin: var(--margin) auto 0 auto;"><fa :icon="faPlay"/></MkButton> + <MkButton @click="autoplay()" :disabled="autoplaying" style="margin: var(--margin) auto 0 auto;"><i class="fas fa-play"></i></MkButton> </div> <div class="info"> @@ -85,9 +85,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faAngleDoubleLeft, faAngleLeft, faAngleRight, faAngleDoubleRight, faPlay } from '@fortawesome/free-solid-svg-icons'; -import { faCircle as fasCircle } from '@fortawesome/free-solid-svg-icons'; -import { faCircle as farCircle } from '@fortawesome/free-regular-svg-icons'; import * as CRC32 from 'crc-32'; import Reversi, { Color } from '../../../games/reversi/core'; import { url } from '@client/config'; @@ -120,7 +117,6 @@ export default defineComponent({ logPos: 0, watchers: [], pollingClock: null, - faAngleDoubleLeft, faAngleLeft, faAngleRight, faAngleDoubleRight, fasCircle, farCircle, faPlay }; }, diff --git a/src/client/pages/reversi/game.setting.vue b/src/client/pages/reversi/game.setting.vue index c7c2937ba838d1beb8621832d94218c96013bf24..1a2abba79527c3c3329c1ee5404c950078093b16 100644 --- a/src/client/pages/reversi/game.setting.vue +++ b/src/client/pages/reversi/game.setting.vue @@ -17,11 +17,11 @@ </header> <div> - <div class="random" v-if="game.map == null"><fa icon="dice"/></div> + <div class="random" v-if="game.map == null"><i class="fas fa-dice"></i></div> <div class="board" v-else :style="{ 'grid-template-rows': `repeat(${ game.map.length }, 1fr)`, 'grid-template-columns': `repeat(${ game.map[0].length }, 1fr)` }"> <div v-for="(x, i) in game.map.join('')" :class="{ none: x == ' ' }" @click="onPixelClick(i, x)"> - <fa v-if="x == 'b'" :icon="fasCircle"/> - <fa v-if="x == 'w'" :icon="farCircle"/> + <i v-if="x === 'b'" class="fas fa-circle"></i> + <i v-if="x === 'w'" class="far fa-circle"></i> </div> </div> </div> @@ -125,8 +125,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faCircle as fasCircle } from '@fortawesome/free-solid-svg-icons'; -import { faCircle as farCircle } from '@fortawesome/free-regular-svg-icons'; import * as maps from '../../../games/reversi/maps'; import MkButton from '@client/components/ui/button.vue'; import MkSwitch from '@client/components/ui/switch.vue'; diff --git a/src/client/pages/reversi/game.vue b/src/client/pages/reversi/game.vue index 896dbc39cc7c97a6c08a1a41e4985b9eaebe056e..62c99d775531fb1860e12f4214d48b445d016deb 100644 --- a/src/client/pages/reversi/game.vue +++ b/src/client/pages/reversi/game.vue @@ -9,7 +9,6 @@ import { defineComponent } from 'vue'; import GameSetting from './game.setting.vue'; import GameBoard from './game.board.vue'; import * as os from '@client/os'; -import { faGamepad } from '@fortawesome/free-solid-svg-icons'; import * as symbols from '@client/symbols'; export default defineComponent({ @@ -29,7 +28,7 @@ export default defineComponent({ return { [symbols.PAGE_INFO]: { title: this.$ts._reversi.reversi, - icon: faGamepad + icon: 'fas fa-gamepad' }, game: null, connection: null, diff --git a/src/client/pages/reversi/index.vue b/src/client/pages/reversi/index.vue index 59b228f5f6713548094dbada6d33a6edf9a2f8df..37126fca10013c3a8bfc7d90ab843579a9900d11 100644 --- a/src/client/pages/reversi/index.vue +++ b/src/client/pages/reversi/index.vue @@ -64,7 +64,6 @@ import { defineComponent } from 'vue'; import * as os from '@client/os'; import MkButton from '@client/components/ui/button.vue'; import MkFolder from '@client/components/ui/folder.vue'; -import { faGamepad } from '@fortawesome/free-solid-svg-icons'; import * as symbols from '@client/symbols'; export default defineComponent({ @@ -78,7 +77,7 @@ export default defineComponent({ return { [symbols.PAGE_INFO]: { title: this.$ts._reversi.reversi, - icon: faGamepad + icon: 'fas fa-gamepad' }, games: [], gamesFetching: true, diff --git a/src/client/pages/room/room.vue b/src/client/pages/room/room.vue index e1de52b8f1fa2854d7cf554f4d2ed203dcaeb8ce..ea34ef11b5bd49ca6a8b93fd507baeaaab1f948c 100644 --- a/src/client/pages/room/room.vue +++ b/src/client/pages/room/room.vue @@ -17,18 +17,18 @@ </template> </div> <div class="_content"> - <MkButton inline @click="translate()" :primary="isTranslateMode"><Fa :icon="faArrowsAlt"/> {{ $ts._rooms.translate }}</MkButton> - <MkButton inline @click="rotate()" :primary="isRotateMode"><Fa :icon="faUndo"/> {{ $ts._rooms.rotate }}</MkButton> - <MkButton inline v-if="isTranslateMode || isRotateMode" @click="exit()"><Fa :icon="faBan"/> {{ $ts._rooms.exit }}</MkButton> + <MkButton inline @click="translate()" :primary="isTranslateMode"><i class="fas fa-arrows-alt"></i> {{ $ts._rooms.translate }}</MkButton> + <MkButton inline @click="rotate()" :primary="isRotateMode"><i class="fas fa-undo"></i> {{ $ts._rooms.rotate }}</MkButton> + <MkButton inline v-if="isTranslateMode || isRotateMode" @click="exit()"><i class="fas fa-ban"></i> {{ $ts._rooms.exit }}</MkButton> </div> <div class="_content"> - <MkButton @click="remove()"><Fa :icon="faTrashAlt"/> {{ $ts._rooms.remove }}</MkButton> + <MkButton @click="remove()"><i class="fas fa-trash-alt"></i> {{ $ts._rooms.remove }}</MkButton> </div> </div> <div class="menu _section" v-if="isMyRoom"> <div class="_content"> - <MkButton @click="add()"><Fa :icon="faBoxOpen"/> {{ $ts._rooms.addFurniture }}</MkButton> + <MkButton @click="add()"><i class="fas fa-box-open"></i> {{ $ts._rooms.addFurniture }}</MkButton> </div> <div class="_content"> <MkSelect :value="roomType" @update:value="updateRoomType($event)"> @@ -42,8 +42,8 @@ </label> </div> <div class="_content"> - <MkButton inline :disabled="!changed" primary @click="save()"><Fa :icon="faSave"/> {{ $ts.save }}</MkButton> - <MkButton inline @click="clear()"><Fa :icon="faBroom"/> {{ $ts._rooms.clear }}</MkButton> + <MkButton inline :disabled="!changed" primary @click="save()"><i class="fas fa-save"></i> {{ $ts.save }}</MkButton> + <MkButton inline @click="clear()"><i class="fas fa-broom"></i> {{ $ts._rooms.clear }}</MkButton> </div> </div> </div> @@ -55,8 +55,6 @@ import { Room } from '@client/scripts/room/room'; import parseAcct from '@/misc/acct/parse'; import XPreview from './preview.vue'; const storeItems = require('@client/scripts/room/furnitures.json5'); -import { faBoxOpen, faUndo, faArrowsAlt, faBan, faBroom } from '@fortawesome/free-solid-svg-icons'; -import { faSave, faTrashAlt } from '@fortawesome/free-regular-svg-icons'; import { query as urlQuery } from '../../../prelude/url'; import MkButton from '@client/components/ui/button.vue'; import MkSelect from '@client/components/ui/select.vue'; @@ -98,7 +96,6 @@ export default defineComponent({ isRotateMode: false, isMyRoom: false, changed: false, - faBoxOpen, faSave, faTrashAlt, faUndo, faArrowsAlt, faBan, faBroom, }; }, diff --git a/src/client/pages/scratchpad.vue b/src/client/pages/scratchpad.vue index 1a863e6b2ecccd5b84bc7099ca2cc7c28018d49b..99164ec51fcd82e2157f2e8f97f50daa9a95caf4 100644 --- a/src/client/pages/scratchpad.vue +++ b/src/client/pages/scratchpad.vue @@ -2,11 +2,11 @@ <div class="iltifgqe"> <div class="editor _panel _gap"> <PrismEditor class="_code code" v-model="code" :highlight="highlighter" :line-numbers="false"/> - <MkButton style="position: absolute; top: 8px; right: 8px;" @click="run()" primary><Fa :icon="faPlay"/></MkButton> + <MkButton style="position: absolute; top: 8px; right: 8px;" @click="run()" primary><i class="fas fa-play"></i></MkButton> </div> <MkContainer :foldable="true" class="_gap"> - <template #header><Fa fixed-width/>{{ $ts.output }}</template> + <template #header>{{ $ts.output }}</template> <div class="bepmlvbi"> <div v-for="log in logs" class="log" :key="log.id" :class="{ print: log.print }">{{ log.text }}</div> </div> @@ -20,7 +20,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faTerminal, faPlay } from '@fortawesome/free-solid-svg-icons'; import 'prismjs'; import { highlight, languages } from 'prismjs/components/prism-core'; import 'prismjs/components/prism-clike'; @@ -46,11 +45,10 @@ export default defineComponent({ return { [symbols.PAGE_INFO]: { title: this.$ts.scratchpad, - icon: faTerminal, + icon: 'fas fa-terminal', }, code: '', logs: [], - faTerminal, faPlay } }, diff --git a/src/client/pages/search.vue b/src/client/pages/search.vue index b670714730f288c838945e1dbddab0ba054c74c3..bf228576be9aedefedcc983381df5cabf995812e 100644 --- a/src/client/pages/search.vue +++ b/src/client/pages/search.vue @@ -8,7 +8,6 @@ <script lang="ts"> import { computed, defineComponent } from 'vue'; -import { faSearch } 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'; @@ -22,7 +21,7 @@ export default defineComponent({ return { [symbols.PAGE_INFO]: { title: computed(() => this.$t('searchWith', { q: this.$route.query.q })), - icon: faSearch + icon: 'fas fa-search' }, pagination: { endpoint: 'notes/search', diff --git a/src/client/pages/settings/2fa.vue b/src/client/pages/settings/2fa.vue index 361611bcb242282080d705a02d29e1f808152330..aa14f91d711df7a6546ea2f19867c77abeea3ef0 100644 --- a/src/client/pages/settings/2fa.vue +++ b/src/client/pages/settings/2fa.vue @@ -1,6 +1,6 @@ <template> <section class="_card"> - <div class="_title"><Fa :icon="faLock"/> {{ $ts.twoStepAuthentication }}</div> + <div class="_title"><i class="fas fa-lock"></i> {{ $ts.twoStepAuthentication }}</div> <div class="_content"> <MkButton v-if="!data && !$i.twoFactorEnabled" @click="register">{{ $ts._2fa.registerDevice }}</MkButton> <template v-if="$i.twoFactorEnabled"> @@ -28,7 +28,7 @@ <ol v-if="registration && !registration.error"> <li v-if="registration.stage >= 0"> {{ $ts.tapSecurityKey }} - <Fa icon="spinner" pulse fixed-width v-if="registration.saving && registration.stage == 0" /> + <i v-if="registration.saving && registration.stage == 0" class="fas fa-spinner fa-pulse fa-fw"></i> </li> <li v-if="registration.stage >= 1"> <MkForm :disabled="registration.stage != 1 || registration.saving"> @@ -36,7 +36,7 @@ <span>{{ $ts.securityKeyName }}</span> </MkInput> <MkButton @click="registerKey" :disabled="keyName.length == 0">{{ $ts.registerSecurityKey }}</MkButton> - <Fa icon="spinner" pulse fixed-width v-if="registration.saving && registration.stage == 1" /> + <i v-if="registration.saving && registration.stage == 1" class="fas fa-spinner fa-pulse fa-fw"></i> </MkForm> </li> </ol> @@ -68,7 +68,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faLock } from '@fortawesome/free-solid-svg-icons'; import { hostname } from '@client/config'; import { byteify, hexify, stringify } from '@client/scripts/2fa'; import MkButton from '@client/components/ui/button.vue'; @@ -93,7 +92,7 @@ export default defineComponent({ return { [symbols.PAGE_INFO]: { title: this.$ts.twoStepAuthentication, - icon: faLock + icon: 'fas fa-lock' }, data: null, supportsCredentials: !!navigator.credentials, @@ -101,7 +100,6 @@ export default defineComponent({ registration: null, keyName: '', token: null, - faLock }; }, diff --git a/src/client/pages/settings/account-info.vue b/src/client/pages/settings/account-info.vue index 955a0f7845bc07a725142c45c3a879e8e3654bbe..4d851b7b1278da050b0f8968457b6529d9b5237d 100644 --- a/src/client/pages/settings/account-info.vue +++ b/src/client/pages/settings/account-info.vue @@ -132,7 +132,6 @@ <script lang="ts"> import { defineAsyncComponent, defineComponent } from 'vue'; -import { faInfoCircle } from '@fortawesome/free-solid-svg-icons'; import FormSwitch from '@client/components/form/switch.vue'; import FormSelect from '@client/components/form/select.vue'; import FormLink from '@client/components/form/link.vue'; @@ -162,7 +161,7 @@ export default defineComponent({ return { [symbols.PAGE_INFO]: { title: this.$ts.accountInfo, - icon: faInfoCircle + icon: 'fas fa-info-circle' }, stats: null } diff --git a/src/client/pages/settings/accounts.vue b/src/client/pages/settings/accounts.vue new file mode 100644 index 0000000000000000000000000000000000000000..a3fa0d4eb0784decf464f95ac5397359b58ee393 --- /dev/null +++ b/src/client/pages/settings/accounts.vue @@ -0,0 +1,148 @@ +<template> +<FormBase> + <FormSuspense :p="init"> + <FormButton @click="addAccount" primary><i class="fas fa-plus"></i> {{ $ts.addAccount }}</FormButton> + + <div class="_formItem _button" v-for="account in accounts" :key="account.id" @click="menu(account, $event)"> + <div class="_formPanel lcjjdxlm"> + <div class="avatar"> + <MkAvatar :user="account" class="avatar"/> + </div> + <div class="body"> + <div class="name"> + <MkUserName :user="account"/> + </div> + <div class="acct"> + <MkAcct :user="account"/> + </div> + </div> + </div> + </div> + </FormSuspense> +</FormBase> +</template> + +<script lang="ts"> +import { defineComponent } from 'vue'; +import FormSuspense from '@client/components/form/suspense.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 FormButton from '@client/components/form/button.vue'; +import * as os from '@client/os'; +import * as symbols from '@client/symbols'; +import { getAccounts, addAccount, login } from '@client/account'; + +export default defineComponent({ + components: { + FormBase, + FormSuspense, + FormButton, + }, + + emits: ['info'], + + data() { + return { + [symbols.PAGE_INFO]: { + title: this.$ts.accounts, + icon: 'fas fa-users', + }, + storedAccounts: getAccounts().filter(x => x.id !== this.$i.id), + accounts: null, + init: () => os.api('users/show', { + userIds: this.storedAccounts.map(x => x.id) + }).then(accounts => { + this.accounts = accounts; + }), + }; + }, + + mounted() { + this.$emit('info', this[symbols.PAGE_INFO]); + }, + + methods: { + menu(account, ev) { + os.modalMenu([{ + text: this.$ts.switch, + icon: 'fas fa-exchange-alt', + action: () => this.switchAccount(account), + }, { + text: this.$ts.remove, + icon: 'fas fa-trash-alt', + danger: true, + action: () => this.removeAccount(account), + }], ev.currentTarget || ev.target); + }, + + addAccount(ev) { + os.modalMenu([{ + text: this.$ts.existingAccount, + action: () => { this.addExistingAccount(); }, + }, { + text: this.$ts.createAccount, + action: () => { this.createAccount(); }, + }], ev.currentTarget || ev.target); + }, + + addExistingAccount() { + os.popup(import('@client/components/signin-dialog.vue'), {}, { + done: res => { + addAccount(res.id, res.i); + os.success(); + }, + }, 'closed'); + }, + + createAccount() { + os.popup(import('@client/components/signup-dialog.vue'), {}, { + done: res => { + addAccount(res.id, res.i); + this.switchAccountWithToken(res.i); + }, + }, 'closed'); + }, + + switchAccount(account: any) { + const storedAccounts = getAccounts(); + const token = storedAccounts.find(x => x.id === account.id).token; + this.switchAccountWithToken(token); + }, + + switchAccountWithToken(token: string) { + login(token); + }, + } +}); +</script> + +<style lang="scss" scoped> +.lcjjdxlm { + display: flex; + padding: 16px; + + > .avatar { + display: block; + flex-shrink: 0; + margin: 0 12px 0 0; + + > .avatar { + width: 50px; + height: 50px; + } + } + + > .body { + display: flex; + flex-direction: column; + justify-content: center; + width: calc(100% - 62px); + position: relative; + + > .name { + font-weight: bold; + } + } +} +</style> diff --git a/src/client/pages/settings/api.vue b/src/client/pages/settings/api.vue index 9b5339987041a1f1016e250ce72e5ef928d857f7..396d4405c3c12d97835441128c057cab28b6ac8c 100644 --- a/src/client/pages/settings/api.vue +++ b/src/client/pages/settings/api.vue @@ -8,7 +8,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faKey } from '@fortawesome/free-solid-svg-icons'; import FormSwitch from '@client/components/form/switch.vue'; import FormSelect from '@client/components/form/select.vue'; import FormLink from '@client/components/form/link.vue'; @@ -31,7 +30,7 @@ export default defineComponent({ return { [symbols.PAGE_INFO]: { title: 'API', - icon: faKey + icon: 'fas fa-key' }, isDesktop: window.innerWidth >= 1100, }; diff --git a/src/client/pages/settings/apps.vue b/src/client/pages/settings/apps.vue index 82bf9b7f8f4a97ece00eb18f46fdca8a9f5b6a5f..c864920ce1b047d91fb42349b8a33d00126597e9 100644 --- a/src/client/pages/settings/apps.vue +++ b/src/client/pages/settings/apps.vue @@ -22,7 +22,7 @@ <div><MkTime :time="token.lastUsedAt"/></div> </div> <div class="actions"> - <button class="_button" @click="revoke(token)"><Fa :icon="faTrashAlt"/></button> + <button class="_button" @click="revoke(token)"><i class="fas fa-trash-alt"></i></button> </div> <details> <summary>{{ $ts.details }}</summary> @@ -39,7 +39,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faTrashAlt, faPlug } from '@fortawesome/free-solid-svg-icons'; import FormPagination from '@client/components/form/pagination.vue'; import FormSelect from '@client/components/form/select.vue'; import FormLink from '@client/components/form/link.vue'; @@ -61,7 +60,7 @@ export default defineComponent({ return { [symbols.PAGE_INFO]: { title: this.$ts.installedApps, - icon: faPlug, + icon: 'fas fa-plug', }, pagination: { endpoint: 'i/apps', @@ -70,7 +69,6 @@ export default defineComponent({ sort: '+lastUsedAt' } }, - faTrashAlt, faPlug }; }, diff --git a/src/client/pages/settings/deck.vue b/src/client/pages/settings/deck.vue index 84992adc09e437a80436cddcd569c7b635f988f4..05f3061ca1bebf7a14b34bf04bb651b1998c982b 100644 --- a/src/client/pages/settings/deck.vue +++ b/src/client/pages/settings/deck.vue @@ -31,7 +31,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faImage, faCog, faColumns } from '@fortawesome/free-solid-svg-icons'; import FormSwitch from '@client/components/form/switch.vue'; import FormLink from '@client/components/form/link.vue'; import FormRadios from '@client/components/form/radios.vue'; @@ -59,9 +58,8 @@ export default defineComponent({ return { [symbols.PAGE_INFO]: { title: this.$ts.deck, - icon: faColumns + icon: 'fas fa-columns' }, - faImage, faCog, } }, diff --git a/src/client/pages/settings/drive.vue b/src/client/pages/settings/drive.vue index 675b025ab88f7beccf4f791951c0880df83367d3..3da2a21dc7aaffd4fecdc3945f93a30a762b772f 100644 --- a/src/client/pages/settings/drive.vue +++ b/src/client/pages/settings/drive.vue @@ -27,7 +27,7 @@ <FormButton :center="false" @click="chooseUploadFolder()" primary> {{ $ts.uploadFolder }} <template #suffix>{{ uploadFolder ? uploadFolder.name : '-' }}</template> - <template #suffixIcon><Fa :icon="faFolderOpen"/></template> + <template #suffixIcon><i class="fas fa-folder-open"></i></template> </FormButton> </FormBase> </template> @@ -36,8 +36,6 @@ import { defineComponent } from 'vue'; import * as tinycolor from 'tinycolor2'; import ApexCharts from 'apexcharts'; -import { faCloud, faFolderOpen } from '@fortawesome/free-solid-svg-icons'; -import { faClock, faEyeSlash, faTrashAlt } from '@fortawesome/free-regular-svg-icons'; import FormButton from '@client/components/form/button.vue'; import FormGroup from '@client/components/form/group.vue'; import FormKeyValueView from '@client/components/form/key-value-view.vue'; @@ -60,13 +58,12 @@ export default defineComponent({ return { [symbols.PAGE_INFO]: { title: this.$ts.drive, - icon: faCloud + icon: 'fas fa-cloud' }, fetching: true, usage: null, capacity: null, uploadFolder: null, - faCloud, faClock, faEyeSlash, faFolderOpen, faTrashAlt } }, diff --git a/src/client/pages/settings/email-address.vue b/src/client/pages/settings/email-address.vue index 97c5d396ceefdf52846502ce60c396c2b5c20af8..28eeeb6b73f679b848c51fdfd7af58b19451feda 100644 --- a/src/client/pages/settings/email-address.vue +++ b/src/client/pages/settings/email-address.vue @@ -13,8 +13,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faCog } from '@fortawesome/free-solid-svg-icons'; -import { faBell, faEnvelope } from '@fortawesome/free-regular-svg-icons'; import FormButton from '@client/components/form/button.vue'; import FormInput from '@client/components/form/input.vue'; import FormBase from '@client/components/form/base.vue'; @@ -36,11 +34,10 @@ export default defineComponent({ return { [symbols.PAGE_INFO]: { title: this.$ts.emailAddress, - icon: faEnvelope + icon: 'fas fa-envelope' }, emailAddress: null, code: null, - faCog } }, diff --git a/src/client/pages/settings/email-notification.vue b/src/client/pages/settings/email-notification.vue index cc28bac4b08af8f2298002fa4f1ced52e94b2f60..ac3402568a75a85c0bb6fc1ada659b3557eaa5ef 100644 --- a/src/client/pages/settings/email-notification.vue +++ b/src/client/pages/settings/email-notification.vue @@ -25,8 +25,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faCog } from '@fortawesome/free-solid-svg-icons'; -import { faBell, faEnvelope } from '@fortawesome/free-regular-svg-icons'; import FormButton from '@client/components/form/button.vue'; import FormSwitch from '@client/components/form/switch.vue'; import FormBase from '@client/components/form/base.vue'; @@ -49,7 +47,7 @@ export default defineComponent({ return { [symbols.PAGE_INFO]: { title: this.$ts.emailNotification, - icon: faEnvelope + icon: 'fas fa-envelope' }, mention: this.$i.emailNotificationTypes.includes('mention'), diff --git a/src/client/pages/settings/email.vue b/src/client/pages/settings/email.vue index 04f433f9ae31fea526daaa636a0c15e2c92f2d34..aa20d9d94e639ffedb18d99f4986be5743a1393a 100644 --- a/src/client/pages/settings/email.vue +++ b/src/client/pages/settings/email.vue @@ -3,14 +3,14 @@ <FormGroup> <template #label>{{ $ts.emailAddress }}</template> <FormLink to="/settings/email/address"> - <template v-if="$i.email && !$i.emailVerified" #icon><Fa :icon="faExclamationTriangle" style="color: var(--warn);"/></template> - <template v-else-if="$i.email && $i.emailVerified" #icon><Fa :icon="faCheck" style="color: var(--success);"/></template> + <template v-if="$i.email && !$i.emailVerified" #icon><i class="fas fa-exclamation-triangle" style="color: var(--warn);"></i></template> + <template v-else-if="$i.email && $i.emailVerified" #icon><i class="fas fa-check" style="color: var(--success);"></i></template> {{ $i.email || $ts.notSet }} </FormLink> </FormGroup> <FormLink to="/settings/email/notification"> - <template #icon><Fa :icon="faBell"/></template> + <template #icon><i class="fas fa-bell"></i></template> {{ $ts.emailNotification }} </FormLink> @@ -22,8 +22,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faCog, faExclamationTriangle, faCheck } from '@fortawesome/free-solid-svg-icons'; -import { faBell, faEnvelope } from '@fortawesome/free-regular-svg-icons'; import FormButton from '@client/components/form/button.vue'; import FormLink from '@client/components/form/link.vue'; import FormBase from '@client/components/form/base.vue'; @@ -47,9 +45,8 @@ export default defineComponent({ return { [symbols.PAGE_INFO]: { title: this.$ts.email, - icon: faEnvelope + icon: 'fas fa-envelope' }, - faCog, faExclamationTriangle, faCheck, faBell } }, diff --git a/src/client/pages/settings/experimental-features.vue b/src/client/pages/settings/experimental-features.vue index 25453b7e105b2eb66356d093e7fa5efc906832c9..f8d5e419e94610d3d88ef3acb6b30505619606f0 100644 --- a/src/client/pages/settings/experimental-features.vue +++ b/src/client/pages/settings/experimental-features.vue @@ -6,7 +6,6 @@ <script lang="ts"> import { defineAsyncComponent, defineComponent } from 'vue'; -import { faFlask } from '@fortawesome/free-solid-svg-icons'; import FormSwitch from '@client/components/form/switch.vue'; import FormSelect from '@client/components/form/select.vue'; import FormLink from '@client/components/form/link.vue'; @@ -34,7 +33,7 @@ export default defineComponent({ return { [symbols.PAGE_INFO]: { title: this.$ts.experimentalFeatures, - icon: faFlask + icon: 'fas fa-flask' }, stats: null } diff --git a/src/client/pages/settings/general.vue b/src/client/pages/settings/general.vue index 2963ddf432b520f748f439808cf352df31c6031b..fdbae0b8a1792c272e47f01f888a9df940531cf3 100644 --- a/src/client/pages/settings/general.vue +++ b/src/client/pages/settings/general.vue @@ -83,7 +83,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faImage, faCog, faColumns, faCogs } from '@fortawesome/free-solid-svg-icons'; import FormSwitch from '@client/components/form/switch.vue'; import FormSelect from '@client/components/form/select.vue'; import FormRadios from '@client/components/form/radios.vue'; @@ -117,13 +116,12 @@ export default defineComponent({ return { [symbols.PAGE_INFO]: { title: this.$ts.general, - icon: faCogs + icon: 'fas fa-cogs' }, langs, lang: localStorage.getItem('lang'), fontSize: localStorage.getItem('fontSize'), useSystemFont: localStorage.getItem('useSystemFont') != null, - faImage, faCog, faColumns } }, diff --git a/src/client/pages/settings/import-export.vue b/src/client/pages/settings/import-export.vue index 1591a9d548fd9b85637251567e184c38d65d133d..e77efb4429d82081a505ccc25194e17c7bc9d6b3 100644 --- a/src/client/pages/settings/import-export.vue +++ b/src/client/pages/settings/import-export.vue @@ -2,32 +2,31 @@ <FormBase> <FormGroup> <template #label>{{ $ts._exportOrImport.allNotes }}</template> - <FormButton @click="doExport('notes')"><Fa :icon="faDownload"/> {{ $ts.export }}</FormButton> + <FormButton @click="doExport('notes')"><i class="fas fa-download"></i> {{ $ts.export }}</FormButton> </FormGroup> <FormGroup> <template #label>{{ $ts._exportOrImport.followingList }}</template> - <FormButton @click="doExport('following')"><Fa :icon="faDownload"/> {{ $ts.export }}</FormButton> - <FormButton @click="doImport('following', $event)"><Fa :icon="faUpload"/> {{ $ts.import }}</FormButton> + <FormButton @click="doExport('following')"><i class="fas fa-download"></i> {{ $ts.export }}</FormButton> + <FormButton @click="doImport('following', $event)"><i class="fas fa-upload"></i> {{ $ts.import }}</FormButton> </FormGroup> <FormGroup> <template #label>{{ $ts._exportOrImport.userLists }}</template> - <FormButton @click="doExport('user-lists')"><Fa :icon="faDownload"/> {{ $ts.export }}</FormButton> - <FormButton @click="doImport('user-lists', $event)"><Fa :icon="faUpload"/> {{ $ts.import }}</FormButton> + <FormButton @click="doExport('user-lists')"><i class="fas fa-download"></i> {{ $ts.export }}</FormButton> + <FormButton @click="doImport('user-lists', $event)"><i class="fas fa-upload"></i> {{ $ts.import }}</FormButton> </FormGroup> <FormGroup> <template #label>{{ $ts._exportOrImport.muteList }}</template> - <FormButton @click="doExport('mute')"><Fa :icon="faDownload"/> {{ $ts.export }}</FormButton> + <FormButton @click="doExport('mute')"><i class="fas fa-download"></i> {{ $ts.export }}</FormButton> </FormGroup> <FormGroup> <template #label>{{ $ts._exportOrImport.blockingList }}</template> - <FormButton @click="doExport('blocking')"><Fa :icon="faDownload"/> {{ $ts.export }}</FormButton> + <FormButton @click="doExport('blocking')"><i class="fas fa-download"></i> {{ $ts.export }}</FormButton> </FormGroup> </FormBase> </template> <script lang="ts"> import { defineComponent } from 'vue'; -import { faDownload, faUpload, faBoxes } from '@fortawesome/free-solid-svg-icons'; import FormSelect from '@client/components/form/select.vue'; import FormButton from '@client/components/form/button.vue'; import FormBase from '@client/components/form/base.vue'; @@ -49,9 +48,8 @@ export default defineComponent({ return { [symbols.PAGE_INFO]: { title: this.$ts.importAndExport, - icon: faBoxes + icon: 'fas fa-boxes' }, - faDownload, faUpload, faBoxes } }, diff --git a/src/client/pages/settings/index.vue b/src/client/pages/settings/index.vue index eb7469c861d10cd9e6a935436b9d05fbaf162fdb..049e912898e31e1cd2418e6ff431566aefe81d3d 100644 --- a/src/client/pages/settings/index.vue +++ b/src/client/pages/settings/index.vue @@ -2,32 +2,40 @@ <div class="vvcocwet" :class="{ wide: !narrow }" ref="el"> <div class="nav" v-if="!narrow || page == null"> <FormBase> + <FormGroup> + <div class="_formItem"> + <div class="_formPanel lwjxoukj"> + <MkAvatar :user="$i" class="avatar"/> + </div> + </div> + <FormLink :active="page === 'accounts'" replace to="/settings/accounts"><template #icon><i class="fas fa-users"></i></template>{{ $ts.accounts }}</FormLink> + </FormGroup> <FormGroup> <template #label>{{ $ts.basicSettings }}</template> - <FormLink :active="page === 'profile'" replace to="/settings/profile"><template #icon><Fa :icon="faUser"/></template>{{ $ts.profile }}</FormLink> - <FormLink :active="page === 'privacy'" replace to="/settings/privacy"><template #icon><Fa :icon="faLockOpen"/></template>{{ $ts.privacy }}</FormLink> - <FormLink :active="page === 'reaction'" replace to="/settings/reaction"><template #icon><Fa :icon="faLaugh"/></template>{{ $ts.reaction }}</FormLink> - <FormLink :active="page === 'drive'" replace to="/settings/drive"><template #icon><Fa :icon="faCloud"/></template>{{ $ts.drive }}</FormLink> - <FormLink :active="page === 'notifications'" replace to="/settings/notifications"><template #icon><Fa :icon="faBell"/></template>{{ $ts.notifications }}</FormLink> - <FormLink :active="page === 'email'" replace to="/settings/email"><template #icon><Fa :icon="faEnvelope"/></template>{{ $ts.email }}</FormLink> - <FormLink :active="page === 'integration'" replace to="/settings/integration"><template #icon><Fa :icon="faShareAlt"/></template>{{ $ts.integration }}</FormLink> - <FormLink :active="page === 'security'" replace to="/settings/security"><template #icon><Fa :icon="faLock"/></template>{{ $ts.security }}</FormLink> + <FormLink :active="page === 'profile'" replace to="/settings/profile"><template #icon><i class="fas fa-user"></i></template>{{ $ts.profile }}</FormLink> + <FormLink :active="page === 'privacy'" replace to="/settings/privacy"><template #icon><i class="fas fa-lock-open"></i></template>{{ $ts.privacy }}</FormLink> + <FormLink :active="page === 'reaction'" replace to="/settings/reaction"><template #icon><i class="fas fa-laugh"></i></template>{{ $ts.reaction }}</FormLink> + <FormLink :active="page === 'drive'" replace to="/settings/drive"><template #icon><i class="fas fa-cloud"></i></template>{{ $ts.drive }}</FormLink> + <FormLink :active="page === 'notifications'" replace to="/settings/notifications"><template #icon><i class="fas fa-bell"></i></template>{{ $ts.notifications }}</FormLink> + <FormLink :active="page === 'email'" replace to="/settings/email"><template #icon><i class="fas fa-envelope"></i></template>{{ $ts.email }}</FormLink> + <FormLink :active="page === 'integration'" replace to="/settings/integration"><template #icon><i class="fas fa-share-alt"></i></template>{{ $ts.integration }}</FormLink> + <FormLink :active="page === 'security'" replace to="/settings/security"><template #icon><i class="fas fa-lock"></i></template>{{ $ts.security }}</FormLink> </FormGroup> <FormGroup> <template #label>{{ $ts.clientSettings }}</template> - <FormLink :active="page === 'general'" replace to="/settings/general"><template #icon><Fa :icon="faCogs"/></template>{{ $ts.general }}</FormLink> - <FormLink :active="page === 'theme'" replace to="/settings/theme"><template #icon><Fa :icon="faPalette"/></template>{{ $ts.theme }}</FormLink> - <FormLink :active="page === 'sidebar'" replace to="/settings/sidebar"><template #icon><Fa :icon="faListUl"/></template>{{ $ts.sidebar }}</FormLink> - <FormLink :active="page === 'sounds'" replace to="/settings/sounds"><template #icon><Fa :icon="faMusic"/></template>{{ $ts.sounds }}</FormLink> - <FormLink :active="page === 'plugin'" replace to="/settings/plugin"><template #icon><Fa :icon="faPlug"/></template>{{ $ts.plugins }}</FormLink> + <FormLink :active="page === 'general'" replace to="/settings/general"><template #icon><i class="fas fa-cogs"></i></template>{{ $ts.general }}</FormLink> + <FormLink :active="page === 'theme'" replace to="/settings/theme"><template #icon><i class="fas fa-palette"></i></template>{{ $ts.theme }}</FormLink> + <FormLink :active="page === 'sidebar'" replace to="/settings/sidebar"><template #icon><i class="fas fa-list-ul"></i></template>{{ $ts.sidebar }}</FormLink> + <FormLink :active="page === 'sounds'" replace to="/settings/sounds"><template #icon><i class="fas fa-music"></i></template>{{ $ts.sounds }}</FormLink> + <FormLink :active="page === 'plugin'" replace to="/settings/plugin"><template #icon><i class="fas fa-plug"></i></template>{{ $ts.plugins }}</FormLink> </FormGroup> <FormGroup> <template #label>{{ $ts.otherSettings }}</template> - <FormLink :active="page === 'import-export'" replace to="/settings/import-export"><template #icon><Fa :icon="faBoxes"/></template>{{ $ts.importAndExport }}</FormLink> - <FormLink :active="page === 'mute-block'" replace to="/settings/mute-block"><template #icon><Fa :icon="faBan"/></template>{{ $ts.muteAndBlock }}</FormLink> - <FormLink :active="page === 'word-mute'" replace to="/settings/word-mute"><template #icon><Fa :icon="faCommentSlash"/></template>{{ $ts.wordMute }}</FormLink> - <FormLink :active="page === 'api'" replace to="/settings/api"><template #icon><Fa :icon="faKey"/></template>API</FormLink> - <FormLink :active="page === 'other'" replace to="/settings/other"><template #icon><Fa :icon="faEllipsisH"/></template>{{ $ts.other }}</FormLink> + <FormLink :active="page === 'import-export'" replace to="/settings/import-export"><template #icon><i class="fas fa-boxes"></i></template>{{ $ts.importAndExport }}</FormLink> + <FormLink :active="page === 'mute-block'" replace to="/settings/mute-block"><template #icon><i class="fas fa-ban"></i></template>{{ $ts.muteAndBlock }}</FormLink> + <FormLink :active="page === 'word-mute'" replace to="/settings/word-mute"><template #icon><i class="fas fa-comment-slash"></i></template>{{ $ts.wordMute }}</FormLink> + <FormLink :active="page === 'api'" replace to="/settings/api"><template #icon><i class="fas fa-key"></i></template>API</FormLink> + <FormLink :active="page === 'other'" replace to="/settings/other"><template #icon><i class="fas fa-ellipsis-h"></i></template>{{ $ts.other }}</FormLink> </FormGroup> <FormGroup> <FormButton @click="clear">{{ $ts.clearCache }}</FormButton> @@ -45,8 +53,6 @@ <script lang="ts"> import { computed, defineAsyncComponent, defineComponent, nextTick, onMounted, reactive, ref, watch } from 'vue'; -import { faCog, faPalette, faPlug, faUser, faListUl, faLock, faCommentSlash, faMusic, faCogs, faEllipsisH, faBan, faShareAlt, faLockOpen, faKey, faBoxes, faCloud } from '@fortawesome/free-solid-svg-icons'; -import { faLaugh, faBell, faEnvelope } from '@fortawesome/free-regular-svg-icons'; import { i18n } from '@client/i18n'; import FormLink from '@client/components/form/link.vue'; import FormGroup from '@client/components/form/group.vue'; @@ -75,7 +81,7 @@ export default defineComponent({ setup(props, context) { const indexInfo = { title: i18n.locale.settings, - icon: faCog + icon: 'fas fa-cog' }; const INFO = ref(indexInfo); const page = ref(props.initialPage); @@ -89,6 +95,7 @@ export default defineComponent({ const component = computed(() => { if (page.value == null) return null; switch (page.value) { + case 'accounts': return defineAsyncComponent(() => import('./accounts.vue')); case 'profile': return defineAsyncComponent(() => import('./profile.vue')); case 'privacy': return defineAsyncComponent(() => import('./privacy.vue')); case 'reaction': return defineAsyncComponent(() => import('./reaction.vue')); @@ -183,7 +190,6 @@ export default defineComponent({ localStorage.removeItem('theme'); unisonReload(); }, - faPalette, faPlug, faUser, faListUl, faLock, faLaugh, faCommentSlash, faMusic, faBell, faCogs, faEllipsisH, faBan, faShareAlt, faLockOpen, faKey, faBoxes, faEnvelope, faCloud, }; }, }); @@ -212,4 +218,15 @@ export default defineComponent({ } } } + +.lwjxoukj { + padding: 16px; + + > .avatar { + display: block; + margin: auto; + width: 42px; + height: 42px; + } +} </style> diff --git a/src/client/pages/settings/integration.vue b/src/client/pages/settings/integration.vue index 49f955bc350d5a7dfc16b354283f3c177e1f5cdd..2d2be04051689991cfa2eda1c729380de1ae3052 100644 --- a/src/client/pages/settings/integration.vue +++ b/src/client/pages/settings/integration.vue @@ -1,7 +1,7 @@ <template> <FormBase> <div class="_formItem" v-if="enableTwitterIntegration"> - <div class="_formLabel"><Fa :icon="faTwitter"/> Twitter</div> + <div class="_formLabel"><i class="fab fa-twitter"></i> Twitter</div> <div class="_formPanel" style="padding: 16px;"> <p v-if="integrations.twitter">{{ $ts.connectedTo }}: <a :href="`https://twitter.com/${integrations.twitter.screenName}`" rel="nofollow noopener" target="_blank">@{{ integrations.twitter.screenName }}</a></p> <MkButton v-if="integrations.twitter" @click="disconnectTwitter" danger>{{ $ts.disconnectSerice }}</MkButton> @@ -10,7 +10,7 @@ </div> <div class="_formItem" v-if="enableDiscordIntegration"> - <div class="_formLabel"><Fa :icon="faDiscord"/> Discord</div> + <div class="_formLabel"><i class="fab fa-discord"></i> Discord</div> <div class="_formPanel" style="padding: 16px;"> <p v-if="integrations.discord">{{ $ts.connectedTo }}: <a :href="`https://discord.com/users/${integrations.discord.id}`" rel="nofollow noopener" target="_blank">@{{ integrations.discord.username }}#{{ integrations.discord.discriminator }}</a></p> <MkButton v-if="integrations.discord" @click="disconnectDiscord" danger>{{ $ts.disconnectSerice }}</MkButton> @@ -19,7 +19,7 @@ </div> <div class="_formItem" v-if="enableGithubIntegration"> - <div class="_formLabel"><Fa :icon="faGithub"/> GitHub</div> + <div class="_formLabel"><i class="fab fa-github"></i> GitHub</div> <div class="_formPanel" style="padding: 16px;"> <p v-if="integrations.github">{{ $ts.connectedTo }}: <a :href="`https://github.com/${integrations.github.login}`" rel="nofollow noopener" target="_blank">@{{ integrations.github.login }}</a></p> <MkButton v-if="integrations.github" @click="disconnectGithub" danger>{{ $ts.disconnectSerice }}</MkButton> @@ -31,8 +31,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faShareAlt } from '@fortawesome/free-solid-svg-icons'; -import { faTwitter, faDiscord, faGithub } from '@fortawesome/free-brands-svg-icons'; import { apiUrl } from '@client/config'; import FormBase from '@client/components/form/base.vue'; import MkButton from '@client/components/ui/button.vue'; @@ -51,7 +49,7 @@ export default defineComponent({ return { [symbols.PAGE_INFO]: { title: this.$ts.integration, - icon: faShareAlt + icon: 'fas fa-share-alt' }, apiUrl, twitterForm: null, @@ -60,7 +58,6 @@ export default defineComponent({ enableTwitterIntegration: false, enableDiscordIntegration: false, enableGithubIntegration: false, - faShareAlt, faTwitter, faDiscord, faGithub }; }, diff --git a/src/client/pages/settings/mute-block.vue b/src/client/pages/settings/mute-block.vue index 11450e049b1e92ab5cb080baa03fe3faddffe347..dde0199e187bbd2f9d36a0eeac2a013af715b3a3 100644 --- a/src/client/pages/settings/mute-block.vue +++ b/src/client/pages/settings/mute-block.vue @@ -33,7 +33,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faBan } from '@fortawesome/free-solid-svg-icons'; import MkPagination from '@client/components/ui/pagination.vue'; import MkTab from '@client/components/tab.vue'; import FormInfo from '@client/components/form/info.vue'; @@ -60,7 +59,7 @@ export default defineComponent({ return { [symbols.PAGE_INFO]: { title: this.$ts.muteAndBlock, - icon: faBan + icon: 'fas fa-ban' }, tab: 'mute', mutingPagination: { diff --git a/src/client/pages/settings/notifications.vue b/src/client/pages/settings/notifications.vue index ea72bcfee8ba1ad96a05f64bd9cc391657920e44..ec95452ba21dbe3eacc628c0af5886b44a718943 100644 --- a/src/client/pages/settings/notifications.vue +++ b/src/client/pages/settings/notifications.vue @@ -11,8 +11,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faCog } from '@fortawesome/free-solid-svg-icons'; -import { faBell } from '@fortawesome/free-regular-svg-icons'; import FormButton from '@client/components/form/button.vue'; import FormLink from '@client/components/form/link.vue'; import FormBase from '@client/components/form/base.vue'; @@ -35,9 +33,8 @@ export default defineComponent({ return { [symbols.PAGE_INFO]: { title: this.$ts.notifications, - icon: faBell + icon: 'fas fa-bell' }, - faCog } }, diff --git a/src/client/pages/settings/other.vue b/src/client/pages/settings/other.vue index 2bd9c2476ce54361a4490b2ba417386732bd767d..f73ff9cb21d4b08e80bddcb079e0550d9317ce72 100644 --- a/src/client/pages/settings/other.vue +++ b/src/client/pages/settings/other.vue @@ -21,10 +21,10 @@ </template> </FormGroup> - <FormLink to="/settings/registry"><template #icon><Fa :icon="faCogs"/></template>{{ $ts.registry }}</FormLink> + <FormLink to="/settings/registry"><template #icon><i class="fas fa-cogs"></i></template>{{ $ts.registry }}</FormLink> - <FormLink to="/bios" behavior="browser"><template #icon><Fa :icon="faDoorOpen"/></template>BIOS</FormLink> - <FormLink to="/cli" behavior="browser"><template #icon><Fa :icon="faDoorOpen"/></template>CLI</FormLink> + <FormLink to="/bios" behavior="browser"><template #icon><i class="fas fa-door-open"></i></template>BIOS</FormLink> + <FormLink to="/cli" behavior="browser"><template #icon><i class="fas fa-door-open"></i></template>CLI</FormLink> <FormButton @click="closeAccount" danger>{{ $ts.closeAccount }}</FormButton> </FormBase> @@ -32,7 +32,6 @@ <script lang="ts"> import { defineAsyncComponent, defineComponent } from 'vue'; -import { faEllipsisH, faCogs, faDoorOpen } from '@fortawesome/free-solid-svg-icons'; import FormSwitch from '@client/components/form/switch.vue'; import FormSelect from '@client/components/form/select.vue'; import FormLink from '@client/components/form/link.vue'; @@ -62,10 +61,9 @@ export default defineComponent({ return { [symbols.PAGE_INFO]: { title: this.$ts.other, - icon: faEllipsisH + icon: 'fas fa-ellipsis-h' }, debug, - faCogs, faDoorOpen, } }, diff --git a/src/client/pages/settings/plugin.install.vue b/src/client/pages/settings/plugin.install.vue index bc80188fc6271108a7ef9f289c50bd43a3e948f8..30cbf58ad792fdb6b5840b4239dcf466f5634f15 100644 --- a/src/client/pages/settings/plugin.install.vue +++ b/src/client/pages/settings/plugin.install.vue @@ -8,13 +8,12 @@ </FormTextarea> </FormGroup> - <FormButton @click="install" :disabled="code == null" primary inline><Fa :icon="faCheck"/> {{ $ts.install }}</FormButton> + <FormButton @click="install" :disabled="code == null" primary inline><i class="fas fa-check"></i> {{ $ts.install }}</FormButton> </FormBase> </template> <script lang="ts"> import { defineComponent } from 'vue'; -import { faPalette, faDownload, faFolderOpen, faCheck, faTrashAlt, faEye } from '@fortawesome/free-solid-svg-icons'; import { AiScript, parse } from '@syuilo/aiscript'; import { serialize } from '@syuilo/aiscript/built/serializer'; import { v4 as uuid } from 'uuid'; @@ -49,10 +48,9 @@ export default defineComponent({ return { [symbols.PAGE_INFO]: { title: this.$ts._plugin.install, - icon: faDownload + icon: 'fas fa-download' }, code: null, - faPalette, faDownload, faFolderOpen, faCheck, faTrashAlt, faEye } }, diff --git a/src/client/pages/settings/plugin.manage.vue b/src/client/pages/settings/plugin.manage.vue index d7aabe560ecc44a993b76cde6d68abf5b4678c4e..3df87ca084e5225acceef107c9dc9ab436b7ea81 100644 --- a/src/client/pages/settings/plugin.manage.vue +++ b/src/client/pages/settings/plugin.manage.vue @@ -22,8 +22,8 @@ </div> <div class="_formItem"> <div class="_formPanel" style="padding: 16px;"> - <MkButton @click="config(plugin)" inline v-if="plugin.config"><Fa :icon="faCog"/> {{ $ts.settings }}</MkButton> - <MkButton @click="uninstall(plugin)" inline danger><Fa :icon="faTrashAlt"/> {{ $ts.uninstall }}</MkButton> + <MkButton @click="config(plugin)" inline v-if="plugin.config"><i class="fas fa-cog"></i> {{ $ts.settings }}</MkButton> + <MkButton @click="uninstall(plugin)" inline danger><i class="fas fa-trash-alt"></i> {{ $ts.uninstall }}</MkButton> </div> </div> </FormGroup> @@ -32,7 +32,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faPlug, faSave, faTrashAlt, faFolderOpen, faDownload, faCog } from '@fortawesome/free-solid-svg-icons'; import MkButton from '@client/components/ui/button.vue'; import MkTextarea from '@client/components/ui/textarea.vue'; import MkSelect from '@client/components/ui/select.vue'; @@ -59,10 +58,9 @@ export default defineComponent({ return { [symbols.PAGE_INFO]: { title: this.$ts._plugin.manage, - icon: faPlug + icon: 'fas fa-plug' }, plugins: ColdDeviceStorage.get('plugins'), - faPlug, faSave, faTrashAlt, faFolderOpen, faDownload, faCog } }, diff --git a/src/client/pages/settings/plugin.vue b/src/client/pages/settings/plugin.vue index bee4e57ec334bed22f9d8969c374de90fd562c4d..13eaca07fd971403f8e3582838480b6e7a9ee537 100644 --- a/src/client/pages/settings/plugin.vue +++ b/src/client/pages/settings/plugin.vue @@ -1,13 +1,12 @@ <template> <FormBase> - <FormLink to="/settings/plugin/install"><template #icon><Fa :icon="faDownload"/></template>{{ $ts._plugin.install }}</FormLink> - <FormLink to="/settings/plugin/manage"><template #icon><Fa :icon="faFolderOpen"/></template>{{ $ts._plugin.manage }}<template #suffix>{{ plugins }}</template></FormLink> + <FormLink to="/settings/plugin/install"><template #icon><i class="fas fa-download"></i></template>{{ $ts._plugin.install }}</FormLink> + <FormLink to="/settings/plugin/manage"><template #icon><i class="fas fa-folder-open"></i></template>{{ $ts._plugin.manage }}<template #suffix>{{ plugins }}</template></FormLink> </FormBase> </template> <script lang="ts"> import { defineComponent } from 'vue'; -import { faPlug, faSave, faTrashAlt, faFolderOpen, faDownload, faCog } from '@fortawesome/free-solid-svg-icons'; import FormBase from '@client/components/form/base.vue'; import FormGroup from '@client/components/form/group.vue'; import FormLink from '@client/components/form/link.vue'; @@ -27,10 +26,9 @@ export default defineComponent({ return { [symbols.PAGE_INFO]: { title: this.$ts.plugins, - icon: faPlug + icon: 'fas fa-plug' }, plugins: ColdDeviceStorage.get('plugins').length, - faPlug, faSave, faTrashAlt, faFolderOpen, faDownload, faCog } }, diff --git a/src/client/pages/settings/privacy.vue b/src/client/pages/settings/privacy.vue index c8df37841072580da82ba9daf4e5959311893edf..4095e744c239b9ae9f7b8c59654e98269d785ef3 100644 --- a/src/client/pages/settings/privacy.vue +++ b/src/client/pages/settings/privacy.vue @@ -33,7 +33,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faLockOpen } from '@fortawesome/free-solid-svg-icons'; import FormSwitch from '@client/components/form/switch.vue'; import FormSelect from '@client/components/form/select.vue'; import FormBase from '@client/components/form/base.vue'; @@ -56,7 +55,7 @@ export default defineComponent({ return { [symbols.PAGE_INFO]: { title: this.$ts.privacy, - icon: faLockOpen + icon: 'fas fa-lock-open' }, isLocked: false, autoAcceptFollowed: false, diff --git a/src/client/pages/settings/profile.vue b/src/client/pages/settings/profile.vue index 5ec580a206cd34aa8cf2bff1a943abf2bb5cce04..de7e86bd12457edac2199f81c44d8825ba6505f9 100644 --- a/src/client/pages/settings/profile.vue +++ b/src/client/pages/settings/profile.vue @@ -19,12 +19,12 @@ <FormInput v-model:value="location" manual-save> <span>{{ $ts.location }}</span> - <template #prefix><Fa :icon="faMapMarkerAlt"/></template> + <template #prefix><i class="fas fa-map-marker-alt"></i></template> </FormInput> <FormInput v-model:value="birthday" type="date" manual-save> <span>{{ $ts.birthday }}</span> - <template #prefix><Fa :icon="faBirthdayCake"/></template> + <template #prefix><i class="fas fa-birthday-cake"></i></template> </FormInput> <FormSelect v-model:value="lang"> @@ -47,8 +47,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faUnlockAlt, faCogs, faUser, faMapMarkerAlt, faBirthdayCake } from '@fortawesome/free-solid-svg-icons'; -import { faSave } from '@fortawesome/free-regular-svg-icons'; import FormButton from '@client/components/form/button.vue'; import FormInput from '@client/components/form/input.vue'; import FormTextarea from '@client/components/form/textarea.vue'; @@ -78,7 +76,7 @@ export default defineComponent({ return { [symbols.PAGE_INFO]: { title: this.$ts.profile, - icon: faUser + icon: 'fas fa-user' }, host, langs, @@ -101,7 +99,6 @@ export default defineComponent({ isCat: false, alwaysMarkNsfw: false, saving: false, - faSave, faUnlockAlt, faCogs, faUser, faMapMarkerAlt, faBirthdayCake } }, diff --git a/src/client/pages/settings/reaction.vue b/src/client/pages/settings/reaction.vue index 0293f53fa84c36a9db499a8e8f36433233f62534..9bffd5f90301e6af76b036c3d5ac4640b81b4062 100644 --- a/src/client/pages/settings/reaction.vue +++ b/src/client/pages/settings/reaction.vue @@ -10,7 +10,7 @@ </button> </template> <template #footer> - <button class="_button add" @click="chooseEmoji"><Fa :icon="faPlus"/></button> + <button class="_button add" @click="chooseEmoji"><i class="fas fa-plus"></i></button> </template> </XDraggable> </div> @@ -29,15 +29,13 @@ <option :value="2">{{ $ts.medium }}</option> <option :value="3">{{ $ts.large }}</option> </FormRadios> - <FormButton @click="preview"><Fa :icon="faEye"/> {{ $ts.preview }}</FormButton> - <FormButton danger @click="setDefault"><Fa :icon="faUndo"/> {{ $ts.default }}</FormButton> + <FormButton @click="preview"><i class="fas fa-eye"></i> {{ $ts.preview }}</FormButton> + <FormButton danger @click="setDefault"><i class="fas fa-undo"></i> {{ $ts.default }}</FormButton> </FormBase> </template> <script lang="ts"> import { defineComponent } from 'vue'; -import { faLaugh, faSave, faEye } from '@fortawesome/free-regular-svg-icons'; -import { faUndo, faPlus } from '@fortawesome/free-solid-svg-icons'; import XDraggable from 'vuedraggable'; import FormInput from '@client/components/form/input.vue'; import FormRadios from '@client/components/form/radios.vue'; @@ -62,14 +60,13 @@ export default defineComponent({ return { [symbols.PAGE_INFO]: { title: this.$ts.reaction, - icon: faLaugh, + icon: 'fas fa-laugh', action: { - icon: faEye, + icon: 'fas fa-eye', handler: this.preview } }, reactions: JSON.parse(JSON.stringify(this.$store.state.reactions)), - faLaugh, faSave, faEye, faUndo, faPlus } }, diff --git a/src/client/pages/settings/registry.keys.vue b/src/client/pages/settings/registry.keys.vue index 5cdfdc1332c45b3e732c62ff60fa76209b06fee5..f71589ba4f5b34fe6c6b3e6f14612b4cbf631a2e 100644 --- a/src/client/pages/settings/registry.keys.vue +++ b/src/client/pages/settings/registry.keys.vue @@ -22,7 +22,6 @@ <script lang="ts"> import { defineAsyncComponent, defineComponent } from 'vue'; -import { faCogs } from '@fortawesome/free-solid-svg-icons'; import * as JSON5 from 'json5'; import FormSwitch from '@client/components/form/switch.vue'; import FormSelect from '@client/components/form/select.vue'; @@ -57,7 +56,7 @@ export default defineComponent({ return { [symbols.PAGE_INFO]: { title: this.$ts.registry, - icon: faCogs + icon: 'fas fa-cogs' }, keys: null, } diff --git a/src/client/pages/settings/registry.value.vue b/src/client/pages/settings/registry.value.vue index 7d5756af991375a8b5a1cec43e80bb186f761d04..48245ae99fb935ec2da89b255d3987d02a18adb0 100644 --- a/src/client/pages/settings/registry.value.vue +++ b/src/client/pages/settings/registry.value.vue @@ -22,7 +22,7 @@ <FormTextarea tall v-model:value="valueForEditor" class="_monospace" style="tab-size: 2;"> <span>{{ $ts.value }} (JSON)</span> </FormTextarea> - <FormButton @click="save" primary><Fa :icon="faSave"/> {{ $ts.save }}</FormButton> + <FormButton @click="save" primary><i class="fas fa-save"></i> {{ $ts.save }}</FormButton> </FormGroup> <FormKeyValueView> @@ -30,14 +30,13 @@ <template #value><MkTime :time="value.updatedAt" mode="detail"/></template> </FormKeyValueView> - <FormButton danger @click="del"><Fa :icon="faTrash"/> {{ $ts.delete }}</FormButton> + <FormButton danger @click="del"><i class="fas fa-trash"></i> {{ $ts.delete }}</FormButton> </template> </FormBase> </template> <script lang="ts"> import { defineAsyncComponent, defineComponent } from 'vue'; -import { faCogs, faSave, faTrash } from '@fortawesome/free-solid-svg-icons'; import * as JSON5 from 'json5'; import FormInfo from '@client/components/form/info.vue'; import FormSwitch from '@client/components/form/switch.vue'; @@ -77,11 +76,10 @@ export default defineComponent({ return { [symbols.PAGE_INFO]: { title: this.$ts.registry, - icon: faCogs + icon: 'fas fa-cogs' }, value: null, valueForEditor: null, - faSave, faTrash, } }, diff --git a/src/client/pages/settings/registry.vue b/src/client/pages/settings/registry.vue index 085389fc9527550d54cf005438bbf3d0f39ba25b..5ba1bc751b93102537bc42afceb15bdf32f2c6c6 100644 --- a/src/client/pages/settings/registry.vue +++ b/src/client/pages/settings/registry.vue @@ -10,7 +10,6 @@ <script lang="ts"> import { defineAsyncComponent, defineComponent } from 'vue'; -import { faCogs } from '@fortawesome/free-solid-svg-icons'; import * as JSON5 from 'json5'; import FormSwitch from '@client/components/form/switch.vue'; import FormSelect from '@client/components/form/select.vue'; @@ -39,7 +38,7 @@ export default defineComponent({ return { [symbols.PAGE_INFO]: { title: this.$ts.registry, - icon: faCogs + icon: 'fas fa-cogs' }, scopes: null, } diff --git a/src/client/pages/settings/security.vue b/src/client/pages/settings/security.vue index 64733c55a2fddc4643558b599637ea5f949c833f..b70fa5a9f30cc3a342dba1b112d7f434a6fb3e73 100644 --- a/src/client/pages/settings/security.vue +++ b/src/client/pages/settings/security.vue @@ -1,15 +1,15 @@ <template> <FormBase> <X2fa/> - <FormLink to="/settings/2fa"><template #icon><Fa :icon="faMobileAlt"/></template>{{ $ts.twoStepAuthentication }}</FormLink> + <FormLink to="/settings/2fa"><template #icon><i class="fas fa-mobile-alt"></i></template>{{ $ts.twoStepAuthentication }}</FormLink> <FormButton primary @click="change()">{{ $ts.changePassword }}</FormButton> <FormPagination :pagination="pagination"> <template #label>{{ $ts.signinHistory }}</template> <template #default="{items}"> <div class="_formPanel timnmucd" v-for="item in items" :key="item.id"> <header> - <Fa class="icon succ" :icon="faCheck" v-if="item.success"/> - <Fa class="icon fail" :icon="faTimesCircle" v-else/> + <i v-if="item.success" class="fas fa-check icon succ"></i> + <i v-else class="fas fa-times-circle icon fail"></i> <code class="ip _monospace">{{ item.ip }}</code> <MkTime :time="item.createdAt" class="time"/> </header> @@ -17,7 +17,7 @@ </template> </FormPagination> <FormGroup> - <FormButton danger @click="regenerateToken"><Fa :icon="faSyncAlt"/> {{ $ts.regenerateLoginToken }}</FormButton> + <FormButton danger @click="regenerateToken"><i class="fas fa-sync-alt"></i> {{ $ts.regenerateLoginToken }}</FormButton> <template #caption>{{ $ts.regenerateLoginTokenDescription }}</template> </FormGroup> </FormBase> @@ -25,7 +25,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faCheck, faTimesCircle, faLock, faSyncAlt, faMobileAlt } from '@fortawesome/free-solid-svg-icons'; import FormBase from '@client/components/form/base.vue'; import FormLink from '@client/components/form/link.vue'; import FormGroup from '@client/components/form/group.vue'; @@ -49,13 +48,12 @@ export default defineComponent({ return { [symbols.PAGE_INFO]: { title: this.$ts.security, - icon: faLock + icon: 'fas fa-lock' }, pagination: { endpoint: 'i/signin-history', limit: 5, }, - faLock, faSyncAlt, faCheck, faTimesCircle, faMobileAlt, } }, diff --git a/src/client/pages/settings/sidebar.vue b/src/client/pages/settings/sidebar.vue index adeec2f636dc5457e073ad3265e480b16616a9ba..f0172e945f0806bd622f4bc8e426c89a795a395d 100644 --- a/src/client/pages/settings/sidebar.vue +++ b/src/client/pages/settings/sidebar.vue @@ -12,14 +12,13 @@ <!-- <MkRadio v-model="sidebarDisplay" value="hide" disabled>{{ $ts._sidebar.hide }}</MkRadio>--> <!-- TODO: サイドãƒãƒ¼ã‚’完全ã«éš ã›ã‚‹ã‚ˆã†ã«ã™ã‚‹ã¨ã€åˆ¥é€”ãƒãƒ³ãƒãƒ¼ã‚¬ãƒ¼ãƒœã‚¿ãƒ³ã®ã‚ˆã†ãªã‚‚ã®ã‚’UIã«è¡¨ç¤ºã™ã‚‹å¿…è¦ãŒã‚ã‚Šé¢å€’ --> </FormRadios> - <FormButton @click="save()" primary><Fa :icon="faSave"/> {{ $ts.save }}</FormButton> - <FormButton @click="reset()" danger><Fa :icon="faRedo"/> {{ $ts.default }}</FormButton> + <FormButton @click="save()" primary><i class="fas fa-save"></i> {{ $ts.save }}</FormButton> + <FormButton @click="reset()" danger><i class="fas fa-redo"></i> {{ $ts.default }}</FormButton> </FormBase> </template> <script lang="ts"> import { defineComponent } from 'vue'; -import { faListUl, faSave, faRedo } from '@fortawesome/free-solid-svg-icons'; import FormSwitch from '@client/components/form/switch.vue'; import FormTextarea from '@client/components/form/textarea.vue'; import FormRadios from '@client/components/form/radios.vue'; @@ -45,11 +44,10 @@ export default defineComponent({ return { [symbols.PAGE_INFO]: { title: this.$ts.sidebar, - icon: faListUl + icon: 'fas fa-list-ul' }, menuDef: sidebarDef, items: '', - faSave, faRedo } }, diff --git a/src/client/pages/settings/sounds.vue b/src/client/pages/settings/sounds.vue index 54be0031156fe89a03439a3c919ed813b49503a5..f56ec4cd89def80aea129645373ed7b76b7da767 100644 --- a/src/client/pages/settings/sounds.vue +++ b/src/client/pages/settings/sounds.vue @@ -1,7 +1,7 @@ <template> <FormBase> <FormRange v-model:value="masterVolume" :min="0" :max="1" :step="0.05"> - <template #label><Fa :icon="volumeIcon" :key="volumeIcon"/> {{ $ts.masterVolume }}</template> + <template #label><i class="fas fa-volume-icon"></i> {{ $ts.masterVolume }}</template> </FormRange> <FormGroup> @@ -9,17 +9,16 @@ <FormButton v-for="type in Object.keys(sounds)" :key="type" :center="false" @click="edit(type)"> {{ $t('_sfx.' + type) }} <template #suffix>{{ sounds[type].type || $ts.none }}</template> - <template #suffixIcon><Fa :icon="faChevronDown"/></template> + <template #suffixIcon><i class="fas fa-chevron-down"></i></template> </FormButton> </FormGroup> - <FormButton @click="reset()" danger><Fa :icon="faRedo"/> {{ $ts.default }}</FormButton> + <FormButton @click="reset()" danger><i class="fas fa-redo"></i> {{ $ts.default }}</FormButton> </FormBase> </template> <script lang="ts"> import { defineComponent } from 'vue'; -import { faMusic, faPlay, faVolumeUp, faVolumeMute, faChevronDown, faRedo } from '@fortawesome/free-solid-svg-icons'; import FormRange from '@client/components/form/range.vue'; import FormSelect from '@client/components/form/select.vue'; import FormBase from '@client/components/form/base.vue'; @@ -71,10 +70,9 @@ export default defineComponent({ return { [symbols.PAGE_INFO]: { title: this.$ts.sounds, - icon: faMusic + icon: 'fas fa-music' }, sounds: {}, - faMusic, faPlay, faVolumeUp, faVolumeMute, faChevronDown, faRedo, } }, @@ -84,7 +82,7 @@ export default defineComponent({ set(value) { ColdDeviceStorage.set('sound_masterVolume', value); } }, volumeIcon() { - return this.masterVolume === 0 ? faVolumeMute : faVolumeUp; + return this.masterVolume === 0 ? 'fas fa-volume-mute' : 'fas fa-volume-up'; } }, diff --git a/src/client/pages/settings/theme.install.vue b/src/client/pages/settings/theme.install.vue index 744d1aba4491cd9b7316d2d329e0dad9caa1d805..d719cc801fa05e95f8499df7b0d6d4032c4ec75b 100644 --- a/src/client/pages/settings/theme.install.vue +++ b/src/client/pages/settings/theme.install.vue @@ -4,16 +4,15 @@ <FormTextarea v-model:value="installThemeCode"> <span>{{ $ts._theme.code }}</span> </FormTextarea> - <FormButton @click="() => preview(installThemeCode)" :disabled="installThemeCode == null" inline><Fa :icon="faEye"/> {{ $ts.preview }}</FormButton> + <FormButton @click="() => preview(installThemeCode)" :disabled="installThemeCode == null" inline><i class="fas fa-eye"></i> {{ $ts.preview }}</FormButton> </FormGroup> - <FormButton @click="() => install(installThemeCode)" :disabled="installThemeCode == null" primary inline><Fa :icon="faCheck"/> {{ $ts.install }}</FormButton> + <FormButton @click="() => install(installThemeCode)" :disabled="installThemeCode == null" primary inline><i class="fas fa-check"></i> {{ $ts.install }}</FormButton> </FormBase> </template> <script lang="ts"> import { defineComponent } from 'vue'; -import { faPalette, faDownload, faFolderOpen, faCheck, faTrashAlt, faEye } from '@fortawesome/free-solid-svg-icons'; import * as JSON5 from 'json5'; import FormTextarea from '@client/components/form/textarea.vue'; import FormSelect from '@client/components/form/select.vue'; @@ -45,10 +44,9 @@ export default defineComponent({ return { [symbols.PAGE_INFO]: { title: this.$ts._theme.install, - icon: faDownload + icon: 'fas fa-download' }, installThemeCode: null, - faPalette, faDownload, faFolderOpen, faCheck, faTrashAlt, faEye } }, diff --git a/src/client/pages/settings/theme.manage.vue b/src/client/pages/settings/theme.manage.vue index ea9d5949ffcb6ebf71aff23b7d5603eeb887e768..7cc7a0169a8771fe5bd6ef66d2990591d5c8447e 100644 --- a/src/client/pages/settings/theme.manage.vue +++ b/src/client/pages/settings/theme.manage.vue @@ -20,14 +20,13 @@ <span>{{ $ts._theme.code }}</span> <template #desc><button @click="copyThemeCode()" class="_textButton">{{ $ts.copy }}</button></template> </FormTextarea> - <FormButton @click="uninstall()" danger v-if="!builtinThemes.some(t => t.id == selectedTheme.id)"><Fa :icon="faTrashAlt"/> {{ $ts.uninstall }}</FormButton> + <FormButton @click="uninstall()" danger v-if="!builtinThemes.some(t => t.id == selectedTheme.id)"><i class="fas fa-trash-alt"></i> {{ $ts.uninstall }}</FormButton> </template> </FormBase> </template> <script lang="ts"> import { defineComponent } from 'vue'; -import { faPalette, faDownload, faFolderOpen, faCheck, faTrashAlt, faEye } from '@fortawesome/free-solid-svg-icons'; import * as JSON5 from 'json5'; import FormTextarea from '@client/components/form/textarea.vue'; import FormSelect from '@client/components/form/select.vue'; @@ -60,12 +59,11 @@ export default defineComponent({ return { [symbols.PAGE_INFO]: { title: this.$ts._theme.manage, - icon: faFolderOpen + icon: 'fas fa-folder-open' }, installedThemes: getThemes(), builtinThemes, selectedThemeId: null, - faPalette, faDownload, faFolderOpen, faCheck, faTrashAlt, faEye } }, diff --git a/src/client/pages/settings/theme.vue b/src/client/pages/settings/theme.vue index 606e10ab7ab6a69de0f8e9bbf7d7698a4eea75f7..1eb0d68be5d751639b14a760ae6a6ec9ff594962 100644 --- a/src/client/pages/settings/theme.vue +++ b/src/client/pages/settings/theme.vue @@ -71,22 +71,21 @@ <FormButton primary v-else @click="wallpaper = null">{{ $ts.removeWallpaper }}</FormButton> <FormGroup> - <FormLink to="https://assets.msky.cafe/theme/list" external><template #icon><Fa :icon="faGlobe"/></template>{{ $ts._theme.explore }}</FormLink> - <FormLink to="/settings/theme/install"><template #icon><Fa :icon="faDownload"/></template>{{ $ts._theme.install }}</FormLink> + <FormLink to="https://assets.msky.cafe/theme/list" external><template #icon><i class="fas fa-globe"></i></template>{{ $ts._theme.explore }}</FormLink> + <FormLink to="/settings/theme/install"><template #icon><i class="fas fa-download"></i></template>{{ $ts._theme.install }}</FormLink> </FormGroup> <FormGroup> - <FormLink to="/theme-editor"><template #icon><Fa :icon="faPaintRoller"/></template>{{ $ts._theme.make }}</FormLink> - <!--<FormLink to="/advanced-theme-editor"><template #icon><Fa :icon="faPaintRoller"/></template>{{ $ts._theme.make }} ({{ $ts.advanced }})</FormLink>--> + <FormLink to="/theme-editor"><template #icon><i class="fas fa-paint-roller"></i></template>{{ $ts._theme.make }}</FormLink> + <!--<FormLink to="/advanced-theme-editor"><template #icon><i class="fas fa-paint-roller"></i></template>{{ $ts._theme.make }} ({{ $ts.advanced }})</FormLink>--> </FormGroup> - <FormLink to="/settings/theme/manage"><template #icon><Fa :icon="faFolderOpen"/></template>{{ $ts._theme.manage }}<template #suffix>{{ themesCount }}</template></FormLink> + <FormLink to="/settings/theme/manage"><template #icon><i class="fas fa-folder-open"></i></template>{{ $ts._theme.manage }}<template #suffix>{{ themesCount }}</template></FormLink> </FormBase> </template> <script lang="ts"> import { computed, defineComponent, onActivated, onMounted, ref, watch } from 'vue'; -import { faPalette, faDownload, faFolderOpen, faCheck, faTrashAlt, faEye, faGlobe, faPaintRoller } from '@fortawesome/free-solid-svg-icons'; import FormSwitch from '@client/components/form/switch.vue'; import FormSelect from '@client/components/form/select.vue'; import FormBase from '@client/components/form/base.vue'; @@ -117,7 +116,7 @@ export default defineComponent({ setup(props, { emit }) { const INFO = { title: i18n.locale.theme, - icon: faPalette + icon: 'fas fa-palette' }; const installedThemes = ref(getThemes()); @@ -191,7 +190,6 @@ export default defineComponent({ wallpaper.value = file.url; }); }, - faPalette, faDownload, faFolderOpen, faCheck, faTrashAlt, faEye, faGlobe, faPaintRoller, }; } }); diff --git a/src/client/pages/settings/update.vue b/src/client/pages/settings/update.vue index d7b2adae56440958d8723a14c9d99fdd01a951d4..8000327d0cbbf64cd304ef5d6160ad8c05649514 100644 --- a/src/client/pages/settings/update.vue +++ b/src/client/pages/settings/update.vue @@ -30,7 +30,6 @@ <script lang="ts"> import { defineAsyncComponent, defineComponent } from 'vue'; -import { faInfoCircle, faSyncAlt } from '@fortawesome/free-solid-svg-icons'; import FormSwitch from '@client/components/form/switch.vue'; import FormSelect from '@client/components/form/select.vue'; import FormLink from '@client/components/form/link.vue'; @@ -61,7 +60,7 @@ export default defineComponent({ return { [symbols.PAGE_INFO]: { title: 'Misskey Update', - icon: faSyncAlt + icon: 'fas fa-sync-alt' }, version, instanceName, diff --git a/src/client/pages/settings/word-mute.vue b/src/client/pages/settings/word-mute.vue index 79de2ebbdf885b984d27b3ebde1ab75a28f835e9..fe3fece844cc0149056d6220fc0ece41fe31809f 100644 --- a/src/client/pages/settings/word-mute.vue +++ b/src/client/pages/settings/word-mute.vue @@ -25,14 +25,13 @@ </FormKeyValueView> </div> </div> - <FormButton @click="save()" primary inline :disabled="!changed"><Fa :icon="faSave"/> {{ $ts.save }}</FormButton> + <FormButton @click="save()" primary inline :disabled="!changed"><i class="fas fa-save"></i> {{ $ts.save }}</FormButton> </FormBase> </div> </template> <script lang="ts"> import { defineComponent } from 'vue'; -import { faCommentSlash, faSave } from '@fortawesome/free-solid-svg-icons'; import FormTextarea from '@client/components/form/textarea.vue'; import FormBase from '@client/components/form/base.vue'; import FormKeyValueView from '@client/components/form/key-value-view.vue'; @@ -59,14 +58,13 @@ export default defineComponent({ return { [symbols.PAGE_INFO]: { title: this.$ts.wordMute, - icon: faCommentSlash + icon: 'fas fa-comment-slash' }, tab: 'soft', softMutedWords: '', hardMutedWords: '', hardWordMutedNotesCount: null, changed: false, - faSave, } }, diff --git a/src/client/pages/share.vue b/src/client/pages/share.vue index 313b73b9cb984628c00c22b373941b92707cbf76..67e598fa8f7edc70df6b964882e2e9ecc6914e86 100644 --- a/src/client/pages/share.vue +++ b/src/client/pages/share.vue @@ -13,7 +13,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faShareAlt } from '@fortawesome/free-solid-svg-icons'; import MkButton from '@client/components/ui/button.vue'; import XPostForm from '@client/components/post-form.vue'; import * as os from '@client/os'; @@ -29,7 +28,7 @@ export default defineComponent({ return { [symbols.PAGE_INFO]: { title: this.$ts.share, - icon: faShareAlt + icon: 'fas fa-share-alt' }, title: null, text: null, @@ -37,7 +36,6 @@ export default defineComponent({ initialText: null, posted: false, - faShareAlt } }, diff --git a/src/client/pages/tag.vue b/src/client/pages/tag.vue index 813181dd1f70fa601a3ec5ffdeb05e5c6a84623b..3ca9fe5c0c2299a94cce1a8dd42c39f49e7baeb8 100644 --- a/src/client/pages/tag.vue +++ b/src/client/pages/tag.vue @@ -6,7 +6,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faHashtag } 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'; @@ -27,7 +26,7 @@ export default defineComponent({ return { [symbols.PAGE_INFO]: { title: this.tag, - icon: faHashtag + icon: 'fas fa-hashtag' }, pagination: { endpoint: 'notes/search-by-tag', @@ -36,7 +35,6 @@ export default defineComponent({ tag: this.tag, }) }, - faHashtag }; }, diff --git a/src/client/pages/test.vue b/src/client/pages/test.vue index 252fa1c828fa6a85cf91415f053c49f967855bcb..9a06d31090c2e4b495cebc4cbce50d2160f2032a 100644 --- a/src/client/pages/test.vue +++ b/src/client/pages/test.vue @@ -132,7 +132,6 @@ <script lang="ts"> import { defineComponent, defineAsyncComponent } from 'vue'; -import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons'; import MkButton from '@client/components/ui/button.vue'; import MkInput from '@client/components/ui/input.vue'; import MkSwitch from '@client/components/ui/switch.vue'; @@ -154,7 +153,7 @@ export default defineComponent({ return { [symbols.PAGE_INFO]: { title: 'TEST', - icon: faExclamationTriangle + icon: 'fas fa-exclamation-triangle' }, dialogTitle: 'Hello', dialogBody: 'World!', diff --git a/src/client/pages/theme-editor.vue b/src/client/pages/theme-editor.vue index db273746a8ebf24b53c7122e5c105b8633e4a04c..ce8bae4ff538ac8b524fb65724a754ac80c38cea 100644 --- a/src/client/pages/theme-editor.vue +++ b/src/client/pages/theme-editor.vue @@ -42,7 +42,7 @@ </FormTextarea> <FormButton @click="applyThemeCode" primary>{{ $ts.apply }}</FormButton> </FormGroup> - <FormButton v-else @click="codeEnabled = true"><Fa :icon="faCode"/> {{ $ts.editCode }}</FormButton> + <FormButton v-else @click="codeEnabled = true"><i class="fas fa-code"></i> {{ $ts.editCode }}</FormButton> <FormGroup v-if="descriptionEnabled"> <FormTextarea v-model:value="description"> @@ -52,15 +52,14 @@ <FormButton v-else @click="descriptionEnabled = true">{{ $ts.addDescription }}</FormButton> <FormGroup> - <FormButton @click="showPreview"><Fa :icon="faEye"/> {{ $ts.preview }}</FormButton> - <FormButton @click="saveAs" primary><Fa :icon="faSave"/> {{ $ts.saveAs }}</FormButton> + <FormButton @click="showPreview"><i class="fas fa-eye"></i> {{ $ts.preview }}</FormButton> + <FormButton @click="saveAs" primary><i class="fas fa-save"></i> {{ $ts.saveAs }}</FormButton> </FormGroup> </FormBase> </template> <script lang="ts"> import { defineComponent } from 'vue'; -import { faPalette, faSave, faEye, faCode } from '@fortawesome/free-solid-svg-icons'; import { toUnicode } from 'punycode/'; import * as tinycolor from 'tinycolor2'; import { v4 as uuid} from 'uuid'; @@ -90,7 +89,7 @@ export default defineComponent({ return { [symbols.PAGE_INFO]: { title: this.$ts.themeEditor, - icon: faPalette, + icon: 'fas fa-palette', }, theme: { base: 'light', @@ -129,7 +128,6 @@ export default defineComponent({ { color: 'pink', forLight: '#84667d', forDark: '#e4d1e0', forPreview: '#b12390' }, ], changed: false, - faPalette, faSave, faEye, faCode, } }, diff --git a/src/client/pages/timeline.tutorial.vue b/src/client/pages/timeline.tutorial.vue index bcbf16acc76b5466c39c1da05bb7f450fdb97e8d..620994c0da403121ca47c13cec7022a0dd373609 100644 --- a/src/client/pages/timeline.tutorial.vue +++ b/src/client/pages/timeline.tutorial.vue @@ -1,6 +1,6 @@ <template> <div class="_card tbkwesmv"> - <div class="_title"><Fa :icon="faInfoCircle"/> {{ $ts._tutorial.title }}</div> + <div class="_title"><i class="fas fa-info-circle"></i> {{ $ts._tutorial.title }}</div> <div class="_content" v-if="tutorial === 0"> <div>{{ $ts._tutorial.step1_1 }}</div> <div>{{ $ts._tutorial.step1_2 }}</div> @@ -52,22 +52,21 @@ <div class="_footer navigation"> <div class="step"> <button class="arrow _button" @click="tutorial--" :disabled="tutorial === 0"> - <Fa :icon="faChevronLeft"/> + <i class="fas fa-chevron-left"></i> </button> <span>{{ tutorial + 1 }} / 7</span> <button class="arrow _button" @click="tutorial++" :disabled="tutorial === 6"> - <Fa :icon="faChevronRight"/> + <i class="fas fa-chevron-right"></i> </button> </div> - <MkButton class="ok" @click="tutorial = -1" primary v-if="tutorial === 6"><Fa :icon="faCheck"/> {{ $ts.gotIt }}</MkButton> - <MkButton class="ok" @click="tutorial++" primary v-else><Fa :icon="faCheck"/> {{ $ts.next }}</MkButton> + <MkButton class="ok" @click="tutorial = -1" primary v-if="tutorial === 6"><i class="fas fa-check"></i> {{ $ts.gotIt }}</MkButton> + <MkButton class="ok" @click="tutorial++" primary v-else><i class="fas fa-check"></i> {{ $ts.next }}</MkButton> </div> </div> </template> <script lang="ts"> import { defineComponent } from 'vue'; -import { faInfoCircle, faChevronLeft, faChevronRight, faCheck } from '@fortawesome/free-solid-svg-icons' import MkButton from '@client/components/ui/button.vue'; export default defineComponent({ @@ -77,7 +76,6 @@ export default defineComponent({ data() { return { - faInfoCircle, faChevronLeft, faChevronRight, faCheck } }, diff --git a/src/client/pages/timeline.vue b/src/client/pages/timeline.vue index efad31c252d11aa258674bc6a92c566de4d0adae..5660d0099e8aaa0c602e2659f2d8cadf120f7a5a 100644 --- a/src/client/pages/timeline.vue +++ b/src/client/pages/timeline.vue @@ -4,18 +4,18 @@ <XPostForm v-if="$store.reactiveState.showFixedPostForm.value" class="post-form _block" fixed/> <div class="tabs _block"> <div class="left"> - <button class="_button tab" @click="() => { src = 'home'; saveSrc(); }" :class="{ active: src === 'home' }" v-tooltip="$ts._timelines.home"><Fa :icon="faHome"/></button> - <button class="_button tab" @click="() => { src = 'local'; saveSrc(); }" :class="{ active: src === 'local' }" v-tooltip="$ts._timelines.local" v-if="isLocalTimelineAvailable"><Fa :icon="faComments"/></button> - <button class="_button tab" @click="() => { src = 'social'; saveSrc(); }" :class="{ active: src === 'social' }" v-tooltip="$ts._timelines.social" v-if="isLocalTimelineAvailable"><Fa :icon="faShareAlt"/></button> - <button class="_button tab" @click="() => { src = 'global'; saveSrc(); }" :class="{ active: src === 'global' }" v-tooltip="$ts._timelines.global" v-if="isGlobalTimelineAvailable"><Fa :icon="faGlobe"/></button> + <button class="_button tab" @click="() => { src = 'home'; saveSrc(); }" :class="{ active: src === 'home' }" v-tooltip="$ts._timelines.home"><i class="fas fa-home"></i></button> + <button class="_button tab" @click="() => { src = 'local'; saveSrc(); }" :class="{ active: src === 'local' }" v-tooltip="$ts._timelines.local" v-if="isLocalTimelineAvailable"><i class="fas fa-comments"></i></button> + <button class="_button tab" @click="() => { src = 'social'; saveSrc(); }" :class="{ active: src === 'social' }" v-tooltip="$ts._timelines.social" v-if="isLocalTimelineAvailable"><i class="fas fa-share-alt"></i></button> + <button class="_button tab" @click="() => { src = 'global'; saveSrc(); }" :class="{ active: src === 'global' }" v-tooltip="$ts._timelines.global" v-if="isGlobalTimelineAvailable"><i class="fas fa-globe"></i></button> <span class="divider"></span> - <button class="_button tab" @click="() => { src = 'mentions'; saveSrc(); }" :class="{ active: src === 'mentions' }" v-tooltip="$ts.mentions"><Fa :icon="faAt"/><Fa :icon="faCircle" class="i" v-if="$i.hasUnreadMentions"/></button> - <button class="_button tab" @click="() => { src = 'directs'; saveSrc(); }" :class="{ active: src === 'directs' }" v-tooltip="$ts.directNotes"><Fa :icon="faEnvelope"/><Fa :icon="faCircle" class="i" v-if="$i.hasUnreadSpecifiedNotes"/></button> + <button class="_button tab" @click="() => { src = 'mentions'; saveSrc(); }" :class="{ active: src === 'mentions' }" v-tooltip="$ts.mentions"><i class="fas fa-at"></i><i v-if="$i.hasUnreadMentions" class="fas fa-circle i"></i></button> + <button class="_button tab" @click="() => { src = 'directs'; saveSrc(); }" :class="{ active: src === 'directs' }" v-tooltip="$ts.directNotes"><i class="fas fa-envelope"></i><i v-if="$i.hasUnreadSpecifiedNotes" class="fas fa-circle i"></i></button> </div> <div class="right"> - <button class="_button tab" @click="chooseChannel" :class="{ active: src === 'channel' }" v-tooltip="$ts.channel"><Fa :icon="faSatelliteDish"/><Fa :icon="faCircle" class="i" v-if="$i.hasUnreadChannel"/></button> - <button class="_button tab" @click="chooseAntenna" :class="{ active: src === 'antenna' }" v-tooltip="$ts.antennas"><Fa :icon="faSatellite"/><Fa :icon="faCircle" class="i" v-if="$i.hasUnreadAntenna"/></button> - <button class="_button tab" @click="chooseList" :class="{ active: src === 'list' }" v-tooltip="$ts.lists"><Fa :icon="faListUl"/></button> + <button class="_button tab" @click="chooseChannel" :class="{ active: src === 'channel' }" v-tooltip="$ts.channel"><i class="fas fa-satellite-dish"></i><i v-if="$i.hasUnreadChannel" class="fas fa-circle i"></i></button> + <button class="_button tab" @click="chooseAntenna" :class="{ active: src === 'antenna' }" v-tooltip="$ts.antennas"><i class="fas fa-satellite"></i><i v-if="$i.hasUnreadAntenna" class="fas fa-circle i"></i></button> + <button class="_button tab" @click="chooseList" :class="{ active: src === 'list' }" v-tooltip="$ts.lists"><i class="fas fa-list-ul"></i></button> </div> </div> <XTimeline ref="tl" @@ -36,8 +36,6 @@ <script lang="ts"> import { defineComponent, defineAsyncComponent, computed } from 'vue'; -import { faAngleDown, faAngleUp, faHome, faShareAlt, faGlobe, faListUl, faSatellite, faSatelliteDish, faCircle, faEllipsisH, faPencilAlt, faAt } from '@fortawesome/free-solid-svg-icons'; -import { faComments, faEnvelope, faCalendarAlt } from '@fortawesome/free-regular-svg-icons'; import Progress from '@client/scripts/loading'; import XTimeline from '@client/components/timeline.vue'; import XPostForm from '@client/components/post-form.vue'; @@ -64,14 +62,13 @@ export default defineComponent({ queue: 0, [symbols.PAGE_INFO]: computed(() => ({ title: this.$ts.timeline, - icon: this.src === 'local' ? faComments : this.src === 'social' ? faShareAlt : this.src === 'global' ? faGlobe : faHome, + icon: this.src === 'local' ? 'fas fa-comments' : this.src === 'social' ? 'fas fa-share-alt' : this.src === 'global' ? 'fas fa-globe' : 'fas fa-home', actions: [{ - icon: faCalendarAlt, + icon: 'fas fa-calendar-alt', text: this.$ts.jumpToSpecifiedDate, handler: this.timetravel }] })), - faAngleDown, faAngleUp, faHome, faShareAlt, faGlobe, faComments, faListUl, faSatellite, faSatelliteDish, faCircle, faEllipsisH, faAt, faEnvelope, }; }, diff --git a/src/client/pages/user-ap-info.vue b/src/client/pages/user-ap-info.vue index 648ecdb10ac79287f88e8982211d32d007bef89d..c08a3525711233b626cb8c1b948626470c7d3648 100644 --- a/src/client/pages/user-ap-info.vue +++ b/src/client/pages/user-ap-info.vue @@ -58,7 +58,6 @@ <script lang="ts"> import { defineAsyncComponent, defineComponent } from 'vue'; -import { faInfoCircle } from '@fortawesome/free-solid-svg-icons'; import FormObjectView from '@client/components/form/object-view.vue'; import FormTextarea from '@client/components/form/textarea.vue'; import FormLink from '@client/components/form/link.vue'; @@ -96,7 +95,7 @@ export default defineComponent({ return { [symbols.PAGE_INFO]: { title: this.$ts.userInfo, - icon: faInfoCircle + icon: 'fas fa-info-circle' }, user: null, apPromiseFactory: null, diff --git a/src/client/pages/user-info.vue b/src/client/pages/user-info.vue index 06f2e4270dce98b4c50ecee8270d180619dc3fe6..51bd5016bbe4e3f58df6bd6b4fdd91d3bf29397b 100644 --- a/src/client/pages/user-info.vue +++ b/src/client/pages/user-info.vue @@ -1,12 +1,34 @@ <template> <FormBase> - <FormGroup v-if="user"> - <template #label><MkAcct :user="user"/></template> + <FormSuspense :p="init"> + <div class="_formItem aeakzknw"> + <MkAvatar class="avatar" :user="user" :show-indicator="true"/> + </div> - <FormKeyValueView> - <template #key>ID</template> - <template #value><span class="_monospace">{{ user.id }}</span></template> - </FormKeyValueView> + <FormLink :to="userPage(user)">Profile</FormLink> + + <FormGroup> + <FormKeyValueView> + <template #key>Acct</template> + <template #value><span class="_monospace">{{ acct(user) }}</span></template> + </FormKeyValueView> + + <FormKeyValueView> + <template #key>ID</template> + <template #value><span class="_monospace">{{ user.id }}</span></template> + </FormKeyValueView> + </FormGroup> + + <FormGroup v-if="iAmModerator"> + <FormSwitch v-if="user.host == null && $i.isAdmin && (moderator || !user.isAdmin)" @update:value="toggleModerator" v-model:value="moderator">{{ $ts.moderator }}</FormSwitch> + <FormSwitch @update:value="toggleSilence" v-model:value="silenced">{{ $ts.silence }}</FormSwitch> + <FormSwitch @update:value="toggleSuspend" v-model:value="suspended">{{ $ts.suspend }}</FormSwitch> + </FormGroup> + + <FormGroup> + <FormButton v-if="user.host != null" @click="updateRemoteUser"><i class="fas fa-sync"></i> {{ $ts.updateRemoteUser }}</FormButton> + <FormButton v-if="user.host == null && iAmModerator" @click="resetPassword"><i class="fas fa-key"></i> {{ $ts.resetPassword }}</FormButton> + </FormGroup> <FormGroup> <FormLink :to="`/user-ap-info/${user.id}`">ActivityPub</FormLink> @@ -28,15 +50,15 @@ <FormObjectView tall :value="user"> <span>Raw</span> </FormObjectView> - </FormGroup> + </FormSuspense> </FormBase> </template> <script lang="ts"> import { computed, defineAsyncComponent, defineComponent } from 'vue'; -import { faExternalLinkAlt, faInfoCircle } from '@fortawesome/free-solid-svg-icons'; import FormObjectView from '@client/components/form/object-view.vue'; import FormTextarea from '@client/components/form/textarea.vue'; +import FormSwitch from '@client/components/form/switch.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'; @@ -48,11 +70,13 @@ import number from '@client/filters/number'; import bytes from '@client/filters/bytes'; import * as symbols from '@client/symbols'; import { url } from '@client/config'; +import { userPage, acct } from '@client/filters/user'; export default defineComponent({ components: { FormBase, FormTextarea, + FormSwitch, FormObjectView, FormButton, FormLink, @@ -71,33 +95,151 @@ export default defineComponent({ data() { return { [symbols.PAGE_INFO]: computed(() => ({ - title: this.$ts.userInfo, - icon: faInfoCircle, + title: this.user ? acct(this.user) : this.$ts.userInfo, + icon: 'fas fa-info-circle', actions: this.user ? [this.user.url ? { text: this.user.url, - icon: faExternalLinkAlt, + icon: 'fas fa-external-link-alt', handler: () => { window.open(this.user.url, '_blank'); } } : undefined].filter(x => x !== undefined) : [], })), + init: null, user: null, + info: null, + moderator: false, + silenced: false, + suspended: false, + } + }, + + computed: { + iAmModerator(): boolean { + return this.$i && (this.$i.isAdmin || this.$i.isModerator); } }, - mounted() { - this.fetch(); + watch: { + userId: { + handler() { + this.init = this.createFetcher(); + }, + immediate: true + } }, methods: { number, bytes, + userPage, + acct, + + createFetcher() { + if (this.iAmModerator) { + return () => Promise.all([os.api('users/show', { + userId: this.userId + }), os.api('admin/show-user', { + userId: this.userId + })]).then(([user, info]) => { + this.user = user; + this.info = info; + this.moderator = this.info.isModerator; + this.silenced = this.info.isSilenced; + this.suspended = this.info.isSuspended; + }); + } else { + return () => os.api('users/show', { + userId: this.userId + }).then((user) => { + this.user = user; + }); + } + }, + + refreshUser() { + this.init = this.createFetcher(); + }, - async fetch() { - this.user = await os.api('users/show', { - userId: this.userId + async updateRemoteUser() { + await os.apiWithDialog('federation/update-remote-user', { userId: this.user.id }); + this.refreshUser(); + }, + + async resetPassword() { + os.apiWithDialog('admin/reset-password', { + userId: this.user.id, + }, undefined, ({ password }) => { + os.dialog({ + type: 'success', + text: this.$t('newPasswordIs', { password }) + }); }); - } + }, + + async toggleSilence(v) { + const confirm = await os.dialog({ + type: 'warning', + showCancelButton: true, + text: v ? this.$ts.silenceConfirm : this.$ts.unsilenceConfirm, + }); + if (confirm.canceled) { + this.silenced = !v; + } else { + await os.api(v ? 'admin/silence-user' : 'admin/unsilence-user', { userId: this.user.id }); + await this.refreshUser(); + } + }, + + async toggleSuspend(v) { + const confirm = await os.dialog({ + type: 'warning', + showCancelButton: true, + text: v ? this.$ts.suspendConfirm : this.$ts.unsuspendConfirm, + }); + if (confirm.canceled) { + this.suspended = !v; + } else { + await os.api(v ? 'admin/suspend-user' : 'admin/unsuspend-user', { userId: this.user.id }); + await this.refreshUser(); + } + }, + + async toggleModerator(v) { + await os.api(v ? 'admin/moderators/add' : 'admin/moderators/remove', { userId: this.user.id }); + await this.refreshUser(); + }, + + async deleteAllFiles() { + const confirm = await os.dialog({ + type: 'warning', + showCancelButton: true, + text: this.$ts.deleteAllFilesConfirm, + }); + if (confirm.canceled) return; + const process = async () => { + await os.api('admin/delete-all-files-of-a-user', { userId: this.user.id }); + os.success(); + }; + await process().catch(e => { + os.dialog({ + type: 'error', + text: e.toString() + }); + }); + await this.refreshUser(); + }, } }); </script> + +<style lang="scss" scoped> +.aeakzknw { + > .avatar { + display: block; + margin: 0 auto; + width: 64px; + height: 64px; + } +} +</style> diff --git a/src/client/pages/user/index.activity.vue b/src/client/pages/user/index.activity.vue index 3eca1ab210aa767a215f1a1667b505a3d0d78b71..9101c8ae5f7a8128a16a1bc92b5380cd9c9208e9 100644 --- a/src/client/pages/user/index.activity.vue +++ b/src/client/pages/user/index.activity.vue @@ -1,6 +1,6 @@ <template> <MkContainer> - <template #header><Fa :icon="faChartBar" style="margin-right: 0.5em;"/>{{ $ts.activity }}</template> + <template #header><i class="fas fa-chart-bar" style="margin-right: 0.5em;"></i>{{ $ts.activity }}</template> <div style="padding: 8px;"> <div ref="chart"></div> @@ -11,7 +11,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; import ApexCharts from 'apexcharts'; -import { faChartBar } from '@fortawesome/free-solid-svg-icons'; import * as os from '@client/os'; import MkContainer from '@client/components/ui/container.vue'; @@ -35,7 +34,6 @@ export default defineComponent({ fetching: true, data: [], peak: null, - faChartBar, }; }, mounted() { diff --git a/src/client/pages/user/index.photos.vue b/src/client/pages/user/index.photos.vue index 21d84cef4f8cebf2620b0bf7dbb694b815198b35..a899b116e5259280da0df36cbc441cb18616342b 100644 --- a/src/client/pages/user/index.photos.vue +++ b/src/client/pages/user/index.photos.vue @@ -1,6 +1,6 @@ <template> <MkContainer :max-height="300" :foldable="true"> - <template #header><Fa :icon="faImage" style="margin-right: 0.5em;"/>{{ $ts.images }}</template> + <template #header><i class="fas fa-image" style="margin-right: 0.5em;"></i>{{ $ts.images }}</template> <div class="ujigsodd"> <MkLoading v-if="fetching"/> <div class="stream" v-if="!fetching && images.length > 0"> @@ -19,7 +19,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faImage } from '@fortawesome/free-solid-svg-icons'; import { getStaticImageUrl } from '@client/scripts/get-static-image-url'; import notePage from '../../filters/note'; import * as os from '@client/os'; @@ -41,7 +40,6 @@ export default defineComponent({ return { fetching: true, images: [], - faImage }; }, mounted() { diff --git a/src/client/pages/user/index.vue b/src/client/pages/user/index.vue index 92656fff2cdabfc511fd2f7d7dc77fb5b4c4c02a..207b44f631bb49e7003159abefb6e45a5c518f0d 100644 --- a/src/client/pages/user/index.vue +++ b/src/client/pages/user/index.vue @@ -34,15 +34,15 @@ </div> <div class="fields system"> <dl class="field" v-if="user.location"> - <dt class="name"><Fa :icon="faMapMarker" fixed-width/> {{ $ts.location }}</dt> + <dt class="name"><i class="fas fa-map-marker fa-fw"></i> {{ $ts.location }}</dt> <dd class="value">{{ user.location }}</dd> </dl> <dl class="field" v-if="user.birthday"> - <dt class="name"><Fa :icon="faBirthdayCake" fixed-width/> {{ $ts.birthday }}</dt> + <dt class="name"><i class="fas fa-birthday-cake fa-fw"></i> {{ $ts.birthday }}</dt> <dd class="value">{{ user.birthday.replace('-', '/').replace('-', '/') }} ({{ $t('yearsOld', { age }) }})</dd> </dl> <dl class="field"> - <dt class="name"><Fa :icon="faCalendarAlt" fixed-width/> {{ $ts.registeredDate }}</dt> + <dt class="name"><i class="fas fa-calendar-alt fa-fw"></i> {{ $ts.registeredDate }}</dt> <dd class="value">{{ new Date(user.createdAt).toLocaleString() }} (<MkTime :time="user.createdAt"/>)</dd> </dl> </div> @@ -62,19 +62,19 @@ <div class="main"> <div class="nav _gap"> <MkA :to="userPage(user)" :class="{ active: page === 'index' }" class="link"> - <Fa :icon="faCommentAlt" class="icon"/> + <i class="fas fa-comment-alt icon"></i> <span>{{ $ts.notes }}</span> </MkA> <MkA :to="userPage(user, 'clips')" :class="{ active: page === 'clips' }" class="link"> - <Fa :icon="faPaperclip" class="icon"/> + <i class="fas fa-paperclip icon"></i> <span>{{ $ts.clips }}</span> </MkA> <MkA :to="userPage(user, 'pages')" :class="{ active: page === 'pages' }" class="link"> - <Fa :icon="faFileAlt" class="icon"/> + <i class="fas fa-file-alt icon"></i> <span>{{ $ts.pages }}</span> </MkA> <div class="actions"> - <button @click="menu" class="menu _button"><Fa :icon="faEllipsisH"/></button> + <button @click="menu" class="menu _button"><i class="fas fa-ellipsis-h"></i></button> <MkFollowButton v-if="!$i || $i.id != user.id" :user="user" :inline="true" :transparent="false" :full="true" large class="koudoku"/> </div> </div> @@ -95,8 +95,8 @@ </div> <div class="ftskorzw narrow _root" v-else-if="user && narrow === true" v-size="{ max: [500] }"> <!-- TODO --> - <!-- <div class="punished" v-if="user.isSuspended"><Fa :icon="faExclamationTriangle" style="margin-right: 8px;"/> {{ $ts.userSuspended }}</div> --> - <!-- <div class="punished" v-if="user.isSilenced"><Fa :icon="faExclamationTriangle" style="margin-right: 8px;"/> {{ $ts.userSilenced }}</div> --> + <!-- <div class="punished" v-if="user.isSuspended"><i class="fas fa-exclamation-triangle" style="margin-right: 8px;"></i> {{ $ts.userSuspended }}</div> --> + <!-- <div class="punished" v-if="user.isSilenced"><i class="fas fa-exclamation-triangle" style="margin-right: 8px;"></i> {{ $ts.userSilenced }}</div> --> <div class="profile"> <MkRemoteCaution v-if="user.host != null" :href="user.url" class="warn"/> @@ -109,15 +109,15 @@ <MkUserName class="name" :user="user" :nowrap="true"/> <div class="bottom"> <span class="username"><MkAcct :user="user" :detail="true" /></span> - <span v-if="user.isAdmin" :title="$ts.isAdmin" style="color: var(--badge);"><Fa :icon="faBookmark"/></span> - <span v-if="!user.isAdmin && user.isModerator" :title="$ts.isModerator" style="color: var(--badge);"><Fa :icon="farBookmark"/></span> - <span v-if="user.isLocked" :title="$ts.isLocked"><Fa :icon="faLock"/></span> - <span v-if="user.isBot" :title="$ts.isBot"><Fa :icon="faRobot"/></span> + <span v-if="user.isAdmin" :title="$ts.isAdmin" style="color: var(--badge);"><i class="fas fa-bookmark"></i></span> + <span v-if="!user.isAdmin && user.isModerator" :title="$ts.isModerator" style="color: var(--badge);"><i class="far fa-bookmark"></i></span> + <span v-if="user.isLocked" :title="$ts.isLocked"><i class="fas fa-lock"></i></span> + <span v-if="user.isBot" :title="$ts.isBot"><i class="fas fa-robot"></i></span> </div> </div> <span class="followed" v-if="$i && $i.id != user.id && user.isFollowed">{{ $ts.followsYou }}</span> <div class="actions" v-if="$i"> - <button @click="menu" class="menu _button"><Fa :icon="faEllipsisH"/></button> + <button @click="menu" class="menu _button"><i class="fas fa-ellipsis-h"></i></button> <MkFollowButton v-if="$i.id != user.id" :user="user" :inline="true" :transparent="false" :full="true" class="koudoku"/> </div> </div> @@ -126,10 +126,10 @@ <MkUserName :user="user" :nowrap="false" class="name"/> <div class="bottom"> <span class="username"><MkAcct :user="user" :detail="true" /></span> - <span v-if="user.isAdmin" :title="$ts.isAdmin" style="color: var(--badge);"><Fa :icon="faBookmark"/></span> - <span v-if="!user.isAdmin && user.isModerator" :title="$ts.isModerator" style="color: var(--badge);"><Fa :icon="farBookmark"/></span> - <span v-if="user.isLocked" :title="$ts.isLocked"><Fa :icon="faLock"/></span> - <span v-if="user.isBot" :title="$ts.isBot"><Fa :icon="faRobot"/></span> + <span v-if="user.isAdmin" :title="$ts.isAdmin" style="color: var(--badge);"><i class="fas fa-bookmark"></i></span> + <span v-if="!user.isAdmin && user.isModerator" :title="$ts.isModerator" style="color: var(--badge);"><i class="far fa-bookmark"></i></span> + <span v-if="user.isLocked" :title="$ts.isLocked"><i class="fas fa-lock"></i></span> + <span v-if="user.isBot" :title="$ts.isBot"><i class="fas fa-robot"></i></span> </div> </div> <div class="description"> @@ -138,15 +138,15 @@ </div> <div class="fields system"> <dl class="field" v-if="user.location"> - <dt class="name"><Fa :icon="faMapMarker" fixed-width/> {{ $ts.location }}</dt> + <dt class="name"><i class="fas fa-map-marker fa-fw"></i> {{ $ts.location }}</dt> <dd class="value">{{ user.location }}</dd> </dl> <dl class="field" v-if="user.birthday"> - <dt class="name"><Fa :icon="faBirthdayCake" fixed-width/> {{ $ts.birthday }}</dt> + <dt class="name"><i class="fas fa-birthday-cake fa-fw"></i> {{ $ts.birthday }}</dt> <dd class="value">{{ user.birthday.replace('-', '/').replace('-', '/') }} ({{ $t('yearsOld', { age }) }})</dd> </dl> <dl class="field"> - <dt class="name"><Fa :icon="faCalendarAlt" fixed-width/> {{ $ts.registeredDate }}</dt> + <dt class="name"><i class="fas fa-calendar-alt fa-fw"></i> {{ $ts.registeredDate }}</dt> <dd class="value">{{ new Date(user.createdAt).toLocaleString() }} (<MkTime :time="user.createdAt"/>)</dd> </dl> </div> @@ -180,22 +180,22 @@ <div class="contents"> <div class="nav _gap"> <MkA :to="userPage(user)" :class="{ active: page === 'index' }" class="link"> - <Fa :icon="faCommentAlt" class="icon"/> + <i class="fas fa-comment-alt icon"></i> <span>{{ $ts.notes }}</span> </MkA> <MkA :to="userPage(user, 'clips')" :class="{ active: page === 'clips' }" class="link"> - <Fa :icon="faPaperclip" class="icon"/> + <i class="fas fa-paperclip icon"></i> <span>{{ $ts.clips }}</span> </MkA> <MkA :to="userPage(user, 'pages')" :class="{ active: page === 'pages' }" class="link"> - <Fa :icon="faFileAlt" class="icon"/> + <i class="fas fa-file-alt icon"></i> <span>{{ $ts.pages }}</span> </MkA> </div> <template v-if="page === 'index'"> <div> - <div v-if="user.pinnedNotes.length > 0"> + <div v-if="user.pinnedNotes.length > 0" class="_gap"> <XNote v-for="note in user.pinnedNotes" class="note _block" :note="note" @update:note="pinnedNoteUpdated(note, $event)" :key="note.id" :pinned="true"/> </div> <MkInfo v-else-if="$i && $i.id === user.id">{{ $ts.userPagePinTip }}</MkInfo> @@ -219,8 +219,6 @@ <script lang="ts"> import { defineComponent, defineAsyncComponent, computed } from 'vue'; -import { faExclamationTriangle, faEllipsisH, faRobot, faLock, faBookmark, faChartBar, faImage, faBirthdayCake, faMapMarker, faPaperclip, faFileAlt } from '@fortawesome/free-solid-svg-icons'; -import { faCalendarAlt, faBookmark as farBookmark, faCommentAlt } from '@fortawesome/free-regular-svg-icons'; import * as age from 's-age'; import XUserTimeline from './index.timeline.vue'; import XNote from '@client/components/note.vue'; @@ -284,7 +282,6 @@ export default defineComponent({ error: null, parallaxAnimationId: null, narrow: null, - faExclamationTriangle, faEllipsisH, faRobot, faLock, faBookmark, farBookmark, faChartBar, faImage, faBirthdayCake, faMapMarker, faCalendarAlt, faCommentAlt, faPaperclip, faFileAlt, }; }, diff --git a/src/client/pages/v.vue b/src/client/pages/v.vue index 37a850b6252e7261ecd58183693841d13dadf274..4440e8070e6ec392eb3009834d88f0e5ee5a3a1c 100644 --- a/src/client/pages/v.vue +++ b/src/client/pages/v.vue @@ -12,7 +12,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faInfoCircle } from '@fortawesome/free-solid-svg-icons'; import { version } from '@client/config'; import * as symbols from '@client/symbols'; @@ -24,7 +23,6 @@ export default defineComponent({ icon: null }, version, - faInfoCircle } }, }); diff --git a/src/client/pages/welcome.entrance.a.vue b/src/client/pages/welcome.entrance.a.vue index 7b02c4492368893d569421c9a972616b38915a26..da3c69426575ae64dc6ec8700b69145fcc5513ce 100644 --- a/src/client/pages/welcome.entrance.a.vue +++ b/src/client/pages/welcome.entrance.a.vue @@ -43,7 +43,7 @@ <template #n><b>{{ onlineUsersCount }}</b></template> </I18n> </div> - <button class="_button _acrylic menu" @click="showMenu"><Fa :icon="faEllipsisH"/></button> + <button class="_button _acrylic menu" @click="showMenu"><i class="fas fa-ellipsis-h"></i></button> </div> </div> </div> @@ -52,7 +52,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faEllipsisH, faInfoCircle, faQuestionCircle } from '@fortawesome/free-solid-svg-icons'; import { toUnicode } from 'punycode/'; import XSigninDialog from '@client/components/signin-dialog.vue'; import XSignupDialog from '@client/components/signup-dialog.vue'; @@ -80,7 +79,6 @@ export default defineComponent({ stats: null, tags: [], onlineUsersCount: null, - faEllipsisH }; }, @@ -121,19 +119,19 @@ export default defineComponent({ showMenu(ev) { os.modalMenu([{ text: this.$t('aboutX', { x: instanceName }), - icon: faInfoCircle, + icon: 'fas fa-info-circle', action: () => { os.pageWindow('/about'); } }, { text: this.$ts.aboutMisskey, - icon: faInfoCircle, + icon: 'fas fa-info-circle', action: () => { os.pageWindow('/about-misskey'); } }, null, { text: this.$ts.help, - icon: faQuestionCircle, + icon: 'fas fa-question-circle', action: () => { os.pageWindow('/docs'); } diff --git a/src/client/pages/welcome.entrance.b.vue b/src/client/pages/welcome.entrance.b.vue index d8622e4d8e652083c12bef050c029799f04d7c1c..d108eb7d94e033b44c69b83fdd413b374b0ec12d 100644 --- a/src/client/pages/welcome.entrance.b.vue +++ b/src/client/pages/welcome.entrance.b.vue @@ -36,7 +36,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faEllipsisH, faInfoCircle, faQuestionCircle } from '@fortawesome/free-solid-svg-icons'; import { toUnicode } from 'punycode/'; import XSigninDialog from '@client/components/signin-dialog.vue'; import XSignupDialog from '@client/components/signup-dialog.vue'; @@ -64,7 +63,6 @@ export default defineComponent({ stats: null, tags: [], onlineUsersCount: null, - faEllipsisH }; }, @@ -105,19 +103,19 @@ export default defineComponent({ showMenu(ev) { os.modalMenu([{ text: this.$t('aboutX', { x: instanceName }), - icon: faInfoCircle, + icon: 'fas fa-info-circle', action: () => { os.pageWindow('/about'); } }, { text: this.$ts.aboutMisskey, - icon: faInfoCircle, + icon: 'fas fa-info-circle', action: () => { os.pageWindow('/about-misskey'); } }, null, { text: this.$ts.help, - icon: faQuestionCircle, + icon: 'fas fa-question-circle', action: () => { os.pageWindow('/docs'); } diff --git a/src/client/pages/welcome.entrance.c.vue b/src/client/pages/welcome.entrance.c.vue index 47ddf9e5ed5e0d4a497bd88b41ba6d8f4805df50..93811e98fb5dbc04961940b16368b1c838377c27 100644 --- a/src/client/pages/welcome.entrance.c.vue +++ b/src/client/pages/welcome.entrance.c.vue @@ -40,7 +40,7 @@ <template #n><b>{{ onlineUsersCount }}</b></template> </I18n> </div> - <button class="_button _acrylic menu" @click="showMenu"><Fa :icon="faEllipsisH"/></button> + <button class="_button _acrylic menu" @click="showMenu"><i class="fas fa-ellipsis-h"></i></button> </div> </div> <nav class="nav"> @@ -56,7 +56,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faEllipsisH, faInfoCircle, faQuestionCircle } from '@fortawesome/free-solid-svg-icons'; import { toUnicode } from 'punycode/'; import XSigninDialog from '@client/components/signin-dialog.vue'; import XSignupDialog from '@client/components/signup-dialog.vue'; @@ -84,7 +83,6 @@ export default defineComponent({ stats: null, tags: [], onlineUsersCount: null, - faEllipsisH }; }, @@ -125,19 +123,19 @@ export default defineComponent({ showMenu(ev) { os.modalMenu([{ text: this.$t('aboutX', { x: instanceName }), - icon: faInfoCircle, + icon: 'fas fa-info-circle', action: () => { os.pageWindow('/about'); } }, { text: this.$ts.aboutMisskey, - icon: faInfoCircle, + icon: 'fas fa-info-circle', action: () => { os.pageWindow('/about-misskey'); } }, null, { text: this.$ts.help, - icon: faQuestionCircle, + icon: 'fas fa-question-circle', action: () => { os.pageWindow('/docs'); } diff --git a/src/client/pages/welcome.setup.vue b/src/client/pages/welcome.setup.vue index db64f6b1944e14c78fd0e224fbae11f70cfca81e..2a71e2311ca0e6dc59ba5c594a477cff3023aa86 100644 --- a/src/client/pages/welcome.setup.vue +++ b/src/client/pages/welcome.setup.vue @@ -10,7 +10,7 @@ </MkInput> <MkInput v-model:value="password" type="password"> <span>{{ $ts.password }}</span> - <template #prefix><Fa :icon="faLock"/></template> + <template #prefix><i class="fas fa-lock"></i></template> </MkInput> <footer> <MkButton primary type="submit" :disabled="submitting">{{ submitting ? $ts.processing : $ts.done }}<MkEllipsis v-if="submitting"/></MkButton> @@ -21,7 +21,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faLock } from '@fortawesome/free-solid-svg-icons'; import MkButton from '@client/components/ui/button.vue'; import MkInput from '@client/components/ui/input.vue'; import { host } from '@client/config'; @@ -40,7 +39,6 @@ export default defineComponent({ password: '', submitting: false, host, - faLock } }, diff --git a/src/client/router.ts b/src/client/router.ts index bf45c806e21fd2a632a4c35365c96223f6208aed..26a4dac4994807b1ddf83dce8ffa436a052e927a 100644 --- a/src/client/router.ts +++ b/src/client/router.ts @@ -59,17 +59,8 @@ export const router = createRouter({ { path: '/my/antennas', component: page('my-antennas/index') }, { path: '/my/clips', component: page('my-clips/index') }, { path: '/scratchpad', component: page('scratchpad') }, + { path: '/instance/:page(.*)?', component: page('instance/index'), props: route => ({ initialPage: route.params.page || null }) }, { path: '/instance', component: page('instance/index') }, - { path: '/instance/emojis', component: page('instance/emojis') }, - { path: '/instance/users', component: page('instance/users') }, - { path: '/instance/logs', component: page('instance/logs') }, - { path: '/instance/files', component: page('instance/files') }, - { path: '/instance/queue', component: page('instance/queue') }, - { path: '/instance/settings', component: page('instance/settings') }, - { path: '/instance/federation', component: page('instance/federation') }, - { path: '/instance/relays', component: page('instance/relays') }, - { path: '/instance/announcements', component: page('instance/announcements') }, - { path: '/instance/abuses', component: page('instance/abuses') }, { path: '/notes/:note', name: 'note', component: page('note'), props: route => ({ noteId: route.params.note }) }, { path: '/tags/:tag', component: page('tag'), props: route => ({ tag: route.params.tag }) }, { path: '/user-info/:user', component: page('user-info'), props: route => ({ userId: route.params.user }) }, diff --git a/src/client/scripts/get-user-menu.ts b/src/client/scripts/get-user-menu.ts index 0496e8750263c7643211f77b35b0eea13f05b83b..ceb2bfe1730342403f1a86d359b19696223eca67 100644 --- a/src/client/scripts/get-user-menu.ts +++ b/src/client/scripts/get-user-menu.ts @@ -1,5 +1,3 @@ -import { faAt, faListUl, faEye, faEyeSlash, faBan, faPencilAlt, faComments, faUsers, faMicrophoneSlash, faPlug, faExclamationCircle, faInfoCircle } from '@fortawesome/free-solid-svg-icons'; -import { faSnowflake, faEnvelope } from '@fortawesome/free-regular-svg-icons'; import { i18n } from '@client/i18n'; import copyToClipboard from '@client/scripts/copy-to-clipboard'; import { host } from '@client/config'; @@ -121,62 +119,62 @@ export function getUserMenu(user) { } let menu = [{ - icon: faAt, + icon: 'fas fa-at', text: i18n.locale.copyUsername, action: () => { copyToClipboard(`@${user.username}@${user.host || host}`); } }, { - icon: faInfoCircle, + icon: 'fas fa-info-circle', text: i18n.locale.info, action: () => { os.pageWindow(`/user-info/${user.id}`); } }, { - icon: faEnvelope, + icon: 'fas fa-envelope', text: i18n.locale.sendMessage, action: () => { os.post({ specified: user }); } }, meId != user.id ? { type: 'link', - icon: faComments, + icon: 'fas fa-comments', text: i18n.locale.startMessaging, to: '/my/messaging/' + getAcct(user), } : undefined, null, { - icon: faListUl, + icon: 'fas fa-list-ul', text: i18n.locale.addToList, action: pushList }, meId != user.id ? { - icon: faUsers, + icon: 'fas fa-users', text: i18n.locale.inviteToGroup, action: inviteGroup } : undefined] as any; if ($i && meId != user.id) { menu = menu.concat([null, { - icon: user.isMuted ? faEye : faEyeSlash, + icon: user.isMuted ? 'fas fa-eye' : 'fas fa-eye-slash', text: user.isMuted ? i18n.locale.unmute : i18n.locale.mute, action: toggleMute }, { - icon: faBan, + icon: 'fas fa-ban', text: user.isBlocking ? i18n.locale.unblock : i18n.locale.block, action: toggleBlock }]); menu = menu.concat([null, { - icon: faExclamationCircle, + icon: 'fas fa-exclamation-circle', text: i18n.locale.reportAbuse, action: reportAbuse }]); if ($i && ($i.isAdmin || $i.isModerator)) { menu = menu.concat([null, { - icon: faMicrophoneSlash, + icon: 'fas fa-microphone-slash', text: user.isSilenced ? i18n.locale.unsilence : i18n.locale.silence, action: toggleSilence }, { - icon: faSnowflake, + icon: 'fas fa-snowflake', text: user.isSuspended ? i18n.locale.unsuspend : i18n.locale.suspend, action: toggleSuspend }]); @@ -185,7 +183,7 @@ export function getUserMenu(user) { if ($i && meId === user.id) { menu = menu.concat([null, { - icon: faPencilAlt, + icon: 'fas fa-pencil-alt', text: i18n.locale.editProfile, action: () => { router.push('/settings/profile'); @@ -195,7 +193,7 @@ export function getUserMenu(user) { if (userActions.length > 0) { menu = menu.concat([null, ...userActions.map(action => ({ - icon: faPlug, + icon: 'fas fa-plug', text: action.title, action: () => { action.handler(user); diff --git a/src/client/scripts/hpml/index.ts b/src/client/scripts/hpml/index.ts index 924cd32eb59d766a30afe229ed380a635105e513..ac81eac2d987e1579ac6b9d2b1cbd140ffc452ed 100644 --- a/src/client/scripts/hpml/index.ts +++ b/src/client/scripts/hpml/index.ts @@ -3,14 +3,6 @@ */ import autobind from 'autobind-decorator'; -import { - faMagic, - faSquareRootAlt, - faAlignLeft, - faList, - faQuoteRight, - faSortNumericUp, -} from '@fortawesome/free-solid-svg-icons'; import { Hpml } from './evaluator'; import { funcDefs } from './lib'; @@ -22,13 +14,13 @@ export type Fn = { export type Type = 'string' | 'number' | 'boolean' | 'stringArray' | null; export const literalDefs: Record<string, { out: any; category: string; icon: any; }> = { - text: { out: 'string', category: 'value', icon: faQuoteRight, }, - multiLineText: { out: 'string', category: 'value', icon: faAlignLeft, }, - textList: { out: 'stringArray', category: 'value', icon: faList, }, - number: { out: 'number', category: 'value', icon: faSortNumericUp, }, - ref: { out: null, category: 'value', icon: faMagic, }, - aiScriptVar: { out: null, category: 'value', icon: faMagic, }, - fn: { out: 'function', category: 'value', icon: faSquareRootAlt, }, + text: { out: 'string', category: 'value', icon: 'fas fa-quote-right', }, + multiLineText: { out: 'string', category: 'value', icon: 'fas fa-align-left', }, + textList: { out: 'stringArray', category: 'value', icon: 'fas fa-list', }, + number: { out: 'number', category: 'value', icon: 'fas fa-sort-numeric-up', }, + ref: { out: null, category: 'value', icon: 'fas fa-magic', }, + aiScriptVar: { out: null, category: 'value', icon: 'fas fa-magic', }, + fn: { out: 'function', category: 'value', icon: 'fas fa-square-root-alt', }, }; export const blockDefs = [ diff --git a/src/client/scripts/hpml/lib.ts b/src/client/scripts/hpml/lib.ts index 745456218410753d425f5730e5cd7454159a6916..150a04732f6d497fb4c86210366a2f976da7a633 100644 --- a/src/client/scripts/hpml/lib.ts +++ b/src/client/scripts/hpml/lib.ts @@ -6,27 +6,6 @@ import { Fn, HpmlScope } from '.'; import { Expr } from './expr'; import * as seedrandom from 'seedrandom'; -import { - faShareAlt, - faPlus, - faMinus, - faTimes, - faDivide, - faQuoteRight, - faEquals, - faGreaterThan, - faLessThan, - faGreaterThanEqual, - faLessThanEqual, - faNotEqual, - faDice, - faExchangeAlt, - faRecycle, - faIndent, - faCalculator, -} from '@fortawesome/free-solid-svg-icons'; -import { faFlag } from '@fortawesome/free-regular-svg-icons'; - // https://stackoverflow.com/questions/38493564/chart-area-background-color-chartjs Chart.pluginService.register({ beforeDraw: (chart, easing) => { @@ -148,43 +127,43 @@ export function initAiLib(hpml: Hpml) { } export const funcDefs: Record<string, { in: any[]; out: any; category: string; icon: any; }> = { - if: { in: ['boolean', 0, 0], out: 0, category: 'flow', icon: faShareAlt, }, - for: { in: ['number', 'function'], out: null, category: 'flow', icon: faRecycle, }, - not: { in: ['boolean'], out: 'boolean', category: 'logical', icon: faFlag, }, - or: { in: ['boolean', 'boolean'], out: 'boolean', category: 'logical', icon: faFlag, }, - and: { in: ['boolean', 'boolean'], out: 'boolean', category: 'logical', icon: faFlag, }, - add: { in: ['number', 'number'], out: 'number', category: 'operation', icon: faPlus, }, - subtract: { in: ['number', 'number'], out: 'number', category: 'operation', icon: faMinus, }, - multiply: { in: ['number', 'number'], out: 'number', category: 'operation', icon: faTimes, }, - divide: { in: ['number', 'number'], out: 'number', category: 'operation', icon: faDivide, }, - mod: { in: ['number', 'number'], out: 'number', category: 'operation', icon: faDivide, }, - round: { in: ['number'], out: 'number', category: 'operation', icon: faCalculator, }, - eq: { in: [0, 0], out: 'boolean', category: 'comparison', icon: faEquals, }, - notEq: { in: [0, 0], out: 'boolean', category: 'comparison', icon: faNotEqual, }, - gt: { in: ['number', 'number'], out: 'boolean', category: 'comparison', icon: faGreaterThan, }, - lt: { in: ['number', 'number'], out: 'boolean', category: 'comparison', icon: faLessThan, }, - gtEq: { in: ['number', 'number'], out: 'boolean', category: 'comparison', icon: faGreaterThanEqual, }, - ltEq: { in: ['number', 'number'], out: 'boolean', category: 'comparison', icon: faLessThanEqual, }, - strLen: { in: ['string'], out: 'number', category: 'text', icon: faQuoteRight, }, - strPick: { in: ['string', 'number'], out: 'string', category: 'text', icon: faQuoteRight, }, - strReplace: { in: ['string', 'string', 'string'], out: 'string', category: 'text', icon: faQuoteRight, }, - strReverse: { in: ['string'], out: 'string', category: 'text', icon: faQuoteRight, }, - join: { in: ['stringArray', 'string'], out: 'string', category: 'text', icon: faQuoteRight, }, - stringToNumber: { in: ['string'], out: 'number', category: 'convert', icon: faExchangeAlt, }, - numberToString: { in: ['number'], out: 'string', category: 'convert', icon: faExchangeAlt, }, - splitStrByLine: { in: ['string'], out: 'stringArray', category: 'convert', icon: faExchangeAlt, }, - pick: { in: [null, 'number'], out: null, category: 'list', icon: faIndent, }, - listLen: { in: [null], out: 'number', category: 'list', icon: faIndent, }, - rannum: { in: ['number', 'number'], out: 'number', category: 'random', icon: faDice, }, - dailyRannum: { in: ['number', 'number'], out: 'number', category: 'random', icon: faDice, }, - seedRannum: { in: [null, 'number', 'number'], out: 'number', category: 'random', icon: faDice, }, - random: { in: ['number'], out: 'boolean', category: 'random', icon: faDice, }, - dailyRandom: { in: ['number'], out: 'boolean', category: 'random', icon: faDice, }, - seedRandom: { in: [null, 'number'], out: 'boolean', category: 'random', icon: faDice, }, - randomPick: { in: [0], out: 0, category: 'random', icon: faDice, }, - dailyRandomPick: { in: [0], out: 0, category: 'random', icon: faDice, }, - seedRandomPick: { in: [null, 0], out: 0, category: 'random', icon: faDice, }, - DRPWPM: { in: ['stringArray'], out: 'string', category: 'random', icon: faDice, }, // dailyRandomPickWithProbabilityMapping + if: { in: ['boolean', 0, 0], out: 0, category: 'flow', icon: 'fas fa-share-alt', }, + for: { in: ['number', 'function'], out: null, category: 'flow', icon: 'fas fa-recycle', }, + not: { in: ['boolean'], out: 'boolean', category: 'logical', icon: 'fas fa-flag', }, + or: { in: ['boolean', 'boolean'], out: 'boolean', category: 'logical', icon: 'fas fa-flag', }, + and: { in: ['boolean', 'boolean'], out: 'boolean', category: 'logical', icon: 'fas fa-flag', }, + add: { in: ['number', 'number'], out: 'number', category: 'operation', icon: 'fas fa-plus', }, + subtract: { in: ['number', 'number'], out: 'number', category: 'operation', icon: 'fas fa-minus', }, + multiply: { in: ['number', 'number'], out: 'number', category: 'operation', icon: 'fas fa-times', }, + divide: { in: ['number', 'number'], out: 'number', category: 'operation', icon: 'fas fa-divide', }, + mod: { in: ['number', 'number'], out: 'number', category: 'operation', icon: 'fas fa-divide', }, + round: { in: ['number'], out: 'number', category: 'operation', icon: 'fas fa-calculator', }, + eq: { in: [0, 0], out: 'boolean', category: 'comparison', icon: 'fas fa-equals', }, + notEq: { in: [0, 0], out: 'boolean', category: 'comparison', icon: 'fas fa-not-equal', }, + gt: { in: ['number', 'number'], out: 'boolean', category: 'comparison', icon: 'fas fa-greater-than', }, + lt: { in: ['number', 'number'], out: 'boolean', category: 'comparison', icon: 'fas fa-less-than', }, + gtEq: { in: ['number', 'number'], out: 'boolean', category: 'comparison', icon: 'fas fa-greater-than-equal', }, + ltEq: { in: ['number', 'number'], out: 'boolean', category: 'comparison', icon: 'fas fa-less-than-equal', }, + strLen: { in: ['string'], out: 'number', category: 'text', icon: 'fas fa-quote-right', }, + strPick: { in: ['string', 'number'], out: 'string', category: 'text', icon: 'fas fa-quote-right', }, + strReplace: { in: ['string', 'string', 'string'], out: 'string', category: 'text', icon: 'fas fa-quote-right', }, + strReverse: { in: ['string'], out: 'string', category: 'text', icon: 'fas fa-quote-right', }, + join: { in: ['stringArray', 'string'], out: 'string', category: 'text', icon: 'fas fa-quote-right', }, + stringToNumber: { in: ['string'], out: 'number', category: 'convert', icon: 'fas fa-exchange-alt', }, + numberToString: { in: ['number'], out: 'string', category: 'convert', icon: 'fas fa-exchange-alt', }, + splitStrByLine: { in: ['string'], out: 'stringArray', category: 'convert', icon: 'fas fa-exchange-alt', }, + pick: { in: [null, 'number'], out: null, category: 'list', icon: 'fas fa-indent', }, + listLen: { in: [null], out: 'number', category: 'list', icon: 'fas fa-indent', }, + rannum: { in: ['number', 'number'], out: 'number', category: 'random', icon: 'fas fa-dice', }, + dailyRannum: { in: ['number', 'number'], out: 'number', category: 'random', icon: 'fas fa-dice', }, + seedRannum: { in: [null, 'number', 'number'], out: 'number', category: 'random', icon: 'fas fa-dice', }, + random: { in: ['number'], out: 'boolean', category: 'random', icon: 'fas fa-dice', }, + dailyRandom: { in: ['number'], out: 'boolean', category: 'random', icon: 'fas fa-dice', }, + seedRandom: { in: [null, 'number'], out: 'boolean', category: 'random', icon: 'fas fa-dice', }, + randomPick: { in: [0], out: 0, category: 'random', icon: 'fas fa-dice', }, + dailyRandomPick: { in: [0], out: 0, category: 'random', icon: 'fas fa-dice', }, + seedRandomPick: { in: [null, 0], out: 0, category: 'random', icon: 'fas fa-dice', }, + DRPWPM: { in: ['stringArray'], out: 'string', category: 'random', icon: 'fas fa-dice', }, // dailyRandomPickWithProbabilityMapping }; export function initHpmlLib(expr: Expr, scope: HpmlScope, randomSeed: string, visitor?: any) { diff --git a/src/client/scripts/lookup-user.ts b/src/client/scripts/lookup-user.ts new file mode 100644 index 0000000000000000000000000000000000000000..269777d874b6c16b2b6fc99e1871beb9a1140336 --- /dev/null +++ b/src/client/scripts/lookup-user.ts @@ -0,0 +1,37 @@ +import parseAcct from '@/misc/acct/parse'; +import { i18n } from '@client/i18n'; +import * as os from '@client/os'; + +export async function lookupUser() { + const { canceled, result } = await os.dialog({ + title: i18n.locale.usernameOrUserId, + input: true + }); + if (canceled) return; + + const show = (user) => { + os.pageWindow(`/user-info/${user.id}`); + }; + + const usernamePromise = os.api('users/show', parseAcct(result)); + const idPromise = os.api('users/show', { userId: result }); + let _notFound = false; + const notFound = () => { + if (_notFound) { + os.dialog({ + type: 'error', + text: i18n.locale.noSuchUser + }); + } else { + _notFound = true; + } + }; + usernamePromise.then(show).catch(e => { + if (e.code === 'NO_SUCH_USER') { + notFound(); + } + }); + idPromise.then(show).catch(e => { + notFound(); + }); +} diff --git a/src/client/scripts/search.ts b/src/client/scripts/search.ts index 829065534c3e3f3e020ca2c0f2f7af7bcc93692e..2221f5f279c216fe17c12fdc7af2eb13d726b2b7 100644 --- a/src/client/scripts/search.ts +++ b/src/client/scripts/search.ts @@ -1,4 +1,3 @@ -import { faHistory } from '@fortawesome/free-solid-svg-icons'; import * as os from '@client/os'; import { i18n } from '@client/i18n'; import { router } from '@client/router'; @@ -37,7 +36,7 @@ export async function search() { // TODO //v.$root.$emit('warp', date); os.dialog({ - icon: faHistory, + icon: 'fas fa-history', iconOnly: true, autoClose: true }); return; diff --git a/src/client/scripts/select-file.ts b/src/client/scripts/select-file.ts index 03ac863aa0c61de7bf4bfce1b32c97ff3a1e2ae9..c193e7dc711b72c9260ec362ba6f6ba4140d9125 100644 --- a/src/client/scripts/select-file.ts +++ b/src/client/scripts/select-file.ts @@ -1,4 +1,3 @@ -import { faUpload, faCloud, faLink } from '@fortawesome/free-solid-svg-icons'; import * as os from '@client/os'; import { i18n } from '@client/i18n'; @@ -73,15 +72,15 @@ export function selectFile(src: any, label: string | null, multiple = false) { type: 'label' } : undefined, { text: i18n.locale.upload, - icon: faUpload, + icon: 'fas fa-upload', action: chooseFileFromPc }, { text: i18n.locale.fromDrive, - icon: faCloud, + icon: 'fas fa-cloud', action: chooseFileFromDrive }, { text: i18n.locale.fromUrl, - icon: faLink, + icon: 'fas fa-link', action: chooseFileFromUrl }], src); }); diff --git a/src/client/sidebar.ts b/src/client/sidebar.ts index 09b69fd8152258dabe84be5ca5a2d0e4989685f1..e5105f13b4578dbd13380ea2fc2c4f2bcfb0b400 100644 --- a/src/client/sidebar.ts +++ b/src/client/sidebar.ts @@ -1,5 +1,3 @@ -import { faBell, faComments, faEnvelope } from '@fortawesome/free-regular-svg-icons'; -import { faAt, faBroadcastTower, faCloud, faColumns, faDoorClosed, faFileAlt, faFireAlt, faGamepad, faHashtag, faListUl, faPaperclip, faSatellite, faSatelliteDish, faSearch, faStar, faTerminal, faUserClock, faUsers } from '@fortawesome/free-solid-svg-icons'; import { computed } from 'vue'; import { search } from '@client/scripts/search'; import * as os from '@client/os'; @@ -10,125 +8,125 @@ import { unisonReload } from '@client/scripts/unison-reload'; export const sidebarDef = { notifications: { title: 'notifications', - icon: faBell, + icon: 'fas fa-bell', show: computed(() => $i != null), indicated: computed(() => $i != null && $i.hasUnreadNotification), to: '/my/notifications', }, messaging: { title: 'messaging', - icon: faComments, + icon: 'fas fa-comments', show: computed(() => $i != null), indicated: computed(() => $i != null && $i.hasUnreadMessagingMessage), to: '/my/messaging', }, drive: { title: 'drive', - icon: faCloud, + icon: 'fas fa-cloud', show: computed(() => $i != null), to: '/my/drive', }, followRequests: { title: 'followRequests', - icon: faUserClock, + icon: 'fas fa-user-clock', show: computed(() => $i != null && $i.isLocked), indicated: computed(() => $i != null && $i.hasPendingReceivedFollowRequest), to: '/my/follow-requests', }, featured: { title: 'featured', - icon: faFireAlt, + icon: 'fas fa-fire-alt', to: '/featured', }, explore: { title: 'explore', - icon: faHashtag, + icon: 'fas fa-hashtag', to: '/explore', }, announcements: { title: 'announcements', - icon: faBroadcastTower, + icon: 'fas fa-broadcast-tower', indicated: computed(() => $i != null && $i.hasUnreadAnnouncement), to: '/announcements', }, search: { title: 'search', - icon: faSearch, + icon: 'fas fa-search', action: () => search(), }, lists: { title: 'lists', - icon: faListUl, + icon: 'fas fa-list-ul', show: computed(() => $i != null), to: '/my/lists', }, groups: { title: 'groups', - icon: faUsers, + icon: 'fas fa-users', show: computed(() => $i != null), to: '/my/groups', }, antennas: { title: 'antennas', - icon: faSatellite, + icon: 'fas fa-satellite', show: computed(() => $i != null), to: '/my/antennas', }, mentions: { title: 'mentions', - icon: faAt, + icon: 'fas fa-at', show: computed(() => $i != null), indicated: computed(() => $i != null && $i.hasUnreadMentions), to: '/my/mentions', }, messages: { title: 'directNotes', - icon: faEnvelope, + icon: 'fas fa-envelope', show: computed(() => $i != null), indicated: computed(() => $i != null && $i.hasUnreadSpecifiedNotes), to: '/my/messages', }, favorites: { title: 'favorites', - icon: faStar, + icon: 'fas fa-star', show: computed(() => $i != null), to: '/my/favorites', }, pages: { title: 'pages', - icon: faFileAlt, + icon: 'fas fa-file-alt', to: '/pages', }, clips: { title: 'clip', - icon: faPaperclip, + icon: 'fas fa-paperclip', show: computed(() => $i != null), to: '/my/clips', }, channels: { title: 'channel', - icon: faSatelliteDish, + icon: 'fas fa-satellite-dish', to: '/channels', }, games: { title: 'games', - icon: faGamepad, + icon: 'fas fa-gamepad', to: '/games/reversi', }, scratchpad: { title: 'scratchpad', - icon: faTerminal, + icon: 'fas fa-terminal', to: '/scratchpad', }, rooms: { title: 'rooms', - icon: faDoorClosed, + icon: 'fas fa-door-closed', show: computed(() => $i != null), to: computed(() => `/@${$i.username}/room`), }, ui: { title: 'switchUi', - icon: faColumns, + icon: 'fas fa-columns', action: (ev) => { os.modalMenu([{ text: i18n.locale.default, diff --git a/src/client/style.scss b/src/client/style.scss index ab8da9ccfa2c73e05c399c8ace3c07741a78f4cb..07b80d553f6ab3275f53d34723ae6b26b2da18c1 100644 --- a/src/client/style.scss +++ b/src/client/style.scss @@ -520,3 +520,27 @@ hr { transform: scale3d(1, 1, 1); } } + +._anime_bounce { + animation: bounce ease 0.7s; + animation-iteration-count: 1; + transform-origin: 50% 50%; +} +._anime_bounce_ready { + transform: scaleX(0.90) scaleY(0.90) ; +} + +@keyframes bounce{ + 0% { + transform: scaleX(0.90) scaleY(0.90) ; + } + 19% { + transform: scaleX(1.10) scaleY(1.10) ; + } + 48% { + transform: scaleX(0.95) scaleY(0.95) ; + } + 100% { + transform: scaleX(1.00) scaleY(1.00) ; + } +} diff --git a/src/client/ui/_common_/header.vue b/src/client/ui/_common_/header.vue index 493deaeb965aa76e1934dfbbe5231ba5058ce602..83aa669b44f2ad36d486340d61e1faf46625bab7 100644 --- a/src/client/ui/_common_/header.vue +++ b/src/client/ui/_common_/header.vue @@ -1,12 +1,12 @@ <template> <div class="fdidabkb" :class="{ center }" :style="`--height:${height};`" :key="key"> <transition :name="$store.state.animation ? 'header' : ''" mode="out-in" appear> - <button class="_button back" v-if="withBack && canBack" @click.stop="back()" v-tooltip="$ts.goBack"><Fa :icon="faChevronLeft"/></button> + <button class="_button back" v-if="withBack && canBack" @click.stop="back()" v-tooltip="$ts.goBack"><i class="fas fa-chevron-left"></i></button> </transition> <template v-if="info"> <div class="titleContainer"> <div class="title"> - <Fa v-if="info.icon" :icon="info.icon" :key="info.icon" class="icon"/> + <i v-if="info.icon" class="icon" :class="info.icon"></i> <MkAvatar v-else-if="info.avatar" class="avatar" :user="info.avatar" :disable-preview="true" :show-indicator="true"/> <MkUserName v-if="info.userName" :user="info.userName" :nowrap="false" class="text"/> <span v-else-if="info.title" class="text">{{ info.title }}</span> @@ -14,9 +14,9 @@ </div> <div class="buttons"> <template v-if="info.actions && showActions"> - <button v-for="action in info.actions" class="_button button" @click.stop="action.handler" v-tooltip="action.text"><Fa :icon="action.icon"/></button> + <button v-for="action in info.actions" class="_button button" @click.stop="action.handler" v-tooltip="action.text"><i :class="action.icon"></i></button> </template> - <button v-if="showMenu" class="_button button" @click.stop="menu"><Fa :icon="faEllipsisH"/></button> + <button v-if="showMenu" class="_button button" @click.stop="menu"><i class="fas fa-ellipsis-h"></i></button> </div> </template> </div> @@ -24,7 +24,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faChevronLeft, faCircle, faShareAlt, faEllipsisH } from '@fortawesome/free-solid-svg-icons'; import { modalMenu } from '@client/os'; import { url } from '@client/config'; @@ -51,7 +50,6 @@ export default defineComponent({ showActions: false, height: 0, key: 0, - faChevronLeft, faCircle, faShareAlt, faEllipsisH, }; }, @@ -111,7 +109,7 @@ export default defineComponent({ if (menu.length > 0) menu.push(null); menu.push({ text: this.$ts.share, - icon: faShareAlt, + icon: 'fas fa-share-alt', action: this.share }); } diff --git a/src/client/ui/_common_/sidebar.vue b/src/client/ui/_common_/sidebar.vue index 6243d6fcc2c545d22a238fa234988ab8cf95f4fc..df118771472462e02caa1db9fda5734254ba0f28 100644 --- a/src/client/ui/_common_/sidebar.vue +++ b/src/client/ui/_common_/sidebar.vue @@ -15,28 +15,28 @@ <MkAvatar :user="$i" class="avatar"/><MkAcct class="text" :user="$i"/> </button> <MkA class="item index" active-class="active" to="/" exact> - <Fa :icon="faHome" fixed-width/><span class="text">{{ $ts.timeline }}</span> + <i class="fas fa-home fa-fw"></i><span class="text">{{ $ts.timeline }}</span> </MkA> <template v-for="item in menu"> <div v-if="item === '-'" class="divider"></div> <component v-else-if="menuDef[item] && (menuDef[item].show !== false)" :is="menuDef[item].to ? 'MkA' : 'button'" class="item _button" :class="item" active-class="active" v-on="menuDef[item].action ? { click: menuDef[item].action } : {}" :to="menuDef[item].to"> - <Fa :icon="menuDef[item].icon" fixed-width/><span class="text">{{ $ts[menuDef[item].title] }}</span> - <i v-if="menuDef[item].indicated"><Fa :icon="faCircle"/></i> + <i class="fa-fw" :class="menuDef[item].icon"></i><span class="text">{{ $ts[menuDef[item].title] }}</span> + <span v-if="menuDef[item].indicated" class="indicator"><i class="fas fa-circle"></i></span> </component> </template> <div class="divider"></div> - <button class="item _button" :class="{ active: $route.path === '/instance' || $route.path.startsWith('/instance/') }" v-if="$i.isAdmin || $i.isModerator" @click="oepnInstanceMenu"> - <Fa :icon="faServer" fixed-width/><span class="text">{{ $ts.instance }}</span> - </button> + <MkA v-if="$i.isAdmin || $i.isModerator" class="item" active-class="active" to="/instance"> + <i class="fas fa-server fa-fw"></i><span class="text">{{ $ts.instance }}</span> + </MkA> <button class="item _button" @click="more"> - <Fa :icon="faEllipsisH" fixed-width/><span class="text">{{ $ts.more }}</span> - <i v-if="otherNavItemIndicated"><Fa :icon="faCircle"/></i> + <i class="fa fa-ellipsis-h fa-fw"></i><span class="text">{{ $ts.more }}</span> + <span v-if="otherNavItemIndicated" class="indicator"><i class="fas fa-circle"></i></span> </button> <MkA class="item" active-class="active" to="/settings"> - <Fa :icon="faCog" fixed-width/><span class="text">{{ $ts.settings }}</span> + <i class="fas fa-cog fa-fw"></i><span class="text">{{ $ts.settings }}</span> </MkA> <button class="item _button post" @click="post"> - <Fa :icon="faPencilAlt" fixed-width/><span class="text">{{ $ts.note }}</span> + <i class="fas fa-pencil-alt fa-fw"></i><span class="text">{{ $ts.note }}</span> </button> </div> </nav> @@ -46,8 +46,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faGripVertical, faChevronLeft, faHashtag, faBroadcastTower, faFireAlt, faEllipsisH, faPencilAlt, faBars, faTimes, faSearch, faUserCog, faCog, faUser, faHome, faStar, faCircle, faAt, faListUl, faPlus, faUserClock, faUsers, faTachometerAlt, faExchangeAlt, faGlobe, faChartBar, faCloud, faServer, faInfoCircle, faQuestionCircle, faProjectDiagram, faStream, faExclamationCircle } from '@fortawesome/free-solid-svg-icons'; -import { faBell, faEnvelope, faLaugh, faComments } from '@fortawesome/free-regular-svg-icons'; import { host } from '@client/config'; import { search } from '@client/scripts/search'; import * as os from '@client/os'; @@ -72,7 +70,6 @@ export default defineComponent({ menuDef: sidebarDef, iconOnly: false, hidden: this.defaultHidden, - faGripVertical, faChevronLeft, faComments, faHashtag, faBroadcastTower, faFireAlt, faEllipsisH, faPencilAlt, faBars, faTimes, faBell, faSearch, faUserCog, faCog, faUser, faHome, faStar, faCircle, faAt, faEnvelope, faListUl, faPlus, faUserClock, faLaugh, faUsers, faTachometerAlt, faExchangeAlt, faGlobe, faChartBar, faCloud, faServer, faProjectDiagram }; }, @@ -159,12 +156,12 @@ export default defineComponent({ to: `/@${ this.$i.username }`, avatar: this.$i, }, null, ...accountItemPromises, { - icon: faPlus, - text: this.$ts.addAcount, + icon: 'fas fa-plus', + text: this.$ts.addAccount, action: () => { os.modalMenu([{ - text: this.$ts.existingAcount, - action: () => { this.addAcount(); }, + text: this.$ts.existingAccount, + action: () => { this.addAccount(); }, }, { text: this.$ts.createAccount, action: () => { this.createAccount(); }, @@ -175,71 +172,12 @@ export default defineComponent({ }); }, - oepnInstanceMenu(ev) { - os.modalMenu([{ - type: 'link', - text: this.$ts.dashboard, - to: '/instance', - icon: faTachometerAlt, - }, null, this.$i.isAdmin ? { - type: 'link', - text: this.$ts.settings, - to: '/instance/settings', - icon: faCog, - } : undefined, { - type: 'link', - text: this.$ts.customEmojis, - to: '/instance/emojis', - icon: faLaugh, - }, { - type: 'link', - text: this.$ts.users, - to: '/instance/users', - icon: faUsers, - }, { - type: 'link', - text: this.$ts.files, - to: '/instance/files', - icon: faCloud, - }, { - type: 'link', - text: this.$ts.jobQueue, - to: '/instance/queue', - icon: faExchangeAlt, - }, { - type: 'link', - text: this.$ts.federation, - to: '/instance/federation', - icon: faGlobe, - }, { - type: 'link', - text: this.$ts.relays, - to: '/instance/relays', - icon: faProjectDiagram, - }, { - type: 'link', - text: this.$ts.announcements, - to: '/instance/announcements', - icon: faBroadcastTower, - }, { - type: 'link', - text: this.$ts.abuseReports, - to: '/instance/abuses', - icon: faExclamationCircle, - }, { - type: 'link', - text: this.$ts.logs, - to: '/instance/logs', - icon: faStream, - }], ev.currentTarget || ev.target); - }, - more(ev) { os.popup(import('@client/components/launch-pad.vue'), {}, { }, 'closed'); }, - addAcount() { + addAccount() { os.popup(import('@client/components/signin-dialog.vue'), {}, { done: res => { addAccount(res.id, res.i); @@ -330,7 +268,7 @@ export default defineComponent({ font-size: $ui-font-size * 1.1; line-height: 3.7rem; - > [data-icon], + > i, > .avatar { margin-right: 0; } @@ -397,11 +335,11 @@ export default defineComponent({ box-sizing: border-box; color: var(--navFg); - > [data-icon] { + > i { width: 32px; } - > [data-icon], + > i, > .avatar { margin-right: $avatar-margin; } @@ -412,7 +350,7 @@ export default defineComponent({ vertical-align: middle; } - > i { + > .indicator { position: absolute; top: 0; left: 20px; diff --git a/src/client/ui/_common_/upload.vue b/src/client/ui/_common_/upload.vue index bd3b2cd6848a876397b76b0af5b755e7c46386d3..25a807cd3638547002fb6139f1b663c195b3d301 100644 --- a/src/client/ui/_common_/upload.vue +++ b/src/client/ui/_common_/upload.vue @@ -4,7 +4,7 @@ <li v-for="ctx in uploads" :key="ctx.id"> <div class="img" :style="{ backgroundImage: `url(${ ctx.img })` }"></div> <div class="top"> - <p class="name"><Fa :icon="faSpinner" pulse/>{{ ctx.name }}</p> + <p class="name"><i class="fas fa-spinner fa-pulse"></i>{{ ctx.name }}</p> <p class="status"> <span class="initing" v-if="ctx.progressValue === undefined">{{ $ts.waiting }}<MkEllipsis/></span> <span class="kb" v-if="ctx.progressValue !== undefined">{{ String(Math.floor(ctx.progressValue / 1024)).replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1,') }}<i>KB</i> / {{ String(Math.floor(ctx.progressMax / 1024)).replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1,') }}<i>KB</i></span> @@ -19,14 +19,12 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faSpinner } from '@fortawesome/free-solid-svg-icons'; import * as os from '@client/os'; export default defineComponent({ data() { return { uploads: os.uploads, - faSpinner }; }, }); @@ -92,7 +90,7 @@ export default defineComponent({ overflow: hidden; flex-shrink: 1; } -.mk-uploader > ol > li > .top > .name > [data-icon] { +.mk-uploader > ol > li > .top > .name > i { margin-right: 4px; } .mk-uploader > ol > li > .top > .status { diff --git a/src/client/ui/chat/date-separated-list.vue b/src/client/ui/chat/date-separated-list.vue index 65deb9e1c23a605502b9de9959423c638a5a488c..b073a38eb11ba8bc6581dc12d264932468fdc08a 100644 --- a/src/client/ui/chat/date-separated-list.vue +++ b/src/client/ui/chat/date-separated-list.vue @@ -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: { @@ -57,17 +55,15 @@ export default defineComponent({ class: 'date' }, [ h('span', [ - h(FontAwesomeIcon, { - class: 'icon', - icon: faAngleUp, + h('i', { + class: 'fas fa-angle-up icon', }), getDateText(item.createdAt) ]), h('span', [ getDateText(this.items[i + 1].createdAt), - h(FontAwesomeIcon, { - class: 'icon', - icon: faAngleDown, + h('i', { + class: 'fas fa-angle-down icon', }) ]) ])); diff --git a/src/client/ui/chat/index.vue b/src/client/ui/chat/index.vue index d5c455d123e9296f9982eaa579491c6400ef43b0..b498d70a7517467065235f3785fe2501b475b031 100644 --- a/src/client/ui/chat/index.vue +++ b/src/client/ui/chat/index.vue @@ -10,63 +10,63 @@ </button> </div> <div class="right"> - <MkA class="item" to="/my/messaging" v-tooltip="$ts.messaging"><Fa class="icon" :icon="faComments"/><i v-if="$i.hasUnreadMessagingMessage"><Fa :icon="faCircle"/></i></MkA> - <MkA class="item" to="/my/messages" v-tooltip="$ts.directNotes"><Fa class="icon" :icon="faEnvelope"/><i v-if="$i.hasUnreadSpecifiedNotes"><Fa :icon="faCircle"/></i></MkA> - <MkA class="item" to="/my/mentions" v-tooltip="$ts.mentions"><Fa class="icon" :icon="faAt"/><i v-if="$i.hasUnreadMentions"><Fa :icon="faCircle"/></i></MkA> - <MkA class="item" to="/my/notifications" v-tooltip="$ts.notifications"><Fa class="icon" :icon="faBell"/><i v-if="$i.hasUnreadNotification"><Fa :icon="faCircle"/></i></MkA> + <MkA class="item" to="/my/messaging" v-tooltip="$ts.messaging"><i class="fas fa-comments icon"></i><span v-if="$i.hasUnreadMessagingMessage" class="indicator"><i class="fas fa-circle"></i></span></MkA> + <MkA class="item" to="/my/messages" v-tooltip="$ts.directNotes"><i class="fas fa-envelope icon"></i><span v-if="$i.hasUnreadSpecifiedNotes" class="indicator"><i class="fas fa-circle"></i></span></MkA> + <MkA class="item" to="/my/mentions" v-tooltip="$ts.mentions"><i class="fas fa-at icon"></i><span v-if="$i.hasUnreadMentions" class="indicator"><i class="fas fa-circle"></i></span></MkA> + <MkA class="item" to="/my/notifications" v-tooltip="$ts.notifications"><i class="fas fa-bell icon"></i><span v-if="$i.hasUnreadNotification" class="indicator"><i class="fas fa-circle"></i></span></MkA> </div> </header> <div class="body"> <div class="container"> <div class="header">{{ $ts.timeline }}</div> <div class="body"> - <MkA to="/timeline/home" class="item" :class="{ active: tl === 'home' }"><Fa :icon="faHome" class="icon"/>{{ $ts._timelines.home }}</MkA> - <MkA to="/timeline/local" class="item" :class="{ active: tl === 'local' }"><Fa :icon="faComments" class="icon"/>{{ $ts._timelines.local }}</MkA> - <MkA to="/timeline/social" class="item" :class="{ active: tl === 'social' }"><Fa :icon="faShareAlt" class="icon"/>{{ $ts._timelines.social }}</MkA> - <MkA to="/timeline/global" class="item" :class="{ active: tl === 'global' }"><Fa :icon="faGlobe" class="icon"/>{{ $ts._timelines.global }}</MkA> + <MkA to="/timeline/home" class="item" :class="{ active: tl === 'home' }"><i class="fas fa-home icon"></i>{{ $ts._timelines.home }}</MkA> + <MkA to="/timeline/local" class="item" :class="{ active: tl === 'local' }"><i class="fas fa-comments icon"></i>{{ $ts._timelines.local }}</MkA> + <MkA to="/timeline/social" class="item" :class="{ active: tl === 'social' }"><i class="fas fa-share-alt icon"></i>{{ $ts._timelines.social }}</MkA> + <MkA to="/timeline/global" class="item" :class="{ active: tl === 'global' }"><i class="fas fa-globe icon"></i>{{ $ts._timelines.global }}</MkA> </div> </div> <div class="container" v-if="followedChannels"> - <div class="header">{{ $ts.channel }} ({{ $ts.following }})<button class="_button add" @click="addChannel"><Fa :icon="faPlus"/></button></div> + <div class="header">{{ $ts.channel }} ({{ $ts.following }})<button class="_button add" @click="addChannel"><i class="fas fa-plus"></i></button></div> <div class="body"> - <MkA v-for="channel in followedChannels" :key="channel.id" :to="`/channels/${ channel.id }`" class="item" :class="{ active: tl === `channel:${ channel.id }`, read: !channel.hasUnreadNote }"><Fa :icon="faSatelliteDish" class="icon"/>{{ channel.name }}</MkA> + <MkA v-for="channel in followedChannels" :key="channel.id" :to="`/channels/${ channel.id }`" class="item" :class="{ active: tl === `channel:${ channel.id }`, read: !channel.hasUnreadNote }"><i class="fas fa-satellite-dish icon"></i>{{ channel.name }}</MkA> </div> </div> <div class="container" v-if="featuredChannels"> - <div class="header">{{ $ts.channel }}<button class="_button add" @click="addChannel"><Fa :icon="faPlus"/></button></div> + <div class="header">{{ $ts.channel }}<button class="_button add" @click="addChannel"><i class="fas fa-plus"></i></button></div> <div class="body"> - <MkA v-for="channel in featuredChannels" :key="channel.id" :to="`/channels/${ channel.id }`" class="item" :class="{ active: tl === `channel:${ channel.id }` }"><Fa :icon="faSatelliteDish" class="icon"/>{{ channel.name }}</MkA> + <MkA v-for="channel in featuredChannels" :key="channel.id" :to="`/channels/${ channel.id }`" class="item" :class="{ active: tl === `channel:${ channel.id }` }"><i class="fas fa-satellite-dish icon"></i>{{ channel.name }}</MkA> </div> </div> <div class="container" v-if="lists"> - <div class="header">{{ $ts.lists }}<button class="_button add" @click="addList"><Fa :icon="faPlus"/></button></div> + <div class="header">{{ $ts.lists }}<button class="_button add" @click="addList"><i class="fas fa-plus"></i></button></div> <div class="body"> - <MkA v-for="list in lists" :key="list.id" :to="`/my/list/${ list.id }`" class="item" :class="{ active: tl === `list:${ list.id }` }"><Fa :icon="faListUl" class="icon"/>{{ list.name }}</MkA> + <MkA v-for="list in lists" :key="list.id" :to="`/my/list/${ list.id }`" class="item" :class="{ active: tl === `list:${ list.id }` }"><i class="fas fa-list-ul icon"></i>{{ list.name }}</MkA> </div> </div> <div class="container" v-if="antennas"> - <div class="header">{{ $ts.antennas }}<button class="_button add" @click="addAntenna"><Fa :icon="faPlus"/></button></div> + <div class="header">{{ $ts.antennas }}<button class="_button add" @click="addAntenna"><i class="fas fa-plus"></i></button></div> <div class="body"> - <MkA v-for="antenna in antennas" :key="antenna.id" :to="`/my/antenna/${ antenna.id }`" class="item" :class="{ active: tl === `antenna:${ antenna.id }` }"><Fa :icon="faSatellite" class="icon"/>{{ antenna.name }}</MkA> + <MkA v-for="antenna in antennas" :key="antenna.id" :to="`/my/antenna/${ antenna.id }`" class="item" :class="{ active: tl === `antenna:${ antenna.id }` }"><i class="fas fa-satellite icon"></i>{{ antenna.name }}</MkA> </div> </div> <div class="container"> <div class="body"> - <MkA to="/my/favorites" class="item"><Fa :icon="faStar" class="icon"/>{{ $ts.favorites }}</MkA> + <MkA to="/my/favorites" class="item"><i class="fas fa-star icon"></i>{{ $ts.favorites }}</MkA> </div> </div> </div> <footer class="footer"> <div class="left"> <button class="_button menu" @click="showMenu"> - <Fa class="icon" :icon="faBars"/> + <i class="fas fa-bars icon"></i> </button> </div> <div class="right"> <button class="_button item search" @click="search" v-tooltip="$ts.search"> - <Fa :icon="faSearch"/> + <i class="fas fa-search"></i> </button> - <MkA class="item" to="/settings" v-tooltip="$ts.settings"><Fa class="icon" :icon="faCog"/></MkA> + <MkA class="item" to="/settings" v-tooltip="$ts.settings"><i class="fas fa-cog icon"></i></MkA> </div> </footer> </div> @@ -75,23 +75,23 @@ <header class="header" ref="header" @click="onHeaderClick"> <div class="left"> <template v-if="tl === 'home'"> - <Fa :icon="faHome" class="icon"/> + <i class="fas fa-home icon"></i> <div class="title">{{ $ts._timelines.home }}</div> </template> <template v-else-if="tl === 'local'"> - <Fa :icon="faComments" class="icon"/> + <i class="fas fa-comments icon"></i> <div class="title">{{ $ts._timelines.local }}</div> </template> <template v-else-if="tl === 'social'"> - <Fa :icon="faShareAlt" class="icon"/> + <i class="fas fa-share-alt icon"></i> <div class="title">{{ $ts._timelines.social }}</div> </template> <template v-else-if="tl === 'global'"> - <Fa :icon="faGlobe" class="icon"/> + <i class="fas fa-globe icon"></i> <div class="title">{{ $ts._timelines.global }}</div> </template> <template v-else-if="tl.startsWith('channel:')"> - <Fa :icon="faSatelliteDish" class="icon"/> + <i class="fas fa-satellite-dish icon"></i> <div class="title" v-if="currentChannel">{{ currentChannel.name }}<div class="description">{{ currentChannel.description }}</div></div> </template> </div> @@ -100,20 +100,20 @@ <div class="instance">{{ instanceName }}</div> <XHeaderClock class="clock"/> <button class="_button button timetravel" @click="timetravel" v-tooltip="$ts.jumpToSpecifiedDate"> - <Fa :icon="faCalendarAlt"/> + <i class="fas fa-calendar-alt"></i> </button> <button class="_button button search" v-if="tl.startsWith('channel:') && currentChannel" @click="inChannelSearch" v-tooltip="$ts.inChannelSearch"> - <Fa :icon="faSearch"/> + <i class="fas fa-search"></i> </button> <button class="_button button search" v-else @click="search" v-tooltip="$ts.search"> - <Fa :icon="faSearch"/> + <i class="fas fa-search"></i> </button> <button class="_button button follow" v-if="tl.startsWith('channel:') && currentChannel" :class="{ followed: currentChannel.isFollowing }" @click="toggleChannelFollow" v-tooltip="currentChannel.isFollowing ? $ts.unfollow : $ts.follow"> - <Fa v-if="currentChannel.isFollowing" :icon="faStar"/> - <Fa v-else :icon="farStar"/> + <i v-if="currentChannel.isFollowing" class="fas fa-star"></i> + <i v-else class="far fa-star"></i> </button> <button class="_button button menu" v-if="tl.startsWith('channel:') && currentChannel" @click="openChannelMenu"> - <Fa :icon="faEllipsisH"/> + <i class="fas fa-ellipsis-h"></i> </button> </div> </header> @@ -133,8 +133,6 @@ <script lang="ts"> import { defineComponent, defineAsyncComponent } from 'vue'; -import { faLayerGroup, faBars, faHome, faCircle, faWindowMaximize, faColumns, faPencilAlt, faShareAlt, faSatelliteDish, faListUl, faSatellite, faCog, faSearch, faPlus, faStar, faAt, faLink, faEllipsisH, faGlobe } from '@fortawesome/free-solid-svg-icons'; -import { faBell, faStar as farStar, faEnvelope, faComments, faCalendarAlt } from '@fortawesome/free-regular-svg-icons'; import { instanceName, url } from '@client/config'; import XSidebar from '@client/ui/_common_/sidebar.vue'; import XWidgets from './widgets.vue'; @@ -195,7 +193,6 @@ export default defineComponent({ menuDef: sidebarDef, sideViewOpening: false, instanceName, - faLayerGroup, faBars, faBell, faHome, faCircle, faPencilAlt, faShareAlt, faSatelliteDish, faListUl, faSatellite, faCog, faSearch, faPlus, faStar, farStar, faAt, faLink, faEllipsisH, faGlobe, faComments, faEnvelope, faCalendarAlt, }; }, @@ -293,7 +290,7 @@ export default defineComponent({ openChannelMenu(ev) { os.modalMenu([{ text: this.$ts.copyUrl, - icon: faLink, + icon: 'fas fa-link', action: () => { copyToClipboard(`${url}/channels/${this.currentChannel.id}`); } @@ -323,13 +320,13 @@ export default defineComponent({ type: 'label', text: path, }, { - icon: faColumns, + icon: 'fas fa-columns', text: this.$ts.openInSideView, action: () => { this.$refs.side.navigate(path); } }, { - icon: faWindowMaximize, + icon: 'fas fa-window-maximize', text: this.$ts.openInWindow, action: () => { os.pageWindow(path); @@ -398,7 +395,7 @@ export default defineComponent({ margin: auto; } - > i { + > .indicator { position: absolute; top: 8px; right: 8px; diff --git a/src/client/ui/chat/note-header.vue b/src/client/ui/chat/note-header.vue index be08183d39af56596ed5c66bc622c1cd0342ac13..e40f22f588047a18b534472fad8e82a1f97c65db 100644 --- a/src/client/ui/chat/note-header.vue +++ b/src/client/ui/chat/note-header.vue @@ -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 '@client/filters/note'; import { userPage } from '@client/filters/user'; import * as os from '@client/os'; @@ -40,7 +38,6 @@ export default defineComponent({ data() { return { - faHome, faUnlock, faEnvelope, faMobileAlt, faBookmark, farBookmark, faBiohazard }; }, diff --git a/src/client/ui/chat/note.vue b/src/client/ui/chat/note.vue index 77b7440ca1c37b3d57c84b98d36d673d08907c36..7a525d9edbf5e1c6ea92a4660c690ec7996f54df 100644 --- a/src/client/ui/chat/note.vue +++ b/src/client/ui/chat/note.vue @@ -8,12 +8,12 @@ v-hotkey="keymap" > <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"> @@ -23,15 +23,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"> @@ -47,7 +47,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> @@ -61,29 +61,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> <XReactionsViewer :note="appearNote" ref="reactionsViewer"/> <footer class="footer _panel"> <button @click="reply()" class="button _button" v-tooltip="$ts.reply"> - <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" v-tooltip="$ts.renote"> - <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" v-tooltip="$ts.reaction"> - <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" v-tooltip="$ts.reaction"> - <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> @@ -102,8 +102,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'; @@ -124,14 +122,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({ isDeleted: false, muted: false, operating: false, - faEdit, faBolt, faTimes, faBullhorn, faPlus, faMinus, faRetweet, faReply, faReplyAll, faEllipsisH, faHome, faUnlock, faEnvelope, faThumbtack, faBan, faBiohazard, faPlug, faSatelliteDish }; }, @@ -445,7 +434,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 @@ -453,7 +442,7 @@ export default defineComponent({ } }, { text: this.$ts.quote, - icon: faQuoteRight, + icon: 'fas fa-quote-right', action: () => { os.post({ renote: this.appearNote, @@ -593,62 +582,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 }] @@ -657,7 +646,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}`; @@ -672,12 +661,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 @@ -687,15 +676,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'); @@ -706,7 +695,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); @@ -749,7 +738,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', { @@ -792,7 +781,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, { @@ -914,7 +903,7 @@ export default defineComponent({ white-space: pre; color: #d28a3f; - > [data-icon] { + > i { margin-right: 4px; } @@ -952,7 +941,7 @@ export default defineComponent({ border-radius: 6px; } - > [data-icon] { + > i { margin-right: 4px; } diff --git a/src/client/ui/chat/post-form.vue b/src/client/ui/chat/post-form.vue index a9413ea8bc83a05edcccd13e80f23c9acf3de10e..6030166fc5a06a2e9f711399110b7a52536ad3ef 100644 --- a/src/client/ui/chat/post-form.vue +++ b/src/client/ui/chat/post-form.vue @@ -6,15 +6,15 @@ @drop.stop="onDrop" > <div class="form"> - <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> <input v-show="useCw" ref="cw" class="cw" v-model="cw" :placeholder="$ts.annotation" @keydown="onKeydown"> @@ -23,23 +23,23 @@ <XPollEditor v-if="poll" :poll="poll" @destroyed="poll = null" @updated="onPollUpdate"/> <footer> <div class="left"> - <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> </div> <div class="right"> <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> </footer> </div> @@ -48,8 +48,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/'; @@ -138,7 +136,6 @@ export default defineComponent({ } }), postFormActions, - faReply, faQuoteRight, faPaperPlane, faTimes, faUpload, faPollH, faGlobe, faHome, faUnlock, faEnvelope, faEyeSlash, faLaughSquint, faPlus, faPhotoVideo, faAt, faBiohazard, faPlug }; }, @@ -767,7 +764,7 @@ export default defineComponent({ opacity: 0.7; } - > [data-icon] { + > i { margin-left: 6px; } } diff --git a/src/client/ui/chat/side.vue b/src/client/ui/chat/side.vue index 2f182175ba8f47a4acc47c891f99e5cdfb87161e..8cc69fee8ce5b8a7c1bd0e2a53588da8c04d2c06 100644 --- a/src/client/ui/chat/side.vue +++ b/src/client/ui/chat/side.vue @@ -1,9 +1,9 @@ <template> <div class="mrajymqm _narrow_" v-if="component"> <header class="header" @contextmenu.prevent.stop="onContextmenu"> - <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> <XHeader class="title" :info="pageInfo" :with-back="false" :center="false"/> - <button class="_button" @click="close()"><Fa :icon="faTimes"/></button> + <button class="_button" @click="close()"><i class="fas fa-times"></i></button> </header> <component :is="component" v-bind="props" :ref="changePage"/> </div> @@ -11,7 +11,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faTimes, faChevronLeft, faExpandAlt, faWindowMaximize, faExternalLinkAlt, faLink } from '@fortawesome/free-solid-svg-icons'; import XHeader from '../_common_/header.vue'; import * as os from '@client/os'; import copyToClipboard from '@client/scripts/copy-to-clipboard'; @@ -39,7 +38,6 @@ export default defineComponent({ props: {}, pageInfo: null, history: [], - faTimes, faChevronLeft, }; }, @@ -82,28 +80,28 @@ export default defineComponent({ type: 'label', text: this.path, }, { - icon: faExpandAlt, + icon: 'fas fa-expand-alt', text: this.$ts.showInPage, action: () => { this.$router.push(this.path); this.close(); } }, { - icon: faWindowMaximize, + icon: 'fas fa-window-maximize', text: this.$ts.openInWindow, action: () => { os.pageWindow(this.path); this.close(); } }, null, { - icon: faExternalLinkAlt, + icon: 'fas fa-external-link-alt', text: this.$ts.openInNewTab, action: () => { window.open(this.url, '_blank'); this.close(); } }, { - icon: faLink, + icon: 'fas fa-link', text: this.$ts.copyLink, action: () => { copyToClipboard(this.url); diff --git a/src/client/ui/chat/sub-note-content.vue b/src/client/ui/chat/sub-note-content.vue index e530a88172e94f946808e34e435cd2634b598f2c..8a3cf1160f648331715bd3d5a2ee29f9becc24e2 100644 --- a/src/client/ui/chat/sub-note-content.vue +++ b/src/client/ui/chat/sub-note-content.vue @@ -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 '@client/components/poll.vue'; import XMediaList from '@client/components/media-list.vue'; import * as os from '@client/os'; @@ -38,7 +37,6 @@ export default defineComponent({ }, data() { return { - faReply }; } }); diff --git a/src/client/ui/deck.vue b/src/client/ui/deck.vue index 0429dbc9b13cdd8c37e9b21f6fe67fc794f34ade..935445a54db66591dc582a16400347efa8c3538c 100644 --- a/src/client/ui/deck.vue +++ b/src/client/ui/deck.vue @@ -22,8 +22,8 @@ /> </template> - <button v-if="$i" class="nav _button" @click="showNav()"><Fa :icon="faBars"/><i v-if="navIndicated"><Fa :icon="faCircle"/></i></button> - <button v-if="$i" class="post _buttonPrimary" @click="post()"><Fa :icon="faPencilAlt"/></button> + <button v-if="$i" class="nav _button" @click="showNav()"><i class="fas fa-bars"></i><span v-if="navIndicated" class="indicator"><i class="fas fa-circle"></i></span></button> + <button v-if="$i" class="post _buttonPrimary" @click="post()"><i class="fas fa-pencil-alt"></i></button> <XCommon/> </div> @@ -31,8 +31,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faPlus, faPencilAlt, faChevronLeft, faBars, faCircle } from '@fortawesome/free-solid-svg-icons'; -import { } from '@fortawesome/free-regular-svg-icons'; import { v4 as uuid } from 'uuid'; import { host } from '@client/config'; import DeckColumnCore from '@client/ui/deck/column-core.vue'; @@ -64,7 +62,6 @@ export default defineComponent({ host: host, menuDef: sidebarDef, wallpaper: localStorage.getItem('wallpaper') != null, - faPlus, faPencilAlt, faChevronLeft, faBars, faCircle }; }, @@ -219,7 +216,7 @@ export default defineComponent({ background: var(--X2); } - > i { + > .indicator { position: absolute; top: 0; left: 0; diff --git a/src/client/ui/deck/antenna-column.vue b/src/client/ui/deck/antenna-column.vue index 0de870233a4bae79a01d2c4f94349272f67d9428..3abd3d3a45bac46acf73ff3c2b5f9371c21a9e09 100644 --- a/src/client/ui/deck/antenna-column.vue +++ b/src/client/ui/deck/antenna-column.vue @@ -1,7 +1,7 @@ <template> <XColumn :func="{ handler: setAntenna, title: $ts.selectAntenna }" :column="column" :is-stacked="isStacked"> <template #header> - <Fa :icon="faSatellite"/><span style="margin-left: 8px;">{{ column.name }}</span> + <i class="fas fa-satellite"></i><span style="margin-left: 8px;">{{ column.name }}</span> </template> <XTimeline v-if="column.antennaId" ref="timeline" src="antenna" :antenna="column.antennaId" @after="() => $emit('loaded')"/> @@ -10,7 +10,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faSatellite, faCog } from '@fortawesome/free-solid-svg-icons'; import XColumn from './column.vue'; import XTimeline from '@client/components/timeline.vue'; import * as os from '@client/os'; @@ -35,7 +34,6 @@ export default defineComponent({ data() { return { - faSatellite }; }, diff --git a/src/client/ui/deck/column.vue b/src/client/ui/deck/column.vue index 7a08b65a647206aa95f2c4dea1b0fceda03ba784..eaf928069855aa39ae049bd28010bbf81b829ab8 100644 --- a/src/client/ui/deck/column.vue +++ b/src/client/ui/deck/column.vue @@ -15,14 +15,14 @@ @contextmenu.prevent.stop="onContextmenu" > <button class="toggleActive _button" @click="toggleActive" v-if="isStacked && !isMainColumn"> - <template v-if="active"><Fa :icon="faAngleUp"/></template> - <template v-else><Fa :icon="faAngleDown"/></template> + <template v-if="active"><i class="fas fa-angle-up"></i></template> + <template v-else><i class="fas fa-angle-down"></i></template> </button> <div class="action"> <slot name="action"></slot> </div> <span class="header"><slot name="header"></slot></span> - <button v-if="func" class="menu _button" v-tooltip="func.title" @click.stop="func.handler"><Fa :icon="func.icon || faCog"/></button> + <button v-if="func" class="menu _button" v-tooltip="func.title" @click.stop="func.handler"><i :class="func.icon || 'fas fa-cog'"></i></button> </header> <div ref="body" v-show="active"> <slot></slot> @@ -32,8 +32,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faArrowUp, faArrowDown, faAngleUp, faAngleDown, faCaretDown, faArrowRight, faArrowLeft, faPencilAlt, faCog } from '@fortawesome/free-solid-svg-icons'; -import { faWindowMaximize, faTrashAlt, faWindowRestore } from '@fortawesome/free-regular-svg-icons'; import * as os from '@client/os'; import { updateColumn, swapLeftColumn, swapRightColumn, swapUpColumn, swapDownColumn, stackLeftColumn, popRightColumn, removeColumn, swapColumn } from './deck-store'; import { deckStore } from './deck-store'; @@ -73,7 +71,6 @@ export default defineComponent({ dragging: false, draghover: false, dropready: false, - faArrowUp, faArrowDown, faAngleUp, faAngleDown, faCaretDown, faCog, }; }, @@ -134,7 +131,7 @@ export default defineComponent({ getMenu() { const items = [{ - icon: faPencilAlt, + icon: 'fas fa-pencil-alt', text: this.$ts.edit, action: async () => { const { canceled, result } = await os.form(this.column.name, { @@ -158,43 +155,43 @@ export default defineComponent({ updateColumn(this.column.id, result); } }, null, { - icon: faArrowLeft, + icon: 'fas fa-arrow-left', text: this.$ts._deck.swapLeft, action: () => { swapLeftColumn(this.column.id); } }, { - icon: faArrowRight, + icon: 'fas fa-arrow-right', text: this.$ts._deck.swapRight, action: () => { swapRightColumn(this.column.id); } }, this.isStacked ? { - icon: faArrowUp, + icon: 'fas fa-arrow-up', text: this.$ts._deck.swapUp, action: () => { swapUpColumn(this.column.id); } } : undefined, this.isStacked ? { - icon: faArrowDown, + icon: 'fas fa-arrow-down', text: this.$ts._deck.swapDown, action: () => { swapDownColumn(this.column.id); } } : undefined, null, { - icon: faWindowRestore, + icon: 'fas fa-window-restore', text: this.$ts._deck.stackLeft, action: () => { stackLeftColumn(this.column.id); } }, this.isStacked ? { - icon: faWindowMaximize, + icon: 'fas fa-window-maximize', text: this.$ts._deck.popRight, action: () => { popRightColumn(this.column.id); } } : undefined, null, { - icon: faTrashAlt, + icon: 'fas fa-trash-alt', text: this.$ts.remove, danger: true, action: () => { diff --git a/src/client/ui/deck/direct-column.vue b/src/client/ui/deck/direct-column.vue index 6fceae4ed7ac5815dcd2e49fea0b1398e8ba30b6..5b4b02932b404c7c369dbd65a29ac1cbac70bb6e 100644 --- a/src/client/ui/deck/direct-column.vue +++ b/src/client/ui/deck/direct-column.vue @@ -1,6 +1,6 @@ <template> <XColumn :column="column" :is-stacked="isStacked"> - <template #header><Fa :icon="faEnvelope" style="margin-right: 8px;"/>{{ column.name }}</template> + <template #header><i class="fas fa-envelope" style="margin-right: 8px;"></i>{{ column.name }}</template> <XNotes :pagination="pagination" @before="before()" @after="after()"/> </XColumn> @@ -8,7 +8,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faEnvelope } from '@fortawesome/free-solid-svg-icons'; import Progress from '@client/scripts/loading'; import XColumn from './column.vue'; import XNotes from '@client/components/notes.vue'; @@ -40,7 +39,6 @@ export default defineComponent({ visibility: 'specified' }) }, - faEnvelope } }, diff --git a/src/client/ui/deck/list-column.vue b/src/client/ui/deck/list-column.vue index c70abc9f6e466ffaaed2978e26cecb3f9e772f58..450280b863ce3c3c4397443e668f148d5cb6a722 100644 --- a/src/client/ui/deck/list-column.vue +++ b/src/client/ui/deck/list-column.vue @@ -1,7 +1,7 @@ <template> <XColumn :func="{ handler: setList, title: $ts.selectList }" :column="column" :is-stacked="isStacked"> <template #header> - <Fa :icon="faListUl"/><span style="margin-left: 8px;">{{ column.name }}</span> + <i class="fas fa-list-ul"></i><span style="margin-left: 8px;">{{ column.name }}</span> </template> <XTimeline v-if="column.listId" ref="timeline" src="list" :list="column.listId" @after="() => $emit('loaded')"/> @@ -10,7 +10,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faListUl, faCog } from '@fortawesome/free-solid-svg-icons'; import XColumn from './column.vue'; import XTimeline from '@client/components/timeline.vue'; import * as os from '@client/os'; @@ -35,7 +34,6 @@ export default defineComponent({ data() { return { - faListUl }; }, diff --git a/src/client/ui/deck/main-column.vue b/src/client/ui/deck/main-column.vue index 2206fa5e13fa413cd0e8c9daf6906d6d792523ee..75cf94aaed9c4a94190cdfb2cdd1b48aa3927554 100644 --- a/src/client/ui/deck/main-column.vue +++ b/src/client/ui/deck/main-column.vue @@ -16,7 +16,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faWindowMaximize } from '@fortawesome/free-solid-svg-icons'; import XColumn from './column.vue'; import XNotes from '@client/components/notes.vue'; import XHeader from '@client/ui/_common_/header.vue'; @@ -72,7 +71,7 @@ export default defineComponent({ type: 'label', text: path, }, { - icon: faWindowMaximize, + icon: 'fas fa-window-maximize', text: this.$ts.openInWindow, action: () => { os.pageWindow(path); diff --git a/src/client/ui/deck/mentions-column.vue b/src/client/ui/deck/mentions-column.vue index 996123cb1f05815773e9cc3f57235ac8e552855c..053ef918f096dff56058fa3651471a4782f4718b 100644 --- a/src/client/ui/deck/mentions-column.vue +++ b/src/client/ui/deck/mentions-column.vue @@ -1,6 +1,6 @@ <template> <XColumn :column="column" :is-stacked="isStacked"> - <template #header><Fa :icon="faAt" style="margin-right: 8px;"/>{{ column.name }}</template> + <template #header><i class="fas fa-at" style="margin-right: 8px;"></i>{{ column.name }}</template> <XNotes :pagination="pagination" @before="before()" @after="after()"/> </XColumn> @@ -8,7 +8,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faAt } from '@fortawesome/free-solid-svg-icons'; import Progress from '@client/scripts/loading'; import XColumn from './column.vue'; import XNotes from '@client/components/notes.vue'; diff --git a/src/client/ui/deck/notifications-column.vue b/src/client/ui/deck/notifications-column.vue index 1b29a2d54f00230956adb93ab3f543cb53cf3658..c24bf7ab1029c1523eca9149e41a8948cac76734 100644 --- a/src/client/ui/deck/notifications-column.vue +++ b/src/client/ui/deck/notifications-column.vue @@ -1,6 +1,6 @@ <template> <XColumn :column="column" :is-stacked="isStacked" :func="{ handler: func, title: $ts.notificationSetting }"> - <template #header><Fa :icon="faBell" style="margin-right: 8px;"/>{{ column.name }}</template> + <template #header><i class="fas fa-bell" style="margin-right: 8px;"></i>{{ column.name }}</template> <XNotifications :include-types="column.includingTypes"/> </XColumn> @@ -8,8 +8,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faCog } from '@fortawesome/free-solid-svg-icons'; -import { faBell } from '@fortawesome/free-regular-svg-icons'; import XColumn from './column.vue'; import XNotifications from '@client/components/notifications.vue'; import * as os from '@client/os'; @@ -34,7 +32,6 @@ export default defineComponent({ data() { return { - faBell } }, diff --git a/src/client/ui/deck/tl-column.vue b/src/client/ui/deck/tl-column.vue index d4908d0edfae2bff82604ad6a459284e0b08294c..370f7d507f2400cf61c584f824f9aa884450bb7e 100644 --- a/src/client/ui/deck/tl-column.vue +++ b/src/client/ui/deck/tl-column.vue @@ -1,16 +1,16 @@ <template> <XColumn :func="{ handler: setType, title: $ts.timeline }" :column="column" :is-stacked="isStacked" :indicated="indicated" @change-active-state="onChangeActiveState"> <template #header> - <Fa v-if="column.tl === 'home'" :icon="faHome"/> - <Fa v-else-if="column.tl === 'local'" :icon="faComments"/> - <Fa v-else-if="column.tl === 'social'" :icon="faShareAlt"/> - <Fa v-else-if="column.tl === 'global'" :icon="faGlobe"/> + <i v-if="column.tl === 'home'" class="fas fa-home"></i> + <i v-else-if="column.tl === 'local'" class="fas fa-comments"></i> + <i v-else-if="column.tl === 'social'" class="fas fa-share-alt"></i> + <i v-else-if="column.tl === 'global'" class="fas fa-globe"></i> <span style="margin-left: 8px;">{{ column.name }}</span> </template> <div class="iwaalbte" v-if="disabled"> <p> - <Fa :icon="faMinusCircle"/> + <i class="fas fa-minus-circle"></i> {{ $t('disabled-timeline.title') }} </p> <p class="desc">{{ $t('disabled-timeline.description') }}</p> @@ -21,7 +21,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faMinusCircle, faHome, faComments, faShareAlt, faGlobe, faCog } from '@fortawesome/free-solid-svg-icons'; import XColumn from './column.vue'; import XTimeline from '@client/components/timeline.vue'; import * as os from '@client/os'; @@ -49,7 +48,6 @@ export default defineComponent({ disabled: false, indicated: false, columnActive: true, - faMinusCircle, faHome, faComments, faShareAlt, faGlobe, }; }, diff --git a/src/client/ui/deck/widgets-column.vue b/src/client/ui/deck/widgets-column.vue index 992845ff7eacb029d7788789d4c4b8c4cb34af25..47d7e7e314fd81a48308f82550ebf193481ec0e4 100644 --- a/src/client/ui/deck/widgets-column.vue +++ b/src/client/ui/deck/widgets-column.vue @@ -1,6 +1,6 @@ <template> <XColumn :func="{ handler: func, title: $ts.editWidgets }" :naked="true" :column="column" :is-stacked="isStacked"> - <template #header><Fa :icon="faWindowMaximize" style="margin-right: 8px;"/>{{ column.name }}</template> + <template #header><i class="fas fa-window-maximize" style="margin-right: 8px;"></i>{{ column.name }}</template> <div class="wtdtxvec"> <XWidgets :edit="edit" :widgets="column.widgets" @add-widget="addWidget" @remove-widget="removeWidget" @update-widget="updateWidget" @update-widgets="updateWidgets" @exit="edit = false"/> @@ -10,7 +10,6 @@ <script lang="ts"> import { defineComponent, defineAsyncComponent } from 'vue'; -import { faWindowMaximize, faTimes, faCog, faPlus } from '@fortawesome/free-solid-svg-icons'; import XWidgets from '@client/components/widgets.vue'; import XColumn from './column.vue'; import { addColumnWidget, removeColumnWidget, setColumnWidgets, updateColumnWidget } from './deck-store'; @@ -35,7 +34,6 @@ export default defineComponent({ data() { return { edit: false, - faWindowMaximize, faTimes, faPlus }; }, diff --git a/src/client/ui/default.side.vue b/src/client/ui/default.side.vue index 89b648244fbbeae7ff13039597870758d0d911a7..5c8de80378bd4cdb2daff3ae645dfba34a7c55c7 100644 --- a/src/client/ui/default.side.vue +++ b/src/client/ui/default.side.vue @@ -2,10 +2,10 @@ <div class="qvzfzxam _narrow_" v-if="component"> <div class="container"> <header class="header" @contextmenu.prevent.stop="onContextmenu"> - <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> <XHeader class="title" :info="pageInfo" :with-back="false"/> - <button class="_button" @click="close()"><Fa :icon="faTimes"/></button> + <button class="_button" @click="close()"><i class="fas fa-times"></i></button> </header> <component :is="component" v-bind="props" :ref="changePage"/> </div> @@ -14,7 +14,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faTimes, faChevronLeft, faExpandAlt, faWindowMaximize, faExternalLinkAlt, faLink } from '@fortawesome/free-solid-svg-icons'; import XHeader from './_common_/header.vue'; import * as os from '@client/os'; import copyToClipboard from '@client/scripts/copy-to-clipboard'; @@ -42,7 +41,6 @@ export default defineComponent({ props: {}, pageInfo: null, history: [], - faTimes, faChevronLeft, }; }, @@ -83,28 +81,28 @@ export default defineComponent({ type: 'label', text: this.path, }, { - icon: faExpandAlt, + icon: 'fas fa-expand-alt', text: this.$ts.showInPage, action: () => { this.$router.push(this.path); this.close(); } }, { - icon: faWindowMaximize, + icon: 'fas fa-window-maximize', text: this.$ts.openInWindow, action: () => { os.pageWindow(this.path); this.close(); } }, null, { - icon: faExternalLinkAlt, + icon: 'fas fa-external-link-alt', text: this.$ts.openInNewTab, action: () => { window.open(this.url, '_blank'); this.close(); } }, { - icon: faLink, + icon: 'fas fa-link', text: this.$ts.copyLink, action: () => { copyToClipboard(this.url); diff --git a/src/client/ui/default.sidebar.vue b/src/client/ui/default.sidebar.vue index 3e956679cd18e81ee406085d18b47a6c946b5822..a55a1770ff8907752c07b797fa644b7cdcea1a66 100644 --- a/src/client/ui/default.sidebar.vue +++ b/src/client/ui/default.sidebar.vue @@ -1,34 +1,34 @@ <template> <div class="npcljfve" :class="{ iconOnly }"> - <button class="item _button account" @click="openAccountMenu"> + <button class="item _button account" @click="openAccountMenu" v-click-anime> <MkAvatar :user="$i" class="avatar"/><MkAcct class="text" :user="$i"/> </button> <div class="post" @click="post"> <MkButton class="button" primary full> - <Fa :icon="faPencilAlt" fixed-width/><span class="text" v-if="!iconOnly">{{ $ts.note }}</span> + <i class="fas fa-pencil-alt fa-fw"></i><span class="text" v-if="!iconOnly">{{ $ts.note }}</span> </MkButton> </div> <div class="divider"></div> - <MkA class="item index" active-class="active" to="/" exact> - <Fa :icon="faHome" fixed-width/><span class="text">{{ $ts.timeline }}</span> + <MkA class="item index" active-class="active" to="/" exact v-click-anime> + <i class="fas fa-home fa-fw"></i><span class="text">{{ $ts.timeline }}</span> </MkA> <template v-for="item in menu"> <div v-if="item === '-'" class="divider"></div> - <component v-else-if="menuDef[item] && (menuDef[item].show !== false)" :is="menuDef[item].to ? 'MkA' : 'button'" class="item _button" :class="item" active-class="active" v-on="menuDef[item].action ? { click: menuDef[item].action } : {}" :to="menuDef[item].to"> - <Fa :icon="menuDef[item].icon" fixed-width/><span class="text">{{ $ts[menuDef[item].title] }}</span> - <i v-if="menuDef[item].indicated"><Fa :icon="faCircle"/></i> + <component v-else-if="menuDef[item] && (menuDef[item].show !== false)" :is="menuDef[item].to ? 'MkA' : 'button'" class="item _button" :class="item" active-class="active" v-on="menuDef[item].action ? { click: menuDef[item].action } : {}" :to="menuDef[item].to" v-click-anime> + <i class="fa-fw" :class="menuDef[item].icon"></i><span class="text">{{ $ts[menuDef[item].title] }}</span> + <span v-if="menuDef[item].indicated" class="indicator"><i class="fas fa-circle"></i></span> </component> </template> <div class="divider"></div> - <button class="item _button" :class="{ active: $route.path === '/instance' || $route.path.startsWith('/instance/') }" v-if="$i.isAdmin || $i.isModerator" @click="oepnInstanceMenu"> - <Fa :icon="faServer" fixed-width/><span class="text">{{ $ts.instance }}</span> - </button> - <button class="item _button" @click="more"> - <Fa :icon="faEllipsisH" fixed-width/><span class="text">{{ $ts.more }}</span> - <i v-if="otherNavItemIndicated"><Fa :icon="faCircle"/></i> + <MkA v-if="$i.isAdmin || $i.isModerator" class="item" active-class="active" to="/instance" :behavior="settingsWindowed ? 'modalWindow' : null" v-click-anime> + <i class="fas fa-server fa-fw"></i><span class="text">{{ $ts.instance }}</span> + </MkA> + <button class="item _button" @click="more" v-click-anime> + <i class="fas fa-ellipsis-h fa-fw"></i><span class="text">{{ $ts.more }}</span> + <span v-if="otherNavItemIndicated" class="indicator"><i class="fas fa-circle"></i></span> </button> - <MkA class="item" active-class="active" to="/settings" :behavior="settingsWindowed ? 'modalWindow' : null"> - <Fa :icon="faCog" fixed-width/><span class="text">{{ $ts.settings }}</span> + <MkA class="item" active-class="active" to="/settings" :behavior="settingsWindowed ? 'modalWindow' : null" v-click-anime> + <i class="fas fa-cog fa-fw"></i><span class="text">{{ $ts.settings }}</span> </MkA> <div class="divider"></div> <div class="foo"> @@ -40,8 +40,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faGripVertical, faChevronLeft, faHashtag, faBroadcastTower, faFireAlt, faEllipsisH, faPencilAlt, faBars, faTimes, faSearch, faUserCog, faCog, faUser, faHome, faStar, faCircle, faAt, faListUl, faPlus, faUserClock, faUsers, faTachometerAlt, faExchangeAlt, faGlobe, faChartBar, faCloud, faServer, faInfoCircle, faQuestionCircle, faProjectDiagram, faStream, faExclamationCircle } from '@fortawesome/free-solid-svg-icons'; -import { faBell, faEnvelope, faLaugh, faComments } from '@fortawesome/free-regular-svg-icons'; import { host } from '@client/config'; import { search } from '@client/scripts/search'; import * as os from '@client/os'; @@ -65,7 +63,6 @@ export default defineComponent({ menuDef: sidebarDef, iconOnly: false, settingsWindowed: false, - faGripVertical, faChevronLeft, faComments, faHashtag, faBroadcastTower, faFireAlt, faEllipsisH, faPencilAlt, faBars, faTimes, faBell, faSearch, faUserCog, faCog, faUser, faHome, faStar, faCircle, faAt, faEnvelope, faListUl, faPlus, faUserClock, faLaugh, faUsers, faTachometerAlt, faExchangeAlt, faGlobe, faChartBar, faCloud, faServer, faProjectDiagram }; }, @@ -143,12 +140,12 @@ export default defineComponent({ to: `/@${ this.$i.username }`, avatar: this.$i, }, null, ...accountItemPromises, { - icon: faPlus, - text: this.$ts.addAcount, + icon: 'fas fa-plus', + text: this.$ts.addAccount, action: () => { os.modalMenu([{ - text: this.$ts.existingAcount, - action: () => { this.addAcount(); }, + text: this.$ts.existingAccount, + action: () => { this.addAccount(); }, }, { text: this.$ts.createAccount, action: () => { this.createAccount(); }, @@ -159,71 +156,12 @@ export default defineComponent({ }); }, - oepnInstanceMenu(ev) { - os.modalMenu([{ - type: 'link', - text: this.$ts.dashboard, - to: '/instance', - icon: faTachometerAlt, - }, null, this.$i.isAdmin ? { - type: 'link', - text: this.$ts.settings, - to: '/instance/settings', - icon: faCog, - } : undefined, { - type: 'link', - text: this.$ts.customEmojis, - to: '/instance/emojis', - icon: faLaugh, - }, { - type: 'link', - text: this.$ts.users, - to: '/instance/users', - icon: faUsers, - }, { - type: 'link', - text: this.$ts.files, - to: '/instance/files', - icon: faCloud, - }, { - type: 'link', - text: this.$ts.jobQueue, - to: '/instance/queue', - icon: faExchangeAlt, - }, { - type: 'link', - text: this.$ts.federation, - to: '/instance/federation', - icon: faGlobe, - }, { - type: 'link', - text: this.$ts.relays, - to: '/instance/relays', - icon: faProjectDiagram, - }, { - type: 'link', - text: this.$ts.announcements, - to: '/instance/announcements', - icon: faBroadcastTower, - }, { - type: 'link', - text: this.$ts.abuseReports, - to: '/instance/abuses', - icon: faExclamationCircle, - }, { - type: 'link', - text: this.$ts.logs, - to: '/instance/logs', - icon: faStream, - }], ev.currentTarget || ev.target); - }, - more(ev) { os.popup(import('@client/components/launch-pad.vue'), {}, { }, 'closed'); }, - addAcount() { + addAccount() { os.popup(import('@client/components/signin-dialog.vue'), {}, { done: res => { addAccount(res.id, res.i); @@ -289,7 +227,7 @@ export default defineComponent({ font-size: $ui-font-size * 1.1; line-height: 3.7rem; - > [data-icon], + > i, > .avatar { margin-right: 0; } @@ -344,11 +282,11 @@ export default defineComponent({ text-align: left; box-sizing: border-box; - > [data-icon] { + > i { width: 32px; } - > [data-icon], + > i, > .avatar { margin-right: $avatar-margin; } @@ -359,7 +297,7 @@ export default defineComponent({ vertical-align: middle; } - > i { + > .indicator { position: absolute; top: 0; left: 20px; diff --git a/src/client/ui/default.vue b/src/client/ui/default.vue index c3dce0f3230c7e405317a9a64b544f1ee33c9123..0cc969272ae9c4b6c1b6e3a36eb56b15da065d57 100644 --- a/src/client/ui/default.vue +++ b/src/client/ui/default.vue @@ -26,11 +26,11 @@ </div> <div class="buttons" v-if="isMobile"> - <button class="button nav _button" @click="showDrawerNav" ref="navButton"><Fa :icon="faBars"/><i v-if="navIndicated"><Fa :icon="faCircle"/></i></button> - <button class="button home _button" @click="$route.name === 'index' ? top() : $router.push('/')"><Fa :icon="faHome"/></button> - <button class="button notifications _button" @click="$router.push('/my/notifications')"><Fa :icon="faBell"/><i v-if="$i.hasUnreadNotification"><Fa :icon="faCircle"/></i></button> - <button class="button widget _button" @click="widgetsShowing = true"><Fa :icon="faLayerGroup"/></button> - <button class="button post _button" @click="post"><Fa :icon="faPencilAlt"/></button> + <button class="button nav _button" @click="showDrawerNav" ref="navButton"><i class="fas fa-bars"></i><span v-if="navIndicated" class="indicator"><i class="fas fa-circle"></i></span></button> + <button class="button home _button" @click="$route.name === 'index' ? top() : $router.push('/')"><i class="fas fa-home"></i></button> + <button class="button notifications _button" @click="$router.push('/my/notifications')"><i class="fas fa-bell"></i><span v-if="$i.hasUnreadNotification" class="indicator"><i class="fas fa-circle"></i></span></button> + <button class="button widget _button" @click="widgetsShowing = true"><i class="fas fa-layer-group"></i></button> + <button class="button post _button" @click="post"><i class="fas fa-pencil-alt"></i></button> </div> <XDrawerSidebar ref="drawerNav" class="sidebar" v-if="isMobile"/> @@ -53,8 +53,6 @@ <script lang="ts"> import { defineComponent, defineAsyncComponent } from 'vue'; -import { faLayerGroup, faBars, faHome, faCircle, faWindowMaximize, faExpand, faPencilAlt, faCompress } from '@fortawesome/free-solid-svg-icons'; -import { faBell } from '@fortawesome/free-regular-svg-icons'; import { instanceName } from '@client/config'; import { StickySidebar } from '@client/scripts/sticky-sidebar'; import XSidebar from './default.sidebar.vue'; @@ -86,7 +84,6 @@ export default defineComponent({ widgetsShowing: false, fullView: false, wallpaper: localStorage.getItem('wallpaper') != null, - faLayerGroup, faBars, faBell, faHome, faCircle, faPencilAlt, }; }, @@ -175,13 +172,13 @@ export default defineComponent({ type: 'label', text: path, }, { - icon: this.fullView ? faCompress : faExpand, + icon: this.fullView ? 'fas fa-compress' : 'fas fa-expand', text: this.fullView ? this.$ts.quitFullView : this.$ts.fullView, action: () => { this.fullView = !this.fullView; } }, { - icon: faWindowMaximize, + icon: 'fas fa-window-maximize', text: this.$ts.openInWindow, action: () => { os.pageWindow(path); @@ -221,6 +218,8 @@ export default defineComponent({ $widgets-hide-threshold: 1200px; $nav-icon-only-width: 78px; // TODO: ã©ã“ã‹ã«é›†ç´„ã—ãŸã„ + --panelShadow: none; + // ã»ã‚“ã¨ã¯å˜ã« 100vh ã¨æ›¸ããŸã„ã¨ã“ã‚ã ãŒ... https://css-tricks.com/the-trick-to-viewport-units-on-mobile/ min-height: calc(var(--vh, 1vh) * 100); box-sizing: border-box; @@ -253,7 +252,7 @@ export default defineComponent({ display: flex; justify-content: center; max-width: 100%; - margin: 32px 0; + //margin: 32px 0; &.fullView { margin: 0; @@ -279,6 +278,8 @@ export default defineComponent({ width: 750px; margin: 0 16px 0 0; background: var(--bg); + box-shadow: 0 0 0 1px var(--divider); + border-radius: 0; --margin: 12px; > .header { @@ -311,12 +312,17 @@ export default defineComponent({ > .widgets { //--panelShadow: none; width: 300px; + margin-top: 16px; @media (max-width: $widgets-hide-threshold) { display: none; } } + > .sidebar { + margin-top: 16px; + } + @media (max-width: 850px) { margin: 0; @@ -372,7 +378,7 @@ export default defineComponent({ background: var(--X2); } - > i { + > .indicator { position: absolute; top: 0; left: 0; diff --git a/src/client/ui/default.widgets.vue b/src/client/ui/default.widgets.vue index e5a04193872f310c3878b406d4b73276368452a3..cabd83937e837d21bba783ee3e69a4b4a99c3bcd 100644 --- a/src/client/ui/default.widgets.vue +++ b/src/client/ui/default.widgets.vue @@ -2,14 +2,13 @@ <div class="efzpzdvf"> <XWidgets class="widgets" :edit="editMode" :widgets="$store.reactiveState.widgets.value" @add-widget="addWidget" @remove-widget="removeWidget" @update-widget="updateWidget" @update-widgets="updateWidgets" @exit="editMode = false"/> - <button v-if="editMode" @click="editMode = false" class="_textButton edit" style="font-size: 0.9em;"><Fa :icon="faCheck"/> {{ $ts.editWidgetsExit }}</button> - <button v-else @click="editMode = true" class="_textButton edit" style="font-size: 0.9em;"><Fa :icon="faPencilAlt"/> {{ $ts.editWidgets }}</button> + <button v-if="editMode" @click="editMode = false" class="_textButton edit" style="font-size: 0.9em;"><i class="fas fa-check"></i> {{ $ts.editWidgetsExit }}</button> + <button v-else @click="editMode = true" class="_textButton edit" style="font-size: 0.9em;"><i class="fas fa-pencil-alt"></i> {{ $ts.editWidgets }}</button> </div> </template> <script lang="ts"> import { defineComponent, defineAsyncComponent } from 'vue'; -import { faPencilAlt, faPlus, faBars, faTimes, faCheck } from '@fortawesome/free-solid-svg-icons'; import XWidgets from '@client/components/widgets.vue'; import * as os from '@client/os'; @@ -23,7 +22,6 @@ export default defineComponent({ data() { return { editMode: false, - faPencilAlt, faPlus, faBars, faTimes, faCheck, }; }, diff --git a/src/client/ui/universal.vue b/src/client/ui/universal.vue index 6df09937dff53c8d7d09fde73849d8e0cf1602bf..a44dfc42f00f0be358d887e528cf5fb27d915e25 100644 --- a/src/client/ui/universal.vue +++ b/src/client/ui/universal.vue @@ -27,14 +27,14 @@ </div> <div class="buttons" :class="{ navHidden }"> - <button class="button nav _button" @click="showNav" ref="navButton"><Fa :icon="faBars"/><i v-if="navIndicated"><Fa :icon="faCircle"/></i></button> - <button class="button home _button" @click="$route.name === 'index' ? top() : $router.push('/')"><Fa :icon="faHome"/></button> - <button class="button notifications _button" @click="$router.push('/my/notifications')"><Fa :icon="faBell"/><i v-if="$i.hasUnreadNotification"><Fa :icon="faCircle"/></i></button> - <button class="button widget _button" @click="widgetsShowing = true"><Fa :icon="faLayerGroup"/></button> - <button class="button post _button" @click="post"><Fa :icon="faPencilAlt"/></button> + <button class="button nav _button" @click="showNav" ref="navButton"><i class="fas fa-bars"></i><span v-if="navIndicated" class="indicator"><i class="fas fa-circle"></i></span></button> + <button class="button home _button" @click="$route.name === 'index' ? top() : $router.push('/')"><i class="fas fa-home"></i></button> + <button class="button notifications _button" @click="$router.push('/my/notifications')"><i class="fas fa-bell"></i><span v-if="$i.hasUnreadNotification" class="indicator"><i class="fas fa-circle"></i></span></button> + <button class="button widget _button" @click="widgetsShowing = true"><i class="fas fa-layer-group"></i></button> + <button class="button post _button" @click="post"><i class="fas fa-pencil-alt"></i></button> </div> - <button class="widgetButton _button" :class="{ navHidden }" @click="widgetsShowing = true"><Fa :icon="faLayerGroup"/></button> + <button class="widgetButton _button" :class="{ navHidden }" @click="widgetsShowing = true"><i class="fas fa-layer-group"></i></button> <transition name="tray-back"> <div class="tray-back _modalBg" @@ -54,8 +54,6 @@ <script lang="ts"> import { defineComponent, defineAsyncComponent } from 'vue'; -import { faLayerGroup, faBars, faHome, faCircle, faWindowMaximize, faColumns, faPencilAlt } from '@fortawesome/free-solid-svg-icons'; -import { faBell } from '@fortawesome/free-regular-svg-icons'; import { instanceName } from '@client/config'; import { StickySidebar } from '@client/scripts/sticky-sidebar'; import XSidebar from '@client/ui/_common_/sidebar.vue'; @@ -93,7 +91,6 @@ export default defineComponent({ navHidden: false, widgetsShowing: false, wallpaper: localStorage.getItem('wallpaper') != null, - faLayerGroup, faBars, faBell, faHome, faCircle, faPencilAlt, }; }, @@ -201,13 +198,13 @@ export default defineComponent({ type: 'label', text: path, }, { - icon: faColumns, + icon: 'fas fa-columns', text: this.$ts.openInSideView, action: () => { this.$refs.side.navigate(path); } }, { - icon: faWindowMaximize, + icon: 'fas fa-window-maximize', text: this.$ts.openInWindow, action: () => { os.pageWindow(path); @@ -378,7 +375,7 @@ export default defineComponent({ background: var(--X2); } - > i { + > .indicator { position: absolute; top: 0; left: 0; diff --git a/src/client/ui/universal.widgets.vue b/src/client/ui/universal.widgets.vue index 35d3442bb2f9f9e0be6bdd1676214371cf1ef9df..28b14749d1762c3f1c446a929dc1ca9efb60c85d 100644 --- a/src/client/ui/universal.widgets.vue +++ b/src/client/ui/universal.widgets.vue @@ -2,14 +2,13 @@ <div class="efzpzdvf"> <XWidgets :edit="editMode" :widgets="$store.reactiveState.widgets.value" @add-widget="addWidget" @remove-widget="removeWidget" @update-widget="updateWidget" @update-widgets="updateWidgets" @exit="editMode = false"/> - <button v-if="editMode" @click="editMode = false" class="_textButton" style="font-size: 0.9em;"><Fa :icon="faCheck"/> {{ $ts.editWidgetsExit }}</button> - <button v-else @click="editMode = true" class="_textButton" style="font-size: 0.9em;"><Fa :icon="faPencilAlt"/> {{ $ts.editWidgets }}</button> + <button v-if="editMode" @click="editMode = false" class="_textButton" style="font-size: 0.9em;"><i class="fas fa-check"></i> {{ $ts.editWidgetsExit }}</button> + <button v-else @click="editMode = true" class="_textButton" style="font-size: 0.9em;"><i class="fas fa-pencil-alt"></i> {{ $ts.editWidgets }}</button> </div> </template> <script lang="ts"> import { defineComponent, defineAsyncComponent } from 'vue'; -import { faPencilAlt, faPlus, faBars, faTimes, faCheck } from '@fortawesome/free-solid-svg-icons'; import XWidgets from '@client/components/widgets.vue'; import * as os from '@client/os'; @@ -23,7 +22,6 @@ export default defineComponent({ data() { return { editMode: false, - faPencilAlt, faPlus, faBars, faTimes, faCheck, }; }, diff --git a/src/client/ui/visitor/a.vue b/src/client/ui/visitor/a.vue index 1b080c9e825e3173f920077705666d0b85c384c4..1dcb803eb19df8383661c89e117f701498ce5071 100644 --- a/src/client/ui/visitor/a.vue +++ b/src/client/ui/visitor/a.vue @@ -41,7 +41,6 @@ <script lang="ts"> import { defineComponent, defineAsyncComponent } from 'vue'; -import { } from '@fortawesome/free-solid-svg-icons'; import { host, instanceName } from '@client/config'; import { search } from '@client/scripts/search'; import * as os from '@client/os'; diff --git a/src/client/ui/visitor/b.vue b/src/client/ui/visitor/b.vue index da2ae4518017989b26761ca7ccefb922faa40cb8..0a70e5e1d1c0996fb99dbda6c1a73cfac183ffe0 100644 --- a/src/client/ui/visitor/b.vue +++ b/src/client/ui/visitor/b.vue @@ -35,10 +35,10 @@ <transition name="tray"> <div v-if="showMenu" class="menu"> - <MkA to="/" class="link" active-class="active"><Fa :icon="faHome" class="icon"/>{{ $ts.home }}</MkA> - <MkA to="/explore" class="link" active-class="active"><Fa :icon="faHashtag" class="icon"/>{{ $ts.explore }}</MkA> - <MkA to="/featured" class="link" active-class="active"><Fa :icon="faFireAlt" class="icon"/>{{ $ts.featured }}</MkA> - <MkA to="/channels" class="link" active-class="active"><Fa :icon="faSatelliteDish" class="icon"/>{{ $ts.channel }}</MkA> + <MkA to="/" class="link" active-class="active"><i class="fas fa-home icon"></i>{{ $ts.home }}</MkA> + <MkA to="/explore" class="link" active-class="active"><i class="fas fa-hashtag icon"></i>{{ $ts.explore }}</MkA> + <MkA to="/featured" class="link" active-class="active"><i class="fas fa-fire-alt icon"></i>{{ $ts.featured }}</MkA> + <MkA to="/channels" class="link" active-class="active"><i class="fas fa-satellite-dish icon"></i>{{ $ts.channel }}</MkA> <div class="action"> <button class="_buttonPrimary" @click="signup()">{{ $ts.signup }}</button> <button class="_button" @click="signin()">{{ $ts.login }}</button> @@ -50,7 +50,6 @@ <script lang="ts"> import { defineComponent, defineAsyncComponent } from 'vue'; -import { } from '@fortawesome/free-solid-svg-icons'; import { host, instanceName } from '@client/config'; import { search } from '@client/scripts/search'; import * as os from '@client/os'; diff --git a/src/client/ui/visitor/header.vue b/src/client/ui/visitor/header.vue index 42598ce1c054b4c144f1cf133b4549289252cbc5..1effadf4f73c642e5d0f98f4d7bd7c317843475d 100644 --- a/src/client/ui/visitor/header.vue +++ b/src/client/ui/visitor/header.vue @@ -2,21 +2,21 @@ <div class="sqxihjet"> <div class="wide" v-if="narrow === false"> <div class="content"> - <MkA to="/" class="link" active-class="active"><Fa :icon="faHome" class="icon"/>{{ $ts.home }}</MkA> - <MkA to="/explore" class="link" active-class="active"><Fa :icon="faHashtag" class="icon"/>{{ $ts.explore }}</MkA> - <MkA to="/featured" class="link" active-class="active"><Fa :icon="faFireAlt" class="icon"/>{{ $ts.featured }}</MkA> - <MkA to="/channels" class="link" active-class="active"><Fa :icon="faSatelliteDish" class="icon"/>{{ $ts.channel }}</MkA> + <MkA to="/" class="link" active-class="active"><i class="fas fa-home icon"></i>{{ $ts.home }}</MkA> + <MkA to="/explore" class="link" active-class="active"><i class="fas fa-hashtag icon"></i>{{ $ts.explore }}</MkA> + <MkA to="/featured" class="link" active-class="active"><i class="fas fa-fire-alt icon"></i>{{ $ts.featured }}</MkA> + <MkA to="/channels" class="link" active-class="active"><i class="fas fa-satellite-dish icon"></i>{{ $ts.channel }}</MkA> <div class="page active link" v-if="info"> <div class="title"> - <Fa v-if="info.icon" :icon="info.icon" :key="info.icon" class="icon"/> + <i v-if="info.icon" class="icon" :class="info.icon"></i> <MkAvatar v-else-if="info.avatar" class="avatar" :user="info.avatar" :disable-preview="true" :show-indicator="true"/> <span v-if="info.title" class="text">{{ info.title }}</span> <MkUserName v-else-if="info.userName" :user="info.userName" :nowrap="false" class="text"/> </div> - <button class="_button action" v-if="info.action" @click.stop="info.action.handler"><Fa :icon="info.action.icon" :key="info.action.icon"/></button> + <button class="_button action" v-if="info.action" @click.stop="info.action.handler"><!-- TODO --></button> </div> <div class="right"> - <button class="_button search" @click="search()"><Fa :icon="faSearch" class="icon"/><span>{{ $ts.search }}</span></button> + <button class="_button search" @click="search()"><i class="fas fa-search icon"></i><span>{{ $ts.search }}</span></button> <button class="_buttonPrimary signup" @click="signup()">{{ $ts.signup }}</button> <button class="_button login" @click="signin()">{{ $ts.login }}</button> </div> @@ -24,16 +24,16 @@ </div> <div class="narrow" v-else-if="narrow === true"> <button class="menu _button" @click="$parent.showMenu = true"> - <Fa :icon="faBars" class="icon"/> + <i class="fas fa-bars icon"></i> </button> <div class="title" v-if="info"> - <Fa v-if="info.icon" :icon="info.icon" :key="info.icon" class="icon"/> + <i v-if="info.icon" class="icon" :class="info.icon"></i> <MkAvatar v-else-if="info.avatar" class="avatar" :user="info.avatar" :disable-preview="true" :show-indicator="true"/> <span v-if="info.title" class="text">{{ info.title }}</span> <MkUserName v-else-if="info.userName" :user="info.userName" :nowrap="false" class="text"/> </div> <button class="action _button" v-if="info && info.action" @click.stop="info.action.handler"> - <Fa :icon="info.action.icon" :key="info.action.icon" class="icon"/> + <!-- TODO --> </button> </div> </div> @@ -41,7 +41,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faSearch, faHome, faFireAlt, faHashtag, faSatelliteDish, faBars } from '@fortawesome/free-solid-svg-icons'; import XSigninDialog from '@client/components/signin-dialog.vue'; import XSignupDialog from '@client/components/signup-dialog.vue'; import * as os from '@client/os'; @@ -58,7 +57,6 @@ export default defineComponent({ return { narrow: null, showMenu: false, - faSearch, faHome, faFireAlt, faHashtag, faSatelliteDish, faBars, }; }, diff --git a/src/client/ui/visitor/kanban.vue b/src/client/ui/visitor/kanban.vue index 2ed8cf4bc03fd6fb5dec35705f3d1437491d377a..ffa7a3d1ff145d4d2ff83858b333c170795e8d3c 100644 --- a/src/client/ui/visitor/kanban.vue +++ b/src/client/ui/visitor/kanban.vue @@ -38,7 +38,6 @@ <script lang="ts"> import { defineComponent, defineAsyncComponent } from 'vue'; -import { } from '@fortawesome/free-solid-svg-icons'; import { host, instanceName } from '@client/config'; import * as os from '@client/os'; import MkPagination from '@client/components/ui/pagination.vue'; diff --git a/src/client/ui/zen.vue b/src/client/ui/zen.vue index af3e53225e5ec874c3c84ea82714c478356757b9..6e7382b0d3ed5de103d0f187f2a594846a5dad6a 100644 --- a/src/client/ui/zen.vue +++ b/src/client/ui/zen.vue @@ -23,8 +23,6 @@ <script lang="ts"> import { defineComponent, defineAsyncComponent } from 'vue'; -import { faLayerGroup, faBars, faHome, faCircle } from '@fortawesome/free-solid-svg-icons'; -import { faBell } from '@fortawesome/free-regular-svg-icons'; import { host } from '@client/config'; import XHeader from './_common_/header.vue'; import XCommon from './_common_/common.vue'; @@ -40,7 +38,6 @@ export default defineComponent({ return { host: host, pageInfo: null, - faLayerGroup, faBars, faBell, faHome, faCircle, }; }, diff --git a/src/client/widgets/activity.vue b/src/client/widgets/activity.vue index 9623765e40a9f7f839c310b38adf023f7e0d632d..cc8d4debd099f3e168bf7e93fd1bce2f2f2b3b77 100644 --- a/src/client/widgets/activity.vue +++ b/src/client/widgets/activity.vue @@ -1,7 +1,7 @@ <template> <MkContainer :show-header="props.showHeader" :naked="props.transparent"> - <template #header><Fa :icon="faChartBar"/>{{ $ts._widgets.activity }}</template> - <template #func><button @click="toggleView()" class="_button"><Fa :icon="faSort"/></button></template> + <template #header><i class="fas fa-chart-bar"></i>{{ $ts._widgets.activity }}</template> + <template #func><button @click="toggleView()" class="_button"><i class="fas fa-sort"></i></button></template> <div> <MkLoading v-if="fetching"/> @@ -15,7 +15,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faChartBar, faSort } from '@fortawesome/free-solid-svg-icons'; import MkContainer from '@client/components/ui/container.vue'; import define from './define'; import XCalendar from './activity.calendar.vue'; @@ -52,7 +51,6 @@ export default defineComponent({ return { fetching: true, activity: null, - faChartBar, faSort }; }, mounted() { diff --git a/src/client/widgets/aiscript.vue b/src/client/widgets/aiscript.vue index f24e03359399b17fbaf0dcd47307d3d39a8e7a53..2ea6d09ff53f74ed65f59e13eb8cd4d2466d59dc 100644 --- a/src/client/widgets/aiscript.vue +++ b/src/client/widgets/aiscript.vue @@ -1,6 +1,6 @@ <template> <MkContainer :show-header="props.showHeader"> - <template #header><Fa :icon="faTerminal"/>{{ $ts._widgets.aiscript }}</template> + <template #header><i class="fas fa-terminal"></i>{{ $ts._widgets.aiscript }}</template> <div class="uylguesu _monospace"> <textarea v-model="props.script" placeholder="(1 + 1)"></textarea> @@ -14,7 +14,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faTerminal } from '@fortawesome/free-solid-svg-icons'; import MkContainer from '@client/components/ui/container.vue'; import define from './define'; import * as os from '@client/os'; @@ -46,7 +45,6 @@ export default defineComponent({ data() { return { logs: [], - faTerminal }; }, diff --git a/src/client/widgets/federation.vue b/src/client/widgets/federation.vue index eb17915f0870b9c921d1c4bfbe98d25a0e66e2a5..3f2e1e691d38dd8e62a47d7eee5644de29927cbf 100644 --- a/src/client/widgets/federation.vue +++ b/src/client/widgets/federation.vue @@ -1,6 +1,6 @@ <template> <MkContainer :show-header="props.showHeader" :foldable="foldable" :scrollable="scrollable"> - <template #header><Fa :icon="faGlobe"/>{{ $ts._widgets.federation }}</template> + <template #header><i class="fas fa-globe"></i>{{ $ts._widgets.federation }}</template> <div class="wbrkwalb"> <MkLoading v-if="fetching"/> @@ -20,7 +20,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faGlobe } from '@fortawesome/free-solid-svg-icons'; import MkContainer from '@client/components/ui/container.vue'; import define from './define'; import MkMiniChart from '@client/components/mini-chart.vue'; @@ -58,7 +57,6 @@ export default defineComponent({ instances: [], charts: [], fetching: true, - faGlobe }; }, mounted() { diff --git a/src/client/widgets/job-queue.vue b/src/client/widgets/job-queue.vue index 007fd412c848204842f2d0f712de57441bdfa58c..31a322e6e2180a4ba092c10628849afe7a6190e7 100644 --- a/src/client/widgets/job-queue.vue +++ b/src/client/widgets/job-queue.vue @@ -1,7 +1,7 @@ <template> <div class="mkw-jobQueue _monospace" :class="{ _panel: !props.transparent }"> <div class="inbox"> - <div class="label">Inbox queue<Fa :icon="faExclamationTriangle" v-if="inbox.waiting > 0" class="icon"/></div> + <div class="label">Inbox queue<i v-if="inbox.waiting > 0" class="fas fa-exclamation-triangle icon"></i></div> <div class="values"> <div> <div>Process</div> @@ -22,7 +22,7 @@ </div> </div> <div class="deliver"> - <div class="label">Deliver queue<Fa :icon="faExclamationTriangle" v-if="deliver.waiting > 0" class="icon"/></div> + <div class="label">Deliver queue<i v-if="deliver.waiting > 0" class="fas fa-exclamation-triangle icon"></i></div> <div class="values"> <div> <div>Process</div> @@ -47,7 +47,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons'; import define from './define'; import * as os from '@client/os'; import number from '@client/filters/number'; @@ -80,7 +79,6 @@ export default defineComponent({ delayed: 0, }, prev: {}, - faExclamationTriangle, }; }, created() { diff --git a/src/client/widgets/memo.vue b/src/client/widgets/memo.vue index c3ab2934a8a7ef7d73f23a2b9780589face290b7..13ab628f24695c639f020695bf4acc5eec515989 100644 --- a/src/client/widgets/memo.vue +++ b/src/client/widgets/memo.vue @@ -1,6 +1,6 @@ <template> <MkContainer :show-header="props.showHeader"> - <template #header><Fa :icon="faStickyNote"/>{{ $ts._widgets.memo }}</template> + <template #header><i class="fas fa-sticky-note"></i>{{ $ts._widgets.memo }}</template> <div class="otgbylcu"> <textarea v-model="text" :placeholder="$ts.placeholder" @input="onChange"></textarea> @@ -11,7 +11,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faStickyNote } from '@fortawesome/free-solid-svg-icons'; import MkContainer from '@client/components/ui/container.vue'; import define from './define'; import * as os from '@client/os'; @@ -37,7 +36,6 @@ export default defineComponent({ text: null, changed: false, timeoutId: null, - faStickyNote }; }, diff --git a/src/client/widgets/notifications.vue b/src/client/widgets/notifications.vue index 046556ef1c56781f6a24067cb15af6a3fde11a26..01c76850d8c12ab8123e19a9f9681c0d5f7332b8 100644 --- a/src/client/widgets/notifications.vue +++ b/src/client/widgets/notifications.vue @@ -1,7 +1,7 @@ <template> <MkContainer :style="`height: ${props.height}px;`" :show-header="props.showHeader" :scrollable="true"> - <template #header><Fa :icon="faBell"/>{{ $ts.notifications }}</template> - <template #func><button @click="configure()" class="_button"><Fa :icon="faCog"/></button></template> + <template #header><i class="fas fa-bell"></i>{{ $ts.notifications }}</template> + <template #func><button @click="configure()" class="_button"><i class="fas fa-cog"></i></button></template> <div class="_flat_"> <XNotifications :include-types="props.includingTypes"/> @@ -11,7 +11,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faBell, faCog } from '@fortawesome/free-solid-svg-icons'; import MkContainer from '@client/components/ui/container.vue'; import XNotifications from '@client/components/notifications.vue'; import define from './define'; @@ -46,7 +45,6 @@ export default defineComponent({ data() { return { - faBell, faCog }; }, diff --git a/src/client/widgets/photos.vue b/src/client/widgets/photos.vue index f1041b4ec258936e974fe9ed46ecaa828ead220f..65843385b613ed577bdbc8e263e7a24d1f5cfa40 100644 --- a/src/client/widgets/photos.vue +++ b/src/client/widgets/photos.vue @@ -1,6 +1,6 @@ <template> <MkContainer :show-header="props.showHeader" :naked="props.transparent" :class="$style.root" :data-transparent="props.transparent ? true : null"> - <template #header><Fa :icon="faCamera"/>{{ $ts._widgets.photos }}</template> + <template #header><i class="fas fa-camera"></i>{{ $ts._widgets.photos }}</template> <div class=""> <MkLoading v-if="fetching"/> @@ -16,7 +16,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faCamera } from '@fortawesome/free-solid-svg-icons'; import MkContainer from '@client/components/ui/container.vue'; import define from './define'; import { getStaticImageUrl } from '@client/scripts/get-static-image-url'; @@ -46,7 +45,6 @@ export default defineComponent({ images: [], fetching: true, connection: null, - faCamera }; }, mounted() { diff --git a/src/client/widgets/rss.vue b/src/client/widgets/rss.vue index 78ad390d275fb2f0b25f654ebbf84209761a1631..6d19a86dffa95ea6494aea428855b400466770f2 100644 --- a/src/client/widgets/rss.vue +++ b/src/client/widgets/rss.vue @@ -1,7 +1,7 @@ <template> <MkContainer :show-header="props.showHeader"> - <template #header><Fa :icon="faRssSquare"/>RSS</template> - <template #func><button class="_button" @click="setting"><Fa :icon="faCog"/></button></template> + <template #header><i class="fas fa-rss-square"></i>RSS</template> + <template #func><button class="_button" @click="setting"><i class="fas fa-cog"></i></button></template> <div class="ekmkgxbj"> <MkLoading v-if="fetching"/> @@ -14,7 +14,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faRssSquare, faCog } from '@fortawesome/free-solid-svg-icons'; import MkContainer from '@client/components/ui/container.vue'; import define from './define'; import * as os from '@client/os'; @@ -43,7 +42,6 @@ export default defineComponent({ items: [], fetching: true, clock: null, - faRssSquare, faCog }; }, mounted() { diff --git a/src/client/widgets/server-metric/cpu.vue b/src/client/widgets/server-metric/cpu.vue index f1574522c2d45cdd19247619a215b68e05e7d71b..4478ee30655e93e4d058ab89cf519ec698463ad7 100644 --- a/src/client/widgets/server-metric/cpu.vue +++ b/src/client/widgets/server-metric/cpu.vue @@ -2,7 +2,7 @@ <div class="vrvdvrys"> <XPie class="pie" :value="usage"/> <div> - <p><fa :icon="faMicrochip"/>CPU</p> + <p><i class="fas fa-microchip"></i>CPU</p> <p>{{ meta.cpu.cores }} Logical cores</p> <p>{{ meta.cpu.model }}</p> </div> @@ -11,7 +11,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faMicrochip } from '@fortawesome/free-solid-svg-icons'; import XPie from './pie.vue'; export default defineComponent({ @@ -29,7 +28,6 @@ export default defineComponent({ data() { return { usage: 0, - faMicrochip, }; }, mounted() { @@ -68,7 +66,7 @@ export default defineComponent({ font-weight: bold; margin-bottom: 4px; - > [data-icon] { + > i { margin-right: 4px; } } diff --git a/src/client/widgets/server-metric/disk.vue b/src/client/widgets/server-metric/disk.vue index fa5933e7b900e3d2cd1aa91b098b435025239e93..a3f5d0376bee62fddfdd409a3ba3c94737821a0b 100644 --- a/src/client/widgets/server-metric/disk.vue +++ b/src/client/widgets/server-metric/disk.vue @@ -2,7 +2,7 @@ <div class="zbwaqsat"> <XPie class="pie" :value="usage"/> <div> - <p><fa :icon="faHdd"/>Disk</p> + <p><i class="fas fa-hdd"></i>Disk</p> <p>Total: {{ bytes(total, 1) }}</p> <p>Free: {{ bytes(available, 1) }}</p> <p>Used: {{ bytes(used, 1) }}</p> @@ -12,7 +12,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faHdd } from '@fortawesome/free-solid-svg-icons'; import XPie from './pie.vue'; import bytes from '@client/filters/bytes'; @@ -31,7 +30,6 @@ export default defineComponent({ total: this.meta.fs.total, used: this.meta.fs.used, available: this.meta.fs.total - this.meta.fs.used, - faHdd, }; }, methods: { @@ -62,7 +60,7 @@ export default defineComponent({ font-weight: bold; margin-bottom: 4px; - > [data-icon] { + > i { margin-right: 4px; } } diff --git a/src/client/widgets/server-metric/index.vue b/src/client/widgets/server-metric/index.vue index 7f2aea6b49f6ce5dacda0f5d1a8dacab08002f0b..6331b5bdf1c913a07cbc1ccabf1e37234b58cfbb 100644 --- a/src/client/widgets/server-metric/index.vue +++ b/src/client/widgets/server-metric/index.vue @@ -1,7 +1,7 @@ <template> <MkContainer :show-header="props.showHeader" :naked="props.transparent"> - <template #header><Fa :icon="faServer"/>{{ $ts._widgets.serverMetric }}</template> - <template #func><button @click="toggleView()" class="_button"><Fa :icon="faSort"/></button></template> + <template #header><i class="fas fa-server"></i>{{ $ts._widgets.serverMetric }}</template> + <template #func><button @click="toggleView()" class="_button"><i class="fas fa-sort"></i></button></template> <div class="mkw-serverMetric" v-if="meta"> <XCpuMemory v-if="props.view === 0" :connection="connection" :meta="meta"/> @@ -15,7 +15,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faServer, faSort } from '@fortawesome/free-solid-svg-icons'; import define from '../define'; import MkContainer from '@client/components/ui/container.vue'; import XCpuMemory from './cpu-mem.vue'; @@ -58,7 +57,6 @@ export default defineComponent({ return { meta: null, connection: null, - faServer, faSort, }; }, created() { diff --git a/src/client/widgets/server-metric/mem.vue b/src/client/widgets/server-metric/mem.vue index 89fa8fef43945fdc74c5cb5ee5640bbcf0672e4a..92c0aa0c77fa271472737f8e21bdd346be3bd06e 100644 --- a/src/client/widgets/server-metric/mem.vue +++ b/src/client/widgets/server-metric/mem.vue @@ -2,7 +2,7 @@ <div class="zlxnikvl"> <XPie class="pie" :value="usage"/> <div> - <p><fa :icon="faMemory"/>RAM</p> + <p><i class="fas fa-memory"></i>RAM</p> <p>Total: {{ bytes(total, 1) }}</p> <p>Used: {{ bytes(used, 1) }}</p> <p>Free: {{ bytes(free, 1) }}</p> @@ -12,7 +12,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faMemory } from '@fortawesome/free-solid-svg-icons'; import XPie from './pie.vue'; import bytes from '@client/filters/bytes'; @@ -34,7 +33,6 @@ export default defineComponent({ total: 0, used: 0, free: 0, - faMemory, }; }, mounted() { @@ -77,7 +75,7 @@ export default defineComponent({ font-weight: bold; margin-bottom: 4px; - > [data-icon] { + > i { margin-right: 4px; } } diff --git a/src/client/widgets/slideshow.vue b/src/client/widgets/slideshow.vue index 69c5cc01b2c6e6ba4411d8b0c8eb68c3c35d7729..2f079e0d428559fa6ab7d74eecc7d11087020636 100644 --- a/src/client/widgets/slideshow.vue +++ b/src/client/widgets/slideshow.vue @@ -14,7 +14,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { } from '@fortawesome/free-solid-svg-icons'; import define from './define'; import * as os from '@client/os'; diff --git a/src/client/widgets/timeline.vue b/src/client/widgets/timeline.vue index f1ddc9cb801f6cf69990a9198ac1546c3eda0f86..8548574afc0590b5cf6e5f63a4d43a31f8e25c06 100644 --- a/src/client/widgets/timeline.vue +++ b/src/client/widgets/timeline.vue @@ -2,14 +2,14 @@ <MkContainer :show-header="props.showHeader" :style="`height: ${props.height}px;`" :scrollable="true"> <template #header> <button @click="choose" class="_button"> - <Fa v-if="props.src === 'home'" :icon="faHome"/> - <Fa v-if="props.src === 'local'" :icon="faComments"/> - <Fa v-if="props.src === 'social'" :icon="faShareAlt"/> - <Fa v-if="props.src === 'global'" :icon="faGlobe"/> - <Fa v-if="props.src === 'list'" :icon="faListUl"/> - <Fa v-if="props.src === 'antenna'" :icon="faSatellite"/> + <i v-if="props.src === 'home'" class="fas fa-home"></i> + <i v-else-if="props.src === 'local'" class="fas fa-comments"></i> + <i v-else-if="props.src === 'social'" class="fas fa-share-alt"></i> + <i v-else-if="props.src === 'global'" class="fas fa-globe"></i> + <i v-else-if="props.src === 'list'" class="fas fa-list-ul"></i> + <i v-else-if="props.src === 'antenna'" class="fas fa-satellite"></i> <span style="margin-left: 8px;">{{ props.src === 'list' ? props.list.name : props.src === 'antenna' ? props.antenna.name : $t('_timelines.' + props.src) }}</span> - <Fa :icon="menuOpened ? faAngleUp : faAngleDown" style="margin-left: 8px;"/> + <i :class="menuOpened ? 'fas fa-angle-up' : 'fas fa-angle-down'" style="margin-left: 8px;"></i> </button> </template> @@ -21,8 +21,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faAngleDown, faAngleUp, faHome, faShareAlt, faGlobe, faListUl, faSatellite } from '@fortawesome/free-solid-svg-icons'; -import { faComments } from '@fortawesome/free-regular-svg-icons'; import MkContainer from '@client/components/ui/container.vue'; import XTimeline from '@client/components/timeline.vue'; import define from './define'; @@ -62,7 +60,6 @@ export default defineComponent({ data() { return { menuOpened: false, - faAngleDown, faAngleUp, faHome, faShareAlt, faGlobe, faComments, faListUl, faSatellite }; }, @@ -75,7 +72,7 @@ export default defineComponent({ ]); const antennaItems = antennas.map(antenna => ({ text: antenna.name, - icon: faSatellite, + icon: 'fas fa-satellite', action: () => { this.props.antenna = antenna; this.setSrc('antenna'); @@ -83,7 +80,7 @@ export default defineComponent({ })); const listItems = lists.map(list => ({ text: list.name, - icon: faListUl, + icon: 'fas fa-list-ul', action: () => { this.props.list = list; this.setSrc('list'); @@ -91,19 +88,19 @@ export default defineComponent({ })); os.modalMenu([{ text: this.$ts._timelines.home, - icon: faHome, + icon: 'fas fa-home', action: () => { this.setSrc('home') } }, { text: this.$ts._timelines.local, - icon: faComments, + icon: 'fas fa-comments', action: () => { this.setSrc('local') } }, { text: this.$ts._timelines.social, - icon: faShareAlt, + icon: 'fas fa-share-alt', action: () => { this.setSrc('social') } }, { text: this.$ts._timelines.global, - icon: faGlobe, + icon: 'fas fa-globe', action: () => { this.setSrc('global') } }, antennaItems.length > 0 ? null : undefined, ...antennaItems, listItems.length > 0 ? null : undefined, ...listItems], ev.currentTarget || ev.target).then(() => { this.menuOpened = false; diff --git a/src/client/widgets/trends.vue b/src/client/widgets/trends.vue index cd7202f1f8c124ee6808ee75e5c2386caade31f3..8511bc718f667e50a295969b95b6525a82df28f8 100644 --- a/src/client/widgets/trends.vue +++ b/src/client/widgets/trends.vue @@ -1,6 +1,6 @@ <template> <MkContainer :show-header="props.showHeader"> - <template #header><Fa :icon="faHashtag"/>{{ $ts._widgets.trends }}</template> + <template #header><i class="fas fa-hashtag"></i>{{ $ts._widgets.trends }}</template> <div class="wbrkwala"> <MkLoading v-if="fetching"/> @@ -19,7 +19,6 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import { faHashtag } from '@fortawesome/free-solid-svg-icons'; import MkContainer from '@client/components/ui/container.vue'; import define from './define'; import MkMiniChart from '@client/components/mini-chart.vue'; @@ -44,7 +43,6 @@ export default defineComponent({ return { stats: [], fetching: true, - faHashtag }; }, mounted() { diff --git a/src/models/repositories/user.ts b/src/models/repositories/user.ts index 0d59ed2545e31993cdae1f69079365cd4357986a..1ebc16a5638dcfa46de9ddad1770bb5799ba1d5e 100644 --- a/src/models/repositories/user.ts +++ b/src/models/repositories/user.ts @@ -147,7 +147,7 @@ export class UserRepository extends Repository<User> { } public getOnlineStatus(user: User): string { - if (user.hideOnlineStatus == null) return 'unknown'; + if (user.hideOnlineStatus) return 'unknown'; if (user.lastActiveDate == null) return 'unknown'; const elapsed = Date.now() - user.lastActiveDate.getTime(); return ( diff --git a/src/server/api/endpoints/admin/update-remote-user.ts b/src/server/api/endpoints/federation/update-remote-user.ts similarity index 94% rename from src/server/api/endpoints/admin/update-remote-user.ts rename to src/server/api/endpoints/federation/update-remote-user.ts index 9577ac0a55bef69a076e17c01c75f12552bccf6a..1b7a9c4d5b9646bf8ea914de28143272f657ccdb 100644 --- a/src/server/api/endpoints/admin/update-remote-user.ts +++ b/src/server/api/endpoints/federation/update-remote-user.ts @@ -10,10 +10,9 @@ export const meta = { 'en-US': 'Update specified remote user information.' }, - tags: ['admin'], + tags: ['federation'], requireCredential: true as const, - requireModerator: true, params: { userId: { diff --git a/src/server/web/index.ts b/src/server/web/index.ts index 953f2b47f1733bdfcf8b84007fec4e2ababac7ba..1caab14cc24fd16957410ee7585608174f0b46b1 100644 --- a/src/server/web/index.ts +++ b/src/server/web/index.ts @@ -99,7 +99,7 @@ router.get('/manifest.json', require('./manifest')); router.get('/robots.txt', async ctx => { await send(ctx as any, '/robots.txt', { - root: assets + root: staticAssets }); }); diff --git a/src/server/web/views/base.pug b/src/server/web/views/base.pug index 22d5fd0c677cdc77d31d01dc449290ab32da865b..8992f96db9d9bcfdcf6599d275a37cb69c9b0abc 100644 --- a/src/server/web/views/base.pug +++ b/src/server/web/views/base.pug @@ -2,9 +2,11 @@ block vars doctype html -!= '\n<!-- Thank you for using Misskey! -->\n' -!= '\n<!-- If you are reading this message... how about joining the development of Misskey? -->\n' -!= '\n<!-- https://github.com/misskey-dev/misskey -->\n' +!= '\n' +!= '<!-- Thank you for using Misskey! -->\n' +!= '<!-- If you are reading this message... how about joining the development of Misskey? -->\n' +!= '<!-- https://github.com/misskey-dev/misskey -->' +!= '\n' html @@ -22,13 +24,15 @@ html link(rel='prefetch' href='https://xn--931a.moe/assets/info.jpg') link(rel='prefetch' href='https://xn--931a.moe/assets/not-found.jpg') link(rel='prefetch' href='https://xn--931a.moe/assets/error.jpg') + link(rel='preload' href='https://use.fontawesome.com/releases/v5.15.3/css/all.css' as='style') + link(rel='stylesheet' href='https://use.fontawesome.com/releases/v5.15.3/css/all.css') title block title = title || 'Misskey' block desc - meta(name='description' content= desc || '✨🌎✨ A federated blogging platform ✨🚀✨') + meta(name='description' content= desc || '✨🌎✨ A interplanetary communication platform ✨🚀✨') block meta diff --git a/webpack.config.ts b/webpack.config.ts index 9f2a3a89af20ed7c3bda1d704cba92f156dc3d61..296813caa0131ba5e238d9bfd9002a6e105c8aa1 100644 --- a/webpack.config.ts +++ b/webpack.config.ts @@ -70,7 +70,7 @@ module.exports = { options: { implementation: require('sass'), sassOptions: { - fiber: require('fibers') + fiber: false } } }] @@ -88,7 +88,7 @@ module.exports = { options: { implementation: require('sass'), sassOptions: { - fiber: require('fibers') + fiber: false } } }] diff --git a/yarn.lock b/yarn.lock index ac5b283498dfb82f14472628a8a6aca65ce81687..8d17fc1bc221bba8d7ab982ffe70ec84e1093262 100644 --- a/yarn.lock +++ b/yarn.lock @@ -227,44 +227,6 @@ minimatch "^3.0.4" strip-json-comments "^3.1.1" -"@fortawesome/fontawesome-common-types@^0.2.35": - version "0.2.35" - resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.35.tgz#01dd3d054da07a00b764d78748df20daf2b317e9" - integrity sha512-IHUfxSEDS9dDGqYwIW7wTN6tn/O8E0n5PcAHz9cAaBoZw6UpG20IG/YM3NNLaGPwPqgjBAFjIURzqoQs3rrtuw== - -"@fortawesome/fontawesome-svg-core@1.2.35": - version "1.2.35" - resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.2.35.tgz#85aea8c25645fcec88d35f2eb1045c38d3e65cff" - integrity sha512-uLEXifXIL7hnh2sNZQrIJWNol7cTVIzwI+4qcBIq9QWaZqUblm0IDrtSqbNg+3SQf8SMGHkiSigD++rHmCHjBg== - dependencies: - "@fortawesome/fontawesome-common-types" "^0.2.35" - -"@fortawesome/free-brands-svg-icons@5.15.3": - version "5.15.3" - resolved "https://registry.yarnpkg.com/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-5.15.3.tgz#bec2821d23b9c667be1d192a6c5bfb2667e588eb" - integrity sha512-1hirPcbjj72ZJtFvdnXGPbAbpn3Ox6mH3g5STbANFp3vGSiE5u5ingAKV06mK6ZVqNYxUPlh4DlTnaIvLtF2kw== - dependencies: - "@fortawesome/fontawesome-common-types" "^0.2.35" - -"@fortawesome/free-regular-svg-icons@5.15.3": - version "5.15.3" - resolved "https://registry.yarnpkg.com/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-5.15.3.tgz#1ec4f2410ff638db549c5c5484fc60b66407dbe6" - integrity sha512-q4/p8Xehy9qiVTdDWHL4Z+o5PCLRChePGZRTXkl+/Z7erDVL8VcZUuqzJjs6gUz6czss4VIPBRdCz6wP37/zMQ== - dependencies: - "@fortawesome/fontawesome-common-types" "^0.2.35" - -"@fortawesome/free-solid-svg-icons@5.15.3": - version "5.15.3" - resolved "https://registry.yarnpkg.com/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.15.3.tgz#52eebe354f60dc77e0bde934ffc5c75ffd04f9d8" - integrity sha512-XPeeu1IlGYqz4VWGRAT5ukNMd4VHUEEJ7ysZ7pSSgaEtNvSo+FLurybGJVmiqkQdK50OkSja2bfZXOeyMGRD8Q== - dependencies: - "@fortawesome/fontawesome-common-types" "^0.2.35" - -"@fortawesome/vue-fontawesome@3.0.0-3": - version "3.0.0-3" - resolved "https://registry.yarnpkg.com/@fortawesome/vue-fontawesome/-/vue-fontawesome-3.0.0-3.tgz#b658a7c1f35d4eb04ac85749da693be483442b25" - integrity sha512-fCM7+R9M7Y/ipKC5n9hukGpJHhe53JOENGqtku/KWtpXsnbGik3AS5zfJYEupV2uXOw/5S0RSSfttQ2hNIrmFA== - "@jfonx/console-utils@^1.0.3": version "1.0.3" resolved "https://registry.yarnpkg.com/@jfonx/console-utils/-/console-utils-1.0.3.tgz#cbb7f911e4191a4a2fe1ba4807d29f100b5d099f" @@ -4326,13 +4288,6 @@ feed@4.2.2: dependencies: xml-js "^1.6.11" -fibers@5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/fibers/-/fibers-5.0.0.tgz#3a60e0695b3ee5f6db94e62726716fa7a59acc41" - integrity sha512-UpGv/YAZp7mhKHxDvC1tColrroGRX90sSvh8RMZV9leo+e5+EkRVgCEZPlmXeo3BUNQTZxUaVdLskq1Q2FyCPg== - dependencies: - detect-libc "^1.0.3" - figlet@^1.1.1: version "1.3.0" resolved "https://registry.yarnpkg.com/figlet/-/figlet-1.3.0.tgz#c49e3d92907ba13bebadc7124f76ba71f1f32ef0" @@ -6695,10 +6650,10 @@ methods@^1.1.2: resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= -mfm-js@0.16.0: - version "0.16.0" - resolved "https://registry.yarnpkg.com/mfm-js/-/mfm-js-0.16.0.tgz#71852124eba5564f8a94cd7476a4eaa4ddeed1cd" - integrity sha512-z33e1yPj9dLN+DjDHakhslvGhCnzTxsUNpodyFw3nemO6gnKOE1adUrm49jjB2boQxtBExKhH7FERMCsNFcpBQ== +mfm-js@0.16.2: + version "0.16.2" + resolved "https://registry.yarnpkg.com/mfm-js/-/mfm-js-0.16.2.tgz#6dfa44a9b6ac0fd9d55d6f8c21eaa60c75bcd9fa" + integrity sha512-Ah/XTPsg88il3kRwXxY6QqlNGkc9ToWWFhW9BGBk6V6T108iLjS30pd79WL02Nd1tw1Jl/JduJMgpb5QzCE45w== dependencies: twemoji-parser "13.0.x"