mirror of
				https://github.com/advplyr/audiobookshelf.git
				synced 2025-10-27 11:18:14 +01:00 
			
		
		
		
	Improve track order detection, allow for excluding audio files from tracklist
This commit is contained in:
		
							parent
							
								
									45ee42bddd
								
							
						
					
					
						commit
						af0365c81f
					
				@ -9,7 +9,15 @@
 | 
				
			|||||||
<script>
 | 
					<script>
 | 
				
			||||||
export default {
 | 
					export default {
 | 
				
			||||||
  props: {
 | 
					  props: {
 | 
				
			||||||
    value: Boolean
 | 
					    value: Boolean,
 | 
				
			||||||
 | 
					    onColor: {
 | 
				
			||||||
 | 
					      type: String,
 | 
				
			||||||
 | 
					      default: 'success'
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    offColor: {
 | 
				
			||||||
 | 
					      type: String,
 | 
				
			||||||
 | 
					      default: 'primary'
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  computed: {
 | 
					  computed: {
 | 
				
			||||||
    toggleValue: {
 | 
					    toggleValue: {
 | 
				
			||||||
@ -21,12 +29,11 @@ export default {
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    toggleColor() {
 | 
					    toggleColor() {
 | 
				
			||||||
      return this.toggleValue ? 'bg-success' : 'bg-primary'
 | 
					      return this.toggleValue ? `bg-${this.onColor}` : `bg-${this.offColor}`
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  methods: {
 | 
					  methods: {
 | 
				
			||||||
    clickToggle() {
 | 
					    clickToggle() {
 | 
				
			||||||
      console.log('click toggle', this.toggleValue)
 | 
					 | 
				
			||||||
      this.toggleValue = !this.toggleValue
 | 
					      this.toggleValue = !this.toggleValue
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,6 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  "name": "audiobookshelf-client",
 | 
					  "name": "audiobookshelf-client",
 | 
				
			||||||
  "version": "1.0.0",
 | 
					  "version": "1.0.1",
 | 
				
			||||||
  "description": "Audiobook manager and player",
 | 
					  "description": "Audiobook manager and player",
 | 
				
			||||||
  "main": "index.js",
 | 
					  "main": "index.js",
 | 
				
			||||||
  "scripts": {
 | 
					  "scripts": {
 | 
				
			||||||
 | 
				
			|||||||
@ -19,16 +19,15 @@
 | 
				
			|||||||
        <div class="font-mono w-20 text-center">Duration</div>
 | 
					        <div class="font-mono w-20 text-center">Duration</div>
 | 
				
			||||||
        <div class="font-mono text-center w-20">Status</div>
 | 
					        <div class="font-mono text-center w-20">Status</div>
 | 
				
			||||||
        <div class="font-mono w-56">Notes</div>
 | 
					        <div class="font-mono w-56">Notes</div>
 | 
				
			||||||
 | 
					        <div class="font-book w-40">Include in Tracklist</div>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
      <draggable v-model="files" v-bind="dragOptions" class="list-group border border-gray-600" draggable=".item" tag="ul" @start="drag = true" @end="drag = false">
 | 
					      <draggable v-model="files" v-bind="dragOptions" class="list-group border border-gray-600" draggable=".item" tag="ul" @start="drag = true" @end="drag = false">
 | 
				
			||||||
        <transition-group type="transition" :name="!drag ? 'flip-list' : null">
 | 
					        <transition-group type="transition" :name="!drag ? 'flip-list' : null">
 | 
				
			||||||
          <li v-for="(audio, index) in files" :key="audio.path" class="w-full list-group-item item flex items-center">
 | 
					          <li v-for="(audio, index) in files" :key="audio.path" :class="audio.include ? 'item' : 'exclude'" class="w-full list-group-item flex items-center">
 | 
				
			||||||
            <div class="font-book text-center px-4 py-1 w-12">
 | 
					            <div class="font-book text-center px-4 py-1 w-12">
 | 
				
			||||||
              {{ index + 1 }}
 | 
					              {{ audio.include ? index - numExcluded + 1 : -1 }}
 | 
				
			||||||
            </div>
 | 
					 | 
				
			||||||
            <div class="font-book text-center px-4 w-12">
 | 
					 | 
				
			||||||
              {{ audio.index }}
 | 
					 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
 | 
					            <div class="font-book text-center px-4 w-12">{{ audio.index }}</div>
 | 
				
			||||||
            <div class="font-book text-center px-2 w-32">
 | 
					            <div class="font-book text-center px-2 w-32">
 | 
				
			||||||
              {{ audio.trackNumFromFilename }}
 | 
					              {{ audio.trackNumFromFilename }}
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
@ -51,6 +50,9 @@
 | 
				
			|||||||
            <div class="font-sans text-xs font-normal w-56">
 | 
					            <div class="font-sans text-xs font-normal w-56">
 | 
				
			||||||
              {{ audio.error }}
 | 
					              {{ audio.error }}
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
 | 
					            <div class="font-sans text-xs font-normal w-40 flex justify-center">
 | 
				
			||||||
 | 
					              <ui-toggle-switch v-model="audio.include" :off-color="'error'" @input="includeToggled(audio)" />
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
          </li>
 | 
					          </li>
 | 
				
			||||||
        </transition-group>
 | 
					        </transition-group>
 | 
				
			||||||
      </draggable>
 | 
					      </draggable>
 | 
				
			||||||
@ -77,10 +79,10 @@ export default {
 | 
				
			|||||||
      console.error('No audiobook...', params.id)
 | 
					      console.error('No audiobook...', params.id)
 | 
				
			||||||
      return redirect('/')
 | 
					      return redirect('/')
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    let index = 0
 | 
					 | 
				
			||||||
    return {
 | 
					    return {
 | 
				
			||||||
      audiobook,
 | 
					      audiobook,
 | 
				
			||||||
      files: audiobook.audioFiles ? audiobook.audioFiles.map((af) => ({ ...af, index: ++index })) : []
 | 
					      files: audiobook.audioFiles ? audiobook.audioFiles.map((af) => ({ ...af, include: !af.exclude })) : []
 | 
				
			||||||
 | 
					      // files: audiobook.audioFiles ? audiobook.audioFiles.map((af) => ({ ...af, index: ++index })) : []
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  data() {
 | 
					  data() {
 | 
				
			||||||
@ -98,6 +100,13 @@ export default {
 | 
				
			|||||||
    audioFiles() {
 | 
					    audioFiles() {
 | 
				
			||||||
      return this.audiobook.audioFiles || []
 | 
					      return this.audiobook.audioFiles || []
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    numExcluded() {
 | 
				
			||||||
 | 
					      var count = 0
 | 
				
			||||||
 | 
					      this.files.forEach((file) => {
 | 
				
			||||||
 | 
					        if (!file.include) count++
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					      return count
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    missingPartChunks() {
 | 
					    missingPartChunks() {
 | 
				
			||||||
      if (this.missingParts === 1) return this.missingParts[0]
 | 
					      if (this.missingParts === 1) return this.missingParts[0]
 | 
				
			||||||
      var chunks = []
 | 
					      var chunks = []
 | 
				
			||||||
@ -164,15 +173,36 @@ export default {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  methods: {
 | 
					  methods: {
 | 
				
			||||||
 | 
					    includeToggled(audio) {
 | 
				
			||||||
 | 
					      var new_index = 0
 | 
				
			||||||
 | 
					      if (audio.include) {
 | 
				
			||||||
 | 
					        new_index = this.numExcluded
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      var old_index = this.files.findIndex((f) => f.ino === audio.ino)
 | 
				
			||||||
 | 
					      if (new_index >= this.files.length) {
 | 
				
			||||||
 | 
					        var k = new_index - this.files.length + 1
 | 
				
			||||||
 | 
					        while (k--) {
 | 
				
			||||||
 | 
					          this.files.push(undefined)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      this.files.splice(new_index, 0, this.files.splice(old_index, 1)[0])
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    saveTracklist() {
 | 
					    saveTracklist() {
 | 
				
			||||||
      console.log('Tracklist', this.files)
 | 
					      var orderedFileData = this.files.map((file) => {
 | 
				
			||||||
 | 
					        return {
 | 
				
			||||||
 | 
					          index: file.index,
 | 
				
			||||||
 | 
					          filename: file.filename,
 | 
				
			||||||
 | 
					          ino: file.ino,
 | 
				
			||||||
 | 
					          exclude: !file.include
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      this.saving = true
 | 
					      this.saving = true
 | 
				
			||||||
      this.$axios
 | 
					      this.$axios
 | 
				
			||||||
        .$patch(`/api/audiobook/${this.audiobook.id}/tracks`, { files: this.files })
 | 
					        .$patch(`/api/audiobook/${this.audiobook.id}/tracks`, { orderedFileData })
 | 
				
			||||||
        .then((data) => {
 | 
					        .then((data) => {
 | 
				
			||||||
          console.log('Finished patching files', data)
 | 
					          console.log('Finished patching files', data)
 | 
				
			||||||
          this.saving = false
 | 
					          this.saving = false
 | 
				
			||||||
          // this.$router.go()
 | 
					 | 
				
			||||||
          this.$toast.success('Tracks Updated')
 | 
					          this.$toast.success('Tracks Updated')
 | 
				
			||||||
          this.$router.push(`/audiobook/${this.audiobookId}`)
 | 
					          this.$router.push(`/audiobook/${this.audiobookId}`)
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
@ -207,16 +237,26 @@ export default {
 | 
				
			|||||||
.list-group {
 | 
					.list-group {
 | 
				
			||||||
  min-height: 30px;
 | 
					  min-height: 30px;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
.list-group-item {
 | 
					.list-group-item:not(.exclude) {
 | 
				
			||||||
  cursor: n-resize;
 | 
					  cursor: n-resize;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
.list-group-item:not(.ghost):hover {
 | 
					.list-group-item.exclude {
 | 
				
			||||||
 | 
					  cursor: not-allowed;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.list-group-item:not(.ghost):not(.exclude):hover {
 | 
				
			||||||
  background-color: rgba(0, 0, 0, 0.1);
 | 
					  background-color: rgba(0, 0, 0, 0.1);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
.list-group-item:nth-child(even):not(.ghost) {
 | 
					.list-group-item:nth-child(even):not(.ghost):not(.exclude) {
 | 
				
			||||||
  background-color: rgba(0, 0, 0, 0.25);
 | 
					  background-color: rgba(0, 0, 0, 0.25);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
.list-group-item:nth-child(even):not(.ghost):hover {
 | 
					.list-group-item:nth-child(even):not(.ghost):not(.exclude):hover {
 | 
				
			||||||
  background-color: rgba(0, 0, 0, 0.1);
 | 
					  background-color: rgba(0, 0, 0, 0.1);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.list-group-item.exclude:not(.ghost) {
 | 
				
			||||||
 | 
					  background-color: rgba(255, 0, 0, 0.25);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.list-group-item.exclude:not(.ghost):hover {
 | 
				
			||||||
 | 
					  background-color: rgba(223, 0, 0, 0.25);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
</style>
 | 
					</style>
 | 
				
			||||||
@ -209,7 +209,7 @@ export default {
 | 
				
			|||||||
    streamAudiobook() {
 | 
					    streamAudiobook() {
 | 
				
			||||||
      return this.$store.state.streamAudiobook
 | 
					      return this.$store.state.streamAudiobook
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    isStreaming() {
 | 
					    streaming() {
 | 
				
			||||||
      return this.streamAudiobook && this.streamAudiobook.id === this.audiobookId
 | 
					      return this.streamAudiobook && this.streamAudiobook.id === this.audiobookId
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,6 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  "name": "audiobookshelf",
 | 
					  "name": "audiobookshelf",
 | 
				
			||||||
  "version": "1.0.0",
 | 
					  "version": "1.0.1",
 | 
				
			||||||
  "description": "Self-hosted audiobook server for managing and playing audiobooks.",
 | 
					  "description": "Self-hosted audiobook server for managing and playing audiobooks.",
 | 
				
			||||||
  "main": "index.js",
 | 
					  "main": "index.js",
 | 
				
			||||||
  "scripts": {
 | 
					  "scripts": {
 | 
				
			||||||
 | 
				
			|||||||
@ -182,9 +182,9 @@ class ApiController {
 | 
				
			|||||||
  async updateAudiobookTracks(req, res) {
 | 
					  async updateAudiobookTracks(req, res) {
 | 
				
			||||||
    var audiobook = this.db.audiobooks.find(a => a.id === req.params.id)
 | 
					    var audiobook = this.db.audiobooks.find(a => a.id === req.params.id)
 | 
				
			||||||
    if (!audiobook) return res.sendStatus(404)
 | 
					    if (!audiobook) return res.sendStatus(404)
 | 
				
			||||||
    var files = req.body.files
 | 
					    var orderedFileData = req.body.orderedFileData
 | 
				
			||||||
    Logger.info(`Updating audiobook tracks called ${audiobook.id}`)
 | 
					    Logger.info(`Updating audiobook tracks called ${audiobook.id}`)
 | 
				
			||||||
    audiobook.updateAudioTracks(files)
 | 
					    audiobook.updateAudioTracks(orderedFileData)
 | 
				
			||||||
    await this.db.updateAudiobook(audiobook)
 | 
					    await this.db.updateAudiobook(audiobook)
 | 
				
			||||||
    this.emitter('audiobook_updated', audiobook.toJSONMinified())
 | 
					    this.emitter('audiobook_updated', audiobook.toJSONMinified())
 | 
				
			||||||
    res.json(audiobook.toJSON())
 | 
					    res.json(audiobook.toJSON())
 | 
				
			||||||
 | 
				
			|||||||
@ -25,7 +25,8 @@ class FolderWatcher extends EventEmitter {
 | 
				
			|||||||
        .on('add', (path) => {
 | 
					        .on('add', (path) => {
 | 
				
			||||||
          this.onNewFile(path)
 | 
					          this.onNewFile(path)
 | 
				
			||||||
        }).on('change', (path) => {
 | 
					        }).on('change', (path) => {
 | 
				
			||||||
          this.onFileUpdated(path)
 | 
					          // This is triggered from metadata changes, not what we want
 | 
				
			||||||
 | 
					          // this.onFileUpdated(path)
 | 
				
			||||||
        }).on('unlink', path => {
 | 
					        }).on('unlink', path => {
 | 
				
			||||||
          this.onFileRemoved(path)
 | 
					          this.onFileRemoved(path)
 | 
				
			||||||
        }).on('rename', (path, pathNext) => {
 | 
					        }).on('rename', (path, pathNext) => {
 | 
				
			||||||
 | 
				
			|||||||
@ -29,6 +29,7 @@ class AudioFile {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    this.manuallyVerified = false
 | 
					    this.manuallyVerified = false
 | 
				
			||||||
    this.invalid = false
 | 
					    this.invalid = false
 | 
				
			||||||
 | 
					    this.exclude = false
 | 
				
			||||||
    this.error = null
 | 
					    this.error = null
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (data) {
 | 
					    if (data) {
 | 
				
			||||||
@ -49,6 +50,7 @@ class AudioFile {
 | 
				
			|||||||
      trackNumFromFilename: this.trackNumFromFilename,
 | 
					      trackNumFromFilename: this.trackNumFromFilename,
 | 
				
			||||||
      manuallyVerified: !!this.manuallyVerified,
 | 
					      manuallyVerified: !!this.manuallyVerified,
 | 
				
			||||||
      invalid: !!this.invalid,
 | 
					      invalid: !!this.invalid,
 | 
				
			||||||
 | 
					      exclude: !!this.exclude,
 | 
				
			||||||
      error: this.error || null,
 | 
					      error: this.error || null,
 | 
				
			||||||
      format: this.format,
 | 
					      format: this.format,
 | 
				
			||||||
      duration: this.duration,
 | 
					      duration: this.duration,
 | 
				
			||||||
@ -76,6 +78,7 @@ class AudioFile {
 | 
				
			|||||||
    this.addedAt = data.addedAt
 | 
					    this.addedAt = data.addedAt
 | 
				
			||||||
    this.manuallyVerified = !!data.manuallyVerified
 | 
					    this.manuallyVerified = !!data.manuallyVerified
 | 
				
			||||||
    this.invalid = !!data.invalid
 | 
					    this.invalid = !!data.invalid
 | 
				
			||||||
 | 
					    this.exclude = !!data.exclude
 | 
				
			||||||
    this.error = data.error || null
 | 
					    this.error = data.error || null
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    this.trackNumFromMeta = data.trackNumFromMeta || null
 | 
					    this.trackNumFromMeta = data.trackNumFromMeta || null
 | 
				
			||||||
@ -112,6 +115,7 @@ class AudioFile {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    this.manuallyVerified = !!data.manuallyVerified
 | 
					    this.manuallyVerified = !!data.manuallyVerified
 | 
				
			||||||
    this.invalid = !!data.invalid
 | 
					    this.invalid = !!data.invalid
 | 
				
			||||||
 | 
					    this.exclude = !!data.exclude
 | 
				
			||||||
    this.error = data.error || null
 | 
					    this.error = data.error || null
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    this.format = data.format
 | 
					    this.format = data.format
 | 
				
			||||||
@ -131,6 +135,10 @@ class AudioFile {
 | 
				
			|||||||
    this.tagTrack = data.file_tag_track || null
 | 
					    this.tagTrack = data.file_tag_track || null
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  clone() {
 | 
				
			||||||
 | 
					    return new AudioFile(this.toJSON())
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  syncFile(newFile) {
 | 
					  syncFile(newFile) {
 | 
				
			||||||
    var hasUpdates = false
 | 
					    var hasUpdates = false
 | 
				
			||||||
    var keysToSync = ['path', 'fullPath', 'ext', 'filename']
 | 
					    var keysToSync = ['path', 'fullPath', 'ext', 'filename']
 | 
				
			||||||
 | 
				
			|||||||
@ -57,14 +57,14 @@ class Audiobook {
 | 
				
			|||||||
    return this.book ? this.book.title : 'No Title'
 | 
					    return this.book ? this.book.title : 'No Title'
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  get cover() {
 | 
					 | 
				
			||||||
    return this.book ? this.book.cover : ''
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  get author() {
 | 
					  get author() {
 | 
				
			||||||
    return this.book ? this.book.author : 'Unknown'
 | 
					    return this.book ? this.book.author : 'Unknown'
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  get cover() {
 | 
				
			||||||
 | 
					    return this.book ? this.book.cover : ''
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  get authorLF() {
 | 
					  get authorLF() {
 | 
				
			||||||
    return this.book ? this.book.authorLF : null
 | 
					    return this.book ? this.book.authorLF : null
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@ -273,19 +273,32 @@ class Audiobook {
 | 
				
			|||||||
    return hasUpdates
 | 
					    return hasUpdates
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  updateAudioTracks(files) {
 | 
					  updateAudioTracks(orderedFileData) {
 | 
				
			||||||
    var index = 1
 | 
					    var index = 1
 | 
				
			||||||
    this.audioFiles = files.map((file) => {
 | 
					    this.audioFiles = orderedFileData.map((fileData) => {
 | 
				
			||||||
      file.manuallyVerified = true
 | 
					      var audioFile = this.audioFiles.find(af => af.ino === fileData.ino)
 | 
				
			||||||
      file.invalid = false
 | 
					      audioFile.manuallyVerified = true
 | 
				
			||||||
      file.error = null
 | 
					      audioFile.invalid = false
 | 
				
			||||||
      file.index = index++
 | 
					      audioFile.error = null
 | 
				
			||||||
      return new AudioFile(file)
 | 
					      if (fileData.exclude !== undefined) {
 | 
				
			||||||
 | 
					        audioFile.exclude = !!fileData.exclude
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      if (audioFile.exclude) {
 | 
				
			||||||
 | 
					        audioFile.index = -1
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        audioFile.index = index++
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      return audioFile
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    this.audioFiles.sort((a, b) => a.index - b.index)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    this.tracks = []
 | 
					    this.tracks = []
 | 
				
			||||||
    this.missingParts = []
 | 
					    this.missingParts = []
 | 
				
			||||||
    this.audioFiles.forEach((file) => {
 | 
					    this.audioFiles.forEach((file) => {
 | 
				
			||||||
 | 
					      if (!file.exclude) {
 | 
				
			||||||
        this.addTrack(file)
 | 
					        this.addTrack(file)
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
    this.lastUpdate = Date.now()
 | 
					    this.lastUpdate = Date.now()
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
				
			|||||||
@ -66,8 +66,15 @@ function getTrackNumberFromMeta(scanData) {
 | 
				
			|||||||
  return !isNaN(scanData.trackNumber) && scanData.trackNumber !== null ? Number(scanData.trackNumber) : null
 | 
					  return !isNaN(scanData.trackNumber) && scanData.trackNumber !== null ? Number(scanData.trackNumber) : null
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function getTrackNumberFromFilename(filename) {
 | 
					function getTrackNumberFromFilename(title, author, series, publishYear, filename) {
 | 
				
			||||||
  var partbasename = Path.basename(filename, Path.extname(filename))
 | 
					  var partbasename = Path.basename(filename, Path.extname(filename))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Remove title, author, series, and publishYear from filename if there
 | 
				
			||||||
 | 
					  if (title) partbasename = partbasename.replace(title, '')
 | 
				
			||||||
 | 
					  if (author) partbasename = partbasename.replace(author, '')
 | 
				
			||||||
 | 
					  if (series) partbasename = partbasename.replace(series, '')
 | 
				
			||||||
 | 
					  if (publishYear) partbasename = partbasename.replace(publishYear)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  var numbersinpath = partbasename.match(/\d+/g)
 | 
					  var numbersinpath = partbasename.match(/\d+/g)
 | 
				
			||||||
  if (!numbersinpath) return null
 | 
					  if (!numbersinpath) return null
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -92,7 +99,8 @@ async function scanAudioFiles(audiobook, newAudioFiles) {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    var trackNumFromMeta = getTrackNumberFromMeta(scanData)
 | 
					    var trackNumFromMeta = getTrackNumberFromMeta(scanData)
 | 
				
			||||||
    var trackNumFromFilename = getTrackNumberFromFilename(audioFile.filename)
 | 
					    var book = audiobook.book || {}
 | 
				
			||||||
 | 
					    var trackNumFromFilename = getTrackNumberFromFilename(book.title, book.author, book.series, book.publishYear, audioFile.filename)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    var audioFileObj = {
 | 
					    var audioFileObj = {
 | 
				
			||||||
      ino: audioFile.ino,
 | 
					      ino: audioFile.ino,
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user