Merge branch 'develop'

This commit is contained in:
syuilo 2021-04-23 18:25:44 +09:00
commit 37dc1c9a82
282 changed files with 3796 additions and 3553 deletions

View file

@ -138,7 +138,7 @@ flagAsBotDescription: "このアカウントがプログラムによって運用
flagAsCat: "Catとして設定" flagAsCat: "Catとして設定"
flagAsCatDescription: "このアカウントが猫であることを示す場合は、このフラグをオンにします。" flagAsCatDescription: "このアカウントが猫であることを示す場合は、このフラグをオンにします。"
autoAcceptFollowed: "フォロー中ユーザーからのフォロリクを自動承認" autoAcceptFollowed: "フォロー中ユーザーからのフォロリクを自動承認"
addAcount: "アカウント追加" addAccount: "アカウント追加"
loginFailed: "ログインに失敗しました" loginFailed: "ログインに失敗しました"
showOnRemote: "リモートで表示" showOnRemote: "リモートで表示"
general: "全般" general: "全般"
@ -183,7 +183,7 @@ clearQueueConfirmTitle: "キューをクリアしますか?"
clearQueueConfirmText: "未配達の投稿は配送されなくなります。通常この操作を行う必要はありません。" clearQueueConfirmText: "未配達の投稿は配送されなくなります。通常この操作を行う必要はありません。"
clearCachedFiles: "キャッシュをクリア" clearCachedFiles: "キャッシュをクリア"
clearCachedFilesConfirm: "キャッシュされたリモートファイルをすべて削除しますか?" clearCachedFilesConfirm: "キャッシュされたリモートファイルをすべて削除しますか?"
blockedInstances: "インスタンスブロック" blockedInstances: "ブロックしたインスタンス"
blockedInstancesDescription: "ブロックしたいインスタンスのホストを改行で区切って設定します。ブロックされたインスタンスは、このインスタンスとやり取りできなくなります。" blockedInstancesDescription: "ブロックしたいインスタンスのホストを改行で区切って設定します。ブロックされたインスタンスは、このインスタンスとやり取りできなくなります。"
muteAndBlock: "ミュートとブロック" muteAndBlock: "ミュートとブロック"
mutedUsers: "ミュートしたユーザー" mutedUsers: "ミュートしたユーザー"
@ -349,7 +349,6 @@ antennaExcludeKeywords: "除外キーワード"
antennaKeywordsDescription: "スペースで区切るとAND指定になり、改行で区切るとOR指定になります" antennaKeywordsDescription: "スペースで区切るとAND指定になり、改行で区切るとOR指定になります"
notifyAntenna: "新しいノートを通知する" notifyAntenna: "新しいノートを通知する"
withFileAntenna: "ファイルが添付されたノートのみ" withFileAntenna: "ファイルが添付されたノートのみ"
serviceworker: "ServiceWorker"
enableServiceworker: "ServiceWorkerを有効にする" enableServiceworker: "ServiceWorkerを有効にする"
antennaUsersDescription: "ユーザー名を改行で区切って指定します" antennaUsersDescription: "ユーザー名を改行で区切って指定します"
caseSensitive: "大文字小文字を区別する" caseSensitive: "大文字小文字を区別する"
@ -453,7 +452,7 @@ category: "カテゴリ"
tags: "タグ" tags: "タグ"
docSource: "このドキュメントのソース" docSource: "このドキュメントのソース"
createAccount: "アカウントを作成" createAccount: "アカウントを作成"
existingAcount: "既存のアカウント" existingAccount: "既存のアカウント"
regenerate: "再生成" regenerate: "再生成"
fontSize: "フォントサイズ" fontSize: "フォントサイズ"
noFollowRequests: "フォロー申請はありません" noFollowRequests: "フォロー申請はありません"
@ -568,7 +567,7 @@ pluginTokenRequestedDescription: "このプラグインはここで設定した
notificationType: "通知の種類" notificationType: "通知の種類"
edit: "編集" edit: "編集"
useStarForReactionFallback: "リアクション絵文字が不明な場合、代わりに★を使う" useStarForReactionFallback: "リアクション絵文字が不明な場合、代わりに★を使う"
emailConfig: "メールサーバー設定" emailServer: "メールサーバー"
enableEmail: "メール配信機能を有効化する" enableEmail: "メール配信機能を有効化する"
emailConfigInfo: "メールアドレスの確認やパスワードリセットの際に使います" emailConfigInfo: "メールアドレスの確認やパスワードリセットの際に使います"
email: "メール" email: "メール"
@ -728,6 +727,20 @@ hideOnlineStatusDescription: "オンライン状態を隠すと、検索など
online: "オンライン" online: "オンライン"
active: "アクティブ" active: "アクティブ"
offline: "オフライン" offline: "オフライン"
notRecommended: "非推奨"
botProtection: "Bot防御"
instanceBlocking: "インスタンスブロック"
selectAccount: "アカウントを選択"
enabled: "有効"
disabled: "無効"
quickAction: "クイックアクション"
user: "ユーザー"
administration: "管理"
accounts: "アカウント"
switch: "切り替え"
noMaintainerInformationWarning: "管理者情報が設定されていません。"
noBotProtectionWarning: "Bot防御が設定されていません。"
configure: "設定する"
_email: _email:
_follow: _follow:

View file

