diff --git a/.devcontainer/dev.js b/.devcontainer/dev.js index b5f6714e..28c0074b 100644 --- a/.devcontainer/dev.js +++ b/.devcontainer/dev.js @@ -6,5 +6,5 @@ module.exports.config = { MetadataPath: Path.resolve('metadata'), FFmpegPath: '/usr/bin/ffmpeg', FFProbePath: '/usr/bin/ffprobe', - SkipBinariesCheck: false + SkipBinariesCheck: true } \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/bug.yaml b/.github/ISSUE_TEMPLATE/bug.yaml index 7f47d710..89aec401 100644 --- a/.github/ISSUE_TEMPLATE/bug.yaml +++ b/.github/ISSUE_TEMPLATE/bug.yaml @@ -1,40 +1,50 @@ name: 🐞 Bug Report -description: File a bug/issue -title: "[Bug]: " -labels: ["bug", "triage"] +description: File a bug/issue and help us improve Audiobookshelf +title: '[Bug]: ' +labels: ['bug', 'triage'] body: - type: markdown attributes: - value: "### Please first search for your issue and check the [docs](https://audiobookshelf.org/docs)." + value: 'Thank you for filing a bug report! 🐛' - type: markdown attributes: - value: "### Mobile app issues report [here](https://github.com/advplyr/audiobookshelf-app/issues/new/choose)." + value: 'Please first search for your issue and check the [docs](https://audiobookshelf.org/docs).' - type: markdown attributes: - value: "### Join the [discord server](https://discord.gg/HQgCbd6E75) for questions or if you are not sure about a bug." + value: 'Report issues with the mobile app [here](https://github.com/advplyr/audiobookshelf-app/issues/new/choose).' - type: markdown attributes: - value: "## Be as descriptive as you can. Include screenshots, error logs, browser, file types, everything you can think of that might be relevant." + value: 'Join the [discord server](https://discord.gg/HQgCbd6E75) for questions or if you are not sure about a bug.' - type: textarea id: what-happened attributes: - label: Describe the issue - description: What happened & what did you expect to happen + label: What happened? + placeholder: Tell us what you see! + validations: + required: true + - type: textarea + id: what-was-expected + attributes: + label: What did you expect to happen? + placeholder: Tell us what you expected to see! Be as descriptive as you can and include screenshots if applicable. validations: required: true - type: textarea id: steps-to-reproduce attributes: label: Steps to reproduce the issue - value: "1. " + value: '1. ' validations: required: true + - type: markdown + attributes: + value: '## Install Environment' - type: input id: version attributes: label: Audiobookshelf version description: Do not put 'Latest version', please put the actual version here - placeholder: "e.g. v1.6.60" + placeholder: 'e.g. v1.6.60' validations: required: true - type: dropdown @@ -46,6 +56,43 @@ body: - Debian/PPA - Windows Tray App - Built from source - - Other + - Other (list in "Additional Notes" box) validations: - required: true + required: true + - type: dropdown + id: server-os + attributes: + label: What OS is your Audiobookshelf server hosted from? + options: + - Windows + - macOS + - Linux + - Other (list in "Additional Notes" box) + validations: + required: true + - type: dropdown + id: desktop-browsers + attributes: + label: If the issue is being seen in the UI, what browsers are you seeing the problem on? + options: + - Chrome + - Firefox + - Safari + - Edge + - Firefox for Android + - Chrome for Android + - Safari on iOS + - Other (list in "Additional Notes" box) + - type: textarea + id: logs + attributes: + label: Logs + description: Please include any relevant logs here. This field is automatically formatted into code, so you do not need to include any backticks. + placeholder: Paste logs here + render: shell + - type: textarea + id: additional-notes + attributes: + label: Additional Notes + description: Anything else you want to add? + placeholder: 'e.g. I have tried X, Y, and Z.' diff --git a/.github/ISSUE_TEMPLATE/feature.yml b/.github/ISSUE_TEMPLATE/feature.yml index 75363c0e..76888091 100644 --- a/.github/ISSUE_TEMPLATE/feature.yml +++ b/.github/ISSUE_TEMPLATE/feature.yml @@ -1,17 +1,63 @@ name: 🚀 Feature Request description: Request a feature/enhancement -title: "[Enhancement]: " -labels: ["enhancement"] +title: '[Enhancement]: ' +labels: ['enhancement'] body: - type: markdown attributes: - value: "### Please first search in both issues & discussions for your enhancement." + value: '#### *Mobile app features should be [requested here](https://github.com/advplyr/audiobookshelf-app/issues/new/choose)*.' - type: markdown attributes: - value: "### Mobile app features should be requested [here](https://github.com/advplyr/audiobookshelf-app/issues/new/choose)." + value: '## Web/Server Feature Request Description' + - type: markdown + attributes: + value: 'Please first search in both issues & discussions for your enhancement.' + - type: dropdown + id: enhancment-type + attributes: + label: Type of Enhancement + options: + - Server Backend + - Web Interface/Frontend + - Documentation - type: textarea id: describe attributes: - label: Describe the feature/enhancement + label: Describe the Feature/Enhancement + description: Please help us understand what you want. + placeholder: What is your vision? validations: required: true + - type: textarea + id: the-why + attributes: + label: Why would this be helpful? + description: Please help us understand why this would enhance your experience. + placeholder: Explain the "why" or "use case". + validations: + required: true + - type: textarea + id: image + attributes: + label: Future Implementation (Screenshot) + description: Please help us visualize by including a doodle or screenshot. + placeholder: How could this look? + validations: + required: true + - type: markdown + attributes: + value: '## Web/Server Current Implementation' + - type: input + id: version + attributes: + label: Audiobookshelf Server Version + description: Do not put 'Latest version', please put your current version number here + placeholder: 'e.g. v1.6.60' + validations: + required: true + - type: textarea + id: current-image + attributes: + label: Current Implementation (Screenshot) + description: What page were you looking at when you thought of this enhancement? + placeholder: If an image is not applicable, please explain why. diff --git a/client/components/app/BookShelfCategorized.vue b/client/components/app/BookShelfCategorized.vue index eb4e9424..0c4562a4 100644 --- a/client/components/app/BookShelfCategorized.vue +++ b/client/components/app/BookShelfCategorized.vue @@ -4,10 +4,10 @@
-

