1
0
mirror of https://github.com/misskey-dev/misskey.git synced 2026-07-13 06:04:43 +02:00

Compare commits

..

69 Commits

Author SHA1 Message Date
syuilo
b780ea336c 6.2.0 2018-08-17 00:39:30 +09:00
syuilo
bd9f589d32 Merge pull request #2255 from syuilo/l10n_master
New Crowdin translations
2018-08-17 00:38:30 +09:00
syuilo
d9d18bd8f9 New translations ja.yml (English) 2018-08-17 00:33:59 +09:00
syuilo
ffdaa6bc56 Use thumbnail 2018-08-17 00:27:36 +09:00
syuilo
c7f60e337e New translations ja.yml (English) 2018-08-17 00:23:38 +09:00
syuilo
7f265dbd52 New translations ja.yml (Catalan) 2018-08-17 00:22:15 +09:00
syuilo
8929c5cabc New translations ja.yml (Portuguese) 2018-08-17 00:22:12 +09:00
syuilo
4a610f3b0a New translations ja.yml (Korean) 2018-08-17 00:22:09 +09:00
syuilo
55ec19edb5 New translations ja.yml (Polish) 2018-08-17 00:22:07 +09:00
syuilo
c319c61832 New translations ja.yml (Chinese Simplified) 2018-08-17 00:22:05 +09:00
syuilo
66db99b8cd New translations ja.yml (Italian) 2018-08-17 00:22:02 +09:00
syuilo
ff2162974d New translations ja.yml (Russian) 2018-08-17 00:22:00 +09:00
syuilo
78e86af086 New translations ja.yml (English) 2018-08-17 00:21:57 +09:00
syuilo
2dcf89eecf New translations ja.yml (Spanish) 2018-08-17 00:21:55 +09:00
syuilo
fdf94be998 New translations ja.yml (German) 2018-08-17 00:21:53 +09:00
syuilo
0e913a5727 New translations ja.yml (French) 2018-08-17 00:21:50 +09:00
syuilo
f3be077adc Fix bug 2018-08-17 00:19:27 +09:00
syuilo
a6e0471f8c ✌️ 2018-08-17 00:13:52 +09:00
syuilo
c5d734f9ad 6.1.0 2018-08-17 00:09:01 +09:00
syuilo
ee12d887ae typo 2018-08-17 00:07:23 +09:00
syuilo
b78d24be1e Fix bug 2018-08-17 00:05:57 +09:00
syuilo
d5379e2b36 autoWatchをデフォルトでfalseに 2018-08-17 00:04:07 +09:00
syuilo
cf36557084 New translations ja.yml (Catalan) 2018-08-17 00:00:54 +09:00
syuilo
fd1ee129dc New translations ja.yml (Portuguese) 2018-08-17 00:00:51 +09:00
syuilo
1471b7a6b5 New translations ja.yml (Korean) 2018-08-17 00:00:49 +09:00
syuilo
1d39d7efcb New translations ja.yml (Polish) 2018-08-17 00:00:46 +09:00
syuilo
69ee97f6e2 New translations ja.yml (Chinese Simplified) 2018-08-17 00:00:44 +09:00
syuilo
12092e6083 New translations ja.yml (Italian) 2018-08-17 00:00:41 +09:00
syuilo
6e29e40b8b New translations ja.yml (Russian) 2018-08-17 00:00:39 +09:00
syuilo
842c9e735b New translations ja.yml (English) 2018-08-17 00:00:37 +09:00
syuilo
2f63a25058 New translations ja.yml (Spanish) 2018-08-17 00:00:33 +09:00
syuilo
d3b084003c New translations ja.yml (German) 2018-08-17 00:00:31 +09:00
syuilo
0da9d3d8b0 New translations ja.yml (French) 2018-08-17 00:00:27 +09:00
syuilo
58f3c6aab7 Merge branch 'master' of https://github.com/syuilo/misskey 2018-08-16 23:59:25 +09:00
syuilo
22e79675ad #2263 2018-08-16 23:59:22 +09:00
syuilo
e5c350d740 Fix bug 2018-08-16 23:33:11 +09:00
syuilo
210124ac34 New translations ja.yml (English) 2018-08-16 21:24:31 +09:00
syuilo
7f9a35d7ac Improve object storage key 2018-08-16 21:23:31 +09:00
syuilo
71a30f9001 New translations ja.yml (Korean) 2018-08-16 21:02:39 +09:00
syuilo
95a34d55fb New translations ja.yml (English) 2018-08-16 21:02:36 +09:00
syuilo
34f052b672 New translations ja.yml (Korean) 2018-08-16 20:51:53 +09:00
syuilo
0178c2e696 New translations ja.yml (English) 2018-08-16 20:51:51 +09:00
syuilo
5cb0c07627 New translations ja.yml (English) 2018-08-16 20:24:07 +09:00
syuilo
d8fdbfe164 New translations ja.yml (English) 2018-08-16 20:11:53 +09:00
syuilo
74e0b2734d New translations ja.yml (English) 2018-08-16 20:06:07 +09:00
syuilo
3f5785bd03 New translations ja.yml (English) 2018-08-16 17:43:46 +09:00
syuilo
15e5c69c15 New translations ja.yml (English) 2018-08-16 17:32:01 +09:00
syuilo
57019c0b40 New translations ja.yml (English) 2018-08-16 09:01:03 +09:00
syuilo
9d6641be3a Fix bug 2018-08-16 08:18:41 +09:00
syuilo
ac15c2e71f Fix bug 2018-08-16 08:11:21 +09:00
syuilo
1fc9206c6d 6.0.0 2018-08-16 08:02:50 +09:00
syuilo
a8fb0d477f Merge pull request #2251 from syuilo/provide-thumbnails
Provide drive file thumbnails
2018-08-16 07:59:16 +09:00
syuilo
0c372b68d4 Merge pull request #2252 from syuilo/greenkeeper/minio-7.0.0
Update minio to the latest version 🚀
2018-08-16 07:58:56 +09:00
syuilo
e7d9018944 ✌️ 2018-08-16 07:56:53 +09:00
syuilo
ce16884587 Update example.yml 2018-08-16 07:31:58 +09:00
greenkeeper[bot]
3345733d00 fix(package): update minio to version 7.0.0 2018-08-15 22:26:17 +00:00
greenkeeper[bot]
f91cccb6b1 fix(package): update @types/webpack to version 4.4.10 2018-08-16 07:24:19 +09:00
syuilo
6183262037 wip 2018-08-16 07:17:04 +09:00
syuilo
1c7a194950 wip 2018-08-16 06:27:35 +09:00
greenkeeper[bot]
286e15b967 fix(package): update @types/node to version 10.7.1 2018-08-16 06:08:15 +09:00
syuilo
744d366874 Merge pull request #2248 from syuilo/new-kao
Add new kao
2018-08-16 05:17:56 +09:00
Aya Morisawa
afa62d3d44 Add new kao 2018-08-16 05:17:00 +09:00
Aya Morisawa
270c7997c6 Remove trailing comma 2018-08-16 05:15:51 +09:00
Aya Morisawa
fa95641f88 Use Array.prototype.length to avoid magic number 2018-08-16 05:15:06 +09:00
syuilo
aa9fe38c25 Merge pull request #2247 from syuilo/clickable-reaction
Make reactions in reactions-viewer clickable
2018-08-16 05:00:13 +09:00
Aya Morisawa
0d33cbbbbb Make reactions in reactions-viewer clickable 2018-08-16 04:57:09 +09:00
syuilo
bf077da72f Trim code 2018-08-16 04:42:44 +09:00
syuilo
d8f8e19d06 Merge pull request #2246 from mei23/mei-0816-player
動画プレーヤーの修正
2018-08-16 03:17:41 +09:00
mei23
3c3d3e4c0c Fix url-preview.vue 2018-08-16 03:06:59 +09:00
48 changed files with 466 additions and 225 deletions

View File

@@ -50,7 +50,10 @@ remoteDriveCapacityMb: 8
# If enabled:
# Server will not cache remote files (Using direct link instead).
# You can save your storage.
# Users cannot see remote images when they turn off "Show media from a remote server" setting.
#
# NOTE:
# * Users cannot see remote images when they turn off "Show media from a remote server" setting.
# * Since thumbnails are not provided, traffic increases.
preventCacheRemoteFiles: false
drive:

View File

@@ -5,6 +5,15 @@ ChangeLog
This document describes breaking changes only.
6.0.0
-----
### Migration
オブジェクトストレージを使用している場合、設定ファイルの`drive.config.secure``drive.config.useSSL`にリネームしてください。
If you use object storage, please rename `drive.config.secure` to `drive.config.useSSL` in config.
5.0.0
-----

View File

