diff --git a/.gitignore b/.gitignore index 90b61fd40..50e8c00ff 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,6 @@ node_modules/ test/ /client/.nuxt/ /client/dist/ -/dist/ \ No newline at end of file +/dist/ + +sw.* \ No newline at end of file diff --git a/client/components/app/Appbar.vue b/client/components/app/Appbar.vue index 5ea6252ce..0e4ea9632 100644 --- a/client/components/app/Appbar.vue +++ b/client/components/app/Appbar.vue @@ -2,7 +2,7 @@
Series
{{ numShowing }} {{ entityName }}
{{ name }}
File | -Datetime | -Size | +Datetime | +Size | |
---|---|---|---|---|---|
- /{{ backup.path.replace(/\\/g, '/') }} +/{{ backup.path.replace(/\\/g, '/') }} |
- {{ backup.datePretty }} | -{{ $bytesPretty(backup.fileSize) }} | +{{ backup.datePretty }} | +{{ $bytesPretty(backup.fileSize) }} |
-
+
diff --git a/client/components/ui/Checkbox.vue b/client/components/ui/Checkbox.vue
index b384d018e..710fe3309 100644
--- a/client/components/ui/Checkbox.vue
+++ b/client/components/ui/Checkbox.vue
@@ -43,7 +43,7 @@ export default {
return classes.join(' ')
},
labelClass() {
- if (this.small) return 'text-sm'
+ if (this.small) return 'text-xs md:text-sm'
return ''
},
svgClass() {
diff --git a/client/layouts/default.vue b/client/layouts/default.vue
index 0c4d545a5..46708139b 100644
--- a/client/layouts/default.vue
+++ b/client/layouts/default.vue
@@ -502,12 +502,17 @@ export default {
this.$eventBus.$emit('player-hotkey', name)
e.preventDefault()
}
+ },
+ resize() {
+ this.$store.commit('globals/updateWindowSize', { width: window.innerWidth, height: window.innerHeight })
}
},
beforeMount() {
this.initializeSocket()
},
mounted() {
+ this.resize()
+ window.addEventListener('resize', this.resize)
window.addEventListener('keydown', this.keyDown)
this.$store.dispatch('libraries/load')
@@ -530,6 +535,7 @@ export default {
}
},
beforeDestroy() {
+ window.removeEventListener('resize', this.resize)
window.removeEventListener('keydown', this.keyDown)
}
}
diff --git a/client/nuxt.config.js b/client/nuxt.config.js
index 312c29328..7f7ba77f1 100644
--- a/client/nuxt.config.js
+++ b/client/nuxt.config.js
@@ -64,6 +64,7 @@ module.exports = {
buildModules: [
// https://go.nuxtjs.dev/tailwindcss
'@nuxtjs/tailwindcss',
+ '@nuxtjs/pwa'
],
// Modules: https://go.nuxtjs.dev/config-modules
@@ -98,6 +99,38 @@ module.exports = {
baseURL: process.env.serverUrl || ''
},
+ // nuxt/pwa https://pwa.nuxtjs.org
+ pwa: {
+ icon: false,
+ meta: {
+ appleStatusBarStyle: 'black',
+ name: 'Audiobookshelf',
+ theme_color: '#373838',
+ mobileAppIOS: true,
+ nativeUI: true
+ },
+ manifest: {
+ name: 'Audiobookshelf',
+ short_name: 'Audiobookshelf',
+ display: 'standalone',
+ background_color: '#373838',
+ icons: [
+ {
+ src: '/icon64.png',
+ sizes: "64x64"
+ },
+ {
+ src: '/icon192.png',
+ sizes: "192x192"
+ },
+ {
+ src: '/Logo.png',
+ sizes: "512x512"
+ }
+ ]
+ }
+ },
+
// Build Configuration: https://go.nuxtjs.dev/config-build
build: {},
watchers: {
diff --git a/client/package-lock.json b/client/package-lock.json
index 12aaf4460..82bfa5096 100644
--- a/client/package-lock.json
+++ b/client/package-lock.json
@@ -1,7 +1,7 @@
{
"name": "audiobookshelf-client",
- "version": "1.6.64",
- "lockfileVersion": 2,
+ "version": "1.6.65",
+ "lockfileVersion": 1,
"requires": true,
"packages": {
"": {
@@ -21270,6 +21270,31 @@
"http-proxy-middleware": "^1.0.6"
}
},
+ "@nuxtjs/pwa": {
+ "version": "3.3.5",
+ "resolved": "https://registry.npmjs.org/@nuxtjs/pwa/-/pwa-3.3.5.tgz",
+ "integrity": "sha512-8tTmW8DBspWxlJwTimOHTkwfkwPpL9wIcGmy75Gcmin+c9YtX2Ehxmhgt/TLFOC9XsLAqojqynw3/Agr/9OE1w==",
+ "dev": true,
+ "requires": {
+ "clone-deep": "^4.0.1",
+ "defu": "^3.2.2",
+ "execa": "^5.0.0",
+ "fs-extra": "^9.1.0",
+ "hasha": "^5.2.2",
+ "jimp-compact": "^0.16.1",
+ "lodash.template": "^4.5.0",
+ "serve-static": "^1.14.1",
+ "workbox-cdn": "^5.1.4"
+ },
+ "dependencies": {
+ "defu": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/defu/-/defu-3.2.2.tgz",
+ "integrity": "sha512-8UWj5lNv7HD+kB0e9w77Z7TdQlbUYDVWqITLHNqFIn6khrNHv5WQo38Dcm1f6HeNyZf0U7UbPf6WeZDSdCzGDQ==",
+ "dev": true
+ }
+ }
+ },
"@nuxtjs/tailwindcss": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/@nuxtjs/tailwindcss/-/tailwindcss-4.2.1.tgz",
@@ -23313,6 +23338,17 @@
}
}
},
+ "clone-deep": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz",
+ "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==",
+ "dev": true,
+ "requires": {
+ "is-plain-object": "^2.0.4",
+ "kind-of": "^6.0.2",
+ "shallow-clone": "^3.0.0"
+ }
+ },
"co": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
@@ -25558,6 +25594,24 @@
"minimalistic-assert": "^1.0.1"
}
},
+ "hasha": {
+ "version": "5.2.2",
+ "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz",
+ "integrity": "sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==",
+ "dev": true,
+ "requires": {
+ "is-stream": "^2.0.0",
+ "type-fest": "^0.8.0"
+ },
+ "dependencies": {
+ "type-fest": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
+ "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
+ "dev": true
+ }
+ }
+ },
"he": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
@@ -26313,6 +26367,12 @@
}
}
},
+ "jimp-compact": {
+ "version": "0.16.1",
+ "resolved": "https://registry.npmjs.org/jimp-compact/-/jimp-compact-0.16.1.tgz",
+ "integrity": "sha512-dZ6Ra7u1G8c4Letq/B5EzAxj4tLFHL+cGtdpR+PVm4yzPDj+lCk+AbivWt1eOM+ikzkowtyV7qSqX6qr3t71Ww==",
+ "dev": true
+ },
"jiti": {
"version": "1.11.0",
"resolved": "https://registry.npmjs.org/jiti/-/jiti-1.11.0.tgz",
@@ -31111,6 +31171,15 @@
"safe-buffer": "^5.0.1"
}
},
+ "shallow-clone": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz",
+ "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.2"
+ }
+ },
"shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
@@ -33413,6 +33482,12 @@
}
}
},
+ "workbox-cdn": {
+ "version": "5.1.4",
+ "resolved": "https://registry.npmjs.org/workbox-cdn/-/workbox-cdn-5.1.4.tgz",
+ "integrity": "sha512-04gM3mi8QGutokkSaA9xunVfjURnLbo9TTWyi8+pSDCEW5cD8u5GbJiliLK1vB9CShk/9OY1UDfW+XcmD+d6KQ==",
+ "dev": true
+ },
"worker-farm": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz",
diff --git a/client/package.json b/client/package.json
index f7582737b..eed861fc9 100644
--- a/client/package.json
+++ b/client/package.json
@@ -1,6 +1,6 @@
{
"name": "audiobookshelf-client",
- "version": "1.6.65",
+ "version": "1.6.66",
"description": "Audiobook manager and player",
"main": "index.js",
"scripts": {
@@ -28,6 +28,7 @@
"vuedraggable": "^2.24.3"
},
"devDependencies": {
+ "@nuxtjs/pwa": "^3.3.5",
"@nuxtjs/tailwindcss": "^4.2.1",
"postcss": "^8.3.6"
}
diff --git a/client/pages/audiobook/_id/index.vue b/client/pages/audiobook/_id/index.vue
index 9ca3dc782..0fc3c8bbd 100644
--- a/client/pages/audiobook/_id/index.vue
+++ b/client/pages/audiobook/_id/index.vue
@@ -1,15 +1,15 @@
-
-
+
+
-
-
+
@@ -82,7 +82,7 @@
@@ -73,7 +73,7 @@Book has no audio tracks but has valid ebook files. The e-reader is experimental and can be turned on in config.
+ Your Progress: {{ Math.round(progressPercent * 100) }}% {{ $elapsedPretty(userTimeRemaining) }} remaining
@@ -90,7 +90,7 @@
+
+
-
-
-
Logger +
+
Logger -
+
diff --git a/client/pages/config/stats.vue b/client/pages/config/stats.vue
index 230a4fc19..758827fd5 100644
--- a/client/pages/config/stats.vue
+++ b/client/pages/config/stats.vue
@@ -30,7 +30,7 @@
+ Recent Listening Sessionsdiff --git a/client/plugins/init.client.js b/client/plugins/init.client.js index 71e9f87ab..33b9bdc89 100644 --- a/client/plugins/init.client.js +++ b/client/plugins/init.client.js @@ -143,6 +143,5 @@ export { export default ({ app }, inject) => { app.$decode = decode app.$encode = encode - // app.$isDev = process.env.NODE_ENV !== 'production' inject('isDev', process.env.NODE_ENV !== 'production') } \ No newline at end of file diff --git a/client/static/Logo.png b/client/static/Logo.png index c9397c020..24e03a64a 100644 Binary files a/client/static/Logo.png and b/client/static/Logo.png differ diff --git a/client/static/Logo48.png b/client/static/Logo48.png deleted file mode 100644 index 8fb2a168c..000000000 Binary files a/client/static/Logo48.png and /dev/null differ diff --git a/client/static/icon192.png b/client/static/icon192.png new file mode 100644 index 000000000..5cbf1d4db Binary files /dev/null and b/client/static/icon192.png differ diff --git a/client/static/icon48.png b/client/static/icon48.png new file mode 100644 index 000000000..8f94f77c1 Binary files /dev/null and b/client/static/icon48.png differ diff --git a/client/static/icon64.png b/client/static/icon64.png new file mode 100644 index 000000000..e420b7ca9 Binary files /dev/null and b/client/static/icon64.png differ diff --git a/client/store/globals.js b/client/store/globals.js index d42fa52d8..786e6e014 100644 --- a/client/store/globals.js +++ b/client/store/globals.js @@ -1,5 +1,7 @@ export const state = () => ({ + isMobile: false, + isMobileLandscape: false, showBatchUserCollectionModal: false, showUserCollectionsModal: false, showEditCollectionModal: false, @@ -7,15 +9,13 @@ export const state = () => ({ showBookshelfTextureModal: false }) -export const getters = { - -} - -export const actions = { - -} +export const getters = {} export const mutations = { + updateWindowSize(state, { width, height }) { + state.isMobile = width < 768 || height < 768 + state.isMobileLandscape = state.isMobile && height > width + }, setShowUserCollectionsModal(state, val) { state.showBatchUserCollectionModal = false state.showUserCollectionsModal = val diff --git a/package.json b/package.json index 15bd07d5b..1e97a7b78 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "audiobookshelf", - "version": "1.6.65", + "version": "1.6.66", "description": "Self-hosted audiobook server for managing and playing audiobooks", "main": "index.js", "scripts": { |