Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ gem "tailwindcss-rails", "~> 2.6"

# Hotwire
gem "stimulus-rails"
gem "turbo-rails"
gem "turbo-rails", github: "rosa/turbo-rails", branch: "offline-cache"

# Deployment
gem "kamal", require: false
Expand Down
15 changes: 10 additions & 5 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
GIT
remote: https://github.com/rosa/turbo-rails.git
revision: 25538ece2934237200c36e5ef49cff932463aed9
branch: offline-cache
specs:
turbo-rails (2.0.16)
actionpack (>= 7.1.0)
railties (>= 7.1.0)

GIT
remote: https://github.com/ruby/net-pop.git
revision: e8d0afe2773b9eb6a23c39e9e437f6fc0fc7c733
Expand Down Expand Up @@ -622,10 +631,6 @@ GEM
timeliness (0.5.2)
timeout (0.4.3)
tty-which (0.5.0)
turbo-rails (2.0.6)
actionpack (>= 6.0.0)
activejob (>= 6.0.0)
railties (>= 6.0.0)
turbo_power (0.7.0)
turbo-rails (>= 1.3.0)
tzinfo (2.0.6)
Expand Down Expand Up @@ -738,7 +743,7 @@ DEPENDENCIES
stimulus-rails
tailwindcss-rails (~> 2.6)
timecop
turbo-rails
turbo-rails!
tzinfo-data
validate_url
validates_timeliness (~> 8.0)
Expand Down
3 changes: 0 additions & 3 deletions app/controllers/service_worker_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,4 @@ def service_worker

def manifest
end

def offline
end
end
8 changes: 7 additions & 1 deletion app/javascript/application.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
// Configure your import map in config/importmap.rb. Read more: https://github.com/rails/importmap-rails
import '@hotwired/turbo-rails'
import { Turbo } from '@hotwired/turbo-rails'
import 'controllers'
import 'custom/companion'
import 'trix'
import '@rails/actiontext'

Turbo.offline.start('/service-worker.js', {
scope: '/',
type: 'classic',
native: true
})
47 changes: 47 additions & 0 deletions app/javascript/controllers/offline_banner_controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { Controller } from '@hotwired/stimulus'

export default class extends Controller {
static targets = ['banner']

connect () {
this.handleOnlineStatus = this.handleOnlineStatus.bind(this)

window.addEventListener('online', this.handleOnlineStatus)
window.addEventListener('offline', this.handleOnlineStatus)

this.handleOnlineStatus()
}

disconnect () {
window.removeEventListener('online', this.handleOnlineStatus)
window.removeEventListener('offline', this.handleOnlineStatus)
}

handleOnlineStatus () {
if (navigator.onLine) {
this.hideBanner()
} else {
this.showBanner()
}
}

showBanner () {
this.bannerTarget.classList.remove('hidden', '-translate-y-full')
this.bannerTarget.classList.add('translate-y-0')
}

hideBanner () {
this.bannerTarget.classList.remove('translate-y-0')
this.bannerTarget.classList.add('-translate-y-full')

setTimeout(() => {
if (navigator.onLine) {
this.bannerTarget.classList.add('hidden')
}
}, 300)
}

dismiss () {
this.hideBanner()
}
}
29 changes: 29 additions & 0 deletions app/views/layouts/_offline_banner.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<div
data-controller="offline-banner"
data-offline-banner-target="banner"
class="fixed top-0 left-0 right-0 z-50 bg-amber-500 text-amber-900 px-4 py-3 shadow-lg transform -translate-y-full transition-transform duration-300 ease-in-out hidden">
<div class="flex items-center justify-between max-w-7xl mx-auto">
<div class="flex items-center space-x-3">
<svg class="w-5 h-5 text-amber-700" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L3.732 16.5c-.77.833.192 2.5 1.732 2.5z" />
</svg>
<div class="flex-1">
<p class="text-sm font-medium">
You're currently offline
</p>
<p class="text-xs text-amber-800">
The app may not work properly until your connection is restored.
</p>
</div>
</div>