@@ -627,7 +627,8 @@ desktop/views/components/settings.vue:
post-form-on-timeline: "タイムライン上部に投稿フォームを表示する"
show-reply-target: "リプライ先を表示する"
show-my-renotes: "自分の行ったRenoteをタイムラインに表示する"
show-renoted-my-notes: "Renoteされた自分の投稿をタイムラインに表示する"
show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する"
show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する"
show-maps: "マップの自動展開"
show-maps-desc: "位置情報が添付された投稿のマップを自動的に展開します。"
sound: "サウンド"
@@ -1106,7 +1107,8 @@ mobile/views/pages/settings.vue:
timeline: "タイムライン"
show-reply-target: "リプライ先を表示する"
show-my-renotes: "自分の行ったRenoteを表示する"
show-renoted-my-notes: "Renoteされた自分の投稿を表示する"
show-renoted-my-notes: "自分の投稿のRenoteを表示する"
show-local-renotes: "ローカルの投稿のRenoteを表示する"
post-style: "投稿の表示スタイル"
post-style-standard: "標準"
post-style-smart: "スマート"

View File

@@ -627,7 +627,8 @@ desktop/views/components/settings.vue:
post-form-on-timeline: "タイムライン上部に投稿フォームを表示する"
show-reply-target: "Zeige Antworten"
show-my-renotes: "Zeige meine Reposts auf der Zeitleiste"
show-renoted-my-notes: "Zeige meine Reposts, die geteilt wurden, auf der Zeitleiste"
show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する"
show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する"
show-maps: "Karte anzeigen"
show-maps-desc: "Zeige den Standort zu diesem Beitrag automatisch an."
sound: "Ton"
@@ -1106,7 +1107,8 @@ mobile/views/pages/settings.vue:
timeline: "タイムライン"
show-reply-target: "リプライ先を表示する"
show-my-renotes: "自分の行ったRenoteを表示する"
show-renoted-my-notes: "Renoteされた自分の投稿を表示する"
show-renoted-my-notes: "自分の投稿のRenoteを表示する"
show-local-renotes: "ローカルの投稿のRenoteを表示する"
post-style: "投稿の表示スタイル"
post-style-standard: "標準"
post-style-smart: "スマート"

View File

@@ -16,7 +16,7 @@ common:
customization-tips:
title: "Customization tips"
paragraph1: "Home customization allows you to add/delete, drag and drop and rearrange widgets."
paragraph2: "You can change the display by <strong>right clicking</strong> on some widgets."
paragraph2: "You can change the display by <strong><strong>right</strong> clicking</strong> on some widgets."
paragraph3: "To delete a widget, drag and drop the widget onto <strong>the area labeled \"Trash\"</strong> in the header."
paragraph4: "To finish the customization, click \"Finish\" on the upper right."
gotit: "Got it!"
@@ -141,11 +141,11 @@ common:
auth/views/form.vue:
share-access: "Would you <b>allow</b> <i>{{ app.name }}</i> to access your account?"
permission-ask: "This application requires the following permissions:"
account-read: "Viewing account information:"
account-write: "Modify account informations:"
account-read: "View account information."
account-write: "Modify account information."
note-write: "Post."
like-write: "To react to posts."
following-write: "Follow or unfollow."
like-write: "React to posts."
following-write: "Follow and unfollow."
drive-read: "Read your drive."
drive-write: "Upload/delete files in your drive."
notification-read: "Read your notifications."
@@ -154,10 +154,10 @@ auth/views/form.vue:
accept: "Allow access."
auth/views/index.vue:
loading: "Loading"
denied: "Application authorization denied."
denied: "Application authorization has been denied."
denied-paragraph: "This application will not access your account."
already-authorized: "This application has already been authorized."
allowed: "Application authorizations allowed.+"
allowed: "Application authorizations allowed."
callback-url: "Going back to the application."
please-go-back: "Please go back to the application."
error: "Session does not exist."
@@ -169,7 +169,7 @@ common/views/components/games/reversi/reversi.vue:
common/views/components/games/reversi/reversi.game.vue:
surrender: "Surrender"
surrendered: "By surrender"
is-llotheo: "The lesser one wins"
is-llotheo: "The lesser one wins(Llotheo)"
looped-map: "Looped map"
can-put-everywhere: "Can put everywhere"
common/views/components/games/reversi/reversi.index.vue:
@@ -200,7 +200,7 @@ common/views/components/games/reversi/reversi.room.vue:
settings-of-the-bot: "Bot settings"
this-game-is-started-soon: "The game will begin in seconds"
waiting-for-other: "Waiting for the opponent"
waiting-for-me: "Waiting for you"
waiting-for-me: "Waiting for the your preparation"
waiting-for-both: "Prepareing"
cancel: "Cancel"
ready: "Ready"
@@ -226,7 +226,7 @@ common/views/components/connect-failed.troubleshooter.vue:
no-server: "Unable to connect to the Misskey server"
no-server-desc: "The network connection of your device is normal, but you could not connect to the Misskey server. There is a possibility that the server is either down, or under maintenance, please try again later."
success: "Successfully connected to the Misskey server"
success-desc: "It seems to be able to connect. Please reload the page."
success-desc: "Looks like we have a connection. Please reload the page."
flush: "Clean cache"
set-version: "Specify version"
common/views/components/messaging.vue:
@@ -388,8 +388,8 @@ common/views/widgets/tips.vue:
tips-line20: "The percentage of the calendar widget shows the percentage of time elapsed."
tips-line21: "You can also use the API to develop bots."
tips-line23: "Mayu is so cute with its eyebrows."
tips-line24: "Misskey started in 2014."
tips-line25: "You can receive notification even if Misskey is not open in a compatible browser."
tips-line24: "Misskey has been running since 2014."
tips-line25: "In a browser compatible with notification features, you can receive notifications in case Misskey is not open"
common/views/pages/follow.vue:
signed-in-as: "Signed in as {}"
following: "Following"
@@ -470,7 +470,7 @@ desktop/views/components/drive.nav-folder.vue:
desktop/views/components/drive.vue:
search: "Search"
load-more: "Load more"
empty-draghover: "Drop it here, don't I look cute?"
empty-draghover: "Drop it here! Yep, cuz you know I'm cute, right?"
empty-drive: "Your media storage is empty"
empty-drive-description: "Right-click to open the menu, or drag and drop a file onto here for uploading."
empty-folder: "This folder is empty"
@@ -480,7 +480,7 @@ desktop/views/components/drive.vue:
url-upload: "Upload from a URL"
url-of-file: "URL of file you want to upload"
url-upload-requested: "Upload requested"
may-take-time: "It may take some time for the upload to complete."
may-take-time: "It may take some time until the upload is complete."
create-folder: "Create a folder"
folder-name: "Folder name"
contextmenu:
@@ -505,7 +505,7 @@ desktop/views/components/followers.vue:
desktop/views/components/following-window.vue:
following: "Following {}"
desktop/views/components/following.vue:
empty: "You dont follow anyone."
empty: "It seems you don't have any following users…"
desktop/views/components/friends-maker.vue:
title: "Recommended users:"
empty: "Couldn't find any recommended users."
@@ -554,7 +554,7 @@ desktop/views/components/post-form.vue:
add-visible-user: "+Add a user"
attach-location-information: "Attach location information"
hide-contents: "Hide contents"
reply-placeholder: "Reply to this Post..."
reply-placeholder: "Reply to this post..."
quote-placeholder: "Quote this Post..."
submit: "Post"
reply: "Reply"
@@ -575,7 +575,7 @@ desktop/views/components/post-form.vue:
recent-tags: "Recent"
click-to-tagging: "Click to tagging"
visibility: "Visibility"
geolocation-alert: "Your device can not measure location infomation"
geolocation-alert: "Your device does not provide location services."
error: "Error"
enter-username: "Please enter a username..."
annotations: "Annotations for the post (optional)"
@@ -613,7 +613,7 @@ desktop/views/components/settings.vue:
fetch-on-scroll: "Endless loading on scroll"
fetch-on-scroll-desc: "When you scroll down the page, it automatically fetches additional content."
auto-popout: "Auto pop-out window"
auto-popout-desc: "Pops-out a newly opened window (onto a new tab), if possible. This setting is stored in the browser."
auto-popout-desc: "If it's possible, pop-out display will be used instead of opening a new window. This setting is stored in your browser."
advanced: "Advanced settings"
api-via-stream: "API request via stream"
api-via-stream-desc: "API request is performed via the WebSocket connection instead of native fetch API (for better performance). This setting is stored in the browser."
@@ -626,9 +626,10 @@ desktop/views/components/settings.vue:
gradient-window-header: "Use gradients on window headers"
post-form-on-timeline: "Display post form at the top of the timeline"
show-reply-target: "Display reply target"
show-my-renotes: "Show my reposts in the timeline"
show-renoted-my-notes: "Show my posts that have been shared in the timeline"
show-maps: "Show the map"
show-my-renotes: "Show my renotes in the timeline"
show-renoted-my-notes: "Show renoted my posts in timelines"
show-local-renotes: "Show renoted local posts in timelines"
show-maps: "Display a map to show the location"
show-maps-desc: "Automatically show the location on the map attached to this post."
sound: "Sound"
enable-sounds: "Enable sound"
@@ -674,18 +675,18 @@ desktop/views/components/settings.vue:
third-parties: "Third-parties"
desktop/views/components/settings.2fa.vue:
intro: "If you set up 2-step verification, you will not only need a password at sign-in, but also a pre-registered physical device (such as your smartphone), which will improve security."
detail: "See details..."
detail: "Details"
url: "https://www.google.com/landing/2step/"
caution: "If you lose access to your device, you won't be able to connect to Misskey anymore!"
caution: "If you lose access to your registered device, you won't be able to connect to Misskey anymore!"
register: "Register a device"
already-registered: "A device is already registered"
unregister: "Disable"
already-registered: "This device is already registered"
unregister: "Unregister"
unregistered: "Two-factor authentication has been disabled."
enter-password: "Enter the password"
authenticator: "First, you need to install Google Authenticator on your device:"
howtoinstall: "How to install"
scan: "And then, scan the QR code:"
done: "Please enter the token displaying on your device:"
done: "Please enter the token displayed on your device:"
submit: "Submit"
success: "Settings saved!"
failed: "Failed to setup. Please ensure that the token is correct."
@@ -693,15 +694,15 @@ desktop/views/components/settings.2fa.vue:
desktop/views/components/settings.api.vue:
intro: "To access the API, set this token as the key 'i' of request parameters."
caution: "Do not enter this token to any apps nor tell this token to others otherwise your account may get compromised."
regeneration-of-token: "In case this token (may) leaks out, you want to regenerate it so that youll be safe."
regeneration-of-token: "If your token gets leaked, you can regenerate it."
regenerate-token: "Regenerate the token"
token: "Token:"
enter-password: "Please enter the password"
desktop/views/components/settings.apps.vue:
no-apps: "No linked applications"
desktop/views/components/settings.drive.vue:
max: "Max "
in-use: " in use."
max: "Max"
in-use: "In use"
desktop/views/components/settings.mute.vue:
no-users: "No muted users"
desktop/views/components/settings.password.vue:
@@ -724,7 +725,7 @@ desktop/views/components/settings.profile.vue:
other: "Other"
is-bot: "This account is a Bot"
is-cat: "This account is a Cat"
profile-updated: "Profile has successfully updated"
profile-updated: "Your profile has been updated"
desktop/views/components/sub-note-content.vue:
private: "This post is private"
deleted: "This post has been deleted"
@@ -740,7 +741,7 @@ desktop/views/components/timeline.vue:
list: "Lists"
desktop/views/components/ui.header.vue:
welcome-back: "Welcome back,"
adjective: "Sir "
adjective: "-san"
desktop/views/components/ui.header.account.vue:
profile: "Your profile"
drive: "Media storage"
@@ -835,7 +836,7 @@ desktop/views/pages/selectdrive.vue:
cancel: "Cancel"
upload: "Upload files from your device"
desktop/views/pages/search.vue:
not-available: "The search feature is not available."
not-available: "The search feature is not available for now."
not-found: "No posts were found for '{}'"
desktop/views/pages/share.vue:
share-with: "Share with {}."
@@ -855,7 +856,7 @@ desktop/views/pages/user/user.friends.vue:
no-users: "No frequent mentions"
desktop/views/pages/user/user.vue:
is-suspended: "This account has been suspended."
is-remote: "The user is a remote user. Information about them that you see here may not complete."
is-remote: "The user is a remote user. The profile that you see here may not complete."
view-remote: "See their complete profile"
desktop/views/pages/user/user.home.vue:
last-used-at: "Last active:"
@@ -1106,7 +1107,8 @@ mobile/views/pages/settings.vue:
timeline: "Timeline"
show-reply-target: "Show reply target"
show-my-renotes: "Show my reposts"
show-renoted-my-notes: "Show my reposted posts"
show-renoted-my-notes: "Show renoted my posts"
show-local-renotes: "Show renoted local posts"
post-style: "Post design"
post-style-standard: "Standard"
post-style-smart: "Smart"
@@ -1163,7 +1165,7 @@ mobile/views/pages/user/home.photos.vue:
loading: "Loading"
no-photos: "No photos"
docs:
edit-this-page-on-github: "Did you find an error or do you want to contribute to the documentation? "
edit-this-page-on-github: "Found a mistake or want to contribute for the documentation?"
edit-this-page-on-github-link: "Edit this page on Github!"
api:
entities:
@@ -1175,11 +1177,11 @@ docs:
require-credential: "This endpoint requires the authentication information."
require-permission: "This endpoint requires {permission} permission."
has-limit: "There is a rate limit."
duration-limit: "You can't request when a frequency of a request in during {duration} milliseconds exceeds {max} times."
min-interval-limit: "You can't request before {interval} milliseconds have passed since the previous request."
duration-limit: "If you have sent your requests more than {max} times in {duration} milliseconds, you will be unable to send more requests."
min-interval-limit: "If {interval} milliseconds haven't passed since the last request, you can't send a request."
show-src: "You can view the source code for this endpoint."
show-src-link: "See the code on GitHub"
generated: "This doc is generated by an API definition."
generated: "This document is generated by the API definition."
props:
name: "Name"
type: "Type"

