mirror of
				https://github.com/advplyr/audiobookshelf.git
				synced 2025-11-04 03:17:00 -05:00 
			
		
		
		
	Add:Server setting to ignore "The" infront of titles and series when sorting #361
This commit is contained in:
		
							parent
							
								
									e0a6631396
								
							
						
					
					
						commit
						f15be4c96e
					
				@ -4,7 +4,7 @@
 | 
			
		||||
      <div :key="shelf" :id="`shelf-${shelf - 1}`" class="w-full px-4 sm:px-8 relative" :class="{ bookshelfRow: !isAlternativeBookshelfView }" :style="{ height: shelfHeight + 'px' }">
 | 
			
		||||
        <!-- <div class="absolute top-0 left-0 bottom-0 p-4 z-10">
 | 
			
		||||
          <p class="text-white text-2xl">{{ shelf }}</p>
 | 
			
		||||
        </div> -->
 | 
			
		||||
        </div>-->
 | 
			
		||||
        <div v-if="!isAlternativeBookshelfView" class="bookshelfDivider w-full absolute bottom-0 left-0 right-0 z-20" :class="`h-${shelfDividerHeightIndex}`" />
 | 
			
		||||
      </div>
 | 
			
		||||
    </template>
 | 
			
		||||
@ -26,7 +26,9 @@
 | 
			
		||||
    <widgets-cover-size-widget class="fixed bottom-4 right-4 z-30" />
 | 
			
		||||
    <!-- Experimental Bookshelf Texture -->
 | 
			
		||||
    <div v-show="showExperimentalFeatures" class="fixed bottom-4 right-28 z-40">
 | 
			
		||||
      <div class="rounded-full py-1 bg-primary hover:bg-bg cursor-pointer px-2 border border-black-100 text-center flex items-center box-shadow-md" @mousedown.prevent @mouseup.prevent @click="showBookshelfTextureModal"><p class="text-sm py-0.5">Texture</p></div>
 | 
			
		||||
      <div class="rounded-full py-1 bg-primary hover:bg-bg cursor-pointer px-2 border border-black-100 text-center flex items-center box-shadow-md" @mousedown.prevent @mouseup.prevent @click="showBookshelfTextureModal">
 | 
			
		||||
        <p class="text-sm py-0.5">Texture</p>
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
@ -245,7 +247,7 @@ export default {
 | 
			
		||||
        console.error('failed to fetch books', error)
 | 
			
		||||
        return null
 | 
			
		||||
      })
 | 
			
		||||
      console.log('payload', payload)
 | 
			
		||||
 | 
			
		||||
      this.isFetchingEntities = false
 | 
			
		||||
      if (this.pendingReset) {
 | 
			
		||||
        this.pendingReset = false
 | 
			
		||||
 | 
			
		||||
@ -10,24 +10,38 @@
 | 
			
		||||
      <div class="flex items-center py-2">
 | 
			
		||||
        <ui-toggle-switch v-model="storeCoversInAudiobookDir" :disabled="updatingServerSettings" @input="updateCoverStorageDestination" />
 | 
			
		||||
        <ui-tooltip :text="coverDestinationTooltip">
 | 
			
		||||
          <p class="pl-4 text-lg">Store covers with audiobook <span class="material-icons icon-text">info_outlined</span></p>
 | 
			
		||||
          <p class="pl-4 text-lg">
 | 
			
		||||
            Store covers with audiobook
 | 
			
		||||
            <span class="material-icons icon-text">info_outlined</span>
 | 
			
		||||
          </p>
 | 
			
		||||
        </ui-tooltip>
 | 
			
		||||
      </div>
 | 
			
		||||
 | 
			
		||||
      <div class="flex items-center py-2">
 | 
			
		||||
        <ui-toggle-switch v-model="useSquareBookCovers" :disabled="updatingServerSettings" @input="updateBookCoverAspectRatio" />
 | 
			
		||||
        <ui-tooltip :text="coverAspectRatioTooltip">
 | 
			
		||||
          <p class="pl-4 text-lg">Use square book covers <span class="material-icons icon-text">info_outlined</span></p>
 | 
			
		||||
          <p class="pl-4 text-lg">
 | 
			
		||||
            Use square book covers
 | 
			
		||||
            <span class="material-icons icon-text">info_outlined</span>
 | 
			
		||||
          </p>
 | 
			
		||||
        </ui-tooltip>
 | 
			
		||||
      </div>
 | 
			
		||||
 | 
			
		||||
      <div class="flex items-center py-2">
 | 
			
		||||
        <ui-toggle-switch v-model="useAlternativeBookshelfView" :disabled="updatingServerSettings" @input="updateAlternativeBookshelfView" />
 | 
			
		||||
        <ui-tooltip :text="bookshelfViewTooltip">
 | 
			
		||||
          <p class="pl-4 text-lg">Use alternative library bookshelf view <span class="material-icons icon-text">info_outlined</span></p>
 | 
			
		||||
          <p class="pl-4 text-lg">
 | 
			
		||||
            Use alternative library bookshelf view
 | 
			
		||||
            <span class="material-icons icon-text">info_outlined</span>
 | 
			
		||||
          </p>
 | 
			
		||||
        </ui-tooltip>
 | 
			
		||||
      </div>
 | 
			
		||||
 | 
			
		||||
      <div class="flex items-center py-2">
 | 
			
		||||
        <ui-toggle-switch v-model="newServerSettings.sortingIgnorePrefix" :disabled="updatingServerSettings" @input="updateSortIgnorePrefix" />
 | 
			
		||||
        <p class="pl-4 text-lg">Ignore prefix "The" when sorting title and series</p>
 | 
			
		||||
      </div>
 | 
			
		||||
 | 
			
		||||
      <div class="flex items-center mb-2 mt-8">
 | 
			
		||||
        <h1 class="text-xl">Scanner Settings</h1>
 | 
			
		||||
      </div>
 | 
			
		||||
@ -35,14 +49,20 @@
 | 
			
		||||
      <div class="flex items-center py-2">
 | 
			
		||||
        <ui-toggle-switch v-model="newServerSettings.scannerParseSubtitle" small :disabled="updatingServerSettings" @input="updateScannerParseSubtitle" />
 | 
			
		||||
        <ui-tooltip :text="parseSubtitleTooltip">
 | 
			
		||||
          <p class="pl-4 text-lg">Scanner parse subtitles <span class="material-icons icon-text">info_outlined</span></p>
 | 
			
		||||
          <p class="pl-4 text-lg">
 | 
			
		||||
            Scanner parse subtitles
 | 
			
		||||
            <span class="material-icons icon-text">info_outlined</span>
 | 
			
		||||
          </p>
 | 
			
		||||
        </ui-tooltip>
 | 
			
		||||
      </div>
 | 
			
		||||
 | 
			
		||||
      <div class="flex items-center py-2">
 | 
			
		||||
        <ui-toggle-switch v-model="newServerSettings.scannerFindCovers" :disabled="updatingServerSettings" @input="updateScannerFindCovers" />
 | 
			
		||||
        <ui-tooltip :text="scannerFindCoversTooltip">
 | 
			
		||||
          <p class="pl-4 text-lg">Scanner find covers <span class="material-icons icon-text">info_outlined</span></p>
 | 
			
		||||
          <p class="pl-4 text-lg">
 | 
			
		||||
            Scanner find covers
 | 
			
		||||
            <span class="material-icons icon-text">info_outlined</span>
 | 
			
		||||
          </p>
 | 
			
		||||
        </ui-tooltip>
 | 
			
		||||
        <div class="flex-grow" />
 | 
			
		||||
      </div>
 | 
			
		||||
@ -53,14 +73,20 @@
 | 
			
		||||
      <div class="flex items-center py-2">
 | 
			
		||||
        <ui-toggle-switch v-model="newServerSettings.scannerPreferAudioMetadata" :disabled="updatingServerSettings" @input="updateScannerPreferAudioMeta" />
 | 
			
		||||
        <ui-tooltip :text="scannerPreferAudioMetaTooltip">
 | 
			
		||||
          <p class="pl-4 text-lg">Scanner prefer audio metadata <span class="material-icons icon-text">info_outlined</span></p>
 | 
			
		||||
          <p class="pl-4 text-lg">
 | 
			
		||||
            Scanner prefer audio metadata
 | 
			
		||||
            <span class="material-icons icon-text">info_outlined</span>
 | 
			
		||||
          </p>
 | 
			
		||||
        </ui-tooltip>
 | 
			
		||||
      </div>
 | 
			
		||||
 | 
			
		||||
      <div class="flex items-center py-2">
 | 
			
		||||
        <ui-toggle-switch v-model="newServerSettings.scannerPreferOpfMetadata" :disabled="updatingServerSettings" @input="updateScannerPreferOpfMeta" />
 | 
			
		||||
        <ui-tooltip :text="scannerPreferOpfMetaTooltip">
 | 
			
		||||
          <p class="pl-4 text-lg">Scanner prefer OPF metadata <span class="material-icons icon-text">info_outlined</span></p>
 | 
			
		||||
          <p class="pl-4 text-lg">
 | 
			
		||||
            Scanner prefer OPF metadata
 | 
			
		||||
            <span class="material-icons icon-text">info_outlined</span>
 | 
			
		||||
          </p>
 | 
			
		||||
        </ui-tooltip>
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
@ -71,7 +97,10 @@
 | 
			
		||||
      <ui-btn color="bg" small :padding-x="4" class="hidden lg:block mr-2" :loading="isPurgingCache" @click="purgeCache">Purge Cache</ui-btn>
 | 
			
		||||
      <ui-btn color="bg" small :padding-x="4" class="hidden lg:block" :loading="isResettingAudiobooks" @click="resetAudiobooks">Remove All Audiobooks</ui-btn>
 | 
			
		||||
      <div class="flex-grow" />
 | 
			
		||||
      <p class="pr-2 text-sm font-book text-yellow-400">Report bugs, request features, provide feedback, and contribute on <a class="underline" href="https://github.com/advplyr/audiobookshelf" target="_blank">github</a>.</p>
 | 
			
		||||
      <p class="pr-2 text-sm font-book text-yellow-400">
 | 
			
		||||
        Report bugs, request features, provide feedback, and contribute on
 | 
			
		||||
        <a class="underline" href="https://github.com/advplyr/audiobookshelf" target="_blank">github</a>.
 | 
			
		||||
      </p>
 | 
			
		||||
      <a href="https://github.com/advplyr/audiobookshelf" target="_blank" class="text-white hover:text-gray-200 hover:scale-150 hover:rotate-6 transform duration-500">
 | 
			
		||||
        <svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" width="24" height="24" viewBox="0 0 24 24">
 | 
			
		||||
          <path
 | 
			
		||||
@ -89,13 +118,16 @@
 | 
			
		||||
          <div class="flex items-center">
 | 
			
		||||
            <ui-toggle-switch v-model="showExperimentalFeatures" />
 | 
			
		||||
            <ui-tooltip :text="experimentalFeaturesTooltip">
 | 
			
		||||
              <p class="pl-4 text-lg">Experimental Features <span class="material-icons icon-text">info_outlined</span></p>
 | 
			
		||||
              <p class="pl-4 text-lg">
 | 
			
		||||
                Experimental Features
 | 
			
		||||
                <span class="material-icons icon-text">info_outlined</span>
 | 
			
		||||
              </p>
 | 
			
		||||
            </ui-tooltip>
 | 
			
		||||
          </div>
 | 
			
		||||
        </div>
 | 
			
		||||
        <!-- <div class="hidden md:block">
 | 
			
		||||
          <a href="https://github.com/advplyr/audiobookshelf/discussions/75#discussion-3604812" target="_blank" class="text-blue-500 hover:text-blue-300 underline">Join the discussion</a>
 | 
			
		||||
        </div> -->
 | 
			
		||||
        </div>-->
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
  </div>
 | 
			
		||||
@ -166,6 +198,11 @@ export default {
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    updateSortIgnorePrefix(val) {
 | 
			
		||||
      this.updateServerSettings({
 | 
			
		||||
        sortingIgnorePrefix: val
 | 
			
		||||
      })
 | 
			
		||||
    },
 | 
			
		||||
    updateScannerFindCovers(val) {
 | 
			
		||||
      this.updateServerSettings({
 | 
			
		||||
        scannerFindCovers: !!val
 | 
			
		||||
 | 
			
		||||
@ -144,10 +144,19 @@ class LibraryController {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (payload.sortBy) {
 | 
			
		||||
      var sortKey = payload.sortBy
 | 
			
		||||
 | 
			
		||||
      // Handle server setting sortingIgnorePrefix
 | 
			
		||||
      if ((sortKey === 'book.series' || sortKey === 'book.title') && this.db.serverSettings.sortingIgnorePrefix) {
 | 
			
		||||
        // Book.js has seriesIgnorePrefix and titleIgnorePrefix getters
 | 
			
		||||
        sortKey += 'IgnorePrefix'
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      var direction = payload.sortDesc ? 'desc' : 'asc'
 | 
			
		||||
      audiobooks = naturalSort(audiobooks)[direction]((ab) => {
 | 
			
		||||
 | 
			
		||||
        // Supports dot notation strings i.e. "book.title"
 | 
			
		||||
        return payload.sortBy.split('.').reduce((a, b) => a[b], ab)
 | 
			
		||||
        return sortKey.split('.').reduce((a, b) => a[b], ab)
 | 
			
		||||
      })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -202,7 +211,14 @@ class LibraryController {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    var series = libraryHelpers.getSeriesFromBooks(audiobooks, payload.minified)
 | 
			
		||||
    series = sort(series).asc(s => s.name)
 | 
			
		||||
 | 
			
		||||
    var sortingIgnorePrefix = this.db.serverSettings.sortingIgnorePrefix
 | 
			
		||||
    series = sort(series).asc(s => {
 | 
			
		||||
      if (sortingIgnorePrefix && s.name.toLowerCase().startsWith('the')) {
 | 
			
		||||
        return s.name.substr(4)
 | 
			
		||||
      }
 | 
			
		||||
      return s.name
 | 
			
		||||
    })
 | 
			
		||||
    payload.total = series.length
 | 
			
		||||
 | 
			
		||||
    if (payload.limit) {
 | 
			
		||||
 | 
			
		||||
@ -49,6 +49,20 @@ class Book {
 | 
			
		||||
  get _asin() { return this.asin || '' }
 | 
			
		||||
  get genresCommaSeparated() { return this._genres.join(', ') }
 | 
			
		||||
 | 
			
		||||
  get titleIgnorePrefix() {
 | 
			
		||||
    if (this._title.toLowerCase().startsWith('the ')) {
 | 
			
		||||
      return this._title.substr(4) + ', The'
 | 
			
		||||
    }
 | 
			
		||||
    return this._title
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  get seriesIgnorePrefix() {
 | 
			
		||||
    if (this._series.toLowerCase().startsWith('the ')) {
 | 
			
		||||
      return this._series.substr(4) + ', The'
 | 
			
		||||
    }
 | 
			
		||||
    return this._series
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  get shouldSearchForCover() {
 | 
			
		||||
    if (this.cover) return false
 | 
			
		||||
    if (this.authorFL !== this.lastCoverSearchAuthor || this.title !== this.lastCoverSearchTitle || !this.lastCoverSearch) return true
 | 
			
		||||
 | 
			
		||||
@ -38,6 +38,8 @@ class ServerSettings {
 | 
			
		||||
    this.coverAspectRatio = BookCoverAspectRatio.SQUARE
 | 
			
		||||
    this.bookshelfView = BookshelfView.STANDARD
 | 
			
		||||
 | 
			
		||||
    this.sortingIgnorePrefix = false
 | 
			
		||||
 | 
			
		||||
    this.logLevel = Logger.logLevel
 | 
			
		||||
    this.version = null
 | 
			
		||||
 | 
			
		||||
@ -70,6 +72,8 @@ class ServerSettings {
 | 
			
		||||
    this.coverAspectRatio = !isNaN(settings.coverAspectRatio) ? settings.coverAspectRatio : BookCoverAspectRatio.SQUARE
 | 
			
		||||
    this.bookshelfView = settings.bookshelfView || BookshelfView.STANDARD
 | 
			
		||||
 | 
			
		||||
    this.sortingIgnorePrefix = !!settings.sortingIgnorePrefix
 | 
			
		||||
 | 
			
		||||
    this.logLevel = settings.logLevel || Logger.logLevel
 | 
			
		||||
    this.version = settings.version || null
 | 
			
		||||
 | 
			
		||||
@ -99,6 +103,7 @@ class ServerSettings {
 | 
			
		||||
      loggerScannerLogsToKeep: this.loggerScannerLogsToKeep,
 | 
			
		||||
      coverAspectRatio: this.coverAspectRatio,
 | 
			
		||||
      bookshelfView: this.bookshelfView,
 | 
			
		||||
      sortingIgnorePrefix: this.sortingIgnorePrefix,
 | 
			
		||||
      logLevel: this.logLevel,
 | 
			
		||||
      version: this.version
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -1,9 +1,4 @@
 | 
			
		||||
const ffprobe = require('node-ffprobe')
 | 
			
		||||
 | 
			
		||||
if (process.env.FFPROBE_PATH) {
 | 
			
		||||
  ffprobe.FFPROBE_PATH = process.env.FFPROBE_PATH
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const AudioProbeData = require('../scanner/AudioProbeData')
 | 
			
		||||
 | 
			
		||||
const Logger = require('../Logger')
 | 
			
		||||
@ -281,6 +276,10 @@ function parseProbeData(data, verbose = false) {
 | 
			
		||||
 | 
			
		||||
// Updated probe returns AudioProbeData object
 | 
			
		||||
function probe(filepath, verbose = false) {
 | 
			
		||||
  if (process.env.FFPROBE_PATH) {
 | 
			
		||||
    ffprobe.FFPROBE_PATH = process.env.FFPROBE_PATH
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return ffprobe(filepath)
 | 
			
		||||
    .then(raw => {
 | 
			
		||||
      var rawProbeData = parseProbeData(raw, verbose)
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user