From 6bbfd70a447d38605191cbcd644eda93c85f8018 Mon Sep 17 00:00:00 2001 From: bakaneko Date: Wed, 18 Sep 2024 15:42:11 +0900 Subject: [PATCH 01/17] pagination() only used by certain models --- app/Models/BeatmapDiscussion.php | 4 +++- app/Models/BeatmapDiscussionPost.php | 3 ++- app/Models/BeatmapDiscussionVote.php | 4 +++- app/Models/BeatmapsetEvent.php | 4 +++- app/Models/Model.php | 11 +++++++++++ app/helpers.php | 12 +----------- 6 files changed, 23 insertions(+), 15 deletions(-) diff --git a/app/Models/BeatmapDiscussion.php b/app/Models/BeatmapDiscussion.php index 0e3b95e9077..702f8636e5d 100644 --- a/app/Models/BeatmapDiscussion.php +++ b/app/Models/BeatmapDiscussion.php @@ -62,6 +62,8 @@ class BeatmapDiscussion extends Model 'review' => 5, ]; + const int PER_PAGE = 20; + const RESOLVABLE_TYPES = [1, 2]; const KUDOSUABLE_TYPES = [1, 2]; @@ -71,7 +73,7 @@ class BeatmapDiscussion extends Model // FIXME: This and other static search functions should be extracted out. public static function search($rawParams = []) { - $pagination = pagination(cursor_from_params($rawParams) ?? $rawParams); + $pagination = static::pagination(cursor_from_params($rawParams) ?? $rawParams); $params = [ 'limit' => $pagination['limit'], diff --git a/app/Models/BeatmapDiscussionPost.php b/app/Models/BeatmapDiscussionPost.php index 22d8efea995..a03910d6471 100644 --- a/app/Models/BeatmapDiscussionPost.php +++ b/app/Models/BeatmapDiscussionPost.php @@ -31,6 +31,7 @@ class BeatmapDiscussionPost extends Model implements Traits\ReportableInterface const MESSAGE_LIMIT = 16_000; // column limit for 4 bytes utf8 const MESSAGE_LIMIT_TIMELINE = 750; + const int PER_PAGE = 20; protected $touches = ['beatmapDiscussion']; @@ -41,7 +42,7 @@ class BeatmapDiscussionPost extends Model implements Traits\ReportableInterface public static function search($rawParams = []) { - $pagination = pagination(cursor_from_params($rawParams) ?? $rawParams); + $pagination = static::pagination(cursor_from_params($rawParams) ?? $rawParams); $params = [ 'limit' => $pagination['limit'], diff --git a/app/Models/BeatmapDiscussionVote.php b/app/Models/BeatmapDiscussionVote.php index 0b8dd6fc8ba..a3210b1e915 100644 --- a/app/Models/BeatmapDiscussionVote.php +++ b/app/Models/BeatmapDiscussionVote.php @@ -19,6 +19,8 @@ */ class BeatmapDiscussionVote extends Model { + const int PER_PAGE = 20; + protected $touches = ['beatmapDiscussion']; public static function recentlyReceivedByUser($userId, $timeframeMonths = 3) @@ -57,7 +59,7 @@ public static function recentlyGivenByUser($userId, $timeframeMonths = 3) public static function search($rawParams = []) { - $pagination = pagination(cursor_from_params($rawParams) ?? $rawParams); + $pagination = static::pagination(cursor_from_params($rawParams) ?? $rawParams); $params = [ 'limit' => $pagination['limit'], diff --git a/app/Models/BeatmapsetEvent.php b/app/Models/BeatmapsetEvent.php index d5331a8d1d8..97ee28e88d5 100644 --- a/app/Models/BeatmapsetEvent.php +++ b/app/Models/BeatmapsetEvent.php @@ -57,6 +57,8 @@ class BeatmapsetEvent extends Model const BEATMAP_OWNER_CHANGE = 'beatmap_owner_change'; + const int PER_PAGE = 20; + public static function log($type, $user, $object, $extraData = []) { if ($object instanceof BeatmapDiscussionPost) { @@ -83,7 +85,7 @@ public static function log($type, $user, $object, $extraData = []) public static function search($rawParams = []) { - $pagination = pagination($rawParams); + $pagination = static::pagination($rawParams); $params = [ 'limit' => $pagination['limit'], diff --git a/app/Models/Model.php b/app/Models/Model.php index 49c27893450..8cecaafa9d9 100644 --- a/app/Models/Model.php +++ b/app/Models/Model.php @@ -35,6 +35,17 @@ public static function booted() static::addGlobalScope(new MacroableModelScope()); } + public static function pagination($params, $defaults = null) + { + $limit = clamp(get_int($params['limit'] ?? null) ?? $defaults['limit'] ?? static::PER_PAGE, 5, 50); + $page = max(get_int($params['page'] ?? null) ?? 1, 1); + + $offset = max_offset($page, $limit); + $page = 1 + $offset / $limit; + + return compact('limit', 'page', 'offset'); + } + public function getForeignKey() { if ($this->primaryKey === null || $this->primaryKey === 'id') { diff --git a/app/helpers.php b/app/helpers.php index 23dc6dd75c5..99039ea75cc 100644 --- a/app/helpers.php +++ b/app/helpers.php @@ -9,6 +9,7 @@ use App\Libraries\Base64Url; use App\Libraries\LocaleMeta; use App\Models\LoginAttempt; +use App\Models\Model; use Egulias\EmailValidator\EmailValidator; use Egulias\EmailValidator\Validation\NoRFCWarningsValidation; use Illuminate\Database\Migrations\Migration; @@ -651,17 +652,6 @@ function pack_str($str) return pack('ccH*', 0x0b, strlen($str), bin2hex($str)); } -function pagination($params, $defaults = null) -{ - $limit = clamp(get_int($params['limit'] ?? null) ?? $defaults['limit'] ?? 20, 5, 50); - $page = max(get_int($params['page'] ?? null) ?? 1, 1); - - $offset = max_offset($page, $limit); - $page = 1 + $offset / $limit; - - return compact('limit', 'page', 'offset'); -} - function product_quantity_options($product, $selected = null) { if ($product->stock === null) { From 50f0d75f861522136a93e6b9800d367f59e900b6 Mon Sep 17 00:00:00 2001 From: bakaneko Date: Wed, 18 Sep 2024 15:43:12 +0900 Subject: [PATCH 02/17] defaults param not used; max(null, 1) is 1 --- app/Models/Model.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/Models/Model.php b/app/Models/Model.php index 8cecaafa9d9..37ad46987c8 100644 --- a/app/Models/Model.php +++ b/app/Models/Model.php @@ -35,10 +35,10 @@ public static function booted() static::addGlobalScope(new MacroableModelScope()); } - public static function pagination($params, $defaults = null) + public static function pagination($params) { - $limit = clamp(get_int($params['limit'] ?? null) ?? $defaults['limit'] ?? static::PER_PAGE, 5, 50); - $page = max(get_int($params['page'] ?? null) ?? 1, 1); + $limit = clamp(get_int($params['limit'] ?? null) ?? static::PER_PAGE, 5, 50); + $page = max(get_int($params['page'] ?? null), 1); $offset = max_offset($page, $limit); $page = 1 + $offset / $limit; From 50135d9ce4fbdb90c1f8fcd40074dac3aaff6c64 Mon Sep 17 00:00:00 2001 From: bakaneko Date: Wed, 18 Sep 2024 17:58:18 +0900 Subject: [PATCH 03/17] streamline making the query and params for the search --- app/Models/BeatmapDiscussion.php | 8 +------- app/Models/BeatmapDiscussionPost.php | 8 +------- app/Models/BeatmapDiscussionVote.php | 8 +------- app/Models/BeatmapsetEvent.php | 8 +------- app/Models/Model.php | 6 ++++-- 5 files changed, 8 insertions(+), 30 deletions(-) diff --git a/app/Models/BeatmapDiscussion.php b/app/Models/BeatmapDiscussion.php index 702f8636e5d..9f925bcf14a 100644 --- a/app/Models/BeatmapDiscussion.php +++ b/app/Models/BeatmapDiscussion.php @@ -73,14 +73,8 @@ class BeatmapDiscussion extends Model // FIXME: This and other static search functions should be extracted out. public static function search($rawParams = []) { - $pagination = static::pagination(cursor_from_params($rawParams) ?? $rawParams); + [$query, $params] = static::searchQueryAndParams(cursor_from_params($rawParams) ?? $rawParams); - $params = [ - 'limit' => $pagination['limit'], - 'page' => $pagination['page'], - ]; - - $query = static::limit($params['limit'])->offset($pagination['offset']); $isModerator = $rawParams['is_moderator'] ?? false; if (present($rawParams['user'] ?? null)) { diff --git a/app/Models/BeatmapDiscussionPost.php b/app/Models/BeatmapDiscussionPost.php index a03910d6471..988b97a52ac 100644 --- a/app/Models/BeatmapDiscussionPost.php +++ b/app/Models/BeatmapDiscussionPost.php @@ -42,14 +42,8 @@ class BeatmapDiscussionPost extends Model implements Traits\ReportableInterface public static function search($rawParams = []) { - $pagination = static::pagination(cursor_from_params($rawParams) ?? $rawParams); + [$query, $params] = static::searchQueryAndParams(cursor_from_params($rawParams) ?? $rawParams); - $params = [ - 'limit' => $pagination['limit'], - 'page' => $pagination['page'], - ]; - - $query = static::limit($params['limit'])->offset($pagination['offset']); $isModerator = $rawParams['is_moderator'] ?? false; if (isset($rawParams['user'])) { diff --git a/app/Models/BeatmapDiscussionVote.php b/app/Models/BeatmapDiscussionVote.php index a3210b1e915..d6b5d1c9c02 100644 --- a/app/Models/BeatmapDiscussionVote.php +++ b/app/Models/BeatmapDiscussionVote.php @@ -59,14 +59,8 @@ public static function recentlyGivenByUser($userId, $timeframeMonths = 3) public static function search($rawParams = []) { - $pagination = static::pagination(cursor_from_params($rawParams) ?? $rawParams); + [$query, $params] = static::searchQueryAndParams(cursor_from_params($rawParams) ?? $rawParams); - $params = [ - 'limit' => $pagination['limit'], - 'page' => $pagination['page'], - ]; - - $query = static::limit($params['limit'])->offset($pagination['offset']); $isModerator = $rawParams['is_moderator'] ?? false; if (isset($rawParams['user'])) { diff --git a/app/Models/BeatmapsetEvent.php b/app/Models/BeatmapsetEvent.php index 97ee28e88d5..6ecfeb184e2 100644 --- a/app/Models/BeatmapsetEvent.php +++ b/app/Models/BeatmapsetEvent.php @@ -85,14 +85,8 @@ public static function log($type, $user, $object, $extraData = []) public static function search($rawParams = []) { - $pagination = static::pagination($rawParams); + [$query, $params] = static::searchQueryAndParams($rawParams); - $params = [ - 'limit' => $pagination['limit'], - 'page' => $pagination['page'], - ]; - - $query = static::limit($params['limit'])->offset($pagination['offset']); $searchByUser = present($rawParams['user'] ?? null); $isModerator = $rawParams['is_moderator'] ?? false; diff --git a/app/Models/Model.php b/app/Models/Model.php index 37ad46987c8..df5caf449b0 100644 --- a/app/Models/Model.php +++ b/app/Models/Model.php @@ -35,7 +35,7 @@ public static function booted() static::addGlobalScope(new MacroableModelScope()); } - public static function pagination($params) + protected static function searchQueryAndParams(array $params) { $limit = clamp(get_int($params['limit'] ?? null) ?? static::PER_PAGE, 5, 50); $page = max(get_int($params['page'] ?? null), 1); @@ -43,7 +43,9 @@ public static function pagination($params) $offset = max_offset($page, $limit); $page = 1 + $offset / $limit; - return compact('limit', 'page', 'offset'); + $query = static::limit($limit)->offset($offset); + + return [$query, compact('limit', 'page')]; } public function getForeignKey() From d37e840c025e9d4cd6027f51e53bbe3aa8838f77 Mon Sep 17 00:00:00 2001 From: bakaneko Date: Wed, 18 Sep 2024 18:12:52 +0900 Subject: [PATCH 04/17] unused import --- app/helpers.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/helpers.php b/app/helpers.php index 99039ea75cc..51053a3aec2 100644 --- a/app/helpers.php +++ b/app/helpers.php @@ -9,7 +9,6 @@ use App\Libraries\Base64Url; use App\Libraries\LocaleMeta; use App\Models\LoginAttempt; -use App\Models\Model; use Egulias\EmailValidator\EmailValidator; use Egulias\EmailValidator\Validation\NoRFCWarningsValidation; use Illuminate\Database\Migrations\Migration; From 7c73b1c916cd3968c31479d311702e365b406b69 Mon Sep 17 00:00:00 2001 From: nanaya Date: Sat, 28 Sep 2024 23:11:41 +0900 Subject: [PATCH 05/17] Fix params handler not returning expected array Most (if not all) usage of it already assumes the function returns array with specified keys when `null_missing` is enabled. --- app/helpers.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/app/helpers.php b/app/helpers.php index 23dc6dd75c5..22804bce7af 100644 --- a/app/helpers.php +++ b/app/helpers.php @@ -1605,9 +1605,13 @@ function get_params($input, $namespace, $keys, $options = []) $params = []; - if (Arr::accessible($input)) { - $options['null_missing'] = $options['null_missing'] ?? false; + $options['null_missing'] ??= false; + + if (!Arr::accessible($input) && $options['null_missing']) { + $input = []; + } + if (Arr::accessible($input)) { foreach ($keys as $keyAndType) { $keyAndType = explode(':', $keyAndType); From 6b226ddf4bee98a5e77e93a56637ab1d8a94ed0c Mon Sep 17 00:00:00 2001 From: nanaya Date: Thu, 26 Sep 2024 21:19:52 +0900 Subject: [PATCH 06/17] Put back announcement channel user listing --- .../Chat/Channels/UsersController.php | 48 +++++++++++++++++++ app/Models/Chat/UserChannel.php | 9 ++++ resources/css/bem/chat-conversation.less | 16 ++++++- resources/js/chat/chat-api.ts | 12 +++++ resources/js/chat/conversation-view.tsx | 35 ++++++++++---- resources/js/models/chat/channel.ts | 40 +++++++++------- routes/web.php | 1 + 7 files changed, 133 insertions(+), 28 deletions(-) create mode 100644 app/Http/Controllers/Chat/Channels/UsersController.php diff --git a/app/Http/Controllers/Chat/Channels/UsersController.php b/app/Http/Controllers/Chat/Channels/UsersController.php new file mode 100644 index 00000000000..b04d29aa073 --- /dev/null +++ b/app/Http/Controllers/Chat/Channels/UsersController.php @@ -0,0 +1,48 @@ +. Licensed under the GNU Affero General Public License v3.0. +// See the LICENCE file in the repository root for full licence text. + +namespace App\Http\Controllers\Chat\Channels; + +use App\Http\Controllers\Chat\Controller; +use App\Models\Chat\Channel; +use App\Models\Chat\UserChannel; +use App\Models\User; +use App\Transformers\UserCompactTransformer; + +class UsersController extends Controller +{ + public function index($channelId) + { + $channel = Channel::findOrFail($channelId); + + if (!$channel->isAnnouncement() || !priv_check('ChatAnnounce', $channel)->can()) { + return [ + 'users' => [], + ...cursor_for_response(null), + ]; + } + + $channel = Channel::findOrFail($channelId); + $cursorHelper = UserChannel::makeDbCursorHelper(); + [$userChannels, $hasMore] = $channel + ->userChannels() + ->select('user_id') + ->limit(UserChannel::PER_PAGE) + ->cursorSort($cursorHelper, cursor_from_params(\Request::all())) + ->getWithHasMore(); + $users = User + ::with(UserCompactTransformer::CARD_INCLUDES_PRELOAD) + ->find($userChannels->pluck('user_id')); + + return [ + 'users' => json_collection( + $users, + new UserCompactTransformer(), + UserCompactTransformer::CARD_INCLUDES, + ), + ...cursor_for_response($cursorHelper->next($userChannels, $hasMore)), + ]; + } +} diff --git a/app/Models/Chat/UserChannel.php b/app/Models/Chat/UserChannel.php index ac16373952a..62631b78b24 100644 --- a/app/Models/Chat/UserChannel.php +++ b/app/Models/Chat/UserChannel.php @@ -6,6 +6,7 @@ namespace App\Models\Chat; use App\Libraries\Notification\BatchIdentities; +use App\Models\Traits\WithDbCursorHelper; use App\Models\User; use App\Models\UserNotification; use DB; @@ -20,6 +21,14 @@ */ class UserChannel extends Model { + use WithDbCursorHelper; + + const DEFAULT_SORT = 'user_id_asc'; + + const SORTS = [ + 'user_id_asc' => [['column' => 'user_id', 'order' => 'ASC']], + ]; + public $incrementing = false; public $timestamps = false; diff --git a/resources/css/bem/chat-conversation.less b/resources/css/bem/chat-conversation.less index 903276fed0d..dc4bf178616 100644 --- a/resources/css/bem/chat-conversation.less +++ b/resources/css/bem/chat-conversation.less @@ -66,6 +66,12 @@ margin-top: 10px; } + &__more-users { + width: 100%; + display: flex; + justify-content: center; + } + &__unread-marker { border-bottom: 1px solid @osu-colour-h1; color: @osu-colour-h1; @@ -106,10 +112,18 @@ gap: 2px; align-content: center; justify-content: center; - margin: 10px; &--loading { gap: 5px; } } + + &__users-container { + .default-border-radius(); + background-color: hsl(var(--hsl-b5)); + padding: 5px; + display: grid; + gap: 5px; + margin: 10px; + } } diff --git a/resources/js/chat/chat-api.ts b/resources/js/chat/chat-api.ts index f4d568db0fc..78974cd1297 100644 --- a/resources/js/chat/chat-api.ts +++ b/resources/js/chat/chat-api.ts @@ -16,6 +16,11 @@ interface GetChannelResponse { users: UserJson[]; } +interface GetChannelUsersResponse { + cursor_string: null | string; + users: UserJson[]; +} + interface GetMessagesResponse { messages: MessageJson[]; users: UserJson[]; @@ -56,6 +61,13 @@ export function getChannel(channelId: number) { })); } +export function getChannelUsers(channelId: number, cursor: string) { + return $.get(route('chat.channels.users.index', { + channel: channelId, + cursor_string: cursor, + })) as JQuery.jqXHR; +} + export function getMessages(channelId: number, params?: { until?: number }) { const request = $.get(route('chat.channels.messages.index', { channel: channelId, return_object: 1, ...params })) as JQuery.jqXHR; diff --git a/resources/js/chat/conversation-view.tsx b/resources/js/chat/conversation-view.tsx index 15c1dfaf53f..15fb5ba3290 100644 --- a/resources/js/chat/conversation-view.tsx +++ b/resources/js/chat/conversation-view.tsx @@ -259,16 +259,33 @@ export default class ConversationView extends React.Component { renderUsers() { if (this.currentChannel?.type !== 'ANNOUNCE') return null; + const users = this.currentChannel.users; + + if (users != null && users.length === 0) { + return null; + } + return ( -
- {this.currentChannel.announcementUsers == null ? ( - <> - {trans('chat.loading_users')} - - ) : ( - this.currentChannel.announcementUsers.map((user) => ( - - )) +
+
+ {users == null ? ( + <> + {trans('chat.loading_users')} + + ) : ( + users.map((user) => ( + + )) + )} +
+ {users != null && this.currentChannel.usersCursor != null && ( +
+ +
)}
); diff --git a/resources/js/models/chat/channel.ts b/resources/js/models/chat/channel.ts index 0d0972db99d..625daaa99ae 100644 --- a/resources/js/models/chat/channel.ts +++ b/resources/js/models/chat/channel.ts @@ -1,12 +1,13 @@ // Copyright (c) ppy Pty Ltd . Licensed under the GNU Affero General Public License v3.0. // See the LICENCE file in the repository root for full licence text. -import { markAsRead, getChannel, getMessages } from 'chat/chat-api'; +import { markAsRead, getChannel, getChannelUsers, getMessages } from 'chat/chat-api'; import ChannelJson, { ChannelType, SupportedChannelType, supportedTypeLookup } from 'interfaces/chat/channel-json'; import MessageJson from 'interfaces/chat/message-json'; +import UserJson from 'interfaces/user-json'; import { sortBy, throttle } from 'lodash'; import { action, computed, makeObservable, observable, runInAction } from 'mobx'; -import User, { usernameSortAscending } from 'models/user'; +import User from 'models/user'; import core from 'osu-core-singleton'; import Message from './message'; @@ -38,6 +39,7 @@ export default class Channel { @observable lastReadId?: number; @observable loadingEarlierMessages = false; @observable loadingMessages = false; + @observable loadUsersXhr: ReturnType | undefined; @observable messageLengthLimit = maxMessageLength; @observable name = ''; needsRefresh = true; @@ -49,21 +51,12 @@ export default class Channel { scrollY: 0, }; @observable userIds: number[] = []; + @observable users: null | UserJson[] = null; + @observable usersCursor: null | string = ''; private markAsReadLastSent = 0; @observable private readonly messagesMap = new Map(); private serverLastMessageId?: number; - @observable private usersLoaded = false; - - @computed - get announcementUsers() { - return this.usersLoaded - ? this.userIds - .map((userId) => core.dataStore.userStore.get(userId)) - .filter((u): u is User => u != null) - .sort(usernameSortAscending) - : null; - } @computed get canMessage() { @@ -204,10 +197,7 @@ export default class Channel { // nothing to load if (this.newPmChannel) return; - if (this.type === 'ANNOUNCE' && !this.usersLoaded) { - this.loadMetadata(); - } - + this.loadUsers(); this.loadRecentMessages(); } @@ -246,11 +236,25 @@ export default class Channel { getChannel(this.channelId).done((json) => { runInAction(() => { this.updateWithJson(json); - this.usersLoaded = true; }); }); } + @action + readonly loadUsers = () => { + if (this.type !== 'ANNOUNCE' || this.usersCursor == null || this.loadUsersXhr != null) { + return; + } + + this.loadUsersXhr = getChannelUsers(this.channelId, this.usersCursor) + .done((json) => runInAction(() => { + this.users = [...(this.users ?? []), ...json.users]; + this.usersCursor = json.cursor_string; + })).always(action(() => { + this.loadUsersXhr = undefined; + })); + }; + @action moveMarkAsReadMarker() { this.setLastReadId(this.lastMessageId); diff --git a/routes/web.php b/routes/web.php index 06070decb2c..9d1f9cb1712 100644 --- a/routes/web.php +++ b/routes/web.php @@ -187,6 +187,7 @@ Route::get('updates', 'ChatController@updates')->name('updates'); Route::group(['as' => 'channels.', 'prefix' => 'channels'], function () { Route::apiResource('{channel}/messages', 'Channels\MessagesController', ['only' => ['index', 'store']]); + Route::apiResource('{channel}/users', 'Channels\UsersController', ['only' => ['index']]); Route::put('{channel}/users/{user}', 'ChannelsController@join')->name('join'); Route::delete('{channel}/users/{user}', 'ChannelsController@part')->name('part'); Route::put('{channel}/mark-as-read/{message}', 'ChannelsController@markAsRead')->name('mark-as-read'); From 5072a6ad184e477fa1dee628b58b3b2093f6d61f Mon Sep 17 00:00:00 2001 From: nanaya Date: Tue, 1 Oct 2024 20:29:53 +0900 Subject: [PATCH 07/17] Improve chat announcement permission message --- app/Singletons/OsuAuthorize.php | 2 +- resources/lang/en/authorization.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Singletons/OsuAuthorize.php b/app/Singletons/OsuAuthorize.php index 2ae7d2041cd..9607bdf5cd2 100644 --- a/app/Singletons/OsuAuthorize.php +++ b/app/Singletons/OsuAuthorize.php @@ -863,7 +863,7 @@ public function checkChatAnnounce(?User $user): string return 'ok'; } - return $prefix.'annnonce_only'; + return $prefix.'no_announce'; } /** diff --git a/resources/lang/en/authorization.php b/resources/lang/en/authorization.php index 804f05c1cc7..7eec1d3ea6d 100644 --- a/resources/lang/en/authorization.php +++ b/resources/lang/en/authorization.php @@ -61,11 +61,11 @@ ], 'chat' => [ - 'annnonce_only' => 'This channel is for announcements only.', 'blocked' => 'Cannot message a user that is blocking you or that you have blocked.', 'friends_only' => 'User is blocking messages from people not on their friends list.', 'moderated' => 'This channel is currently moderated.', 'no_access' => 'You do not have access to that channel.', + 'no_announce' => 'You do not have permission to post announcement.', 'receive_friends_only' => 'The user may not be able to reply because you are only accepting messages from people on your friends list.', 'restricted' => 'You cannot send messages while silenced, restricted or banned.', 'silenced' => 'You cannot send messages while silenced, restricted or banned.', From da812ce451bcfd71e0092eca01579aeab4ee7425 Mon Sep 17 00:00:00 2001 From: nanaya Date: Tue, 1 Oct 2024 21:56:00 +0900 Subject: [PATCH 08/17] Allow prefilling reset password username --- resources/views/password_reset/index.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/views/password_reset/index.blade.php b/resources/views/password_reset/index.blade.php index 91ac1f495fc..d8235e796cb 100644 --- a/resources/views/password_reset/index.blade.php +++ b/resources/views/password_reset/index.blade.php @@ -4,7 +4,7 @@ --}} @php $params = [ - 'username' => null, + 'username' => presence(get_string(request('username'))), 'reason' => null, ...(Session::get('password_reset_start') ?? []), ]; From 3be56c8311f9f7f022792518d1fea35084f7491b Mon Sep 17 00:00:00 2001 From: bakaneko Date: Wed, 2 Oct 2024 15:45:10 +0900 Subject: [PATCH 09/17] default to 50 --- app/Models/BeatmapDiscussion.php | 2 -- app/Models/BeatmapDiscussionPost.php | 1 - app/Models/BeatmapDiscussionVote.php | 2 -- app/Models/BeatmapsetEvent.php | 2 -- 4 files changed, 7 deletions(-) diff --git a/app/Models/BeatmapDiscussion.php b/app/Models/BeatmapDiscussion.php index 9f925bcf14a..06fb22bd261 100644 --- a/app/Models/BeatmapDiscussion.php +++ b/app/Models/BeatmapDiscussion.php @@ -62,8 +62,6 @@ class BeatmapDiscussion extends Model 'review' => 5, ]; - const int PER_PAGE = 20; - const RESOLVABLE_TYPES = [1, 2]; const KUDOSUABLE_TYPES = [1, 2]; diff --git a/app/Models/BeatmapDiscussionPost.php b/app/Models/BeatmapDiscussionPost.php index 988b97a52ac..a02f502f0e6 100644 --- a/app/Models/BeatmapDiscussionPost.php +++ b/app/Models/BeatmapDiscussionPost.php @@ -31,7 +31,6 @@ class BeatmapDiscussionPost extends Model implements Traits\ReportableInterface const MESSAGE_LIMIT = 16_000; // column limit for 4 bytes utf8 const MESSAGE_LIMIT_TIMELINE = 750; - const int PER_PAGE = 20; protected $touches = ['beatmapDiscussion']; diff --git a/app/Models/BeatmapDiscussionVote.php b/app/Models/BeatmapDiscussionVote.php index d6b5d1c9c02..7006417adcc 100644 --- a/app/Models/BeatmapDiscussionVote.php +++ b/app/Models/BeatmapDiscussionVote.php @@ -19,8 +19,6 @@ */ class BeatmapDiscussionVote extends Model { - const int PER_PAGE = 20; - protected $touches = ['beatmapDiscussion']; public static function recentlyReceivedByUser($userId, $timeframeMonths = 3) diff --git a/app/Models/BeatmapsetEvent.php b/app/Models/BeatmapsetEvent.php index 6ecfeb184e2..2d0fabf891d 100644 --- a/app/Models/BeatmapsetEvent.php +++ b/app/Models/BeatmapsetEvent.php @@ -57,8 +57,6 @@ class BeatmapsetEvent extends Model const BEATMAP_OWNER_CHANGE = 'beatmap_owner_change'; - const int PER_PAGE = 20; - public static function log($type, $user, $object, $extraData = []) { if ($object instanceof BeatmapDiscussionPost) { From 0af1c0f23686f30d8be708a3ef38387b6a6d9968 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 3 Oct 2024 12:59:39 +0900 Subject: [PATCH 10/17] Update translations from crowdin --- resources/lang/be/home.php | 4 ++-- resources/lang/bg/beatmaps.php | 14 +++++++------- resources/lang/cs/beatmapsets.php | 2 +- resources/lang/cs/rankings.php | 8 ++++---- resources/lang/de/accounts.php | 2 +- resources/lang/de/rankings.php | 8 ++++---- resources/lang/es-419/beatmapsets.php | 2 +- resources/lang/es-419/rankings.php | 8 ++++---- resources/lang/es/beatmapsets.php | 2 +- resources/lang/es/rankings.php | 8 ++++---- resources/lang/fr/accounts.php | 2 +- resources/lang/fr/beatmapsets.php | 2 +- resources/lang/fr/rankings.php | 8 ++++---- resources/lang/id/beatmaps.php | 2 +- resources/lang/id/beatmapsets.php | 2 +- resources/lang/id/notifications.php | 6 +++--- resources/lang/id/rankings.php | 8 ++++---- resources/lang/it/beatmapsets.php | 2 +- resources/lang/it/rankings.php | 8 ++++---- resources/lang/it/users.php | 4 ++-- resources/lang/ko/beatmapsets.php | 14 +++++++------- resources/lang/ko/rankings.php | 10 +++++----- resources/lang/ko/users.php | 4 ++-- resources/lang/pl/rankings.php | 4 ++-- resources/lang/pt-br/beatmapsets.php | 2 +- resources/lang/pt-br/rankings.php | 8 ++++---- resources/lang/pt/beatmapsets.php | 2 +- resources/lang/pt/rankings.php | 8 ++++---- resources/lang/pt/users.php | 2 +- resources/lang/ro/rankings.php | 2 +- resources/lang/ru/accounts.php | 2 +- resources/lang/ru/beatmapsets.php | 2 +- resources/lang/ru/rankings.php | 8 ++++---- resources/lang/th/beatmapsets.php | 2 +- resources/lang/th/rankings.php | 8 ++++---- resources/lang/uk/beatmapsets.php | 2 +- resources/lang/uk/rankings.php | 8 ++++---- resources/lang/vi/rankings.php | 4 ++-- resources/lang/zh-tw/beatmapsets.php | 2 +- resources/lang/zh-tw/rankings.php | 8 ++++---- resources/lang/zh/accounts.php | 2 +- resources/lang/zh/beatmaps.php | 2 +- resources/lang/zh/beatmapsets.php | 2 +- resources/lang/zh/model_validation.php | 2 +- resources/lang/zh/rankings.php | 8 ++++---- resources/lang/zh/users.php | 12 ++++++------ 46 files changed, 116 insertions(+), 116 deletions(-) diff --git a/resources/lang/be/home.php b/resources/lang/be/home.php index 3f5a05d4b80..461d9c6f529 100644 --- a/resources/lang/be/home.php +++ b/resources/lang/be/home.php @@ -74,11 +74,11 @@ 'download' => [ 'action' => 'Спампаваць osu!', - 'action_lazer' => 'Скачаць osu!(lazer)', + 'action_lazer' => 'Спампаваць osu!(lazer)', 'action_lazer_description' => 'наступнае глабальнае абнаўленне osu!', 'action_lazer_info' => 'артыкул з падрабязнай інфармацыяй', 'action_lazer_title' => 'паспрабаваць osu!(lazer)', - 'action_title' => 'скачаць osu!', + 'action_title' => 'спампаваць osu!', 'for_os' => 'для :os', 'macos-fallback' => 'для macOS', 'mirror' => 'люстэрка', diff --git a/resources/lang/bg/beatmaps.php b/resources/lang/bg/beatmaps.php index a0be5d126b7..f99334b7d6b 100644 --- a/resources/lang/bg/beatmaps.php +++ b/resources/lang/bg/beatmaps.php @@ -24,11 +24,11 @@ 'message_placeholder_locked' => 'Изключена е дискусията за този бийтмап.', 'message_placeholder_silenced' => "Не може да публикувате дискусии, докато сте заглушени.", 'message_type_select' => 'Избор на вид коментар', - 'reply_notice' => 'Натисни enter за отговор.', + 'reply_notice' => 'Натиснете enter, за да отговорите.', 'reply_resolve_notice' => '', 'reply_placeholder' => 'Въведете вашия отговор тук', - 'require-login' => 'Моля, влез в профила си, за публикуване или отговор', - 'resolved' => 'Приключен', + 'require-login' => 'Моля, влезте в профила си, за да публикувате или отговаряте', + 'resolved' => 'Разрешени', 'restore' => 'възстанови', 'show_deleted' => 'Покажи изтрити', 'title' => 'Дискусии', @@ -46,13 +46,13 @@ 'lock' => [ 'button' => [ - 'lock' => 'Заключи дискусия', - 'unlock' => 'Отключи дискусия', + 'lock' => 'Заключи дискусията', + 'unlock' => 'Отключи дискусията', ], 'prompt' => [ - 'lock' => 'Причина за заключване', - 'unlock' => 'Наистина ли искате да отключите?', + 'lock' => 'Причина за заключването', + 'unlock' => 'Сигурни ли сте, че искате да отключите дискусията?', ], ], diff --git a/resources/lang/cs/beatmapsets.php b/resources/lang/cs/beatmapsets.php index d6043df8b09..4606c1a5e10 100644 --- a/resources/lang/cs/beatmapsets.php +++ b/resources/lang/cs/beatmapsets.php @@ -52,7 +52,7 @@ 'dialog' => [ 'confirmation' => 'Jste si jisti, že chcete nominovat tuto beatmapu?', - 'different_nominator_warning' => '', + 'different_nominator_warning' => 'Kvalifikace této beatmapy s jinými nominátory vyresetuje její pozici ve frontě kvalifikací.', 'header' => 'Nominovat beatmapu', 'hybrid_warning' => 'poznámka: můžete nominovat pouze jednou, takže se ujistěte, že nominujete za všechny herní režimy, které chcete', 'current_main_ruleset' => 'Hlavní ruleset je aktuálně: :ruleset', diff --git a/resources/lang/cs/rankings.php b/resources/lang/cs/rankings.php index 369bb33d25b..21c34634725 100644 --- a/resources/lang/cs/rankings.php +++ b/resources/lang/cs/rankings.php @@ -10,9 +10,9 @@ ], 'daily_challenge' => [ - 'beatmap' => '', - 'percentile_10' => '', - 'percentile_50' => '', + 'beatmap' => 'Obtížnost', + 'percentile_10' => 'Skóre 10. percentilu', + 'percentile_50' => 'Skóre 50. percentilu', ], 'filter' => [ @@ -36,7 +36,7 @@ 'type' => [ 'charts' => 'výběry (staré)', 'country' => 'stát', - 'daily_challenge' => '', + 'daily_challenge' => 'denní výzva', 'kudosu' => 'kudosu', 'multiplayer' => 'hra pro více hráčů', 'performance' => 'výkon', diff --git a/resources/lang/de/accounts.php b/resources/lang/de/accounts.php index 4b0d138dc77..aaadc7089ae 100644 --- a/resources/lang/de/accounts.php +++ b/resources/lang/de/accounts.php @@ -81,7 +81,7 @@ 'beatmapset_disqualify' => 'Erhalte Benachrichtigungen, wenn Beatmaps der folgenden Modi disqualifiziert werden', 'comment_reply' => 'Erhalte Benachrichtigungen für Antworten auf deine Kommentare', 'title' => 'Benachrichtigungen', - 'topic_auto_subscribe' => 'Benachrichtigungen zu den von dir erstellten Forenposts immer aktivieren', + 'topic_auto_subscribe' => 'Benachrichtigungen zu den Forenposts, die du erstellt oder auf die du geantwortet hast, immer aktivieren', 'options' => [ '_' => 'Zustelloptionen', diff --git a/resources/lang/de/rankings.php b/resources/lang/de/rankings.php index 1e38f1cbb08..8d446f73e21 100644 --- a/resources/lang/de/rankings.php +++ b/resources/lang/de/rankings.php @@ -10,9 +10,9 @@ ], 'daily_challenge' => [ - 'beatmap' => '', - 'percentile_10' => '', - 'percentile_50' => '', + 'beatmap' => 'Level', + 'percentile_10' => 'Punktzahl im 10ten Perzentil', + 'percentile_50' => 'Median', ], 'filter' => [ @@ -36,7 +36,7 @@ 'type' => [ 'charts' => 'Spotlights (alt)', 'country' => 'Länder', - 'daily_challenge' => '', + 'daily_challenge' => 'Tägliche Herausforderung', 'kudosu' => 'Kudosu', 'multiplayer' => 'Mehrspieler', 'performance' => 'Performance', diff --git a/resources/lang/es-419/beatmapsets.php b/resources/lang/es-419/beatmapsets.php index 23969e1bf21..6806be11a82 100644 --- a/resources/lang/es-419/beatmapsets.php +++ b/resources/lang/es-419/beatmapsets.php @@ -52,7 +52,7 @@ 'dialog' => [ 'confirmation' => '¿Estás seguro de que quieres nominar este mapa?', - 'different_nominator_warning' => '', + 'different_nominator_warning' => 'Calificar este mapa con diferentes nominadores restablecerá su posición en la cola de calificación.', 'header' => 'Nominar mapa', 'hybrid_warning' => 'nota: solo puedes nominar una vez, así que asegúrate de que estás nominando todos los modos de juego que quieres nominar', 'current_main_ruleset' => 'El modo de juego principal es: :ruleset', diff --git a/resources/lang/es-419/rankings.php b/resources/lang/es-419/rankings.php index 82692639c77..ee261f98e8b 100644 --- a/resources/lang/es-419/rankings.php +++ b/resources/lang/es-419/rankings.php @@ -10,9 +10,9 @@ ], 'daily_challenge' => [ - 'beatmap' => '', - 'percentile_10' => '', - 'percentile_50' => '', + 'beatmap' => 'Dificultad', + 'percentile_10' => 'Puntuación requerida para quedar dentro del top 10 %', + 'percentile_50' => 'Puntuación requerida para quedar dentro del top 50 %', ], 'filter' => [ @@ -36,7 +36,7 @@ 'type' => [ 'charts' => 'spotlights (viejo)', 'country' => 'país', - 'daily_challenge' => '', + 'daily_challenge' => 'desafío diario', 'kudosu' => 'kudosu', 'multiplayer' => 'multijugador', 'performance' => 'rendimiento', diff --git a/resources/lang/es/beatmapsets.php b/resources/lang/es/beatmapsets.php index 3449c9ebbe9..598f6f28502 100644 --- a/resources/lang/es/beatmapsets.php +++ b/resources/lang/es/beatmapsets.php @@ -52,7 +52,7 @@ 'dialog' => [ 'confirmation' => '¿Estás seguro de que quieres nominar este mapa?', - 'different_nominator_warning' => '', + 'different_nominator_warning' => 'Calificar este mapa con diferentes nominadores restablecerá su posición en la cola de calificación.', 'header' => 'Nominar mapa', 'hybrid_warning' => 'nota: solo puedes nominar una vez, así que asegúrate de que estás nominando para todos los modos de juego que desees', 'current_main_ruleset' => 'El modo de juego principal es: :ruleset', diff --git a/resources/lang/es/rankings.php b/resources/lang/es/rankings.php index 9b65d670f35..6183571a5bf 100644 --- a/resources/lang/es/rankings.php +++ b/resources/lang/es/rankings.php @@ -10,9 +10,9 @@ ], 'daily_challenge' => [ - 'beatmap' => '', - 'percentile_10' => '', - 'percentile_50' => '', + 'beatmap' => 'Dificultad', + 'percentile_10' => 'Puntuación requerida para quedar dentro del top 10 %', + 'percentile_50' => 'Puntuación requerida para quedar dentro del top 50 %', ], 'filter' => [ @@ -36,7 +36,7 @@ 'type' => [ 'charts' => 'destacados', 'country' => 'país', - 'daily_challenge' => '', + 'daily_challenge' => 'desafío diario', 'kudosu' => 'kudosu', 'multiplayer' => 'multijugador', 'performance' => 'rendimiento', diff --git a/resources/lang/fr/accounts.php b/resources/lang/fr/accounts.php index 3824dadaff8..6f46c70251a 100644 --- a/resources/lang/fr/accounts.php +++ b/resources/lang/fr/accounts.php @@ -81,7 +81,7 @@ 'beatmapset_disqualify' => 'recevoir des notifications lorsque des beatmaps sont disqualifiées dans les modes suivants', 'comment_reply' => 'recevoir des notifications pour des réponses à vos commentaires', 'title' => 'Notifications', - 'topic_auto_subscribe' => 'activer automatiquement les notifications sur les nouveaux sujets que vous créez sur le forum', + 'topic_auto_subscribe' => 'activer automatiquement les notifications sur les nouveaux sujets que vous créez ou auxquels vous avez répondu sur le forum', 'options' => [ '_' => 'types d\'alertes', diff --git a/resources/lang/fr/beatmapsets.php b/resources/lang/fr/beatmapsets.php index 5bc95090f0b..c62eff48de2 100644 --- a/resources/lang/fr/beatmapsets.php +++ b/resources/lang/fr/beatmapsets.php @@ -52,7 +52,7 @@ 'dialog' => [ 'confirmation' => 'Êtes-vous sûr de vouloir nominer cette beatmap ?', - 'different_nominator_warning' => '', + 'different_nominator_warning' => 'Qualifier cette beatmap avec différents nominateurs réinitialisera sa position dans la file de qualification.', 'header' => 'Nominer la beatmap', 'hybrid_warning' => 'remarque : vous ne pouvez nominer qu\'une seule fois, assurez-vous alors que vous nominez la beatmap pour tous les modes de jeu que vous souhaitez', 'current_main_ruleset' => 'Le mode de jeu principal est actuellement : :ruleset', diff --git a/resources/lang/fr/rankings.php b/resources/lang/fr/rankings.php index 747b73b086a..135a7ee542f 100644 --- a/resources/lang/fr/rankings.php +++ b/resources/lang/fr/rankings.php @@ -10,9 +10,9 @@ ], 'daily_challenge' => [ - 'beatmap' => '', - 'percentile_10' => '', - 'percentile_50' => '', + 'beatmap' => 'Difficulté', + 'percentile_10' => 'Score du 10ᵉ centile', + 'percentile_50' => 'Score médian', ], 'filter' => [ @@ -36,7 +36,7 @@ 'type' => [ 'charts' => 'spotlights (ancien)', 'country' => 'pays', - 'daily_challenge' => '', + 'daily_challenge' => 'défi du jour', 'kudosu' => 'kudosu', 'multiplayer' => 'multijoueur', 'performance' => 'performance', diff --git a/resources/lang/id/beatmaps.php b/resources/lang/id/beatmaps.php index 4bf1a76a426..a16d66819e1 100644 --- a/resources/lang/id/beatmaps.php +++ b/resources/lang/id/beatmaps.php @@ -218,7 +218,7 @@ 'unresolved_problems' => 'Beatmap ini sedang diblokir untuk dapat melewati kategori Qualified hingga :problems terselesaikan.', 'problems' => 'masalah berikut', 'on' => 'pada tanggal :date', - 'queue' => 'antrian ranking', + 'queue' => 'antrean ranking', 'soon' => 'segera', ], diff --git a/resources/lang/id/beatmapsets.php b/resources/lang/id/beatmapsets.php index 257d22cbdb1..9ccb9287203 100644 --- a/resources/lang/id/beatmapsets.php +++ b/resources/lang/id/beatmapsets.php @@ -52,7 +52,7 @@ 'dialog' => [ 'confirmation' => 'Apakah kamu yakin untuk menominasikan beatmap ini?', - 'different_nominator_warning' => '', + 'different_nominator_warning' => 'Mengkualifikasikan beatmap ini dengan nominator yang berbeda akan mengatur ulang posisi antrean kualifikasinya.', 'header' => 'Nominasikan Beatmap', 'hybrid_warning' => 'catatan: kamu hanya dapat memberikan nominasi satu kali, sehingga pastikan kamu memberikan nominasi pada mode permainan yang memang kamu kehendaki', 'current_main_ruleset' => 'Ruleset utama saat ini: :ruleset', diff --git a/resources/lang/id/notifications.php b/resources/lang/id/notifications.php index 4fa32494cd7..7fda9c4df77 100644 --- a/resources/lang/id/notifications.php +++ b/resources/lang/id/notifications.php @@ -79,8 +79,8 @@ 'beatmapset_love_compact' => 'Beatmap telah dipromosikan ke kategori Loved', 'beatmapset_nominate' => '":title" telah dinominasikan', 'beatmapset_nominate_compact' => 'Beatmap telah dinominasikan', - 'beatmapset_qualify' => '":title" telah memperoleh jumlah nominasi yang dibutuhkan untuk dapat memasuki antrian ranking', - 'beatmapset_qualify_compact' => 'Beatmap memasuki antrian ranking', + 'beatmapset_qualify' => '":title" telah memperoleh jumlah nominasi yang dibutuhkan untuk dapat memasuki antrean ranking', + 'beatmapset_qualify_compact' => 'Beatmap memasuki antrean ranking', 'beatmapset_rank' => '":title" telah berstatus Ranked', 'beatmapset_rank_compact' => 'Beatmap telah berstatus Ranked', 'beatmapset_remove_from_loved' => '":title" telah dilepas dari Loved', @@ -204,7 +204,7 @@ 'beatmapset_disqualify' => '":title" telah didiskualifikasi', 'beatmapset_love' => '":title" telah dipromosikan ke kategori Loved', 'beatmapset_nominate' => '":title" telah dinominasikan', - 'beatmapset_qualify' => '":title" telah memperoleh jumlah nominasi yang dibutuhkan untuk dapat memasuki antrian ranking', + 'beatmapset_qualify' => '":title" telah memperoleh jumlah nominasi yang dibutuhkan untuk dapat memasuki antrean ranking', 'beatmapset_rank' => '":title" telah berstatus Ranked', 'beatmapset_remove_from_loved' => ':title telah dilepas dari Loved', 'beatmapset_reset_nominations' => 'Nominasi pada beatmap ":title" telah dianulir', diff --git a/resources/lang/id/rankings.php b/resources/lang/id/rankings.php index 9eacb3cc312..11e9258508a 100644 --- a/resources/lang/id/rankings.php +++ b/resources/lang/id/rankings.php @@ -10,9 +10,9 @@ ], 'daily_challenge' => [ - 'beatmap' => '', - 'percentile_10' => '', - 'percentile_50' => '', + 'beatmap' => 'Tingkat Kesulitan', + 'percentile_10' => 'Skor Persentil Ke-10', + 'percentile_50' => 'Skor Persentil Ke-50', ], 'filter' => [ @@ -36,7 +36,7 @@ 'type' => [ 'charts' => 'spotlights', 'country' => 'negara', - 'daily_challenge' => '', + 'daily_challenge' => 'tantangan harian', 'kudosu' => 'kudosu', 'multiplayer' => 'multiplayer', 'performance' => 'performa', diff --git a/resources/lang/it/beatmapsets.php b/resources/lang/it/beatmapsets.php index 3255f19ddb4..5136a3b91f4 100644 --- a/resources/lang/it/beatmapsets.php +++ b/resources/lang/it/beatmapsets.php @@ -52,7 +52,7 @@ 'dialog' => [ 'confirmation' => 'Sei sicuro di voler nominare questa beatmap?', - 'different_nominator_warning' => '', + 'different_nominator_warning' => 'Qualificare questa beatmap con diversi nominatori resetterà la sua posizione nella coda di qualifica.', 'header' => 'Nomina Beatmap', 'hybrid_warning' => 'nota: puoi nominare una sola volta, quindi assicurati di nominare per tutte le modalità di gioco che vuoi', 'current_main_ruleset' => 'La modalità principale al momento è: :ruleset', diff --git a/resources/lang/it/rankings.php b/resources/lang/it/rankings.php index 817c8caf34e..daf14785067 100644 --- a/resources/lang/it/rankings.php +++ b/resources/lang/it/rankings.php @@ -10,9 +10,9 @@ ], 'daily_challenge' => [ - 'beatmap' => '', - 'percentile_10' => '', - 'percentile_50' => '', + 'beatmap' => 'Difficoltà', + 'percentile_10' => 'Punteggio nel primo 10%', + 'percentile_50' => 'Punteggio nel primo 50%', ], 'filter' => [ @@ -36,7 +36,7 @@ 'type' => [ 'charts' => 'spotlight (archivio)', 'country' => 'paese', - 'daily_challenge' => '', + 'daily_challenge' => 'sfida giornaliera', 'kudosu' => 'kudosu', 'multiplayer' => 'multigiocatore', 'performance' => 'performance', diff --git a/resources/lang/it/users.php b/resources/lang/it/users.php index 4bf24370cbd..979384a831b 100644 --- a/resources/lang/it/users.php +++ b/resources/lang/it/users.php @@ -202,8 +202,8 @@ 'daily_streak_current' => 'Attuale Serie Giornaliera', 'playcount' => 'Partecipazione Totale', 'title' => 'Sfida\nGiornaliera', - 'top_10p_placements' => 'Raggiungimenti del primo 10%', - 'top_50p_placements' => 'Raggiungimenti del primo 50%', + 'top_10p_placements' => 'Piazzamenti nel primo 10%', + 'top_50p_placements' => 'Piazzamenti nel primo 50%', 'weekly' => 'Serie Settimanale', 'weekly_streak_best' => 'Migliore Serie Settimanale', 'weekly_streak_current' => 'Attuale Serie Settimanale', diff --git a/resources/lang/ko/beatmapsets.php b/resources/lang/ko/beatmapsets.php index 89aad973ffb..668594238d9 100644 --- a/resources/lang/ko/beatmapsets.php +++ b/resources/lang/ko/beatmapsets.php @@ -41,21 +41,21 @@ ], 'nominate' => [ - 'bng_limited_too_many_rulesets' => '', - 'full_nomination_required' => '', + 'bng_limited_too_many_rulesets' => '견습 노미네이터는 여러 게임 모드를 가진 비트맵을 노미네이트 할 수 없습니다.', + 'full_nomination_required' => '이 게임 모드를 최종 노미네이션 하려면 정식 노미네이터여야 합니다.', 'hybrid_requires_modes' => '하이브리드 비트맵 셋은 노미네이트 할 플레이 모드를 하나 이상 선택해야 합니다.', 'incorrect_mode' => ':mode 모드를 노미네이트 할 권한을 가지고 있지 않습니다.', - 'invalid_limited_nomination' => '', - 'invalid_ruleset' => '', + 'invalid_limited_nomination' => '이 비트맵에 적합하지 않은 노미네이션이 있어 Qualify 할 수 없는 상태입니다.', + 'invalid_ruleset' => '이 노미네이션의 게임 모드가 잘못되었습니다.', 'too_many' => '노미네이션 요구 사항을 이미 만족했습니다.', - 'too_many_non_main_ruleset' => '', + 'too_many_non_main_ruleset' => '메인이 아닌 모드에 대한 노미네이션 조건이 충족되었습니다.', 'dialog' => [ 'confirmation' => '정말로 이 비트맵을 노미네이트 하시겠어요?', - 'different_nominator_warning' => '', + 'different_nominator_warning' => '다른 노미네이터가 이 비트맵을 Qualify하면 Qualification 대기열의 순서가 초기화됩니다.', 'header' => '비트맵 노미네이트', 'hybrid_warning' => '주의: 딱 한 번만 노미네이트 할 수 있으므로 자신이 노미네이트 하려는 모든 게임 모드를 선택했는지 확인해주세요.', - 'current_main_ruleset' => '', + 'current_main_ruleset' => '메인 모드는 현재 :ruleset입니다.', 'which_modes' => '어떤 모드를 노미네이트 하겠습니까?', ], ], diff --git a/resources/lang/ko/rankings.php b/resources/lang/ko/rankings.php index 319844bb55c..a8fbea281b4 100644 --- a/resources/lang/ko/rankings.php +++ b/resources/lang/ko/rankings.php @@ -10,9 +10,9 @@ ], 'daily_challenge' => [ - 'beatmap' => '', - 'percentile_10' => '', - 'percentile_50' => '', + 'beatmap' => '난이도', + 'percentile_10' => '상위 10% 점수', + 'percentile_50' => '상위 50% 점수', ], 'filter' => [ @@ -30,13 +30,13 @@ ], 'performance' => [ - 'insufficient_history' => '', + 'insufficient_history' => '해당 유저는 랭킹 이력이 최근 30일 이내입니다.', ], 'type' => [ 'charts' => '스포트라이트', 'country' => '국가별', - 'daily_challenge' => '', + 'daily_challenge' => '데일리 챌린지', 'kudosu' => 'Kudosu', 'multiplayer' => '멀티플레이어', 'performance' => '퍼포먼스', diff --git a/resources/lang/ko/users.php b/resources/lang/ko/users.php index 354f8dbc029..b7161e87bd9 100644 --- a/resources/lang/ko/users.php +++ b/resources/lang/ko/users.php @@ -201,7 +201,7 @@ 'daily_streak_best' => '최다 연속 진행일 ', 'daily_streak_current' => '현재 연속 진행일', - 'playcount' => '', + 'playcount' => '참여 일수', 'title' => '일일미션', 'top_10p_placements' => '상위 10%', 'top_50p_placements' => '상위 50%', @@ -247,7 +247,7 @@ 'title' => '색상', 'supporter' => [ - '_' => '', + '_' => '커스텀 색상 테마는 :link만 사용할 수 있습니다.', 'link' => 'osu! 서포터', ], ], diff --git a/resources/lang/pl/rankings.php b/resources/lang/pl/rankings.php index 4062265a788..5ce456af9e6 100644 --- a/resources/lang/pl/rankings.php +++ b/resources/lang/pl/rankings.php @@ -10,7 +10,7 @@ ], 'daily_challenge' => [ - 'beatmap' => '', + 'beatmap' => 'Poziom trudności', 'percentile_10' => '', 'percentile_50' => '', ], @@ -36,7 +36,7 @@ 'type' => [ 'charts' => 'Wyróżnionych', 'country' => 'krajowy', - 'daily_challenge' => '', + 'daily_challenge' => 'wyzwanie dnia', 'kudosu' => 'kudosu', 'multiplayer' => 'wieloosobowy', 'performance' => 'globalny', diff --git a/resources/lang/pt-br/beatmapsets.php b/resources/lang/pt-br/beatmapsets.php index 49eef322c62..2528c4fd990 100644 --- a/resources/lang/pt-br/beatmapsets.php +++ b/resources/lang/pt-br/beatmapsets.php @@ -52,7 +52,7 @@ 'dialog' => [ 'confirmation' => 'Tem certeza que deseja nomear este Beatmap?', - 'different_nominator_warning' => '', + 'different_nominator_warning' => 'Qualificar esse beatmap com nominadores diferentes irá redefinir sua posição na fila de qualificação.', 'header' => 'Nomear Beatmap', 'hybrid_warning' => 'nota: você pode apenas nomear uma vez, então por favor, certifique-se de que você está nomeando para todos os modos de jogo que você pretende', 'current_main_ruleset' => 'A atual regra principal é: :ruleset', diff --git a/resources/lang/pt-br/rankings.php b/resources/lang/pt-br/rankings.php index 0112dafcf4f..b712ba486ed 100644 --- a/resources/lang/pt-br/rankings.php +++ b/resources/lang/pt-br/rankings.php @@ -10,9 +10,9 @@ ], 'daily_challenge' => [ - 'beatmap' => '', - 'percentile_10' => '', - 'percentile_50' => '', + 'beatmap' => 'Dificuldade', + 'percentile_10' => '10° percentual de pontuação', + 'percentile_50' => '50° percentual de pontuação', ], 'filter' => [ @@ -36,7 +36,7 @@ 'type' => [ 'charts' => 'Destaques', 'country' => 'país', - 'daily_challenge' => '', + 'daily_challenge' => 'desafio diário', 'kudosu' => 'kudosu', 'multiplayer' => 'multijogador', 'performance' => 'desempenho', diff --git a/resources/lang/pt/beatmapsets.php b/resources/lang/pt/beatmapsets.php index 3e9dbf511d1..32c7439eebd 100644 --- a/resources/lang/pt/beatmapsets.php +++ b/resources/lang/pt/beatmapsets.php @@ -52,7 +52,7 @@ 'dialog' => [ 'confirmation' => 'Tens a certeza que queres nomear este beatmap?', - 'different_nominator_warning' => '', + 'different_nominator_warning' => 'Qualificar este beatmaps com nominadores diferentes irá redefinir a tua posição na fila de qualificação.', 'header' => 'Nomear beatmap', 'hybrid_warning' => 'nota: poderás apenas nomear uma vez, por isso certifica-te de que estás a nomear para todos os modos de jogo que pretendes', 'current_main_ruleset' => 'O conjunto de regras principal está de momento: :ruleset', diff --git a/resources/lang/pt/rankings.php b/resources/lang/pt/rankings.php index 9c6a1c07a26..a2d4e340a54 100644 --- a/resources/lang/pt/rankings.php +++ b/resources/lang/pt/rankings.php @@ -11,9 +11,9 @@ ], 'daily_challenge' => [ - 'beatmap' => '', - 'percentile_10' => '', - 'percentile_50' => '', + 'beatmap' => 'Dificuldade', + 'percentile_10' => '10° percentual de pontuação', + 'percentile_50' => '50° percentual de pontuação', ], 'filter' => [ @@ -37,7 +37,7 @@ 'type' => [ 'charts' => 'Em destaque', 'country' => 'País', - 'daily_challenge' => '', + 'daily_challenge' => 'desafio diário', 'kudosu' => 'kudosu', 'multiplayer' => 'multijogador', 'performance' => 'Desempenho', diff --git a/resources/lang/pt/users.php b/resources/lang/pt/users.php index c4c94039698..abf00759239 100644 --- a/resources/lang/pt/users.php +++ b/resources/lang/pt/users.php @@ -200,7 +200,7 @@ 'daily' => 'Série de vitórias diária', 'daily_streak_best' => 'Melhor série de vitórias diária', 'daily_streak_current' => 'Série de vitórias diária atual', - 'playcount' => '', + 'playcount' => 'Participação total', 'title' => 'Desafio\nDiário', 'top_10p_placements' => 'Os melhores 10%', 'top_50p_placements' => 'Os melhores 50%', diff --git a/resources/lang/ro/rankings.php b/resources/lang/ro/rankings.php index ea8efd37b73..affacc8b5e5 100644 --- a/resources/lang/ro/rankings.php +++ b/resources/lang/ro/rankings.php @@ -36,7 +36,7 @@ 'type' => [ 'charts' => 'promovări', 'country' => 'național', - 'daily_challenge' => '', + 'daily_challenge' => 'provocare zilnică', 'kudosu' => 'kudosu', 'multiplayer' => 'multiplayer', 'performance' => 'performanță', diff --git a/resources/lang/ru/accounts.php b/resources/lang/ru/accounts.php index ecf74725a15..fd0c148719d 100644 --- a/resources/lang/ru/accounts.php +++ b/resources/lang/ru/accounts.php @@ -81,7 +81,7 @@ 'beatmapset_disqualify' => 'получать уведомления, когда карты для следующих режимов будут дисквалифицированы', 'comment_reply' => 'получать уведомления об ответах на комментарии', 'title' => 'Уведомления', - 'topic_auto_subscribe' => 'следить за темами на форуме, которые я создаю', + 'topic_auto_subscribe' => 'всегда подписываться на уведомления в новых темах на форуме, которые я создаю или в которых мне отвечают', 'options' => [ '_' => 'способы получения', diff --git a/resources/lang/ru/beatmapsets.php b/resources/lang/ru/beatmapsets.php index 02988d5a1cd..73fa343d690 100644 --- a/resources/lang/ru/beatmapsets.php +++ b/resources/lang/ru/beatmapsets.php @@ -52,7 +52,7 @@ 'dialog' => [ 'confirmation' => 'Вы уверены, что хотите номинировать эту карту?', - 'different_nominator_warning' => '', + 'different_nominator_warning' => 'Повторная квалификация этой карты парой номинаторов, отличающейся от изначальной, сбросит её позицию в очереди получения рейтинга.', 'header' => 'Номинировать карту', 'hybrid_warning' => 'примечание: Вы можете номинировать лишь один раз, так что убедитесь, что Вы номинируете все необходимые режимы игры', 'current_main_ruleset' => 'Текущий основной режим игры: :ruleset', diff --git a/resources/lang/ru/rankings.php b/resources/lang/ru/rankings.php index 3034082e2fd..74bd4568a50 100644 --- a/resources/lang/ru/rankings.php +++ b/resources/lang/ru/rankings.php @@ -10,9 +10,9 @@ ], 'daily_challenge' => [ - 'beatmap' => '', - 'percentile_10' => '', - 'percentile_50' => '', + 'beatmap' => 'Сложность', + 'percentile_10' => '90-й процентиль очков', + 'percentile_50' => '50-й процентиль очков', ], 'filter' => [ @@ -36,7 +36,7 @@ 'type' => [ 'charts' => 'по чартам (устар.)', 'country' => 'по странам', - 'daily_challenge' => '', + 'daily_challenge' => 'карта дня', 'kudosu' => 'по кудосу', 'multiplayer' => 'в мультиплеере', 'performance' => 'по производительности', diff --git a/resources/lang/th/beatmapsets.php b/resources/lang/th/beatmapsets.php index 87e7f81c51b..5a46f646679 100644 --- a/resources/lang/th/beatmapsets.php +++ b/resources/lang/th/beatmapsets.php @@ -52,7 +52,7 @@ 'dialog' => [ 'confirmation' => 'คุณแน่ใจที่จะเสนอชื่อแมพนี้ใช่ไหม', - 'different_nominator_warning' => '', + 'different_nominator_warning' => 'การผ่านคุณสมบัติบีทแมพนี้กับโนมิเนเตอร์ที่แตกต่างกันจะรีเซ็ตตำแหน่งในคิวการตรวจสอบคุณสมบัติ', 'header' => 'เสนอชื่อบีทแมพ', 'hybrid_warning' => 'โน้ต: คุณสามารถเสนอชื่อได้เพียงแค่ครั้งเดียว ดังนั้นโปรดตรวจสอบให้แน่ใจว่าคุณเสนอชื่อในเกมโหมดทั้งหมดที่คุณต้องการจะเสนอชื่อ', 'current_main_ruleset' => 'Ruleset ตอนนี้คือ: :ruleset', diff --git a/resources/lang/th/rankings.php b/resources/lang/th/rankings.php index eb1cf8a2608..522f39788f4 100644 --- a/resources/lang/th/rankings.php +++ b/resources/lang/th/rankings.php @@ -10,9 +10,9 @@ ], 'daily_challenge' => [ - 'beatmap' => '', - 'percentile_10' => '', - 'percentile_50' => '', + 'beatmap' => 'ระดับความยาก', + 'percentile_10' => 'คะแนนเปอร์เซ็นไทล์ที่ 10', + 'percentile_50' => 'คะแนนเปอร์เซ็นไทล์ที่ 50', ], 'filter' => [ @@ -36,7 +36,7 @@ 'type' => [ 'charts' => 'โดดเด่น', 'country' => 'ประเทศ', - 'daily_challenge' => '', + 'daily_challenge' => 'ชาเลนจ์ประจำวัน', 'kudosu' => 'kudosu', 'multiplayer' => 'โหมดผู้เล่นหลายคน', 'performance' => 'ประสิทธิภาพ', diff --git a/resources/lang/uk/beatmapsets.php b/resources/lang/uk/beatmapsets.php index 7284fc54c58..80ee71b9022 100644 --- a/resources/lang/uk/beatmapsets.php +++ b/resources/lang/uk/beatmapsets.php @@ -52,7 +52,7 @@ 'dialog' => [ 'confirmation' => 'Ви впевнені що хочете номінувати цю мапу?', - 'different_nominator_warning' => '', + 'different_nominator_warning' => 'Кваліфікування цієї мапи іншими номінаторами призведе до скидання її позиції в черзі кваліфікованих.', 'header' => 'Номінувати мапу', 'hybrid_warning' => 'примітка: ви можете номінувати лише один раз, так що, переконайтеся в тому, що ви номінуєте всі режими, які збиралися', 'current_main_ruleset' => 'Головний набір ігрових режимів зараз: :ruleset', diff --git a/resources/lang/uk/rankings.php b/resources/lang/uk/rankings.php index 87306e539f1..8b131c4482f 100644 --- a/resources/lang/uk/rankings.php +++ b/resources/lang/uk/rankings.php @@ -10,9 +10,9 @@ ], 'daily_challenge' => [ - 'beatmap' => '', - 'percentile_10' => '', - 'percentile_50' => '', + 'beatmap' => 'Складність', + 'percentile_10' => '10-ий Відсотковий Рекорд', + 'percentile_50' => '50-ий Відсотковий Рекорд', ], 'filter' => [ @@ -36,7 +36,7 @@ 'type' => [ 'charts' => 'чарти', 'country' => 'країни', - 'daily_challenge' => '', + 'daily_challenge' => 'щоденний виклик', 'kudosu' => 'кудосу', 'multiplayer' => 'мультиплеєр', 'performance' => 'продуктивність', diff --git a/resources/lang/vi/rankings.php b/resources/lang/vi/rankings.php index 8263bbd24fe..934b5a37888 100644 --- a/resources/lang/vi/rankings.php +++ b/resources/lang/vi/rankings.php @@ -10,7 +10,7 @@ ], 'daily_challenge' => [ - 'beatmap' => '', + 'beatmap' => 'Độ khó', 'percentile_10' => '', 'percentile_50' => '', ], @@ -36,7 +36,7 @@ 'type' => [ 'charts' => 'tiêu điểm', 'country' => 'quốc gia', - 'daily_challenge' => '', + 'daily_challenge' => 'thử thách hằng ngày', 'kudosu' => 'kudosu', 'multiplayer' => 'nhiều người chơi', 'performance' => 'thành tích', diff --git a/resources/lang/zh-tw/beatmapsets.php b/resources/lang/zh-tw/beatmapsets.php index 27df9900356..c0ec59325c1 100644 --- a/resources/lang/zh-tw/beatmapsets.php +++ b/resources/lang/zh-tw/beatmapsets.php @@ -52,7 +52,7 @@ 'dialog' => [ 'confirmation' => '您確定要提名這張圖譜嗎?', - 'different_nominator_warning' => '', + 'different_nominator_warning' => '以其他提名者的身分提名此圖譜會重設提名順序。', 'header' => '提名圖譜', 'hybrid_warning' => '注意: 您只能提名一次,所以請確保您的提名包含所有您想提名的模式。', 'current_main_ruleset' => '目前遊戲模式為: :ruleset', diff --git a/resources/lang/zh-tw/rankings.php b/resources/lang/zh-tw/rankings.php index 0201bb164bc..c4b465ef02b 100644 --- a/resources/lang/zh-tw/rankings.php +++ b/resources/lang/zh-tw/rankings.php @@ -10,9 +10,9 @@ ], 'daily_challenge' => [ - 'beatmap' => '', - 'percentile_10' => '', - 'percentile_50' => '', + 'beatmap' => '難度', + 'percentile_10' => '前十名的分數', + 'percentile_50' => '前五十名的分數', ], 'filter' => [ @@ -36,7 +36,7 @@ 'type' => [ 'charts' => '月賽', 'country' => '國家', - 'daily_challenge' => '', + 'daily_challenge' => '每日挑戰', 'kudosu' => 'kudosu', 'multiplayer' => '多人遊戲', 'performance' => '成績', diff --git a/resources/lang/zh/accounts.php b/resources/lang/zh/accounts.php index df77b66ae55..12098957242 100644 --- a/resources/lang/zh/accounts.php +++ b/resources/lang/zh/accounts.php @@ -12,7 +12,7 @@ 'title' => '头像', 'reset' => '重置', 'rules' => '请确保你的头像符合 :link。
这意味着头像内容必须是全年龄的,即没有裸露、亵渎或暗示的内容。', - 'rules_link' => '社区规则', + 'rules_link' => '视觉内容注意事项', ], 'email' => [ diff --git a/resources/lang/zh/beatmaps.php b/resources/lang/zh/beatmaps.php index bd0f6070f1c..ed8b0dac1c3 100644 --- a/resources/lang/zh/beatmaps.php +++ b/resources/lang/zh/beatmaps.php @@ -190,7 +190,7 @@ 'nominations' => [ 'already_nominated' => '你已经提名过这张谱面了。', - 'cannot_nominate' => '您不能提名此谱面游戏模式。', + 'cannot_nominate' => '您不能提名这个游戏模式的谱面。', 'delete' => '删除', 'delete_own_confirm' => '你确定要删除吗?删除后你将回到个人资料页。', 'delete_other_confirm' => '你确定要删除吗?删除后你将回到他的个人资料页。', diff --git a/resources/lang/zh/beatmapsets.php b/resources/lang/zh/beatmapsets.php index 9d663dffff8..bb8fcf5cf23 100644 --- a/resources/lang/zh/beatmapsets.php +++ b/resources/lang/zh/beatmapsets.php @@ -52,7 +52,7 @@ 'dialog' => [ 'confirmation' => '您确定要提名这张谱面吗?', - 'different_nominator_warning' => '', + 'different_nominator_warning' => '如果谱面的提名者发生了变更,那么在谱面过审后,它在过审区的队列位置将重置。', 'header' => '提名谱面', 'hybrid_warning' => '注意:您只能提名一次,所以请确保提名包含所有您想要提名的游戏模式。', 'current_main_ruleset' => '主游戏模式::ruleset', diff --git a/resources/lang/zh/model_validation.php b/resources/lang/zh/model_validation.php index 51d69bb06db..5ad0f1c5bfb 100644 --- a/resources/lang/zh/model_validation.php +++ b/resources/lang/zh/model_validation.php @@ -169,7 +169,7 @@ '_' => '你必须 :link 才能更改用户名!', 'link_text' => '支持 osu!', ], - 'username_is_same' => '这就是你现在的用户名,大笨蛋!', + 'username_is_same' => '这就是你现在的玩家名,大笨蛋!', ], ], diff --git a/resources/lang/zh/rankings.php b/resources/lang/zh/rankings.php index d09b209afac..129763e2a34 100644 --- a/resources/lang/zh/rankings.php +++ b/resources/lang/zh/rankings.php @@ -10,9 +10,9 @@ ], 'daily_challenge' => [ - 'beatmap' => '', - 'percentile_10' => '', - 'percentile_50' => '', + 'beatmap' => '难度', + 'percentile_10' => '前 10% 成绩', + 'percentile_50' => '前 50% 成绩', ], 'filter' => [ @@ -36,7 +36,7 @@ 'type' => [ 'charts' => '季赛(旧版)', 'country' => '国家/地区', - 'daily_challenge' => '', + 'daily_challenge' => '每日挑战', 'kudosu' => 'Kudosu', 'multiplayer' => '多人游戏', 'performance' => '表现', diff --git a/resources/lang/zh/users.php b/resources/lang/zh/users.php index 3daa4ba74da..39db6b5977a 100644 --- a/resources/lang/zh/users.php +++ b/resources/lang/zh/users.php @@ -198,15 +198,15 @@ ], 'daily_challenge' => [ 'daily' => '每日连续完成数', - 'daily_streak_best' => '最佳每日完成数', - 'daily_streak_current' => '当前每日完成数', + 'daily_streak_best' => '最佳连续完成天数', + 'daily_streak_current' => '当前连续完成天数', 'playcount' => '参加次数', 'title' => '每日\n挑战', - 'top_10p_placements' => '前 10% 位置', - 'top_50p_placements' => '前 50% 位置', + 'top_10p_placements' => '排名达到前 10% 次数', + 'top_50p_placements' => '排名达到前 50% 次数', 'weekly' => '每周完成数', - 'weekly_streak_best' => '最佳每周完成数', - 'weekly_streak_current' => '当前每周完成数', + 'weekly_streak_best' => '最佳连续完成周数', + 'weekly_streak_current' => '当前连续完成周数', 'unit' => [ 'day' => ':value 天', From 6339031e56f6639c5d4b415e33b50338d9f033a6 Mon Sep 17 00:00:00 2001 From: nanaya Date: Thu, 3 Oct 2024 14:35:11 +0900 Subject: [PATCH 11/17] Add hint on channel user listing capability --- app/Http/Controllers/Chat/Channels/UsersController.php | 2 +- app/Singletons/OsuAuthorize.php | 9 +++++++++ app/Transformers/Chat/ChannelTransformer.php | 1 + resources/js/interfaces/chat/channel-json.ts | 1 + resources/js/models/chat/channel.ts | 10 +++++++++- 5 files changed, 21 insertions(+), 2 deletions(-) diff --git a/app/Http/Controllers/Chat/Channels/UsersController.php b/app/Http/Controllers/Chat/Channels/UsersController.php index b04d29aa073..6d54103bca8 100644 --- a/app/Http/Controllers/Chat/Channels/UsersController.php +++ b/app/Http/Controllers/Chat/Channels/UsersController.php @@ -17,7 +17,7 @@ public function index($channelId) { $channel = Channel::findOrFail($channelId); - if (!$channel->isAnnouncement() || !priv_check('ChatAnnounce', $channel)->can()) { + if (!priv_check('ChatChannelListUsers', $channel)->can()) { return [ 'users' => [], ...cursor_for_response(null), diff --git a/app/Singletons/OsuAuthorize.php b/app/Singletons/OsuAuthorize.php index 2ae7d2041cd..afc443dce40 100644 --- a/app/Singletons/OsuAuthorize.php +++ b/app/Singletons/OsuAuthorize.php @@ -919,6 +919,15 @@ public function checkChatChannelCanMessage(?User $user, Channel $channel): strin return 'ok'; } + public function checkChatChannelListUsers(?User $user, Channel $channel): ?string + { + if ($channel->isAnnouncement() && $this->doCheckUser($user, 'ChatAnnounce', $channel)->can()) { + return 'ok'; + } + + return null; + } + /** * TODO: always use a channel for this check? * diff --git a/app/Transformers/Chat/ChannelTransformer.php b/app/Transformers/Chat/ChannelTransformer.php index c0e636ab7c2..c80b4e2d9fd 100644 --- a/app/Transformers/Chat/ChannelTransformer.php +++ b/app/Transformers/Chat/ChannelTransformer.php @@ -60,6 +60,7 @@ public function includeCurrentUserAttributes(Channel $channel) $result = $channel->checkCanMessage($this->user); return $this->primitive([ + 'can_list_users' => priv_check_user($this->user, 'ChatChannelListUsers', $channel)->can(), 'can_message' => $result->can(), 'can_message_error' => $result->message(), 'last_read_id' => $channel->lastReadIdFor($this->user), diff --git a/resources/js/interfaces/chat/channel-json.ts b/resources/js/interfaces/chat/channel-json.ts index 503744ddde3..4d352aed358 100644 --- a/resources/js/interfaces/chat/channel-json.ts +++ b/resources/js/interfaces/chat/channel-json.ts @@ -14,6 +14,7 @@ export function filterSupportedChannelTypes(json: ChannelJson[]) { export default interface ChannelJson { channel_id: number; current_user_attributes?: { + can_list_users: boolean; can_message: boolean; can_message_error: string | null; last_read_id: number | null; diff --git a/resources/js/models/chat/channel.ts b/resources/js/models/chat/channel.ts index 625daaa99ae..a6e307ed445 100644 --- a/resources/js/models/chat/channel.ts +++ b/resources/js/models/chat/channel.ts @@ -30,6 +30,7 @@ function getMinMessageIdFrom(messages: Message[]) { export default class Channel { private static readonly defaultIcon = '/images/layout/chat/channel-default.png'; // TODO: update with channel-specific icons? + @observable canListUsers: boolean = false; @observable canMessageError: string | null = null; @observable channelId: number; @observable description?: string; @@ -242,7 +243,13 @@ export default class Channel { @action readonly loadUsers = () => { - if (this.type !== 'ANNOUNCE' || this.usersCursor == null || this.loadUsersXhr != null) { + if (!this.canListUsers) { + this.users = []; + this.usersCursor = null; + return; + } + + if (this.usersCursor == null || this.loadUsersXhr != null) { return; } @@ -286,6 +293,7 @@ export default class Channel { this.serverLastMessageId = json.last_message_id; if (json.current_user_attributes != null) { + this.canListUsers = json.current_user_attributes.can_list_users; this.canMessageError = json.current_user_attributes.can_message_error; const lastReadId = json.current_user_attributes.last_read_id ?? 0; this.setLastReadId(lastReadId); From a18cfb16864305f5b1161b42781a845f2dac10cd Mon Sep 17 00:00:00 2001 From: nanaya Date: Thu, 3 Oct 2024 16:41:56 +0900 Subject: [PATCH 12/17] Adjust verification reissue limit --- app/Http/Controllers/AccountController.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/Http/Controllers/AccountController.php b/app/Http/Controllers/AccountController.php index 7f99c18791c..b4c239991c4 100644 --- a/app/Http/Controllers/AccountController.php +++ b/app/Http/Controllers/AccountController.php @@ -59,8 +59,11 @@ public function __construct() 'updateOptions', ]]); - $this->middleware('throttle:60,10', ['only' => [ + $this->middleware('throttle:3,5', ['only' => [ 'reissueCode', + ]]); + + $this->middleware('throttle:60,10', ['only' => [ 'updateEmail', 'updatePassword', 'verify', From 44bb5c11a046187b1ca8f88518e3733c378222d4 Mon Sep 17 00:00:00 2001 From: nanaya Date: Thu, 3 Oct 2024 16:45:18 +0900 Subject: [PATCH 13/17] Reduce session verification key lifetime --- app/Libraries/SessionVerification/State.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Libraries/SessionVerification/State.php b/app/Libraries/SessionVerification/State.php index 1f9b0133f15..0d35f0f8fd8 100644 --- a/app/Libraries/SessionVerification/State.php +++ b/app/Libraries/SessionVerification/State.php @@ -14,7 +14,7 @@ class State { - private const KEY_VALID_DURATION = 5 * 3600; + private const KEY_VALID_DURATION = 600; public readonly CarbonImmutable $expiresAt; public readonly string $key; From f6ce8d199028438a013c7002b467f90491a05102 Mon Sep 17 00:00:00 2001 From: nanaya Date: Thu, 3 Oct 2024 16:50:45 +0900 Subject: [PATCH 14/17] Update test json --- tests/api_routes.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/api_routes.json b/tests/api_routes.json index 37bd76de513..d1cf43ce259 100644 --- a/tests/api_routes.json +++ b/tests/api_routes.json @@ -29,7 +29,7 @@ "App\\Http\\Middleware\\RequireScopes:any", "Illuminate\\Auth\\Middleware\\Authenticate", "App\\Http\\Middleware\\VerifyUser", - "App\\Http\\Middleware\\ThrottleRequests:60,10" + "App\\Http\\Middleware\\ThrottleRequests:3,5" ], "scopes": [ "any" From 3e52e0aecb53437fdf4e724769a1b6e00c00935c Mon Sep 17 00:00:00 2001 From: nanaya Date: Thu, 3 Oct 2024 17:37:55 +0900 Subject: [PATCH 15/17] Adjust user current location length limit --- app/Models/User.php | 2 +- database/factories/UserFactory.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Models/User.php b/app/Models/User.php index 4b79ff6e989..7823d021f6c 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -239,7 +239,7 @@ class User extends Model implements AfterCommit, AuthenticatableContract, HasLoc const MAX_FIELD_LENGTHS = [ 'user_discord' => 37, // max 32char username + # + 4-digit discriminator - 'user_from' => 30, + 'user_from' => 25, 'user_interests' => 30, 'user_occ' => 30, 'user_sig' => 3000, diff --git a/database/factories/UserFactory.php b/database/factories/UserFactory.php index d930cc4d8d6..9efc011e646 100644 --- a/database/factories/UserFactory.php +++ b/database/factories/UserFactory.php @@ -76,7 +76,7 @@ public function definition(): array 'user_interests' => fn () => mb_substr($this->faker->bs(), 0, 30), 'user_occ' => fn () => mb_substr($this->faker->catchPhrase(), 0, 30), 'user_sig' => fn () => $this->faker->realText(155), - 'user_from' => fn () => mb_substr($this->faker->country(), 0, 30), + 'user_from' => fn () => mb_substr($this->faker->country(), 0, 25), 'user_regdate' => fn () => $this->faker->dateTimeBetween('-6 years'), ]; } From d70a5c91b92e54ca170a14f42eae3b4b58d6520f Mon Sep 17 00:00:00 2001 From: nanaya Date: Thu, 3 Oct 2024 19:52:02 +0900 Subject: [PATCH 16/17] Prevent poll option image(?) from overflowing --- resources/css/bem/forum-poll-option.less | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/resources/css/bem/forum-poll-option.less b/resources/css/bem/forum-poll-option.less index b4703584d25..ac4182aa217 100644 --- a/resources/css/bem/forum-poll-option.less +++ b/resources/css/bem/forum-poll-option.less @@ -14,4 +14,8 @@ &__input { margin-right: 10px; } + + &__label { + min-width: 0; + } } From 771901b4c6bd305a4743426d2788a3dc2b3aaf24 Mon Sep 17 00:00:00 2001 From: nanaya Date: Thu, 3 Oct 2024 21:19:43 +0900 Subject: [PATCH 17/17] Add warning before sending message to announcement channel --- resources/js/chat/input-box.tsx | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/resources/js/chat/input-box.tsx b/resources/js/chat/input-box.tsx index 181cf87316f..a71a4f990b0 100644 --- a/resources/js/chat/input-box.tsx +++ b/resources/js/chat/input-box.tsx @@ -24,7 +24,7 @@ export default class InputBox extends React.Component { private readonly inputBoxRef = React.createRef(); get allowMultiLine() { - return this.currentChannel?.type === 'ANNOUNCE'; + return this.isAnnouncement; } @computed @@ -37,6 +37,10 @@ export default class InputBox extends React.Component { return !this.currentChannel?.canMessage; } + get isAnnouncement() { + return this.currentChannel != null && this.currentChannel.type === 'ANNOUNCE'; + } + @computed get sendDisabled() { return this.inputDisabled || !core.dataStore.chatState.isReady; @@ -67,8 +71,7 @@ export default class InputBox extends React.Component { } buttonClicked = () => { - this.sendMessage(this.currentChannel?.inputText); - this.currentChannel?.setInputText(''); + this.startSendMessage(); }; checkIfEnterPressed = (e: React.KeyboardEvent) => { @@ -77,8 +80,7 @@ export default class InputBox extends React.Component { e.preventDefault(); if (!this.sendDisabled) { - this.sendMessage(this.currentChannel?.inputText); - this.currentChannel?.setInputText(''); + this.startSendMessage(); } } }; @@ -181,4 +183,13 @@ export default class InputBox extends React.Component { dispatch(new ChatMessageSendAction(message)); } + + @action + private readonly startSendMessage = () => { + if (this.isAnnouncement && !confirm(trans('common.confirmation'))) { + return; + } + this.sendMessage(this.currentChannel?.inputText); + this.currentChannel?.setInputText(''); + }; }