diff --git a/.SRCINFO b/.SRCINFO index 5e0952d..a3ee6e5 100644 --- a/.SRCINFO +++ b/.SRCINFO @@ -1,6 +1,6 @@ pkgbase = coolerdash pkgdesc = Plug-in for CoolerControl that extends the LCD functionality with additional features - pkgver = 3.1.2 + pkgver = 3.1.3 pkgrel = 1 url = https://github.com/damachine/coolerdash install = coolerdash.install @@ -17,7 +17,6 @@ pkgbase = coolerdash provides = coolerdash-git conflicts = coolerdash-git replaces = coolerdash-git - backup = etc/coolercontrol/plugins/coolerdash/config.json - backup = etc/coolercontrol/plugins/coolerdash/credentials.json + backup = var/lib/coolercontrol/plugins/coolerdash/config.json pkgname = coolerdash diff --git a/.github/workflows/install.yml b/.github/workflows/install.yml index 3d35f76..3ea9cba 100644 --- a/.github/workflows/install.yml +++ b/.github/workflows/install.yml @@ -59,7 +59,7 @@ jobs: steps: - name: Checkout CoolerDash code - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Update package manager run: ${{ matrix.pre_install }} @@ -102,7 +102,7 @@ jobs: fi # Check plugin files - if [ -f "/tmp/install-test/etc/coolercontrol/plugins/coolerdash/config.json" ]; then + if [ -f "/tmp/install-test/var/lib/coolercontrol/plugins/coolerdash/config.json" ]; then echo "✅ Config file installed (plugin mode)" else echo "❌ Config file not found" @@ -110,7 +110,7 @@ jobs: fi # Check manifest.toml - if [ -f "/tmp/install-test/etc/coolercontrol/plugins/coolerdash/manifest.toml" ]; then + if [ -f "/tmp/install-test/var/lib/coolercontrol/plugins/coolerdash/manifest.toml" ]; then echo "✅ Plugin manifest installed" else echo "❌ Plugin manifest not found" @@ -118,7 +118,7 @@ jobs: fi # Check UI files - if [ -f "/tmp/install-test/etc/coolercontrol/plugins/coolerdash/ui/index.html" ]; then + if [ -f "/tmp/install-test/var/lib/coolercontrol/plugins/coolerdash/ui/index.html" ]; then echo "✅ Plugin UI file installed" else echo "❌ Plugin UI file not found" @@ -126,7 +126,7 @@ jobs: fi # Check CC-Plugin Lib JS is NOT installed (served by CoolerControl) - if [ -f "/tmp/install-test/etc/coolercontrol/plugins/coolerdash/ui/cc-plugin-lib.js" ]; then + if [ -f "/tmp/install-test/var/lib/coolercontrol/plugins/coolerdash/ui/cc-plugin-lib.js" ]; then echo "❌ Plugin Lib JS should NOT be installed (served by CoolerControl)" exit 1 else @@ -176,7 +176,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Setup Arch Linux run: | @@ -202,7 +202,7 @@ jobs: fi # Check plugin config - if [ -f "/tmp/install-test/etc/coolercontrol/plugins/coolerdash/config.json" ]; then + if [ -f "/tmp/install-test/var/lib/coolercontrol/plugins/coolerdash/config.json" ]; then echo "✅ Config file installed" else echo "❌ Config file not found" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6704742..79eed52 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -25,7 +25,7 @@ jobs: commit_sha: ${{ steps.commit.outputs.sha }} steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: fetch-depth: 0 token: ${{ secrets.GITHUB_TOKEN }} @@ -178,7 +178,7 @@ jobs: git - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: ref: master fetch-depth: 0 @@ -259,7 +259,7 @@ jobs: if: github.ref == 'refs/heads/master' steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: fetch-depth: 0 token: ${{ secrets.GITHUB_TOKEN }} @@ -466,7 +466,7 @@ jobs: if: github.ref == 'refs/heads/master' steps: - name: Checkout main repository - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: fetch-depth: 0 diff --git a/.gitignore b/.gitignore index 90e6945..cc0d70d 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ coolerdash-bin/ *.old *.db *.files +docs/ src/ pkg/ bin/ diff --git a/Makefile b/Makefile index 6548330..c0c8c95 100644 --- a/Makefile +++ b/Makefile @@ -60,8 +60,8 @@ INSTALL ?= install INSTALL_PROGRAM ?= $(INSTALL) INSTALL_DATA ?= $(INSTALL) -m 644 -# Plugin directory (derived) -PLUGINDIR = $(sysconfdir)/coolercontrol/plugins/coolerdash +# Plugin directory (canonical path per CoolerControl cc-plugins spec) +PLUGINDIR = /var/lib/coolercontrol/plugins/coolerdash # Colors for terminal output RED = \033[0;31m @@ -239,7 +239,7 @@ check: $(OBJDIR) ./$(OBJDIR)/test_scaling @printf "$(GREEN)All tests passed$(RESET)\n" -# Install binary to /usr/libexec, plugin data to /etc/coolercontrol/plugins/coolerdash/ +# Install binary to /usr/libexec, plugin data to /var/lib/coolercontrol/plugins/coolerdash/ install: check-deps $(TARGET) @printf "\n" @printf "$(WHITE)=== COOLERDASH INSTALLATION ===$(RESET)\n" @@ -322,6 +322,28 @@ install: check-deps $(TARGET) printf " $(BLUE)->$(RESET) No legacy files found (clean install)\n"; \ fi; \ printf "\n"; \ + if [ -f /etc/coolercontrol/plugins/coolerdash/config.json ] && \ + [ ! -f "$(PLUGINDIR)/config.json" ]; then \ + $(SUDO) mkdir -p "$(PLUGINDIR)"; \ + $(SUDO) cp /etc/coolercontrol/plugins/coolerdash/config.json \ + "$(PLUGINDIR)/config.json"; \ + $(SUDO) chmod 600 "$(PLUGINDIR)/config.json"; \ + printf " $(GREEN)Migrated:$(RESET) config.json to $(PLUGINDIR)/\n"; \ + fi; \ + if [ -f /etc/coolercontrol/plugins/coolerdash/credentials.json ] && \ + [ ! -f "$(PLUGINDIR)/credentials.json" ]; then \ + $(SUDO) mkdir -p "$(PLUGINDIR)"; \ + $(SUDO) cp /etc/coolercontrol/plugins/coolerdash/credentials.json \ + "$(PLUGINDIR)/credentials.json"; \ + $(SUDO) chmod 600 "$(PLUGINDIR)/credentials.json"; \ + printf " $(GREEN)Migrated:$(RESET) credentials.json to $(PLUGINDIR)/\n"; \ + fi; \ + rm -f /etc/coolercontrol/plugins/coolerdash/manifest.toml; \ + rm -rf /etc/coolercontrol/plugins/coolerdash/ui; \ + rm -f /etc/coolercontrol/plugins/coolerdash/shutdown.png; \ + rm -f /etc/coolercontrol/plugins/coolerdash/README.md; \ + rm -f /etc/coolercontrol/plugins/coolerdash/CHANGELOG.md; \ + rm -f /etc/coolercontrol/plugins/coolerdash/VERSION; \ COOLERDASH_COUNT=$$(pgrep -x coolerdash 2>/dev/null | wc -l); \ if [ "$$COOLERDASH_COUNT" -gt 0 ]; then \ printf "$(CYAN)Terminating running coolerdash process(es)...$(RESET)\n"; \ @@ -484,6 +506,8 @@ uninstall: fi; \ fi @$(SUDO) rm -rf "$(DESTDIR)$(PLUGINDIR)" + # Legacy path cleanup for users upgrading from older versions + @$(SUDO) rm -rf "$(DESTDIR)/etc/coolercontrol/plugins/coolerdash" @$(SUDO) rm -rf "$(DESTDIR)$(libexecdir)/coolerdash" @$(SUDO) rm -rf "$(DESTDIR)$(datarootdir)/licenses/coolerdash" @$(SUDO) rm -f "$(DESTDIR)$(mandir)/man1/coolerdash.1" diff --git a/PKGBUILD b/PKGBUILD index e521e89..9827d7d 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -15,8 +15,7 @@ license=('MIT') depends=('cairo' 'jansson' 'libcurl-gnutls' 'ttf-roboto') makedepends=('gcc' 'make' 'pkg-config' 'git') optdepends=() -backup=('etc/coolercontrol/plugins/coolerdash/config.json' - 'etc/coolercontrol/plugins/coolerdash/credentials.json') +backup=('var/lib/coolercontrol/plugins/coolerdash/config.json') install=coolerdash.install source=() sha256sums=() @@ -43,14 +42,14 @@ build() { make # Copy files to srcdir for packaging (fakeroot cannot access startdir) - mkdir -p "${srcdir}/bin" "${srcdir}/images" "${srcdir}/man" "${srcdir}/etc/coolercontrol/plugins/coolerdash/ui" "${srcdir}/etc/applications" "${srcdir}/etc/icons" + mkdir -p "${srcdir}/bin" "${srcdir}/images" "${srcdir}/man" "${srcdir}/var/lib/coolercontrol/plugins/coolerdash/ui" "${srcdir}/etc/applications" "${srcdir}/etc/icons" cp -a bin/coolerdash "${srcdir}/bin/coolerdash" cp -a README.md CHANGELOG.md VERSION LICENSE "${srcdir}/" - cp -a etc/coolercontrol/plugins/coolerdash/config.json "${srcdir}/etc/coolercontrol/plugins/coolerdash/" - cp -a etc/coolercontrol/plugins/coolerdash/ui/index.html "${srcdir}/etc/coolercontrol/plugins/coolerdash/ui/" + cp -a etc/coolercontrol/plugins/coolerdash/config.json "${srcdir}/var/lib/coolercontrol/plugins/coolerdash/" + cp -a etc/coolercontrol/plugins/coolerdash/ui/index.html "${srcdir}/var/lib/coolercontrol/plugins/coolerdash/ui/" cp -a images/shutdown.png "${srcdir}/images/" cp -a man/coolerdash.1 "${srcdir}/man/" - cp -a etc/coolercontrol/plugins/coolerdash/manifest.toml "${srcdir}/etc/coolercontrol/plugins/coolerdash/" + cp -a etc/coolercontrol/plugins/coolerdash/manifest.toml "${srcdir}/var/lib/coolercontrol/plugins/coolerdash/" cp -a etc/applications/coolerdash.desktop "${srcdir}/etc/applications/" cp -a etc/icons/coolerdash.svg "${srcdir}/etc/icons/" } @@ -69,21 +68,22 @@ check() { } package() { - # Binary to /usr/libexec, plugin data stays in /etc/coolercontrol/plugins/ - install -dm755 "${pkgdir}/etc/coolercontrol/plugins/coolerdash" + # Binary to /usr/libexec, plugin data to /var/lib/coolercontrol/plugins/ + install -dm711 "${pkgdir}/var/lib/coolercontrol" + install -dm755 "${pkgdir}/var/lib/coolercontrol/plugins/coolerdash" install -Dm755 "${srcdir}/bin/coolerdash" "${pkgdir}/usr/libexec/coolerdash/coolerdash" - install -Dm644 "${srcdir}/README.md" "${pkgdir}/etc/coolercontrol/plugins/coolerdash/README.md" - install -Dm644 "${srcdir}/VERSION" "${pkgdir}/etc/coolercontrol/plugins/coolerdash/VERSION" - install -Dm644 "${srcdir}/CHANGELOG.md" "${pkgdir}/etc/coolercontrol/plugins/coolerdash/CHANGELOG.md" - install -Dm600 "${srcdir}/etc/coolercontrol/plugins/coolerdash/config.json" "${pkgdir}/etc/coolercontrol/plugins/coolerdash/config.json" + install -Dm644 "${srcdir}/README.md" "${pkgdir}/var/lib/coolercontrol/plugins/coolerdash/README.md" + install -Dm644 "${srcdir}/VERSION" "${pkgdir}/var/lib/coolercontrol/plugins/coolerdash/VERSION" + install -Dm644 "${srcdir}/CHANGELOG.md" "${pkgdir}/var/lib/coolercontrol/plugins/coolerdash/CHANGELOG.md" + install -Dm600 "${srcdir}/var/lib/coolercontrol/plugins/coolerdash/config.json" "${pkgdir}/var/lib/coolercontrol/plugins/coolerdash/config.json" - install -dm755 "${pkgdir}/etc/coolercontrol/plugins/coolerdash/ui" - install -m644 "${srcdir}/etc/coolercontrol/plugins/coolerdash/ui/index.html" "${pkgdir}/etc/coolercontrol/plugins/coolerdash/ui/index.html" - install -Dm644 "${srcdir}/images/shutdown.png" "${pkgdir}/etc/coolercontrol/plugins/coolerdash/shutdown.png" - install -Dm644 "${srcdir}/etc/coolercontrol/plugins/coolerdash/manifest.toml" "${pkgdir}/etc/coolercontrol/plugins/coolerdash/manifest.toml" + install -dm755 "${pkgdir}/var/lib/coolercontrol/plugins/coolerdash/ui" + install -m644 "${srcdir}/var/lib/coolercontrol/plugins/coolerdash/ui/index.html" "${pkgdir}/var/lib/coolercontrol/plugins/coolerdash/ui/index.html" + install -Dm644 "${srcdir}/images/shutdown.png" "${pkgdir}/var/lib/coolercontrol/plugins/coolerdash/shutdown.png" + install -Dm644 "${srcdir}/var/lib/coolercontrol/plugins/coolerdash/manifest.toml" "${pkgdir}/var/lib/coolercontrol/plugins/coolerdash/manifest.toml" - sed -i "s/{{VERSION}}/${pkgver}/g" "${pkgdir}/etc/coolercontrol/plugins/coolerdash/manifest.toml" - sed -i "s/{{VERSION}}/${pkgver}/g" "${pkgdir}/etc/coolercontrol/plugins/coolerdash/ui/index.html" + sed -i "s/{{VERSION}}/${pkgver}/g" "${pkgdir}/var/lib/coolercontrol/plugins/coolerdash/manifest.toml" + sed -i "s/{{VERSION}}/${pkgver}/g" "${pkgdir}/var/lib/coolercontrol/plugins/coolerdash/ui/index.html" install -Dm644 "${srcdir}/man/coolerdash.1" "${pkgdir}/usr/share/man/man1/coolerdash.1" install -Dm644 "${srcdir}/etc/applications/coolerdash.desktop" "${pkgdir}/usr/share/applications/coolerdash.desktop" diff --git a/VERSION b/VERSION index ef538c2..ff365e0 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.1.2 +3.1.3 diff --git a/aur/PKGBUILD b/aur/PKGBUILD index d4c3176..1489068 100644 --- a/aur/PKGBUILD +++ b/aur/PKGBUILD @@ -12,8 +12,7 @@ url="https://github.com/damachine/coolerdash" license=('MIT') depends=('cairo' 'coolercontrol' 'jansson' 'libcurl-gnutls' 'ttf-roboto') makedepends=('gcc' 'make' 'pkg-config' 'git') -backup=('etc/coolercontrol/plugins/coolerdash/config.json' - 'etc/coolercontrol/plugins/coolerdash/credentials.json') +backup=('var/lib/coolercontrol/plugins/coolerdash/config.json') install=coolerdash.install _commit= source=("coolerdash-git::git+https://github.com/damachine/coolerdash.git#commit=${_commit}") @@ -56,21 +55,22 @@ check() { } package() { - # Binary to /usr/libexec, plugin data stays in /etc/coolercontrol/plugins/ - install -dm755 "${pkgdir}/etc/coolercontrol/plugins/coolerdash" + # Binary to /usr/libexec, plugin data to /var/lib/coolercontrol/plugins/ + install -dm711 "${pkgdir}/var/lib/coolercontrol" + install -dm755 "${pkgdir}/var/lib/coolercontrol/plugins/coolerdash" install -Dm755 "${srcdir}/${pkgname}/bin/coolerdash" "${pkgdir}/usr/libexec/coolerdash/coolerdash" - install -m644 "${srcdir}/${pkgname}/README.md" "${pkgdir}/etc/coolercontrol/plugins/coolerdash/README.md" - install -m644 "${srcdir}/${pkgname}/VERSION" "${pkgdir}/etc/coolercontrol/plugins/coolerdash/VERSION" - install -m644 "${srcdir}/${pkgname}/CHANGELOG.md" "${pkgdir}/etc/coolercontrol/plugins/coolerdash/CHANGELOG.md" - install -m600 "${srcdir}/${pkgname}/etc/coolercontrol/plugins/coolerdash/config.json" "${pkgdir}/etc/coolercontrol/plugins/coolerdash/config.json" + install -m644 "${srcdir}/${pkgname}/README.md" "${pkgdir}/var/lib/coolercontrol/plugins/coolerdash/README.md" + install -m644 "${srcdir}/${pkgname}/VERSION" "${pkgdir}/var/lib/coolercontrol/plugins/coolerdash/VERSION" + install -m644 "${srcdir}/${pkgname}/CHANGELOG.md" "${pkgdir}/var/lib/coolercontrol/plugins/coolerdash/CHANGELOG.md" + install -m600 "${srcdir}/${pkgname}/etc/coolercontrol/plugins/coolerdash/config.json" "${pkgdir}/var/lib/coolercontrol/plugins/coolerdash/config.json" - install -dm755 "${pkgdir}/etc/coolercontrol/plugins/coolerdash/ui" - install -m644 "${srcdir}/${pkgname}/etc/coolercontrol/plugins/coolerdash/ui/index.html" "${pkgdir}/etc/coolercontrol/plugins/coolerdash/ui/index.html" - install -m644 "${srcdir}/${pkgname}/images/shutdown.png" "${pkgdir}/etc/coolercontrol/plugins/coolerdash/shutdown.png" - install -m644 "${srcdir}/${pkgname}/etc/coolercontrol/plugins/coolerdash/manifest.toml" "${pkgdir}/etc/coolercontrol/plugins/coolerdash/manifest.toml" + install -dm755 "${pkgdir}/var/lib/coolercontrol/plugins/coolerdash/ui" + install -m644 "${srcdir}/${pkgname}/etc/coolercontrol/plugins/coolerdash/ui/index.html" "${pkgdir}/var/lib/coolercontrol/plugins/coolerdash/ui/index.html" + install -m644 "${srcdir}/${pkgname}/images/shutdown.png" "${pkgdir}/var/lib/coolercontrol/plugins/coolerdash/shutdown.png" + install -m644 "${srcdir}/${pkgname}/etc/coolercontrol/plugins/coolerdash/manifest.toml" "${pkgdir}/var/lib/coolercontrol/plugins/coolerdash/manifest.toml" - sed -i "s/{{VERSION}}/${pkgver}/g" "${pkgdir}/etc/coolercontrol/plugins/coolerdash/manifest.toml" - sed -i "s/{{VERSION}}/${pkgver}/g" "${pkgdir}/etc/coolercontrol/plugins/coolerdash/ui/index.html" + sed -i "s/{{VERSION}}/${pkgver}/g" "${pkgdir}/var/lib/coolercontrol/plugins/coolerdash/manifest.toml" + sed -i "s/{{VERSION}}/${pkgver}/g" "${pkgdir}/var/lib/coolercontrol/plugins/coolerdash/ui/index.html" install -Dm644 "${srcdir}/${pkgname}/man/coolerdash.1" "${pkgdir}/usr/share/man/man1/coolerdash.1" install -Dm644 "${srcdir}/${pkgname}/etc/applications/coolerdash.desktop" "${pkgdir}/usr/share/applications/coolerdash.desktop" diff --git a/aur/coolerdash.install b/aur/coolerdash.install index b6c708d..e730175 100644 --- a/aur/coolerdash.install +++ b/aur/coolerdash.install @@ -1,16 +1,8 @@ -# Created by: damachin3 (damachine3 at proton dot me) -# Website: https://github.com/damachine/coolerdash - -# Pacman install hooks - pre_install() { - # Stop legacy service if systemctl list-unit-files coolerdash.service | grep -q coolerdash; then systemctl stop coolerdash.service systemctl disable coolerdash.service fi - - # Remove legacy files rm -f /etc/systemd/system/coolerdash.service rm -f /etc/systemd/system/coolerdash-helperd.service rm -f /etc/systemd/system/multi-user.target.wants/coolerdash-helperd.service @@ -26,35 +18,73 @@ pre_install() { rm -f /usr/share/applications/coolerdash-settings.desktop rm -f /bin/coolerdash rm -f /usr/bin/coolerdash - - # Remove legacy user if id -u coolerdash &>/dev/null; then userdel -rf coolerdash fi + if [ -f /etc/coolercontrol/plugins/coolerdash/config.json ] && \ + [ ! -f /var/lib/coolercontrol/plugins/coolerdash/config.json ]; then + mkdir -p /var/lib/coolercontrol/plugins/coolerdash + cp /etc/coolercontrol/plugins/coolerdash/config.json \ + /var/lib/coolercontrol/plugins/coolerdash/config.json + chmod 600 /var/lib/coolercontrol/plugins/coolerdash/config.json + fi + if [ -f /etc/coolercontrol/plugins/coolerdash/credentials.json ] && \ + [ ! -f /var/lib/coolercontrol/plugins/coolerdash/credentials.json ]; then + mkdir -p /var/lib/coolercontrol/plugins/coolerdash + cp /etc/coolercontrol/plugins/coolerdash/credentials.json \ + /var/lib/coolercontrol/plugins/coolerdash/credentials.json + chmod 600 /var/lib/coolercontrol/plugins/coolerdash/credentials.json + fi + rm -f /etc/coolercontrol/plugins/coolerdash/manifest.toml + rm -rf /etc/coolercontrol/plugins/coolerdash/ui + rm -f /etc/coolercontrol/plugins/coolerdash/shutdown.png + rm -f /etc/coolercontrol/plugins/coolerdash/README.md + rm -f /etc/coolercontrol/plugins/coolerdash/CHANGELOG.md + rm -f /etc/coolercontrol/plugins/coolerdash/VERSION +} + +pre_upgrade() { + if [ -f /etc/coolercontrol/plugins/coolerdash/config.json ] && \ + [ ! -f /var/lib/coolercontrol/plugins/coolerdash/config.json ]; then + mkdir -p /var/lib/coolercontrol/plugins/coolerdash + cp /etc/coolercontrol/plugins/coolerdash/config.json \ + /var/lib/coolercontrol/plugins/coolerdash/config.json + chmod 600 /var/lib/coolercontrol/plugins/coolerdash/config.json + fi + if [ -f /etc/coolercontrol/plugins/coolerdash/credentials.json ] && \ + [ ! -f /var/lib/coolercontrol/plugins/coolerdash/credentials.json ]; then + mkdir -p /var/lib/coolercontrol/plugins/coolerdash + cp /etc/coolercontrol/plugins/coolerdash/credentials.json \ + /var/lib/coolercontrol/plugins/coolerdash/credentials.json + chmod 600 /var/lib/coolercontrol/plugins/coolerdash/credentials.json + fi + rm -f /etc/coolercontrol/plugins/coolerdash/manifest.toml + rm -rf /etc/coolercontrol/plugins/coolerdash/ui + rm -f /etc/coolercontrol/plugins/coolerdash/shutdown.png + rm -f /etc/coolercontrol/plugins/coolerdash/README.md + rm -f /etc/coolercontrol/plugins/coolerdash/CHANGELOG.md + rm -f /etc/coolercontrol/plugins/coolerdash/VERSION } post_install() { - # Remove legacy files rm -f /etc/systemd/system/multi-user.target.wants/coolerdash-helperd.service rm -f /etc/systemd/system/coolerdash-helperd.service rm -f /usr/lib/systemd/system/coolerdash-helperd.service rm -rf /etc/systemd/system/cc-plugin-coolerdash.service.d rm -f /usr/lib/udev/rules.d/99-coolerdash.rules - - # Ensure correct permissions on config.json - chmod 600 /etc/coolercontrol/plugins/coolerdash/config.json 2>/dev/null || true - chmod 600 /etc/coolercontrol/plugins/coolerdash/credentials.json 2>/dev/null || true - + if [ ! -f /var/lib/coolercontrol/plugins/coolerdash/credentials.json ]; then + mkdir -p /var/lib/coolercontrol/plugins/coolerdash + printf '{\n "access_token": ""\n}\n' > /var/lib/coolercontrol/plugins/coolerdash/credentials.json + fi + chmod 600 /var/lib/coolercontrol/plugins/coolerdash/config.json 2>/dev/null || true + chmod 600 /var/lib/coolercontrol/plugins/coolerdash/credentials.json 2>/dev/null || true systemctl daemon-reload - - # Restart plugin service directly if it already exists (reinstall case) + systemctl reset-failed cc-plugin-coolerdash.service >/dev/null 2>&1 || true if systemctl list-unit-files cc-plugin-coolerdash.service | grep -q cc-plugin-coolerdash; then systemctl restart cc-plugin-coolerdash.service || echo "Note: Plugin restart failed." - else - # Fresh install: restart CoolerControl so it discovers and starts the plugin service - if systemctl list-unit-files coolercontrold.service | grep -q coolercontrold; then - systemctl restart coolercontrold.service || echo "Note: CoolerControl restart failed." - fi + fi + if systemctl list-unit-files coolercontrold.service | grep -q coolercontrold; then + systemctl restart coolercontrold.service || echo "Note: CoolerControl restart failed." fi echo "================================================================" @@ -65,52 +95,47 @@ post_install() { } post_upgrade() { - # Remove legacy files rm -f /etc/systemd/system/multi-user.target.wants/coolerdash-helperd.service rm -f /etc/systemd/system/coolerdash-helperd.service rm -f /usr/lib/systemd/system/coolerdash-helperd.service rm -rf /etc/systemd/system/cc-plugin-coolerdash.service.d rm -f /usr/lib/udev/rules.d/99-coolerdash.rules - - # Ensure correct permissions on config.json - chmod 600 /etc/coolercontrol/plugins/coolerdash/config.json 2>/dev/null || true - chmod 600 /etc/coolercontrol/plugins/coolerdash/credentials.json 2>/dev/null || true - + if [ ! -f /var/lib/coolercontrol/plugins/coolerdash/credentials.json ]; then + mkdir -p /var/lib/coolercontrol/plugins/coolerdash + printf '{\n "access_token": ""\n}\n' > /var/lib/coolercontrol/plugins/coolerdash/credentials.json + fi + chmod 600 /var/lib/coolercontrol/plugins/coolerdash/config.json 2>/dev/null || true + chmod 600 /var/lib/coolercontrol/plugins/coolerdash/credentials.json 2>/dev/null || true systemctl daemon-reload - - # Restart plugin + systemctl reset-failed cc-plugin-coolerdash.service >/dev/null 2>&1 || true if systemctl list-unit-files cc-plugin-coolerdash.service | grep -q cc-plugin-coolerdash; then systemctl restart cc-plugin-coolerdash.service || echo "Note: Plugin restart failed." fi + if systemctl list-unit-files coolercontrold.service | grep -q coolercontrold; then + systemctl restart coolercontrold.service || echo "Note: CoolerControl restart failed." + fi echo "================================================================" echo "CoolerDash upgraded successfully." echo "Note: config.json is preserved. If a new template was shipped," - echo " compare it with /etc/coolercontrol/plugins/coolerdash/config.json.pacnew" + echo " compare it with /var/lib/coolercontrol/plugins/coolerdash/config.json.pacnew" echo "Note: credentials.json is never overwritten by updates." echo "================================================================" } pre_remove() { - # Stop legacy service if systemctl list-unit-files coolerdash.service | grep -q coolerdash; then systemctl stop coolerdash.service systemctl disable coolerdash.service fi - - # Stop plugin if systemctl list-unit-files cc-plugin-coolerdash.service | grep -q cc-plugin-coolerdash; then systemctl stop cc-plugin-coolerdash.service systemctl disable cc-plugin-coolerdash.service fi - - # Stop helperd if systemctl list-unit-files coolerdash-helperd.service | grep -q coolerdash-helperd; then systemctl stop --no-block coolerdash-helperd.service systemctl disable coolerdash-helperd.service fi - - # Remove legacy files rm -f /etc/systemd/system/coolerdash-helperd.service rm -f /etc/systemd/system/coolerdash.service rm -f /etc/systemd/system/multi-user.target.wants/coolerdash-helperd.service @@ -124,15 +149,10 @@ pre_remove() { rm -f /usr/bin/coolerdash rm -rf /opt/coolerdash rm -rf /etc/coolerdash - - # Remove legacy user if id -u coolerdash &>/dev/null; then userdel -rf coolerdash fi - systemctl daemon-reload - - # Restart CoolerControl if systemctl list-unit-files coolercontrold.service | grep -q coolercontrold; then systemctl restart coolercontrold.service || echo "Note: CoolerControl restart failed." fi diff --git a/coolerdash.install b/coolerdash.install index b6c708d..e730175 100644 --- a/coolerdash.install +++ b/coolerdash.install @@ -1,16 +1,8 @@ -# Created by: damachin3 (damachine3 at proton dot me) -# Website: https://github.com/damachine/coolerdash - -# Pacman install hooks - pre_install() { - # Stop legacy service if systemctl list-unit-files coolerdash.service | grep -q coolerdash; then systemctl stop coolerdash.service systemctl disable coolerdash.service fi - - # Remove legacy files rm -f /etc/systemd/system/coolerdash.service rm -f /etc/systemd/system/coolerdash-helperd.service rm -f /etc/systemd/system/multi-user.target.wants/coolerdash-helperd.service @@ -26,35 +18,73 @@ pre_install() { rm -f /usr/share/applications/coolerdash-settings.desktop rm -f /bin/coolerdash rm -f /usr/bin/coolerdash - - # Remove legacy user if id -u coolerdash &>/dev/null; then userdel -rf coolerdash fi + if [ -f /etc/coolercontrol/plugins/coolerdash/config.json ] && \ + [ ! -f /var/lib/coolercontrol/plugins/coolerdash/config.json ]; then + mkdir -p /var/lib/coolercontrol/plugins/coolerdash + cp /etc/coolercontrol/plugins/coolerdash/config.json \ + /var/lib/coolercontrol/plugins/coolerdash/config.json + chmod 600 /var/lib/coolercontrol/plugins/coolerdash/config.json + fi + if [ -f /etc/coolercontrol/plugins/coolerdash/credentials.json ] && \ + [ ! -f /var/lib/coolercontrol/plugins/coolerdash/credentials.json ]; then + mkdir -p /var/lib/coolercontrol/plugins/coolerdash + cp /etc/coolercontrol/plugins/coolerdash/credentials.json \ + /var/lib/coolercontrol/plugins/coolerdash/credentials.json + chmod 600 /var/lib/coolercontrol/plugins/coolerdash/credentials.json + fi + rm -f /etc/coolercontrol/plugins/coolerdash/manifest.toml + rm -rf /etc/coolercontrol/plugins/coolerdash/ui + rm -f /etc/coolercontrol/plugins/coolerdash/shutdown.png + rm -f /etc/coolercontrol/plugins/coolerdash/README.md + rm -f /etc/coolercontrol/plugins/coolerdash/CHANGELOG.md + rm -f /etc/coolercontrol/plugins/coolerdash/VERSION +} + +pre_upgrade() { + if [ -f /etc/coolercontrol/plugins/coolerdash/config.json ] && \ + [ ! -f /var/lib/coolercontrol/plugins/coolerdash/config.json ]; then + mkdir -p /var/lib/coolercontrol/plugins/coolerdash + cp /etc/coolercontrol/plugins/coolerdash/config.json \ + /var/lib/coolercontrol/plugins/coolerdash/config.json + chmod 600 /var/lib/coolercontrol/plugins/coolerdash/config.json + fi + if [ -f /etc/coolercontrol/plugins/coolerdash/credentials.json ] && \ + [ ! -f /var/lib/coolercontrol/plugins/coolerdash/credentials.json ]; then + mkdir -p /var/lib/coolercontrol/plugins/coolerdash + cp /etc/coolercontrol/plugins/coolerdash/credentials.json \ + /var/lib/coolercontrol/plugins/coolerdash/credentials.json + chmod 600 /var/lib/coolercontrol/plugins/coolerdash/credentials.json + fi + rm -f /etc/coolercontrol/plugins/coolerdash/manifest.toml + rm -rf /etc/coolercontrol/plugins/coolerdash/ui + rm -f /etc/coolercontrol/plugins/coolerdash/shutdown.png + rm -f /etc/coolercontrol/plugins/coolerdash/README.md + rm -f /etc/coolercontrol/plugins/coolerdash/CHANGELOG.md + rm -f /etc/coolercontrol/plugins/coolerdash/VERSION } post_install() { - # Remove legacy files rm -f /etc/systemd/system/multi-user.target.wants/coolerdash-helperd.service rm -f /etc/systemd/system/coolerdash-helperd.service rm -f /usr/lib/systemd/system/coolerdash-helperd.service rm -rf /etc/systemd/system/cc-plugin-coolerdash.service.d rm -f /usr/lib/udev/rules.d/99-coolerdash.rules - - # Ensure correct permissions on config.json - chmod 600 /etc/coolercontrol/plugins/coolerdash/config.json 2>/dev/null || true - chmod 600 /etc/coolercontrol/plugins/coolerdash/credentials.json 2>/dev/null || true - + if [ ! -f /var/lib/coolercontrol/plugins/coolerdash/credentials.json ]; then + mkdir -p /var/lib/coolercontrol/plugins/coolerdash + printf '{\n "access_token": ""\n}\n' > /var/lib/coolercontrol/plugins/coolerdash/credentials.json + fi + chmod 600 /var/lib/coolercontrol/plugins/coolerdash/config.json 2>/dev/null || true + chmod 600 /var/lib/coolercontrol/plugins/coolerdash/credentials.json 2>/dev/null || true systemctl daemon-reload - - # Restart plugin service directly if it already exists (reinstall case) + systemctl reset-failed cc-plugin-coolerdash.service >/dev/null 2>&1 || true if systemctl list-unit-files cc-plugin-coolerdash.service | grep -q cc-plugin-coolerdash; then systemctl restart cc-plugin-coolerdash.service || echo "Note: Plugin restart failed." - else - # Fresh install: restart CoolerControl so it discovers and starts the plugin service - if systemctl list-unit-files coolercontrold.service | grep -q coolercontrold; then - systemctl restart coolercontrold.service || echo "Note: CoolerControl restart failed." - fi + fi + if systemctl list-unit-files coolercontrold.service | grep -q coolercontrold; then + systemctl restart coolercontrold.service || echo "Note: CoolerControl restart failed." fi echo "================================================================" @@ -65,52 +95,47 @@ post_install() { } post_upgrade() { - # Remove legacy files rm -f /etc/systemd/system/multi-user.target.wants/coolerdash-helperd.service rm -f /etc/systemd/system/coolerdash-helperd.service rm -f /usr/lib/systemd/system/coolerdash-helperd.service rm -rf /etc/systemd/system/cc-plugin-coolerdash.service.d rm -f /usr/lib/udev/rules.d/99-coolerdash.rules - - # Ensure correct permissions on config.json - chmod 600 /etc/coolercontrol/plugins/coolerdash/config.json 2>/dev/null || true - chmod 600 /etc/coolercontrol/plugins/coolerdash/credentials.json 2>/dev/null || true - + if [ ! -f /var/lib/coolercontrol/plugins/coolerdash/credentials.json ]; then + mkdir -p /var/lib/coolercontrol/plugins/coolerdash + printf '{\n "access_token": ""\n}\n' > /var/lib/coolercontrol/plugins/coolerdash/credentials.json + fi + chmod 600 /var/lib/coolercontrol/plugins/coolerdash/config.json 2>/dev/null || true + chmod 600 /var/lib/coolercontrol/plugins/coolerdash/credentials.json 2>/dev/null || true systemctl daemon-reload - - # Restart plugin + systemctl reset-failed cc-plugin-coolerdash.service >/dev/null 2>&1 || true if systemctl list-unit-files cc-plugin-coolerdash.service | grep -q cc-plugin-coolerdash; then systemctl restart cc-plugin-coolerdash.service || echo "Note: Plugin restart failed." fi + if systemctl list-unit-files coolercontrold.service | grep -q coolercontrold; then + systemctl restart coolercontrold.service || echo "Note: CoolerControl restart failed." + fi echo "================================================================" echo "CoolerDash upgraded successfully." echo "Note: config.json is preserved. If a new template was shipped," - echo " compare it with /etc/coolercontrol/plugins/coolerdash/config.json.pacnew" + echo " compare it with /var/lib/coolercontrol/plugins/coolerdash/config.json.pacnew" echo "Note: credentials.json is never overwritten by updates." echo "================================================================" } pre_remove() { - # Stop legacy service if systemctl list-unit-files coolerdash.service | grep -q coolerdash; then systemctl stop coolerdash.service systemctl disable coolerdash.service fi - - # Stop plugin if systemctl list-unit-files cc-plugin-coolerdash.service | grep -q cc-plugin-coolerdash; then systemctl stop cc-plugin-coolerdash.service systemctl disable cc-plugin-coolerdash.service fi - - # Stop helperd if systemctl list-unit-files coolerdash-helperd.service | grep -q coolerdash-helperd; then systemctl stop --no-block coolerdash-helperd.service systemctl disable coolerdash-helperd.service fi - - # Remove legacy files rm -f /etc/systemd/system/coolerdash-helperd.service rm -f /etc/systemd/system/coolerdash.service rm -f /etc/systemd/system/multi-user.target.wants/coolerdash-helperd.service @@ -124,15 +149,10 @@ pre_remove() { rm -f /usr/bin/coolerdash rm -rf /opt/coolerdash rm -rf /etc/coolerdash - - # Remove legacy user if id -u coolerdash &>/dev/null; then userdel -rf coolerdash fi - systemctl daemon-reload - - # Restart CoolerControl if systemctl list-unit-files coolercontrold.service | grep -q coolercontrold; then systemctl restart coolercontrold.service || echo "Note: CoolerControl restart failed." fi diff --git a/etc/coolercontrol/plugins/coolerdash/config.json b/etc/coolercontrol/plugins/coolerdash/config.json index 24defa5..36e08f4 100644 --- a/etc/coolercontrol/plugins/coolerdash/config.json +++ b/etc/coolercontrol/plugins/coolerdash/config.json @@ -12,10 +12,10 @@ }, "paths": { - "images": "/etc/coolercontrol/plugins/coolerdash", - "image_coolerdash": "/etc/coolercontrol/plugins/coolerdash/coolerdash.png", + "images": "/var/lib/coolercontrol/plugins/coolerdash", + "image_coolerdash": "/var/lib/coolercontrol/plugins/coolerdash/coolerdash.png", "image_background": "", - "image_shutdown": "/etc/coolercontrol/plugins/coolerdash/shutdown.png" + "image_shutdown": "/var/lib/coolercontrol/plugins/coolerdash/shutdown.png" }, "display": { diff --git a/etc/coolercontrol/plugins/coolerdash/credentials.json b/etc/coolercontrol/plugins/coolerdash/credentials.json new file mode 100644 index 0000000..e69de29 diff --git a/etc/coolercontrol/plugins/coolerdash/ui/index.html b/etc/coolercontrol/plugins/coolerdash/ui/index.html index 35e0d88..abf7d6b 100644 --- a/etc/coolercontrol/plugins/coolerdash/ui/index.html +++ b/etc/coolercontrol/plugins/coolerdash/ui/index.html @@ -9,19 +9,21 @@ * { margin: 0; padding: 0; box-sizing: border-box; } :root { - --bg-primary: rgb(26, 26, 46); - --bg-secondary: rgb(22, 33, 62); - --bg-card: rgb(30, 35, 55); - --bg-input: rgb(20, 28, 48); - --border: rgb(45, 66, 99); - --border-light: rgb(55, 76, 109); - --text: rgb(234, 234, 234); - --text-dim: rgb(140, 145, 165); - --text-muted: rgb(100, 105, 125); - --accent: rgb(233, 69, 96); - --accent-hover: rgb(255, 89, 116); - --accent-glow: rgba(233, 69, 96, 0.15); - --success: rgb(34, 197, 94); + /* CoolerControl theme CSS variables. + These fallback values maintain the original dark theme in standalone/dev mode. + When runPluginScript() injects the CC parent stylesheet, CC's :root definitions + override these values, making the entire UI automatically adapt to the active theme. */ + --bg-one: 26 26 46; + --bg-two: 30 35 55; + --text-color: 234 234 234; + --text-color-secondary: 140 145 165; + --border-one: 45 66 99; + --accent: 233 69 96; + --surface-hover: 38 48 78; + --success: 34 197 94; + --error: 233 69 96; + --warning: 255 140 0; + /* Structural — not theme-dependent */ --radius: 10px; --radius-sm: 6px; --shadow: 0 4px 20px rgba(0, 0, 0, 0.25); @@ -30,8 +32,8 @@ body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Inter', sans-serif; - background: linear-gradient(135deg, var(--bg-secondary) 0%, var(--bg-primary) 100%); - color: var(--text); + background: linear-gradient(135deg, rgb(var(--bg-two)) 0%, rgb(var(--bg-one)) 100%); + color: rgb(var(--text-color)); line-height: 1.6; padding: 24px; min-height: 100vh; @@ -44,12 +46,12 @@ /* Header */ .header { - background: var(--bg-card); + background: rgb(var(--bg-two)); border-radius: var(--radius); padding: 28px 32px; margin-bottom: 20px; box-shadow: var(--shadow); - border: 1px solid var(--border); + border: 1px solid rgb(var(--border-one)); } .header h1 { @@ -59,21 +61,21 @@ display: flex; align-items: center; gap: 12px; - background: linear-gradient(135deg, var(--text) 0%, var(--text-dim) 100%); + background: linear-gradient(135deg, rgb(var(--text-color)) 0%, rgb(var(--text-color-secondary)) 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; } .header p { - color: var(--text-dim); + color: rgb(var(--text-color-secondary)); font-size: 14px; } /* Device Tab */ .device-info-card { - background: var(--bg-input); - border: 1px solid var(--border); + background: rgb(var(--bg-one)); + border: 1px solid rgb(var(--border-one)); border-radius: var(--radius); padding: 20px 24px; margin-bottom: 16px; @@ -84,7 +86,7 @@ justify-content: space-between; align-items: center; padding: 10px 0; - border-bottom: 1px solid rgba(45, 66, 99, 0.4); + border-bottom: 1px solid rgb(var(--border-one) / 0.4); } .device-info-row:last-child { @@ -93,14 +95,14 @@ .device-info-label { font-size: 13px; - color: var(--text-dim); + color: rgb(var(--text-color-secondary)); font-weight: 500; } .device-info-value { font-size: 14px; font-weight: 600; - color: var(--text); + color: rgb(var(--text-color)); } .device-info-value.mono { @@ -118,18 +120,18 @@ } .device-status.connected { - background: rgba(34, 197, 94, 0.12); - color: var(--success); + background: rgb(var(--success) / 0.12); + color: rgb(var(--success)); } .device-status.disconnected { - background: rgba(255, 140, 0, 0.12); - color: #ff8c00; + background: rgb(var(--warning) / 0.12); + color: rgb(var(--warning)); } .device-status.error { - background: rgba(233, 69, 96, 0.12); - color: var(--accent); + background: rgb(var(--error) / 0.12); + color: rgb(var(--error)); } .device-status-dot { @@ -145,7 +147,7 @@ .info-item-label { font-size: 11px; - color: var(--text-muted); + color: rgb(var(--text-color-secondary)); text-transform: uppercase; letter-spacing: 0.8px; margin-bottom: 4px; @@ -153,16 +155,17 @@ .info-item-value { font-size: 14px; - color: var(--text); + color: rgb(var(--text-color)); } .info-item-value a { - color: var(--accent); + color: rgb(var(--accent)); text-decoration: none; } .info-item-value a:hover { - color: var(--accent-hover); + color: rgb(var(--accent)); + opacity: 0.8; text-decoration: underline; } @@ -171,13 +174,13 @@ display: flex; gap: 6px; margin-bottom: 20px; - background: var(--bg-card); + background: rgb(var(--bg-two)); padding: 10px; border-radius: var(--radius); box-shadow: var(--shadow-sm); overflow-x: auto; flex-wrap: wrap; - border: 1px solid var(--border); + border: 1px solid rgb(var(--border-one)); } .tab { @@ -187,7 +190,7 @@ background: transparent; border: none; border-radius: var(--radius-sm); - color: var(--text-dim); + color: rgb(var(--text-color-secondary)); cursor: pointer; font-size: 13px; font-weight: 500; @@ -196,25 +199,25 @@ } .tab:hover { - background: var(--accent-glow); - color: var(--text); + background: rgb(var(--surface-hover)); + color: rgb(var(--text-color)); } .tab.active { - background: var(--accent); + background: rgb(var(--accent)); color: white; - box-shadow: 0 2px 8px rgba(233, 69, 96, 0.4); + box-shadow: 0 2px 8px rgb(var(--accent) / 0.4); } /* Panel */ .panel { display: none; - background: var(--bg-card); + background: rgb(var(--bg-two)); border-radius: var(--radius); padding: 28px 32px; box-shadow: var(--shadow); animation: fadeIn 0.3s ease; - border: 1px solid var(--border); + border: 1px solid rgb(var(--border-one)); } .panel.active { @@ -231,8 +234,8 @@ margin: 32px 0 20px; font-size: 13px; font-weight: 600; - color: var(--accent); - border-bottom: 1px solid var(--border); + color: rgb(var(--accent)); + border-bottom: 1px solid rgb(var(--border-one)); padding-bottom: 10px; text-transform: uppercase; letter-spacing: 1px; @@ -257,36 +260,37 @@ font-weight: 500; margin-bottom: 8px; font-size: 13px; - color: var(--text); + color: rgb(var(--text-color)); } .form-hint { display: block; font-size: 11px; - color: var(--text-muted); + color: rgb(var(--text-color-secondary)); margin-bottom: 8px; } .form-control { width: 100%; padding: 11px 14px; - background: var(--bg-input); - border: 1px solid var(--border); + background: rgb(var(--bg-one)); + border: 1px solid rgb(var(--border-one)); border-radius: var(--radius-sm); - color: var(--text); + color: rgb(var(--text-color)); font-size: 14px; transition: all 0.2s ease; } .form-control:hover { - border-color: var(--border-light); + border-color: rgb(var(--border-one)); + opacity: 0.9; } .form-control:focus { outline: none; - border-color: var(--accent); - box-shadow: 0 0 0 3px var(--accent-glow); - background: var(--bg-secondary); + border-color: rgb(var(--accent)); + box-shadow: 0 0 0 3px rgb(var(--accent) / 0.15); + background: rgb(var(--bg-two)); } .form-control[type="number"] { @@ -335,21 +339,21 @@ flex: 1; height: 6px; appearance: none; - background: var(--bg-input); + background: rgb(var(--bg-one)); border-radius: 3px; outline: none; -webkit-appearance: none; - border: 1px solid var(--border); + border: 1px solid rgb(var(--border-one)); } .range-input::-webkit-slider-thumb { -webkit-appearance: none; width: 20px; height: 20px; - background: var(--accent); + background: rgb(var(--accent)); border-radius: 50%; cursor: pointer; - box-shadow: 0 2px 6px rgba(233, 69, 96, 0.4); + box-shadow: 0 2px 6px rgb(var(--accent) / 0.4); transition: transform 0.15s ease; } @@ -361,7 +365,7 @@ min-width: 55px; text-align: right; font-weight: 600; - color: var(--accent); + color: rgb(var(--accent)); font-size: 14px; font-variant-numeric: tabular-nums; } @@ -377,20 +381,21 @@ width: 52px; height: 42px; border-radius: var(--radius-sm); - border: 2px solid var(--border); + border: 2px solid rgb(var(--border-one)); cursor: pointer; transition: all 0.2s ease; } .color-swatch:hover { transform: scale(1.05); - border-color: var(--border-light); + border-color: rgb(var(--border-one)); + opacity: 0.85; } .color-rgb { font-family: 'SF Mono', 'Fira Code', 'Courier New', monospace; font-size: 12px; - color: var(--text-muted); + color: rgb(var(--text-color-secondary)); letter-spacing: 0.3px; } @@ -400,7 +405,7 @@ gap: 14px; margin-top: 28px; padding-top: 28px; - border-top: 1px solid var(--border); + border-top: 1px solid rgb(var(--border-one)); } .btn { @@ -419,31 +424,33 @@ } .btn-primary { - background: linear-gradient(135deg, var(--accent) 0%, var(--accent-hover) 100%); + background: rgb(var(--accent)); color: white; - box-shadow: 0 4px 14px rgba(233, 69, 96, 0.35); + box-shadow: 0 4px 14px rgb(var(--accent) / 0.35); } .btn-primary:hover { transform: translateY(-2px); - box-shadow: 0 6px 20px rgba(233, 69, 96, 0.45); + box-shadow: 0 6px 20px rgb(var(--accent) / 0.45); + opacity: 0.9; } .btn-secondary { - background: var(--bg-input); - color: var(--text); - border: 1px solid var(--border); + background: rgb(var(--bg-one)); + color: rgb(var(--text-color)); + border: 1px solid rgb(var(--border-one)); } .btn-secondary:hover { - background: var(--bg-secondary); - border-color: var(--border-light); + background: rgb(var(--bg-two)); + border-color: rgb(var(--border-one)); + opacity: 0.9; } /* Alert */ .alert { - background: var(--accent-glow); - border-left: 4px solid var(--accent); + background: rgb(var(--accent) / 0.12); + border-left: 4px solid rgb(var(--accent)); padding: 14px 18px; border-radius: var(--radius-sm); margin-bottom: 24px; @@ -453,19 +460,19 @@ .alert strong { display: block; margin-bottom: 6px; - color: var(--text); + color: rgb(var(--text-color)); } .alert-warning { - background: rgba(255, 140, 0, 0.12); - border-left-color: #ff8c00; + background: rgb(var(--warning) / 0.12); + border-left-color: rgb(var(--warning)); } /* Scrollbar */ ::-webkit-scrollbar { width: 8px; height: 8px; } - ::-webkit-scrollbar-track { background: var(--bg-primary); border-radius: 4px; } - ::-webkit-scrollbar-thumb { background: var(--border); border-radius: 4px; } - ::-webkit-scrollbar-thumb:hover { background: var(--accent); } + ::-webkit-scrollbar-track { background: rgb(var(--bg-one)); border-radius: 4px; } + ::-webkit-scrollbar-thumb { background: rgb(var(--border-one)); border-radius: 4px; } + ::-webkit-scrollbar-thumb:hover { background: rgb(var(--accent)); } /* Sensor Config Sections */ .sensor-config-section { @@ -479,7 +486,7 @@ /* Collapsible details (used in Sensors + Layout tabs) */ .sensor-details, .collapsible-details { - border: 1px solid var(--border); + border: 1px solid rgb(var(--border-one)); border-radius: 8px; overflow: hidden; } @@ -487,11 +494,11 @@ .sensor-details summary, .collapsible-details summary { padding: 12px 16px; - background: var(--bg-secondary); + background: rgb(var(--bg-two)); cursor: pointer; font-weight: 600; font-size: 15px; - color: var(--text-primary); + color: rgb(var(--text-color)); display: flex; align-items: center; gap: 8px; @@ -509,7 +516,7 @@ content: '\25B6'; font-size: 10px; transition: transform 0.2s; - color: var(--text-dim); + color: rgb(var(--text-color-secondary)); } .sensor-details[open] summary::before, @@ -519,12 +526,12 @@ .sensor-details[open] summary, .collapsible-details[open] summary { - border-bottom: 1px solid var(--border); + border-bottom: 1px solid rgb(var(--border-one)); } .sensor-details summary:hover, .collapsible-details summary:hover { - background: var(--bg-primary); + background: rgb(var(--surface-hover)); } .sensor-details-content, @@ -536,12 +543,12 @@ .collapsible-details .sub-section-title { font-size: 13px; font-weight: 600; - color: var(--accent); + color: rgb(var(--accent)); text-transform: uppercase; letter-spacing: 0.5px; margin: 16px 0 8px 0; padding-bottom: 4px; - border-bottom: 1px solid rgba(255,107,129,0.15); + border-bottom: 1px solid rgb(var(--accent) / 0.15); } .sensor-details .sub-section-title:first-child, @@ -556,7 +563,7 @@