View File

@@ -627,7 +627,8 @@ desktop/views/components/settings.vue:
post-form-on-timeline: "Mostrar el formulario de las entradas encima de la línea de tiempo"
show-reply-target: "リプライ先を表示する"
show-my-renotes: "自分の行ったRenoteをタイムラインに表示する"
show-renoted-my-notes: "Renoteされた自分の投稿をタイムラインに表示する"
show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する"
show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する"
show-maps: "マップの自動展開"
show-maps-desc: "位置情報が添付された投稿のマップを自動的に展開します。"
sound: "サウンド"
@@ -1106,7 +1107,8 @@ mobile/views/pages/settings.vue:
timeline: "タイムライン"
show-reply-target: "リプライ先を表示する"
show-my-renotes: "自分の行ったRenoteを表示する"
show-renoted-my-notes: "Renoteされた自分の投稿を表示する"
show-renoted-my-notes: "自分の投稿のRenoteを表示する"
show-local-renotes: "ローカルの投稿のRenoteを表示する"
post-style: "投稿の表示スタイル"
post-style-standard: "標準"
post-style-smart: "スマート"

View File

@@ -627,7 +627,8 @@ desktop/views/components/settings.vue:
post-form-on-timeline: "タイムライン上部に投稿フォームを表示する"
show-reply-target: "Afficher les réponses"
show-my-renotes: "Afficher mes republications dans le fil"
show-renoted-my-notes: "Renoteされた自分の投稿をタイムラインに表示する"
show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する"
show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する"
show-maps: "Afficher la carte"
show-maps-desc: "位置情報が添付された投稿のマップを自動的に展開します。"
sound: "Son"
@@ -1106,7 +1107,8 @@ mobile/views/pages/settings.vue:
timeline: "Fil d'actualité"
show-reply-target: "Afficher les réponses"
show-my-renotes: "Afficher mes republications"
show-renoted-my-notes: "Afficher les notes que j'ai repartagé"
show-renoted-my-notes: "自分の投稿のRenoteを表示する"
show-local-renotes: "ローカルの投稿のRenoteを表示する"
post-style: "Style de la publication"
post-style-standard: "Standard"
post-style-smart: "Intelligent"

View File

@@ -627,7 +627,8 @@ desktop/views/components/settings.vue:
post-form-on-timeline: "タイムライン上部に投稿フォームを表示する"
show-reply-target: "リプライ先を表示する"
show-my-renotes: "自分の行ったRenoteをタイムラインに表示する"
show-renoted-my-notes: "Renoteされた自分の投稿をタイムラインに表示する"
show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する"
show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する"
show-maps: "マップの自動展開"
show-maps-desc: "位置情報が添付された投稿のマップを自動的に展開します。"
sound: "サウンド"
@@ -1106,7 +1107,8 @@ mobile/views/pages/settings.vue:
timeline: "タイムライン"
show-reply-target: "リプライ先を表示する"
show-my-renotes: "自分の行ったRenoteを表示する"
show-renoted-my-notes: "Renoteされた自分の投稿を表示する"
show-renoted-my-notes: "自分の投稿のRenoteを表示する"
show-local-renotes: "ローカルの投稿のRenoteを表示する"
post-style: "投稿の表示スタイル"
post-style-standard: "標準"
post-style-smart: "スマート"

View File

@@ -709,7 +709,8 @@ desktop/views/components/settings.vue:
post-form-on-timeline: "タイムライン上部に投稿フォームを表示する"
show-reply-target: "リプライ先を表示する"
show-my-renotes: "自分の行ったRenoteをタイムラインに表示する"
show-renoted-my-notes: "Renoteされた自分の投稿をタイムラインに表示する"
show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する"
show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する"
show-maps: "マップの自動展開"
show-maps-desc: "位置情報が添付された投稿のマップを自動的に展開します。"
@@ -1293,7 +1294,8 @@ mobile/views/pages/settings.vue:
timeline: "タイムライン"
show-reply-target: "リプライ先を表示する"
show-my-renotes: "自分の行ったRenoteを表示する"
show-renoted-my-notes: "Renoteされた自分の投稿を表示する"
show-renoted-my-notes: "自分の投稿のRenoteを表示する"
show-local-renotes: "ローカルの投稿のRenoteを表示する"
post-style: "投稿の表示スタイル"
post-style-standard: "標準"
post-style-smart: "スマート"

View File