{{ libraryName }} Library is empty!

+

{{ $getString('MessageXLibraryIsEmpty', [libraryName]) }}

- Configure Scanner - Scan Library + {{ $strings.ButtonConfigureScanner }} + {{ $strings.ButtonScanLibrary }}
@@ -58,7 +58,8 @@ export default { scannerParseSubtitle: false, wrapperClientWidth: 0, shelves: [], - lastItemIndexSelected: -1 + lastItemIndexSelected: -1, + tempIsScanning: false } }, computed: { @@ -97,6 +98,9 @@ export default { }, streamLibraryItem() { return this.$store.state.streamLibraryItem + }, + isScanningLibrary() { + return !!this.$store.getters['tasks/getRunningLibraryScanTask'](this.currentLibraryId) } }, methods: { @@ -273,14 +277,15 @@ export default { this.shelves = shelves }, scan() { + this.tempIsScanning = true this.$store .dispatch('libraries/requestLibraryScan', { libraryId: this.$store.state.libraries.currentLibraryId }) - .then(() => { - this.$toast.success('Library scan started') - }) .catch((error) => { console.error('Failed to start scan', error) - this.$toast.error('Failed to start scan') + this.$toast.error(this.$strings.ToastLibraryScanFailedToStart) + }) + .finally(() => { + this.tempIsScanning = false }) }, userUpdated(user) { diff --git a/client/components/app/LazyBookshelf.vue b/client/components/app/LazyBookshelf.vue index 5291cdbb..805c6978 100644 --- a/client/components/app/LazyBookshelf.vue +++ b/client/components/app/LazyBookshelf.vue @@ -10,7 +10,7 @@

{{ $getString('MessageXLibraryIsEmpty', [libraryName]) }}

{{ $strings.ButtonConfigureScanner }} - {{ $strings.ButtonScanLibrary }} + {{ $strings.ButtonScanLibrary }}
@@ -62,7 +62,8 @@ export default { currScrollTop: 0, resizeTimeout: null, mountWindowWidth: 0, - lastItemIndexSelected: -1 + lastItemIndexSelected: -1, + tempIsScanning: false } }, watch: { @@ -208,6 +209,9 @@ export default { }, streamLibraryItem() { return this.$store.state.streamLibraryItem + }, + isScanningLibrary() { + return !!this.$store.getters['tasks/getRunningLibraryScanTask'](this.currentLibraryId) } }, methods: { @@ -727,14 +731,15 @@ export default { } }, scan() { + this.tempIsScanning = true this.$store .dispatch('libraries/requestLibraryScan', { libraryId: this.currentLibraryId }) - .then(() => { - this.$toast.success('Library scan started') - }) .catch((error) => { console.error('Failed to start scan', error) - this.$toast.error('Failed to start scan') + this.$toast.error(this.$strings.ToastLibraryScanFailedToStart) + }) + .finally(() => { + this.tempIsScanning = false }) } }, @@ -775,4 +780,4 @@ export default { background: var(--bookshelf-divider-bg); box-shadow: 2px 14px 8px #111111aa; } - \ No newline at end of file + diff --git a/client/components/app/MediaPlayerContainer.vue b/client/components/app/MediaPlayerContainer.vue index 3c4b1d35..e00d4554 100644 --- a/client/components/app/MediaPlayerContainer.vue +++ b/client/components/app/MediaPlayerContainer.vue @@ -6,9 +6,12 @@
- - {{ title }} - +
+ + {{ title }} + + +
person
@@ -18,7 +21,6 @@ {{ author.name }}
{{ $strings.LabelUnknown }}
-
@@ -136,7 +138,7 @@ export default { return this.streamLibraryItem?.mediaType === 'music' }, isExplicit() { - return this.mediaMetadata.explicit || false + return !!this.mediaMetadata.explicit }, mediaMetadata() { return this.media.metadata || {} diff --git a/client/components/cards/BookMatchCard.vue b/client/components/cards/BookMatchCard.vue index f2c15280..d5355e91 100644 --- a/client/components/cards/BookMatchCard.vue +++ b/client/components/cards/BookMatchCard.vue @@ -13,9 +13,9 @@

{{ book.publishedYear }}

-

by {{ book.author }}

-

Narrated by {{ book.narrator }}

-

Runtime: {{ $elapsedPrettyExtended(bookDuration, false) }} {{ bookDurationComparison }}

+

{{ $getString('LabelByAuthor', [book.author]) }}

+

{{ $strings.LabelNarrators }}: {{ book.narrator }}

+

{{ $strings.LabelDuration }}: {{ $elapsedPrettyExtended(bookDuration, false) }} {{ bookDurationComparison }}

@@ -29,9 +29,9 @@

-
{{ book.title }}
+
{{ book.title }}

-

by {{ book.author }}

+

{{ $getString('LabelByAuthor', [book.author]) }}

{{ book.genres.join(', ') }}

{{ book.trackCount }} Episodes

@@ -75,11 +75,11 @@ export default { let differenceInMinutes = currentBookDurationMinutes - this.book.duration if (differenceInMinutes < 0) { differenceInMinutes = Math.abs(differenceInMinutes) - return `(${this.$elapsedPrettyExtended(differenceInMinutes * 60, false, false)} shorter)` + return this.$getString('LabelDurationComparisonLonger', [this.$elapsedPrettyExtended(differenceInMinutes * 60, false, false)]) } else if (differenceInMinutes > 0) { - return `(${this.$elapsedPrettyExtended(differenceInMinutes * 60, false, false)} longer)` + return this.$getString('LabelDurationComparisonShorter', [this.$elapsedPrettyExtended(differenceInMinutes * 60, false, false)]) } - return '(exact match)' + return this.$strings.LabelDurationComparisonExactMatch } }, methods: { diff --git a/client/components/cards/ItemSearchCard.vue b/client/components/cards/ItemSearchCard.vue index f1b5bf3d..bfcac8f0 100644 --- a/client/components/cards/ItemSearchCard.vue +++ b/client/components/cards/ItemSearchCard.vue @@ -7,7 +7,7 @@

-

by {{ authorName }}

+

{{ $getString('LabelByAuthor', [authorName]) }}

@@ -69,7 +69,7 @@ export default { if (this.matchKey === 'episode') return `

${this.$strings.LabelEpisode}: ${html}

` if (this.matchKey === 'tags') return `

${this.$strings.LabelTags}: ${html}

` if (this.matchKey === 'subtitle') return `

${html}

` - if (this.matchKey === 'authors') return `by ${html}` + if (this.matchKey === 'authors') this.$getString('LabelByAuthor', [html]) if (this.matchKey === 'isbn') return `

ISBN: ${html}

` if (this.matchKey === 'asin') return `

ASIN: ${html}

` if (this.matchKey === 'series') return `

${this.$strings.LabelSeries}: ${html}

` @@ -90,4 +90,4 @@ export default { flex-direction: column; justify-content: center; } - \ No newline at end of file + diff --git a/client/components/cards/ItemUploadCard.vue b/client/components/cards/ItemUploadCard.vue index 075c0fd4..51503374 100644 --- a/client/components/cards/ItemUploadCard.vue +++ b/client/components/cards/ItemUploadCard.vue @@ -21,15 +21,16 @@
-
+
sync
-

{{ $strings.LabelDirectory }} (auto)

+

+ {{ $strings.LabelDirectory }} + (auto) +

@@ -40,7 +41,10 @@
- +
@@ -51,10 +55,10 @@ -

{{ $strings.MessageUploaderItemSuccess }}

+

"{{ itemData.title }}" {{ $strings.MessageUploaderItemSuccess }}

-

{{ $strings.MessageUploaderItemFailed }}

+

"{{ itemData.title }}" {{ $strings.MessageUploaderItemFailed }}

@@ -70,7 +74,7 @@ export default { props: { item: { type: Object, - default: () => { } + default: () => {} }, mediaType: String, processing: Boolean, @@ -99,7 +103,7 @@ export default { if (this.isPodcast) return this.itemData.title const outputPathParts = [this.itemData.author, this.itemData.series, this.itemData.title] - const cleanedOutputPathParts = outputPathParts.filter(Boolean).map(part => this.$sanitizeFilename(part)) + const cleanedOutputPathParts = outputPathParts.filter(Boolean).map((part) => this.$sanitizeFilename(part)) return Path.join(...cleanedOutputPathParts) }, diff --git a/client/components/cards/LazyBookCard.vue b/client/components/cards/LazyBookCard.vue index faa93997..0bfac85f 100644 --- a/client/components/cards/LazyBookCard.vue +++ b/client/components/cards/LazyBookCard.vue @@ -1,128 +1,124 @@