CoolerDash Configuration

Customize your LCD temperature dashboard • Changes require plugin restart

-

+

💡 Tip: After an update, click Reset to apply new default values. Feedback & bug reports are welcome — see the Info tab for links.

@@ -590,7 +597,7 @@

CoolerDash Configuration

Authentication — CC4 (Bearer Token)

CoolerControl 4.0 requires API authentication. -
    +
    1. Open the CoolerControl UI
    2. Bottom-left corner → 🔒 Access Protection → Access Tokens
    3. Generate a new Access Token
    4. @@ -744,7 +751,7 @@

      Background & Shutdown Images

- Displayed on the LCD when the daemon stops. Default: /etc/coolercontrol/plugins/coolerdash/shutdown.png + Displayed on the LCD when the daemon stops. Default: /var/lib/coolercontrol/plugins/coolerdash/shutdown.png
@@ -978,7 +985,7 @@

Text Colors

-

+

Discovering sensors from CoolerControl API…

@@ -1107,7 +1114,7 @@

About CoolerDash

Description
-
Displays CPU, GPU, and Liquid temperatures on AIO liquid cooler LCD screens (NZXT Kraken, etc.)
+
Displays CPU, GPU, and Liquid temperatures on AIO liquid cooler LCD screens (NZXT Kraken, etc.)
Author
@@ -1167,7 +1174,7 @@

