diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md deleted file mode 100644 index 0cd521a5b..000000000 --- a/.github/pull_request_template.md +++ /dev/null @@ -1,33 +0,0 @@ - - -## Brief summary - - - -## Which issue is fixed? - - - -## In-depth Description - - - -## How have you tested this? - - - -## Screenshots - - diff --git a/.github/workflows/close_blank_issues.yaml b/.github/workflows/close_blank_issues.yaml deleted file mode 100644 index 7190546a0..000000000 --- a/.github/workflows/close_blank_issues.yaml +++ /dev/null @@ -1,42 +0,0 @@ -name: Close Issues not using a template - -on: - issues: - types: - - opened - -permissions: - issues: write - -jobs: - close_issue: - runs-on: ubuntu-latest - - steps: - - name: Check issue headings - uses: actions/github-script@v7 - with: - script: | - const issueBody = context.payload.issue.body || ""; - - // Match Markdown headings (e.g., # Heading, ## Heading) - const headingRegex = /^(#{1,6})\s.+/gm; - const headings = [...issueBody.matchAll(headingRegex)]; - - if (headings.length < 3) { - // Post a comment - await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: context.payload.issue.number, - body: "Thank you for opening an issue! To help us review your request efficiently, please use one of the provided issue templates. If you're seeking information or have a general question, consider opening a Discussion or joining the conversation on our Discord. Thanks!" - }); - - // Close the issue - await github.rest.issues.update({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: context.payload.issue.number, - state: "closed" - }); - } diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 809563018..a77ab3e0a 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -1,25 +1,11 @@ -name: 'CodeQL' +name: "CodeQL" on: push: - branches: ['master'] - # Only build when files in these directories have been changed - paths: - - client/** - - server/** - - test/** - - index.js - - package.json + branches: [ 'master' ] pull_request: # The branches below must be a subset of the branches above - branches: ['master'] - # Only build when files in these directories have been changed - paths: - - client/** - - server/** - - test/** - - index.js - - package.json + branches: [ 'master' ] schedule: - cron: '16 5 * * 4' @@ -35,44 +21,45 @@ jobs: strategy: fail-fast: false matrix: - language: ['javascript'] + 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@v4 + - name: Checkout repository + uses: actions/checkout@v3 - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v3 - 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. + # 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 + # 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@v3 - # â„šī¸ 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 + # 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 - # 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. + # â„šī¸ 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 - # - run: | - # echo "Run, Build Application using script" - # ./location_of_script_within_repo/buildscript.sh + # 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. - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v3 - with: - category: '/language:${{matrix.language}}' + # - 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/component-tests.yml b/.github/workflows/component-tests.yml deleted file mode 100644 index fcc2c2138..000000000 --- a/.github/workflows/component-tests.yml +++ /dev/null @@ -1,48 +0,0 @@ -name: Run Component Tests - -on: - workflow_dispatch: - inputs: - ref: - description: 'Branch/Tag/SHA to test' - required: true - pull_request: - paths: - - 'client/**' - - '.github/workflows/component-tests.yml' - push: - paths: - - 'client/**' - - '.github/workflows/component-tests.yml' - -jobs: - run-component-tests: - name: Run Component 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 - cache: 'npm' - - - name: Install dependencies - run: | - cd client - npm ci - - - name: Run tests - run: | - cd client - npm test diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml index fdb57fbc5..e783fce63 100644 --- a/.github/workflows/docker-build.yml +++ b/.github/workflows/docker-build.yml @@ -1,4 +1,5 @@ --- + name: Build and Push Docker Image on: @@ -10,7 +11,7 @@ on: required: true default: 'latest' push: - branches: [main, master] + branches: [main,master] tags: - 'v*.*.*' # Only build when files in these directories have been changed @@ -22,16 +23,16 @@ on: jobs: build: - if: ${{ !contains(github.event.head_commit.message, 'skip ci') && github.repository == 'advplyr/audiobookshelf' }} - runs-on: ubuntu-24.04 + if: "!contains(github.event.head_commit.message, 'skip ci')" + runs-on: ubuntu-20.04 steps: - name: Check out - uses: actions/checkout@v4 + uses: actions/checkout@v3 - name: Docker meta id: meta - uses: docker/metadata-action@v5 + uses: docker/metadata-action@v4 with: images: advplyr/audiobookshelf,ghcr.io/${{ github.repository_owner }}/audiobookshelf tags: | @@ -39,13 +40,13 @@ jobs: type=semver,pattern={{version}} - name: Setup QEMU - uses: docker/setup-qemu-action@v3 + uses: docker/setup-qemu-action@v2 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + uses: docker/setup-buildx-action@v2 - name: Cache Docker layers - uses: actions/cache@v4 + uses: actions/cache@v3 with: path: /tmp/.buildx-cache key: ${{ runner.os }}-buildx-${{ github.sha }} @@ -53,23 +54,22 @@ jobs: ${{ runner.os }}-buildx- - name: Login to Dockerhub - uses: docker/login-action@v3 + uses: docker/login-action@v2 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_PASSWORD }} - name: Login to ghcr - uses: docker/login-action@v3 + uses: docker/login-action@v2 with: registry: ghcr.io username: ${{ github.repository_owner }} password: ${{ secrets.GHCR_PASSWORD }} - name: Build image - uses: docker/build-push-action@v6 + uses: docker/build-push-action@v3 with: tags: ${{ github.event.inputs.tags || steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} context: . platforms: linux/amd64,linux/arm64 push: true diff --git a/.github/workflows/i18n-integration.yml b/.github/workflows/i18n-integration.yml index 8b3a4678f..fc8441546 100644 --- a/.github/workflows/i18n-integration.yml +++ b/.github/workflows/i18n-integration.yml @@ -20,8 +20,7 @@ jobs: - name: Set up node uses: actions/setup-node@v4 with: - node-version: 20 - cache: 'npm' + node-version: '20' # The only argument is the `directory`, which is where the i18n files are # stored. diff --git a/.github/workflows/integration-test.yml b/.github/workflows/integration-test.yml index 18c1d2dae..3e499468e 100644 --- a/.github/workflows/integration-test.yml +++ b/.github/workflows/integration-test.yml @@ -5,28 +5,20 @@ on: push: branches-ignore: - 'dependabot/**' # Don't run dependabot branches, as they are already covered by pull requests - # Only build when files in these directories have been changed - paths: - - client/** - - server/** - - test/** - - index.js - - package.json jobs: build: name: build and test runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v3 - - name: setup node - uses: actions/setup-node@v4 + - name: setup nade + uses: actions/setup-node@v3 with: node-version: 20 - cache: 'npm' - - name: install pkg (using yao-pkg fork for targeting node20) + - name: install pkg (using yao-pkg fork for targetting node20) run: npm install -g @yao-pkg/pkg - name: get client dependencies diff --git a/.github/workflows/lint-openapi.yml b/.github/workflows/lint-openapi.yml index ec08ecb36..817e94b97 100644 --- a/.github/workflows/lint-openapi.yml +++ b/.github/workflows/lint-openapi.yml @@ -18,22 +18,15 @@ jobs: # Check out the repository - name: Checkout uses: actions/checkout@v4 - # Set up node to run the javascript - name: Set up node uses: actions/setup-node@v4 - with: - node-version: 20 - cache: 'npm' - # Install Redocly CLI - name: Install Redocly CLI run: npm install -g @redocly/cli@latest - # Perform linting for exploded spec - name: Run linting for exploded spec run: redocly lint docs/root.yaml --format=github-actions - # Perform linting for bundled spec - name: Run linting for bundled spec run: redocly lint docs/openapi.json --format=github-actions diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index 91a22c716..695696c62 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -29,7 +29,6 @@ jobs: uses: actions/setup-node@v4 with: node-version: 20 - cache: 'npm' - name: Install dependencies run: npm ci diff --git a/.gitignore b/.gitignore index 12ebec1c2..ca3768ba3 100644 --- a/.gitignore +++ b/.gitignore @@ -7,7 +7,6 @@ /podcasts/ /media/ /metadata/ -/plugins/ /client/.nuxt/ /client/dist/ /dist/ @@ -17,10 +16,8 @@ /ffmpeg* /ffprobe* /unicode* -/libnusqlite3* sw.* .DS_STORE .idea/* tailwind.compiled.css -tailwind.config.js diff --git a/Dockerfile b/Dockerfile index 816bdd3c3..0d586710e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,73 +1,35 @@ -ARG NUSQLITE3_DIR="/usr/local/lib/nusqlite3" -ARG NUSQLITE3_PATH="${NUSQLITE3_DIR}/libnusqlite3.so" - ### STAGE 0: Build client ### -FROM node:20-alpine AS build-client - +FROM node:20-alpine AS build WORKDIR /client COPY /client /client RUN npm ci && npm cache clean --force RUN npm run generate ### STAGE 1: Build server ### -FROM node:20-alpine AS build-server - -ARG NUSQLITE3_DIR -ARG TARGETPLATFORM +FROM node:20-alpine ENV NODE_ENV=production -RUN apk add --no-cache --update \ - curl \ - make \ - python3 \ - g++ \ - unzip +RUN apk update && \ + apk add --no-cache --update \ + curl \ + tzdata \ + ffmpeg \ + make \ + gcompat \ + python3 \ + g++ \ + tini -WORKDIR /server -COPY index.js package* /server -COPY /server /server/server - -RUN case "$TARGETPLATFORM" in \ - "linux/amd64") \ - curl -L -o /tmp/library.zip "https://github.com/mikiher/nunicode-sqlite/releases/download/v1.2/libnusqlite3-linux-musl-x64.zip" ;; \ - "linux/arm64") \ - curl -L -o /tmp/library.zip "https://github.com/mikiher/nunicode-sqlite/releases/download/v1.2/libnusqlite3-linux-musl-arm64.zip" ;; \ - *) echo "Unsupported platform: $TARGETPLATFORM" && exit 1 ;; \ - esac && \ - unzip /tmp/library.zip -d $NUSQLITE3_DIR && \ - rm /tmp/library.zip +COPY --from=build /client/dist /client/dist +COPY index.js package* / +COPY server server RUN npm ci --only=production -### STAGE 2: Create minimal runtime image ### -FROM node:20-alpine - -ARG NUSQLITE3_DIR -ARG NUSQLITE3_PATH - -# Install only runtime dependencies -RUN apk add --no-cache --update \ - tzdata \ - ffmpeg \ - tini - -WORKDIR /app - -# Copy compiled frontend and server from build stages -COPY --from=build-client /client/dist /app/client/dist -COPY --from=build-server /server /app -COPY --from=build-server ${NUSQLITE3_PATH} ${NUSQLITE3_PATH} +RUN apk del make python3 g++ EXPOSE 80 -ENV PORT=80 -ENV NODE_ENV=production -ENV CONFIG_PATH="/config" -ENV METADATA_PATH="/metadata" -ENV SOURCE="docker" -ENV NUSQLITE3_DIR=${NUSQLITE3_DIR} -ENV NUSQLITE3_PATH=${NUSQLITE3_PATH} - ENTRYPOINT ["tini", "--"] CMD ["node", "index.js"] diff --git a/build/debian/DEBIAN/preinst b/build/debian/DEBIAN/preinst index 241a47010..e30bc490c 100644 --- a/build/debian/DEBIAN/preinst +++ b/build/debian/DEBIAN/preinst @@ -22,7 +22,7 @@ add_user() { declare -r descr="${4:-No description}" declare -r shell="${5:-/bin/false}" - if ! getent passwd "$user" 2>&1 >/dev/null; then + if ! getent passwd | grep -q "^$user:"; then echo "Creating system user: $user in $group with $descr and shell $shell" useradd $uid_flags --gid $group --no-create-home --system --shell $shell -c "$descr" $user fi @@ -39,7 +39,7 @@ add_group() { declare -r gid_flags="--gid $gid" fi - if ! getent group "$group" 2>&1 >/dev/null; then + if ! getent group | grep -q "^$group:" ; then echo "Creating system group: $group" groupadd $gid_flags --system $group fi diff --git a/client/assets/app.css b/client/assets/app.css index 36b3b4bad..7daf74ff4 100644 --- a/client/assets/app.css +++ b/client/assets/app.css @@ -5,7 +5,7 @@ @import './absicons.css'; :root { - --bookshelf-texture-img: url(~static/textures/wood_default.jpg); + --bookshelf-texture-img: url(/textures/wood_default.jpg); --bookshelf-divider-bg: linear-gradient(180deg, rgba(149, 119, 90, 1) 0%, rgba(103, 70, 37, 1) 17%, rgba(103, 70, 37, 1) 88%, rgba(71, 48, 25, 1) 100%); } @@ -92,10 +92,11 @@ } /* Firefox */ -input[type='number'] { +input[type=number] { -moz-appearance: textfield; } + .tracksTable { border-collapse: collapse; width: 100%; @@ -176,10 +177,6 @@ input[type='number'] { box-shadow: 4px 1px 8px #11111166, -4px 1px 8px #11111166, 1px -4px 8px #11111166; } -.box-shadow-progressbar { - box-shadow: 0px -1px 4px rgb(62, 50, 2, 0.5); -} - .shadow-height { height: calc(100% - 4px); } @@ -207,6 +204,7 @@ Bookshelf Label color: #fce3a6; } + .cover-bg { width: calc(100% + 40px); height: calc(100% + 40px); @@ -249,4 +247,4 @@ Bookshelf Label .abs-btn:disabled::before { background-color: rgba(0, 0, 0, 0.2); -} +} \ No newline at end of file diff --git a/client/assets/defaultStyles.css b/client/assets/defaultStyles.css index e0ca79e29..027ccdf23 100644 --- a/client/assets/defaultStyles.css +++ b/client/assets/defaultStyles.css @@ -52,17 +52,4 @@ text-indent: 0px !important; text-align: start !important; text-align-last: start !important; -} - -.default-style.less-spacing p { - margin-block-start: 0; -} - -.default-style.less-spacing ul { - margin-block-start: 0; -} - -.default-style.less-spacing ol { - margin-block-start: 0; -} - +} \ No newline at end of file diff --git a/client/assets/tailwind.css b/client/assets/tailwind.css index 7883f32ff..bd6213e1d 100644 --- a/client/assets/tailwind.css +++ b/client/assets/tailwind.css @@ -1,85 +1,3 @@ -@import 'tailwindcss'; - -/* - The default border color has changed to `currentColor` in Tailwind CSS v4, - so we've added these compatibility styles to make sure everything still - looks the same as it did with Tailwind CSS v3. - - If we ever want to remove these styles, we need to add an explicit border - color utility to any element that depends on these defaults. -*/ -@layer base { - *, - ::after, - ::before, - ::backdrop, - ::file-selector-button { - border-color: var(--color-gray-200, currentColor); - } - - [role='button'], - button { - cursor: pointer; - } -} - -@theme { - --spacing-0\.5e: 0.125em; - --spacing-1e: 0.25em; - --spacing-1\.5e: 0.375em; - --spacing-2e: 0.5em; - --spacing-2\.5e: 0.625em; - --spacing-3e: 0.75em; - --spacing-3\.5e: 0.875em; - --spacing-4e: 1em; - --spacing-5e: 1.25em; - --spacing-6e: 1.5em; - --spacing-7e: 1.75em; - --spacing-8e: 2em; - --spacing-9e: 2.25em; - --spacing-10e: 2.5em; - --spacing-11e: 2.75em; - --spacing-12e: 3em; - --spacing-14e: 3.5em; - --spacing-16e: 4em; - --spacing-20e: 5em; - --spacing-24e: 6em; - --spacing-28e: 7em; - --spacing-32e: 8em; - --spacing-36e: 9em; - --spacing-40e: 10em; - --spacing-44e: 11em; - --spacing-48e: 12em; - --spacing-52e: 13em; - --spacing-56e: 14em; - --spacing-60e: 15em; - --spacing-64e: 16em; - --spacing-72e: 18em; - --spacing-80e: 20em; - --spacing-96e: 24em; - - --color-bg: #373838; - --color-primary: #232323; - --color-accent: #1ad691; - --color-error: #ff5252; - --color-info: #2196f3; - --color-success: #4caf50; - --color-warning: #fb8c00; - --color-darkgreen: rgb(34, 127, 35); - --color-black-50: #bbbbbb; - --color-black-100: #666666; - --color-black-200: #555555; - --color-black-300: #444444; - --color-black-400: #333333; - --color-black-500: #222222; - --color-black-600: #111111; - --color-black-700: #101010; - - --font-sans: 'Source Sans Pro'; - --font-mono: 'Ubuntu Mono'; - - --text-xxs: 0.625rem; - --text-1\.5xl: 1.375rem; - --text-2\.5xl: 1.6875rem; - --text-4\.5xl: 2.625rem; -} +@tailwind base; +@tailwind components; +@tailwind utilities; \ No newline at end of file diff --git a/client/assets/trix.css b/client/assets/trix.css index 7432b25f4..8f88c61f1 100644 --- a/client/assets/trix.css +++ b/client/assets/trix.css @@ -446,7 +446,7 @@ trix-editor .attachment__metadata .attachment__size { } .trix-content { - line-height: inherit; + line-height: 1.5; } .trix-content * { @@ -455,13 +455,6 @@ trix-editor .attachment__metadata .attachment__size { padding: 0; } -.trix-content p { - box-sizing: border-box; - margin-top: 0; - margin-bottom: 0.5em; - padding: 0; -} - .trix-content h1 { font-size: 1.2em; line-height: 1.2; @@ -567,4 +560,4 @@ trix-editor .attachment__metadata .attachment__size { .trix-content .attachment-gallery.attachment-gallery--4 .attachment { flex-basis: 50%; max-width: 50%; -} +} \ No newline at end of file diff --git a/client/components/app/Appbar.vue b/client/components/app/Appbar.vue index f74134041..2d557e32b 100644 --- a/client/components/app/Appbar.vue +++ b/client/components/app/Appbar.vue @@ -1,6 +1,6 @@ @@ -93,13 +93,12 @@ export default { editAuthor(author) { this.$store.commit('globals/showEditAuthorModal', author) }, - editItem(libraryItem, tab = 'details') { + editItem(libraryItem) { var itemIds = this.shelf.entities.map((e) => e.id) this.$store.commit('setBookshelfBookIds', itemIds) - this.$store.commit('showEditModalOnTab', { libraryItem, tab: tab || 'details' }) + this.$store.commit('showEditModal', libraryItem) }, editEpisode({ libraryItem, episode }) { - this.$store.commit('setEpisodeTableEpisodeIds', [episode.id]) this.$store.commit('setSelectedLibraryItem', libraryItem) this.$store.commit('globals/setSelectedEpisode', episode) this.$store.commit('globals/setShowEditPodcastEpisodeModal', true) diff --git a/client/components/app/BookShelfToolbar.vue b/client/components/app/BookShelfToolbar.vue index b7ecff624..ff337428f 100644 --- a/client/components/app/BookShelfToolbar.vue +++ b/client/components/app/BookShelfToolbar.vue @@ -1,63 +1,71 @@