Merge "Screenshot test support"
diff --git a/Documentation/rest-api-accounts.txt b/Documentation/rest-api-accounts.txt
index e4bc8f0..7e06e4a 100644
--- a/Documentation/rest-api-accounts.txt
+++ b/Documentation/rest-api-accounts.txt
@@ -1292,6 +1292,7 @@
"mute_common_path_prefixes": true,
"publish_comments_on_push": true,
"work_in_progress_by_default": true,
+ "allow_browser_notifications": true,
"default_base_for_merges": "FIRST_PARENT",
"my": [
{
@@ -1344,6 +1345,7 @@
"size_bar_in_change_table": true,
"disable_keyboard_shortcuts": true,
"disable_token_highlighting": true,
+ "allow_browser_notifications": false,
"diff_view": "SIDE_BY_SIDE",
"mute_common_path_prefixes": true,
"my": [
@@ -2686,6 +2688,8 @@
|`signed_off_by` |not set if `false`|
Whether to insert Signed-off-by footer in changes created with the
inline edit feature.
+|`allow_browser_notifications` |not set if `false`|
+Whether to prompt user to enable browser notification in browser.
|`my` ||
The menu items of the `MY` top menu as a list of
link:rest-api-config.html#top-menu-item-info[TopMenuItemInfo] entities.
@@ -2755,6 +2759,8 @@
|`signed_off_by` |optional|
Whether to insert Signed-off-by footer in changes created with the
inline edit feature.
+|`allow_browser_notifications` |not set if `false`|
+Whether to prompt user to enable browser notification in browser.
|`my` |optional|
The menu items of the `MY` top menu as a list of
link:rest-api-config.html#top-menu-item-info[TopMenuItemInfo] entities.
diff --git a/java/com/google/gerrit/extensions/client/GeneralPreferencesInfo.java b/java/com/google/gerrit/extensions/client/GeneralPreferencesInfo.java
index 91d6294..1ee2cd8 100644
--- a/java/com/google/gerrit/extensions/client/GeneralPreferencesInfo.java
+++ b/java/com/google/gerrit/extensions/client/GeneralPreferencesInfo.java
@@ -150,6 +150,7 @@
public Boolean workInProgressByDefault;
public List<MenuItem> my;
public List<String> changeTable;
+ public Boolean allowBrowserNotifications;
public DateFormat getDateFormat() {
if (dateFormat == null) {
@@ -208,6 +209,7 @@
p.disableKeyboardShortcuts = false;
p.disableTokenHighlighting = false;
p.workInProgressByDefault = false;
+ p.allowBrowserNotifications = true;
return p;
}
}
diff --git a/javatests/com/google/gerrit/acceptance/api/accounts/GeneralPreferencesIT.java b/javatests/com/google/gerrit/acceptance/api/accounts/GeneralPreferencesIT.java
index ff1aa89..f5b311b 100644
--- a/javatests/com/google/gerrit/acceptance/api/accounts/GeneralPreferencesIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/accounts/GeneralPreferencesIT.java
@@ -84,6 +84,7 @@
i.legacycidInChangeTable ^= true;
i.muteCommonPathPrefixes ^= true;
i.signedOffBy ^= true;
+ i.allowBrowserNotifications ^= false;
i.diffView = DiffView.UNIFIED_DIFF;
i.my = new ArrayList<>();
i.my.add(new MenuItem("name", "url"));
@@ -95,6 +96,7 @@
assertThat(o.my).containsExactlyElementsIn(i.my);
assertThat(o.changeTable).containsExactlyElementsIn(i.changeTable);
assertThat(o.theme).isEqualTo(i.theme);
+ assertThat(o.allowBrowserNotifications).isEqualTo(i.allowBrowserNotifications);
assertThat(o.disableKeyboardShortcuts).isEqualTo(i.disableKeyboardShortcuts);
}
diff --git a/polygerrit-ui/app/services/flags/flags.ts b/polygerrit-ui/app/services/flags/flags.ts
index 5d9800d..0bf1522 100644
--- a/polygerrit-ui/app/services/flags/flags.ts
+++ b/polygerrit-ui/app/services/flags/flags.ts
@@ -16,6 +16,7 @@
export enum KnownExperimentId {
NEW_IMAGE_DIFF_UI = 'UiFeature__new_image_diff_ui',
CHECKS_DEVELOPER = 'UiFeature__checks_developer',
+ PUSH_NOTIFICATIONS_DEVELOPER = 'UiFeature__push_notifications_developer',
DIFF_RENDERING_LIT = 'UiFeature__diff_rendering_lit',
PUSH_NOTIFICATIONS = 'UiFeature__push_notifications',
SUGGEST_EDIT = 'UiFeature__suggest_edit',
diff --git a/polygerrit-ui/app/services/service-worker-installer.ts b/polygerrit-ui/app/services/service-worker-installer.ts
index 3af79a3..0eec23a 100644
--- a/polygerrit-ui/app/services/service-worker-installer.ts
+++ b/polygerrit-ui/app/services/service-worker-installer.ts
@@ -5,9 +5,13 @@
*/
import {FlagsService, KnownExperimentId} from './flags/flags';
-import {registerServiceWorker} from '../utils/worker-util';
+import {
+ areNotificationsEnabled,
+ registerServiceWorker,
+} from '../utils/worker-util';
import {UserModel} from '../models/user/user-model';
import {AccountDetailInfo} from '../api/rest-api';
+import {until} from '../utils/async-util';
/** Type of incoming messages for ServiceWorker. */
export enum ServiceWorkerMessageType {
@@ -30,8 +34,23 @@
async init() {
if (this.initialized) return;
- if (!this.flagsService.isEnabled(KnownExperimentId.PUSH_NOTIFICATIONS)) {
- return;
+ if (
+ !this.flagsService.isEnabled(
+ KnownExperimentId.PUSH_NOTIFICATIONS_DEVELOPER
+ )
+ ) {
+ if (!this.flagsService.isEnabled(KnownExperimentId.PUSH_NOTIFICATIONS)) {
+ return;
+ }
+ const timeout1s = new Promise(resolve => {
+ setTimeout(resolve, 1000);
+ });
+ // We wait for account to be defined, if its not defined in 1s, it's guest
+ await Promise.race([
+ timeout1s,
+ until(this.userModel.account$, account => !!account),
+ ]);
+ if (!areNotificationsEnabled(this.account)) return;
}
if (!('serviceWorker' in navigator)) {
console.error('Service worker API not available');
diff --git a/polygerrit-ui/app/utils/worker-util.ts b/polygerrit-ui/app/utils/worker-util.ts
index c735a44..aeee537 100644
--- a/polygerrit-ui/app/utils/worker-util.ts
+++ b/polygerrit-ui/app/utils/worker-util.ts
@@ -4,6 +4,11 @@
* SPDX-License-Identifier: Apache-2.0
*/
+// This file adds some simple checks to match internal Google rules.
+// Internally at Google it has different a implementation.
+
+import {AccountDetailInfo} from '../api/rest-api';
+
/**
* We cannot import the worker script from cdn directly, because that is
* creating cross-origin issues. Instead we have to create a worker script on
@@ -25,6 +30,10 @@
return window.navigator.serviceWorker.register(workerUrl);
}
+export function areNotificationsEnabled(account?: AccountDetailInfo): boolean {
+ return !!account?._account_id;
+}
+
export function importScript(scope: WorkerGlobalScope, url: string): void {
scope.importScripts(url);
}