System Environment

-

+

Note: Clicking Save will automatically apply the configuration and restart the plugin.

@@ -1186,8 +1193,10 @@

System Environment

blocklist: "mainboard\nmotherboard\nchipset" }, paths: { + images: "/var/lib/coolercontrol/plugins/coolerdash", + image_coolerdash: "/var/lib/coolercontrol/plugins/coolerdash/coolerdash.png", image_background: "", - image_shutdown: "/etc/coolercontrol/plugins/coolerdash/shutdown.png" + image_shutdown: "/var/lib/coolercontrol/plugins/coolerdash/shutdown.png" }, display: { mode: "circle", @@ -1374,6 +1383,13 @@

System Environment

}; } + if (typeof restartPlugin === 'undefined') { + window.restartPlugin = async function() { + console.info('restartPlugin: not in CoolerControl — skipping restart.'); + return true; + }; + } + // Fallback for getDevices() — used when cc-plugin-lib.js is not loaded (dev/browser mode) // Note: cc-plugin-lib defines functions with `const` (not var/window), so typeof check always // triggers even when cc-plugin-lib is loaded. We therefore implement postMessage for CC4 context. @@ -1551,8 +1567,9 @@

System Environment

var name = String(device.name || ''); // Device type: Liquidctl = AIO cooler driver, others penalised + // ServicePlugin = software daemon (CC v4.3.0+), never LCD hardware if (type === 'Liquidctl') score += 30; - else if (type === 'Hwmon' || type === 'CustomSensors' || type === 'CPU' || type === 'GPU') score -= 40; + else if (type === 'Hwmon' || type === 'CustomSensors' || type === 'CPU' || type === 'GPU' || type === 'ServicePlugin') score -= 40; else if (type) score += 8; // Capability signals (independent of brand): has an 'lcd' channel key @@ -1707,21 +1724,21 @@

