Compare commits

..

70 Commits

Author SHA1 Message Date
9dd21a19ff 10.44.1 2018-11-07 19:49:46 +09:00
a8d05cba5a Fix #3149 2018-11-07 19:43:21 +09:00
f5ddfb29f2 10.44.0 2018-11-07 13:16:29 +09:00
ba228a6b10 Clean up 2018-11-07 13:15:09 +09:00
cb6f390fb6 GitHub / Twitter連携の設定をDBに保存するように 2018-11-07 13:14:52 +09:00
5675ecead9 Fix 2018-11-07 12:30:56 +09:00
001bb7bbcd インスタンスの対象言語の設定を実装 2018-11-07 12:28:53 +09:00
1585bb12cf 🎨 2018-11-07 12:17:57 +09:00
26b47c18fd [Client] Fix #2737 2018-11-07 12:15:28 +09:00
665fa7f2aa [API] Improve drive/files/upload_from_url 2018-11-07 12:12:43 +09:00
0068dc30d3 Merge branch 'develop' of https://github.com/syuilo/misskey into develop 2018-11-07 12:09:33 +09:00
8f39655fef Fix bug 2018-11-07 12:09:24 +09:00
b1a4fc03bc Update @types/koa-router requirement from 7.0.32 to 7.0.33 (#3147)
Updates the requirements on [@types/koa-router](https://github.com/DefinitelyTyped/DefinitelyTyped) to permit the latest version.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2018-11-07 09:24:13 +09:00
05d20f1044 Update @types/request requirement from 2.48.0 to 2.48.1 (#3146)
Updates the requirements on [@types/request](https://github.com/DefinitelyTyped/DefinitelyTyped) to permit the latest version.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2018-11-07 09:24:04 +09:00
66a90b3fb1 Update qrcode requirement from 1.3.0 to 1.3.2 (#3145)
Updates the requirements on [qrcode](https://github.com/soldair/node-qrcode) to permit the latest version.
- [Release notes](https://github.com/soldair/node-qrcode/releases)
- [Commits](https://github.com/soldair/node-qrcode/commits)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2018-11-07 09:23:47 +09:00
826d9d9fdf Update typescript requirement from 3.1.5 to 3.1.6 (#3144)
Updates the requirements on [typescript](https://github.com/Microsoft/TypeScript) to permit the latest version.
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Commits](https://github.com/Microsoft/TypeScript/commits/v3.1.6)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2018-11-07 09:23:38 +09:00
4a9a61f108 10.43.1 2018-11-07 03:57:08 +09:00
b72d15b56c [Client] Improve usability 2018-11-07 03:48:58 +09:00
8c68992594 Fix deploy fails on CircleCI 2018-11-07 02:06:32 +09:00
c052028fc3 10.43.0 2018-11-07 01:19:03 +09:00
c46fbcf345 Clean up 2018-11-07 01:18:21 +09:00
06b66f0209 メンテナ情報をDBに保存するように 2018-11-07 01:12:26 +09:00
2de48110bb ghostの設定をDBに保存するように 2018-11-07 00:44:56 +09:00
87d4452d19 Clean up 2018-11-07 00:16:32 +09:00
328fc64ca9 🎨 2018-11-07 00:16:08 +09:00
a6f8327aa2 reCAPTCHAの設定をDBに保存するように 2018-11-07 00:08:21 +09:00
d5ab6b41c9 10.42.2 2018-11-06 20:54:15 +09:00
ffdd0b7de7 [API] 文字列での真理値表現に対応
multipart/formdata では文字列しか送れないっぽい?
2018-11-06 20:53:50 +09:00
1808eb6eee 10.42.1 2018-11-06 20:49:03 +09:00
438563b505 [API] Fix bug 2018-11-06 20:47:56 +09:00
92dfcdad57 Fix #3141 2018-11-06 20:47:07 +09:00
c178cfabfa 10.42.0 2018-11-06 15:52:28 +09:00
260e4c955d 🎨 2018-11-06 15:51:18 +09:00
0c46f5ce70 Clean up 2018-11-06 15:51:05 +09:00
6d67cd07a0 [Client] Use dynamic import to reduce bundle size 2018-11-06 15:37:41 +09:00
fb8af53751 [Client] Improve usability & Refactoring 2018-11-06 15:08:22 +09:00
37999f4af7 [API] Implement notes/watching/ 2018-11-06 14:58:20 +09:00
3b6ab327c1 Twemojiで合字に対応 (#3140)
* Twemojiで合字に対応

* split emoji regex
2018-11-06 14:09:40 +09:00
d3ff3a7d54 10.41.0 2018-11-06 08:06:08 +09:00
cf36106520 🎨 2018-11-06 08:04:34 +09:00
1642fbec31 [Client] カスタム絵文字サジェストの結果をアルファベット順にソートするように 2018-11-06 08:02:19 +09:00
b195fd8145 🎨 2018-11-06 07:57:16 +09:00
5f59b980a7 Fix: download file (#3138)
* Fix: url download

* not explicitly close on end

* resolve on stream finish

* remove unnecessary code

* reject on file error
2018-11-06 07:53:03 +09:00
2a5c19cd01 リモートのファイルをキャッシュするかどうかの設定をDBに保存するように 2018-11-06 07:52:13 +09:00
42e007ddb7 🎨 2018-11-06 07:28:49 +09:00
756dc397d9 🎨 2018-11-06 07:22:39 +09:00
8f714b5b12 ドライブ容量の設定をDBに保存するようにしたりリファクタリングしたり 2018-11-06 07:14:43 +09:00
06bb2a1c7c Clean up 2018-11-06 06:25:35 +09:00
ac50bb9225 Resolve #3137 2018-11-06 06:24:31 +09:00
8fd95de25b 整理 2018-11-06 06:12:51 +09:00
0e14b2eba4 Update file-type requirement from 10.3.0 to 10.4.0 (#3135)
Updates the requirements on [file-type](https://github.com/sindresorhus/file-type) to permit the latest version.
- [Release notes](https://github.com/sindresorhus/file-type/releases)
- [Commits](https://github.com/sindresorhus/file-type/commits/v10.4.0)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2018-11-06 06:08:41 +09:00
08413a7550 Update webpack requirement from 4.23.1 to 4.25.1 (#3136)
Updates the requirements on [webpack](https://github.com/webpack/webpack) to permit the latest version.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/commits/v4.25.1)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2018-11-06 05:35:53 +09:00
5e0f2a5b06 [Client] Fix bug 2018-11-06 04:10:30 +09:00
3b505709c6 10.40.1 2018-11-06 04:02:04 +09:00
af32d1f81e [Client] Fix bug 2018-11-06 04:01:22 +09:00
67d8773e38 [Client] Fix bug 2018-11-06 03:59:58 +09:00
e445d39c2f [Client] Use v-if instaed of v-show 2018-11-06 03:59:02 +09:00
961ed969db メッセージでのカスタム絵文字対応 2018-11-06 03:57:02 +09:00
e9a3495225 Resolve #3132 2018-11-06 03:48:23 +09:00
6c5a78aeb2 Fix #3133 (#3134) 2018-11-06 03:31:16 +09:00
34e249317a 10.40.0 2018-11-06 02:06:15 +09:00
6d8ea89f09 Resolve #3126 2018-11-06 02:05:16 +09:00
64f89ba13e Better error code 2018-11-06 01:57:31 +09:00
f6b2f76bbf 10.39.1 2018-11-06 01:52:39 +09:00
1235bef038 [API] Fix bug 2018-11-06 01:51:42 +09:00
2e11f3a843 Clean up 2018-11-06 01:49:35 +09:00
84b7e0bb7d 🎨 2018-11-06 01:48:33 +09:00
9f5dc2c0df [WIP] Use FontAwesome Component for Vue (#3127)
* wip

* Rename

* Clean up

* Clean up

* wip

* wip

* Enable tree shaking

* ✌️

* ✌️

* wip

* wip

* Clean up
2018-11-06 01:40:11 +09:00
e640dbc501 🎨 2018-11-05 22:45:45 +09:00
85db090d9f 🎨 2018-11-05 22:42:08 +09:00
247 changed files with 2304 additions and 1719 deletions

View File

@ -43,8 +43,8 @@ jobs:
- run:
name: Configure
command: |
cp .ci/default.yml .config
cp .ci/test.yml .config
cp .circleci/misskey/default.yml .config
cp .circleci/misskey/test.yml .config
- run:
name: Build
command: |
@ -102,7 +102,7 @@ jobs:
- run:
name: Build
command: |
docker build . | tee docker.log
docker build -t misskey/misskey .
- when:
condition: <<parameters.with_deploy>>
steps:
@ -111,8 +111,6 @@ jobs:
command: |
if [ "$DOCKERHUB_USERNAME$DOCKERHUB_PASSWORD" ]
then
tail -n 1 docker.log | read __Successfully __built tag
docker tag $tag misskey/misskey
docker login -u $DOCKERHUB_USERNAME -p $DOCKERHUB_PASSWORD
docker push misskey/misskey
else

View File

@ -1,6 +1,3 @@
maintainer:
name: syuilo
url: 'https://syuilo.com'
url: 'http://misskey.local'
port: 80
mongodb:

View File

@ -1,6 +1,3 @@
maintainer:
name: syuilo
url: 'https://syuilo.com'
url: 'http://misskey.local'
port: 80
mongodb:

View File

@ -1,10 +1,3 @@
maintainer:
name: example-maitainer-name # Your name
url: http://example.com/ # Your contact (http or mailto)
repository_url: https://github.com/syuilo/misskey # Repository URL
feedback_url: https://github.com/syuilo/misskey/issues # Feedback URL (e.g. github issue)
# Final accessible URL seen by a user.
url: https://example.tld/
@ -57,21 +50,6 @@ mongodb:
user: example-misskey-user
pass: example-misskey-pass
# Drive capacity of a local user (MB)
localDriveCapacityMb: 256
# Drive capacity of a remote user (MB)
remoteDriveCapacityMb: 8
# If enabled:
# Server will not cache remote files (Using direct link instead).
# You can save your storage.
#
# NOTE:
# * Users cannot see remote images when they turn off "Show media from a remote server" setting.
# * Since thumbnails are not provided, traffic increases.
preventCacheRemoteFiles: false
drive:
storage: 'db'
@ -110,6 +88,10 @@ drive:
# accessKey: XXX
# secretKey: YYY
# If enabled:
# The first account created is automatically marked as Admin.
autoAdmin: true
#
# Below settings are optional
#
@ -126,11 +108,6 @@ drive:
# port: 9200
# pass: null
# reCAPTCHA
#recaptcha:
# site_key: example-site-key
# secret_key: example-secret-key
# ServiceWorker
#sw:
# # Public key of VAPID
@ -139,23 +116,6 @@ drive:
# # Private key of VAPID
# private_key: example-sw-private-key
# Twitter integration
# You need to set the oauth callback url as : https://<your-misskey-instance>/api/tw/cb
#twitter:
# consumer_key: example-twitter-consumer-key
# consumer_secret: example-twitter-consumer-secret-key
# GitHub integration
# You need to set the oauth callback url as : https://<your-misskey-instance>/api/gh/cb
#github:
# client_id: example-github-client-id
# client_secret: example-github-client-secret
# Ghost
# Ghost account is an account used for the purpose of delegating
# followers when putting users in the list.
#ghost: user-id-of-your-ghost-account
# Clustering
#clusterLimit: 1

View File

@ -47,11 +47,6 @@ In root :
4. `git checkout $(git tag -l | grep -v 'rc[0-9]*$' | sort -V | tail -n 1)` Checkout to the [latest release](https://github.com/syuilo/misskey/releases/latest)
5. `npm install` Install misskey dependencies.
*(optional)* reCAPTCHA tokens
----------------------------------------------------------------
If you want to enable reCAPTCHA, you need to generate reCAPTCHA tokens:
Please visit https://www.google.com/recaptcha/intro/ and generate keys.
*(optional)* Generating VAPID keys
----------------------------------------------------------------
If you want to enable ServiceWorker, you need to generate VAPID keys:
@ -62,13 +57,6 @@ npm install web-push -g
web-push generate-vapid-keys
```
*(optional)* Create a twitter application
----------------------------------------------------------------
If you want to enable the twitter integration, you need to create a twitter app at [https://developer.twitter.com/en/apply/user](https://developer.twitter.com/en/apply/user).
In the app you need to set the oauth callback url as : https://misskey-instance/api/tw/cb
*5.* Make configuration file
----------------------------------------------------------------
1. `cp .config/example.yml .config/default.yml` Copy the `.config/example.yml` and rename it to `default.yml`.

View File

@ -53,11 +53,6 @@ adduser --disabled-password --disabled-login misskey
4. `git checkout $(git tag -l | grep -v 'rc[0-9]*$' | sort -V | tail -n 1)` [最新のリリース](https://github.com/syuilo/misskey/releases/latest)を確認
5. `npm install` Misskeyの依存パッケージをインストール
*(オプション)* reCAPTCHAトークン
----------------------------------------------------------------
reCAPTCHAを有効にする場合、reCAPTCHAトークンを取得する必要があります。
https://www.google.com/recaptcha/intro/ にアクセスしてトークンを取得してください。
*(オプション)* VAPIDキーペアの生成
----------------------------------------------------------------
ServiceWorkerを有効にする場合、VAPIDキーペアを生成する必要があります:

View File

@ -21,7 +21,6 @@ import * as htmlmin from 'gulp-htmlmin';
const uglifyes = require('uglify-es');
const locales = require('./locales');
import { fa } from './src/misc/fa';
const uglify = uglifyComposer(uglifyes, console);
@ -164,8 +163,7 @@ gulp.task('build:client:pug', [
gulp.src('./src/client/app/base.pug')
.pipe(pug({
locals: {
themeColor: constants.themeColor,
facss: fa.dom.css()
themeColor: constants.themeColor
}
}))
.pipe(htmlmin({

View File

@ -947,6 +947,7 @@ common/views/components/api-settings.vue:
title: 'APIコンソール'
endpoint: 'エンドポイント'
parameter: 'パラメータ'
credential-info: "「i」パラメータは自動で付与されます。"
send: '送信'
sending: '応答待ち'
response: '結果'
@ -1078,6 +1079,37 @@ admin/views/instance.vue:
instance-name: "インスタンス名"
instance-description: "インスタンスの紹介"
banner-url: "バナー画像URL"
languages: "インスタンスの対象言語"
languages-desc: "スペースで区切って複数設定できます。"
maintainer-config: "管理者情報"
maintainer-name: "管理者名"
maintainer-email: "管理者の連絡先"
drive-config: "ドライブの設定"
cache-remote-files: "リモートのファイルをキャッシュする"
cache-remote-files-desc: "この設定を無効にすると、リモートファイルをキャッシュせず直リンクするようになります。そのためサーバーのストレージを節約できますが、プライバシー設定で直リンクを無効にしているユーザーにはファイルが見えなくなったり、サムネイルが生成されないので通信量が増加します。通常はこの設定をオンにしておくことをおすすめします。"
local-drive-capacity-mb: "ローカルユーザーひとりあたりのドライブ容量"
remote-drive-capacity-mb: "リモートユーザーひとりあたりのドライブ容量"
mb: "メガバイト単位"
recaptcha-config: "reCAPTCHAの設定"
recaptcha-info: "reCAPTCHAを有効にする場合、reCAPTCHAトークンを取得する必要があります。https://www.google.com/recaptcha/intro/ にアクセスしてトークンを取得してください。"
enable-recaptcha: "reCAPTCHAを有効にする"
recaptcha-site-key: "reCAPTCHA site key"
recaptcha-secret-key: "reCAPTCHA secret key"
twitter-integration-config: "Twitter連携の設定"
twitter-integration-info: "コールバックURLは /api/tw/cb に設定します。"
enable-twitter-integration: "Twitter連携を有効にする"
twitter-integration-consumer-key: "Consumer key"
twitter-integration-consumer-secret: "Consumer secret"
github-integration-config: "GitHub連携の設定"
github-integration-info: "コールバックURLは /api/gh/cb に設定します。"
enable-github-integration: "GitHub連携を有効にする"
github-integration-client-id: "Client ID"
github-integration-client-secret: "Client secret"
proxy-account-config: "プロキシアカウントの設定"
proxy-account-info: "プロキシアカウントは、特定の条件下でユーザーのリモートフォローを代行するアカウントです。例えば、ユーザーがリモートユーザーをリストに入れたとき、リストに入れられたユーザーを誰もフォローしていないとアクティビティがサーバーに配達されないため、代わりにプロキシアカウントがフォローするようにします。"
proxy-account-username: "プロキシアカウントのユーザー名"
proxy-account-username-desc: "プロキシとして使用するアカウントのユーザー名を指定してください。"
proxy-account-warn: "アカウントは自動で作られないため、そのユーザー名のアカウントを予め作成しておく必要があります。"
max-note-text-length: "投稿の最大文字数"
disable-registration: "ユーザー登録の受付を停止する"
disable-local-timeline: "ローカルタイムラインを無効にする"

View File

@ -1,8 +1,8 @@
{
"name": "misskey",
"author": "syuilo <i@syuilo.com>",
"version": "10.39.0",
"clientVersion": "1.0.11562",
"version": "10.44.1",
"clientVersion": "1.0.11630",
"codename": "nighthike",
"main": "./built/index.js",
"private": true,
@ -20,10 +20,11 @@
"format": "gulp format"
},
"dependencies": {
"@fortawesome/fontawesome-svg-core": "1.2.6",
"@fortawesome/free-brands-svg-icons": "5.4.1",
"@fortawesome/free-regular-svg-icons": "5.4.1",
"@fortawesome/free-solid-svg-icons": "5.4.1",
"@fortawesome/fontawesome-svg-core": "1.2.8",
"@fortawesome/free-brands-svg-icons": "5.5.0",
"@fortawesome/free-regular-svg-icons": "5.5.0",
"@fortawesome/free-solid-svg-icons": "5.5.0",
"@fortawesome/vue-fontawesome": "0.1.2",
"@koa/cors": "2.2.2",
"@prezzemolo/rap": "0.1.2",
"@prezzemolo/zip": "0.0.3",
@ -52,7 +53,7 @@
"@types/koa-logger": "3.1.1",
"@types/koa-mount": "3.0.1",
"@types/koa-multer": "1.0.0",
"@types/koa-router": "7.0.32",
"@types/koa-router": "7.0.33",
"@types/koa-send": "4.1.1",
"@types/koa-views": "2.0.3",
"@types/koa__cors": "2.2.3",
@ -68,7 +69,7 @@
"@types/qrcode": "1.3.0",
"@types/ratelimiter": "2.1.28",
"@types/redis": "2.8.7",
"@types/request": "2.48.0",
"@types/request": "2.48.1",
"@types/request-promise-native": "1.0.15",
"@types/rimraf": "2.0.2",
"@types/seedrandom": "2.4.27",
@ -112,7 +113,7 @@
"eslint-plugin-vue": "4.7.1",
"eventemitter3": "3.1.0",
"file-loader": "2.0.0",
"file-type": "10.3.0",
"file-type": "10.4.0",
"fuckadblock": "3.2.1",
"gulp": "3.9.1",
"gulp-cssnano": "2.1.3",
@ -173,7 +174,7 @@
"promise-sequential": "1.1.1",
"pug": "2.0.3",
"punycode": "2.1.1",
"qrcode": "1.3.0",
"qrcode": "1.3.2",
"ratelimiter": "3.2.0",
"recaptcha-promise": "0.1.3",
"reconnecting-websocket": "4.1.10",
@ -204,7 +205,7 @@
"ts-loader": "5.3.0",
"ts-node": "7.0.1",
"tslint": "5.10.0",
"typescript": "3.1.5",
"typescript": "3.1.6",
"typescript-eslint-parser": "20.1.1",
"uglify-es": "3.3.9",
"url-loader": "1.1.2",
@ -215,7 +216,6 @@
"vue-content-loading": "1.5.3",
"vue-cropperjs": "2.2.2",
"vue-js-modal": "1.3.26",
"vue-json-tree-view": "2.1.4",
"vue-loader": "15.4.2",
"vue-router": "3.0.1",
"vue-style-loader": "4.1.2",
@ -228,7 +228,7 @@
"vuex-persistedstate": "2.5.4",
"web-push": "3.3.3",
"webfinger.js": "2.6.6",
"webpack": "4.23.1",
"webpack": "4.25.1",
"webpack-cli": "3.1.2",
"websocket": "1.0.28",
"ws": "6.1.0",

View File

@ -1,7 +1,7 @@
<template>
<div class="cdeuzmsthagexbkpofbmatmugjuvogfb">
<ui-card>
<div slot="title">%fa:broadcast-tower% %i18n:@announcements%</div>
<div slot="title"><fa icon="broadcast-tower"/> %i18n:@announcements%</div>
<section v-for="(announcement, i) in announcements" class="fit-top">
<ui-input v-model="announcement.title" @change="save">
<span>%i18n:@title%</span>
@ -10,12 +10,12 @@
<span>%i18n:@text%</span>
</ui-textarea>
<ui-horizon-group>
<ui-button @click="save()">%fa:save R% %i18n:@save%</ui-button>
<ui-button @click="remove(i)">%fa:trash-alt R% %i18n:@remove%</ui-button>
<ui-button @click="save()"><fa :icon="['far', 'save']"/> %i18n:@save%</ui-button>
<ui-button @click="remove(i)"><fa :icon="['far', 'trash-alt']"/> %i18n:@remove%</ui-button>
</ui-horizon-group>
</section>
<section>
<ui-button @click="add">%fa:plus% %i18n:@add%</ui-button>
<ui-button @click="add"><fa icon="plus"/> %i18n:@add%</ui-button>
</section>
</ui-card>
</div>

View File

@ -3,10 +3,10 @@
<table>
<thead>
<tr>
<th>%fa:exchange-alt% In/Out</th>
<th>%fa:server% Host</th>
<th>%fa:bolt% Activity</th>
<th>%fa:user% Actor</th>
<th><fa icon="exchange-alt"/> In/Out</th>
<th><fa icon="server"/> Host</th>
<th><fa icon="bolt"/> Activity</th>
<th><fa icon="user"/> Actor</th>
</tr>
</thead>
<tbody>

View File

@ -1,7 +1,7 @@
<template>
<div class="qvgidhudpqhjttdhxubzuyrhyzgslujw">
<header>
<b>%fa:chart-bar R% %i18n:@title%:</b>
<b><fa :icon="['far', 'chart-bar']"/> %i18n:@title%:</b>
<select v-model="src">
<optgroup label="%i18n:@federation%">
<option value="federation-instances">%i18n:@charts.federation-instances%</option>
@ -274,12 +274,15 @@ export default Vue.extend({
return {
series: [{
name: 'Combined',
type: 'line',
data: this.format(sum(this.stats.notes.local.total, this.stats.notes.remote.total))
}, {
name: 'Local',
type: 'area',
data: this.format(this.stats.notes.local.total)
}, {
name: 'Remote',
type: 'area',
data: this.format(this.stats.notes.remote.total)
}]
};
@ -289,18 +292,21 @@ export default Vue.extend({
return {
series: [{
name: 'Combined',
type: 'line',
data: this.format(total
? sum(this.stats.users.local.total, this.stats.users.remote.total)
: sum(this.stats.users.local.inc, negate(this.stats.users.local.dec), this.stats.users.remote.inc, negate(this.stats.users.remote.dec))
)
}, {
name: 'Local',
type: 'area',
data: this.format(total
? this.stats.users.local.total
: sum(this.stats.users.local.inc, negate(this.stats.users.local.dec))
)
}, {
name: 'Remote',
type: 'area',
data: this.format(total
? this.stats.users.remote.total
: sum(this.stats.users.remote.inc, negate(this.stats.users.remote.dec))
@ -314,6 +320,7 @@ export default Vue.extend({
bytes: true,
series: [{
name: 'All',
type: 'line',
data: this.format(
sum(
this.stats.drive.local.incSize,
@ -324,15 +331,19 @@ export default Vue.extend({
)
}, {
name: 'Local +',
type: 'area',
data: this.format(this.stats.drive.local.incSize)
}, {
name: 'Local -',
type: 'area',
data: this.format(negate(this.stats.drive.local.decSize))
}, {
name: 'Remote +',
type: 'area',
data: this.format(this.stats.drive.remote.incSize)
}, {
name: 'Remote -',
type: 'area',
data: this.format(negate(this.stats.drive.remote.decSize))
}]
};
@ -343,12 +354,15 @@ export default Vue.extend({
bytes: true,
series: [{
name: 'Combined',
type: 'line',
data: this.format(sum(this.stats.drive.local.totalSize, this.stats.drive.remote.totalSize))
}, {
name: 'Local',
type: 'area',
data: this.format(this.stats.drive.local.totalSize)
}, {
name: 'Remote',
type: 'area',
data: this.format(this.stats.drive.remote.totalSize)
}]
};
@ -358,6 +372,7 @@ export default Vue.extend({
return {
series: [{
name: 'All',
type: 'line',
data: this.format(
sum(
this.stats.drive.local.incCount,
@ -368,15 +383,19 @@ export default Vue.extend({
)
}, {
name: 'Local +',
type: 'area',
data: this.format(this.stats.drive.local.incCount)
}, {
name: 'Local -',
type: 'area',
data: this.format(negate(this.stats.drive.local.decCount))
}, {
name: 'Remote +',
type: 'area',
data: this.format(this.stats.drive.remote.incCount)
}, {
name: 'Remote -',
type: 'area',
data: this.format(negate(this.stats.drive.remote.decCount))
}]
};
@ -386,12 +405,15 @@ export default Vue.extend({
return {
series: [{
name: 'Combined',
type: 'line',
data: this.format(sum(this.stats.drive.local.totalCount, this.stats.drive.remote.totalCount))
}, {
name: 'Local',
type: 'area',
data: this.format(this.stats.drive.local.totalCount)
}, {
name: 'Remote',
type: 'area',
data: this.format(this.stats.drive.remote.totalCount)
}]
};

View File

@ -2,14 +2,14 @@
<div class="zyknedwtlthezamcjlolyusmipqmjgxz">
<div>
<header>
<span>%fa:microchip% CPU <span>{{ cpuP }}%</span></span>
<span><fa icon="microchip"/> CPU <span>{{ cpuP }}%</span></span>
<span v-if="meta">{{ meta.cpu.model }}</span>
</header>
<div ref="cpu"></div>
</div>
<div>
<header>
<span>%fa:memory% MEM <span>{{ memP }}%</span></span>
<span><fa icon="memory"/> MEM <span>{{ memP }}%</span></span>
<span v-if="meta"></span>
</header>
<div ref="mem"></div>

View File

@ -11,54 +11,54 @@
<div v-if="stats" class="stats">
<div>
<div>
<div>%fa:user%</div>
<div><fa icon="user"/></div>
<div>
<span>%i18n:@accounts%</span>
<b class="primary">{{ stats.originalUsersCount | number }}</b>
</div>
</div>
<div>
<span>%fa:home% %i18n:@this-instance%</span>
<span @click="setChartSrc('users')">%fa:chart-bar R%</span>
<span><fa icon="home"/> %i18n:@this-instance%</span>
<span @click="setChartSrc('users')"><fa :icon="['far', 'chart-bar']"/></span>
</div>
</div>
<div>
<div>
<div>%fa:pencil-alt%</div>
<div><fa icon="pencil-alt"/></div>
<div>
<span>%i18n:@notes%</span>
<b class="primary">{{ stats.originalNotesCount | number }}</b>
</div>
</div>
<div>
<span>%fa:home% %i18n:@this-instance%</span>
<span @click="setChartSrc('notes')">%fa:chart-bar R%</span>
<span><fa icon="home"/> %i18n:@this-instance%</span>
<span @click="setChartSrc('notes')"><fa :icon="['far', 'chart-bar']"/></span>
</div>
</div>
<div>
<div>
<div>%fa:database%</div>
<div><fa icon="database"/></div>
<div>
<span>%i18n:@drive%</span>
<b>{{ stats.driveUsageLocal | bytes }}</b>
</div>
</div>
<div>
<span>%fa:home% %i18n:@this-instance%</span>
<span @click="setChartSrc('drive')">%fa:chart-bar R%</span>
<span><fa icon="home"/> %i18n:@this-instance%</span>
<span @click="setChartSrc('drive')"><fa :icon="['far', 'chart-bar']"/></span>
</div>
</div>
<div>
<div>
<div>%fa:hdd R%</div>
<div><fa :icon="['far', 'hdd']"/></div>
<div>
<span>%i18n:@instances%</span>
<b>{{ stats.instances | number }}</b>
</div>
</div>
<div>
<span>%fa:globe% %i18n:@federated%</span>
<span @click="setChartSrc('federation-instances-total')">%fa:chart-bar R%</span>
<span><fa icon="globe"/> %i18n:@federated%</span>
<span @click="setChartSrc('federation-instances-total')"><fa :icon="['far', 'chart-bar']"/></span>
</div>
</div>
</div>

View File

@ -1,19 +1,20 @@
<template>
<div class="tumhkfkmgtvzljezfvmgkeurkfncshbe">
<ui-card>
<div slot="title">%fa:plus% %i18n:@add-emoji.title%</div>
<div slot="title"><fa icon="plus"/> %i18n:@add-emoji.title%</div>
<section class="fit-top">
<ui-horizon-group inputs>
<ui-input v-model="name">
<span>%i18n:@add-emoji.name%</span>
<span slot="text">%i18n:@add-emoji.name-desc%</span>
<span slot="desc">%i18n:@add-emoji.name-desc%</span>
</ui-input>
<ui-input v-model="aliases">
<span>%i18n:@add-emoji.aliases%</span>
<span slot="text">%i18n:@add-emoji.aliases-desc%</span>
<span slot="desc">%i18n:@add-emoji.aliases-desc%</span>
</ui-input>
</ui-horizon-group>
<ui-input v-model="url">
<i slot="icon"><fa icon="link"/></i>
<span>%i18n:@add-emoji.url%</span>
</ui-input>
<ui-info>%i18n:@add-emoji.info%</ui-info>
@ -22,7 +23,7 @@
</ui-card>
<ui-card>
<div slot="title">%fa:grin R% %i18n:@emojis.title%</div>
<div slot="title"><fa :icon="['far', 'grin']"/> %i18n:@emojis.title%</div>
<section v-for="emoji in emojis">
<img :src="emoji.url" :alt="emoji.name" style="width: 64px;"/>
<ui-horizon-group inputs>
@ -34,11 +35,12 @@
</ui-input>
</ui-horizon-group>
<ui-input v-model="emoji.url">
<i slot="icon"><fa icon="link"/></i>
<span>%i18n:@add-emoji.url%</span>
</ui-input>
<ui-horizon-group>
<ui-button @click="updateEmoji(emoji)">%fa:save R% %i18n:@emojis.update%</ui-button>
<ui-button @click="removeEmoji(emoji)">%fa:trash-alt R% %i18n:@emojis.remove%</ui-button>
<ui-button @click="updateEmoji(emoji)"><fa :icon="['far', 'save']"/> %i18n:@emojis.update%</ui-button>
<ui-button @click="removeEmoji(emoji)"><fa :icon="['far', 'trash-alt']"/> %i18n:@emojis.remove%</ui-button>
</ui-horizon-group>
</section>
</ui-card>

View File

@ -1,7 +1,7 @@
<template>
<div class="mk-admin" :class="{ isMobile }">
<header v-show="isMobile">
<button class="nav" @click="navOpend = true">%fa:bars%</button>
<button class="nav" @click="navOpend = true"><fa icon="bars"/></button>
<span>MisskeyMyAdmin</span>
</header>
<div class="nav-backdrop"
@ -18,30 +18,30 @@
<p class="name">{{ $store.state.i | userName }}</p>
</div>
<ul>
<li @click="nav('dashboard')" :class="{ active: page == 'dashboard' }">%fa:home .fw%%i18n:@dashboard%</li>
<li @click="nav('instance')" :class="{ active: page == 'instance' }">%fa:cog .fw%%i18n:@instance%</li>
<li @click="nav('users')" :class="{ active: page == 'users' }">%fa:users .fw%%i18n:@users%</li>
<li @click="nav('emoji')" :class="{ active: page == 'emoji' }">%fa:grin R .fw%%i18n:@emoji%</li>
<li @click="nav('announcements')" :class="{ active: page == 'announcements' }">%fa:broadcast-tower .fw%%i18n:@announcements%</li>
<li @click="nav('hashtags')" :class="{ active: page == 'hashtags' }">%fa:hashtag .fw%%i18n:@hashtags%</li>
<li @click="nav('dashboard')" :class="{ active: page == 'dashboard' }"><fa icon="home" fixed-width/>%i18n:@dashboard%</li>
<li @click="nav('instance')" :class="{ active: page == 'instance' }"><fa icon="cog" fixed-width/>%i18n:@instance%</li>
<li @click="nav('users')" :class="{ active: page == 'users' }"><fa icon="users" fixed-width/>%i18n:@users%</li>
<li @click="nav('emoji')" :class="{ active: page == 'emoji' }"><fa :icon="['far', 'grin']" fixed-width/>%i18n:@emoji%</li>
<li @click="nav('announcements')" :class="{ active: page == 'announcements' }"><fa icon="broadcast-tower" fixed-width/>%i18n:@announcements%</li>
<li @click="nav('hashtags')" :class="{ active: page == 'hashtags' }"><fa icon="hashtag" fixed-width/>%i18n:@hashtags%</li>
<!-- <li @click="nav('drive')" :class="{ active: page == 'drive' }">%fa:cloud .fw%%i18n:common.drive%</li> -->
<!-- <li @click="nav('drive')" :class="{ active: page == 'drive' }"><fa icon="cloud" fixed-width/>%i18n:common.drive%</li> -->
<!-- <li @click="nav('update')" :class="{ active: page == 'update' }">%i18n:@update%</li> -->
</ul>
<div class="back-to-misskey">
<a href="/">%fa:arrow-left% %i18n:@back-to-misskey%</a>
<a href="/"><fa icon="arrow-left"/> %i18n:@back-to-misskey%</a>
</div>
<div class="version">
<small>Misskey {{ version }}</small>
</div>
</nav>
<main>
<div v-show="page == 'dashboard'"><x-dashboard/></div>
<div v-show="page == 'instance'"><x-instance/></div>
<div v-if="page == 'dashboard'"><x-dashboard/></div>
<div v-if="page == 'instance'"><x-instance/></div>
<div v-if="page == 'users'"><x-users/></div>
<div v-show="page == 'emoji'"><x-emoji/></div>
<div v-show="page == 'announcements'"><x-announcements/></div>
<div v-show="page == 'hashtags'"><x-hashtags/></div>
<div v-if="page == 'emoji'"><x-emoji/></div>
<div v-if="page == 'announcements'"><x-announcements/></div>
<div v-if="page == 'hashtags'"><x-hashtags/></div>
<div v-if="page == 'drive'"></div>
<div v-if="page == 'update'"></div>
</main>
@ -126,7 +126,7 @@ export default Vue.extend({
line-height $headerHeight
border-right solid 1px rgba(#000, 0.1)
> [data-fa]
> [data-icon]
transition all 0.2s ease
> nav
@ -188,7 +188,7 @@ export default Vue.extend({
&:hover
color #fff
> [data-fa]
> [data-icon]
margin-right 6px
> .version
@ -218,7 +218,7 @@ export default Vue.extend({
&:hover
color #fff
> [data-fa]
> [data-icon]
margin-right 6px
&.active

View File

@ -1,29 +1,78 @@
<template>
<div class="axbwjelsbymowqjyywpirzhdlszoncqs">
<ui-card>
<div slot="title">%fa:cog% %i18n:@instance%</div>
<section class="fit-top">
<div slot="title"><fa icon="cog"/> %i18n:@instance%</div>
<section class="fit-top fit-bottom">
<ui-input v-model="name">%i18n:@instance-name%</ui-input>
<ui-textarea v-model="description">%i18n:@instance-description%</ui-textarea>
<ui-input v-model="bannerUrl">%i18n:@banner-url%</ui-input>
<ui-input v-model="bannerUrl"><i slot="icon"><fa icon="link"/></i>%i18n:@banner-url%</ui-input>
<ui-input v-model="languages"><i slot="icon"><fa icon="language"/></i>%i18n:@languages%<span slot="desc">%i18n:@languages-desc%</span></ui-input>
</section>
<section class="fit-bottom">
<header><fa icon="headset"/> %i18n:@maintainer-config%</header>
<ui-input v-model="maintainerName">%i18n:@maintainer-name%</ui-input>
<ui-input v-model="maintainerEmail" type="email"><i slot="icon"><fa :icon="['far', 'envelope']"/></i>%i18n:@maintainer-email%</ui-input>
</section>
<section class="fit-top fit-bottom">
<ui-input v-model="maxNoteTextLength">%i18n:@max-note-text-length%</ui-input>
</section>
<section class="fit-bottom">
<header><fa icon="cloud"/> %i18n:@drive-config%</header>
<ui-switch v-model="cacheRemoteFiles">%i18n:@cache-remote-files%<span slot="desc">%i18n:@cache-remote-files-desc%</span></ui-switch>
<ui-input v-model="localDriveCapacityMb">%i18n:@local-drive-capacity-mb%<span slot="suffix">MB</span><span slot="desc">%i18n:@mb%</span></ui-input>
<ui-input v-model="remoteDriveCapacityMb" :disabled="!cacheRemoteFiles">%i18n:@remote-drive-capacity-mb%<span slot="suffix">MB</span><span slot="desc">%i18n:@mb%</span></ui-input>
</section>
<section class="fit-bottom">
<header><fa icon="shield-alt"/> %i18n:@recaptcha-config%</header>
<ui-switch v-model="enableRecaptcha">%i18n:@enable-recaptcha%</ui-switch>
<ui-info>%i18n:@recaptcha-info%</ui-info>
<ui-input v-model="recaptchaSiteKey" :disabled="!enableRecaptcha"><i slot="icon"><fa icon="key"/></i>%i18n:@recaptcha-site-key%</ui-input>
<ui-input v-model="recaptchaSecretKey" :disabled="!enableRecaptcha"><i slot="icon"><fa icon="key"/></i>%i18n:@recaptcha-secret-key%</ui-input>
</section>
<section>
<header><fa icon="ghost"/> %i18n:@proxy-account-config%</header>
<ui-info>%i18n:@proxy-account-info%</ui-info>
<ui-input v-model="proxyAccount"><span slot="prefix">@</span>%i18n:@proxy-account-username%<span slot="desc">%i18n:@proxy-account-username-desc%</span></ui-input>
<ui-info warn>%i18n:@proxy-account-warn%</ui-info>
</section>
<section>
<ui-switch v-model="disableRegistration">%i18n:@disable-registration%</ui-switch>
</section>
<section>
<ui-switch v-model="disableLocalTimeline">%i18n:@disable-local-timeline%</ui-switch>
</section>
<section>
<ui-button @click="updateMeta">%i18n:@save%</ui-button>
</section>
</ui-card>
<ui-card>
<div slot="title">%i18n:@disable-registration%</div>
<div slot="title">%i18n:@invite%</div>
<section>
<input type="checkbox" v-model="disableRegistration" @change="updateMeta">
<button class="ui" @click="invite">%i18n:@invite%</button>
<ui-button @click="invite">%i18n:@invite%</ui-button>
<p v-if="inviteCode">Code: <code>{{ inviteCode }}</code></p>
</section>
</ui-card>
<ui-card>
<div slot="title">%i18n:@disable-local-timeline%</div>
<div slot="title"><fa :icon="['fab', 'twitter']"/> %i18n:@twitter-integration-config%</div>
<section>
<input type="checkbox" v-model="disableLocalTimeline" @change="updateMeta">
<ui-switch v-model="enableTwitterIntegration">%i18n:@enable-twitter-integration%</ui-switch>
<ui-info>%i18n:@twitter-integration-info%</ui-info>
<ui-input v-model="twitterConsumerKey" :disabled="!enableTwitterIntegration"><i slot="icon"><fa icon="key"/></i>%i18n:@twitter-integration-consumer-key%</ui-input>
<ui-input v-model="twitterConsumerSecret" :disabled="!enableTwitterIntegration"><i slot="icon"><fa icon="key"/></i>%i18n:@twitter-integration-consumer-secret%</ui-input>
<ui-button @click="updateMeta">%i18n:@save%</ui-button>
</section>
</ui-card>
<ui-card>
<div slot="title"><fa :icon="['fab', 'github']"/> %i18n:@github-integration-config%</div>
<section>
<ui-switch v-model="enableGithubIntegration">%i18n:@enable-github-integration%</ui-switch>
<ui-info>%i18n:@github-integration-info%</ui-info>
<ui-input v-model="githubClientId" :disabled="!enableGithubIntegration"><i slot="icon"><fa icon="key"/></i>%i18n:@github-integration-client-id%</ui-input>
<ui-input v-model="githubClientSecret" :disabled="!enableGithubIntegration"><i slot="icon"><fa icon="key"/></i>%i18n:@github-integration-client-secret%</ui-input>
<ui-button @click="updateMeta">%i18n:@save%</ui-button>
</section>
</ui-card>
</div>
@ -35,22 +84,54 @@ import Vue from "vue";
export default Vue.extend({
data() {
return {
maintainerName: null,
maintainerEmail: null,
disableRegistration: false,
disableLocalTimeline: false,
bannerUrl: null,
name: null,
description: null,
languages: null,
cacheRemoteFiles: false,
localDriveCapacityMb: null,
remoteDriveCapacityMb: null,
maxNoteTextLength: null,
enableRecaptcha: false,
recaptchaSiteKey: null,
recaptchaSecretKey: null,
enableTwitterIntegration: false,
twitterConsumerKey: null,
twitterConsumerSecret: null,
enableGithubIntegration: false,
githubClientId: null,
githubClientSecret: null,
proxyAccount: null,
inviteCode: null,
};
},
created() {
(this as any).os.getMeta().then(meta => {
this.maintainerName = meta.maintainer.name;
this.maintainerEmail = meta.maintainer.email;
this.bannerUrl = meta.bannerUrl;
this.name = meta.name;
this.description = meta.description;
this.languages = meta.langs.join(' ');
this.cacheRemoteFiles = meta.cacheRemoteFiles;
this.localDriveCapacityMb = meta.driveCapacityPerLocalUserMb;
this.remoteDriveCapacityMb = meta.driveCapacityPerRemoteUserMb;
this.maxNoteTextLength = meta.maxNoteTextLength;
this.enableRecaptcha = meta.enableRecaptcha;
this.recaptchaSiteKey = meta.recaptchaSiteKey;
this.recaptchaSecretKey = meta.recaptchaSecretKey;
this.proxyAccount = meta.proxyAccount;
this.enableTwitterIntegration = meta.enableTwitterIntegration;
this.twitterConsumerKey = meta.twitterConsumerKey;
this.twitterConsumerSecret = meta.twitterConsumerSecret;
this.enableGithubIntegration = meta.enableGithubIntegration;
this.githubClientId = meta.githubClientId;
this.githubClientSecret = meta.githubClientSecret;
});
},
@ -68,12 +149,28 @@ export default Vue.extend({
updateMeta() {
(this as any).api('admin/update-meta', {
maintainerName: this.maintainerName,
maintainerEmail: this.maintainerEmail,
disableRegistration: this.disableRegistration,
disableLocalTimeline: this.disableLocalTimeline,
bannerUrl: this.bannerUrl,
name: this.name,
description: this.description,
maxNoteTextLength: parseInt(this.maxNoteTextLength, 10)
langs: this.languages.split(' '),
cacheRemoteFiles: this.cacheRemoteFiles,
localDriveCapacityMb: parseInt(this.localDriveCapacityMb, 10),
remoteDriveCapacityMb: parseInt(this.remoteDriveCapacityMb, 10),
maxNoteTextLength: parseInt(this.maxNoteTextLength, 10),
enableRecaptcha: this.enableRecaptcha,
recaptchaSiteKey: this.recaptchaSiteKey,
recaptchaSecretKey: this.recaptchaSecretKey,
proxyAccount: this.proxyAccount,
enableTwitterIntegration: this.enableTwitterIntegration,
twitterConsumerKey: this.twitterConsumerKey,
twitterConsumerSecret: this.twitterConsumerSecret,
enableGithubIntegration: this.enableGithubIntegration,
githubClientId: this.githubClientId,
githubClientSecret: this.githubClientSecret,
}).then(() => {
this.$swal({
type: 'success',

View File

@ -128,7 +128,7 @@ pre
overflow auto
tab-size 2
[data-fa]
[data-icon]
display inline-block
.swal2-container

View File

@ -1,6 +1,6 @@
<template>
<ui-card>
<div slot="title">%fa:key% API</div>
<div slot="title"><fa icon="key"/> API</div>
<section class="fit-top">
<ui-input :value="$store.state.i.token" readonly>
@ -9,20 +9,21 @@
<p>%i18n:@intro%</p>
<ui-info warn>%i18n:@caution%</ui-info>
<p>%i18n:@regeneration-of-token%</p>
<ui-button @click="regenerateToken">%fa:sync-alt% %i18n:@regenerate-token%</ui-button>
<ui-button @click="regenerateToken"><fa icon="sync-alt"/> %i18n:@regenerate-token%</ui-button>
</section>
<section>
<header>%fa:terminal% %i18n:@console.title%</header>
<header><fa icon="terminal"/> %i18n:@console.title%</header>
<ui-input v-model="endpoint">
<span>%i18n:@console.endpoint%</span>
</ui-input>
<ui-textarea v-model="body">
<span>%i18n:@console.parameter% (JSON or JSON5)</span>
<span slot="desc">%i18n:@console.credential-info%</span>
</ui-textarea>
<ui-button @click="send" :disabled="sending">
<template v-if="sending">%i18n:@console.sending%</template>
<template v-else>%fa:paper-plane% %i18n:@console.send%</template>
<template v-else><fa icon="paper-plane"/> %i18n:@console.send%</template>
</ui-button>
<ui-textarea v-if="res" v-model="res" readonly tall>
<span>%i18n:@console.response%</span>

View File

@ -41,11 +41,17 @@ const lib = Object.entries(emojilib.lib).filter((x: any) => {
return x[1].category != 'flags';
});
const char2file = (char: string) => {
let codes = [...char].map(x => x.codePointAt(0).toString(16));
if (!codes.includes('200d')) codes = codes.filter(x => x != 'fe0f');
return codes.join('-');
};
const emjdb: EmojiDef[] = lib.map((x: any) => ({
emoji: x[1].char,
name: x[0],
aliasOf: null,
url: `https://twemoji.maxcdn.com/2/svg/${x[1].char.codePointAt(0).toString(16)}.svg`
url: `https://twemoji.maxcdn.com/2/svg/${char2file(x[1].char)}.svg`
}));
lib.forEach((x: any) => {
@ -55,7 +61,7 @@ lib.forEach((x: any) => {
emoji: x[1].char,
name: k,
aliasOf: x[0],
url: `https://twemoji.maxcdn.com/2/svg/${x[1].char.codePointAt(0).toString(16)}.svg`
url: `https://twemoji.maxcdn.com/2/svg/${char2file(x[1].char)}.svg`
});
});
}
@ -215,6 +221,15 @@ export default Vue.extend({
}
}
} else if (this.type == 'emoji') {
if (this.q == null || this.q == '') {
this.emojis = this.emojiDb.filter(x => x.isCustomEmoji && !x.aliasOf).sort((a, b) => {
var textA = a.name.toUpperCase();
var textB = b.name.toUpperCase();
return (textA < textB) ? -1 : (textA > textB) ? 1 : 0;
});
return;
}
const matched = [];
const max = 30;

View File

@ -1,35 +1,35 @@
<template>
<div class="troubleshooter">
<div class="body">
<h1>%fa:wrench%%i18n:@title%</h1>
<h1><fa icon="wrench"/>%i18n:@title%</h1>
<div>
<p :data-wip="network == null">
<template v-if="network != null">
<template v-if="network">%fa:check%</template>
<template v-if="!network">%fa:times%</template>
<template v-if="network"><fa icon="check"/></template>
<template v-if="!network"><fa icon="times"/></template>
</template>
{{ network == null ? '%i18n:@checking-network%' : '%i18n:@network%' }}<mk-ellipsis v-if="network == null"/>
</p>
<p v-if="network == true" :data-wip="internet == null">
<template v-if="internet != null">
<template v-if="internet">%fa:check%</template>
<template v-if="!internet">%fa:times%</template>
<template v-if="internet"><fa icon="check"/></template>
<template v-if="!internet"><fa icon="times"/></template>
</template>
{{ internet == null ? '%i18n:@checking-internet%' : '%i18n:@internet%' }}<mk-ellipsis v-if="internet == null"/>
</p>
<p v-if="internet == true" :data-wip="server == null">
<template v-if="server != null">
<template v-if="server">%fa:check%</template>
<template v-if="!server">%fa:times%</template>
<template v-if="server"><fa icon="check"/></template>
<template v-if="!server"><fa icon="times"/></template>
</template>
{{ server == null ? '%i18n:@checking-server%' : '%i18n:@server%' }}<mk-ellipsis v-if="server == null"/>
</p>
</div>
<p v-if="!end">%i18n:@finding%<mk-ellipsis/></p>
<p v-if="network === false"><b>%fa:exclamation-triangle%%i18n:@no-network%</b><br>%i18n:@no-network-desc%</p>
<p v-if="internet === false"><b>%fa:exclamation-triangle%%i18n:@no-internet%</b><br>%i18n:@no-internet-desc%</p>
<p v-if="server === false"><b>%fa:exclamation-triangle%%i18n:@no-server%</b><br>%i18n:@no-server-desc%</p>
<p v-if="server === true" class="success"><b>%fa:info-circle%%i18n:@success%</b><br>%i18n:@success-desc%</p>
<p v-if="network === false"><b><fa icon="exclamation-triangle"/>%i18n:@no-network%</b><br>%i18n:@no-network-desc%</p>
<p v-if="internet === false"><b><fa icon="exclamation-triangle"/>%i18n:@no-internet%</b><br>%i18n:@no-internet-desc%</p>
<p v-if="server === false"><b><fa icon="exclamation-triangle"/>%i18n:@no-server%</b><br>%i18n:@no-server-desc%</p>
<p v-if="server === true" class="success"><b><fa icon="info-circle"/>%i18n:@success%</b><br>%i18n:@success-desc%</p>
</div>
<footer>
<a href="/assets/flush.html">%i18n:@flush%</a> | <a href="/assets/version.html">%i18n:@set-version%</a>
@ -100,7 +100,7 @@ export default Vue.extend({
color #444
border-bottom solid 1px #eee
> [data-fa]
> [data-icon]
margin-right 0.25em
> div
@ -115,7 +115,7 @@ export default Vue.extend({
&[data-wip]
color #888
> [data-fa]
> [data-icon]
margin-right 0.25em
&.times
@ -132,7 +132,7 @@ export default Vue.extend({
border-top solid 1px #eee
> b
> [data-fa]
> [data-icon]
margin-right 0.25em
&.success

View File

@ -1,6 +1,6 @@
<template>
<div class="mk-connect-failed">
<img src="data:image/jpeg;base64,%base64:/assets/error.jpg%" alt=""/>
<img src="https://raw.githubusercontent.com/syuilo/misskey/develop/src/client/assets/error.jpg" alt=""/>
<h1>%i18n:@title%</h1>
<p class="text">
<span>{{ '%i18n:@description%'.substr(0, '%i18n:@description%'.indexOf('{')) }}</span>

View File

@ -1,6 +1,6 @@
<template>
<ui-card>
<div slot="title">%fa:cloud% %i18n:common.drive%</div>
<div slot="title"><fa icon="cloud"/> %i18n:common.drive%</div>
<section v-if="!fetching" class="juakhbxthdewydyreaphkepoxgxvfogn">
<div class="meter"><div :style="meterStyle"></div></div>

View File

@ -60,7 +60,10 @@ export default Vue.extend({
}
if (this.char) {
this.url = `https://twemoji.maxcdn.com/2/svg/${this.char.codePointAt(0).toString(16)}.svg`;
let codes = [...this.char].map(x => x.codePointAt(0).toString(16));
if (!codes.includes('200d')) codes = codes.filter(x => x != 'fe0f');
this.url = `https://twemoji.maxcdn.com/2/svg/${codes.join('-')}.svg`;
}
}
});
@ -68,7 +71,8 @@ export default Vue.extend({
<style lang="stylus" scoped>
.fvgwvorwhxigeolkkrcderjzcawqrscl
height 1em
height 1.25em
vertical-align -0.25em
&.custom
height 2.5em

View File

@ -1,6 +1,6 @@
<template>
<div class="wjqjnyhzogztorhrdgcpqlkxhkmuetgj">
<p>%fa:exclamation-triangle% %i18n:common.error.title%</p>
<p><fa icon="exclamation-triangle"/> %i18n:common.error.title%</p>
<ui-button @click="() => $emit('retry')">%i18n:common.error.retry%</ui-button>
</div>
</template>

View File

@ -1,6 +1,6 @@
<template>
<span class="mk-file-type-icon">
<template v-if="kind == 'image'">%fa:file-image%</template>
<template v-if="kind == 'image'"><fa icon="file-image"/></template>
</span>
</template>

View File

@ -1,6 +1,6 @@
<template>
<div class="xqnhankfuuilcwvhgsopeqncafzsquya">
<button class="go-index" v-if="selfNav" @click="goIndex">%fa:arrow-left%</button>
<button class="go-index" v-if="selfNav" @click="goIndex"><fa icon="arrow-left"/></button>
<header><b><router-link :to="blackUser | userPage">{{ blackUser | userName }}</router-link></b>(%i18n:common.reversi.black%) vs <b><router-link :to="whiteUser | userPage">{{ whiteUser | userName }}</router-link></b>(%i18n:common.reversi.white%)</header>
<div style="overflow: hidden; line-height: 28px;">
@ -51,13 +51,13 @@
<div class="player" v-if="game.isEnded">
<div>
<button @click="logPos = 0" :disabled="logPos == 0">%fa:angle-double-left%</button>
<button @click="logPos--" :disabled="logPos == 0">%fa:angle-left%</button>
<button @click="logPos = 0" :disabled="logPos == 0"><fa icon="angle-double-left"/></button>
<button @click="logPos--" :disabled="logPos == 0"><fa icon="angle-left"/></button>
</div>
<span>{{ logPos }} / {{ logs.length }}</span>
<div>
<button @click="logPos++" :disabled="logPos == logs.length">%fa:angle-right%</button>
<button @click="logPos = logs.length" :disabled="logPos == logs.length">%fa:angle-double-right%</button>
<button @click="logPos++" :disabled="logPos == logs.length"><fa icon="angle-right"/></button>
<button @click="logPos = logs.length" :disabled="logPos == logs.length"><fa icon="angle-double-right"/></button>
</div>
</div>

View File

@ -17,13 +17,13 @@
</header>
<div>
<div class="random" v-if="game.settings.map == null">%fa:dice%</div>
<div class="random" v-if="game.settings.map == null"><fa icon="dice"/></div>
<div class="board" v-else :style="{ 'grid-template-rows': `repeat(${ game.settings.map.length }, 1fr)`, 'grid-template-columns': `repeat(${ game.settings.map[0].length }, 1fr)` }">
<div v-for="(x, i) in game.settings.map.join('')"
:data-none="x == ' '"
@click="onPixelClick(i, x)">
<template v-if="x == 'b'"><template v-if="$store.state.device.darkmode">%fa:circle R%</template><template v-else>%fa:circle%</template></template>
<template v-if="x == 'w'"><template v-if="$store.state.device.darkmode">%fa:circle%</template><template v-else>%fa:circle R%</template></template>
<template v-if="x == 'b'"><template v-if="$store.state.device.darkmode"><fa :icon="['far', 'circle']"/></template><template v-else><fa icon="circle"/></template></template>
<template v-if="x == 'w'"><template v-if="$store.state.device.darkmode"><fa :icon="['far', 'circle']"/></template><template v-else><fa icon="circle"/></template></template>
</div>
</div>
</div>

View File

@ -1,7 +1,7 @@
<template>
<div class="mk-google">
<input type="search" v-model="query" :placeholder="q">
<button @click="search">%fa:search% %i18n:common.search%</button>
<button @click="search"><fa icon="search"/> %i18n:common.search%</button>
</div>
</template>

View File

@ -40,7 +40,6 @@ import twitterSetting from './twitter-setting.vue';
import githubSetting from './github-setting.vue';
import fileTypeIcon from './file-type-icon.vue';
import emoji from './emoji.vue';
import Reversi from './games/reversi/reversi.vue';
import welcomeTimeline from './welcome-timeline.vue';
import uiInput from './ui/input.vue';
import uiButton from './ui/button.vue';
@ -95,7 +94,6 @@ Vue.component('mk-twitter-setting', twitterSetting);
Vue.component('mk-github-setting', githubSetting);
Vue.component('mk-file-type-icon', fileTypeIcon);
Vue.component('mk-emoji', emoji);
Vue.component('mk-reversi', Reversi);
Vue.component('mk-welcome-timeline', welcomeTimeline);
Vue.component('ui-input', uiInput);
Vue.component('ui-button', uiButton);

View File

@ -1,7 +1,7 @@
<template>
<div class="mk-media-banner">
<div class="sensitive" v-if="media.isSensitive && hide" @click="hide = false">
<span class="icon">%fa:exclamation-triangle%</span>
<span class="icon"><fa icon="exclamation-triangle"/></span>
<b>%i18n:@sensitive%</b>
<span>%i18n:@click-to-show%</span>
</div>
@ -18,7 +18,7 @@
:title="media.name"
:download="media.name"
>
<span class="icon">%fa:download%</span>
<span class="icon"><fa icon="download"/></span>
<b>{{ media.name }}</b>
</a>
</div>

View File

@ -4,7 +4,9 @@
<div class="popover" :class="{ hukidasi }" ref="popover">
<template v-for="item, i in items">
<div v-if="item === null"></div>
<button v-if="item" @click="clicked(item.action)" v-html="item.icon ? item.icon + ' ' + item.text : item.text" :tabindex="i"></button>
<button v-if="item" @click="clicked(item.action)" :tabindex="i">
<fa v-if="item.icon" :icon="item.icon"/>{{ item.text }}
</button>
</template>
</div>
</div>
@ -188,6 +190,9 @@ export default Vue.extend({
color var(--primaryForeground)
background var(--primaryDarken10)
> [data-icon]
margin-right 4px
> div
margin 8px 0
height 1px

View File

@ -14,13 +14,13 @@
<div class="file" @click="file = null" v-if="file">{{ file.name }}</div>
<mk-uploader ref="uploader" @uploaded="onUploaded"/>
<button class="send" @click="send" :disabled="!canSend || sending" title="%i18n:@send%">
<template v-if="!sending">%fa:paper-plane%</template><template v-if="sending">%fa:spinner .spin%</template>
<template v-if="!sending"><fa icon="paper-plane"/></template><template v-if="sending"><fa icon="spinner .spin"/></template>
</button>
<button class="attach-from-local" @click="chooseFile" title="%i18n:@attach-from-local%">
%fa:upload%
<fa icon="upload"/>
</button>
<button class="attach-from-drive" @click="chooseFileFromDrive" title="%i18n:@attach-from-drive%">
%fa:R folder-open%
<fa :icon="['far', 'folder-open']"/>
</button>
<input ref="file" type="file" @change="onChangeFile"/>
</div>

View File

@ -24,7 +24,7 @@
<footer>
<span class="read" v-if="isMe && message.isRead">%i18n:@is-read%</span>
<mk-time :time="message.createdAt"/>
<template v-if="message.is_edited">%fa:pencil-alt%</template>
<template v-if="message.is_edited"><fa icon="pencil-alt"/></template>
</footer>
</div>
</div>
@ -179,7 +179,10 @@ export default Vue.extend({
font-size 10px
color var(--messagingRoomMessageInfo)
> [data-fa]
> .read
margin 0 8px
> [data-icon]
margin-left 4px
&:not([data-is-me])

View File

@ -4,11 +4,11 @@
@drop.prevent.stop="onDrop"
>
<div class="body">
<p class="init" v-if="init">%fa:spinner .spin%%i18n:common.loading%</p>
<p class="empty" v-if="!init && messages.length == 0">%fa:info-circle%%i18n:@empty%</p>
<p class="no-history" v-if="!init && messages.length > 0 && !existMoreMessages">%fa:flag%%i18n:@no-history%</p>
<p class="init" v-if="init"><fa icon="spinner .spin"/>%i18n:common.loading%</p>
<p class="empty" v-if="!init && messages.length == 0"><fa icon="info-circle"/>%i18n:@empty%</p>
<p class="no-history" v-if="!init && messages.length > 0 && !existMoreMessages"><fa icon="flag"/>%i18n:@no-history%</p>
<button class="more" :class="{ fetching: fetchingMoreMessages }" v-if="existMoreMessages" @click="fetchMoreMessages" :disabled="fetchingMoreMessages">
<template v-if="fetchingMoreMessages">%fa:spinner .pulse .fw%</template>{{ fetchingMoreMessages ? '%i18n:common.loading%' : '%i18n:@more%' }}
<template v-if="fetchingMoreMessages"><fa icon="spinner .pulse" fixed-width/></template>{{ fetchingMoreMessages ? '%i18n:common.loading%' : '%i18n:@more%' }}
</button>
<template v-for="(message, i) in _messages">
<x-message :message="message" :key="message.id"/>
@ -20,7 +20,7 @@
<footer>
<transition name="fade">
<div class="new-message" v-show="showIndicator">
<button @click="onIndicatorClick">%fa:arrow-circle-down%%i18n:@new-message%</button>
<button @click="onIndicatorClick"><i><fa icon="arrow-circle-down"/></i>%i18n:@new-message%</button>
</div>
</transition>
<x-form :user="user" ref="form"/>
@ -280,7 +280,7 @@ export default Vue.extend({
color var(--messagingRoomInfo)
opacity 0.5
[data-fa]
[data-icon]
margin-right 4px
> .no-history
@ -292,7 +292,7 @@ export default Vue.extend({
color var(--messagingRoomInfo)
opacity 0.5
[data-fa]
[data-icon]
margin-right 4px
> .more
@ -313,7 +313,7 @@ export default Vue.extend({
&.fetching
cursor wait
> [data-fa]
> [data-icon]
margin-right 4px
> .message
@ -381,7 +381,7 @@ export default Vue.extend({
&:active
background var(--primaryDarken10)
> [data-fa]
> i
position absolute
top 0
left 10px

View File

@ -2,7 +2,7 @@
<div class="mk-messaging" :data-compact="compact">
<div class="search" v-if="!compact" :style="{ top: headerTop + 'px' }">
<div class="form">
<label for="search-input">%fa:search%</label>
<label for="search-input"><i><fa icon="search"/></i></label>
<input v-model="q" type="search" @input="search" @keydown="onSearchKeydown" placeholder="%i18n:@search-user%"/>
</div>
<div class="result">
@ -45,7 +45,7 @@
</template>
</div>
<p class="no-history" v-if="!fetching && messages.length == 0">%i18n:@no-history%</p>
<p class="fetching" v-if="fetching">%fa:spinner .pulse .fw%%i18n:common.loading%<mk-ellipsis/></p>
<p class="fetching" v-if="fetching"><fa icon="spinner .pulse" fixed-width/>%i18n:common.loading%<mk-ellipsis/></p>
</div>
</template>
@ -213,7 +213,7 @@ export default Vue.extend({
width 38px
pointer-events none
> [data-fa]
> i
display block
position absolute
top 0
@ -418,7 +418,7 @@ export default Vue.extend({
text-align center
color #aaa
> [data-fa]
> [data-icon]
margin-right 4px
// TODO: element base media query

View File

@ -187,13 +187,14 @@ export default Vue.component('misskey-flavored-markdown', {
}
case 'emoji': {
const customEmojis = (this.os.getMetaSync() || { emojis: [] }).emojis || [];
return [createElement('mk-emoji', {
attrs: {
emoji: token.emoji,
name: token.name
},
props: {
customEmojis: this.customEmojis
customEmojis: this.customEmojis || customEmojis
}
})];
}

View File

@ -1,6 +1,6 @@
<template>
<ui-card>
<div slot="title">%fa:ban% %i18n:@mute-and-block%</div>
<div slot="title"><fa icon="ban"/> %i18n:@mute-and-block%</div>
<section>
<header>%i18n:@mute%</header>

View File

@ -7,8 +7,6 @@
<a :href="feedbackUrl" target="_blank">%i18n:@feedback%</a>
<i></i>
<a href="/dev">%i18n:@develop%</a>
<i></i>
<a href="https://twitter.com/misskey_xyz" target="_blank">Follow us on %fa:B twitter%</a>
</span>
</template>

View File

@ -6,18 +6,18 @@
<span class="is-bot" v-if="note.user.isBot">bot</span>
<span class="is-cat" v-if="note.user.isCat">cat</span>
<span class="username"><mk-acct :user="note.user"/></span>
<span class="is-verified" v-if="note.user.isVerified" title="%i18n:common.verified-user%">%fa:star%</span>
<span class="is-verified" v-if="note.user.isVerified" title="%i18n:common.verified-user%"><fa icon="star"/></span>
<div class="info">
<span class="app" v-if="note.app && !mini">via <b>{{ note.app.name }}</b></span>
<span class="mobile" v-if="note.viaMobile">%fa:mobile-alt%</span>
<span class="mobile" v-if="note.viaMobile"><fa icon="mobile-alt"/></span>
<router-link class="created-at" :to="note | notePage">
<mk-time :time="note.createdAt"/>
</router-link>
<span class="visibility" v-if="note.visibility != 'public'">
<template v-if="note.visibility == 'home'">%fa:home%</template>
<template v-if="note.visibility == 'followers'">%fa:unlock%</template>
<template v-if="note.visibility == 'specified'">%fa:envelope%</template>
<template v-if="note.visibility == 'private'">%fa:lock%</template>
<template v-if="note.visibility == 'home'"><fa icon="home"/></template>
<template v-if="note.visibility == 'followers'"><fa icon="unlock"/></template>
<template v-if="note.visibility == 'specified'"><fa icon="envelope"/></template>
<template v-if="note.visibility == 'private'"><fa icon="lock"/></template>
</span>
</div>
</header>

View File

@ -15,18 +15,18 @@ export default Vue.extend({
computed: {
items() {
const items = [{
icon: '%fa:info-circle%',
icon: 'info-circle',
text: '%i18n:@detail%',
action: this.detail
}, {
icon: '%fa:link%',
icon: 'link',
text: '%i18n:@copy-link%',
action: this.copyLink
}];
if (this.note.uri) {
items.push({
icon: '%fa:external-link-square-alt%',
icon: 'external-link-square-alt',
text: '%i18n:@remote%',
action: () => {
window.open(this.note.uri, '_blank');
@ -38,13 +38,13 @@ export default Vue.extend({
if (this.note.isFavorited) {
items.push({
icon: '%fa:star%',
icon: 'star',
text: '%i18n:@unfavorite%',
action: this.unfavorite
});
} else {
items.push({
icon: '%fa:star%',
icon: 'star',
text: '%i18n:@favorite%',
action: this.favorite
});
@ -53,13 +53,13 @@ export default Vue.extend({
if (this.note.userId == this.$store.state.i.id) {
if ((this.$store.state.i.pinnedNoteIds || []).includes(this.note.id)) {
items.push({
icon: '%fa:thumbtack%',
icon: 'thumbtack',
text: '%i18n:@unpin%',
action: this.unpin
});
} else {
items.push({
icon: '%fa:thumbtack%',
icon: 'thumbtack',
text: '%i18n:@pin%',
action: this.pin
});
@ -69,7 +69,7 @@ export default Vue.extend({
if (this.note.userId == this.$store.state.i.id || this.$store.state.i.isAdmin) {
items.push(null);
items.push({
icon: '%fa:trash-alt R%',
icon: ['far', 'trash-alt'],
text: '%i18n:@delete%',
action: this.del
});

View File

@ -1,19 +1,19 @@
<template>
<div class="mk-poll-editor">
<p class="caution" v-if="choices.length < 2">
%fa:exclamation-triangle%%i18n:@no-only-one-choice%
<fa icon="exclamation-triangle"/>%i18n:@no-only-one-choice%
</p>
<ul ref="choices">
<li v-for="(choice, i) in choices">
<input :value="choice" @input="onInput(i, $event)" :placeholder="'%i18n:@choice-n%'.replace('{}', i + 1)">
<button @click="remove(i)" title="%i18n:@remove%">
%fa:times%
<fa icon="times"/>
</button>
</li>
</ul>
<button class="add" v-if="choices.length < 10" @click="add">%i18n:@add%</button>
<button class="destroy" @click="destroy" title="%i18n:@destroy%">
%fa:times%
<fa icon="times"/>
</button>
</div>
</template>
@ -76,7 +76,7 @@ export default Vue.extend({
font-size 0.8em
color #f00
> [data-fa]
> [data-icon]
margin-right 4px
> ul

View File

@ -4,7 +4,7 @@
<li v-for="choice in poll.choices" :key="choice.id" @click="vote(choice.id)" :class="{ voted: choice.voted }" :title="!isVoted ? '%i18n:@vote-to%'.replace('{}', choice.text) : ''">
<div class="backdrop" :style="{ 'width': (showResult ? (choice.votes / total * 100) : 0) + '%' }"></div>
<span>
<template v-if="choice.isVoted">%fa:check%</template>
<template v-if="choice.isVoted"><fa icon="check"/></template>
<span>{{ choice.text }}</span>
<span class="votes" v-if="showResult">({{ '%i18n:@vote-count%'.replace('{}', choice.votes) }})</span>
</span>
@ -100,7 +100,7 @@ export default Vue.extend({
transition width 1s ease
> span
> [data-fa]
> [data-icon]
margin-right 4px
> .votes

View File

@ -1,6 +1,6 @@
<template>
<ui-card>
<div slot="title">%fa:user% %i18n:@title%</div>
<div slot="title"><fa icon="user"/> %i18n:@title%</div>
<section class="fit-top">
<ui-form :disabled="saving">
@ -16,12 +16,12 @@
<ui-input v-model="location">
<span>%i18n:@location%</span>
<span slot="prefix">%fa:map-marker-alt%</span>
<span slot="prefix"><fa icon="map-marker-alt"/></span>
</ui-input>
<ui-input v-model="birthday" type="date">
<span>%i18n:@birthday%</span>
<span slot="prefix">%fa:birthday-cake%</span>
<span slot="prefix"><fa icon="birthday-cake"/></span>
</ui-input>
<ui-textarea v-model="description" :max="500">
@ -30,14 +30,14 @@
<ui-input type="file" @change="onAvatarChange">
<span>%i18n:@avatar%</span>
<span slot="icon">%fa:image%</span>
<span slot="text" v-if="avatarUploading">%i18n:@uploading%<mk-ellipsis/></span>
<span slot="icon"><fa icon="image"/></span>
<span slot="desc" v-if="avatarUploading">%i18n:@uploading%<mk-ellipsis/></span>
</ui-input>
<ui-input type="file" @change="onBannerChange">
<span>%i18n:@banner%</span>
<span slot="icon">%fa:image%</span>
<span slot="text" v-if="bannerUploading">%i18n:@uploading%<mk-ellipsis/></span>
<span slot="icon"><fa icon="image"/></span>
<span slot="desc" v-if="bannerUploading">%i18n:@uploading%<mk-ellipsis/></span>
</ui-input>
<ui-button @click="save(true)">%i18n:@save%</ui-button>

View File

@ -8,7 +8,7 @@
</ui-input>
<ui-input v-model="password" type="password" required styl="fill">
<span>%i18n:@password%</span>
<span slot="prefix">%fa:lock%</span>
<span slot="prefix"><fa icon="lock"/></span>
</ui-input>
<ui-input v-if="user && user.twoFactorEnabled" v-model="token" type="number" required styl="fill"/>
<ui-button type="submit" :disabled="signing">{{ signing ? '%i18n:@signing-in%' : '%i18n:@signin%' }}</ui-button>

View File

@ -3,39 +3,39 @@
<template v-if="meta">
<ui-input v-if="meta.disableRegistration" v-model="invitationCode" type="text" :autocomplete="Math.random()" spellcheck="false" required styl="fill">
<span>%i18n:@invitation-code%</span>
<span slot="prefix">%fa:id-card-alt%</span>
<p slot="text" v-html="'%i18n:@invitation-info%'.replace('{}', meta.maintainer.url)"></p>
<span slot="prefix"><fa icon="id-card-alt"/></span>
<p slot="desc" v-html="'%i18n:@invitation-info%'.replace('{}', 'mailto:' + meta.maintainer.email)"></p>
</ui-input>
<ui-input v-model="username" type="text" pattern="^[a-zA-Z0-9_]{1,20}$" :autocomplete="Math.random()" spellcheck="false" required @input="onChangeUsername" styl="fill">
<span>%i18n:@username%</span>
<span slot="prefix">@</span>
<span slot="suffix">@{{ host }}</span>
<p slot="text" v-if="usernameState == 'wait'" style="color:#999">%fa:spinner .pulse .fw% %i18n:@checking%</p>
<p slot="text" v-if="usernameState == 'ok'" style="color:#3CB7B5">%fa:check .fw% %i18n:@available%</p>
<p slot="text" v-if="usernameState == 'unavailable'" style="color:#FF1161">%fa:exclamation-triangle .fw% %i18n:@unavailable%</p>
<p slot="text" v-if="usernameState == 'error'" style="color:#FF1161">%fa:exclamation-triangle .fw% %i18n:@error%</p>
<p slot="text" v-if="usernameState == 'invalid-format'" style="color:#FF1161">%fa:exclamation-triangle .fw% %i18n:@invalid-format%</p>
<p slot="text" v-if="usernameState == 'min-range'" style="color:#FF1161">%fa:exclamation-triangle .fw% %i18n:@too-short%</p>
<p slot="text" v-if="usernameState == 'max-range'" style="color:#FF1161">%fa:exclamation-triangle .fw% %i18n:@too-long%</p>
<p slot="desc" v-if="usernameState == 'wait'" style="color:#999"><fa icon="spinner .pulse" fixed-width/> %i18n:@checking%</p>
<p slot="desc" v-if="usernameState == 'ok'" style="color:#3CB7B5"><fa icon="check" fixed-width/> %i18n:@available%</p>
<p slot="desc" v-if="usernameState == 'unavailable'" style="color:#FF1161"><fa icon="exclamation-triangle" fixed-width/> %i18n:@unavailable%</p>
<p slot="desc" v-if="usernameState == 'error'" style="color:#FF1161"><fa icon="exclamation-triangle" fixed-width/> %i18n:@error%</p>
<p slot="desc" v-if="usernameState == 'invalid-format'" style="color:#FF1161"><fa icon="exclamation-triangle" fixed-width/> %i18n:@invalid-format%</p>
<p slot="desc" v-if="usernameState == 'min-range'" style="color:#FF1161"><fa icon="exclamation-triangle" fixed-width/> %i18n:@too-short%</p>
<p slot="desc" v-if="usernameState == 'max-range'" style="color:#FF1161"><fa icon="exclamation-triangle" fixed-width/> %i18n:@too-long%</p>
</ui-input>
<ui-input v-model="password" type="password" :autocomplete="Math.random()" required @input="onChangePassword" :with-password-meter="true" styl="fill">
<span>%i18n:@password%</span>
<span slot="prefix">%fa:lock%</span>
<div slot="text">
<p slot="text" v-if="passwordStrength == 'low'" style="color:#FF1161">%fa:exclamation-triangle .fw% %i18n:@weak-password%</p>
<p slot="text" v-if="passwordStrength == 'medium'" style="color:#3CB7B5">%fa:check .fw% %i18n:@normal-password%</p>
<p slot="text" v-if="passwordStrength == 'high'" style="color:#3CB7B5">%fa:check .fw% %i18n:@strong-password%</p>
<span slot="prefix"><fa icon="lock"/></span>
<div slot="desc">
<p v-if="passwordStrength == 'low'" style="color:#FF1161"><fa icon="exclamation-triangle" fixed-width/> %i18n:@weak-password%</p>
<p v-if="passwordStrength == 'medium'" style="color:#3CB7B5"><fa icon="check" fixed-width/> %i18n:@normal-password%</p>
<p v-if="passwordStrength == 'high'" style="color:#3CB7B5"><fa icon="check" fixed-width/> %i18n:@strong-password%</p>
</div>
</ui-input>
<ui-input v-model="retypedPassword" type="password" :autocomplete="Math.random()" required @input="onChangePasswordRetype" styl="fill">
<span>%i18n:@password% (%i18n:@retype%)</span>
<span slot="prefix">%fa:lock%</span>
<div slot="text">
<p slot="text" v-if="passwordRetypeState == 'match'" style="color:#3CB7B5">%fa:check .fw% %i18n:@password-matched%</p>
<p slot="text" v-if="passwordRetypeState == 'not-match'" style="color:#FF1161">%fa:exclamation-triangle .fw% %i18n:@password-not-matched%</p>
<span slot="prefix"><fa icon="lock"/></span>
<div slot="desc">
<p v-if="passwordRetypeState == 'match'" style="color:#3CB7B5"><fa icon="check" fixed-width/> %i18n:@password-matched%</p>
<p v-if="passwordRetypeState == 'not-match'" style="color:#FF1161"><fa icon="exclamation-triangle" fixed-width/> %i18n:@password-not-matched%</p>
</div>
</ui-input>
<div v-if="meta.recaptchaSitekey != null" class="g-recaptcha" :data-sitekey="meta.recaptchaSitekey" style="margin: 16px 0;"></div>
<div v-if="meta.enableRecaptcha" class="g-recaptcha" :data-sitekey="meta.recaptchaSiteKey" style="margin: 16px 0;"></div>
<ui-button type="submit">%i18n:@create%</ui-button>
</template>
</form>
@ -130,7 +130,7 @@ export default Vue.extend({
username: this.username,
password: this.password,
invitationCode: this.invitationCode,
'g-recaptcha-response': this.meta.recaptchaSitekey != null ? (window as any).grecaptcha.getResponse() : null
'g-recaptcha-response': this.meta.enableRecaptcha ? (window as any).grecaptcha.getResponse() : null
}, true).then(() => {
(this as any).api('signin', {
username: this.username,
@ -141,7 +141,7 @@ export default Vue.extend({
}).catch(() => {
alert('%i18n:@some-error%');
if (this.meta.recaptchaSitekey != null) {
if (this.meta.enableRecaptcha) {
(window as any).grecaptcha.reset();
}
});

View File

@ -1,15 +1,15 @@
<template>
<div class="mk-stream-indicator">
<p v-if="stream.state == 'initializing'">
%fa:spinner .pulse%
<fa icon="spinner .pulse"/>
<span>%i18n:@connecting%<mk-ellipsis/></span>
</p>
<p v-if="stream.state == 'reconnecting'">
%fa:spinner .pulse%
<fa icon="spinner .pulse"/>
<span>%i18n:@reconnecting%<mk-ellipsis/></span>
</p>
<p v-if="stream.state == 'connected'">
%fa:check%
<fa icon="check"/>
<span>%i18n:@connected%</span>
</p>
</div>
@ -80,7 +80,7 @@ export default Vue.extend({
display block
margin 0
> [data-fa]
> [data-icon]
margin-right 0.25em
</style>

View File

@ -1,7 +1,7 @@
<template>
<div class="jtivnzhfwquxpsfidertopbmwmchmnmo">
<p class="fetching" v-if="fetching">%fa:spinner .pulse .fw%%i18n:common.loading%<mk-ellipsis/></p>
<p class="empty" v-else-if="tags.length == 0">%fa:exclamation-circle%%i18n:@empty%</p>
<p class="fetching" v-if="fetching"><fa icon="spinner .pulse" fixed-width/>%i18n:common.loading%<mk-ellipsis/></p>
<p class="empty" v-else-if="tags.length == 0"><fa icon="exclamation-circle"/>%i18n:@empty%</p>
<div v-else>
<vue-word-cloud
:words="tags.slice(0, 20).map(x => [x.name, x.count])"
@ -74,7 +74,7 @@ export default Vue.extend({
text-align center
color #aaa
> [data-fa]
> [data-icon]
margin-right 4px
> div

View File

@ -25,7 +25,7 @@
</label>
<details class="creator">
<summary>%fa:palette% %i18n:@create-a-theme%</summary>
<summary><fa icon="palette"/> %i18n:@create-a-theme%</summary>
<div>
<span>%i18n:@base-theme%:</span>
<ui-radio v-model="myThemeBase" value="light">%i18n:@base-theme-light%</ui-radio>
@ -51,23 +51,23 @@
<div style="padding-bottom:8px;">%i18n:@text-color%:</div>
<color-picker v-model="myThemeText"/>
</div>
<ui-button @click="preview()">%fa:eye% %i18n:@preview-created-theme%</ui-button>
<ui-button primary @click="gen()">%fa:save R% %i18n:@save-created-theme%</ui-button>
<ui-button @click="preview()"><fa icon="eye"/> %i18n:@preview-created-theme%</ui-button>
<ui-button primary @click="gen()"><fa :icon="['far', 'save']"/> %i18n:@save-created-theme%</ui-button>
</details>
<details>
<summary>%fa:download% %i18n:@install-a-theme%</summary>
<ui-button @click="import_()">%fa:file-import% %i18n:@import%</ui-button>
<summary><fa icon="download"/> %i18n:@install-a-theme%</summary>
<ui-button @click="import_()"><fa icon="file-import"/> %i18n:@import%</ui-button>
<input ref="file" type="file" accept=".misskeytheme" style="display:none;" @change="onUpdateImportFile"/>
<p>%i18n:@import-by-code%:</p>
<ui-textarea v-model="installThemeCode">
<span>%i18n:@theme-code%</span>
</ui-textarea>
<ui-button @click="() => install(this.installThemeCode)">%fa:check% %i18n:@install%</ui-button>
<ui-button @click="() => install(this.installThemeCode)"><fa icon="check"/> %i18n:@install%</ui-button>
</details>
<details>
<summary>%fa:folder-open% %i18n:@manage-themes%</summary>
<summary><fa icon="folder-open"/> %i18n:@manage-themes%</summary>
<ui-select v-model="selectedThemeId" placeholder="%i18n:@select-theme%">
<optgroup label="%i18n:@builtin-themes%">
<option v-for="x in builtinThemes" :value="x.id" :key="x.id">{{ x.name }}</option>
@ -89,8 +89,8 @@
<ui-textarea readonly :value="selectedThemeCode">
<span>%i18n:@theme-code%</span>
</ui-textarea>
<ui-button @click="export_()" link :download="`${selectedTheme.name}.misskeytheme`" ref="export">%fa:box% %i18n:@export%</ui-button>
<ui-button @click="uninstall()" v-if="!builtinThemes.some(t => t.id == selectedTheme.id)">%fa:trash-alt R% %i18n:@uninstall%</ui-button>
<ui-button @click="export_()" link :download="`${selectedTheme.name}.misskeytheme`" ref="export"><fa icon="box"/> %i18n:@export%</ui-button>
<ui-button @click="uninstall()" v-if="!builtinThemes.some(t => t.id == selectedTheme.id)"><fa :icon="['far', 'trash-alt']"/> %i18n:@uninstall%</ui-button>
</template>
</details>
</div>

View File

@ -1,7 +1,7 @@
<template>
<div class="csqvmxybqbycalfhkxvyfrgbrdalkaoc">
<p class="fetching" v-if="fetching">%fa:spinner .pulse .fw%%i18n:common.loading%<mk-ellipsis/></p>
<p class="empty" v-else-if="stats.length == 0">%fa:exclamation-circle%%i18n:@empty%</p>
<p class="fetching" v-if="fetching"><fa icon="spinner .pulse" fixed-width/>%i18n:common.loading%<mk-ellipsis/></p>
<p class="empty" v-else-if="stats.length == 0"><fa icon="exclamation-circle"/>%i18n:@empty%</p>
<!-- トランジションを有効にするとなぜかメモリリークする -->
<transition-group v-else tag="div" name="chart">
<div v-for="stat in stats" :key="stat.tag">
@ -58,7 +58,7 @@ export default Vue.extend({
color var(--text)
opacity 0.7
> [data-fa]
> [data-icon]
margin-right 4px
> div

View File

@ -48,6 +48,9 @@ export default Vue.extend({
&.fit-top
padding-top 0
&.fit-bottom
padding-bottom 0
> header
margin-bottom 16px
font-weight bold

View File

@ -1,7 +1,7 @@
<template>
<div class="ymxyweixqwsxauxldgpvecjepnwxbylu" :class="{ warn }">
<i v-if="warn">%fa:exclamation-triangle%</i>
<i v-else>%fa:info-circle%</i>
<i v-if="warn"><fa icon="exclamation-triangle"/></i>
<i v-else><fa icon="info-circle"/></i>
<slot></slot>
</div>
</template>

View File

@ -1,5 +1,5 @@
<template>
<div class="ui-input" :class="[{ focused, filled, inline }, styl]">
<div class="ui-input" :class="[{ focused, filled, inline, disabled }, styl]">
<div class="icon" ref="icon"><slot name="icon"></slot></div>
<div class="input">
<div class="password-meter" v-if="withPasswordMeter" v-show="passwordStrength != ''" :data-strength="passwordStrength">
@ -11,6 +11,7 @@
<input ref="input"
:type="type"
v-model="v"
:disabled="disabled"
:required="required"
:readonly="readonly"
:pattern="pattern"
@ -32,7 +33,7 @@
</template>
<div class="suffix" ref="suffix"><slot name="suffix"></slot></div>
</div>
<div class="text"><slot name="text"></slot></div>
<div class="desc"><slot name="desc"></slot></div>
</div>
</template>
@ -62,6 +63,10 @@ export default Vue.extend({
type: Boolean,
required: false
},
disabled: {
type: Boolean,
required: false
},
pattern: {
type: String,
required: false
@ -316,7 +321,7 @@ root(fill)
if fill
padding-right 12px
> .text
> .desc
margin 6px 0
font-size 13px
@ -353,4 +358,10 @@ root(fill)
display inline-block
margin 0
&.disabled
opacity 0.7
&, *
cursor not-allowed !important
</style>

View File

@ -129,5 +129,6 @@ export default Vue.extend({
> p
margin 0
opacity 0.7
font-size 90%
</style>

View File

@ -13,7 +13,7 @@
@blur="focused = false"
></textarea>
</div>
<div class="text"><slot name="text"></slot></div>
<div class="desc"><slot name="desc"></slot></div>
</div>
</template>
@ -139,7 +139,7 @@ root(fill)
outline none
box-shadow none
> .text
> .desc
margin 6px 0
font-size 13px

View File

@ -3,7 +3,7 @@
<ol v-if="uploads.length > 0">
<li v-for="ctx in uploads" :key="ctx.id">
<div class="img" :style="{ backgroundImage: `url(${ ctx.img })` }"></div>
<p class="name">%fa:spinner .pulse%{{ ctx.name }}</p>
<p class="name"><fa icon="spinner .pulse"/>{{ ctx.name }}</p>
<p class="status">
<span class="initing" v-if="ctx.progress == undefined">%i18n:@waiting%<mk-ellipsis/></span>
<span class="kb" v-if="ctx.progress != undefined">{{ String(Math.floor(ctx.progress.value / 1024)).replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1,') }}<i>KB</i> / {{ String(Math.floor(ctx.progress.max / 1024)).replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1,') }}<i>KB</i></span>
@ -155,7 +155,7 @@ export default Vue.extend({
text-overflow ellipsis
overflow hidden
> [data-fa]
> [data-icon]
margin-right 4px
> .status

View File

@ -6,7 +6,7 @@
<span class="pathname" v-if="pathname != ''">{{ pathname }}</span>
<span class="query">{{ query }}</span>
<span class="hash">{{ hash }}</span>
%fa:external-link-square-alt%
<fa icon="external-link-square-alt"/>
</a>
</template>
@ -40,7 +40,7 @@ export default Vue.extend({
<style lang="stylus" scoped>
.mk-url
word-break break-all
> [data-fa]
> [data-icon]
padding-left 2px
font-size .9em
font-weight 400

View File

@ -3,34 +3,34 @@
<div class="backdrop" ref="backdrop" @click="close"></div>
<div class="popover" :class="{ compact }" ref="popover">
<div @click="choose('public')" :class="{ active: v == 'public' }">
<div>%fa:globe%</div>
<div><fa icon="globe"/></div>
<div>
<span>%i18n:@public%</span>
</div>
</div>
<div @click="choose('home')" :class="{ active: v == 'home' }">
<div>%fa:home%</div>
<div><fa icon="home"/></div>
<div>
<span>%i18n:@home%</span>
<span>%i18n:@home-desc%</span>
</div>
</div>
<div @click="choose('followers')" :class="{ active: v == 'followers' }">
<div>%fa:unlock%</div>
<div><fa icon="unlock"/></div>
<div>
<span>%i18n:@followers%</span>
<span>%i18n:@followers-desc%</span>
</div>
</div>
<div @click="choose('specified')" :class="{ active: v == 'specified' }">
<div>%fa:envelope%</div>
<div><fa icon="envelope"/></div>
<div>
<span>%i18n:@specified%</span>
<span>%i18n:@specified-desc%</span>
</div>
</div>
<div @click="choose('private')" :class="{ active: v == 'private' }">
<div>%fa:lock%</div>
<div><fa icon="lock"/></div>
<div>
<span>%i18n:@private%</span>
</div>

View File

@ -109,7 +109,7 @@ class Autocomplete {
if (isEmoji && opened == false) {
const emoji = text.substr(emojiIndex + 1);
if (emoji != '' && emoji.match(/^[\+\-a-z0-9_]+$/)) {
if (!emoji.includes(' ')) {
this.open('emoji', emoji);
opened = true;
}

View File

@ -19,13 +19,13 @@
@click="onClick"
:disabled="followWait">
<template v-if="!followWait">
<template v-if="user.hasPendingFollowRequestFromYou && user.isLocked">%fa:hourglass-half% %i18n:@request-pending%</template>
<template v-else-if="user.hasPendingFollowRequestFromYou && !user.isLocked">%fa:hourglass-start% %i18n:@follow-processing%</template>
<template v-else-if="user.isFollowing">%fa:minus% %i18n:@following%</template>
<template v-else-if="!user.isFollowing && user.isLocked">%fa:plus% %i18n:@follow-request%</template>
<template v-else-if="!user.isFollowing && !user.isLocked">%fa:plus% %i18n:@follow%</template>
<template v-if="user.hasPendingFollowRequestFromYou && user.isLocked"><fa icon="hourglass-half"/> %i18n:@request-pending%</template>
<template v-else-if="user.hasPendingFollowRequestFromYou && !user.isLocked"><fa icon="hourglass-start"/> %i18n:@follow-processing%</template>
<template v-else-if="user.isFollowing"><fa icon="minus"/> %i18n:@following%</template>
<template v-else-if="!user.isFollowing && user.isLocked"><fa icon="plus"/> %i18n:@follow-request%</template>
<template v-else-if="!user.isFollowing && !user.isLocked"><fa icon="plus"/> %i18n:@follow%</template>
</template>
<template v-else>%fa:spinner .pulse .fw%</template>
<template v-else><fa icon="spinner .pulse" fixed-width/></template>
</button>
</div>
</template>

View File

@ -2,10 +2,10 @@
<div>
<mk-widget-container :show-header="false">
<article class="dolfvtibguprpxxhfndqaosjitixjohx">
<h1>%fa:heart%%i18n:@title%</h1>
<h1><fa icon="heart"/>%i18n:@title%</h1>
<p v-if="meta">
{{ '%i18n:@text%'.substr(0, '%i18n:@text%'.indexOf('{')) }}
<a :href="meta.maintainer.url">{{ meta.maintainer.name }}</a>
<a :href="'mailto:' + meta.maintainer.email">{{ meta.maintainer.name }}</a>
{{ '%i18n:@text%'.substr('%i18n:@text%'.indexOf('}') + 1) }}
</p>
</article>
@ -41,7 +41,7 @@ export default define({
margin 0 0 5px 0
font-size 1em
> [data-fa]
> [data-icon]
margin-right 0.25em
> p

View File

@ -1,7 +1,7 @@
<template>
<div class="mkw-hashtags">
<mk-widget-container :show-header="!props.compact">
<template slot="header">%fa:hashtag%%i18n:@title%</template>
<template slot="header"><fa icon="hashtag"/>%i18n:@title%</template>
<div class="mkw-hashtags--body" :data-mobile="platform == 'mobile'">
<mk-trends/>

View File

@ -1,7 +1,7 @@
<template>
<div class="mkw-memo">
<mk-widget-container :show-header="!props.compact">
<template slot="header">%fa:R sticky-note%%i18n:@title%</template>
<template slot="header"><fa :icon="['far', 'sticky-note']"/>%i18n:@title%</template>
<div class="mkw-memo--body">
<textarea v-model="text" placeholder="%i18n:@memo%" @input="onChange"></textarea>

View File

@ -1,9 +1,9 @@
<template>
<div class="mkw-photo-stream" :class="$style.root" :data-melt="props.design == 2">
<mk-widget-container :show-header="props.design == 0" :naked="props.design == 2">
<template slot="header">%fa:camera%%i18n:@title%</template>
<template slot="header"><fa icon="camera"/>%i18n:@title%</template>
<p :class="$style.fetching" v-if="fetching">%fa:spinner .pulse .fw%%i18n:common.loading%<mk-ellipsis/></p>
<p :class="$style.fetching" v-if="fetching"><fa icon="spinner .pulse" fixed-width/>%i18n:common.loading%<mk-ellipsis/></p>
<div :class="$style.stream" v-if="!fetching && images.length > 0">
<div v-for="image in images" :class="$style.img" :style="`background-image: url(${image.thumbnailUrl || image.url})`"></div>
</div>
@ -94,7 +94,7 @@ export default define({
text-align center
color #aaa
> [data-fa]
> [data-icon]
margin-right 4px
</style>

View File

@ -1,8 +1,8 @@
<template>
<div class="mkw-posts-monitor">
<mk-widget-container :show-header="props.design == 0" :naked="props.design == 2">
<template slot="header">%fa:chart-line%%i18n:@title%</template>
<button slot="func" @click="toggle" title="%i18n:@toggle%">%fa:sort%</button>
<template slot="header"><fa icon="chart-line"/>%i18n:@title%</template>
<button slot="func" @click="toggle" title="%i18n:@toggle%"><fa icon="sort"/></button>
<div class="qpdmibaztplkylerhdbllwcokyrfxeyj" :class="{ dual: props.view == 0 }">
<svg :viewBox="`0 0 ${ viewBoxX } ${ viewBoxY }`" v-show="props.view != 2">

View File

@ -1,11 +1,11 @@
<template>
<div class="mkw-rss">
<mk-widget-container :show-header="!props.compact">
<template slot="header">%fa:rss-square%RSS</template>
<button slot="func" title="設定" @click="setting">%fa:cog%</button>
<template slot="header"><fa icon="rss-square"/>RSS</template>
<button slot="func" title="設定" @click="setting"><fa icon="cog"/></button>
<div class="mkw-rss--body" :data-mobile="platform == 'mobile'">
<p class="fetching" v-if="fetching">%fa:spinner .pulse .fw%%i18n:common.loading%<mk-ellipsis/></p>
<p class="fetching" v-if="fetching"><fa icon="spinner .pulse" fixed-width/>%i18n:common.loading%<mk-ellipsis/></p>
<div class="feed" v-else>
<a v-for="item in items" :href="item.link" target="_blank">{{ item.title }}</a>
</div>
@ -85,7 +85,7 @@ export default define({
text-align center
color #aaa
> [data-fa]
> [data-icon]
margin-right 4px
&[data-mobile]

View File

@ -2,7 +2,7 @@
<div class="cpu">
<x-pie class="pie" :value="usage"/>
<div>
<p>%fa:microchip%CPU</p>
<p><fa icon="microchip"/>CPU</p>
<p>{{ meta.cpu.cores }} Cores</p>
<p>{{ meta.cpu.model }}</p>
</div>
@ -57,7 +57,7 @@ export default Vue.extend({
&:first-child
font-weight bold
> [data-fa]
> [data-icon]
margin-right 4px
&:after

View File

@ -2,7 +2,7 @@
<div class="disk">
<x-pie class="pie" :value="usage"/>
<div>
<p>%fa:R hdd%Storage</p>
<p><fa :icon="['far', 'hdd']"/>Storage</p>
<p>Total: {{ total | bytes(1) }}</p>
<p>Free: {{ available | bytes(1) }}</p>
<p>Used: {{ used | bytes(1) }}</p>
@ -65,7 +65,7 @@ export default Vue.extend({
&:first-child
font-weight bold
> [data-fa]
> [data-icon]
margin-right 4px
&:after

View File

@ -1,6 +1,6 @@
<template>
<div class="info">
<p>Maintainer: <b><a :href="meta.maintainer.url" target="_blank">{{ meta.maintainer.name }}</a></b></p>
<p>Maintainer: <b><a :href="'mailto:' + meta.maintainer.email" target="_blank">{{ meta.maintainer.name }}</a></b></p>
<p>Machine: {{ meta.machine }}</p>
<p>Node: {{ meta.node }}</p>
</div>

View File

@ -2,7 +2,7 @@
<div class="memory">
<x-pie class="pie" :value="usage"/>
<div>
<p>%fa:flask%Memory</p>
<p><fa icon="flask"/>Memory</p>
<p>Total: {{ total | bytes(1) }}</p>
<p>Used: {{ used | bytes(1) }}</p>
<p>Free: {{ free | bytes(1) }}</p>
@ -65,7 +65,7 @@ export default Vue.extend({
&:first-child
font-weight bold
> [data-fa]
> [data-icon]
margin-right 4px
&:after

View File

@ -1,10 +1,10 @@
<template>
<div class="mkw-server">
<mk-widget-container :show-header="props.design == 0" :naked="props.design == 2">
<template slot="header">%fa:server%%i18n:@title%</template>
<button slot="func" @click="toggle" title="%i18n:@toggle%">%fa:sort%</button>
<template slot="header"><fa icon="server"/>%i18n:@title%</template>
<button slot="func" @click="toggle" title="%i18n:@toggle%"><fa icon="sort"/></button>
<p :class="$style.fetching" v-if="fetching">%fa:spinner .pulse .fw%%i18n:common.loading%<mk-ellipsis/></p>
<p :class="$style.fetching" v-if="fetching"><fa icon="spinner .pulse" fixed-width/>%i18n:common.loading%<mk-ellipsis/></p>
<template v-if="!fetching">
<x-cpu-memory v-show="props.view == 0" :connection="connection"/>
<x-cpu v-show="props.view == 1" :connection="connection" :meta="meta"/>
@ -87,7 +87,7 @@ export default define({
text-align center
color #aaa
> [data-fa]
> [data-icon]
margin-right 4px
</style>

View File

@ -1,6 +1,6 @@
<template>
<div class="mkw-tips">
<p ref="tip">%fa:R lightbulb%<span v-html="tip"></span></p>
<p ref="tip"><fa :icon="['far', 'lightbulb']"/><span v-html="tip"></span></p>
</div>
</template>
@ -88,7 +88,7 @@ export default define({
font-size 0.7em
color #999
> [data-fa]
> [data-icon]
margin-right 4px
kbd

View File

@ -1,10 +1,10 @@
<template>
<div class="mk-activity">
<mk-widget-container :show-header="design == 0" :naked="design == 2">
<template slot="header">%fa:chart-bar%%i18n:@title%</template>
<button slot="func" title="%i18n:@toggle%" @click="toggle">%fa:sort%</button>
<template slot="header"><fa icon="chart-bar"/>%i18n:@title%</template>
<button slot="func" title="%i18n:@toggle%" @click="toggle"><fa icon="sort"/></button>
<p :class="$style.fetching" v-if="fetching">%fa:spinner .pulse .fw%%i18n:common.loading%<mk-ellipsis/></p>
<p :class="$style.fetching" v-if="fetching"><fa icon="spinner .pulse" fixed-width/>%i18n:common.loading%<mk-ellipsis/></p>
<template v-else>
<x-calendar v-show="view == 0" :data="[].concat(activity)"/>
<x-chart v-show="view == 1" :data="[].concat(activity)"/>
@ -78,7 +78,7 @@ export default Vue.extend({
text-align center
color #aaa
> [data-fa]
> [data-icon]
margin-right 4px
</style>

View File

@ -1,9 +1,9 @@
<template>
<div class="mk-calendar" :data-melt="design == 4 || design == 5">
<template v-if="design == 0 || design == 1">
<button @click="prev" title="%i18n:@prev%">%fa:chevron-circle-left%</button>
<button @click="prev" title="%i18n:@prev%"><fa icon="chevron-circle-left"/></button>
<p class="title">{{ '%i18n:@title%'.replace('{1}', year).replace('{2}', month) }}</p>
<button @click="next" title="%i18n:@next%">%fa:chevron-circle-right%</button>
<button @click="next" title="%i18n:@next%"><fa icon="chevron-circle-right"/></button>
</template>
<div class="calendar">
@ -151,7 +151,7 @@ export default Vue.extend({
background var(--faceHeader)
box-shadow 0 1px rgba(#000, 0.07)
> [data-fa]
> [data-icon]
margin-right 4px
> button

View File

@ -13,7 +13,7 @@
@change-selection="onChangeSelection"
/>
<div :class="$style.footer">
<button :class="$style.upload" title="%i18n:@upload%" @click="upload">%fa:upload%</button>
<button :class="$style.upload" title="%i18n:@upload%" @click="upload"><fa icon="upload"/></button>
<button :class="$style.cancel" @click="cancel">%i18n:@cancel%</button>
<button :class="$style.ok" :disabled="multiple && files.length == 0" @click="ok">%i18n:@ok%</button>
</div>
@ -28,7 +28,7 @@ export default Vue.extend({
default: false
},
title: {
default: '%fa:R file%%i18n:@choose-prompt%'
default: '<fa :icon="['far', 'file']"/>%i18n:@choose-prompt%'
}
},
data() {
@ -62,7 +62,7 @@ export default Vue.extend({
.title
> [data-fa]
> [data-icon]
margin-right 4px
.count

View File

@ -21,7 +21,7 @@ import Vue from 'vue';
export default Vue.extend({
props: {
title: {
default: '%fa:R folder%%i18n:@choose-prompt%'
default: '<fa :icon="['far', 'folder']"/>%i18n:@choose-prompt%'
}
},
methods: {
@ -40,7 +40,7 @@ export default Vue.extend({
.title
> [data-fa]
> [data-icon]
margin-right 4px
.browser

View File

@ -3,13 +3,13 @@
<li v-for="(item, i) in menu" :class="item ? item.type : item === null ? 'divider' : null">
<template v-if="item">
<template v-if="item.type == null || item.type == 'item'">
<p @click="click(item)"><span :class="$style.icon" v-if="item.icon" v-html="item.icon"></span>{{ item.text }}</p>
<p @click="click(item)"><i v-if="item.icon" :class="$style.icon"><fa :icon="item.icon"/></i>{{ item.text }}</p>
</template>
<template v-else-if="item.type == 'link'">
<a :href="item.href" :target="item.target" @click="click(item)"><span :class="$style.icon" v-if="item.icon" v-html="item.icon"></span>{{ item.text }}</a>
<a :href="item.href" :target="item.target" @click="click(item)"><i v-if="item.icon" :class="$style.icon"><fa :icon="item.icon"/></i>{{ item.text }}</a>
</template>
<template v-else-if="item.type == 'nest'">
<p><span :class="$style.icon" v-if="item.icon" v-html="item.icon"></span>{{ item.text }}...<span class="caret">%fa:caret-right%</span></p>
<p><i v-if="item.icon" :class="$style.icon"><fa :icon="item.icon"/></i>{{ item.text }}...<span class="caret"><fa icon="caret-right"/></span></p>
<me-nu :menu="item.menu" @x="click"/>
</template>
</template>
@ -113,9 +113,9 @@ export default Vue.extend({
<style lang="stylus" module>
.icon
> *
width 28px
margin-left -28px
text-align center
display inline-block
width 28px
margin-left -28px
text-align center
</style>

View File

@ -1,6 +1,6 @@
<template>
<mk-window ref="window" is-modal width="800px" :can-close="false">
<span slot="header">%fa:crop%{{ title }}</span>
<span slot="header"><fa icon="crop"/>{{ title }}</span>
<div class="body">
<vue-cropper ref="cropper"
:src="image.url"
@ -64,7 +64,7 @@ export default Vue.extend({
.header
> [data-fa]
> [data-icon]
margin-right 4px
.img

View File

@ -91,8 +91,6 @@ export default Vue.extend({
</script>
<style lang="stylus" scoped>
.mk-dialog
> .bg
display block

View File

@ -2,7 +2,7 @@
<mk-window ref="window" @closed="destroyDom" width="800px" height="500px" :popout-url="popout">
<template slot="header">
<p v-if="usage" :class="$style.info"><b>{{ usage.toFixed(1) }}%</b> %i18n:@used%</p>
<span :class="$style.title">%fa:cloud%%i18n:common.drive%</span>
<span :class="$style.title"><fa icon="cloud"/>%i18n:common.drive%</span>
</template>
<mk-drive :class="$style.browser" multiple :init-folder="folder" ref="browser"/>
</mk-window>
@ -39,7 +39,7 @@ export default Vue.extend({
<style lang="stylus" module>
.title
> [data-fa]
> [data-icon]
margin-right 4px
.info

View File

@ -71,27 +71,27 @@ export default Vue.extend({
contextmenu((this as any).os)(e, [{
type: 'item',
text: '%i18n:@contextmenu.rename%',
icon: '%fa:i-cursor%',
icon: 'i-cursor',
action: this.rename
}, {
type: 'item',
text: this.file.isSensitive ? '%i18n:@contextmenu.unmark-as-sensitive%' : '%i18n:@contextmenu.mark-as-sensitive%',
icon: this.file.isSensitive ? '%fa:R eye%' : '%fa:R eye-slash%',
icon: this.file.isSensitive ? ['far', 'eye'] : ['far', 'eye-slash'],
action: this.toggleSensitive
}, null, {
type: 'item',
text: '%i18n:@contextmenu.copy-url%',
icon: '%fa:link%',
icon: 'link',
action: this.copyUrl
}, {
type: 'link',
href: `${this.file.url}?download`,
text: '%i18n:@contextmenu.download%',
icon: '%fa:download%',
icon: 'download',
}, null, {
type: 'item',
text: '%i18n:common.delete%',
icon: '%fa:R trash-alt%',
icon: ['far', 'trash-alt'],
action: this.deleteFile
}, null, {
type: 'nest',
@ -170,7 +170,7 @@ export default Vue.extend({
copyUrl() {
copyToClipboard(this.file.url);
(this as any).apis.dialog({
title: '%fa:check%%i18n:@contextmenu.copied%',
title: '<fa icon="check"/>%i18n:@contextmenu.copied%',
text: '%i18n:@contextmenu.copied-url-to-clipboard%',
actions: [{
text: '%i18n:common.ok%'

View File

@ -16,8 +16,8 @@
:title="title"
>
<p class="name">
<template v-if="hover">%fa:R folder-open .fw%</template>
<template v-if="!hover">%fa:R folder .fw%</template>
<template v-if="hover"><fa :icon="['far', 'folder-open']" fixed-width/></template>
<template v-if="!hover"><fa :icon="['far', 'folder']" fixed-width/></template>
{{ folder.name }}
</p>
</div>
@ -55,22 +55,22 @@ export default Vue.extend({
contextmenu((this as any).os)(e, [{
type: 'item',
text: '%i18n:@contextmenu.move-to-this-folder%',
icon: '%fa:arrow-right%',
icon: 'arrow-right',
action: this.go
}, {
type: 'item',
text: '%i18n:@contextmenu.show-in-new-window%',
icon: '%fa:R window-restore%',
icon: ['far', 'window-restore'],
action: this.newWindow
}, null, {
type: 'item',
text: '%i18n:@contextmenu.rename%',
icon: '%fa:i-cursor%',
icon: 'i-cursor',
action: this.rename
}, null, {
type: 'item',
text: '%i18n:common.delete%',
icon: '%fa:R trash-alt%',
icon: ['far', 'trash-alt'],
action: this.deleteFolder
}], {
closed: () => {
@ -155,7 +155,7 @@ export default Vue.extend({
switch (err) {
case 'detected-circular-definition':
(this as any).apis.dialog({
title: '%fa:exclamation-triangle%%i18n:@unable-to-process%',
title: '<fa icon="exclamation-triangle"/>%i18n:@unable-to-process%',
text: '%i18n:@circular-reference-detected%',
actions: [{
text: '%i18n:common.ok%'
@ -255,7 +255,7 @@ export default Vue.extend({
font-size 0.9em
color var(--desktopDriveFolderFg)
> [data-fa]
> [data-icon]
margin-right 4px
margin-left 2px
text-align left

View File

@ -7,7 +7,7 @@
@dragleave="onDragleave"
@drop.stop="onDrop"
>
<template v-if="folder == null">%fa:cloud%</template>
<i v-if="folder == null" class="cloud"><fa icon="cloud"/></i>
<span>{{ folder == null ? '%i18n:common.drive%' : folder.name }}</span>
</div>
</template>
@ -110,7 +110,7 @@ export default Vue.extend({
&[data-draghover]
background #eee
[data-fa].cloud
i.cloud
margin-right 4px
</style>

View File

@ -4,10 +4,10 @@
<div class="path" @contextmenu.prevent.stop="() => {}">
<x-nav-folder :class="{ current: folder == null }"/>
<template v-for="folder in hierarchyFolders">
<span class="separator">%fa:angle-right%</span>
<span class="separator"><fa icon="angle-right"/></span>
<x-nav-folder :folder="folder" :key="folder.id"/>
</template>
<span class="separator" v-if="folder != null">%fa:angle-right%</span>
<span class="separator" v-if="folder != null"><fa icon="angle-right"/></span>
<span class="folder current" v-if="folder != null">{{ folder.name }}</span>
</div>
<!--
@ -138,17 +138,17 @@ export default Vue.extend({
contextmenu((this as any).os)(e, [{
type: 'item',
text: '%i18n:@contextmenu.create-folder%',
icon: '%fa:R folder%',
icon: ['far', 'folder'],
action: this.createFolder
}, {
type: 'item',
text: '%i18n:@contextmenu.upload%',
icon: '%fa:upload%',
icon: 'upload',
action: this.selectLocalFile
}, {
type: 'item',
text: '%i18n:@contextmenu.url-upload%',
icon: '%fa:cloud-upload-alt%',
icon: 'cloud-upload-alt',
action: this.urlUpload
}]);
},
@ -313,7 +313,7 @@ export default Vue.extend({
switch (err) {
case 'detected-circular-definition':
(this as any).apis.dialog({
title: '%fa:exclamation-triangle%%i18n:@unable-to-process%',
title: '<fa icon="exclamation-triangle"/>%i18n:@unable-to-process%',
text: '%i18n:@circular-reference-detected%',
actions: [{
text: '%i18n:common.ok%'
@ -343,7 +343,7 @@ export default Vue.extend({
});
(this as any).apis.dialog({
title: '%fa:check%%i18n:@url-upload-requested%',
title: '<fa icon="check"/>%i18n:@url-upload-requested%',
text: '%i18n:@may-take-time%',
actions: [{
text: '%i18n:common.ok%'
@ -359,7 +359,7 @@ export default Vue.extend({
}).then(name => {
(this as any).api('drive/folders/create', {
name: name,
folderId: this.folder ? this.folder.id : undefined
parentId: this.folder ? this.folder.id : undefined
}).then(folder => {
this.addFolder(folder, true);
});
@ -613,9 +613,6 @@ export default Vue.extend({
line-height 38px
cursor pointer
i
margin-right 4px
*
pointer-events none
@ -635,7 +632,7 @@ export default Vue.extend({
opacity 0.5
cursor default
> [data-fa]
> [data-icon]
margin 0
> .search

View File

@ -5,13 +5,13 @@
:disabled="wait"
>
<template v-if="!wait">
<template v-if="u.hasPendingFollowRequestFromYou && u.isLocked">%fa:hourglass-half%<template v-if="size == 'big'"> %i18n:@request-pending%</template></template>
<template v-else-if="u.hasPendingFollowRequestFromYou && !u.isLocked">%fa:hourglass-start%<template v-if="size == 'big'"> %i18n:@follow-processing%</template></template>
<template v-else-if="u.isFollowing">%fa:minus%<template v-if="size == 'big'"> %i18n:@following%</template></template>
<template v-else-if="!u.isFollowing && u.isLocked">%fa:plus%<template v-if="size == 'big'"> %i18n:@follow-request%</template></template>
<template v-else-if="!u.isFollowing && !u.isLocked">%fa:plus%<template v-if="size == 'big'"> %i18n:@follow%</template></template>
<template v-if="u.hasPendingFollowRequestFromYou && u.isLocked"><fa icon="hourglass-half"/><template v-if="size == 'big'"> %i18n:@request-pending%</template></template>
<template v-else-if="u.hasPendingFollowRequestFromYou && !u.isLocked"><fa icon="hourglass-start"/><template v-if="size == 'big'"> %i18n:@follow-processing%</template></template>
<template v-else-if="u.isFollowing"><fa icon="minus"/><template v-if="size == 'big'"> %i18n:@following%</template></template>
<template v-else-if="!u.isFollowing && u.isLocked"><fa icon="plus"/><template v-if="size == 'big'"> %i18n:@follow-request%</template></template>
<template v-else-if="!u.isFollowing && !u.isLocked"><fa icon="plus"/><template v-if="size == 'big'"> %i18n:@follow%</template></template>
</template>
<template v-else>%fa:spinner .pulse .fw%</template>
<template v-else><fa icon="spinner .pulse" fixed-width/></template>
</button>
</template>

View File

@ -11,9 +11,9 @@
</div>
</div>
<p class="empty" v-if="!fetching && users.length == 0">%i18n:@empty%</p>
<p class="fetching" v-if="fetching">%fa:spinner .pulse .fw%%i18n:@fetching%<mk-ellipsis/></p>
<p class="fetching" v-if="fetching"><fa icon="spinner .pulse" fixed-width/>%i18n:@fetching%<mk-ellipsis/></p>
<a class="refresh" @click="refresh">%i18n:@refresh%</a>
<button class="close" @click="destroyDom()" title="%i18n:@close%">%fa:times%</button>
<button class="close" @click="destroyDom()" title="%i18n:@close%"><fa icon="times"/></button>
</div>
</template>
@ -124,7 +124,7 @@ export default Vue.extend({
text-align center
color #aaa
> [data-fa]
> [data-icon]
margin-right 4px
> .refresh
@ -155,7 +155,7 @@ export default Vue.extend({
&:active
color #222
> [data-fa]
> [data-icon]
padding 14px
</style>

View File

@ -1,7 +1,7 @@
<template>
<mk-window ref="window" width="500px" height="560px" :popout-url="popout" @closed="destroyDom">
<span slot="header" :class="$style.header">%fa:gamepad%%i18n:@game%</span>
<mk-reversi :class="$style.content" @gamed="g => game = g"/>
<span slot="header" :class="$style.header"><fa icon="gamepad"/>%i18n:@game%</span>
<x-reversi :class="$style.content" @gamed="g => game = g"/>
</mk-window>
</template>
@ -10,6 +10,9 @@ import Vue from 'vue';
import { url } from '../../../config';
export default Vue.extend({
components: {
XReversi: () => import('../../../common/views/components/games/reversi/reversi.vue')
},
data() {
return {
game: null
@ -27,7 +30,7 @@ export default Vue.extend({
<style lang="stylus" module>
.header
> [data-fa]
> [data-icon]
margin-right 4px
.content

View File

@ -1,7 +1,7 @@
<template>
<div class="mk-home" :data-customize="customize">
<div class="customize" v-if="customize">
<router-link to="/">%fa:check%%i18n:@done%</router-link>
<router-link to="/"><fa icon="check"/>%i18n:@done%</router-link>
<div>
<div class="adder">
<p>%i18n:@add-widget%</p>
@ -185,7 +185,7 @@ export default Vue.extend({
methods: {
hint() {
(this as any).apis.dialog({
title: '%fa:info-circle%%i18n:common.customization-tips.title%',
title: '<fa icon="info-circle"/>%i18n:common.customization-tips.title%',
text: '<p>%i18n:common.customization-tips.paragraph1%</p>' +
'<p>%i18n:common.customization-tips.paragraph2%</p>' +
'<p>%i18n:common.customization-tips.paragraph3%</p>' +
@ -299,7 +299,7 @@ export default Vue.extend({
background var(--primaryDarken10)
transition background 0s ease
> [data-fa]
> [data-icon]
margin-right 8px
> div

View File

@ -1,7 +1,7 @@
<template>
<mk-window ref="window" is-modal width="500px" @before-close="beforeClose" @closed="destroyDom">
<span slot="header" :class="$style.header">
%fa:i-cursor%{{ title }}
<fa icon="i-cursor"/>{{ title }}
</span>
<div :class="$style.body">
@ -76,10 +76,8 @@ export default Vue.extend({
<style lang="stylus" module>
.header
> [data-fa]
> [data-icon]
margin-right 4px
.body

View File

@ -1,7 +1,7 @@
<template>
<div class="ldwbgwstjsdgcjruamauqdrffetqudry" v-if="image.isSensitive && hide && !$store.state.device.alwaysShowNsfw" @click="hide = false">
<div>
<b>%fa:exclamation-triangle% %i18n:@sensitive%</b>
<b><fa icon="exclamation-triangle"/> %i18n:@sensitive%</b>
<span>%i18n:@click-to-show%</span>
</div>
</div>

View File

@ -1,7 +1,7 @@
<template>
<div class="uofhebxjdgksfmltszlxurtjnjjsvioh" v-if="video.isSensitive && hide" @click="hide = false">
<div>
<b>%fa:exclamation-triangle% %i18n:@sensitive%</b>
<b><fa icon="exclamation-triangle"/> %i18n:@sensitive%</b>
<span>%i18n:@click-to-show%</span>
</div>
</div>
@ -12,7 +12,7 @@
@click.prevent="onClick"
:title="video.name"
>
%fa:R play-circle%
<fa :icon="['far', 'play-circle']"/>
</a>
</div>
</template>

View File

@ -1,6 +1,6 @@
<template>
<mk-window ref="window" width="500px" height="560px" :popout-url="popout" @closed="destroyDom">
<span slot="header" :class="$style.header">%fa:comments%%i18n:@title% {{ user | userName }}</span>
<span slot="header" :class="$style.header"><fa icon="comments"/>%i18n:@title% {{ user | userName }}</span>
<mk-messaging-room :user="user" :class="$style.content"/>
</mk-window>
</template>
@ -22,7 +22,7 @@ export default Vue.extend({
<style lang="stylus" module>
.header
> [data-fa]
> [data-icon]
margin-right 4px
.content

View File

@ -1,6 +1,6 @@
<template>
<mk-window ref="window" width="500px" height="560px" @closed="destroyDom">
<span slot="header" :class="$style.header">%fa:comments%%i18n:@title%</span>
<span slot="header" :class="$style.header"><fa icon="comments"/>%i18n:@title%</span>
<mk-messaging :class="$style.content" @navigate="navigate"/>
</mk-window>
</template>
@ -22,7 +22,7 @@ export default Vue.extend({
<style lang="stylus" module>
.header
> [data-fa]
> [data-icon]
margin-right 4px
.content

View File

@ -7,8 +7,8 @@
@click="fetchConversation"
:disabled="conversationFetching"
>
<template v-if="!conversationFetching">%fa:ellipsis-v%</template>
<template v-if="conversationFetching">%fa:spinner .pulse%</template>
<template v-if="!conversationFetching"><fa icon="ellipsis-v"/></template>
<template v-if="conversationFetching"><fa icon="spinner .pulse"/></template>
</button>
<div class="conversation">
<x-sub v-for="note in conversation" :key="note.id" :note="note"/>
@ -19,7 +19,7 @@
<div class="renote" v-if="isRenote">
<p>
<mk-avatar class="avatar" :user="note.user"/>
%fa:retweet%
<fa icon="retweet"/>
<router-link class="name" :href="note.user | userPage">{{ note.user | userName }}</router-link>
<span>{{ '%i18n:@reposted-by%'.substr(0, '%i18n:@reposted-by%'.indexOf('{')) }}</span>
<a class="name" :href="note.user | userPage" v-user-preview="note.userId">{{ note.user | userName }}</a>
@ -52,7 +52,7 @@
</div>
<mk-poll v-if="p.poll" :note="p"/>
<mk-url-preview v-for="url in urls" :url="url" :key="url" :detail="true"/>
<a class="location" v-if="p.geo" :href="`https://maps.google.com/maps?q=${p.geo.coordinates[1]},${p.geo.coordinates[0]}`" target="_blank">%fa:map-marker-alt% %i18n:@location%</a>
<a class="location" v-if="p.geo" :href="`https://maps.google.com/maps?q=${p.geo.coordinates[1]},${p.geo.coordinates[0]}`" target="_blank"><fa icon="map-marker-alt"/> %i18n:@location%</a>
<div class="map" v-if="p.geo" ref="map"></div>
<div class="renote" v-if="p.renote">
<mk-note-preview :note="p.renote"/>
@ -62,18 +62,18 @@
<footer>
<mk-reactions-viewer :note="p"/>
<button class="replyButton" @click="reply" title="">
<template v-if="p.reply">%fa:reply-all%</template>
<template v-else>%fa:reply%</template>
<template v-if="p.reply"><fa icon="reply-all"/></template>
<template v-else><fa icon="reply"/></template>
<p class="count" v-if="p.repliesCount > 0">{{ p.repliesCount }}</p>
</button>
<button class="renoteButton" @click="renote" title="%i18n:@renote%">
%fa:retweet%<p class="count" v-if="p.renoteCount > 0">{{ p.renoteCount }}</p>
<fa icon="retweet"/><p class="count" v-if="p.renoteCount > 0">{{ p.renoteCount }}</p>
</button>
<button class="reactionButton" :class="{ reacted: p.myReaction != null }" @click="react" ref="reactButton" title="%i18n:@add-reaction%">
%fa:plus%<p class="count" v-if="p.reactions_count > 0">{{ p.reactions_count }}</p>
<fa icon="plus"/><p class="count" v-if="p.reactions_count > 0">{{ p.reactions_count }}</p>
</button>
<button @click="menu" ref="menuButton">
%fa:ellipsis-h%
<fa icon="ellipsis-h"/>
</button>
</footer>
</article>
@ -278,7 +278,7 @@ export default Vue.extend({
margin 0 8px 0 0
border-radius 6px
[data-fa]
[data-icon]
margin-right 4px
.name

View File

@ -15,7 +15,7 @@
</div>
<div class="renote" v-if="isRenote">
<mk-avatar class="avatar" :user="note.user"/>
%fa:retweet%
<fa icon="retweet"/>
<span>{{ '%i18n:@reposted-by%'.substr(0, '%i18n:@reposted-by%'.indexOf('{')) }}</span>
<router-link class="name" :to="note.user | userPage" v-user-preview="note.userId">{{ note.user | userName }}</router-link>
<span>{{ '%i18n:@reposted-by%'.substr('%i18n:@reposted-by%'.indexOf('}') + 1) }}</span>
@ -33,7 +33,7 @@
<div class="content" v-show="appearNote.cw == null || showContent">
<div class="text">
<span v-if="appearNote.isHidden" style="opacity: 0.5">%i18n:@private%</span>
<a class="reply" v-if="appearNote.reply">%fa:reply%</a>
<a class="reply" v-if="appearNote.reply"><fa icon="reply"/></a>
<misskey-flavored-markdown v-if="appearNote.text" :text="appearNote.text" :i="$store.state.i" :class="$style.text" :customEmojis="appearNote.emojis"/>
<a class="rp" v-if="appearNote.renote">RN:</a>
</div>
@ -41,7 +41,7 @@
<mk-media-list :media-list="appearNote.files"/>
</div>
<mk-poll v-if="appearNote.poll" :note="appearNote" ref="pollViewer"/>
<a class="location" v-if="appearNote.geo" :href="`https://maps.google.com/maps?q=${appearNote.geo.coordinates[1]},${appearNote.geo.coordinates[0]}`" target="_blank">%fa:map-marker-alt% 位置情報</a>
<a class="location" v-if="appearNote.geo" :href="`https://maps.google.com/maps?q=${appearNote.geo.coordinates[1]},${appearNote.geo.coordinates[0]}`" target="_blank"><fa icon="map-marker-alt"/> 位置情報</a>
<div class="renote" v-if="appearNote.renote"><mk-note-preview :note="appearNote.renote" :mini="mini"/></div>
<mk-url-preview v-for="url in urls" :url="url" :key="url" :mini="mini"/>
</div>
@ -49,18 +49,18 @@
<footer>
<mk-reactions-viewer :note="appearNote" ref="reactionsViewer"/>
<button class="replyButton" @click="reply()" title="%i18n:@reply%">
<template v-if="appearNote.reply">%fa:reply-all%</template>
<template v-else>%fa:reply%</template>
<template v-if="appearNote.reply"><fa icon="reply-all"/></template>
<template v-else><fa icon="reply"/></template>
<p class="count" v-if="appearNote.repliesCount > 0">{{ appearNote.repliesCount }}</p>
</button>
<button class="renoteButton" @click="renote()" title="%i18n:@renote%">
%fa:retweet%<p class="count" v-if="appearNote.renoteCount > 0">{{ appearNote.renoteCount }}</p>
<fa icon="retweet"/><p class="count" v-if="appearNote.renoteCount > 0">{{ appearNote.renoteCount }}</p>
</button>
<button class="reactionButton" :class="{ reacted: appearNote.myReaction != null }" @click="react()" ref="reactButton" title="%i18n:@add-reaction%">
%fa:plus%<p class="count" v-if="appearNote.reactions_count > 0">{{ appearNote.reactions_count }}</p>
<fa icon="plus"/><p class="count" v-if="appearNote.reactions_count > 0">{{ appearNote.reactions_count }}</p>
</button>
<button @click="menu()" ref="menuButton">
%fa:ellipsis-h%
<fa icon="ellipsis-h"/>
</button>
</footer>
</div>
@ -190,7 +190,7 @@ export default Vue.extend({
margin 0 8px 0 0
border-radius 6px
[data-fa]
[data-icon]
margin-right 4px
> span

View File

@ -17,8 +17,8 @@
<template v-for="(note, i) in _notes">
<x-note :note="note" :key="note.id" @update:note="onNoteUpdated(i, $event)" ref="note"/>
<p class="date" :key="note.id + '_date'" v-if="i != notes.length - 1 && note._date != _notes[i + 1]._date">
<span>%fa:angle-up%{{ note._datetext }}</span>
<span>%fa:angle-down%{{ _notes[i + 1]._datetext }}</span>
<span><fa icon="angle-up"/>{{ note._datetext }}</span>
<span><fa icon="angle-down"/>{{ _notes[i + 1]._datetext }}</span>
</p>
</template>
</component>
@ -26,7 +26,7 @@
<footer v-if="more">
<button @click="loadMore" :disabled="moreFetching" :style="{ cursor: moreFetching ? 'wait' : 'pointer' }">
<template v-if="!moreFetching">%i18n:@load-more%</template>
<template v-if="moreFetching">%fa:spinner .pulse .fw%</template>
<template v-if="moreFetching"><fa icon="spinner .pulse" fixed-width/></template>
</button>
</footer>
</div>
@ -230,7 +230,7 @@ export default Vue.extend({
span
margin 0 16px
[data-fa]
[data-icon]
margin-right 8px
> .newer-indicator

View File

@ -21,7 +21,7 @@
<router-link :to="notification.user | userPage" v-user-preview="notification.user.id">{{ notification.user | userName }}</router-link>
</p>
<router-link class="note-ref" :to="notification.note | notePage">
%fa:quote-left%{{ getNoteSummary(notification.note) }}%fa:quote-right%
<fa icon="quote-left"/>{{ getNoteSummary(notification.note) }}<fa icon="quote-right"/>
</router-link>
</div>
</template>
@ -29,11 +29,11 @@
<template v-if="notification.type == 'renote'">
<mk-avatar class="avatar" :user="notification.note.user"/>
<div class="text">
<p>%fa:retweet%
<p><fa icon="retweet"/>
<router-link :to="notification.note.user | userPage" v-user-preview="notification.note.userId">{{ notification.note.user | userName }}</router-link>
</p>
<router-link class="note-ref" :to="notification.note | notePage">
%fa:quote-left%{{ getNoteSummary(notification.note.renote) }}%fa:quote-right%
<fa icon="quote-left"/>{{ getNoteSummary(notification.note.renote) }}<fa icon="quote-right"/>
</router-link>
</div>
</template>
@ -41,7 +41,7 @@
<template v-if="notification.type == 'quote'">
<mk-avatar class="avatar" :user="notification.note.user"/>
<div class="text">
<p>%fa:quote-left%
<p><fa icon="quote-left"/>
<router-link :to="notification.note.user | userPage" v-user-preview="notification.note.userId">{{ notification.note.user | userName }}</router-link>
</p>
<router-link class="note-preview" :to="notification.note | notePage">{{ getNoteSummary(notification.note) }}</router-link>
@ -51,7 +51,7 @@
<template v-if="notification.type == 'follow'">
<mk-avatar class="avatar" :user="notification.user"/>
<div class="text">
<p>%fa:user-plus%
<p><fa icon="user-plus"/>
<router-link :to="notification.user | userPage" v-user-preview="notification.user.id">{{ notification.user | userName }}</router-link>
</p>
</div>
@ -60,7 +60,7 @@
<template v-if="notification.type == 'receiveFollowRequest'">
<mk-avatar class="avatar" :user="notification.user"/>
<div class="text">
<p>%fa:user-clock%
<p><fa icon="user-clock"/>
<router-link :to="notification.user | userPage" v-user-preview="notification.user.id">{{ notification.user | userName }}</router-link>
</p>
</div>
@ -69,7 +69,7 @@
<template v-if="notification.type == 'reply'">
<mk-avatar class="avatar" :user="notification.note.user"/>
<div class="text">
<p>%fa:reply%
<p><fa icon="reply"/>
<router-link :to="notification.note.user | userPage" v-user-preview="notification.note.userId">{{ notification.note.user | userName }}</router-link>
</p>
<router-link class="note-preview" :to="notification.note | notePage">{{ getNoteSummary(notification.note) }}</router-link>
@ -79,7 +79,7 @@
<template v-if="notification.type == 'mention'">
<mk-avatar class="avatar" :user="notification.note.user"/>
<div class="text">
<p>%fa:at%
<p><fa icon="at"/>
<router-link :to="notification.note.user | userPage" v-user-preview="notification.note.userId">{{ notification.note.user | userName }}</router-link>
</p>
<a class="note-preview" :href="notification.note | notePage">{{ getNoteSummary(notification.note) }}</a>
@ -89,23 +89,23 @@
<template v-if="notification.type == 'poll_vote'">
<mk-avatar class="avatar" :user="notification.user"/>
<div class="text">
<p>%fa:chart-pie%<a :href="notification.user | userPage" v-user-preview="notification.user.id">{{ notification.user | userName }}</a></p>
<p><fa icon="chart-pie"/><a :href="notification.user | userPage" v-user-preview="notification.user.id">{{ notification.user | userName }}</a></p>
<router-link class="note-ref" :to="notification.note | notePage">
%fa:quote-left%{{ getNoteSummary(notification.note) }}%fa:quote-right%
<fa icon="quote-left"/>{{ getNoteSummary(notification.note) }}<fa icon="quote-right"/>
</router-link>
</div>
</template>
</div>
<p class="date" v-if="i != notifications.length - 1 && notification._date != _notifications[i + 1]._date" :key="notification.id + '-time'">
<span>%fa:angle-up%{{ notification._datetext }}</span>
<span>%fa:angle-down%{{ _notifications[i + 1]._datetext }}</span>
<span><fa icon="angle-up"/>{{ notification._datetext }}</span>
<span><fa icon="angle-down"/>{{ _notifications[i + 1]._datetext }}</span>
</p>
</template>
</component>
</div>
<button class="more" :class="{ fetching: fetchingMoreNotifications }" v-if="moreNotifications" @click="fetchMoreNotifications" :disabled="fetchingMoreNotifications">
<template v-if="fetchingMoreNotifications">%fa:spinner .pulse .fw%</template>{{ fetchingMoreNotifications ? '%i18n:common.loading%' : '%i18n:@more%' }}
<template v-if="fetchingMoreNotifications"><fa icon="spinner .pulse" fixed-width/></template>{{ fetchingMoreNotifications ? '%i18n:common.loading%' : '%i18n:@more%' }}
</button>
<p class="empty" v-if="notifications.length == 0 && !fetching">%i18n:@empty%</p>
</div>
@ -255,7 +255,7 @@ export default Vue.extend({
p
margin 0
i, .mk-reaction-icon
[data-icon], .mk-reaction-icon
margin-right 4px
.note-preview
@ -264,7 +264,7 @@ export default Vue.extend({
.note-ref
color var(--noteText)
[data-fa]
[data-icon]
font-size 1em
font-weight normal
font-style normal
@ -272,19 +272,19 @@ export default Vue.extend({
margin-right 3px
&.renote, &.quote
.text p i
.text p [data-icon]
color #77B255
&.follow
.text p i
.text p [data-icon]
color #53c7ce
&.receiveFollowRequest
.text p i
.text p [data-icon]
color #888
&.reply, &.mention
.text p i
.text p [data-icon]
color #555
> .date
@ -300,7 +300,7 @@ export default Vue.extend({
span
margin 0 16px
[data-fa]
[data-icon]
margin-right 8px
> .more
@ -319,7 +319,7 @@ export default Vue.extend({
&.fetching
cursor wait
> [data-fa]
> [data-icon]
margin-right 4px
> .empty

View File

@ -1,7 +1,7 @@
<template>
<mk-window class="mk-post-form-window" ref="window" is-modal @closed="onWindowClosed" :animation="animation">
<span slot="header" class="mk-post-form-window--header">
<span class="icon" v-if="geo">%fa:map-marker-alt%</span>
<span class="icon" v-if="geo"><fa icon="map-marker-alt"/></span>
<span v-if="!reply">%i18n:@note%</span>
<span v-if="reply">%i18n:@reply%</span>
<span class="count" v-if="files.length != 0">{{ '%i18n:@attaches%'.replace('{}', files.length) }}</span>

View File

@ -32,18 +32,18 @@
<mk-poll-editor v-if="poll" ref="poll" @destroyed="poll = false" @updated="saveDraft()"/>
</div>
<mk-uploader ref="uploader" @uploaded="attachMedia" @change="onChangeUploadings"/>
<button class="upload" title="%i18n:@attach-media-from-local%" @click="chooseFile">%fa:upload%</button>
<button class="drive" title="%i18n:@attach-media-from-drive%" @click="chooseFileFromDrive">%fa:cloud%</button>
<button class="kao" title="%i18n:@insert-a-kao%" @click="kao">%fa:R smile%</button>
<button class="poll" title="%i18n:@create-poll%" @click="poll = !poll">%fa:chart-pie%</button>
<button class="poll" title="%i18n:@hide-contents%" @click="useCw = !useCw">%fa:eye-slash%</button>
<button class="geo" title="%i18n:@attach-location-information%" @click="geo ? removeGeo() : setGeo()">%fa:map-marker-alt%</button>
<button class="upload" title="%i18n:@attach-media-from-local%" @click="chooseFile"><fa icon="upload"/></button>
<button class="drive" title="%i18n:@attach-media-from-drive%" @click="chooseFileFromDrive"><fa icon="cloud"/></button>
<button class="kao" title="%i18n:@insert-a-kao%" @click="kao"><fa :icon="['far', 'smile']"/></button>
<button class="poll" title="%i18n:@create-poll%" @click="poll = !poll"><fa icon="chart-pie"/></button>
<button class="poll" title="%i18n:@hide-contents%" @click="useCw = !useCw"><fa icon="eye-slash"/></button>
<button class="geo" title="%i18n:@attach-location-information%" @click="geo ? removeGeo() : setGeo()"><fa icon="map-marker-alt"/></button>
<button class="visibility" title="%i18n:@visibility%" @click="setVisibility" ref="visibilityButton">
<span v-if="visibility === 'public'">%fa:globe%</span>
<span v-if="visibility === 'home'">%fa:home%</span>
<span v-if="visibility === 'followers'">%fa:unlock%</span>
<span v-if="visibility === 'specified'">%fa:envelope%</span>
<span v-if="visibility === 'private'">%fa:lock%</span>
<span v-if="visibility === 'public'"><fa icon="globe"/></span>
<span v-if="visibility === 'home'"><fa icon="home"/></span>
<span v-if="visibility === 'followers'"><fa icon="unlock"/></span>
<span v-if="visibility === 'specified'"><fa icon="envelope"/></span>
<span v-if="visibility === 'private'"><fa icon="lock"/></span>
</button>
<p class="text-count" :class="{ over: this.trimmedLength(text) > this.maxNoteTextLength }">{{ this.maxNoteTextLength - this.trimmedLength(text) }}</p>
<button :class="{ posting }" class="submit" :disabled="!canPost" @click="post">

View File

@ -1,6 +1,6 @@
<template>
<mk-window ref="window" is-modal width="450px" height="500px" @closed="destroyDom">
<span slot="header">%fa:envelope R% %i18n:@title%</span>
<span slot="header"><fa :icon="['far', 'envelope']"/> %i18n:@title%</span>
<div class="slpqaxdoxhvglersgjukmvizkqbmbokc">
<div v-for="req in requests">

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