Compare commits
309 Commits
Author | SHA1 | Date | |
---|---|---|---|
91f1c3a10a | |||
8fc1e07136 | |||
a62e2b83ff | |||
e31a2f7e55 | |||
1598e996b1 | |||
4fb7ee760a | |||
37865cb381 | |||
ab8b882435 | |||
1b2996947e | |||
ea56d368e3 | |||
dbd3a750f5 | |||
f41818141f | |||
d2f576accd | |||
4e483856d4 | |||
2997f26e3c | |||
cdab596240 | |||
fca7a9da94 | |||
8ba178f795 | |||
d98c67e13c | |||
d129151fdf | |||
1b9c69f793 | |||
42dd092334 | |||
8dc9ec06f8 | |||
ae5da782e5 | |||
313b0cec65 | |||
12a51972ed | |||
a2f3b2966f | |||
0c2627f08b | |||
9535df12dd | |||
2400471a0d | |||
784da8c37b | |||
3778f9c521 | |||
e1cec85f1e | |||
ca9c087060 | |||
5b2d91baad | |||
08e099b88d | |||
4153b0db38 | |||
88701a21bb | |||
3ddc73ca94 | |||
693d793265 | |||
5d685233dd | |||
16575751d9 | |||
1f6295f437 | |||
6737fe2ead | |||
4e77939fca | |||
21f528c07d | |||
23f835fac0 | |||
f21343225c | |||
f13a59f7db | |||
0315b9274c | |||
da88043962 | |||
0352bf0cc2 | |||
baa71070a8 | |||
2713064f27 | |||
f6387ac115 | |||
d704aca035 | |||
2b54b4ac06 | |||
7410f2f4c0 | |||
99c3c1258a | |||
e51184931d | |||
3bc9a40b48 | |||
9f49ca8fdb | |||
550d1547b4 | |||
ca0b56ee57 | |||
ef1d854f2c | |||
a5023271ef | |||
c3747db670 | |||
fe1e60a28c | |||
f91d2e8c8d | |||
dccc2c60e3 | |||
933e25804c | |||
0b503661af | |||
58082431ff | |||
2536bfb5f5 | |||
6428066552 | |||
4bf3827b73 | |||
3cad494404 | |||
ef0793311f | |||
6f3e341e89 | |||
2fea3be7c0 | |||
82059d4fd9 | |||
07ddeae2f1 | |||
f2279758b2 | |||
1ed189a518 | |||
137741d307 | |||
d702f6e090 | |||
f33701233c | |||
70003269e5 | |||
61896d2386 | |||
52d640c5a7 | |||
c65f5761e1 | |||
3016ac4805 | |||
28a47cd331 | |||
6ecb88b0d1 | |||
8df1278c8e | |||
52bec430d4 | |||
da4cec8767 | |||
ad0087d7dd | |||
9630860035 | |||
75e4c8d74d | |||
1a5ee81e7e | |||
3476be16ab | |||
c42f61a0f4 | |||
b42a9e1c4e | |||
4495525705 | |||
a603602f32 | |||
67b28f9b6e | |||
fd947407af | |||
30444e5f1a | |||
f0d818de24 | |||
3fb98e808f | |||
2c9bacfcea | |||
ae0284b1b1 | |||
166c4ebda0 | |||
319eed029b | |||
ec5aa10167 | |||
a542765cf8 | |||
fd3f8d43db | |||
4f4496078a | |||
8f4f5b4ce0 | |||
bdc6718ae5 | |||
09d1f1c20d | |||
0efb7af17b | |||
a45a78b94f | |||
6337c26cf0 | |||
208dec25d9 | |||
7d65a0c3d5 | |||
bb925e5de3 | |||
c9de5b65d4 | |||
9bc3fcf74f | |||
19d979c330 | |||
bb7b335491 | |||
be5a0b4794 | |||
48eea03386 | |||
566317dc83 | |||
d4334645c2 | |||
d60c3c4ee3 | |||
452514f7fe | |||
58abb0ce8f | |||
000d9cc1ce | |||
8cc017354a | |||
60269d15e8 | |||
7caa083612 | |||
68e1b00eb1 | |||
1d904c756a | |||
0a1db1f595 | |||
e30e8267dd | |||
288a881817 | |||
f593790872 | |||
1044ad8589 | |||
6e24015e68 | |||
b9a2c449ff | |||
7c390cbf7b | |||
a657d1c774 | |||
f3936a79aa | |||
78b560d89a | |||
2fc6313380 | |||
c2b882a5d7 | |||
667b18fe24 | |||
60c0dac5f2 | |||
79f3e60dac | |||
c4e04d6bf2 | |||
49f8219e54 | |||
abd873e0a8 | |||
0e45d0d47f | |||
043b66f5da | |||
5d6e1fc391 | |||
fe292e77de | |||
c996b5d0c8 | |||
7beb592f0c | |||
b3b11acd96 | |||
3bcdfbbd00 | |||
fdad5d149f | |||
2e712a9212 | |||
86c8e634bb | |||
197a9306c4 | |||
2e502a6b61 | |||
aa8a40e950 | |||
2f45ac3712 | |||
8ecf3db608 | |||
f59c68022f | |||
7aac2c4e29 | |||
0481de6629 | |||
f59d0a75e4 | |||
22f4b3cc7b | |||
a4283c415a | |||
c0fbcee38a | |||
335200c31e | |||
df71c90f9f | |||
4220bdc963 | |||
97f3b1e46f | |||
3a9dc358f8 | |||
2a3ab46a3d | |||
200a01f65f | |||
e68936911d | |||
634ffeec54 | |||
8486cb785d | |||
a9eda4e6e2 | |||
f918f9b307 | |||
d404d02d2d | |||
61f7a3974f | |||
cad8e4dea2 | |||
ef79903811 | |||
c3cd0451ad | |||
773fe28fcb | |||
69e2576387 | |||
908a5a1bb4 | |||
ffbd9ffc75 | |||
96223dd5e3 | |||
3231f12b93 | |||
1408f39d9a | |||
4ba06541aa | |||
5c78ed645a | |||
33e19447aa | |||
b52d995719 | |||
db5b90c093 | |||
39bc75a7f9 | |||
3492067ecf | |||
e342a8da05 | |||
671d71dd47 | |||
2f18d2ed8f | |||
f6e8165db0 | |||
eab3b22772 | |||
7664aa5a8c | |||
a366392cbe | |||
c8c1bc09f9 | |||
11bb1608cf | |||
b1d77775aa | |||
bc3f5e0d78 | |||
53ea709697 | |||
b7adbbb9bf | |||
31aaf559ac | |||
160185b108 | |||
848ff4440b | |||
74291b2cae | |||
ae6c4e0c5f | |||
ecb1840e27 | |||
42eb82a859 | |||
89a22908ce | |||
bc3a94aa57 | |||
77fe579d9b | |||
e8c7803a2f | |||
1abaef624c | |||
72cf2344a9 | |||
0462512e62 | |||
1d6b2bd969 | |||
5df90fdc4a | |||
607a5326d9 | |||
2cbd35acc4 | |||
9a0224ee21 | |||
2beedc5978 | |||
6d53e64798 | |||
3478cdea08 | |||
b360f2ed45 | |||
7b0c4c29b4 | |||
03f5d7575c | |||
e922d8904c | |||
45b55a8c98 | |||
8973b76bda | |||
41cf856e26 | |||
b7aeb10304 | |||
b8d9c1aa45 | |||
d7dbe503b6 | |||
c625dd074a | |||
f8a977f1c0 | |||
c35e760fd3 | |||
bc34ac82cf | |||
e05e97561a | |||
f9d21fd34a | |||
86aef5f3e0 | |||
e6bc7922ac | |||
b2f40b7d3e | |||
3878793405 | |||
33c7aef220 | |||
e927f7a4ec | |||
f409faea2c | |||
77da98cd39 | |||
471afcbd57 | |||
72809f9d78 | |||
743fb45c3c | |||
93d6b71a31 | |||
9b10e93fba | |||
0740837b6a | |||
ff49eacee4 | |||
fbc6b267ff | |||
10cae8894e | |||
9438dc560d | |||
003ef65b59 | |||
978fb7e63a | |||
6203577696 | |||
f2b61f6a7e | |||
6f4aa69723 | |||
b308e1bb2b | |||
ab3dad2d84 | |||
0af103f399 | |||
873608a7de | |||
b04ad167da | |||
151476ae8a | |||
2239eddf88 | |||
94ea21d482 | |||
6a39f92431 | |||
7b2efa35c7 | |||
c41ea84568 | |||
0e8262e623 | |||
4d97946943 | |||
96d48b5519 | |||
4cc54d081e | |||
aab5a2ffbd | |||
c8f165b4ad |
@ -1,69 +0,0 @@
|
||||
<img src="https://github.com/syuilo/misskey/blob/b3f42e62af698a67c2250533c437569559f1fdf9/src/himasaku/resources/himasaku.png?raw=true" align="right" width="320px"/>
|
||||
|
||||
[](https://misskey.xyz/)
|
||||
================================================================
|
||||
|
||||
[![][travis-badge]][travis-link]
|
||||
[![][dependencies-badge]][dependencies-link]
|
||||
[](http://makeapullrequest.com) [](https://greenkeeper.io/)
|
||||
|
||||
[Misskey](https://misskey.xyz) is an **advanced**, **redefined**, and ultimately **sophisticated** microblogging platform.
|
||||
|
||||
<a href="https://www.patreon.com/syuilo"><img src="https://c5.patreon.com/external/logo/become_a_patron_button@2x.png" alt="Become a Patron!" width="160" /></a>
|
||||
|
||||

|
||||
|
||||
:sparkles: Features
|
||||
----------------------------------------------------------------
|
||||
* Rich text contents
|
||||
* Reactions
|
||||
* User lists
|
||||
* Customizable column view (called MisskeyDeck)
|
||||
* and widgets!
|
||||
* Private messages
|
||||
* ActivityPub support
|
||||
|
||||
and more! You can see it with your own eyes at [misskey.xyz](https://misskey.xyz).
|
||||
|
||||
:package: Create your instance
|
||||
----------------------------------------------------------------
|
||||
If you want to run your own instance of Misskey,
|
||||
please see [Setup and installation guide](./docs/setup.en.md).
|
||||
|
||||
:wrench: Contribute
|
||||
----------------------------------------------------------------
|
||||
**[PR](https://github.com/syuilo/misskey/pulls)s welcome!**
|
||||
|
||||
If you want to...
|
||||
* i18n ... please see [Translation guide](./docs/translate.en.md).
|
||||
* l10n ... please visit https://crowdin.com/project/misskey
|
||||
|
||||
:heart: Backers & Sponsors
|
||||
----------------------------------------------------------------
|
||||
<!-- __PATREON__ -->
|
||||
|
||||
:four_leaf_clover: Copyright
|
||||
----------------------------------------------------------------
|
||||
> Copyright (c) 2014-2018 syuilo
|
||||
|
||||
Misskey is an open-source software licensed under the [GNU AGPLv3](LICENSE).
|
||||
|
||||
[![][agpl-3.0-badge]][AGPL-3.0]
|
||||
|
||||
[agpl-3.0]: https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
[agpl-3.0-badge]: https://img.shields.io/badge/license-AGPL--3.0-444444.svg?style=flat-square
|
||||
[travis-link]: https://travis-ci.org/syuilo/misskey
|
||||
[travis-badge]: http://img.shields.io/travis/syuilo/misskey/master.svg?style=flat-square
|
||||
[dependencies-link]: https://david-dm.org/syuilo/misskey
|
||||
[dependencies-badge]: https://img.shields.io/david/syuilo/misskey.svg?style=flat-square
|
||||
|
||||
[backer-url]: #backers
|
||||
[backer-badge]: https://opencollective.com/misskey/backers/badge.svg
|
||||
[backers-image]: https://opencollective.com/misskey/backers.svg
|
||||
[sponsor-url]: #sponsors
|
||||
[sponsor-badge]: https://opencollective.com/misskey/sponsors/badge.svg
|
||||
[sponsors-image]: https://opencollective.com/misskey/sponsors.svg
|
||||
[support-url]: https://opencollective.com/misskey#support
|
||||
|
||||
[syuilo-link]: https://syuilo.com
|
||||
[syuilo-icon]: https://avatars2.githubusercontent.com/u/4439005?v=3&s=70
|
86
.autogen/autogen.sh
Executable file
86
.autogen/autogen.sh
Executable file
@ -0,0 +1,86 @@
|
||||
#!/usr/bin/env bash
|
||||
# BEARER_TOKEN=
|
||||
# CAMPAIGN_ID=
|
||||
# GITHUB_TOKEN=
|
||||
# HEAD='acid-chicken:patch-autogen'
|
||||
# REPO='syuilo/misskey'
|
||||
test "$(curl -LSs -w '\n' -- "https://api.github.com/repos/$REPO/pulls?access_token=$GITHUB_TOKEN" | jq -r '.[].head.label' | grep $HEAD)" && exit 1
|
||||
cd "$(dirname $0)/.." && \
|
||||
touch null.cache && \
|
||||
rm *.cache && \
|
||||
git checkout master && \
|
||||
git pull origin master && \
|
||||
git pull upstream master && \
|
||||
git stash && \
|
||||
git rebase -f upstream/master && \
|
||||
git branch patch-autogen && \
|
||||
git checkout patch-autogen && \
|
||||
git reset --hard HEAD || \
|
||||
exit 1
|
||||
touch patreon.md.cache && \
|
||||
rm patreon.md.cache && \
|
||||
echo '<!-- PATREON_START -->' > patreon.md.cache && \
|
||||
URL="https://www.patreon.com/api/oauth2/v2/campaigns/$CAMPAIGN_ID/members?include=currently_entitled_tiers,user&fields%5Btier%5D=title&fields%5Buser%5D=full_name,thumb_url,url,hide_pledges"
|
||||
while :
|
||||
do
|
||||
touch patreon.raw.cache && \
|
||||
rm patreon.raw.cache && \
|
||||
curl -LSs -w '\n' -H "Authorization: Bearer $BEARER_TOKEN" -- $URL > patreon.raw.cache && \
|
||||
touch patreon.cache && \
|
||||
rm patreon.cache && \
|
||||
cat patreon.raw.cache | \
|
||||
jq -r '(.data|map(select(.relationships.currently_entitled_tiers.data[]))|map(.relationships.user.data.id))as$data|.included|map(select(.attributes.hide_pledges==false))|map(select(.id as$id|$data|contains([$id])))|map(.attributes|[.full_name,.thumb_url,.url]|@tsv)|.[]|@text' >> patreon.cache && \
|
||||
echo '<table><tr>' >> patreon.md.cache && \
|
||||
cat patreon.cache | \
|
||||
awk -F'\t' '{print $2,$1}' | \
|
||||
sed -e 's/ /\\" alt=\\"/' | \
|
||||
xargs -I% echo '<td><img src="%"></td>' >> patreon.md.cache && \
|
||||
echo '</tr><tr>' >> patreon.md.cache && \
|
||||
cat patreon.cache | \
|
||||
awk -F'\t' '{print $3,$1}' | \
|
||||
sed -e 's/ /\\">/' | \
|
||||
xargs -I% echo '<td><a href="%</a></td>' >> patreon.md.cache && \
|
||||
echo '</tr></table>' >> patreon.md.cache || \
|
||||
exit 1
|
||||
NEW_URL="$(cat patreon.raw.cache | jq -r '.links.next')"
|
||||
test "$NEW_URL" = 'null' && \
|
||||
break || \
|
||||
URL="$NEW_URL"
|
||||
done
|
||||
IGNORE= && \
|
||||
echo -e "\n**Last updated:** $(date -uR | sed 's/\+0000/UTC/')\n<!-- PATREON_END -->" >> patreon.md.cache && \
|
||||
touch README.md && \
|
||||
touch .autogen/README.md && \
|
||||
rm .autogen/README.md && \
|
||||
mv README.md .autogen/README.md && \
|
||||
cat .autogen/README.md | while IFS= read LINE;
|
||||
do
|
||||
if [[ -z "$IGNORE" ]]
|
||||
then
|
||||
if [[ "$LINE" = '<!-- PATREON_START -->' ]]
|
||||
then
|
||||
IGNORE='PATREON_INSIDE'
|
||||
else
|
||||
echo "$LINE" >> README.md
|
||||
fi
|
||||
else
|
||||
if [[ "$LINE" = '<!-- PATREON_END -->' ]]
|
||||
then
|
||||
IGNORE=
|
||||
cat patreon.md.cache >> README.md
|
||||
fi
|
||||
fi
|
||||
done
|
||||
cat patreon.md.cache
|
||||
touch null.cache && \
|
||||
rm *.cache && \
|
||||
diff .autogen/README.md README.md > diff.cache
|
||||
cat diff.cache && \
|
||||
test 4 -lt $(cat diff.cache | wc -l) && \
|
||||
git add README.md && \
|
||||
git commit -m 'Update README.md [AUTOGEN]' && \
|
||||
git push -f origin patch-autogen && \
|
||||
curl -LSs -w '\n' -X POST -d '{"title":"[AUTOMATED] Update README.md","body":"*This pull request was created by a tool.*","head":"'$HEAD'","base":"master"}' -- "https://api.github.com/repos/$REPO/pulls?access_token=$GITHUB_TOKEN"
|
||||
git stash
|
||||
git checkout master
|
||||
git branch -D patch-autogen
|
@ -5,6 +5,15 @@ ChangeLog
|
||||
|
||||
This document describes breaking changes only.
|
||||
|
||||
7.0.0
|
||||
-----
|
||||
|
||||
### Migration
|
||||
|
||||
起動する前に、`node cli/migration/7.0.0`してください。
|
||||
|
||||
Please run `node cli/migration/7.0.0` before launch.
|
||||
|
||||
6.0.0
|
||||
-----
|
||||
|
||||
|
89
README.md
89
README.md
@ -7,9 +7,12 @@
|
||||
[![][dependencies-badge]][dependencies-link]
|
||||
[](http://makeapullrequest.com) [](https://greenkeeper.io/)
|
||||
|
||||
**Microblogging. Redefined.**
|
||||
Sophisticated microblogging platform, evolving forever.
|
||||
|
||||
[Misskey](https://misskey.xyz) is an **advanced**, **redefined**, and ultimately **sophisticated** microblogging platform.
|
||||
[Misskey](https://misskey.xyz) is a decentralized microblogging platform born on Earth.
|
||||
Since it exists within the Fediverse (a universe where various social media platforms are organized),
|
||||
it is mutually linked with other social media platforms.
|
||||
Why don't you take a short break from the hustle and bustle of the city, and dive into a new Internet?
|
||||
|
||||
<a href="https://www.patreon.com/syuilo"><img src="https://c5.patreon.com/external/logo/become_a_patron_button@2x.png" alt="Become a Patron!" width="160" /></a>
|
||||
|
||||
@ -27,7 +30,7 @@
|
||||
|
||||
and more! You can see it with your own eyes at [misskey.xyz](https://misskey.xyz).
|
||||
|
||||
:package: Create your instance
|
||||
:package: Create your own instance
|
||||
----------------------------------------------------------------
|
||||
If you want to run your own instance of Misskey,
|
||||
please see [Setup and installation guide](./docs/setup.en.md).
|
||||
@ -36,40 +39,58 @@ please see [Setup and installation guide](./docs/setup.en.md).
|
||||
----------------------------------------------------------------
|
||||
**[PR](https://github.com/syuilo/misskey/pulls)s welcome!**
|
||||
|
||||
If you want to...
|
||||
* i18n ... please see [Translation guide](./docs/translate.en.md).
|
||||
* l10n ... please visit https://crowdin.com/project/misskey
|
||||
### i18n
|
||||
|
||||
Please see [Translation guide](./docs/translate.en.md).
|
||||
|
||||
### l10n
|
||||
|
||||
Misskey is using Crowdin for l10n.
|
||||
|
||||
[](https://crowdin.com/project/misskey)
|
||||
|
||||
:heart: Backers & Sponsors
|
||||
----------------------------------------------------------------
|
||||
<table>
|
||||
<tr>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/619786/32cf01444db24e578cd1982c197f6fc6/1?token-time=2145916800&token-hash=tB1e_r8RlZ5sFL0KV_e8dugapxatNBRK1Z3h67TO1g8%3D"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/12378075/0156f769e20f412594fa6b87d85fe228/1?token-time=2145916800&token-hash=IsIJRUXszzoD6-7pDnRY8I05T9nSznc4GTaxj7C9SwU%3D"></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"></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"></td>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/12959468/c249e15aebec4424b5c0f427173671b6/1?token-time=2145916800&token-hash=lubpCEdxAkxPlpR2O6bvZ7BIh8Q4nGf-U_mE1qpjVAQ%3D"></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"></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"></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"></td>
|
||||
<td><img src="https://c8.patreon.com/2/100/12718187"></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"></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"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="https://www.patreon.com/mastodon">Gargron</a></td>
|
||||
<td><a href="https://www.patreon.com/user/creators?u=12378075">39ff</a></td>
|
||||
<td><a href="https://www.patreon.com/dansup">dansup</a></td>
|
||||
<td><a href="https://www.patreon.com/user/creators?u=12531784">Takashi Shibuya</a></td>
|
||||
<td><a href="https://www.patreon.com/fujishan">fujishan</a></td>
|
||||
<td><a href="https://www.patreon.com/user?u=12913507">Melilot</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=12731202">negao</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=12931605">Reiju</a></td>
|
||||
<td><a href="https://www.patreon.com/gutfuckllc">gutfuckllc</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<!-- PATREON_START -->
|
||||
<table><tr>
|
||||
<td><img src="https://c10.patreonusercontent.com/3/eyJoIjoxMDAsInciOjEwMH0%3D/patreon-media/p/user/12378075/0156f769e20f412594fa6b87d85fe228/1?token-time=2145916800&token-hash=IsIJRUXszzoD6-7pDnRY8I05T9nSznc4GTaxj7C9SwU%3D" alt="39ff"></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/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/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://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>
|
||||
</tr><tr>
|
||||
<td><a href="https://www.patreon.com/user?u=12378075">39ff</a></td>
|
||||
<td><a href="https://www.patreon.com/user?u=12731202">negao</a></td>
|
||||
<td><a href="https://www.patreon.com/user?u=13099460">ne_moni</a></td>
|
||||
<td><a href="https://www.patreon.com/user?u=12913507">Melilot</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/user?u=12718187">Peter G.</a></td>
|
||||
<td><a href="https://www.patreon.com/user?u=13039004">nemu</a></td>
|
||||
</tr></table>
|
||||
<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/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/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/4950409/28e7d016209243759d9316be2e21381d/2?token-time=2145916800&token-hash=LuEaDkchH3GQWUcTOhBQ8xfKQYF0s5FjlZRd7Yduia8%3D" alt="mikan54951"></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/12959468/c249e15aebec4424b5c0f427173671b6/1?token-time=2145916800&token-hash=lubpCEdxAkxPlpR2O6bvZ7BIh8Q4nGf-U_mE1qpjVAQ%3D" alt="fujishan"></td>
|
||||
</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=12931605">Reiju</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/user?u=4950409">mikan54951</a></td>
|
||||
<td><a href="https://www.patreon.com/user?u=12531784">Takashi Shibuya</a></td>
|
||||
<td><a href="https://www.patreon.com/fujishan">fujishan</a></td>
|
||||
</tr></table>
|
||||
|
||||
**Last updated:** Wed, 22 Aug 2018 05:25:06 UTC
|
||||
<!-- PATREON_END -->
|
||||
|
||||
:four_leaf_clover: Copyright
|
||||
----------------------------------------------------------------
|
||||
|
@ -1,101 +0,0 @@
|
||||
const chalk = require('chalk');
|
||||
const log = require('single-line-log').stdout;
|
||||
const sequential = require('promise-sequential');
|
||||
const { default: DriveFile, DriveFileChunk } = require('../built/models/drive-file');
|
||||
const { default: DriveFileThumbnail, DriveFileThumbnailChunk } = require('../built/models/drive-file-thumbnail');
|
||||
const { default: User } = require('../built/models/user');
|
||||
|
||||
const q = {
|
||||
'metadata._user.host': {
|
||||
$ne: null
|
||||
},
|
||||
'metadata.withoutChunks': false
|
||||
};
|
||||
|
||||
async function main() {
|
||||
const promiseGens = [];
|
||||
|
||||
const count = await DriveFile.count(q);
|
||||
|
||||
let prev;
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
promiseGens.push(() => {
|
||||
const promise = new Promise(async (res, rej) => {
|
||||
const file = await DriveFile.findOne(prev ? Object.assign({
|
||||
_id: { $lt: prev._id }
|
||||
}, q) : q, {
|
||||
sort: {
|
||||
_id: -1
|
||||
}
|
||||
});
|
||||
|
||||
prev = file;
|
||||
|
||||
function skip() {
|
||||
res([i, file, false]);
|
||||
}
|
||||
|
||||
if (file == null) return skip();
|
||||
|
||||
log(chalk`{gray ${i}} scanning {bold ${file._id}} ${file.filename} ...`);
|
||||
|
||||
const attachingUsersCount = await User.count({
|
||||
$or: [{
|
||||
avatarId: file._id
|
||||
}, {
|
||||
bannerId: file._id
|
||||
}]
|
||||
}, { limit: 1 });
|
||||
if (attachingUsersCount !== 0) return skip();
|
||||
|
||||
Promise.all([
|
||||
// チャンクをすべて削除
|
||||
DriveFileChunk.remove({
|
||||
files_id: file._id
|
||||
}),
|
||||
|
||||
DriveFile.update({ _id: file._id }, {
|
||||
$set: {
|
||||
'metadata.withoutChunks': true
|
||||
}
|
||||
})
|
||||
]).then(async () => {
|
||||
res([i, file, true]);
|
||||
|
||||
//#region サムネイルもあれば削除
|
||||
const thumbnail = await DriveFileThumbnail.findOne({
|
||||
'metadata.originalId': file._id
|
||||
});
|
||||
|
||||
if (thumbnail) {
|
||||
DriveFileThumbnailChunk.remove({
|
||||
files_id: thumbnail._id
|
||||
});
|
||||
|
||||
DriveFileThumbnail.remove({ _id: thumbnail._id });
|
||||
}
|
||||
//#endregion
|
||||
});
|
||||
});
|
||||
|
||||
promise.then(([i, file, deleted]) => {
|
||||
if (deleted) {
|
||||
log(chalk`{gray ${i}} {red deleted: {bold ${file._id}} ${file.filename}}`);
|
||||
} else {
|
||||
log(chalk`{gray ${i}} {green skipped: {bold ${file._id}} ${file.filename}}`);
|
||||
}
|
||||
log.clear();
|
||||
console.log();
|
||||
});
|
||||
|
||||
return promise;
|
||||
});
|
||||
}
|
||||
|
||||
return await sequential(promiseGens);
|
||||
}
|
||||
|
||||
main().then(() => {
|
||||
console.log('ALL DONE');
|
||||
}).catch(console.error);
|
@ -1,80 +0,0 @@
|
||||
const chalk = require('chalk');
|
||||
const log = require('single-line-log').stdout;
|
||||
const sequential = require('promise-sequential');
|
||||
const { default: DriveFile, deleteDriveFile } = require('../built/models/drive-file');
|
||||
const { default: Note } = require('../built/models/note');
|
||||
const { default: MessagingMessage } = require('../built/models/messaging-message');
|
||||
const { default: User } = require('../built/models/user');
|
||||
|
||||
async function main() {
|
||||
const promiseGens = [];
|
||||
|
||||
const count = await DriveFile.count({});
|
||||
|
||||
let prev;
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
promiseGens.push(() => {
|
||||
const promise = new Promise(async (res, rej) => {
|
||||
const file = await DriveFile.findOne(prev ? {
|
||||
_id: { $lt: prev._id }
|
||||
} : {}, {
|
||||
sort: {
|
||||
_id: -1
|
||||
}
|
||||
});
|
||||
|
||||
prev = file;
|
||||
|
||||
function skip() {
|
||||
res([i, file, false]);
|
||||
}
|
||||
|
||||
if (file == null) return skip();
|
||||
|
||||
log(chalk`{gray ${i}} scanning {bold ${file._id}} ${file.filename} ...`);
|
||||
|
||||
const attachingUsersCount = await User.count({
|
||||
$or: [{
|
||||
avatarId: file._id
|
||||
}, {
|
||||
bannerId: file._id
|
||||
}]
|
||||
}, { limit: 1 });
|
||||
if (attachingUsersCount !== 0) return skip();
|
||||
|
||||
const attachingNotesCount = await Note.count({
|
||||
mediaIds: file._id
|
||||
}, { limit: 1 });
|
||||
if (attachingNotesCount !== 0) return skip();
|
||||
|
||||
const attachingMessagesCount = await MessagingMessage.count({
|
||||
fileId: file._id
|
||||
}, { limit: 1 });
|
||||
if (attachingMessagesCount !== 0) return skip();
|
||||
|
||||
deleteDriveFile(file).then(() => {
|
||||
res([i, file, true]);
|
||||
}).catch(rej);
|
||||
});
|
||||
|
||||
promise.then(([i, file, deleted]) => {
|
||||
if (deleted) {
|
||||
log(chalk`{gray ${i}} {red deleted: {bold ${file._id}} ${file.filename}}`);
|
||||
} else {
|
||||
log(chalk`{gray ${i}} {green skipped: {bold ${file._id}} ${file.filename}}`);
|
||||
}
|
||||
log.clear();
|
||||
console.log();
|
||||
});
|
||||
|
||||
return promise;
|
||||
});
|
||||
}
|
||||
|
||||
return await sequential(promiseGens);
|
||||
}
|
||||
|
||||
main().then(() => {
|
||||
console.log('done');
|
||||
}).catch(console.error);
|
134
cli/migration/7.0.0.js
Normal file
134
cli/migration/7.0.0.js
Normal file
@ -0,0 +1,134 @@
|
||||
const { default: Stats } = require('../../built/models/stats');
|
||||
const { default: User } = require('../../built/models/user');
|
||||
const { default: Note } = require('../../built/models/note');
|
||||
const { default: DriveFile } = require('../../built/models/drive-file');
|
||||
|
||||
const now = new Date();
|
||||
const y = now.getFullYear();
|
||||
const m = now.getMonth();
|
||||
const d = now.getDate();
|
||||
const today = new Date(y, m, d);
|
||||
|
||||
async function main() {
|
||||
const localUsersCount = await User.count({
|
||||
host: null
|
||||
});
|
||||
|
||||
const remoteUsersCount = await User.count({
|
||||
host: { $ne: null }
|
||||
});
|
||||
|
||||
const localNotesCount = await Note.count({
|
||||
'_user.host': null
|
||||
});
|
||||
|
||||
const remoteNotesCount = await Note.count({
|
||||
'_user.host': { $ne: null }
|
||||
});
|
||||
|
||||
const localDriveFilesCount = await DriveFile.count({
|
||||
'metadata._user.host': null
|
||||
});
|
||||
|
||||
const remoteDriveFilesCount = await DriveFile.count({
|
||||
'metadata._user.host': { $ne: null }
|
||||
});
|
||||
|
||||
const localDriveFilesSize = await DriveFile
|
||||
.aggregate([{
|
||||
$match: {
|
||||
'metadata._user.host': null,
|
||||
'metadata.deletedAt': { $exists: false }
|
||||
}
|
||||
}, {
|
||||
$project: {
|
||||
length: true
|
||||
}
|
||||
}, {
|
||||
$group: {
|
||||
_id: null,
|
||||
usage: { $sum: '$length' }
|
||||
}
|
||||
}])
|
||||
.then(aggregates => {
|
||||
if (aggregates.length > 0) {
|
||||
return aggregates[0].usage;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
|
||||
const remoteDriveFilesSize = await DriveFile
|
||||
.aggregate([{
|
||||
$match: {
|
||||
'metadata._user.host': { $ne: null },
|
||||
'metadata.deletedAt': { $exists: false }
|
||||
}
|
||||
}, {
|
||||
$project: {
|
||||
length: true
|
||||
}
|
||||
}, {
|
||||
$group: {
|
||||
_id: null,
|
||||
usage: { $sum: '$length' }
|
||||
}
|
||||
}])
|
||||
.then(aggregates => {
|
||||
if (aggregates.length > 0) {
|
||||
return aggregates[0].usage;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
|
||||
await Stats.insert({
|
||||
date: today,
|
||||
users: {
|
||||
local: {
|
||||
total: localUsersCount,
|
||||
diff: 0
|
||||
},
|
||||
remote: {
|
||||
total: remoteUsersCount,
|
||||
diff: 0
|
||||
}
|
||||
},
|
||||
notes: {
|
||||
local: {
|
||||
total: localNotesCount,
|
||||
diff: 0,
|
||||
diffs: {
|
||||
normal: 0,
|
||||
reply: 0,
|
||||
renote: 0
|
||||
}
|
||||
},
|
||||
remote: {
|
||||
total: remoteNotesCount,
|
||||
diff: 0,
|
||||
diffs: {
|
||||
normal: 0,
|
||||
reply: 0,
|
||||
renote: 0
|
||||
}
|
||||
}
|
||||
},
|
||||
drive: {
|
||||
local: {
|
||||
totalCount: localDriveFilesCount,
|
||||
totalSize: localDriveFilesSize,
|
||||
diffCount: 0,
|
||||
diffSize: 0
|
||||
},
|
||||
remote: {
|
||||
totalCount: remoteDriveFilesCount,
|
||||
totalSize: remoteDriveFilesSize,
|
||||
diffCount: 0,
|
||||
diffSize: 0
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
console.log('done');
|
||||
}
|
||||
|
||||
main();
|
144
cli/migration/8.0.0.js
Normal file
144
cli/migration/8.0.0.js
Normal file
@ -0,0 +1,144 @@
|
||||
const { default: Stats } = require('../../built/models/stats');
|
||||
const { default: User } = require('../../built/models/user');
|
||||
const { default: Note } = require('../../built/models/note');
|
||||
const { default: DriveFile } = require('../../built/models/drive-file');
|
||||
|
||||
const now = new Date();
|
||||
const y = now.getFullYear();
|
||||
const m = now.getMonth();
|
||||
const d = now.getDate();
|
||||
const h = now.getHours();
|
||||
const date = new Date(y, m, d, h);
|
||||
|
||||
async function main() {
|
||||
await Stats.update({}, {
|
||||
$set: {
|
||||
span: 'day'
|
||||
}
|
||||
}, {
|
||||
multi: true
|
||||
});
|
||||
|
||||
const localUsersCount = await User.count({
|
||||
host: null
|
||||
});
|
||||
|
||||
const remoteUsersCount = await User.count({
|
||||
host: { $ne: null }
|
||||
});
|
||||
|
||||
const localNotesCount = await Note.count({
|
||||
'_user.host': null
|
||||
});
|
||||
|
||||
const remoteNotesCount = await Note.count({
|
||||
'_user.host': { $ne: null }
|
||||
});
|
||||
|
||||
const localDriveFilesCount = await DriveFile.count({
|
||||
'metadata._user.host': null
|
||||
});
|
||||
|
||||
const remoteDriveFilesCount = await DriveFile.count({
|
||||
'metadata._user.host': { $ne: null }
|
||||
});
|
||||
|
||||
const localDriveFilesSize = await DriveFile
|
||||
.aggregate([{
|
||||
$match: {
|
||||
'metadata._user.host': null,
|
||||
'metadata.deletedAt': { $exists: false }
|
||||
}
|
||||
}, {
|
||||
$project: {
|
||||
length: true
|
||||
}
|
||||
}, {
|
||||
$group: {
|
||||
_id: null,
|
||||
usage: { $sum: '$length' }
|
||||
}
|
||||
}])
|
||||
.then(aggregates => {
|
||||
if (aggregates.length > 0) {
|
||||
return aggregates[0].usage;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
|
||||
const remoteDriveFilesSize = await DriveFile
|
||||
.aggregate([{
|
||||
$match: {
|
||||
'metadata._user.host': { $ne: null },
|
||||
'metadata.deletedAt': { $exists: false }
|
||||
}
|
||||
}, {
|
||||
$project: {
|
||||
length: true
|
||||
}
|
||||
}, {
|
||||
$group: {
|
||||
_id: null,
|
||||
usage: { $sum: '$length' }
|
||||
}
|
||||
}])
|
||||
.then(aggregates => {
|
||||
if (aggregates.length > 0) {
|
||||
return aggregates[0].usage;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
|
||||
await Stats.insert({
|
||||
date: date,
|
||||
span: 'hour',
|
||||
users: {
|
||||
local: {
|
||||
total: localUsersCount,
|
||||
diff: 0
|
||||
},
|
||||
remote: {
|
||||
total: remoteUsersCount,
|
||||
diff: 0
|
||||
}
|
||||
},
|
||||
notes: {
|
||||
local: {
|
||||
total: localNotesCount,
|
||||
diff: 0,
|
||||
diffs: {
|
||||
normal: 0,
|
||||
reply: 0,
|
||||
renote: 0
|
||||
}
|
||||
},
|
||||
remote: {
|
||||
total: remoteNotesCount,
|
||||
diff: 0,
|
||||
diffs: {
|
||||
normal: 0,
|
||||
reply: 0,
|
||||
renote: 0
|
||||
}
|
||||
}
|
||||
},
|
||||
drive: {
|
||||
local: {
|
||||
totalCount: localDriveFilesCount,
|
||||
totalSize: localDriveFilesSize,
|
||||
diffCount: 0,
|
||||
diffSize: 0
|
||||
},
|
||||
remote: {
|
||||
totalCount: remoteDriveFilesCount,
|
||||
totalSize: remoteDriveFilesSize,
|
||||
diffCount: 0,
|
||||
diffSize: 0
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
console.log('done');
|
||||
}
|
||||
|
||||
main();
|
@ -1,3 +1,3 @@
|
||||
files:
|
||||
- source: /locales/ja.yml
|
||||
translation: /locales/%two_letters_code%.yml
|
||||
- source: /locales/ja-JP.yml
|
||||
translation: /locales/%locale%.yml
|
||||
|
@ -33,14 +33,3 @@ node cli/suspend @syuilo@misskey.xyz
|
||||
``` shell
|
||||
node cli/reset-password (User-ID or Username)
|
||||
```
|
||||
|
||||
## Clean up cached remote files
|
||||
``` shell
|
||||
node cli/clean-cached-remote-files
|
||||
```
|
||||
|
||||
## Clean up unused drive files
|
||||
``` shell
|
||||
node cli/clean-unused-drive-files
|
||||
```
|
||||
> We recommend that you announce a user that unused drive files will be deleted before performing this operation, as it may delete the user's important files.
|
||||
|
@ -33,14 +33,3 @@ node cli/suspend @syuilo@misskey.xyz
|
||||
``` shell
|
||||
node cli/reset-password (ユーザーID または ユーザー名)
|
||||
```
|
||||
|
||||
## キャッシュされたリモートファイルをクリーンアップする
|
||||
``` shell
|
||||
node cli/clean-cached-remote-files
|
||||
```
|
||||
|
||||
## 使われていないドライブのファイルをクリーンアップする
|
||||
``` shell
|
||||
node cli/clean-unused-drive-files
|
||||
```
|
||||
> ユーザーの大事なファイルを削除する可能性があるので、この操作を実行する前にユーザーに告知することをお勧めします。
|
||||
|
@ -11,12 +11,12 @@ If you find an untranslated part on Misskey:
|
||||
- In fact, `foo` should be a word that is appropriate for the situation and is easy to understand in English.
|
||||
- For example, if the untranslated portion is the following "タイムライン" you must write: `%i18n:@timeline%`.
|
||||
|
||||
3. Open the `locales/ja.yml`, check whether the <strong>file name (path)</strong> found in step 1 exists, if not, create it.
|
||||
3. Open the `locales/ja-JP.yml`, check whether the <strong>file name (path)</strong> found in step 1 exists, if not, create it.
|
||||
- Do not put the beginning of the path `src/client/app/` in the locale file.
|
||||
- For example, in this case we want to modify untranslated parts of `src/client/app/mobile/views/pages/home.vue`, so the key is `mobile/views/pages/home.vue`.
|
||||
|
||||
4. Add the text property using the `foo` keyword below the path that you found or created in step 2. Make sure to type your text in quotation marks. Text should always be inside of quotes.
|
||||
- For example, in this case we add timeline: `timeline: "タイムライン"` to `locales/ja.yml`.
|
||||
- For example, in this case we add timeline: `timeline: "タイムライン"` to `locales/ja-JP.yml`.
|
||||
|
||||
5. And done!
|
||||
|
||||
|
@ -16,7 +16,7 @@ Si vous trouvez un segment non-traduit sur Misskey :
|
||||
- Par exemple, dans ce cas de figure, nous voulons modifier le segment non-traduit de : `src/client/app/mobile/views/pages/home.vue`donc il faut juste écrire : `mobile/views/pages/home.vue` dans les fichiers linguistiques.
|
||||
|
||||
4. Ajoutez la propriété du texte traduit grâce à la clef `foo`, en-dessous du chemin correspondant à votre modification que vous avez trouvé ou créé dans l'étape 2. À côté, veuillez indiquer entre "guillemets" la valeur de votre traduction.
|
||||
- Par exemple, dans ce cas de figure, nous ajoutons la propriété et la traduction `timeline: "Timeline"` à `locales/fr.yml`, mais aussi la propriété et la version originale `timeline: "タイムライン"` à `locales/ja.yml`.
|
||||
- Par exemple, dans ce cas de figure, nous ajoutons la propriété et la traduction `timeline: "Timeline"` à `locales/fr.yml`, mais aussi la propriété et la version originale `timeline: "タイムライン"` à `locales/ja-JP.yml`.
|
||||
|
||||
5. Vous avez réussi à traduire une portion de misskey !
|
||||
|
||||
|
@ -11,12 +11,12 @@ Misskey内の未翻訳箇所を見つけたら
|
||||
- `foo`は実際にはその場に適したわかりやすい(英語の)名前にしてください。
|
||||
- 例えば未翻訳箇所が「タイムライン」というテキストだった場合、`%i18n:@timeline%`のようにします。
|
||||
|
||||
3. `locales/ja.yml`を開き、1.で見つけた<strong>ファイル名(パス)</strong>のキーが存在するか確認し、無ければ作成してください。
|
||||
3. `locales/ja-JP.yml`を開き、1.で見つけた<strong>ファイル名(パス)</strong>のキーが存在するか確認し、無ければ作成してください。
|
||||
- パスの`src/client/app/`は省略してください。
|
||||
- 例えば、今回の例では`src/client/app/mobile/views/pages/home.vue`の未翻訳箇所を修正したいので、キーは`mobile/views/pages/home.vue`になります。
|
||||
|
||||
4. そのキーの直下に2.で置換した`foo`の部分をキーとし、テキストを値とするプロパティを追加します。
|
||||
- 例えば、今回の例で言うと`locales/ja.yml`に`timeline: "タイムライン"`を追加します。
|
||||
- 例えば、今回の例で言うと`locales/ja-JP.yml`に`timeline: "タイムライン"`を追加します。
|
||||
|
||||
5. 完了です!
|
||||
|
||||
|
13
gulpfile.ts
13
gulpfile.ts
@ -23,7 +23,6 @@ const uglifyes = require('uglify-es');
|
||||
|
||||
const locales = require('./locales');
|
||||
import { fa } from './src/misc/fa';
|
||||
import config from './src/config';
|
||||
|
||||
const uglify = uglifyComposer(uglifyes, console);
|
||||
|
||||
@ -60,7 +59,16 @@ gulp.task('build:copy:views', () =>
|
||||
gulp.src('./src/server/web/views/**/*').pipe(gulp.dest('./built/server/web/views'))
|
||||
);
|
||||
|
||||
gulp.task('build:copy', ['build:copy:views'], () =>
|
||||
// 互換性のため
|
||||
gulp.task('build:copy:lang', () =>
|
||||
gulp.src(['./built/client/assets/*.*-*.js'])
|
||||
.pipe(rename(path => {
|
||||
path.basename = path.basename.replace(/\-(.*)$/, '');
|
||||
}))
|
||||
.pipe(gulp.dest('./built/client/assets/'))
|
||||
);
|
||||
|
||||
gulp.task('build:copy', ['build:copy:views', 'build:copy:lang'], () =>
|
||||
gulp.src([
|
||||
'./build/Release/crypto_key.node',
|
||||
'./src/const.json',
|
||||
@ -118,7 +126,6 @@ gulp.task('build:client:script', () => {
|
||||
const client = require('./built/client/meta.json');
|
||||
return gulp.src(['./src/client/app/boot.js', './src/client/app/safe.js'])
|
||||
.pipe(replace('VERSION', JSON.stringify(client.version)))
|
||||
.pipe(replace('API', JSON.stringify(config.api_url)))
|
||||
.pipe(replace('ENV', JSON.stringify(env)))
|
||||
.pipe(replace('LANGS', JSON.stringify(Object.keys(locales))))
|
||||
.pipe(isProduction ? uglify({
|
||||
|
5
locales/README.md
Normal file
5
locales/README.md
Normal file
@ -0,0 +1,5 @@
|
||||
# **Please DO NOT edit these files** except `ja-JP.yml`.
|
||||
|
||||
If you want to...
|
||||
* i18n ... please see [Translation guide](../docs/translate.en.md).
|
||||
* l10n ... please visit https://crowdin.com/project/misskey
|
File diff suppressed because it is too large
Load Diff
@ -58,7 +58,7 @@ common:
|
||||
friday: "金曜日"
|
||||
saturday: "土曜日"
|
||||
reactions:
|
||||
like: "Gefällt mir"
|
||||
like: "ええやん"
|
||||
love: "Lieben"
|
||||
laugh: "Lachen"
|
||||
hmm: "Hmm...?"
|
||||
@ -289,6 +289,8 @@ common/views/components/signin.vue:
|
||||
signin-with-twitter: "Twitterでログイン"
|
||||
login-failed: "ログインできませんでした。ユーザー名とパスワードを確認してください。"
|
||||
common/views/components/signup.vue:
|
||||
invitation-code: "招待コード"
|
||||
invitation-info: "招待コードをお持ちでない方は、<a href=\"{}\">管理者</a>までご連絡ください。"
|
||||
username: "Benutzername"
|
||||
checking: "Überprüfung..."
|
||||
available: "Verfügbar"
|
||||
@ -441,6 +443,7 @@ desktop/views/components/drive-window.vue:
|
||||
desktop/views/components/drive.file.vue:
|
||||
avatar: "Avatar"
|
||||
banner: "Banner"
|
||||
nsfw: "閲覧注意"
|
||||
contextmenu:
|
||||
rename: "Umbenennen"
|
||||
mark-as-sensitive: "閲覧注意に設定"
|
||||
@ -798,6 +801,7 @@ desktop/views/pages/admin/admin.dashboard.vue:
|
||||
original-users: "このインスタンスのユーザー"
|
||||
all-notes: "全てのノート"
|
||||
original-notes: "このインスタンスのノート"
|
||||
invite: "招待"
|
||||
desktop/views/pages/admin/admin.suspend-user.vue:
|
||||
suspend-user: "ユーザーの凍結"
|
||||
suspend: "凍結"
|
||||
@ -806,6 +810,26 @@ desktop/views/pages/admin/admin.unsuspend-user.vue:
|
||||
unsuspend-user: "ユーザーの凍結の解除"
|
||||
unsuspend: "凍結の解除"
|
||||
unsuspended: "凍結を解除しました"
|
||||
desktop/views/pages/admin/admin.verify-user.vue:
|
||||
verify-user: "ユーザーの公式アカウント設定"
|
||||
verify: "公式アカウントにする"
|
||||
verified: "公式アカウントにしました"
|
||||
desktop/views/pages/admin/admin.unverify-user.vue:
|
||||
unverify-user: "ユーザーの公式アカウント解除"
|
||||
unverify: "公式アカウントを解除する"
|
||||
unverified: "公式アカウントを解除しました"
|
||||
desktop/views/pages/admin/admin.notes-chart.vue:
|
||||
title: "投稿"
|
||||
local: "ローカル"
|
||||
remote: "リモート"
|
||||
desktop/views/pages/admin/admin.users-chart.vue:
|
||||
title: "ユーザー"
|
||||
local: "ローカル"
|
||||
remote: "リモート"
|
||||
desktop/views/pages/admin/admin.drive-chart.vue:
|
||||
title: "ドライブ"
|
||||
local: "ローカル"
|
||||
remote: "リモート"
|
||||
desktop/views/pages/deck/deck.tl-column.vue:
|
||||
is-media-only: "メディア投稿のみ"
|
||||
is-media-view: "メディアビュー"
|
||||
@ -838,7 +862,7 @@ desktop/views/pages/selectdrive.vue:
|
||||
cancel: "Abbrechen"
|
||||
upload: "PCからドライブにファイルをアップロード"
|
||||
desktop/views/pages/search.vue:
|
||||
not-available: "検索機能を利用することができません。"
|
||||
not-available: "検索機能はインスタンスの設定で無効になっています。"
|
||||
not-found: "「{}」に関する投稿は見つかりませんでした。"
|
||||
desktop/views/pages/share.vue:
|
||||
share-with: "{}で共有"
|
||||
@ -931,12 +955,15 @@ mobile/views/components/drive-file-chooser.vue:
|
||||
select-file: "ファイルを選択"
|
||||
mobile/views/components/drive-folder-chooser.vue:
|
||||
select-folder: "フォルダーを選択"
|
||||
mobile/views/components/drive.file.vue:
|
||||
nsfw: "閲覧注意"
|
||||
mobile/views/components/drive.file-detail.vue:
|
||||
download: "ダウンロード"
|
||||
rename: "名前を変更"
|
||||
move: "移動"
|
||||
hash: "ハッシュ (md5)"
|
||||
exif: "EXIF"
|
||||
nsfw: "閲覧注意"
|
||||
mobile/views/components/media-image.vue:
|
||||
sensitive: "閲覧注意"
|
||||
click-to-show: "クリックして表示"
|
@ -289,6 +289,8 @@ common/views/components/signin.vue:
|
||||
signin-with-twitter: "Log in with Twitter"
|
||||
login-failed: "Log in failed. Make sure you have entered your correct username and password."
|
||||
common/views/components/signup.vue:
|
||||
invitation-code: "Invitation code"
|
||||
invitation-info: "If you do not have an invitation code, please contact an <a href=\"{}\">administrator</a>."
|
||||
username: "Username"
|
||||
checking: "Confirming..."
|
||||
available: "Available"
|
||||
@ -441,6 +443,7 @@ desktop/views/components/drive-window.vue:
|
||||
desktop/views/components/drive.file.vue:
|
||||
avatar: "Avatar"
|
||||
banner: "Banner"
|
||||
nsfw: "NSFW"
|
||||
contextmenu:
|
||||
rename: "Rename"
|
||||
mark-as-sensitive: "Mark as 'sensitive'"
|
||||
@ -798,6 +801,7 @@ desktop/views/pages/admin/admin.dashboard.vue:
|
||||
original-users: "Users on this instance"
|
||||
all-notes: "All Posts"
|
||||
original-notes: "Posts on this instance"
|
||||
invite: "Invite"
|
||||
desktop/views/pages/admin/admin.suspend-user.vue:
|
||||
suspend-user: "Suspend a user"
|
||||
suspend: "Suspend"
|
||||
@ -806,6 +810,26 @@ desktop/views/pages/admin/admin.unsuspend-user.vue:
|
||||
unsuspend-user: "Unsuspend users"
|
||||
unsuspend: "Unsuspend"
|
||||
unsuspended: "The user has successfully unsuspended."
|
||||
desktop/views/pages/admin/admin.verify-user.vue:
|
||||
verify-user: "User account verification settings"
|
||||
verify: "Verify account"
|
||||
verified: "The account is now being verified"
|
||||
desktop/views/pages/admin/admin.unverify-user.vue:
|
||||
unverify-user: "User account unverification settings"
|
||||
unverify: "Unverify account"
|
||||
unverified: "The account is now being unverified"
|
||||
desktop/views/pages/admin/admin.notes-chart.vue:
|
||||
title: "Posts"
|
||||
local: "Local"
|
||||
remote: "Remote"
|
||||
desktop/views/pages/admin/admin.users-chart.vue:
|
||||
title: "Users"
|
||||
local: "Local"
|
||||
remote: "Remote"
|
||||
desktop/views/pages/admin/admin.drive-chart.vue:
|
||||
title: "Drive"
|
||||
local: "Local"
|
||||
remote: "Remote"
|
||||
desktop/views/pages/deck/deck.tl-column.vue:
|
||||
is-media-only: "Only media posts"
|
||||
is-media-view: "Media view"
|
||||
@ -838,7 +862,7 @@ desktop/views/pages/selectdrive.vue:
|
||||
cancel: "Cancel"
|
||||
upload: "Upload files from your device"
|
||||
desktop/views/pages/search.vue:
|
||||
not-available: "The search feature is not available for now."
|
||||
not-available: "Search feature is turned off in the settings for this instance."
|
||||
not-found: "No posts were found for '{}'"
|
||||
desktop/views/pages/share.vue:
|
||||
share-with: "Share with {}."
|
||||
@ -931,12 +955,15 @@ mobile/views/components/drive-file-chooser.vue:
|
||||
select-file: "Choose files"
|
||||
mobile/views/components/drive-folder-chooser.vue:
|
||||
select-folder: "Choose a folder"
|
||||
mobile/views/components/drive.file.vue:
|
||||
nsfw: "NSFW"
|
||||
mobile/views/components/drive.file-detail.vue:
|
||||
download: "Download"
|
||||
rename: "Rename"
|
||||
move: "Move"
|
||||
hash: "Hash (md5)"
|
||||
exif: "EXIF"
|
||||
nsfw: "NSFW"
|
||||
mobile/views/components/media-image.vue:
|
||||
sensitive: "NSFW"
|
||||
click-to-show: "Click to show"
|
@ -58,7 +58,7 @@ common:
|
||||
friday: "Viernes"
|
||||
saturday: "Sábado"
|
||||
reactions:
|
||||
like: "me gusta"
|
||||
like: "ええやん"
|
||||
love: "amor"
|
||||
laugh: "risa"
|
||||
hmm: "hmm"
|
||||
@ -289,6 +289,8 @@ common/views/components/signin.vue:
|
||||
signin-with-twitter: "Ingresar con Twitter"
|
||||
login-failed: "ログインできませんでした。ユーザー名とパスワードを確認してください。"
|
||||
common/views/components/signup.vue:
|
||||
invitation-code: "招待コード"
|
||||
invitation-info: "招待コードをお持ちでない方は、<a href=\"{}\">管理者</a>までご連絡ください。"
|
||||
username: "Usuario"
|
||||
checking: "Comprobando..."
|
||||
available: "Disponible"
|
||||
@ -441,6 +443,7 @@ desktop/views/components/drive-window.vue:
|
||||
desktop/views/components/drive.file.vue:
|
||||
avatar: "Avatar"
|
||||
banner: "Banner"
|
||||
nsfw: "閲覧注意"
|
||||
contextmenu:
|
||||
rename: "Renombrar"
|
||||
mark-as-sensitive: "Marcar como 'sensible'"
|
||||
@ -798,6 +801,7 @@ desktop/views/pages/admin/admin.dashboard.vue:
|
||||
original-users: "このインスタンスのユーザー"
|
||||
all-notes: "全てのノート"
|
||||
original-notes: "このインスタンスのノート"
|
||||
invite: "招待"
|
||||
desktop/views/pages/admin/admin.suspend-user.vue:
|
||||
suspend-user: "ユーザーの凍結"
|
||||
suspend: "凍結"
|
||||
@ -806,6 +810,26 @@ desktop/views/pages/admin/admin.unsuspend-user.vue:
|
||||
unsuspend-user: "ユーザーの凍結の解除"
|
||||
unsuspend: "凍結の解除"
|
||||
unsuspended: "凍結を解除しました"
|
||||
desktop/views/pages/admin/admin.verify-user.vue:
|
||||
verify-user: "ユーザーの公式アカウント設定"
|
||||
verify: "公式アカウントにする"
|
||||
verified: "公式アカウントにしました"
|
||||
desktop/views/pages/admin/admin.unverify-user.vue:
|
||||
unverify-user: "ユーザーの公式アカウント解除"
|
||||
unverify: "公式アカウントを解除する"
|
||||
unverified: "公式アカウントを解除しました"
|
||||
desktop/views/pages/admin/admin.notes-chart.vue:
|
||||
title: "投稿"
|
||||
local: "ローカル"
|
||||
remote: "リモート"
|
||||
desktop/views/pages/admin/admin.users-chart.vue:
|
||||
title: "ユーザー"
|
||||
local: "ローカル"
|
||||
remote: "リモート"
|
||||
desktop/views/pages/admin/admin.drive-chart.vue:
|
||||
title: "ドライブ"
|
||||
local: "ローカル"
|
||||
remote: "リモート"
|
||||
desktop/views/pages/deck/deck.tl-column.vue:
|
||||
is-media-only: "メディア投稿のみ"
|
||||
is-media-view: "メディアビュー"
|
||||
@ -838,7 +862,7 @@ desktop/views/pages/selectdrive.vue:
|
||||
cancel: "キャンセル"
|
||||
upload: "PCからドライブにファイルをアップロード"
|
||||
desktop/views/pages/search.vue:
|
||||
not-available: "検索機能を利用することができません。"
|
||||
not-available: "検索機能はインスタンスの設定で無効になっています。"
|
||||
not-found: "「{}」に関する投稿は見つかりませんでした。"
|
||||
desktop/views/pages/share.vue:
|
||||
share-with: "{}で共有"
|
||||
@ -931,12 +955,15 @@ mobile/views/components/drive-file-chooser.vue:
|
||||
select-file: "ファイルを選択"
|
||||
mobile/views/components/drive-folder-chooser.vue:
|
||||
select-folder: "フォルダーを選択"
|
||||
mobile/views/components/drive.file.vue:
|
||||
nsfw: "閲覧注意"
|
||||
mobile/views/components/drive.file-detail.vue:
|
||||
download: "ダウンロード"
|
||||
rename: "名前を変更"
|
||||
move: "移動"
|
||||
hash: "ハッシュ (md5)"
|
||||
exif: "EXIF"
|
||||
nsfw: "閲覧注意"
|
||||
mobile/views/components/media-image.vue:
|
||||
sensitive: "閲覧注意"
|
||||
click-to-show: "クリックして表示"
|
@ -4,10 +4,10 @@ meta:
|
||||
divider: ""
|
||||
common:
|
||||
misskey: "Une ⭐ du fédiverse"
|
||||
about-title: "Une ⭐ du fédiverse."
|
||||
about: "Merci d'avoir découvert Misskey. Misskey est une <b>plateforme de micro-blogging distribuée</b> née sur Terre. Parce qu'il fait partie du Fédiverse (un univers composé de diverses plateformes de réseaux sociaux organisées), il est mutuellement connecté avec d'autres plateformes de réseaux sociaux. Désirez-vous prendre une pause, pendant un instant, loin de l'agitation de la ville et plonger dans un nouvel Internet ?"
|
||||
about-title: "Une ⭐ du fédivers."
|
||||
about: "Merci d'avoir découvert Misskey. Misskey est une <b>plateforme de microblogage distribuée</b> née sur Terre. Parce qu'il fait partie du Fédivers (un univers composé de diverses plateformes de réseaux sociaux organisées), il est mutuellement connecté avec d'autres plateformes de réseaux sociaux. Désirez-vous prendre une pause, pendant un instant, loin de l'agitation de la ville et plonger dans un nouvel Internet ?"
|
||||
adblock:
|
||||
detected: "Veuillez désactiver le bloqueur de publicités"
|
||||
detected: "Veuillez désactiver votre bloqueur de publicités"
|
||||
warning: "<strong>Misskey n'utilise pas de publicités</strong>, mais quelques options peuvent être non disponibles ou fonctionneraient mal si un bloqueur de publicités est activé."
|
||||
application-authorization: "Permissions de l'application"
|
||||
close: "Fermer"
|
||||
@ -17,7 +17,7 @@ common:
|
||||
title: "Conseils de personnalisation"
|
||||
paragraph1: "La personnalisation à la maison vous permet d'ajouter / supprimer, glisser et déposer et réorganiser les 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."
|
||||
gotit: "Compris!"
|
||||
notification:
|
||||
@ -30,7 +30,7 @@ common:
|
||||
quoted-by: "Cité·e par {} :"
|
||||
time:
|
||||
unknown: "inconnu"
|
||||
future: "future"
|
||||
future: "à l'instant"
|
||||
just_now: "à l'instant"
|
||||
seconds_ago: "Il y a {} seconde·s"
|
||||
minutes_ago: "Il y a {} minute·s"
|
||||
@ -58,7 +58,7 @@ common:
|
||||
friday: "Vendredi"
|
||||
saturday: "Samedi"
|
||||
reactions:
|
||||
like: "Aime"
|
||||
like: "ええやん"
|
||||
love: "Adore"
|
||||
laugh: "Rire"
|
||||
hmm: "Hmm ... ?"
|
||||
@ -69,7 +69,7 @@ common:
|
||||
rip: "RIP"
|
||||
pudding: "Pudding"
|
||||
note-placeholders:
|
||||
a: "Que faîtes vous maintenant ?"
|
||||
a: "Que faites vous maintenant ?"
|
||||
b: "Quoi de neuf ?"
|
||||
c: "Qu'avez-vous en tête ?"
|
||||
d: "Voulez-vous exprimer quelque chose ?"
|
||||
@ -82,9 +82,9 @@ common:
|
||||
update-available-title: "Mise à jour disponible"
|
||||
update-available: "Une nouvelle version de Misskey est disponible ({newer}, version actuelle: {current}). Veuillez recharger la page pour appliquer la mise à jour."
|
||||
my-token-regenerated: "Votre token vient d'être généré, vous allez maintenant être déconnecté."
|
||||
i-like-sushi: "Je préfère les sushis (au pudding)"
|
||||
i-like-sushi: "Je préfère les sushis plutôt que le pudding"
|
||||
show-reversi-board-labels: "Afficher les étiquettes des lignes et colonnes dans Reversi"
|
||||
verified-user: "公式アカウント"
|
||||
verified-user: "Compte vérifié"
|
||||
disable-animated-mfm: "Désactiver les textes animés dans les publications"
|
||||
reversi:
|
||||
drawn: "Partie nulle"
|
||||
@ -101,18 +101,18 @@ common:
|
||||
analog-clock: "Horloge analogique"
|
||||
profile: "Profil"
|
||||
calendar: "Calendrier"
|
||||
timemachine: "Calendrier (Machine de temps)"
|
||||
timemachine: "Calendrier (Machine temporelle)"
|
||||
activity: "Activité"
|
||||
rss: "Lecteur de flux RSS"
|
||||
memo: "Pense-bête"
|
||||
trends: "Tendances"
|
||||
photo-stream: "Flux de photos"
|
||||
posts-monitor: "Graph des publications"
|
||||
posts-monitor: "Graphe des publications"
|
||||
slideshow: "Diaporama"
|
||||
version: "Version"
|
||||
broadcast: "Diffusion"
|
||||
notifications: "Notifications"
|
||||
users: "Utilisateurs"
|
||||
users: "Utilisateur·rice·s"
|
||||
polls: "Sondages"
|
||||
post-form: "Formulaire de publication"
|
||||
messaging: "Messagerie"
|
||||
@ -174,16 +174,16 @@ common/views/components/games/reversi/reversi.game.vue:
|
||||
can-put-everywhere: "どこでも置けるモード"
|
||||
common/views/components/games/reversi/reversi.index.vue:
|
||||
title: "Misskey Reversi"
|
||||
sub-title: "Jouer à Reversi avec vos amis·es !"
|
||||
sub-title: "Jouer à Reversi avec vos ami·e·s !"
|
||||
invite: "Inviter"
|
||||
rule: "Comment Jouer ?"
|
||||
rule: "Comment jouer ?"
|
||||
rule-desc: "リバーシは、相手と交互に石をボードに置いて、相手の石を挟んで自分の色に変えてゆき、最終的に残った石が多い方が勝ちというボードゲームです。"
|
||||
mode-invite: "Inviter"
|
||||
mode-invite-desc: "Inviter un joueur."
|
||||
mode-invite-desc: "Inviter un·e joueur·se."
|
||||
invitations: "Vous avez reçu une invitation !"
|
||||
my-games: "Mes jeux"
|
||||
all-games: "Tous les jeux"
|
||||
enter-username: "Saisir un nom d'utilisateur"
|
||||
enter-username: "Saisir un nom d'utilisateur·rice"
|
||||
game-state:
|
||||
ended: "Terminée"
|
||||
playing: "En cours"
|
||||
@ -204,7 +204,7 @@ common/views/components/games/reversi/reversi.room.vue:
|
||||
waiting-for-both: "En attente que vous soyez prêt"
|
||||
cancel: "Annuler"
|
||||
ready: "Prêt"
|
||||
cancel-ready: "Annuler \"Je suis prêt\""
|
||||
cancel-ready: "Annuler « Prêt »"
|
||||
common/views/components/connect-failed.vue:
|
||||
title: "Échec de connexion au serveur"
|
||||
description: "Il y a soit un problème avec votre connexion internet, soit le serveur est hors-ligne ou en maintenance. Veuillez {ressayer} plus tard."
|
||||
@ -230,20 +230,20 @@ common/views/components/connect-failed.troubleshooter.vue:
|
||||
flush: "Vider le cache"
|
||||
set-version: "Choisissez une version"
|
||||
common/views/components/messaging.vue:
|
||||
search-user: "Trouver un utilisateur"
|
||||
search-user: "Trouver un·e utilisateur·rice"
|
||||
you: "Vous"
|
||||
no-history: "Pas d'historique"
|
||||
common/views/components/messaging-room.vue:
|
||||
empty: "Pas de conversations"
|
||||
more: "Voir Plus"
|
||||
more: "Voir plus"
|
||||
no-history: "Il n'y a pas plus d'historique"
|
||||
resize-form: "Faites glisser pour redimensionner"
|
||||
new-message: "Nouveau message"
|
||||
only-one-file-attached: "Un seul fichier uniquement peut être joint au message"
|
||||
only-one-file-attached: "Un seul fichier peut être joint au message"
|
||||
common/views/components/messaging-room.form.vue:
|
||||
input-message-here: "Tapez ici votre message"
|
||||
send: "Envoyer"
|
||||
attach-from-local: "Joindre un fichier depuis votre PC"
|
||||
attach-from-local: "Joindre un fichier depuis votre ordinateur"
|
||||
attach-from-drive: "Joindre un fichier depuis votre Drive"
|
||||
only-one-file-attached: "Un seul fichier uniquement peut être joint au message"
|
||||
common/views/components/messaging-room.message.vue:
|
||||
@ -251,23 +251,23 @@ common/views/components/messaging-room.message.vue:
|
||||
deleted: "Ce message a été supprimé"
|
||||
common/views/components/nav.vue:
|
||||
about: "À propos"
|
||||
stats: "Stats"
|
||||
status: "Status"
|
||||
stats: "Statistiques"
|
||||
status: "Statut"
|
||||
wiki: "Wiki"
|
||||
donors: "Donateurs"
|
||||
repository: "Repo"
|
||||
develop: "Développeurs"
|
||||
donors: "Donateur·rice·s"
|
||||
repository: "Dépôt"
|
||||
develop: "Développeur·se·s"
|
||||
feedback: "Remarques"
|
||||
common/views/components/note-menu.vue:
|
||||
favorite: "Favorite this note"
|
||||
pin: "Épingler sur votre profile"
|
||||
favorite: "Mettre cette note en favoris"
|
||||
pin: "Épingler sur votre profil"
|
||||
delete: "Supprimer"
|
||||
delete-confirm: "Supprimer cette publication ?"
|
||||
remote: "Afficher les note originale"
|
||||
remote: "Afficher la note originale"
|
||||
common/views/components/poll.vue:
|
||||
vote-to: "Voter pour '{}'"
|
||||
vote-count: "{} votes"
|
||||
total-users: "{} utilisateurs ont voté"
|
||||
total-users: "{} utilisateur·rice·s ont voté·e·s"
|
||||
vote: "Vote"
|
||||
show-result: "Montrer les résultats"
|
||||
voted: "Voté"
|
||||
@ -280,32 +280,34 @@ common/views/components/poll-editor.vue:
|
||||
common/views/components/reaction-picker.vue:
|
||||
choose-reaction: "Choisissez votre réaction"
|
||||
common/views/components/signin.vue:
|
||||
username: "Nom d'utilisateur"
|
||||
username: "Nom d'utilisateur·rice"
|
||||
password: "Mot de passe"
|
||||
token: "Token"
|
||||
signing-in: "Connexion...."
|
||||
signing-in: "Connexion…"
|
||||
signin: "Se connecter"
|
||||
or: "Ou"
|
||||
signin-with-twitter: "Se connecter via Twitter"
|
||||
login-failed: "ログインできませんでした。ユーザー名とパスワードを確認してください。"
|
||||
login-failed: "Échec d'authentification. Veuillez vérifier que votre nom d'utilisateur et mot de passe sont corrects."
|
||||
common/views/components/signup.vue:
|
||||
username: "Nom d'utilisateur"
|
||||
checking: "Vérification"
|
||||
invitation-code: "Code d’invitation"
|
||||
invitation-info: "Si vous n’avez pas de code d’invitation, contactez un·e <a href=\"{}\">administrateur·rice</a>."
|
||||
username: "Nom d'utilisateur·rice"
|
||||
checking: "Vérification…"
|
||||
available: "Disponible"
|
||||
unavailable: "Non disponible"
|
||||
error: "Erreur de réseau"
|
||||
invalid-format: "Utilisez seulement des lettres, nombres et/ou -."
|
||||
error: "Erreur du réseau"
|
||||
invalid-format: "Vous pouvez utiliser des lettres, des nombres et _."
|
||||
too-short: "Veuillez saisir au moins un caractère !"
|
||||
too-long: "Veuillez entrer au maximum 20 caractères."
|
||||
password: "Mot de Passe"
|
||||
password-placeholder: "Nous recommendons au moins 8 caractères."
|
||||
password: "Mot de passe"
|
||||
password-placeholder: "Nous recommandons au moins 8 caractères."
|
||||
weak-password: "Faible"
|
||||
normal-password: "Moyen"
|
||||
strong-password: "Fort"
|
||||
retype: "Retapez"
|
||||
retype-placeholder: "Confirmez votre mot de passe"
|
||||
password-matched: "OK"
|
||||
password-not-matched: "Les mots de passes ne correspondent pas."
|
||||
password-not-matched: "Les mots de passe ne correspondent pas."
|
||||
recaptcha: "Vérifier"
|
||||
create: "Créer un compte"
|
||||
some-error: "La création du compte a échoué. Veuillez réessayer."
|
||||
@ -317,14 +319,14 @@ common/views/components/stream-indicator.vue:
|
||||
reconnecting: "Reconnexion en cours"
|
||||
connected: "Connecté"
|
||||
common/views/components/twitter-setting.vue:
|
||||
description: "Si vous liez votre compte Twitter à votre compte Misskey, vous verrez ensuite votre compte Twitter s'afficher sur votre profile, vous aurez aussi la possibilité de vous connecter à Misskey en utilisant votre compte Twitter."
|
||||
description: "Si vous liez votre compte Twitter à votre compte Misskey, vous verrez ensuite votre compte Twitter s'afficher sur votre profil, vous aurez aussi la possibilité de vous connecter à Misskey en utilisant votre compte Twitter."
|
||||
connected-to: "Vous êtes connecté à ce compte Twitter"
|
||||
detail: "Détails …"
|
||||
reconnect: "Reconnecter"
|
||||
detail: "Détails…"
|
||||
reconnect: "Reconnexion"
|
||||
connect: "Lier votre compte Twitter"
|
||||
disconnect: "Déconnecter"
|
||||
disconnect: "Déconnexion"
|
||||
common/views/components/uploader.vue:
|
||||
waiting: "En attente"
|
||||
waiting: "Veuillez patienter"
|
||||
common/views/components/visibility-chooser.vue:
|
||||
public: "Public"
|
||||
home: "Accueil"
|
||||
@ -332,42 +334,42 @@ common/views/components/visibility-chooser.vue:
|
||||
followers: "Abonné·e·s"
|
||||
followers-desc: "Publier à vos abonné·e·s uniquement"
|
||||
specified: "Direct"
|
||||
specified-desc: "Publier aux utilisateurs·trices mentionné·es"
|
||||
specified-desc: "Publier aux utilisateur·rice·s mentionné·e·s"
|
||||
private: "Privé"
|
||||
common/views/widgets/broadcast.vue:
|
||||
fetching: "Récuperation"
|
||||
fetching: "Récupération"
|
||||
no-broadcasts: "Aucune annonce"
|
||||
have-a-nice-day: "Passez une bonne journée !"
|
||||
next: "Suivant"
|
||||
common/views/widgets/calendar.vue:
|
||||
year: "{} année"
|
||||
month: "{} mois"
|
||||
day: "{} jour"
|
||||
year: "Année {}"
|
||||
month: "Mois {}"
|
||||
day: "Jour {}"
|
||||
today: "Aujourd'hui :"
|
||||
this-month: "Ce mois-ci :"
|
||||
this-year: "Cette année :"
|
||||
common/views/widgets/donation.vue:
|
||||
title: "Dons"
|
||||
title: "Faire un don"
|
||||
text: "Les frais pour faire fonctionner Misskey sortent directement de notre poche. Nous ne recevons pas d'argent issu de la publicité, si vous pouvez nous faire des dons, on vous serait éternellement reconnaissants. Si vous êtes intéressé·es veuillez contacter {}. Merci pour votre contribution !"
|
||||
common/views/widgets/photo-stream.vue:
|
||||
title: "Flux de photo"
|
||||
no-photos: "Pas de photos"
|
||||
title: "Flux de photos"
|
||||
no-photos: "Pas de photo"
|
||||
common/views/widgets/posts-monitor.vue:
|
||||
title: "Graph des publications"
|
||||
title: "Graphe des publications"
|
||||
toggle: "Basculer entre les vues"
|
||||
common/views/widgets/hashtags.vue:
|
||||
title: "Étiquettes"
|
||||
count: "{} utilisateurs mentionnés"
|
||||
count: "{} utilisateur·rice·s mentionné·e·s"
|
||||
empty: "Aucune tendance"
|
||||
common/views/widgets/server.vue:
|
||||
title: "Info sur le serveur"
|
||||
title: "Informations sur le serveur"
|
||||
toggle: "Afficher les vues"
|
||||
common/views/widgets/memo.vue:
|
||||
title: "Pense-bête"
|
||||
memo: "Écrivez ici !"
|
||||
save: "Enregistrer"
|
||||
common/views/widgets/slideshow.vue:
|
||||
folder-customize-mode: "Veuillez quitter le mode personnalisé pour pouvour spécifier un dossier"
|
||||
folder-customize-mode: "Pour pouvoir spécifier un dossier, veuillez quitter le mode de personnalisation"
|
||||
folder: "Veuillez cliquer pour spécifier le dossier"
|
||||
no-image: "Il n'y a aucune image dans ce dossier"
|
||||
common/views/widgets/tips.vue:
|
||||
@ -375,13 +377,13 @@ common/views/widgets/tips.vue:
|
||||
tips-line2: "<kbd>p</kbd>または<kbd>n</kbd>で投稿フォームを開きます"
|
||||
tips-line3: "Vous pouvez glisser et déposer des fichiers 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éplacer"
|
||||
tips-line5: "Vous pouvez téléverser des fichiers sur le Drive en faisant un glisser-déposer"
|
||||
tips-line6: "ドライブでファイルをドラッグしてフォルダ移動できます"
|
||||
tips-line7: "ドライブでフォルダをドラッグしてフォルダ移動できます"
|
||||
tips-line8: "Vous pouvez personnaliser l'Accueil via les paramètres"
|
||||
tips-line9: "Misskey est sous licence AGPLv3"
|
||||
tips-line10: "タイムマシンウィジェットを利用すると、簡単に過去のタイムラインに遡れます"
|
||||
tips-line11: "Vous pouvez épingler des notes sur votre page en appuyant sur \"…\""
|
||||
tips-line11: "Vous pouvez épingler des notes sur votre page en cliquant sur « … »"
|
||||
tips-line13: "Tous les fichiers attachés à cette publication sont sauvegardés dans le Drive"
|
||||
tips-line14: "ホームのカスタマイズ中、ウィジェットを右クリックしてデザインを変更できます"
|
||||
tips-line17: "Vous pouvez mettre un texte en surbrillance en le mettant entre ** **"
|
||||
@ -392,18 +394,18 @@ common/views/widgets/tips.vue:
|
||||
tips-line24: "Misskey a vu le jour en 2014"
|
||||
tips-line25: "対応ブラウザではMisskeyを開いていなくても通知を受け取れます"
|
||||
common/views/pages/follow.vue:
|
||||
signed-in-as: "Connecté·é en tant que {}"
|
||||
signed-in-as: "Connecté·e en tant que {}"
|
||||
following: "Suit"
|
||||
follow: "Suivre"
|
||||
request-pending: "Demande d'abonnement en attente"
|
||||
follow-request: "Demande d'abonnement"
|
||||
desktop:
|
||||
banner-crop-title: "Découpez la partie qui apparaîtra comme une bannière"
|
||||
banner-crop-title: "Découpez la partie qui apparaitra comme bannière"
|
||||
banner: "Bannière"
|
||||
uploading-banner: "Téléversement d'une nouvelle bannière"
|
||||
banner-updated: "La bannière est mise à jour"
|
||||
choose-banner: "Choisir une bannière"
|
||||
avatar-crop-title: "Découpez la partie qui apparaîtra dans l'avatar"
|
||||
avatar-crop-title: "Découpez la partie qui apparaitra comme avatar"
|
||||
avatar: "Avatar"
|
||||
uploading-avatar: "Téléversement du nouvel avatar"
|
||||
avatar-updated: "L'avatar est mis à jour"
|
||||
@ -414,16 +416,16 @@ desktop/views/components/activity.chart.vue:
|
||||
replies: "Rouge ... Réponses"
|
||||
renotes: "Vert ... Partages"
|
||||
desktop/views/components/activity.vue:
|
||||
title: "Activitié"
|
||||
title: "Activité"
|
||||
toggle: "Afficher les vues"
|
||||
desktop/views/components/calendar.vue:
|
||||
title: "{1} / {2}"
|
||||
prev: "Mois dernier"
|
||||
next: "Mois prochain"
|
||||
go: "Cliquer pour naviguer"
|
||||
go: "Cliquez pour naviguer"
|
||||
desktop/views/components/choose-file-from-drive-window.vue:
|
||||
choose-file: "Sélection de fichiers"
|
||||
upload: "Téléverser des fichiers à partir de votre PC"
|
||||
upload: "Téléverser des fichiers à partir de votre ordinateur"
|
||||
cancel: "Annuler"
|
||||
ok: "OK"
|
||||
choose-prompt: "Choisir un fichier"
|
||||
@ -441,6 +443,7 @@ desktop/views/components/drive-window.vue:
|
||||
desktop/views/components/drive.file.vue:
|
||||
avatar: "Avatar"
|
||||
banner: "Bannière"
|
||||
nsfw: "CW"
|
||||
contextmenu:
|
||||
rename: "Renommer"
|
||||
mark-as-sensitive: "Marquer comme sensible"
|
||||
@ -454,14 +457,14 @@ desktop/views/components/drive.file.vue:
|
||||
add-app: "Ajouter une application"
|
||||
rename-file: "Renommer le ficher"
|
||||
input-new-file-name: "Entrer un nouveau nom"
|
||||
copied: "Copied"
|
||||
copied-url-to-clipboard: "L'URL a été copié dans le presse-papier"
|
||||
copied: "Copié"
|
||||
copied-url-to-clipboard: "L'URL a été copiée dans le presse-papier"
|
||||
desktop/views/components/drive.folder.vue:
|
||||
unable-to-process: "L'opération n'a pas pu être complétée"
|
||||
circular-reference-detected: "Le dossier de destination est un sous-dossier du dossier que vous souhaitez déplacer."
|
||||
unhandled-error: "Erreur inconnue"
|
||||
contextmenu:
|
||||
move-to-this-folder: "Bouger dans ce dossier"
|
||||
move-to-this-folder: "Déplacer dans ce dossier"
|
||||
show-in-new-window: "Ouvrir dans une nouvelle fenêtre"
|
||||
rename: "Renommer"
|
||||
rename-folder: "Renommer le dossier"
|
||||
@ -635,7 +638,7 @@ desktop/views/components/settings.vue:
|
||||
show-maps-desc: "位置情報が添付された投稿のマップを自動的に展開します。"
|
||||
sound: "Son"
|
||||
enable-sounds: "Activer le son"
|
||||
enable-sounds-desc: "投稿やメッセージを送受信したときなどにサウンドを再生します。この設定はブラウザに記憶されます。"
|
||||
enable-sounds-desc: "Jouer un son lorsque vous recevez un message. Ce paramètre est sauvegardé dans le navigateur."
|
||||
volume: "Volume"
|
||||
test: "Test"
|
||||
mobile: "Mobile"
|
||||
@ -696,7 +699,7 @@ desktop/views/components/settings.2fa.vue:
|
||||
desktop/views/components/settings.api.vue:
|
||||
intro: "APIを利用するには、上記のトークンを「i」というキーでパラメータに付加してリクエストします。"
|
||||
caution: "アカウントを不正利用される可能性があるため、このトークンは第三者に教えないでください(アプリなどにも入力しないでください)。"
|
||||
regeneration-of-token: "万が一このトークンが漏れたりその可能性がある場合はトークンを再生成できます。"
|
||||
regeneration-of-token: "Si votre jeton est compromis, vous pouvez le régénérer."
|
||||
regenerate-token: "Regenerer le token"
|
||||
token: "Jeton :"
|
||||
enter-password: "Veuillez entrer le mot de passe"
|
||||
@ -789,23 +792,44 @@ desktop/views/components/window.vue:
|
||||
close: "Fermer"
|
||||
desktop/views/pages/admin/admin.vue:
|
||||
dashboard: "ダッシュボード"
|
||||
drive: "ドライブ"
|
||||
users: "ユーザー"
|
||||
update: "更新"
|
||||
drive: "Drive"
|
||||
users: "Utilisateur·rice·s"
|
||||
update: "Mises à jour"
|
||||
desktop/views/pages/admin/admin.dashboard.vue:
|
||||
dashboard: "ダッシュボード"
|
||||
all-users: "全てのユーザー"
|
||||
original-users: "このインスタンスのユーザー"
|
||||
all-notes: "全てのノート"
|
||||
original-notes: "このインスタンスのノート"
|
||||
all-users: "Tou·te·s les utilisateur·rice·s"
|
||||
original-users: "Utilisateur·rice·s sur cette instance"
|
||||
all-notes: "Toutes les publications"
|
||||
original-notes: "Publication sur cette instance"
|
||||
invite: "Invitation"
|
||||
desktop/views/pages/admin/admin.suspend-user.vue:
|
||||
suspend-user: "ユーザーの凍結"
|
||||
suspend: "凍結"
|
||||
suspended: "凍結しました"
|
||||
suspend-user: "Suspendre un·e utilisateur·rice"
|
||||
suspend: "Suspendre"
|
||||
suspended: "Suspendu avec succès"
|
||||
desktop/views/pages/admin/admin.unsuspend-user.vue:
|
||||
unsuspend-user: "ユーザーの凍結の解除"
|
||||
unsuspend: "凍結の解除"
|
||||
unsuspended: "凍結を解除しました"
|
||||
unsuspend-user: "Lever la suspension d’utilisateur·rice·s"
|
||||
unsuspend: "Suspension levée"
|
||||
unsuspended: "La suspension de l’utilisateur·rice a été levée avec succès"
|
||||
desktop/views/pages/admin/admin.verify-user.vue:
|
||||
verify-user: "ユーザーの公式アカウント設定"
|
||||
verify: "Vérification du compte"
|
||||
verified: "Le compte a été vérifié"
|
||||
desktop/views/pages/admin/admin.unverify-user.vue:
|
||||
unverify-user: "ユーザーの公式アカウント解除"
|
||||
unverify: "公式アカウントを解除する"
|
||||
unverified: "公式アカウントを解除しました"
|
||||
desktop/views/pages/admin/admin.notes-chart.vue:
|
||||
title: "投稿"
|
||||
local: "ローカル"
|
||||
remote: "リモート"
|
||||
desktop/views/pages/admin/admin.users-chart.vue:
|
||||
title: "ユーザー"
|
||||
local: "ローカル"
|
||||
remote: "リモート"
|
||||
desktop/views/pages/admin/admin.drive-chart.vue:
|
||||
title: "ドライブ"
|
||||
local: "ローカル"
|
||||
remote: "リモート"
|
||||
desktop/views/pages/deck/deck.tl-column.vue:
|
||||
is-media-only: "Les publications médias uniquement"
|
||||
is-media-view: "Vue média"
|
||||
@ -838,7 +862,7 @@ desktop/views/pages/selectdrive.vue:
|
||||
cancel: "Annuler"
|
||||
upload: "Uploader un ou plusieurs fichier(s) depuis votre PC"
|
||||
desktop/views/pages/search.vue:
|
||||
not-available: "Vous ne pouvez pas utiliser la fonctionnalité de recherche."
|
||||
not-available: "検索機能はインスタンスの設定で無効になっています。"
|
||||
not-found: "Aucun message trouvé pour '{}'"
|
||||
desktop/views/pages/share.vue:
|
||||
share-with: "Partager avec {}"
|
||||
@ -931,12 +955,15 @@ mobile/views/components/drive-file-chooser.vue:
|
||||
select-file: "Choisissez un fichier"
|
||||
mobile/views/components/drive-folder-chooser.vue:
|
||||
select-folder: "Choisissez un dossier"
|
||||
mobile/views/components/drive.file.vue:
|
||||
nsfw: "閲覧注意"
|
||||
mobile/views/components/drive.file-detail.vue:
|
||||
download: "Télécharger"
|
||||
rename: "Renommer"
|
||||
move: "Déplacer"
|
||||
hash: "Hash (md5)"
|
||||
exif: "EXIF"
|
||||
nsfw: "閲覧注意"
|
||||
mobile/views/components/media-image.vue:
|
||||
sensitive: "Le contenu est NSFW"
|
||||
click-to-show: "Cliquer pour afficher"
|
||||
@ -1176,14 +1203,14 @@ docs:
|
||||
params: "Paramètres"
|
||||
no-params: "Aucun paramètre"
|
||||
res: "Réponse"
|
||||
require-credential: "このエンドポイントは認証情報が必須です。"
|
||||
require-permission: "このエンドポイントは{permission}の権限を必要とします。"
|
||||
require-credential: "Ce point de communication nécessite une authentification."
|
||||
require-permission: "Ce point de communication nécessite la permission {permission}."
|
||||
has-limit: "レートリミットがあります。"
|
||||
duration-limit: "直近{duration}ミリ秒の間のこのエンドポイントへのリクエスト数の合計が{max}を超える場合はリクエストできません。"
|
||||
min-interval-limit: "前回のリクエストから{interval}ミリ秒経っていない場合はリクエストできません。"
|
||||
show-src: "このエンドポイントのソースコードも閲覧できます。"
|
||||
show-src: "Vous pouvez voir le code source ce point de communication."
|
||||
show-src-link: "Consulter le code sur GitHub"
|
||||
generated: "このドキュメントはAPI定義に基づき自動生成されています。"
|
||||
generated: "Ce document est généré à partir de la définition de l’API."
|
||||
props:
|
||||
name: "Nom"
|
||||
type: "Type"
|
@ -8,15 +8,16 @@ const yaml = require('js-yaml');
|
||||
const loadLang = lang => yaml.safeLoad(
|
||||
fs.readFileSync(`${__dirname}/${lang}.yml`, 'utf-8'));
|
||||
|
||||
const native = loadLang('ja');
|
||||
const native = loadLang('ja-JP');
|
||||
|
||||
const langs = {
|
||||
'de': loadLang('de'),
|
||||
'en': loadLang('en'),
|
||||
'fr': loadLang('fr'),
|
||||
'ja': native,
|
||||
'pl': loadLang('pl'),
|
||||
'es': loadLang('es')
|
||||
'de-DE': loadLang('de-DE'),
|
||||
'en-US': loadLang('en-US'),
|
||||
'fr-FR': loadLang('fr-FR'),
|
||||
'ja-JP': native,
|
||||
'ja-KS': loadLang('ja-KS'),
|
||||
'pl-PL': loadLang('pl-PL'),
|
||||
'es-ES': loadLang('es-ES')
|
||||
};
|
||||
|
||||
Object.values(langs).forEach(locale => {
|
||||
|
@ -58,7 +58,7 @@ common:
|
||||
friday: "金曜日"
|
||||
saturday: "土曜日"
|
||||
reactions:
|
||||
like: "いいね"
|
||||
like: "ええやん"
|
||||
love: "しゅき"
|
||||
laugh: "笑"
|
||||
hmm: "ふぅ~む"
|
||||
@ -289,6 +289,8 @@ common/views/components/signin.vue:
|
||||
signin-with-twitter: "Twitterでログイン"
|
||||
login-failed: "ログインできませんでした。ユーザー名とパスワードを確認してください。"
|
||||
common/views/components/signup.vue:
|
||||
invitation-code: "招待コード"
|
||||
invitation-info: "招待コードをお持ちでない方は、<a href=\"{}\">管理者</a>までご連絡ください。"
|
||||
username: "ユーザー名"
|
||||
checking: "確認しています..."
|
||||
available: "利用できます"
|
||||
@ -441,6 +443,7 @@ desktop/views/components/drive-window.vue:
|
||||
desktop/views/components/drive.file.vue:
|
||||
avatar: "アイコン"
|
||||
banner: "バナー"
|
||||
nsfw: "閲覧注意"
|
||||
contextmenu:
|
||||
rename: "名前を変更"
|
||||
mark-as-sensitive: "閲覧注意に設定"
|
||||
@ -798,6 +801,7 @@ desktop/views/pages/admin/admin.dashboard.vue:
|
||||
original-users: "このインスタンスのユーザー"
|
||||
all-notes: "全てのノート"
|
||||
original-notes: "このインスタンスのノート"
|
||||
invite: "招待"
|
||||
desktop/views/pages/admin/admin.suspend-user.vue:
|
||||
suspend-user: "ユーザーの凍結"
|
||||
suspend: "凍結"
|
||||
@ -806,6 +810,26 @@ desktop/views/pages/admin/admin.unsuspend-user.vue:
|
||||
unsuspend-user: "ユーザーの凍結の解除"
|
||||
unsuspend: "凍結の解除"
|
||||
unsuspended: "凍結を解除しました"
|
||||
desktop/views/pages/admin/admin.verify-user.vue:
|
||||
verify-user: "ユーザーの公式アカウント設定"
|
||||
verify: "公式アカウントにする"
|
||||
verified: "公式アカウントにしました"
|
||||
desktop/views/pages/admin/admin.unverify-user.vue:
|
||||
unverify-user: "ユーザーの公式アカウント解除"
|
||||
unverify: "公式アカウントを解除する"
|
||||
unverified: "公式アカウントを解除しました"
|
||||
desktop/views/pages/admin/admin.notes-chart.vue:
|
||||
title: "投稿"
|
||||
local: "ローカル"
|
||||
remote: "リモート"
|
||||
desktop/views/pages/admin/admin.users-chart.vue:
|
||||
title: "ユーザー"
|
||||
local: "ローカル"
|
||||
remote: "リモート"
|
||||
desktop/views/pages/admin/admin.drive-chart.vue:
|
||||
title: "ドライブ"
|
||||
local: "ローカル"
|
||||
remote: "リモート"
|
||||
desktop/views/pages/deck/deck.tl-column.vue:
|
||||
is-media-only: "メディア投稿のみ"
|
||||
is-media-view: "メディアビュー"
|
||||
@ -838,7 +862,7 @@ desktop/views/pages/selectdrive.vue:
|
||||
cancel: "キャンセル"
|
||||
upload: "PCからドライブにファイルをアップロード"
|
||||
desktop/views/pages/search.vue:
|
||||
not-available: "検索機能を利用することができません。"
|
||||
not-available: "検索機能はインスタンスの設定で無効になっています。"
|
||||
not-found: "「{}」に関する投稿は見つかりませんでした。"
|
||||
desktop/views/pages/share.vue:
|
||||
share-with: "{}で共有"
|
||||
@ -931,12 +955,15 @@ mobile/views/components/drive-file-chooser.vue:
|
||||
select-file: "ファイルを選択"
|
||||
mobile/views/components/drive-folder-chooser.vue:
|
||||
select-folder: "フォルダーを選択"
|
||||
mobile/views/components/drive.file.vue:
|
||||
nsfw: "閲覧注意"
|
||||
mobile/views/components/drive.file-detail.vue:
|
||||
download: "ダウンロード"
|
||||
rename: "名前を変更"
|
||||
move: "移動"
|
||||
hash: "ハッシュ (md5)"
|
||||
exif: "EXIF"
|
||||
nsfw: "閲覧注意"
|
||||
mobile/views/components/media-image.vue:
|
||||
sensitive: "閲覧注意"
|
||||
click-to-show: "クリックして表示"
|
File diff suppressed because it is too large
Load Diff
@ -1,33 +1,33 @@
|
||||
---
|
||||
meta:
|
||||
lang: "Português"
|
||||
lang: "日本語 (関西弁)"
|
||||
divider: ""
|
||||
common:
|
||||
misskey: "A ⭐ of fediverse"
|
||||
about-title: "A ⭐ of fediverse."
|
||||
about: "Misskeyを見つけていただき、ありがとうございます。Misskeyは、地球で生まれた<b>分散マイクロブログSNS</b>です。Fediverse(様々なSNSで構成される宇宙)の中に存在するため、他のSNSと相互に繋がっています。暫し都会の喧騒から離れて、新しいインターネットにダイブしてみませんか。"
|
||||
about: "ようMisskeyを見つけてくれて、おおきにやで。Misskeyは、地球で生まれた<b>分散マイクロブログSNS</b>やねん。Fediverse(ぎょうさんのSNSで構成されとる宇宙)っちゅうもんの中におるから、お隣さんのSNSとも仲良うさせてもろてんねん。ちょいとやかましい心斎橋から離れて、新しいインターネットにダイブしてみぃひん?"
|
||||
adblock:
|
||||
detected: "広告ブロッカーを無効にしてください"
|
||||
warning: "<strong>Misskeyは広告を掲載していません</strong>が、広告をブロックする機能が有効だと一部の機能が利用できなかったり、不具合が発生する場合があります。"
|
||||
detected: "広告ブロッカーを無効にしてや"
|
||||
warning: "<strong>Misskeyは広告を掲載してへん</strong>けど、広告をブロックしはる機能がおると一部の機能が利用できんくなったり、不具合が発生するかも分からん。知らんけど。"
|
||||
application-authorization: "アプリの連携"
|
||||
close: "閉じる"
|
||||
do-not-copy-paste: "ここにコードを入力したり張り付けたりしないでください。アカウントが不正利用される可能性があります。"
|
||||
got-it: "わかった"
|
||||
close: "さいなら"
|
||||
do-not-copy-paste: "ここにコードを入力したり張り付けたりせんといてください。アカウントが不正利用されるかも分からん。知らんけど。"
|
||||
got-it: "ほい"
|
||||
customization-tips:
|
||||
title: "カスタマイズのヒント"
|
||||
paragraph1: "ホームのカスタマイズでは、ウィジェットを追加/削除したり、ドラッグ&ドロップして並べ替えたりすることができます。"
|
||||
paragraph2: "一部のウィジェットは、<strong><strong>右</strong>クリック</strong>することで表示を変更することができます。"
|
||||
paragraph3: "ウィジェットを削除するには、ヘッダーの<strong>「ゴミ箱」</strong>と書かれたエリアにウィジェットをドラッグ&ドロップします。"
|
||||
paragraph4: "カスタマイズを終了するには、右上の「完了」をクリックします。"
|
||||
paragraph1: "ホームのカスタマイズやと、ウィジェットを追加/削除したり、ドラッグ&ドロップして並べ替えたりできんねやわ。"
|
||||
paragraph2: "一部のウィジェットは、<strong><strong>右</strong>クリック</strong>したったら表示を変更できんねやわ。"
|
||||
paragraph3: "ウィジェットを削除するんやったら、ヘッダーの<strong>「ゴミ箱」</strong>と書いたぁるエリアにウィジェットをドラッグ&ドロップしてな。"
|
||||
paragraph4: "カスタマイズを終了するんやったら、右上の「完了」をクリックしてな。"
|
||||
gotit: "Got it!"
|
||||
notification:
|
||||
file-uploaded: "ファイルがアップロードされました"
|
||||
message-from: "{}さんからメッセージ:"
|
||||
reversi-invited: "対局への招待があります"
|
||||
reversi-invited-by: "{}さんから"
|
||||
notified-by: "{}さんから"
|
||||
reply-from: "{}さんから返信:"
|
||||
quoted-by: "{}さんが引用:"
|
||||
file-uploaded: "ファイルがアップロードされたで"
|
||||
message-from: "{}はんからメッセージ:"
|
||||
reversi-invited: "対局への招待がきとるで"
|
||||
reversi-invited-by: "{}はんから"
|
||||
notified-by: "{}はんから"
|
||||
reply-from: "{}はんから返信:"
|
||||
quoted-by: "{}はんが引用:"
|
||||
time:
|
||||
unknown: "なぞのじかん"
|
||||
future: "未来"
|
||||
@ -58,41 +58,41 @@ common:
|
||||
friday: "金曜日"
|
||||
saturday: "土曜日"
|
||||
reactions:
|
||||
like: "いいね"
|
||||
love: "しゅき"
|
||||
laugh: "笑"
|
||||
like: "ええやん"
|
||||
love: "好きやねん"
|
||||
laugh: "わろた"
|
||||
hmm: "ふぅ~む"
|
||||
surprise: "わお"
|
||||
congrats: "おめでとう"
|
||||
angry: "おこ"
|
||||
confused: "こまこまのこまり"
|
||||
congrats: "おめでとうさん"
|
||||
angry: "何言うてまんねん"
|
||||
confused: "こまこまのこまりやわぁ"
|
||||
rip: "RIP"
|
||||
pudding: "Pudding"
|
||||
pudding: "アメちゃんちゃうんちゃう?"
|
||||
note-placeholders:
|
||||
a: "今どうしてる?"
|
||||
b: "何かありましたか?"
|
||||
c: "何をお考えですか?"
|
||||
d: "言いたいことは?"
|
||||
e: "ここに書いてください"
|
||||
f: "あなたが書くのを待っています..."
|
||||
a: "今なにしてん?"
|
||||
b: "何かあったんか?"
|
||||
c: "何考えとりますん?"
|
||||
d: "言うときたいことは?"
|
||||
e: "ここに書いてや"
|
||||
f: "あんさんが書くんを待っちょります..."
|
||||
search: "検索"
|
||||
delete: "削除"
|
||||
loading: "読み込み中"
|
||||
ok: "わかった"
|
||||
update-available-title: "更新があります"
|
||||
update-available: "Misskeyの新しいバージョンがあります({newer}。現在{current}を利用中)。ページを再度読み込みすると更新が適用されます。"
|
||||
my-token-regenerated: "あなたのトークンが更新されたのでサインアウトします。"
|
||||
i-like-sushi: "私は(プリンよりむしろ)寿司が好き"
|
||||
show-reversi-board-labels: "リバーシのボードの行と列のラベルを表示"
|
||||
verified-user: "公式アカウント"
|
||||
disable-animated-mfm: "投稿内の動きのあるテキストを無効にする"
|
||||
ok: "ほい"
|
||||
update-available-title: "更新があんで"
|
||||
update-available: "Misskeyの新しいバージョンがあんで({newer}。現在{current}をつこてるわ)。ページを再度読み込みしたると更新が適用されるわ。"
|
||||
my-token-regenerated: "あんさんのトークンが更新されたらしいわ。すまんがとりあえずサインアウトすんで。"
|
||||
i-like-sushi: "寿司(のほうがプリンよりむしろ)ウマい、タコ焼きはあらへんけど。"
|
||||
show-reversi-board-labels: "リバーシのボードの行と列のラベルを表示や!"
|
||||
verified-user: "アメちゃん付きアカウント"
|
||||
disable-animated-mfm: "投稿内のちょろちょろ動いてんのを止める"
|
||||
reversi:
|
||||
drawn: "引き分け"
|
||||
my-turn: "あなたのターンです"
|
||||
opponent-turn: "相手のターンです"
|
||||
turn-of: "{}のターンです"
|
||||
drawn: "おあいこ"
|
||||
my-turn: "あんさんのターンや"
|
||||
opponent-turn: "相手のターンや"
|
||||
turn-of: "{}のターンや"
|
||||
past-turn-of: "{}のターン"
|
||||
won: "{}の勝ち"
|
||||
won: "{}の勝ちや!"
|
||||
black: "黒"
|
||||
white: "白"
|
||||
total: "合計"
|
||||
@ -123,67 +123,67 @@ common:
|
||||
hashtags: "ハッシュタグ"
|
||||
deck:
|
||||
widgets: "ウィジェット"
|
||||
home: "ホーム"
|
||||
home: "うち"
|
||||
local: "ローカル"
|
||||
hybrid: "ソーシャル"
|
||||
global: "グローバル"
|
||||
notifications: "通知"
|
||||
list: "リスト"
|
||||
swap-left: "左に移動"
|
||||
swap-right: "右に移動"
|
||||
swap-up: "上に移動"
|
||||
swap-down: "下に移動"
|
||||
remove: "カラムを削除"
|
||||
add-column: "カラムを追加"
|
||||
rename: "名前を変更"
|
||||
stack-left: "左に重ねる"
|
||||
pop-right: "右に出す"
|
||||
swap-left: "左に移動や!"
|
||||
swap-right: "右に移動や!"
|
||||
swap-up: "上に移動!"
|
||||
swap-down: "下に移動!"
|
||||
remove: "カラムを削除や!"
|
||||
add-column: "カラムを追加!"
|
||||
rename: "名前を変更や!"
|
||||
stack-left: "左に重ねんで!"
|
||||
pop-right: "右に出すで!"
|
||||
auth/views/form.vue:
|
||||
share-access: "<i>{{ app.name }}</i>があなたのアカウントにアクセスすることを<b>許可</b>しますか?"
|
||||
permission-ask: "このアプリは次の権限を要求しています:"
|
||||
account-read: "アカウントの情報を見る。"
|
||||
account-write: "アカウントの情報を操作する。"
|
||||
note-write: "投稿する。"
|
||||
like-write: "いいねしたりいいね解除する。"
|
||||
following-write: "フォローしたりフォロー解除する。"
|
||||
drive-read: "ドライブを見る。"
|
||||
drive-write: "ドライブを操作する。"
|
||||
notification-read: "通知を見る。"
|
||||
notification-write: "通知を操作する。"
|
||||
cancel: "キャンセル"
|
||||
accept: "アクセスを許可"
|
||||
share-access: "<i>{{ app.name }}</i>があんさんのアカウントにアクセスすんのを<b>許可</b>してもええか?"
|
||||
permission-ask: "このアプリは次の権限を要求してんで:"
|
||||
account-read: "アカウントの情報を見させてもらうで。"
|
||||
account-write: "アカウントの情報を操作させてもらうで。"
|
||||
note-write: "投稿させてもらうで。"
|
||||
like-write: "いいねしたりいいね解除させてもらうで。"
|
||||
following-write: "フォローしたりフォロー解除させてもらうで。"
|
||||
drive-read: "ドライブを見させてもらうで。"
|
||||
drive-write: "ドライブを操作させてもらうで。"
|
||||
notification-read: "通知を見させてもらうで。"
|
||||
notification-write: "通知を操作させてもらうで。"
|
||||
cancel: "やめとくわ"
|
||||
accept: "アクセスを許可や!"
|
||||
auth/views/index.vue:
|
||||
loading: "読み込み中"
|
||||
denied: "アプリケーションの連携をキャンセルしました。"
|
||||
denied-paragraph: "このアプリがあなたのアカウントにアクセスすることはありません。"
|
||||
already-authorized: "このアプリは既に連携済みです"
|
||||
allowed: "アプリケーションの連携を許可しました"
|
||||
callback-url: "アプリケーションに戻っています"
|
||||
please-go-back: "アプリケーションに戻って、やっていってください。"
|
||||
error: "セッションが存在しません。"
|
||||
sign-in: "サインインしてください"
|
||||
denied: "アプリケーションの連携をやめといたわ。"
|
||||
denied-paragraph: "このアプリがあんさんのアカウントにアクセスすることは多分あらへん。知らんけど。"
|
||||
already-authorized: "このアプリはもう連携済みやったわ"
|
||||
allowed: "アプリケーションの連携を許可したで"
|
||||
callback-url: "アプリケーションに戻っとります"
|
||||
please-go-back: "アプリケーションに戻って、気張ってってな。"
|
||||
error: "セッションが存在してへん。"
|
||||
sign-in: "サインインしてや"
|
||||
common/views/components/games/reversi/reversi.vue:
|
||||
matching:
|
||||
waiting-for: "{}を待っています"
|
||||
cancel: "キャンセル"
|
||||
waiting-for: "{}を待っとります"
|
||||
cancel: "やめとくわ"
|
||||
common/views/components/games/reversi/reversi.game.vue:
|
||||
surrender: "投了"
|
||||
surrender: "投了や..."
|
||||
surrendered: "投了により"
|
||||
is-llotheo: "石の少ない方が勝ち(ロセオ)"
|
||||
looped-map: "ループマップ"
|
||||
can-put-everywhere: "どこでも置けるモード"
|
||||
can-put-everywhere: "どこに置いてもええモード"
|
||||
common/views/components/games/reversi/reversi.index.vue:
|
||||
title: "Misskey Reversi"
|
||||
sub-title: "他のMisskeyユーザーとリバーシで対戦しよう"
|
||||
sub-title: "お隣のミスキストはんらとリバーシで対戦や!"
|
||||
invite: "招待"
|
||||
rule: "遊び方"
|
||||
rule-desc: "リバーシは、相手と交互に石をボードに置いて、相手の石を挟んで自分の色に変えてゆき、最終的に残った石が多い方が勝ちというボードゲームです。"
|
||||
rule-desc: "リバーシは、相手と交互に石をボードに置いて、相手の石を挟んで自分の色に変えてって、最終的に残った石が多い方が勝ちっちゅうボードゲームや。"
|
||||
mode-invite: "招待"
|
||||
mode-invite-desc: "指定したユーザーと対戦するモードです。"
|
||||
invitations: "対局の招待があります!"
|
||||
mode-invite-desc: "指定したユーザーと対戦するモードや。"
|
||||
invitations: "対局の招待がきてんで!"
|
||||
my-games: "自分の対局"
|
||||
all-games: "みんなの対局"
|
||||
enter-username: "ユーザー名を入力してください"
|
||||
enter-username: "ユーザー名を入力してや"
|
||||
game-state:
|
||||
ended: "終了"
|
||||
playing: "進行中"
|
||||
@ -202,7 +202,7 @@ common/views/components/games/reversi/reversi.room.vue:
|
||||
waiting-for-other: "相手の準備が完了するのを待っています"
|
||||
waiting-for-me: "あなたの準備が完了するのを待っています"
|
||||
waiting-for-both: "準備中"
|
||||
cancel: "キャンセル"
|
||||
cancel: "やめとくわ"
|
||||
ready: "準備完了"
|
||||
cancel-ready: "準備続行"
|
||||
common/views/components/connect-failed.vue:
|
||||
@ -289,6 +289,8 @@ common/views/components/signin.vue:
|
||||
signin-with-twitter: "Twitterでログイン"
|
||||
login-failed: "ログインできませんでした。ユーザー名とパスワードを確認してください。"
|
||||
common/views/components/signup.vue:
|
||||
invitation-code: "招待コード"
|
||||
invitation-info: "招待コードをお持ちでない方は、<a href=\"{}\">管理者</a>までご連絡ください。"
|
||||
username: "ユーザー名"
|
||||
checking: "確認しています..."
|
||||
available: "利用できます"
|
||||
@ -424,16 +426,16 @@ desktop/views/components/calendar.vue:
|
||||
desktop/views/components/choose-file-from-drive-window.vue:
|
||||
choose-file: "ファイル選択中"
|
||||
upload: "PCからドライブにファイルをアップロード"
|
||||
cancel: "キャンセル"
|
||||
cancel: "やめとくわ"
|
||||
ok: "決定"
|
||||
choose-prompt: "ファイルを選択"
|
||||
desktop/views/components/choose-folder-from-drive-window.vue:
|
||||
cancel: "キャンセル"
|
||||
cancel: "やめとくわ"
|
||||
ok: "決定"
|
||||
choose-prompt: "フォルダを選択"
|
||||
desktop/views/components/crop-window.vue:
|
||||
skip: "クロップをスキップ"
|
||||
cancel: "キャンセル"
|
||||
cancel: "やめとくわ"
|
||||
ok: "決定"
|
||||
desktop/views/components/drive-window.vue:
|
||||
used: "使用中"
|
||||
@ -441,6 +443,7 @@ desktop/views/components/drive-window.vue:
|
||||
desktop/views/components/drive.file.vue:
|
||||
avatar: "アイコン"
|
||||
banner: "バナー"
|
||||
nsfw: "閲覧注意"
|
||||
contextmenu:
|
||||
rename: "名前を変更"
|
||||
mark-as-sensitive: "閲覧注意に設定"
|
||||
@ -520,7 +523,7 @@ desktop/views/components/home.vue:
|
||||
add-widget: "ウィジェットを追加:"
|
||||
add: "追加"
|
||||
desktop/views/input-dialog.vue:
|
||||
cancel: "キャンセル"
|
||||
cancel: "やめとくわ"
|
||||
ok: "決定"
|
||||
desktop/views/components/messaging-room-window.vue:
|
||||
title: "メッセージ:"
|
||||
@ -589,7 +592,7 @@ desktop/views/components/progress-dialog.vue:
|
||||
waiting: "待機中"
|
||||
desktop/views/components/renote-form.vue:
|
||||
quote: "引用する..."
|
||||
cancel: "キャンセル"
|
||||
cancel: "やめとくわ"
|
||||
renote: "Renote"
|
||||
reposting: "しています..."
|
||||
success: "Renoteしました!"
|
||||
@ -798,6 +801,7 @@ desktop/views/pages/admin/admin.dashboard.vue:
|
||||
original-users: "このインスタンスのユーザー"
|
||||
all-notes: "全てのノート"
|
||||
original-notes: "このインスタンスのノート"
|
||||
invite: "招待"
|
||||
desktop/views/pages/admin/admin.suspend-user.vue:
|
||||
suspend-user: "ユーザーの凍結"
|
||||
suspend: "凍結"
|
||||
@ -806,6 +810,26 @@ desktop/views/pages/admin/admin.unsuspend-user.vue:
|
||||
unsuspend-user: "ユーザーの凍結の解除"
|
||||
unsuspend: "凍結の解除"
|
||||
unsuspended: "凍結を解除しました"
|
||||
desktop/views/pages/admin/admin.verify-user.vue:
|
||||
verify-user: "ユーザーの公式アカウント設定"
|
||||
verify: "公式アカウントにする"
|
||||
verified: "公式アカウントにしました"
|
||||
desktop/views/pages/admin/admin.unverify-user.vue:
|
||||
unverify-user: "ユーザーの公式アカウント解除"
|
||||
unverify: "公式アカウントを解除する"
|
||||
unverified: "公式アカウントを解除しました"
|
||||
desktop/views/pages/admin/admin.notes-chart.vue:
|
||||
title: "投稿"
|
||||
local: "ローカル"
|
||||
remote: "リモート"
|
||||
desktop/views/pages/admin/admin.users-chart.vue:
|
||||
title: "ユーザー"
|
||||
local: "ローカル"
|
||||
remote: "リモート"
|
||||
desktop/views/pages/admin/admin.drive-chart.vue:
|
||||
title: "ドライブ"
|
||||
local: "ローカル"
|
||||
remote: "リモート"
|
||||
desktop/views/pages/deck/deck.tl-column.vue:
|
||||
is-media-only: "メディア投稿のみ"
|
||||
is-media-view: "メディアビュー"
|
||||
@ -835,10 +859,10 @@ desktop/views/pages/note.vue:
|
||||
desktop/views/pages/selectdrive.vue:
|
||||
title: "ファイルを選択してください"
|
||||
ok: "決定"
|
||||
cancel: "キャンセル"
|
||||
cancel: "やめとくわ"
|
||||
upload: "PCからドライブにファイルをアップロード"
|
||||
desktop/views/pages/search.vue:
|
||||
not-available: "検索機能を利用することができません。"
|
||||
not-available: "検索機能はインスタンスの設定で無効になっています。"
|
||||
not-found: "「{}」に関する投稿は見つかりませんでした。"
|
||||
desktop/views/pages/share.vue:
|
||||
share-with: "{}で共有"
|
||||
@ -931,12 +955,15 @@ mobile/views/components/drive-file-chooser.vue:
|
||||
select-file: "ファイルを選択"
|
||||
mobile/views/components/drive-folder-chooser.vue:
|
||||
select-folder: "フォルダーを選択"
|
||||
mobile/views/components/drive.file.vue:
|
||||
nsfw: "閲覧注意"
|
||||
mobile/views/components/drive.file-detail.vue:
|
||||
download: "ダウンロード"
|
||||
rename: "名前を変更"
|
||||
move: "移動"
|
||||
hash: "ハッシュ (md5)"
|
||||
exif: "EXIF"
|
||||
nsfw: "閲覧注意"
|
||||
mobile/views/components/media-image.vue:
|
||||
sensitive: "閲覧注意"
|
||||
click-to-show: "クリックして表示"
|
@ -58,7 +58,7 @@ common:
|
||||
friday: "금요일"
|
||||
saturday: "토요일"
|
||||
reactions:
|
||||
like: "좋네"
|
||||
like: "ええやん"
|
||||
love: "좋아"
|
||||
laugh: "크크"
|
||||
hmm: "음..."
|
||||
@ -289,6 +289,8 @@ common/views/components/signin.vue:
|
||||
signin-with-twitter: "Twitterでログイン"
|
||||
login-failed: "ログインできませんでした。ユーザー名とパスワードを確認してください。"
|
||||
common/views/components/signup.vue:
|
||||
invitation-code: "招待コード"
|
||||
invitation-info: "招待コードをお持ちでない方は、<a href=\"{}\">管理者</a>までご連絡ください。"
|
||||
username: "ユーザー名"
|
||||
checking: "確認しています..."
|
||||
available: "利用できます"
|
||||
@ -441,6 +443,7 @@ desktop/views/components/drive-window.vue:
|
||||
desktop/views/components/drive.file.vue:
|
||||
avatar: "アイコン"
|
||||
banner: "バナー"
|
||||
nsfw: "閲覧注意"
|
||||
contextmenu:
|
||||
rename: "名前を変更"
|
||||
mark-as-sensitive: "閲覧注意に設定"
|
||||
@ -798,6 +801,7 @@ desktop/views/pages/admin/admin.dashboard.vue:
|
||||
original-users: "このインスタンスのユーザー"
|
||||
all-notes: "全てのノート"
|
||||
original-notes: "このインスタンスのノート"
|
||||
invite: "招待"
|
||||
desktop/views/pages/admin/admin.suspend-user.vue:
|
||||
suspend-user: "ユーザーの凍結"
|
||||
suspend: "凍結"
|
||||
@ -806,6 +810,26 @@ desktop/views/pages/admin/admin.unsuspend-user.vue:
|
||||
unsuspend-user: "ユーザーの凍結の解除"
|
||||
unsuspend: "凍結の解除"
|
||||
unsuspended: "凍結を解除しました"
|
||||
desktop/views/pages/admin/admin.verify-user.vue:
|
||||
verify-user: "ユーザーの公式アカウント設定"
|
||||
verify: "公式アカウントにする"
|
||||
verified: "公式アカウントにしました"
|
||||
desktop/views/pages/admin/admin.unverify-user.vue:
|
||||
unverify-user: "ユーザーの公式アカウント解除"
|
||||
unverify: "公式アカウントを解除する"
|
||||
unverified: "公式アカウントを解除しました"
|
||||
desktop/views/pages/admin/admin.notes-chart.vue:
|
||||
title: "投稿"
|
||||
local: "ローカル"
|
||||
remote: "リモート"
|
||||
desktop/views/pages/admin/admin.users-chart.vue:
|
||||
title: "ユーザー"
|
||||
local: "ローカル"
|
||||
remote: "リモート"
|
||||
desktop/views/pages/admin/admin.drive-chart.vue:
|
||||
title: "ドライブ"
|
||||
local: "ローカル"
|
||||
remote: "リモート"
|
||||
desktop/views/pages/deck/deck.tl-column.vue:
|
||||
is-media-only: "メディア投稿のみ"
|
||||
is-media-view: "メディアビュー"
|
||||
@ -838,7 +862,7 @@ desktop/views/pages/selectdrive.vue:
|
||||
cancel: "キャンセル"
|
||||
upload: "PCからドライブにファイルをアップロード"
|
||||
desktop/views/pages/search.vue:
|
||||
not-available: "検索機能を利用することができません。"
|
||||
not-available: "検索機能はインスタンスの設定で無効になっています。"
|
||||
not-found: "「{}」に関する投稿は見つかりませんでした。"
|
||||
desktop/views/pages/share.vue:
|
||||
share-with: "{}で共有"
|
||||
@ -931,12 +955,15 @@ mobile/views/components/drive-file-chooser.vue:
|
||||
select-file: "ファイルを選択"
|
||||
mobile/views/components/drive-folder-chooser.vue:
|
||||
select-folder: "フォルダーを選択"
|
||||
mobile/views/components/drive.file.vue:
|
||||
nsfw: "閲覧注意"
|
||||
mobile/views/components/drive.file-detail.vue:
|
||||
download: "ダウンロード"
|
||||
rename: "名前を変更"
|
||||
move: "移動"
|
||||
hash: "ハッシュ (md5)"
|
||||
exif: "EXIF"
|
||||
nsfw: "閲覧注意"
|
||||
mobile/views/components/media-image.vue:
|
||||
sensitive: "閲覧注意"
|
||||
click-to-show: "クリックして表示"
|
@ -58,7 +58,7 @@ common:
|
||||
friday: "Piątek"
|
||||
saturday: "Sobota"
|
||||
reactions:
|
||||
like: "Lubię"
|
||||
like: "ええやん"
|
||||
love: "Kocham"
|
||||
laugh: "Śmieszne"
|
||||
hmm: "Hmm…?"
|
||||
@ -289,6 +289,8 @@ common/views/components/signin.vue:
|
||||
signin-with-twitter: "Zaloguj się za pomocą Twittera"
|
||||
login-failed: "ログインできませんでした。ユーザー名とパスワードを確認してください。"
|
||||
common/views/components/signup.vue:
|
||||
invitation-code: "招待コード"
|
||||
invitation-info: "招待コードをお持ちでない方は、<a href=\"{}\">管理者</a>までご連絡ください。"
|
||||
username: "Nazwa użytkownika"
|
||||
checking: "Sprawdzanie…"
|
||||
available: "Dostępna"
|
||||
@ -441,6 +443,7 @@ desktop/views/components/drive-window.vue:
|
||||
desktop/views/components/drive.file.vue:
|
||||
avatar: "Awatar"
|
||||
banner: "Baner"
|
||||
nsfw: "閲覧注意"
|
||||
contextmenu:
|
||||
rename: "Zmień nazwę"
|
||||
mark-as-sensitive: "Oznacz jako zawartość wrażliwą"
|
||||
@ -798,6 +801,7 @@ desktop/views/pages/admin/admin.dashboard.vue:
|
||||
original-users: "このインスタンスのユーザー"
|
||||
all-notes: "全てのノート"
|
||||
original-notes: "このインスタンスのノート"
|
||||
invite: "招待"
|
||||
desktop/views/pages/admin/admin.suspend-user.vue:
|
||||
suspend-user: "ユーザーの凍結"
|
||||
suspend: "凍結"
|
||||
@ -806,6 +810,26 @@ desktop/views/pages/admin/admin.unsuspend-user.vue:
|
||||
unsuspend-user: "ユーザーの凍結の解除"
|
||||
unsuspend: "凍結の解除"
|
||||
unsuspended: "凍結を解除しました"
|
||||
desktop/views/pages/admin/admin.verify-user.vue:
|
||||
verify-user: "ユーザーの公式アカウント設定"
|
||||
verify: "公式アカウントにする"
|
||||
verified: "公式アカウントにしました"
|
||||
desktop/views/pages/admin/admin.unverify-user.vue:
|
||||
unverify-user: "ユーザーの公式アカウント解除"
|
||||
unverify: "公式アカウントを解除する"
|
||||
unverified: "公式アカウントを解除しました"
|
||||
desktop/views/pages/admin/admin.notes-chart.vue:
|
||||
title: "投稿"
|
||||
local: "ローカル"
|
||||
remote: "リモート"
|
||||
desktop/views/pages/admin/admin.users-chart.vue:
|
||||
title: "ユーザー"
|
||||
local: "ローカル"
|
||||
remote: "リモート"
|
||||
desktop/views/pages/admin/admin.drive-chart.vue:
|
||||
title: "ドライブ"
|
||||
local: "ローカル"
|
||||
remote: "リモート"
|
||||
desktop/views/pages/deck/deck.tl-column.vue:
|
||||
is-media-only: "Tylko wpisy z zawartością multimedialną"
|
||||
is-media-view: "Widok multimediów"
|
||||
@ -838,7 +862,7 @@ desktop/views/pages/selectdrive.vue:
|
||||
cancel: "Anuluj"
|
||||
upload: "Wyślij pliki z Twojego komputera"
|
||||
desktop/views/pages/search.vue:
|
||||
not-available: "Funkcja wyszukiwania nie może zostać wykorzystywana."
|
||||
not-available: "検索機能はインスタンスの設定で無効になっています。"
|
||||
not-found: "Nie znaleziono wpisów zawierających „{}”"
|
||||
desktop/views/pages/share.vue:
|
||||
share-with: "Udostępnij z {}."
|
||||
@ -931,12 +955,15 @@ mobile/views/components/drive-file-chooser.vue:
|
||||
select-file: "Wybierz plik"
|
||||
mobile/views/components/drive-folder-chooser.vue:
|
||||
select-folder: "Wybierz katalog"
|
||||
mobile/views/components/drive.file.vue:
|
||||
nsfw: "閲覧注意"
|
||||
mobile/views/components/drive.file-detail.vue:
|
||||
download: "Pobierz"
|
||||
rename: "Zmień nazwę"
|
||||
move: "Przenieś"
|
||||
hash: "Hash (md5)"
|
||||
exif: "EXIF"
|
||||
nsfw: "閲覧注意"
|
||||
mobile/views/components/media-image.vue:
|
||||
sensitive: "To jest zawartość NSFW"
|
||||
click-to-show: "Naciśnij aby wyświetlić"
|
1219
locales/pt-PT.yml
Normal file
1219
locales/pt-PT.yml
Normal file
File diff suppressed because it is too large
Load Diff
@ -58,7 +58,7 @@ common:
|
||||
friday: "金曜日"
|
||||
saturday: "土曜日"
|
||||
reactions:
|
||||
like: "いいね"
|
||||
like: "ええやん"
|
||||
love: "しゅき"
|
||||
laugh: "笑"
|
||||
hmm: "ふぅ~む"
|
||||
@ -289,6 +289,8 @@ common/views/components/signin.vue:
|
||||
signin-with-twitter: "Twitterでログイン"
|
||||
login-failed: "ログインできませんでした。ユーザー名とパスワードを確認してください。"
|
||||
common/views/components/signup.vue:
|
||||
invitation-code: "招待コード"
|
||||
invitation-info: "招待コードをお持ちでない方は、<a href=\"{}\">管理者</a>までご連絡ください。"
|
||||
username: "ユーザー名"
|
||||
checking: "確認しています..."
|
||||
available: "利用できます"
|
||||
@ -441,6 +443,7 @@ desktop/views/components/drive-window.vue:
|
||||
desktop/views/components/drive.file.vue:
|
||||
avatar: "アイコン"
|
||||
banner: "バナー"
|
||||
nsfw: "閲覧注意"
|
||||
contextmenu:
|
||||
rename: "名前を変更"
|
||||
mark-as-sensitive: "閲覧注意に設定"
|
||||
@ -798,6 +801,7 @@ desktop/views/pages/admin/admin.dashboard.vue:
|
||||
original-users: "このインスタンスのユーザー"
|
||||
all-notes: "全てのノート"
|
||||
original-notes: "このインスタンスのノート"
|
||||
invite: "招待"
|
||||
desktop/views/pages/admin/admin.suspend-user.vue:
|
||||
suspend-user: "ユーザーの凍結"
|
||||
suspend: "凍結"
|
||||
@ -806,6 +810,26 @@ desktop/views/pages/admin/admin.unsuspend-user.vue:
|
||||
unsuspend-user: "ユーザーの凍結の解除"
|
||||
unsuspend: "凍結の解除"
|
||||
unsuspended: "凍結を解除しました"
|
||||
desktop/views/pages/admin/admin.verify-user.vue:
|
||||
verify-user: "ユーザーの公式アカウント設定"
|
||||
verify: "公式アカウントにする"
|
||||
verified: "公式アカウントにしました"
|
||||
desktop/views/pages/admin/admin.unverify-user.vue:
|
||||
unverify-user: "ユーザーの公式アカウント解除"
|
||||
unverify: "公式アカウントを解除する"
|
||||
unverified: "公式アカウントを解除しました"
|
||||
desktop/views/pages/admin/admin.notes-chart.vue:
|
||||
title: "投稿"
|
||||
local: "ローカル"
|
||||
remote: "リモート"
|
||||
desktop/views/pages/admin/admin.users-chart.vue:
|
||||
title: "ユーザー"
|
||||
local: "ローカル"
|
||||
remote: "リモート"
|
||||
desktop/views/pages/admin/admin.drive-chart.vue:
|
||||
title: "ドライブ"
|
||||
local: "ローカル"
|
||||
remote: "リモート"
|
||||
desktop/views/pages/deck/deck.tl-column.vue:
|
||||
is-media-only: "メディア投稿のみ"
|
||||
is-media-view: "メディアビュー"
|
||||
@ -838,7 +862,7 @@ desktop/views/pages/selectdrive.vue:
|
||||
cancel: "キャンセル"
|
||||
upload: "PCからドライブにファイルをアップロード"
|
||||
desktop/views/pages/search.vue:
|
||||
not-available: "検索機能を利用することができません。"
|
||||
not-available: "検索機能はインスタンスの設定で無効になっています。"
|
||||
not-found: "「{}」に関する投稿は見つかりませんでした。"
|
||||
desktop/views/pages/share.vue:
|
||||
share-with: "{}で共有"
|
||||
@ -931,12 +955,15 @@ mobile/views/components/drive-file-chooser.vue:
|
||||
select-file: "ファイルを選択"
|
||||
mobile/views/components/drive-folder-chooser.vue:
|
||||
select-folder: "フォルダーを選択"
|
||||
mobile/views/components/drive.file.vue:
|
||||
nsfw: "閲覧注意"
|
||||
mobile/views/components/drive.file-detail.vue:
|
||||
download: "ダウンロード"
|
||||
rename: "名前を変更"
|
||||
move: "移動"
|
||||
hash: "ハッシュ (md5)"
|
||||
exif: "EXIF"
|
||||
nsfw: "閲覧注意"
|
||||
mobile/views/components/media-image.vue:
|
||||
sensitive: "閲覧注意"
|
||||
click-to-show: "クリックして表示"
|
@ -58,7 +58,7 @@ common:
|
||||
friday: "金曜日"
|
||||
saturday: "土曜日"
|
||||
reactions:
|
||||
like: "いいね"
|
||||
like: "ええやん"
|
||||
love: "しゅき"
|
||||
laugh: "笑"
|
||||
hmm: "ふぅ~む"
|
||||
@ -289,6 +289,8 @@ common/views/components/signin.vue:
|
||||
signin-with-twitter: "Twitterでログイン"
|
||||
login-failed: "ログインできませんでした。ユーザー名とパスワードを確認してください。"
|
||||
common/views/components/signup.vue:
|
||||
invitation-code: "招待コード"
|
||||
invitation-info: "招待コードをお持ちでない方は、<a href=\"{}\">管理者</a>までご連絡ください。"
|
||||
username: "ユーザー名"
|
||||
checking: "確認しています..."
|
||||
available: "利用できます"
|
||||
@ -441,6 +443,7 @@ desktop/views/components/drive-window.vue:
|
||||
desktop/views/components/drive.file.vue:
|
||||
avatar: "アイコン"
|
||||
banner: "バナー"
|
||||
nsfw: "閲覧注意"
|
||||
contextmenu:
|
||||
rename: "名前を変更"
|
||||
mark-as-sensitive: "閲覧注意に設定"
|
||||
@ -798,6 +801,7 @@ desktop/views/pages/admin/admin.dashboard.vue:
|
||||
original-users: "このインスタンスのユーザー"
|
||||
all-notes: "全てのノート"
|
||||
original-notes: "このインスタンスのノート"
|
||||
invite: "招待"
|
||||
desktop/views/pages/admin/admin.suspend-user.vue:
|
||||
suspend-user: "ユーザーの凍結"
|
||||
suspend: "凍結"
|
||||
@ -806,6 +810,26 @@ desktop/views/pages/admin/admin.unsuspend-user.vue:
|
||||
unsuspend-user: "ユーザーの凍結の解除"
|
||||
unsuspend: "凍結の解除"
|
||||
unsuspended: "凍結を解除しました"
|
||||
desktop/views/pages/admin/admin.verify-user.vue:
|
||||
verify-user: "ユーザーの公式アカウント設定"
|
||||
verify: "公式アカウントにする"
|
||||
verified: "公式アカウントにしました"
|
||||
desktop/views/pages/admin/admin.unverify-user.vue:
|
||||
unverify-user: "ユーザーの公式アカウント解除"
|
||||
unverify: "公式アカウントを解除する"
|
||||
unverified: "公式アカウントを解除しました"
|
||||
desktop/views/pages/admin/admin.notes-chart.vue:
|
||||
title: "投稿"
|
||||
local: "ローカル"
|
||||
remote: "リモート"
|
||||
desktop/views/pages/admin/admin.users-chart.vue:
|
||||
title: "ユーザー"
|
||||
local: "ローカル"
|
||||
remote: "リモート"
|
||||
desktop/views/pages/admin/admin.drive-chart.vue:
|
||||
title: "ドライブ"
|
||||
local: "ローカル"
|
||||
remote: "リモート"
|
||||
desktop/views/pages/deck/deck.tl-column.vue:
|
||||
is-media-only: "メディア投稿のみ"
|
||||
is-media-view: "メディアビュー"
|
||||
@ -838,7 +862,7 @@ desktop/views/pages/selectdrive.vue:
|
||||
cancel: "キャンセル"
|
||||
upload: "PCからドライブにファイルをアップロード"
|
||||
desktop/views/pages/search.vue:
|
||||
not-available: "検索機能を利用することができません。"
|
||||
not-available: "検索機能はインスタンスの設定で無効になっています。"
|
||||
not-found: "「{}」に関する投稿は見つかりませんでした。"
|
||||
desktop/views/pages/share.vue:
|
||||
share-with: "{}で共有"
|
||||
@ -931,12 +955,15 @@ mobile/views/components/drive-file-chooser.vue:
|
||||
select-file: "ファイルを選択"
|
||||
mobile/views/components/drive-folder-chooser.vue:
|
||||
select-folder: "フォルダーを選択"
|
||||
mobile/views/components/drive.file.vue:
|
||||
nsfw: "閲覧注意"
|
||||
mobile/views/components/drive.file-detail.vue:
|
||||
download: "ダウンロード"
|
||||
rename: "名前を変更"
|
||||
move: "移動"
|
||||
hash: "ハッシュ (md5)"
|
||||
exif: "EXIF"
|
||||
nsfw: "閲覧注意"
|
||||
mobile/views/components/media-image.vue:
|
||||
sensitive: "閲覧注意"
|
||||
click-to-show: "クリックして表示"
|
17
package.json
17
package.json
@ -1,8 +1,8 @@
|
||||
{
|
||||
"name": "misskey",
|
||||
"author": "syuilo <i@syuilo.com>",
|
||||
"version": "6.3.2",
|
||||
"clientVersion": "1.0.8498",
|
||||
"version": "8.0.0",
|
||||
"clientVersion": "1.0.8790",
|
||||
"codename": "nighthike",
|
||||
"main": "./built/index.js",
|
||||
"private": true,
|
||||
@ -126,7 +126,7 @@
|
||||
"gulp-util": "3.0.8",
|
||||
"hard-source-webpack-plugin": "0.12.0",
|
||||
"highlight.js": "9.12.0",
|
||||
"html-minifier": "3.5.19",
|
||||
"html-minifier": "3.5.20",
|
||||
"http-signature": "1.2.0",
|
||||
"insert-text-at-cursor": "0.1.1",
|
||||
"is-root": "2.0.0",
|
||||
@ -157,6 +157,7 @@
|
||||
"monk": "6.0.6",
|
||||
"ms": "2.1.1",
|
||||
"nan": "2.10.0",
|
||||
"nested-property": "0.0.7",
|
||||
"node-sass": "4.9.3",
|
||||
"node-sass-json-importer": "3.3.1",
|
||||
"nprogress": "0.2.0",
|
||||
@ -181,7 +182,7 @@
|
||||
"s-age": "1.1.2",
|
||||
"sass-loader": "7.1.0",
|
||||
"seedrandom": "2.4.4",
|
||||
"sharp": "0.20.5",
|
||||
"sharp": "0.20.7",
|
||||
"showdown": "1.8.6",
|
||||
"showdown-highlightjs-extension": "0.1.2",
|
||||
"single-line-log": "1.1.2",
|
||||
@ -190,7 +191,7 @@
|
||||
"style-loader": "0.22.1",
|
||||
"stylus": "0.54.5",
|
||||
"stylus-loader": "3.0.2",
|
||||
"summaly": "2.1.3",
|
||||
"summaly": "2.1.4",
|
||||
"systeminformation": "3.42.9",
|
||||
"syuilo-password-strength": "0.0.1",
|
||||
"textarea-caret": "3.1.0",
|
||||
@ -206,9 +207,9 @@
|
||||
"v-animate-css": "0.0.2",
|
||||
"vue": "2.5.17",
|
||||
"vue-cropperjs": "2.2.1",
|
||||
"vue-js-modal": "1.3.17",
|
||||
"vue-js-modal": "1.3.18",
|
||||
"vue-json-tree-view": "2.1.4",
|
||||
"vue-loader": "15.3.0",
|
||||
"vue-loader": "15.4.0",
|
||||
"vue-router": "3.0.1",
|
||||
"vue-style-loader": "4.1.2",
|
||||
"vue-template-compiler": "2.5.17",
|
||||
@ -217,7 +218,7 @@
|
||||
"vuex-persistedstate": "2.5.4",
|
||||
"web-push": "3.3.2",
|
||||
"webfinger.js": "2.6.6",
|
||||
"webpack": "4.16.5",
|
||||
"webpack": "4.17.1",
|
||||
"webpack-cli": "3.1.0",
|
||||
"websocket": "1.0.26",
|
||||
"ws": "6.0.0",
|
||||
|
@ -7,7 +7,7 @@
|
||||
<div class="app">
|
||||
<section>
|
||||
<h2>{{ app.name }}</h2>
|
||||
<p class="nid">{{ app.nameId }}</p>
|
||||
<p class="id">{{ app.id }}</p>
|
||||
<p class="description">{{ app.description }}</p>
|
||||
</section>
|
||||
<section>
|
||||
|
@ -32,16 +32,24 @@
|
||||
//#region Detect app name
|
||||
let app = null;
|
||||
|
||||
if (url.pathname == '/docs' || url.pathname.startsWith('/docs/')) app = 'docs';
|
||||
if (url.pathname == '/dev' || url.pathname.startsWith('/dev/')) app = 'dev';
|
||||
if (url.pathname == '/auth' || url.pathname.startsWith('/auth/')) app = 'auth';
|
||||
if (`${url.pathname}/`.startsWith('/docs/')) app = 'docs';
|
||||
if (`${url.pathname}/`.startsWith('/dev/')) app = 'dev';
|
||||
if (`${url.pathname}/`.startsWith('/auth/')) app = 'auth';
|
||||
//#endregion
|
||||
|
||||
//#region Detect the user language
|
||||
let lang = navigator.language.split('-')[0];
|
||||
let lang = null;
|
||||
|
||||
// The default language is English
|
||||
if (!LANGS.includes(lang)) lang = 'en';
|
||||
if (LANGS.includes(navigator.language)) {
|
||||
lang = navigator.language;
|
||||
} else {
|
||||
lang = LANGS.find(x => x.split('-')[0] == navigator.language);
|
||||
|
||||
if (lang == null) {
|
||||
// Fallback
|
||||
lang = 'en-US';
|
||||
}
|
||||
}
|
||||
|
||||
if (settings) {
|
||||
if (settings.device.lang) lang = settings.device.lang;
|
||||
@ -104,7 +112,7 @@
|
||||
// グローバルにタイマーIDを代入しておく
|
||||
window.mkBootTimer = window.setTimeout(async () => {
|
||||
// Fetch meta
|
||||
const res = await fetch(API + '/meta', {
|
||||
const res = await fetch('/api/meta', {
|
||||
method: 'POST',
|
||||
cache: 'no-cache'
|
||||
});
|
||||
|
10
src/client/app/common/scripts/get-face.ts
Normal file
10
src/client/app/common/scripts/get-face.ts
Normal file
@ -0,0 +1,10 @@
|
||||
const faces = [
|
||||
'(=^・・^=)',
|
||||
'v(\'ω\')v',
|
||||
'🐡( \'-\' 🐡 )フグパンチ!!!!',
|
||||
'🖕(´・_・`)🖕',
|
||||
'(。>﹏<。)',
|
||||
'(Δ・x・Δ)'
|
||||
];
|
||||
|
||||
export default () => faces[Math.floor(Math.random() * faces.length)];
|
@ -1,9 +0,0 @@
|
||||
const kaos = [
|
||||
'(=^・・^=)',
|
||||
'v(\'ω\')v',
|
||||
'🐡( \'-\' 🐡 )フグパンチ!!!!',
|
||||
'🖕(´・_・`)🖕',
|
||||
'(。>﹏<。)'
|
||||
];
|
||||
|
||||
export default () => kaos[Math.floor(Math.random() * kaos.length)];
|
@ -18,11 +18,11 @@
|
||||
</div>
|
||||
|
||||
<div class="board">
|
||||
<div class="labels-x" v-if="this.$store.state.settings.reversiBoardLabels">
|
||||
<div class="labels-x" v-if="this.$store.state.settings.games.reversi.showBoardLabels">
|
||||
<span v-for="i in game.settings.map[0].length">{{ String.fromCharCode(64 + i) }}</span>
|
||||
</div>
|
||||
<div class="flex">
|
||||
<div class="labels-y" v-if="this.$store.state.settings.reversiBoardLabels">
|
||||
<div class="labels-y" v-if="this.$store.state.settings.games.reversi.showBoardLabels">
|
||||
<div v-for="i in game.settings.map.length">{{ i }}</div>
|
||||
</div>
|
||||
<div class="cells" :style="cellsStyle">
|
||||
@ -30,15 +30,15 @@
|
||||
:class="{ empty: stone == null, none: o.map[i] == 'null', isEnded: game.isEnded, myTurn: !game.isEnded && isMyTurn, can: turnUser ? o.canPut(turnUser.id == blackUser.id, i) : null, prev: o.prevPos == i }"
|
||||
@click="set(i)"
|
||||
:title="`${String.fromCharCode(65 + o.transformPosToXy(i)[0])}${o.transformPosToXy(i)[1] + 1}`">
|
||||
<img v-if="stone === true" :src="blackUser.avatarUrl" alt="">
|
||||
<img v-if="stone === false" :src="whiteUser.avatarUrl" alt="">
|
||||
<img v-if="stone === true" :src="blackUser.avatarUrl" alt="black" :class="{ contrast: $store.state.settings.games.reversi.useContrastStones }">
|
||||
<img v-if="stone === false" :src="whiteUser.avatarUrl" alt="white" :class="{ contrast: $store.state.settings.games.reversi.useContrastStones }">
|
||||
</div>
|
||||
</div>
|
||||
<div class="labels-y" v-if="this.$store.state.settings.reversiBoardLabels">
|
||||
<div class="labels-y" v-if="this.$store.state.settings.games.reversi.showBoardLabels">
|
||||
<div v-for="i in game.settings.map.length">{{ i }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="labels-x" v-if="this.$store.state.settings.reversiBoardLabels">
|
||||
<div class="labels-x" v-if="this.$store.state.settings.games.reversi.showBoardLabels">
|
||||
<span v-for="i in game.settings.map[0].length">{{ String.fromCharCode(64 + i) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
@ -421,6 +421,13 @@ root(isDark)
|
||||
width 100%
|
||||
height 100%
|
||||
|
||||
&.contrast
|
||||
&[alt="black"]
|
||||
filter brightness(.5)
|
||||
|
||||
&[alt="white"]
|
||||
filter brightness(2)
|
||||
|
||||
> .graph
|
||||
display grid
|
||||
grid-template-columns repeat(61, 1fr)
|
||||
|
@ -32,6 +32,7 @@
|
||||
<mk-avatar class="avatar" :user="g.user2"/>
|
||||
<span><b>{{ g.user1 | userName }}</b> vs <b>{{ g.user2 | userName }}</b></span>
|
||||
<span class="state">{{ g.isEnded ? '%i18n:@game-state.ended%' : '%i18n:@game-state.playing%' }}</span>
|
||||
<mk-time :time="g.createdAt" />
|
||||
</a>
|
||||
</section>
|
||||
<section v-if="games.length > 0">
|
||||
@ -41,6 +42,7 @@
|
||||
<mk-avatar class="avatar" :user="g.user2"/>
|
||||
<span><b>{{ g.user1 | userName }}</b> vs <b>{{ g.user2 | userName }}</b></span>
|
||||
<span class="state">{{ g.isEnded ? '%i18n:@game-state.ended%' : '%i18n:@game-state.playing%' }}</span>
|
||||
<mk-time :time="g.createdAt" />
|
||||
</a>
|
||||
</section>
|
||||
</div>
|
||||
|
@ -6,7 +6,7 @@
|
||||
<i>・</i>
|
||||
<a :href="feedbackUrl" target="_blank">%i18n:@feedback%</a>
|
||||
<i>・</i>
|
||||
<a :href="devUrl">%i18n:@develop%</a>
|
||||
<a href="/dev">%i18n:@develop%</a>
|
||||
<i>・</i>
|
||||
<a href="https://twitter.com/misskey_xyz" target="_blank">Follow us on %fa:B twitter%</a>
|
||||
</span>
|
||||
@ -14,18 +14,21 @@
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
import { docsUrl, statsUrl, statusUrl, devUrl, repositoryUrl, feedbackUrl, lang } from '../../../config';
|
||||
import { lang } from '../../../config';
|
||||
|
||||
export default Vue.extend({
|
||||
data() {
|
||||
return {
|
||||
aboutUrl: `${docsUrl}/${lang}/about`,
|
||||
statsUrl,
|
||||
statusUrl,
|
||||
devUrl,
|
||||
repositoryUrl: repositoryUrl || `https://github.com/syuilo/misskey`,
|
||||
feedbackUrl: feedbackUrl || `https://github.com/syuilo/misskey/issues/new`
|
||||
aboutUrl: `/docs/${lang}/about`,
|
||||
repositoryUrl: 'https://github.com/syuilo/misskey',
|
||||
feedbackUrl: 'https://github.com/syuilo/misskey/issues/new'
|
||||
}
|
||||
},
|
||||
created() {
|
||||
(this as any).os.getMeta().then(meta => {
|
||||
if (meta.repositoryUrl) this.repositoryUrl = meta.repositoryUrl;
|
||||
if (meta.feedbackUrl) this.feedbackUrl = meta.feedbackUrl;
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
@ -12,13 +12,13 @@
|
||||
</ui-input>
|
||||
<ui-input v-if="user && user.twoFactorEnabled" v-model="token" type="number" required/>
|
||||
<ui-button type="submit" :disabled="signing">{{ signing ? '%i18n:@signing-in%' : '%i18n:@signin%' }}</ui-button>
|
||||
<p style="margin: 8px 0;" v-if="twitterIntegration">%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>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
import { apiUrl, host, twitterIntegration } from '../../../config';
|
||||
import { apiUrl, host } from '../../../config';
|
||||
|
||||
export default Vue.extend({
|
||||
props: {
|
||||
@ -36,8 +36,7 @@ export default Vue.extend({
|
||||
password: '',
|
||||
token: '',
|
||||
apiUrl,
|
||||
host,
|
||||
twitterIntegration
|
||||
host
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
|
@ -1,48 +1,50 @@
|
||||
<template>
|
||||
<form class="mk-signup" @submit.prevent="onSubmit" :autocomplete="Math.random()">
|
||||
<ui-input v-if="meta.disableRegistration" v-model="invitationCode" type="text" :autocomplete="Math.random()" spellcheck="false" required>
|
||||
<span>%i18n:@invitation-code%</span>
|
||||
<span slot="prefix">%fa:id-card-alt%</span>
|
||||
<p slot="text" v-html="'%i18n:@invitation-info%'.replace('{}', meta.maintainer.url)"></p>
|
||||
</ui-input>
|
||||
<ui-input v-model="username" type="text" pattern="^[a-zA-Z0-9_]{1,20}$" :autocomplete="Math.random()" spellcheck="false" required @input="onChangeUsername">
|
||||
<span>%i18n:@username%</span>
|
||||
<span slot="prefix">@</span>
|
||||
<span slot="suffix">@{{ host }}</span>
|
||||
<p slot="text" v-if="usernameState == 'wait'" style="color:#999">%fa:spinner .pulse .fw% %i18n:@checking%</p>
|
||||
<p slot="text" v-if="usernameState == 'ok'" style="color:#3CB7B5">%fa:check .fw% %i18n:@available%</p>
|
||||
<p slot="text" v-if="usernameState == 'unavailable'" style="color:#FF1161">%fa:exclamation-triangle .fw% %i18n:@unavailable%</p>
|
||||
<p slot="text" v-if="usernameState == 'error'" style="color:#FF1161">%fa:exclamation-triangle .fw% %i18n:@error%</p>
|
||||
<p slot="text" v-if="usernameState == 'invalid-format'" style="color:#FF1161">%fa:exclamation-triangle .fw% %i18n:@invalid-format%</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>
|
||||
</ui-input>
|
||||
<ui-input v-model="password" type="password" :autocomplete="Math.random()" required @input="onChangePassword" :with-password-meter="true">
|
||||
<span>%i18n:@password%</span>
|
||||
<span slot="prefix">%fa:lock%</span>
|
||||
<div slot="text">
|
||||
<p slot="text" v-if="passwordStrength == 'low'" style="color:#FF1161">%fa:exclamation-triangle .fw% %i18n:@weak-password%</p>
|
||||
<p slot="text" v-if="passwordStrength == 'medium'" style="color:#3CB7B5">%fa:check .fw% %i18n:@normal-password%</p>
|
||||
<p slot="text" v-if="passwordStrength == 'high'" style="color:#3CB7B5">%fa:check .fw% %i18n:@strong-password%</p>
|
||||
</div>
|
||||
</ui-input>
|
||||
<ui-input v-model="retypedPassword" type="password" :autocomplete="Math.random()" required @input="onChangePasswordRetype">
|
||||
<span>%i18n:@password% (%i18n:@retype%)</span>
|
||||
<span slot="prefix">%fa:lock%</span>
|
||||
<div slot="text">
|
||||
<p slot="text" v-if="passwordRetypeState == 'match'" style="color:#3CB7B5">%fa:check .fw% %i18n:@password-matched%</p>
|
||||
<p slot="text" v-if="passwordRetypeState == 'not-match'" style="color:#FF1161">%fa:exclamation-triangle .fw% %i18n:@password-not-matched%</p>
|
||||
</div>
|
||||
</ui-input>
|
||||
<div v-if="recaptchaSitekey != null" class="g-recaptcha" :data-sitekey="recaptchaSitekey" style="margin: 16px 0;"></div>
|
||||
<ui-button type="submit">%i18n:@create%</ui-button>
|
||||
<template v-if="meta">
|
||||
<ui-input v-if="meta.disableRegistration" v-model="invitationCode" type="text" :autocomplete="Math.random()" spellcheck="false" required>
|
||||
<span>%i18n:@invitation-code%</span>
|
||||
<span slot="prefix">%fa:id-card-alt%</span>
|
||||
<p slot="text" v-html="'%i18n:@invitation-info%'.replace('{}', meta.maintainer.url)"></p>
|
||||
</ui-input>
|
||||
<ui-input v-model="username" type="text" pattern="^[a-zA-Z0-9_]{1,20}$" :autocomplete="Math.random()" spellcheck="false" required @input="onChangeUsername">
|
||||
<span>%i18n:@username%</span>
|
||||
<span slot="prefix">@</span>
|
||||
<span slot="suffix">@{{ host }}</span>
|
||||
<p slot="text" v-if="usernameState == 'wait'" style="color:#999">%fa:spinner .pulse .fw% %i18n:@checking%</p>
|
||||
<p slot="text" v-if="usernameState == 'ok'" style="color:#3CB7B5">%fa:check .fw% %i18n:@available%</p>
|
||||
<p slot="text" v-if="usernameState == 'unavailable'" style="color:#FF1161">%fa:exclamation-triangle .fw% %i18n:@unavailable%</p>
|
||||
<p slot="text" v-if="usernameState == 'error'" style="color:#FF1161">%fa:exclamation-triangle .fw% %i18n:@error%</p>
|
||||
<p slot="text" v-if="usernameState == 'invalid-format'" style="color:#FF1161">%fa:exclamation-triangle .fw% %i18n:@invalid-format%</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>
|
||||
</ui-input>
|
||||
<ui-input v-model="password" type="password" :autocomplete="Math.random()" required @input="onChangePassword" :with-password-meter="true">
|
||||
<span>%i18n:@password%</span>
|
||||
<span slot="prefix">%fa:lock%</span>
|
||||
<div slot="text">
|
||||
<p slot="text" v-if="passwordStrength == 'low'" style="color:#FF1161">%fa:exclamation-triangle .fw% %i18n:@weak-password%</p>
|
||||
<p slot="text" v-if="passwordStrength == 'medium'" style="color:#3CB7B5">%fa:check .fw% %i18n:@normal-password%</p>
|
||||
<p slot="text" v-if="passwordStrength == 'high'" style="color:#3CB7B5">%fa:check .fw% %i18n:@strong-password%</p>
|
||||
</div>
|
||||
</ui-input>
|
||||
<ui-input v-model="retypedPassword" type="password" :autocomplete="Math.random()" required @input="onChangePasswordRetype">
|
||||
<span>%i18n:@password% (%i18n:@retype%)</span>
|
||||
<span slot="prefix">%fa:lock%</span>
|
||||
<div slot="text">
|
||||
<p slot="text" v-if="passwordRetypeState == 'match'" style="color:#3CB7B5">%fa:check .fw% %i18n:@password-matched%</p>
|
||||
<p slot="text" v-if="passwordRetypeState == 'not-match'" style="color:#FF1161">%fa:exclamation-triangle .fw% %i18n:@password-not-matched%</p>
|
||||
</div>
|
||||
</ui-input>
|
||||
<div v-if="meta.recaptchaSitekey != null" class="g-recaptcha" :data-sitekey="meta.recaptchaSitekey" style="margin: 16px 0;"></div>
|
||||
<ui-button type="submit">%i18n:@create%</ui-button>
|
||||
</template>
|
||||
</form>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
const getPasswordStrength = require('syuilo-password-strength');
|
||||
import { host, url, recaptchaSitekey } from '../../../config';
|
||||
import { host, url } from '../../../config';
|
||||
|
||||
export default Vue.extend({
|
||||
data() {
|
||||
@ -53,7 +55,6 @@ export default Vue.extend({
|
||||
retypedPassword: '',
|
||||
invitationCode: '',
|
||||
url,
|
||||
recaptchaSitekey,
|
||||
usernameState: null,
|
||||
passwordStrength: '',
|
||||
passwordRetypeState: null,
|
||||
@ -73,6 +74,12 @@ export default Vue.extend({
|
||||
this.meta = meta;
|
||||
});
|
||||
},
|
||||
mounted() {
|
||||
const head = document.getElementsByTagName('head')[0];
|
||||
const script = document.createElement('script');
|
||||
script.setAttribute('src', 'https://www.google.com/recaptcha/api.js');
|
||||
head.appendChild(script);
|
||||
},
|
||||
methods: {
|
||||
onChangeUsername() {
|
||||
if (this.username == '') {
|
||||
@ -123,7 +130,7 @@ export default Vue.extend({
|
||||
username: this.username,
|
||||
password: this.password,
|
||||
invitationCode: this.invitationCode,
|
||||
'g-recaptcha-response': recaptchaSitekey != null ? (window as any).grecaptcha.getResponse() : null
|
||||
'g-recaptcha-response': this.meta.recaptchaSitekey != null ? (window as any).grecaptcha.getResponse() : null
|
||||
}).then(() => {
|
||||
(this as any).api('signin', {
|
||||
username: this.username,
|
||||
@ -134,19 +141,11 @@ export default Vue.extend({
|
||||
}).catch(() => {
|
||||
alert('%i18n:@some-error%');
|
||||
|
||||
if (recaptchaSitekey != null) {
|
||||
if (this.meta.recaptchaSitekey != null) {
|
||||
(window as any).grecaptcha.reset();
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
if (recaptchaSitekey != null) {
|
||||
const head = document.getElementsByTagName('head')[0];
|
||||
const script = document.createElement('script');
|
||||
script.setAttribute('src', 'https://www.google.com/recaptcha/api.js');
|
||||
head.appendChild(script);
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
@ -1,5 +1,7 @@
|
||||
<template>
|
||||
<iframe v-if="player" :src="player" heigth="250" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen />
|
||||
<div v-if="player.url" class="player" :style="`padding: ${(player.height || 0) / (player.width || 1) * 100}% 0 0`">
|
||||
<iframe :src="player.url" :width="player.width || '100%'" :heigth="player.height || 250" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen />
|
||||
</div>
|
||||
<div v-else-if="tweetUrl && detail" class="twitter">
|
||||
<blockquote ref="tweet" class="twitter-tweet" :data-theme="$store.state.device.darkmode ? 'dark' : null">
|
||||
<a :href="url"></a>
|
||||
@ -46,7 +48,11 @@ export default Vue.extend({
|
||||
thumbnail: null,
|
||||
icon: null,
|
||||
sitename: null,
|
||||
player: null,
|
||||
player: {
|
||||
url: null,
|
||||
width: null,
|
||||
height: null
|
||||
},
|
||||
tweetUrl: null,
|
||||
misskeyUrl
|
||||
};
|
||||
@ -170,9 +176,17 @@ export default Vue.extend({
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
iframe
|
||||
.twitter
|
||||
position relative
|
||||
width 100%
|
||||
|
||||
> iframe
|
||||
height 100%
|
||||
left 0
|
||||
position absolute
|
||||
top 0
|
||||
width 100%
|
||||
|
||||
root(isDark)
|
||||
> a
|
||||
display block
|
||||
|
@ -122,7 +122,7 @@ export default Vue.extend({
|
||||
this.memP = (stats.mem.used / stats.mem.total * 100).toFixed(0);
|
||||
},
|
||||
onStatsLog(statsLog) {
|
||||
statsLog.forEach(stats => this.onStats(stats));
|
||||
statsLog.reverse().forEach(stats => this.onStats(stats));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -1,51 +1,20 @@
|
||||
declare const _HOST_: string;
|
||||
declare const _HOSTNAME_: string;
|
||||
declare const _URL_: string;
|
||||
declare const _NAME_: string;
|
||||
declare const _DESCRIPTION_: string;
|
||||
declare const _API_URL_: string;
|
||||
declare const _WS_URL_: string;
|
||||
declare const _DOCS_URL_: string;
|
||||
declare const _STATS_URL_: string;
|
||||
declare const _STATUS_URL_: string;
|
||||
declare const _DEV_URL_: string;
|
||||
declare const _REPOSITORY_URL_: string;
|
||||
declare const _FEEDBACK_URL_: string;
|
||||
declare const _LANG_: string;
|
||||
declare const _LANGS_: string;
|
||||
declare const _RECAPTCHA_SITEKEY_: string;
|
||||
declare const _SW_PUBLICKEY_: string;
|
||||
declare const _THEME_COLOR_: string;
|
||||
declare const _COPYRIGHT_: string;
|
||||
declare const _VERSION_: string;
|
||||
declare const _CODENAME_: string;
|
||||
declare const _LICENSE_: string;
|
||||
declare const _GOOGLE_MAPS_API_KEY_: string;
|
||||
declare const _WELCOME_BG_URL_: string;
|
||||
declare const _TWITTER_INTEGRATION_: boolean;
|
||||
|
||||
export const host = _HOST_;
|
||||
export const hostname = _HOSTNAME_;
|
||||
export const url = _URL_;
|
||||
export const name = _NAME_;
|
||||
export const description = _DESCRIPTION_;
|
||||
export const apiUrl = _API_URL_;
|
||||
export const wsUrl = _WS_URL_;
|
||||
export const docsUrl = _DOCS_URL_;
|
||||
export const statsUrl = _STATS_URL_;
|
||||
export const statusUrl = _STATUS_URL_;
|
||||
export const devUrl = _DEV_URL_;
|
||||
export const repositoryUrl = _REPOSITORY_URL_;
|
||||
export const feedbackUrl = _FEEDBACK_URL_;
|
||||
const address = new URL(location.href);
|
||||
|
||||
export const host = address.host;
|
||||
export const hostname = address.hostname;
|
||||
export const url = address.origin;
|
||||
export const apiUrl = url + '/api';
|
||||
export const wsUrl = url.replace('http://', 'ws://').replace('https://', 'wss://');
|
||||
export const lang = _LANG_;
|
||||
export const langs = _LANGS_;
|
||||
export const recaptchaSitekey = _RECAPTCHA_SITEKEY_;
|
||||
export const swPublickey = _SW_PUBLICKEY_;
|
||||
export const themeColor = _THEME_COLOR_;
|
||||
export const copyright = _COPYRIGHT_;
|
||||
export const version = _VERSION_;
|
||||
export const codename = _CODENAME_;
|
||||
export const license = _LICENSE_;
|
||||
export const googleMapsApiKey = _GOOGLE_MAPS_API_KEY_;
|
||||
export const welcomeBgUrl = _WELCOME_BG_URL_;
|
||||
export const twitterIntegration = _TWITTER_INTEGRATION_;
|
||||
|
@ -9,12 +9,18 @@
|
||||
@contextmenu.prevent.stop="onContextmenu"
|
||||
:title="title"
|
||||
>
|
||||
<div class="label" v-if="$store.state.i.avatarId == file.id"><img src="/assets/label.svg"/>
|
||||
<div class="label" v-if="$store.state.i.avatarId == file.id">
|
||||
<img src="/assets/label.svg"/>
|
||||
<p>%i18n:@avatar%</p>
|
||||
</div>
|
||||
<div class="label" v-if="$store.state.i.bannerId == file.id"><img src="/assets/label.svg"/>
|
||||
<div class="label" v-if="$store.state.i.bannerId == file.id">
|
||||
<img src="/assets/label.svg"/>
|
||||
<p>%i18n:@banner%</p>
|
||||
</div>
|
||||
<div class="label red" v-if="file.isSensitive">
|
||||
<img src="/assets/label-red.svg"/>
|
||||
<p>%i18n:@nsfw%</p>
|
||||
</div>
|
||||
<div class="thumbnail" ref="thumbnail" :style="`background-color: ${ background }`">
|
||||
<img :src="file.thumbnailUrl" alt="" @load="onThumbnailLoaded"/>
|
||||
</div>
|
||||
@ -212,6 +218,11 @@ root(isDark)
|
||||
&:after
|
||||
background #0b65a5
|
||||
|
||||
&.red
|
||||
&:before
|
||||
&:after
|
||||
background #c12113
|
||||
|
||||
&:active
|
||||
background rgba(#000, 0.1)
|
||||
|
||||
@ -220,6 +231,11 @@ root(isDark)
|
||||
&:after
|
||||
background #0b588c
|
||||
|
||||
&.red
|
||||
&:before
|
||||
&:after
|
||||
background #ce2212
|
||||
|
||||
&[data-is-selected]
|
||||
background $theme-color
|
||||
|
||||
@ -256,26 +272,29 @@ root(isDark)
|
||||
pointer-events none
|
||||
|
||||
&:before
|
||||
content ""
|
||||
display block
|
||||
position absolute
|
||||
z-index 1
|
||||
top 0
|
||||
left 57px
|
||||
width 28px
|
||||
height 8px
|
||||
background #0c7ac9
|
||||
|
||||
&:after
|
||||
content ""
|
||||
display block
|
||||
position absolute
|
||||
z-index 1
|
||||
background #0c7ac9
|
||||
|
||||
&:before
|
||||
top 0
|
||||
left 57px
|
||||
width 28px
|
||||
height 8px
|
||||
|
||||
&:after
|
||||
top 57px
|
||||
left 0
|
||||
width 8px
|
||||
height 28px
|
||||
background #0c7ac9
|
||||
|
||||
&.red
|
||||
&:before
|
||||
&:after
|
||||
background #c12113
|
||||
|
||||
> img
|
||||
position absolute
|
||||
|
@ -193,7 +193,7 @@ export default Vue.extend({
|
||||
|
||||
clearNotification() {
|
||||
this.unreadCount = 0;
|
||||
document.title = config.name;
|
||||
document.title = (this as any).os.instanceName;
|
||||
},
|
||||
|
||||
onVisibilitychange() {
|
||||
|
@ -58,7 +58,7 @@
|
||||
import Vue from 'vue';
|
||||
import insertTextAtCursor from 'insert-text-at-cursor';
|
||||
import * as XDraggable from 'vuedraggable';
|
||||
import getKao from '../../../common/scripts/get-kao';
|
||||
import getFace from '../../../common/scripts/get-face';
|
||||
import MkVisibilityChooser from '../../../common/views/components/visibility-chooser.vue';
|
||||
import parse from '../../../../../mfm/parse';
|
||||
import { host } from '../../../config';
|
||||
@ -421,7 +421,7 @@ export default Vue.extend({
|
||||
},
|
||||
|
||||
kao() {
|
||||
this.text += getKao();
|
||||
this.text += getFace();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -56,8 +56,9 @@
|
||||
<mk-switch v-model="$store.state.settings.showMaps" @change="onChangeShowMaps" text="%i18n:@show-maps%">
|
||||
<span>%i18n:@show-maps-desc%</span>
|
||||
</mk-switch>
|
||||
<mk-switch v-model="$store.state.settings.reversiBoardLabels" @change="onChangeReversiBoardLabels" text="%i18n:common.show-reversi-board-labels%"/>
|
||||
<mk-switch v-model="$store.state.settings.disableAnimatedMfm" @change="onChangeDisableAnimatedMfm" text="%i18n:common.disable-animated-mfm%"/>
|
||||
<mk-switch v-model="$store.state.settings.games.reversi.showBoardLabels" @change="onChangeReversiBoardLabels" text="%i18n:common.show-reversi-board-labels%"/>
|
||||
<mk-switch v-model="$store.state.settings.games.reversi.useContrastStones" @change="onChangeUseContrastReversiStones" text="%i18n:common.use-contrast-reversi-stones%"/>
|
||||
</section>
|
||||
|
||||
<section class="web" v-show="page == 'web'">
|
||||
@ -191,12 +192,6 @@
|
||||
<button class="ui button block" @click="taskmngr">%i18n:@task-manager%</button>
|
||||
</details>
|
||||
</section>
|
||||
|
||||
<section class="other" v-show="page == 'other'">
|
||||
<h1>%i18n:@license%</h1>
|
||||
<div v-html="license"></div>
|
||||
<a :href="licenseUrl" target="_blank">%i18n:@third-parties%</a>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@ -211,7 +206,7 @@ import XApi from './settings.api.vue';
|
||||
import XApps from './settings.apps.vue';
|
||||
import XSignins from './settings.signins.vue';
|
||||
import XDrive from './settings.drive.vue';
|
||||
import { url, docsUrl, license, lang, langs, version } from '../../../config';
|
||||
import { url, langs, version } from '../../../config';
|
||||
import checkForUpdate from '../../../common/scripts/check-for-update';
|
||||
import MkTaskManager from './taskmanager.vue';
|
||||
|
||||
@ -230,7 +225,6 @@ export default Vue.extend({
|
||||
return {
|
||||
page: 'profile',
|
||||
meta: null,
|
||||
license,
|
||||
version,
|
||||
langs,
|
||||
latestVersion: undefined,
|
||||
@ -238,10 +232,6 @@ export default Vue.extend({
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
licenseUrl(): string {
|
||||
return `${docsUrl}/${lang}/license`;
|
||||
},
|
||||
|
||||
apiViaStream: {
|
||||
get() { return this.$store.state.device.apiViaStream; },
|
||||
set(value) { this.$store.commit('device/set', { key: 'apiViaStream', value }); }
|
||||
@ -387,7 +377,13 @@ export default Vue.extend({
|
||||
},
|
||||
onChangeReversiBoardLabels(v) {
|
||||
this.$store.dispatch('settings/set', {
|
||||
key: 'reversiBoardLabels',
|
||||
key: 'games.reversi.showBoardLabels',
|
||||
value: v
|
||||
});
|
||||
},
|
||||
onChangeUseContrastReversiStones(v) {
|
||||
this.$store.dispatch('settings/set', {
|
||||
key: 'games.reversi.useContrastStones',
|
||||
value: v
|
||||
});
|
||||
},
|
||||
|
@ -30,10 +30,8 @@
|
||||
<li @click="settings">
|
||||
<p>%fa:cog%<span>%i18n:@settings%</span>%fa:angle-right%</p>
|
||||
</li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li @click="signout">
|
||||
<p class="signout">%fa:power-off%<span>%i18n:@signout%</span></p>
|
||||
<li v-if="$store.state.i.isAdmin">
|
||||
<router-link to="/admin">%fa:terminal%<span>%i18n:@admin%</span>%fa:angle-right%</router-link>
|
||||
</li>
|
||||
</ul>
|
||||
<ul>
|
||||
@ -41,6 +39,11 @@
|
||||
<p><span>%i18n:@dark%</span><template v-if="$store.state.device.darkmode">%fa:moon%</template><template v-else>%fa:R moon%</template></p>
|
||||
</li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li @click="signout">
|
||||
<p class="signout">%fa:power-off%<span>%i18n:@signout%</span></p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</transition>
|
||||
</div>
|
||||
|
144
src/client/app/desktop/views/pages/admin/admin.cpu-memory.vue
Normal file
144
src/client/app/desktop/views/pages/admin/admin.cpu-memory.vue
Normal file
@ -0,0 +1,144 @@
|
||||
<template>
|
||||
<div class="zyknedwtlthezamcjlolyusmipqmjgxz">
|
||||
<svg :viewBox="`0 0 ${ viewBoxX } ${ viewBoxY }`">
|
||||
<defs>
|
||||
<linearGradient :id="cpuGradientId" x1="0" x2="0" y1="1" y2="0">
|
||||
<stop offset="0%" stop-color="hsl(180, 80%, 70%)"></stop>
|
||||
<stop offset="100%" stop-color="hsl(0, 80%, 70%)"></stop>
|
||||
</linearGradient>
|
||||
<mask :id="cpuMaskId" x="0" y="0" :width="viewBoxX" :height="viewBoxY">
|
||||
<polygon
|
||||
:points="cpuPolygonPoints"
|
||||
fill="#fff"
|
||||
fill-opacity="0.5"/>
|
||||
<polyline
|
||||
:points="cpuPolylinePoints"
|
||||
fill="none"
|
||||
stroke="#fff"
|
||||
stroke-width="1"/>
|
||||
</mask>
|
||||
</defs>
|
||||
<rect
|
||||
x="0" y="0"
|
||||
:width="viewBoxX" :height="viewBoxY"
|
||||
:style="`stroke: none; fill: url(#${ cpuGradientId }); mask: url(#${ cpuMaskId })`"/>
|
||||
<text x="1" y="12">CPU <tspan>{{ cpuP }}%</tspan></text>
|
||||
</svg>
|
||||
<svg :viewBox="`0 0 ${ viewBoxX } ${ viewBoxY }`">
|
||||
<defs>
|
||||
<linearGradient :id="memGradientId" x1="0" x2="0" y1="1" y2="0">
|
||||
<stop offset="0%" stop-color="hsl(180, 80%, 70%)"></stop>
|
||||
<stop offset="100%" stop-color="hsl(0, 80%, 70%)"></stop>
|
||||
</linearGradient>
|
||||
<mask :id="memMaskId" x="0" y="0" :width="viewBoxX" :height="viewBoxY">
|
||||
<polygon
|
||||
:points="memPolygonPoints"
|
||||
fill="#fff"
|
||||
fill-opacity="0.5"/>
|
||||
<polyline
|
||||
:points="memPolylinePoints"
|
||||
fill="none"
|
||||
stroke="#fff"
|
||||
stroke-width="1"/>
|
||||
</mask>
|
||||
</defs>
|
||||
<rect
|
||||
x="0" y="0"
|
||||
:width="viewBoxX" :height="viewBoxY"
|
||||
:style="`stroke: none; fill: url(#${ memGradientId }); mask: url(#${ memMaskId })`"/>
|
||||
<text x="1" y="12">MEM <tspan>{{ memP }}%</tspan></text>
|
||||
</svg>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
import * as uuid from 'uuid';
|
||||
|
||||
export default Vue.extend({
|
||||
props: ['connection'],
|
||||
data() {
|
||||
return {
|
||||
viewBoxX: 200,
|
||||
viewBoxY: 70,
|
||||
stats: [],
|
||||
cpuGradientId: uuid(),
|
||||
cpuMaskId: uuid(),
|
||||
memGradientId: uuid(),
|
||||
memMaskId: uuid(),
|
||||
cpuPolylinePoints: '',
|
||||
memPolylinePoints: '',
|
||||
cpuPolygonPoints: '',
|
||||
memPolygonPoints: '',
|
||||
cpuP: '',
|
||||
memP: ''
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.connection.on('stats', this.onStats);
|
||||
this.connection.on('statsLog', this.onStatsLog);
|
||||
this.connection.send({
|
||||
type: 'requestLog',
|
||||
id: Math.random().toString(),
|
||||
length: 200
|
||||
});
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.connection.off('stats', this.onStats);
|
||||
this.connection.off('statsLog', this.onStatsLog);
|
||||
},
|
||||
methods: {
|
||||
onStats(stats) {
|
||||
this.stats.push(stats);
|
||||
if (this.stats.length > 200) this.stats.shift();
|
||||
|
||||
const cpuPolylinePoints = this.stats.map((s, i) => [this.viewBoxX - ((this.stats.length - 1) - i), (1 - s.cpu_usage) * this.viewBoxY]);
|
||||
const memPolylinePoints = this.stats.map((s, i) => [this.viewBoxX - ((this.stats.length - 1) - i), (1 - (s.mem.used / s.mem.total)) * this.viewBoxY]);
|
||||
this.cpuPolylinePoints = cpuPolylinePoints.map(xy => `${xy[0]},${xy[1]}`).join(' ');
|
||||
this.memPolylinePoints = memPolylinePoints.map(xy => `${xy[0]},${xy[1]}`).join(' ');
|
||||
|
||||
this.cpuPolygonPoints = `${this.viewBoxX - (this.stats.length - 1)},${this.viewBoxY} ${this.cpuPolylinePoints} ${this.viewBoxX},${this.viewBoxY}`;
|
||||
this.memPolygonPoints = `${this.viewBoxX - (this.stats.length - 1)},${this.viewBoxY} ${this.memPolylinePoints} ${this.viewBoxX},${this.viewBoxY}`;
|
||||
|
||||
this.cpuP = (stats.cpu_usage * 100).toFixed(0);
|
||||
this.memP = (stats.mem.used / stats.mem.total * 100).toFixed(0);
|
||||
},
|
||||
onStatsLog(statsLog) {
|
||||
statsLog.reverse().forEach(stats => this.onStats(stats));
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
root(isDark)
|
||||
> svg
|
||||
display block
|
||||
width 50%
|
||||
float left
|
||||
|
||||
&:first-child
|
||||
padding-right 5px
|
||||
|
||||
&:last-child
|
||||
padding-left 5px
|
||||
|
||||
> text
|
||||
font-size 10px
|
||||
fill isDark ? rgba(#fff, 0.55) : rgba(#000, 0.55)
|
||||
|
||||
> tspan
|
||||
opacity 0.5
|
||||
|
||||
&:after
|
||||
content ""
|
||||
display block
|
||||
clear both
|
||||
|
||||
.zyknedwtlthezamcjlolyusmipqmjgxz[data-darkmode]
|
||||
root(true)
|
||||
|
||||
.zyknedwtlthezamcjlolyusmipqmjgxz:not([data-darkmode])
|
||||
root(false)
|
||||
|
||||
</style>
|
@ -1,13 +1,20 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>%i18n:@dashboard%</h1>
|
||||
<div v-if="stats">
|
||||
<p><b>%i18n:@all-users%</b>: <span>{{ stats.usersCount | number }}</span></p>
|
||||
<p><b>%i18n:@original-users%</b>: <span>{{ stats.originalUsersCount | number }}</span></p>
|
||||
<p><b>%i18n:@all-notes%</b>: <span>{{ stats.notesCount | number }}</span></p>
|
||||
<p><b>%i18n:@original-notes%</b>: <span>{{ stats.originalNotesCount | number }}</span></p>
|
||||
<div class="obdskegsannmntldydackcpzezagxqfy card">
|
||||
<header>%i18n:@dashboard%</header>
|
||||
<div v-if="stats" class="stats">
|
||||
<div><b>%fa:user% {{ stats.originalUsersCount | number }}</b><span>%i18n:@original-users%</span></div>
|
||||
<div><span>%fa:user% {{ stats.usersCount | number }}</span><span>%i18n:@all-users%</span></div>
|
||||
<div><b>%fa:pen% {{ stats.originalNotesCount | number }}</b><span>%i18n:@original-notes%</span></div>
|
||||
<div><span>%fa:pen% {{ stats.notesCount | number }}</span><span>%i18n:@all-notes%</span></div>
|
||||
</div>
|
||||
<div class="cpu-memory">
|
||||
<x-cpu-memory :connection="connection"/>
|
||||
</div>
|
||||
<div>
|
||||
<label>
|
||||
<input type="checkbox" v-model="disableRegistration" @change="updateMeta">
|
||||
<span>disableRegistration</span>
|
||||
</label>
|
||||
<button class="ui" @click="invite">%i18n:@invite%</button>
|
||||
<p v-if="inviteCode">Code: <code>{{ inviteCode }}</code></p>
|
||||
</div>
|
||||
@ -16,34 +23,78 @@
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from "vue";
|
||||
import XCpuMemory from "./admin.cpu-memory.vue";
|
||||
|
||||
export default Vue.extend({
|
||||
components: {
|
||||
XCpuMemory
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
stats: null,
|
||||
inviteCode: null
|
||||
disableRegistration: false,
|
||||
inviteCode: null,
|
||||
connection: null,
|
||||
connectionId: null
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.connection = (this as any).os.streams.serverStatsStream.getConnection();
|
||||
this.connectionId = (this as any).os.streams.serverStatsStream.use();
|
||||
|
||||
(this as any).os.getMeta().then(meta => {
|
||||
this.disableRegistration = meta.disableRegistration;
|
||||
});
|
||||
|
||||
(this as any).api('stats').then(stats => {
|
||||
this.stats = stats;
|
||||
});
|
||||
},
|
||||
beforeDestroy() {
|
||||
(this as any).os.streams.serverStatsStream.dispose(this.connectionId);
|
||||
},
|
||||
methods: {
|
||||
invite() {
|
||||
(this as any).api('admin/invite').then(x => {
|
||||
this.inviteCode = x.code;
|
||||
});
|
||||
},
|
||||
updateMeta() {
|
||||
(this as any).api('admin/update-meta', {
|
||||
disableRegistration: this.disableRegistration
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
h1
|
||||
margin 0 0 1em 0
|
||||
padding 0 0 8px 0
|
||||
font-size 1em
|
||||
color #555
|
||||
border-bottom solid 1px #eee
|
||||
@import '~const.styl'
|
||||
|
||||
.obdskegsannmntldydackcpzezagxqfy
|
||||
> .stats
|
||||
display flex
|
||||
justify-content center
|
||||
margin-bottom 16px
|
||||
padding 16px
|
||||
border solid 1px #eee
|
||||
border-radius 8px
|
||||
|
||||
> div
|
||||
flex 1
|
||||
text-align center
|
||||
|
||||
> *:first-child
|
||||
display block
|
||||
color $theme-color
|
||||
|
||||
> *:last-child
|
||||
font-size 70%
|
||||
|
||||
> .cpu-memory
|
||||
margin-bottom 16px
|
||||
padding 16px
|
||||
border solid 1px #eee
|
||||
border-radius: 8px
|
||||
|
||||
</style>
|
||||
|
@ -0,0 +1,51 @@
|
||||
<template>
|
||||
<svg :viewBox="`0 0 ${ viewBoxX } ${ viewBoxY }`">
|
||||
<polyline
|
||||
:points="points"
|
||||
fill="none"
|
||||
stroke-width="1"
|
||||
stroke="#555"/>
|
||||
</svg>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
|
||||
export default Vue.extend({
|
||||
props: {
|
||||
chart: {
|
||||
required: true
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
viewBoxX: 365,
|
||||
viewBoxY: 70,
|
||||
points: null
|
||||
};
|
||||
},
|
||||
created() {
|
||||
const peak = Math.max.apply(null, this.chart.map(d => this.type == 'local' ? d.drive.local.totalSize : d.drive.remote.totalSize));
|
||||
|
||||
if (peak != 0) {
|
||||
const data = this.chart.slice().reverse().map(x => ({
|
||||
size: this.type == 'local' ? x.drive.local.totalSize : x.drive.remote.totalSize
|
||||
}));
|
||||
|
||||
this.points = data.map((d, i) => `${i},${(1 - (d.size / peak)) * this.viewBoxY}`).join(' ');
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
svg
|
||||
display block
|
||||
padding 10px
|
||||
width 100%
|
||||
|
||||
</style>
|
@ -0,0 +1,34 @@
|
||||
<template>
|
||||
<div class="card">
|
||||
<header>%i18n:@title%</header>
|
||||
<div class="card">
|
||||
<header>%i18n:@local%</header>
|
||||
<x-chart v-if="chart" :chart="chart" type="local"/>
|
||||
</div>
|
||||
<div class="card">
|
||||
<header>%i18n:@remote%</header>
|
||||
<x-chart v-if="chart" :chart="chart" type="remote"/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from "vue";
|
||||
import XChart from "./admin.drive-chart.chart.vue";
|
||||
|
||||
export default Vue.extend({
|
||||
components: {
|
||||
XChart
|
||||
},
|
||||
props: {
|
||||
chart: {
|
||||
required: true
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
@import '~const.styl'
|
||||
|
||||
</style>
|
@ -0,0 +1,76 @@
|
||||
<template>
|
||||
<svg :viewBox="`0 0 ${ viewBoxX } ${ viewBoxY }`">
|
||||
<polyline
|
||||
:points="pointsNote"
|
||||
fill="none"
|
||||
stroke-width="1"
|
||||
stroke="#41ddde"/>
|
||||
<polyline
|
||||
:points="pointsReply"
|
||||
fill="none"
|
||||
stroke-width="1"
|
||||
stroke="#f7796c"/>
|
||||
<polyline
|
||||
:points="pointsRenote"
|
||||
fill="none"
|
||||
stroke-width="1"
|
||||
stroke="#a1de41"/>
|
||||
<polyline
|
||||
:points="pointsTotal"
|
||||
fill="none"
|
||||
stroke-width="1"
|
||||
stroke="#555"
|
||||
stroke-dasharray="2 2"/>
|
||||
</svg>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
|
||||
export default Vue.extend({
|
||||
props: {
|
||||
chart: {
|
||||
required: true
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
viewBoxX: 365,
|
||||
viewBoxY: 70,
|
||||
pointsNote: null,
|
||||
pointsReply: null,
|
||||
pointsRenote: null,
|
||||
pointsTotal: null
|
||||
};
|
||||
},
|
||||
created() {
|
||||
const peak = Math.max.apply(null, this.chart.map(d => this.type == 'local' ? d.notes.local.diff : d.notes.remote.diff));
|
||||
|
||||
if (peak != 0) {
|
||||
const data = this.chart.slice().reverse().map(x => ({
|
||||
normal: this.type == 'local' ? x.notes.local.diffs.normal : x.notes.remote.diffs.normal,
|
||||
reply: this.type == 'local' ? x.notes.local.diffs.reply : x.notes.remote.diffs.reply,
|
||||
renote: this.type == 'local' ? x.notes.local.diffs.renote : x.notes.remote.diffs.renote,
|
||||
total: this.type == 'local' ? x.notes.local.diff : x.notes.remote.diff
|
||||
}));
|
||||
|
||||
this.pointsNote = data.map((d, i) => `${i},${(1 - (d.normal / peak)) * this.viewBoxY}`).join(' ');
|
||||
this.pointsReply = data.map((d, i) => `${i},${(1 - (d.reply / peak)) * this.viewBoxY}`).join(' ');
|
||||
this.pointsRenote = data.map((d, i) => `${i},${(1 - (d.renote / peak)) * this.viewBoxY}`).join(' ');
|
||||
this.pointsTotal = data.map((d, i) => `${i},${(1 - (d.total / peak)) * this.viewBoxY}`).join(' ');
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
svg
|
||||
display block
|
||||
padding 10px
|
||||
width 100%
|
||||
|
||||
</style>
|
@ -0,0 +1,34 @@
|
||||
<template>
|
||||
<div class="card">
|
||||
<header>%i18n:@title%</header>
|
||||
<div class="card">
|
||||
<header>%i18n:@local%</header>
|
||||
<x-chart v-if="chart" :chart="chart" type="local"/>
|
||||
</div>
|
||||
<div class="card">
|
||||
<header>%i18n:@remote%</header>
|
||||
<x-chart v-if="chart" :chart="chart" type="remote"/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from "vue";
|
||||
import XChart from "./admin.notes-chart.chart.vue";
|
||||
|
||||
export default Vue.extend({
|
||||
components: {
|
||||
XChart
|
||||
},
|
||||
props: {
|
||||
chart: {
|
||||
required: true
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
@import '~const.styl'
|
||||
|
||||
</style>
|
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="card">
|
||||
<header>%i18n:@suspend-user%</header>
|
||||
<input v-model="username" type="text" class="ui"/>
|
||||
<button class="ui" @click="suspendUser" :disabled="suspending">%i18n:@suspend%</button>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="card">
|
||||
<header>%i18n:@unsuspend-user%</header>
|
||||
<input v-model="username" type="text" class="ui"/>
|
||||
<button class="ui" @click="unsuspendUser" :disabled="unsuspending">%i18n:@unsuspend%</button>
|
||||
|
@ -0,0 +1,51 @@
|
||||
<template>
|
||||
<div class="card">
|
||||
<header>%i18n:@unverify-user%</header>
|
||||
<input v-model="username" type="text" class="ui"/>
|
||||
<button class="ui" @click="unverifyUser" :disabled="unverifying">%i18n:@unverify%</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from "vue";
|
||||
import parseAcct from "../../../../../../misc/acct/parse";
|
||||
|
||||
export default Vue.extend({
|
||||
data() {
|
||||
return {
|
||||
username: null,
|
||||
unverifying: false
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
async unverifyUser() {
|
||||
this.unverifying = true;
|
||||
|
||||
const user = await (this as any).os.api(
|
||||
"users/show",
|
||||
parseAcct(this.username)
|
||||
);
|
||||
|
||||
await (this as any).os.api("admin/unverify-user", {
|
||||
userId: user.id
|
||||
});
|
||||
|
||||
this.unverifying = false;
|
||||
|
||||
(this as any).os.apis.dialog({ text: "%i18n:@unverified%" });
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
@import '~const.styl'
|
||||
|
||||
header
|
||||
margin 10px 0
|
||||
|
||||
|
||||
button
|
||||
margin 16px 0
|
||||
|
||||
</style>
|
@ -0,0 +1,51 @@
|
||||
<template>
|
||||
<svg :viewBox="`0 0 ${ viewBoxX } ${ viewBoxY }`">
|
||||
<polyline
|
||||
:points="points"
|
||||
fill="none"
|
||||
stroke-width="1"
|
||||
stroke="#555"/>
|
||||
</svg>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
|
||||
export default Vue.extend({
|
||||
props: {
|
||||
chart: {
|
||||
required: true
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
viewBoxX: 365,
|
||||
viewBoxY: 70,
|
||||
points: null
|
||||
};
|
||||
},
|
||||
created() {
|
||||
const peak = Math.max.apply(null, this.chart.map(d => this.type == 'local' ? d.users.local.diff : d.users.remote.diff));
|
||||
|
||||
if (peak != 0) {
|
||||
const data = this.chart.slice().reverse().map(x => ({
|
||||
count: this.type == 'local' ? x.users.local.diff : x.users.remote.diff
|
||||
}));
|
||||
|
||||
this.points = data.map((d, i) => `${i},${(1 - (d.count / peak)) * this.viewBoxY}`).join(' ');
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
svg
|
||||
display block
|
||||
padding 10px
|
||||
width 100%
|
||||
|
||||
</style>
|
@ -0,0 +1,34 @@
|
||||
<template>
|
||||
<div class="card">
|
||||
<header>%i18n:@title%</header>
|
||||
<div class="card">
|
||||
<header>%i18n:@local%</header>
|
||||
<x-chart v-if="chart" :chart="chart" type="local"/>
|
||||
</div>
|
||||
<div class="card">
|
||||
<header>%i18n:@remote%</header>
|
||||
<x-chart v-if="chart" :chart="chart" type="remote"/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from "vue";
|
||||
import XChart from "./admin.users-chart.chart.vue";
|
||||
|
||||
export default Vue.extend({
|
||||
components: {
|
||||
XChart
|
||||
},
|
||||
props: {
|
||||
chart: {
|
||||
required: true
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
@import '~const.styl'
|
||||
|
||||
</style>
|
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="card">
|
||||
<header>%i18n:@verify-user%</header>
|
||||
<input v-model="username" type="text" class="ui"/>
|
||||
<button class="ui" @click="verifyUser" :disabled="verifying">%i18n:@verify%</button>
|
||||
|
@ -9,13 +9,17 @@
|
||||
</ul>
|
||||
</nav>
|
||||
<main>
|
||||
<div v-if="page == 'dashboard'">
|
||||
<div v-show="page == 'dashboard'">
|
||||
<x-dashboard/>
|
||||
<x-users-chart :chart="chart"/>
|
||||
<x-notes-chart :chart="chart"/>
|
||||
<x-drive-chart :chart="chart"/>
|
||||
</div>
|
||||
<div v-if="page == 'users'">
|
||||
<x-suspend-user/>
|
||||
<x-unsuspend-user/>
|
||||
<x-verify-user/>
|
||||
<x-unverify-user/>
|
||||
</div>
|
||||
<div v-if="page == 'drive'"></div>
|
||||
<div v-if="page == 'update'"></div>
|
||||
@ -29,19 +33,33 @@ import XDashboard from "./admin.dashboard.vue";
|
||||
import XSuspendUser from "./admin.suspend-user.vue";
|
||||
import XUnsuspendUser from "./admin.unsuspend-user.vue";
|
||||
import XVerifyUser from "./admin.verify-user.vue";
|
||||
import XUnverifyUser from "./admin.unverify-user.vue";
|
||||
import XUsersChart from "./admin.users-chart.vue";
|
||||
import XNotesChart from "./admin.notes-chart.vue";
|
||||
import XDriveChart from "./admin.drive-chart.vue";
|
||||
|
||||
export default Vue.extend({
|
||||
components: {
|
||||
XDashboard,
|
||||
XSuspendUser,
|
||||
XUnsuspendUser,
|
||||
XVerifyUser
|
||||
XVerifyUser,
|
||||
XUnverifyUser,
|
||||
XUsersChart,
|
||||
XNotesChart,
|
||||
XDriveChart
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
page: 'dashboard'
|
||||
page: 'dashboard',
|
||||
chart: null
|
||||
};
|
||||
},
|
||||
created() {
|
||||
(this as any).api('admin/chart').then(chart => {
|
||||
this.chart = chart;
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
nav(page: string) {
|
||||
this.page = page;
|
||||
@ -50,7 +68,7 @@ export default Vue.extend({
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
<style lang="stylus">
|
||||
@import '~const.styl'
|
||||
|
||||
.mk-admin
|
||||
@ -95,19 +113,21 @@ export default Vue.extend({
|
||||
|
||||
> div
|
||||
> div
|
||||
margin-bottom 16px
|
||||
padding 32px
|
||||
max-width 800px
|
||||
background #fff
|
||||
box-shadow 0 2px 8px rgba(#000, 0.1)
|
||||
|
||||
header
|
||||
margin 10px 0
|
||||
.card
|
||||
padding 32px
|
||||
background #fff
|
||||
box-shadow 0 2px 8px rgba(#000, 0.1)
|
||||
|
||||
&:not(:last-child)
|
||||
margin-bottom 16px
|
||||
|
||||
button
|
||||
margin 16px 0
|
||||
position absolute
|
||||
right 0
|
||||
> header
|
||||
margin 0 0 1em 0
|
||||
padding 0 0 8px 0
|
||||
font-size 1em
|
||||
color #555
|
||||
border-bottom solid 1px #eee
|
||||
|
||||
</style>
|
||||
|
@ -4,11 +4,10 @@
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
import * as config from '../../../config';
|
||||
|
||||
export default Vue.extend({
|
||||
mounted() {
|
||||
document.title = `${config.name} - %i18n:@title%`;
|
||||
document.title = `${(this as any).os.instanceName} - %i18n:@title%`;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
@ -7,7 +7,6 @@
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
import Progress from '../../../common/scripts/loading';
|
||||
import * as config from '../../../config';
|
||||
|
||||
export default Vue.extend({
|
||||
props: {
|
||||
@ -17,7 +16,7 @@ export default Vue.extend({
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
document.title = config.name;
|
||||
document.title = (this as any).os.instanceName;
|
||||
|
||||
Progress.start();
|
||||
},
|
||||
|
@ -12,12 +12,11 @@
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
import * as config from '../../../config';
|
||||
|
||||
export default Vue.extend({
|
||||
data() {
|
||||
return {
|
||||
name: config.name,
|
||||
name: (this as any).os.instanceName,
|
||||
posted: false,
|
||||
text: new URLSearchParams(location.search).get('text')
|
||||
};
|
||||
|
@ -5,7 +5,7 @@
|
||||
<template v-if="$store.state.device.darkmode">%fa:moon%</template>
|
||||
<template v-else>%fa:R moon%</template>
|
||||
</button>
|
||||
<div class="body" :style="{ backgroundImage: `url('${ welcomeBgUrl }')` }">
|
||||
<div class="body">
|
||||
<div class="container">
|
||||
<div class="info">
|
||||
<span><b>{{ host }}</b></span>
|
||||
@ -46,22 +46,26 @@
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
import { host, name, description, copyright, welcomeBgUrl } from '../../../config';
|
||||
import { host, copyright } from '../../../config';
|
||||
|
||||
export default Vue.extend({
|
||||
data() {
|
||||
return {
|
||||
stats: null,
|
||||
copyright,
|
||||
welcomeBgUrl,
|
||||
host,
|
||||
name,
|
||||
description,
|
||||
name: 'Misskey',
|
||||
description: '',
|
||||
pointerInterval: null,
|
||||
tags: []
|
||||
};
|
||||
},
|
||||
created() {
|
||||
(this as any).os.getMeta().then(meta => {
|
||||
this.name = meta.name;
|
||||
this.description = meta.description;
|
||||
});
|
||||
|
||||
(this as any).api('stats').then(stats => {
|
||||
this.stats = stats;
|
||||
});
|
||||
|
@ -5,16 +5,6 @@
|
||||
<b-form-group label="アプリケーション名" description="あなたのアプリの名称。">
|
||||
<b-form-input v-model="name" type="text" placeholder="ex) Misskey for iOS" autocomplete="off" required/>
|
||||
</b-form-group>
|
||||
<b-form-group label="ID" description="あなたのアプリのID。">
|
||||
<b-input v-model="nid" type="text" pattern="^[a-zA-Z0-9_]{1,30}$" placeholder="ex) misskey-for-ios" autocomplete="off" required/>
|
||||
<p class="info" v-if="nidState == 'wait'" style="color:#999">%fa:spinner .pulse .fw%確認しています...</p>
|
||||
<p class="info" v-if="nidState == 'ok'" style="color:#3CB7B5">%fa:fw check%利用できます</p>
|
||||
<p class="info" v-if="nidState == 'unavailable'" style="color:#FF1161">%fa:fw exclamation-triangle%既に利用されています</p>
|
||||
<p class="info" v-if="nidState == 'error'" style="color:#FF1161">%fa:fw exclamation-triangle%通信エラー</p>
|
||||
<p class="info" v-if="nidState == 'invalid-format'" style="color:#FF1161">%fa:fw exclamation-triangle%a~z、A~Z、0~9、_が使えます</p>
|
||||
<p class="info" v-if="nidState == 'min-range'" style="color:#FF1161">%fa:fw exclamation-triangle%1文字以上でお願いします!</p>
|
||||
<p class="info" v-if="nidState == 'max-range'" style="color:#FF1161">%fa:fw exclamation-triangle%30文字以内でお願いします</p>
|
||||
</b-form-group>
|
||||
<b-form-group label="アプリの概要" description="あなたのアプリの簡単な説明や紹介。">
|
||||
<b-textarea v-model="description" placeholder="ex) Misskey iOSクライアント。" autocomplete="off" required></b-textarea>
|
||||
</b-form-group>
|
||||
@ -50,47 +40,16 @@ export default Vue.extend({
|
||||
data() {
|
||||
return {
|
||||
name: '',
|
||||
nid: '',
|
||||
description: '',
|
||||
cb: '',
|
||||
nidState: null,
|
||||
permission: []
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
nid() {
|
||||
if (this.nid == null || this.nid == '') {
|
||||
this.nidState = null;
|
||||
return;
|
||||
}
|
||||
|
||||
const err =
|
||||
!this.nid.match(/^[a-zA-Z0-9_]+$/) ? 'invalid-format' :
|
||||
this.nid.length < 1 ? 'min-range' :
|
||||
this.nid.length > 30 ? 'max-range' :
|
||||
null;
|
||||
|
||||
if (err) {
|
||||
this.nidState = err;
|
||||
return;
|
||||
}
|
||||
|
||||
this.nidState = 'wait';
|
||||
|
||||
(this as any).api('app/name_id/available', {
|
||||
nameId: this.nid
|
||||
}).then(result => {
|
||||
this.nidState = result.available ? 'ok' : 'unavailable';
|
||||
}).catch(err => {
|
||||
this.nidState = 'error';
|
||||
});
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onSubmit() {
|
||||
(this as any).api('app/create', {
|
||||
name: this.name,
|
||||
nameId: this.nid,
|
||||
description: this.description,
|
||||
callbackUrl: this.cb,
|
||||
permission: this.permission
|
||||
|
@ -70,6 +70,10 @@ export default class MiOS extends EventEmitter {
|
||||
chachedAt: Date;
|
||||
};
|
||||
|
||||
public get instanceName() {
|
||||
return this.meta ? this.meta.data.name : 'Misskey';
|
||||
}
|
||||
|
||||
private isMetaFetching = false;
|
||||
|
||||
public app: Vue;
|
||||
|
@ -30,6 +30,10 @@
|
||||
<span class="data-size">{{ file.datasize | bytes }}</span>
|
||||
<span class="separator"></span>
|
||||
<span class="created-at" @click="showCreatedAt">%fa:R clock%<mk-time :time="file.createdAt"/></span>
|
||||
<template v-if="file.isSensitive">
|
||||
<span class="separator"></span>
|
||||
<span class="nsfw">%fa:eye-slash% %i18n:@nsfw%</span>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<div class="menu">
|
||||
@ -198,6 +202,9 @@ export default Vue.extend({
|
||||
> [data-fa]
|
||||
margin-right 2px
|
||||
|
||||
> .nsfw
|
||||
color #bf4633
|
||||
|
||||
> .menu
|
||||
padding 14px
|
||||
border-top solid 1px #dfdfdf
|
||||
|
@ -14,13 +14,17 @@
|
||||
li.tag(style={background: tag.color, color: contrast(tag.color)})= tag.name
|
||||
-->
|
||||
<footer>
|
||||
<p class="type"><mk-file-type-icon :type="file.type"/>{{ file.type }}</p>
|
||||
<p class="separator"></p>
|
||||
<p class="data-size">{{ file.datasize | bytes }}</p>
|
||||
<p class="separator"></p>
|
||||
<p class="created-at">
|
||||
<span class="type"><mk-file-type-icon :type="file.type"/>{{ file.type }}</span>
|
||||
<span class="separator"></span>
|
||||
<span class="data-size">{{ file.datasize | bytes }}</span>
|
||||
<span class="separator"></span>
|
||||
<span class="created-at">
|
||||
%fa:R clock%<mk-time :time="file.createdAt"/>
|
||||
</p>
|
||||
</span>
|
||||
<template v-if="file.isSensitive">
|
||||
<span class="separator"></span>
|
||||
<span class="nsfw">%fa:eye-slash% %i18n:@nsfw%</span>
|
||||
</template>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
@ -133,35 +137,27 @@ export default Vue.extend({
|
||||
font-size 0.7em
|
||||
|
||||
> .separator
|
||||
display inline
|
||||
margin 0
|
||||
padding 0 4px
|
||||
color #CDCDCD
|
||||
|
||||
> .type
|
||||
display inline
|
||||
margin 0
|
||||
padding 0
|
||||
color #9D9D9D
|
||||
|
||||
> .mk-file-type-icon
|
||||
margin-right 4px
|
||||
|
||||
> .data-size
|
||||
display inline
|
||||
margin 0
|
||||
padding 0
|
||||
color #9D9D9D
|
||||
|
||||
> .created-at
|
||||
display inline
|
||||
margin 0
|
||||
padding 0
|
||||
color #BDBDBD
|
||||
|
||||
> [data-fa]
|
||||
margin-right 2px
|
||||
|
||||
> .nsfw
|
||||
color #bf4633
|
||||
|
||||
&[data-is-selected]
|
||||
background $theme-color
|
||||
|
||||
|
@ -99,7 +99,7 @@ export default Vue.extend({
|
||||
cursor pointer
|
||||
padding 0 16px
|
||||
margin 0
|
||||
min-width 150px
|
||||
min-width 100px
|
||||
line-height 36px
|
||||
font-size 14px
|
||||
font-weight bold
|
||||
|
@ -12,6 +12,7 @@ import noteCard from './note-card.vue';
|
||||
import userCard from './user-card.vue';
|
||||
import noteDetail from './note-detail.vue';
|
||||
import followButton from './follow-button.vue';
|
||||
import muteButton from './mute-button.vue';
|
||||
import friendsMaker from './friends-maker.vue';
|
||||
import notification from './notification.vue';
|
||||
import notifications from './notifications.vue';
|
||||
@ -36,6 +37,7 @@ Vue.component('mk-note-card', noteCard);
|
||||
Vue.component('mk-user-card', userCard);
|
||||
Vue.component('mk-note-detail', noteDetail);
|
||||
Vue.component('mk-follow-button', followButton);
|
||||
Vue.component('mk-mute-button', muteButton);
|
||||
Vue.component('mk-friends-maker', friendsMaker);
|
||||
Vue.component('mk-notification', notification);
|
||||
Vue.component('mk-notifications', notifications);
|
||||
|
79
src/client/app/mobile/views/components/mute-button.vue
Normal file
79
src/client/app/mobile/views/components/mute-button.vue
Normal file
@ -0,0 +1,79 @@
|
||||
<template>
|
||||
<button
|
||||
class="mk-mute-button"
|
||||
:class="{ active: user.isMuted }"
|
||||
@click="onClick">
|
||||
<span v-if="!user.isMuted">%fa:eye-slash% %i18n:@mute%</span>
|
||||
<span v-else>%fa:eye% %i18n:@unmute%</span>
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue'
|
||||
export default Vue.extend({
|
||||
props: {
|
||||
user: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onClick() {
|
||||
if (!this.user.isMuted) {
|
||||
this.mute();
|
||||
} else {
|
||||
this.unmute();
|
||||
}
|
||||
},
|
||||
mute() {
|
||||
(this as any).api('mute/create', { userId: this.user.id})
|
||||
.then(() => { this.user.isMuted = true })
|
||||
.catch(() => { alert('error')})
|
||||
},
|
||||
unmute() {
|
||||
(this as any).api('mute/delete', { userId: this.user.id })
|
||||
.then(() => { this.user.isMuted = false })
|
||||
.catch(() => { alert('error') })
|
||||
}
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
@import '~const.styl'
|
||||
|
||||
.mk-mute-button
|
||||
display block
|
||||
user-select none
|
||||
cursor pointer
|
||||
padding 0 16px
|
||||
margin 0
|
||||
min-width 100px
|
||||
line-height 36px
|
||||
font-size 14px
|
||||
font-weight bold
|
||||
color $theme-color
|
||||
background transparent
|
||||
outline none
|
||||
border solid 1px $theme-color
|
||||
border-radius 36px
|
||||
|
||||
&:hover
|
||||
background rgba($theme-color, 0.1)
|
||||
|
||||
&:active
|
||||
background rgba($theme-color, 0.2)
|
||||
|
||||
&.active
|
||||
color $theme-color-foreground
|
||||
background $theme-color
|
||||
|
||||
&:hover
|
||||
background lighten($theme-color, 10%)
|
||||
border-color lighten($theme-color, 10%)
|
||||
&:active
|
||||
background darken($theme-color, 10%)
|
||||
border-color darken($theme-color, 10%)
|
||||
|
||||
</style>
|
@ -38,7 +38,6 @@
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
import getNoteSummary from '../../../../../misc/get-note-summary';
|
||||
import * as config from '../../../config';
|
||||
|
||||
const displayLimit = 30;
|
||||
|
||||
@ -190,7 +189,7 @@ export default Vue.extend({
|
||||
|
||||
clearNotification() {
|
||||
this.unreadCount = 0;
|
||||
document.title = config.name;
|
||||
document.title = (this as any).os.instanceName;
|
||||
},
|
||||
|
||||
onVisibilitychange() {
|
||||
|
@ -56,7 +56,7 @@ import Vue from 'vue';
|
||||
import insertTextAtCursor from 'insert-text-at-cursor';
|
||||
import * as XDraggable from 'vuedraggable';
|
||||
import MkVisibilityChooser from '../../../common/views/components/visibility-chooser.vue';
|
||||
import getKao from '../../../common/scripts/get-kao';
|
||||
import getFace from '../../../common/scripts/get-face';
|
||||
import parse from '../../../../../mfm/parse';
|
||||
import { host } from '../../../config';
|
||||
|
||||
@ -313,7 +313,7 @@ export default Vue.extend({
|
||||
},
|
||||
|
||||
kao() {
|
||||
this.text += getKao();
|
||||
this.text += getFace();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -8,7 +8,7 @@
|
||||
<button class="nav" @click="$parent.isDrawerOpening = true">%fa:bars%</button>
|
||||
<template v-if="hasUnreadNotification || hasUnreadMessagingMessage || hasGameInvitation">%fa:circle%</template>
|
||||
<h1>
|
||||
<slot>config.name</slot>
|
||||
<slot>{{ os.instanceName }}</slot>
|
||||
</h1>
|
||||
<slot name="func"></slot>
|
||||
</div>
|
||||
@ -20,13 +20,11 @@
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
import * as anime from 'animejs';
|
||||
import * as config from '../../../config';
|
||||
|
||||
export default Vue.extend({
|
||||
props: ['func'],
|
||||
data() {
|
||||
return {
|
||||
config,
|
||||
hasGameInvitation: false,
|
||||
connection: null,
|
||||
connectionId: null
|
||||
|
@ -30,6 +30,7 @@
|
||||
<ul>
|
||||
<li><a @click="search">%fa:search%%i18n:@search%%fa:angle-right%</a></li>
|
||||
<li><router-link to="/i/settings" :data-active="$route.name == 'settings'">%fa:cog%%i18n:@settings%%fa:angle-right%</router-link></li>
|
||||
<li v-if="$store.getters.isSignedIn && $store.state.i.isAdmin"><router-link to="/admin">%fa:terminal%<span>%i18n:@admin%</span>%fa:angle-right%</router-link></li>
|
||||
<li @click="dark"><p><template v-if="$store.state.device.darkmode">%fa:moon%</template><template v-else>%fa:R moon%</template><span>%i18n:@darkmode%</span></p></li>
|
||||
</ul>
|
||||
</div>
|
||||
@ -41,7 +42,7 @@
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
import { docsUrl, lang } from '../../../config';
|
||||
import { lang } from '../../../config';
|
||||
|
||||
export default Vue.extend({
|
||||
props: ['isOpen'],
|
||||
@ -50,7 +51,7 @@ export default Vue.extend({
|
||||
hasGameInvitation: false,
|
||||
connection: null,
|
||||
connectionId: null,
|
||||
aboutUrl: `${docsUrl}/${lang}/about`
|
||||
aboutUrl: `/docs/${lang}/about`
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
@ -25,7 +25,6 @@
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
import Progress from '../../../common/scripts/loading';
|
||||
import * as config from '../../../config';
|
||||
|
||||
export default Vue.extend({
|
||||
data() {
|
||||
@ -44,7 +43,7 @@ export default Vue.extend({
|
||||
window.addEventListener('popstate', this.onPopState);
|
||||
},
|
||||
mounted() {
|
||||
document.title = `${config.name} Drive`;
|
||||
document.title = `${(this as any).os.instanceName} Drive`;
|
||||
document.documentElement.style.background = '#fff';
|
||||
},
|
||||
beforeDestroy() {
|
||||
@ -64,7 +63,7 @@ export default Vue.extend({
|
||||
(this.$refs as any).browser.openContextMenu();
|
||||
},
|
||||
onMoveRoot(silent) {
|
||||
const title = `${config.name} Drive`;
|
||||
const title = `${(this as any).os.instanceName} Drive`;
|
||||
|
||||
if (!silent) {
|
||||
// Rewrite URL
|
||||
@ -77,7 +76,7 @@ export default Vue.extend({
|
||||
this.folder = null;
|
||||
},
|
||||
onOpenFolder(folder, silent) {
|
||||
const title = `${folder.name} | ${config.name} Drive`;
|
||||
const title = `${folder.name} | ${(this as any).os.instanceName} Drive`;
|
||||
|
||||
if (!silent) {
|
||||
// Rewrite URL
|
||||
@ -90,7 +89,7 @@ export default Vue.extend({
|
||||
this.folder = folder;
|
||||
},
|
||||
onOpenFile(file, silent) {
|
||||
const title = `${file.name} | ${config.name} Drive`;
|
||||
const title = `${file.name} | ${(this as any).os.instanceName} Drive`;
|
||||
|
||||
if (!silent) {
|
||||
// Rewrite URL
|
||||
|
@ -14,7 +14,6 @@
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
import Progress from '../../../common/scripts/loading';
|
||||
import * as config from '../../../config';
|
||||
|
||||
export default Vue.extend({
|
||||
data() {
|
||||
@ -29,7 +28,7 @@ export default Vue.extend({
|
||||
this.fetch();
|
||||
},
|
||||
mounted() {
|
||||
document.title = `${config.name} | %i18n:@notifications%`;
|
||||
document.title = `${(this as any).os.instanceName} | %i18n:@notifications%`;
|
||||
},
|
||||
methods: {
|
||||
fetch() {
|
||||
|
@ -21,7 +21,6 @@ import Vue from 'vue';
|
||||
import Progress from '../../../common/scripts/loading';
|
||||
import parseAcct from '../../../../../misc/acct/parse';
|
||||
import getUserName from '../../../../../misc/get-user-name';
|
||||
import * as config from '../../../config';
|
||||
|
||||
export default Vue.extend({
|
||||
data() {
|
||||
@ -50,7 +49,7 @@ export default Vue.extend({
|
||||
this.user = user;
|
||||
this.fetching = false;
|
||||
|
||||
document.title = '%i18n:@followers-of%'.replace('{}', this.name) + ' | ' + config.name;
|
||||
document.title = '%i18n:@followers-of%'.replace('{}', this.name) + ' | ' + (this as any).os.instanceName;
|
||||
});
|
||||
},
|
||||
onLoaded() {
|
||||
|
@ -20,7 +20,6 @@
|
||||
import Vue from 'vue';
|
||||
import Progress from '../../../common/scripts/loading';
|
||||
import parseAcct from '../../../../../misc/acct/parse';
|
||||
import * as config from '../../../config';
|
||||
|
||||
export default Vue.extend({
|
||||
data() {
|
||||
@ -49,7 +48,7 @@ export default Vue.extend({
|
||||
this.user = user;
|
||||
this.fetching = false;
|
||||
|
||||
document.title = '%i18n:@followers-of%'.replace('{}', this.name) + ' | ' + config.name;
|
||||
document.title = '%i18n:@followers-of%'.replace('{}', this.name) + ' | ' + (this as any).os.instanceName;
|
||||
});
|
||||
},
|
||||
onLoaded() {
|
||||
|
@ -7,11 +7,10 @@
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
import * as config from '../../../../config';
|
||||
|
||||
export default Vue.extend({
|
||||
mounted() {
|
||||
document.title = `${config.name} %i18n:@reversi%`;
|
||||
document.title = `${(this as any).os.instanceName} %i18n:@reversi%`;
|
||||
document.documentElement.style.background = '#fff';
|
||||
},
|
||||
methods: {
|
||||
|
@ -49,7 +49,6 @@
|
||||
import Vue from 'vue';
|
||||
import Progress from '../../../common/scripts/loading';
|
||||
import XTl from './home.timeline.vue';
|
||||
import * as config from '../../../config';
|
||||
|
||||
export default Vue.extend({
|
||||
components: {
|
||||
@ -97,7 +96,7 @@ export default Vue.extend({
|
||||
},
|
||||
|
||||
mounted() {
|
||||
document.title = config.name;
|
||||
document.title = (this as any).os.instanceName;
|
||||
|
||||
Progress.start();
|
||||
|
||||
|
@ -11,7 +11,6 @@
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
import parseAcct from '../../../../../misc/acct/parse';
|
||||
import * as config from '../../../config';
|
||||
|
||||
export default Vue.extend({
|
||||
data() {
|
||||
@ -48,7 +47,7 @@ export default Vue.extend({
|
||||
this.user = user;
|
||||
this.fetching = false;
|
||||
|
||||
document.title = `%i18n:@messaging%: ${Vue.filter('userName')(this.user)} | ${config.name}`;
|
||||
document.title = `%i18n:@messaging%: ${Vue.filter('userName')(this.user)} | ${(this as any).os.instanceName}`;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -8,11 +8,10 @@
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
import getAcct from '../../../../../misc/acct/render';
|
||||
import * as config from '../../../config';
|
||||
|
||||
export default Vue.extend({
|
||||
mounted() {
|
||||
document.title = `${config.name} %i18n:@messaging%`;
|
||||
document.title = `${(this as any).os.instanceName} %i18n:@messaging%`;
|
||||
},
|
||||
methods: {
|
||||
navigate(user) {
|
||||
|
@ -16,7 +16,6 @@
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
import Progress from '../../../common/scripts/loading';
|
||||
import * as config from '../../../config';
|
||||
|
||||
export default Vue.extend({
|
||||
data() {
|
||||
@ -32,7 +31,7 @@ export default Vue.extend({
|
||||
this.fetch();
|
||||
},
|
||||
mounted() {
|
||||
document.title = config.name;
|
||||
document.title = (this as any).os.instanceName;
|
||||
},
|
||||
methods: {
|
||||
fetch() {
|
||||
|
@ -12,7 +12,6 @@
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
import Progress from '../../../common/scripts/loading';
|
||||
import * as config from '../../../config';
|
||||
|
||||
const limit = 20;
|
||||
|
||||
@ -35,7 +34,7 @@ export default Vue.extend({
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
document.title = `%i18n:@search%: ${this.q} | ${config.name}`;
|
||||
document.title = `%i18n:@search%: ${this.q} | ${(this as any).os.instanceName}`;
|
||||
|
||||
this.fetch();
|
||||
},
|
||||
|
@ -13,8 +13,9 @@
|
||||
<ui-switch v-model="darkmode">%i18n:@dark-mode%</ui-switch>
|
||||
<ui-switch v-model="$store.state.settings.circleIcons" @change="onChangeCircleIcons">%i18n:@circle-icons%</ui-switch>
|
||||
<ui-switch v-model="$store.state.settings.iLikeSushi" @change="onChangeILikeSushi">%i18n:common.i-like-sushi%</ui-switch>
|
||||
<ui-switch v-model="$store.state.settings.reversiBoardLabels" @change="onChangeReversiBoardLabels">%i18n:common.show-reversi-board-labels%</ui-switch>
|
||||
<ui-switch v-model="$store.state.settings.disableAnimatedMfm" @change="onChangeDisableAnimatedMfm">%i18n:common.disable-animated-mfm%</ui-switch>
|
||||
<ui-switch v-model="$store.state.settings.games.reversi.showBoardLabels" @change="onChangeReversiBoardLabels">%i18n:common.show-reversi-board-labels%</ui-switch>
|
||||
<ui-switch v-model="$store.state.settings.games.reversi.useContrastStones" @change="onChangeUseContrastReversiStones">%i18n:common.use-contrast-reversi-stones%</ui-switch>
|
||||
|
||||
<div>
|
||||
<div>%i18n:@timeline%</div>
|
||||
@ -189,7 +190,14 @@ export default Vue.extend({
|
||||
|
||||
onChangeReversiBoardLabels(v) {
|
||||
this.$store.dispatch('settings/set', {
|
||||
key: 'reversiBoardLabels',
|
||||
key: 'games.reversi.showBoardLabels',
|
||||
value: v
|
||||
});
|
||||
},
|
||||
|
||||
onChangeUseContrastReversiStones(v) {
|
||||
this.$store.dispatch('settings/set', {
|
||||
key: 'games.reversi.useContrastStones',
|
||||
value: v
|
||||
});
|
||||
},
|
||||
|
@ -91,15 +91,15 @@ export default Vue.extend({
|
||||
method: 'POST',
|
||||
body: data
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(f => {
|
||||
this.avatarId = f.id;
|
||||
this.avatarUploading = false;
|
||||
})
|
||||
.catch(e => {
|
||||
this.avatarUploading = false;
|
||||
alert('%18n:!@upload-failed%');
|
||||
});
|
||||
.then(response => response.json())
|
||||
.then(f => {
|
||||
this.avatarId = f.id;
|
||||
this.avatarUploading = false;
|
||||
})
|
||||
.catch(e => {
|
||||
this.avatarUploading = false;
|
||||
alert('%18n:@upload-failed%');
|
||||
});
|
||||
},
|
||||
|
||||
onBannerChange([file]) {
|
||||
@ -113,15 +113,15 @@ export default Vue.extend({
|
||||
method: 'POST',
|
||||
body: data
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(f => {
|
||||
this.bannerId = f.id;
|
||||
this.bannerUploading = false;
|
||||
})
|
||||
.catch(e => {
|
||||
this.bannerUploading = false;
|
||||
alert('%18n:!@upload-failed%');
|
||||
});
|
||||
.then(response => response.json())
|
||||
.then(f => {
|
||||
this.bannerId = f.id;
|
||||
this.bannerUploading = false;
|
||||
})
|
||||
.catch(e => {
|
||||
this.bannerUploading = false;
|
||||
alert('%18n:@upload-failed%');
|
||||
});
|
||||
},
|
||||
|
||||
save() {
|
||||
|
@ -12,12 +12,11 @@
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
import * as config from '../../../config';
|
||||
|
||||
export default Vue.extend({
|
||||
data() {
|
||||
return {
|
||||
name: config.name,
|
||||
name: (this as any).os.instanceName,
|
||||
posted: false,
|
||||
text: new URLSearchParams(location.search).get('text')
|
||||
};
|
||||
|
@ -11,6 +11,7 @@
|
||||
<a class="avatar">
|
||||
<img :src="user.avatarUrl" alt="avatar"/>
|
||||
</a>
|
||||
<mk-mute-button v-if="$store.state.i.id != user.id" :user="user"/>
|
||||
<mk-follow-button v-if="$store.getters.isSignedIn && $store.state.i.id != user.id" :user="user"/>
|
||||
</div>
|
||||
<div class="title">
|
||||
@ -67,7 +68,6 @@ import * as age from 's-age';
|
||||
import parseAcct from '../../../../../misc/acct/parse';
|
||||
import Progress from '../../../common/scripts/loading';
|
||||
import XHome from './user/home.vue';
|
||||
import * as config from '../../../config';
|
||||
|
||||
export default Vue.extend({
|
||||
components: {
|
||||
@ -107,7 +107,7 @@ export default Vue.extend({
|
||||
this.fetching = false;
|
||||
|
||||
Progress.done();
|
||||
document.title = Vue.filter('userName')(this.user) + ' | ' + config.name;
|
||||
document.title = Vue.filter('userName')(this.user) + ' | ' + (this as any).os.instanceName;
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -185,6 +185,9 @@ root(isDark)
|
||||
border 4px solid $bg
|
||||
border-radius 12px
|
||||
|
||||
> .mk-mute-button
|
||||
float right
|
||||
|
||||
> .mk-follow-button
|
||||
float right
|
||||
|
||||
@ -248,7 +251,7 @@ root(isDark)
|
||||
top 47px
|
||||
box-shadow 0 4px 4px isDark ? rgba(#000, 0.3) : rgba(#000, 0.07)
|
||||
background-color $bg
|
||||
z-index 1
|
||||
z-index 2
|
||||
|
||||
> .nav-container
|
||||
display flex
|
||||
|
@ -30,7 +30,7 @@
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
import { apiUrl, copyright, host, name, description } from '../../../config';
|
||||
import { apiUrl, copyright, host } from '../../../config';
|
||||
|
||||
export default Vue.extend({
|
||||
data() {
|
||||
@ -39,12 +39,17 @@ export default Vue.extend({
|
||||
copyright,
|
||||
stats: null,
|
||||
host,
|
||||
name,
|
||||
description,
|
||||
name: 'Misskey',
|
||||
description: '',
|
||||
tags: []
|
||||
};
|
||||
},
|
||||
created() {
|
||||
(this as any).os.getMeta().then(meta => {
|
||||
this.name = meta.name;
|
||||
this.description = meta.description;
|
||||
});
|
||||
|
||||
(this as any).api('stats').then(stats => {
|
||||
this.stats = stats;
|
||||
});
|
||||
|
@ -53,7 +53,6 @@
|
||||
import Vue from 'vue';
|
||||
import * as XDraggable from 'vuedraggable';
|
||||
import * as uuid from 'uuid';
|
||||
import * as config from '../../../config';
|
||||
|
||||
export default Vue.extend({
|
||||
components: {
|
||||
@ -103,7 +102,7 @@ export default Vue.extend({
|
||||
},
|
||||
|
||||
mounted() {
|
||||
document.title = config.name;
|
||||
document.title = (this as any).os.instanceName;
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
@ -1,10 +0,0 @@
|
||||
@import "../app"
|
||||
@import "../reset"
|
||||
|
||||
html
|
||||
color #456267
|
||||
background #fff
|
||||
|
||||
body
|
||||
margin 0
|
||||
padding 0
|
@ -1,209 +0,0 @@
|
||||
<mk-index>
|
||||
<h1>Misskey<i>Statistics</i></h1>
|
||||
<main v-if="!initializing">
|
||||
<mk-users stats={ stats }/>
|
||||
<mk-notes stats={ stats }/>
|
||||
</main>
|
||||
<footer><a href={ _URL_ }>{ _HOST_ }</a></footer>
|
||||
<style lang="stylus" scoped>
|
||||
:scope
|
||||
display block
|
||||
margin 0 auto
|
||||
padding 0 16px
|
||||
max-width 700px
|
||||
|
||||
> h1
|
||||
margin 0
|
||||
padding 24px 0 0 0
|
||||
font-size 24px
|
||||
font-weight normal
|
||||
|
||||
> i
|
||||
font-style normal
|
||||
color #f43b16
|
||||
|
||||
> main
|
||||
> *
|
||||
margin 24px 0
|
||||
padding-top 24px
|
||||
border-top solid 1px #eee
|
||||
|
||||
> h2
|
||||
margin 0 0 12px 0
|
||||
font-size 18px
|
||||
font-weight normal
|
||||
|
||||
> footer
|
||||
margin 24px 0
|
||||
text-align center
|
||||
|
||||
> a
|
||||
color #546567
|
||||
</style>
|
||||
<script lang="typescript">
|
||||
this.mixin('api');
|
||||
|
||||
this.initializing = true;
|
||||
|
||||
this.on('mount', () => {
|
||||
this.$root.$data.os.api('stats').then(stats => {
|
||||
this.update({
|
||||
initializing: false,
|
||||
stats
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</mk-index>
|
||||
|
||||
<mk-notes>
|
||||
<h2>%i18n:stats.notes-count% <b>{ stats.notesCount }</b></h2>
|
||||
<mk-notes-chart v-if="!initializing" data={ data }/>
|
||||
<style lang="stylus" scoped>
|
||||
:scope
|
||||
display block
|
||||
</style>
|
||||
<script lang="typescript">
|
||||
this.mixin('api');
|
||||
|
||||
this.initializing = true;
|
||||
this.stats = this.opts.stats;
|
||||
|
||||
this.on('mount', () => {
|
||||
this.$root.$data.os.api('aggregation/notes', {
|
||||
limit: 365
|
||||
}).then(data => {
|
||||
this.update({
|
||||
initializing: false,
|
||||
data
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</mk-notes>
|
||||
|
||||
<mk-users>
|
||||
<h2>%i18n:stats.users-count% <b>{ stats.usersCount }</b></h2>
|
||||
<mk-users-chart v-if="!initializing" data={ data }/>
|
||||
<style lang="stylus" scoped>
|
||||
:scope
|
||||
display block
|
||||
</style>
|
||||
<script lang="typescript">
|
||||
this.mixin('api');
|
||||
|
||||
this.initializing = true;
|
||||
this.stats = this.opts.stats;
|
||||
|
||||
this.on('mount', () => {
|
||||
this.$root.$data.os.api('aggregation/users', {
|
||||
limit: 365
|
||||
}).then(data => {
|
||||
this.update({
|
||||
initializing: false,
|
||||
data
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</mk-users>
|
||||
|
||||
<mk-notes-chart>
|
||||
<svg riot-viewBox="0 0 { viewBoxX } { viewBoxY }" preserveAspectRatio="none">
|
||||
<title>Black ... Total<br/>Blue ... Notes<br/>Red ... Replies<br/>Green ... Renotes</title>
|
||||
<polyline
|
||||
riot-points={ pointsNote }
|
||||
fill="none"
|
||||
stroke-width="1"
|
||||
stroke="#41ddde"/>
|
||||
<polyline
|
||||
riot-points={ pointsReply }
|
||||
fill="none"
|
||||
stroke-width="1"
|
||||
stroke="#f7796c"/>
|
||||
<polyline
|
||||
riot-points={ pointsRenote }
|
||||
fill="none"
|
||||
stroke-width="1"
|
||||
stroke="#a1de41"/>
|
||||
<polyline
|
||||
riot-points={ pointsTotal }
|
||||
fill="none"
|
||||
stroke-width="1"
|
||||
stroke="#555"
|
||||
stroke-dasharray="2 2"/>
|
||||
</svg>
|
||||
<style lang="stylus" scoped>
|
||||
:scope
|
||||
display block
|
||||
|
||||
> svg
|
||||
display block
|
||||
padding 1px
|
||||
width 100%
|
||||
</style>
|
||||
<script lang="typescript">
|
||||
this.viewBoxX = 365;
|
||||
this.viewBoxY = 80;
|
||||
|
||||
this.data = this.opts.data.reverse();
|
||||
this.data.forEach(d => d.total = d.notes + d.replies + d.renotes);
|
||||
const peak = Math.max.apply(null, this.data.map(d => d.total));
|
||||
|
||||
this.on('mount', () => {
|
||||
this.render();
|
||||
});
|
||||
|
||||
this.render = () => {
|
||||
this.update({
|
||||
pointsNote: this.data.map((d, i) => `${i},${(1 - (d.notes / peak)) * this.viewBoxY}`).join(' '),
|
||||
pointsReply: this.data.map((d, i) => `${i},${(1 - (d.replies / peak)) * this.viewBoxY}`).join(' '),
|
||||
pointsRenote: this.data.map((d, i) => `${i},${(1 - (d.renotes / peak)) * this.viewBoxY}`).join(' '),
|
||||
pointsTotal: this.data.map((d, i) => `${i},${(1 - (d.total / peak)) * this.viewBoxY}`).join(' ')
|
||||
});
|
||||
};
|
||||
</script>
|
||||
</mk-notes-chart>
|
||||
|
||||
<mk-users-chart>
|
||||
<svg riot-viewBox="0 0 { viewBoxX } { viewBoxY }" preserveAspectRatio="none">
|
||||
<polyline
|
||||
riot-points={ createdPoints }
|
||||
fill="none"
|
||||
stroke-width="1"
|
||||
stroke="#1cde84"/>
|
||||
<polyline
|
||||
riot-points={ totalPoints }
|
||||
fill="none"
|
||||
stroke-width="1"
|
||||
stroke="#555"/>
|
||||
</svg>
|
||||
<style lang="stylus" scoped>
|
||||
:scope
|
||||
display block
|
||||
|
||||
> svg
|
||||
display block
|
||||
padding 1px
|
||||
width 100%
|
||||
</style>
|
||||
<script lang="typescript">
|
||||
this.viewBoxX = 365;
|
||||
this.viewBoxY = 80;
|
||||
|
||||
this.data = this.opts.data.reverse();
|
||||
const totalPeak = Math.max.apply(null, this.data.map(d => d.total));
|
||||
const createdPeak = Math.max.apply(null, this.data.map(d => d.created));
|
||||
|
||||
this.on('mount', () => {
|
||||
this.render();
|
||||
});
|
||||
|
||||
this.render = () => {
|
||||
this.update({
|
||||
totalPoints: this.data.map((d, i) => `${i},${(1 - (d.total / totalPeak)) * this.viewBoxY}`).join(' '),
|
||||
createdPoints: this.data.map((d, i) => `${i},${(1 - (d.created / createdPeak)) * this.viewBoxY}`).join(' ')
|
||||
});
|
||||
};
|
||||
</script>
|
||||
</mk-users-chart>
|
@ -1 +0,0 @@
|
||||
require('./index.tag');
|
@ -1,10 +0,0 @@
|
||||
@import "../app"
|
||||
@import "../reset"
|
||||
|
||||
html
|
||||
color #456267
|
||||
background #fff
|
||||
|
||||
body
|
||||
margin 0
|
||||
padding 0
|
@ -1,201 +0,0 @@
|
||||
<mk-index>
|
||||
<h1>Misskey<i>Status</i></h1>
|
||||
<p>%fa:info-circle%%i18n:status.all-systems-maybe-operational%</p>
|
||||
<main>
|
||||
<mk-cpu-usage connection={ connection }/>
|
||||
<mk-mem-usage connection={ connection }/>
|
||||
</main>
|
||||
<footer><a href={ _URL_ }>{ _HOST_ }</a></footer>
|
||||
<style lang="stylus" scoped>
|
||||
:scope
|
||||
display block
|
||||
margin 0 auto
|
||||
padding 0 16px
|
||||
max-width 700px
|
||||
|
||||
> h1
|
||||
margin 0
|
||||
padding 24px 0 16px 0
|
||||
font-size 24px
|
||||
font-weight normal
|
||||
|
||||
> [data-fa]
|
||||
font-style normal
|
||||
color #f43b16
|
||||
|
||||
> p
|
||||
display block
|
||||
margin 0
|
||||
padding 12px 16px
|
||||
background #eaf4ef
|
||||
//border solid 1px #99ccb2
|
||||
border-radius 4px
|
||||
|
||||
> [data-fa]
|
||||
margin-right 5px
|
||||
|
||||
> main
|
||||
> *
|
||||
margin 24px 0
|
||||
|
||||
> h2
|
||||
margin 0 0 12px 0
|
||||
font-size 18px
|
||||
font-weight normal
|
||||
|
||||
> footer
|
||||
margin 24px 0
|
||||
text-align center
|
||||
|
||||
> a
|
||||
color #546567
|
||||
</style>
|
||||
<script lang="typescript">
|
||||
import Connection from '../../common/scripts/streaming/server-stream';
|
||||
|
||||
this.mixin('api');
|
||||
|
||||
this.initializing = true;
|
||||
this.connection = new Connection();
|
||||
|
||||
this.on('mount', () => {
|
||||
this.$root.$data.os.api('meta').then(meta => {
|
||||
this.update({
|
||||
initializing: false,
|
||||
meta
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
this.on('unmount', () => {
|
||||
this.connection.close();
|
||||
});
|
||||
|
||||
</script>
|
||||
</mk-index>
|
||||
|
||||
<mk-cpu-usage>
|
||||
<h2>CPU <b>{ percentage }%</b></h2>
|
||||
<mk-line-chart ref="chart"/>
|
||||
<style lang="stylus" scoped>
|
||||
:scope
|
||||
display block
|
||||
</style>
|
||||
<script lang="typescript">
|
||||
this.connection = this.opts.connection;
|
||||
|
||||
this.on('mount', () => {
|
||||
this.connection.on('stats', this.onStats);
|
||||
});
|
||||
|
||||
this.on('unmount', () => {
|
||||
this.connection.off('stats', this.onStats);
|
||||
});
|
||||
|
||||
this.onStats = stats => {
|
||||
this.$refs.chart.addData(1 - stats.cpu_usage);
|
||||
|
||||
const percentage = (stats.cpu_usage * 100).toFixed(0);
|
||||
|
||||
this.update({
|
||||
percentage
|
||||
});
|
||||
};
|
||||
</script>
|
||||
</mk-cpu-usage>
|
||||
|
||||
<mk-mem-usage>
|
||||
<h2>MEM <b>{ percentage }%</b></h2>
|
||||
<mk-line-chart ref="chart"/>
|
||||
<style lang="stylus" scoped>
|
||||
:scope
|
||||
display block
|
||||
</style>
|
||||
<script lang="typescript">
|
||||
this.connection = this.opts.connection;
|
||||
|
||||
this.on('mount', () => {
|
||||
this.connection.on('stats', this.onStats);
|
||||
});
|
||||
|
||||
this.on('unmount', () => {
|
||||
this.connection.off('stats', this.onStats);
|
||||
});
|
||||
|
||||
this.onStats = stats => {
|
||||
stats.mem.used = stats.mem.total - stats.mem.free;
|
||||
this.$refs.chart.addData(1 - (stats.mem.used / stats.mem.total));
|
||||
|
||||
const percentage = (stats.mem.used / stats.mem.total * 100).toFixed(0);
|
||||
|
||||
this.update({
|
||||
percentage
|
||||
});
|
||||
};
|
||||
</script>
|
||||
</mk-mem-usage>
|
||||
|
||||
<mk-line-chart>
|
||||
<svg riot-viewBox="0 0 { viewBoxX } { viewBoxY }" preserveAspectRatio="none">
|
||||
<defs>
|
||||
<linearGradient id={ gradientId } x1="0" x2="0" y1="1" y2="0">
|
||||
<stop offset="0%" stop-color="rgba(244, 59, 22, 0)"></stop>
|
||||
<stop offset="100%" stop-color="#f43b16"></stop>
|
||||
</linearGradient>
|
||||
<mask id={ maskId } x="0" y="0" riot-width={ viewBoxX } riot-height={ viewBoxY }>
|
||||
<polygon
|
||||
riot-points={ polygonPoints }
|
||||
fill="#fff"
|
||||
fill-opacity="0.5"/>
|
||||
</mask>
|
||||
</defs>
|
||||
<line x1="0" y1="0" riot-x2={ viewBoxX } y2="0" stroke="rgba(255, 255, 255, 0.1)" stroke-width="0.25" stroke-dasharray="1"/>
|
||||
<line x1="0" y1="25%" riot-x2={ viewBoxX } y2="25%" stroke="rgba(255, 255, 255, 0.1)" stroke-width="0.25" stroke-dasharray="1"/>
|
||||
<line x1="0" y1="50%" riot-x2={ viewBoxX } y2="50%" stroke="rgba(255, 255, 255, 0.1)" stroke-width="0.25" stroke-dasharray="1"/>
|
||||
<line x1="0" y1="75%" riot-x2={ viewBoxX } y2="75%" stroke="rgba(255, 255, 255, 0.1)" stroke-width="0.25" stroke-dasharray="1"/>
|
||||
<line x1="0" y1="100%" riot-x2={ viewBoxX } y2="100%" stroke="rgba(255, 255, 255, 0.1)" stroke-width="0.25" stroke-dasharray="1"/>
|
||||
<rect
|
||||
x="-1" y="-1"
|
||||
riot-width={ viewBoxX + 2 } riot-height={ viewBoxY + 2 }
|
||||
style="stroke: none; fill: url(#{ gradientId }); mask: url(#{ maskId })"/>
|
||||
<polyline
|
||||
riot-points={ polylinePoints }
|
||||
fill="none"
|
||||
stroke="#f43b16"
|
||||
stroke-width="0.5"/>
|
||||
</svg>
|
||||
<style lang="stylus" scoped>
|
||||
:scope
|
||||
display block
|
||||
padding 16px
|
||||
border-radius 8px
|
||||
background #1c2531
|
||||
|
||||
> svg
|
||||
display block
|
||||
padding 1px
|
||||
width 100%
|
||||
</style>
|
||||
<script lang="typescript">
|
||||
import uuid from 'uuid';
|
||||
|
||||
this.viewBoxX = 100;
|
||||
this.viewBoxY = 30;
|
||||
this.data = [];
|
||||
this.gradientId = uuid();
|
||||
this.maskId = uuid();
|
||||
|
||||
this.addData = data => {
|
||||
this.data.push(data);
|
||||
if (this.data.length > 100) this.data.shift();
|
||||
|
||||
const polylinePoints = this.data.map((d, i) => `${this.viewBoxX - ((this.data.length - 1) - i)},${d * this.viewBoxY}`).join(' ');
|
||||
const polygonPoints = `${this.viewBoxX - (this.data.length - 1)},${ this.viewBoxY } ${ polylinePoints } ${ this.viewBoxX },${ this.viewBoxY }`;
|
||||
|
||||
this.update({
|
||||
polylinePoints,
|
||||
polygonPoints
|
||||
});
|
||||
};
|
||||
</script>
|
||||
</mk-line-chart>
|
@ -1 +0,0 @@
|
||||
require('./index.tag');
|
@ -1,5 +1,6 @@
|
||||
import Vuex from 'vuex';
|
||||
import createPersistedState from 'vuex-persistedstate';
|
||||
import * as nestedProperty from 'nested-property';
|
||||
|
||||
import MiOS from './mios';
|
||||
import { hostname } from './config';
|
||||
@ -22,7 +23,12 @@ const defaultSettings = {
|
||||
disableViaMobile: false,
|
||||
memo: null,
|
||||
iLikeSushi: false,
|
||||
reversiBoardLabels: false
|
||||
games: {
|
||||
reversi: {
|
||||
showBoardLabels: false,
|
||||
useContrastStones: false
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const defaultDeviceSettings = {
|
||||
@ -125,7 +131,7 @@ export default (os: MiOS) => new Vuex.Store({
|
||||
|
||||
mutations: {
|
||||
set(state, x: { key: string; value: any }) {
|
||||
state[x.key] = x.value;
|
||||
nestedProperty.set(state, x.key, x.value);
|
||||
},
|
||||
|
||||
setHome(state, data) {
|
||||
|
6
src/client/assets/label-red.svg
Normal file
6
src/client/assets/label-red.svg
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
|
||||
y="0px" width="96px" height="96px" viewBox="0 0 96 96" enable-background="new 0 0 96 96" xml:space="preserve">
|
||||
<polygon fill="#ea2412" points="0,45.255 45.254,0 84.854,0 0,84.854 "/>
|
||||
</svg>
|
After Width: | Height: | Size: 441 B |
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user