Compare commits
	
		
			188 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 359da9a5a1 | ||
|   | 2a235151ed | ||
|   | 9e318d5ebc | ||
|   | 6819eb3b4d | ||
|   | 4c6fb60dd2 | ||
|   | bffb9a5c45 | ||
|   | dca4053a67 | ||
|   | fd07f00d14 | ||
|   | bbeb6d534e | ||
|   | 63b8af4531 | ||
|   | e89e76076a | ||
|   | 18b4f74cdb | ||
|   | e53dde385c | ||
|   | 6a7a4c20e6 | ||
|   | 6434dac04d | ||
|   | 5deb1bf40e | ||
| ![greenkeeper[bot]](/assets/img/avatar_default.png)  | 9cd334576c | ||
|   | ae36bf301a | ||
|   | 6a5a9de795 | ||
|   | f0abc46429 | ||
|   | 9fd4f5ee0a | ||
|   | 5e202c3def | ||
|   | 48223c1c76 | ||
|   | dddf7834cc | ||
|   | 66ef30b2cc | ||
|   | f802fe57b9 | ||
|   | ead884ce89 | ||
| ![greenkeeper[bot]](/assets/img/avatar_default.png)  | 6a87e9f690 | ||
| ![greenkeeper[bot]](/assets/img/avatar_default.png)  | 5b943722fb | ||
|   | 4d92b14308 | ||
|   | 167c96d14e | ||
|   | 8a42373753 | ||
|   | c1751a9b84 | ||
|   | 4e11da98d9 | ||
|   | 1b7d98c17e | ||
|   | 3038434712 | ||
|   | 117ab633a1 | ||
|   | e50fa4762d | ||
|   | aed1e839ba | ||
|   | 00f2974a2a | ||
| ![greenkeeper[bot]](/assets/img/avatar_default.png)  | 073c96af47 | ||
|   | 71da498364 | ||
|   | 8e9c11f160 | ||
| ![greenkeeper[bot]](/assets/img/avatar_default.png)  | 98f6b23249 | ||
|   | 89288d8e0d | ||
|   | 724121eeaa | ||
|   | edee95a5ca | ||
|   | 0c2361bf72 | ||
|   | 92f8dc48e3 | ||
|   | 06a0fff4b0 | ||
|   | d55e4621ac | ||
|   | bc6bda3714 | ||
|   | d3aafd3f13 | ||
|   | 1a508de1c4 | ||
|   | 768cc0aff5 | ||
|   | 67f4c1f429 | ||
|   | 2d4ceec0a5 | ||
|   | 3e2a0cd89a | ||
|   | d1f4f2f663 | ||
|   | 6e3bf26cad | ||
|   | 672377f116 | ||
|   | 80ee5afba7 | ||
|   | f55fcd3305 | ||
|   | 64fc14ade5 | ||
|   | 807f245657 | ||
| ![greenkeeper[bot]](/assets/img/avatar_default.png)  | 62f966dc27 | ||
|   | 09f97bf7a7 | ||
|   | 69460e494c | ||
| ![greenkeeper[bot]](/assets/img/avatar_default.png)  | 9bef723346 | ||
| ![greenkeeper[bot]](/assets/img/avatar_default.png)  | b99eabb2cf | ||
|   | 17be3f3d0f | ||
|   | 05fe2cb173 | ||
|   | 428be14c27 | ||
|   | a04fa8441e | ||
|   | 7bcfa84e1a | ||
|   | 1cc5986df3 | ||
|   | 7aa5d03875 | ||
|   | a59fbfac19 | ||
|   | 677f9ee8f6 | ||
|   | f4a16be2b4 | ||
|   | 46b967ee4a | ||
|   | 78568accd1 | ||
|   | e9f20a0fad | ||
|   | bbd9894e6b | ||
|   | f92745e381 | ||
|   | 2762b78bcc | ||
|   | 2d4ed2c8c2 | ||
|   | 2de8e8c358 | ||
|   | eb7b638db3 | ||
|   | 321e851b26 | ||
| ![greenkeeper[bot]](/assets/img/avatar_default.png)  | f8340be3bf | ||
|   | 02341ceb6e | ||
|   | 3dcdd7a5d7 | ||
|   | 85188b5de2 | ||
|   | b721d049c6 | ||
|   | e518fff944 | ||
|   | 048128c7e1 | ||
|   | d3717449c2 | ||
|   | 04de6218d3 | ||
|   | 0082473d78 | ||
|   | 77baca8e6e | ||
|   | 6a7169630c | ||
|   | 6b2089e043 | ||
|   | 14ad3af30d | ||
|   | e7e6d833b7 | ||
|   | d1a9561135 | ||
| ![greenkeeper[bot]](/assets/img/avatar_default.png)  | c7bda6f908 | ||
|   | ef43721e32 | ||
| ![greenkeeper[bot]](/assets/img/avatar_default.png)  | ba6cd874aa | ||
|   | f283d2423f | ||
|   | c07f668f14 | ||
|   | 596524a63c | ||
|   | 975e4dd285 | ||
|   | 09b05c8552 | ||
|   | 530ee6f80e | ||
|   | 6ad31dca76 | ||
|   | d423f8ae57 | ||
|   | 8e5ce7f8e3 | ||
|   | 33dfc21e4b | ||
|   | 3266f3948a | ||
|   | 7259887124 | ||
|   | 800de03187 | ||
|   | 78ba305e5c | ||
|   | bfed1475bb | ||
|   | 3281d263c4 | ||
|   | a9a1798e3a | ||
| ![greenkeeper[bot]](/assets/img/avatar_default.png)  | 6806eafaed | ||
|   | 3e20ea5b2e | ||
|   | 3f30a69b8b | ||
|   | 2d2e16d9f6 | ||
|   | 3d754ea7eb | ||
|   | f755f24560 | ||
|   | 491bc75095 | ||
|   | f5dd83a44a | ||
|   | 8e06d93c31 | ||
|   | 1a42200137 | ||
|   | bbf33d2475 | ||
|   | 93203ebfd1 | ||
|   | 67053eeaa0 | ||
|   | 43baf4ad6a | ||
|   | 5b2a36e47b | ||
|   | 2a0862a24e | ||
|   | ce31027b2e | ||
|   | 3f66c77821 | ||
|   | bc713656ec | ||
|   | 46d89faebc | ||
|   | c17f99b7a5 | ||
|   | 7cd76d60c2 | ||
|   | 05fb8d35af | ||
|   | eaa827e2d9 | ||
|   | f365ea4585 | ||
|   | 5d2e43ffb9 | ||
|   | e9a97ed99a | ||
|   | fe98102600 | ||
|   | aae8845664 | ||
|   | 81a4388ecc | ||
|   | be3ab026fd | ||
|   | f92f9d8cb0 | ||
| ![greenkeeper[bot]](/assets/img/avatar_default.png)  | c624da70ef | ||
|   | 675668c395 | ||
| ![greenkeeper[bot]](/assets/img/avatar_default.png)  | bc9c7efe85 | ||
|   | 52da66d550 | ||
|   | 251c3c3fe4 | ||
|   | 3b6d242ef6 | ||
|   | 4f62043b0c | ||
|   | b1ae304c51 | ||
|   | 425bc032d0 | ||
|   | 0156b75bde | ||
|   | 8bc8fc58de | ||
|   | 9bf847b1fb | ||
|   | 0b078d203b | ||
|   | df59018b47 | ||
|   | b2681dcb5d | ||
|   | 46fa471636 | ||
|   | 5f2c441996 | ||
|   | a79cc42b26 | ||
|   | bd97e315ff | ||
|   | 51083419f5 | ||
|   | b23bfd4d86 | ||
|   | 7de3e847bd | ||
|   | 0d1a541dba | ||
|   | 2717109fe2 | ||
|   | 60ca0626ce | ||
|   | 15dae0ae65 | ||
|   | 1c680118a0 | ||
|   | ad5efbba59 | ||
|   | 6dc7baa5e9 | ||
|   | c2b886e750 | 
| @@ -57,6 +57,7 @@ Misskey is using Crowdin for l10n. | |||||||
| <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/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/13099460/43cecdbaa63a40d79bf50a96b9910b9d/1?token-time=2145916800&token-hash=d6P5MWHHsCMxUuBAEPAoVc5wLUR19mIhqAq7Ma9h9rI%3D" alt="ne_moni"></td> | <td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/13099460/43cecdbaa63a40d79bf50a96b9910b9d/1?token-time=2145916800&token-hash=d6P5MWHHsCMxUuBAEPAoVc5wLUR19mIhqAq7Ma9h9rI%3D" alt="ne_moni"></td> | ||||||
| <td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/12913507/f7181eacafe8469a93033d85f5969c29/1?token-time=2145916800&token-hash=f03BFb4S2FUx9YEt87TnEmifb4h33OywGBW2akQVtQY%3D" alt="Melilot"></td> | <td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/12913507/f7181eacafe8469a93033d85f5969c29/1?token-time=2145916800&token-hash=f03BFb4S2FUx9YEt87TnEmifb4h33OywGBW2akQVtQY%3D" alt="Melilot"></td> | ||||||
|  | <td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/12999811/5f349fafcce44dd1824a8b1ebbec4564/1?token-time=2145916800&token-hash=DVrSdOqQq2dufgNgWZ3XMnEtl_ZAktr8Lhf2tbHKtoA%3D" alt="Axella"></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/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/12021162/963128bb8d14476dbd8407943db8f31a/1?token-time=2145916800&token-hash=GgJ_NmUB6_nnRNLVGUWjV-WX91On7BOu59LKncYV9fE%3D" alt="gutfuckllc"></td> | ||||||
| <td><img src="https://c8.patreon.com/2/100/12718187" alt="Peter G."></td> | <td><img src="https://c8.patreon.com/2/100/12718187" alt="Peter G."></td> | ||||||
| @@ -66,6 +67,7 @@ Misskey is using Crowdin for l10n. | |||||||
| <td><a href="https://www.patreon.com/user?u=12731202">negao</a></td> | <td><a href="https://www.patreon.com/user?u=12731202">negao</a></td> | ||||||
| <td><a href="https://www.patreon.com/user?u=13099460">ne_moni</a></td> | <td><a href="https://www.patreon.com/user?u=13099460">ne_moni</a></td> | ||||||
| <td><a href="https://www.patreon.com/user?u=12913507">Melilot</a></td> | <td><a href="https://www.patreon.com/user?u=12913507">Melilot</a></td> | ||||||
|  | <td><a href="https://www.patreon.com/AxellaMC">Axella</a></td> | ||||||
| <td><a href="https://www.patreon.com/user?u=3384329">べすれい</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/gutfuckllc">gutfuckllc</a></td> | ||||||
| <td><a href="https://www.patreon.com/user?u=12718187">Peter G.</a></td> | <td><a href="https://www.patreon.com/user?u=12718187">Peter G.</a></td> | ||||||
| @@ -89,7 +91,7 @@ Misskey is using Crowdin for l10n. | |||||||
| <td><a href="https://www.patreon.com/fujishan">fujishan</a></td> | <td><a href="https://www.patreon.com/fujishan">fujishan</a></td> | ||||||
| </tr></table> | </tr></table> | ||||||
|  |  | ||||||
| **Last updated:** Wed, 22 Aug 2018 05:25:06 UTC | **Last updated:** Sun, 26 Aug 2018 08:55:06 UTC | ||||||
| <!-- PATREON_END --> | <!-- PATREON_END --> | ||||||
|  |  | ||||||
| :four_leaf_clover: Copyright | :four_leaf_clover: Copyright | ||||||
|   | |||||||
| @@ -1,40 +0,0 @@ | |||||||
| const { default: User, deleteUser } = require('../built/models/user'); |  | ||||||
| const { default: zip } = require('@prezzemolo/zip') |  | ||||||
|  |  | ||||||
| const migrate = async (user) => { |  | ||||||
| 	try { |  | ||||||
| 		await deleteUser(user._id); |  | ||||||
| 		return true; |  | ||||||
| 	} catch (e) { |  | ||||||
| 		return false; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| async function main() { |  | ||||||
| 	const count = await User.count({ |  | ||||||
| 		uri: /#/ |  | ||||||
| 	}); |  | ||||||
|  |  | ||||||
| 	const dop = 1 |  | ||||||
| 	const idop = ((count - (count % dop)) / dop) + 1 |  | ||||||
|  |  | ||||||
| 	return zip( |  | ||||||
| 		1, |  | ||||||
| 		async (time) => { |  | ||||||
| 			console.log(`${time} / ${idop}`) |  | ||||||
| 			const doc = await User.find({ |  | ||||||
| 				uri: /#/ |  | ||||||
| 			}, { |  | ||||||
| 				limit: dop, skip: time * dop |  | ||||||
| 			}) |  | ||||||
| 			return Promise.all(doc.map(migrate)) |  | ||||||
| 		}, |  | ||||||
| 		idop |  | ||||||
| 	).then(a => { |  | ||||||
| 		const rv = [] |  | ||||||
| 		a.forEach(e => rv.push(...e)) |  | ||||||
| 		return rv |  | ||||||
| 	}) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| main().then(console.dir).catch(console.error) |  | ||||||
| @@ -411,6 +411,7 @@ desktop: | |||||||
|   uploading-avatar: "新しいアバターをアップロードしています" |   uploading-avatar: "新しいアバターをアップロードしています" | ||||||
|   avatar-updated: "アバターを更新しました" |   avatar-updated: "アバターを更新しました" | ||||||
|   choose-avatar: "アバターにする画像を選択" |   choose-avatar: "アバターにする画像を選択" | ||||||
|  |   invalid-filetype: "この形式のファイルはサポートされていません" | ||||||
| desktop/views/components/activity.chart.vue: | desktop/views/components/activity.chart.vue: | ||||||
|   total: "Black ... Total" |   total: "Black ... Total" | ||||||
|   notes: "Blue ... Notes" |   notes: "Blue ... Notes" | ||||||
| @@ -649,6 +650,7 @@ desktop/views/components/settings.vue: | |||||||
|   gradient-window-header: "ウィンドウのタイトルバーにグラデーションを使用" |   gradient-window-header: "ウィンドウのタイトルバーにグラデーションを使用" | ||||||
|   post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" |   post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" | ||||||
|   suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する" |   suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する" | ||||||
|  |   show-clock-on-header: "右上に時計を表示する" | ||||||
|   show-reply-target: "リプライ先を表示する" |   show-reply-target: "リプライ先を表示する" | ||||||
|   show-my-renotes: "自分の行ったRenoteをタイムラインに表示する" |   show-my-renotes: "自分の行ったRenoteをタイムラインに表示する" | ||||||
|   show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する" |   show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する" | ||||||
| @@ -819,8 +821,8 @@ desktop/views/pages/admin/admin.dashboard.vue: | |||||||
|   dashboard: "ダッシュボード" |   dashboard: "ダッシュボード" | ||||||
|   all-users: "全てのユーザー" |   all-users: "全てのユーザー" | ||||||
|   original-users: "このインスタンスのユーザー" |   original-users: "このインスタンスのユーザー" | ||||||
|   all-notes: "全てのノート" |   all-notes: "全ての投稿" | ||||||
|   original-notes: "このインスタンスのノート" |   original-notes: "このインスタンスの投稿" | ||||||
|   invite: "招待" |   invite: "招待" | ||||||
| desktop/views/pages/admin/admin.suspend-user.vue: | desktop/views/pages/admin/admin.suspend-user.vue: | ||||||
|   suspend-user: "ユーザーの凍結" |   suspend-user: "ユーザーの凍結" | ||||||
| @@ -846,6 +848,11 @@ desktop/views/pages/deck/deck.note.vue: | |||||||
|   reposted-by: "{}がRenote" |   reposted-by: "{}がRenote" | ||||||
|   private: "この投稿は非公開です" |   private: "この投稿は非公開です" | ||||||
|   deleted: "この投稿は削除されました" |   deleted: "この投稿は削除されました" | ||||||
|  | desktop/views/pages/stats/stats.vue: | ||||||
|  |   all-users: "全てのユーザー" | ||||||
|  |   original-users: "このインスタンスのユーザー" | ||||||
|  |   all-notes: "全ての投稿" | ||||||
|  |   original-notes: "このインスタンスの投稿" | ||||||
| desktop/views/pages/welcome.vue: | desktop/views/pages/welcome.vue: | ||||||
|   about: "詳しく..." |   about: "詳しく..." | ||||||
|   gotit: "わかった" |   gotit: "わかった" | ||||||
| @@ -1170,6 +1177,8 @@ mobile/views/pages/settings.vue: | |||||||
|   update-available-desc: "ページを再度読み込みすると更新が適用されます。" |   update-available-desc: "ページを再度読み込みすると更新が適用されます。" | ||||||
|   settings: "設定" |   settings: "設定" | ||||||
|   signout: "サインアウト" |   signout: "サインアウト" | ||||||
|  |   sound: "サウンド" | ||||||
|  |   enableSounds: "サウンドを有効にする" | ||||||
| mobile/views/pages/user.vue: | mobile/views/pages/user.vue: | ||||||
|   follows-you: "フォローされています" |   follows-you: "フォローされています" | ||||||
|   following: "フォロー" |   following: "フォロー" | ||||||
|   | |||||||
| @@ -411,6 +411,7 @@ desktop: | |||||||
|   uploading-avatar: "新しいアバターをアップロードしています" |   uploading-avatar: "新しいアバターをアップロードしています" | ||||||
|   avatar-updated: "アバターを更新しました" |   avatar-updated: "アバターを更新しました" | ||||||
|   choose-avatar: "アバターにする画像を選択" |   choose-avatar: "アバターにする画像を選択" | ||||||
|  |   invalid-filetype: "この形式のファイルはサポートされていません" | ||||||
| desktop/views/components/activity.chart.vue: | desktop/views/components/activity.chart.vue: | ||||||
|   total: "Schwarz ... komplett" |   total: "Schwarz ... komplett" | ||||||
|   notes: "Blau ... Hinweise" |   notes: "Blau ... Hinweise" | ||||||
| @@ -649,6 +650,7 @@ desktop/views/components/settings.vue: | |||||||
|   gradient-window-header: "Übergang in Fensterköpfen" |   gradient-window-header: "Übergang in Fensterköpfen" | ||||||
|   post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" |   post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" | ||||||
|   suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する" |   suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する" | ||||||
|  |   show-clock-on-header: "右上に時計を表示する" | ||||||
|   show-reply-target: "Zeige Antworten" |   show-reply-target: "Zeige Antworten" | ||||||
|   show-my-renotes: "Zeige meine Reposts auf der Zeitleiste" |   show-my-renotes: "Zeige meine Reposts auf der Zeitleiste" | ||||||
|   show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する" |   show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する" | ||||||
| @@ -819,8 +821,8 @@ desktop/views/pages/admin/admin.dashboard.vue: | |||||||
|   dashboard: "ダッシュボード" |   dashboard: "ダッシュボード" | ||||||
|   all-users: "全てのユーザー" |   all-users: "全てのユーザー" | ||||||
|   original-users: "このインスタンスのユーザー" |   original-users: "このインスタンスのユーザー" | ||||||
|   all-notes: "全てのノート" |   all-notes: "全ての投稿" | ||||||
|   original-notes: "このインスタンスのノート" |   original-notes: "このインスタンスの投稿" | ||||||
|   invite: "招待" |   invite: "招待" | ||||||
| desktop/views/pages/admin/admin.suspend-user.vue: | desktop/views/pages/admin/admin.suspend-user.vue: | ||||||
|   suspend-user: "ユーザーの凍結" |   suspend-user: "ユーザーの凍結" | ||||||
| @@ -846,6 +848,11 @@ desktop/views/pages/deck/deck.note.vue: | |||||||
|   reposted-by: "{}がRenote" |   reposted-by: "{}がRenote" | ||||||
|   private: "この投稿は非公開です" |   private: "この投稿は非公開です" | ||||||
|   deleted: "この投稿は削除されました" |   deleted: "この投稿は削除されました" | ||||||
|  | desktop/views/pages/stats/stats.vue: | ||||||
|  |   all-users: "全てのユーザー" | ||||||
|  |   original-users: "このインスタンスのユーザー" | ||||||
|  |   all-notes: "全ての投稿" | ||||||
|  |   original-notes: "このインスタンスの投稿" | ||||||
| desktop/views/pages/welcome.vue: | desktop/views/pages/welcome.vue: | ||||||
|   about: "詳しく..." |   about: "詳しく..." | ||||||
|   gotit: "わかった" |   gotit: "わかった" | ||||||
| @@ -1170,6 +1177,8 @@ mobile/views/pages/settings.vue: | |||||||
|   update-available-desc: "ページを再度読み込みすると更新が適用されます。" |   update-available-desc: "ページを再度読み込みすると更新が適用されます。" | ||||||
|   settings: "設定" |   settings: "設定" | ||||||
|   signout: "サインアウト" |   signout: "サインアウト" | ||||||
|  |   sound: "サウンド" | ||||||
|  |   enableSounds: "サウンドを有効にする" | ||||||
| mobile/views/pages/user.vue: | mobile/views/pages/user.vue: | ||||||
|   follows-you: "フォローされています" |   follows-you: "フォローされています" | ||||||
|   following: "フォロー" |   following: "フォロー" | ||||||
|   | |||||||
| @@ -411,6 +411,7 @@ desktop: | |||||||
|   uploading-avatar: "Uploading a new avatar" |   uploading-avatar: "Uploading a new avatar" | ||||||
|   avatar-updated: "Successfully updated the avatar" |   avatar-updated: "Successfully updated the avatar" | ||||||
|   choose-avatar: "Select an image for the avatar" |   choose-avatar: "Select an image for the avatar" | ||||||
|  |   invalid-filetype: "This filetype is not acceptable here" | ||||||
| desktop/views/components/activity.chart.vue: | desktop/views/components/activity.chart.vue: | ||||||
|   total: "Black ... Total" |   total: "Black ... Total" | ||||||
|   notes: "Blue ... Notes" |   notes: "Blue ... Notes" | ||||||
| @@ -649,6 +650,7 @@ desktop/views/components/settings.vue: | |||||||
|   gradient-window-header: "Use gradients on window headers" |   gradient-window-header: "Use gradients on window headers" | ||||||
|   post-form-on-timeline: "Display post form at the top of the timeline" |   post-form-on-timeline: "Display post form at the top of the timeline" | ||||||
|   suggest-recent-hashtags: "Show recent popular hashtags on the post form" |   suggest-recent-hashtags: "Show recent popular hashtags on the post form" | ||||||
|  |   show-clock-on-header: "Show clock on upper-right" | ||||||
|   show-reply-target: "Display reply target" |   show-reply-target: "Display reply target" | ||||||
|   show-my-renotes: "Show my renotes in the timeline" |   show-my-renotes: "Show my renotes in the timeline" | ||||||
|   show-renoted-my-notes: "Show renoted my posts in timelines" |   show-renoted-my-notes: "Show renoted my posts in timelines" | ||||||
| @@ -819,7 +821,7 @@ desktop/views/pages/admin/admin.dashboard.vue: | |||||||
|   dashboard: "Dashboard" |   dashboard: "Dashboard" | ||||||
|   all-users: "All Users" |   all-users: "All Users" | ||||||
|   original-users: "Users on this instance" |   original-users: "Users on this instance" | ||||||
|   all-notes: "All Posts" |   all-notes: "All the posts" | ||||||
|   original-notes: "Posts on this instance" |   original-notes: "Posts on this instance" | ||||||
|   invite: "Invite" |   invite: "Invite" | ||||||
| desktop/views/pages/admin/admin.suspend-user.vue: | desktop/views/pages/admin/admin.suspend-user.vue: | ||||||
| @@ -846,6 +848,11 @@ desktop/views/pages/deck/deck.note.vue: | |||||||
|   reposted-by: "Reposted by {}" |   reposted-by: "Reposted by {}" | ||||||
|   private: "This post is private" |   private: "This post is private" | ||||||
|   deleted: "This post has been deleted" |   deleted: "This post has been deleted" | ||||||
|  | desktop/views/pages/stats/stats.vue: | ||||||
|  |   all-users: "All Users" | ||||||
|  |   original-users: "Users on this instance" | ||||||
|  |   all-notes: "All the posts" | ||||||
|  |   original-notes: "Posts on this instance" | ||||||
| desktop/views/pages/welcome.vue: | desktop/views/pages/welcome.vue: | ||||||
|   about: "More details..." |   about: "More details..." | ||||||
|   gotit: "Got it!" |   gotit: "Got it!" | ||||||
| @@ -1066,7 +1073,7 @@ mobile/views/pages/favorites.vue: | |||||||
|   title: "Favorites" |   title: "Favorites" | ||||||
| mobile/views/pages/user-lists.vue: | mobile/views/pages/user-lists.vue: | ||||||
|   title: "Lists" |   title: "Lists" | ||||||
|   enter-list-name: "Enter list name" |   enter-list-name: "Enter a name of the list to make" | ||||||
| mobile/views/pages/drive.vue: | mobile/views/pages/drive.vue: | ||||||
|   drive: "Drive" |   drive: "Drive" | ||||||
|   more: "Load more" |   more: "Load more" | ||||||
| @@ -1170,6 +1177,8 @@ mobile/views/pages/settings.vue: | |||||||
|   update-available-desc: "Updates will be applied after reloading the page" |   update-available-desc: "Updates will be applied after reloading the page" | ||||||
|   settings: "Settings" |   settings: "Settings" | ||||||
|   signout: "Sign out" |   signout: "Sign out" | ||||||
|  |   sound: "Sounds" | ||||||
|  |   enableSounds: "Enable sounds" | ||||||
| mobile/views/pages/user.vue: | mobile/views/pages/user.vue: | ||||||
|   follows-you: "Follows you" |   follows-you: "Follows you" | ||||||
|   following: "Following" |   following: "Following" | ||||||
|   | |||||||
| @@ -411,6 +411,7 @@ desktop: | |||||||
|   uploading-avatar: "Cargando un nuevo avatar" |   uploading-avatar: "Cargando un nuevo avatar" | ||||||
|   avatar-updated: "Avatar actualizado" |   avatar-updated: "Avatar actualizado" | ||||||
|   choose-avatar: "Escoge una imagen de avatar" |   choose-avatar: "Escoge una imagen de avatar" | ||||||
|  |   invalid-filetype: "この形式のファイルはサポートされていません" | ||||||
| desktop/views/components/activity.chart.vue: | desktop/views/components/activity.chart.vue: | ||||||
|   total: "Negro ... Total" |   total: "Negro ... Total" | ||||||
|   notes: "Azul ... Notas" |   notes: "Azul ... Notas" | ||||||
| @@ -649,6 +650,7 @@ desktop/views/components/settings.vue: | |||||||
|   gradient-window-header: "Usar degradados en las cabeceras de las páginas" |   gradient-window-header: "Usar degradados en las cabeceras de las páginas" | ||||||
|   post-form-on-timeline: "Mostrar el formulario de las entradas encima de la línea de tiempo" |   post-form-on-timeline: "Mostrar el formulario de las entradas encima de la línea de tiempo" | ||||||
|   suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する" |   suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する" | ||||||
|  |   show-clock-on-header: "右上に時計を表示する" | ||||||
|   show-reply-target: "リプライ先を表示する" |   show-reply-target: "リプライ先を表示する" | ||||||
|   show-my-renotes: "自分の行ったRenoteをタイムラインに表示する" |   show-my-renotes: "自分の行ったRenoteをタイムラインに表示する" | ||||||
|   show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する" |   show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する" | ||||||
| @@ -819,8 +821,8 @@ desktop/views/pages/admin/admin.dashboard.vue: | |||||||
|   dashboard: "ダッシュボード" |   dashboard: "ダッシュボード" | ||||||
|   all-users: "全てのユーザー" |   all-users: "全てのユーザー" | ||||||
|   original-users: "このインスタンスのユーザー" |   original-users: "このインスタンスのユーザー" | ||||||
|   all-notes: "全てのノート" |   all-notes: "全ての投稿" | ||||||
|   original-notes: "このインスタンスのノート" |   original-notes: "このインスタンスの投稿" | ||||||
|   invite: "招待" |   invite: "招待" | ||||||
| desktop/views/pages/admin/admin.suspend-user.vue: | desktop/views/pages/admin/admin.suspend-user.vue: | ||||||
|   suspend-user: "ユーザーの凍結" |   suspend-user: "ユーザーの凍結" | ||||||
| @@ -846,6 +848,11 @@ desktop/views/pages/deck/deck.note.vue: | |||||||
|   reposted-by: "{}がRenote" |   reposted-by: "{}がRenote" | ||||||
|   private: "この投稿は非公開です" |   private: "この投稿は非公開です" | ||||||
|   deleted: "この投稿は削除されました" |   deleted: "この投稿は削除されました" | ||||||
|  | desktop/views/pages/stats/stats.vue: | ||||||
|  |   all-users: "全てのユーザー" | ||||||
|  |   original-users: "このインスタンスのユーザー" | ||||||
|  |   all-notes: "全ての投稿" | ||||||
|  |   original-notes: "このインスタンスの投稿" | ||||||
| desktop/views/pages/welcome.vue: | desktop/views/pages/welcome.vue: | ||||||
|   about: "詳しく..." |   about: "詳しく..." | ||||||
|   gotit: "わかった" |   gotit: "わかった" | ||||||
| @@ -1170,6 +1177,8 @@ mobile/views/pages/settings.vue: | |||||||
|   update-available-desc: "ページを再度読み込みすると更新が適用されます。" |   update-available-desc: "ページを再度読み込みすると更新が適用されます。" | ||||||
|   settings: "設定" |   settings: "設定" | ||||||
|   signout: "サインアウト" |   signout: "サインアウト" | ||||||
|  |   sound: "サウンド" | ||||||
|  |   enableSounds: "サウンドを有効にする" | ||||||
| mobile/views/pages/user.vue: | mobile/views/pages/user.vue: | ||||||
|   follows-you: "フォローされています" |   follows-you: "フォローされています" | ||||||
|   following: "フォロー" |   following: "フォロー" | ||||||
|   | |||||||
| @@ -411,6 +411,7 @@ desktop: | |||||||
|   uploading-avatar: "Téléversement du nouvel avatar" |   uploading-avatar: "Téléversement du nouvel avatar" | ||||||
|   avatar-updated: "L'avatar est mis à jour" |   avatar-updated: "L'avatar est mis à jour" | ||||||
|   choose-avatar: "Choisir un avatar" |   choose-avatar: "Choisir un avatar" | ||||||
|  |   invalid-filetype: "この形式のファイルはサポートされていません" | ||||||
| desktop/views/components/activity.chart.vue: | desktop/views/components/activity.chart.vue: | ||||||
|   total: "Noirs ... Total" |   total: "Noirs ... Total" | ||||||
|   notes: "Bleu ... Notes" |   notes: "Bleu ... Notes" | ||||||
| @@ -425,12 +426,12 @@ desktop/views/components/calendar.vue: | |||||||
|   next: "Mois prochain" |   next: "Mois prochain" | ||||||
|   go: "Cliquez pour naviguer" |   go: "Cliquez pour naviguer" | ||||||
| desktop/views/components/charts.vue: | desktop/views/components/charts.vue: | ||||||
|   title: "チャート" |   title: "Graphiques" | ||||||
|   per-day: "1日ごと" |   per-day: "par jour" | ||||||
|   per-hour: "1時間ごと" |   per-hour: "par heure" | ||||||
|   notes: "投稿" |   notes: "Publications" | ||||||
|   users: "ユーザー" |   users: "Utilisateurs" | ||||||
|   drive: "ドライブ" |   drive: "Drive" | ||||||
|   charts: |   charts: | ||||||
|     notes: "投稿の増減 (統合)" |     notes: "投稿の増減 (統合)" | ||||||
|     local-notes: "投稿の増減 (ローカル)" |     local-notes: "投稿の増減 (ローカル)" | ||||||
| @@ -649,6 +650,7 @@ desktop/views/components/settings.vue: | |||||||
|   gradient-window-header: "Utiliser les dégradés sur la barre de titre de la fenêtre" |   gradient-window-header: "Utiliser les dégradés sur la barre de titre de la fenêtre" | ||||||
|   post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" |   post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" | ||||||
|   suggest-recent-hashtags: "Afficher les hashtags populaires dans le champs de saisie" |   suggest-recent-hashtags: "Afficher les hashtags populaires dans le champs de saisie" | ||||||
|  |   show-clock-on-header: "Afficher l'horloge à droite sur le coté supérieur" | ||||||
|   show-reply-target: "Afficher les réponses" |   show-reply-target: "Afficher les réponses" | ||||||
|   show-my-renotes: "Afficher mes republications dans le fil" |   show-my-renotes: "Afficher mes republications dans le fil" | ||||||
|   show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する" |   show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する" | ||||||
| @@ -817,8 +819,8 @@ desktop/views/pages/admin/admin.vue: | |||||||
|   update: "Mises à jour" |   update: "Mises à jour" | ||||||
| desktop/views/pages/admin/admin.dashboard.vue: | desktop/views/pages/admin/admin.dashboard.vue: | ||||||
|   dashboard: "Tableau de bord" |   dashboard: "Tableau de bord" | ||||||
|   all-users: "Tou·te·s les utilisateur·rice·s" |   all-users: "Toutes les utilisateurrices" | ||||||
|   original-users: "Utilisateur·rice·s sur cette instance" |   original-users: "Utilisateurrices sur cette instance" | ||||||
|   all-notes: "Toutes les publications" |   all-notes: "Toutes les publications" | ||||||
|   original-notes: "Publication sur cette instance" |   original-notes: "Publication sur cette instance" | ||||||
|   invite: "Invitation" |   invite: "Invitation" | ||||||
| @@ -837,7 +839,7 @@ desktop/views/pages/admin/admin.verify-user.vue: | |||||||
| desktop/views/pages/admin/admin.unverify-user.vue: | desktop/views/pages/admin/admin.unverify-user.vue: | ||||||
|   unverify-user: "ユーザーの公式アカウント解除" |   unverify-user: "ユーザーの公式アカウント解除" | ||||||
|   unverify: "Ôter la vérification du compte" |   unverify: "Ôter la vérification du compte" | ||||||
|   unverified: "公式アカウントを解除しました" |   unverified: "Ce compte n'est pas vérifié" | ||||||
| desktop/views/pages/deck/deck.tl-column.vue: | desktop/views/pages/deck/deck.tl-column.vue: | ||||||
|   is-media-only: "Les publications médias uniquement" |   is-media-only: "Les publications médias uniquement" | ||||||
|   is-media-view: "Vue média" |   is-media-view: "Vue média" | ||||||
| @@ -846,6 +848,11 @@ desktop/views/pages/deck/deck.note.vue: | |||||||
|   reposted-by: "Reposté par {}" |   reposted-by: "Reposté par {}" | ||||||
|   private: "cette publication est privée" |   private: "cette publication est privée" | ||||||
|   deleted: "cette publication a été supprimée" |   deleted: "cette publication a été supprimée" | ||||||
|  | desktop/views/pages/stats/stats.vue: | ||||||
|  |   all-users: "Toutes les utilisateurrices" | ||||||
|  |   original-users: "Utilisateurrices sur cette instance" | ||||||
|  |   all-notes: "Toutes les publications" | ||||||
|  |   original-notes: "Publication sur cette instance" | ||||||
| desktop/views/pages/welcome.vue: | desktop/views/pages/welcome.vue: | ||||||
|   about: "à propos" |   about: "à propos" | ||||||
|   gotit: "J'ai compris !" |   gotit: "J'ai compris !" | ||||||
| @@ -1052,7 +1059,7 @@ mobile/views/components/ui.nav.vue: | |||||||
|   game: "Jeux" |   game: "Jeux" | ||||||
|   darkmode: "Mode nuit" |   darkmode: "Mode nuit" | ||||||
|   settings: "Réglages" |   settings: "Réglages" | ||||||
|   admin: "管理" |   admin: "Admin" | ||||||
|   about: "À propose de Misskey" |   about: "À propose de Misskey" | ||||||
| mobile/views/components/user-timeline.vue: | mobile/views/components/user-timeline.vue: | ||||||
|   no-notes: "Cette utilisateur semble n'avoir rien poster pour le moment" |   no-notes: "Cette utilisateur semble n'avoir rien poster pour le moment" | ||||||
| @@ -1170,6 +1177,8 @@ mobile/views/pages/settings.vue: | |||||||
|   update-available-desc: "Les mises à jour seront appliquées une fois la page est rechargée." |   update-available-desc: "Les mises à jour seront appliquées une fois la page est rechargée." | ||||||
|   settings: "Réglages" |   settings: "Réglages" | ||||||
|   signout: "Déconnexion" |   signout: "Déconnexion" | ||||||
|  |   sound: "Sons" | ||||||
|  |   enableSounds: "Activer le son" | ||||||
| mobile/views/pages/user.vue: | mobile/views/pages/user.vue: | ||||||
|   follows-you: "vous suit" |   follows-you: "vous suit" | ||||||
|   following: "Abonnements" |   following: "Abonnements" | ||||||
|   | |||||||
| @@ -411,6 +411,7 @@ desktop: | |||||||
|   uploading-avatar: "新しいアバターをアップロードしています" |   uploading-avatar: "新しいアバターをアップロードしています" | ||||||
|   avatar-updated: "アバターを更新しました" |   avatar-updated: "アバターを更新しました" | ||||||
|   choose-avatar: "アバターにする画像を選択" |   choose-avatar: "アバターにする画像を選択" | ||||||
|  |   invalid-filetype: "この形式のファイルはサポートされていません" | ||||||
| desktop/views/components/activity.chart.vue: | desktop/views/components/activity.chart.vue: | ||||||
|   total: "Black ... Total" |   total: "Black ... Total" | ||||||
|   notes: "Blue ... Notes" |   notes: "Blue ... Notes" | ||||||
| @@ -649,6 +650,7 @@ desktop/views/components/settings.vue: | |||||||
|   gradient-window-header: "ウィンドウのタイトルバーにグラデーションを使用" |   gradient-window-header: "ウィンドウのタイトルバーにグラデーションを使用" | ||||||
|   post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" |   post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" | ||||||
|   suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する" |   suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する" | ||||||
|  |   show-clock-on-header: "右上に時計を表示する" | ||||||
|   show-reply-target: "リプライ先を表示する" |   show-reply-target: "リプライ先を表示する" | ||||||
|   show-my-renotes: "自分の行ったRenoteをタイムラインに表示する" |   show-my-renotes: "自分の行ったRenoteをタイムラインに表示する" | ||||||
|   show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する" |   show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する" | ||||||
| @@ -819,8 +821,8 @@ desktop/views/pages/admin/admin.dashboard.vue: | |||||||
|   dashboard: "ダッシュボード" |   dashboard: "ダッシュボード" | ||||||
|   all-users: "全てのユーザー" |   all-users: "全てのユーザー" | ||||||
|   original-users: "このインスタンスのユーザー" |   original-users: "このインスタンスのユーザー" | ||||||
|   all-notes: "全てのノート" |   all-notes: "全ての投稿" | ||||||
|   original-notes: "このインスタンスのノート" |   original-notes: "このインスタンスの投稿" | ||||||
|   invite: "招待" |   invite: "招待" | ||||||
| desktop/views/pages/admin/admin.suspend-user.vue: | desktop/views/pages/admin/admin.suspend-user.vue: | ||||||
|   suspend-user: "ユーザーの凍結" |   suspend-user: "ユーザーの凍結" | ||||||
| @@ -846,6 +848,11 @@ desktop/views/pages/deck/deck.note.vue: | |||||||
|   reposted-by: "{}がRenote" |   reposted-by: "{}がRenote" | ||||||
|   private: "この投稿は非公開です" |   private: "この投稿は非公開です" | ||||||
|   deleted: "この投稿は削除されました" |   deleted: "この投稿は削除されました" | ||||||
|  | desktop/views/pages/stats/stats.vue: | ||||||
|  |   all-users: "全てのユーザー" | ||||||
|  |   original-users: "このインスタンスのユーザー" | ||||||
|  |   all-notes: "全ての投稿" | ||||||
|  |   original-notes: "このインスタンスの投稿" | ||||||
| desktop/views/pages/welcome.vue: | desktop/views/pages/welcome.vue: | ||||||
|   about: "詳しく..." |   about: "詳しく..." | ||||||
|   gotit: "わかった" |   gotit: "わかった" | ||||||
| @@ -1170,6 +1177,8 @@ mobile/views/pages/settings.vue: | |||||||
|   update-available-desc: "ページを再度読み込みすると更新が適用されます。" |   update-available-desc: "ページを再度読み込みすると更新が適用されます。" | ||||||
|   settings: "設定" |   settings: "設定" | ||||||
|   signout: "サインアウト" |   signout: "サインアウト" | ||||||
|  |   sound: "サウンド" | ||||||
|  |   enableSounds: "サウンドを有効にする" | ||||||
| mobile/views/pages/user.vue: | mobile/views/pages/user.vue: | ||||||
|   follows-you: "フォローされています" |   follows-you: "フォローされています" | ||||||
|   following: "フォロー" |   following: "フォロー" | ||||||
|   | |||||||
| @@ -94,6 +94,8 @@ common: | |||||||
|   verified-user: "公式アカウント" |   verified-user: "公式アカウント" | ||||||
|   disable-animated-mfm: "投稿内の動きのあるテキストを無効にする" |   disable-animated-mfm: "投稿内の動きのあるテキストを無効にする" | ||||||
|  |  | ||||||
|  |   do-not-use-in-production: 'これは開発ビルドです。本番環境で使用しないでください。' | ||||||
|  |  | ||||||
|   reversi: |   reversi: | ||||||
|     drawn: "引き分け" |     drawn: "引き分け" | ||||||
|     my-turn: "あなたのターンです" |     my-turn: "あなたのターンです" | ||||||
| @@ -283,6 +285,8 @@ common/views/components/nav.vue: | |||||||
|   feedback: "フィードバック" |   feedback: "フィードバック" | ||||||
|  |  | ||||||
| common/views/components/note-menu.vue: | common/views/components/note-menu.vue: | ||||||
|  |   detail: "詳細" | ||||||
|  |   copy-link: "リンクをコピー" | ||||||
|   favorite: "お気に入り" |   favorite: "お気に入り" | ||||||
|   pin: "ピン留め" |   pin: "ピン留め" | ||||||
|   delete: "削除" |   delete: "削除" | ||||||
| @@ -456,6 +460,7 @@ desktop: | |||||||
|   uploading-avatar: "新しいアバターをアップロードしています" |   uploading-avatar: "新しいアバターをアップロードしています" | ||||||
|   avatar-updated: "アバターを更新しました" |   avatar-updated: "アバターを更新しました" | ||||||
|   choose-avatar: "アバターにする画像を選択" |   choose-avatar: "アバターにする画像を選択" | ||||||
|  |   invalid-filetype: "この形式のファイルはサポートされていません" | ||||||
|  |  | ||||||
| desktop/views/components/activity.chart.vue: | desktop/views/components/activity.chart.vue: | ||||||
|   total: "Black ... Total" |   total: "Black ... Total" | ||||||
| @@ -1368,6 +1373,8 @@ mobile/views/pages/settings.vue: | |||||||
|   update-available-desc: "ページを再度読み込みすると更新が適用されます。" |   update-available-desc: "ページを再度読み込みすると更新が適用されます。" | ||||||
|   settings: "設定" |   settings: "設定" | ||||||
|   signout: "サインアウト" |   signout: "サインアウト" | ||||||
|  |   sound: "サウンド" | ||||||
|  |   enableSounds: "サウンドを有効にする" | ||||||
|  |  | ||||||
| mobile/views/pages/user.vue: | mobile/views/pages/user.vue: | ||||||
|   follows-you: "フォローされています" |   follows-you: "フォローされています" | ||||||
|   | |||||||
| @@ -207,9 +207,9 @@ common/views/components/games/reversi/reversi.room.vue: | |||||||
|   ready: "準備完了" |   ready: "準備完了" | ||||||
|   cancel-ready: "準備続行" |   cancel-ready: "準備続行" | ||||||
| common/views/components/connect-failed.vue: | common/views/components/connect-failed.vue: | ||||||
|   title: "サーバーに接続できません" |   title: "サーバーに接続でけへんわ" | ||||||
|   description: "インターネット回線に問題があるか、サーバーがダウンまたはメンテナンスしている可能性があります。しばらくしてから{再度お試し}ください。" |   description: "インターネット回線に問題が起きとるか、サーバーがダウンまたはメンテナンスしとるっぽいわ。知らんけど。とりあえずあとで{再試行}してや。" | ||||||
|   thanks: "いつもMisskeyをご利用いただきありがとうございます。" |   thanks: "いつもMisskeyをつこてくれてほんまありがとな。" | ||||||
|   troubleshoot: "トラブルシュート" |   troubleshoot: "トラブルシュート" | ||||||
| common/views/components/connect-failed.troubleshooter.vue: | common/views/components/connect-failed.troubleshooter.vue: | ||||||
|   title: "トラブルシューティング" |   title: "トラブルシューティング" | ||||||
| @@ -219,99 +219,99 @@ common/views/components/connect-failed.troubleshooter.vue: | |||||||
|   checking-internet: "インターネット接続を確認中" |   checking-internet: "インターネット接続を確認中" | ||||||
|   server: "サーバー接続" |   server: "サーバー接続" | ||||||
|   checking-server: "サーバー接続を確認中" |   checking-server: "サーバー接続を確認中" | ||||||
|   finding: "問題を調べています" |   finding: "問題を調べとるで" | ||||||
|   no-network: "ネットワークに接続されていません" |   no-network: "ネットワークに接続されとらんで" | ||||||
|   no-network-desc: "お使いのPCのネットワーク接続が正常か確認してください。" |   no-network-desc: "つこてるPCのネットワーク接続が正常か確認してや。" | ||||||
|   no-internet: "インターネットに接続されていません" |   no-internet: "インターネットに接続されとらんで" | ||||||
|   no-internet-desc: "ネットワークには接続されていますが、インターネットには接続されていないようです。お使いのPCのインターネット接続が正常か確認してください。" |   no-internet-desc: "ネットワークには接続されとるけど、インターネットには接続されとらんようやわ。つこてるPCのインターネット接続が正常か確認してや。" | ||||||
|   no-server: "Misskeyのサーバーに接続できません" |   no-server: "Misskeyのサーバーに接続でけへんわ" | ||||||
|   no-server-desc: "お使いのPCのインターネット接続は正常ですが、Misskeyのサーバーには接続できませんでした。サーバーがダウンまたはメンテナンスしている可能性があるので、しばらくしてから再度御アクセスください。" |   no-server-desc: "つこてるPCのインターネット接続は正常やけど、Misskeyのサーバーにはつながらんわ。多分サーバーがダウンまたはメンテナンスしとるわ、知らんけど。すまんけどしばらくしてから再度アクセスしてみてや。" | ||||||
|   success: "Misskeyのサーバーに接続できました" |   success: "Misskeyのサーバーに接続できたわ" | ||||||
|   success-desc: "正常に接続できるようです。ページを再度読み込みしてください。" |   success-desc: "正常に接続できるようやわ。ページを再度読み込みしてな。" | ||||||
|   flush: "キャッシュの削除" |   flush: "キャッシュの削除" | ||||||
|   set-version: "バージョン指定" |   set-version: "バージョン指定" | ||||||
| common/views/components/messaging.vue: | common/views/components/messaging.vue: | ||||||
|   search-user: "ユーザーを探す" |   search-user: "ユーザーを探す" | ||||||
|   you: "あなた" |   you: "あんさん" | ||||||
|   no-history: "履歴はありません" |   no-history: "履歴はあらへんで" | ||||||
| common/views/components/messaging-room.vue: | common/views/components/messaging-room.vue: | ||||||
|   empty: "このユーザーと話したことはありません" |   empty: "このユーザーと話したことはあらへんで" | ||||||
|   more: "もっと読む" |   more: "もっと読む" | ||||||
|   no-history: "これより過去の履歴はありません" |   no-history: "これより過去の履歴はあらへんで" | ||||||
|   resize-form: "ドラッグしてフォームの広さを調整" |   resize-form: "ドラッグしてフォームの広さを調整" | ||||||
|   new-message: "新しいメッセージがあります" |   new-message: "新しいメッセージがあるで" | ||||||
|   only-one-file-attached: "メッセージに添付できるのはひとつのファイルのみです" |   only-one-file-attached: "メッセージに添付できんのはひとつのファイルのみやで" | ||||||
| common/views/components/messaging-room.form.vue: | common/views/components/messaging-room.form.vue: | ||||||
|   input-message-here: "ここにメッセージを入力" |   input-message-here: "ここにメッセージ書いてや" | ||||||
|   send: "送信" |   send: "送信" | ||||||
|   attach-from-local: "PCからファイルを添付する" |   attach-from-local: "PCからファイルを添付する" | ||||||
|   attach-from-drive: "ドライブからファイルを添付する" |   attach-from-drive: "ドライブからファイルを添付する" | ||||||
|   only-one-file-attached: "メッセージに添付できるのはひとつのファイルのみです" |   only-one-file-attached: "メッセージに添付できんのはひとつのファイルのみやで" | ||||||
| common/views/components/messaging-room.message.vue: | common/views/components/messaging-room.message.vue: | ||||||
|   is-read: "既読" |   is-read: "既読" | ||||||
|   deleted: "このメッセージは削除されました" |   deleted: "このメッセージは削除されたわ" | ||||||
| common/views/components/nav.vue: | common/views/components/nav.vue: | ||||||
|   about: "Misskeyについて" |   about: "Misskeyについて" | ||||||
|   stats: "統計" |   stats: "統計" | ||||||
|   status: "ステータス" |   status: "ステータス" | ||||||
|   wiki: "Wiki" |   wiki: "Wiki" | ||||||
|   donors: "ドナー" |   donors: "支援者" | ||||||
|   repository: "リポジトリ" |   repository: "リポジトリ" | ||||||
|   develop: "開発者" |   develop: "開発者" | ||||||
|   feedback: "フィードバック" |   feedback: "フィードバック" | ||||||
| common/views/components/note-menu.vue: | common/views/components/note-menu.vue: | ||||||
|   favorite: "お気に入り" |   favorite: "お気に入り" | ||||||
|   pin: "ピン留め" |   pin: "ピン留め" | ||||||
|   delete: "削除" |   delete: "ほかす" | ||||||
|   delete-confirm: "この投稿を削除しますか?" |   delete-confirm: "この投稿を削除してもええか?" | ||||||
|   remote: "投稿元で見る" |   remote: "投稿元で見る" | ||||||
| common/views/components/poll.vue: | common/views/components/poll.vue: | ||||||
|   vote-to: "「{}」に投票する" |   vote-to: "「{}」に投票や!" | ||||||
|   vote-count: "{}票" |   vote-count: "{}票" | ||||||
|   total-users: "{}人が投票" |   total-users: "{}人が投票" | ||||||
|   vote: "投票する" |   vote: "投票するで" | ||||||
|   show-result: "結果を見る" |   show-result: "結果を見よか" | ||||||
|   voted: "投票済み" |   voted: "投票済みや" | ||||||
| common/views/components/poll-editor.vue: | common/views/components/poll-editor.vue: | ||||||
|   no-only-one-choice: "アンケートには、選択肢が最低2つ必要です" |   no-only-one-choice: "選択肢が最低2つ必要やで" | ||||||
|   choice-n: "選択肢{}" |   choice-n: "選択肢{}" | ||||||
|   remove: "この選択肢を削除" |   remove: "この選択肢を消すで" | ||||||
|   add: "+選択肢を追加" |   add: "+選択肢を追加" | ||||||
|   destroy: "アンケートを破棄" |   destroy: "アンケートをほかそ" | ||||||
| common/views/components/reaction-picker.vue: | common/views/components/reaction-picker.vue: | ||||||
|   choose-reaction: "リアクションを選択" |   choose-reaction: "リアクションを選択" | ||||||
| common/views/components/signin.vue: | common/views/components/signin.vue: | ||||||
|   username: "ユーザー名" |   username: "ユーザー名" | ||||||
|   password: "パスワード" |   password: "パスワード" | ||||||
|   token: "トークン" |   token: "トークン" | ||||||
|   signing-in: "やってます..." |   signing-in: "サインイン中や..." | ||||||
|   signin: "サインイン" |   signin: "サインイン" | ||||||
|   or: "または" |   or: "または" | ||||||
|   signin-with-twitter: "Twitterでログイン" |   signin-with-twitter: "Twitterでサインイン" | ||||||
|   login-failed: "ログインできませんでした。ユーザー名とパスワードを確認してください。" |   login-failed: "なんかログインできんかったわ。ユーザー名とパスワードとかを確認してや。" | ||||||
| common/views/components/signup.vue: | common/views/components/signup.vue: | ||||||
|   invitation-code: "招待コード" |   invitation-code: "招待コード" | ||||||
|   invitation-info: "招待コードをお持ちでない方は、<a href=\"{}\">管理者</a>までご連絡ください。" |   invitation-info: "招待コードをお持ちでない方は、<a href=\"{}\">管理者</a>までご連絡ください。" | ||||||
|   username: "ユーザー名" |   username: "ユーザー名" | ||||||
|   checking: "確認しています..." |   checking: "確認中や…" | ||||||
|   available: "利用できます" |   available: "使えるで" | ||||||
|   unavailable: "既に利用されています" |   unavailable: "もう使われとるで" | ||||||
|   error: "通信エラー" |   error: "通信エラー" | ||||||
|   invalid-format: "a~z、A~Z、0~9、_が使えます" |   invalid-format: "a~z、A~Z、0~9、_が使えるで" | ||||||
|   too-short: "1文字以上でお願いします!" |   too-short: "1文字以上でお願いします!" | ||||||
|   too-long: "20文字以内でお願いします" |   too-long: "20文字以内でお願いします" | ||||||
|   password: "パスワード" |   password: "パスワード" | ||||||
|   password-placeholder: "8文字以上を推奨します" |   password-placeholder: "8文字以上を推奨します" | ||||||
|   weak-password: "弱いパスワード" |   weak-password: "へぼいパスワード" | ||||||
|   normal-password: "まあまあのパスワード" |   normal-password: "ぼちぼちなパスワード" | ||||||
|   strong-password: "強いパスワード" |   strong-password: "良さげなパスワード" | ||||||
|   retype: "再入力" |   retype: "もっかい入力頼むで" | ||||||
|   retype-placeholder: "確認のため再入力してください" |   retype-placeholder: "確認のためもっぺん入力してや" | ||||||
|   password-matched: "確認されました" |   password-matched: "一致しとるで" | ||||||
|   password-not-matched: "一致していません" |   password-not-matched: "一致しとらんで" | ||||||
|   recaptcha: "認証" |   recaptcha: "認証" | ||||||
|   create: "アカウント作成" |   create: "アカウント作成" | ||||||
|   some-error: "何らかの原因によりアカウントの作成に失敗しました。再度お試しください。" |   some-error: "何かよう分からんけど、アカウントの作成に失敗してしもたわ。すまんがもっぺん試してくれへんか?" | ||||||
| common/views/components/special-message.vue: | common/views/components/special-message.vue: | ||||||
|   new-year: "Happy New Year!" |   new-year: "Happy New Year!" | ||||||
|   christmas: "Merry Christmas!" |   christmas: "Merry Christmas!" | ||||||
| @@ -320,8 +320,8 @@ common/views/components/stream-indicator.vue: | |||||||
|   reconnecting: "再接続中" |   reconnecting: "再接続中" | ||||||
|   connected: "接続完了" |   connected: "接続完了" | ||||||
| common/views/components/twitter-setting.vue: | common/views/components/twitter-setting.vue: | ||||||
|   description: "お使いのTwitterアカウントをお使いのMisskeyアカウントに接続しておくと、プロフィールでTwitterアカウント情報が表示されるようになったり、Twitterを用いた便利なサインインを利用できるようになります。" |   description: "あんさんがつことるTwitterアカウントをMisskeyアカウントに接続しとくと、あんさんのプロフィールにTwitterアカウント情報が表示されるようになったり、Twitterをつこた便利なサインインが使えるようになったりすんで。" | ||||||
|   connected-to: "次のTwitterアカウントに接続されています" |   connected-to: "次のTwitterアカウントに接続されとるで" | ||||||
|   detail: "詳細..." |   detail: "詳細..." | ||||||
|   reconnect: "再接続する" |   reconnect: "再接続する" | ||||||
|   connect: "Twitterと接続する" |   connect: "Twitterと接続する" | ||||||
| @@ -339,7 +339,7 @@ common/views/components/visibility-chooser.vue: | |||||||
|   private: "非公開" |   private: "非公開" | ||||||
| common/views/widgets/broadcast.vue: | common/views/widgets/broadcast.vue: | ||||||
|   fetching: "確認中" |   fetching: "確認中" | ||||||
|   no-broadcasts: "お知らせはありません" |   no-broadcasts: "お知らせはあらへんで" | ||||||
|   have-a-nice-day: "良い一日を!" |   have-a-nice-day: "良い一日を!" | ||||||
|   next: "次" |   next: "次" | ||||||
| common/views/widgets/calendar.vue: | common/views/widgets/calendar.vue: | ||||||
| @@ -351,17 +351,17 @@ common/views/widgets/calendar.vue: | |||||||
|   this-year: "今年:" |   this-year: "今年:" | ||||||
| common/views/widgets/donation.vue: | common/views/widgets/donation.vue: | ||||||
|   title: "寄付のお願い" |   title: "寄付のお願い" | ||||||
|   text: "Misskeyの運営にはドメイン、サーバー等のコストが掛かります。Misskeyは広告を掲載したりしないため、収入を皆様からの寄付に頼っています。もしご興味があれば、{}までご連絡ください。ご協力ありがとうございます。" |   text: "Misskeyの運営にはドメイン、サーバー等のコストが掛かるんや。Misskeyは広告を掲載したりせんから、収入を皆様からの寄付に頼ってますねん。もし興味があるなら、{}までご連絡よろしゅう頼んます。ご協力おおきに。" | ||||||
| common/views/widgets/photo-stream.vue: | common/views/widgets/photo-stream.vue: | ||||||
|   title: "フォトストリーム" |   title: "フォトストリーム" | ||||||
|   no-photos: "写真はありません" |   no-photos: "写真はあらへんで" | ||||||
| common/views/widgets/posts-monitor.vue: | common/views/widgets/posts-monitor.vue: | ||||||
|   title: "投稿チャート" |   title: "投稿チャート" | ||||||
|   toggle: "表示を切り替え" |   toggle: "表示を切り替え" | ||||||
| common/views/widgets/hashtags.vue: | common/views/widgets/hashtags.vue: | ||||||
|   title: "ハッシュタグ" |   title: "ハッシュタグ" | ||||||
|   count: "{}人が投稿" |   count: "{}人が投稿" | ||||||
|   empty: "トレンドなし" |   empty: "流行は自分で作るんや" | ||||||
| common/views/widgets/server.vue: | common/views/widgets/server.vue: | ||||||
|   title: "サーバー情報" |   title: "サーバー情報" | ||||||
|   toggle: "表示を切り替え" |   toggle: "表示を切り替え" | ||||||
| @@ -370,30 +370,30 @@ common/views/widgets/memo.vue: | |||||||
|   memo: "ここに書いて!" |   memo: "ここに書いて!" | ||||||
|   save: "保存" |   save: "保存" | ||||||
| common/views/widgets/slideshow.vue: | common/views/widgets/slideshow.vue: | ||||||
|   folder-customize-mode: "フォルダを指定するには、カスタマイズモードを終了してください" |   folder-customize-mode: "フォルダを指定するんやったら、一旦カスタマイズモードを終了してや" | ||||||
|   folder: "クリックしてフォルダを指定してください" |   folder: "クリックしてフォルダを指定してください" | ||||||
|   no-image: "このフォルダには画像がありません" |   no-image: "このフォルダには画像がありません" | ||||||
| common/views/widgets/tips.vue: | common/views/widgets/tips.vue: | ||||||
|   tips-line1: "<kbd>t</kbd>でタイムラインにフォーカスできます" |   tips-line1: "<kbd>t</kbd>でタイムラインにフォーカスできんで" | ||||||
|   tips-line2: "<kbd>p</kbd>または<kbd>n</kbd>で投稿フォームを開きます" |   tips-line2: "<kbd>p</kbd>または<kbd>n</kbd>で投稿フォームを開くで" | ||||||
|   tips-line3: "投稿フォームにはファイルをドラッグ&ドロップできます" |   tips-line3: "投稿フォームにはファイルをドラッグ&ドロップできんで" | ||||||
|   tips-line4: "投稿フォームにクリップボードにある画像データをペーストできます" |   tips-line4: "投稿フォームにクリップボードにおる画像データをペーストできんで" | ||||||
|   tips-line5: "ドライブにファイルをドラッグ&ドロップしてアップロードできます" |   tips-line5: "ドライブにファイルをドラッグ&ドロップしてアップロードできんで" | ||||||
|   tips-line6: "ドライブでファイルをドラッグしてフォルダ移動できます" |   tips-line6: "ドライブやと、ファイルをドラッグしてフォルダ移動できんで" | ||||||
|   tips-line7: "ドライブでフォルダをドラッグしてフォルダ移動できます" |   tips-line7: "ドライブやと、フォルダをドラッグしてフォルダ移動できんで" | ||||||
|   tips-line8: "ホームは設定からカスタマイズできます" |   tips-line8: "ホームは設定からカスタマイズできんで" | ||||||
|   tips-line9: "MisskeyはAGPLv3です" |   tips-line9: "MisskeyはAGPLv3やで" | ||||||
|   tips-line10: "タイムマシンウィジェットを利用すると、簡単に過去のタイムラインに遡れます" |   tips-line10: "タイムマシンウィジェットを利用すると、簡単に過去のタイムラインに遡れんで" | ||||||
|   tips-line11: "投稿の ... をクリックして、投稿をユーザーページにピン留めできます" |   tips-line11: "投稿の ... をクリックして、ピン留めから投稿をユーザーページにピン留めできんで" | ||||||
|   tips-line13: "投稿に添付したファイルは全てドライブに保存されます" |   tips-line13: "投稿に添付したファイルは全てドライブに保存されんで" | ||||||
|   tips-line14: "ホームのカスタマイズ中、ウィジェットを右クリックしてデザインを変更できます" |   tips-line14: "ホームのカスタマイズ中、ウィジェットを右クリックしてデザインを変更できんで" | ||||||
|   tips-line17: "「**」でテキストを囲むと**強調表示**されます" |   tips-line17: "「**」でテキストを囲ったると**強調表示**されんで" | ||||||
|   tips-line19: "いくつかのウィンドウはブラウザの外に切り離すことができます" |   tips-line19: "いくつかのウィンドウはブラウザの外に切り離すことができんで" | ||||||
|   tips-line20: "カレンダーウィジェットのパーセンテージは、経過の割合を示しています" |   tips-line20: "カレンダーウィジェットのパーセンテージは、経過の割合を示してんねん" | ||||||
|   tips-line21: "APIを利用してbotの開発なども行えます" |   tips-line21: "APIをつこてbotの開発なども行えるで" | ||||||
|   tips-line23: "まゆかわいいよまゆ" |   tips-line23: "まゆかわいいよまゆ" | ||||||
|   tips-line24: "Misskeyは2014年にサービスを開始しました" |   tips-line24: "Misskeyは2014年にサービスを開始したんよ" | ||||||
|   tips-line25: "対応ブラウザではMisskeyを開いていなくても通知を受け取れます" |   tips-line25: "対応ブラウザやったらMisskeyを開いとらんでも通知を受け取れんで" | ||||||
| common/views/pages/follow.vue: | common/views/pages/follow.vue: | ||||||
|   signed-in-as: "{}としてサインイン中" |   signed-in-as: "{}としてサインイン中" | ||||||
|   following: "フォロー中" |   following: "フォロー中" | ||||||
| @@ -403,14 +403,15 @@ common/views/pages/follow.vue: | |||||||
| desktop: | desktop: | ||||||
|   banner-crop-title: "バナーとして表示する部分を選択" |   banner-crop-title: "バナーとして表示する部分を選択" | ||||||
|   banner: "バナー" |   banner: "バナー" | ||||||
|   uploading-banner: "新しいバナーをアップロードしています" |   uploading-banner: "新しいバナーをアップロードしとるで" | ||||||
|   banner-updated: "バナーを更新しました" |   banner-updated: "バナーを更新したで" | ||||||
|   choose-banner: "バナーにする画像を選択" |   choose-banner: "バナーにする画像を選択" | ||||||
|   avatar-crop-title: "アバターとして表示する部分を選択" |   avatar-crop-title: "アバターとして表示する部分を選択" | ||||||
|   avatar: "アバター" |   avatar: "アバター" | ||||||
|   uploading-avatar: "新しいアバターをアップロードしています" |   uploading-avatar: "新しいアバターをアップロードしています" | ||||||
|   avatar-updated: "アバターを更新しました" |   avatar-updated: "アバターを更新しました" | ||||||
|   choose-avatar: "アバターにする画像を選択" |   choose-avatar: "アバターにする画像を選択" | ||||||
|  |   invalid-filetype: "この形式のファイルはサポートされていません" | ||||||
| desktop/views/components/activity.chart.vue: | desktop/views/components/activity.chart.vue: | ||||||
|   total: "Black ... Total" |   total: "Black ... Total" | ||||||
|   notes: "Blue ... Notes" |   notes: "Blue ... Notes" | ||||||
| @@ -420,10 +421,10 @@ desktop/views/components/activity.vue: | |||||||
|   title: "アクティビティ" |   title: "アクティビティ" | ||||||
|   toggle: "表示を切り替え" |   toggle: "表示を切り替え" | ||||||
| desktop/views/components/calendar.vue: | desktop/views/components/calendar.vue: | ||||||
|   title: "{1}年 {2}月" |   title: "{1}年 {2} 月" | ||||||
|   prev: "前の月" |   prev: "前の月" | ||||||
|   next: "次の月" |   next: "次の月" | ||||||
|   go: "クリックして時間遡行" |   go: "クリックしてタイムリープ" | ||||||
| desktop/views/components/charts.vue: | desktop/views/components/charts.vue: | ||||||
|   title: "チャート" |   title: "チャート" | ||||||
|   per-day: "1日ごと" |   per-day: "1日ごと" | ||||||
| @@ -464,7 +465,7 @@ desktop/views/components/drive.file.vue: | |||||||
|   banner: "バナー" |   banner: "バナー" | ||||||
|   nsfw: "閲覧注意" |   nsfw: "閲覧注意" | ||||||
|   contextmenu: |   contextmenu: | ||||||
|     rename: "名前を変更" |     rename: "名前を変えるで" | ||||||
|     mark-as-sensitive: "閲覧注意に設定" |     mark-as-sensitive: "閲覧注意に設定" | ||||||
|     unmark-as-sensitive: "閲覧注意を解除" |     unmark-as-sensitive: "閲覧注意を解除" | ||||||
|     copy-url: "URLをコピー" |     copy-url: "URLをコピー" | ||||||
| @@ -475,26 +476,26 @@ desktop/views/components/drive.file.vue: | |||||||
|     open-in-app: "アプリで開く" |     open-in-app: "アプリで開く" | ||||||
|     add-app: "アプリを追加" |     add-app: "アプリを追加" | ||||||
|     rename-file: "ファイル名の変更" |     rename-file: "ファイル名の変更" | ||||||
|     input-new-file-name: "新しいファイル名を入力してください" |     input-new-file-name: "新しいファイル名を入力してや" | ||||||
|     copied: "コピー完了" |     copied: "コピー完了や" | ||||||
|     copied-url-to-clipboard: "URLをクリップボードにコピーしました" |     copied-url-to-clipboard: "URLをクリップボードにコピーしました" | ||||||
| desktop/views/components/drive.folder.vue: | desktop/views/components/drive.folder.vue: | ||||||
|   unable-to-process: "操作を完了できません" |   unable-to-process: "操作を完了できません" | ||||||
|   circular-reference-detected: "移動先のフォルダーは、移動するフォルダーのサブフォルダーです。" |   circular-reference-detected: "移動先のフォルダーは、移動するフォルダーのサブフォルダーです。" | ||||||
|   unhandled-error: "不明なエラー" |   unhandled-error: "ようわからん" | ||||||
|   contextmenu: |   contextmenu: | ||||||
|     move-to-this-folder: "このフォルダへ移動" |     move-to-this-folder: "このフォルダへ移動" | ||||||
|     show-in-new-window: "新しいウィンドウで表示" |     show-in-new-window: "新しいウィンドウで表示" | ||||||
|     rename: "名前を変更" |     rename: "名前を変えるで" | ||||||
|     rename-folder: "フォルダ名の変更" |     rename-folder: "フォルダ名を変えるで" | ||||||
|     input-new-folder-name: "新しいフォルダ名を入力してください" |     input-new-folder-name: "新しいフォルダ名を入力してや" | ||||||
| desktop/views/components/drive.nav-folder.vue: | desktop/views/components/drive.nav-folder.vue: | ||||||
|   drive: "ドライブ" |   drive: "ドライブ" | ||||||
| desktop/views/components/drive.vue: | desktop/views/components/drive.vue: | ||||||
|   search: "検索" |   search: "検索" | ||||||
|   load-more: "もっと読み込む" |   load-more: "もっと読み込む" | ||||||
|   empty-draghover: "ドロップですか?いいですよ、ボクはカワイイですからね" |   empty-draghover: "ドロップですか?いいですよ、ボクはカワイイですからね" | ||||||
|   empty-drive: "ドライブには何もありません。" |   empty-drive: "ドライブには何もあらへんで。" | ||||||
|   empty-drive-description: "右クリックして「ファイルをアップロード」を選んだり、ファイルをドラッグ&ドロップすることでもアップロードできます。" |   empty-drive-description: "右クリックして「ファイルをアップロード」を選んだり、ファイルをドラッグ&ドロップすることでもアップロードできます。" | ||||||
|   empty-folder: "このフォルダーは空です" |   empty-folder: "このフォルダーは空です" | ||||||
|   unable-to-process: "操作を完了できません" |   unable-to-process: "操作を完了できません" | ||||||
| @@ -511,11 +512,11 @@ desktop/views/components/drive.vue: | |||||||
|     upload: "ファイルをアップロード" |     upload: "ファイルをアップロード" | ||||||
|     url-upload: "URLからアップロード" |     url-upload: "URLからアップロード" | ||||||
| desktop/views/components/media-image.vue: | desktop/views/components/media-image.vue: | ||||||
|   sensitive: "閲覧注意" |   sensitive: "ちょっと見せられへんわ" | ||||||
|   click-to-show: "クリックして表示" |   click-to-show: "クリックして見せるで" | ||||||
| desktop/views/components/media-video.vue: | desktop/views/components/media-video.vue: | ||||||
|   sensitive: "閲覧注意" |   sensitive: "ちょっと見せられへんわ" | ||||||
|   click-to-show: "クリックして表示" |   click-to-show: "クリックして見せるで" | ||||||
| desktop/views/components/follow-button.vue: | desktop/views/components/follow-button.vue: | ||||||
|   following: "フォロー中" |   following: "フォロー中" | ||||||
|   follow: "フォロー" |   follow: "フォロー" | ||||||
| @@ -536,7 +537,7 @@ desktop/views/components/friends-maker.vue: | |||||||
|   refresh: "もっと見る" |   refresh: "もっと見る" | ||||||
|   close: "閉じる" |   close: "閉じる" | ||||||
| desktop/views/components/game-window.vue: | desktop/views/components/game-window.vue: | ||||||
|   game: "リバーシ" |   game: "ゲーム" | ||||||
| desktop/views/components/home.vue: | desktop/views/components/home.vue: | ||||||
|   done: "完了" |   done: "完了" | ||||||
|   add-widget: "ウィジェットを追加:" |   add-widget: "ウィジェットを追加:" | ||||||
| @@ -575,32 +576,32 @@ desktop/views/components/notifications.vue: | |||||||
|   empty: "ありません!" |   empty: "ありません!" | ||||||
| desktop/views/components/post-form.vue: | desktop/views/components/post-form.vue: | ||||||
|   add-visible-user: "+ユーザーを追加" |   add-visible-user: "+ユーザーを追加" | ||||||
|   attach-location-information: "位置情報を添付する" |   attach-location-information: "いる場所くっつけるで" | ||||||
|   hide-contents: "内容を隠す" |   hide-contents: "内容を隠す" | ||||||
|   reply-placeholder: "この投稿への返信..." |   reply-placeholder: "この投稿への返信..." | ||||||
|   quote-placeholder: "この投稿を引用..." |   quote-placeholder: "この投稿を引用..." | ||||||
|   submit: "投稿" |   submit: "投稿" | ||||||
|   reply: "返信" |   reply: "返信" | ||||||
|   renote: "Renote" |   renote: "Renote" | ||||||
|   posted: "投稿しました!" |   posted: "投稿したで!" | ||||||
|   replied: "返信しました!" |   replied: "返信したで!" | ||||||
|   reposted: "Renoteしました!" |   reposted: "Renoteしました!" | ||||||
|   note-failed: "投稿に失敗しました" |   note-failed: "投稿に失敗したで" | ||||||
|   reply-failed: "返信に失敗しました" |   reply-failed: "返信に失敗したで" | ||||||
|   renote-failed: "Renoteに失敗しました" |   renote-failed: "Renoteに失敗しました" | ||||||
|   posting: "投稿中" |   posting: "投稿中" | ||||||
|   attach-media-from-local: "PCからメディアを添付" |   attach-media-from-local: "PCからメディアを添付" | ||||||
|   attach-media-from-drive: "ドライブからメディアを添付" |   attach-media-from-drive: "ドライブからメディアを添付" | ||||||
|   attach-cancel: "添付取り消し" |   attach-cancel: "くっつけるのやめよか" | ||||||
|   insert-a-kao: "v('ω')v" |   insert-a-kao: "v('ω')v" | ||||||
|   create-poll: "アンケートを作成" |   create-poll: "アンケートを作成" | ||||||
|   text-remain: "残り{}文字" |   text-remain: "残り{}文字" | ||||||
|   recent-tags: "最近" |   recent-tags: "最近のタグ" | ||||||
|   click-to-tagging: "クリックでタグ付け" |   click-to-tagging: "クリックでタグ付け" | ||||||
|   visibility: "公開範囲" |   visibility: "公開範囲" | ||||||
|   geolocation-alert: "お使いの端末は位置情報に対応していません" |   geolocation-alert: "あんさんのつことる端末は位置情報に対応しとらんみたいやわ、知らんけど。" | ||||||
|   error: "エラー" |   error: "エラー" | ||||||
|   enter-username: "ユーザー名を入力してください" |   enter-username: "ユーザー名を入力してや" | ||||||
|   annotations: "内容への注釈 (オプション)" |   annotations: "内容への注釈 (オプション)" | ||||||
| desktop/views/components/post-form-window.vue: | desktop/views/components/post-form-window.vue: | ||||||
|   note: "新規投稿" |   note: "新規投稿" | ||||||
| @@ -639,7 +640,7 @@ desktop/views/components/settings.vue: | |||||||
|   auto-popout-desc: "ウィンドウが開かれるとき、ポップアウト(ブラウザ外に切り離す)可能なら自動でポップアウトします。この設定はブラウザに記憶されます。" |   auto-popout-desc: "ウィンドウが開かれるとき、ポップアウト(ブラウザ外に切り離す)可能なら自動でポップアウトします。この設定はブラウザに記憶されます。" | ||||||
|   advanced: "詳細設定" |   advanced: "詳細設定" | ||||||
|   api-via-stream: "ストリームを経由したAPIリクエスト" |   api-via-stream: "ストリームを経由したAPIリクエスト" | ||||||
|   api-via-stream-desc: "この設定をオンにすると、websocket接続を経由してAPIリクエストが行われます(パフォーマンス向上が期待できます)。オフにすると、ネイティブの fetch APIが利用されます。この設定はこのデバイスのみ有効です。" |   api-via-stream-desc: "この設定をオンにすると、WebSocket接続を経由してAPIリクエストが行われんで(パフォーマンス向上するかも、知らんけど)。オフにすると、ネイティブの fetch API が利用されるで。この設定はこのデバイスのみ有効やで。" | ||||||
|   display: "デザインと表示" |   display: "デザインと表示" | ||||||
|   customize: "ホームをカスタマイズ" |   customize: "ホームをカスタマイズ" | ||||||
|   choose-wallpaper: "壁紙を選択" |   choose-wallpaper: "壁紙を選択" | ||||||
| @@ -649,6 +650,7 @@ desktop/views/components/settings.vue: | |||||||
|   gradient-window-header: "ウィンドウのタイトルバーにグラデーションを使用" |   gradient-window-header: "ウィンドウのタイトルバーにグラデーションを使用" | ||||||
|   post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" |   post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" | ||||||
|   suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する" |   suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する" | ||||||
|  |   show-clock-on-header: "右上に時計を表示する" | ||||||
|   show-reply-target: "リプライ先を表示する" |   show-reply-target: "リプライ先を表示する" | ||||||
|   show-my-renotes: "自分の行ったRenoteをタイムラインに表示する" |   show-my-renotes: "自分の行ったRenoteをタイムラインに表示する" | ||||||
|   show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する" |   show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する" | ||||||
| @@ -686,9 +688,9 @@ desktop/views/components/settings.vue: | |||||||
|   prevent-update: "アップデートを延期する(非推奨)" |   prevent-update: "アップデートを延期する(非推奨)" | ||||||
|   prevent-update-desc: "この設定をオンにしてもアップデートが反映される場合があります。この設定はこのデバイスのみ有効です。" |   prevent-update-desc: "この設定をオンにしてもアップデートが反映される場合があります。この設定はこのデバイスのみ有効です。" | ||||||
|   no-updates: "利用可能な更新はありません" |   no-updates: "利用可能な更新はありません" | ||||||
|   no-updates-desc: "お使いのMisskeyは最新です。" |   no-updates-desc: "つこてるMisskeyは最新や!" | ||||||
|   update-available: "新しいバージョンが利用可能です" |   update-available: "新しいバージョンが利用可能や" | ||||||
|   update-available-desc: "ページを再度読み込みすると更新が適用されます。" |   update-available-desc: "ページを再度読み込みすると更新が適用されるで。" | ||||||
|   advanced-settings: "高度な設定" |   advanced-settings: "高度な設定" | ||||||
|   debug-mode: "デバッグモードを有効にする" |   debug-mode: "デバッグモードを有効にする" | ||||||
|   debug-mode-desc: "この設定はブラウザに記憶されます。" |   debug-mode-desc: "この設定はブラウザに記憶されます。" | ||||||
| @@ -707,28 +709,28 @@ desktop/views/components/settings.2fa.vue: | |||||||
|   unregister: "設定を解除" |   unregister: "設定を解除" | ||||||
|   unregistered: "二段階認証が無効になりました。" |   unregistered: "二段階認証が無効になりました。" | ||||||
|   enter-password: "パスワードを入力してください" |   enter-password: "パスワードを入力してください" | ||||||
|   authenticator: "まず、Google Authenticatorをお使いのデバイスにインストールします:" |   authenticator: "まず、Google Authenticatorとかのをつこてるデバイスにインストールしてや:" | ||||||
|   howtoinstall: "インストール方法はこちら" |   howtoinstall: "インストール方法はここやで" | ||||||
|   scan: "次に、表示されているQRコードをスキャンします:" |   scan: "んで、ここに出とるQRコードをスキャンしてな:" | ||||||
|   done: "お使いのデバイスに表示されているトークンを入力して完了します:" |   done: "最後にデバイスに表示されとるトークンを入力してな:" | ||||||
|   submit: "完了" |   submit: "送信" | ||||||
|   success: "設定が完了しました!" |   success: "設定が完了したで!" | ||||||
|   failed: "設定に失敗しました。トークンに誤りがないかご確認ください。" |   failed: "なんか設定に失敗したで。トークンを間違えとらんか確認してや。" | ||||||
|   info: "次回サインインからは、同様にパスワードに加えてデバイスに表示されているトークンを入力します。" |   info: "次のサインインからは、パスワードに加えてデバイスに出とるトークンを入力してな。" | ||||||
| desktop/views/components/settings.api.vue: | desktop/views/components/settings.api.vue: | ||||||
|   intro: "APIを利用するには、上記のトークンを「i」というキーでパラメータに付加してリクエストします。" |   intro: "APIを利用するには、上記のトークンを「i」っちゅうキーでパラメータに付加してリクエストしてや。" | ||||||
|   caution: "アカウントを不正利用される可能性があるため、このトークンは第三者に教えないでください(アプリなどにも入力しないでください)。" |   caution: "アカウントを不正利用されるかも知れんから、このトークンは第三者に教えたらあかんで(アプリなどにも入力しんといてな)。" | ||||||
|   regeneration-of-token: "万が一このトークンが漏れたりその可能性がある場合はトークンを再生成できます。" |   regeneration-of-token: "万が一このトークンが漏れたとかその可能性があったらトークンを再生成できるで。" | ||||||
|   regenerate-token: "トークンを再生成" |   regenerate-token: "トークンを再生成" | ||||||
|   token: "Token:" |   token: "トークン:" | ||||||
|   enter-password: "パスワードを入力してください" |   enter-password: "パスワードを入力してや" | ||||||
| desktop/views/components/settings.apps.vue: | desktop/views/components/settings.apps.vue: | ||||||
|   no-apps: "連携しているアプリケーションはありません" |   no-apps: "連携しているアプリケーションはあらへんで" | ||||||
| desktop/views/components/settings.drive.vue: | desktop/views/components/settings.drive.vue: | ||||||
|   max: "中" |   max: "中" | ||||||
|   in-use: "使用中" |   in-use: "使用中" | ||||||
| desktop/views/components/settings.mute.vue: | desktop/views/components/settings.mute.vue: | ||||||
|   no-users: "ミュートしているユーザーはいません" |   no-users: "ミュートしているユーザーはおらんで" | ||||||
| desktop/views/components/settings.password.vue: | desktop/views/components/settings.password.vue: | ||||||
|   reset: "パスワードを変更する" |   reset: "パスワードを変更する" | ||||||
|   enter-current-password: "現在のパスワードを入力してください" |   enter-current-password: "現在のパスワードを入力してください" | ||||||
| @@ -764,7 +766,7 @@ desktop/views/components/timeline.vue: | |||||||
|   global: "グローバル" |   global: "グローバル" | ||||||
|   list: "リスト" |   list: "リスト" | ||||||
| desktop/views/components/ui.header.vue: | desktop/views/components/ui.header.vue: | ||||||
|   welcome-back: "おかえりなさい、" |   welcome-back: "おかえり、" | ||||||
|   adjective: "さん" |   adjective: "さん" | ||||||
| desktop/views/components/ui.header.account.vue: | desktop/views/components/ui.header.account.vue: | ||||||
|   profile: "プロフィール" |   profile: "プロフィール" | ||||||
| @@ -772,7 +774,7 @@ desktop/views/components/ui.header.account.vue: | |||||||
|   favorites: "お気に入り" |   favorites: "お気に入り" | ||||||
|   lists: "リスト" |   lists: "リスト" | ||||||
|   follow-requests: "フォロー申請" |   follow-requests: "フォロー申請" | ||||||
|   customize: "ホームのカスタマイズ" |   customize: "ホームをカスタマイズ" | ||||||
|   admin: "管理" |   admin: "管理" | ||||||
|   settings: "設定" |   settings: "設定" | ||||||
|   signout: "サインアウト" |   signout: "サインアウト" | ||||||
| @@ -794,7 +796,7 @@ desktop/views/components/received-follow-requests-window.vue: | |||||||
|   reject: "拒否" |   reject: "拒否" | ||||||
| desktop/views/components/user-lists-window.vue: | desktop/views/components/user-lists-window.vue: | ||||||
|   title: "リスト" |   title: "リスト" | ||||||
|   create-list: "リストを作成" |   create-list: "新しいリストを作成" | ||||||
|   list-name: "リスト名" |   list-name: "リスト名" | ||||||
| desktop/views/components/user-preview.vue: | desktop/views/components/user-preview.vue: | ||||||
|   notes: "投稿" |   notes: "投稿" | ||||||
| @@ -819,8 +821,8 @@ desktop/views/pages/admin/admin.dashboard.vue: | |||||||
|   dashboard: "ダッシュボード" |   dashboard: "ダッシュボード" | ||||||
|   all-users: "全てのユーザー" |   all-users: "全てのユーザー" | ||||||
|   original-users: "このインスタンスのユーザー" |   original-users: "このインスタンスのユーザー" | ||||||
|   all-notes: "全てのノート" |   all-notes: "全ての投稿" | ||||||
|   original-notes: "このインスタンスのノート" |   original-notes: "このインスタンスの投稿" | ||||||
|   invite: "招待" |   invite: "招待" | ||||||
| desktop/views/pages/admin/admin.suspend-user.vue: | desktop/views/pages/admin/admin.suspend-user.vue: | ||||||
|   suspend-user: "ユーザーの凍結" |   suspend-user: "ユーザーの凍結" | ||||||
| @@ -829,11 +831,11 @@ desktop/views/pages/admin/admin.suspend-user.vue: | |||||||
| desktop/views/pages/admin/admin.unsuspend-user.vue: | desktop/views/pages/admin/admin.unsuspend-user.vue: | ||||||
|   unsuspend-user: "ユーザーの凍結の解除" |   unsuspend-user: "ユーザーの凍結の解除" | ||||||
|   unsuspend: "凍結の解除" |   unsuspend: "凍結の解除" | ||||||
|   unsuspended: "凍結を解除しました" |   unsuspended: "凍結を解除したで" | ||||||
| desktop/views/pages/admin/admin.verify-user.vue: | desktop/views/pages/admin/admin.verify-user.vue: | ||||||
|   verify-user: "ユーザーの公式アカウント設定" |   verify-user: "ユーザーの公式アカウント設定" | ||||||
|   verify: "公式アカウントにする" |   verify: "公式アカウントにする" | ||||||
|   verified: "公式アカウントにしました" |   verified: "公式アカウントにしたで" | ||||||
| desktop/views/pages/admin/admin.unverify-user.vue: | desktop/views/pages/admin/admin.unverify-user.vue: | ||||||
|   unverify-user: "ユーザーの公式アカウント解除" |   unverify-user: "ユーザーの公式アカウント解除" | ||||||
|   unverify: "公式アカウントを解除する" |   unverify: "公式アカウントを解除する" | ||||||
| @@ -846,21 +848,26 @@ desktop/views/pages/deck/deck.note.vue: | |||||||
|   reposted-by: "{}がRenote" |   reposted-by: "{}がRenote" | ||||||
|   private: "この投稿は非公開です" |   private: "この投稿は非公開です" | ||||||
|   deleted: "この投稿は削除されました" |   deleted: "この投稿は削除されました" | ||||||
|  | desktop/views/pages/stats/stats.vue: | ||||||
|  |   all-users: "全てのユーザー" | ||||||
|  |   original-users: "このインスタンスのユーザー" | ||||||
|  |   all-notes: "全ての投稿" | ||||||
|  |   original-notes: "このインスタンスの投稿" | ||||||
| desktop/views/pages/welcome.vue: | desktop/views/pages/welcome.vue: | ||||||
|   about: "詳しく..." |   about: "詳しく..." | ||||||
|   gotit: "わかった" |   gotit: "わかった" | ||||||
|   signin: "ログイン" |   signin: "サインイン" | ||||||
|   signup: "新規登録" |   signup: "サインアップ" | ||||||
|   signin-button: "やってる" |   signin-button: "サインイン中…" | ||||||
|   signup-button: "やる" |   signup-button: "サインアップ" | ||||||
|   timeline: "タイムライン" |   timeline: "タイムライン" | ||||||
|   powered-by-misskey: "Powered by <b>Misskey</b>." |   powered-by-misskey: "Powered by <b>Misskey</b>." | ||||||
| desktop/views/pages/drive.vue: | desktop/views/pages/drive.vue: | ||||||
|   title: "Misskey Drive" |   title: "ドライブ" | ||||||
| desktop/views/pages/favorites.vue: | desktop/views/pages/favorites.vue: | ||||||
|   more: "さらに読み込む" |   more: "もっと読み込んでくで" | ||||||
| desktop/views/pages/home-customize.vue: | desktop/views/pages/home-customize.vue: | ||||||
|   title: "ホームのカスタマイズ" |   title: "ホームをカスタマイズ" | ||||||
| desktop/views/pages/note.vue: | desktop/views/pages/note.vue: | ||||||
|   prev: "前の投稿" |   prev: "前の投稿" | ||||||
|   next: "次の投稿" |   next: "次の投稿" | ||||||
| @@ -895,19 +902,19 @@ desktop/views/pages/user/user.vue: | |||||||
| desktop/views/pages/user/user.home.vue: | desktop/views/pages/user/user.home.vue: | ||||||
|   last-used-at: "最終アクセス" |   last-used-at: "最終アクセス" | ||||||
| desktop/views/pages/user/user.photos.vue: | desktop/views/pages/user/user.photos.vue: | ||||||
|   title: "フォト" |   title: "写真" | ||||||
|   loading: "読み込み中" |   loading: "読み込み中" | ||||||
|   no-photos: "写真はありません" |   no-photos: "写真はあらへんで" | ||||||
| desktop/views/pages/user/user.profile.vue: | desktop/views/pages/user/user.profile.vue: | ||||||
|   follows-you: "フォローされています" |   follows-you: "フォローされとるで" | ||||||
|   stalk: "ストークする" |   stalk: "ストークする" | ||||||
|   stalking: "ストーキングしています" |   stalking: "ストーキングしとるで" | ||||||
|   unstalk: "ストーク解除" |   unstalk: "ストーク解除" | ||||||
|   mute: "ミュートする" |   mute: "ミュートする" | ||||||
|   muted: "ミュートしています" |   muted: "ミュートしとるで" | ||||||
|   unmute: "ミュート解除" |   unmute: "ミュート解除" | ||||||
|   push-to-a-list: "リストに追加" |   push-to-a-list: "リストに追加" | ||||||
|   list-pushed: "{user}を{list}に追加しました。" |   list-pushed: "{user}を{list}に追加したで。" | ||||||
| desktop/views/pages/user/user.header.vue: | desktop/views/pages/user/user.header.vue: | ||||||
|   posts: "投稿" |   posts: "投稿" | ||||||
|   following: "フォロー" |   following: "フォロー" | ||||||
| @@ -926,7 +933,7 @@ desktop/views/widgets/notifications.vue: | |||||||
| desktop/views/widgets/polls.vue: | desktop/views/widgets/polls.vue: | ||||||
|   title: "アンケート" |   title: "アンケート" | ||||||
|   refresh: "他を見る" |   refresh: "他を見る" | ||||||
|   nothing: "ありません!" |   nothing: "あらへん!" | ||||||
| desktop/views/widgets/post-form.vue: | desktop/views/widgets/post-form.vue: | ||||||
|   title: "投稿" |   title: "投稿" | ||||||
|   note: "投稿" |   note: "投稿" | ||||||
| @@ -948,7 +955,7 @@ mobile/views/components/drive.vue: | |||||||
|   count-separator: "、" |   count-separator: "、" | ||||||
|   file-count: "ファイル" |   file-count: "ファイル" | ||||||
|   load-more: "もっと読み込む" |   load-more: "もっと読み込む" | ||||||
|   nothing-in-drive: "ドライブには何もありません" |   nothing-in-drive: "ドライブには何もあらへんで。" | ||||||
|   folder-is-empty: "このフォルダは空です" |   folder-is-empty: "このフォルダは空です" | ||||||
|   prompt: "何をしますか?(数字を入力してください): <1 → ファイルをアップロード | 2 → ファイルをURLでアップロード | 3 → フォルダ作成 | 4 → このフォルダ名を変更 | 5 → このフォルダを移動 | 6 → このフォルダを削除>" |   prompt: "何をしますか?(数字を入力してください): <1 → ファイルをアップロード | 2 → ファイルをURLでアップロード | 3 → フォルダ作成 | 4 → このフォルダ名を変更 | 5 → このフォルダを移動 | 6 → このフォルダを削除>" | ||||||
|   deletion-alert: "ごめんなさい!フォルダの削除は未実装です...。" |   deletion-alert: "ごめんなさい!フォルダの削除は未実装です...。" | ||||||
| @@ -1025,9 +1032,9 @@ mobile/views/components/post-form.vue: | |||||||
|   quote-placeholder: "この投稿を引用... (オプション)" |   quote-placeholder: "この投稿を引用... (オプション)" | ||||||
|   reply-placeholder: "この投稿への返信..." |   reply-placeholder: "この投稿への返信..." | ||||||
|   cw-placeholder: "内容への注釈 (オプション)" |   cw-placeholder: "内容への注釈 (オプション)" | ||||||
|   location-alert: "お使いの端末は位置情報に対応していません" |   location-alert: "あんさんのつことる端末は位置情報に対応しとらんみたいやわ、知らんけど。" | ||||||
|   error: "エラー" |   error: "エラー" | ||||||
|   username-prompt: "ユーザー名を入力してください" |   username-prompt: "ユーザー名を入力してや" | ||||||
| mobile/views/components/sub-note-content.vue: | mobile/views/components/sub-note-content.vue: | ||||||
|   private: "この投稿は非公開です" |   private: "この投稿は非公開です" | ||||||
|   deleted: "この投稿は削除されました" |   deleted: "この投稿は削除されました" | ||||||
| @@ -1066,7 +1073,7 @@ mobile/views/pages/favorites.vue: | |||||||
|   title: "お気に入り" |   title: "お気に入り" | ||||||
| mobile/views/pages/user-lists.vue: | mobile/views/pages/user-lists.vue: | ||||||
|   title: "リスト" |   title: "リスト" | ||||||
|   enter-list-name: "リスト名を入力してください" |   enter-list-name: "リスト名を入力してや" | ||||||
| mobile/views/pages/drive.vue: | mobile/views/pages/drive.vue: | ||||||
|   drive: "ドライブ" |   drive: "ドライブ" | ||||||
|   more: "もっと見る" |   more: "もっと見る" | ||||||
| @@ -1082,7 +1089,7 @@ mobile/views/pages/home.vue: | |||||||
|   hybrid: "ソーシャル" |   hybrid: "ソーシャル" | ||||||
|   global: "グローバル" |   global: "グローバル" | ||||||
| mobile/views/pages/tag.vue: | mobile/views/pages/tag.vue: | ||||||
|   no-posts-found: "ハッシュタグ「{}」が付けられた投稿は見つかりませんでした。" |   no-posts-found: "ハッシュタグ「{}」が付けられた投稿はあらへんで。" | ||||||
| mobile/views/pages/welcome.vue: | mobile/views/pages/welcome.vue: | ||||||
|   signup: "新規登録" |   signup: "新規登録" | ||||||
| mobile/views/pages/widgets.vue: | mobile/views/pages/widgets.vue: | ||||||
| @@ -1149,7 +1156,7 @@ mobile/views/pages/settings.vue: | |||||||
|   show-local-renotes: "ローカルの投稿のRenoteを表示する" |   show-local-renotes: "ローカルの投稿のRenoteを表示する" | ||||||
|   post-style: "投稿の表示スタイル" |   post-style: "投稿の表示スタイル" | ||||||
|   post-style-standard: "標準" |   post-style-standard: "標準" | ||||||
|   post-style-smart: "スマート" |   post-style-smart: "べっぴんさん" | ||||||
|   behavior: "動作" |   behavior: "動作" | ||||||
|   fetch-on-scroll: "スクロールで自動読み込み" |   fetch-on-scroll: "スクロールで自動読み込み" | ||||||
|   disable-via-mobile: "「モバイルからの投稿」フラグを付けない" |   disable-via-mobile: "「モバイルからの投稿」フラグを付けない" | ||||||
| @@ -1170,6 +1177,8 @@ mobile/views/pages/settings.vue: | |||||||
|   update-available-desc: "ページを再度読み込みすると更新が適用されます。" |   update-available-desc: "ページを再度読み込みすると更新が適用されます。" | ||||||
|   settings: "設定" |   settings: "設定" | ||||||
|   signout: "サインアウト" |   signout: "サインアウト" | ||||||
|  |   sound: "サウンド" | ||||||
|  |   enableSounds: "サウンドを有効にする" | ||||||
| mobile/views/pages/user.vue: | mobile/views/pages/user.vue: | ||||||
|   follows-you: "フォローされています" |   follows-you: "フォローされています" | ||||||
|   following: "フォロー" |   following: "フォロー" | ||||||
|   | |||||||
| @@ -411,6 +411,7 @@ desktop: | |||||||
|   uploading-avatar: "新しいアバターをアップロードしています" |   uploading-avatar: "新しいアバターをアップロードしています" | ||||||
|   avatar-updated: "アバターを更新しました" |   avatar-updated: "アバターを更新しました" | ||||||
|   choose-avatar: "アバターにする画像を選択" |   choose-avatar: "アバターにする画像を選択" | ||||||
|  |   invalid-filetype: "この形式のファイルはサポートされていません" | ||||||
| desktop/views/components/activity.chart.vue: | desktop/views/components/activity.chart.vue: | ||||||
|   total: "Black ... Total" |   total: "Black ... Total" | ||||||
|   notes: "Blue ... Notes" |   notes: "Blue ... Notes" | ||||||
| @@ -649,6 +650,7 @@ desktop/views/components/settings.vue: | |||||||
|   gradient-window-header: "ウィンドウのタイトルバーにグラデーションを使用" |   gradient-window-header: "ウィンドウのタイトルバーにグラデーションを使用" | ||||||
|   post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" |   post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" | ||||||
|   suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する" |   suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する" | ||||||
|  |   show-clock-on-header: "右上に時計を表示する" | ||||||
|   show-reply-target: "リプライ先を表示する" |   show-reply-target: "リプライ先を表示する" | ||||||
|   show-my-renotes: "自分の行ったRenoteをタイムラインに表示する" |   show-my-renotes: "自分の行ったRenoteをタイムラインに表示する" | ||||||
|   show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する" |   show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する" | ||||||
| @@ -819,8 +821,8 @@ desktop/views/pages/admin/admin.dashboard.vue: | |||||||
|   dashboard: "ダッシュボード" |   dashboard: "ダッシュボード" | ||||||
|   all-users: "全てのユーザー" |   all-users: "全てのユーザー" | ||||||
|   original-users: "このインスタンスのユーザー" |   original-users: "このインスタンスのユーザー" | ||||||
|   all-notes: "全てのノート" |   all-notes: "全ての投稿" | ||||||
|   original-notes: "このインスタンスのノート" |   original-notes: "このインスタンスの投稿" | ||||||
|   invite: "招待" |   invite: "招待" | ||||||
| desktop/views/pages/admin/admin.suspend-user.vue: | desktop/views/pages/admin/admin.suspend-user.vue: | ||||||
|   suspend-user: "ユーザーの凍結" |   suspend-user: "ユーザーの凍結" | ||||||
| @@ -846,6 +848,11 @@ desktop/views/pages/deck/deck.note.vue: | |||||||
|   reposted-by: "{}がRenote" |   reposted-by: "{}がRenote" | ||||||
|   private: "この投稿は非公開です" |   private: "この投稿は非公開です" | ||||||
|   deleted: "この投稿は削除されました" |   deleted: "この投稿は削除されました" | ||||||
|  | desktop/views/pages/stats/stats.vue: | ||||||
|  |   all-users: "全てのユーザー" | ||||||
|  |   original-users: "このインスタンスのユーザー" | ||||||
|  |   all-notes: "全ての投稿" | ||||||
|  |   original-notes: "このインスタンスの投稿" | ||||||
| desktop/views/pages/welcome.vue: | desktop/views/pages/welcome.vue: | ||||||
|   about: "詳しく..." |   about: "詳しく..." | ||||||
|   gotit: "わかった" |   gotit: "わかった" | ||||||
| @@ -1170,6 +1177,8 @@ mobile/views/pages/settings.vue: | |||||||
|   update-available-desc: "ページを再度読み込みすると更新が適用されます。" |   update-available-desc: "ページを再度読み込みすると更新が適用されます。" | ||||||
|   settings: "設定" |   settings: "設定" | ||||||
|   signout: "サインアウト" |   signout: "サインアウト" | ||||||
|  |   sound: "サウンド" | ||||||
|  |   enableSounds: "サウンドを有効にする" | ||||||
| mobile/views/pages/user.vue: | mobile/views/pages/user.vue: | ||||||
|   follows-you: "フォローされています" |   follows-you: "フォローされています" | ||||||
|   following: "フォロー" |   following: "フォロー" | ||||||
|   | |||||||
| @@ -411,6 +411,7 @@ desktop: | |||||||
|   uploading-avatar: "Wysyłanie awatara" |   uploading-avatar: "Wysyłanie awatara" | ||||||
|   avatar-updated: "Wysłano awatar" |   avatar-updated: "Wysłano awatar" | ||||||
|   choose-avatar: "Wybierz awatar" |   choose-avatar: "Wybierz awatar" | ||||||
|  |   invalid-filetype: "この形式のファイルはサポートされていません" | ||||||
| desktop/views/components/activity.chart.vue: | desktop/views/components/activity.chart.vue: | ||||||
|   total: "Czarny … Łącznie" |   total: "Czarny … Łącznie" | ||||||
|   notes: "Niebieski … Wpisy" |   notes: "Niebieski … Wpisy" | ||||||
| @@ -649,6 +650,7 @@ desktop/views/components/settings.vue: | |||||||
|   gradient-window-header: "Używaj gradientów na pasku tytułu okna" |   gradient-window-header: "Używaj gradientów na pasku tytułu okna" | ||||||
|   post-form-on-timeline: "Wyświetlaj formularz tworzenia wpisu w górnej części osi czasu" |   post-form-on-timeline: "Wyświetlaj formularz tworzenia wpisu w górnej części osi czasu" | ||||||
|   suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する" |   suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する" | ||||||
|  |   show-clock-on-header: "右上に時計を表示する" | ||||||
|   show-reply-target: "Pokazuj cel odpowiedzi" |   show-reply-target: "Pokazuj cel odpowiedzi" | ||||||
|   show-my-renotes: "Pokazuj moje udostępnienia na osi czasu" |   show-my-renotes: "Pokazuj moje udostępnienia na osi czasu" | ||||||
|   show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する" |   show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する" | ||||||
| @@ -819,8 +821,8 @@ desktop/views/pages/admin/admin.dashboard.vue: | |||||||
|   dashboard: "ダッシュボード" |   dashboard: "ダッシュボード" | ||||||
|   all-users: "全てのユーザー" |   all-users: "全てのユーザー" | ||||||
|   original-users: "このインスタンスのユーザー" |   original-users: "このインスタンスのユーザー" | ||||||
|   all-notes: "全てのノート" |   all-notes: "全ての投稿" | ||||||
|   original-notes: "このインスタンスのノート" |   original-notes: "このインスタンスの投稿" | ||||||
|   invite: "招待" |   invite: "招待" | ||||||
| desktop/views/pages/admin/admin.suspend-user.vue: | desktop/views/pages/admin/admin.suspend-user.vue: | ||||||
|   suspend-user: "ユーザーの凍結" |   suspend-user: "ユーザーの凍結" | ||||||
| @@ -846,6 +848,11 @@ desktop/views/pages/deck/deck.note.vue: | |||||||
|   reposted-by: "Udostępniono przez {}" |   reposted-by: "Udostępniono przez {}" | ||||||
|   private: "ten wpis jest prywatny" |   private: "ten wpis jest prywatny" | ||||||
|   deleted: "ten wpis został usunięty" |   deleted: "ten wpis został usunięty" | ||||||
|  | desktop/views/pages/stats/stats.vue: | ||||||
|  |   all-users: "全てのユーザー" | ||||||
|  |   original-users: "このインスタンスのユーザー" | ||||||
|  |   all-notes: "全ての投稿" | ||||||
|  |   original-notes: "このインスタンスの投稿" | ||||||
| desktop/views/pages/welcome.vue: | desktop/views/pages/welcome.vue: | ||||||
|   about: "O Misskey" |   about: "O Misskey" | ||||||
|   gotit: "Rozumiem!" |   gotit: "Rozumiem!" | ||||||
| @@ -1170,6 +1177,8 @@ mobile/views/pages/settings.vue: | |||||||
|   update-available-desc: "Odśwież stronę, aby zastosować aktualizację." |   update-available-desc: "Odśwież stronę, aby zastosować aktualizację." | ||||||
|   settings: "Ustawienia" |   settings: "Ustawienia" | ||||||
|   signout: "Wyloguj" |   signout: "Wyloguj" | ||||||
|  |   sound: "サウンド" | ||||||
|  |   enableSounds: "サウンドを有効にする" | ||||||
| mobile/views/pages/user.vue: | mobile/views/pages/user.vue: | ||||||
|   follows-you: "Śledzi Cię" |   follows-you: "Śledzi Cię" | ||||||
|   following: "Śledzeni" |   following: "Śledzeni" | ||||||
|   | |||||||
| @@ -58,7 +58,7 @@ common: | |||||||
|     friday: "sexta" |     friday: "sexta" | ||||||
|     saturday: "sábado" |     saturday: "sábado" | ||||||
|   reactions: |   reactions: | ||||||
|     like: "いいね" |     like: "Curtir" | ||||||
|     love: "Amei" |     love: "Amei" | ||||||
|     laugh: "Riso" |     laugh: "Riso" | ||||||
|     hmm: "Hmm...?" |     hmm: "Hmm...?" | ||||||
| @@ -81,7 +81,7 @@ common: | |||||||
|   ok: "OK" |   ok: "OK" | ||||||
|   update-available-title: "Atualização disponível" |   update-available-title: "Atualização disponível" | ||||||
|   update-available: "Uma nova versão de Misskey está disponível ({newer}). A versão atual é {current}. Recarregue a página para atualizar." |   update-available: "Uma nova versão de Misskey está disponível ({newer}). A versão atual é {current}. Recarregue a página para atualizar." | ||||||
|   my-token-regenerated: "あなたのトークンが更新されたのでサインアウトします。" |   my-token-regenerated: "Seu token foi recriado, portanto você foi deslogado." | ||||||
|   i-like-sushi: "Eu prefiro sushi a pudim" |   i-like-sushi: "Eu prefiro sushi a pudim" | ||||||
|   show-reversi-board-labels: "Mostrar etiquetas de colunas e linhas no Reversi" |   show-reversi-board-labels: "Mostrar etiquetas de colunas e linhas no Reversi" | ||||||
|   use-contrast-reversi-stones: "リバーシのアイコンにコントラストを付ける" |   use-contrast-reversi-stones: "リバーシのアイコンにコントラストを付ける" | ||||||
| @@ -97,7 +97,7 @@ common: | |||||||
|     black: "Pretas" |     black: "Pretas" | ||||||
|     white: "Brancas" |     white: "Brancas" | ||||||
|     total: "Total" |     total: "Total" | ||||||
|     this-turn: "{}ターン目" |     this-turn: "Turno de {}" | ||||||
|   widgets: |   widgets: | ||||||
|     analog-clock: "Relógio analógico" |     analog-clock: "Relógio analógico" | ||||||
|     profile: "Perfil" |     profile: "Perfil" | ||||||
| @@ -106,16 +106,16 @@ common: | |||||||
|     activity: "Atividade" |     activity: "Atividade" | ||||||
|     rss: "Leitor de RSS" |     rss: "Leitor de RSS" | ||||||
|     memo: "Nota adesiva" |     memo: "Nota adesiva" | ||||||
|     trends: "トレンド" |     trends: "Tendências" | ||||||
|     photo-stream: "フォトストリーム" |     photo-stream: "フォトストリーム" | ||||||
|     posts-monitor: "投稿チャート" |     posts-monitor: "Gráfico de publicações" | ||||||
|     slideshow: "スライドショー" |     slideshow: "スライドショー" | ||||||
|     version: "Versão" |     version: "Versão" | ||||||
|     broadcast: "ブロードキャスト" |     broadcast: "ブロードキャスト" | ||||||
|     notifications: "Notificações" |     notifications: "Notificações" | ||||||
|     users: "Usuário sugeridos" |     users: "Usuário sugeridos" | ||||||
|     polls: "Enquetes" |     polls: "Enquetes" | ||||||
|     post-form: "投稿フォーム" |     post-form: "Formulário de publicação" | ||||||
|     messaging: "Mensagens" |     messaging: "Mensagens" | ||||||
|     server: "Informações do servidor" |     server: "Informações do servidor" | ||||||
|     donation: "Doações" |     donation: "Doações" | ||||||
| @@ -135,10 +135,10 @@ common: | |||||||
|     swap-up: "Mover para cima" |     swap-up: "Mover para cima" | ||||||
|     swap-down: "Mover para baixo" |     swap-down: "Mover para baixo" | ||||||
|     remove: "Remover" |     remove: "Remover" | ||||||
|     add-column: "カラムを追加" |     add-column: "Adicionar coluna" | ||||||
|     rename: "Renomear" |     rename: "Renomear" | ||||||
|     stack-left: "左に重ねる" |     stack-left: "左に重ねる" | ||||||
|     pop-right: "右に出す" |     pop-right: "Acoplar à direita" | ||||||
| auth/views/form.vue: | auth/views/form.vue: | ||||||
|   share-access: "Você <b>permite</b> que <i>{{ app.name }}</i> acesse sua conta?" |   share-access: "Você <b>permite</b> que <i>{{ app.name }}</i> acesse sua conta?" | ||||||
|   permission-ask: "Este aplicativo precisa das seguintes permissões:" |   permission-ask: "Este aplicativo precisa das seguintes permissões:" | ||||||
| @@ -151,18 +151,18 @@ auth/views/form.vue: | |||||||
|   drive-write: "ドライブを操作する。" |   drive-write: "ドライブを操作する。" | ||||||
|   notification-read: "通知を見る。" |   notification-read: "通知を見る。" | ||||||
|   notification-write: "通知を操作する。" |   notification-write: "通知を操作する。" | ||||||
|   cancel: "キャンセル" |   cancel: "Cancelar" | ||||||
|   accept: "アクセスを許可" |   accept: "Permitir acesso" | ||||||
| auth/views/index.vue: | auth/views/index.vue: | ||||||
|   loading: "読み込み中" |   loading: "Carregando" | ||||||
|   denied: "アプリケーションの連携をキャンセルしました。" |   denied: "アプリケーションの連携をキャンセルしました。" | ||||||
|   denied-paragraph: "このアプリがあなたのアカウントにアクセスすることはありません。" |   denied-paragraph: "このアプリがあなたのアカウントにアクセスすることはありません。" | ||||||
|   already-authorized: "このアプリは既に連携済みです" |   already-authorized: "Este aplicativo já foi autorizado" | ||||||
|   allowed: "アプリケーションの連携を許可しました" |   allowed: "Aplicativos com acesso autorizado" | ||||||
|   callback-url: "アプリケーションに戻っています" |   callback-url: "Voltando ao aplicativo" | ||||||
|   please-go-back: "アプリケーションに戻って、やっていってください。" |   please-go-back: "Por favor, volte ao aplicativo." | ||||||
|   error: "セッションが存在しません。" |   error: "A sessão não existe." | ||||||
|   sign-in: "サインインしてください" |   sign-in: "Por favor, entre." | ||||||
| common/views/components/games/reversi/reversi.vue: | common/views/components/games/reversi/reversi.vue: | ||||||
|   matching: |   matching: | ||||||
|     waiting-for: "{}を待っています" |     waiting-for: "{}を待っています" | ||||||
| @@ -176,17 +176,17 @@ common/views/components/games/reversi/reversi.game.vue: | |||||||
| common/views/components/games/reversi/reversi.index.vue: | common/views/components/games/reversi/reversi.index.vue: | ||||||
|   title: "Misskey Reversi" |   title: "Misskey Reversi" | ||||||
|   sub-title: "他のMisskeyユーザーとリバーシで対戦しよう" |   sub-title: "他のMisskeyユーザーとリバーシで対戦しよう" | ||||||
|   invite: "招待" |   invite: "Convidar" | ||||||
|   rule: "遊び方" |   rule: "Como jogar" | ||||||
|   rule-desc: "リバーシは、相手と交互に石をボードに置いて、相手の石を挟んで自分の色に変えてゆき、最終的に残った石が多い方が勝ちというボードゲームです。" |   rule-desc: "リバーシは、相手と交互に石をボードに置いて、相手の石を挟んで自分の色に変えてゆき、最終的に残った石が多い方が勝ちというボードゲームです。" | ||||||
|   mode-invite: "招待" |   mode-invite: "Convidar" | ||||||
|   mode-invite-desc: "指定したユーザーと対戦するモードです。" |   mode-invite-desc: "Convidar um usuário para jogar" | ||||||
|   invitations: "対局の招待があります!" |   invitations: "Você foi convidado!" | ||||||
|   my-games: "自分の対局" |   my-games: "Meu jogo" | ||||||
|   all-games: "みんなの対局" |   all-games: "Todos os jogos" | ||||||
|   enter-username: "ユーザー名を入力してください" |   enter-username: "Digite o nome de usuário." | ||||||
|   game-state: |   game-state: | ||||||
|     ended: "終了" |     ended: "Terminado" | ||||||
|     playing: "進行中" |     playing: "進行中" | ||||||
| common/views/components/games/reversi/reversi.room.vue: | common/views/components/games/reversi/reversi.room.vue: | ||||||
|   settings-of-the-game: "ゲームの設定" |   settings-of-the-game: "ゲームの設定" | ||||||
| @@ -228,11 +228,11 @@ common/views/components/connect-failed.troubleshooter.vue: | |||||||
|   no-server-desc: "お使いのPCのインターネット接続は正常ですが、Misskeyのサーバーには接続できませんでした。サーバーがダウンまたはメンテナンスしている可能性があるので、しばらくしてから再度御アクセスください。" |   no-server-desc: "お使いのPCのインターネット接続は正常ですが、Misskeyのサーバーには接続できませんでした。サーバーがダウンまたはメンテナンスしている可能性があるので、しばらくしてから再度御アクセスください。" | ||||||
|   success: "Misskeyのサーバーに接続できました" |   success: "Misskeyのサーバーに接続できました" | ||||||
|   success-desc: "正常に接続できるようです。ページを再度読み込みしてください。" |   success-desc: "正常に接続できるようです。ページを再度読み込みしてください。" | ||||||
|   flush: "キャッシュの削除" |   flush: "Limpar o cache" | ||||||
|   set-version: "バージョン指定" |   set-version: "バージョン指定" | ||||||
| common/views/components/messaging.vue: | common/views/components/messaging.vue: | ||||||
|   search-user: "ユーザーを探す" |   search-user: "ユーザーを探す" | ||||||
|   you: "あなた" |   you: "Você" | ||||||
|   no-history: "履歴はありません" |   no-history: "履歴はありません" | ||||||
| common/views/components/messaging-room.vue: | common/views/components/messaging-room.vue: | ||||||
|   empty: "このユーザーと話したことはありません" |   empty: "このユーザーと話したことはありません" | ||||||
| @@ -411,6 +411,7 @@ desktop: | |||||||
|   uploading-avatar: "新しいアバターをアップロードしています" |   uploading-avatar: "新しいアバターをアップロードしています" | ||||||
|   avatar-updated: "アバターを更新しました" |   avatar-updated: "アバターを更新しました" | ||||||
|   choose-avatar: "アバターにする画像を選択" |   choose-avatar: "アバターにする画像を選択" | ||||||
|  |   invalid-filetype: "この形式のファイルはサポートされていません" | ||||||
| desktop/views/components/activity.chart.vue: | desktop/views/components/activity.chart.vue: | ||||||
|   total: "Black ... Total" |   total: "Black ... Total" | ||||||
|   notes: "Blue ... Notes" |   notes: "Blue ... Notes" | ||||||
| @@ -649,6 +650,7 @@ desktop/views/components/settings.vue: | |||||||
|   gradient-window-header: "ウィンドウのタイトルバーにグラデーションを使用" |   gradient-window-header: "ウィンドウのタイトルバーにグラデーションを使用" | ||||||
|   post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" |   post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" | ||||||
|   suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する" |   suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する" | ||||||
|  |   show-clock-on-header: "右上に時計を表示する" | ||||||
|   show-reply-target: "リプライ先を表示する" |   show-reply-target: "リプライ先を表示する" | ||||||
|   show-my-renotes: "自分の行ったRenoteをタイムラインに表示する" |   show-my-renotes: "自分の行ったRenoteをタイムラインに表示する" | ||||||
|   show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する" |   show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する" | ||||||
| @@ -819,8 +821,8 @@ desktop/views/pages/admin/admin.dashboard.vue: | |||||||
|   dashboard: "ダッシュボード" |   dashboard: "ダッシュボード" | ||||||
|   all-users: "Todos os usuários" |   all-users: "Todos os usuários" | ||||||
|   original-users: "このインスタンスのユーザー" |   original-users: "このインスタンスのユーザー" | ||||||
|   all-notes: "Todas as notas" |   all-notes: "全ての投稿" | ||||||
|   original-notes: "このインスタンスのノート" |   original-notes: "このインスタンスの投稿" | ||||||
|   invite: "招待" |   invite: "招待" | ||||||
| desktop/views/pages/admin/admin.suspend-user.vue: | desktop/views/pages/admin/admin.suspend-user.vue: | ||||||
|   suspend-user: "ユーザーの凍結" |   suspend-user: "ユーザーの凍結" | ||||||
| @@ -846,6 +848,11 @@ desktop/views/pages/deck/deck.note.vue: | |||||||
|   reposted-by: "{}がRenote" |   reposted-by: "{}がRenote" | ||||||
|   private: "この投稿は非公開です" |   private: "この投稿は非公開です" | ||||||
|   deleted: "この投稿は削除されました" |   deleted: "この投稿は削除されました" | ||||||
|  | desktop/views/pages/stats/stats.vue: | ||||||
|  |   all-users: "全てのユーザー" | ||||||
|  |   original-users: "このインスタンスのユーザー" | ||||||
|  |   all-notes: "全ての投稿" | ||||||
|  |   original-notes: "このインスタンスの投稿" | ||||||
| desktop/views/pages/welcome.vue: | desktop/views/pages/welcome.vue: | ||||||
|   about: "詳しく..." |   about: "詳しく..." | ||||||
|   gotit: "わかった" |   gotit: "わかった" | ||||||
| @@ -1170,6 +1177,8 @@ mobile/views/pages/settings.vue: | |||||||
|   update-available-desc: "ページを再度読み込みすると更新が適用されます。" |   update-available-desc: "ページを再度読み込みすると更新が適用されます。" | ||||||
|   settings: "設定" |   settings: "設定" | ||||||
|   signout: "サインアウト" |   signout: "サインアウト" | ||||||
|  |   sound: "サウンド" | ||||||
|  |   enableSounds: "サウンドを有効にする" | ||||||
| mobile/views/pages/user.vue: | mobile/views/pages/user.vue: | ||||||
|   follows-you: "フォローされています" |   follows-you: "フォローされています" | ||||||
|   following: "フォロー" |   following: "フォロー" | ||||||
|   | |||||||
| @@ -411,6 +411,7 @@ desktop: | |||||||
|   uploading-avatar: "新しいアバターをアップロードしています" |   uploading-avatar: "新しいアバターをアップロードしています" | ||||||
|   avatar-updated: "アバターを更新しました" |   avatar-updated: "アバターを更新しました" | ||||||
|   choose-avatar: "アバターにする画像を選択" |   choose-avatar: "アバターにする画像を選択" | ||||||
|  |   invalid-filetype: "この形式のファイルはサポートされていません" | ||||||
| desktop/views/components/activity.chart.vue: | desktop/views/components/activity.chart.vue: | ||||||
|   total: "Black ... Total" |   total: "Black ... Total" | ||||||
|   notes: "Blue ... Notes" |   notes: "Blue ... Notes" | ||||||
| @@ -649,6 +650,7 @@ desktop/views/components/settings.vue: | |||||||
|   gradient-window-header: "ウィンドウのタイトルバーにグラデーションを使用" |   gradient-window-header: "ウィンドウのタイトルバーにグラデーションを使用" | ||||||
|   post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" |   post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" | ||||||
|   suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する" |   suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する" | ||||||
|  |   show-clock-on-header: "右上に時計を表示する" | ||||||
|   show-reply-target: "リプライ先を表示する" |   show-reply-target: "リプライ先を表示する" | ||||||
|   show-my-renotes: "自分の行ったRenoteをタイムラインに表示する" |   show-my-renotes: "自分の行ったRenoteをタイムラインに表示する" | ||||||
|   show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する" |   show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する" | ||||||
| @@ -819,8 +821,8 @@ desktop/views/pages/admin/admin.dashboard.vue: | |||||||
|   dashboard: "ダッシュボード" |   dashboard: "ダッシュボード" | ||||||
|   all-users: "全てのユーザー" |   all-users: "全てのユーザー" | ||||||
|   original-users: "このインスタンスのユーザー" |   original-users: "このインスタンスのユーザー" | ||||||
|   all-notes: "全てのノート" |   all-notes: "全ての投稿" | ||||||
|   original-notes: "このインスタンスのノート" |   original-notes: "このインスタンスの投稿" | ||||||
|   invite: "招待" |   invite: "招待" | ||||||
| desktop/views/pages/admin/admin.suspend-user.vue: | desktop/views/pages/admin/admin.suspend-user.vue: | ||||||
|   suspend-user: "ユーザーの凍結" |   suspend-user: "ユーザーの凍結" | ||||||
| @@ -846,6 +848,11 @@ desktop/views/pages/deck/deck.note.vue: | |||||||
|   reposted-by: "{}がRenote" |   reposted-by: "{}がRenote" | ||||||
|   private: "この投稿は非公開です" |   private: "この投稿は非公開です" | ||||||
|   deleted: "この投稿は削除されました" |   deleted: "この投稿は削除されました" | ||||||
|  | desktop/views/pages/stats/stats.vue: | ||||||
|  |   all-users: "全てのユーザー" | ||||||
|  |   original-users: "このインスタンスのユーザー" | ||||||
|  |   all-notes: "全ての投稿" | ||||||
|  |   original-notes: "このインスタンスの投稿" | ||||||
| desktop/views/pages/welcome.vue: | desktop/views/pages/welcome.vue: | ||||||
|   about: "詳しく..." |   about: "詳しく..." | ||||||
|   gotit: "わかった" |   gotit: "わかった" | ||||||
| @@ -1170,6 +1177,8 @@ mobile/views/pages/settings.vue: | |||||||
|   update-available-desc: "ページを再度読み込みすると更新が適用されます。" |   update-available-desc: "ページを再度読み込みすると更新が適用されます。" | ||||||
|   settings: "設定" |   settings: "設定" | ||||||
|   signout: "サインアウト" |   signout: "サインアウト" | ||||||
|  |   sound: "サウンド" | ||||||
|  |   enableSounds: "サウンドを有効にする" | ||||||
| mobile/views/pages/user.vue: | mobile/views/pages/user.vue: | ||||||
|   follows-you: "フォローされています" |   follows-you: "フォローされています" | ||||||
|   following: "フォロー" |   following: "フォロー" | ||||||
|   | |||||||
| @@ -411,6 +411,7 @@ desktop: | |||||||
|   uploading-avatar: "新しいアバターをアップロードしています" |   uploading-avatar: "新しいアバターをアップロードしています" | ||||||
|   avatar-updated: "アバターを更新しました" |   avatar-updated: "アバターを更新しました" | ||||||
|   choose-avatar: "アバターにする画像を選択" |   choose-avatar: "アバターにする画像を選択" | ||||||
|  |   invalid-filetype: "この形式のファイルはサポートされていません" | ||||||
| desktop/views/components/activity.chart.vue: | desktop/views/components/activity.chart.vue: | ||||||
|   total: "Black ... Total" |   total: "Black ... Total" | ||||||
|   notes: "Blue ... Notes" |   notes: "Blue ... Notes" | ||||||
| @@ -649,6 +650,7 @@ desktop/views/components/settings.vue: | |||||||
|   gradient-window-header: "ウィンドウのタイトルバーにグラデーションを使用" |   gradient-window-header: "ウィンドウのタイトルバーにグラデーションを使用" | ||||||
|   post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" |   post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" | ||||||
|   suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する" |   suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する" | ||||||
|  |   show-clock-on-header: "右上に時計を表示する" | ||||||
|   show-reply-target: "リプライ先を表示する" |   show-reply-target: "リプライ先を表示する" | ||||||
|   show-my-renotes: "自分の行ったRenoteをタイムラインに表示する" |   show-my-renotes: "自分の行ったRenoteをタイムラインに表示する" | ||||||
|   show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する" |   show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する" | ||||||
| @@ -819,8 +821,8 @@ desktop/views/pages/admin/admin.dashboard.vue: | |||||||
|   dashboard: "ダッシュボード" |   dashboard: "ダッシュボード" | ||||||
|   all-users: "全てのユーザー" |   all-users: "全てのユーザー" | ||||||
|   original-users: "このインスタンスのユーザー" |   original-users: "このインスタンスのユーザー" | ||||||
|   all-notes: "全てのノート" |   all-notes: "全ての投稿" | ||||||
|   original-notes: "このインスタンスのノート" |   original-notes: "このインスタンスの投稿" | ||||||
|   invite: "招待" |   invite: "招待" | ||||||
| desktop/views/pages/admin/admin.suspend-user.vue: | desktop/views/pages/admin/admin.suspend-user.vue: | ||||||
|   suspend-user: "ユーザーの凍結" |   suspend-user: "ユーザーの凍結" | ||||||
| @@ -846,6 +848,11 @@ desktop/views/pages/deck/deck.note.vue: | |||||||
|   reposted-by: "{}がRenote" |   reposted-by: "{}がRenote" | ||||||
|   private: "この投稿は非公開です" |   private: "この投稿は非公開です" | ||||||
|   deleted: "この投稿は削除されました" |   deleted: "この投稿は削除されました" | ||||||
|  | desktop/views/pages/stats/stats.vue: | ||||||
|  |   all-users: "全てのユーザー" | ||||||
|  |   original-users: "このインスタンスのユーザー" | ||||||
|  |   all-notes: "全ての投稿" | ||||||
|  |   original-notes: "このインスタンスの投稿" | ||||||
| desktop/views/pages/welcome.vue: | desktop/views/pages/welcome.vue: | ||||||
|   about: "詳しく..." |   about: "詳しく..." | ||||||
|   gotit: "わかった" |   gotit: "わかった" | ||||||
| @@ -1170,6 +1177,8 @@ mobile/views/pages/settings.vue: | |||||||
|   update-available-desc: "ページを再度読み込みすると更新が適用されます。" |   update-available-desc: "ページを再度読み込みすると更新が適用されます。" | ||||||
|   settings: "設定" |   settings: "設定" | ||||||
|   signout: "サインアウト" |   signout: "サインアウト" | ||||||
|  |   sound: "サウンド" | ||||||
|  |   enableSounds: "サウンドを有効にする" | ||||||
| mobile/views/pages/user.vue: | mobile/views/pages/user.vue: | ||||||
|   follows-you: "フォローされています" |   follows-you: "フォローされています" | ||||||
|   following: "フォロー" |   following: "フォロー" | ||||||
|   | |||||||
							
								
								
									
										25
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										25
									
								
								package.json
									
									
									
									
									
								
							| @@ -1,8 +1,8 @@ | |||||||
| { | { | ||||||
| 	"name": "misskey", | 	"name": "misskey", | ||||||
| 	"author": "syuilo <i@syuilo.com>", | 	"author": "syuilo <i@syuilo.com>", | ||||||
| 	"version": "8.14.0", | 	"version": "8.17.0", | ||||||
| 	"clientVersion": "1.0.9022", | 	"clientVersion": "1.0.9212", | ||||||
| 	"codename": "nighthike", | 	"codename": "nighthike", | ||||||
| 	"main": "./built/index.js", | 	"main": "./built/index.js", | ||||||
| 	"private": true, | 	"private": true, | ||||||
| @@ -32,7 +32,7 @@ | |||||||
| 		"@types/debug": "0.0.30", | 		"@types/debug": "0.0.30", | ||||||
| 		"@types/deep-equal": "1.0.1", | 		"@types/deep-equal": "1.0.1", | ||||||
| 		"@types/double-ended-queue": "2.1.0", | 		"@types/double-ended-queue": "2.1.0", | ||||||
| 		"@types/elasticsearch": "5.0.25", | 		"@types/elasticsearch": "5.0.26", | ||||||
| 		"@types/file-type": "5.2.1", | 		"@types/file-type": "5.2.1", | ||||||
| 		"@types/gulp": "3.8.36", | 		"@types/gulp": "3.8.36", | ||||||
| 		"@types/gulp-htmlmin": "1.3.32", | 		"@types/gulp-htmlmin": "1.3.32", | ||||||
| @@ -60,7 +60,7 @@ | |||||||
| 		"@types/mocha": "5.2.3", | 		"@types/mocha": "5.2.3", | ||||||
| 		"@types/mongodb": "3.1.4", | 		"@types/mongodb": "3.1.4", | ||||||
| 		"@types/ms": "0.7.30", | 		"@types/ms": "0.7.30", | ||||||
| 		"@types/node": "10.9.2", | 		"@types/node": "10.9.4", | ||||||
| 		"@types/portscanner": "2.1.0", | 		"@types/portscanner": "2.1.0", | ||||||
| 		"@types/pug": "2.0.4", | 		"@types/pug": "2.0.4", | ||||||
| 		"@types/qrcode": "1.2.0", | 		"@types/qrcode": "1.2.0", | ||||||
| @@ -76,10 +76,10 @@ | |||||||
| 		"@types/speakeasy": "2.0.2", | 		"@types/speakeasy": "2.0.2", | ||||||
| 		"@types/systeminformation": "3.23.0", | 		"@types/systeminformation": "3.23.0", | ||||||
| 		"@types/tmp": "0.0.33", | 		"@types/tmp": "0.0.33", | ||||||
| 		"@types/uuid": "3.4.3", | 		"@types/uuid": "3.4.4", | ||||||
| 		"@types/webpack": "4.4.11", | 		"@types/webpack": "4.4.11", | ||||||
| 		"@types/webpack-stream": "3.2.10", | 		"@types/webpack-stream": "3.2.10", | ||||||
| 		"@types/websocket": "0.0.39", | 		"@types/websocket": "0.0.40", | ||||||
| 		"@types/ws": "6.0.0", | 		"@types/ws": "6.0.0", | ||||||
| 		"animejs": "2.2.0", | 		"animejs": "2.2.0", | ||||||
| 		"autosize": "4.0.2", | 		"autosize": "4.0.2", | ||||||
| @@ -158,7 +158,7 @@ | |||||||
| 		"mongodb": "3.1.1", | 		"mongodb": "3.1.1", | ||||||
| 		"monk": "6.0.6", | 		"monk": "6.0.6", | ||||||
| 		"ms": "2.1.1", | 		"ms": "2.1.1", | ||||||
| 		"nan": "2.10.0", | 		"nan": "2.11.0", | ||||||
| 		"nested-property": "0.0.7", | 		"nested-property": "0.0.7", | ||||||
| 		"node-sass": "4.9.3", | 		"node-sass": "4.9.3", | ||||||
| 		"node-sass-json-importer": "3.3.1", | 		"node-sass-json-importer": "3.3.1", | ||||||
| @@ -190,11 +190,11 @@ | |||||||
| 		"single-line-log": "1.1.2", | 		"single-line-log": "1.1.2", | ||||||
| 		"speakeasy": "2.0.0", | 		"speakeasy": "2.0.0", | ||||||
| 		"stringz": "1.0.0", | 		"stringz": "1.0.0", | ||||||
| 		"style-loader": "0.22.1", | 		"style-loader": "0.23.0", | ||||||
| 		"stylus": "0.54.5", | 		"stylus": "0.54.5", | ||||||
| 		"stylus-loader": "3.0.2", | 		"stylus-loader": "3.0.2", | ||||||
| 		"summaly": "2.1.4", | 		"summaly": "2.2.0", | ||||||
| 		"systeminformation": "3.43.0", | 		"systeminformation": "3.44.2", | ||||||
| 		"syuilo-password-strength": "0.0.1", | 		"syuilo-password-strength": "0.0.1", | ||||||
| 		"textarea-caret": "3.1.0", | 		"textarea-caret": "3.1.0", | ||||||
| 		"tmp": "0.0.33", | 		"tmp": "0.0.33", | ||||||
| @@ -210,12 +210,13 @@ | |||||||
| 		"vue": "2.5.17", | 		"vue": "2.5.17", | ||||||
| 		"vue-chartjs": "3.4.0", | 		"vue-chartjs": "3.4.0", | ||||||
| 		"vue-cropperjs": "2.2.1", | 		"vue-cropperjs": "2.2.1", | ||||||
| 		"vue-js-modal": "1.3.19", | 		"vue-js-modal": "1.3.24", | ||||||
| 		"vue-json-tree-view": "2.1.4", | 		"vue-json-tree-view": "2.1.4", | ||||||
| 		"vue-loader": "15.4.0", | 		"vue-loader": "15.4.1", | ||||||
| 		"vue-router": "3.0.1", | 		"vue-router": "3.0.1", | ||||||
| 		"vue-style-loader": "4.1.2", | 		"vue-style-loader": "4.1.2", | ||||||
| 		"vue-template-compiler": "2.5.17", | 		"vue-template-compiler": "2.5.17", | ||||||
|  | 		"vue-thin-modal": "1.1.1", | ||||||
| 		"vuedraggable": "2.16.0", | 		"vuedraggable": "2.16.0", | ||||||
| 		"vuex": "3.0.1", | 		"vuex": "3.0.1", | ||||||
| 		"vuex-persistedstate": "2.5.4", | 		"vuex-persistedstate": "2.5.4", | ||||||
|   | |||||||
| @@ -1,3 +1,6 @@ | |||||||
| <template> | <template> | ||||||
| <router-view id="app"></router-view> | <div> | ||||||
|  | 	<router-view id="app"></router-view> | ||||||
|  | 	<modal-portal/> | ||||||
|  | </div> | ||||||
| </template> | </template> | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ | |||||||
| 	@dragover.prevent.stop="onDragover" | 	@dragover.prevent.stop="onDragover" | ||||||
| 	@drop.prevent.stop="onDrop" | 	@drop.prevent.stop="onDrop" | ||||||
| > | > | ||||||
| 	<div class="stream"> | 	<div class="body"> | ||||||
| 		<p class="init" v-if="init">%fa:spinner .spin%%i18n:common.loading%</p> | 		<p class="init" v-if="init">%fa:spinner .spin%%i18n:common.loading%</p> | ||||||
| 		<p class="empty" v-if="!init && messages.length == 0">%fa:info-circle%%i18n:@empty%</p> | 		<p class="empty" v-if="!init && messages.length == 0">%fa:info-circle%%i18n:@empty%</p> | ||||||
| 		<p class="no-history" v-if="!init && messages.length > 0 && !existMoreMessages">%fa:flag%%i18n:@no-history%</p> | 		<p class="no-history" v-if="!init && messages.length > 0 && !existMoreMessages">%fa:flag%%i18n:@no-history%</p> | ||||||
| @@ -77,6 +77,12 @@ export default Vue.extend({ | |||||||
| 		this.connection.on('message', this.onMessage); | 		this.connection.on('message', this.onMessage); | ||||||
| 		this.connection.on('read', this.onRead); | 		this.connection.on('read', this.onRead); | ||||||
|  |  | ||||||
|  | 		if (this.isNaked) { | ||||||
|  | 			window.addEventListener('scroll', this.onScroll, { passive: true }); | ||||||
|  | 		} else { | ||||||
|  | 			this.$el.addEventListener('scroll', this.onScroll, { passive: true }); | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		document.addEventListener('visibilitychange', this.onVisibilitychange); | 		document.addEventListener('visibilitychange', this.onVisibilitychange); | ||||||
|  |  | ||||||
| 		this.fetchMessages().then(() => { | 		this.fetchMessages().then(() => { | ||||||
| @@ -90,6 +96,12 @@ export default Vue.extend({ | |||||||
| 		this.connection.off('read', this.onRead); | 		this.connection.off('read', this.onRead); | ||||||
| 		this.connection.close(); | 		this.connection.close(); | ||||||
|  |  | ||||||
|  | 		if (this.isNaked) { | ||||||
|  | 			window.removeEventListener('scroll', this.onScroll); | ||||||
|  | 		} else { | ||||||
|  | 			this.$el.removeEventListener('scroll', this.onScroll); | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		document.removeEventListener('visibilitychange', this.onVisibilitychange); | 		document.removeEventListener('visibilitychange', this.onVisibilitychange); | ||||||
| 	}, | 	}, | ||||||
|  |  | ||||||
| @@ -226,6 +238,14 @@ export default Vue.extend({ | |||||||
| 			}, 4000); | 			}, 4000); | ||||||
| 		}, | 		}, | ||||||
|  |  | ||||||
|  | 		onScroll() { | ||||||
|  | 			const el = this.isNaked ? window.document.documentElement : this.$el; | ||||||
|  | 			const current = el.scrollTop + el.clientHeight; | ||||||
|  | 			if (current > el.scrollHeight - 1) { | ||||||
|  | 				this.showIndicator = false; | ||||||
|  | 			} | ||||||
|  | 		}, | ||||||
|  |  | ||||||
| 		onVisibilitychange() { | 		onVisibilitychange() { | ||||||
| 			if (document.hidden) return; | 			if (document.hidden) return; | ||||||
| 			this.messages.forEach(message => { | 			this.messages.forEach(message => { | ||||||
| @@ -251,7 +271,7 @@ root(isDark) | |||||||
| 	height 100% | 	height 100% | ||||||
| 	background isDark ? #191b22 : #fff | 	background isDark ? #191b22 : #fff | ||||||
|  |  | ||||||
| 	> .stream | 	> .body | ||||||
| 		width 100% | 		width 100% | ||||||
| 		max-width 600px | 		max-width 600px | ||||||
| 		margin 0 auto | 		margin 0 auto | ||||||
|   | |||||||
| @@ -6,17 +6,27 @@ | |||||||
|  |  | ||||||
| <script lang="ts"> | <script lang="ts"> | ||||||
| import Vue from 'vue'; | import Vue from 'vue'; | ||||||
|  | import { url } from '../../../config'; | ||||||
|  | import copyToClipboard from '../../../common/scripts/copy-to-clipboard'; | ||||||
|  |  | ||||||
| export default Vue.extend({ | export default Vue.extend({ | ||||||
| 	props: ['note', 'source', 'compact'], | 	props: ['note', 'source', 'compact'], | ||||||
| 	computed: { | 	computed: { | ||||||
| 		items() { | 		items() { | ||||||
| 			const items = []; | 			const items = [{ | ||||||
| 			items.push({ | 				icon: '%fa:info-circle%', | ||||||
|  | 				text: '%i18n:@detail%', | ||||||
|  | 				action: this.detail | ||||||
|  | 			}, { | ||||||
|  | 				icon: '%fa:link%', | ||||||
|  | 				text: '%i18n:@copy-link%', | ||||||
|  | 				action: this.copyLink | ||||||
|  | 			}, null, { | ||||||
| 				icon: '%fa:star%', | 				icon: '%fa:star%', | ||||||
| 				text: '%i18n:@favorite%', | 				text: '%i18n:@favorite%', | ||||||
| 				action: this.favorite | 				action: this.favorite | ||||||
| 			}); | 			}]; | ||||||
|  |  | ||||||
| 			if (this.note.userId == this.$store.state.i.id) { | 			if (this.note.userId == this.$store.state.i.id) { | ||||||
| 				items.push({ | 				items.push({ | ||||||
| 					icon: '%fa:thumbtack%', | 					icon: '%fa:thumbtack%', | ||||||
| @@ -42,6 +52,14 @@ export default Vue.extend({ | |||||||
| 		} | 		} | ||||||
| 	}, | 	}, | ||||||
| 	methods: { | 	methods: { | ||||||
|  | 		detail() { | ||||||
|  | 			this.$router.push(`/notes/${ this.note.id }`); | ||||||
|  | 		}, | ||||||
|  |  | ||||||
|  | 		copyLink() { | ||||||
|  | 			copyToClipboard(`${url}/notes/${ this.note.id }`); | ||||||
|  | 		}, | ||||||
|  |  | ||||||
| 		pin() { | 		pin() { | ||||||
| 			(this as any).api('i/pin', { | 			(this as any).api('i/pin', { | ||||||
| 				noteId: this.note.id | 				noteId: this.note.id | ||||||
|   | |||||||
| @@ -28,69 +28,8 @@ | |||||||
| import Vue from 'vue'; | import Vue from 'vue'; | ||||||
| import { url as misskeyUrl } from '../../../config'; | import { url as misskeyUrl } from '../../../config'; | ||||||
|  |  | ||||||
| export default Vue.extend({ | // THIS IS THE WHITELIST FOR THE EMBED PLAYER | ||||||
| 	props: { | const whiteList = [ | ||||||
| 		url: { |  | ||||||
| 			type: String, |  | ||||||
| 			require: true |  | ||||||
| 		}, |  | ||||||
| 		detail: { |  | ||||||
| 			type: Boolean, |  | ||||||
| 			required: false, |  | ||||||
| 			default: false |  | ||||||
| 		} |  | ||||||
| 	}, |  | ||||||
| 	data() { |  | ||||||
| 		return { |  | ||||||
| 			fetching: true, |  | ||||||
| 			title: null, |  | ||||||
| 			description: null, |  | ||||||
| 			thumbnail: null, |  | ||||||
| 			icon: null, |  | ||||||
| 			sitename: null, |  | ||||||
| 			player: { |  | ||||||
| 				url: null, |  | ||||||
| 				width: null, |  | ||||||
| 				height: null |  | ||||||
| 			}, |  | ||||||
| 			tweetUrl: null, |  | ||||||
| 			misskeyUrl |  | ||||||
| 		}; |  | ||||||
| 	}, |  | ||||||
| 	created() { |  | ||||||
| 		const url = new URL(this.url); |  | ||||||
|  |  | ||||||
| 		if (this.detail && url.hostname == 'twitter.com' && /^\/.+\/status(es)?\/\d+/.test(url.pathname)) { |  | ||||||
| 			this.tweetUrl = url; |  | ||||||
| 			const twttr = (window as any).twttr || {}; |  | ||||||
| 			const loadTweet = () => twttr.widgets.load(this.$refs.tweet); |  | ||||||
|  |  | ||||||
| 			if (twttr.widgets) { |  | ||||||
| 				Vue.nextTick(loadTweet); |  | ||||||
| 			} else { |  | ||||||
| 				const wjsId = 'twitter-wjs'; |  | ||||||
| 				if (!document.getElementById(wjsId)) { |  | ||||||
| 					const head = document.getElementsByTagName('head')[0]; |  | ||||||
| 					const script = document.createElement('script'); |  | ||||||
| 					script.setAttribute('id', wjsId); |  | ||||||
| 					script.setAttribute('src', 'https://platform.twitter.com/widgets.js'); |  | ||||||
| 					head.appendChild(script); |  | ||||||
| 				} |  | ||||||
| 				twttr.ready = loadTweet; |  | ||||||
| 				(window as any).twttr = twttr; |  | ||||||
| 			} |  | ||||||
| 			return; |  | ||||||
| 		} |  | ||||||
| 		fetch('/url?url=' + encodeURIComponent(this.url)).then(res => { |  | ||||||
| 			res.json().then(info => { |  | ||||||
| 				if (info.url != null) { |  | ||||||
| 					this.title = info.title; |  | ||||||
| 					this.description = info.description; |  | ||||||
| 					this.thumbnail = info.thumbnail; |  | ||||||
| 					this.icon = info.icon; |  | ||||||
| 					this.sitename = info.sitename; |  | ||||||
| 					this.fetching = false; |  | ||||||
| 					if ([ // THIS IS THE WHITELIST FOR THE EMBED PLAYER |  | ||||||
| 	'afreecatv.com', | 	'afreecatv.com', | ||||||
| 	'aparat.com', | 	'aparat.com', | ||||||
| 	'applemusic.com', | 	'applemusic.com', | ||||||
| @@ -166,12 +105,80 @@ export default Vue.extend({ | |||||||
| 	'web.tv', | 	'web.tv', | ||||||
| 	'youtube.com', | 	'youtube.com', | ||||||
| 	'youtu.be' | 	'youtu.be' | ||||||
| 					].some(x => x == url.hostname || url.hostname.endsWith(`.${x}`))) | ]; | ||||||
|  |  | ||||||
|  | export default Vue.extend({ | ||||||
|  | 	props: { | ||||||
|  | 		url: { | ||||||
|  | 			type: String, | ||||||
|  | 			require: true | ||||||
|  | 		}, | ||||||
|  |  | ||||||
|  | 		detail: { | ||||||
|  | 			type: Boolean, | ||||||
|  | 			required: false, | ||||||
|  | 			default: false | ||||||
|  | 		} | ||||||
|  | 	}, | ||||||
|  |  | ||||||
|  | 	data() { | ||||||
|  | 		return { | ||||||
|  | 			fetching: true, | ||||||
|  | 			title: null, | ||||||
|  | 			description: null, | ||||||
|  | 			thumbnail: null, | ||||||
|  | 			icon: null, | ||||||
|  | 			sitename: null, | ||||||
|  | 			player: { | ||||||
|  | 				url: null, | ||||||
|  | 				width: null, | ||||||
|  | 				height: null | ||||||
|  | 			}, | ||||||
|  | 			tweetUrl: null, | ||||||
|  | 			misskeyUrl | ||||||
|  | 		}; | ||||||
|  | 	}, | ||||||
|  |  | ||||||
|  | 	created() { | ||||||
|  | 		const url = new URL(this.url); | ||||||
|  |  | ||||||
|  | 		if (this.detail && url.hostname == 'twitter.com' && /^\/.+\/status(es)?\/\d+/.test(url.pathname)) { | ||||||
|  | 			this.tweetUrl = url; | ||||||
|  | 			const twttr = (window as any).twttr || {}; | ||||||
|  | 			const loadTweet = () => twttr.widgets.load(this.$refs.tweet); | ||||||
|  |  | ||||||
|  | 			if (twttr.widgets) { | ||||||
|  | 				Vue.nextTick(loadTweet); | ||||||
|  | 			} else { | ||||||
|  | 				const wjsId = 'twitter-wjs'; | ||||||
|  | 				if (!document.getElementById(wjsId)) { | ||||||
|  | 					const head = document.getElementsByTagName('head')[0]; | ||||||
|  | 					const script = document.createElement('script'); | ||||||
|  | 					script.setAttribute('id', wjsId); | ||||||
|  | 					script.setAttribute('src', 'https://platform.twitter.com/widgets.js'); | ||||||
|  | 					head.appendChild(script); | ||||||
|  | 				} | ||||||
|  | 				twttr.ready = loadTweet; | ||||||
|  | 				(window as any).twttr = twttr; | ||||||
|  | 			} | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		fetch('/url?url=' + encodeURIComponent(this.url)).then(res => { | ||||||
|  | 			res.json().then(info => { | ||||||
|  | 				if (info.url == null) return; | ||||||
|  | 				this.title = info.title; | ||||||
|  | 				this.description = info.description; | ||||||
|  | 				this.thumbnail = info.thumbnail; | ||||||
|  | 				this.icon = info.icon; | ||||||
|  | 				this.sitename = info.sitename; | ||||||
|  | 				this.fetching = false; | ||||||
|  | 				if (whiteList.some(x => x == url.hostname || url.hostname.endsWith(`.${x}`))) { | ||||||
| 					this.player = info.player; | 					this.player = info.player; | ||||||
| 				}	// info.url | 				} | ||||||
| 			})	// json | 			}) | ||||||
| 		});	// fetch | 		}); | ||||||
| 	}	// created | 	} | ||||||
| }); | }); | ||||||
| </script> | </script> | ||||||
|  |  | ||||||
|   | |||||||
| @@ -2,9 +2,9 @@ | |||||||
| <div class="mkw-donation" :data-mobile="platform == 'mobile'"> | <div class="mkw-donation" :data-mobile="platform == 'mobile'"> | ||||||
| 	<article> | 	<article> | ||||||
| 		<h1>%fa:heart%%i18n:@title%</h1> | 		<h1>%fa:heart%%i18n:@title%</h1> | ||||||
| 		<p> | 		<p v-if="meta"> | ||||||
| 			{{ '%i18n:@text%'.substr(0, '%i18n:@text%'.indexOf('{')) }} | 			{{ '%i18n:@text%'.substr(0, '%i18n:@text%'.indexOf('{')) }} | ||||||
| 			<a href="https://syuilo.com">@syuilo</a> | 			<a :href="meta.maintainer.url">{{ meta.maintainer.name }}</a> | ||||||
| 			{{ '%i18n:@text%'.substr('%i18n:@text%'.indexOf('}') + 1) }} | 			{{ '%i18n:@text%'.substr('%i18n:@text%'.indexOf('}') + 1) }} | ||||||
| 		</p> | 		</p> | ||||||
| 	</article> | 	</article> | ||||||
| @@ -15,6 +15,17 @@ | |||||||
| import define from '../../../common/define-widget'; | import define from '../../../common/define-widget'; | ||||||
| export default define({ | export default define({ | ||||||
| 	name: 'donation' | 	name: 'donation' | ||||||
|  | }).extend({ | ||||||
|  | 	data() { | ||||||
|  | 		return { | ||||||
|  | 			meta: null | ||||||
|  | 		}; | ||||||
|  | 	}, | ||||||
|  | 	created() { | ||||||
|  | 		(this as any).os.getMeta().then(meta => { | ||||||
|  | 			this.meta = meta; | ||||||
|  | 		}); | ||||||
|  | 	} | ||||||
| }); | }); | ||||||
| </script> | </script> | ||||||
|  |  | ||||||
|   | |||||||
| @@ -4,6 +4,7 @@ declare const _THEME_COLOR_: string; | |||||||
| declare const _COPYRIGHT_: string; | declare const _COPYRIGHT_: string; | ||||||
| declare const _VERSION_: string; | declare const _VERSION_: string; | ||||||
| declare const _CODENAME_: string; | declare const _CODENAME_: string; | ||||||
|  | declare const _ENV_: string; | ||||||
|  |  | ||||||
| const address = new URL(location.href); | const address = new URL(location.href); | ||||||
|  |  | ||||||
| @@ -18,3 +19,4 @@ export const themeColor = _THEME_COLOR_; | |||||||
| export const copyright = _COPYRIGHT_; | export const copyright = _COPYRIGHT_; | ||||||
| export const version = _VERSION_; | export const version = _VERSION_; | ||||||
| export const codename = _CODENAME_; | export const codename = _CODENAME_; | ||||||
|  | export const env = _ENV_; | ||||||
|   | |||||||
| @@ -3,8 +3,21 @@ import { apiUrl } from '../../config'; | |||||||
| import CropWindow from '../views/components/crop-window.vue'; | import CropWindow from '../views/components/crop-window.vue'; | ||||||
| import ProgressDialog from '../views/components/progress-dialog.vue'; | import ProgressDialog from '../views/components/progress-dialog.vue'; | ||||||
|  |  | ||||||
| export default (os: OS) => (cb, file = null) => { | export default (os: OS) => { | ||||||
| 	const fileSelected = file => { |  | ||||||
|  | 	const cropImage = file => new Promise((resolve, reject) => { | ||||||
|  |  | ||||||
|  | 		const regex = RegExp('\.(jpg|jpeg|png|gif|webp|bmp|tiff)$'); | ||||||
|  | 		if (!regex.test(file.name) ) { | ||||||
|  | 			os.apis.dialog({ | ||||||
|  | 				title: '%fa:info-circle% %i18n:desktop.invalid-filetype%', | ||||||
|  | 				text: null, | ||||||
|  | 				actions: [{ | ||||||
|  | 					text: '%i18n:common.got-it%' | ||||||
|  | 				}] | ||||||
|  | 			}); | ||||||
|  | 			return reject('invalid-filetype'); | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		const w = os.new(CropWindow, { | 		const w = os.new(CropWindow, { | ||||||
| 			image: file, | 			image: file, | ||||||
| @@ -19,27 +32,29 @@ export default (os: OS) => (cb, file = null) => { | |||||||
|  |  | ||||||
| 			os.api('drive/folders/find', { | 			os.api('drive/folders/find', { | ||||||
| 				name: '%i18n:desktop.avatar%' | 				name: '%i18n:desktop.avatar%' | ||||||
| 			}).then(iconFolder => { | 			}).then(avatarFolder => { | ||||||
| 				if (iconFolder.length === 0) { | 				if (avatarFolder.length === 0) { | ||||||
| 					os.api('drive/folders/create', { | 					os.api('drive/folders/create', { | ||||||
| 						name: '%i18n:desktop.avatar%' | 						name: '%i18n:desktop.avatar%' | ||||||
| 					}).then(iconFolder => { | 					}).then(iconFolder => { | ||||||
| 						upload(data, iconFolder); | 						resolve(upload(data, iconFolder)); | ||||||
| 					}); | 					}); | ||||||
| 				} else { | 				} else { | ||||||
| 					upload(data, iconFolder[0]); | 					resolve(upload(data, avatarFolder[0])); | ||||||
| 				} | 				} | ||||||
| 			}); | 			}); | ||||||
| 		}); | 		}); | ||||||
|  |  | ||||||
| 		w.$once('skipped', () => { | 		w.$once('skipped', () => { | ||||||
| 			set(file); | 			resolve(file); | ||||||
| 		}); | 		}); | ||||||
|  |  | ||||||
| 		document.body.appendChild(w.$el); | 		w.$once('cancelled', reject); | ||||||
| 	}; |  | ||||||
|  |  | ||||||
| 	const upload = (data, folder) => { | 		document.body.appendChild(w.$el); | ||||||
|  | 	}); | ||||||
|  |  | ||||||
|  | 	const upload = (data, folder) => new Promise((resolve, reject) => { | ||||||
| 		const dialog = os.new(ProgressDialog, { | 		const dialog = os.new(ProgressDialog, { | ||||||
| 			title: '%i18n:desktop.uploading-avatar%' | 			title: '%i18n:desktop.uploading-avatar%' | ||||||
| 		}); | 		}); | ||||||
| @@ -52,18 +67,19 @@ export default (os: OS) => (cb, file = null) => { | |||||||
| 		xhr.onload = e => { | 		xhr.onload = e => { | ||||||
| 			const file = JSON.parse((e.target as any).response); | 			const file = JSON.parse((e.target as any).response); | ||||||
| 			(dialog as any).close(); | 			(dialog as any).close(); | ||||||
| 			set(file); | 			resolve(file); | ||||||
| 		}; | 		}; | ||||||
|  | 		xhr.onerror = reject; | ||||||
|  |  | ||||||
| 		xhr.upload.onprogress = e => { | 		xhr.upload.onprogress = e => { | ||||||
| 			if (e.lengthComputable) (dialog as any).update(e.loaded, e.total); | 			if (e.lengthComputable) (dialog as any).update(e.loaded, e.total); | ||||||
| 		}; | 		}; | ||||||
|  |  | ||||||
| 		xhr.send(data); | 		xhr.send(data); | ||||||
| 	}; | 	}); | ||||||
|  |  | ||||||
| 	const set = file => { | 	const setAvatar = file => { | ||||||
| 		os.api('i/update', { | 		return os.api('i/update', { | ||||||
| 			avatarId: file.id | 			avatarId: file.id | ||||||
| 		}).then(i => { | 		}).then(i => { | ||||||
| 			os.store.commit('updateIKeyValue', { | 			os.store.commit('updateIKeyValue', { | ||||||
| @@ -83,18 +99,21 @@ export default (os: OS) => (cb, file = null) => { | |||||||
| 				}] | 				}] | ||||||
| 			}); | 			}); | ||||||
|  |  | ||||||
| 			if (cb) cb(i); | 			return i; | ||||||
| 		}); | 		}); | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| 	if (file) { | 	return (file = null) => { | ||||||
| 		fileSelected(file); | 		const selectedFile = file | ||||||
| 	} else { | 			? Promise.resolve(file) | ||||||
| 		os.apis.chooseDriveFile({ | 			: os.apis.chooseDriveFile({ | ||||||
| 				multiple: false, | 				multiple: false, | ||||||
| 				title: '%fa:image% %i18n:desktop.choose-avatar%' | 				title: '%fa:image% %i18n:desktop.choose-avatar%' | ||||||
| 		}).then(file => { |  | ||||||
| 			fileSelected(file); |  | ||||||
| 			}); | 			}); | ||||||
| 	} |  | ||||||
|  | 		return selectedFile | ||||||
|  | 			.then(cropImage) | ||||||
|  | 			.then(setAvatar) | ||||||
|  | 			.catch(err => err && console.warn(err)); | ||||||
|  | 	}; | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -6,6 +6,19 @@ import ProgressDialog from '../views/components/progress-dialog.vue'; | |||||||
| export default (os: OS) => { | export default (os: OS) => { | ||||||
|  |  | ||||||
| 	const cropImage = file => new Promise((resolve, reject) => { | 	const cropImage = file => new Promise((resolve, reject) => { | ||||||
|  |  | ||||||
|  | 		const regex = RegExp('\.(jpg|jpeg|png|gif|webp|bmp|tiff)$'); | ||||||
|  | 		if (!regex.test(file.name) ) { | ||||||
|  | 			os.apis.dialog({ | ||||||
|  | 				title: '%fa:info-circle% %i18n:desktop.invalid-filetype%', | ||||||
|  | 				text: null, | ||||||
|  | 				actions: [{ | ||||||
|  | 					text: '%i18n:common.got-it%' | ||||||
|  | 				}] | ||||||
|  | 			}); | ||||||
|  | 			return reject('invalid-filetype'); | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		const w = os.new(CropWindow, { | 		const w = os.new(CropWindow, { | ||||||
| 			image: file, | 			image: file, | ||||||
| 			title: '%i18n:desktop.banner-crop-title%', | 			title: '%i18n:desktop.banner-crop-title%', | ||||||
|   | |||||||
| @@ -88,7 +88,9 @@ export default Vue.extend({ | |||||||
| 	}, | 	}, | ||||||
|  |  | ||||||
| 	created() { | 	created() { | ||||||
| 		(this as any).api('chart').then(chart => { | 		(this as any).api('chart', { | ||||||
|  | 			limit: 32 | ||||||
|  | 		}).then(chart => { | ||||||
| 			this.chart = chart; | 			this.chart = chart; | ||||||
| 		}); | 		}); | ||||||
| 	}, | 	}, | ||||||
| @@ -580,6 +582,6 @@ export default Vue.extend({ | |||||||
| 	> div | 	> div | ||||||
| 		> * | 		> * | ||||||
| 			display block | 			display block | ||||||
| 			height 300px | 			height 320px | ||||||
|  |  | ||||||
| </style> | </style> | ||||||
|   | |||||||
| @@ -47,7 +47,7 @@ | |||||||
| 			</div> | 			</div> | ||||||
| 			<mk-poll v-if="p.poll" :note="p"/> | 			<mk-poll v-if="p.poll" :note="p"/> | ||||||
| 			<mk-url-preview v-for="url in urls" :url="url" :key="url" :detail="true"/> | 			<mk-url-preview v-for="url in urls" :url="url" :key="url" :detail="true"/> | ||||||
| 			<a class="location" v-if="p.geo" :href="`http://maps.google.com/maps?q=${p.geo.coordinates[1]},${p.geo.coordinates[0]}`" target="_blank">%fa:map-marker-alt% %i18n:@location%</a> | 			<a class="location" v-if="p.geo" :href="`https://maps.google.com/maps?q=${p.geo.coordinates[1]},${p.geo.coordinates[0]}`" target="_blank">%fa:map-marker-alt% %i18n:@location%</a> | ||||||
| 			<div class="map" v-if="p.geo" ref="map"></div> | 			<div class="map" v-if="p.geo" ref="map"></div> | ||||||
| 			<div class="renote" v-if="p.renote"> | 			<div class="renote" v-if="p.renote"> | ||||||
| 				<mk-note-preview :note="p.renote"/> | 				<mk-note-preview :note="p.renote"/> | ||||||
|   | |||||||
| @@ -32,7 +32,7 @@ | |||||||
| 						<mk-media-list :media-list="p.media"/> | 						<mk-media-list :media-list="p.media"/> | ||||||
| 					</div> | 					</div> | ||||||
| 					<mk-poll v-if="p.poll" :note="p" ref="pollViewer"/> | 					<mk-poll v-if="p.poll" :note="p" ref="pollViewer"/> | ||||||
| 					<a class="location" v-if="p.geo" :href="`http://maps.google.com/maps?q=${p.geo.coordinates[1]},${p.geo.coordinates[0]}`" target="_blank">%fa:map-marker-alt% 位置情報</a> | 					<a class="location" v-if="p.geo" :href="`https://maps.google.com/maps?q=${p.geo.coordinates[1]},${p.geo.coordinates[0]}`" target="_blank">%fa:map-marker-alt% 位置情報</a> | ||||||
| 					<div class="map" v-if="p.geo" ref="map"></div> | 					<div class="map" v-if="p.geo" ref="map"></div> | ||||||
| 					<div class="renote" v-if="p.renote"> | 					<div class="renote" v-if="p.renote"> | ||||||
| 						<mk-note-preview :note="p.renote"/> | 						<mk-note-preview :note="p.renote"/> | ||||||
|   | |||||||
| @@ -11,7 +11,7 @@ | |||||||
| 			<li class="deck" :class="{ active: $route.name == 'deck' }" @click="goToTop"> | 			<li class="deck" :class="{ active: $route.name == 'deck' }" @click="goToTop"> | ||||||
| 				<router-link to="/deck"> | 				<router-link to="/deck"> | ||||||
| 					%fa:columns% | 					%fa:columns% | ||||||
| 					<p>%i18n:@deck% <small>(beta)</small></p> | 					<p>%i18n:@deck%</p> | ||||||
| 				</router-link> | 				</router-link> | ||||||
| 			</li> | 			</li> | ||||||
| 			<li class="messaging"> | 			<li class="messaging"> | ||||||
|   | |||||||
| @@ -1,5 +1,6 @@ | |||||||
| <template> | <template> | ||||||
| <div class="header"> | <div class="header"> | ||||||
|  | 	<p class="warn" v-if="env != 'production'">%i18n:common.do-not-use-in-production%</p> | ||||||
| 	<mk-special-message/> | 	<mk-special-message/> | ||||||
| 	<div class="main" ref="main"> | 	<div class="main" ref="main"> | ||||||
| 		<div class="backdrop"></div> | 		<div class="backdrop"></div> | ||||||
| @@ -28,6 +29,7 @@ | |||||||
| <script lang="ts"> | <script lang="ts"> | ||||||
| import Vue from 'vue'; | import Vue from 'vue'; | ||||||
| import * as anime from 'animejs'; | import * as anime from 'animejs'; | ||||||
|  | import { env } from '../../../config'; | ||||||
|  |  | ||||||
| import XNav from './ui.header.nav.vue'; | import XNav from './ui.header.nav.vue'; | ||||||
| import XSearch from './ui.header.search.vue'; | import XSearch from './ui.header.search.vue'; | ||||||
| @@ -43,7 +45,13 @@ export default Vue.extend({ | |||||||
| 		XAccount, | 		XAccount, | ||||||
| 		XNotifications, | 		XNotifications, | ||||||
| 		XPost, | 		XPost, | ||||||
| 		XClock, | 		XClock | ||||||
|  | 	}, | ||||||
|  |  | ||||||
|  | 	data() { | ||||||
|  | 		return { | ||||||
|  | 			env: env | ||||||
|  | 		}; | ||||||
| 	}, | 	}, | ||||||
|  |  | ||||||
| 	mounted() { | 	mounted() { | ||||||
| @@ -119,6 +127,15 @@ root(isDark) | |||||||
| 	width 100% | 	width 100% | ||||||
| 	box-shadow 0 1px 1px rgba(#000, 0.075) | 	box-shadow 0 1px 1px rgba(#000, 0.075) | ||||||
|  |  | ||||||
|  | 	> .warn | ||||||
|  | 		display block | ||||||
|  | 		margin 0 | ||||||
|  | 		padding 4px | ||||||
|  | 		text-align center | ||||||
|  | 		font-size 12px | ||||||
|  | 		background #f00 | ||||||
|  | 		color #fff | ||||||
|  |  | ||||||
| 	> .main | 	> .main | ||||||
| 		height 48px | 		height 48px | ||||||
|  |  | ||||||
|   | |||||||
| @@ -3,18 +3,20 @@ | |||||||
| 		@dragover.prevent.stop="onDragover" | 		@dragover.prevent.stop="onDragover" | ||||||
| 		@dragenter.prevent="onDragenter" | 		@dragenter.prevent="onDragenter" | ||||||
| 		@dragleave="onDragleave" | 		@dragleave="onDragleave" | ||||||
| 		@drop.prevent.stop="onDrop" | 		@drop.prevent.stop="onDrop"> | ||||||
| > |  | ||||||
| 	<header :class="{ indicate: count > 0 }" | 	<header :class="{ indicate: count > 0 }" | ||||||
| 			draggable="true" | 			draggable="true" | ||||||
| 			@click="toggleActive" | 			@click="goTop" | ||||||
| 			@dragstart="onDragstart" | 			@dragstart="onDragstart" | ||||||
| 			@dragend="onDragend" | 			@dragend="onDragend" | ||||||
| 			@contextmenu.prevent.stop="onContextmenu" | 			@contextmenu.prevent.stop="onContextmenu"> | ||||||
| 		> | 		<button class="toggleActive" @click="toggleActive" v-if="isStacked"> | ||||||
|  | 			<template v-if="active">%fa:angle-up%</template> | ||||||
|  | 			<template v-else>%fa:angle-down%</template> | ||||||
|  | 		</button> | ||||||
| 		<slot name="header"></slot> | 		<slot name="header"></slot> | ||||||
| 		<span class="count" v-if="count > 0">({{ count }})</span> | 		<span class="count" v-if="count > 0">({{ count }})</span> | ||||||
| 		<button ref="menu" @click.stop="showMenu">%fa:caret-down%</button> | 		<button class="menu" ref="menu" @click.stop="showMenu">%fa:caret-down%</button> | ||||||
| 	</header> | 	</header> | ||||||
| 	<div ref="body" v-show="active"> | 	<div ref="body" v-show="active"> | ||||||
| 		<slot></slot> | 		<slot></slot> | ||||||
| @@ -211,6 +213,13 @@ export default Vue.extend({ | |||||||
| 			}); | 			}); | ||||||
| 		}, | 		}, | ||||||
|  |  | ||||||
|  | 		goTop() { | ||||||
|  | 			this.$refs.body.scrollTo({ | ||||||
|  | 				top: 0, | ||||||
|  | 				behavior: 'smooth' | ||||||
|  | 			}); | ||||||
|  | 		}, | ||||||
|  |  | ||||||
| 		onDragstart(e) { | 		onDragstart(e) { | ||||||
| 			e.dataTransfer.effectAllowed = 'move'; | 			e.dataTransfer.effectAllowed = 'move'; | ||||||
| 			e.dataTransfer.setData('mk-deck-column', this.column.id); | 			e.dataTransfer.setData('mk-deck-column', this.column.id); | ||||||
| @@ -302,6 +311,7 @@ root(isDark) | |||||||
| 					color #bbb | 					color #bbb | ||||||
|  |  | ||||||
| 	> header | 	> header | ||||||
|  | 		display flex | ||||||
| 		z-index 1 | 		z-index 1 | ||||||
| 		line-height $header-height | 		line-height $header-height | ||||||
| 		padding 0 16px | 		padding 0 16px | ||||||
| @@ -328,10 +338,8 @@ root(isDark) | |||||||
| 			margin-left 4px | 			margin-left 4px | ||||||
| 			opacity 0.5 | 			opacity 0.5 | ||||||
|  |  | ||||||
| 		> button | 		> .toggleActive | ||||||
| 			position absolute | 		> .menu | ||||||
| 			top 0 |  | ||||||
| 			right 0 |  | ||||||
| 			width $header-height | 			width $header-height | ||||||
| 			line-height $header-height | 			line-height $header-height | ||||||
| 			font-size 16px | 			font-size 16px | ||||||
| @@ -343,6 +351,13 @@ root(isDark) | |||||||
| 			&:active | 			&:active | ||||||
| 				color isDark ? #b2c1d5 : #999 | 				color isDark ? #b2c1d5 : #999 | ||||||
|  |  | ||||||
|  | 		> .toggleActive | ||||||
|  | 			margin-left -16px | ||||||
|  |  | ||||||
|  | 		> .menu | ||||||
|  | 			margin-left auto | ||||||
|  | 			margin-right -16px | ||||||
|  |  | ||||||
| 	> div | 	> div | ||||||
| 		height "calc(100% - %s)" % $header-height | 		height "calc(100% - %s)" % $header-height | ||||||
| 		overflow auto | 		overflow auto | ||||||
|   | |||||||
| @@ -32,7 +32,7 @@ | |||||||
| 						<mk-media-list :media-list="p.media"/> | 						<mk-media-list :media-list="p.media"/> | ||||||
| 					</div> | 					</div> | ||||||
| 					<mk-poll v-if="p.poll" :note="p" ref="pollViewer"/> | 					<mk-poll v-if="p.poll" :note="p" ref="pollViewer"/> | ||||||
| 					<a class="location" v-if="p.geo" :href="`http://maps.google.com/maps?q=${p.geo.coordinates[1]},${p.geo.coordinates[0]}`" target="_blank">%fa:map-marker-alt% %i18n:@location%</a> | 					<a class="location" v-if="p.geo" :href="`https://maps.google.com/maps?q=${p.geo.coordinates[1]},${p.geo.coordinates[0]}`" target="_blank">%fa:map-marker-alt% %i18n:@location%</a> | ||||||
| 					<div class="renote" v-if="p.renote"> | 					<div class="renote" v-if="p.renote"> | ||||||
| 						<mk-note-preview :note="p.renote" :mini="true"/> | 						<mk-note-preview :note="p.renote" :mini="true"/> | ||||||
| 					</div> | 					</div> | ||||||
|   | |||||||
| @@ -60,5 +60,5 @@ export default Vue.extend({ | |||||||
| 				font-size 70% | 				font-size 70% | ||||||
|  |  | ||||||
| 	> div | 	> div | ||||||
| 		max-width 800px | 		max-width 850px | ||||||
| </style> | </style> | ||||||
|   | |||||||
| @@ -36,8 +36,9 @@ export default Vue.extend({ | |||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <style lang="stylus" scoped> | <style lang="stylus" scoped> | ||||||
|  | root(isDark) | ||||||
| .followers-you-know | .followers-you-know | ||||||
| 	background #fff | 	background isDark ? #282C37 : #fff | ||||||
| 	border solid 1px rgba(#000, 0.075) | 	border solid 1px rgba(#000, 0.075) | ||||||
| 	border-radius 6px | 	border-radius 6px | ||||||
|  |  | ||||||
| @@ -48,7 +49,7 @@ export default Vue.extend({ | |||||||
| 		line-height 42px | 		line-height 42px | ||||||
| 		font-size 0.9em | 		font-size 0.9em | ||||||
| 		font-weight bold | 		font-weight bold | ||||||
| 		color #888 | 		color isDark ? #e3e5e8 : #888 | ||||||
| 		box-shadow 0 1px rgba(#000, 0.07) | 		box-shadow 0 1px rgba(#000, 0.07) | ||||||
|  |  | ||||||
| 		> i | 		> i | ||||||
|   | |||||||
| @@ -40,10 +40,12 @@ export default Vue.extend({ | |||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <style lang="stylus" scoped> | <style lang="stylus" scoped> | ||||||
|  | root(isDark) | ||||||
| .friends | .friends | ||||||
| 	background #fff | 	background isDark ? #282C37 : #fff | ||||||
| 	border solid 1px rgba(#000, 0.075) | 	border solid 1px rgba(#000, 0.075) | ||||||
| 	border-radius 6px | 	border-radius 6px | ||||||
|  | 	overflow hidden | ||||||
|  |  | ||||||
| 	> .title | 	> .title | ||||||
| 		z-index 1 | 		z-index 1 | ||||||
| @@ -52,7 +54,8 @@ export default Vue.extend({ | |||||||
| 		line-height 42px | 		line-height 42px | ||||||
| 		font-size 0.9em | 		font-size 0.9em | ||||||
| 		font-weight bold | 		font-weight bold | ||||||
| 		color #888 | 		background isDark ? #313543 : inherit | ||||||
|  | 		color isDark ? #e3e5e8 : #888 | ||||||
| 		box-shadow 0 1px rgba(#000, 0.07) | 		box-shadow 0 1px rgba(#000, 0.07) | ||||||
|  |  | ||||||
| 		> i | 		> i | ||||||
| @@ -70,7 +73,7 @@ export default Vue.extend({ | |||||||
|  |  | ||||||
| 	> .user | 	> .user | ||||||
| 		padding 16px | 		padding 16px | ||||||
| 		border-bottom solid 1px #eee | 		border-bottom solid 1px isDark ? #21242f : #eee | ||||||
|  |  | ||||||
| 		&:last-child | 		&:last-child | ||||||
| 			border-bottom none | 			border-bottom none | ||||||
| @@ -96,18 +99,24 @@ export default Vue.extend({ | |||||||
| 				margin 0 | 				margin 0 | ||||||
| 				font-size 16px | 				font-size 16px | ||||||
| 				line-height 24px | 				line-height 24px | ||||||
| 				color #555 | 				color isDark ? #ccc : #555 | ||||||
|  |  | ||||||
| 			> .username | 			> .username | ||||||
| 				display block | 				display block | ||||||
| 				margin 0 | 				margin 0 | ||||||
| 				font-size 15px | 				font-size 15px | ||||||
| 				line-height 16px | 				line-height 16px | ||||||
| 				color #ccc | 				color isDark ? #555 : #ccc | ||||||
|  |  | ||||||
| 		> .mk-follow-button | 		> .mk-follow-button | ||||||
| 			position absolute | 			position absolute | ||||||
| 			top 16px | 			top 16px | ||||||
| 			right 16px | 			right 16px | ||||||
|  |  | ||||||
|  | .friends[data-darkmode] | ||||||
|  | 	root(true) | ||||||
|  |  | ||||||
|  | .friends:not([data-darkmode]) | ||||||
|  | 	root(false) | ||||||
|  |  | ||||||
| </style> | </style> | ||||||
|   | |||||||
| @@ -39,10 +39,12 @@ export default Vue.extend({ | |||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <style lang="stylus" scoped> | <style lang="stylus" scoped> | ||||||
|  | root(isDark) | ||||||
| .photos | .photos | ||||||
| 	background #fff | 	background isDark ? #282C37 : #fff | ||||||
| 	border solid 1px rgba(#000, 0.075) | 	border solid 1px rgba(#000, 0.075) | ||||||
| 	border-radius 6px | 	border-radius 6px | ||||||
|  | 	overflow hidden | ||||||
|  |  | ||||||
| 	> .title | 	> .title | ||||||
| 		z-index 1 | 		z-index 1 | ||||||
| @@ -51,7 +53,8 @@ export default Vue.extend({ | |||||||
| 		line-height 42px | 		line-height 42px | ||||||
| 		font-size 0.9em | 		font-size 0.9em | ||||||
| 		font-weight bold | 		font-weight bold | ||||||
| 		color #888 | 		background: isDark ? #313543 : inherit | ||||||
|  | 		color isDark ? #e3e5e8 : #888 | ||||||
| 		box-shadow 0 1px rgba(#000, 0.07) | 		box-shadow 0 1px rgba(#000, 0.07) | ||||||
|  |  | ||||||
| 		> i | 		> i | ||||||
| @@ -85,4 +88,10 @@ export default Vue.extend({ | |||||||
| 		> i | 		> i | ||||||
| 			margin-right 4px | 			margin-right 4px | ||||||
|  |  | ||||||
|  | .photos[data-darkmode] | ||||||
|  | 	root(true) | ||||||
|  |  | ||||||
|  | .photos:not([data-darkmode]) | ||||||
|  | 	root(false) | ||||||
|  |  | ||||||
| </style> | </style> | ||||||
|   | |||||||
| @@ -138,7 +138,7 @@ root(isDark) | |||||||
| 				padding 16px | 				padding 16px | ||||||
| 				font-size 12px | 				font-size 12px | ||||||
| 				color #aaa | 				color #aaa | ||||||
| 				background #fff | 				background isDark ? #21242f : #fff | ||||||
| 				border solid 1px rgba(#000, 0.075) | 				border solid 1px rgba(#000, 0.075) | ||||||
| 				border-radius 6px | 				border-radius 6px | ||||||
|  |  | ||||||
|   | |||||||
| @@ -11,6 +11,8 @@ import VAnimateCss from 'v-animate-css'; | |||||||
| import Element from 'element-ui'; | import Element from 'element-ui'; | ||||||
| import ElementLocaleEn from 'element-ui/lib/locale/lang/en'; | import ElementLocaleEn from 'element-ui/lib/locale/lang/en'; | ||||||
| import ElementLocaleJa from 'element-ui/lib/locale/lang/ja'; | import ElementLocaleJa from 'element-ui/lib/locale/lang/ja'; | ||||||
|  | import VueThinModal from 'vue-thin-modal'; | ||||||
|  | import 'vue-thin-modal/dist/vue-thin-modal.css'; | ||||||
|  |  | ||||||
| import App from './app.vue'; | import App from './app.vue'; | ||||||
| import checkForUpdate from './common/scripts/check-for-update'; | import checkForUpdate from './common/scripts/check-for-update'; | ||||||
| @@ -19,8 +21,8 @@ import { version, codename, lang } from './config'; | |||||||
|  |  | ||||||
| let elementLocale; | let elementLocale; | ||||||
| switch (lang) { | switch (lang) { | ||||||
| 	case 'ja': elementLocale = ElementLocaleJa; break; | 	case 'ja-JP': elementLocale = ElementLocaleJa; break; | ||||||
| 	case 'en': elementLocale = ElementLocaleEn; break; | 	case 'en-US': elementLocale = ElementLocaleEn; break; | ||||||
| 	default: elementLocale = ElementLocaleEn; break; | 	default: elementLocale = ElementLocaleEn; break; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -30,6 +32,9 @@ Vue.use(VModal); | |||||||
| Vue.use(TreeView); | Vue.use(TreeView); | ||||||
| Vue.use(VAnimateCss); | Vue.use(VAnimateCss); | ||||||
| Vue.use(Element, { locale: elementLocale }); | Vue.use(Element, { locale: elementLocale }); | ||||||
|  | Vue.use(VueThinModal, { | ||||||
|  | 	autoMountPortal: false | ||||||
|  | }); | ||||||
|  |  | ||||||
| // Register global directives | // Register global directives | ||||||
| require('./common/views/directives'); | require('./common/views/directives'); | ||||||
|   | |||||||
| @@ -1,24 +0,0 @@ | |||||||
| import PostForm from '../views/components/post-form.vue'; |  | ||||||
|  |  | ||||||
| export default (os) => (opts) => { |  | ||||||
| 	const o = opts || {}; |  | ||||||
|  |  | ||||||
| 	const app = document.getElementById('app'); |  | ||||||
| 	app.style.display = 'none'; |  | ||||||
|  |  | ||||||
| 	function recover() { |  | ||||||
| 		app.style.display = 'block'; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	const vm = new PostForm({ |  | ||||||
| 		parent: os.app, |  | ||||||
| 		propsData: { |  | ||||||
| 			reply: o.reply, |  | ||||||
| 			renote: o.renote |  | ||||||
| 		} |  | ||||||
| 	}).$mount(); |  | ||||||
| 	vm.$once('cancel', recover); |  | ||||||
| 	vm.$once('posted', recover); |  | ||||||
| 	document.body.appendChild(vm.$el); |  | ||||||
| 	(vm as any).focus(); |  | ||||||
| }; |  | ||||||
| @@ -14,7 +14,6 @@ import chooseDriveFolder from './api/choose-drive-folder'; | |||||||
| import chooseDriveFile from './api/choose-drive-file'; | import chooseDriveFile from './api/choose-drive-file'; | ||||||
| import dialog from './api/dialog'; | import dialog from './api/dialog'; | ||||||
| import input from './api/input'; | import input from './api/input'; | ||||||
| import post from './api/post'; |  | ||||||
| import notify from './api/notify'; | import notify from './api/notify'; | ||||||
|  |  | ||||||
| import MkIndex from './views/pages/index.vue'; | import MkIndex from './views/pages/index.vue'; | ||||||
| @@ -91,7 +90,7 @@ init((launch) => { | |||||||
| 		chooseDriveFile, | 		chooseDriveFile, | ||||||
| 		dialog: dialog(os), | 		dialog: dialog(os), | ||||||
| 		input, | 		input, | ||||||
| 		post: post(os), | 		post: () => alert('deprecated'), | ||||||
| 		notify | 		notify | ||||||
| 	})); | 	})); | ||||||
| }, true); | }, true); | ||||||
|   | |||||||
| @@ -17,3 +17,13 @@ body | |||||||
| 	display flex | 	display flex | ||||||
| 	flex-direction column | 	flex-direction column | ||||||
| 	min-height 100% | 	min-height 100% | ||||||
|  |  | ||||||
|  | .modal-backdrop | ||||||
|  | 	z-index 10000 !important | ||||||
|  |  | ||||||
|  | .modal-content-wrapper | ||||||
|  | 	z-index 10001 !important | ||||||
|  |  | ||||||
|  | .modal-content | ||||||
|  | 	padding 0 !important | ||||||
|  | 	background-color transparent !important | ||||||
|   | |||||||
| @@ -48,7 +48,7 @@ export default Vue.extend({ | |||||||
| <style lang="stylus" scoped> | <style lang="stylus" scoped> | ||||||
| .mk-drive-file-chooser | .mk-drive-file-chooser | ||||||
| 	position fixed | 	position fixed | ||||||
| 	z-index 2048 | 	z-index 20000 | ||||||
| 	top 0 | 	top 0 | ||||||
| 	left 0 | 	left 0 | ||||||
| 	width 100% | 	width 100% | ||||||
|   | |||||||
| @@ -45,7 +45,7 @@ | |||||||
| 			</div> | 			</div> | ||||||
| 			<mk-poll v-if="p.poll" :note="p"/> | 			<mk-poll v-if="p.poll" :note="p"/> | ||||||
| 			<mk-url-preview v-for="url in urls" :url="url" :key="url" :detail="true"/> | 			<mk-url-preview v-for="url in urls" :url="url" :key="url" :detail="true"/> | ||||||
| 			<a class="location" v-if="p.geo" :href="`http://maps.google.com/maps?q=${p.geo.coordinates[1]},${p.geo.coordinates[0]}`" target="_blank">%fa:map-marker-alt% %i18n:@location%</a> | 			<a class="location" v-if="p.geo" :href="`https://maps.google.com/maps?q=${p.geo.coordinates[1]},${p.geo.coordinates[0]}`" target="_blank">%fa:map-marker-alt% %i18n:@location%</a> | ||||||
| 			<div class="map" v-if="p.geo" ref="map"></div> | 			<div class="map" v-if="p.geo" ref="map"></div> | ||||||
| 			<div class="renote" v-if="p.renote"> | 			<div class="renote" v-if="p.renote"> | ||||||
| 				<mk-note-preview :note="p.renote"/> | 				<mk-note-preview :note="p.renote"/> | ||||||
| @@ -75,6 +75,13 @@ | |||||||
| 	<div class="replies" v-if="!compact"> | 	<div class="replies" v-if="!compact"> | ||||||
| 		<x-sub v-for="note in replies" :key="note.id" :note="note"/> | 		<x-sub v-for="note in replies" :key="note.id" :note="note"/> | ||||||
| 	</div> | 	</div> | ||||||
|  |  | ||||||
|  | 	<modal name="replyForm"> | ||||||
|  | 		<mk-post-form @posted="replyFormClosed" @cancel="replyFormClosed" :reply="p"/> | ||||||
|  | 	</modal> | ||||||
|  | 	<modal name="renoteForm"> | ||||||
|  | 		<mk-post-form @posted="renoteFormClosed" @cancel="renoteFormClosed" :renote="p"/> | ||||||
|  | 	</modal> | ||||||
| </div> | </div> | ||||||
| </template> | </template> | ||||||
|  |  | ||||||
| @@ -116,9 +123,11 @@ export default Vue.extend({ | |||||||
| 				this.note.mediaIds.length == 0 && | 				this.note.mediaIds.length == 0 && | ||||||
| 				this.note.poll == null); | 				this.note.poll == null); | ||||||
| 		}, | 		}, | ||||||
|  |  | ||||||
| 		p(): any { | 		p(): any { | ||||||
| 			return this.isRenote ? this.note.renote : this.note; | 			return this.isRenote ? this.note.renote : this.note; | ||||||
| 		}, | 		}, | ||||||
|  |  | ||||||
| 		reactionsCount(): number { | 		reactionsCount(): number { | ||||||
| 			return this.p.reactionCounts | 			return this.p.reactionCounts | ||||||
| 				? Object.keys(this.p.reactionCounts) | 				? Object.keys(this.p.reactionCounts) | ||||||
| @@ -126,6 +135,7 @@ export default Vue.extend({ | |||||||
| 					.reduce((a, b) => a + b) | 					.reduce((a, b) => a + b) | ||||||
| 				: 0; | 				: 0; | ||||||
| 		}, | 		}, | ||||||
|  |  | ||||||
| 		urls(): string[] { | 		urls(): string[] { | ||||||
| 			if (this.p.text) { | 			if (this.p.text) { | ||||||
| 				const ast = parse(this.p.text); | 				const ast = parse(this.p.text); | ||||||
| @@ -180,16 +190,23 @@ export default Vue.extend({ | |||||||
| 				this.conversation = conversation.reverse(); | 				this.conversation = conversation.reverse(); | ||||||
| 			}); | 			}); | ||||||
| 		}, | 		}, | ||||||
|  |  | ||||||
| 		reply() { | 		reply() { | ||||||
| 			(this as any).apis.post({ | 			this.$modal.push('replyForm'); | ||||||
| 				reply: this.p |  | ||||||
| 			}); |  | ||||||
| 		}, | 		}, | ||||||
|  |  | ||||||
|  | 		replyFormClosed() { | ||||||
|  | 			this.$modal.pop(); | ||||||
|  | 		}, | ||||||
|  |  | ||||||
| 		renote() { | 		renote() { | ||||||
| 			(this as any).apis.post({ | 			this.$modal.push('renoteForm'); | ||||||
| 				renote: this.p |  | ||||||
| 			}); |  | ||||||
| 		}, | 		}, | ||||||
|  |  | ||||||
|  | 		renoteFormClosed() { | ||||||
|  | 			this.$modal.pop(); | ||||||
|  | 		}, | ||||||
|  |  | ||||||
| 		react() { | 		react() { | ||||||
| 			(this as any).os.new(MkReactionPicker, { | 			(this as any).os.new(MkReactionPicker, { | ||||||
| 				source: this.$refs.reactButton, | 				source: this.$refs.reactButton, | ||||||
| @@ -198,6 +215,7 @@ export default Vue.extend({ | |||||||
| 				big: true | 				big: true | ||||||
| 			}); | 			}); | ||||||
| 		}, | 		}, | ||||||
|  |  | ||||||
| 		menu() { | 		menu() { | ||||||
| 			(this as any).os.new(MkNoteMenu, { | 			(this as any).os.new(MkNoteMenu, { | ||||||
| 				source: this.$refs.menuButton, | 				source: this.$refs.menuButton, | ||||||
|   | |||||||
| @@ -33,7 +33,7 @@ | |||||||
| 					</div> | 					</div> | ||||||
| 					<mk-poll v-if="p.poll" :note="p" ref="pollViewer"/> | 					<mk-poll v-if="p.poll" :note="p" ref="pollViewer"/> | ||||||
| 					<mk-url-preview v-for="url in urls" :url="url" :key="url"/> | 					<mk-url-preview v-for="url in urls" :url="url" :key="url"/> | ||||||
| 					<a class="location" v-if="p.geo" :href="`http://maps.google.com/maps?q=${p.geo.coordinates[1]},${p.geo.coordinates[0]}`" target="_blank">%fa:map-marker-alt% %i18n:@location%</a> | 					<a class="location" v-if="p.geo" :href="`https://maps.google.com/maps?q=${p.geo.coordinates[1]},${p.geo.coordinates[0]}`" target="_blank">%fa:map-marker-alt% %i18n:@location%</a> | ||||||
| 					<div class="map" v-if="p.geo" ref="map"></div> | 					<div class="map" v-if="p.geo" ref="map"></div> | ||||||
| 					<div class="renote" v-if="p.renote"> | 					<div class="renote" v-if="p.renote"> | ||||||
| 						<mk-note-preview :note="p.renote"/> | 						<mk-note-preview :note="p.renote"/> | ||||||
| @@ -60,6 +60,13 @@ | |||||||
| 			</footer> | 			</footer> | ||||||
| 		</div> | 		</div> | ||||||
| 	</article> | 	</article> | ||||||
|  |  | ||||||
|  | 	<modal name="replyForm"> | ||||||
|  | 		<mk-post-form @posted="replyFormClosed" @cancel="replyFormClosed" :reply="p"/> | ||||||
|  | 	</modal> | ||||||
|  | 	<modal name="renoteForm"> | ||||||
|  | 		<mk-post-form @posted="renoteFormClosed" @cancel="renoteFormClosed" :renote="p"/> | ||||||
|  | 	</modal> | ||||||
| </div> | </div> | ||||||
| </template> | </template> | ||||||
|  |  | ||||||
| @@ -195,15 +202,19 @@ export default Vue.extend({ | |||||||
| 		}, | 		}, | ||||||
|  |  | ||||||
| 		reply() { | 		reply() { | ||||||
| 			(this as any).apis.post({ | 			this.$modal.push('replyForm'); | ||||||
| 				reply: this.p | 		}, | ||||||
| 			}); |  | ||||||
|  | 		replyFormClosed() { | ||||||
|  | 			this.$modal.pop(); | ||||||
| 		}, | 		}, | ||||||
|  |  | ||||||
| 		renote() { | 		renote() { | ||||||
| 			(this as any).apis.post({ | 			this.$modal.push('renoteForm'); | ||||||
| 				renote: this.p | 		}, | ||||||
| 			}); |  | ||||||
|  | 		renoteFormClosed() { | ||||||
|  | 			this.$modal.pop(); | ||||||
| 		}, | 		}, | ||||||
|  |  | ||||||
| 		react() { | 		react() { | ||||||
|   | |||||||
| @@ -293,9 +293,6 @@ export default Vue.extend({ | |||||||
| 				viaMobile: viaMobile | 				viaMobile: viaMobile | ||||||
| 			}).then(data => { | 			}).then(data => { | ||||||
| 				this.$emit('posted'); | 				this.$emit('posted'); | ||||||
| 				this.$nextTick(() => { |  | ||||||
| 					this.$destroy(); |  | ||||||
| 				}); |  | ||||||
| 			}).catch(err => { | 			}).catch(err => { | ||||||
| 				this.posting = false; | 				this.posting = false; | ||||||
| 			}); | 			}); | ||||||
| @@ -309,7 +306,6 @@ export default Vue.extend({ | |||||||
|  |  | ||||||
| 		cancel() { | 		cancel() { | ||||||
| 			this.$emit('cancel'); | 			this.$emit('cancel'); | ||||||
| 			this.$destroy(); |  | ||||||
| 		}, | 		}, | ||||||
|  |  | ||||||
| 		kao() { | 		kao() { | ||||||
|   | |||||||
| @@ -1,5 +1,6 @@ | |||||||
| <template> | <template> | ||||||
| <div class="header"> | <div class="header" ref="root"> | ||||||
|  | 	<p class="warn" v-if="env != 'production'">%i18n:common.do-not-use-in-production%</p> | ||||||
| 	<mk-special-message/> | 	<mk-special-message/> | ||||||
| 	<div class="main" ref="main"> | 	<div class="main" ref="main"> | ||||||
| 		<div class="backdrop"></div> | 		<div class="backdrop"></div> | ||||||
| @@ -20,6 +21,7 @@ | |||||||
| <script lang="ts"> | <script lang="ts"> | ||||||
| import Vue from 'vue'; | import Vue from 'vue'; | ||||||
| import * as anime from 'animejs'; | import * as anime from 'animejs'; | ||||||
|  | import { env } from '../../../config'; | ||||||
|  |  | ||||||
| export default Vue.extend({ | export default Vue.extend({ | ||||||
| 	props: ['func'], | 	props: ['func'], | ||||||
| @@ -27,7 +29,8 @@ export default Vue.extend({ | |||||||
| 		return { | 		return { | ||||||
| 			hasGameInvitation: false, | 			hasGameInvitation: false, | ||||||
| 			connection: null, | 			connection: null, | ||||||
| 			connectionId: null | 			connectionId: null, | ||||||
|  | 			env: env | ||||||
| 		}; | 		}; | ||||||
| 	}, | 	}, | ||||||
| 	computed: { | 	computed: { | ||||||
| @@ -39,7 +42,7 @@ export default Vue.extend({ | |||||||
| 		} | 		} | ||||||
| 	}, | 	}, | ||||||
| 	mounted() { | 	mounted() { | ||||||
| 		this.$store.commit('setUiHeaderHeight', 48); | 		this.$store.commit('setUiHeaderHeight', this.$refs.root.offsetHeight); | ||||||
|  |  | ||||||
| 		if (this.$store.getters.isSignedIn) { | 		if (this.$store.getters.isSignedIn) { | ||||||
| 			this.connection = (this as any).os.stream.getConnection(); | 			this.connection = (this as any).os.stream.getConnection(); | ||||||
| @@ -133,6 +136,15 @@ root(isDark) | |||||||
| 		height 3px | 		height 3px | ||||||
| 		background $theme-color | 		background $theme-color | ||||||
|  |  | ||||||
|  | 	> .warn | ||||||
|  | 		display block | ||||||
|  | 		margin 0 | ||||||
|  | 		padding 4px | ||||||
|  | 		text-align center | ||||||
|  | 		font-size 12px | ||||||
|  | 		background #f00 | ||||||
|  | 		color #fff | ||||||
|  |  | ||||||
| 	> .main | 	> .main | ||||||
| 		color rgba(#fff, 0.9) | 		color rgba(#fff, 0.9) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -31,7 +31,14 @@ export default Vue.extend({ | |||||||
| 			connectionId: null | 			connectionId: null | ||||||
| 		}; | 		}; | ||||||
| 	}, | 	}, | ||||||
|  | 	watch: { | ||||||
|  | 		'$store.state.uiHeaderHeight'() { | ||||||
|  | 			this.$el.style.paddingTop = this.$store.state.uiHeaderHeight + 'px'; | ||||||
|  | 		} | ||||||
|  | 	}, | ||||||
| 	mounted() { | 	mounted() { | ||||||
|  | 		this.$el.style.paddingTop = this.$store.state.uiHeaderHeight + 'px'; | ||||||
|  |  | ||||||
| 		if (this.$store.getters.isSignedIn) { | 		if (this.$store.getters.isSignedIn) { | ||||||
| 			this.connection = (this as any).os.stream.getConnection(); | 			this.connection = (this as any).os.stream.getConnection(); | ||||||
| 			this.connectionId = (this as any).os.stream.use(); | 			this.connectionId = (this as any).os.stream.use(); | ||||||
|   | |||||||
| @@ -42,6 +42,10 @@ | |||||||
| 			<mk-user-list-timeline v-if="src == 'list'" ref="tl" :key="list.id" :list="list"/> | 			<mk-user-list-timeline v-if="src == 'list'" ref="tl" :key="list.id" :list="list"/> | ||||||
| 		</div> | 		</div> | ||||||
| 	</main> | 	</main> | ||||||
|  |  | ||||||
|  | 	<modal name="postForm"> | ||||||
|  | 		<mk-post-form @posted="postFormClosed" @cancel="postFormClosed"/> | ||||||
|  | 	</modal> | ||||||
| </mk-ui> | </mk-ui> | ||||||
| </template> | </template> | ||||||
|  |  | ||||||
| @@ -107,7 +111,11 @@ export default Vue.extend({ | |||||||
|  |  | ||||||
| 	methods: { | 	methods: { | ||||||
| 		fn() { | 		fn() { | ||||||
| 			(this as any).apis.post(); | 			this.$modal.push('postForm'); | ||||||
|  | 		}, | ||||||
|  |  | ||||||
|  | 		postFormClosed() { | ||||||
|  | 			this.$modal.pop(); | ||||||
| 		}, | 		}, | ||||||
|  |  | ||||||
| 		saveSrc() { | 		saveSrc() { | ||||||
|   | |||||||
| @@ -41,6 +41,12 @@ | |||||||
| 				<ui-switch v-model="lightmode">%i18n:@i-am-under-limited-internet%</ui-switch> | 				<ui-switch v-model="lightmode">%i18n:@i-am-under-limited-internet%</ui-switch> | ||||||
| 			</ui-card> | 			</ui-card> | ||||||
|  |  | ||||||
|  | 			<ui-card> | ||||||
|  | 				<div slot="title">%fa:volume-up% %i18n:@sound%</div> | ||||||
|  |  | ||||||
|  | 				<ui-switch v-model="enableSounds">%i18n:@enable-sounds%</ui-switch> | ||||||
|  | 			</ui-card> | ||||||
|  |  | ||||||
| 			<ui-card> | 			<ui-card> | ||||||
| 				<div slot="title">%fa:language% %i18n:@lang%</div> | 				<div slot="title">%fa:language% %i18n:@lang%</div> | ||||||
|  |  | ||||||
| @@ -142,6 +148,11 @@ export default Vue.extend({ | |||||||
| 			get() { return this.$store.state.device.lang; }, | 			get() { return this.$store.state.device.lang; }, | ||||||
| 			set(value) { this.$store.commit('device/set', { key: 'lang', value }); } | 			set(value) { this.$store.commit('device/set', { key: 'lang', value }); } | ||||||
| 		}, | 		}, | ||||||
|  |  | ||||||
|  | 		enableSounds: { | ||||||
|  | 			get() { return this.$store.state.device.enableSounds; }, | ||||||
|  | 			set(value) { this.$store.commit('device/set', { key: 'enableSounds', value }); } | ||||||
|  | 		}, | ||||||
| 	}, | 	}, | ||||||
|  |  | ||||||
| 	mounted() { | 	mounted() { | ||||||
|   | |||||||
| @@ -13,7 +13,7 @@ const defaultSettings = { | |||||||
| 	showMaps: true, | 	showMaps: true, | ||||||
| 	showPostFormOnTopOfTl: false, | 	showPostFormOnTopOfTl: false, | ||||||
| 	suggestRecentHashtags: true, | 	suggestRecentHashtags: true, | ||||||
| 	showClockOnHeader: false, | 	showClockOnHeader: true, | ||||||
| 	circleIcons: true, | 	circleIcons: true, | ||||||
| 	gradientWindowHeader: false, | 	gradientWindowHeader: false, | ||||||
| 	showReplyTarget: true, | 	showReplyTarget: true, | ||||||
|   | |||||||
| @@ -53,5 +53,5 @@ export default function load() { | |||||||
| } | } | ||||||
|  |  | ||||||
| function normalizeUrl(url: string) { | function normalizeUrl(url: string) { | ||||||
| 	return url[url.length - 1] === '/' ? url.substr(0, url.length - 1) : url; | 	return url.endsWith('/') ? url.substr(0, url.length - 1) : url; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -15,7 +15,7 @@ block main | |||||||
| 		span.path= endpointUrl.path | 		span.path= endpointUrl.path | ||||||
|  |  | ||||||
| 	if endpoint.desc | 	if endpoint.desc | ||||||
| 		p#desc= endpoint.desc[lang] || endpoint.desc['ja'] | 		p#desc= endpoint.desc[lang] || endpoint.desc['ja-JP'] | ||||||
|  |  | ||||||
| 	if endpoint.requireCredential | 	if endpoint.requireCredential | ||||||
| 		div.ui.info: p | 		div.ui.info: p | ||||||
|   | |||||||
| @@ -1,90 +1,90 @@ | |||||||
| name: "DriveFile" | name: "DriveFile" | ||||||
|  |  | ||||||
| desc: | desc: | ||||||
|   ja: "ドライブのファイル。" |   ja-JP: "ドライブのファイル。" | ||||||
|   en: "A file of Drive." |   en-US: "A file of Drive." | ||||||
|  |  | ||||||
| props: | props: | ||||||
|   id: |   id: | ||||||
|     type: "id" |     type: "id" | ||||||
|     optional: false |     optional: false | ||||||
|     desc: |     desc: | ||||||
|       ja: "ファイルID" |       ja-JP: "ファイルID" | ||||||
|       en: "The ID of this file" |       en-US: "The ID of this file" | ||||||
|  |  | ||||||
|   createdAt: |   createdAt: | ||||||
|     type: "date" |     type: "date" | ||||||
|     optional: false |     optional: false | ||||||
|     desc: |     desc: | ||||||
|       ja: "アップロード日時" |       ja-JP: "アップロード日時" | ||||||
|       en: "The upload date of this file" |       en-US: "The upload date of this file" | ||||||
|  |  | ||||||
|   userId: |   userId: | ||||||
|     type: "id(User)" |     type: "id(User)" | ||||||
|     optional: false |     optional: false | ||||||
|     desc: |     desc: | ||||||
|       ja: "所有者ID" |       ja-JP: "所有者ID" | ||||||
|       en: "The ID of the owner of this file" |       en-US: "The ID of the owner of this file" | ||||||
|  |  | ||||||
|   user: |   user: | ||||||
|     type: "entity(User)" |     type: "entity(User)" | ||||||
|     optional: true |     optional: true | ||||||
|     desc: |     desc: | ||||||
|       ja: "所有者" |       ja-JP: "所有者" | ||||||
|       en: "The owner of this file" |       en-US: "The owner of this file" | ||||||
|  |  | ||||||
|   name: |   name: | ||||||
|     type: "string" |     type: "string" | ||||||
|     optional: false |     optional: false | ||||||
|     desc: |     desc: | ||||||
|       ja: "ファイル名" |       ja-JP: "ファイル名" | ||||||
|       en: "The name of this file" |       en-US: "The name of this file" | ||||||
|  |  | ||||||
|   md5: |   md5: | ||||||
|     type: "string" |     type: "string" | ||||||
|     optional: false |     optional: false | ||||||
|     desc: |     desc: | ||||||
|       ja: "ファイルのMD5ハッシュ値" |       ja-JP: "ファイルのMD5ハッシュ値" | ||||||
|       en: "The md5 hash value of this file" |       en-US: "The md5 hash value of this file" | ||||||
|  |  | ||||||
|   type: |   type: | ||||||
|     type: "string" |     type: "string" | ||||||
|     optional: false |     optional: false | ||||||
|     desc: |     desc: | ||||||
|       ja: "ファイルの種類" |       ja-JP: "ファイルの種類" | ||||||
|       en: "The type of this file" |       en-US: "The type of this file" | ||||||
|  |  | ||||||
|   datasize: |   datasize: | ||||||
|     type: "number" |     type: "number" | ||||||
|     optional: false |     optional: false | ||||||
|     desc: |     desc: | ||||||
|       ja: "ファイルサイズ(bytes)" |       ja-JP: "ファイルサイズ(bytes)" | ||||||
|       en: "The size of this file (bytes)" |       en-US: "The size of this file (bytes)" | ||||||
|  |  | ||||||
|   url: |   url: | ||||||
|     type: "string" |     type: "string" | ||||||
|     optional: false |     optional: false | ||||||
|     desc: |     desc: | ||||||
|       ja: "ファイルのURL" |       ja-JP: "ファイルのURL" | ||||||
|       en: "The URL of this file" |       en-US: "The URL of this file" | ||||||
|  |  | ||||||
|   folderId: |   folderId: | ||||||
|     type: "id(DriveFolder)" |     type: "id(DriveFolder)" | ||||||
|     optional: true |     optional: true | ||||||
|     desc: |     desc: | ||||||
|       ja: "フォルダID" |       ja-JP: "フォルダID" | ||||||
|       en: "The ID of the folder of this file" |       en-US: "The ID of the folder of this file" | ||||||
|  |  | ||||||
|   folder: |   folder: | ||||||
|     type: "entity(DriveFolder)" |     type: "entity(DriveFolder)" | ||||||
|     optional: true |     optional: true | ||||||
|     desc: |     desc: | ||||||
|       ja: "フォルダ" |       ja-JP: "フォルダ" | ||||||
|       en: "The folder of this file" |       en-US: "The folder of this file" | ||||||
|  |  | ||||||
|   isSensitive: |   isSensitive: | ||||||
|     type: "boolean" |     type: "boolean" | ||||||
|     optional: true |     optional: true | ||||||
|     desc: |     desc: | ||||||
|       ja: "このメディアが「閲覧注意」(NSFW)かどうか" |       ja-JP: "このメディアが「閲覧注意」(NSFW)かどうか" | ||||||
|       en: "Whether this media is NSFW" |       en-US: "Whether this media is NSFW" | ||||||
|   | |||||||
| @@ -1,41 +1,41 @@ | |||||||
| name: "DriveFolder" | name: "DriveFolder" | ||||||
|  |  | ||||||
| desc: | desc: | ||||||
|   ja: "ドライブのフォルダを表します。" |   ja-JP: "ドライブのフォルダを表します。" | ||||||
|   en: "A folder of Drive." |   en-US: "A folder of Drive." | ||||||
|  |  | ||||||
| props: | props: | ||||||
|   id: |   id: | ||||||
|     type: "id" |     type: "id" | ||||||
|     optional: false |     optional: false | ||||||
|     desc: |     desc: | ||||||
|       ja: "フォルダID" |       ja-JP: "フォルダID" | ||||||
|       en: "The ID of this folder" |       en-US: "The ID of this folder" | ||||||
|  |  | ||||||
|   createdAt: |   createdAt: | ||||||
|     type: "date" |     type: "date" | ||||||
|     optional: false |     optional: false | ||||||
|     desc: |     desc: | ||||||
|       ja: "作成日時" |       ja-JP: "作成日時" | ||||||
|       en: "The created date of this folder" |       en-US: "The created date of this folder" | ||||||
|  |  | ||||||
|   userId: |   userId: | ||||||
|     type: "id(User)" |     type: "id(User)" | ||||||
|     optional: false |     optional: false | ||||||
|     desc: |     desc: | ||||||
|       ja: "所有者ID" |       ja-JP: "所有者ID" | ||||||
|       en: "The ID of the owner of this folder" |       en-US: "The ID of the owner of this folder" | ||||||
|  |  | ||||||
|   parentId: |   parentId: | ||||||
|     type: "entity(DriveFolder)" |     type: "entity(DriveFolder)" | ||||||
|     optional: false |     optional: false | ||||||
|     desc: |     desc: | ||||||
|       ja: "親フォルダのID (ルートなら null)" |       ja-JP: "親フォルダのID (ルートなら null)" | ||||||
|       en: "The ID of parent folder" |       en-US: "The ID of parent folder" | ||||||
|  |  | ||||||
|   name: |   name: | ||||||
|     type: "string" |     type: "string" | ||||||
|     optional: false |     optional: false | ||||||
|     desc: |     desc: | ||||||
|       ja: "フォルダ名" |       ja-JP: "フォルダ名" | ||||||
|       en: "The name of this folder" |       en-US: "The name of this folder" | ||||||
|   | |||||||
| @@ -1,190 +1,190 @@ | |||||||
| name: "Note" | name: "Note" | ||||||
|  |  | ||||||
| desc: | desc: | ||||||
|   ja: "投稿。" |   ja-JP: "投稿。" | ||||||
|   en: "A note." |   en-US: "A note." | ||||||
|  |  | ||||||
| props: | props: | ||||||
|   id: |   id: | ||||||
|     type: "id" |     type: "id" | ||||||
|     optional: false |     optional: false | ||||||
|     desc: |     desc: | ||||||
|       ja: "投稿ID" |       ja-JP: "投稿ID" | ||||||
|       en: "The ID of this note" |       en-US: "The ID of this note" | ||||||
|  |  | ||||||
|   createdAt: |   createdAt: | ||||||
|     type: "date" |     type: "date" | ||||||
|     optional: false |     optional: false | ||||||
|     desc: |     desc: | ||||||
|       ja: "投稿日時" |       ja-JP: "投稿日時" | ||||||
|       en: "The posted date of this note" |       en-US: "The posted date of this note" | ||||||
|  |  | ||||||
|   viaMobile: |   viaMobile: | ||||||
|     type: "boolean" |     type: "boolean" | ||||||
|     optional: true |     optional: true | ||||||
|     desc: |     desc: | ||||||
|       ja: "モバイル端末から投稿したか否か(自己申告であることに留意)" |       ja-JP: "モバイル端末から投稿したか否か(自己申告であることに留意)" | ||||||
|       en: "Whether this note sent via a mobile device" |       en-US: "Whether this note sent via a mobile device" | ||||||
|  |  | ||||||
|   text: |   text: | ||||||
|     type: "string" |     type: "string" | ||||||
|     optional: true |     optional: true | ||||||
|     desc: |     desc: | ||||||
|       ja: "投稿の本文" |       ja-JP: "投稿の本文" | ||||||
|       en: "The text of this note" |       en-US: "The text of this note" | ||||||
|  |  | ||||||
|   mediaIds: |   mediaIds: | ||||||
|     type: "id(DriveFile)[]" |     type: "id(DriveFile)[]" | ||||||
|     optional: true |     optional: true | ||||||
|     desc: |     desc: | ||||||
|       ja: "添付されているメディアのID (なければレスポンスでは空配列)" |       ja-JP: "添付されているメディアのID (なければレスポンスでは空配列)" | ||||||
|       en: "The IDs of the attached media (empty array for response if no media is attached)" |       en-US: "The IDs of the attached media (empty array for response if no media is attached)" | ||||||
|  |  | ||||||
|   media: |   media: | ||||||
|     type: "entity(DriveFile)[]" |     type: "entity(DriveFile)[]" | ||||||
|     optional: true |     optional: true | ||||||
|     desc: |     desc: | ||||||
|       ja: "添付されているメディア" |       ja-JP: "添付されているメディア" | ||||||
|       en: "The attached media" |       en-US: "The attached media" | ||||||
|  |  | ||||||
|   userId: |   userId: | ||||||
|     type: "id(User)" |     type: "id(User)" | ||||||
|     optional: false |     optional: false | ||||||
|     desc: |     desc: | ||||||
|       ja: "投稿者ID" |       ja-JP: "投稿者ID" | ||||||
|       en: "The ID of author of this note" |       en-US: "The ID of author of this note" | ||||||
|  |  | ||||||
|   user: |   user: | ||||||
|     type: "entity(User)" |     type: "entity(User)" | ||||||
|     optional: true |     optional: true | ||||||
|     desc: |     desc: | ||||||
|       ja: "投稿者" |       ja-JP: "投稿者" | ||||||
|       en: "The author of this note" |       en-US: "The author of this note" | ||||||
|  |  | ||||||
|   myReaction: |   myReaction: | ||||||
|     type: "string" |     type: "string" | ||||||
|     optional: true |     optional: true | ||||||
|     desc: |     desc: | ||||||
|       ja: "この投稿に対する自分の<a href='/docs/api/reactions'>リアクション</a>" |       ja-JP: "この投稿に対する自分の<a href='/docs/api/reactions'>リアクション</a>" | ||||||
|       en: "The your <a href='/docs/api/reactions'>reaction</a> of this note" |       en-US: "The your <a href='/docs/api/reactions'>reaction</a> of this note" | ||||||
|  |  | ||||||
|   reactionCounts: |   reactionCounts: | ||||||
|     type: "object" |     type: "object" | ||||||
|     optional: false |     optional: false | ||||||
|     desc: |     desc: | ||||||
|       ja: "<a href='/docs/api/reactions'>リアクション</a>をキーとし、この投稿に対するそのリアクションの数を値としたオブジェクト" |       ja-JP: "<a href='/docs/api/reactions'>リアクション</a>をキーとし、この投稿に対するそのリアクションの数を値としたオブジェクト" | ||||||
|  |  | ||||||
|   replyId: |   replyId: | ||||||
|     type: "id(Note)" |     type: "id(Note)" | ||||||
|     optional: true |     optional: true | ||||||
|     desc: |     desc: | ||||||
|       ja: "返信した投稿のID" |       ja-JP: "返信した投稿のID" | ||||||
|       en: "The ID of the replyed note" |       en-US: "The ID of the replyed note" | ||||||
|  |  | ||||||
|   reply: |   reply: | ||||||
|     type: "entity(Note)" |     type: "entity(Note)" | ||||||
|     optional: true |     optional: true | ||||||
|     desc: |     desc: | ||||||
|       ja: "返信した投稿" |       ja-JP: "返信した投稿" | ||||||
|       en: "The replyed note" |       en-US: "The replyed note" | ||||||
|  |  | ||||||
|   renoteId: |   renoteId: | ||||||
|     type: "id(Note)" |     type: "id(Note)" | ||||||
|     optional: true |     optional: true | ||||||
|     desc: |     desc: | ||||||
|       ja: "引用した投稿のID" |       ja-JP: "引用した投稿のID" | ||||||
|       en: "The ID of the quoted note" |       en-US: "The ID of the quoted note" | ||||||
|  |  | ||||||
|   renote: |   renote: | ||||||
|     type: "entity(Note)" |     type: "entity(Note)" | ||||||
|     optional: true |     optional: true | ||||||
|     desc: |     desc: | ||||||
|       ja: "引用した投稿" |       ja-JP: "引用した投稿" | ||||||
|       en: "The quoted note" |       en-US: "The quoted note" | ||||||
|  |  | ||||||
|   poll: |   poll: | ||||||
|     type: "object" |     type: "object" | ||||||
|     optional: true |     optional: true | ||||||
|     desc: |     desc: | ||||||
|       ja: "投票" |       ja-JP: "投票" | ||||||
|       en: "The poll" |       en-US: "The poll" | ||||||
|  |  | ||||||
|     props: |     props: | ||||||
|       choices: |       choices: | ||||||
|         type: "object[]" |         type: "object[]" | ||||||
|         optional: false |         optional: false | ||||||
|         desc: |         desc: | ||||||
|           ja: "投票の選択肢" |           ja-JP: "投票の選択肢" | ||||||
|           en: "The choices of this poll" |           en-US: "The choices of this poll" | ||||||
|  |  | ||||||
|         props: |         props: | ||||||
|           id: |           id: | ||||||
|             type: "number" |             type: "number" | ||||||
|             optional: false |             optional: false | ||||||
|             desc: |             desc: | ||||||
|               ja: "選択肢ID" |               ja-JP: "選択肢ID" | ||||||
|               en: "The ID of this choice" |               en-US: "The ID of this choice" | ||||||
|  |  | ||||||
|           isVoted: |           isVoted: | ||||||
|             type: "boolean" |             type: "boolean" | ||||||
|             optional: true |             optional: true | ||||||
|             desc: |             desc: | ||||||
|               ja: "自分がこの選択肢に投票したかどうか" |               ja-JP: "自分がこの選択肢に投票したかどうか" | ||||||
|               en: "Whether you voted to this choice" |               en-US: "Whether you voted to this choice" | ||||||
|  |  | ||||||
|           text: |           text: | ||||||
|             type: "string" |             type: "string" | ||||||
|             optional: false |             optional: false | ||||||
|             desc: |             desc: | ||||||
|               ja: "選択肢本文" |               ja-JP: "選択肢本文" | ||||||
|               en: "The text of this choice" |               en-US: "The text of this choice" | ||||||
|  |  | ||||||
|           votes: |           votes: | ||||||
|             type: "number" |             type: "number" | ||||||
|             optional: false |             optional: false | ||||||
|             desc: |             desc: | ||||||
|               ja: "この選択肢に投票された数" |               ja-JP: "この選択肢に投票された数" | ||||||
|               en: "The number voted for this choice" |               en-US: "The number voted for this choice" | ||||||
|   geo: |   geo: | ||||||
|     type: "object" |     type: "object" | ||||||
|     optional: true |     optional: true | ||||||
|     desc: |     desc: | ||||||
|       ja: "位置情報" |       ja-JP: "位置情報" | ||||||
|       en: "Geo location" |       en-US: "Geo location" | ||||||
|  |  | ||||||
|     props: |     props: | ||||||
|       coordinates: |       coordinates: | ||||||
|         type: "number[]" |         type: "number[]" | ||||||
|         optional: false |         optional: false | ||||||
|         desc: |         desc: | ||||||
|           ja: "座標。最初に経度:-180〜180で表す。最後に緯度:-90〜90で表す。" |           ja-JP: "座標。最初に経度:-180〜180で表す。最後に緯度:-90〜90で表す。" | ||||||
|  |  | ||||||
|       altitude: |       altitude: | ||||||
|         type: "number" |         type: "number" | ||||||
|         optional: false |         optional: false | ||||||
|         desc: |         desc: | ||||||
|           ja: "高度。メートル単位で表す。" |           ja-JP: "高度。メートル単位で表す。" | ||||||
|  |  | ||||||
|       accuracy: |       accuracy: | ||||||
|         type: "number" |         type: "number" | ||||||
|         optional: false |         optional: false | ||||||
|         desc: |         desc: | ||||||
|           ja: "緯度、経度の精度。メートル単位で表す。" |           ja-JP: "緯度、経度の精度。メートル単位で表す。" | ||||||
|  |  | ||||||
|       altitudeAccuracy: |       altitudeAccuracy: | ||||||
|         type: "number" |         type: "number" | ||||||
|         optional: false |         optional: false | ||||||
|         desc: |         desc: | ||||||
|           ja: "高度の精度。メートル単位で表す。" |           ja-JP: "高度の精度。メートル単位で表す。" | ||||||
|  |  | ||||||
|       heading: |       heading: | ||||||
|         type: "number" |         type: "number" | ||||||
|         optional: false |         optional: false | ||||||
|         desc: |         desc: | ||||||
|           ja: "方角。0〜360の角度で表す。0が北、90が東、180が南、270が西。" |           ja-JP: "方角。0〜360の角度で表す。0が北、90が東、180が南、270が西。" | ||||||
|  |  | ||||||
|       speed: |       speed: | ||||||
|         type: "number" |         type: "number" | ||||||
|         optional: false |         optional: false | ||||||
|         desc: |         desc: | ||||||
|           ja: "速度。メートル / 秒数で表す。" |           ja-JP: "速度。メートル / 秒数で表す。" | ||||||
|   | |||||||
| @@ -1,174 +1,174 @@ | |||||||
| name: "User" | name: "User" | ||||||
|  |  | ||||||
| desc: | desc: | ||||||
|   ja: "ユーザー。" |   ja-JP: "ユーザー。" | ||||||
|   en: "A user." |   en-US: "A user." | ||||||
|  |  | ||||||
| props: | props: | ||||||
|   id: |   id: | ||||||
|     type: "id" |     type: "id" | ||||||
|     optional: false |     optional: false | ||||||
|     desc: |     desc: | ||||||
|       ja: "ユーザーID" |       ja-JP: "ユーザーID" | ||||||
|       en: "The ID of this user" |       en-US: "The ID of this user" | ||||||
|  |  | ||||||
|   createdAt: |   createdAt: | ||||||
|     type: "date" |     type: "date" | ||||||
|     optional: false |     optional: false | ||||||
|     desc: |     desc: | ||||||
|       ja: "アカウント作成日時" |       ja-JP: "アカウント作成日時" | ||||||
|       en: "The registered date of this user" |       en-US: "The registered date of this user" | ||||||
|  |  | ||||||
|   username: |   username: | ||||||
|     type: "string" |     type: "string" | ||||||
|     optional: false |     optional: false | ||||||
|     desc: |     desc: | ||||||
|       ja: "ユーザー名" |       ja-JP: "ユーザー名" | ||||||
|       en: "The username of this user" |       en-US: "The username of this user" | ||||||
|  |  | ||||||
|   description: |   description: | ||||||
|     type: "string" |     type: "string" | ||||||
|     optional: false |     optional: false | ||||||
|     desc: |     desc: | ||||||
|       ja: "アカウントの説明(自己紹介)" |       ja-JP: "アカウントの説明(自己紹介)" | ||||||
|       en: "The description of this user" |       en-US: "The description of this user" | ||||||
|  |  | ||||||
|   avatarId: |   avatarId: | ||||||
|     type: "id(DriveFile)" |     type: "id(DriveFile)" | ||||||
|     optional: true |     optional: true | ||||||
|     desc: |     desc: | ||||||
|       ja: "アバターのID" |       ja-JP: "アバターのID" | ||||||
|       en: "The ID of the avatar of this user" |       en-US: "The ID of the avatar of this user" | ||||||
|  |  | ||||||
|   avatarUrl: |   avatarUrl: | ||||||
|     type: "string" |     type: "string" | ||||||
|     optional: false |     optional: false | ||||||
|     desc: |     desc: | ||||||
|       ja: "アバターのURL" |       ja-JP: "アバターのURL" | ||||||
|       en: "The URL of the avatar of this user" |       en-US: "The URL of the avatar of this user" | ||||||
|  |  | ||||||
|   bannerId: |   bannerId: | ||||||
|     type: "id(DriveFile)" |     type: "id(DriveFile)" | ||||||
|     optional: true |     optional: true | ||||||
|     desc: |     desc: | ||||||
|       ja: "バナーのID" |       ja-JP: "バナーのID" | ||||||
|       en: "The ID of the banner of this user" |       en-US: "The ID of the banner of this user" | ||||||
|  |  | ||||||
|   bannerUrl: |   bannerUrl: | ||||||
|     type: "string" |     type: "string" | ||||||
|     optional: false |     optional: false | ||||||
|     desc: |     desc: | ||||||
|       ja: "バナーのURL" |       ja-JP: "バナーのURL" | ||||||
|       en: "The URL of the banner of this user" |       en-US: "The URL of the banner of this user" | ||||||
|  |  | ||||||
|   followersCount: |   followersCount: | ||||||
|     type: "number" |     type: "number" | ||||||
|     optional: false |     optional: false | ||||||
|     desc: |     desc: | ||||||
|       ja: "フォロワーの数" |       ja-JP: "フォロワーの数" | ||||||
|       en: "The number of the followers for this user" |       en-US: "The number of the followers for this user" | ||||||
|  |  | ||||||
|   followingCount: |   followingCount: | ||||||
|     type: "number" |     type: "number" | ||||||
|     optional: false |     optional: false | ||||||
|     desc: |     desc: | ||||||
|       ja: "フォローしているユーザーの数" |       ja-JP: "フォローしているユーザーの数" | ||||||
|       en: "The number of the following users for this user" |       en-US: "The number of the following users for this user" | ||||||
|  |  | ||||||
|   isFollowing: |   isFollowing: | ||||||
|     type: "boolean" |     type: "boolean" | ||||||
|     optional: true |     optional: true | ||||||
|     desc: |     desc: | ||||||
|       ja: "自分がこのユーザーをフォローしているか" |       ja-JP: "自分がこのユーザーをフォローしているか" | ||||||
|  |  | ||||||
|   isFollowed: |   isFollowed: | ||||||
|     type: "boolean" |     type: "boolean" | ||||||
|     optional: true |     optional: true | ||||||
|     desc: |     desc: | ||||||
|       ja: "自分がこのユーザーにフォローされているか" |       ja-JP: "自分がこのユーザーにフォローされているか" | ||||||
|  |  | ||||||
|   isMuted: |   isMuted: | ||||||
|     type: "boolean" |     type: "boolean" | ||||||
|     optional: true |     optional: true | ||||||
|     desc: |     desc: | ||||||
|       ja: "自分がこのユーザーをミュートしているか" |       ja-JP: "自分がこのユーザーをミュートしているか" | ||||||
|       en: "Whether you muted this user" |       en-US: "Whether you muted this user" | ||||||
|  |  | ||||||
|   notesCount: |   notesCount: | ||||||
|     type: "number" |     type: "number" | ||||||
|     optional: false |     optional: false | ||||||
|     desc: |     desc: | ||||||
|       ja: "投稿の数" |       ja-JP: "投稿の数" | ||||||
|       en: "The number of the notes of this user" |       en-US: "The number of the notes of this user" | ||||||
|  |  | ||||||
|   pinnedNote: |   pinnedNote: | ||||||
|     type: "entity(Note)" |     type: "entity(Note)" | ||||||
|     optional: true |     optional: true | ||||||
|     desc: |     desc: | ||||||
|       ja: "ピン留めされた投稿" |       ja-JP: "ピン留めされた投稿" | ||||||
|       en: "The pinned note of this user" |       en-US: "The pinned note of this user" | ||||||
|  |  | ||||||
|   pinnedNoteId: |   pinnedNoteId: | ||||||
|     type: "id(Note)" |     type: "id(Note)" | ||||||
|     optional: true |     optional: true | ||||||
|     desc: |     desc: | ||||||
|       ja: "ピン留めされた投稿のID" |       ja-JP: "ピン留めされた投稿のID" | ||||||
|       en: "The ID of the pinned note of this user" |       en-US: "The ID of the pinned note of this user" | ||||||
|  |  | ||||||
|   host: |   host: | ||||||
|     type: "string | null" |     type: "string | null" | ||||||
|     optional: false |     optional: false | ||||||
|     desc: |     desc: | ||||||
|       ja: "ホスト (例: example.com:3000)" |       ja-JP: "ホスト (例: example.com:3000)" | ||||||
|       en: "Host (e.g. example.com:3000)" |       en-US: "Host (e.g. example.com:3000)" | ||||||
|  |  | ||||||
|   twitter: |   twitter: | ||||||
|     type: "object" |     type: "object" | ||||||
|     optional: true |     optional: true | ||||||
|     desc: |     desc: | ||||||
|       ja: "連携されているTwitterアカウント情報" |       ja-JP: "連携されているTwitterアカウント情報" | ||||||
|       en: "The info of the connected twitter account of this user" |       en-US: "The info of the connected twitter account of this user" | ||||||
|  |  | ||||||
|     props: |     props: | ||||||
|       userId: |       userId: | ||||||
|         type: "string" |         type: "string" | ||||||
|         optional: false |         optional: false | ||||||
|         desc: |         desc: | ||||||
|           ja: "ユーザーID" |           ja-JP: "ユーザーID" | ||||||
|           en: "The user ID" |           en-US: "The user ID" | ||||||
|  |  | ||||||
|       screenName: |       screenName: | ||||||
|         type: "string" |         type: "string" | ||||||
|         optional: false |         optional: false | ||||||
|         desc: |         desc: | ||||||
|           ja: "ユーザー名" |           ja-JP: "ユーザー名" | ||||||
|           en: "The screen name of this user" |           en-US: "The screen name of this user" | ||||||
|  |  | ||||||
|   isBot: |   isBot: | ||||||
|     type: "boolean" |     type: "boolean" | ||||||
|     optional: true |     optional: true | ||||||
|     desc: |     desc: | ||||||
|       ja: "botか否か(自己申告であることに留意)" |       ja-JP: "botか否か(自己申告であることに留意)" | ||||||
|       en: "Whether is bot or not" |       en-US: "Whether is bot or not" | ||||||
|  |  | ||||||
|   profile: |   profile: | ||||||
|     type: "object" |     type: "object" | ||||||
|     optional: false |     optional: false | ||||||
|     desc: |     desc: | ||||||
|       ja: "プロフィール" |       ja-JP: "プロフィール" | ||||||
|       en: "The profile of this user" |       en-US: "The profile of this user" | ||||||
|  |  | ||||||
|     props: |     props: | ||||||
|       location: |       location: | ||||||
|         type: "string" |         type: "string" | ||||||
|         optional: true |         optional: true | ||||||
|         desc: |         desc: | ||||||
|           ja: "場所" |           ja-JP: "場所" | ||||||
|           en: "The location of this user" |           en-US: "The location of this user" | ||||||
|  |  | ||||||
|       birthday: |       birthday: | ||||||
|         type: "string" |         type: "string" | ||||||
|         optional: true |         optional: true | ||||||
|         desc: |         desc: | ||||||
|           ja: "誕生日 (YYYY-MM-DD)" |           ja-JP: "誕生日 (YYYY-MM-DD)" | ||||||
|           en: "The birthday of this user (YYYY-MM-DD)" |           en-US: "The birthday of this user (YYYY-MM-DD)" | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ block meta | |||||||
| block main | block main | ||||||
| 	h1= name | 	h1= name | ||||||
|  |  | ||||||
| 	p#desc= desc[lang] || desc['ja'] | 	p#desc= desc[lang] || desc['ja-JP'] | ||||||
|  |  | ||||||
| 	section | 	section | ||||||
| 		h2= i18n('docs.api.entities.properties') | 		h2= i18n('docs.api.entities.properties') | ||||||
|   | |||||||
| @@ -31,4 +31,4 @@ mixin propTable(props) | |||||||
| 					td.name= prop.name | 					td.name= prop.name | ||||||
| 					td.type | 					td.type | ||||||
| 						+type(prop) | 						+type(prop) | ||||||
| 					td.desc!= prop.desc ? prop.desc[lang] || prop.desc['ja'] : null | 					td.desc!= prop.desc ? prop.desc[lang] || prop.desc['ja-JP'] : null | ||||||
|   | |||||||
| @@ -16,7 +16,7 @@ html(lang= lang) | |||||||
| 		nav | 		nav | ||||||
| 			ul | 			ul | ||||||
| 				each doc in docs | 				each doc in docs | ||||||
| 					li: a(href=`/docs/${lang}/${doc.name}`)= doc.title[lang] || doc.title['ja'] | 					li: a(href=`/docs/${lang}/${doc.name}`)= doc.title[lang] || doc.title['ja-JP'] | ||||||
| 			section | 			section | ||||||
| 				h2 API | 				h2 API | ||||||
| 				ul | 				ul | ||||||
|   | |||||||
| @@ -2,7 +2,8 @@ import * as mongo from 'mongodb'; | |||||||
| import db from '../db/mongodb'; | import db from '../db/mongodb'; | ||||||
|  |  | ||||||
| const Stats = db.get<IStats>('stats'); | const Stats = db.get<IStats>('stats'); | ||||||
| Stats.createIndex({ date: -1 }, { unique: true }); | Stats.dropIndex({ date: -1 }); // 後方互換性のため | ||||||
|  | Stats.createIndex({ span: -1, date: -1 }, { unique: true }); | ||||||
| export default Stats; | export default Stats; | ||||||
|  |  | ||||||
| export interface IStats { | export interface IStats { | ||||||
|   | |||||||
| @@ -6,6 +6,8 @@ import parseAcct from '../../../misc/acct/parse'; | |||||||
| import User, { IRemoteUser } from '../../../models/user'; | import User, { IRemoteUser } from '../../../models/user'; | ||||||
| import perform from '../../../remote/activitypub/perform'; | import perform from '../../../remote/activitypub/perform'; | ||||||
| import { resolvePerson } from '../../../remote/activitypub/models/person'; | import { resolvePerson } from '../../../remote/activitypub/models/person'; | ||||||
|  | import { toUnicode } from 'punycode'; | ||||||
|  | import { URL } from 'url'; | ||||||
|  |  | ||||||
| const log = debug('misskey:queue:inbox'); | const log = debug('misskey:queue:inbox'); | ||||||
|  |  | ||||||
| @@ -32,6 +34,15 @@ export default async (job: bq.Job, done: any): Promise<void> => { | |||||||
| 			return; | 			return; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | 		// アクティビティ内のホストの検証 | ||||||
|  | 		try { | ||||||
|  | 			ValidateActivity(activity, host); | ||||||
|  | 		} catch (e) { | ||||||
|  | 			console.warn(e.message); | ||||||
|  | 			done(); | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		user = await User.findOne({ usernameLower: username, host: host.toLowerCase() }) as IRemoteUser; | 		user = await User.findOne({ usernameLower: username, host: host.toLowerCase() }) as IRemoteUser; | ||||||
|  |  | ||||||
| 		// アクティビティを送信してきたユーザーがまだMisskeyサーバーに登録されていなかったら登録する | 		// アクティビティを送信してきたユーザーがまだMisskeyサーバーに登録されていなかったら登録する | ||||||
| @@ -39,6 +50,16 @@ export default async (job: bq.Job, done: any): Promise<void> => { | |||||||
| 			user = await resolvePerson(activity.actor) as IRemoteUser; | 			user = await resolvePerson(activity.actor) as IRemoteUser; | ||||||
| 		} | 		} | ||||||
| 	} else { | 	} else { | ||||||
|  | 		// アクティビティ内のホストの検証 | ||||||
|  | 		const host = toUnicode(new URL(signature.keyId).hostname.toLowerCase()); | ||||||
|  | 		try { | ||||||
|  | 			ValidateActivity(activity, host); | ||||||
|  | 		} catch (e) { | ||||||
|  | 			console.warn(e.message); | ||||||
|  | 			done(); | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		user = await User.findOne({ | 		user = await User.findOne({ | ||||||
| 			host: { $ne: null }, | 			host: { $ne: null }, | ||||||
| 			'publicKey.id': signature.keyId | 			'publicKey.id': signature.keyId | ||||||
| @@ -69,3 +90,40 @@ export default async (job: bq.Job, done: any): Promise<void> => { | |||||||
| 		done(e); | 		done(e); | ||||||
| 	} | 	} | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Validate host in activity | ||||||
|  |  * @param activity Activity | ||||||
|  |  * @param host Expect host | ||||||
|  |  */ | ||||||
|  | function ValidateActivity(activity: any, host: string) { | ||||||
|  | 	// id (if exists) | ||||||
|  | 	if (typeof activity.id === 'string') { | ||||||
|  | 		const uriHost = toUnicode(new URL(activity.id).hostname.toLowerCase()); | ||||||
|  | 		if (host !== uriHost) { | ||||||
|  | 			const diag = activity.signature ? '. Has LD-Signature. Forwarded?' : ''; | ||||||
|  | 			throw new Error(`activity.id(${activity.id}) has different host(${host})${diag}`); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// actor (if exists) | ||||||
|  | 	if (typeof activity.actor === 'string') { | ||||||
|  | 		const uriHost = toUnicode(new URL(activity.actor).hostname.toLowerCase()); | ||||||
|  | 		if (host !== uriHost) throw new Error('activity.actor has different host'); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// For Create activity | ||||||
|  | 	if (activity.type === 'Create' && activity.object) { | ||||||
|  | 		// object.id (if exists) | ||||||
|  | 		if (typeof activity.object.id === 'string') { | ||||||
|  | 			const uriHost = toUnicode(new URL(activity.object.id).hostname.toLowerCase()); | ||||||
|  | 			if (host !== uriHost) throw new Error('activity.object.id has different host'); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		// object.attributedTo (if exists) | ||||||
|  | 		if (typeof activity.object.attributedTo === 'string') { | ||||||
|  | 			const uriHost = toUnicode(new URL(activity.object.attributedTo).hostname.toLowerCase()); | ||||||
|  | 			if (host !== uriHost) throw new Error('activity.object.attributedTo has different host'); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|   | |||||||
| @@ -4,18 +4,25 @@ import * as debug from 'debug'; | |||||||
|  |  | ||||||
| import config from '../../../config'; | import config from '../../../config'; | ||||||
| import User, { validateUsername, isValidName, IUser, IRemoteUser } from '../../../models/user'; | import User, { validateUsername, isValidName, IUser, IRemoteUser } from '../../../models/user'; | ||||||
| import webFinger from '../../webfinger'; |  | ||||||
| import Resolver from '../resolver'; | import Resolver from '../resolver'; | ||||||
| import { resolveImage } from './image'; | import { resolveImage } from './image'; | ||||||
| import { isCollectionOrOrderedCollection, IObject, IPerson } from '../type'; | import { isCollectionOrOrderedCollection, IPerson } from '../type'; | ||||||
| import { IDriveFile } from '../../../models/drive-file'; | import { IDriveFile } from '../../../models/drive-file'; | ||||||
| import Meta from '../../../models/meta'; | import Meta from '../../../models/meta'; | ||||||
| import htmlToMFM from '../../../mfm/html-to-mfm'; | import htmlToMFM from '../../../mfm/html-to-mfm'; | ||||||
| import { updateUserStats } from '../../../services/update-chart'; | import { updateUserStats } from '../../../services/update-chart'; | ||||||
|  | import { URL } from 'url'; | ||||||
|  |  | ||||||
| const log = debug('misskey:activitypub'); | const log = debug('misskey:activitypub'); | ||||||
|  |  | ||||||
| function validatePerson(x: any) { | /** | ||||||
|  |  * Validate Person object | ||||||
|  |  * @param x Fetched person object | ||||||
|  |  * @param uri Fetch target URI | ||||||
|  |  */ | ||||||
|  | function validatePerson(x: any, uri: string) { | ||||||
|  | 	const expectHost = toUnicode(new URL(uri).hostname.toLowerCase()); | ||||||
|  |  | ||||||
| 	if (x == null) { | 	if (x == null) { | ||||||
| 		return new Error('invalid person: object is null'); | 		return new Error('invalid person: object is null'); | ||||||
| 	} | 	} | ||||||
| @@ -40,6 +47,24 @@ function validatePerson(x: any) { | |||||||
| 		return new Error('invalid person: invalid name'); | 		return new Error('invalid person: invalid name'); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	if (typeof x.id !== 'string') { | ||||||
|  | 		return new Error('invalid person: id is not a string'); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	const idHost = toUnicode(new URL(x.id).hostname.toLowerCase()); | ||||||
|  | 	if (idHost !== expectHost) { | ||||||
|  | 		return new Error('invalid person: id has different host'); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (typeof x.publicKey.id !== 'string') { | ||||||
|  | 		return new Error('invalid person: publicKey.id is not a string'); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	const publicKeyIdHost = toUnicode(new URL(x.publicKey.id).hostname.toLowerCase()); | ||||||
|  | 	if (publicKeyIdHost !== expectHost) { | ||||||
|  | 		return new Error('invalid person: publicKey.id has different host'); | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	return null; | 	return null; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -48,8 +73,8 @@ function validatePerson(x: any) { | |||||||
|  * |  * | ||||||
|  * Misskeyに対象のPersonが登録されていればそれを返します。 |  * Misskeyに対象のPersonが登録されていればそれを返します。 | ||||||
|  */ |  */ | ||||||
| export async function fetchPerson(value: string | IObject, resolver?: Resolver): Promise<IUser> { | export async function fetchPerson(uri: string, resolver?: Resolver): Promise<IUser> { | ||||||
| 	const uri = typeof value == 'string' ? value : value.id; | 	if (typeof uri !== 'string') throw 'uri is not string'; | ||||||
|  |  | ||||||
| 	// URIがこのサーバーを指しているならデータベースからフェッチ | 	// URIがこのサーバーを指しているならデータベースからフェッチ | ||||||
| 	if (uri.startsWith(config.url + '/')) { | 	if (uri.startsWith(config.url + '/')) { | ||||||
| @@ -71,12 +96,14 @@ export async function fetchPerson(value: string | IObject, resolver?: Resolver): | |||||||
| /** | /** | ||||||
|  * Personを作成します。 |  * Personを作成します。 | ||||||
|  */ |  */ | ||||||
| export async function createPerson(value: any, resolver?: Resolver): Promise<IUser> { | export async function createPerson(uri: string, resolver?: Resolver): Promise<IUser> { | ||||||
|  | 	if (typeof uri !== 'string') throw 'uri is not string'; | ||||||
|  |  | ||||||
| 	if (resolver == null) resolver = new Resolver(); | 	if (resolver == null) resolver = new Resolver(); | ||||||
|  |  | ||||||
| 	const object = await resolver.resolve(value) as any; | 	const object = await resolver.resolve(uri) as any; | ||||||
|  |  | ||||||
| 	const err = validatePerson(object); | 	const err = validatePerson(object, uri); | ||||||
|  |  | ||||||
| 	if (err) { | 	if (err) { | ||||||
| 		throw err; | 		throw err; | ||||||
| @@ -86,7 +113,7 @@ export async function createPerson(value: any, resolver?: Resolver): Promise<IUs | |||||||
|  |  | ||||||
| 	log(`Creating the Person: ${person.id}`); | 	log(`Creating the Person: ${person.id}`); | ||||||
|  |  | ||||||
| 	const [followersCount = 0, followingCount = 0, notesCount = 0, finger] = await Promise.all([ | 	const [followersCount = 0, followingCount = 0, notesCount = 0] = await Promise.all([ | ||||||
| 		resolver.resolve(person.followers).then( | 		resolver.resolve(person.followers).then( | ||||||
| 			resolved => isCollectionOrOrderedCollection(resolved) ? resolved.totalItems : undefined, | 			resolved => isCollectionOrOrderedCollection(resolved) ? resolved.totalItems : undefined, | ||||||
| 			() => undefined | 			() => undefined | ||||||
| @@ -98,11 +125,10 @@ export async function createPerson(value: any, resolver?: Resolver): Promise<IUs | |||||||
| 		resolver.resolve(person.outbox).then( | 		resolver.resolve(person.outbox).then( | ||||||
| 			resolved => isCollectionOrOrderedCollection(resolved) ? resolved.totalItems : undefined, | 			resolved => isCollectionOrOrderedCollection(resolved) ? resolved.totalItems : undefined, | ||||||
| 			() => undefined | 			() => undefined | ||||||
| 		), | 		) | ||||||
| 		webFinger(person.id) |  | ||||||
| 	]); | 	]); | ||||||
|  |  | ||||||
| 	const host = toUnicode(finger.subject.replace(/^.*?@/, '')).toLowerCase(); | 	const host = toUnicode(new URL(object.id).hostname.toLowerCase()); | ||||||
|  |  | ||||||
| 	const isBot = object.type == 'Service'; | 	const isBot = object.type == 'Service'; | ||||||
|  |  | ||||||
| @@ -192,8 +218,8 @@ export async function createPerson(value: any, resolver?: Resolver): Promise<IUs | |||||||
|  * |  * | ||||||
|  * Misskeyに対象のPersonが登録されていなければ無視します。 |  * Misskeyに対象のPersonが登録されていなければ無視します。 | ||||||
|  */ |  */ | ||||||
| export async function updatePerson(value: string | IObject, resolver?: Resolver): Promise<void> { | export async function updatePerson(uri: string, resolver?: Resolver): Promise<void> { | ||||||
| 	const uri = typeof value == 'string' ? value : value.id; | 	if (typeof uri !== 'string') throw 'uri is not string'; | ||||||
|  |  | ||||||
| 	// URIがこのサーバーを指しているならスキップ | 	// URIがこのサーバーを指しているならスキップ | ||||||
| 	if (uri.startsWith(config.url + '/')) { | 	if (uri.startsWith(config.url + '/')) { | ||||||
| @@ -210,9 +236,9 @@ export async function updatePerson(value: string | IObject, resolver?: Resolver) | |||||||
|  |  | ||||||
| 	if (resolver == null) resolver = new Resolver(); | 	if (resolver == null) resolver = new Resolver(); | ||||||
|  |  | ||||||
| 	const object = await resolver.resolve(value) as any; | 	const object = await resolver.resolve(uri) as any; | ||||||
|  |  | ||||||
| 	const err = validatePerson(object); | 	const err = validatePerson(object, uri); | ||||||
|  |  | ||||||
| 	if (err) { | 	if (err) { | ||||||
| 		throw err; | 		throw err; | ||||||
| @@ -275,8 +301,8 @@ export async function updatePerson(value: string | IObject, resolver?: Resolver) | |||||||
|  * Misskeyに対象のPersonが登録されていればそれを返し、そうでなければ |  * Misskeyに対象のPersonが登録されていればそれを返し、そうでなければ | ||||||
|  * リモートサーバーからフェッチしてMisskeyに登録しそれを返します。 |  * リモートサーバーからフェッチしてMisskeyに登録しそれを返します。 | ||||||
|  */ |  */ | ||||||
| export async function resolvePerson(value: string | IObject, verifier?: string): Promise<IUser> { | export async function resolvePerson(uri: string, verifier?: string): Promise<IUser> { | ||||||
| 	const uri = typeof value == 'string' ? value : value.id; | 	if (typeof uri !== 'string') throw 'uri is not string'; | ||||||
|  |  | ||||||
| 	//#region このサーバーに既に登録されていたらそれを返す | 	//#region このサーバーに既に登録されていたらそれを返す | ||||||
| 	const exist = await fetchPerson(uri); | 	const exist = await fetchPerson(uri); | ||||||
| @@ -287,5 +313,5 @@ export async function resolvePerson(value: string | IObject, verifier?: string): | |||||||
| 	//#endregion | 	//#endregion | ||||||
|  |  | ||||||
| 	// リモートサーバーからフェッチしてきて登録 | 	// リモートサーバーからフェッチしてきて登録 | ||||||
| 	return await createPerson(value); | 	return await createPerson(uri); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -2,6 +2,7 @@ import { request } from 'https'; | |||||||
| const { sign } = require('http-signature'); | const { sign } = require('http-signature'); | ||||||
| import { URL } from 'url'; | import { URL } from 'url'; | ||||||
| import * as debug from 'debug'; | import * as debug from 'debug'; | ||||||
|  | const crypto = require('crypto'); | ||||||
|  |  | ||||||
| import config from '../../config'; | import config from '../../config'; | ||||||
| import { ILocalUser } from '../../models/user'; | import { ILocalUser } from '../../models/user'; | ||||||
| @@ -13,6 +14,12 @@ export default (user: ILocalUser, url: string, object: any) => new Promise((reso | |||||||
|  |  | ||||||
| 	const { protocol, hostname, port, pathname, search } = new URL(url); | 	const { protocol, hostname, port, pathname, search } = new URL(url); | ||||||
|  |  | ||||||
|  | 	const data = JSON.stringify(object); | ||||||
|  |  | ||||||
|  | 	const sha256 = crypto.createHash('sha256'); | ||||||
|  | 	sha256.update(data); | ||||||
|  | 	const hash = sha256.digest('base64'); | ||||||
|  |  | ||||||
| 	const req = request({ | 	const req = request({ | ||||||
| 		protocol, | 		protocol, | ||||||
| 		hostname, | 		hostname, | ||||||
| @@ -20,7 +27,8 @@ export default (user: ILocalUser, url: string, object: any) => new Promise((reso | |||||||
| 		method: 'POST', | 		method: 'POST', | ||||||
| 		path: pathname + search, | 		path: pathname + search, | ||||||
| 		headers: { | 		headers: { | ||||||
| 			'Content-Type': 'application/activity+json' | 			'Content-Type': 'application/activity+json', | ||||||
|  | 			'Digest': `SHA-256=${hash}` | ||||||
| 		} | 		} | ||||||
| 	}, res => { | 	}, res => { | ||||||
| 		log(`${url} --> ${res.statusCode}`); | 		log(`${url} --> ${res.statusCode}`); | ||||||
| @@ -35,7 +43,8 @@ export default (user: ILocalUser, url: string, object: any) => new Promise((reso | |||||||
| 	sign(req, { | 	sign(req, { | ||||||
| 		authorizationHeaderName: 'Signature', | 		authorizationHeaderName: 'Signature', | ||||||
| 		key: user.keypair, | 		key: user.keypair, | ||||||
| 		keyId: `${config.url}/users/${user._id}/publickey` | 		keyId: `${config.url}/users/${user._id}/publickey`, | ||||||
|  | 		headers: ['date', 'host', 'digest'] | ||||||
| 	}); | 	}); | ||||||
|  |  | ||||||
| 	// Signature: Signature ... => Signature: ... | 	// Signature: Signature ... => Signature: ... | ||||||
| @@ -43,5 +52,5 @@ export default (user: ILocalUser, url: string, object: any) => new Promise((reso | |||||||
| 	sig = sig.replace(/^Signature /, ''); | 	sig = sig.replace(/^Signature /, ''); | ||||||
| 	req.setHeader('Signature', sig); | 	req.setHeader('Signature', sig); | ||||||
|  |  | ||||||
| 	req.end(JSON.stringify(object)); | 	req.end(data); | ||||||
| }); | }); | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ import RegistrationTicket from '../../../../models/registration-tickets'; | |||||||
|  |  | ||||||
| export const meta = { | export const meta = { | ||||||
| 	desc: { | 	desc: { | ||||||
| 		ja: '招待コードを発行します。' | 		'ja-JP': '招待コードを発行します。' | ||||||
| 	}, | 	}, | ||||||
|  |  | ||||||
| 	requireCredential: true, | 	requireCredential: true, | ||||||
|   | |||||||
| @@ -5,8 +5,8 @@ import User from '../../../../models/user'; | |||||||
|  |  | ||||||
| export const meta = { | export const meta = { | ||||||
| 	desc: { | 	desc: { | ||||||
| 		ja: '指定したユーザーを凍結します。', | 		'ja-JP': '指定したユーザーを凍結します。', | ||||||
| 		en: 'Suspend a user.' | 		'en-US': 'Suspend a user.' | ||||||
| 	}, | 	}, | ||||||
|  |  | ||||||
| 	requireCredential: true, | 	requireCredential: true, | ||||||
| @@ -15,8 +15,8 @@ export const meta = { | |||||||
| 	params: { | 	params: { | ||||||
| 		userId: $.type(ID).note({ | 		userId: $.type(ID).note({ | ||||||
| 			desc: { | 			desc: { | ||||||
| 				ja: '対象のユーザーID', | 				'ja-JP': '対象のユーザーID', | ||||||
| 				en: 'The user ID which you want to suspend' | 				'en-US': 'The user ID which you want to suspend' | ||||||
| 			} | 			} | ||||||
| 		}), | 		}), | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -5,8 +5,8 @@ import User from '../../../../models/user'; | |||||||
|  |  | ||||||
| export const meta = { | export const meta = { | ||||||
| 	desc: { | 	desc: { | ||||||
| 		ja: '指定したユーザーの凍結を解除します。', | 		'ja-JP': '指定したユーザーの凍結を解除します。', | ||||||
| 		en: 'Unsuspend a user.' | 		'en-US': 'Unsuspend a user.' | ||||||
| 	}, | 	}, | ||||||
|  |  | ||||||
| 	requireCredential: true, | 	requireCredential: true, | ||||||
| @@ -15,8 +15,8 @@ export const meta = { | |||||||
| 	params: { | 	params: { | ||||||
| 		userId: $.type(ID).note({ | 		userId: $.type(ID).note({ | ||||||
| 			desc: { | 			desc: { | ||||||
| 				ja: '対象のユーザーID', | 				'ja-JP': '対象のユーザーID', | ||||||
| 				en: 'The user ID which you want to unsuspend' | 				'en-US': 'The user ID which you want to unsuspend' | ||||||
| 			} | 			} | ||||||
| 		}), | 		}), | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -5,8 +5,8 @@ import User from '../../../../models/user'; | |||||||
|  |  | ||||||
| export const meta = { | export const meta = { | ||||||
| 	desc: { | 	desc: { | ||||||
| 		ja: '指定したユーザーの公式アカウントを解除します。', | 		'ja-JP': '指定したユーザーの公式アカウントを解除します。', | ||||||
| 		en: 'Mark a user as unverified.' | 		'en-US': 'Mark a user as unverified.' | ||||||
| 	}, | 	}, | ||||||
|  |  | ||||||
| 	requireCredential: true, | 	requireCredential: true, | ||||||
| @@ -15,8 +15,8 @@ export const meta = { | |||||||
| 	params: { | 	params: { | ||||||
| 		userId: $.type(ID).note({ | 		userId: $.type(ID).note({ | ||||||
| 			desc: { | 			desc: { | ||||||
| 				ja: '対象のユーザーID', | 				'ja-JP': '対象のユーザーID', | ||||||
| 				en: 'The user ID which you want to unverify' | 				'en-US': 'The user ID which you want to unverify' | ||||||
| 			} | 			} | ||||||
| 		}), | 		}), | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -4,7 +4,7 @@ import getParams from '../../get-params'; | |||||||
|  |  | ||||||
| export const meta = { | export const meta = { | ||||||
| 	desc: { | 	desc: { | ||||||
| 		ja: 'インスタンスの設定を更新します。' | 		'ja-JP': 'インスタンスの設定を更新します。' | ||||||
| 	}, | 	}, | ||||||
|  |  | ||||||
| 	requireCredential: true, | 	requireCredential: true, | ||||||
| @@ -13,7 +13,7 @@ export const meta = { | |||||||
| 	params: { | 	params: { | ||||||
| 		disableRegistration: $.bool.optional.nullable.note({ | 		disableRegistration: $.bool.optional.nullable.note({ | ||||||
| 			desc: { | 			desc: { | ||||||
| 				ja: '招待制か否か' | 				'ja-JP': '招待制か否か' | ||||||
| 			} | 			} | ||||||
| 		}), | 		}), | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -5,8 +5,8 @@ import User from '../../../../models/user'; | |||||||
|  |  | ||||||
| export const meta = { | export const meta = { | ||||||
| 	desc: { | 	desc: { | ||||||
| 		ja: '指定したユーザーを公式アカウントにします。', | 		'ja-JP': '指定したユーザーを公式アカウントにします。', | ||||||
| 		en: 'Mark a user as verified.' | 		'en-US': 'Mark a user as verified.' | ||||||
| 	}, | 	}, | ||||||
|  |  | ||||||
| 	requireCredential: true, | 	requireCredential: true, | ||||||
| @@ -15,8 +15,8 @@ export const meta = { | |||||||
| 	params: { | 	params: { | ||||||
| 		userId: $.type(ID).note({ | 		userId: $.type(ID).note({ | ||||||
| 			desc: { | 			desc: { | ||||||
| 				ja: '対象のユーザーID', | 				'ja-JP': '対象のユーザーID', | ||||||
| 				en: 'The user ID which you want to verify' | 				'en-US': 'The user ID which you want to verify' | ||||||
| 			} | 			} | ||||||
| 		}), | 		}), | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -1,4 +1,6 @@ | |||||||
|  | import $ from 'cafy'; | ||||||
| import Stats, { IStats } from '../../../models/stats'; | import Stats, { IStats } from '../../../models/stats'; | ||||||
|  | import getParams from '../get-params'; | ||||||
|  |  | ||||||
| type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>; | type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>; | ||||||
|  |  | ||||||
| @@ -44,11 +46,26 @@ function migrateStats(stats: IStats[]) { | |||||||
| } | } | ||||||
|  |  | ||||||
| export const meta = { | export const meta = { | ||||||
|  | 	desc: { | ||||||
|  | 		'ja-JP': 'インスタンスの統計を取得します。' | ||||||
|  | 	}, | ||||||
|  |  | ||||||
|  | 	params: { | ||||||
|  | 		limit: $.num.optional.range(1, 100).note({ | ||||||
|  | 			default: 30, | ||||||
|  | 			desc: { | ||||||
|  | 				'ja-JP': '最大数' | ||||||
|  | 			} | ||||||
|  | 		}), | ||||||
|  | 	} | ||||||
| }; | }; | ||||||
|  |  | ||||||
| export default (params: any) => new Promise(async (res, rej) => { | export default (params: any) => new Promise(async (res, rej) => { | ||||||
| 	const daysRange = 30; | 	const [ps, psErr] = getParams(meta, params); | ||||||
| 	const hoursRange = 30; | 	if (psErr) throw psErr; | ||||||
|  |  | ||||||
|  | 	const daysRange = ps.limit; | ||||||
|  | 	const hoursRange = ps.limit; | ||||||
|  |  | ||||||
| 	const now = new Date(); | 	const now = new Date(); | ||||||
| 	const y = now.getFullYear(); | 	const y = now.getFullYear(); | ||||||
|   | |||||||
| @@ -4,8 +4,8 @@ import config from '../../../config'; | |||||||
|  |  | ||||||
| export const meta = { | export const meta = { | ||||||
| 	desc: { | 	desc: { | ||||||
| 		ja: 'ドライブの情報を取得します。', | 		'ja-JP': 'ドライブの情報を取得します。', | ||||||
| 		en: 'Get drive information.' | 		'en-US': 'Get drive information.' | ||||||
| 	}, | 	}, | ||||||
|  |  | ||||||
| 	requireCredential: true, | 	requireCredential: true, | ||||||
|   | |||||||
| @@ -4,8 +4,8 @@ import { ILocalUser } from '../../../../models/user'; | |||||||
|  |  | ||||||
| export const meta = { | export const meta = { | ||||||
| 	desc: { | 	desc: { | ||||||
| 		ja: 'ドライブのファイル一覧を取得します。', | 		'ja-JP': 'ドライブのファイル一覧を取得します。', | ||||||
| 		en: 'Get files of drive.' | 		'en-US': 'Get files of drive.' | ||||||
| 	}, | 	}, | ||||||
|  |  | ||||||
| 	requireCredential: true, | 	requireCredential: true, | ||||||
|   | |||||||
| @@ -8,8 +8,8 @@ import getParams from '../../../get-params'; | |||||||
|  |  | ||||||
| export const meta = { | export const meta = { | ||||||
| 	desc: { | 	desc: { | ||||||
| 		ja: 'ドライブにファイルをアップロードします。', | 		'ja-JP': 'ドライブにファイルをアップロードします。', | ||||||
| 		en: 'Upload a file to drive.' | 		'en-US': 'Upload a file to drive.' | ||||||
| 	}, | 	}, | ||||||
|  |  | ||||||
| 	requireCredential: true, | 	requireCredential: true, | ||||||
| @@ -27,15 +27,15 @@ export const meta = { | |||||||
| 		folderId: $.type(ID).optional.nullable.note({ | 		folderId: $.type(ID).optional.nullable.note({ | ||||||
| 			default: null, | 			default: null, | ||||||
| 			desc: { | 			desc: { | ||||||
| 				ja: 'フォルダID' | 				'ja-JP': 'フォルダID' | ||||||
| 			} | 			} | ||||||
| 		}), | 		}), | ||||||
|  |  | ||||||
| 		isSensitive: $.bool.optional.note({ | 		isSensitive: $.bool.optional.note({ | ||||||
| 			default: false, | 			default: false, | ||||||
| 			desc: { | 			desc: { | ||||||
| 				ja: 'このメディアが「閲覧注意」(NSFW)かどうか', | 				'ja-JP': 'このメディアが「閲覧注意」(NSFW)かどうか', | ||||||
| 				en: 'Whether this media is NSFW' | 				'en-US': 'Whether this media is NSFW' | ||||||
| 			} | 			} | ||||||
| 		}) | 		}) | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -6,8 +6,8 @@ import { ILocalUser } from '../../../../../models/user'; | |||||||
|  |  | ||||||
| export const meta = { | export const meta = { | ||||||
| 	desc: { | 	desc: { | ||||||
| 		ja: 'ドライブのファイルを削除します。', | 		'ja-JP': 'ドライブのファイルを削除します。', | ||||||
| 		en: 'Delete a file of drive.' | 		'en-US': 'Delete a file of drive.' | ||||||
| 	}, | 	}, | ||||||
|  |  | ||||||
| 	requireCredential: true, | 	requireCredential: true, | ||||||
|   | |||||||
| @@ -4,8 +4,8 @@ import { ILocalUser } from '../../../../../models/user'; | |||||||
|  |  | ||||||
| export const meta = { | export const meta = { | ||||||
| 	desc: { | 	desc: { | ||||||
| 		ja: '指定したドライブのファイルの情報を取得します。', | 		'ja-JP': '指定したドライブのファイルの情報を取得します。', | ||||||
| 		en: 'Get specified file of drive.' | 		'en-US': 'Get specified file of drive.' | ||||||
| 	}, | 	}, | ||||||
|  |  | ||||||
| 	requireCredential: true, | 	requireCredential: true, | ||||||
|   | |||||||
| @@ -7,8 +7,8 @@ import getParams from '../../../get-params'; | |||||||
|  |  | ||||||
| export const meta = { | export const meta = { | ||||||
| 	desc: { | 	desc: { | ||||||
| 		ja: '指定したドライブのファイルの情報を更新します。', | 		'ja-JP': '指定したドライブのファイルの情報を更新します。', | ||||||
| 		en: 'Update specified file of drive.' | 		'en-US': 'Update specified file of drive.' | ||||||
| 	}, | 	}, | ||||||
|  |  | ||||||
| 	requireCredential: true, | 	requireCredential: true, | ||||||
| @@ -18,30 +18,30 @@ export const meta = { | |||||||
| 	params: { | 	params: { | ||||||
| 		fileId: $.type(ID).note({ | 		fileId: $.type(ID).note({ | ||||||
| 			desc: { | 			desc: { | ||||||
| 				ja: '対象のファイルID' | 				'ja-JP': '対象のファイルID' | ||||||
| 			} | 			} | ||||||
| 		}), | 		}), | ||||||
|  |  | ||||||
| 		folderId: $.type(ID).optional.nullable.note({ | 		folderId: $.type(ID).optional.nullable.note({ | ||||||
| 			default: undefined, | 			default: undefined, | ||||||
| 			desc: { | 			desc: { | ||||||
| 				ja: 'フォルダID' | 				'ja-JP': 'フォルダID' | ||||||
| 			} | 			} | ||||||
| 		}), | 		}), | ||||||
|  |  | ||||||
| 		name: $.str.optional.pipe(validateFileName).note({ | 		name: $.str.optional.pipe(validateFileName).note({ | ||||||
| 			default: undefined, | 			default: undefined, | ||||||
| 			desc: { | 			desc: { | ||||||
| 				ja: 'ファイル名', | 				'ja-JP': 'ファイル名', | ||||||
| 				en: 'Name of the file' | 				'en-US': 'Name of the file' | ||||||
| 			} | 			} | ||||||
| 		}), | 		}), | ||||||
|  |  | ||||||
| 		isSensitive: $.bool.optional.note({ | 		isSensitive: $.bool.optional.note({ | ||||||
| 			default: undefined, | 			default: undefined, | ||||||
| 			desc: { | 			desc: { | ||||||
| 				ja: 'このメディアが「閲覧注意」(NSFW)かどうか', | 				'ja-JP': 'このメディアが「閲覧注意」(NSFW)かどうか', | ||||||
| 				en: 'Whether this media is NSFW' | 				'en-US': 'Whether this media is NSFW' | ||||||
| 			} | 			} | ||||||
| 		}) | 		}) | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -6,7 +6,7 @@ import { ILocalUser } from '../../../../../models/user'; | |||||||
|  |  | ||||||
| export const meta = { | export const meta = { | ||||||
| 	desc: { | 	desc: { | ||||||
| 		ja: 'ドライブに指定されたURLに存在するファイルをアップロードします。' | 		'ja-JP': 'ドライブに指定されたURLに存在するファイルをアップロードします。' | ||||||
| 	}, | 	}, | ||||||
|  |  | ||||||
| 	limit: { | 	limit: { | ||||||
|   | |||||||
| @@ -4,8 +4,8 @@ import { ILocalUser } from '../../../../models/user'; | |||||||
|  |  | ||||||
| export const meta = { | export const meta = { | ||||||
| 	desc: { | 	desc: { | ||||||
| 		ja: 'ドライブのフォルダ一覧を取得します。', | 		'ja-JP': 'ドライブのフォルダ一覧を取得します。', | ||||||
| 		en: 'Get folders of drive.' | 		'en-US': 'Get folders of drive.' | ||||||
| 	}, | 	}, | ||||||
|  |  | ||||||
| 	requireCredential: true, | 	requireCredential: true, | ||||||
|   | |||||||
| @@ -5,8 +5,8 @@ import { ILocalUser } from '../../../../../models/user'; | |||||||
|  |  | ||||||
| export const meta = { | export const meta = { | ||||||
| 	desc: { | 	desc: { | ||||||
| 		ja: 'ドライブのフォルダを作成します。', | 		'ja-JP': 'ドライブのフォルダを作成します。', | ||||||
| 		en: 'Create a folder of drive.' | 		'en-US': 'Create a folder of drive.' | ||||||
| 	}, | 	}, | ||||||
|  |  | ||||||
| 	requireCredential: true, | 	requireCredential: true, | ||||||
|   | |||||||
| @@ -4,7 +4,7 @@ import { ILocalUser } from '../../../../../models/user'; | |||||||
|  |  | ||||||
| export const meta = { | export const meta = { | ||||||
| 	desc: { | 	desc: { | ||||||
| 		ja: '指定したドライブのフォルダの情報を取得します。' | 		'ja-JP': '指定したドライブのフォルダの情報を取得します。' | ||||||
| 	}, | 	}, | ||||||
|  |  | ||||||
| 	requireCredential: true, | 	requireCredential: true, | ||||||
|   | |||||||
| @@ -5,8 +5,8 @@ import { ILocalUser } from '../../../../../models/user'; | |||||||
|  |  | ||||||
| export const meta = { | export const meta = { | ||||||
| 	desc: { | 	desc: { | ||||||
| 		ja: '指定したドライブのフォルダの情報を更新します。', | 		'ja-JP': '指定したドライブのフォルダの情報を更新します。', | ||||||
| 		en: 'Update specified folder of drive.' | 		'en-US': 'Update specified folder of drive.' | ||||||
| 	}, | 	}, | ||||||
|  |  | ||||||
| 	requireCredential: true, | 	requireCredential: true, | ||||||
|   | |||||||
| @@ -6,8 +6,8 @@ import create from '../../../../services/following/create'; | |||||||
|  |  | ||||||
| export const meta = { | export const meta = { | ||||||
| 	desc: { | 	desc: { | ||||||
| 		ja: '指定したユーザーをフォローします。', | 		'ja-JP': '指定したユーザーをフォローします。', | ||||||
| 		en: 'Follow a user.' | 		'en-US': 'Follow a user.' | ||||||
| 	}, | 	}, | ||||||
|  |  | ||||||
| 	limit: { | 	limit: { | ||||||
|   | |||||||
| @@ -6,8 +6,8 @@ import deleteFollowing from '../../../../services/following/delete'; | |||||||
|  |  | ||||||
| export const meta = { | export const meta = { | ||||||
| 	desc: { | 	desc: { | ||||||
| 		ja: '指定したユーザーのフォローを解除します。', | 		'ja-JP': '指定したユーザーのフォローを解除します。', | ||||||
| 		en: 'Unfollow a user.' | 		'en-US': 'Unfollow a user.' | ||||||
| 	}, | 	}, | ||||||
|  |  | ||||||
| 	limit: { | 	limit: { | ||||||
|   | |||||||
| @@ -4,8 +4,8 @@ import User, { ILocalUser } from '../../../../../models/user'; | |||||||
|  |  | ||||||
| export const meta = { | export const meta = { | ||||||
| 	desc: { | 	desc: { | ||||||
| 		ja: '自分に届いた、指定したフォローリクエストを承認します。', | 		'ja-JP': '自分に届いた、指定したフォローリクエストを承認します。', | ||||||
| 		en: 'Accept a follow request.' | 		'en-US': 'Accept a follow request.' | ||||||
| 	}, | 	}, | ||||||
|  |  | ||||||
| 	requireCredential: true, | 	requireCredential: true, | ||||||
|   | |||||||
| @@ -4,8 +4,8 @@ import User, { pack, ILocalUser } from '../../../../../models/user'; | |||||||
|  |  | ||||||
| export const meta = { | export const meta = { | ||||||
| 	desc: { | 	desc: { | ||||||
| 		ja: '自分が作成した、指定したフォローリクエストをキャンセルします。', | 		'ja-JP': '自分が作成した、指定したフォローリクエストをキャンセルします。', | ||||||
| 		en: 'Cancel a follow request.' | 		'en-US': 'Cancel a follow request.' | ||||||
| 	}, | 	}, | ||||||
|  |  | ||||||
| 	requireCredential: true, | 	requireCredential: true, | ||||||
|   | |||||||
| @@ -4,8 +4,8 @@ import { ILocalUser } from '../../../../../models/user'; | |||||||
|  |  | ||||||
| export const meta = { | export const meta = { | ||||||
| 	desc: { | 	desc: { | ||||||
| 		ja: '自分に届いたフォローリクエストの一覧を取得します。', | 		'ja-JP': '自分に届いたフォローリクエストの一覧を取得します。', | ||||||
| 		en: 'Get all pending received follow requests.' | 		'en-US': 'Get all pending received follow requests.' | ||||||
| 	}, | 	}, | ||||||
|  |  | ||||||
| 	requireCredential: true, | 	requireCredential: true, | ||||||
|   | |||||||
| @@ -4,8 +4,8 @@ import User, { ILocalUser } from '../../../../../models/user'; | |||||||
|  |  | ||||||
| export const meta = { | export const meta = { | ||||||
| 	desc: { | 	desc: { | ||||||
| 		ja: '自分に届いた、指定したフォローリクエストを拒否します。', | 		'ja-JP': '自分に届いた、指定したフォローリクエストを拒否します。', | ||||||
| 		en: 'Reject a follow request.' | 		'en-US': 'Reject a follow request.' | ||||||
| 	}, | 	}, | ||||||
|  |  | ||||||
| 	requireCredential: true, | 	requireCredential: true, | ||||||
|   | |||||||
| @@ -4,8 +4,8 @@ import { ILocalUser } from '../../../../models/user'; | |||||||
|  |  | ||||||
| export const meta = { | export const meta = { | ||||||
| 	desc: { | 	desc: { | ||||||
| 		ja: '指定したユーザーをストーキングします。', | 		'ja-JP': '指定したユーザーをストーキングします。', | ||||||
| 		en: 'Stalk a user.' | 		'en-US': 'Stalk a user.' | ||||||
| 	}, | 	}, | ||||||
|  |  | ||||||
| 	requireCredential: true, | 	requireCredential: true, | ||||||
|   | |||||||
| @@ -4,8 +4,8 @@ import { ILocalUser } from '../../../../models/user'; | |||||||
|  |  | ||||||
| export const meta = { | export const meta = { | ||||||
| 	desc: { | 	desc: { | ||||||
| 		ja: '指定したユーザーのストーキングをやめます。', | 		'ja-JP': '指定したユーザーのストーキングをやめます。', | ||||||
| 		en: 'Unstalk a user.' | 		'en-US': 'Unstalk a user.' | ||||||
| 	}, | 	}, | ||||||
|  |  | ||||||
| 	requireCredential: true, | 	requireCredential: true, | ||||||
|   | |||||||
| @@ -6,7 +6,7 @@ import { publishReversiGameStream } from '../../../../../../stream'; | |||||||
|  |  | ||||||
| export const meta = { | export const meta = { | ||||||
| 	desc: { | 	desc: { | ||||||
| 		ja: '指定したリバーシの対局で投了します。' | 		'ja-JP': '指定したリバーシの対局で投了します。' | ||||||
| 	}, | 	}, | ||||||
|  |  | ||||||
| 	requireCredential: true, | 	requireCredential: true, | ||||||
| @@ -14,7 +14,7 @@ export const meta = { | |||||||
| 	params: { | 	params: { | ||||||
| 		gameId: $.type(ID).note({ | 		gameId: $.type(ID).note({ | ||||||
| 			desc: { | 			desc: { | ||||||
| 				ja: '投了したい対局' | 				'ja-JP': '投了したい対局' | ||||||
| 			} | 			} | ||||||
| 		}) | 		}) | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ const escapeRegexp = require('escape-regexp'); | |||||||
|  |  | ||||||
| export const meta = { | export const meta = { | ||||||
| 	desc: { | 	desc: { | ||||||
| 		ja: 'ハッシュタグを検索します。' | 		'ja-JP': 'ハッシュタグを検索します。' | ||||||
| 	}, | 	}, | ||||||
|  |  | ||||||
| 	requireCredential: false, | 	requireCredential: false, | ||||||
| @@ -14,20 +14,20 @@ export const meta = { | |||||||
| 		limit: $.num.optional.range(1, 100).note({ | 		limit: $.num.optional.range(1, 100).note({ | ||||||
| 			default: 10, | 			default: 10, | ||||||
| 			desc: { | 			desc: { | ||||||
| 				ja: '最大数' | 				'ja-JP': '最大数' | ||||||
| 			} | 			} | ||||||
| 		}), | 		}), | ||||||
|  |  | ||||||
| 		query: $.str.note({ | 		query: $.str.note({ | ||||||
| 			desc: { | 			desc: { | ||||||
| 				ja: 'クエリ' | 				'ja-JP': 'クエリ' | ||||||
| 			} | 			} | ||||||
| 		}), | 		}), | ||||||
|  |  | ||||||
| 		offset: $.num.optional.min(0).note({ | 		offset: $.num.optional.min(0).note({ | ||||||
| 			default: 0, | 			default: 0, | ||||||
| 			desc: { | 			desc: { | ||||||
| 				ja: 'オフセット' | 				'ja-JP': 'オフセット' | ||||||
| 			} | 			} | ||||||
| 		}) | 		}) | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ import { IApp } from '../../../models/app'; | |||||||
|  |  | ||||||
| export const meta = { | export const meta = { | ||||||
| 	desc: { | 	desc: { | ||||||
| 		ja: '自分のアカウント情報を取得します。' | 		'ja-JP': '自分のアカウント情報を取得します。' | ||||||
| 	}, | 	}, | ||||||
|  |  | ||||||
| 	requireCredential: true, | 	requireCredential: true, | ||||||
|   | |||||||
| @@ -4,8 +4,8 @@ import { ILocalUser } from '../../../../models/user'; | |||||||
|  |  | ||||||
| export const meta = { | export const meta = { | ||||||
| 	desc: { | 	desc: { | ||||||
| 		ja: 'お気に入りに登録した投稿一覧を取得します。', | 		'ja-JP': 'お気に入りに登録した投稿一覧を取得します。', | ||||||
| 		en: 'Get favorited notes' | 		'en-US': 'Get favorited notes' | ||||||
| 	}, | 	}, | ||||||
|  |  | ||||||
| 	requireCredential: true, | 	requireCredential: true, | ||||||
|   | |||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user