Compare commits
103 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e3ade148ca | ||
|
|
34c0eff89f | ||
|
|
40aba47a47 | ||
|
|
6736f51134 | ||
|
|
9d826d6e52 | ||
|
|
902d9bc7a5 | ||
|
|
b6c86e2845 | ||
|
|
34dffdfc8f | ||
|
|
a56f3f1d89 | ||
|
|
88dc4c83cb | ||
|
|
5a28dc0198 | ||
|
|
40d2650d49 | ||
|
|
545e83efb1 | ||
|
|
d4b00a5482 | ||
|
|
c2b1bbeec5 | ||
|
|
8c8f165a6e | ||
|
|
04553de230 | ||
|
|
2776934728 | ||
|
|
0064dbb010 | ||
|
|
d52e671adf | ||
|
|
6017dc2dff | ||
|
|
937f7cbd60 | ||
|
|
f8b3f66904 | ||
|
|
9d5701f35a | ||
|
|
dff65810c6 | ||
|
|
6752cf1d64 | ||
|
|
8336910a59 | ||
|
|
957a1149e0 | ||
|
|
e8719ff6e6 | ||
|
|
28b63298e5 | ||
|
|
dd4dee8095 | ||
|
|
c47818fed4 | ||
|
|
e53c383908 | ||
|
|
55c9c0436b | ||
|
|
66b79e5e24 | ||
|
|
514b830910 | ||
|
|
e4f799bf1d | ||
|
|
b383427d3d | ||
|
|
e969518139 | ||
|
|
113fe294bd | ||
|
|
a4d92f781f | ||
|
|
414cac49c3 | ||
|
|
95b157ac3e | ||
|
|
8e3d884081 | ||
|
|
9def6fcadd | ||
|
|
7837bd44fc | ||
|
|
a6c3663155 | ||
|
|
0b5afadbb8 | ||
|
|
43864f0da4 | ||
|
|
6a0d9d70ed | ||
|
|
63c6dce68e | ||
|
|
53422ffcb2 | ||
|
|
38ca514f53 | ||
|
|
caea0f0376 | ||
|
|
25a8b26977 | ||
|
|
bcaefe8d62 | ||
|
|
46f1e8c599 | ||
|
|
16230f320e | ||
|
|
ace6419aef | ||
|
|
77fb9eb2be | ||
|
|
aa7fc7c893 | ||
|
|
8fc170109f | ||
|
|
ad12d00d7e | ||
|
|
fa5ea45726 | ||
|
|
4b6c113251 | ||
|
|
3548290ff2 | ||
|
|
b165b90c40 | ||
|
|
4ffe9c908b | ||
|
|
a135f75e71 | ||
|
|
cbc61ba03d | ||
|
|
5aa58da918 | ||
|
|
b083430011 | ||
|
|
a8946b0404 | ||
|
|
0303bccc61 | ||
|
|
f3ce8564ea | ||
|
|
52c3f9e98c | ||
|
|
6c8b4184fe | ||
|
|
a0979f8435 | ||
|
|
faba21d003 | ||
|
|
d82c5dff71 | ||
|
|
59fbc5b054 | ||
|
|
2c1a7f4392 | ||
|
|
769e6182d8 | ||
|
|
88176a17a3 | ||
|
|
fc660e869f | ||
|
|
dc04869650 | ||
|
|
93c3f34813 | ||
|
|
1282eed192 | ||
|
|
962b3ca78e | ||
|
|
62d17c9266 | ||
|
|
f5b928a537 | ||
|
|
c8811894b5 | ||
|
|
e579b49228 | ||
|
|
9561908ad3 | ||
|
|
fac7ebf4f6 | ||
|
|
a0769d65e3 | ||
|
|
d17aa4b24e | ||
|
|
310371658b | ||
|
|
7ca073aafd | ||
|
|
7216d0fb1f | ||
|
|
22a9e950c7 | ||
|
|
6683d50bae | ||
|
|
8f26176273 |
@@ -2,6 +2,11 @@ version: 2.1
|
|||||||
|
|
||||||
executors:
|
executors:
|
||||||
default:
|
default:
|
||||||
|
working_directory: /tmp/workspace
|
||||||
|
docker:
|
||||||
|
- image: misskey/ci:latest
|
||||||
|
- image: circleci/mongo:latest
|
||||||
|
with-redis:
|
||||||
working_directory: /tmp/workspace
|
working_directory: /tmp/workspace
|
||||||
docker:
|
docker:
|
||||||
- image: misskey/ci:latest
|
- image: misskey/ci:latest
|
||||||
@@ -24,7 +29,6 @@ jobs:
|
|||||||
name: OK
|
name: OK
|
||||||
command: |
|
command: |
|
||||||
echo -e '\033[0;32mOK\033[0;39m'
|
echo -e '\033[0;32mOK\033[0;39m'
|
||||||
|
|
||||||
build:
|
build:
|
||||||
executor: default
|
executor: default
|
||||||
steps:
|
steps:
|
||||||
@@ -68,10 +72,13 @@ jobs:
|
|||||||
- .
|
- .
|
||||||
test:
|
test:
|
||||||
parameters:
|
parameters:
|
||||||
without_redis:
|
executor:
|
||||||
type: string
|
type: string
|
||||||
default: ""
|
default: "default"
|
||||||
executor: default
|
without_redis:
|
||||||
|
type: boolean
|
||||||
|
default: false
|
||||||
|
executor: <<parameters.executor>>
|
||||||
steps:
|
steps:
|
||||||
- attach_workspace:
|
- attach_workspace:
|
||||||
at: /tmp/workspace
|
at: /tmp/workspace
|
||||||
@@ -94,12 +101,11 @@ jobs:
|
|||||||
key: yarn-v1-arch-{{ arch }}-env-{{ .Environment.variableName }}-package-{{ checksum "package.json" }}-lock-{{ checksum "yarn.lock" }}
|
key: yarn-v1-arch-{{ arch }}-env-{{ .Environment.variableName }}-package-{{ checksum "package.json" }}-lock-{{ checksum "yarn.lock" }}
|
||||||
paths:
|
paths:
|
||||||
- node_modules
|
- node_modules
|
||||||
|
|
||||||
docker:
|
docker:
|
||||||
parameters:
|
parameters:
|
||||||
with_deploy:
|
with_deploy:
|
||||||
type: string
|
type: boolean
|
||||||
default: ""
|
default: false
|
||||||
executor: docker
|
executor: docker
|
||||||
steps:
|
steps:
|
||||||
- checkout
|
- checkout
|
||||||
@@ -126,7 +132,7 @@ jobs:
|
|||||||
|
|
||||||
workflows:
|
workflows:
|
||||||
version: 2
|
version: 2
|
||||||
build-and-test:
|
nodejs:
|
||||||
jobs:
|
jobs:
|
||||||
- ok:
|
- ok:
|
||||||
filters:
|
filters:
|
||||||
@@ -135,7 +141,14 @@ workflows:
|
|||||||
- l10n_develop
|
- l10n_develop
|
||||||
- imgbot
|
- imgbot
|
||||||
- patch-autogen
|
- patch-autogen
|
||||||
|
- hold:
|
||||||
|
type: approval
|
||||||
|
filters:
|
||||||
|
branches:
|
||||||
|
ignore: master
|
||||||
- build:
|
- build:
|
||||||
|
requires:
|
||||||
|
- hold
|
||||||
filters:
|
filters:
|
||||||
branches:
|
branches:
|
||||||
ignore:
|
ignore:
|
||||||
@@ -143,6 +156,7 @@ workflows:
|
|||||||
- imgbot
|
- imgbot
|
||||||
- patch-autogen
|
- patch-autogen
|
||||||
- test:
|
- test:
|
||||||
|
executor: with-redis
|
||||||
requires:
|
requires:
|
||||||
- build
|
- build
|
||||||
filters:
|
filters:
|
||||||
@@ -153,7 +167,7 @@ workflows:
|
|||||||
- imgbot
|
- imgbot
|
||||||
- patch-autogen
|
- patch-autogen
|
||||||
- test:
|
- test:
|
||||||
without_redis: "true"
|
without_redis: true
|
||||||
requires:
|
requires:
|
||||||
- build
|
- build
|
||||||
filters:
|
filters:
|
||||||
@@ -165,12 +179,21 @@ workflows:
|
|||||||
- l10n_develop
|
- l10n_develop
|
||||||
- imgbot
|
- imgbot
|
||||||
- patch-autogen
|
- patch-autogen
|
||||||
# - docker:
|
docker:
|
||||||
# filters:
|
jobs:
|
||||||
# branches:
|
- hold:
|
||||||
# ignore: master
|
type: approval
|
||||||
|
filters:
|
||||||
|
branches:
|
||||||
|
ignore: master
|
||||||
- docker:
|
- docker:
|
||||||
with_deploy: "true"
|
requires:
|
||||||
|
- hold
|
||||||
|
filters:
|
||||||
|
branches:
|
||||||
|
ignore: master
|
||||||
|
- docker:
|
||||||
|
with_deploy: true
|
||||||
filters:
|
filters:
|
||||||
branches:
|
branches:
|
||||||
only: master
|
only: master
|
||||||
|
|||||||
49
CHANGELOG.md
49
CHANGELOG.md
@@ -1,6 +1,55 @@
|
|||||||
ChangeLog
|
ChangeLog
|
||||||
=========
|
=========
|
||||||
|
|
||||||
|
10.86.1
|
||||||
|
----------
|
||||||
|
* ナビゲーションバーの「ホーム」を「タイムライン」に改称
|
||||||
|
* モバイル版でユーザーページが二重に描画される問題を修正
|
||||||
|
* ユーザー一覧の「もっと読み込む」の動作がおかしい問題を修正
|
||||||
|
* デザインの調整
|
||||||
|
|
||||||
|
10.86.0
|
||||||
|
----------
|
||||||
|
* Exploreページを実装
|
||||||
|
* UIを改良
|
||||||
|
* その他細かな修正
|
||||||
|
|
||||||
|
10.85.2
|
||||||
|
----------
|
||||||
|
* デッキから フォロー/フォロワー ページに行けるように
|
||||||
|
* ナビゲーションが発生したときに最上部までスクロールように
|
||||||
|
* 検索結果でページ遷移が発生する問題を修正
|
||||||
|
* デザインの調整
|
||||||
|
|
||||||
|
10.85.1
|
||||||
|
----------
|
||||||
|
* ローカルのみ投稿をログイン画面のタイムラインに表示しないように
|
||||||
|
* ナビゲーションバーを横にしてるとデッキに行けない問題を修正
|
||||||
|
|
||||||
|
10.85.0
|
||||||
|
----------
|
||||||
|
* デスクトップ版のUIを改良
|
||||||
|
* 投稿ハイライトページを実装
|
||||||
|
* 無効化されているタイムラインのフォールバック
|
||||||
|
* 既にフォローされている場合はフォローリクエストを生成しないように
|
||||||
|
* その他細かな修正
|
||||||
|
|
||||||
|
10.84.2
|
||||||
|
----------
|
||||||
|
* GIF画像にGIFバッジを表示
|
||||||
|
* よく話すユーザーからサスペンドされたユーザーを隠すなど
|
||||||
|
* nodeinfoが重い問題を修正
|
||||||
|
* ハッシュタグクラウド取得が重い問題を軽減
|
||||||
|
|
||||||
|
10.84.1
|
||||||
|
----------
|
||||||
|
* deckにフォローされていますマークを追加
|
||||||
|
* URLプレビューのサムネイルの調整
|
||||||
|
* 管理画面でサイレンスされているユーザーを一覧できるように
|
||||||
|
* ドキュメントにアクセスできない問題を修正
|
||||||
|
* ジョブキューを無効化
|
||||||
|
* 軽微なバグ修正
|
||||||
|
|
||||||
10.84.0
|
10.84.0
|
||||||
----------
|
----------
|
||||||
* インスタンス管理の強化
|
* インスタンス管理の強化
|
||||||
|
|||||||
12
Dockerfile
12
Dockerfile
@@ -8,7 +8,6 @@ WORKDIR /misskey
|
|||||||
|
|
||||||
FROM base AS builder
|
FROM base AS builder
|
||||||
|
|
||||||
RUN unlink /usr/bin/free
|
|
||||||
RUN apk add --no-cache \
|
RUN apk add --no-cache \
|
||||||
autoconf \
|
autoconf \
|
||||||
automake \
|
automake \
|
||||||
@@ -20,18 +19,13 @@ RUN apk add --no-cache \
|
|||||||
make \
|
make \
|
||||||
nasm \
|
nasm \
|
||||||
pkgconfig \
|
pkgconfig \
|
||||||
procps \
|
|
||||||
python \
|
python \
|
||||||
zlib-dev
|
zlib-dev
|
||||||
RUN npm i -g node-gyp
|
RUN npm i -g yarn
|
||||||
|
|
||||||
COPY ./package.json ./
|
|
||||||
RUN npm i
|
|
||||||
|
|
||||||
COPY . ./
|
COPY . ./
|
||||||
RUN node-gyp configure \
|
RUN yarn install
|
||||||
&& node-gyp build \
|
RUN yarn build
|
||||||
&& npm run build
|
|
||||||
|
|
||||||
FROM base AS runner
|
FROM base AS runner
|
||||||
|
|
||||||
|
|||||||
14
README.md
14
README.md
@@ -3,9 +3,9 @@
|
|||||||
[](https://misskey.xyz/)
|
[](https://misskey.xyz/)
|
||||||
================================================================
|
================================================================
|
||||||
|
|
||||||
[](https://circleci.com/gh/syuilo/misskey)
|
[](https://circleci.com/gh/syuilo/misskey)
|
||||||
[](https://david-dm.org/syuilo/misskey)
|
[](https://david-dm.org/syuilo/misskey)
|
||||||
[](http://makeapullrequest.com)
|
[](http://makeapullrequest.com)
|
||||||
|
|
||||||
**A forever evolving, sophisticated microblogging platform.**
|
**A forever evolving, sophisticated microblogging platform.**
|
||||||
|
|
||||||
@@ -94,7 +94,7 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
|
|||||||
<!-- PATREON_START -->
|
<!-- PATREON_START -->
|
||||||
<table><tr>
|
<table><tr>
|
||||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/12190916/fb7fa7983c14425f890369535b1506a4/1?token-time=2145916800&token-hash=WeuDzzz24cRXJogyIkU-mxARqkdyms-rcZKbO-GpGjw%3D" alt="weep" width="100"></td>
|
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/12190916/fb7fa7983c14425f890369535b1506a4/1?token-time=2145916800&token-hash=WeuDzzz24cRXJogyIkU-mxARqkdyms-rcZKbO-GpGjw%3D" alt="weep" width="100"></td>
|
||||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/12731202/0995c46cdcb54153ab5f073f5869b70a/1?token-time=2145916800&token-hash=prtYqPOiSHBulhM7NU0VzMaWx39-9ntdq25b6kafDNA%3D" alt="negao" width="100"></td>
|
<td><img src="https://c8.patreon.com/2/200/12059069" alt="naga_rus" width="100"></td>
|
||||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/12913507/f7181eacafe8469a93033d85f5969c29/3?token-time=2145916800&token-hash=c8HeVqLtmdgH-gSBJg8i10gmOcwllM87MDHeznl3el0%3D" alt="Melilot" width="100"></td>
|
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/12913507/f7181eacafe8469a93033d85f5969c29/3?token-time=2145916800&token-hash=c8HeVqLtmdgH-gSBJg8i10gmOcwllM87MDHeznl3el0%3D" alt="Melilot" width="100"></td>
|
||||||
<td><img src="https://c8.patreon.com/2/200/16869916" alt="見当かなみ" width="100"></td>
|
<td><img src="https://c8.patreon.com/2/200/16869916" alt="見当かなみ" width="100"></td>
|
||||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/12999811/5f349fafcce44dd1824a8b1ebbec4564/3?token-time=2145916800&token-hash=LtV2lRi3L2jOWMLwccr9qWYfPrFlzIo2jYZHKzHEb6k%3D" alt="Xeltica" width="100"></td>
|
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/12999811/5f349fafcce44dd1824a8b1ebbec4564/3?token-time=2145916800&token-hash=LtV2lRi3L2jOWMLwccr9qWYfPrFlzIo2jYZHKzHEb6k%3D" alt="Xeltica" width="100"></td>
|
||||||
@@ -102,7 +102,7 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
|
|||||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/12021162/963128bb8d14476dbd8407943db8f31a/1?token-time=2145916800&token-hash=1FlxS9MEgmNGH_RHUVHbO5hIXB5I1z0lvA33CTvYvjA%3D" alt="gutfuckllc" width="100"></td>
|
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/12021162/963128bb8d14476dbd8407943db8f31a/1?token-time=2145916800&token-hash=1FlxS9MEgmNGH_RHUVHbO5hIXB5I1z0lvA33CTvYvjA%3D" alt="gutfuckllc" width="100"></td>
|
||||||
</tr><tr>
|
</tr><tr>
|
||||||
<td><a href="https://www.patreon.com/weepjp">weep</a></td>
|
<td><a href="https://www.patreon.com/weepjp">weep</a></td>
|
||||||
<td><a href="https://www.patreon.com/negao">negao</a></td>
|
<td><a href="https://www.patreon.com/user?u=12059069">naga_rus</a></td>
|
||||||
<td><a href="https://www.patreon.com/user?u=12913507">Melilot</a></td>
|
<td><a href="https://www.patreon.com/user?u=12913507">Melilot</a></td>
|
||||||
<td><a href="https://www.patreon.com/user?u=16869916">見当かなみ</a></td>
|
<td><a href="https://www.patreon.com/user?u=16869916">見当かなみ</a></td>
|
||||||
<td><a href="https://www.patreon.com/Xeltica">Xeltica</a></td>
|
<td><a href="https://www.patreon.com/Xeltica">Xeltica</a></td>
|
||||||
@@ -115,6 +115,7 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
|
|||||||
<td><img src="https://c8.patreon.com/2/200/16542964" alt="Takumi Sugita" width="100"></td>
|
<td><img src="https://c8.patreon.com/2/200/16542964" alt="Takumi Sugita" width="100"></td>
|
||||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/13039004/509d0c412eb14ae08d6a812a3054f7d6/1?token-time=2145916800&token-hash=2PsbFNw0tnubZzgSXD01R6hIgncfiElG7H7HX2Y3dyo%3D" alt="nemu" width="100"></td>
|
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/13039004/509d0c412eb14ae08d6a812a3054f7d6/1?token-time=2145916800&token-hash=2PsbFNw0tnubZzgSXD01R6hIgncfiElG7H7HX2Y3dyo%3D" alt="nemu" width="100"></td>
|
||||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/5881381/6235ca5d3fb04c8e95ef5b4ff2abcc18/3?token-time=2145916800&token-hash=9JtETp0X8gI280Ne1E8bxn6j4Lw5o2k4mJkICx97V_k%3D" alt="YUKIMOCHI" width="100"></td>
|
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/5881381/6235ca5d3fb04c8e95ef5b4ff2abcc18/3?token-time=2145916800&token-hash=9JtETp0X8gI280Ne1E8bxn6j4Lw5o2k4mJkICx97V_k%3D" alt="YUKIMOCHI" width="100"></td>
|
||||||
|
<td><img src="https://c8.patreon.com/2/200/17463605" alt="Sampot" width="100"></td>
|
||||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/17195955/be45e5e14c3e48b2bee0456c84e19df4/4?token-time=2145916800&token-hash=SbdZeN5SmsuT9stD6v0jN1z0hftg0FmRiCTxysU0Ihw%3D" alt="Damillora" width="100"></td>
|
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/17195955/be45e5e14c3e48b2bee0456c84e19df4/4?token-time=2145916800&token-hash=SbdZeN5SmsuT9stD6v0jN1z0hftg0FmRiCTxysU0Ihw%3D" alt="Damillora" width="100"></td>
|
||||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/8241184/39e18850e87a449e9c9a71acb3310ebd/3?token-time=2145916800&token-hash=gMq30aylxu5v3G8pRhWR5jeRBbYWEoRKjGbNeiCQz5g%3D" alt="Acid Chicken" width="100"></td>
|
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/8241184/39e18850e87a449e9c9a71acb3310ebd/3?token-time=2145916800&token-hash=gMq30aylxu5v3G8pRhWR5jeRBbYWEoRKjGbNeiCQz5g%3D" alt="Acid Chicken" width="100"></td>
|
||||||
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/4389829/9f709180ac714651a70f74a82f3ffdb9/2?token-time=2145916800&token-hash=zcwFxb2zopzWwksKVU1YpfAEjsl4yKT02aQ6yiAFRiQ%3D" alt="natalie" width="100"></td>
|
<td><img src="https://c10.patreonusercontent.com/3/eyJ3IjoyMDB9/patreon-media/p/user/4389829/9f709180ac714651a70f74a82f3ffdb9/2?token-time=2145916800&token-hash=zcwFxb2zopzWwksKVU1YpfAEjsl4yKT02aQ6yiAFRiQ%3D" alt="natalie" width="100"></td>
|
||||||
@@ -125,6 +126,7 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
|
|||||||
<td><a href="https://www.patreon.com/user?u=16542964">Takumi Sugita</a></td>
|
<td><a href="https://www.patreon.com/user?u=16542964">Takumi Sugita</a></td>
|
||||||
<td><a href="https://www.patreon.com/user?u=13039004">nemu</a></td>
|
<td><a href="https://www.patreon.com/user?u=13039004">nemu</a></td>
|
||||||
<td><a href="https://www.patreon.com/yukimochi">YUKIMOCHI</a></td>
|
<td><a href="https://www.patreon.com/yukimochi">YUKIMOCHI</a></td>
|
||||||
|
<td><a href="https://www.patreon.com/user?u=17463605">Sampot</a></td>
|
||||||
<td><a href="https://www.patreon.com/damillora">Damillora</a></td>
|
<td><a href="https://www.patreon.com/damillora">Damillora</a></td>
|
||||||
<td><a href="https://www.patreon.com/acid_chicken">Acid Chicken</a></td>
|
<td><a href="https://www.patreon.com/acid_chicken">Acid Chicken</a></td>
|
||||||
<td><a href="https://www.patreon.com/user?u=4389829">natalie</a></td>
|
<td><a href="https://www.patreon.com/user?u=4389829">natalie</a></td>
|
||||||
@@ -142,7 +144,7 @@ Please see the [Contribution Guide](./CONTRIBUTING.md).
|
|||||||
<td><a href="https://www.patreon.com/user?u=12531784">Takashi Shibuya</a></td>
|
<td><a href="https://www.patreon.com/user?u=12531784">Takashi Shibuya</a></td>
|
||||||
</tr></table>
|
</tr></table>
|
||||||
|
|
||||||
**Last updated:** Wed, 06 Feb 2019 18:18:05 UTC
|
**Last updated:** Fri, 15 Feb 2019 19:12:06 UTC
|
||||||
<!-- PATREON_END -->
|
<!-- PATREON_END -->
|
||||||
|
|
||||||
:four_leaf_clover: Copyright
|
:four_leaf_clover: Copyright
|
||||||
|
|||||||
@@ -122,6 +122,8 @@ CentOSで1024以下のポートを使用してMisskeyを使用する場合は`Ex
|
|||||||
4. `npm run build`
|
4. `npm run build`
|
||||||
5. [ChangeLog](../CHANGELOG.md)でマイグレーション情報を確認する
|
5. [ChangeLog](../CHANGELOG.md)でマイグレーション情報を確認する
|
||||||
|
|
||||||
|
なにか問題が発生した場合は、`npm run clean`すると直る場合があります。
|
||||||
|
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
|
|
||||||
なにかお困りのことがありましたらお気軽にご連絡ください。
|
なにかお困りのことがありましたらお気軽にご連絡ください。
|
||||||
|
|||||||
@@ -1186,6 +1186,7 @@ admin/views/users.vue:
|
|||||||
moderator: "モデレーター"
|
moderator: "モデレーター"
|
||||||
adminOrModerator: "管理者+モデレーター"
|
adminOrModerator: "管理者+モデレーター"
|
||||||
verified: "公式アカウント"
|
verified: "公式アカウント"
|
||||||
|
silenced: "サイレンス済み"
|
||||||
suspended: "凍結済み"
|
suspended: "凍結済み"
|
||||||
origin:
|
origin:
|
||||||
title: "オリジン"
|
title: "オリジン"
|
||||||
@@ -1590,13 +1591,13 @@ mobile/views/pages/user/home.vue:
|
|||||||
activity: "アクティビティ"
|
activity: "アクティビティ"
|
||||||
keywords: "キーワード"
|
keywords: "キーワード"
|
||||||
domains: "頻出ドメイン"
|
domains: "頻出ドメイン"
|
||||||
frequently-replied-users: "よく会話するユーザー"
|
frequently-replied-users: "よく話すユーザー"
|
||||||
followers-you-know: "知り合いのフォロワー"
|
followers-you-know: "知り合いのフォロワー"
|
||||||
last-used-at: "最終ログイン"
|
last-used-at: "最終ログイン"
|
||||||
mobile/views/pages/user/home.followers-you-know.vue:
|
mobile/views/pages/user/home.followers-you-know.vue:
|
||||||
no-users: "知り合いのユーザーはいません"
|
no-users: "知り合いのユーザーはいません"
|
||||||
mobile/views/pages/user/home.friends.vue:
|
mobile/views/pages/user/home.friends.vue:
|
||||||
no-users: "よく会話するユーザーはいません"
|
no-users: "よく話すユーザーはいません"
|
||||||
mobile/views/pages/user/home.notes.vue:
|
mobile/views/pages/user/home.notes.vue:
|
||||||
no-notes: "投稿はありません"
|
no-notes: "投稿はありません"
|
||||||
mobile/views/pages/user/home.photos.vue:
|
mobile/views/pages/user/home.photos.vue:
|
||||||
@@ -1626,6 +1627,7 @@ deck/deck.tl-column.vue:
|
|||||||
is-media-view: "メディアビュー"
|
is-media-view: "メディアビュー"
|
||||||
edit: "オプション"
|
edit: "オプション"
|
||||||
deck/deck.user-column.vue:
|
deck/deck.user-column.vue:
|
||||||
|
follows-you: "フォローされています"
|
||||||
posts: "投稿"
|
posts: "投稿"
|
||||||
following: "フォロー"
|
following: "フォロー"
|
||||||
followers: "フォロワー"
|
followers: "フォロワー"
|
||||||
|
|||||||
@@ -1186,6 +1186,7 @@ admin/views/users.vue:
|
|||||||
moderator: "モデレーター"
|
moderator: "モデレーター"
|
||||||
adminOrModerator: "管理者+モデレーター"
|
adminOrModerator: "管理者+モデレーター"
|
||||||
verified: "公式アカウント"
|
verified: "公式アカウント"
|
||||||
|
silenced: "サイレンス済み"
|
||||||
suspended: "凍結済み"
|
suspended: "凍結済み"
|
||||||
origin:
|
origin:
|
||||||
title: "オリジン"
|
title: "オリジン"
|
||||||
@@ -1590,13 +1591,13 @@ mobile/views/pages/user/home.vue:
|
|||||||
activity: "アクティビティ"
|
activity: "アクティビティ"
|
||||||
keywords: "Schlagwörter"
|
keywords: "Schlagwörter"
|
||||||
domains: "頻出ドメイン"
|
domains: "頻出ドメイン"
|
||||||
frequently-replied-users: "よく会話するユーザー"
|
frequently-replied-users: "よく話すユーザー"
|
||||||
followers-you-know: "知り合いのフォロワー"
|
followers-you-know: "知り合いのフォロワー"
|
||||||
last-used-at: "最終ログイン"
|
last-used-at: "最終ログイン"
|
||||||
mobile/views/pages/user/home.followers-you-know.vue:
|
mobile/views/pages/user/home.followers-you-know.vue:
|
||||||
no-users: "知り合いのユーザーはいません"
|
no-users: "知り合いのユーザーはいません"
|
||||||
mobile/views/pages/user/home.friends.vue:
|
mobile/views/pages/user/home.friends.vue:
|
||||||
no-users: "よく会話するユーザーはいません"
|
no-users: "よく話すユーザーはいません"
|
||||||
mobile/views/pages/user/home.notes.vue:
|
mobile/views/pages/user/home.notes.vue:
|
||||||
no-notes: "投稿はありません"
|
no-notes: "投稿はありません"
|
||||||
mobile/views/pages/user/home.photos.vue:
|
mobile/views/pages/user/home.photos.vue:
|
||||||
@@ -1626,6 +1627,7 @@ deck/deck.tl-column.vue:
|
|||||||
is-media-view: "メディアビュー"
|
is-media-view: "メディアビュー"
|
||||||
edit: "オプション"
|
edit: "オプション"
|
||||||
deck/deck.user-column.vue:
|
deck/deck.user-column.vue:
|
||||||
|
follows-you: "フォローされています"
|
||||||
posts: "投稿"
|
posts: "投稿"
|
||||||
following: "フォロー"
|
following: "フォロー"
|
||||||
followers: "フォロワー"
|
followers: "フォロワー"
|
||||||
|
|||||||
@@ -1118,7 +1118,7 @@ admin/views/charts.vue:
|
|||||||
users: "The number of users: increase/decrease"
|
users: "The number of users: increase/decrease"
|
||||||
users-total: "Total users"
|
users-total: "Total users"
|
||||||
active-users: "Active users"
|
active-users: "Active users"
|
||||||
drive: "Capacity used as the storage: increase/decrease"
|
drive: "Increase and decrease in storage capacity use"
|
||||||
drive-total: "Total usage of Drive"
|
drive-total: "Total usage of Drive"
|
||||||
drive-files: "The number of files on the storage: increase/decrease"
|
drive-files: "The number of files on the storage: increase/decrease"
|
||||||
drive-files-total: "Total number of files on Drive"
|
drive-files-total: "Total number of files on Drive"
|
||||||
@@ -1186,6 +1186,7 @@ admin/views/users.vue:
|
|||||||
moderator: "Moderator"
|
moderator: "Moderator"
|
||||||
adminOrModerator: "Admin/Moderator"
|
adminOrModerator: "Admin/Moderator"
|
||||||
verified: "Verified account"
|
verified: "Verified account"
|
||||||
|
silenced: "Already silenced"
|
||||||
suspended: "Suspended"
|
suspended: "Suspended"
|
||||||
origin:
|
origin:
|
||||||
title: "Origin"
|
title: "Origin"
|
||||||
@@ -1244,7 +1245,7 @@ admin/views/federation.vue:
|
|||||||
latest-request-sent-at: "Time of last request sent"
|
latest-request-sent-at: "Time of last request sent"
|
||||||
latest-request-received-at: "Last request received at"
|
latest-request-received-at: "Last request received at"
|
||||||
remove-all-following: "Withold all followers"
|
remove-all-following: "Withold all followers"
|
||||||
remove-all-following-info: "{host}からのフォローをすべて解除します。そのインスタンスがもう存在しなくなった場合などに実行してください。"
|
remove-all-following-info: "Unfollow all accounts from {host}. Please run this if the instance no longer exists."
|
||||||
block: "Block"
|
block: "Block"
|
||||||
marked-as-closed: "Marked as closed"
|
marked-as-closed: "Marked as closed"
|
||||||
lookup: "Look up"
|
lookup: "Look up"
|
||||||
@@ -1254,8 +1255,8 @@ admin/views/federation.vue:
|
|||||||
sorts:
|
sorts:
|
||||||
caughtAtAsc: "Date of discovery (Ascending)"
|
caughtAtAsc: "Date of discovery (Ascending)"
|
||||||
caughtAtDesc: "Date of discovery (Descending)"
|
caughtAtDesc: "Date of discovery (Descending)"
|
||||||
lastCommunicatedAtAsc: "最後にやり取りした日時が古い順"
|
lastCommunicatedAtAsc: "The date and time of the older interactions"
|
||||||
lastCommunicatedAtDesc: "最後にやり取りした日時が新しい順"
|
lastCommunicatedAtDesc: "The date and time of the newer interactions"
|
||||||
notesAsc: "Order by least Notes posted"
|
notesAsc: "Order by least Notes posted"
|
||||||
notesDesc: "Order by most Notes posted"
|
notesDesc: "Order by most Notes posted"
|
||||||
usersAsc: "Less followers"
|
usersAsc: "Less followers"
|
||||||
@@ -1264,10 +1265,10 @@ admin/views/federation.vue:
|
|||||||
followingDesc: "Has more followers"
|
followingDesc: "Has more followers"
|
||||||
followersAsc: "Sort by having less followers"
|
followersAsc: "Sort by having less followers"
|
||||||
followersDesc: "Sort by the larger number of followers"
|
followersDesc: "Sort by the larger number of followers"
|
||||||
driveUsageAsc: "ドライブ使用量が少ない順"
|
driveUsageAsc: "Least storage used"
|
||||||
driveUsageDesc: "ドライブ使用量が多い順"
|
driveUsageDesc: "Most storage used"
|
||||||
driveFilesAsc: "ドライブのファイル数が少ない順"
|
driveFilesAsc: "By the smallest number of files stored on Drive"
|
||||||
driveFilesDesc: "ドライブのファイル数が多い順"
|
driveFilesDesc: "By the largest number of files stored on Drive"
|
||||||
state: "Status"
|
state: "Status"
|
||||||
states:
|
states:
|
||||||
all: "All"
|
all: "All"
|
||||||
@@ -1282,12 +1283,12 @@ admin/views/federation.vue:
|
|||||||
users-total: "Total number of users"
|
users-total: "Total number of users"
|
||||||
notes: "Increase, or decrease in the number of notes"
|
notes: "Increase, or decrease in the number of notes"
|
||||||
notes-total: "Total number of notes"
|
notes-total: "Total number of notes"
|
||||||
ff: "フォロー/フォロワーの増減"
|
ff: "Increase of followers"
|
||||||
ff-total: "フォロー/フォロワーの積算"
|
ff-total: "Total number of follows accumulated"
|
||||||
drive-usage: "ドライブ使用量の増減"
|
drive-usage: "Increase and decrease in storage use"
|
||||||
drive-usage-total: "ドライブ使用量の積算"
|
drive-usage-total: "Total usage of the Drive"
|
||||||
drive-files: "ドライブファイル数の増減"
|
drive-files: "Increase, or decrease in the number of files stored on Drive"
|
||||||
drive-files-total: "ドライブファイル数の積算"
|
drive-files-total: "The number of files accumulated on Drive"
|
||||||
chart-spans:
|
chart-spans:
|
||||||
hour: "Hourly"
|
hour: "Hourly"
|
||||||
day: "Daily"
|
day: "Daily"
|
||||||
@@ -1626,6 +1627,7 @@ deck/deck.tl-column.vue:
|
|||||||
is-media-view: "Media view"
|
is-media-view: "Media view"
|
||||||
edit: "Options"
|
edit: "Options"
|
||||||
deck/deck.user-column.vue:
|
deck/deck.user-column.vue:
|
||||||
|
follows-you: "Follows you"
|
||||||
posts: "Posts"
|
posts: "Posts"
|
||||||
following: "Following"
|
following: "Following"
|
||||||
followers: "Followers"
|
followers: "Followers"
|
||||||
|
|||||||
@@ -1186,6 +1186,7 @@ admin/views/users.vue:
|
|||||||
moderator: "モデレーター"
|
moderator: "モデレーター"
|
||||||
adminOrModerator: "管理者+モデレーター"
|
adminOrModerator: "管理者+モデレーター"
|
||||||
verified: "公式アカウント"
|
verified: "公式アカウント"
|
||||||
|
silenced: "サイレンス済み"
|
||||||
suspended: "凍結済み"
|
suspended: "凍結済み"
|
||||||
origin:
|
origin:
|
||||||
title: "オリジン"
|
title: "オリジン"
|
||||||
@@ -1590,13 +1591,13 @@ mobile/views/pages/user/home.vue:
|
|||||||
activity: "アクティビティ"
|
activity: "アクティビティ"
|
||||||
keywords: "キーワード"
|
keywords: "キーワード"
|
||||||
domains: "頻出ドメイン"
|
domains: "頻出ドメイン"
|
||||||
frequently-replied-users: "よく会話するユーザー"
|
frequently-replied-users: "よく話すユーザー"
|
||||||
followers-you-know: "知り合いのフォロワー"
|
followers-you-know: "知り合いのフォロワー"
|
||||||
last-used-at: "最終ログイン"
|
last-used-at: "最終ログイン"
|
||||||
mobile/views/pages/user/home.followers-you-know.vue:
|
mobile/views/pages/user/home.followers-you-know.vue:
|
||||||
no-users: "知り合いのユーザーはいません"
|
no-users: "知り合いのユーザーはいません"
|
||||||
mobile/views/pages/user/home.friends.vue:
|
mobile/views/pages/user/home.friends.vue:
|
||||||
no-users: "よく会話するユーザーはいません"
|
no-users: "よく話すユーザーはいません"
|
||||||
mobile/views/pages/user/home.notes.vue:
|
mobile/views/pages/user/home.notes.vue:
|
||||||
no-notes: "投稿はありません"
|
no-notes: "投稿はありません"
|
||||||
mobile/views/pages/user/home.photos.vue:
|
mobile/views/pages/user/home.photos.vue:
|
||||||
@@ -1626,6 +1627,7 @@ deck/deck.tl-column.vue:
|
|||||||
is-media-view: "メディアビュー"
|
is-media-view: "メディアビュー"
|
||||||
edit: "オプション"
|
edit: "オプション"
|
||||||
deck/deck.user-column.vue:
|
deck/deck.user-column.vue:
|
||||||
|
follows-you: "フォローされています"
|
||||||
posts: "投稿"
|
posts: "投稿"
|
||||||
following: "フォロー"
|
following: "フォロー"
|
||||||
followers: "フォロワー"
|
followers: "フォロワー"
|
||||||
|
|||||||
@@ -1186,6 +1186,7 @@ admin/views/users.vue:
|
|||||||
moderator: "Modérateur"
|
moderator: "Modérateur"
|
||||||
adminOrModerator: "Administrateur/Modérateur"
|
adminOrModerator: "Administrateur/Modérateur"
|
||||||
verified: "Compte vérifié"
|
verified: "Compte vérifié"
|
||||||
|
silenced: "サイレンス済み"
|
||||||
suspended: "Suspendu"
|
suspended: "Suspendu"
|
||||||
origin:
|
origin:
|
||||||
title: "Origine"
|
title: "Origine"
|
||||||
@@ -1626,6 +1627,7 @@ deck/deck.tl-column.vue:
|
|||||||
is-media-view: "Vue média"
|
is-media-view: "Vue média"
|
||||||
edit: "Option"
|
edit: "Option"
|
||||||
deck/deck.user-column.vue:
|
deck/deck.user-column.vue:
|
||||||
|
follows-you: "フォローされています"
|
||||||
posts: "Notes"
|
posts: "Notes"
|
||||||
following: "Suit"
|
following: "Suit"
|
||||||
followers: "Abonnés"
|
followers: "Abonnés"
|
||||||
|
|||||||
6
locales/index.d.ts
vendored
6
locales/index.d.ts
vendored
@@ -1,5 +1,3 @@
|
|||||||
type Locale = { [key: string]: string };
|
declare const locales: { [lang: string]: any };
|
||||||
|
|
||||||
declare const locales: { [lang: string]: Locale };
|
export = locales;
|
||||||
|
|
||||||
export default locales;
|
|
||||||
|
|||||||
@@ -1186,6 +1186,7 @@ admin/views/users.vue:
|
|||||||
moderator: "モデレーター"
|
moderator: "モデレーター"
|
||||||
adminOrModerator: "管理者+モデレーター"
|
adminOrModerator: "管理者+モデレーター"
|
||||||
verified: "公式アカウント"
|
verified: "公式アカウント"
|
||||||
|
silenced: "サイレンス済み"
|
||||||
suspended: "凍結済み"
|
suspended: "凍結済み"
|
||||||
origin:
|
origin:
|
||||||
title: "オリジン"
|
title: "オリジン"
|
||||||
@@ -1590,13 +1591,13 @@ mobile/views/pages/user/home.vue:
|
|||||||
activity: "アクティビティ"
|
activity: "アクティビティ"
|
||||||
keywords: "キーワード"
|
keywords: "キーワード"
|
||||||
domains: "頻出ドメイン"
|
domains: "頻出ドメイン"
|
||||||
frequently-replied-users: "よく会話するユーザー"
|
frequently-replied-users: "よく話すユーザー"
|
||||||
followers-you-know: "知り合いのフォロワー"
|
followers-you-know: "知り合いのフォロワー"
|
||||||
last-used-at: "最終ログイン"
|
last-used-at: "最終ログイン"
|
||||||
mobile/views/pages/user/home.followers-you-know.vue:
|
mobile/views/pages/user/home.followers-you-know.vue:
|
||||||
no-users: "知り合いのユーザーはいません"
|
no-users: "知り合いのユーザーはいません"
|
||||||
mobile/views/pages/user/home.friends.vue:
|
mobile/views/pages/user/home.friends.vue:
|
||||||
no-users: "よく会話するユーザーはいません"
|
no-users: "よく話すユーザーはいません"
|
||||||
mobile/views/pages/user/home.notes.vue:
|
mobile/views/pages/user/home.notes.vue:
|
||||||
no-notes: "投稿はありません"
|
no-notes: "投稿はありません"
|
||||||
mobile/views/pages/user/home.photos.vue:
|
mobile/views/pages/user/home.photos.vue:
|
||||||
@@ -1626,6 +1627,7 @@ deck/deck.tl-column.vue:
|
|||||||
is-media-view: "メディアビュー"
|
is-media-view: "メディアビュー"
|
||||||
edit: "オプション"
|
edit: "オプション"
|
||||||
deck/deck.user-column.vue:
|
deck/deck.user-column.vue:
|
||||||
|
follows-you: "フォローされています"
|
||||||
posts: "投稿"
|
posts: "投稿"
|
||||||
following: "フォロー"
|
following: "フォロー"
|
||||||
followers: "フォロワー"
|
followers: "フォロワー"
|
||||||
|
|||||||
@@ -28,6 +28,8 @@ common:
|
|||||||
load-more: "もっと読み込む"
|
load-more: "もっと読み込む"
|
||||||
enter-password: "パスワードを入力してください"
|
enter-password: "パスワードを入力してください"
|
||||||
2fa: "二段階認証"
|
2fa: "二段階認証"
|
||||||
|
customize-home: "ホームをカスタマイズ"
|
||||||
|
featured-notes: "ハイライト"
|
||||||
|
|
||||||
got-it: "わかった"
|
got-it: "わかった"
|
||||||
customization-tips:
|
customization-tips:
|
||||||
@@ -58,6 +60,11 @@ common:
|
|||||||
trash: "ゴミ箱"
|
trash: "ゴミ箱"
|
||||||
drive: "ドライブ"
|
drive: "ドライブ"
|
||||||
messaging: "トーク"
|
messaging: "トーク"
|
||||||
|
deck: "デッキ"
|
||||||
|
timeline: "タイムライン"
|
||||||
|
explore: "みつける"
|
||||||
|
following: "フォロー中"
|
||||||
|
followers: "フォロワー"
|
||||||
|
|
||||||
weekday-short:
|
weekday-short:
|
||||||
sunday: "日"
|
sunday: "日"
|
||||||
@@ -862,6 +869,9 @@ desktop/views/components/renote-form.vue:
|
|||||||
desktop/views/components/renote-form-window.vue:
|
desktop/views/components/renote-form-window.vue:
|
||||||
title: "この投稿をRenoteしますか?"
|
title: "この投稿をRenoteしますか?"
|
||||||
|
|
||||||
|
desktop/views/components/timeline.core.vue:
|
||||||
|
empty: "投稿がありません"
|
||||||
|
|
||||||
desktop/views/pages/user-following-or-followers.vue:
|
desktop/views/pages/user-following-or-followers.vue:
|
||||||
following: "{user}のフォロー"
|
following: "{user}のフォロー"
|
||||||
followers: "{user}のフォロワー"
|
followers: "{user}のフォロワー"
|
||||||
@@ -893,14 +903,10 @@ desktop/views/components/settings.vue:
|
|||||||
web-search-engine-desc: "例: https://www.google.com/?#q={{query}}"
|
web-search-engine-desc: "例: https://www.google.com/?#q={{query}}"
|
||||||
auto-popout: "ウィンドウの自動ポップアウト"
|
auto-popout: "ウィンドウの自動ポップアウト"
|
||||||
auto-popout-desc: "ウィンドウが開かれるとき、ポップアウト(ブラウザ外に切り離す)可能なら自動でポップアウトします。この設定はブラウザに記憶されます。"
|
auto-popout-desc: "ウィンドウが開かれるとき、ポップアウト(ブラウザ外に切り離す)可能なら自動でポップアウトします。この設定はブラウザに記憶されます。"
|
||||||
deck-nav: "デッキ内ナビゲーション"
|
|
||||||
deck-nav-desc: "デッキを使用しているとき、ナビゲーションが発生する際にページ遷移を行わずに一時的なカラムで受けるようにします。"
|
|
||||||
keep-cw: "CW保持"
|
keep-cw: "CW保持"
|
||||||
keep-cw-desc: "投稿にリプライする際、リプライ元の投稿にCWが設定されていたとき、デフォルトで同じCWを設定するようにします。"
|
keep-cw-desc: "投稿にリプライする際、リプライ元の投稿にCWが設定されていたとき、デフォルトで同じCWを設定するようにします。"
|
||||||
deck-default: "デッキをデフォルトのUIにする"
|
|
||||||
|
|
||||||
display: "デザインと表示"
|
display: "デザインと表示"
|
||||||
customize: "ホームをカスタマイズ"
|
|
||||||
wallpaper: "壁紙"
|
wallpaper: "壁紙"
|
||||||
choose-wallpaper: "壁紙を選択"
|
choose-wallpaper: "壁紙を選択"
|
||||||
delete-wallpaper: "壁紙を削除"
|
delete-wallpaper: "壁紙を削除"
|
||||||
@@ -1076,15 +1082,12 @@ desktop/views/components/ui.header.account.vue:
|
|||||||
favorites: "お気に入り"
|
favorites: "お気に入り"
|
||||||
lists: "リスト"
|
lists: "リスト"
|
||||||
follow-requests: "フォロー申請"
|
follow-requests: "フォロー申請"
|
||||||
customize: "ホームのカスタマイズ"
|
|
||||||
admin: "管理"
|
admin: "管理"
|
||||||
settings: "設定"
|
settings: "設定"
|
||||||
signout: "サインアウト"
|
signout: "サインアウト"
|
||||||
dark: "闇に飲まれる"
|
dark: "闇に飲まれる"
|
||||||
|
|
||||||
desktop/views/components/ui.header.nav.vue:
|
desktop/views/components/ui.header.nav.vue:
|
||||||
home: "ホーム"
|
|
||||||
deck: "デッキ"
|
|
||||||
game: "ゲーム"
|
game: "ゲーム"
|
||||||
|
|
||||||
desktop/views/components/ui.header.notifications.vue:
|
desktop/views/components/ui.header.notifications.vue:
|
||||||
@@ -1319,6 +1322,7 @@ admin/views/users.vue:
|
|||||||
moderator: "モデレーター"
|
moderator: "モデレーター"
|
||||||
adminOrModerator: "管理者+モデレーター"
|
adminOrModerator: "管理者+モデレーター"
|
||||||
verified: "公式アカウント"
|
verified: "公式アカウント"
|
||||||
|
silenced: "サイレンス済み"
|
||||||
suspended: "凍結済み"
|
suspended: "凍結済み"
|
||||||
origin:
|
origin:
|
||||||
title: "オリジン"
|
title: "オリジン"
|
||||||
@@ -1446,9 +1450,6 @@ desktop/views/pages/welcome.vue:
|
|||||||
desktop/views/pages/drive.vue:
|
desktop/views/pages/drive.vue:
|
||||||
title: "Misskey Drive"
|
title: "Misskey Drive"
|
||||||
|
|
||||||
desktop/views/pages/home-customize.vue:
|
|
||||||
title: "ホームのカスタマイズ"
|
|
||||||
|
|
||||||
desktop/views/pages/note.vue:
|
desktop/views/pages/note.vue:
|
||||||
prev: "前の投稿"
|
prev: "前の投稿"
|
||||||
next: "次の投稿"
|
next: "次の投稿"
|
||||||
@@ -1489,10 +1490,6 @@ desktop/views/pages/user/user.photos.vue:
|
|||||||
loading: "読み込み中"
|
loading: "読み込み中"
|
||||||
no-photos: "写真はありません"
|
no-photos: "写真はありません"
|
||||||
|
|
||||||
desktop/views/pages/user/user.profile.vue:
|
|
||||||
follows-you: "フォローされています"
|
|
||||||
menu: "メニュー"
|
|
||||||
|
|
||||||
desktop/views/pages/user/user.header.vue:
|
desktop/views/pages/user/user.header.vue:
|
||||||
posts: "投稿"
|
posts: "投稿"
|
||||||
following: "フォロー"
|
following: "フォロー"
|
||||||
@@ -1502,6 +1499,7 @@ desktop/views/pages/user/user.header.vue:
|
|||||||
year: "年"
|
year: "年"
|
||||||
month: "月"
|
month: "月"
|
||||||
day: "日"
|
day: "日"
|
||||||
|
follows-you: "フォローされています"
|
||||||
|
|
||||||
desktop/views/pages/user/user.timeline.vue:
|
desktop/views/pages/user/user.timeline.vue:
|
||||||
default: "投稿"
|
default: "投稿"
|
||||||
@@ -1660,10 +1658,6 @@ mobile/views/components/user-timeline.vue:
|
|||||||
no-notes: "このユーザーは投稿していないようです。"
|
no-notes: "このユーザーは投稿していないようです。"
|
||||||
no-notes-with-media: "メディア付き投稿はありません。"
|
no-notes-with-media: "メディア付き投稿はありません。"
|
||||||
|
|
||||||
mobile/views/components/users-list.vue:
|
|
||||||
all: "すべて"
|
|
||||||
known: "知り合い"
|
|
||||||
|
|
||||||
mobile/views/pages/favorites.vue:
|
mobile/views/pages/favorites.vue:
|
||||||
title: "お気に入り"
|
title: "お気に入り"
|
||||||
|
|
||||||
@@ -1688,6 +1682,9 @@ mobile/views/pages/home.vue:
|
|||||||
mentions: "あなた宛て"
|
mentions: "あなた宛て"
|
||||||
messages: "メッセージ"
|
messages: "メッセージ"
|
||||||
|
|
||||||
|
mobile/views/pages/home.timeline.vue:
|
||||||
|
empty: "投稿がありません"
|
||||||
|
|
||||||
mobile/views/pages/tag.vue:
|
mobile/views/pages/tag.vue:
|
||||||
no-posts-found: "ハッシュタグ「{q}」が付けられた投稿は見つかりませんでした。"
|
no-posts-found: "ハッシュタグ「{q}」が付けられた投稿は見つかりませんでした。"
|
||||||
|
|
||||||
@@ -1790,7 +1787,7 @@ mobile/views/pages/user/home.vue:
|
|||||||
activity: "アクティビティ"
|
activity: "アクティビティ"
|
||||||
keywords: "キーワード"
|
keywords: "キーワード"
|
||||||
domains: "頻出ドメイン"
|
domains: "頻出ドメイン"
|
||||||
frequently-replied-users: "よく会話するユーザー"
|
frequently-replied-users: "よく話すユーザー"
|
||||||
followers-you-know: "知り合いのフォロワー"
|
followers-you-know: "知り合いのフォロワー"
|
||||||
last-used-at: "最終ログイン"
|
last-used-at: "最終ログイン"
|
||||||
|
|
||||||
@@ -1798,7 +1795,7 @@ mobile/views/pages/user/home.followers-you-know.vue:
|
|||||||
no-users: "知り合いのユーザーはいません"
|
no-users: "知り合いのユーザーはいません"
|
||||||
|
|
||||||
mobile/views/pages/user/home.friends.vue:
|
mobile/views/pages/user/home.friends.vue:
|
||||||
no-users: "よく会話するユーザーはいません"
|
no-users: "よく話すユーザーはいません"
|
||||||
|
|
||||||
mobile/views/pages/user/home.notes.vue:
|
mobile/views/pages/user/home.notes.vue:
|
||||||
no-notes: "投稿はありません"
|
no-notes: "投稿はありません"
|
||||||
@@ -1833,6 +1830,7 @@ deck/deck.tl-column.vue:
|
|||||||
edit: "オプション"
|
edit: "オプション"
|
||||||
|
|
||||||
deck/deck.user-column.vue:
|
deck/deck.user-column.vue:
|
||||||
|
follows-you: "フォローされています"
|
||||||
posts: "投稿"
|
posts: "投稿"
|
||||||
following: "フォロー"
|
following: "フォロー"
|
||||||
followers: "フォロワー"
|
followers: "フォロワー"
|
||||||
|
|||||||
@@ -1186,6 +1186,7 @@ admin/views/users.vue:
|
|||||||
moderator: "モデレーター"
|
moderator: "モデレーター"
|
||||||
adminOrModerator: "管理者+モデレーター"
|
adminOrModerator: "管理者+モデレーター"
|
||||||
verified: "公式アカウント"
|
verified: "公式アカウント"
|
||||||
|
silenced: "サイレンス済み"
|
||||||
suspended: "凍結済み"
|
suspended: "凍結済み"
|
||||||
origin:
|
origin:
|
||||||
title: "オリジン"
|
title: "オリジン"
|
||||||
@@ -1626,6 +1627,7 @@ deck/deck.tl-column.vue:
|
|||||||
is-media-view: "メディアビュー"
|
is-media-view: "メディアビュー"
|
||||||
edit: "オプション"
|
edit: "オプション"
|
||||||
deck/deck.user-column.vue:
|
deck/deck.user-column.vue:
|
||||||
|
follows-you: "フォローされています"
|
||||||
posts: "投稿"
|
posts: "投稿"
|
||||||
following: "フォロー"
|
following: "フォロー"
|
||||||
followers: "フォロワー"
|
followers: "フォロワー"
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ common:
|
|||||||
use-avatar-reversi-stones: "리버시의 돌로 아바타를 사용"
|
use-avatar-reversi-stones: "리버시의 돌로 아바타를 사용"
|
||||||
verified-user: "공식 계정"
|
verified-user: "공식 계정"
|
||||||
disable-animated-mfm: "글의 문자 애니메이션을 비활성화"
|
disable-animated-mfm: "글의 문자 애니메이션을 비활성화"
|
||||||
disable-showing-animated-images: "アニメーション画像を再生しない"
|
disable-showing-animated-images: "움직이는 이미지를 자동으로 재생하지 않음"
|
||||||
suggest-recent-hashtags: "최근 해시태그를 글 작성란에 표시"
|
suggest-recent-hashtags: "최근 해시태그를 글 작성란에 표시"
|
||||||
always-show-nsfw: "항상 열람주의 미디어를 표시"
|
always-show-nsfw: "항상 열람주의 미디어를 표시"
|
||||||
always-mark-nsfw: "항상 미디어를 열람주의로 설정하여 게시"
|
always-mark-nsfw: "항상 미디어를 열람주의로 설정하여 게시"
|
||||||
@@ -345,8 +345,8 @@ common/views/components/note-menu.vue:
|
|||||||
copy-link: "링크 복사"
|
copy-link: "링크 복사"
|
||||||
favorite: "이 노트 즐겨찾기"
|
favorite: "이 노트 즐겨찾기"
|
||||||
unfavorite: "즐겨찾기에서 제거"
|
unfavorite: "즐겨찾기에서 제거"
|
||||||
watch: "ウォッチ"
|
watch: "지켜보기"
|
||||||
unwatch: "ウォッチ解除"
|
unwatch: "지켜보기 해제"
|
||||||
pin: "프로필에 고정"
|
pin: "프로필에 고정"
|
||||||
unpin: "프로필에서 고정 해제"
|
unpin: "프로필에서 고정 해제"
|
||||||
delete: "삭제"
|
delete: "삭제"
|
||||||
@@ -509,13 +509,13 @@ common/views/components/profile-editor.vue:
|
|||||||
email-address: "메일 주소"
|
email-address: "메일 주소"
|
||||||
email-verified: "매일 주소가 확인되었습니다"
|
email-verified: "매일 주소가 확인되었습니다"
|
||||||
email-not-verified: "메일 주소가 확인되지 않았습니다. 받은 편지함을 확인하여 주시기 바랍니다."
|
email-not-verified: "메일 주소가 확인되지 않았습니다. 받은 편지함을 확인하여 주시기 바랍니다."
|
||||||
export: "エクスポート"
|
export: "내보내기"
|
||||||
export-targets:
|
export-targets:
|
||||||
all-notes: "すべての投稿データ"
|
all-notes: "모든 글 데이터"
|
||||||
following-list: "フォロー"
|
following-list: "팔로잉"
|
||||||
mute-list: "ミュート"
|
mute-list: "뮤트"
|
||||||
blocking-list: "ブロック"
|
blocking-list: "차단"
|
||||||
export-requested: "エクスポートをリクエストしました。これには時間がかかる場合があります。エクスポートが終わると、ドライブにファイルが追加されます。"
|
export-requested: "내보내기를 요청하였습니다. 이 작업은 시간이 걸릴 수 있습니다. 내보내기가 완료되면 드라이브에 파일이 추가됩니다."
|
||||||
common/views/components/user-list-editor.vue:
|
common/views/components/user-list-editor.vue:
|
||||||
users: "사용자"
|
users: "사용자"
|
||||||
rename: "리스트 이름 바꾸기"
|
rename: "리스트 이름 바꾸기"
|
||||||
@@ -1007,7 +1007,7 @@ admin/views/index.vue:
|
|||||||
announcements: "공지사항"
|
announcements: "공지사항"
|
||||||
hashtags: "해시태그"
|
hashtags: "해시태그"
|
||||||
abuse: "스팸 신고"
|
abuse: "스팸 신고"
|
||||||
queue: "ジョブキュー"
|
queue: "작업 대기열"
|
||||||
back-to-misskey: "Misskey로 돌아가기"
|
back-to-misskey: "Misskey로 돌아가기"
|
||||||
admin/views/dashboard.vue:
|
admin/views/dashboard.vue:
|
||||||
dashboard: "대시보드"
|
dashboard: "대시보드"
|
||||||
@@ -1018,8 +1018,8 @@ admin/views/dashboard.vue:
|
|||||||
this-instance: "이 인스턴스"
|
this-instance: "이 인스턴스"
|
||||||
federated: "연합"
|
federated: "연합"
|
||||||
admin/views/queue.vue:
|
admin/views/queue.vue:
|
||||||
operation: "操作"
|
operation: "동작"
|
||||||
remove-all-jobs: "すべてのジョブをクリア"
|
remove-all-jobs: "모든 작업 제거"
|
||||||
admin/views/abuse.vue:
|
admin/views/abuse.vue:
|
||||||
title: "스팸 신고"
|
title: "스팸 신고"
|
||||||
target: "대상"
|
target: "대상"
|
||||||
@@ -1114,7 +1114,7 @@ admin/views/charts.vue:
|
|||||||
notes: "글 증감 (통합)"
|
notes: "글 증감 (통합)"
|
||||||
local-notes: "글 증감 (로컬)"
|
local-notes: "글 증감 (로컬)"
|
||||||
remote-notes: "글 증감 (원격)"
|
remote-notes: "글 증감 (원격)"
|
||||||
notes-total: "글 누적 수"
|
notes-total: "글 누적"
|
||||||
users: "사용자 증감"
|
users: "사용자 증감"
|
||||||
users-total: "사용자 누적"
|
users-total: "사용자 누적"
|
||||||
active-users: "활성 사용자 수"
|
active-users: "활성 사용자 수"
|
||||||
@@ -1186,6 +1186,7 @@ admin/views/users.vue:
|
|||||||
moderator: "모더레이터"
|
moderator: "모더레이터"
|
||||||
adminOrModerator: "관리자+모더레이터"
|
adminOrModerator: "관리자+모더레이터"
|
||||||
verified: "공식 계정"
|
verified: "공식 계정"
|
||||||
|
silenced: "침묵됨"
|
||||||
suspended: "정지됨"
|
suspended: "정지됨"
|
||||||
origin:
|
origin:
|
||||||
title: "위치 (오리진)"
|
title: "위치 (오리진)"
|
||||||
@@ -1234,63 +1235,63 @@ admin/views/announcements.vue:
|
|||||||
admin/views/hashtags.vue:
|
admin/views/hashtags.vue:
|
||||||
hided-tags: "Hidden Tags"
|
hided-tags: "Hidden Tags"
|
||||||
admin/views/federation.vue:
|
admin/views/federation.vue:
|
||||||
federation: "連合"
|
federation: "연합"
|
||||||
host: "ホスト"
|
host: "호스트"
|
||||||
notes: "投稿"
|
notes: "글"
|
||||||
users: "ユーザー"
|
users: "사용자"
|
||||||
following: "フォロー中"
|
following: "팔로우 중"
|
||||||
followers: "フォロワー"
|
followers: "팔로워"
|
||||||
status: "ステータス"
|
status: "상태"
|
||||||
latest-request-sent-at: "直近のリクエスト送信"
|
latest-request-sent-at: "마지막으로 요청을 전송한 시간"
|
||||||
latest-request-received-at: "直近のリクエスト受信"
|
latest-request-received-at: "마지막으로 요청을 받은 시간"
|
||||||
remove-all-following: "フォローを全解除"
|
remove-all-following: "모든 팔로잉 해제"
|
||||||
remove-all-following-info: "{host}からのフォローをすべて解除します。そのインスタンスがもう存在しなくなった場合などに実行してください。"
|
remove-all-following-info: "{host}(으)로부터 모든 팔로잉을 해제합니다. 해당 인스턴스가 더 이상 존재하지 않게 된 경우 등에 실행하십시오."
|
||||||
block: "ブロック"
|
block: "차단"
|
||||||
marked-as-closed: "閉鎖されているとマーク"
|
marked-as-closed: "폐쇄된 것으로 표시"
|
||||||
lookup: "照会"
|
lookup: "조회"
|
||||||
instances: "インスタンス"
|
instances: "인스턴스"
|
||||||
instance-not-registered: "そのインスタンスは登録されていません"
|
instance-not-registered: "해당 인스턴스가 등록되어 있지 않습니다"
|
||||||
sort: "ソート"
|
sort: "정렬"
|
||||||
sorts:
|
sorts:
|
||||||
caughtAtAsc: "登録日時が古い順"
|
caughtAtAsc: "등록일이 오래된 순"
|
||||||
caughtAtDesc: "登録日時が新しい順"
|
caughtAtDesc: "등록일이 최신인 순"
|
||||||
lastCommunicatedAtAsc: "最後にやり取りした日時が古い順"
|
lastCommunicatedAtAsc: "마지막으로 요청을 주고받은 일시가 오래된 순"
|
||||||
lastCommunicatedAtDesc: "最後にやり取りした日時が新しい順"
|
lastCommunicatedAtDesc: "마지막으로 요청을 주고받은 일시가 빠른 순"
|
||||||
notesAsc: "投稿が少ない順"
|
notesAsc: "글이 적은 순"
|
||||||
notesDesc: "投稿が多い順"
|
notesDesc: "글이 많은 순"
|
||||||
usersAsc: "ユーザーが少ない順"
|
usersAsc: "사용자가 적은 순"
|
||||||
usersDesc: "ユーザーが多い順"
|
usersDesc: "사용자가 많은 순"
|
||||||
followingAsc: "フォローが少ない順"
|
followingAsc: "팔로잉이 적은 순"
|
||||||
followingDesc: "フォローが多い順"
|
followingDesc: "팔로잉이 많은 순"
|
||||||
followersAsc: "フォロワーが少ない順"
|
followersAsc: "팔로워가 적은 순"
|
||||||
followersDesc: "フォロワーが多い順"
|
followersDesc: "팔로워가 많은 순"
|
||||||
driveUsageAsc: "ドライブ使用量が少ない順"
|
driveUsageAsc: "드라이브 사용량이 적은 순"
|
||||||
driveUsageDesc: "ドライブ使用量が多い順"
|
driveUsageDesc: "드라이브 사용량이 많은 순"
|
||||||
driveFilesAsc: "ドライブのファイル数が少ない順"
|
driveFilesAsc: "드라이브 파일 수가 적은 순"
|
||||||
driveFilesDesc: "ドライブのファイル数が多い順"
|
driveFilesDesc: "드라이브 파일 수가 많은 순"
|
||||||
state: "状態"
|
state: "상태"
|
||||||
states:
|
states:
|
||||||
all: "すべて"
|
all: "모두"
|
||||||
blocked: "ブロック"
|
blocked: "차단됨"
|
||||||
not-responding: "応答なし"
|
not-responding: "응답 없음"
|
||||||
marked-as-closed: "閉鎖とマーク済み"
|
marked-as-closed: "폐쇄된 것으로 표시됨"
|
||||||
result-is-truncated: "上位{n}件を表示しています。"
|
result-is-truncated: "상위 {n}개를 표시하고 있습니다."
|
||||||
charts: "チャート"
|
charts: "차트"
|
||||||
chart-srcs:
|
chart-srcs:
|
||||||
requests: "リクエスト"
|
requests: "요청"
|
||||||
users: "ユーザーの増減"
|
users: "사용자 증감"
|
||||||
users-total: "ユーザーの積算"
|
users-total: "사용자 누적"
|
||||||
notes: "投稿の増減"
|
notes: "글 증감"
|
||||||
notes-total: "投稿の積算"
|
notes-total: "글 누적"
|
||||||
ff: "フォロー/フォロワーの増減"
|
ff: "팔로잉/팔로워 증감"
|
||||||
ff-total: "フォロー/フォロワーの積算"
|
ff-total: "팔로잉/팔로워 누적"
|
||||||
drive-usage: "ドライブ使用量の増減"
|
drive-usage: "드라이브 사용량 증감"
|
||||||
drive-usage-total: "ドライブ使用量の積算"
|
drive-usage-total: "드라이브 사용량 누적"
|
||||||
drive-files: "ドライブファイル数の増減"
|
drive-files: "드라이브 파일 수 증감"
|
||||||
drive-files-total: "ドライブファイル数の積算"
|
drive-files-total: "드라이브 파일 수 누적"
|
||||||
chart-spans:
|
chart-spans:
|
||||||
hour: "1時間ごと"
|
hour: "1시간마다"
|
||||||
day: "1日ごと"
|
day: "1일마다"
|
||||||
desktop/views/pages/welcome.vue:
|
desktop/views/pages/welcome.vue:
|
||||||
about: "자세히..."
|
about: "자세히..."
|
||||||
gotit: "알겠습니다"
|
gotit: "알겠습니다"
|
||||||
@@ -1626,6 +1627,7 @@ deck/deck.tl-column.vue:
|
|||||||
is-media-view: "미디어 보기"
|
is-media-view: "미디어 보기"
|
||||||
edit: "옵션"
|
edit: "옵션"
|
||||||
deck/deck.user-column.vue:
|
deck/deck.user-column.vue:
|
||||||
|
follows-you: "당신을 팔로우합니다"
|
||||||
posts: "글"
|
posts: "글"
|
||||||
following: "팔로잉"
|
following: "팔로잉"
|
||||||
followers: "팔로워"
|
followers: "팔로워"
|
||||||
|
|||||||
@@ -1186,6 +1186,7 @@ admin/views/users.vue:
|
|||||||
moderator: "モデレーター"
|
moderator: "モデレーター"
|
||||||
adminOrModerator: "管理者+モデレーター"
|
adminOrModerator: "管理者+モデレーター"
|
||||||
verified: "公式アカウント"
|
verified: "公式アカウント"
|
||||||
|
silenced: "サイレンス済み"
|
||||||
suspended: "凍結済み"
|
suspended: "凍結済み"
|
||||||
origin:
|
origin:
|
||||||
title: "オリジン"
|
title: "オリジン"
|
||||||
@@ -1626,6 +1627,7 @@ deck/deck.tl-column.vue:
|
|||||||
is-media-view: "メディアビュー"
|
is-media-view: "メディアビュー"
|
||||||
edit: "オプション"
|
edit: "オプション"
|
||||||
deck/deck.user-column.vue:
|
deck/deck.user-column.vue:
|
||||||
|
follows-you: "フォローされています"
|
||||||
posts: "投稿"
|
posts: "投稿"
|
||||||
following: "フォロー"
|
following: "フォロー"
|
||||||
followers: "フォロワー"
|
followers: "フォロワー"
|
||||||
|
|||||||
@@ -1186,6 +1186,7 @@ admin/views/users.vue:
|
|||||||
moderator: "モデレーター"
|
moderator: "モデレーター"
|
||||||
adminOrModerator: "管理者+モデレーター"
|
adminOrModerator: "管理者+モデレーター"
|
||||||
verified: "公式アカウント"
|
verified: "公式アカウント"
|
||||||
|
silenced: "サイレンス済み"
|
||||||
suspended: "凍結済み"
|
suspended: "凍結済み"
|
||||||
origin:
|
origin:
|
||||||
title: "オリジン"
|
title: "オリジン"
|
||||||
@@ -1590,13 +1591,13 @@ mobile/views/pages/user/home.vue:
|
|||||||
activity: "アクティビティ"
|
activity: "アクティビティ"
|
||||||
keywords: "Nøkkelord"
|
keywords: "Nøkkelord"
|
||||||
domains: "頻出ドメイン"
|
domains: "頻出ドメイン"
|
||||||
frequently-replied-users: "よく会話するユーザー"
|
frequently-replied-users: "よく話すユーザー"
|
||||||
followers-you-know: "知り合いのフォロワー"
|
followers-you-know: "知り合いのフォロワー"
|
||||||
last-used-at: "最終ログイン"
|
last-used-at: "最終ログイン"
|
||||||
mobile/views/pages/user/home.followers-you-know.vue:
|
mobile/views/pages/user/home.followers-you-know.vue:
|
||||||
no-users: "知り合いのユーザーはいません"
|
no-users: "知り合いのユーザーはいません"
|
||||||
mobile/views/pages/user/home.friends.vue:
|
mobile/views/pages/user/home.friends.vue:
|
||||||
no-users: "よく会話するユーザーはいません"
|
no-users: "よく話すユーザーはいません"
|
||||||
mobile/views/pages/user/home.notes.vue:
|
mobile/views/pages/user/home.notes.vue:
|
||||||
no-notes: "投稿はありません"
|
no-notes: "投稿はありません"
|
||||||
mobile/views/pages/user/home.photos.vue:
|
mobile/views/pages/user/home.photos.vue:
|
||||||
@@ -1626,6 +1627,7 @@ deck/deck.tl-column.vue:
|
|||||||
is-media-view: "メディアビュー"
|
is-media-view: "メディアビュー"
|
||||||
edit: "オプション"
|
edit: "オプション"
|
||||||
deck/deck.user-column.vue:
|
deck/deck.user-column.vue:
|
||||||
|
follows-you: "フォローされています"
|
||||||
posts: "投稿"
|
posts: "投稿"
|
||||||
following: "フォロー"
|
following: "フォロー"
|
||||||
followers: "フォロワー"
|
followers: "フォロワー"
|
||||||
|
|||||||
@@ -1186,6 +1186,7 @@ admin/views/users.vue:
|
|||||||
moderator: "モデレーター"
|
moderator: "モデレーター"
|
||||||
adminOrModerator: "管理者+モデレーター"
|
adminOrModerator: "管理者+モデレーター"
|
||||||
verified: "公式アカウント"
|
verified: "公式アカウント"
|
||||||
|
silenced: "サイレンス済み"
|
||||||
suspended: "凍結済み"
|
suspended: "凍結済み"
|
||||||
origin:
|
origin:
|
||||||
title: "Źródło"
|
title: "Źródło"
|
||||||
@@ -1626,6 +1627,7 @@ deck/deck.tl-column.vue:
|
|||||||
is-media-view: "Widok multimediów"
|
is-media-view: "Widok multimediów"
|
||||||
edit: "Opcje"
|
edit: "Opcje"
|
||||||
deck/deck.user-column.vue:
|
deck/deck.user-column.vue:
|
||||||
|
follows-you: "フォローされています"
|
||||||
posts: "Wpisy"
|
posts: "Wpisy"
|
||||||
following: "Śledzeni"
|
following: "Śledzeni"
|
||||||
followers: "Śledzący"
|
followers: "Śledzący"
|
||||||
|
|||||||
@@ -1186,6 +1186,7 @@ admin/views/users.vue:
|
|||||||
moderator: "モデレーター"
|
moderator: "モデレーター"
|
||||||
adminOrModerator: "管理者+モデレーター"
|
adminOrModerator: "管理者+モデレーター"
|
||||||
verified: "公式アカウント"
|
verified: "公式アカウント"
|
||||||
|
silenced: "サイレンス済み"
|
||||||
suspended: "凍結済み"
|
suspended: "凍結済み"
|
||||||
origin:
|
origin:
|
||||||
title: "オリジン"
|
title: "オリジン"
|
||||||
@@ -1596,7 +1597,7 @@ mobile/views/pages/user/home.vue:
|
|||||||
mobile/views/pages/user/home.followers-you-know.vue:
|
mobile/views/pages/user/home.followers-you-know.vue:
|
||||||
no-users: "知り合いのユーザーはいません"
|
no-users: "知り合いのユーザーはいません"
|
||||||
mobile/views/pages/user/home.friends.vue:
|
mobile/views/pages/user/home.friends.vue:
|
||||||
no-users: "よく会話するユーザーはいません"
|
no-users: "よく話すユーザーはいません"
|
||||||
mobile/views/pages/user/home.notes.vue:
|
mobile/views/pages/user/home.notes.vue:
|
||||||
no-notes: "Nenhuma mensagem"
|
no-notes: "Nenhuma mensagem"
|
||||||
mobile/views/pages/user/home.photos.vue:
|
mobile/views/pages/user/home.photos.vue:
|
||||||
@@ -1626,6 +1627,7 @@ deck/deck.tl-column.vue:
|
|||||||
is-media-view: "メディアビュー"
|
is-media-view: "メディアビュー"
|
||||||
edit: "オプション"
|
edit: "オプション"
|
||||||
deck/deck.user-column.vue:
|
deck/deck.user-column.vue:
|
||||||
|
follows-you: "フォローされています"
|
||||||
posts: "投稿"
|
posts: "投稿"
|
||||||
following: "フォロー"
|
following: "フォロー"
|
||||||
followers: "フォロワー"
|
followers: "フォロワー"
|
||||||
|
|||||||
@@ -1186,6 +1186,7 @@ admin/views/users.vue:
|
|||||||
moderator: "モデレーター"
|
moderator: "モデレーター"
|
||||||
adminOrModerator: "管理者+モデレーター"
|
adminOrModerator: "管理者+モデレーター"
|
||||||
verified: "公式アカウント"
|
verified: "公式アカウント"
|
||||||
|
silenced: "サイレンス済み"
|
||||||
suspended: "凍結済み"
|
suspended: "凍結済み"
|
||||||
origin:
|
origin:
|
||||||
title: "オリジン"
|
title: "オリジン"
|
||||||
@@ -1590,13 +1591,13 @@ mobile/views/pages/user/home.vue:
|
|||||||
activity: "アクティビティ"
|
activity: "アクティビティ"
|
||||||
keywords: "キーワード"
|
keywords: "キーワード"
|
||||||
domains: "頻出ドメイン"
|
domains: "頻出ドメイン"
|
||||||
frequently-replied-users: "よく会話するユーザー"
|
frequently-replied-users: "よく話すユーザー"
|
||||||
followers-you-know: "知り合いのフォロワー"
|
followers-you-know: "知り合いのフォロワー"
|
||||||
last-used-at: "最終ログイン"
|
last-used-at: "最終ログイン"
|
||||||
mobile/views/pages/user/home.followers-you-know.vue:
|
mobile/views/pages/user/home.followers-you-know.vue:
|
||||||
no-users: "知り合いのユーザーはいません"
|
no-users: "知り合いのユーザーはいません"
|
||||||
mobile/views/pages/user/home.friends.vue:
|
mobile/views/pages/user/home.friends.vue:
|
||||||
no-users: "よく会話するユーザーはいません"
|
no-users: "よく話すユーザーはいません"
|
||||||
mobile/views/pages/user/home.notes.vue:
|
mobile/views/pages/user/home.notes.vue:
|
||||||
no-notes: "投稿はありません"
|
no-notes: "投稿はありません"
|
||||||
mobile/views/pages/user/home.photos.vue:
|
mobile/views/pages/user/home.photos.vue:
|
||||||
@@ -1626,6 +1627,7 @@ deck/deck.tl-column.vue:
|
|||||||
is-media-view: "メディアビュー"
|
is-media-view: "メディアビュー"
|
||||||
edit: "オプション"
|
edit: "オプション"
|
||||||
deck/deck.user-column.vue:
|
deck/deck.user-column.vue:
|
||||||
|
follows-you: "フォローされています"
|
||||||
posts: "投稿"
|
posts: "投稿"
|
||||||
following: "フォロー"
|
following: "フォロー"
|
||||||
followers: "フォロワー"
|
followers: "フォロワー"
|
||||||
|
|||||||
@@ -1186,6 +1186,7 @@ admin/views/users.vue:
|
|||||||
moderator: "版主"
|
moderator: "版主"
|
||||||
adminOrModerator: "管理员+版主"
|
adminOrModerator: "管理员+版主"
|
||||||
verified: "官方认证账户"
|
verified: "官方认证账户"
|
||||||
|
silenced: "已禁言"
|
||||||
suspended: "已冻结"
|
suspended: "已冻结"
|
||||||
origin:
|
origin:
|
||||||
title: "源自"
|
title: "源自"
|
||||||
@@ -1626,6 +1627,7 @@ deck/deck.tl-column.vue:
|
|||||||
is-media-view: "媒体视图"
|
is-media-view: "媒体视图"
|
||||||
edit: "选项"
|
edit: "选项"
|
||||||
deck/deck.user-column.vue:
|
deck/deck.user-column.vue:
|
||||||
|
follows-you: "关注您"
|
||||||
posts: "帖子"
|
posts: "帖子"
|
||||||
following: "关注中"
|
following: "关注中"
|
||||||
followers: "关注者"
|
followers: "关注者"
|
||||||
|
|||||||
19
package.json
19
package.json
@@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"name": "misskey",
|
"name": "misskey",
|
||||||
"author": "syuilo <i@syuilo.com>",
|
"author": "syuilo <i@syuilo.com>",
|
||||||
"version": "10.84.0",
|
"version": "10.86.1",
|
||||||
"clientVersion": "2.0.14224",
|
"clientVersion": "2.0.14327",
|
||||||
"codename": "nighthike",
|
"codename": "nighthike",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@@ -23,9 +23,6 @@
|
|||||||
"test": "gulp test",
|
"test": "gulp test",
|
||||||
"format": "gulp format"
|
"format": "gulp format"
|
||||||
},
|
},
|
||||||
"resolutions": {
|
|
||||||
"terser": "3.14.1"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fortawesome/fontawesome-svg-core": "1.2.14",
|
"@fortawesome/fontawesome-svg-core": "1.2.14",
|
||||||
"@fortawesome/free-brands-svg-icons": "5.7.1",
|
"@fortawesome/free-brands-svg-icons": "5.7.1",
|
||||||
@@ -99,14 +96,14 @@
|
|||||||
"@types/websocket": "0.0.40",
|
"@types/websocket": "0.0.40",
|
||||||
"@types/ws": "6.0.1",
|
"@types/ws": "6.0.1",
|
||||||
"animejs": "3.0.1",
|
"animejs": "3.0.1",
|
||||||
"apexcharts": "3.2.2",
|
"apexcharts": "3.3.0",
|
||||||
"autobind-decorator": "2.4.0",
|
"autobind-decorator": "2.4.0",
|
||||||
"autosize": "4.0.2",
|
"autosize": "4.0.2",
|
||||||
"autwh": "0.1.0",
|
"autwh": "0.1.0",
|
||||||
"bcryptjs": "2.4.3",
|
"bcryptjs": "2.4.3",
|
||||||
"bee-queue": "1.2.2",
|
"bee-queue": "1.2.2",
|
||||||
"bootstrap-vue": "2.0.0-rc.11",
|
"bootstrap-vue": "2.0.0-rc.11",
|
||||||
"cafy": "12.1.0",
|
"cafy": "14.0.1",
|
||||||
"chai": "4.2.0",
|
"chai": "4.2.0",
|
||||||
"chai-http": "4.2.1",
|
"chai-http": "4.2.1",
|
||||||
"chalk": "2.4.2",
|
"chalk": "2.4.2",
|
||||||
@@ -144,7 +141,7 @@
|
|||||||
"hard-source-webpack-plugin": "0.13.1",
|
"hard-source-webpack-plugin": "0.13.1",
|
||||||
"html-minifier": "3.5.21",
|
"html-minifier": "3.5.21",
|
||||||
"http-signature": "1.2.0",
|
"http-signature": "1.2.0",
|
||||||
"insert-text-at-cursor": "0.1.1",
|
"insert-text-at-cursor": "0.1.2",
|
||||||
"is-root": "2.0.0",
|
"is-root": "2.0.0",
|
||||||
"is-svg": "3.0.0",
|
"is-svg": "3.0.0",
|
||||||
"js-yaml": "3.12.1",
|
"js-yaml": "3.12.1",
|
||||||
@@ -232,11 +229,11 @@
|
|||||||
"uuid": "3.3.2",
|
"uuid": "3.3.2",
|
||||||
"v-animate-css": "0.0.3",
|
"v-animate-css": "0.0.3",
|
||||||
"video-thumbnail-generator": "1.1.3",
|
"video-thumbnail-generator": "1.1.3",
|
||||||
"vue": "2.6.4",
|
"vue": "2.6.6",
|
||||||
"vue-color": "2.7.0",
|
"vue-color": "2.7.0",
|
||||||
"vue-content-loading": "1.5.3",
|
"vue-content-loading": "1.5.3",
|
||||||
"vue-cropperjs": "3.0.0",
|
"vue-cropperjs": "3.0.0",
|
||||||
"vue-i18n": "8.8.0",
|
"vue-i18n": "8.8.1",
|
||||||
"vue-js-modal": "1.3.28",
|
"vue-js-modal": "1.3.28",
|
||||||
"vue-loader": "15.6.2",
|
"vue-loader": "15.6.2",
|
||||||
"vue-marquee-text-component": "1.1.1",
|
"vue-marquee-text-component": "1.1.1",
|
||||||
@@ -245,7 +242,7 @@
|
|||||||
"vue-sequential-entrance": "1.1.3",
|
"vue-sequential-entrance": "1.1.3",
|
||||||
"vue-style-loader": "4.1.2",
|
"vue-style-loader": "4.1.2",
|
||||||
"vue-svg-inline-loader": "1.2.10",
|
"vue-svg-inline-loader": "1.2.10",
|
||||||
"vue-template-compiler": "2.6.4",
|
"vue-template-compiler": "2.6.6",
|
||||||
"vuedraggable": "2.17.0",
|
"vuedraggable": "2.17.0",
|
||||||
"vuewordcloud": "18.7.11",
|
"vuewordcloud": "18.7.11",
|
||||||
"vuex": "3.1.0",
|
"vuex": "3.1.0",
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ program
|
|||||||
.version(pkg.version)
|
.version(pkg.version)
|
||||||
.option('--no-daemons', 'Disable daemon processes (for debbuging)')
|
.option('--no-daemons', 'Disable daemon processes (for debbuging)')
|
||||||
.option('--disable-clustering', 'Disable clustering')
|
.option('--disable-clustering', 'Disable clustering')
|
||||||
.option('--disable-ap-queue', 'Disable creating job queue related to ap')
|
|
||||||
.option('--disable-queue', 'Disable job queue processing')
|
.option('--disable-queue', 'Disable job queue processing')
|
||||||
.option('--only-queue', 'Pocessing job queue only')
|
.option('--only-server', 'Run server only (without job queue)')
|
||||||
|
.option('--only-queue', 'Pocessing job queue only (without server)')
|
||||||
.option('--quiet', 'Suppress all logs')
|
.option('--quiet', 'Suppress all logs')
|
||||||
.option('--verbose', 'Enable all logs')
|
.option('--verbose', 'Enable all logs')
|
||||||
.option('--with-log-time', 'Include timestamp for each logs')
|
.option('--with-log-time', 'Include timestamp for each logs')
|
||||||
@@ -15,8 +15,7 @@ program
|
|||||||
.option('--color', 'This option is a dummy for some external program\'s (e.g. forever) issue.')
|
.option('--color', 'This option is a dummy for some external program\'s (e.g. forever) issue.')
|
||||||
.parse(process.argv);
|
.parse(process.argv);
|
||||||
|
|
||||||
/*if (process.env.MK_DISABLE_AP_QUEUE)*/ program.disableApQueue = true;
|
/*if (process.env.MK_DISABLE_QUEUE)*/ program.disableQueue = true;
|
||||||
if (process.env.MK_DISABLE_QUEUE) program.disableQueue = true;
|
|
||||||
if (process.env.MK_ONLY_QUEUE) program.onlyQueue = true;
|
if (process.env.MK_ONLY_QUEUE) program.onlyQueue = true;
|
||||||
|
|
||||||
export { program };
|
export { program };
|
||||||
|
|||||||
@@ -148,7 +148,7 @@ export default Vue.extend({
|
|||||||
return {
|
return {
|
||||||
instance: null,
|
instance: null,
|
||||||
target: null,
|
target: null,
|
||||||
sort: '+caughtAt',
|
sort: '+lastCommunicatedAt',
|
||||||
state: 'all',
|
state: 'all',
|
||||||
limit: 50,
|
limit: 50,
|
||||||
instances: [],
|
instances: [],
|
||||||
|
|||||||
@@ -48,6 +48,7 @@
|
|||||||
<option value="admin">{{ $t('users.state.admin') }}</option>
|
<option value="admin">{{ $t('users.state.admin') }}</option>
|
||||||
<option value="moderator">{{ $t('users.state.moderator') }}</option>
|
<option value="moderator">{{ $t('users.state.moderator') }}</option>
|
||||||
<option value="verified">{{ $t('users.state.verified') }}</option>
|
<option value="verified">{{ $t('users.state.verified') }}</option>
|
||||||
|
<option value="silenced">{{ $t('users.state.silenced') }}</option>
|
||||||
<option value="suspended">{{ $t('users.state.suspended') }}</option>
|
<option value="suspended">{{ $t('users.state.suspended') }}</option>
|
||||||
</ui-select>
|
</ui-select>
|
||||||
<ui-select v-model="origin">
|
<ui-select v-model="origin">
|
||||||
@@ -89,7 +90,7 @@ export default Vue.extend({
|
|||||||
unsuspending: false,
|
unsuspending: false,
|
||||||
sort: '+createdAt',
|
sort: '+createdAt',
|
||||||
state: 'all',
|
state: 'all',
|
||||||
origin: 'combined',
|
origin: 'local',
|
||||||
limit: 10,
|
limit: 10,
|
||||||
offset: 0,
|
offset: 0,
|
||||||
users: [],
|
users: [],
|
||||||
@@ -129,16 +130,25 @@ export default Vue.extend({
|
|||||||
const usernamePromise = this.$root.api('users/show', parseAcct(this.target));
|
const usernamePromise = this.$root.api('users/show', parseAcct(this.target));
|
||||||
const idPromise = this.$root.api('users/show', { userId: this.target });
|
const idPromise = this.$root.api('users/show', { userId: this.target });
|
||||||
|
|
||||||
usernamePromise.then(res);
|
let _notFound = false;
|
||||||
idPromise.then(res);
|
const notFound = () => {
|
||||||
|
if (_notFound) {
|
||||||
idPromise.catch(e => {
|
|
||||||
if (e == 'user not found') {
|
|
||||||
this.$root.dialog({
|
this.$root.dialog({
|
||||||
type: 'error',
|
type: 'error',
|
||||||
text: this.$t('user-not-found')
|
text: this.$t('user-not-found')
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
_notFound = true;
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
usernamePromise.then(res).catch(e => {
|
||||||
|
if (e == 'user not found') {
|
||||||
|
notFound();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
idPromise.then(res).catch(e => {
|
||||||
|
notFound();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -329,7 +339,7 @@ export default Vue.extend({
|
|||||||
});
|
});
|
||||||
|
|
||||||
return !confirm.canceled;
|
return !confirm.canceled;
|
||||||
}
|
},
|
||||||
|
|
||||||
fetchUsers() {
|
fetchUsers() {
|
||||||
this.$root.api('admin/show-users', {
|
this.$root.api('admin/show-users', {
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
import { url as instanceUrl } from '../../config';
|
import { url as instanceUrl } from '../../config';
|
||||||
|
import * as url from '../../../../prelude/url';
|
||||||
|
|
||||||
export function getStaticImageUrl(url: string): string {
|
export function getStaticImageUrl(baseUrl: string): string {
|
||||||
const u = new URL(url);
|
const u = new URL(baseUrl);
|
||||||
const dummy = `${u.host}${u.pathname}`; // 拡張子がないとキャッシュしてくれないCDNがあるので
|
const dummy = `${u.host}${u.pathname}`; // 拡張子がないとキャッシュしてくれないCDNがあるので
|
||||||
let result = `${instanceUrl}/proxy/${dummy}?url=${encodeURIComponent(u.href)}`;
|
return `${instanceUrl}/proxy/${dummy}?${url.query({
|
||||||
result += '&static=1';
|
url: u.href,
|
||||||
return result;
|
static: '1'
|
||||||
|
})}`;
|
||||||
}
|
}
|
||||||
|
|||||||
18
src/client/app/common/size.ts
Normal file
18
src/client/app/common/size.ts
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
export default {
|
||||||
|
install(Vue) {
|
||||||
|
Vue.directive('size', {
|
||||||
|
inserted(el, binding) {
|
||||||
|
const query = binding.value;
|
||||||
|
const width = el.clientWidth;
|
||||||
|
for (const q of query) {
|
||||||
|
if (q.lt && (width <= q.lt)) {
|
||||||
|
el.classList.add(q.class);
|
||||||
|
}
|
||||||
|
if (q.gt && (width >= q.gt)) {
|
||||||
|
el.classList.add(q.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="mk-activity">
|
<div>
|
||||||
<div ref="chart"></div>
|
<div ref="chart"></div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -9,7 +9,17 @@ import Vue from 'vue';
|
|||||||
import ApexCharts from 'apexcharts';
|
import ApexCharts from 'apexcharts';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
props: ['user'],
|
props: {
|
||||||
|
user: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
limit: {
|
||||||
|
type: Number,
|
||||||
|
required: false,
|
||||||
|
default: 21
|
||||||
|
}
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
fetching: true,
|
fetching: true,
|
||||||
@@ -21,7 +31,7 @@ export default Vue.extend({
|
|||||||
this.$root.api('charts/user/notes', {
|
this.$root.api('charts/user/notes', {
|
||||||
userId: this.user.id,
|
userId: this.user.id,
|
||||||
span: 'day',
|
span: 'day',
|
||||||
limit: 21
|
limit: this.limit
|
||||||
}).then(stats => {
|
}).then(stats => {
|
||||||
const normal = [];
|
const normal = [];
|
||||||
const reply = [];
|
const reply = [];
|
||||||
@@ -32,7 +42,7 @@ export default Vue.extend({
|
|||||||
const m = now.getMonth();
|
const m = now.getMonth();
|
||||||
const d = now.getDate();
|
const d = now.getDate();
|
||||||
|
|
||||||
for (let i = 0; i < 21; i++) {
|
for (let i = 0; i < this.limit; i++) {
|
||||||
const x = new Date(y, m, d - i);
|
const x = new Date(y, m, d - i);
|
||||||
normal.push([
|
normal.push([
|
||||||
x,
|
x,
|
||||||
@@ -99,10 +109,3 @@ export default Vue.extend({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="stylus" scoped>
|
|
||||||
.mk-activity
|
|
||||||
max-width 600px
|
|
||||||
margin 0 auto
|
|
||||||
|
|
||||||
</style>
|
|
||||||
11
src/client/app/common/views/components/dummy.vue
Normal file
11
src/client/app/common/views/components/dummy.vue
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import Vue from 'vue';
|
||||||
|
export default Vue.extend({
|
||||||
|
});
|
||||||
|
</script>
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<button class="wfliddvnhxvyusikowhxozkyxyenqxqr"
|
<button class="wfliddvnhxvyusikowhxozkyxyenqxqr"
|
||||||
:class="{ wait, block, mini, active: isFollowing || hasPendingFollowRequestFromYou }"
|
:class="{ wait, block, inline, mini, active: isFollowing || hasPendingFollowRequestFromYou }"
|
||||||
@click="onClick"
|
@click="onClick"
|
||||||
:disabled="wait"
|
:disabled="wait"
|
||||||
|
:inline="inline"
|
||||||
>
|
>
|
||||||
<template v-if="!wait">
|
<template v-if="!wait">
|
||||||
<fa :icon="iconAndText[0]"/> <template v-if="!mini">{{ iconAndText[1] }}</template>
|
<fa :icon="iconAndText[0]"/> <template v-if="!mini">{{ iconAndText[1] }}</template>
|
||||||
@@ -28,6 +29,11 @@ export default Vue.extend({
|
|||||||
required: false,
|
required: false,
|
||||||
default: false
|
default: false
|
||||||
},
|
},
|
||||||
|
inline: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
mini: {
|
mini: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
required: false,
|
required: false,
|
||||||
@@ -128,6 +134,9 @@ export default Vue.extend({
|
|||||||
border solid 1px var(--primary)
|
border solid 1px var(--primary)
|
||||||
border-radius 36px
|
border-radius 36px
|
||||||
|
|
||||||
|
&.inline
|
||||||
|
display inline-block
|
||||||
|
|
||||||
&.mini
|
&.mini
|
||||||
padding 0
|
padding 0
|
||||||
min-width 0
|
min-width 0
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
|
|
||||||
|
import dummy from './dummy.vue';
|
||||||
import userName from './user-name.vue';
|
import userName from './user-name.vue';
|
||||||
import followButton from './follow-button.vue';
|
import followButton from './follow-button.vue';
|
||||||
import error from './error.vue';
|
import error from './error.vue';
|
||||||
@@ -32,6 +33,7 @@ import urlPreview from './url-preview.vue';
|
|||||||
import fileTypeIcon from './file-type-icon.vue';
|
import fileTypeIcon from './file-type-icon.vue';
|
||||||
import emoji from './emoji.vue';
|
import emoji from './emoji.vue';
|
||||||
import welcomeTimeline from './welcome-timeline.vue';
|
import welcomeTimeline from './welcome-timeline.vue';
|
||||||
|
import userList from './user-list.vue';
|
||||||
import uiInput from './ui/input.vue';
|
import uiInput from './ui/input.vue';
|
||||||
import uiButton from './ui/button.vue';
|
import uiButton from './ui/button.vue';
|
||||||
import uiHorizonGroup from './ui/horizon-group.vue';
|
import uiHorizonGroup from './ui/horizon-group.vue';
|
||||||
@@ -46,6 +48,7 @@ import formButton from './ui/form/button.vue';
|
|||||||
import formRadio from './ui/form/radio.vue';
|
import formRadio from './ui/form/radio.vue';
|
||||||
|
|
||||||
Vue.component('mfm', misskeyFlavoredMarkdown);
|
Vue.component('mfm', misskeyFlavoredMarkdown);
|
||||||
|
Vue.component('mk-dummy', dummy);
|
||||||
Vue.component('mk-user-name', userName);
|
Vue.component('mk-user-name', userName);
|
||||||
Vue.component('mk-follow-button', followButton);
|
Vue.component('mk-follow-button', followButton);
|
||||||
Vue.component('mk-error', error);
|
Vue.component('mk-error', error);
|
||||||
@@ -77,6 +80,7 @@ Vue.component('mk-url-preview', urlPreview);
|
|||||||
Vue.component('mk-file-type-icon', fileTypeIcon);
|
Vue.component('mk-file-type-icon', fileTypeIcon);
|
||||||
Vue.component('mk-emoji', emoji);
|
Vue.component('mk-emoji', emoji);
|
||||||
Vue.component('mk-welcome-timeline', welcomeTimeline);
|
Vue.component('mk-welcome-timeline', welcomeTimeline);
|
||||||
|
Vue.component('mk-user-list', userList);
|
||||||
Vue.component('ui-input', uiInput);
|
Vue.component('ui-input', uiInput);
|
||||||
Vue.component('ui-button', uiButton);
|
Vue.component('ui-button', uiButton);
|
||||||
Vue.component('ui-horizon-group', uiHorizonGroup);
|
Vue.component('ui-horizon-group', uiHorizonGroup);
|
||||||
|
|||||||
@@ -10,7 +10,9 @@
|
|||||||
:style="style"
|
:style="style"
|
||||||
:title="image.name"
|
:title="image.name"
|
||||||
@click.prevent="onClick"
|
@click.prevent="onClick"
|
||||||
></a>
|
>
|
||||||
|
<div v-if="image.type === 'image/gif'">GIF</div>
|
||||||
|
</a>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
@@ -76,6 +78,20 @@ export default Vue.extend({
|
|||||||
background-size contain
|
background-size contain
|
||||||
background-repeat no-repeat
|
background-repeat no-repeat
|
||||||
|
|
||||||
|
> div
|
||||||
|
background-color var(--text)
|
||||||
|
border-radius var(--round)
|
||||||
|
color var(--secondary)
|
||||||
|
display inline-block
|
||||||
|
font-size 14px
|
||||||
|
font-weight bold
|
||||||
|
left 12px
|
||||||
|
opacity .5
|
||||||
|
padding 0 6px
|
||||||
|
text-align center
|
||||||
|
top 12px
|
||||||
|
pointer-events none
|
||||||
|
|
||||||
.qjewsnkgzzxlxtzncydssfbgjibiehcy
|
.qjewsnkgzzxlxtzncydssfbgjibiehcy
|
||||||
display flex
|
display flex
|
||||||
justify-content center
|
justify-content center
|
||||||
|
|||||||
161
src/client/app/common/views/components/user-list.vue
Normal file
161
src/client/app/common/views/components/user-list.vue
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
<template>
|
||||||
|
<ui-container :body-togglable="true">
|
||||||
|
<template slot="header"><slot></slot></template>
|
||||||
|
|
||||||
|
<mk-error v-if="!fetching && !inited" @retry="init()"/>
|
||||||
|
|
||||||
|
<div class="efvhhmdq" v-size="[{ lt: 500, class: 'narrow' }]">
|
||||||
|
<div class="user" v-for="user in us">
|
||||||
|
<mk-avatar class="avatar" :user="user"/>
|
||||||
|
<div class="body">
|
||||||
|
<div class="name">
|
||||||
|
<router-link class="name" :to="user | userPage" v-user-preview="user.id"><mk-user-name :user="user"/></router-link>
|
||||||
|
<p class="username">@{{ user | acct }}</p>
|
||||||
|
</div>
|
||||||
|
<div class="description" v-if="user.description" :title="user.description">
|
||||||
|
<mfm :text="user.description" :author="user" :i="$store.state.i" :custom-emojis="user.emojis" :should-break="false"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button class="more" :class="{ fetching: fetchingMoreUsers }" v-if="cursor != null" @click="fetchMoreUsers()" :disabled="fetchingMoreUsers">
|
||||||
|
<template v-if="fetchingMoreUsers"><fa icon="spinner" pulse fixed-width/></template>{{ fetchingMoreUsers ? $t('@.loading') : $t('@.load-more') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</ui-container>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import Vue from 'vue';
|
||||||
|
|
||||||
|
export default Vue.extend({
|
||||||
|
props: {
|
||||||
|
makePromise: {
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
iconOnly: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
fetching: true,
|
||||||
|
fetchingMoreUsers: false,
|
||||||
|
us: [],
|
||||||
|
inited: false,
|
||||||
|
cursor: null
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
created() {
|
||||||
|
this.init();
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
init() {
|
||||||
|
this.fetching = true;
|
||||||
|
this.makePromise().then(x => {
|
||||||
|
if (Array.isArray(x)) {
|
||||||
|
this.us = x;
|
||||||
|
} else {
|
||||||
|
this.us = x.users;
|
||||||
|
this.cursor = x.cursor;
|
||||||
|
}
|
||||||
|
this.inited = true;
|
||||||
|
this.fetching = false;
|
||||||
|
}, e => {
|
||||||
|
this.fetching = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
fetchMoreUsers() {
|
||||||
|
this.fetchingMoreUsers = true;
|
||||||
|
this.makePromise(this.cursor).then(x => {
|
||||||
|
this.us = this.us.concat(x.users);
|
||||||
|
this.cursor = x.cursor;
|
||||||
|
this.fetchingMoreUsers = false;
|
||||||
|
}, e => {
|
||||||
|
this.fetchingMoreUsers = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="stylus" scoped>
|
||||||
|
.efvhhmdq
|
||||||
|
&.narrow
|
||||||
|
> .user > .body > .name
|
||||||
|
width 100%
|
||||||
|
|
||||||
|
> .user > .body > .description
|
||||||
|
display none
|
||||||
|
|
||||||
|
> .user
|
||||||
|
display flex
|
||||||
|
padding 16px
|
||||||
|
border-bottom solid 1px var(--faceDivider)
|
||||||
|
|
||||||
|
&:last-child
|
||||||
|
border-bottom none
|
||||||
|
|
||||||
|
> .avatar
|
||||||
|
display block
|
||||||
|
flex-shrink 0
|
||||||
|
margin 0 12px 0 0
|
||||||
|
width 42px
|
||||||
|
height 42px
|
||||||
|
border-radius 8px
|
||||||
|
|
||||||
|
> .body
|
||||||
|
display flex
|
||||||
|
width calc(100% - 54px)
|
||||||
|
|
||||||
|
> .name
|
||||||
|
width 45%
|
||||||
|
|
||||||
|
> .name
|
||||||
|
margin 0
|
||||||
|
font-size 16px
|
||||||
|
line-height 24px
|
||||||
|
color var(--text)
|
||||||
|
|
||||||
|
> .username
|
||||||
|
display block
|
||||||
|
margin 0
|
||||||
|
font-size 15px
|
||||||
|
line-height 16px
|
||||||
|
color var(--text)
|
||||||
|
opacity 0.7
|
||||||
|
|
||||||
|
> .description
|
||||||
|
width 55%
|
||||||
|
color var(--text)
|
||||||
|
line-height 42px
|
||||||
|
white-space nowrap
|
||||||
|
overflow hidden
|
||||||
|
text-overflow ellipsis
|
||||||
|
opacity 0.7
|
||||||
|
font-size 14px
|
||||||
|
|
||||||
|
> .more
|
||||||
|
display block
|
||||||
|
width 100%
|
||||||
|
padding 16px
|
||||||
|
color var(--text)
|
||||||
|
border-top solid var(--lineWidth) rgba(#000, 0.05)
|
||||||
|
|
||||||
|
&:hover
|
||||||
|
background rgba(#000, 0.025)
|
||||||
|
|
||||||
|
&:active
|
||||||
|
background rgba(#000, 0.05)
|
||||||
|
|
||||||
|
&.fetching
|
||||||
|
cursor wait
|
||||||
|
|
||||||
|
> [data-icon]
|
||||||
|
margin-right 4px
|
||||||
|
|
||||||
|
</style>
|
||||||
@@ -76,6 +76,7 @@ export default Vue.extend({
|
|||||||
if (note.replyId != null) return;
|
if (note.replyId != null) return;
|
||||||
if (note.renoteId != null) return;
|
if (note.renoteId != null) return;
|
||||||
if (note.poll != null) return;
|
if (note.poll != null) return;
|
||||||
|
if (note.localOnly) return;
|
||||||
|
|
||||||
this.notes.unshift(note);
|
this.notes.unshift(note);
|
||||||
},
|
},
|
||||||
|
|||||||
50
src/client/app/common/views/pages/explore.vue
Normal file
50
src/client/app/common/views/pages/explore.vue
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<mk-user-list :make-promise="verifiedUsers">
|
||||||
|
<span><fa :icon="faBookmark"/> {{ $t('verified-users') }}</span>
|
||||||
|
</mk-user-list>
|
||||||
|
<mk-user-list :make-promise="popularUsers">
|
||||||
|
<span><fa :icon="faChartLine"/> {{ $t('popular-users') }}</span>
|
||||||
|
</mk-user-list>
|
||||||
|
<mk-user-list :make-promise="recentlyUpdatedUsers">
|
||||||
|
<span><fa :icon="faCommentAlt"/> {{ $t('recently-updated-users') }}</span>
|
||||||
|
</mk-user-list>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import Vue from 'vue';
|
||||||
|
import i18n from '../../../i18n';
|
||||||
|
import { faChartLine } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
import { faBookmark, faCommentAlt } from '@fortawesome/free-regular-svg-icons';
|
||||||
|
|
||||||
|
export default Vue.extend({
|
||||||
|
i18n: i18n('common/views/pages/explore.vue'),
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
verifiedUsers: () => this.$root.api('users', {
|
||||||
|
state: 'verified',
|
||||||
|
origin: 'local',
|
||||||
|
sort: '+follower',
|
||||||
|
limit: 10
|
||||||
|
}),
|
||||||
|
popularUsers: () => this.$root.api('users', {
|
||||||
|
state: 'alive',
|
||||||
|
origin: 'local',
|
||||||
|
sort: '+follower',
|
||||||
|
limit: 10
|
||||||
|
}),
|
||||||
|
recentlyUpdatedUsers: () => this.$root.api('users', {
|
||||||
|
origin: 'local',
|
||||||
|
sort: '+updatedAt',
|
||||||
|
limit: 10
|
||||||
|
}),
|
||||||
|
faBookmark, faChartLine, faCommentAlt
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="stylus" scoped>
|
||||||
|
</style>
|
||||||
30
src/client/app/common/views/pages/followers.vue
Normal file
30
src/client/app/common/views/pages/followers.vue
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<mk-user-list :make-promise="makePromise">{{ $t('@.followers') }}</mk-user-list>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import Vue from 'vue';
|
||||||
|
import parseAcct from '../../../../../misc/acct/parse';
|
||||||
|
import i18n from '../../../i18n';
|
||||||
|
|
||||||
|
export default Vue.extend({
|
||||||
|
i18n: i18n(''),
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
makePromise: cursor => this.$root.api('users/followers', {
|
||||||
|
...parseAcct(this.$route.params.user),
|
||||||
|
limit: 30,
|
||||||
|
cursor: cursor ? cursor : undefined
|
||||||
|
}).then(x => {
|
||||||
|
return {
|
||||||
|
users: x.users,
|
||||||
|
cursor: x.next
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
27
src/client/app/common/views/pages/following.vue
Normal file
27
src/client/app/common/views/pages/following.vue
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<mk-user-list :make-promise="makePromise">{{ $t('@.following') }}</mk-user-list>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import Vue from 'vue';
|
||||||
|
import parseAcct from '../../../../../misc/acct/parse';
|
||||||
|
|
||||||
|
export default Vue.extend({
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
makePromise: cursor => this.$root.api('users/following', {
|
||||||
|
...parseAcct(this.$route.params.user),
|
||||||
|
limit: 30,
|
||||||
|
cursor: cursor ? cursor : undefined
|
||||||
|
}).then(x => {
|
||||||
|
return {
|
||||||
|
users: x.users,
|
||||||
|
cursor: x.next
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="mkw-analog-clock">
|
<div class="mkw-analog-clock">
|
||||||
<mk-widget-container :naked="props.style % 2 === 0" :show-header="false">
|
<ui-container :naked="props.style % 2 === 0" :show-header="false">
|
||||||
<div class="mkw-analog-clock--body">
|
<div class="mkw-analog-clock--body">
|
||||||
<mk-analog-clock :dark="$store.state.device.darkmode" :smooth="props.style < 2"/>
|
<mk-analog-clock :dark="$store.state.device.darkmode" :smooth="props.style < 2"/>
|
||||||
</div>
|
</div>
|
||||||
</mk-widget-container>
|
</ui-container>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="anltbovirfeutcigvwgmgxipejaeozxi">
|
<div class="anltbovirfeutcigvwgmgxipejaeozxi">
|
||||||
<mk-widget-container :show-header="false" :naked="props.design == 1">
|
<ui-container :show-header="false" :naked="props.design == 1">
|
||||||
<div class="anltbovirfeutcigvwgmgxipejaeozxi-body"
|
<div class="anltbovirfeutcigvwgmgxipejaeozxi-body"
|
||||||
:data-found="announcements && announcements.length != 0"
|
:data-found="announcements && announcements.length != 0"
|
||||||
:data-melt="props.design == 1"
|
:data-melt="props.design == 1"
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
</p>
|
</p>
|
||||||
<a v-if="announcements.length > 1" @click="next">{{ $t('next') }} >></a>
|
<a v-if="announcements.length > 1" @click="next">{{ $t('next') }} >></a>
|
||||||
</div>
|
</div>
|
||||||
</mk-widget-container>
|
</ui-container>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="mkw-calendar" :data-special="special" :data-mobile="platform == 'mobile'">
|
<div class="mkw-calendar" :data-special="special" :data-mobile="platform == 'mobile'">
|
||||||
<mk-widget-container :naked="props.design == 1" :show-header="false">
|
<ui-container :naked="props.design == 1" :show-header="false">
|
||||||
<div class="mkw-calendar--body">
|
<div class="mkw-calendar--body">
|
||||||
<div class="calendar" :data-is-holiday="isHoliday">
|
<div class="calendar" :data-is-holiday="isHoliday">
|
||||||
<p class="month-and-year">
|
<p class="month-and-year">
|
||||||
@@ -31,7 +31,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</mk-widget-container>
|
</ui-container>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="mkw-hashtags">
|
<div class="mkw-hashtags">
|
||||||
<mk-widget-container :show-header="!props.compact">
|
<ui-container :show-header="!props.compact">
|
||||||
<template slot="header"><fa icon="hashtag"/>{{ $t('title') }}</template>
|
<template slot="header"><fa icon="hashtag"/>{{ $t('title') }}</template>
|
||||||
|
|
||||||
<div class="mkw-hashtags--body" :data-mobile="platform == 'mobile'">
|
<div class="mkw-hashtags--body" :data-mobile="platform == 'mobile'">
|
||||||
<mk-trends/>
|
<mk-trends/>
|
||||||
</div>
|
</div>
|
||||||
</mk-widget-container>
|
</ui-container>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import wSlideshow from './slideshow.vue';
|
|||||||
import wTips from './tips.vue';
|
import wTips from './tips.vue';
|
||||||
import wNav from './nav.vue';
|
import wNav from './nav.vue';
|
||||||
import wHashtags from './hashtags.vue';
|
import wHashtags from './hashtags.vue';
|
||||||
|
import wInstance from './instance.vue';
|
||||||
|
|
||||||
Vue.component('mkw-analog-clock', wAnalogClock);
|
Vue.component('mkw-analog-clock', wAnalogClock);
|
||||||
Vue.component('mkw-nav', wNav);
|
Vue.component('mkw-nav', wNav);
|
||||||
@@ -27,3 +28,4 @@ Vue.component('mkw-memo', wMemo);
|
|||||||
Vue.component('mkw-rss', wRss);
|
Vue.component('mkw-rss', wRss);
|
||||||
Vue.component('mkw-version', wVersion);
|
Vue.component('mkw-version', wVersion);
|
||||||
Vue.component('mkw-hashtags', wHashtags);
|
Vue.component('mkw-hashtags', wHashtags);
|
||||||
|
Vue.component('mkw-instance', wInstance);
|
||||||
|
|||||||
14
src/client/app/common/views/widgets/instance.vue
Normal file
14
src/client/app/common/views/widgets/instance.vue
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<template>
|
||||||
|
<div class="mkw-instance">
|
||||||
|
<ui-container>
|
||||||
|
<mk-instance/>
|
||||||
|
</ui-container>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import define from '../../../common/define-widget';
|
||||||
|
export default define({
|
||||||
|
name: 'instance'
|
||||||
|
});
|
||||||
|
</script>
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="mkw-memo">
|
<div class="mkw-memo">
|
||||||
<mk-widget-container :show-header="!props.compact">
|
<ui-container :show-header="!props.compact">
|
||||||
<template slot="header"><fa :icon="['far', 'sticky-note']"/>{{ $t('title') }}</template>
|
<template slot="header"><fa :icon="['far', 'sticky-note']"/>{{ $t('title') }}</template>
|
||||||
|
|
||||||
<div class="mkw-memo--body">
|
<div class="mkw-memo--body">
|
||||||
<textarea v-model="text" :placeholder="$t('placeholder')" @input="onChange"></textarea>
|
<textarea v-model="text" :placeholder="$t('placeholder')" @input="onChange"></textarea>
|
||||||
<button @click="saveMemo" :disabled="!changed">{{ $t('save') }}</button>
|
<button @click="saveMemo" :disabled="!changed">{{ $t('save') }}</button>
|
||||||
</div>
|
</div>
|
||||||
</mk-widget-container>
|
</ui-container>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="mkw-nav">
|
<div class="mkw-nav">
|
||||||
<mk-widget-container>
|
<ui-container>
|
||||||
<div class="mkw-nav--body">
|
<div class="mkw-nav--body">
|
||||||
<mk-nav/>
|
<mk-nav/>
|
||||||
</div>
|
</div>
|
||||||
</mk-widget-container>
|
</ui-container>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="mkw-photo-stream" :class="$style.root" :data-melt="props.design == 2">
|
<div class="mkw-photo-stream" :class="$style.root" :data-melt="props.design == 2">
|
||||||
<mk-widget-container :show-header="props.design == 0" :naked="props.design == 2">
|
<ui-container :show-header="props.design == 0" :naked="props.design == 2">
|
||||||
<template slot="header"><fa icon="camera"/>{{ $t('title') }}</template>
|
<template slot="header"><fa icon="camera"/>{{ $t('title') }}</template>
|
||||||
|
|
||||||
<p :class="$style.fetching" v-if="fetching"><fa icon="spinner" pulse fixed-width/>{{ $t('@.loading') }}<mk-ellipsis/></p>
|
<p :class="$style.fetching" v-if="fetching"><fa icon="spinner" pulse fixed-width/>{{ $t('@.loading') }}<mk-ellipsis/></p>
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
></div>
|
></div>
|
||||||
</div>
|
</div>
|
||||||
<p :class="$style.empty" v-if="!fetching && images.length == 0">{{ $t('no-photos') }}</p>
|
<p :class="$style.empty" v-if="!fetching && images.length == 0">{{ $t('no-photos') }}</p>
|
||||||
</mk-widget-container>
|
</ui-container>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="mkw-posts-monitor">
|
<div class="mkw-posts-monitor">
|
||||||
<mk-widget-container :show-header="props.design == 0" :naked="props.design == 2">
|
<ui-container :show-header="props.design == 0" :naked="props.design == 2">
|
||||||
<template slot="header"><fa icon="chart-line"/>{{ $t('title') }}</template>
|
<template slot="header"><fa icon="chart-line"/>{{ $t('title') }}</template>
|
||||||
<button slot="func" @click="toggle" :title="$t('toggle')"><fa icon="sort"/></button>
|
<button slot="func" @click="toggle" :title="$t('toggle')"><fa icon="sort"/></button>
|
||||||
|
|
||||||
@@ -64,7 +64,7 @@
|
|||||||
<text x="1" y="5">Fedi</text>
|
<text x="1" y="5">Fedi</text>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
</mk-widget-container>
|
</ui-container>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="mkw-rss">
|
<div class="mkw-rss">
|
||||||
<mk-widget-container :show-header="!props.compact">
|
<ui-container :show-header="!props.compact">
|
||||||
<template slot="header"><fa icon="rss-square"/>RSS</template>
|
<template slot="header"><fa icon="rss-square"/>RSS</template>
|
||||||
<button slot="func" title="設定" @click="setting"><fa icon="cog"/></button>
|
<button slot="func" title="設定" @click="setting"><fa icon="cog"/></button>
|
||||||
|
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
<a v-for="item in items" :href="item.link" target="_blank">{{ item.title }}</a>
|
<a v-for="item in items" :href="item.link" target="_blank">{{ item.title }}</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</mk-widget-container>
|
</ui-container>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="mkw-server">
|
<div class="mkw-server">
|
||||||
<mk-widget-container :show-header="props.design == 0" :naked="props.design == 2">
|
<ui-container :show-header="props.design == 0" :naked="props.design == 2">
|
||||||
<template slot="header"><fa icon="server"/>{{ $t('title') }}</template>
|
<template slot="header"><fa icon="server"/>{{ $t('title') }}</template>
|
||||||
<button slot="func" @click="toggle" :title="$t('toggle')"><fa icon="sort"/></button>
|
<button slot="func" @click="toggle" :title="$t('toggle')"><fa icon="sort"/></button>
|
||||||
|
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
<x-uptimes v-show="props.view == 4" :connection="connection"/>
|
<x-uptimes v-show="props.view == 4" :connection="connection"/>
|
||||||
<x-info v-show="props.view == 5" :connection="connection" :meta="meta"/>
|
<x-info v-show="props.view == 5" :connection="connection" :meta="meta"/>
|
||||||
</template>
|
</template>
|
||||||
</mk-widget-container>
|
</ui-container>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -12,19 +12,12 @@ import init from '../init';
|
|||||||
import fuckAdBlock from '../common/scripts/fuck-ad-block';
|
import fuckAdBlock from '../common/scripts/fuck-ad-block';
|
||||||
import composeNotification from '../common/scripts/compose-notification';
|
import composeNotification from '../common/scripts/compose-notification';
|
||||||
|
|
||||||
import MkIndex from './views/pages/index.vue';
|
import MkHome from './views/home/home.vue';
|
||||||
import MkHome from './views/pages/home.vue';
|
import MkDeck from './views/deck/deck.vue';
|
||||||
import MkDeck from './views/pages/deck/deck.vue';
|
|
||||||
import MkUser from './views/pages/user/user.vue';
|
|
||||||
import MkUserFollowingOrFollowers from './views/pages/user-following-or-followers.vue';
|
import MkUserFollowingOrFollowers from './views/pages/user-following-or-followers.vue';
|
||||||
import MkFavorites from './views/pages/favorites.vue';
|
|
||||||
import MkSelectDrive from './views/pages/selectdrive.vue';
|
import MkSelectDrive from './views/pages/selectdrive.vue';
|
||||||
import MkDrive from './views/pages/drive.vue';
|
import MkDrive from './views/pages/drive.vue';
|
||||||
import MkHomeCustomize from './views/pages/home-customize.vue';
|
|
||||||
import MkMessagingRoom from './views/pages/messaging-room.vue';
|
import MkMessagingRoom from './views/pages/messaging-room.vue';
|
||||||
import MkNote from './views/pages/note.vue';
|
|
||||||
import MkSearch from './views/pages/search.vue';
|
|
||||||
import MkTag from './views/pages/tag.vue';
|
|
||||||
import MkReversi from './views/pages/games/reversi.vue';
|
import MkReversi from './views/pages/games/reversi.vue';
|
||||||
import MkShare from './views/pages/share.vue';
|
import MkShare from './views/pages/share.vue';
|
||||||
import MkFollow from '../common/views/pages/follow.vue';
|
import MkFollow from '../common/views/pages/follow.vue';
|
||||||
@@ -36,6 +29,7 @@ import PostFormWindow from './views/components/post-form-window.vue';
|
|||||||
import RenoteFormWindow from './views/components/renote-form-window.vue';
|
import RenoteFormWindow from './views/components/renote-form-window.vue';
|
||||||
import MkChooseFileFromDriveWindow from './views/components/choose-file-from-drive-window.vue';
|
import MkChooseFileFromDriveWindow from './views/components/choose-file-from-drive-window.vue';
|
||||||
import MkChooseFolderFromDriveWindow from './views/components/choose-folder-from-drive-window.vue';
|
import MkChooseFolderFromDriveWindow from './views/components/choose-folder-from-drive-window.vue';
|
||||||
|
import MkHomeTimeline from './views/home/timeline.vue';
|
||||||
import Notification from './views/components/ui-notification.vue';
|
import Notification from './views/components/ui-notification.vue';
|
||||||
|
|
||||||
import { url } from '../config';
|
import { url } from '../config';
|
||||||
@@ -44,7 +38,7 @@ import MiOS from '../mios';
|
|||||||
/**
|
/**
|
||||||
* init
|
* init
|
||||||
*/
|
*/
|
||||||
init(async (launch) => {
|
init(async (launch, os) => {
|
||||||
Vue.mixin({
|
Vue.mixin({
|
||||||
methods: {
|
methods: {
|
||||||
$contextmenu(e, menu, opts?) {
|
$contextmenu(e, menu, opts?) {
|
||||||
@@ -134,31 +128,52 @@ init(async (launch) => {
|
|||||||
const router = new VueRouter({
|
const router = new VueRouter({
|
||||||
mode: 'history',
|
mode: 'history',
|
||||||
routes: [
|
routes: [
|
||||||
{ path: '/', name: 'index', component: MkIndex },
|
os.store.getters.isSignedIn && os.store.state.device.deckMode
|
||||||
{ path: '/home', name: 'home', component: MkHome },
|
? { path: '/', name: 'index', component: MkDeck, children: [
|
||||||
{ path: '/deck', name: 'deck', component: MkDeck },
|
{ path: '/@:user', name: 'user', component: () => import('./views/deck/deck.user-column.vue').then(m => m.default), children: [
|
||||||
{ path: '/i/customize-home', component: MkHomeCustomize },
|
{ path: '', name: 'user', component: () => import('./views/deck/deck.user-column.home.vue').then(m => m.default) },
|
||||||
{ path: '/i/favorites', component: MkFavorites },
|
{ path: 'following', component: () => import('../common/views/pages/following.vue').then(m => m.default) },
|
||||||
|
{ path: 'followers', component: () => import('../common/views/pages/followers.vue').then(m => m.default) },
|
||||||
|
]},
|
||||||
|
{ path: '/notes/:note', name: 'note', component: () => import('./views/deck/deck.note-column.vue').then(m => m.default) },
|
||||||
|
{ path: '/search', component: () => import('./views/deck/deck.search-column.vue').then(m => m.default) },
|
||||||
|
{ path: '/tags/:tag', name: 'tag', component: () => import('./views/deck/deck.hashtag-column.vue').then(m => m.default) },
|
||||||
|
{ path: '/featured', component: () => import('./views/deck/deck.featured-column.vue').then(m => m.default) },
|
||||||
|
{ path: '/explore', component: () => import('./views/deck/deck.explore-column.vue').then(m => m.default) },
|
||||||
|
{ path: '/i/favorites', component: () => import('./views/deck/deck.favorites-column.vue').then(m => m.default) }
|
||||||
|
]}
|
||||||
|
: { path: '/', component: MkHome, children: [
|
||||||
|
{ path: '', name: 'index', component: MkHomeTimeline },
|
||||||
|
{ path: '/@:user', component: () => import('./views/home/user/index.vue').then(m => m.default), children: [
|
||||||
|
{ path: '', name: 'user', component: () => import('./views/home/user/user.home.vue').then(m => m.default) },
|
||||||
|
{ path: 'following', component: () => import('../common/views/pages/following.vue').then(m => m.default) },
|
||||||
|
{ path: 'followers', component: () => import('../common/views/pages/followers.vue').then(m => m.default) },
|
||||||
|
]},
|
||||||
|
{ path: '/notes/:note', name: 'note', component: () => import('./views/home/note.vue').then(m => m.default) },
|
||||||
|
{ path: '/search', component: () => import('./views/home/search.vue').then(m => m.default) },
|
||||||
|
{ path: '/tags/:tag', name: 'tag', component: () => import('./views/home/tag.vue').then(m => m.default) },
|
||||||
|
{ path: '/featured', component: () => import('./views/home/featured.vue').then(m => m.default) },
|
||||||
|
{ path: '/explore', component: () => import('../common/views/pages/explore.vue').then(m => m.default) },
|
||||||
|
{ path: '/i/favorites', component: () => import('./views/home/favorites.vue').then(m => m.default) },
|
||||||
|
]},
|
||||||
{ path: '/i/messaging/:user', component: MkMessagingRoom },
|
{ path: '/i/messaging/:user', component: MkMessagingRoom },
|
||||||
{ path: '/i/drive', component: MkDrive },
|
{ path: '/i/drive', component: MkDrive },
|
||||||
{ path: '/i/drive/folder/:folder', component: MkDrive },
|
{ path: '/i/drive/folder/:folder', component: MkDrive },
|
||||||
{ path: '/i/settings', component: MkSettings },
|
{ path: '/i/settings', component: MkSettings },
|
||||||
{ path: '/selectdrive', component: MkSelectDrive },
|
{ path: '/selectdrive', component: MkSelectDrive },
|
||||||
{ path: '/search', component: MkSearch },
|
|
||||||
{ path: '/tags/:tag', name: 'tag', component: MkTag },
|
|
||||||
{ path: '/share', component: MkShare },
|
{ path: '/share', component: MkShare },
|
||||||
{ path: '/games/reversi/:game?', component: MkReversi },
|
{ path: '/games/reversi/:game?', component: MkReversi },
|
||||||
{ path: '/@:user', name: 'user', component: MkUser },
|
|
||||||
{ path: '/@:user/following', name: 'userFollowing', component: MkUserFollowingOrFollowers },
|
|
||||||
{ path: '/@:user/followers', name: 'userFollowers', component: MkUserFollowingOrFollowers },
|
|
||||||
{ path: '/notes/:note', name: 'note', component: MkNote },
|
|
||||||
{ path: '/authorize-follow', component: MkFollow },
|
{ path: '/authorize-follow', component: MkFollow },
|
||||||
|
{ path: '/deck', redirect: '/' },
|
||||||
{ path: '*', component: MkNotFound }
|
{ path: '*', component: MkNotFound }
|
||||||
]
|
],
|
||||||
|
scrollBehavior(to, from, savedPosition) {
|
||||||
|
return { x: 0, y: 0 };
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Launch the app
|
// Launch the app
|
||||||
const [app, os] = launch(router);
|
const [app, _] = launch(router);
|
||||||
|
|
||||||
if (os.store.getters.isSignedIn) {
|
if (os.store.getters.isSignedIn) {
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="mk-activity">
|
<div class="mk-activity">
|
||||||
<mk-widget-container :show-header="design == 0" :naked="design == 2">
|
<ui-container :show-header="design == 0" :naked="design == 2">
|
||||||
<template slot="header"><fa icon="chart-bar"/>{{ $t('title') }}</template>
|
<template slot="header"><fa icon="chart-bar"/>{{ $t('title') }}</template>
|
||||||
<button slot="func" :title="$t('toggle')" @click="toggle"><fa icon="sort"/></button>
|
<button slot="func" :title="$t('toggle')" @click="toggle"><fa icon="sort"/></button>
|
||||||
|
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
<x-calendar v-show="view == 0" :data="[].concat(activity)"/>
|
<x-calendar v-show="view == 0" :data="[].concat(activity)"/>
|
||||||
<x-chart v-show="view == 1" :data="[].concat(activity)"/>
|
<x-chart v-show="view == 1" :data="[].concat(activity)"/>
|
||||||
</template>
|
</template>
|
||||||
</mk-widget-container>
|
</ui-container>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -160,6 +160,7 @@ export default Vue.extend({
|
|||||||
color #222
|
color #222
|
||||||
|
|
||||||
> [data-icon]
|
> [data-icon]
|
||||||
|
box-sizing initial
|
||||||
padding 14px
|
padding 14px
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,396 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="mk-home" :data-customize="customize">
|
|
||||||
<div class="customize" v-if="customize">
|
|
||||||
<router-link to="/"><fa icon="check"/>{{ $t('done') }}</router-link>
|
|
||||||
<div>
|
|
||||||
<div class="adder">
|
|
||||||
<p>{{ $t('add-widget') }}</p>
|
|
||||||
<select v-model="widgetAdderSelected">
|
|
||||||
<option value="profile">{{ $t('@.widgets.profile') }}</option>
|
|
||||||
<option value="analog-clock">{{ $t('@.widgets.analog-clock') }}</option>
|
|
||||||
<option value="calendar">{{ $t('@.widgets.calendar') }}</option>
|
|
||||||
<option value="timemachine">{{ $t('@.widgets.timemachine') }}</option>
|
|
||||||
<option value="activity">{{ $t('@.widgets.activity') }}</option>
|
|
||||||
<option value="rss">{{ $t('@.widgets.rss') }}</option>
|
|
||||||
<option value="trends">{{ $t('@.widgets.trends') }}</option>
|
|
||||||
<option value="photo-stream">{{ $t('@.widgets.photo-stream') }}</option>
|
|
||||||
<option value="slideshow">{{ $t('@.widgets.slideshow') }}</option>
|
|
||||||
<option value="version">{{ $t('@.widgets.version') }}</option>
|
|
||||||
<option value="broadcast">{{ $t('@.widgets.broadcast') }}</option>
|
|
||||||
<option value="notifications">{{ $t('@.widgets.notifications') }}</option>
|
|
||||||
<option value="users">{{ $t('@.widgets.users') }}</option>
|
|
||||||
<option value="polls">{{ $t('@.widgets.polls') }}</option>
|
|
||||||
<option value="post-form">{{ $t('@.widgets.post-form') }}</option>
|
|
||||||
<option value="messaging">{{ $t('@.widgets.messaging') }}</option>
|
|
||||||
<option value="memo">{{ $t('@.widgets.memo') }}</option>
|
|
||||||
<option value="hashtags">{{ $t('@.widgets.hashtags') }}</option>
|
|
||||||
<option value="posts-monitor">{{ $t('@.widgets.posts-monitor') }}</option>
|
|
||||||
<option value="server">{{ $t('@.widgets.server') }}</option>
|
|
||||||
<option value="nav">{{ $t('@.widgets.nav') }}</option>
|
|
||||||
<option value="tips">{{ $t('@.widgets.tips') }}</option>
|
|
||||||
</select>
|
|
||||||
<button @click="addWidget">{{ $t('add') }}</button>
|
|
||||||
</div>
|
|
||||||
<div class="trash">
|
|
||||||
<x-draggable v-model="trash" :options="{ group: 'x' }" @add="onTrash"></x-draggable>
|
|
||||||
<p>{{ $t('@.trash') }}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="main" :class="{ side: widgets.left.length == 0 || widgets.right.length == 0 }">
|
|
||||||
<template v-if="customize">
|
|
||||||
<x-draggable v-for="place in ['left', 'right']"
|
|
||||||
:list="widgets[place]"
|
|
||||||
:class="place"
|
|
||||||
:data-place="place"
|
|
||||||
:options="{ group: 'x', animation: 150 }"
|
|
||||||
@sort="onWidgetSort"
|
|
||||||
:key="place"
|
|
||||||
>
|
|
||||||
<div v-for="widget in widgets[place]" class="customize-container" :key="widget.id" @contextmenu.stop.prevent="onWidgetContextmenu(widget.id)">
|
|
||||||
<component :is="`mkw-${widget.name}`" :widget="widget" :ref="widget.id" :is-customize-mode="true" platform="desktop"/>
|
|
||||||
</div>
|
|
||||||
</x-draggable>
|
|
||||||
<div class="main">
|
|
||||||
<a @click="hint">{{ $t('@.customization-tips.title') }}</a>
|
|
||||||
<div>
|
|
||||||
<mk-post-form v-if="$store.state.settings.showPostFormOnTopOfTl"/>
|
|
||||||
<mk-timeline ref="tl" @loaded="onTlLoaded"/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<template v-else>
|
|
||||||
<div v-for="place in ['left', 'right']" :class="place">
|
|
||||||
<component v-for="widget in widgets[place]" :is="`mkw-${widget.name}`" :key="widget.id" :ref="widget.id" :widget="widget" @chosen="warp" platform="desktop"/>
|
|
||||||
</div>
|
|
||||||
<div class="main">
|
|
||||||
<mk-post-form class="form" v-if="$store.state.settings.showPostFormOnTopOfTl"/>
|
|
||||||
<mk-timeline class="tl" ref="tl" @loaded="onTlLoaded" v-if="mode == 'timeline'"/>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import Vue from 'vue';
|
|
||||||
import i18n from '../../../i18n';
|
|
||||||
import * as XDraggable from 'vuedraggable';
|
|
||||||
import * as uuid from 'uuid';
|
|
||||||
|
|
||||||
const defaultDesktopHomeWidgets = {
|
|
||||||
left: [
|
|
||||||
'profile',
|
|
||||||
'calendar',
|
|
||||||
'activity',
|
|
||||||
'rss',
|
|
||||||
'hashtags',
|
|
||||||
'photo-stream',
|
|
||||||
'version'
|
|
||||||
],
|
|
||||||
right: [
|
|
||||||
'broadcast',
|
|
||||||
'notifications',
|
|
||||||
'users',
|
|
||||||
'polls',
|
|
||||||
'server',
|
|
||||||
'nav',
|
|
||||||
'tips'
|
|
||||||
]
|
|
||||||
};
|
|
||||||
|
|
||||||
//#region Construct home data
|
|
||||||
const _defaultDesktopHomeWidgets = [];
|
|
||||||
|
|
||||||
for (const widget of defaultDesktopHomeWidgets.left) {
|
|
||||||
_defaultDesktopHomeWidgets.push({
|
|
||||||
name: widget,
|
|
||||||
id: uuid(),
|
|
||||||
place: 'left',
|
|
||||||
data: {}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const widget of defaultDesktopHomeWidgets.right) {
|
|
||||||
_defaultDesktopHomeWidgets.push({
|
|
||||||
name: widget,
|
|
||||||
id: uuid(),
|
|
||||||
place: 'right',
|
|
||||||
data: {}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
//#endregion
|
|
||||||
|
|
||||||
export default Vue.extend({
|
|
||||||
i18n: i18n('desktop/views/components/home.vue'),
|
|
||||||
components: {
|
|
||||||
XDraggable
|
|
||||||
},
|
|
||||||
|
|
||||||
props: {
|
|
||||||
customize: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
mode: {
|
|
||||||
type: String,
|
|
||||||
default: 'timeline'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
connection: null,
|
|
||||||
widgetAdderSelected: null,
|
|
||||||
trash: []
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
computed: {
|
|
||||||
home(): any[] {
|
|
||||||
return this.$store.state.settings.home || [];
|
|
||||||
},
|
|
||||||
left(): any[] {
|
|
||||||
return this.home.filter(w => w.place == 'left');
|
|
||||||
},
|
|
||||||
right(): any[] {
|
|
||||||
return this.home.filter(w => w.place == 'right');
|
|
||||||
},
|
|
||||||
widgets(): any {
|
|
||||||
return {
|
|
||||||
left: this.left,
|
|
||||||
right: this.right
|
|
||||||
};
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
created() {
|
|
||||||
if (this.$store.state.settings.home == null) {
|
|
||||||
this.$root.api('i/update_home', {
|
|
||||||
home: _defaultDesktopHomeWidgets
|
|
||||||
}).then(() => {
|
|
||||||
this.$store.commit('settings/setHome', _defaultDesktopHomeWidgets);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
mounted() {
|
|
||||||
this.connection = this.$root.stream.useSharedConnection('main');
|
|
||||||
},
|
|
||||||
|
|
||||||
beforeDestroy() {
|
|
||||||
this.connection.dispose();
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
|
||||||
hint() {
|
|
||||||
this.$root.dialog({
|
|
||||||
title: this.$t('@.customization-tips.title'),
|
|
||||||
text: this.$t('@.customization-tips.paragraph')
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
onTlLoaded() {
|
|
||||||
this.$emit('loaded');
|
|
||||||
},
|
|
||||||
|
|
||||||
onWidgetContextmenu(widgetId) {
|
|
||||||
const w = (this.$refs[widgetId] as any)[0];
|
|
||||||
if (w.func) w.func();
|
|
||||||
},
|
|
||||||
|
|
||||||
onWidgetSort() {
|
|
||||||
this.saveHome();
|
|
||||||
},
|
|
||||||
|
|
||||||
onTrash(evt) {
|
|
||||||
this.saveHome();
|
|
||||||
},
|
|
||||||
|
|
||||||
addWidget() {
|
|
||||||
this.$store.dispatch('settings/addHomeWidget', {
|
|
||||||
name: this.widgetAdderSelected,
|
|
||||||
id: uuid(),
|
|
||||||
place: 'left',
|
|
||||||
data: {}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
saveHome() {
|
|
||||||
const left = this.widgets.left;
|
|
||||||
const right = this.widgets.right;
|
|
||||||
this.$store.commit('settings/setHome', left.concat(right));
|
|
||||||
for (const w of left) w.place = 'left';
|
|
||||||
for (const w of right) w.place = 'right';
|
|
||||||
this.$root.api('i/update_home', {
|
|
||||||
home: this.home
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
warp(date) {
|
|
||||||
(this.$refs.tl as any).warp(date);
|
|
||||||
},
|
|
||||||
|
|
||||||
focus() {
|
|
||||||
(this.$refs.tl as any).focus();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="stylus" scoped>
|
|
||||||
.mk-home
|
|
||||||
display block
|
|
||||||
|
|
||||||
&[data-customize]
|
|
||||||
padding-top 48px
|
|
||||||
background-image url('/assets/desktop/grid.svg')
|
|
||||||
|
|
||||||
> .main > .main
|
|
||||||
> a
|
|
||||||
display block
|
|
||||||
margin-bottom 8px
|
|
||||||
text-align center
|
|
||||||
|
|
||||||
> div
|
|
||||||
cursor not-allowed !important
|
|
||||||
|
|
||||||
> *
|
|
||||||
pointer-events none
|
|
||||||
|
|
||||||
&:not([data-customize])
|
|
||||||
> .main > *:empty
|
|
||||||
display none
|
|
||||||
|
|
||||||
> .customize
|
|
||||||
position fixed
|
|
||||||
z-index 1000
|
|
||||||
top 0
|
|
||||||
left 0
|
|
||||||
width 100%
|
|
||||||
height 48px
|
|
||||||
color var(--text)
|
|
||||||
background var(--desktopHeaderBg)
|
|
||||||
box-shadow 0 1px 1px rgba(#000, 0.075)
|
|
||||||
|
|
||||||
> a
|
|
||||||
display block
|
|
||||||
position absolute
|
|
||||||
z-index 1001
|
|
||||||
top 0
|
|
||||||
right 0
|
|
||||||
padding 0 16px
|
|
||||||
line-height 48px
|
|
||||||
text-decoration none
|
|
||||||
color var(--primaryForeground)
|
|
||||||
background var(--primary)
|
|
||||||
transition background 0.1s ease
|
|
||||||
|
|
||||||
&:hover
|
|
||||||
background var(--primaryLighten10)
|
|
||||||
|
|
||||||
&:active
|
|
||||||
background var(--primaryDarken10)
|
|
||||||
transition background 0s ease
|
|
||||||
|
|
||||||
> [data-icon]
|
|
||||||
margin-right 8px
|
|
||||||
|
|
||||||
> div
|
|
||||||
display flex
|
|
||||||
margin 0 auto
|
|
||||||
max-width 1220px - 32px
|
|
||||||
|
|
||||||
> div
|
|
||||||
width 50%
|
|
||||||
|
|
||||||
&.adder
|
|
||||||
> p
|
|
||||||
display inline
|
|
||||||
line-height 48px
|
|
||||||
|
|
||||||
&.trash
|
|
||||||
border-left solid 1px var(--faceDivider)
|
|
||||||
|
|
||||||
> div
|
|
||||||
width 100%
|
|
||||||
height 100%
|
|
||||||
|
|
||||||
> p
|
|
||||||
position absolute
|
|
||||||
top 0
|
|
||||||
left 0
|
|
||||||
width 100%
|
|
||||||
line-height 48px
|
|
||||||
margin 0
|
|
||||||
text-align center
|
|
||||||
pointer-events none
|
|
||||||
|
|
||||||
> .main
|
|
||||||
display flex
|
|
||||||
justify-content center
|
|
||||||
margin 0 auto
|
|
||||||
max-width 1240px
|
|
||||||
|
|
||||||
> *
|
|
||||||
.customize-container
|
|
||||||
cursor move
|
|
||||||
border-radius 6px
|
|
||||||
|
|
||||||
&:hover
|
|
||||||
box-shadow 0 0 8px rgba(64, 120, 200, 0.3)
|
|
||||||
|
|
||||||
> *
|
|
||||||
pointer-events none
|
|
||||||
|
|
||||||
> .main
|
|
||||||
padding 16px
|
|
||||||
width calc(100% - 280px * 2)
|
|
||||||
order 2
|
|
||||||
|
|
||||||
> .form
|
|
||||||
margin-bottom 16px
|
|
||||||
box-shadow var(--shadow)
|
|
||||||
border-radius var(--round)
|
|
||||||
|
|
||||||
&.side
|
|
||||||
> .main
|
|
||||||
width calc(100% - 280px)
|
|
||||||
max-width 680px
|
|
||||||
|
|
||||||
> *:not(.main)
|
|
||||||
width 280px
|
|
||||||
padding 16px 0 16px 0
|
|
||||||
|
|
||||||
> *:not(:last-child)
|
|
||||||
margin-bottom 16px
|
|
||||||
|
|
||||||
> .left
|
|
||||||
padding-left 16px
|
|
||||||
order 1
|
|
||||||
|
|
||||||
> .right
|
|
||||||
padding-right 16px
|
|
||||||
order 3
|
|
||||||
|
|
||||||
&.side
|
|
||||||
@media (max-width 1000px)
|
|
||||||
> *:not(.main)
|
|
||||||
display none
|
|
||||||
|
|
||||||
> .main
|
|
||||||
width 100%
|
|
||||||
max-width 700px
|
|
||||||
margin 0 auto
|
|
||||||
|
|
||||||
&:not(.side)
|
|
||||||
@media (max-width 1200px)
|
|
||||||
> *:not(.main)
|
|
||||||
display none
|
|
||||||
|
|
||||||
> .main
|
|
||||||
width 100%
|
|
||||||
max-width 700px
|
|
||||||
margin 0 auto
|
|
||||||
|
|
||||||
</style>
|
|
||||||
@@ -2,8 +2,6 @@ import Vue from 'vue';
|
|||||||
|
|
||||||
import ui from './ui.vue';
|
import ui from './ui.vue';
|
||||||
import uiNotification from './ui-notification.vue';
|
import uiNotification from './ui-notification.vue';
|
||||||
import home from './home.vue';
|
|
||||||
import timeline from './timeline.vue';
|
|
||||||
import notes from './notes.vue';
|
import notes from './notes.vue';
|
||||||
import subNoteContent from './sub-note-content.vue';
|
import subNoteContent from './sub-note-content.vue';
|
||||||
import window from './window.vue';
|
import window from './window.vue';
|
||||||
@@ -20,12 +18,10 @@ import activity from './activity.vue';
|
|||||||
import friendsMaker from './friends-maker.vue';
|
import friendsMaker from './friends-maker.vue';
|
||||||
import userCard from './user-card.vue';
|
import userCard from './user-card.vue';
|
||||||
import userListTimeline from './user-list-timeline.vue';
|
import userListTimeline from './user-list-timeline.vue';
|
||||||
import widgetContainer from './widget-container.vue';
|
import uiContainer from './ui-container.vue';
|
||||||
|
|
||||||
Vue.component('mk-ui', ui);
|
Vue.component('mk-ui', ui);
|
||||||
Vue.component('mk-ui-notification', uiNotification);
|
Vue.component('mk-ui-notification', uiNotification);
|
||||||
Vue.component('mk-home', home);
|
|
||||||
Vue.component('mk-timeline', timeline);
|
|
||||||
Vue.component('mk-notes', notes);
|
Vue.component('mk-notes', notes);
|
||||||
Vue.component('mk-sub-note-content', subNoteContent);
|
Vue.component('mk-sub-note-content', subNoteContent);
|
||||||
Vue.component('mk-window', window);
|
Vue.component('mk-window', window);
|
||||||
@@ -42,4 +38,4 @@ Vue.component('mk-activity', activity);
|
|||||||
Vue.component('mk-friends-maker', friendsMaker);
|
Vue.component('mk-friends-maker', friendsMaker);
|
||||||
Vue.component('mk-user-card', userCard);
|
Vue.component('mk-user-card', userCard);
|
||||||
Vue.component('mk-user-list-timeline', userListTimeline);
|
Vue.component('mk-user-list-timeline', userListTimeline);
|
||||||
Vue.component('mk-widget-container', widgetContainer);
|
Vue.component('ui-container', uiContainer);
|
||||||
|
|||||||
@@ -31,9 +31,6 @@
|
|||||||
<ui-switch v-model="autoPopout">{{ $t('auto-popout') }}
|
<ui-switch v-model="autoPopout">{{ $t('auto-popout') }}
|
||||||
<span slot="desc">{{ $t('auto-popout-desc') }}</span>
|
<span slot="desc">{{ $t('auto-popout-desc') }}</span>
|
||||||
</ui-switch>
|
</ui-switch>
|
||||||
<ui-switch v-model="deckNav">{{ $t('deck-nav') }}
|
|
||||||
<span slot="desc">{{ $t('deck-nav-desc') }}</span>
|
|
||||||
</ui-switch>
|
|
||||||
<ui-switch v-model="keepCw">{{ $t('keep-cw') }}
|
<ui-switch v-model="keepCw">{{ $t('keep-cw') }}
|
||||||
<span slot="desc">{{ $t('keep-cw-desc') }}</span>
|
<span slot="desc">{{ $t('keep-cw-desc') }}</span>
|
||||||
</ui-switch>
|
</ui-switch>
|
||||||
@@ -89,9 +86,6 @@
|
|||||||
<ui-radio v-model="navbar" value="left">{{ $t('navbar-position-left') }}</ui-radio>
|
<ui-radio v-model="navbar" value="left">{{ $t('navbar-position-left') }}</ui-radio>
|
||||||
<ui-radio v-model="navbar" value="right">{{ $t('navbar-position-right') }}</ui-radio>
|
<ui-radio v-model="navbar" value="right">{{ $t('navbar-position-right') }}</ui-radio>
|
||||||
</section>
|
</section>
|
||||||
<section>
|
|
||||||
<ui-switch v-model="deckDefault">{{ $t('deck-default') }}</ui-switch>
|
|
||||||
</section>
|
|
||||||
<section>
|
<section>
|
||||||
<ui-switch v-model="darkmode">{{ $t('dark-mode') }}</ui-switch>
|
<ui-switch v-model="darkmode">{{ $t('dark-mode') }}</ui-switch>
|
||||||
<ui-switch v-model="useShadow">{{ $t('use-shadow') }}</ui-switch>
|
<ui-switch v-model="useShadow">{{ $t('use-shadow') }}</ui-switch>
|
||||||
@@ -337,11 +331,6 @@ export default Vue.extend({
|
|||||||
set(value) { this.$store.commit('device/set', { key: 'autoPopout', value }); }
|
set(value) { this.$store.commit('device/set', { key: 'autoPopout', value }); }
|
||||||
},
|
},
|
||||||
|
|
||||||
deckNav: {
|
|
||||||
get() { return this.$store.state.settings.deckNav; },
|
|
||||||
set(value) { this.$store.commit('settings/set', { key: 'deckNav', value }); }
|
|
||||||
},
|
|
||||||
|
|
||||||
keepCw: {
|
keepCw: {
|
||||||
get() { return this.$store.state.settings.keepCw; },
|
get() { return this.$store.state.settings.keepCw; },
|
||||||
set(value) { this.$store.commit('settings/set', { key: 'keepCw', value }); }
|
set(value) { this.$store.commit('settings/set', { key: 'keepCw', value }); }
|
||||||
@@ -367,11 +356,6 @@ export default Vue.extend({
|
|||||||
set(value) { this.$store.commit('device/set', { key: 'deckColumnWidth', value }); }
|
set(value) { this.$store.commit('device/set', { key: 'deckColumnWidth', value }); }
|
||||||
},
|
},
|
||||||
|
|
||||||
deckDefault: {
|
|
||||||
get() { return this.$store.state.device.deckDefault; },
|
|
||||||
set(value) { this.$store.commit('device/set', { key: 'deckDefault', value }); }
|
|
||||||
},
|
|
||||||
|
|
||||||
enableSounds: {
|
enableSounds: {
|
||||||
get() { return this.$store.state.device.enableSounds; },
|
get() { return this.$store.state.device.enableSounds; },
|
||||||
set(value) { this.$store.commit('device/set', { key: 'enableSounds', value }); }
|
set(value) { this.$store.commit('device/set', { key: 'enableSounds', value }); }
|
||||||
@@ -534,8 +518,7 @@ export default Vue.extend({
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
customizeHome() {
|
customizeHome() {
|
||||||
this.$router.push('/i/customize-home');
|
location.href = '/?customize';
|
||||||
this.$emit('done');
|
|
||||||
},
|
},
|
||||||
updateWallpaper() {
|
updateWallpaper() {
|
||||||
this.$chooseDriveFile({
|
this.$chooseDriveFile({
|
||||||
|
|||||||
@@ -1,260 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="mk-timeline">
|
|
||||||
<header>
|
|
||||||
<span :data-active="src == 'home'" @click="src = 'home'"><fa icon="home"/> {{ $t('home') }}</span>
|
|
||||||
<span :data-active="src == 'local'" @click="src = 'local'" v-if="enableLocalTimeline"><fa :icon="['far', 'comments']"/> {{ $t('local') }}</span>
|
|
||||||
<span :data-active="src == 'hybrid'" @click="src = 'hybrid'" v-if="enableLocalTimeline"><fa icon="share-alt"/> {{ $t('hybrid') }}</span>
|
|
||||||
<span :data-active="src == 'global'" @click="src = 'global'" v-if="enableGlobalTimeline"><fa icon="globe"/> {{ $t('global') }}</span>
|
|
||||||
<span :data-active="src == 'tag'" @click="src = 'tag'" v-if="tagTl"><fa icon="hashtag"/> {{ tagTl.title }}</span>
|
|
||||||
<span :data-active="src == 'list'" @click="src = 'list'" v-if="list"><fa icon="list"/> {{ list.title }}</span>
|
|
||||||
<div class="buttons">
|
|
||||||
<button :data-active="src == 'mentions'" @click="src = 'mentions'" :title="$t('mentions')"><fa icon="at"/><i class="badge" v-if="$store.state.i.hasUnreadMentions"><fa icon="circle"/></i></button>
|
|
||||||
<button :data-active="src == 'messages'" @click="src = 'messages'" :title="$t('messages')"><fa :icon="['far', 'envelope']"/><i class="badge" v-if="$store.state.i.hasUnreadSpecifiedNotes"><fa icon="circle"/></i></button>
|
|
||||||
<button @click="chooseTag" :title="$t('hashtag')" ref="tagButton"><fa icon="hashtag"/></button>
|
|
||||||
<button @click="chooseList" :title="$t('list')" ref="listButton"><fa icon="list"/></button>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
<x-core v-if="src == 'home'" ref="tl" key="home" src="home"/>
|
|
||||||
<x-core v-if="src == 'local'" ref="tl" key="local" src="local"/>
|
|
||||||
<x-core v-if="src == 'hybrid'" ref="tl" key="hybrid" src="hybrid"/>
|
|
||||||
<x-core v-if="src == 'global'" ref="tl" key="global" src="global"/>
|
|
||||||
<x-core v-if="src == 'mentions'" ref="tl" key="mentions" src="mentions"/>
|
|
||||||
<x-core v-if="src == 'messages'" ref="tl" key="messages" src="messages"/>
|
|
||||||
<x-core v-if="src == 'tag'" ref="tl" key="tag" src="tag" :tag-tl="tagTl"/>
|
|
||||||
<mk-user-list-timeline v-if="src == 'list'" ref="tl" :key="list.id" :list="list"/>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import Vue from 'vue';
|
|
||||||
import i18n from '../../../i18n';
|
|
||||||
import XCore from './timeline.core.vue';
|
|
||||||
import Menu from '../../../common/views/components/menu.vue';
|
|
||||||
import MkSettingsWindow from './settings-window.vue';
|
|
||||||
|
|
||||||
export default Vue.extend({
|
|
||||||
i18n: i18n('desktop/views/components/timeline.vue'),
|
|
||||||
components: {
|
|
||||||
XCore
|
|
||||||
},
|
|
||||||
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
src: 'home',
|
|
||||||
list: null,
|
|
||||||
tagTl: null,
|
|
||||||
enableLocalTimeline: false,
|
|
||||||
enableGlobalTimeline: false,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
watch: {
|
|
||||||
src() {
|
|
||||||
this.saveSrc();
|
|
||||||
},
|
|
||||||
|
|
||||||
list(x) {
|
|
||||||
this.saveSrc();
|
|
||||||
if (x != null) this.tagTl = null;
|
|
||||||
},
|
|
||||||
|
|
||||||
tagTl(x) {
|
|
||||||
this.saveSrc();
|
|
||||||
if (x != null) this.list = null;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
created() {
|
|
||||||
this.$root.getMeta().then(meta => {
|
|
||||||
this.enableLocalTimeline = !meta.disableLocalTimeline || this.$store.state.i.isModerator || this.$store.state.i.isAdmin;
|
|
||||||
this.enableGlobalTimeline = !meta.disableGlobalTimeline || this.$store.state.i.isModerator || this.$store.state.i.isAdmin;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (this.$store.state.device.tl) {
|
|
||||||
this.src = this.$store.state.device.tl.src;
|
|
||||||
if (this.src == 'list') {
|
|
||||||
this.list = this.$store.state.device.tl.arg;
|
|
||||||
} else if (this.src == 'tag') {
|
|
||||||
this.tagTl = this.$store.state.device.tl.arg;
|
|
||||||
}
|
|
||||||
} else if (this.$store.state.i.followingCount == 0) {
|
|
||||||
this.src = 'hybrid';
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
mounted() {
|
|
||||||
(this.$refs.tl as any).$once('loaded', () => {
|
|
||||||
this.$emit('loaded');
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
|
||||||
saveSrc() {
|
|
||||||
this.$store.commit('device/setTl', {
|
|
||||||
src: this.src,
|
|
||||||
arg: this.src == 'list' ? this.list : this.tagTl
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
focus() {
|
|
||||||
(this.$refs.tl as any).focus();
|
|
||||||
},
|
|
||||||
|
|
||||||
warp(date) {
|
|
||||||
(this.$refs.tl as any).warp(date);
|
|
||||||
},
|
|
||||||
|
|
||||||
async chooseList() {
|
|
||||||
const lists = await this.$root.api('users/lists/list');
|
|
||||||
|
|
||||||
let menu = [{
|
|
||||||
icon: 'plus',
|
|
||||||
text: this.$t('add-list'),
|
|
||||||
action: () => {
|
|
||||||
this.$root.dialog({
|
|
||||||
title: this.$t('list-name'),
|
|
||||||
input: true
|
|
||||||
}).then(async ({ canceled, result: title }) => {
|
|
||||||
if (canceled) return;
|
|
||||||
const list = await this.$root.api('users/lists/create', {
|
|
||||||
title
|
|
||||||
});
|
|
||||||
|
|
||||||
this.list = list;
|
|
||||||
this.src = 'list';
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}];
|
|
||||||
|
|
||||||
if (lists.length > 0) {
|
|
||||||
menu.push(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
menu = menu.concat(lists.map(list => ({
|
|
||||||
icon: 'list',
|
|
||||||
text: list.title,
|
|
||||||
action: () => {
|
|
||||||
this.list = list;
|
|
||||||
this.src = 'list';
|
|
||||||
}
|
|
||||||
})));
|
|
||||||
|
|
||||||
this.$root.new(Menu, {
|
|
||||||
source: this.$refs.listButton,
|
|
||||||
items: menu
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
chooseTag() {
|
|
||||||
let menu = [{
|
|
||||||
icon: 'plus',
|
|
||||||
text: this.$t('add-tag-timeline'),
|
|
||||||
action: () => {
|
|
||||||
this.$root.new(MkSettingsWindow, {
|
|
||||||
initialPage: 'hashtags'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}];
|
|
||||||
|
|
||||||
if (this.$store.state.settings.tagTimelines.length > 0) {
|
|
||||||
menu.push(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
menu = menu.concat(this.$store.state.settings.tagTimelines.map(t => ({
|
|
||||||
icon: 'hashtag',
|
|
||||||
text: t.title,
|
|
||||||
action: () => {
|
|
||||||
this.tagTl = t;
|
|
||||||
this.src = 'tag';
|
|
||||||
}
|
|
||||||
})));
|
|
||||||
|
|
||||||
this.$root.new(Menu, {
|
|
||||||
source: this.$refs.tagButton,
|
|
||||||
items: menu
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="stylus" scoped>
|
|
||||||
.mk-timeline
|
|
||||||
background var(--face)
|
|
||||||
box-shadow var(--shadow)
|
|
||||||
border-radius var(--round)
|
|
||||||
overflow hidden
|
|
||||||
|
|
||||||
> header
|
|
||||||
padding 0 8px
|
|
||||||
z-index 10
|
|
||||||
background var(--faceHeader)
|
|
||||||
box-shadow 0 var(--lineWidth) var(--desktopTimelineHeaderShadow)
|
|
||||||
|
|
||||||
> .buttons
|
|
||||||
position absolute
|
|
||||||
z-index 2
|
|
||||||
top 0
|
|
||||||
right 0
|
|
||||||
padding-right 8px
|
|
||||||
|
|
||||||
> button
|
|
||||||
padding 0 8px
|
|
||||||
font-size 0.9em
|
|
||||||
line-height 42px
|
|
||||||
color var(--faceTextButton)
|
|
||||||
|
|
||||||
> .badge
|
|
||||||
position absolute
|
|
||||||
top -4px
|
|
||||||
right 4px
|
|
||||||
font-size 10px
|
|
||||||
color var(--notificationIndicator)
|
|
||||||
|
|
||||||
&:hover
|
|
||||||
color var(--faceTextButtonHover)
|
|
||||||
|
|
||||||
&[data-active]
|
|
||||||
color var(--primary)
|
|
||||||
cursor default
|
|
||||||
|
|
||||||
&:before
|
|
||||||
content ""
|
|
||||||
display block
|
|
||||||
position absolute
|
|
||||||
bottom 0
|
|
||||||
left 0
|
|
||||||
width 100%
|
|
||||||
height 2px
|
|
||||||
background var(--primary)
|
|
||||||
|
|
||||||
> span
|
|
||||||
display inline-block
|
|
||||||
padding 0 10px
|
|
||||||
line-height 42px
|
|
||||||
font-size 12px
|
|
||||||
user-select none
|
|
||||||
|
|
||||||
&[data-active]
|
|
||||||
color var(--primary)
|
|
||||||
cursor default
|
|
||||||
font-weight bold
|
|
||||||
|
|
||||||
&:before
|
|
||||||
content ""
|
|
||||||
display block
|
|
||||||
position absolute
|
|
||||||
bottom 0
|
|
||||||
left -8px
|
|
||||||
width calc(100% + 16px)
|
|
||||||
height 2px
|
|
||||||
background var(--primary)
|
|
||||||
|
|
||||||
&:not([data-active])
|
|
||||||
color var(--desktopTimelineSrc)
|
|
||||||
cursor pointer
|
|
||||||
|
|
||||||
&:hover
|
|
||||||
color var(--desktopTimelineSrcHover)
|
|
||||||
|
|
||||||
</style>
|
|
||||||
117
src/client/app/desktop/views/components/ui-container.vue
Normal file
117
src/client/app/desktop/views/components/ui-container.vue
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
<template>
|
||||||
|
<div class="kedshtep" :class="{ naked, inDeck }">
|
||||||
|
<header v-if="showHeader">
|
||||||
|
<div class="title"><slot name="header"></slot></div>
|
||||||
|
<slot name="func"></slot>
|
||||||
|
<button v-if="bodyTogglable" @click="() => showBody = !showBody">
|
||||||
|
<template v-if="showBody"><fa icon="angle-up"/></template>
|
||||||
|
<template v-else><fa icon="angle-down"/></template>
|
||||||
|
</button>
|
||||||
|
</header>
|
||||||
|
<div v-show="showBody">
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import Vue from 'vue';
|
||||||
|
export default Vue.extend({
|
||||||
|
props: {
|
||||||
|
showHeader: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
naked: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
bodyTogglable: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
},
|
||||||
|
inject: {
|
||||||
|
inDeck: {
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
showBody: true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="stylus" scoped>
|
||||||
|
.kedshtep
|
||||||
|
overflow hidden
|
||||||
|
|
||||||
|
&:not(.inDeck)
|
||||||
|
background var(--face)
|
||||||
|
box-shadow var(--shadow)
|
||||||
|
border-radius var(--round)
|
||||||
|
|
||||||
|
& + .kedshtep
|
||||||
|
margin-top 16px
|
||||||
|
|
||||||
|
&.naked
|
||||||
|
background transparent !important
|
||||||
|
box-shadow none !important
|
||||||
|
|
||||||
|
> header
|
||||||
|
background var(--faceHeader)
|
||||||
|
|
||||||
|
> .title
|
||||||
|
z-index 1
|
||||||
|
margin 0
|
||||||
|
padding 0 16px
|
||||||
|
line-height 42px
|
||||||
|
font-size 0.9em
|
||||||
|
font-weight bold
|
||||||
|
color var(--faceHeaderText)
|
||||||
|
box-shadow 0 var(--lineWidth) rgba(#000, 0.07)
|
||||||
|
|
||||||
|
> [data-icon]
|
||||||
|
margin-right 6px
|
||||||
|
|
||||||
|
&:empty
|
||||||
|
display none
|
||||||
|
|
||||||
|
> button
|
||||||
|
position absolute
|
||||||
|
z-index 2
|
||||||
|
top 0
|
||||||
|
right 0
|
||||||
|
padding 0
|
||||||
|
width 42px
|
||||||
|
font-size 0.9em
|
||||||
|
line-height 42px
|
||||||
|
color var(--faceTextButton)
|
||||||
|
|
||||||
|
&:hover
|
||||||
|
color var(--faceTextButtonHover)
|
||||||
|
|
||||||
|
&:active
|
||||||
|
color var(--faceTextButtonActive)
|
||||||
|
|
||||||
|
&.inDeck
|
||||||
|
background var(--face)
|
||||||
|
|
||||||
|
> header
|
||||||
|
margin 0
|
||||||
|
padding 8px 16px
|
||||||
|
font-size 12px
|
||||||
|
color var(--text)
|
||||||
|
background var(--deckColumnBg)
|
||||||
|
|
||||||
|
> button
|
||||||
|
position absolute
|
||||||
|
top 0
|
||||||
|
right 8px
|
||||||
|
padding 8px 6px
|
||||||
|
font-size 14px
|
||||||
|
color var(--text)
|
||||||
|
|
||||||
|
</style>
|
||||||
@@ -44,13 +44,6 @@
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
|
||||||
<router-link to="/i/customize-home">
|
|
||||||
<i><fa icon="wrench"/></i>
|
|
||||||
<span>{{ $t('customize') }}</span>
|
|
||||||
<i><fa icon="angle-right"/></i>
|
|
||||||
</router-link>
|
|
||||||
</li>
|
|
||||||
<li>
|
<li>
|
||||||
<router-link to="/i/settings">
|
<router-link to="/i/settings">
|
||||||
<i><fa icon="cog"/></i>
|
<i><fa icon="cog"/></i>
|
||||||
@@ -67,6 +60,13 @@
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<ul>
|
<ul>
|
||||||
|
<li @click="toggleDeckMode">
|
||||||
|
<p>
|
||||||
|
<span>{{ $t('@.deck') }}</span>
|
||||||
|
<template v-if="$store.state.device.deckMode"><i><fa :icon="faHome"/></i></template>
|
||||||
|
<template v-else><i><fa :icon="faColumns"/></i></template>
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
<li @click="dark">
|
<li @click="dark">
|
||||||
<p>
|
<p>
|
||||||
<span>{{ $t('dark') }}</span>
|
<span>{{ $t('dark') }}</span>
|
||||||
@@ -97,12 +97,14 @@ import MkFollowRequestsWindow from './received-follow-requests-window.vue';
|
|||||||
import MkSettingsWindow from './settings-window.vue';
|
import MkSettingsWindow from './settings-window.vue';
|
||||||
import MkDriveWindow from './drive-window.vue';
|
import MkDriveWindow from './drive-window.vue';
|
||||||
import contains from '../../../common/scripts/contains';
|
import contains from '../../../common/scripts/contains';
|
||||||
|
import { faHome, faColumns } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
i18n: i18n('desktop/views/components/ui.header.account.vue'),
|
i18n: i18n('desktop/views/components/ui.header.account.vue'),
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
isOpen: false
|
isOpen: false,
|
||||||
|
faHome, faColumns
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@@ -161,7 +163,11 @@ export default Vue.extend({
|
|||||||
key: 'darkmode',
|
key: 'darkmode',
|
||||||
value: !this.$store.state.device.darkmode
|
value: !this.$store.state.device.darkmode
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
|
toggleDeckMode() {
|
||||||
|
this.$store.commit('device/set', { key: 'deckMode', value: !this.$store.state.device.deckMode });
|
||||||
|
location.reload();
|
||||||
|
},
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -0,0 +1,68 @@
|
|||||||
|
<template>
|
||||||
|
<div class="toltmoik">
|
||||||
|
<button @click="open()" :title="$t('@.messaging')">
|
||||||
|
<i class="bell"><fa :icon="faComments"/></i>
|
||||||
|
<i class="circle" v-if="hasUnreadMessagingMessage"><fa icon="circle"/></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import Vue from 'vue';
|
||||||
|
import i18n from '../../../i18n';
|
||||||
|
import MkMessagingWindow from './messaging-window.vue';
|
||||||
|
import { faComments } from '@fortawesome/free-regular-svg-icons';
|
||||||
|
|
||||||
|
export default Vue.extend({
|
||||||
|
i18n: i18n(),
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
faComments
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
hasUnreadMessagingMessage(): boolean {
|
||||||
|
return this.$store.getters.isSignedIn && this.$store.state.i.hasUnreadMessagingMessage;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
open() {
|
||||||
|
this.$root.new(MkMessagingWindow);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="stylus" scoped>
|
||||||
|
.toltmoik
|
||||||
|
> button
|
||||||
|
display block
|
||||||
|
margin 0
|
||||||
|
padding 0
|
||||||
|
width 32px
|
||||||
|
color var(--desktopHeaderFg)
|
||||||
|
border none
|
||||||
|
background transparent
|
||||||
|
cursor pointer
|
||||||
|
|
||||||
|
*
|
||||||
|
pointer-events none
|
||||||
|
|
||||||
|
&:hover
|
||||||
|
&[data-active='true']
|
||||||
|
color var(--desktopHeaderHoverFg)
|
||||||
|
|
||||||
|
> i.bell
|
||||||
|
font-size 1.2em
|
||||||
|
line-height 48px
|
||||||
|
|
||||||
|
> i.circle
|
||||||
|
margin-left -5px
|
||||||
|
vertical-align super
|
||||||
|
font-size 10px
|
||||||
|
color var(--notificationIndicator)
|
||||||
|
|
||||||
|
</style>
|
||||||
@@ -1,29 +1,14 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="nav">
|
<div class="nav">
|
||||||
<ul>
|
<ul>
|
||||||
<template v-if="$store.getters.isSignedIn">
|
<li v-if="!$store.state.device.deckMode" class="timeline" @click="goToTop">
|
||||||
<template v-if="$store.state.device.deckDefault">
|
<router-link to="/"><fa icon="home"/><p>{{ $t('@.timeline') }}</p></router-link>
|
||||||
<li class="deck" :class="{ active: $route.name == 'deck' || $route.name == 'index' }" @click="goToTop">
|
|
||||||
<router-link to="/"><fa icon="columns"/><p>{{ $t('deck') }}</p></router-link>
|
|
||||||
</li>
|
</li>
|
||||||
<li class="home" :class="{ active: $route.name == 'home' }" @click="goToTop">
|
<li class="featured">
|
||||||
<router-link to="/home"><fa icon="home"/><p>{{ $t('home') }}</p></router-link>
|
<router-link to="/featured"><fa :icon="faNewspaper"/><p>{{ $t('@.featured-notes') }}</p></router-link>
|
||||||
</li>
|
</li>
|
||||||
</template>
|
<li class="explore">
|
||||||
<template v-else>
|
<router-link to="/explore"><fa :icon="faHashtag"/><p>{{ $t('@.explore') }}</p></router-link>
|
||||||
<li class="home" :class="{ active: $route.name == 'home' || $route.name == 'index' }" @click="goToTop">
|
|
||||||
<router-link to="/"><fa icon="home"/><p>{{ $t('home') }}</p></router-link>
|
|
||||||
</li>
|
|
||||||
<li class="deck" :class="{ active: $route.name == 'deck' }" @click="goToTop">
|
|
||||||
<router-link to="/deck"><fa icon="columns"/><p>{{ $t('deck') }}</p></router-link>
|
|
||||||
</li>
|
|
||||||
</template>
|
|
||||||
<li class="messaging">
|
|
||||||
<a @click="messaging">
|
|
||||||
<fa icon="comments"/>
|
|
||||||
<p>{{ $t('@.messaging') }}</p>
|
|
||||||
<template v-if="hasUnreadMessagingMessage"><fa icon="circle"/></template>
|
|
||||||
</a>
|
|
||||||
</li>
|
</li>
|
||||||
<li class="game">
|
<li class="game">
|
||||||
<a @click="game">
|
<a @click="game">
|
||||||
@@ -32,7 +17,6 @@
|
|||||||
<template v-if="hasGameInvitations"><fa icon="circle"/></template>
|
<template v-if="hasGameInvitations"><fa icon="circle"/></template>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</template>
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -40,22 +24,18 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import i18n from '../../../i18n';
|
import i18n from '../../../i18n';
|
||||||
import MkMessagingWindow from './messaging-window.vue';
|
|
||||||
import MkGameWindow from './game-window.vue';
|
import MkGameWindow from './game-window.vue';
|
||||||
|
import { faNewspaper, faHashtag } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
i18n: i18n('desktop/views/components/ui.header.nav.vue'),
|
i18n: i18n('desktop/views/components/ui.header.nav.vue'),
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
hasGameInvitations: false,
|
hasGameInvitations: false,
|
||||||
connection: null
|
connection: null,
|
||||||
|
faNewspaper, faHashtag
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
|
||||||
hasUnreadMessagingMessage(): boolean {
|
|
||||||
return this.$store.getters.isSignedIn && this.$store.state.i.hasUnreadMessagingMessage;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
mounted() {
|
||||||
if (this.$store.getters.isSignedIn) {
|
if (this.$store.getters.isSignedIn) {
|
||||||
this.connection = this.$root.stream.useSharedConnection('main');
|
this.connection = this.$root.stream.useSharedConnection('main');
|
||||||
@@ -78,10 +58,6 @@ export default Vue.extend({
|
|||||||
this.hasGameInvitations = false;
|
this.hasGameInvitations = false;
|
||||||
},
|
},
|
||||||
|
|
||||||
messaging() {
|
|
||||||
this.$root.new(MkMessagingWindow);
|
|
||||||
},
|
|
||||||
|
|
||||||
game() {
|
game() {
|
||||||
this.$root.new(MkGameWindow);
|
this.$root.new(MkGameWindow);
|
||||||
},
|
},
|
||||||
@@ -126,7 +102,7 @@ export default Vue.extend({
|
|||||||
display inline-block
|
display inline-block
|
||||||
z-index 1
|
z-index 1
|
||||||
height 100%
|
height 100%
|
||||||
padding 0 24px
|
padding 0 20px
|
||||||
font-size 13px
|
font-size 13px
|
||||||
font-variant small-caps
|
font-variant small-caps
|
||||||
color var(--desktopHeaderFg)
|
color var(--desktopHeaderFg)
|
||||||
|
|||||||
@@ -16,9 +16,10 @@
|
|||||||
<div class="right">
|
<div class="right">
|
||||||
<x-search/>
|
<x-search/>
|
||||||
<x-account v-if="$store.getters.isSignedIn"/>
|
<x-account v-if="$store.getters.isSignedIn"/>
|
||||||
|
<x-messaging v-if="$store.getters.isSignedIn"/>
|
||||||
<x-notifications v-if="$store.getters.isSignedIn"/>
|
<x-notifications v-if="$store.getters.isSignedIn"/>
|
||||||
<x-post v-if="$store.getters.isSignedIn"/>
|
<x-post v-if="$store.getters.isSignedIn"/>
|
||||||
<x-clock v-if="$store.state.settings.showClockOnHeader"/>
|
<x-clock v-if="$store.state.settings.showClockOnHeader" class="clock"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -37,6 +38,7 @@ import XAccount from './ui.header.account.vue';
|
|||||||
import XNotifications from './ui.header.notifications.vue';
|
import XNotifications from './ui.header.notifications.vue';
|
||||||
import XPost from './ui.header.post.vue';
|
import XPost from './ui.header.post.vue';
|
||||||
import XClock from './ui.header.clock.vue';
|
import XClock from './ui.header.clock.vue';
|
||||||
|
import XMessaging from './ui.header.messaging.vue';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
i18n: i18n(),
|
i18n: i18n(),
|
||||||
@@ -45,6 +47,7 @@ export default Vue.extend({
|
|||||||
XSearch,
|
XSearch,
|
||||||
XAccount,
|
XAccount,
|
||||||
XNotifications,
|
XNotifications,
|
||||||
|
XMessaging,
|
||||||
XPost,
|
XPost,
|
||||||
XClock
|
XClock
|
||||||
},
|
},
|
||||||
@@ -116,7 +119,7 @@ export default Vue.extend({
|
|||||||
> .container
|
> .container
|
||||||
display flex
|
display flex
|
||||||
width 100%
|
width 100%
|
||||||
max-width 1300px
|
max-width 1208px
|
||||||
margin 0 auto
|
margin 0 auto
|
||||||
|
|
||||||
> *
|
> *
|
||||||
@@ -152,7 +155,7 @@ export default Vue.extend({
|
|||||||
vertical-align top
|
vertical-align top
|
||||||
|
|
||||||
@media (max-width 1100px)
|
@media (max-width 1100px)
|
||||||
> .mk-ui-header-search
|
> .clock
|
||||||
display none
|
display none
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -6,20 +6,20 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="nav" v-if="$store.getters.isSignedIn">
|
<div class="nav" v-if="$store.getters.isSignedIn">
|
||||||
<template v-if="$store.state.device.deckDefault">
|
<template v-if="$store.state.device.deckMode">
|
||||||
<div class="deck" :class="{ active: $route.name == 'deck' || $route.name == 'index' }" @click="goToTop">
|
<div class="deck active" @click="goToTop">
|
||||||
<router-link to="/"><fa icon="columns"/></router-link>
|
<router-link to="/"><fa icon="columns"/></router-link>
|
||||||
</div>
|
</div>
|
||||||
<div class="home" :class="{ active: $route.name == 'home' }" @click="goToTop">
|
<div class="home">
|
||||||
<router-link to="/home"><fa icon="home"/></router-link>
|
<a @click="toggleDeckMode(false)"><fa icon="home"/></a>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<div class="home" :class="{ active: $route.name == 'home' || $route.name == 'index' }" @click="goToTop">
|
<div class="home active" @click="goToTop">
|
||||||
<router-link to="/"><fa icon="home"/></router-link>
|
<router-link to="/"><fa icon="home"/></router-link>
|
||||||
</div>
|
</div>
|
||||||
<div class="deck" :class="{ active: $route.name == 'deck' }" @click="goToTop">
|
<div class="deck">
|
||||||
<router-link to="/deck"><fa icon="columns"/></router-link>
|
<a @click="toggleDeckMode(true)"><fa icon="columns"/></a>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<div class="messaging">
|
<div class="messaging">
|
||||||
@@ -122,6 +122,11 @@ export default Vue.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
|
toggleDeckMode(deck) {
|
||||||
|
this.$store.commit('device/set', { key: 'deckMode', value: deck });
|
||||||
|
location.reload();
|
||||||
|
},
|
||||||
|
|
||||||
onReversiInvited() {
|
onReversiInvited() {
|
||||||
this.hasGameInvitations = true;
|
this.hasGameInvitations = true;
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<div class="zvdbznxvfixtmujpsigoccczftvpiwqh">
|
<div class="zvdbznxvfixtmujpsigoccczftvpiwqh">
|
||||||
<div class="banner" :style="bannerStyle"></div>
|
<div class="banner" :style="bannerStyle"></div>
|
||||||
<mk-avatar class="avatar" :user="user" :disable-preview="true"/>
|
<mk-avatar class="avatar" :user="user" :disable-preview="true"/>
|
||||||
<mk-follow-button :user="user" class="follow" mini/>
|
<mk-follow-button v-if="$store.getters.isSignedIn && user.id != $store.state.i.id" :user="user" class="follow" mini/>
|
||||||
<div class="body">
|
<div class="body">
|
||||||
<router-link :to="user | userPage" class="name">
|
<router-link :to="user | userPage" class="name">
|
||||||
<mk-user-name :user="user"/>
|
<mk-user-name :user="user"/>
|
||||||
@@ -41,7 +41,6 @@ export default Vue.extend({
|
|||||||
height 280px
|
height 280px
|
||||||
overflow hidden
|
overflow hidden
|
||||||
font-size 13px
|
font-size 13px
|
||||||
text-align center
|
|
||||||
background $bg
|
background $bg
|
||||||
box-shadow 0 2px 4px rgba(0, 0, 0, 0.1)
|
box-shadow 0 2px 4px rgba(0, 0, 0, 0.1)
|
||||||
color var(--faceText)
|
color var(--faceText)
|
||||||
@@ -54,7 +53,7 @@ export default Vue.extend({
|
|||||||
|
|
||||||
> .avatar
|
> .avatar
|
||||||
display block
|
display block
|
||||||
margin -40px auto 0 auto
|
margin -40px 0 0 16px
|
||||||
width 80px
|
width 80px
|
||||||
height 80px
|
height 80px
|
||||||
border-radius 100%
|
border-radius 100%
|
||||||
@@ -67,6 +66,7 @@ export default Vue.extend({
|
|||||||
|
|
||||||
> .body
|
> .body
|
||||||
padding 0px 24px
|
padding 0px 24px
|
||||||
|
margin-top -40px
|
||||||
|
|
||||||
> .name
|
> .name
|
||||||
font-size 120%
|
font-size 120%
|
||||||
|
|||||||
@@ -1,74 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="mk-widget-container" :class="{ naked }">
|
|
||||||
<header v-if="showHeader">
|
|
||||||
<div class="title"><slot name="header"></slot></div>
|
|
||||||
<slot name="func"></slot>
|
|
||||||
</header>
|
|
||||||
<slot></slot>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import Vue from 'vue';
|
|
||||||
export default Vue.extend({
|
|
||||||
props: {
|
|
||||||
showHeader: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true
|
|
||||||
},
|
|
||||||
naked: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="stylus" scoped>
|
|
||||||
.mk-widget-container
|
|
||||||
background var(--face)
|
|
||||||
box-shadow var(--shadow)
|
|
||||||
border-radius var(--round)
|
|
||||||
overflow hidden
|
|
||||||
|
|
||||||
&.naked
|
|
||||||
background transparent !important
|
|
||||||
box-shadow none !important
|
|
||||||
|
|
||||||
> header
|
|
||||||
background var(--faceHeader)
|
|
||||||
|
|
||||||
> .title
|
|
||||||
z-index 1
|
|
||||||
margin 0
|
|
||||||
padding 0 16px
|
|
||||||
line-height 42px
|
|
||||||
font-size 0.9em
|
|
||||||
font-weight bold
|
|
||||||
color var(--faceHeaderText)
|
|
||||||
box-shadow 0 var(--lineWidth) rgba(#000, 0.07)
|
|
||||||
|
|
||||||
> [data-icon]
|
|
||||||
margin-right 6px
|
|
||||||
|
|
||||||
&:empty
|
|
||||||
display none
|
|
||||||
|
|
||||||
> button
|
|
||||||
position absolute
|
|
||||||
z-index 2
|
|
||||||
top 0
|
|
||||||
right 0
|
|
||||||
padding 0
|
|
||||||
width 42px
|
|
||||||
font-size 0.9em
|
|
||||||
line-height 42px
|
|
||||||
color var(--faceTextButton)
|
|
||||||
|
|
||||||
&:hover
|
|
||||||
color var(--faceTextButtonHover)
|
|
||||||
|
|
||||||
&:active
|
|
||||||
color var(--faceTextButtonActive)
|
|
||||||
|
|
||||||
</style>
|
|
||||||
@@ -27,9 +27,9 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import i18n from '../../../../i18n';
|
import i18n from '../../../i18n';
|
||||||
import Menu from '../../../../common/views/components/menu.vue';
|
import Menu from '../../../common/views/components/menu.vue';
|
||||||
import { countIf } from '../../../../../../prelude/array';
|
import { countIf } from '../../../../../prelude/array';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
i18n: i18n('deck'),
|
i18n: i18n('deck'),
|
||||||
@@ -65,6 +65,16 @@ export default Vue.extend({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
count: 0,
|
||||||
|
active: true,
|
||||||
|
dragging: false,
|
||||||
|
draghover: false,
|
||||||
|
dropready: false
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
isTemporaryColumn(): boolean {
|
isTemporaryColumn(): boolean {
|
||||||
return this.column == null;
|
return this.column == null;
|
||||||
@@ -84,16 +94,6 @@ export default Vue.extend({
|
|||||||
getColumnVm: { from: 'getColumnVm' }
|
getColumnVm: { from: 'getColumnVm' }
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
count: 0,
|
|
||||||
active: true,
|
|
||||||
dragging: false,
|
|
||||||
draghover: false,
|
|
||||||
dropready: false
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
active(v) {
|
active(v) {
|
||||||
if (v && this.isScrollTop()) {
|
if (v && this.isScrollTop()) {
|
||||||
@@ -109,7 +109,8 @@ export default Vue.extend({
|
|||||||
return {
|
return {
|
||||||
column: this,
|
column: this,
|
||||||
isScrollTop: this.isScrollTop,
|
isScrollTop: this.isScrollTop,
|
||||||
count: v => this.count = v
|
count: v => this.count = v,
|
||||||
|
inDeck: !this.naked
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -245,10 +246,7 @@ export default Vue.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
close() {
|
close() {
|
||||||
this.$store.commit('device/set', {
|
this.$router.push('/');
|
||||||
key: 'deckTemporaryColumn',
|
|
||||||
value: null
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
goTop() {
|
goTop() {
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import i18n from '../../../../i18n';
|
import i18n from '../../../i18n';
|
||||||
import XColumn from './deck.column.vue';
|
import XColumn from './deck.column.vue';
|
||||||
import XDirect from './deck.direct.vue';
|
import XDirect from './deck.direct.vue';
|
||||||
|
|
||||||
34
src/client/app/desktop/views/deck/deck.explore-column.vue
Normal file
34
src/client/app/desktop/views/deck/deck.explore-column.vue
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
<template>
|
||||||
|
<x-column>
|
||||||
|
<span slot="header">
|
||||||
|
<fa :icon="faHashtag"/>{{ $t('@.explore') }}
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<x-explore/>
|
||||||
|
</div>
|
||||||
|
</x-column>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import Vue from 'vue';
|
||||||
|
import i18n from '../../../i18n';
|
||||||
|
import XColumn from './deck.column.vue';
|
||||||
|
import XExplore from '../../../common/views/pages/explore.vue';
|
||||||
|
import { faHashtag } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
|
||||||
|
export default Vue.extend({
|
||||||
|
i18n: i18n(),
|
||||||
|
|
||||||
|
components: {
|
||||||
|
XColumn,
|
||||||
|
XExplore,
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
faHashtag
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
88
src/client/app/desktop/views/deck/deck.favorites-column.vue
Normal file
88
src/client/app/desktop/views/deck/deck.favorites-column.vue
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
<template>
|
||||||
|
<x-column>
|
||||||
|
<span slot="header">
|
||||||
|
<fa :icon="['fa', 'star']"/>{{ $t('favorites') }}
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<x-notes ref="timeline" :more="existMore ? more : null"/>
|
||||||
|
</div>
|
||||||
|
</x-column>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import Vue from 'vue';
|
||||||
|
import i18n from '../../../i18n';
|
||||||
|
import XColumn from './deck.column.vue';
|
||||||
|
import XNotes from './deck.notes.vue';
|
||||||
|
|
||||||
|
const fetchLimit = 10;
|
||||||
|
|
||||||
|
export default Vue.extend({
|
||||||
|
i18n: i18n(),
|
||||||
|
|
||||||
|
components: {
|
||||||
|
XColumn,
|
||||||
|
XNotes,
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
fetching: true,
|
||||||
|
moreFetching: false,
|
||||||
|
existMore: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
this.fetch();
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
fetch() {
|
||||||
|
this.fetching = true;
|
||||||
|
|
||||||
|
(this.$refs.timeline as any).init(() => new Promise((res, rej) => {
|
||||||
|
this.$root.api('i/favorites', {
|
||||||
|
limit: fetchLimit + 1,
|
||||||
|
}).then(notes => {
|
||||||
|
if (notes.length == fetchLimit + 1) {
|
||||||
|
notes.pop();
|
||||||
|
this.existMore = true;
|
||||||
|
}
|
||||||
|
res(notes.map(x => x.note));
|
||||||
|
this.fetching = false;
|
||||||
|
this.$emit('loaded');
|
||||||
|
}, rej);
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
|
||||||
|
more() {
|
||||||
|
this.moreFetching = true;
|
||||||
|
|
||||||
|
const promise = this.$root.api('i/favorites', {
|
||||||
|
limit: fetchLimit + 1,
|
||||||
|
untilId: (this.$refs.timeline as any).tail().id,
|
||||||
|
});
|
||||||
|
|
||||||
|
promise.then(notes => {
|
||||||
|
if (notes.length == fetchLimit + 1) {
|
||||||
|
notes.pop();
|
||||||
|
} else {
|
||||||
|
this.existMore = false;
|
||||||
|
}
|
||||||
|
for (const n of notes) {
|
||||||
|
(this.$refs.timeline as any).append(n);
|
||||||
|
}
|
||||||
|
this.moreFetching = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
return promise;
|
||||||
|
},
|
||||||
|
|
||||||
|
focus() {
|
||||||
|
this.$refs.timeline.focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
59
src/client/app/desktop/views/deck/deck.featured-column.vue
Normal file
59
src/client/app/desktop/views/deck/deck.featured-column.vue
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
<template>
|
||||||
|
<x-column>
|
||||||
|
<span slot="header">
|
||||||
|
<fa :icon="faNewspaper"/>{{ $t('@.featured-notes') }}
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<x-notes ref="timeline" :more="null"/>
|
||||||
|
</div>
|
||||||
|
</x-column>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import Vue from 'vue';
|
||||||
|
import i18n from '../../../i18n';
|
||||||
|
import XColumn from './deck.column.vue';
|
||||||
|
import XNotes from './deck.notes.vue';
|
||||||
|
import { faNewspaper } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
|
||||||
|
export default Vue.extend({
|
||||||
|
i18n: i18n(),
|
||||||
|
|
||||||
|
components: {
|
||||||
|
XColumn,
|
||||||
|
XNotes,
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
fetching: true,
|
||||||
|
faNewspaper
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
this.fetch();
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
fetch() {
|
||||||
|
this.fetching = true;
|
||||||
|
|
||||||
|
(this.$refs.timeline as any).init(() => new Promise((res, rej) => {
|
||||||
|
this.$root.api('notes/featured', {
|
||||||
|
limit: 20,
|
||||||
|
}).then(notes => {
|
||||||
|
res(notes);
|
||||||
|
this.fetching = false;
|
||||||
|
this.$emit('loaded');
|
||||||
|
}, rej);
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
|
||||||
|
focus() {
|
||||||
|
this.$refs.timeline.focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
119
src/client/app/desktop/views/deck/deck.hashtag-column.vue
Normal file
119
src/client/app/desktop/views/deck/deck.hashtag-column.vue
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
<template>
|
||||||
|
<x-column>
|
||||||
|
<span slot="header">
|
||||||
|
<fa icon="hashtag"/><span>{{ tag }}</span>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<div class="xroyrflcmhhtmlwmyiwpfqiirqokfueb">
|
||||||
|
<div ref="chart" class="chart"></div>
|
||||||
|
<x-hashtag-tl :tag-tl="tagTl" class="tl"/>
|
||||||
|
</div>
|
||||||
|
</x-column>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import Vue from 'vue';
|
||||||
|
import XColumn from './deck.column.vue';
|
||||||
|
import XHashtagTl from './deck.hashtag-tl.vue';
|
||||||
|
import ApexCharts from 'apexcharts';
|
||||||
|
|
||||||
|
export default Vue.extend({
|
||||||
|
components: {
|
||||||
|
XColumn,
|
||||||
|
XHashtagTl
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
tag(): string {
|
||||||
|
return this.$route.params.tag;
|
||||||
|
},
|
||||||
|
|
||||||
|
tagTl(): any {
|
||||||
|
return {
|
||||||
|
query: [[this.tag]]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
$route: 'fetch'
|
||||||
|
},
|
||||||
|
|
||||||
|
created() {
|
||||||
|
this.fetch();
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
fetch() {
|
||||||
|
this.$root.api('charts/hashtag', {
|
||||||
|
tag: this.tag,
|
||||||
|
span: 'hour',
|
||||||
|
limit: 24
|
||||||
|
}).then(stats => {
|
||||||
|
const local = [];
|
||||||
|
const remote = [];
|
||||||
|
|
||||||
|
const now = new Date();
|
||||||
|
const y = now.getFullYear();
|
||||||
|
const m = now.getMonth();
|
||||||
|
const d = now.getDate();
|
||||||
|
const h = now.getHours();
|
||||||
|
|
||||||
|
for (let i = 0; i < 24; i++) {
|
||||||
|
const x = new Date(y, m, d, h - i);
|
||||||
|
local.push([x, stats.local.count[i]]);
|
||||||
|
remote.push([x, stats.remote.count[i]]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const chart = new ApexCharts(this.$refs.chart, {
|
||||||
|
chart: {
|
||||||
|
type: 'area',
|
||||||
|
height: 70,
|
||||||
|
sparkline: {
|
||||||
|
enabled: true
|
||||||
|
},
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
clipMarkers: false,
|
||||||
|
padding: {
|
||||||
|
top: 16,
|
||||||
|
right: 16,
|
||||||
|
bottom: 16,
|
||||||
|
left: 16
|
||||||
|
}
|
||||||
|
},
|
||||||
|
stroke: {
|
||||||
|
curve: 'straight',
|
||||||
|
width: 2
|
||||||
|
},
|
||||||
|
series: [{
|
||||||
|
name: 'Local',
|
||||||
|
data: local
|
||||||
|
}, {
|
||||||
|
name: 'Remote',
|
||||||
|
data: remote
|
||||||
|
}],
|
||||||
|
xaxis: {
|
||||||
|
type: 'datetime',
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
chart.render();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="stylus" scoped>
|
||||||
|
.xroyrflcmhhtmlwmyiwpfqiirqokfueb
|
||||||
|
background var(--deckColumnBg)
|
||||||
|
|
||||||
|
> .chart
|
||||||
|
margin-bottom 16px
|
||||||
|
background var(--face)
|
||||||
|
|
||||||
|
> .tl
|
||||||
|
background var(--face)
|
||||||
|
|
||||||
|
</style>
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import i18n from '../../../../i18n';
|
import i18n from '../../../i18n';
|
||||||
import XColumn from './deck.column.vue';
|
import XColumn from './deck.column.vue';
|
||||||
import XMentions from './deck.mentions.vue';
|
import XMentions from './deck.mentions.vue';
|
||||||
|
|
||||||
@@ -18,10 +18,10 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import i18n from '../../../../i18n';
|
import i18n from '../../../i18n';
|
||||||
import XColumn from './deck.column.vue';
|
import XColumn from './deck.column.vue';
|
||||||
import XNotes from './deck.notes.vue';
|
import XNotes from './deck.notes.vue';
|
||||||
import XNote from '../../components/note.vue';
|
import XNote from '../components/note.vue';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
i18n: i18n(),
|
i18n: i18n(),
|
||||||
@@ -31,13 +31,6 @@ export default Vue.extend({
|
|||||||
XNote
|
XNote
|
||||||
},
|
},
|
||||||
|
|
||||||
props: {
|
|
||||||
noteId: {
|
|
||||||
type: String,
|
|
||||||
required: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
note: null,
|
note: null,
|
||||||
@@ -45,12 +38,26 @@ export default Vue.extend({
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
$route: 'fetch'
|
||||||
|
},
|
||||||
|
|
||||||
created() {
|
created() {
|
||||||
this.$root.api('notes/show', { noteId: this.noteId }).then(note => {
|
this.fetch();
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
fetch() {
|
||||||
|
this.fetching = true;
|
||||||
|
|
||||||
|
this.$root.api('notes/show', {
|
||||||
|
noteId: this.$route.params.note
|
||||||
|
}).then(note => {
|
||||||
this.note = note;
|
this.note = note;
|
||||||
this.fetching = false;
|
this.fetching = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -38,10 +38,10 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import i18n from '../../../../i18n';
|
import i18n from '../../../i18n';
|
||||||
import shouldMuteNote from '../../../../common/scripts/should-mute-note';
|
import shouldMuteNote from '../../../common/scripts/should-mute-note';
|
||||||
|
|
||||||
import XNote from '../../components/note.vue';
|
import XNote from '../components/note.vue';
|
||||||
|
|
||||||
const displayLimit = 20;
|
const displayLimit = 20;
|
||||||
|
|
||||||
@@ -96,8 +96,8 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import getNoteSummary from '../../../../../../misc/get-note-summary';
|
import getNoteSummary from '../../../../../misc/get-note-summary';
|
||||||
import XNote from '../../components/note.vue';
|
import XNote from '../components/note.vue';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
components: {
|
components: {
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import i18n from '../../../../i18n';
|
import i18n from '../../../i18n';
|
||||||
import XColumn from './deck.column.vue';
|
import XColumn from './deck.column.vue';
|
||||||
import XNotifications from './deck.notifications.vue';
|
import XNotifications from './deck.notifications.vue';
|
||||||
|
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import i18n from '../../../../i18n';
|
import i18n from '../../../i18n';
|
||||||
import XNotification from './deck.notification.vue';
|
import XNotification from './deck.notification.vue';
|
||||||
|
|
||||||
const displayLimit = 20;
|
const displayLimit = 20;
|
||||||
99
src/client/app/desktop/views/deck/deck.search-column.vue
Normal file
99
src/client/app/desktop/views/deck/deck.search-column.vue
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
<template>
|
||||||
|
<x-column>
|
||||||
|
<span slot="header">
|
||||||
|
<fa icon="search"/><span>{{ q }}</span>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<x-notes ref="timeline" :more="existMore ? more : null"/>
|
||||||
|
</div>
|
||||||
|
</x-column>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import Vue from 'vue';
|
||||||
|
import XColumn from './deck.column.vue';
|
||||||
|
import XNotes from './deck.notes.vue';
|
||||||
|
|
||||||
|
const limit = 20;
|
||||||
|
|
||||||
|
export default Vue.extend({
|
||||||
|
components: {
|
||||||
|
XColumn,
|
||||||
|
XNotes
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
fetching: true,
|
||||||
|
moreFetching: false,
|
||||||
|
existMore: false,
|
||||||
|
offset: 0,
|
||||||
|
empty: false,
|
||||||
|
notAvailable: false
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
q(): string {
|
||||||
|
return this.$route.query.q;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
$route: 'fetch'
|
||||||
|
},
|
||||||
|
|
||||||
|
created() {
|
||||||
|
this.fetch();
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
fetch() {
|
||||||
|
this.fetching = true;
|
||||||
|
|
||||||
|
(this.$refs.timeline as any).init(() => new Promise((res, rej) => {
|
||||||
|
this.$root.api('notes/search', {
|
||||||
|
limit: limit + 1,
|
||||||
|
offset: this.offset,
|
||||||
|
query: this.q
|
||||||
|
}).then(notes => {
|
||||||
|
if (notes.length == 0) this.empty = true;
|
||||||
|
if (notes.length == limit + 1) {
|
||||||
|
notes.pop();
|
||||||
|
this.existMore = true;
|
||||||
|
}
|
||||||
|
res(notes);
|
||||||
|
this.fetching = false;
|
||||||
|
}, (e: string) => {
|
||||||
|
this.fetching = false;
|
||||||
|
if (e === 'searching not available') this.notAvailable = true;
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
more() {
|
||||||
|
this.offset += limit;
|
||||||
|
|
||||||
|
const promise = this.$root.api('notes/search', {
|
||||||
|
limit: limit + 1,
|
||||||
|
offset: this.offset,
|
||||||
|
query: this.q
|
||||||
|
});
|
||||||
|
|
||||||
|
promise.then(notes => {
|
||||||
|
if (notes.length == limit + 1) {
|
||||||
|
notes.pop();
|
||||||
|
} else {
|
||||||
|
this.existMore = false;
|
||||||
|
}
|
||||||
|
for (const n of notes) {
|
||||||
|
(this.$refs.timeline as any).append(n);
|
||||||
|
}
|
||||||
|
this.moreFetching = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
return promise;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import i18n from '../../../../i18n';
|
import i18n from '../../../i18n';
|
||||||
import XColumn from './deck.column.vue';
|
import XColumn from './deck.column.vue';
|
||||||
import XTl from './deck.tl.vue';
|
import XTl from './deck.tl.vue';
|
||||||
import XListTl from './deck.list-tl.vue';
|
import XListTl from './deck.list-tl.vue';
|
||||||
244
src/client/app/desktop/views/deck/deck.user-column.home.vue
Normal file
244
src/client/app/desktop/views/deck/deck.user-column.home.vue
Normal file
@@ -0,0 +1,244 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<ui-container v-if="user.pinnedNotes && user.pinnedNotes.length > 0" :body-togglable="true">
|
||||||
|
<span slot="header"><fa icon="thumbtack"/> {{ $t('pinned-notes') }}</span>
|
||||||
|
<div>
|
||||||
|
<x-note v-for="n in user.pinnedNotes" :key="n.id" :note="n" :mini="true"/>
|
||||||
|
</div>
|
||||||
|
</ui-container>
|
||||||
|
<ui-container v-if="images.length > 0" :body-togglable="true">
|
||||||
|
<span slot="header"><fa :icon="['far', 'images']"/> {{ $t('images') }}</span>
|
||||||
|
<div class="sainvnaq">
|
||||||
|
<router-link v-for="image in images"
|
||||||
|
:style="`background-image: url(${image.thumbnailUrl})`"
|
||||||
|
:key="`${image.id}:${image._note.id}`"
|
||||||
|
:to="image._note | notePage"
|
||||||
|
:title="`${image.name}\n${(new Date(image.createdAt)).toLocaleString()}`"
|
||||||
|
></router-link>
|
||||||
|
</div>
|
||||||
|
</ui-container>
|
||||||
|
<ui-container :body-togglable="true">
|
||||||
|
<span slot="header"><fa :icon="['far', 'chart-bar']"/> {{ $t('activity') }}</span>
|
||||||
|
<div>
|
||||||
|
<div ref="chart"></div>
|
||||||
|
</div>
|
||||||
|
</ui-container>
|
||||||
|
<ui-container>
|
||||||
|
<span slot="header"><fa :icon="['far', 'comment-alt']"/> {{ $t('timeline') }}</span>
|
||||||
|
<div>
|
||||||
|
<x-notes ref="timeline" :more="existMore ? fetchMoreNotes : null"/>
|
||||||
|
</div>
|
||||||
|
</ui-container>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import Vue from 'vue';
|
||||||
|
import i18n from '../../../i18n';
|
||||||
|
import parseAcct from '../../../../../misc/acct/parse';
|
||||||
|
import XNotes from './deck.notes.vue';
|
||||||
|
import XNote from '../components/note.vue';
|
||||||
|
import { concat } from '../../../../../prelude/array';
|
||||||
|
import ApexCharts from 'apexcharts';
|
||||||
|
|
||||||
|
const fetchLimit = 10;
|
||||||
|
|
||||||
|
export default Vue.extend({
|
||||||
|
i18n: i18n('deck/deck.user-column.vue'),
|
||||||
|
components: {
|
||||||
|
XNotes,
|
||||||
|
XNote
|
||||||
|
},
|
||||||
|
|
||||||
|
props: {
|
||||||
|
user: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
existMore: false,
|
||||||
|
moreFetching: false,
|
||||||
|
withFiles: false,
|
||||||
|
images: [],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
created() {
|
||||||
|
this.fetch();
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
fetch() {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
(this.$refs.timeline as any).init(() => this.initTl());
|
||||||
|
});
|
||||||
|
|
||||||
|
const image = [
|
||||||
|
'image/jpeg',
|
||||||
|
'image/png',
|
||||||
|
'image/gif'
|
||||||
|
];
|
||||||
|
|
||||||
|
this.$root.api('users/notes', {
|
||||||
|
userId: this.user.id,
|
||||||
|
fileType: image,
|
||||||
|
excludeNsfw: !this.$store.state.device.alwaysShowNsfw,
|
||||||
|
limit: 9,
|
||||||
|
untilDate: new Date().getTime() + 1000 * 86400 * 365
|
||||||
|
}).then(notes => {
|
||||||
|
for (const note of notes) {
|
||||||
|
for (const file of note.files) {
|
||||||
|
file._note = note;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const files = concat(notes.map((n: any): any[] => n.files));
|
||||||
|
this.images = files.filter(f => image.includes(f.type)).slice(0, 9);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.$root.api('charts/user/notes', {
|
||||||
|
userId: this.user.id,
|
||||||
|
span: 'day',
|
||||||
|
limit: 21
|
||||||
|
}).then(stats => {
|
||||||
|
const normal = [];
|
||||||
|
const reply = [];
|
||||||
|
const renote = [];
|
||||||
|
|
||||||
|
const now = new Date();
|
||||||
|
const y = now.getFullYear();
|
||||||
|
const m = now.getMonth();
|
||||||
|
const d = now.getDate();
|
||||||
|
|
||||||
|
for (let i = 0; i < 21; i++) {
|
||||||
|
const x = new Date(y, m, d - i);
|
||||||
|
normal.push([
|
||||||
|
x,
|
||||||
|
stats.diffs.normal[i]
|
||||||
|
]);
|
||||||
|
reply.push([
|
||||||
|
x,
|
||||||
|
stats.diffs.reply[i]
|
||||||
|
]);
|
||||||
|
renote.push([
|
||||||
|
x,
|
||||||
|
stats.diffs.renote[i]
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const chart = new ApexCharts(this.$refs.chart, {
|
||||||
|
chart: {
|
||||||
|
type: 'bar',
|
||||||
|
stacked: true,
|
||||||
|
height: 100,
|
||||||
|
sparkline: {
|
||||||
|
enabled: true
|
||||||
|
},
|
||||||
|
},
|
||||||
|
plotOptions: {
|
||||||
|
bar: {
|
||||||
|
columnWidth: '90%'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
clipMarkers: false,
|
||||||
|
padding: {
|
||||||
|
top: 16,
|
||||||
|
right: 16,
|
||||||
|
bottom: 16,
|
||||||
|
left: 16
|
||||||
|
}
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
shared: true,
|
||||||
|
intersect: false
|
||||||
|
},
|
||||||
|
series: [{
|
||||||
|
name: 'Normal',
|
||||||
|
data: normal
|
||||||
|
}, {
|
||||||
|
name: 'Reply',
|
||||||
|
data: reply
|
||||||
|
}, {
|
||||||
|
name: 'Renote',
|
||||||
|
data: renote
|
||||||
|
}],
|
||||||
|
xaxis: {
|
||||||
|
type: 'datetime',
|
||||||
|
crosshairs: {
|
||||||
|
width: 1,
|
||||||
|
opacity: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
chart.render();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
initTl() {
|
||||||
|
return new Promise((res, rej) => {
|
||||||
|
this.$root.api('users/notes', {
|
||||||
|
userId: this.user.id,
|
||||||
|
limit: fetchLimit + 1,
|
||||||
|
untilDate: new Date().getTime() + 1000 * 86400 * 365,
|
||||||
|
withFiles: this.withFiles,
|
||||||
|
includeMyRenotes: this.$store.state.settings.showMyRenotes,
|
||||||
|
includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes,
|
||||||
|
includeLocalRenotes: this.$store.state.settings.showLocalRenotes
|
||||||
|
}).then(notes => {
|
||||||
|
if (notes.length == fetchLimit + 1) {
|
||||||
|
notes.pop();
|
||||||
|
this.existMore = true;
|
||||||
|
}
|
||||||
|
res(notes);
|
||||||
|
}, rej);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
fetchMoreNotes() {
|
||||||
|
this.moreFetching = true;
|
||||||
|
|
||||||
|
const promise = this.$root.api('users/notes', {
|
||||||
|
userId: this.user.id,
|
||||||
|
limit: fetchLimit + 1,
|
||||||
|
untilDate: new Date((this.$refs.timeline as any).tail().createdAt).getTime(),
|
||||||
|
withFiles: this.withFiles,
|
||||||
|
includeMyRenotes: this.$store.state.settings.showMyRenotes,
|
||||||
|
includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes,
|
||||||
|
includeLocalRenotes: this.$store.state.settings.showLocalRenotes
|
||||||
|
});
|
||||||
|
|
||||||
|
promise.then(notes => {
|
||||||
|
if (notes.length == fetchLimit + 1) {
|
||||||
|
notes.pop();
|
||||||
|
} else {
|
||||||
|
this.existMore = false;
|
||||||
|
}
|
||||||
|
for (const n of notes) (this.$refs.timeline as any).append(n);
|
||||||
|
this.moreFetching = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
return promise;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="stylus" scoped>
|
||||||
|
.sainvnaq
|
||||||
|
display grid
|
||||||
|
grid-template-columns 1fr 1fr 1fr
|
||||||
|
gap 8px
|
||||||
|
padding 16px
|
||||||
|
|
||||||
|
> *
|
||||||
|
height 70px
|
||||||
|
background-position center center
|
||||||
|
background-size cover
|
||||||
|
background-clip content-box
|
||||||
|
border-radius 4px
|
||||||
|
|
||||||
|
</style>
|
||||||
262
src/client/app/desktop/views/deck/deck.user-column.vue
Normal file
262
src/client/app/desktop/views/deck/deck.user-column.vue
Normal file
@@ -0,0 +1,262 @@
|
|||||||
|
<template>
|
||||||
|
<x-column>
|
||||||
|
<span slot="header">
|
||||||
|
<fa icon="user"/><mk-user-name :user="user" v-if="user"/>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<div class="zubukjlciycdsyynicqrnlsmdwmymzqu" v-if="user">
|
||||||
|
<div class="is-remote" v-if="user.host != null">
|
||||||
|
<details>
|
||||||
|
<summary><fa icon="exclamation-triangle"/> {{ $t('@.is-remote-user') }}</summary>
|
||||||
|
<a :href="user.url || user.uri" target="_blank">{{ $t('@.view-on-remote') }}</a>
|
||||||
|
</details>
|
||||||
|
</div>
|
||||||
|
<header :style="bannerStyle">
|
||||||
|
<div>
|
||||||
|
<button class="menu" @click="menu" ref="menu"><fa icon="ellipsis-h"/></button>
|
||||||
|
<mk-follow-button v-if="$store.getters.isSignedIn && user.id != $store.state.i.id" :user="user" class="follow" mini/>
|
||||||
|
<mk-avatar class="avatar" :user="user" :disable-preview="true"/>
|
||||||
|
<span class="name">
|
||||||
|
<mk-user-name :user="user"/>
|
||||||
|
</span>
|
||||||
|
<span class="acct">@{{ user | acct }} <fa v-if="user.isLocked == true" class="locked" icon="lock" fixed-width/></span>
|
||||||
|
<span class="followed" v-if="user.isFollowed">{{ $t('follows-you') }}</span>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
<div class="info">
|
||||||
|
<div class="description">
|
||||||
|
<mfm v-if="user.description" :text="user.description" :author="user" :i="$store.state.i" :custom-emojis="user.emojis"/>
|
||||||
|
</div>
|
||||||
|
<div class="fields" v-if="user.fields">
|
||||||
|
<dl class="field" v-for="(field, i) in user.fields" :key="i">
|
||||||
|
<dt class="name">
|
||||||
|
<mfm :text="field.name" :should-break="false" :plain-text="true" :custom-emojis="user.emojis"/>
|
||||||
|
</dt>
|
||||||
|
<dd class="value">
|
||||||
|
<mfm :text="field.value" :author="user" :i="$store.state.i" :custom-emojis="user.emojis"/>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</div>
|
||||||
|
<div class="counts">
|
||||||
|
<div>
|
||||||
|
<router-link :to="user | userPage()">
|
||||||
|
<b>{{ user.notesCount | number }}</b>
|
||||||
|
<span>{{ $t('posts') }}</span>
|
||||||
|
</router-link>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<router-link :to="user | userPage('following')">
|
||||||
|
<b>{{ user.followingCount | number }}</b>
|
||||||
|
<span>{{ $t('following') }}</span>
|
||||||
|
</router-link>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<router-link :to="user | userPage('followers')">
|
||||||
|
<b>{{ user.followersCount | number }}</b>
|
||||||
|
<span>{{ $t('followers') }}</span>
|
||||||
|
</router-link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<router-view :user="user"></router-view>
|
||||||
|
</div>
|
||||||
|
</x-column>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import Vue from 'vue';
|
||||||
|
import i18n from '../../../i18n';
|
||||||
|
import parseAcct from '../../../../../misc/acct/parse';
|
||||||
|
import XColumn from './deck.column.vue';
|
||||||
|
import XUserMenu from '../../../common/views/components/user-menu.vue';
|
||||||
|
|
||||||
|
export default Vue.extend({
|
||||||
|
i18n: i18n('deck/deck.user-column.vue'),
|
||||||
|
components: {
|
||||||
|
XColumn,
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
user: null,
|
||||||
|
fetching: true,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
bannerStyle(): any {
|
||||||
|
if (this.user == null) return {};
|
||||||
|
if (this.user.bannerUrl == null) return {};
|
||||||
|
return {
|
||||||
|
backgroundColor: this.user.bannerColor && this.user.bannerColor.length == 3 ? `rgb(${ this.user.bannerColor.join(',') })` : null,
|
||||||
|
backgroundImage: `url(${ this.user.bannerUrl })`
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
$route: 'fetch'
|
||||||
|
},
|
||||||
|
|
||||||
|
created() {
|
||||||
|
this.fetch();
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
fetch() {
|
||||||
|
this.fetching = true;
|
||||||
|
this.$root.api('users/show', parseAcct(this.$route.params.user)).then(user => {
|
||||||
|
this.user = user;
|
||||||
|
this.fetching = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
menu() {
|
||||||
|
this.$root.new(XUserMenu, {
|
||||||
|
source: this.$refs.menu,
|
||||||
|
user: this.user
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="stylus" scoped>
|
||||||
|
.zubukjlciycdsyynicqrnlsmdwmymzqu
|
||||||
|
background var(--deckColumnBg)
|
||||||
|
|
||||||
|
> .is-remote
|
||||||
|
padding 8px 16px
|
||||||
|
font-size 12px
|
||||||
|
|
||||||
|
&.is-remote
|
||||||
|
color var(--remoteInfoFg)
|
||||||
|
background var(--remoteInfoBg)
|
||||||
|
|
||||||
|
> a
|
||||||
|
font-weight bold
|
||||||
|
|
||||||
|
> header
|
||||||
|
overflow hidden
|
||||||
|
background-size cover
|
||||||
|
background-position center
|
||||||
|
|
||||||
|
> div
|
||||||
|
padding 32px
|
||||||
|
background rgba(#000, 0.5)
|
||||||
|
color #fff
|
||||||
|
text-align center
|
||||||
|
|
||||||
|
> .menu
|
||||||
|
position absolute
|
||||||
|
top 8px
|
||||||
|
left 8px
|
||||||
|
padding 8px
|
||||||
|
font-size 16px
|
||||||
|
text-shadow 0 0 8px #000
|
||||||
|
|
||||||
|
> .follow
|
||||||
|
position absolute
|
||||||
|
top 16px
|
||||||
|
right 16px
|
||||||
|
|
||||||
|
> .avatar
|
||||||
|
display block
|
||||||
|
width 64px
|
||||||
|
height 64px
|
||||||
|
margin 0 auto
|
||||||
|
|
||||||
|
> .name
|
||||||
|
display block
|
||||||
|
margin-top 8px
|
||||||
|
font-weight bold
|
||||||
|
text-shadow 0 0 8px #000
|
||||||
|
|
||||||
|
> .acct
|
||||||
|
display block
|
||||||
|
font-size 14px
|
||||||
|
opacity 0.7
|
||||||
|
text-shadow 0 0 8px #000
|
||||||
|
|
||||||
|
> .locked
|
||||||
|
opacity 0.8
|
||||||
|
|
||||||
|
> .followed
|
||||||
|
display inline-block
|
||||||
|
font-size 12px
|
||||||
|
background rgba(0, 0, 0, 0.5)
|
||||||
|
opacity 0.7
|
||||||
|
margin-top: 2px
|
||||||
|
padding 4px
|
||||||
|
border-radius 4px
|
||||||
|
|
||||||
|
> .info
|
||||||
|
padding 16px
|
||||||
|
font-size 12px
|
||||||
|
color var(--text)
|
||||||
|
text-align center
|
||||||
|
background var(--face)
|
||||||
|
|
||||||
|
&:before
|
||||||
|
content ""
|
||||||
|
display blcok
|
||||||
|
position absolute
|
||||||
|
top -32px
|
||||||
|
left 0
|
||||||
|
right 0
|
||||||
|
width 0px
|
||||||
|
margin 0 auto
|
||||||
|
border-top solid 16px transparent
|
||||||
|
border-left solid 16px transparent
|
||||||
|
border-right solid 16px transparent
|
||||||
|
border-bottom solid 16px var(--face)
|
||||||
|
|
||||||
|
> .fields
|
||||||
|
margin-top 8px
|
||||||
|
|
||||||
|
> .field
|
||||||
|
display flex
|
||||||
|
padding 0
|
||||||
|
margin 0
|
||||||
|
align-items center
|
||||||
|
|
||||||
|
> .name
|
||||||
|
padding 4px
|
||||||
|
margin 4px
|
||||||
|
width 30%
|
||||||
|
overflow hidden
|
||||||
|
white-space nowrap
|
||||||
|
text-overflow ellipsis
|
||||||
|
font-weight bold
|
||||||
|
|
||||||
|
> .value
|
||||||
|
padding 4px
|
||||||
|
margin 4px
|
||||||
|
width 70%
|
||||||
|
overflow hidden
|
||||||
|
white-space nowrap
|
||||||
|
text-overflow ellipsis
|
||||||
|
|
||||||
|
> .counts
|
||||||
|
display grid
|
||||||
|
grid-template-columns 2fr 2fr 2fr
|
||||||
|
margin-top 8px
|
||||||
|
border-top solid var(--lineWidth) var(--faceDivider)
|
||||||
|
|
||||||
|
> div
|
||||||
|
padding 8px 8px 0 8px
|
||||||
|
text-align center
|
||||||
|
|
||||||
|
> a
|
||||||
|
color var(--text)
|
||||||
|
|
||||||
|
> b
|
||||||
|
display block
|
||||||
|
font-size 110%
|
||||||
|
|
||||||
|
> span
|
||||||
|
display block
|
||||||
|
font-size 80%
|
||||||
|
opacity 0.7
|
||||||
|
|
||||||
|
</style>
|
||||||
@@ -9,11 +9,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<x-column-core v-else :ref="ids[0]" :key="ids[0]" :column="columns.find(c => c.id == ids[0])" @parentFocus="moveFocus(ids[0], $event)"/>
|
<x-column-core v-else :ref="ids[0]" :key="ids[0]" :column="columns.find(c => c.id == ids[0])" @parentFocus="moveFocus(ids[0], $event)"/>
|
||||||
</template>
|
</template>
|
||||||
<template v-if="temporaryColumn">
|
<router-view></router-view>
|
||||||
<x-user-column v-if="temporaryColumn.type == 'user'" :acct="temporaryColumn.acct" :key="temporaryColumn.acct"/>
|
|
||||||
<x-note-column v-else-if="temporaryColumn.type == 'note'" :note-id="temporaryColumn.noteId" :key="temporaryColumn.noteId"/>
|
|
||||||
<x-hashtag-column v-else-if="temporaryColumn.type == 'tag'" :tag="temporaryColumn.tag" :key="temporaryColumn.tag"/>
|
|
||||||
</template>
|
|
||||||
<button ref="add" @click="add" :title="$t('@deck.add-column')"><fa icon="plus"/></button>
|
<button ref="add" @click="add" :title="$t('@deck.add-column')"><fa icon="plus"/></button>
|
||||||
</div>
|
</div>
|
||||||
</mk-ui>
|
</mk-ui>
|
||||||
@@ -21,20 +17,17 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import i18n from '../../../../i18n';
|
import i18n from '../../../i18n';
|
||||||
import XColumnCore from './deck.column-core.vue';
|
import XColumnCore from './deck.column-core.vue';
|
||||||
import Menu from '../../../../common/views/components/menu.vue';
|
import Menu from '../../../common/views/components/menu.vue';
|
||||||
import MkUserListsWindow from '../../components/user-lists-window.vue';
|
import MkUserListsWindow from '../components/user-lists-window.vue';
|
||||||
|
|
||||||
import * as uuid from 'uuid';
|
import * as uuid from 'uuid';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
i18n: i18n('deck'),
|
i18n: i18n('deck'),
|
||||||
components: {
|
components: {
|
||||||
XColumnCore,
|
XColumnCore
|
||||||
XUserColumn: () => import('./deck.user-column.vue').then(m => m.default),
|
|
||||||
XNoteColumn: () => import('./deck.note-column.vue').then(m => m.default),
|
|
||||||
XHashtagColumn: () => import('./deck.hashtag-column.vue').then(m => m.default)
|
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
@@ -55,10 +48,6 @@ export default Vue.extend({
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
temporaryColumn(): any {
|
|
||||||
return this.$store.state.device.deckTemporaryColumn;
|
|
||||||
},
|
|
||||||
|
|
||||||
keymap(): any {
|
keymap(): any {
|
||||||
return {
|
return {
|
||||||
't': this.focus
|
't': this.focus
|
||||||
@@ -67,8 +56,8 @@ export default Vue.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
temporaryColumn() {
|
$route() {
|
||||||
if (this.temporaryColumn != null) {
|
if (this.$route.name == 'index') return;
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.$refs.body.scrollTo({
|
this.$refs.body.scrollTo({
|
||||||
left: this.$refs.body.scrollWidth - this.$refs.body.clientWidth,
|
left: this.$refs.body.scrollWidth - this.$refs.body.clientWidth,
|
||||||
@@ -76,7 +65,6 @@ export default Vue.extend({
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
provide() {
|
provide() {
|
||||||
@@ -86,8 +74,6 @@ export default Vue.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
created() {
|
created() {
|
||||||
this.$store.commit('navHook', this.onNav);
|
|
||||||
|
|
||||||
if (this.$store.state.settings.deck == null) {
|
if (this.$store.state.settings.deck == null) {
|
||||||
const deck = {
|
const deck = {
|
||||||
columns: [/*{
|
columns: [/*{
|
||||||
@@ -133,8 +119,6 @@ export default Vue.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
this.$store.commit('navHook', null);
|
|
||||||
|
|
||||||
document.documentElement.style.overflow = 'auto';
|
document.documentElement.style.overflow = 'auto';
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -143,39 +127,6 @@ export default Vue.extend({
|
|||||||
return this.$refs[id][0];
|
return this.$refs[id][0];
|
||||||
},
|
},
|
||||||
|
|
||||||
onNav(to) {
|
|
||||||
if (!this.$store.state.settings.deckNav) return false;
|
|
||||||
|
|
||||||
if (to.name == 'user') {
|
|
||||||
this.$store.commit('device/set', {
|
|
||||||
key: 'deckTemporaryColumn',
|
|
||||||
value: {
|
|
||||||
type: 'user',
|
|
||||||
acct: to.params.user
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return true;
|
|
||||||
} else if (to.name == 'note') {
|
|
||||||
this.$store.commit('device/set', {
|
|
||||||
key: 'deckTemporaryColumn',
|
|
||||||
value: {
|
|
||||||
type: 'note',
|
|
||||||
noteId: to.params.note
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return true;
|
|
||||||
} else if (to.name == 'tag') {
|
|
||||||
this.$store.commit('device/set', {
|
|
||||||
key: 'deckTemporaryColumn',
|
|
||||||
value: {
|
|
||||||
type: 'tag',
|
|
||||||
tag: to.params.tag
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
add() {
|
add() {
|
||||||
this.$root.new(Menu, {
|
this.$root.new(Menu, {
|
||||||
source: this.$refs.add,
|
source: this.$refs.add,
|
||||||
@@ -50,7 +50,7 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import i18n from '../../../../i18n';
|
import i18n from '../../../i18n';
|
||||||
import XColumn from './deck.column.vue';
|
import XColumn from './deck.column.vue';
|
||||||
import * as XDraggable from 'vuedraggable';
|
import * as XDraggable from 'vuedraggable';
|
||||||
import * as uuid from 'uuid';
|
import * as uuid from 'uuid';
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<mk-ui>
|
<div class="ecsvsegy" v-if="!fetching">
|
||||||
<main v-if="!fetching">
|
|
||||||
<sequential-entrance animation="entranceFromTop" delay="25">
|
<sequential-entrance animation="entranceFromTop" delay="25">
|
||||||
<template v-for="favorite in favorites">
|
<template v-for="favorite in favorites">
|
||||||
<mk-note-detail class="post" :note="favorite.note" :key="favorite.note.id"/>
|
<mk-note-detail class="post" :note="favorite.note" :key="favorite.note.id"/>
|
||||||
@@ -9,8 +8,7 @@
|
|||||||
<div class="more" v-if="existMore">
|
<div class="more" v-if="existMore">
|
||||||
<ui-button inline @click="more">{{ $t('@.load-more') }}</ui-button>
|
<ui-button inline @click="more">{{ $t('@.load-more') }}</ui-button>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</div>
|
||||||
</mk-ui>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
@@ -72,10 +70,8 @@ export default Vue.extend({
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="stylus" scoped>
|
<style lang="stylus" scoped>
|
||||||
main
|
.ecsvsegy
|
||||||
margin 0 auto
|
margin 0 auto
|
||||||
padding 16px
|
|
||||||
max-width 700px
|
|
||||||
|
|
||||||
> * > .post
|
> * > .post
|
||||||
margin-bottom 16px
|
margin-bottom 16px
|
||||||
54
src/client/app/desktop/views/home/featured.vue
Normal file
54
src/client/app/desktop/views/home/featured.vue
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
<template>
|
||||||
|
<div class="glowckho" v-if="!fetching">
|
||||||
|
<sequential-entrance animation="entranceFromTop" delay="25">
|
||||||
|
<template v-for="note in notes">
|
||||||
|
<mk-note-detail class="post" :note="note" :key="note.id"/>
|
||||||
|
</template>
|
||||||
|
</sequential-entrance>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import Vue from 'vue';
|
||||||
|
import Progress from '../../../common/scripts/loading';
|
||||||
|
|
||||||
|
export default Vue.extend({
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
fetching: true,
|
||||||
|
notes: [],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.fetch();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
fetch() {
|
||||||
|
Progress.start();
|
||||||
|
this.fetching = true;
|
||||||
|
|
||||||
|
this.$root.api('notes/featured', {
|
||||||
|
limit: 20
|
||||||
|
}).then(notes => {
|
||||||
|
this.notes = notes;
|
||||||
|
this.fetching = false;
|
||||||
|
|
||||||
|
Progress.done();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="stylus" scoped>
|
||||||
|
.glowckho
|
||||||
|
margin 0 auto
|
||||||
|
|
||||||
|
> * > .post
|
||||||
|
margin-bottom 16px
|
||||||
|
|
||||||
|
> .more
|
||||||
|
margin 32px 16px 16px 16px
|
||||||
|
text-align center
|
||||||
|
|
||||||
|
</style>
|
||||||
404
src/client/app/desktop/views/home/home.vue
Normal file
404
src/client/app/desktop/views/home/home.vue
Normal file
@@ -0,0 +1,404 @@
|
|||||||
|
<template>
|
||||||
|
<component :is="customize ? 'mk-dummy' : 'mk-ui'" v-hotkey.global="keymap" v-if="$store.getters.isSignedIn || $route.name != 'index'">
|
||||||
|
<div class="wqsofvpm" :data-customize="customize">
|
||||||
|
<div class="customize" v-if="customize">
|
||||||
|
<a @click="done()"><fa icon="check"/>{{ $t('done') }}</a>
|
||||||
|
<div>
|
||||||
|
<div class="adder">
|
||||||
|
<p>{{ $t('add-widget') }}</p>
|
||||||
|
<select v-model="widgetAdderSelected">
|
||||||
|
<option value="profile">{{ $t('@.widgets.profile') }}</option>
|
||||||
|
<option value="analog-clock">{{ $t('@.widgets.analog-clock') }}</option>
|
||||||
|
<option value="calendar">{{ $t('@.widgets.calendar') }}</option>
|
||||||
|
<option value="timemachine">{{ $t('@.widgets.timemachine') }}</option>
|
||||||
|
<option value="activity">{{ $t('@.widgets.activity') }}</option>
|
||||||
|
<option value="rss">{{ $t('@.widgets.rss') }}</option>
|
||||||
|
<option value="trends">{{ $t('@.widgets.trends') }}</option>
|
||||||
|
<option value="photo-stream">{{ $t('@.widgets.photo-stream') }}</option>
|
||||||
|
<option value="slideshow">{{ $t('@.widgets.slideshow') }}</option>
|
||||||
|
<option value="version">{{ $t('@.widgets.version') }}</option>
|
||||||
|
<option value="broadcast">{{ $t('@.widgets.broadcast') }}</option>
|
||||||
|
<option value="notifications">{{ $t('@.widgets.notifications') }}</option>
|
||||||
|
<option value="users">{{ $t('@.widgets.users') }}</option>
|
||||||
|
<option value="polls">{{ $t('@.widgets.polls') }}</option>
|
||||||
|
<option value="post-form">{{ $t('@.widgets.post-form') }}</option>
|
||||||
|
<option value="messaging">{{ $t('@.widgets.messaging') }}</option>
|
||||||
|
<option value="memo">{{ $t('@.widgets.memo') }}</option>
|
||||||
|
<option value="hashtags">{{ $t('@.widgets.hashtags') }}</option>
|
||||||
|
<option value="posts-monitor">{{ $t('@.widgets.posts-monitor') }}</option>
|
||||||
|
<option value="server">{{ $t('@.widgets.server') }}</option>
|
||||||
|
<option value="nav">{{ $t('@.widgets.nav') }}</option>
|
||||||
|
<option value="tips">{{ $t('@.widgets.tips') }}</option>
|
||||||
|
</select>
|
||||||
|
<button @click="addWidget">{{ $t('add') }}</button>
|
||||||
|
</div>
|
||||||
|
<div class="trash">
|
||||||
|
<x-draggable v-model="trash" :options="{ group: 'x' }" @add="onTrash"></x-draggable>
|
||||||
|
<p>{{ $t('@.trash') }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="main" :class="{ side: widgets.left.length == 0 || widgets.right.length == 0 }">
|
||||||
|
<template v-if="customize">
|
||||||
|
<x-draggable v-for="place in ['left', 'right']"
|
||||||
|
:list="widgets[place]"
|
||||||
|
:class="place"
|
||||||
|
:data-place="place"
|
||||||
|
:options="{ group: 'x', animation: 150 }"
|
||||||
|
@sort="onWidgetSort"
|
||||||
|
:key="place"
|
||||||
|
>
|
||||||
|
<div v-for="widget in widgets[place]" class="customize-container" :key="widget.id" @contextmenu.stop.prevent="onWidgetContextmenu(widget.id)">
|
||||||
|
<component :is="`mkw-${widget.name}`" :widget="widget" :ref="widget.id" :is-customize-mode="true" platform="desktop"/>
|
||||||
|
</div>
|
||||||
|
</x-draggable>
|
||||||
|
<div class="main">
|
||||||
|
<a @click="hint">{{ $t('@.customization-tips.title') }}</a>
|
||||||
|
<div>
|
||||||
|
<x-timeline/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<div v-for="place in ['left', 'right']" :class="place">
|
||||||
|
<component v-for="widget in widgets[place]" :is="`mkw-${widget.name}`" :key="widget.id" :ref="widget.id" :widget="widget" platform="desktop"/>
|
||||||
|
</div>
|
||||||
|
<div class="main">
|
||||||
|
<router-view ref="content"></router-view>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</component>
|
||||||
|
<x-welcome v-else/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import Vue from 'vue';
|
||||||
|
import i18n from '../../../i18n';
|
||||||
|
import * as XDraggable from 'vuedraggable';
|
||||||
|
import * as uuid from 'uuid';
|
||||||
|
import XWelcome from '../pages/welcome.vue';
|
||||||
|
|
||||||
|
export default Vue.extend({
|
||||||
|
i18n: i18n('desktop/views/components/home.vue'),
|
||||||
|
components: {
|
||||||
|
XDraggable,
|
||||||
|
XWelcome
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
customize: window.location.search == '?customize',
|
||||||
|
connection: null,
|
||||||
|
widgetAdderSelected: null,
|
||||||
|
trash: [],
|
||||||
|
view: null
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
home(): any[] {
|
||||||
|
if (this.$store.getters.isSignedIn) {
|
||||||
|
return this.$store.state.settings.home || [];
|
||||||
|
} else {
|
||||||
|
return [{
|
||||||
|
name: 'instance',
|
||||||
|
place: 'right'
|
||||||
|
}, {
|
||||||
|
name: 'broadcast',
|
||||||
|
place: 'right',
|
||||||
|
data: {}
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
left(): any[] {
|
||||||
|
return this.home.filter(w => w.place == 'left');
|
||||||
|
},
|
||||||
|
right(): any[] {
|
||||||
|
return this.home.filter(w => w.place == 'right');
|
||||||
|
},
|
||||||
|
widgets(): any {
|
||||||
|
return {
|
||||||
|
left: this.left,
|
||||||
|
right: this.right
|
||||||
|
};
|
||||||
|
},
|
||||||
|
keymap(): any {
|
||||||
|
return {
|
||||||
|
't': this.focus
|
||||||
|
};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
created() {
|
||||||
|
if (this.$store.getters.isSignedIn) {
|
||||||
|
const defaultDesktopHomeWidgets = {
|
||||||
|
left: [
|
||||||
|
'profile',
|
||||||
|
'calendar',
|
||||||
|
'activity',
|
||||||
|
'rss',
|
||||||
|
'hashtags',
|
||||||
|
'photo-stream',
|
||||||
|
'version'
|
||||||
|
],
|
||||||
|
right: [
|
||||||
|
'customize',
|
||||||
|
'broadcast',
|
||||||
|
'notifications',
|
||||||
|
'users',
|
||||||
|
'polls',
|
||||||
|
'server',
|
||||||
|
'nav',
|
||||||
|
'tips'
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
//#region Construct home data
|
||||||
|
const _defaultDesktopHomeWidgets = [];
|
||||||
|
|
||||||
|
for (const widget of defaultDesktopHomeWidgets.left) {
|
||||||
|
_defaultDesktopHomeWidgets.push({
|
||||||
|
name: widget,
|
||||||
|
id: uuid(),
|
||||||
|
place: 'left',
|
||||||
|
data: {}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const widget of defaultDesktopHomeWidgets.right) {
|
||||||
|
_defaultDesktopHomeWidgets.push({
|
||||||
|
name: widget,
|
||||||
|
id: uuid(),
|
||||||
|
place: 'right',
|
||||||
|
data: {}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
//#endregion
|
||||||
|
|
||||||
|
if (this.$store.state.settings.home == null) {
|
||||||
|
this.$root.api('i/update_home', {
|
||||||
|
home: _defaultDesktopHomeWidgets
|
||||||
|
}).then(() => {
|
||||||
|
this.$store.commit('settings/setHome', _defaultDesktopHomeWidgets);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
this.connection = this.$root.stream.useSharedConnection('main');
|
||||||
|
},
|
||||||
|
|
||||||
|
beforeDestroy() {
|
||||||
|
this.connection.dispose();
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
hint() {
|
||||||
|
this.$root.dialog({
|
||||||
|
title: this.$t('@.customization-tips.title'),
|
||||||
|
text: this.$t('@.customization-tips.paragraph')
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
onTlLoaded() {
|
||||||
|
this.$emit('loaded');
|
||||||
|
},
|
||||||
|
|
||||||
|
onWidgetContextmenu(widgetId) {
|
||||||
|
const w = (this.$refs[widgetId] as any)[0];
|
||||||
|
if (w.func) w.func();
|
||||||
|
},
|
||||||
|
|
||||||
|
onWidgetSort() {
|
||||||
|
this.saveHome();
|
||||||
|
},
|
||||||
|
|
||||||
|
onTrash(evt) {
|
||||||
|
this.saveHome();
|
||||||
|
},
|
||||||
|
|
||||||
|
addWidget() {
|
||||||
|
this.$store.dispatch('settings/addHomeWidget', {
|
||||||
|
name: this.widgetAdderSelected,
|
||||||
|
id: uuid(),
|
||||||
|
place: 'left',
|
||||||
|
data: {}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
saveHome() {
|
||||||
|
const left = this.widgets.left;
|
||||||
|
const right = this.widgets.right;
|
||||||
|
this.$store.commit('settings/setHome', left.concat(right));
|
||||||
|
for (const w of left) w.place = 'left';
|
||||||
|
for (const w of right) w.place = 'right';
|
||||||
|
this.$root.api('i/update_home', {
|
||||||
|
home: this.home
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
done() {
|
||||||
|
location.href = '/';
|
||||||
|
},
|
||||||
|
|
||||||
|
focus() {
|
||||||
|
(this.$refs.content as any).focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="stylus" scoped>
|
||||||
|
.wqsofvpm
|
||||||
|
display block
|
||||||
|
|
||||||
|
&[data-customize]
|
||||||
|
padding-top 48px
|
||||||
|
background-image url('/assets/desktop/grid.svg')
|
||||||
|
|
||||||
|
> .main > .main
|
||||||
|
> a
|
||||||
|
display block
|
||||||
|
margin-bottom 8px
|
||||||
|
text-align center
|
||||||
|
|
||||||
|
> div
|
||||||
|
cursor not-allowed !important
|
||||||
|
|
||||||
|
> *
|
||||||
|
pointer-events none
|
||||||
|
|
||||||
|
&:not([data-customize])
|
||||||
|
> .main > *:not(.main):empty
|
||||||
|
display none
|
||||||
|
|
||||||
|
> .customize
|
||||||
|
position fixed
|
||||||
|
z-index 1000
|
||||||
|
top 0
|
||||||
|
left 0
|
||||||
|
width 100%
|
||||||
|
height 48px
|
||||||
|
color var(--text)
|
||||||
|
background var(--desktopHeaderBg)
|
||||||
|
box-shadow 0 1px 1px rgba(#000, 0.075)
|
||||||
|
|
||||||
|
> a
|
||||||
|
display block
|
||||||
|
position absolute
|
||||||
|
z-index 1001
|
||||||
|
top 0
|
||||||
|
right 0
|
||||||
|
padding 0 16px
|
||||||
|
line-height 48px
|
||||||
|
text-decoration none
|
||||||
|
color var(--primaryForeground)
|
||||||
|
background var(--primary)
|
||||||
|
transition background 0.1s ease
|
||||||
|
|
||||||
|
&:hover
|
||||||
|
background var(--primaryLighten10)
|
||||||
|
|
||||||
|
&:active
|
||||||
|
background var(--primaryDarken10)
|
||||||
|
transition background 0s ease
|
||||||
|
|
||||||
|
> [data-icon]
|
||||||
|
margin-right 8px
|
||||||
|
|
||||||
|
> div
|
||||||
|
display flex
|
||||||
|
margin 0 auto
|
||||||
|
max-width 1220px - 32px
|
||||||
|
|
||||||
|
> div
|
||||||
|
width 50%
|
||||||
|
|
||||||
|
&.adder
|
||||||
|
> p
|
||||||
|
display inline
|
||||||
|
line-height 48px
|
||||||
|
|
||||||
|
&.trash
|
||||||
|
border-left solid 1px var(--faceDivider)
|
||||||
|
|
||||||
|
> div
|
||||||
|
width 100%
|
||||||
|
height 100%
|
||||||
|
|
||||||
|
> p
|
||||||
|
position absolute
|
||||||
|
top 0
|
||||||
|
left 0
|
||||||
|
width 100%
|
||||||
|
line-height 48px
|
||||||
|
margin 0
|
||||||
|
text-align center
|
||||||
|
pointer-events none
|
||||||
|
|
||||||
|
> .main
|
||||||
|
display flex
|
||||||
|
justify-content center
|
||||||
|
margin 0 auto
|
||||||
|
max-width 1240px
|
||||||
|
|
||||||
|
> *
|
||||||
|
.customize-container
|
||||||
|
cursor move
|
||||||
|
border-radius 6px
|
||||||
|
|
||||||
|
&:hover
|
||||||
|
box-shadow 0 0 8px rgba(64, 120, 200, 0.3)
|
||||||
|
|
||||||
|
> *
|
||||||
|
pointer-events none
|
||||||
|
|
||||||
|
> .main
|
||||||
|
padding 16px
|
||||||
|
width calc(100% - 280px * 2)
|
||||||
|
order 2
|
||||||
|
|
||||||
|
&.side
|
||||||
|
> .main
|
||||||
|
width calc(100% - 280px)
|
||||||
|
max-width 680px
|
||||||
|
|
||||||
|
> *:not(.main)
|
||||||
|
width 280px
|
||||||
|
padding 16px 0 16px 0
|
||||||
|
|
||||||
|
> *:not(:last-child)
|
||||||
|
margin-bottom 16px
|
||||||
|
|
||||||
|
> .left
|
||||||
|
padding-left 16px
|
||||||
|
order 1
|
||||||
|
|
||||||
|
> .right
|
||||||
|
padding-right 16px
|
||||||
|
order 3
|
||||||
|
|
||||||
|
&.side
|
||||||
|
@media (max-width 1000px)
|
||||||
|
> *:not(.main)
|
||||||
|
display none
|
||||||
|
|
||||||
|
> .main
|
||||||
|
width 100%
|
||||||
|
max-width 700px
|
||||||
|
margin 0 auto
|
||||||
|
|
||||||
|
&:not(.side)
|
||||||
|
@media (max-width 1200px)
|
||||||
|
> *:not(.main)
|
||||||
|
display none
|
||||||
|
|
||||||
|
> .main
|
||||||
|
width 100%
|
||||||
|
max-width 700px
|
||||||
|
margin 0 auto
|
||||||
|
|
||||||
|
</style>
|
||||||
@@ -1,13 +1,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<mk-ui>
|
<div v-if="!fetching" class="kcthdwmv">
|
||||||
<main v-if="!fetching">
|
|
||||||
<mk-note-detail :note="note"/>
|
<mk-note-detail :note="note"/>
|
||||||
<footer>
|
<footer>
|
||||||
<router-link v-if="note.next" :to="note.next"><fa icon="angle-left"/> {{ $t('next') }}</router-link>
|
<router-link v-if="note.next" :to="note.next"><fa icon="angle-left"/> {{ $t('next') }}</router-link>
|
||||||
<router-link v-if="note.prev" :to="note.prev">{{ $t('prev') }} <fa icon="angle-right"/></router-link>
|
<router-link v-if="note.prev" :to="note.prev">{{ $t('prev') }} <fa icon="angle-right"/></router-link>
|
||||||
</footer>
|
</footer>
|
||||||
</main>
|
</div>
|
||||||
</mk-ui>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
@@ -48,8 +46,7 @@ export default Vue.extend({
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="stylus" scoped>
|
<style lang="stylus" scoped>
|
||||||
main
|
.kcthdwmv
|
||||||
padding 16px
|
|
||||||
text-align center
|
text-align center
|
||||||
|
|
||||||
> footer
|
> footer
|
||||||
@@ -59,8 +56,4 @@ main
|
|||||||
display inline-block
|
display inline-block
|
||||||
margin 0 16px
|
margin 0 16px
|
||||||
|
|
||||||
> .mk-note-detail
|
|
||||||
margin 0 auto
|
|
||||||
width 640px
|
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
@@ -1,12 +1,14 @@
|
|||||||
<template>
|
<template>
|
||||||
<mk-ui>
|
<div class="oxgbmvii">
|
||||||
<header :class="$style.header">
|
<div class="notes">
|
||||||
<h1>{{ q }}</h1>
|
<header>
|
||||||
|
<span><fa icon="search"/> {{ q }}</span>
|
||||||
</header>
|
</header>
|
||||||
<p :class="$style.notAvailable" v-if="!fetching && notAvailable">{{ $t('not-available') }}</p>
|
<p v-if="!fetching && notAvailable">{{ $t('not-available') }}</p>
|
||||||
<p :class="$style.empty" v-if="!fetching && empty"><fa icon="search"/> {{ $t('not-found', { q }) }}</p>
|
<p v-if="!fetching && empty"><fa icon="search"/> {{ $t('not-found', { q }) }}</p>
|
||||||
<mk-notes ref="timeline" :class="$style.notes" :more="existMore ? more : null"/>
|
<mk-notes ref="timeline" :more="existMore ? more : null"/>
|
||||||
</mk-ui>
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
@@ -106,45 +108,23 @@ export default Vue.extend({
|
|||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="stylus" module>
|
<style lang="stylus" scoped>
|
||||||
.header
|
.oxgbmvii
|
||||||
width 100%
|
> .notes
|
||||||
max-width 600px
|
background var(--face)
|
||||||
margin 0 auto
|
box-shadow var(--shadow)
|
||||||
color #555
|
border-radius var(--round)
|
||||||
|
|
||||||
.notes
|
|
||||||
max-width 600px
|
|
||||||
margin 0 auto
|
|
||||||
border solid 1px rgba(#000, 0.075)
|
|
||||||
border-radius 6px
|
|
||||||
overflow hidden
|
overflow hidden
|
||||||
|
|
||||||
.empty
|
> header
|
||||||
display block
|
padding 0 8px
|
||||||
margin 0 auto
|
z-index 10
|
||||||
padding 32px
|
background var(--faceHeader)
|
||||||
max-width 400px
|
box-shadow 0 var(--lineWidth) var(--desktopTimelineHeaderShadow)
|
||||||
text-align center
|
|
||||||
color #999
|
|
||||||
|
|
||||||
> [data-icon]
|
> span
|
||||||
display block
|
padding 0 8px
|
||||||
margin-bottom 16px
|
font-size 0.9em
|
||||||
font-size 3em
|
line-height 42px
|
||||||
color #ccc
|
color var(--text)
|
||||||
|
|
||||||
.notAvailable
|
|
||||||
display block
|
|
||||||
margin 0 auto
|
|
||||||
padding 32px
|
|
||||||
max-width 400px
|
|
||||||
text-align center
|
|
||||||
color #999
|
|
||||||
|
|
||||||
> [data-icon]
|
|
||||||
display block
|
|
||||||
margin-bottom 16px
|
|
||||||
font-size 3em
|
|
||||||
color #ccc
|
|
||||||
</style>
|
</style>
|
||||||
@@ -1,11 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<mk-ui>
|
<div>
|
||||||
<header :class="$style.header">
|
|
||||||
<h1>#{{ $route.params.tag }}</h1>
|
|
||||||
</header>
|
|
||||||
<p :class="$style.empty" v-if="!fetching && empty"><fa icon="search"/> {{ $t('no-posts-found', { q: $route.params.tag }) }}</p>
|
<p :class="$style.empty" v-if="!fetching && empty"><fa icon="search"/> {{ $t('no-posts-found', { q: $route.params.tag }) }}</p>
|
||||||
<mk-notes ref="timeline" :class="$style.notes" :more="existMore ? more : null"/>
|
<mk-notes ref="timeline" :class="$style.notes" :more="existMore ? more : null"/>
|
||||||
</mk-ui>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
@@ -96,17 +93,10 @@ export default Vue.extend({
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="stylus" module>
|
<style lang="stylus" module>
|
||||||
.header
|
|
||||||
width 100%
|
|
||||||
max-width 600px
|
|
||||||
margin 0 auto
|
|
||||||
color #555
|
|
||||||
|
|
||||||
.notes
|
.notes
|
||||||
width 600px
|
background var(--face)
|
||||||
margin 0 auto
|
box-shadow var(--shadow)
|
||||||
border solid 1px rgba(#000, 0.075)
|
border-radius var(--round)
|
||||||
border-radius 6px
|
|
||||||
overflow hidden
|
overflow hidden
|
||||||
|
|
||||||
.empty
|
.empty
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user