Merge branch 'master' into greenkeeper/@types/mongodb-2.2.4
This commit is contained in:
		
						commit
						cb4b120548
					
				
					 44 changed files with 1323 additions and 374 deletions
				
			
		
							
								
								
									
										1
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							| 
						 | 
					@ -7,3 +7,4 @@ npm-debug.log
 | 
				
			||||||
*.pem
 | 
					*.pem
 | 
				
			||||||
run.bat
 | 
					run.bat
 | 
				
			||||||
api-docs.json
 | 
					api-docs.json
 | 
				
			||||||
 | 
					package-lock.json
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,10 +16,10 @@ Key features
 | 
				
			||||||
----------------------------------------------------------------
 | 
					----------------------------------------------------------------
 | 
				
			||||||
* Automatically updated timeline
 | 
					* Automatically updated timeline
 | 
				
			||||||
* Private messages
 | 
					* Private messages
 | 
				
			||||||
* Free 1GB storage
 | 
					* Free 1GB storage for each all users
 | 
				
			||||||
* Mobile device support (smartphone, tablet, etc)
 | 
					* Mobile device support (smartphone, tablet, etc)
 | 
				
			||||||
* Web API for third-party applications
 | 
					* Web API for third-party applications
 | 
				
			||||||
* Twitter integration
 | 
					* No ads
 | 
				
			||||||
 | 
					
 | 
				
			||||||
