mirror of
https://github.com/discourse/discourse.git
synced 2024-11-29 04:03:57 -06:00
DEV: Move desktop notifications logic to service (#24466)
This commit is contained in:
parent
8cf13977a1
commit
c4767158df
@ -0,0 +1,46 @@
|
||||
import Component from "@glimmer/component";
|
||||
import { inject as service } from "@ember/service";
|
||||
import DButton from "discourse/components/d-button";
|
||||
import i18n from "discourse-common/helpers/i18n";
|
||||
|
||||
export default class DesktopNotificationsConfig extends Component {
|
||||
@service desktopNotifications;
|
||||
|
||||
<template>
|
||||
<div class="controls">
|
||||
{{#if this.desktopNotifications.isNotSupported}}
|
||||
<DButton
|
||||
@icon="bell-slash"
|
||||
@label="user.desktop_notifications.not_supported"
|
||||
@disabled="true"
|
||||
class="btn-default"
|
||||
/>
|
||||
{{/if}}
|
||||
{{#if this.desktopNotifications.isDeniedPermission}}
|
||||
<DButton
|
||||
@icon="bell-slash"
|
||||
@label="user.desktop_notifications.perm_denied_btn"
|
||||
@disabled="true"
|
||||
class="btn-default"
|
||||
/>
|
||||
{{i18n "user.desktop_notifications.perm_denied_expl"}}
|
||||
{{else}}
|
||||
{{#if this.desktopNotifications.isSubscribed}}
|
||||
<DButton
|
||||
@icon="far-bell-slash"
|
||||
@label="user.desktop_notifications.disable"
|
||||
@action={{this.desktopNotifications.disable}}
|
||||
class="btn-default"
|
||||
/>
|
||||
{{else}}
|
||||
<DButton
|
||||
@icon="far-bell"
|
||||
@label="user.desktop_notifications.enable"
|
||||
@action={{this.desktopNotifications.enable}}
|
||||
class="btn-default"
|
||||
/>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</template>
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
{{#if this.isNotSupported}}
|
||||
<DButton
|
||||
@icon="bell-slash"
|
||||
@label="user.desktop_notifications.not_supported"
|
||||
@disabled="true"
|
||||
class="btn-default"
|
||||
/>
|
||||
{{/if}}
|
||||
{{#if this.isDeniedPermission}}
|
||||
<DButton
|
||||
@icon="bell-slash"
|
||||
@label="user.desktop_notifications.perm_denied_btn"
|
||||
@action={{action "recheckPermission"}}
|
||||
@disabled="true"
|
||||
class="btn-default"
|
||||
/>
|
||||
{{i18n "user.desktop_notifications.perm_denied_expl"}}
|
||||
{{else}}
|
||||
{{#if this.isSubscribed}}
|
||||
<DButton
|
||||
@icon="far-bell-slash"
|
||||
@label="user.desktop_notifications.disable"
|
||||
@action={{action "turnoff"}}
|
||||
class="btn-default"
|
||||
/>
|
||||
{{else}}
|
||||
<DButton
|
||||
@icon="far-bell"
|
||||
@label="user.desktop_notifications.enable"
|
||||
@action={{action "turnon"}}
|
||||
class="btn-default"
|
||||
/>
|
||||
{{/if}}
|
||||
{{/if}}
|
@ -1,138 +0,0 @@
|
||||
import Component from "@ember/component";
|
||||
import { or } from "@ember/object/computed";
|
||||
import {
|
||||
confirmNotification,
|
||||
context,
|
||||
} from "discourse/lib/desktop-notifications";
|
||||
import KeyValueStore from "discourse/lib/key-value-store";
|
||||
import {
|
||||
isPushNotificationsSupported,
|
||||
keyValueStore as pushNotificationKeyValueStore,
|
||||
subscribe as subscribePushNotification,
|
||||
unsubscribe as unsubscribePushNotification,
|
||||
userSubscriptionKey as pushNotificationUserSubscriptionKey,
|
||||
} from "discourse/lib/push-notifications";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
|
||||
const keyValueStore = new KeyValueStore(context);
|
||||
|
||||
export default Component.extend({
|
||||
classNames: ["controls"],
|
||||
|
||||
@discourseComputed("isNotSupported")
|
||||
notificationsPermission(isNotSupported) {
|
||||
return isNotSupported ? "" : Notification.permission;
|
||||
},
|
||||
|
||||
@discourseComputed
|
||||
notificationsDisabled: {
|
||||
set(value) {
|
||||
keyValueStore.setItem("notifications-disabled", value);
|
||||
return keyValueStore.getItem("notifications-disabled");
|
||||
},
|
||||
get() {
|
||||
return keyValueStore.getItem("notifications-disabled");
|
||||
},
|
||||
},
|
||||
|
||||
@discourseComputed
|
||||
isNotSupported() {
|
||||
return typeof window.Notification === "undefined";
|
||||
},
|
||||
|
||||
@discourseComputed("isNotSupported", "notificationsPermission")
|
||||
isDeniedPermission(isNotSupported, notificationsPermission) {
|
||||
return isNotSupported ? false : notificationsPermission === "denied";
|
||||
},
|
||||
|
||||
@discourseComputed("isNotSupported", "notificationsPermission")
|
||||
isGrantedPermission(isNotSupported, notificationsPermission) {
|
||||
return isNotSupported ? false : notificationsPermission === "granted";
|
||||
},
|
||||
|
||||
@discourseComputed("isGrantedPermission", "notificationsDisabled")
|
||||
isEnabledDesktop(isGrantedPermission, notificationsDisabled) {
|
||||
return isGrantedPermission ? !notificationsDisabled : false;
|
||||
},
|
||||
|
||||
// TODO: (selase) getter should consistently return a boolean
|
||||
@discourseComputed
|
||||
isEnabledPush: {
|
||||
set(value) {
|
||||
const user = this.currentUser;
|
||||
if (!user) {
|
||||
return false;
|
||||
}
|
||||
pushNotificationKeyValueStore.setItem(
|
||||
pushNotificationUserSubscriptionKey(user),
|
||||
value
|
||||
);
|
||||
return pushNotificationKeyValueStore.getItem(
|
||||
pushNotificationUserSubscriptionKey(user)
|
||||
);
|
||||
},
|
||||
get() {
|
||||
const user = this.currentUser;
|
||||
return user
|
||||
? pushNotificationKeyValueStore.getItem(
|
||||
pushNotificationUserSubscriptionKey(user)
|
||||
)
|
||||
: false;
|
||||
},
|
||||
},
|
||||
|
||||
isEnabled: or("isEnabledDesktop", "isEnabledPush"),
|
||||
|
||||
@discourseComputed("isEnabled", "isEnabledPush", "notificationsDisabled")
|
||||
isSubscribed(isEnabled, isEnabledPush, notificationsDisabled) {
|
||||
if (!isEnabled) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.isPushNotificationsPreferred()) {
|
||||
return isEnabledPush === "subscribed";
|
||||
} else {
|
||||
return notificationsDisabled === "";
|
||||
}
|
||||
},
|
||||
|
||||
isPushNotificationsPreferred() {
|
||||
return (
|
||||
(this.site.mobileView ||
|
||||
this.siteSettings.enable_desktop_push_notifications) &&
|
||||
isPushNotificationsSupported()
|
||||
);
|
||||
},
|
||||
|
||||
actions: {
|
||||
recheckPermission() {
|
||||
this.notifyPropertyChange("notificationsPermission");
|
||||
},
|
||||
|
||||
turnoff() {
|
||||
if (this.isEnabledDesktop) {
|
||||
this.set("notificationsDisabled", "disabled");
|
||||
this.notifyPropertyChange("notificationsPermission");
|
||||
}
|
||||
if (this.isEnabledPush) {
|
||||
unsubscribePushNotification(this.currentUser, () => {
|
||||
this.set("isEnabledPush", "");
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
turnon() {
|
||||
if (this.isPushNotificationsPreferred()) {
|
||||
subscribePushNotification(() => {
|
||||
this.set("isEnabledPush", "subscribed");
|
||||
}, this.siteSettings.vapid_public_key_bytes);
|
||||
} else {
|
||||
this.set("notificationsDisabled", "");
|
||||
Notification.requestPermission(() => {
|
||||
confirmNotification(this.siteSettings);
|
||||
this.notifyPropertyChange("notificationsPermission");
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
@ -0,0 +1,79 @@
|
||||
import Component from "@glimmer/component";
|
||||
import { tracked } from "@glimmer/tracking";
|
||||
import { action } from "@ember/object";
|
||||
import { inject as service } from "@ember/service";
|
||||
import DButton from "discourse/components/d-button";
|
||||
import { keyValueStore as pushNotificationKeyValueStore } from "discourse/lib/push-notifications";
|
||||
import i18n from "discourse-common/helpers/i18n";
|
||||
|
||||
const userDismissedPromptKey = "dismissed-prompt";
|
||||
|
||||
export default class NotificationConsentBanner extends Component {
|
||||
@service capabilities;
|
||||
@service currentUser;
|
||||
@service desktopNotifications;
|
||||
@service siteSettings;
|
||||
|
||||
@tracked bannerDismissed;
|
||||
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
this.bannerDismissed = pushNotificationKeyValueStore.getItem(
|
||||
userDismissedPromptKey
|
||||
);
|
||||
}
|
||||
|
||||
setBannerDismissed(value) {
|
||||
pushNotificationKeyValueStore.setItem(userDismissedPromptKey, value);
|
||||
this.bannerDismissed = pushNotificationKeyValueStore.getItem(
|
||||
userDismissedPromptKey
|
||||
);
|
||||
}
|
||||
|
||||
get showNotificationPromptBanner() {
|
||||
return (
|
||||
this.siteSettings.push_notifications_prompt &&
|
||||
!this.desktopNotifications.isNotSupported &&
|
||||
this.currentUser &&
|
||||
this.capabilities.isPwa &&
|
||||
Notification.permission !== "denied" &&
|
||||
Notification.permission !== "granted" &&
|
||||
!this.desktopNotifications.isEnabled &&
|
||||
!this.bannerDismissed
|
||||
);
|
||||
}
|
||||
|
||||
@action
|
||||
turnon() {
|
||||
this.desktopNotifications.enable();
|
||||
this.setBannerDismissed(true);
|
||||
}
|
||||
|
||||
@action
|
||||
dismiss() {
|
||||
this.setBannerDismissed(false);
|
||||
}
|
||||
|
||||
<template>
|
||||
{{#if this.showNotificationPromptBanner}}
|
||||
<div class="row">
|
||||
<div class="consent_banner alert alert-info">
|
||||
<span>
|
||||
{{i18n "user.desktop_notifications.consent_prompt"}}
|
||||
<DButton
|
||||
@display="link"
|
||||
@action={{this.turnon}}
|
||||
@label="user.desktop_notifications.enable"
|
||||
/>
|
||||
</span>
|
||||
<DButton
|
||||
@icon="times"
|
||||
@action={{this.dismiss}}
|
||||
@title="banner.close"
|
||||
class="btn-flat close"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
</template>
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
{{#if this.showNotificationPromptBanner}}
|
||||
<div class="row">
|
||||
<div class="consent_banner alert alert-info">
|
||||
<span>
|
||||
{{i18n "user.desktop_notifications.consent_prompt"}}
|
||||
<DButton
|
||||
@display="link"
|
||||
@action={{action "turnon"}}
|
||||
@label="user.desktop_notifications.enable"
|
||||
/>
|
||||
</span>
|
||||
<DButton
|
||||
@icon="times"
|
||||
@action={{action "dismiss"}}
|
||||
@title="banner.close"
|
||||
class="btn-flat close"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
@ -1,52 +0,0 @@
|
||||
import DesktopNotificationConfig from "discourse/components/desktop-notification-config";
|
||||
import { keyValueStore as pushNotificationKeyValueStore } from "discourse/lib/push-notifications";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
|
||||
const userDismissedPromptKey = "dismissed-prompt";
|
||||
|
||||
export default DesktopNotificationConfig.extend({
|
||||
@discourseComputed
|
||||
bannerDismissed: {
|
||||
set(value) {
|
||||
pushNotificationKeyValueStore.setItem(userDismissedPromptKey, value);
|
||||
return pushNotificationKeyValueStore.getItem(userDismissedPromptKey);
|
||||
},
|
||||
get() {
|
||||
return pushNotificationKeyValueStore.getItem(userDismissedPromptKey);
|
||||
},
|
||||
},
|
||||
|
||||
@discourseComputed(
|
||||
"isNotSupported",
|
||||
"isEnabled",
|
||||
"bannerDismissed",
|
||||
"currentUser.any_posts"
|
||||
)
|
||||
showNotificationPromptBanner(
|
||||
isNotSupported,
|
||||
isEnabled,
|
||||
bannerDismissed,
|
||||
anyPosts
|
||||
) {
|
||||
return (
|
||||
this.siteSettings.push_notifications_prompt &&
|
||||
!isNotSupported &&
|
||||
this.currentUser &&
|
||||
(this.capabilities.isPwa || anyPosts) &&
|
||||
Notification.permission !== "denied" &&
|
||||
Notification.permission !== "granted" &&
|
||||
!isEnabled &&
|
||||
!bannerDismissed
|
||||
);
|
||||
},
|
||||
|
||||
actions: {
|
||||
turnon() {
|
||||
this._super(...arguments);
|
||||
this.set("bannerDismissed", true);
|
||||
},
|
||||
dismiss() {
|
||||
this.set("bannerDismissed", true);
|
||||
},
|
||||
},
|
||||
});
|
@ -0,0 +1,143 @@
|
||||
import { tracked } from "@glimmer/tracking";
|
||||
import { action } from "@ember/object";
|
||||
import Service, { inject as service } from "@ember/service";
|
||||
import {
|
||||
confirmNotification,
|
||||
context,
|
||||
} from "discourse/lib/desktop-notifications";
|
||||
import { disableImplicitInjections } from "discourse/lib/implicit-injections";
|
||||
import KeyValueStore from "discourse/lib/key-value-store";
|
||||
import {
|
||||
isPushNotificationsSupported,
|
||||
keyValueStore as pushNotificationKeyValueStore,
|
||||
subscribe as subscribePushNotification,
|
||||
unsubscribe as unsubscribePushNotification,
|
||||
userSubscriptionKey as pushNotificationUserSubscriptionKey,
|
||||
} from "discourse/lib/push-notifications";
|
||||
|
||||
const keyValueStore = new KeyValueStore(context);
|
||||
|
||||
@disableImplicitInjections
|
||||
export default class DesktopNotificationsService extends Service {
|
||||
@service currentUser;
|
||||
@service site;
|
||||
@service siteSettings;
|
||||
|
||||
@tracked notificationsDisabled;
|
||||
@tracked isEnabledPush;
|
||||
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
this.notificationsDisabled = keyValueStore.getItem(
|
||||
"notifications-disabled"
|
||||
);
|
||||
this.isEnabledPush = this.currentUser
|
||||
? pushNotificationKeyValueStore.getItem(
|
||||
pushNotificationUserSubscriptionKey(this.currentUser)
|
||||
)
|
||||
: false;
|
||||
}
|
||||
|
||||
get isNotSupported() {
|
||||
return typeof window.Notification === "undefined";
|
||||
}
|
||||
|
||||
get notificationsPermission() {
|
||||
return this.isNotSupported ? "" : Notification.permission;
|
||||
}
|
||||
|
||||
setNotificationsDisabled(value) {
|
||||
keyValueStore.setItem("notifications-disabled", value);
|
||||
this.notificationsDisabled = keyValueStore.getItem(
|
||||
"notifications-disabled"
|
||||
);
|
||||
}
|
||||
|
||||
get isDeniedPermission() {
|
||||
if (this.isNotSupported) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.notificationsPermission === "denied";
|
||||
}
|
||||
|
||||
get isGrantedPermission() {
|
||||
if (this.isNotSupported) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.notificationsPermission === "granted";
|
||||
}
|
||||
|
||||
get isEnabledDesktop() {
|
||||
if (this.isGrantedPermission) {
|
||||
return this.notificationsDisabled;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
setIsEnabledPush(value) {
|
||||
const user = this.currentUser;
|
||||
if (!user) {
|
||||
return false;
|
||||
}
|
||||
pushNotificationKeyValueStore.setItem(
|
||||
pushNotificationUserSubscriptionKey(user),
|
||||
value
|
||||
);
|
||||
this.isEnabledPush = pushNotificationKeyValueStore.getItem(
|
||||
pushNotificationUserSubscriptionKey(user)
|
||||
);
|
||||
}
|
||||
|
||||
get isEnabled() {
|
||||
return this.isEnabledDesktop || this.isEnabledPush;
|
||||
}
|
||||
|
||||
get isSubscribed() {
|
||||
if (!this.isEnabled) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.isPushNotificationsPreferred) {
|
||||
return this.isEnabledPush === "subscribed";
|
||||
} else {
|
||||
return this.notificationsDisabled === "";
|
||||
}
|
||||
}
|
||||
|
||||
get isPushNotificationsPreferred() {
|
||||
return (
|
||||
(this.site.mobileView ||
|
||||
this.siteSettings.enable_desktop_push_notifications) &&
|
||||
isPushNotificationsSupported()
|
||||
);
|
||||
}
|
||||
|
||||
@action
|
||||
disable() {
|
||||
if (this.isEnabledDesktop) {
|
||||
this.setNotificationsDisabled("disabled");
|
||||
}
|
||||
if (this.isEnabledPush) {
|
||||
unsubscribePushNotification(this.currentUser, () => {
|
||||
this.setIsEnabledPush("");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@action
|
||||
enable() {
|
||||
if (this.isPushNotificationsPreferred) {
|
||||
subscribePushNotification(() => {
|
||||
this.setIsEnabledPush("subscribed");
|
||||
}, this.siteSettings.vapid_public_key_bytes);
|
||||
} else {
|
||||
this.setNotificationsDisabled("");
|
||||
Notification.requestPermission(() => {
|
||||
confirmNotification(this.siteSettings);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user