<button
data-action="click->offline-banner#dismiss"
class="text-amber-700 hover:text-amber-900 focus:outline-none focus:text-amber-900 transition-colors duration-200"
aria-label="Dismiss offline notification">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
</div>
7 changes: 5 additions & 2 deletions app/views/layouts/application.html.erb
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
<!DOCTYPE html>
<html class="h-screen <%= resolved_theme_class %>">
<head>
<title><%= page_title %></title>
<head>
<title><%= page_title %></title>

<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no,viewport-fit=cover">
<meta name="turbo-refresh-scroll" content="preserve">
<meta name="turbo-refresh-method" content="morph">
<meta name="view-transition" content="same-origin">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="turbo-prefetch" content="false">

<link rel="apple-touch-icon" href="<%= image_path "homescreen_icon.png" %>">
<link rel="manifest" crossorigin="use-credentials" href="/manifest.json">
Expand Down Expand Up @@ -48,6 +49,8 @@
data-web-push-notifications-vapid-key-value=#{vapid_public_key}
data-web-push-notifications-notifications-enabled-value=#{current_profile.web_push_notifications}" : '' %>>

<%= render 'layouts/offline_banner' %>

<div class="fixed top-0 z-40 w-full">
<%= yield :top_nav %>
</div>
Expand Down
11 changes: 0 additions & 11 deletions app/views/service_worker/offline.html.erb

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
importScripts(
'https://storage.googleapis.com/workbox-cdn/releases/6.4.1/workbox-sw.js'
)
importScripts("<%= javascript_url('turbo-offline-umd.js') %>")

// ------------- Push Notifications -------------

self.addEventListener('push', async (event) => {
let data
try {
Expand Down Expand Up @@ -48,50 +48,14 @@ self.addEventListener('notificationclick', function (event) {
)
})

// ------------- Request handling -------------

const { CacheFirst, NetworkFirst } = workbox.strategies
const { registerRoute } = workbox.routing

// For assets (scripts and images), cache first
registerRoute(
({ request }) => request.destination === 'script' ||
request.destination === 'style',
new CacheFirst({
cacheName: 'assets-styles-and-scripts'
})
)

registerRoute(
({ request }) => request.destination === 'image',
new CacheFirst({
cacheName: 'assets-images'
// ------------- Turbo Offline -------------
TurboOffline.addRule({
match: /.*/,
handler: TurboOffline.handlers.networkFirst({
cacheName: "general",
maxAge: 60 * 60 * 24 * 7,
networkTimeout: 1
})
)

// For pages, network first
registerRoute(
({ request, url }) => request.destination === 'document' ||
request.destination === '',
new NetworkFirst()
)

// Offline fallback

const { warmStrategyCache } = workbox.recipes
const { setCatchHandler } = workbox.routing
const strategy = new NetworkFirst()
const urls = ['/offline.html']

// Warm the runtime cache with a list of asset URLs
warmStrategyCache({ urls, strategy })

// Trigger a 'catch' handler when any of the other routes fail to generate a response
setCatchHandler(async ({ event }) => {
switch (event.request.destination) {
case 'document':
return strategy.handle({ event, request: urls[0] })
default:
return Response.error()
}
})

TurboOffline.start()
3 changes: 2 additions & 1 deletion config/importmap.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# Pin npm packages by running ./bin/importmap

pin "application"
pin "@hotwired/turbo-rails", to: "turbo.min.js"
pin "@hotwired/turbo-rails", to: "turbo.min.js", preload: true
pin "@hotwired/turbo/offline", to: "turbo-offline-umd.js", preload: true
pin "@hotwired/stimulus", to: "@hotwired--stimulus.js" # @3.2.2
pin "@hotwired/stimulus-loading", to: "stimulus-loading.js"
pin_all_from "app/javascript/controllers", under: "controllers"
Expand Down
Loading