System Environment

if (sensors.length === 0) { setSensorDiscoveryStatus('warn', 'No extra sensors found — CoolerControl API is reachable, but returned no temperature or channel data.
' + - 'Only Standard sensors (CPU, GPU, Liquid) are shown. ' + - '' + 'Only Standard sensors (CPU, GPU, Liquid) are shown. ' + + '' ); } else { setSensorDiscoveryStatus('ok', '✔ ' + sensors.length + ' sensor(s) discovered from CoolerControl API — see “CC4 Sensors” section below. ' + - '' + '' ); } } catch (error) { console.warn('Sensor discovery failed:', error); setSensorDiscoveryStatus('error', 'CC4 Sensor Discovery failed — ' + escapeHtml(error.message) + '.
' + - 'Make sure CoolerControl is running and the API address in the Connection tab is correct. ' + - '' + 'Make sure CoolerControl is running and the API address in the Connection tab is correct. ' + + '' ); } } @@ -1733,7 +1750,10 @@

System Environment

var addrInput = document.querySelector('[name="daemon.address"]'); var tokenInput = document.querySelector('[name="daemon.access_token"]'); if (addrInput && addrInput.value) apiAddr = addrInput.value; - if (tokenInput) apiToken = tokenInput.value; + if (tokenInput) { + var _tv = tokenInput.value; + apiToken = (_tv === '***' && tokenInput.dataset.realToken) ? tokenInput.dataset.realToken : _tv; + } var statusEl = document.getElementById('sensor-discovery-status'); if (statusEl) { statusEl.style.display = 'block'; @@ -1913,7 +1933,7 @@

System Environment

}); if (sensorIds.length === 0) { - container.innerHTML = '

No sensors found. Make sure CoolerControl is running and reachable.

'; + container.innerHTML = '

No sensors found. Make sure CoolerControl is running and reachable.

'; return; } @@ -2284,7 +2304,7 @@

System Environment

var latest = (data.tag_name || '').replace(/^v/i, ''); var dlUrl = 'https://github.com/damachine/coolerdash/releases/tag/' + (data.tag_name || 'latest'); if (latest && latest !== current) { - el.innerHTML = 'v' + latest + ' available — ' + el.innerHTML = 'v' + latest + ' available — ' + 'Download'; } else { el.textContent = 'v' + (latest || current) + ' (up to date)'; @@ -2295,9 +2315,6 @@

System Environment

})(); try { - lastApiAddress = apiAddress; - lastApiToken = token; - // /health fetch isolated so a failure doesn't block the kernel lookup below. // Also used as fallback in dev/browser mode where fetch() works. var healthFetched = false; @@ -2515,6 +2532,12 @@

System Environment

var extraInfoCb = document.getElementById('circle_show_extra_info'); config.display.circle_show_extra_info = extraInfoCb ? extraInfoCb.checked : false; + // Restore real token if user left the *** placeholder unchanged + var _tokenInput = document.querySelector('[name="daemon.access_token"]'); + if (_tokenInput && _tokenInput.value.trim() === '***' && _tokenInput.dataset.realToken) { + config.daemon.access_token = _tokenInput.dataset.realToken; + } + var merged = mergeConfigWithDefaults(config, DEFAULT_CONFIG || FACTORY_DEFAULTS); return merged; @@ -2533,8 +2556,18 @@

System Environment

var value = fields[field]; var input = document.querySelector('[name="' + section + '.' + field + '"]'); if (input && typeof value !== 'object') { - input.value = (typeof value === 'boolean') ? (value ? "1" : "0") : value; - if (field === 'brightness') updateRangeValue('brightness', value); + if (section === 'daemon' && field === 'access_token') { + if (value && String(value).trim()) { + input.dataset.realToken = value; + input.value = '***'; + } else { + input.value = ''; + delete input.dataset.realToken; + } + } else { + input.value = (typeof value === 'boolean') ? (value ? "1" : "0") : value; + if (field === 'brightness') updateRangeValue('brightness', value); + } } } } @@ -2602,9 +2635,9 @@

