mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2025-03-26 15:16:07 +01:00
Add book item more menu item for Share, restrict share to admin or up, add admin socket events for open/close shares
This commit is contained in:
parent
e05ab14ad2
commit
2f2ec2ec1f
@ -601,6 +601,30 @@ export default {
|
|||||||
this.executeRebuild()
|
this.executeRebuild()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
shareOpen(mediaItemShare) {
|
||||||
|
if (this.entityName === 'items' || this.entityName === 'series-books') {
|
||||||
|
var indexOf = this.entities.findIndex((ent) => ent?.media?.id === mediaItemShare.mediaItemId)
|
||||||
|
if (indexOf >= 0) {
|
||||||
|
if (this.entityComponentRefs[indexOf]) {
|
||||||
|
const libraryItem = { ...this.entityComponentRefs[indexOf].libraryItem }
|
||||||
|
libraryItem.mediaItemShare = mediaItemShare
|
||||||
|
this.entityComponentRefs[indexOf].setEntity?.(libraryItem)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
shareClosed(mediaItemShare) {
|
||||||
|
if (this.entityName === 'items' || this.entityName === 'series-books') {
|
||||||
|
var indexOf = this.entities.findIndex((ent) => ent?.media?.id === mediaItemShare.mediaItemId)
|
||||||
|
if (indexOf >= 0) {
|
||||||
|
if (this.entityComponentRefs[indexOf]) {
|
||||||
|
const libraryItem = { ...this.entityComponentRefs[indexOf].libraryItem }
|
||||||
|
libraryItem.mediaItemShare = null
|
||||||
|
this.entityComponentRefs[indexOf].setEntity?.(libraryItem)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
updatePagesLoaded() {
|
updatePagesLoaded() {
|
||||||
let numPages = Math.ceil(this.totalEntities / this.booksPerFetch)
|
let numPages = Math.ceil(this.totalEntities / this.booksPerFetch)
|
||||||
for (let page = 0; page < numPages; page++) {
|
for (let page = 0; page < numPages; page++) {
|
||||||
@ -703,6 +727,8 @@ export default {
|
|||||||
this.$root.socket.on('playlist_added', this.playlistAdded)
|
this.$root.socket.on('playlist_added', this.playlistAdded)
|
||||||
this.$root.socket.on('playlist_updated', this.playlistUpdated)
|
this.$root.socket.on('playlist_updated', this.playlistUpdated)
|
||||||
this.$root.socket.on('playlist_removed', this.playlistRemoved)
|
this.$root.socket.on('playlist_removed', this.playlistRemoved)
|
||||||
|
this.$root.socket.on('share_open', this.shareOpen)
|
||||||
|
this.$root.socket.on('share_closed', this.shareClosed)
|
||||||
} else {
|
} else {
|
||||||
console.error('Bookshelf - Socket not initialized')
|
console.error('Bookshelf - Socket not initialized')
|
||||||
}
|
}
|
||||||
@ -730,6 +756,8 @@ export default {
|
|||||||
this.$root.socket.off('playlist_added', this.playlistAdded)
|
this.$root.socket.off('playlist_added', this.playlistAdded)
|
||||||
this.$root.socket.off('playlist_updated', this.playlistUpdated)
|
this.$root.socket.off('playlist_updated', this.playlistUpdated)
|
||||||
this.$root.socket.off('playlist_removed', this.playlistRemoved)
|
this.$root.socket.off('playlist_removed', this.playlistRemoved)
|
||||||
|
this.$root.socket.off('share_open', this.shareOpen)
|
||||||
|
this.$root.socket.off('share_closed', this.shareClosed)
|
||||||
} else {
|
} else {
|
||||||
console.error('Bookshelf - Socket not initialized')
|
console.error('Bookshelf - Socket not initialized')
|
||||||
}
|
}
|
||||||
|
@ -528,6 +528,12 @@ export default {
|
|||||||
func: 'openPlaylists',
|
func: 'openPlaylists',
|
||||||
text: this.$strings.LabelAddToPlaylist
|
text: this.$strings.LabelAddToPlaylist
|
||||||
})
|
})
|
||||||
|
if (this.userIsAdminOrUp) {
|
||||||
|
items.push({
|
||||||
|
func: 'openShare',
|
||||||
|
text: this.$strings.LabelShare
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (this.ebookFormat && this.store.state.libraries.ereaderDevices?.length) {
|
if (this.ebookFormat && this.store.state.libraries.ereaderDevices?.length) {
|
||||||
items.push({
|
items.push({
|
||||||
@ -880,6 +886,10 @@ export default {
|
|||||||
this.store.commit('globals/setSelectedPlaylistItems', [{ libraryItem: this.libraryItem, episode: this.recentEpisode }])
|
this.store.commit('globals/setSelectedPlaylistItems', [{ libraryItem: this.libraryItem, episode: this.recentEpisode }])
|
||||||
this.store.commit('globals/setShowPlaylistsModal', true)
|
this.store.commit('globals/setShowPlaylistsModal', true)
|
||||||
},
|
},
|
||||||
|
openShare() {
|
||||||
|
this.store.commit('setSelectedLibraryItem', this.libraryItem)
|
||||||
|
this.store.commit('globals/setShareModal', this.mediaItemShare)
|
||||||
|
},
|
||||||
deleteLibraryItem() {
|
deleteLibraryItem() {
|
||||||
const payload = {
|
const payload = {
|
||||||
message: this.$strings.MessageConfirmDeleteLibraryItem,
|
message: this.$strings.MessageConfirmDeleteLibraryItem,
|
||||||
|
@ -89,6 +89,9 @@ export default {
|
|||||||
this.$emit('input', val)
|
this.$emit('input', val)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
userIsAdminOrUp() {
|
||||||
|
return this.$store.getters['user/getIsAdminOrUp']
|
||||||
|
},
|
||||||
libraryMediaType() {
|
libraryMediaType() {
|
||||||
return this.$store.getters['libraries/getCurrentLibraryMediaType']
|
return this.$store.getters['libraries/getCurrentLibraryMediaType']
|
||||||
},
|
},
|
||||||
@ -148,7 +151,7 @@ export default {
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
bookItems() {
|
bookItems() {
|
||||||
return [
|
const items = [
|
||||||
{
|
{
|
||||||
text: this.$strings.LabelAll,
|
text: this.$strings.LabelAll,
|
||||||
value: 'all'
|
value: 'all'
|
||||||
@ -229,13 +232,16 @@ export default {
|
|||||||
text: this.$strings.LabelRSSFeedOpen,
|
text: this.$strings.LabelRSSFeedOpen,
|
||||||
value: 'feed-open',
|
value: 'feed-open',
|
||||||
sublist: false
|
sublist: false
|
||||||
},
|
}
|
||||||
{
|
]
|
||||||
|
if (this.userIsAdminOrUp) {
|
||||||
|
items.push({
|
||||||
text: this.$strings.LabelShareOpen,
|
text: this.$strings.LabelShareOpen,
|
||||||
value: 'share-open',
|
value: 'share-open',
|
||||||
sublist: false
|
sublist: false
|
||||||
|
})
|
||||||
}
|
}
|
||||||
]
|
return items
|
||||||
},
|
},
|
||||||
podcastItems() {
|
podcastItems() {
|
||||||
return [
|
return [
|
||||||
|
@ -53,17 +53,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {},
|
||||||
value: Boolean,
|
|
||||||
libraryItem: {
|
|
||||||
type: Object,
|
|
||||||
default: () => null
|
|
||||||
},
|
|
||||||
mediaItemShare: {
|
|
||||||
type: Object,
|
|
||||||
default: () => null
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
processing: false,
|
processing: false,
|
||||||
@ -99,12 +89,18 @@ export default {
|
|||||||
computed: {
|
computed: {
|
||||||
show: {
|
show: {
|
||||||
get() {
|
get() {
|
||||||
return this.value
|
return this.$store.state.globals.showShareModal
|
||||||
},
|
},
|
||||||
set(val) {
|
set(val) {
|
||||||
this.$emit('input', val)
|
this.$store.commit('globals/setShowShareModal', val)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
mediaItemShare() {
|
||||||
|
return this.$store.state.globals.selectedMediaItemShare
|
||||||
|
},
|
||||||
|
libraryItem() {
|
||||||
|
return this.$store.state.selectedLibraryItem
|
||||||
|
},
|
||||||
user() {
|
user() {
|
||||||
return this.$store.state.user.user
|
return this.$store.state.user.user
|
||||||
},
|
},
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
<modals-batch-quick-match-model />
|
<modals-batch-quick-match-model />
|
||||||
<modals-rssfeed-open-close-modal />
|
<modals-rssfeed-open-close-modal />
|
||||||
<modals-raw-cover-preview-modal />
|
<modals-raw-cover-preview-modal />
|
||||||
|
<modals-share-modal />
|
||||||
<prompt-confirm />
|
<prompt-confirm />
|
||||||
<readers-reader />
|
<readers-reader />
|
||||||
</div>
|
</div>
|
||||||
|
@ -147,7 +147,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<modals-share-modal v-model="showShareModal" :media-item-share="mediaItemShare" :library-item="libraryItem" @opened="openedShare" @removed="removedShare" />
|
|
||||||
<modals-podcast-episode-feed v-model="showPodcastEpisodeFeed" :library-item="libraryItem" :episodes="podcastFeedEpisodes" />
|
<modals-podcast-episode-feed v-model="showPodcastEpisodeFeed" :library-item="libraryItem" :episodes="podcastFeedEpisodes" />
|
||||||
<modals-bookmarks-modal v-model="showBookmarksModal" :bookmarks="bookmarks" :library-item-id="libraryItemId" hide-create @select="selectBookmark" />
|
<modals-bookmarks-modal v-model="showBookmarksModal" :bookmarks="bookmarks" :library-item-id="libraryItemId" hide-create @select="selectBookmark" />
|
||||||
</div>
|
</div>
|
||||||
@ -186,8 +185,7 @@ export default {
|
|||||||
episodeDownloadsQueued: [],
|
episodeDownloadsQueued: [],
|
||||||
showBookmarksModal: false,
|
showBookmarksModal: false,
|
||||||
isDescriptionClamped: false,
|
isDescriptionClamped: false,
|
||||||
showFullDescription: false,
|
showFullDescription: false
|
||||||
showShareModal: false
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -440,7 +438,7 @@ export default {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.userIsAdminOrUp && !this.isPodcast) {
|
if (this.userIsAdminOrUp && !this.isPodcast && this.tracks.length) {
|
||||||
items.push({
|
items.push({
|
||||||
text: this.$strings.LabelShare,
|
text: this.$strings.LabelShare,
|
||||||
action: 'share'
|
action: 'share'
|
||||||
@ -458,12 +456,6 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
openedShare(mediaItemShare) {
|
|
||||||
this.mediaItemShare = mediaItemShare
|
|
||||||
},
|
|
||||||
removedShare() {
|
|
||||||
this.mediaItemShare = null
|
|
||||||
},
|
|
||||||
selectBookmark(bookmark) {
|
selectBookmark(bookmark) {
|
||||||
if (!bookmark) return
|
if (!bookmark) return
|
||||||
if (this.isStreaming) {
|
if (this.isStreaming) {
|
||||||
@ -682,6 +674,16 @@ export default {
|
|||||||
this.rssFeed = null
|
this.rssFeed = null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
shareOpen(mediaItemShare) {
|
||||||
|
if (mediaItemShare.mediaItemId === this.media.id) {
|
||||||
|
this.mediaItemShare = mediaItemShare
|
||||||
|
}
|
||||||
|
},
|
||||||
|
shareClosed(mediaItemShare) {
|
||||||
|
if (mediaItemShare.mediaItemId === this.media.id) {
|
||||||
|
this.mediaItemShare = null
|
||||||
|
}
|
||||||
|
},
|
||||||
queueBtnClick() {
|
queueBtnClick() {
|
||||||
if (this.isQueued) {
|
if (this.isQueued) {
|
||||||
// Remove from queue
|
// Remove from queue
|
||||||
@ -778,7 +780,8 @@ export default {
|
|||||||
} else if (action === 'sendToDevice') {
|
} else if (action === 'sendToDevice') {
|
||||||
this.sendToDevice(data)
|
this.sendToDevice(data)
|
||||||
} else if (action === 'share') {
|
} else if (action === 'share') {
|
||||||
this.showShareModal = true
|
this.$store.commit('setSelectedLibraryItem', this.libraryItem)
|
||||||
|
this.$store.commit('globals/setShareModal', this.mediaItemShare)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -796,6 +799,8 @@ export default {
|
|||||||
this.$root.socket.on('item_updated', this.libraryItemUpdated)
|
this.$root.socket.on('item_updated', this.libraryItemUpdated)
|
||||||
this.$root.socket.on('rss_feed_open', this.rssFeedOpen)
|
this.$root.socket.on('rss_feed_open', this.rssFeedOpen)
|
||||||
this.$root.socket.on('rss_feed_closed', this.rssFeedClosed)
|
this.$root.socket.on('rss_feed_closed', this.rssFeedClosed)
|
||||||
|
this.$root.socket.on('share_open', this.shareOpen)
|
||||||
|
this.$root.socket.on('share_closed', this.shareClosed)
|
||||||
this.$root.socket.on('episode_download_queued', this.episodeDownloadQueued)
|
this.$root.socket.on('episode_download_queued', this.episodeDownloadQueued)
|
||||||
this.$root.socket.on('episode_download_started', this.episodeDownloadStarted)
|
this.$root.socket.on('episode_download_started', this.episodeDownloadStarted)
|
||||||
this.$root.socket.on('episode_download_finished', this.episodeDownloadFinished)
|
this.$root.socket.on('episode_download_finished', this.episodeDownloadFinished)
|
||||||
@ -805,6 +810,8 @@ export default {
|
|||||||
this.$root.socket.off('item_updated', this.libraryItemUpdated)
|
this.$root.socket.off('item_updated', this.libraryItemUpdated)
|
||||||
this.$root.socket.off('rss_feed_open', this.rssFeedOpen)
|
this.$root.socket.off('rss_feed_open', this.rssFeedOpen)
|
||||||
this.$root.socket.off('rss_feed_closed', this.rssFeedClosed)
|
this.$root.socket.off('rss_feed_closed', this.rssFeedClosed)
|
||||||
|
this.$root.socket.off('share_open', this.shareOpen)
|
||||||
|
this.$root.socket.off('share_closed', this.shareClosed)
|
||||||
this.$root.socket.off('episode_download_queued', this.episodeDownloadQueued)
|
this.$root.socket.off('episode_download_queued', this.episodeDownloadQueued)
|
||||||
this.$root.socket.off('episode_download_started', this.episodeDownloadStarted)
|
this.$root.socket.off('episode_download_started', this.episodeDownloadStarted)
|
||||||
this.$root.socket.off('episode_download_finished', this.episodeDownloadFinished)
|
this.$root.socket.off('episode_download_finished', this.episodeDownloadFinished)
|
||||||
|
@ -10,6 +10,7 @@ export const state = () => ({
|
|||||||
showEditPodcastEpisode: false,
|
showEditPodcastEpisode: false,
|
||||||
showViewPodcastEpisodeModal: false,
|
showViewPodcastEpisodeModal: false,
|
||||||
showRSSFeedOpenCloseModal: false,
|
showRSSFeedOpenCloseModal: false,
|
||||||
|
showShareModal: false,
|
||||||
showConfirmPrompt: false,
|
showConfirmPrompt: false,
|
||||||
showRawCoverPreviewModal: false,
|
showRawCoverPreviewModal: false,
|
||||||
confirmPromptOptions: null,
|
confirmPromptOptions: null,
|
||||||
@ -22,6 +23,7 @@ export const state = () => ({
|
|||||||
selectedAuthor: null,
|
selectedAuthor: null,
|
||||||
selectedMediaItems: [],
|
selectedMediaItems: [],
|
||||||
selectedRawCoverUrl: null,
|
selectedRawCoverUrl: null,
|
||||||
|
selectedMediaItemShare: null,
|
||||||
isCasting: false, // Actively casting
|
isCasting: false, // Actively casting
|
||||||
isChromecastInitialized: false, // Script loadeds
|
isChromecastInitialized: false, // Script loadeds
|
||||||
showBatchQuickMatchModal: false,
|
showBatchQuickMatchModal: false,
|
||||||
@ -157,6 +159,13 @@ export const mutations = {
|
|||||||
state.rssFeedEntity = entity
|
state.rssFeedEntity = entity
|
||||||
state.showRSSFeedOpenCloseModal = true
|
state.showRSSFeedOpenCloseModal = true
|
||||||
},
|
},
|
||||||
|
setShowShareModal(state, val) {
|
||||||
|
state.showShareModal = val
|
||||||
|
},
|
||||||
|
setShareModal(state, mediaItemShare) {
|
||||||
|
state.selectedMediaItemShare = mediaItemShare
|
||||||
|
state.showShareModal = true
|
||||||
|
},
|
||||||
setShowConfirmPrompt(state, val) {
|
setShowConfirmPrompt(state, val) {
|
||||||
state.showConfirmPrompt = val
|
state.showConfirmPrompt = val
|
||||||
},
|
},
|
||||||
|
@ -43,7 +43,7 @@ class LibraryItemController {
|
|||||||
item.rssFeed = feedData?.toJSONMinified() || null
|
item.rssFeed = feedData?.toJSONMinified() || null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.mediaType === 'book' && includeEntities.includes('share')) {
|
if (item.mediaType === 'book' && req.user.isAdminOrUp && includeEntities.includes('share')) {
|
||||||
item.mediaItemShare = ShareManager.findByMediaItemId(item.media.id)
|
item.mediaItemShare = ShareManager.findByMediaItemId(item.media.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
const Database = require('../Database')
|
const Database = require('../Database')
|
||||||
const Logger = require('../Logger')
|
const Logger = require('../Logger')
|
||||||
|
const SocketAuthority = require('../SocketAuthority')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef OpenMediaItemShareObject
|
* @typedef OpenMediaItemShareObject
|
||||||
@ -136,6 +137,7 @@ class ShareManager {
|
|||||||
} else {
|
} else {
|
||||||
this.openMediaItemShares.push({ id: mediaItemShare.id, mediaItemShare: mediaItemShare.toJSON() })
|
this.openMediaItemShares.push({ id: mediaItemShare.id, mediaItemShare: mediaItemShare.toJSON() })
|
||||||
}
|
}
|
||||||
|
SocketAuthority.adminEmitter('share_open', mediaItemShare.toJSONForClient())
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -153,6 +155,12 @@ class ShareManager {
|
|||||||
this.openMediaItemShares = this.openMediaItemShares.filter((s) => s.id !== mediaItemShareId)
|
this.openMediaItemShares = this.openMediaItemShares.filter((s) => s.id !== mediaItemShareId)
|
||||||
this.openSharePlaybackSessions = this.openSharePlaybackSessions.filter((s) => s.mediaItemShareId !== mediaItemShareId)
|
this.openSharePlaybackSessions = this.openSharePlaybackSessions.filter((s) => s.mediaItemShareId !== mediaItemShareId)
|
||||||
await this.destroyMediaItemShare(mediaItemShareId)
|
await this.destroyMediaItemShare(mediaItemShareId)
|
||||||
|
|
||||||
|
const mediaItemShareObjectForClient = { ...mediaItemShare.mediaItemShare }
|
||||||
|
delete mediaItemShareObjectForClient.pash
|
||||||
|
delete mediaItemShareObjectForClient.userId
|
||||||
|
delete mediaItemShareObjectForClient.extraData
|
||||||
|
SocketAuthority.adminEmitter('share_closed', mediaItemShareObjectForClient)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -567,8 +567,8 @@ class LibraryItem extends Model {
|
|||||||
if (li.numEpisodesIncomplete) {
|
if (li.numEpisodesIncomplete) {
|
||||||
oldLibraryItem.numEpisodesIncomplete = li.numEpisodesIncomplete
|
oldLibraryItem.numEpisodesIncomplete = li.numEpisodesIncomplete
|
||||||
}
|
}
|
||||||
if (li.mediaType === 'book' && options.include?.includes?.('share')) {
|
if (li.mediaItemShare) {
|
||||||
oldLibraryItem.mediaItemShare = ShareManager.findByMediaItemId(li.mediaId)
|
oldLibraryItem.mediaItemShare = li.mediaItemShare
|
||||||
}
|
}
|
||||||
|
|
||||||
return oldLibraryItem
|
return oldLibraryItem
|
||||||
|
@ -332,9 +332,9 @@ module.exports = {
|
|||||||
/**
|
/**
|
||||||
* Get library items for book media type using filter and sort
|
* Get library items for book media type using filter and sort
|
||||||
* @param {string} libraryId
|
* @param {string} libraryId
|
||||||
* @param {[oldUser]} user
|
* @param {import('../../objects/user/User')} user
|
||||||
* @param {[string]} filterGroup
|
* @param {string|null} filterGroup
|
||||||
* @param {[string]} filterValue
|
* @param {string|null} filterValue
|
||||||
* @param {string} sortBy
|
* @param {string} sortBy
|
||||||
* @param {string} sortDesc
|
* @param {string} sortDesc
|
||||||
* @param {boolean} collapseseries
|
* @param {boolean} collapseseries
|
||||||
@ -356,7 +356,7 @@ module.exports = {
|
|||||||
sortBy = 'media.metadata.title'
|
sortBy = 'media.metadata.title'
|
||||||
}
|
}
|
||||||
const includeRSSFeed = include.includes('rssfeed')
|
const includeRSSFeed = include.includes('rssfeed')
|
||||||
const includeMediaItemShare = include.includes('share')
|
const includeMediaItemShare = !!user?.isAdminOrUp && include.includes('share')
|
||||||
|
|
||||||
// For sorting by author name an additional attribute must be added
|
// For sorting by author name an additional attribute must be added
|
||||||
// with author names concatenated
|
// with author names concatenated
|
||||||
|
Loading…
Reference in New Issue
Block a user