@ -1,7 +1,7 @@
{ {
"name": "misskey", "name": "misskey",
"author": "syuilo <syuilotan@yahoo.co.jp>", "author": "syuilo <syuilotan@yahoo.co.jp>",
"version": "12.77.1", "version": "12.78.0",
"codename": "indigo", "codename": "indigo",
"repository": { "repository": {
"type": "git", "type": "git",
@ -39,11 +39,6 @@
"dependencies": { "dependencies": {
"@babel/plugin-transform-runtime": "7.13.15", "@babel/plugin-transform-runtime": "7.13.15",
"@elastic/elasticsearch": "7.11.0", "@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/cors": "3.1.0",
"@koa/multer": "3.0.0", "@koa/multer": "3.0.0",
"@koa/router": "9.0.1", "@koa/router": "9.0.1",
@ -140,7 +135,6 @@
"eslint-plugin-vue": "7.9.0", "eslint-plugin-vue": "7.9.0",
"eventemitter3": "4.0.7", "eventemitter3": "4.0.7",
"feed": "4.2.2", "feed": "4.2.2",
"fibers": "5.0.0",
"file-type": "16.3.0", "file-type": "16.3.0",
"fluent-ffmpeg": "2.1.2", "fluent-ffmpeg": "2.1.2",
"glob": "7.1.6", "glob": "7.1.6",
@ -181,7 +175,7 @@
"markdown-it": "12.0.5", "markdown-it": "12.0.5",
"markdown-it-anchor": "7.1.0", "markdown-it-anchor": "7.1.0",
"matter-js": "0.17.1", "matter-js": "0.17.1",
"mfm-js": "0.16.0", "mfm-js": "0.16.2",
"mocha": "8.3.2", "mocha": "8.3.2",
"moji": "0.5.1", "moji": "0.5.1",
"ms": "2.1.3", "ms": "2.1.3",

View file

@ -1,7 +1,7 @@
<template> <template>
<XWindow ref="window" :initial-width="400" :initial-height="500" :can-resize="true" @closed="$emit('closed')"> <XWindow ref="window" :initial-width="400" :initial-height="500" :can-resize="true" @closed="$emit('closed')">
<template #header> <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"> <I18n :src="$ts.reportAbuseOf" tag="span">
<template #name> <template #name>
<b><MkAcct :user="user"/></b> <b><MkAcct :user="user"/></b>
@ -24,7 +24,6 @@
<script lang="ts"> <script lang="ts">
import { defineComponent, markRaw } from 'vue'; import { defineComponent, markRaw } from 'vue';
import { faExclamationCircle } from '@fortawesome/free-solid-svg-icons';
import XWindow from '@client/components/ui/window.vue'; import XWindow from '@client/components/ui/window.vue';
import MkTextarea from '@client/components/ui/textarea.vue'; import MkTextarea from '@client/components/ui/textarea.vue';
import MkButton from '@client/components/ui/button.vue'; import MkButton from '@client/components/ui/button.vue';
@ -53,7 +52,6 @@ export default defineComponent({
data() { data() {
return { return {
comment: this.initialComment || '', comment: this.initialComment || '',
faExclamationCircle,
}; };
}, },

View file

@ -18,7 +18,7 @@ type Captcha = {
getResponse(id: string): string; getResponse(id: string): string;
}; };
type CaptchaProvider = 'hcaptcha' | 'grecaptcha'; type CaptchaProvider = 'hcaptcha' | 'recaptcha';
type CaptchaContainer = { type CaptchaContainer = {
readonly [_ in CaptchaProvider]?: Captcha; readonly [_ in CaptchaProvider]?: Captcha;
@ -57,7 +57,7 @@ export default defineComponent({
src() { src() {
const endpoint = ({ const endpoint = ({
hcaptcha: 'https://hcaptcha.com/1', hcaptcha: 'https://hcaptcha.com/1',
grecaptcha: 'https://www.recaptcha.net/recaptcha', recaptcha: 'https://www.recaptcha.net/recaptcha',
} as Record<PropertyKey, unknown>)[this.provider]; } as Record<PropertyKey, unknown>)[this.provider];
return `${typeof endpoint == 'string' ? endpoint : 'about:invalid'}/api.js?render=explicit`; return `${typeof endpoint == 'string' ? endpoint : 'about:invalid'}/api.js?render=explicit`;

View file

@ -6,21 +6,20 @@
> >
<template v-if="!wait"> <template v-if="!wait">
<template v-if="isFollowing"> <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>
<template v-else> <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> </template>
<template v-else> <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> </template>
</button> </button>
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { faSpinner, faPlus, faMinus, } from '@fortawesome/free-solid-svg-icons';
import * as os from '@client/os'; import * as os from '@client/os';
export default defineComponent({ export default defineComponent({
@ -40,7 +39,6 @@ export default defineComponent({
return { return {
isFollowing: this.channel.isFollowing, isFollowing: this.channel.isFollowing,
wait: false, wait: false,
faSpinner, faPlus, faMinus,
}; };
}, },

View file

@ -2,10 +2,10 @@
<MkA :to="`/channels/${channel.id}`" class="eftoefju _panel" tabindex="-1"> <MkA :to="`/channels/${channel.id}`" class="eftoefju _panel" tabindex="-1">
<div class="banner" :style="bannerStyle"> <div class="banner" :style="bannerStyle">
<div class="fade"></div> <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 class="status">
<div> <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;"> <I18n :src="$ts._channel.usersCount" tag="span" style="margin-left: 4px;">
<template #n> <template #n>
<b>{{ channel.usersCount }}</b> <b>{{ channel.usersCount }}</b>
@ -13,7 +13,7 @@
</I18n> </I18n>
</div> </div>
<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;"> <I18n :src="$ts._channel.notesCount" tag="span" style="margin-left: 4px;">
<template #n> <template #n>
<b>{{ channel.notesCount }}</b> <b>{{ channel.notesCount }}</b>
@ -35,7 +35,6 @@
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { faSatelliteDish, faUsers, faPencilAlt } from '@fortawesome/free-solid-svg-icons';
export default defineComponent({ export default defineComponent({
props: { props: {
@ -57,7 +56,6 @@ export default defineComponent({
data() { data() {
return { return {
faSatelliteDish, faUsers, faPencilAlt,
}; };
}, },
}); });

View file

@ -1,7 +1,5 @@
<script lang="ts"> <script lang="ts">
import { defineComponent, h, TransitionGroup } from 'vue'; import { defineComponent, h, TransitionGroup } from 'vue';
import { faAngleUp, faAngleDown } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
export default defineComponent({ export default defineComponent({
props: { props: {
@ -73,17 +71,15 @@ export default defineComponent({
class: 'date' class: 'date'
}, [ }, [
h('span', [ h('span', [
h(FontAwesomeIcon, { h('i', {
class: 'icon', class: 'fas fa-angle-up icon',
icon: faAngleUp,
}), }),
this.getDateText(item.createdAt) this.getDateText(item.createdAt)
]), ]),
h('span', [ h('span', [
this.getDateText(this.items[i + 1].createdAt), this.getDateText(this.items[i + 1].createdAt),
h(FontAwesomeIcon, { h('i', {
class: 'icon', class: 'fas fa-angle-down icon',
icon: faAngleDown,
}) })
]) ])
])); ]));

View file

@ -2,15 +2,15 @@
<MkModal ref="modal" @click="done(true)" @closed="$emit('closed')"> <MkModal ref="modal" @click="done(true)" @closed="$emit('closed')">
<div class="mk-dialog"> <div class="mk-dialog">
<div class="icon" v-if="icon"> <div class="icon" v-if="icon">
<Fa :icon="icon"/> <i :class="icon"></i>
</div> </div>
<div class="icon" v-else-if="!input && !select" :class="type"> <div class="icon" v-else-if="!input && !select" :class="type">
<Fa :icon="faCheck" v-if="type === 'success'"/> <i v-if="type === 'success'" class="fas fa-check"></i>
<Fa :icon="faTimesCircle" v-if="type === 'error'"/> <i v-else-if="type === 'error'" class="fas fa-times-circle"></i>
<Fa :icon="faExclamationTriangle" v-if="type === 'warning'"/> <i v-else-if="type === 'warning'" class="fas fa-exclamation-triangle"></i>
<Fa :icon="faInfoCircle" v-if="type === 'info'"/> <i v-else-if="type === 'info'" class="fas fa-info-circle"></i>
<Fa :icon="faQuestionCircle" v-if="type === 'question'"/> <i v-else-if="type === 'question'" class="fas fa-question-circle"></i>
<Fa :icon="faSpinner" pulse v-if="type === 'waiting'"/> <i v-else-if="type === 'waiting'" class="fas fa-spinner fa-pulse"></i>
</div> </div>
<header v-if="title"><Mfm :text="title"/></header> <header v-if="title"><Mfm :text="title"/></header>
<div class="body" v-if="text"><Mfm :text="text"/></div> <div class="body" v-if="text"><Mfm :text="text"/></div>
@ -38,8 +38,6 @@
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; 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 MkModal from '@client/components/ui/modal.vue';
import MkButton from '@client/components/ui/button.vue'; import MkButton from '@client/components/ui/button.vue';
import MkInput from '@client/components/ui/input.vue'; import MkInput from '@client/components/ui/input.vue';
@ -99,7 +97,6 @@ export default defineComponent({
return { return {
inputValue: this.input && this.input.default ? this.input.default : null, 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, 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
}; };
}, },

View file

@ -1,31 +1,21 @@
<template> <template>
<div class="zdjebgpv" ref="thumbnail"> <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 }`"/> <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'"/> <i v-else-if="is === 'image'" class="fas fa-file-image icon"></i>
<Fa :icon="faFileVideo" class="icon" v-else-if="is === 'video'"/> <i v-else-if="is === 'video'" class="fas fa-file-video icon"></i>
<Fa :icon="faMusic" class="icon" v-else-if="is === 'audio' || is === 'midi'"/> <i v-else-if="is === 'audio' || is === 'midi'" class="fas fa-music icon"></i>
<Fa :icon="faFileCsv" class="icon" v-else-if="is === 'csv'"/> <i v-else-if="is === 'csv'" class="fas fa-file-csv icon"></i>
<Fa :icon="faFilePdf" class="icon" v-else-if="is === 'pdf'"/> <i v-else-if="is === 'pdf'" class="fas fa-file-pdf icon"></i>
<Fa :icon="faFileAlt" class="icon" v-else-if="is === 'textfile'"/> <i v-else-if="is === 'textfile'" class="fas fa-file-alt icon"></i>
<Fa :icon="faFileArchive" class="icon" v-else-if="is === 'archive'"/> <i v-else-if="is === 'archive'" class="fas fa-file-archive icon"></i>
<Fa :icon="faFile" class="icon" v-else/> <i v-else class="fas fa-file icon"></i>
<Fa :icon="faFilm" class="icon-sub" v-if="isThumbnailAvailable && is === 'video'"/>
<i v-if="isThumbnailAvailable && is === 'video'" class="fas fa-film icon-sub"></i>
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; 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 ImgWithBlurhash from '@client/components/img-with-blurhash.vue';
import { ColdDeviceStorage } from '@client/store'; import { ColdDeviceStorage } from '@client/store';
@ -49,15 +39,6 @@ export default defineComponent({
isContextmenuShowing: false, isContextmenuShowing: false,
isDragging: false, isDragging: false,
faFile,
faFileAlt,
faFileImage,
faMusic,
faFileVideo,
faFileCsv,
faFilePdf,
faFileArchive,
faFilm
}; };
}, },
computed: { computed: {

View file

@ -32,8 +32,6 @@
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; 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 copyToClipboard from '@client/scripts/copy-to-clipboard';
import MkDriveFileThumbnail from './drive-file-thumbnail.vue'; import MkDriveFileThumbnail from './drive-file-thumbnail.vue';
import bytes from '@client/filters/bytes'; import bytes from '@client/filters/bytes';
@ -87,22 +85,22 @@ export default defineComponent({
action: this.rename action: this.rename
}, { }, {
text: this.file.isSensitive ? this.$ts.unmarkAsSensitive : this.$ts.markAsSensitive, 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 action: this.toggleSensitive
}, null, { }, null, {
text: this.$ts.copyUrl, text: this.$ts.copyUrl,
icon: faLink, icon: 'fas fa-link',
action: this.copyUrl action: this.copyUrl
}, { }, {
type: 'a', type: 'a',
href: this.file.url, href: this.file.url,
target: '_blank', target: '_blank',
text: this.$ts.download, text: this.$ts.download,
icon: faDownload, icon: 'fas fa-download',
download: this.file.name download: this.file.name
}, null, { }, null, {
text: this.$ts.delete, text: this.$ts.delete,
icon: faTrashAlt, icon: 'fas fa-trash-alt',
danger: true, danger: true,
action: this.deleteFile action: this.deleteFile
}]; }];

View file

@ -15,8 +15,8 @@
:title="title" :title="title"
> >
<p class="name"> <p class="name">
<template v-if="hover"><Fa :icon="faFolderOpen" fixed-width/></template> <template v-if="hover"><i class="fas fa-folder-open fa-fw"></i></template>
<template v-if="!hover"><Fa :icon="faFolder" fixed-width/></template> <template v-if="!hover"><i class="fas fa-folder fa-fw"></i></template>
{{ folder.name }} {{ folder.name }}
</p> </p>
<p class="upload" v-if="$store.state.uploadFolder == folder.id"> <p class="upload" v-if="$store.state.uploadFolder == folder.id">
@ -28,9 +28,7 @@
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { faFolder, faFolderOpen, faTrashAlt, faWindowRestore } from '@fortawesome/free-regular-svg-icons';
import * as os from '@client/os'; import * as os from '@client/os';
import { faICursor } from '@fortawesome/free-solid-svg-icons';
export default defineComponent({ export default defineComponent({
props: { props: {
@ -57,7 +55,6 @@ export default defineComponent({
hover: false, hover: false,
draghover: false, draghover: false,
isDragging: false, isDragging: false,
faFolder, faFolderOpen
}; };
}, },
@ -241,7 +238,7 @@ export default defineComponent({
onContextmenu(e) { onContextmenu(e) {
os.contextMenu([{ os.contextMenu([{
text: this.$ts.openInWindow, text: this.$ts.openInWindow,
icon: faWindowRestore, icon: 'fas fa-window-restore',
action: () => { action: () => {
os.popup(import('./drive-window.vue'), { os.popup(import('./drive-window.vue'), {
initialFolder: this.folder initialFolder: this.folder
@ -254,7 +251,7 @@ export default defineComponent({
action: this.rename action: this.rename
}, null, { }, null, {
text: this.$ts.delete, text: this.$ts.delete,
icon: faTrashAlt, icon: 'fas fa-trash-alt',
danger: true, danger: true,
action: this.deleteFolder action: this.deleteFolder
}], e); }], e);
@ -312,7 +309,7 @@ export default defineComponent({
font-size: 0.9em; font-size: 0.9em;
color: var(--desktopDriveFolderFg); color: var(--desktopDriveFolderFg);
> [data-icon] { > i {
margin-right: 4px; margin-right: 4px;
margin-left: 2px; margin-left: 2px;
text-align: left; text-align: left;

View file

@ -7,14 +7,13 @@
@dragleave="onDragleave" @dragleave="onDragleave"
@drop.stop="onDrop" @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> <span>{{ folder == null ? $ts.drive : folder.name }}</span>
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { faCloud } from '@fortawesome/free-solid-svg-icons';
import * as os from '@client/os'; import * as os from '@client/os';
export default defineComponent({ export default defineComponent({
@ -29,7 +28,6 @@ export default defineComponent({
return { return {
hover: false, hover: false,
draghover: false, draghover: false,
faCloud
}; };
}, },

View file

@ -4,10 +4,10 @@
<div class="path" @contextmenu.prevent.stop="() => {}"> <div class="path" @contextmenu.prevent.stop="() => {}">
<XNavFolder :class="{ current: folder == null }"/> <XNavFolder :class="{ current: folder == null }"/>
<template v-for="f in hierarchyFolders"> <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"/> <XNavFolder :folder="f"/>
</template> </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> <span class="folder current" v-if="folder != null">{{ folder.name }}</span>
</div> </div>
</nav> </nav>
@ -47,13 +47,11 @@
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { faAngleRight, faFolderPlus, faICursor, faLink, faUpload } from '@fortawesome/free-solid-svg-icons';
import XNavFolder from './drive.nav-folder.vue'; import XNavFolder from './drive.nav-folder.vue';
import XFolder from './drive.folder.vue'; import XFolder from './drive.folder.vue';
import XFile from './drive.file.vue'; import XFile from './drive.file.vue';
import MkButton from './ui/button.vue'; import MkButton from './ui/button.vue';
import * as os from '@client/os'; import * as os from '@client/os';
import { faTrashAlt } from '@fortawesome/free-regular-svg-icons';
export default defineComponent({ export default defineComponent({
components: { components: {
@ -125,7 +123,6 @@ export default defineComponent({
), ),
moreFilesElement: null as Element, moreFilesElement: null as Element,
faAngleRight
}; };
}, },
@ -606,11 +603,11 @@ export default defineComponent({
type: 'label' type: 'label'
}, { }, {
text: this.$ts.upload, text: this.$ts.upload,
icon: faUpload, icon: 'fas fa-upload',
action: () => { this.selectLocalFile(); } action: () => { this.selectLocalFile(); }
}, { }, {
text: this.$ts.fromUrl, text: this.$ts.fromUrl,
icon: faLink, icon: 'fas fa-link',
action: () => { this.urlUpload(); } action: () => { this.urlUpload(); }
}, null, { }, null, {
text: this.folder ? this.folder.name : this.$ts.drive, text: this.folder ? this.folder.name : this.$ts.drive,
@ -621,11 +618,11 @@ export default defineComponent({
action: () => { this.renameFolder(this.folder); } action: () => { this.renameFolder(this.folder); }
} : undefined, this.folder ? { } : undefined, this.folder ? {
text: this.$ts.deleteFolder, text: this.$ts.deleteFolder,
icon: faTrashAlt, icon: 'fas fa-trash-alt',
action: () => { this.deleteFolder(this.folder); } action: () => { this.deleteFolder(this.folder); }
} : undefined, { } : undefined, {
text: this.$ts.createFolder, text: this.$ts.createFolder,
icon: faFolderPlus, icon: 'fas fa-folder-plus',
action: () => { this.createFolder(); } action: () => { this.createFolder(); }
}]; }];
}, },
@ -693,7 +690,7 @@ export default defineComponent({
opacity: 0.5; opacity: 0.5;
cursor: default; cursor: default;
> [data-icon] { > i {
margin: 0; margin: 0;
} }
} }

View file

@ -1,7 +1,7 @@
<template> <template>
<section> <section>
<header class="_acrylic" @click="shown = !shown"> <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> </header>
<div v-if="shown"> <div v-if="shown">
<button v-for="emoji in emojis" <button v-for="emoji in emojis"
@ -17,7 +17,6 @@
<script lang="ts"> <script lang="ts">
import { defineComponent, markRaw } from 'vue'; import { defineComponent, markRaw } from 'vue';
import { faChevronUp, faChevronDown } from '@fortawesome/free-solid-svg-icons';
import { getStaticImageUrl } from '@client/scripts/get-static-image-url'; import { getStaticImageUrl } from '@client/scripts/get-static-image-url';
export default defineComponent({ export default defineComponent({
@ -36,7 +35,6 @@ export default defineComponent({
return { return {
getStaticImageUrl, getStaticImageUrl,
shown: this.initialShown, shown: this.initialShown,
faChevronUp, faChevronDown,
}; };
}, },

View file

@ -42,7 +42,7 @@
</section> </section>
<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> <div>
<button v-for="emoji in $store.state.recentlyUsedEmojis" <button v-for="emoji in $store.state.recentlyUsedEmojis"
class="_button" class="_button"
@ -64,10 +64,10 @@
</div> </div>
</div> </div>
<div class="tabs"> <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 === 'index' }" @click="tab = 'index'"><i class="fas fa-asterisk fa-fw"></i></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 === 'custom' }" @click="tab = 'custom'"><i class="fas fa-laugh fa-fw"></i></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 === 'unicode' }" @click="tab = 'unicode'"><i class="fas fa-leaf fa-fw"></i></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 === 'tags' }" @click="tab = 'tags'"><i class="fas fa-hashtag fa-fw"></i></button>
</div> </div>
</div> </div>
</template> </template>
@ -76,8 +76,6 @@
import { defineComponent, markRaw } from 'vue'; import { defineComponent, markRaw } from 'vue';
import { emojilist } from '@/misc/emojilist'; import { emojilist } from '@/misc/emojilist';
import { getStaticImageUrl } from '@client/scripts/get-static-image-url'; 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 Particle from '@client/components/particle.vue';
import * as os from '@client/os'; import * as os from '@client/os';
import { isDeviceTouch } from '@client/scripts/is-device-touch'; import { isDeviceTouch } from '@client/scripts/is-device-touch';
@ -117,7 +115,6 @@ export default defineComponent({
searchResultUnicode: [], searchResultUnicode: [],
tab: 'index', tab: 'index',
categories: ['face', 'people', 'animals_and_nature', 'food_and_drink', 'activity', 'travel_and_places', 'objects', 'symbols', 'flags'], 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,
}; };
}, },

View file

@ -1,12 +1,11 @@
<template> <template>
<span class="mk-file-type-icon"> <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> </span>
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { faFileImage } from '@fortawesome/free-solid-svg-icons';
import * as os from '@client/os'; import * as os from '@client/os';
export default defineComponent({ export default defineComponent({
@ -18,7 +17,6 @@ export default defineComponent({
}, },
data() { data() {
return { return {
faFileImage
}; };
}, },
computed: { computed: {

View file

@ -6,30 +6,29 @@
> >
<template v-if="!wait"> <template v-if="!wait">
<template v-if="hasPendingFollowRequestFromYou && user.isLocked"> <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>
<template v-else-if="hasPendingFollowRequestFromYou && !user.isLocked"> <!-- つまりリモートフォローの場合 --> <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>
<template v-else-if="isFollowing"> <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>
<template v-else-if="!isFollowing && user.isLocked"> <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>
<template v-else-if="!isFollowing && !user.isLocked"> <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> </template>
<template v-else> <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> </template>
</button> </button>
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { faSpinner, faPlus, faMinus, faHourglassHalf } from '@fortawesome/free-solid-svg-icons';
import * as os from '@client/os'; import * as os from '@client/os';
export default defineComponent({ export default defineComponent({
@ -56,7 +55,6 @@ export default defineComponent({
hasPendingFollowRequestFromYou: this.user.hasPendingFollowRequestFromYou, hasPendingFollowRequestFromYou: this.user.hasPendingFollowRequestFromYou,
wait: false, wait: false,
connection: null, connection: null,
faSpinner, faPlus, faMinus, faHourglassHalf
}; };
}, },

View file

@ -24,6 +24,8 @@ export default defineComponent({
--formXPadding: 32px; --formXPadding: 32px;
--formYPadding: 32px; --formYPadding: 32px;
--formContentHMargin: 16px;
font-size: 95%; font-size: 95%;
line-height: 1.3em; line-height: 1.3em;
background: var(--bg); background: var(--bg);

View file

@ -30,7 +30,7 @@
top: var(--stickyTop, 0px); top: var(--stickyTop, 0px);
z-index: 2; z-index: 2;
margin: -8px calc(var(--formXPadding) * -1) 0 calc(var(--formXPadding) * -1); 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); background: var(--X17);
-webkit-backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
backdrop-filter: blur(10px); backdrop-filter: blur(10px);
@ -42,7 +42,7 @@
} }
._formCaption { ._formCaption {
padding: 8px 16px 0 16px; padding: 8px var(--formContentHMargin) 0 var(--formContentHMargin);
} }
._formItem { ._formItem {

View file

@ -1,8 +1,8 @@
<template> <template>
<div class="fzenkabp _formItem"> <div class="fzenkabp _formItem">
<div class="_formPanel" :class="{ warn }"> <div class="_formPanel" :class="{ warn }">
<i v-if="warn"><Fa :icon="faExclamationTriangle"/></i> <i v-if="warn" class="fas fa-exclamation-triangle"></i>
<i v-else><Fa :icon="faInfoCircle"/></i> <i v-else class="fas fa-info-circle"></i>
<slot></slot> <slot></slot>
</div> </div>
</div> </div>
@ -10,7 +10,6 @@
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { faInfoCircle, faExclamationTriangle } from '@fortawesome/free-solid-svg-icons';
export default defineComponent({ export default defineComponent({
props: { props: {
@ -22,7 +21,6 @@ export default defineComponent({
}, },
data() { data() {
return { return {
faInfoCircle, faExclamationTriangle
}; };
} }
}); });

View file

@ -30,13 +30,12 @@
</div> </div>
<template #caption><slot name="desc"></slot></template> <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> </FormGroup>
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, onMounted, onUnmounted, nextTick, ref, watch, computed, toRefs } from 'vue'; import { defineComponent, onMounted, onUnmounted, nextTick, ref, watch, computed, toRefs } from 'vue';
import { faExclamationCircle, faSave } from '@fortawesome/free-solid-svg-icons';
import './form.scss'; import './form.scss';
import FormButton from './button.vue'; import FormButton from './button.vue';
import FormGroup from './group.vue'; import FormGroup from './group.vue';
@ -191,7 +190,6 @@ export default defineComponent({
onInput, onInput,
onKeydown, onKeydown,
updated, updated,
faExclamationCircle, faSave,
}; };
}, },
}); });

View file

@ -20,7 +20,7 @@ export default defineComponent({
.anocepby { .anocepby {
display: flex; display: flex;
align-items: center; align-items: center;
padding: 14px 16px; padding: 14px var(--formContentHMargin);
> .key { > .key {
margin-right: 12px; margin-right: 12px;

View file

@ -5,7 +5,7 @@
<span class="text"><slot></slot></span> <span class="text"><slot></slot></span>
<span class="right"> <span class="right">
<span class="text"><slot name="suffix"></slot></span> <span class="text"><slot name="suffix"></slot></span>
<Fa :icon="faExternalLinkAlt" class="icon"/> <i class="fas fa-external-link-alt icon"></i>
</span> </span>
</a> </a>
<MkA class="main _button _formPanel _formClickable" :class="{ active }" :to="to" :behavior="behavior" v-else> <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="text"><slot></slot></span>
<span class="right"> <span class="right">
<span class="text"><slot name="suffix"></slot></span> <span class="text"><slot name="suffix"></slot></span>
<Fa :icon="faChevronRight" class="icon"/> <i class="fas fa-chevron-right icon"></i>
</span> </span>
</MkA> </MkA>
</div> </div>
@ -21,7 +21,6 @@
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { faChevronRight, faExternalLinkAlt } from '@fortawesome/free-solid-svg-icons';
import './form.scss'; import './form.scss';
export default defineComponent({ export default defineComponent({
@ -45,7 +44,6 @@ export default defineComponent({
}, },
data() { data() {
return { return {
faChevronRight, faExternalLinkAlt
}; };
} }
}); });

View file

@ -75,7 +75,7 @@ export default defineComponent({
max-width: 100%; max-width: 100%;
min-height: 130px; min-height: 130px;
margin: 0; margin: 0;
padding: 16px; padding: 16px var(--formContentHMargin);
box-sizing: border-box; box-sizing: border-box;
font: inherit; font: inherit;
font-weight: normal; font-weight: normal;

View file

@ -18,6 +18,9 @@ export default defineComponent({
} }
}, },
watch: { watch: {
modelValue() {
this.value = this.modelValue;
},
value() { value() {
this.$emit('update:modelValue', this.value); this.$emit('update:modelValue', this.value);
} }

View file

@ -14,7 +14,7 @@
<slot></slot> <slot></slot>
</select> </select>
<div class="suffix"> <div class="suffix">
<Fa :icon="faChevronDown"/> <i class="fas fa-chevron-down"></i>
</div> </div>
</div> </div>
<div class="_formCaption"><slot name="caption"></slot></div> <div class="_formCaption"><slot name="caption"></slot></div>
@ -23,7 +23,6 @@
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { faChevronDown } from '@fortawesome/free-solid-svg-icons';
import './form.scss'; import './form.scss';
export default defineComponent({ export default defineComponent({
@ -47,7 +46,6 @@ export default defineComponent({
}, },
data() { data() {
return { return {
faChevronDown,
}; };
}, },
computed: { computed: {

View file

@ -5,13 +5,13 @@
<MkLoading/> <MkLoading/>
</div> </div>
</div> </div>
<FormGroup v-else-if="resolved" class="_formItem"> <div v-else-if="resolved" class="_formItem">
<slot :result="result"></slot> <slot :result="result"></slot>
</FormGroup> </div>
<div class="_formItem" v-else> <div class="_formItem" v-else>
<div class="_formPanel"> <div class="_formPanel eiurkvay">
error! <div><i class="fas fa-exclamation-triangle"></i> {{ $ts.somethingHappened }}</div>
<button @click="retry">retry</button> <MkButton inline @click="retry" class="retry"><i class="fas fa-redo-alt"></i> {{ $ts.retry }}</MkButton>
</div> </div>
</div> </div>
</transition> </transition>
@ -20,11 +20,11 @@
<script lang="ts"> <script lang="ts">
import { defineComponent, PropType, ref, watch } from 'vue'; import { defineComponent, PropType, ref, watch } from 'vue';
import './form.scss'; import './form.scss';
import FormGroup from './group.vue'; import MkButton from '@client/components/ui/button.vue';
export default defineComponent({ export default defineComponent({
components: { components: {
FormGroup, MkButton
}, },
props: { props: {
@ -89,4 +89,13 @@ export default defineComponent({
.fade-leave-to { .fade-leave-to {
opacity: 0; opacity: 0;
} }
.eiurkvay {
padding: 16px;
text-align: center;
> .retry {
margin-top: 16px;
}
}
</style> </style>

View file

@ -18,13 +18,12 @@
</div> </div>
<template #caption><slot name="desc"></slot></template> <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> </FormGroup>
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, ref, toRefs, watch } from 'vue'; import { defineComponent, ref, toRefs, watch } from 'vue';
import { faSave } from '@fortawesome/free-solid-svg-icons';
import './form.scss'; import './form.scss';
import FormButton from './button.vue'; import FormButton from './button.vue';
import FormGroup from './group.vue'; import FormGroup from './group.vue';
@ -106,7 +105,6 @@ export default defineComponent({
changed, changed,
focus, focus,
onInput, onInput,
faSave,
}; };
} }
}); });

View file

@ -6,7 +6,6 @@
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { faExpandAlt, faColumns, faExternalLinkAlt, faLink, faWindowMaximize } from '@fortawesome/free-solid-svg-icons';
import * as os from '@client/os'; import * as os from '@client/os';
import copyToClipboard from '@client/scripts/copy-to-clipboard'; import copyToClipboard from '@client/scripts/copy-to-clipboard';
import { router } from '@client/router'; import { router } from '@client/router';
@ -57,31 +56,31 @@ export default defineComponent({
type: 'label', type: 'label',
text: this.to, text: this.to,
}, { }, {
icon: faWindowMaximize, icon: 'fas fa-window-maximize',
text: this.$ts.openInWindow, text: this.$ts.openInWindow,
action: () => { action: () => {
os.pageWindow(this.to); os.pageWindow(this.to);
} }
}, this.sideViewHook ? { }, this.sideViewHook ? {
icon: faColumns, icon: 'fas fa-columns',
text: this.$ts.openInSideView, text: this.$ts.openInSideView,
action: () => { action: () => {
this.sideViewHook(this.to); this.sideViewHook(this.to);
} }
} : undefined, { } : undefined, {
icon: faExpandAlt, icon: 'fas fa-expand-alt',
text: this.$ts.showInPage, text: this.$ts.showInPage,
action: () => { action: () => {
this.$router.push(this.to); this.$router.push(this.to);
} }
}, null, { }, null, {
icon: faExternalLinkAlt, icon: 'fas fa-external-link-alt',
text: this.$ts.openInNewTab, text: this.$ts.openInNewTab,
action: () => { action: () => {
window.open(this.to, '_blank'); window.open(this.to, '_blank');
} }
}, { }, {
icon: faLink, icon: 'fas fa-link',
text: this.$ts.copyLink, text: this.$ts.copyLink,
action: () => { action: () => {
copyToClipboard(`${url}${this.to}`); copyToClipboard(`${url}${this.to}`);

View file

@ -2,7 +2,7 @@
<transition :name="$store.state.animation ? 'zoom' : ''" appear> <transition :name="$store.state.animation ? 'zoom' : ''" appear>
<div class="mjndxjcg"> <div class="mjndxjcg">
<img src="https://xn--931a.moe/assets/error.jpg" class="_ghost"/> <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> <MkButton @click="() => $emit('retry')" class="button">{{ $ts.retry }}</MkButton>
</div> </div>
</transition> </transition>
@ -10,7 +10,6 @@
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons';
import MkButton from '@client/components/ui/button.vue'; import MkButton from '@client/components/ui/button.vue';
export default defineComponent({ export default defineComponent({
@ -19,7 +18,6 @@ export default defineComponent({
}, },
data() { data() {
return { return {
faExclamationTriangle
}; };
}, },
}); });

View file

@ -15,13 +15,12 @@
<span class="pathname" v-if="pathname != ''">{{ self ? pathname.substr(1) : pathname }}</span> <span class="pathname" v-if="pathname != ''">{{ self ? pathname.substr(1) : pathname }}</span>
<span class="query">{{ query }}</span> <span class="query">{{ query }}</span>
<span class="hash">{{ hash }}</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> </component>
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { faExternalLinkSquareAlt } from '@fortawesome/free-solid-svg-icons';
import { toUnicode as decodePunycode } from 'punycode/'; import { toUnicode as decodePunycode } from 'punycode/';
import { url as local } from '@client/config'; import { url as local } from '@client/config';
import { isDeviceTouch } from '@client/scripts/is-device-touch'; import { isDeviceTouch } from '@client/scripts/is-device-touch';
@ -55,7 +54,6 @@ export default defineComponent({
hideTimer: null, hideTimer: null,
checkTimer: null, checkTimer: null,
close: null, close: null,
faExternalLinkSquareAlt
}; };
}, },
created() { created() {

View file

@ -1,13 +1,12 @@
<template> <template>
<div class="mk-google"> <div class="mk-google">
<input type="search" v-model="query" :placeholder="q"> <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> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { faSearch } from '@fortawesome/free-solid-svg-icons';
import * as os from '@client/os'; import * as os from '@client/os';
export default defineComponent({ export default defineComponent({
@ -15,7 +14,6 @@ export default defineComponent({
data() { data() {
return { return {
query: null, query: null,
faSearch
}; };
}, },
mounted() { mounted() {

View file

@ -1,129 +1,40 @@
<template> <template>
<div class="zbcjwnqg" v-size="{ max: [550, 1000] }"> <div class="zbcjwnqg" style="margin-top: -8px;">
<div class="stats" v-if="info"> <div class="selects" style="display: flex;">
<div class="_panel"> <MkSelect v-model:value="chartSrc" style="margin: 0; flex: 1;">
<div> <optgroup :label="$ts.federation">
<b><Fa :icon="faUser"/>{{ $ts.users }}</b> <option value="federation-instances">{{ $ts._charts.federationInstancesIncDec }}</option>
<small>{{ $ts.local }}</small> <option value="federation-instances-total">{{ $ts._charts.federationInstancesTotal }}</option>
</div> </optgroup>
<div> <optgroup :label="$ts.users">
<dl class="total"> <option value="users">{{ $ts._charts.usersIncDec }}</option>
<dt>{{ $ts.total }}</dt> <option value="users-total">{{ $ts._charts.usersTotal }}</option>
<dd>{{ number(info.originalUsersCount) }}</dd> <option value="active-users">{{ $ts._charts.activeUsers }}</option>
</dl> </optgroup>
<dl class="diff" :class="{ inc: usersLocalDoD > 0 }"> <optgroup :label="$ts.notes">
<dt>{{ $ts.dayOverDayChanges }}</dt> <option value="notes">{{ $ts._charts.notesIncDec }}</option>
<dd>{{ number(usersLocalDoD) }}</dd> <option value="local-notes">{{ $ts._charts.localNotesIncDec }}</option>
</dl> <option value="remote-notes">{{ $ts._charts.remoteNotesIncDec }}</option>
<dl class="diff" :class="{ inc: usersLocalWoW > 0 }"> <option value="notes-total">{{ $ts._charts.notesTotal }}</option>
<dt>{{ $ts.weekOverWeekChanges }}</dt> </optgroup>
<dd>{{ number(usersLocalWoW) }}</dd> <optgroup :label="$ts.drive">
</dl> <option value="drive-files">{{ $ts._charts.filesIncDec }}</option>
</div> <option value="drive-files-total">{{ $ts._charts.filesTotal }}</option>
</div> <option value="drive">{{ $ts._charts.storageUsageIncDec }}</option>
<div class="_panel"> <option value="drive-total">{{ $ts._charts.storageUsageTotal }}</option>
<div> </optgroup>
<b><Fa :icon="faUser"/>{{ $ts.users }}</b> </MkSelect>
<small>{{ $ts.remote }}</small> <MkSelect v-model:value="chartSpan" style="margin: 0;">
</div> <option value="hour">{{ $ts.perHour }}</option>
<div> <option value="day">{{ $ts.perDay }}</option>
<dl class="total"> </MkSelect>
<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> </div>
<canvas ref="chart"></canvas>
<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>
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, markRaw } from 'vue'; import { defineComponent, markRaw } from 'vue';
import { faChartBar, faUser, faPencilAlt, faSync } from '@fortawesome/free-solid-svg-icons';
import Chart from 'chart.js'; import Chart from 'chart.js';
import MkSelect from './ui/select.vue'; import MkSelect from './ui/select.vue';
import number from '@client/filters/number'; import number from '@client/filters/number';
@ -159,7 +70,6 @@ export default defineComponent({
data() { data() {
return { return {
info: null,
notesLocalWoW: 0, notesLocalWoW: 0,
notesLocalDoD: 0, notesLocalDoD: 0,
notesRemoteWoW: 0, notesRemoteWoW: 0,
@ -173,7 +83,6 @@ export default defineComponent({
chartInstance: null, chartInstance: null,
chartSrc: 'notes', chartSrc: 'notes',
chartSpan: 'hour', chartSpan: 'hour',
faChartBar, faUser, faPencilAlt, faSync
} }
}, },
@ -218,8 +127,6 @@ export default defineComponent({
}, },
async created() { async created() {
this.info = await os.api('stats');
this.now = new Date(); this.now = new Date();
this.fetchChart(); 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.chart = chart;
this.renderChart(); this.renderChart();
@ -302,10 +200,10 @@ export default defineComponent({
aspectRatio: 2.5, aspectRatio: 2.5,
layout: { layout: {
padding: { padding: {
left: 0, left: 16,
right: 0, right: 16,
top: 16, top: 16,
bottom: 0 bottom: 8
} }
}, },
legend: { legend: {
@ -632,90 +530,8 @@ export default defineComponent({
<style lang="scss" scoped> <style lang="scss" scoped>
.zbcjwnqg { .zbcjwnqg {
&.max-width_1000px { > .selects {
> .stats { padding: 8px 16px 0 16px;
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: "+";
}
}
}
}
}
}
}
} }
} }
</style> </style>

View file

@ -4,28 +4,28 @@
<div class="main"> <div class="main">
<template v-for="item in items"> <template v-for="item in items">
<button v-if="item.action" class="_button" @click="$event => { item.action($event); close(); }"> <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> <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> </button>
<MkA v-else :to="item.to" @click.passive="close()"> <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> <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> </MkA>
</template> </template>
</div> </div>
<div class="sub"> <div class="sub">
<MkA to="/docs" @click.passive="close()"> <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> <div class="text">{{ $ts.help }}</div>
</MkA> </MkA>
<MkA to="/about" @click.passive="close()"> <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> <div class="text">{{ $t('aboutX', { x: instanceName }) }}</div>
</MkA> </MkA>
<MkA to="/about-misskey" @click.passive="close()"> <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> <div class="text">{{ $ts.aboutMisskey }}</div>
</MkA> </MkA>
</div> </div>
@ -35,7 +35,6 @@
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { faQuestionCircle, faInfoCircle, faCircle } from '@fortawesome/free-solid-svg-icons';
import MkModal from '@client/components/ui/modal.vue'; import MkModal from '@client/components/ui/modal.vue';
import { sidebarDef } from '@client/sidebar'; import { sidebarDef } from '@client/sidebar';
import { instanceName } from '@client/config'; import { instanceName } from '@client/config';
@ -52,7 +51,6 @@ export default defineComponent({
menuDef: sidebarDef, menuDef: sidebarDef,
items: [], items: [],
instanceName, instanceName,
faQuestionCircle, faInfoCircle, faCircle,
}; };
}, },
@ -127,7 +125,7 @@ export default defineComponent({
line-height: 1.5em; line-height: 1.5em;
} }
> i { > .indicator {
position: absolute; position: absolute;
top: 32px; top: 32px;
left: 32px; left: 32px;

View file

@ -5,13 +5,12 @@
:title="url" :title="url"
> >
<slot></slot> <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> </component>
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { faExternalLinkSquareAlt } from '@fortawesome/free-solid-svg-icons';
import { url as local } from '@client/config'; import { url as local } from '@client/config';
import { isDeviceTouch } from '@client/scripts/is-device-touch'; import { isDeviceTouch } from '@client/scripts/is-device-touch';
import * as os from '@client/os'; import * as os from '@client/os';
@ -38,7 +37,6 @@ export default defineComponent({
hideTimer: null, hideTimer: null,
checkTimer: null, checkTimer: null,
close: null, close: null,
faExternalLinkSquareAlt
}; };
}, },
methods: { methods: {

View file

@ -1,7 +1,7 @@
<template> <template>
<div class="mk-media-banner"> <div class="mk-media-banner">
<div class="sensitive" v-if="media.isSensitive && hide" @click="hide = false"> <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> <b>{{ $ts.sensitive }}</b>
<span>{{ $ts.clickToShow }}</span> <span>{{ $ts.clickToShow }}</span>
</div> </div>
@ -19,7 +19,7 @@
:title="media.name" :title="media.name"
:download="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> <b>{{ media.name }}</b>
</a> </a>
</div> </div>
@ -27,7 +27,6 @@
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons';
import * as os from '@client/os'; import * as os from '@client/os';
import { ColdDeviceStorage } from '@client/store'; import { ColdDeviceStorage } from '@client/store';
@ -41,7 +40,6 @@ export default defineComponent({
data() { data() {
return { return {
hide: true, hide: true,
faExclamationTriangle
}; };
}, },
mounted() { mounted() {

View file

@ -3,13 +3,13 @@
<ImgWithBlurhash class="bg" :hash="image.blurhash" :title="image.name"/> <ImgWithBlurhash class="bg" :hash="image.blurhash" :title="image.name"/>
<div class="text"> <div class="text">
<div> <div>
<b><Fa :icon="faExclamationTriangle"/> {{ $ts.sensitive }}</b> <b><i class="fas fa-exclamation-triangle"></i> {{ $ts.sensitive }}</b>
<span>{{ $ts.clickToShow }}</span> <span>{{ $ts.clickToShow }}</span>
</div> </div>
</div> </div>
</div> </div>
<div class="gqnyydlz" :style="{ background: color }" v-else> <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 <a
:href="image.url" :href="image.url"
:title="image.name" :title="image.name"
@ -23,7 +23,6 @@
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { faExclamationTriangle, faEyeSlash } from '@fortawesome/free-solid-svg-icons';
import { getStaticImageUrl } from '@client/scripts/get-static-image-url'; import { getStaticImageUrl } from '@client/scripts/get-static-image-url';
import { extractAvgColorFromBlurhash } from '@client/scripts/extract-avg-color-from-blurhash'; import { extractAvgColorFromBlurhash } from '@client/scripts/extract-avg-color-from-blurhash';
import ImageViewer from './image-viewer.vue'; import ImageViewer from './image-viewer.vue';
@ -47,7 +46,6 @@ export default defineComponent({
return { return {
hide: true, hide: true,
color: null, color: null,
faExclamationTriangle, faEyeSlash,
}; };
}, },
computed: { computed: {

View file

@ -1,7 +1,7 @@
<template> <template>
<div class="icozogqfvdetwohsdglrbswgrejoxbdj" v-if="hide" @click="hide = false"> <div class="icozogqfvdetwohsdglrbswgrejoxbdj" v-if="hide" @click="hide = false">
<div> <div>
<b><Fa :icon="faExclamationTriangle"/> {{ $ts.sensitive }}</b> <b><i class="fas fa-exclamation-triangle"></i> {{ $ts.sensitive }}</b>
<span>{{ $ts.clickToShow }}</span> <span>{{ $ts.clickToShow }}</span>
</div> </div>
</div> </div>
@ -18,13 +18,12 @@
:type="video.type" :type="video.type"
> >
</video> </video>
<i><Fa :icon="faEyeSlash" @click="hide = true"/></i> <i class="fas fa-eye-slash" @click="hide = true"></i>
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { faExclamationTriangle, faEyeSlash } from '@fortawesome/free-solid-svg-icons';
import * as os from '@client/os'; import * as os from '@client/os';
export default defineComponent({ export default defineComponent({
@ -37,8 +36,6 @@ export default defineComponent({
data() { data() {
return { return {
hide: true, hide: true,
faExclamationTriangle,
faEyeSlash
}; };
}, },
created() { created() {

View file

@ -1,13 +1,13 @@
<template> <template>
<MkModal ref="modal" @click="$emit('click')" @closed="$emit('closed')"> <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="hrmcaedk _popup _narrow_" :style="{ width: `${width}px`, height: (height ? `min(${height}px, 100%)` : '100%') }">
<div class="header"> <div class="header" @contextmenu="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> <button class="_button" style="pointer-events: none;" v-else><!-- マージンのバランスを取るためのダミー --></button>
<span class="title"> <span class="title">
<XHeader :info="pageInfo" :with-back="false"/> <XHeader :info="pageInfo" :with-back="false"/>
</span> </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>
<div class="body _flat_"> <div class="body _flat_">
<keep-alive> <keep-alive>
@ -20,7 +20,6 @@
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; 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 MkModal from '@client/components/ui/modal.vue';
import XHeader from '@client/ui/_common_/header.vue'; import XHeader from '@client/ui/_common_/header.vue';
import { popout } from '@client/scripts/popout'; import { popout } from '@client/scripts/popout';
@ -28,6 +27,7 @@ import copyToClipboard from '@client/scripts/copy-to-clipboard';
import { resolve } from '@client/router'; import { resolve } from '@client/router';
import { url } from '@client/config'; import { url } from '@client/config';
import * as symbols from '@client/symbols'; import * as symbols from '@client/symbols';
import * as os from '@client/os';
export default defineComponent({ export default defineComponent({
components: { components: {
@ -76,7 +76,6 @@ export default defineComponent({
component: this.initialComponent, component: this.initialComponent,
props: this.initialProps, props: this.initialProps,
history: [], history: [],
faChevronLeft, faTimes,
}; };
}, },
@ -90,29 +89,29 @@ export default defineComponent({
type: 'label', type: 'label',
text: this.path, text: this.path,
}, { }, {
icon: faExpandAlt, icon: 'fas fa-expand-alt',
text: this.$ts.showInPage, text: this.$ts.showInPage,
action: this.expand action: this.expand
}, this.sideViewHook ? { }, this.sideViewHook ? {
icon: faColumns, icon: 'fas fa-columns',
text: this.$ts.openInSideView, text: this.$ts.openInSideView,
action: () => { action: () => {
this.sideViewHook(this.path); this.sideViewHook(this.path);
this.$refs.window.close(); this.$refs.window.close();
} }
} : undefined, { } : undefined, {
icon: faExternalLinkAlt, icon: 'fas fa-external-link-alt',
text: this.$ts.popout, text: this.$ts.popout,
action: this.popout action: this.popout
}, null, { }, null, {
icon: faExternalLinkAlt, icon: 'fas fa-external-link-alt',
text: this.$ts.openInNewTab, text: this.$ts.openInNewTab,
action: () => { action: () => {
window.open(this.url, '_blank'); window.open(this.url, '_blank');
this.$refs.window.close(); this.$refs.window.close();
} }
}, { }, {
icon: faLink, icon: 'fas fa-link',
text: this.$ts.copyLink, text: this.$ts.copyLink,
action: () => { action: () => {
copyToClipboard(this.url); copyToClipboard(this.url);
@ -150,6 +149,10 @@ export default defineComponent({
popout(this.path, this.$el); popout(this.path, this.$el);
this.$refs.window.close(); this.$refs.window.close();
}, },
onContextmenu(e) {
os.contextMenu(this.contextmenu, e);
}
}, },
}); });
</script> </script>

View file

@ -12,7 +12,7 @@
<XSub :note="appearNote.reply" class="reply-to" v-if="appearNote.reply"/> <XSub :note="appearNote.reply" class="reply-to" v-if="appearNote.reply"/>
<div class="renote" v-if="isRenote"> <div class="renote" v-if="isRenote">
<MkAvatar class="avatar" :user="note.user"/> <MkAvatar class="avatar" :user="note.user"/>
<Fa :icon="faRetweet"/> <i class="fas fa-retweet"></i>
<I18n :src="$ts.renotedBy" tag="span"> <I18n :src="$ts.renotedBy" tag="span">
<template #user> <template #user>
<MkA class="name" :to="userPage(note.user)" v-user-preview="note.userId"> <MkA class="name" :to="userPage(note.user)" v-user-preview="note.userId">
@ -22,15 +22,15 @@
</I18n> </I18n>
<div class="info"> <div class="info">
<button class="_button time" @click="showRenoteMenu()" ref="renoteTime"> <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"/> <MkTime :time="note.createdAt"/>
</button> </button>
<span class="visibility" v-if="note.visibility !== 'public'"> <span class="visibility" v-if="note.visibility !== 'public'">
<Fa v-if="note.visibility === 'home'" :icon="faHome"/> <i v-if="note.visibility === 'home'" class="fas fa-home"></i>
<Fa v-if="note.visibility === 'followers'" :icon="faUnlock"/> <i v-else-if="note.visibility === 'followers'" class="fas fa-unlock"></i>
<Fa v-if="note.visibility === 'specified'" :icon="faEnvelope"/> <i v-else-if="note.visibility === 'specified'" class="fas fa-envelope"></i>
</span> </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>
</div> </div>
<article class="article" @contextmenu.stop="onContextmenu"> <article class="article" @contextmenu.stop="onContextmenu">
@ -42,14 +42,14 @@
<MkUserName :user="appearNote.user"/> <MkUserName :user="appearNote.user"/>
</MkA> </MkA>
<span class="is-bot" v-if="appearNote.user.isBot">bot</span> <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="admin" v-if="appearNote.user.isAdmin"><i class="fas fa-bookmark"></i></span>
<span class="moderator" v-if="!appearNote.user.isAdmin && appearNote.user.isModerator"><Fa :icon="farBookmark"/></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'"> <span class="visibility" v-if="appearNote.visibility !== 'public'">
<Fa v-if="appearNote.visibility === 'home'" :icon="faHome"/> <i v-if="appearNote.visibility === 'home'" class="fas fa-home"></i>
<Fa v-if="appearNote.visibility === 'followers'" :icon="faUnlock"/> <i v-else-if="appearNote.visibility === 'followers'" class="fas fa-unlock"></i>
<Fa v-if="appearNote.visibility === 'specified'" :icon="faEnvelope"/> <i v-else-if="appearNote.visibility === 'specified'" class="fas fa-envelope"></i>
</span> </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>
<div class="username"><MkAcct :user="appearNote.user"/></div> <div class="username"><MkAcct :user="appearNote.user"/></div>
<MkInstanceTicker v-if="showTicker" class="ticker" :instance="appearNote.user.instance"/> <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="content" v-show="appearNote.cw == null || showContent">
<div class="text"> <div class="text">
<span v-if="appearNote.isHidden" style="opacity: 0.5">({{ $ts.private }})</span> <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"/> <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> <a class="rp" v-if="appearNote.renote != null">RN:</a>
</div> </div>
@ -75,33 +75,33 @@
<MkUrlPreview v-for="url in urls" :url="url" :key="url" :compact="true" :detail="true" class="url-preview"/> <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 class="renote" v-if="appearNote.renote"><XNotePreview :note="appearNote.renote"/></div>
</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> </div>
<footer class="footer"> <footer class="footer">
<div class="info"> <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"/> <MkTime class="created-at" :time="note.createdAt" mode="detail"/>
</div> </div>
<XReactionsViewer :note="appearNote" ref="reactionsViewer"/> <XReactionsViewer :note="appearNote" ref="reactionsViewer"/>
<button @click="reply()" class="button _button"> <button @click="reply()" class="button _button">
<template v-if="appearNote.reply"><Fa :icon="faReplyAll"/></template> <template v-if="appearNote.reply"><i class="fas fa-reply-all"></i></template>
<template v-else><Fa :icon="faReply"/></template> <template v-else><i class="fas fa-reply"></i></template>
<p class="count" v-if="appearNote.repliesCount > 0">{{ appearNote.repliesCount }}</p> <p class="count" v-if="appearNote.repliesCount > 0">{{ appearNote.repliesCount }}</p>
</button> </button>
<button v-if="canRenote" @click="renote()" class="button _button" ref="renoteButton"> <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>
<button v-else class="button _button"> <button v-else class="button _button">
<Fa :icon="faBan"/> <i class="fas fa-ban"></i>
</button> </button>
<button v-if="appearNote.myReaction == null" class="button _button" @click="react()" ref="reactButton"> <button v-if="appearNote.myReaction == null" class="button _button" @click="react()" ref="reactButton">
<Fa :icon="faPlus"/> <i class="fas fa-plus"></i>
</button> </button>
<button v-if="appearNote.myReaction != null" class="button _button reacted" @click="undoReact(appearNote)" ref="reactButton"> <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>
<button class="button _button" @click="menu()" ref="menuButton"> <button class="button _button" @click="menu()" ref="menuButton">
<Fa :icon="faEllipsisH"/> <i class="fas fa-ellipsis-h"></i>
</button> </button>
</footer> </footer>
</div> </div>
@ -121,8 +121,6 @@
<script lang="ts"> <script lang="ts">
import { defineAsyncComponent, defineComponent, markRaw } from 'vue'; 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 * as mfm from 'mfm-js';
import { sum } from '../../prelude/array'; import { sum } from '../../prelude/array';
import XSub from './note.sub.vue'; import XSub from './note.sub.vue';
@ -143,14 +141,6 @@ import { noteActions, noteViewInterruptors } from '@client/store';
import { reactionPicker } from '@client/scripts/reaction-picker'; import { reactionPicker } from '@client/scripts/reaction-picker';
import { extractUrlFromMfm } from '@/misc/extract-url-from-mfm'; 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 // TODO: note.vue
export default defineComponent({ export default defineComponent({
components: { components: {
@ -188,7 +178,6 @@ export default defineComponent({
showContent: false, showContent: false,
isDeleted: false, isDeleted: false,
muted: 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(); this.blur();
os.modalMenu([{ os.modalMenu([{
text: this.$ts.renote, text: this.$ts.renote,
icon: faRetweet, icon: 'fas fa-retweet',
action: () => { action: () => {
os.api('notes/create', { os.api('notes/create', {
renoteId: this.appearNote.id renoteId: this.appearNote.id
@ -475,7 +464,7 @@ export default defineComponent({
} }
}, { }, {
text: this.$ts.quote, text: this.$ts.quote,
icon: faQuoteRight, icon: 'fas fa-quote-right',
action: () => { action: () => {
os.post({ os.post({
renote: this.appearNote, renote: this.appearNote,
@ -611,62 +600,62 @@ export default defineComponent({
}); });
menu = [{ menu = [{
icon: faCopy, icon: 'fas fa-copy',
text: this.$ts.copyContent, text: this.$ts.copyContent,
action: this.copyContent action: this.copyContent
}, { }, {
icon: faLink, icon: 'fas fa-link',
text: this.$ts.copyLink, text: this.$ts.copyLink,
action: this.copyLink action: this.copyLink
}, (this.appearNote.url || this.appearNote.uri) ? { }, (this.appearNote.url || this.appearNote.uri) ? {
icon: faExternalLinkSquareAlt, icon: 'fas fa-external-link-square-alt',
text: this.$ts.showOnRemote, text: this.$ts.showOnRemote,
action: () => { action: () => {
window.open(this.appearNote.url || this.appearNote.uri, '_blank'); window.open(this.appearNote.url || this.appearNote.uri, '_blank');
} }
} : undefined, } : undefined,
{ {
icon: faShareAlt, icon: 'fas fa-share-alt',
text: this.$ts.share, text: this.$ts.share,
action: this.share action: this.share
}, },
null, null,
statePromise.then(state => state.isFavorited ? { statePromise.then(state => state.isFavorited ? {
icon: faStar, icon: 'fas fa-star',
text: this.$ts.unfavorite, text: this.$ts.unfavorite,
action: () => this.toggleFavorite(false) action: () => this.toggleFavorite(false)
} : { } : {
icon: faStar, icon: 'fas fa-star',
text: this.$ts.favorite, text: this.$ts.favorite,
action: () => this.toggleFavorite(true) action: () => this.toggleFavorite(true)
}), }),
{ {
icon: faPaperclip, icon: 'fas fa-paperclip',
text: this.$ts.clip, text: this.$ts.clip,
action: () => this.clip() action: () => this.clip()
}, },
(this.appearNote.userId != this.$i.id) ? statePromise.then(state => state.isWatching ? { (this.appearNote.userId != this.$i.id) ? statePromise.then(state => state.isWatching ? {
icon: faEyeSlash, icon: 'fas fa-eye-slash',
text: this.$ts.unwatch, text: this.$ts.unwatch,
action: () => this.toggleWatch(false) action: () => this.toggleWatch(false)
} : { } : {
icon: faEye, icon: 'fas fa-eye',
text: this.$ts.watch, text: this.$ts.watch,
action: () => this.toggleWatch(true) action: () => this.toggleWatch(true)
}) : undefined, }) : undefined,
this.appearNote.userId == this.$i.id ? (this.$i.pinnedNoteIds || []).includes(this.appearNote.id) ? { this.appearNote.userId == this.$i.id ? (this.$i.pinnedNoteIds || []).includes(this.appearNote.id) ? {
icon: faThumbtack, icon: 'fas fa-thumbtack',
text: this.$ts.unpin, text: this.$ts.unpin,
action: () => this.togglePin(false) action: () => this.togglePin(false)
} : { } : {
icon: faThumbtack, icon: 'fas fa-thumbtack',
text: this.$ts.pin, text: this.$ts.pin,
action: () => this.togglePin(true) action: () => this.togglePin(true)
} : undefined, } : undefined,
...(this.$i.isModerator || this.$i.isAdmin ? [ ...(this.$i.isModerator || this.$i.isAdmin ? [
null, null,
{ {
icon: faBullhorn, icon: 'fas fa-bullhorn',
text: this.$ts.promote, text: this.$ts.promote,
action: this.promote action: this.promote
}] }]
@ -675,7 +664,7 @@ export default defineComponent({
...(this.appearNote.userId != this.$i.id ? [ ...(this.appearNote.userId != this.$i.id ? [
null, null,
{ {
icon: faExclamationCircle, icon: 'fas fa-exclamation-circle',
text: this.$ts.reportAbuse, text: this.$ts.reportAbuse,
action: () => { action: () => {
const u = `${url}/notes/${this.appearNote.id}`; 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 ? [ ...(this.appearNote.userId == this.$i.id || this.$i.isModerator || this.$i.isAdmin ? [
null, null,
this.appearNote.userId == this.$i.id ? { this.appearNote.userId == this.$i.id ? {
icon: faEdit, icon: 'fas fa-edit',
text: this.$ts.deleteAndEdit, text: this.$ts.deleteAndEdit,
action: this.delEdit action: this.delEdit
} : undefined, } : undefined,
{ {
icon: faTrashAlt, icon: 'fas fa-trash-alt',
text: this.$ts.delete, text: this.$ts.delete,
danger: true, danger: true,
action: this.del action: this.del
@ -705,15 +694,15 @@ export default defineComponent({
.filter(x => x !== undefined); .filter(x => x !== undefined);
} else { } else {
menu = [{ menu = [{
icon: faCopy, icon: 'fas fa-copy',
text: this.$ts.copyContent, text: this.$ts.copyContent,
action: this.copyContent action: this.copyContent
}, { }, {
icon: faLink, icon: 'fas fa-link',
text: this.$ts.copyLink, text: this.$ts.copyLink,
action: this.copyLink action: this.copyLink
}, (this.appearNote.url || this.appearNote.uri) ? { }, (this.appearNote.url || this.appearNote.uri) ? {
icon: faExternalLinkSquareAlt, icon: 'fas fa-external-link-square-alt',
text: this.$ts.showOnRemote, text: this.$ts.showOnRemote,
action: () => { action: () => {
window.open(this.appearNote.url || this.appearNote.uri, '_blank'); window.open(this.appearNote.url || this.appearNote.uri, '_blank');
@ -724,7 +713,7 @@ export default defineComponent({
if (noteActions.length > 0) { if (noteActions.length > 0) {
menu = menu.concat([null, ...noteActions.map(action => ({ menu = menu.concat([null, ...noteActions.map(action => ({
icon: faPlug, icon: 'fas fa-plug',
text: action.title, text: action.title,
action: () => { action: () => {
action.handler(this.appearNote); action.handler(this.appearNote);
@ -763,7 +752,7 @@ export default defineComponent({
if (!this.isMyRenote) return; if (!this.isMyRenote) return;
os.modalMenu([{ os.modalMenu([{
text: this.$ts.unrenote, text: this.$ts.unrenote,
icon: faTrashAlt, icon: 'fas fa-trash-alt',
danger: true, danger: true,
action: () => { action: () => {
os.api('notes/delete', { os.api('notes/delete', {
@ -806,7 +795,7 @@ export default defineComponent({
async clip() { async clip() {
const clips = await os.api('clips/list'); const clips = await os.api('clips/list');
os.modalMenu([{ os.modalMenu([{
icon: faPlus, icon: 'fas fa-plus',
text: this.$ts.createNew, text: this.$ts.createNew,
action: async () => { action: async () => {
const { canceled, result } = await os.form(this.$ts.createNewClip, { const { canceled, result } = await os.form(this.$ts.createNewClip, {
@ -943,7 +932,7 @@ export default defineComponent({
border-radius: 6px; border-radius: 6px;
} }
> [data-icon] { > i {
margin-right: 4px; margin-right: 4px;
} }

View file

@ -5,27 +5,25 @@
</MkA> </MkA>
<span class="is-bot" v-if="note.user.isBot">bot</span> <span class="is-bot" v-if="note.user.isBot">bot</span>
<span class="username"><MkAcct :user="note.user"/></span> <span class="username"><MkAcct :user="note.user"/></span>
<span class="admin" v-if="note.user.isAdmin"><Fa :icon="faBookmark"/></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"><Fa :icon="farBookmark"/></span> <span class="moderator" v-if="!note.user.isAdmin && note.user.isModerator"><i class="far fa-bookmark"></i></span>
<div class="info"> <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)"> <MkA class="created-at" :to="notePage(note)">
<MkTime :time="note.createdAt"/> <MkTime :time="note.createdAt"/>
</MkA> </MkA>
<span class="visibility" v-if="note.visibility !== 'public'"> <span class="visibility" v-if="note.visibility !== 'public'">
<Fa v-if="note.visibility === 'home'" :icon="faHome"/> <i v-if="note.visibility === 'home'" class="fas fa-home"></i>
<Fa v-if="note.visibility === 'followers'" :icon="faUnlock"/> <i v-else-if="note.visibility === 'followers'" class="fas fa-unlock"></i>
<Fa v-if="note.visibility === 'specified'" :icon="faEnvelope"/> <i v-else-if="note.visibility === 'specified'" class="fas fa-envelope"></i>
</span> </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>
</header> </header>
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; 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 notePage from '../filters/note';
import { userPage } from '../filters/user'; import { userPage } from '../filters/user';
import * as os from '@client/os'; import * as os from '@client/os';
@ -40,7 +38,6 @@ export default defineComponent({
data() { data() {
return { return {
faHome, faUnlock, faEnvelope, faMobileAlt, faBookmark, farBookmark, faBiohazard
}; };
}, },

View file

@ -9,12 +9,12 @@
v-size="{ max: [500, 450, 350, 300] }" v-size="{ max: [500, 450, 350, 300] }"
> >
<XSub :note="appearNote.reply" class="reply-to" v-if="appearNote.reply"/> <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="pinned"><i class="fas fa-thumbtack"></i> {{ $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._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_"><Fa :icon="faBolt"/> {{ $ts.featured }}</div> <div class="info" v-if="appearNote._featuredId_"><i class="fas fa-bolt"></i> {{ $ts.featured }}</div>
<div class="renote" v-if="isRenote"> <div class="renote" v-if="isRenote">
<MkAvatar class="avatar" :user="note.user"/> <MkAvatar class="avatar" :user="note.user"/>
<Fa :icon="faRetweet"/> <i class="fas fa-retweet"></i>
<I18n :src="$ts.renotedBy" tag="span"> <I18n :src="$ts.renotedBy" tag="span">
<template #user> <template #user>
<MkA class="name" :to="userPage(note.user)" v-user-preview="note.userId"> <MkA class="name" :to="userPage(note.user)" v-user-preview="note.userId">
@ -24,15 +24,15 @@
</I18n> </I18n>
<div class="info"> <div class="info">
<button class="_button time" @click="showRenoteMenu()" ref="renoteTime"> <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"/> <MkTime :time="note.createdAt"/>
</button> </button>
<span class="visibility" v-if="note.visibility !== 'public'"> <span class="visibility" v-if="note.visibility !== 'public'">
<Fa v-if="note.visibility === 'home'" :icon="faHome"/> <i v-if="note.visibility === 'home'" class="fas fa-home"></i>
<Fa v-if="note.visibility === 'followers'" :icon="faUnlock"/> <i v-else-if="note.visibility === 'followers'" class="fas fa-unlock"></i>
<Fa v-if="note.visibility === 'specified'" :icon="faEnvelope"/> <i v-else-if="note.visibility === 'specified'" class="fas fa-envelope"></i>
</span> </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>
</div> </div>
<article class="article" @contextmenu.stop="onContextmenu"> <article class="article" @contextmenu.stop="onContextmenu">
@ -48,7 +48,7 @@
<div class="content" :class="{ collapsed }" v-show="appearNote.cw == null || showContent"> <div class="content" :class="{ collapsed }" v-show="appearNote.cw == null || showContent">
<div class="text"> <div class="text">
<span v-if="appearNote.isHidden" style="opacity: 0.5">({{ $ts.private }})</span> <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"/> <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> <a class="rp" v-if="appearNote.renote != null">RN:</a>
</div> </div>
@ -62,29 +62,29 @@
<span>{{ $ts.showMore }}</span> <span>{{ $ts.showMore }}</span>
</button> </button>
</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> </div>
<footer class="footer"> <footer class="footer">
<XReactionsViewer :note="appearNote" ref="reactionsViewer"/> <XReactionsViewer :note="appearNote" ref="reactionsViewer"/>
<button @click="reply()" class="button _button"> <button @click="reply()" class="button _button">
<template v-if="appearNote.reply"><Fa :icon="faReplyAll"/></template> <template v-if="appearNote.reply"><i class="fas fa-reply-all"></i></template>
<template v-else><Fa :icon="faReply"/></template> <template v-else><i class="fas fa-reply"></i></template>
<p class="count" v-if="appearNote.repliesCount > 0">{{ appearNote.repliesCount }}</p> <p class="count" v-if="appearNote.repliesCount > 0">{{ appearNote.repliesCount }}</p>
</button> </button>
<button v-if="canRenote" @click="renote()" class="button _button" ref="renoteButton"> <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>
<button v-else class="button _button"> <button v-else class="button _button">
<Fa :icon="faBan"/> <i class="fas fa-ban"></i>
</button> </button>
<button v-if="appearNote.myReaction == null" class="button _button" @click="react()" ref="reactButton"> <button v-if="appearNote.myReaction == null" class="button _button" @click="react()" ref="reactButton">
<Fa :icon="faPlus"/> <i class="fas fa-plus"></i>
</button> </button>
<button v-if="appearNote.myReaction != null" class="button _button reacted" @click="undoReact(appearNote)" ref="reactButton"> <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>
<button class="button _button" @click="menu()" ref="menuButton"> <button class="button _button" @click="menu()" ref="menuButton">
<Fa :icon="faEllipsisH"/> <i class="fas fa-ellipsis-h"></i>
</button> </button>
</footer> </footer>
</div> </div>
@ -103,8 +103,6 @@
<script lang="ts"> <script lang="ts">
import { defineAsyncComponent, defineComponent, markRaw } from 'vue'; 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 * as mfm from 'mfm-js';
import { sum } from '../../prelude/array'; import { sum } from '../../prelude/array';
import XSub from './note.sub.vue'; import XSub from './note.sub.vue';
@ -125,14 +123,6 @@ import { noteActions, noteViewInterruptors } from '@client/store';
import { reactionPicker } from '@client/scripts/reaction-picker'; import { reactionPicker } from '@client/scripts/reaction-picker';
import { extractUrlFromMfm } from '@/misc/extract-url-from-mfm'; 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({ export default defineComponent({
components: { components: {
XSub, XSub,
@ -174,7 +164,6 @@ export default defineComponent({
collapsed: false, collapsed: false,
isDeleted: false, isDeleted: false,
muted: 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(); this.blur();
os.modalMenu([{ os.modalMenu([{
text: this.$ts.renote, text: this.$ts.renote,
icon: faRetweet, icon: 'fas fa-retweet',
action: () => { action: () => {
os.api('notes/create', { os.api('notes/create', {
renoteId: this.appearNote.id renoteId: this.appearNote.id
@ -450,7 +439,7 @@ export default defineComponent({
} }
}, { }, {
text: this.$ts.quote, text: this.$ts.quote,
icon: faQuoteRight, icon: 'fas fa-quote-right',
action: () => { action: () => {
os.post({ os.post({
renote: this.appearNote, renote: this.appearNote,
@ -586,62 +575,62 @@ export default defineComponent({
}); });
menu = [{ menu = [{
icon: faCopy, icon: 'fas fa-copy',
text: this.$ts.copyContent, text: this.$ts.copyContent,
action: this.copyContent action: this.copyContent
}, { }, {
icon: faLink, icon: 'fas fa-link',
text: this.$ts.copyLink, text: this.$ts.copyLink,
action: this.copyLink action: this.copyLink
}, (this.appearNote.url || this.appearNote.uri) ? { }, (this.appearNote.url || this.appearNote.uri) ? {
icon: faExternalLinkSquareAlt, icon: 'fas fa-external-link-square-alt',
text: this.$ts.showOnRemote, text: this.$ts.showOnRemote,
action: () => { action: () => {
window.open(this.appearNote.url || this.appearNote.uri, '_blank'); window.open(this.appearNote.url || this.appearNote.uri, '_blank');
} }
} : undefined, } : undefined,
{ {
icon: faShareAlt, icon: 'fas fa-share-alt',
text: this.$ts.share, text: this.$ts.share,
action: this.share action: this.share
}, },
null, null,
statePromise.then(state => state.isFavorited ? { statePromise.then(state => state.isFavorited ? {
icon: faStar, icon: 'fas fa-star',
text: this.$ts.unfavorite, text: this.$ts.unfavorite,
action: () => this.toggleFavorite(false) action: () => this.toggleFavorite(false)
} : { } : {
icon: faStar, icon: 'fas fa-star',
text: this.$ts.favorite, text: this.$ts.favorite,
action: () => this.toggleFavorite(true) action: () => this.toggleFavorite(true)
}), }),
{ {
icon: faPaperclip, icon: 'fas fa-paperclip',
text: this.$ts.clip, text: this.$ts.clip,
action: () => this.clip() action: () => this.clip()
}, },
(this.appearNote.userId != this.$i.id) ? statePromise.then(state => state.isWatching ? { (this.appearNote.userId != this.$i.id) ? statePromise.then(state => state.isWatching ? {
icon: faEyeSlash, icon: 'fas fa-eye-slash',
text: this.$ts.unwatch, text: this.$ts.unwatch,
action: () => this.toggleWatch(false) action: () => this.toggleWatch(false)
} : { } : {
icon: faEye, icon: 'fas fa-eye',
text: this.$ts.watch, text: this.$ts.watch,
action: () => this.toggleWatch(true) action: () => this.toggleWatch(true)
}) : undefined, }) : undefined,
this.appearNote.userId == this.$i.id ? (this.$i.pinnedNoteIds || []).includes(this.appearNote.id) ? { this.appearNote.userId == this.$i.id ? (this.$i.pinnedNoteIds || []).includes(this.appearNote.id) ? {
icon: faThumbtack, icon: 'fas fa-thumbtack',
text: this.$ts.unpin, text: this.$ts.unpin,
action: () => this.togglePin(false) action: () => this.togglePin(false)
} : { } : {
icon: faThumbtack, icon: 'fas fa-thumbtack',
text: this.$ts.pin, text: this.$ts.pin,
action: () => this.togglePin(true) action: () => this.togglePin(true)
} : undefined, } : undefined,
...(this.$i.isModerator || this.$i.isAdmin ? [ ...(this.$i.isModerator || this.$i.isAdmin ? [
null, null,
{ {
icon: faBullhorn, icon: 'fas fa-bullhorn',
text: this.$ts.promote, text: this.$ts.promote,
action: this.promote action: this.promote
}] }]
@ -650,7 +639,7 @@ export default defineComponent({
...(this.appearNote.userId != this.$i.id ? [ ...(this.appearNote.userId != this.$i.id ? [
null, null,
{ {
icon: faExclamationCircle, icon: 'fas fa-exclamation-circle',
text: this.$ts.reportAbuse, text: this.$ts.reportAbuse,
action: () => { action: () => {
const u = `${url}/notes/${this.appearNote.id}`; 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 ? [ ...(this.appearNote.userId == this.$i.id || this.$i.isModerator || this.$i.isAdmin ? [
null, null,
this.appearNote.userId == this.$i.id ? { this.appearNote.userId == this.$i.id ? {
icon: faEdit, icon: 'fas fa-edit',
text: this.$ts.deleteAndEdit, text: this.$ts.deleteAndEdit,
action: this.delEdit action: this.delEdit
} : undefined, } : undefined,
{ {
icon: faTrashAlt, icon: 'fas fa-trash-alt',
text: this.$ts.delete, text: this.$ts.delete,
danger: true, danger: true,
action: this.del action: this.del
@ -680,15 +669,15 @@ export default defineComponent({
.filter(x => x !== undefined); .filter(x => x !== undefined);
} else { } else {
menu = [{ menu = [{
icon: faCopy, icon: 'fas fa-copy',
text: this.$ts.copyContent, text: this.$ts.copyContent,
action: this.copyContent action: this.copyContent
}, { }, {
icon: faLink, icon: 'fas fa-link',
text: this.$ts.copyLink, text: this.$ts.copyLink,
action: this.copyLink action: this.copyLink
}, (this.appearNote.url || this.appearNote.uri) ? { }, (this.appearNote.url || this.appearNote.uri) ? {
icon: faExternalLinkSquareAlt, icon: 'fas fa-external-link-square-alt',
text: this.$ts.showOnRemote, text: this.$ts.showOnRemote,
action: () => { action: () => {
window.open(this.appearNote.url || this.appearNote.uri, '_blank'); window.open(this.appearNote.url || this.appearNote.uri, '_blank');
@ -699,7 +688,7 @@ export default defineComponent({
if (noteActions.length > 0) { if (noteActions.length > 0) {
menu = menu.concat([null, ...noteActions.map(action => ({ menu = menu.concat([null, ...noteActions.map(action => ({
icon: faPlug, icon: 'fas fa-plug',
text: action.title, text: action.title,
action: () => { action: () => {
action.handler(this.appearNote); action.handler(this.appearNote);
@ -738,7 +727,7 @@ export default defineComponent({
if (!this.isMyRenote) return; if (!this.isMyRenote) return;
os.modalMenu([{ os.modalMenu([{
text: this.$ts.unrenote, text: this.$ts.unrenote,
icon: faTrashAlt, icon: 'fas fa-trash-alt',
danger: true, danger: true,
action: () => { action: () => {
os.api('notes/delete', { os.api('notes/delete', {
@ -781,7 +770,7 @@ export default defineComponent({
async clip() { async clip() {
const clips = await os.api('clips/list'); const clips = await os.api('clips/list');
os.modalMenu([{ os.modalMenu([{
icon: faPlus, icon: 'fas fa-plus',
text: this.$ts.createNew, text: this.$ts.createNew,
action: async () => { action: async () => {
const { canceled, result } = await os.form(this.$ts.createNewClip, { const { canceled, result } = await os.form(this.$ts.createNewClip, {
@ -909,7 +898,7 @@ export default defineComponent({
white-space: pre; white-space: pre;
color: #d28a3f; color: #d28a3f;
> [data-icon] { > i {
margin-right: 4px; margin-right: 4px;
} }
@ -945,7 +934,7 @@ export default defineComponent({
border-radius: 6px; border-radius: 6px;
} }
> [data-icon] { > i {
margin-right: 4px; margin-right: 4px;
} }

View file

@ -4,15 +4,15 @@
<MkAvatar v-if="notification.user" class="icon" :user="notification.user"/> <MkAvatar v-if="notification.user" class="icon" :user="notification.user"/>
<img v-else-if="notification.icon" class="icon" :src="notification.icon" alt=""/> <img v-else-if="notification.icon" class="icon" :src="notification.icon" alt=""/>
<div class="sub-icon" :class="notification.type"> <div class="sub-icon" :class="notification.type">
<Fa :icon="faPlus" v-if="notification.type === 'follow'"/> <i v-if="notification.type === 'follow'" class="fas fa-plus"></i>
<Fa :icon="faClock" v-else-if="notification.type === 'receiveFollowRequest'"/> <i v-else-if="notification.type === 'receiveFollowRequest'" class="fas fa-clock"></i>
<Fa :icon="faCheck" v-else-if="notification.type === 'followRequestAccepted'"/> <i v-else-if="notification.type === 'followRequestAccepted'" class="fas fa-check"></i>
<Fa :icon="faIdCardAlt" v-else-if="notification.type === 'groupInvited'"/> <i v-else-if="notification.type === 'groupInvited'" class="fas fa-id-card-alt"></i>
<Fa :icon="faRetweet" v-else-if="notification.type === 'renote'"/> <i v-else-if="notification.type === 'renote'" class="fas fa-retweet"></i>
<Fa :icon="faReply" v-else-if="notification.type === 'reply'"/> <i v-else-if="notification.type === 'reply'" class="fas fa-reply"></i>
<Fa :icon="faAt" v-else-if="notification.type === 'mention'"/> <i v-else-if="notification.type === 'mention'" class="fas fa-at"></i>
<Fa :icon="faQuoteLeft" v-else-if="notification.type === 'quote'"/> <i v-else-if="notification.type === 'quote'" class="fas fa-quote-left"></i>
<Fa :icon="faPollH" v-else-if="notification.type === 'pollVote'"/> <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"/> <XReactionIcon v-else-if="notification.type === 'reaction'" :reaction="notification.reaction" :custom-emojis="notification.note.emojis" :no-style="true"/>
</div> </div>
</div> </div>
@ -23,14 +23,14 @@
<MkTime :time="notification.createdAt" v-if="withTime" class="time"/> <MkTime :time="notification.createdAt" v-if="withTime" class="time"/>
</header> </header>
<MkA v-if="notification.type === 'reaction'" class="text" :to="notePage(notification.note)" :title="getNoteSummary(notification.note)"> <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"/> <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>
<MkA v-if="notification.type === 'renote'" class="text" :to="notePage(notification.note)" :title="getNoteSummary(notification.note.renote)"> <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"/> <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>
<MkA v-if="notification.type === 'reply'" class="text" :to="notePage(notification.note)" :title="getNoteSummary(notification.note)"> <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"/> <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"/> <Mfm :text="getNoteSummary(notification.note)" :plain="true" :nowrap="!full" :custom-emojis="notification.note.emojis"/>
</MkA> </MkA>
<MkA v-if="notification.type === 'pollVote'" class="text" :to="notePage(notification.note)" :title="getNoteSummary(notification.note)"> <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"/> <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>
<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 === '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> <span v-if="notification.type === 'followRequestAccepted'" class="text" style="opacity: 0.6;">{{ $ts.followRequestAccepted }}</span>
@ -59,8 +59,6 @@
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; 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 { getNoteSummary } from '@/misc/get-note-summary';
import XReactionIcon from './reaction-icon.vue'; import XReactionIcon from './reaction-icon.vue';
import MkFollowButton from './follow-button.vue'; import MkFollowButton from './follow-button.vue';
@ -96,7 +94,6 @@ export default defineComponent({
groupInviteDone: false, groupInviteDone: false,
connection: null, connection: null,
readObserver: null, readObserver: null,
faIdCardAlt, faPlus, faQuoteLeft, faQuoteRight, faRetweet, faReply, faAt, faClock, faCheck, faPollH
}; };
}, },
@ -271,17 +268,17 @@ export default defineComponent({
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
> [data-icon] { > i {
vertical-align: super; vertical-align: super;
font-size: 50%; font-size: 50%;
opacity: 0.5; opacity: 0.5;
} }
> [data-icon]:first-child { > i:first-child {
margin-right: 4px; margin-right: 4px;
} }
> [data-icon]:last-child { > i:last-child {
margin-left: 4px; margin-left: 4px;
} }
} }

View file

@ -11,7 +11,7 @@
<XHeader :info="pageInfo" :with-back="false"/> <XHeader :info="pageInfo" :with-back="false"/>
</template> </template>
<template #buttons> <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> <button class="_button" style="pointer-events: none;" v-else><!-- マージンのバランスを取るためのダミー --></button>
</template> </template>
<div class="yrolvcoq _flat_"> <div class="yrolvcoq _flat_">
@ -22,7 +22,6 @@
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; 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 XWindow from '@client/components/ui/window.vue';
import XHeader from '@client/ui/_common_/header.vue'; import XHeader from '@client/ui/_common_/header.vue';
import { popout } from '@client/scripts/popout'; import { popout } from '@client/scripts/popout';
@ -76,7 +75,6 @@ export default defineComponent({
component: this.initialComponent, component: this.initialComponent,
props: this.initialProps, props: this.initialProps,
history: [], history: [],
faChevronLeft,
}; };
}, },
@ -90,29 +88,29 @@ export default defineComponent({
type: 'label', type: 'label',
text: this.path, text: this.path,
}, { }, {
icon: faExpandAlt, icon: 'fas fa-expand-alt',
text: this.$ts.showInPage, text: this.$ts.showInPage,
action: this.expand action: this.expand
}, this.sideViewHook ? { }, this.sideViewHook ? {
icon: faColumns, icon: 'fas fa-columns',
text: this.$ts.openInSideView, text: this.$ts.openInSideView,
action: () => { action: () => {
this.sideViewHook(this.path); this.sideViewHook(this.path);
this.$refs.window.close(); this.$refs.window.close();
} }
} : undefined, { } : undefined, {
icon: faExternalLinkAlt, icon: 'fas fa-external-link-alt',
text: this.$ts.popout, text: this.$ts.popout,
action: this.popout action: this.popout
}, null, { }, null, {
icon: faExternalLinkAlt, icon: 'fas fa-external-link-alt',
text: this.$ts.openInNewTab, text: this.$ts.openInNewTab,
action: () => { action: () => {
window.open(this.url, '_blank'); window.open(this.url, '_blank');
this.$refs.window.close(); this.$refs.window.close();
} }
}, { }, {
icon: faLink, icon: 'fas fa-link',
text: this.$ts.copyLink, text: this.$ts.copyLink,
action: () => { action: () => {
copyToClipboard(this.url); copyToClipboard(this.url);

View file

@ -1,13 +1,15 @@
<template> <template>
<div class="ngbfujlo"> <div class="ngbfujlo">
<MkTextarea :value="text" readonly style="margin: 0;"></MkTextarea> <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> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, PropType } from 'vue'; import { defineComponent, PropType } from 'vue';
import { faCheck, faPaperPlane } from '@fortawesome/free-solid-svg-icons';
import MkTextarea from '../ui/textarea.vue'; import MkTextarea from '../ui/textarea.vue';
import MkButton from '../ui/button.vue'; import MkButton from '../ui/button.vue';
import { apiUrl } from '@client/config'; import { apiUrl } from '@client/config';
@ -35,7 +37,6 @@ export default defineComponent({
text: this.hpml.interpolate(this.block.text), text: this.hpml.interpolate(this.block.text),
posted: false, posted: false,
posting: false, posting: false,
faCheck, faPaperPlane
}; };
}, },
watch: { watch: {

View file

@ -1,7 +1,7 @@
<template> <template>
<div class="zmdxowus"> <div class="zmdxowus">
<p class="caution" v-if="choices.length < 2"> <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> </p>
<ul ref="choices"> <ul ref="choices">
<li v-for="(choice, i) in choices" :key="i"> <li v-for="(choice, i) in choices" :key="i">
@ -9,7 +9,7 @@
<span>{{ $t('_poll.choiceN', { n: i + 1 }) }}</span> <span>{{ $t('_poll.choiceN', { n: i + 1 }) }}</span>
</MkInput> </MkInput>
<button @click="remove(i)" class="_button"> <button @click="remove(i)" class="_button">
<Fa :icon="faTimes"/> <i class="fas fa-times"></i>
</button> </button>
</li> </li>
</ul> </ul>
@ -50,7 +50,6 @@
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { faExclamationTriangle, faTimes } from '@fortawesome/free-solid-svg-icons';
import { addTime } from '../../prelude/time'; import { addTime } from '../../prelude/time';
import { formatDateTimeString } from '@/misc/format-time-string'; import { formatDateTimeString } from '@/misc/format-time-string';
import MkInput from './ui/input.vue'; import MkInput from './ui/input.vue';
@ -84,7 +83,6 @@ export default defineComponent({
atTime: '00:00', atTime: '00:00',
after: 0, after: 0,
unit: 'second', unit: 'second',
faExclamationTriangle, faTimes
}; };
}, },
@ -190,7 +188,7 @@ export default defineComponent({
font-size: 0.8em; font-size: 0.8em;
color: #f00; color: #f00;
> [data-icon] { > i {
margin-right: 4px; margin-right: 4px;
} }
} }

View file

@ -4,7 +4,7 @@
<li v-for="(choice, i) in poll.choices" :key="i" @click="vote(i)" :class="{ voted: choice.voted }"> <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> <div class="backdrop" :style="{ 'width': `${showResult ? (choice.votes / total * 100) : 0}%` }"></div>
<span> <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"/> <Mfm :text="choice.text" :plain="true" :custom-emojis="note.emojis"/>
<span class="votes" v-if="showResult">({{ $t('_poll.votesCount', { n: choice.votes }) }})</span> <span class="votes" v-if="showResult">({{ $t('_poll.votesCount', { n: choice.votes }) }})</span>
</span> </span>
@ -23,7 +23,6 @@
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { faCheck } from '@fortawesome/free-solid-svg-icons';
import { sum } from '../../prelude/array'; import { sum } from '../../prelude/array';
import * as os from '@client/os'; import * as os from '@client/os';
@ -38,7 +37,6 @@ export default defineComponent({
return { return {
remaining: -1, remaining: -1,
showResult: false, showResult: false,
faCheck
}; };
}, },
computed: { computed: {
@ -135,7 +133,7 @@ export default defineComponent({
> span { > span {
position: relative; position: relative;
> [data-icon] { > i {
margin-right: 4px; margin-right: 4px;
} }

View file

@ -5,7 +5,7 @@
<div @click="showFileMenu(element, $event)" @contextmenu.prevent="showFileMenu(element, $event)"> <div @click="showFileMenu(element, $event)" @contextmenu.prevent="showFileMenu(element, $event)">
<MkDriveFileThumbnail :data-id="element.id" class="thumbnail" :file="element" fit="cover"/> <MkDriveFileThumbnail :data-id="element.id" class="thumbnail" :file="element" fit="cover"/>
<div class="sensitive" v-if="element.isSensitive"> <div class="sensitive" v-if="element.isSensitive">
<Fa class="icon" :icon="faExclamationTriangle"/> <i class="fas fa-exclamation-triangle icon"></i>
</div> </div>
</div> </div>
</template> </template>
@ -16,8 +16,6 @@
<script lang="ts"> <script lang="ts">
import { defineComponent, defineAsyncComponent } from 'vue'; 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 MkDriveFileThumbnail from './drive-file-thumbnail.vue'
import * as os from '@client/os'; import * as os from '@client/os';
@ -44,7 +42,6 @@ export default defineComponent({
return { return {
menu: null as Promise<null> | null, menu: null as Promise<null> | null,
faExclamationTriangle
}; };
}, },
@ -100,11 +97,11 @@ export default defineComponent({
action: () => { this.rename(file) } action: () => { this.rename(file) }
}, { }, {
text: file.isSensitive ? this.$ts.unmarkAsSensitive : this.$ts.markAsSensitive, 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) } action: () => { this.toggleSensitive(file) }
}, { }, {
text: this.$ts.attachCancel, text: this.$ts.attachCancel,
icon: faTimesCircle, icon: 'fas fa-times-circle',
action: () => { this.detachMedia(file.id) } action: () => { this.detachMedia(file.id) }
}], ev.currentTarget || ev.target).then(() => this.menu = null); }], ev.currentTarget || ev.target).then(() => this.menu = null);
} }

View file

@ -7,31 +7,31 @@
@drop.stop="onDrop" @drop.stop="onDrop"
> >
<header> <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> <div>
<span class="text-count" :class="{ over: textLength > max }">{{ max - textLength }}</span> <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"> <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 === 'public'"><i class="fas fa-globe"></i></span>
<span v-if="visibility === 'home'"><Fa :icon="faHome"/></span> <span v-if="visibility === 'home'"><i class="fas fa-home"></i></span>
<span v-if="visibility === 'followers'"><Fa :icon="faUnlock"/></span> <span v-if="visibility === 'followers'"><i class="fas fa-unlock"></i></span>
<span v-if="visibility === 'specified'"><Fa :icon="faEnvelope"/></span> <span v-if="visibility === 'specified'"><i class="fas fa-envelope"></i></span>
</button> </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> </div>
</header> </header>
<div class="form" :class="{ fixed }"> <div class="form" :class="{ fixed }">
<XNotePreview class="preview" v-if="reply" :note="reply"/> <XNotePreview class="preview" v-if="reply" :note="reply"/>
<XNotePreview class="preview" v-if="renote" :note="renote"/> <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"> <div v-if="visibility === 'specified'" class="to-specified">
<span style="margin-right: 8px;">{{ $ts.recipient }}</span> <span style="margin-right: 8px;">{{ $ts.recipient }}</span>
<div class="visibleUsers"> <div class="visibleUsers">
<span v-for="u in visibleUsers" :key="u.id"> <span v-for="u in visibleUsers" :key="u.id">
<MkAcct :user="u"/> <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> </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>
</div> </div>
<MkInfo warn v-if="hasNotSpecifiedMentions" class="hasNotSpecifiedMentions">{{ $ts.notSpecifiedMentionWarning }} - <button class="_textButton" @click="addMissingMention()">{{ $ts.add }}</button></MkInfo> <MkInfo warn v-if="hasNotSpecifiedMentions" class="hasNotSpecifiedMentions">{{ $ts.notSpecifiedMentionWarning }} - <button class="_textButton" @click="addMissingMention()">{{ $ts.add }}</button></MkInfo>
@ -40,12 +40,12 @@
<XPostFormAttaches class="attaches" :files="files" @updated="updateFiles" @detach="detachFile" @changeSensitive="updateFileSensitive" @changeName="updateFileName"/> <XPostFormAttaches class="attaches" :files="files" @updated="updateFiles" @detach="detachFile" @changeSensitive="updateFileSensitive" @changeName="updateFileName"/>
<XPollEditor v-if="poll" :poll="poll" @destroyed="poll = null" @updated="onPollUpdate"/> <XPollEditor v-if="poll" :poll="poll" @destroyed="poll = null" @updated="onPollUpdate"/>
<footer> <footer>
<button class="_button" @click="chooseFileFrom" v-tooltip="$ts.attachFile"><Fa :icon="faPhotoVideo"/></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"><Fa :icon="faPollH"/></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"><Fa :icon="faEyeSlash"/></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"><Fa :icon="faAt"/></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"><Fa :icon="faLaughSquint"/></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"><Fa :icon="faPlug"/></button> <button class="_button" @click="showActions" v-tooltip="$ts.plugin" v-if="postFormActions.length > 0"><i class="fas fa-plug"></i></button>
</footer> </footer>
</div> </div>
</div> </div>
@ -53,8 +53,6 @@
<script lang="ts"> <script lang="ts">
import { defineComponent, defineAsyncComponent } from 'vue'; 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 insertTextAtCursor from 'insert-text-at-cursor';
import { length } from 'stringz'; import { length } from 'stringz';
import { toASCII } from 'punycode/'; import { toASCII } from 'punycode/';
@ -155,7 +153,6 @@ export default defineComponent({
} }
}), }),
postFormActions, 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; opacity: 0.7;
} }
> [data-icon] { > i {
margin-left: 6px; margin-left: 6px;
} }
} }

View file

@ -1,10 +1,9 @@
<template> <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> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons';
import * as os from '@client/os'; import * as os from '@client/os';
export default defineComponent({ export default defineComponent({
@ -16,7 +15,6 @@ export default defineComponent({
}, },
data() { data() {
return { return {
faExclamationTriangle
}; };
} }
}); });

View file

@ -10,7 +10,7 @@
</MkInput> </MkInput>
<MkInput v-model:value="password" type="password" :with-password-toggle="true" v-if="!user || user && !user.usePasswordLessLogin" required> <MkInput v-model:value="password" type="password" :with-password-toggle="true" v-if="!user || user && !user.usePasswordLessLogin" required>
<span>{{ $ts.password }}</span> <span>{{ $ts.password }}</span>
<template #prefix><Fa :icon="faLock"/></template> <template #prefix><i class="fas fa-lock"></i></template>
</MkInput> </MkInput>
<MkButton type="submit" primary :disabled="signing" style="margin: 0 auto;">{{ signing ? $ts.loggingIn : $ts.login }}</MkButton> <MkButton type="submit" primary :disabled="signing" style="margin: 0 auto;">{{ signing ? $ts.loggingIn : $ts.login }}</MkButton>
</div> </div>
@ -28,20 +28,20 @@
<p style="margin-bottom:0;">{{ $ts.twoStepAuthentication }}</p> <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> <MkInput v-model:value="password" type="password" :with-password-toggle="true" v-if="user && user.usePasswordLessLogin" required>
<span>{{ $ts.password }}</span> <span>{{ $ts.password }}</span>
<template #prefix><Fa :icon="faLock"/></template> <template #prefix><i class="fas fa-lock"></i></template>
</MkInput> </MkInput>
<MkInput v-model:value="token" type="text" pattern="^[0-9]{6}$" autocomplete="off" spellcheck="false" required> <MkInput v-model:value="token" type="text" pattern="^[0-9]{6}$" autocomplete="off" spellcheck="false" required>
<span>{{ $ts.token }}</span> <span>{{ $ts.token }}</span>
<template #prefix><Fa :icon="faGavel"/></template> <template #prefix><i class="fas fa-gavel"></i></template>
</MkInput> </MkInput>
<MkButton type="submit" :disabled="signing" primary style="margin: 0 auto;">{{ signing ? $ts.loggingIn : $ts.login }}</MkButton> <MkButton type="submit" :disabled="signing" primary style="margin: 0 auto;">{{ signing ? $ts.loggingIn : $ts.login }}</MkButton>
</div> </div>
</div> </div>
</div> </div>
<div class="social _section"> <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.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`"><Fa :icon="faGithub" style="margin-right: 4px;"/>{{ $t('signinWith', { x: 'GitHub' }) }}</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`"><Fa :icon="faDiscord" style="margin-right: 4px;"/>{{ $t('signinWith', { x: 'Discord' }) }}</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> </div>
</form> </form>
</template> </template>
@ -49,8 +49,6 @@
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { toUnicode } from 'punycode/'; 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 MkButton from './ui/button.vue';
import MkInput from './ui/input.vue'; import MkInput from './ui/input.vue';
import { apiUrl, host } from '@client/config'; import { apiUrl, host } from '@client/config';
@ -92,7 +90,6 @@ export default defineComponent({
credential: null, credential: null,
challengeData: null, challengeData: null,
queryingKey: false, queryingKey: false,
faLock, faGavel, faTwitter, faDiscord, faGithub
}; };
}, },

View file

@ -3,37 +3,37 @@
<template v-if="meta"> <template v-if="meta">
<MkInput v-if="meta.disableRegistration" v-model:value="invitationCode" type="text" :autocomplete="Math.random()" spellcheck="false" required> <MkInput v-if="meta.disableRegistration" v-model:value="invitationCode" type="text" :autocomplete="Math.random()" spellcheck="false" required>
<span>{{ $ts.invitationCode }}</span> <span>{{ $ts.invitationCode }}</span>
<template #prefix><Fa :icon="faKey"/></template> <template #prefix><i class="fas fa-key"></i></template>
</MkInput> </MkInput>
<MkInput v-model:value="username" type="text" pattern="^[a-zA-Z0-9_]{1,20}$" :autocomplete="Math.random()" spellcheck="false" required @update:value="onChangeUsername"> <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> <span>{{ $ts.username }}</span>
<template #prefix>@</template> <template #prefix>@</template>
<template #suffix>@{{ host }}</template> <template #suffix>@{{ host }}</template>
<template #desc> <template #desc>
<span v-if="usernameState == 'wait'" style="color:#999"><Fa :icon="faSpinner" pulse fixed-width/> {{ $ts.checking }}</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"><Fa :icon="faCheck" fixed-width/> {{ $ts.available }}</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"><Fa :icon="faExclamationTriangle" fixed-width/> {{ $ts.unavailable }}</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"><Fa :icon="faExclamationTriangle" fixed-width/> {{ $ts.error }}</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"><Fa :icon="faExclamationTriangle" fixed-width/> {{ $ts.usernameInvalidFormat }}</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"><Fa :icon="faExclamationTriangle" fixed-width/> {{ $ts.tooShort }}</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"><Fa :icon="faExclamationTriangle" fixed-width/> {{ $ts.tooLong }}</span> <span v-if="usernameState == 'max-range'" style="color:#FF1161"><i class="fas fa-exclamation-triangle fa-fw"></i> {{ $ts.tooLong }}</span>
</template> </template>
</MkInput> </MkInput>
<MkInput v-model:value="password" type="password" :autocomplete="Math.random()" required @update:value="onChangePassword"> <MkInput v-model:value="password" type="password" :autocomplete="Math.random()" required @update:value="onChangePassword">
<span>{{ $ts.password }}</span> <span>{{ $ts.password }}</span>
<template #prefix><Fa :icon="faLock"/></template> <template #prefix><i class="fas fa-lock"></i></template>
<template #desc> <template #desc>
<p v-if="passwordStrength == 'low'" style="color:#FF1161"><Fa :icon="faExclamationTriangle" fixed-width/> {{ $ts.weakPassword }}</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"><Fa :icon="faCheck" fixed-width/> {{ $ts.normalPassword }}</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"><Fa :icon="faCheck" fixed-width/> {{ $ts.strongPassword }}</p> <p v-if="passwordStrength == 'high'" style="color:#3CB7B5"><i class="fas fa-check fa-fw"></i> {{ $ts.strongPassword }}</p>
</template> </template>
</MkInput> </MkInput>
<MkInput v-model:value="retypedPassword" type="password" :autocomplete="Math.random()" required @update:value="onChangePasswordRetype"> <MkInput v-model:value="retypedPassword" type="password" :autocomplete="Math.random()" required @update:value="onChangePasswordRetype">
<span>{{ $ts.password }} ({{ $ts.retype }})</span> <span>{{ $ts.password }} ({{ $ts.retype }})</span>
<template #prefix><Fa :icon="faLock"/></template> <template #prefix><i class="fas fa-lock"></i></template>
<template #desc> <template #desc>
<p v-if="passwordRetypeState == 'match'" style="color:#3CB7B5"><Fa :icon="faCheck" fixed-width/> {{ $ts.passwordMatched }}</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"><Fa :icon="faExclamationTriangle" fixed-width/> {{ $ts.passwordNotMatched }}</p> <p v-if="passwordRetypeState == 'not-match'" style="color:#FF1161"><i class="fas fa-exclamation-triangle fa-fw"></i> {{ $ts.passwordNotMatched }}</p>
</template> </template>
</MkInput> </MkInput>
<label v-if="meta.tosUrl" class="tou"> <label v-if="meta.tosUrl" class="tou">
@ -45,7 +45,7 @@
</I18n> </I18n>
</label> </label>
<captcha v-if="meta.enableHcaptcha" class="captcha" provider="hcaptcha" ref="hcaptcha" v-model:value="hCaptchaResponse" :sitekey="meta.hcaptchaSiteKey"/> <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> <MkButton type="submit" :disabled="shouldDisableSubmitting" primary>{{ $ts.start }}</MkButton>
</template> </template>
</form> </form>
@ -53,7 +53,6 @@
<script lang="ts"> <script lang="ts">
import { defineComponent, defineAsyncComponent } from 'vue'; import { defineComponent, defineAsyncComponent } from 'vue';
import { faLock, faExclamationTriangle, faSpinner, faCheck, faKey } from '@fortawesome/free-solid-svg-icons';
const getPasswordStrength = require('syuilo-password-strength'); const getPasswordStrength = require('syuilo-password-strength');
import { toUnicode } from 'punycode/'; import { toUnicode } from 'punycode/';
import { host, url } from '@client/config'; import { host, url } from '@client/config';
@ -96,7 +95,6 @@ export default defineComponent({
ToSAgreement: false, ToSAgreement: false,
hCaptchaResponse: null, hCaptchaResponse: null,
reCaptchaResponse: null, reCaptchaResponse: null,
faLock, faExclamationTriangle, faSpinner, faCheck, faKey
} }
}, },

View file

@ -3,7 +3,7 @@
<div class="body"> <div class="body">
<span v-if="note.isHidden" style="opacity: 0.5">({{ $ts.private }})</span> <span v-if="note.isHidden" style="opacity: 0.5">({{ $ts.private }})</span>
<span v-if="note.deletedAt" style="opacity: 0.5">({{ $ts.deleted }})</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"/> <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> <MkA class="rp" v-if="note.renoteId" :to="`/notes/${note.renoteId}`">RN: ...</MkA>
</div> </div>
@ -20,7 +20,6 @@
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { faReply } from '@fortawesome/free-solid-svg-icons';
import XPoll from './poll.vue'; import XPoll from './poll.vue';
import XMediaList from './media-list.vue'; import XMediaList from './media-list.vue';
import * as os from '@client/os'; import * as os from '@client/os';
@ -38,7 +37,6 @@ export default defineComponent({
}, },
data() { data() {
return { return {
faReply
}; };
} }
}); });

View file

@ -29,6 +29,7 @@ export default defineComponent({
<style lang="scss"> <style lang="scss">
.pxhvhrfw { .pxhvhrfw {
display: flex; display: flex;
font-size: 90%;
> button { > button {
flex: 1; flex: 1;

View file

@ -1,7 +1,7 @@
<template> <template>
<XWindow ref="window" :initial-width="650" :initial-height="420" :can-resize="true" @closed="$emit('closed')"> <XWindow ref="window" :initial-width="650" :initial-height="420" :can-resize="true" @closed="$emit('closed')">
<template #header> <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> </template>
<div class="qljqmnzj _monospace"> <div class="qljqmnzj _monospace">
<MkTab v-model:value="tab" style="border-bottom: solid 0.5px var(--divider);"> <MkTab v-model:value="tab" style="border-bottom: solid 0.5px var(--divider);">
@ -78,7 +78,6 @@
<script lang="ts"> <script lang="ts">
import { defineComponent, markRaw, onBeforeUnmount, ref, shallowRef } from 'vue'; 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 XWindow from '@client/components/ui/window.vue';
import MkTab from '@client/components/tab.vue'; import MkTab from '@client/components/tab.vue';
import MkButton from '@client/components/ui/button.vue'; import MkButton from '@client/components/ui/button.vue';
@ -139,7 +138,6 @@ export default defineComponent({
pools, pools,
killPopup, killPopup,
showReq, showReq,
faTerminal,
}; };
}, },
}); });

View file

@ -5,8 +5,8 @@
<div class="sub"> <div class="sub">
<slot name="func"></slot> <slot name="func"></slot>
<button class="_button" v-if="foldable" @click="() => showBody = !showBody"> <button class="_button" v-if="foldable" @click="() => showBody = !showBody">
<template v-if="showBody"><Fa :icon="faAngleUp"/></template> <template v-if="showBody"><i class="fas fa-angle-up"></i></template>
<template v-else><Fa :icon="faAngleDown"/></template> <template v-else><i class="fas fa-angle-down"></i></template>
</button> </button>
</div> </div>
</header> </header>
@ -28,7 +28,6 @@
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { faAngleUp, faAngleDown } from '@fortawesome/free-solid-svg-icons';
export default defineComponent({ export default defineComponent({
props: { props: {
@ -68,7 +67,6 @@ export default defineComponent({
showBody: this.expanded, showBody: this.expanded,
omitted: null, omitted: null,
ignoreOmit: false, ignoreOmit: false,
faAngleUp, faAngleDown
}; };
}, },
mounted() { mounted() {
@ -169,7 +167,7 @@ export default defineComponent({
margin: 0; margin: 0;
padding: 12px 16px; padding: 12px 16px;
> ::v-deep([data-icon]) { > ::v-deep(i) {
margin-right: 6px; margin-right: 6px;
} }

View file

@ -4,8 +4,8 @@
<div class="title"><slot name="header"></slot></div> <div class="title"><slot name="header"></slot></div>
<div class="divider"></div> <div class="divider"></div>
<button class="_button"> <button class="_button">
<template v-if="showBody"><Fa :icon="faAngleUp"/></template> <template v-if="showBody"><i class="fas fa-angle-up"></i></template>
<template v-else><Fa :icon="faAngleDown"/></template> <template v-else><i class="fas fa-angle-down"></i></template>
</button> </button>
</header> </header>
<transition name="folder-toggle" <transition name="folder-toggle"
@ -23,7 +23,6 @@
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { faAngleUp, faAngleDown } from '@fortawesome/free-solid-svg-icons';
const localStoragePrefix = 'ui:folder:'; const localStoragePrefix = 'ui:folder:';
@ -43,7 +42,6 @@ export default defineComponent({
data() { data() {
return { return {
showBody: (this.persistKey && localStorage.getItem(localStoragePrefix + this.persistKey)) ? localStorage.getItem(localStoragePrefix + this.persistKey) === 't' : this.expanded, showBody: (this.persistKey && localStorage.getItem(localStoragePrefix + this.persistKey)) ? localStorage.getItem(localStoragePrefix + this.persistKey) === 't' : this.expanded,
faAngleUp, faAngleDown
}; };
}, },
watch: { watch: {
@ -109,7 +107,7 @@ export default defineComponent({
margin: 0; margin: 0;
padding: 12px 16px 12px 0; padding: 12px 16px 12px 0;
> [data-icon] { > i {
margin-right: 6px; margin-right: 6px;
} }

View file

@ -1,14 +1,13 @@
<template> <template>
<div class="fpezltsf" :class="{ warn }"> <div class="fpezltsf" :class="{ warn }">
<i v-if="warn"><Fa :icon="faExclamationTriangle"/></i> <i v-if="warn" class="fas fa-exclamation-triangle"></i>
<i v-else><Fa :icon="faInfoCircle"/></i> <i v-else class="fas fa-info-circle"></i>
<slot></slot> <slot></slot>
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { faInfoCircle, faExclamationTriangle } from '@fortawesome/free-solid-svg-icons';
import * as os from '@client/os'; import * as os from '@client/os';
export default defineComponent({ export default defineComponent({
@ -21,7 +20,6 @@ export default defineComponent({
}, },
data() { data() {
return { return {
faInfoCircle, faExclamationTriangle
}; };
} }
}); });

View file

@ -5,7 +5,7 @@
<span class="label" ref="labelEl"><slot></slot></span> <span class="label" ref="labelEl"><slot></slot></span>
<span class="title" ref="title"> <span class="title" ref="title">
<slot name="title"></slot> <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> </span>
<div class="prefix" ref="prefixEl"><slot name="prefix"></slot></div> <div class="prefix" ref="prefixEl"><slot name="prefix"></slot></div>
<input v-if="debounce" ref="inputEl" <input v-if="debounce" ref="inputEl"
@ -56,7 +56,6 @@
<script lang="ts"> <script lang="ts">
import { defineComponent, onMounted, onUnmounted, nextTick, ref, watch, computed, toRefs } from 'vue'; import { defineComponent, onMounted, onUnmounted, nextTick, ref, watch, computed, toRefs } from 'vue';
import debounce from 'v-debounce'; import debounce from 'v-debounce';
import { faExclamationCircle } from '@fortawesome/free-solid-svg-icons';
import * as os from '@client/os'; import * as os from '@client/os';
export default defineComponent({ export default defineComponent({
@ -205,7 +204,6 @@ export default defineComponent({
focus, focus,
onInput, onInput,
onKeydown, onKeydown,
faExclamationCircle,
}; };
}, },
}); });

View file

@ -13,25 +13,25 @@
<span><MkEllipsis/></span> <span><MkEllipsis/></span>
</span> </span>
<MkA v-else-if="item.type === 'link'" :to="item.to" @click.passive="close()" :tabindex="i" class="_button item"> <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"/> <MkAvatar v-if="item.avatar" :user="item.avatar" class="avatar"/>
<span>{{ item.text }}</span> <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> </MkA>
<a v-else-if="item.type === 'a'" :href="item.href" :target="item.target" :download="item.download" @click="close()" :tabindex="i" class="_button item"> <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> <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> </a>
<button v-else-if="item.type === 'user'" @click="clicked(item.action, $event)" :tabindex="i" class="_button item"> <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"/> <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>
<button v-else @click="clicked(item.action, $event)" :tabindex="i" class="_button item" :class="{ danger: item.danger }"> <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"/> <MkAvatar v-if="item.avatar" :user="item.avatar" class="avatar"/>
<span>{{ item.text }}</span> <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> </button>
</template> </template>
<span v-if="_items.length === 0" class="none item"> <span v-if="_items.length === 0" class="none item">
@ -42,7 +42,6 @@
<script lang="ts"> <script lang="ts">
import { defineComponent, ref } from 'vue'; import { defineComponent, ref } from 'vue';
import { faCircle } from '@fortawesome/free-solid-svg-icons';
import { focusPrev, focusNext } from '@client/scripts/focus'; import { focusPrev, focusNext } from '@client/scripts/focus';
import contains from '@client/scripts/contains'; import contains from '@client/scripts/contains';
@ -65,7 +64,6 @@ export default defineComponent({
data() { data() {
return { return {
_items: [], _items: [],
faCircle,
}; };
}, },
computed: { computed: {
@ -207,7 +205,7 @@ export default defineComponent({
opacity: 0.7; opacity: 0.7;
} }
> [data-icon] { > i {
margin-right: 4px; margin-right: 4px;
width: 20px; width: 20px;
} }
@ -218,7 +216,7 @@ export default defineComponent({
height: 20px; height: 20px;
} }
> i { > .indicator {
position: absolute; position: absolute;
top: 5px; top: 5px;
left: 13px; left: 13px;

View file

@ -2,12 +2,12 @@
<MkModal ref="modal" @click="$emit('click')" @closed="$emit('closed')"> <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="ebkgoccj _popup _narrow_" @keydown="onKeydown" :style="{ width: `${width}px`, height: scroll ? (height ? `${height}px` : null) : (height ? `min(${height}px, 100%)` : '100%') }">
<div class="header"> <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"> <span class="title">
<slot name="header"></slot> <slot name="header"></slot>
</span> </span>
<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>
<button class="_button" v-if="withOkButton" @click="$emit('ok')" :disabled="okButtonDisabled"><Fa :icon="faCheck"/></button> <button class="_button" v-if="withOkButton" @click="$emit('ok')" :disabled="okButtonDisabled"><i class="fas fa-check"></i></button>
</div> </div>
<div class="body" v-if="padding"> <div class="body" v-if="padding">
<div class="_section"> <div class="_section">
@ -23,7 +23,6 @@
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { faTimes, faCheck } from '@fortawesome/free-solid-svg-icons';
import MkModal from './modal.vue'; import MkModal from './modal.vue';
export default defineComponent({ export default defineComponent({
@ -72,7 +71,6 @@ export default defineComponent({
data() { data() {
return { return {
faTimes, faCheck
}; };
}, },

View file

@ -1,16 +1,23 @@
<template> <template>
<div class="cxiknjgy"> <transition name="fade" mode="out-in">
<slot :items="items"></slot> <MkLoading v-if="fetching"/>
<div class="empty" v-if="empty" key="_empty_">
<MkError v-else-if="error" @retry="init()"/>
<div class="empty" v-else-if="empty" key="_empty_">
<slot name="empty"></slot> <slot name="empty"></slot>
</div> </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> <div v-else class="cxiknjgy">
<template v-if="!moreFetching">{{ $ts.loadMore }}</template> <slot :items="items"></slot>
<template v-if="moreFetching"><MkLoading inline/></template> <div class="more" v-show="more" key="_more_">
</MkButton> <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>
</div> </transition>
</template> </template>
<script lang="ts"> <script lang="ts">
@ -36,6 +43,15 @@ export default defineComponent({
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.125s ease;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
.cxiknjgy { .cxiknjgy {
> .more > .button { > .more > .button {
margin-left: auto; margin-left: auto;

View file

@ -15,7 +15,7 @@
</select> </select>
<div class="suffix"> <div class="suffix">
<slot name="suffix"> <slot name="suffix">
<Fa :icon="faChevronDown"/> <i class="fas fa-chevron-down"></i>
</slot> </slot>
</div> </div>
</div> </div>
@ -25,7 +25,6 @@
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { faChevronDown } from '@fortawesome/free-solid-svg-icons';
export default defineComponent({ export default defineComponent({
props: { props: {
@ -49,7 +48,6 @@ export default defineComponent({
data() { data() {
return { return {
focused: false, focused: false,
faChevronDown,
}; };
}, },
computed: { computed: {

View file

@ -4,13 +4,13 @@
<div class="body _popup _shadow _narrow_" @mousedown="onBodyMousedown" @keydown="onKeydown"> <div class="body _popup _shadow _narrow_" @mousedown="onBodyMousedown" @keydown="onKeydown">
<div class="header" :class="{ mini }" @contextmenu.prevent.stop="onContextmenu"> <div class="header" :class="{ mini }" @contextmenu.prevent.stop="onContextmenu">
<slot v-if="closeRight" name="buttons"><button class="_button" style="pointer-events: none;"></button></slot> <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"> <span class="title" @mousedown.prevent="onHeaderMousedown" @touchstart.prevent="onHeaderMousedown">
<slot name="header"></slot> <slot name="header"></slot>
</span> </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> <slot v-else name="buttons"><button class="_button" style="pointer-events: none;"></button></slot>
</div> </div>
<div class="body" v-if="padding"> <div class="body" v-if="padding">
@ -38,7 +38,6 @@
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { faTimes, faCheck } from '@fortawesome/free-solid-svg-icons';
import contains from '@client/scripts/contains'; import contains from '@client/scripts/contains';
import * as os from '@client/os'; import * as os from '@client/os';
@ -114,7 +113,6 @@ export default defineComponent({
return { return {
showing: true, showing: true,
id: Math.random().toString(), // TODO: UUID id: Math.random().toString(), // TODO: UUID
faTimes
}; };
}, },

View file

@ -1,6 +1,6 @@
<template> <template>
<div v-if="playerEnabled" class="player" :style="`padding: ${(player.height || 0) / (player.width || 1) * 100}% 0 0`"> <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 /> <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>
<div v-else-if="tweetId && tweetExpanded" class="twitter" ref="twitter"> <div v-else-if="tweetId && tweetExpanded" class="twitter" ref="twitter">
@ -10,7 +10,7 @@
<transition name="zoom" mode="out-in"> <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"> <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}')`"> <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> </div>
<article> <article>
<header> <header>
@ -26,7 +26,7 @@
</transition> </transition>
<div class="expandTweet" v-if="tweetId"> <div class="expandTweet" v-if="tweetId">
<a @click="tweetExpanded = true"> <a @click="tweetExpanded = true">
<Fa :icon="faTwitter"/> {{ $ts.expandTweet }} <i class="fab fa-twitter"></i> {{ $ts.expandTweet }}
</a> </a>
</div> </div>
</div> </div>
@ -34,8 +34,6 @@
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; 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 { url as local, lang } from '@client/config';
import * as os from '@client/os'; import * as os from '@client/os';
@ -83,7 +81,6 @@ export default defineComponent({
self: self, self: self,
attr: self ? 'to' : 'href', attr: self ? 'to' : 'href',
target: self ? null : '_blank', target: self ? null : '_blank',
faPlayCircle, faTwitter
}; };
}, },

View file

@ -9,7 +9,7 @@
<MkUserInfo class="user" v-for="user in users" :user="user" :key="user.id"/> <MkUserInfo class="user" v-for="user in users" :user="user" :key="user.id"/>
</div> </div>
<button class="more" v-appear="$store.state.enableInfiniteScroll ? fetchMore : null" @click="fetchMore" :class="{ fetching: moreFetching }" v-show="more" :disabled="moreFetching"> <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> </button>
</div> </div>
</template> </template>
@ -83,7 +83,7 @@ export default defineComponent({
cursor: wait; cursor: wait;
} }
> [data-icon] { > i {
margin-right: 4px; margin-right: 4px;
} }
} }

View file

@ -29,7 +29,7 @@ export default defineComponent({
<style lang="scss" scoped> <style lang="scss" scoped>
.fzgwjkgc { .fzgwjkgc {
box-shadow: 0 0 0 3px var(--panel); box-shadow: 0 0 0 3px var(--panel);
border-radius: 100%; border-radius: 120%; // Blink100%
&.online { &.online {
background: #58d4c9; background: #58d4c9;

View file

@ -44,7 +44,6 @@
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { faTimes, faCheck } from '@fortawesome/free-solid-svg-icons';
import MkInput from './ui/input.vue'; import MkInput from './ui/input.vue';
import XModalWindow from '@client/components/ui/modal-window.vue'; import XModalWindow from '@client/components/ui/modal-window.vue';
import * as os from '@client/os'; import * as os from '@client/os';
@ -67,7 +66,6 @@ export default defineComponent({
recentUsers: [], recentUsers: [],
users: [], users: [],
selected: null, selected: null,
faTimes, faCheck
}; };
}, },

View file

@ -2,7 +2,7 @@
<div class="mk-users-dialog"> <div class="mk-users-dialog">
<div class="header"> <div class="header">
<span>{{ title }}</span> <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>
<div class="users"> <div class="users">
@ -16,7 +16,7 @@
</div> </div>
<button class="more _button" v-appear="$store.state.enableInfiniteScroll ? fetchMore : null" @click="fetchMore" v-show="more" :disabled="moreFetching"> <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">{{ $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> </button>
<p class="empty" v-if="empty">{{ $ts.noUsers }}</p> <p class="empty" v-if="empty">{{ $ts.noUsers }}</p>
@ -27,7 +27,6 @@
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { faTimes } from '@fortawesome/free-solid-svg-icons';
import paging from '@client/scripts/paging'; import paging from '@client/scripts/paging';
import { userPage } from '../filters/user'; import { userPage } from '../filters/user';
@ -50,7 +49,6 @@ export default defineComponent({
data() { data() {
return { return {
faTimes
}; };
}, },

View file

@ -2,28 +2,28 @@
<MkModal ref="modal" :src="src" @click="$refs.modal.close()" @closed="$emit('closed')"> <MkModal ref="modal" :src="src" @click="$refs.modal.close()" @closed="$emit('closed')">
<div class="gqyayizv _popup"> <div class="gqyayizv _popup">
<button class="_button" @click="choose('public')" :class="{ active: v == 'public' }" data-index="1" key="public"> <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> <div>
<span>{{ $ts._visibility.public }}</span> <span>{{ $ts._visibility.public }}</span>
<span>{{ $ts._visibility.publicDescription }}</span> <span>{{ $ts._visibility.publicDescription }}</span>
</div> </div>
</button> </button>
<button class="_button" @click="choose('home')" :class="{ active: v == 'home' }" data-index="2" key="home"> <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> <div>
<span>{{ $ts._visibility.home }}</span> <span>{{ $ts._visibility.home }}</span>
<span>{{ $ts._visibility.homeDescription }}</span> <span>{{ $ts._visibility.homeDescription }}</span>
</div> </div>
</button> </button>
<button class="_button" @click="choose('followers')" :class="{ active: v == 'followers' }" data-index="3" key="followers"> <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> <div>
<span>{{ $ts._visibility.followers }}</span> <span>{{ $ts._visibility.followers }}</span>
<span>{{ $ts._visibility.followersDescription }}</span> <span>{{ $ts._visibility.followersDescription }}</span>
</div> </div>
</button> </button>
<button :disabled="localOnly" class="_button" @click="choose('specified')" :class="{ active: v == 'specified' }" data-index="4" key="specified"> <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> <div>
<span>{{ $ts._visibility.specified }}</span> <span>{{ $ts._visibility.specified }}</span>
<span>{{ $ts._visibility.specifiedDescription }}</span> <span>{{ $ts._visibility.specifiedDescription }}</span>
@ -31,12 +31,12 @@
</button> </button>
<div class="divider"></div> <div class="divider"></div>
<button class="_button localOnly" @click="localOnly = !localOnly" :class="{ active: localOnly }" data-index="5" key="localOnly"> <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> <div>
<span>{{ $ts._visibility.localOnly }}</span> <span>{{ $ts._visibility.localOnly }}</span>
<span>{{ $ts._visibility.localOnlyDescription }}</span> <span>{{ $ts._visibility.localOnlyDescription }}</span>
</div> </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> </button>
</div> </div>
</MkModal> </MkModal>
@ -44,8 +44,6 @@
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; 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'; import MkModal from '@client/components/ui/modal.vue';
export default defineComponent({ export default defineComponent({
@ -70,7 +68,6 @@ export default defineComponent({
return { return {
v: this.currentVisibility, v: this.currentVisibility,
localOnly: this.currentLocalOnly, localOnly: this.currentLocalOnly,
faGlobe, faUnlock, faEnvelope, faHome, faBiohazard, faToggleOn, faToggleOff
} }
}, },
watch: { watch: {

View file

@ -1,8 +1,8 @@
<template> <template>
<MkModal ref="modal" @click="success ? done() : () => {}" @closed="$emit('closed')"> <MkModal ref="modal" @click="success ? done() : () => {}" @closed="$emit('closed')">
<div class="iuyakobc" :class="{ iconOnly: (text == null) || success }"> <div class="iuyakobc" :class="{ iconOnly: (text == null) || success }">
<Fa class="icon success" v-if="success" :icon="faCheck"/> <i v-if="success" class="fas fa-check icon success"></i>
<Fa class="icon waiting" v-else :icon="faSpinner" pulse/> <i v-else class="fas fa-spinner fa-pulse icon waiting"></i>
<div class="text" v-if="text && !success">{{ text }}<MkEllipsis/></div> <div class="text" v-if="text && !success">{{ text }}<MkEllipsis/></div>
</div> </div>
</MkModal> </MkModal>
@ -10,7 +10,6 @@
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { faCheck, faSpinner } from '@fortawesome/free-solid-svg-icons';
import MkModal from '@client/components/ui/modal.vue'; import MkModal from '@client/components/ui/modal.vue';
export default defineComponent({ export default defineComponent({
@ -37,7 +36,6 @@ export default defineComponent({
data() { data() {
return { return {
faCheck, faSpinner,
}; };
}, },
@ -70,10 +68,9 @@ export default defineComponent({
padding: 0; padding: 0;
width: 96px; width: 96px;
height: 96px; height: 96px;
display: flex;
> .icon { align-items: center;
height: 100%; justify-content: center;
}
} }
> .icon { > .icon {

View file

@ -6,7 +6,7 @@
<template #label>{{ $ts.selectWidget }}</template> <template #label>{{ $ts.selectWidget }}</template>
<option v-for="widget in widgetDefs" :value="widget" :key="widget">{{ $t(`_widgets.${widget}`) }}</option> <option v-for="widget in widgetDefs" :value="widget" :key="widget">{{ $t(`_widgets.${widget}`) }}</option>
</MkSelect> </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> <MkButton inline @click="$emit('exit')">{{ $ts.close }}</MkButton>
</header> </header>
<XDraggable <XDraggable
@ -16,8 +16,8 @@
> >
<template #item="{element}"> <template #item="{element}">
<div class="customize-container"> <div class="customize-container">
<button class="config _button" @click.prevent.stop="configWidget(element.id)"><Fa :icon="faCog"/></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)"><Fa :icon="faTimes"/></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)"/> <component :is="`mkw-${element.name}`" :widget="element" :setting-callback="setting => settings[element.id] = setting" :column="column" @updateProps="updateWidget(element.id, $event)"/>
</div> </div>
</template> </template>
@ -30,7 +30,6 @@
<script lang="ts"> <script lang="ts">
import { defineComponent, defineAsyncComponent } from 'vue'; import { defineComponent, defineAsyncComponent } from 'vue';
import { v4 as uuid } from 'uuid'; 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 MkSelect from '@client/components/ui/select.vue';
import MkButton from '@client/components/ui/button.vue'; import MkButton from '@client/components/ui/button.vue';
import { widgets as widgetDefs } from '@client/widgets'; import { widgets as widgetDefs } from '@client/widgets';
@ -59,7 +58,6 @@ export default defineComponent({
widgetAdderSelected: null, widgetAdderSelected: null,
widgetDefs, widgetDefs,
settings: {}, settings: {},
faTimes, faPlus, faCog
}; };
}, },

View file

@ -0,0 +1,22 @@
import { Directive } from 'vue';
export default {
mounted(el, binding, vn) {
el.addEventListener('mousedown', () => {
el.classList.add('_anime_bounce_ready');
el.addEventListener('mouseleave', () => {
el.classList.remove('_anime_bounce_ready');
});
});
el.addEventListener('click', () => {
el.classList.add('_anime_bounce');
});
el.addEventListener('animationend', () => {
el.classList.remove('_anime_bounce_ready');
el.classList.remove('_anime_bounce');
});
}
} as Directive;

View file

@ -8,6 +8,7 @@ import hotkey from './hotkey';
import appear from './appear'; import appear from './appear';
import anim from './anim'; import anim from './anim';
import stickyContainer from './sticky-container'; import stickyContainer from './sticky-container';
import clickAnime from './click-anime';
export default function(app: App) { export default function(app: App) {
app.directive('userPreview', userPreview); app.directive('userPreview', userPreview);
@ -18,5 +19,6 @@ export default function(app: App) {
app.directive('hotkey', hotkey); app.directive('hotkey', hotkey);
app.directive('appear', appear); app.directive('appear', appear);
app.directive('anim', anim); app.directive('anim', anim);
app.directive('click-anime', clickAnime);
app.directive('sticky-container', stickyContainer); app.directive('sticky-container', stickyContainer);
} }

View file

@ -7,7 +7,6 @@ import '@client/style.scss';
import * as Sentry from '@sentry/browser'; import * as Sentry from '@sentry/browser';
import { Integrations } from '@sentry/tracing'; import { Integrations } from '@sentry/tracing';
import { computed, createApp, watch } from 'vue'; import { computed, createApp, watch } from 'vue';
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
import widgets from '@client/widgets'; import widgets from '@client/widgets';
import directives from '@client/directives'; 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('lightTheme', require('@client/themes/l-light.json5'));
ColdDeviceStorage.set('darkTheme', require('@client/themes/d-dark.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_) { if (_DEV_) {
console.warn('Development mode!!!'); console.warn('Development mode!!!');
@ -184,8 +188,6 @@ app.config.globalProperties = {
}; };
app.use(router); app.use(router);
// eslint-disable-next-line vue/component-definition-name-casing
app.component('Fa', FontAwesomeIcon);
widgets(app); widgets(app);
directives(app); directives(app);

View file

@ -3,7 +3,7 @@
<div class="_section"> <div class="_section">
<div class="mjndxjch _content"> <div class="mjndxjch _content">
<img src="https://xn--931a.moe/assets/error.jpg" class="_ghost"/> <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> <p>{{ $ts.pageLoadErrorDescription }}</p>
</div> </div>
</div> </div>
@ -12,7 +12,6 @@
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons';
import MkButton from '@client/components/ui/button.vue'; import MkButton from '@client/components/ui/button.vue';
import * as symbols from '@client/symbols'; import * as symbols from '@client/symbols';
@ -24,9 +23,8 @@ export default defineComponent({
return { return {
[symbols.PAGE_INFO]: { [symbols.PAGE_INFO]: {
title: this.$ts.error, title: this.$ts.error,
icon: faExclamationTriangle icon: 'fas fa-exclamation-triangle'
}, },
faExclamationTriangle
}; };
}, },
}); });

View file

@ -15,17 +15,17 @@
</section> </section>
<FormGroup> <FormGroup>
<FormLink to="https://github.com/misskey-dev/misskey" external> <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 }} {{ $ts._aboutMisskey.source }}
<template #suffix>GitHub</template> <template #suffix>GitHub</template>
</FormLink> </FormLink>
<FormLink to="https://crowdin.com/project/misskey" external> <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 }} {{ $ts._aboutMisskey.translation }}
<template #suffix>Crowdin</template> <template #suffix>Crowdin</template>
</FormLink> </FormLink>
<FormLink to="https://www.patreon.com/syuilo" external> <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 }} {{ $ts._aboutMisskey.donate }}
<template #suffix>Patreon</template> <template #suffix>Patreon</template>
</FormLink> </FormLink>
@ -54,7 +54,6 @@
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { faInfoCircle, faCode, faLanguage, faHandHoldingMedical, } from '@fortawesome/free-solid-svg-icons';
import VanillaTilt from 'vanilla-tilt'; import VanillaTilt from 'vanilla-tilt';
import { version } from '@client/config'; import { version } from '@client/config';
import FormLink from '@client/components/form/link.vue'; import FormLink from '@client/components/form/link.vue';
@ -125,7 +124,6 @@ export default defineComponent({
easterEggReady: false, easterEggReady: false,
easterEggEmojis: [], easterEggEmojis: [],
easterEggEngine: null, easterEggEngine: null,
faInfoCircle, faCode, faLanguage, faHandHoldingMedical,
} }
}, },

View file

@ -40,7 +40,6 @@
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { faInfoCircle } from '@fortawesome/free-solid-svg-icons';
import { version, instanceName } from '@client/config'; import { version, instanceName } from '@client/config';
import FormLink from '@client/components/form/link.vue'; import FormLink from '@client/components/form/link.vue';
import FormBase from '@client/components/form/base.vue'; import FormBase from '@client/components/form/base.vue';
@ -62,12 +61,11 @@ export default defineComponent({
return { return {
[symbols.PAGE_INFO]: { [symbols.PAGE_INFO]: {
title: this.$ts.instanceInfo, title: this.$ts.instanceInfo,
icon: faInfoCircle icon: 'fas fa-info-circle'
}, },
version, version,
instanceName, instanceName,
stats: null, stats: null,
faInfoCircle
} }
}, },

View file

@ -34,7 +34,7 @@
</div> </div>
<div> <div>
<div class="type" @click="chooseType($event, i)"> <div class="type" @click="chooseType($event, i)">
{{ getTypeOf(v) }} <Fa :icon="faChevronDown"/> {{ getTypeOf(v) }} <i class="fas fa-chevron-down"></i>
</div> </div>
<!-- default --> <!-- default -->
<div v-if="v === null" v-text="baseProps[k]" class="default-value" /> <div v-if="v === null" v-text="baseProps[k]" class="default-value" />
@ -92,7 +92,6 @@
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { faPalette, faChevronDown, faKeyboard } from '@fortawesome/free-solid-svg-icons';
import * as JSON5 from 'json5'; import * as JSON5 from 'json5';
import { toUnicode } from 'punycode/'; import { toUnicode } from 'punycode/';
@ -125,7 +124,7 @@ export default defineComponent({
return { return {
[symbols.PAGE_INFO]: { [symbols.PAGE_INFO]: {
title: this.$ts.themeEditor, title: this.$ts.themeEditor,
icon: faPalette, icon: 'fas fa-palette',
}, },
theme: [] as ThemeViewModel, theme: [] as ThemeViewModel,
name: '', name: '',
@ -135,7 +134,6 @@ export default defineComponent({
themeToImport: '', themeToImport: '',
changed: false, changed: false,
lightTheme, darkTheme, themeProps, lightTheme, darkTheme, themeProps,
faPalette, faChevronDown, faKeyboard,
} }
}, },

View file

@ -8,7 +8,7 @@
<img v-if="announcement.imageUrl" :src="announcement.imageUrl"/> <img v-if="announcement.imageUrl" :src="announcement.imageUrl"/>
</div> </div>
<div class="_footer" v-if="$i && !announcement.isRead"> <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> </div>
</section> </section>
</MkPagination> </MkPagination>
@ -17,7 +17,6 @@
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { faCheck, faBroadcastTower } from '@fortawesome/free-solid-svg-icons';
import MkPagination from '@client/components/ui/pagination.vue'; import MkPagination from '@client/components/ui/pagination.vue';
import MkButton from '@client/components/ui/button.vue'; import MkButton from '@client/components/ui/button.vue';
import * as os from '@client/os'; import * as os from '@client/os';
@ -33,13 +32,12 @@ export default defineComponent({
return { return {
[symbols.PAGE_INFO]: { [symbols.PAGE_INFO]: {
title: this.$ts.announcements, title: this.$ts.announcements,
icon: faBroadcastTower icon: 'fas fa-broadcast-tower'
}, },
pagination: { pagination: {
endpoint: 'announcements', endpoint: 'announcements',
limit: 10, limit: 10,
}, },
faCheck,
}; };
}, },

View file

@ -12,7 +12,7 @@
</MkSwitch> </MkSwitch>
<MkButton primary full @click="send" :disabled="sending"> <MkButton primary full @click="send" :disabled="sending">
<template v-if="sending"><MkEllipsis/></template> <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> </MkButton>
</div> </div>
<div v-if="res" class="_block" style="padding: 24px;"> <div v-if="res" class="_block" style="padding: 24px;">
@ -25,7 +25,6 @@
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { faTerminal, faPaperPlane } from '@fortawesome/free-solid-svg-icons';
import * as JSON5 from 'json5'; import * as JSON5 from 'json5';
import MkButton from '@client/components/ui/button.vue'; import MkButton from '@client/components/ui/button.vue';
import MkInput from '@client/components/ui/input.vue'; import MkInput from '@client/components/ui/input.vue';
@ -43,7 +42,7 @@ export default defineComponent({
return { return {
[symbols.PAGE_INFO]: { [symbols.PAGE_INFO]: {
title: 'API console', title: 'API console',
icon: faTerminal icon: 'fas fa-terminal'
}, },
endpoint: '', endpoint: '',
@ -53,7 +52,6 @@ export default defineComponent({
endpoints: [], endpoints: [],
withCredential: true, withCredential: true,
faPaperPlane
}; };
}, },

View file

@ -7,15 +7,15 @@
<MkTextarea v-model:value="description">{{ $ts.description }}</MkTextarea> <MkTextarea v-model:value="description">{{ $ts.description }}</MkTextarea>
<div class="banner"> <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"> <div v-else-if="bannerUrl">
<img :src="bannerUrl" style="width: 100%;"/> <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>
</div> </div>
<div class="_footer"> <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> </div>
</div> </div>
@ -23,8 +23,6 @@
<script lang="ts"> <script lang="ts">
import { computed, defineComponent } from 'vue'; 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 MkTextarea from '@client/components/ui/textarea.vue';
import MkButton from '@client/components/ui/button.vue'; import MkButton from '@client/components/ui/button.vue';
import MkInput from '@client/components/ui/input.vue'; import MkInput from '@client/components/ui/input.vue';
@ -48,17 +46,16 @@ export default defineComponent({
return { return {
[symbols.PAGE_INFO]: computed(() => this.channelId ? { [symbols.PAGE_INFO]: computed(() => this.channelId ? {
title: this.$ts._channel.edit, title: this.$ts._channel.edit,
icon: faSatelliteDish, icon: 'fas fa-satellite-dish',
} : { } : {
title: this.$ts._channel.create, title: this.$ts._channel.create,
icon: faSatelliteDish, icon: 'fas fa-satellite-dish',
}), }),
channel: null, channel: null,
name: null, name: null,
description: null, description: null,
bannerUrl: null, bannerUrl: null,
bannerId: null, bannerId: null,
faSave, faTrashAlt, faPlus,faSatelliteDish,
}; };
}, },

View file

@ -3,15 +3,15 @@
<div class="wpgynlbz _content _panel _gap" :class="{ hide: !showBanner }"> <div class="wpgynlbz _content _panel _gap" :class="{ hide: !showBanner }">
<XChannelFollowButton :channel="channel" :full="true" class="subscribe"/> <XChannelFollowButton :channel="channel" :full="true" class="subscribe"/>
<button class="_button toggle" @click="() => showBanner = !showBanner"> <button class="_button toggle" @click="() => showBanner = !showBanner">
<template v-if="showBanner"><Fa :icon="faAngleUp"/></template> <template v-if="showBanner"><i class="fas fa-angle-up"></i></template>
<template v-else><Fa :icon="faAngleDown"/></template> <template v-else><i class="fas fa-angle-down"></i></template>
</button> </button>
<div class="hideOverlay" v-if="!showBanner"> <div class="hideOverlay" v-if="!showBanner">
</div> </div>
<div :style="{ backgroundImage: channel.bannerUrl ? `url(${channel.bannerUrl})` : null }" class="banner"> <div :style="{ backgroundImage: channel.bannerUrl ? `url(${channel.bannerUrl})` : null }" class="banner">
<div class="status"> <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><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><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-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>
<div class="fade"></div> <div class="fade"></div>
</div> </div>
@ -28,8 +28,6 @@
<script lang="ts"> <script lang="ts">
import { computed, defineComponent } from 'vue'; 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 MkContainer from '@client/components/ui/container.vue';
import XPostForm from '@client/components/post-form.vue'; import XPostForm from '@client/components/post-form.vue';
import XTimeline from '@client/components/timeline.vue'; import XTimeline from '@client/components/timeline.vue';
@ -56,7 +54,7 @@ export default defineComponent({
return { return {
[symbols.PAGE_INFO]: computed(() => this.channel ? { [symbols.PAGE_INFO]: computed(() => this.channel ? {
title: this.channel.name, title: this.channel.name,
icon: faSatelliteDish, icon: 'fas fa-satellite-dish',
} : null), } : null),
channel: null, channel: null,
showBanner: true, showBanner: true,
@ -67,7 +65,6 @@ export default defineComponent({
channelId: this.channelId, channelId: this.channelId,
}) })
}, },
faSatelliteDish, faUsers, faPencilAlt, faAngleUp, faAngleDown,
}; };
}, },
@ -111,7 +108,7 @@ export default defineComponent({
background: rgba(0, 0, 0, 0.5); background: rgba(0, 0, 0, 0.5);
border-radius: 100%; border-radius: 100%;
> [data-icon] { > i {
vertical-align: middle; vertical-align: middle;
} }
} }

View file

@ -2,9 +2,9 @@
<div> <div>
<div class="_section" style="padding: 0;" v-if="$i"> <div class="_section" style="padding: 0;" v-if="$i">
<MkTab class="_content" v-model:value="tab"> <MkTab class="_content" v-model:value="tab">
<option value="featured"><Fa :icon="faFireAlt"/> {{ $ts._channel.featured }}</option> <option value="featured"><i class="fas fa-fire-alt"></i> {{ $ts._channel.featured }}</option>
<option value="following"><Fa :icon="faHeart"/> {{ $ts._channel.following }}</option> <option value="following"><i class="fas fa-heart"></i> {{ $ts._channel.following }}</option>
<option value="owned"><Fa :icon="faEdit"/> {{ $ts._channel.owned }}</option> <option value="owned"><i class="fas fa-edit"></i> {{ $ts._channel.owned }}</option>
</MkTab> </MkTab>
</div> </div>
@ -22,7 +22,7 @@
</div> </div>
<div class="_content grwlizim owned" v-if="tab === 'owned'"> <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}"> <MkPagination :pagination="ownedPagination" #default="{items}">
<MkChannelPreview v-for="channel in items" class="_gap" :channel="channel" :key="channel.id"/> <MkChannelPreview v-for="channel in items" class="_gap" :channel="channel" :key="channel.id"/>
</MkPagination> </MkPagination>
@ -33,8 +33,6 @@
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; 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 MkChannelPreview from '@client/components/channel-preview.vue';
import MkPagination from '@client/components/ui/pagination.vue'; import MkPagination from '@client/components/ui/pagination.vue';
import MkButton from '@client/components/ui/button.vue'; import MkButton from '@client/components/ui/button.vue';
@ -49,9 +47,9 @@ export default defineComponent({
return { return {
[symbols.PAGE_INFO]: { [symbols.PAGE_INFO]: {
title: this.$ts.channel, title: this.$ts.channel,
icon: faSatelliteDish, icon: 'fas fa-satellite-dish',
action: { action: {
icon: faPlus, icon: 'fas fa-plus',
handler: this.create handler: this.create
} }
}, },
@ -68,7 +66,6 @@ export default defineComponent({
endpoint: 'channels/owned', endpoint: 'channels/owned',
limit: 5, limit: 5,
}, },
faSatelliteDish, faPlus, faEdit, faHeart, faFireAlt
}; };
}, },
methods: { methods: {

View file

@ -15,7 +15,6 @@
<script lang="ts"> <script lang="ts">
import { computed, defineComponent } from 'vue'; 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 MkContainer from '@client/components/ui/container.vue';
import XPostForm from '@client/components/post-form.vue'; import XPostForm from '@client/components/post-form.vue';
import XNotes from '@client/components/notes.vue'; import XNotes from '@client/components/notes.vue';
@ -40,9 +39,9 @@ export default defineComponent({
return { return {
[symbols.PAGE_INFO]: computed(() => this.clip ? { [symbols.PAGE_INFO]: computed(() => this.clip ? {
title: this.clip.name, title: this.clip.name,
icon: faPaperclip, icon: 'fas fa-paperclip',
action: { action: {
icon: faEllipsisH, icon: 'fas fa-ellipsis-h',
handler: this.menu handler: this.menu
} }
} : null), } : null),
@ -81,7 +80,7 @@ export default defineComponent({
methods: { methods: {
menu(ev) { menu(ev) {
os.modalMenu([this.isOwned ? { os.modalMenu([this.isOwned ? {
icon: faPencilAlt, icon: 'fas fa-pencil-alt',
text: this.$ts.edit, text: this.$ts.edit,
action: async () => { action: async () => {
const { canceled, result } = await os.form(this.clip.name, { const { canceled, result } = await os.form(this.clip.name, {
@ -111,7 +110,7 @@ export default defineComponent({
}); });
} }
} : undefined, this.isOwned ? { } : undefined, this.isOwned ? {
icon: faTrashAlt, icon: 'fas fa-trash-alt',
text: this.$ts.delete, text: this.$ts.delete,
danger: true, danger: true,
action: async () => { action: async () => {

View file

@ -10,7 +10,6 @@
<script lang="ts"> <script lang="ts">
import { computed, defineComponent } from 'vue'; import { computed, defineComponent } from 'vue';
import { faQuestionCircle } from '@fortawesome/free-solid-svg-icons'
import MarkdownIt from 'markdown-it'; import MarkdownIt from 'markdown-it';
import MarkdownItAnchor from 'markdown-it-anchor'; import MarkdownItAnchor from 'markdown-it-anchor';
import { url, lang } from '@client/config'; import { url, lang } from '@client/config';
@ -41,7 +40,7 @@ export default defineComponent({
return { return {
[symbols.PAGE_INFO]: computed(() => this.title ? { [symbols.PAGE_INFO]: computed(() => this.title ? {
title: this.title, title: this.title,
icon: faQuestionCircle, icon: 'fas fa-question-circle',
} : null), } : null),
title: null, title: null,
body: null, body: null,

View file

@ -14,7 +14,6 @@
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { faQuestionCircle } from '@fortawesome/free-solid-svg-icons'
import { url, lang } from '@client/config'; import { url, lang } from '@client/config';
import * as symbols from '@client/symbols'; import * as symbols from '@client/symbols';
@ -23,10 +22,9 @@ export default defineComponent({
return { return {
[symbols.PAGE_INFO]: { [symbols.PAGE_INFO]: {
title: this.$ts.help, title: this.$ts.help,
icon: faQuestionCircle icon: 'fas fa-question-circle'
}, },
docs: [], docs: [],
faQuestionCircle
} }
}, },

View file

@ -6,7 +6,6 @@
<script lang="ts"> <script lang="ts">
import { computed, defineComponent } from 'vue'; import { computed, defineComponent } from 'vue';
import { faCloud } from '@fortawesome/free-solid-svg-icons';
import XDrive from '@client/components/drive.vue'; import XDrive from '@client/components/drive.vue';
import * as os from '@client/os'; import * as os from '@client/os';
import * as symbols from '@client/symbols'; import * as symbols from '@client/symbols';
@ -20,7 +19,7 @@ export default defineComponent({
return { return {
[symbols.PAGE_INFO]: { [symbols.PAGE_INFO]: {
title: computed(() => this.folder ? this.folder.name : this.$ts.drive), title: computed(() => this.folder ? this.folder.name : this.$ts.drive),
icon: faCloud, icon: 'fas fa-cloud',
menu: () => this.$refs.drive.getMenu() menu: () => this.$refs.drive.getMenu()
}, },
folder: null, folder: null,

View file

@ -2,7 +2,7 @@
<div class="lznhrdub _root"> <div class="lznhrdub _root">
<div> <div>
<div class="_isolated"> <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> </div>
<XUserList v-if="query" class="_gap" :pagination="searchPagination" ref="search"/> <XUserList v-if="query" class="_gap" :pagination="searchPagination" ref="search"/>
@ -14,19 +14,19 @@
<template v-if="tag == null"> <template v-if="tag == null">
<MkFolder class="_gap" persist-key="explore-pinned-users"> <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"/> <XUserList :pagination="pinnedUsers"/>
</MkFolder> </MkFolder>
<MkFolder class="_gap" persist-key="explore-popular-users"> <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"/> <XUserList :pagination="popularUsers"/>
</MkFolder> </MkFolder>
<MkFolder class="_gap" persist-key="explore-recently-updated-users"> <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"/> <XUserList :pagination="recentlyUpdatedUsers"/>
</MkFolder> </MkFolder>
<MkFolder class="_gap" persist-key="explore-recently-registered-users"> <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"/> <XUserList :pagination="recentlyRegisteredUsers"/>
</MkFolder> </MkFolder>
</template> </template>
@ -37,7 +37,7 @@
</div> </div>
<MkFolder :foldable="true" :expanded="false" ref="tags" class="_gap"> <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"> <div class="vxjfqztj">
<MkA v-for="tag in tagsLocal" :to="`/explore/tags/${tag.tag}`" :key="'local:' + tag.tag" class="local">{{ tag.tag }}</MkA> <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>
<MkFolder v-if="tag != null" :key="`${tag}`" class="_gap"> <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"/> <XUserList :pagination="tagUsers"/>
</MkFolder> </MkFolder>
<template v-if="tag == null"> <template v-if="tag == null">
<MkFolder class="_gap"> <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"/> <XUserList :pagination="popularUsersF"/>
</MkFolder> </MkFolder>
<MkFolder class="_gap"> <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"/> <XUserList :pagination="recentlyUpdatedUsersF"/>
</MkFolder> </MkFolder>
<MkFolder class="_gap"> <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"/> <XUserList :pagination="recentlyRegisteredUsersF"/>
</MkFolder> </MkFolder>
</template> </template>
@ -70,8 +70,6 @@
<script lang="ts"> <script lang="ts">
import { computed, defineComponent } from 'vue'; 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 XUserList from '@client/components/user-list.vue';
import MkFolder from '@client/components/ui/folder.vue'; import MkFolder from '@client/components/ui/folder.vue';
import MkInput from '@client/components/ui/input.vue'; import MkInput from '@client/components/ui/input.vue';
@ -97,7 +95,7 @@ export default defineComponent({
return { return {
[symbols.PAGE_INFO]: { [symbols.PAGE_INFO]: {
title: this.$ts.explore, title: this.$ts.explore,
icon: faHashtag icon: 'fas fa-hashtag'
}, },
pinnedUsers: { endpoint: 'pinned-users' }, pinnedUsers: { endpoint: 'pinned-users' },
popularUsers: { endpoint: 'users', limit: 10, noPaging: true, params: { popularUsers: { endpoint: 'users', limit: 10, noPaging: true, params: {
@ -139,7 +137,6 @@ export default defineComponent({
stats: null, stats: null,
query: null, query: null,
num: number, num: number,
faBookmark, faChartLine, faCommentAlt, faPlus, faHashtag, faRocket, faSearch,
}; };
}, },

View file

@ -6,7 +6,6 @@
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { faStar } from '@fortawesome/free-solid-svg-icons';
import Progress from '@client/scripts/loading'; import Progress from '@client/scripts/loading';
import XNotes from '@client/components/notes.vue'; import XNotes from '@client/components/notes.vue';
import * as os from '@client/os'; import * as os from '@client/os';
@ -21,7 +20,7 @@ export default defineComponent({
return { return {
[symbols.PAGE_INFO]: { [symbols.PAGE_INFO]: {
title: this.$ts.favorites, title: this.$ts.favorites,
icon: faStar icon: 'fas fa-star'
}, },
pagination: { pagination: {
endpoint: 'i/favorites', endpoint: 'i/favorites',

View file

@ -6,7 +6,6 @@
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { faFireAlt } from '@fortawesome/free-solid-svg-icons';
import Progress from '@client/scripts/loading'; import Progress from '@client/scripts/loading';
import XNotes from '@client/components/notes.vue'; import XNotes from '@client/components/notes.vue';
import * as symbols from '@client/symbols'; import * as symbols from '@client/symbols';
@ -20,14 +19,13 @@ export default defineComponent({
return { return {
[symbols.PAGE_INFO]: { [symbols.PAGE_INFO]: {
title: this.$ts.featured, title: this.$ts.featured,
icon: faFireAlt icon: 'fas fa-fire-alt'
}, },
pagination: { pagination: {
endpoint: 'notes/featured', endpoint: 'notes/featured',
limit: 10, limit: 10,
offsetMode: true offsetMode: true
}, },
faFireAlt
}; };
}, },

View file

@ -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"/> <Mfm :text="req.follower.description" :is-note="false" :author="req.follower" :i="$i" :custom-emojis="req.follower.emojis" :plain="true" :nowrap="true"/>
</div> </div>
<div class="actions"> <div class="actions">
<button class="_button" @click="accept(req.follower)"><Fa :icon="faCheck"/></button> <button class="_button" @click="accept(req.follower)"><i class="fas fa-check"></i></button>
<button class="_button" @click="reject(req.follower)"><Fa :icon="faTimes"/></button> <button class="_button" @click="reject(req.follower)"><i class="fas fa-times"></i></button>
</div> </div>
</div> </div>
</div> </div>
@ -31,7 +31,6 @@
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { faUserClock, faCheck, faTimes } from '@fortawesome/free-solid-svg-icons';
import MkPagination from '@client/components/ui/pagination.vue'; import MkPagination from '@client/components/ui/pagination.vue';
import { userPage, acct } from '../filters/user'; import { userPage, acct } from '../filters/user';
import * as os from '@client/os'; import * as os from '@client/os';
@ -46,13 +45,12 @@ export default defineComponent({
return { return {
[symbols.PAGE_INFO]: { [symbols.PAGE_INFO]: {
title: this.$ts.followRequests, title: this.$ts.followRequests,
icon: faUserClock, icon: 'fas fa-user-clock',
}, },
pagination: { pagination: {
endpoint: 'following/requests/list', endpoint: 'following/requests/list',
limit: 10, limit: 10,
}, },
faCheck, faTimes, faUserClock
}; };
}, },

View file

@ -99,9 +99,12 @@
<span>Raw</span> <span>Raw</span>
</FormObjectView> </FormObjectView>
<FormGroup> <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`" external>host-meta</FormLink>
<FormLink :to="`https://${host}/.well-known/host-meta.json`" external>host-meta.json</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}/.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> </FormGroup>
<FormSuspense :p="dnsPromiseFactory" v-slot="{ result: dns }"> <FormSuspense :p="dnsPromiseFactory" v-slot="{ result: dns }">
<FormGroup> <FormGroup>
@ -130,7 +133,6 @@
<script lang="ts"> <script lang="ts">
import { defineAsyncComponent, defineComponent } from 'vue'; import { defineAsyncComponent, defineComponent } from 'vue';
import { faExternalLinkAlt, faInfoCircle } from '@fortawesome/free-solid-svg-icons';
import Chart from 'chart.js'; import Chart from 'chart.js';
import FormObjectView from '@client/components/form/object-view.vue'; import FormObjectView from '@client/components/form/object-view.vue';
import FormTextarea from '@client/components/form/textarea.vue'; import FormTextarea from '@client/components/form/textarea.vue';
@ -182,10 +184,10 @@ export default defineComponent({
return { return {
[symbols.PAGE_INFO]: { [symbols.PAGE_INFO]: {
title: this.$ts.instanceInfo, title: this.$ts.instanceInfo,
icon: faInfoCircle, icon: 'fas fa-info-circle',
actions: [{ actions: [{
text: `https://${this.host}`, text: `https://${this.host}`,
icon: faExternalLinkAlt, icon: 'fas fa-external-link-alt',
handler: () => { handler: () => {
window.open(`https://${this.host}`, '_blank'); window.open(`https://${this.host}`, '_blank');
} }

View file

@ -1,5 +1,5 @@
<template> <template>
<div class=""> <div class="lcixvhis">
<div class="_section reports"> <div class="_section reports">
<div class="_content"> <div class="_content">
<div class="inputs" style="display: flex;"> <div class="inputs" style="display: flex;">
@ -63,8 +63,6 @@
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; 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 parseAcct from '@/misc/acct/parse';
import MkButton from '@client/components/ui/button.vue'; import MkButton from '@client/components/ui/button.vue';
import MkInput from '@client/components/ui/input.vue'; import MkInput from '@client/components/ui/input.vue';
@ -82,11 +80,13 @@ export default defineComponent({
MkPagination, MkPagination,
}, },
emits: ['info'],
data() { data() {
return { return {
[symbols.PAGE_INFO]: { [symbols.PAGE_INFO]: {
title: this.$ts.abuseReports, title: this.$ts.abuseReports,
icon: faExclamationCircle icon: 'fas fa-exclamation-circle'
}, },
searchUsername: '', searchUsername: '',
searchHost: '', searchHost: '',
@ -102,7 +102,6 @@ export default defineComponent({
targetUserOrigin: this.targetUserOrigin, 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: { methods: {
acct, acct,
@ -135,6 +138,10 @@ export default defineComponent({
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.lcixvhis {
margin: var(--margin);
}
.bcekxzvu { .bcekxzvu {
> .target { > .target {
display: flex; display: flex;

View file

@ -1,35 +1,29 @@
<template> <template>
<div class="ztgjmzrw"> <div class="ztgjmzrw">
<div class="_section"> <MkButton @click="add()" primary style="margin: 0 auto 16px auto;"><i class="fas fa-plus"></i> {{ $ts.add }}</MkButton>
<div class="_content"> <section class="_card _gap announcements" v-for="announcement in announcements">
<MkButton @click="add()" primary style="margin: 0 auto 16px auto;"><Fa :icon="faPlus"/> {{ $ts.add }}</MkButton> <div class="_content announcement">
<section class="_card _gap announcements" v-for="announcement in announcements"> <MkInput v-model:value="announcement.title">
<div class="_content announcement"> <span>{{ $ts.title }}</span>
<MkInput v-model:value="announcement.title"> </MkInput>
<span>{{ $ts.title }}</span> <MkTextarea v-model:value="announcement.text">
</MkInput> <span>{{ $ts.text }}</span>
<MkTextarea v-model:value="announcement.text"> </MkTextarea>
<span>{{ $ts.text }}</span> <MkInput v-model:value="announcement.imageUrl">
</MkTextarea> <span>{{ $ts.imageUrl }}</span>
<MkInput v-model:value="announcement.imageUrl"> </MkInput>
<span>{{ $ts.imageUrl }}</span> <p v-if="announcement.reads">{{ $t('nUsersRead', { n: announcement.reads }) }}</p>
</MkInput> <div class="buttons">
<p v-if="announcement.reads">{{ $t('nUsersRead', { n: announcement.reads }) }}</p> <MkButton class="button" inline @click="save(announcement)" primary><i class="fas fa-save"></i> {{ $ts.save }}</MkButton>
<div class="buttons"> <MkButton class="button" inline @click="remove(announcement)"><i class="fas fa-trash-alt"></i> {{ $ts.remove }}</MkButton>
<MkButton class="button" inline @click="save(announcement)" primary><Fa :icon="faSave"/> {{ $ts.save }}</MkButton> </div>
<MkButton class="button" inline @click="remove(announcement)"><Fa :icon="faTrashAlt"/> {{ $ts.remove }}</MkButton>
</div>
</div>
</section>
</div> </div>
</div> </section>
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; 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 MkButton from '@client/components/ui/button.vue';
import MkInput from '@client/components/ui/input.vue'; import MkInput from '@client/components/ui/input.vue';
import MkTextarea from '@client/components/ui/textarea.vue'; import MkTextarea from '@client/components/ui/textarea.vue';
@ -43,14 +37,15 @@ export default defineComponent({
MkTextarea, MkTextarea,
}, },
emits: ['info'],
data() { data() {
return { return {
[symbols.PAGE_INFO]: { [symbols.PAGE_INFO]: {
title: this.$ts.announcements, title: this.$ts.announcements,
icon: faBroadcastTower icon: 'fas fa-broadcast-tower'
}, },
announcements: [], announcements: [],
faBroadcastTower, faSave, faTrashAlt, faPlus
} }
}, },
@ -60,6 +55,10 @@ export default defineComponent({
}); });
}, },
mounted() {
this.$emit('info', this[symbols.PAGE_INFO]);
},
methods: { methods: {
add() { add() {
this.announcements.unshift({ this.announcements.unshift({
@ -112,3 +111,9 @@ export default defineComponent({
} }
}); });
</script> </script>
<style lang="scss" scoped>
.ztgjmzrw {
margin: var(--margin);
}
</style>

View file

@ -0,0 +1,138 @@
<template>
<FormBase>
<FormSuspense :p="init">
<FormRadios v-model="provider">
<template #desc><i class="fas fa-shield-alt"></i> {{ $ts.botProtection }}</template>
<option :value="null">{{ $ts.none }} ({{ $ts.notRecommended }})</option>
<option value="hcaptcha">hCaptcha</option>
<option value="recaptcha">reCAPTCHA</option>
</FormRadios>
<template v-if="provider === 'hcaptcha'">
<div class="_formItem _formNoConcat" v-sticky-container>
<div class="_formLabel">hCaptcha</div>
<div class="main">
<FormInput v-model:value="hcaptchaSiteKey">
<template #prefix><i class="fas fa-key"></i></template>
<span>{{ $ts.hcaptchaSiteKey }}</span>
</FormInput>
<FormInput v-model:value="hcaptchaSecretKey">
<template #prefix><i class="fas fa-key"></i></template>
<span>{{ $ts.hcaptchaSecretKey }}</span>
</FormInput>
</div>
</div>
<div class="_formItem _formNoConcat" v-sticky-container>
<div class="_formLabel">{{ $ts.preview }}</div>
<div class="_formPanel" style="padding: var(--formContentHMargin);">
<MkCaptcha provider="hcaptcha" :sitekey="hcaptchaSiteKey || '10000000-ffff-ffff-ffff-000000000001'"/>
</div>
</div>
</template>
<template v-else-if="provider === 'recaptcha'">
<div class="_formItem _formNoConcat" v-sticky-container>
<div class="_formLabel">reCAPTCHA</div>
<div class="main">
<FormInput v-model:value="recaptchaSiteKey">
<template #prefix><i class="fas fa-key"></i></template>
<span>{{ $ts.recaptchaSiteKey }}</span>
</FormInput>
<FormInput v-model:value="recaptchaSecretKey">
<template #prefix><i class="fas fa-key"></i></template>
<span>{{ $ts.recaptchaSecretKey }}</span>
</FormInput>
</div>
</div>
<div v-if="recaptchaSiteKey" class="_formItem _formNoConcat" v-sticky-container>
<div class="_formLabel">{{ $ts.preview }}</div>
<div class="_formPanel" style="padding: var(--formContentHMargin);">
<MkCaptcha provider="recaptcha" :sitekey="recaptchaSiteKey"/>
</div>
</div>
</template>
<FormButton @click="save" primary><i class="fas fa-save"></i> {{ $ts.save }}</FormButton>
</FormSuspense>
</FormBase>
</template>
<script lang="ts">
import { defineAsyncComponent, defineComponent } from 'vue';
import FormRadios from '@client/components/form/radios.vue';
import FormInput from '@client/components/form/input.vue';
import FormButton from '@client/components/form/button.vue';
import FormBase from '@client/components/form/base.vue';
import FormGroup from '@client/components/form/group.vue';
import FormInfo from '@client/components/form/info.vue';
import FormSuspense from '@client/components/form/suspense.vue';
import * as os from '@client/os';
import * as symbols from '@client/symbols';
import { fetchInstance } from '@client/instance';
export default defineComponent({
components: {
FormRadios,
FormInput,
FormBase,
FormGroup,
FormButton,
FormInfo,
FormSuspense,
MkCaptcha: defineAsyncComponent(() => import('@client/components/captcha.vue')),
},
emits: ['info'],
data() {
return {
[symbols.PAGE_INFO]: {
title: this.$ts.botProtection,
icon: 'fas fa-shield-alt'
},
provider: null,
enableHcaptcha: false,
hcaptchaSiteKey: null,
hcaptchaSecretKey: null,
enableRecaptcha: false,
recaptchaSiteKey: null,
recaptchaSecretKey: null,
}
},
async mounted() {
this.$emit('info', this[symbols.PAGE_INFO]);
},
methods: {
async init() {
const meta = await os.api('meta', { detail: true });
this.enableHcaptcha = meta.enableHcaptcha;
this.hcaptchaSiteKey = meta.hcaptchaSiteKey;
this.hcaptchaSecretKey = meta.hcaptchaSecretKey;
this.enableRecaptcha = meta.enableRecaptcha;
this.recaptchaSiteKey = meta.recaptchaSiteKey;
this.recaptchaSecretKey = meta.recaptchaSecretKey;
this.provider = this.enableHcaptcha ? 'hcaptcha' : this.enableRecaptcha ? 'recaptcha' : null;
this.$watch(() => this.provider, () => {
this.enableHcaptcha = this.provider === 'hcaptcha';
this.enableRecaptcha = this.provider === 'recaptcha';
});
},
save() {
os.apiWithDialog('admin/update-meta', {
enableHcaptcha: this.enableHcaptcha,
hcaptchaSiteKey: this.hcaptchaSiteKey,
hcaptchaSecretKey: this.hcaptchaSecretKey,
enableRecaptcha: this.enableRecaptcha,
recaptchaSiteKey: this.recaptchaSiteKey,
recaptchaSecretKey: this.recaptchaSecretKey,
}).then(() => {
fetchInstance();
});
}
}
});
</script>

View file

@ -0,0 +1,60 @@
<template>
<FormBase>
<FormSuspense :p="databasePromiseFactory" v-slot="{ result: database }">
<FormGroup v-for="table in database" :key="table[0]">
<template #label>{{ table[0] }}</template>
<FormKeyValueView>
<template #key>Size</template>
<template #value>{{ bytes(table[1].size) }}</template>
</FormKeyValueView>
<FormKeyValueView>
<template #key>Records</template>
<template #value>{{ number(table[1].count) }}</template>
</FormKeyValueView>
</FormGroup>
</FormSuspense>
</FormBase>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import FormSuspense from '@client/components/form/suspense.vue';
import FormKeyValueView from '@client/components/form/key-value-view.vue';
import FormLink from '@client/components/form/link.vue';
import FormBase from '@client/components/form/base.vue';
import FormGroup from '@client/components/form/group.vue';
import * as os from '@client/os';
import * as symbols from '@client/symbols';
import bytes from '@client/filters/bytes';
import number from '@client/filters/number';
export default defineComponent({
components: {
FormSuspense,
FormKeyValueView,
FormBase,
FormGroup,
FormLink,
},
emits: ['info'],
data() {
return {
[symbols.PAGE_INFO]: {
title: this.$ts.database,
icon: 'fas fa-database'
},
databasePromiseFactory: () => os.api('admin/get-table-stats', {}).then(res => Object.entries(res).sort((a, b) => b[1].size - a[1].size)),
}
},
mounted() {
this.$emit('info', this[symbols.PAGE_INFO]);
},
methods: {
bytes, number,
}
});
</script>

View file

@ -0,0 +1,127 @@
<template>
<FormBase>
<FormSuspense :p="init">
<FormSwitch v-model:value="enableEmail">{{ $ts.enableEmail }}<template #desc>{{ $ts.emailConfigInfo }}</template></FormSwitch>
<template v-if="enableEmail">
<FormInput v-model:value="email" type="email">
<span>{{ $ts.emailAddress }}</span>
</FormInput>
<div class="_formItem _formNoConcat" v-sticky-container>
<div class="_formLabel">{{ $ts.smtpConfig }}</div>
<div class="main">
<FormInput v-model:value="smtpHost">
<span>{{ $ts.smtpHost }}</span>
</FormInput>
<FormInput v-model:value="smtpPort" type="number">
<span>{{ $ts.smtpPort }}</span>
</FormInput>
<FormInput v-model:value="smtpUser">
<span>{{ $ts.smtpUser }}</span>
</FormInput>
<FormInput v-model:value="smtpPass" type="password">
<span>{{ $ts.smtpPass }}</span>
</FormInput>
<FormInfo>{{ $ts.emptyToDisableSmtpAuth }}</FormInfo>
<FormSwitch v-model:value="smtpSecure">{{ $ts.smtpSecure }}<template #desc>{{ $ts.smtpSecureInfo }}</template></FormSwitch>
</div>
</div>
<FormButton @click="testEmail">{{ $ts.testEmail }}</FormButton>
</template>
<FormButton @click="save" primary><i class="fas fa-save"></i> {{ $ts.save }}</FormButton>
</FormSuspense>
</FormBase>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import FormSwitch from '@client/components/form/switch.vue';
import FormInput from '@client/components/form/input.vue';
import FormButton from '@client/components/form/button.vue';
import FormBase from '@client/components/form/base.vue';
import FormGroup from '@client/components/form/group.vue';
import FormInfo from '@client/components/form/info.vue';
import FormSuspense from '@client/components/form/suspense.vue';
import * as os from '@client/os';
import * as symbols from '@client/symbols';
import { fetchInstance } from '@client/instance';
export default defineComponent({
components: {
FormSwitch,
FormInput,
FormBase,
FormGroup,
FormButton,
FormInfo,
FormSuspense,
},
emits: ['info'],
data() {
return {
[symbols.PAGE_INFO]: {
title: this.$ts.emailServer,
icon: 'fas fa-envelope'
},
enableEmail: false,
email: null,
smtpSecure: false,
smtpHost: '',
smtpPort: 0,
smtpUser: '',
smtpPass: '',
}
},
async mounted() {
this.$emit('info', this[symbols.PAGE_INFO]);
},
methods: {
async init() {
const meta = await os.api('meta', { detail: true });
this.enableEmail = meta.enableEmail;
this.email = meta.email;
this.smtpSecure = meta.smtpSecure;
this.smtpHost = meta.smtpHost;
this.smtpPort = meta.smtpPort;
this.smtpUser = meta.smtpUser;
this.smtpPass = meta.smtpPass;
},
async testEmail() {
const { canceled, result: destination } = await os.dialog({
title: this.$ts.destination,
input: {
placeholder: this.$instance.maintainerEmail
}
});
if (canceled) return;
os.apiWithDialog('admin/send-email', {
to: destination,
subject: 'Test email',
text: 'Yo'
});
},
save() {
os.apiWithDialog('admin/update-meta', {
enableEmail: this.enableEmail,
email: this.email,
smtpSecure: this.smtpSecure,
smtpHost: this.smtpHost,
smtpPort: this.smtpPort,
smtpUser: this.smtpUser,
smtpPass: this.smtpPass,
}).then(() => {
fetchInstance();
});
}
}
});
</script>

View file

@ -8,22 +8,23 @@
> >
<template #header>:{{ emoji.name }}:</template> <template #header>:{{ emoji.name }}:</template>
<div class="yigymqpb _section"> <div class="_monolithic_">
<img :src="emoji.url" class="img"/> <div class="yigymqpb _section">
<MkInput v-model:value="name"><span>{{ $ts.name }}</span></MkInput> <img :src="emoji.url" class="img"/>
<MkInput v-model:value="category" :datalist="categories"><span>{{ $ts.category }}</span></MkInput> <MkInput v-model:value="name"><span>{{ $ts.name }}</span></MkInput>
<MkInput v-model:value="aliases"> <MkInput v-model:value="category" :datalist="categories"><span>{{ $ts.category }}</span></MkInput>
<span>{{ $ts.tags }}</span> <MkInput v-model:value="aliases">
<template #desc>{{ $ts.setMultipleBySeparatingWithSpace }}</template> <span>{{ $ts.tags }}</span>
</MkInput> <template #desc>{{ $ts.setMultipleBySeparatingWithSpace }}</template>
<MkButton danger @click="del()"><Fa :icon="faTrashAlt"/> {{ $ts.delete }}</MkButton> </MkInput>
<MkButton danger @click="del()"><i class="fas fa-trash-alt"></i> {{ $ts.delete }}</MkButton>
</div>
</div> </div>
</XModalWindow> </XModalWindow>
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { faTrashAlt } from '@fortawesome/free-regular-svg-icons';
import XModalWindow from '@client/components/ui/modal-window.vue'; import XModalWindow from '@client/components/ui/modal-window.vue';
import MkButton from '@client/components/ui/button.vue'; import MkButton from '@client/components/ui/button.vue';
import MkInput from '@client/components/ui/input.vue'; import MkInput from '@client/components/ui/input.vue';
@ -51,7 +52,6 @@ export default defineComponent({
category: this.emoji.category, category: this.emoji.category,
aliases: this.emoji.aliases?.join(' '), aliases: this.emoji.aliases?.join(' '),
categories: [], categories: [],
faTrashAlt,
} }
}, },

View file

@ -1,58 +1,52 @@
<template> <template>
<div class="mk-instance-emojis"> <div class="ogwlenmc">
<div class="_section" style="padding: 0;"> <MkTab v-model:value="tab">
<MkTab v-model:value="tab"> <option value="local">{{ $ts.local }}</option>
<option value="local">{{ $ts.local }}</option> <option value="remote">{{ $ts.remote }}</option>
<option value="remote">{{ $ts.remote }}</option> </MkTab>
</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>
<div class="_section"> <div class="remote" v-else-if="tab === 'remote'">
<div class="local" v-if="tab === 'local'"> <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>
<MkButton primary @click="add" style="margin: 0 auto var(--margin) auto;"><Fa :icon="faPlus"/> {{ $ts.addEmoji }}</MkButton> <MkInput v-model:value="host" :debounce="true" style="margin: var(--margin);"><span>{{ $ts.host }}</span></MkInput>
<MkInput v-model:value="query" :debounce="true" type="search"><template #icon><Fa :icon="faSearch"/></template><span>{{ $ts.search }}</span></MkInput> <MkPagination :pagination="remotePagination" ref="remoteEmojis">
<MkPagination :pagination="pagination" ref="emojis"> <template #empty><span>{{ $ts.noCustomEmojis }}</span></template>
<template #empty><span>{{ $ts.noCustomEmojis }}</span></template> <template #default="{items}">
<template #default="{items}"> <div class="ldhfsamy">
<div class="emojis"> <div class="emoji _panel _button" v-for="emoji in items" :key="emoji.id" @click="remoteMenu(emoji, $event)">
<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"/>
<img :src="emoji.url" class="img" :alt="emoji.name"/> <div class="body">
<div class="body"> <div class="name _monospace">{{ emoji.name }}</div>
<div class="name">{{ emoji.name }}</div> <div class="info">{{ emoji.host }}</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> </div>
</div> </div>
</template> </div>
</MkPagination> </template>
</div> </MkPagination>
</div> </div>
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { computed, defineComponent } from 'vue'; 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 MkButton from '@client/components/ui/button.vue';
import MkInput from '@client/components/ui/input.vue'; import MkInput from '@client/components/ui/input.vue';
import MkPagination from '@client/components/ui/pagination.vue'; import MkPagination from '@client/components/ui/pagination.vue';
@ -69,13 +63,15 @@ export default defineComponent({
MkPagination, MkPagination,
}, },
emits: ['info'],
data() { data() {
return { return {
[symbols.PAGE_INFO]: { [symbols.PAGE_INFO]: {
title: this.$ts.customEmojis, title: this.$ts.customEmojis,
icon: faLaugh, icon: 'fas fa-laugh',
action: { action: {
icon: faPlus, icon: 'fas fa-plus',
handler: this.add handler: this.add
} }
}, },
@ -98,10 +94,13 @@ export default defineComponent({
host: (this.host && this.host !== '') ? this.host : null host: (this.host && this.host !== '') ? this.host : null
})) }))
}, },
faTrashAlt, faPlus, faLaugh, faSave, faSearch,
} }
}, },
async mounted() {
this.$emit('info', this[symbols.PAGE_INFO]);
},
methods: { methods: {
async add(e) { async add(e) {
const files = await selectFile(e.currentTarget || e.target, null, true); const files = await selectFile(e.currentTarget || e.target, null, true);
@ -144,7 +143,7 @@ export default defineComponent({
text: ':' + emoji.name + ':', text: ':' + emoji.name + ':',
}, { }, {
text: this.$ts.import, text: this.$ts.import,
icon: faPlus, icon: 'fas fa-plus',
action: () => { this.im(emoji) } action: () => { this.im(emoji) }
}], ev.currentTarget || ev.target); }], ev.currentTarget || ev.target);
} }
@ -153,85 +152,86 @@ export default defineComponent({
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.mk-instance-emojis { .ogwlenmc {
> ._section { > .local {
> .local { .ldhfsamy {
.emojis { display: grid;
display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); grid-gap: 12px;
grid-gap: var(--margin); margin: var(--margin);
> .emoji { > .emoji {
display: flex; display: flex;
align-items: center; align-items: center;
padding: 12px; padding: 12px;
text-align: left; text-align: left;
&:hover { &:hover {
color: var(--accent); color: var(--accent);
} }
> .img { > .img {
width: 42px; width: 42px;
height: 42px; height: 42px;
} }
> .body { > .body {
padding: 0 0 0 8px; padding: 0 0 0 8px;
white-space: nowrap; white-space: nowrap;
overflow: hidden;
> .name {
text-overflow: ellipsis;
overflow: hidden; overflow: hidden;
}
> .name { > .info {
text-overflow: ellipsis; opacity: 0.5;
overflow: hidden; text-overflow: ellipsis;
} overflow: hidden;
> .info {
opacity: 0.5;
text-overflow: ellipsis;
overflow: hidden;
}
} }
} }
} }
} }
}
> .remote { > .remote {
.emojis { .ldhfsamy {
display: grid; display: grid;
grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
grid-gap: var(--margin); grid-gap: 12px;
margin: var(--margin);
> .emoji { > .emoji {
display: flex; display: flex;
align-items: center; align-items: center;
padding: 12px; padding: 12px;
text-align: left; text-align: left;
&:hover { &:hover {
color: var(--accent); color: var(--accent);
} }
> .img { > .img {
width: 32px; width: 32px;
height: 32px; height: 32px;
} }
> .body { > .body {
padding: 0 0 0 8px; padding: 0 0 0 8px;
white-space: nowrap; white-space: nowrap;
overflow: hidden;
> .name {
text-overflow: ellipsis;
overflow: hidden; overflow: hidden;
}
> .name { > .info {
text-overflow: ellipsis; opacity: 0.5;
overflow: hidden; font-size: 90%;
} text-overflow: ellipsis;
overflow: hidden;
> .info {
opacity: 0.5;
text-overflow: ellipsis;
overflow: hidden;
}
} }
} }
} }

Some files were not shown because too many files have changed in this diff Show more