+
+
-
-
-
-
play_circle_filled
+
+
+
+
+
+
+
+
+ play_circle_filled
+
+
+
+ edit
+
+
+ {{ selected ? 'radio_button_checked' : 'radio_button_unchecked' }}
-
- edit
-
-
- {{ selected ? 'radio_button_checked' : 'radio_button_unchecked' }}
-
-
-
+
-
-
- priority_high
-
-
-
-
+
+
+ priority_high
+
+
+
+
+
@@ -51,6 +61,12 @@ export default {
}
},
computed: {
+ isNew() {
+ return this.tags.includes('new')
+ },
+ tags() {
+ return this.audiobook.tags || []
+ },
audiobookId() {
return this.audiobook.id
},
diff --git a/client/components/controls/FilterSelect.vue b/client/components/controls/FilterSelect.vue
index fba24bd4..a87fb3d8 100644
--- a/client/components/controls/FilterSelect.vue
+++ b/client/components/controls/FilterSelect.vue
@@ -115,9 +115,6 @@ export default {
if (!_sel) return ''
return _sel.text
},
- authors() {
- return this.$store.getters['audiobooks/getUniqueAuthors']
- },
genres() {
return this.$store.state.audiobooks.genres
},
diff --git a/client/components/ui/MultiSelect.vue b/client/components/ui/MultiSelect.vue
index 8c9519d2..1b7ccc75 100644
--- a/client/components/ui/MultiSelect.vue
+++ b/client/components/ui/MultiSelect.vue
@@ -103,7 +103,6 @@ export default {
this.menu.style.top = boundingBox.y + boundingBox.height - 4 + 'px'
this.menu.style.left = boundingBox.x + 'px'
this.menu.style.width = boundingBox.width + 'px'
- console.log('Recalc menu pos', boundingBox.height)
},
unmountMountMenu() {
if (!this.$refs.menu) return
@@ -138,8 +137,10 @@ export default {
if (this.$refs.input) this.$refs.input.blur()
},
clickedOption(e, itemValue) {
- e.stopPropagation()
- e.preventDefault()
+ if (e) {
+ e.stopPropagation()
+ e.preventDefault()
+ }
if (this.$refs.input) this.$refs.input.focus()
var newSelected = null
@@ -187,7 +188,7 @@ export default {
return i === cleaned || cleanedKebab === i
})
if (matchesItem) {
- this.clickedOption(matchesItem.value)
+ this.clickedOption(null, matchesItem)
} else {
this.insertNewItem(this.textInput)
}
diff --git a/client/nuxt.config.js b/client/nuxt.config.js
index c1703017..517a08a6 100644
--- a/client/nuxt.config.js
+++ b/client/nuxt.config.js
@@ -36,6 +36,7 @@ module.exports = {
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' },
{ rel: 'stylesheet', href: 'https://fonts.googleapis.com/css2?family=Fira+Mono&family=Ubuntu+Mono&family=Open+Sans:wght@400;600&family=Gentium+Book+Basic' },
+ { rel: 'stylesheet', href: "https://fonts.googleapis.com/css2?family=Fondamento&family=Gentium+Book+Basic&family=Kurale&family=Lateef&family=Mate+SC&family=Merienda&display=swap" },
{ rel: 'stylesheet', href: 'https://fonts.googleapis.com/icon?family=Material+Icons' }
]
},
diff --git a/client/package.json b/client/package.json
index 69a1ad6e..f4c7dac9 100644
--- a/client/package.json
+++ b/client/package.json
@@ -1,6 +1,6 @@
{
"name": "audiobookshelf-client",
- "version": "0.9.86-beta",
+ "version": "0.9.87-beta",
"description": "Audiobook manager and player",
"main": "index.js",
"scripts": {
diff --git a/client/tailwind.config.js b/client/tailwind.config.js
index 41643a0b..8436bb35 100644
--- a/client/tailwind.config.js
+++ b/client/tailwind.config.js
@@ -23,6 +23,7 @@ module.exports = {
info: '#2196F3',
success: '#4CAF50',
warning: '#FB8C00',
+ darkgreen: 'rgb(34,127,35)',
'black-50': '#bbbbbb',
'black-100': '#666666',
'black-200': '#555555',
@@ -38,7 +39,12 @@ module.exports = {
fontFamily: {
sans: ['Open Sans', ...defaultTheme.fontFamily.sans],
mono: ['Ubuntu Mono', ...defaultTheme.fontFamily.mono],
- book: ['Gentium Book Basic', 'serif']
+ book: ['Gentium Book Basic', 'serif'],
+ fondamento: 'Fondamento',
+ gentium: 'Gentium Book Basic',
+ kurale: 'Kurale',
+ mate: 'Mate SC',
+ merienda: 'Merienda'
}
}
},
diff --git a/package.json b/package.json
index 6e66a91e..966d513a 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "audiobookshelf",
- "version": "0.9.86-beta",
+ "version": "0.9.87-beta",
"description": "Self-hosted audiobook server for managing and playing audiobooks.",
"main": "index.js",
"scripts": {
diff --git a/server/HlsController.js b/server/HlsController.js
index bacc60bd..4ac0f30e 100644
--- a/server/HlsController.js
+++ b/server/HlsController.js
@@ -30,6 +30,12 @@ class HlsController {
var streamId = req.params.stream
var fullFilePath = Path.join(this.MetadataPath, streamId, req.params.file)
+ // development test stream - ignore
+ if (streamId === 'test') {
+ Logger.debug('Test Stream Request', streamId, req.headers, fullFilePath)
+ return res.sendFile(fullFilePath)
+ }
+
var exists = await fs.pathExists(fullFilePath)
if (!exists) {
Logger.warn('File path does not exist', fullFilePath)
diff --git a/server/RssFeeds.js b/server/RssFeeds.js
index 2f98d26a..be446515 100644
--- a/server/RssFeeds.js
+++ b/server/RssFeeds.js
@@ -3,6 +3,7 @@ const express = require('express')
const ip = require('ip')
const Logger = require('./Logger')
+// Not functional at the moment - just an idea
class RssFeeds {
constructor(Port, db) {
this.Port = Port
diff --git a/server/Server.js b/server/Server.js
index 9761b00a..44545b63 100644
--- a/server/Server.js
+++ b/server/Server.js
@@ -133,6 +133,7 @@ class Server {
app.use('/api', this.authMiddleware.bind(this), this.apiController.router)
app.use('/hls', this.authMiddleware.bind(this), this.hlsController.router)
+ // app.use('/hls', this.hlsController.router)
app.use('/feeds', this.rssFeeds.router)
app.post('/login', (req, res) => this.auth.login(req, res))
@@ -142,6 +143,21 @@ class Server {
res.json({ success: true })
})
+
+ // Used in development to set-up streams without authentication
+ if (process.env.NODE_ENV !== 'production') {
+ app.use('/test-hls', this.hlsController.router)
+ app.get('/test-stream/:id', async (req, res) => {
+ var uri = await this.streamManager.openTestStream(this.MetadataPath, req.params.id)
+ res.send(uri)
+ })
+ app.get('/catalog.json', (req, res) => {
+ Logger.error('Catalog request made', req.headers)
+ res.json()
+ })
+ }
+
+
this.server.listen(this.Port, this.Host, () => {
Logger.info(`Running on http://${this.Host}:${this.Port}`)
})
diff --git a/server/StreamManager.js b/server/StreamManager.js
index d020d039..a0e5bbb2 100644
--- a/server/StreamManager.js
+++ b/server/StreamManager.js
@@ -1,4 +1,5 @@
const Stream = require('./Stream')
+const StreamTest = require('./test/StreamTest')
const Logger = require('./Logger')
const fs = require('fs-extra')
const Path = require('path')
@@ -100,6 +101,23 @@ class StreamManager {
this.db.updateUserStream(client.user.id, null)
}
+ async openTestStream(streamPath, audiobookId) {
+ Logger.info('Open Stream Test Request', audiobookId)
+ var audiobook = this.audiobooks.find(ab => ab.id === audiobookId)
+ var stream = new StreamTest(streamPath, audiobook)
+
+ stream.on('closed', () => {
+ console.log('Stream closed')
+ })
+
+ var playlistUri = await stream.generatePlaylist()
+ stream.start()
+
+ Logger.info('Stream Playlist', playlistUri)
+ Logger.info('Test Stream Opened for audiobook', audiobook.title, 'with streamId', stream.id)
+ return playlistUri
+ }
+
streamUpdate(socket, { currentTime, streamId }) {
var client = socket.sheepClient
if (!client || !client.stream) {