diff --git a/.devcontainer/dev.js b/.devcontainer/dev.js index 0d113a3e5..28c0074b4 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 000000000..0efcc5b5b --- /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 7f47d710f..89aec401c 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 75363c0e4..768880916 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 000000000..a77ab3e0a --- /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 000000000..12d82c3e6 --- /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 000000000..9ede33b81 --- /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 000000000..695696c62 --- /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 0690f38f5..9ddb1a707 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 000000000..d3d0ff992 --- /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 000000000..d2a045982 --- /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 397b9618e..75503e6a4 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 a43d4ed18..5f03a2e8e 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 2e0714f97..7daf74ff4 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 f9acc6bfb..9504d4c3d 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/BookShelfRow.vue b/client/components/app/BookShelfRow.vue index 60632db7d..5b2c42589 100644 --- a/client/components/app/BookShelfRow.vue +++ b/client/components/app/BookShelfRow.vue @@ -4,7 +4,7 @@
{{ name }}
{{ numBooks }} {{ $strings.LabelBooks }}
{{ name }}
+{{ name }}
{{ $strings.LabelDirectory }} (auto)
++ {{ $strings.LabelDirectory }} + (auto) +
{{ $strings.MessageUploaderItemSuccess }}
+"{{ itemData.title }}" {{ $strings.MessageUploaderItemSuccess }}
{{ $strings.MessageUploaderItemFailed }}
+"{{ itemData.title }}" {{ $strings.MessageUploaderItemFailed }}
{{ displayTitle }}
@@ -358,7 +358,7 @@ export default { }, showError() { if (this.recentEpisode) return false // Dont show podcast error on episode card - return this.numInvalidAudioFiles || this.numMissingParts || this.isMissing || this.isInvalid + return this.isMissing || this.isInvalid }, libraryItemIdStreaming() { return this.store.getters['getLibraryItemIdStreaming'] @@ -388,29 +388,13 @@ export default { isInvalid() { return this._libraryItem.isInvalid }, - numMissingParts() { - if (this.isPodcast) return 0 - return this.media.numMissingParts - }, - numInvalidAudioFiles() { - if (this.isPodcast) return 0 - return this.media.numInvalidAudioFiles - }, errorText() { if (this.isMissing) return 'Item directory is missing!' else if (this.isInvalid) { if (this.isPodcast) return 'Podcast has no episodes' return 'Item has no audio tracks & ebook' } - let txt = '' - if (this.numMissingParts) { - txt += `${this.numMissingParts} missing parts.` - } - if (this.numInvalidAudioFiles) { - if (txt) txt += ' ' - txt += `${this.numInvalidAudioFiles} invalid audio files.` - } - return txt || 'Unknown Error' + return 'Unknown Error' }, overlayWrapperClasslist() { const classes = [] diff --git a/client/components/cards/LazySeriesCard.vue b/client/components/cards/LazySeriesCard.vue index 1175acf1b..c8bbf12c2 100644 --- a/client/components/cards/LazySeriesCard.vue +++ b/client/components/cards/LazySeriesCard.vue @@ -1,28 +1,28 @@ -{{ displayTitle }}
{{ displayTitle }}
+{{ displayTitle }}
{{ displayTitle }}
-{{ displaySortLine }}
+{{ displayTitle }}
+{{ displaySortLine }}
{{ name }}
-{{ numBooks }} Book{{ numBooks === 1 ? '' : 's' }}
+{{ name }}
+{{ numBooks }} Book{{ numBooks === 1 ? '' : 's' }}
{{ $strings.LabelEnable }}
{{ _session.mediaPlayer }}
{{ $strings.LabelDevice }}
+{{ clientDisplayName }}
{{ deviceInfo.ipAddress }}
{{ osDisplayName }}
{{ deviceInfo.browserName }}
-{{ clientDisplayName }}
+{{ deviceDisplayName }}
SDK {{ $strings.LabelVersion }}: {{ deviceInfo.sdkVersion }}
{{ $strings.LabelType }}: {{ deviceInfo.deviceType }}
{{ $strings.MessageNoChapters }}
-