From 2511bfffc0c190cc2355bf07022cdb42f0d6539a Mon Sep 17 00:00:00 2001 From: nanaya Date: Tue, 12 Nov 2024 20:27:40 +0900 Subject: [PATCH 01/44] Typescript PostPreview --- .../js/{core-legacy/post-preview.coffee => core/post-preview.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename resources/js/{core-legacy/post-preview.coffee => core/post-preview.ts} (100%) diff --git a/resources/js/core-legacy/post-preview.coffee b/resources/js/core/post-preview.ts similarity index 100% rename from resources/js/core-legacy/post-preview.coffee rename to resources/js/core/post-preview.ts From e72b7ee19890cc1375aff8d756ddaaef57582fcc Mon Sep 17 00:00:00 2001 From: nanaya Date: Tue, 12 Nov 2024 21:28:59 +0900 Subject: [PATCH 02/44] Typescript PostPreview (actual) --- resources/js/core/post-preview.ts | 97 ++++++++++++++++++------------ resources/js/forum/post-box.coffee | 6 +- resources/js/main.coffee | 2 - resources/js/osu-core.ts | 3 + 4 files changed, 63 insertions(+), 45 deletions(-) diff --git a/resources/js/core/post-preview.ts b/resources/js/core/post-preview.ts index a9fef6e94db..45198399708 100644 --- a/resources/js/core/post-preview.ts +++ b/resources/js/core/post-preview.ts @@ -1,39 +1,58 @@ -# 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 { route } from 'laroute' - -export default class PostPreview - constructor: -> - @debouncedLoadPreview = _.debounce @loadPreview, 500 - - $(document).on 'input', '.js-post-preview--auto', (e) => - # get the target immediately because event object may change later. - @debouncedLoadPreview(e.currentTarget) - - - loadPreview: (target) => - $form = $(target).closest('form') - body = target.value - $preview = $form.find('.js-post-preview--preview') - preview = $preview[0] - $previewBox = $form.find('.js-post-preview--box') - - if !preview? - return - - preview._xhr?.abort() - - if body == '' - $previewBox.addClass 'hidden' - return - - if $preview.attr('data-raw') == body - $previewBox.removeClass 'hidden' - return - - preview._xhr = $.post(route('bbcode-preview'), text: body) - .done (data) => - $preview.html data - $preview.attr 'data-raw', body - $previewBox.removeClass 'hidden' +// 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 { route } from 'laroute'; +import { debounce } from 'lodash'; +import { fail } from 'utils/fail'; +import { htmlElementOrNull } from 'utils/html'; + +export default class PostPreview { + private readonly debouncedLoadPreview; + private readonly xhr = new Map>(); + + constructor() { + this.debouncedLoadPreview = debounce(this.loadPreview, 500); + document.addEventListener('input', this.onInput); + } + + private readonly loadPreview = (target: HTMLTextAreaElement) => { + const form = target.closest('form') ?? fail('form element is missing'); + const body = target.value; + const preview = htmlElementOrNull(form.querySelector('.js-post-preview--preview')); + const previewBox = form.querySelector('.js-post-preview--box'); + + if (preview == null) { + return; + } + + this.xhr.get(preview)?.abort(); + + if (body === '') { + previewBox?.classList.add('hidden'); + preview.innerHTML = ''; + return; + } + + if (preview.dataset.raw === body) { + previewBox?.classList.remove('hidden'); + return; + } + + const xhr = $.post(route('bbcode-preview'), { text: body }) as JQuery.jqXHR; + xhr.done((data) => { + preview.innerHTML = data; + preview.dataset.raw = body; + previewBox?.classList.remove('hidden'); + }).always(() => { + this.xhr.delete(preview); + }); + }; + + private readonly onInput = (e: InputEvent) => { + const target = htmlElementOrNull(e.target)?.closest('.js-post-preview--auto'); + + if (target instanceof HTMLTextAreaElement) { + this.debouncedLoadPreview(target); + } + }; +} diff --git a/resources/js/forum/post-box.coffee b/resources/js/forum/post-box.coffee index 1e22449b25d..78707ae1cf1 100644 --- a/resources/js/forum/post-box.coffee +++ b/resources/js/forum/post-box.coffee @@ -25,10 +25,8 @@ insert = (event, tagOpen, tagClose = '') -> box.selectionStart = startPos box.selectionEnd = texts[0].length + texts[1].length + tagClose.length - $box - .trigger 'bbcode:inserted' # for react - .trigger 'input' # ignored by react - .focus() + box.dispatchEvent(new InputEvent('input', { bubbles: true })) + box.focus() [ ['bold', '[b]', '[/b]'] diff --git a/resources/js/main.coffee b/resources/js/main.coffee index 964ae4ebd66..5e49fc5bb2d 100644 --- a/resources/js/main.coffee +++ b/resources/js/main.coffee @@ -24,7 +24,6 @@ import LandingGraph from 'core-legacy/landing-graph' import Menu from 'core-legacy/menu' import NavButton from 'core-legacy/nav-button' import Nav2 from 'core-legacy/nav2' -import PostPreview from 'core-legacy/post-preview' import Search from 'core-legacy/search' import { StoreCheckout } from 'core-legacy/store-checkout' import TooltipDefault from 'core-legacy/tooltip-default' @@ -60,7 +59,6 @@ window.globalDrag ?= new GlobalDrag window.landingGraph ?= new LandingGraph window.menu ?= new Menu window.navButton ?= new NavButton -window.postPreview ?= new PostPreview window.search ?= new Search window.tooltipDefault ?= new TooltipDefault diff --git a/resources/js/osu-core.ts b/resources/js/osu-core.ts index 3f1329e9fd9..a96a8650df3 100644 --- a/resources/js/osu-core.ts +++ b/resources/js/osu-core.ts @@ -19,6 +19,7 @@ import ForumPostReport from 'core/forum/forum-post-report'; import Localtime from 'core/localtime'; import MobileToggle from 'core/mobile-toggle'; import OsuAudio from 'core/osu-audio/main'; +import PostPreview from 'core/post-preview'; import ReactTurbolinks from 'core/react-turbolinks'; import Spoilerbox from 'core/spoilerbox'; import StickyFooter from 'core/sticky-footer'; @@ -68,6 +69,7 @@ export default class OsuCore { readonly mobileToggle; readonly notificationsWorker; readonly osuAudio; + readonly postPreview; readonly reactTurbolinks; readonly referenceLinkTooltip; readonly scorePins; @@ -114,6 +116,7 @@ export default class OsuCore { this.localtime = new Localtime(); this.mobileToggle = new MobileToggle(); this.browserTitleWithNotificationCount = new BrowserTitleWithNotificationCount(this); + this.postPreview = new PostPreview(); this.referenceLinkTooltip = new ReferenceLinkTooltip(); this.scorePins = new ScorePins(); this.spoilerbox = new Spoilerbox(); From 3dd58f165e79d600ac56223c7703670735bea261 Mon Sep 17 00:00:00 2001 From: nanaya Date: Tue, 12 Nov 2024 21:36:23 +0900 Subject: [PATCH 03/44] Better name --- resources/js/core/{post-preview.ts => bbcode-auto-preview.ts} | 2 +- resources/js/osu-core.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) rename resources/js/core/{post-preview.ts => bbcode-auto-preview.ts} (97%) diff --git a/resources/js/core/post-preview.ts b/resources/js/core/bbcode-auto-preview.ts similarity index 97% rename from resources/js/core/post-preview.ts rename to resources/js/core/bbcode-auto-preview.ts index 45198399708..b816f7cacf9 100644 --- a/resources/js/core/post-preview.ts +++ b/resources/js/core/bbcode-auto-preview.ts @@ -6,7 +6,7 @@ import { debounce } from 'lodash'; import { fail } from 'utils/fail'; import { htmlElementOrNull } from 'utils/html'; -export default class PostPreview { +export default class BbcodeAutoPreview { private readonly debouncedLoadPreview; private readonly xhr = new Map>(); diff --git a/resources/js/osu-core.ts b/resources/js/osu-core.ts index a96a8650df3..1e81caddd44 100644 --- a/resources/js/osu-core.ts +++ b/resources/js/osu-core.ts @@ -7,6 +7,7 @@ import AccountEdit from 'core/account-edit'; import AccountEditAvatar from 'core/account-edit-avatar'; import AccountEditBlocklist from 'core/account-edit-blocklist'; import AnimateNav from 'core/animate-nav'; +import BbcodeAutoPreview from 'core/bbcode-auto-preview'; import BrowserTitleWithNotificationCount from 'core/browser-title-with-notification-count'; import Captcha from 'core/captcha'; import ClickMenu from 'core/click-menu'; @@ -19,7 +20,6 @@ import ForumPostReport from 'core/forum/forum-post-report'; import Localtime from 'core/localtime'; import MobileToggle from 'core/mobile-toggle'; import OsuAudio from 'core/osu-audio/main'; -import PostPreview from 'core/post-preview'; import ReactTurbolinks from 'core/react-turbolinks'; import Spoilerbox from 'core/spoilerbox'; import StickyFooter from 'core/sticky-footer'; @@ -104,6 +104,7 @@ export default class OsuCore { $.subscribe('user:update', this.onCurrentUserUpdate); this.animateNav = new AnimateNav(); + this.bbcodeAutoPreview = new BbcodeAutoPreview(); this.captcha = new Captcha(); this.chatWorker = new ChatWorker(); this.clickMenu = new ClickMenu(); @@ -116,7 +117,6 @@ export default class OsuCore { this.localtime = new Localtime(); this.mobileToggle = new MobileToggle(); this.browserTitleWithNotificationCount = new BrowserTitleWithNotificationCount(this); - this.postPreview = new PostPreview(); this.referenceLinkTooltip = new ReferenceLinkTooltip(); this.scorePins = new ScorePins(); this.spoilerbox = new Spoilerbox(); From 6493ccdf1529ee38a27421dc6f7766cd959b69b6 Mon Sep 17 00:00:00 2001 From: nanaya Date: Tue, 12 Nov 2024 21:40:20 +0900 Subject: [PATCH 04/44] Also reset raw bbcode cache when emptying --- resources/js/core/bbcode-auto-preview.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/resources/js/core/bbcode-auto-preview.ts b/resources/js/core/bbcode-auto-preview.ts index b816f7cacf9..cf76f73b35a 100644 --- a/resources/js/core/bbcode-auto-preview.ts +++ b/resources/js/core/bbcode-auto-preview.ts @@ -28,8 +28,9 @@ export default class BbcodeAutoPreview { this.xhr.get(preview)?.abort(); if (body === '') { - previewBox?.classList.add('hidden'); + preview.dataset.raw = ''; preview.innerHTML = ''; + previewBox?.classList.add('hidden'); return; } @@ -40,8 +41,8 @@ export default class BbcodeAutoPreview { const xhr = $.post(route('bbcode-preview'), { text: body }) as JQuery.jqXHR; xhr.done((data) => { - preview.innerHTML = data; preview.dataset.raw = body; + preview.innerHTML = data; previewBox?.classList.remove('hidden'); }).always(() => { this.xhr.delete(preview); From 8181fec53900730e477a1d254b24b10362305041 Mon Sep 17 00:00:00 2001 From: nanaya Date: Tue, 12 Nov 2024 21:43:28 +0900 Subject: [PATCH 05/44] More coffee --- resources/js/forum/post-box.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/js/forum/post-box.coffee b/resources/js/forum/post-box.coffee index 78707ae1cf1..f99d5afffaf 100644 --- a/resources/js/forum/post-box.coffee +++ b/resources/js/forum/post-box.coffee @@ -25,7 +25,7 @@ insert = (event, tagOpen, tagClose = '') -> box.selectionStart = startPos box.selectionEnd = texts[0].length + texts[1].length + tagClose.length - box.dispatchEvent(new InputEvent('input', { bubbles: true })) + box.dispatchEvent(new InputEvent('input', bubbles: true)) box.focus() [ From ffa709bbcedc597e5006d34f37cf42587ee42949 Mon Sep 17 00:00:00 2001 From: nanaya Date: Tue, 12 Nov 2024 21:45:14 +0900 Subject: [PATCH 06/44] Forgot another rename --- resources/js/osu-core.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/js/osu-core.ts b/resources/js/osu-core.ts index 1e81caddd44..fab7aafc277 100644 --- a/resources/js/osu-core.ts +++ b/resources/js/osu-core.ts @@ -50,6 +50,7 @@ export default class OsuCore { readonly accountEditAvatar; readonly accountEditBlocklist; readonly animateNav; + readonly bbcodeAutoPreview; readonly beatmapsetSearchController; readonly browserTitleWithNotificationCount; readonly captcha; @@ -69,7 +70,6 @@ export default class OsuCore { readonly mobileToggle; readonly notificationsWorker; readonly osuAudio; - readonly postPreview; readonly reactTurbolinks; readonly referenceLinkTooltip; readonly scorePins; From 723fde04a1422a3648f185d8b79a0665e1433a54 Mon Sep 17 00:00:00 2001 From: nanaya Date: Mon, 9 Dec 2024 16:10:05 +0900 Subject: [PATCH 07/44] Exclude restricted user scores from score listing --- app/Models/Solo/Score.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/Models/Solo/Score.php b/app/Models/Solo/Score.php index ac3780ea400..b02a6ce54ad 100644 --- a/app/Models/Solo/Score.php +++ b/app/Models/Solo/Score.php @@ -169,9 +169,14 @@ public function scopeDefault(Builder $query): Builder return $query->whereHas('beatmap.beatmapset'); } + /** + * This should only be sorted by primary key(s) + */ public function scopeForListing(Builder $query): Builder { return $query->where('ranked', true) + ->whereHas('user', fn ($q) => $q->default()) + ->from(\DB::raw("{$this->getTable()} FORCE INDEX (PRIMARY)")) ->leftJoinRelation('processHistory') ->select([$query->qualifyColumn('*'), 'processed_version']); } From f509110784960f75433337743962e4351f68816b Mon Sep 17 00:00:00 2001 From: nanaya Date: Mon, 9 Dec 2024 20:22:41 +0900 Subject: [PATCH 08/44] Fix flag size on team page --- resources/css/bem/profile-info.less | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/css/bem/profile-info.less b/resources/css/bem/profile-info.less index 7cd9658deeb..afb8b40fd43 100644 --- a/resources/css/bem/profile-info.less +++ b/resources/css/bem/profile-info.less @@ -61,6 +61,7 @@ align-self: flex-end; margin-bottom: var(--vertical-padding); background-image: var(--avatar); + background-size: contain; .default-box-shadow(); } From 2b0764df45921554d96c5d534f9b48cbe71c9012 Mon Sep 17 00:00:00 2001 From: nanaya Date: Mon, 9 Dec 2024 23:02:34 +0900 Subject: [PATCH 09/44] Use relative sizing for icons and flags on profile page cover --- resources/css/bem/profile-info.less | 28 ++++++++++------------------ resources/js/profile-page/cover.tsx | 4 +--- 2 files changed, 11 insertions(+), 21 deletions(-) diff --git a/resources/css/bem/profile-info.less b/resources/css/bem/profile-info.less index afb8b40fd43..b04f5cb2c15 100644 --- a/resources/css/bem/profile-info.less +++ b/resources/css/bem/profile-info.less @@ -111,10 +111,6 @@ align-items: center; } - &__flag-flag { - font-size: var(--icon-height); // icon size - } - &__flag-text { display: none; @@ -126,23 +122,20 @@ } &__flags { - --icon-font-size: @font-size--small; - --icon-height-desktop: 20px; - --icon-height: 15px; - display: flex; gap: 5px; margin-top: 10px; + font-size: 15px; // icon size @media @desktop { - --icon-height: var(--icon-height-desktop); + font-size: @flag-size-medium; // icon size margin-top: 5px; } } &__icon { - font-size: var(--icon-font-size); // icon size - height: var(--icon-height); + font-size: 0.75em; // icon size + height: (1em * 1em / $font-size); // revert sizing from font-size color: @osu-colour-c1; display: flex; text-shadow: none; @@ -158,19 +151,21 @@ } &__icons { - align-items: baseline; - gap: 2px; - margin-left: 5px; - &--flag-inline { display: contents; + @media @desktop { display: none; } } &--name-inline { + align-items: baseline; + gap: 2px; + margin-left: 5px; + font-size: 15px; // icon size display: none; + @media @desktop { display: flex; } @@ -191,9 +186,6 @@ } &__name { - --icon-height: 15px; - --icon-font-size: @font-size--small; - padding: 0; margin: -5px 0 0; font-weight: normal; diff --git a/resources/js/profile-page/cover.tsx b/resources/js/profile-page/cover.tsx index d342b7ba233..fd74bb3d387 100644 --- a/resources/js/profile-page/cover.tsx +++ b/resources/js/profile-page/cover.tsx @@ -87,9 +87,7 @@ export default class Cover extends React.Component { className='profile-info__flag' href={route('rankings', { country: this.props.user.country.code, mode: this.props.currentMode, type: 'performance' })} > - - - + {this.props.user.country.name} } From e68978428f0bc26823a54af635bc3dc2c51bab7f Mon Sep 17 00:00:00 2001 From: nanaya Date: Mon, 9 Dec 2024 23:16:26 +0900 Subject: [PATCH 10/44] Move around styling for flag-text --- resources/css/bem/profile-info.less | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/css/bem/profile-info.less b/resources/css/bem/profile-info.less index b04f5cb2c15..ed0ea1854d2 100644 --- a/resources/css/bem/profile-info.less +++ b/resources/css/bem/profile-info.less @@ -108,16 +108,16 @@ .link-plain(); .link-white(); display: flex; + gap: 4px; align-items: center; } &__flag-text { + font-size: @font-size--title-small; display: none; @media @desktop { display: block; - padding-left: 4px; - font-size: @font-size--title-small; } } From ba6424303f1fb71ac38ea99425a8c622221d6cc6 Mon Sep 17 00:00:00 2001 From: nanaya Date: Mon, 9 Dec 2024 23:56:32 +0900 Subject: [PATCH 11/44] Fix switching locale doesn't set js locale correctly --- resources/views/layout/metadata.blade.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/views/layout/metadata.blade.php b/resources/views/layout/metadata.blade.php index 64bc5034bd8..9364f456aef 100644 --- a/resources/views/layout/metadata.blade.php +++ b/resources/views/layout/metadata.blade.php @@ -96,9 +96,9 @@ - + @if ($fallbackLocale !== $currentLocale) - + @endif From 33ca70922424caade67f030ac7f83b9093cf362c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 10 Dec 2024 01:28:34 +0000 Subject: [PATCH 12/44] Bump league/commonmark from 2.5.3 to 2.6.0 Bumps [league/commonmark](https://github.com/thephpleague/commonmark) from 2.5.3 to 2.6.0. - [Release notes](https://github.com/thephpleague/commonmark/releases) - [Changelog](https://github.com/thephpleague/commonmark/blob/2.6/CHANGELOG.md) - [Commits](https://github.com/thephpleague/commonmark/compare/2.5.3...2.6.0) --- updated-dependencies: - dependency-name: league/commonmark dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- composer.lock | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/composer.lock b/composer.lock index a2e9c5b6e3c..a5f11026f9f 100644 --- a/composer.lock +++ b/composer.lock @@ -3583,16 +3583,16 @@ }, { "name": "league/commonmark", - "version": "2.5.3", + "version": "2.6.0", "source": { "type": "git", "url": "https://github.com/thephpleague/commonmark.git", - "reference": "b650144166dfa7703e62a22e493b853b58d874b0" + "reference": "d150f911e0079e90ae3c106734c93137c184f932" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/b650144166dfa7703e62a22e493b853b58d874b0", - "reference": "b650144166dfa7703e62a22e493b853b58d874b0", + "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/d150f911e0079e90ae3c106734c93137c184f932", + "reference": "d150f911e0079e90ae3c106734c93137c184f932", "shasum": "" }, "require": { @@ -3617,8 +3617,9 @@ "phpstan/phpstan": "^1.8.2", "phpunit/phpunit": "^9.5.21 || ^10.5.9 || ^11.0.0", "scrutinizer/ocular": "^1.8.1", - "symfony/finder": "^5.3 | ^6.0 || ^7.0", - "symfony/yaml": "^2.3 | ^3.0 | ^4.0 | ^5.0 | ^6.0 || ^7.0", + "symfony/finder": "^5.3 | ^6.0 | ^7.0", + "symfony/process": "^5.4 | ^6.0 | ^7.0", + "symfony/yaml": "^2.3 | ^3.0 | ^4.0 | ^5.0 | ^6.0 | ^7.0", "unleashedtech/php-coding-standard": "^3.1.1", "vimeo/psalm": "^4.24.0 || ^5.0.0" }, @@ -3628,7 +3629,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "2.6-dev" + "dev-main": "2.7-dev" } }, "autoload": { @@ -3685,7 +3686,7 @@ "type": "tidelift" } ], - "time": "2024-08-16T11:46:16+00:00" + "time": "2024-12-07T15:34:16+00:00" }, { "name": "league/config", @@ -8307,16 +8308,16 @@ }, { "name": "symfony/deprecation-contracts", - "version": "v3.5.0", + "version": "v3.5.1", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1" + "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", - "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", + "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", "shasum": "" }, "require": { @@ -8354,7 +8355,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.0" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.1" }, "funding": [ { @@ -8370,7 +8371,7 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:32:20+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/error-handler", @@ -9682,8 +9683,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { From 690bba5970ffa126ddc01c3df62e31f1e2aba88e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 10 Dec 2024 05:00:48 +0000 Subject: [PATCH 13/44] Bump nanoid from 3.3.6 to 3.3.8 Bumps [nanoid](https://github.com/ai/nanoid) from 3.3.6 to 3.3.8. - [Release notes](https://github.com/ai/nanoid/releases) - [Changelog](https://github.com/ai/nanoid/blob/main/CHANGELOG.md) - [Commits](https://github.com/ai/nanoid/compare/3.3.6...3.3.8) --- updated-dependencies: - dependency-name: nanoid dependency-type: indirect ... Signed-off-by: dependabot[bot] --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 382762fb08d..9be0db075dd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5371,9 +5371,9 @@ ms@^2.1.1: integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== nanoid@^3.3.6: - version "3.3.6" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.6.tgz#443380c856d6e9f9824267d960b4236ad583ea4c" - integrity sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA== + version "3.3.8" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.8.tgz#b1be3030bee36aaff18bacb375e5cce521684baf" + integrity sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w== nanomatch@^1.2.9: version "1.2.13" From 8a104b4a3f5ffe4154401cc9773639acf1cf0839 Mon Sep 17 00:00:00 2001 From: bakaneko Date: Tue, 10 Dec 2024 18:29:39 +0900 Subject: [PATCH 14/44] doesn't return array --- app/Http/Controllers/Chat/ChatController.php | 28 +++++++++----------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/app/Http/Controllers/Chat/ChatController.php b/app/Http/Controllers/Chat/ChatController.php index 1f949f6679e..71351c863a6 100644 --- a/app/Http/Controllers/Chat/ChatController.php +++ b/app/Http/Controllers/Chat/ChatController.php @@ -89,21 +89,19 @@ public function ack() * @bodyParam uuid string client-side message identifier which will be sent back in response and websocket json. Example: some-uuid-string * * @response { - * "channel": [ - * { - * "channel_id": 1234, - * "current_user_attributes": { - * "can_message": true, - * "can_message_error": null, - * "last_read_id": 9150005005 - * }, - * "name": "peppy", - * "description": "", - * "type": "PM", - * "last_read_id": 9150005005, - * "last_message_id": 9150005005 - * } - * ], + * "channel": { + * "channel_id": 1234, + * "current_user_attributes": { + * "can_message": true, + * "can_message_error": null, + * "last_read_id": 9150005005 + * }, + * "name": "peppy", + * "description": "", + * "type": "PM", + * "last_read_id": 9150005005, + * "last_message_id": 9150005005 + * }, * "message": { * "message_id": 9150005005, * "sender_id": 102, From 3af4bd6c0f986a91db84325dd4e3796018afd4aa Mon Sep 17 00:00:00 2001 From: bakaneko Date: Tue, 10 Dec 2024 19:01:22 +0900 Subject: [PATCH 15/44] update response with missing stuff --- app/Http/Controllers/Chat/ChatController.php | 35 ++++++++++++-------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/app/Http/Controllers/Chat/ChatController.php b/app/Http/Controllers/Chat/ChatController.php index 71351c863a6..27c7d2edf28 100644 --- a/app/Http/Controllers/Chat/ChatController.php +++ b/app/Http/Controllers/Chat/ChatController.php @@ -91,35 +91,42 @@ public function ack() * @response { * "channel": { * "channel_id": 1234, - * "current_user_attributes": { - * "can_message": true, - * "can_message_error": null, - * "last_read_id": 9150005005 - * }, - * "name": "peppy", * "description": "", + * "icon": "https://a.ppy.sh/102?1500537068" + * "message_length_limit": 450, + * "moderated": false, + * "name": "peppy", * "type": "PM", - * "last_read_id": 9150005005, - * "last_message_id": 9150005005 + * "uuid": null, + * "last_message_id": 9150005005, + * "users": [ + * 101, + * 102 + * ] * }, * "message": { - * "message_id": 9150005005, - * "sender_id": 102, * "channel_id": 1234, - * "timestamp": "2018-07-06T06:33:42+00:00", * "content": "i can haz featured artist plz?", * "is_action": false, + * "message_id": 9150005005, + * "sender_id": 102, + * "timestamp": "2024-12-23T01:23:45+00:00", + * "type": "plain", * "uuid": "some-uuid-string", * "sender": { - * "id": 102, - * "username": "nekodex", - * "profile_colour": "#333333", * "avatar_url": "https://a.ppy.sh/102?1500537068", * "country_code": "AU", + * "default_group": "default", + * "id": 102, * "is_active": true, * "is_bot": false, + * "is_deleted": false, * "is_online": true, * "is_supporter": true + * "last_visit": "2024-12-23T01:23:45+00:00", + * "pm_friends_only": false, + * "profile_colour": "#333333", + * "username": "nekodex", * } * }, * "new_channel_id": 1234, From 5522a2df8da7e035f178a740be5b827136f41abc Mon Sep 17 00:00:00 2001 From: nanaya Date: Mon, 2 Dec 2024 18:10:00 +0900 Subject: [PATCH 16/44] Show team flag on user display --- app/Http/Controllers/BeatmapsController.php | 4 +-- .../Controllers/Forum/TopicsController.php | 1 + app/Http/Controllers/RankingController.php | 3 +- app/Http/Controllers/UsersController.php | 1 + app/Models/DeletedUser.php | 1 + app/Models/Multiplayer/Room.php | 2 +- app/Models/Spotlight.php | 2 +- app/Models/User.php | 16 ++++++--- app/Transformers/CurrentUserTransformer.php | 1 + app/Transformers/TeamTransformer.php | 23 +++++++++++++ app/Transformers/UserCompactTransformer.php | 10 ++++++ resources/css/bem-index.less | 1 + .../css/bem/beatmap-scoreboard-table.less | 14 +++++--- resources/css/bem/flag-team.less | 10 ++++++ resources/css/bem/profile-info.less | 2 +- resources/css/bem/ranking-page-table.less | 6 ++++ .../beatmapsets-show/scoreboard/table-row.tsx | 22 +++++++----- .../beatmapsets-show/scoreboard/top-card.tsx | 10 ++++++ resources/js/components/flag-team.tsx | 15 ++++++++ resources/js/components/user-card.tsx | 10 ++++++ resources/js/interfaces/team-json.ts | 9 +++++ resources/js/interfaces/user-json.ts | 2 ++ resources/js/profile-page/cover.tsx | 10 ++++++ .../views/forum/topics/_post_info.blade.php | 11 ++++++ .../rooms/_rankings_table.blade.php | 14 +++++--- resources/views/objects/_flag_team.blade.php | 9 +++++ .../_spotlight_rankings_table.blade.php | 14 +++++--- resources/views/rankings/kudosu.blade.php | 15 +++++--- .../views/rankings/performance.blade.php | 34 ++++++++++++------- resources/views/rankings/score.blade.php | 18 ++++++---- 30 files changed, 236 insertions(+), 54 deletions(-) create mode 100644 app/Transformers/TeamTransformer.php create mode 100644 resources/css/bem/flag-team.less create mode 100644 resources/js/components/flag-team.tsx create mode 100644 resources/js/interfaces/team-json.ts create mode 100644 resources/views/objects/_flag_team.blade.php diff --git a/app/Http/Controllers/BeatmapsController.php b/app/Http/Controllers/BeatmapsController.php index dca765187d0..be0feca32b1 100644 --- a/app/Http/Controllers/BeatmapsController.php +++ b/app/Http/Controllers/BeatmapsController.php @@ -24,7 +24,7 @@ class BeatmapsController extends Controller { const DEFAULT_API_INCLUDES = ['beatmapset.ratings', 'failtimes', 'max_combo']; - const DEFAULT_SCORE_INCLUDES = ['user', 'user.country', 'user.cover']; + const DEFAULT_SCORE_INCLUDES = ['user', 'user.country', 'user.cover', 'user.team']; public function __construct() { @@ -74,7 +74,7 @@ private static function beatmapScores(string $id, ?string $scoreTransformerType, 'type' => $type, 'user' => $currentUser, ]); - $scores = $esFetch->all()->loadMissing(['beatmap', 'user.country', 'processHistory']); + $scores = $esFetch->all()->loadMissing(['beatmap', 'user.country', 'user.team', 'processHistory']); $userScore = $esFetch->userBest(); $scoreTransformer = new ScoreTransformer($scoreTransformerType); diff --git a/app/Http/Controllers/Forum/TopicsController.php b/app/Http/Controllers/Forum/TopicsController.php index d8c4e34b628..ce704bcfe5c 100644 --- a/app/Http/Controllers/Forum/TopicsController.php +++ b/app/Http/Controllers/Forum/TopicsController.php @@ -396,6 +396,7 @@ public function show($id) 'user.country', 'user.rank', 'user.supporterTagPurchases', + 'user.team', 'user.userGroups', ]); diff --git a/app/Http/Controllers/RankingController.php b/app/Http/Controllers/RankingController.php index 51980dc82d8..ad64bb83332 100644 --- a/app/Http/Controllers/RankingController.php +++ b/app/Http/Controllers/RankingController.php @@ -174,7 +174,7 @@ public function index($mode, $type) $table = (new $class())->getTable(); $ppColumn = $class::ppColumn(); $stats = $class - ::with(['user', 'user.country']) + ::with(['user', 'user.country', 'user.team']) ->where($ppColumn, '>', 0) ->whereHas('user', function ($userQuery) { $userQuery->default(); @@ -307,6 +307,7 @@ public function kudosu() $page = min(get_int(request('page')) ?? 1, $maxPage); $scores = User::default() + ->with('team') ->orderBy('osu_kudostotal', 'desc') ->paginate(static::PAGE_SIZE, ['*'], 'page', $page, $maxResults); diff --git a/app/Http/Controllers/UsersController.php b/app/Http/Controllers/UsersController.php index cd72c10642a..b358af1928c 100644 --- a/app/Http/Controllers/UsersController.php +++ b/app/Http/Controllers/UsersController.php @@ -931,6 +931,7 @@ private function showUserIncludes() 'statistics.country_rank', 'statistics.rank', 'statistics.variants', + 'team', 'user_achievements', ]; diff --git a/app/Models/DeletedUser.php b/app/Models/DeletedUser.php index 56c14151d46..4e1e3252502 100644 --- a/app/Models/DeletedUser.php +++ b/app/Models/DeletedUser.php @@ -7,6 +7,7 @@ class DeletedUser extends User { + public null $team = null; public $user_avatar = null; public $username = '[deleted user]'; diff --git a/app/Models/Multiplayer/Room.php b/app/Models/Multiplayer/Room.php index 8ea4ebc3674..1cf6bd075ec 100644 --- a/app/Models/Multiplayer/Room.php +++ b/app/Models/Multiplayer/Room.php @@ -676,7 +676,7 @@ public function startPlay(User $user, PlaylistItem $playlistItem, int $buildId) public function topScores() { - return $this->userHighScores()->forRanking()->with('user.country'); + return $this->userHighScores()->forRanking()->with(['user.country', 'user.team']); } private function assertHostRoomAllowance() diff --git a/app/Models/Spotlight.php b/app/Models/Spotlight.php index 3fe43f972db..1c470a04442 100644 --- a/app/Models/Spotlight.php +++ b/app/Models/Spotlight.php @@ -96,7 +96,7 @@ public function ranking(string $mode) // These models will not have the correct table name set on them // as they get overriden when Laravel hydrates them. return $this->userStats($mode) - ->with(['user', 'user.country']) + ->with(['user', 'user.country', 'user.team']) ->whereHas('user', function ($userQuery) { $model = new User(); $userQuery diff --git a/app/Models/User.php b/app/Models/User.php index 306f4710502..737b66a56e6 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -37,6 +37,7 @@ use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasOne; +use Illuminate\Database\Eloquent\Relations\HasOneThrough; use Illuminate\Database\QueryException; use Laravel\Passport\HasApiTokens; use League\OAuth2\Server\Exception\OAuthServerException; @@ -127,7 +128,7 @@ * @property-read Collection $storeAddresses * @property-read Collection $supporterTagPurchases * @property-read Collection $supporterTags - * @property-read TeamMember|null $teamMembership + * @property-read Team|null $team * @property-read Collection $tokens * @property-read Collection $topicWatches * @property-read Collection $userAchievements @@ -297,9 +298,16 @@ public function userCountryHistory(): HasMany return $this->hasMany(UserCountryHistory::class); } - public function teamMembership(): HasOne + public function team(): HasOneThrough { - return $this->hasOne(TeamMember::class, 'user_id'); + return $this->hasOneThrough( + Team::class, + TeamMember::class, + 'user_id', + 'id', + 'user_id', + 'team_id', + ); } public function getAuthPassword() @@ -958,7 +966,7 @@ public function getAttribute($key) 'storeAddresses', 'supporterTagPurchases', 'supporterTags', - 'teamMembership', + 'team', 'tokens', 'topicWatches', 'userAchievements', diff --git a/app/Transformers/CurrentUserTransformer.php b/app/Transformers/CurrentUserTransformer.php index 6e89c338df2..beccb8c54b2 100644 --- a/app/Transformers/CurrentUserTransformer.php +++ b/app/Transformers/CurrentUserTransformer.php @@ -16,6 +16,7 @@ public function __construct() 'friends', 'groups', 'is_admin', + 'team', 'unread_pm_count', 'user_preferences', ]; diff --git a/app/Transformers/TeamTransformer.php b/app/Transformers/TeamTransformer.php new file mode 100644 index 00000000000..e2e1bb15055 --- /dev/null +++ b/app/Transformers/TeamTransformer.php @@ -0,0 +1,23 @@ +. Licensed under the GNU Affero General Public License v3.0. +// See the LICENCE file in the repository root for full licence text. + +declare(strict_types=1); + +namespace App\Transformers; + +use App\Models\Team; + +class TeamTransformer extends TransformerAbstract +{ + public function transform(Team $team): array + { + return [ + 'id' => $team->getKey(), + 'logo' => $team->logo()->url(), + 'name' => $team->name, + 'short_name' => $team->short_name, + ]; + } +} diff --git a/app/Transformers/UserCompactTransformer.php b/app/Transformers/UserCompactTransformer.php index 21df9c260e5..e18c90cf8f3 100644 --- a/app/Transformers/UserCompactTransformer.php +++ b/app/Transformers/UserCompactTransformer.php @@ -19,9 +19,11 @@ class UserCompactTransformer extends TransformerAbstract 'country', 'cover', 'groups', + 'team', ]; const CARD_INCLUDES_PRELOAD = [ + 'team', 'userGroups', ]; @@ -92,6 +94,7 @@ class UserCompactTransformer extends TransformerAbstract 'statistics', 'statistics_rulesets', 'support_level', + 'team', 'unread_pm_count', 'user_achievements', 'user_preferences', @@ -454,6 +457,13 @@ public function includeSupportLevel(User $user) return $this->primitive($user->supportLevel()); } + public function includeTeam(User $user) + { + return ($team = $user->team) === null + ? $this->null() + : $this->item($team, new TeamTransformer()); + } + public function includeUnreadPmCount(User $user) { // legacy pm has been turned off diff --git a/resources/css/bem-index.less b/resources/css/bem-index.less index 6371fa373e9..0228a0d00a2 100644 --- a/resources/css/bem-index.less +++ b/resources/css/bem-index.less @@ -157,6 +157,7 @@ @import "bem/fileupload"; @import "bem/fixed-bar"; @import "bem/flag-country"; +@import "bem/flag-team"; @import "bem/floating-toolbar"; @import "bem/floating-toolbar-button"; @import "bem/follow-mapper"; diff --git a/resources/css/bem/beatmap-scoreboard-table.less b/resources/css/bem/beatmap-scoreboard-table.less index 35711f1da30..75adb4e6dec 100644 --- a/resources/css/bem/beatmap-scoreboard-table.less +++ b/resources/css/bem/beatmap-scoreboard-table.less @@ -184,12 +184,9 @@ } &--user-link { - .link-inverted(); - .link-hover({ - text-decoration: underline; - }); - position: absolute; + display: flex; + gap: 5px; } &--zero { @@ -221,4 +218,11 @@ opacity: 1; } } + + &__user-link { + .link-inverted(); + .link-hover({ + text-decoration: underline; + }); + } } diff --git a/resources/css/bem/flag-team.less b/resources/css/bem/flag-team.less new file mode 100644 index 00000000000..ac8ad25ace0 --- /dev/null +++ b/resources/css/bem/flag-team.less @@ -0,0 +1,10 @@ +// 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. + +.flag-team { + height: 1em; + width: 2em; + display: inline-block; + background-size: contain; + border-radius: min(0.25em, @border-radius-large); +} diff --git a/resources/css/bem/profile-info.less b/resources/css/bem/profile-info.less index ed0ea1854d2..802b81ba63c 100644 --- a/resources/css/bem/profile-info.less +++ b/resources/css/bem/profile-info.less @@ -123,7 +123,7 @@ &__flags { display: flex; - gap: 5px; + gap: 10px; margin-top: 10px; font-size: 15px; // icon size diff --git a/resources/css/bem/ranking-page-table.less b/resources/css/bem/ranking-page-table.less index e27cb807bba..5129952b76e 100644 --- a/resources/css/bem/ranking-page-table.less +++ b/resources/css/bem/ranking-page-table.less @@ -105,6 +105,12 @@ margin-left: 10px; } + &__flags { + display: inline-flex; + gap: 10px; + font-size: @flag-size-medium; // icon size + } + &__user-link { display: flex; align-items: center; diff --git a/resources/js/beatmapsets-show/scoreboard/table-row.tsx b/resources/js/beatmapsets-show/scoreboard/table-row.tsx index a26908235e0..72ada1397b6 100644 --- a/resources/js/beatmapsets-show/scoreboard/table-row.tsx +++ b/resources/js/beatmapsets-show/scoreboard/table-row.tsx @@ -2,10 +2,12 @@ // See the LICENCE file in the repository root for full licence text. import FlagCountry from 'components/flag-country'; +import FlagTeam from 'components/flag-team'; import Mod from 'components/mod'; import { PlayDetailMenu } from 'components/play-detail-menu'; import ScoreValue from 'components/score-value'; import ScoreboardTime from 'components/scoreboard-time'; +import UserLink from 'components/user-link'; import BeatmapJson from 'interfaces/beatmap-json'; import { SoloScoreJsonForBeatmap } from 'interfaces/solo-score-json'; import { route } from 'laroute'; @@ -113,14 +115,18 @@ export default class ScoreboardTableRow extends React.Component { ) : ( - - {score.user.username} - - + + {score.user.team != null && + + + + } + + )} diff --git a/resources/js/beatmapsets-show/scoreboard/top-card.tsx b/resources/js/beatmapsets-show/scoreboard/top-card.tsx index 7a9ea4359fb..6250d4d57e4 100644 --- a/resources/js/beatmapsets-show/scoreboard/top-card.tsx +++ b/resources/js/beatmapsets-show/scoreboard/top-card.tsx @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. import FlagCountry from 'components/flag-country'; +import FlagTeam from 'components/flag-team'; import Mod from 'components/mod'; import ScorePin from 'components/score-pin'; import ScoreValue from 'components/score-value'; @@ -94,6 +95,15 @@ export default class TopCard extends React.PureComponent { modifiers='flat' /> + + {this.props.score.user.team != null && + + + + } diff --git a/resources/js/components/flag-team.tsx b/resources/js/components/flag-team.tsx new file mode 100644 index 00000000000..57f3ff244c8 --- /dev/null +++ b/resources/js/components/flag-team.tsx @@ -0,0 +1,15 @@ +// 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 TeamJson from 'interfaces/team-json'; +import * as React from 'react'; + +export default function FlagTeam({ team }: { team: TeamJson }) { + return ( + + ); +} diff --git a/resources/js/components/user-card.tsx b/resources/js/components/user-card.tsx index 8c5ca1ac5a4..403ef104f45 100644 --- a/resources/js/components/user-card.tsx +++ b/resources/js/components/user-card.tsx @@ -14,6 +14,7 @@ import { trans } from 'utils/lang'; import { present } from 'utils/string'; import { giftSupporterTagUrl } from 'utils/url'; import FlagCountry from './flag-country'; +import FlagTeam from './flag-team'; import FollowUserMappingButton from './follow-user-mapping-button'; import { PopupMenuPersistent } from './popup-menu-persistent'; import { ReportReportable } from './report-reportable'; @@ -226,6 +227,15 @@ export class UserCard extends React.PureComponent { + {this.user.team != null && ( + + + + )} + {this.props.mode === 'card' && ( <> {this.user.is_supporter && ( diff --git a/resources/js/interfaces/team-json.ts b/resources/js/interfaces/team-json.ts new file mode 100644 index 00000000000..16270293c1b --- /dev/null +++ b/resources/js/interfaces/team-json.ts @@ -0,0 +1,9 @@ +// 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. + +export default interface TeamJson { + id: number; + logo: string | null; + name: string; + short_name: string; +} diff --git a/resources/js/interfaces/user-json.ts b/resources/js/interfaces/user-json.ts index 137f8c2d817..75cc94c65c4 100644 --- a/resources/js/interfaces/user-json.ts +++ b/resources/js/interfaces/user-json.ts @@ -6,6 +6,7 @@ import DailyChallengeUserStatsJson from './daily-challenge-user-stats-json'; import ProfileBannerJson from './profile-banner'; import RankHighestJson from './rank-highest-json'; import RankHistoryJson from './rank-history-json'; +import TeamJson from './team-json'; import UserAccountHistoryJson from './user-account-history-json'; import UserAchievementJson from './user-achievement-json'; import UserBadgeJson from './user-badge-json'; @@ -66,6 +67,7 @@ interface UserJsonAvailableIncludes { statistics: UserStatisticsJson; statistics_rulesets: UserStatisticsRulesetsJson; support_level: number; + team: TeamJson; unread_pm_count: number; user_achievements: UserAchievementJson[]; user_preferences: UserPreferencesJson; diff --git a/resources/js/profile-page/cover.tsx b/resources/js/profile-page/cover.tsx index fd74bb3d387..ef2dddff87c 100644 --- a/resources/js/profile-page/cover.tsx +++ b/resources/js/profile-page/cover.tsx @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. import FlagCountry from 'components/flag-country'; +import FlagTeam from 'components/flag-team'; import { Spinner } from 'components/spinner'; import UserAvatar from 'components/user-avatar'; import UserGroupBadges from 'components/user-group-badges'; @@ -91,6 +92,15 @@ export default class Cover extends React.Component { {this.props.user.country.name} } + {this.props.user.team != null && + + + {this.props.user.team.name} + + }
{this.renderIcons()}
diff --git a/resources/views/forum/topics/_post_info.blade.php b/resources/views/forum/topics/_post_info.blade.php index 8e2b5c4c3cc..db4bd562cbd 100644 --- a/resources/views/forum/topics/_post_info.blade.php +++ b/resources/views/forum/topics/_post_info.blade.php @@ -71,6 +71,17 @@ class="forum-post-info__row forum-post-info__row--title" @endif + @if (($team = $user->team) !== null) + + @endif + @if ($user->country !== null)