diff --git a/app/assets/images/gear.svg b/app/assets/images/gear.svg new file mode 100644 index 000000000..197da4fd9 --- /dev/null +++ b/app/assets/images/gear.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/images/install-edge.svg b/app/assets/images/install-edge.svg new file mode 100644 index 000000000..0f1ec118a --- /dev/null +++ b/app/assets/images/install-edge.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/images/install.svg b/app/assets/images/install.svg new file mode 100644 index 000000000..82608c765 --- /dev/null +++ b/app/assets/images/install.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/images/lifebuoy.svg b/app/assets/images/lifebuoy.svg new file mode 100644 index 000000000..b26ca7307 --- /dev/null +++ b/app/assets/images/lifebuoy.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/images/sliders.svg b/app/assets/images/sliders.svg new file mode 100644 index 000000000..d84a39c1b --- /dev/null +++ b/app/assets/images/sliders.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/images/switch.svg b/app/assets/images/switch.svg new file mode 100644 index 000000000..2dc1f1232 --- /dev/null +++ b/app/assets/images/switch.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/stylesheets/icons.css b/app/assets/stylesheets/icons.css index 7b6b2f73a..2167c28bc 100644 --- a/app/assets/stylesheets/icons.css +++ b/app/assets/stylesheets/icons.css @@ -41,10 +41,15 @@ .icon--crown { --svg: url("crown.svg "); } .icon--email { --svg: url("email.svg "); } .icon--everyone { --svg: url("everyone.svg "); } + .icon--gear { --svg: url("gear.svg "); } .icon--filter { --svg: url("filter.svg "); } .icon--globe { --svg: url("globe.svg "); } .icon--golden-ticket { --svg: url("golden-ticket.svg "); } .icon--home { --svg: url("home.svg "); } + .icon--install { --svg: url("install.svg "); } + .icon--install { --svg: url("install.svg "); } + .icon--install-edge { --svg: url("install-edge.svg "); } + .icon--lifebuoy { --svg: url("lifebuoy.svg "); } .icon--lock { --svg: url("lock.svg "); } .icon--logout { --svg: url("logout.svg "); } .icon--menu { --svg: url("menu.svg "); } @@ -72,6 +77,8 @@ .icon--search { --svg: url("search.svg "); } .icon--settings { --svg: url("settings.svg "); } .icon--share { --svg: url("share.svg "); } + .icon--sliders { --svg: url("sliders.svg "); } + .icon--switch { --svg: url("switch.svg "); } .icon--tag { --svg: url("tag.svg "); } .icon--thumb-up { --svg: url("thumb-up.svg "); } .icon--trash { --svg: url("trash.svg "); } diff --git a/app/assets/stylesheets/notifications.css b/app/assets/stylesheets/notifications.css index e8659a268..7aac80d0b 100644 --- a/app/assets/stylesheets/notifications.css +++ b/app/assets/stylesheets/notifications.css @@ -44,5 +44,53 @@ display: none; } } + + + /* Help + /* ------------------------------------------------------------------------ */ + .notifications-help { + h2 { + font-size: var(--text-medium); + margin: 0; + } + + .icon { + --icon-size: 1.2em; + + vertical-align: text-top; + } + + ol { + margin-block: var(--block-space-half) var(--block-space); + + &:last-of-type { + margin-block-end: var(--block-space-half); + } + } + } + + .notifications-help__explainer { + padding: var(--block-space); + } + + .notifications__on-message { + display: none; + + .notifications--on & { + display: block; + } + } + + .notifications__off-message { + display: block; + + .notifications--on & { + display: none; + } + } + + .notifications__status { + --panel-padding: var(--block-space); + } } diff --git a/app/assets/stylesheets/pwa.css b/app/assets/stylesheets/pwa.css new file mode 100644 index 000000000..4f30941b0 --- /dev/null +++ b/app/assets/stylesheets/pwa.css @@ -0,0 +1,14 @@ +/* PWA install */ +.pwa__instructions { + @media (display-mode: standalone) { + display: none; + } +} + +.pwa__installer { + display: none; + + .pwa--can-install & { + display: block; + } +} \ No newline at end of file diff --git a/app/assets/stylesheets/utilities.css b/app/assets/stylesheets/utilities.css index 45cfd7d56..4661c391e 100644 --- a/app/assets/stylesheets/utilities.css +++ b/app/assets/stylesheets/utilities.css @@ -219,6 +219,18 @@ [hidden] { display: none !important; } [contents] { display: contents; } + .hide-in-pwa { + @media (display-mode: standalone) { + display: none; + } + } + + .hide-in-browser { + @media (display-mode: browser) { + display: none; + } + } + .hide-focus-ring { --focus-ring-size: 0; } diff --git a/app/javascript/controllers/notifications_controller.js b/app/javascript/controllers/notifications_controller.js index eff1f888d..11820ba86 100644 --- a/app/javascript/controllers/notifications_controller.js +++ b/app/javascript/controllers/notifications_controller.js @@ -1,14 +1,24 @@ import { Controller } from "@hotwired/stimulus" import { post } from "@rails/request.js" -import { pageIsTurboPreview } from "helpers/turbo_helpers" -import { onNextEventLoopTick } from "helpers/timing_helpers" export default class extends Controller { + static classes = [ "enabled" ] + static targets = [ "subscribeButton", "explainer" ] static values = { subscriptionsUrl: String } - - async connect() { - const state = await this.getCurrentState() - this.updateUI(state) + async connect() { + if (this.#allowed && Notification.permission == "default") { + this.subscribeButtonTarget.hidden = false + this.explainerTarget.hidden = true + } + + if (this.#allowed && Notification.permission == "granted") { + const registration = await this.#getServiceWorkerRegistration() + const subscription = await registration?.pushManager?.getSubscription() + + if (registration && subscription) { + this.element.classList.add(this.enabledClass) + } + } } async attemptToSubscribe() { @@ -20,8 +30,6 @@ export default class extends Controller { case "granted": { this.#subscribe(registration); break } case "default": { this.#requestPermissionAndSubscribe(registration) } } - } else { - console.log("Should display not-allowed notice") } } @@ -31,9 +39,6 @@ export default class extends Controller { const existingSubscription = await registration?.pushManager?.getSubscription() return Notification.permission == "granted" && registration && existingSubscription - } else { - console.log("Not alllowed") - return false } } @@ -59,7 +64,12 @@ export default class extends Controller { async #syncPushSubscription(subscription) { const response = await post(this.subscriptionsUrlValue, { body: this.#extractJsonPayloadAsString(subscription), responseKind: "turbo-stream" }) - if (!response.ok) subscription.unsubscribe() + if (response.ok) { + this.element.classList.add(this.enabledClass) + this.subscribeButtonTarget.hidden = true + } else { + subscription.unsubscribe() + } } async #requestPermissionAndSubscribe(registration) { @@ -91,35 +101,4 @@ export default class extends Controller { return outputArray } - - updateUI(state) { - console.log(state) - } - - async getCurrentState() { - if (!this.#allowed) { - return { status: 'not-supported' } - } - - const registration = await this.#getServiceWorkerRegistration() - const subscription = await registration?.pushManager?.getSubscription() - - return { - permission: Notification.permission, - hasRegistration: !!registration, - hasSubscription: !!subscription, - status: this.#determineStatus(Notification.permission, registration, subscription) - } - } - - #determineStatus(permission, registration, subscription) { - if (permission === "denied") return "permission-denied" - if (permission === "default") return "permission-not-requested" - if (permission === "granted") { - if (!registration) return "service-worker-missing" - if (!subscription) return "subscription-missing" - return "enabled" - } - return "unknown" - } } diff --git a/app/models/application_platform.rb b/app/models/application_platform.rb index c8c24a50b..500f4adc6 100644 --- a/app/models/application_platform.rb +++ b/app/models/application_platform.rb @@ -15,6 +15,14 @@ class ApplicationPlatform < PlatformAgent user_agent.browser.match? /Chrome/ end + def edge? + user_agent.browser.match? /Edg/ + end + + def firefox? + user_agent.browser.match? /Firefox|FxiOS/ + end + def safari? user_agent.browser.match? /Safari/ end @@ -26,4 +34,21 @@ class ApplicationPlatform < PlatformAgent def desktop? !mobile? end + + def windows? + operating_system == "Windows" + end + + def operating_system + case user_agent.platform + when /Android/ then "Android" + when /iPad/ then "iPad" + when /iPhone/ then "iPhone" + when /Macintosh/ then "macOS" + when /Windows/ then "Windows" + when /CrOS/ then "ChromeOS" + else + os =~ /Linux/ ? "Linux" : os + end + end end diff --git a/app/views/notifications/settings/_browser.html.erb b/app/views/notifications/settings/_browser.html.erb new file mode 100644 index 000000000..4662c558b --- /dev/null +++ b/app/views/notifications/settings/_browser.html.erb @@ -0,0 +1,109 @@ +<% unless (platform.safari? || platform.chrome?) && platform.ios? %> +
+ <% case + when platform.firefox? && platform.android? %> +

Turn on notifications for <%= platform.browser.capitalize %>.

+
    +
  1. Tap <%= icon_tag "lock", alt: "the View site information button" %> in the address bar.
  2. +
  3. Tap Notification to change to Allowed.
  4. +
+ <% when platform.edge? && platform.desktop? %> +

Turn on notifications for this website.

+
    +
  1. Click <%= icon_tag "lock", alt: "the View site information button" %> left of the address bar.
  2. +
  3. Under Permissions for this site > Notifications, choose Allow.
  4. +
+

Turn on notifications for <%= platform.browser.capitalize %>.

+
    + <% if platform.windows? %> +
  1. Click Start, then Settings.
  2. +
  3. Go to System > Notification.
  4. +
  5. Click <%= icon_tag "switch", alt: "the switch" %> ON for <%= platform.browser.capitalize %>.
  6. + <% else %> +
  7. Click in the top left.
  8. +
  9. Click System Settings….
  10. +
  11. Click Notifications.
  12. +
  13. Click <%= platform.browser.capitalize %>.
  14. +
  15. Click <%= icon_tag "switch", alt: "the switch" %> to Allow notifications.
  16. + <% end %> +
+ <% when platform.firefox? && platform.desktop? %> +

Turn on notifications for this website.

+
    +
  1. Click <%= platform.browser.capitalize %> in the top left.
  2. +
  3. Click Settings….
  4. +
  5. Click Privacy & Security in the sidebar.
  6. +
  7. Scroll down to Permissions.
  8. +
  9. Click Settings next to Notifications.
  10. +
  11. Select Allow next to <%= root_url %>.
  12. +
+ +

Turn on notifications for <%= platform.browser.capitalize %>.

+
    + <% if platform.windows? %> +
  1. Click Start, then Settings.
  2. +
  3. Go to System > Notification.
  4. +
  5. Click <%= icon_tag "switch", alt: "the toggle button" %> ON for <%= platform.browser.capitalize %>.
  6. + <% else %> +
  7. Click in the top left.
  8. +
  9. Click System Settings….
  10. +
  11. Click Notifications.
  12. +
  13. Click <%= platform.browser.capitalize %>.
  14. +
  15. Click <%= icon_tag "switch", alt: "the switch" %> to Allow notifications.
  16. + <% end %> +
+ <% when platform.chrome? && platform.desktop? %> +

Turn on notifications for this website.

+
    +
  1. Click the <%= icon_tag "sliders", alt: "View site information" %> icon in the address bar.
  2. +
  3. Click Site Settings.
  4. +
  5. Ensure notifications are Allowed.
  6. +
+ +

Turn on notifications for <%= platform.browser.capitalize %>.

+
    + <% if platform.windows? %> +
  1. Click Start, then Settings.
  2. +
  3. Go to System > Notification.
  4. +
  5. Click <%= icon_tag "switch", alt: "the switch" %> ON for <%= platform.browser.capitalize %>.
  6. + <% else %> +
  7. Click in the top left.
  8. +
  9. Click System Settings….
  10. +
  11. Click Notifications.
  12. +
  13. Click <%= platform.browser.capitalize %>.
  14. +
  15. Click <%= icon_tag "switch", alt: "the switch" %> to Allow notifications.
  16. + <% end %> +
+ <% when platform.chrome? && platform.android? %> +

Turn on notifications for <%= platform.browser.capitalize %>.

+
    +
  1. Tap the <%= icon_tag "menu-dots-vertical", alt: "More options" %> menu button.
  2. +
  3. Tap Settings.
  4. +
  5. Tap Notifications.
  6. +
  7. Tap <%= icon_tag "switch", alt: "the switch" %> to Allow <%= platform.browser.capitalize %> notifications.
  8. +
  9. Tap <%= icon_tag "switch", alt: "the switch" %> next to Web apps.
  10. +
  11. Tap <%= icon_tag "notification-bell-alert", alt: "the notification bell" %> and select Allow.
  12. +
+ <% when platform.safari? && platform.desktop? %> +

Turn on notifications for this website.

+
    +
  1. Click in the top left.
  2. +
  3. Click System Settings….
  4. +
  5. Click Notifications.
  6. +
  7. Click <%= request.base_url %> in the list.
  8. +
  9. Click <%= icon_tag "switch", alt: "the switch" %> to Allow notifications.
  10. +
+

Turn on notifications for <%= platform.browser.capitalize %>.

+
    +
  1. Click <%= platform.browser.capitalize %> in the top left.
  2. +
  3. Click Settings….
  4. +
  5. Click the Websites tab.
  6. +
  7. Click Notifications in the sidebar.
  8. +
  9. Click <%= request.base_url %> in the list.
  10. +
  11. Select Allow.
  12. +
+ <% else %> +

Ensure notifications are enabled for <%= root_url %> in your web browser settings.

+ <% end %> +
+<% end %> diff --git a/app/views/notifications/settings/_install.html.erb b/app/views/notifications/settings/_install.html.erb new file mode 100644 index 000000000..f8d664043 --- /dev/null +++ b/app/views/notifications/settings/_install.html.erb @@ -0,0 +1,35 @@ +<% unless (platform.chrome? && !platform.ios?) || (platform.firefox? && !platform.android?) %> +
+

<%= platform.safari? && platform.desktop? ? "…or install" : "Install " -%> Fizzy as a web app.

+ <% case + when platform.edge? %> +
    +
  1. Click <%= icon_tag "install-edge", alt: "the app available - install Fizzy button" %>in the address bar.
  2. +
  3. Click Install.
  4. +
+ <% when platform.chrome? && platform.android? %> +
    +
  1. Tap the <%= icon_tag "menu-dots-vertical", alt: "More options" %> menu button.
  2. +
  3. Tap Install app in the menu.
  4. +
+ <% when platform.firefox? && platform.android? %> +
    +
  1. Tap the <%= icon_tag "menu-dots-vertical", alt: "More options" %> menu button.
  2. +
  3. Tap Install in the menu.
  4. +
+ <% when platform.safari? && platform.desktop? %> +
    +
  1. Click File in the top left.
  2. +
  3. Click Add to Dock….
  4. +
+ <% when (platform.safari? || platform.chrome?) && platform.ios? %> +

To receive push notifications in <%= platform.browser.capitalize %> for <%= platform.operating_system %>, you must first install Fizzy as a web app.

+
    +
  1. Tap <%= icon_tag "share", alt: "the share button" %>
  2. +
  3. Tap Add to Home Screen.
  4. +
+ <% else %> +

Some platforms require you to install Fizzy as a web app to receive push notifications.

+ <% end %> +
+<% end %> diff --git a/app/views/notifications/settings/_system.html.erb b/app/views/notifications/settings/_system.html.erb new file mode 100644 index 000000000..afe0efd45 --- /dev/null +++ b/app/views/notifications/settings/_system.html.erb @@ -0,0 +1,57 @@ +
+

Check your <%= platform.operating_system %> settings

+ <% case + when platform.firefox? && platform.android? %> +
    +
  1. Tap the <%= icon_tag "menu-dots-vertical.svg", alt: "More options" %> menu button.
  2. +
  3. Tap Settings.
  4. +
  5. Tap Notifications.
  6. +
  7. Tap <%= icon_tag "switch", alt: "the toggle button" %> to Allow <%= platform.browser.capitalize %> notifications.
  8. +
+ <% when platform.edge? && platform.desktop? %> +
    +
  1. Click Start, then Settings.
  2. +
  3. Go to System > Notification.
  4. +
  5. Click <%= icon_tag "switch", alt: "the toggle button" %> ON for Fizzy.
  6. +
+ <% when (platform.firefox? || platform.chrome?) && platform.desktop? %> +
    + <% if platform.windows? %> +
  1. Click Start, then Settings.
  2. +
  3. Go to System > Notification.
  4. +
  5. Click <%= icon_tag "switch", alt: "the toggle button" %> ON for Fizzy.
  6. + <% else %> +
  7. Click in the top left.
  8. +
  9. Click System Settings….
  10. +
  11. Click Notifications.
  12. +
  13. Click Fizzy.
  14. +
  15. Click <%= icon_tag "switch", alt: "the allow notifications switch" %> to Allow notifications.
  16. + <% end %> +
+ <% when platform.safari? && platform.desktop? %> +
    +
  1. Click in the top left.
  2. +
  3. Click System Settings….
  4. +
  5. Click Notifications.
  6. +
  7. Click Fizzy.
  8. +
  9. Click <%= icon_tag "switch", alt: "the allow notifications switch" %> to Allow notifications.
  10. +
+ <% when (platform.safari? || platform.chrome?) && platform.ios? %> +
    +
  1. Open the <%= icon_tag "gear", aria: { hidden: "true" } %> Settings app.
  2. +
  3. Scroll to and tap Fizzy.
  4. +
  5. Tap Notifications.
  6. +
  7. Tap <%= icon_tag "switch", alt: "the allow notifications switch button" %> to Allow Notifications.
  8. +
+ <% when platform.chrome? && platform.android? %> +
    +
  1. Open the <%= icon_tag "gear", aria: { hidden: "true" } %> Settings app.
  2. +
  3. Tap Notifications.
  4. +
  5. Tap App notifications.
  6. +
  7. Scroll to Fizzy.
  8. +
  9. Tap <%= icon_tag "switch", alt: "the switch" %> to Allow Notifications.
  10. +
+ <% else %> +

Ensure notifications are allowed for <%= platform.browser.capitalize %> in your system settings.

+ <% end %> +
diff --git a/app/views/notifications/settings/show.html.erb b/app/views/notifications/settings/show.html.erb index 36288fa89..74dd03731 100644 --- a/app/views/notifications/settings/show.html.erb +++ b/app/views/notifications/settings/show.html.erb @@ -12,16 +12,34 @@ <% end %> -
-
- - - +
+

Push notifications are ON

+

Push notifications are OFF

+ + +
+ + <%= icon_tag "lifebuoy" %> + Help me fix this + Not receiving notifications? + + +
+

When push notifications aren’t working, this can usually be fixed by checking your notification settings to make sure they’re allowed.

+ <%= render partial: "notifications/settings/browser" %> + <%= render partial: "notifications/settings/system" %> + <%= render partial: "notifications/settings/install" %> +
+
+
+ +

Collections

<%= render partial: "notifications/settings/collection", collection: @collections, locals: { user: Current.user } %>