and more! You can touch with your own eyes at https://misskey.xyz/.
 | 
					and more! You can touch with your own eyes at https://misskey.xyz/.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -45,6 +45,8 @@ common:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    mk-messaging-room:
 | 
					    mk-messaging-room:
 | 
				
			||||||
      empty: "No conversations"
 | 
					      empty: "No conversations"
 | 
				
			||||||
 | 
					      more: "More"
 | 
				
			||||||
 | 
					      no-history: "There is no more history"
 | 
				
			||||||
      resize-form: "Drag to resize"
 | 
					      resize-form: "Drag to resize"
 | 
				
			||||||
      new-message: "New message"
 | 
					      new-message: "New message"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -52,7 +54,7 @@ common:
 | 
				
			||||||
      no-apps: "No apps"
 | 
					      no-apps: "No apps"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    mk-error:
 | 
					    mk-error:
 | 
				
			||||||
      title: "Cannot connect to the server"
 | 
					      title: "Unable to connect to the server"
 | 
				
			||||||
      description: "インターネット回線に問題があるか、サーバーがダウンまたはメンテナンスしている可能性があります。しばらくしてから再度お試しください。"
 | 
					      description: "インターネット回線に問題があるか、サーバーがダウンまたはメンテナンスしている可能性があります。しばらくしてから再度お試しください。"
 | 
				
			||||||
      thanks: "Thank you for using Misskey."
 | 
					      thanks: "Thank you for using Misskey."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -219,7 +221,7 @@ desktop:
 | 
				
			||||||
      attach-media-from-local: "Attach media from your pc"
 | 
					      attach-media-from-local: "Attach media from your pc"
 | 
				
			||||||
      attach-media-from-drive: "Attach media from the drive"
 | 
					      attach-media-from-drive: "Attach media from the drive"
 | 
				
			||||||
      attach-cancel: "Cancel attachment"
 | 
					      attach-cancel: "Cancel attachment"
 | 
				
			||||||
      insert-the-cat: "Insert a cat"
 | 
					      insert-a-kao: "v(‘ω’)v"
 | 
				
			||||||
      create-poll: "Create a poll"
 | 
					      create-poll: "Create a poll"
 | 
				
			||||||
      text-remain: "{} chars remaining"
 | 
					      text-remain: "{} chars remaining"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -243,8 +245,13 @@ desktop:
 | 
				
			||||||
      title: "Notifications"
 | 
					      title: "Notifications"
 | 
				
			||||||
      settings: "Notification settings"
 | 
					      settings: "Notification settings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    mk-server-home-widget:
 | 
				
			||||||
 | 
					      title: "Server info"
 | 
				
			||||||
 | 
					      toggle: "Toggle views"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    mk-activity-home-widget:
 | 
					    mk-activity-home-widget:
 | 
				
			||||||
      title: "Activity"
 | 
					      title: "Activity"
 | 
				
			||||||
 | 
					      toggle: "Toggle views"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    mk-user-recommendation-home-widget:
 | 
					    mk-user-recommendation-home-widget:
 | 
				
			||||||
      title: "Recommended users"
 | 
					      title: "Recommended users"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -45,6 +45,8 @@ common:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    mk-messaging-room:
 | 
					    mk-messaging-room:
 | 
				
			||||||
      empty: "このユーザーと話したことはありません"
 | 
					      empty: "このユーザーと話したことはありません"
 | 
				
			||||||
 | 
					      more: "もっと読む"
 | 
				
			||||||
 | 
					      no-history: "これより過去の履歴はありません"
 | 
				
			||||||
      resize-form: "ドラッグしてフォームの広さを調整"
 | 
					      resize-form: "ドラッグしてフォームの広さを調整"
 | 
				
			||||||
      new-message: "新しいメッセージがあります"
 | 
					      new-message: "新しいメッセージがあります"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -219,7 +221,7 @@ desktop:
 | 
				
			||||||
      attach-media-from-local: "PCからメディアを添付"
 | 
					      attach-media-from-local: "PCからメディアを添付"
 | 
				
			||||||
      attach-media-from-drive: "ドライブからメディアを添付"
 | 
					      attach-media-from-drive: "ドライブからメディアを添付"
 | 
				
			||||||
      attach-cancel: "添付取り消し"
 | 
					      attach-cancel: "添付取り消し"
 | 
				
			||||||
      insert-the-cat: "猫挿入"
 | 
					      insert-a-kao: "v(‘ω’)v"
 | 
				
			||||||
      create-poll: "投票を作成"
 | 
					      create-poll: "投票を作成"
 | 
				
			||||||
      text-remain: "のこり{}文字"
 | 
					      text-remain: "のこり{}文字"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -243,8 +245,13 @@ desktop:
 | 
				
			||||||
      title: "通知"
 | 
					      title: "通知"
 | 
				
			||||||
      settings: "通知の設定"
 | 
					      settings: "通知の設定"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    mk-server-home-widget:
 | 
				
			||||||
 | 
					      title: "サーバー情報"
 | 
				
			||||||
 | 
					      toggle: "表示を切り替え"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    mk-activity-home-widget:
 | 
					    mk-activity-home-widget:
 | 
				
			||||||
      title: "アクティビティ"
 | 
					      title: "アクティビティ"
 | 
				
			||||||
 | 
					      toggle: "表示を切り替え"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    mk-user-recommendation-home-widget:
 | 
					    mk-user-recommendation-home-widget:
 | 
				
			||||||
      title: "おすすめユーザー"
 | 
					      title: "おすすめユーザー"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										299
									
								
								package.json
									
										
									
									
									
								
							
							
						
						
									
										299
									
								
								package.json
									
										
									
									
									
								
							| 
						 | 
					@ -1,150 +1,153 @@
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	"name": "misskey",
 | 
					  "name": "misskey",
 | 
				
			||||||
	"author": "syuilo <i@syuilo.com>",
 | 
					  "author": "syuilo <i@syuilo.com>",
 | 
				
			||||||
	"version": "0.0.2027",
 | 
					  "version": "0.0.2097",
 | 
				
			||||||
	"license": "MIT",
 | 
					  "license": "MIT",
 | 
				
			||||||
	"description": "A miniblog-based SNS",
 | 
					  "description": "A miniblog-based SNS",
 | 
				
			||||||
	"bugs": "https://github.com/syuilo/misskey/issues",
 | 
					  "bugs": "https://github.com/syuilo/misskey/issues",
 | 
				
			||||||
	"repository": "https://github.com/syuilo/misskey.git",
 | 
					  "repository": "https://github.com/syuilo/misskey.git",
 | 
				
			||||||
	"main": "./built/index.js",
 | 
					  "main": "./built/index.js",
 | 
				
			||||||
	"private": true,
 | 
					  "private": true,
 | 
				
			||||||
	"scripts": {
 | 
					  "scripts": {
 | 
				
			||||||
		"config": "node ./tools/init.js",
 | 
					    "config": "node ./tools/init.js",
 | 
				
			||||||
		"start": "node ./built",
 | 
					    "start": "node ./built",
 | 
				
			||||||
		"debug": "DEBUG=misskey:* node ./built",
 | 
					    "debug": "DEBUG=misskey:* node ./built",
 | 
				
			||||||
		"swagger": "node ./swagger.js",
 | 
					    "swagger": "node ./swagger.js",
 | 
				
			||||||
		"build": "gulp build",
 | 
					    "build": "gulp build",
 | 
				
			||||||
		"rebuild": "gulp rebuild",
 | 
					    "rebuild": "gulp rebuild",
 | 
				
			||||||
		"clean": "gulp clean",
 | 
					    "clean": "gulp clean",
 | 
				
			||||||
		"cleanall": "gulp cleanall",
 | 
					    "cleanall": "gulp cleanall",
 | 
				
			||||||
		"lint": "gulp lint",
 | 
					    "lint": "gulp lint",
 | 
				
			||||||
		"test": "gulp test"
 | 
					    "test": "gulp test"
 | 
				
			||||||
	},
 | 
					  },
 | 
				
			||||||
	"devDependencies": {
 | 
					  "devDependencies": {
 | 
				
			||||||
		"@types/bcryptjs": "2.4.0",
 | 
					    "@types/bcryptjs": "2.4.0",
 | 
				
			||||||
		"@types/body-parser": "1.16.3",
 | 
					    "@types/body-parser": "1.16.3",
 | 
				
			||||||
		"@types/chai": "4.0.0",
 | 
					    "@types/chai": "4.0.0",
 | 
				
			||||||
		"@types/chai-http": "0.0.30",
 | 
					    "@types/chai-http": "0.0.30",
 | 
				
			||||||
		"@types/chalk": "0.4.31",
 | 
					    "@types/chalk": "0.4.31",
 | 
				
			||||||
		"@types/compression": "0.0.33",
 | 
					    "@types/compression": "0.0.33",
 | 
				
			||||||
		"@types/cors": "2.8.1",
 | 
					    "@types/cors": "2.8.1",
 | 
				
			||||||
		"@types/debug": "0.0.29",
 | 
					    "@types/debug": "0.0.29",
 | 
				
			||||||
		"@types/deep-equal": "1.0.0",
 | 
					    "@types/deep-equal": "1.0.0",
 | 
				
			||||||
		"@types/elasticsearch": "5.0.13",
 | 
					    "@types/elasticsearch": "5.0.13",
 | 
				
			||||||
		"@types/event-stream": "3.3.31",
 | 
					    "@types/event-stream": "3.3.31",
 | 
				
			||||||
		"@types/express": "4.0.35",
 | 
					    "@types/express": "4.0.35",
 | 
				
			||||||
		"@types/gm": "1.17.31",
 | 
					    "@types/gm": "1.17.31",
 | 
				
			||||||
		"@types/gulp": "4.0.3",
 | 
					    "@types/gulp": "4.0.3",
 | 
				
			||||||
		"@types/gulp-mocha": "0.0.30",
 | 
					    "@types/gulp-mocha": "0.0.30",
 | 
				
			||||||
		"@types/gulp-rename": "0.0.32",
 | 
					    "@types/gulp-rename": "0.0.32",
 | 
				
			||||||
		"@types/gulp-replace": "0.0.30",
 | 
					    "@types/gulp-replace": "0.0.30",
 | 
				
			||||||
		"@types/gulp-tslint": "3.6.31",
 | 
					    "@types/gulp-tslint": "3.6.31",
 | 
				
			||||||
		"@types/gulp-typescript": "2.13.0",
 | 
					    "@types/gulp-typescript": "2.13.0",
 | 
				
			||||||
		"@types/gulp-uglify": "0.0.30",
 | 
					    "@types/gulp-uglify": "0.0.30",
 | 
				
			||||||
		"@types/gulp-util": "3.0.31",
 | 
					    "@types/gulp-util": "3.0.31",
 | 
				
			||||||
		"@types/inquirer": "0.0.34",
 | 
					    "@types/inquirer": "0.0.34",
 | 
				
			||||||
		"@types/is-root": "1.0.0",
 | 
					    "@types/is-root": "1.0.0",
 | 
				
			||||||
		"@types/is-url": "1.2.28",
 | 
					    "@types/is-url": "1.2.28",
 | 
				
			||||||
		"@types/js-yaml": "3.5.30",
 | 
					    "@types/js-yaml": "3.5.30",
 | 
				
			||||||
		"@types/mocha": "2.2.41",
 | 
					    "@types/mocha": "2.2.41",
 | 
				
			||||||
		"@types/mongodb": "2.2.4",
 | 
					    "@types/mongodb": "2.2.4",
 | 
				
			||||||
		"@types/monk": "1.0.5",
 | 
					    "@types/monk": "1.0.5",
 | 
				
			||||||
		"@types/morgan": "1.7.32",
 | 
					    "@types/morgan": "1.7.32",
 | 
				
			||||||
		"@types/ms": "0.7.29",
 | 
					    "@types/ms": "0.7.29",
 | 
				
			||||||
		"@types/multer": "0.0.34",
 | 
					    "@types/multer": "0.0.34",
 | 
				
			||||||
		"@types/node": "7.0.29",
 | 
					    "@types/node": "7.0.31",
 | 
				
			||||||
		"@types/ratelimiter": "2.1.28",
 | 
					    "@types/ratelimiter": "2.1.28",
 | 
				
			||||||
		"@types/redis": "2.6.0",
 | 
					    "@types/redis": "2.6.0",
 | 
				
			||||||
		"@types/request": "0.0.43",
 | 
					    "@types/request": "0.0.43",
 | 
				
			||||||
		"@types/rimraf": "0.0.28",
 | 
					    "@types/rimraf": "0.0.28",
 | 
				
			||||||
		"@types/riot": "2.6.2",
 | 
					    "@types/riot": "2.6.2",
 | 
				
			||||||
		"@types/serve-favicon": "2.2.28",
 | 
					    "@types/serve-favicon": "2.2.28",
 | 
				
			||||||
		"@types/uuid": "3.0.0",
 | 
					    "@types/uuid": "3.0.0",
 | 
				
			||||||
		"@types/webpack": "2.2.15",
 | 
					    "@types/webpack": "2.2.15",
 | 
				
			||||||
		"@types/webpack-stream": "3.2.7",
 | 
					    "@types/webpack-stream": "3.2.7",
 | 
				
			||||||
		"@types/websocket": "0.0.33",
 | 
					    "@types/websocket": "0.0.33",
 | 
				
			||||||
		"chai": "4.0.2",
 | 
					    "chai": "4.0.2",
 | 
				
			||||||
		"chai-http": "3.0.0",
 | 
					    "chai-http": "3.0.0",
 | 
				
			||||||
		"css-loader": "0.28.4",
 | 
					    "css-loader": "0.28.4",
 | 
				
			||||||
		"event-stream": "3.3.4",
 | 
					    "event-stream": "3.3.4",
 | 
				
			||||||
		"gulp": "3.9.1",
 | 
					    "gulp": "3.9.1",
 | 
				
			||||||
		"gulp-cssnano": "2.1.2",
 | 
					    "gulp-cssnano": "2.1.2",
 | 
				
			||||||
		"gulp-imagemin": "3.3.0",
 | 
					    "gulp-imagemin": "3.3.0",
 | 
				
			||||||
		"gulp-mocha": "4.3.1",
 | 
					    "gulp-mocha": "4.3.1",
 | 
				
			||||||
		"gulp-pug": "3.3.0",
 | 
					    "gulp-pug": "3.3.0",
 | 
				
			||||||
		"gulp-rename": "1.2.2",
 | 
					    "gulp-rename": "1.2.2",
 | 
				
			||||||
		"gulp-replace": "0.5.4",
 | 
					    "gulp-replace": "0.5.4",
 | 
				
			||||||
		"gulp-tslint": "8.1.1",
 | 
					    "gulp-tslint": "8.1.1",
 | 
				
			||||||
		"gulp-typescript": "3.1.7",
 | 
					    "gulp-typescript": "3.1.7",
 | 
				
			||||||
		"gulp-uglify": "3.0.0",
 | 
					    "gulp-uglify": "3.0.0",
 | 
				
			||||||
		"gulp-util": "3.0.8",
 | 
					    "gulp-util": "3.0.8",
 | 
				
			||||||
		"mocha": "3.4.2",
 | 
					    "mocha": "3.4.2",
 | 
				
			||||||
		"riot-tag-loader": "1.0.0",
 | 
					    "riot-tag-loader": "1.0.0",
 | 
				
			||||||
		"string-replace-webpack-plugin": "0.1.3",
 | 
					    "string-replace-webpack-plugin": "0.1.3",
 | 
				
			||||||
		"style-loader": "0.18.2",
 | 
					    "style-loader": "0.18.2",
 | 
				
			||||||
		"stylus": "0.54.5",
 | 
					    "stylus": "0.54.5",
 | 
				
			||||||
		"stylus-loader": "3.0.1",
 | 
					    "stylus-loader": "3.0.1",
 | 
				
			||||||
		"swagger-jsdoc": "1.9.4",
 | 
					    "swagger-jsdoc": "1.9.4",
 | 
				
			||||||
		"tslint": "5.4.3",
 | 
					    "tslint": "5.4.3",
 | 
				
			||||||
		"uglify-es": "3.0.15",
 | 
					    "uglify-es": "3.0.15",
 | 
				
			||||||
		"uglify-es-webpack-plugin": "0.0.2",
 | 
					    "uglify-es-webpack-plugin": "0.0.2",
 | 
				
			||||||
		"uglify-js": "git+https://github.com/mishoo/UglifyJS2.git#harmony",
 | 
					    "uglify-js": "git+https://github.com/mishoo/UglifyJS2.git#harmony",
 | 
				
			||||||
		"webpack": "2.6.1"
 | 
					    "webpack": "2.6.1"
 | 
				
			||||||
	},
 | 
					  },
 | 
				
			||||||
	"dependencies": {
 | 
					  "dependencies": {
 | 
				
			||||||
		"accesses": "2.5.0",
 | 
					    "accesses": "2.5.0",
 | 
				
			||||||
		"animejs": "2.0.2",
 | 
					    "animejs": "2.0.2",
 | 
				
			||||||
		"autwh": "0.0.1",
 | 
					    "autwh": "0.0.1",
 | 
				
			||||||
		"bcryptjs": "2.4.3",
 | 
					    "bcryptjs": "2.4.3",
 | 
				
			||||||
		"body-parser": "1.17.2",
 | 
					    "body-parser": "1.17.2",
 | 
				
			||||||
		"cafy": "2.4.0",
 | 
					    "cafy": "2.4.0",
 | 
				
			||||||
		"chalk": "1.1.3",
 | 
					    "chalk": "1.1.3",
 | 
				
			||||||
		"compression": "1.6.2",
 | 
					    "compression": "1.6.2",
 | 
				
			||||||
		"cors": "2.8.3",
 | 
					    "cors": "2.8.3",
 | 
				
			||||||
		"cropperjs": "1.0.0-rc.2",
 | 
					    "cropperjs": "1.0.0-rc.2",
 | 
				
			||||||
		"crypto": "0.0.3",
 | 
					    "crypto": "0.0.3",
 | 
				
			||||||
		"debug": "2.6.8",
 | 
					    "debug": "2.6.8",
 | 
				
			||||||
		"deep-equal": "1.0.1",
 | 
					    "deep-equal": "1.0.1",
 | 
				
			||||||
		"deepcopy": "0.6.3",
 | 
					    "deepcopy": "0.6.3",
 | 
				
			||||||
		"download": "6.2.2",
 | 
					    "diskusage": "^0.2.2",
 | 
				
			||||||
		"elasticsearch": "13.0.1",
 | 
					    "download": "6.2.2",
 | 
				
			||||||
		"escape-regexp": "0.0.1",
 | 
					    "elasticsearch": "13.0.1",
 | 
				
			||||||
		"express": "4.15.3",
 | 
					    "escape-regexp": "0.0.1",
 | 
				
			||||||
		"file-type": "5.0.0",
 | 
					    "express": "4.15.3",
 | 
				
			||||||
		"fuckadblock": "3.2.1",
 | 
					    "file-type": "5.1.1",
 | 
				
			||||||
		"gm": "1.23.0",
 | 
					    "fuckadblock": "3.2.1",
 | 
				
			||||||
		"inquirer": "3.1.0",
 | 
					    "gm": "1.23.0",
 | 
				
			||||||
		"is-root": "1.0.0",
 | 
					    "inquirer": "3.1.0",
 | 
				
			||||||
		"is-url": "1.2.2",
 | 
					    "is-root": "1.0.0",
 | 
				
			||||||
		"js-yaml": "3.8.4",
 | 
					    "is-url": "1.2.2",
 | 
				
			||||||
		"mongodb": "2.2.28",
 | 
					    "js-yaml": "3.8.4",
 | 
				
			||||||
		"monk": "6.0.0",
 | 
					    "mongodb": "2.2.28",
 | 
				
			||||||
		"morgan": "1.8.2",
 | 
					    "monk": "6.0.0",
 | 
				
			||||||
		"ms": "2.0.0",
 | 
					    "morgan": "1.8.2",
 | 
				
			||||||
		"multer": "1.3.0",
 | 
					    "ms": "2.0.0",
 | 
				
			||||||
		"nprogress": "0.2.0",
 | 
					    "multer": "1.3.0",
 | 
				
			||||||
		"page": "1.7.1",
 | 
					    "nprogress": "0.2.0",
 | 
				
			||||||
		"pictograph": "2.0.4",
 | 
					    "os-utils": "0.0.14",
 | 
				
			||||||
		"prominence": "0.2.0",
 | 
					    "page": "1.7.1",
 | 
				
			||||||
		"pug": "2.0.0-rc.2",
 | 
					    "pictograph": "2.0.4",
 | 
				
			||||||
		"ratelimiter": "3.0.3",
 | 
					    "prominence": "0.2.0",
 | 
				
			||||||
		"recaptcha-promise": "0.1.2",
 | 
					    "pug": "2.0.0-rc.2",
 | 
				
			||||||
		"reconnecting-websocket": "3.0.5",
 | 
					    "ratelimiter": "3.0.3",
 | 
				
			||||||
		"redis": "2.7.1",
 | 
					    "recaptcha-promise": "0.1.2",
 | 
				
			||||||
		"request": "2.81.0",
 | 
					    "reconnecting-websocket": "3.0.5",
 | 
				
			||||||
		"rimraf": "2.6.1",
 | 
					    "redis": "2.7.1",
 | 
				
			||||||
		"riot": "3.5.1",
 | 
					    "request": "2.81.0",
 | 
				
			||||||
		"rndstr": "1.0.0",
 | 
					    "rimraf": "2.6.1",
 | 
				
			||||||
		"s-age": "1.1.0",
 | 
					    "riot": "3.6.0",
 | 
				
			||||||
		"serve-favicon": "2.4.3",
 | 
					    "rndstr": "1.0.0",
 | 
				
			||||||
		"summaly": "2.0.3",
 | 
					    "s-age": "1.1.0",
 | 
				
			||||||
		"syuilo-password-strength": "0.0.1",
 | 
					    "serve-favicon": "2.4.3",
 | 
				
			||||||
		"tcp-port-used": "0.1.2",
 | 
					    "summaly": "2.0.3",
 | 
				
			||||||
		"textarea-caret": "3.0.2",
 | 
					    "syuilo-password-strength": "0.0.1",
 | 
				
			||||||
		"ts-node": "3.0.6",
 | 
					    "tcp-port-used": "0.1.2",
 | 
				
			||||||
		"typescript": "2.3.4",
 | 
					    "textarea-caret": "3.0.2",
 | 
				
			||||||
		"uuid": "3.0.1",
 | 
					    "ts-node": "3.0.6",
 | 
				
			||||||
		"vhost": "3.0.2",
 | 
					    "typescript": "2.3.4",
 | 
				
			||||||
		"websocket": "1.0.24"
 | 
					    "uuid": "3.0.1",
 | 
				
			||||||
	}
 | 
					    "vhost": "3.0.2",
 | 
				
			||||||
 | 
					    "websocket": "1.0.24",
 | 
				
			||||||
 | 
					    "xev": "^2.0.0"
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										64
									
								
								src/api/common/read-messaging-message.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								src/api/common/read-messaging-message.ts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,64 @@
 | 
				
			||||||
 | 
					import * as mongo from 'mongodb';
 | 
				
			||||||
 | 
					import Message from '../models/messaging-message';
 | 
				
			||||||
 | 
					import { IMessagingMessage as IMessage } from '../models/messaging-message';
 | 
				
			||||||
 | 
					import publishUserStream from '../event';
 | 
				
			||||||
 | 
					import { publishMessagingStream } from '../event';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Mark as read message(s)
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export default (
 | 
				
			||||||
 | 
						user: string | mongo.ObjectID,
 | 
				
			||||||
 | 
						otherparty: string | mongo.ObjectID,
 | 
				
			||||||
 | 
						message: string | string[] | IMessage | IMessage[] | mongo.ObjectID | mongo.ObjectID[]
 | 
				
			||||||
 | 
					) => new Promise<any>(async (resolve, reject) => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const userId = mongo.ObjectID.prototype.isPrototypeOf(user)
 | 
				
			||||||
 | 
							? user
 | 
				
			||||||
 | 
							: new mongo.ObjectID(user);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const otherpartyId = mongo.ObjectID.prototype.isPrototypeOf(otherparty)
 | 
				
			||||||
 | 
							? otherparty
 | 
				
			||||||
 | 
							: new mongo.ObjectID(otherparty);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const ids: mongo.ObjectID[] = Array.isArray(message)
 | 
				
			||||||
 | 
							? mongo.ObjectID.prototype.isPrototypeOf(message[0])
 | 
				
			||||||
 | 
								? (message as mongo.ObjectID[])
 | 
				
			||||||
 | 
								: typeof message[0] === 'string'
 | 
				
			||||||
 | 
									? (message as string[]).map(m => new mongo.ObjectID(m))
 | 
				
			||||||
 | 
									: (message as IMessage[]).map(m => m._id)
 | 
				
			||||||
 | 
							: mongo.ObjectID.prototype.isPrototypeOf(message)
 | 
				
			||||||
 | 
								? [(message as mongo.ObjectID)]
 | 
				
			||||||
 | 
								: typeof message === 'string'
 | 
				
			||||||
 | 
									? [new mongo.ObjectID(message)]
 | 
				
			||||||
 | 
									: [(message as IMessage)._id];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Update documents
 | 
				
			||||||
 | 
						await Message.update({
 | 
				
			||||||
 | 
							_id: { $in: ids },
 | 
				
			||||||
 | 
							user_id: otherpartyId,
 | 
				
			||||||
 | 
							recipient_id: userId,
 | 
				
			||||||
 | 
							is_read: false
 | 
				
			||||||
 | 
						}, {
 | 
				
			||||||
 | 
							$set: {
 | 
				
			||||||
 | 
								is_read: true
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}, {
 | 
				
			||||||
 | 
							multi: true
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Publish event
 | 
				
			||||||
 | 
						publishMessagingStream(otherpartyId, userId, 'read', ids.map(id => id.toString()));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Calc count of my unread messages
 | 
				
			||||||
 | 
						const count = await Message
 | 
				
			||||||
 | 
							.count({
 | 
				
			||||||
 | 
								recipient_id: userId,
 | 
				
			||||||
 | 
								is_read: false
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (count == 0) {
 | 
				
			||||||
 | 
							// 全ての(いままで未読だった)自分宛てのメッセージを(これで)読みましたよというイベントを発行
 | 
				
			||||||
 | 
							publishUserStream(userId, 'read_all_messaging_messages');
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
| 
						 | 
					@ -5,8 +5,7 @@ import $ from 'cafy';
 | 
				
			||||||
import Message from '../../models/messaging-message';
 | 
					import Message from '../../models/messaging-message';
 | 
				
			||||||
import User from '../../models/user';
 | 
					import User from '../../models/user';
 | 
				
			||||||
import serialize from '../../serializers/messaging-message';
 | 
					import serialize from '../../serializers/messaging-message';
 | 
				
			||||||
import publishUserStream from '../../event';
 | 
					import read from '../../common/read-messaging-message';
 | 
				
			||||||
import { publishMessagingStream } from '../../event';
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Get messages
 | 
					 * Get messages
 | 
				
			||||||
| 
						 | 
					@ -98,32 +97,6 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Mark as read all
 | 
						// Mark as read all
 | 
				
			||||||
	if (markAsRead) {
 | 
						if (markAsRead) {
 | 
				
			||||||
		const ids = messages
 | 
							read(user._id, recipient._id, messages);
 | 
				
			||||||
			.filter(m => m.is_read == false)
 | 
					 | 
				
			||||||
			.filter(m => m.recipient_id.equals(user._id))
 | 
					 | 
				
			||||||
			.map(m => m._id);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Update documents
 | 
					 | 
				
			||||||
		await Message.update({
 | 
					 | 
				
			||||||
			_id: { $in: ids }
 | 
					 | 
				
			||||||
		}, {
 | 
					 | 
				
			||||||
			$set: { is_read: true }
 | 
					 | 
				
			||||||
		}, {
 | 
					 | 
				
			||||||
			multi: true
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Publish event
 | 
					 | 
				
			||||||
		publishMessagingStream(recipient._id, user._id, 'read', ids.map(id => id.toString()));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		const count = await Message
 | 
					 | 
				
			||||||
			.count({
 | 
					 | 
				
			||||||
				recipient_id: user._id,
 | 
					 | 
				
			||||||
				is_read: false
 | 
					 | 
				
			||||||
			});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (count == 0) {
 | 
					 | 
				
			||||||
			// 全ての(いままで未読だった)メッセージを(これで)読みましたよというイベントを発行
 | 
					 | 
				
			||||||
			publishUserStream(user._id, 'read_all_messaging_messages');
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -93,13 +93,13 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
 | 
				
			||||||
	publishMessagingStream(message.recipient_id, message.user_id, 'message', messageObj);
 | 
						publishMessagingStream(message.recipient_id, message.user_id, 'message', messageObj);
 | 
				
			||||||
	publishUserStream(message.recipient_id, 'messaging_message', messageObj);
 | 
						publishUserStream(message.recipient_id, 'messaging_message', messageObj);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// 5秒経っても(今回作成した)メッセージが既読にならなかったら「未読のメッセージがありますよ」イベントを発行する
 | 
						// 3秒経っても(今回作成した)メッセージが既読にならなかったら「未読のメッセージがありますよ」イベントを発行する
 | 
				
			||||||
	setTimeout(async () => {
 | 
						setTimeout(async () => {
 | 
				
			||||||
		const freshMessage = await Message.findOne({ _id: message._id }, { is_read: true });
 | 
							const freshMessage = await Message.findOne({ _id: message._id }, { is_read: true });
 | 
				
			||||||
		if (!freshMessage.is_read) {
 | 
							if (!freshMessage.is_read) {
 | 
				
			||||||
			publishUserStream(message.recipient_id, 'unread_messaging_message', messageObj);
 | 
								publishUserStream(message.recipient_id, 'unread_messaging_message', messageObj);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}, 5000);
 | 
						}, 3000);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Register to search database
 | 
						// Register to search database
 | 
				
			||||||
	if (message.text && config.elasticsearch.enable) {
 | 
						if (message.text && config.elasticsearch.enable) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,7 @@
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Module dependencies
 | 
					 * Module dependencies
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					import * as os from 'os';
 | 
				
			||||||
import version from '../../version';
 | 
					import version from '../../version';
 | 
				
			||||||
import config from '../../conf';
 | 
					import config from '../../conf';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -41,6 +42,13 @@ module.exports = (params) => new Promise(async (res, rej) => {
 | 
				
			||||||
	res({
 | 
						res({
 | 
				
			||||||
		maintainer: config.maintainer,
 | 
							maintainer: config.maintainer,
 | 
				
			||||||
		version: version,
 | 
							version: version,
 | 
				
			||||||
		secure: config.https.enable
 | 
							secure: config.https.enable,
 | 
				
			||||||
 | 
							machine: os.hostname(),
 | 
				
			||||||
 | 
							os: os.platform(),
 | 
				
			||||||
 | 
							node: process.version,
 | 
				
			||||||
 | 
							cpu: {
 | 
				
			||||||
 | 
								model: os.cpus()[0].model,
 | 
				
			||||||
 | 
								cores: os.cpus().length
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -42,7 +42,7 @@ async function byNative(res, rej, me, query, offset, max) {
 | 
				
			||||||
	const users = await User
 | 
						const users = await User
 | 
				
			||||||
		.find({
 | 
							.find({
 | 
				
			||||||
			$or: [{
 | 
								$or: [{
 | 
				
			||||||
				username_lower: new RegExp(escapedQuery.toLowerCase())
 | 
									username_lower: new RegExp(escapedQuery.replace('@', '').toLowerCase())
 | 
				
			||||||
			}, {
 | 
								}, {
 | 
				
			||||||
				name: new RegExp(escapedQuery)
 | 
									name: new RegExp(escapedQuery)
 | 
				
			||||||
			}]
 | 
								}]
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,12 @@
 | 
				
			||||||
 | 
					import * as mongo from 'mongodb';
 | 
				
			||||||
import db from '../../db/mongodb';
 | 
					import db from '../../db/mongodb';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default db.get('messaging_messages') as any; // fuck type definition
 | 
					export default db.get('messaging_messages') as any; // fuck type definition
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface IMessagingMessage {
 | 
				
			||||||
 | 
						_id: mongo.ObjectID;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function isValidText(text: string): boolean {
 | 
					export function isValidText(text: string): boolean {
 | 
				
			||||||
	return text.length <= 1000 && text.trim() != '';
 | 
						return text.length <= 1000 && text.trim() != '';
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,8 +1,6 @@
 | 
				
			||||||
import * as mongodb from 'mongodb';
 | 
					 | 
				
			||||||
import * as websocket from 'websocket';
 | 
					import * as websocket from 'websocket';
 | 
				
			||||||
import * as redis from 'redis';
 | 
					import * as redis from 'redis';
 | 
				
			||||||
import Message from '../models/messaging-message';
 | 
					import read from '../common/read-messaging-message';
 | 
				
			||||||
import { publishMessagingStream } from '../event';
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default function messagingStream(request: websocket.request, connection: websocket.connection, subscriber: redis.RedisClient, user: any): void {
 | 
					export default function messagingStream(request: websocket.request, connection: websocket.connection, subscriber: redis.RedisClient, user: any): void {
 | 
				
			||||||
	const otherparty = request.resourceURL.query.otherparty;
 | 
						const otherparty = request.resourceURL.query.otherparty;
 | 
				
			||||||
| 
						 | 
					@ -18,42 +16,8 @@ export default function messagingStream(request: websocket.request, connection:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		switch (msg.type) {
 | 
							switch (msg.type) {
 | 
				
			||||||
			case 'read':
 | 
								case 'read':
 | 
				
			||||||
				if (!msg.id) {
 | 
									if (!msg.id) return;
 | 
				
			||||||
					return;
 | 
									read(user._id, otherparty, msg.id);
 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				const id = new mongodb.ObjectID(msg.id);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				// Fetch message
 | 
					 | 
				
			||||||
				// SELECT _id, user_id, is_read
 | 
					 | 
				
			||||||
				const message = await Message.findOne({
 | 
					 | 
				
			||||||
					_id: id,
 | 
					 | 
				
			||||||
					recipient_id: user._id
 | 
					 | 
				
			||||||
				}, {
 | 
					 | 
				
			||||||
					fields: {
 | 
					 | 
				
			||||||
						_id: true,
 | 
					 | 
				
			||||||
						user_id: true,
 | 
					 | 
				
			||||||
						is_read: true
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				if (message == null) {
 | 
					 | 
				
			||||||
					return;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				if (message.is_read) {
 | 
					 | 
				
			||||||
					return;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				// Update documents
 | 
					 | 
				
			||||||
				await Message.update({
 | 
					 | 
				
			||||||
					_id: id
 | 
					 | 
				
			||||||
				}, {
 | 
					 | 
				
			||||||
					$set: { is_read: true }
 | 
					 | 
				
			||||||
				});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				// Publish event
 | 
					 | 
				
			||||||
				publishMessagingStream(message.user_id, user._id, 'read', id.toString());
 | 
					 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										20
									
								
								src/api/stream/server.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								src/api/stream/server.ts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,20 @@
 | 
				
			||||||
 | 
					import * as websocket from 'websocket';
 | 
				
			||||||
 | 
					import Xev from 'xev';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ev = new Xev();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default function homeStream(request: websocket.request, connection: websocket.connection): void {
 | 
				
			||||||
 | 
						const onStats = stats => {
 | 
				
			||||||
 | 
							connection.send(JSON.stringify({
 | 
				
			||||||
 | 
								type: 'stats',
 | 
				
			||||||
 | 
								body: stats
 | 
				
			||||||
 | 
							}));
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ev.addListener('stats', onStats);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						connection.on('close', () => {
 | 
				
			||||||
 | 
							console.log('yooo');
 | 
				
			||||||
 | 
							ev.removeListener('stats', onStats);
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -8,6 +8,7 @@ import isNativeToken from './common/is-native-token';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import homeStream from './stream/home';
 | 
					import homeStream from './stream/home';
 | 
				
			||||||
import messagingStream from './stream/messaging';
 | 
					import messagingStream from './stream/messaging';
 | 
				
			||||||
 | 
					import serverStream from './stream/server';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = (server: http.Server) => {
 | 
					module.exports = (server: http.Server) => {
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
| 
						 | 
					@ -20,6 +21,11 @@ module.exports = (server: http.Server) => {
 | 
				
			||||||
	ws.on('request', async (request) => {
 | 
						ws.on('request', async (request) => {
 | 
				
			||||||
		const connection = request.accept();
 | 
							const connection = request.accept();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (request.resourceURL.pathname === '/server') {
 | 
				
			||||||
 | 
								serverStream(request, connection);
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		const user = await authenticate(connection, request.resourceURL.query.i);
 | 
							const user = await authenticate(connection, request.resourceURL.query.i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (user == null) {
 | 
							if (user == null) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,17 +12,20 @@ import * as chalk from 'chalk';
 | 
				
			||||||
// import portUsed = require('tcp-port-used');
 | 
					// import portUsed = require('tcp-port-used');
 | 
				
			||||||
import isRoot = require('is-root');
 | 
					import isRoot = require('is-root');
 | 
				
			||||||
import { master } from 'accesses';
 | 
					import { master } from 'accesses';
 | 
				
			||||||
 | 
					import Xev from 'xev';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import Logger from './utils/logger';
 | 
					import Logger from './utils/logger';
 | 
				
			||||||
import ProgressBar from './utils/cli/progressbar';
 | 
					import ProgressBar from './utils/cli/progressbar';
 | 
				
			||||||
import EnvironmentInfo from './utils/environmentInfo';
 | 
					import EnvironmentInfo from './utils/environmentInfo';
 | 
				
			||||||
import MachineInfo from './utils/machineInfo';
 | 
					import MachineInfo from './utils/machineInfo';
 | 
				
			||||||
import DependencyInfo from './utils/dependencyInfo';
 | 
					import DependencyInfo from './utils/dependencyInfo';
 | 
				
			||||||
 | 
					import stats from './utils/stats';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { Config, path as configPath } from './config';
 | 
					import { Config, path as configPath } from './config';
 | 
				
			||||||
import loadConfig from './config';
 | 
					import loadConfig from './config';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const clusterLog = debug('misskey:cluster');
 | 
					const clusterLog = debug('misskey:cluster');
 | 
				
			||||||
 | 
					const ev = new Xev();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
process.title = 'Misskey';
 | 
					process.title = 'Misskey';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -35,6 +38,9 @@ main();
 | 
				
			||||||
function main() {
 | 
					function main() {
 | 
				
			||||||
	if (cluster.isMaster) {
 | 
						if (cluster.isMaster) {
 | 
				
			||||||
		masterMain();
 | 
							masterMain();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ev.mount();
 | 
				
			||||||
 | 
							stats();
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		workerMain();
 | 
							workerMain();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										27
									
								
								src/utils/stats.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								src/utils/stats.ts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,27 @@
 | 
				
			||||||
 | 
					import * as os from 'os';
 | 
				
			||||||
 | 
					const osUtils = require('os-utils');
 | 
				
			||||||
 | 
					import * as diskusage from 'diskusage';
 | 
				
			||||||
 | 
					import Xev from 'xev';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ev = new Xev();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Report stats regularly
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export default function() {
 | 
				
			||||||
 | 
						setInterval(() => {
 | 
				
			||||||
 | 
							osUtils.cpuUsage(cpuUsage => {
 | 
				
			||||||
 | 
								const disk = diskusage.checkSync(os.platform() == 'win32' ? 'c:' : '/');
 | 
				
			||||||
 | 
								ev.emit('stats', {
 | 
				
			||||||
 | 
									cpu_usage: cpuUsage,
 | 
				
			||||||
 | 
									mem: {
 | 
				
			||||||
 | 
										total: os.totalmem(),
 | 
				
			||||||
 | 
										free: os.freemem()
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									disk,
 | 
				
			||||||
 | 
									os_uptime: os.uptime(),
 | 
				
			||||||
 | 
									process_uptime: process.uptime()
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
						}, 1000);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -20,7 +20,7 @@ html
 | 
				
			||||||
		script
 | 
							script
 | 
				
			||||||
			include ./../../../built/web/assets/safe.js
 | 
								include ./../../../built/web/assets/safe.js
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		script(src='https://use.fontawesome.com/22aba0df4f.js' async)
 | 
							script(src='https://use.fontawesome.com/db921426cb.js' async)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	body
 | 
						body
 | 
				
			||||||
		noscript: p
 | 
							noscript: p
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -30,14 +30,7 @@ html
 | 
				
			||||||
			cursor progress !important
 | 
								cursor progress !important
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#error
 | 
					#error
 | 
				
			||||||
	position fixed
 | 
					 | 
				
			||||||
	z-index 32768
 | 
					 | 
				
			||||||
	top 0
 | 
					 | 
				
			||||||
	left 0
 | 
					 | 
				
			||||||
	width 100%
 | 
					 | 
				
			||||||
	height 100%
 | 
					 | 
				
			||||||
	padding 32px
 | 
						padding 32px
 | 
				
			||||||
	background #1269e2
 | 
					 | 
				
			||||||
	color #fff
 | 
						color #fff
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	hr
 | 
						hr
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,6 @@
 | 
				
			||||||
export default bytes => {
 | 
					export default (bytes, digits = 0) => {
 | 
				
			||||||
	var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
 | 
						var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
 | 
				
			||||||
	if (bytes == 0) return '0Byte';
 | 
						if (bytes == 0) return '0Byte';
 | 
				
			||||||
	var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
 | 
						var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
 | 
				
			||||||
	return Math.round(bytes / Math.pow(1024, i), 2) + sizes[i];
 | 
						return (bytes / Math.pow(1024, i)).toFixed(digits).replace(/\.0+$/, '') + sizes[i];
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1 +0,0 @@
 | 
				
			||||||
export default () => '(=^・・^=)';
 | 
					 | 
				
			||||||
							
								
								
									
										5
									
								
								src/web/app/common/scripts/get-kao.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/web/app/common/scripts/get-kao.js
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,5 @@
 | 
				
			||||||
 | 
					export default () => [
 | 
				
			||||||
 | 
						'(=^・・^=)',
 | 
				
			||||||
 | 
						'v(‘ω’)v',
 | 
				
			||||||
 | 
						'🐡( '-' 🐡 )フグパンチ!!!!'
 | 
				
			||||||
 | 
					][Math.floor(Math.random() * 3)];
 | 
				
			||||||
							
								
								
									
										18
									
								
								src/web/app/common/scripts/home-stream.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								src/web/app/common/scripts/home-stream.js
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,18 @@
 | 
				
			||||||
 | 
					'use strict';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import Stream from './stream';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Home stream connection
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					class Connection extends Stream {
 | 
				
			||||||
 | 
						constructor(me) {
 | 
				
			||||||
 | 
							super('', {
 | 
				
			||||||
 | 
								i: me.token
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this.on('i_updated', me.update);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Connection;
 | 
				
			||||||
| 
						 | 
					@ -1,42 +1,22 @@
 | 
				
			||||||
const ReconnectingWebSocket = require('reconnecting-websocket');
 | 
					'use strict';
 | 
				
			||||||
import * as riot from 'riot';
 | 
					 | 
				
			||||||
import CONFIG from './config';
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Connection {
 | 
					import Stream from './stream';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Messaging stream connection
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					class Connection extends Stream {
 | 
				
			||||||
	constructor(me, otherparty) {
 | 
						constructor(me, otherparty) {
 | 
				
			||||||
		// BIND -----------------------------------
 | 
							super('messaging', {
 | 
				
			||||||
		this.onOpen =    this.onOpen.bind(this);
 | 
								i: me.token,
 | 
				
			||||||
		this.onMessage = this.onMessage.bind(this);
 | 
								otherparty
 | 
				
			||||||
		this.close =     this.close.bind(this);
 | 
							});
 | 
				
			||||||
		// ----------------------------------------
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		this.event = riot.observable();
 | 
							this.on('_connected_', () => {
 | 
				
			||||||
		this.me = me;
 | 
								this.send({
 | 
				
			||||||
 | 
									i: me.token
 | 
				
			||||||
		const host = CONFIG.apiUrl.replace('http', 'ws');
 | 
								});
 | 
				
			||||||
		this.socket = new ReconnectingWebSocket(`${host}/messaging?i=${me.token}&otherparty=${otherparty}`);
 | 
							});
 | 
				
			||||||
		this.socket.addEventListener('open', this.onOpen);
 | 
					 | 
				
			||||||
		this.socket.addEventListener('message', this.onMessage);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	onOpen() {
 | 
					 | 
				
			||||||
		this.socket.send(JSON.stringify({
 | 
					 | 
				
			||||||
			i: this.me.token
 | 
					 | 
				
			||||||
		}));
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	onMessage(message) {
 | 
					 | 
				
			||||||
		try {
 | 
					 | 
				
			||||||
			const msg = JSON.parse(message.data);
 | 
					 | 
				
			||||||
			if (msg.type) this.event.trigger(msg.type, msg.body);
 | 
					 | 
				
			||||||
		} catch(e) {
 | 
					 | 
				
			||||||
			// noop
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	close() {
 | 
					 | 
				
			||||||
		this.socket.removeEventListener('open', this.onOpen);
 | 
					 | 
				
			||||||
		this.socket.removeEventListener('message', this.onMessage);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										14
									
								
								src/web/app/common/scripts/server-stream.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/web/app/common/scripts/server-stream.js
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,14 @@
 | 
				
			||||||
 | 
					'use strict';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import Stream from './stream';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Server stream connection
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					class Connection extends Stream {
 | 
				
			||||||
 | 
						constructor() {
 | 
				
			||||||
 | 
							super('server');
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default Connection;
 | 
				
			||||||
| 
						 | 
					@ -5,10 +5,10 @@ import * as riot from 'riot';
 | 
				
			||||||
import CONFIG from './config';
 | 
					import CONFIG from './config';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Home stream connection
 | 
					 * Misskey stream connection
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
class Connection {
 | 
					class Connection {
 | 
				
			||||||
	constructor(me) {
 | 
						constructor(endpoint, params) {
 | 
				
			||||||
		// BIND -----------------------------------
 | 
							// BIND -----------------------------------
 | 
				
			||||||
		this.onOpen =    this.onOpen.bind(this);
 | 
							this.onOpen =    this.onOpen.bind(this);
 | 
				
			||||||
		this.onClose =   this.onClose.bind(this);
 | 
							this.onClose =   this.onClose.bind(this);
 | 
				
			||||||
| 
						 | 
					@ -20,16 +20,19 @@ class Connection {
 | 
				
			||||||
		riot.observable(this);
 | 
							riot.observable(this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		this.state = 'initializing';
 | 
							this.state = 'initializing';
 | 
				
			||||||
		this.me = me;
 | 
					 | 
				
			||||||
		this.buffer = [];
 | 
							this.buffer = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		const host = CONFIG.apiUrl.replace('http', 'ws');
 | 
							const host = CONFIG.apiUrl.replace('http', 'ws');
 | 
				
			||||||
		this.socket = new ReconnectingWebSocket(`${host}?i=${me.token}`);
 | 
							const query = params
 | 
				
			||||||
 | 
								? Object.keys(params)
 | 
				
			||||||
 | 
									.map(k => encodeURIComponent(k) + '=' + encodeURIComponent(params[k]))
 | 
				
			||||||
 | 
									.join('&')
 | 
				
			||||||
 | 
								: null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this.socket = new ReconnectingWebSocket(`${host}/${endpoint}${query ? '?' + query : ''}`);
 | 
				
			||||||
		this.socket.addEventListener('open', this.onOpen);
 | 
							this.socket.addEventListener('open', this.onOpen);
 | 
				
			||||||
		this.socket.addEventListener('close', this.onClose);
 | 
							this.socket.addEventListener('close', this.onClose);
 | 
				
			||||||
		this.socket.addEventListener('message', this.onMessage);
 | 
							this.socket.addEventListener('message', this.onMessage);
 | 
				
			||||||
 | 
					 | 
				
			||||||
		this.on('i_updated', me.update);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,7 +22,7 @@ export default (tokens, shouldBreak) => {
 | 
				
			||||||
			case 'bold':
 | 
								case 'bold':
 | 
				
			||||||
				return `<strong>${escape(token.bold)}</strong>`;
 | 
									return `<strong>${escape(token.bold)}</strong>`;
 | 
				
			||||||
			case 'url':
 | 
								case 'url':
 | 
				
			||||||
				return `<mk-url href="${escape(token.content)}" target="_blank"/>`;
 | 
									return `<mk-url href="${escape(token.content)}" target="_blank"></mk-url>`;
 | 
				
			||||||
			case 'link':
 | 
								case 'link':
 | 
				
			||||||
				return `<a class="link" href="${escape(token.url)}" target="_blank" title="${escape(token.url)}">${escape(token.title)}</a>`;
 | 
									return `<a class="link" href="${escape(token.url)}" target="_blank" title="${escape(token.url)}">${escape(token.title)}</a>`;
 | 
				
			||||||
			case 'mention':
 | 
								case 'mention':
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,7 +2,15 @@
 | 
				
			||||||
	<svg if={ data } ref="canvas" viewBox="0 0 53 7" preserveAspectRatio="none">
 | 
						<svg if={ data } ref="canvas" viewBox="0 0 53 7" preserveAspectRatio="none">
 | 
				
			||||||
		<rect each={ data } width="1" height="1"
 | 
							<rect each={ data } width="1" height="1"
 | 
				
			||||||
			riot-x={ x } riot-y={ date.weekday }
 | 
								riot-x={ x } riot-y={ date.weekday }
 | 
				
			||||||
			fill={ color }></rect>
 | 
								rx="1" ry="1"
 | 
				
			||||||
 | 
								fill={ color }
 | 
				
			||||||
 | 
								style="transform: scale({ v });"/>
 | 
				
			||||||
 | 
							<rect class="today" width="1" height="1"
 | 
				
			||||||
 | 
								riot-x={ data[data.length - 1].x } riot-y={ data[data.length - 1].date.weekday }
 | 
				
			||||||
 | 
								rx="1" ry="1"
 | 
				
			||||||
 | 
								fill="none"
 | 
				
			||||||
 | 
								stroke-width="0.1"
 | 
				
			||||||
 | 
								stroke="#f73520"/>
 | 
				
			||||||
	</svg>
 | 
						</svg>
 | 
				
			||||||
	<style>
 | 
						<style>
 | 
				
			||||||
		:scope
 | 
							:scope
 | 
				
			||||||
| 
						 | 
					@ -16,7 +24,6 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				> rect
 | 
									> rect
 | 
				
			||||||
					transform-origin center
 | 
										transform-origin center
 | 
				
			||||||
					transform scale(0.8)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	</style>
 | 
						</style>
 | 
				
			||||||
	<script>
 | 
						<script>
 | 
				
			||||||
| 
						 | 
					@ -33,9 +40,9 @@
 | 
				
			||||||
				let x = 0;
 | 
									let x = 0;
 | 
				
			||||||
				data.reverse().forEach(d => {
 | 
									data.reverse().forEach(d => {
 | 
				
			||||||
					d.x = x;
 | 
										d.x = x;
 | 
				
			||||||
					let v = d.total / this.peak;
 | 
										d.v = d.total / this.peak;
 | 
				
			||||||
					if (v > 1) v = 1;
 | 
										if (d.v > 1) d.v = 1;
 | 
				
			||||||
					d.color = `hsl(180, ${v * 100}%, ${15 + ((1 - v) * 80)}%)`;
 | 
										d.color = `hsl(170, ${d.v * 100}%, ${15 + ((1 - d.v) * 80)}%)`;
 | 
				
			||||||
					d.date.weekday = (new Date(d.date.year, d.date.month - 1, d.date.day)).getDay();
 | 
										d.date.weekday = (new Date(d.date.year, d.date.month - 1, d.date.day)).getDay();
 | 
				
			||||||
					if (d.date.weekday == 6) x++;
 | 
										if (d.date.weekday == 6) x++;
 | 
				
			||||||
				});
 | 
									});
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,36 +1,25 @@
 | 
				
			||||||
<mk-error>
 | 
					<mk-error>
 | 
				
			||||||
	<!--i: i.fa.fa-times-circle-->
 | 
					 | 
				
			||||||
	<img src="/assets/error.jpg" alt=""/>
 | 
						<img src="/assets/error.jpg" alt=""/>
 | 
				
			||||||
	<h1>%i18n:common.tags.mk-error.title%</h1>
 | 
						<h1>%i18n:common.tags.mk-error.title%</h1>
 | 
				
			||||||
	<p class="text">%i18n:common.tags.mk-error.description%</p>
 | 
						<p class="text">%i18n:common.tags.mk-error.description%</p>
 | 
				
			||||||
	<p class="thanks">%i18n:common.tags.mk-error.thanks%</p>
 | 
						<p class="thanks">%i18n:common.tags.mk-error.thanks%</p>
 | 
				
			||||||
	<style>
 | 
						<style>
 | 
				
			||||||
		:scope
 | 
							:scope
 | 
				
			||||||
			position fixed
 | 
								display block
 | 
				
			||||||
			z-index 100000
 | 
					 | 
				
			||||||
			top 0
 | 
					 | 
				
			||||||
			left 0
 | 
					 | 
				
			||||||
			width 100%
 | 
								width 100%
 | 
				
			||||||
			height 100%
 | 
								padding 32px 18px
 | 
				
			||||||
			text-align center
 | 
								text-align center
 | 
				
			||||||
			background #f8f8f8
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			> i
 | 
					 | 
				
			||||||
				display block
 | 
					 | 
				
			||||||
				margin-top 64px
 | 
					 | 
				
			||||||
				font-size 5em
 | 
					 | 
				
			||||||
				color #6998a0
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			> img
 | 
								> img
 | 
				
			||||||
				display block
 | 
									display block
 | 
				
			||||||
				height 200px
 | 
									height 200px
 | 
				
			||||||
				margin 64px auto 0 auto
 | 
									margin 0 auto
 | 
				
			||||||
				pointer-events none
 | 
									pointer-events none
 | 
				
			||||||
				user-select none
 | 
									user-select none
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			> h1
 | 
								> h1
 | 
				
			||||||
				display block
 | 
									display block
 | 
				
			||||||
				margin 32px auto 16px auto
 | 
									margin 1.25em auto 0.65em auto
 | 
				
			||||||
				font-size 1.5em
 | 
									font-size 1.5em
 | 
				
			||||||
				color #555
 | 
									color #555
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -43,13 +32,26 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			> .thanks
 | 
								> .thanks
 | 
				
			||||||
				display block
 | 
									display block
 | 
				
			||||||
				margin 32px auto 0 auto
 | 
									margin 2em auto 0 auto
 | 
				
			||||||
				padding 32px 0 32px 0
 | 
									padding 2em 0 0 0
 | 
				
			||||||
				max-width 600px
 | 
									max-width 600px
 | 
				
			||||||
				font-size 0.9em
 | 
									font-size 0.9em
 | 
				
			||||||
				font-style oblique
 | 
									font-style oblique
 | 
				
			||||||
				color #aaa
 | 
									color #aaa
 | 
				
			||||||
				border-top solid 1px #eee
 | 
									border-top solid 1px #eee
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								@media (max-width 500px)
 | 
				
			||||||
 | 
									padding 24px 18px
 | 
				
			||||||
 | 
									font-size 80%
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									> img
 | 
				
			||||||
 | 
										height 150px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	</style>
 | 
						</style>
 | 
				
			||||||
 | 
						<script>
 | 
				
			||||||
 | 
							this.on('mount', () => {
 | 
				
			||||||
 | 
								document.title = 'Oops!';
 | 
				
			||||||
 | 
								document.documentElement.style.background = '#f8f8f8';
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
						</script>
 | 
				
			||||||
</mk-error>
 | 
					</mk-error>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,7 @@
 | 
				
			||||||
<mk-messaging-message data-is-me={ message.is_me }><a class="avatar-anchor" href={ '/' + message.user.username } title={ message.user.username } target="_blank"><img class="avatar" src={ message.user.avatar_url + '?thumbnail&size=64' } alt=""/></a>
 | 
					<mk-messaging-message data-is-me={ message.is_me }>
 | 
				
			||||||
 | 
						<a class="avatar-anchor" href={ '/' + message.user.username } title={ message.user.username } target="_blank">
 | 
				
			||||||
 | 
							<img class="avatar" src={ message.user.avatar_url + '?thumbnail&size=80' } alt=""/>
 | 
				
			||||||
 | 
						</a>
 | 
				
			||||||
	<div class="content-container">
 | 
						<div class="content-container">
 | 
				
			||||||
		<div class="balloon">
 | 
							<div class="balloon">
 | 
				
			||||||
			<p class="read" if={ message.is_me && message.is_read }>%i18n:common.tags.mk-messaging-message.is-read%</p>
 | 
								<p class="read" if={ message.is_me && message.is_read }>%i18n:common.tags.mk-messaging-message.is-read%</p>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,6 +2,10 @@
 | 
				
			||||||
	<div class="stream">
 | 
						<div class="stream">
 | 
				
			||||||
		<p class="init" if={ init }><i class="fa fa-spinner fa-spin"></i>%i18n:common.loading%</p>
 | 
							<p class="init" if={ init }><i class="fa fa-spinner fa-spin"></i>%i18n:common.loading%</p>
 | 
				
			||||||
		<p class="empty" if={ !init && messages.length == 0 }><i class="fa fa-info-circle"></i>%i18n:common.tags.mk-messaging-room.empty%</p>
 | 
							<p class="empty" if={ !init && messages.length == 0 }><i class="fa fa-info-circle"></i>%i18n:common.tags.mk-messaging-room.empty%</p>
 | 
				
			||||||
 | 
							<p class="no-history" if={ !init && messages.length > 0 && !moreMessagesIsInStock }><i class="fa fa-flag"></i>%i18n:common.tags.mk-messaging-room.no-history%</p>
 | 
				
			||||||
 | 
							<button class="more { fetching: fetchingMoreMessages }" if={ moreMessagesIsInStock } onclick={ fetchMoreMessages } disabled={ fetchingMoreMessages }>
 | 
				
			||||||
 | 
								<i class="fa fa-spinner fa-pulse fa-fw" if={ fetchingMoreMessages }></i>{ fetchingMoreMessages ? '%i18n:common.loading%' : '%i18n:common.tags.mk-messaging-room.more%' }
 | 
				
			||||||
 | 
							</button>
 | 
				
			||||||
		<virtual each={ message, i in messages }>
 | 
							<virtual each={ message, i in messages }>
 | 
				
			||||||
			<mk-messaging-message message={ message }/>
 | 
								<mk-messaging-message message={ message }/>
 | 
				
			||||||
			<p class="date" if={ i != messages.length - 1 && message._date != messages[i + 1]._date }><span>{ messages[i + 1]._datetext }</span></p>
 | 
								<p class="date" if={ i != messages.length - 1 && message._date != messages[i + 1]._date }><span>{ messages[i + 1]._datetext }</span></p>
 | 
				
			||||||
| 
						 | 
					@ -20,6 +24,17 @@
 | 
				
			||||||
				max-width 600px
 | 
									max-width 600px
 | 
				
			||||||
				margin 0 auto
 | 
									margin 0 auto
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									> .init
 | 
				
			||||||
 | 
										width 100%
 | 
				
			||||||
 | 
										margin 0
 | 
				
			||||||
 | 
										padding 16px 8px 8px 8px
 | 
				
			||||||
 | 
										text-align center
 | 
				
			||||||
 | 
										font-size 0.8em
 | 
				
			||||||
 | 
										color rgba(0, 0, 0, 0.4)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										i
 | 
				
			||||||
 | 
											margin-right 4px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				> .empty
 | 
									> .empty
 | 
				
			||||||
					width 100%
 | 
										width 100%
 | 
				
			||||||
					margin 0
 | 
										margin 0
 | 
				
			||||||
| 
						 | 
					@ -42,6 +57,27 @@
 | 
				
			||||||
					i
 | 
										i
 | 
				
			||||||
						margin-right 4px
 | 
											margin-right 4px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									> .more
 | 
				
			||||||
 | 
										display block
 | 
				
			||||||
 | 
										margin 16px auto
 | 
				
			||||||
 | 
										padding 0 12px
 | 
				
			||||||
 | 
										line-height 24px
 | 
				
			||||||
 | 
										color #fff
 | 
				
			||||||
 | 
										background rgba(0, 0, 0, 0.3)
 | 
				
			||||||
 | 
										border-radius 12px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										&:hover
 | 
				
			||||||
 | 
											background rgba(0, 0, 0, 0.4)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										&:active
 | 
				
			||||||
 | 
											background rgba(0, 0, 0, 0.5)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										&.fetching
 | 
				
			||||||
 | 
											cursor wait
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										> i
 | 
				
			||||||
 | 
											margin-right 4px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				> .message
 | 
									> .message
 | 
				
			||||||
					// something
 | 
										// something
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -90,6 +126,9 @@
 | 
				
			||||||
					padding 8px 0
 | 
										padding 8px 0
 | 
				
			||||||
					text-align center
 | 
										text-align center
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										&:empty
 | 
				
			||||||
 | 
											display none
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					> p
 | 
										> p
 | 
				
			||||||
						display inline-block
 | 
											display inline-block
 | 
				
			||||||
						margin 0
 | 
											margin 0
 | 
				
			||||||
| 
						 | 
					@ -137,24 +176,21 @@
 | 
				
			||||||
		this.connection = new MessagingStreamConnection(this.I, this.user.id);
 | 
							this.connection = new MessagingStreamConnection(this.I, this.user.id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		this.on('mount', () => {
 | 
							this.on('mount', () => {
 | 
				
			||||||
			this.connection.event.on('message', this.onMessage);
 | 
								this.connection.on('message', this.onMessage);
 | 
				
			||||||
			this.connection.event.on('read', this.onRead);
 | 
								this.connection.on('read', this.onRead);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			document.addEventListener('visibilitychange', this.onVisibilitychange);
 | 
								document.addEventListener('visibilitychange', this.onVisibilitychange);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			this.api('messaging/messages', {
 | 
								this.fetchMessages().then(() => {
 | 
				
			||||||
				user_id: this.user.id
 | 
					 | 
				
			||||||
			}).then(messages => {
 | 
					 | 
				
			||||||
				this.init = false;
 | 
									this.init = false;
 | 
				
			||||||
				this.messages = messages.reverse();
 | 
					 | 
				
			||||||
				this.update();
 | 
									this.update();
 | 
				
			||||||
				this.scrollToBottom();
 | 
									this.scrollToBottom();
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		this.on('unmount', () => {
 | 
							this.on('unmount', () => {
 | 
				
			||||||
			this.connection.event.off('message', this.onMessage);
 | 
								this.connection.off('message', this.onMessage);
 | 
				
			||||||
			this.connection.event.off('read', this.onRead);
 | 
								this.connection.off('read', this.onRead);
 | 
				
			||||||
			this.connection.close();
 | 
								this.connection.close();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			document.removeEventListener('visibilitychange', this.onVisibilitychange);
 | 
								document.removeEventListener('visibilitychange', this.onVisibilitychange);
 | 
				
			||||||
| 
						 | 
					@ -174,10 +210,10 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			this.messages.push(message);
 | 
								this.messages.push(message);
 | 
				
			||||||
			if (message.user_id != this.I.id && !document.hidden) {
 | 
								if (message.user_id != this.I.id && !document.hidden) {
 | 
				
			||||||
				this.connection.socket.send(JSON.stringify({
 | 
									this.connection.send({
 | 
				
			||||||
					type: 'read',
 | 
										type: 'read',
 | 
				
			||||||
					id: message.id
 | 
										id: message.id
 | 
				
			||||||
				}));
 | 
									});
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			this.update();
 | 
								this.update();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -201,6 +237,39 @@
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this.fetchMoreMessages = () => {
 | 
				
			||||||
 | 
								this.update({
 | 
				
			||||||
 | 
									fetchingMoreMessages: true
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
								this.fetchMessages().then(() => {
 | 
				
			||||||
 | 
									this.update({
 | 
				
			||||||
 | 
										fetchingMoreMessages: false
 | 
				
			||||||
 | 
									});
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this.fetchMessages = () => new Promise((resolve, reject) => {
 | 
				
			||||||
 | 
								const max = this.moreMessagesIsInStock ? 20 : 10;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								this.api('messaging/messages', {
 | 
				
			||||||
 | 
									user_id: this.user.id,
 | 
				
			||||||
 | 
									limit: max + 1,
 | 
				
			||||||
 | 
									max_id: this.moreMessagesIsInStock ? this.messages[0].id : undefined
 | 
				
			||||||
 | 
								}).then(messages => {
 | 
				
			||||||
 | 
									if (messages.length == max + 1) {
 | 
				
			||||||
 | 
										this.moreMessagesIsInStock = true;
 | 
				
			||||||
 | 
										messages.pop();
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										this.moreMessagesIsInStock = false;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									this.messages.unshift.apply(this.messages, messages.reverse());
 | 
				
			||||||
 | 
									this.update();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									resolve();
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		this.isBottom = () => {
 | 
							this.isBottom = () => {
 | 
				
			||||||
			const asobi = 32;
 | 
								const asobi = 32;
 | 
				
			||||||
			const current = this.isNaked
 | 
								const current = this.isNaked
 | 
				
			||||||
| 
						 | 
					@ -239,10 +308,10 @@
 | 
				
			||||||
			if (document.hidden) return;
 | 
								if (document.hidden) return;
 | 
				
			||||||
			this.messages.forEach(message => {
 | 
								this.messages.forEach(message => {
 | 
				
			||||||
				if (message.user_id !== this.I.id && !message.is_read) {
 | 
									if (message.user_id !== this.I.id && !message.is_read) {
 | 
				
			||||||
					this.connection.socket.send(JSON.stringify({
 | 
										this.connection.send({
 | 
				
			||||||
						type: 'read',
 | 
											type: 'read',
 | 
				
			||||||
						id: message.id
 | 
											id: message.id
 | 
				
			||||||
					}));
 | 
										});
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -74,4 +74,18 @@ function registerNotifications(stream) {
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
		setTimeout(n.close.bind(n), 6000);
 | 
							setTimeout(n.close.bind(n), 6000);
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stream.on('unread_messaging_message', message => {
 | 
				
			||||||
 | 
							const n = new Notification(`${message.user.name}さんからメッセージ:`, {
 | 
				
			||||||
 | 
								body: message.text, // TODO: getMessagingMessageSummary(message),
 | 
				
			||||||
 | 
								icon: message.user.avatar_url + '?thumbnail&size=64'
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
							n.onclick = () => {
 | 
				
			||||||
 | 
								n.close();
 | 
				
			||||||
 | 
								riot.mount(document.body.appendChild(document.createElement('mk-messaging-room-window')), {
 | 
				
			||||||
 | 
									user: message.user
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
							setTimeout(n.close.bind(n), 7000);
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,11 +1,9 @@
 | 
				
			||||||
<mk-activity-home-widget>
 | 
					<mk-activity-home-widget>
 | 
				
			||||||
	<p class="title"><i class="fa fa-bar-chart"></i>%i18n:desktop.tags.mk-activity-home-widget.title%</p>
 | 
						<p class="title"><i class="fa fa-bar-chart"></i>%i18n:desktop.tags.mk-activity-home-widget.title%</p>
 | 
				
			||||||
 | 
						<button onclick={ toggle } title="%i18n:desktop.tags.mk-activity-home-widget.toggle%"><i class="fa fa-sort"></i></button>
 | 
				
			||||||
	<p class="initializing" if={ initializing }><i class="fa fa-spinner fa-pulse fa-fw"></i>%i18n:common.loading%<mk-ellipsis/></p>
 | 
						<p class="initializing" if={ initializing }><i class="fa fa-spinner fa-pulse fa-fw"></i>%i18n:common.loading%<mk-ellipsis/></p>
 | 
				
			||||||
	<svg if={ !initializing } ref="canvas" viewBox="0 0 21 7" preserveAspectRatio="none">
 | 
						<mk-activity-home-widget-calender if={ !initializing && view == 0 } data={ [].concat(data) }/>
 | 
				
			||||||
		<rect each={ data } width="1" height="1"
 | 
						<mk-activity-home-widget-chart if={ !initializing && view == 1 } data={ [].concat(data) }/>
 | 
				
			||||||
			riot-x={ x } riot-y={ date.weekday }
 | 
					 | 
				
			||||||
			fill={ color }></rect>
 | 
					 | 
				
			||||||
	</svg>
 | 
					 | 
				
			||||||
	<style>
 | 
						<style>
 | 
				
			||||||
		:scope
 | 
							:scope
 | 
				
			||||||
			display block
 | 
								display block
 | 
				
			||||||
| 
						 | 
					@ -24,6 +22,23 @@
 | 
				
			||||||
				> i
 | 
									> i
 | 
				
			||||||
					margin-right 4px
 | 
										margin-right 4px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								> button
 | 
				
			||||||
 | 
									position absolute
 | 
				
			||||||
 | 
									z-index 2
 | 
				
			||||||
 | 
									top 0
 | 
				
			||||||
 | 
									right 0
 | 
				
			||||||
 | 
									padding 0
 | 
				
			||||||
 | 
									width 42px
 | 
				
			||||||
 | 
									font-size 0.9em
 | 
				
			||||||
 | 
									line-height 42px
 | 
				
			||||||
 | 
									color #ccc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									&:hover
 | 
				
			||||||
 | 
										color #aaa
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									&:active
 | 
				
			||||||
 | 
										color #999
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			> .initializing
 | 
								> .initializing
 | 
				
			||||||
				margin 0
 | 
									margin 0
 | 
				
			||||||
				padding 16px
 | 
									padding 16px
 | 
				
			||||||
| 
						 | 
					@ -33,6 +48,60 @@
 | 
				
			||||||
				> i
 | 
									> i
 | 
				
			||||||
					margin-right 4px
 | 
										margin-right 4px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						</style>
 | 
				
			||||||
 | 
						<script>
 | 
				
			||||||
 | 
							this.mixin('i');
 | 
				
			||||||
 | 
							this.mixin('api');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this.initializing = true;
 | 
				
			||||||
 | 
							this.view = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this.on('mount', () => {
 | 
				
			||||||
 | 
								this.api('aggregation/users/activity', {
 | 
				
			||||||
 | 
									user_id: this.I.id,
 | 
				
			||||||
 | 
									limit: 20 * 7
 | 
				
			||||||
 | 
								}).then(data => {
 | 
				
			||||||
 | 
									this.update({
 | 
				
			||||||
 | 
										initializing: false,
 | 
				
			||||||
 | 
										data
 | 
				
			||||||
 | 
									});
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this.toggle = () => {
 | 
				
			||||||
 | 
								this.view++;
 | 
				
			||||||
 | 
								if (this.view == 2) this.view = 0;
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
						</script>
 | 
				
			||||||
 | 
					</mk-activity-home-widget>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<mk-activity-home-widget-calender>
 | 
				
			||||||
 | 
						<svg viewBox="0 0 21 7" preserveAspectRatio="none">
 | 
				
			||||||
 | 
							<rect each={ data } class="day"
 | 
				
			||||||
 | 
								width="1" height="1"
 | 
				
			||||||
 | 
								riot-x={ x } riot-y={ date.weekday }
 | 
				
			||||||
 | 
								rx="1" ry="1"
 | 
				
			||||||
 | 
								fill="transparent">
 | 
				
			||||||
 | 
								<title>{ date.year }/{ date.month }/{ date.day }<br/>Post: { posts }, Reply: { replies }, Repost: { reposts }</title>
 | 
				
			||||||
 | 
							</rect>
 | 
				
			||||||
 | 
							<rect each={ data }
 | 
				
			||||||
 | 
								width="1" height="1"
 | 
				
			||||||
 | 
								riot-x={ x } riot-y={ date.weekday }
 | 
				
			||||||
 | 
								rx="1" ry="1"
 | 
				
			||||||
 | 
								fill={ color }
 | 
				
			||||||
 | 
								style="pointer-events: none; transform: scale({ v });"/>
 | 
				
			||||||
 | 
							<rect class="today"
 | 
				
			||||||
 | 
								width="1" height="1"
 | 
				
			||||||
 | 
								riot-x={ data[data.length - 1].x } riot-y={ data[data.length - 1].date.weekday }
 | 
				
			||||||
 | 
								rx="1" ry="1"
 | 
				
			||||||
 | 
								fill="none"
 | 
				
			||||||
 | 
								stroke-width="0.1"
 | 
				
			||||||
 | 
								stroke="#f73520"/>
 | 
				
			||||||
 | 
						</svg>
 | 
				
			||||||
 | 
						<style>
 | 
				
			||||||
 | 
							:scope
 | 
				
			||||||
 | 
								display block
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			> svg
 | 
								> svg
 | 
				
			||||||
				display block
 | 
									display block
 | 
				
			||||||
				padding 10px
 | 
									padding 10px
 | 
				
			||||||
| 
						 | 
					@ -40,37 +109,121 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				> rect
 | 
									> rect
 | 
				
			||||||
					transform-origin center
 | 
										transform-origin center
 | 
				
			||||||
					transform scale(0.8)
 | 
					
 | 
				
			||||||
 | 
										&.day
 | 
				
			||||||
 | 
											&:hover
 | 
				
			||||||
 | 
												fill rgba(0, 0, 0, 0.05)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	</style>
 | 
						</style>
 | 
				
			||||||
	<script>
 | 
						<script>
 | 
				
			||||||
		this.mixin('i');
 | 
							this.data = this.opts.data;
 | 
				
			||||||
		this.mixin('api');
 | 
							this.data.forEach(d => d.total = d.posts + d.replies + d.reposts);
 | 
				
			||||||
 | 
							const peak = Math.max.apply(null, this.data.map(d => d.total));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		this.initializing = true;
 | 
							let x = 0;
 | 
				
			||||||
 | 
							this.data.reverse().forEach(d => {
 | 
				
			||||||
		this.on('mount', () => {
 | 
								d.x = x;
 | 
				
			||||||
			this.api('aggregation/users/activity', {
 | 
								d.v = d.total / (peak / 2);
 | 
				
			||||||
				user_id: this.I.id,
 | 
								if (d.v > 1) d.v = 1;
 | 
				
			||||||
				limit: 20 * 7
 | 
								d.color = `hsl(170, ${d.v * 100}%, ${15 + ((1 - d.v) * 80)}%)`;
 | 
				
			||||||
			}).then(data => {
 | 
								d.date.weekday = (new Date(d.date.year, d.date.month - 1, d.date.day)).getDay();
 | 
				
			||||||
				data.forEach(d => d.total = d.posts + d.replies + d.reposts);
 | 
								if (d.date.weekday == 6) x++;
 | 
				
			||||||
				this.peak = Math.max.apply(null, data.map(d => d.total)) / 2;
 | 
					 | 
				
			||||||
				let x = 0;
 | 
					 | 
				
			||||||
				data.reverse().forEach(d => {
 | 
					 | 
				
			||||||
					d.x = x;
 | 
					 | 
				
			||||||
					let v = d.total / this.peak;
 | 
					 | 
				
			||||||
					if (v > 1) v = 1;
 | 
					 | 
				
			||||||
					d.color = `hsl(180, ${v * 100}%, ${15 + ((1 - v) * 80)}%)`;
 | 
					 | 
				
			||||||
					d.date.weekday = (new Date(d.date.year, d.date.month - 1, d.date.day)).getDay();
 | 
					 | 
				
			||||||
					if (d.date.weekday == 6) x++;
 | 
					 | 
				
			||||||
				});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				this.update({
 | 
					 | 
				
			||||||
					initializing: false,
 | 
					 | 
				
			||||||
					data
 | 
					 | 
				
			||||||
				});
 | 
					 | 
				
			||||||
			});
 | 
					 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
	</script>
 | 
						</script>
 | 
				
			||||||
</mk-activity-home-widget>
 | 
					</mk-activity-home-widget-calender>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<mk-activity-home-widget-chart>
 | 
				
			||||||
 | 
						<svg riot-viewBox="0 0 { viewBoxX } { viewBoxY }" preserveAspectRatio="none" onmousedown={ onMousedown }>
 | 
				
			||||||
 | 
							<title>Black ... Total<br/>Blue ... Posts<br/>Red ... Replies<br/>Green ... Reposts</title>
 | 
				
			||||||
 | 
							<polyline
 | 
				
			||||||
 | 
								riot-points={ pointsPost }
 | 
				
			||||||
 | 
								fill="none"
 | 
				
			||||||
 | 
								stroke-width="1"
 | 
				
			||||||
 | 
								stroke="#41ddde"/>
 | 
				
			||||||
 | 
							<polyline
 | 
				
			||||||
 | 
								riot-points={ pointsReply }
 | 
				
			||||||
 | 
								fill="none"
 | 
				
			||||||
 | 
								stroke-width="1"
 | 
				
			||||||
 | 
								stroke="#f7796c"/>
 | 
				
			||||||
 | 
							<polyline
 | 
				
			||||||
 | 
								riot-points={ pointsRepost }
 | 
				
			||||||
 | 
								fill="none"
 | 
				
			||||||
 | 
								stroke-width="1"
 | 
				
			||||||
 | 
								stroke="#a1de41"/>
 | 
				
			||||||
 | 
							<polyline
 | 
				
			||||||
 | 
								riot-points={ pointsTotal }
 | 
				
			||||||
 | 
								fill="none"
 | 
				
			||||||
 | 
								stroke-width="1"
 | 
				
			||||||
 | 
								stroke="#555"
 | 
				
			||||||
 | 
								stroke-dasharray="2 2"/>
 | 
				
			||||||
 | 
						</svg>
 | 
				
			||||||
 | 
						<style>
 | 
				
			||||||
 | 
							:scope
 | 
				
			||||||
 | 
								display block
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								> svg
 | 
				
			||||||
 | 
									display block
 | 
				
			||||||
 | 
									padding 10px
 | 
				
			||||||
 | 
									width 100%
 | 
				
			||||||
 | 
									cursor all-scroll
 | 
				
			||||||
 | 
						</style>
 | 
				
			||||||
 | 
						<script>
 | 
				
			||||||
 | 
							this.viewBoxX = 140;
 | 
				
			||||||
 | 
							this.viewBoxY = 60;
 | 
				
			||||||
 | 
							this.zoom = 1;
 | 
				
			||||||
 | 
							this.pos = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this.data = this.opts.data.reverse();
 | 
				
			||||||
 | 
							this.data.forEach(d => d.total = d.posts + d.replies + d.reposts);
 | 
				
			||||||
 | 
							const peak = Math.max.apply(null, this.data.map(d => d.total));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this.on('mount', () => {
 | 
				
			||||||
 | 
								this.render();
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this.render = () => {
 | 
				
			||||||
 | 
								this.update({
 | 
				
			||||||
 | 
									pointsPost: this.data.map((d, i) => `${(i * this.zoom) + this.pos},${(1 - (d.posts / peak)) * this.viewBoxY}`).join(' '),
 | 
				
			||||||
 | 
									pointsReply: this.data.map((d, i) => `${(i * this.zoom) + this.pos},${(1 - (d.replies / peak)) * this.viewBoxY}`).join(' '),
 | 
				
			||||||
 | 
									pointsRepost: this.data.map((d, i) => `${(i * this.zoom) + this.pos},${(1 - (d.reposts / peak)) * this.viewBoxY}`).join(' '),
 | 
				
			||||||
 | 
									pointsTotal: this.data.map((d, i) => `${(i * this.zoom) + this.pos},${(1 - (d.total / peak)) * this.viewBoxY}`).join(' ')
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this.onMousedown = e => {
 | 
				
			||||||
 | 
								e.preventDefault();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								const clickX = e.clientX;
 | 
				
			||||||
 | 
								const clickY = e.clientY;
 | 
				
			||||||
 | 
								const baseZoom = this.zoom;
 | 
				
			||||||
 | 
								const basePos = this.pos;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// 動かした時
 | 
				
			||||||
 | 
								dragListen(me => {
 | 
				
			||||||
 | 
									let moveLeft = me.clientX - clickX;
 | 
				
			||||||
 | 
									let moveTop = me.clientY - clickY;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									this.zoom = baseZoom + (-moveTop / 20);
 | 
				
			||||||
 | 
									this.pos = basePos + moveLeft;
 | 
				
			||||||
 | 
									if (this.zoom < 1) this.zoom = 1;
 | 
				
			||||||
 | 
									if (this.pos > 0) this.pos = 0;
 | 
				
			||||||
 | 
									if (this.pos < -(((this.data.length - 1) * this.zoom) - this.viewBoxX)) this.pos = -(((this.data.length - 1) * this.zoom) - this.viewBoxX);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									this.render();
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							function dragListen(fn) {
 | 
				
			||||||
 | 
								window.addEventListener('mousemove',  fn);
 | 
				
			||||||
 | 
								window.addEventListener('mouseleave', dragClear.bind(null, fn));
 | 
				
			||||||
 | 
								window.addEventListener('mouseup',    dragClear.bind(null, fn));
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							function dragClear(fn) {
 | 
				
			||||||
 | 
								window.removeEventListener('mousemove',  fn);
 | 
				
			||||||
 | 
								window.removeEventListener('mouseleave', dragClear);
 | 
				
			||||||
 | 
								window.removeEventListener('mouseup',    dragClear);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						</script>
 | 
				
			||||||
 | 
					</mk-activity-home-widget-chart>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										510
									
								
								src/web/app/desktop/tags/home-widgets/server.tag
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										510
									
								
								src/web/app/desktop/tags/home-widgets/server.tag
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,510 @@
 | 
				
			||||||
 | 
					<mk-server-home-widget>
 | 
				
			||||||
 | 
						<p class="title"><i class="fa fa-server"></i>%i18n:desktop.tags.mk-server-home-widget.title%</p>
 | 
				
			||||||
 | 
						<button onclick={ toggle } title="%i18n:desktop.tags.mk-server-home-widget.toggle%"><i class="fa fa-sort"></i></button>
 | 
				
			||||||
 | 
						<p class="initializing" if={ initializing }><i class="fa fa-spinner fa-pulse fa-fw"></i>%i18n:common.loading%<mk-ellipsis/></p>
 | 
				
			||||||
 | 
						<mk-server-home-widget-cpu-and-memory-usage if={ !initializing } show={ view == 0 } connection={ connection }/>
 | 
				
			||||||
 | 
						<mk-server-home-widget-cpu if={ !initializing } show={ view == 1 } connection={ connection } meta={ meta }/>
 | 
				
			||||||
 | 
						<mk-server-home-widget-memory if={ !initializing } show={ view == 2 } connection={ connection }/>
 | 
				
			||||||
 | 
						<mk-server-home-widget-disk if={ !initializing } show={ view == 3 } connection={ connection }/>
 | 
				
			||||||
 | 
						<mk-server-home-widget-uptimes if={ !initializing } show={ view == 4 } connection={ connection }/>
 | 
				
			||||||
 | 
						<mk-server-home-widget-info if={ !initializing } show={ view == 5 } connection={ connection } meta={ meta }/>
 | 
				
			||||||
 | 
						<style>
 | 
				
			||||||
 | 
							:scope
 | 
				
			||||||
 | 
								display block
 | 
				
			||||||
 | 
								background #fff
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								> .title
 | 
				
			||||||
 | 
									z-index 1
 | 
				
			||||||
 | 
									margin 0
 | 
				
			||||||
 | 
									padding 0 16px
 | 
				
			||||||
 | 
									line-height 42px
 | 
				
			||||||
 | 
									font-size 0.9em
 | 
				
			||||||
 | 
									font-weight bold
 | 
				
			||||||
 | 
									color #888
 | 
				
			||||||
 | 
									box-shadow 0 1px rgba(0, 0, 0, 0.07)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									> i
 | 
				
			||||||
 | 
										margin-right 4px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								> button
 | 
				
			||||||
 | 
									position absolute
 | 
				
			||||||
 | 
									z-index 2
 | 
				
			||||||
 | 
									top 0
 | 
				
			||||||
 | 
									right 0
 | 
				
			||||||
 | 
									padding 0
 | 
				
			||||||
 | 
									width 42px
 | 
				
			||||||
 | 
									font-size 0.9em
 | 
				
			||||||
 | 
									line-height 42px
 | 
				
			||||||
 | 
									color #ccc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									&:hover
 | 
				
			||||||
 | 
										color #aaa
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									&:active
 | 
				
			||||||
 | 
										color #999
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								> .initializing
 | 
				
			||||||
 | 
									margin 0
 | 
				
			||||||
 | 
									padding 16px
 | 
				
			||||||
 | 
									text-align center
 | 
				
			||||||
 | 
									color #aaa
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									> i
 | 
				
			||||||
 | 
										margin-right 4px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						</style>
 | 
				
			||||||
 | 
						<script>
 | 
				
			||||||
 | 
							import Connection from '../../../common/scripts/server-stream';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this.mixin('api');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this.initializing = true;
 | 
				
			||||||
 | 
							this.view = 0;
 | 
				
			||||||
 | 
							this.connection = new Connection();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this.on('mount', () => {
 | 
				
			||||||
 | 
								this.api('meta').then(meta => {
 | 
				
			||||||
 | 
									this.update({
 | 
				
			||||||
 | 
										initializing: false,
 | 
				
			||||||
 | 
										meta
 | 
				
			||||||
 | 
									});
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this.on('unmount', () => {
 | 
				
			||||||
 | 
								this.connection.close();
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this.toggle = () => {
 | 
				
			||||||
 | 
								this.view++;
 | 
				
			||||||
 | 
								if (this.view == 6) this.view = 0;
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
						</script>
 | 
				
			||||||
 | 
					</mk-server-home-widget>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<mk-server-home-widget-cpu-and-memory-usage>
 | 
				
			||||||
 | 
						<svg riot-viewBox="0 0 { viewBoxX } { viewBoxY }" preserveAspectRatio="none">
 | 
				
			||||||
 | 
							<defs>
 | 
				
			||||||
 | 
								<linearGradient id={ cpuGradientId } x1="0" x2="0" y1="1" y2="0">
 | 
				
			||||||
 | 
									<stop offset="0%" stop-color="hsl(180, 80%, 70%)"></stop>
 | 
				
			||||||
 | 
									<stop offset="33%" stop-color="hsl(120, 80%, 70%)"></stop>
 | 
				
			||||||
 | 
									<stop offset="66%" stop-color="hsl(60, 80%, 70%)"></stop>
 | 
				
			||||||
 | 
									<stop offset="100%" stop-color="hsl(0, 80%, 70%)"></stop>
 | 
				
			||||||
 | 
								</linearGradient>
 | 
				
			||||||
 | 
								<mask id={ cpuMaskId } x="0" y="0" riot-width={ viewBoxX } riot-height={ viewBoxY }>
 | 
				
			||||||
 | 
									<polygon
 | 
				
			||||||
 | 
										riot-points={ cpuPolygonPoints }
 | 
				
			||||||
 | 
										fill="#fff"
 | 
				
			||||||
 | 
										fill-opacity="0.5"/>
 | 
				
			||||||
 | 
									<polyline
 | 
				
			||||||
 | 
										riot-points={ cpuPolylinePoints }
 | 
				
			||||||
 | 
										fill="none"
 | 
				
			||||||
 | 
										stroke="#fff"
 | 
				
			||||||
 | 
										stroke-width="1"/>
 | 
				
			||||||
 | 
								</mask>
 | 
				
			||||||
 | 
							</defs>
 | 
				
			||||||
 | 
							<rect
 | 
				
			||||||
 | 
								x="-1" y="-1"
 | 
				
			||||||
 | 
								riot-width={ viewBoxX + 2 } riot-height={ viewBoxY + 2 }
 | 
				
			||||||
 | 
								style="stroke: none; fill: url(#{ cpuGradientId }); mask: url(#{ cpuMaskId })"/>
 | 
				
			||||||
 | 
							<text x="1" y="5">CPU <tspan>{ cpuP }%</tspan></text>
 | 
				
			||||||
 | 
						</svg>
 | 
				
			||||||
 | 
						<svg riot-viewBox="0 0 { viewBoxX } { viewBoxY }" preserveAspectRatio="none">
 | 
				
			||||||
 | 
							<defs>
 | 
				
			||||||
 | 
								<linearGradient id={ memGradientId } x1="0" x2="0" y1="1" y2="0">
 | 
				
			||||||
 | 
									<stop offset="0%" stop-color="hsl(180, 80%, 70%)"></stop>
 | 
				
			||||||
 | 
									<stop offset="33%" stop-color="hsl(120, 80%, 70%)"></stop>
 | 
				
			||||||
 | 
									<stop offset="66%" stop-color="hsl(60, 80%, 70%)"></stop>
 | 
				
			||||||
 | 
									<stop offset="100%" stop-color="hsl(0, 80%, 70%)"></stop>
 | 
				
			||||||
 | 
								</linearGradient>
 | 
				
			||||||
 | 
								<mask id={ memMaskId } x="0" y="0" riot-width={ viewBoxX } riot-height={ viewBoxY }>
 | 
				
			||||||
 | 
									<polygon
 | 
				
			||||||
 | 
										riot-points={ memPolygonPoints }
 | 
				
			||||||
 | 
										fill="#fff"
 | 
				
			||||||
 | 
										fill-opacity="0.5"/>
 | 
				
			||||||
 | 
									<polyline
 | 
				
			||||||
 | 
										riot-points={ memPolylinePoints }
 | 
				
			||||||
 | 
										fill="none"
 | 
				
			||||||
 | 
										stroke="#fff"
 | 
				
			||||||
 | 
										stroke-width="1"/>
 | 
				
			||||||
 | 
								</mask>
 | 
				
			||||||
 | 
							</defs>
 | 
				
			||||||
 | 
							<rect
 | 
				
			||||||
 | 
								x="-1" y="-1"
 | 
				
			||||||
 | 
								riot-width={ viewBoxX + 2 } riot-height={ viewBoxY + 2 }
 | 
				
			||||||
 | 
								style="stroke: none; fill: url(#{ memGradientId }); mask: url(#{ memMaskId })"/>
 | 
				
			||||||
 | 
							<text x="1" y="5">MEM <tspan>{ memP }%</tspan></text>
 | 
				
			||||||
 | 
						</svg>
 | 
				
			||||||
 | 
						<style>
 | 
				
			||||||
 | 
							:scope
 | 
				
			||||||
 | 
								display block
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								> svg
 | 
				
			||||||
 | 
									display block
 | 
				
			||||||
 | 
									padding 10px
 | 
				
			||||||
 | 
									width 50%
 | 
				
			||||||
 | 
									float left
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									&:first-child
 | 
				
			||||||
 | 
										padding-right 5px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									&:last-child
 | 
				
			||||||
 | 
										padding-left 5px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									> text
 | 
				
			||||||
 | 
										font-size 5px
 | 
				
			||||||
 | 
										fill rgba(0, 0, 0, 0.55)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										> tspan
 | 
				
			||||||
 | 
											opacity 0.5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								&:after
 | 
				
			||||||
 | 
									content ""
 | 
				
			||||||
 | 
									display block
 | 
				
			||||||
 | 
									clear both
 | 
				
			||||||
 | 
						</style>
 | 
				
			||||||
 | 
						<script>
 | 
				
			||||||
 | 
							import uuid from '../../../common/scripts/uuid';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this.viewBoxX = 50;
 | 
				
			||||||
 | 
							this.viewBoxY = 30;
 | 
				
			||||||
 | 
							this.stats = [];
 | 
				
			||||||
 | 
							this.connection = this.opts.connection;
 | 
				
			||||||
 | 
							this.cpuGradientId = uuid();
 | 
				
			||||||
 | 
							this.cpuMaskId = uuid();
 | 
				
			||||||
 | 
							this.memGradientId = uuid();
 | 
				
			||||||
 | 
							this.memMaskId = uuid();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this.on('mount', () => {
 | 
				
			||||||
 | 
								this.connection.on('stats', this.onStats);
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this.on('unmount', () => {
 | 
				
			||||||
 | 
								this.connection.off('stats', this.onStats);
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this.onStats = stats => {
 | 
				
			||||||
 | 
								stats.mem.used = stats.mem.total - stats.mem.free;
 | 
				
			||||||
 | 
								this.stats.push(stats);
 | 
				
			||||||
 | 
								if (this.stats.length > 50) this.stats.shift();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								const cpuPolylinePoints = this.stats.map((s, i) => `${this.viewBoxX - ((this.stats.length - 1) - i)},${(1 - s.cpu_usage) * this.viewBoxY}`).join(' ');
 | 
				
			||||||
 | 
								const memPolylinePoints = this.stats.map((s, i) => `${this.viewBoxX - ((this.stats.length - 1) - i)},${(1 - (s.mem.used / s.mem.total)) * this.viewBoxY}`).join(' ');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								const cpuPolygonPoints = `${this.viewBoxX - (this.stats.length - 1)},${ this.viewBoxY } ${ cpuPolylinePoints } ${ this.viewBoxX },${ this.viewBoxY }`;
 | 
				
			||||||
 | 
								const memPolygonPoints = `${this.viewBoxX - (this.stats.length - 1)},${ this.viewBoxY } ${ memPolylinePoints } ${ this.viewBoxX },${ this.viewBoxY }`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								const cpuP = (stats.cpu_usage * 100).toFixed(0);
 | 
				
			||||||
 | 
								const memP = (stats.mem.used / stats.mem.total * 100).toFixed(0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								this.update({
 | 
				
			||||||
 | 
									cpuPolylinePoints,
 | 
				
			||||||
 | 
									memPolylinePoints,
 | 
				
			||||||
 | 
									cpuPolygonPoints,
 | 
				
			||||||
 | 
									memPolygonPoints,
 | 
				
			||||||
 | 
									cpuP,
 | 
				
			||||||
 | 
									memP
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
						</script>
 | 
				
			||||||
 | 
					</mk-server-home-widget-cpu-and-memory-usage>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<mk-server-home-widget-cpu>
 | 
				
			||||||
 | 
						<mk-server-home-widget-pie ref="pie"/>
 | 
				
			||||||
 | 
						<div>
 | 
				
			||||||
 | 
							<p><i class="fa fa-microchip"></i>CPU</p>
 | 
				
			||||||
 | 
							<p>{ cores } Cores</p>
 | 
				
			||||||
 | 
							<p>{ model }</p>
 | 
				
			||||||
 | 
						</div>
 | 
				
			||||||
 | 
						<style>
 | 
				
			||||||
 | 
							:scope
 | 
				
			||||||
 | 
								display block
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								> mk-server-home-widget-pie
 | 
				
			||||||
 | 
									padding 10px
 | 
				
			||||||
 | 
									height 100px
 | 
				
			||||||
 | 
									float left
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								> div
 | 
				
			||||||
 | 
									float left
 | 
				
			||||||
 | 
									width calc(100% - 100px)
 | 
				
			||||||
 | 
									padding 10px 10px 10px 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									> p
 | 
				
			||||||
 | 
										margin 0
 | 
				
			||||||
 | 
										font-size 12px
 | 
				
			||||||
 | 
										color #505050
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										&:first-child
 | 
				
			||||||
 | 
											font-weight bold
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											> i
 | 
				
			||||||
 | 
												margin-right 4px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								&:after
 | 
				
			||||||
 | 
									content ""
 | 
				
			||||||
 | 
									display block
 | 
				
			||||||
 | 
									clear both
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						</style>
 | 
				
			||||||
 | 
						<script>
 | 
				
			||||||
 | 
							this.cores = this.opts.meta.cpu.cores;
 | 
				
			||||||
 | 
							this.model = this.opts.meta.cpu.model;
 | 
				
			||||||
 | 
							this.connection = this.opts.connection;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this.on('mount', () => {
 | 
				
			||||||
 | 
								this.connection.on('stats', this.onStats);
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this.on('unmount', () => {
 | 
				
			||||||
 | 
								this.connection.off('stats', this.onStats);
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this.onStats = stats => {
 | 
				
			||||||
 | 
								this.refs.pie.render(stats.cpu_usage);
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
						</script>
 | 
				
			||||||
 | 
					</mk-server-home-widget-cpu>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<mk-server-home-widget-memory>
 | 
				
			||||||
 | 
						<mk-server-home-widget-pie ref="pie"/>
 | 
				
			||||||
 | 
						<div>
 | 
				
			||||||
 | 
							<p><i class="fa fa-flask"></i>Memory</p>
 | 
				
			||||||
 | 
							<p>Total: { bytesToSize(total, 1) }</p>
 | 
				
			||||||
 | 
							<p>Used: { bytesToSize(used, 1) }</p>
 | 
				
			||||||
 | 
							<p>Free: { bytesToSize(free, 1) }</p>
 | 
				
			||||||
 | 
						</div>
 | 
				
			||||||
 | 
						<style>
 | 
				
			||||||
 | 
							:scope
 | 
				
			||||||
 | 
								display block
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								> mk-server-home-widget-pie
 | 
				
			||||||
 | 
									padding 10px
 | 
				
			||||||
 | 
									height 100px
 | 
				
			||||||
 | 
									float left
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								> div
 | 
				
			||||||
 | 
									float left
 | 
				
			||||||
 | 
									width calc(100% - 100px)
 | 
				
			||||||
 | 
									padding 10px 10px 10px 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									> p
 | 
				
			||||||
 | 
										margin 0
 | 
				
			||||||
 | 
										font-size 12px
 | 
				
			||||||
 | 
										color #505050
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										&:first-child
 | 
				
			||||||
 | 
											font-weight bold
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											> i
 | 
				
			||||||
 | 
												margin-right 4px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								&:after
 | 
				
			||||||
 | 
									content ""
 | 
				
			||||||
 | 
									display block
 | 
				
			||||||
 | 
									clear both
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						</style>
 | 
				
			||||||
 | 
						<script>
 | 
				
			||||||
 | 
							import bytesToSize from '../../../common/scripts/bytes-to-size';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this.connection = this.opts.connection;
 | 
				
			||||||
 | 
							this.bytesToSize = bytesToSize;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this.on('mount', () => {
 | 
				
			||||||
 | 
								this.connection.on('stats', this.onStats);
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this.on('unmount', () => {
 | 
				
			||||||
 | 
								this.connection.off('stats', this.onStats);
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this.onStats = stats => {
 | 
				
			||||||
 | 
								stats.mem.used = stats.mem.total - stats.mem.free;
 | 
				
			||||||
 | 
								this.refs.pie.render(stats.mem.used / stats.mem.total);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								this.update({
 | 
				
			||||||
 | 
									total: stats.mem.total,
 | 
				
			||||||
 | 
									used: stats.mem.used,
 | 
				
			||||||
 | 
									free: stats.mem.free
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
						</script>
 | 
				
			||||||
 | 
					</mk-server-home-widget-memory>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<mk-server-home-widget-disk>
 | 
				
			||||||
 | 
						<mk-server-home-widget-pie ref="pie"/>
 | 
				
			||||||
 | 
						<div>
 | 
				
			||||||
 | 
							<p><i class="fa fa-hdd-o"></i>Storage</p>
 | 
				
			||||||
 | 
							<p>Total: { bytesToSize(total, 1) }</p>
 | 
				
			||||||
 | 
							<p>Available: { bytesToSize(available, 1) }</p>
 | 
				
			||||||
 | 
							<p>Used: { bytesToSize(used, 1) }</p>
 | 
				
			||||||
 | 
						</div>
 | 
				
			||||||
 | 
						<style>
 | 
				
			||||||
 | 
							:scope
 | 
				
			||||||
 | 
								display block
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								> mk-server-home-widget-pie
 | 
				
			||||||
 | 
									padding 10px
 | 
				
			||||||
 | 
									height 100px
 | 
				
			||||||
 | 
									float left
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								> div
 | 
				
			||||||
 | 
									float left
 | 
				
			||||||
 | 
									width calc(100% - 100px)
 | 
				
			||||||
 | 
									padding 10px 10px 10px 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									> p
 | 
				
			||||||
 | 
										margin 0
 | 
				
			||||||
 | 
										font-size 12px
 | 
				
			||||||
 | 
										color #505050
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										&:first-child
 | 
				
			||||||
 | 
											font-weight bold
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											> i
 | 
				
			||||||
 | 
												margin-right 4px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								&:after
 | 
				
			||||||
 | 
									content ""
 | 
				
			||||||
 | 
									display block
 | 
				
			||||||
 | 
									clear both
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						</style>
 | 
				
			||||||
 | 
						<script>
 | 
				
			||||||
 | 
							import bytesToSize from '../../../common/scripts/bytes-to-size';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this.connection = this.opts.connection;
 | 
				
			||||||
 | 
							this.bytesToSize = bytesToSize;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this.on('mount', () => {
 | 
				
			||||||
 | 
								this.connection.on('stats', this.onStats);
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this.on('unmount', () => {
 | 
				
			||||||
 | 
								this.connection.off('stats', this.onStats);
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this.onStats = stats => {
 | 
				
			||||||
 | 
								stats.disk.used = stats.disk.total - stats.disk.free;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								this.refs.pie.render(stats.disk.used / stats.disk.total);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								this.update({
 | 
				
			||||||
 | 
									total: stats.disk.total,
 | 
				
			||||||
 | 
									used: stats.disk.used,
 | 
				
			||||||
 | 
									available: stats.disk.available
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
						</script>
 | 
				
			||||||
 | 
					</mk-server-home-widget-disk>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<mk-server-home-widget-uptimes>
 | 
				
			||||||
 | 
						<p>Uptimes</p>
 | 
				
			||||||
 | 
						<p>Process: { process ? process.toFixed(0) : '---' }s</p>
 | 
				
			||||||
 | 
						<p>OS: { os ? os.toFixed(0) : '---' }s</p>
 | 
				
			||||||
 | 
						<style>
 | 
				
			||||||
 | 
							:scope
 | 
				
			||||||
 | 
								display block
 | 
				
			||||||
 | 
								padding 10px 14px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								> p
 | 
				
			||||||
 | 
									margin 0
 | 
				
			||||||
 | 
									font-size 12px
 | 
				
			||||||
 | 
									color #505050
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									&:first-child
 | 
				
			||||||
 | 
										font-weight bold
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						</style>
 | 
				
			||||||
 | 
						<script>
 | 
				
			||||||
 | 
							this.connection = this.opts.connection;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this.on('mount', () => {
 | 
				
			||||||
 | 
								this.connection.on('stats', this.onStats);
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this.on('unmount', () => {
 | 
				
			||||||
 | 
								this.connection.off('stats', this.onStats);
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this.onStats = stats => {
 | 
				
			||||||
 | 
								this.update({
 | 
				
			||||||
 | 
									process: stats.process_uptime,
 | 
				
			||||||
 | 
									os: stats.os_uptime
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
						</script>
 | 
				
			||||||
 | 
					</mk-server-home-widget-uptimes>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<mk-server-home-widget-info>
 | 
				
			||||||
 | 
						<p>Maintainer: <b>{ meta.maintainer }</b></p>
 | 
				
			||||||
 | 
						<p>Machine: { meta.machine }</p>
 | 
				
			||||||
 | 
						<p>Node: { meta.node }</p>
 | 
				
			||||||
 | 
						<style>
 | 
				
			||||||
 | 
							:scope
 | 
				
			||||||
 | 
								display block
 | 
				
			||||||
 | 
								padding 10px 14px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								> p
 | 
				
			||||||
 | 
									margin 0
 | 
				
			||||||
 | 
									font-size 12px
 | 
				
			||||||
 | 
									color #505050
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						</style>
 | 
				
			||||||
 | 
						<script>
 | 
				
			||||||
 | 
							this.meta = this.opts.meta;
 | 
				
			||||||
 | 
						</script>
 | 
				
			||||||
 | 
					</mk-server-home-widget-info>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<mk-server-home-widget-pie>
 | 
				
			||||||
 | 
						<svg viewBox="0 0 1 1" preserveAspectRatio="none">
 | 
				
			||||||
 | 
							<circle
 | 
				
			||||||
 | 
								riot-r={ r }
 | 
				
			||||||
 | 
								cx="50%" cy="50%"
 | 
				
			||||||
 | 
								fill="none"
 | 
				
			||||||
 | 
								stroke-width="0.1"
 | 
				
			||||||
 | 
								stroke="rgba(0, 0, 0, 0.05)"/>
 | 
				
			||||||
 | 
							<circle
 | 
				
			||||||
 | 
								riot-r={ r }
 | 
				
			||||||
 | 
								cx="50%" cy="50%"
 | 
				
			||||||
 | 
								riot-stroke-dasharray={ Math.PI * (r * 2) }
 | 
				
			||||||
 | 
								riot-stroke-dashoffset={ strokeDashoffset }
 | 
				
			||||||
 | 
								fill="none"
 | 
				
			||||||
 | 
								stroke-width="0.1"
 | 
				
			||||||
 | 
								riot-stroke={ color }/>
 | 
				
			||||||
 | 
							<text x="50%" y="50%" dy="0.05" text-anchor="middle">{ (p * 100).toFixed(0) }%</text>
 | 
				
			||||||
 | 
						</svg>
 | 
				
			||||||
 | 
						<style>
 | 
				
			||||||
 | 
							:scope
 | 
				
			||||||
 | 
								display block
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								> svg
 | 
				
			||||||
 | 
									display block
 | 
				
			||||||
 | 
									height 100%
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									> circle
 | 
				
			||||||
 | 
										transform-origin center
 | 
				
			||||||
 | 
										transform rotate(-90deg)
 | 
				
			||||||
 | 
										transition stroke-dashoffset 0.5s ease
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									> text
 | 
				
			||||||
 | 
										font-size 0.15px
 | 
				
			||||||
 | 
										fill rgba(0, 0, 0, 0.6)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						</style>
 | 
				
			||||||
 | 
						<script>
 | 
				
			||||||
 | 
							this.r = 0.4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this.render = p => {
 | 
				
			||||||
 | 
								const color = `hsl(${180 - (p * 180)}, 80%, 70%)`;
 | 
				
			||||||
 | 
								const strokeDashoffset = (1 - p) * (Math.PI * (this.r * 2));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								this.update({
 | 
				
			||||||
 | 
									p,
 | 
				
			||||||
 | 
									color,
 | 
				
			||||||
 | 
									strokeDashoffset
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
						</script>
 | 
				
			||||||
 | 
					</mk-server-home-widget-pie>
 | 
				
			||||||
| 
						 | 
					@ -77,6 +77,7 @@
 | 
				
			||||||
				'notifications',
 | 
									'notifications',
 | 
				
			||||||
				'user-recommendation',
 | 
									'user-recommendation',
 | 
				
			||||||
				'recommended-polls',
 | 
									'recommended-polls',
 | 
				
			||||||
 | 
									'server',
 | 
				
			||||||
				'donation',
 | 
									'donation',
 | 
				
			||||||
				'nav',
 | 
									'nav',
 | 
				
			||||||
				'tips'
 | 
									'tips'
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -45,6 +45,7 @@ require('./home-widgets/version.tag');
 | 
				
			||||||
require('./home-widgets/recommended-polls.tag');
 | 
					require('./home-widgets/recommended-polls.tag');
 | 
				
			||||||
require('./home-widgets/trends.tag');
 | 
					require('./home-widgets/trends.tag');
 | 
				
			||||||
require('./home-widgets/activity.tag');
 | 
					require('./home-widgets/activity.tag');
 | 
				
			||||||
 | 
					require('./home-widgets/server.tag');
 | 
				
			||||||
require('./timeline.tag');
 | 
					require('./timeline.tag');
 | 
				
			||||||
require('./messaging/window.tag');
 | 
					require('./messaging/window.tag');
 | 
				
			||||||
require('./messaging/room-window.tag');
 | 
					require('./messaging/room-window.tag');
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -63,7 +63,7 @@
 | 
				
			||||||
			<p class="date" if={ i != notifications.length - 1 && notification._date != notifications[i + 1]._date }><span><i class="fa fa-angle-up"></i>{ notification._datetext }</span><span><i class="fa fa-angle-down"></i>{ notifications[i + 1]._datetext }</span></p>
 | 
								<p class="date" if={ i != notifications.length - 1 && notification._date != notifications[i + 1]._date }><span><i class="fa fa-angle-up"></i>{ notification._datetext }</span><span><i class="fa fa-angle-down"></i>{ notifications[i + 1]._datetext }</span></p>
 | 
				
			||||||
		</virtual>
 | 
							</virtual>
 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
	<button class="more" if={ moreNotifications } onclick={ fetchMoreNotifications } disabled={ fetchingMoreNotifications }>
 | 
						<button class="more { fetching: fetchingMoreNotifications }" if={ moreNotifications } onclick={ fetchMoreNotifications } disabled={ fetchingMoreNotifications }>
 | 
				
			||||||
		<i class="fa fa-spinner fa-pulse fa-fw" if={ fetchingMoreNotifications }></i>{ fetchingMoreNotifications ? '%i18n:common.loading%' : '%i18n:desktop.tags.mk-notifications.more%' }
 | 
							<i class="fa fa-spinner fa-pulse fa-fw" if={ fetchingMoreNotifications }></i>{ fetchingMoreNotifications ? '%i18n:common.loading%' : '%i18n:desktop.tags.mk-notifications.more%' }
 | 
				
			||||||
	</button>
 | 
						</button>
 | 
				
			||||||
	<p class="empty" if={ notifications.length == 0 && !loading }>ありません!</p>
 | 
						<p class="empty" if={ notifications.length == 0 && !loading }>ありません!</p>
 | 
				
			||||||
| 
						 | 
					@ -184,6 +184,9 @@
 | 
				
			||||||
				&:active
 | 
									&:active
 | 
				
			||||||
					background rgba(0, 0, 0, 0.05)
 | 
										background rgba(0, 0, 0, 0.05)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									&.fetching
 | 
				
			||||||
 | 
										cursor wait
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				> i
 | 
									> i
 | 
				
			||||||
					margin-right 4px
 | 
										margin-right 4px
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,7 +16,7 @@
 | 
				
			||||||
	<mk-uploader ref="uploader"/>
 | 
						<mk-uploader ref="uploader"/>
 | 
				
			||||||
	<button ref="upload" title="%i18n:desktop.tags.mk-post-form.attach-media-from-local%" onclick={ selectFile }><i class="fa fa-upload"></i></button>
 | 
						<button ref="upload" title="%i18n:desktop.tags.mk-post-form.attach-media-from-local%" onclick={ selectFile }><i class="fa fa-upload"></i></button>
 | 
				
			||||||
	<button ref="drive" title="%i18n:desktop.tags.mk-post-form.attach-media-from-drive%" onclick={ selectFileFromDrive }><i class="fa fa-cloud"></i></button>
 | 
						<button ref="drive" title="%i18n:desktop.tags.mk-post-form.attach-media-from-drive%" onclick={ selectFileFromDrive }><i class="fa fa-cloud"></i></button>
 | 
				
			||||||
	<button class="cat" title="%i18n:desktop.tags.mk-post-form.insert-the-cat%" onclick={ cat }><i class="fa fa-smile-o"></i></button>
 | 
						<button class="kao" title="%i18n:desktop.tags.mk-post-form.insert-a-kao%" onclick={ kao }><i class="fa fa-smile-o"></i></button>
 | 
				
			||||||
	<button class="poll" title="%i18n:desktop.tags.mk-post-form.create-poll%" onclick={ addPoll }><i class="fa fa-pie-chart"></i></button>
 | 
						<button class="poll" title="%i18n:desktop.tags.mk-post-form.create-poll%" onclick={ addPoll }><i class="fa fa-pie-chart"></i></button>
 | 
				
			||||||
	<p class="text-count { over: refs.text.value.length > 1000 }">{ '%i18n:desktop.tags.mk-post-form.text-remain%'.replace('{}', 1000 - refs.text.value.length) }</p>
 | 
						<p class="text-count { over: refs.text.value.length > 1000 }">{ '%i18n:desktop.tags.mk-post-form.text-remain%'.replace('{}', 1000 - refs.text.value.length) }</p>
 | 
				
			||||||
	<button class={ wait: wait } ref="submit" disabled={ wait || (refs.text.value.length == 0 && files.length == 0 && !poll && !repost) } onclick={ post }>
 | 
						<button class={ wait: wait } ref="submit" disabled={ wait || (refs.text.value.length == 0 && files.length == 0 && !poll && !repost) } onclick={ post }>
 | 
				
			||||||
| 
						 | 
					@ -258,7 +258,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			[ref='upload']
 | 
								[ref='upload']
 | 
				
			||||||
			[ref='drive']
 | 
								[ref='drive']
 | 
				
			||||||
			.cat
 | 
								.kao
 | 
				
			||||||
			.poll
 | 
								.poll
 | 
				
			||||||
				display inline-block
 | 
									display inline-block
 | 
				
			||||||
				cursor pointer
 | 
									cursor pointer
 | 
				
			||||||
| 
						 | 
					@ -306,7 +306,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	</style>
 | 
						</style>
 | 
				
			||||||
	<script>
 | 
						<script>
 | 
				
			||||||
		import getCat from '../../common/scripts/get-cat';
 | 
							import getKao from '../../common/scripts/get-kao';
 | 
				
			||||||
		import notify from '../scripts/notify';
 | 
							import notify from '../scripts/notify';
 | 
				
			||||||
		import Autocomplete from '../scripts/autocomplete';
 | 
							import Autocomplete from '../scripts/autocomplete';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -500,8 +500,8 @@
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		this.cat = () => {
 | 
							this.kao = () => {
 | 
				
			||||||
			this.refs.text.value += getCat();
 | 
								this.refs.text.value += getKao();
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		this.on('update', () => {
 | 
							this.on('update', () => {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,7 +8,8 @@ import * as riot from 'riot';
 | 
				
			||||||
import api from './common/scripts/api';
 | 
					import api from './common/scripts/api';
 | 
				
			||||||
import signout from './common/scripts/signout';
 | 
					import signout from './common/scripts/signout';
 | 
				
			||||||
import checkForUpdate from './common/scripts/check-for-update';
 | 
					import checkForUpdate from './common/scripts/check-for-update';
 | 
				
			||||||
import Connection from './common/scripts/stream';
 | 
					import Connection from './common/scripts/home-stream';
 | 
				
			||||||
 | 
					import Progress from './common/scripts/loading';
 | 
				
			||||||
import mixin from './common/mixins';
 | 
					import mixin from './common/mixins';
 | 
				
			||||||
import generateDefaultUserdata from './common/scripts/generate-default-userdata';
 | 
					import generateDefaultUserdata from './common/scripts/generate-default-userdata';
 | 
				
			||||||
import CONFIG from './common/scripts/config';
 | 
					import CONFIG from './common/scripts/config';
 | 
				
			||||||
| 
						 | 
					@ -95,7 +96,7 @@ export default callback => {
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Init stream connection
 | 
							// Init home stream connection
 | 
				
			||||||
		const stream = me ? new Connection(me) : null;
 | 
							const stream = me ? new Connection(me) : null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// ミックスイン初期化
 | 
							// ミックスイン初期化
 | 
				
			||||||
| 
						 | 
					@ -147,9 +148,10 @@ function fetchme(token, cb) {
 | 
				
			||||||
			me.data ? done() : init();
 | 
								me.data ? done() : init();
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
	}, () => { // When failure
 | 
						}, () => { // When failure
 | 
				
			||||||
		// Display error screen
 | 
							// Render the error screen
 | 
				
			||||||
		riot.mount(document.body.appendChild(
 | 
							document.body.innerHTML = '<mk-error />';
 | 
				
			||||||
			document.createElement('mk-error')));
 | 
							riot.mount('*');
 | 
				
			||||||
 | 
							Progress.done();
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	function done() {
 | 
						function done() {
 | 
				
			||||||
| 
						 | 
					@ -173,6 +175,7 @@ function panic(e) {
 | 
				
			||||||
	console.error(e);
 | 
						console.error(e);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Display blue screen
 | 
						// Display blue screen
 | 
				
			||||||
 | 
						document.documentElement.style.background = '#1269e2';
 | 
				
			||||||
	document.body.innerHTML =
 | 
						document.body.innerHTML =
 | 
				
			||||||
		'<div id="error">'
 | 
							'<div id="error">'
 | 
				
			||||||
			+ '<h1>:( 致命的な問題が発生しました。</h1>'
 | 
								+ '<h1>:( 致命的な問題が発生しました。</h1>'
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -39,7 +39,7 @@
 | 
				
			||||||
			</button>
 | 
								</button>
 | 
				
			||||||
		</div>
 | 
							</div>
 | 
				
			||||||
		<div class="empty" if={ files.length == 0 && folders.length == 0 && !fetching }>
 | 
							<div class="empty" if={ files.length == 0 && folders.length == 0 && !fetching }>
 | 
				
			||||||
			<p if={ !folder == null }>%i18n:mobile.tags.mk-drive.nothing-in-drive%</p>
 | 
								<p if={ folder == null }>%i18n:mobile.tags.mk-drive.nothing-in-drive%</p>
 | 
				
			||||||
			<p if={ folder != null }>%i18n:mobile.tags.mk-drive.folder-is-empty%</p>
 | 
								<p if={ folder != null }>%i18n:mobile.tags.mk-drive.folder-is-empty%</p>
 | 
				
			||||||
		</div>
 | 
							</div>
 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -63,7 +63,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				document.title = title;
 | 
									document.title = title;
 | 
				
			||||||
				// TODO: escape html characters in file.name
 | 
									// TODO: escape html characters in file.name
 | 
				
			||||||
				ui.trigger('title', '<mk-file-type-icon class="icon"/>' + file.name);
 | 
									ui.trigger('title', '<mk-file-type-icon class="icon"></mk-file-type-icon>' + file.name);
 | 
				
			||||||
				riot.mount('mk-file-type-icon', {
 | 
									riot.mount('mk-file-type-icon', {
 | 
				
			||||||
					type: file.type
 | 
										type: file.type
 | 
				
			||||||
				});
 | 
									});
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,7 +23,7 @@
 | 
				
			||||||
		<mk-uploader ref="uploader"/>
 | 
							<mk-uploader ref="uploader"/>
 | 
				
			||||||
		<button ref="upload" onclick={ selectFile }><i class="fa fa-upload"></i></button>
 | 
							<button ref="upload" onclick={ selectFile }><i class="fa fa-upload"></i></button>
 | 
				
			||||||
		<button ref="drive" onclick={ selectFileFromDrive }><i class="fa fa-cloud"></i></button>
 | 
							<button ref="drive" onclick={ selectFileFromDrive }><i class="fa fa-cloud"></i></button>
 | 
				
			||||||
		<button class="cat" onclick={ cat }><i class="fa fa-smile-o"></i></button>
 | 
							<button class="kao" onclick={ kao }><i class="fa fa-smile-o"></i></button>
 | 
				
			||||||
		<button class="poll" onclick={ addPoll }><i class="fa fa-pie-chart"></i></button>
 | 
							<button class="poll" onclick={ addPoll }><i class="fa fa-pie-chart"></i></button>
 | 
				
			||||||
		<input ref="file" type="file" accept="image/*" multiple="multiple" onchange={ changeFile }/>
 | 
							<input ref="file" type="file" accept="image/*" multiple="multiple" onchange={ changeFile }/>
 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
| 
						 | 
					@ -165,7 +165,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				> [ref='upload']
 | 
									> [ref='upload']
 | 
				
			||||||
				> [ref='drive']
 | 
									> [ref='drive']
 | 
				
			||||||
				.cat
 | 
									.kao
 | 
				
			||||||
				.poll
 | 
									.poll
 | 
				
			||||||
					display inline-block
 | 
										display inline-block
 | 
				
			||||||
					padding 0
 | 
										padding 0
 | 
				
			||||||
| 
						 | 
					@ -182,7 +182,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	</style>
 | 
						</style>
 | 
				
			||||||
	<script>
 | 
						<script>
 | 
				
			||||||
		import getCat from '../../common/scripts/get-cat';
 | 
							import getKao from '../../common/scripts/get-kao';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		this.mixin('api');
 | 
							this.mixin('api');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -285,8 +285,8 @@
 | 
				
			||||||
			this.unmount();
 | 
								this.unmount();
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		this.cat = () => {
 | 
							this.kao = () => {
 | 
				
			||||||
			this.refs.text.value += getCat();
 | 
								this.refs.text.value += getKao();
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
	</script>
 | 
						</script>
 | 
				
			||||||
</mk-post-form>
 | 
					</mk-post-form>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,6 +4,7 @@
 | 
				
			||||||
		<div class="backdrop"></div>
 | 
							<div class="backdrop"></div>
 | 
				
			||||||
		<div class="content">
 | 
							<div class="content">
 | 
				
			||||||
			<button class="nav" onclick={ parent.toggleDrawer }><i class="fa fa-bars"></i></button>
 | 
								<button class="nav" onclick={ parent.toggleDrawer }><i class="fa fa-bars"></i></button>
 | 
				
			||||||
 | 
								<i class="fa fa-circle" if={ hasUnreadMessagingMessages }></i>
 | 
				
			||||||
			<h1 ref="title">Misskey</h1>
 | 
								<h1 ref="title">Misskey</h1>
 | 
				
			||||||
			<button if={ func } onclick={ func }><i class="fa fa-{ funcIcon }"></i></button>
 | 
								<button if={ func } onclick={ func }><i class="fa fa-{ funcIcon }"></i></button>
 | 
				
			||||||
		</div>
 | 
							</div>
 | 
				
			||||||
| 
						 | 
					@ -74,6 +75,14 @@
 | 
				
			||||||
						> i
 | 
											> i
 | 
				
			||||||
							transition all 0.2s ease
 | 
												transition all 0.2s ease
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										> i
 | 
				
			||||||
 | 
											position absolute
 | 
				
			||||||
 | 
											top 8px
 | 
				
			||||||
 | 
											left 8px
 | 
				
			||||||
 | 
											pointer-events none
 | 
				
			||||||
 | 
											font-size 10px
 | 
				
			||||||
 | 
											color $theme-color
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					> button:last-child
 | 
										> button:last-child
 | 
				
			||||||
						display block
 | 
											display block
 | 
				
			||||||
						position absolute
 | 
											position absolute
 | 
				
			||||||
| 
						 | 
					@ -90,14 +99,46 @@
 | 
				
			||||||
	<script>
 | 
						<script>
 | 
				
			||||||
		import ui from '../scripts/ui-event';
 | 
							import ui from '../scripts/ui-event';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this.mixin('api');
 | 
				
			||||||
 | 
							this.mixin('stream');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		this.func = null;
 | 
							this.func = null;
 | 
				
			||||||
		this.funcIcon = null;
 | 
							this.funcIcon = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this.on('mount', () => {
 | 
				
			||||||
 | 
								this.stream.on('read_all_messaging_messages', this.onReadAllMessagingMessages);
 | 
				
			||||||
 | 
								this.stream.on('unread_messaging_message', this.onUnreadMessagingMessage);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// Fetch count of unread messaging messages
 | 
				
			||||||
 | 
								this.api('messaging/unread').then(res => {
 | 
				
			||||||
 | 
									if (res.count > 0) {
 | 
				
			||||||
 | 
										this.update({
 | 
				
			||||||
 | 
											hasUnreadMessagingMessages: true
 | 
				
			||||||
 | 
										});
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		this.on('unmount', () => {
 | 
							this.on('unmount', () => {
 | 
				
			||||||
 | 
								this.stream.off('read_all_messaging_messages', this.onReadAllMessagingMessages);
 | 
				
			||||||
 | 
								this.stream.off('unread_messaging_message', this.onUnreadMessagingMessage);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			ui.off('title', this.setTitle);
 | 
								ui.off('title', this.setTitle);
 | 
				
			||||||
			ui.off('func', this.setFunc);
 | 
								ui.off('func', this.setFunc);
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this.onReadAllMessagingMessages = () => {
 | 
				
			||||||
 | 
								this.update({
 | 
				
			||||||
 | 
									hasUnreadMessagingMessages: false
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this.onUnreadMessagingMessage = () => {
 | 
				
			||||||
 | 
								this.update({
 | 
				
			||||||
 | 
									hasUnreadMessagingMessages: true
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		this.setTitle = title => {
 | 
							this.setTitle = title => {
 | 
				
			||||||
			this.refs.title.innerHTML = title;
 | 
								this.refs.title.innerHTML = title;
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,18 +7,18 @@
 | 
				
			||||||
		</a>
 | 
							</a>
 | 
				
			||||||
		<div class="links">
 | 
							<div class="links">
 | 
				
			||||||
			<ul>
 | 
								<ul>
 | 
				
			||||||
				<li class="home"><a href="/"><i class="icon fa fa-home"></i>%i18n:mobile.tags.mk-ui-nav.home%<i class="angle fa fa-angle-right"></i></a></li>
 | 
									<li><a href="/"><i class="fa fa-home"></i>%i18n:mobile.tags.mk-ui-nav.home%<i class="fa fa-angle-right"></i></a></li>
 | 
				
			||||||
				<li class="notifications"><a href="/i/notifications"><i class="icon fa fa-bell-o"></i>%i18n:mobile.tags.mk-ui-nav.notifications%<i class="angle fa fa-angle-right"></i></a></li>
 | 
									<li><a href="/i/notifications"><i class="fa fa-bell-o"></i>%i18n:mobile.tags.mk-ui-nav.notifications%<i class="fa fa-angle-right"></i></a></li>
 | 
				
			||||||
				<li class="messaging"><a href="/i/messaging"><i class="icon fa fa-comments-o"></i>%i18n:mobile.tags.mk-ui-nav.messaging%<i class="angle fa fa-angle-right"></i></a></li>
 | 
									<li><a href="/i/messaging"><i class="fa fa-comments-o"></i>%i18n:mobile.tags.mk-ui-nav.messaging%<i class="i fa fa-circle" if={ hasUnreadMessagingMessages }></i><i class="fa fa-angle-right"></i></a></li>
 | 
				
			||||||
			</ul>
 | 
								</ul>
 | 
				
			||||||
			<ul>
 | 
								<ul>
 | 
				
			||||||
				<li class="settings"><a onclick={ search }><i class="icon fa fa-search"></i>%i18n:mobile.tags.mk-ui-nav.search%<i class="angle fa fa-angle-right"></i></a></li>
 | 
									<li><a onclick={ search }><i class="fa fa-search"></i>%i18n:mobile.tags.mk-ui-nav.search%<i class="fa fa-angle-right"></i></a></li>
 | 
				
			||||||
			</ul>
 | 
								</ul>
 | 
				
			||||||
			<ul>
 | 
								<ul>
 | 
				
			||||||
				<li class="settings"><a href="/i/drive"><i class="icon fa fa-cloud"></i>%i18n:mobile.tags.mk-ui-nav.drive%<i class="angle fa fa-angle-right"></i></a></li>
 | 
									<li><a href="/i/drive"><i class="fa fa-cloud"></i>%i18n:mobile.tags.mk-ui-nav.drive%<i class="fa fa-angle-right"></i></a></li>
 | 
				
			||||||
			</ul>
 | 
								</ul>
 | 
				
			||||||
			<ul>
 | 
								<ul>
 | 
				
			||||||
				<li class="settings"><a href="/i/settings"><i class="icon fa fa-cog"></i>%i18n:mobile.tags.mk-ui-nav.settings%<i class="angle fa fa-angle-right"></i></a></li>
 | 
									<li><a href="/i/settings"><i class="fa fa-cog"></i>%i18n:mobile.tags.mk-ui-nav.settings%<i class="fa fa-angle-right"></i></a></li>
 | 
				
			||||||
			</ul>
 | 
								</ul>
 | 
				
			||||||
		</div>
 | 
							</div>
 | 
				
			||||||
		<a href={ CONFIG.aboutUrl }><p class="about">%i18n:mobile.tags.mk-ui-nav.about%</p></a>
 | 
							<a href={ CONFIG.aboutUrl }><p class="about">%i18n:mobile.tags.mk-ui-nav.about%</p></a>
 | 
				
			||||||
| 
						 | 
					@ -94,10 +94,16 @@
 | 
				
			||||||
						color #777
 | 
											color #777
 | 
				
			||||||
						text-decoration none
 | 
											text-decoration none
 | 
				
			||||||
 | 
					
 | 
				
			||||||
						> .icon
 | 
											> i:first-child
 | 
				
			||||||
							margin-right 0.5em
 | 
												margin-right 0.5em
 | 
				
			||||||
 | 
					
 | 
				
			||||||
						> .angle
 | 
											> .i
 | 
				
			||||||
 | 
												margin-left 6px
 | 
				
			||||||
 | 
												vertical-align super
 | 
				
			||||||
 | 
												font-size 10px
 | 
				
			||||||
 | 
												color $theme-color
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											> i:last-child
 | 
				
			||||||
							position absolute
 | 
												position absolute
 | 
				
			||||||
							top 0
 | 
												top 0
 | 
				
			||||||
							right 0
 | 
												right 0
 | 
				
			||||||
| 
						 | 
					@ -120,6 +126,39 @@
 | 
				
			||||||
	<script>
 | 
						<script>
 | 
				
			||||||
		this.mixin('i');
 | 
							this.mixin('i');
 | 
				
			||||||
		this.mixin('page');
 | 
							this.mixin('page');
 | 
				
			||||||
 | 
							this.mixin('api');
 | 
				
			||||||
 | 
							this.mixin('stream');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this.on('mount', () => {
 | 
				
			||||||
 | 
								this.stream.on('read_all_messaging_messages', this.onReadAllMessagingMessages);
 | 
				
			||||||
 | 
								this.stream.on('unread_messaging_message', this.onUnreadMessagingMessage);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// Fetch count of unread messaging messages
 | 
				
			||||||
 | 
								this.api('messaging/unread').then(res => {
 | 
				
			||||||
 | 
									if (res.count > 0) {
 | 
				
			||||||
 | 
										this.update({
 | 
				
			||||||
 | 
											hasUnreadMessagingMessages: true
 | 
				
			||||||
 | 
										});
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this.on('unmount', () => {
 | 
				
			||||||
 | 
								this.stream.off('read_all_messaging_messages', this.onReadAllMessagingMessages);
 | 
				
			||||||
 | 
								this.stream.off('unread_messaging_message', this.onUnreadMessagingMessage);
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this.onReadAllMessagingMessages = () => {
 | 
				
			||||||
 | 
								this.update({
 | 
				
			||||||
 | 
									hasUnreadMessagingMessages: false
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							this.onUnreadMessagingMessage = () => {
 | 
				
			||||||
 | 
								this.update({
 | 
				
			||||||
 | 
									hasUnreadMessagingMessages: true
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		this.search = () => {
 | 
							this.search = () => {
 | 
				
			||||||
			const query = window.prompt('%i18n:mobile.tags.mk-ui-nav.search%');
 | 
								const query = window.prompt('%i18n:mobile.tags.mk-ui-nav.search%');
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,7 +5,7 @@
 | 
				
			||||||
			<div class="body">
 | 
								<div class="body">
 | 
				
			||||||
				<div class="top">
 | 
									<div class="top">
 | 
				
			||||||
					<a class="avatar">
 | 
										<a class="avatar">
 | 
				
			||||||
						<img src={ user.avatar_url + '?thumbnail&size=160' } alt="avatar"/>
 | 
											<img src={ user.avatar_url + '?thumbnail&size=200' } alt="avatar"/>
 | 
				
			||||||
					</a>
 | 
										</a>
 | 
				
			||||||
					<mk-follow-button if={ SIGNIN && I.id != user.id } user={ user }/>
 | 
										<mk-follow-button if={ SIGNIN && I.id != user.id } user={ user }/>
 | 
				
			||||||
				</div>
 | 
									</div>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue