This commit is contained in:
Dan Elbert 2018-04-17 18:38:48 -05:00
parent 26b4401450
commit fcf191e355
9 changed files with 118 additions and 2 deletions

View File

@ -1,5 +1,7 @@
class HomeController < ApplicationController class HomeController < ApplicationController
skip_forgery_protection
def index def index
render layout: false render layout: false
end end

View File

@ -13,6 +13,7 @@
</div> </div>
<div class="navbar-menu" :class="{ 'is-active': menuActive}"> <div class="navbar-menu" :class="{ 'is-active': menuActive}">
<div class="navbar-start"> <div class="navbar-start">
<a v-if="updateAvailable" href="#" @click.prevent="updateApp">UPDATE AVAILABLE!</a>
<router-link to="/" class="navbar-item">Recipes</router-link> <router-link to="/" class="navbar-item">Recipes</router-link>
<router-link to="/ingredients" class="navbar-item">Ingredients</router-link> <router-link to="/ingredients" class="navbar-item">Ingredients</router-link>
<router-link to="/calculator" class="navbar-item">Calculator</router-link> <router-link to="/calculator" class="navbar-item">Calculator</router-link>
@ -50,6 +51,7 @@
import UserLogin from "./UserLogin"; import UserLogin from "./UserLogin";
import { mapState } from "vuex"; import { mapState } from "vuex";
import { swUpdate } from "../lib/ServiceWorker";
export default { export default {
data() { data() {
@ -61,10 +63,17 @@
computed: { computed: {
...mapState([ ...mapState([
'route', 'route',
'user' 'user',
'updateAvailable'
]) ])
}, },
methods: {
updateApp() {
swUpdate();
}
},
watch: { watch: {
route() { route() {
this.menuActive = false; this.menuActive = false;

View File

@ -1,6 +1,6 @@
<template> <template>
<div> <div>
<h1 class="title">Recipes</h1> <h1 class="title">Recipes 2</h1>
<router-link v-if="isLoggedIn" :to="{name: 'new_recipe'}" class="button is-primary">Create Recipe</router-link> <router-link v-if="isLoggedIn" :to="{name: 'new_recipe'}" class="button is-primary">Create Recipe</router-link>

View File

@ -0,0 +1,49 @@
function trackInstall(worker, cb) {
worker.addEventListener('statechange', function() {
//If the worker is now installed, let the user know that there is an update ready
if (worker.state == 'installed') {
cb();
}
});
}
export function swUpdate() {
navigator.serviceWorker.getRegistration().then(reg => {
if (reg && reg.waiting) {
reg.waiting.postMessage("skipWaiting");
window.location.reload(true);
}
});
}
export function swInit(store) {
const updateReady = () => store.commit("setUpdateAvailable", true);
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js')
.then(function (reg) {
console.log('Registration succeeded. Scope is ' + reg.scope);
if (reg.waiting) {
updateReady();
}
// If there's an updated worker installing, track its progress. If it becomes "installed", call
// indexController._updateReady()
if (reg.installing) {
trackInstall(reg.installing, updateReady);
}
reg.addEventListener('updatefound', function () {
trackInstall(reg.installing, updateReady);
});
}).catch(function (error) {
console.log('Registration failed with ' + error);
});
}
}

View File

@ -2,6 +2,7 @@ import '../styles';
import Vue from 'vue' import Vue from 'vue'
import { sync } from 'vuex-router-sync'; import { sync } from 'vuex-router-sync';
import { swInit } from "../lib/ServiceWorker";
import VueProgressBar from "vue-progressbar"; import VueProgressBar from "vue-progressbar";
import config from '../config'; import config from '../config';
import store from '../store'; import store from '../store';
@ -47,6 +48,7 @@ Vue.use(VueProgressBar, {
}); });
sync(store, router); sync(store, router);
swInit(store);
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {

View File

@ -8,6 +8,7 @@ Vue.use(Vuex);
export default new Vuex.Store({ export default new Vuex.Store({
strict: process.env.NODE_ENV !== 'production', strict: process.env.NODE_ENV !== 'production',
state: { state: {
updateAvailable: false,
loading: false, loading: false,
error: null, error: null,
authChecked: false, authChecked: false,
@ -38,6 +39,10 @@ export default new Vuex.Store({
} }
}, },
mutations: { mutations: {
setUpdateAvailable(state, value) {
state.updateAvailable = value;
},
setLoading(state, value) { setLoading(state, value) {
state.loading = value; state.loading = value;
}, },

View File

@ -5,6 +5,10 @@
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="manifest" href="/manifest.json"> <link rel="manifest" href="/manifest.json">
<script type="text/javascript">
</script>
<title>Parsley</title> <title>Parsley</title>
<%= stylesheet_pack_tag 'application' %> <%= stylesheet_pack_tag 'application' %>

44
app/views/home/sw.js.erb Normal file
View File

@ -0,0 +1,44 @@
var cacheName = "parsley-cache-<%= File.mtime(Webpacker::manifest.config.public_manifest_path).to_i %>";
var staticAssets = [
"/",
"<%= asset_pack_path("application.js") %>",
"<%= asset_pack_path("application.css") %>"
];
self.addEventListener('install', function(event) {
event.waitUntil(
caches.open(cacheName).then(function (cache) {
console.log('[ServiceWorker] Caching app shell');
return cache.addAll(staticAssets);
})
);
});
self.addEventListener('activate', function(event) {
event.waitUntil(
caches.keys().then(function (keyList) {
return Promise.all(keyList.map(function (key) {
if (key !== cacheName) {
console.log('[ServiceWorker] Removing old cache', key);
return caches.delete(key);
}
}));
})
);
});
self.addEventListener('fetch', function(event) {
event.respondWith(
caches.match(event.request).then(function (response) {
return response || fetch(event.request);
})
);
});
self.addEventListener('message', function (event) {
if (event.data === "skipWaiting") {
self.skipWaiting();
}
});

View File

@ -52,6 +52,7 @@ Rails.application.routes.draw do
resources :users, except: [:new, :create] resources :users, except: [:new, :create]
end end
get 'sw.js' => 'home#sw'
root 'home#index' root 'home#index'