Compare commits

...

34 Commits
v0.6.9 ... dev

Author SHA1 Message Date
2090abcc51 fix: add latest tag for default branch in Docker metadata extraction 2025-08-18 13:54:46 +00:00
1104c079dc fix: format Dockerfile for improved readability and consistency 2025-08-18 13:54:41 +00:00
7973c9e2c8 fix: update image source and restore volume paths in docker-compose.yml 2025-08-18 13:36:06 +00:00
37774b1b99 fix: update import path for AppBar component and remove unnecessary comment in service worker file 2025-08-18 13:19:31 +00:00
5454dac5a7 Add system dependencies installation step in Docker workflow 2025-08-18 13:00:51 +00:00
f20ef97230 Refactor Docker workflow: remove system dependencies installation, update registry credentials, and adjust event conditionals 2025-08-18 12:57:35 +00:00
32f5262b93 Update Gitea Container Registry URL in workflow configuration 2025-08-18 12:53:10 +00:00
34dc770854 Update devcontainer image to use node:18 for consistency 2025-08-18 12:53:05 +00:00
221fe79f87 Upgrade actions/checkout to v4 and streamline system dependencies installation 2025-08-18 12:41:28 +00:00
b73cf924bc Add .gitattributes for consistent line endings across platforms 2025-08-18 12:40:53 +00:00
8c3744db9b Add PWA support and service worker for offline capabilities
- Create .devcontainer/devcontainer.env and .devcontainer/devcontainer.json for development environment configuration
- Add Gitea Actions README and Docker workflow for building and pushing images
- Update package.json to include @vue/cli-plugin-pwa
- Enhance index.html with manifest link and theme color
- Create public/manifest.webmanifest for PWA configuration
- Implement service worker registration and media session management in registerServiceWorker.js
- Update main.js to register the service worker
- Configure vue.config.js for PWA settings and caching strategies
2025-08-18 07:25:53 -05:00
Kevin Thomas
8595a3f155 Change version to 0.7.0 2025-08-12 20:07:13 -04:00
Kevin Thomas
9f376ae56f Fix comments in json file 2025-08-12 19:56:33 -04:00
Kevin Thomas
cba9cd6e85 Upgrade vue to 2.7.16 2025-08-12 19:42:46 -04:00
Kevin Thomas
7b080e0163 Bump node to 20 and fix some vulnerabilities 2025-08-12 19:38:41 -04:00
Isaac Johnson
0618f9e8d6 Kubernetes Manifest install 2025-08-12 19:38:05 -04:00
Kay Thomas
1c3f09fcb8 Merge pull request #63 from kaythomas0/v0.6.13
v0.6.13
2023-12-11 15:36:03 -05:00
Kevin Thomas
98419b6248 Bump to v0.6.13 2023-12-03 19:33:57 -05:00
Kay Thomas
2d2f1810d1 Merge pull request #62 from kaythomas0/dependabot/npm_and_yarn/axios-1.6.0
Bump axios from 0.21.4 to 1.6.0
2023-12-03 19:24:40 -05:00
Kay Thomas
c9fcf06503 Merge pull request #61 from kaythomas0/dependabot/npm_and_yarn/babel/traverse-7.23.2
Bump @babel/traverse from 7.18.2 to 7.23.2
2023-12-03 19:19:26 -05:00
dependabot[bot]
53c05dfe56 Bump axios from 0.21.4 to 1.6.0
Bumps [axios](https://github.com/axios/axios) from 0.21.4 to 1.6.0.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v0.21.4...v1.6.0)

---
updated-dependencies:
- dependency-name: axios
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-10 16:37:21 +00:00
dependabot[bot]
2dc54c7347 Bump @babel/traverse from 7.18.2 to 7.23.2
Bumps [@babel/traverse](https://github.com/babel/babel/tree/HEAD/packages/babel-traverse) from 7.18.2 to 7.23.2.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.23.2/packages/babel-traverse)

---
updated-dependencies:
- dependency-name: "@babel/traverse"
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-18 03:02:56 +00:00
Kay Thomas
bd73809ad9 Merge pull request #60 from kaythomas0/v0.6.12
v0.6.12
2023-07-25 03:22:19 +01:00
Kevin Thomas
3d7c3545ea Bump to v0.6.12 2023-07-19 09:58:18 -07:00
Kay Thomas
02c5fd9660 Merge pull request #59 from kaythomas0/dependabot/npm_and_yarn/word-wrap-1.2.4
Bump word-wrap from 1.2.3 to 1.2.4
2023-07-19 17:57:13 +01:00
dependabot[bot]
d98b23ed40 Bump word-wrap from 1.2.3 to 1.2.4
Bumps [word-wrap](https://github.com/jonschlinkert/word-wrap) from 1.2.3 to 1.2.4.
- [Release notes](https://github.com/jonschlinkert/word-wrap/releases)
- [Commits](https://github.com/jonschlinkert/word-wrap/compare/1.2.3...1.2.4)

---
updated-dependencies:
- dependency-name: word-wrap
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-19 05:08:43 +00:00
Kay Thomas
d57ea01750 Merge pull request #58 from kaythomas0/dev
Update README.md
2023-04-17 01:42:51 -07:00
Kay Thomas
3cc060fdae Update README.md 2023-04-17 01:42:32 -07:00
Kay Thomas
2f21025d20 Merge pull request #57 from kaythomas0/v0.6.11
v0.6.11
2023-04-17 01:40:29 -07:00
Kay Thomas
bdbbdee48d Upgrade node to 16 2023-04-16 23:36:35 -07:00
Kay Thomas
f442d486a3 Merge pull request #56 from kaythomas0/v0.6.10
v0.6.10
2023-03-16 15:43:46 -07:00
Kevin Thomas
ef3eb1a70a Bump to v0.6.10 2023-03-16 13:41:21 -07:00
Kay Thomas
2bb67a9a22 Merge pull request #55 from kaythomas0/dependabot/npm_and_yarn/webpack-5.76.1
Bump webpack from 5.72.1 to 5.76.1
2023-03-16 13:39:47 -07:00
dependabot[bot]
af2384b790 Bump webpack from 5.72.1 to 5.76.1
Bumps [webpack](https://github.com/webpack/webpack) from 5.72.1 to 5.76.1.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.72.1...v5.76.1)

---
updated-dependencies:
- dependency-name: webpack
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-15 01:24:57 +00:00
20 changed files with 18555 additions and 2898 deletions

View File

@@ -0,0 +1,2 @@
CHOKIDAR_USEPOLLING=true
WDS_SOCKET_PORT=0

View File

@@ -0,0 +1,39 @@
{
"name": "Noisedash Dev",
"image": "node:18",
"forwardPorts": [8080, 1432],
"portsAttributes": {
"8080": { "label": "Vue dev server" },
"1432": { "label": "Noisedash API" }
},
"postCreateCommand": "npm install",
"remoteEnv": {
"HOST": "0.0.0.0"
},
"containerEnv": {
"HOST": "0.0.0.0"
},
"runArgs": ["--env-file", ".devcontainer/devcontainer.env"],
"remoteUser": "node",
"customizations": {
"vscode": {
"settings": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
"eslint.format.enable": true,
"eslint.validate": ["javascript", "vue"],
"terminal.integrated.defaultProfile.linux": "bash",
"vetur.validation.template": true,
"vetur.validation.script": true,
"vetur.validation.style": true
},
"extensions": [
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"octref.vetur"
]
}
},
"updateContentCommand": "",
"onCreateCommand": "mkdir -p samples sessions log",
"postStartCommand": "npm run server & npm run serve"
}

3
.gitattributes vendored Normal file
View File

@@ -0,0 +1,3 @@
* text=auto eol=lf
*.{cmd,[cC][mM][dD]} text eol=crlf
*.{bat,[bB][aA][tT]} text eol=crlf

17
.gitea/README.md Normal file
View File

@@ -0,0 +1,17 @@
Gitea Actions for Docker builds
This folder contains workflows for building and pushing Docker images to the Gitea Container Registry.
Setup
- Ensure Gitea Actions is enabled in your instance and for this repo.
- Create the following repository secrets:
- REGISTRY_HOST: your Gitea host (e.g., gitea.example.com)
- REGISTRY_OWNER: your namespace/user/org (e.g., ryan)
- REGISTRY_REPO: repository name (e.g., noisedash)
- REGISTRY_USERNAME: registry username
- REGISTRY_PASSWORD: registry password or a scoped token
Notes
- The workflow builds on pushes to main/master/dev and on tags v*.*.*.
- It produces multi-arch images (amd64, arm64). Adjust platforms if not needed.
- Image name resolves to: ${REGISTRY_HOST}/${REGISTRY_OWNER}/${REGISTRY_REPO} with tags derived from branch/tag/sha.

View File

@@ -0,0 +1,62 @@
name: build-and-push-docker
on:
push:
branches: [ main, master, dev ]
tags:
- 'v*.*.*'
pull_request:
branches: [ main, master, dev ]
jobs:
docker:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install system Dependencies
run: |
apt-get update && apt-get install -y curl jq docker.io
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Gitea Container Registry
uses: docker/login-action@v3
with:
registry: gitea.purpleraft.com
username: ${{ gitea.actor }}
password: ${{ secrets.REGISTRY_TOKEN }}
- name: Extract metadata (tags, labels)
id: meta
uses: docker/metadata-action@v5
with:
images: gitea.purpleraft.com/${{ gitea.repository_owner }}/noisedash
tags: |
type=ref,event=branch
type=ref,event=tag
type=sha
type=raw,value=latest,enable={{is_default_branch}}
- name: Build (PR only)
if: ${{ gitea.event_name == 'pull_request' }}
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile
push: false
platforms: linux/amd64
labels: ${{ steps.meta.outputs.labels }}
- name: Build and push (branches/tags)
if: ${{ gitea.event_name != 'pull_request' }}
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile
push: true
platforms: linux/amd64
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}

View File

@@ -1,10 +1,24 @@
FROM node:14
# NoiseDash - Audio sample management platform
FROM node:20
LABEL maintainer="kaythomas@pm.me"
# Set working directory
WORKDIR /var/noisedash
# Copy package files and install dependencies
COPY package*.json ./
RUN npm install
RUN npm install --force
# Copy application code (includes default config files)
COPY . .
ENV NODE_ENV production
# Set production environment and build frontend
ENV NODE_ENV=production
RUN npm run build
# Expose application port
EXPOSE 1432
# Start the server
CMD [ "node", "server/bin/www.js" ]

View File

@@ -23,6 +23,9 @@ Requires docker and docker-compose
* Download the provided [docker-compose.yml file](https://github.com/kaythomas0/noisedash/blob/main/docker-compose.yml)
* In the same directory as the docker-compose file, created a folder called `config`, and inside it, put the provided [config file](https://github.com/kaythomas0/noisedash/blob/main/config/default.json)
* `maxSampleSize` is in bytes - 10GB by default
* Keep `tls` as `false` if using an external web server like nginx
* `production.json` exists in the source code and is left empty intentionally for the reason outlined here: https://github.com/node-config/node-config/wiki/Strict-Mode#node_env-value-of-node_env-did-not-match-any-deployment-config-file-names=
* Edit the config file to your preference
* Bring the container up:
@@ -34,9 +37,26 @@ docker-compose up -d
(Raspberry Pi compatible images are available, see armv7 images on [Docker Hub](https://hub.docker.com/repository/docker/noisedash/noisedash))
## Kubernetes
You can apply the manifest.yaml in the kubernetes folder to install Noisedash into your Kubernetes cluster.
Optionally, uncomment the last lines in the file to also create an ingress. The ingress, commented out by default, needs to have the clusterIssuser annotation set to your cluster issuer (default: letsencrypt-prod) and the ingress class set to your Ingress class (default: Nginx)
``` bash
$ kubectl apply -f ./kubernetes/manifest.yaml
persistentvolumeclaim/db-pvc created
persistentvolumeclaim/samples-pvc created
deployment.apps/noisedash created
service/noisedash created
configmap/noisedashcfg created
ingress.networking.k8s.io/noisedashingress created
```
## From Source
Requires node 14 and npm
Requires node 20 and npm
* Clone the repo:

View File

@@ -3,9 +3,9 @@
"listeningPort": 1432,
"sessionFileStorePath": "sessions",
"sampleUploadPath": "samples",
"maxSampleSize": 10737418240, // In bytes, 10GB by default
"maxSampleSize": 10737418240,
"logFile": "log/noisedash.log",
"tls": false, // Keep this as false if using an external web server like nginx
"tls": false,
"tlsKey": "certs/key.pem",
"tlsCert": "certs/cert.pem"
}

View File

@@ -1 +1 @@
{} // Left empty intentionally: https://github.com/node-config/node-config/wiki/Strict-Mode#node_env-value-of-node_env-did-not-match-any-deployment-config-file-names=
{}

View File

@@ -2,16 +2,13 @@ version: "3"
services:
noisedash:
image: noisedash/noisedash:latest
container_name: noisedash
image: gitea.purpleraft.com/ryan/noisedash:latest
ports:
- "1432:1432"
volumes:
- db:/var/noisedash/db
- samples:/var/noisedash/samples
- ./config/default.json:/var/noisedash/config/default.json
- ./db:/var/noisedash/db
- ./samples:/var/noisedash/samples
# Optional: Override default config if you have custom settings
# - ./config/default.json:/var/noisedash/config/default.json
volumes:
db:
samples:

240
kubernetes/manifest.yaml Normal file
View File

@@ -0,0 +1,240 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: db-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: samples-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: noisedash
spec:
replicas: 1
selector:
matchLabels:
app: noisedash
template:
metadata:
labels:
app: noisedash
spec:
containers:
- name: noisedash
image: noisedash/noisedash:latest
ports:
- containerPort: 1432
volumeMounts:
- name: db
mountPath: /var/noisedash/db
- name: samples
mountPath: /var/noisedash/samples
- name: config
mountPath: /var/noisedash/config/default.json
subPath: config.json
volumes:
- name: db
persistentVolumeClaim:
claimName: db-pvc
- name: samples
persistentVolumeClaim:
claimName: samples-pvc
- name: config
configMap:
name: noisedashcfg
---
apiVersion: v1
kind: Service
metadata:
name: noisedash
spec:
selector:
app: noisedash
ports:
- protocol: TCP
port: 80
targetPort: 1432
---
apiVersion: v1
kind: ConfigMap
metadata:
name: noisedashcfg
data:
config.json: |
{
"Server": {
"listeningPort": 1432,
"sessionFileStorePath": "sessions",
"sampleUploadPath": "samples",
"maxSampleSize": 10737418240,
"logFile": "log/noisedash.log",
"tls": false,
"tlsKey": "certs/key.pem",
"tlsCert": "certs/cert.pem"
}
}
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
kubernetes.io/ingress.class: nginx
kubernetes.io/tls-acme: "true"
nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
labels:
app.kubernetes.io/instance: noisedash
name: noisedashingress
spec:
rules:
- host: noisedash.freshbrewed.science
http:
paths:
- backend:
service:
name: noisedash
port:
number: 80
path: /
pathType: ImplementationSpecific
tls:
- hosts:
- noisedash.freshbrewed.science
secretName: noisedash-tls
builder@DESKTOP-QADGF36:~/Workspaces/pyplanereport$
builder@DESKTOP-QADGF36:~/Workspaces/pyplanereport$ cat noiseall.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: db-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: samples-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: noisedash
spec:
replicas: 1
selector:
matchLabels:
app: noisedash
template:
metadata:
labels:
app: noisedash
spec:
containers:
- name: noisedash
image: noisedash/noisedash:latest
ports:
- containerPort: 1432
volumeMounts:
- name: db
mountPath: /var/noisedash/db
- name: samples
mountPath: /var/noisedash/samples
- name: config
mountPath: /var/noisedash/config/default.json
subPath: config.json
volumes:
- name: db
persistentVolumeClaim:
claimName: db-pvc
- name: samples
persistentVolumeClaim:
claimName: samples-pvc
- name: config
configMap:
name: noisedashcfg
---
apiVersion: v1
kind: Service
metadata:
name: noisedash
spec:
selector:
app: noisedash
ports:
- protocol: TCP
port: 80
targetPort: 1432
---
apiVersion: v1
kind: ConfigMap
metadata:
name: noisedashcfg
data:
config.json: |
{
"Server": {
"listeningPort": 1432,
"sessionFileStorePath": "sessions",
"sampleUploadPath": "samples",
"maxSampleSize": 10737418240,
"logFile": "log/noisedash.log",
"tls": false,
"tlsKey": "certs/key.pem",
"tlsCert": "certs/cert.pem"
}
}
# ---
# apiVersion: networking.k8s.io/v1
# kind: Ingress
# metadata:
# annotations:
# cert-manager.io/cluster-issuer: letsencrypt-prod
# kubernetes.io/ingress.class: nginx
# kubernetes.io/tls-acme: "true"
# nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
# nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
# labels:
# app.kubernetes.io/instance: noisedash
# name: noisedashingress
# spec:
# rules:
# - host: noisedash.freshbrewed.science
# http:
# paths:
# - backend:
# service:
# name: noisedash
# port:
# number: 80
# path: /
# pathType: ImplementationSpecific
# tls:
# - hosts:
# - noisedash.freshbrewed.science
# secretName: noisedash-tls

20871
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "noisedash",
"version": "0.6.9",
"version": "0.7.0",
"private": true,
"author": "Kay Thomas <kaythomas@pm.me> (https://kaythomas.dev)",
"scripts": {
@@ -12,11 +12,11 @@
},
"dependencies": {
"@vscode/sqlite3": "^5.0.8",
"axios": "^0.21.4",
"axios": "^1.6.0",
"config": "^3.3.6",
"connect-history-api-fallback": "^1.6.0",
"cookie-parser": "^1.4.5",
"core-js": "^3.22.7",
"core-js": "^3.23.5",
"express": "^4.18.1",
"express-session": "^1.17.3",
"multer": "^1.4.5-lts.1",
@@ -25,7 +25,7 @@
"path": "^0.12.7",
"session-file-store": "^1.5.0",
"tone": "^14.7.77",
"vue": "^2.6.11",
"vue": "^2.7.16",
"vue-router": "^3.5.4",
"vuetify": "^2.6.10",
"winston": "^3.3.3"
@@ -33,6 +33,7 @@
"devDependencies": {
"@babel/core": "^7.12.16",
"@babel/eslint-parser": "^7.12.16",
"@vue/cli-plugin-pwa": "^5.0.8",
"@vue/cli-plugin-babel": "^5.0.8",
"@vue/cli-plugin-eslint": "^5.0.8",
"@vue/cli-plugin-router": "^5.0.8",
@@ -44,11 +45,11 @@
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^5.1.0",
"eslint-plugin-standard": "^4.0.0",
"eslint-plugin-vue": "^8.0.3",
"eslint-plugin-vue": "^7.20.0",
"sass": "~1.32.0",
"sass-loader": "^10.0.0",
"vue-cli-plugin-vuetify": "^2.5.8",
"vue-template-compiler": "^2.6.11",
"vue-template-compiler": "^2.7.16",
"vuetify-loader": "^1.7.3"
},
"bugs": "https://github.com/kaythomas0/noisedash/issues",

View File

@@ -5,6 +5,8 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<meta name="theme-color" content="#121212">
<link rel="manifest" href="<%= BASE_URL %>manifest.webmanifest">
<title><%= htmlWebpackPlugin.options.title %></title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@mdi/font@latest/css/materialdesignicons.min.css">

View File

@@ -0,0 +1,16 @@
{
"name": "Noisedash",
"short_name": "Noisedash",
"start_url": "/",
"display": "standalone",
"background_color": "#121212",
"theme_color": "#121212",
"description": "Ambient noise generator",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
}
]
}

View File

@@ -8,7 +8,7 @@
</template>
<script>
import AppBar from '@/components/AppBar'
import AppBar from '@/components/AppBar.vue'
export default {
name: 'App',

View File

@@ -1,4 +1,5 @@
import * as Tone from 'tone'
import { setMediaSessionMetadata } from '@/registerServiceWorker'
export default {
name: 'Noise',
@@ -241,6 +242,17 @@ export default {
})
Tone.Transport.start('+0.1')
// Update Media Session so playback can continue in background with proper metadata
try {
setMediaSessionMetadata({ title: (this.selectedProfile && this.selectedProfile.text) ? this.selectedProfile.text : 'Noisedash' })
if ('mediaSession' in navigator) {
navigator.mediaSession.playbackState = 'playing'
navigator.mediaSession.setActionHandler('play', () => this.play())
navigator.mediaSession.setActionHandler('pause', () => this.stop())
navigator.mediaSession.setActionHandler('stop', () => this.stop())
}
} catch (e) { /* no-op */ }
},
playSporadicSample (id) {
const sample = this.loadedSamples.find(s => s.id === id)
@@ -271,6 +283,11 @@ export default {
clearInterval(s.sporadicInterval)
}
})
// Reflect playback state for OS controls
if ('mediaSession' in navigator) {
try { navigator.mediaSession.playbackState = 'paused' } catch (e) { /* no-op */ }
}
},
startTimer () {
this.timeRemaining -= 1

View File

@@ -3,6 +3,7 @@ import App from './App.vue'
import router from './router'
import vuetify from './plugins/vuetify'
import instance from './axios'
import './registerServiceWorker'
Vue.prototype.$http = instance

View File

@@ -0,0 +1,45 @@
// Registers the service worker generated by @vue/cli-plugin-pwa
// This enables installability and offline caching for static assets.
if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
const register = async () => {
try {
const reg = await navigator.serviceWorker.register(`${process.env.BASE_URL}service-worker.js`)
// Listen for updates and activate immediately
reg.addEventListener('updatefound', () => {
const newWorker = reg.installing
if (!newWorker) return
newWorker.addEventListener('statechange', () => {
if (newWorker.state === 'installed' && navigator.serviceWorker.controller) {
// New content is available; refresh clients
reg.waiting && reg.waiting.postMessage({ type: 'SKIP_WAITING' })
}
})
})
// Claim clients after activation
navigator.serviceWorker.addEventListener('controllerchange', () => {
// optional: location.reload()
})
} catch (e) {
// eslint-disable-next-line no-console
console.warn('SW registration failed', e)
}
}
register()
}
// Minimal Media Session API wiring so playback can continue in background on supported browsers
export function setMediaSessionMetadata (opts = {}) {
if ('mediaSession' in navigator) {
const md = new window.MediaMetadata({
title: opts.title || 'Noisedash',
artist: opts.artist || 'Ambient Generator',
album: opts.album || 'Noisedash',
artwork: opts.artwork || [
{ src: '/favicon.ico', sizes: '64x64', type: 'image/x-icon' }
]
})
navigator.mediaSession.metadata = md
}
}

View File

@@ -3,6 +3,48 @@ module.exports = {
'vuetify'
],
devServer: {
host: '0.0.0.0',
port: 8080,
allowedHosts: 'all',
proxy: 'http://localhost:1432'
},
pwa: {
name: 'Noisedash',
themeColor: '#121212',
backgroundColor: '#121212',
display: 'standalone',
startUrl: '/',
manifestOptions: {
short_name: 'Noisedash',
description: 'Ambient noise generator',
categories: ['music', 'audio', 'productivity'],
display_override: ['standalone', 'browser'],
orientation: 'any'
},
iconPaths: {
favicon32: 'favicon.ico',
favicon16: 'favicon.ico',
appleTouchIcon: 'favicon.ico',
maskIcon: 'favicon.ico',
msTileImage: 'favicon.ico'
},
workboxPluginMode: 'GenerateSW',
workboxOptions: {
cleanupOutdatedCaches: true,
skipWaiting: true,
clientsClaim: true,
offlineGoogleAnalytics: false,
runtimeCaching: [
{
urlPattern: /\.(?:png|jpg|jpeg|svg|gif|webp|mp3|wav|ogg)$/,
handler: 'CacheFirst',
options: {
cacheName: 'assets-cache',
expiration: { maxEntries: 60, maxAgeSeconds: 7 * 24 * 60 * 60 },
cacheableResponse: { statuses: [0, 200] }
}
}
]
}
}
}