From 31d3412f72d4b3db509786ad3fdefe520e421cac Mon Sep 17 00:00:00 2001 From: Max Bolotin Date: Wed, 27 Jul 2022 21:41:28 +0200 Subject: [PATCH 1/8] refresh button when branch changes --- options/locale/locale_en-US.ini | 3 +- routers/private/event.go | 67 +++++++++++ routers/private/hook_post_receive.go | 13 +++ routers/web/repo/issue.go | 1 + templates/repo/issue/view_title.tmpl | 3 + .../js/features/eventsource.sharedworker.js | 1 + web_src/js/features/repo-refresh-pr.js | 106 ++++++++++++++++++ web_src/js/index.js | 2 + web_src/less/_repository.less | 8 ++ 9 files changed, 203 insertions(+), 1 deletion(-) create mode 100644 routers/private/event.go create mode 100644 web_src/js/features/repo-refresh-pr.js diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index a97e2e2b3b86d..4ef0b8fc3fe93 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -1615,6 +1615,8 @@ pulls.auto_merge_canceled_schedule_comment = `canceled auto merging this pull re pulls.delete.title = Delete this pull request? pulls.delete.text = Do you really want to delete this pull request? (This will permanently remove all content. Consider closing it instead, if you intend to keep it archived) +pulls.refresh = Refresh + milestones.new = New Milestone milestones.closed = Closed %s milestones.update_ago = Updated %s ago @@ -3044,7 +3046,6 @@ title = Packages desc = Manage repository packages. empty = There are no packages yet. empty.documentation = For more information on the package registry, see the documentation. -empty.repo = Did you upload a package, but it's not shown here? Go to package settings and link it to this repo. filter.type = Type filter.type.all = All filter.no_result = Your filter produced no results. diff --git a/routers/private/event.go b/routers/private/event.go new file mode 100644 index 0000000000000..2de56682a99b6 --- /dev/null +++ b/routers/private/event.go @@ -0,0 +1,67 @@ +// Copyright 2022 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +// Package private includes all internal routes. The package name internal is ideal but Golang is not allowed, so we use private as package name instead. +package private + +import ( + access_model "code.gitea.io/gitea/models/perm/access" + user_model "code.gitea.io/gitea/models/user" + gitea_context "code.gitea.io/gitea/modules/context" + "code.gitea.io/gitea/modules/eventsource" + "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/private" + "code.gitea.io/gitea/modules/web" +) + +type BranchUpdateEvent struct { + CommitID string + Branch string + BranchDeleted bool + Owner string + RefFullName string + Repository string +} + +func SendBranchUpdateEvent(readers []*user_model.User, commitID, branchName, repoName, refFullName, ownerName string) { + manager := eventsource.GetManager() + + for _, reader := range readers { + manager.SendMessage(reader.ID, &eventsource.Event{ + Name: "branch-update", + Data: BranchUpdateEvent{ + CommitID: commitID, + Branch: branchName, + BranchDeleted: commitID == git.EmptySHA, + Repository: repoName, + RefFullName: refFullName, + Owner: ownerName, + }, + }) + } +} + +func SendContextBranchUpdateEvents(ctx *gitea_context.PrivateContext) error { + opts := web.GetForm(ctx).(*private.HookOptions) + + ownerName := ctx.Params(":owner") + repoName := ctx.Params(":repo") + + repo := loadRepository(ctx, ownerName, repoName) + + readers, err := access_model.GetRepoReaders(repo) + if err != nil { + return err + } + + for i := range opts.OldCommitIDs { + branch := git.RefEndName(opts.RefFullNames[i]) + commitID := opts.NewCommitIDs[i] + refFullName := opts.RefFullNames[i] + + SendBranchUpdateEvent(readers, commitID, branch, repoName, refFullName, ownerName) + } + + return nil +} diff --git a/routers/private/hook_post_receive.go b/routers/private/hook_post_receive.go index 93aa450f9c3b7..c7e8dc2495e70 100644 --- a/routers/private/hook_post_receive.go +++ b/routers/private/hook_post_receive.go @@ -233,6 +233,19 @@ func HookPostReceive(ctx *gitea_context.PrivateContext) { } } } + + // Notify users with read access via eventsource that a change + // has been made + if err := SendContextBranchUpdateEvents(ctx); err != nil { + log.Error("Failed to Get Repo Readers: %s/%s Error: %v", ownerName, repoName, err) + + ctx.JSON(http.StatusInternalServerError, private.HookPostReceiveResult{ + Err: fmt.Sprintf("Failed to Get Repo Readers: %s/%s Error: %v", ownerName, repoName, err), + }) + + return + } + ctx.JSON(http.StatusOK, private.HookPostReceiveResult{ Results: results, RepoWasEmpty: wasEmpty, diff --git a/routers/web/repo/issue.go b/routers/web/repo/issue.go index e6f9529e31e81..846901704b01e 100644 --- a/routers/web/repo/issue.go +++ b/routers/web/repo/issue.go @@ -1171,6 +1171,7 @@ func ViewIssue(ctx *context.Context) { } ctx.Data["PageIsPullList"] = true ctx.Data["PageIsPullConversation"] = true + ctx.Data["Reponame"] = ctx.Repo.Repository.Name } else { MustEnableIssues(ctx) if ctx.Written() { diff --git a/templates/repo/issue/view_title.tmpl b/templates/repo/issue/view_title.tmpl index 456515af33100..3f330e772e4f3 100644 --- a/templates/repo/issue/view_title.tmpl +++ b/templates/repo/issue/view_title.tmpl @@ -5,6 +5,9 @@
{{.locale.Tr "repo.issues.edit"}}
{{end}} +
+ +

{{RenderIssueTitle $.Context .Issue.Title $.RepoLink $.Repository.ComposeMetas}} #{{.Issue.Index}} diff --git a/web_src/js/features/eventsource.sharedworker.js b/web_src/js/features/eventsource.sharedworker.js index 824ccfea79f84..48c2eda4d9e00 100644 --- a/web_src/js/features/eventsource.sharedworker.js +++ b/web_src/js/features/eventsource.sharedworker.js @@ -13,6 +13,7 @@ class Source { this.listen('notification-count'); this.listen('stopwatches'); this.listen('error'); + this.listen('branch-update'); } register(port) { diff --git a/web_src/js/features/repo-refresh-pr.js b/web_src/js/features/repo-refresh-pr.js new file mode 100644 index 0000000000000..d560591cc74f3 --- /dev/null +++ b/web_src/js/features/repo-refresh-pr.js @@ -0,0 +1,106 @@ +import $ from 'jquery'; + +const {appSubUrl} = window.config; + +async function receiveBranchUpdated(event) { + try { + const data = JSON.parse(event.data); + + // eslint-disable-next-line no-console + console.log('Received data', data); + + const staleBranchAlert = document.querySelector('.refresh-pull-request'); + + if (!staleBranchAlert) { + return; + } + + const baseTarget = $(staleBranchAlert).data('baseTarget'); + const headTarget = $(staleBranchAlert).data('headTarget'); + const ownerName = $(staleBranchAlert).data('ownerName'); + const repositoryName = $(staleBranchAlert).data('repositoryName'); + + // eslint-disable-next-line no-console + console.log($(staleBranchAlert).data()); + // eslint-disable-next-line no-console + console.log(data); + + if ( + [baseTarget, headTarget].includes(data.Branch) && + data.Owner === ownerName && + data.Repository === repositoryName + ) { + staleBranchAlert.classList.add('active'); + } + } catch (error) { + console.error(error, event); + } +} + +export function initRepoRefreshPullRequest() { + const staleBranchAlert = $('.refresh-pull-request'); + + if (!staleBranchAlert.length) { + return; + } + + $(staleBranchAlert).on('click', () => { + window.location.reload(); + }); + + if (!!window.EventSource && window.SharedWorker) { + const worker = new SharedWorker( + `${__webpack_public_path__}js/eventsource.sharedworker.js`, + 'notification-worker' + ); + worker.addEventListener('error', (event) => { + console.error(event); + }); + worker.port.addEventListener('messageerror', () => { + console.error('Unable to deserialize message'); + }); + worker.port.postMessage({ + type: 'start', + url: `${window.location.origin}${appSubUrl}/user/events`, + }); + worker.port.addEventListener('message', (event) => { + // eslint-disable-next-line no-console + console.log('received message', event); + if (!event.data || !event.data.type) { + console.error(event); + return; + } + if (event.data.type === 'branch-update') { + const _promise = receiveBranchUpdated(event.data); + } else if (event.data.type === 'error') { + console.error(event.data); + } else if (event.data.type === 'logout') { + if (event.data.data !== 'here') { + return; + } + worker.port.postMessage({ + type: 'close', + }); + worker.port.close(); + window.location.href = appSubUrl; + } else if (event.data.type === 'close') { + worker.port.postMessage({ + type: 'close', + }); + worker.port.close(); + } + }); + worker.port.addEventListener('error', (e) => { + console.error(e); + }); + worker.port.start(); + window.addEventListener('beforeunload', () => { + worker.port.postMessage({ + type: 'close', + }); + worker.port.close(); + }); + } else { + console.error('Service workers not available'); + } +} diff --git a/web_src/js/index.js b/web_src/js/index.js index 6f872b5353378..24685cc4512b1 100644 --- a/web_src/js/index.js +++ b/web_src/js/index.js @@ -82,6 +82,7 @@ import {initInstall} from './features/install.js'; import {initCompWebHookEditor} from './features/comp/WebHookEditor.js'; import {initCommonIssue} from './features/common-issue.js'; import {initRepoBranchButton} from './features/repo-branch.js'; +import {initRepoRefreshPullRequest} from './features/repo-refresh-pr.js'; import {initCommonOrganization} from './features/common-organization.js'; import {initRepoWikiForm} from './features/repo-wiki.js'; import {initRepoCommentForm, initRepository} from './features/repo-legacy.js'; @@ -176,6 +177,7 @@ $(document).ready(() => { initRepoSettingGitHook(); initRepoSettingSearchTeamBox(); initRepoSettingsCollaboration(); + initRepoRefreshPullRequest(); initRepoTemplateSearch(); initRepoTopicBar(); initRepoWikiForm(); diff --git a/web_src/less/_repository.less b/web_src/less/_repository.less index 5aed4dcf72358..6f6ea750d9b98 100644 --- a/web_src/less/_repository.less +++ b/web_src/less/_repository.less @@ -2572,6 +2572,14 @@ display: none; } +.refresh-pull-request { + display: none; + + &.active { + display: inherit; + } +} + .ui.menu .item > img:not(.ui) { width: auto; } From a874a3dd11fcb73f94ea6b093985c05dfb15fd49 Mon Sep 17 00:00:00 2001 From: Max Bolotin Date: Wed, 27 Jul 2022 21:44:09 +0200 Subject: [PATCH 2/8] restore missing locale entry --- options/locale/locale_en-US.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 4ef0b8fc3fe93..f91a5edfe0faf 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -3046,6 +3046,7 @@ title = Packages desc = Manage repository packages. empty = There are no packages yet. empty.documentation = For more information on the package registry, see the documentation. +empty.repo = Did you upload a package, but it's not shown here? Go to package settings and link it to this repo. filter.type = Type filter.type.all = All filter.no_result = Your filter produced no results. From 0b92795fc7e436cdbf22e16f50afcfedf01473ec Mon Sep 17 00:00:00 2001 From: Max Bolotin Date: Wed, 27 Jul 2022 21:45:21 +0200 Subject: [PATCH 3/8] remove js logging --- web_src/js/features/repo-refresh-pr.js | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/web_src/js/features/repo-refresh-pr.js b/web_src/js/features/repo-refresh-pr.js index d560591cc74f3..2cad218ee0e49 100644 --- a/web_src/js/features/repo-refresh-pr.js +++ b/web_src/js/features/repo-refresh-pr.js @@ -6,9 +6,6 @@ async function receiveBranchUpdated(event) { try { const data = JSON.parse(event.data); - // eslint-disable-next-line no-console - console.log('Received data', data); - const staleBranchAlert = document.querySelector('.refresh-pull-request'); if (!staleBranchAlert) { @@ -20,11 +17,6 @@ async function receiveBranchUpdated(event) { const ownerName = $(staleBranchAlert).data('ownerName'); const repositoryName = $(staleBranchAlert).data('repositoryName'); - // eslint-disable-next-line no-console - console.log($(staleBranchAlert).data()); - // eslint-disable-next-line no-console - console.log(data); - if ( [baseTarget, headTarget].includes(data.Branch) && data.Owner === ownerName && @@ -64,8 +56,6 @@ export function initRepoRefreshPullRequest() { url: `${window.location.origin}${appSubUrl}/user/events`, }); worker.port.addEventListener('message', (event) => { - // eslint-disable-next-line no-console - console.log('received message', event); if (!event.data || !event.data.type) { console.error(event); return; From fd2af951cc73fe7027334304f4dcceaecb5f121c Mon Sep 17 00:00:00 2001 From: Max Bolotin Date: Wed, 27 Jul 2022 21:45:55 +0200 Subject: [PATCH 4/8] rename staleBranchAlert element --- web_src/js/features/repo-refresh-pr.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/web_src/js/features/repo-refresh-pr.js b/web_src/js/features/repo-refresh-pr.js index 2cad218ee0e49..bd8e64674ab78 100644 --- a/web_src/js/features/repo-refresh-pr.js +++ b/web_src/js/features/repo-refresh-pr.js @@ -6,23 +6,23 @@ async function receiveBranchUpdated(event) { try { const data = JSON.parse(event.data); - const staleBranchAlert = document.querySelector('.refresh-pull-request'); + const refreshPullRequest = document.querySelector('.refresh-pull-request'); - if (!staleBranchAlert) { + if (!refreshPullRequest) { return; } - const baseTarget = $(staleBranchAlert).data('baseTarget'); - const headTarget = $(staleBranchAlert).data('headTarget'); - const ownerName = $(staleBranchAlert).data('ownerName'); - const repositoryName = $(staleBranchAlert).data('repositoryName'); + const baseTarget = $(refreshPullRequest).data('baseTarget'); + const headTarget = $(refreshPullRequest).data('headTarget'); + const ownerName = $(refreshPullRequest).data('ownerName'); + const repositoryName = $(refreshPullRequest).data('repositoryName'); if ( [baseTarget, headTarget].includes(data.Branch) && data.Owner === ownerName && data.Repository === repositoryName ) { - staleBranchAlert.classList.add('active'); + refreshPullRequest.classList.add('active'); } } catch (error) { console.error(error, event); From 105d5879fbc6a10c226077611893fecc5636aa4a Mon Sep 17 00:00:00 2001 From: Max Bolotin Date: Wed, 27 Jul 2022 22:04:01 +0200 Subject: [PATCH 5/8] fix: nonsensical error message when failing to send branch update events --- routers/private/hook_post_receive.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/routers/private/hook_post_receive.go b/routers/private/hook_post_receive.go index c7e8dc2495e70..7799310b6c855 100644 --- a/routers/private/hook_post_receive.go +++ b/routers/private/hook_post_receive.go @@ -237,10 +237,10 @@ func HookPostReceive(ctx *gitea_context.PrivateContext) { // Notify users with read access via eventsource that a change // has been made if err := SendContextBranchUpdateEvents(ctx); err != nil { - log.Error("Failed to Get Repo Readers: %s/%s Error: %v", ownerName, repoName, err) + log.Error("Failed to Send Branch Update Events: %s/%s Error: %v", ownerName, repoName, err) ctx.JSON(http.StatusInternalServerError, private.HookPostReceiveResult{ - Err: fmt.Sprintf("Failed to Get Repo Readers: %s/%s Error: %v", ownerName, repoName, err), + Err: fmt.Sprintf("Failed to Send Branch Update Events: %s/%s Error: %v", ownerName, repoName, err), }) return From 1d71ee65c052076a6e3cab4d7853d7dc4dd40c78 Mon Sep 17 00:00:00 2001 From: Max Bolotin Date: Fri, 29 Jul 2022 14:19:19 +0200 Subject: [PATCH 6/8] refactor shared worker into singleton instance --- web_src/js/features/notification.js | 38 +---------------- web_src/js/features/repo-refresh-pr.js | 46 +------------------- web_src/js/features/shared-worker.js | 58 ++++++++++++++++++++++++++ web_src/js/features/stopwatch.js | 39 +---------------- 4 files changed, 62 insertions(+), 119 deletions(-) create mode 100644 web_src/js/features/shared-worker.js diff --git a/web_src/js/features/notification.js b/web_src/js/features/notification.js index 36df196cac2d8..c2db756a88dbe 100644 --- a/web_src/js/features/notification.js +++ b/web_src/js/features/notification.js @@ -1,4 +1,5 @@ import $ from 'jquery'; +import worker from './shared-worker.js'; const {appSubUrl, csrfToken, notificationSettings} = window.config; let notificationSequenceNumber = 0; @@ -51,17 +52,6 @@ export function initNotificationCount() { if (notificationSettings.EventSourceUpdateTime > 0 && !!window.EventSource && window.SharedWorker) { // Try to connect to the event source via the shared worker first - const worker = new SharedWorker(`${__webpack_public_path__}js/eventsource.sharedworker.js`, 'notification-worker'); - worker.addEventListener('error', (event) => { - console.error(event); - }); - worker.port.addEventListener('messageerror', () => { - console.error('Unable to deserialize message'); - }); - worker.port.postMessage({ - type: 'start', - url: `${window.location.origin}${appSubUrl}/user/events`, - }); worker.port.addEventListener('message', (event) => { if (!event.data || !event.data.type) { console.error(event); @@ -69,34 +59,8 @@ export function initNotificationCount() { } if (event.data.type === 'notification-count') { const _promise = receiveUpdateCount(event.data); - } else if (event.data.type === 'error') { - console.error(event.data); - } else if (event.data.type === 'logout') { - if (event.data.data !== 'here') { - return; - } - worker.port.postMessage({ - type: 'close', - }); - worker.port.close(); - window.location.href = appSubUrl; - } else if (event.data.type === 'close') { - worker.port.postMessage({ - type: 'close', - }); - worker.port.close(); } }); - worker.port.addEventListener('error', (e) => { - console.error(e); - }); - worker.port.start(); - window.addEventListener('beforeunload', () => { - worker.port.postMessage({ - type: 'close', - }); - worker.port.close(); - }); return; } diff --git a/web_src/js/features/repo-refresh-pr.js b/web_src/js/features/repo-refresh-pr.js index bd8e64674ab78..9fe94298ca793 100644 --- a/web_src/js/features/repo-refresh-pr.js +++ b/web_src/js/features/repo-refresh-pr.js @@ -1,6 +1,5 @@ import $ from 'jquery'; - -const {appSubUrl} = window.config; +import worker from './shared-worker.js'; async function receiveBranchUpdated(event) { try { @@ -41,55 +40,14 @@ export function initRepoRefreshPullRequest() { }); if (!!window.EventSource && window.SharedWorker) { - const worker = new SharedWorker( - `${__webpack_public_path__}js/eventsource.sharedworker.js`, - 'notification-worker' - ); - worker.addEventListener('error', (event) => { - console.error(event); - }); - worker.port.addEventListener('messageerror', () => { - console.error('Unable to deserialize message'); - }); - worker.port.postMessage({ - type: 'start', - url: `${window.location.origin}${appSubUrl}/user/events`, - }); worker.port.addEventListener('message', (event) => { if (!event.data || !event.data.type) { - console.error(event); return; } if (event.data.type === 'branch-update') { - const _promise = receiveBranchUpdated(event.data); - } else if (event.data.type === 'error') { - console.error(event.data); - } else if (event.data.type === 'logout') { - if (event.data.data !== 'here') { - return; - } - worker.port.postMessage({ - type: 'close', - }); - worker.port.close(); - window.location.href = appSubUrl; - } else if (event.data.type === 'close') { - worker.port.postMessage({ - type: 'close', - }); - worker.port.close(); + receiveBranchUpdated(event.data); } }); - worker.port.addEventListener('error', (e) => { - console.error(e); - }); - worker.port.start(); - window.addEventListener('beforeunload', () => { - worker.port.postMessage({ - type: 'close', - }); - worker.port.close(); - }); } else { console.error('Service workers not available'); } diff --git a/web_src/js/features/shared-worker.js b/web_src/js/features/shared-worker.js new file mode 100644 index 0000000000000..5a4474d6894c7 --- /dev/null +++ b/web_src/js/features/shared-worker.js @@ -0,0 +1,58 @@ +const {appSubUrl} = window.config; + +const worker = new SharedWorker( + `${__webpack_public_path__}js/eventsource.sharedworker.js`, + 'notification-worker' +); + +worker.addEventListener('error', (event) => { + console.error(event); +}); + +worker.port.addEventListener('messageerror', () => { + console.error('Unable to deserialize message'); +}); + +worker.port.postMessage({ + type: 'start', + url: `${window.location.origin}${appSubUrl}/user/events`, +}); + +worker.port.addEventListener('message', (event) => { + if (!event.data || !event.data.type) { + console.error(event); + return; + } + if (event.data.type === 'error') { + console.error(event.data); + } else if (event.data.type === 'logout') { + if (event.data.data !== 'here') { + return; + } + worker.port.postMessage({ + type: 'close', + }); + worker.port.close(); + window.location.href = appSubUrl; + } else if (event.data.type === 'close') { + worker.port.postMessage({ + type: 'close', + }); + worker.port.close(); + } +}); + +worker.port.addEventListener('error', (e) => { + console.error(e); +}); + +worker.port.start(); + +window.addEventListener('beforeunload', () => { + worker.port.postMessage({ + type: 'close', + }); + worker.port.close(); +}); + +export default worker; diff --git a/web_src/js/features/stopwatch.js b/web_src/js/features/stopwatch.js index d63da4155af27..c0d1008160fcf 100644 --- a/web_src/js/features/stopwatch.js +++ b/web_src/js/features/stopwatch.js @@ -1,5 +1,6 @@ import $ from 'jquery'; import prettyMilliseconds from 'pretty-ms'; +import worker from './shared-worker.js'; const {appSubUrl, csrfToken, notificationSettings, enableTimeTracking} = window.config; let updateTimeInterval = null; // holds setInterval id when active @@ -28,52 +29,14 @@ export function initStopwatch() { if (notificationSettings.EventSourceUpdateTime > 0 && !!window.EventSource && window.SharedWorker) { // Try to connect to the event source via the shared worker first - const worker = new SharedWorker(`${__webpack_public_path__}js/eventsource.sharedworker.js`, 'notification-worker'); - worker.addEventListener('error', (event) => { - console.error(event); - }); - worker.port.addEventListener('messageerror', () => { - console.error('Unable to deserialize message'); - }); - worker.port.postMessage({ - type: 'start', - url: `${window.location.origin}${appSubUrl}/user/events`, - }); worker.port.addEventListener('message', (event) => { if (!event.data || !event.data.type) { - console.error(event); return; } if (event.data.type === 'stopwatches') { updateStopwatchData(JSON.parse(event.data.data)); - } else if (event.data.type === 'error') { - console.error(event.data); - } else if (event.data.type === 'logout') { - if (event.data.data !== 'here') { - return; - } - worker.port.postMessage({ - type: 'close', - }); - worker.port.close(); - window.location.href = appSubUrl; - } else if (event.data.type === 'close') { - worker.port.postMessage({ - type: 'close', - }); - worker.port.close(); } }); - worker.port.addEventListener('error', (e) => { - console.error(e); - }); - worker.port.start(); - window.addEventListener('beforeunload', () => { - worker.port.postMessage({ - type: 'close', - }); - worker.port.close(); - }); return; } From effd79ea9e58e16c73c3b636b7bd0422689ea7d9 Mon Sep 17 00:00:00 2001 From: Max Bolotin Date: Sat, 30 Jul 2022 13:42:57 +0200 Subject: [PATCH 7/8] shared worker exported through singleton instantiation function that checks for EventSource dependencies --- web_src/js/features/notification.js | 6 +- web_src/js/features/repo-refresh-pr.js | 6 +- web_src/js/features/shared-worker.js | 110 ++++++++++++++----------- web_src/js/features/stopwatch.js | 6 +- 4 files changed, 74 insertions(+), 54 deletions(-) diff --git a/web_src/js/features/notification.js b/web_src/js/features/notification.js index c2db756a88dbe..aa7676c3e0a2c 100644 --- a/web_src/js/features/notification.js +++ b/web_src/js/features/notification.js @@ -1,5 +1,5 @@ import $ from 'jquery'; -import worker from './shared-worker.js'; +import getMemoizedSharedWorker from './shared-worker.js'; const {appSubUrl, csrfToken, notificationSettings} = window.config; let notificationSequenceNumber = 0; @@ -50,7 +50,9 @@ export function initNotificationCount() { return; } - if (notificationSettings.EventSourceUpdateTime > 0 && !!window.EventSource && window.SharedWorker) { + let worker; + + if (notificationSettings.EventSourceUpdateTime > 0 && (worker = getMemoizedSharedWorker())) { // Try to connect to the event source via the shared worker first worker.port.addEventListener('message', (event) => { if (!event.data || !event.data.type) { diff --git a/web_src/js/features/repo-refresh-pr.js b/web_src/js/features/repo-refresh-pr.js index 9fe94298ca793..19d57c68b2612 100644 --- a/web_src/js/features/repo-refresh-pr.js +++ b/web_src/js/features/repo-refresh-pr.js @@ -1,5 +1,5 @@ import $ from 'jquery'; -import worker from './shared-worker.js'; +import getMemoizedSharedWorker from './shared-worker.js'; async function receiveBranchUpdated(event) { try { @@ -39,7 +39,9 @@ export function initRepoRefreshPullRequest() { window.location.reload(); }); - if (!!window.EventSource && window.SharedWorker) { + const worker = getMemoizedSharedWorker(); + + if (worker) { worker.port.addEventListener('message', (event) => { if (!event.data || !event.data.type) { return; diff --git a/web_src/js/features/shared-worker.js b/web_src/js/features/shared-worker.js index 5a4474d6894c7..c0894b3cbcec0 100644 --- a/web_src/js/features/shared-worker.js +++ b/web_src/js/features/shared-worker.js @@ -1,58 +1,72 @@ const {appSubUrl} = window.config; -const worker = new SharedWorker( - `${__webpack_public_path__}js/eventsource.sharedworker.js`, - 'notification-worker' -); - -worker.addEventListener('error', (event) => { - console.error(event); -}); - -worker.port.addEventListener('messageerror', () => { - console.error('Unable to deserialize message'); -}); - -worker.port.postMessage({ - type: 'start', - url: `${window.location.origin}${appSubUrl}/user/events`, -}); - -worker.port.addEventListener('message', (event) => { - if (!event.data || !event.data.type) { - console.error(event); - return; +let worker; + +function getMemoizedSharedWorker() { + if (!window.EventSource || !window.SharedWorker) { + return null; } - if (event.data.type === 'error') { - console.error(event.data); - } else if (event.data.type === 'logout') { - if (event.data.data !== 'here') { - return; - } - worker.port.postMessage({ - type: 'close', + + if (!worker) { + // eslint-disable-next-line no-console + console.log('Starting worker'); + worker = new SharedWorker( + `${__webpack_public_path__}js/eventsource.sharedworker.js`, + 'notification-worker' + ); + + worker.addEventListener('error', (event) => { + console.error(event); }); - worker.port.close(); - window.location.href = appSubUrl; - } else if (event.data.type === 'close') { + + worker.port.addEventListener('messageerror', () => { + console.error('Unable to deserialize message'); + }); + worker.port.postMessage({ - type: 'close', + type: 'start', + url: `${window.location.origin}${appSubUrl}/user/events`, + }); + + worker.port.addEventListener('message', (event) => { + if (!event.data || !event.data.type) { + console.error(event); + return; + } + if (event.data.type === 'error') { + console.error(event.data); + } else if (event.data.type === 'logout') { + if (event.data.data !== 'here') { + return; + } + worker.port.postMessage({ + type: 'close', + }); + worker.port.close(); + window.location.href = appSubUrl; + } else if (event.data.type === 'close') { + worker.port.postMessage({ + type: 'close', + }); + worker.port.close(); + } }); - worker.port.close(); - } -}); -worker.port.addEventListener('error', (e) => { - console.error(e); -}); + worker.port.addEventListener('error', (e) => { + console.error(e); + }); -worker.port.start(); + worker.port.start(); + + window.addEventListener('beforeunload', () => { + worker.port.postMessage({ + type: 'close', + }); + worker.port.close(); + }); + } -window.addEventListener('beforeunload', () => { - worker.port.postMessage({ - type: 'close', - }); - worker.port.close(); -}); + return worker; +} -export default worker; +export default getMemoizedSharedWorker; diff --git a/web_src/js/features/stopwatch.js b/web_src/js/features/stopwatch.js index c0d1008160fcf..e0a2f8dd1fe98 100644 --- a/web_src/js/features/stopwatch.js +++ b/web_src/js/features/stopwatch.js @@ -1,6 +1,6 @@ import $ from 'jquery'; import prettyMilliseconds from 'pretty-ms'; -import worker from './shared-worker.js'; +import getMemoizedSharedWorker from './shared-worker.js'; const {appSubUrl, csrfToken, notificationSettings, enableTimeTracking} = window.config; let updateTimeInterval = null; // holds setInterval id when active @@ -27,7 +27,9 @@ export function initStopwatch() { $(this).parent().trigger('submit'); }); - if (notificationSettings.EventSourceUpdateTime > 0 && !!window.EventSource && window.SharedWorker) { + let worker; + + if (notificationSettings.EventSourceUpdateTime > 0 && (worker = getMemoizedSharedWorker())) { // Try to connect to the event source via the shared worker first worker.port.addEventListener('message', (event) => { if (!event.data || !event.data.type) { From e7a22407ea580c4c37e80a35bad8f2213043a0fc Mon Sep 17 00:00:00 2001 From: Max Bolotin Date: Sat, 30 Jul 2022 13:44:07 +0200 Subject: [PATCH 8/8] remove logging --- web_src/js/features/shared-worker.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/web_src/js/features/shared-worker.js b/web_src/js/features/shared-worker.js index c0894b3cbcec0..4ea51cdce26ca 100644 --- a/web_src/js/features/shared-worker.js +++ b/web_src/js/features/shared-worker.js @@ -8,8 +8,6 @@ function getMemoizedSharedWorker() { } if (!worker) { - // eslint-disable-next-line no-console - console.log('Starting worker'); worker = new SharedWorker( `${__webpack_public_path__}js/eventsource.sharedworker.js`, 'notification-worker'