@@ -12,7 +12,7 @@ common:
application-authorization: "앱의 연계"
close: "닫기"
do-not-copy-paste: "ここにコードを入力したり張り付けたりしないでください。アカウントが不正利用される可能性があります。"
got-it: "わかった"
got-it: "알았습니다"
customization-tips:
title: "사용자 정의 팁"
paragraph1: "홈 정의는 위젯을 추가 / 삭제하거나 드래그 앤 드롭하여 정렬 할 수 있습니다."
@@ -39,7 +39,7 @@ common:
weeks_ago: "{}주전"
months_ago: "{}개월전"
years_ago: "{}년전"
month-and-day: "{month} {day}"
month-and-day: "{month} {day}"
trash: "휴지통"
weekday-short:
sunday: "일"
@@ -122,13 +122,13 @@ common:
tips: "팁"
hashtags: "해시 태그"
deck:
widgets: "ウィジェット"
home: "ホーム"
local: "ローカル"
hybrid: "ソーシャル"
global: "グローバル"
notifications: "通知"
list: "リスト"
widgets: "위젯"
home: ""
local: "로컬"
hybrid: "소셜"
global: "글로벌"
notifications: "통지"
list: "목록"
swap-left: "左に移動"
swap-right: "右に移動"
swap-up: "上に移動"
@@ -150,10 +150,10 @@ auth/views/form.vue:
drive-write: "ドライブを操作する。"
notification-read: "通知を見る。"
notification-write: "通知を操作する。"
cancel: "キャンセル"
cancel: "취소"
accept: "アクセスを許可"
auth/views/index.vue:
loading: "読み込み中"
loading: "로드 중"
denied: "アプリケーションの連携をキャンセルしました。"
denied-paragraph: "このアプリがあなたのアカウントにアクセスすることはありません。"
already-authorized: "このアプリは既に連携済みです"
@@ -165,18 +165,18 @@ auth/views/index.vue:
common/views/components/games/reversi/reversi.vue:
matching:
waiting-for: "{}を待っています"
cancel: "キャンセル"
cancel: "취소"
common/views/components/games/reversi/reversi.game.vue:
surrender: "投了"
surrender: "기권"
surrendered: "投了により"
is-llotheo: "石の少ない方が勝ち(ロセオ)"
looped-map: "ループマップ"
looped-map: "루프 지도"
can-put-everywhere: "どこでも置けるモード"
common/views/components/games/reversi/reversi.index.vue:
title: "Misskey Reversi"
sub-title: "他のMisskeyユーザーとリバーシで対戦しよう"
invite: "招待"
rule: "遊び方"
invite: "초대"
rule: "게임 방법"
rule-desc: "リバーシは、相手と交互に石をボードに置いて、相手の石を挟んで自分の色に変えてゆき、最終的に残った石が多い方が勝ちというボードゲームです。"
mode-invite: "招待"
mode-invite-desc: "指定したユーザーと対戦するモードです。"
@@ -185,26 +185,26 @@ common/views/components/games/reversi/reversi.index.vue:
all-games: "みんなの対局"
enter-username: "ユーザー名を入力してください"
game-state:
ended: "終了"
playing: "進行中"
ended: "종료"
playing: "진행중"
common/views/components/games/reversi/reversi.room.vue:
settings-of-the-game: "ゲームの設定"
choose-map: "マップを選択"
random: "ランダム"
black-or-white: "先手/後手"
black-is: "{}が黒"
rules: "ルール"
rules: "규칙"
is-llotheo: "石の少ない方が勝ち(ロセオ)"
looped-map: "ループマップ"
looped-map: "루프 지도"
can-put-everywhere: "どこでも置けるモード"
settings-of-the-bot: "Botの設定"
this-game-is-started-soon: "ゲームは数秒後に開始されます"
waiting-for-other: "相手の準備が完了するのを待っています"
waiting-for-me: "あなたの準備が完了するのを待っています"
waiting-for-both: "準備中"
cancel: "キャンセル"
ready: "準備完了"
cancel-ready: "準備続行"
waiting-for-both: "준비중"
cancel: "취소"
ready: "준비 완료"
cancel-ready: "준비 계속"
common/views/components/connect-failed.vue:
title: "サーバーに接続できません"
description: "インターネット回線に問題があるか、サーバーがダウンまたはメンテナンスしている可能性があります。しばらくしてから{再度お試し}ください。"
@@ -231,7 +231,7 @@ common/views/components/connect-failed.troubleshooter.vue:
set-version: "バージョン指定"
common/views/components/messaging.vue:
search-user: "ユーザーを探す"
you: "あなた"
you: "당신"
no-history: "履歴はありません"
common/views/components/messaging-room.vue:
empty: "このユーザーと話したことはありません"
@@ -242,12 +242,12 @@ common/views/components/messaging-room.vue:
only-one-file-attached: "メッセージに添付できるのはひとつのファイルのみです"
common/views/components/messaging-room.form.vue:
input-message-here: "ここにメッセージを入力"
send: "送信"
send: "전송"
attach-from-local: "PCからファイルを添付する"
attach-from-drive: "ドライブからファイルを添付する"
only-one-file-attached: "メッセージに添付できるのはひとつのファイルのみです"
common/views/components/messaging-room.message.vue:
is-read: "既読"
is-read: "읽음"
deleted: "このメッセージは削除されました"
common/views/components/nav.vue:
about: "Misskeyについて"
@@ -627,7 +627,8 @@ desktop/views/components/settings.vue:
post-form-on-timeline: "タイムライン上部に投稿フォームを表示する"
show-reply-target: "リプライ先を表示する"
show-my-renotes: "自分の行ったRenoteをタイムラインに表示する"
show-renoted-my-notes: "Renoteされた自分の投稿をタイムラインに表示する"
show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する"
show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する"
show-maps: "マップの自動展開"
show-maps-desc: "位置情報が添付された投稿のマップを自動的に展開します。"
sound: "サウンド"
@@ -1106,7 +1107,8 @@ mobile/views/pages/settings.vue:
timeline: "タイムライン"
show-reply-target: "リプライ先を表示する"
show-my-renotes: "自分の行ったRenoteを表示する"
show-renoted-my-notes: "Renoteされた自分の投稿を表示する"
show-renoted-my-notes: "自分の投稿のRenoteを表示する"
show-local-renotes: "ローカルの投稿のRenoteを表示する"
post-style: "投稿の表示スタイル"
post-style-standard: "標準"
post-style-smart: "スマート"

View File

@@ -627,7 +627,8 @@ desktop/views/components/settings.vue:
post-form-on-timeline: "Wyświetlaj formularz tworzenia wpisu w górnej części osi czasu"
show-reply-target: "Pokazuj cel odpowiedzi"
show-my-renotes: "Pokazuj moje udostępnienia na osi czasu"
show-renoted-my-notes: "Pokazuj udostępnienia moich wpisów na osi czasu"
show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する"
show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する"
show-maps: "Automatycznie pokazuj mapę"
show-maps-desc: "Mapa będzie automatycznie rozwijana dla wpisów zawierających informacje o lokalizacji."
sound: "Dźwięk"
@@ -1106,7 +1107,8 @@ mobile/views/pages/settings.vue:
timeline: "Oś czasu"
show-reply-target: "Pokazuj cel odpowiedzi"
show-my-renotes: "Pokazuj moje udostępnienia"
show-renoted-my-notes: "Pokazuj udostępnienia moich wpisów"
show-renoted-my-notes: "自分の投稿のRenoteを表示する"
show-local-renotes: "ローカルの投稿のRenoteを表示する"
post-style: "Styl wpisów"
post-style-standard: "Standardowy"
post-style-smart: "Inteligentny"

View File

@@ -627,7 +627,8 @@ desktop/views/components/settings.vue:
post-form-on-timeline: "タイムライン上部に投稿フォームを表示する"
show-reply-target: "リプライ先を表示する"
show-my-renotes: "自分の行ったRenoteをタイムラインに表示する"
show-renoted-my-notes: "Renoteされた自分の投稿をタイムラインに表示する"
show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する"
show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する"
show-maps: "マップの自動展開"
show-maps-desc: "位置情報が添付された投稿のマップを自動的に展開します。"
sound: "サウンド"
@@ -1106,7 +1107,8 @@ mobile/views/pages/settings.vue:
timeline: "タイムライン"
show-reply-target: "リプライ先を表示する"
show-my-renotes: "自分の行ったRenoteを表示する"
show-renoted-my-notes: "Renoteされた自分の投稿を表示する"
show-renoted-my-notes: "自分の投稿のRenoteを表示する"
show-local-renotes: "ローカルの投稿のRenoteを表示する"
post-style: "投稿の表示スタイル"
post-style-standard: "標準"
post-style-smart: "スマート"

View File

