Compare commits
	
		
			443 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | db248a69c8 | ||
|   | 5951288159 | ||
|   | 17b92c9db2 | ||
|   | 962d1060d9 | ||
|   | cb2640d961 | ||
| ![greenkeeper[bot]](/assets/img/avatar_default.png)  | 29aeb0f082 | ||
|   | 990347f856 | ||
|   | 7a406c1f13 | ||
|   | 9432af2ab5 | ||
|   | 136b13e7ca | ||
|   | ba1c823fb1 | ||
| ![greenkeeper[bot]](/assets/img/avatar_default.png)  | f1301a4780 | ||
| ![greenkeeper[bot]](/assets/img/avatar_default.png)  | 7957cd4963 | ||
| ![greenkeeper[bot]](/assets/img/avatar_default.png)  | ee6590d03f | ||
| ![greenkeeper[bot]](/assets/img/avatar_default.png)  | f2a1238b20 | ||
|   | e9ce84f368 | ||
|   | 52e84decb4 | ||
|   | e893002bb6 | ||
|   | 3792103e80 | ||
|   | 7a861c9481 | ||
|   | 942b565224 | ||
|   | 88390d7a9a | ||
|   | 966fc4c5d7 | ||
|   | 84dbdf1196 | ||
|   | 211e7f90d9 | ||
|   | e54b8e3fb2 | ||
|   | 836c89ed33 | ||
|   | c7c73afea1 | ||
|   | 7b9ca63b1e | ||
|   | c464183329 | ||
|   | 389f420cad | ||
|   | 6b2888383c | ||
|   | 3c38a867b4 | ||
|   | 7f5a69f4d8 | ||
|   | bb9ab31d5e | ||
|   | 9def80af8a | ||
| ![greenkeeper[bot]](/assets/img/avatar_default.png)  | 9256bcdbe4 | ||
|   | 9b775022bc | ||
|   | 32371ed2bd | ||
|   | 8b98c08a81 | ||
|   | 7cf72f7447 | ||
|   | 913385b10d | ||
|   | 7306468d08 | ||
| ![greenkeeper[bot]](/assets/img/avatar_default.png)  | 11e5667778 | ||
|   | 38cc02e261 | ||
|   | d52cf46cc1 | ||
|   | c6110dd996 | ||
|   | 51d8de2c38 | ||
|   | 4455a1aa9d | ||
|   | 040d395ddb | ||
|   | 8296cac636 | ||
|   | 3eafe8b87d | ||
|   | c01512e261 | ||
|   | e5cf3aecd5 | ||
| ![greenkeeper[bot]](/assets/img/avatar_default.png)  | a8f90b41b7 | ||
|   | b79169b975 | ||
|   | 437d52e2ed | ||
|   | 1329721440 | ||
|   | 6affb4fe97 | ||
|   | 15395686aa | ||
|   | 047bcc78ad | ||
|   | 9df68618f2 | ||
|   | 732db087ab | ||
|   | 0e95b33b6a | ||
|   | 816ae7eb7e | ||
|   | 5a5ff194fa | ||
|   | a60edf9cff | ||
|   | 1c2dbb914e | ||
|   | 9c170c426b | ||
|   | c6239c8ad9 | ||
|   | 159b361bac | ||
|   | 160f64c18e | ||
|   | e5916b3789 | ||
|   | 70982b33c5 | ||
|   | b4d614ad45 | ||
|   | 6d2ef41b37 | ||
|   | e102237aab | ||
|   | 665af87031 | ||
|   | 6f4e439697 | ||
|   | 742dcf35c9 | ||
|   | 9cd70c568c | ||
|   | facabf274f | ||
|   | e3ab51022f | ||
|   | d278367cf9 | ||
|   | a70ced8e90 | ||
|   | 567cedc7cc | ||
| ![greenkeeper[bot]](/assets/img/avatar_default.png)  | 9b3af6efcd | ||
|   | d9edc1eb1d | ||
|   | 65e46b5cec | ||
|   | e00b5f11cb | ||
|   | 6b53d5f269 | ||
|   | 59c80ab140 | ||
|   | da323aad36 | ||
|   | 7c1611c939 | ||
|   | ab861beabe | ||
|   | d260e93161 | ||
|   | 65a1855606 | ||
|   | c0e08e44a4 | ||
|   | 5c1cebcef4 | ||
|   | af25d3a85e | ||
|   | 8cb7183107 | ||
|   | 1bf228d73e | ||
|   | d952b996e6 | ||
|   | 1e407c4059 | ||
|   | b56d1fa60e | ||
|   | 6340f95bfc | ||
|   | 3c08dacf6c | ||
|   | 2908124ad8 | ||
|   | 3d62faaaf2 | ||
|   | b1efa9700d | ||
|   | 1d08af5747 | ||
|   | 2f82d0db87 | ||
|   | d88159907d | ||
|   | 9ed9fbef65 | ||
|   | 86c2e5bb91 | ||
|   | d9b548de1a | ||
|   | 2271c6cbd8 | ||
| ![greenkeeper[bot]](/assets/img/avatar_default.png)  | c4d4293c46 | ||
|   | 39bdfb6e0d | ||
|   | 1003fd393e | ||
|   | 2ede3c0864 | ||
|   | 674764a035 | ||
|   | a780e7b936 | ||
|   | 03d0ce1f89 | ||
|   | 4182a0cf4c | ||
|   | 305915611e | ||
|   | b0cd59bed9 | ||
|   | 599dcbaa48 | ||
|   | 2806dc98bd | ||
|   | bdc52dc114 | ||
|   | 3f6b9e554c | ||
|   | f47ad7bf31 | ||
|   | f992f72d31 | ||
|   | a26f1db2cb | ||
| ![greenkeeper[bot]](/assets/img/avatar_default.png)  | 361ab00c61 | ||
| ![greenkeeper[bot]](/assets/img/avatar_default.png)  | f5cbcf3452 | ||
| ![greenkeeper[bot]](/assets/img/avatar_default.png)  | 599386190a | ||
| ![greenkeeper[bot]](/assets/img/avatar_default.png)  | ec541d3cd0 | ||
|   | 3199819ded | ||
| ![greenkeeper[bot]](/assets/img/avatar_default.png)  | ccf04d63ec | ||
|   | b9f5fca333 | ||
|   | b6a330928d | ||
|   | 1c65cb3e36 | ||
|   | dbb8c99efb | ||
|   | 0adcb646fe | ||
|   | a1ef70c0bf | ||
|   | 75cd580c3a | ||
|   | e05acb8d18 | ||
|   | 10af684804 | ||
|   | 3e897727ca | ||
|   | d0570d7fe3 | ||
|   | 5cf1956135 | ||
|   | 0b98a2364b | ||
|   | fff307d4bb | ||
|   | 2b7782ba03 | ||
|   | 96d961ee80 | ||
|   | 9f064d76d9 | ||
|   | 2e39106c4b | ||
|   | 1305006391 | ||
|   | 04650464f3 | ||
|   | 3bc7e1e35c | ||
|   | 7019ddbfc7 | ||
|   | 106d990bd2 | ||
|   | b29eb29556 | ||
|   | aeac1854ed | ||
|   | dbc57dd0d3 | ||
|   | 328a87609e | ||
|   | 5d848f3900 | ||
|   | cf4ed45fe4 | ||
|   | 07293094d5 | ||
|   | 0917696c86 | ||
|   | 030a027366 | ||
|   | 372c488585 | ||
|   | 738b8ff1ee | ||
|   | 1561fc5994 | ||
|   | c84f18545e | ||
|   | 48e4dc75f4 | ||
|   | 63a8d556e5 | ||
|   | e5591618ee | ||
|   | 4794748c73 | ||
|   | 02e7e3b971 | ||
| ![greenkeeper[bot]](/assets/img/avatar_default.png)  | d2aca3c28b | ||
|   | 11b84a04b3 | ||
|   | f243ce66e7 | ||
|   | baf9b65801 | ||
| ![greenkeeper[bot]](/assets/img/avatar_default.png)  | 55419d2524 | ||
|   | 401d0b1298 | ||
|   | fce7dc0f4e | ||
|   | 35489ef5b7 | ||
|   | 546d494587 | ||
|   | e8afa2c940 | ||
|   | c1ef1bf605 | ||
|   | 4ab0dbe7e3 | ||
|   | 44f86a94f4 | ||
|   | a0278154a3 | ||
| ![greenkeeper[bot]](/assets/img/avatar_default.png)  | 8b7e6b200e | ||
| ![greenkeeper[bot]](/assets/img/avatar_default.png)  | d6f6c26725 | ||
| ![greenkeeper[bot]](/assets/img/avatar_default.png)  | cf66343b31 | ||
| ![greenkeeper[bot]](/assets/img/avatar_default.png)  | d53689332f | ||
| ![greenkeeper[bot]](/assets/img/avatar_default.png)  | 4105237027 | ||
| ![greenkeeper[bot]](/assets/img/avatar_default.png)  | 436962e4b8 | ||
|   | a85efa1392 | ||
|   | f0115a5e21 | ||
|   | 80105239dc | ||
|   | baad11288a | ||
|   | 7e50646ede | ||
|   | d4b8e47bcb | ||
|   | 0eefd2922c | ||
|   | 30c0f98691 | ||
|   | 06a7c2e138 | ||
|   | 3537b3de8e | ||
|   | ed6450244d | ||
|   | e813880392 | ||
|   | 9a57efa6d9 | ||
|   | 03ee5eba3b | ||
|   | 295ea79231 | ||
|   | a5486176c1 | ||
|   | de58325fd0 | ||
|   | 1e7932d9c7 | ||
|   | 8ba76df409 | ||
|   | a8f9d20229 | ||
|   | 5e6d1b9ae8 | ||
|   | c5afbaef35 | ||
|   | 3b5a36a09f | ||
|   | fcb20d05d7 | ||
|   | 9e6990c44b | ||
|   | 8f3fd9b0dc | ||
|   | 5b1b4a02d8 | ||
|   | 31de530497 | ||
|   | 16b6b1f2b3 | ||
|   | dba83aa50d | ||
|   | bade054a6a | ||
|   | 34d3485dc9 | ||
|   | a84d066daa | ||
|   | 3360cf27cd | ||
|   | c1a13af611 | ||
|   | 47274a658b | ||
|   | b194334031 | ||
|   | 4136c4a807 | ||
|   | f1c212fe75 | ||
|   | d08cbff4b7 | ||
|   | 0b774475fa | ||
|   | c4f6195df3 | ||
|   | 192cdbe322 | ||
|   | a2a25eb5f8 | ||
|   | 274cf1af1c | ||
|   | 7d11c8b767 | ||
|   | abef6bafe3 | ||
|   | da237a5e2d | ||
|   | 7e50e03cfb | ||
|   | 89d5df20a5 | ||
|   | c09a2a37fe | ||
|   | b5745877ca | ||
|   | c0ac15cad7 | ||
|   | 90ce09be2e | ||
|   | fd39afb374 | ||
|   | 6e04549a9b | ||
|   | 80e56fddd9 | ||
|   | 4daf9e1180 | ||
|   | f72abc0e47 | ||
|   | 9c177f3df2 | ||
|   | a279b32c93 | ||
|   | 51465ba026 | ||
|   | 6a7bdcc533 | ||
|   | fddb3a5f10 | ||
|   | 643c7abc12 | ||
|   | 5715afd44c | ||
|   | d65c1c420e | ||
|   | 38139ee6c9 | ||
|   | 6b96bd0185 | ||
|   | f2b9863eea | ||
|   | f56adce51f | ||
|   | 35598c8064 | ||
|   | a5e716eb5d | ||
|   | e8073b7484 | ||
|   | d6a5fc20bb | ||
|   | e763d43085 | ||
|   | a6904d5249 | ||
|   | 7bcb91d3ca | ||
|   | fb0c1efa41 | ||
|   | 03d243d444 | ||
|   | b91585d1fe | ||
|   | d1fa318cda | ||
|   | 42decae424 | ||
|   | 78bc7c20ed | ||
|   | e6616bdf57 | ||
|   | 35362ed3c7 | ||
|   | cd0b9a8e3f | ||
|   | 110aadd65c | ||
|   | cefe1f34be | ||
|   | d469e2152c | ||
|   | 35c2d47518 | ||
|   | c00634a2cf | ||
|   | d1835e262d | ||
|   | d0f304f0ce | ||
|   | 154abe06a7 | ||
|   | ac41cd378c | ||
|   | d59afda2c9 | ||
|   | 4d213833e2 | ||
|   | e9214d4330 | ||
|   | 6b41bb95b2 | ||
|   | 36de13d543 | ||
|   | 3893def9f4 | ||
|   | ff76c815b1 | ||
|   | 1b9b8912ae | ||
|   | b91b0d17c3 | ||
|   | 579b61a806 | ||
|   | 1e2b484929 | ||
|   | ab7d4fa2a2 | ||
|   | f30c8b8a47 | ||
|   | 25dd19dd8c | ||
|   | fdaebc6315 | ||
|   | f1a05c214e | ||
|   | 9ad32ffee9 | ||
|   | 70f83ab019 | ||
|   | 07e64631f2 | ||
|   | 498416e2e3 | ||
|   | 87c4f908fe | ||
|   | 27e6eaacde | ||
|   | ada47920ca | ||
|   | f2606d62ff | ||
|   | 35032152b3 | ||
|   | 90b545fd69 | ||
|   | 4f7776d1f9 | ||
|   | 03bd0c4c9e | ||
|   | b8b4991a46 | ||
|   | 8b68c5da37 | ||
|   | f26e641905 | ||
|   | 57669c9c03 | ||
|   | 094d873f2e | ||
|   | 7b42653271 | ||
|   | 6a82e94c54 | ||
|   | 1fa4d0d3f8 | ||
|   | d5818214f3 | ||
|   | 0c63ec8157 | ||
|   | 8317a219a5 | ||
|   | ec652dd0ac | ||
|   | 8e3dd75c85 | ||
|   | 3f4de3b1cc | ||
|   | e0d3fd17ce | ||
|   | 671c7cf06b | ||
|   | 99a2c5b3fa | ||
|   | 0343de95b8 | ||
|   | 13f258308e | ||
|   | c627288bde | ||
|   | 1eef90f6cb | ||
|   | 29476ea3da | ||
|   | 7609741680 | ||
|   | 5df85b5feb | ||
|   | b4a4d784c3 | ||
|   | d715af0620 | ||
|   | fe8c384618 | ||
|   | 47d4de75da | ||
|   | 016c7fd2c4 | ||
|   | 7ca5e33a3a | ||
|   | 436773837b | ||
|   | fccfe19e13 | ||
|   | 18be0d36f3 | ||
|   | 9ea7de3564 | ||
|   | d1dce76e28 | ||
|   | f4bf824e79 | ||
|   | cbf5d4b71d | ||
|   | 61e5cb2041 | ||
|   | 38a6aa26bc | ||
|   | 32942709bf | ||
|   | a0305c4c04 | ||
|   | 74be1c81b1 | ||
|   | e82a44c03d | ||
|   | 1e9eeeb980 | ||
|   | 0c7111b438 | ||
|   | ef74653a4b | ||
|   | b032f78769 | ||
|   | 7a0a8b5d2b | ||
|   | 459b374d61 | ||
|   | cc6af402be | ||
|   | f3eeadcd8f | ||
|   | 5b0b83faa7 | ||
|   | 5f289e4767 | ||
|   | a36d73cb52 | ||
|   | 9e319006f3 | ||
|   | 7b8a2aef0f | ||
|   | 4fe2f29478 | ||
|   | 76a25917c0 | ||
|   | df6c9b1a1c | ||
|   | 0ef64a6d0b | ||
|   | 1eb6ad58d5 | ||
|   | 49f8cfb0db | ||
|   | 15a8b4c6e5 | ||
|   | 97d68d7b31 | ||
|   | 4dde54e344 | ||
|   | 3304cc106e | ||
|   | dabda21eb7 | ||
|   | 0a64f638c6 | ||
|   | 3cbdfcb43d | ||
|   | 5734221c8f | ||
|   | b6e33e93de | ||
|   | 77b441f14c | ||
|   | 297019c22c | ||
|   | f5f2215b47 | ||
|   | 904114740b | ||
|   | d2d3f7810e | ||
|   | 2b07b3a873 | ||
|   | d17280b341 | ||
|   | f523d3f3bc | ||
|   | f6e4a1770e | ||
|   | 31006507c0 | ||
|   | 9ca6a6bf06 | ||
|   | afdacf14b7 | ||
|   | 5da18ba535 | ||
|   | e6cc937ac2 | ||
|   | 87091a2e03 | ||
|   | d23bc1e02a | ||
|   | 86fcd9208e | ||
|   | f2b97a889c | ||
|   | 97f91102fe | ||
|   | 07b04578c8 | ||
|   | 31f3c1996b | ||
|   | f4116e7300 | ||
|   | 5e5239c16e | ||
|   | 3adfcd1d13 | ||
|   | 3eb43a5413 | ||
|   | 80f41e2ac1 | ||
|   | 9e0b0b4210 | ||
|   | f3380d3184 | ||
|   | 54bc91ea2b | ||
|   | 59d67d3140 | ||
|   | 7b4c307c46 | ||
|   | 92484be87f | ||
|   | 7bb25917f8 | ||
|   | c5ff6df7e6 | ||
|   | e2b2982f95 | ||
|   | a6e307010f | ||
|   | c636e35467 | ||
|   | 3d26bd0532 | ||
|   | 16130e46dd | ||
|   | 9f703085ba | ||
|   | 0af09f13cf | ||
|   | cd8619113a | ||
|   | 4bf6d9f80b | ||
|   | a559b2c20c | ||
|   | 72411abfcd | ||
|   | 491c3f1dc0 | ||
|   | d2ffc4df6c | 
| @@ -7,27 +7,51 @@ maintainer: | |||||||
|   repository_url: https://github.com/syuilo/misskey # Repository URL |   repository_url: https://github.com/syuilo/misskey # Repository URL | ||||||
|   feedback_url: https://github.com/syuilo/misskey/issues # Feedback URL (e.g. github issue) |   feedback_url: https://github.com/syuilo/misskey/issues # Feedback URL (e.g. github issue) | ||||||
|  |  | ||||||
| # URL and Port settings overview |  | ||||||
| # e.g., If you want to realize following structure: |  | ||||||
| # |  | ||||||
| #               +--- https://example.com:123 ----------+ |  | ||||||
| # +------+      |+-------------+      +---------------+| |  | ||||||
| # | User | ---> || Proxy (123) | ---> | Misskey (456) || |  | ||||||
| # +------+      |+-------------+      +---------------+| |  | ||||||
| #               +--------------------------------------+ |  | ||||||
| # |  | ||||||
| # You need to set 'https://example.com:123' to 'url' prop and |  | ||||||
| # You need to set 456 to 'port' prop. |  | ||||||
| # |  | ||||||
| # In other words, the 'url' prop should be the final accessible URL seen by a user. |  | ||||||
| # 'port' prop is a port that the Misskey server should actually listen |  | ||||||
| # on and it is not necessarily the port that a user accesses. |  | ||||||
|  |  | ||||||
| url: http://localhost/ | # Final accessible URL seen by a user. | ||||||
|  | url: https://example.tld/ | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ### Port and TLS settings ###################################### | ||||||
|  | # | ||||||
|  | # Misskey supports two deployment options for public. | ||||||
|  | # | ||||||
|  |  | ||||||
|  | # Option 1: With Reverse Proxy | ||||||
|  | # | ||||||
|  | #                 +----- https://example.tld/ ------------+ | ||||||
|  | #   +------+      |+-------------+      +----------------+| | ||||||
|  | #   | User | ---> || Proxy (443) | ---> | Misskey (3000) || | ||||||
|  | #   +------+      |+-------------+      +----------------+| | ||||||
|  | #                 +---------------------------------------+ | ||||||
|  | # | ||||||
|  | #   You need to setup reverse proxy. (eg. Nginx) | ||||||
|  | #   You do not define 'https' section. | ||||||
|  |  | ||||||
|  | # Option 2: Standalone | ||||||
|  | # | ||||||
|  | #                 +- https://example.tld/ -+ | ||||||
|  | #   +------+      |   +---------------+    | | ||||||
|  | #   | User | ---> |   | Misskey (443) |    | | ||||||
|  | #   +------+      |   +---------------+    | | ||||||
|  | #                 +------------------------+ | ||||||
|  | # | ||||||
|  | #   You need to run Misskey as root. | ||||||
|  | #   You need to set Certificate in 'https' section. | ||||||
|  |  | ||||||
|  | # To use option 1, uncomment below line. | ||||||
|  | # port: 3000    # A port that your Misskey server should listen. | ||||||
|  |  | ||||||
|  | # To use option 2, uncomment below lines. | ||||||
|  | # port: 443 | ||||||
|  | # | ||||||
|  | # https: | ||||||
|  | #   # path for certification | ||||||
|  | #   key: /etc/letsencrypt/live/example.tld/privkey.pem | ||||||
|  | #   cert: /etc/letsencrypt/live/example.tld/fullchain.pem | ||||||
|  |  | ||||||
|  | ################################################################ | ||||||
|  |  | ||||||
| # A port that your Misskey server should listen. |  | ||||||
| # This value is not a port to use when accessing with a browser. |  | ||||||
| port: 80 |  | ||||||
|  |  | ||||||
| mongodb: | mongodb: | ||||||
|   host: localhost |   host: localhost | ||||||
| @@ -98,12 +122,6 @@ drive: | |||||||
| # Below settings are optional | # Below settings are optional | ||||||
| # | # | ||||||
|  |  | ||||||
| # TLS |  | ||||||
| # https: |  | ||||||
| #   # path for certification |  | ||||||
| #   key: example-tls-key |  | ||||||
| #   cert: example-tls-cert |  | ||||||
|  |  | ||||||
| # Elasticsearch | # Elasticsearch | ||||||
| # elasticsearch: | # elasticsearch: | ||||||
| #   host: localhost | #   host: localhost | ||||||
| @@ -141,3 +159,10 @@ drive: | |||||||
|  |  | ||||||
| # Summaly proxy | # Summaly proxy | ||||||
| # summalyProxy: "http://example.com" | # summalyProxy: "http://example.com" | ||||||
|  |  | ||||||
|  | # User recommendation | ||||||
|  | user_recommendation: | ||||||
|  |   external: true | ||||||
|  |   engine: http://vinayaka.distsn.org/cgi-bin/vinayaka-user-match-misskey-api.cgi?{{host}}+{{user}}+{{limit}}+{{offset}} | ||||||
|  |   timeout: 300000 | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										13
									
								
								.config/mongo_initdb_example.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								.config/mongo_initdb_example.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | |||||||
|  | var user = { | ||||||
|  | 	user: 'example-misskey-user', | ||||||
|  | 	pwd: 'example-misskey-pass', | ||||||
|  | 	roles: [ | ||||||
|  | 	    { | ||||||
|  | 		    role: 'readWrite', | ||||||
|  | 		    db: 'misskey' | ||||||
|  | 	    } | ||||||
|  | 	] | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | db.createUser(user); | ||||||
|  |  | ||||||
							
								
								
									
										12
									
								
								.dockerignore
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										12
									
								
								.dockerignore
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,12 @@ | |||||||
|  | .autogen | ||||||
|  | .git | ||||||
|  | .github | ||||||
|  | .travis | ||||||
|  | .vscode | ||||||
|  | Dockerfile | ||||||
|  | build/ | ||||||
|  | docker-compose.yml | ||||||
|  | node_modules/ | ||||||
|  | mongo/ | ||||||
|  | redis/ | ||||||
|  | elasticsearch/ | ||||||
							
								
								
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,6 @@ | |||||||
| /.config/* | /.config/* | ||||||
| !/.config/example.yml | !/.config/example.yml | ||||||
|  | !/.config/mongo_initdb_example.js | ||||||
| /.vscode | /.vscode | ||||||
| /node_modules | /node_modules | ||||||
| /build | /build | ||||||
| @@ -12,3 +13,6 @@ npm-debug.log | |||||||
| run.bat | run.bat | ||||||
| api-docs.json | api-docs.json | ||||||
| *.log | *.log | ||||||
|  | /redis | ||||||
|  | /mongo | ||||||
|  | /elasticsearch | ||||||
|   | |||||||
							
								
								
									
										88
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										88
									
								
								CHANGELOG.md
									
									
									
									
									
								
							| @@ -5,6 +5,94 @@ ChangeLog | |||||||
|  |  | ||||||
| This document describes breaking changes only. | This document describes breaking changes only. | ||||||
|  |  | ||||||
|  | 10.0.0 | ||||||
|  | ------ | ||||||
|  |  | ||||||
|  | ストリーミングAPIに破壊的変更があります。運営者がすべきことはありません。 | ||||||
|  |  | ||||||
|  | 変更は以下の通りです | ||||||
|  |  | ||||||
|  | * ストリーミングでやり取りする際の snake_case が全て camelCase に | ||||||
|  | * リバーシのストリームエンドポイント名が reversi → gamesReversi、reversiGame → gamesReversiGame に | ||||||
|  | * ストリーミングの個々のエンドポイントが廃止され、一旦元となるストリームに接続してから、個々のチャンネル(今までのエンドポイント)に接続します。詳細は後述します。 | ||||||
|  | * ストリームから流れてくる、キャプチャした投稿の更新イベントに投稿自体のデータは含まれず、代わりにアクションが設定されるようになります。詳細は後述します。 | ||||||
|  | * ストリームに接続する際に追加で指定していたパラメータ(トークン除く)が、URLにクエリとして含むのではなくチャンネル接続時にパラメータ指定するように | ||||||
|  |  | ||||||
|  | ### 個々のエンドポイントが廃止されることによる新しいストリーミングAPIの利用方法 | ||||||
|  | 具体的には、まず https://example.misskey/streaming にwebsocket接続します。 | ||||||
|  | 次に、例えば「messaging」ストリーム(チャンネルと呼びます)に接続したいときは、ストリームに次のようなデータを送信します: | ||||||
|  | ``` javascript | ||||||
|  | { | ||||||
|  |   type: 'connect', | ||||||
|  |   body: { | ||||||
|  |     channel: 'messaging', | ||||||
|  |     id: 'foobar', | ||||||
|  |     params: { | ||||||
|  |       otherparty: 'xxxxxxxxxxxx' | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | ``` | ||||||
|  | ここで、`id`にはそのチャンネルとやり取りするための任意のIDを設定します。 | ||||||
|  | IDはチャンネルごとではなく「チャンネルの接続ごと」です。なぜなら、同じチャンネルに異なるパラメータで複数接続するケースもあるからです。 | ||||||
|  | `params`はチャンネルに接続する際のパラメータです。チャンネルによって接続時に必要とされるパラメータは異なります。パラメータ不要のチャンネルに接続する際は、このプロパティは省略可能です。 | ||||||
|  |  | ||||||
|  | チャンネルにメッセージを送信するには、次のようなデータを送信します: | ||||||
|  | ``` javascript | ||||||
|  | { | ||||||
|  |   type: 'channel', | ||||||
|  |   body: { | ||||||
|  |     id: 'foobar', | ||||||
|  |     type: 'something', | ||||||
|  |     body: { | ||||||
|  |       some: 'thing' | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | ``` | ||||||
|  | ここで、`id`にはチャンネルに接続するときに指定したIDを設定します。 | ||||||
|  |  | ||||||
|  | 逆に、チャンネルからメッセージが流れてくると、次のようなデータが受信されます: | ||||||
|  | ``` javascript | ||||||
|  | { | ||||||
|  |   type: 'channel', | ||||||
|  |   body: { | ||||||
|  |     id: 'foobar', | ||||||
|  |     type: 'something', | ||||||
|  |     body: { | ||||||
|  |       some: 'thing' | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | ``` | ||||||
|  | ここで、`id`にはチャンネルに接続するときに指定したIDが設定されています。 | ||||||
|  |  | ||||||
|  | ### 投稿のキャプチャに関する変更 | ||||||
|  | 投稿の更新イベントに投稿情報は含まれなくなりました。代わりに、その投稿が「リアクションされた」「アンケートに投票された」「削除された」といったアクション情報が設定されます。 | ||||||
|  |  | ||||||
|  | 具体的には次のようなデータが受信されます: | ||||||
|  | ``` javascript | ||||||
|  | { | ||||||
|  |   type: 'noteUpdated', | ||||||
|  |   body: { | ||||||
|  |     id: 'xxxxxxxxxxx', | ||||||
|  |     type: 'reacted', | ||||||
|  |     body: { | ||||||
|  |       reaction: 'hmm' | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | * reacted ... 投稿にリアクションされた。`reaction`プロパティにリアクションコードが含まれます。 | ||||||
|  | * pollVoted ... アンケートに投票された。`choice`プロパティに選択肢ID、`userId`に投票者IDが含まれます。 | ||||||
|  |  | ||||||
|  | 9.0.0 | ||||||
|  | ----- | ||||||
|  |  | ||||||
|  | Misskey v8.64.0 を使っている方は、9.0.0に際しては特にすべきことはありません。 | ||||||
|  | Misskey v8.64.0 に満たないバージョンをお使いの方は、一旦8.64.0にアップデートして(そして起動して)から9.0.0に再度アップデートしてください。 | ||||||
|  |  | ||||||
| 8.0.0 | 8.0.0 | ||||||
| ----- | ----- | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										28
									
								
								Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								Dockerfile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | |||||||
|  | FROM alpine:latest AS base | ||||||
|  |  | ||||||
|  | ENV NODE_ENV=production | ||||||
|  |  | ||||||
|  | RUN apk add --no-cache nodejs nodejs-npm | ||||||
|  | RUN apk add vips fftw --update-cache --repository https://dl-3.alpinelinux.org/alpine/edge/testing/ | ||||||
|  | WORKDIR /misskey | ||||||
|  | COPY . ./ | ||||||
|  |  | ||||||
|  | FROM base AS builder | ||||||
|  |  | ||||||
|  | RUN apk add --no-cache	gcc g++ python autoconf automake file make nasm | ||||||
|  | RUN apk add vips-dev fftw-dev --update-cache --repository https://dl-3.alpinelinux.org/alpine/edge/testing/ | ||||||
|  | RUN npm install \ | ||||||
|  |     && npm install -g node-gyp \ | ||||||
|  |     && node-gyp configure \ | ||||||
|  |     && node-gyp build \ | ||||||
|  |     && npm run build | ||||||
|  |  | ||||||
|  | FROM base AS runner | ||||||
|  |  | ||||||
|  | COPY --from=builder /misskey/built ./built | ||||||
|  | COPY --from=builder /misskey/node_modules ./node_modules | ||||||
|  |  | ||||||
|  | RUN apk add --no-cache tini | ||||||
|  | ENTRYPOINT ["/sbin/tini", "--"] | ||||||
|  |  | ||||||
|  | CMD ["npm", "start"] | ||||||
							
								
								
									
										14
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								README.md
									
									
									
									
									
								
							| @@ -71,19 +71,21 @@ Please see [Contribution guide](./CONTRIBUTING.md). | |||||||
| ---------------------------------------------------------------- | ---------------------------------------------------------------- | ||||||
| <!-- PATREON_START --> | <!-- PATREON_START --> | ||||||
| <table><tr> | <table><tr> | ||||||
|  | <td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/619786/32cf01444db24e578cd1982c197f6fc6/1?token-time=2145916800&token-hash=CXe9AqlZy9AsYfiWd3OBYVOzvODoN47Litz0Tu4BFpU%3D" alt="Gargron"></td> | ||||||
| <td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/12731202/0995c46cdcb54153ab5f073f5869b70a/1?token-time=2145916800&token-hash=Yd60FK_SWfQO56SeiJpy1tDHOnCV4xdEywQe8gn5_Wo%3D" alt="negao"></td> | <td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/12731202/0995c46cdcb54153ab5f073f5869b70a/1?token-time=2145916800&token-hash=Yd60FK_SWfQO56SeiJpy1tDHOnCV4xdEywQe8gn5_Wo%3D" alt="negao"></td> | ||||||
| <td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/13099460/43cecdbaa63a40d79bf50a96b9910b9d/1?token-time=2145916800&token-hash=d6P5MWHHsCMxUuBAEPAoVc5wLUR19mIhqAq7Ma9h9rI%3D" alt="ne_moni"></td> | <td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/13099460/43cecdbaa63a40d79bf50a96b9910b9d/1?token-time=2145916800&token-hash=d6P5MWHHsCMxUuBAEPAoVc5wLUR19mIhqAq7Ma9h9rI%3D" alt="ne_moni"></td> | ||||||
| <td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/12913507/f7181eacafe8469a93033d85f5969c29/1?token-time=2145916800&token-hash=f03BFb4S2FUx9YEt87TnEmifb4h33OywGBW2akQVtQY%3D" alt="Melilot"></td> | <td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/12913507/f7181eacafe8469a93033d85f5969c29/2?token-time=2145916800&token-hash=mgPdX9TqZxEg4TTPuc477dxhIgYk9246qafjWZEqZ7g%3D" alt="Melilot"></td> | ||||||
| <td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/12999811/5f349fafcce44dd1824a8b1ebbec4564/2?token-time=2145916800&token-hash=rwZ8qvbm_kpA4ib3kc07tVKupXeySpY5ATQFGxfL9v0%3D" alt="Axella"></td> | <td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/12999811/5f349fafcce44dd1824a8b1ebbec4564/2?token-time=2145916800&token-hash=rwZ8qvbm_kpA4ib3kc07tVKupXeySpY5ATQFGxfL9v0%3D" alt="Xeltica"></td> | ||||||
| <td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/3384329/8b713330cb27404ea6e9fac50ff96efe/1?token-time=2145916800&token-hash=0eu4-m1gTWA9PhptVZt6rdKcusqcD7RB87rJT23VVFI%3D" alt="べすれい"></td> | <td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/3384329/8b713330cb27404ea6e9fac50ff96efe/1?token-time=2145916800&token-hash=0eu4-m1gTWA9PhptVZt6rdKcusqcD7RB87rJT23VVFI%3D" alt="べすれい"></td> | ||||||
| <td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/12021162/963128bb8d14476dbd8407943db8f31a/1?token-time=2145916800&token-hash=GgJ_NmUB6_nnRNLVGUWjV-WX91On7BOu59LKncYV9fE%3D" alt="gutfuckllc"></td> | <td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/12021162/963128bb8d14476dbd8407943db8f31a/1?token-time=2145916800&token-hash=GgJ_NmUB6_nnRNLVGUWjV-WX91On7BOu59LKncYV9fE%3D" alt="gutfuckllc"></td> | ||||||
| <td><img src="https://c8.patreon.com/2/100/12718187" alt="Peter G."></td> | <td><img src="https://c8.patreon.com/2/100/12718187" alt="Peter G."></td> | ||||||
| <td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/13039004/509d0c412eb14ae08d6a812a3054f7d6/1?token-time=2145916800&token-hash=zwSu01tOtn5xTUucDZHuPsCxF2HBEMVs9ROJKTlEV_o%3D" alt="nemu"></td> | <td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/13039004/509d0c412eb14ae08d6a812a3054f7d6/1?token-time=2145916800&token-hash=zwSu01tOtn5xTUucDZHuPsCxF2HBEMVs9ROJKTlEV_o%3D" alt="nemu"></td> | ||||||
| </tr><tr> | </tr><tr> | ||||||
| <td><a href="https://www.patreon.com/user?u=12731202">negao</a></td> | <td><a href="https://www.patreon.com/mastodon">Gargron</a></td> | ||||||
|  | <td><a href="https://www.patreon.com/negao">negao</a></td> | ||||||
| <td><a href="https://www.patreon.com/user?u=13099460">ne_moni</a></td> | <td><a href="https://www.patreon.com/user?u=13099460">ne_moni</a></td> | ||||||
| <td><a href="https://www.patreon.com/user?u=12913507">Melilot</a></td> | <td><a href="https://www.patreon.com/user?u=12913507">Melilot</a></td> | ||||||
| <td><a href="https://www.patreon.com/AxellaMC">Axella</a></td> | <td><a href="https://www.patreon.com/AxellaMC">Xeltica</a></td> | ||||||
| <td><a href="https://www.patreon.com/user?u=3384329">べすれい</a></td> | <td><a href="https://www.patreon.com/user?u=3384329">べすれい</a></td> | ||||||
| <td><a href="https://www.patreon.com/gutfuckllc">gutfuckllc</a></td> | <td><a href="https://www.patreon.com/gutfuckllc">gutfuckllc</a></td> | ||||||
| <td><a href="https://www.patreon.com/user?u=12718187">Peter G.</a></td> | <td><a href="https://www.patreon.com/user?u=12718187">Peter G.</a></td> | ||||||
| @@ -91,19 +93,17 @@ Please see [Contribution guide](./CONTRIBUTING.md). | |||||||
| </tr></table> | </tr></table> | ||||||
| <table><tr> | <table><tr> | ||||||
| <td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/5881381/6235ca5d3fb04c8e95ef5b4ff2abcc18/2?token-time=2145916800&token-hash=zElv7ZcPL3viGsXbNG_KWiKrbV0vvw1gk0panx8DJoo%3D" alt="Naoki Kosaka"></td> | <td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/5881381/6235ca5d3fb04c8e95ef5b4ff2abcc18/2?token-time=2145916800&token-hash=zElv7ZcPL3viGsXbNG_KWiKrbV0vvw1gk0panx8DJoo%3D" alt="Naoki Kosaka"></td> | ||||||
| <td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/12931605/ead494101f364dffa90efe49e36fb494/1?token-time=2145916800&token-hash=NzSFPjIlodXyv41rwK61aZWVZWfI4surJaNj8vWKvqM%3D" alt="Reiju"></td> |  | ||||||
| <td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/13034746/c711c7f58e204ecfbc2fd646bc8a4eee/1?token-time=2145916800&token-hash=UERBN4OyP7Nh5XwwdDg0N0IE5cD6_qUQMO81Z5Wizso%3D" alt="Hiratake"></td> | <td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/13034746/c711c7f58e204ecfbc2fd646bc8a4eee/1?token-time=2145916800&token-hash=UERBN4OyP7Nh5XwwdDg0N0IE5cD6_qUQMO81Z5Wizso%3D" alt="Hiratake"></td> | ||||||
| <td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/4503830/ccf2cc867ea64de0b524bb2e24b9a1cb/1?token-time=2145916800&token-hash=S1zP0QyLU52Dqq6dtc9qNYyWfW86XrYHiR4NMbeOrnA%3D" alt="dansup"></td> | <td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/4503830/ccf2cc867ea64de0b524bb2e24b9a1cb/1?token-time=2145916800&token-hash=S1zP0QyLU52Dqq6dtc9qNYyWfW86XrYHiR4NMbeOrnA%3D" alt="dansup"></td> | ||||||
| <td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/12531784/93a45137841849329ba692da92ac7c60/1?token-time=2145916800&token-hash=tMosUojzUYJCH_3t--tvYA-SMCyrS__hzSndyaRSnbo%3D" alt="Takashi Shibuya"></td> | <td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/12531784/93a45137841849329ba692da92ac7c60/1?token-time=2145916800&token-hash=tMosUojzUYJCH_3t--tvYA-SMCyrS__hzSndyaRSnbo%3D" alt="Takashi Shibuya"></td> | ||||||
| </tr><tr> | </tr><tr> | ||||||
| <td><a href="https://www.patreon.com/user?u=5881381">Naoki Kosaka</a></td> | <td><a href="https://www.patreon.com/user?u=5881381">Naoki Kosaka</a></td> | ||||||
| <td><a href="https://www.patreon.com/user?u=12931605">Reiju</a></td> |  | ||||||
| <td><a href="https://www.patreon.com/hiratake">Hiratake</a></td> | <td><a href="https://www.patreon.com/hiratake">Hiratake</a></td> | ||||||
| <td><a href="https://www.patreon.com/dansup">dansup</a></td> | <td><a href="https://www.patreon.com/dansup">dansup</a></td> | ||||||
| <td><a href="https://www.patreon.com/user?u=12531784">Takashi Shibuya</a></td> | <td><a href="https://www.patreon.com/user?u=12531784">Takashi Shibuya</a></td> | ||||||
| </tr></table> | </tr></table> | ||||||
|  |  | ||||||
| **Last updated:** Sun, 02 Sep 2018 05:30:06 UTC | **Last updated:** Tue, 02 Oct 2018 09:25:07 UTC | ||||||
| <!-- PATREON_END --> | <!-- PATREON_END --> | ||||||
|  |  | ||||||
| :four_leaf_clover: Copyright | :four_leaf_clover: Copyright | ||||||
|   | |||||||
							
								
								
									
										52
									
								
								docker-compose.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								docker-compose.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,52 @@ | |||||||
|  | version: "3" | ||||||
|  |  | ||||||
|  | services: | ||||||
|  |   web: | ||||||
|  |     build: . | ||||||
|  |     restart: always | ||||||
|  |     links: | ||||||
|  |       - mongo | ||||||
|  |       - redis | ||||||
|  | #      - es | ||||||
|  |     ports: | ||||||
|  |       - "127.0.0.1:3000:3000" | ||||||
|  |     networks: | ||||||
|  |       - internal_network | ||||||
|  |       - external_network | ||||||
|  |  | ||||||
|  |   redis: | ||||||
|  |     restart: always | ||||||
|  |     image: redis:4.0-alpine | ||||||
|  |     networks: | ||||||
|  |       - internal_network | ||||||
|  | ### Uncomment to enable Redis persistance | ||||||
|  | #    volumes: | ||||||
|  | #      - ./redis:/data | ||||||
|  |  | ||||||
|  |   mongo: | ||||||
|  |     restart: always | ||||||
|  |     image: mongo:4.1-bionic | ||||||
|  |     networks: | ||||||
|  |       - internal_network | ||||||
|  |     environment: | ||||||
|  |       MONGO_INITDB_DATABASE: "misskey" | ||||||
|  |     volumes: | ||||||
|  |       - ./.config/mongo_initdb.js:/docker-entrypoint-initdb.d/mongo_initdb.js:ro | ||||||
|  | ### Uncomment to enable MongoDB persistance | ||||||
|  | #      - ./mongo:/data | ||||||
|  |  | ||||||
|  | #  es: | ||||||
|  | #    restart: always | ||||||
|  | #    image: docker.elastic.co/elasticsearch/elasticsearch-oss:6.4.2 | ||||||
|  | #    environment: | ||||||
|  | #      - "ES_JAVA_OPTS=-Xms512m -Xmx512m" | ||||||
|  | #    networks: | ||||||
|  | #      - internal_network | ||||||
|  | #### Uncomment to enable ES persistence | ||||||
|  | ##    volumes: | ||||||
|  | ##      - ./elasticsearch:/usr/share/elasticsearch/data | ||||||
|  |  | ||||||
|  | networks: | ||||||
|  |   internal_network: | ||||||
|  |     internal: true | ||||||
|  |   external_network: | ||||||
							
								
								
									
										47
									
								
								docs/docker.en.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								docs/docker.en.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,47 @@ | |||||||
|  | Docker Guide | ||||||
|  | ================================================================ | ||||||
|  |  | ||||||
|  | This guide describes how to install and setup Misskey with Docker. | ||||||
|  |  | ||||||
|  | [Japanese version also available - 日本語版もあります](./docker.ja.md) | ||||||
|  |  | ||||||
|  | ---------------------------------------------------------------- | ||||||
|  |  | ||||||
|  | *1.* Make configuration files | ||||||
|  | ---------------------------------------------------------------- | ||||||
|  | 1. `cp .config/example.yml .config/default.yml` Copy the `.config/example.yml` and rename it to `default.yml`. | ||||||
|  | 2. `cp .config/mongo_initdb_example.js .config/mongo_initdb.js` Copy the `.config/mongo_initdb_example.js` and rename it to `mongo_initdb.js`. | ||||||
|  | 2. Edit `default.yml` and `mongo_initdb.js`. | ||||||
|  |  | ||||||
|  | *2.* Configure Docker | ||||||
|  | ---------------------------------------------------------------- | ||||||
|  | Edit `docker-compose.yml`. | ||||||
|  |  | ||||||
|  | *3.* Build Misskey | ||||||
|  | ---------------------------------------------------------------- | ||||||
|  | Build misskey with the following: | ||||||
|  |  | ||||||
|  | `docker-compose build` | ||||||
|  |  | ||||||
|  | *4.* That is it. | ||||||
|  | ---------------------------------------------------------------- | ||||||
|  | Well done! Now, you have an environment that run to Misskey. | ||||||
|  |  | ||||||
|  | ### Launch normally | ||||||
|  | Just `docker-compose up -d`. GLHF! | ||||||
|  |  | ||||||
|  | ### Way to Update to latest version of your Misskey | ||||||
|  | 1. `git fetch` | ||||||
|  | 2. `git stash` | ||||||
|  | 3. `git checkout $(git tag -l | grep -v 'rc[0-9]*$' | sort -V | tail -n 1)` | ||||||
|  | 4. `git stash pop` | ||||||
|  | 5. `docker-compose build` | ||||||
|  | 6. Check [ChangeLog](../CHANGELOG.md) for migration information | ||||||
|  | 7. `docker-compose stop && docker-compose up -d` | ||||||
|  |  | ||||||
|  | ### Way to execute cli command: | ||||||
|  | `docker-compose run --rm web node cli/mark-admin @example` | ||||||
|  |  | ||||||
|  | ---------------------------------------------------------------- | ||||||
|  |  | ||||||
|  | If you have any questions or troubles, feel free to contact us! | ||||||
							
								
								
									
										48
									
								
								docs/docker.ja.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								docs/docker.ja.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,48 @@ | |||||||
|  | Dockerを使ったMisskey構築方法 | ||||||
|  | ================================================================ | ||||||
|  |  | ||||||
|  | このガイドはDockerを使ったMisskeyセットアップ方法について解説します。 | ||||||
|  |  | ||||||
|  | [英語版もあります - English version also available](./docker.en.md) | ||||||
|  |  | ||||||
|  | ---------------------------------------------------------------- | ||||||
|  |  | ||||||
|  | *1.* 設定ファイルを作成する | ||||||
|  | ---------------------------------------------------------------- | ||||||
|  | 1. `cp .config/example.yml .config/default.yml` `.config/example.yml`をコピーし名前を`default.yml`にする | ||||||
|  | 2. `cp .config/mongo_initdb_example.js .config/mongo_initdb.js` `.config/mongo_initdb_example.js`をコピーし名前を`mongo_initdb.js`にする | ||||||
|  | 3. `default.yml`と`mongo_initdb.js`を編集する | ||||||
|  |  | ||||||
|  | *2.* Dockerの設定 | ||||||
|  | ---------------------------------------------------------------- | ||||||
|  | `docker-compose.yml`を編集してください。 | ||||||
|  |  | ||||||
|  | *3.* Misskeyのビルド | ||||||
|  | ---------------------------------------------------------------- | ||||||
|  | 次のコマンドでMisskeyをビルドしてください: | ||||||
|  |  | ||||||
|  | `docker-compose build` | ||||||
|  |  | ||||||
|  | *4.* 以上です! | ||||||
|  | ---------------------------------------------------------------- | ||||||
|  | お疲れ様でした。これでMisskeyを動かす準備は整いました。 | ||||||
|  |  | ||||||
|  | ### 通常起動 | ||||||
|  | `docker-compose up -d`するだけです。GLHF! | ||||||
|  |  | ||||||
|  | ### Misskeyを最新バージョンにアップデートする方法: | ||||||
|  | 1. `git fetch` | ||||||
|  | 2. `git stash` | ||||||
|  | 3. `git checkout $(git tag -l | grep -v 'rc[0-9]*$' | sort -V | tail -n 1)` | ||||||
|  | 4. `git stash pop` | ||||||
|  | 5. `docker-compose build` | ||||||
|  | 6. [ChangeLog](../CHANGELOG.md)でマイグレーション情報を確認する | ||||||
|  | 7. `docker-compose stop && docker-compose up -d` | ||||||
|  |  | ||||||
|  | ### cliコマンドを実行する方法: | ||||||
|  |  | ||||||
|  | `docker-compose run --rm web node cli/mark-admin @example` | ||||||
|  |  | ||||||
|  | ---------------------------------------------------------------- | ||||||
|  |  | ||||||
|  | なにかお困りのことがありましたらお気軽にご連絡ください。 | ||||||
| @@ -2,7 +2,6 @@ | |||||||
|  * Gulp tasks |  * Gulp tasks | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| import * as fs from 'fs'; |  | ||||||
| import * as gulp from 'gulp'; | import * as gulp from 'gulp'; | ||||||
| import * as gutil from 'gulp-util'; | import * as gutil from 'gulp-util'; | ||||||
| import * as ts from 'gulp-typescript'; | import * as ts from 'gulp-typescript'; | ||||||
| @@ -166,9 +165,7 @@ gulp.task('build:client:pug', [ | |||||||
| 			.pipe(pug({ | 			.pipe(pug({ | ||||||
| 				locals: { | 				locals: { | ||||||
| 					themeColor: constants.themeColor, | 					themeColor: constants.themeColor, | ||||||
| 					facss: fa.dom.css(), | 					facss: fa.dom.css() | ||||||
| 					//hljscss: fs.readFileSync('./node_modules/highlight.js/styles/default.css', 'utf8') |  | ||||||
| 					hljscss: fs.readFileSync('./src/client/assets/code-highlight.css', 'utf8') |  | ||||||
| 				} | 				} | ||||||
| 			})) | 			})) | ||||||
| 			.pipe(htmlmin({ | 			.pipe(htmlmin({ | ||||||
|   | |||||||
| @@ -264,6 +264,41 @@ common/views/components/connect-failed.troubleshooter.vue: | |||||||
| common/views/components/media-banner.vue: | common/views/components/media-banner.vue: | ||||||
|   sensitive: "閲覧注意" |   sensitive: "閲覧注意" | ||||||
|   click-to-show: "クリックして表示" |   click-to-show: "クリックして表示" | ||||||
|  | common/views/components/theme.vue: | ||||||
|  |   light-theme: "非ダークモード時に使用するテーマ" | ||||||
|  |   dark-theme: "ダークモード時に使用するテーマ" | ||||||
|  |   light-themes: "明るいテーマ" | ||||||
|  |   dark-themes: "暗いテーマ" | ||||||
|  |   install-a-theme: "テーマのインストール" | ||||||
|  |   theme-code: "テーマコード" | ||||||
|  |   install: "インストール" | ||||||
|  |   installed: "「{}」をインストールしました" | ||||||
|  |   create-a-theme: "テーマの作成" | ||||||
|  |   save-created-theme: "テーマを保存" | ||||||
|  |   primary-color: "プライマリ カラー" | ||||||
|  |   secondary-color: "セカンダリ カラー" | ||||||
|  |   text-color: "文字色" | ||||||
|  |   base-theme: "ベーステーマ" | ||||||
|  |   base-theme-light: "Light" | ||||||
|  |   base-theme-dark: "Dark" | ||||||
|  |   theme-name: "テーマ名" | ||||||
|  |   preview-created-theme: "プレビュー" | ||||||
|  |   invalid-theme: "テーマが正しくありません。" | ||||||
|  |   already-installed: "既にそのテーマはインストールされています。" | ||||||
|  |   saved: "保存しました" | ||||||
|  |   manage-themes: "テーマの管理" | ||||||
|  |   builtin-themes: "標準テーマ" | ||||||
|  |   my-themes: "マイテーマ" | ||||||
|  |   installed-themes: "インストールされたテーマ" | ||||||
|  |   select-theme: "テーマを選択してください" | ||||||
|  |   uninstall: "アンインストール" | ||||||
|  |   uninstalled: "「{}」をアンインストールしました" | ||||||
|  |   author: "作者" | ||||||
|  |   desc: "説明" | ||||||
|  |   export: "エクスポート" | ||||||
|  |   import: "インポート" | ||||||
|  |   import-by-code: "またはコードをペースト" | ||||||
|  |   theme-name-required: "テーマ名は必須です。" | ||||||
| common/views/components/cw-button.vue: | common/views/components/cw-button.vue: | ||||||
|   hide: "隠す" |   hide: "隠す" | ||||||
|   show: "もっと見る" |   show: "もっと見る" | ||||||
| @@ -301,6 +336,7 @@ common/views/components/note-menu.vue: | |||||||
|   copy-link: "リンクをコピー" |   copy-link: "リンクをコピー" | ||||||
|   favorite: "お気に入り" |   favorite: "お気に入り" | ||||||
|   pin: "ピン留め" |   pin: "ピン留め" | ||||||
|  |   unpin: "ピン留め解除" | ||||||
|   delete: "削除" |   delete: "削除" | ||||||
|   delete-confirm: "この投稿を削除しますか?" |   delete-confirm: "この投稿を削除しますか?" | ||||||
|   remote: "投稿元で見る" |   remote: "投稿元で見る" | ||||||
| @@ -439,6 +475,7 @@ common/views/pages/follow.vue: | |||||||
|   following: "フォロー中" |   following: "フォロー中" | ||||||
|   follow: "フォロー" |   follow: "フォロー" | ||||||
|   request-pending: "フォロー許可待ち" |   request-pending: "フォロー許可待ち" | ||||||
|  |   follow-processing: "フォロー処理中" | ||||||
|   follow-request: "フォロー申請" |   follow-request: "フォロー申請" | ||||||
| desktop: | desktop: | ||||||
|   banner-crop-title: "バナーとして表示する部分を選択" |   banner-crop-title: "バナーとして表示する部分を選択" | ||||||
| @@ -477,13 +514,13 @@ desktop/views/components/charts.vue: | |||||||
|     notes: "投稿の増減 (統合)" |     notes: "投稿の増減 (統合)" | ||||||
|     local-notes: "投稿の増減 (ローカル)" |     local-notes: "投稿の増減 (ローカル)" | ||||||
|     remote-notes: "投稿の増減 (リモート)" |     remote-notes: "投稿の増減 (リモート)" | ||||||
|     notes-total: "投稿の累計" |     notes-total: "投稿の積算" | ||||||
|     users: "ユーザーの増減" |     users: "ユーザーの増減" | ||||||
|     users-total: "ユーザーの累計" |     users-total: "ユーザーの積算" | ||||||
|     drive: "ドライブ使用量の増減" |     drive: "ドライブ使用量の増減" | ||||||
|     drive-total: "ドライブ使用量の累計" |     drive-total: "ドライブ使用量の積算" | ||||||
|     drive-files: "ドライブのファイル数の増減" |     drive-files: "ドライブのファイル数の増減" | ||||||
|     drive-files-total: "ドライブのファイル数の累計" |     drive-files-total: "ドライブのファイル数の積算" | ||||||
|     network-requests: "リクエスト" |     network-requests: "リクエスト" | ||||||
|     network-time: "応答時間" |     network-time: "応答時間" | ||||||
|     network-usage: "通信量" |     network-usage: "通信量" | ||||||
| @@ -565,6 +602,7 @@ desktop/views/components/follow-button.vue: | |||||||
|   following: "フォロー中" |   following: "フォロー中" | ||||||
|   follow: "フォロー" |   follow: "フォロー" | ||||||
|   request-pending: "フォロー許可待ち" |   request-pending: "フォロー許可待ち" | ||||||
|  |   follow-processing: "フォロー処理中" | ||||||
|   follow-request: "フォロー申請" |   follow-request: "フォロー申請" | ||||||
| desktop/views/components/followers-window.vue: | desktop/views/components/followers-window.vue: | ||||||
|   followers: "{} のフォロワー" |   followers: "{} のフォロワー" | ||||||
| @@ -675,6 +713,7 @@ desktop/views/components/settings.vue: | |||||||
|   2fa: "二段階認証" |   2fa: "二段階認証" | ||||||
|   other: "その他" |   other: "その他" | ||||||
|   license: "ライセンス" |   license: "ライセンス" | ||||||
|  |   theme: "テーマ" | ||||||
|   behaviour: "動作" |   behaviour: "動作" | ||||||
|   fetch-on-scroll: "スクロールで自動読み込み" |   fetch-on-scroll: "スクロールで自動読み込み" | ||||||
|   fetch-on-scroll-desc: "ページを下までスクロールしたときに自動で追加のコンテンツを読み込みます。" |   fetch-on-scroll-desc: "ページを下までスクロールしたときに自動で追加のコンテンツを読み込みます。" | ||||||
| @@ -691,9 +730,10 @@ desktop/views/components/settings.vue: | |||||||
|   choose-wallpaper: "壁紙を選択" |   choose-wallpaper: "壁紙を選択" | ||||||
|   delete-wallpaper: "壁紙を削除" |   delete-wallpaper: "壁紙を削除" | ||||||
|   dark-mode: "ダークモード" |   dark-mode: "ダークモード" | ||||||
|  |   use-shadow: "UIに影を使用" | ||||||
|  |   rounded-corners: "UIの角を丸める" | ||||||
|   circle-icons: "円形のアイコンを使用" |   circle-icons: "円形のアイコンを使用" | ||||||
|   contrasted-acct: "ユーザー名にコントラストを付ける" |   contrasted-acct: "ユーザー名にコントラストを付ける" | ||||||
|   gradient-window-header: "ウィンドウのタイトルバーにグラデーションを使用" |  | ||||||
|   post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" |   post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" | ||||||
|   suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する" |   suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する" | ||||||
|   show-clock-on-header: "右上に時計を表示する" |   show-clock-on-header: "右上に時計を表示する" | ||||||
| @@ -702,7 +742,6 @@ desktop/views/components/settings.vue: | |||||||
|   show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する" |   show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する" | ||||||
|   show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する" |   show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する" | ||||||
|   show-maps: "マップの自動展開" |   show-maps: "マップの自動展開" | ||||||
|   show-maps-desc: "位置情報が添付された投稿のマップを自動的に展開します。" |  | ||||||
|   sound: "サウンド" |   sound: "サウンド" | ||||||
|   enable-sounds: "サウンドを有効にする" |   enable-sounds: "サウンドを有効にする" | ||||||
|   enable-sounds-desc: "投稿やメッセージを送受信したときなどにサウンドを再生します。この設定はブラウザに記憶されます。" |   enable-sounds-desc: "投稿やメッセージを送受信したときなどにサウンドを再生します。この設定はブラウザに記憶されます。" | ||||||
| @@ -1044,6 +1083,7 @@ mobile/views/components/follow-button.vue: | |||||||
|   following: "フォロー中" |   following: "フォロー中" | ||||||
|   follow: "フォロー" |   follow: "フォロー" | ||||||
|   request-pending: "フォロー許可待ち" |   request-pending: "フォロー許可待ち" | ||||||
|  |   follow-processing: "フォロー処理中" | ||||||
|   follow-request: "フォロー申請" |   follow-request: "フォロー申請" | ||||||
| mobile/views/components/friends-maker.vue: | mobile/views/components/friends-maker.vue: | ||||||
|   title: "気になるユーザーをフォロー" |   title: "気になるユーザーをフォロー" | ||||||
| @@ -1219,6 +1259,7 @@ mobile/views/pages/settings.vue: | |||||||
|   notification-position: "通知の表示" |   notification-position: "通知の表示" | ||||||
|   notification-position-bottom: "下" |   notification-position-bottom: "下" | ||||||
|   notification-position-top: "上" |   notification-position-top: "上" | ||||||
|  |   theme: "テーマ" | ||||||
|   behavior: "動作" |   behavior: "動作" | ||||||
|   fetch-on-scroll: "スクロールで自動読み込み" |   fetch-on-scroll: "スクロールで自動読み込み" | ||||||
|   note-visibility: "投稿の公開範囲" |   note-visibility: "投稿の公開範囲" | ||||||
|   | |||||||
| @@ -264,6 +264,41 @@ common/views/components/connect-failed.troubleshooter.vue: | |||||||
| common/views/components/media-banner.vue: | common/views/components/media-banner.vue: | ||||||
|   sensitive: "閲覧注意" |   sensitive: "閲覧注意" | ||||||
|   click-to-show: "クリックして表示" |   click-to-show: "クリックして表示" | ||||||
|  | common/views/components/theme.vue: | ||||||
|  |   light-theme: "非ダークモード時に使用するテーマ" | ||||||
|  |   dark-theme: "ダークモード時に使用するテーマ" | ||||||
|  |   light-themes: "明るいテーマ" | ||||||
|  |   dark-themes: "暗いテーマ" | ||||||
|  |   install-a-theme: "テーマのインストール" | ||||||
|  |   theme-code: "テーマコード" | ||||||
|  |   install: "インストール" | ||||||
|  |   installed: "「{}」をインストールしました" | ||||||
|  |   create-a-theme: "テーマの作成" | ||||||
|  |   save-created-theme: "テーマを保存" | ||||||
|  |   primary-color: "プライマリ カラー" | ||||||
|  |   secondary-color: "セカンダリ カラー" | ||||||
|  |   text-color: "文字色" | ||||||
|  |   base-theme: "ベーステーマ" | ||||||
|  |   base-theme-light: "Light" | ||||||
|  |   base-theme-dark: "Dark" | ||||||
|  |   theme-name: "テーマ名" | ||||||
|  |   preview-created-theme: "プレビュー" | ||||||
|  |   invalid-theme: "テーマが正しくありません。" | ||||||
|  |   already-installed: "既にそのテーマはインストールされています。" | ||||||
|  |   saved: "保存しました" | ||||||
|  |   manage-themes: "テーマの管理" | ||||||
|  |   builtin-themes: "標準テーマ" | ||||||
|  |   my-themes: "マイテーマ" | ||||||
|  |   installed-themes: "インストールされたテーマ" | ||||||
|  |   select-theme: "テーマを選択してください" | ||||||
|  |   uninstall: "アンインストール" | ||||||
|  |   uninstalled: "「{}」をアンインストールしました" | ||||||
|  |   author: "作者" | ||||||
|  |   desc: "説明" | ||||||
|  |   export: "エクスポート" | ||||||
|  |   import: "インポート" | ||||||
|  |   import-by-code: "またはコードをペースト" | ||||||
|  |   theme-name-required: "テーマ名は必須です。" | ||||||
| common/views/components/cw-button.vue: | common/views/components/cw-button.vue: | ||||||
|   hide: "隠す" |   hide: "隠す" | ||||||
|   show: "もっと見る" |   show: "もっと見る" | ||||||
| @@ -301,6 +336,7 @@ common/views/components/note-menu.vue: | |||||||
|   copy-link: "リンクをコピー" |   copy-link: "リンクをコピー" | ||||||
|   favorite: "Diese Anmerkung favorisieren" |   favorite: "Diese Anmerkung favorisieren" | ||||||
|   pin: "An die Profilseite pinnen" |   pin: "An die Profilseite pinnen" | ||||||
|  |   unpin: "ピン留め解除" | ||||||
|   delete: "Löschen" |   delete: "Löschen" | ||||||
|   delete-confirm: "Diesen Post löschen?" |   delete-confirm: "Diesen Post löschen?" | ||||||
|   remote: "Auf Quelle anzeigen" |   remote: "Auf Quelle anzeigen" | ||||||
| @@ -439,6 +475,7 @@ common/views/pages/follow.vue: | |||||||
|   following: "フォロー中" |   following: "フォロー中" | ||||||
|   follow: "フォロー" |   follow: "フォロー" | ||||||
|   request-pending: "フォロー許可待ち" |   request-pending: "フォロー許可待ち" | ||||||
|  |   follow-processing: "フォロー処理中" | ||||||
|   follow-request: "フォロー申請" |   follow-request: "フォロー申請" | ||||||
| desktop: | desktop: | ||||||
|   banner-crop-title: "バナーとして表示する部分を選択" |   banner-crop-title: "バナーとして表示する部分を選択" | ||||||
| @@ -477,13 +514,13 @@ desktop/views/components/charts.vue: | |||||||
|     notes: "投稿の増減 (統合)" |     notes: "投稿の増減 (統合)" | ||||||
|     local-notes: "投稿の増減 (ローカル)" |     local-notes: "投稿の増減 (ローカル)" | ||||||
|     remote-notes: "投稿の増減 (リモート)" |     remote-notes: "投稿の増減 (リモート)" | ||||||
|     notes-total: "投稿の累計" |     notes-total: "投稿の積算" | ||||||
|     users: "ユーザーの増減" |     users: "ユーザーの増減" | ||||||
|     users-total: "ユーザーの累計" |     users-total: "ユーザーの積算" | ||||||
|     drive: "ドライブ使用量の増減" |     drive: "ドライブ使用量の増減" | ||||||
|     drive-total: "ドライブ使用量の累計" |     drive-total: "ドライブ使用量の積算" | ||||||
|     drive-files: "ドライブのファイル数の増減" |     drive-files: "ドライブのファイル数の増減" | ||||||
|     drive-files-total: "ドライブのファイル数の累計" |     drive-files-total: "ドライブのファイル数の積算" | ||||||
|     network-requests: "リクエスト" |     network-requests: "リクエスト" | ||||||
|     network-time: "応答時間" |     network-time: "応答時間" | ||||||
|     network-usage: "通信量" |     network-usage: "通信量" | ||||||
| @@ -565,6 +602,7 @@ desktop/views/components/follow-button.vue: | |||||||
|   following: "Folge ich" |   following: "Folge ich" | ||||||
|   follow: "Folgen" |   follow: "Folgen" | ||||||
|   request-pending: "Ausstehend" |   request-pending: "Ausstehend" | ||||||
|  |   follow-processing: "フォロー処理中" | ||||||
|   follow-request: "Follower-Anfragen" |   follow-request: "Follower-Anfragen" | ||||||
| desktop/views/components/followers-window.vue: | desktop/views/components/followers-window.vue: | ||||||
|   followers: "{} のフォロワー" |   followers: "{} のフォロワー" | ||||||
| @@ -675,6 +713,7 @@ desktop/views/components/settings.vue: | |||||||
|   2fa: "Zwei-Faktor-Authentifizierung" |   2fa: "Zwei-Faktor-Authentifizierung" | ||||||
|   other: "Anderes" |   other: "Anderes" | ||||||
|   license: "Lizenz" |   license: "Lizenz" | ||||||
|  |   theme: "テーマ" | ||||||
|   behaviour: "Verhalten" |   behaviour: "Verhalten" | ||||||
|   fetch-on-scroll: "Aktualisieren beim scrollen" |   fetch-on-scroll: "Aktualisieren beim scrollen" | ||||||
|   fetch-on-scroll-desc: "Wenn du runterscrollst empfängt die Seite automatisch zusätzliche Inhalte." |   fetch-on-scroll-desc: "Wenn du runterscrollst empfängt die Seite automatisch zusätzliche Inhalte." | ||||||
| @@ -691,9 +730,10 @@ desktop/views/components/settings.vue: | |||||||
|   choose-wallpaper: "壁紙を選択" |   choose-wallpaper: "壁紙を選択" | ||||||
|   delete-wallpaper: "壁紙を削除" |   delete-wallpaper: "壁紙を削除" | ||||||
|   dark-mode: "Nacht Modus" |   dark-mode: "Nacht Modus" | ||||||
|  |   use-shadow: "UIに影を使用" | ||||||
|  |   rounded-corners: "UIの角を丸める" | ||||||
|   circle-icons: "Kreisförmige Icons" |   circle-icons: "Kreisförmige Icons" | ||||||
|   contrasted-acct: "ユーザー名にコントラストを付ける" |   contrasted-acct: "ユーザー名にコントラストを付ける" | ||||||
|   gradient-window-header: "Übergang in Fensterköpfen" |  | ||||||
|   post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" |   post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" | ||||||
|   suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する" |   suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する" | ||||||
|   show-clock-on-header: "右上に時計を表示する" |   show-clock-on-header: "右上に時計を表示する" | ||||||
| @@ -702,7 +742,6 @@ desktop/views/components/settings.vue: | |||||||
|   show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する" |   show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する" | ||||||
|   show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する" |   show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する" | ||||||
|   show-maps: "Karte anzeigen" |   show-maps: "Karte anzeigen" | ||||||
|   show-maps-desc: "Zeige den Standort zu diesem Beitrag automatisch an." |  | ||||||
|   sound: "Ton" |   sound: "Ton" | ||||||
|   enable-sounds: "Ton aktivieren" |   enable-sounds: "Ton aktivieren" | ||||||
|   enable-sounds-desc: "Spiel einen Ton ab beim Erhalten eines Beitrags bzw. einer Nachricht. Diese Einstellung wird im Browser gespeichert." |   enable-sounds-desc: "Spiel einen Ton ab beim Erhalten eines Beitrags bzw. einer Nachricht. Diese Einstellung wird im Browser gespeichert." | ||||||
| @@ -1044,6 +1083,7 @@ mobile/views/components/follow-button.vue: | |||||||
|   following: "フォロー中" |   following: "フォロー中" | ||||||
|   follow: "フォロー" |   follow: "フォロー" | ||||||
|   request-pending: "フォロー許可待ち" |   request-pending: "フォロー許可待ち" | ||||||
|  |   follow-processing: "フォロー処理中" | ||||||
|   follow-request: "フォロー申請" |   follow-request: "フォロー申請" | ||||||
| mobile/views/components/friends-maker.vue: | mobile/views/components/friends-maker.vue: | ||||||
|   title: "気になるユーザーをフォロー" |   title: "気になるユーザーをフォロー" | ||||||
| @@ -1219,6 +1259,7 @@ mobile/views/pages/settings.vue: | |||||||
|   notification-position: "通知の表示" |   notification-position: "通知の表示" | ||||||
|   notification-position-bottom: "下" |   notification-position-bottom: "下" | ||||||
|   notification-position-top: "上" |   notification-position-top: "上" | ||||||
|  |   theme: "テーマ" | ||||||
|   behavior: "動作" |   behavior: "動作" | ||||||
|   fetch-on-scroll: "スクロールで自動読み込み" |   fetch-on-scroll: "スクロールで自動読み込み" | ||||||
|   note-visibility: "投稿の公開範囲" |   note-visibility: "投稿の公開範囲" | ||||||
|   | |||||||
| @@ -109,7 +109,7 @@ common: | |||||||
|   use-contrast-reversi-stones: "Make the stone color clear in reversi" |   use-contrast-reversi-stones: "Make the stone color clear in reversi" | ||||||
|   verified-user: "Verified account" |   verified-user: "Verified account" | ||||||
|   disable-animated-mfm: "Disable animated texts in a post" |   disable-animated-mfm: "Disable animated texts in a post" | ||||||
|   always-show-nsfw: "常に閲覧注意のメディアを表示する" |   always-show-nsfw: "Always show NSFW contents" | ||||||
|   always-mark-nsfw: "Always post with a warning about media attachment" |   always-mark-nsfw: "Always post with a warning about media attachment" | ||||||
|   show-full-acct: "Do not omit the hostname from the username" |   show-full-acct: "Do not omit the hostname from the username" | ||||||
|   reduce-motion: "Reduce motion in UI" |   reduce-motion: "Reduce motion in UI" | ||||||
| @@ -158,7 +158,7 @@ common: | |||||||
|     hashtag: "Hashtag" |     hashtag: "Hashtag" | ||||||
|     global: "Global" |     global: "Global" | ||||||
|     mentions: "Mentions" |     mentions: "Mentions" | ||||||
|     direct: "ダイレクト投稿" |     direct: "Direct post" | ||||||
|     notifications: "Notifications" |     notifications: "Notifications" | ||||||
|     list: "Lists" |     list: "Lists" | ||||||
|     swap-left: "Move to the left" |     swap-left: "Move to the left" | ||||||
| @@ -264,6 +264,41 @@ common/views/components/connect-failed.troubleshooter.vue: | |||||||
| common/views/components/media-banner.vue: | common/views/components/media-banner.vue: | ||||||
|   sensitive: "NSFW" |   sensitive: "NSFW" | ||||||
|   click-to-show: "Click to show" |   click-to-show: "Click to show" | ||||||
|  | common/views/components/theme.vue: | ||||||
|  |   light-theme: "非ダークモード時に使用するテーマ" | ||||||
|  |   dark-theme: "ダークモード時に使用するテーマ" | ||||||
|  |   light-themes: "明るいテーマ" | ||||||
|  |   dark-themes: "暗いテーマ" | ||||||
|  |   install-a-theme: "テーマのインストール" | ||||||
|  |   theme-code: "テーマコード" | ||||||
|  |   install: "インストール" | ||||||
|  |   installed: "「{}」をインストールしました" | ||||||
|  |   create-a-theme: "テーマの作成" | ||||||
|  |   save-created-theme: "テーマを保存" | ||||||
|  |   primary-color: "プライマリ カラー" | ||||||
|  |   secondary-color: "セカンダリ カラー" | ||||||
|  |   text-color: "文字色" | ||||||
|  |   base-theme: "ベーステーマ" | ||||||
|  |   base-theme-light: "Light" | ||||||
|  |   base-theme-dark: "Dark" | ||||||
|  |   theme-name: "テーマ名" | ||||||
|  |   preview-created-theme: "プレビュー" | ||||||
|  |   invalid-theme: "テーマが正しくありません。" | ||||||
|  |   already-installed: "既にそのテーマはインストールされています。" | ||||||
|  |   saved: "保存しました" | ||||||
|  |   manage-themes: "テーマの管理" | ||||||
|  |   builtin-themes: "標準テーマ" | ||||||
|  |   my-themes: "マイテーマ" | ||||||
|  |   installed-themes: "インストールされたテーマ" | ||||||
|  |   select-theme: "テーマを選択してください" | ||||||
|  |   uninstall: "アンインストール" | ||||||
|  |   uninstalled: "「{}」をアンインストールしました" | ||||||
|  |   author: "作者" | ||||||
|  |   desc: "説明" | ||||||
|  |   export: "エクスポート" | ||||||
|  |   import: "インポート" | ||||||
|  |   import-by-code: "またはコードをペースト" | ||||||
|  |   theme-name-required: "テーマ名は必須です。" | ||||||
| common/views/components/cw-button.vue: | common/views/components/cw-button.vue: | ||||||
|   hide: "Hide" |   hide: "Hide" | ||||||
|   show: "See more" |   show: "See more" | ||||||
| @@ -301,6 +336,7 @@ common/views/components/note-menu.vue: | |||||||
|   copy-link: "Copy link" |   copy-link: "Copy link" | ||||||
|   favorite: "Favorite this note" |   favorite: "Favorite this note" | ||||||
|   pin: "Pin to your profile" |   pin: "Pin to your profile" | ||||||
|  |   unpin: "ピン留め解除" | ||||||
|   delete: "Delete" |   delete: "Delete" | ||||||
|   delete-confirm: "Delete this post?" |   delete-confirm: "Delete this post?" | ||||||
|   remote: "Show original note" |   remote: "Show original note" | ||||||
| @@ -439,6 +475,7 @@ common/views/pages/follow.vue: | |||||||
|   following: "Following" |   following: "Following" | ||||||
|   follow: "Follow" |   follow: "Follow" | ||||||
|   request-pending: "Pending follow request" |   request-pending: "Pending follow request" | ||||||
|  |   follow-processing: "Processing follow" | ||||||
|   follow-request: "Follow request" |   follow-request: "Follow request" | ||||||
| desktop: | desktop: | ||||||
|   banner-crop-title: "Crop the part that appears as a banner" |   banner-crop-title: "Crop the part that appears as a banner" | ||||||
| @@ -477,13 +514,13 @@ desktop/views/components/charts.vue: | |||||||
|     notes: "The number of posts: increase/decrease (Combined)" |     notes: "The number of posts: increase/decrease (Combined)" | ||||||
|     local-notes: "The number of posts: increase/decrease (Local)" |     local-notes: "The number of posts: increase/decrease (Local)" | ||||||
|     remote-notes: "The number of posts: increase/decrease (Remote)" |     remote-notes: "The number of posts: increase/decrease (Remote)" | ||||||
|     notes-total: "The number of posts: cumulative total" |     notes-total: "投稿の積算" | ||||||
|     users: "The number of users: increase/decrease" |     users: "The number of users: increase/decrease" | ||||||
|     users-total: "The number of users: cumulative total" |     users-total: "ユーザーの積算" | ||||||
|     drive: "Capacity used as the storage: increase/decrease" |     drive: "Capacity used as the storage: increase/decrease" | ||||||
|     drive-total: "Capacity used as the storage: cumulative total" |     drive-total: "ドライブ使用量の積算" | ||||||
|     drive-files: "The number of files on the storage: increase/decrease" |     drive-files: "The number of files on the storage: increase/decrease" | ||||||
|     drive-files-total: "The number of files on the storage: cumulative total" |     drive-files-total: "ドライブのファイル数の積算" | ||||||
|     network-requests: "Requests" |     network-requests: "Requests" | ||||||
|     network-time: "Response time" |     network-time: "Response time" | ||||||
|     network-usage: "Traffic" |     network-usage: "Traffic" | ||||||
| @@ -565,6 +602,7 @@ desktop/views/components/follow-button.vue: | |||||||
|   following: "Following" |   following: "Following" | ||||||
|   follow: "Follow" |   follow: "Follow" | ||||||
|   request-pending: "Pending follow request" |   request-pending: "Pending follow request" | ||||||
|  |   follow-processing: "Processing follow" | ||||||
|   follow-request: "Follow request" |   follow-request: "Follow request" | ||||||
| desktop/views/components/followers-window.vue: | desktop/views/components/followers-window.vue: | ||||||
|   followers: "{}'s followers" |   followers: "{}'s followers" | ||||||
| @@ -675,6 +713,7 @@ desktop/views/components/settings.vue: | |||||||
|   2fa: "Two-factor authentication" |   2fa: "Two-factor authentication" | ||||||
|   other: "Other" |   other: "Other" | ||||||
|   license: "License" |   license: "License" | ||||||
|  |   theme: "Theme" | ||||||
|   behaviour: "Behavior" |   behaviour: "Behavior" | ||||||
|   fetch-on-scroll: "Endless loading on scroll" |   fetch-on-scroll: "Endless loading on scroll" | ||||||
|   fetch-on-scroll-desc: "When you scroll down the page, it automatically fetches additional content." |   fetch-on-scroll-desc: "When you scroll down the page, it automatically fetches additional content." | ||||||
| @@ -691,9 +730,10 @@ desktop/views/components/settings.vue: | |||||||
|   choose-wallpaper: "Choose a background" |   choose-wallpaper: "Choose a background" | ||||||
|   delete-wallpaper: "Remove background" |   delete-wallpaper: "Remove background" | ||||||
|   dark-mode: "Dark Mode" |   dark-mode: "Dark Mode" | ||||||
|  |   use-shadow: "UIに影を使用" | ||||||
|  |   rounded-corners: "UIの角を丸める" | ||||||
|   circle-icons: "Use circle icons" |   circle-icons: "Use circle icons" | ||||||
|   contrasted-acct: "Add contrast to username" |   contrasted-acct: "Add contrast to username" | ||||||
|   gradient-window-header: "Use gradients on window headers" |  | ||||||
|   post-form-on-timeline: "Display post form at the top of the timeline" |   post-form-on-timeline: "Display post form at the top of the timeline" | ||||||
|   suggest-recent-hashtags: "Show recent popular hashtags on the post form" |   suggest-recent-hashtags: "Show recent popular hashtags on the post form" | ||||||
|   show-clock-on-header: "Show clock on upper-right" |   show-clock-on-header: "Show clock on upper-right" | ||||||
| @@ -702,7 +742,6 @@ desktop/views/components/settings.vue: | |||||||
|   show-renoted-my-notes: "Show renoted my posts in timelines" |   show-renoted-my-notes: "Show renoted my posts in timelines" | ||||||
|   show-local-renotes: "Show renoted local posts in timelines" |   show-local-renotes: "Show renoted local posts in timelines" | ||||||
|   show-maps: "Display a map to show the location" |   show-maps: "Display a map to show the location" | ||||||
|   show-maps-desc: "If there comes a post contains location information, show a map to display the location." |  | ||||||
|   sound: "Sound" |   sound: "Sound" | ||||||
|   enable-sounds: "Enable sound" |   enable-sounds: "Enable sound" | ||||||
|   enable-sounds-desc: "Play a sound when you receive a post/message. This setting is stored in the browser." |   enable-sounds-desc: "Play a sound when you receive a post/message. This setting is stored in the browser." | ||||||
| @@ -1044,6 +1083,7 @@ mobile/views/components/follow-button.vue: | |||||||
|   following: "Following" |   following: "Following" | ||||||
|   follow: "Follow" |   follow: "Follow" | ||||||
|   request-pending: "Pending follow request" |   request-pending: "Pending follow request" | ||||||
|  |   follow-processing: "Processing follow" | ||||||
|   follow-request: "Follow request" |   follow-request: "Follow request" | ||||||
| mobile/views/components/friends-maker.vue: | mobile/views/components/friends-maker.vue: | ||||||
|   title: "Let's follow them" |   title: "Let's follow them" | ||||||
| @@ -1219,6 +1259,7 @@ mobile/views/pages/settings.vue: | |||||||
|   notification-position: "Notification style" |   notification-position: "Notification style" | ||||||
|   notification-position-bottom: "Bottom" |   notification-position-bottom: "Bottom" | ||||||
|   notification-position-top: "Top" |   notification-position-top: "Top" | ||||||
|  |   theme: "Theme" | ||||||
|   behavior: "Behavior" |   behavior: "Behavior" | ||||||
|   fetch-on-scroll: "Endless loading on scroll" |   fetch-on-scroll: "Endless loading on scroll" | ||||||
|   note-visibility: "Post visibility" |   note-visibility: "Post visibility" | ||||||
|   | |||||||
| @@ -264,6 +264,41 @@ common/views/components/connect-failed.troubleshooter.vue: | |||||||
| common/views/components/media-banner.vue: | common/views/components/media-banner.vue: | ||||||
|   sensitive: "閲覧注意" |   sensitive: "閲覧注意" | ||||||
|   click-to-show: "クリックして表示" |   click-to-show: "クリックして表示" | ||||||
|  | common/views/components/theme.vue: | ||||||
|  |   light-theme: "非ダークモード時に使用するテーマ" | ||||||
|  |   dark-theme: "ダークモード時に使用するテーマ" | ||||||
|  |   light-themes: "明るいテーマ" | ||||||
|  |   dark-themes: "暗いテーマ" | ||||||
|  |   install-a-theme: "テーマのインストール" | ||||||
|  |   theme-code: "テーマコード" | ||||||
|  |   install: "インストール" | ||||||
|  |   installed: "「{}」をインストールしました" | ||||||
|  |   create-a-theme: "テーマの作成" | ||||||
|  |   save-created-theme: "テーマを保存" | ||||||
|  |   primary-color: "プライマリ カラー" | ||||||
|  |   secondary-color: "セカンダリ カラー" | ||||||
|  |   text-color: "文字色" | ||||||
|  |   base-theme: "ベーステーマ" | ||||||
|  |   base-theme-light: "Light" | ||||||
|  |   base-theme-dark: "Dark" | ||||||
|  |   theme-name: "テーマ名" | ||||||
|  |   preview-created-theme: "プレビュー" | ||||||
|  |   invalid-theme: "テーマが正しくありません。" | ||||||
|  |   already-installed: "既にそのテーマはインストールされています。" | ||||||
|  |   saved: "保存しました" | ||||||
|  |   manage-themes: "テーマの管理" | ||||||
|  |   builtin-themes: "標準テーマ" | ||||||
|  |   my-themes: "マイテーマ" | ||||||
|  |   installed-themes: "インストールされたテーマ" | ||||||
|  |   select-theme: "テーマを選択してください" | ||||||
|  |   uninstall: "アンインストール" | ||||||
|  |   uninstalled: "「{}」をアンインストールしました" | ||||||
|  |   author: "作者" | ||||||
|  |   desc: "説明" | ||||||
|  |   export: "エクスポート" | ||||||
|  |   import: "インポート" | ||||||
|  |   import-by-code: "またはコードをペースト" | ||||||
|  |   theme-name-required: "テーマ名は必須です。" | ||||||
| common/views/components/cw-button.vue: | common/views/components/cw-button.vue: | ||||||
|   hide: "隠す" |   hide: "隠す" | ||||||
|   show: "もっと見る" |   show: "もっと見る" | ||||||
| @@ -301,6 +336,7 @@ common/views/components/note-menu.vue: | |||||||
|   copy-link: "Copiar enlace" |   copy-link: "Copiar enlace" | ||||||
|   favorite: "Me gusta esta nota" |   favorite: "Me gusta esta nota" | ||||||
|   pin: "Fijar en el perfil" |   pin: "Fijar en el perfil" | ||||||
|  |   unpin: "ピン留め解除" | ||||||
|   delete: "Borrar" |   delete: "Borrar" | ||||||
|   delete-confirm: "¿Seguro que quieres borrar la publicación?" |   delete-confirm: "¿Seguro que quieres borrar la publicación?" | ||||||
|   remote: "Ver el original" |   remote: "Ver el original" | ||||||
| @@ -439,6 +475,7 @@ common/views/pages/follow.vue: | |||||||
|   following: "Siguiendo" |   following: "Siguiendo" | ||||||
|   follow: "Seguir" |   follow: "Seguir" | ||||||
|   request-pending: "Solicitud pendiente" |   request-pending: "Solicitud pendiente" | ||||||
|  |   follow-processing: "フォロー処理中" | ||||||
|   follow-request: "Solicitar suscripción" |   follow-request: "Solicitar suscripción" | ||||||
| desktop: | desktop: | ||||||
|   banner-crop-title: "Corta la parte que aparece como un banner" |   banner-crop-title: "Corta la parte que aparece como un banner" | ||||||
| @@ -477,13 +514,13 @@ desktop/views/components/charts.vue: | |||||||
|     notes: "Número de publicaciones: aumentar/disminuir (Combinado)" |     notes: "Número de publicaciones: aumentar/disminuir (Combinado)" | ||||||
|     local-notes: "Número de publicaciones: aumentar/disminuir (Local)" |     local-notes: "Número de publicaciones: aumentar/disminuir (Local)" | ||||||
|     remote-notes: "Número de publicaciones: aumentar/disminuir (Remoto)" |     remote-notes: "Número de publicaciones: aumentar/disminuir (Remoto)" | ||||||
|     notes-total: "Número de publicaciones: Acumulativo total" |     notes-total: "投稿の積算" | ||||||
|     users: "Número de usuarios: aumentar/disminuir" |     users: "Número de usuarios: aumentar/disminuir" | ||||||
|     users-total: "Número de usuarios: Acumulativo total" |     users-total: "ユーザーの積算" | ||||||
|     drive: "Capacidad de almacenamiento usada: aumentar/disminuir" |     drive: "Capacidad de almacenamiento usada: aumentar/disminuir" | ||||||
|     drive-total: "Capacidad de almacenamiento usada: Acumulativa total" |     drive-total: "ドライブ使用量の積算" | ||||||
|     drive-files: "Número de archivos almacenados: aumentar/disminuir" |     drive-files: "Número de archivos almacenados: aumentar/disminuir" | ||||||
|     drive-files-total: "Número de archivos almacenados: Acumulativo total" |     drive-files-total: "ドライブのファイル数の積算" | ||||||
|     network-requests: "リクエスト" |     network-requests: "リクエスト" | ||||||
|     network-time: "応答時間" |     network-time: "応答時間" | ||||||
|     network-usage: "通信量" |     network-usage: "通信量" | ||||||
| @@ -565,6 +602,7 @@ desktop/views/components/follow-button.vue: | |||||||
|   following: "Siguiendo" |   following: "Siguiendo" | ||||||
|   follow: "Sigue" |   follow: "Sigue" | ||||||
|   request-pending: "Pendiente de aprobación" |   request-pending: "Pendiente de aprobación" | ||||||
|  |   follow-processing: "フォロー処理中" | ||||||
|   follow-request: "Solicitud de seguir" |   follow-request: "Solicitud de seguir" | ||||||
| desktop/views/components/followers-window.vue: | desktop/views/components/followers-window.vue: | ||||||
|   followers: "{} seguidores" |   followers: "{} seguidores" | ||||||
| @@ -675,6 +713,7 @@ desktop/views/components/settings.vue: | |||||||
|   2fa: "Autenticación de Doble-Factor" |   2fa: "Autenticación de Doble-Factor" | ||||||
|   other: "Otros" |   other: "Otros" | ||||||
|   license: "Licencia" |   license: "Licencia" | ||||||
|  |   theme: "テーマ" | ||||||
|   behaviour: "Acciones" |   behaviour: "Acciones" | ||||||
|   fetch-on-scroll: "Desplazamiento infinito" |   fetch-on-scroll: "Desplazamiento infinito" | ||||||
|   fetch-on-scroll-desc: "Cuando te deslizas al final de la página nuevo contenido se carga automáticamente." |   fetch-on-scroll-desc: "Cuando te deslizas al final de la página nuevo contenido se carga automáticamente." | ||||||
| @@ -691,9 +730,10 @@ desktop/views/components/settings.vue: | |||||||
|   choose-wallpaper: "Elije un fondo" |   choose-wallpaper: "Elije un fondo" | ||||||
|   delete-wallpaper: "Suprimir fondo" |   delete-wallpaper: "Suprimir fondo" | ||||||
|   dark-mode: "Modo Nocturno" |   dark-mode: "Modo Nocturno" | ||||||
|  |   use-shadow: "UIに影を使用" | ||||||
|  |   rounded-corners: "UIの角を丸める" | ||||||
|   circle-icons: "Usar iconos circulares" |   circle-icons: "Usar iconos circulares" | ||||||
|   contrasted-acct: "ユーザー名にコントラストを付ける" |   contrasted-acct: "ユーザー名にコントラストを付ける" | ||||||
|   gradient-window-header: "Usar degradados en las cabeceras de las páginas" |  | ||||||
|   post-form-on-timeline: "Mostrar el formulario de las entradas encima de la línea de tiempo" |   post-form-on-timeline: "Mostrar el formulario de las entradas encima de la línea de tiempo" | ||||||
|   suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する" |   suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する" | ||||||
|   show-clock-on-header: "右上に時計を表示する" |   show-clock-on-header: "右上に時計を表示する" | ||||||
| @@ -702,7 +742,6 @@ desktop/views/components/settings.vue: | |||||||
|   show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する" |   show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する" | ||||||
|   show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する" |   show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する" | ||||||
|   show-maps: "マップの自動展開" |   show-maps: "マップの自動展開" | ||||||
|   show-maps-desc: "位置情報が添付された投稿のマップを自動的に展開します。" |  | ||||||
|   sound: "サウンド" |   sound: "サウンド" | ||||||
|   enable-sounds: "サウンドを有効にする" |   enable-sounds: "サウンドを有効にする" | ||||||
|   enable-sounds-desc: "投稿やメッセージを送受信したときなどにサウンドを再生します。この設定はブラウザに記憶されます。" |   enable-sounds-desc: "投稿やメッセージを送受信したときなどにサウンドを再生します。この設定はブラウザに記憶されます。" | ||||||
| @@ -1044,6 +1083,7 @@ mobile/views/components/follow-button.vue: | |||||||
|   following: "フォロー中" |   following: "フォロー中" | ||||||
|   follow: "フォロー" |   follow: "フォロー" | ||||||
|   request-pending: "フォロー許可待ち" |   request-pending: "フォロー許可待ち" | ||||||
|  |   follow-processing: "フォロー処理中" | ||||||
|   follow-request: "フォロー申請" |   follow-request: "フォロー申請" | ||||||
| mobile/views/components/friends-maker.vue: | mobile/views/components/friends-maker.vue: | ||||||
|   title: "気になるユーザーをフォロー" |   title: "気になるユーザーをフォロー" | ||||||
| @@ -1219,6 +1259,7 @@ mobile/views/pages/settings.vue: | |||||||
|   notification-position: "通知の表示" |   notification-position: "通知の表示" | ||||||
|   notification-position-bottom: "下" |   notification-position-bottom: "下" | ||||||
|   notification-position-top: "上" |   notification-position-top: "上" | ||||||
|  |   theme: "テーマ" | ||||||
|   behavior: "動作" |   behavior: "動作" | ||||||
|   fetch-on-scroll: "スクロールで自動読み込み" |   fetch-on-scroll: "スクロールで自動読み込み" | ||||||
|   note-visibility: "投稿の公開範囲" |   note-visibility: "投稿の公開範囲" | ||||||
|   | |||||||
| @@ -9,7 +9,7 @@ common: | |||||||
|   intro: |   intro: | ||||||
|     title: "C’est quoi Misskey ?" |     title: "C’est quoi Misskey ?" | ||||||
|     about: "Misskeyはオープンソースの<b>分散型マイクロブログSNS</b>です。リッチで高度にカスタマイズできるUI、投稿へのリアクション、ファイルを一元管理できるドライブなど、先進的な機能を揃えています。また、Fediverseと呼ばれるネットワークに接続できるため、他のSNSともやり取りできます。例えば、あなたが何か投稿すると、その投稿はMisskeyだけでなく他のSNSにも伝わります。ちょうどある惑星から他の惑星に電波を発信している様子をイメージしてください。" |     about: "Misskeyはオープンソースの<b>分散型マイクロブログSNS</b>です。リッチで高度にカスタマイズできるUI、投稿へのリアクション、ファイルを一元管理できるドライブなど、先進的な機能を揃えています。また、Fediverseと呼ばれるネットワークに接続できるため、他のSNSともやり取りできます。例えば、あなたが何か投稿すると、その投稿はMisskeyだけでなく他のSNSにも伝わります。ちょうどある惑星から他の惑星に電波を発信している様子をイメージしてください。" | ||||||
|     features: "Fonctionnalités" |     features: "Options" | ||||||
|     rich-contents: "Notes" |     rich-contents: "Notes" | ||||||
|     rich-contents-desc: "自分の考え、話題の出来事、皆と共有したいことについて発信してください。必要であれば、様々な構文を使って投稿を装飾したり、好きな画像、動画などのファイルやアンケートを添付することもできます。" |     rich-contents-desc: "自分の考え、話題の出来事、皆と共有したいことについて発信してください。必要であれば、様々な構文を使って投稿を装飾したり、好きな画像、動画などのファイルやアンケートを添付することもできます。" | ||||||
|     reaction: "Réactions" |     reaction: "Réactions" | ||||||
| @@ -32,7 +32,7 @@ common: | |||||||
|     paragraph2: "Vous pouvez changer l'affichage en <strong>cliquant droit</strong> sur certains widgets." |     paragraph2: "Vous pouvez changer l'affichage en <strong>cliquant droit</strong> sur certains widgets." | ||||||
|     paragraph3: "Pour supprimer un widget, <strong>glissez et déposez le widget sur la zone étiquetée « Corbeille »</strong> dans l'en-tête." |     paragraph3: "Pour supprimer un widget, <strong>glissez et déposez le widget sur la zone étiquetée « Corbeille »</strong> dans l'en-tête." | ||||||
|     paragraph4: "Pour terminer la personnalisation, cliquez sur \"Terminer\" dans le coin supérieur droit." |     paragraph4: "Pour terminer la personnalisation, cliquez sur \"Terminer\" dans le coin supérieur droit." | ||||||
|     gotit: "Compris!" |     gotit: "Compris !" | ||||||
|   notification: |   notification: | ||||||
|     file-uploaded: "Le fichier a été téléversé !" |     file-uploaded: "Le fichier a été téléversé !" | ||||||
|     message-from: "Message de {} :" |     message-from: "Message de {} :" | ||||||
| @@ -52,7 +52,7 @@ common: | |||||||
|     weeks_ago: "Il y a {} semaines·s" |     weeks_ago: "Il y a {} semaines·s" | ||||||
|     months_ago: "Il y a {} mois" |     months_ago: "Il y a {} mois" | ||||||
|     years_ago: "Il y a {} an·s" |     years_ago: "Il y a {} an·s" | ||||||
|   month-and-day: "{month}/{day}" |   month-and-day: "{month} mois/{day} jour" | ||||||
|   trash: "Corbeille" |   trash: "Corbeille" | ||||||
|   weekday-short: |   weekday-short: | ||||||
|     sunday: "D" |     sunday: "D" | ||||||
| @@ -111,7 +111,7 @@ common: | |||||||
|   disable-animated-mfm: "Désactiver les textes animés dans les publications" |   disable-animated-mfm: "Désactiver les textes animés dans les publications" | ||||||
|   always-show-nsfw: "常に閲覧注意のメディアを表示する" |   always-show-nsfw: "常に閲覧注意のメディアを表示する" | ||||||
|   always-mark-nsfw: "常にメディアを閲覧注意として投稿" |   always-mark-nsfw: "常にメディアを閲覧注意として投稿" | ||||||
|   show-full-acct: "ユーザー名のホストを省略しない" |   show-full-acct: "Afficher l’adresse complète de l’utilisateur" | ||||||
|   reduce-motion: "Réduire les animations dans l’interface utilisateur" |   reduce-motion: "Réduire les animations dans l’interface utilisateur" | ||||||
|   this-setting-is-this-device-only: "Uniquement sur cet appareil" |   this-setting-is-this-device-only: "Uniquement sur cet appareil" | ||||||
|   do-not-use-in-production: 'Il s’agit d’une version de développement. Ne pas utiliser dans un environnement de production.' |   do-not-use-in-production: 'Il s’agit d’une version de développement. Ne pas utiliser dans un environnement de production.' | ||||||
| @@ -149,16 +149,16 @@ common: | |||||||
|     donation: "Dons" |     donation: "Dons" | ||||||
|     nav: "Navigation" |     nav: "Navigation" | ||||||
|     tips: "Conseils" |     tips: "Conseils" | ||||||
|     hashtags: "Étiquettes" |     hashtags: "Hashtags" | ||||||
|   deck: |   deck: | ||||||
|     widgets: "Widgets" |     widgets: "Widgets" | ||||||
|     home: "Accueil" |     home: "Accueil" | ||||||
|     local: "Local" |     local: "Local" | ||||||
|     hybrid: "Social" |     hybrid: "Social" | ||||||
|     hashtag: "ハッシュタグ" |     hashtag: "Hashtag" | ||||||
|     global: "Global" |     global: "Global" | ||||||
|     mentions: "Mentions" |     mentions: "Mentions" | ||||||
|     direct: "ダイレクト投稿" |     direct: "Messages directs" | ||||||
|     notifications: "Notifications" |     notifications: "Notifications" | ||||||
|     list: "Liste" |     list: "Liste" | ||||||
|     swap-left: "Déplacer à gauche" |     swap-left: "Déplacer à gauche" | ||||||
| @@ -189,7 +189,7 @@ auth/views/index.vue: | |||||||
|   denied: "L'autorisation de l'application a été refusée." |   denied: "L'autorisation de l'application a été refusée." | ||||||
|   denied-paragraph: "Cette application ne va pas accéder à votre compte." |   denied-paragraph: "Cette application ne va pas accéder à votre compte." | ||||||
|   already-authorized: "Cette application est déjà autorisée" |   already-authorized: "Cette application est déjà autorisée" | ||||||
|   allowed: "アプリケーションの連携を許可しました" |   allowed: "Permissions autorisées de l’application." | ||||||
|   callback-url: "Retour vers l'application" |   callback-url: "Retour vers l'application" | ||||||
|   please-go-back: "Veillez retourner à l'application." |   please-go-back: "Veillez retourner à l'application." | ||||||
|   error: "La session n'existe pas." |   error: "La session n'existe pas." | ||||||
| @@ -264,6 +264,41 @@ common/views/components/connect-failed.troubleshooter.vue: | |||||||
| common/views/components/media-banner.vue: | common/views/components/media-banner.vue: | ||||||
|   sensitive: "Contenu sensible" |   sensitive: "Contenu sensible" | ||||||
|   click-to-show: "Cliquer pour afficher" |   click-to-show: "Cliquer pour afficher" | ||||||
|  | common/views/components/theme.vue: | ||||||
|  |   light-theme: "非ダークモード時に使用するテーマ" | ||||||
|  |   dark-theme: "ダークモード時に使用するテーマ" | ||||||
|  |   light-themes: "明るいテーマ" | ||||||
|  |   dark-themes: "暗いテーマ" | ||||||
|  |   install-a-theme: "Installer un thème" | ||||||
|  |   theme-code: "Code du thème" | ||||||
|  |   install: "Installation" | ||||||
|  |   installed: "« {} » a été installé" | ||||||
|  |   create-a-theme: "Créer un thème" | ||||||
|  |   save-created-theme: "Enregistrer le thème" | ||||||
|  |   primary-color: "Couleur primaire" | ||||||
|  |   secondary-color: "Couleur secondaire" | ||||||
|  |   text-color: "Couleur du texte" | ||||||
|  |   base-theme: "Thème de base" | ||||||
|  |   base-theme-light: "Clair" | ||||||
|  |   base-theme-dark: "Sombre" | ||||||
|  |   theme-name: "Nom du Thème" | ||||||
|  |   preview-created-theme: "Prévisualisation" | ||||||
|  |   invalid-theme: "Thème n’est pas valide." | ||||||
|  |   already-installed: "Le thème est déjà installé." | ||||||
|  |   saved: "enregistré" | ||||||
|  |   manage-themes: "テーマの管理" | ||||||
|  |   builtin-themes: "標準テーマ" | ||||||
|  |   my-themes: "マイテーマ" | ||||||
|  |   installed-themes: "Thèmes installés" | ||||||
|  |   select-theme: "Veuillez sélectionner un thème" | ||||||
|  |   uninstall: "Désinstaller" | ||||||
|  |   uninstalled: "« {} » a été désinstallé" | ||||||
|  |   author: "Auteur" | ||||||
|  |   desc: "Description" | ||||||
|  |   export: "エクスポート" | ||||||
|  |   import: "Importer" | ||||||
|  |   import-by-code: "Ou coller du code" | ||||||
|  |   theme-name-required: "Nom du thème est obligatoire." | ||||||
| common/views/components/cw-button.vue: | common/views/components/cw-button.vue: | ||||||
|   hide: "Masquer" |   hide: "Masquer" | ||||||
|   show: "Voir plus" |   show: "Voir plus" | ||||||
| @@ -301,6 +336,7 @@ common/views/components/note-menu.vue: | |||||||
|   copy-link: "Copier le lien" |   copy-link: "Copier le lien" | ||||||
|   favorite: "Mettre cette note en favoris" |   favorite: "Mettre cette note en favoris" | ||||||
|   pin: "Épingler sur votre profil" |   pin: "Épingler sur votre profil" | ||||||
|  |   unpin: "Désépingler" | ||||||
|   delete: "Supprimer" |   delete: "Supprimer" | ||||||
|   delete-confirm: "Supprimer cette publication ?" |   delete-confirm: "Supprimer cette publication ?" | ||||||
|   remote: "Afficher la note originale" |   remote: "Afficher la note originale" | ||||||
| @@ -401,7 +437,7 @@ common/views/widgets/posts-monitor.vue: | |||||||
|   title: "Graphe des publications" |   title: "Graphe des publications" | ||||||
|   toggle: "Basculer entre les vues" |   toggle: "Basculer entre les vues" | ||||||
| common/views/widgets/hashtags.vue: | common/views/widgets/hashtags.vue: | ||||||
|   title: "Étiquettes" |   title: "Hashtags" | ||||||
| common/views/widgets/server.vue: | common/views/widgets/server.vue: | ||||||
|   title: "Informations sur le serveur" |   title: "Informations sur le serveur" | ||||||
|   toggle: "Afficher les vues" |   toggle: "Afficher les vues" | ||||||
| @@ -420,7 +456,7 @@ common/views/widgets/tips.vue: | |||||||
|   tips-line4: "Vous pouvez coller des images à partir du presse-papier sur la fenêtre de la note" |   tips-line4: "Vous pouvez coller des images à partir du presse-papier sur la fenêtre de la note" | ||||||
|   tips-line5: "Vous pouvez téléverser des fichiers sur le Drive en faisant un glisser-déposer" |   tips-line5: "Vous pouvez téléverser des fichiers sur le Drive en faisant un glisser-déposer" | ||||||
|   tips-line6: "Vous pouvez déplacer un dossier en le glissant dans le Drive" |   tips-line6: "Vous pouvez déplacer un dossier en le glissant dans le Drive" | ||||||
|   tips-line7: "ドライブでフォルダをドラッグしてフォルダ移動できます" |   tips-line7: "Vous pouvez déplacer des dossiers en les glissant dans le Drive" | ||||||
|   tips-line8: "Vous pouvez personnaliser l'Accueil via les paramètres" |   tips-line8: "Vous pouvez personnaliser l'Accueil via les paramètres" | ||||||
|   tips-line9: "Misskey est sous licence AGPLv3" |   tips-line9: "Misskey est sous licence AGPLv3" | ||||||
|   tips-line10: "タイムマシンウィジェットを利用すると、簡単に過去のタイムラインに遡れます" |   tips-line10: "タイムマシンウィジェットを利用すると、簡単に過去のタイムラインに遡れます" | ||||||
| @@ -428,7 +464,7 @@ common/views/widgets/tips.vue: | |||||||
|   tips-line13: "Tous les fichiers attachés à cette publication sont sauvegardés dans le Drive" |   tips-line13: "Tous les fichiers attachés à cette publication sont sauvegardés dans le Drive" | ||||||
|   tips-line14: "ホームのカスタマイズ中、ウィジェットを右クリックしてデザインを変更できます" |   tips-line14: "ホームのカスタマイズ中、ウィジェットを右クリックしてデザインを変更できます" | ||||||
|   tips-line17: "Vous pouvez mettre un texte en surbrillance en le mettant entre ** **" |   tips-line17: "Vous pouvez mettre un texte en surbrillance en le mettant entre ** **" | ||||||
|   tips-line19: "いくつかのウィンドウはブラウザの外に切り離すことができます" |   tips-line19: "Plusieurs fenêtres peuvent être détachées en dehors du navigateur." | ||||||
|   tips-line20: "カレンダーウィジェットのパーセンテージは、経過の割合を示しています" |   tips-line20: "カレンダーウィジェットのパーセンテージは、経過の割合を示しています" | ||||||
|   tips-line21: "Vous pouvez aussi utiliser l'API pour développer des Bots." |   tips-line21: "Vous pouvez aussi utiliser l'API pour développer des Bots." | ||||||
|   tips-line23: "Mayu est mignone avec ses sourcils." |   tips-line23: "Mayu est mignone avec ses sourcils." | ||||||
| @@ -439,6 +475,7 @@ common/views/pages/follow.vue: | |||||||
|   following: "Suit" |   following: "Suit" | ||||||
|   follow: "Suivre" |   follow: "Suivre" | ||||||
|   request-pending: "Demande d'abonnement en attente" |   request-pending: "Demande d'abonnement en attente" | ||||||
|  |   follow-processing: "フォロー処理中" | ||||||
|   follow-request: "Demande d'abonnement" |   follow-request: "Demande d'abonnement" | ||||||
| desktop: | desktop: | ||||||
|   banner-crop-title: "Découpez la partie qui apparaitra comme bannière" |   banner-crop-title: "Découpez la partie qui apparaitra comme bannière" | ||||||
| @@ -451,7 +488,7 @@ desktop: | |||||||
|   uploading-avatar: "Téléversement du nouvel avatar" |   uploading-avatar: "Téléversement du nouvel avatar" | ||||||
|   avatar-updated: "L'avatar est mis à jour" |   avatar-updated: "L'avatar est mis à jour" | ||||||
|   choose-avatar: "Choisir un avatar" |   choose-avatar: "Choisir un avatar" | ||||||
|   invalid-filetype: "この形式のファイルはサポートされていません" |   invalid-filetype: "Ce format de fichier n’est pas pris en charge" | ||||||
| desktop/views/components/activity.chart.vue: | desktop/views/components/activity.chart.vue: | ||||||
|   total: "Noirs ... Total" |   total: "Noirs ... Total" | ||||||
|   notes: "Bleu ... Notes" |   notes: "Bleu ... Notes" | ||||||
| @@ -477,13 +514,13 @@ desktop/views/components/charts.vue: | |||||||
|     notes: "投稿の増減 (統合)" |     notes: "投稿の増減 (統合)" | ||||||
|     local-notes: "投稿の増減 (ローカル)" |     local-notes: "投稿の増減 (ローカル)" | ||||||
|     remote-notes: "投稿の増減 (リモート)" |     remote-notes: "投稿の増減 (リモート)" | ||||||
|     notes-total: "投稿の累計" |     notes-total: "投稿の積算" | ||||||
|     users: "Nombre d’utilisateurs·trices : augmentation/diminution" |     users: "Nombre d’utilisateurs·trices : augmentation/diminution" | ||||||
|     users-total: "Nombre total d’utilisateurs·trices : total cumulé" |     users-total: "ユーザーの積算" | ||||||
|     drive: "ドライブ使用量の増減" |     drive: "ドライブ使用量の増減" | ||||||
|     drive-total: "ドライブ使用量の累計" |     drive-total: "ドライブ使用量の積算" | ||||||
|     drive-files: "ドライブのファイル数の増減" |     drive-files: "ドライブのファイル数の増減" | ||||||
|     drive-files-total: "ドライブのファイル数の累計" |     drive-files-total: "ドライブのファイル数の積算" | ||||||
|     network-requests: "Requêtes" |     network-requests: "Requêtes" | ||||||
|     network-time: "Temps de réponse" |     network-time: "Temps de réponse" | ||||||
|     network-usage: "Traffic" |     network-usage: "Traffic" | ||||||
| @@ -565,6 +602,7 @@ desktop/views/components/follow-button.vue: | |||||||
|   following: "Abonnements" |   following: "Abonnements" | ||||||
|   follow: "Suivre" |   follow: "Suivre" | ||||||
|   request-pending: "En attente d'approbation" |   request-pending: "En attente d'approbation" | ||||||
|  |   follow-processing: "フォロー処理中" | ||||||
|   follow-request: "Demande d'abonnement" |   follow-request: "Demande d'abonnement" | ||||||
| desktop/views/components/followers-window.vue: | desktop/views/components/followers-window.vue: | ||||||
|   followers: "{} abonné·e·s" |   followers: "{} abonné·e·s" | ||||||
| @@ -675,6 +713,7 @@ desktop/views/components/settings.vue: | |||||||
|   2fa: "Vérification en deux étapes" |   2fa: "Vérification en deux étapes" | ||||||
|   other: "Autres" |   other: "Autres" | ||||||
|   license: "License" |   license: "License" | ||||||
|  |   theme: "Thèmes" | ||||||
|   behaviour: "Comportement" |   behaviour: "Comportement" | ||||||
|   fetch-on-scroll: "Chargement lors du défilement" |   fetch-on-scroll: "Chargement lors du défilement" | ||||||
|   fetch-on-scroll-desc: "Chargement automatique du contenu lors du défilement de la page." |   fetch-on-scroll-desc: "Chargement automatique du contenu lors du défilement de la page." | ||||||
| @@ -691,18 +730,18 @@ desktop/views/components/settings.vue: | |||||||
|   choose-wallpaper: "Sélectionner un fond d'écran" |   choose-wallpaper: "Sélectionner un fond d'écran" | ||||||
|   delete-wallpaper: "Supprimer le fond d'écran" |   delete-wallpaper: "Supprimer le fond d'écran" | ||||||
|   dark-mode: "Mode nuit" |   dark-mode: "Mode nuit" | ||||||
|  |   use-shadow: "Utiliser les ombres dans l'interface utilisateur" | ||||||
|  |   rounded-corners: "Coins arrondis" | ||||||
|   circle-icons: "Utiliser des icônes circulaires" |   circle-icons: "Utiliser des icônes circulaires" | ||||||
|   contrasted-acct: "Nom d’utilisateur contrasté" |   contrasted-acct: "Nom d’utilisateur contrasté" | ||||||
|   gradient-window-header: "Utiliser les dégradés sur la barre de titre de la fenêtre" |  | ||||||
|   post-form-on-timeline: "Afficher le formulaire en haut du fil" |   post-form-on-timeline: "Afficher le formulaire en haut du fil" | ||||||
|   suggest-recent-hashtags: "Afficher les hashtags populaires dans le champs de saisie" |   suggest-recent-hashtags: "Afficher les hashtags populaires dans le champs de saisie" | ||||||
|   show-clock-on-header: "Afficher l'horloge à droite sur le coté supérieur" |   show-clock-on-header: "Afficher l'horloge à droite sur le coté supérieur" | ||||||
|   show-reply-target: "Afficher les réponses" |   show-reply-target: "Afficher les réponses" | ||||||
|   show-my-renotes: "Afficher mes republications dans le fil" |   show-my-renotes: "Afficher mes republications dans le fil" | ||||||
|   show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する" |   show-renoted-my-notes: "Afficher mes republications dans les fils" | ||||||
|   show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する" |   show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する" | ||||||
|   show-maps: "Afficher la carte" |   show-maps: "Afficher la carte" | ||||||
|   show-maps-desc: "位置情報が添付された投稿のマップを自動的に展開します。" |  | ||||||
|   sound: "Son" |   sound: "Son" | ||||||
|   enable-sounds: "Activer le son" |   enable-sounds: "Activer le son" | ||||||
|   enable-sounds-desc: "Jouer un son lorsque vous recevez un message. Ce paramètre est sauvegardé dans le navigateur." |   enable-sounds-desc: "Jouer un son lorsque vous recevez un message. Ce paramètre est sauvegardé dans le navigateur." | ||||||
| @@ -741,7 +780,7 @@ desktop/views/components/settings.vue: | |||||||
|   debug-mode: "Activer le mode debug" |   debug-mode: "Activer le mode debug" | ||||||
|   debug-mode-desc: "Ce paramètre est stocké dans le navigateur." |   debug-mode-desc: "Ce paramètre est stocké dans le navigateur." | ||||||
|   experimental: "Activer les fonctionnalités expérimentales" |   experimental: "Activer les fonctionnalités expérimentales" | ||||||
|   experimental-desc: "実験的機能を有効にするとMisskeyの動作が不安定になる可能性があります。この設定はブラウザに記憶されます。" |   experimental-desc: "L’activation des fonctionnalités expérimentales peuvent rendre le client Misskey instable. Ce paramètre est stocké dans le navigateur." | ||||||
|   tools: "Outils" |   tools: "Outils" | ||||||
|   task-manager: "Gestionnaire de tâches" |   task-manager: "Gestionnaire de tâches" | ||||||
|   third-parties: "Services tiers" |   third-parties: "Services tiers" | ||||||
| @@ -811,12 +850,12 @@ desktop/views/components/timeline.vue: | |||||||
|   hybrid: "Social" |   hybrid: "Social" | ||||||
|   global: "Global" |   global: "Global" | ||||||
|   mentions: "Mentions" |   mentions: "Mentions" | ||||||
|   messages: "メッセージ" |   messages: "Messages" | ||||||
|   list: "Listes" |   list: "Listes" | ||||||
|   hashtag: "ハッシュタグ" |   hashtag: "Hashtag" | ||||||
|   add-tag-timeline: "ハッシュタグを追加" |   add-tag-timeline: "Ajouter un fil de hashtags" | ||||||
|   add-list: "リストを追加" |   add-list: "Ajouter une nouvelle liste" | ||||||
|   list-name: "リスト名" |   list-name: "Nom de la liste" | ||||||
| desktop/views/components/ui.header.vue: | desktop/views/components/ui.header.vue: | ||||||
|   welcome-back: "Content de vous revoir !" |   welcome-back: "Content de vous revoir !" | ||||||
|   adjective: "さん" |   adjective: "さん" | ||||||
| @@ -932,7 +971,7 @@ desktop/views/pages/selectdrive.vue: | |||||||
|   cancel: "Annuler" |   cancel: "Annuler" | ||||||
|   upload: "Uploader un ou plusieurs fichier(s) depuis votre PC" |   upload: "Uploader un ou plusieurs fichier(s) depuis votre PC" | ||||||
| desktop/views/pages/search.vue: | desktop/views/pages/search.vue: | ||||||
|   not-available: "検索機能はインスタンスの設定で無効になっています。" |   not-available: "La fonction de recherche est désactivée dans les paramètres de l’instance." | ||||||
|   not-found: "Aucun message trouvé pour '{}'" |   not-found: "Aucun message trouvé pour '{}'" | ||||||
| desktop/views/pages/share.vue: | desktop/views/pages/share.vue: | ||||||
|   share-with: "Partager avec {}" |   share-with: "Partager avec {}" | ||||||
| @@ -1044,6 +1083,7 @@ mobile/views/components/follow-button.vue: | |||||||
|   following: "Abonnements" |   following: "Abonnements" | ||||||
|   follow: "Suivre" |   follow: "Suivre" | ||||||
|   request-pending: "En attente d'approbation" |   request-pending: "En attente d'approbation" | ||||||
|  |   follow-processing: "フォロー処理中" | ||||||
|   follow-request: "Demande d'abonnement" |   follow-request: "Demande d'abonnement" | ||||||
| mobile/views/components/friends-maker.vue: | mobile/views/components/friends-maker.vue: | ||||||
|   title: "Abonnez-vous aux utilisateurs" |   title: "Abonnez-vous aux utilisateurs" | ||||||
| @@ -1142,7 +1182,7 @@ mobile/views/pages/home.vue: | |||||||
|   hybrid: "Social" |   hybrid: "Social" | ||||||
|   global: "Global" |   global: "Global" | ||||||
|   mentions: "Mentions" |   mentions: "Mentions" | ||||||
|   messages: "メッセージ" |   messages: "Messages" | ||||||
| mobile/views/pages/tag.vue: | mobile/views/pages/tag.vue: | ||||||
|   no-posts-found: "Pas de message avec un hashtag {} trouvé." |   no-posts-found: "Pas de message avec un hashtag {} trouvé." | ||||||
| mobile/views/pages/welcome.vue: | mobile/views/pages/welcome.vue: | ||||||
| @@ -1219,6 +1259,7 @@ mobile/views/pages/settings.vue: | |||||||
|   notification-position: "Style de notification" |   notification-position: "Style de notification" | ||||||
|   notification-position-bottom: "en bas" |   notification-position-bottom: "en bas" | ||||||
|   notification-position-top: "en haut" |   notification-position-top: "en haut" | ||||||
|  |   theme: "Thème" | ||||||
|   behavior: "Comportement" |   behavior: "Comportement" | ||||||
|   fetch-on-scroll: "Chargement lors du défilement" |   fetch-on-scroll: "Chargement lors du défilement" | ||||||
|   note-visibility: "Visibilité de la publication" |   note-visibility: "Visibilité de la publication" | ||||||
|   | |||||||
| @@ -264,6 +264,41 @@ common/views/components/connect-failed.troubleshooter.vue: | |||||||
| common/views/components/media-banner.vue: | common/views/components/media-banner.vue: | ||||||
|   sensitive: "閲覧注意" |   sensitive: "閲覧注意" | ||||||
|   click-to-show: "クリックして表示" |   click-to-show: "クリックして表示" | ||||||
|  | common/views/components/theme.vue: | ||||||
|  |   light-theme: "非ダークモード時に使用するテーマ" | ||||||
|  |   dark-theme: "ダークモード時に使用するテーマ" | ||||||
|  |   light-themes: "明るいテーマ" | ||||||
|  |   dark-themes: "暗いテーマ" | ||||||
|  |   install-a-theme: "テーマのインストール" | ||||||
|  |   theme-code: "テーマコード" | ||||||
|  |   install: "インストール" | ||||||
|  |   installed: "「{}」をインストールしました" | ||||||
|  |   create-a-theme: "テーマの作成" | ||||||
|  |   save-created-theme: "テーマを保存" | ||||||
|  |   primary-color: "プライマリ カラー" | ||||||
|  |   secondary-color: "セカンダリ カラー" | ||||||
|  |   text-color: "文字色" | ||||||
|  |   base-theme: "ベーステーマ" | ||||||
|  |   base-theme-light: "Light" | ||||||
|  |   base-theme-dark: "Dark" | ||||||
|  |   theme-name: "テーマ名" | ||||||
|  |   preview-created-theme: "プレビュー" | ||||||
|  |   invalid-theme: "テーマが正しくありません。" | ||||||
|  |   already-installed: "既にそのテーマはインストールされています。" | ||||||
|  |   saved: "保存しました" | ||||||
|  |   manage-themes: "テーマの管理" | ||||||
|  |   builtin-themes: "標準テーマ" | ||||||
|  |   my-themes: "マイテーマ" | ||||||
|  |   installed-themes: "インストールされたテーマ" | ||||||
|  |   select-theme: "テーマを選択してください" | ||||||
|  |   uninstall: "アンインストール" | ||||||
|  |   uninstalled: "「{}」をアンインストールしました" | ||||||
|  |   author: "作者" | ||||||
|  |   desc: "説明" | ||||||
|  |   export: "エクスポート" | ||||||
|  |   import: "インポート" | ||||||
|  |   import-by-code: "またはコードをペースト" | ||||||
|  |   theme-name-required: "テーマ名は必須です。" | ||||||
| common/views/components/cw-button.vue: | common/views/components/cw-button.vue: | ||||||
|   hide: "隠す" |   hide: "隠す" | ||||||
|   show: "もっと見る" |   show: "もっと見る" | ||||||
| @@ -301,6 +336,7 @@ common/views/components/note-menu.vue: | |||||||
|   copy-link: "リンクをコピー" |   copy-link: "リンクをコピー" | ||||||
|   favorite: "お気に入り" |   favorite: "お気に入り" | ||||||
|   pin: "ピン留め" |   pin: "ピン留め" | ||||||
|  |   unpin: "ピン留め解除" | ||||||
|   delete: "削除" |   delete: "削除" | ||||||
|   delete-confirm: "この投稿を削除しますか?" |   delete-confirm: "この投稿を削除しますか?" | ||||||
|   remote: "投稿元で見る" |   remote: "投稿元で見る" | ||||||
| @@ -439,6 +475,7 @@ common/views/pages/follow.vue: | |||||||
|   following: "フォロー中" |   following: "フォロー中" | ||||||
|   follow: "フォロー" |   follow: "フォロー" | ||||||
|   request-pending: "フォロー許可待ち" |   request-pending: "フォロー許可待ち" | ||||||
|  |   follow-processing: "フォロー処理中" | ||||||
|   follow-request: "フォロー申請" |   follow-request: "フォロー申請" | ||||||
| desktop: | desktop: | ||||||
|   banner-crop-title: "バナーとして表示する部分を選択" |   banner-crop-title: "バナーとして表示する部分を選択" | ||||||
| @@ -477,13 +514,13 @@ desktop/views/components/charts.vue: | |||||||
|     notes: "投稿の増減 (統合)" |     notes: "投稿の増減 (統合)" | ||||||
|     local-notes: "投稿の増減 (ローカル)" |     local-notes: "投稿の増減 (ローカル)" | ||||||
|     remote-notes: "投稿の増減 (リモート)" |     remote-notes: "投稿の増減 (リモート)" | ||||||
|     notes-total: "投稿の累計" |     notes-total: "投稿の積算" | ||||||
|     users: "ユーザーの増減" |     users: "ユーザーの増減" | ||||||
|     users-total: "ユーザーの累計" |     users-total: "ユーザーの積算" | ||||||
|     drive: "ドライブ使用量の増減" |     drive: "ドライブ使用量の増減" | ||||||
|     drive-total: "ドライブ使用量の累計" |     drive-total: "ドライブ使用量の積算" | ||||||
|     drive-files: "ドライブのファイル数の増減" |     drive-files: "ドライブのファイル数の増減" | ||||||
|     drive-files-total: "ドライブのファイル数の累計" |     drive-files-total: "ドライブのファイル数の積算" | ||||||
|     network-requests: "リクエスト" |     network-requests: "リクエスト" | ||||||
|     network-time: "応答時間" |     network-time: "応答時間" | ||||||
|     network-usage: "通信量" |     network-usage: "通信量" | ||||||
| @@ -565,6 +602,7 @@ desktop/views/components/follow-button.vue: | |||||||
|   following: "フォロー中" |   following: "フォロー中" | ||||||
|   follow: "フォロー" |   follow: "フォロー" | ||||||
|   request-pending: "フォロー許可待ち" |   request-pending: "フォロー許可待ち" | ||||||
|  |   follow-processing: "フォロー処理中" | ||||||
|   follow-request: "フォロー申請" |   follow-request: "フォロー申請" | ||||||
| desktop/views/components/followers-window.vue: | desktop/views/components/followers-window.vue: | ||||||
|   followers: "{} のフォロワー" |   followers: "{} のフォロワー" | ||||||
| @@ -675,6 +713,7 @@ desktop/views/components/settings.vue: | |||||||
|   2fa: "二段階認証" |   2fa: "二段階認証" | ||||||
|   other: "その他" |   other: "その他" | ||||||
|   license: "ライセンス" |   license: "ライセンス" | ||||||
|  |   theme: "テーマ" | ||||||
|   behaviour: "動作" |   behaviour: "動作" | ||||||
|   fetch-on-scroll: "スクロールで自動読み込み" |   fetch-on-scroll: "スクロールで自動読み込み" | ||||||
|   fetch-on-scroll-desc: "ページを下までスクロールしたときに自動で追加のコンテンツを読み込みます。" |   fetch-on-scroll-desc: "ページを下までスクロールしたときに自動で追加のコンテンツを読み込みます。" | ||||||
| @@ -691,9 +730,10 @@ desktop/views/components/settings.vue: | |||||||
|   choose-wallpaper: "壁紙を選択" |   choose-wallpaper: "壁紙を選択" | ||||||
|   delete-wallpaper: "壁紙を削除" |   delete-wallpaper: "壁紙を削除" | ||||||
|   dark-mode: "ダークモード" |   dark-mode: "ダークモード" | ||||||
|  |   use-shadow: "UIに影を使用" | ||||||
|  |   rounded-corners: "UIの角を丸める" | ||||||
|   circle-icons: "円形のアイコンを使用" |   circle-icons: "円形のアイコンを使用" | ||||||
|   contrasted-acct: "ユーザー名にコントラストを付ける" |   contrasted-acct: "ユーザー名にコントラストを付ける" | ||||||
|   gradient-window-header: "ウィンドウのタイトルバーにグラデーションを使用" |  | ||||||
|   post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" |   post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" | ||||||
|   suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する" |   suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する" | ||||||
|   show-clock-on-header: "右上に時計を表示する" |   show-clock-on-header: "右上に時計を表示する" | ||||||
| @@ -702,7 +742,6 @@ desktop/views/components/settings.vue: | |||||||
|   show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する" |   show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する" | ||||||
|   show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する" |   show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する" | ||||||
|   show-maps: "マップの自動展開" |   show-maps: "マップの自動展開" | ||||||
|   show-maps-desc: "位置情報が添付された投稿のマップを自動的に展開します。" |  | ||||||
|   sound: "サウンド" |   sound: "サウンド" | ||||||
|   enable-sounds: "サウンドを有効にする" |   enable-sounds: "サウンドを有効にする" | ||||||
|   enable-sounds-desc: "投稿やメッセージを送受信したときなどにサウンドを再生します。この設定はブラウザに記憶されます。" |   enable-sounds-desc: "投稿やメッセージを送受信したときなどにサウンドを再生します。この設定はブラウザに記憶されます。" | ||||||
| @@ -1044,6 +1083,7 @@ mobile/views/components/follow-button.vue: | |||||||
|   following: "フォロー中" |   following: "フォロー中" | ||||||
|   follow: "フォロー" |   follow: "フォロー" | ||||||
|   request-pending: "フォロー許可待ち" |   request-pending: "フォロー許可待ち" | ||||||
|  |   follow-processing: "フォロー処理中" | ||||||
|   follow-request: "フォロー申請" |   follow-request: "フォロー申請" | ||||||
| mobile/views/components/friends-maker.vue: | mobile/views/components/friends-maker.vue: | ||||||
|   title: "気になるユーザーをフォロー" |   title: "気になるユーザーをフォロー" | ||||||
| @@ -1219,6 +1259,7 @@ mobile/views/pages/settings.vue: | |||||||
|   notification-position: "通知の表示" |   notification-position: "通知の表示" | ||||||
|   notification-position-bottom: "下" |   notification-position-bottom: "下" | ||||||
|   notification-position-top: "上" |   notification-position-top: "上" | ||||||
|  |   theme: "テーマ" | ||||||
|   behavior: "動作" |   behavior: "動作" | ||||||
|   fetch-on-scroll: "スクロールで自動読み込み" |   fetch-on-scroll: "スクロールで自動読み込み" | ||||||
|   note-visibility: "投稿の公開範囲" |   note-visibility: "投稿の公開範囲" | ||||||
|   | |||||||
| @@ -285,6 +285,42 @@ common/views/components/media-banner.vue: | |||||||
|   sensitive: "閲覧注意" |   sensitive: "閲覧注意" | ||||||
|   click-to-show: "クリックして表示" |   click-to-show: "クリックして表示" | ||||||
|  |  | ||||||
|  | common/views/components/theme.vue: | ||||||
|  |   light-theme: "非ダークモード時に使用するテーマ" | ||||||
|  |   dark-theme: "ダークモード時に使用するテーマ" | ||||||
|  |   light-themes: "明るいテーマ" | ||||||
|  |   dark-themes: "暗いテーマ" | ||||||
|  |   install-a-theme: "テーマのインストール" | ||||||
|  |   theme-code: "テーマコード" | ||||||
|  |   install: "インストール" | ||||||
|  |   installed: "「{}」をインストールしました" | ||||||
|  |   create-a-theme: "テーマの作成" | ||||||
|  |   save-created-theme: "テーマを保存" | ||||||
|  |   primary-color: "プライマリ カラー" | ||||||
|  |   secondary-color: "セカンダリ カラー" | ||||||
|  |   text-color: "文字色" | ||||||
|  |   base-theme: "ベーステーマ" | ||||||
|  |   base-theme-light: "Light" | ||||||
|  |   base-theme-dark: "Dark" | ||||||
|  |   theme-name: "テーマ名" | ||||||
|  |   preview-created-theme: "プレビュー" | ||||||
|  |   invalid-theme: "テーマが正しくありません。" | ||||||
|  |   already-installed: "既にそのテーマはインストールされています。" | ||||||
|  |   saved: "保存しました" | ||||||
|  |   manage-themes: "テーマの管理" | ||||||
|  |   builtin-themes: "標準テーマ" | ||||||
|  |   my-themes: "マイテーマ" | ||||||
|  |   installed-themes: "インストールされたテーマ" | ||||||
|  |   select-theme: "テーマを選択してください" | ||||||
|  |   uninstall: "アンインストール" | ||||||
|  |   uninstalled: "「{}」をアンインストールしました" | ||||||
|  |   author: "作者" | ||||||
|  |   desc: "説明" | ||||||
|  |   export: "エクスポート" | ||||||
|  |   import: "インポート" | ||||||
|  |   import-by-code: "またはコードをペースト" | ||||||
|  |   theme-name-required: "テーマ名は必須です。" | ||||||
|  |  | ||||||
| common/views/components/cw-button.vue: | common/views/components/cw-button.vue: | ||||||
|   hide: "隠す" |   hide: "隠す" | ||||||
|   show: "もっと見る" |   show: "もっと見る" | ||||||
| @@ -328,6 +364,7 @@ common/views/components/note-menu.vue: | |||||||
|   copy-link: "リンクをコピー" |   copy-link: "リンクをコピー" | ||||||
|   favorite: "お気に入り" |   favorite: "お気に入り" | ||||||
|   pin: "ピン留め" |   pin: "ピン留め" | ||||||
|  |   unpin: "ピン留め解除" | ||||||
|   delete: "削除" |   delete: "削除" | ||||||
|   delete-confirm: "この投稿を削除しますか?" |   delete-confirm: "この投稿を削除しますか?" | ||||||
|   remote: "投稿元で見る" |   remote: "投稿元で見る" | ||||||
| @@ -488,6 +525,7 @@ common/views/pages/follow.vue: | |||||||
|   following: "フォロー中" |   following: "フォロー中" | ||||||
|   follow: "フォロー" |   follow: "フォロー" | ||||||
|   request-pending: "フォロー許可待ち" |   request-pending: "フォロー許可待ち" | ||||||
|  |   follow-processing: "フォロー処理中" | ||||||
|   follow-request: "フォロー申請" |   follow-request: "フォロー申請" | ||||||
|  |  | ||||||
| desktop: | desktop: | ||||||
| @@ -531,13 +569,13 @@ desktop/views/components/charts.vue: | |||||||
|     notes: "投稿の増減 (統合)" |     notes: "投稿の増減 (統合)" | ||||||
|     local-notes: "投稿の増減 (ローカル)" |     local-notes: "投稿の増減 (ローカル)" | ||||||
|     remote-notes: "投稿の増減 (リモート)" |     remote-notes: "投稿の増減 (リモート)" | ||||||
|     notes-total: "投稿の累計" |     notes-total: "投稿の積算" | ||||||
|     users: "ユーザーの増減" |     users: "ユーザーの増減" | ||||||
|     users-total: "ユーザーの累計" |     users-total: "ユーザーの積算" | ||||||
|     drive: "ドライブ使用量の増減" |     drive: "ドライブ使用量の増減" | ||||||
|     drive-total: "ドライブ使用量の累計" |     drive-total: "ドライブ使用量の積算" | ||||||
|     drive-files: "ドライブのファイル数の増減" |     drive-files: "ドライブのファイル数の増減" | ||||||
|     drive-files-total: "ドライブのファイル数の累計" |     drive-files-total: "ドライブのファイル数の積算" | ||||||
|     network-requests: "リクエスト" |     network-requests: "リクエスト" | ||||||
|     network-time: "応答時間" |     network-time: "応答時間" | ||||||
|     network-usage: "通信量" |     network-usage: "通信量" | ||||||
| @@ -630,6 +668,7 @@ desktop/views/components/follow-button.vue: | |||||||
|   following: "フォロー中" |   following: "フォロー中" | ||||||
|   follow: "フォロー" |   follow: "フォロー" | ||||||
|   request-pending: "フォロー許可待ち" |   request-pending: "フォロー許可待ち" | ||||||
|  |   follow-processing: "フォロー処理中" | ||||||
|   follow-request: "フォロー申請" |   follow-request: "フォロー申請" | ||||||
|  |  | ||||||
| desktop/views/components/followers-window.vue: | desktop/views/components/followers-window.vue: | ||||||
| @@ -761,6 +800,7 @@ desktop/views/components/settings.vue: | |||||||
|   2fa: "二段階認証" |   2fa: "二段階認証" | ||||||
|   other: "その他" |   other: "その他" | ||||||
|   license: "ライセンス" |   license: "ライセンス" | ||||||
|  |   theme: "テーマ" | ||||||
|  |  | ||||||
|   behaviour: "動作" |   behaviour: "動作" | ||||||
|   fetch-on-scroll: "スクロールで自動読み込み" |   fetch-on-scroll: "スクロールで自動読み込み" | ||||||
| @@ -783,7 +823,6 @@ desktop/views/components/settings.vue: | |||||||
|   rounded-corners: "UIの角を丸める" |   rounded-corners: "UIの角を丸める" | ||||||
|   circle-icons: "円形のアイコンを使用" |   circle-icons: "円形のアイコンを使用" | ||||||
|   contrasted-acct: "ユーザー名にコントラストを付ける" |   contrasted-acct: "ユーザー名にコントラストを付ける" | ||||||
|   gradient-window-header: "ウィンドウのタイトルバーにグラデーションを使用" |  | ||||||
|   post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" |   post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" | ||||||
|   suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する" |   suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する" | ||||||
|   show-clock-on-header: "右上に時計を表示する" |   show-clock-on-header: "右上に時計を表示する" | ||||||
| @@ -792,7 +831,6 @@ desktop/views/components/settings.vue: | |||||||
|   show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する" |   show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する" | ||||||
|   show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する" |   show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する" | ||||||
|   show-maps: "マップの自動展開" |   show-maps: "マップの自動展開" | ||||||
|   show-maps-desc: "位置情報が添付された投稿のマップを自動的に展開します。" |  | ||||||
|  |  | ||||||
|   sound: "サウンド" |   sound: "サウンド" | ||||||
|   enable-sounds: "サウンドを有効にする" |   enable-sounds: "サウンドを有効にする" | ||||||
| @@ -1207,6 +1245,7 @@ mobile/views/components/follow-button.vue: | |||||||
|   following: "フォロー中" |   following: "フォロー中" | ||||||
|   follow: "フォロー" |   follow: "フォロー" | ||||||
|   request-pending: "フォロー許可待ち" |   request-pending: "フォロー許可待ち" | ||||||
|  |   follow-processing: "フォロー処理中" | ||||||
|   follow-request: "フォロー申請" |   follow-request: "フォロー申請" | ||||||
|  |  | ||||||
| mobile/views/components/friends-maker.vue: | mobile/views/components/friends-maker.vue: | ||||||
| @@ -1418,6 +1457,7 @@ mobile/views/pages/settings.vue: | |||||||
|   notification-position: "通知の表示" |   notification-position: "通知の表示" | ||||||
|   notification-position-bottom: "下" |   notification-position-bottom: "下" | ||||||
|   notification-position-top: "上" |   notification-position-top: "上" | ||||||
|  |   theme: "テーマ" | ||||||
|   behavior: "動作" |   behavior: "動作" | ||||||
|   fetch-on-scroll: "スクロールで自動読み込み" |   fetch-on-scroll: "スクロールで自動読み込み" | ||||||
|   note-visibility: "投稿の公開範囲" |   note-visibility: "投稿の公開範囲" | ||||||
|   | |||||||
| @@ -264,9 +264,44 @@ common/views/components/connect-failed.troubleshooter.vue: | |||||||
| common/views/components/media-banner.vue: | common/views/components/media-banner.vue: | ||||||
|   sensitive: "見せたらあかん" |   sensitive: "見せたらあかん" | ||||||
|   click-to-show: "押してみ、見せたるわ" |   click-to-show: "押してみ、見せたるわ" | ||||||
|  | common/views/components/theme.vue: | ||||||
|  |   light-theme: "非ダークモード時に使用するテーマ" | ||||||
|  |   dark-theme: "ダークモード時に使用するテーマ" | ||||||
|  |   light-themes: "明るいテーマ" | ||||||
|  |   dark-themes: "暗いテーマ" | ||||||
|  |   install-a-theme: "テーマのインストール" | ||||||
|  |   theme-code: "テーマコード" | ||||||
|  |   install: "インストール" | ||||||
|  |   installed: "「{}」をインストールしました" | ||||||
|  |   create-a-theme: "テーマの作成" | ||||||
|  |   save-created-theme: "テーマを保存" | ||||||
|  |   primary-color: "プライマリ カラー" | ||||||
|  |   secondary-color: "セカンダリ カラー" | ||||||
|  |   text-color: "文字色" | ||||||
|  |   base-theme: "ベーステーマ" | ||||||
|  |   base-theme-light: "Light" | ||||||
|  |   base-theme-dark: "Dark" | ||||||
|  |   theme-name: "テーマ名" | ||||||
|  |   preview-created-theme: "プレビュー" | ||||||
|  |   invalid-theme: "テーマが正しくありません。" | ||||||
|  |   already-installed: "既にそのテーマはインストールされています。" | ||||||
|  |   saved: "保存しました" | ||||||
|  |   manage-themes: "テーマの管理" | ||||||
|  |   builtin-themes: "標準テーマ" | ||||||
|  |   my-themes: "マイテーマ" | ||||||
|  |   installed-themes: "インストールされたテーマ" | ||||||
|  |   select-theme: "テーマを選択してください" | ||||||
|  |   uninstall: "アンインストール" | ||||||
|  |   uninstalled: "「{}」をアンインストールしました" | ||||||
|  |   author: "作者" | ||||||
|  |   desc: "説明" | ||||||
|  |   export: "エクスポート" | ||||||
|  |   import: "インポート" | ||||||
|  |   import-by-code: "またはコードをペースト" | ||||||
|  |   theme-name-required: "テーマ名は必須です。" | ||||||
| common/views/components/cw-button.vue: | common/views/components/cw-button.vue: | ||||||
|   hide: "見せへんわ" |   hide: "もうええわ" | ||||||
|   show: "もっとあるやろ!" |   show: "見たいやろ?" | ||||||
| common/views/components/messaging.vue: | common/views/components/messaging.vue: | ||||||
|   search-user: "ユーザーを探す" |   search-user: "ユーザーを探す" | ||||||
|   you: "あんさん" |   you: "あんさん" | ||||||
| @@ -301,6 +336,7 @@ common/views/components/note-menu.vue: | |||||||
|   copy-link: "リンクをコピー" |   copy-link: "リンクをコピー" | ||||||
|   favorite: "お気に入り" |   favorite: "お気に入り" | ||||||
|   pin: "ピン留め" |   pin: "ピン留め" | ||||||
|  |   unpin: "ピン留めやめる" | ||||||
|   delete: "ほかす" |   delete: "ほかす" | ||||||
|   delete-confirm: "この投稿を削除してもええか?" |   delete-confirm: "この投稿を削除してもええか?" | ||||||
|   remote: "投稿元に行ってみよか" |   remote: "投稿元に行ってみよか" | ||||||
| @@ -431,7 +467,7 @@ common/views/widgets/tips.vue: | |||||||
|   tips-line19: "いくつかのウィンドウはブラウザの外に切り離すことができんで" |   tips-line19: "いくつかのウィンドウはブラウザの外に切り離すことができんで" | ||||||
|   tips-line20: "カレンダーウィジェットのパーセンテージは、経過の割合を示してんねん" |   tips-line20: "カレンダーウィジェットのパーセンテージは、経過の割合を示してんねん" | ||||||
|   tips-line21: "APIをつこてbotの開発なども行えるで" |   tips-line21: "APIをつこてbotの開発なども行えるで" | ||||||
|   tips-line23: "まゆかわいいよまゆ" |   tips-line23: "ウチのタコちゃんかわええやろ…今の突っ込むところや!" | ||||||
|   tips-line24: "Misskeyは2014年にサービスを開始したんよ" |   tips-line24: "Misskeyは2014年にサービスを開始したんよ" | ||||||
|   tips-line25: "対応ブラウザやったらMisskeyを開いとらんでも通知を受け取れんで" |   tips-line25: "対応ブラウザやったらMisskeyを開いとらんでも通知を受け取れんで" | ||||||
| common/views/pages/follow.vue: | common/views/pages/follow.vue: | ||||||
| @@ -439,6 +475,7 @@ common/views/pages/follow.vue: | |||||||
|   following: "フォローしとる" |   following: "フォローしとる" | ||||||
|   follow: "フォロー" |   follow: "フォロー" | ||||||
|   request-pending: "フォローの許し待っとる" |   request-pending: "フォローの許し待っとる" | ||||||
|  |   follow-processing: "フォロー処理中" | ||||||
|   follow-request: "フォロー許してくれや!言うてみる" |   follow-request: "フォロー許してくれや!言うてみる" | ||||||
| desktop: | desktop: | ||||||
|   banner-crop-title: "どこバナーとして出す?" |   banner-crop-title: "どこバナーとして出す?" | ||||||
| @@ -453,10 +490,10 @@ desktop: | |||||||
|   choose-avatar: "アバターにする画像選んでや" |   choose-avatar: "アバターにする画像選んでや" | ||||||
|   invalid-filetype: "この形式のファイル無理やねん" |   invalid-filetype: "この形式のファイル無理やねん" | ||||||
| desktop/views/components/activity.chart.vue: | desktop/views/components/activity.chart.vue: | ||||||
|   total: "Black ... Total" |   total: "黒いの… 全部" | ||||||
|   notes: "Blue ... Notes" |   notes: "青いの… 投稿" | ||||||
|   replies: "Red ... Replies" |   replies: "赤いの… 返信" | ||||||
|   renotes: "Green ... Renotes" |   renotes: "みどり… Renotes" | ||||||
| desktop/views/components/activity.vue: | desktop/views/components/activity.vue: | ||||||
|   title: "アクティビティ" |   title: "アクティビティ" | ||||||
|   toggle: "表示変える" |   toggle: "表示変える" | ||||||
| @@ -477,13 +514,13 @@ desktop/views/components/charts.vue: | |||||||
|     notes: "投稿の増減(統合)" |     notes: "投稿の増減(統合)" | ||||||
|     local-notes: "投稿の増減 (ローカル)" |     local-notes: "投稿の増減 (ローカル)" | ||||||
|     remote-notes: "投稿の増減 (リモート)" |     remote-notes: "投稿の増減 (リモート)" | ||||||
|     notes-total: "全部の投稿" |     notes-total: "投稿の積算" | ||||||
|     users: "ユーザーの増減" |     users: "ユーザーの増減" | ||||||
|     users-total: "ユーザーの累計" |     users-total: "ユーザーの積算" | ||||||
|     drive: "ドライブ使用量の増減" |     drive: "ドライブ使用量の増減" | ||||||
|     drive-total: "ドライブ使用量の累計" |     drive-total: "ドライブ使用量の積算" | ||||||
|     drive-files: "ドライブのファイル数の増減" |     drive-files: "ドライブのファイル数の増減" | ||||||
|     drive-files-total: "ドライブのファイル数の累計" |     drive-files-total: "ドライブのファイル数の積算" | ||||||
|     network-requests: "リクエスト" |     network-requests: "リクエスト" | ||||||
|     network-time: "応答時間" |     network-time: "応答時間" | ||||||
|     network-usage: "通信量" |     network-usage: "通信量" | ||||||
| @@ -565,6 +602,7 @@ desktop/views/components/follow-button.vue: | |||||||
|   following: "フォローしとる" |   following: "フォローしとる" | ||||||
|   follow: "フォロー" |   follow: "フォロー" | ||||||
|   request-pending: "フォローの許し待っとる" |   request-pending: "フォローの許し待っとる" | ||||||
|  |   follow-processing: "フォロー処理中" | ||||||
|   follow-request: "フォロー許してくれや!言うてみる" |   follow-request: "フォロー許してくれや!言うてみる" | ||||||
| desktop/views/components/followers-window.vue: | desktop/views/components/followers-window.vue: | ||||||
|   followers: "{} のフォロワー" |   followers: "{} のフォロワー" | ||||||
| @@ -588,7 +626,7 @@ desktop/views/components/home.vue: | |||||||
|   add: "増やす" |   add: "増やす" | ||||||
| desktop/views/input-dialog.vue: | desktop/views/input-dialog.vue: | ||||||
|   cancel: "やめとくわ" |   cancel: "やめとくわ" | ||||||
|   ok: "決定" |   ok: "これや!" | ||||||
| desktop/views/components/messaging-room-window.vue: | desktop/views/components/messaging-room-window.vue: | ||||||
|   title: "メッセージ:" |   title: "メッセージ:" | ||||||
| desktop/views/components/messaging-window.vue: | desktop/views/components/messaging-window.vue: | ||||||
| @@ -675,6 +713,7 @@ desktop/views/components/settings.vue: | |||||||
|   2fa: "二段階認証" |   2fa: "二段階認証" | ||||||
|   other: "その他" |   other: "その他" | ||||||
|   license: "ライセンス" |   license: "ライセンス" | ||||||
|  |   theme: "テーマ" | ||||||
|   behaviour: "動き" |   behaviour: "動き" | ||||||
|   fetch-on-scroll: "スクロールしたらもっと見せてや" |   fetch-on-scroll: "スクロールしたらもっと見せてや" | ||||||
|   fetch-on-scroll-desc: "ページを下までスクロールしたときに自動でもっとコンテンツを読み込むで。" |   fetch-on-scroll-desc: "ページを下までスクロールしたときに自動でもっとコンテンツを読み込むで。" | ||||||
| @@ -691,9 +730,10 @@ desktop/views/components/settings.vue: | |||||||
|   choose-wallpaper: "壁紙選ぶ" |   choose-wallpaper: "壁紙選ぶ" | ||||||
|   delete-wallpaper: "壁紙ほかす" |   delete-wallpaper: "壁紙ほかす" | ||||||
|   dark-mode: "夜にすんで" |   dark-mode: "夜にすんで" | ||||||
|  |   use-shadow: "UIに影付けたる" | ||||||
|  |   rounded-corners: "みんなまぁるくUI変更" | ||||||
|   circle-icons: "アイコンもタコ焼きも丸いやんな?" |   circle-icons: "アイコンもタコ焼きも丸いやんな?" | ||||||
|   contrasted-acct: "ユーザー名ようわからんし見やすしといて" |   contrasted-acct: "ユーザー名ようわからんし見やすしといて" | ||||||
|   gradient-window-header: "ウィンドウのタイトルバーにグラデーション付ける" |  | ||||||
|   post-form-on-timeline: "タイムラインの上の方で投稿できるようにせえへん?" |   post-form-on-timeline: "タイムラインの上の方で投稿できるようにせえへん?" | ||||||
|   suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示すんで" |   suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示すんで" | ||||||
|   show-clock-on-header: "右上をカリヨン広場にする(時計表示)" |   show-clock-on-header: "右上をカリヨン広場にする(時計表示)" | ||||||
| @@ -702,7 +742,6 @@ desktop/views/components/settings.vue: | |||||||
|   show-renoted-my-notes: "わしのRenoteもタイムライン載せてくれや" |   show-renoted-my-notes: "わしのRenoteもタイムライン載せてくれや" | ||||||
|   show-local-renotes: "ローカル投稿のRenoteも見たいんや" |   show-local-renotes: "ローカル投稿のRenoteも見たいんや" | ||||||
|   show-maps: "地図勝手にバァーって開いてくれ" |   show-maps: "地図勝手にバァーって開いてくれ" | ||||||
|   show-maps-desc: "どこにおるんかわかっとる投稿の地図は自動で見せるで" |  | ||||||
|   sound: "サウンド" |   sound: "サウンド" | ||||||
|   enable-sounds: "サウンド鳴らす" |   enable-sounds: "サウンド鳴らす" | ||||||
|   enable-sounds-desc: "投稿やメッセージもろたとき、音鳴らしたるわ。大丈夫や、この設定はブラウザが覚えてくれとる。" |   enable-sounds-desc: "投稿やメッセージもろたとき、音鳴らしたるわ。大丈夫や、この設定はブラウザが覚えてくれとる。" | ||||||
| @@ -793,7 +832,7 @@ desktop/views/components/settings.profile.vue: | |||||||
|   birthday: "誕生日" |   birthday: "誕生日" | ||||||
|   save: "保存" |   save: "保存" | ||||||
|   locked-account: "アカウント守る" |   locked-account: "アカウント守る" | ||||||
|   is-locked: "他人のフォローは許してからや!" |   is-locked: "他人のフォローは許可してからや!" | ||||||
|   other: "その他" |   other: "その他" | ||||||
|   is-bot: "このアカウントはBotやで" |   is-bot: "このアカウントはBotやで" | ||||||
|   is-cat: "このアカウントはCatやで" |   is-cat: "このアカウントはCatやで" | ||||||
| @@ -1044,6 +1083,7 @@ mobile/views/components/follow-button.vue: | |||||||
|   following: "フォローしとる" |   following: "フォローしとる" | ||||||
|   follow: "フォロー" |   follow: "フォロー" | ||||||
|   request-pending: "フォローの許し待っとる" |   request-pending: "フォローの許し待っとる" | ||||||
|  |   follow-processing: "フォロー処理中" | ||||||
|   follow-request: "フォロー許してくれや!言うてみる" |   follow-request: "フォロー許してくれや!言うてみる" | ||||||
| mobile/views/components/friends-maker.vue: | mobile/views/components/friends-maker.vue: | ||||||
|   title: "おもろそうやな" |   title: "おもろそうやな" | ||||||
| @@ -1185,97 +1225,98 @@ mobile/views/pages/settings/settings.profile.vue: | |||||||
|   is-cat: "このアカウントはCatや" |   is-cat: "このアカウントはCatや" | ||||||
|   is-locked: "他人のフォローは許してからや!" |   is-locked: "他人のフォローは許してからや!" | ||||||
|   advanced: "その他" |   advanced: "その他" | ||||||
|   privacy: "プライバシー" |   privacy: "プライバシー⇔オカンの年齢" | ||||||
|   save: "保存" |   save: "保存" | ||||||
|   saved: "プロフィールを保存しました" |   saved: "プロフィールを保存したで" | ||||||
|   uploading: "アップロード中" |   uploading: "アップロードしとるで…" | ||||||
|   upload-failed: "アップロードに失敗しました" |   upload-failed: "これアップロードでけへんわ" | ||||||
| mobile/views/pages/search.vue: | mobile/views/pages/search.vue: | ||||||
|   search: "検索" |   search: "探す" | ||||||
|   empty: "「{}」に関する投稿は見つかりませんでした。" |   empty: "ワイは「{}」なんて投稿知らんわ、無いんちゃう?知らんけど。" | ||||||
|   not-found: "「{}」に関する投稿は見つかりませんでした。" |   not-found: "ワイは「{}」なんて投稿知らんわ、無いんちゃう?知らんけど。" | ||||||
| mobile/views/pages/selectdrive.vue: | mobile/views/pages/selectdrive.vue: | ||||||
|   select-file: "ファイルを選択" |   select-file: "ファイル選んでや" | ||||||
| mobile/views/pages/settings.vue: | mobile/views/pages/settings.vue: | ||||||
|   signed-in-as: "{}としてサインイン中" |   signed-in-as: "あんたは橋の下で拾った{}や!" | ||||||
|   lang: "言語" |   lang: "言語" | ||||||
|   lang-tip: "変更はページの再読み込み後に反映されます。" |   lang-tip: "ページもっぺん読み込んだら反映したるで。" | ||||||
|   recommended: "推奨" |   recommended: "これええで" | ||||||
|   auto: "自動" |   auto: "勝手にやる" | ||||||
|   specify-language: "言語を指定" |   specify-language: "言語選びや" | ||||||
|   design: "デザインと表示" |   design: "見た感じ" | ||||||
|   dark-mode: "ダークモード" |   dark-mode: "ナイトゲームや!" | ||||||
|   i-am-under-limited-internet: "私は通信を制限されている" |   i-am-under-limited-internet: "電波がバァーっといけへんねん" | ||||||
|   circle-icons: "円形のアイコンを使用" |   circle-icons: "アイコンもタコ焼きも丸いやんな?" | ||||||
|   contrasted-acct: "ユーザー名にコントラストを付ける" |   contrasted-acct: "ユーザー名ようわからんし見やすしといて" | ||||||
|   timeline: "タイムライン" |   timeline: "タイムライン" | ||||||
|   show-reply-target: "リプライ先を表示する" |   show-reply-target: "どこにリプライするんや見せて" | ||||||
|   show-my-renotes: "自分の行ったRenoteを表示する" |   show-my-renotes: "あんたのしたRenoteも出すで" | ||||||
|   show-renoted-my-notes: "自分の投稿のRenoteを表示する" |   show-renoted-my-notes: "あんたの言うたことのRenoteも出すで" | ||||||
|   show-local-renotes: "ローカルの投稿のRenoteを表示する" |   show-local-renotes: "ローカル投稿のRenoteも出すで" | ||||||
|   post-style: "投稿の表示スタイル" |   post-style: "投稿の表示スタイル" | ||||||
|   post-style-standard: "標準" |   post-style-standard: "標準" | ||||||
|   post-style-smart: "べっぴんさん" |   post-style-smart: "べっぴんさん" | ||||||
|   notification-position: "通知の表示" |   notification-position: "通知どこ見せる?" | ||||||
|   notification-position-bottom: "下" |   notification-position-bottom: "ミナミ" | ||||||
|   notification-position-top: "上" |   notification-position-top: "キタ" | ||||||
|   behavior: "動作" |   theme: "テーマ" | ||||||
|   fetch-on-scroll: "スクロールで自動読み込み" |   behavior: "動き" | ||||||
|  |   fetch-on-scroll: "スクロールしたらもっと見せてや" | ||||||
|   note-visibility: "投稿の公開範囲" |   note-visibility: "投稿の公開範囲" | ||||||
|   default-note-visibility: "デフォルトの公開範囲" |   default-note-visibility: "もとからの公開範囲" | ||||||
|   remember-note-visibility: "投稿の公開範囲を記憶する" |   remember-note-visibility: "投稿の公開範囲おぼえといて" | ||||||
|   disable-via-mobile: "「モバイルからの投稿」フラグを付けない" |   disable-via-mobile: "「モバイルからの投稿」フラグなんて要らんわ" | ||||||
|   load-raw-images: "添付された画像を高画質で表示する" |   load-raw-images: "添付された画像もべっぴんさんのままにしといてな" | ||||||
|   load-remote-media: "リモートサーバーのメディアを表示する" |   load-remote-media: "東京とか、リモートサーバーのメディアも見せてや" | ||||||
|   twitter: "Twitter連携" |   twitter: "鳥さんとも連携や!" | ||||||
|   twitter-connect: "Twitterアカウントに接続する" |   twitter-connect: "鳥さん邪魔すんで" | ||||||
|   twitter-reconnect: "再接続する" |   twitter-reconnect: "もっぺん繋ぎ直すで" | ||||||
|   twitter-disconnect: "切断する" |   twitter-disconnect: "邪魔するんやったら帰って" | ||||||
|   update: "Misskey Update" |   update: "あんたのMisskeyいつのや?" | ||||||
|   version: "バージョン:" |   version: "バージョン:" | ||||||
|   latest-version: "最新のバージョン:" |   latest-version: "いっちゃん新しいやつ:" | ||||||
|   update-checking: "アップデートを確認中" |   update-checking: "アップデートはあらへんか…" | ||||||
|   check-for-updates: "アップデートを確認" |   check-for-updates: "アップデートあるんかな?" | ||||||
|   no-updates: "利用可能な更新はありません" |   no-updates: "アップデートあらへんわ" | ||||||
|   no-updates-desc: "お使いのMisskeyは最新です。" |   no-updates-desc: "つこてるMisskeyは最新や!" | ||||||
|   update-available: "新しいバージョンが利用可能です" |   update-available: "もっとええバージョンがあるで" | ||||||
|   update-available-desc: "ページを再度読み込みすると更新が適用されます。" |   update-available-desc: "もっぺんページ読み込んだら新しなるで" | ||||||
|   settings: "設定" |   settings: "設定" | ||||||
|   signout: "サインアウト" |   signout: "さいなら" | ||||||
|   sound: "サウンド" |   sound: "サウンド" | ||||||
|   enable-sounds: "サウンドを有効にする" |   enable-sounds: "サウンド鳴らす" | ||||||
| mobile/views/pages/user.vue: | mobile/views/pages/user.vue: | ||||||
|   follows-you: "フォローされています" |   follows-you: "フォローされとるで" | ||||||
|   following: "フォロー" |   following: "フォロー" | ||||||
|   followers: "フォロワー" |   followers: "フォロワー" | ||||||
|   notes: "投稿" |   notes: "投稿" | ||||||
|   overview: "概要" |   overview: "こんなやつ" | ||||||
|   timeline: "タイムライン" |   timeline: "タイムライン" | ||||||
|   media: "メディア" |   media: "メディア" | ||||||
|   is-suspended: "このユーザーは凍結されています。" |   is-suspended: "このユーザーはあかんわ。凍結されとる。" | ||||||
|   is-remote: "このユーザーはリモートユーザーです。" |   is-remote: "このユーザーは東京とかそこらへんのリモートユーザーや。" | ||||||
|   view-remote: "正確な情報を見る" |   view-remote: "ちゃんとした情報を見る" | ||||||
| mobile/views/pages/user/home.vue: | mobile/views/pages/user/home.vue: | ||||||
|   recent-notes: "最近の投稿" |   recent-notes: "最近儲かりまっか?" | ||||||
|   images: "画像" |   images: "画像" | ||||||
|   activity: "アクティビティ" |   activity: "やっとること" | ||||||
|   keywords: "キーワード" |   keywords: "キーワード" | ||||||
|   domains: "頻出ドメイン" |   domains: "よく出るドメイン" | ||||||
|   frequently-replied-users: "よく会話するユーザー" |   frequently-replied-users: "よう話しとるユーザー" | ||||||
|   followers-you-know: "知り合いのフォロワー" |   followers-you-know: "知っとるフォロワー" | ||||||
|   last-used-at: "最終ログイン" |   last-used-at: "最後いつ来た?" | ||||||
| mobile/views/pages/user/home.followers-you-know.vue: | mobile/views/pages/user/home.followers-you-know.vue: | ||||||
|   loading: "読み込み中" |   loading: "読み込んどる…" | ||||||
|   no-users: "知り合いのユーザーはいません" |   no-users: "知っとるユーザーは居らん" | ||||||
| mobile/views/pages/user/home.friends.vue: | mobile/views/pages/user/home.friends.vue: | ||||||
|   loading: "読み込み中" |   loading: "読み込んどる…" | ||||||
|   no-users: "よく会話するユーザーはいません" |   no-users: "よう話すユーザーは居らん" | ||||||
| mobile/views/pages/user/home.notes.vue: | mobile/views/pages/user/home.notes.vue: | ||||||
|   loading: "読み込み中" |   loading: "読み込んどる…" | ||||||
|   no-notes: "投稿はありません" |   no-notes: "投稿はあらへん" | ||||||
| mobile/views/pages/user/home.photos.vue: | mobile/views/pages/user/home.photos.vue: | ||||||
|   loading: "読み込み中" |   loading: "読み込んどる…" | ||||||
|   no-photos: "写真はありません" |   no-photos: "写真はあらへんで" | ||||||
| docs: | docs: | ||||||
|   edit-this-page-on-github: "間違いや改善点を見つけましたか?" |   edit-this-page-on-github: "間違いや改善点を見つけましたか?" | ||||||
|   edit-this-page-on-github-link: "このページをGitHubで編集" |   edit-this-page-on-github-link: "このページをGitHubで編集" | ||||||
|   | |||||||
| @@ -3,20 +3,20 @@ meta: | |||||||
|   lang: "한국어" |   lang: "한국어" | ||||||
|   divider: "" |   divider: "" | ||||||
| common: | common: | ||||||
|   misskey: "A ⭐ of fediverse" |   misskey: "연합우주의 ⭐" | ||||||
|   about-title: "A ⭐ of fediverse." |   about-title: "연합우주의 ⭐." | ||||||
|   about: "Misskey를 찾아 주셔서 감사합니다. Misskey은 지구에서 태어난 <b>분산 마이크로 블로그 SNS </b> 입니다. Fediverse (다양한 SNS로 구성되는 우주)에 존재하는 다른 SNS와 상호 연결되어 있습니다. 잠시 도시의 번잡함에서 벗어나 새로운 인터넷에 다이브 해 보지 않겠습니까." |   about: "Misskey를 찾아 주셔서 감사합니다. Misskey은 지구에서 태어난 <b>분산 마이크로 블로그 SNS </b> 입니다. Fediverse (다양한 SNS로 구성되는 우주)에 존재하는 다른 SNS와 상호 연결되어 있습니다. 잠시 도시의 번잡함에서 벗어나 새로운 인터넷에 다이브 해 보지 않겠습니까." | ||||||
|   intro: |   intro: | ||||||
|     title: "Misskeyって?" |     title: "Misskey란?" | ||||||
|     about: "Misskeyはオープンソースの<b>分散型マイクロブログSNS</b>です。リッチで高度にカスタマイズできるUI、投稿へのリアクション、ファイルを一元管理できるドライブなど、先進的な機能を揃えています。また、Fediverseと呼ばれるネットワークに接続できるため、他のSNSともやり取りできます。例えば、あなたが何か投稿すると、その投稿はMisskeyだけでなく他のSNSにも伝わります。ちょうどある惑星から他の惑星に電波を発信している様子をイメージしてください。" |     about: "Misskeyはオープンソースの<b>分散型マイクロブログSNS</b>です。リッチで高度にカスタマイズできるUI、投稿へのリアクション、ファイルを一元管理できるドライブなど、先進的な機能を揃えています。また、Fediverseと呼ばれるネットワークに接続できるため、他のSNSともやり取りできます。例えば、あなたが何か投稿すると、その投稿はMisskeyだけでなく他のSNSにも伝わります。ちょうどある惑星から他の惑星に電波を発信している様子をイメージしてください。" | ||||||
|     features: "特徴" |     features: "특징" | ||||||
|     rich-contents: "投稿" |     rich-contents: "게시" | ||||||
|     rich-contents-desc: "自分の考え、話題の出来事、皆と共有したいことについて発信してください。必要であれば、様々な構文を使って投稿を装飾したり、好きな画像、動画などのファイルやアンケートを添付することもできます。" |     rich-contents-desc: "自分の考え、話題の出来事、皆と共有したいことについて発信してください。必要であれば、様々な構文を使って投稿を装飾したり、好きな画像、動画などのファイルやアンケートを添付することもできます。" | ||||||
|     reaction: "リアクション" |     reaction: "반응" | ||||||
|     reaction-desc: "あなたの気持ちを伝える最も簡単な方法です。Misskeyは、他のユーザーの投稿に様々なリアクションを付けることができます。いちどMisskeyのリアクション機能を体験してしまうと、もう「いいね」の概念しか存在しないSNSには戻れなくなるかもしれません。" |     reaction-desc: "あなたの気持ちを伝える最も簡単な方法です。Misskeyは、他のユーザーの投稿に様々なリアクションを付けることができます。いちどMisskeyのリアクション機能を体験してしまうと、もう「いいね」の概念しか存在しないSNSには戻れなくなるかもしれません。" | ||||||
|     ui: "インターフェース" |     ui: "인터페이스" | ||||||
|     ui-desc: "どのようなUIが使いやすいかは人それぞれです。だから、Misskeyは自由度の高いUIを持っています。レイアウトやデザインを調整したり、カスタマイズ可能な様々なウィジェットを配置したりして、自分だけのホームを作ってください。" |     ui-desc: "どのようなUIが使いやすいかは人それぞれです。だから、Misskeyは自由度の高いUIを持っています。レイアウトやデザインを調整したり、カスタマイズ可能な様々なウィジェットを配置したりして、自分だけのホームを作ってください。" | ||||||
|     drive: "ドライブ" |     drive: "드라이브" | ||||||
|     drive-desc: "以前投稿したことのある画像をまた投稿したくなったことはありませんか?もしくは、アップロードしたファイルをフォルダ分けして整理したくなったことはありませんか?Misskeyの根幹に組み込まれたドライブ機能によってそれらが解決します。ファイルの共有も簡単です。" |     drive-desc: "以前投稿したことのある画像をまた投稿したくなったことはありませんか?もしくは、アップロードしたファイルをフォルダ分けして整理したくなったことはありませんか?Misskeyの根幹に組み込まれたドライブ機能によってそれらが解決します。ファイルの共有も簡単です。" | ||||||
|     outro: "他にもMisskeyにしかない機能はまだまだあるので、ぜひあなた自身の目で確かめてください。Misskeyは分散型SNSなので、このインスタンスが気に入らなければ他のインスタンスを試すこともできます。それでは、GLHF!" |     outro: "他にもMisskeyにしかない機能はまだまだあるので、ぜひあなた自身の目で確かめてください。Misskeyは分散型SNSなので、このインスタンスが気に入らなければ他のインスタンスを試すこともできます。それでは、GLHF!" | ||||||
|   adblock: |   adblock: | ||||||
| @@ -71,7 +71,7 @@ common: | |||||||
|     friday: "금요일" |     friday: "금요일" | ||||||
|     saturday: "토요일" |     saturday: "토요일" | ||||||
|   reactions: |   reactions: | ||||||
|     like: "いいね" |     like: "좋아요" | ||||||
|     love: "좋아" |     love: "좋아" | ||||||
|     laugh: "크크" |     laugh: "크크" | ||||||
|     hmm: "음..." |     hmm: "음..." | ||||||
| @@ -82,14 +82,14 @@ common: | |||||||
|     rip: "RIP" |     rip: "RIP" | ||||||
|     pudding: "Pudding" |     pudding: "Pudding" | ||||||
|   note-visibility: |   note-visibility: | ||||||
|     public: "公開" |     public: "공개" | ||||||
|     home: "ホーム" |     home: "홈" | ||||||
|     home-desc: "ホームタイムラインにのみ公開" |     home-desc: "홈 타임라인에만 공개" | ||||||
|     followers: "フォロワー" |     followers: "팔로워" | ||||||
|     followers-desc: "自分のフォロワーにのみ公開" |     followers-desc: "자신의 팔로워에게만 공개" | ||||||
|     specified: "ダイレクト" |     specified: "다이렉트" | ||||||
|     specified-desc: "指定したユーザーにのみ公開" |     specified-desc: "지정한 사용자에게만 공개" | ||||||
|     private: "非公開" |     private: "비공개" | ||||||
|   note-placeholders: |   note-placeholders: | ||||||
|     a: "지금 어떻게하고있어?" |     a: "지금 어떻게하고있어?" | ||||||
|     b: "뭔가 있었습니까?" |     b: "뭔가 있었습니까?" | ||||||
| @@ -107,14 +107,14 @@ common: | |||||||
|   i-like-sushi: "나는(푸딩보다 오히려)스시가 좋아" |   i-like-sushi: "나는(푸딩보다 오히려)스시가 좋아" | ||||||
|   show-reversi-board-labels: "리버시 보드의 행과 열 레이블을 표시" |   show-reversi-board-labels: "리버시 보드의 행과 열 레이블을 표시" | ||||||
|   use-contrast-reversi-stones: "リバーシのアイコンにコントラストを付ける" |   use-contrast-reversi-stones: "リバーシのアイコンにコントラストを付ける" | ||||||
|   verified-user: "公式アカウント" |   verified-user: "공식 계정" | ||||||
|   disable-animated-mfm: "게시물의 문자 애니메이션을 비활성화 할" |   disable-animated-mfm: "게시물의 문자 애니메이션을 비활성화 할" | ||||||
|   always-show-nsfw: "常に閲覧注意のメディアを表示する" |   always-show-nsfw: "항상 열람주의 미디어를 표시" | ||||||
|   always-mark-nsfw: "常にメディアを閲覧注意として投稿" |   always-mark-nsfw: "항상 미디어를 열람주의로 설정하여 게시" | ||||||
|   show-full-acct: "ユーザー名のホストを省略しない" |   show-full-acct: "ユーザー名のホストを省略しない" | ||||||
|   reduce-motion: "UIの動きを減らす" |   reduce-motion: "UIの動きを減らす" | ||||||
|   this-setting-is-this-device-only: "このデバイスのみ" |   this-setting-is-this-device-only: "이 장치만" | ||||||
|   do-not-use-in-production: 'これは開発ビルドです。本番環境で使用しないでください。' |   do-not-use-in-production: '이것은 개발 빌드입니다. 프로덕션 환경에서 사용하지 마십시오.' | ||||||
|   reversi: |   reversi: | ||||||
|     drawn: "무승부" |     drawn: "무승부" | ||||||
|     my-turn: "당신의 차례입니다" |     my-turn: "당신의 차례입니다" | ||||||
| @@ -155,19 +155,19 @@ common: | |||||||
|     home: "홈" |     home: "홈" | ||||||
|     local: "로컬" |     local: "로컬" | ||||||
|     hybrid: "소셜" |     hybrid: "소셜" | ||||||
|     hashtag: "ハッシュタグ" |     hashtag: "해시태그" | ||||||
|     global: "글로벌" |     global: "글로벌" | ||||||
|     mentions: "あなた宛て" |     mentions: "あなた宛て" | ||||||
|     direct: "ダイレクト投稿" |     direct: "ダイレクト投稿" | ||||||
|     notifications: "통지" |     notifications: "통지" | ||||||
|     list: "목록" |     list: "목록" | ||||||
|     swap-left: "左に移動" |     swap-left: "왼쪽으로 이동" | ||||||
|     swap-right: "右に移動" |     swap-right: "오른쪽으로 이동" | ||||||
|     swap-up: "上に移動" |     swap-up: "위로 이동" | ||||||
|     swap-down: "下に移動" |     swap-down: "아래로 이동" | ||||||
|     remove: "カラムを削除" |     remove: "칼럼 제거" | ||||||
|     add-column: "カラムを追加" |     add-column: "칼럼 추가" | ||||||
|     rename: "名前を変更" |     rename: "이름 변경" | ||||||
|     stack-left: "左に重ねる" |     stack-left: "左に重ねる" | ||||||
|     pop-right: "右に出す" |     pop-right: "右に出す" | ||||||
| auth/views/form.vue: | auth/views/form.vue: | ||||||
| @@ -248,22 +248,57 @@ common/views/components/connect-failed.troubleshooter.vue: | |||||||
|   checking-network: "ネットワーク接続を確認中" |   checking-network: "ネットワーク接続を確認中" | ||||||
|   internet: "インターネット接続" |   internet: "インターネット接続" | ||||||
|   checking-internet: "インターネット接続を確認中" |   checking-internet: "インターネット接続を確認中" | ||||||
|   server: "サーバー接続" |   server: "서버 연결" | ||||||
|   checking-server: "サーバー接続を確認中" |   checking-server: "サーバー接続を確認中" | ||||||
|   finding: "問題を調べています" |   finding: "問題を調べています" | ||||||
|   no-network: "ネットワークに接続されていません" |   no-network: "ネットワークに接続されていません" | ||||||
|   no-network-desc: "お使いのPCのネットワーク接続が正常か確認してください。" |   no-network-desc: "お使いのPCのネットワーク接続が正常か確認してください。" | ||||||
|   no-internet: "インターネットに接続されていません" |   no-internet: "インターネットに接続されていません" | ||||||
|   no-internet-desc: "ネットワークには接続されていますが、インターネットには接続されていないようです。お使いのPCのインターネット接続が正常か確認してください。" |   no-internet-desc: "ネットワークには接続されていますが、インターネットには接続されていないようです。お使いのPCのインターネット接続が正常か確認してください。" | ||||||
|   no-server: "Misskeyのサーバーに接続できません" |   no-server: "Misskey 서버에 연결할 수 없습니다." | ||||||
|   no-server-desc: "お使いのPCのインターネット接続は正常ですが、Misskeyのサーバーには接続できませんでした。サーバーがダウンまたはメンテナンスしている可能性があるので、しばらくしてから再度御アクセスください。" |   no-server-desc: "お使いのPCのインターネット接続は正常ですが、Misskeyのサーバーには接続できませんでした。サーバーがダウンまたはメンテナンスしている可能性があるので、しばらくしてから再度御アクセスください。" | ||||||
|   success: "Misskeyのサーバーに接続できました" |   success: "Misskeyのサーバーに接続できました" | ||||||
|   success-desc: "正常に接続できるようです。ページを再度読み込みしてください。" |   success-desc: "正常に接続できるようです。ページを再度読み込みしてください。" | ||||||
|   flush: "キャッシュの削除" |   flush: "캐시 삭제" | ||||||
|   set-version: "バージョン指定" |   set-version: "버전 지정" | ||||||
| common/views/components/media-banner.vue: | common/views/components/media-banner.vue: | ||||||
|   sensitive: "閲覧注意" |   sensitive: "열람주의" | ||||||
|   click-to-show: "クリックして表示" |   click-to-show: "클릭하여 표시" | ||||||
|  | common/views/components/theme.vue: | ||||||
|  |   light-theme: "非ダークモード時に使用するテーマ" | ||||||
|  |   dark-theme: "ダークモード時に使用するテーマ" | ||||||
|  |   light-themes: "밝은 테마" | ||||||
|  |   dark-themes: "어두운 테마" | ||||||
|  |   install-a-theme: "테마 설치" | ||||||
|  |   theme-code: "테마 코드" | ||||||
|  |   install: "설치" | ||||||
|  |   installed: "「{}」をインストールしました" | ||||||
|  |   create-a-theme: "테마 만들기" | ||||||
|  |   save-created-theme: "테마 저장" | ||||||
|  |   primary-color: "기본 색" | ||||||
|  |   secondary-color: "보조 색" | ||||||
|  |   text-color: "글자 색상" | ||||||
|  |   base-theme: "ベーステーマ" | ||||||
|  |   base-theme-light: "Light" | ||||||
|  |   base-theme-dark: "Dark" | ||||||
|  |   theme-name: "테마명" | ||||||
|  |   preview-created-theme: "미리보기" | ||||||
|  |   invalid-theme: "テーマが正しくありません。" | ||||||
|  |   already-installed: "既にそのテーマはインストールされています。" | ||||||
|  |   saved: "保存しました" | ||||||
|  |   manage-themes: "テーマの管理" | ||||||
|  |   builtin-themes: "標準テーマ" | ||||||
|  |   my-themes: "マイテーマ" | ||||||
|  |   installed-themes: "インストールされたテーマ" | ||||||
|  |   select-theme: "テーマを選択してください" | ||||||
|  |   uninstall: "アンインストール" | ||||||
|  |   uninstalled: "「{}」をアンインストールしました" | ||||||
|  |   author: "作者" | ||||||
|  |   desc: "説明" | ||||||
|  |   export: "エクスポート" | ||||||
|  |   import: "インポート" | ||||||
|  |   import-by-code: "またはコードをペースト" | ||||||
|  |   theme-name-required: "テーマ名は必須です。" | ||||||
| common/views/components/cw-button.vue: | common/views/components/cw-button.vue: | ||||||
|   hide: "隠す" |   hide: "隠す" | ||||||
|   show: "もっと見る" |   show: "もっと見る" | ||||||
| @@ -273,7 +308,7 @@ common/views/components/messaging.vue: | |||||||
|   no-history: "履歴はありません" |   no-history: "履歴はありません" | ||||||
| common/views/components/messaging-room.vue: | common/views/components/messaging-room.vue: | ||||||
|   empty: "このユーザーと話したことはありません" |   empty: "このユーザーと話したことはありません" | ||||||
|   more: "もっと読む" |   more: "더 보기" | ||||||
|   no-history: "これより過去の履歴はありません" |   no-history: "これより過去の履歴はありません" | ||||||
|   resize-form: "ドラッグしてフォームの広さを調整" |   resize-form: "ドラッグしてフォームの広さを調整" | ||||||
|   new-message: "新しいメッセージがあります" |   new-message: "新しいメッセージがあります" | ||||||
| @@ -288,19 +323,20 @@ common/views/components/messaging-room.message.vue: | |||||||
|   is-read: "읽음" |   is-read: "읽음" | ||||||
|   deleted: "このメッセージは削除されました" |   deleted: "このメッセージは削除されました" | ||||||
| common/views/components/nav.vue: | common/views/components/nav.vue: | ||||||
|   about: "Misskeyについて" |   about: "Misskey에 대하여" | ||||||
|   stats: "統計" |   stats: "통계" | ||||||
|   status: "ステータス" |   status: "ステータス" | ||||||
|   wiki: "Wiki" |   wiki: "Wiki" | ||||||
|   donors: "ドナー" |   donors: "기증자" | ||||||
|   repository: "リポジトリ" |   repository: "저장소" | ||||||
|   develop: "開発者" |   develop: "개발자" | ||||||
|   feedback: "フィードバック" |   feedback: "피드백" | ||||||
| common/views/components/note-menu.vue: | common/views/components/note-menu.vue: | ||||||
|   detail: "詳細" |   detail: "詳細" | ||||||
|   copy-link: "リンクをコピー" |   copy-link: "링크 복사" | ||||||
|   favorite: "お気に入り" |   favorite: "お気に入り" | ||||||
|   pin: "ピン留め" |   pin: "ピン留め" | ||||||
|  |   unpin: "ピン留め解除" | ||||||
|   delete: "削除" |   delete: "削除" | ||||||
|   delete-confirm: "この投稿を削除しますか?" |   delete-confirm: "この投稿を削除しますか?" | ||||||
|   remote: "投稿元で見る" |   remote: "投稿元で見る" | ||||||
| @@ -439,6 +475,7 @@ common/views/pages/follow.vue: | |||||||
|   following: "フォロー中" |   following: "フォロー中" | ||||||
|   follow: "フォロー" |   follow: "フォロー" | ||||||
|   request-pending: "フォロー許可待ち" |   request-pending: "フォロー許可待ち" | ||||||
|  |   follow-processing: "フォロー処理中" | ||||||
|   follow-request: "フォロー申請" |   follow-request: "フォロー申請" | ||||||
| desktop: | desktop: | ||||||
|   banner-crop-title: "バナーとして表示する部分を選択" |   banner-crop-title: "バナーとして表示する部分を選択" | ||||||
| @@ -477,13 +514,13 @@ desktop/views/components/charts.vue: | |||||||
|     notes: "投稿の増減 (統合)" |     notes: "投稿の増減 (統合)" | ||||||
|     local-notes: "投稿の増減 (ローカル)" |     local-notes: "投稿の増減 (ローカル)" | ||||||
|     remote-notes: "投稿の増減 (リモート)" |     remote-notes: "投稿の増減 (リモート)" | ||||||
|     notes-total: "投稿の累計" |     notes-total: "投稿の積算" | ||||||
|     users: "ユーザーの増減" |     users: "ユーザーの増減" | ||||||
|     users-total: "ユーザーの累計" |     users-total: "ユーザーの積算" | ||||||
|     drive: "ドライブ使用量の増減" |     drive: "ドライブ使用量の増減" | ||||||
|     drive-total: "ドライブ使用量の累計" |     drive-total: "ドライブ使用量の積算" | ||||||
|     drive-files: "ドライブのファイル数の増減" |     drive-files: "ドライブのファイル数の増減" | ||||||
|     drive-files-total: "ドライブのファイル数の累計" |     drive-files-total: "ドライブのファイル数の積算" | ||||||
|     network-requests: "リクエスト" |     network-requests: "リクエスト" | ||||||
|     network-time: "応答時間" |     network-time: "応答時間" | ||||||
|     network-usage: "通信量" |     network-usage: "通信量" | ||||||
| @@ -565,6 +602,7 @@ desktop/views/components/follow-button.vue: | |||||||
|   following: "フォロー中" |   following: "フォロー中" | ||||||
|   follow: "フォロー" |   follow: "フォロー" | ||||||
|   request-pending: "フォロー許可待ち" |   request-pending: "フォロー許可待ち" | ||||||
|  |   follow-processing: "フォロー処理中" | ||||||
|   follow-request: "フォロー申請" |   follow-request: "フォロー申請" | ||||||
| desktop/views/components/followers-window.vue: | desktop/views/components/followers-window.vue: | ||||||
|   followers: "{} のフォロワー" |   followers: "{} のフォロワー" | ||||||
| @@ -675,6 +713,7 @@ desktop/views/components/settings.vue: | |||||||
|   2fa: "二段階認証" |   2fa: "二段階認証" | ||||||
|   other: "その他" |   other: "その他" | ||||||
|   license: "ライセンス" |   license: "ライセンス" | ||||||
|  |   theme: "テーマ" | ||||||
|   behaviour: "動作" |   behaviour: "動作" | ||||||
|   fetch-on-scroll: "スクロールで自動読み込み" |   fetch-on-scroll: "スクロールで自動読み込み" | ||||||
|   fetch-on-scroll-desc: "ページを下までスクロールしたときに自動で追加のコンテンツを読み込みます。" |   fetch-on-scroll-desc: "ページを下までスクロールしたときに自動で追加のコンテンツを読み込みます。" | ||||||
| @@ -691,9 +730,10 @@ desktop/views/components/settings.vue: | |||||||
|   choose-wallpaper: "壁紙を選択" |   choose-wallpaper: "壁紙を選択" | ||||||
|   delete-wallpaper: "壁紙を削除" |   delete-wallpaper: "壁紙を削除" | ||||||
|   dark-mode: "ダークモード" |   dark-mode: "ダークモード" | ||||||
|  |   use-shadow: "UIに影を使用" | ||||||
|  |   rounded-corners: "UIの角を丸める" | ||||||
|   circle-icons: "円形のアイコンを使用" |   circle-icons: "円形のアイコンを使用" | ||||||
|   contrasted-acct: "ユーザー名にコントラストを付ける" |   contrasted-acct: "ユーザー名にコントラストを付ける" | ||||||
|   gradient-window-header: "ウィンドウのタイトルバーにグラデーションを使用" |  | ||||||
|   post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" |   post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" | ||||||
|   suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する" |   suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する" | ||||||
|   show-clock-on-header: "右上に時計を表示する" |   show-clock-on-header: "右上に時計を表示する" | ||||||
| @@ -702,7 +742,6 @@ desktop/views/components/settings.vue: | |||||||
|   show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する" |   show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する" | ||||||
|   show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する" |   show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する" | ||||||
|   show-maps: "マップの自動展開" |   show-maps: "マップの自動展開" | ||||||
|   show-maps-desc: "位置情報が添付された投稿のマップを自動的に展開します。" |  | ||||||
|   sound: "サウンド" |   sound: "サウンド" | ||||||
|   enable-sounds: "サウンドを有効にする" |   enable-sounds: "サウンドを有効にする" | ||||||
|   enable-sounds-desc: "投稿やメッセージを送受信したときなどにサウンドを再生します。この設定はブラウザに記憶されます。" |   enable-sounds-desc: "投稿やメッセージを送受信したときなどにサウンドを再生します。この設定はブラウザに記憶されます。" | ||||||
| @@ -1044,6 +1083,7 @@ mobile/views/components/follow-button.vue: | |||||||
|   following: "フォロー中" |   following: "フォロー中" | ||||||
|   follow: "フォロー" |   follow: "フォロー" | ||||||
|   request-pending: "フォロー許可待ち" |   request-pending: "フォロー許可待ち" | ||||||
|  |   follow-processing: "フォロー処理中" | ||||||
|   follow-request: "フォロー申請" |   follow-request: "フォロー申請" | ||||||
| mobile/views/components/friends-maker.vue: | mobile/views/components/friends-maker.vue: | ||||||
|   title: "気になるユーザーをフォロー" |   title: "気になるユーザーをフォロー" | ||||||
| @@ -1219,6 +1259,7 @@ mobile/views/pages/settings.vue: | |||||||
|   notification-position: "通知の表示" |   notification-position: "通知の表示" | ||||||
|   notification-position-bottom: "下" |   notification-position-bottom: "下" | ||||||
|   notification-position-top: "上" |   notification-position-top: "上" | ||||||
|  |   theme: "テーマ" | ||||||
|   behavior: "動作" |   behavior: "動作" | ||||||
|   fetch-on-scroll: "スクロールで自動読み込み" |   fetch-on-scroll: "スクロールで自動読み込み" | ||||||
|   note-visibility: "投稿の公開範囲" |   note-visibility: "投稿の公開範囲" | ||||||
|   | |||||||
| @@ -264,6 +264,41 @@ common/views/components/connect-failed.troubleshooter.vue: | |||||||
| common/views/components/media-banner.vue: | common/views/components/media-banner.vue: | ||||||
|   sensitive: "閲覧注意" |   sensitive: "閲覧注意" | ||||||
|   click-to-show: "クリックして表示" |   click-to-show: "クリックして表示" | ||||||
|  | common/views/components/theme.vue: | ||||||
|  |   light-theme: "非ダークモード時に使用するテーマ" | ||||||
|  |   dark-theme: "ダークモード時に使用するテーマ" | ||||||
|  |   light-themes: "明るいテーマ" | ||||||
|  |   dark-themes: "暗いテーマ" | ||||||
|  |   install-a-theme: "テーマのインストール" | ||||||
|  |   theme-code: "テーマコード" | ||||||
|  |   install: "インストール" | ||||||
|  |   installed: "「{}」をインストールしました" | ||||||
|  |   create-a-theme: "テーマの作成" | ||||||
|  |   save-created-theme: "テーマを保存" | ||||||
|  |   primary-color: "プライマリ カラー" | ||||||
|  |   secondary-color: "セカンダリ カラー" | ||||||
|  |   text-color: "文字色" | ||||||
|  |   base-theme: "ベーステーマ" | ||||||
|  |   base-theme-light: "Light" | ||||||
|  |   base-theme-dark: "Dark" | ||||||
|  |   theme-name: "テーマ名" | ||||||
|  |   preview-created-theme: "プレビュー" | ||||||
|  |   invalid-theme: "テーマが正しくありません。" | ||||||
|  |   already-installed: "既にそのテーマはインストールされています。" | ||||||
|  |   saved: "保存しました" | ||||||
|  |   manage-themes: "テーマの管理" | ||||||
|  |   builtin-themes: "標準テーマ" | ||||||
|  |   my-themes: "マイテーマ" | ||||||
|  |   installed-themes: "インストールされたテーマ" | ||||||
|  |   select-theme: "テーマを選択してください" | ||||||
|  |   uninstall: "アンインストール" | ||||||
|  |   uninstalled: "「{}」をアンインストールしました" | ||||||
|  |   author: "作者" | ||||||
|  |   desc: "説明" | ||||||
|  |   export: "エクスポート" | ||||||
|  |   import: "インポート" | ||||||
|  |   import-by-code: "またはコードをペースト" | ||||||
|  |   theme-name-required: "テーマ名は必須です。" | ||||||
| common/views/components/cw-button.vue: | common/views/components/cw-button.vue: | ||||||
|   hide: "隠す" |   hide: "隠す" | ||||||
|   show: "もっと見る" |   show: "もっと見る" | ||||||
| @@ -301,6 +336,7 @@ common/views/components/note-menu.vue: | |||||||
|   copy-link: "リンクをコピー" |   copy-link: "リンクをコピー" | ||||||
|   favorite: "Deze notitie toevoegen aan favorieten" |   favorite: "Deze notitie toevoegen aan favorieten" | ||||||
|   pin: "Vastmaken aan profielpagina" |   pin: "Vastmaken aan profielpagina" | ||||||
|  |   unpin: "ピン留め解除" | ||||||
|   delete: "削除" |   delete: "削除" | ||||||
|   delete-confirm: "この投稿を削除しますか?" |   delete-confirm: "この投稿を削除しますか?" | ||||||
|   remote: "Origineel tonen" |   remote: "Origineel tonen" | ||||||
| @@ -439,6 +475,7 @@ common/views/pages/follow.vue: | |||||||
|   following: "フォロー中" |   following: "フォロー中" | ||||||
|   follow: "フォロー" |   follow: "フォロー" | ||||||
|   request-pending: "フォロー許可待ち" |   request-pending: "フォロー許可待ち" | ||||||
|  |   follow-processing: "フォロー処理中" | ||||||
|   follow-request: "フォロー申請" |   follow-request: "フォロー申請" | ||||||
| desktop: | desktop: | ||||||
|   banner-crop-title: "バナーとして表示する部分を選択" |   banner-crop-title: "バナーとして表示する部分を選択" | ||||||
| @@ -477,13 +514,13 @@ desktop/views/components/charts.vue: | |||||||
|     notes: "投稿の増減 (統合)" |     notes: "投稿の増減 (統合)" | ||||||
|     local-notes: "投稿の増減 (ローカル)" |     local-notes: "投稿の増減 (ローカル)" | ||||||
|     remote-notes: "投稿の増減 (リモート)" |     remote-notes: "投稿の増減 (リモート)" | ||||||
|     notes-total: "投稿の累計" |     notes-total: "投稿の積算" | ||||||
|     users: "ユーザーの増減" |     users: "ユーザーの増減" | ||||||
|     users-total: "ユーザーの累計" |     users-total: "ユーザーの積算" | ||||||
|     drive: "ドライブ使用量の増減" |     drive: "ドライブ使用量の増減" | ||||||
|     drive-total: "ドライブ使用量の累計" |     drive-total: "ドライブ使用量の積算" | ||||||
|     drive-files: "ドライブのファイル数の増減" |     drive-files: "ドライブのファイル数の増減" | ||||||
|     drive-files-total: "ドライブのファイル数の累計" |     drive-files-total: "ドライブのファイル数の積算" | ||||||
|     network-requests: "リクエスト" |     network-requests: "リクエスト" | ||||||
|     network-time: "応答時間" |     network-time: "応答時間" | ||||||
|     network-usage: "通信量" |     network-usage: "通信量" | ||||||
| @@ -565,6 +602,7 @@ desktop/views/components/follow-button.vue: | |||||||
|   following: "フォロー中" |   following: "フォロー中" | ||||||
|   follow: "Volgen" |   follow: "Volgen" | ||||||
|   request-pending: "フォロー許可待ち" |   request-pending: "フォロー許可待ち" | ||||||
|  |   follow-processing: "フォロー処理中" | ||||||
|   follow-request: "フォロー申請" |   follow-request: "フォロー申請" | ||||||
| desktop/views/components/followers-window.vue: | desktop/views/components/followers-window.vue: | ||||||
|   followers: "Volgers van {}" |   followers: "Volgers van {}" | ||||||
| @@ -675,6 +713,7 @@ desktop/views/components/settings.vue: | |||||||
|   2fa: "Authenticatie in twee stappen" |   2fa: "Authenticatie in twee stappen" | ||||||
|   other: "Overig" |   other: "Overig" | ||||||
|   license: "Licentie" |   license: "Licentie" | ||||||
|  |   theme: "テーマ" | ||||||
|   behaviour: "Gedrag" |   behaviour: "Gedrag" | ||||||
|   fetch-on-scroll: "Ophalen bij scrollen" |   fetch-on-scroll: "Ophalen bij scrollen" | ||||||
|   fetch-on-scroll-desc: "Als je omlaag scrolt, wordt de rest van de inhoud automatisch opgehaald." |   fetch-on-scroll-desc: "Als je omlaag scrolt, wordt de rest van de inhoud automatisch opgehaald." | ||||||
| @@ -691,9 +730,10 @@ desktop/views/components/settings.vue: | |||||||
|   choose-wallpaper: "壁紙を選択" |   choose-wallpaper: "壁紙を選択" | ||||||
|   delete-wallpaper: "壁紙を削除" |   delete-wallpaper: "壁紙を削除" | ||||||
|   dark-mode: "Donkere modus" |   dark-mode: "Donkere modus" | ||||||
|  |   use-shadow: "UIに影を使用" | ||||||
|  |   rounded-corners: "UIの角を丸める" | ||||||
|   circle-icons: "Ronde pictogrammen gebruiken" |   circle-icons: "Ronde pictogrammen gebruiken" | ||||||
|   contrasted-acct: "ユーザー名にコントラストを付ける" |   contrasted-acct: "ユーザー名にコントラストを付ける" | ||||||
|   gradient-window-header: "Kleurverloop gebruiken op vensterkoppen" |  | ||||||
|   post-form-on-timeline: "Berichtformulier boven de tijdlijn tonen" |   post-form-on-timeline: "Berichtformulier boven de tijdlijn tonen" | ||||||
|   suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する" |   suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する" | ||||||
|   show-clock-on-header: "右上に時計を表示する" |   show-clock-on-header: "右上に時計を表示する" | ||||||
| @@ -702,7 +742,6 @@ desktop/views/components/settings.vue: | |||||||
|   show-renoted-my-notes: "Mijn gerenote bericht tonen op de tijdlijn" |   show-renoted-my-notes: "Mijn gerenote bericht tonen op de tijdlijn" | ||||||
|   show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する" |   show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する" | ||||||
|   show-maps: "Kaart tonen" |   show-maps: "Kaart tonen" | ||||||
|   show-maps-desc: "Kaart van bijgevoegde locatie tonen." |  | ||||||
|   sound: "Geluid" |   sound: "Geluid" | ||||||
|   enable-sounds: "Geluid inschakelen" |   enable-sounds: "Geluid inschakelen" | ||||||
|   enable-sounds-desc: "Een geluid afspelen bij het ontvangen van een bericht. Deze instelling wordt opgeslagen in je browser." |   enable-sounds-desc: "Een geluid afspelen bij het ontvangen van een bericht. Deze instelling wordt opgeslagen in je browser." | ||||||
| @@ -1044,6 +1083,7 @@ mobile/views/components/follow-button.vue: | |||||||
|   following: "フォロー中" |   following: "フォロー中" | ||||||
|   follow: "Volgen" |   follow: "Volgen" | ||||||
|   request-pending: "フォロー許可待ち" |   request-pending: "フォロー許可待ち" | ||||||
|  |   follow-processing: "フォロー処理中" | ||||||
|   follow-request: "フォロー申請" |   follow-request: "フォロー申請" | ||||||
| mobile/views/components/friends-maker.vue: | mobile/views/components/friends-maker.vue: | ||||||
|   title: "気になるユーザーをフォロー" |   title: "気になるユーザーをフォロー" | ||||||
| @@ -1219,6 +1259,7 @@ mobile/views/pages/settings.vue: | |||||||
|   notification-position: "通知の表示" |   notification-position: "通知の表示" | ||||||
|   notification-position-bottom: "下" |   notification-position-bottom: "下" | ||||||
|   notification-position-top: "上" |   notification-position-top: "上" | ||||||
|  |   theme: "テーマ" | ||||||
|   behavior: "Gedrag" |   behavior: "Gedrag" | ||||||
|   fetch-on-scroll: "Ophalen bij scrollen" |   fetch-on-scroll: "Ophalen bij scrollen" | ||||||
|   note-visibility: "投稿の公開範囲" |   note-visibility: "投稿の公開範囲" | ||||||
|   | |||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -264,6 +264,41 @@ common/views/components/connect-failed.troubleshooter.vue: | |||||||
| common/views/components/media-banner.vue: | common/views/components/media-banner.vue: | ||||||
|   sensitive: "閲覧注意" |   sensitive: "閲覧注意" | ||||||
|   click-to-show: "クリックして表示" |   click-to-show: "クリックして表示" | ||||||
|  | common/views/components/theme.vue: | ||||||
|  |   light-theme: "非ダークモード時に使用するテーマ" | ||||||
|  |   dark-theme: "ダークモード時に使用するテーマ" | ||||||
|  |   light-themes: "明るいテーマ" | ||||||
|  |   dark-themes: "暗いテーマ" | ||||||
|  |   install-a-theme: "テーマのインストール" | ||||||
|  |   theme-code: "テーマコード" | ||||||
|  |   install: "インストール" | ||||||
|  |   installed: "「{}」をインストールしました" | ||||||
|  |   create-a-theme: "テーマの作成" | ||||||
|  |   save-created-theme: "テーマを保存" | ||||||
|  |   primary-color: "プライマリ カラー" | ||||||
|  |   secondary-color: "セカンダリ カラー" | ||||||
|  |   text-color: "文字色" | ||||||
|  |   base-theme: "ベーステーマ" | ||||||
|  |   base-theme-light: "Light" | ||||||
|  |   base-theme-dark: "Dark" | ||||||
|  |   theme-name: "テーマ名" | ||||||
|  |   preview-created-theme: "プレビュー" | ||||||
|  |   invalid-theme: "テーマが正しくありません。" | ||||||
|  |   already-installed: "既にそのテーマはインストールされています。" | ||||||
|  |   saved: "保存しました" | ||||||
|  |   manage-themes: "テーマの管理" | ||||||
|  |   builtin-themes: "標準テーマ" | ||||||
|  |   my-themes: "マイテーマ" | ||||||
|  |   installed-themes: "インストールされたテーマ" | ||||||
|  |   select-theme: "テーマを選択してください" | ||||||
|  |   uninstall: "アンインストール" | ||||||
|  |   uninstalled: "「{}」をアンインストールしました" | ||||||
|  |   author: "作者" | ||||||
|  |   desc: "説明" | ||||||
|  |   export: "エクスポート" | ||||||
|  |   import: "インポート" | ||||||
|  |   import-by-code: "またはコードをペースト" | ||||||
|  |   theme-name-required: "テーマ名は必須です。" | ||||||
| common/views/components/cw-button.vue: | common/views/components/cw-button.vue: | ||||||
|   hide: "隠す" |   hide: "隠す" | ||||||
|   show: "もっと見る" |   show: "もっと見る" | ||||||
| @@ -301,6 +336,7 @@ common/views/components/note-menu.vue: | |||||||
|   copy-link: "リンクをコピー" |   copy-link: "リンクをコピー" | ||||||
|   favorite: "Dodaj do ulubionych" |   favorite: "Dodaj do ulubionych" | ||||||
|   pin: "Przypnij do profilu" |   pin: "Przypnij do profilu" | ||||||
|  |   unpin: "ピン留め解除" | ||||||
|   delete: "Usuń" |   delete: "Usuń" | ||||||
|   delete-confirm: "Czy na pewno chcesz usunąć ten wpis?" |   delete-confirm: "Czy na pewno chcesz usunąć ten wpis?" | ||||||
|   remote: "Pokaż oryginał" |   remote: "Pokaż oryginał" | ||||||
| @@ -439,6 +475,7 @@ common/views/pages/follow.vue: | |||||||
|   following: "Śledzisz" |   following: "Śledzisz" | ||||||
|   follow: "Śledź" |   follow: "Śledź" | ||||||
|   request-pending: "Oczekiwanie na pozwolenie" |   request-pending: "Oczekiwanie na pozwolenie" | ||||||
|  |   follow-processing: "フォロー処理中" | ||||||
|   follow-request: "Poproś o śledzenie" |   follow-request: "Poproś o śledzenie" | ||||||
| desktop: | desktop: | ||||||
|   banner-crop-title: "バナーとして表示する部分を選択" |   banner-crop-title: "バナーとして表示する部分を選択" | ||||||
| @@ -477,13 +514,13 @@ desktop/views/components/charts.vue: | |||||||
|     notes: "投稿の増減 (統合)" |     notes: "投稿の増減 (統合)" | ||||||
|     local-notes: "投稿の増減 (ローカル)" |     local-notes: "投稿の増減 (ローカル)" | ||||||
|     remote-notes: "投稿の増減 (リモート)" |     remote-notes: "投稿の増減 (リモート)" | ||||||
|     notes-total: "投稿の累計" |     notes-total: "投稿の積算" | ||||||
|     users: "ユーザーの増減" |     users: "ユーザーの増減" | ||||||
|     users-total: "ユーザーの累計" |     users-total: "ユーザーの積算" | ||||||
|     drive: "ドライブ使用量の増減" |     drive: "ドライブ使用量の増減" | ||||||
|     drive-total: "ドライブ使用量の累計" |     drive-total: "ドライブ使用量の積算" | ||||||
|     drive-files: "ドライブのファイル数の増減" |     drive-files: "ドライブのファイル数の増減" | ||||||
|     drive-files-total: "ドライブのファイル数の累計" |     drive-files-total: "ドライブのファイル数の積算" | ||||||
|     network-requests: "リクエスト" |     network-requests: "リクエスト" | ||||||
|     network-time: "応答時間" |     network-time: "応答時間" | ||||||
|     network-usage: "通信量" |     network-usage: "通信量" | ||||||
| @@ -565,6 +602,7 @@ desktop/views/components/follow-button.vue: | |||||||
|   following: "Śledzisz" |   following: "Śledzisz" | ||||||
|   follow: "Śledź" |   follow: "Śledź" | ||||||
|   request-pending: "Oczekiwanie na pozwolenie" |   request-pending: "Oczekiwanie na pozwolenie" | ||||||
|  |   follow-processing: "フォロー処理中" | ||||||
|   follow-request: "Poproś o śledzenie" |   follow-request: "Poproś o śledzenie" | ||||||
| desktop/views/components/followers-window.vue: | desktop/views/components/followers-window.vue: | ||||||
|   followers: "Śledzący" |   followers: "Śledzący" | ||||||
| @@ -675,6 +713,7 @@ desktop/views/components/settings.vue: | |||||||
|   2fa: "Uwierzytelnianie dwuetapowe" |   2fa: "Uwierzytelnianie dwuetapowe" | ||||||
|   other: "Inne" |   other: "Inne" | ||||||
|   license: "Licencja" |   license: "Licencja" | ||||||
|  |   theme: "テーマ" | ||||||
|   behaviour: "Zachowanie" |   behaviour: "Zachowanie" | ||||||
|   fetch-on-scroll: "Automatycznie ładuj po przeciągnięciu w dół" |   fetch-on-scroll: "Automatycznie ładuj po przeciągnięciu w dół" | ||||||
|   fetch-on-scroll-desc: "Po przewinięciu na dół strony automatycznie zostaną załadowane nowe treści." |   fetch-on-scroll-desc: "Po przewinięciu na dół strony automatycznie zostaną załadowane nowe treści." | ||||||
| @@ -691,9 +730,10 @@ desktop/views/components/settings.vue: | |||||||
|   choose-wallpaper: "Wybierz tło" |   choose-wallpaper: "Wybierz tło" | ||||||
|   delete-wallpaper: "Usuń tło" |   delete-wallpaper: "Usuń tło" | ||||||
|   dark-mode: "Tryb ciemny" |   dark-mode: "Tryb ciemny" | ||||||
|  |   use-shadow: "UIに影を使用" | ||||||
|  |   rounded-corners: "UIの角を丸める" | ||||||
|   circle-icons: "Używaj okrągłych ikon" |   circle-icons: "Używaj okrągłych ikon" | ||||||
|   contrasted-acct: "ユーザー名にコントラストを付ける" |   contrasted-acct: "ユーザー名にコントラストを付ける" | ||||||
|   gradient-window-header: "Używaj gradientów na pasku tytułu okna" |  | ||||||
|   post-form-on-timeline: "Wyświetlaj formularz tworzenia wpisu w górnej części osi czasu" |   post-form-on-timeline: "Wyświetlaj formularz tworzenia wpisu w górnej części osi czasu" | ||||||
|   suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する" |   suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する" | ||||||
|   show-clock-on-header: "右上に時計を表示する" |   show-clock-on-header: "右上に時計を表示する" | ||||||
| @@ -702,7 +742,6 @@ desktop/views/components/settings.vue: | |||||||
|   show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する" |   show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する" | ||||||
|   show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する" |   show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する" | ||||||
|   show-maps: "Automatycznie pokazuj mapę" |   show-maps: "Automatycznie pokazuj mapę" | ||||||
|   show-maps-desc: "Mapa będzie automatycznie rozwijana dla wpisów zawierających informacje o lokalizacji." |  | ||||||
|   sound: "Dźwięk" |   sound: "Dźwięk" | ||||||
|   enable-sounds: "Włącz dźwięk" |   enable-sounds: "Włącz dźwięk" | ||||||
|   enable-sounds-desc: "Odtwarzaj dźwięk przy wstawianiu wpisów, wysyłaniu lub otrzymywaniu wiadomości. Opcja ta jest zapamiętywana przez przeglądarkę." |   enable-sounds-desc: "Odtwarzaj dźwięk przy wstawianiu wpisów, wysyłaniu lub otrzymywaniu wiadomości. Opcja ta jest zapamiętywana przez przeglądarkę." | ||||||
| @@ -1044,6 +1083,7 @@ mobile/views/components/follow-button.vue: | |||||||
|   following: "Śledzisz" |   following: "Śledzisz" | ||||||
|   follow: "Śledź" |   follow: "Śledź" | ||||||
|   request-pending: "Oczekiwanie na pozwolenie" |   request-pending: "Oczekiwanie na pozwolenie" | ||||||
|  |   follow-processing: "フォロー処理中" | ||||||
|   follow-request: "Poproś o śledzenie" |   follow-request: "Poproś o śledzenie" | ||||||
| mobile/views/components/friends-maker.vue: | mobile/views/components/friends-maker.vue: | ||||||
|   title: "Zacznij śledzić ludzi takich jak Ty" |   title: "Zacznij śledzić ludzi takich jak Ty" | ||||||
| @@ -1219,6 +1259,7 @@ mobile/views/pages/settings.vue: | |||||||
|   notification-position: "通知の表示" |   notification-position: "通知の表示" | ||||||
|   notification-position-bottom: "下" |   notification-position-bottom: "下" | ||||||
|   notification-position-top: "上" |   notification-position-top: "上" | ||||||
|  |   theme: "テーマ" | ||||||
|   behavior: "Zachowanie" |   behavior: "Zachowanie" | ||||||
|   fetch-on-scroll: "Automatycznie ładuj po przeciągnięciu w dół" |   fetch-on-scroll: "Automatycznie ładuj po przeciągnięciu w dół" | ||||||
|   note-visibility: "投稿の公開範囲" |   note-visibility: "投稿の公開範囲" | ||||||
|   | |||||||
| @@ -264,6 +264,41 @@ common/views/components/connect-failed.troubleshooter.vue: | |||||||
| common/views/components/media-banner.vue: | common/views/components/media-banner.vue: | ||||||
|   sensitive: "閲覧注意" |   sensitive: "閲覧注意" | ||||||
|   click-to-show: "クリックして表示" |   click-to-show: "クリックして表示" | ||||||
|  | common/views/components/theme.vue: | ||||||
|  |   light-theme: "非ダークモード時に使用するテーマ" | ||||||
|  |   dark-theme: "ダークモード時に使用するテーマ" | ||||||
|  |   light-themes: "明るいテーマ" | ||||||
|  |   dark-themes: "暗いテーマ" | ||||||
|  |   install-a-theme: "テーマのインストール" | ||||||
|  |   theme-code: "テーマコード" | ||||||
|  |   install: "インストール" | ||||||
|  |   installed: "「{}」をインストールしました" | ||||||
|  |   create-a-theme: "テーマの作成" | ||||||
|  |   save-created-theme: "テーマを保存" | ||||||
|  |   primary-color: "プライマリ カラー" | ||||||
|  |   secondary-color: "セカンダリ カラー" | ||||||
|  |   text-color: "文字色" | ||||||
|  |   base-theme: "ベーステーマ" | ||||||
|  |   base-theme-light: "Light" | ||||||
|  |   base-theme-dark: "Dark" | ||||||
|  |   theme-name: "テーマ名" | ||||||
|  |   preview-created-theme: "プレビュー" | ||||||
|  |   invalid-theme: "テーマが正しくありません。" | ||||||
|  |   already-installed: "既にそのテーマはインストールされています。" | ||||||
|  |   saved: "保存しました" | ||||||
|  |   manage-themes: "テーマの管理" | ||||||
|  |   builtin-themes: "標準テーマ" | ||||||
|  |   my-themes: "マイテーマ" | ||||||
|  |   installed-themes: "インストールされたテーマ" | ||||||
|  |   select-theme: "テーマを選択してください" | ||||||
|  |   uninstall: "アンインストール" | ||||||
|  |   uninstalled: "「{}」をアンインストールしました" | ||||||
|  |   author: "作者" | ||||||
|  |   desc: "説明" | ||||||
|  |   export: "エクスポート" | ||||||
|  |   import: "インポート" | ||||||
|  |   import-by-code: "またはコードをペースト" | ||||||
|  |   theme-name-required: "テーマ名は必須です。" | ||||||
| common/views/components/cw-button.vue: | common/views/components/cw-button.vue: | ||||||
|   hide: "隠す" |   hide: "隠す" | ||||||
|   show: "もっと見る" |   show: "もっと見る" | ||||||
| @@ -301,6 +336,7 @@ common/views/components/note-menu.vue: | |||||||
|   copy-link: "リンクをコピー" |   copy-link: "リンクをコピー" | ||||||
|   favorite: "お気に入り" |   favorite: "お気に入り" | ||||||
|   pin: "ピン留め" |   pin: "ピン留め" | ||||||
|  |   unpin: "ピン留め解除" | ||||||
|   delete: "削除" |   delete: "削除" | ||||||
|   delete-confirm: "この投稿を削除しますか?" |   delete-confirm: "この投稿を削除しますか?" | ||||||
|   remote: "投稿元で見る" |   remote: "投稿元で見る" | ||||||
| @@ -439,6 +475,7 @@ common/views/pages/follow.vue: | |||||||
|   following: "フォロー中" |   following: "フォロー中" | ||||||
|   follow: "フォロー" |   follow: "フォロー" | ||||||
|   request-pending: "フォロー許可待ち" |   request-pending: "フォロー許可待ち" | ||||||
|  |   follow-processing: "フォロー処理中" | ||||||
|   follow-request: "フォロー申請" |   follow-request: "フォロー申請" | ||||||
| desktop: | desktop: | ||||||
|   banner-crop-title: "バナーとして表示する部分を選択" |   banner-crop-title: "バナーとして表示する部分を選択" | ||||||
| @@ -477,13 +514,13 @@ desktop/views/components/charts.vue: | |||||||
|     notes: "投稿の増減 (統合)" |     notes: "投稿の増減 (統合)" | ||||||
|     local-notes: "投稿の増減 (ローカル)" |     local-notes: "投稿の増減 (ローカル)" | ||||||
|     remote-notes: "投稿の増減 (リモート)" |     remote-notes: "投稿の増減 (リモート)" | ||||||
|     notes-total: "投稿の累計" |     notes-total: "投稿の積算" | ||||||
|     users: "ユーザーの増減" |     users: "ユーザーの増減" | ||||||
|     users-total: "ユーザーの累計" |     users-total: "ユーザーの積算" | ||||||
|     drive: "ドライブ使用量の増減" |     drive: "ドライブ使用量の増減" | ||||||
|     drive-total: "ドライブ使用量の累計" |     drive-total: "ドライブ使用量の積算" | ||||||
|     drive-files: "ドライブのファイル数の増減" |     drive-files: "ドライブのファイル数の増減" | ||||||
|     drive-files-total: "ドライブのファイル数の累計" |     drive-files-total: "ドライブのファイル数の積算" | ||||||
|     network-requests: "リクエスト" |     network-requests: "リクエスト" | ||||||
|     network-time: "応答時間" |     network-time: "応答時間" | ||||||
|     network-usage: "通信量" |     network-usage: "通信量" | ||||||
| @@ -565,6 +602,7 @@ desktop/views/components/follow-button.vue: | |||||||
|   following: "フォロー中" |   following: "フォロー中" | ||||||
|   follow: "フォロー" |   follow: "フォロー" | ||||||
|   request-pending: "フォロー許可待ち" |   request-pending: "フォロー許可待ち" | ||||||
|  |   follow-processing: "フォロー処理中" | ||||||
|   follow-request: "フォロー申請" |   follow-request: "フォロー申請" | ||||||
| desktop/views/components/followers-window.vue: | desktop/views/components/followers-window.vue: | ||||||
|   followers: "{} のフォロワー" |   followers: "{} のフォロワー" | ||||||
| @@ -675,6 +713,7 @@ desktop/views/components/settings.vue: | |||||||
|   2fa: "二段階認証" |   2fa: "二段階認証" | ||||||
|   other: "その他" |   other: "その他" | ||||||
|   license: "ライセンス" |   license: "ライセンス" | ||||||
|  |   theme: "テーマ" | ||||||
|   behaviour: "動作" |   behaviour: "動作" | ||||||
|   fetch-on-scroll: "スクロールで自動読み込み" |   fetch-on-scroll: "スクロールで自動読み込み" | ||||||
|   fetch-on-scroll-desc: "ページを下までスクロールしたときに自動で追加のコンテンツを読み込みます。" |   fetch-on-scroll-desc: "ページを下までスクロールしたときに自動で追加のコンテンツを読み込みます。" | ||||||
| @@ -691,9 +730,10 @@ desktop/views/components/settings.vue: | |||||||
|   choose-wallpaper: "壁紙を選択" |   choose-wallpaper: "壁紙を選択" | ||||||
|   delete-wallpaper: "壁紙を削除" |   delete-wallpaper: "壁紙を削除" | ||||||
|   dark-mode: "ダークモード" |   dark-mode: "ダークモード" | ||||||
|  |   use-shadow: "UIに影を使用" | ||||||
|  |   rounded-corners: "UIの角を丸める" | ||||||
|   circle-icons: "円形のアイコンを使用" |   circle-icons: "円形のアイコンを使用" | ||||||
|   contrasted-acct: "ユーザー名にコントラストを付ける" |   contrasted-acct: "ユーザー名にコントラストを付ける" | ||||||
|   gradient-window-header: "ウィンドウのタイトルバーにグラデーションを使用" |  | ||||||
|   post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" |   post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" | ||||||
|   suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する" |   suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する" | ||||||
|   show-clock-on-header: "右上に時計を表示する" |   show-clock-on-header: "右上に時計を表示する" | ||||||
| @@ -702,7 +742,6 @@ desktop/views/components/settings.vue: | |||||||
|   show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する" |   show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する" | ||||||
|   show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する" |   show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する" | ||||||
|   show-maps: "マップの自動展開" |   show-maps: "マップの自動展開" | ||||||
|   show-maps-desc: "位置情報が添付された投稿のマップを自動的に展開します。" |  | ||||||
|   sound: "サウンド" |   sound: "サウンド" | ||||||
|   enable-sounds: "サウンドを有効にする" |   enable-sounds: "サウンドを有効にする" | ||||||
|   enable-sounds-desc: "投稿やメッセージを送受信したときなどにサウンドを再生します。この設定はブラウザに記憶されます。" |   enable-sounds-desc: "投稿やメッセージを送受信したときなどにサウンドを再生します。この設定はブラウザに記憶されます。" | ||||||
| @@ -1044,6 +1083,7 @@ mobile/views/components/follow-button.vue: | |||||||
|   following: "フォロー中" |   following: "フォロー中" | ||||||
|   follow: "フォロー" |   follow: "フォロー" | ||||||
|   request-pending: "フォロー許可待ち" |   request-pending: "フォロー許可待ち" | ||||||
|  |   follow-processing: "フォロー処理中" | ||||||
|   follow-request: "フォロー申請" |   follow-request: "フォロー申請" | ||||||
| mobile/views/components/friends-maker.vue: | mobile/views/components/friends-maker.vue: | ||||||
|   title: "気になるユーザーをフォロー" |   title: "気になるユーザーをフォロー" | ||||||
| @@ -1219,6 +1259,7 @@ mobile/views/pages/settings.vue: | |||||||
|   notification-position: "通知の表示" |   notification-position: "通知の表示" | ||||||
|   notification-position-bottom: "下" |   notification-position-bottom: "下" | ||||||
|   notification-position-top: "上" |   notification-position-top: "上" | ||||||
|  |   theme: "テーマ" | ||||||
|   behavior: "動作" |   behavior: "動作" | ||||||
|   fetch-on-scroll: "スクロールで自動読み込み" |   fetch-on-scroll: "スクロールで自動読み込み" | ||||||
|   note-visibility: "投稿の公開範囲" |   note-visibility: "投稿の公開範囲" | ||||||
|   | |||||||
| @@ -264,6 +264,41 @@ common/views/components/connect-failed.troubleshooter.vue: | |||||||
| common/views/components/media-banner.vue: | common/views/components/media-banner.vue: | ||||||
|   sensitive: "閲覧注意" |   sensitive: "閲覧注意" | ||||||
|   click-to-show: "クリックして表示" |   click-to-show: "クリックして表示" | ||||||
|  | common/views/components/theme.vue: | ||||||
|  |   light-theme: "非ダークモード時に使用するテーマ" | ||||||
|  |   dark-theme: "ダークモード時に使用するテーマ" | ||||||
|  |   light-themes: "明るいテーマ" | ||||||
|  |   dark-themes: "暗いテーマ" | ||||||
|  |   install-a-theme: "テーマのインストール" | ||||||
|  |   theme-code: "テーマコード" | ||||||
|  |   install: "インストール" | ||||||
|  |   installed: "「{}」をインストールしました" | ||||||
|  |   create-a-theme: "テーマの作成" | ||||||
|  |   save-created-theme: "テーマを保存" | ||||||
|  |   primary-color: "プライマリ カラー" | ||||||
|  |   secondary-color: "セカンダリ カラー" | ||||||
|  |   text-color: "文字色" | ||||||
|  |   base-theme: "ベーステーマ" | ||||||
|  |   base-theme-light: "Light" | ||||||
|  |   base-theme-dark: "Dark" | ||||||
|  |   theme-name: "テーマ名" | ||||||
|  |   preview-created-theme: "プレビュー" | ||||||
|  |   invalid-theme: "テーマが正しくありません。" | ||||||
|  |   already-installed: "既にそのテーマはインストールされています。" | ||||||
|  |   saved: "保存しました" | ||||||
|  |   manage-themes: "テーマの管理" | ||||||
|  |   builtin-themes: "標準テーマ" | ||||||
|  |   my-themes: "マイテーマ" | ||||||
|  |   installed-themes: "インストールされたテーマ" | ||||||
|  |   select-theme: "テーマを選択してください" | ||||||
|  |   uninstall: "アンインストール" | ||||||
|  |   uninstalled: "「{}」をアンインストールしました" | ||||||
|  |   author: "作者" | ||||||
|  |   desc: "説明" | ||||||
|  |   export: "エクスポート" | ||||||
|  |   import: "インポート" | ||||||
|  |   import-by-code: "またはコードをペースト" | ||||||
|  |   theme-name-required: "テーマ名は必須です。" | ||||||
| common/views/components/cw-button.vue: | common/views/components/cw-button.vue: | ||||||
|   hide: "隠す" |   hide: "隠す" | ||||||
|   show: "もっと見る" |   show: "もっと見る" | ||||||
| @@ -301,6 +336,7 @@ common/views/components/note-menu.vue: | |||||||
|   copy-link: "リンクをコピー" |   copy-link: "リンクをコピー" | ||||||
|   favorite: "お気に入り" |   favorite: "お気に入り" | ||||||
|   pin: "ピン留め" |   pin: "ピン留め" | ||||||
|  |   unpin: "ピン留め解除" | ||||||
|   delete: "削除" |   delete: "削除" | ||||||
|   delete-confirm: "この投稿を削除しますか?" |   delete-confirm: "この投稿を削除しますか?" | ||||||
|   remote: "投稿元で見る" |   remote: "投稿元で見る" | ||||||
| @@ -439,6 +475,7 @@ common/views/pages/follow.vue: | |||||||
|   following: "フォロー中" |   following: "フォロー中" | ||||||
|   follow: "フォロー" |   follow: "フォロー" | ||||||
|   request-pending: "フォロー許可待ち" |   request-pending: "フォロー許可待ち" | ||||||
|  |   follow-processing: "フォロー処理中" | ||||||
|   follow-request: "フォロー申請" |   follow-request: "フォロー申請" | ||||||
| desktop: | desktop: | ||||||
|   banner-crop-title: "バナーとして表示する部分を選択" |   banner-crop-title: "バナーとして表示する部分を選択" | ||||||
| @@ -477,13 +514,13 @@ desktop/views/components/charts.vue: | |||||||
|     notes: "投稿の増減 (統合)" |     notes: "投稿の増減 (統合)" | ||||||
|     local-notes: "投稿の増減 (ローカル)" |     local-notes: "投稿の増減 (ローカル)" | ||||||
|     remote-notes: "投稿の増減 (リモート)" |     remote-notes: "投稿の増減 (リモート)" | ||||||
|     notes-total: "投稿の累計" |     notes-total: "投稿の積算" | ||||||
|     users: "ユーザーの増減" |     users: "ユーザーの増減" | ||||||
|     users-total: "ユーザーの累計" |     users-total: "ユーザーの積算" | ||||||
|     drive: "ドライブ使用量の増減" |     drive: "ドライブ使用量の増減" | ||||||
|     drive-total: "ドライブ使用量の累計" |     drive-total: "ドライブ使用量の積算" | ||||||
|     drive-files: "ドライブのファイル数の増減" |     drive-files: "ドライブのファイル数の増減" | ||||||
|     drive-files-total: "ドライブのファイル数の累計" |     drive-files-total: "ドライブのファイル数の積算" | ||||||
|     network-requests: "リクエスト" |     network-requests: "リクエスト" | ||||||
|     network-time: "応答時間" |     network-time: "応答時間" | ||||||
|     network-usage: "通信量" |     network-usage: "通信量" | ||||||
| @@ -565,6 +602,7 @@ desktop/views/components/follow-button.vue: | |||||||
|   following: "フォロー中" |   following: "フォロー中" | ||||||
|   follow: "フォロー" |   follow: "フォロー" | ||||||
|   request-pending: "フォロー許可待ち" |   request-pending: "フォロー許可待ち" | ||||||
|  |   follow-processing: "フォロー処理中" | ||||||
|   follow-request: "フォロー申請" |   follow-request: "フォロー申請" | ||||||
| desktop/views/components/followers-window.vue: | desktop/views/components/followers-window.vue: | ||||||
|   followers: "{} のフォロワー" |   followers: "{} のフォロワー" | ||||||
| @@ -675,6 +713,7 @@ desktop/views/components/settings.vue: | |||||||
|   2fa: "二段階認証" |   2fa: "二段階認証" | ||||||
|   other: "その他" |   other: "その他" | ||||||
|   license: "ライセンス" |   license: "ライセンス" | ||||||
|  |   theme: "テーマ" | ||||||
|   behaviour: "動作" |   behaviour: "動作" | ||||||
|   fetch-on-scroll: "スクロールで自動読み込み" |   fetch-on-scroll: "スクロールで自動読み込み" | ||||||
|   fetch-on-scroll-desc: "ページを下までスクロールしたときに自動で追加のコンテンツを読み込みます。" |   fetch-on-scroll-desc: "ページを下までスクロールしたときに自動で追加のコンテンツを読み込みます。" | ||||||
| @@ -691,9 +730,10 @@ desktop/views/components/settings.vue: | |||||||
|   choose-wallpaper: "壁紙を選択" |   choose-wallpaper: "壁紙を選択" | ||||||
|   delete-wallpaper: "壁紙を削除" |   delete-wallpaper: "壁紙を削除" | ||||||
|   dark-mode: "ダークモード" |   dark-mode: "ダークモード" | ||||||
|  |   use-shadow: "UIに影を使用" | ||||||
|  |   rounded-corners: "UIの角を丸める" | ||||||
|   circle-icons: "円形のアイコンを使用" |   circle-icons: "円形のアイコンを使用" | ||||||
|   contrasted-acct: "ユーザー名にコントラストを付ける" |   contrasted-acct: "ユーザー名にコントラストを付ける" | ||||||
|   gradient-window-header: "ウィンドウのタイトルバーにグラデーションを使用" |  | ||||||
|   post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" |   post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" | ||||||
|   suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する" |   suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する" | ||||||
|   show-clock-on-header: "右上に時計を表示する" |   show-clock-on-header: "右上に時計を表示する" | ||||||
| @@ -702,7 +742,6 @@ desktop/views/components/settings.vue: | |||||||
|   show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する" |   show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する" | ||||||
|   show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する" |   show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する" | ||||||
|   show-maps: "マップの自動展開" |   show-maps: "マップの自動展開" | ||||||
|   show-maps-desc: "位置情報が添付された投稿のマップを自動的に展開します。" |  | ||||||
|   sound: "サウンド" |   sound: "サウンド" | ||||||
|   enable-sounds: "サウンドを有効にする" |   enable-sounds: "サウンドを有効にする" | ||||||
|   enable-sounds-desc: "投稿やメッセージを送受信したときなどにサウンドを再生します。この設定はブラウザに記憶されます。" |   enable-sounds-desc: "投稿やメッセージを送受信したときなどにサウンドを再生します。この設定はブラウザに記憶されます。" | ||||||
| @@ -1044,6 +1083,7 @@ mobile/views/components/follow-button.vue: | |||||||
|   following: "フォロー中" |   following: "フォロー中" | ||||||
|   follow: "フォロー" |   follow: "フォロー" | ||||||
|   request-pending: "フォロー許可待ち" |   request-pending: "フォロー許可待ち" | ||||||
|  |   follow-processing: "フォロー処理中" | ||||||
|   follow-request: "フォロー申請" |   follow-request: "フォロー申請" | ||||||
| mobile/views/components/friends-maker.vue: | mobile/views/components/friends-maker.vue: | ||||||
|   title: "気になるユーザーをフォロー" |   title: "気になるユーザーをフォロー" | ||||||
| @@ -1219,6 +1259,7 @@ mobile/views/pages/settings.vue: | |||||||
|   notification-position: "通知の表示" |   notification-position: "通知の表示" | ||||||
|   notification-position-bottom: "下" |   notification-position-bottom: "下" | ||||||
|   notification-position-top: "上" |   notification-position-top: "上" | ||||||
|  |   theme: "テーマ" | ||||||
|   behavior: "動作" |   behavior: "動作" | ||||||
|   fetch-on-scroll: "スクロールで自動読み込み" |   fetch-on-scroll: "スクロールで自動読み込み" | ||||||
|   note-visibility: "投稿の公開範囲" |   note-visibility: "投稿の公開範囲" | ||||||
|   | |||||||
| @@ -264,6 +264,41 @@ common/views/components/connect-failed.troubleshooter.vue: | |||||||
| common/views/components/media-banner.vue: | common/views/components/media-banner.vue: | ||||||
|   sensitive: "閲覧注意" |   sensitive: "閲覧注意" | ||||||
|   click-to-show: "クリックして表示" |   click-to-show: "クリックして表示" | ||||||
|  | common/views/components/theme.vue: | ||||||
|  |   light-theme: "非ダークモード時に使用するテーマ" | ||||||
|  |   dark-theme: "ダークモード時に使用するテーマ" | ||||||
|  |   light-themes: "明るいテーマ" | ||||||
|  |   dark-themes: "暗いテーマ" | ||||||
|  |   install-a-theme: "テーマのインストール" | ||||||
|  |   theme-code: "テーマコード" | ||||||
|  |   install: "インストール" | ||||||
|  |   installed: "「{}」をインストールしました" | ||||||
|  |   create-a-theme: "テーマの作成" | ||||||
|  |   save-created-theme: "テーマを保存" | ||||||
|  |   primary-color: "プライマリ カラー" | ||||||
|  |   secondary-color: "セカンダリ カラー" | ||||||
|  |   text-color: "文字色" | ||||||
|  |   base-theme: "ベーステーマ" | ||||||
|  |   base-theme-light: "Light" | ||||||
|  |   base-theme-dark: "Dark" | ||||||
|  |   theme-name: "テーマ名" | ||||||
|  |   preview-created-theme: "プレビュー" | ||||||
|  |   invalid-theme: "テーマが正しくありません。" | ||||||
|  |   already-installed: "既にそのテーマはインストールされています。" | ||||||
|  |   saved: "保存しました" | ||||||
|  |   manage-themes: "テーマの管理" | ||||||
|  |   builtin-themes: "標準テーマ" | ||||||
|  |   my-themes: "マイテーマ" | ||||||
|  |   installed-themes: "インストールされたテーマ" | ||||||
|  |   select-theme: "テーマを選択してください" | ||||||
|  |   uninstall: "アンインストール" | ||||||
|  |   uninstalled: "「{}」をアンインストールしました" | ||||||
|  |   author: "作者" | ||||||
|  |   desc: "説明" | ||||||
|  |   export: "エクスポート" | ||||||
|  |   import: "インポート" | ||||||
|  |   import-by-code: "またはコードをペースト" | ||||||
|  |   theme-name-required: "テーマ名は必須です。" | ||||||
| common/views/components/cw-button.vue: | common/views/components/cw-button.vue: | ||||||
|   hide: "隠す" |   hide: "隠す" | ||||||
|   show: "もっと見る" |   show: "もっと見る" | ||||||
| @@ -301,6 +336,7 @@ common/views/components/note-menu.vue: | |||||||
|   copy-link: "リンクをコピー" |   copy-link: "リンクをコピー" | ||||||
|   favorite: "お気に入り" |   favorite: "お気に入り" | ||||||
|   pin: "ピン留め" |   pin: "ピン留め" | ||||||
|  |   unpin: "ピン留め解除" | ||||||
|   delete: "削除" |   delete: "削除" | ||||||
|   delete-confirm: "この投稿を削除しますか?" |   delete-confirm: "この投稿を削除しますか?" | ||||||
|   remote: "投稿元で見る" |   remote: "投稿元で見る" | ||||||
| @@ -439,6 +475,7 @@ common/views/pages/follow.vue: | |||||||
|   following: "フォロー中" |   following: "フォロー中" | ||||||
|   follow: "フォロー" |   follow: "フォロー" | ||||||
|   request-pending: "フォロー許可待ち" |   request-pending: "フォロー許可待ち" | ||||||
|  |   follow-processing: "フォロー処理中" | ||||||
|   follow-request: "フォロー申請" |   follow-request: "フォロー申請" | ||||||
| desktop: | desktop: | ||||||
|   banner-crop-title: "バナーとして表示する部分を選択" |   banner-crop-title: "バナーとして表示する部分を選択" | ||||||
| @@ -477,13 +514,13 @@ desktop/views/components/charts.vue: | |||||||
|     notes: "投稿の増減 (統合)" |     notes: "投稿の増減 (統合)" | ||||||
|     local-notes: "投稿の増減 (ローカル)" |     local-notes: "投稿の増減 (ローカル)" | ||||||
|     remote-notes: "投稿の増減 (リモート)" |     remote-notes: "投稿の増減 (リモート)" | ||||||
|     notes-total: "投稿の累計" |     notes-total: "投稿の積算" | ||||||
|     users: "ユーザーの増減" |     users: "ユーザーの増減" | ||||||
|     users-total: "ユーザーの累計" |     users-total: "ユーザーの積算" | ||||||
|     drive: "ドライブ使用量の増減" |     drive: "ドライブ使用量の増減" | ||||||
|     drive-total: "ドライブ使用量の累計" |     drive-total: "ドライブ使用量の積算" | ||||||
|     drive-files: "ドライブのファイル数の増減" |     drive-files: "ドライブのファイル数の増減" | ||||||
|     drive-files-total: "ドライブのファイル数の累計" |     drive-files-total: "ドライブのファイル数の積算" | ||||||
|     network-requests: "リクエスト" |     network-requests: "リクエスト" | ||||||
|     network-time: "応答時間" |     network-time: "応答時間" | ||||||
|     network-usage: "通信量" |     network-usage: "通信量" | ||||||
| @@ -565,6 +602,7 @@ desktop/views/components/follow-button.vue: | |||||||
|   following: "フォロー中" |   following: "フォロー中" | ||||||
|   follow: "フォロー" |   follow: "フォロー" | ||||||
|   request-pending: "フォロー許可待ち" |   request-pending: "フォロー許可待ち" | ||||||
|  |   follow-processing: "フォロー処理中" | ||||||
|   follow-request: "フォロー申請" |   follow-request: "フォロー申請" | ||||||
| desktop/views/components/followers-window.vue: | desktop/views/components/followers-window.vue: | ||||||
|   followers: "{} のフォロワー" |   followers: "{} のフォロワー" | ||||||
| @@ -675,6 +713,7 @@ desktop/views/components/settings.vue: | |||||||
|   2fa: "二段階認証" |   2fa: "二段階認証" | ||||||
|   other: "その他" |   other: "その他" | ||||||
|   license: "ライセンス" |   license: "ライセンス" | ||||||
|  |   theme: "テーマ" | ||||||
|   behaviour: "動作" |   behaviour: "動作" | ||||||
|   fetch-on-scroll: "スクロールで自動読み込み" |   fetch-on-scroll: "スクロールで自動読み込み" | ||||||
|   fetch-on-scroll-desc: "ページを下までスクロールしたときに自動で追加のコンテンツを読み込みます。" |   fetch-on-scroll-desc: "ページを下までスクロールしたときに自動で追加のコンテンツを読み込みます。" | ||||||
| @@ -691,9 +730,10 @@ desktop/views/components/settings.vue: | |||||||
|   choose-wallpaper: "壁紙を選択" |   choose-wallpaper: "壁紙を選択" | ||||||
|   delete-wallpaper: "壁紙を削除" |   delete-wallpaper: "壁紙を削除" | ||||||
|   dark-mode: "ダークモード" |   dark-mode: "ダークモード" | ||||||
|  |   use-shadow: "UIに影を使用" | ||||||
|  |   rounded-corners: "UIの角を丸める" | ||||||
|   circle-icons: "円形のアイコンを使用" |   circle-icons: "円形のアイコンを使用" | ||||||
|   contrasted-acct: "ユーザー名にコントラストを付ける" |   contrasted-acct: "ユーザー名にコントラストを付ける" | ||||||
|   gradient-window-header: "ウィンドウのタイトルバーにグラデーションを使用" |  | ||||||
|   post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" |   post-form-on-timeline: "タイムライン上部に投稿フォームを表示する" | ||||||
|   suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する" |   suggest-recent-hashtags: "最近のハッシュタグを投稿フォームに表示する" | ||||||
|   show-clock-on-header: "右上に時計を表示する" |   show-clock-on-header: "右上に時計を表示する" | ||||||
| @@ -702,7 +742,6 @@ desktop/views/components/settings.vue: | |||||||
|   show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する" |   show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する" | ||||||
|   show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する" |   show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する" | ||||||
|   show-maps: "マップの自動展開" |   show-maps: "マップの自動展開" | ||||||
|   show-maps-desc: "位置情報が添付された投稿のマップを自動的に展開します。" |  | ||||||
|   sound: "サウンド" |   sound: "サウンド" | ||||||
|   enable-sounds: "サウンドを有効にする" |   enable-sounds: "サウンドを有効にする" | ||||||
|   enable-sounds-desc: "投稿やメッセージを送受信したときなどにサウンドを再生します。この設定はブラウザに記憶されます。" |   enable-sounds-desc: "投稿やメッセージを送受信したときなどにサウンドを再生します。この設定はブラウザに記憶されます。" | ||||||
| @@ -1044,6 +1083,7 @@ mobile/views/components/follow-button.vue: | |||||||
|   following: "フォロー中" |   following: "フォロー中" | ||||||
|   follow: "フォロー" |   follow: "フォロー" | ||||||
|   request-pending: "フォロー許可待ち" |   request-pending: "フォロー許可待ち" | ||||||
|  |   follow-processing: "フォロー処理中" | ||||||
|   follow-request: "フォロー申請" |   follow-request: "フォロー申請" | ||||||
| mobile/views/components/friends-maker.vue: | mobile/views/components/friends-maker.vue: | ||||||
|   title: "気になるユーザーをフォロー" |   title: "気になるユーザーをフォロー" | ||||||
| @@ -1219,6 +1259,7 @@ mobile/views/pages/settings.vue: | |||||||
|   notification-position: "通知の表示" |   notification-position: "通知の表示" | ||||||
|   notification-position-bottom: "下" |   notification-position-bottom: "下" | ||||||
|   notification-position-top: "上" |   notification-position-top: "上" | ||||||
|  |   theme: "テーマ" | ||||||
|   behavior: "動作" |   behavior: "動作" | ||||||
|   fetch-on-scroll: "スクロールで自動読み込み" |   fetch-on-scroll: "スクロールで自動読み込み" | ||||||
|   note-visibility: "投稿の公開範囲" |   note-visibility: "投稿の公開範囲" | ||||||
|   | |||||||
							
								
								
									
										60
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										60
									
								
								package.json
									
									
									
									
									
								
							| @@ -1,8 +1,8 @@ | |||||||
| { | { | ||||||
| 	"name": "misskey", | 	"name": "misskey", | ||||||
| 	"author": "syuilo <i@syuilo.com>", | 	"author": "syuilo <i@syuilo.com>", | ||||||
| 	"version": "8.60.0", | 	"version": "10.4.0", | ||||||
| 	"clientVersion": "1.0.9954", | 	"clientVersion": "1.0.10397", | ||||||
| 	"codename": "nighthike", | 	"codename": "nighthike", | ||||||
| 	"main": "./built/index.js", | 	"main": "./built/index.js", | ||||||
| 	"private": true, | 	"private": true, | ||||||
| @@ -29,7 +29,7 @@ | |||||||
| 		"@prezzemolo/zip": "0.0.3", | 		"@prezzemolo/zip": "0.0.3", | ||||||
| 		"@types/bcryptjs": "2.4.2", | 		"@types/bcryptjs": "2.4.2", | ||||||
| 		"@types/dateformat": "1.0.1", | 		"@types/dateformat": "1.0.1", | ||||||
| 		"@types/debug": "0.0.30", | 		"@types/debug": "0.0.31", | ||||||
| 		"@types/deep-equal": "1.0.1", | 		"@types/deep-equal": "1.0.1", | ||||||
| 		"@types/double-ended-queue": "2.1.0", | 		"@types/double-ended-queue": "2.1.0", | ||||||
| 		"@types/elasticsearch": "5.0.26", | 		"@types/elasticsearch": "5.0.26", | ||||||
| @@ -58,14 +58,14 @@ | |||||||
| 		"@types/minio": "7.0.0", | 		"@types/minio": "7.0.0", | ||||||
| 		"@types/mkdirp": "0.5.2", | 		"@types/mkdirp": "0.5.2", | ||||||
| 		"@types/mocha": "5.2.3", | 		"@types/mocha": "5.2.3", | ||||||
| 		"@types/mongodb": "3.1.7", | 		"@types/mongodb": "3.1.11", | ||||||
| 		"@types/ms": "0.7.30", | 		"@types/ms": "0.7.30", | ||||||
| 		"@types/node": "10.10.3", | 		"@types/node": "10.11.5", | ||||||
| 		"@types/portscanner": "2.1.0", | 		"@types/portscanner": "2.1.0", | ||||||
| 		"@types/pug": "2.0.4", | 		"@types/pug": "2.0.4", | ||||||
| 		"@types/qrcode": "1.2.0", | 		"@types/qrcode": "1.3.0", | ||||||
| 		"@types/ratelimiter": "2.1.28", | 		"@types/ratelimiter": "2.1.28", | ||||||
| 		"@types/redis": "2.8.6", | 		"@types/redis": "2.8.7", | ||||||
| 		"@types/request": "2.47.1", | 		"@types/request": "2.47.1", | ||||||
| 		"@types/request-promise-native": "1.0.15", | 		"@types/request-promise-native": "1.0.15", | ||||||
| 		"@types/rimraf": "2.0.2", | 		"@types/rimraf": "2.0.2", | ||||||
| @@ -75,13 +75,15 @@ | |||||||
| 		"@types/single-line-log": "1.1.0", | 		"@types/single-line-log": "1.1.0", | ||||||
| 		"@types/speakeasy": "2.0.2", | 		"@types/speakeasy": "2.0.2", | ||||||
| 		"@types/systeminformation": "3.23.0", | 		"@types/systeminformation": "3.23.0", | ||||||
|  | 		"@types/tinycolor2": "1.4.1", | ||||||
| 		"@types/tmp": "0.0.33", | 		"@types/tmp": "0.0.33", | ||||||
| 		"@types/uuid": "3.4.4", | 		"@types/uuid": "3.4.4", | ||||||
| 		"@types/webpack": "4.4.12", | 		"@types/webpack": "4.4.15", | ||||||
| 		"@types/webpack-stream": "3.2.10", | 		"@types/webpack-stream": "3.2.10", | ||||||
| 		"@types/websocket": "0.0.40", | 		"@types/websocket": "0.0.40", | ||||||
| 		"@types/ws": "6.0.1", | 		"@types/ws": "6.0.1", | ||||||
| 		"animejs": "2.2.0", | 		"animejs": "2.2.0", | ||||||
|  | 		"autobind-decorator": "2.1.0", | ||||||
| 		"autosize": "4.0.2", | 		"autosize": "4.0.2", | ||||||
| 		"autwh": "0.1.0", | 		"autwh": "0.1.0", | ||||||
| 		"bcryptjs": "2.4.3", | 		"bcryptjs": "2.4.3", | ||||||
| @@ -90,14 +92,14 @@ | |||||||
| 		"cafy": "11.3.0", | 		"cafy": "11.3.0", | ||||||
| 		"chalk": "2.4.1", | 		"chalk": "2.4.1", | ||||||
| 		"chart.js": "2.7.2", | 		"chart.js": "2.7.2", | ||||||
| 		"commander": "2.17.1", | 		"commander": "2.19.0", | ||||||
| 		"crc-32": "1.2.0", | 		"crc-32": "1.2.0", | ||||||
| 		"css-loader": "1.0.0", | 		"css-loader": "1.0.0", | ||||||
| 		"dateformat": "3.0.3", | 		"dateformat": "3.0.3", | ||||||
| 		"debug": "4.0.1", | 		"debug": "4.1.0", | ||||||
| 		"deep-equal": "1.0.1", | 		"deep-equal": "1.0.1", | ||||||
| 		"deepcopy": "0.6.3", | 		"deepcopy": "0.6.3", | ||||||
| 		"diskusage": "0.2.4", | 		"diskusage": "0.2.5", | ||||||
| 		"dompurify": "1.0.5", | 		"dompurify": "1.0.5", | ||||||
| 		"double-ended-queue": "2.1.0-0", | 		"double-ended-queue": "2.1.0-0", | ||||||
| 		"elasticsearch": "15.1.1", | 		"elasticsearch": "15.1.1", | ||||||
| @@ -107,12 +109,12 @@ | |||||||
| 		"eslint-plugin-vue": "4.7.1", | 		"eslint-plugin-vue": "4.7.1", | ||||||
| 		"eventemitter3": "3.1.0", | 		"eventemitter3": "3.1.0", | ||||||
| 		"exif-js": "2.3.0", | 		"exif-js": "2.3.0", | ||||||
| 		"file-loader": "1.1.11", | 		"file-loader": "2.0.0", | ||||||
| 		"file-type": "9.0.0", | 		"file-type": "10.0.0", | ||||||
| 		"fuckadblock": "3.2.1", | 		"fuckadblock": "3.2.1", | ||||||
| 		"gulp": "3.9.1", | 		"gulp": "3.9.1", | ||||||
| 		"gulp-cssnano": "2.1.3", | 		"gulp-cssnano": "2.1.3", | ||||||
| 		"gulp-htmlmin": "4.0.0", | 		"gulp-htmlmin": "5.0.1", | ||||||
| 		"gulp-imagemin": "4.1.0", | 		"gulp-imagemin": "4.1.0", | ||||||
| 		"gulp-mocha": "6.0.0", | 		"gulp-mocha": "6.0.0", | ||||||
| 		"gulp-pug": "4.0.1", | 		"gulp-pug": "4.0.1", | ||||||
| @@ -132,14 +134,16 @@ | |||||||
| 		"is-root": "2.0.0", | 		"is-root": "2.0.0", | ||||||
| 		"is-url": "1.2.4", | 		"is-url": "1.2.4", | ||||||
| 		"js-yaml": "3.12.0", | 		"js-yaml": "3.12.0", | ||||||
| 		"jsdom": "11.12.0", | 		"jsdom": "12.2.0", | ||||||
|  | 		"json5": "2.1.0", | ||||||
|  | 		"json5-loader": "1.0.1", | ||||||
| 		"koa": "2.5.1", | 		"koa": "2.5.1", | ||||||
| 		"koa-bodyparser": "4.2.1", | 		"koa-bodyparser": "4.2.1", | ||||||
| 		"koa-compress": "3.0.0", | 		"koa-compress": "3.0.0", | ||||||
| 		"koa-favicon": "2.0.1", | 		"koa-favicon": "2.0.1", | ||||||
| 		"koa-json-body": "5.3.0", | 		"koa-json-body": "5.3.0", | ||||||
| 		"koa-logger": "3.2.0", | 		"koa-logger": "3.2.0", | ||||||
| 		"koa-mount": "3.0.0", | 		"koa-mount": "4.0.0", | ||||||
| 		"koa-multer": "1.0.2", | 		"koa-multer": "1.0.2", | ||||||
| 		"koa-router": "7.4.0", | 		"koa-router": "7.4.0", | ||||||
| 		"koa-send": "5.0.0", | 		"koa-send": "5.0.0", | ||||||
| @@ -156,7 +160,7 @@ | |||||||
| 		"mongodb": "3.1.1", | 		"mongodb": "3.1.1", | ||||||
| 		"monk": "6.0.6", | 		"monk": "6.0.6", | ||||||
| 		"ms": "2.1.1", | 		"ms": "2.1.1", | ||||||
| 		"nan": "2.11.0", | 		"nan": "2.11.1", | ||||||
| 		"nested-property": "0.0.7", | 		"nested-property": "0.0.7", | ||||||
| 		"nprogress": "0.2.0", | 		"nprogress": "0.2.0", | ||||||
| 		"object-assign-deep": "0.4.0", | 		"object-assign-deep": "0.4.0", | ||||||
| @@ -168,10 +172,10 @@ | |||||||
| 		"promise-sequential": "1.1.1", | 		"promise-sequential": "1.1.1", | ||||||
| 		"pug": "2.0.3", | 		"pug": "2.0.3", | ||||||
| 		"punycode": "2.1.1", | 		"punycode": "2.1.1", | ||||||
| 		"qrcode": "1.2.2", | 		"qrcode": "1.3.0", | ||||||
| 		"ratelimiter": "3.2.0", | 		"ratelimiter": "3.2.0", | ||||||
| 		"recaptcha-promise": "0.1.3", | 		"recaptcha-promise": "0.1.3", | ||||||
| 		"reconnecting-websocket": "3.2.2", | 		"reconnecting-websocket": "4.1.5", | ||||||
| 		"redis": "2.8.0", | 		"redis": "2.8.0", | ||||||
| 		"request": "2.88.0", | 		"request": "2.88.0", | ||||||
| 		"request-promise-native": "1.0.5", | 		"request-promise-native": "1.0.5", | ||||||
| @@ -181,37 +185,41 @@ | |||||||
| 		"s-age": "1.1.2", | 		"s-age": "1.1.2", | ||||||
| 		"sass-loader": "7.1.0", | 		"sass-loader": "7.1.0", | ||||||
| 		"seedrandom": "2.4.4", | 		"seedrandom": "2.4.4", | ||||||
| 		"sharp": "0.20.7", | 		"sharp": "0.21.0", | ||||||
| 		"showdown": "1.8.6", | 		"showdown": "1.8.6", | ||||||
| 		"showdown-highlightjs-extension": "0.1.2", | 		"showdown-highlightjs-extension": "0.1.2", | ||||||
| 		"single-line-log": "1.1.2", | 		"single-line-log": "1.1.2", | ||||||
| 		"speakeasy": "2.0.0", | 		"speakeasy": "2.0.0", | ||||||
| 		"stringz": "1.0.0", | 		"stringz": "1.0.0", | ||||||
| 		"style-loader": "0.23.0", | 		"style-loader": "0.23.1", | ||||||
| 		"stylus": "0.54.5", | 		"stylus": "0.54.5", | ||||||
| 		"stylus-loader": "3.0.2", | 		"stylus-loader": "3.0.2", | ||||||
| 		"summaly": "2.2.0", | 		"summaly": "2.2.0", | ||||||
| 		"systeminformation": "3.45.6", | 		"systeminformation": "3.45.7", | ||||||
| 		"syuilo-password-strength": "0.0.1", | 		"syuilo-password-strength": "0.0.1", | ||||||
| 		"textarea-caret": "3.1.0", | 		"textarea-caret": "3.1.0", | ||||||
|  | 		"tinycolor2": "1.4.1", | ||||||
| 		"tmp": "0.0.33", | 		"tmp": "0.0.33", | ||||||
| 		"ts-loader": "4.4.1", | 		"ts-loader": "4.4.1", | ||||||
| 		"ts-node": "7.0.1", | 		"ts-node": "7.0.1", | ||||||
| 		"tslint": "5.10.0", | 		"tslint": "5.10.0", | ||||||
| 		"typescript": "2.9.2", | 		"typescript": "2.9.2", | ||||||
| 		"typescript-eslint-parser": "18.0.0", | 		"typescript-eslint-parser": "20.0.0", | ||||||
| 		"uglify-es": "3.3.9", | 		"uglify-es": "3.3.9", | ||||||
| 		"url-loader": "1.1.1", | 		"url-loader": "1.1.1", | ||||||
| 		"uuid": "3.3.2", | 		"uuid": "3.3.2", | ||||||
| 		"v-animate-css": "0.0.2", | 		"v-animate-css": "0.0.2", | ||||||
| 		"vue": "2.5.17", | 		"vue": "2.5.17", | ||||||
| 		"vue-chartjs": "3.4.0", | 		"vue-chartjs": "3.4.0", | ||||||
|  | 		"vue-color": "2.6.0", | ||||||
| 		"vue-cropperjs": "2.2.2", | 		"vue-cropperjs": "2.2.2", | ||||||
| 		"vue-js-modal": "1.3.26", | 		"vue-js-modal": "1.3.26", | ||||||
| 		"vue-json-tree-view": "2.1.4", | 		"vue-json-tree-view": "2.1.4", | ||||||
| 		"vue-loader": "15.4.2", | 		"vue-loader": "15.4.2", | ||||||
| 		"vue-router": "3.0.1", | 		"vue-router": "3.0.1", | ||||||
| 		"vue-style-loader": "4.1.2", | 		"vue-style-loader": "4.1.2", | ||||||
|  | 		"vue-svg-inline-loader": "1.2.0", | ||||||
|  | 		"vue-sweetalert2": "1.5.5", | ||||||
| 		"vue-template-compiler": "2.5.17", | 		"vue-template-compiler": "2.5.17", | ||||||
| 		"vuedraggable": "2.16.0", | 		"vuedraggable": "2.16.0", | ||||||
| 		"vuewordcloud": "18.7.11", | 		"vuewordcloud": "18.7.11", | ||||||
| @@ -219,10 +227,10 @@ | |||||||
| 		"vuex-persistedstate": "2.5.4", | 		"vuex-persistedstate": "2.5.4", | ||||||
| 		"web-push": "3.3.3", | 		"web-push": "3.3.3", | ||||||
| 		"webfinger.js": "2.6.6", | 		"webfinger.js": "2.6.6", | ||||||
| 		"webpack": "4.19.1", | 		"webpack": "4.20.2", | ||||||
| 		"webpack-cli": "3.1.0", | 		"webpack-cli": "3.1.2", | ||||||
| 		"websocket": "1.0.28", | 		"websocket": "1.0.28", | ||||||
| 		"ws": "6.0.0", | 		"ws": "6.1.0", | ||||||
| 		"xev": "2.0.1" | 		"xev": "2.0.1" | ||||||
| 	}, | 	}, | ||||||
| 	"greenkeeper": { | 	"greenkeeper": { | ||||||
|   | |||||||
| @@ -27,7 +27,7 @@ body | |||||||
| 	z-index 65536 | 	z-index 65536 | ||||||
|  |  | ||||||
| 	.bar | 	.bar | ||||||
| 		background $theme-color | 		background var(--primary) | ||||||
|  |  | ||||||
| 		position fixed | 		position fixed | ||||||
| 		z-index 65537 | 		z-index 65537 | ||||||
| @@ -44,7 +44,7 @@ body | |||||||
| 		right 0px | 		right 0px | ||||||
| 		width 100px | 		width 100px | ||||||
| 		height 100% | 		height 100% | ||||||
| 		box-shadow 0 0 10px $theme-color, 0 0 5px $theme-color | 		box-shadow 0 0 10px var(--primary), 0 0 5px var(--primary) | ||||||
| 		opacity 1 | 		opacity 1 | ||||||
|  |  | ||||||
| 		transform rotate(3deg) translate(0px, -4px) | 		transform rotate(3deg) translate(0px, -4px) | ||||||
| @@ -64,8 +64,8 @@ body | |||||||
| 		box-sizing border-box | 		box-sizing border-box | ||||||
|  |  | ||||||
| 		border solid 2px transparent | 		border solid 2px transparent | ||||||
| 		border-top-color $theme-color | 		border-top-color var(--primary) | ||||||
| 		border-left-color $theme-color | 		border-left-color var(--primary) | ||||||
| 		border-radius 50% | 		border-radius 50% | ||||||
|  |  | ||||||
| 		animation progress-spinner 400ms linear infinite | 		animation progress-spinner 400ms linear infinite | ||||||
| @@ -130,3 +130,16 @@ pre | |||||||
|  |  | ||||||
| [data-fa] | [data-fa] | ||||||
| 	display inline-block | 	display inline-block | ||||||
|  |  | ||||||
|  | .swal2-popup | ||||||
|  | 	background var(--face) !important | ||||||
|  |  | ||||||
|  | .swal-icon-only | ||||||
|  | 	width 180px !important | ||||||
|  |  | ||||||
|  | 	> .swal2-header | ||||||
|  | 		> .swal2-icon | ||||||
|  | 			margin 1.25em auto 1.875em | ||||||
|  |  | ||||||
|  | 		> .swal2-title | ||||||
|  | 			display none | ||||||
|   | |||||||
| @@ -34,9 +34,6 @@ html | |||||||
| 		//- FontAwesome style | 		//- FontAwesome style | ||||||
| 		style #{facss} | 		style #{facss} | ||||||
|  |  | ||||||
| 		//- highlight.js style |  | ||||||
| 		style #{hljscss} |  | ||||||
|  |  | ||||||
| 	body | 	body | ||||||
| 		noscript: p | 		noscript: p | ||||||
| 			| JavaScriptを有効にしてください | 			| JavaScriptを有効にしてください | ||||||
|   | |||||||
| @@ -20,6 +20,15 @@ | |||||||
|  |  | ||||||
| 	const langs = LANGS; | 	const langs = LANGS; | ||||||
|  |  | ||||||
|  | 	//#region Apply theme | ||||||
|  | 	const theme = localStorage.getItem('theme'); | ||||||
|  | 	if (theme) { | ||||||
|  | 		Object.entries(JSON.parse(theme)).forEach(([k, v]) => { | ||||||
|  | 			document.documentElement.style.setProperty(`--${k}`, v.toString()); | ||||||
|  | 		}); | ||||||
|  | 	} | ||||||
|  | 	//#endregion | ||||||
|  |  | ||||||
| 	//#region Load settings | 	//#region Load settings | ||||||
| 	let settings = null; | 	let settings = null; | ||||||
| 	const vuex = localStorage.getItem('vuex'); | 	const vuex = localStorage.getItem('vuex'); | ||||||
| @@ -84,13 +93,6 @@ | |||||||
| 		app = isMobile ? 'mobile' : 'desktop'; | 		app = isMobile ? 'mobile' : 'desktop'; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// Dark/Light |  | ||||||
| 	if (settings) { |  | ||||||
| 		if (settings.device.darkmode) { |  | ||||||
| 			document.documentElement.setAttribute('data-darkmode', 'true'); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	// Script version | 	// Script version | ||||||
| 	const ver = localStorage.getItem('v') || VERSION; | 	const ver = localStorage.getItem('v') || VERSION; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -59,7 +59,7 @@ export default { | |||||||
|  |  | ||||||
| 				el.dataset.reservedKeys = reservedKeys.map(key => `'${key}'`).join(' '); | 				el.dataset.reservedKeys = reservedKeys.map(key => `'${key}'`).join(' '); | ||||||
|  |  | ||||||
| 				el._keyHandler = e => { | 				el._keyHandler = (e: KeyboardEvent) => { | ||||||
| 					const key = e.code.toLowerCase(); | 					const key = e.code.toLowerCase(); | ||||||
|  |  | ||||||
| 					const targetReservedKeys = document.activeElement ? ((document.activeElement as any).dataset || {}).reservedKeys || '' : ''; | 					const targetReservedKeys = document.activeElement ? ((document.activeElement as any).dataset || {}).reservedKeys || '' : ''; | ||||||
| @@ -72,7 +72,8 @@ export default { | |||||||
| 							const matched = pattern.which.includes(key) && | 							const matched = pattern.which.includes(key) && | ||||||
| 								pattern.ctrl == e.ctrlKey && | 								pattern.ctrl == e.ctrlKey && | ||||||
| 								pattern.shift == e.shiftKey && | 								pattern.shift == e.shiftKey && | ||||||
| 								pattern.alt == e.altKey; | 								pattern.alt == e.altKey && | ||||||
|  | 								e.metaKey == false; | ||||||
|  |  | ||||||
| 							if (matched) { | 							if (matched) { | ||||||
| 								e.preventDefault(); | 								e.preventDefault(); | ||||||
|   | |||||||
| @@ -13,21 +13,21 @@ type Notification = { | |||||||
|  |  | ||||||
| export default function(type, data): Notification { | export default function(type, data): Notification { | ||||||
| 	switch (type) { | 	switch (type) { | ||||||
| 		case 'drive_file_created': | 		case 'driveFileCreated': | ||||||
| 			return { | 			return { | ||||||
| 				title: '%i18n:common.notification.file-uploaded%', | 				title: '%i18n:common.notification.file-uploaded%', | ||||||
| 				body: data.name, | 				body: data.name, | ||||||
| 				icon: data.url | 				icon: data.url | ||||||
| 			}; | 			}; | ||||||
|  |  | ||||||
| 		case 'unread_messaging_message': | 		case 'unreadMessagingMessage': | ||||||
| 			return { | 			return { | ||||||
| 				title: '%i18n:common.notification.message-from%'.split("{}")[0] + `${getUserName(data.user)}` + '%i18n:common.notification.message-from%'.split("{}")[1] , | 				title: '%i18n:common.notification.message-from%'.split("{}")[0] + `${getUserName(data.user)}` + '%i18n:common.notification.message-from%'.split("{}")[1] , | ||||||
| 				body: data.text, // TODO: getMessagingMessageSummary(data), | 				body: data.text, // TODO: getMessagingMessageSummary(data), | ||||||
| 				icon: data.user.avatarUrl | 				icon: data.user.avatarUrl | ||||||
| 			}; | 			}; | ||||||
|  |  | ||||||
| 		case 'reversi_invited': | 		case 'reversiInvited': | ||||||
| 			return { | 			return { | ||||||
| 				title: '%i18n:common.notification.reversi-invited%', | 				title: '%i18n:common.notification.reversi-invited%', | ||||||
| 				body: '%i18n:common.notification.reversi-invited-by%'.split("{}")[0] + `${getUserName(data.parent)}` + '%i18n:common.notification.reversi-invited-by%'.split("{}")[1], | 				body: '%i18n:common.notification.reversi-invited-by%'.split("{}")[0] + `${getUserName(data.parent)}` + '%i18n:common.notification.reversi-invited-by%'.split("{}")[1], | ||||||
|   | |||||||
							
								
								
									
										8
									
								
								src/client/app/common/scripts/get-md5.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/client/app/common/scripts/get-md5.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | |||||||
|  | const crypto = require('crypto'); | ||||||
|  |  | ||||||
|  | export default (data: ArrayBuffer) => { | ||||||
|  |   const buf = new Buffer(data); | ||||||
|  |   const hash = crypto.createHash("md5"); | ||||||
|  |   hash.update(buf); | ||||||
|  |   return hash.digest("hex"); | ||||||
|  | }; | ||||||
							
								
								
									
										128
									
								
								src/client/app/common/scripts/note-subscriber.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								src/client/app/common/scripts/note-subscriber.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,128 @@ | |||||||
|  | import Vue from 'vue'; | ||||||
|  |  | ||||||
|  | export default prop => ({ | ||||||
|  | 	data() { | ||||||
|  | 		return { | ||||||
|  | 			connection: null | ||||||
|  | 		}; | ||||||
|  | 	}, | ||||||
|  |  | ||||||
|  | 	computed: { | ||||||
|  | 		$_ns_note_(): any { | ||||||
|  | 			return this[prop]; | ||||||
|  | 		}, | ||||||
|  |  | ||||||
|  | 		$_ns_isRenote(): boolean { | ||||||
|  | 			return (this.$_ns_note_.renote != null && | ||||||
|  | 				this.$_ns_note_.text == null && | ||||||
|  | 				this.$_ns_note_.fileIds.length == 0 && | ||||||
|  | 				this.$_ns_note_.poll == null); | ||||||
|  | 		}, | ||||||
|  |  | ||||||
|  | 		$_ns_target(): any { | ||||||
|  | 			return this.$_ns_isRenote ? this.$_ns_note_.renote : this.$_ns_note_; | ||||||
|  | 		}, | ||||||
|  | 	}, | ||||||
|  |  | ||||||
|  | 	created() { | ||||||
|  | 		if (this.$store.getters.isSignedIn) { | ||||||
|  | 			this.connection = (this as any).os.stream; | ||||||
|  | 		} | ||||||
|  | 	}, | ||||||
|  |  | ||||||
|  | 	mounted() { | ||||||
|  | 		this.capture(true); | ||||||
|  |  | ||||||
|  | 		if (this.$store.getters.isSignedIn) { | ||||||
|  | 			this.connection.on('_connected_', this.onStreamConnected); | ||||||
|  | 		} | ||||||
|  | 	}, | ||||||
|  |  | ||||||
|  | 	beforeDestroy() { | ||||||
|  | 		this.decapture(true); | ||||||
|  |  | ||||||
|  | 		if (this.$store.getters.isSignedIn) { | ||||||
|  | 			this.connection.off('_connected_', this.onStreamConnected); | ||||||
|  | 		} | ||||||
|  | 	}, | ||||||
|  |  | ||||||
|  | 	methods: { | ||||||
|  | 		capture(withHandler = false) { | ||||||
|  | 			if (this.$store.getters.isSignedIn) { | ||||||
|  | 				const data = { | ||||||
|  | 					id: this.$_ns_target.id | ||||||
|  | 				} as any; | ||||||
|  |  | ||||||
|  | 				if ( | ||||||
|  | 					(this.$_ns_target.visibleUserIds || []).includes(this.$store.state.i.id) || | ||||||
|  | 					(this.$_ns_target.mentions || []).includes(this.$store.state.i.id) | ||||||
|  | 				) { | ||||||
|  | 					data.read = true; | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				this.connection.send('sn', data); | ||||||
|  | 				if (withHandler) this.connection.on('noteUpdated', this.onStreamNoteUpdated); | ||||||
|  | 			} | ||||||
|  | 		}, | ||||||
|  |  | ||||||
|  | 		decapture(withHandler = false) { | ||||||
|  | 			if (this.$store.getters.isSignedIn) { | ||||||
|  | 				this.connection.send('un', { | ||||||
|  | 					id: this.$_ns_target.id | ||||||
|  | 				}); | ||||||
|  | 				if (withHandler) this.connection.off('noteUpdated', this.onStreamNoteUpdated); | ||||||
|  | 			} | ||||||
|  | 		}, | ||||||
|  |  | ||||||
|  | 		onStreamConnected() { | ||||||
|  | 			this.capture(); | ||||||
|  | 		}, | ||||||
|  |  | ||||||
|  | 		onStreamNoteUpdated(data) { | ||||||
|  | 			const { type, id, body } = data; | ||||||
|  |  | ||||||
|  | 			if (id !== this.$_ns_target.id) return; | ||||||
|  |  | ||||||
|  | 			switch (type) { | ||||||
|  | 				case 'reacted': { | ||||||
|  | 					const reaction = body.reaction; | ||||||
|  |  | ||||||
|  | 					if (this.$_ns_target.reactionCounts == null) { | ||||||
|  | 						Vue.set(this.$_ns_target, 'reactionCounts', {}); | ||||||
|  | 					} | ||||||
|  |  | ||||||
|  | 					if (this.$_ns_target.reactionCounts[reaction] == null) { | ||||||
|  | 						Vue.set(this.$_ns_target.reactionCounts, reaction, 0); | ||||||
|  | 					} | ||||||
|  |  | ||||||
|  | 					this.$_ns_target.reactionCounts[reaction]++; | ||||||
|  |  | ||||||
|  | 					if (body.userId == this.$store.state.i.id) { | ||||||
|  | 						Vue.set(this.$_ns_target, 'myReaction', reaction); | ||||||
|  | 					} | ||||||
|  | 					break; | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				case 'pollVoted': { | ||||||
|  | 					if (body.userId == this.$store.state.i.id) return; | ||||||
|  | 					const choice = body.choice; | ||||||
|  | 					this.$_ns_target.poll.choices.find(c => c.id === choice).votes++; | ||||||
|  | 					break; | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				case 'deleted': { | ||||||
|  | 					Vue.set(this.$_ns_target, 'deletedAt', body.deletedAt); | ||||||
|  | 					this.$_ns_target.text = null; | ||||||
|  | 					this.$_ns_target.tags = []; | ||||||
|  | 					this.$_ns_target.fileIds = []; | ||||||
|  | 					this.$_ns_target.poll = null; | ||||||
|  | 					this.$_ns_target.geo = null; | ||||||
|  | 					this.$_ns_target.cw = null; | ||||||
|  | 					break; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			this.$emit(`update:${prop}`, this.$_ns_note_); | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | }); | ||||||
							
								
								
									
										231
									
								
								src/client/app/common/scripts/stream.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										231
									
								
								src/client/app/common/scripts/stream.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,231 @@ | |||||||
|  | import autobind from 'autobind-decorator'; | ||||||
|  | import { EventEmitter } from 'eventemitter3'; | ||||||
|  | import ReconnectingWebsocket from 'reconnecting-websocket'; | ||||||
|  | import { wsUrl } from '../../config'; | ||||||
|  | import MiOS from '../../mios'; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Misskey stream connection | ||||||
|  |  */ | ||||||
|  | export default class Stream extends EventEmitter { | ||||||
|  | 	private stream: ReconnectingWebsocket; | ||||||
|  | 	private state: string; | ||||||
|  | 	private buffer: any[]; | ||||||
|  | 	private sharedConnections: SharedConnection[] = []; | ||||||
|  | 	private nonSharedConnections: NonSharedConnection[] = []; | ||||||
|  |  | ||||||
|  | 	constructor(os: MiOS) { | ||||||
|  | 		super(); | ||||||
|  |  | ||||||
|  | 		this.state = 'initializing'; | ||||||
|  | 		this.buffer = []; | ||||||
|  |  | ||||||
|  | 		const user = os.store.state.i; | ||||||
|  |  | ||||||
|  | 		this.stream = new ReconnectingWebsocket(wsUrl + (user ? `?i=${user.token}` : '')); | ||||||
|  | 		this.stream.addEventListener('open', this.onOpen); | ||||||
|  | 		this.stream.addEventListener('close', this.onClose); | ||||||
|  | 		this.stream.addEventListener('message', this.onMessage); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public useSharedConnection = (channel: string): SharedConnection => { | ||||||
|  | 		const existConnection = this.sharedConnections.find(c => c.channel === channel); | ||||||
|  |  | ||||||
|  | 		if (existConnection) { | ||||||
|  | 			existConnection.use(); | ||||||
|  | 			return existConnection; | ||||||
|  | 		} else { | ||||||
|  | 			const connection = new SharedConnection(this, channel); | ||||||
|  | 			connection.use(); | ||||||
|  | 			this.sharedConnections.push(connection); | ||||||
|  | 			return connection; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@autobind | ||||||
|  | 	public removeSharedConnection(connection: SharedConnection) { | ||||||
|  | 		this.sharedConnections = this.sharedConnections.filter(c => c.id !== connection.id); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public connectToChannel = (channel: string, params?: any): NonSharedConnection => { | ||||||
|  | 		const connection = new NonSharedConnection(this, channel, params); | ||||||
|  | 		this.nonSharedConnections.push(connection); | ||||||
|  | 		return connection; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@autobind | ||||||
|  | 	public disconnectToChannel(connection: NonSharedConnection) { | ||||||
|  | 		this.nonSharedConnections = this.nonSharedConnections.filter(c => c.id !== connection.id); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Callback of when open connection | ||||||
|  | 	 */ | ||||||
|  | 	@autobind | ||||||
|  | 	private onOpen() { | ||||||
|  | 		const isReconnect = this.state == 'reconnecting'; | ||||||
|  |  | ||||||
|  | 		this.state = 'connected'; | ||||||
|  | 		this.emit('_connected_'); | ||||||
|  |  | ||||||
|  | 		// バッファーを処理 | ||||||
|  | 		const _buffer = [].concat(this.buffer); // Shallow copy | ||||||
|  | 		this.buffer = []; // Clear buffer | ||||||
|  | 		_buffer.forEach(data => { | ||||||
|  | 			this.send(data); // Resend each buffered messages | ||||||
|  | 		}); | ||||||
|  |  | ||||||
|  | 		// チャンネル再接続 | ||||||
|  | 		if (isReconnect) { | ||||||
|  | 			this.sharedConnections.forEach(c => { | ||||||
|  | 				c.connect(); | ||||||
|  | 			}); | ||||||
|  | 			this.nonSharedConnections.forEach(c => { | ||||||
|  | 				c.connect(); | ||||||
|  | 			}); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Callback of when close connection | ||||||
|  | 	 */ | ||||||
|  | 	@autobind | ||||||
|  | 	private onClose() { | ||||||
|  | 		this.state = 'reconnecting'; | ||||||
|  | 		this.emit('_disconnected_'); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Callback of when received a message from connection | ||||||
|  | 	 */ | ||||||
|  | 	@autobind | ||||||
|  | 	private onMessage(message) { | ||||||
|  | 		const { type, body } = JSON.parse(message.data); | ||||||
|  |  | ||||||
|  | 		if (type == 'channel') { | ||||||
|  | 			const id = body.id; | ||||||
|  | 			const connection = this.sharedConnections.find(c => c.id === id) || this.nonSharedConnections.find(c => c.id === id); | ||||||
|  | 			connection.emit(body.type, body.body); | ||||||
|  | 		} else { | ||||||
|  | 			this.emit(type, body); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Send a message to connection | ||||||
|  | 	 */ | ||||||
|  | 	@autobind | ||||||
|  | 	public send(typeOrPayload, payload?) { | ||||||
|  | 		const data = payload === undefined ? typeOrPayload : { | ||||||
|  | 			type: typeOrPayload, | ||||||
|  | 			body: payload | ||||||
|  | 		}; | ||||||
|  |  | ||||||
|  | 		// まだ接続が確立されていなかったらバッファリングして次に接続した時に送信する | ||||||
|  | 		if (this.state != 'connected') { | ||||||
|  | 			this.buffer.push(data); | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		this.stream.send(JSON.stringify(data)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Close this connection | ||||||
|  | 	 */ | ||||||
|  | 	@autobind | ||||||
|  | 	public close() { | ||||||
|  | 		this.stream.removeEventListener('open', this.onOpen); | ||||||
|  | 		this.stream.removeEventListener('message', this.onMessage); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | abstract class Connection extends EventEmitter { | ||||||
|  | 	public channel: string; | ||||||
|  | 	public id: string; | ||||||
|  | 	protected params: any; | ||||||
|  | 	protected stream: Stream; | ||||||
|  |  | ||||||
|  | 	constructor(stream: Stream, channel: string, params?: any) { | ||||||
|  | 		super(); | ||||||
|  |  | ||||||
|  | 		this.stream = stream; | ||||||
|  | 		this.channel = channel; | ||||||
|  | 		this.params = params; | ||||||
|  | 		this.id = Math.random().toString(); | ||||||
|  | 		this.connect(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@autobind | ||||||
|  | 	public connect() { | ||||||
|  | 		this.stream.send('connect', { | ||||||
|  | 			channel: this.channel, | ||||||
|  | 			id: this.id, | ||||||
|  | 			params: this.params | ||||||
|  | 		}); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@autobind | ||||||
|  | 	public send(typeOrPayload, payload?) { | ||||||
|  | 		const type = payload === undefined ? typeOrPayload.type : typeOrPayload; | ||||||
|  | 		const body = payload === undefined ? typeOrPayload.body : payload; | ||||||
|  |  | ||||||
|  | 		this.stream.send('channel', { | ||||||
|  | 			id: this.id, | ||||||
|  | 			type: type, | ||||||
|  | 			body: body | ||||||
|  | 		}); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	public abstract dispose(): void; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | class SharedConnection extends Connection { | ||||||
|  | 	private users = 0; | ||||||
|  | 	private disposeTimerId: any; | ||||||
|  |  | ||||||
|  | 	constructor(stream: Stream, channel: string) { | ||||||
|  | 		super(stream, channel); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@autobind | ||||||
|  | 	public use() { | ||||||
|  | 		this.users++; | ||||||
|  |  | ||||||
|  | 		// タイマー解除 | ||||||
|  | 		if (this.disposeTimerId) { | ||||||
|  | 			clearTimeout(this.disposeTimerId); | ||||||
|  | 			this.disposeTimerId = null; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@autobind | ||||||
|  | 	public dispose() { | ||||||
|  | 		this.users--; | ||||||
|  |  | ||||||
|  | 		// そのコネクションの利用者が誰もいなくなったら | ||||||
|  | 		if (this.users === 0) { | ||||||
|  | 			// また直ぐに再利用される可能性があるので、一定時間待ち、 | ||||||
|  | 			// 新たな利用者が現れなければコネクションを切断する | ||||||
|  | 			this.disposeTimerId = setTimeout(() => { | ||||||
|  | 				this.disposeTimerId = null; | ||||||
|  | 				this.removeAllListeners(); | ||||||
|  | 				this.stream.send('disconnect', { id: this.id }); | ||||||
|  | 				this.stream.removeSharedConnection(this); | ||||||
|  | 			}, 3000); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | class NonSharedConnection extends Connection { | ||||||
|  | 	constructor(stream: Stream, channel: string, params?: any) { | ||||||
|  | 		super(stream, channel, params); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	@autobind | ||||||
|  | 	public dispose() { | ||||||
|  | 		this.removeAllListeners(); | ||||||
|  | 		this.stream.send('disconnect', { id: this.id }); | ||||||
|  | 		this.stream.disconnectToChannel(this); | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @@ -1,34 +0,0 @@ | |||||||
| import Stream from './stream'; |  | ||||||
| import StreamManager from './stream-manager'; |  | ||||||
| import MiOS from '../../../mios'; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Drive stream connection |  | ||||||
|  */ |  | ||||||
| export class DriveStream extends Stream { |  | ||||||
| 	constructor(os: MiOS, me) { |  | ||||||
| 		super(os, 'drive', { |  | ||||||
| 			i: me.token |  | ||||||
| 		}); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| export class DriveStreamManager extends StreamManager<DriveStream> { |  | ||||||
| 	private me; |  | ||||||
| 	private os: MiOS; |  | ||||||
|  |  | ||||||
| 	constructor(os: MiOS, me) { |  | ||||||
| 		super(); |  | ||||||
|  |  | ||||||
| 		this.me = me; |  | ||||||
| 		this.os = os; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	public getConnection() { |  | ||||||
| 		if (this.connection == null) { |  | ||||||
| 			this.connection = new DriveStream(this.os, this.me); |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		return this.connection; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| @@ -1,13 +0,0 @@ | |||||||
| import Stream from '../../stream'; |  | ||||||
| import MiOS from '../../../../../mios'; |  | ||||||
|  |  | ||||||
| export class ReversiGameStream extends Stream { |  | ||||||
| 	constructor(os: MiOS, me, game) { |  | ||||||
| 		super(os, 'games/reversi-game', me ? { |  | ||||||
| 			i: me.token, |  | ||||||
| 			game: game.id |  | ||||||
| 		} : { |  | ||||||
| 			game: game.id |  | ||||||
| 		}); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| @@ -1,31 +0,0 @@ | |||||||
| import StreamManager from '../../stream-manager'; |  | ||||||
| import Stream from '../../stream'; |  | ||||||
| import MiOS from '../../../../../mios'; |  | ||||||
|  |  | ||||||
| export class ReversiStream extends Stream { |  | ||||||
| 	constructor(os: MiOS, me) { |  | ||||||
| 		super(os, 'games/reversi', { |  | ||||||
| 			i: me.token |  | ||||||
| 		}); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| export class ReversiStreamManager extends StreamManager<ReversiStream> { |  | ||||||
| 	private me; |  | ||||||
| 	private os: MiOS; |  | ||||||
|  |  | ||||||
| 	constructor(os: MiOS, me) { |  | ||||||
| 		super(); |  | ||||||
|  |  | ||||||
| 		this.me = me; |  | ||||||
| 		this.os = os; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	public getConnection() { |  | ||||||
| 		if (this.connection == null) { |  | ||||||
| 			this.connection = new ReversiStream(this.os, this.me); |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		return this.connection; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| @@ -1,34 +0,0 @@ | |||||||
| import Stream from './stream'; |  | ||||||
| import StreamManager from './stream-manager'; |  | ||||||
| import MiOS from '../../../mios'; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Global timeline stream connection |  | ||||||
|  */ |  | ||||||
| export class GlobalTimelineStream extends Stream { |  | ||||||
| 	constructor(os: MiOS, me) { |  | ||||||
| 		super(os, 'global-timeline', { |  | ||||||
| 			i: me.token |  | ||||||
| 		}); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| export class GlobalTimelineStreamManager extends StreamManager<GlobalTimelineStream> { |  | ||||||
| 	private me; |  | ||||||
| 	private os: MiOS; |  | ||||||
|  |  | ||||||
| 	constructor(os: MiOS, me) { |  | ||||||
| 		super(); |  | ||||||
|  |  | ||||||
| 		this.me = me; |  | ||||||
| 		this.os = os; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	public getConnection() { |  | ||||||
| 		if (this.connection == null) { |  | ||||||
| 			this.connection = new GlobalTimelineStream(this.os, this.me); |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		return this.connection; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| @@ -1,13 +0,0 @@ | |||||||
| import Stream from './stream'; |  | ||||||
| import MiOS from '../../../mios'; |  | ||||||
|  |  | ||||||
| export class HashtagStream extends Stream { |  | ||||||
| 	constructor(os: MiOS, me, q) { |  | ||||||
| 		super(os, 'hashtag', me ? { |  | ||||||
| 			i: me.token, |  | ||||||
| 			q: JSON.stringify(q) |  | ||||||
| 		} : { |  | ||||||
| 			q: JSON.stringify(q) |  | ||||||
| 		}); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| @@ -1,126 +0,0 @@ | |||||||
| import Stream from './stream'; |  | ||||||
| import StreamManager from './stream-manager'; |  | ||||||
| import MiOS from '../../../mios'; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Home stream connection |  | ||||||
|  */ |  | ||||||
| export class HomeStream extends Stream { |  | ||||||
| 	constructor(os: MiOS, me) { |  | ||||||
| 		super(os, '', { |  | ||||||
| 			i: me.token |  | ||||||
| 		}); |  | ||||||
|  |  | ||||||
| 		// 最終利用日時を更新するため定期的にaliveメッセージを送信 |  | ||||||
| 		setInterval(() => { |  | ||||||
| 			this.send({ type: 'alive' }); |  | ||||||
| 			me.lastUsedAt = new Date(); |  | ||||||
| 		}, 1000 * 60); |  | ||||||
|  |  | ||||||
| 		// 自分の情報が更新されたとき |  | ||||||
| 		this.on('meUpdated', i => { |  | ||||||
| 			if (os.debug) { |  | ||||||
| 				console.log('I updated:', i); |  | ||||||
| 			} |  | ||||||
|  |  | ||||||
| 			os.store.dispatch('mergeMe', i); |  | ||||||
| 		}); |  | ||||||
|  |  | ||||||
| 		this.on('read_all_notifications', () => { |  | ||||||
| 			os.store.dispatch('mergeMe', { |  | ||||||
| 				hasUnreadNotification: false |  | ||||||
| 			}); |  | ||||||
| 		}); |  | ||||||
|  |  | ||||||
| 		this.on('unread_notification', () => { |  | ||||||
| 			os.store.dispatch('mergeMe', { |  | ||||||
| 				hasUnreadNotification: true |  | ||||||
| 			}); |  | ||||||
| 		}); |  | ||||||
|  |  | ||||||
| 		this.on('read_all_messaging_messages', () => { |  | ||||||
| 			os.store.dispatch('mergeMe', { |  | ||||||
| 				hasUnreadMessagingMessage: false |  | ||||||
| 			}); |  | ||||||
| 		}); |  | ||||||
|  |  | ||||||
| 		this.on('unread_messaging_message', () => { |  | ||||||
| 			os.store.dispatch('mergeMe', { |  | ||||||
| 				hasUnreadMessagingMessage: true |  | ||||||
| 			}); |  | ||||||
| 		}); |  | ||||||
|  |  | ||||||
| 		this.on('unreadMention', () => { |  | ||||||
| 			os.store.dispatch('mergeMe', { |  | ||||||
| 				hasUnreadMentions: true |  | ||||||
| 			}); |  | ||||||
| 		}); |  | ||||||
|  |  | ||||||
| 		this.on('readAllUnreadMentions', () => { |  | ||||||
| 			os.store.dispatch('mergeMe', { |  | ||||||
| 				hasUnreadMentions: false |  | ||||||
| 			}); |  | ||||||
| 		}); |  | ||||||
|  |  | ||||||
| 		this.on('unreadSpecifiedNote', () => { |  | ||||||
| 			os.store.dispatch('mergeMe', { |  | ||||||
| 				hasUnreadSpecifiedNotes: true |  | ||||||
| 			}); |  | ||||||
| 		}); |  | ||||||
|  |  | ||||||
| 		this.on('readAllUnreadSpecifiedNotes', () => { |  | ||||||
| 			os.store.dispatch('mergeMe', { |  | ||||||
| 				hasUnreadSpecifiedNotes: false |  | ||||||
| 			}); |  | ||||||
| 		}); |  | ||||||
|  |  | ||||||
| 		this.on('clientSettingUpdated', x => { |  | ||||||
| 			os.store.commit('settings/set', { |  | ||||||
| 				key: x.key, |  | ||||||
| 				value: x.value |  | ||||||
| 			}); |  | ||||||
| 		}); |  | ||||||
|  |  | ||||||
| 		this.on('home_updated', x => { |  | ||||||
| 			os.store.commit('settings/setHome', x); |  | ||||||
| 		}); |  | ||||||
|  |  | ||||||
| 		this.on('mobile_home_updated', x => { |  | ||||||
| 			os.store.commit('settings/setMobileHome', x); |  | ||||||
| 		}); |  | ||||||
|  |  | ||||||
| 		this.on('widgetUpdated', x => { |  | ||||||
| 			os.store.commit('settings/setWidget', { |  | ||||||
| 				id: x.id, |  | ||||||
| 				data: x.data |  | ||||||
| 			}); |  | ||||||
| 		}); |  | ||||||
|  |  | ||||||
| 		// トークンが再生成されたとき |  | ||||||
| 		// このままではMisskeyが利用できないので強制的にサインアウトさせる |  | ||||||
| 		this.on('my_token_regenerated', () => { |  | ||||||
| 			alert('%i18n:common.my-token-regenerated%'); |  | ||||||
| 			os.signout(); |  | ||||||
| 		}); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| export class HomeStreamManager extends StreamManager<HomeStream> { |  | ||||||
| 	private me; |  | ||||||
| 	private os: MiOS; |  | ||||||
|  |  | ||||||
| 	constructor(os: MiOS, me) { |  | ||||||
| 		super(); |  | ||||||
|  |  | ||||||
| 		this.me = me; |  | ||||||
| 		this.os = os; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	public getConnection() { |  | ||||||
| 		if (this.connection == null) { |  | ||||||
| 			this.connection = new HomeStream(this.os, this.me); |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		return this.connection; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| @@ -1,34 +0,0 @@ | |||||||
| import Stream from './stream'; |  | ||||||
| import StreamManager from './stream-manager'; |  | ||||||
| import MiOS from '../../../mios'; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Hybrid timeline stream connection |  | ||||||
|  */ |  | ||||||
| export class HybridTimelineStream extends Stream { |  | ||||||
| 	constructor(os: MiOS, me) { |  | ||||||
| 		super(os, 'hybrid-timeline', { |  | ||||||
| 			i: me.token |  | ||||||
| 		}); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| export class HybridTimelineStreamManager extends StreamManager<HybridTimelineStream> { |  | ||||||
| 	private me; |  | ||||||
| 	private os: MiOS; |  | ||||||
|  |  | ||||||
| 	constructor(os: MiOS, me) { |  | ||||||
| 		super(); |  | ||||||
|  |  | ||||||
| 		this.me = me; |  | ||||||
| 		this.os = os; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	public getConnection() { |  | ||||||
| 		if (this.connection == null) { |  | ||||||
| 			this.connection = new HybridTimelineStream(this.os, this.me); |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		return this.connection; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| @@ -1,34 +0,0 @@ | |||||||
| import Stream from './stream'; |  | ||||||
| import StreamManager from './stream-manager'; |  | ||||||
| import MiOS from '../../../mios'; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Local timeline stream connection |  | ||||||
|  */ |  | ||||||
| export class LocalTimelineStream extends Stream { |  | ||||||
| 	constructor(os: MiOS, me) { |  | ||||||
| 		super(os, 'local-timeline', me ? { |  | ||||||
| 			i: me.token |  | ||||||
| 		} : {}); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| export class LocalTimelineStreamManager extends StreamManager<LocalTimelineStream> { |  | ||||||
| 	private me; |  | ||||||
| 	private os: MiOS; |  | ||||||
|  |  | ||||||
| 	constructor(os: MiOS, me) { |  | ||||||
| 		super(); |  | ||||||
|  |  | ||||||
| 		this.me = me; |  | ||||||
| 		this.os = os; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	public getConnection() { |  | ||||||
| 		if (this.connection == null) { |  | ||||||
| 			this.connection = new LocalTimelineStream(this.os, this.me); |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		return this.connection; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| @@ -1,34 +0,0 @@ | |||||||
| import Stream from './stream'; |  | ||||||
| import StreamManager from './stream-manager'; |  | ||||||
| import MiOS from '../../../mios'; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Messaging index stream connection |  | ||||||
|  */ |  | ||||||
| export class MessagingIndexStream extends Stream { |  | ||||||
| 	constructor(os: MiOS, me) { |  | ||||||
| 		super(os, 'messaging-index', { |  | ||||||
| 			i: me.token |  | ||||||
| 		}); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| export class MessagingIndexStreamManager extends StreamManager<MessagingIndexStream> { |  | ||||||
| 	private me; |  | ||||||
| 	private os: MiOS; |  | ||||||
|  |  | ||||||
| 	constructor(os: MiOS, me) { |  | ||||||
| 		super(); |  | ||||||
|  |  | ||||||
| 		this.me = me; |  | ||||||
| 		this.os = os; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	public getConnection() { |  | ||||||
| 		if (this.connection == null) { |  | ||||||
| 			this.connection = new MessagingIndexStream(this.os, this.me); |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		return this.connection; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| @@ -1,20 +0,0 @@ | |||||||
| import Stream from './stream'; |  | ||||||
| import MiOS from '../../../mios'; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Messaging stream connection |  | ||||||
|  */ |  | ||||||
| export class MessagingStream extends Stream { |  | ||||||
| 	constructor(os: MiOS, me, otherparty) { |  | ||||||
| 		super(os, 'messaging', { |  | ||||||
| 			i: me.token, |  | ||||||
| 			otherparty |  | ||||||
| 		}); |  | ||||||
|  |  | ||||||
| 		(this as any).on('_connected_', () => { |  | ||||||
| 			this.send({ |  | ||||||
| 				i: me.token |  | ||||||
| 			}); |  | ||||||
| 		}); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| @@ -1,30 +0,0 @@ | |||||||
| import Stream from './stream'; |  | ||||||
| import StreamManager from './stream-manager'; |  | ||||||
| import MiOS from '../../../mios'; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Notes stats stream connection |  | ||||||
|  */ |  | ||||||
| export class NotesStatsStream extends Stream { |  | ||||||
| 	constructor(os: MiOS) { |  | ||||||
| 		super(os, 'notes-stats'); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| export class NotesStatsStreamManager extends StreamManager<NotesStatsStream> { |  | ||||||
| 	private os: MiOS; |  | ||||||
|  |  | ||||||
| 	constructor(os: MiOS) { |  | ||||||
| 		super(); |  | ||||||
|  |  | ||||||
| 		this.os = os; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	public getConnection() { |  | ||||||
| 		if (this.connection == null) { |  | ||||||
| 			this.connection = new NotesStatsStream(this.os); |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		return this.connection; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| @@ -1,30 +0,0 @@ | |||||||
| import Stream from './stream'; |  | ||||||
| import StreamManager from './stream-manager'; |  | ||||||
| import MiOS from '../../../mios'; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Server stats stream connection |  | ||||||
|  */ |  | ||||||
| export class ServerStatsStream extends Stream { |  | ||||||
| 	constructor(os: MiOS) { |  | ||||||
| 		super(os, 'server-stats'); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| export class ServerStatsStreamManager extends StreamManager<ServerStatsStream> { |  | ||||||
| 	private os: MiOS; |  | ||||||
|  |  | ||||||
| 	constructor(os: MiOS) { |  | ||||||
| 		super(); |  | ||||||
|  |  | ||||||
| 		this.os = os; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	public getConnection() { |  | ||||||
| 		if (this.connection == null) { |  | ||||||
| 			this.connection = new ServerStatsStream(this.os); |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		return this.connection; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| @@ -1,109 +0,0 @@ | |||||||
| import { EventEmitter } from 'eventemitter3'; |  | ||||||
| import * as uuid from 'uuid'; |  | ||||||
| import Connection from './stream'; |  | ||||||
| import { erase } from '../../../../../prelude/array'; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * ストリーム接続を管理するクラス |  | ||||||
|  * 複数の場所から同じストリームを利用する際、接続をまとめたりする |  | ||||||
|  */ |  | ||||||
| export default abstract class StreamManager<T extends Connection> extends EventEmitter { |  | ||||||
| 	private _connection: T = null; |  | ||||||
|  |  | ||||||
| 	private disposeTimerId: any; |  | ||||||
|  |  | ||||||
| 	/** |  | ||||||
| 	 * コネクションを必要としているユーザー |  | ||||||
| 	 */ |  | ||||||
| 	private users = []; |  | ||||||
|  |  | ||||||
| 	protected set connection(connection: T) { |  | ||||||
| 		this._connection = connection; |  | ||||||
|  |  | ||||||
| 		if (this._connection == null) { |  | ||||||
| 			this.emit('disconnected'); |  | ||||||
| 		} else { |  | ||||||
| 			this.emit('connected', this._connection); |  | ||||||
|  |  | ||||||
| 			this._connection.on('_connected_', () => { |  | ||||||
| 				this.emit('_connected_'); |  | ||||||
| 			}); |  | ||||||
|  |  | ||||||
| 			this._connection.on('_disconnected_', () => { |  | ||||||
| 				this.emit('_disconnected_'); |  | ||||||
| 			}); |  | ||||||
|  |  | ||||||
| 			this._connection.user = 'Managed'; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	protected get connection() { |  | ||||||
| 		return this._connection; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	/** |  | ||||||
| 	 * コネクションを持っているか否か |  | ||||||
| 	 */ |  | ||||||
| 	public get hasConnection() { |  | ||||||
| 		return this._connection != null; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	public get state(): string { |  | ||||||
| 		if (!this.hasConnection) return 'no-connection'; |  | ||||||
| 		return this._connection.state; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	/** |  | ||||||
| 	 * コネクションを要求します |  | ||||||
| 	 */ |  | ||||||
| 	public abstract getConnection(): T; |  | ||||||
|  |  | ||||||
| 	/** |  | ||||||
| 	 * 現在接続しているコネクションを取得します |  | ||||||
| 	 */ |  | ||||||
| 	public borrow() { |  | ||||||
| 		return this._connection; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	/** |  | ||||||
| 	 * コネクションを要求するためのユーザーIDを発行します |  | ||||||
| 	 */ |  | ||||||
| 	public use() { |  | ||||||
| 		// タイマー解除 |  | ||||||
| 		if (this.disposeTimerId) { |  | ||||||
| 			clearTimeout(this.disposeTimerId); |  | ||||||
| 			this.disposeTimerId = null; |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		// ユーザーID生成 |  | ||||||
| 		const userId = uuid(); |  | ||||||
|  |  | ||||||
| 		this.users.push(userId); |  | ||||||
|  |  | ||||||
| 		this._connection.user = `Managed (${ this.users.length })`; |  | ||||||
|  |  | ||||||
| 		return userId; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	/** |  | ||||||
| 	 * コネクションを利用し終わってもう必要ないことを通知します |  | ||||||
| 	 * @param userId use で発行したユーザーID |  | ||||||
| 	 */ |  | ||||||
| 	public dispose(userId) { |  | ||||||
| 		this.users = erase(userId, this.users); |  | ||||||
|  |  | ||||||
| 		this._connection.user = `Managed (${ this.users.length })`; |  | ||||||
|  |  | ||||||
| 		// 誰もコネクションの利用者がいなくなったら |  | ||||||
| 		if (this.users.length == 0) { |  | ||||||
| 			// また直ぐに再利用される可能性があるので、一定時間待ち、 |  | ||||||
| 			// 新たな利用者が現れなければコネクションを切断する |  | ||||||
| 			this.disposeTimerId = setTimeout(() => { |  | ||||||
| 				this.disposeTimerId = null; |  | ||||||
|  |  | ||||||
| 				this.connection.close(); |  | ||||||
| 				this.connection = null; |  | ||||||
| 			}, 3000); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| @@ -1,137 +0,0 @@ | |||||||
| import { EventEmitter } from 'eventemitter3'; |  | ||||||
| import * as uuid from 'uuid'; |  | ||||||
| import * as ReconnectingWebsocket from 'reconnecting-websocket'; |  | ||||||
| import { wsUrl } from '../../../config'; |  | ||||||
| import MiOS from '../../../mios'; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Misskey stream connection |  | ||||||
|  */ |  | ||||||
| export default class Connection extends EventEmitter { |  | ||||||
| 	public state: string; |  | ||||||
| 	private buffer: any[]; |  | ||||||
| 	public socket: ReconnectingWebsocket; |  | ||||||
| 	public name: string; |  | ||||||
| 	public connectedAt: Date; |  | ||||||
| 	public user: string = null; |  | ||||||
| 	public in: number = 0; |  | ||||||
| 	public out: number = 0; |  | ||||||
| 	public inout: Array<{ |  | ||||||
| 		type: 'in' | 'out', |  | ||||||
| 		at: Date, |  | ||||||
| 		data: string |  | ||||||
| 	}> = []; |  | ||||||
| 	public id: string; |  | ||||||
| 	public isSuspended = false; |  | ||||||
| 	private os: MiOS; |  | ||||||
|  |  | ||||||
| 	constructor(os: MiOS, endpoint, params?) { |  | ||||||
| 		super(); |  | ||||||
|  |  | ||||||
| 		//#region BIND |  | ||||||
| 		this.onOpen =    this.onOpen.bind(this); |  | ||||||
| 		this.onClose =   this.onClose.bind(this); |  | ||||||
| 		this.onMessage = this.onMessage.bind(this); |  | ||||||
| 		this.send =      this.send.bind(this); |  | ||||||
| 		this.close =     this.close.bind(this); |  | ||||||
| 		//#endregion |  | ||||||
|  |  | ||||||
| 		this.id = uuid(); |  | ||||||
| 		this.os = os; |  | ||||||
| 		this.name = endpoint; |  | ||||||
| 		this.state = 'initializing'; |  | ||||||
| 		this.buffer = []; |  | ||||||
|  |  | ||||||
| 		const query = params |  | ||||||
| 			? Object.keys(params) |  | ||||||
| 				.map(k => `${encodeURIComponent(k)}=${encodeURIComponent(params[k])}`) |  | ||||||
| 				.join('&') |  | ||||||
| 			: null; |  | ||||||
|  |  | ||||||
| 		this.socket = new ReconnectingWebsocket(`${wsUrl}/${endpoint}${query ? `?${query}` : ''}`); |  | ||||||
| 		this.socket.addEventListener('open', this.onOpen); |  | ||||||
| 		this.socket.addEventListener('close', this.onClose); |  | ||||||
| 		this.socket.addEventListener('message', this.onMessage); |  | ||||||
|  |  | ||||||
| 		// Register this connection for debugging |  | ||||||
| 		this.os.registerStreamConnection(this); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	/** |  | ||||||
| 	 * Callback of when open connection |  | ||||||
| 	 */ |  | ||||||
| 	private onOpen() { |  | ||||||
| 		this.state = 'connected'; |  | ||||||
| 		this.emit('_connected_'); |  | ||||||
|  |  | ||||||
| 		this.connectedAt = new Date(); |  | ||||||
|  |  | ||||||
| 		// バッファーを処理 |  | ||||||
| 		const _buffer = [].concat(this.buffer); // Shallow copy |  | ||||||
| 		this.buffer = []; // Clear buffer |  | ||||||
| 		_buffer.forEach(data => { |  | ||||||
| 			this.send(data); // Resend each buffered messages |  | ||||||
|  |  | ||||||
| 			if (this.os.debug) { |  | ||||||
| 				this.out++; |  | ||||||
| 				this.inout.push({ type: 'out', at: new Date(), data }); |  | ||||||
| 			} |  | ||||||
| 		}); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	/** |  | ||||||
| 	 * Callback of when close connection |  | ||||||
| 	 */ |  | ||||||
| 	private onClose() { |  | ||||||
| 		this.state = 'reconnecting'; |  | ||||||
| 		this.emit('_disconnected_'); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	/** |  | ||||||
| 	 * Callback of when received a message from connection |  | ||||||
| 	 */ |  | ||||||
| 	private onMessage(message) { |  | ||||||
| 		if (this.isSuspended) return; |  | ||||||
|  |  | ||||||
| 		if (this.os.debug) { |  | ||||||
| 			this.in++; |  | ||||||
| 			this.inout.push({ type: 'in', at: new Date(), data: message.data }); |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		try { |  | ||||||
| 			const msg = JSON.parse(message.data); |  | ||||||
| 			if (msg.type) this.emit(msg.type, msg.body); |  | ||||||
| 		} catch (e) { |  | ||||||
| 			// noop |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	/** |  | ||||||
| 	 * Send a message to connection |  | ||||||
| 	 */ |  | ||||||
| 	public send(data) { |  | ||||||
| 		if (this.isSuspended) return; |  | ||||||
|  |  | ||||||
| 		// まだ接続が確立されていなかったらバッファリングして次に接続した時に送信する |  | ||||||
| 		if (this.state != 'connected') { |  | ||||||
| 			this.buffer.push(data); |  | ||||||
| 			return; |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		if (this.os.debug) { |  | ||||||
| 			this.out++; |  | ||||||
| 			this.inout.push({ type: 'out', at: new Date(), data }); |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		this.socket.send(JSON.stringify(data)); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	/** |  | ||||||
| 	 * Close this connection |  | ||||||
| 	 */ |  | ||||||
| 	public close() { |  | ||||||
| 		this.os.unregisterStreamConnection(this); |  | ||||||
| 		this.socket.removeEventListener('open', this.onOpen); |  | ||||||
| 		this.socket.removeEventListener('message', this.onMessage); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| @@ -1,17 +0,0 @@ | |||||||
| import Stream from './stream'; |  | ||||||
| import MiOS from '../../mios'; |  | ||||||
|  |  | ||||||
| export class UserListStream extends Stream { |  | ||||||
| 	constructor(os: MiOS, me, listId) { |  | ||||||
| 		super(os, 'user-list', { |  | ||||||
| 			i: me.token, |  | ||||||
| 			listId |  | ||||||
| 		}); |  | ||||||
|  |  | ||||||
| 		(this as any).on('_connected_', () => { |  | ||||||
| 			this.send({ |  | ||||||
| 				i: me.token |  | ||||||
| 			}); |  | ||||||
| 		}); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| @@ -259,15 +259,13 @@ export default Vue.extend({ | |||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <style lang="stylus" scoped> | <style lang="stylus" scoped> | ||||||
| @import '~const.styl' | .mk-autocomplete | ||||||
|  |  | ||||||
| root(isDark) |  | ||||||
| 	position fixed | 	position fixed | ||||||
| 	z-index 65535 | 	z-index 65535 | ||||||
| 	max-width 100% | 	max-width 100% | ||||||
| 	margin-top calc(1em + 8px) | 	margin-top calc(1em + 8px) | ||||||
| 	overflow hidden | 	overflow hidden | ||||||
| 	background isDark ? #313543 : #fff | 	background var(--faceHeader) | ||||||
| 	border solid 1px rgba(#000, 0.1) | 	border solid 1px rgba(#000, 0.1) | ||||||
| 	border-radius 4px | 	border-radius 4px | ||||||
| 	transition top 0.1s ease, left 0.1s ease | 	transition top 0.1s ease, left 0.1s ease | ||||||
| @@ -299,16 +297,16 @@ root(isDark) | |||||||
| 				text-overflow ellipsis | 				text-overflow ellipsis | ||||||
|  |  | ||||||
| 			&:hover | 			&:hover | ||||||
| 				background isDark ? rgba(#fff, 0.1) : rgba(#000, 0.1) | 				background var(--autocompleteItemHoverBg) | ||||||
|  |  | ||||||
| 			&[data-selected='true'] | 			&[data-selected='true'] | ||||||
| 				background $theme-color | 				background var(--primary) | ||||||
|  |  | ||||||
| 				&, * | 				&, * | ||||||
| 					color #fff !important | 					color #fff !important | ||||||
|  |  | ||||||
| 			&:active | 			&:active | ||||||
| 				background darken($theme-color, 10%) | 				background var(--primaryDarken10) | ||||||
|  |  | ||||||
| 				&, * | 				&, * | ||||||
| 					color #fff !important | 					color #fff !important | ||||||
| @@ -325,15 +323,15 @@ root(isDark) | |||||||
|  |  | ||||||
| 		.name | 		.name | ||||||
| 			margin 0 8px 0 0 | 			margin 0 8px 0 0 | ||||||
| 			color isDark ? rgba(#fff, 0.8) : rgba(#000, 0.8) | 			color var(--autocompleteItemText) | ||||||
|  |  | ||||||
| 		.username | 		.username | ||||||
| 			color isDark ? rgba(#fff, 0.3) : rgba(#000, 0.3) | 			color var(--autocompleteItemTextSub) | ||||||
|  |  | ||||||
| 	> .hashtags > li | 	> .hashtags > li | ||||||
|  |  | ||||||
| 		.name | 		.name | ||||||
| 			color isDark ? rgba(#fff, 0.8) : rgba(#000, 0.8) | 			color var(--autocompleteItemText) | ||||||
|  |  | ||||||
| 	> .emojis > li | 	> .emojis > li | ||||||
|  |  | ||||||
| @@ -343,15 +341,9 @@ root(isDark) | |||||||
| 			width 24px | 			width 24px | ||||||
|  |  | ||||||
| 		.name | 		.name | ||||||
| 			color isDark ? rgba(#fff, 0.8) : rgba(#000, 0.8) | 			color var(--autocompleteItemText) | ||||||
|  |  | ||||||
| 		.alias | 		.alias | ||||||
| 			margin 0 0 0 8px | 			margin 0 0 0 8px | ||||||
| 			color isDark ? rgba(#fff, 0.3) : rgba(#000, 0.3) | 			color var(--autocompleteItemTextSub) | ||||||
|  |  | ||||||
| .mk-autocomplete[data-darkmode] |  | ||||||
| 	root(true) |  | ||||||
|  |  | ||||||
| .mk-autocomplete:not([data-darkmode]) |  | ||||||
| 	root(false) |  | ||||||
| </style> | </style> | ||||||
|   | |||||||
| @@ -58,6 +58,11 @@ export default Vue.extend({ | |||||||
| 			}; | 			}; | ||||||
| 		} | 		} | ||||||
| 	}, | 	}, | ||||||
|  | 	mounted() { | ||||||
|  | 		if (this.user.avatarColor) { | ||||||
|  | 			this.$el.style.color = `rgb(${this.user.avatarColor.slice(0, 3).join(',')})`; | ||||||
|  | 		} | ||||||
|  | 	}, | ||||||
| 	methods: { | 	methods: { | ||||||
| 		onClick(e) { | 		onClick(e) { | ||||||
| 			this.$emit('click', e); | 			this.$emit('click', e); | ||||||
| @@ -67,8 +72,7 @@ export default Vue.extend({ | |||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <style lang="stylus" scoped> | <style lang="stylus" scoped> | ||||||
|  | .mk-avatar | ||||||
| root(isDark) |  | ||||||
| 	display inline-block | 	display inline-block | ||||||
| 	vertical-align bottom | 	vertical-align bottom | ||||||
|  |  | ||||||
| @@ -79,7 +83,7 @@ root(isDark) | |||||||
| 	&.cat::before, | 	&.cat::before, | ||||||
| 	&.cat::after | 	&.cat::after | ||||||
| 		background #df548f | 		background #df548f | ||||||
| 		border solid 4px isDark ? #e0eefd : #202224 | 		border solid 4px currentColor | ||||||
| 		box-sizing border-box | 		box-sizing border-box | ||||||
| 		content '' | 		content '' | ||||||
| 		display inline-block | 		display inline-block | ||||||
| @@ -105,9 +109,4 @@ root(isDark) | |||||||
| 		transition border-radius 1s ease | 		transition border-radius 1s ease | ||||||
| 		z-index 1 | 		z-index 1 | ||||||
|  |  | ||||||
| .mk-avatar[data-darkmode] |  | ||||||
| 	root(true) |  | ||||||
|  |  | ||||||
| .mk-avatar:not([data-darkmode]) |  | ||||||
| 	root(false) |  | ||||||
| </style> | </style> | ||||||
|   | |||||||
| @@ -39,7 +39,7 @@ export default Vue.extend({ | |||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <style lang="stylus" scoped> | <style lang="stylus" scoped> | ||||||
| @import '~const.styl' |  | ||||||
|  |  | ||||||
| .mk-connect-failed | .mk-connect-failed | ||||||
| 	width 100% | 	width 100% | ||||||
| @@ -70,17 +70,17 @@ export default Vue.extend({ | |||||||
| 		display block | 		display block | ||||||
| 		margin 1em auto 0 auto | 		margin 1em auto 0 auto | ||||||
| 		padding 8px 10px | 		padding 8px 10px | ||||||
| 		color $theme-color-foreground | 		color var(--primaryForeground) | ||||||
| 		background $theme-color | 		background var(--primary) | ||||||
|  |  | ||||||
| 		&:focus | 		&:focus | ||||||
| 			outline solid 3px rgba($theme-color, 0.3) | 			outline solid 3px var(--primaryAlpha03) | ||||||
|  |  | ||||||
| 		&:hover | 		&:hover | ||||||
| 			background lighten($theme-color, 10%) | 			background var(--primaryLighten10) | ||||||
|  |  | ||||||
| 		&:active | 		&:active | ||||||
| 			background darken($theme-color, 10%) | 			background var(--primaryDarken10) | ||||||
|  |  | ||||||
| 	> .thanks | 	> .thanks | ||||||
| 		display block | 		display block | ||||||
|   | |||||||
| @@ -22,23 +22,17 @@ export default Vue.extend({ | |||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <style lang="stylus" scoped> | <style lang="stylus" scoped> | ||||||
| root(isDark) | .nrvgflfuaxwgkxoynpnumyookecqrrvh | ||||||
| 	display inline-block | 	display inline-block | ||||||
| 	padding 4px 8px | 	padding 4px 8px | ||||||
| 	font-size 0.7em | 	font-size 0.7em | ||||||
| 	color isDark ? #393f4f : #fff | 	color var(--cwButtonFg) | ||||||
| 	background isDark ? #687390 : #b1b9c1 | 	background var(--cwButtonBg) | ||||||
| 	border-radius 2px | 	border-radius 2px | ||||||
| 	cursor pointer | 	cursor pointer | ||||||
| 	user-select none | 	user-select none | ||||||
|  |  | ||||||
| 	&:hover | 	&:hover | ||||||
| 		background isDark ? #707b97 : #bbc4ce | 		background var(--cwButtonHoverBg) | ||||||
|  |  | ||||||
| .nrvgflfuaxwgkxoynpnumyookecqrrvh[data-darkmode] |  | ||||||
| 	root(true) |  | ||||||
|  |  | ||||||
| .nrvgflfuaxwgkxoynpnumyookecqrrvh:not([data-darkmode]) |  | ||||||
| 	root(false) |  | ||||||
|  |  | ||||||
| </style> | </style> | ||||||
|   | |||||||
| @@ -9,7 +9,7 @@ | |||||||
| </template> | </template> | ||||||
|  |  | ||||||
| <style lang="stylus" scoped> | <style lang="stylus" scoped> | ||||||
| @import '~const.styl' |  | ||||||
|  |  | ||||||
| .a | .a | ||||||
| 	display block | 	display block | ||||||
| @@ -18,8 +18,8 @@ | |||||||
| 		display block | 		display block | ||||||
| 		//fill #151513 | 		//fill #151513 | ||||||
| 		//color #fff | 		//color #fff | ||||||
| 		fill $theme-color | 		fill var(--primary) | ||||||
| 		color $theme-color-foreground | 		color var(--primaryForeground) | ||||||
|  |  | ||||||
| 		.octo-arm | 		.octo-arm | ||||||
| 			transform-origin 130px 106px | 			transform-origin 130px 106px | ||||||
|   | |||||||
| @@ -186,9 +186,8 @@ export default Vue.extend({ | |||||||
| 		if (this.game.isStarted && !this.game.isEnded) { | 		if (this.game.isStarted && !this.game.isEnded) { | ||||||
| 			this.pollingClock = setInterval(() => { | 			this.pollingClock = setInterval(() => { | ||||||
| 				const crc32 = CRC32.str(this.logs.map(x => x.pos.toString()).join('')); | 				const crc32 = CRC32.str(this.logs.map(x => x.pos.toString()).join('')); | ||||||
| 				this.connection.send({ | 				this.connection.send('check', { | ||||||
| 					type: 'check', | 					crc32: crc32 | ||||||
| 					crc32 |  | ||||||
| 				}); | 				}); | ||||||
| 			}, 3000); | 			}, 3000); | ||||||
| 		} | 		} | ||||||
| @@ -224,9 +223,8 @@ export default Vue.extend({ | |||||||
| 				sound.play(); | 				sound.play(); | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			this.connection.send({ | 			this.connection.send('set', { | ||||||
| 				type: 'set', | 				pos: pos | ||||||
| 				pos |  | ||||||
| 			}); | 			}); | ||||||
|  |  | ||||||
| 			this.checkEnd(); | 			this.checkEnd(); | ||||||
| @@ -304,9 +302,7 @@ export default Vue.extend({ | |||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <style lang="stylus" scoped> | <style lang="stylus" scoped> | ||||||
| @import '~const.styl' | .xqnhankfuuilcwvhgsopeqncafzsquya | ||||||
|  |  | ||||||
| root(isDark) |  | ||||||
| 	text-align center | 	text-align center | ||||||
|  |  | ||||||
| 	> .go-index | 	> .go-index | ||||||
| @@ -319,7 +315,7 @@ root(isDark) | |||||||
|  |  | ||||||
| 	> header | 	> header | ||||||
| 		padding 8px | 		padding 8px | ||||||
| 		border-bottom dashed 1px isDark ? #4c5761 : #c4cdd4 | 		border-bottom dashed 1px var(--reversiGameHeaderLine) | ||||||
|  |  | ||||||
| 		a | 		a | ||||||
| 			color inherit | 			color inherit | ||||||
| @@ -386,30 +382,30 @@ root(isDark) | |||||||
| 						user-select none | 						user-select none | ||||||
|  |  | ||||||
| 					&.empty | 					&.empty | ||||||
| 						border solid 2px isDark ? #51595f : #eee | 						border solid 2px var(--reversiGameEmptyCell) | ||||||
|  |  | ||||||
| 					&.empty.can | 					&.empty.can | ||||||
| 						background isDark ? #51595f : #eee | 						background var(--reversiGameEmptyCell) | ||||||
|  |  | ||||||
| 					&.empty.myTurn | 					&.empty.myTurn | ||||||
| 						border-color isDark ? #6a767f : #ddd | 						border-color var(--reversiGameEmptyCellMyTurn) | ||||||
|  |  | ||||||
| 						&.can | 						&.can | ||||||
| 							background isDark ? #51595f : #eee | 							background var(--reversiGameEmptyCellCanPut) | ||||||
| 							cursor pointer | 							cursor pointer | ||||||
|  |  | ||||||
| 							&:hover | 							&:hover | ||||||
| 								border-color darken($theme-color, 10%) | 								border-color var(--primaryDarken10) | ||||||
| 								background $theme-color | 								background var(--primary) | ||||||
|  |  | ||||||
| 							&:active | 							&:active | ||||||
| 								background darken($theme-color, 10%) | 								background var(--primaryDarken10) | ||||||
|  |  | ||||||
| 					&.prev | 					&.prev | ||||||
| 						box-shadow 0 0 0 4px rgba($theme-color, 0.7) | 						box-shadow 0 0 0 4px var(--primaryAlpha07) | ||||||
|  |  | ||||||
| 					&.isEnded | 					&.isEnded | ||||||
| 						border-color isDark ? #6a767f : #ddd | 						border-color var(--reversiGameEmptyCellMyTurn) | ||||||
|  |  | ||||||
| 					&.none | 					&.none | ||||||
| 						border-color transparent !important | 						border-color transparent !important | ||||||
| @@ -458,10 +454,4 @@ root(isDark) | |||||||
| 			margin 0 8px | 			margin 0 8px | ||||||
| 			min-width 70px | 			min-width 70px | ||||||
|  |  | ||||||
| .xqnhankfuuilcwvhgsopeqncafzsquya[data-darkmode] |  | ||||||
| 	root(true) |  | ||||||
|  |  | ||||||
| .xqnhankfuuilcwvhgsopeqncafzsquya:not([data-darkmode]) |  | ||||||
| 	root(false) |  | ||||||
|  |  | ||||||
| </style> | </style> | ||||||
|   | |||||||
| @@ -9,7 +9,6 @@ | |||||||
| import Vue from 'vue'; | import Vue from 'vue'; | ||||||
| import XGame from './reversi.game.vue'; | import XGame from './reversi.game.vue'; | ||||||
| import XRoom from './reversi.room.vue'; | import XRoom from './reversi.room.vue'; | ||||||
| import { ReversiGameStream } from '../../../../scripts/streaming/games/reversi/reversi-game'; |  | ||||||
|  |  | ||||||
| export default Vue.extend({ | export default Vue.extend({ | ||||||
| 	components: { | 	components: { | ||||||
| @@ -34,12 +33,13 @@ export default Vue.extend({ | |||||||
| 	}, | 	}, | ||||||
| 	created() { | 	created() { | ||||||
| 		this.g = this.game; | 		this.g = this.game; | ||||||
| 		this.connection = new ReversiGameStream((this as any).os, this.$store.state.i, this.game); | 		this.connection = (this as any).os.stream.connectToChannel('gamesReversiGame', { | ||||||
|  | 			gameId: this.game.id | ||||||
|  | 		}); | ||||||
| 		this.connection.on('started', this.onStarted); | 		this.connection.on('started', this.onStarted); | ||||||
| 	}, | 	}, | ||||||
| 	beforeDestroy() { | 	beforeDestroy() { | ||||||
| 		this.connection.off('started', this.onStarted); | 		this.connection.dispose(); | ||||||
| 		this.connection.close(); |  | ||||||
| 	}, | 	}, | ||||||
| 	methods: { | 	methods: { | ||||||
| 		onStarted(game) { | 		onStarted(game) { | ||||||
|   | |||||||
| @@ -59,15 +59,13 @@ export default Vue.extend({ | |||||||
| 			myGames: [], | 			myGames: [], | ||||||
| 			matching: null, | 			matching: null, | ||||||
| 			invitations: [], | 			invitations: [], | ||||||
| 			connection: null, | 			connection: null | ||||||
| 			connectionId: null |  | ||||||
| 		}; | 		}; | ||||||
| 	}, | 	}, | ||||||
|  |  | ||||||
| 	mounted() { | 	mounted() { | ||||||
| 		if (this.$store.getters.isSignedIn) { | 		if (this.$store.getters.isSignedIn) { | ||||||
| 			this.connection = (this as any).os.streams.reversiStream.getConnection(); | 			this.connection = (this as any).os.stream.useSharedConnection('gamesReversi'); | ||||||
| 			this.connectionId = (this as any).os.streams.reversiStream.use(); |  | ||||||
|  |  | ||||||
| 			this.connection.on('invited', this.onInvited); | 			this.connection.on('invited', this.onInvited); | ||||||
|  |  | ||||||
| @@ -90,8 +88,7 @@ export default Vue.extend({ | |||||||
|  |  | ||||||
| 	beforeDestroy() { | 	beforeDestroy() { | ||||||
| 		if (this.connection) { | 		if (this.connection) { | ||||||
| 			this.connection.off('invited', this.onInvited); | 			this.connection.dispose(); | ||||||
| 			(this as any).os.streams.reversiStream.dispose(this.connectionId); |  | ||||||
| 		} | 		} | ||||||
| 	}, | 	}, | ||||||
|  |  | ||||||
| @@ -138,9 +135,7 @@ export default Vue.extend({ | |||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <style lang="stylus" scoped> | <style lang="stylus" scoped> | ||||||
| @import '~const.styl' | .phgnkghfpyvkrvwiajkiuoxyrdaqpzcx | ||||||
|  |  | ||||||
| root(isDark) |  | ||||||
| 	> h1 | 	> h1 | ||||||
| 		margin 0 | 		margin 0 | ||||||
| 		padding 24px | 		padding 24px | ||||||
| @@ -148,7 +143,7 @@ root(isDark) | |||||||
| 		text-align center | 		text-align center | ||||||
| 		font-weight normal | 		font-weight normal | ||||||
| 		color #fff | 		color #fff | ||||||
| 		background linear-gradient(to bottom, isDark ? #45730e : #8bca3e, isDark ? #464300 : #d6cf31) | 		background linear-gradient(to bottom, var(--reversiBannerGradientStart), var(--reversiBannerGradientEnd)) | ||||||
|  |  | ||||||
| 		& + p | 		& + p | ||||||
| 			margin 0 | 			margin 0 | ||||||
| @@ -156,7 +151,7 @@ root(isDark) | |||||||
| 			margin-bottom 12px | 			margin-bottom 12px | ||||||
| 			text-align center | 			text-align center | ||||||
| 			font-size 14px | 			font-size 14px | ||||||
| 			border-bottom solid 1px isDark ? #535f65 : #d3d9dc | 			border-bottom solid 1px var(--faceDivider) | ||||||
|  |  | ||||||
| 	> .play | 	> .play | ||||||
| 		margin 0 auto | 		margin 0 auto | ||||||
| @@ -171,14 +166,14 @@ root(isDark) | |||||||
| 				padding 16px | 				padding 16px | ||||||
| 				font-size 14px | 				font-size 14px | ||||||
| 				text-align left | 				text-align left | ||||||
| 				background isDark ? #282c37 : #f5f5f5 | 				background var(--reversiDescBg) | ||||||
| 				border-radius 8px | 				border-radius 8px | ||||||
|  |  | ||||||
| 	> section | 	> section | ||||||
| 		margin 0 auto | 		margin 0 auto | ||||||
| 		padding 0 16px 16px 16px | 		padding 0 16px 16px 16px | ||||||
| 		max-width 500px | 		max-width 500px | ||||||
| 		border-top solid 1px isDark ? #535f65 : #d3d9dc | 		border-top solid 1px var(--faceDivider) | ||||||
|  |  | ||||||
| 		> h2 | 		> h2 | ||||||
| 			margin 0 | 			margin 0 | ||||||
| @@ -189,9 +184,9 @@ root(isDark) | |||||||
| 	.invitation | 	.invitation | ||||||
| 		margin 8px 0 | 		margin 8px 0 | ||||||
| 		padding 8px | 		padding 8px | ||||||
| 		color isDark ? #fff : #677f84 | 		color var(--text) | ||||||
| 		background isDark ? #282c37 : #fff | 		background var(--face) | ||||||
| 		box-shadow 0 2px 16px rgba(#000, isDark ? 0.7 : 0.15) | 		box-shadow 0 2px 16px var(--reversiListItemShadow) | ||||||
| 		border-radius 6px | 		border-radius 6px | ||||||
| 		cursor pointer | 		cursor pointer | ||||||
|  |  | ||||||
| @@ -200,13 +195,13 @@ root(isDark) | |||||||
| 			user-select none | 			user-select none | ||||||
|  |  | ||||||
| 		&:focus | 		&:focus | ||||||
| 			border-color $theme-color | 			border-color var(--primary) | ||||||
|  |  | ||||||
| 		&:hover | 		&:hover | ||||||
| 			background isDark ? #313543 : #f5f5f5 | 			box-shadow 0 0 0 100px inset rgba(0, 0, 0, 0.05) | ||||||
|  |  | ||||||
| 		&:active | 		&:active | ||||||
| 			background isDark ? #1e222b : #eee | 			box-shadow 0 0 0 100px inset rgba(0, 0, 0, 0.1) | ||||||
|  |  | ||||||
| 		> .avatar | 		> .avatar | ||||||
| 			width 32px | 			width 32px | ||||||
| @@ -221,9 +216,9 @@ root(isDark) | |||||||
| 		display block | 		display block | ||||||
| 		margin 8px 0 | 		margin 8px 0 | ||||||
| 		padding 8px | 		padding 8px | ||||||
| 		color isDark ? #fff : #677f84 | 		color var(--text) | ||||||
| 		background isDark ? #282c37 : #fff | 		background var(--face) | ||||||
| 		box-shadow 0 2px 16px rgba(#000, isDark ? 0.7 : 0.15) | 		box-shadow 0 2px 16px var(--reversiListItemShadow) | ||||||
| 		border-radius 6px | 		border-radius 6px | ||||||
| 		cursor pointer | 		cursor pointer | ||||||
|  |  | ||||||
| @@ -232,10 +227,10 @@ root(isDark) | |||||||
| 			user-select none | 			user-select none | ||||||
|  |  | ||||||
| 		&:hover | 		&:hover | ||||||
| 			background isDark ? #313543 : #f5f5f5 | 			box-shadow 0 0 0 100px inset rgba(0, 0, 0, 0.05) | ||||||
|  |  | ||||||
| 		&:active | 		&:active | ||||||
| 			background isDark ? #1e222b : #eee | 			box-shadow 0 0 0 100px inset rgba(0, 0, 0, 0.1) | ||||||
|  |  | ||||||
| 		> .avatar | 		> .avatar | ||||||
| 			width 32px | 			width 32px | ||||||
| @@ -246,10 +241,4 @@ root(isDark) | |||||||
| 			margin 0 8px | 			margin 0 8px | ||||||
| 			line-height 32px | 			line-height 32px | ||||||
|  |  | ||||||
| .phgnkghfpyvkrvwiajkiuoxyrdaqpzcx[data-darkmode] |  | ||||||
| 	root(true) |  | ||||||
|  |  | ||||||
| .phgnkghfpyvkrvwiajkiuoxyrdaqpzcx:not([data-darkmode]) |  | ||||||
| 	root(false) |  | ||||||
|  |  | ||||||
| </style> | </style> | ||||||
|   | |||||||
| @@ -47,9 +47,9 @@ | |||||||
| 			</header> | 			</header> | ||||||
|  |  | ||||||
| 			<div> | 			<div> | ||||||
| 				<mk-switch v-model="game.settings.isLlotheo" @change="updateSettings" text="%i18n:@is-llotheo%"/> | 				<ui-switch v-model="game.settings.isLlotheo" @change="updateSettings">%i18n:@is-llotheo%</ui-switch> | ||||||
| 				<mk-switch v-model="game.settings.loopedBoard" @change="updateSettings" text="%i18n:@looped-map%"/> | 				<ui-switch v-model="game.settings.loopedBoard" @change="updateSettings">%i18n:@looped-map%</ui-switch> | ||||||
| 				<mk-switch v-model="game.settings.canPutEverywhere" @change="updateSettings" text="%i18n:@can-put-everywhere%"/> | 				<ui-switch v-model="game.settings.canPutEverywhere" @change="updateSettings">%i18n:@can-put-everywhere%</ui-switch> | ||||||
| 			</div> | 			</div> | ||||||
| 		</div> | 		</div> | ||||||
|  |  | ||||||
| @@ -60,7 +60,7 @@ | |||||||
|  |  | ||||||
| 			<div> | 			<div> | ||||||
| 				<template v-for="item in form"> | 				<template v-for="item in form"> | ||||||
| 					<mk-switch v-if="item.type == 'switch'" v-model="item.value" :key="item.id" :text="item.label" @change="onChangeForm(item)">{{ item.desc || '' }}</mk-switch> | 					<ui-switch v-if="item.type == 'switch'" v-model="item.value" :key="item.id" :text="item.label" @change="onChangeForm(item)">{{ item.desc || '' }}</ui-switch> | ||||||
|  |  | ||||||
| 					<div class="card" v-if="item.type == 'radio'" :key="item.id"> | 					<div class="card" v-if="item.type == 'radio'" :key="item.id"> | ||||||
| 						<header> | 						<header> | ||||||
| @@ -149,9 +149,9 @@ export default Vue.extend({ | |||||||
| 	}, | 	}, | ||||||
|  |  | ||||||
| 	created() { | 	created() { | ||||||
| 		this.connection.on('change-accepts', this.onChangeAccepts); | 		this.connection.on('changeAccepts', this.onChangeAccepts); | ||||||
| 		this.connection.on('update-settings', this.onUpdateSettings); | 		this.connection.on('updateSettings', this.onUpdateSettings); | ||||||
| 		this.connection.on('init-form', this.onInitForm); | 		this.connection.on('initForm', this.onInitForm); | ||||||
| 		this.connection.on('message', this.onMessage); | 		this.connection.on('message', this.onMessage); | ||||||
|  |  | ||||||
| 		if (this.game.user1Id != this.$store.state.i.id && this.game.settings.form1) this.form = this.game.settings.form1; | 		if (this.game.user1Id != this.$store.state.i.id && this.game.settings.form1) this.form = this.game.settings.form1; | ||||||
| @@ -159,9 +159,9 @@ export default Vue.extend({ | |||||||
| 	}, | 	}, | ||||||
|  |  | ||||||
| 	beforeDestroy() { | 	beforeDestroy() { | ||||||
| 		this.connection.off('change-accepts', this.onChangeAccepts); | 		this.connection.off('changeAccepts', this.onChangeAccepts); | ||||||
| 		this.connection.off('update-settings', this.onUpdateSettings); | 		this.connection.off('updateSettings', this.onUpdateSettings); | ||||||
| 		this.connection.off('init-form', this.onInitForm); | 		this.connection.off('initForm', this.onInitForm); | ||||||
| 		this.connection.off('message', this.onMessage); | 		this.connection.off('message', this.onMessage); | ||||||
| 	}, | 	}, | ||||||
|  |  | ||||||
| @@ -171,15 +171,11 @@ export default Vue.extend({ | |||||||
| 		}, | 		}, | ||||||
|  |  | ||||||
| 		accept() { | 		accept() { | ||||||
| 			this.connection.send({ | 			this.connection.send('accept', {}); | ||||||
| 				type: 'accept' |  | ||||||
| 			}); |  | ||||||
| 		}, | 		}, | ||||||
|  |  | ||||||
| 		cancel() { | 		cancel() { | ||||||
| 			this.connection.send({ | 			this.connection.send('cancelAccept', {}); | ||||||
| 				type: 'cancel-accept' |  | ||||||
| 			}); |  | ||||||
| 		}, | 		}, | ||||||
|  |  | ||||||
| 		onChangeAccepts(accepts) { | 		onChangeAccepts(accepts) { | ||||||
| @@ -189,8 +185,7 @@ export default Vue.extend({ | |||||||
| 		}, | 		}, | ||||||
|  |  | ||||||
| 		updateSettings() { | 		updateSettings() { | ||||||
| 			this.connection.send({ | 			this.connection.send('updateSettings', { | ||||||
| 				type: 'update-settings', |  | ||||||
| 				settings: this.game.settings | 				settings: this.game.settings | ||||||
| 			}); | 			}); | ||||||
| 		}, | 		}, | ||||||
| @@ -216,8 +211,7 @@ export default Vue.extend({ | |||||||
| 		}, | 		}, | ||||||
|  |  | ||||||
| 		onChangeForm(item) { | 		onChangeForm(item) { | ||||||
| 			this.connection.send({ | 			this.connection.send('updateForm', { | ||||||
| 				type: 'update-form', |  | ||||||
| 				id: item.id, | 				id: item.id, | ||||||
| 				value: item.value | 				value: item.value | ||||||
| 			}); | 			}); | ||||||
| @@ -238,9 +232,9 @@ export default Vue.extend({ | |||||||
| 			const y = Math.floor(pos / this.game.settings.map[0].length); | 			const y = Math.floor(pos / this.game.settings.map[0].length); | ||||||
| 			const newPixel = | 			const newPixel = | ||||||
| 				pixel == ' ' ? '-' : | 				pixel == ' ' ? '-' : | ||||||
| 					pixel == '-' ? 'b' : | 				pixel == '-' ? 'b' : | ||||||
| 						pixel == 'b' ? 'w' : | 				pixel == 'b' ? 'w' : | ||||||
| 							' '; | 				' '; | ||||||
| 			const line = this.game.settings.map[y].split(''); | 			const line = this.game.settings.map[y].split(''); | ||||||
| 			line[x] = newPixel; | 			line[x] = newPixel; | ||||||
| 			this.$set(this.game.settings.map, y, line.join('')); | 			this.$set(this.game.settings.map, y, line.join('')); | ||||||
| @@ -252,11 +246,9 @@ export default Vue.extend({ | |||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <style lang="stylus" scoped> | <style lang="stylus" scoped> | ||||||
| @import '~const.styl' | .urbixznjwwuukfsckrwzwsqzsxornqij | ||||||
|  |  | ||||||
| root(isDark) |  | ||||||
| 	text-align center | 	text-align center | ||||||
| 	background isDark ? #191b22 : #f9f9f9 | 	background var(--bg) | ||||||
|  |  | ||||||
| 	> header | 	> header | ||||||
| 		padding 8px | 		padding 8px | ||||||
| @@ -273,10 +265,10 @@ root(isDark) | |||||||
| 					> select | 					> select | ||||||
| 						width 100% | 						width 100% | ||||||
| 						padding 12px 14px | 						padding 12px 14px | ||||||
| 						background isDark ? #282C37 : #fff | 						background var(--face) | ||||||
| 						border 1px solid isDark ? #6a707d : #dcdfe6 | 						border 1px solid var(--reversiMapSelectBorder) | ||||||
| 						border-radius 4px | 						border-radius 4px | ||||||
| 						color isDark ? #fff : #606266 | 						color var(--text) | ||||||
| 						cursor pointer | 						cursor pointer | ||||||
| 						transition border-color 0.2s cubic-bezier(0.645, 0.045, 0.355, 1) | 						transition border-color 0.2s cubic-bezier(0.645, 0.045, 0.355, 1) | ||||||
| 						-webkit-appearance none | 						-webkit-appearance none | ||||||
| @@ -284,17 +276,18 @@ root(isDark) | |||||||
| 						appearance none | 						appearance none | ||||||
|  |  | ||||||
| 						&:hover | 						&:hover | ||||||
| 							border-color isDark ? #a7aebd : #c0c4cc | 							border-color var(--reversiMapSelectHoverBorder) | ||||||
|  |  | ||||||
| 						&:focus | 						&:focus | ||||||
| 						&:active | 						&:active | ||||||
| 							border-color $theme-color | 							border-color var(--primary) | ||||||
|  |  | ||||||
| 				> div | 				> div | ||||||
| 					> .random | 					> .random | ||||||
| 						padding 32px 0 | 						padding 32px 0 | ||||||
| 						font-size 64px | 						font-size 64px | ||||||
| 						color isDark ? #4e5961 : #d8d8d8 | 						color var(--text) | ||||||
|  | 						opacity 0.7 | ||||||
|  |  | ||||||
| 					> .board | 					> .board | ||||||
| 						display grid | 						display grid | ||||||
| @@ -302,11 +295,11 @@ root(isDark) | |||||||
| 						width 300px | 						width 300px | ||||||
| 						height 300px | 						height 300px | ||||||
| 						margin 0 auto | 						margin 0 auto | ||||||
| 						color isDark ? #fff : #444 | 						color var(--text) | ||||||
|  |  | ||||||
| 						> div | 						> div | ||||||
| 							background transparent | 							background transparent | ||||||
| 							border solid 2px isDark ? #6a767f : #ddd | 							border solid 2px var(--faceDivider) | ||||||
| 							border-radius 6px | 							border-radius 6px | ||||||
| 							overflow hidden | 							overflow hidden | ||||||
| 							cursor pointer | 							cursor pointer | ||||||
| @@ -331,32 +324,26 @@ root(isDark) | |||||||
| 		.card | 		.card | ||||||
| 			max-width 400px | 			max-width 400px | ||||||
| 			border-radius 4px | 			border-radius 4px | ||||||
| 			background isDark ? #282C37 : #fff | 			background var(--face) | ||||||
| 			color isDark ? #fff : #303133 | 			color var(--text) | ||||||
| 			box-shadow 0 2px 12px 0 rgba(#000, isDark ? 0.7 : 0.1) | 			box-shadow 0 2px 12px 0 var(--reversiRoomFormShadow) | ||||||
|  |  | ||||||
| 			> header | 			> header | ||||||
| 				padding 18px 20px | 				padding 18px 20px | ||||||
| 				border-bottom 1px solid isDark ? #1c2023 : #ebeef5 | 				border-bottom 1px solid var(--faceDivider) | ||||||
|  |  | ||||||
| 			> div | 			> div | ||||||
| 				padding 20px | 				padding 20px | ||||||
| 				color isDark ? #fff : #606266 | 				color var(--text) | ||||||
|  |  | ||||||
| 	> footer | 	> footer | ||||||
| 		position sticky | 		position sticky | ||||||
| 		bottom 0 | 		bottom 0 | ||||||
| 		padding 16px | 		padding 16px | ||||||
| 		background rgba(isDark ? #191b22 : #fff, 0.9) | 		background var(--reversiRoomFooterBg) | ||||||
| 		border-top solid 1px isDark ? #606266 : #c4cdd4 | 		border-top solid 1px var(--faceDivider) | ||||||
|  |  | ||||||
| 		> .status | 		> .status | ||||||
| 			margin 0 0 16px 0 | 			margin 0 0 16px 0 | ||||||
|  |  | ||||||
| .urbixznjwwuukfsckrwzwsqzsxornqij[data-darkmode] |  | ||||||
| 	root(true) |  | ||||||
|  |  | ||||||
| .urbixznjwwuukfsckrwzwsqzsxornqij:not([data-darkmode]) |  | ||||||
| 	root(false) |  | ||||||
|  |  | ||||||
| </style> | </style> | ||||||
|   | |||||||
| @@ -47,7 +47,6 @@ export default Vue.extend({ | |||||||
| 			game: null, | 			game: null, | ||||||
| 			matching: null, | 			matching: null, | ||||||
| 			connection: null, | 			connection: null, | ||||||
| 			connectionId: null, |  | ||||||
| 			pingClock: null | 			pingClock: null | ||||||
| 		}; | 		}; | ||||||
| 	}, | 	}, | ||||||
| @@ -66,15 +65,13 @@ export default Vue.extend({ | |||||||
| 		this.fetch(); | 		this.fetch(); | ||||||
|  |  | ||||||
| 		if (this.$store.getters.isSignedIn) { | 		if (this.$store.getters.isSignedIn) { | ||||||
| 			this.connection = (this as any).os.streams.reversiStream.getConnection(); | 			this.connection = (this as any).os.stream.useSharedConnection('gamesReversi'); | ||||||
| 			this.connectionId = (this as any).os.streams.reversiStream.use(); |  | ||||||
|  |  | ||||||
| 			this.connection.on('matched', this.onMatched); | 			this.connection.on('matched', this.onMatched); | ||||||
|  |  | ||||||
| 			this.pingClock = setInterval(() => { | 			this.pingClock = setInterval(() => { | ||||||
| 				if (this.matching) { | 				if (this.matching) { | ||||||
| 					this.connection.send({ | 					this.connection.send('ping', { | ||||||
| 						type: 'ping', |  | ||||||
| 						id: this.matching.id | 						id: this.matching.id | ||||||
| 					}); | 					}); | ||||||
| 				} | 				} | ||||||
| @@ -84,9 +81,7 @@ export default Vue.extend({ | |||||||
|  |  | ||||||
| 	beforeDestroy() { | 	beforeDestroy() { | ||||||
| 		if (this.connection) { | 		if (this.connection) { | ||||||
| 			this.connection.off('matched', this.onMatched); | 			this.connection.dispose(); | ||||||
| 			(this as any).os.streams.reversiStream.dispose(this.connectionId); |  | ||||||
|  |  | ||||||
| 			clearInterval(this.pingClock); | 			clearInterval(this.pingClock); | ||||||
| 		} | 		} | ||||||
| 	}, | 	}, | ||||||
| @@ -156,11 +151,9 @@ export default Vue.extend({ | |||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <style lang="stylus" scoped> | <style lang="stylus" scoped> | ||||||
| @import '~const.styl' | .vchtoekanapleubgzioubdtmlkribzfd | ||||||
|  | 	color var(--text) | ||||||
| root(isDark) | 	background var(--bg) | ||||||
| 	color isDark ? #fff : #677f84 |  | ||||||
| 	background isDark ? #191b22 : #fff |  | ||||||
|  |  | ||||||
| 	> .matching | 	> .matching | ||||||
| 		> h1 | 		> h1 | ||||||
| @@ -177,10 +170,4 @@ root(isDark) | |||||||
| 			text-align center | 			text-align center | ||||||
| 			border-top dashed 1px #c4cdd4 | 			border-top dashed 1px #c4cdd4 | ||||||
|  |  | ||||||
| .vchtoekanapleubgzioubdtmlkribzfd[data-darkmode] |  | ||||||
| 	root(true) |  | ||||||
|  |  | ||||||
| .vchtoekanapleubgzioubdtmlkribzfd:not([data-darkmode]) |  | ||||||
| 	root(false) |  | ||||||
|  |  | ||||||
| </style> | </style> | ||||||
|   | |||||||
| @@ -26,7 +26,7 @@ export default Vue.extend({ | |||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <style lang="stylus" scoped> | <style lang="stylus" scoped> | ||||||
| root(isDark) | .mk-google | ||||||
| 	display flex | 	display flex | ||||||
| 	margin 8px 0 | 	margin 8px 0 | ||||||
|  |  | ||||||
| @@ -37,31 +37,25 @@ root(isDark) | |||||||
| 		height 40px | 		height 40px | ||||||
| 		font-family sans-serif | 		font-family sans-serif | ||||||
| 		font-size 16px | 		font-size 16px | ||||||
| 		color isDark ? #dee4e8 : #55595c | 		color var(--googleSearchFg) | ||||||
| 		background isDark ? #191b22 : #fff | 		background var(--googleSearchBg) | ||||||
| 		border solid 1px isDark ? #495156 : #dadada | 		border solid 1px var(--googleSearchBorder) | ||||||
| 		border-radius 4px 0 0 4px | 		border-radius 4px 0 0 4px | ||||||
|  |  | ||||||
| 		&:hover | 		&:hover | ||||||
| 			border-color isDark ? #777c86 : #b0b0b0 | 			border-color var(--googleSearchHoverBorder) | ||||||
|  |  | ||||||
| 	> button | 	> button | ||||||
| 		flex-shrink 0 | 		flex-shrink 0 | ||||||
| 		padding 0 16px | 		padding 0 16px | ||||||
| 		border solid 1px isDark ? #495156 : #dadada | 		border solid 1px var(--googleSearchBorder) | ||||||
| 		border-left none | 		border-left none | ||||||
| 		border-radius 0 4px 4px 0 | 		border-radius 0 4px 4px 0 | ||||||
|  |  | ||||||
| 		&:hover | 		&:hover | ||||||
| 			background-color isDark ? #2e3440 : #eee | 			background-color var(--googleSearchHoverButton) | ||||||
|  |  | ||||||
| 		&:active | 		&:active | ||||||
| 			box-shadow 0 2px 4px rgba(#000, 0.15) inset | 			box-shadow 0 2px 4px rgba(#000, 0.15) inset | ||||||
|  |  | ||||||
| .mk-google[data-darkmode] |  | ||||||
| 	root(true) |  | ||||||
|  |  | ||||||
| .mk-google:not([data-darkmode]) |  | ||||||
| 	root(false) |  | ||||||
|  |  | ||||||
| </style> | </style> | ||||||
|   | |||||||
| @@ -1,5 +1,6 @@ | |||||||
| import Vue from 'vue'; | import Vue from 'vue'; | ||||||
|  |  | ||||||
|  | import theme from './theme.vue'; | ||||||
| import instance from './instance.vue'; | import instance from './instance.vue'; | ||||||
| import cwButton from './cw-button.vue'; | import cwButton from './cw-button.vue'; | ||||||
| import tagCloud from './tag-cloud.vue'; | import tagCloud from './tag-cloud.vue'; | ||||||
| @@ -30,7 +31,6 @@ import messagingRoom from './messaging-room.vue'; | |||||||
| import urlPreview from './url-preview.vue'; | import urlPreview from './url-preview.vue'; | ||||||
| import twitterSetting from './twitter-setting.vue'; | import twitterSetting from './twitter-setting.vue'; | ||||||
| import fileTypeIcon from './file-type-icon.vue'; | import fileTypeIcon from './file-type-icon.vue'; | ||||||
| import Switch from './switch.vue'; |  | ||||||
| import Reversi from './games/reversi/reversi.vue'; | import Reversi from './games/reversi/reversi.vue'; | ||||||
| import welcomeTimeline from './welcome-timeline.vue'; | import welcomeTimeline from './welcome-timeline.vue'; | ||||||
| import uiInput from './ui/input.vue'; | import uiInput from './ui/input.vue'; | ||||||
| @@ -44,6 +44,7 @@ import uiSelect from './ui/select.vue'; | |||||||
| import formButton from './ui/form/button.vue'; | import formButton from './ui/form/button.vue'; | ||||||
| import formRadio from './ui/form/radio.vue'; | import formRadio from './ui/form/radio.vue'; | ||||||
|  |  | ||||||
|  | Vue.component('mk-theme', theme); | ||||||
| Vue.component('mk-instance', instance); | Vue.component('mk-instance', instance); | ||||||
| Vue.component('mk-cw-button', cwButton); | Vue.component('mk-cw-button', cwButton); | ||||||
| Vue.component('mk-tag-cloud', tagCloud); | Vue.component('mk-tag-cloud', tagCloud); | ||||||
| @@ -74,7 +75,6 @@ Vue.component('mk-messaging-room', messagingRoom); | |||||||
| Vue.component('mk-url-preview', urlPreview); | Vue.component('mk-url-preview', urlPreview); | ||||||
| Vue.component('mk-twitter-setting', twitterSetting); | Vue.component('mk-twitter-setting', twitterSetting); | ||||||
| Vue.component('mk-file-type-icon', fileTypeIcon); | Vue.component('mk-file-type-icon', fileTypeIcon); | ||||||
| Vue.component('mk-switch', Switch); |  | ||||||
| Vue.component('mk-reversi', Reversi); | Vue.component('mk-reversi', Reversi); | ||||||
| Vue.component('mk-welcome-timeline', welcomeTimeline); | Vue.component('mk-welcome-timeline', welcomeTimeline); | ||||||
| Vue.component('ui-input', uiInput); | Vue.component('ui-input', uiInput); | ||||||
|   | |||||||
| @@ -26,9 +26,9 @@ export default Vue.extend({ | |||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <style lang="stylus" scoped> | <style lang="stylus" scoped> | ||||||
| root(isDark) | .nhasjydimbopojusarffqjyktglcuxjy | ||||||
| 	color isDark ? #fff : #5b646f | 	color var(--text) | ||||||
| 	background isDark ? #21242f : #fff | 	background var(--face) | ||||||
| 	text-align center | 	text-align center | ||||||
|  |  | ||||||
| 	> .banner | 	> .banner | ||||||
| @@ -48,10 +48,4 @@ root(isDark) | |||||||
| 		display block | 		display block | ||||||
| 		padding-bottom 16px | 		padding-bottom 16px | ||||||
|  |  | ||||||
| .nhasjydimbopojusarffqjyktglcuxjy[data-darkmode] |  | ||||||
| 	root(true) |  | ||||||
|  |  | ||||||
| .nhasjydimbopojusarffqjyktglcuxjy:not([data-darkmode]) |  | ||||||
| 	root(false) |  | ||||||
|  |  | ||||||
| </style> | </style> | ||||||
|   | |||||||
| @@ -43,7 +43,7 @@ export default Vue.extend({ | |||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <style lang="stylus" scoped> | <style lang="stylus" scoped> | ||||||
| root(isDark) | .mk-media-banner | ||||||
| 	width 100% | 	width 100% | ||||||
| 	border-radius 4px | 	border-radius 4px | ||||||
| 	margin-top 4px | 	margin-top 4px | ||||||
| @@ -71,7 +71,7 @@ root(isDark) | |||||||
| 			font-size 1.6em | 			font-size 1.6em | ||||||
|  |  | ||||||
| 	> .download | 	> .download | ||||||
| 		background isDark ? #21242d : #f7f7f7 | 		background var(--noteAttachedFile) | ||||||
|  |  | ||||||
| 	> .sensitive | 	> .sensitive | ||||||
| 		background #111 | 		background #111 | ||||||
| @@ -82,9 +82,4 @@ root(isDark) | |||||||
| 			display block | 			display block | ||||||
| 			width 100% | 			width 100% | ||||||
|  |  | ||||||
| .mk-media-banner[data-darkmode] |  | ||||||
| 	root(true) |  | ||||||
|  |  | ||||||
| .mk-media-banner:not([data-darkmode]) |  | ||||||
| 	root(false) |  | ||||||
| </style> | </style> | ||||||
|   | |||||||
| @@ -117,10 +117,8 @@ export default Vue.extend({ | |||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <style lang="stylus" scoped> | <style lang="stylus" scoped> | ||||||
| @import '~const.styl' | .onchrpzrvnoruiaenfcqvccjfuupzzwv | ||||||
|  | 	$bg-color = var(--popupBg) | ||||||
| root(isDark) |  | ||||||
| 	$bg-color = isDark ? #2c303c : #fff |  | ||||||
| 	$border-color = rgba(27, 31, 35, 0.15) | 	$border-color = rgba(27, 31, 35, 0.15) | ||||||
|  |  | ||||||
| 	position initial | 	position initial | ||||||
| @@ -132,7 +130,7 @@ root(isDark) | |||||||
| 		z-index 10000 | 		z-index 10000 | ||||||
| 		width 100% | 		width 100% | ||||||
| 		height 100% | 		height 100% | ||||||
| 		background rgba(#000, isDark ? 0.5 : 0.1) | 		background var(--modalBackdrop) | ||||||
| 		opacity 0 | 		opacity 0 | ||||||
|  |  | ||||||
| 	> .popover | 	> .popover | ||||||
| @@ -179,26 +177,20 @@ root(isDark) | |||||||
| 			display block | 			display block | ||||||
| 			padding 8px 16px | 			padding 8px 16px | ||||||
| 			width 100% | 			width 100% | ||||||
| 			color isDark ? #d6dce2 : #111 | 			color var(--popupFg) | ||||||
|  |  | ||||||
| 			&:hover | 			&:hover | ||||||
| 				color $theme-color-foreground | 				color var(--primaryForeground) | ||||||
| 				background $theme-color | 				background var(--primary) | ||||||
| 				text-decoration none | 				text-decoration none | ||||||
|  |  | ||||||
| 			&:active | 			&:active | ||||||
| 				color $theme-color-foreground | 				color var(--primaryForeground) | ||||||
| 				background darken($theme-color, 10%) | 				background var(--primaryDarken10) | ||||||
|  |  | ||||||
| 		> div | 		> div | ||||||
| 			margin 8px 0 | 			margin 8px 0 | ||||||
| 			height 1px | 			height 1px | ||||||
| 			background isDark ? #1c2023 : #eee | 			background var(--faceDivider) | ||||||
|  |  | ||||||
| .onchrpzrvnoruiaenfcqvccjfuupzzwv[data-darkmode] |  | ||||||
| 	root(true) |  | ||||||
|  |  | ||||||
| .onchrpzrvnoruiaenfcqvccjfuupzzwv:not([data-darkmode]) |  | ||||||
| 	root(false) |  | ||||||
|  |  | ||||||
| </style> | </style> | ||||||
|   | |||||||
| @@ -195,9 +195,7 @@ export default Vue.extend({ | |||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <style lang="stylus" scoped> | <style lang="stylus" scoped> | ||||||
| @import '~const.styl' | .mk-messaging-form | ||||||
|  |  | ||||||
| root(isDark) |  | ||||||
| 	> textarea | 	> textarea | ||||||
| 		cursor auto | 		cursor auto | ||||||
| 		display block | 		display block | ||||||
| @@ -209,10 +207,10 @@ root(isDark) | |||||||
| 		padding 8px | 		padding 8px | ||||||
| 		resize none | 		resize none | ||||||
| 		font-size 1em | 		font-size 1em | ||||||
| 		color isDark ? #fff : #000 | 		color var(--inputText) | ||||||
| 		outline none | 		outline none | ||||||
| 		border none | 		border none | ||||||
| 		border-top solid 1px isDark ? #4b5056 : #eee | 		border-top solid 1px var(--faceDivider) | ||||||
| 		border-radius 0 | 		border-radius 0 | ||||||
| 		box-shadow none | 		box-shadow none | ||||||
| 		background transparent | 		background transparent | ||||||
| @@ -234,10 +232,10 @@ root(isDark) | |||||||
| 		transition color 0.1s ease | 		transition color 0.1s ease | ||||||
|  |  | ||||||
| 		&:hover | 		&:hover | ||||||
| 			color $theme-color | 			color var(--primary) | ||||||
|  |  | ||||||
| 		&:active | 		&:active | ||||||
| 			color darken($theme-color, 10%) | 			color var(--primaryDarken10) | ||||||
| 			transition color 0s ease | 			transition color 0s ease | ||||||
|  |  | ||||||
| 	.files | 	.files | ||||||
| @@ -293,19 +291,13 @@ root(isDark) | |||||||
| 		transition color 0.1s ease | 		transition color 0.1s ease | ||||||
|  |  | ||||||
| 		&:hover | 		&:hover | ||||||
| 			color $theme-color | 			color var(--primary) | ||||||
|  |  | ||||||
| 		&:active | 		&:active | ||||||
| 			color darken($theme-color, 10%) | 			color var(--primaryDarken10) | ||||||
| 			transition color 0s ease | 			transition color 0s ease | ||||||
|  |  | ||||||
| 	input[type=file] | 	input[type=file] | ||||||
| 		display none | 		display none | ||||||
|  |  | ||||||
| .mk-messaging-form[data-darkmode] |  | ||||||
| 	root(true) |  | ||||||
|  |  | ||||||
| .mk-messaging-form:not([data-darkmode]) |  | ||||||
| 	root(false) |  | ||||||
|  |  | ||||||
| </style> | </style> | ||||||
|   | |||||||
| @@ -59,10 +59,8 @@ export default Vue.extend({ | |||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <style lang="stylus" scoped> | <style lang="stylus" scoped> | ||||||
| @import '~const.styl' | .message | ||||||
|  | 	$me-balloon-color = var(--primary) | ||||||
| root(isDark) |  | ||||||
| 	$me-balloon-color = $theme-color |  | ||||||
|  |  | ||||||
| 	padding 10px 12px 10px 12px | 	padding 10px 12px 10px 12px | ||||||
| 	background-color transparent | 	background-color transparent | ||||||
| @@ -179,7 +177,7 @@ root(isDark) | |||||||
| 			display block | 			display block | ||||||
| 			margin 2px 0 0 0 | 			margin 2px 0 0 0 | ||||||
| 			font-size 10px | 			font-size 10px | ||||||
| 			color isDark ? rgba(#fff, 0.4) : rgba(#000, 0.4) | 			color var(--messagingRoomMessageInfo) | ||||||
|  |  | ||||||
| 			> [data-fa] | 			> [data-fa] | ||||||
| 				margin-left 4px | 				margin-left 4px | ||||||
| @@ -192,7 +190,7 @@ root(isDark) | |||||||
| 			padding-left 66px | 			padding-left 66px | ||||||
|  |  | ||||||
| 			> .balloon | 			> .balloon | ||||||
| 				$color = isDark ? #2d3338 : #eee | 				$color = var(--messagingRoomMessageBg) | ||||||
| 				float left | 				float left | ||||||
| 				background $color | 				background $color | ||||||
|  |  | ||||||
| @@ -208,8 +206,7 @@ root(isDark) | |||||||
|  |  | ||||||
| 				> .content | 				> .content | ||||||
| 					> .text | 					> .text | ||||||
| 						if isDark | 							color var(--messagingRoomMessageFg) | ||||||
| 							color #fff |  | ||||||
|  |  | ||||||
| 			> footer | 			> footer | ||||||
| 				text-align left | 				text-align left | ||||||
| @@ -250,18 +247,9 @@ root(isDark) | |||||||
|  |  | ||||||
| 				> .read | 				> .read | ||||||
| 					user-select none | 					user-select none | ||||||
| 					margin 0 4px 0 0 |  | ||||||
| 					color isDark ? rgba(#fff, 0.5) : rgba(#000, 0.5) |  | ||||||
| 					font-size 11px |  | ||||||
|  |  | ||||||
| 	&[data-is-deleted] | 	&[data-is-deleted] | ||||||
| 		> .balloon | 		> .balloon | ||||||
| 			opacity 0.5 | 			opacity 0.5 | ||||||
|  |  | ||||||
| .message[data-darkmode] |  | ||||||
| 	root(true) |  | ||||||
|  |  | ||||||
| .message:not([data-darkmode]) |  | ||||||
| 	root(false) |  | ||||||
|  |  | ||||||
| </style> | </style> | ||||||
|   | |||||||
| @@ -30,7 +30,6 @@ | |||||||
|  |  | ||||||
| <script lang="ts"> | <script lang="ts"> | ||||||
| import Vue from 'vue'; | import Vue from 'vue'; | ||||||
| import { MessagingStream } from '../../scripts/streaming/messaging'; |  | ||||||
| import XMessage from './messaging-room.message.vue'; | import XMessage from './messaging-room.message.vue'; | ||||||
| import XForm from './messaging-room.form.vue'; | import XForm from './messaging-room.form.vue'; | ||||||
| import { url } from '../../../config'; | import { url } from '../../../config'; | ||||||
| @@ -72,7 +71,7 @@ export default Vue.extend({ | |||||||
| 	}, | 	}, | ||||||
|  |  | ||||||
| 	mounted() { | 	mounted() { | ||||||
| 		this.connection = new MessagingStream((this as any).os, this.$store.state.i, this.user.id); | 		this.connection =((this as any).os.stream.connectToChannel('messaging', { otherparty: this.user.id }); | ||||||
|  |  | ||||||
| 		this.connection.on('message', this.onMessage); | 		this.connection.on('message', this.onMessage); | ||||||
| 		this.connection.on('read', this.onRead); | 		this.connection.on('read', this.onRead); | ||||||
| @@ -92,9 +91,7 @@ export default Vue.extend({ | |||||||
| 	}, | 	}, | ||||||
|  |  | ||||||
| 	beforeDestroy() { | 	beforeDestroy() { | ||||||
| 		this.connection.off('message', this.onMessage); | 		this.connection.dispose(); | ||||||
| 		this.connection.off('read', this.onRead); |  | ||||||
| 		this.connection.close(); |  | ||||||
|  |  | ||||||
| 		if (this.isNaked) { | 		if (this.isNaked) { | ||||||
| 			window.removeEventListener('scroll', this.onScroll); | 			window.removeEventListener('scroll', this.onScroll); | ||||||
| @@ -177,8 +174,7 @@ export default Vue.extend({ | |||||||
|  |  | ||||||
| 			this.messages.push(message); | 			this.messages.push(message); | ||||||
| 			if (message.userId != this.$store.state.i.id && !document.hidden) { | 			if (message.userId != this.$store.state.i.id && !document.hidden) { | ||||||
| 				this.connection.send({ | 				this.connection.send('read', { | ||||||
| 					type: 'read', |  | ||||||
| 					id: message.id | 					id: message.id | ||||||
| 				}); | 				}); | ||||||
| 			} | 			} | ||||||
| @@ -250,8 +246,7 @@ export default Vue.extend({ | |||||||
| 			if (document.hidden) return; | 			if (document.hidden) return; | ||||||
| 			this.messages.forEach(message => { | 			this.messages.forEach(message => { | ||||||
| 				if (message.userId !== this.$store.state.i.id && !message.isRead) { | 				if (message.userId !== this.$store.state.i.id && !message.isRead) { | ||||||
| 					this.connection.send({ | 					this.connection.send('read', { | ||||||
| 						type: 'read', |  | ||||||
| 						id: message.id | 						id: message.id | ||||||
| 					}); | 					}); | ||||||
| 				} | 				} | ||||||
| @@ -262,14 +257,12 @@ export default Vue.extend({ | |||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <style lang="stylus" scoped> | <style lang="stylus" scoped> | ||||||
| @import '~const.styl' | .mk-messaging-room | ||||||
|  |  | ||||||
| root(isDark) |  | ||||||
| 	display flex | 	display flex | ||||||
| 	flex 1 | 	flex 1 | ||||||
| 	flex-direction column | 	flex-direction column | ||||||
| 	height 100% | 	height 100% | ||||||
| 	background isDark ? #191b22 : #fff | 	background var(--messagingRoomBg) | ||||||
|  |  | ||||||
| 	> .body | 	> .body | ||||||
| 		width 100% | 		width 100% | ||||||
| @@ -277,24 +270,15 @@ root(isDark) | |||||||
| 		margin 0 auto | 		margin 0 auto | ||||||
| 		flex 1 | 		flex 1 | ||||||
|  |  | ||||||
| 		> .init | 		> .init, | ||||||
| 			width 100% |  | ||||||
| 			margin 0 |  | ||||||
| 			padding 16px 8px 8px 8px |  | ||||||
| 			text-align center |  | ||||||
| 			font-size 0.8em |  | ||||||
| 			color rgba(isDark ? #fff : #000, 0.4) |  | ||||||
|  |  | ||||||
| 			[data-fa] |  | ||||||
| 				margin-right 4px |  | ||||||
|  |  | ||||||
| 		> .empty | 		> .empty | ||||||
| 			width 100% | 			width 100% | ||||||
| 			margin 0 | 			margin 0 | ||||||
| 			padding 16px 8px 8px 8px | 			padding 16px 8px 8px 8px | ||||||
| 			text-align center | 			text-align center | ||||||
| 			font-size 0.8em | 			font-size 0.8em | ||||||
| 			color rgba(isDark ? #fff : #000, 0.4) | 			color var(--messagingRoomInfo) | ||||||
|  | 			opacity 0.5 | ||||||
|  |  | ||||||
| 			[data-fa] | 			[data-fa] | ||||||
| 				margin-right 4px | 				margin-right 4px | ||||||
| @@ -305,7 +289,8 @@ root(isDark) | |||||||
| 			padding 16px | 			padding 16px | ||||||
| 			text-align center | 			text-align center | ||||||
| 			font-size 0.8em | 			font-size 0.8em | ||||||
| 			color rgba(isDark ? #fff : #000, 0.4) | 			color var(--messagingRoomInfo) | ||||||
|  | 			opacity 0.5 | ||||||
|  |  | ||||||
| 			[data-fa] | 			[data-fa] | ||||||
| 				margin-right 4px | 				margin-right 4px | ||||||
| @@ -349,7 +334,7 @@ root(isDark) | |||||||
| 				left 0 | 				left 0 | ||||||
| 				right 0 | 				right 0 | ||||||
| 				margin 0 auto | 				margin 0 auto | ||||||
| 				background rgba(isDark ? #fff : #000, 0.1) | 				background var(--messagingRoomDateDividerLine) | ||||||
|  |  | ||||||
| 			> span | 			> span | ||||||
| 				display inline-block | 				display inline-block | ||||||
| @@ -357,8 +342,8 @@ root(isDark) | |||||||
| 				padding 0 16px | 				padding 0 16px | ||||||
| 				//font-weight bold | 				//font-weight bold | ||||||
| 				line-height 32px | 				line-height 32px | ||||||
| 				color rgba(isDark ? #fff : #000, 0.3) | 				color var(--messagingRoomDateDividerText) | ||||||
| 				background isDark ? #191b22 : #fff | 				background var(--messagingRoomBg) | ||||||
|  |  | ||||||
| 	> footer | 	> footer | ||||||
| 		position -webkit-sticky | 		position -webkit-sticky | ||||||
| @@ -369,7 +354,7 @@ root(isDark) | |||||||
| 		max-width 600px | 		max-width 600px | ||||||
| 		margin 0 auto | 		margin 0 auto | ||||||
| 		padding 0 | 		padding 0 | ||||||
| 		background rgba(isDark ? #282c37 : #fff, 0.95) | 		//background rgba(var(--face), 0.95) | ||||||
| 		background-clip content-box | 		background-clip content-box | ||||||
|  |  | ||||||
| 		> .new-message | 		> .new-message | ||||||
| @@ -386,15 +371,15 @@ root(isDark) | |||||||
| 				cursor pointer | 				cursor pointer | ||||||
| 				line-height 32px | 				line-height 32px | ||||||
| 				font-size 12px | 				font-size 12px | ||||||
| 				color $theme-color-foreground | 				color var(--primaryForeground) | ||||||
| 				background $theme-color | 				background var(--primary) | ||||||
| 				border-radius 16px | 				border-radius 16px | ||||||
|  |  | ||||||
| 				&:hover | 				&:hover | ||||||
| 					background lighten($theme-color, 10%) | 					background var(--primaryLighten10) | ||||||
|  |  | ||||||
| 				&:active | 				&:active | ||||||
| 					background darken($theme-color, 10%) | 					background var(--primaryDarken10) | ||||||
|  |  | ||||||
| 				> [data-fa] | 				> [data-fa] | ||||||
| 					position absolute | 					position absolute | ||||||
| @@ -410,10 +395,4 @@ root(isDark) | |||||||
| 	transition opacity 0.5s | 	transition opacity 0.5s | ||||||
| 	opacity 0 | 	opacity 0 | ||||||
|  |  | ||||||
| .mk-messaging-room[data-darkmode] |  | ||||||
| 	root(true) |  | ||||||
|  |  | ||||||
| .mk-messaging-room:not([data-darkmode]) |  | ||||||
| 	root(false) |  | ||||||
|  |  | ||||||
| </style> | </style> | ||||||
|   | |||||||
| @@ -71,13 +71,11 @@ export default Vue.extend({ | |||||||
| 			messages: [], | 			messages: [], | ||||||
| 			q: null, | 			q: null, | ||||||
| 			result: [], | 			result: [], | ||||||
| 			connection: null, | 			connection: null | ||||||
| 			connectionId: null |  | ||||||
| 		}; | 		}; | ||||||
| 	}, | 	}, | ||||||
| 	mounted() { | 	mounted() { | ||||||
| 		this.connection = (this as any).os.streams.messagingIndexStream.getConnection(); | 		this.connection = (this as any).os.stream.useSharedConnection('messagingIndex'); | ||||||
| 		this.connectionId = (this as any).os.streams.messagingIndexStream.use(); |  | ||||||
|  |  | ||||||
| 		this.connection.on('message', this.onMessage); | 		this.connection.on('message', this.onMessage); | ||||||
| 		this.connection.on('read', this.onRead); | 		this.connection.on('read', this.onRead); | ||||||
| @@ -88,9 +86,7 @@ export default Vue.extend({ | |||||||
| 		}); | 		}); | ||||||
| 	}, | 	}, | ||||||
| 	beforeDestroy() { | 	beforeDestroy() { | ||||||
| 		this.connection.off('message', this.onMessage); | 		this.connection.dispose(); | ||||||
| 		this.connection.off('read', this.onRead); |  | ||||||
| 		(this as any).os.streams.messagingIndexStream.dispose(this.connectionId); |  | ||||||
| 	}, | 	}, | ||||||
| 	methods: { | 	methods: { | ||||||
| 		getAcct, | 		getAcct, | ||||||
| @@ -167,9 +163,7 @@ export default Vue.extend({ | |||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <style lang="stylus" scoped> | <style lang="stylus" scoped> | ||||||
| @import '~const.styl' | .mk-messaging | ||||||
|  |  | ||||||
| root(isDark) |  | ||||||
|  |  | ||||||
| 	&[data-compact] | 	&[data-compact] | ||||||
| 		font-size 0.8em | 		font-size 0.8em | ||||||
| @@ -204,12 +198,10 @@ root(isDark) | |||||||
| 		left 0 | 		left 0 | ||||||
| 		z-index 1 | 		z-index 1 | ||||||
| 		width 100% | 		width 100% | ||||||
| 		background #fff |  | ||||||
| 		box-shadow 0 0px 2px rgba(#000, 0.2) | 		box-shadow 0 0px 2px rgba(#000, 0.2) | ||||||
|  |  | ||||||
| 		> .form | 		> .form | ||||||
| 			padding 8px | 			background rgba(0, 0, 0, 0.02) | ||||||
| 			background isDark ? #282c37 : #f7f7f7 |  | ||||||
|  |  | ||||||
| 			> label | 			> label | ||||||
| 				display block | 				display block | ||||||
| @@ -229,32 +221,22 @@ root(isDark) | |||||||
| 					bottom 0 | 					bottom 0 | ||||||
| 					left 0 | 					left 0 | ||||||
| 					width 1em | 					width 1em | ||||||
| 					line-height 56px | 					line-height 48px | ||||||
| 					margin auto | 					margin auto | ||||||
| 					color #555 | 					color #555 | ||||||
|  |  | ||||||
| 			> input | 			> input | ||||||
| 				margin 0 | 				margin 0 | ||||||
| 				padding 0 0 0 32px | 				padding 0 0 0 42px | ||||||
| 				width 100% | 				width 100% | ||||||
| 				font-size 1em | 				font-size 1em | ||||||
| 				line-height 38px | 				line-height 48px | ||||||
| 				color #000 | 				color var(--faceText) | ||||||
| 				outline none | 				outline none | ||||||
| 				background isDark ? #191b22 : #fff | 				background transparent | ||||||
| 				border solid 1px isDark ? #495156 : #eee | 				border none | ||||||
| 				border-radius 5px | 				border-radius 5px | ||||||
| 				box-shadow none | 				box-shadow none | ||||||
| 				transition color 0.5s ease, border 0.5s ease |  | ||||||
|  |  | ||||||
| 				&:hover |  | ||||||
| 					border solid 1px isDark ? #b0b0b0 : #ddd |  | ||||||
| 					transition border 0.2s ease |  | ||||||
|  |  | ||||||
| 				&:focus |  | ||||||
| 					color darken($theme-color, 20%) |  | ||||||
| 					border solid 1px $theme-color |  | ||||||
| 					transition color 0, border 0 |  | ||||||
|  |  | ||||||
| 		> .result | 		> .result | ||||||
| 			display block | 			display block | ||||||
| @@ -287,7 +269,7 @@ root(isDark) | |||||||
| 					&:hover | 					&:hover | ||||||
| 					&:focus | 					&:focus | ||||||
| 						color #fff | 						color #fff | ||||||
| 						background $theme-color | 						background var(--primary) | ||||||
|  |  | ||||||
| 						.name | 						.name | ||||||
| 							color #fff | 							color #fff | ||||||
| @@ -297,7 +279,7 @@ root(isDark) | |||||||
|  |  | ||||||
| 					&:active | 					&:active | ||||||
| 						color #fff | 						color #fff | ||||||
| 						background darken($theme-color, 10%) | 						background var(--primaryDarken10) | ||||||
|  |  | ||||||
| 						.name | 						.name | ||||||
| 							color #fff | 							color #fff | ||||||
| @@ -329,21 +311,21 @@ root(isDark) | |||||||
| 		> a | 		> a | ||||||
| 			display block | 			display block | ||||||
| 			text-decoration none | 			text-decoration none | ||||||
| 			background isDark ? #282c37 : #fff | 			background var(--face) | ||||||
| 			border-bottom solid 1px isDark ? #1c2023 : #eee | 			border-bottom solid 1px var(--faceDivider) | ||||||
|  |  | ||||||
| 			* | 			* | ||||||
| 				pointer-events none | 				pointer-events none | ||||||
| 				user-select none | 				user-select none | ||||||
|  |  | ||||||
| 			&:hover | 			&:hover | ||||||
| 				background isDark ? #1e2129 : #fafafa | 				box-shadow 0 0 0 100px inset rgba(0, 0, 0, 0.05) | ||||||
|  |  | ||||||
| 				> .avatar | 				.avatar | ||||||
| 					filter saturate(200%) | 					filter saturate(200%) | ||||||
|  |  | ||||||
| 			&:active | 			&:active | ||||||
| 				background isDark ? #14161b : #eee | 				box-shadow 0 0 0 100px inset rgba(0, 0, 0, 0.1) | ||||||
|  |  | ||||||
| 			&[data-is-read] | 			&[data-is-read] | ||||||
| 			&[data-is-me] | 			&[data-is-me] | ||||||
| @@ -383,17 +365,17 @@ root(isDark) | |||||||
| 						overflow hidden | 						overflow hidden | ||||||
| 						text-overflow ellipsis | 						text-overflow ellipsis | ||||||
| 						font-size 1em | 						font-size 1em | ||||||
| 						color isDark ? #fff : rgba(#000, 0.9) | 						color var(--noteHeaderName) | ||||||
| 						font-weight bold | 						font-weight bold | ||||||
| 						transition all 0.1s ease | 						transition all 0.1s ease | ||||||
|  |  | ||||||
| 					> .username | 					> .username | ||||||
| 						margin 0 8px | 						margin 0 8px | ||||||
| 						color isDark ? #606984 : rgba(#000, 0.5) | 						color var(--noteHeaderAcct) | ||||||
|  |  | ||||||
| 					> .mk-time | 					> .mk-time | ||||||
| 						margin 0 0 0 auto | 						margin 0 0 0 auto | ||||||
| 						color isDark ? #606984 : rgba(#000, 0.5) | 						color var(--noteHeaderInfo) | ||||||
| 						font-size 80% | 						font-size 80% | ||||||
|  |  | ||||||
| 				> .avatar | 				> .avatar | ||||||
| @@ -413,10 +395,10 @@ root(isDark) | |||||||
| 						overflow hidden | 						overflow hidden | ||||||
| 						overflow-wrap break-word | 						overflow-wrap break-word | ||||||
| 						font-size 1.1em | 						font-size 1.1em | ||||||
| 						color isDark ? #fff : rgba(#000, 0.8) | 						color var(--faceText) | ||||||
|  |  | ||||||
| 						.me | 						.me | ||||||
| 							color isDark ? rgba(#fff, 0.7) : rgba(#000, 0.4) | 							opacity 0.7 | ||||||
|  |  | ||||||
| 					> .image | 					> .image | ||||||
| 						display block | 						display block | ||||||
| @@ -461,10 +443,4 @@ root(isDark) | |||||||
| 					> .avatar | 					> .avatar | ||||||
| 						margin 0 12px 0 0 | 						margin 0 12px 0 0 | ||||||
|  |  | ||||||
| .mk-messaging[data-darkmode] |  | ||||||
| 	root(true) |  | ||||||
|  |  | ||||||
| .mk-messaging:not([data-darkmode]) |  | ||||||
| 	root(false) |  | ||||||
|  |  | ||||||
| </style> | </style> | ||||||
|   | |||||||
| @@ -95,7 +95,8 @@ export default Vue.component('misskey-flavored-markdown', { | |||||||
| 					return [createElement(MkUrl, { | 					return [createElement(MkUrl, { | ||||||
| 						props: { | 						props: { | ||||||
| 							url: token.content, | 							url: token.content, | ||||||
| 							target: '_blank' | 							target: '_blank', | ||||||
|  | 							style: 'color:var(--mfmLink);' | ||||||
| 						} | 						} | ||||||
| 					})]; | 					})]; | ||||||
| 				} | 				} | ||||||
| @@ -106,7 +107,8 @@ export default Vue.component('misskey-flavored-markdown', { | |||||||
| 							class: 'link', | 							class: 'link', | ||||||
| 							href: token.url, | 							href: token.url, | ||||||
| 							target: '_blank', | 							target: '_blank', | ||||||
| 							title: token.url | 							title: token.url, | ||||||
|  | 							style: 'color:var(--mfmLink);' | ||||||
| 						} | 						} | ||||||
| 					}, token.title)]; | 					}, token.title)]; | ||||||
| 				} | 				} | ||||||
| @@ -116,7 +118,8 @@ export default Vue.component('misskey-flavored-markdown', { | |||||||
| 						attrs: { | 						attrs: { | ||||||
| 							href: `${url}/@${getAcct(token)}`, | 							href: `${url}/@${getAcct(token)}`, | ||||||
| 							target: '_blank', | 							target: '_blank', | ||||||
| 							dataIsMe: (this as any).i && getAcct((this as any).i) == getAcct(token) | 							dataIsMe: (this as any).i && getAcct((this as any).i) == getAcct(token), | ||||||
|  | 							style: 'color:var(--mfmMention);' | ||||||
| 						}, | 						}, | ||||||
| 						directives: [{ | 						directives: [{ | ||||||
| 							name: 'user-preview', | 							name: 'user-preview', | ||||||
| @@ -129,7 +132,8 @@ export default Vue.component('misskey-flavored-markdown', { | |||||||
| 					return [createElement('a', { | 					return [createElement('a', { | ||||||
| 						attrs: { | 						attrs: { | ||||||
| 							href: `${url}/tags/${encodeURIComponent(token.hashtag)}`, | 							href: `${url}/tags/${encodeURIComponent(token.hashtag)}`, | ||||||
| 							target: '_blank' | 							target: '_blank', | ||||||
|  | 							style: 'color:var(--mfmHashtag);' | ||||||
| 						} | 						} | ||||||
| 					}, token.content)]; | 					}, token.content)]; | ||||||
| 				} | 				} | ||||||
|   | |||||||
| @@ -42,9 +42,7 @@ export default Vue.extend({ | |||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <style lang="stylus" scoped> | <style lang="stylus" scoped> | ||||||
| @import '~const.styl' | .bvonvjxbwzaiskogyhbwgyxvcgserpmu | ||||||
|  |  | ||||||
| root(isDark) |  | ||||||
| 	display flex | 	display flex | ||||||
| 	align-items baseline | 	align-items baseline | ||||||
| 	white-space nowrap | 	white-space nowrap | ||||||
| @@ -61,7 +59,7 @@ root(isDark) | |||||||
| 		margin 0 .5em 0 0 | 		margin 0 .5em 0 0 | ||||||
| 		padding 0 | 		padding 0 | ||||||
| 		overflow hidden | 		overflow hidden | ||||||
| 		color isDark ? #fff : #627079 | 		color var(--noteHeaderName) | ||||||
| 		font-size 1em | 		font-size 1em | ||||||
| 		font-weight bold | 		font-weight bold | ||||||
| 		text-decoration none | 		text-decoration none | ||||||
| @@ -82,19 +80,19 @@ root(isDark) | |||||||
| 		margin 0 .5em 0 0 | 		margin 0 .5em 0 0 | ||||||
| 		padding 1px 6px | 		padding 1px 6px | ||||||
| 		font-size 80% | 		font-size 80% | ||||||
| 		color isDark ? #758188 : #aaa | 		color var(--noteHeaderBadgeFg) | ||||||
| 		border solid 1px isDark ? #57616f : #ddd | 		background var(--noteHeaderBadgeBg) | ||||||
| 		border-radius 3px | 		border-radius 3px | ||||||
|  |  | ||||||
| 		&.is-admin | 		&.is-admin | ||||||
| 			border-color isDark ? #d42c41 : #f56a7b | 			background var(--noteHeaderAdminBg) | ||||||
| 			color isDark ? #d42c41 : #f56a7b | 			color var(--noteHeaderAdminFg) | ||||||
|  |  | ||||||
| 	> .username | 	> .username | ||||||
| 		margin 0 .5em 0 0 | 		margin 0 .5em 0 0 | ||||||
| 		overflow hidden | 		overflow hidden | ||||||
| 		text-overflow ellipsis | 		text-overflow ellipsis | ||||||
| 		color isDark ? #606984 : #ccc | 		color var(--noteHeaderAcct) | ||||||
| 		flex-shrink 2147483647 | 		flex-shrink 2147483647 | ||||||
|  |  | ||||||
| 	> .info | 	> .info | ||||||
| @@ -102,7 +100,7 @@ root(isDark) | |||||||
| 		font-size 0.9em | 		font-size 0.9em | ||||||
|  |  | ||||||
| 		> * | 		> * | ||||||
| 			color isDark ? #606984 : #c0c0c0 | 			color var(--noteHeaderInfo) | ||||||
|  |  | ||||||
| 		> .mobile | 		> .mobile | ||||||
| 			margin-right 8px | 			margin-right 8px | ||||||
| @@ -110,15 +108,9 @@ root(isDark) | |||||||
| 		> .app | 		> .app | ||||||
| 			margin-right 8px | 			margin-right 8px | ||||||
| 			padding-right 8px | 			padding-right 8px | ||||||
| 			border-right solid 1px isDark ? #1c2023 : #eaeaea | 			border-right solid 1px var(--faceDivider) | ||||||
|  |  | ||||||
| 		> .visibility | 		> .visibility | ||||||
| 			margin-left 8px | 			margin-left 8px | ||||||
|  |  | ||||||
| .bvonvjxbwzaiskogyhbwgyxvcgserpmu[data-darkmode] |  | ||||||
| 	root(true) |  | ||||||
|  |  | ||||||
| .bvonvjxbwzaiskogyhbwgyxvcgserpmu:not([data-darkmode]) |  | ||||||
| 	root(false) |  | ||||||
|  |  | ||||||
| </style> | </style> | ||||||
|   | |||||||
| @@ -28,11 +28,19 @@ export default Vue.extend({ | |||||||
| 			}]; | 			}]; | ||||||
|  |  | ||||||
| 			if (this.note.userId == this.$store.state.i.id) { | 			if (this.note.userId == this.$store.state.i.id) { | ||||||
| 				items.push({ | 				if ((this.$store.state.i.pinnedNoteIds || []).includes(this.note.id)) { | ||||||
| 					icon: '%fa:thumbtack%', | 					items.push({ | ||||||
| 					text: '%i18n:@pin%', | 						icon: '%fa:thumbtack%', | ||||||
| 					action: this.pin | 						text: '%i18n:@unpin%', | ||||||
| 				}); | 						action: this.unpin | ||||||
|  | 					}); | ||||||
|  | 				} else { | ||||||
|  | 					items.push({ | ||||||
|  | 						icon: '%fa:thumbtack%', | ||||||
|  | 						text: '%i18n:@pin%', | ||||||
|  | 						action: this.pin | ||||||
|  | 					}); | ||||||
|  | 				} | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			if (this.note.userId == this.$store.state.i.id || this.$store.state.i.isAdmin) { | 			if (this.note.userId == this.$store.state.i.id || this.$store.state.i.isAdmin) { | ||||||
| @@ -56,6 +64,7 @@ export default Vue.extend({ | |||||||
| 			return items; | 			return items; | ||||||
| 		} | 		} | ||||||
| 	}, | 	}, | ||||||
|  |  | ||||||
| 	methods: { | 	methods: { | ||||||
| 		detail() { | 		detail() { | ||||||
| 			this.$router.push(`/notes/${ this.note.id }`); | 			this.$router.push(`/notes/${ this.note.id }`); | ||||||
| @@ -73,6 +82,14 @@ export default Vue.extend({ | |||||||
| 			}); | 			}); | ||||||
| 		}, | 		}, | ||||||
|  |  | ||||||
|  | 		unpin() { | ||||||
|  | 			(this as any).api('i/unpin', { | ||||||
|  | 				noteId: this.note.id | ||||||
|  | 			}).then(() => { | ||||||
|  | 				this.destroyDom(); | ||||||
|  | 			}); | ||||||
|  | 		}, | ||||||
|  |  | ||||||
| 		del() { | 		del() { | ||||||
| 			if (!window.confirm('%i18n:@delete-confirm%')) return; | 			if (!window.confirm('%i18n:@delete-confirm%')) return; | ||||||
| 			(this as any).api('notes/delete', { | 			(this as any).api('notes/delete', { | ||||||
| @@ -86,6 +103,12 @@ export default Vue.extend({ | |||||||
| 			(this as any).api('notes/favorites/create', { | 			(this as any).api('notes/favorites/create', { | ||||||
| 				noteId: this.note.id | 				noteId: this.note.id | ||||||
| 			}).then(() => { | 			}).then(() => { | ||||||
|  | 				this.$swal({ | ||||||
|  | 					type: 'success', | ||||||
|  | 					showConfirmButton: false, | ||||||
|  | 					timer: 1250, | ||||||
|  | 					customClass: 'swal-icon-only' | ||||||
|  | 				}); | ||||||
| 				this.destroyDom(); | 				this.destroyDom(); | ||||||
| 			}); | 			}); | ||||||
| 		}, | 		}, | ||||||
|   | |||||||
| @@ -68,9 +68,7 @@ export default Vue.extend({ | |||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <style lang="stylus" scoped> | <style lang="stylus" scoped> | ||||||
| @import '~const.styl' | .mk-poll-editor | ||||||
|  |  | ||||||
| root(isDark) |  | ||||||
| 	padding 8px | 	padding 8px | ||||||
|  |  | ||||||
| 	> .caution | 	> .caution | ||||||
| @@ -103,49 +101,43 @@ root(isDark) | |||||||
| 				padding 6px 8px | 				padding 6px 8px | ||||||
| 				width 300px | 				width 300px | ||||||
| 				font-size 14px | 				font-size 14px | ||||||
| 				color isDark ? #fff : #000 | 				color var(--inputText) | ||||||
| 				background isDark ? #191b22 : #fff | 				background var(--pollEditorInputBg) | ||||||
| 				border solid 1px rgba($theme-color, 0.1) | 				border solid 1px var(--primaryAlpha01) | ||||||
| 				border-radius 4px | 				border-radius 4px | ||||||
|  |  | ||||||
| 				&:hover | 				&:hover | ||||||
| 					border-color rgba($theme-color, 0.2) | 					border-color var(--primaryAlpha02) | ||||||
|  |  | ||||||
| 				&:focus | 				&:focus | ||||||
| 					border-color rgba($theme-color, 0.5) | 					border-color var(--primaryAlpha05) | ||||||
|  |  | ||||||
| 			> button | 			> button | ||||||
| 				padding 4px 8px | 				padding 4px 8px | ||||||
| 				color rgba($theme-color, 0.4) | 				color var(--primaryAlpha04) | ||||||
|  |  | ||||||
| 				&:hover | 				&:hover | ||||||
| 					color rgba($theme-color, 0.6) | 					color var(--primaryAlpha06) | ||||||
|  |  | ||||||
| 				&:active | 				&:active | ||||||
| 					color darken($theme-color, 30%) | 					color var(--primaryDarken30) | ||||||
|  |  | ||||||
| 	> .add | 	> .add | ||||||
| 		margin 8px 0 0 0 | 		margin 8px 0 0 0 | ||||||
| 		vertical-align top | 		vertical-align top | ||||||
| 		color $theme-color | 		color var(--primary) | ||||||
|  |  | ||||||
| 	> .destroy | 	> .destroy | ||||||
| 		position absolute | 		position absolute | ||||||
| 		top 0 | 		top 0 | ||||||
| 		right 0 | 		right 0 | ||||||
| 		padding 4px 8px | 		padding 4px 8px | ||||||
| 		color rgba($theme-color, 0.4) | 		color var(--primaryAlpha04) | ||||||
|  |  | ||||||
| 		&:hover | 		&:hover | ||||||
| 			color rgba($theme-color, 0.6) | 			color var(--primaryAlpha06) | ||||||
|  |  | ||||||
| 		&:active | 		&:active | ||||||
| 			color darken($theme-color, 30%) | 			color var(--primaryDarken30) | ||||||
|  |  | ||||||
| .mk-poll-editor[data-darkmode] |  | ||||||
| 	root(true) |  | ||||||
|  |  | ||||||
| .mk-poll-editor:not([data-darkmode]) |  | ||||||
| 	root(false) |  | ||||||
|  |  | ||||||
| </style> | </style> | ||||||
|   | |||||||
| @@ -67,10 +67,7 @@ export default Vue.extend({ | |||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <style lang="stylus" scoped> | <style lang="stylus" scoped> | ||||||
| @import '~const.styl' | .mk-poll | ||||||
|  |  | ||||||
| root(isDark) |  | ||||||
|  |  | ||||||
| 	> ul | 	> ul | ||||||
| 		display block | 		display block | ||||||
| 		margin 0 | 		margin 0 | ||||||
| @@ -82,8 +79,8 @@ root(isDark) | |||||||
| 			margin 4px 0 | 			margin 4px 0 | ||||||
| 			padding 4px 8px | 			padding 4px 8px | ||||||
| 			width 100% | 			width 100% | ||||||
| 			color isDark ? #fff : #000 | 			color var(--pollChoiceText) | ||||||
| 			border solid 1px isDark ? #5e636f : #eee | 			border solid 1px var(--pollChoiceBorder) | ||||||
| 			border-radius 4px | 			border-radius 4px | ||||||
| 			overflow hidden | 			overflow hidden | ||||||
| 			cursor pointer | 			cursor pointer | ||||||
| @@ -99,7 +96,7 @@ root(isDark) | |||||||
| 				top 0 | 				top 0 | ||||||
| 				left 0 | 				left 0 | ||||||
| 				height 100% | 				height 100% | ||||||
| 				background $theme-color | 				background var(--primary) | ||||||
| 				transition width 1s ease | 				transition width 1s ease | ||||||
|  |  | ||||||
| 			> span | 			> span | ||||||
| @@ -110,7 +107,7 @@ root(isDark) | |||||||
| 					margin-left 4px | 					margin-left 4px | ||||||
|  |  | ||||||
| 	> p | 	> p | ||||||
| 		color isDark ? #a3aebf : #000 | 		color var(--text) | ||||||
|  |  | ||||||
| 		a | 		a | ||||||
| 			color inherit | 			color inherit | ||||||
| @@ -125,10 +122,4 @@ root(isDark) | |||||||
| 			&:active | 			&:active | ||||||
| 				background transparent | 				background transparent | ||||||
|  |  | ||||||
| .mk-poll[data-darkmode] |  | ||||||
| 	root(true) |  | ||||||
|  |  | ||||||
| .mk-poll:not([data-darkmode]) |  | ||||||
| 	root(false) |  | ||||||
|  |  | ||||||
| </style> | </style> | ||||||
|   | |||||||
| @@ -210,11 +210,9 @@ export default Vue.extend({ | |||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <style lang="stylus" scoped> | <style lang="stylus" scoped> | ||||||
| @import '~const.styl' |  | ||||||
|  |  | ||||||
| $border-color = rgba(27, 31, 35, 0.15) | $border-color = rgba(27, 31, 35, 0.15) | ||||||
|  |  | ||||||
| root(isDark) | .mk-reaction-picker | ||||||
| 	position initial | 	position initial | ||||||
|  |  | ||||||
| 	> .backdrop | 	> .backdrop | ||||||
| @@ -224,11 +222,11 @@ root(isDark) | |||||||
| 		z-index 10000 | 		z-index 10000 | ||||||
| 		width 100% | 		width 100% | ||||||
| 		height 100% | 		height 100% | ||||||
| 		background isDark ? rgba(#000, 0.4) : rgba(#000, 0.1) | 		background var(--modalBackdrop) | ||||||
| 		opacity 0 | 		opacity 0 | ||||||
|  |  | ||||||
| 	> .popover | 	> .popover | ||||||
| 		$bgcolor = isDark ? #2c303c : #fff | 		$bgcolor = var(--popupBg) | ||||||
| 		position absolute | 		position absolute | ||||||
| 		z-index 10001 | 		z-index 10001 | ||||||
| 		background $bgcolor | 		background $bgcolor | ||||||
| @@ -281,8 +279,8 @@ root(isDark) | |||||||
| 			margin 0 | 			margin 0 | ||||||
| 			padding 8px 10px | 			padding 8px 10px | ||||||
| 			font-size 14px | 			font-size 14px | ||||||
| 			color isDark ? #d6dce2 : #586069 | 			color var(--popupFg) | ||||||
| 			border-bottom solid 1px isDark ? #1c2023 : #e1e4e8 | 			border-bottom solid 1px var(--faceDivider) | ||||||
|  |  | ||||||
| 		> div | 		> div | ||||||
| 			padding 4px | 			padding 4px | ||||||
| @@ -301,7 +299,7 @@ root(isDark) | |||||||
| 						right 0 | 						right 0 | ||||||
| 						bottom 0 | 						bottom 0 | ||||||
| 						left 0 | 						left 0 | ||||||
| 						border 2px solid rgba($theme-color, 0.3) | 						border 2px solid var(--primaryAlpha03) | ||||||
| 						border-radius 4px | 						border-radius 4px | ||||||
|  |  | ||||||
| 			> button | 			> button | ||||||
| @@ -312,16 +310,10 @@ root(isDark) | |||||||
| 				border-radius 2px | 				border-radius 2px | ||||||
|  |  | ||||||
| 				&:hover | 				&:hover | ||||||
| 					background isDark ? #252731 : #eee | 					background var(--reactionPickerButtonHoverBg) | ||||||
|  |  | ||||||
| 				&:active | 				&:active | ||||||
| 					background $theme-color | 					background var(--primary) | ||||||
| 					box-shadow inset 0 0.15em 0.3em rgba(27, 31, 35, 0.15) | 					box-shadow inset 0 0.15em 0.3em rgba(27, 31, 35, 0.15) | ||||||
|  |  | ||||||
| .mk-reaction-picker[data-darkmode] |  | ||||||
| 	root(true) |  | ||||||
|  |  | ||||||
| .mk-reaction-picker:not([data-darkmode]) |  | ||||||
| 	root(false) |  | ||||||
|  |  | ||||||
| </style> | </style> | ||||||
|   | |||||||
| @@ -1,16 +1,16 @@ | |||||||
| <template> | <template> | ||||||
| <div class="mk-reactions-viewer"> | <div class="mk-reactions-viewer"> | ||||||
| 	<template v-if="reactions"> | 	<template v-if="reactions"> | ||||||
| 		<span :class="{notReacted}" @click="react('like')" v-if="reactions.like"><mk-reaction-icon reaction="like"/><span>{{ reactions.like }}</span></span> | 		<span :class="{ reacted: note.myReaction == 'like' }" @click="react('like')" v-if="reactions.like"><mk-reaction-icon reaction="like"/><span>{{ reactions.like }}</span></span> | ||||||
| 		<span :class="{notReacted}" @click="react('love')" v-if="reactions.love"><mk-reaction-icon reaction="love"/><span>{{ reactions.love }}</span></span> | 		<span :class="{ reacted: note.myReaction == 'love' }" @click="react('love')" v-if="reactions.love"><mk-reaction-icon reaction="love"/><span>{{ reactions.love }}</span></span> | ||||||
| 		<span :class="{notReacted}" @click="react('laugh')" v-if="reactions.laugh"><mk-reaction-icon reaction="laugh"/><span>{{ reactions.laugh }}</span></span> | 		<span :class="{ reacted: note.myReaction == 'laugh' }" @click="react('laugh')" v-if="reactions.laugh"><mk-reaction-icon reaction="laugh"/><span>{{ reactions.laugh }}</span></span> | ||||||
| 		<span :class="{notReacted}" @click="react('hmm')" v-if="reactions.hmm"><mk-reaction-icon reaction="hmm"/><span>{{ reactions.hmm }}</span></span> | 		<span :class="{ reacted: note.myReaction == 'hmm' }" @click="react('hmm')" v-if="reactions.hmm"><mk-reaction-icon reaction="hmm"/><span>{{ reactions.hmm }}</span></span> | ||||||
| 		<span :class="{notReacted}" @click="react('surprise')" v-if="reactions.surprise"><mk-reaction-icon reaction="surprise"/><span>{{ reactions.surprise }}</span></span> | 		<span :class="{ reacted: note.myReaction == 'surprise' }" @click="react('surprise')" v-if="reactions.surprise"><mk-reaction-icon reaction="surprise"/><span>{{ reactions.surprise }}</span></span> | ||||||
| 		<span :class="{notReacted}" @click="react('congrats')" v-if="reactions.congrats"><mk-reaction-icon reaction="congrats"/><span>{{ reactions.congrats }}</span></span> | 		<span :class="{ reacted: note.myReaction == 'congrats' }" @click="react('congrats')" v-if="reactions.congrats"><mk-reaction-icon reaction="congrats"/><span>{{ reactions.congrats }}</span></span> | ||||||
| 		<span :class="{notReacted}" @click="react('angry')" v-if="reactions.angry"><mk-reaction-icon reaction="angry"/><span>{{ reactions.angry }}</span></span> | 		<span :class="{ reacted: note.myReaction == 'angry' }" @click="react('angry')" v-if="reactions.angry"><mk-reaction-icon reaction="angry"/><span>{{ reactions.angry }}</span></span> | ||||||
| 		<span :class="{notReacted}" @click="react('confused')" v-if="reactions.confused"><mk-reaction-icon reaction="confused"/><span>{{ reactions.confused }}</span></span> | 		<span :class="{ reacted: note.myReaction == 'confused' }" @click="react('confused')" v-if="reactions.confused"><mk-reaction-icon reaction="confused"/><span>{{ reactions.confused }}</span></span> | ||||||
| 		<span :class="{notReacted}" @click="react('rip')" v-if="reactions.rip"><mk-reaction-icon reaction="rip"/><span>{{ reactions.rip }}</span></span> | 		<span :class="{ reacted: note.myReaction == 'rip' }" @click="react('rip')" v-if="reactions.rip"><mk-reaction-icon reaction="rip"/><span>{{ reactions.rip }}</span></span> | ||||||
| 		<span :class="{notReacted}" @click="react('pudding')" v-if="reactions.pudding"><mk-reaction-icon reaction="pudding"/><span>{{ reactions.pudding }}</span></span> | 		<span :class="{ reacted: note.myReaction == 'pudding' }" @click="react('pudding')" v-if="reactions.pudding"><mk-reaction-icon reaction="pudding"/><span>{{ reactions.pudding }}</span></span> | ||||||
| 	</template> | 	</template> | ||||||
| </div> | </div> | ||||||
| </template> | </template> | ||||||
| @@ -22,9 +22,6 @@ export default Vue.extend({ | |||||||
| 	computed: { | 	computed: { | ||||||
| 		reactions(): number { | 		reactions(): number { | ||||||
| 			return this.note.reactionCounts; | 			return this.note.reactionCounts; | ||||||
| 		}, |  | ||||||
| 		notReacted(): boolean { |  | ||||||
| 			return this.note.myReaction == null; |  | ||||||
| 		} | 		} | ||||||
| 	}, | 	}, | ||||||
| 	methods: { | 	methods: { | ||||||
| @@ -39,33 +36,43 @@ export default Vue.extend({ | |||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <style lang="stylus" scoped> | <style lang="stylus" scoped> | ||||||
| root(isDark) | .mk-reactions-viewer | ||||||
| 	$borderColor = isDark ? #5e6673 : #eee | 	margin 6px 0 | ||||||
| 	border-top dashed 1px $borderColor |  | ||||||
| 	border-bottom dashed 1px $borderColor |  | ||||||
| 	margin 4px 0 |  | ||||||
|  |  | ||||||
| 	&:empty | 	&:empty | ||||||
| 		display none | 		display none | ||||||
|  |  | ||||||
| 	> span | 	> span | ||||||
| 		margin-right 8px | 		display inline-block | ||||||
|  | 		height 32px | ||||||
|  | 		margin-right 6px | ||||||
|  | 		padding 0 6px | ||||||
|  | 		border-radius 4px | ||||||
|  |  | ||||||
| 		&.notReacted | 		* | ||||||
|  | 			user-select none | ||||||
|  | 			pointer-events none | ||||||
|  |  | ||||||
|  | 		&.reacted | ||||||
|  | 			background var(--primary) | ||||||
|  |  | ||||||
|  | 			> span | ||||||
|  | 				color var(--primaryForeground) | ||||||
|  |  | ||||||
|  | 		&:not(.reacted) | ||||||
| 			cursor pointer | 			cursor pointer | ||||||
|  | 			background var(--reactionViewerButtonBg) | ||||||
|  |  | ||||||
|  | 			&:hover | ||||||
|  | 				background var(--reactionViewerButtonHoverBg) | ||||||
|  |  | ||||||
| 		> .mk-reaction-icon | 		> .mk-reaction-icon | ||||||
| 			font-size 1.4em | 			font-size 1.4em | ||||||
|  |  | ||||||
| 		> span | 		> span | ||||||
| 			margin-left 4px | 			font-size 1.1em | ||||||
| 			font-size 1.2em | 			line-height 32px | ||||||
| 			color isDark ? #d1d5dc : #444 | 			vertical-align middle | ||||||
|  | 			color var(--text) | ||||||
| .mk-reactions-viewer[data-darkmode] |  | ||||||
| 	root(true) |  | ||||||
|  |  | ||||||
| .mk-reactions-viewer:not([data-darkmode]) |  | ||||||
| 	root(false) |  | ||||||
|  |  | ||||||
| </style> | </style> | ||||||
|   | |||||||
| @@ -1,16 +1,16 @@ | |||||||
| <template> | <template> | ||||||
| <form class="mk-signin" :class="{ signing }" @submit.prevent="onSubmit"> | <form class="mk-signin" :class="{ signing }" @submit.prevent="onSubmit"> | ||||||
| 	<div class="avatar" :style="{ backgroundImage: user ? `url('${ user.avatarUrl }')` : null }" v-show="withAvatar"></div> | 	<div class="avatar" :style="{ backgroundImage: user ? `url('${ user.avatarUrl }')` : null }" v-show="withAvatar"></div> | ||||||
| 	<ui-input v-model="username" type="text" pattern="^[a-zA-Z0-9_]+$" spellcheck="false" autofocus required @input="onUsernameChange"> | 	<ui-input v-model="username" type="text" pattern="^[a-zA-Z0-9_]+$" spellcheck="false" autofocus required @input="onUsernameChange" styl="fill"> | ||||||
| 		<span>%i18n:@username%</span> | 		<span>%i18n:@username%</span> | ||||||
| 		<span slot="prefix">@</span> | 		<span slot="prefix">@</span> | ||||||
| 		<span slot="suffix">@{{ host }}</span> | 		<span slot="suffix">@{{ host }}</span> | ||||||
| 	</ui-input> | 	</ui-input> | ||||||
| 	<ui-input v-model="password" type="password" required> | 	<ui-input v-model="password" type="password" required styl="fill"> | ||||||
| 		<span>%i18n:@password%</span> | 		<span>%i18n:@password%</span> | ||||||
| 		<span slot="prefix">%fa:lock%</span> | 		<span slot="prefix">%fa:lock%</span> | ||||||
| 	</ui-input> | 	</ui-input> | ||||||
| 	<ui-input v-if="user && user.twoFactorEnabled" v-model="token" type="number" required/> | 	<ui-input v-if="user && user.twoFactorEnabled" v-model="token" type="number" required styl="fill"/> | ||||||
| 	<ui-button type="submit" :disabled="signing">{{ signing ? '%i18n:@signing-in%' : '%i18n:@signin%' }}</ui-button> | 	<ui-button type="submit" :disabled="signing">{{ signing ? '%i18n:@signing-in%' : '%i18n:@signin%' }}</ui-button> | ||||||
| 	<p style="margin: 8px 0;">%i18n:@or% <a :href="`${apiUrl}/signin/twitter`">%i18n:@signin-with-twitter%</a></p> | 	<p style="margin: 8px 0;">%i18n:@or% <a :href="`${apiUrl}/signin/twitter`">%i18n:@signin-with-twitter%</a></p> | ||||||
| </form> | </form> | ||||||
| @@ -56,7 +56,7 @@ export default Vue.extend({ | |||||||
| 				username: this.username, | 				username: this.username, | ||||||
| 				password: this.password, | 				password: this.password, | ||||||
| 				token: this.user && this.user.twoFactorEnabled ? this.token : undefined | 				token: this.user && this.user.twoFactorEnabled ? this.token : undefined | ||||||
| 			}).then(() => { | 			}, true).then(() => { | ||||||
| 				location.reload(); | 				location.reload(); | ||||||
| 			}).catch(() => { | 			}).catch(() => { | ||||||
| 				alert('%i18n:@login-failed%'); | 				alert('%i18n:@login-failed%'); | ||||||
| @@ -68,7 +68,7 @@ export default Vue.extend({ | |||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <style lang="stylus" scoped> | <style lang="stylus" scoped> | ||||||
| @import '~const.styl' |  | ||||||
|  |  | ||||||
| .mk-signin | .mk-signin | ||||||
| 	color #555 | 	color #555 | ||||||
|   | |||||||
| @@ -1,12 +1,12 @@ | |||||||
| <template> | <template> | ||||||
| <form class="mk-signup" @submit.prevent="onSubmit" :autocomplete="Math.random()"> | <form class="mk-signup" @submit.prevent="onSubmit" :autocomplete="Math.random()"> | ||||||
| 	<template v-if="meta"> | 	<template v-if="meta"> | ||||||
| 		<ui-input v-if="meta.disableRegistration" v-model="invitationCode" type="text" :autocomplete="Math.random()" spellcheck="false" required> | 		<ui-input v-if="meta.disableRegistration" v-model="invitationCode" type="text" :autocomplete="Math.random()" spellcheck="false" required styl="fill"> | ||||||
| 			<span>%i18n:@invitation-code%</span> | 			<span>%i18n:@invitation-code%</span> | ||||||
| 			<span slot="prefix">%fa:id-card-alt%</span> | 			<span slot="prefix">%fa:id-card-alt%</span> | ||||||
| 			<p slot="text" v-html="'%i18n:@invitation-info%'.replace('{}', meta.maintainer.url)"></p> | 			<p slot="text" v-html="'%i18n:@invitation-info%'.replace('{}', meta.maintainer.url)"></p> | ||||||
| 		</ui-input> | 		</ui-input> | ||||||
| 		<ui-input v-model="username" type="text" pattern="^[a-zA-Z0-9_]{1,20}$" :autocomplete="Math.random()" spellcheck="false" required @input="onChangeUsername"> | 		<ui-input v-model="username" type="text" pattern="^[a-zA-Z0-9_]{1,20}$" :autocomplete="Math.random()" spellcheck="false" required @input="onChangeUsername" styl="fill"> | ||||||
| 			<span>%i18n:@username%</span> | 			<span>%i18n:@username%</span> | ||||||
| 			<span slot="prefix">@</span> | 			<span slot="prefix">@</span> | ||||||
| 			<span slot="suffix">@{{ host }}</span> | 			<span slot="suffix">@{{ host }}</span> | ||||||
| @@ -18,7 +18,7 @@ | |||||||
| 			<p slot="text" v-if="usernameState == 'min-range'" style="color:#FF1161">%fa:exclamation-triangle .fw% %i18n:@too-short%</p> | 			<p slot="text" v-if="usernameState == 'min-range'" style="color:#FF1161">%fa:exclamation-triangle .fw% %i18n:@too-short%</p> | ||||||
| 			<p slot="text" v-if="usernameState == 'max-range'" style="color:#FF1161">%fa:exclamation-triangle .fw% %i18n:@too-long%</p> | 			<p slot="text" v-if="usernameState == 'max-range'" style="color:#FF1161">%fa:exclamation-triangle .fw% %i18n:@too-long%</p> | ||||||
| 		</ui-input> | 		</ui-input> | ||||||
| 		<ui-input v-model="password" type="password" :autocomplete="Math.random()" required @input="onChangePassword" :with-password-meter="true"> | 		<ui-input v-model="password" type="password" :autocomplete="Math.random()" required @input="onChangePassword" :with-password-meter="true" styl="fill"> | ||||||
| 			<span>%i18n:@password%</span> | 			<span>%i18n:@password%</span> | ||||||
| 			<span slot="prefix">%fa:lock%</span> | 			<span slot="prefix">%fa:lock%</span> | ||||||
| 			<div slot="text"> | 			<div slot="text"> | ||||||
| @@ -27,7 +27,7 @@ | |||||||
| 				<p slot="text" v-if="passwordStrength == 'high'" style="color:#3CB7B5">%fa:check .fw% %i18n:@strong-password%</p> | 				<p slot="text" v-if="passwordStrength == 'high'" style="color:#3CB7B5">%fa:check .fw% %i18n:@strong-password%</p> | ||||||
| 			</div> | 			</div> | ||||||
| 		</ui-input> | 		</ui-input> | ||||||
| 		<ui-input v-model="retypedPassword" type="password" :autocomplete="Math.random()" required @input="onChangePasswordRetype"> | 		<ui-input v-model="retypedPassword" type="password" :autocomplete="Math.random()" required @input="onChangePasswordRetype" styl="fill"> | ||||||
| 			<span>%i18n:@password% (%i18n:@retype%)</span> | 			<span>%i18n:@password% (%i18n:@retype%)</span> | ||||||
| 			<span slot="prefix">%fa:lock%</span> | 			<span slot="prefix">%fa:lock%</span> | ||||||
| 			<div slot="text"> | 			<div slot="text"> | ||||||
| @@ -131,11 +131,11 @@ export default Vue.extend({ | |||||||
| 				password: this.password, | 				password: this.password, | ||||||
| 				invitationCode: this.invitationCode, | 				invitationCode: this.invitationCode, | ||||||
| 				'g-recaptcha-response': this.meta.recaptchaSitekey != null ? (window as any).grecaptcha.getResponse() : null | 				'g-recaptcha-response': this.meta.recaptchaSitekey != null ? (window as any).grecaptcha.getResponse() : null | ||||||
| 			}).then(() => { | 			}, true).then(() => { | ||||||
| 				(this as any).api('signin', { | 				(this as any).api('signin', { | ||||||
| 					username: this.username, | 					username: this.username, | ||||||
| 					password: this.password | 					password: this.password | ||||||
| 				}).then(() => { | 				}, true).then(() => { | ||||||
| 					location.href = '/'; | 					location.href = '/'; | ||||||
| 				}); | 				}); | ||||||
| 			}).catch(() => { | 			}).catch(() => { | ||||||
| @@ -151,7 +151,7 @@ export default Vue.extend({ | |||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <style lang="stylus" scoped> | <style lang="stylus" scoped> | ||||||
| @import '~const.styl' |  | ||||||
|  |  | ||||||
| .mk-signup | .mk-signup | ||||||
| 	min-width 302px | 	min-width 302px | ||||||
|   | |||||||
| @@ -1,14 +1,14 @@ | |||||||
| <template> | <template> | ||||||
| <div class="mk-stream-indicator"> | <div class="mk-stream-indicator"> | ||||||
| 	<p v-if=" stream.state == 'initializing' "> | 	<p v-if="stream.state == 'initializing'"> | ||||||
| 		%fa:spinner .pulse% | 		%fa:spinner .pulse% | ||||||
| 		<span>%i18n:@connecting%<mk-ellipsis/></span> | 		<span>%i18n:@connecting%<mk-ellipsis/></span> | ||||||
| 	</p> | 	</p> | ||||||
| 	<p v-if=" stream.state == 'reconnecting' "> | 	<p v-if="stream.state == 'reconnecting'"> | ||||||
| 		%fa:spinner .pulse% | 		%fa:spinner .pulse% | ||||||
| 		<span>%i18n:@reconnecting%<mk-ellipsis/></span> | 		<span>%i18n:@reconnecting%<mk-ellipsis/></span> | ||||||
| 	</p> | 	</p> | ||||||
| 	<p v-if=" stream.state == 'connected' "> | 	<p v-if="stream.state == 'connected'"> | ||||||
| 		%fa:check% | 		%fa:check% | ||||||
| 		<span>%i18n:@connected%</span> | 		<span>%i18n:@connected%</span> | ||||||
| 	</p> | 	</p> | ||||||
|   | |||||||
| @@ -1,199 +0,0 @@ | |||||||
| <template> |  | ||||||
| <div |  | ||||||
| 	class="mk-switch" |  | ||||||
| 	:class="{ disabled, checked }" |  | ||||||
| 	role="switch" |  | ||||||
| 	:aria-checked="checked" |  | ||||||
| 	:aria-disabled="disabled" |  | ||||||
| 	@click="switchValue" |  | ||||||
| 	@mouseover="mouseenter" |  | ||||||
| > |  | ||||||
| 	<input |  | ||||||
| 		type="checkbox" |  | ||||||
| 		@change="handleChange" |  | ||||||
| 		ref="input" |  | ||||||
| 		:disabled="disabled" |  | ||||||
| 		@keydown.enter="switchValue" |  | ||||||
| 	> |  | ||||||
| 	<span class="button"> |  | ||||||
| 		<span :style="{ transform }"></span> |  | ||||||
| 	</span> |  | ||||||
| 	<span class="label"> |  | ||||||
| 		<span :aria-hidden="!checked">{{ text }}</span> |  | ||||||
| 		<p :aria-hidden="!checked"> |  | ||||||
| 			<slot></slot> |  | ||||||
| 		</p> |  | ||||||
| 	</span> |  | ||||||
| </div> |  | ||||||
| </template> |  | ||||||
|  |  | ||||||
| <script lang="ts"> |  | ||||||
| import Vue from 'vue'; |  | ||||||
| export default Vue.extend({ |  | ||||||
| 	props: { |  | ||||||
| 		value: { |  | ||||||
| 			type: Boolean, |  | ||||||
| 			default: false |  | ||||||
| 		}, |  | ||||||
| 		disabled: { |  | ||||||
| 			type: Boolean, |  | ||||||
| 			default: false |  | ||||||
| 		}, |  | ||||||
| 		text: String |  | ||||||
| 	},/* |  | ||||||
| 	created() { |  | ||||||
| 		if (!~[true, false].indexOf(this.value)) { |  | ||||||
| 			this.$emit('input', false); |  | ||||||
| 		} |  | ||||||
| 	},*/ |  | ||||||
| 	computed: { |  | ||||||
| 		checked(): boolean { |  | ||||||
| 			return this.value; |  | ||||||
| 		}, |  | ||||||
| 		transform(): string { |  | ||||||
| 			return this.checked ? 'translate3d(20px, 0, 0)' : ''; |  | ||||||
| 		} |  | ||||||
| 	}, |  | ||||||
| 	watch: { |  | ||||||
| 		value() { |  | ||||||
| 			(this.$el).style.transition = 'all 0.3s'; |  | ||||||
| 			(this.$refs.input as any).checked = this.checked; |  | ||||||
| 		} |  | ||||||
| 	}, |  | ||||||
| 	mounted() { |  | ||||||
| 		(this.$refs.input as any).checked = this.checked; |  | ||||||
| 	}, |  | ||||||
| 	methods: { |  | ||||||
| 		mouseenter() { |  | ||||||
| 			(this.$el).style.transition = 'all 0s'; |  | ||||||
| 		}, |  | ||||||
| 		handleChange() { |  | ||||||
| 			(this.$el).style.transition = 'all 0.3s'; |  | ||||||
| 			this.$emit('input', !this.checked); |  | ||||||
| 			this.$emit('change', !this.checked); |  | ||||||
| 			this.$nextTick(() => { |  | ||||||
| 				// set input's checked property |  | ||||||
| 				// in case parent refuses to change component's value |  | ||||||
| 				(this.$refs.input as any).checked = this.checked; |  | ||||||
| 			}); |  | ||||||
| 		}, |  | ||||||
| 		switchValue() { |  | ||||||
| 			!this.disabled && this.handleChange(); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| }); |  | ||||||
| </script> |  | ||||||
|  |  | ||||||
| <style lang="stylus" scoped> |  | ||||||
| @import '~const.styl' |  | ||||||
|  |  | ||||||
| root(isDark) |  | ||||||
| 	display flex |  | ||||||
| 	margin 12px 0 |  | ||||||
| 	cursor pointer |  | ||||||
| 	transition all 0.3s |  | ||||||
|  |  | ||||||
| 	> * |  | ||||||
| 		user-select none |  | ||||||
|  |  | ||||||
| 	&.disabled |  | ||||||
| 		opacity 0.6 |  | ||||||
| 		cursor not-allowed |  | ||||||
|  |  | ||||||
| 	&.checked |  | ||||||
| 		> .button |  | ||||||
| 			background-color $theme-color |  | ||||||
| 			border-color $theme-color |  | ||||||
|  |  | ||||||
| 		> .label |  | ||||||
| 			> span |  | ||||||
| 				color $theme-color |  | ||||||
|  |  | ||||||
| 		&:hover |  | ||||||
| 			> .label |  | ||||||
| 				> span |  | ||||||
| 					color darken($theme-color, 10%) |  | ||||||
|  |  | ||||||
| 			> .button |  | ||||||
| 				background darken($theme-color, 10%) |  | ||||||
| 				border-color darken($theme-color, 10%) |  | ||||||
|  |  | ||||||
| 	&:hover |  | ||||||
| 		> .label |  | ||||||
| 			> span |  | ||||||
| 				color isDark ? #fff : #2e3338 |  | ||||||
|  |  | ||||||
| 		> .button |  | ||||||
| 			$color = isDark ? #15181d : #ced2da |  | ||||||
| 			background $color |  | ||||||
| 			border-color $color |  | ||||||
|  |  | ||||||
| 	> input |  | ||||||
| 		position absolute |  | ||||||
| 		width 0 |  | ||||||
| 		height 0 |  | ||||||
| 		opacity 0 |  | ||||||
| 		margin 0 |  | ||||||
|  |  | ||||||
| 		&:focus + .button |  | ||||||
| 			&:after |  | ||||||
| 				content "" |  | ||||||
| 				pointer-events none |  | ||||||
| 				position absolute |  | ||||||
| 				top -5px |  | ||||||
| 				right -5px |  | ||||||
| 				bottom -5px |  | ||||||
| 				left -5px |  | ||||||
| 				border 2px solid rgba($theme-color, 0.3) |  | ||||||
| 				border-radius 14px |  | ||||||
|  |  | ||||||
| 	> .button |  | ||||||
| 		$color = isDark ? #1c1f25 : #dcdfe6 |  | ||||||
|  |  | ||||||
| 		display inline-block |  | ||||||
| 		margin 0 |  | ||||||
| 		width 40px |  | ||||||
| 		min-width 40px |  | ||||||
| 		height 20px |  | ||||||
| 		min-height 20px |  | ||||||
| 		background $color |  | ||||||
| 		border 1px solid $color |  | ||||||
| 		outline none |  | ||||||
| 		border-radius 10px |  | ||||||
| 		transition inherit |  | ||||||
|  |  | ||||||
| 		> * |  | ||||||
| 			position absolute |  | ||||||
| 			top 1px |  | ||||||
| 			left 1px |  | ||||||
| 			border-radius 100% |  | ||||||
| 			transition transform 0.3s |  | ||||||
| 			width 16px |  | ||||||
| 			height 16px |  | ||||||
| 			background-color #fff |  | ||||||
|  |  | ||||||
| 	> .label |  | ||||||
| 		margin-left 8px |  | ||||||
| 		display block |  | ||||||
| 		font-size 15px |  | ||||||
| 		cursor pointer |  | ||||||
| 		transition inherit |  | ||||||
|  |  | ||||||
| 		> span |  | ||||||
| 			display block |  | ||||||
| 			line-height 20px |  | ||||||
| 			color isDark ? #c4ccd2 : #4a535a |  | ||||||
| 			transition inherit |  | ||||||
|  |  | ||||||
| 		> p |  | ||||||
| 			margin 0 |  | ||||||
| 			//font-size 90% |  | ||||||
| 			color isDark ? #78858e : #9daab3 |  | ||||||
|  |  | ||||||
| .mk-switch[data-darkmode] |  | ||||||
| 	root(true) |  | ||||||
|  |  | ||||||
| .mk-switch:not([data-darkmode]) |  | ||||||
| 	root(false) |  | ||||||
|  |  | ||||||
| </style> |  | ||||||
| @@ -63,7 +63,7 @@ export default Vue.extend({ | |||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <style lang="stylus" scoped> | <style lang="stylus" scoped> | ||||||
| root(isDark) | .jtivnzhfwquxpsfidertopbmwmchmnmo | ||||||
| 	height 100% | 	height 100% | ||||||
| 	width 100% | 	width 100% | ||||||
|  |  | ||||||
| @@ -81,10 +81,4 @@ root(isDark) | |||||||
| 		height 100% | 		height 100% | ||||||
| 		width 100% | 		width 100% | ||||||
|  |  | ||||||
| .jtivnzhfwquxpsfidertopbmwmchmnmo[data-darkmode] |  | ||||||
| 	root(true) |  | ||||||
|  |  | ||||||
| .jtivnzhfwquxpsfidertopbmwmchmnmo:not([data-darkmode]) |  | ||||||
| 	root(false) |  | ||||||
|  |  | ||||||
| </style> | </style> | ||||||
|   | |||||||
							
								
								
									
										317
									
								
								src/client/app/common/views/components/theme.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										317
									
								
								src/client/app/common/views/components/theme.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,317 @@ | |||||||
|  | <template> | ||||||
|  | <div class="nicnklzforebnpfgasiypmpdaaglujqm"> | ||||||
|  | 	<label> | ||||||
|  | 		<span>%i18n:@light-theme%</span> | ||||||
|  | 		<ui-select v-model="light" placeholder="%i18n:@light-theme%"> | ||||||
|  | 			<optgroup label="%i18n:@light-themes%"> | ||||||
|  | 				<option v-for="x in lightThemes" :value="x.id" :key="x.id">{{ x.name }}</option> | ||||||
|  | 			</optgroup> | ||||||
|  | 			<optgroup label="%i18n:@dark-themes%"> | ||||||
|  | 				<option v-for="x in darkThemes" :value="x.id" :key="x.id">{{ x.name }}</option> | ||||||
|  | 			</optgroup> | ||||||
|  | 		</ui-select> | ||||||
|  | 	</label> | ||||||
|  |  | ||||||
|  | 	<label> | ||||||
|  | 		<span>%i18n:@dark-theme%</span> | ||||||
|  | 		<ui-select v-model="dark" placeholder="%i18n:@dark-theme%"> | ||||||
|  | 			<optgroup label="%i18n:@dark-themes%"> | ||||||
|  | 				<option v-for="x in darkThemes" :value="x.id" :key="x.id">{{ x.name }}</option> | ||||||
|  | 			</optgroup> | ||||||
|  | 			<optgroup label="%i18n:@light-themes%"> | ||||||
|  | 				<option v-for="x in lightThemes" :value="x.id" :key="x.id">{{ x.name }}</option> | ||||||
|  | 			</optgroup> | ||||||
|  | 		</ui-select> | ||||||
|  | 	</label> | ||||||
|  |  | ||||||
|  | 	<details class="creator"> | ||||||
|  | 		<summary>%fa:palette% %i18n:@create-a-theme%</summary> | ||||||
|  | 		<div> | ||||||
|  | 			<span>%i18n:@base-theme%:</span> | ||||||
|  | 			<ui-radio v-model="myThemeBase" value="light">%i18n:@base-theme-light%</ui-radio> | ||||||
|  | 			<ui-radio v-model="myThemeBase" value="dark">%i18n:@base-theme-dark%</ui-radio> | ||||||
|  | 		</div> | ||||||
|  | 		<div> | ||||||
|  | 			<ui-input v-model="myThemeName"> | ||||||
|  | 				<span>%i18n:@theme-name%</span> | ||||||
|  | 			</ui-input> | ||||||
|  | 			<ui-textarea v-model="myThemeDesc"> | ||||||
|  | 				<span>%i18n:@desc%</span> | ||||||
|  | 			</ui-textarea> | ||||||
|  | 		</div> | ||||||
|  | 		<div> | ||||||
|  | 			<div style="padding-bottom:8px;">%i18n:@primary-color%:</div> | ||||||
|  | 			<color-picker v-model="myThemePrimary"/> | ||||||
|  | 		</div> | ||||||
|  | 		<div> | ||||||
|  | 			<div style="padding-bottom:8px;">%i18n:@secondary-color%:</div> | ||||||
|  | 			<color-picker v-model="myThemeSecondary"/> | ||||||
|  | 		</div> | ||||||
|  | 		<div> | ||||||
|  | 			<div style="padding-bottom:8px;">%i18n:@text-color%:</div> | ||||||
|  | 			<color-picker v-model="myThemeText"/> | ||||||
|  | 		</div> | ||||||
|  | 		<ui-button @click="preview()">%fa:eye% %i18n:@preview-created-theme%</ui-button> | ||||||
|  | 		<ui-button primary @click="gen()">%fa:save R% %i18n:@save-created-theme%</ui-button> | ||||||
|  | 	</details> | ||||||
|  |  | ||||||
|  | 	<details> | ||||||
|  | 		<summary>%fa:download% %i18n:@install-a-theme%</summary> | ||||||
|  | 		<ui-button @click="import_()">%fa:file-import% %i18n:@import%</ui-button> | ||||||
|  | 		<input ref="file" type="file" accept=".misskeytheme" style="display:none;" @change="onUpdateImportFile"/> | ||||||
|  | 		<p>%i18n:@import-by-code%:</p> | ||||||
|  | 		<ui-textarea v-model="installThemeCode"> | ||||||
|  | 			<span>%i18n:@theme-code%</span> | ||||||
|  | 		</ui-textarea> | ||||||
|  | 		<ui-button @click="() => install(this.installThemeCode)">%fa:check% %i18n:@install%</ui-button> | ||||||
|  | 	</details> | ||||||
|  |  | ||||||
|  | 	<details> | ||||||
|  | 		<summary>%fa:folder-open% %i18n:@manage-themes%</summary> | ||||||
|  | 		<ui-select v-model="selectedThemeId" placeholder="%i18n:@select-theme%"> | ||||||
|  | 			<optgroup label="%i18n:@builtin-themes%"> | ||||||
|  | 				<option v-for="x in builtinThemes" :value="x.id" :key="x.id">{{ x.name }}</option> | ||||||
|  | 			</optgroup> | ||||||
|  | 			<optgroup label="%i18n:@my-themes%"> | ||||||
|  | 				<option v-for="x in installedThemes.filter(t => t.author == this.$store.state.i.username)" :value="x.id" :key="x.id">{{ x.name }}</option> | ||||||
|  | 			</optgroup> | ||||||
|  | 			<optgroup label="%i18n:@installed-themes%"> | ||||||
|  | 				<option v-for="x in installedThemes.filter(t => t.author != this.$store.state.i.username)" :value="x.id" :key="x.id">{{ x.name }}</option> | ||||||
|  | 			</optgroup> | ||||||
|  | 		</ui-select> | ||||||
|  | 		<template v-if="selectedTheme"> | ||||||
|  | 			<ui-input readonly :value="selectedTheme.author"> | ||||||
|  | 				<span>%i18n:@author%</span> | ||||||
|  | 			</ui-input> | ||||||
|  | 			<ui-textarea v-if="selectedTheme.desc" readonly :value="selectedTheme.desc"> | ||||||
|  | 				<span>%i18n:@desc%</span> | ||||||
|  | 			</ui-textarea> | ||||||
|  | 			<ui-textarea readonly :value="selectedThemeCode"> | ||||||
|  | 				<span>%i18n:@theme-code%</span> | ||||||
|  | 			</ui-textarea> | ||||||
|  | 			<ui-button @click="export_()" link :download="`${selectedTheme.name}.misskeytheme`" ref="export">%fa:box% %i18n:@export%</ui-button> | ||||||
|  | 			<ui-button @click="uninstall()" v-if="!builtinThemes.some(t => t.id == selectedTheme.id)">%fa:trash-alt R% %i18n:@uninstall%</ui-button> | ||||||
|  | 		</template> | ||||||
|  | 	</details> | ||||||
|  | </div> | ||||||
|  | </template> | ||||||
|  |  | ||||||
|  | <script lang="ts"> | ||||||
|  | import Vue from 'vue'; | ||||||
|  | import { lightTheme, darkTheme, builtinThemes, applyTheme, Theme } from '../../../theme'; | ||||||
|  | import { Chrome } from 'vue-color'; | ||||||
|  | import * as uuid from 'uuid'; | ||||||
|  | import * as tinycolor from 'tinycolor2'; | ||||||
|  | import * as JSON5 from 'json5'; | ||||||
|  |  | ||||||
|  | // 後方互換性のため | ||||||
|  | function convertOldThemedefinition(t) { | ||||||
|  | 	const t2 = { | ||||||
|  | 		id: t.meta.id, | ||||||
|  | 		name: t.meta.name, | ||||||
|  | 		author: t.meta.author, | ||||||
|  | 		base: t.meta.base, | ||||||
|  | 		vars: t.meta.vars, | ||||||
|  | 		props: t | ||||||
|  | 	}; | ||||||
|  | 	delete t2.props.meta; | ||||||
|  | 	return t2; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | export default Vue.extend({ | ||||||
|  | 	components: { | ||||||
|  | 		ColorPicker: Chrome | ||||||
|  | 	}, | ||||||
|  |  | ||||||
|  | 	data() { | ||||||
|  | 		return { | ||||||
|  | 			builtinThemes: builtinThemes, | ||||||
|  | 			installThemeCode: null, | ||||||
|  | 			selectedThemeId: null, | ||||||
|  | 			myThemeBase: 'light', | ||||||
|  | 			myThemeName: '', | ||||||
|  | 			myThemeDesc: '', | ||||||
|  | 			myThemePrimary: lightTheme.vars.primary, | ||||||
|  | 			myThemeSecondary: lightTheme.vars.secondary, | ||||||
|  | 			myThemeText: lightTheme.vars.text | ||||||
|  | 		}; | ||||||
|  | 	}, | ||||||
|  |  | ||||||
|  | 	computed: { | ||||||
|  | 		themes(): Theme[] { | ||||||
|  | 			return builtinThemes.concat(this.$store.state.device.themes); | ||||||
|  | 		}, | ||||||
|  |  | ||||||
|  | 		darkThemes(): Theme[] { | ||||||
|  | 			return this.themes.filter(t => t.base == 'dark' || t.kind == 'dark'); | ||||||
|  | 		}, | ||||||
|  |  | ||||||
|  | 		lightThemes(): Theme[] { | ||||||
|  | 			return this.themes.filter(t => t.base == 'light' || t.kind == 'light'); | ||||||
|  | 		}, | ||||||
|  |  | ||||||
|  | 		installedThemes(): Theme[] { | ||||||
|  | 			return this.$store.state.device.themes; | ||||||
|  | 		}, | ||||||
|  |  | ||||||
|  | 		light: { | ||||||
|  | 			get() { return this.$store.state.device.lightTheme; }, | ||||||
|  | 			set(value) { this.$store.commit('device/set', { key: 'lightTheme', value }); } | ||||||
|  | 		}, | ||||||
|  |  | ||||||
|  | 		dark: { | ||||||
|  | 			get() { return this.$store.state.device.darkTheme; }, | ||||||
|  | 			set(value) { this.$store.commit('device/set', { key: 'darkTheme', value }); } | ||||||
|  | 		}, | ||||||
|  |  | ||||||
|  | 		selectedTheme() { | ||||||
|  | 			if (this.selectedThemeId == null) return null; | ||||||
|  | 			return this.themes.find(x => x.id == this.selectedThemeId); | ||||||
|  | 		}, | ||||||
|  |  | ||||||
|  | 		selectedThemeCode() { | ||||||
|  | 			if (this.selectedTheme == null) return null; | ||||||
|  | 			return JSON5.stringify(this.selectedTheme, null, '\t'); | ||||||
|  | 		}, | ||||||
|  |  | ||||||
|  | 		myTheme(): any { | ||||||
|  | 			return { | ||||||
|  | 				name: this.myThemeName, | ||||||
|  | 				author: this.$store.state.i.username, | ||||||
|  | 				desc: this.myThemeDesc, | ||||||
|  | 				base: this.myThemeBase, | ||||||
|  | 				vars: { | ||||||
|  | 					primary: tinycolor(typeof this.myThemePrimary == 'string' ? this.myThemePrimary : this.myThemePrimary.rgba).toRgbString(), | ||||||
|  | 					secondary: tinycolor(typeof this.myThemeSecondary == 'string' ? this.myThemeSecondary : this.myThemeSecondary.rgba).toRgbString(), | ||||||
|  | 					text: tinycolor(typeof this.myThemeText == 'string' ? this.myThemeText : this.myThemeText.rgba).toRgbString() | ||||||
|  | 				} | ||||||
|  | 			}; | ||||||
|  | 		} | ||||||
|  | 	}, | ||||||
|  |  | ||||||
|  | 	watch: { | ||||||
|  | 		myThemeBase(v) { | ||||||
|  | 			const theme = v == 'light' ? lightTheme : darkTheme; | ||||||
|  | 			this.myThemePrimary = theme.vars.primary; | ||||||
|  | 			this.myThemeSecondary = theme.vars.secondary; | ||||||
|  | 			this.myThemeText = theme.vars.text; | ||||||
|  | 		} | ||||||
|  | 	}, | ||||||
|  |  | ||||||
|  | 	beforeCreate() { | ||||||
|  | 		// migrate old theme definitions | ||||||
|  | 		// 後方互換性のため | ||||||
|  | 		this.$store.commit('device/set', { | ||||||
|  | 			key: 'themes', value: this.$store.state.device.themes.map(t => { | ||||||
|  | 				if (t.id == null) { | ||||||
|  | 					return convertOldThemedefinition(t); | ||||||
|  | 				} else { | ||||||
|  | 					return t; | ||||||
|  | 				} | ||||||
|  | 			}) | ||||||
|  | 		}); | ||||||
|  | 	}, | ||||||
|  |  | ||||||
|  | 	methods: { | ||||||
|  | 		install(code) { | ||||||
|  | 			let theme; | ||||||
|  |  | ||||||
|  | 			try { | ||||||
|  | 				theme = JSON5.parse(code); | ||||||
|  | 			} catch (e) { | ||||||
|  | 				alert('%i18n:@invalid-theme%'); | ||||||
|  | 				return; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			// 後方互換性のため | ||||||
|  | 			if (theme.id == null && theme.meta != null) { | ||||||
|  | 				theme = convertOldThemedefinition(theme); | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			if (theme.id == null) { | ||||||
|  | 				alert('%i18n:@invalid-theme%'); | ||||||
|  | 				return; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			if (this.$store.state.device.themes.some(t => t.id == theme.id)) { | ||||||
|  | 				alert('%i18n:@already-installed%'); | ||||||
|  | 				return; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			const themes = this.$store.state.device.themes.concat(theme); | ||||||
|  | 			this.$store.commit('device/set', { | ||||||
|  | 				key: 'themes', value: themes | ||||||
|  | 			}); | ||||||
|  |  | ||||||
|  | 			alert('%i18n:@installed%'.replace('{}', theme.name)); | ||||||
|  | 		}, | ||||||
|  |  | ||||||
|  | 		uninstall() { | ||||||
|  | 			const theme = this.selectedTheme; | ||||||
|  | 			const themes = this.$store.state.device.themes.filter(t => t.id != theme.id); | ||||||
|  | 			this.$store.commit('device/set', { | ||||||
|  | 				key: 'themes', value: themes | ||||||
|  | 			}); | ||||||
|  | 			alert('%i18n:@uninstalled%'.replace('{}', theme.name)); | ||||||
|  | 		}, | ||||||
|  |  | ||||||
|  | 		import_() { | ||||||
|  | 			(this.$refs.file as any).click(); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		export_() { | ||||||
|  | 			const blob = new Blob([this.selectedThemeCode], { | ||||||
|  | 				type: 'application/json5' | ||||||
|  | 			}); | ||||||
|  | 			this.$refs.export.$el.href = window.URL.createObjectURL(blob); | ||||||
|  | 		}, | ||||||
|  |  | ||||||
|  | 		onUpdateImportFile() { | ||||||
|  | 			const f = (this.$refs.file as any).files[0]; | ||||||
|  |  | ||||||
|  | 			const reader = new FileReader(); | ||||||
|  |  | ||||||
|  | 			reader.onload = e => { | ||||||
|  | 				this.install(e.target.result); | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			reader.readAsText(f); | ||||||
|  | 		}, | ||||||
|  |  | ||||||
|  | 		preview() { | ||||||
|  | 			applyTheme(this.myTheme, false); | ||||||
|  | 		}, | ||||||
|  |  | ||||||
|  | 		gen() { | ||||||
|  | 			const theme = this.myTheme; | ||||||
|  | 			if (theme.name == null || theme.name.trim() == '') { | ||||||
|  | 				alert('%i18n:@theme-name-required%'); | ||||||
|  | 				return; | ||||||
|  | 			} | ||||||
|  | 			theme.id = uuid(); | ||||||
|  | 			const themes = this.$store.state.device.themes.concat(theme); | ||||||
|  | 			this.$store.commit('device/set', { | ||||||
|  | 				key: 'themes', value: themes | ||||||
|  | 			}); | ||||||
|  | 			alert('%i18n:@saved%'); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | }); | ||||||
|  | </script> | ||||||
|  |  | ||||||
|  | <style lang="stylus" scoped> | ||||||
|  | .nicnklzforebnpfgasiypmpdaaglujqm | ||||||
|  | 	> details | ||||||
|  | 		border-top solid 1px var(--faceDivider) | ||||||
|  |  | ||||||
|  | 		> summary | ||||||
|  | 			padding 16px 0 | ||||||
|  |  | ||||||
|  | 		> *:last-child | ||||||
|  | 			margin-bottom 16px | ||||||
|  |  | ||||||
|  | 	> .creator | ||||||
|  | 		> div | ||||||
|  | 			padding 16px 0 | ||||||
|  | 			border-bottom solid 1px var(--faceDivider) | ||||||
|  | </style> | ||||||
| @@ -49,13 +49,14 @@ export default Vue.extend({ | |||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <style lang="stylus" scoped> | <style lang="stylus" scoped> | ||||||
| root(isDark) | .csqvmxybqbycalfhkxvyfrgbrdalkaoc | ||||||
| 	> .fetching | 	> .fetching | ||||||
| 	> .empty | 	> .empty | ||||||
| 		margin 0 | 		margin 0 | ||||||
| 		padding 16px | 		padding 16px | ||||||
| 		text-align center | 		text-align center | ||||||
| 		color #aaa | 		color var(--text) | ||||||
|  | 		opacity 0.7 | ||||||
|  |  | ||||||
| 		> [data-fa] | 		> [data-fa] | ||||||
| 			margin-right 4px | 			margin-right 4px | ||||||
| @@ -70,13 +71,13 @@ root(isDark) | |||||||
| 			padding 14px 16px | 			padding 14px 16px | ||||||
|  |  | ||||||
| 			&:not(:last-child) | 			&:not(:last-child) | ||||||
| 				border-bottom solid 1px isDark ? #393f4f : #eee | 				border-bottom solid 1px var(--faceDivider) | ||||||
|  |  | ||||||
| 			> .tag | 			> .tag | ||||||
| 				flex 1 | 				flex 1 | ||||||
| 				overflow hidden | 				overflow hidden | ||||||
| 				font-size 14px | 				font-size 14px | ||||||
| 				color isDark ? #9baec8 : #65727b | 				color var(--text) | ||||||
|  |  | ||||||
| 				> a | 				> a | ||||||
| 					display block | 					display block | ||||||
| @@ -94,10 +95,4 @@ root(isDark) | |||||||
| 			> .chart | 			> .chart | ||||||
| 				height 30px | 				height 30px | ||||||
|  |  | ||||||
| .csqvmxybqbycalfhkxvyfrgbrdalkaoc[data-darkmode] |  | ||||||
| 	root(true) |  | ||||||
|  |  | ||||||
| .csqvmxybqbycalfhkxvyfrgbrdalkaoc:not([data-darkmode]) |  | ||||||
| 	root(false) |  | ||||||
|  |  | ||||||
| </style> | </style> | ||||||
|   | |||||||
| @@ -1,9 +1,7 @@ | |||||||
| <template> | <template> | ||||||
| <div class="ui-button" :class="[styl]"> | <component class="dmtdnykelhudezerjlfpbhgovrgnqqgr" :is="link ? 'a' : 'button'" :class="[styl, { inline, primary }]" :type="type" @click="$emit('click')"> | ||||||
| 	<button :type="type" @click="$emit('click')"> | 	<slot></slot> | ||||||
| 		<slot></slot> | </component> | ||||||
| 	</button> |  | ||||||
| </div> |  | ||||||
| </template> | </template> | ||||||
|  |  | ||||||
| <script lang="ts"> | <script lang="ts"> | ||||||
| @@ -13,70 +11,100 @@ export default Vue.extend({ | |||||||
| 		type: { | 		type: { | ||||||
| 			type: String, | 			type: String, | ||||||
| 			required: false | 			required: false | ||||||
|  | 		}, | ||||||
|  | 		primary: { | ||||||
|  | 			type: Boolean, | ||||||
|  | 			required: false, | ||||||
|  | 			default: false | ||||||
|  | 		}, | ||||||
|  | 		inline: { | ||||||
|  | 			type: Boolean, | ||||||
|  | 			required: false, | ||||||
|  | 			default: false | ||||||
|  | 		}, | ||||||
|  | 		link: { | ||||||
|  | 			type: Boolean, | ||||||
|  | 			required: false, | ||||||
|  | 			default: false | ||||||
| 		} | 		} | ||||||
| 	}, | 	}, | ||||||
| 	data() { | 	data() { | ||||||
| 		return { | 		return { | ||||||
| 			styl: 'fill' | 			styl: 'fill' | ||||||
| 		}; | 		}; | ||||||
| 	}, |  | ||||||
| 	inject: { |  | ||||||
| 		isCardChild: { default: false } |  | ||||||
| 	}, |  | ||||||
| 	created() { |  | ||||||
| 		if (this.isCardChild) { |  | ||||||
| 			this.styl = 'line'; |  | ||||||
| 		} |  | ||||||
| 	} | 	} | ||||||
| }); | }); | ||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <style lang="stylus" scoped> | <style lang="stylus" scoped> | ||||||
| @import '~const.styl' | .dmtdnykelhudezerjlfpbhgovrgnqqgr | ||||||
|  | 	display block | ||||||
|  | 	width 100% | ||||||
|  | 	margin 0 | ||||||
|  | 	padding 8px | ||||||
|  | 	text-align center | ||||||
|  | 	font-weight normal | ||||||
|  | 	font-size 16px | ||||||
|  | 	border none | ||||||
|  | 	border-radius 6px | ||||||
|  | 	outline none | ||||||
|  | 	box-shadow none | ||||||
|  | 	text-decoration none | ||||||
|  | 	user-select none | ||||||
|  |  | ||||||
| root(isDark, fill) | 	* | ||||||
| 	> button | 		pointer-events none | ||||||
| 		display block |  | ||||||
| 		width 100% | 	&:focus | ||||||
| 		margin 0 | 		&:after | ||||||
| 		padding 0 | 			content "" | ||||||
|  | 			pointer-events none | ||||||
|  | 			position absolute | ||||||
|  | 			top -5px | ||||||
|  | 			right -5px | ||||||
|  | 			bottom -5px | ||||||
|  | 			left -5px | ||||||
|  | 			border 2px solid var(--primaryAlpha03) | ||||||
|  | 			border-radius 10px | ||||||
|  |  | ||||||
|  | 	&:not(.inline) + .dmtdnykelhudezerjlfpbhgovrgnqqgr | ||||||
|  | 		margin-top 16px | ||||||
|  |  | ||||||
|  | 	&.inline | ||||||
|  | 		display inline-block | ||||||
|  | 		width auto | ||||||
|  |  | ||||||
|  | 	&.primary | ||||||
| 		font-weight bold | 		font-weight bold | ||||||
| 		font-size 16px |  | ||||||
| 		line-height 44px |  | ||||||
| 		border none |  | ||||||
| 		border-radius 6px |  | ||||||
| 		outline none |  | ||||||
| 		box-shadow none |  | ||||||
|  |  | ||||||
| 		if fill | 	&.fill | ||||||
| 			color $theme-color-foreground | 		color var(--text) | ||||||
| 			background $theme-color | 		background var(--buttonBg) | ||||||
|  |  | ||||||
|  | 		&:hover | ||||||
|  | 			background var(--buttonHoverBg) | ||||||
|  |  | ||||||
|  | 		&:active | ||||||
|  | 			background var(--buttonActiveBg) | ||||||
|  |  | ||||||
|  | 		&.primary | ||||||
|  | 			color var(--primaryForeground) | ||||||
|  | 			background var(--primary) | ||||||
|  |  | ||||||
| 			&:hover | 			&:hover | ||||||
| 				background lighten($theme-color, 5%) | 				background var(--primaryLighten5) | ||||||
|  |  | ||||||
| 			&:active | 			&:active | ||||||
| 				background darken($theme-color, 5%) | 				background var(--primaryDarken5) | ||||||
| 		else |  | ||||||
| 			color $theme-color |  | ||||||
| 			background none |  | ||||||
|  |  | ||||||
| 			&:hover |  | ||||||
| 				color darken($theme-color, 5%) |  | ||||||
|  |  | ||||||
| 			&:active |  | ||||||
| 				background rgba($theme-color, 0.3) |  | ||||||
|  |  | ||||||
| .ui-button[data-darkmode] |  | ||||||
| 	&.fill |  | ||||||
| 		root(true, true) |  | ||||||
| 	&:not(.fill) | 	&:not(.fill) | ||||||
| 		root(true, false) | 		color var(--primary) | ||||||
|  | 		background none | ||||||
|  |  | ||||||
| .ui-button:not([data-darkmode]) | 		&:hover | ||||||
| 	&.fill | 			color var(--primaryDarken5) | ||||||
| 		root(false, true) |  | ||||||
| 	&:not(.fill) | 		&:active | ||||||
| 		root(false, false) | 			background var(--primaryAlpha03) | ||||||
|  |  | ||||||
| </style> | </style> | ||||||
|   | |||||||
| @@ -20,26 +20,24 @@ export default Vue.extend({ | |||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <style lang="stylus" scoped> | <style lang="stylus" scoped> | ||||||
| @import '~const.styl' | .ui-card | ||||||
|  |  | ||||||
| root(isDark) |  | ||||||
| 	margin 16px | 	margin 16px | ||||||
| 	color isDark ? #fff : #000 | 	color var(--faceText) | ||||||
| 	background isDark ? #282C37 : #fff | 	background var(--face) | ||||||
| 	box-shadow 0 3px 1px -2px rgba(#000, 0.2), 0 2px 2px 0 rgba(#000, 0.14), 0 1px 5px 0 rgba(#000, 0.12) | 	box-shadow 0 3px 1px -2px rgba(#000, 0.2), 0 2px 2px 0 rgba(#000, 0.14), 0 1px 5px 0 rgba(#000, 0.12) | ||||||
|  |  | ||||||
| 	> header | 	> header | ||||||
| 		padding 16px | 		padding 16px | ||||||
| 		font-weight bold | 		font-weight bold | ||||||
| 		font-size 20px | 		font-size 20px | ||||||
| 		color isDark ? #fff : #444 | 		color var(--faceText) | ||||||
|  |  | ||||||
| 		@media (min-width 500px) | 		@media (min-width 500px) | ||||||
| 			padding 24px 32px | 			padding 24px 32px | ||||||
|  |  | ||||||
| 	> section | 	> section | ||||||
| 		padding 20px 16px | 		padding 20px 16px | ||||||
| 		border-top solid 1px isDark ? rgba(#000, 0.3) : rgba(#000, 0.1) | 		border-top solid 1px var(--faceDivider) | ||||||
|  |  | ||||||
| 		@media (min-width 500px) | 		@media (min-width 500px) | ||||||
| 			padding 32px | 			padding 32px | ||||||
| @@ -50,12 +48,5 @@ root(isDark) | |||||||
| 		> header | 		> header | ||||||
| 			margin-bottom 16px | 			margin-bottom 16px | ||||||
| 			font-weight bold | 			font-weight bold | ||||||
| 			color isDark ? #fff : #444 | 			color var(--faceText) | ||||||
|  |  | ||||||
| .ui-card[data-darkmode] |  | ||||||
| 	root(true) |  | ||||||
|  |  | ||||||
| .ui-card:not([data-darkmode]) |  | ||||||
| 	root(false) |  | ||||||
|  |  | ||||||
| </style> | </style> | ||||||
|   | |||||||
| @@ -19,7 +19,7 @@ export default Vue.extend({ | |||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <style lang="stylus" scoped> | <style lang="stylus" scoped> | ||||||
| @import '~const.styl' |  | ||||||
|  |  | ||||||
| .ui-form | .ui-form | ||||||
| 	> fieldset | 	> fieldset | ||||||
|   | |||||||
| @@ -25,9 +25,7 @@ export default Vue.extend({ | |||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <style lang="stylus" scoped> | <style lang="stylus" scoped> | ||||||
| @import '~const.styl' | .nvemkhtwcnnpkdrwfcbzuwhfulejhmzg | ||||||
|  |  | ||||||
| root(isDark) |  | ||||||
| 	display inline-block | 	display inline-block | ||||||
|  |  | ||||||
| 	& + .nvemkhtwcnnpkdrwfcbzuwhfulejhmzg | 	& + .nvemkhtwcnnpkdrwfcbzuwhfulejhmzg | ||||||
| @@ -38,11 +36,11 @@ root(isDark) | |||||||
| 		margin 0 | 		margin 0 | ||||||
| 		padding 12px 20px | 		padding 12px 20px | ||||||
| 		font-size 14px | 		font-size 14px | ||||||
| 		border 1px solid isDark ? #6d727d : #dcdfe6 | 		border 1px solid var(--formButtonBorder) | ||||||
| 		border-radius 4px | 		border-radius 4px | ||||||
| 		outline none | 		outline none | ||||||
| 		box-shadow none | 		box-shadow none | ||||||
| 		color isDark ? #fff : #606266 | 		color var(--text) | ||||||
| 		transition 0.1s | 		transition 0.1s | ||||||
|  |  | ||||||
| 		* | 		* | ||||||
| @@ -50,40 +48,34 @@ root(isDark) | |||||||
|  |  | ||||||
| 		&:hover | 		&:hover | ||||||
| 		&:focus | 		&:focus | ||||||
| 			color $theme-color | 			color var(--primary) | ||||||
| 			background rgba($theme-color, isDark ? 0.2 : 0.12) | 			background var(--formButtonHoverBg) | ||||||
| 			border-color rgba($theme-color, isDark ? 0.5 : 0.3) | 			border-color var(--formButtonHoverBorder) | ||||||
|  |  | ||||||
| 		&:active | 		&:active | ||||||
| 			color darken($theme-color, 20%) | 			color var(--primaryDarken20) | ||||||
| 			background rgba($theme-color, 0.12) | 			background var(--formButtonActiveBg) | ||||||
| 			border-color $theme-color | 			border-color var(--primary) | ||||||
| 			transition all 0s | 			transition all 0s | ||||||
|  |  | ||||||
| 	&.primary | 	&.primary | ||||||
| 		> button | 		> button | ||||||
| 			border 1px solid $theme-color | 			border 1px solid var(--primary) | ||||||
| 			background $theme-color | 			background var(--primary) | ||||||
| 			color $theme-color-foreground | 			color var(--primaryForeground) | ||||||
|  |  | ||||||
| 			&:hover | 			&:hover | ||||||
| 			&:focus | 			&:focus | ||||||
| 				background lighten($theme-color, 20%) | 				background var(--primaryLighten20) | ||||||
| 				border-color lighten($theme-color, 20%) | 				border-color var(--primaryLighten20) | ||||||
|  |  | ||||||
| 			&:active | 			&:active | ||||||
| 				background darken($theme-color, 20%) | 				background var(--primaryDarken20) | ||||||
| 				border-color darken($theme-color, 20%) | 				border-color var(--primaryDarken20) | ||||||
| 				transition all 0s | 				transition all 0s | ||||||
|  |  | ||||||
| 	&.round | 	&.round | ||||||
| 		> button | 		> button | ||||||
| 			border-radius 64px | 			border-radius 64px | ||||||
|  |  | ||||||
| .nvemkhtwcnnpkdrwfcbzuwhfulejhmzg[data-darkmode] |  | ||||||
| 	root(true) |  | ||||||
|  |  | ||||||
| .nvemkhtwcnnpkdrwfcbzuwhfulejhmzg:not([data-darkmode]) |  | ||||||
| 	root(false) |  | ||||||
|  |  | ||||||
| </style> | </style> | ||||||
|   | |||||||
| @@ -49,9 +49,7 @@ export default Vue.extend({ | |||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <style lang="stylus" scoped> | <style lang="stylus" scoped> | ||||||
| @import '~const.styl' | .uywduthvrdnlpsvsjkqigicixgyfctto | ||||||
|  |  | ||||||
| root(isDark) |  | ||||||
| 	display inline-flex | 	display inline-flex | ||||||
| 	margin 0 16px 0 0 | 	margin 0 16px 0 0 | ||||||
| 	cursor pointer | 	cursor pointer | ||||||
| @@ -62,7 +60,7 @@ root(isDark) | |||||||
|  |  | ||||||
| 	&:hover | 	&:hover | ||||||
| 		> .button | 		> .button | ||||||
| 			border solid 2px isDark ? rgba(#fff, 0.7) : rgba(#000, 0.54) | 			border solid 2px var(--inputLabel) | ||||||
|  |  | ||||||
| 	&.disabled | 	&.disabled | ||||||
| 		opacity 0.6 | 		opacity 0.6 | ||||||
| @@ -70,15 +68,15 @@ root(isDark) | |||||||
|  |  | ||||||
| 	&.checked | 	&.checked | ||||||
| 		> .button | 		> .button | ||||||
| 			border-color $theme-color | 			border-color var(--primary) | ||||||
|  |  | ||||||
| 			&:after | 			&:after | ||||||
| 				background-color $theme-color | 				background-color var(--primary) | ||||||
| 				transform scale(1) | 				transform scale(1) | ||||||
| 				opacity 1 | 				opacity 1 | ||||||
|  |  | ||||||
| 		> .label | 		> .label | ||||||
| 			color $theme-color | 			color var(--primary) | ||||||
|  |  | ||||||
| 	> input | 	> input | ||||||
| 		position absolute | 		position absolute | ||||||
| @@ -93,7 +91,7 @@ root(isDark) | |||||||
| 		width 20px | 		width 20px | ||||||
| 		height 20px | 		height 20px | ||||||
| 		background none | 		background none | ||||||
| 		border solid 2px isDark ? rgba(#fff, 0.6) : rgba(#000, 0.4) | 		border solid 2px var(--radioBorder) | ||||||
| 		border-radius 100% | 		border-radius 100% | ||||||
| 		transition inherit | 		transition inherit | ||||||
|  |  | ||||||
| @@ -117,10 +115,4 @@ root(isDark) | |||||||
| 		line-height 20px | 		line-height 20px | ||||||
| 		cursor pointer | 		cursor pointer | ||||||
|  |  | ||||||
| .uywduthvrdnlpsvsjkqigicixgyfctto[data-darkmode] |  | ||||||
| 	root(true) |  | ||||||
|  |  | ||||||
| .uywduthvrdnlpsvsjkqigicixgyfctto:not([data-darkmode]) |  | ||||||
| 	root(false) |  | ||||||
|  |  | ||||||
| </style> | </style> | ||||||
|   | |||||||
| @@ -71,14 +71,18 @@ export default Vue.extend({ | |||||||
| 			type: Boolean, | 			type: Boolean, | ||||||
| 			required: false, | 			required: false, | ||||||
| 			default: false | 			default: false | ||||||
|  | 		}, | ||||||
|  | 		styl: { | ||||||
|  | 			type: String, | ||||||
|  | 			required: false, | ||||||
|  | 			default: 'line' | ||||||
| 		} | 		} | ||||||
| 	}, | 	}, | ||||||
| 	data() { | 	data() { | ||||||
| 		return { | 		return { | ||||||
| 			v: this.value, | 			v: this.value, | ||||||
| 			focused: false, | 			focused: false, | ||||||
| 			passwordStrength: '', | 			passwordStrength: '' | ||||||
| 			styl: 'fill' |  | ||||||
| 		}; | 		}; | ||||||
| 	}, | 	}, | ||||||
| 	computed: { | 	computed: { | ||||||
| @@ -117,14 +121,6 @@ export default Vue.extend({ | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	}, | 	}, | ||||||
| 	inject: { |  | ||||||
| 		isCardChild: { default: false } |  | ||||||
| 	}, |  | ||||||
| 	created() { |  | ||||||
| 		if (this.isCardChild) { |  | ||||||
| 			this.styl = 'line'; |  | ||||||
| 		} |  | ||||||
| 	}, |  | ||||||
| 	mounted() { | 	mounted() { | ||||||
| 		if (this.$refs.prefix) { | 		if (this.$refs.prefix) { | ||||||
| 			this.$refs.label.style.left = (this.$refs.prefix.offsetLeft + this.$refs.prefix.offsetWidth) + 'px'; | 			this.$refs.label.style.left = (this.$refs.prefix.offsetLeft + this.$refs.prefix.offsetWidth) + 'px'; | ||||||
| @@ -155,9 +151,7 @@ export default Vue.extend({ | |||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <style lang="stylus" scoped> | <style lang="stylus" scoped> | ||||||
| @import '~const.styl' | root(fill) | ||||||
|  |  | ||||||
| root(isDark, fill) |  | ||||||
| 	margin 32px 0 | 	margin 32px 0 | ||||||
|  |  | ||||||
| 	> .icon | 	> .icon | ||||||
| @@ -167,7 +161,7 @@ root(isDark, fill) | |||||||
| 		width 24px | 		width 24px | ||||||
| 		text-align center | 		text-align center | ||||||
| 		line-height 32px | 		line-height 32px | ||||||
| 		color isDark ? rgba(#fff, 0.7) : rgba(#000, 0.54) | 		color var(--inputLabel) | ||||||
|  |  | ||||||
| 		&:not(:empty) + .input | 		&:not(:empty) + .input | ||||||
| 			margin-left 28px | 			margin-left 28px | ||||||
| @@ -183,7 +177,7 @@ root(isDark, fill) | |||||||
| 				left 0 | 				left 0 | ||||||
| 				right 0 | 				right 0 | ||||||
| 				height 1px | 				height 1px | ||||||
| 				background isDark ? rgba(#fff, 0.7) : rgba(#000, 0.42) | 				background var(--inputBorder) | ||||||
|  |  | ||||||
| 			&:after | 			&:after | ||||||
| 				content '' | 				content '' | ||||||
| @@ -193,7 +187,7 @@ root(isDark, fill) | |||||||
| 				left 0 | 				left 0 | ||||||
| 				right 0 | 				right 0 | ||||||
| 				height 2px | 				height 2px | ||||||
| 				background $theme-color | 				background var(--primary) | ||||||
| 				opacity 0 | 				opacity 0 | ||||||
| 				transform scaleX(0.12) | 				transform scaleX(0.12) | ||||||
| 				transition border 0.3s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1), transform 0.3s cubic-bezier(0.4, 0, 0.2, 1) | 				transition border 0.3s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1), transform 0.3s cubic-bezier(0.4, 0, 0.2, 1) | ||||||
| @@ -242,7 +236,7 @@ root(isDark, fill) | |||||||
| 			transition-duration 0.3s | 			transition-duration 0.3s | ||||||
| 			font-size 16px | 			font-size 16px | ||||||
| 			line-height 32px | 			line-height 32px | ||||||
| 			color isDark ? rgba(#fff, 0.7) : rgba(#000, 0.54) | 			color var(--inputLabel) | ||||||
| 			pointer-events none | 			pointer-events none | ||||||
| 			//will-change transform | 			//will-change transform | ||||||
| 			transform-origin top left | 			transform-origin top left | ||||||
| @@ -257,7 +251,7 @@ root(isDark, fill) | |||||||
| 			font-weight fill ? bold : normal | 			font-weight fill ? bold : normal | ||||||
| 			font-size 16px | 			font-size 16px | ||||||
| 			line-height 32px | 			line-height 32px | ||||||
| 			color isDark ? #fff : #000 | 			color var(--inputText) | ||||||
| 			background transparent | 			background transparent | ||||||
| 			border none | 			border none | ||||||
| 			border-radius 0 | 			border-radius 0 | ||||||
| @@ -280,7 +274,7 @@ root(isDark, fill) | |||||||
| 			top 0 | 			top 0 | ||||||
| 			font-size 16px | 			font-size 16px | ||||||
| 			line-height fill ? 44px : 32px | 			line-height fill ? 44px : 32px | ||||||
| 			color isDark ? rgba(#fff, 0.7) : rgba(#000, 0.54) | 			color var(--inputLabel) | ||||||
| 			pointer-events none | 			pointer-events none | ||||||
|  |  | ||||||
| 			&:empty | 			&:empty | ||||||
| @@ -325,7 +319,7 @@ root(isDark, fill) | |||||||
| 					transform scaleX(1) | 					transform scaleX(1) | ||||||
|  |  | ||||||
| 			> .label | 			> .label | ||||||
| 				color $theme-color | 				color var(--primary) | ||||||
|  |  | ||||||
| 	&.focused | 	&.focused | ||||||
| 	&.filled | 	&.filled | ||||||
| @@ -335,16 +329,10 @@ root(isDark, fill) | |||||||
| 				left 0 !important | 				left 0 !important | ||||||
| 				transform scale(0.75) | 				transform scale(0.75) | ||||||
|  |  | ||||||
| .ui-input[data-darkmode] | .ui-input | ||||||
| 	&.fill | 	&.fill | ||||||
| 		root(true, true) | 		root(true) | ||||||
| 	&:not(.fill) | 	&:not(.fill) | ||||||
| 		root(true, false) | 		root(false) | ||||||
|  |  | ||||||
| .ui-input:not([data-darkmode]) |  | ||||||
| 	&.fill |  | ||||||
| 		root(false, true) |  | ||||||
| 	&:not(.fill) |  | ||||||
| 		root(false, false) |  | ||||||
|  |  | ||||||
| </style> | </style> | ||||||
|   | |||||||
| @@ -51,9 +51,7 @@ export default Vue.extend({ | |||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <style lang="stylus" scoped> | <style lang="stylus" scoped> | ||||||
| @import '~const.styl' | .ui-radio | ||||||
|  |  | ||||||
| root(isDark) |  | ||||||
| 	display inline-block | 	display inline-block | ||||||
| 	margin 0 32px 0 0 | 	margin 0 32px 0 0 | ||||||
| 	cursor pointer | 	cursor pointer | ||||||
| @@ -68,10 +66,10 @@ root(isDark) | |||||||
|  |  | ||||||
| 	&.checked | 	&.checked | ||||||
| 		> .button | 		> .button | ||||||
| 			border-color $theme-color | 			border-color var(--primary) | ||||||
|  |  | ||||||
| 			&:after | 			&:after | ||||||
| 				background-color $theme-color | 				background-color var(--primary) | ||||||
| 				transform scale(1) | 				transform scale(1) | ||||||
| 				opacity 1 | 				opacity 1 | ||||||
|  |  | ||||||
| @@ -87,7 +85,7 @@ root(isDark) | |||||||
| 		width 20px | 		width 20px | ||||||
| 		height 20px | 		height 20px | ||||||
| 		background none | 		background none | ||||||
| 		border solid 2px isDark ? rgba(#fff, 0.7) : rgba(#000, 0.54) | 		border solid 2px var(--inputLabel) | ||||||
| 		border-radius 100% | 		border-radius 100% | ||||||
| 		transition inherit | 		transition inherit | ||||||
|  |  | ||||||
| @@ -111,10 +109,4 @@ root(isDark) | |||||||
| 		line-height 20px | 		line-height 20px | ||||||
| 		cursor pointer | 		cursor pointer | ||||||
|  |  | ||||||
| .ui-radio[data-darkmode] |  | ||||||
| 	root(true) |  | ||||||
|  |  | ||||||
| .ui-radio:not([data-darkmode]) |  | ||||||
| 	root(false) |  | ||||||
|  |  | ||||||
| </style> | </style> | ||||||
|   | |||||||
| @@ -29,13 +29,17 @@ export default Vue.extend({ | |||||||
| 		required: { | 		required: { | ||||||
| 			type: Boolean, | 			type: Boolean, | ||||||
| 			required: false | 			required: false | ||||||
|  | 		}, | ||||||
|  | 		styl: { | ||||||
|  | 			type: String, | ||||||
|  | 			required: false, | ||||||
|  | 			default: 'line' | ||||||
| 		} | 		} | ||||||
| 	}, | 	}, | ||||||
| 	data() { | 	data() { | ||||||
| 		return { | 		return { | ||||||
| 			v: this.value, | 			v: this.value, | ||||||
| 			focused: false, | 			focused: false | ||||||
| 			styl: 'fill' |  | ||||||
| 		}; | 		}; | ||||||
| 	}, | 	}, | ||||||
| 	computed: { | 	computed: { | ||||||
| @@ -48,14 +52,6 @@ export default Vue.extend({ | |||||||
| 			this.v = v; | 			this.v = v; | ||||||
| 		} | 		} | ||||||
| 	}, | 	}, | ||||||
| 	inject: { |  | ||||||
| 		isCardChild: { default: false } |  | ||||||
| 	}, |  | ||||||
| 	created() { |  | ||||||
| 		if (this.isCardChild) { |  | ||||||
| 			this.styl = 'line'; |  | ||||||
| 		} |  | ||||||
| 	}, |  | ||||||
| 	mounted() { | 	mounted() { | ||||||
| 		if (this.$refs.prefix) { | 		if (this.$refs.prefix) { | ||||||
| 			this.$refs.label.style.left = (this.$refs.prefix.offsetLeft + this.$refs.prefix.offsetWidth) + 'px'; | 			this.$refs.label.style.left = (this.$refs.prefix.offsetLeft + this.$refs.prefix.offsetWidth) + 'px'; | ||||||
| @@ -70,9 +66,7 @@ export default Vue.extend({ | |||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <style lang="stylus" scoped> | <style lang="stylus" scoped> | ||||||
| @import '~const.styl' | root(fill) | ||||||
|  |  | ||||||
| root(isDark, fill) |  | ||||||
| 	margin 32px 0 | 	margin 32px 0 | ||||||
|  |  | ||||||
| 	> .icon | 	> .icon | ||||||
| @@ -103,7 +97,7 @@ root(isDark, fill) | |||||||
| 				left 0 | 				left 0 | ||||||
| 				right 0 | 				right 0 | ||||||
| 				height 1px | 				height 1px | ||||||
| 				background isDark ? rgba(#fff, 0.7) : rgba(#000, 0.42) | 				background var(--inputBorder) | ||||||
|  |  | ||||||
| 			&:after | 			&:after | ||||||
| 				content '' | 				content '' | ||||||
| @@ -113,7 +107,7 @@ root(isDark, fill) | |||||||
| 				left 0 | 				left 0 | ||||||
| 				right 0 | 				right 0 | ||||||
| 				height 2px | 				height 2px | ||||||
| 				background $theme-color | 				background var(--primary) | ||||||
| 				opacity 0 | 				opacity 0 | ||||||
| 				transform scaleX(0.12) | 				transform scaleX(0.12) | ||||||
| 				transition border 0.3s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1), transform 0.3s cubic-bezier(0.4, 0, 0.2, 1) | 				transition border 0.3s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1), transform 0.3s cubic-bezier(0.4, 0, 0.2, 1) | ||||||
| @@ -143,7 +137,7 @@ root(isDark, fill) | |||||||
| 			font-weight fill ? bold : normal | 			font-weight fill ? bold : normal | ||||||
| 			font-size 16px | 			font-size 16px | ||||||
| 			height 32px | 			height 32px | ||||||
| 			color isDark ? #fff : #000 | 			color var(--inputText) | ||||||
| 			background transparent | 			background transparent | ||||||
| 			border none | 			border none | ||||||
| 			border-radius 0 | 			border-radius 0 | ||||||
| @@ -190,7 +184,7 @@ root(isDark, fill) | |||||||
| 					transform scaleX(1) | 					transform scaleX(1) | ||||||
|  |  | ||||||
| 			> .label | 			> .label | ||||||
| 				color $theme-color | 				color var(--primary) | ||||||
|  |  | ||||||
| 	&.focused | 	&.focused | ||||||
| 	&.filled | 	&.filled | ||||||
| @@ -200,16 +194,10 @@ root(isDark, fill) | |||||||
| 				left 0 !important | 				left 0 !important | ||||||
| 				transform scale(0.75) | 				transform scale(0.75) | ||||||
|  |  | ||||||
| .ui-select[data-darkmode] | .ui-select | ||||||
| 	&.fill | 	&.fill | ||||||
| 		root(true, true) | 		root(true) | ||||||
| 	&:not(.fill) | 	&:not(.fill) | ||||||
| 		root(true, false) | 		root(false) | ||||||
|  |  | ||||||
| .ui-select:not([data-darkmode]) |  | ||||||
| 	&.fill |  | ||||||
| 		root(false, true) |  | ||||||
| 	&:not(.fill) |  | ||||||
| 		root(false, false) |  | ||||||
|  |  | ||||||
| </style> | </style> | ||||||
|   | |||||||
| @@ -19,7 +19,7 @@ | |||||||
| 	<span class="label"> | 	<span class="label"> | ||||||
| 		<span :aria-hidden="!checked"><slot></slot></span> | 		<span :aria-hidden="!checked"><slot></slot></span> | ||||||
| 		<p :aria-hidden="!checked"> | 		<p :aria-hidden="!checked"> | ||||||
| 			<slot name="text"></slot> | 			<slot name="desc"></slot> | ||||||
| 		</p> | 		</p> | ||||||
| 	</span> | 	</span> | ||||||
| </div> | </div> | ||||||
| @@ -56,9 +56,7 @@ export default Vue.extend({ | |||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <style lang="stylus" scoped> | <style lang="stylus" scoped> | ||||||
| @import '~const.styl' | .ui-switch | ||||||
|  |  | ||||||
| root(isDark) |  | ||||||
| 	display flex | 	display flex | ||||||
| 	margin 32px 0 | 	margin 32px 0 | ||||||
| 	cursor pointer | 	cursor pointer | ||||||
| @@ -79,11 +77,11 @@ root(isDark) | |||||||
|  |  | ||||||
| 	&.checked | 	&.checked | ||||||
| 		> .button | 		> .button | ||||||
| 			background-color rgba($theme-color, 0.4) | 			background-color var(--primaryAlpha04) | ||||||
| 			border-color rgba($theme-color, 0.4) | 			border-color var(--primaryAlpha04) | ||||||
|  |  | ||||||
| 			> * | 			> * | ||||||
| 				background-color $theme-color | 				background-color var(--primary) | ||||||
| 				transform translateX(14px) | 				transform translateX(14px) | ||||||
|  |  | ||||||
| 	> input | 	> input | ||||||
| @@ -99,7 +97,7 @@ root(isDark) | |||||||
| 		margin 3px 0 0 0 | 		margin 3px 0 0 0 | ||||||
| 		width 34px | 		width 34px | ||||||
| 		height 14px | 		height 14px | ||||||
| 		background isDark ? rgba(#fff, 0.15) : rgba(#000, 0.25) | 		background var(--switchTrack) | ||||||
| 		outline none | 		outline none | ||||||
| 		border-radius 14px | 		border-radius 14px | ||||||
| 		transition inherit | 		transition inherit | ||||||
| @@ -125,18 +123,11 @@ root(isDark) | |||||||
| 		> span | 		> span | ||||||
| 			display block | 			display block | ||||||
| 			line-height 20px | 			line-height 20px | ||||||
| 			color isDark ? #c4ccd2 : rgba(#000, 0.75) | 			color currentColor | ||||||
| 			transition inherit | 			transition inherit | ||||||
|  |  | ||||||
| 		> p | 		> p | ||||||
| 			margin 0 | 			margin 0 | ||||||
| 			//font-size 90% | 			opacity 0.7 | ||||||
| 			color isDark ? #78858e : #9daab3 |  | ||||||
|  |  | ||||||
| .ui-switch[data-darkmode] |  | ||||||
| 	root(true) |  | ||||||
|  |  | ||||||
| .ui-switch:not([data-darkmode]) |  | ||||||
| 	root(false) |  | ||||||
|  |  | ||||||
| </style> | </style> | ||||||
|   | |||||||
| @@ -63,9 +63,7 @@ export default Vue.extend({ | |||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <style lang="stylus" scoped> | <style lang="stylus" scoped> | ||||||
| @import '~const.styl' | root(fill) | ||||||
|  |  | ||||||
| root(isDark, fill) |  | ||||||
| 	margin 42px 0 32px 0 | 	margin 42px 0 32px 0 | ||||||
|  |  | ||||||
| 	> .input | 	> .input | ||||||
| @@ -84,7 +82,7 @@ root(isDark, fill) | |||||||
| 				left 0 | 				left 0 | ||||||
| 				right 0 | 				right 0 | ||||||
| 				background none | 				background none | ||||||
| 				border solid 1px isDark ? rgba(#fff, 0.7) : rgba(#000, 0.42) | 				border solid 1px var(--inputBorder) | ||||||
| 				border-radius 3px | 				border-radius 3px | ||||||
| 				pointer-events none | 				pointer-events none | ||||||
|  |  | ||||||
| @@ -97,7 +95,7 @@ root(isDark, fill) | |||||||
| 				left 0 | 				left 0 | ||||||
| 				right 0 | 				right 0 | ||||||
| 				background none | 				background none | ||||||
| 				border solid 2px $theme-color | 				border solid 2px var(--primary) | ||||||
| 				border-radius 3px | 				border-radius 3px | ||||||
| 				opacity 0 | 				opacity 0 | ||||||
| 				transition opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1) | 				transition opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1) | ||||||
| @@ -112,7 +110,7 @@ root(isDark, fill) | |||||||
| 			transition-duration 0.3s | 			transition-duration 0.3s | ||||||
| 			font-size 16px | 			font-size 16px | ||||||
| 			line-height 32px | 			line-height 32px | ||||||
| 			color isDark ? rgba(#fff, 0.7) : rgba(#000, 0.54) | 			color var(--inputLabel) | ||||||
| 			pointer-events none | 			pointer-events none | ||||||
| 			//will-change transform | 			//will-change transform | ||||||
| 			transform-origin top left | 			transform-origin top left | ||||||
| @@ -126,7 +124,7 @@ root(isDark, fill) | |||||||
| 			font inherit | 			font inherit | ||||||
| 			font-weight fill ? bold : normal | 			font-weight fill ? bold : normal | ||||||
| 			font-size 16px | 			font-size 16px | ||||||
| 			color isDark ? #fff : #000 | 			color var(--inputText) | ||||||
| 			background transparent | 			background transparent | ||||||
| 			border none | 			border none | ||||||
| 			border-radius 0 | 			border-radius 0 | ||||||
| @@ -149,7 +147,7 @@ root(isDark, fill) | |||||||
| 					opacity 1 | 					opacity 1 | ||||||
|  |  | ||||||
| 			> .label | 			> .label | ||||||
| 				color $theme-color | 				color var(--primary) | ||||||
|  |  | ||||||
| 	&.focused | 	&.focused | ||||||
| 	&.filled | 	&.filled | ||||||
| @@ -159,16 +157,10 @@ root(isDark, fill) | |||||||
| 				left 0 !important | 				left 0 !important | ||||||
| 				transform scale(0.75) | 				transform scale(0.75) | ||||||
|  |  | ||||||
| .ui-textarea[data-darkmode] | .ui-textarea.fill | ||||||
| 	&.fill | 	root(true) | ||||||
| 		root(true, true) |  | ||||||
| 	&:not(.fill) |  | ||||||
| 		root(true, false) |  | ||||||
|  |  | ||||||
| .ui-textarea:not([data-darkmode]) | .ui-textarea:not(.fill) | ||||||
| 	&.fill | 	root(false) | ||||||
| 		root(false, true) |  | ||||||
| 	&:not(.fill) |  | ||||||
| 		root(false, false) |  | ||||||
|  |  | ||||||
| </style> | </style> | ||||||
|   | |||||||
| @@ -20,6 +20,7 @@ | |||||||
| <script lang="ts"> | <script lang="ts"> | ||||||
| import Vue from 'vue'; | import Vue from 'vue'; | ||||||
| import { apiUrl } from '../../../config'; | import { apiUrl } from '../../../config'; | ||||||
|  | import getMD5 from '../../scripts/get-md5'; | ||||||
|  |  | ||||||
| export default Vue.extend({ | export default Vue.extend({ | ||||||
| 	data() { | 	data() { | ||||||
| @@ -28,61 +29,83 @@ export default Vue.extend({ | |||||||
| 		}; | 		}; | ||||||
| 	}, | 	}, | ||||||
| 	methods: { | 	methods: { | ||||||
| 		upload(file, folder) { | 		checkExistence(fileData: ArrayBuffer): Promise<any> { | ||||||
|  | 			return new Promise((resolve, reject) => { | ||||||
|  | 				const data = new FormData(); | ||||||
|  | 				data.append('md5', getMD5(fileData)); | ||||||
|  |  | ||||||
|  | 				(this as any).api('drive/files/check_existence', { | ||||||
|  | 					md5: getMD5(fileData) | ||||||
|  | 				}).then(resp => { | ||||||
|  | 					resolve(resp.file); | ||||||
|  | 				}); | ||||||
|  | 			}); | ||||||
|  | 		}, | ||||||
|  |  | ||||||
|  | 		upload(file: File, folder: any) { | ||||||
| 			if (folder && typeof folder == 'object') folder = folder.id; | 			if (folder && typeof folder == 'object') folder = folder.id; | ||||||
|  |  | ||||||
| 			const id = Math.random(); | 			const id = Math.random(); | ||||||
|  |  | ||||||
| 			const ctx = { |  | ||||||
| 				id: id, |  | ||||||
| 				name: file.name || 'untitled', |  | ||||||
| 				progress: undefined, |  | ||||||
| 				img: undefined |  | ||||||
| 			}; |  | ||||||
|  |  | ||||||
| 			this.uploads.push(ctx); |  | ||||||
| 			this.$emit('change', this.uploads); |  | ||||||
|  |  | ||||||
| 			const reader = new FileReader(); | 			const reader = new FileReader(); | ||||||
| 			reader.onload = (e: any) => { | 			reader.onload = (e: any) => { | ||||||
| 				ctx.img = e.target.result; | 				this.checkExistence(e.target.result).then(result => { | ||||||
| 			}; | 					if (result !== null) { | ||||||
| 			reader.readAsDataURL(file); | 						this.$emit('uploaded', result); | ||||||
|  | 						return; | ||||||
|  | 					} | ||||||
|  |  | ||||||
| 			const data = new FormData(); | 					// Upload if the file didn't exist yet | ||||||
| 			data.append('i', this.$store.state.i.token); | 					const buf = new Uint8Array(e.target.result); | ||||||
| 			data.append('file', file); | 					let bin = ''; | ||||||
|  | 					// We use for-of loop instead of apply() to avoid RangeError | ||||||
|  | 					// SEE: https://stackoverflow.com/questions/9267899/arraybuffer-to-base64-encoded-string | ||||||
|  | 					for (const byte of buf) bin += String.fromCharCode(byte); | ||||||
|  | 					const ctx = { | ||||||
|  | 						id: id, | ||||||
|  | 						name: file.name || 'untitled', | ||||||
|  | 						progress: undefined, | ||||||
|  | 						img: 'data:*/*;base64,' + btoa(bin) | ||||||
|  | 					}; | ||||||
|  |  | ||||||
| 			if (folder) data.append('folderId', folder); | 					this.uploads.push(ctx); | ||||||
|  | 					this.$emit('change', this.uploads); | ||||||
|  |  | ||||||
| 			const xhr = new XMLHttpRequest(); | 					const data = new FormData(); | ||||||
| 			xhr.open('POST', apiUrl + '/drive/files/create', true); | 					data.append('i', this.$store.state.i.token); | ||||||
| 			xhr.onload = (e: any) => { | 					data.append('file', file); | ||||||
| 				const driveFile = JSON.parse(e.target.response); |  | ||||||
|  |  | ||||||
| 				this.$emit('uploaded', driveFile); | 					if (folder) data.append('folderId', folder); | ||||||
|  |  | ||||||
| 				this.uploads = this.uploads.filter(x => x.id != id); | 					const xhr = new XMLHttpRequest(); | ||||||
| 				this.$emit('change', this.uploads); | 					xhr.open('POST', apiUrl + '/drive/files/create', true); | ||||||
| 			}; | 					xhr.onload = (e: any) => { | ||||||
|  | 						const driveFile = JSON.parse(e.target.response); | ||||||
|  |  | ||||||
| 			xhr.upload.onprogress = e => { | 						this.$emit('uploaded', driveFile); | ||||||
| 				if (e.lengthComputable) { |  | ||||||
| 					if (ctx.progress == undefined) ctx.progress = {}; |  | ||||||
| 					ctx.progress.max = e.total; |  | ||||||
| 					ctx.progress.value = e.loaded; |  | ||||||
| 				} |  | ||||||
| 			}; |  | ||||||
|  |  | ||||||
| 			xhr.send(data); | 						this.uploads = this.uploads.filter(x => x.id != id); | ||||||
|  | 						this.$emit('change', this.uploads); | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					xhr.upload.onprogress = e => { | ||||||
|  | 						if (e.lengthComputable) { | ||||||
|  | 							if (ctx.progress == undefined) ctx.progress = {}; | ||||||
|  | 							ctx.progress.max = e.total; | ||||||
|  | 							ctx.progress.value = e.loaded; | ||||||
|  | 						} | ||||||
|  | 					}; | ||||||
|  |  | ||||||
|  | 					xhr.send(data); | ||||||
|  | 				}) | ||||||
|  | 			} | ||||||
|  | 			reader.readAsArrayBuffer(file); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| }); | }); | ||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <style lang="stylus" scoped> | <style lang="stylus" scoped> | ||||||
| @import '~const.styl' |  | ||||||
|  |  | ||||||
| .mk-uploader | .mk-uploader | ||||||
| 	overflow auto | 	overflow auto | ||||||
|  |  | ||||||
| @@ -100,7 +123,7 @@ export default Vue.extend({ | |||||||
| 			margin 8px 0 0 0 | 			margin 8px 0 0 0 | ||||||
| 			padding 0 | 			padding 0 | ||||||
| 			height 36px | 			height 36px | ||||||
| 			box-shadow 0 -1px 0 rgba($theme-color, 0.1) | 			box-shadow 0 -1px 0 var(--primaryAlpha01) | ||||||
| 			border-top solid 8px transparent | 			border-top solid 8px transparent | ||||||
|  |  | ||||||
| 			&:first-child | 			&:first-child | ||||||
| @@ -127,7 +150,7 @@ export default Vue.extend({ | |||||||
| 				padding 0 | 				padding 0 | ||||||
| 				max-width 256px | 				max-width 256px | ||||||
| 				font-size 0.8em | 				font-size 0.8em | ||||||
| 				color rgba($theme-color, 0.7) | 				color var(--primaryAlpha07) | ||||||
| 				white-space nowrap | 				white-space nowrap | ||||||
| 				text-overflow ellipsis | 				text-overflow ellipsis | ||||||
| 				overflow hidden | 				overflow hidden | ||||||
| @@ -145,17 +168,17 @@ export default Vue.extend({ | |||||||
| 				font-size 0.8em | 				font-size 0.8em | ||||||
|  |  | ||||||
| 				> .initing | 				> .initing | ||||||
| 					color rgba($theme-color, 0.5) | 					color var(--primaryAlpha05) | ||||||
|  |  | ||||||
| 				> .kb | 				> .kb | ||||||
| 					color rgba($theme-color, 0.5) | 					color var(--primaryAlpha05) | ||||||
|  |  | ||||||
| 				> .percentage | 				> .percentage | ||||||
| 					display inline-block | 					display inline-block | ||||||
| 					width 48px | 					width 48px | ||||||
| 					text-align right | 					text-align right | ||||||
|  |  | ||||||
| 					color rgba($theme-color, 0.7) | 					color var(--primaryAlpha07) | ||||||
|  |  | ||||||
| 					&:after | 					&:after | ||||||
| 						content '%' | 						content '%' | ||||||
| @@ -174,10 +197,10 @@ export default Vue.extend({ | |||||||
| 				overflow hidden | 				overflow hidden | ||||||
|  |  | ||||||
| 				&::-webkit-progress-value | 				&::-webkit-progress-value | ||||||
| 					background $theme-color | 					background var(--primary) | ||||||
|  |  | ||||||
| 				&::-webkit-progress-bar | 				&::-webkit-progress-bar | ||||||
| 					background rgba($theme-color, 0.1) | 					background var(--primaryAlpha01) | ||||||
|  |  | ||||||
| 			> .progress | 			> .progress | ||||||
| 				display block | 				display block | ||||||
| @@ -191,13 +214,13 @@ export default Vue.extend({ | |||||||
| 				border-radius 4px | 				border-radius 4px | ||||||
| 				background linear-gradient( | 				background linear-gradient( | ||||||
| 					45deg, | 					45deg, | ||||||
| 					lighten($theme-color, 30%) 25%, | 					var(--primaryLighten30) 25%, | ||||||
| 					$theme-color               25%, | 					var(--primary)               25%, | ||||||
| 					$theme-color               50%, | 					var(--primary)               50%, | ||||||
| 					lighten($theme-color, 30%) 50%, | 					var(--primaryLighten30) 50%, | ||||||
| 					lighten($theme-color, 30%) 75%, | 					var(--primaryLighten30) 75%, | ||||||
| 					$theme-color               75%, | 					var(--primary)               75%, | ||||||
| 					$theme-color | 					var(--primary) | ||||||
| 				) | 				) | ||||||
| 				background-size 32px 32px | 				background-size 32px 32px | ||||||
| 				animation bg 1.5s linear infinite | 				animation bg 1.5s linear infinite | ||||||
|   | |||||||
| @@ -200,17 +200,17 @@ export default Vue.extend({ | |||||||
| 		top 0 | 		top 0 | ||||||
| 		width 100% | 		width 100% | ||||||
|  |  | ||||||
| root(isDark) | .mk-url-preview | ||||||
| 	> a | 	> a | ||||||
| 		display block | 		display block | ||||||
| 		font-size 14px | 		font-size 14px | ||||||
| 		border solid 1px isDark ? #191b1f : #eee | 		border solid 1px var(--urlPreviewBorder) | ||||||
| 		border-radius 4px | 		border-radius 4px | ||||||
| 		overflow hidden | 		overflow hidden | ||||||
|  |  | ||||||
| 		&:hover | 		&:hover | ||||||
| 			text-decoration none | 			text-decoration none | ||||||
| 			border-color isDark ? #4f5561 : #ddd | 			border-color var(--urlPreviewBorderHover) | ||||||
|  |  | ||||||
| 			> article > header > h1 | 			> article > header > h1 | ||||||
| 				text-decoration underline | 				text-decoration underline | ||||||
| @@ -235,11 +235,11 @@ root(isDark) | |||||||
| 				> h1 | 				> h1 | ||||||
| 					margin 0 | 					margin 0 | ||||||
| 					font-size 1em | 					font-size 1em | ||||||
| 					color isDark ? #d6dae0 : #555 | 					color var(--urlPreviewTitle) | ||||||
|  |  | ||||||
| 			> p | 			> p | ||||||
| 				margin 0 | 				margin 0 | ||||||
| 				color isDark ? #a4aab3 : #777 | 				color var(--urlPreviewText) | ||||||
| 				font-size 0.8em | 				font-size 0.8em | ||||||
|  |  | ||||||
| 			> footer | 			> footer | ||||||
| @@ -256,7 +256,7 @@ root(isDark) | |||||||
| 				> p | 				> p | ||||||
| 					display inline-block | 					display inline-block | ||||||
| 					margin 0 | 					margin 0 | ||||||
| 					color isDark ? #b0b4bf : #666 | 					color var(--urlPreviewInfo) | ||||||
| 					font-size 0.8em | 					font-size 0.8em | ||||||
| 					line-height 16px | 					line-height 16px | ||||||
| 					vertical-align top | 					vertical-align top | ||||||
| @@ -322,10 +322,4 @@ root(isDark) | |||||||
| 						width 12px | 						width 12px | ||||||
| 						height 12px | 						height 12px | ||||||
|  |  | ||||||
| .mk-url-preview[data-darkmode] |  | ||||||
| 	root(true) |  | ||||||
|  |  | ||||||
| .mk-url-preview:not([data-darkmode]) |  | ||||||
| 	root(false) |  | ||||||
|  |  | ||||||
| </style> | </style> | ||||||
|   | |||||||
| @@ -127,11 +127,9 @@ export default Vue.extend({ | |||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <style lang="stylus" scoped> | <style lang="stylus" scoped> | ||||||
| @import '~const.styl' |  | ||||||
|  |  | ||||||
| $border-color = rgba(27, 31, 35, 0.15) | $border-color = rgba(27, 31, 35, 0.15) | ||||||
|  |  | ||||||
| root(isDark) | .mk-visibility-chooser | ||||||
| 	position initial | 	position initial | ||||||
|  |  | ||||||
| 	> .backdrop | 	> .backdrop | ||||||
| @@ -141,11 +139,11 @@ root(isDark) | |||||||
| 		z-index 10000 | 		z-index 10000 | ||||||
| 		width 100% | 		width 100% | ||||||
| 		height 100% | 		height 100% | ||||||
| 		background isDark ? rgba(#000, 0.4) : rgba(#000, 0.1) | 		background var(--modalBackdrop) | ||||||
| 		opacity 0 | 		opacity 0 | ||||||
|  |  | ||||||
| 	> .popover | 	> .popover | ||||||
| 		$bgcolor = isDark ? #2c303c : #fff | 		$bgcolor = var(--popupBg) | ||||||
| 		position absolute | 		position absolute | ||||||
| 		z-index 10001 | 		z-index 10001 | ||||||
| 		width 240px | 		width 240px | ||||||
| @@ -189,18 +187,18 @@ root(isDark) | |||||||
| 			display flex | 			display flex | ||||||
| 			padding 8px 14px | 			padding 8px 14px | ||||||
| 			font-size 12px | 			font-size 12px | ||||||
| 			color isDark ? #fff : #666 | 			color var(--popupFg) | ||||||
| 			cursor pointer | 			cursor pointer | ||||||
|  |  | ||||||
| 			&:hover | 			&:hover | ||||||
| 				background isDark ? #252731 : #eee | 				background var(--faceClearButtonHover) | ||||||
|  |  | ||||||
| 			&:active | 			&:active | ||||||
| 				background isDark ? #21242b : #ddd | 				background var(--faceClearButtonActive) | ||||||
|  |  | ||||||
| 			&.active | 			&.active | ||||||
| 				color $theme-color-foreground | 				color var(--primaryForeground) | ||||||
| 				background $theme-color | 				background var(--primary) | ||||||
|  |  | ||||||
| 			> * | 			> * | ||||||
| 				user-select none | 				user-select none | ||||||
| @@ -222,11 +220,4 @@ root(isDark) | |||||||
|  |  | ||||||
| 				> span:last-child:not(:first-child) | 				> span:last-child:not(:first-child) | ||||||
| 					opacity 0.6 | 					opacity 0.6 | ||||||
|  |  | ||||||
| .mk-visibility-chooser[data-darkmode] |  | ||||||
| 	root(true) |  | ||||||
|  |  | ||||||
| .mk-visibility-chooser:not([data-darkmode]) |  | ||||||
| 	root(false) |  | ||||||
|  |  | ||||||
| </style> | </style> | ||||||
|   | |||||||
| @@ -38,23 +38,20 @@ export default Vue.extend({ | |||||||
| 		return { | 		return { | ||||||
| 			fetching: true, | 			fetching: true, | ||||||
| 			notes: [], | 			notes: [], | ||||||
| 			connection: null, | 			connection: null | ||||||
| 			connectionId: null |  | ||||||
| 		}; | 		}; | ||||||
| 	}, | 	}, | ||||||
|  |  | ||||||
| 	mounted() { | 	mounted() { | ||||||
| 		this.fetch(); | 		this.fetch(); | ||||||
|  |  | ||||||
| 		this.connection = (this as any).os.streams.localTimelineStream.getConnection(); | 		this.connection = (this as any).os.stream.useSharedConnection('localTimeline'); | ||||||
| 		this.connectionId = (this as any).os.streams.localTimelineStream.use(); |  | ||||||
|  |  | ||||||
| 		this.connection.on('note', this.onNote); | 		this.connection.on('note', this.onNote); | ||||||
| 	}, | 	}, | ||||||
|  |  | ||||||
| 	beforeDestroy() { | 	beforeDestroy() { | ||||||
| 		this.connection.off('note', this.onNote); | 		this.connection.dispose(); | ||||||
| 		(this as any).os.streams.localTimelineStream.dispose(this.connectionId); |  | ||||||
| 	}, | 	}, | ||||||
|  |  | ||||||
| 	methods: { | 	methods: { | ||||||
| @@ -90,8 +87,8 @@ export default Vue.extend({ | |||||||
| 	opacity 0 | 	opacity 0 | ||||||
| 	transform translateY(-30px) | 	transform translateY(-30px) | ||||||
|  |  | ||||||
| root(isDark) | .mk-welcome-timeline | ||||||
| 	background isDark ? #282C37 : #fff | 	background var(--face) | ||||||
|  |  | ||||||
| 	> div | 	> div | ||||||
| 		> * | 		> * | ||||||
| @@ -101,8 +98,8 @@ root(isDark) | |||||||
| 			padding 16px | 			padding 16px | ||||||
| 			overflow-wrap break-word | 			overflow-wrap break-word | ||||||
| 			font-size .9em | 			font-size .9em | ||||||
| 			color isDark ? #fff : #4C4C4C | 			color var(--noteText) | ||||||
| 			border-bottom 1px solid isDark ? rgba(#000, 0.1) : rgba(#000, 0.05) | 			border-bottom 1px solid var(--faceDivider) | ||||||
|  |  | ||||||
| 			&:after | 			&:after | ||||||
| 				content "" | 				content "" | ||||||
| @@ -137,26 +134,20 @@ root(isDark) | |||||||
| 						overflow hidden | 						overflow hidden | ||||||
| 						font-weight bold | 						font-weight bold | ||||||
| 						text-overflow ellipsis | 						text-overflow ellipsis | ||||||
| 						color isDark ? #fff : #627079 | 						color var(--noteHeaderName) | ||||||
|  |  | ||||||
| 					> .username | 					> .username | ||||||
| 						margin 0 .5em 0 0 | 						margin 0 .5em 0 0 | ||||||
| 						color isDark ? #606984 : #ccc | 						color var(--noteHeaderAcct) | ||||||
|  |  | ||||||
| 					> .info | 					> .info | ||||||
| 						margin-left auto | 						margin-left auto | ||||||
| 						font-size 0.9em | 						font-size 0.9em | ||||||
|  |  | ||||||
| 						> .created-at | 						> .created-at | ||||||
| 							color isDark ? #606984 : #c0c0c0 | 							color var(--noteHeaderInfo) | ||||||
|  |  | ||||||
| 				> .text | 				> .text | ||||||
| 					text-align left | 					text-align left | ||||||
|  |  | ||||||
| .mk-welcome-timeline[data-darkmode] |  | ||||||
| 	root(true) |  | ||||||
|  |  | ||||||
| .mk-welcome-timeline:not([data-darkmode]) |  | ||||||
| 	root(false) |  | ||||||
|  |  | ||||||
| </style> | </style> | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| <template> | <template> | ||||||
| <div class="syxhndwprovvuqhmyvveewmbqayniwkv" v-if="!fetching" :data-darkmode="$store.state.device.darkmode"> | <div class="syxhndwprovvuqhmyvveewmbqayniwkv" v-if="!fetching"> | ||||||
| 	<div class="signed-in-as" v-html="'%i18n:@signed-in-as%'.replace('{}', `<b>${myName}`)"></div> | 	<div class="signed-in-as" v-html="'%i18n:@signed-in-as%'.replace('{}', `<b>${myName}`)"></div> | ||||||
|  |  | ||||||
| 	<main> | 	<main> | ||||||
| @@ -19,7 +19,8 @@ | |||||||
| 			@click="onClick" | 			@click="onClick" | ||||||
| 			:disabled="followWait"> | 			:disabled="followWait"> | ||||||
| 		<template v-if="!followWait"> | 		<template v-if="!followWait"> | ||||||
| 			<template v-if="user.hasPendingFollowRequestFromYou">%fa:hourglass-half% %i18n:@request-pending%</template> | 			<template v-if="user.hasPendingFollowRequestFromYou && user.isLocked">%fa:hourglass-half% %i18n:@request-pending%</template> | ||||||
|  | 			<template v-else-if="user.hasPendingFollowRequestFromYou && !user.isLocked">%fa:hourglass-start% %i18n:@follow-processing%</template> | ||||||
| 			<template v-else-if="user.isFollowing">%fa:minus% %i18n:@following%</template> | 			<template v-else-if="user.isFollowing">%fa:minus% %i18n:@following%</template> | ||||||
| 			<template v-else-if="!user.isFollowing && user.isLocked">%fa:plus% %i18n:@follow-request%</template> | 			<template v-else-if="!user.isFollowing && user.isLocked">%fa:plus% %i18n:@follow-request%</template> | ||||||
| 			<template v-else-if="!user.isFollowing && !user.isLocked">%fa:plus% %i18n:@follow%</template> | 			<template v-else-if="!user.isFollowing && !user.isLocked">%fa:plus% %i18n:@follow%</template> | ||||||
| @@ -107,16 +108,14 @@ export default Vue.extend({ | |||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <style lang="stylus" scoped> | <style lang="stylus" scoped> | ||||||
| @import '~const.styl' | .syxhndwprovvuqhmyvveewmbqayniwkv | ||||||
|  |  | ||||||
| root(isDark) |  | ||||||
| 	padding 32px | 	padding 32px | ||||||
| 	max-width 500px | 	max-width 500px | ||||||
| 	margin 0 auto | 	margin 0 auto | ||||||
| 	text-align center | 	text-align center | ||||||
| 	color isDark ? #9baec8 : #868c8c | 	color var(--text) | ||||||
|  |  | ||||||
| 	$bg = isDark ? #282C37 : #fff | 	$bg = var(--face) | ||||||
|  |  | ||||||
| 	@media (max-width 400px) | 	@media (max-width 400px) | ||||||
| 		padding 16px | 		padding 16px | ||||||
| @@ -124,7 +123,6 @@ root(isDark) | |||||||
| 	> .signed-in-as | 	> .signed-in-as | ||||||
| 		margin-bottom 16px | 		margin-bottom 16px | ||||||
| 		font-size 14px | 		font-size 14px | ||||||
| 		color isDark ? #9baec8 : #9daab3 |  | ||||||
|  |  | ||||||
| 	> main | 	> main | ||||||
| 		margin-bottom 16px | 		margin-bottom 16px | ||||||
| @@ -173,29 +171,29 @@ root(isDark) | |||||||
| 		min-width 150px | 		min-width 150px | ||||||
| 		font-size 14px | 		font-size 14px | ||||||
| 		font-weight bold | 		font-weight bold | ||||||
| 		color $theme-color | 		color var(--primary) | ||||||
| 		background transparent | 		background transparent | ||||||
| 		outline none | 		outline none | ||||||
| 		border solid 1px $theme-color | 		border solid 1px var(--primary) | ||||||
| 		border-radius 36px | 		border-radius 36px | ||||||
|  |  | ||||||
| 		&:hover | 		&:hover | ||||||
| 			background rgba($theme-color, 0.1) | 			background var(--primaryAlpha01) | ||||||
|  |  | ||||||
| 		&:active | 		&:active | ||||||
| 			background rgba($theme-color, 0.2) | 			background var(--primaryAlpha02) | ||||||
|  |  | ||||||
| 		&.active | 		&.active | ||||||
| 			color $theme-color-foreground | 			color var(--primaryForeground) | ||||||
| 			background $theme-color | 			background var(--primary) | ||||||
|  |  | ||||||
| 			&:hover | 			&:hover | ||||||
| 				background lighten($theme-color, 10%) | 				background var(--primaryLighten10) | ||||||
| 				border-color lighten($theme-color, 10%) | 				border-color var(--primaryLighten10) | ||||||
|  |  | ||||||
| 			&:active | 			&:active | ||||||
| 				background darken($theme-color, 10%) | 				background var(--primaryDarken10) | ||||||
| 				border-color darken($theme-color, 10%) | 				border-color var(--primaryDarken10) | ||||||
|  |  | ||||||
| 		&.wait | 		&.wait | ||||||
| 			cursor wait !important | 			cursor wait !important | ||||||
| @@ -204,10 +202,4 @@ root(isDark) | |||||||
| 		* | 		* | ||||||
| 			pointer-events none | 			pointer-events none | ||||||
|  |  | ||||||
| .syxhndwprovvuqhmyvveewmbqayniwkv[data-darkmode] |  | ||||||
| 	root(true) |  | ||||||
|  |  | ||||||
| .syxhndwprovvuqhmyvveewmbqayniwkv:not([data-darkmode]) |  | ||||||
| 	root(false) |  | ||||||
|  |  | ||||||
| </style> | </style> | ||||||
|   | |||||||
| @@ -26,16 +26,8 @@ export default define({ | |||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <style lang="stylus" scoped> | <style lang="stylus" scoped> | ||||||
| @import '~const.styl' | .mkw-analog-clock | ||||||
|  |  | ||||||
| root(isDark) |  | ||||||
| 	.mkw-analog-clock--body | 	.mkw-analog-clock--body | ||||||
| 		padding 8px | 		padding 8px | ||||||
|  |  | ||||||
| .mkw-analog-clock[data-darkmode] |  | ||||||
| 	root(true) |  | ||||||
|  |  | ||||||
| .mkw-analog-clock:not([data-darkmode]) |  | ||||||
| 	root(false) |  | ||||||
|  |  | ||||||
| </style> | </style> | ||||||
|   | |||||||
| @@ -5,7 +5,6 @@ | |||||||
| 			:data-found="announcements && announcements.length != 0" | 			:data-found="announcements && announcements.length != 0" | ||||||
| 			:data-melt="props.design == 1" | 			:data-melt="props.design == 1" | ||||||
| 			:data-mobile="platform == 'mobile'" | 			:data-mobile="platform == 'mobile'" | ||||||
| 			:data-darkmode="$store.state.device.darkmode" |  | ||||||
| 		> | 		> | ||||||
| 			<div class="icon"> | 			<div class="icon"> | ||||||
| 				<svg height="32" version="1.1" viewBox="0 0 32 32" width="32"> | 				<svg height="32" version="1.1" viewBox="0 0 32 32" width="32"> | ||||||
| @@ -71,9 +70,9 @@ export default define({ | |||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <style lang="stylus" scoped> | <style lang="stylus" scoped> | ||||||
| root(isDark) | .anltbovirfeutcigvwgmgxipejaeozxi-body | ||||||
| 	padding 10px | 	padding 10px | ||||||
| 	background isDark ? #253a50 : #f3f9ff | 	background var(--announcementsBg) | ||||||
|  |  | ||||||
| 	&[data-melt] | 	&[data-melt] | ||||||
| 		background transparent | 		background transparent | ||||||
| @@ -130,14 +129,14 @@ root(isDark) | |||||||
| 		margin 0 | 		margin 0 | ||||||
| 		font-size 0.95em | 		font-size 0.95em | ||||||
| 		font-weight normal | 		font-weight normal | ||||||
| 		color isDark ? #539eff : #4078c0 | 		color var(--announcementsTitle) | ||||||
|  |  | ||||||
| 	> p | 	> p | ||||||
| 		display block | 		display block | ||||||
| 		z-index 1 | 		z-index 1 | ||||||
| 		margin 0 | 		margin 0 | ||||||
| 		font-size 0.7em | 		font-size 0.7em | ||||||
| 		color isDark ? #fff : #57616f | 		color var(--announcementsText) | ||||||
|  |  | ||||||
| 		&.fetching | 		&.fetching | ||||||
| 			text-align center | 			text-align center | ||||||
| @@ -150,10 +149,4 @@ root(isDark) | |||||||
| 		> p | 		> p | ||||||
| 			color #fff | 			color #fff | ||||||
|  |  | ||||||
| .anltbovirfeutcigvwgmgxipejaeozxi-body[data-darkmode] |  | ||||||
| 	root(true) |  | ||||||
|  |  | ||||||
| .anltbovirfeutcigvwgmgxipejaeozxi-body:not([data-darkmode]) |  | ||||||
| 	root(false) |  | ||||||
|  |  | ||||||
| </style> | </style> | ||||||
|   | |||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user