System Environment

var config = buildConfig(); try { - await saveAndRestartConfig(config); - alert("Configuration saved! Plugin will restart."); - setTimeout(function() { window.close(); }, 300); + await savePluginConfig(config); + await restartPlugin(); + close(); } catch (error) { console.error("Save failed:", error); alert("Save failed: " + error.message); @@ -2631,25 +2664,7 @@

System Environment

} } - async function triggerPluginRestart(delayMs) { - delayMs = delayMs || 800; - if (delayMs > 0) { - await new Promise(function(resolve) { setTimeout(resolve, delayMs); }); - } - - if (typeof restart !== 'function') { - throw new Error('CoolerControl native restart API is unavailable in this context.'); - } - - restart(); - return true; - } - - async function saveAndRestartConfig(config, delayMs) { - await savePluginConfig(config); - return triggerPluginRestart(delayMs); - } async function resetConfig() { try { @@ -2663,10 +2678,10 @@

System Environment

} else if (factoryConfig.daemon) { delete factoryConfig.daemon.access_token; } - await saveAndRestartConfig(factoryConfig); + await savePluginConfig(factoryConfig); populateForm(factoryConfig); - alert('Reset to factory defaults! Plugin will restart.'); - setTimeout(function() { window.close(); }, 300); + await restartPlugin(); + close(); } catch (error) { console.error("Reset failed:", error); alert('Reset failed: ' + error.message); @@ -2761,10 +2776,6 @@

System Environment

return merged; } - function migrateConfig(config) { - return mergeConfigWithDefaults(config, DEFAULT_CONFIG || FACTORY_DEFAULTS); - } - // ===== INITIALIZATION ===== runPluginScript(async function() { try { @@ -2778,9 +2789,9 @@