@@ -627,7 +627,8 @@ desktop/views/components/settings.vue:
post-form-on-timeline: "タイムライン上部に投稿フォームを表示する"
show-reply-target: "リプライ先を表示する"
show-my-renotes: "自分の行ったRenoteをタイムラインに表示する"
show-renoted-my-notes: "Renoteされた自分の投稿をタイムラインに表示する"
show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する"
show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する"
show-maps: "マップの自動展開"
show-maps-desc: "位置情報が添付された投稿のマップを自動的に展開します。"
sound: "サウンド"
@@ -1106,7 +1107,8 @@ mobile/views/pages/settings.vue:
timeline: "タイムライン"
show-reply-target: "リプライ先を表示する"
show-my-renotes: "自分の行ったRenoteを表示する"
show-renoted-my-notes: "Renoteされた自分の投稿を表示する"
show-renoted-my-notes: "自分の投稿のRenoteを表示する"
show-local-renotes: "ローカルの投稿のRenoteを表示する"
post-style: "投稿の表示スタイル"
post-style-standard: "標準"
post-style-smart: "スマート"

View File

@@ -627,7 +627,8 @@ desktop/views/components/settings.vue:
post-form-on-timeline: "タイムライン上部に投稿フォームを表示する"
show-reply-target: "リプライ先を表示する"
show-my-renotes: "自分の行ったRenoteをタイムラインに表示する"
show-renoted-my-notes: "Renoteされた自分の投稿をタイムラインに表示する"
show-renoted-my-notes: "自分の投稿のRenoteをタイムラインに表示する"
show-local-renotes: "ローカルの投稿のRenoteをタイムラインに表示する"
show-maps: "マップの自動展開"
show-maps-desc: "位置情報が添付された投稿のマップを自動的に展開します。"
sound: "サウンド"
@@ -1106,7 +1107,8 @@ mobile/views/pages/settings.vue:
timeline: "タイムライン"
show-reply-target: "リプライ先を表示する"
show-my-renotes: "自分の行ったRenoteを表示する"
show-renoted-my-notes: "Renoteされた自分の投稿を表示する"
show-renoted-my-notes: "自分の投稿のRenoteを表示する"
show-local-renotes: "ローカルの投稿のRenoteを表示する"
post-style: "投稿の表示スタイル"
post-style-standard: "標準"
post-style-smart: "スマート"

View File

@@ -1,8 +1,8 @@
{
"name": "misskey",
"author": "syuilo <i@syuilo.com>",
"version": "5.25.0",
"clientVersion": "1.0.8348",
"version": "6.2.0",
"clientVersion": "1.0.8417",
"codename": "nighthike",
"main": "./built/index.js",
"private": true,
@@ -60,7 +60,7 @@
"@types/mocha": "5.2.3",
"@types/mongodb": "3.1.4",
"@types/ms": "0.7.30",
"@types/node": "10.7.0",
"@types/node": "10.7.1",
"@types/portscanner": "2.1.0",
"@types/pug": "2.0.4",
"@types/qrcode": "1.2.0",
@@ -77,7 +77,7 @@
"@types/systeminformation": "3.23.0",
"@types/tmp": "0.0.33",
"@types/uuid": "3.4.3",
"@types/webpack": "4.4.9",
"@types/webpack": "4.4.10",
"@types/webpack-stream": "3.2.10",
"@types/websocket": "0.0.39",
"@types/ws": "6.0.0",
@@ -149,7 +149,7 @@
"loader-utils": "1.1.0",
"lodash.assign": "4.2.0",
"mecab-async": "0.1.2",
"minio": "6.0.0",
"minio": "7.0.0",
"mkdirp": "0.5.1",
"mocha": "5.2.0",
"moji": "0.5.1",

View File

@@ -1,6 +1,9 @@
export default () => [
const kaos = [
'(=^・・^=)',
'v(\'ω\')v',
'🐡( \'-\' 🐡 )フグパンチ!!!!',
'🖕(´・_・`)🖕'
][Math.floor(Math.random() * 4)];
'🖕(´・_・`)🖕',
'(。><。)'
];
export default () => kaos[Math.floor(Math.random() * kaos.length)];

View File

@@ -1,16 +1,16 @@
<template>
<div class="mk-reactions-viewer">
<template v-if="reactions">
<span v-if="reactions.like"><mk-reaction-icon reaction="like"/><span>{{ reactions.like }}</span></span>
<span v-if="reactions.love"><mk-reaction-icon reaction="love"/><span>{{ reactions.love }}</span></span>
<span v-if="reactions.laugh"><mk-reaction-icon reaction="laugh"/><span>{{ reactions.laugh }}</span></span>
<span v-if="reactions.hmm"><mk-reaction-icon reaction="hmm"/><span>{{ reactions.hmm }}</span></span>
<span v-if="reactions.surprise"><mk-reaction-icon reaction="surprise"/><span>{{ reactions.surprise }}</span></span>
<span v-if="reactions.congrats"><mk-reaction-icon reaction="congrats"/><span>{{ reactions.congrats }}</span></span>
<span v-if="reactions.angry"><mk-reaction-icon reaction="angry"/><span>{{ reactions.angry }}</span></span>
<span v-if="reactions.confused"><mk-reaction-icon reaction="confused"/><span>{{ reactions.confused }}</span></span>
<span v-if="reactions.rip"><mk-reaction-icon reaction="rip"/><span>{{ reactions.rip }}</span></span>
<span v-if="reactions.pudding"><mk-reaction-icon reaction="pudding"/><span>{{ reactions.pudding }}</span></span>
<span :class="{notReacted}" @click="react('like')" v-if="reactions.like"><mk-reaction-icon reaction="like"/><span>{{ reactions.like }}</span></span>
<span :class="{notReacted}" @click="react('love')" v-if="reactions.love"><mk-reaction-icon reaction="love"/><span>{{ reactions.love }}</span></span>
<span :class="{notReacted}" @click="react('laugh')" v-if="reactions.laugh"><mk-reaction-icon reaction="laugh"/><span>{{ reactions.laugh }}</span></span>
<span :class="{notReacted}" @click="react('hmm')" v-if="reactions.hmm"><mk-reaction-icon reaction="hmm"/><span>{{ reactions.hmm }}</span></span>
<span :class="{notReacted}" @click="react('surprise')" v-if="reactions.surprise"><mk-reaction-icon reaction="surprise"/><span>{{ reactions.surprise }}</span></span>
<span :class="{notReacted}" @click="react('congrats')" v-if="reactions.congrats"><mk-reaction-icon reaction="congrats"/><span>{{ reactions.congrats }}</span></span>
<span :class="{notReacted}" @click="react('angry')" v-if="reactions.angry"><mk-reaction-icon reaction="angry"/><span>{{ reactions.angry }}</span></span>
<span :class="{notReacted}" @click="react('confused')" v-if="reactions.confused"><mk-reaction-icon reaction="confused"/><span>{{ reactions.confused }}</span></span>
<span :class="{notReacted}" @click="react('rip')" v-if="reactions.rip"><mk-reaction-icon reaction="rip"/><span>{{ reactions.rip }}</span></span>
<span :class="{notReacted}" @click="react('pudding')" v-if="reactions.pudding"><mk-reaction-icon reaction="pudding"/><span>{{ reactions.pudding }}</span></span>
</template>
</div>
</template>
@@ -22,6 +22,17 @@ export default Vue.extend({
computed: {
reactions(): number {
return this.note.reactionCounts;
},
notReacted(): boolean {
return this.note.myReaction == null;
}
},
methods: {
react(reaction: string) {
(this as any).api('notes/reactions/create', {
noteId: this.note.id,
reaction: reaction
});
}
}
});
@@ -40,6 +51,9 @@ root(isDark)
> span
margin-right 8px
&.notReacted
cursor pointer
> .mk-reaction-icon
font-size 1.4em

View File

@@ -160,12 +160,12 @@ export default Vue.extend({
'web.tv',
'youtube.com',
'youtu.be'
].some(x => x == url.hostname || url.hostname.endsWith(`.${x}`))))
].some(x => x == url.hostname || url.hostname.endsWith(`.${x}`)))
this.player = info.player;
}
});
}
}
} // info.url
}) // json
}); // fetch
} // created
});
</script>

View File

@@ -16,7 +16,7 @@
<p>%i18n:@banner%</p>
</div>
<div class="thumbnail" ref="thumbnail" :style="`background-color: ${ background }`">
<img :src="file.url" alt="" @load="onThumbnailLoaded"/>
<img :src="file.thumbnailUrl" alt="" @load="onThumbnailLoaded"/>
</div>
<p class="name">
<span>{{ file.name.lastIndexOf('.') != -1 ? file.name.substr(0, file.name.lastIndexOf('.')) : file.name }}</span>

View File

