From 2511bfffc0c190cc2355bf07022cdb42f0d6539a Mon Sep 17 00:00:00 2001 From: nanaya Date: Tue, 12 Nov 2024 20:27:40 +0900 Subject: [PATCH 1/6] 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 2/6] 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 3/6] 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 4/6] 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 5/6] 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 6/6] 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;