System Environment

var config = await getPluginConfig(); if (!config || Object.keys(config).length === 0) { - config = JSON.parse(JSON.stringify(DEFAULT_CONFIG)); + config = cloneConfig(DEFAULT_CONFIG); } else { - config = migrateConfig(config); + config = mergeConfigWithDefaults(config, DEFAULT_CONFIG || FACTORY_DEFAULTS); } populateForm(config); diff --git a/packaging/coolerdash.spec b/packaging/coolerdash.spec index de8687a..5346b71 100644 --- a/packaging/coolerdash.spec +++ b/packaging/coolerdash.spec @@ -44,15 +44,12 @@ make install DESTDIR=%{buildroot} SUDO="" REALOS=no gzip -9 %{buildroot}/usr/share/man/man1/coolerdash.1 %pre -# Stop legacy service if command -v systemctl >/dev/null 2>&1; then if systemctl list-unit-files coolerdash.service | grep -q coolerdash; then systemctl stop coolerdash.service systemctl disable coolerdash.service fi fi - -# Remove legacy files rm -f /etc/systemd/system/coolerdash.service rm -f /etc/systemd/system/coolerdash-helperd.service rm -f /etc/systemd/system/multi-user.target.wants/coolerdash-helperd.service @@ -68,20 +65,43 @@ rm -f /etc/coolercontrol/plugins/coolerdash/coolerdash rm -f /usr/share/applications/coolerdash-settings.desktop rm -f /bin/coolerdash rm -f /usr/bin/coolerdash - -# Remove legacy user if id -u coolerdash >/dev/null 2>&1; then userdel -rf coolerdash fi +if [ -f /etc/coolercontrol/plugins/coolerdash/config.json ] && \ + [ ! -f /var/lib/coolercontrol/plugins/coolerdash/config.json ]; then + mkdir -p /var/lib/coolercontrol/plugins/coolerdash + cp /etc/coolercontrol/plugins/coolerdash/config.json \ + /var/lib/coolercontrol/plugins/coolerdash/config.json + chmod 600 /var/lib/coolercontrol/plugins/coolerdash/config.json +fi +if [ -f /etc/coolercontrol/plugins/coolerdash/credentials.json ] && \ + [ ! -f /var/lib/coolercontrol/plugins/coolerdash/credentials.json ]; then + mkdir -p /var/lib/coolercontrol/plugins/coolerdash + cp /etc/coolercontrol/plugins/coolerdash/credentials.json \ + /var/lib/coolercontrol/plugins/coolerdash/credentials.json + chmod 600 /var/lib/coolercontrol/plugins/coolerdash/credentials.json +fi +rm -f /etc/coolercontrol/plugins/coolerdash/manifest.toml +rm -rf /etc/coolercontrol/plugins/coolerdash/ui +rm -f /etc/coolercontrol/plugins/coolerdash/shutdown.png +rm -f /etc/coolercontrol/plugins/coolerdash/README.md +rm -f /etc/coolercontrol/plugins/coolerdash/CHANGELOG.md +rm -f /etc/coolercontrol/plugins/coolerdash/VERSION +# /etc/coolercontrol/plugins is a symlink to /var/lib/coolercontrol/plugins; +# never rm -rf the directory — it would delete credentials.json via the symlink. %post -if [ -f /etc/coolercontrol/plugins/coolerdash/config.json ]; then - chmod 600 /etc/coolercontrol/plugins/coolerdash/config.json +if [ ! -f /var/lib/coolercontrol/plugins/coolerdash/credentials.json ]; then + mkdir -p /var/lib/coolercontrol/plugins/coolerdash + printf '{\n "access_token": ""\n}\n' > /var/lib/coolercontrol/plugins/coolerdash/credentials.json fi -if [ -f /etc/coolercontrol/plugins/coolerdash/credentials.json ]; then - chmod 600 /etc/coolercontrol/plugins/coolerdash/credentials.json +if [ -f /var/lib/coolercontrol/plugins/coolerdash/config.json ]; then + chmod 600 /var/lib/coolercontrol/plugins/coolerdash/config.json +fi +if [ -f /var/lib/coolercontrol/plugins/coolerdash/credentials.json ]; then + chmod 600 /var/lib/coolercontrol/plugins/coolerdash/credentials.json fi -# Remove legacy files rm -f /etc/systemd/system/multi-user.target.wants/coolerdash-helperd.service rm -f /etc/systemd/system/coolerdash-helperd.service rm -f /usr/lib/systemd/system/coolerdash-helperd.service @@ -89,6 +109,10 @@ rm -rf /etc/systemd/system/cc-plugin-coolerdash.service.d rm -f /usr/lib/udev/rules.d/99-coolerdash.rules if command -v systemctl >/dev/null 2>&1; then systemctl daemon-reload + systemctl reset-failed cc-plugin-coolerdash.service >/dev/null 2>&1 || true + if systemctl list-unit-files cc-plugin-coolerdash.service | grep -q cc-plugin-coolerdash; then + systemctl restart cc-plugin-coolerdash.service || echo "Note: Plugin restart failed." + fi if systemctl is-active --quiet coolercontrold.service; then systemctl restart coolercontrold.service || echo "Note: CoolerControl restart failed." fi @@ -105,7 +129,6 @@ if command -v systemctl >/dev/null 2>&1; then fi fi -# Remove legacy files if [ "$1" = "0" ]; then rm -f /etc/systemd/system/coolerdash-helperd.service rm -f /etc/systemd/system/coolerdash.service @@ -120,7 +143,6 @@ if [ "$1" = "0" ]; then rm -f /usr/bin/coolerdash rm -rf /opt/coolerdash rm -rf /etc/coolerdash - # Remove legacy user if id -u coolerdash >/dev/null 2>&1; then userdel -rf coolerdash fi @@ -140,15 +162,15 @@ fi %license /usr/share/licenses/%{name}/LICENSE %dir /usr/libexec/coolerdash /usr/libexec/coolerdash/coolerdash -%dir /etc/coolercontrol/plugins/coolerdash -%config(noreplace) /etc/coolercontrol/plugins/coolerdash/config.json -/etc/coolercontrol/plugins/coolerdash/manifest.toml -%dir /etc/coolercontrol/plugins/coolerdash/ui -/etc/coolercontrol/plugins/coolerdash/ui/index.html -/etc/coolercontrol/plugins/coolerdash/shutdown.png -/etc/coolercontrol/plugins/coolerdash/README.md -/etc/coolercontrol/plugins/coolerdash/CHANGELOG.md -/etc/coolercontrol/plugins/coolerdash/VERSION +%dir /var/lib/coolercontrol/plugins/coolerdash +%config(noreplace) /var/lib/coolercontrol/plugins/coolerdash/config.json +/var/lib/coolercontrol/plugins/coolerdash/manifest.toml +%dir /var/lib/coolercontrol/plugins/coolerdash/ui +/var/lib/coolercontrol/plugins/coolerdash/ui/index.html +/var/lib/coolercontrol/plugins/coolerdash/shutdown.png +/var/lib/coolercontrol/plugins/coolerdash/README.md +/var/lib/coolercontrol/plugins/coolerdash/CHANGELOG.md +/var/lib/coolercontrol/plugins/coolerdash/VERSION /usr/share/man/man1/coolerdash.1.gz /usr/share/applications/coolerdash.desktop /usr/share/icons/hicolor/scalable/apps/coolerdash.svg diff --git a/packaging/debian/conffiles b/packaging/debian/conffiles index de41f0e..e69de29 100644 --- a/packaging/debian/conffiles +++ b/packaging/debian/conffiles @@ -1 +0,0 @@ -/etc/coolercontrol/plugins/coolerdash/config.json diff --git a/packaging/debian/install b/packaging/debian/install index 09fc557..9d49a02 100644 --- a/packaging/debian/install +++ b/packaging/debian/install @@ -1,12 +1,12 @@ usr/libexec/coolerdash/coolerdash usr/share/licenses/coolerdash/LICENSE -etc/coolercontrol/plugins/coolerdash/config.json -etc/coolercontrol/plugins/coolerdash/manifest.toml -etc/coolercontrol/plugins/coolerdash/shutdown.png -etc/coolercontrol/plugins/coolerdash/README.md -etc/coolercontrol/plugins/coolerdash/VERSION -etc/coolercontrol/plugins/coolerdash/CHANGELOG.md -etc/coolercontrol/plugins/coolerdash/ui/index.html +var/lib/coolercontrol/plugins/coolerdash/config.json +var/lib/coolercontrol/plugins/coolerdash/manifest.toml +var/lib/coolercontrol/plugins/coolerdash/shutdown.png +var/lib/coolercontrol/plugins/coolerdash/README.md +var/lib/coolercontrol/plugins/coolerdash/VERSION +var/lib/coolercontrol/plugins/coolerdash/CHANGELOG.md +var/lib/coolercontrol/plugins/coolerdash/ui/index.html usr/share/man/man1/coolerdash.1 usr/share/applications/coolerdash.desktop usr/share/icons/hicolor/scalable/apps/coolerdash.svg diff --git a/packaging/debian/postinst b/packaging/debian/postinst index c139131..5df31c7 100755 --- a/packaging/debian/postinst +++ b/packaging/debian/postinst @@ -3,9 +3,17 @@ set -e case "$1" in configure) + if [ ! -f /var/lib/coolercontrol/plugins/coolerdash/credentials.json ]; then + mkdir -p /var/lib/coolercontrol/plugins/coolerdash + printf '{\n "access_token": ""\n}\n' > /var/lib/coolercontrol/plugins/coolerdash/credentials.json + fi + # Set permissions on config.json - if [ -f /etc/coolercontrol/plugins/coolerdash/config.json ]; then - chmod 600 /etc/coolercontrol/plugins/coolerdash/config.json + if [ -f /var/lib/coolercontrol/plugins/coolerdash/config.json ]; then + chmod 600 /var/lib/coolercontrol/plugins/coolerdash/config.json + fi + if [ -f /var/lib/coolercontrol/plugins/coolerdash/credentials.json ]; then + chmod 600 /var/lib/coolercontrol/plugins/coolerdash/credentials.json fi # Remove legacy files @@ -17,6 +25,10 @@ case "$1" in if command -v systemctl >/dev/null 2>&1; then systemctl daemon-reload + systemctl reset-failed cc-plugin-coolerdash.service >/dev/null 2>&1 || true + if systemctl list-unit-files cc-plugin-coolerdash.service | grep -q cc-plugin-coolerdash; then + systemctl restart cc-plugin-coolerdash.service || echo "Note: Plugin restart failed." + fi if systemctl is-active --quiet coolercontrold.service; then systemctl restart coolercontrold.service || echo "Note: CoolerControl restart failed." fi diff --git a/packaging/debian/preinst b/packaging/debian/preinst index face5ee..277650e 100755 --- a/packaging/debian/preinst +++ b/packaging/debian/preinst @@ -3,15 +3,12 @@ set -e case "$1" in install|upgrade) - # Stop legacy service if command -v systemctl >/dev/null 2>&1; then if systemctl list-unit-files coolerdash.service | grep -q coolerdash; then systemctl stop coolerdash.service systemctl disable coolerdash.service fi fi - - # Remove legacy files rm -f /etc/systemd/system/coolerdash.service rm -f /etc/systemd/system/coolerdash-helperd.service rm -f /etc/systemd/system/multi-user.target.wants/coolerdash-helperd.service @@ -27,11 +24,31 @@ case "$1" in rm -f /usr/share/applications/coolerdash-settings.desktop rm -f /bin/coolerdash rm -f /usr/bin/coolerdash - - # Remove legacy user if id -u coolerdash >/dev/null 2>&1; then userdel -rf coolerdash fi + if [ -f /etc/coolercontrol/plugins/coolerdash/config.json ] && \ + [ ! -f /var/lib/coolercontrol/plugins/coolerdash/config.json ]; then + mkdir -p /var/lib/coolercontrol/plugins/coolerdash + cp /etc/coolercontrol/plugins/coolerdash/config.json \ + /var/lib/coolercontrol/plugins/coolerdash/config.json + chmod 600 /var/lib/coolercontrol/plugins/coolerdash/config.json + fi + if [ -f /etc/coolercontrol/plugins/coolerdash/credentials.json ] && \ + [ ! -f /var/lib/coolercontrol/plugins/coolerdash/credentials.json ]; then + mkdir -p /var/lib/coolercontrol/plugins/coolerdash + cp /etc/coolercontrol/plugins/coolerdash/credentials.json \ + /var/lib/coolercontrol/plugins/coolerdash/credentials.json + chmod 600 /var/lib/coolercontrol/plugins/coolerdash/credentials.json + fi + rm -f /etc/coolercontrol/plugins/coolerdash/manifest.toml + rm -rf /etc/coolercontrol/plugins/coolerdash/ui + rm -f /etc/coolercontrol/plugins/coolerdash/shutdown.png + rm -f /etc/coolercontrol/plugins/coolerdash/README.md + rm -f /etc/coolercontrol/plugins/coolerdash/CHANGELOG.md + rm -f /etc/coolercontrol/plugins/coolerdash/VERSION + # /etc/coolercontrol/plugins is a symlink to /var/lib/coolercontrol/plugins; + # never rm -rf the directory — it would delete credentials.json via the symlink. ;; esac diff --git a/src/device/config.c b/src/device/config.c index 763b18b..2430624 100644 --- a/src/device/config.c +++ b/src/device/config.c @@ -79,11 +79,11 @@ static void set_paths_defaults(Config *config) { if (config->paths_images[0] == '\0') { - SAFE_STRCPY(config->paths_images, "/etc/coolercontrol/plugins/coolerdash"); + SAFE_STRCPY(config->paths_images, "/var/lib/coolercontrol/plugins/coolerdash"); } if (config->paths_image_coolerdash[0] == '\0') { - SAFE_STRCPY(config->paths_image_coolerdash, "/etc/coolercontrol/plugins/coolerdash/coolerdash.png"); + SAFE_STRCPY(config->paths_image_coolerdash, "/var/lib/coolercontrol/plugins/coolerdash/coolerdash.png"); } if (config->paths_image_background[0] == '\0') { @@ -92,7 +92,7 @@ static void set_paths_defaults(Config *config) if (config->paths_image_shutdown[0] == '\0') { SAFE_STRCPY(config->paths_image_shutdown, - "/etc/coolercontrol/plugins/coolerdash/shutdown.png"); + "/var/lib/coolercontrol/plugins/coolerdash/shutdown.png"); } } @@ -650,7 +650,8 @@ static const char *find_config_json(const char *custom_path) } static const char *possible_paths[] = { - "/etc/coolercontrol/plugins/coolerdash/config.json", + "/var/lib/coolercontrol/plugins/coolerdash/config.json", + "/etc/coolercontrol/plugins/coolerdash/config.json", /* symlink fallback */ NULL}; for (int i = 0; possible_paths[i] != NULL; i++) @@ -738,6 +739,14 @@ static void load_credentials_file(const char *config_json_path, Config *config) if (!config_json_path || !config) return; + int had_sentinel = (strcmp(config->access_token, "***") == 0); + + /* credentials.json is the single authoritative source for the access token. + * It always overrides whatever config.json contained — config.json is only + * the temporary delivery channel when the user saves a new token via the UI. + * The save_credentials_file() call before this one already persisted any new + * token from config.json into credentials.json, so reading here is safe. */ + char cred_path[CONFIG_MAX_PATH_LEN]; if (!get_credentials_path(config_json_path, cred_path, sizeof(cred_path))) return; @@ -746,21 +755,38 @@ static void load_credentials_file(const char *config_json_path, Config *config) json_t *root = json_load_file(cred_path, 0, &error); if (!root) { + if (had_sentinel) + { + config->access_token[0] = '\0'; + log_message(LOG_WARNING, + "credentials.json missing; cleared stale token sentinel from runtime config"); + } log_message(LOG_INFO, "No credentials.json at %s", cred_path); return; } json_t *token = json_object_get(root, "access_token"); + int loaded_token = 0; if (token && json_is_string(token) && json_string_length(token) > 0) { const char *value = json_string_value(token); - if (value) + /* Skip sentinel — credentials.json should never contain "***" but + * guard against accidental writes of the UI placeholder. */ + if (value && strcmp(value, "***") != 0) { SAFE_STRCPY(config->access_token, value); log_message(LOG_INFO, "Loaded access_token from credentials.json"); + loaded_token = 1; } } + if (!loaded_token && had_sentinel) + { + config->access_token[0] = '\0'; + log_message(LOG_WARNING, + "credentials.json has no usable token; cleared stale token sentinel from runtime config"); + } + json_decref(root); } @@ -778,15 +804,25 @@ static void save_credentials_file(const char *config_json_path, const Config *co if (!config_json_path || !config) return; + /* Never overwrite credentials.json with an empty token or the sentinel. + * credentials.json is authoritative — only update it when we actually + * have a new token (delivered via config.json after a UI save). */ + if (config->access_token[0] == '\0') + return; + + /* "***" is the UI sentinel meaning "token already set, no change" — never + * persist the sentinel itself into credentials.json. */ + if (strcmp(config->access_token, "***") == 0) + return; + + const char *token = config->access_token; + char cred_path[CONFIG_MAX_PATH_LEN]; if (!get_credentials_path(config_json_path, cred_path, sizeof(cred_path))) return; - const char *token = config->access_token[0] != '\0' - ? config->access_token - : ""; - /* Check if credentials.json already has the same token */ + /* (skip unnecessary writes for unchanged tokens) */ json_t *existing = json_load_file(cred_path, 0, NULL); if (existing) { @@ -824,10 +860,7 @@ static void save_credentials_file(const char *config_json_path, const Config *co json_decref(root); - if (token[0] != '\0') - log_message(LOG_STATUS, "Access token persisted to credentials.json"); - else - log_message(LOG_STATUS, "Created credentials.json"); + log_message(LOG_STATUS, "Access token persisted to credentials.json"); } /** @@ -863,11 +896,22 @@ static void normalize_config_json(const char *json_path, json_t *root) if (head[0] == '{' && head[1] == '\n' && head[2] == ' ' && head[3] == ' ') return; - /* Remove access_token before writing (belongs in credentials.json) */ + /* Replace real access_token with sentinel "***" before writing. + * The actual token stays safe in credentials.json; the sentinel tells + * the UI that a token is already configured without exposing the value. */ json_t *daemon = json_object_get(root, "daemon"); if (daemon && json_is_object(daemon)) { - json_object_del(daemon, "access_token"); + json_t *tok = json_object_get(daemon, "access_token"); + if (tok && json_is_string(tok)) + { + const char *tv = json_string_value(tok); + if (tv && tv[0] != '\0' && strcmp(tv, "***") != 0) + json_object_set_new(daemon, "access_token", json_string("***")); + else if (!tv || tv[0] == '\0') + json_object_del(daemon, "access_token"); + /* "***" already present — leave as-is */ + } } if (json_dump_file(root, json_path, @@ -1430,6 +1474,61 @@ static void load_positioning_from_json(json_t *root, Config *config) // Public API Implementation // ============================================================================ +/** + * @brief Write "***" sentinel for access_token into config.json. + * @details Called after loading credentials.json so the UI can display that + * a token is configured without exposing the real value. Safe to call + * repeatedly — skips the write if the sentinel is already present. + * @param json_path Path to config.json + * @param config Config struct (used to check whether a token is actually set) + */ +static void write_token_sentinel_to_config(const char *json_path, const Config *config) +{ + if (!json_path || !config || config->access_token[0] == '\0') + return; + + json_error_t error; + json_t *root = json_load_file(json_path, 0, &error); + if (!root) + return; + + json_t *daemon_obj = json_object_get(root, "daemon"); + if (!daemon_obj || !json_is_object(daemon_obj)) + { + json_decref(root); + return; + } + + json_t *tok = json_object_get(daemon_obj, "access_token"); + const char *tv = (tok && json_is_string(tok)) ? json_string_value(tok) : ""; + if (tv && strcmp(tv, "***") == 0) + { + /* Already correct — nothing to write */ + json_decref(root); + return; + } + + json_object_set_new(daemon_obj, "access_token", json_string("***")); + + if (json_dump_file(root, json_path, JSON_INDENT(2) | JSON_PRESERVE_ORDER) == 0) + { + /* Append trailing newline (json_dump_file omits it) */ + FILE *fp = fopen(json_path, "a"); + if (fp) + { + fputc('\n', fp); + fclose(fp); + } + log_message(LOG_INFO, "Token sentinel written to config.json"); + } + else + { + log_message(LOG_WARNING, "Failed to write token sentinel to config.json"); + } + + json_decref(root); +} + /** * @brief Load complete configuration from config.json with hardcoded defaults. */ @@ -1494,8 +1593,19 @@ int load_plugin_config(Config *config, const char *config_path) log_message(LOG_STATUS, "Using hardcoded defaults"); } - /* Load credentials.json (overrides access_token from config.json) */ + /* If config.json delivered a new token (user saved via UI), persist it + * to credentials.json NOW — before reading credentials.json as authority. */ + save_credentials_file(json_path, config); + + /* Load credentials.json as the single authoritative source for access_token. + * This always wins — it is the persisted, update-safe store. */ load_credentials_file(json_path, config); + + /* If a token is now active, write the "***" sentinel back to config.json + * so the UI (getPluginConfig) can show that a token is configured + * without exposing the real value. */ + if (config->access_token[0] != '\0') + write_token_sentinel_to_config(json_path, config); } else { @@ -1505,11 +1615,5 @@ int load_plugin_config(Config *config, const char *config_path) // Apply defaults for any missing fields apply_system_defaults(config); - /* Auto-persist token to credentials.json (survives config.json updates) */ - if (json_path) - { - save_credentials_file(json_path, config); - } - return loaded_from_json; } diff --git a/src/srv/cc_conf.c b/src/srv/cc_conf.c index bdc6af7..147cb1e 100644 --- a/src/srv/cc_conf.c +++ b/src/srv/cc_conf.c @@ -110,11 +110,12 @@ const char *extract_device_type_from_json(const json_t *dev) if (!dev) return NULL; - const json_t *type_val = json_object_get(dev, "type"); + /* Both DeviceDto (/devices) and DeviceStatusDto (/status) use the "d_type" field. */ + const json_t *type_val = json_object_get(dev, "d_type"); if (!type_val || !json_is_string(type_val)) { - /* Fallback: /status endpoint uses "d_type" instead of "type" */ - type_val = json_object_get(dev, "d_type"); + /* Legacy fallback for older CC versions that may have used "type" */ + type_val = json_object_get(dev, "type"); if (!type_val || !json_is_string(type_val)) return NULL; } @@ -446,7 +447,8 @@ static int score_lcd_candidate(const Config *config, const char *device_uid, else if (type_str && (strcmp(type_str, "Hwmon") == 0 || strcmp(type_str, "CustomSensors") == 0 || - strcmp(type_str, "CPU") == 0 || strcmp(type_str, "GPU") == 0)) + strcmp(type_str, "CPU") == 0 || strcmp(type_str, "GPU") == 0 || + strcmp(type_str, "ServicePlugin") == 0)) /* CC v4.3.0: plugins are never LCD hw */ score -= 40; else if (type_str && type_str[0] != '\0') score += 8; diff --git a/src/srv/cc_main.c b/src/srv/cc_main.c index 05ecaa9..5e0c3ee 100644 --- a/src/srv/cc_main.c +++ b/src/srv/cc_main.c @@ -332,7 +332,7 @@ int send_image_to_lcd(const Config *config, const char *image_path, char upload_url[CC_URL_SIZE]; int written = snprintf(upload_url, sizeof(upload_url), - "%s/devices/%s/settings/lcd/lcd", + "%s/devices/%s/settings/lcd/lcd?log=false", config->daemon_address, device_uid); if (!validate_snprintf(written, sizeof(upload_url), upload_url)) {