@@ -37,7 +37,7 @@ export default Vue.extend({
style(): any {
return {
'background-color': this.image.properties.avgColor && this.image.properties.avgColor.length == 3 ? `rgb(${this.image.properties.avgColor.join(',')})` : 'transparent',
'background-image': this.raw ? `url(${this.image.url})` : `url(${this.image.url})`
'background-image': this.raw ? `url(${this.image.url})` : `url(${this.image.thumbnailUrl})`
};
}
},

View File

@@ -135,6 +135,12 @@ export default Vue.extend({
return;
}
}
if (this.$store.state.settings.showLocalRenotes === false) {
if (isPureRenote && (note.renote.user.host == null)) {
return;
}
}
//#endregion
// 投稿が自分のものではないかつ、タブが非表示またはスクロール位置が最上部ではないならタイトルで通知

View File

@@ -23,7 +23,7 @@
<div class="medias" :class="{ with: poll }" v-show="files.length != 0">
<x-draggable :list="files" :options="{ animation: 150 }">
<div v-for="file in files" :key="file.id">
<div class="img" :style="{ backgroundImage: `url(${file.url})` }" :title="file.name"></div>
<div class="img" :style="{ backgroundImage: `url(${file.thumbnailUrl})` }" :title="file.name"></div>
<img class="remove" @click="detachMedia(file.id)" src="/assets/desktop/remove.png" title="%i18n:@attach-cancel%" alt=""/>
</div>
</x-draggable>

View File

@@ -51,6 +51,7 @@
<mk-switch v-model="$store.state.settings.showReplyTarget" @change="onChangeShowReplyTarget" text="%i18n:@show-reply-target%"/>
<mk-switch v-model="$store.state.settings.showMyRenotes" @change="onChangeShowMyRenotes" text="%i18n:@show-my-renotes%"/>
<mk-switch v-model="$store.state.settings.showRenotedMyNotes" @change="onChangeShowRenotedMyNotes" text="%i18n:@show-renoted-my-notes%"/>
<mk-switch v-model="$store.state.settings.showLocalRenotes" @change="onChangeShowLocalRenotes" text="%i18n:@show-local-renotes%"/>
<mk-switch v-model="$store.state.settings.showMaps" @change="onChangeShowMaps" text="%i18n:@show-maps%">
<span>%i18n:@show-maps-desc%</span>
</mk-switch>
@@ -353,6 +354,12 @@ export default Vue.extend({
value: v
});
},
onChangeShowLocalRenotes(v) {
this.$store.dispatch('settings/set', {
key: 'showLocalRenotes',
value: v
});
},
onChangeShowMaps(v) {
this.$store.dispatch('settings/set', {
key: 'showMaps',

View File

@@ -100,7 +100,8 @@ export default Vue.extend({
limit: fetchLimit + 1,
untilDate: this.date ? this.date.getTime() : undefined,
includeMyRenotes: this.$store.state.settings.showMyRenotes,
includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes
includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes,
includeLocalRenotes: this.$store.state.settings.showLocalRenotes
}).then(notes => {
if (notes.length == fetchLimit + 1) {
notes.pop();
@@ -122,7 +123,8 @@ export default Vue.extend({
limit: fetchLimit + 1,
untilId: (this.$refs.timeline as any).tail().id,
includeMyRenotes: this.$store.state.settings.showMyRenotes,
includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes
includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes,
includeLocalRenotes: this.$store.state.settings.showLocalRenotes
});
promise.then(notes => {

View File

@@ -47,7 +47,8 @@ export default Vue.extend({
listId: this.list.id,
limit: fetchLimit + 1,
includeMyRenotes: this.$store.state.settings.showMyRenotes,
includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes
includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes,
includeLocalRenotes: this.$store.state.settings.showLocalRenotes
}).then(notes => {
if (notes.length == fetchLimit + 1) {
notes.pop();
@@ -67,7 +68,8 @@ export default Vue.extend({
limit: fetchLimit + 1,
untilId: (this.$refs.timeline as any).tail().id,
includeMyRenotes: this.$store.state.settings.showMyRenotes,
includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes
includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes,
includeLocalRenotes: this.$store.state.settings.showLocalRenotes
});
promise.then(notes => {

View File

@@ -70,7 +70,8 @@ export default Vue.extend({
limit: fetchLimit + 1,
mediaOnly: this.mediaOnly,
includeMyRenotes: this.$store.state.settings.showMyRenotes,
includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes
includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes,
includeLocalRenotes: this.$store.state.settings.showLocalRenotes
}).then(notes => {
if (notes.length == fetchLimit + 1) {
notes.pop();
@@ -91,7 +92,8 @@ export default Vue.extend({
untilId: (this.$refs.timeline as any).tail().id,
mediaOnly: this.mediaOnly,
includeMyRenotes: this.$store.state.settings.showMyRenotes,
includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes
includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes,
includeLocalRenotes: this.$store.state.settings.showLocalRenotes
});
promise.then(notes => {

View File

@@ -140,6 +140,12 @@ export default Vue.extend({
return;
}
}
if (this.$store.state.settings.showLocalRenotes === false) {
if (isPureRenote && (note.renote.user.host == null)) {
return;
}
}
//#endregion
if (this.isScrollTop()) {

View File

@@ -98,7 +98,8 @@ export default Vue.extend({
limit: fetchLimit + 1,
mediaOnly: this.mediaOnly,
includeMyRenotes: this.$store.state.settings.showMyRenotes,
includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes
includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes,
includeLocalRenotes: this.$store.state.settings.showLocalRenotes
}).then(notes => {
if (notes.length == fetchLimit + 1) {
notes.pop();
@@ -119,7 +120,8 @@ export default Vue.extend({
mediaOnly: this.mediaOnly,
untilId: (this.$refs.timeline as any).tail().id,
includeMyRenotes: this.$store.state.settings.showMyRenotes,
includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes
includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes,
includeLocalRenotes: this.$store.state.settings.showLocalRenotes
});
promise.then(notes => {

View File

@@ -43,7 +43,7 @@ export default Vue.extend({
thumbnail(): any {
return {
'background-color': this.file.properties.avgColor && this.file.properties.avgColor.length == 3 ? `rgb(${this.file.properties.avgColor.join(',')})` : 'transparent',
'background-image': `url(${this.file.url})`
'background-image': `url(${this.file.thumbnailUrl})`
};
}
},

View File

@@ -27,7 +27,7 @@ export default Vue.extend({
},
computed: {
style(): any {
let url = `url(${this.image.url})`;
let url = `url(${this.image.thumbnailUrl})`;
if (this.$store.state.device.loadRemoteMedia || this.$store.state.device.lightmode) {
url = null;

View File

@@ -139,6 +139,12 @@ export default Vue.extend({
return;
}
}
if (this.$store.state.settings.showLocalRenotes === false) {
if (isPureRenote && (note.renote.user.host == null)) {
return;
}
}
//#endregion
// 投稿が自分のものではないかつ、タブが非表示またはスクロール位置が最上部ではないならタイトルで通知

View File

@@ -21,7 +21,7 @@
<div class="attaches" v-show="files.length != 0">
<x-draggable class="files" :list="files" :options="{ animation: 150 }">
<div class="file" v-for="file in files" :key="file.id">
<div class="img" :style="`background-image: url(${file.url})`" @click="detachMedia(file)"></div>
<div class="img" :style="`background-image: url(${file.thumbnailUrl})`" @click="detachMedia(file)"></div>
</div>
</x-draggable>
</div>

View File

@@ -59,7 +59,8 @@ export default Vue.extend({
listId: this.list.id,
limit: fetchLimit + 1,
includeMyRenotes: this.$store.state.settings.showMyRenotes,
includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes
includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes,
includeLocalRenotes: this.$store.state.settings.showLocalRenotes
}).then(notes => {
if (notes.length == fetchLimit + 1) {
notes.pop();
@@ -82,7 +83,8 @@ export default Vue.extend({
limit: fetchLimit + 1,
untilId: (this.$refs.timeline as any).tail().id,
includeMyRenotes: this.$store.state.settings.showMyRenotes,
includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes
includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes,
includeLocalRenotes: this.$store.state.settings.showLocalRenotes
});
promise.then(notes => {

View File

@@ -95,7 +95,8 @@ export default Vue.extend({
limit: fetchLimit + 1,
untilDate: this.date ? this.date.getTime() : undefined,
includeMyRenotes: this.$store.state.settings.showMyRenotes,
includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes
includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes,
includeLocalRenotes: this.$store.state.settings.showLocalRenotes
}).then(notes => {
if (notes.length == fetchLimit + 1) {
notes.pop();
@@ -117,7 +118,8 @@ export default Vue.extend({
limit: fetchLimit + 1,
untilId: (this.$refs.timeline as any).tail().id,
includeMyRenotes: this.$store.state.settings.showMyRenotes,
includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes
includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes,
includeLocalRenotes: this.$store.state.settings.showLocalRenotes
});
promise.then(notes => {

View File

@@ -21,6 +21,7 @@
<ui-switch v-model="$store.state.settings.showReplyTarget" @change="onChangeShowReplyTarget">%i18n:@show-reply-target%</ui-switch>
<ui-switch v-model="$store.state.settings.showMyRenotes" @change="onChangeShowMyRenotes">%i18n:@show-my-renotes%</ui-switch>
<ui-switch v-model="$store.state.settings.showRenotedMyNotes" @change="onChangeShowRenotedMyNotes">%i18n:@show-renoted-my-notes%</ui-switch>
<ui-switch v-model="$store.state.settings.showLocalRenotes" @change="onChangeShowLocalRenotes">%i18n:@show-local-renotes%</ui-switch>
</div>
<div>
@@ -221,6 +222,13 @@ export default Vue.extend({
});
},
onChangeShowLocalRenotes(v) {
this.$store.dispatch('settings/set', {
key: 'showLocalRenotes',
value: v
});
},
checkForUpdate() {
this.checkingForUpdate = true;
checkForUpdate((this as any).os, true, true).then(newer => {

View File

@@ -61,7 +61,6 @@ export default Vue.extend({
birthday: null,
avatarId: null,
bannerId: null,
isBot: false,
isCat: false,
saving: false,
avatarUploading: false,
@@ -77,7 +76,6 @@ export default Vue.extend({
this.birthday = this.$store.state.i.profile.birthday;
this.avatarId = this.$store.state.i.avatarId;
this.bannerId = this.$store.state.i.bannerId;
this.isBot = this.$store.state.i.isBot;
this.isCat = this.$store.state.i.isCat;
},
@@ -136,7 +134,6 @@ export default Vue.extend({
birthday: this.birthday || null,
avatarId: this.avatarId,
bannerId: this.bannerId,
isBot: this.isBot,
isCat: this.isCat
}).then(i => {
this.saving = false;

View File

@@ -16,6 +16,7 @@ const defaultSettings = {
showReplyTarget: true,
showMyRenotes: true,
showRenotedMyNotes: true,
showLocalRenotes: true,
loadRemoteMedia: true,
disableViaMobile: false,
memo: null,

View File

@@ -19,6 +19,6 @@ export default function(text: string) {
type: 'code',
content: code,
code: match[1],
html: genHtml(match[1])
html: genHtml(match[1].trim())
} as TextElementCode;
}

View File

@@ -31,6 +31,7 @@ export type IMetadata = {
comment: string;
uri?: string;
url?: string;
thumbnailUrl?: string;
src?: string;
deletedAt?: Date;
withoutChunks?: boolean;
@@ -164,6 +165,7 @@ export const pack = (
_target = Object.assign(_target, _file.metadata);
_target.url = _file.metadata.url ? _file.metadata.url : `${config.drive_url}/${_target.id}/${encodeURIComponent(_target.name)}`;
_target.thumbnailUrl = _file.metadata.thumbnailUrl ? _file.metadata.thumbnailUrl : _file.metadata.url ? _file.metadata.url : `${config.drive_url}/${_target.id}/${encodeURIComponent(_target.name)}?thumbnail`;
_target.isRemote = _file.metadata.isRemote;
if (_target.properties == null) _target.properties = {};

View File

@@ -59,6 +59,13 @@ export const meta = {
}
}),
includeLocalRenotes: $.bool.optional.note({
default: true,
desc: {
ja: 'Renoteされたローカルの投稿を含めるかどうか'
}
}),
mediaOnly: $.bool.optional.note({
desc: {
ja: 'true にすると、メディアが添付された投稿だけ取得します'
@@ -180,6 +187,22 @@ export default async (params: any, user: ILocalUser) => {
});
}
if (ps.includeLocalRenotes === false) {
query.$and.push({
$or: [{
'_renote.user.host': { $ne: null }
}, {
renoteId: null
}, {
text: { $ne: null }
}, {
mediaIds: { $ne: [] }
}, {
poll: { $ne: null }
}]
});
}
if (ps.mediaOnly) {
query.$and.push({
mediaIds: { $exists: true, $ne: [] }

View File

@@ -60,6 +60,13 @@ export const meta = {
}
}),
includeLocalRenotes: $.bool.optional.note({
default: true,
desc: {
ja: 'Renoteされたローカルの投稿を含めるかどうか'
}
}),
mediaOnly: $.bool.optional.note({
desc: {
ja: 'true にすると、メディアが添付された投稿だけ取得します'
@@ -170,6 +177,22 @@ export default async (params: any, user: ILocalUser) => {
});
}
if (ps.includeLocalRenotes === false) {
query.$and.push({
$or: [{
'_renote.user.host': { $ne: null }
}, {
renoteId: null
}, {
text: { $ne: null }
}, {
mediaIds: { $ne: [] }
}, {
poll: { $ne: null }
}]
});
}
if (ps.mediaOnly) {
query.$and.push({
mediaIds: { $exists: true, $ne: [] }

View File

@@ -4,6 +4,7 @@ import Mute from '../../../../models/mute';
import { pack } from '../../../../models/note';
import UserList from '../../../../models/user-list';
import { ILocalUser } from '../../../../models/user';
import getParams from '../../get-params';
export const meta = {
desc: {
@@ -11,56 +12,84 @@ export const meta = {
en: 'Get timeline of a user list.'
},
requireCredential: true
requireCredential: true,
params: {
listId: $.type(ID).note({
desc: {
ja: 'リストのID'
}
}),
limit: $.num.optional.range(1, 100).note({
default: 10,
desc: {
ja: '最大数'
}
}),
sinceId: $.type(ID).optional.note({
desc: {
ja: '指定すると、この投稿を基点としてより新しい投稿を取得します'
}
}),
untilId: $.type(ID).optional.note({
desc: {
ja: '指定すると、この投稿を基点としてより古い投稿を取得します'
}
}),
sinceDate: $.num.optional.note({
desc: {
ja: '指定した時間を基点としてより新しい投稿を取得します。数値は、1970年1月1日 00:00:00 UTC から指定した日時までの経過時間をミリ秒単位で表します。'
}
}),
untilDate: $.num.optional.note({
desc: {
ja: '指定した時間を基点としてより古い投稿を取得します。数値は、1970年1月1日 00:00:00 UTC から指定した日時までの経過時間をミリ秒単位で表します。'
}
}),
includeMyRenotes: $.bool.optional.note({
default: true,
desc: {
ja: '自分の行ったRenoteを含めるかどうか'
}
}),
includeRenotedMyNotes: $.bool.optional.note({
default: true,
desc: {
ja: 'Renoteされた自分の投稿を含めるかどうか'
}
}),
includeLocalRenotes: $.bool.optional.note({
default: true,
desc: {
ja: 'Renoteされたローカルの投稿を含めるかどうか'
}
}),
mediaOnly: $.bool.optional.note({
desc: {
ja: 'true にすると、メディアが添付された投稿だけ取得します'
}
}),
}
};
export default async (params: any, user: ILocalUser) => {
// Get 'limit' parameter
const [limit = 10, limitErr] = $.num.optional.range(1, 100).get(params.limit);
if (limitErr) throw 'invalid limit param';
// Get 'sinceId' parameter
const [sinceId, sinceIdErr] = $.type(ID).optional.get(params.sinceId);
if (sinceIdErr) throw 'invalid sinceId param';
// Get 'untilId' parameter
const [untilId, untilIdErr] = $.type(ID).optional.get(params.untilId);
if (untilIdErr) throw 'invalid untilId param';
// Get 'sinceDate' parameter
const [sinceDate, sinceDateErr] = $.num.optional.get(params.sinceDate);
if (sinceDateErr) throw 'invalid sinceDate param';
// Get 'untilDate' parameter
const [untilDate, untilDateErr] = $.num.optional.get(params.untilDate);
if (untilDateErr) throw 'invalid untilDate param';
// Check if only one of sinceId, untilId, sinceDate, untilDate specified
if ([sinceId, untilId, sinceDate, untilDate].filter(x => x != null).length > 1) {
throw 'only one of sinceId, untilId, sinceDate, untilDate can be specified';
}
// Get 'includeMyRenotes' parameter
const [includeMyRenotes = true, includeMyRenotesErr] = $.bool.optional.get(params.includeMyRenotes);
if (includeMyRenotesErr) throw 'invalid includeMyRenotes param';
// Get 'includeRenotedMyNotes' parameter
const [includeRenotedMyNotes = true, includeRenotedMyNotesErr] = $.bool.optional.get(params.includeRenotedMyNotes);
if (includeRenotedMyNotesErr) throw 'invalid includeRenotedMyNotes param';
// Get 'mediaOnly' parameter
const [mediaOnly, mediaOnlyErr] = $.bool.optional.get(params.mediaOnly);
if (mediaOnlyErr) throw 'invalid mediaOnly param';
// Get 'listId' parameter
const [listId, listIdErr] = $.type(ID).get(params.listId);
if (listIdErr) throw 'invalid listId param';
const [ps, psErr] = getParams(meta, params);
if (psErr) throw psErr;
const [list, mutedUserIds] = await Promise.all([
// リストを取得
// Fetch the list
UserList.findOne({
_id: listId,
_id: ps.listId,
userId: user._id
}),
@@ -122,7 +151,7 @@ export default async (params: any, user: ILocalUser) => {
// つまり、「『自分の投稿かつRenote』ではない」を「『自分の投稿ではない』または『Renoteではない』」と表現します。
// for details: https://en.wikipedia.org/wiki/De_Morgan%27s_laws
if (includeMyRenotes === false) {
if (ps.includeMyRenotes === false) {
query.$and.push({
$or: [{
userId: { $ne: user._id }
@@ -138,7 +167,7 @@ export default async (params: any, user: ILocalUser) => {
});
}
if (includeRenotedMyNotes === false) {
if (ps.includeRenotedMyNotes === false) {
query.$and.push({
$or: [{
'_renote.userId': { $ne: user._id }
@@ -154,29 +183,45 @@ export default async (params: any, user: ILocalUser) => {
});
}
if (mediaOnly) {
if (ps.includeLocalRenotes === false) {
query.$and.push({
$or: [{
'_renote.user.host': { $ne: null }
}, {
renoteId: null
}, {
text: { $ne: null }
}, {
mediaIds: { $ne: [] }
}, {
poll: { $ne: null }
}]
});
}
if (ps.mediaOnly) {
query.$and.push({
mediaIds: { $exists: true, $ne: [] }
});
}
if (sinceId) {
if (ps.sinceId) {
sort._id = 1;
query._id = {
$gt: sinceId
$gt: ps.sinceId
};
} else if (untilId) {
} else if (ps.untilId) {
query._id = {
$lt: untilId
$lt: ps.untilId
};
} else if (sinceDate) {
} else if (ps.sinceDate) {
sort._id = 1;
query.createdAt = {
$gt: new Date(sinceDate)
$gt: new Date(ps.sinceDate)
};
} else if (untilDate) {
} else if (ps.untilDate) {
query.createdAt = {
$lt: new Date(untilDate)
$lt: new Date(ps.untilDate)
};
}
//#endregion
@@ -184,7 +229,7 @@ export default async (params: any, user: ILocalUser) => {
// Issue query
const timeline = await Note
.find(query, {
limit: limit,
limit: ps.limit,
sort: sort
});

View File

@@ -16,17 +16,13 @@ export default (params: any, me: ILocalUser) => new Promise(async (res, rej) =>
if (usernameErr) return rej('invalid username param');
if (userId === undefined && username === undefined) {
return rej('userId or pair of username and host is required');
return rej('userId or username is required');
}
// Get 'host' parameter
const [host, hostErr] = $.str.optional.get(params.host);
if (hostErr) return rej('invalid host param');
if (userId === undefined && host === undefined) {
return rej('userId or pair of username and host is required');
}
// Get 'includeReplies' parameter
const [includeReplies = true, includeRepliesErr] = $.bool.optional.get(params.includeReplies);
if (includeRepliesErr) return rej('invalid includeReplies param');

View File

@@ -92,7 +92,7 @@ export default async (ctx: Koa.Context) => {
weight: null
},
settings: {
autoWatch: true
autoWatch: false
}
});

View File

@@ -1,5 +1,3 @@
import * as fs from 'fs';
import * as Koa from 'koa';
import * as send from 'koa-send';
import * as mongodb from 'mongodb';
@@ -51,23 +49,16 @@ export default async function(ctx: Koa.Context) {
};
if ('thumbnail' in ctx.query) {
// 画像以外
if (!file.contentType.startsWith('image/')) {
const readable = fs.createReadStream(`${__dirname}/assets/thumbnail-not-available.png`);
ctx.set('Content-Type', 'image/png');
ctx.body = readable;
} else if (file.contentType == 'image/gif') {
// GIF
await sendRaw();
const thumb = await DriveFileThumbnail.findOne({
'metadata.originalId': fileId
});
if (thumb != null) {
ctx.set('Content-Type', 'image/jpeg');
const bucket = await getDriveFileThumbnailBucket();
ctx.body = bucket.openDownloadStream(thumb._id);
} else {
const thumb = await DriveFileThumbnail.findOne({ 'metadata.originalId': fileId });
if (thumb != null) {
ctx.set('Content-Type', 'image/jpeg');
const bucket = await getDriveFileThumbnailBucket();
ctx.body = bucket.openDownloadStream(thumb._id);
} else {
await sendRaw();
}
await sendRaw();
}
} else {
if ('download' in ctx.query) {

View File

@@ -1,6 +1,5 @@
import { Buffer } from 'buffer';
import * as fs from 'fs';
import * as stream from 'stream';
import * as mongodb from 'mongodb';
import * as crypto from 'crypto';
@@ -17,30 +16,52 @@ import { publishUserStream, publishDriveStream } from '../../stream';
import { isLocalUser, IUser, IRemoteUser } from '../../models/user';
import delFile from './delete-file';
import config from '../../config';
import { getDriveFileThumbnailBucket } from '../../models/drive-file-thumbnail';
const log = debug('misskey:drive:add-file');
async function save(readable: stream.Readable, name: string, type: string, hash: string, size: number, metadata: any): Promise<IDriveFile> {
async function save(path: string, name: string, type: string, hash: string, size: number, metadata: any): Promise<IDriveFile> {
let thumbnail: Buffer;
if (['image/jpeg', 'image/png', 'image/webp'].includes(type)) {
thumbnail = await sharp(path)
.resize(300)
.jpeg({
quality: 50,
progressive: true
})
.toBuffer();
}
if (config.drive && config.drive.storage == 'minio') {
const minio = new Minio.Client(config.drive.config);
const id = uuid.v4();
const obj = `${config.drive.prefix}/${id}`;
const key = `${config.drive.prefix}/${uuid.v4()}/${name}`;
const thumbnailKey = `${config.drive.prefix}/${uuid.v4()}/${name}.thumbnail.jpg`;
const baseUrl = config.drive.baseUrl
|| `${ config.drive.config.secure ? 'https' : 'http' }://${ config.drive.config.endPoint }${ config.drive.config.port ? ':' + config.drive.config.port : '' }/${ config.drive.bucket }`;
await minio.putObject(config.drive.bucket, obj, readable, size, {
await minio.putObject(config.drive.bucket, key, fs.createReadStream(path), size, {
'Content-Type': type,
'Cache-Control': 'max-age=31536000, immutable'
});
if (thumbnail) {
await minio.putObject(config.drive.bucket, thumbnailKey, thumbnail, size, {
'Content-Type': 'image/jpeg',
'Cache-Control': 'max-age=31536000, immutable'
});
}
Object.assign(metadata, {
withoutChunks: true,
storage: 'minio',
storageProps: {
id: id
key: key,
thumbnailKey: thumbnailKey
},
url: `${ baseUrl }/${ obj }`
url: `${ baseUrl }/${ key }`,
thumbnailUrl: thumbnail ? `${ baseUrl }/${ thumbnailKey }` : null
});
const file = await DriveFile.insert({
@@ -57,12 +78,36 @@ async function save(readable: stream.Readable, name: string, type: string, hash:
// Get MongoDB GridFS bucket
const bucket = await getDriveFileBucket();
return new Promise<IDriveFile>((resolve, reject) => {
const writeStream = bucket.openUploadStream(name, { contentType: type, metadata });
const file = await new Promise<IDriveFile>((resolve, reject) => {
const writeStream = bucket.openUploadStream(name, {
contentType: type,
metadata
});
writeStream.once('finish', resolve);
writeStream.on('error', reject);
readable.pipe(writeStream);
fs.createReadStream(path).pipe(writeStream);
});
if (thumbnail) {
const thumbnailBucket = await getDriveFileThumbnailBucket();
await new Promise<IDriveFile>((resolve, reject) => {
const writeStream = thumbnailBucket.openUploadStream(name, {
contentType: 'image/jpeg',
metadata: {
originalId: file._id
}
});
writeStream.once('finish', resolve);
writeStream.on('error', reject);
writeStream.end(thumbnail);
});
}
return file;
}
}
@@ -321,7 +366,7 @@ export default async function(
}
}
} else {
driveFile = await (save(fs.createReadStream(path), detectedName, mime, hash, size, metadata));
driveFile = await (save(path, detectedName, mime, hash, size, metadata));
}
log(`drive file has been created ${driveFile._id}`);

View File

@@ -6,8 +6,18 @@ import config from '../../config';
export default async function(file: IDriveFile, isExpired = false) {
if (file.metadata.storage == 'minio') {
const minio = new Minio.Client(config.drive.config);
const obj = `${config.drive.prefix}/${file.metadata.storageProps.id}`;
// 後方互換性のため、file.metadata.storageProps.key があるかどうかチェックしています。
// 将来的には const obj = file.metadata.storageProps.key; とします。
const obj = file.metadata.storageProps.key ? file.metadata.storageProps.key : `${config.drive.prefix}/${file.metadata.storageProps.id}`;
await minio.removeObject(config.drive.bucket, obj);
if (file.metadata.thumbnailUrl) {
// 後方互換性のため、file.metadata.storageProps.thumbnailKey があるかどうかチェックしています。
// 将来的には const thumbnailObj = file.metadata.storageProps.thumbnailKey; とします。
const thumbnailObj = file.metadata.storageProps.thumbnailKey ? file.metadata.storageProps.thumbnailKey : `${config.drive.prefix}/${file.metadata.storageProps.id}-thumbnail`;
await minio.removeObject(config.drive.bucket, thumbnailObj);
}
}
// チャンクをすべて削除

View File

@@ -328,8 +328,18 @@ async function insertNote(user: IUser, data: Option, tokens: ReturnType<typeof p
: [],
// 以下非正規化データ
_reply: data.reply ? { userId: data.reply.userId } : null,
_renote: data.renote ? { userId: data.renote.userId } : null,
_reply: data.reply ? {
userId: data.reply.userId,
user: {
host: data.reply._user.host
}
} : null,
_renote: data.renote ? {
userId: data.renote.userId,
user: {
host: data.renote._user.host
}
} : null,
_user: {
host: user.host,
inbox: isRemoteUser(user) ? user.inbox : undefined