diff --git a/.devcontainer/dev.js b/.devcontainer/dev.js
index 0d113a3e..28c0074b 100644
--- a/.devcontainer/dev.js
+++ b/.devcontainer/dev.js
@@ -5,5 +5,6 @@ module.exports.config = {
ConfigPath: Path.resolve('config'),
MetadataPath: Path.resolve('metadata'),
FFmpegPath: '/usr/bin/ffmpeg',
- FFProbePath: '/usr/bin/ffprobe'
+ FFProbePath: '/usr/bin/ffprobe',
+ SkipBinariesCheck: true
}
\ No newline at end of file
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 00000000..0efcc5b5
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,8 @@
+root = true
+
+[*]
+indent_style = space
+indent_size = 2
+charset = utf-8
+insert_final_newline = true
+trim_trailing_whitespace = 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/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
new file mode 100644
index 00000000..a77ab3e0
--- /dev/null
+++ b/.github/workflows/codeql.yml
@@ -0,0 +1,65 @@
+name: "CodeQL"
+
+on:
+ push:
+ branches: [ 'master' ]
+ pull_request:
+ # The branches below must be a subset of the branches above
+ branches: [ 'master' ]
+ schedule:
+ - cron: '16 5 * * 4'
+
+jobs:
+ analyze:
+ name: Analyze
+ runs-on: ubuntu-latest
+ permissions:
+ actions: read
+ contents: read
+ security-events: write
+
+ strategy:
+ fail-fast: false
+ matrix:
+ language: [ 'javascript' ]
+ # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
+ # Use only 'java' to analyze code written in Java, Kotlin or both
+ # Use only 'javascript' to analyze code written in JavaScript, TypeScript or both
+ # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v3
+
+ # Initializes the CodeQL tools for scanning.
+ - name: Initialize CodeQL
+ uses: github/codeql-action/init@v2
+ with:
+ languages: ${{ matrix.language }}
+ # If you wish to specify custom queries, you can do so here or in a config file.
+ # By default, queries listed here will override any specified in a config file.
+ # Prefix the list here with "+" to use these queries and those in the config file.
+
+ # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
+ # queries: security-extended,security-and-quality
+
+
+ # Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift).
+ # If this step fails, then you should remove it and run the build manually (see below)
+ - name: Autobuild
+ uses: github/codeql-action/autobuild@v2
+
+ # âšī¸ Command-line programs to run using the OS shell.
+ # đ See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
+
+ # If the Autobuild fails above, remove it and uncomment the following three lines.
+ # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
+
+ # - run: |
+ # echo "Run, Build Application using script"
+ # ./location_of_script_within_repo/buildscript.sh
+
+ - name: Perform CodeQL Analysis
+ uses: github/codeql-action/analyze@v2
+ with:
+ category: "/language:${{matrix.language}}"
diff --git a/.github/workflows/i18n-integration.yml b/.github/workflows/i18n-integration.yml
new file mode 100644
index 00000000..12d82c3e
--- /dev/null
+++ b/.github/workflows/i18n-integration.yml
@@ -0,0 +1,30 @@
+name: Verify all i18n files are alphabetized
+
+on:
+ pull_request:
+ paths:
+ - client/strings/** # Should only check if any strings changed
+ push:
+ paths:
+ - client/strings/** # Should only check if any strings changed
+
+jobs:
+ update_translations:
+ runs-on: ubuntu-latest
+ steps:
+ # Check out the repository
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ # Set up node to run the javascript
+ - name: Set up node
+ uses: actions/setup-node@v4
+ with:
+ node-version: "20"
+
+ # The only argument is the `directory`, which is where the i18n files are
+ # stored.
+ - name: Run Update JSON Files action
+ uses: audiobookshelf/audiobookshelf-i18n-updater@v1.2.0
+ with:
+ directory: "client/strings/" # Adjust the directory path as needed
diff --git a/.github/workflows/notify-abs-windows.yml b/.github/workflows/notify-abs-windows.yml
new file mode 100644
index 00000000..9ede33b8
--- /dev/null
+++ b/.github/workflows/notify-abs-windows.yml
@@ -0,0 +1,17 @@
+name: Dispatch an abs-windows event
+
+on:
+ release:
+ types: [published]
+ workflow_dispatch:
+
+jobs:
+ abs-windows-dispatch:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Send a remote repository dispatch event
+ uses: peter-evans/repository-dispatch@v3
+ with:
+ token: ${{ secrets.ABS_WINDOWS_PAT }}
+ repository: mikiher/audiobookshelf-windows
+ event-type: build-windows
diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml
new file mode 100644
index 00000000..695696c6
--- /dev/null
+++ b/.github/workflows/unit-tests.yml
@@ -0,0 +1,37 @@
+name: Run Unit Tests
+
+on:
+ workflow_dispatch:
+ inputs:
+ ref:
+ description: 'Branch/Tag/SHA to test'
+ required: true
+ pull_request:
+ push:
+
+jobs:
+ run-unit-tests:
+ name: Run Unit Tests
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout (push/pull request)
+ uses: actions/checkout@v4
+ if: github.event_name != 'workflow_dispatch'
+
+ - name: Checkout (workflow_dispatch)
+ uses: actions/checkout@v4
+ with:
+ ref: ${{ inputs.ref }}
+ if: github.event_name == 'workflow_dispatch'
+
+ - name: Set up Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version: 20
+
+ - name: Install dependencies
+ run: npm ci
+
+ - name: Run tests
+ run: npm test
diff --git a/.gitignore b/.gitignore
index 0690f38f..9ddb1a70 100644
--- a/.gitignore
+++ b/.gitignore
@@ -19,3 +19,4 @@
sw.*
.DS_STORE
.idea/*
+tailwind.compiled.css
\ No newline at end of file
diff --git a/.prettierrc b/.prettierrc
new file mode 100644
index 00000000..d3d0ff99
--- /dev/null
+++ b/.prettierrc
@@ -0,0 +1,17 @@
+{
+ "semi": false,
+ "singleQuote": true,
+ "printWidth": 400,
+ "proseWrap": "never",
+ "trailingComma": "none",
+ "overrides": [
+ {
+ "files": ["*.html"],
+ "options": {
+ "singleQuote": false,
+ "wrapAttributes": false,
+ "sortAttributes": false
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.vscode/extensions.json b/.vscode/extensions.json
new file mode 100644
index 00000000..d2a04598
--- /dev/null
+++ b/.vscode/extensions.json
@@ -0,0 +1,7 @@
+{
+ "recommendations": [
+ "EditorConfig.EditorConfig",
+ "esbenp.prettier-vscode",
+ "octref.vetur"
+ ]
+}
\ No newline at end of file
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 397b9618..75503e6a 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -17,5 +17,11 @@
"editor.formatOnSave": true,
"editor.detectIndentation": true,
"editor.tabSize": 2,
- "javascript.format.semicolons": "remove"
+ "javascript.format.semicolons": "remove",
+ "[javascript][json][jsonc]": {
+ "editor.defaultFormatter": "esbenp.prettier-vscode"
+ },
+ "[vue]": {
+ "editor.defaultFormatter": "octref.vetur"
+ }
}
\ No newline at end of file
diff --git a/build/linuxpackager b/build/linuxpackager
index a43d4ed1..5f03a2e8 100755
--- a/build/linuxpackager
+++ b/build/linuxpackager
@@ -50,9 +50,8 @@ echo "$controlfile" > dist/debian/DEBIAN/control;
# Package debian
pkg -t node18-linux-x64 -o dist/debian/usr/share/audiobookshelf/audiobookshelf .
-fakeroot dpkg-deb --build dist/debian
+fakeroot dpkg-deb -Zxz --build dist/debian
mv dist/debian.deb "dist/$OUTPUT_FILE"
-chmod +x "dist/$OUTPUT_FILE"
echo "Finished! Filename: $OUTPUT_FILE"
diff --git a/client/assets/app.css b/client/assets/app.css
index 2e0714f9..7daf74ff 100644
--- a/client/assets/app.css
+++ b/client/assets/app.css
@@ -30,8 +30,7 @@
}
.bookshelf-row {
- /* Sidebar width + scrollbar width */
- width: calc(100vw - 88px);
+ width: calc(100vw - (100vw - 100%));
}
@media (max-width: 768px) {
diff --git a/client/assets/fonts.css b/client/assets/fonts.css
index f9acc6bf..9504d4c3 100644
--- a/client/assets/fonts.css
+++ b/client/assets/fonts.css
@@ -24,6 +24,7 @@
word-wrap: normal;
direction: ltr;
-webkit-font-smoothing: antialiased;
+ vertical-align: top;
}
.material-icons:not([class*="text-"]) {
diff --git a/client/components/app/BookShelfCategorized.vue b/client/components/app/BookShelfCategorized.vue
index eb4e9424..b9b2fbfd 100644
--- a/client/components/app/BookShelfCategorized.vue
+++ b/client/components/app/BookShelfCategorized.vue
@@ -4,14 +4,14 @@
{{ libraryName }} Library is empty!
+{{ $getString('MessageXLibraryIsEmpty', [libraryName]) }}
No results for query
+{{ $strings.MessageBookshelfNoResultsForQuery }}
{{ $getString('MessageXLibraryIsEmpty', [libraryName]) }}
{{ name }}
{{ numBooks }} {{ $strings.LabelBooks }}
{{ name }}
+{{ name }}
{{ 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 @@
by {{ book.author }}
+{{ $getString('LabelByAuthor', [book.author]) }}
{{ book.genres.join(', ') }}
{{ book.trackCount }} Episodes
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 @@{{ $strings.LabelDirectory }} (auto)
++ {{ $strings.LabelDirectory }} + (auto) +
{{ $strings.MessageUploaderItemSuccess }}
+"{{ itemData.title }}" {{ $strings.MessageUploaderItemSuccess }}
{{ $strings.MessageUploaderItemFailed }}
+"{{ itemData.title }}" {{ $strings.MessageUploaderItemFailed }}
{{ displayTitle }}
-{{ displayTitle }}
+{{ displayLineTwo || ' ' }}
-{{ displaySortLine }}
+{{ displayLineTwo || ' ' }}
+{{ displaySortLine }}
#{{ seriesSequenceList }}
{{ booksInSeries }}
{{ title }}
- {{ titleCleaned }} -
+{{ titleCleaned }}
{{ authorCleaned }}
+{{ authorCleaned }}