Compare commits

..

77 Commits

Author SHA1 Message Date
syuilo ff52ea2a7c 11.30.0 2019-08-24 02:28:43 +09:00
syuilo f247ee9dd3 New Crowdin translations (#5322)
* New translations ja-JP.yml (English)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Czech)

* New translations ja-JP.yml (Czech)

* New translations ja-JP.yml (Danish)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Czech)

* New translations ja-JP.yml (Dutch)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Polish)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Czech)

* New translations ja-JP.yml (Danish)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Polish)

* New translations ja-JP.yml (Spanish)

* New translations ja-JP.yml (Japanese, Kansai)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Czech)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Korean)
2019-08-24 02:24:24 +09:00
syuilo f4cec53ba1 [Room] Make Pinguin customizable 2019-08-24 02:18:21 +09:00
syuilo ad70b50fee [Room] Add energy drink 2019-08-23 06:52:42 +09:00
Acid Chicken (硫酸鶏) ea7b2b3141 Update README.md [AUTOGEN] (#5335) 2019-08-23 05:06:22 +09:00
syuilo c2f932e28b Fix #5324 2019-08-22 19:56:27 +09:00
syuilo c637882578 カップ麺をスムーズシェードするように 2019-08-22 19:42:52 +09:00
syuilo ef7221e39e Fix holo-display animation glitch 2019-08-22 19:37:01 +09:00
Oni-Men 6b571a7799 Improve furniture preview (#5328)
* Improve furniture preview

* improve calc method

* camera.aspectいらないことに気付いた

* refactor & go camera far away

* 対角線の長さで計算するように

* 対角線の計算にhypot()を使用

Co-Authored-By: Aya Morisawa <AyaMorisawa4869@gmail.com>
2019-08-22 18:34:15 +09:00
MeiMei 0638b6cb69 Roomで未保存警告ダイアログなどを追加 (#5332)
* Room保存時にダイアログを表示するように

* Roomから移動するときに未保存ならば警告するように
2019-08-22 18:33:50 +09:00
syuilo a39c1706a1 Merge branch 'develop' of https://github.com/syuilo/misskey into develop 2019-08-22 02:40:19 +09:00
syuilo c741e27057 [Room] Add holo-display 2019-08-22 02:40:01 +09:00
Aya Morisawa ede854c215 Update button.vue (#5331) 2019-08-22 02:36:19 +09:00
Satsuki Yanagi 6a953b4d94 Update yarn.lock (#5327) 2019-08-21 13:04:51 +09:00
Aya Morisawa 1d763096c7 Update room section of CONTRIBUTING.md 2019-08-20 16:16:27 +09:00
Oni-Men 630d873ec0 [room]Add cup noodle (#5323)
* [Room] Add cup noodles

* remove ,

* Fix Cup-Noodle Texture
2019-08-20 15:57:42 +09:00
syuilo d427957ea7 New Crowdin translations (#5321)
* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Korean)
2019-08-20 02:19:06 +09:00
syuilo 2430cc0e2c New translations ja-JP.yml (English) (#5320) 2019-08-20 02:04:55 +09:00
syuilo e57ee24864 New translations ja-JP.yml (French) (#5319) 2019-08-20 01:55:35 +09:00
syuilo 3bc05ab3f2 New Crowdin translations (#5318)
* New translations ja-JP.yml (French)

* New translations ja-JP.yml (French)
2019-08-20 01:44:22 +09:00
syuilo 4e50dcfa93 New Crowdin translations (#5313)
* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Chinese Simplified)
2019-08-19 21:24:43 +09:00
syuilo fcf5531e5b 🎨 2019-08-19 16:44:55 +09:00
syuilo 3bef69ee58 🎨 2019-08-19 16:13:08 +09:00
syuilo 311a4f28b0 Resolve #5298 2019-08-19 16:05:57 +09:00
syuilo 01e692b353 Refactor 2019-08-19 15:59:36 +09:00
syuilo 3b445af6fc Improve readability 2019-08-19 15:51:00 +09:00
syuilo 1e43ece637 [Room] Update model 2019-08-19 14:01:05 +09:00
syuilo 6f1048c006 11.29.0 2019-08-19 12:39:26 +09:00
syuilo d686e70f2b [Room] Better rendering 2019-08-19 12:35:18 +09:00
syuilo 70f524b82d New Crowdin translations (#5312)
* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Chinese Traditional)

* New translations ja-JP.yml (Czech)

* New translations ja-JP.yml (Danish)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Norwegian)

* New translations ja-JP.yml (Polish)

* New translations ja-JP.yml (Portuguese)

* New translations ja-JP.yml (Russian)

* New translations ja-JP.yml (Spanish)

* New translations ja-JP.yml (Japanese, Kansai)
2019-08-19 12:17:37 +09:00
syuilo 79c6475028 Improve readability 2019-08-19 02:19:37 +09:00
syuilo 7dee5309dc Refactoring 2019-08-19 02:06:37 +09:00
syuilo 958ec7b03f Fix #5307 2019-08-19 02:02:10 +09:00
syuilo 9153434906 [Room] Add bin 2019-08-19 01:54:06 +09:00
syuilo 3a08364c24 [Room] Add some furnitures 2019-08-19 01:45:20 +09:00
syuilo a9beeab502 [Room] Better rendering 2019-08-19 01:43:45 +09:00
syuilo 38c901069a [Room] Better avatar rendering 2019-08-19 01:15:30 +09:00
syuilo 3f7606060e Update geometry name 2019-08-19 01:01:15 +09:00
kabo2468 777f20e9be Add Trash can (#5309)
new file:   src/client/assets/room/furnitures/trash-can/trash-can.blend
	new file:   src/client/assets/room/furnitures/trash-can/trash-can.glb
2019-08-19 00:51:57 +09:00
Aya Morisawa 8e39aecffe Update room section of CONTRIBUTING.md (#5306)
* Update room section of CONTRIBUTING.md

* Update CONTRIBUTING.md

* Update CONTRIBUTING.md
2019-08-18 23:40:52 +09:00
syuilo 9e1ab54097 11.28.2 2019-08-18 20:32:23 +09:00
syuilo 0f9e09f4bd cors 2019-08-18 20:32:04 +09:00
MeiMei 743ebc17b9 Fix #5291 (#5294) 2019-08-18 20:25:12 +09:00
syuilo 9bc4af76b8 モバイルでもRoomを表示できるように 2019-08-18 19:11:24 +09:00
syuilo 46fa26426d Fix bug 2019-08-18 19:08:33 +09:00
syuilo 58d0dc1795 11.28.1 2019-08-18 16:56:42 +09:00
syuilo bc11702f7d Fix #5290 2019-08-18 16:55:09 +09:00
syuilo 6288de5813 Fix #5291 2019-08-18 16:51:27 +09:00
syuilo bbf59c7d9f 11.28.0 2019-08-18 16:07:55 +09:00
imgbot[bot] d7787bacf7 [ImgBot] Optimize images (#5289)
*Total -- 2,381.44kb -> 1,992.59kb (16.33%)

/src/client/assets/room/furnitures/photoframe/photo-uv.png -- 20.34kb -> 2.58kb (87.33%)
/src/client/assets/room/furnitures/pc/motherboard-uv.png -- 21.43kb -> 2.85kb (86.69%)
/src/client/assets/room/furnitures/cardboard-box3/uv.png -- 21.58kb -> 3.51kb (83.72%)
/src/client/assets/room/furnitures/poster-v/uv.png -- 21.85kb -> 3.71kb (83.04%)
/src/client/assets/room/furnitures/milk/milk.png -- 3.76kb -> 0.64kb (82.89%)
/src/client/assets/room/furnitures/server/uv.png -- 22.29kb -> 3.92kb (82.42%)
/src/client/assets/room/furnitures/facial-tissue/facial-tissue.png -- 3.80kb -> 0.67kb (82.3%)
/src/client/assets/room/rooms/washitsu/tatami-uv.png -- 22.27kb -> 3.98kb (82.13%)
/src/client/assets/room/rooms/washitsu/husuma-uv.png -- 22.06kb -> 3.94kb (82.13%)
/src/client/assets/room/furnitures/tv/screen-uv.png -- 20.55kb -> 3.70kb (81.98%)
/src/client/assets/room/furnitures/poster-h/uv.png -- 20.15kb -> 3.70kb (81.65%)
/src/client/assets/room/furnitures/plant/plant-soil-uv.png -- 23.17kb -> 4.40kb (81%)
/src/client/assets/room/furnitures/facial-tissue/facial-tissue-uv.png -- 22.96kb -> 4.37kb (80.99%)
/src/client/assets/room/furnitures/cardboard-box2/uv.png -- 22.36kb -> 4.52kb (79.78%)
/src/client/assets/room/furnitures/book2/uv.png -- 37.36kb -> 8.41kb (77.49%)
/src/client/assets/room/furnitures/server/rack-uv.png -- 26.68kb -> 6.55kb (75.46%)
/src/client/assets/room/furnitures/monitor/screen-uv.png -- 5.81kb -> 1.46kb (74.88%)
/src/client/assets/room/furnitures/milk/milk-uv.png -- 49.21kb -> 16.19kb (67.1%)
/src/client/assets/room/furnitures/eraser/eraser-uv.png -- 27.93kb -> 10.90kb (60.96%)
/src/client/assets/room/furnitures/book2/barcode.png -- 8.71kb -> 3.42kb (60.72%)
/src/client/assets/room/rooms/washitsu/husuma.png -- 4.23kb -> 2.48kb (41.44%)
/src/client/assets/room/furnitures/server/rack.png -- 9.42kb -> 6.88kb (26.92%)
/src/client/assets/room/furnitures/eraser/cover.png -- 10.75kb -> 8.14kb (24.26%)
/src/client/assets/room/furnitures/plant2/soil.png -- 13.06kb -> 10.60kb (18.83%)
/src/client/assets/room/furnitures/plant/plant-soil.png -- 13.06kb -> 10.60kb (18.83%)
/src/client/assets/room/furnitures/monitor/screen.jpg -- 28.93kb -> 24.26kb (16.16%)
/src/client/assets/room/furnitures/cardboard-box3/texture.png -- 18.23kb -> 15.82kb (13.21%)
/src/client/assets/room/furnitures/cardboard-box2/texture.png -- 18.64kb -> 16.48kb (11.56%)
/src/client/assets/room/furnitures/book2/texture.png -- 64.05kb -> 59.59kb (6.97%)
/src/client/assets/room/furnitures/server/server.png -- 121.75kb -> 114.13kb (6.26%)
/src/client/assets/room/furnitures/pc/motherboard.jpg -- 67.25kb -> 63.09kb (6.19%)
/src/client/assets/room/furnitures/photoframe/photo.jpg -- 31.10kb -> 29.79kb (4.22%)
/src/client/assets/room/rooms/washitsu/tatami-single1600.png -- 1,163.42kb -> 1,145.84kb (1.51%)
/src/client/assets/room/rooms/washitsu/tatami.png -- 308.19kb -> 306.37kb (0.59%)
/src/client/assets/room/furnitures/moon/moon.jpg -- 85.11kb -> 85.11kb (0%)

Signed-off-by: ImgBotApp <ImgBotHelp@gmail.com>
2019-08-18 15:06:22 +09:00
syuilo 23ae0515c4 Update CHANGELOG.md 2019-08-18 15:05:13 +09:00
syuilo fe88b34b8a Update node version 2019-08-18 14:56:54 +09:00
syuilo 74aa031a22 Update dependencies 🚀 2019-08-18 14:56:47 +09:00
syuilo 6aeed212d9 New Crowdin translations (#5249)
* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Polish)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Czech)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Danish)

* New translations ja-JP.yml (German)

* New translations ja-JP.yml (Spanish)

* New translations ja-JP.yml (Japanese, Kansai)

* New translations ja-JP.yml (Czech)

* New translations ja-JP.yml (Polish)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Polish)

* New translations ja-JP.yml (Polish)

* New translations ja-JP.yml (Czech)

* New translations ja-JP.yml (English)

* New translations ja-JP.yml (Polish)

* New translations ja-JP.yml (French)

* New translations ja-JP.yml (Korean)

* New translations ja-JP.yml (Czech)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Danish)

* New translations ja-JP.yml (Dutch)
2019-08-18 14:43:30 +09:00
syuilo 45b972c059 MisskeyRoom (#5267)
* wip

* Add pemcil

* Fix bug

* Update .gitattributes

* Add 🍮

* Better 🍮

* Add color boxes

* Add pc

* Add keyboard

* Add 📦

* Add more 📦

* ✌️

* carpet

* Add plant

* ✌️

* ✌️

* Update room.vue

* Add plant

* ✌️

* ✌️

* ✌️

* ✌️

* ✌️

* 段ボール箱がてかりすぎているのを修正

* Update room.ts

* Render username

* ✌️

* Add new 📦

* Update room.ts

* Remove blender backup files

* Refactor

* Improve performance

* Update room.ts

* Update .gitattributes

* Update room.ts

* Better fan

* Better tissue rendering

* Add 🐧

* Create photoframe2.glb

* chairs

* Add 📖

* fix: HiDPi環境でオブジェクトを選択できない (#5268)

* Better monitor

* ✌️

* Add corkboard

* Add missing blend

* mousepad

* Add missing blend

* Add cube

* 額縁やモニターなどに任意の画像を表示できるように

* Update MisskeyRoom section of CONTRIBUTING.md (#5272)

* Update MisskeyRoom section of CONTRIBUTING.md

* Update CONTRIBUTING.md

* Update CONTRIBUTING.md

* Refactor

* カスタムテクスチャがずれないように

* Remove debug code

* Update furnitures.json5

* 一部の家具の色を自由に変えられるように

* Update ja-JP.yml

* Type annotation

* 家具の色やテクスチャをすぐ反映するように

* Update room.vue

* Update furnitures.json5

* Add 📺

* Update ja-JP.yml

* 床の色を変えられるように

* 和室にできるように

* Update washitsu

* Use MeshLambertMaterial to improve performance

* Use MeshLambertMaterial

* Fix bug

* Refactor

* Update room.ts

* Fix washitsu

* Update room.vue

* Update washistu

* Use MeshLambertMaterial

* Update room.ts

* Set current property value

* Disable reactivity to improve performance a bit

* Fix bug

* Set current carpet color

* Update ja-JP.yml

* Add rubik-cube (#5278)

* Update ja-JP.yml (#5279)

* Update UI

* ルームの設定を追加

* Add room link

* 家具をドラッグで移動や回転できるように

* esnextにする (#5286)

* Fix moduleResolution

* Use uuid v4

* Fix bug

* マットの色を変えられるように

* ✌️

* 異方性フィルタリングするように

* グラフィックの品質をフィルタリングに反映

* Add bloom effect when ultra graphics

* Add posters

* 🎨
2019-08-18 14:41:33 +09:00
MeiMei 7ecfc007a9 updateHashtagを並列で行わないように (#5284) 2019-08-18 12:47:45 +09:00
MeiMei fc78c75bab Fix: Hashtagがupdateできない (#5285) 2019-08-18 12:46:47 +09:00
Satsuki Yanagi 59493a0cd9 uuid() と lint (#5288)
* Import only v4 uuid, uuid() without version is deprecated

* Add Missing semicolon
2019-08-18 12:42:58 +09:00
MeiMei 6060c6d56e リモートユーザー向けのNoteUnreadsレコードは作成しないように (#5280) 2019-08-17 14:40:06 +09:00
MeiMei 6cdbb27169 Fix: ドライブアップロード直後に取得できるURLがoriginalじゃない (#5274) 2019-08-17 12:32:52 +09:00
MeiMei ed8b073e54 タイトルやアイコンがきちんと設定されないことがあるのを修正 (#5265)
* Fix: og:site_nameがbase系ページに正しく反映さんれない

* instanceNameはAPIのmetaじゃなくてog:site_nameを参照するように

* Fix: タイトルが変更されるページから通常ページに遷移してもタイトルが戻らない

* Fix: タイトルが戻らない mobile / notifications

* Fix: faviconの変更が効かないページがある
2019-08-16 14:16:19 +09:00
syuilo 7dd193636c Fix #5260 2019-08-11 20:13:57 +09:00
MeiMei 01d018510c ユーザー名の突き抜けの修正 (#5261)
* 突き抜け deck フォロリク/vote

* 突き抜け desktop

* notification reactionで絵文字の縦がずれないように

* Fix: ユーザーページの名前が突き抜ける

* Fix: デッキカラムでユーザー名が長いと閉じれなくなる

* デッキのカウントの位置が右になってしまってたのを修正

* デッキヘッダーのellipsis
2019-08-11 19:48:54 +09:00
和風ドレッシング 1c273a0a75 Elasticsearchのインデックス名をconfigで変更できるように (#5257) 2019-08-09 13:04:35 +09:00
Satsuki Yanagi fa2c7658a0 PackedUserがサイレンスや凍結の情報を持つように (#5255) 2019-08-08 09:31:40 +09:00
Satsuki Yanagi 84ca3a7d45 Unified the notation with "Renote" for consistency (#5256)
https://crowdin.com/translate/misskey/3/ja-zhcn#5238
2019-08-08 06:45:39 +09:00
Acid Chicken (硫酸鶏) 902c73e6ac Update README.md [AUTOGEN] (#5251) 2019-08-06 23:23:01 +09:00
MeiMei 3b626f72e4 Resolve #5247 (#5248) 2019-08-05 10:30:31 +09:00
Acid Chicken (硫酸鶏) f5ce137a6b Update README.md [AUTOGEN] (#5246) 2019-08-03 19:56:59 +09:00
Acid Chicken (硫酸鶏) 3ce9d12361 Update README.md [AUTOGEN] (#5243) 2019-08-02 22:37:31 +09:00
Acid Chicken (硫酸鶏) 2fe2f3b1eb Update README.md [AUTOGEN] (#5240) 2019-08-02 21:21:31 +09:00
Acid Chicken (硫酸鶏) 17b3ee41db Update README.md [AUTOGEN] (#5239) 2019-08-01 22:26:11 +09:00
Takeshi Umeda 56d2a5d5d3 Modify ssl directive to 'ssl' for listen directive (#5237)
the "ssl" directive is deprecated. 
http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl
2019-08-01 19:12:32 +09:00
syuilo 3a17ff0983 11.27.1 2019-08-01 15:47:02 +09:00
syuilo 9a9270bbe9 New Crowdin translations (#5230)
* New translations ja-JP.yml (Czech)

* New translations ja-JP.yml (Czech)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Chinese Simplified)

* New translations ja-JP.yml (Chinese Simplified)
2019-08-01 15:44:53 +09:00
Acid Chicken (硫酸鶏) 512eee4f51 Update README.md [AUTOGEN] (#5236) 2019-08-01 01:32:00 +09:00
MeiMei db01fa0eef Enable s3ForcePathStyle (#5234) 2019-07-31 18:11:11 +09:00
236 changed files with 2821 additions and 346 deletions
+4
View File
@@ -1,3 +1,7 @@
*.svg -diff -text
*.psd -diff -text
*.ai -diff -text
*.mqo -diff -text
*.glb -diff -text
*.blend -diff -text
*.afdesign -diff -text
+7
View File
@@ -30,3 +30,10 @@ api-docs.json
.DS_Store
/files
ormconfig.json
# blender backups
*.blend1
*.blend2
*.blend3
*.blend4
*.blend5
+1 -1
View File
@@ -1 +1 @@
v12.6.0
v12.8.1
+61
View File
@@ -1,6 +1,67 @@
ChangeLog
=========
11.30.0 (2019/08/24)
--------------------
### ✨Improvements
* Room: 家具をすべてしまうボタンを追加
* Room: カップ麺追加
* Room: ホログラフィックディスプレイ追加
* Room: エナジードリンク追加
* Room: ピンギンの色を変えられるように
* Room: プレビューの見やすさを向上
* Room保存時にダイアログを表示するように
* Roomから移動するときに未保存ならば警告するように
### 🐛Fixes
* MisskeyRoomからページを戻した時、テキスト入力画面で選択位置変更ができない問題を修正
11.29.0 (2019/08/19)
--------------------
### ✨Improvements
* Room: ソファ追加
* Room: 螺旋階段追加
* Room: ゴミ箱追加
### 🐛Fixes
* Room: 部屋を離れても裏でレンダリングが続く問題を修正
* Room: アバターのレンダリングを修正
* Room: ライティングの調整
11.28.2 (2019/08/18)
--------------------
### 🐛Fixes
* 他人の部屋なのに部屋編集UIが表示されるのを修正
* オブジェクトストレージを使用している場合Roomで画像を読み込めない問題を修正
11.28.1 (2019/08/18)
--------------------
### 🐛Fixes
* オブジェクトストレージを使用している場合Roomで画像を読み込めない問題を修正
* Roomで家具を移動など確定せずに「しまう」と部屋ごと消える問題を修正
11.28.0 (2019/08/18)
--------------------
### ✨Improvements
* 自分の部屋を作れるように
* Delキーを押して投稿を削除するときに確認ダイアログを出すように
* Elasticsearchのインデックス名をconfigで変更できるように
### 🐛Fixes
* コンテンツを遡ってる途中に新しいアイテムが先頭に追加されると上限に達している場合末尾のアイテムが削除される問題を修正
* ユーザー名が突き抜けるのを修正
* ユーザー一覧とかでサイレンス・凍結されたユーザーの状態が表示されてなかったのを修正
* タイトルやアイコンがきちんと設定されないことがあるのを修正
* ドライブアップロード直後に取得できるURLがoriginalじゃない問題を修正
* リモートユーザー向けのNoteUnreadsレコードが作成される問題を修正
* Hashtagがupdateできない問題を修正
* ハッシュタグの更新がタグの数だけ並列で行われてDBを重くしてしまうことがあるのを修正
11.27.1 (2019/08/01)
--------------------
### 🐛Fixes
* オブジェクトストレージに関する問題を修正
11.27.0 (2019/07/29)
--------------------
### ✨Improvements
+11
View File
@@ -38,6 +38,17 @@ Documentation of Vue I18n is available at http://kazupon.github.io/vue-i18n/intr
Misskey uses CircleCI for executing automated tests.
Configuration files are located in [`/.circleci`](/.circleci).
## Adding MisskeyRoom items
* Use English for material, object and texture names.
* Use meter for unit of length.
* Your PR should include all source files (e.g. `.png`, `.blend`) of your models (for later editing).
* Your PR must include the glTF binary files (`.glb`) of your models.
* Add a locale key `room.furnitures.YOUR_ITEM` at [`/locales/ja-JP.yml`](/locales/ja-JP.yml).
* Add a furniture definition at [`/src/client/app/common/scripts/room/furnitures.json5`](/src/client/app/common/scripts/room/furnitures.json5).
If you have no experience on 3D modeling, we suggest to use the free 3DCG software [Blender](https://www.blender.org/).
You can find information on glTF 2.0 at [glTF 2.0 — Blender Manual]( https://docs.blender.org/manual/en/dev/addons/io_scene_gltf2.html).
## FAQ
### How to resolve conflictions occurred at yarn.lock?
+1 -1
View File
@@ -1,4 +1,4 @@
FROM node:12.6-alpine AS base
FROM node:12.8-alpine AS base
ENV NODE_ENV=production
+2 -10
View File
@@ -109,7 +109,6 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/19045173/cb91c0f345c24d4ebfd05f19906d5e26/1.png?token-time=2145916800&token-hash=o_zKBytJs_AxHwSYw_5R8eD0eSJe3RoTR3kR3Q0syN0%3D" alt="kiritan" width="100"></td>
<td><img src="https://c8.patreon.com/2/200/776209" alt="Denshi" width="100"></td>
<td><img src="https://c8.patreon.com/2/200/557245" alt="mkatze" width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/13099460/43cecdbaa63a40d79bf50a96b9910b9d/1.jpe?token-time=2145916800&token-hash=bqwLTk0Wo0hUJJ8J5y7ii05bLzz-_CDA7Bo0Mp4RFU0%3D" alt="ne_moni" width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/12913507/f7181eacafe8469a93033d85f5969c29/4.jpe?token-time=2145916800&token-hash=zEyJqVM7u9d8Ri-65fJYSJcWF1jBH1nJ5a3taRzrTmw%3D" alt="Melilot" width="100"></td>
</tr><tr>
<td><a href="https://www.patreon.com/rane_hs">Hiroshi Seki</a></td>
@@ -118,7 +117,6 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
<td><a href="https://www.patreon.com/user?u=19045173">kiritan</a></td>
<td><a href="https://www.patreon.com/user?u=776209">Denshi</a></td>
<td><a href="https://www.patreon.com/user?u=557245">mkatze</a></td>
<td><a href="https://www.patreon.com/user?u=13099460">ne_moni</a></td>
<td><a href="https://www.patreon.com/user?u=12913507">Melilot</a></td>
</tr></table>
<table><tr>
@@ -126,32 +124,27 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
<td><img src="https://c8.patreon.com/2/200/16869916" alt="見当かなみ" width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/18899730/6a22797f68254034a854d69ea2445fc8/1.png?token-time=2145916800&token-hash=b_uj57yxo5VzkSOUS7oXE_762dyOTB_oxzbO6lFNG3k%3D" alt="YuzuRyo61" width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/11357794/923ce94cd8c44ba788ee931907881839/1.png?token-time=2145916800&token-hash=9nEQje_eMvUjq9a7L3uBqW-MQbS-rRMaMgd7UYVoFNM%3D" alt="mydarkstar" width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/13039004/509d0c412eb14ae08d6a812a3054f7d6/1.jpe?token-time=2145916800&token-hash=UQRWf01TwHDV4Cls1K0YAOAjM29ssif7hLVq0ESQ0hs%3D" alt="nemu" width="100"></td>
<td><img src="https://c8.patreon.com/2/200/17866454" alt="sikyosyounin" width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/5881381/6235ca5d3fb04c8e95ef5b4ff2abcc18/3.png?token-time=2145916800&token-hash=KjfQL8nf3AIf6WqzLshBYAyX44piAqOAZiYXgZS_H6A%3D" alt="YUKIMOCHI" width="100"></td>
<td><img src="https://c8.patreon.com/2/200/17463605" alt="Sampot" width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/19356899/496b4681d33b4520bd7688e0fd19c04d/2.jpeg?token-time=2145916800&token-hash=_sTj3dUBOhn9qwiJ7F19Qd-yWWfUqJC_0jG1h0agEqQ%3D" alt="sheeta.s" width="100"></td>
</tr><tr>
<td><a href="https://www.patreon.com/osapon">osapon</a></td>
<td><a href="https://www.patreon.com/user?u=16869916">見当かなみ</a></td>
<td><a href="https://www.patreon.com/Yuzulia">YuzuRyo61</a></td>
<td><a href="https://www.patreon.com/mydarkstar">mydarkstar</a></td>
<td><a href="https://www.patreon.com/user?u=13039004">nemu</a></td>
<td><a href="https://www.patreon.com/user?u=17866454">sikyosyounin</a></td>
<td><a href="https://www.patreon.com/yukimochi">YUKIMOCHI</a></td>
<td><a href="https://www.patreon.com/user?u=17463605">Sampot</a></td>
<td><a href="https://www.patreon.com/user?u=19356899">sheeta.s</a></td>
</tr></table>
<table><tr>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/13737140/1adf7835017d479280d90fe8d30aade2/1.png?token-time=2145916800&token-hash=0pdle8h5pDZrww0BDOjdz6zO-HudeGTh36a3qi1biVU%3D" alt="Satsuki Yanagi" width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/17880724/311738c8a48f4a6b9443c2445a75adde/1.jpe?token-time=2145916800&token-hash=CPxGQhKIlEaa6WUcgbyHixyKEhakiw9RFdOhsIJBQ_o%3D" alt="takimura" width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/16900731/83884b38afc74d4cbe83c30a13b10edd/1.png?token-time=2145916800&token-hash=R5Tog8RWg0rguRoCIoir3lThokrdPvs8Utfikhc0nhY%3D" alt="Atsuko Tominaga" width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/16900731/619ab87cc08448439222631ebb26802f/1.gif?token-time=2145916800&token-hash=o27K7M02s1z-LkDUEO5Oa7cu-GviRXeOXxryi4o_6VU%3D" alt="Atsuko Tominaga" width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/4389829/9f709180ac714651a70f74a82f3ffdb9/3.png?token-time=2145916800&token-hash=FTm3WVom4dJ9NwWMU4OpCL_8Yc13WiwEbKrDPyTZTPs%3D" alt="natalie" width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/13034746/c711c7f58e204ecfbc2fd646bc8a4eee/1.jpe?token-time=2145916800&token-hash=EWxXhVbZYH7KB4IDT3joc8TbIg8zPO40x1r5IDn3R7c%3D" alt="Hiratake" width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/5923936/2a743cbfbff946c2af3f09026047c0da/2.png?token-time=2145916800&token-hash=h6yphW1qnM0n_NOWaf8qtszMRLXEwIxfk5beu4RxdT0%3D" alt="noellabo" width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/2384390/5681180e1efb46a8b28e0e8d4c8b9037/1.jpg?token-time=2145916800&token-hash=SJcMy-Q1BcS940-LFUVOMfR7-5SgrzsEQGhYb3yowFk%3D" alt="CG" width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/18072312/98e894d960314fa7bc236a72a39488fe/1.jpe?token-time=2145916800&token-hash=qA8j97lIZNc-74AuZ0p4F3ms6sKPeKjtNt2vEuwpsyo%3D" alt="Hekovic" width="100"></td>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/10789744/97175095d8f04c0f86225ff47cb98d40/1.jpeg?token-time=2145916800&token-hash=l4AoMR7Nj7K4yAHrkrk2hAoggPkbSPm12m1nmbe9Pb8%3D" alt="Naoki Hirayama" width="100"></td>
</tr><tr>
<td><a href="https://www.patreon.com/user?u=13737140">Satsuki Yanagi</a></td>
<td><a href="https://www.patreon.com/takimura">takimura</a></td>
@@ -161,7 +154,6 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
<td><a href="https://www.patreon.com/noellabo">noellabo</a></td>
<td><a href="https://www.patreon.com/Corset">CG</a></td>
<td><a href="https://www.patreon.com/hekovic">Hekovic</a></td>
<td><a href="https://www.patreon.com/spinlock">Naoki Hirayama</a></td>
</tr></table>
<table><tr>
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/4503830/ccf2cc867ea64de0b524bb2e24b9a1cb/1.jpeg?token-time=2145916800&token-hash=L55UhJ0rcuNAH3w_ryeeGN4hC6taoOixyAhraEi0bzw%3D" alt="dansup" width="100"></td>
@@ -175,7 +167,7 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
<td><a href="https://www.patreon.com/user?u=12531784">Takashi Shibuya</a></td>
</tr></table>
**Last updated:** Fri, 19 Jul 2019 15:41:09 UTC
**Last updated:** Thu, 22 Aug 2019 17:38:06 UTC
<!-- PATREON_END -->
:four_leaf_clover: Copyright
+2 -3
View File
@@ -25,10 +25,9 @@ server {
}
server {
listen 443 http2;
listen [::]:443 http2;
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.tld;
ssl on;
ssl_session_cache shared:ssl_session_cache:10m;
# To use Let's Encrypt certificate
+5 -1
View File
@@ -47,7 +47,11 @@ gulp.task('build:copy:views', () =>
gulp.src('./src/server/web/views/**/*').pipe(gulp.dest('./built/server/web/views'))
);
gulp.task('build:copy', gulp.parallel('build:copy:views', () =>
gulp.task('build:copy:fonts', () =>
gulp.src('./node_modules/three/examples/fonts/**/*').pipe(gulp.dest('./built/client/assets/fonts/'))
);
gulp.task('build:copy', gulp.parallel('build:copy:views', 'build:copy:fonts', () =>
gulp.src([
'./src/const.json',
'./src/server/web/views/**/*',
+30 -1
View File
@@ -34,10 +34,18 @@ common:
signup: "Registrovat"
signout: "Odhlásit"
reload-to-apply-the-setting: "Pro uplatnění tohoto nastavení musíte znovu načíst tuto stránku. Chcete ji načíst teď?"
delete-confirm: "Opravdu chcete smazat tento příspěvek?"
signin-required: "Přihlašte se, prosím"
notification-type: "Typy oznámení"
notification-types:
all: "Všechny"
reply: "Odpovědět"
pollVote: "Hlasy"
follow: "Sledovaní"
receiveFollowRequest: "Žádost o sledování"
reply: "Odpovědi"
quote: "Citace"
renote: "Renotovat"
mention: "Zmínky"
reaction: "Reakce"
got-it: "Rozumím!"
customization-tips:
@@ -104,6 +112,7 @@ common:
hide-contents: "Schovat obsah"
reply-placeholder: "Odpovědět na tento příspěvek"
quote-placeholder: "Citovat tento příspěvek"
quote-attached: "Přiložit citaci"
submit: "Odeslat"
reply: "Odpovědět"
renote: "Renotovat"
@@ -113,12 +122,14 @@ common:
create-poll: "Vytvořit anketu"
text-remain: "zbývá ještě {} znaků"
recent-tags: "Nejnovější"
click-to-tagging: "Klikni pro otágování"
visibility: "Viditelnost"
geolocation-alert: "Vaše zařízení nedalo k dispozici lokaci"
error: "Chyba"
enter-username: "Zadejte své uživatelské jméno"
add-visible-user: "Přidat uživatele"
username-prompt: "Zadejte své uživatelské jméno"
enter-file-name: "Upravit název souboru"
weekday-short:
sunday: "Ne"
monday: "Po"
@@ -271,6 +282,15 @@ common:
sync: "Synchronizace"
save: "Uložit"
saved: "Uloženo"
room: "Místnost"
_room:
graphicsQuality: "Kvalita grafiky"
_graphicsQuality:
ultra: "Nejvyšší"
high: "Vysoká"
medium: "Střední"
low: "Nízká"
cheep: "Nejnižší"
search: "Hledání"
delete: "Odstranit"
loading: "Načítám..."
@@ -495,6 +515,7 @@ common/views/components/note-menu.vue:
unpin: "Odepnout"
delete: "Odstranit"
delete-confirm: "Opravdu chcete smazat tento příspěvek?"
delete-and-edit: "Smazat a upravit"
remote: "Ukázat originální poznámku"
common/views/components/user-menu.vue:
mention: "Zmínění"
@@ -927,6 +948,7 @@ desktop/views/components/ui.header.account.vue:
lists: "Seznamy"
groups: "Skupiny"
admin: "Administrace"
room: "Místnost"
desktop/views/components/ui.header.nav.vue:
game: "Hry"
desktop/views/components/ui.header.notifications.vue:
@@ -1340,3 +1362,10 @@ pages:
arg1: "Seznamy"
types:
array: "Seznamy"
room:
translate: "Přesunout"
save: "Uložit"
saved: "Uloženo"
furnitures:
moon: "Měsíc"
bin: "Koš"
+8
View File
@@ -35,6 +35,7 @@ common:
signout: "Log ud"
reload-to-apply-the-setting: "Denne indstilling slår først igennem, når du har genindlæst siden. Vil du genindlæse siden nu?"
fetching-as-ap-object: "Tilladelse til sammenkobling"
delete-confirm: "Er du helt sikker på, at du vil slette denne post?"
notification-types:
all: "Alle"
follow: "Følger"
@@ -1909,3 +1910,10 @@ pages:
enviromentVariables: "Miljø variabel"
pageVariables: "Side element"
argVariables: "Input slot"
room:
translate: "Flyt"
save: "Gem"
saved: "Gemt"
furnitures:
moon: "Måne"
bin: "Skraldespand"
+7
View File
@@ -35,6 +35,7 @@ common:
signout: "Ausloggen"
reload-to-apply-the-setting: "Die Seite muss zum Übernehmen dieser Einstellung aktualisiert werden. Soll die Seite jetzt neu geladen werden?"
fetching-as-ap-object: "Hole Daten…"
delete-confirm: "Diesen Beitrag löschen?"
notification-types:
reply: "Antworten"
renote: "Anmerkung"
@@ -945,3 +946,9 @@ pages:
arg1: "Listen"
types:
array: "Listen"
room:
save: "Speichern"
saved: "Gespeichert"
furnitures:
moon: "Mond"
bin: "Papierkorb"
+75 -2
View File
@@ -30,13 +30,14 @@ common:
customize-home: "Customize home layout"
featured-notes: "Featured notes"
dark-mode: "Dark Mode"
signin: "Log In"
signin: "Login"
signup: "Sign up"
signout: "Logout"
reload-to-apply-the-setting: "You'll need to reload the page to reflect this setting. Do you want to reload it now?"
fetching-as-ap-object: "Inquiring to fediverse"
unfollow-confirm: "Do you want to unfollow {name}?"
signin-required: "Please Log In"
delete-confirm: "Are you sure you want to delete this post?"
signin-required: "Please login"
notification-type: "Notification Type"
notification-types:
all: "All"
@@ -295,6 +296,16 @@ common:
saved: "Saved"
home-profile: "Home profile"
deck-profile: "Deck profile"
room: "Room"
_room:
graphicsQuality: "Graphics Quality"
_graphicsQuality:
ultra: "Ultra"
high: "High"
medium: "Medium"
low: "Low"
cheep: "Cheep"
useOrthographicCamera: "Use Orthographic Camera"
search: "Search"
delete: "Delete"
loading: "Loading"
@@ -1134,6 +1145,7 @@ desktop/views/components/ui.header.account.vue:
groups: "Groups"
follow-requests: "Follow requests"
admin: "Admin"
room: "Room"
desktop/views/components/ui.header.nav.vue:
game: "Games"
desktop/views/components/ui.header.notifications.vue:
@@ -2073,3 +2085,64 @@ pages:
enviromentVariables: "Environment variable"
pageVariables: "Page element"
argVariables: "Input slot"
room:
add-furniture: "Place furniture"
translate: "Move"
rotate: "Rotate"
exit: "Deselect"
remove: "Remove"
save: "Save"
saved: "Saved"
clear: "Remove All"
clear-confirm: "Are you sure to remove all furnitures in your room?"
leave-confirm: "There are unsaved changes. Do you really want to leave?"
chooseImage: "Select an image"
room-type: "Room type"
carpet-color: "Color of carpet"
rooms:
default: "Default"
washitsu: "Japanese-style"
furnitures:
milk: "Milk carton"
bed: "Bed"
low-table: "Low Table"
desk: "Desk"
chair: "Chair"
chair2: "Chair 2"
fan: "Fan"
pc: "Computer"
plant: "Houseplant"
plant2: "Houseplant 2"
eraser: "Eraser"
pencil: "Pencil"
pudding: "Pudding"
cardboard-box: "Cardboard Box"
cardboard-box2: "Cardboard Box 2"
cardboard-box3: "Cardboard Box 3"
book: "Book"
book2: "Book 2"
piano: "Piano"
facial-tissue: "Facial tissue"
server: "Servers"
moon: "Moon"
corkboard: "Cork board"
mousepad: "Mousepad"
monitor: "Monitor"
keyboard: "Keyboard"
carpet-stripe: "Carpet (stripe)"
mat: "Mat"
color-box: "Bookshelf"
wall-clock: "Wall clock"
photoframe: "Picture frame"
cube: "Cube"
tv: "TV"
pinguin: "Penguin"
rubik-cube: "Rubik's Cube"
poster-h: "Poster (Horizontal)"
poster-v: "Poster (Vertical)"
sofa: "Sofa"
spiral: "Spiral Staircase"
bin: "Waste bin"
cup-noodle: "Cup noodle"
holo-display: "Holographic display"
energy-drink: "Energy drink"
+7
View File
@@ -31,6 +31,7 @@ common:
signin: "Iniciar sesión"
signup: "¡Regístrate!"
signout: "Cerrar sesión"
delete-confirm: "¿Seguro que quieres borrar la publicación?"
notification-types:
all: "Todo"
reply: "Responder"
@@ -1134,3 +1135,9 @@ pages:
arg1: "Listas"
types:
array: "Listas"
room:
save: "Guardar"
saved: "Guardado"
furnitures:
moon: "Luna"
bin: "Papelera"
+52
View File
@@ -35,6 +35,7 @@ common:
signout: "Se déconnecter"
reload-to-apply-the-setting: "Le rechargement de la page est nécessaire pour appliquer ces paramètres. Désirez-vous la recharger maintenant ?"
unfollow-confirm: "Désirez-vous vous désabonner de {name} ?"
delete-confirm: "Supprimer cette publication ?"
signin-required: "Veuillez vous connecter"
notification-type: "Type de notification"
notification-types:
@@ -1998,3 +1999,54 @@ pages:
emptySlot: "Slot vide"
enviromentVariables: "Variables d'environnement"
pageVariables: "Élément de page"
room:
add-furniture: "Placer des meubles"
translate: "Déplacer"
rotate: "Tourner"
remove: "Enlever"
save: "Enregistrer"
saved: "enregistré"
chooseImage: "Sélectionnez une image"
room-type: "Type de chambre"
carpet-color: "Couleur du tapis"
rooms:
default: "Par défaut"
washitsu: "Style japonnais"
furnitures:
milk: "Lait en carton"
bed: "Lit"
low-table: "Table basse"
desk: "Bureau"
chair: "Chaise"
chair2: "Chaise 2"
fan: "Ventilateur"
pc: "Ordinateur"
plant: "Plante dintérieur"
plant2: "Plante dintérieur 2"
eraser: "Gomme"
pencil: "Crayon"
cardboard-box: "Boîte en carton"
cardboard-box2: "Boîte en carton 2"
cardboard-box3: "Boîte en carton 3"
book: "Livre"
book2: "Livre 2"
piano: "Piano"
server: "Serveurs"
moon: "Lune"
corkboard: "Tableau en liège"
mousepad: "Tapis de souris"
monitor: "Écran"
keyboard: "Clavier"
carpet-stripe: "Tapis (zébré)"
color-box: "Étagère"
wall-clock: "Horloge murale"
photoframe: "Cadre photo"
cube: "Cube"
tv: "Téléviseur"
pinguin: "Pingouin"
rubik-cube: "Cube de Rubik"
poster-h: "Affiche (horizontale)"
poster-v: "Affiche (verticale)"
sofa: "Canapé"
spiral: "Escaliers en spirale"
bin: "Corbeille"
+75 -1
View File
@@ -37,6 +37,7 @@ common:
reload-to-apply-the-setting: "この設定を反映するにはページをリロードする必要があります。今すぐリロードしますか?"
fetching-as-ap-object: "連合に照会中"
unfollow-confirm: "{name}さんをフォロー解除しますか?"
delete-confirm: "この投稿を削除しますか?"
signin-required: "ログインしてください"
notification-type: "通知の種類"
notification-types:
@@ -307,6 +308,16 @@ common:
saved: "保存しました"
home-profile: "ホームのプロファイル"
deck-profile: "デッキのプロファイル"
room: "ルーム"
_room:
graphicsQuality: "グラフィックの品質"
_graphicsQuality:
ultra: "最高"
high: "高"
medium: "中"
low: "低"
cheep: "最低"
useOrthographicCamera: "平行投影カメラを使用"
search: "検索"
delete: "削除"
@@ -583,7 +594,7 @@ common/views/components/note-menu.vue:
delete: "削除"
delete-confirm: "この投稿を削除しますか?"
delete-and-edit: "削除して編集"
delete-and-edit-confirm: "この投稿を削除してもう一度編集しますか?この投稿へのリアクション、リノート、返信も全て削除されます。"
delete-and-edit-confirm: "この投稿を削除してもう一度編集しますか?この投稿へのリアクション、Renote、返信も全て削除されます。"
remote: "投稿元で見る"
pin-limit-exceeded: "これ以上ピン留めできません。"
@@ -1249,6 +1260,7 @@ desktop/views/components/ui.header.account.vue:
groups: "グループ"
follow-requests: "フォロー申請"
admin: "管理"
room: "ルーム"
desktop/views/components/ui.header.nav.vue:
game: "ゲーム"
@@ -2280,3 +2292,65 @@ pages:
enviromentVariables: "環境変数"
pageVariables: "ページ要素"
argVariables: "入力スロット"
room:
add-furniture: "家具を置く"
translate: "移動"
rotate: "回転"
exit: "戻る"
remove: "しまう"
save: "保存"
saved: "保存しました"
clear: "片付け"
clear-confirm: "全ての家具をしまいますか?"
leave-confirm: "未保存の変更があります、移動しますか?"
chooseImage: "画像を選択"
room-type: "部屋のタイプ"
carpet-color: "床の色"
rooms:
default: "デフォルト"
washitsu: "和室"
furnitures:
milk: "牛乳パック"
bed: "ベッド"
low-table: "ローテーブル"
desk: "デスク"
chair: "チェア"
chair2: "チェア2"
fan: "換気扇"
pc: "パソコン"
plant: "観葉植物"
plant2: "観葉植物2"
eraser: "消しゴム"
pencil: "鉛筆"
pudding: "プリン"
cardboard-box: "段ボール箱"
cardboard-box2: "段ボール箱2"
cardboard-box3: "段ボール箱3"
book: "本"
book2: "本2"
piano: "ピアノ"
facial-tissue: "ティッシュボックス"
server: "サーバー"
moon: "月"
corkboard: "コルクボード"
mousepad: "マウスパッド"
monitor: "モニター"
keyboard: "キーボード"
carpet-stripe: "カーペット(縞)"
mat: "マット"
color-box: "カラーボックス"
wall-clock: "壁掛け時計"
photoframe: "額縁"
cube: "キューブ"
tv: "テレビ"
pinguin: "ピンギン"
rubik-cube: "ルービックキューブ"
poster-h: "ポスター(横長)"
poster-v: "ポスター(縦長)"
sofa: "ソファ"
spiral: "螺旋階段"
bin: "ゴミ箱"
cup-noodle: "カップ麺"
holo-display: "ホログラフィックディスプレイ"
energy-drink: "エナジードリンク"
+8
View File
@@ -27,6 +27,7 @@ common:
load-more: "もっとあらへんのか!"
enter-password: "パスワードを入れてや"
2fa: "二段階認証"
delete-confirm: "この投稿を削除してもええか?"
notification-types:
all: "すべて"
follow: "フォロー"
@@ -1283,3 +1284,10 @@ pages:
arg1: "リスト"
types:
array: "リスト"
room:
translate: "移動"
save: "保存"
saved: "保存したで!"
furnitures:
moon: "月"
bin: "ゴミ箱"
+73
View File
@@ -36,6 +36,7 @@ common:
reload-to-apply-the-setting: "이 설정을 적용하려면 페이지를 새로고침해야 합니다. 바로 새로고침하시겠습니까?"
fetching-as-ap-object: "연합에서 조회 중"
unfollow-confirm: "{name} 님을 팔로우 해제하시겠습니까?"
delete-confirm: "이 글을 삭제하시겠습니까?"
signin-required: "로그인 해주세요"
notification-type: "알림의 종류"
notification-types:
@@ -295,6 +296,16 @@ common:
saved: "저장하였습니다"
home-profile: "홈 프로필"
deck-profile: "덱 프로필"
room: "룸"
_room:
graphicsQuality: "그래픽 품질"
_graphicsQuality:
ultra: "최고"
high: "높음"
medium: "보통"
low: "낮음"
cheep: "최저"
useOrthographicCamera: "평행 투시 카메라를 사용"
search: "검색"
delete: "삭제"
loading: "로드 중"
@@ -1134,6 +1145,7 @@ desktop/views/components/ui.header.account.vue:
groups: "그룹"
follow-requests: "팔로우 요청"
admin: "관리"
room: "룸"
desktop/views/components/ui.header.nav.vue:
game: "게임"
desktop/views/components/ui.header.notifications.vue:
@@ -2073,3 +2085,64 @@ pages:
enviromentVariables: "환경 변수"
pageVariables: "페이지 요소"
argVariables: "입력 슬롯"
room:
add-furniture: "가구를 배치"
translate: "이동"
rotate: "회전"
exit: "선택 해제"
remove: "치우기"
save: "저장"
saved: "저장하였습니다"
clear: "모두 치우기"
clear-confirm: "정말 방 안의 모든 가구를 치우시겠습니까?"
leave-confirm: "저장되지 않은 변경 사항이 있습니다. 정말 떠나시겠습니까?"
chooseImage: "이미지 선택"
room-type: "룸 종류"
carpet-color: "바닥 색상"
rooms:
default: "기본"
washitsu: "일본식"
furnitures:
milk: "우유 팩"
bed: "침대"
low-table: "낮은 테이블"
desk: "책상"
chair: "의자"
chair2: "의자 2"
fan: "환기구"
pc: "컴퓨터"
plant: "관엽식물"
plant2: "관엽식물 2"
eraser: "지우개"
pencil: "연필"
pudding: "푸딩"
cardboard-box: "골판지 상자"
cardboard-box2: "골판지 상자 2"
cardboard-box3: "골판지 상자 3"
book: "책"
book2: "책 2"
piano: "피아노"
facial-tissue: "휴지 상자"
server: "서버"
moon: "달"
corkboard: "게시판"
mousepad: "마우스 패드"
monitor: "모니터"
keyboard: "키보드"
carpet-stripe: "카페트 (줄무늬)"
mat: "매트"
color-box: "책장"
wall-clock: "벽걸이 시계"
photoframe: "액자"
cube: "큐브"
tv: "TV"
pinguin: "펭귄"
rubik-cube: "루빅스 큐브"
poster-h: "포스터 (가로)"
poster-v: "포스터 (세로)"
sofa: "소파"
spiral: "나선형 계단"
bin: "휴지통"
cup-noodle: "컵라면"
holo-display: "홀로그램"
energy-drink: "에너지 드링크"
+4
View File
@@ -638,3 +638,7 @@ pages:
arg1: "Lijsten"
types:
array: "Lijsten"
room:
translate: "Verplaatsen"
furnitures:
moon: "Maan"
+6
View File
@@ -520,3 +520,9 @@ pages:
arg1: "Lister"
types:
array: "Lister"
room:
translate: "Flytt"
save: "Lagre"
furnitures:
moon: "Måne"
bin: "Papirkurv"
+15 -2
View File
@@ -28,12 +28,18 @@ common:
signin: "Zaloguj się"
signup: "Rejestracja"
signout: "Wyloguj się"
delete-confirm: "Czy na pewno chcesz usunąć ten wpis?"
notification-type: "Typy powiadomień"
notification-types:
all: "Wszyscy"
pollVote: "Głosy"
follow: "Śledzeni"
reply: "Odpowiedz"
receiveFollowRequest: "Prośby o śledzenie"
reply: "Odpowiedzi"
quote: "Cytat"
renote: "Udostępnij"
reaction: "Reakcja"
mention: "Wzmianki"
reaction: "Reakcje"
got-it: "Rozumiem!"
customization-tips:
title: "Wskazówki o dostosowywaniu"
@@ -1250,3 +1256,10 @@ pages:
arg1: "Listy"
types:
array: "Listy"
room:
translate: "Przenieś"
save: "Zapisz"
saved: "Zapisano"
furnitures:
moon: "Księżyc"
bin: "Kosz"
+4
View File
@@ -284,3 +284,7 @@ pages:
blocks:
image: "Imagens"
post: "Formulário de publicação"
room:
furnitures:
moon: "Lua"
bin: "Lixo"
+4
View File
@@ -168,3 +168,7 @@ pages:
random: "Случайно"
blocks:
random: "Случайно"
room:
furnitures:
moon: "Луна"
bin: "Мусорное ведро"
+79
View File
@@ -36,11 +36,18 @@ common:
reload-to-apply-the-setting: "必须重新加载页面以应用此设置。 确实要立即重新加载吗?"
fetching-as-ap-object: "联合查询"
unfollow-confirm: "取消对{name}的关注?"
delete-confirm: "确定删除这个投稿吗?"
signin-required: "请先登录"
notification-type: "通知类型"
notification-types:
all: "所有"
pollVote: "投票"
follow: "关注中"
receiveFollowRequest: "关注请求"
reply: "回复"
quote: "引用"
renote: "转推"
mention: "提及"
reaction: "回应"
got-it: "知道了"
customization-tips:
@@ -208,6 +215,7 @@ common:
use-avatar-reversi-stones: "用头像作为黑白棋的棋子"
disable-animated-mfm: "在帖子中禁用动画文本"
disable-showing-animated-images: "不播放动画"
enable-quick-notification-view: "启用通知快速查看"
suggest-recent-hashtags: "在帖子表单上显示最近流行的哈希标签"
always-show-nsfw: "总是显示 NSFW 的内容"
always-mark-nsfw: "总是用 NSFW 来标记附件"
@@ -288,6 +296,16 @@ common:
saved: "已保存"
home-profile: "定制首页数据"
deck-profile: "定制Deck数据"
room: "房间"
_room:
graphicsQuality: "图形质量"
_graphicsQuality:
ultra: "最高"
high: "高"
medium: "中"
low: "低"
cheep: "最低"
useOrthographicCamera: "使用正交相机"
search: "搜索"
delete: "删除"
loading: "正在加载中"
@@ -537,6 +555,8 @@ common/views/components/note-menu.vue:
unpin: "取消置顶"
delete: "删除"
delete-confirm: "确定删除这个投稿吗?"
delete-and-edit: "删除和编辑"
delete-and-edit-confirm: "要删除此帖并再次编辑吗?对此帖的所有回应,转推和回复也将被删除。"
remote: "显示原始投稿"
pin-limit-exceeded: "无法置顶更多了。"
common/views/components/user-menu.vue:
@@ -1125,6 +1145,7 @@ desktop/views/components/ui.header.account.vue:
groups: "群组"
follow-requests: "关注申请"
admin: "管理"
room: "房间"
desktop/views/components/ui.header.nav.vue:
game: "游戏"
desktop/views/components/ui.header.notifications.vue:
@@ -2064,3 +2085,61 @@ pages:
enviromentVariables: "环境变量"
pageVariables: "页面元素"
argVariables: "输入槽函数"
room:
add-furniture: "放置家具"
translate: "移动"
rotate: "旋转"
exit: "返回"
remove: "移除"
save: "保存"
saved: "已保存"
clear: "清理"
clear-confirm: "是否清除所有家具?"
chooseImage: "选择图片"
room-type: "房间类型"
carpet-color: "地板颜色"
rooms:
default: "默认"
washitsu: "和式房间"
furnitures:
milk: "牛奶纸箱"
bed: "床"
low-table: "矮桌"
desk: "书桌"
chair: "椅子"
chair2: "椅子2"
fan: "换气扇"
pc: "电脑"
plant: "观叶植物"
plant2: "观叶植物2"
eraser: "橡皮擦"
pencil: "铅笔"
pudding: "布丁"
cardboard-box: "纸板箱"
cardboard-box2: "纸板箱2"
cardboard-box3: "纸板箱3"
book: "书"
book2: "书2"
piano: "钢琴"
facial-tissue: "纸巾盒"
server: "服务器"
moon: "月球"
corkboard: "软木板"
mousepad: "鼠标垫"
monitor: "显示器"
keyboard: "键盘"
carpet-stripe: "地毯(条纹)"
mat: "垫子"
color-box: "收纳柜"
wall-clock: "挂钟"
photoframe: "相框"
cube: "立方体"
tv: "电视"
pinguin: "企鹅君"
rubik-cube: "魔方"
poster-h: "海报(横向)"
poster-v: "海报(纵向)"
sofa: "沙发"
spiral: "螺旋楼梯"
bin: "垃圾箱"
cup-noodle: "杯面"
+3
View File
@@ -88,3 +88,6 @@ admin/views/charts.vue:
drive: "雲端硬碟"
pages:
like: "贊"
room:
furnitures:
moon: "月"
+13
View File
@@ -0,0 +1,13 @@
import {MigrationInterface, QueryRunner} from "typeorm";
export class room1565634203341 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<any> {
await queryRunner.query(`ALTER TABLE "user_profile" ADD "room" jsonb NOT NULL DEFAULT '{}'`);
}
public async down(queryRunner: QueryRunner): Promise<any> {
await queryRunner.query(`ALTER TABLE "user_profile" DROP COLUMN "room"`);
}
}
+23 -22
View File
@@ -1,7 +1,7 @@
{
"name": "misskey",
"author": "syuilo <i@syuilo.com>",
"version": "11.27.0",
"version": "11.30.0",
"codename": "daybreak",
"repository": {
"type": "git",
@@ -30,7 +30,7 @@
"lodash": "^4.17.13"
},
"dependencies": {
"@elastic/elasticsearch": "7.1.0",
"@elastic/elasticsearch": "7.3.0",
"@fortawesome/fontawesome-svg-core": "1.2.19",
"@fortawesome/free-brands-svg-icons": "5.9.0",
"@fortawesome/free-regular-svg-icons": "5.9.0",
@@ -99,25 +99,25 @@
"@types/ws": "6.0.1",
"@typescript-eslint/parser": "1.11.0",
"agentkeepalive": "4.0.2",
"animejs": "3.0.1",
"apexcharts": "3.8.3",
"animejs": "3.1.0",
"apexcharts": "3.8.4",
"autobind-decorator": "2.4.0",
"autosize": "4.0.2",
"autwh": "0.1.0",
"aws-sdk": "2.500.0",
"aws-sdk": "2.512.0",
"bcryptjs": "2.4.3",
"bootstrap": "4.3.1",
"bootstrap-vue": "2.0.0-rc.13",
"bull": "3.10.0",
"cafy": "15.1.1",
"cbor": "4.1.5",
"cbor": "4.2.1",
"chai": "4.2.0",
"chalk": "2.4.2",
"cli-highlight": "2.1.1",
"commander": "2.20.0",
"content-disposition": "0.5.3",
"crc-32": "1.2.0",
"css-loader": "3.1.0",
"css-loader": "3.2.0",
"cssnano": "4.1.10",
"dateformat": "3.0.3",
"deep-equal": "1.0.1",
@@ -128,7 +128,7 @@
"eslint-plugin-vue": "5.2.3",
"eventemitter3": "4.0.0",
"feed": "3.0.0",
"file-type": "12.0.1",
"file-type": "12.1.0",
"fluent-ffmpeg": "2.1.2",
"fuckadblock": "3.2.1",
"gulp": "4.0.2",
@@ -155,7 +155,7 @@
"json5": "2.1.0",
"json5-loader": "3.0.0",
"jsrsasign": "8.0.12",
"katex": "0.10.2",
"katex": "0.11.0",
"koa": "2.7.0",
"koa-bodyparser": "4.2.1",
"koa-compress": "3.0.0",
@@ -170,7 +170,7 @@
"koa-views": "6.2.0",
"langmap": "0.0.16",
"loader-utils": "1.2.3",
"lolex": "4.1.0",
"lolex": "4.2.0",
"lookup-dns-cache": "2.1.0",
"mocha": "6.2.0",
"moji": "0.5.1",
@@ -182,11 +182,11 @@
"object-assign-deep": "0.4.0",
"os-utils": "0.0.14",
"parse5": "5.1.0",
"parsimmon": "1.12.1",
"pg": "7.11.0",
"parsimmon": "1.13.0",
"pg": "7.12.1",
"portscanner": "2.2.0",
"postcss-loader": "3.0.0",
"prismjs": "1.16.0",
"prismjs": "1.17.1",
"progress-bar-webpack-plugin": "1.12.1",
"promise-limit": "2.7.0",
"promise-sequential": "1.1.1",
@@ -196,7 +196,7 @@
"qrcode": "1.4.1",
"random-seed": "0.3.0",
"randomcolor": "0.5.4",
"ratelimiter": "3.3.0",
"ratelimiter": "3.3.1",
"recaptcha-promise": "0.1.3",
"reconnecting-websocket": "4.1.10",
"redis": "2.8.0",
@@ -209,8 +209,8 @@
"rimraf": "2.6.3",
"rndstr": "1.0.0",
"s-age": "1.1.2",
"seedrandom": "3.0.1",
"sharp": "0.22.1",
"seedrandom": "3.0.3",
"sharp": "0.23.0",
"showdown": "1.9.0",
"showdown-highlightjs-extension": "0.1.2",
"speakeasy": "2.0.0",
@@ -221,8 +221,9 @@
"summaly": "2.3.0",
"systeminformation": "4.14.4",
"syuilo-password-strength": "0.0.1",
"terser-webpack-plugin": "1.3.0",
"terser-webpack-plugin": "1.4.1",
"textarea-caret": "3.1.0",
"three": "0.107.0",
"tinycolor2": "1.4.1",
"tmp": "0.1.0",
"ts-loader": "5.3.3",
@@ -241,13 +242,13 @@
"vue-color": "2.7.0",
"vue-content-loading": "1.6.0",
"vue-cropperjs": "4.0.0",
"vue-i18n": "8.12.0",
"vue-i18n": "8.14.0",
"vue-js-modal": "1.3.31",
"vue-json-pretty": "1.6.0",
"vue-loader": "15.7.1",
"vue-marquee-text-component": "1.1.1",
"vue-prism-component": "1.1.1",
"vue-router": "3.0.7",
"vue-router": "3.1.2",
"vue-sequential-entrance": "1.1.3",
"vue-style-loader": "4.1.2",
"vue-svg-inline-loader": "1.2.16",
@@ -257,10 +258,10 @@
"vuex": "3.1.1",
"vuex-persistedstate": "2.5.4",
"web-push": "3.3.5",
"webpack": "4.36.1",
"webpack-cli": "3.3.6",
"webpack": "4.39.2",
"webpack-cli": "3.3.7",
"websocket": "1.0.29",
"ws": "7.1.1",
"ws": "7.1.2",
"xev": "2.0.1"
},
"devDependencies": {
+1 -1
View File
@@ -1,5 +1,5 @@
declare module 'lookup-dns-cache' {
import { LookupOneOptions, LookupAllOptions, LookupOptions, LookupAddress } from 'dns'
import { LookupOneOptions, LookupAllOptions, LookupOptions, LookupAddress } from 'dns';
function lookup(hostname: string, family: number, callback: (err: NodeJS.ErrnoException | null, address: string, family: number) => void): void;
function lookup(hostname: string, options: LookupOneOptions, callback: (err: NodeJS.ErrnoException | null, address: string, family: number) => void): void;
+13 -2
View File
@@ -4,6 +4,7 @@ import shouldMuteNote from './should-mute-note';
import MkNoteMenu from '../views/components/note-menu.vue';
import MkReactionPicker from '../views/components/reaction-picker.vue';
import pleaseLogin from './please-login';
import i18n from '../../i18n';
function focus(el, fn) {
const target = fn(el);
@@ -21,6 +22,8 @@ type Opts = {
};
export default (opts: Opts = {}) => ({
i18n: i18n(),
data() {
return {
showContent: false,
@@ -175,8 +178,16 @@ export default (opts: Opts = {}) => ({
},
del() {
this.$root.api('notes/delete', {
noteId: this.appearNote.id
this.$root.dialog({
type: 'warning',
text: this.$t('@.delete-confirm'),
showCancelButton: true
}).then(({ canceled }) => {
if (canceled) return;
this.$root.api('notes/delete', {
noteId: this.appearNote.id
});
});
},
+15 -5
View File
@@ -44,13 +44,21 @@ export default (opts) => ({
return window.scrollY <= 8;
};
window.addEventListener('scroll', this.onWindowScroll, { passive: true });
window.addEventListener('scroll', this.onScroll, { passive: true });
} else if (opts.isContainer) {
this.isScrollTop = () => {
return this.$el.scrollTop <= 8;
};
this.$el.addEventListener('scroll', this.onScroll, { passive: true });
}
},
beforeDestroy() {
if (opts.captureWindowScroll) {
window.removeEventListener('scroll', this.onWindowScroll);
window.removeEventListener('scroll', this.onScroll);
} else if (opts.isContainer) {
this.$el.removeEventListener('scroll', this.onScroll);
}
},
@@ -152,7 +160,7 @@ export default (opts) => ({
this.queue = [];
},
onWindowScroll() {
onScroll() {
if (this.isScrollTop()) {
this.onTop();
}
@@ -163,8 +171,10 @@ export default (opts) => ({
// http://d.hatena.ne.jp/favril/20091105/1257403319
if (this.$el.offsetHeight == 0) return;
const current = window.scrollY + window.innerHeight;
if (current > document.body.offsetHeight - 8) this.onBottom();
const bottomPosition = opts.isContainer ? this.$el.scrollHeight : document.body.offsetHeight;
const currentBottomPosition = opts.isContainer ? this.$el.scrollTop + this.$el.clientHeight : window.scrollY + window.innerHeight;
if (currentBottomPosition > (bottomPosition - 8)) this.onBottom();
}
},
@@ -0,0 +1,21 @@
export type RoomInfo = {
roomType: string;
carpetColor: string;
furnitures: Furniture[];
};
export type Furniture = {
id: string; // 同じ家具が複数ある場合にそれぞれを識別するためのIDであり、家具IDではない
type: string; // こっちが家具ID(chairとか)
position: {
x: number;
y: number;
z: number;
};
rotation: {
x: number;
y: number;
z: number;
};
props?: Record<string, any>;
};
@@ -0,0 +1,397 @@
// 家具メタデータ
// 家具にはユーザーが設定できるプロパティを設定可能です:
//
// props: {
// <propname>: <proptype>
// }
//
// proptype一覧:
// * image ... 画像選択ダイアログを出し、その画像のURLが格納されます
// * color ... 色選択コントロールを出し、選択された色が格納されます
// 家具にカスタムテクスチャを適用できるようにするには、textureプロパティに以下の追加の情報を含めます:
// 便宜上そのUVのどの部分にカスタムテクスチャを貼り合わせるかのエリアをテクスチャエリアと呼びます。
// UVは1024*1024だと仮定します。
//
// <key>: {
// prop: <プロパティ名>,
// uv: {
// x: <テクスチャエリアX座標>,
// y: <テクスチャエリアY座標>,
// width: <テクスチャエリアの幅>,
// height: <テクスチャエリアの高さ>,
// },
// }
//
// <key>には、カスタムテクスチャを適用したいメッシュ名を指定します
// <プロパティ名>には、カスタムテクスチャとして使用する画像を格納するプロパティ(前述)名を指定します
// 家具にカスタムカラーを適用できるようにするには、colorプロパティに以下の追加の情報を含めます:
//
// <key>: <プロパティ名>
//
// <key>には、カスタムカラーを適用したいマテリアル名を指定します
// <プロパティ名>には、カスタムカラーとして使用する色を格納するプロパティ(前述)名を指定します
[
{
id: "milk",
place: "floor"
},
{
id: "bed",
place: "floor"
},
{
id: "low-table",
place: "floor",
props: {
color: 'color'
},
color: {
Table: 'color'
}
},
{
id: "desk",
place: "floor",
props: {
color: 'color'
},
color: {
Board: 'color'
}
},
{
id: "chair",
place: "floor",
props: {
color: 'color'
},
color: {
Chair: 'color'
}
},
{
id: "chair2",
place: "floor",
props: {
color1: 'color',
color2: 'color'
},
color: {
Cushion: 'color1',
Leg: 'color2'
}
},
{
id: "fan",
place: "wall"
},
{
id: "pc",
place: "floor"
},
{
id: "plant",
place: "floor"
},
{
id: "plant2",
place: "floor"
},
{
id: "eraser",
place: "floor"
},
{
id: "pencil",
place: "floor"
},
{
id: "pudding",
place: "floor"
},
{
id: "cardboard-box",
place: "floor"
},
{
id: "cardboard-box2",
place: "floor"
},
{
id: "cardboard-box3",
place: "floor"
},
{
id: "book",
place: "floor",
props: {
color: 'color'
},
color: {
Cover: 'color'
}
},
{
id: "book2",
place: "floor"
},
{
id: "piano",
place: "floor"
},
{
id: "facial-tissue",
place: "floor"
},
{
id: "server",
place: "floor"
},
{
id: "moon",
place: "floor"
},
{
id: "corkboard",
place: "wall"
},
{
id: "mousepad",
place: "floor",
props: {
color: 'color'
},
color: {
Pad: 'color'
}
},
{
id: "monitor",
place: "floor",
props: {
screen: 'image'
},
texture: {
Screen: {
prop: 'screen',
uv: {
x: 0,
y: 434,
width: 1024,
height: 588,
},
},
},
},
{
id: "tv",
place: "floor",
props: {
screen: 'image'
},
texture: {
Screen: {
prop: 'screen',
uv: {
x: 0,
y: 434,
width: 1024,
height: 588,
},
},
},
},
{
id: "keyboard",
place: "floor"
},
{
id: "carpet-stripe",
place: "floor",
props: {
color1: 'color',
color2: 'color'
},
color: {
CarpetAreaA: 'color1',
CarpetAreaB: 'color2'
},
},
{
id: "mat",
place: "floor",
props: {
color: 'color'
},
color: {
Mat: 'color'
}
},
{
id: "color-box",
place: "floor",
props: {
color: 'color'
},
color: {
main: 'color'
}
},
{
id: "wall-clock",
place: "wall"
},
{
id: "cube",
place: "floor",
props: {
color: 'color'
},
color: {
Cube: 'color'
}
},
{
id: "photoframe",
place: "wall",
props: {
photo: 'image',
color: 'color'
},
texture: {
Photo: {
prop: 'photo',
uv: {
x: 0,
y: 342,
width: 1024,
height: 683,
},
},
},
color: {
Frame: 'color'
}
},
{
id: "pinguin",
place: "floor",
props: {
body: 'color',
belly: 'color'
},
color: {
Body: 'body',
Belly: 'belly',
}
},
{
id: "rubik-cube",
place: "floor",
},
{
id: "poster-h",
place: "wall",
props: {
picture: 'image'
},
texture: {
Poster: {
prop: 'picture',
uv: {
x: 0,
y: 277,
width: 1024,
height: 745,
},
},
},
},
{
id: "poster-v",
place: "wall",
props: {
picture: 'image'
},
texture: {
Poster: {
prop: 'picture',
uv: {
x: 0,
y: 0,
width: 745,
height: 1024,
},
},
},
},
{
id: "sofa",
place: "floor",
props: {
color: 'color'
},
color: {
Sofa: 'color'
}
},
{
id: "spiral",
place: "floor",
props: {
color: 'color'
},
color: {
Step: 'color'
}
},
{
id: "bin",
place: "floor",
props: {
color: 'color'
},
color: {
Bin: 'color'
}
},
{
id: "cup-noodle",
place: "floor"
},
{
id: "holo-display",
place: "floor",
props: {
image: 'image'
},
texture: {
Image_Front: {
prop: 'image',
uv: {
x: 0,
y: 0,
width: 1024,
height: 1024,
},
},
Image_Back: {
prop: 'image',
uv: {
x: 0,
y: 0,
width: 1024,
height: 1024,
},
},
},
},
{
id: 'energy-drink',
place: "floor",
}
]
+776
View File
@@ -0,0 +1,776 @@
import autobind from 'autobind-decorator';
import { v4 as uuid } from 'uuid';
import * as THREE from 'three';
import { GLTFLoader, GLTF } from 'three/examples/jsm/loaders/GLTFLoader';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer.js';
import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass.js';
import { ShaderPass } from 'three/examples/jsm/postprocessing/ShaderPass.js';
import { BloomPass } from 'three/examples/jsm/postprocessing/BloomPass.js';
import { FXAAShader } from 'three/examples/jsm/shaders/FXAAShader.js';
import { TransformControls } from 'three/examples/jsm/controls/TransformControls.js';
import { Furniture, RoomInfo } from './furniture';
import { query as urlQuery } from '../../../../../prelude/url';
const furnitureDefs = require('./furnitures.json5');
THREE.ImageUtils.crossOrigin = '';
type Options = {
graphicsQuality: Room['graphicsQuality'];
onChangeSelect: Room['onChangeSelect'];
useOrthographicCamera: boolean;
};
/**
* MisskeyRoom Core Engine
*/
export class Room {
private clock: THREE.Clock;
private scene: THREE.Scene;
private renderer: THREE.WebGLRenderer;
private camera: THREE.PerspectiveCamera | THREE.OrthographicCamera;
private controls: OrbitControls;
private composer: EffectComposer;
private mixers: THREE.AnimationMixer[] = [];
private furnitureControl: TransformControls;
private roomInfo: RoomInfo;
private graphicsQuality: 'cheep' | 'low' | 'medium' | 'high' | 'ultra';
private roomObj: THREE.Object3D;
private objects: THREE.Object3D[] = [];
private selectedObject: THREE.Object3D = null;
private onChangeSelect: Function;
private isTransformMode = false;
private renderFrameRequestId: number;
private get canvas(): HTMLCanvasElement {
return this.renderer.domElement;
}
private get furnitures(): Furniture[] {
return this.roomInfo.furnitures;
}
private set furnitures(furnitures: Furniture[]) {
this.roomInfo.furnitures = furnitures;
}
private get enableShadow() {
return this.graphicsQuality != 'cheep';
}
private get usePostFXs() {
return this.graphicsQuality !== 'cheep' && this.graphicsQuality !== 'low';
}
private get shadowQuality() {
return (
this.graphicsQuality === 'ultra' ? 16384 :
this.graphicsQuality === 'high' ? 8192 :
this.graphicsQuality === 'medium' ? 4096 :
this.graphicsQuality === 'low' ? 1024 :
0); // cheep
}
constructor(user, isMyRoom, roomInfo: RoomInfo, container, options: Options) {
this.roomInfo = roomInfo;
this.graphicsQuality = options.graphicsQuality;
this.onChangeSelect = options.onChangeSelect;
this.clock = new THREE.Clock(true);
//#region Init a scene
this.scene = new THREE.Scene();
const width = window.innerWidth;
const height = window.innerHeight;
//#region Init a renderer
this.renderer = new THREE.WebGLRenderer({
antialias: false,
stencil: false,
alpha: false,
powerPreference:
this.graphicsQuality === 'ultra' ? 'high-performance' :
this.graphicsQuality === 'high' ? 'high-performance' :
this.graphicsQuality === 'medium' ? 'default' :
this.graphicsQuality === 'low' ? 'low-power' :
'low-power' // cheep
});
this.renderer.setPixelRatio(window.devicePixelRatio);
this.renderer.setSize(width, height);
this.renderer.autoClear = false;
this.renderer.setClearColor(new THREE.Color(0x051f2d));
this.renderer.shadowMap.enabled = this.enableShadow;
this.renderer.shadowMap.type =
this.graphicsQuality === 'ultra' ? THREE.PCFSoftShadowMap :
this.graphicsQuality === 'high' ? THREE.PCFSoftShadowMap :
this.graphicsQuality === 'medium' ? THREE.PCFShadowMap :
this.graphicsQuality === 'low' ? THREE.BasicShadowMap :
THREE.BasicShadowMap; // cheep
container.appendChild(this.canvas);
//#endregion
//#region Init a camera
this.camera = options.useOrthographicCamera
? new THREE.OrthographicCamera(
width / - 2, width / 2, height / 2, height / - 2, -10, 10)
: new THREE.PerspectiveCamera(45, width / height);
if (options.useOrthographicCamera) {
this.camera.position.x = 2;
this.camera.position.y = 2;
this.camera.position.z = 2;
this.camera.zoom = 100;
this.camera.updateProjectionMatrix();
} else {
this.camera.position.x = 5;
this.camera.position.y = 2;
this.camera.position.z = 5;
}
this.scene.add(this.camera);
//#endregion
//#region AmbientLight
const ambientLight = new THREE.AmbientLight(0xffffff, 1);
this.scene.add(ambientLight);
//#endregion
if (this.graphicsQuality !== 'cheep') {
//#region Room light
const roomLight = new THREE.SpotLight(0xffffff, 0.1);
roomLight.position.set(0, 8, 0);
roomLight.castShadow = this.enableShadow;
roomLight.shadow.bias = -0.0001;
roomLight.shadow.mapSize.width = this.shadowQuality;
roomLight.shadow.mapSize.height = this.shadowQuality;
roomLight.shadow.camera.near = 0.1;
roomLight.shadow.camera.far = 9;
roomLight.shadow.camera.fov = 45;
this.scene.add(roomLight);
//#endregion
}
//#region Out light
const outLight1 = new THREE.SpotLight(0xffffff, 0.4);
outLight1.position.set(9, 3, -2);
outLight1.castShadow = this.enableShadow;
outLight1.shadow.bias = -0.001; // アクネ、アーチファクト対策 その代わりピーターパンが発生する可能性がある
outLight1.shadow.mapSize.width = this.shadowQuality;
outLight1.shadow.mapSize.height = this.shadowQuality;
outLight1.shadow.camera.near = 6;
outLight1.shadow.camera.far = 15;
outLight1.shadow.camera.fov = 45;
this.scene.add(outLight1);
const outLight2 = new THREE.SpotLight(0xffffff, 0.2);
outLight2.position.set(-2, 3, 9);
outLight2.castShadow = false;
outLight2.shadow.bias = -0.001; // アクネ、アーチファクト対策 その代わりピーターパンが発生する可能性がある
outLight2.shadow.camera.near = 6;
outLight2.shadow.camera.far = 15;
outLight2.shadow.camera.fov = 45;
this.scene.add(outLight2);
//#endregion
//#region Init a controller
this.controls = new OrbitControls(this.camera, this.canvas);
this.controls.target.set(0, 1, 0);
this.controls.enableZoom = true;
this.controls.enablePan = isMyRoom;
this.controls.minPolarAngle = 0;
this.controls.maxPolarAngle = Math.PI / 2;
this.controls.minAzimuthAngle = 0;
this.controls.maxAzimuthAngle = Math.PI / 2;
this.controls.enableDamping = true;
this.controls.dampingFactor = 0.2;
this.controls.mouseButtons.LEFT = 1;
this.controls.mouseButtons.MIDDLE = 2;
this.controls.mouseButtons.RIGHT = 0;
//#endregion
//#region POST FXs
if (!this.usePostFXs) {
this.composer = null;
} else {
const renderTarget = new THREE.WebGLRenderTarget(width, height, {
minFilter: THREE.LinearFilter,
magFilter: THREE.LinearFilter,
format: THREE.RGBFormat,
stencilBuffer: false,
});
const fxaa = new ShaderPass(FXAAShader);
fxaa.uniforms['resolution'].value = new THREE.Vector2(1 / width, 1 / height);
fxaa.renderToScreen = true;
this.composer = new EffectComposer(this.renderer, renderTarget);
this.composer.addPass(new RenderPass(this.scene, this.camera));
if (this.graphicsQuality === 'ultra') {
this.composer.addPass(new BloomPass(0.25, 30, 128.0, 512));
}
this.composer.addPass(fxaa);
}
//#endregion
//#endregion
//#region Label
//#region Avatar
const avatarUrl = `/proxy/?${urlQuery({ url: user.avatarUrl })}`;
const textureLoader = new THREE.TextureLoader();
textureLoader.crossOrigin = 'anonymous';
const iconTexture = textureLoader.load(avatarUrl);
iconTexture.wrapS = THREE.RepeatWrapping;
iconTexture.wrapT = THREE.RepeatWrapping;
iconTexture.anisotropy = 16;
const avatarMaterial = new THREE.MeshBasicMaterial({
map: iconTexture,
side: THREE.DoubleSide,
alphaTest: 0.5
});
const iconGeometry = new THREE.PlaneGeometry(1, 1);
const avatarObject = new THREE.Mesh(iconGeometry, avatarMaterial);
avatarObject.position.set(-3, 2.5, 2);
avatarObject.rotation.y = Math.PI / 2;
avatarObject.castShadow = false;
this.scene.add(avatarObject);
//#endregion
//#region Username
const name = user.username;
new THREE.FontLoader().load('/assets/fonts/helvetiker_regular.typeface.json', font => {
const nameGeometry = new THREE.TextGeometry(name, {
size: 0.5,
height: 0,
curveSegments: 8,
font: font,
bevelThickness: 0,
bevelSize: 0,
bevelEnabled: false
});
const nameMaterial = new THREE.MeshLambertMaterial({
color: 0xffffff
});
const nameObject = new THREE.Mesh(nameGeometry, nameMaterial);
nameObject.position.set(-3, 2.25, 1.25);
nameObject.rotation.y = Math.PI / 2;
nameObject.castShadow = false;
this.scene.add(nameObject);
});
//#endregion
//#endregion
//#region Interaction
if (isMyRoom) {
this.furnitureControl = new TransformControls(this.camera, this.canvas);
this.scene.add(this.furnitureControl);
// Hover highlight
this.canvas.onmousemove = this.onmousemove;
// Click
this.canvas.onmousedown = this.onmousedown;
}
//#endregion
//#region Init room
this.loadRoom();
//#endregion
//#region Load furnitures
for (const furniture of this.furnitures) {
this.loadFurniture(furniture).then(obj => {
this.scene.add(obj.scene);
this.objects.push(obj.scene);
});
}
//#endregion
// Start render
if (this.usePostFXs) {
this.renderWithPostFXs();
} else {
this.renderWithoutPostFXs();
}
}
@autobind
private renderWithoutPostFXs() {
this.renderFrameRequestId =
window.requestAnimationFrame(this.renderWithoutPostFXs);
// Update animations
const clock = this.clock.getDelta();
for (const mixer of this.mixers) {
mixer.update(clock);
}
this.controls.update();
this.renderer.render(this.scene, this.camera);
}
@autobind
private renderWithPostFXs() {
this.renderFrameRequestId =
window.requestAnimationFrame(this.renderWithPostFXs);
// Update animations
const clock = this.clock.getDelta();
for (const mixer of this.mixers) {
mixer.update(clock);
}
this.controls.update();
this.renderer.clear();
this.composer.render();
}
@autobind
private loadRoom() {
const type = this.roomInfo.roomType;
new GLTFLoader().load(`/assets/room/rooms/${type}/${type}.glb`, gltf => {
gltf.scene.traverse(child => {
if (!(child instanceof THREE.Mesh)) return;
child.receiveShadow = this.enableShadow;
child.material = new THREE.MeshLambertMaterial({
color: (child.material as THREE.MeshStandardMaterial).color,
map: (child.material as THREE.MeshStandardMaterial).map,
name: (child.material as THREE.MeshStandardMaterial).name,
});
// 異方性フィルタリング
if ((child.material as THREE.MeshLambertMaterial).map && this.graphicsQuality !== 'cheep') {
(child.material as THREE.MeshLambertMaterial).map.minFilter = THREE.LinearMipMapLinearFilter;
(child.material as THREE.MeshLambertMaterial).map.magFilter = THREE.LinearMipMapLinearFilter;
(child.material as THREE.MeshLambertMaterial).map.anisotropy = 8;
}
});
gltf.scene.position.set(0, 0, 0);
this.scene.add(gltf.scene);
this.roomObj = gltf.scene;
if (this.roomInfo.roomType === 'default') {
this.applyCarpetColor();
}
});
}
@autobind
private loadFurniture(furniture: Furniture) {
const def = furnitureDefs.find(d => d.id === furniture.type);
return new Promise<GLTF>((res, rej) => {
const loader = new GLTFLoader();
loader.load(`/assets/room/furnitures/${furniture.type}/${furniture.type}.glb`, gltf => {
const model = gltf.scene;
// Load animation
if (gltf.animations.length > 0) {
const mixer = new THREE.AnimationMixer(model);
this.mixers.push(mixer);
for (const clip of gltf.animations) {
mixer.clipAction(clip).play();
}
}
model.name = furniture.id;
model.position.x = furniture.position.x;
model.position.y = furniture.position.y;
model.position.z = furniture.position.z;
model.rotation.x = furniture.rotation.x;
model.rotation.y = furniture.rotation.y;
model.rotation.z = furniture.rotation.z;
model.traverse(child => {
if (!(child instanceof THREE.Mesh)) return;
child.castShadow = this.enableShadow;
child.receiveShadow = this.enableShadow;
(child.material as THREE.MeshStandardMaterial).metalness = 0;
// 異方性フィルタリング
if ((child.material as THREE.MeshStandardMaterial).map && this.graphicsQuality !== 'cheep') {
(child.material as THREE.MeshStandardMaterial).map.minFilter = THREE.LinearMipMapLinearFilter;
(child.material as THREE.MeshStandardMaterial).map.magFilter = THREE.LinearMipMapLinearFilter;
(child.material as THREE.MeshStandardMaterial).map.anisotropy = 8;
}
});
if (def.color) { // カスタムカラー
this.applyCustomColor(model);
}
if (def.texture) { // カスタムテクスチャ
this.applyCustomTexture(model);
}
res(gltf);
}, null, rej);
});
}
@autobind
private applyCarpetColor() {
this.roomObj.traverse(child => {
if (!(child instanceof THREE.Mesh)) return;
if (child.material &&
(child.material as THREE.MeshStandardMaterial).name &&
(child.material as THREE.MeshStandardMaterial).name === 'Carpet'
) {
const colorHex = parseInt(this.roomInfo.carpetColor.substr(1), 16);
(child.material as THREE.MeshStandardMaterial).color.setHex(colorHex);
}
});
}
@autobind
private applyCustomColor(model: THREE.Object3D) {
const furniture = this.furnitures.find(furniture => furniture.id === model.name);
const def = furnitureDefs.find(d => d.id === furniture.type);
if (def.color == null) return;
model.traverse(child => {
if (!(child instanceof THREE.Mesh)) return;
for (const t of Object.keys(def.color)) {
if (!child.material ||
!(child.material as THREE.MeshStandardMaterial).name ||
(child.material as THREE.MeshStandardMaterial).name !== t
) continue;
const prop = def.color[t];
const val = furniture.props ? furniture.props[prop] : undefined;
if (val == null) continue;
const colorHex = parseInt(val.substr(1), 16);
(child.material as THREE.MeshStandardMaterial).color.setHex(colorHex);
}
});
}
@autobind
private applyCustomTexture(model: THREE.Object3D) {
const furniture = this.furnitures.find(furniture => furniture.id === model.name);
const def = furnitureDefs.find(d => d.id === furniture.type);
if (def.texture == null) return;
model.traverse(child => {
if (!(child instanceof THREE.Mesh)) return;
for (const t of Object.keys(def.texture)) {
if (child.name !== t) continue;
const prop = def.texture[t].prop;
const val = furniture.props ? furniture.props[prop] : undefined;
if (val == null) continue;
const canvas = document.createElement('canvas');
canvas.height = 1024;
canvas.width = 1024;
child.material = new THREE.MeshLambertMaterial({
emissive: 0x111111,
side: THREE.DoubleSide,
alphaTest: 0.5,
});
const img = new Image();
img.crossOrigin = 'anonymous';
img.onload = () => {
const uvInfo = def.texture[t].uv;
const ctx = canvas.getContext('2d');
ctx.drawImage(img,
0, 0, img.width, img.height,
uvInfo.x, uvInfo.y, uvInfo.width, uvInfo.height);
const texture = new THREE.Texture(canvas);
texture.wrapS = THREE.RepeatWrapping;
texture.wrapT = THREE.RepeatWrapping;
texture.anisotropy = 16;
texture.flipY = false;
(child.material as THREE.MeshLambertMaterial).map = texture;
(child.material as THREE.MeshLambertMaterial).needsUpdate = true;
(child.material as THREE.MeshLambertMaterial).map.needsUpdate = true;
};
img.src = val;
}
});
}
@autobind
private onmousemove(ev: MouseEvent) {
if (this.isTransformMode) return;
const rect = (ev.target as HTMLElement).getBoundingClientRect();
const x = (((ev.clientX * window.devicePixelRatio) - rect.left) / this.canvas.width) * 2 - 1;
const y = -(((ev.clientY * window.devicePixelRatio) - rect.top) / this.canvas.height) * 2 + 1;
const pos = new THREE.Vector2(x, y);
this.camera.updateMatrixWorld();
const raycaster = new THREE.Raycaster();
raycaster.setFromCamera(pos, this.camera);
const intersects = raycaster.intersectObjects(this.objects, true);
for (const object of this.objects) {
if (this.isSelectedObject(object)) continue;
object.traverse(child => {
if (child instanceof THREE.Mesh) {
(child.material as THREE.MeshStandardMaterial).emissive.setHex(0x000000);
}
});
}
if (intersects.length > 0) {
const intersected = this.getRoot(intersects[0].object);
if (this.isSelectedObject(intersected)) return;
intersected.traverse(child => {
if (child instanceof THREE.Mesh) {
(child.material as THREE.MeshStandardMaterial).emissive.setHex(0x191919);
}
});
}
}
@autobind
private onmousedown(ev: MouseEvent) {
if (this.isTransformMode) return;
if (ev.target !== this.canvas || ev.button !== 0) return;
const rect = (ev.target as HTMLElement).getBoundingClientRect();
const x = (((ev.clientX * window.devicePixelRatio) - rect.left) / this.canvas.width) * 2 - 1;
const y = -(((ev.clientY * window.devicePixelRatio) - rect.top) / this.canvas.height) * 2 + 1;
const pos = new THREE.Vector2(x, y);
this.camera.updateMatrixWorld();
const raycaster = new THREE.Raycaster();
raycaster.setFromCamera(pos, this.camera);
const intersects = raycaster.intersectObjects(this.objects, true);
for (const object of this.objects) {
object.traverse(child => {
if (child instanceof THREE.Mesh) {
(child.material as THREE.MeshStandardMaterial).emissive.setHex(0x000000);
}
});
}
if (intersects.length > 0) {
const selectedObj = this.getRoot(intersects[0].object);
this.selectFurniture(selectedObj);
} else {
this.selectedObject = null;
this.onChangeSelect(null);
}
}
@autobind
private getRoot(obj: THREE.Object3D): THREE.Object3D {
let found = false;
let x = obj.parent;
while (!found) {
if (x.parent.parent == null) {
found = true;
} else {
x = x.parent;
}
}
return x;
}
@autobind
private isSelectedObject(obj: THREE.Object3D): boolean {
if (this.selectedObject == null) {
return false;
} else {
return obj.name === this.selectedObject.name;
}
}
@autobind
private selectFurniture(obj: THREE.Object3D) {
this.selectedObject = obj;
this.onChangeSelect(obj);
obj.traverse(child => {
if (child instanceof THREE.Mesh) {
(child.material as THREE.MeshStandardMaterial).emissive.setHex(0xff0000);
}
});
}
/**
* /
* @param type
*/
@autobind
public enterTransformMode(type: 'translate' | 'rotate') {
this.isTransformMode = true;
this.furnitureControl.setMode(type);
this.furnitureControl.attach(this.selectedObject);
}
/**
* /
*/
@autobind
public exitTransformMode() {
this.isTransformMode = false;
this.furnitureControl.detach();
}
/**
*
* @param key
* @param value
*/
@autobind
public updateProp(key: string, value: any) {
const furniture = this.furnitures.find(furniture => furniture.id === this.selectedObject.name);
if (furniture.props == null) furniture.props = {};
furniture.props[key] = value;
this.applyCustomColor(this.selectedObject);
this.applyCustomTexture(this.selectedObject);
}
/**
*
* @param type
*/
@autobind
public addFurniture(type: string) {
const furniture = {
id: uuid(),
type: type,
position: {
x: 0,
y: 0,
z: 0,
},
rotation: {
x: 0,
y: 0,
z: 0,
},
};
this.furnitures.push(furniture);
this.loadFurniture(furniture).then(obj => {
this.scene.add(obj.scene);
this.objects.push(obj.scene);
});
}
/**
*
*/
@autobind
public removeFurniture() {
this.exitTransformMode();
const obj = this.selectedObject;
this.scene.remove(obj);
this.objects = this.objects.filter(object => object.name !== obj.name);
this.furnitures = this.furnitures.filter(furniture => furniture.id !== obj.name);
this.selectedObject = null;
this.onChangeSelect(null);
}
/**
*
*/
@autobind
public removeAllFurnitures() {
this.exitTransformMode();
for (const obj of this.objects) {
this.scene.remove(obj);
}
this.objects = [];
this.furnitures = [];
this.selectedObject = null;
this.onChangeSelect(null);
}
/**
*
* @param color
*/
@autobind
public updateCarpetColor(color: string) {
this.roomInfo.carpetColor = color;
this.applyCarpetColor();
}
/**
*
* @param type
*/
@autobind
public changeRoomType(type: string) {
this.roomInfo.roomType = type;
this.scene.remove(this.roomObj);
this.loadRoom();
}
/**
*
*/
@autobind
public getRoomInfo() {
for (const obj of this.objects) {
const furniture = this.furnitures.find(f => f.id === obj.name);
furniture.position.x = obj.position.x;
furniture.position.y = obj.position.y;
furniture.position.z = obj.position.z;
furniture.rotation.x = obj.rotation.x;
furniture.rotation.y = obj.rotation.y;
furniture.rotation.z = obj.rotation.z;
}
return this.roomInfo;
}
/**
*
*/
@autobind
public getSelectedObject() {
return this.selectedObject;
}
@autobind
public findFurnitureById(id: string) {
return this.furnitures.find(furniture => furniture.id === id);
}
/**
*
*/
@autobind
public destroy() {
// Stop render loop
window.cancelAnimationFrame(this.renderFrameRequestId);
this.controls.dispose();
this.scene.dispose();
}
}
@@ -159,6 +159,19 @@
<template #desc>{{ $t('@._settings.paste-dialog-desc') }}</template>
</ui-switch>
</section>
<section>
<header>{{ $t('@._settings.room') }}</header>
<ui-select v-model="roomGraphicsQuality">
<template #label>{{ $t('@._settings._room.graphicsQuality') }}</template>
<option value="ultra">{{ $t('@._settings._room._graphicsQuality.ultra') }}</option>
<option value="high">{{ $t('@._settings._room._graphicsQuality.high') }}</option>
<option value="medium">{{ $t('@._settings._room._graphicsQuality.medium') }}</option>
<option value="low">{{ $t('@._settings._room._graphicsQuality.low') }}</option>
<option value="cheep">{{ $t('@._settings._room._graphicsQuality.cheep') }}</option>
</ui-select>
<ui-switch v-model="roomUseOrthographicCamera">{{ $t('@._settings._room.useOrthographicCamera') }}</ui-switch>
</section>
</ui-card>
<ui-card>
@@ -503,6 +516,16 @@ export default Vue.extend({
set(value) { this.$store.dispatch('settings/set', { key: 'iLikeSushi', value }); }
},
roomUseOrthographicCamera: {
get() { return this.$store.state.device.roomUseOrthographicCamera; },
set(value) { this.$store.commit('device/set', { key: 'roomUseOrthographicCamera', value }); }
},
roomGraphicsQuality: {
get() { return this.$store.state.device.roomGraphicsQuality; },
set(value) { this.$store.commit('device/set', { key: 'roomGraphicsQuality', value }); }
},
games_reversi_showBoardLabels: {
get() { return this.$store.state.settings.gamesReversiShowBoardLabels; },
set(value) { this.$store.dispatch('settings/set', { key: 'gamesReversiShowBoardLabels', value }); }
@@ -16,7 +16,7 @@
<script lang="ts">
import Vue from 'vue';
import i18n from '../../../../i18n';
import * as uuid from 'uuid';
import { v4 as uuid } from 'uuid';
export default Vue.extend({
i18n: i18n('desktop/views/components/settings.tags.vue'),
@@ -125,7 +125,7 @@ import Vue from 'vue';
import i18n from '../../../../i18n';
import { lightTheme, darkTheme, builtinThemes, applyTheme, Theme } from '../../../../theme';
import { Chrome } from 'vue-color';
import * as uuid from 'uuid';
import { v4 as uuid } from 'uuid';
import * as tinycolor from 'tinycolor2';
import * as JSON5 from 'json5';
import { faMoon, faSun } from '@fortawesome/free-regular-svg-icons';
@@ -31,7 +31,7 @@
<script lang="ts">
import Vue from 'vue';
import * as uuid from 'uuid';
import { v4 as uuid } from 'uuid';
export default Vue.extend({
props: {
@@ -64,8 +64,7 @@ export default Vue.extend({
methods: {
onMousedown(e: MouseEvent) {
function distance(p, q) {
const sqrt = Math.sqrt, pow = Math.pow;
return sqrt(pow(p.x - q.x, 2) + pow(p.y - q.y, 2));
return Math.hypot(p.x - q.x, p.y - q.y);
}
function calcCircleScale(boxW, boxH, circleCenterX, circleCenterY) {
@@ -1,5 +1,5 @@
<template>
<mfm :text="user.name || user.username" :plain="true" :nowrap="true" :custom-emojis="user.emojis"/>
<mfm :text="user.name || user.username" :plain="true" :nowrap="nowrap" :custom-emojis="user.emojis"/>
</template>
<script lang="ts">
@@ -10,7 +10,11 @@ export default Vue.extend({
user: {
type: Object,
required: true
}
},
nowrap: {
type: Boolean,
default: true
},
}
});
</script>
@@ -14,7 +14,7 @@
<template v-if="active"><fa icon="angle-up"/></template>
<template v-else><fa icon="angle-down"/></template>
</button>
<span><slot name="header"></slot></span>
<span class="header"><slot name="header"></slot></span>
<span class="count" v-if="count > 0">({{ count }})</span>
<button v-if="!isTemporaryColumn" class="menu" ref="menu" @click.stop="showMenu"><fa icon="caret-down"/></button>
<button v-else class="close" @click.stop="close"><fa icon="times"/></button>
@@ -395,13 +395,22 @@ export default Vue.extend({
&.indicate
box-shadow 0 3px 0 0 var(--primary)
> span
> .header
display inline-block
align-items center
overflow hidden
text-overflow ellipsis
white-space nowrap
[data-icon]
margin-right 8px
> .count
margin-left 4px
opacity 0.5
> span:only-of-type
width 100%
> .toggleActive
> .menu
@@ -54,8 +54,8 @@
<div>
<header>
<fa icon="user-clock" class="icon"/>
<router-link :to="notification.user | userPage">
<mk-user-name :user="notification.user" class="name"/>
<router-link :to="notification.user | userPage" class="name">
<mk-user-name :user="notification.user"/>
</router-link>
<mk-time :time="notification.createdAt"/>
</header>
@@ -67,8 +67,8 @@
<div>
<header>
<fa icon="chart-pie" class="icon"/>
<router-link :to="notification.user | userPage">
<mk-user-name :user="notification.user" class="name"/>
<router-link :to="notification.user | userPage" class="name">
<mk-user-name :user="notification.user"/>
</router-link>
<mk-time :time="notification.createdAt"/>
</header>
@@ -167,6 +167,10 @@ export default Vue.extend({
display inline-block
margin-right 3px
&.reaction
> div > header
align-items normal
&.renote
> div > header [data-icon]
color #77B255
@@ -17,7 +17,7 @@
<mk-follow-button v-if="$store.getters.isSignedIn && user.id != $store.state.i.id" :user="user" class="follow" mini/>
<mk-avatar class="avatar" :user="user" :disable-preview="true" :key="user.id"/>
<router-link class="name" :to="user | userPage()">
<mk-user-name :user="user" :key="user.id"/>
<mk-user-name :user="user" :key="user.id" :nowrap="false"/>
</router-link>
<span class="acct">@{{ user | acct }} <fa v-if="user.isLocked == true" class="locked" icon="lock" fixed-width/></span>
<span class="followed" v-if="user.isFollowed">{{ $t('follows-you') }}</span>
+1 -1
View File
@@ -21,7 +21,7 @@ import i18n from '../../../i18n';
import XColumnCore from './deck.column-core.vue';
import Menu from '../../../common/views/components/menu.vue';
import * as uuid from 'uuid';
import { v4 as uuid } from 'uuid';
export default Vue.extend({
i18n: i18n('deck'),
@@ -54,7 +54,7 @@ import Vue from 'vue';
import i18n from '../../../i18n';
import XColumn from './deck.column.vue';
import * as XDraggable from 'vuedraggable';
import * as uuid from 'uuid';
import { v4 as uuid } from 'uuid';
export default Vue.extend({
i18n: i18n(),
@@ -143,7 +143,11 @@ export default Vue.extend({
this.$root.getMeta().then(meta => {
this.meta = meta;
});
}
},
mounted() {
document.title = this.$root.instanceName;
},
});
</script>
@@ -40,5 +40,9 @@ export default Vue.extend({
icon: faStar
});
},
mounted() {
document.title = this.$root.instanceName;
},
});
</script>
@@ -40,5 +40,9 @@ export default Vue.extend({
icon: faNewspaper
});
},
mounted() {
document.title = this.$root.instanceName;
},
});
</script>
@@ -26,7 +26,7 @@
<script lang="ts">
import Vue from 'vue';
import * as uuid from 'uuid';
import { v4 as uuid } from 'uuid';
import { faPlus, faQuestion } from '@fortawesome/free-solid-svg-icons';
import i18n from '../../../../../i18n';
import XContainer from '../page-editor.container.vue';
@@ -76,7 +76,7 @@ export default Vue.extend({
});
if (canceled) return;
const id = uuid.v4();
const id = uuid();
this.value.children.push({ id, type });
},
}
@@ -18,7 +18,7 @@
<script lang="ts">
import Vue from 'vue';
import * as uuid from 'uuid';
import { v4 as uuid } from 'uuid';
import { faPlus, faPencilAlt } from '@fortawesome/free-solid-svg-icons';
import { faStickyNote } from '@fortawesome/free-regular-svg-icons';
import i18n from '../../../../../i18n';
@@ -88,7 +88,7 @@ export default Vue.extend({
});
if (canceled) return;
const id = uuid.v4();
const id = uuid();
this.value.children.push({ id, type });
},
}
@@ -58,7 +58,7 @@ import i18n from '../../../../i18n';
import XContainer from './page-editor.container.vue';
import { faPencilAlt, faPlug } from '@fortawesome/free-solid-svg-icons';
import { isLiteralBlock, funcDefs, blockDefs } from '../../../../../../misc/aiscript/index';
import * as uuid from 'uuid';
import { v4 as uuid } from 'uuid';
export default Vue.extend({
i18n: i18n('pages'),
@@ -143,7 +143,7 @@ export default Vue.extend({
this.warn = null;
if (this.value.type === 'fn') {
const id = uuid.v4();
const id = uuid();
this.value.value = {};
Vue.set(this.value.value, 'slots', []);
Vue.set(this.value.value, 'expression', { id, type: null });
@@ -156,7 +156,7 @@ export default Vue.extend({
const empties = [];
for (let i = 0; i < fn.value.slots.length; i++) {
const id = uuid.v4();
const id = uuid();
empties.push({ id, type: null });
}
Vue.set(this.value, 'args', empties);
@@ -167,7 +167,7 @@ export default Vue.extend({
const empties = [];
for (let i = 0; i < funcDefs[this.value.type].in.length; i++) {
const id = uuid.v4();
const id = uuid();
empties.push({ id, type: null });
}
Vue.set(this.value, 'args', empties);
@@ -99,7 +99,7 @@ import { faSave, faStickyNote, faTrashAlt } from '@fortawesome/free-regular-svg-
import i18n from '../../../../i18n';
import XVariable from './page-editor.script-block.vue';
import XBlocks from './page-editor.blocks.vue';
import * as uuid from 'uuid';
import { v4 as uuid } from 'uuid';
import { blockDefs } from '../../../../../../misc/aiscript/index';
import { ASTypeChecker } from '../../../../../../misc/aiscript/type-checker';
import { url } from '../../../../config';
@@ -201,7 +201,7 @@ export default Vue.extend({
this.variables = this.page.variables;
this.eyeCatchingImageId = this.page.eyeCatchingImageId;
} else {
const id = uuid.v4();
const id = uuid();
this.content = [{
id,
type: 'text',
@@ -292,7 +292,7 @@ export default Vue.extend({
});
if (canceled) return;
const id = uuid.v4();
const id = uuid();
this.content.push({ id, type });
},
@@ -316,7 +316,7 @@ export default Vue.extend({
return;
}
const id = uuid.v4();
const id = uuid();
this.variables.push({ id, name, type: null });
},
@@ -52,6 +52,9 @@ export default Vue.extend({
icon: faStickyNote
});
},
mounted() {
document.title = this.$root.instanceName;
},
methods: {
create() {
this.$router.push(`/i/pages/new`);
@@ -0,0 +1,106 @@
<template>
<canvas width=224 height=128></canvas>
</template>
<script lang="ts">
import Vue from 'vue';
import * as THREE from 'three';
export default Vue.extend({
data() {
return {
selected: null,
objectHeight: 0,
orbitRadius: 5
};
},
mounted() {
const canvas = this.$el;
const width = canvas.width;
const height = canvas.height;
const scene = new THREE.Scene();
const renderer = new THREE.WebGLRenderer({
canvas: canvas,
antialias: true,
alpha: false
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(width, height);
renderer.setClearColor(0x000000);
renderer.autoClear = false;
renderer.shadowMap.enabled = true;
renderer.shadowMap.cullFace = THREE.CullFaceBack;
const camera = new THREE.PerspectiveCamera(75, width / height, 0.1, 100);
camera.zoom = 10;
camera.position.x = 0;
camera.position.y = 2;
camera.position.z = 0;
camera.updateProjectionMatrix();
scene.add(camera);
const ambientLight = new THREE.AmbientLight(0xffffff, 1);
ambientLight.castShadow = false;
scene.add(ambientLight);
const light = new THREE.PointLight(0xffffff, 1, 100);
light.position.set(3, 3, 3);
scene.add(light);
const grid = new THREE.GridHelper(5, 16, 0x444444, 0x222222);
scene.add(grid);
const render = () => {
const timer = Date.now() * 0.0004;
requestAnimationFrame(render);
camera.position.y = Math.sin(Math.PI / 6) * this.orbitRadius; // Math.PI / 6 => 30deg
camera.position.z = Math.cos(timer) * this.orbitRadius;
camera.position.x = Math.sin(timer) * this.orbitRadius;
camera.lookAt(new THREE.Vector3(0, this.objectHeight / 2, 0));
renderer.render(scene, camera);
};
this.selected = selected => {
const obj = selected.clone();
// Remove current object
const current = scene.getObjectByName('obj');
if (current != null) {
scene.remove(current);
}
// Add new object
obj.name = 'obj';
obj.position.x = 0;
obj.position.y = 0;
obj.position.z = 0;
obj.rotation.x = 0;
obj.rotation.y = 0;
obj.rotation.z = 0;
obj.traverse(child => {
if (child instanceof THREE.Mesh) {
child.material = child.material.clone();
return child.material.emissive.setHex(0x000000);
}
});
const objectBoundingBox = new THREE.Box3().setFromObject(obj);
this.objectHeight = objectBoundingBox.max.y - objectBoundingBox.min.y;
const objectWidth = objectBoundingBox.max.x - objectBoundingBox.min.x;
const objectDepth = objectBoundingBox.max.z - objectBoundingBox.min.z;
const horizontal = Math.hypot(objectWidth, objectDepth) / camera.aspect;
this.orbitRadius = Math.max(horizontal, this.objectHeight) * camera.zoom * 0.625 / Math.tan(camera.fov * 0.5 * (Math.PI / 180));
scene.add(obj);
};
render();
},
});
</script>
@@ -0,0 +1,310 @@
<template>
<div class="hveuntkp">
<div class="controller" v-if="objectSelected">
<section>
<p class="name">{{ selectedFurnitureName }}</p>
<x-preview ref="preview"/>
<template v-if="selectedFurnitureInfo.props">
<div v-for="k in Object.keys(selectedFurnitureInfo.props)" :key="k">
<p>{{ k }}</p>
<template v-if="selectedFurnitureInfo.props[k] === 'image'">
<ui-button @click="chooseImage(k)">{{ $t('chooseImage') }}</ui-button>
</template>
<template v-else-if="selectedFurnitureInfo.props[k] === 'color'">
<input type="color" :value="selectedFurnitureProps ? selectedFurnitureProps[k] : null" @change="updateColor(k, $event)"/>
</template>
</div>
</template>
</section>
<section>
<ui-button @click="translate()" :primary="isTranslateMode"><fa :icon="faArrowsAlt"/> {{ $t('translate') }}</ui-button>
<ui-button @click="rotate()" :primary="isRotateMode"><fa :icon="faUndo"/> {{ $t('rotate') }}</ui-button>
<ui-button v-if="isTranslateMode || isRotateMode" @click="exit()"><fa :icon="faBan"/> {{ $t('exit') }}</ui-button>
</section>
<section>
<ui-button @click="remove()"><fa :icon="faTrashAlt"/> {{ $t('remove') }}</ui-button>
</section>
</div>
<div class="menu" v-if="isMyRoom">
<section>
<ui-button @click="add()"><fa :icon="faBoxOpen"/> {{ $t('add-furniture') }}</ui-button>
</section>
<section>
<ui-select :value="roomType" @input="updateRoomType($event)">
<template #label>{{ $t('room-type') }}</template>
<option value="default">{{ $t('rooms.default') }}</option>
<option value="washitsu">{{ $t('rooms.washitsu') }}</option>
</ui-select>
<label v-if="roomType === 'default'">
<span>{{ $t('carpet-color') }}</span>
<input type="color" :value="carpetColor" @change="updateCarpetColor($event)"/>
</label>
</section>
<section>
<ui-button :primary="changed" @click="save()"><fa :icon="faSave"/> {{ $t('save') }}</ui-button>
<ui-button @click="clear()"><fa :icon="faBroom"/> {{ $t('clear') }}</ui-button>
</section>
</div>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
import i18n from '../../../../i18n';
import { Room } from '../../../scripts/room/room';
import parseAcct from '../../../../../../misc/acct/parse';
import XPreview from './preview.vue';
const storeItems = require('../../../scripts/room/furnitures.json5');
import { faBoxOpen, faUndo, faArrowsAlt, faBan, faBroom } from '@fortawesome/free-solid-svg-icons';
import { faSave, faTrashAlt } from '@fortawesome/free-regular-svg-icons';
import { query as urlQuery } from '../../../../../../prelude/url';
let room: Room;
export default Vue.extend({
i18n: i18n('room'),
components: {
XPreview
},
props: {
acct: {
type: String,
required: true
},
},
data() {
return {
objectSelected: false,
selectedFurnitureName: null,
selectedFurnitureInfo: null,
selectedFurnitureProps: null,
roomType: null,
carpetColor: null,
isTranslateMode: false,
isRotateMode: false,
isMyRoom: false,
changed: false,
faBoxOpen, faSave, faTrashAlt, faUndo, faArrowsAlt, faBan, faBroom,
};
},
async mounted() {
window.addEventListener('beforeunload', this.beforeunload);
const user = await this.$root.api('users/show', {
...parseAcct(this.acct)
});
this.isMyRoom = this.$store.getters.isSignedIn && this.$store.state.i.id === user.id;
const roomInfo = await this.$root.api('room/show', {
userId: user.id
});
this.roomType = roomInfo.roomType;
this.carpetColor = roomInfo.carpetColor;
room = new Room(user, this.isMyRoom, roomInfo, this.$el, {
graphicsQuality: this.$store.state.device.roomGraphicsQuality,
onChangeSelect: obj => {
this.objectSelected = obj != null;
if (obj) {
const f = room.findFurnitureById(obj.name);
this.selectedFurnitureName = this.$t('furnitures.' + f.type);
this.selectedFurnitureInfo = storeItems.find(x => x.id === f.type);
this.selectedFurnitureProps = f.props
? JSON.parse(JSON.stringify(f.props)) // Disable reactivity
: null;
this.$nextTick(() => {
this.$refs.preview.selected(obj);
});
}
},
useOrthographicCamera: this.$store.state.device.roomUseOrthographicCamera
});
},
beforeRouteLeave(to, from, next) {
if (this.changed) {
this.$root.dialog({
type: 'warning',
text: this.$t('leave-confirm'),
showCancelButton: true
}).then(({ canceled }) => {
if (canceled) {
next(false);
} else {
next();
}
});
} else {
next();
}
},
beforeDestroy() {
room.destroy();
window.removeEventListener('beforeunload', this.beforeunload);
},
methods: {
beforeunload(e: BeforeUnloadEvent) {
if (this.changed) {
e.preventDefault();
e.returnValue = '';
}
},
async add() {
const { canceled, result: id } = await this.$root.dialog({
type: null,
title: this.$t('add-furniture'),
select: {
items: storeItems.map(item => ({
value: item.id, text: this.$t('furnitures.' + item.id)
}))
},
showCancelButton: true
});
if (canceled) return;
room.addFurniture(id);
this.changed = true;
},
remove() {
this.isTranslateMode = false;
this.isRotateMode = false;
room.removeFurniture();
this.changed = true;
},
save() {
this.$root.api('room/update', {
room: room.getRoomInfo()
}).then(() => {
this.changed = false;
this.$root.dialog({
type: 'success',
text: this.$t('saved')
});
}).catch((e: any) => {
this.$root.dialog({
type: 'error',
text: e.message
});
});
},
clear() {
this.$root.dialog({
type: 'warning',
text: this.$t('clear-confirm'),
showCancelButton: true
}).then(({ canceled }) => {
if (canceled) return;
room.removeAllFurnitures();
this.changed = true;
});
},
chooseImage(key) {
this.$chooseDriveFile({
multiple: false
}).then(file => {
room.updateProp(key, `/proxy/?${urlQuery({ url: file.thumbnailUrl })}`);
this.$refs.preview.selected(room.getSelectedObject());
this.changed = true;
});
},
updateColor(key, ev) {
room.updateProp(key, ev.target.value);
this.$refs.preview.selected(room.getSelectedObject());
this.changed = true;
},
updateCarpetColor(ev) {
room.updateCarpetColor(ev.target.value);
this.carpetColor = ev.target.value;
this.changed = true;
},
updateRoomType(type) {
room.changeRoomType(type);
this.roomType = type;
this.changed = true;
},
translate() {
if (this.isTranslateMode) {
this.exit();
} else {
this.isRotateMode = false;
this.isTranslateMode = true;
room.enterTransformMode('translate');
}
this.changed = true;
},
rotate() {
if (this.isRotateMode) {
this.exit();
} else {
this.isTranslateMode = false;
this.isRotateMode = true;
room.enterTransformMode('rotate');
}
this.changed = true;
},
exit() {
this.isTranslateMode = false;
this.isRotateMode = false;
room.exitTransformMode();
this.changed = true;
}
}
});
</script>
<style lang="stylus" scoped>
.hveuntkp
> .controller
> .menu
position fixed
z-index 1
padding 16px
background var(--face)
color var(--text)
> section
padding 16px 0
&:first-child
padding-top 0
&:last-child
padding-bottom 0
&:not(:last-child)
border-bottom solid 1px var(--faceDivider)
> .controller
top 16px
left 16px
width 256px
> section
> .name
margin 0
> .menu
top 16px
right 16px
width 256px
</style>
@@ -62,6 +62,8 @@ export default Vue.extend({
};
},
mounted() {
document.title = this.$root.instanceName;
this.$root.api('users/groups/owned').then(groups => {
this.ownedGroups = groups;
});
@@ -33,6 +33,8 @@ export default Vue.extend({
};
},
mounted() {
document.title = this.$root.instanceName;
this.$root.api('users/lists/list').then(lists => {
this.fetching = false;
this.lists = lists;
@@ -71,7 +71,7 @@
<script lang="ts">
import define from '../../../common/define-widget';
import i18n from '../../../i18n';
import * as uuid from 'uuid';
import { v4 as uuid } from 'uuid';
export default define({
name: 'posts-monitor',
@@ -63,7 +63,7 @@
<script lang="ts">
import Vue from 'vue';
import * as uuid from 'uuid';
import { v4 as uuid } from 'uuid';
export default Vue.extend({
props: ['connection'],
+1
View File
@@ -187,6 +187,7 @@ init(async (launch, os) => {
{ path: '/i/drive/folder/:folder', component: MkDrive },
{ path: '/i/settings', component: MkSettings },
{ path: '/selectdrive', component: MkSelectDrive },
{ path: '/@:acct/room', props: true, component: () => import('../common/views/pages/room/room.vue').then(m => m.default) },
{ path: '/share', component: MkShare },
{ path: '/games/reversi/:game?', component: MkReversi },
{ path: '/authorize-follow', component: MkFollow },
@@ -11,17 +11,16 @@
<component :is="!$store.state.device.reduceMotion ? 'transition-group' : 'div'" name="mk-notifications" class="transition" tag="div">
<template v-for="(notification, i) in _notifications">
<div class="notification" :class="notification.type" :key="notification.id">
<mk-time :time="notification.createdAt"/>
<template v-if="notification.type == 'reaction'">
<mk-avatar class="avatar" :user="notification.user"/>
<div class="text">
<p>
<mk-reaction-icon :reaction="notification.reaction"/>
<router-link :to="notification.user | userPage" v-user-preview="notification.user.id">
<header>
<mk-reaction-icon :reaction="notification.reaction" class="icon"/>
<router-link :to="notification.user | userPage" v-user-preview="notification.user.id" class="name">
<mk-user-name :user="notification.user"/>
</router-link>
</p>
<mk-time :time="notification.createdAt"/>
</header>
<router-link class="note-ref" :to="notification.note | notePage" :title="getNoteSummary(notification.note)">
<fa icon="quote-left"/>
<mfm :text="getNoteSummary(notification.note)" :plain="true" :nowrap="true" :custom-emojis="notification.note.emojis"/>
@@ -33,11 +32,13 @@
<template v-if="notification.type == 'renote'">
<mk-avatar class="avatar" :user="notification.note.user"/>
<div class="text">
<p><fa icon="retweet"/>
<router-link :to="notification.note.user | userPage" v-user-preview="notification.note.userId">
<header>
<fa icon="retweet" class="icon"/>
<router-link :to="notification.note.user | userPage" v-user-preview="notification.note.userId" class="name">
<mk-user-name :user="notification.note.user"/>
</router-link>
</p>
<mk-time :time="notification.createdAt"/>
</header>
<router-link class="note-ref" :to="notification.note | notePage" :title="getNoteSummary(notification.note.renote)">
<fa icon="quote-left"/>
<mfm :text="getNoteSummary(notification.note.renote)" :plain="true" :nowrap="true" :custom-emojis="notification.note.renote.emojis"/>
@@ -49,11 +50,13 @@
<template v-if="notification.type == 'quote'">
<mk-avatar class="avatar" :user="notification.note.user"/>
<div class="text">
<p><fa icon="quote-left"/>
<router-link :to="notification.note.user | userPage" v-user-preview="notification.note.userId">
<header>
<fa icon="quote-left" class="icon"/>
<router-link :to="notification.note.user | userPage" v-user-preview="notification.note.userId" class="name">
<mk-user-name :user="notification.note.user"/>
</router-link>
</p>
<mk-time :time="notification.createdAt"/>
</header>
<router-link class="note-preview" :to="notification.note | notePage" :title="getNoteSummary(notification.note)">
<mfm :text="getNoteSummary(notification.note)" :plain="true" :custom-emojis="notification.note.emojis"/>
</router-link>
@@ -63,33 +66,39 @@
<template v-if="notification.type == 'follow'">
<mk-avatar class="avatar" :user="notification.user"/>
<div class="text">
<p><fa icon="user-plus"/>
<router-link :to="notification.user | userPage" v-user-preview="notification.user.id">
<header>
<fa icon="user-plus" class="icon"/>
<router-link :to="notification.user | userPage" v-user-preview="notification.user.id" class="name">
<mk-user-name :user="notification.user"/>
</router-link>
</p>
<mk-time :time="notification.createdAt"/>
</header>
</div>
</template>
<template v-if="notification.type == 'receiveFollowRequest'">
<mk-avatar class="avatar" :user="notification.user"/>
<div class="text">
<p><fa icon="user-clock"/>
<router-link :to="notification.user | userPage" v-user-preview="notification.user.id">
<header>
<fa icon="user-clock" class="icon"/>
<router-link :to="notification.user | userPage" v-user-preview="notification.user.id" class="name">
<mk-user-name :user="notification.user"/>
</router-link>
</p>
<mk-time :time="notification.createdAt"/>
</header>
</div>
</template>
<template v-if="notification.type == 'reply'">
<mk-avatar class="avatar" :user="notification.note.user"/>
<div class="text">
<p><fa icon="reply"/>
<router-link :to="notification.note.user | userPage" v-user-preview="notification.note.userId">
<header>
<fa icon="reply" class="icon"/>
<router-link :to="notification.note.user | userPage" v-user-preview="notification.note.userId" class="name">
<mk-user-name :user="notification.note.user"/>
</router-link>
</p>
<mk-time :time="notification.createdAt"/>
</header>
<router-link class="note-preview" :to="notification.note | notePage" :title="getNoteSummary(notification.note)">
<mfm :text="getNoteSummary(notification.note)" :plain="true" :custom-emojis="notification.note.emojis"/>
</router-link>
@@ -99,11 +108,13 @@
<template v-if="notification.type == 'mention'">
<mk-avatar class="avatar" :user="notification.note.user"/>
<div class="text">
<p><fa icon="at"/>
<router-link :to="notification.note.user | userPage" v-user-preview="notification.note.userId">
<header>
<fa icon="at" class="icon"/>
<router-link :to="notification.note.user | userPage" v-user-preview="notification.note.userId" class="name">
<mk-user-name :user="notification.note.user"/>
</router-link>
</p>
<mk-time :time="notification.createdAt"/>
</header>
<router-link class="note-preview" :to="notification.note | notePage" :title="getNoteSummary(notification.note)">
<mfm :text="getNoteSummary(notification.note)" :plain="true" :custom-emojis="notification.note.emojis"/>
</router-link>
@@ -113,9 +124,13 @@
<template v-if="notification.type == 'pollVote'">
<mk-avatar class="avatar" :user="notification.user"/>
<div class="text">
<p><fa icon="chart-pie"/><router-link :to="notification.user | userPage" v-user-preview="notification.user.id">
<mk-user-name :user="notification.user"/>
</router-link></p>
<header>
<fa icon="chart-pie" class="icon"/>
<router-link :to="notification.user | userPage" v-user-preview="notification.user.id" class="name">
<mk-user-name :user="notification.user"/>
</router-link>
<mk-time :time="notification.createdAt"/>
</header>
<router-link class="note-ref" :to="notification.note | notePage" :title="getNoteSummary(notification.note)">
<fa icon="quote-left"/>
<mfm :text="getNoteSummary(notification.note)" :plain="true" :nowrap="true" :custom-emojis="notification.note.emojis"/>
@@ -150,7 +165,9 @@ export default Vue.extend({
i18n: i18n(),
mixins: [
paging({}),
paging({
isContainer: true
}),
],
props: {
@@ -241,15 +258,6 @@ export default Vue.extend({
&:last-child
border-bottom none
> .mk-time
display inline
position absolute
top 16px
right 12px
vertical-align top
color var(--noteHeaderInfo)
font-size small
&:after
content ""
display block
@@ -270,12 +278,23 @@ export default Vue.extend({
width calc(100% - 36px)
padding-left 8px
p
margin 0
> header
display flex
align-items baseline
white-space nowrap
[data-icon], .mk-reaction-icon
> .icon
margin-right 4px
> .name
overflow hidden
text-overflow ellipsis
> .mk-time
margin-left auto
color var(--noteHeaderInfo)
font-size 0.9em
.note-preview
color var(--noteText)
display inline-block
@@ -296,20 +315,24 @@ export default Vue.extend({
display inline-block
margin-right 3px
&.reaction
.text header
align-items normal
&.renote, &.quote
.text p [data-icon]
.text header [data-icon]
color #77B255
&.follow
.text p [data-icon]
.text header [data-icon]
color #53c7ce
&.receiveFollowRequest
.text p [data-icon]
.text header [data-icon]
color #888
&.reply, &.mention
.text p [data-icon]
.text header [data-icon]
color #555
> .date
@@ -56,6 +56,13 @@
<i><fa icon="angle-right"/></i>
</router-link>
</li>
<li>
<router-link :to="`/@${ $store.state.i.username }/room`">
<i><fa :icon="faDoorOpen" fixed-width/></i>
<span>{{ $t('room') }}</span>
<i><fa icon="angle-right"/></i>
</router-link>
</li>
</ul>
<ul>
<li>
@@ -106,7 +113,7 @@ import i18n from '../../../i18n';
// import MkSettingsWindow from './settings-window.vue';
import MkDriveWindow from './drive-window.vue';
import contains from '../../../common/scripts/contains';
import { faHome, faColumns, faUsers } from '@fortawesome/free-solid-svg-icons';
import { faHome, faColumns, faUsers, faDoorOpen } from '@fortawesome/free-solid-svg-icons';
import { faMoon, faSun, faStickyNote } from '@fortawesome/free-regular-svg-icons';
export default Vue.extend({
@@ -114,7 +121,7 @@ export default Vue.extend({
data() {
return {
isOpen: false,
faHome, faColumns, faMoon, faSun, faStickyNote, faUsers
faHome, faColumns, faMoon, faSun, faStickyNote, faUsers, faDoorOpen
};
},
computed: {
@@ -4,7 +4,7 @@
<div class="banner" :style="u.bannerUrl ? `background-image: url(${u.bannerUrl})` : ''"></div>
<mk-avatar class="avatar" :user="u" :disable-preview="true"/>
<div class="title">
<router-link class="name" :to="u | userPage"><mk-user-name :user="u"/></router-link>
<router-link class="name" :to="u | userPage"><mk-user-name :user="u" :nowrap="false"/></router-link>
<p class="username"><mk-acct :user="u"/></p>
</div>
<div class="description">
+1 -1
View File
@@ -79,7 +79,7 @@
import Vue from 'vue';
import i18n from '../../../i18n';
import * as XDraggable from 'vuedraggable';
import * as uuid from 'uuid';
import { v4 as uuid } from 'uuid';
import XWelcome from '../pages/welcome.vue';
export default Vue.extend({
@@ -94,6 +94,8 @@ export default Vue.extend({
},
mounted() {
document.title = this.$root.instanceName;
(this.$refs.tl as any).$once('loaded', () => {
this.$emit('loaded');
});
@@ -5,7 +5,7 @@
<div class="fade"></div>
<div class="title">
<p class="name">
<mk-user-name :user="user"/>
<mk-user-name :user="user" :nowrap="false"/>
</p>
<div>
<span class="username"><mk-acct :user="user" :detail="true" /></span>
@@ -13,6 +13,9 @@ export default Vue.extend({
components: {
XSettings: () => import('../components/settings.vue').then(m => m.default)
},
mounted() {
document.title = this.$root.instanceName;
},
});
</script>
+7 -2
View File
@@ -1,7 +1,7 @@
import autobind from 'autobind-decorator';
import Vue from 'vue';
import { EventEmitter } from 'eventemitter3';
import * as uuid from 'uuid';
import { v4 as uuid } from 'uuid';
import initStore from './store';
import { apiUrl, version, locale } from './config';
@@ -28,7 +28,12 @@ export default class MiOS extends EventEmitter {
};
public get instanceName() {
return this.meta ? (this.meta.data.name || 'Misskey') : 'Misskey';
const siteName = document.querySelector('meta[property="og:site_name"]') as HTMLMetaElement;
if (siteName && siteName.content) {
return siteName.content;
}
return 'Misskey';
}
private isMetaFetching = false;
+1
View File
@@ -171,6 +171,7 @@ init((launch, os) => {
]},
{ path: '/@:user/pages/:page', component: UI, props: route => ({ component: () => import('../common/views/pages/page.vue').then(m => m.default), pageName: route.params.page, username: route.params.user }) },
{ path: '/@:user/pages/:pageName/view-source', component: UI, props: route => ({ component: () => import('../common/views/pages/page-editor/page-editor.vue').then(m => m.default), initUser: route.params.user, initPageName: route.params.pageName }) },
{ path: '/@:acct/room', props: true, component: () => import('../common/views/pages/room/room.vue').then(m => m.default) },
{ path: '/notes/:note', component: MkNote },
{ path: '/authorize-follow', component: MkFollow },
{ path: '*', component: MkNotFound }
@@ -180,6 +180,10 @@ export default Vue.extend({
display inline-block
margin-right 3px
&.reaction
> div > header
align-items normal
&.renote
> div > header [data-icon]
color #77B255
@@ -25,6 +25,9 @@ export default Vue.extend({
faBell,
};
},
mounted() {
document.title = this.$root.instanceName;
},
methods: {
beforeInit() {
Progress.start();
@@ -17,7 +17,7 @@
<mk-follow-button v-if="$store.getters.isSignedIn && $store.state.i.id != user.id" :user="user"/>
</div>
<div class="title">
<h1><mk-user-name :user="user" :key="user.id"/></h1>
<h1><mk-user-name :user="user" :key="user.id" :nowrap="false"/></h1>
<span class="username"><mk-acct :user="user" :detail="true" :key="user.id"/></span>
<span class="followed" v-if="user.isFollowed">{{ $t('follows-you') }}</span>
</div>
@@ -54,7 +54,7 @@
import Vue from 'vue';
import i18n from '../../../i18n';
import * as XDraggable from 'vuedraggable';
import * as uuid from 'uuid';
import { v4 as uuid } from 'uuid';
export default Vue.extend({
i18n: i18n('mobile/views/pages/widgets.vue'),
+2
View File
@@ -76,6 +76,8 @@ const defaultDeviceSettings = {
expandUsersPhotos: true,
expandUsersActivity: true,
enableMobileQuickNotificationView: false,
roomGraphicsQuality: 'medium',
roomUseOrthographicCamera: true,
};
export default (os: MiOS) => new Vuex.Store({
+7 -1
View File
@@ -11,11 +11,17 @@
"sourceMap": false,
"target": "es2017",
"module": "esnext",
"moduleResolution": "node",
"removeComments": false,
"noLib": false,
"strict": true,
"strictNullChecks": false,
"experimentalDecorators": true
"experimentalDecorators": true,
"resolveJsonModule": true,
"typeRoots": [
"node_modules/@types",
"src/@types"
]
},
"compileOnSave": false,
"include": [
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

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