Compare commits

..

100 Commits

Author SHA1 Message Date
syuilo
48dc56e834 10.64.2 2018-12-17 17:27:07 +09:00
Acid Chicken (硫酸鶏)
2c33bd6e31 Update README.md [AUTOGEN] (#3641) 2018-12-17 17:26:02 +09:00
syuilo
b6524616bc Clean up 2018-12-17 17:21:45 +09:00
syuilo
7e2b70f912 [Client] UIの動きを減らすオプションが一部のアニメーションに適用されなかったのを修正
Resolve #3632
2018-12-17 17:21:36 +09:00
syuilo
4f071a66b6 10.64.1 2018-12-17 03:33:22 +09:00
syuilo
39f2303429 Merge pull request #3631 from syuilo/l10n_develop
New Crowdin translations
2018-12-17 03:31:49 +09:00
syuilo
cacf072027 Merge branch 'develop' of https://github.com/syuilo/misskey into develop 2018-12-17 03:31:31 +09:00
Acid Chicken (硫酸鶏)
6ab1fdfe1a Update README.md [AUTOGEN] (#3639) 2018-12-17 03:31:19 +09:00
syuilo
6e5c93f926 [Client] Add animation 🎨 2018-12-17 03:29:57 +09:00
syuilo
1670737075 [API] Resolve #3637 2018-12-17 01:43:34 +09:00
syuilo
fee235c4e4 Update README.md 2018-12-16 17:24:52 +09:00
syuilo
7a39d489f2 New translations ja-JP.yml (Norwegian) 2018-12-16 16:23:07 +09:00
syuilo
7c634218d1 New translations ja-JP.yml (Dutch) 2018-12-16 16:23:02 +09:00
syuilo
2704c5be73 New translations ja-JP.yml (Japanese, Kansai) 2018-12-16 16:22:58 +09:00
syuilo
489b51ba9f New translations ja-JP.yml (Spanish) 2018-12-16 16:22:52 +09:00
syuilo
21807c29f1 New translations ja-JP.yml (Russian) 2018-12-16 16:22:48 +09:00
syuilo
3bc62fe3eb New translations ja-JP.yml (Portuguese) 2018-12-16 16:22:43 +09:00
syuilo
ba0e3c4a5f New translations ja-JP.yml (Polish) 2018-12-16 16:22:38 +09:00
syuilo
9ec1fb5e37 New translations ja-JP.yml (Korean) 2018-12-16 16:22:33 +09:00
syuilo
d708409462 New translations ja-JP.yml (Italian) 2018-12-16 16:22:29 +09:00
syuilo
07d05d4f86 New translations ja-JP.yml (German) 2018-12-16 16:22:24 +09:00
syuilo
bbdb2ebb40 New translations ja-JP.yml (French) 2018-12-16 16:22:20 +09:00
syuilo
f7908ba098 New translations ja-JP.yml (English) 2018-12-16 16:22:15 +09:00
syuilo
f2fda3075e New translations ja-JP.yml (Chinese Simplified) 2018-12-16 16:22:11 +09:00
syuilo
1338a68979 New translations ja-JP.yml (Catalan) 2018-12-16 16:22:05 +09:00
syuilo
e7da505fb3 [Client] Bug fix and clean up 2018-12-16 16:12:41 +09:00
syuilo
5a9228372f New translations ja-JP.yml (Korean) 2018-12-16 13:31:39 +09:00
syuilo
c4a6ba9097 New translations ja-JP.yml (Korean) 2018-12-16 12:13:35 +09:00
syuilo
d5871b408b 10.64.0 2018-12-16 11:36:44 +09:00
syuilo
7b3338e373 Merge branch 'develop' of https://github.com/syuilo/misskey into develop 2018-12-16 11:32:30 +09:00
syuilo
d18ee12d2f [Client] Add some animations 🎨 2018-12-16 11:32:20 +09:00
dependabot[bot]
ca9cc97940 Update minio requirement from 7.0.1 to 7.0.2 (#3606)
Updates the requirements on [minio](https://github.com/minio/minio-js) to permit the latest version.
- [Release notes](https://github.com/minio/minio-js/releases)
- [Commits](https://github.com/minio/minio-js/commits/7.0.2)

Signed-off-by: dependabot[bot] <support@dependabot.com>
2018-12-16 10:30:33 +09:00
syuilo
a70070ac7d Merge branch 'develop' of https://github.com/syuilo/misskey into develop 2018-12-16 10:30:06 +09:00
syuilo
069d99b320 Update dependency 🚀 2018-12-16 10:29:55 +09:00
syuilo
37d350dcad Merge pull request #3601 from syuilo/l10n_develop
New Crowdin translations
2018-12-16 10:24:04 +09:00
syuilo
8653e09b59 [Client] Add particle effect 2018-12-16 10:20:46 +09:00
syuilo
7cd2d59576 [Client] Fix bug 2018-12-16 09:03:07 +09:00
Acid Chicken (硫酸鶏)
a0839de38f Add 'twitter:creator' meta data in user pages (#3618)
* Update user.pug

* Update user.pug

* Update note.pug

* Update user.pug

* Update note.pug

* Update note.pug
2018-12-16 08:49:38 +09:00
syuilo
b7c5c71c6f [Client] Resolve #2951
あと検索フォームでサジェストを有効に
2018-12-16 08:45:10 +09:00
syuilo
adab0adbdd New translations ja-JP.yml (English) 2018-12-16 07:31:43 +09:00
MeiMei
2faa58928f Format uptimes (#3629)
* Format uptime

* 逆だわ

* ザ

* 1個多い

* Fix comment
2018-12-16 07:06:43 +09:00
MeiMei
ffb80efe21 Return 404 for invalid Object ID (#3627)
* Update activitypub.ts

* Update activitypub.ts

* Update featured.ts

* Update followers.ts

* Update following.ts

* Update outbox.ts

* Fix following, outbox
2018-12-16 01:44:59 +09:00
syuilo
6f959218ef Update analog-clock.vue 2018-12-15 23:34:46 +09:00
syuilo
be1125dcb9 OGP向けにインスタンスのバナー画像を提供するように 2018-12-15 23:19:04 +09:00
Acid Chicken (硫酸鶏)
9ab34c2301 Update index.ts (#3624) 2018-12-15 20:54:34 +09:00
syuilo
0166d81d9e New translations ja-JP.yml (Polish) 2018-12-15 18:31:49 +09:00
syuilo
0b26efbd2f New translations ja-JP.yml (French) 2018-12-15 18:01:50 +09:00
syuilo
2cbaedf946 New translations ja-JP.yml (Norwegian) 2018-12-15 17:13:24 +09:00
syuilo
b66924fbe8 New translations ja-JP.yml (Dutch) 2018-12-15 17:13:19 +09:00
syuilo
8c91148954 New translations ja-JP.yml (Japanese, Kansai) 2018-12-15 17:13:13 +09:00
syuilo
be0eff3dda New translations ja-JP.yml (Spanish) 2018-12-15 17:13:08 +09:00
syuilo
85903ac9c6 New translations ja-JP.yml (Russian) 2018-12-15 17:13:04 +09:00
syuilo
dbdd778dc7 New translations ja-JP.yml (Portuguese) 2018-12-15 17:12:59 +09:00
syuilo
fc50dfd8d5 New translations ja-JP.yml (Polish) 2018-12-15 17:12:54 +09:00
syuilo
f444e132ee New translations ja-JP.yml (Korean) 2018-12-15 17:12:50 +09:00
syuilo
68f562c323 New translations ja-JP.yml (Italian) 2018-12-15 17:12:44 +09:00
syuilo
820ea69613 New translations ja-JP.yml (German) 2018-12-15 17:12:40 +09:00
syuilo
6f4b3853a1 New translations ja-JP.yml (French) 2018-12-15 17:12:33 +09:00
syuilo
a706ad0e80 New translations ja-JP.yml (English) 2018-12-15 17:12:26 +09:00
syuilo
820116affc New translations ja-JP.yml (Chinese Simplified) 2018-12-15 17:12:22 +09:00
syuilo
52650342be New translations ja-JP.yml (Catalan) 2018-12-15 17:12:16 +09:00
syuilo
85ddabdc65 Update ja-JP.yml 2018-12-15 17:09:05 +09:00
syuilo
0730cc4fa4 🎨 2018-12-15 17:01:19 +09:00
syuilo
17b6ab0ef0 🎨 2018-12-15 16:48:28 +09:00
syuilo
4e208b85bb New translations ja-JP.yml (Polish) 2018-12-15 08:51:47 +09:00
syuilo
00f8b29f6d New translations ja-JP.yml (Polish) 2018-12-15 08:41:45 +09:00
syuilo
9cf0fcadb1 New translations ja-JP.yml (Polish) 2018-12-15 08:31:50 +09:00
syuilo
c595efeead New translations ja-JP.yml (Polish) 2018-12-15 08:21:59 +09:00
syuilo
b56c6793a1 New translations ja-JP.yml (Polish) 2018-12-15 08:12:15 +09:00
syuilo
ebceffba1e Resolve #2165 2018-12-15 00:09:04 +09:00
syuilo
3ae42d9b85 🎨 2018-12-14 23:35:07 +09:00
syuilo
796237b3c6 Implement admin drive page 2018-12-14 19:09:11 +09:00
syuilo
cb7a97ee4c New translations ja-JP.yml (Korean) 2018-12-14 07:32:03 +09:00
syuilo
0cf758b6d1 New translations ja-JP.yml (French) 2018-12-14 02:03:02 +09:00
syuilo
d28fca320e New translations ja-JP.yml (French) 2018-12-14 01:42:26 +09:00
MeiMei
8bd17703c3 Fix reversi settings bot switch (#3609) 2018-12-13 13:40:10 +09:00
和風ドレッシング
a78eebc43f ていねい (#3608)
「古い」という表現でキレる方もいるので、丁寧な言葉づかいに変更
2018-12-13 09:42:14 +09:00
syuilo
79fb5246df New translations ja-JP.yml (English) 2018-12-13 08:01:55 +09:00
syuilo
458b8c78dc New translations ja-JP.yml (French) 2018-12-13 04:12:31 +09:00
syuilo
64e0cbd6fc New translations ja-JP.yml (French) 2018-12-13 04:04:32 +09:00
Acid Chicken (硫酸鶏)
7fe937026b Update html.ts (#3603) 2018-12-13 01:33:18 +09:00
syuilo
656cec65b9 Merge branch 'develop' of https://github.com/syuilo/misskey into develop 2018-12-13 01:18:29 +09:00
syuilo
8045bbff1c 🎨 2018-12-13 01:18:17 +09:00
MeiMei
c1a7a21746 Hide unavailable integration settings (#3604) 2018-12-12 23:21:02 +09:00
Acid Chicken (硫酸鶏)
f3ee63fcbe Update url-preview.vue (#3602) 2018-12-12 21:19:52 +09:00
MeiMei
7645c212a3 No @ for account name (#3586)
* No @ for account name

* Use @ for GitHub
2018-12-12 17:33:08 +09:00
syuilo
8b38e2ea58 New translations ja-JP.yml (Norwegian) 2018-12-12 13:12:57 +09:00
syuilo
c9eb6a8919 New translations ja-JP.yml (Dutch) 2018-12-12 13:12:53 +09:00
syuilo
9a41fd4734 New translations ja-JP.yml (Japanese, Kansai) 2018-12-12 13:12:47 +09:00
syuilo
70d96ee076 New translations ja-JP.yml (Spanish) 2018-12-12 13:12:43 +09:00
syuilo
3b6fb3959b New translations ja-JP.yml (Russian) 2018-12-12 13:12:36 +09:00
syuilo
484d705320 New translations ja-JP.yml (Portuguese) 2018-12-12 13:12:30 +09:00
syuilo
786031be66 New translations ja-JP.yml (Polish) 2018-12-12 13:12:25 +09:00
syuilo
bc0027ce43 New translations ja-JP.yml (Korean) 2018-12-12 13:12:21 +09:00
syuilo
3e7c6d9bdc New translations ja-JP.yml (Italian) 2018-12-12 13:12:15 +09:00
syuilo
5463e3e55e New translations ja-JP.yml (German) 2018-12-12 13:12:11 +09:00
syuilo
84a880086e New translations ja-JP.yml (French) 2018-12-12 13:12:06 +09:00
syuilo
89419b7136 New translations ja-JP.yml (English) 2018-12-12 13:12:01 +09:00
syuilo
9106ec74f7 New translations ja-JP.yml (Chinese Simplified) 2018-12-12 13:11:57 +09:00
syuilo
ebf9a0921d New translations ja-JP.yml (Catalan) 2018-12-12 13:11:53 +09:00
75 changed files with 1094 additions and 391 deletions

View File

@@ -1,6 +1,23 @@
ChangeLog
=========
10.64.2
-------
* UIの動きを減らすオプションが一部のアニメーションに適用されなかったのを修正
10.64.1
-------
* レートリミットの調整
* アニメーションの調整
10.64.0
-------
* いくつかのアニメーションを追加
* OGP向けにインスタンスのバナー画像を提供するように
* 管理者ページでドライブのファイルを表示できるように
* ユーザビリティの強化
* バグ修正
10.63.1
-------
* メンションの表示を改善

View File

@@ -3,9 +3,9 @@
[![Misskey](/assets/title.png)](https://misskey.xyz/)
================================================================
[![CircleCI](https://circleci.com/gh/syuilo/misskey.svg?style=svg)](https://circleci.com/gh/syuilo/misskey)
[![][dependencies-badge]][dependencies-link]
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)
[![CircleCI](https://img.shields.io/circleci/project/github/syuilo/misskey.svg?style=for-the-badge)](https://circleci.com/gh/syuilo/misskey)
[![Dependencies](https://img.shields.io/david/syuilo/misskey.svg?style=for-the-badge)](https://david-dm.org/syuilo/misskey)
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=for-the-badge)](http://makeapullrequest.com)
**Sophisticated microblogging platform, evolving forever.**
@@ -77,7 +77,7 @@ Please see [Contribution guide](./CONTRIBUTING.md).
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/13376668/71f3cf87ec6c4393a44b1b9df5ee3d12/1?token-time=2145916800&token-hash=7pSmWqgMfMSJHVIEcNsuuQoKeU3TRluew5p0EGTzWA4%3D" alt="Arctic"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/12731202/0995c46cdcb54153ab5f073f5869b70a/1?token-time=2145916800&token-hash=Yd60FK_SWfQO56SeiJpy1tDHOnCV4xdEywQe8gn5_Wo%3D" alt="negao"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/12913507/f7181eacafe8469a93033d85f5969c29/2?token-time=2145916800&token-hash=mgPdX9TqZxEg4TTPuc477dxhIgYk9246qafjWZEqZ7g%3D" alt="Melilot"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/12999811/5f349fafcce44dd1824a8b1ebbec4564/2?token-time=2145916800&token-hash=rwZ8qvbm_kpA4ib3kc07tVKupXeySpY5ATQFGxfL9v0%3D" alt="Xeltica"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/12999811/5f349fafcce44dd1824a8b1ebbec4564/3?token-time=2145916800&token-hash=ybYtxfpte1b-rGg6Zecpys2ZdZDtwR_UNJHQjt-3eoU%3D" alt="Xeltica"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/3384329/8b713330cb27404ea6e9fac50ff96efe/1?token-time=2145916800&token-hash=0eu4-m1gTWA9PhptVZt6rdKcusqcD7RB87rJT23VVFI%3D" alt="べすれい"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/12021162/963128bb8d14476dbd8407943db8f31a/1?token-time=2145916800&token-hash=GgJ_NmUB6_nnRNLVGUWjV-WX91On7BOu59LKncYV9fE%3D" alt="gutfuckllc"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/11357794/923ce94cd8c44ba788ee931907881839/1?token-time=2145916800&token-hash=I8lJVM8LeW6TSo5W6uIIRZ42cw83zp1wK_FsbzY0mcQ%3D" alt="mydarkstar"></td>
@@ -86,7 +86,7 @@ Please see [Contribution guide](./CONTRIBUTING.md).
<td><a href="https://www.patreon.com/user?u=13376668">Arctic</a></td>
<td><a href="https://www.patreon.com/negao">negao</a></td>
<td><a href="https://www.patreon.com/user?u=12913507">Melilot</a></td>
<td><a href="https://www.patreon.com/AxellaMC">Xeltica</a></td>
<td><a href="https://www.patreon.com/Xeltica">Xeltica</a></td>
<td><a href="https://www.patreon.com/user?u=3384329">べすれい</a></td>
<td><a href="https://www.patreon.com/gutfuckllc">gutfuckllc</a></td>
<td><a href="https://www.patreon.com/mydarkstar">mydarkstar</a></td>
@@ -118,7 +118,7 @@ Please see [Contribution guide](./CONTRIBUTING.md).
<td><a href="https://www.patreon.com/user?u=12531784">Takashi Shibuya</a></td>
</tr></table>
**Last updated:** Thu, 06 Dec 2018 14:22:05 UTC
**Last updated:** Sun, 16 Dec 2018 18:32:06 UTC
<!-- PATREON_END -->
:four_leaf_clover: Copyright
@@ -130,9 +130,7 @@ Misskey is an open-source software licensed under the [GNU AGPLv3](LICENSE).
[![][agpl-3.0-badge]][AGPL-3.0]
[agpl-3.0]: https://www.gnu.org/licenses/agpl-3.0.en.html
[agpl-3.0-badge]: https://img.shields.io/badge/license-AGPL--3.0-444444.svg?style=flat-square
[dependencies-link]: https://david-dm.org/syuilo/misskey
[dependencies-badge]: https://img.shields.io/david/syuilo/misskey.svg?style=flat-square
[agpl-3.0-badge]: https://img.shields.io/badge/license-AGPL--3.0-444444.svg?style=for-the-badge
[backer-url]: #backers
[backer-badge]: https://opencollective.com/misskey/backers/badge.svg

View File

@@ -11,14 +11,12 @@ import tslint from 'gulp-tslint';
const cssnano = require('gulp-cssnano');
const stylus = require('gulp-stylus');
import * as uglifyComposer from 'gulp-uglify/composer';
import pug = require('gulp-pug');
import * as rimraf from 'rimraf';
import chalk from 'chalk';
const imagemin = require('gulp-imagemin');
import * as rename from 'gulp-rename';
import * as mocha from 'gulp-mocha';
import * as replace from 'gulp-replace';
import * as htmlmin from 'gulp-htmlmin';
const uglifyes = require('uglify-es');
const locales = require('./locales');
@@ -34,8 +32,6 @@ if (isDebug) {
console.warn(chalk.yellow.bold(' built script will not be compressed.'));
}
const constants = require('./src/const.json');
gulp.task('build', [
'build:ts',
'build:copy',
@@ -109,7 +105,7 @@ gulp.task('default', ['build']);
gulp.task('build:client', [
'build:ts',
'build:client:script',
'build:client:pug',
'build:client:styles',
'copy:client'
]);
@@ -148,52 +144,6 @@ gulp.task('copy:client', [
.pipe(gulp.dest('./built/client/assets/'))
);
gulp.task('build:client:pug', [
'copy:client',
'build:client:script',
'build:client:styles'
], () =>
gulp.src('./src/client/app/base.pug')
.pipe(pug({
locals: {
themeColor: constants.themeColor
}
}))
.pipe(htmlmin({
// 真理値属性の簡略化 e.g.
// <input value="foo" readonly="readonly"> to
// <input value="foo" readonly>
collapseBooleanAttributes: true,
// テキストの一部かもしれない空白も削除する e.g.
// <div> <p> foo </p> </div> to
// <div><p>foo</p></div>
collapseWhitespace: true,
// タグ間の改行を保持する
preserveLineBreaks: true,
// (できる場合は)属性のクォーテーション削除する e.g.
// <p class="foo-bar" id="moo" title="blah blah">foo</p> to
// <p class=foo-bar id=moo title="blah blah">foo</p>
removeAttributeQuotes: true,
// 省略可能なタグを省略する e.g.
// <html><p>yo</p></html> ro
// <p>yo</p>
removeOptionalTags: true,
// 属性の値がデフォルトと同じなら省略する e.g.
// <input type="text"> to
// <input>
removeRedundantAttributes: true,
// CSSも圧縮する
minifyCSS: true
}))
.pipe(gulp.dest('./built/client/app/'))
);
gulp.task('locales', () =>
gulp.src('./locales/*.yml')
.pipe(yaml({ schema: 'DEFAULT_SAFE_SCHEMA' }))

View File

@@ -111,7 +111,6 @@ common:
i-like-sushi: "私は(プリンよりむしろ)寿司が好き"
show-reversi-board-labels: "リバーシのボードの行と列のラベルを表示"
use-white-black-reversi-stones: "リバーシに白黒の石を使う"
use-contrast-reversi-stones: "リバーシのアイコンにコントラストを付ける"
verified-user: "公式アカウント"
disable-animated-mfm: "投稿内の動きのあるテキストを無効にする"
suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する"
@@ -165,6 +164,7 @@ common:
hashtags: "ハッシュタグ"
dev: "アプリの作成に失敗しました。再度お試しください。"
ai-chan-kawaii: "藍ちゃかわいい"
you: "あなた"
auth/views/form.vue:
share-access: "<i>{name}</i>があなたのアカウントにアクセスすることを許可しますか?"
permission-ask: "このアプリは次の権限を要求しています:"
@@ -1054,6 +1054,20 @@ admin/views/charts.vue:
network-requests: "リクエスト"
network-time: "応答時間"
network-usage: "通信量"
admin/views/drive.vue:
sort:
title: "ソート"
createdAtAsc: "アップロード日時が古い順"
createdAtDesc: "アップロード日時が新しい順"
sizeAsc: "サイズが小さい順"
sizeDesc: "サイズが大きい順"
origin:
title: "オリジン"
combined: "ローカル+リモート"
local: "ローカル"
remote: "リモート"
delete: "削除"
deleted: "削除しました"
admin/views/users.vue:
operation: "操作"
username-or-userid: "ユーザー名またはユーザーID"

View File

@@ -111,7 +111,6 @@ common:
i-like-sushi: "Ich bevorzuge Sushi anstelle von Pudding"
show-reversi-board-labels: "リバーシのボードの行と列のラベルを表示"
use-white-black-reversi-stones: "リバーシに白黒の石を使う"
use-contrast-reversi-stones: "リバーシのアイコンにコントラストを付ける"
verified-user: "Verifizierter Benutzer"
disable-animated-mfm: "投稿内の動きのあるテキストを無効にする"
suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する"
@@ -165,6 +164,7 @@ common:
hashtags: "Hashtags"
dev: "Fehler beim Erstellen der Applikation. Bitte versuche es erneut."
ai-chan-kawaii: "藍ちゃかわいい"
you: "あなた"
auth/views/form.vue:
share-access: "<i>{name}</i>があなたのアカウントにアクセスすることを許可しますか?"
permission-ask: "このアプリは次の権限を要求しています:"
@@ -1054,6 +1054,20 @@ admin/views/charts.vue:
network-requests: "リクエスト"
network-time: "応答時間"
network-usage: "通信量"
admin/views/drive.vue:
sort:
title: "ソート"
createdAtAsc: "アップロード日時が古い順"
createdAtDesc: "アップロード日時が新しい順"
sizeAsc: "サイズが小さい順"
sizeDesc: "サイズが大きい順"
origin:
title: "オリジン"
combined: "ローカル+リモート"
local: "ローカル"
remote: "リモート"
delete: "削除"
deleted: "削除しました"
admin/views/users.vue:
operation: "操作"
username-or-userid: "ユーザー名またはユーザーID"

View File

@@ -111,7 +111,6 @@ common:
i-like-sushi: "I prefer sushi rather than pudding"
show-reversi-board-labels: "Show row and column labels in Reversi"
use-white-black-reversi-stones: "Use white-black stone in reversi"
use-contrast-reversi-stones: "Make the stone color clear in reversi"
verified-user: "Verified account"
disable-animated-mfm: "Disable animated texts in a post"
suggest-recent-hashtags: "Suggest recently used hashtags within the post composition area"
@@ -165,6 +164,7 @@ common:
hashtags: "Hashtags"
dev: "Failed to create the application. Please try again."
ai-chan-kawaii: "Ai-chan kawaii!"
you: "You"
auth/views/form.vue:
share-access: "Would you allow <i>{name}</i> to access your account?"
permission-ask: "This application requires the following permissions:"
@@ -1054,6 +1054,20 @@ admin/views/charts.vue:
network-requests: "Requests"
network-time: "Response time"
network-usage: "Traffic"
admin/views/drive.vue:
sort:
title: "Sort"
createdAtAsc: "アップロード日時が古い順"
createdAtDesc: "アップロード日時が新しい順"
sizeAsc: "サイズが小さい順"
sizeDesc: "サイズが大きい順"
origin:
title: "Origin"
combined: "Local + Remote"
local: "Local"
remote: "Remote"
delete: "Delete"
deleted: "Deleted successfully"
admin/views/users.vue:
operation: "Operations"
username-or-userid: "Username or user ID"

View File

@@ -111,7 +111,6 @@ common:
i-like-sushi: "Prefiero sushi a pudín"
show-reversi-board-labels: "Mostrar etiquetas de filas y columnas en Reversi"
use-white-black-reversi-stones: "リバーシに白黒の石を使う"
use-contrast-reversi-stones: "Hacer el color de la piedra claro en Reversi"
verified-user: "Cuenta verificada"
disable-animated-mfm: "Desactivar texto animado en una publicación"
suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する"
@@ -165,6 +164,7 @@ common:
hashtags: "Etiquetas"
dev: "アプリの作成に失敗しました。再度お試しください。"
ai-chan-kawaii: "藍ちゃかわいい"
you: "あなた"
auth/views/form.vue:
share-access: "<i>{name}</i>があなたのアカウントにアクセスすることを許可しますか?"
permission-ask: "La aplicación requiere los siguientes permisos:"
@@ -1054,6 +1054,20 @@ admin/views/charts.vue:
network-requests: "リクエスト"
network-time: "応答時間"
network-usage: "通信量"
admin/views/drive.vue:
sort:
title: "ソート"
createdAtAsc: "アップロード日時が古い順"
createdAtDesc: "アップロード日時が新しい順"
sizeAsc: "サイズが小さい順"
sizeDesc: "サイズが大きい順"
origin:
title: "オリジン"
combined: "ローカル+リモート"
local: "ローカル"
remote: "リモート"
delete: "削除"
deleted: "削除しました"
admin/views/users.vue:
operation: "操作"
username-or-userid: "ユーザー名またはユーザーID"

View File

@@ -47,11 +47,11 @@ common:
seconds_ago: "Il y a {} seconde·s"
minutes_ago: "Il y a {} min"
hours_ago: "Il y a {} h"
days_ago: "Il y a {} jours"
weeks_ago: "Il y a {} semaines·s"
days_ago: "Il y a {} j"
weeks_ago: "Il y a {} semaines"
months_ago: "Il y a {} mois"
years_ago: "Il y a {} an·s"
month-and-day: "{day}/{month}"
month-and-day: "{day}-{month}"
trash: "Corbeille"
drive: "Drive"
messaging: "Conversations"
@@ -111,7 +111,6 @@ common:
i-like-sushi: "Je préfère les sushis plutôt que le pudding"
show-reversi-board-labels: "Afficher les étiquettes des lignes et colonnes dans Reversi"
use-white-black-reversi-stones: "Jouer avec des pions noirs et blancs sur Reversi"
use-contrast-reversi-stones: "Icône avec contraste sur Reversi"
verified-user: "Compte vérifié"
disable-animated-mfm: "Désactiver les textes animés dans les publications"
suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する"
@@ -165,6 +164,7 @@ common:
hashtags: "Hashtags"
dev: "Échec lors de la création de lapplication. Veuillez réessayer."
ai-chan-kawaii: "Ai-Chan est mignonne !"
you: "Vous"
auth/views/form.vue:
share-access: "Désirez-vous autoriser <i>{name}</i> à avoir accès à votre compte?"
permission-ask: "Cette application nécessite les autorisations suivantes :"
@@ -478,7 +478,7 @@ common/views/widgets/broadcast.vue:
next: "Suivant"
common/views/widgets/calendar.vue:
year: "Année {}"
month: "Mois {}"
month: "{},"
day: "{}"
today: "Aujourdhui:"
this-month: "Ce mois-ci :"
@@ -515,7 +515,7 @@ common/views/widgets/tips.vue:
tips-line10: "タイムマシンウィジェットを利用すると、簡単に過去のタイムラインに遡れます"
tips-line11: "Vous pouvez épingler des notes sur votre page en cliquant sur « … »"
tips-line13: "Tous les fichiers attachés à cette publication sont sauvegardés dans le Drive"
tips-line14: "ホームのカスタマイズ中、ウィジェットを右クリックしてデザインを変更できます"
tips-line14: "Lorsque vous personnalisez la disposition de votre page daccueil, vous pouvez effectuer un clique droit sur un widget pour changer son apparence."
tips-line17: "Vous pouvez mettre un texte en surbrillance en le mettant entre ** **"
tips-line19: "Plusieurs fenêtres peuvent être détachées en dehors du navigateur."
tips-line20: "Pourcentage sur le widget calendrier qui indique le pourcentage de temps passé"
@@ -524,7 +524,7 @@ common/views/widgets/tips.vue:
tips-line24: "Misskey est fonctionnel depuis 2014"
tips-line25: "Vous pouvez recevoir les notifications de Misskey dans un navigateur web compatible"
common/views/pages/404.vue:
page-not-found: "ページが見つかりませんでした"
page-not-found: "La page demandée est introuvable !"
common/views/pages/follow.vue:
signed-in-as: "Connecté·e en tant que {}"
following: "Suit"
@@ -553,7 +553,7 @@ desktop/views/components/activity.vue:
title: "Activité"
toggle: "Afficher les vues"
desktop/views/components/calendar.vue:
title: "{month} / {year}"
title: "{month} - {year}"
prev: "Mois précédent"
next: "Mois suivant"
go: "Cliquez pour naviguer"
@@ -877,7 +877,7 @@ common/views/components/password-settings.vue:
enter-new-password-again: "Entrez à nouveau le nouveau mot de passe"
not-match: "Les nouveaux mots de passe ne sont pas identiques"
changed: "Mot de passe modifié avec succès"
failed: "パスワード変更に失敗しました"
failed: "Échec lors de la modification du mot de passe"
desktop/views/components/sub-note-content.vue:
private: "cette publication est privée"
deleted: "cette publication a été supprimée"
@@ -970,7 +970,7 @@ admin/views/instance.vue:
instance-description: "Description de linstance"
host: "Hôte"
banner-url: "Url de limage de la bannière"
error-image-url: "エラー画像URL"
error-image-url: "URL de limage derreur"
languages: "Langue de linstance"
languages-desc: "Vous pouvez en définir plus dune, séparées par des espaces."
maintainer-config: "Informations de ladministrateur"
@@ -1054,6 +1054,20 @@ admin/views/charts.vue:
network-requests: "Requêtes"
network-time: "Temps de réponse"
network-usage: "Traffic"
admin/views/drive.vue:
sort:
title: "Tri"
createdAtAsc: "アップロード日時が古い順"
createdAtDesc: "アップロード日時が新しい順"
sizeAsc: "Taille - Ascendant"
sizeDesc: "Taille - Volumineux en premier"
origin:
title: "Origine"
combined: "Locaux et distants combinés"
local: "Local"
remote: "Distant"
delete: "Supprimer"
deleted: "Supprimé"
admin/views/users.vue:
operation: "Actions"
username-or-userid: "Nom dutilisateur·rice ou ID utilisateur"
@@ -1076,7 +1090,7 @@ admin/views/users.vue:
createdAtAsc: "Date dinscription (Ascendant)"
createdAtDesc: "Date dinscription (Descendant)"
updatedAtAsc: "Mis à jour récemment (Ascendant)"
updatedAtDesc: "更新日時が新しい順"
updatedAtDesc: "Mis à jour récemment (descendant)"
origin:
title: "Origine"
combined: "Locaux + distants"
@@ -1189,7 +1203,7 @@ desktop/views/pages/user/user.header.vue:
years-old: "{age} ans"
year: "/"
month: "/"
day: "/"
day: "-"
desktop/views/pages/user/user.timeline.vue:
default: "Publications"
with-replies: "Publications et réponses"
@@ -1349,7 +1363,7 @@ mobile/views/pages/welcome.vue:
signup: "S'enregistrer"
mobile/views/pages/widgets.vue:
dashboard: "Tableau de bord"
widgets-hints: "ウィジェットを追加/削除したり並べ替えたりできます。ウィジェットを移動するには「三」をドラッグします。ウィジェットを削除するには「x」をタップします。いくつかのウィジェットはタップすることで表示を変更できます。"
widgets-hints: "Vous pouvez ajouter, supprimer et réaranger les widgets. Faites glisser « 三 » pour déplacer le widget. Appuyez sur « x » pour supprimer le widget. Certains widgets peuvent changer dapparence en cliquant dessus."
add-widget: "Ajouter"
customization-tips: "Conseils de personnalisation"
mobile/views/pages/widgets/activity.vue:

View File

@@ -111,7 +111,6 @@ common:
i-like-sushi: "私は(プリンよりむしろ)寿司が好き"
show-reversi-board-labels: "リバーシのボードの行と列のラベルを表示"
use-white-black-reversi-stones: "リバーシに白黒の石を使う"
use-contrast-reversi-stones: "リバーシのアイコンにコントラストを付ける"
verified-user: "公式アカウント"
disable-animated-mfm: "投稿内の動きのあるテキストを無効にする"
suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する"
@@ -165,6 +164,7 @@ common:
hashtags: "ハッシュタグ"
dev: "アプリの作成に失敗しました。再度お試しください。"
ai-chan-kawaii: "藍ちゃかわいい"
you: "あなた"
auth/views/form.vue:
share-access: "<i>{name}</i>があなたのアカウントにアクセスすることを許可しますか?"
permission-ask: "このアプリは次の権限を要求しています:"
@@ -1054,6 +1054,20 @@ admin/views/charts.vue:
network-requests: "リクエスト"
network-time: "応答時間"
network-usage: "通信量"
admin/views/drive.vue:
sort:
title: "ソート"
createdAtAsc: "アップロード日時が古い順"
createdAtDesc: "アップロード日時が新しい順"
sizeAsc: "サイズが小さい順"
sizeDesc: "サイズが大きい順"
origin:
title: "オリジン"
combined: "ローカル+リモート"
local: "ローカル"
remote: "リモート"
delete: "削除"
deleted: "削除しました"
admin/views/users.vue:
operation: "操作"
username-or-userid: "ユーザー名またはユーザーID"

View File

@@ -119,7 +119,6 @@ common:
i-like-sushi: "私は(プリンよりむしろ)寿司が好き"
show-reversi-board-labels: "リバーシのボードの行と列のラベルを表示"
use-white-black-reversi-stones: "リバーシに白黒の石を使う"
use-contrast-reversi-stones: "リバーシのアイコンにコントラストを付ける"
verified-user: "公式アカウント"
disable-animated-mfm: "投稿内の動きのあるテキストを無効にする"
suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する"
@@ -1184,6 +1183,21 @@ admin/views/charts.vue:
network-time: "応答時間"
network-usage: "通信量"
admin/views/drive.vue:
sort:
title: "ソート"
createdAtAsc: "アップロード日時が古い順"
createdAtDesc: "アップロード日時が新しい順"
sizeAsc: "サイズが小さい順"
sizeDesc: "サイズが大きい順"
origin:
title: "オリジン"
combined: "ローカル+リモート"
local: "ローカル"
remote: "リモート"
delete: "削除"
deleted: "削除しました"
admin/views/users.vue:
operation: "操作"
username-or-userid: "ユーザー名またはユーザーID"

View File

@@ -111,7 +111,6 @@ common:
i-like-sushi: "寿司(のほうがプリンよりむしろ)ウマい、タコ焼きはあらへんけど。"
show-reversi-board-labels: "リバーシのボードの行と列のラベルを表示や!"
use-white-black-reversi-stones: "リバーシに白黒の石を使う"
use-contrast-reversi-stones: "リバーシのアイコンにコントラストをつけんで!"
verified-user: "アメちゃん付きアカウント"
disable-animated-mfm: "投稿内のちょろちょろ動いてんのを止める"
suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する"
@@ -165,6 +164,7 @@ common:
hashtags: "ハッシュタグ"
dev: "アプリの作成あかんかったわ。もっぺんやってみて。"
ai-chan-kawaii: "藍ちゃめっさべっぴんさんや"
you: "あなた"
auth/views/form.vue:
share-access: "あんたのアカウントに<i>{name}</i>がアクセスしようとしてるで?ええか?"
permission-ask: "このアプリは次の権限を要求してんで:"
@@ -1054,6 +1054,20 @@ admin/views/charts.vue:
network-requests: "リクエスト"
network-time: "応答時間"
network-usage: "通信量"
admin/views/drive.vue:
sort:
title: "ソート"
createdAtAsc: "アップロード日時が古い順"
createdAtDesc: "アップロード日時が新しい順"
sizeAsc: "サイズが小さい順"
sizeDesc: "サイズが大きい順"
origin:
title: "オリジン"
combined: "ローカル+リモート"
local: "ローカル"
remote: "リモート"
delete: "削除"
deleted: "削除しました"
admin/views/users.vue:
operation: "操作"
username-or-userid: "ユーザー名またはユーザーID"

View File

@@ -111,7 +111,6 @@ common:
i-like-sushi: "저는 (푸딩보다 차라리) 초밥이 좋아요"
show-reversi-board-labels: "리버시 보드의 행과 열 레이블을 표시"
use-white-black-reversi-stones: "리버시에 흑백 돌을 사용"
use-contrast-reversi-stones: "리버시 아이콘의 대비를 높이기"
verified-user: "공식 계정"
disable-animated-mfm: "글의 문자 애니메이션을 비활성화"
suggest-recent-hashtags: "최근 해시태그를 글 작성란에 표시"
@@ -165,6 +164,7 @@ common:
hashtags: "해시태그"
dev: "앱을 만드는 데 실패했습니다. 다시 시도하시기 바랍니다."
ai-chan-kawaii: "아이쨩 귀여워"
you: "당신"
auth/views/form.vue:
share-access: "<i>{name}</i>가 당신의 계정에 엑세스하도록 허용하시겠습니까?"
permission-ask: "이 앱은 다음의 권한을 요청합니다:"
@@ -1054,6 +1054,20 @@ admin/views/charts.vue:
network-requests: "요청"
network-time: "응답시간"
network-usage: "통신량"
admin/views/drive.vue:
sort:
title: "정렬"
createdAtAsc: "업로드 날짜 오랜 순"
createdAtDesc: "업로드 날짜 최신순"
sizeAsc: "크기가 작은 순"
sizeDesc: "크기가 큰 순"
origin:
title: "출처"
combined: "로컬 + 리모트"
local: "로컬"
remote: "리모트"
delete: "삭제"
deleted: "삭제하였습니다"
admin/views/users.vue:
operation: "작업"
username-or-userid: "사용자명 혹은 사용자 ID"

View File

@@ -111,7 +111,6 @@ common:
i-like-sushi: "私は(プリンよりむしろ)寿司が好き"
show-reversi-board-labels: "リバーシのボードの行と列のラベルを表示"
use-white-black-reversi-stones: "リバーシに白黒の石を使う"
use-contrast-reversi-stones: "リバーシのアイコンにコントラストを付ける"
verified-user: "公式アカウント"
disable-animated-mfm: "投稿内の動きのあるテキストを無効にする"
suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する"
@@ -165,6 +164,7 @@ common:
hashtags: "ハッシュタグ"
dev: "アプリの作成に失敗しました。再度お試しください。"
ai-chan-kawaii: "藍ちゃかわいい"
you: "あなた"
auth/views/form.vue:
share-access: "<i>{name}</i>があなたのアカウントにアクセスすることを許可しますか?"
permission-ask: "このアプリは次の権限を要求しています:"
@@ -1054,6 +1054,20 @@ admin/views/charts.vue:
network-requests: "リクエスト"
network-time: "応答時間"
network-usage: "通信量"
admin/views/drive.vue:
sort:
title: "ソート"
createdAtAsc: "アップロード日時が古い順"
createdAtDesc: "アップロード日時が新しい順"
sizeAsc: "サイズが小さい順"
sizeDesc: "サイズが大きい順"
origin:
title: "オリジン"
combined: "ローカル+リモート"
local: "ローカル"
remote: "リモート"
delete: "削除"
deleted: "削除しました"
admin/views/users.vue:
operation: "操作"
username-or-userid: "ユーザー名またはユーザーID"

View File

@@ -111,7 +111,6 @@ common:
i-like-sushi: "私は(プリンよりむしろ)寿司が好き"
show-reversi-board-labels: "リバーシのボードの行と列のラベルを表示"
use-white-black-reversi-stones: "リバーシに白黒の石を使う"
use-contrast-reversi-stones: "リバーシのアイコンにコントラストを付ける"
verified-user: "公式アカウント"
disable-animated-mfm: "投稿内の動きのあるテキストを無効にする"
suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する"
@@ -165,6 +164,7 @@ common:
hashtags: "ハッシュタグ"
dev: "アプリの作成に失敗しました。再度お試しください。"
ai-chan-kawaii: "藍ちゃかわいい"
you: "あなた"
auth/views/form.vue:
share-access: "<i>{name}</i>があなたのアカウントにアクセスすることを許可しますか?"
permission-ask: "このアプリは次の権限を要求しています:"
@@ -1054,6 +1054,20 @@ admin/views/charts.vue:
network-requests: "リクエスト"
network-time: "応答時間"
network-usage: "通信量"
admin/views/drive.vue:
sort:
title: "ソート"
createdAtAsc: "アップロード日時が古い順"
createdAtDesc: "アップロード日時が新しい順"
sizeAsc: "サイズが小さい順"
sizeDesc: "サイズが大きい順"
origin:
title: "オリジン"
combined: "ローカル+リモート"
local: "ローカル"
remote: "リモート"
delete: "削除"
deleted: "削除しました"
admin/views/users.vue:
operation: "操作"
username-or-userid: "ユーザー名またはユーザーID"

View File

@@ -111,15 +111,14 @@ common:
i-like-sushi: "Wolę sushi od puddingu"
show-reversi-board-labels: "Pokazuj podpisy wierszy i kolumn w Reversi"
use-white-black-reversi-stones: "リバーシに白黒の石を使う"
use-contrast-reversi-stones: "リバーシのアイコンにコントラストを付ける"
verified-user: "公式アカウント"
verified-user: "Zweryfikowane konto"
disable-animated-mfm: "Wyłącz animowany tekst we wpisach"
suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する"
always-show-nsfw: "常に閲覧注意のメディアを表示する"
always-show-nsfw: "Zawszę pokazuj zawartość NSFW"
always-mark-nsfw: "Zawsze oznaczaj posty z multimediami jako NSFW"
show-full-acct: "ユーザー名のホストを省略しない"
show-via: "viaを表示する"
reduce-motion: "UIの動きを減らす"
reduce-motion: "Zredukuj ruch w UI"
this-setting-is-this-device-only: "このデバイスのみ"
use-os-default-emojis: "Użyj domyślnych Emoji systemowych"
do-not-use-in-production: 'これは開発ビルドです。本番環境で使用しないでください。'
@@ -165,6 +164,7 @@ common:
hashtags: "Hashtagi"
dev: "アプリの作成に失敗しました。再度お試しください。"
ai-chan-kawaii: "藍ちゃかわいい"
you: "Ty"
auth/views/form.vue:
share-access: "<i>{name}</i>があなたのアカウントにアクセスすることを許可しますか?"
permission-ask: "Ta aplikacja wymaga następujących uprawnień:"
@@ -298,7 +298,7 @@ common/views/components/cw-button.vue:
hide: "Ukryj"
show: "Pokaż więcej"
chars: "{count} znaków"
files: "{count}ファイル"
files: "{count} plików"
common/views/components/messaging.vue:
search-user: "Znajdź użytkownika"
you: "Ty"
@@ -576,7 +576,7 @@ desktop/views/components/drive-window.vue:
desktop/views/components/drive.file.vue:
avatar: "Awatar"
banner: "Baner"
nsfw: "閲覧注意"
nsfw: "NSFW"
contextmenu:
rename: "Zmień nazwę"
mark-as-sensitive: "Oznacz jako zawartość wrażliwą"
@@ -662,7 +662,7 @@ desktop/views/components/note-detail.vue:
add-reaction: "Dodaj reakcję"
desktop/views/components/note.vue:
reply: "Odpowiedz"
renote: "Renote"
renote: "Udostępnij"
add-reaction: "Dodaj reakcję"
detail: "Szczegóły"
private: "この投稿は非公開です"
@@ -729,7 +729,7 @@ desktop/views/components/settings.vue:
notification: "Powiadomienia"
apps: "Aplikacje"
tags: "Hashtagi"
mute-and-block: "ミュート/ブロック"
mute-and-block: "Wycisz / Zablokuj"
blocking: "ブロック"
security: "Bezpieczeństwo"
signin: "Historia logowań"
@@ -753,14 +753,14 @@ desktop/views/components/settings.vue:
api-via-stream-desc: "この設定をオンにすると、websocket接続を経由してAPIリクエストが行われます(パフォーマンス向上が期待できます)。オフにすると、ネイティブの fetch APIが利用されます。この設定はこのデバイスのみ有効です。"
deck-nav: "デッキ内ナビゲーション"
deck-nav-desc: "デッキを使用しているとき、ナビゲーションが発生する際にページ遷移を行わずに一時的なカラムで受けるようにします。"
deck-default: "デッキをデフォルトのUIにする"
deck-default: "Użyj Talię jako domyślne UI"
display: "Wygląd i wyświetlanie"
customize: "Dostosuj stronę główną"
wallpaper: "Tapeta"
choose-wallpaper: "Wybierz tło"
delete-wallpaper: "Usuń tło"
dark-mode: "Tryb ciemny"
use-shadow: "UIに影を使用"
use-shadow: "Użyj cieni w UI"
rounded-corners: "Zaokrąglaj rogi w UI"
circle-icons: "Używaj okrągłych ikon"
contrasted-acct: "ユーザー名にコントラストを付ける"
@@ -769,20 +769,20 @@ desktop/views/components/settings.vue:
show-reply-target: "Pokazuj cel odpowiedzi"
timeline: "Oś czasu"
show-my-renotes: "Pokazuj moje udostępnienia na osi czasu"
show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する"
show-renoted-my-notes: "Pokazuj moje udostępnione wpisy na osi czasu"
show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する"
show-maps: "Automatycznie pokazuj mapę"
remain-deleted-note: "削除された投稿を表示し続ける"
deck-column-align: "デッキのカラムの配置"
deck-column-align-center: "中央"
deck-column-align-left: ""
deck-column-align-left: "Lewo"
deck-column-align-flexible: "Elastyczne"
deck-column-width: "Szerokość kolumn w talii"
deck-column-width-narrow: "wąskie"
deck-column-width-narrower: "やや狭"
deck-column-width-normal: "Normalny"
deck-column-width-wider: "やや広"
deck-column-width-wide: "szeroki"
deck-column-width-narrow: "Wąska"
deck-column-width-narrower: "Trochę wąska"
deck-column-width-normal: "Normalna"
deck-column-width-wider: "Trochę szeroka"
deck-column-width-wide: "Szeroka"
sound: "Dźwięk"
enable-sounds: "Włącz dźwięk"
enable-sounds-desc: "Odtwarzaj dźwięk przy wstawianiu wpisów, wysyłaniu lub otrzymywaniu wiadomości. Opcja ta jest zapamiętywana przez przeglądarkę."
@@ -817,10 +817,10 @@ desktop/views/components/settings.vue:
tools: "Narzędzia"
task-manager: "Menedżer zadań"
third-parties: "Autorzy trzeci"
navbar-position: "ナビゲーションバーの位置"
navbar-position-top: ""
navbar-position-left: ""
navbar-position-right: ""
navbar-position: "Pozycja paska nawigacji"
navbar-position-top: "Góra"
navbar-position-left: "Lewo"
navbar-position-right: "Prawo"
desktop/views/components/settings.2fa.vue:
intro: "Jeżeli skonfigurujesz uwierzytelnianie dwuetapowe, aby zablokować się będziesz potrzebować (oprócz hasła) kodu ze skonfigurowanego urządzenia (np. smartfonu), co zwiększy bezpieczeństwo."
detail: "Zobacz szczegóły…"
@@ -840,7 +840,7 @@ desktop/views/components/settings.2fa.vue:
failed: "Nie udało się skonfigurować uwierzytelniania dwuetapowego, upewnij się że wprowadziłeś prawidłowy token."
info: "Od teraz, wprowadzaj token wyświetlany na urządzeniu przy każdym logowaniu do Misskey."
common/views/components/api-settings.vue:
intro: "APIを利用するには、上記のトークンを「i」というキーでパラメータに付加してリクエストします。"
intro: "Aby uzyskać dostęp do API, ustaw ten token jako klucz 'i' parametrów żądań."
caution: "アカウントを不正利用される可能性があるため、このトークンは第三者に教えないでください(アプリなどにも入力しないでください)。"
regeneration-of-token: "W przypadku wycieku tokenu, możesz wygenerować nowy."
regenerate-token: "Wygeneruj nowy token"
@@ -863,11 +863,11 @@ common/views/components/drive-settings.vue:
common/views/components/mute-and-block.vue:
mute-and-block: "Wycisz / Zablokuj"
mute: "Wycisz"
block: "ブロック"
block: "Zablokuj"
no-muted-users: "Brak wyciszonych użytkowników"
no-blocked-users: "Brak zablokowanych użytkowników"
word-mute: "Wyciszenie słowa"
muted-words: "ミュートされたキーワード"
muted-words: "Wyciszone słowa kluczowe"
muted-words-description: "スペースで区切るとAND指定になり、改行で区切るとOR指定になります"
save: "Zapisz"
common/views/components/password-settings.vue:
@@ -884,7 +884,7 @@ desktop/views/components/sub-note-content.vue:
media-count: "{}zawartości multimedialnej"
poll: "Ankieta"
desktop/views/components/settings.tags.vue:
title: "タグ"
title: "Tagi"
query: "クエリ (省略可)"
add: "Dodaj"
save: "Zapisz"
@@ -899,8 +899,8 @@ desktop/views/components/timeline.vue:
messages: "Wiadomości"
list: "Listy"
hashtag: "Hashtag"
add-tag-timeline: "ハッシュタグを追加"
add-list: "リストを追加"
add-tag-timeline: "Dodaj hashtag"
add-list: "Dodaj listę"
list-name: "リスト名"
desktop/views/components/ui.header.vue:
welcome-back: "Witaj ponownie,"
@@ -1054,6 +1054,20 @@ admin/views/charts.vue:
network-requests: "Żądania"
network-time: "Czas reakcji"
network-usage: "通信量"
admin/views/drive.vue:
sort:
title: "ソート"
createdAtAsc: "アップロード日時が古い順"
createdAtDesc: "アップロード日時が新しい順"
sizeAsc: "サイズが小さい順"
sizeDesc: "サイズが大きい順"
origin:
title: "Źródło"
combined: "ローカル+リモート"
local: "ローカル"
remote: "リモート"
delete: "Usuń"
deleted: "削除しました"
admin/views/users.vue:
operation: "操作"
username-or-userid: "ユーザー名またはユーザーID"
@@ -1237,14 +1251,14 @@ mobile/views/components/drive-file-chooser.vue:
mobile/views/components/drive-folder-chooser.vue:
select-folder: "Wybierz katalog"
mobile/views/components/drive.file.vue:
nsfw: "閲覧注意"
nsfw: "NSFW"
mobile/views/components/drive.file-detail.vue:
download: "Pobierz"
rename: "Zmień nazwę"
move: "Przenieś"
hash: "Hash (md5)"
exif: "EXIF"
nsfw: "閲覧注意"
nsfw: "NSFW"
mark-as-sensitive: "閲覧注意に設定"
unmark-as-sensitive: "閲覧注意を解除"
mobile/views/components/media-image.vue:
@@ -1384,7 +1398,7 @@ mobile/views/pages/settings.vue:
timeline: "Oś czasu"
show-reply-target: "Pokazuj cel odpowiedzi"
show-my-renotes: "Pokazuj moje udostępnienia"
show-renoted-my-notes: "自分の投稿のRenoteを表示する"
show-renoted-my-notes: "Pokazuj moje udostępnione wpisy"
show-local-renotes: "ローカルの投稿のRenoteを表示する"
post-style: "Styl wpisów"
post-style-standard: "Standardowy"
@@ -1465,7 +1479,7 @@ deck:
list: "Listy"
swap-left: "Przesuń w lewo"
swap-right: "Przesuń w prawo"
swap-up: "上に移動"
swap-up: "Przenieś w górę"
swap-down: "下に移動"
remove: "Usuń"
add-column: "Dodaj kolumnę"

View File

@@ -111,7 +111,6 @@ common:
i-like-sushi: "Eu prefiro sushi a pudim"
show-reversi-board-labels: "Mostrar etiquetas de colunas e linhas no Reversi"
use-white-black-reversi-stones: "リバーシに白黒の石を使う"
use-contrast-reversi-stones: "リバーシのアイコンにコントラストを付ける"
verified-user: "Conta verificada"
disable-animated-mfm: "Desativar texto animado nas publicações"
suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する"
@@ -165,6 +164,7 @@ common:
hashtags: "Hashtags"
dev: "アプリの作成に失敗しました。再度お試しください。"
ai-chan-kawaii: "藍ちゃかわいい"
you: "あなた"
auth/views/form.vue:
share-access: "<i>{name}</i>があなたのアカウントにアクセスすることを許可しますか?"
permission-ask: "Este aplicativo precisa das seguintes permissões:"
@@ -1054,6 +1054,20 @@ admin/views/charts.vue:
network-requests: "リクエスト"
network-time: "応答時間"
network-usage: "通信量"
admin/views/drive.vue:
sort:
title: "ソート"
createdAtAsc: "アップロード日時が古い順"
createdAtDesc: "アップロード日時が新しい順"
sizeAsc: "サイズが小さい順"
sizeDesc: "サイズが大きい順"
origin:
title: "オリジン"
combined: "ローカル+リモート"
local: "ローカル"
remote: "リモート"
delete: "削除"
deleted: "削除しました"
admin/views/users.vue:
operation: "操作"
username-or-userid: "ユーザー名またはユーザーID"

View File

@@ -111,7 +111,6 @@ common:
i-like-sushi: "私は(プリンよりむしろ)寿司が好き"
show-reversi-board-labels: "リバーシのボードの行と列のラベルを表示"
use-white-black-reversi-stones: "リバーシに白黒の石を使う"
use-contrast-reversi-stones: "リバーシのアイコンにコントラストを付ける"
verified-user: "公式アカウント"
disable-animated-mfm: "Отключить анимированный текст в постах"
suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する"
@@ -165,6 +164,7 @@ common:
hashtags: "Хэштеги"
dev: "Не удалось создать приложение. Пожалуйста, попробуйте ещё раз."
ai-chan-kawaii: "Ai-chan kawaii!"
you: "あなた"
auth/views/form.vue:
share-access: "Вы разрешаете <i>{name}</i> получить доступ к вашему аккаунту?"
permission-ask: "このアプリは次の権限を要求しています:"
@@ -1054,6 +1054,20 @@ admin/views/charts.vue:
network-requests: "リクエスト"
network-time: "応答時間"
network-usage: "通信量"
admin/views/drive.vue:
sort:
title: "ソート"
createdAtAsc: "アップロード日時が古い順"
createdAtDesc: "アップロード日時が新しい順"
sizeAsc: "サイズが小さい順"
sizeDesc: "サイズが大きい順"
origin:
title: "オリジン"
combined: "ローカル+リモート"
local: "ローカル"
remote: "リモート"
delete: "削除"
deleted: "削除しました"
admin/views/users.vue:
operation: "操作"
username-or-userid: "ユーザー名またはユーザーID"

View File

@@ -111,7 +111,6 @@ common:
i-like-sushi: "相比于布丁来说, 我更喜欢寿司。"
show-reversi-board-labels: "在 Reversi 中显示行和列表签"
use-white-black-reversi-stones: "リバーシに白黒の石を使う"
use-contrast-reversi-stones: "Make the stone color clear in Reversi"
verified-user: "认证用户"
disable-animated-mfm: "在帖子中禁用动画文本"
suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する"
@@ -165,6 +164,7 @@ common:
hashtags: "标签"
dev: "构建应用程序失败,请再试一次。"
ai-chan-kawaii: "Ai-chan kawaii!"
you: "あなた"
auth/views/form.vue:
share-access: "您要允许<i>{name}</i>来访问您的账户吗?"
permission-ask: "这个应用程序需要以下权限:"
@@ -1054,6 +1054,20 @@ admin/views/charts.vue:
network-requests: "请求"
network-time: "响应时间"
network-usage: "网络流量"
admin/views/drive.vue:
sort:
title: "ソート"
createdAtAsc: "アップロード日時が古い順"
createdAtDesc: "アップロード日時が新しい順"
sizeAsc: "サイズが小さい順"
sizeDesc: "サイズが大きい順"
origin:
title: "オリジン"
combined: "ローカル+リモート"
local: "ローカル"
remote: "リモート"
delete: "削除"
deleted: "削除しました"
admin/views/users.vue:
operation: "操作"
username-or-userid: "用户名或用户ID"

View File

@@ -1,8 +1,8 @@
{
"name": "misskey",
"author": "syuilo <i@syuilo.com>",
"version": "10.63.1",
"clientVersion": "2.0.12696",
"version": "10.64.2",
"clientVersion": "2.0.12796",
"codename": "nighthike",
"main": "./built/index.js",
"private": true,
@@ -37,7 +37,6 @@
"@types/elasticsearch": "5.0.29",
"@types/file-type": "5.2.2",
"@types/gulp": "3.8.36",
"@types/gulp-htmlmin": "1.3.32",
"@types/gulp-mocha": "0.0.32",
"@types/gulp-rename": "0.0.33",
"@types/gulp-replace": "0.0.31",
@@ -88,7 +87,7 @@
"@types/websocket": "0.0.40",
"@types/ws": "6.0.1",
"animejs": "2.2.0",
"apexcharts": "2.2.4",
"apexcharts": "2.4.2",
"autobind-decorator": "2.4.0",
"autosize": "4.0.2",
"autwh": "0.1.0",
@@ -120,10 +119,8 @@
"fuckadblock": "3.2.1",
"gulp": "3.9.1",
"gulp-cssnano": "2.1.3",
"gulp-htmlmin": "5.0.1",
"gulp-imagemin": "4.1.0",
"gulp-mocha": "6.0.0",
"gulp-pug": "4.0.1",
"gulp-rename": "1.4.0",
"gulp-replace": "1.0.0",
"gulp-sourcemaps": "2.6.4",
@@ -158,7 +155,7 @@
"koa-views": "6.1.4",
"langmap": "0.0.16",
"loader-utils": "1.1.0",
"minio": "7.0.1",
"minio": "7.0.2",
"mkdirp": "0.5.1",
"mocha": "5.2.0",
"moji": "0.5.1",
@@ -228,6 +225,7 @@
"vue-loader": "15.4.2",
"vue-marquee-text-component": "1.1.0",
"vue-router": "3.0.2",
"vue-sequential-entrance": "1.1.3",
"vue-style-loader": "4.1.2",
"vue-svg-inline-loader": "1.2.4",
"vue-template-compiler": "2.5.17",

View File

@@ -64,7 +64,7 @@ export default abstract class Chart<T> {
const keys = {
span: -1,
date: -1
} as any;
} as { [key: string]: 1 | -1; };
if (grouped) keys.group = -1;
this.collection.createIndex(keys, { unique: true });
}

View File

@@ -0,0 +1,175 @@
<template>
<div class="pwnqwyet">
<ui-card>
<div slot="title"><fa :icon="faCloud"/> {{ $t('@.drive') }}</div>
<section class="fit-top">
<ui-horizon-group inputs>
<ui-select v-model="sort">
<span slot="label">{{ $t('sort.title') }}</span>
<option value="-createdAt">{{ $t('sort.createdAtAsc') }}</option>
<option value="+createdAt">{{ $t('sort.createdAtDesc') }}</option>
<option value="-size">{{ $t('sort.sizeAsc') }}</option>
<option value="+size">{{ $t('sort.sizeDesc') }}</option>
</ui-select>
<ui-select v-model="origin">
<span slot="label">{{ $t('origin.title') }}</span>
<option value="combined">{{ $t('origin.combined') }}</option>
<option value="local">{{ $t('origin.local') }}</option>
<option value="remote">{{ $t('origin.remote') }}</option>
</ui-select>
</ui-horizon-group>
<sequential-entrance animation="entranceFromTop" delay="25">
<div class="kidvdlkg" v-for="file in files">
<div @click="file._open = !file._open">
<div>
<div class="thumbnail" :style="thumbnail(file)"></div>
</div>
<div>
<header>
<b>{{ file.name }}</b>
<span class="username">@{{ file.user | acct }}</span>
</header>
<div>
<div>
<span style="margin-right:16px;">{{ file.type }}</span>
<span>{{ file.datasize | bytes }}</span>
</div>
<div><mk-time :time="file.createdAt" mode="detail"/></div>
</div>
</div>
</div>
<div v-show="file._open">
<ui-button @click="del(file)"><fa :icon="faTrashAlt"/> {{ $t('delete') }}</ui-button>
</div>
</div>
</sequential-entrance>
<ui-button v-if="existMore" @click="fetch">{{ $t('@.load-more') }}</ui-button>
</section>
</ui-card>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
import i18n from '../../i18n';
import { faCloud } from '@fortawesome/free-solid-svg-icons';
import { faTrashAlt } from '@fortawesome/free-regular-svg-icons';
export default Vue.extend({
i18n: i18n('admin/views/drive.vue'),
data() {
return {
sort: '+createdAt',
origin: 'combined',
limit: 10,
offset: 0,
files: [],
existMore: false,
faCloud, faTrashAlt
};
},
watch: {
sort() {
this.files = [];
this.offset = 0;
this.fetch();
},
origin() {
this.files = [];
this.offset = 0;
this.fetch();
}
},
mounted() {
this.fetch();
},
methods: {
fetch() {
this.$root.api('admin/drive/files', {
origin: this.origin,
sort: this.sort,
offset: this.offset,
limit: this.limit + 1
}).then(files => {
if (files.length == this.limit + 1) {
files.pop();
this.existMore = true;
} else {
this.existMore = false;
}
for (const x of files) {
x._open = false;
}
this.files = this.files.concat(files);
this.offset += this.limit;
});
},
thumbnail(file: any): any {
return {
'background-color': file.properties.avgColor && file.properties.avgColor.length == 3 ? `rgb(${file.properties.avgColor.join(',')})` : 'transparent',
'background-image': `url(${file.thumbnailUrl})`
};
},
async del(file: any) {
const process = async () => {
await this.$root.api('drive/files/delete', { fileId: file.id });
this.$root.dialog({
type: 'success',
text: this.$t('deleted')
});
};
await process().catch(e => {
this.$root.dialog({
type: 'error',
text: e.toString()
});
});
}
}
});
</script>
<style lang="stylus" scoped>
.pwnqwyet
@media (min-width 500px)
padding 16px
.kidvdlkg
padding 16px 0
border-top solid 1px var(--faceDivider)
> div:first-child
display flex
cursor pointer
> div:nth-child(1)
> .thumbnail
display block
width 64px
height 64px
background-size cover
background-position center center
> div:nth-child(2)
flex 1
padding-left 16px
@media (max-width 500px)
font-size 14px
> header
word-break break-word
> .username
margin-left 8px
opacity 0.7
</style>

View File

@@ -24,24 +24,28 @@
<ui-card>
<div slot="title"><fa :icon="faGrin"/> {{ $t('emojis.title') }}</div>
<section v-for="emoji in emojis">
<img :src="emoji.url" :alt="emoji.name" style="width: 64px;"/>
<ui-horizon-group inputs>
<ui-input v-model="emoji.name">
<span>{{ $t('add-emoji.name') }}</span>
<section v-for="emoji in emojis" class="oryfrbft">
<div>
<img :src="emoji.url" :alt="emoji.name" style="width: 64px;"/>
</div>
<div>
<ui-horizon-group>
<ui-input v-model="emoji.name">
<span>{{ $t('add-emoji.name') }}</span>
</ui-input>
<ui-input v-model="emoji.aliases">
<span>{{ $t('add-emoji.aliases') }}</span>
</ui-input>
</ui-horizon-group>
<ui-input v-model="emoji.url">
<i slot="icon"><fa icon="link"/></i>
<span>{{ $t('add-emoji.url') }}</span>
</ui-input>
<ui-input v-model="emoji.aliases">
<span>{{ $t('add-emoji.aliases') }}</span>
</ui-input>
</ui-horizon-group>
<ui-input v-model="emoji.url">
<i slot="icon"><fa icon="link"/></i>
<span>{{ $t('add-emoji.url') }}</span>
</ui-input>
<ui-horizon-group class="fit-bottom">
<ui-button @click="updateEmoji(emoji)"><fa :icon="['far', 'save']"/> {{ $t('emojis.update') }}</ui-button>
<ui-button @click="removeEmoji(emoji)"><fa :icon="['far', 'trash-alt']"/> {{ $t('emojis.remove') }}</ui-button>
</ui-horizon-group>
<ui-horizon-group class="fit-bottom">
<ui-button @click="updateEmoji(emoji)"><fa :icon="['far', 'save']"/> {{ $t('emojis.update') }}</ui-button>
<ui-button @click="removeEmoji(emoji)"><fa :icon="['far', 'trash-alt']"/> {{ $t('emojis.remove') }}</ui-button>
</ui-horizon-group>
</div>
</section>
</ui-card>
</div>
@@ -150,4 +154,21 @@ export default Vue.extend({
@media (min-width 500px)
padding 16px
.oryfrbft
@media (min-width 500px)
display flex
> div:first-child
@media (max-width 500px)
padding-bottom 16px
> img
vertical-align bottom
> div:last-child
flex 1
@media (min-width 500px)
padding-left 16px
</style>

View File

@@ -22,12 +22,11 @@
<li @click="nav('instance')" :class="{ active: page == 'instance' }"><fa icon="cog" fixed-width/>{{ $t('instance') }}</li>
<li @click="nav('moderators')" :class="{ active: page == 'moderators' }"><fa :icon="faHeadset" fixed-width/>{{ $t('moderators') }}</li>
<li @click="nav('users')" :class="{ active: page == 'users' }"><fa icon="users" fixed-width/>{{ $t('users') }}</li>
<li @click="nav('drive')" :class="{ active: page == 'drive' }"><fa icon="cloud" fixed-width/>{{ $t('@.drive') }}</li>
<!-- <li @click="nav('federation')" :class="{ active: page == 'federation' }"><fa :icon="faShareAlt" fixed-width/>{{ $t('federation') }}</li> -->
<li @click="nav('emoji')" :class="{ active: page == 'emoji' }"><fa :icon="faGrin" fixed-width/>{{ $t('emoji') }}</li>
<li @click="nav('announcements')" :class="{ active: page == 'announcements' }"><fa icon="broadcast-tower" fixed-width/>{{ $t('announcements') }}</li>
<li @click="nav('hashtags')" :class="{ active: page == 'hashtags' }"><fa icon="hashtag" fixed-width/>{{ $t('hashtags') }}</li>
<!-- <li @click="nav('drive')" :class="{ active: page == 'drive' }"><fa icon="cloud" fixed-width/>{{ $t('@.drive') }}</li> -->
</ul>
<div class="back-to-misskey">
<a href="/"><fa :icon="faArrowLeft"/> {{ $t('back-to-misskey') }}</a>
@@ -45,7 +44,7 @@
<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 == 'drive'"><x-drive/></div>
<div v-if="page == 'update'"></div>
</div>
</main>
@@ -63,6 +62,7 @@ import XEmoji from "./emoji.vue";
import XAnnouncements from "./announcements.vue";
import XHashtags from "./hashtags.vue";
import XUsers from "./users.vue";
import XDrive from "./drive.vue";
import { faHeadset, faArrowLeft, faShareAlt } from '@fortawesome/free-solid-svg-icons';
import { faGrin } from '@fortawesome/free-regular-svg-icons';
@@ -79,7 +79,8 @@ export default Vue.extend({
XEmoji,
XAnnouncements,
XHashtags,
XUsers
XUsers,
XDrive,
},
provide: {
isMobile

View File

@@ -32,8 +32,10 @@
<header><fa :icon="faShieldAlt"/> {{ $t('recaptcha-config') }}</header>
<ui-switch v-model="enableRecaptcha">{{ $t('enable-recaptcha') }}</ui-switch>
<ui-info>{{ $t('recaptcha-info') }}</ui-info>
<ui-input v-model="recaptchaSiteKey" :disabled="!enableRecaptcha"><i slot="icon"><fa icon="key"/></i>{{ $t('recaptcha-site-key') }}</ui-input>
<ui-input v-model="recaptchaSecretKey" :disabled="!enableRecaptcha"><i slot="icon"><fa icon="key"/></i>{{ $t('recaptcha-secret-key') }}</ui-input>
<ui-horizon-group inputs>
<ui-input v-model="recaptchaSiteKey" :disabled="!enableRecaptcha"><i slot="icon"><fa icon="key"/></i>{{ $t('recaptcha-site-key') }}</ui-input>
<ui-input v-model="recaptchaSecretKey" :disabled="!enableRecaptcha"><i slot="icon"><fa icon="key"/></i>{{ $t('recaptcha-secret-key') }}</ui-input>
</ui-horizon-group>
</section>
<section>
<header><fa :icon="faGhost"/> {{ $t('proxy-account-config') }}</header>
@@ -82,9 +84,11 @@
<div slot="title"><fa :icon="['fab', 'twitter']"/> {{ $t('twitter-integration-config') }}</div>
<section>
<ui-switch v-model="enableTwitterIntegration">{{ $t('enable-twitter-integration') }}</ui-switch>
<ui-horizon-group>
<ui-input v-model="twitterConsumerKey" :disabled="!enableTwitterIntegration"><i slot="icon"><fa icon="key"/></i>{{ $t('twitter-integration-consumer-key') }}</ui-input>
<ui-input v-model="twitterConsumerSecret" :disabled="!enableTwitterIntegration"><i slot="icon"><fa icon="key"/></i>{{ $t('twitter-integration-consumer-secret') }}</ui-input>
</ui-horizon-group>
<ui-info>{{ $t('twitter-integration-info', { url: `${url}/api/tw/cb` }) }}</ui-info>
<ui-input v-model="twitterConsumerKey" :disabled="!enableTwitterIntegration"><i slot="icon"><fa icon="key"/></i>{{ $t('twitter-integration-consumer-key') }}</ui-input>
<ui-input v-model="twitterConsumerSecret" :disabled="!enableTwitterIntegration"><i slot="icon"><fa icon="key"/></i>{{ $t('twitter-integration-consumer-secret') }}</ui-input>
<ui-button @click="updateMeta">{{ $t('save') }}</ui-button>
</section>
</ui-card>
@@ -93,9 +97,11 @@
<div slot="title"><fa :icon="['fab', 'github']"/> {{ $t('github-integration-config') }}</div>
<section>
<ui-switch v-model="enableGithubIntegration">{{ $t('enable-github-integration') }}</ui-switch>
<ui-horizon-group>
<ui-input v-model="githubClientId" :disabled="!enableGithubIntegration"><i slot="icon"><fa icon="key"/></i>{{ $t('github-integration-client-id') }}</ui-input>
<ui-input v-model="githubClientSecret" :disabled="!enableGithubIntegration"><i slot="icon"><fa icon="key"/></i>{{ $t('github-integration-client-secret') }}</ui-input>
</ui-horizon-group>
<ui-info>{{ $t('github-integration-info', { url: `${url}/api/gh/cb` }) }}</ui-info>
<ui-input v-model="githubClientId" :disabled="!enableGithubIntegration"><i slot="icon"><fa icon="key"/></i>{{ $t('github-integration-client-id') }}</ui-input>
<ui-input v-model="githubClientSecret" :disabled="!enableGithubIntegration"><i slot="icon"><fa icon="key"/></i>{{ $t('github-integration-client-secret') }}</ui-input>
<ui-button @click="updateMeta">{{ $t('save') }}</ui-button>
</section>
</ui-card>
@@ -104,9 +110,11 @@
<div slot="title"><fa :icon="['fab', 'discord']"/> {{ $t('discord-integration-config') }}</div>
<section>
<ui-switch v-model="enableDiscordIntegration">{{ $t('enable-discord-integration') }}</ui-switch>
<ui-horizon-group>
<ui-input v-model="discordClientId" :disabled="!enableDiscordIntegration"><i slot="icon"><fa icon="key"/></i>{{ $t('discord-integration-client-id') }}</ui-input>
<ui-input v-model="discordClientSecret" :disabled="!enableDiscordIntegration"><i slot="icon"><fa icon="key"/></i>{{ $t('discord-integration-client-secret') }}</ui-input>
</ui-horizon-group>
<ui-info>{{ $t('discord-integration-info', { url: `${url}/api/dc/cb` }) }}</ui-info>
<ui-input v-model="discordClientId" :disabled="!enableDiscordIntegration"><i slot="icon"><fa icon="key"/></i>{{ $t('discord-integration-client-id') }}</ui-input>
<ui-input v-model="discordClientSecret" :disabled="!enableDiscordIntegration"><i slot="icon"><fa icon="key"/></i>{{ $t('discord-integration-client-secret') }}</ui-input>
<ui-button @click="updateMeta">{{ $t('save') }}</ui-button>
</section>
</ui-card>

View File

@@ -38,25 +38,27 @@
<option value="remote">{{ $t('users.origin.remote') }}</option>
</ui-select>
</ui-horizon-group>
<div class="kofvwchc" v-for="user in users">
<div>
<a :href="user | userPage(null, true)">
<mk-avatar class="avatar" :user="user" :disable-link="true"/>
</a>
</div>
<div>
<header>
<b><mk-user-name :user="user"/></b>
<span class="username">@{{ user | acct }}</span>
</header>
<sequential-entrance animation="entranceFromTop" delay="25">
<div class="kofvwchc" v-for="user in users">
<div>
<span>{{ $t('users.updatedAt') }}: <mk-time :time="user.updatedAt" mode="detail"/></span>
<a :href="user | userPage(null, true)">
<mk-avatar class="avatar" :user="user" :disable-link="true"/>
</a>
</div>
<div>
<span>{{ $t('users.createdAt') }}: <mk-time :time="user.createdAt" mode="detail"/></span>
<header>
<b><mk-user-name :user="user"/></b>
<span class="username">@{{ user | acct }}</span>
</header>
<div>
<span>{{ $t('users.updatedAt') }}: <mk-time :time="user.updatedAt" mode="detail"/></span>
</div>
<div>
<span>{{ $t('users.createdAt') }}: <mk-time :time="user.createdAt" mode="detail"/></span>
</div>
</div>
</div>
</div>
</sequential-entrance>
<ui-button v-if="existMore" @click="fetchUsers">{{ $t('@.load-more') }}</ui-button>
</section>
</ui-card>
@@ -274,6 +276,9 @@ export default Vue.extend({
flex 1
padding-left 16px
@media (max-width 500px)
font-size 14px
> header
> .username
margin-left 8px

View File

@@ -10,3 +10,19 @@
opacity: 0;
transform: scaleY(0);
}
.entranceFromTop {
animation-duration: 0.5s;
animation-name: entranceFromTop;
}
@keyframes entranceFromTop {
from {
opacity: 0;
transform: translateY(-64px);
}
to {
opacity: 1;
transform: translateY(0);
}
}

View File

@@ -0,0 +1,25 @@
/**
* Format like the uptime command
*/
export default function(sec) {
if (!sec) return sec;
const day = Math.floor(sec / 86400);
const tod = sec % 86400;
// Days part in string: 2 days, 1 day, null
const d = day >= 2 ? `${day} days` : day >= 1 ? `${day} day` : null;
// Time part in string: 1 sec, 1 min, 1:01
const t
= tod < 60 ? `${Math.floor(tod)} sec`
: tod < 3600 ? `${Math.floor(tod / 60)} min`
: `${Math.floor(tod / 60 / 60)}:${Math.floor((tod / 60) % 60).toString().padStart(2, "0")}`;
let str = '';
if (d) str += `${d}, `;
str += t;
return str;
}

View File

@@ -32,7 +32,7 @@
<script lang="ts">
import Vue from 'vue';
import { themeColor } from '../../../config';
import * as tinycolor from 'tinycolor2';
export default Vue.extend({
props: {
@@ -75,7 +75,7 @@ export default Vue.extend({
return this.dark ? '#fff' : '#777';
},
hHandColor(): string {
return themeColor;
return tinycolor(getComputedStyle(document.documentElement).getPropertyValue('--themeColor')).toHexString();
},
ms(): number {

View File

@@ -31,8 +31,8 @@
@click="set(i)"
:title="`${String.fromCharCode(65 + o.transformPosToXy(i)[0])}${o.transformPosToXy(i)[1] + 1}`">
<template v-if="!$store.state.settings.games.reversi.useWhiteBlackStones">
<img v-if="stone === true" :src="blackUser.avatarUrl" alt="black" :class="{ contrast: $store.state.settings.games.reversi.useContrastStones }">
<img v-if="stone === false" :src="whiteUser.avatarUrl" alt="white" :class="{ contrast: $store.state.settings.games.reversi.useContrastStones }">
<img v-if="stone === true" :src="blackUser.avatarUrl" alt="black">
<img v-if="stone === false" :src="whiteUser.avatarUrl" alt="white">
</template>
<template v-if="$store.state.settings.games.reversi.useWhiteBlackStones">
<fa v-if="stone === true" :icon="fasCircle"/>
@@ -430,13 +430,6 @@ export default Vue.extend({
width 100%
height 100%
&.contrast
&[alt="black"]
filter brightness(.5)
&[alt="white"]
filter brightness(2)
> .graph
display grid
grid-template-columns repeat(61, 1fr)

View File

@@ -60,7 +60,7 @@
<div>
<template v-for="item in form">
<ui-switch v-if="item.type == 'switch'" v-model="item.value" :key="item.id" :text="item.label" @change="onChangeForm(item)">{{ item.desc || '' }}</ui-switch>
<ui-switch v-if="item.type == 'switch'" v-model="item.value" :key="item.id" @change="onChangeForm(item)">{{ item.label || item.desc || '' }}</ui-switch>
<div class="card" v-if="item.type == 'radio'" :key="item.id">
<header>

View File

@@ -1,22 +1,22 @@
<template>
<ui-card>
<ui-card v-if="enableTwitterIntegration || enableDiscordIntegration || enableGithubIntegration">
<div slot="title"><fa icon="share-alt"/> {{ $t('title') }}</div>
<section>
<section v-if="enableTwitterIntegration">
<header><fa :icon="['fab', 'twitter']"/> Twitter</header>
<p v-if="$store.state.i.twitter">{{ $t('connected-to') }}: <a :href="`https://twitter.com/${$store.state.i.twitter.screenName}`" target="_blank">@{{ $store.state.i.twitter.screenName }}</a></p>
<ui-button v-if="$store.state.i.twitter" @click="disconnectTwitter">{{ $t('disconnect') }}</ui-button>
<ui-button v-else @click="connectTwitter">{{ $t('connect') }}</ui-button>
</section>
<section>
<section v-if="enableDiscordIntegration">
<header><fa :icon="['fab', 'discord']"/> Discord</header>
<p v-if="$store.state.i.discord">{{ $t('connected-to') }}: <a :href="`https://discordapp.com/users/${$store.state.i.discord.id}`" target="_blank">@{{ $store.state.i.discord.username }}#{{ $store.state.i.discord.discriminator }}</a></p>
<ui-button v-if="$store.state.i.discord" @click="disconnectDiscord">{{ $t('disconnect') }}</ui-button>
<ui-button v-else @click="connectDiscord">{{ $t('connect') }}</ui-button>
</section>
<section>
<section v-if="enableGithubIntegration">
<header><fa :icon="['fab', 'github']"/> GitHub</header>
<p v-if="$store.state.i.github">{{ $t('connected-to') }}: <a :href="`https://github.com/${$store.state.i.github.login}`" target="_blank">@{{ $store.state.i.github.login }}</a></p>
<ui-button v-if="$store.state.i.github" @click="disconnectGithub">{{ $t('disconnect') }}</ui-button>
@@ -39,9 +39,20 @@ export default Vue.extend({
twitterForm: null,
discordForm: null,
githubForm: null,
enableTwitterIntegration: false,
enableDiscordIntegration: false,
enableGithubIntegration: false,
};
},
created() {
this.$root.getMeta().then(meta => {
this.enableTwitterIntegration = meta.enableTwitterIntegration;
this.enableDiscordIntegration = meta.enableDiscordIntegration;
this.enableGithubIntegration = meta.enableGithubIntegration;
});
},
mounted() {
document.cookie = `i=${this.$store.state.i.token}`;
this.$watch('$store.state.i', () => {

View File

@@ -9,7 +9,7 @@
@keypress="onKeypress"
@paste="onPaste"
:placeholder="$t('input-message-here')"
v-autocomplete="'text'"
v-autocomplete="{ model: 'text' }"
></textarea>
<div class="file" @click="file = null" v-if="file">{{ file.name }}</div>
<mk-uploader ref="uploader" @uploaded="onUploaded"/>

File diff suppressed because one or more lines are too long

View File

@@ -4,16 +4,16 @@
<div class="popover" :class="{ compact, big }" ref="popover">
<p v-if="!compact">{{ title }}</p>
<div ref="buttons" :class="{ showFocus }">
<button @click="react('like')" @mouseover="onMouseover" @mouseout="onMouseout" tabindex="1" :title="$t('@.reactions.like')"><mk-reaction-icon reaction='like'/></button>
<button @click="react('love')" @mouseover="onMouseover" @mouseout="onMouseout" tabindex="2" :title="$t('@.reactions.love')"><mk-reaction-icon reaction='love'/></button>
<button @click="react('laugh')" @mouseover="onMouseover" @mouseout="onMouseout" tabindex="3" :title="$t('@.reactions.laugh')"><mk-reaction-icon reaction='laugh'/></button>
<button @click="react('hmm')" @mouseover="onMouseover" @mouseout="onMouseout" tabindex="4" :title="$t('@.reactions.hmm')"><mk-reaction-icon reaction='hmm'/></button>
<button @click="react('surprise')" @mouseover="onMouseover" @mouseout="onMouseout" tabindex="5" :title="$t('@.reactions.surprise')"><mk-reaction-icon reaction='surprise'/></button>
<button @click="react('congrats')" @mouseover="onMouseover" @mouseout="onMouseout" tabindex="6" :title="$t('@.reactions.congrats')"><mk-reaction-icon reaction='congrats'/></button>
<button @click="react('angry')" @mouseover="onMouseover" @mouseout="onMouseout" tabindex="7" :title="$t('@.reactions.angry')"><mk-reaction-icon reaction='angry'/></button>
<button @click="react('confused')" @mouseover="onMouseover" @mouseout="onMouseout" tabindex="8" :title="$t('@.reactions.confused')"><mk-reaction-icon reaction='confused'/></button>
<button @click="react('rip')" @mouseover="onMouseover" @mouseout="onMouseout" tabindex="9" :title="$t('@.reactions.rip')"><mk-reaction-icon reaction='rip'/></button>
<button @click="react('pudding')" @mouseover="onMouseover" @mouseout="onMouseout" tabindex="10" :title="$t('@.reactions.pudding')"><mk-reaction-icon reaction='pudding'/></button>
<button @click="react('like')" @mouseover="onMouseover" @mouseout="onMouseout" tabindex="1" :title="$t('@.reactions.like')" v-particle><mk-reaction-icon reaction="like"/></button>
<button @click="react('love')" @mouseover="onMouseover" @mouseout="onMouseout" tabindex="2" :title="$t('@.reactions.love')" v-particle><mk-reaction-icon reaction="love"/></button>
<button @click="react('laugh')" @mouseover="onMouseover" @mouseout="onMouseout" tabindex="3" :title="$t('@.reactions.laugh')" v-particle><mk-reaction-icon reaction="laugh"/></button>
<button @click="react('hmm')" @mouseover="onMouseover" @mouseout="onMouseout" tabindex="4" :title="$t('@.reactions.hmm')" v-particle><mk-reaction-icon reaction="hmm"/></button>
<button @click="react('surprise')" @mouseover="onMouseover" @mouseout="onMouseout" tabindex="5" :title="$t('@.reactions.surprise')" v-particle><mk-reaction-icon reaction="surprise"/></button>
<button @click="react('congrats')" @mouseover="onMouseover" @mouseout="onMouseout" tabindex="6" :title="$t('@.reactions.congrats')" v-particle><mk-reaction-icon reaction="congrats"/></button>
<button @click="react('angry')" @mouseover="onMouseover" @mouseout="onMouseout" tabindex="7" :title="$t('@.reactions.angry')" v-particle><mk-reaction-icon reaction="angry"/></button>
<button @click="react('confused')" @mouseover="onMouseover" @mouseout="onMouseout" tabindex="8" :title="$t('@.reactions.confused')" v-particle><mk-reaction-icon reaction="confused"/></button>
<button @click="react('rip')" @mouseover="onMouseover" @mouseout="onMouseout" tabindex="9" :title="$t('@.reactions.rip')" v-particle><mk-reaction-icon reaction="rip"/></button>
<button @click="react('pudding')" @mouseover="onMouseover" @mouseout="onMouseout" tabindex="10" :title="$t('@.reactions.pudding')" v-particle><mk-reaction-icon reaction="pudding"/></button>
</div>
</div>
</div>

View File

@@ -1,36 +1,106 @@
<template>
<div class="mk-reactions-viewer">
<template v-if="reactions">
<span :class="{ reacted: note.myReaction == 'like' }" @click="react('like')" v-if="reactions.like"><mk-reaction-icon reaction="like"/><span>{{ reactions.like }}</span></span>
<span :class="{ reacted: note.myReaction == 'love' }" @click="react('love')" v-if="reactions.love"><mk-reaction-icon reaction="love"/><span>{{ reactions.love }}</span></span>
<span :class="{ reacted: note.myReaction == 'laugh' }" @click="react('laugh')" v-if="reactions.laugh"><mk-reaction-icon reaction="laugh"/><span>{{ reactions.laugh }}</span></span>
<span :class="{ reacted: note.myReaction == 'hmm' }" @click="react('hmm')" v-if="reactions.hmm"><mk-reaction-icon reaction="hmm"/><span>{{ reactions.hmm }}</span></span>
<span :class="{ reacted: note.myReaction == 'surprise' }" @click="react('surprise')" v-if="reactions.surprise"><mk-reaction-icon reaction="surprise"/><span>{{ reactions.surprise }}</span></span>
<span :class="{ reacted: note.myReaction == 'congrats' }" @click="react('congrats')" v-if="reactions.congrats"><mk-reaction-icon reaction="congrats"/><span>{{ reactions.congrats }}</span></span>
<span :class="{ reacted: note.myReaction == 'angry' }" @click="react('angry')" v-if="reactions.angry"><mk-reaction-icon reaction="angry"/><span>{{ reactions.angry }}</span></span>
<span :class="{ reacted: note.myReaction == 'confused' }" @click="react('confused')" v-if="reactions.confused"><mk-reaction-icon reaction="confused"/><span>{{ reactions.confused }}</span></span>
<span :class="{ reacted: note.myReaction == 'rip' }" @click="react('rip')" v-if="reactions.rip"><mk-reaction-icon reaction="rip"/><span>{{ reactions.rip }}</span></span>
<span :class="{ reacted: note.myReaction == 'pudding' }" @click="react('pudding')" v-if="reactions.pudding"><mk-reaction-icon reaction="pudding"/><span>{{ reactions.pudding }}</span></span>
<span :class="{ reacted: note.myReaction == 'like' }" @click="react('like')" v-if="reactions.like" v-particle><mk-reaction-icon reaction="like" ref="like"/><span>{{ reactions.like }}</span></span>
<span :class="{ reacted: note.myReaction == 'love' }" @click="react('love')" v-if="reactions.love" v-particle><mk-reaction-icon reaction="love" ref="love"/><span>{{ reactions.love }}</span></span>
<span :class="{ reacted: note.myReaction == 'laugh' }" @click="react('laugh')" v-if="reactions.laugh" v-particle><mk-reaction-icon reaction="laugh" ref="laugh"/><span>{{ reactions.laugh }}</span></span>
<span :class="{ reacted: note.myReaction == 'hmm' }" @click="react('hmm')" v-if="reactions.hmm" v-particle><mk-reaction-icon reaction="hmm" ref="hmm"/><span>{{ reactions.hmm }}</span></span>
<span :class="{ reacted: note.myReaction == 'surprise' }" @click="react('surprise')" v-if="reactions.surprise" v-particle><mk-reaction-icon reaction="surprise" ref="surprise"/><span>{{ reactions.surprise }}</span></span>
<span :class="{ reacted: note.myReaction == 'congrats' }" @click="react('congrats')" v-if="reactions.congrats" v-particle><mk-reaction-icon reaction="congrats" ref="congrats"/><span>{{ reactions.congrats }}</span></span>
<span :class="{ reacted: note.myReaction == 'angry' }" @click="react('angry')" v-if="reactions.angry" v-particle><mk-reaction-icon reaction="angry" ref="angry"/><span>{{ reactions.angry }}</span></span>
<span :class="{ reacted: note.myReaction == 'confused' }" @click="react('confused')" v-if="reactions.confused" v-particle><mk-reaction-icon reaction="confused" ref="confused"/><span>{{ reactions.confused }}</span></span>
<span :class="{ reacted: note.myReaction == 'rip' }" @click="react('rip')" v-if="reactions.rip" v-particle><mk-reaction-icon reaction="rip" ref="rip"/><span>{{ reactions.rip }}</span></span>
<span :class="{ reacted: note.myReaction == 'pudding' }" @click="react('pudding')" v-if="reactions.pudding" v-particle><mk-reaction-icon reaction="pudding" ref="pudding"/><span>{{ reactions.pudding }}</span></span>
</template>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
import Icon from './reaction-icon.vue';
import * as anime from 'animejs';
export default Vue.extend({
props: ['note'],
computed: {
reactions(): number {
reactions(): any {
return this.note.reactionCounts;
}
},
watch: {
'reactions.like'() {
this.anime('like');
},
'reactions.love'() {
this.anime('love');
},
'reactions.laugh'() {
this.anime('laugh');
},
'reactions.hmm'() {
this.anime('hmm');
},
'reactions.surprise'() {
this.anime('surprise');
},
'reactions.congrats'() {
this.anime('congrats');
},
'reactions.angry'() {
this.anime('angry');
},
'reactions.confused'() {
this.anime('confused');
},
'reactions.rip'() {
this.anime('rip');
},
'reactions.pudding'() {
this.anime('pudding');
}
},
methods: {
react(reaction: string) {
this.$root.api('notes/reactions/create', {
noteId: this.note.id,
reaction: reaction
});
},
anime(reaction: string) {
if (this.$store.state.device.reduceMotion) return;
this.$nextTick(() => {
const rect = this.$refs[reaction].$el.getBoundingClientRect();
const x = rect.left;
const y = rect.top;
const icon = new Icon({
parent: this,
propsData: {
reaction: reaction
}
}).$mount();
icon.$el.style.position = 'absolute';
icon.$el.style.zIndex = 100;
icon.$el.style.top = (y + window.scrollY) + 'px';
icon.$el.style.left = (x + window.scrollX) + 'px';
icon.$el.style.fontSize = window.getComputedStyle(this.$refs[reaction].$el).fontSize;
document.body.appendChild(icon.$el);
anime({
targets: icon.$el,
opacity: [1, 0],
translateY: [0, -64],
duration: 1000,
easing: 'linear',
complete: () => {
icon.destroyDom();
}
});
});
}
}
});

View File

@@ -1,7 +1,7 @@
<template>
<component class="dmtdnykelhudezerjlfpbhgovrgnqqgr"
:is="link ? 'a' : 'button'"
:class="[styl, { inline, primary }]"
:class="{ inline, primary, wait }"
:type="type"
@click="$emit('click')"
@mousedown="onMousedown"
@@ -48,11 +48,11 @@ export default Vue.extend({
required: false,
default: false
},
},
data() {
return {
styl: 'fill'
};
wait: {
type: Boolean,
required: false,
default: false
},
},
mounted() {
if (this.autofocus) {
@@ -121,6 +121,24 @@ export default Vue.extend({
box-shadow none
text-decoration none
user-select none
color var(--text)
background var(--buttonBg)
&:not(:disabled):hover
background var(--buttonHoverBg)
&:not(:disabled):active
background var(--buttonActiveBg)
&.primary
color var(--primaryForeground)
background var(--primary)
&:not(:disabled):hover
background var(--primaryLighten5)
&:not(:disabled):active
background var(--primaryDarken5)
*
pointer-events none
@@ -152,35 +170,25 @@ export default Vue.extend({
&.primary
font-weight bold
&.fill
color var(--text)
background var(--buttonBg)
&.wait
background linear-gradient(
45deg,
var(--primaryDarken10) 25%,
var(--primary) 25%,
var(--primary) 50%,
var(--primaryDarken10) 50%,
var(--primaryDarken10) 75%,
var(--primary) 75%,
var(--primary)
)
background-size 32px 32px
animation stripe-bg 1.5s linear infinite
opacity 0.7
cursor wait
&:not(:disabled):hover
background var(--buttonHoverBg)
&:not(:disabled):active
background var(--buttonActiveBg)
&.primary
color var(--primaryForeground)
background var(--primary)
&:not(:disabled):hover
background var(--primaryLighten5)
&:not(:disabled):active
background var(--primaryDarken5)
&:not(.fill)
color var(--primary)
background none
&:not(:disabled):hover
color var(--primaryDarken5)
&:not(:disabled):active
background var(--primaryAlpha03)
@keyframes stripe-bg
from {background-position: 0 0;}
to {background-position: -64px 32px;}
> .ripples
position absolute

View File

@@ -170,6 +170,9 @@ export default Vue.extend({
return;
}
if (url.hostname === 'music.youtube.com')
url.hostname = 'youtube.com';
fetch(`/url?url=${encodeURIComponent(this.url)}`).then(res => {
res.json().then(info => {
if (info.url == null) return;

View File

@@ -21,21 +21,23 @@ class Autocomplete {
private suggestion: any;
private textarea: any;
private vm: any;
private model: any;
private currentType: string;
private opts: {
model: string;
};
private get text(): string {
return this.vm[this.model];
return this.vm[this.opts.model];
}
private set text(text: string) {
this.vm[this.model] = text;
this.vm[this.opts.model] = text;
}
/**
* 対象のテキストエリアを与えてインスタンスを初期化します。
*/
constructor(textarea, vm, model) {
constructor(textarea, vm, opts) {
//#region BIND
this.onInput = this.onInput.bind(this);
this.complete = this.complete.bind(this);
@@ -45,7 +47,7 @@ class Autocomplete {
this.suggestion = null;
this.textarea = textarea;
this.vm = vm;
this.model = model;
this.opts = opts;
}
/**

View File

@@ -1,5 +1,7 @@
import Vue from 'vue';
import autocomplete from './autocomplete';
import particle from './particle';
Vue.directive('autocomplete', autocomplete);
Vue.directive('particle', particle);

View File

@@ -0,0 +1,24 @@
import Particle from '../components/particle.vue';
export default {
bind(el, binding, vn) {
if (vn.context.$store.state.device.reduceMotion) return;
el.addEventListener('click', () => {
const rect = el.getBoundingClientRect();
const x = rect.left + (el.clientWidth / 2);
const y = rect.top + (el.clientHeight / 2);
const particle = new Particle({
parent: vn.context,
propsData: {
x,
y
}
}).$mount();
document.body.appendChild(particle.$el);
});
}
};

View File

@@ -1,13 +1,14 @@
<template>
<div class="uptimes">
<p>Uptimes</p>
<p>Process: {{ process ? process.toFixed(0) : '---' }}s</p>
<p>OS: {{ os ? os.toFixed(0) : '---' }}s</p>
<p>Process: {{ process }}</p>
<p>OS: {{ os }}</p>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
import formatUptime from '../../scripts/format-uptime';
export default Vue.extend({
props: ['connection'],
@@ -25,8 +26,8 @@ export default Vue.extend({
},
methods: {
onStats(stats) {
this.process = stats.process_uptime;
this.os = stats.os_uptime;
this.process = formatUptime(stats.process_uptime);
this.os = formatUptime(stats.os_uptime);
}
}
});

View File

@@ -16,7 +16,6 @@ export const wsUrl = url.replace('http://', 'ws://').replace('https://', 'wss://
export const lang = window.lang;
export const langs = _LANGS_;
export const locale = JSON.parse(localStorage.getItem('locale'));
export const themeColor = _THEME_COLOR_;
export const copyright = _COPYRIGHT_;
export const version = _VERSION_;
export const clientVersion = _CLIENT_VERSION_;

View File

@@ -16,13 +16,13 @@
<b>{{ $t('recent-tags') }}:</b>
<a v-for="tag in recentHashtags.slice(0, 5)" @click="addTag(tag)" :title="$t('click-to-tagging')">#{{ tag }}</a>
</div>
<div class="local-only" v-if="this.localOnly == true">{{ $t('local-only-message') }}</div>
<input v-show="useCw" ref="cw" v-model="cw" :placeholder="$t('annotations')" v-autocomplete="'cw'">
<div class="local-only" v-if="localOnly == true">{{ $t('local-only-message') }}</div>
<input v-show="useCw" ref="cw" v-model="cw" :placeholder="$t('annotations')" v-autocomplete="{ model: 'cw' }">
<div class="textarea">
<textarea :class="{ with: (files.length != 0 || poll) }"
ref="text" v-model="text" :disabled="posting"
@keydown="onKeydown" @paste="onPaste" :placeholder="placeholder"
v-autocomplete="'text'"
v-autocomplete="{ model: 'text' }"
></textarea>
<button class="emoji" @click="emoji" ref="emoji">
<fa :icon="['far', 'laugh']"/>
@@ -54,9 +54,9 @@
<span v-if="visibility === 'private'"><fa icon="lock"/></span>
</button>
<p class="text-count" :class="{ over: trimmedLength(text) > maxNoteTextLength }">{{ maxNoteTextLength - trimmedLength(text) }}</p>
<button :class="{ posting }" class="submit" :disabled="!canPost" @click="post">
<ui-button primary :wait="posting" class="submit" :disabled="!canPost" @click="post">
{{ posting ? $t('posting') : submitText }}<mk-ellipsis v-if="posting"/>
</button>
</ui-button>
<input ref="file" type="file" multiple="multiple" tabindex="-1" @change="onChangeFile"/>
<div class="dropzone" v-if="draghover"></div>
</div>
@@ -684,62 +684,8 @@ export default Vue.extend({
position absolute
bottom 16px
right 16px
cursor pointer
padding 0
margin 0
width 110px
height 40px
font-size 1em
color var(--primaryForeground)
background var(--primary)
outline none
border none
border-radius 4px
&:not(:disabled)
font-weight bold
&:hover:not(:disabled)
background var(--primaryLighten5)
&:active:not(:disabled)
background var(--primaryDarken5)
&:focus
&:after
content ""
pointer-events none
position absolute
top -5px
right -5px
bottom -5px
left -5px
border 2px solid var(--primaryAlpha03)
border-radius 8px
&:disabled
opacity 0.7
cursor default
&.wait
background linear-gradient(
45deg,
var(--primaryDarken10) 25%,
var(--primary) 25%,
var(--primary) 50%,
var(--primaryDarken10) 50%,
var(--primaryDarken10) 75%,
var(--primary) 75%,
var(--primary)
)
background-size 32px 32px
animation stripe-bg 1.5s linear infinite
opacity 0.7
cursor wait
@keyframes stripe-bg
from {background-position: 0 0;}
to {background-position: -64px 32px;}
> .text-count
pointer-events none

View File

@@ -137,7 +137,6 @@
<section>
<ui-switch v-model="games_reversi_showBoardLabels">{{ $t('@.show-reversi-board-labels') }}</ui-switch>
<ui-switch v-model="games_reversi_useWhiteBlackStones">{{ $t('@.use-white-black-reversi-stones') }}</ui-switch>
<ui-switch v-model="games_reversi_useContrastStones">{{ $t('@.use-contrast-reversi-stones') }}</ui-switch>
</section>
</ui-card>
@@ -511,11 +510,6 @@ export default Vue.extend({
set(value) { this.$store.dispatch('settings/set', { key: 'games.reversi.useWhiteBlackStones', value }); }
},
games_reversi_useContrastStones: {
get() { return this.$store.state.settings.games.reversi.useContrastStones; },
set(value) { this.$store.dispatch('settings/set', { key: 'games.reversi.useContrastStones', value }); }
},
disableAnimatedMfm: {
get() { return this.$store.state.settings.disableAnimatedMfm; },
set(value) { this.$store.dispatch('settings/set', { key: 'disableAnimatedMfm', value }); }

View File

@@ -1,7 +1,7 @@
<template>
<form class="search" @submit.prevent="onSubmit">
<form class="wlvfdpkp" @submit.prevent="onSubmit">
<i><fa icon="search"/></i>
<input v-model="q" type="search" :placeholder="$t('placeholder')"/>
<input v-model="q" type="search" :placeholder="$t('placeholder')" v-autocomplete="{ model: 'q' }"/>
<div class="result"></div>
</form>
</template>
@@ -19,10 +19,13 @@ export default Vue.extend({
},
methods: {
onSubmit() {
if (this.q.startsWith('#')) {
this.$router.push(`/tags/${encodeURIComponent(this.q.substr(1))}`);
const q = this.q.trim();
if (q.startsWith('@')) {
this.$router.push(`/${q}`);
} else if (q.startsWith('#')) {
this.$router.push(`/tags/${encodeURIComponent(q.substr(1))}`);
} else {
this.$router.push(`/search?q=${encodeURIComponent(this.q)}`);
this.$router.push(`/search?q=${encodeURIComponent(q)}`);
}
}
}
@@ -30,7 +33,7 @@ export default Vue.extend({
</script>
<style lang="stylus" scoped>
.search
.wlvfdpkp
@media (max-width 800px)
display none !important

View File

@@ -11,7 +11,7 @@
<mk-error v-if="!fetching && requestInitPromise != null" @retry="resolveInitPromise"/>
<!-- トランジションを有効にするとなぜかメモリリークする -->
<transition-group name="mk-notes" class="transition notes" ref="notes">
<transition-group name="mk-notes" class="transition notes" ref="notes" tag="div">
<template v-for="(note, i) in _notes">
<x-note
:note="note"

View File

@@ -7,7 +7,7 @@
</div>
<!-- トランジションを有効にするとなぜかメモリリークする -->
<component :is="!$store.state.device.reduceMotion ? 'transition-group' : 'div'" name="mk-notifications" class="transition notifications">
<component :is="!$store.state.device.reduceMotion ? 'transition-group' : 'div'" name="mk-notifications" class="transition notifications" tag="div">
<template v-for="(notification, i) in _notifications">
<x-notification class="notification" :notification="notification" :key="notification.id"/>
<p class="date" v-if="i != notifications.length - 1 && notification._date != _notifications[i + 1]._date" :key="notification.id + '-time'">

View File

@@ -1,9 +1,11 @@
<template>
<mk-ui>
<main v-if="!fetching">
<template v-for="favorite in favorites">
<mk-note-detail class="post" :note="favorite.note" :key="favorite.note.id"/>
</template>
<sequential-entrance animation="entranceFromTop" delay="25">
<template v-for="favorite in favorites">
<mk-note-detail class="post" :note="favorite.note" :key="favorite.note.id"/>
</template>
</sequential-entrance>
<div class="more" v-if="existMore">
<ui-button inline @click="more">{{ $t('@.load-more') }}</ui-button>
</div>
@@ -75,7 +77,7 @@ main
padding 16px
max-width 700px
> .post
> * > .post
margin-bottom 16px
> .more

View File

@@ -15,7 +15,7 @@
@paste="onPaste"
:placeholder="placeholder"
ref="text"
v-autocomplete="'text'"
v-autocomplete="{ model: 'text' }"
></textarea>
<button class="emoji" @click="emoji" ref="emoji">
<fa :icon="['far', 'laugh']"/>

View File

@@ -8,6 +8,7 @@ import VueRouter from 'vue-router';
import VAnimateCss from 'v-animate-css';
import VModal from 'vue-js-modal';
import VueI18n from 'vue-i18n';
import SequentialEntrance from 'vue-sequential-entrance';
import VueHotkey from './common/hotkey';
import App from './app.vue';
@@ -287,6 +288,7 @@ Vue.use(VAnimateCss);
Vue.use(VModal);
Vue.use(VueHotkey);
Vue.use(VueI18n);
Vue.use(SequentialEntrance);
Vue.component('fa', FontAwesomeIcon);

View File

@@ -7,7 +7,7 @@
</div>
<!-- トランジションを有効にするとなぜかメモリリークする -->
<component :is="!$store.state.device.reduceMotion ? 'transition-group' : 'div'" name="mk-notifications" class="transition notifications">
<component :is="!$store.state.device.reduceMotion ? 'transition-group' : 'div'" name="mk-notifications" class="transition notifications" tag="div">
<template v-for="(notification, i) in _notifications">
<mk-notification :notification="notification" :key="notification.id"/>
<p class="date" :key="notification.id + '_date'" v-if="i != notifications.length - 1 && notification._date != _notifications[i + 1]._date">

View File

@@ -19,8 +19,8 @@
</span>
<a @click="addVisibleUser">+{{ $t('add-visible-user') }}</a>
</div>
<input v-show="useCw" ref="cw" v-model="cw" :placeholder="$t('annotations')" v-autocomplete="'cw'">
<textarea v-model="text" ref="text" :disabled="posting" :placeholder="placeholder" v-autocomplete="'text'"></textarea>
<input v-show="useCw" ref="cw" v-model="cw" :placeholder="$t('annotations')" v-autocomplete="{ model: 'cw' }">
<textarea v-model="text" ref="text" :disabled="posting" :placeholder="placeholder" v-autocomplete="{ model: 'text' }"></textarea>
<div class="attaches" v-show="files.length != 0">
<x-draggable class="files" :list="files" :options="{ animation: 150 }">
<div class="file" v-for="file in files" :key="file.id">

View File

@@ -100,7 +100,15 @@ export default Vue.extend({
input: true
}).then(({ canceled, result: query }) => {
if (canceled) return;
this.$router.push(`/search?q=${encodeURIComponent(query)}`);
const q = query.trim();
if (q.startsWith('@')) {
this.$router.push(`/${q}`);
} else if (q.startsWith('#')) {
this.$router.push(`/tags/${encodeURIComponent(q.substr(1))}`);
} else {
this.$router.push(`/search?q=${encodeURIComponent(q)}`);
}
});
},

View File

@@ -3,9 +3,11 @@
<span slot="header"><span style="margin-right:4px;"><fa icon="star"/></span>{{ $t('title') }}</span>
<main>
<template v-for="favorite in favorites">
<mk-note-detail class="post" :note="favorite.note" :key="favorite.note.id"/>
</template>
<sequential-entrance animation="entranceFromTop" delay="25">
<template v-for="favorite in favorites">
<mk-note-detail class="post" :note="favorite.note" :key="favorite.note.id"/>
</template>
</sequential-entrance>
<ui-button v-if="existMore" @click="more">{{ $t('@.load-more') }}</ui-button>
</main>
</mk-ui>
@@ -79,13 +81,13 @@ main
margin 0 auto
padding 8px
> .post
> * > .post
margin-bottom 8px
@media (min-width 500px)
padding 16px
> .post
> * > .post
margin-bottom 16px
@media (min-width 600px)

View File

@@ -33,7 +33,7 @@
<section>
<ui-switch v-model="games_reversi_showBoardLabels">{{ $t('@.show-reversi-board-labels') }}</ui-switch>
<ui-switch v-model="games_reversi_useContrastStones">{{ $t('@.use-contrast-reversi-stones') }}</ui-switch>
<ui-switch v-model="games_reversi_useWhiteBlackStones">{{ $t('@.use-white-black-reversi-stones') }}</ui-switch>
</section>
<section>
@@ -287,9 +287,9 @@ export default Vue.extend({
set(value) { this.$store.dispatch('settings/set', { key: 'games.reversi.showBoardLabels', value }); }
},
games_reversi_useContrastStones: {
get() { return this.$store.state.settings.games.reversi.useContrastStones; },
set(value) { this.$store.dispatch('settings/set', { key: 'games.reversi.useContrastStones', value }); }
games_reversi_useWhiteBlackStones: {
get() { return this.$store.state.settings.games.reversi.useWhiteBlackStones; },
set(value) { this.$store.dispatch('settings/set', { key: 'games.reversi.useWhiteBlackStones', value }); }
},
disableAnimatedMfm: {

View File

@@ -5,7 +5,7 @@
// Detect an old browser
if (!('fetch' in window)) {
alert(
'お使いのブラウザ(またはOS)が古いためMisskeyを動作させることができません。' +
'お使いのブラウザ(またはOS)のバージョンが旧式のためMisskeyを動作させることができません。' +
'バージョンを最新のものに更新するか、別のブラウザをお試しください。' +
'\n\n' +
'Your browser (or your OS) seems outdated. ' +

View File

@@ -40,8 +40,7 @@ const defaultSettings = {
games: {
reversi: {
showBoardLabels: false,
useWhileBlackStones: false,
useContrastStones: false
useWhiteBlackStones: false,
}
}
};

View File

@@ -1,5 +1,3 @@
{
"copyright": "Copyright (c) 2014-2018 syuilo",
"themeColor": "#fb4e4e",
"themeColorForeground": "#fff"
"copyright": "Copyright (c) 2014-2018 syuilo"
}

View File

@@ -124,7 +124,7 @@ type: `switch`
スイッチを表示します。何かの機能をオン/オフさせたい場合に有用です。
##### プロパティ
`desc` ... スイッチの詳細な説明
`label` ... スイッチに表記するテキスト
#### ラジオボタン
type: `radio`

View File

@@ -103,8 +103,18 @@ export default (tokens: Node[], mentionedRemoteUsers: INote['mentionedRemoteUser
mention(token) {
const a = doc.createElement('a');
const { username, host, acct } = token.props;
const remoteUserInfo = mentionedRemoteUsers.find(remoteUser => remoteUser.username === username && remoteUser.host === host);
a.href = remoteUserInfo ? remoteUserInfo.uri : `${config.url}/${acct}`;
switch (host) {
case 'github.com':
a.href = `https://github.com/${username}`;
break;
case 'twitter.com':
a.href = `https://twitter.com/${username}`;
break;
default:
const remoteUserInfo = mentionedRemoteUsers.find(remoteUser => remoteUser.username === username && remoteUser.host === host);
a.href = remoteUserInfo ? remoteUserInfo.uri : `${config.url}/${acct}`;
break;
}
a.textContent = acct;
return a;
},

View File

@@ -1,6 +1,7 @@
import * as mongo from 'mongodb';
const deepcopy = require('deepcopy');
import { pack as packFolder } from './drive-folder';
import { pack as packUser } from './user';
import monkDb, { nativeDbConn } from '../db/mongodb';
import isObjectId from '../misc/is-objectid';
import getDriveFileUrl, { getOriginalUrl } from '../misc/get-drive-file-url';
@@ -131,6 +132,7 @@ export const packMany = (
options?: {
detail?: boolean
self?: boolean,
withUser?: boolean,
}
) => {
return Promise.all(files.map(f => pack(f, options)));
@@ -144,6 +146,7 @@ export const pack = (
options?: {
detail?: boolean,
self?: boolean,
withUser?: boolean,
}
) => new Promise<any>(async (resolve, reject) => {
const opts = Object.assign({
@@ -208,6 +211,11 @@ export const pack = (
*/
}
if (opts.withUser) {
// Populate user
_target.user = await packUser(_file.metadata.userId);
}
delete _target.withoutChunks;
delete _target.storage;
delete _target.storageProps;

View File

@@ -43,7 +43,7 @@ export default async (user: ILocalUser) => {
attachment.push({
type: 'PropertyValue',
name: 'Discord',
value: `<a href="https://discordapp.com/users/${user.discord.id}" rel="me nofollow noopener" target="_blank"><span>@${user.discord.username}#${user.discord.discriminator}</span></a>`
value: `<a href="https://discordapp.com/users/${user.discord.id}" rel="me nofollow noopener" target="_blank"><span>${user.discord.username}#${user.discord.discriminator}</span></a>`
});
}

View File

@@ -1,4 +1,4 @@
import * as mongo from 'mongodb';
import { ObjectID } from 'mongodb';
import * as Router from 'koa-router';
const json = require('koa-json-body');
const httpSignature = require('http-signature');
@@ -64,8 +64,13 @@ router.post('/users/:user/inbox', json(), inbox);
router.get('/notes/:note', async (ctx, next) => {
if (!isActivityPubReq(ctx)) return await next();
if (!ObjectID.isValid(ctx.params.note)) {
ctx.status = 404;
return;
}
const note = await Note.findOne({
_id: new mongo.ObjectID(ctx.params.note),
_id: new ObjectID(ctx.params.note),
visibility: { $in: ['public', 'home'] },
localOnly: { $ne: true }
});
@@ -82,8 +87,13 @@ router.get('/notes/:note', async (ctx, next) => {
// note activity
router.get('/notes/:note/activity', async ctx => {
if (!ObjectID.isValid(ctx.params.note)) {
ctx.status = 404;
return;
}
const note = await Note.findOne({
_id: new mongo.ObjectID(ctx.params.note),
_id: new ObjectID(ctx.params.note),
visibility: { $in: ['public', 'home'] },
localOnly: { $ne: true }
});
@@ -112,7 +122,12 @@ router.get('/users/:user/collections/featured', Featured);
// publickey
router.get('/users/:user/publickey', async ctx => {
const userId = new mongo.ObjectID(ctx.params.user);
if (!ObjectID.isValid(ctx.params.user)) {
ctx.status = 404;
return;
}
const userId = new ObjectID(ctx.params.user);
const user = await User.findOne({
_id: userId,
@@ -146,7 +161,12 @@ async function userInfo(ctx: Router.IRouterContext, user: IUser) {
}
router.get('/users/:user', async ctx => {
const userId = new mongo.ObjectID(ctx.params.user);
if (!ObjectID.isValid(ctx.params.user)) {
ctx.status = 404;
return;
}
const userId = new ObjectID(ctx.params.user);
const user = await User.findOne({
_id: userId,

View File

@@ -1,4 +1,4 @@
import * as mongo from 'mongodb';
import { ObjectID } from 'mongodb';
import * as Router from 'koa-router';
import config from '../../config';
import User from '../../models/user';
@@ -9,7 +9,12 @@ import Note from '../../models/note';
import renderNote from '../../remote/activitypub/renderer/note';
export default async (ctx: Router.IRouterContext) => {
const userId = new mongo.ObjectID(ctx.params.user);
if (!ObjectID.isValid(ctx.params.user)) {
ctx.status = 404;
return;
}
const userId = new ObjectID(ctx.params.user);
// Verify user
const user = await User.findOne({
@@ -24,7 +29,7 @@ export default async (ctx: Router.IRouterContext) => {
const pinnedNoteIds = user.pinnedNoteIds || [];
const pinnedNotes = await Promise.all(pinnedNoteIds.map(id => Note.findOne({ _id: id })));
const pinnedNotes = await Promise.all(pinnedNoteIds.filter(ObjectID.isValid).map(id => Note.findOne({ _id: id })));
const renderedNotes = await Promise.all(pinnedNotes.map(note => renderNote(note)));

View File

@@ -1,4 +1,4 @@
import * as mongo from 'mongodb';
import { ObjectID } from 'mongodb';
import * as Router from 'koa-router';
import config from '../../config';
import $ from 'cafy'; import ID, { transform } from '../../misc/cafy-id';
@@ -11,7 +11,12 @@ import renderFollowUser from '../../remote/activitypub/renderer/follow-user';
import { setResponseType } from '../activitypub';
export default async (ctx: Router.IRouterContext) => {
const userId = new mongo.ObjectID(ctx.params.user);
if (!ObjectID.isValid(ctx.params.user)) {
ctx.status = 404;
return;
}
const userId = new ObjectID(ctx.params.user);
// Get 'cursor' parameter
const [cursor = null, cursorErr] = $.type(ID).optional.get(ctx.request.query.cursor);

View File

@@ -1,7 +1,8 @@
import * as mongo from 'mongodb';
import { ObjectID } from 'mongodb';
import * as Router from 'koa-router';
import config from '../../config';
import $ from 'cafy'; import ID, { transform } from '../../misc/cafy-id';
import $ from 'cafy';
import ID, { transform } from '../../misc/cafy-id';
import User from '../../models/user';
import Following from '../../models/following';
import pack from '../../remote/activitypub/renderer';
@@ -11,7 +12,12 @@ import renderFollowUser from '../../remote/activitypub/renderer/follow-user';
import { setResponseType } from '../activitypub';
export default async (ctx: Router.IRouterContext) => {
const userId = new mongo.ObjectID(ctx.params.user);
if (!ObjectID.isValid(ctx.params.user)) {
ctx.status = 404;
return;
}
const userId = new ObjectID(ctx.params.user);
// Get 'cursor' parameter
const [cursor = null, cursorErr] = $.type(ID).optional.get(ctx.request.query.cursor);

View File

@@ -1,7 +1,8 @@
import * as mongo from 'mongodb';
import { ObjectID } from 'mongodb';
import * as Router from 'koa-router';
import config from '../../config';
import $ from 'cafy'; import ID, { transform } from '../../misc/cafy-id';
import $ from 'cafy';
import ID, { transform } from '../../misc/cafy-id';
import User from '../../models/user';
import pack from '../../remote/activitypub/renderer';
import renderOrderedCollection from '../../remote/activitypub/renderer/ordered-collection';
@@ -15,7 +16,12 @@ import renderAnnounce from '../../remote/activitypub/renderer/announce';
import { countIf } from '../../prelude/array';
export default async (ctx: Router.IRouterContext) => {
const userId = new mongo.ObjectID(ctx.params.user);
if (!ObjectID.isValid(ctx.params.user)) {
ctx.status = 404;
return;
}
const userId = new ObjectID(ctx.params.user);
// Get 'sinceId' parameter
const [sinceId, sinceIdErr] = $.type(ID).optional.get(ctx.request.query.since_id);

View File

@@ -0,0 +1,81 @@
import $ from 'cafy';
import File, { packMany } from '../../../../../models/drive-file';
import define from '../../../define';
export const meta = {
requireCredential: false,
requireModerator: true,
params: {
limit: {
validator: $.num.optional.range(1, 100),
default: 10
},
offset: {
validator: $.num.optional.min(0),
default: 0
},
sort: {
validator: $.str.optional.or([
'+createdAt',
'-createdAt',
'+size',
'-size',
]),
},
origin: {
validator: $.str.optional.or([
'combined',
'local',
'remote',
]),
default: 'local'
}
}
};
export default define(meta, (ps, me) => new Promise(async (res, rej) => {
let _sort;
if (ps.sort) {
if (ps.sort == '+createdAt') {
_sort = {
uploadDate: -1
};
} else if (ps.sort == '-createdAt') {
_sort = {
uploadDate: 1
};
} else if (ps.sort == '+size') {
_sort = {
length: -1
};
} else if (ps.sort == '+size') {
_sort = {
length: -1
};
}
} else {
_sort = {
_id: -1
};
}
const q = {
'metadata.deletedAt': { $exists: false },
} as any;
if (ps.origin == 'local') q['metadata._user.host'] = null;
if (ps.origin == 'remote') q['metadata._user.host'] = { $ne: null };
const files = await File
.find(q, {
limit: ps.limit,
sort: _sort,
skip: ps.offset
});
res(await packMany(files, { detail: true, withUser: true }));
}));

View File

@@ -32,14 +32,17 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
// Fetch file
const file = await DriveFile
.findOne({
_id: ps.fileId,
'metadata.userId': user._id
_id: ps.fileId
});
if (file === null) {
return rej('file-not-found');
}
if (!user.isAdmin && !user.isModerator && !file.metadata.userId.equals(user._id)) {
return rej('access denied');
}
// Delete
await del(file);

View File

@@ -3,6 +3,7 @@ import Note from '../../../../models/note';
import deleteNote from '../../../../services/note/delete';
import User from '../../../../models/user';
import define from '../../define';
const ms = require('ms');
export const meta = {
stability: 'stable',
@@ -16,6 +17,12 @@ export const meta = {
kind: 'note-write',
limit: {
duration: ms('1hour'),
max: 300,
minInterval: ms('1sec')
},
params: {
noteId: {
validator: $.type(ID),

View File

@@ -15,7 +15,7 @@ import parseAcct from '../../misc/acct/parse';
import config from '../../config';
import Note, { pack as packNote } from '../../models/note';
import getNoteSummary from '../../misc/get-note-summary';
const consts = require('../../const.json');
import fetchMeta from '../../misc/fetch-meta';
const client = `${__dirname}/../../client/`;
@@ -26,8 +26,7 @@ const app = new Koa();
app.use(views(__dirname + '/views', {
extension: 'pug',
options: {
config,
themeColor: consts.themeColor
config
}
}));
@@ -120,10 +119,11 @@ router.get('/notes/:note', async ctx => {
// Render base html for all requests
router.get('*', async ctx => {
await send(ctx, `app/base.html`, {
root: client,
maxage: ms('5m')
const meta = await fetchMeta();
await ctx.render('base', {
img: meta.bannerUrl
});
ctx.set('Cache-Control', 'public, max-age=86400');
});
// Register router

View File

@@ -9,7 +9,6 @@ html
head
meta(charset='utf-8')
meta(name='application-name' content='Misskey')
meta(name='theme-color' content=themeColor)
meta(name='referrer' content='origin')
meta(property='og:site_name' content='Misskey')
link(rel='manifest' href='/manifest.json')
@@ -23,16 +22,16 @@ html
block meta
block og
meta(property='og:image' content=img)
style
include ./../../../built/client/assets/init.css
include ./../../../../built/client/assets/init.css
script
include ./../../../built/client/assets/boot.js
include ./../../../../built/client/assets/boot.js
script
include ./../../../built/client/assets/safe.js
//- FontAwesome style
style #{facss}
include ./../../../../built/client/assets/safe.js
body
noscript: p
@@ -41,5 +40,5 @@ html
| Please turn on your JavaScript
div#ini.
<svg viewBox="0 0 50 50">
<path fill=#{themeColor} d="M25.251,6.461c-10.318,0-18.683,8.365-18.683,18.683h4.068c0-8.071,6.543-14.615,14.615-14.615V6.461z" />
<path fill=#fb4e4e d="M25.251,6.461c-10.318,0-18.683,8.365-18.683,18.683h4.068c0-8.071,6.543-14.615,14.615-14.615V6.461z" />
</svg>

View File

@@ -1,4 +1,4 @@
extends ../../../../src/client/app/base
extends ./base
block vars
- const user = note.user;
@@ -11,14 +11,19 @@ block title
block desc
meta(name='description' content= summary)
block meta
meta(name='twitter:card' content='summary')
block og
meta(property='og:type' content='article')
meta(property='og:title' content= title)
meta(property='og:description' content= summary)
meta(property='og:url' content= url)
meta(property='og:image' content= user.avatarUrl)
block meta
meta(name='twitter:card' content='summary')
if user.twitter
meta(name='twitter:creator' content=`@${user.twitter.screenName}`)
if note.prev
link(rel='prev' href=`${config.url}/notes/${note.prev}`)
if note.next

View File

@@ -1,4 +1,4 @@
extends ../../../../src/client/app/base
extends ./base
block vars
- const title = user.name ? `${user.name} (@${user.username})` : `@${user.username}`;
@@ -11,14 +11,19 @@ block title
block desc
meta(name='description' content= user.description)
block meta
meta(name='twitter:card' content='summary')
block og
meta(property='og:type' content='blog')
meta(property='og:title' content= title)
meta(property='og:description' content= user.description)
meta(property='og:url' content= url)
meta(property='og:image' content= img)
block meta
meta(name='twitter:card' content='summary')
if user.twitter
meta(name='twitter:creator' content=`@${user.twitter.screenName}`)
if !user.host
link(rel='alternate' href=`${config.url}/users/${user._id}` type='application/activity+json')
if user.uri

View File

@@ -114,7 +114,6 @@ module.exports = {
clear: false
}),
new webpack.DefinePlugin({
_THEME_COLOR_: JSON.stringify(constants.themeColor),
_COPYRIGHT_: JSON.stringify(constants.copyright),
_VERSION_: JSON.stringify(meta.version),
_CLIENT_VERSION_: JSON.stringify(version),