diff --git a/.gitignore b/.gitignore
index 789f14aecd..e833f8dbd2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,4 +15,4 @@ yarn-error.log
public/google*.html
report.html
composer.phar
-app.js.map
+app.js.map
\ No newline at end of file
diff --git a/frontend/package.json b/frontend/package.json
index ed40078817..da2c1d26f8 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -17,13 +17,13 @@
"lodash.clonedeep": "^4.5.0",
"postcss": "^8.1.14",
"resolve-url-loader": "^4.0.0",
- "sass": "^1.39.0",
+ "sass": "^1.39.2",
"sass-loader": "^12.0.0",
"vue-i18n": "^8.24.2",
"vue-loader": "^15",
"vue-template-compiler": "^2.6.12",
"vuex": "^3.6.2",
- "webpack": "^5.52.0"
+ "webpack": "^5.52.1"
},
"dependencies": {
"@fortawesome/fontawesome-free": "^5.15.3",
diff --git a/frontend/src/serviceworker.js b/frontend/src/serviceworker.js
new file mode 100644
index 0000000000..dda3b1111b
--- /dev/null
+++ b/frontend/src/serviceworker.js
@@ -0,0 +1,58 @@
+/*
+ * serviceworker.js
+ * Copyright (c) 2021 Lorenzo Breda (https://github.com/lbreda)
+ *
+ * This file is part of Firefly III (https://github.com/firefly-iii).
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+let staticCachePrefix = "firefly-III-"
+let staticCacheName = staticCachePrefix + new Date().getTime();
+let cachedFiles = [
+ '/offline',
+ '/v2/plugins/local-fonts/gf-source.css',
+ '/v2/css/app.css',
+];
+
+// Create cache on install
+self.addEventListener("install", event => {
+ this.skipWaiting();
+ event.waitUntil(
+ caches.open(staticCacheName).then(cache => cache.addAll(cachedFiles))
+ )
+});
+
+// Clear cache on activate
+self.addEventListener('activate', event => {
+ event.waitUntil(
+ caches.keys().then(cacheNames => {
+ return Promise.all(
+ cacheNames
+ .filter(cacheName => (cacheName.startsWith(staticCachePrefix)))
+ .filter(cacheName => (cacheName !== staticCacheName))
+ .map(cacheName => caches.delete(cacheName))
+ );
+ })
+ );
+});
+
+// Serve from Cache or return the offline page
+self.addEventListener("fetch", event => {
+ event.respondWith(
+ caches.match(event.request)
+ .then(response => (response || fetch(event.request)))
+ .catch(() => caches.match('offline'))
+ )
+});
diff --git a/frontend/yarn.lock b/frontend/yarn.lock
index e8498e320d..66a01bc5a1 100644
--- a/frontend/yarn.lock
+++ b/frontend/yarn.lock
@@ -1406,10 +1406,10 @@ ansi-escapes@^4.3.1:
dependencies:
type-fest "^0.21.3"
-ansi-html@^0.0.7:
- version "0.0.7"
- resolved "https://registry.yarnpkg.com/ansi-html/-/ansi-html-0.0.7.tgz#813584021962a9e9e6fd039f940d12f56ca7859e"
- integrity sha1-gTWEAhliqenm/QOflA0S9WynhZ4=
+ansi-html-community@^0.0.8:
+ version "0.0.8"
+ resolved "https://registry.yarnpkg.com/ansi-html-community/-/ansi-html-community-0.0.8.tgz#69fbc4d6ccbe383f9736934ae34c3f8290f1bf41"
+ integrity sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==
ansi-regex@^5.0.0:
version "5.0.0"
@@ -1528,9 +1528,9 @@ axios-cache-adapter@^2.7.3:
md5 "^2.2.1"
axios@^0.21:
- version "0.21.3"
- resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.3.tgz#f85d9b747f9b66d59ca463605cedf1844872b82e"
- integrity sha512-JtoZ3Ndke/+Iwt5n+BgSli/3idTvpt5OjKyoCmz4LX5+lPiY5l7C1colYezhlxThjNa/NhngCUWZSZFypIFuaA==
+ version "0.21.4"
+ resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575"
+ integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==
dependencies:
follow-redirects "^1.14.0"
@@ -4196,9 +4196,9 @@ klona@^2.0.4:
integrity sha512-ZRbnvdg/NxqzC7L9Uyqzf4psi1OM4Cuc+sJAkQPjO6XkQIJTNbfK2Rsmbw8fx1p2mkZdp2FZYo2+LwXYY/uwIA==
laravel-mix@^6:
- version "6.0.29"
- resolved "https://registry.yarnpkg.com/laravel-mix/-/laravel-mix-6.0.29.tgz#4b07b731f3d3de624d19e392a2bd93ca741a5b69"
- integrity sha512-GGDpeicvHYh6J6uickr1ZiDtJdNuKsQUjWrthB4MTaN0ZzxL0kLxpNXIRHGhpoEHM+2Tl/tA40ATIDAAumCyow==
+ version "6.0.31"
+ resolved "https://registry.yarnpkg.com/laravel-mix/-/laravel-mix-6.0.31.tgz#c33b869d11549e781484c52f11b12405cecc72a1"
+ integrity sha512-T9uFNNARS5hXl5JggCkLKybwAnyYEHBXzPseC0yJ/6EVK7eyvPOq2UAGDVqhfYTZKxrMd5B5ww1kEooDRoH+OA==
dependencies:
"@babel/core" "^7.14.5"
"@babel/plugin-proposal-object-rest-spread" "^7.14.5"
@@ -4245,7 +4245,7 @@ laravel-mix@^6:
vue-style-loader "^4.1.3"
webpack "^5.38.1"
webpack-cli "^4.7.2"
- webpack-dev-server "4.0.0-rc.1"
+ webpack-dev-server "4.1.1"
webpack-merge "^5.8.0"
webpack-notifier "^1.13.0"
webpackbar "^5.0.0-3"
@@ -5698,10 +5698,10 @@ sass-loader@^12.0.0:
klona "^2.0.4"
neo-async "^2.6.2"
-sass@^1.39.0:
- version "1.39.0"
- resolved "https://registry.yarnpkg.com/sass/-/sass-1.39.0.tgz#6c64695d1c437767c8f1a4e471288e831f81d035"
- integrity sha512-F4o+RhJkNOIG0b6QudYU8c78ZADKZjKDk5cyrf8XTKWfrgbtyVVXImFstJrc+1pkQDCggyidIOytq6gS4gCCZg==
+sass@^1.39.2:
+ version "1.39.2"
+ resolved "https://registry.yarnpkg.com/sass/-/sass-1.39.2.tgz#1681964378f58d76fc64a6a502619bd5ac99f660"
+ integrity sha512-4/6Vn2RPc+qNwSclUSKvssh7dqK1Ih3FfHBW16I/GfH47b3scbYeOw65UIrYG7PkweFiKbpJjgkf5CV8EMmvzw==
dependencies:
chokidar ">=3.0.0 <4.0.0"
@@ -6596,12 +6596,12 @@ webpack-dev-middleware@^5.0.0:
range-parser "^1.2.1"
schema-utils "^3.0.0"
-webpack-dev-server@4.0.0-rc.1:
- version "4.0.0-rc.1"
- resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.0.0-rc.1.tgz#4826530cdff3ebe56d3a5e0fa3e7d1e006b40d33"
- integrity sha512-gZlGe0CMA0YZ5bIXFbtSegd33tYsUujYv+rgJu9Y75xHvXBSXFJiBvakMV7yTkBE+k8dgz4VsBzl7J5I5xatyg==
+webpack-dev-server@4.1.1:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.1.1.tgz#e8eb8f0ce1a0e1fa65e234641763c97735398bed"
+ integrity sha512-Kl1mnCEw8Cy1Kw173gCxLIB242LfPKEOj9WoKhKz/MbryZTNrILzOJTk8kiczw/YUEPzn3gcltCQv6hDsLudRg==
dependencies:
- ansi-html "^0.0.7"
+ ansi-html-community "^0.0.8"
bonjour "^3.5.0"
chokidar "^3.5.1"
colorette "^1.2.2"
@@ -6656,10 +6656,10 @@ webpack-sources@^3.2.0:
resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.0.tgz#b16973bcf844ebcdb3afde32eda1c04d0b90f89d"
integrity sha512-fahN08Et7P9trej8xz/Z7eRu8ltyiygEo/hnRi9KqBUs80KeDcnf96ZJo++ewWd84fEf3xSX9bp4ZS9hbw0OBw==
-webpack@^5.38.1, webpack@^5.52.0:
- version "5.52.0"
- resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.52.0.tgz#88d997c2c3ebb62abcaa453d2a26e0fd917c71a3"
- integrity sha512-yRZOat8jWGwBwHpco3uKQhVU7HYaNunZiJ4AkAVQkPCUGoZk/tiIXiwG+8HIy/F+qsiZvSOa+GLQOj3q5RKRYg==
+webpack@^5.38.1, webpack@^5.52.1:
+ version "5.52.1"
+ resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.52.1.tgz#2dc1d9029ecb7acfb80da7bf67baab67baa517a7"
+ integrity sha512-wkGb0hLfrS7ML3n2xIKfUIwHbjB6gxwQHyLmVHoAqEQBw+nWo+G6LoHL098FEXqahqximsntjBLuewStrnJk0g==
dependencies:
"@types/eslint-scope" "^3.7.0"
"@types/estree" "^0.0.50"
diff --git a/package.json b/package.json
index 95b9c0e1e4..2f25de1d18 100644
--- a/package.json
+++ b/package.json
@@ -10,7 +10,7 @@
},
"devDependencies": {
"@johmun/vue-tags-input": "^2",
- "@vue/compiler-sfc": "^3.2.9",
+ "@vue/compiler-sfc": "^3.2.11",
"axios": "^0.21",
"bootstrap-sass": "^3",
"cross-env": "^7.0",
diff --git a/public/manifest.webmanifest b/public/manifest.webmanifest
index cb44fea0e3..cf49fb98e2 100644
--- a/public/manifest.webmanifest
+++ b/public/manifest.webmanifest
@@ -3,15 +3,83 @@
"short_name": "Firefly III",
"start_url": "/",
"icons": [
+ {
+ "src": "/maskable72.png",
+ "sizes": "72x72",
+ "type": "image/png",
+ "scope": "maskable"
+ },
+ {
+ "src": "/maskable76.png",
+ "sizes": "76x76",
+ "type": "image/png",
+ "scope": "maskable"
+ },
+ {
+ "src": "/maskable96.png",
+ "sizes": "96x96",
+ "type": "image/png",
+ "scope": "maskable"
+ },
+ {
+ "src": "/maskable120.png",
+ "sizes": "120x120",
+ "type": "image/png",
+ "scope": "maskable"
+ },
+ {
+ "src": "/maskable128.png",
+ "sizes": "128x128",
+ "type": "image/png",
+ "scope": "maskable"
+ },
+ {
+ "src": "/maskable144.png",
+ "sizes": "144x144",
+ "type": "image/png",
+ "scope": "maskable"
+ },
+ {
+ "src": "/maskable152.png",
+ "sizes": "152x152",
+ "type": "image/png",
+ "scope": "maskable"
+ },
+ {
+ "src": "/maskable180.png",
+ "sizes": "180x180",
+ "type": "image/png",
+ "scope": "maskable"
+ },
{
"src": "/android-chrome-192x192.png",
"sizes": "192x192",
- "type": "image/png"
+ "type": "image/png",
+ "scope": "any"
+ },
+ {
+ "src": "/maskable192.png",
+ "sizes": "192x192",
+ "type": "image/png",
+ "scope": "maskable"
+ },
+ {
+ "src": "/maskable384.png",
+ "sizes": "384x384",
+ "type": "image/png",
+ "scope": "maskable"
},
{
"src": "/android-chrome-512x512.png",
"sizes": "512x512",
- "type": "image/png"
+ "type": "image/png",
+ "scope": "any"
+ },
+ {
+ "src": "/maskable512.png",
+ "sizes": "512x512",
+ "type": "image/png",
+ "scope": "maskable"
}
],
"theme_color": "#1e6581",
diff --git a/public/maskable-icon.svg b/public/maskable-icon.svg
new file mode 100644
index 0000000000..6eb3ecc6f5
--- /dev/null
+++ b/public/maskable-icon.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/maskable120.png b/public/maskable120.png
new file mode 100644
index 0000000000..28472c71b9
Binary files /dev/null and b/public/maskable120.png differ
diff --git a/public/maskable128.png b/public/maskable128.png
new file mode 100644
index 0000000000..6a29bd5ded
Binary files /dev/null and b/public/maskable128.png differ
diff --git a/public/maskable144.png b/public/maskable144.png
new file mode 100644
index 0000000000..7567806438
Binary files /dev/null and b/public/maskable144.png differ
diff --git a/public/maskable152.png b/public/maskable152.png
new file mode 100644
index 0000000000..8301098084
Binary files /dev/null and b/public/maskable152.png differ
diff --git a/public/maskable180.png b/public/maskable180.png
new file mode 100644
index 0000000000..a3eb3f2127
Binary files /dev/null and b/public/maskable180.png differ
diff --git a/public/maskable192.png b/public/maskable192.png
new file mode 100644
index 0000000000..f280d1d2b2
Binary files /dev/null and b/public/maskable192.png differ
diff --git a/public/maskable384.png b/public/maskable384.png
new file mode 100644
index 0000000000..bed923b227
Binary files /dev/null and b/public/maskable384.png differ
diff --git a/public/maskable512.png b/public/maskable512.png
new file mode 100644
index 0000000000..311b9015b1
Binary files /dev/null and b/public/maskable512.png differ
diff --git a/public/maskable72.png b/public/maskable72.png
new file mode 100644
index 0000000000..d4e50a6039
Binary files /dev/null and b/public/maskable72.png differ
diff --git a/public/maskable76.png b/public/maskable76.png
new file mode 100644
index 0000000000..d793ac1218
Binary files /dev/null and b/public/maskable76.png differ
diff --git a/public/maskable96.png b/public/maskable96.png
new file mode 100644
index 0000000000..5a02b5acf1
Binary files /dev/null and b/public/maskable96.png differ
diff --git a/public/serviceworker.js b/public/serviceworker.js
new file mode 100644
index 0000000000..1eb9b19f82
--- /dev/null
+++ b/public/serviceworker.js
@@ -0,0 +1,58 @@
+/*
+ * serviceworker.js
+ * Copyright (c) 2021 james@firefly-iii.org
+ *
+ * This file is part of Firefly III (https://github.com/firefly-iii).
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+let staticCachePrefix = "firefly-III-"
+let staticCacheName = staticCachePrefix + new Date().getTime();
+let cachedFiles = [
+ '/offline',
+ '/v2/plugins/local-fonts/gf-source.css',
+ '/v2/css/app.css',
+];
+
+// Create cache on install
+self.addEventListener("install", event => {
+ this.skipWaiting();
+ event.waitUntil(
+ caches.open(staticCacheName).then(cache => cache.addAll(cachedFiles))
+ )
+});
+
+// Clear cache on activate
+self.addEventListener('activate', event => {
+ event.waitUntil(
+ caches.keys().then(cacheNames => {
+ return Promise.all(
+ cacheNames
+ .filter(cacheName => (cacheName.startsWith(staticCachePrefix)))
+ .filter(cacheName => (cacheName !== staticCacheName))
+ .map(cacheName => caches.delete(cacheName))
+ );
+ })
+ );
+});
+
+// Serve from Cache or return the offline page
+self.addEventListener("fetch", event => {
+ event.respondWith(
+ caches.match(event.request)
+ .then(response => (response || fetch(event.request)))
+ .catch(() => caches.match('offline'))
+ )
+});
diff --git a/resources/lang/en_GB/errors.php b/resources/lang/en_GB/errors.php
index 1818adc8c6..4dac63fc73 100644
--- a/resources/lang/en_GB/errors.php
+++ b/resources/lang/en_GB/errors.php
@@ -47,5 +47,4 @@ return [
'tell_more' => 'Tell us more than "it says Whoops!"',
'include_logs' => 'Include error logs (see above).',
'what_did_you_do' => 'Tell us what you were doing.',
-
];
diff --git a/resources/lang/en_US/errors.php b/resources/lang/en_US/errors.php
index 1818adc8c6..b63c231504 100644
--- a/resources/lang/en_US/errors.php
+++ b/resources/lang/en_US/errors.php
@@ -47,5 +47,8 @@ return [
'tell_more' => 'Tell us more than "it says Whoops!"',
'include_logs' => 'Include error logs (see above).',
'what_did_you_do' => 'Tell us what you were doing.',
+ 'offline_header' => 'You are probably offline',
+ 'offline_unreachable' => 'Firefly III is unreachable. Your device is currently offline or the server is not working.',
+ 'offline_github' => 'If you are sure both your device and the server are online, please open a ticket on GitHub.',
];
diff --git a/resources/lang/it_IT/errors.php b/resources/lang/it_IT/errors.php
index bdd4fe0a54..5bb4f6a123 100644
--- a/resources/lang/it_IT/errors.php
+++ b/resources/lang/it_IT/errors.php
@@ -47,5 +47,4 @@ return [
'tell_more' => 'Dicci di più di "dice Oops!"',
'include_logs' => 'Includi i log degli errori (vedi sopra).',
'what_did_you_do' => 'Dicci cosa stavi facendo.',
-
];
diff --git a/resources/views/errors/offline.twig b/resources/views/errors/offline.twig
new file mode 100644
index 0000000000..b1130978ee
--- /dev/null
+++ b/resources/views/errors/offline.twig
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+ Firefly III | Offline
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Offline
+
+ {{ trans('errors.offline_header') }}
+
+
+ {{ trans('errors.offline_unreachable') }}
+
+
+ {{ trans('errors.offline_github')|raw }}
+
+
+
+
+
+
+
+
+
diff --git a/resources/views/v1/layout/default.twig b/resources/views/v1/layout/default.twig
index 29956298df..cf02557e28 100644
--- a/resources/views/v1/layout/default.twig
+++ b/resources/views/v1/layout/default.twig
@@ -228,5 +228,17 @@
{% endif %}
+
+