From dceab1a75a0c7f3ee1d53610649319d25c9a616e Mon Sep 17 00:00:00 2001 From: Djuri Baars Date: Tue, 26 Nov 2024 16:50:46 +0100 Subject: [PATCH 01/21] Add Forgejo action --- .forgejo/workflows/build.yaml | 117 ++++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 .forgejo/workflows/build.yaml diff --git a/.forgejo/workflows/build.yaml b/.forgejo/workflows/build.yaml new file mode 100644 index 0000000..d386a7d --- /dev/null +++ b/.forgejo/workflows/build.yaml @@ -0,0 +1,117 @@ +on: [push] +jobs: + check-changes: + runs-on: docker + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Get changed files count + id: changed-files + uses: tj-actions/changed-files@v45 + with: + files_ignore: 'doc/**,README.md,Dockerfile,.*' + files_ignore_separator: ',' + - name: Print changed files count + run: > + echo "Changed files count: ${{ + steps.changed-files.outputs.all_changed_and_modified_files_count }}" + + build: + needs: check-changes + runs-on: ubuntu-latest + if: ${{ needs.check-changes.outputs.all_changed_and_modified_files_count >= 1 }} + permissions: + contents: write + + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + - uses: actions/setup-node@v4 + with: + node-version: lts/* + cache: yarn + cache-dependency-path: '**/yarn.lock' + - uses: actions/cache@v4 + with: + path: | + ~/.cache/pip + ~/node_modules + key: ${{ runner.os }}-pio + - uses: actions/setup-python@v5 + with: + python-version: '3.9' + - name: Get current date + id: dateAndTime + run: echo "dateAndTime=$(date +'%Y-%m-%d-%H:%M')" >> $GITHUB_OUTPUT + - name: Install mklittlefs + run: > + git clone https://github.com/earlephilhower/mklittlefs.git /tmp/mklittlefs && + cd /tmp/mklittlefs && + git submodule update --init && + make dist + - name: Install yarn + run: yarn && yarn postinstall + - name: Run linter + run: yarn lint + - name: Run vitest tests + run: yarn vitest run + - name: Install Playwright Browsers + run: npx playwright install --with-deps + - name: Run Playwright tests + run: npx playwright test + - name: Build WebUI + run: yarn build + - name: Get current block + id: getBlockHeight + run: echo "blockHeight=$(curl -s https://mempool.space/api/blocks/tip/height)" >> $GITHUB_OUTPUT + - name: Write block height to file + env: + BLOCK_HEIGHT: ${{ steps.getBlockHeight.outputs.blockHeight }} + run: mkdir -p output && echo "$BLOCK_HEIGHT" > output/version.txt + - name: gzip build for LittleFS + run: find dist -type f ! -name ".*" -exec sh -c 'mkdir -p "build_gz/$(dirname "${1#dist/}")" && gzip -k "$1" -c > "build_gz/${1#dist/}".gz' _ {} \; + - name: Write git rev to file + run: echo "$GITHUB_SHA" > build_gz/fs_hash.txt && echo "$GITHUB_SHA" > output/commit.txt + - name: Check GZipped directory size + run: | + # Set the threshold size in bytes + THRESHOLD=409600 + + # Calculate the total size of files in the directory + DIRECTORY_SIZE=$(du -b -s build_gz | awk '{print $1}') + + # Fail the workflow if the size exceeds the threshold + if [ "$DIRECTORY_SIZE" -gt "$THRESHOLD" ]; then + echo "Directory size exceeds the threshold of $THRESHOLD bytes" + exit 1 + else + echo "Directory size is within the threshold $DIRECTORY_SIZE" + fi + - name: Create tarball + run: tar czf webui.tgz --strip-components=1 dist + - name: Build LittleFS + run: | + set -e + /tmp/mklittlefs/mklittlefs -c build_gz -s 409600 output/littlefs.bin + - name: Upload artifacts + uses: actions/upload-artifact@v4 + with: + path: | + webui.tgz + output/littlefs.bin + - name: Create release + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + uses: https://code.forgejo.org/actions/forgejo-release@v2.4.0 + with: + url: "https://git.btclock.dev/" + repo: "btclock/webui" + direction: upload + tag: ${{ steps.getBlockHeight.outputs.blockHeight }} + sha: "${{ github.sha }}" + release-dir: output + token: ${{ secrets.TOKEN }} + override: false + verbose: false + release-notes-assistant: false \ No newline at end of file From 0b3f6d3de17ceeb498bd5578f0d9dcff0077e098 Mon Sep 17 00:00:00 2001 From: Djuri Baars Date: Tue, 26 Nov 2024 16:55:42 +0100 Subject: [PATCH 02/21] Fix forgejo workflow --- .forgejo/workflows/build.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.forgejo/workflows/build.yaml b/.forgejo/workflows/build.yaml index d386a7d..129385e 100644 --- a/.forgejo/workflows/build.yaml +++ b/.forgejo/workflows/build.yaml @@ -19,7 +19,7 @@ jobs: build: needs: check-changes - runs-on: ubuntu-latest + runs-on: docker if: ${{ needs.check-changes.outputs.all_changed_and_modified_files_count >= 1 }} permissions: contents: write @@ -106,7 +106,7 @@ jobs: uses: https://code.forgejo.org/actions/forgejo-release@v2.4.0 with: url: "https://git.btclock.dev/" - repo: "btclock/webui" + repo: "${{ github.repository }}" direction: upload tag: ${{ steps.getBlockHeight.outputs.blockHeight }} sha: "${{ github.sha }}" From 6028268227943f4a391f697a3771098ef9bd093d Mon Sep 17 00:00:00 2001 From: Djuri Baars Date: Tue, 26 Nov 2024 16:57:33 +0100 Subject: [PATCH 03/21] Fix workflow --- .forgejo/workflows/build.yaml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.forgejo/workflows/build.yaml b/.forgejo/workflows/build.yaml index 129385e..0d8651a 100644 --- a/.forgejo/workflows/build.yaml +++ b/.forgejo/workflows/build.yaml @@ -2,6 +2,8 @@ on: [push] jobs: check-changes: runs-on: docker + outputs: + all_changed_and_modified_files_count: ${{ steps.changed-files.outputs.all_changed_and_modified_files_count }} steps: - name: Checkout code uses: actions/checkout@v4 @@ -105,13 +107,13 @@ jobs: if: github.event_name == 'push' && github.ref == 'refs/heads/main' uses: https://code.forgejo.org/actions/forgejo-release@v2.4.0 with: - url: "https://git.btclock.dev/" - repo: "${{ github.repository }}" + url: 'https://git.btclock.dev/' + repo: '${{ github.repository }}' direction: upload tag: ${{ steps.getBlockHeight.outputs.blockHeight }} - sha: "${{ github.sha }}" + sha: '${{ github.sha }}' release-dir: output token: ${{ secrets.TOKEN }} override: false verbose: false - release-notes-assistant: false \ No newline at end of file + release-notes-assistant: false From 55859cf8d4c9522f4ebc3f217254886e61afc926 Mon Sep 17 00:00:00 2001 From: Djuri Baars Date: Tue, 26 Nov 2024 17:04:51 +0100 Subject: [PATCH 04/21] Fix workflow python version --- .forgejo/workflows/build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.forgejo/workflows/build.yaml b/.forgejo/workflows/build.yaml index 0d8651a..4a06721 100644 --- a/.forgejo/workflows/build.yaml +++ b/.forgejo/workflows/build.yaml @@ -43,7 +43,7 @@ jobs: key: ${{ runner.os }}-pio - uses: actions/setup-python@v5 with: - python-version: '3.9' + python-version: '>=3.10' - name: Get current date id: dateAndTime run: echo "dateAndTime=$(date +'%Y-%m-%d-%H:%M')" >> $GITHUB_OUTPUT From a891529cdc92d4b2a9aadf76a5ac6624d16afeb3 Mon Sep 17 00:00:00 2001 From: Djuri Baars Date: Tue, 26 Nov 2024 17:14:57 +0100 Subject: [PATCH 05/21] Fix workflow container --- .forgejo/workflows/build.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.forgejo/workflows/build.yaml b/.forgejo/workflows/build.yaml index 4a06721..0f088ee 100644 --- a/.forgejo/workflows/build.yaml +++ b/.forgejo/workflows/build.yaml @@ -22,6 +22,8 @@ jobs: build: needs: check-changes runs-on: docker + container: + image: catthehacker/ubuntu:act-22.04 if: ${{ needs.check-changes.outputs.all_changed_and_modified_files_count >= 1 }} permissions: contents: write From 81238e57edbde561b48c38c25dda60638943c515 Mon Sep 17 00:00:00 2001 From: Djuri Baars Date: Tue, 26 Nov 2024 17:19:29 +0100 Subject: [PATCH 06/21] Forgejo js image --- .forgejo/workflows/build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.forgejo/workflows/build.yaml b/.forgejo/workflows/build.yaml index 0f088ee..1f64a5c 100644 --- a/.forgejo/workflows/build.yaml +++ b/.forgejo/workflows/build.yaml @@ -23,7 +23,7 @@ jobs: needs: check-changes runs-on: docker container: - image: catthehacker/ubuntu:act-22.04 + image: ghcr.io/catthehacker/ubuntu:js-22.04 if: ${{ needs.check-changes.outputs.all_changed_and_modified_files_count >= 1 }} permissions: contents: write From 1bac10e4ef1f88b0d98fdfd351dd593c4e80fc03 Mon Sep 17 00:00:00 2001 From: Djuri Baars Date: Tue, 26 Nov 2024 17:27:22 +0100 Subject: [PATCH 07/21] use upload artifacts fork --- .forgejo/workflows/build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.forgejo/workflows/build.yaml b/.forgejo/workflows/build.yaml index 1f64a5c..fe38500 100644 --- a/.forgejo/workflows/build.yaml +++ b/.forgejo/workflows/build.yaml @@ -100,7 +100,7 @@ jobs: set -e /tmp/mklittlefs/mklittlefs -c build_gz -s 409600 output/littlefs.bin - name: Upload artifacts - uses: actions/upload-artifact@v4 + uses: https://code.forgejo.org/forgejo/upload-artifact@v4 with: path: | webui.tgz From da3c70285d8574d69e3048b046028c74d2edc6a7 Mon Sep 17 00:00:00 2001 From: Djuri Baars Date: Tue, 26 Nov 2024 16:50:46 +0100 Subject: [PATCH 08/21] Add Forgejo action Fix forgejo workflow Fix workflow Fix workflow python version Fix workflow container Forgejo js image use upload artifacts fork --- .forgejo/workflows/build.yaml | 121 ++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 .forgejo/workflows/build.yaml diff --git a/.forgejo/workflows/build.yaml b/.forgejo/workflows/build.yaml new file mode 100644 index 0000000..fe38500 --- /dev/null +++ b/.forgejo/workflows/build.yaml @@ -0,0 +1,121 @@ +on: [push] +jobs: + check-changes: + runs-on: docker + outputs: + all_changed_and_modified_files_count: ${{ steps.changed-files.outputs.all_changed_and_modified_files_count }} + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Get changed files count + id: changed-files + uses: tj-actions/changed-files@v45 + with: + files_ignore: 'doc/**,README.md,Dockerfile,.*' + files_ignore_separator: ',' + - name: Print changed files count + run: > + echo "Changed files count: ${{ + steps.changed-files.outputs.all_changed_and_modified_files_count }}" + + build: + needs: check-changes + runs-on: docker + container: + image: ghcr.io/catthehacker/ubuntu:js-22.04 + if: ${{ needs.check-changes.outputs.all_changed_and_modified_files_count >= 1 }} + permissions: + contents: write + + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + - uses: actions/setup-node@v4 + with: + node-version: lts/* + cache: yarn + cache-dependency-path: '**/yarn.lock' + - uses: actions/cache@v4 + with: + path: | + ~/.cache/pip + ~/node_modules + key: ${{ runner.os }}-pio + - uses: actions/setup-python@v5 + with: + python-version: '>=3.10' + - name: Get current date + id: dateAndTime + run: echo "dateAndTime=$(date +'%Y-%m-%d-%H:%M')" >> $GITHUB_OUTPUT + - name: Install mklittlefs + run: > + git clone https://github.com/earlephilhower/mklittlefs.git /tmp/mklittlefs && + cd /tmp/mklittlefs && + git submodule update --init && + make dist + - name: Install yarn + run: yarn && yarn postinstall + - name: Run linter + run: yarn lint + - name: Run vitest tests + run: yarn vitest run + - name: Install Playwright Browsers + run: npx playwright install --with-deps + - name: Run Playwright tests + run: npx playwright test + - name: Build WebUI + run: yarn build + - name: Get current block + id: getBlockHeight + run: echo "blockHeight=$(curl -s https://mempool.space/api/blocks/tip/height)" >> $GITHUB_OUTPUT + - name: Write block height to file + env: + BLOCK_HEIGHT: ${{ steps.getBlockHeight.outputs.blockHeight }} + run: mkdir -p output && echo "$BLOCK_HEIGHT" > output/version.txt + - name: gzip build for LittleFS + run: find dist -type f ! -name ".*" -exec sh -c 'mkdir -p "build_gz/$(dirname "${1#dist/}")" && gzip -k "$1" -c > "build_gz/${1#dist/}".gz' _ {} \; + - name: Write git rev to file + run: echo "$GITHUB_SHA" > build_gz/fs_hash.txt && echo "$GITHUB_SHA" > output/commit.txt + - name: Check GZipped directory size + run: | + # Set the threshold size in bytes + THRESHOLD=409600 + + # Calculate the total size of files in the directory + DIRECTORY_SIZE=$(du -b -s build_gz | awk '{print $1}') + + # Fail the workflow if the size exceeds the threshold + if [ "$DIRECTORY_SIZE" -gt "$THRESHOLD" ]; then + echo "Directory size exceeds the threshold of $THRESHOLD bytes" + exit 1 + else + echo "Directory size is within the threshold $DIRECTORY_SIZE" + fi + - name: Create tarball + run: tar czf webui.tgz --strip-components=1 dist + - name: Build LittleFS + run: | + set -e + /tmp/mklittlefs/mklittlefs -c build_gz -s 409600 output/littlefs.bin + - name: Upload artifacts + uses: https://code.forgejo.org/forgejo/upload-artifact@v4 + with: + path: | + webui.tgz + output/littlefs.bin + - name: Create release + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + uses: https://code.forgejo.org/actions/forgejo-release@v2.4.0 + with: + url: 'https://git.btclock.dev/' + repo: '${{ github.repository }}' + direction: upload + tag: ${{ steps.getBlockHeight.outputs.blockHeight }} + sha: '${{ github.sha }}' + release-dir: output + token: ${{ secrets.TOKEN }} + override: false + verbose: false + release-notes-assistant: false From d74e9dab60772ef11f9b033cfe982d216a9c95ee Mon Sep 17 00:00:00 2001 From: Djuri Baars Date: Wed, 27 Nov 2024 10:03:32 +0100 Subject: [PATCH 09/21] Add Mow suffix mode setting --- src/lib/locales/de.json | 3 ++- src/lib/locales/en.json | 3 ++- src/lib/locales/es.json | 3 ++- src/lib/locales/nl.json | 3 ++- src/routes/Settings.svelte | 10 ++++++++++ 5 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/lib/locales/de.json b/src/lib/locales/de.json index 946b962..2ae345f 100644 --- a/src/lib/locales/de.json +++ b/src/lib/locales/de.json @@ -42,7 +42,8 @@ "httpAuthUser": "WebUI-Benutzername", "httpAuthPass": "WebUI-Passwort", "httpAuthText": "Schützt nur die WebUI mit einem Passwort, nicht API-Aufrufe.", - "currencies": "Währungen" + "currencies": "Währungen", + "mowMode": "Mow suffixmodus" }, "control": { "systemInfo": "Systeminfo", diff --git a/src/lib/locales/en.json b/src/lib/locales/en.json index a9ba033..32af86e 100644 --- a/src/lib/locales/en.json +++ b/src/lib/locales/en.json @@ -54,7 +54,8 @@ "httpAuthText": "Only password-protects WebUI, not API-calls.", "currencies": "Currencies", "stagingSource": "Use Staging datasource (for development)", - "useNostrTooltip": "Very experimental and unstable. Nostr data source is not required for Nostr Zap notifications." + "useNostrTooltip": "Very experimental and unstable. Nostr data source is not required for Nostr Zap notifications.", + "mowMode": "Mow Suffix Mode" }, "control": { "systemInfo": "System info", diff --git a/src/lib/locales/es.json b/src/lib/locales/es.json index 5eced4c..891f5ba 100644 --- a/src/lib/locales/es.json +++ b/src/lib/locales/es.json @@ -41,7 +41,8 @@ "httpAuthUser": "Nombre de usuario WebUI", "httpAuthPass": "Contraseña WebUI", "httpAuthText": "Solo la WebUI está protegida con contraseña, no las llamadas API.", - "currencies": "Monedas" + "currencies": "Monedas", + "mowMode": "Modo de sufijo Mow" }, "control": { "turnOff": "Apagar", diff --git a/src/lib/locales/nl.json b/src/lib/locales/nl.json index f126bcf..f000bd1 100644 --- a/src/lib/locales/nl.json +++ b/src/lib/locales/nl.json @@ -42,7 +42,8 @@ "httpAuthUser": "WebUI-gebruikersnaam", "httpAuthPass": "WebUI-wachtwoord", "httpAuthText": "Beveiligd enkel WebUI, niet de API.", - "currencies": "Valuta's" + "currencies": "Valuta's", + "mowMode": "Mow achtervoegsel" }, "control": { "systemInfo": "Systeeminformatie", diff --git a/src/routes/Settings.svelte b/src/routes/Settings.svelte index 40df8d3..761c6ee 100644 --- a/src/routes/Settings.svelte +++ b/src/routes/Settings.svelte @@ -651,6 +651,16 @@ label={$_('section.settings.suffixPrice')} /> + + + Date: Thu, 28 Nov 2024 17:40:10 +0100 Subject: [PATCH 10/21] Dependency updates, increase fs allowance, split up settings section and add settings --- .forgejo/workflows/build.yaml | 4 +- package.json | 1 + src/components/ToggleHeader.svelte | 28 + src/lib/locales/de.json | 14 +- src/lib/locales/en.json | 18 +- src/lib/locales/es.json | 14 +- src/lib/locales/nl.json | 14 +- src/routes/Settings.svelte | 1336 +++++++++++++++------------- src/routes/Status.svelte | 2 +- yarn.lock | 310 +++++-- 10 files changed, 1044 insertions(+), 697 deletions(-) create mode 100644 src/components/ToggleHeader.svelte diff --git a/.forgejo/workflows/build.yaml b/.forgejo/workflows/build.yaml index fe38500..b439c55 100644 --- a/.forgejo/workflows/build.yaml +++ b/.forgejo/workflows/build.yaml @@ -81,7 +81,7 @@ jobs: - name: Check GZipped directory size run: | # Set the threshold size in bytes - THRESHOLD=409600 + THRESHOLD=419840 # Calculate the total size of files in the directory DIRECTORY_SIZE=$(du -b -s build_gz | awk '{print $1}') @@ -98,7 +98,7 @@ jobs: - name: Build LittleFS run: | set -e - /tmp/mklittlefs/mklittlefs -c build_gz -s 409600 output/littlefs.bin + /tmp/mklittlefs/mklittlefs -c build_gz -s 419840 output/littlefs.bin - name: Upload artifacts uses: https://code.forgejo.org/forgejo/upload-artifact@v4 with: diff --git a/package.json b/package.json index 9c4937d..930fc00 100644 --- a/package.json +++ b/package.json @@ -58,6 +58,7 @@ "msgpack-es": "^0.0.5", "nostr-tools": "^2.7.1", "patch-package": "^8.0.0", + "svelte-bootstrap-icons": "^3.1.1", "svelte-i18n": "^4.0.0" }, "resolutions": { diff --git a/src/components/ToggleHeader.svelte b/src/components/ToggleHeader.svelte new file mode 100644 index 0000000..acc8d3b --- /dev/null +++ b/src/components/ToggleHeader.svelte @@ -0,0 +1,28 @@ + + +

+ (isOpen = !isOpen)} + tabindex="0" + on:keypress={() => (isOpen = !isOpen)} + > + {#if isOpen} + + {:else} + + {/if} + {header} + +

+ + + diff --git a/src/lib/locales/de.json b/src/lib/locales/de.json index 2ae345f..50c6ffc 100644 --- a/src/lib/locales/de.json +++ b/src/lib/locales/de.json @@ -43,7 +43,19 @@ "httpAuthPass": "WebUI-Passwort", "httpAuthText": "Schützt nur die WebUI mit einem Passwort, nicht API-Aufrufe.", "currencies": "Währungen", - "mowMode": "Mow suffixmodus" + "mowMode": "Mow suffixmodus", + "suffixShareDot": "Kompakte Suffix-Notation", + "section": { + "displaysAndLed": "Anzeigen und LEDs", + "screenSettings": "Infospezifisch", + "dataSource": "Datenquelle", + "extraFeatures": "Zusätzliche Funktionen", + "system": "System" + }, + "ledFlashOnZap": "LED blinkt bei Nostr Zap", + "flFlashOnZap": "Displaybeleuchting bei Nostr Zap", + "showAll": "Alle anzeigen", + "hideAll": "Alles ausblenden" }, "control": { "systemInfo": "Systeminfo", diff --git a/src/lib/locales/en.json b/src/lib/locales/en.json index 32af86e..b4420dd 100644 --- a/src/lib/locales/en.json +++ b/src/lib/locales/en.json @@ -41,7 +41,7 @@ "nostrZapKey": "Nostr zap pubkey", "nostrRelay": "Nostr Relay", "nostrZapNotify": "Nostr Zap Notifications", - "useNostr": "Use Nostr datasource", + "useNostr": "Use Nostr data source", "bitaxeHostname": "BitAxe hostname or IP", "bitaxeEnabled": "Enable BitAxe", "nostrZapPubkey": "Nostr Zap pubkey", @@ -53,9 +53,21 @@ "httpAuthPass": "WebUI Password", "httpAuthText": "Only password-protects WebUI, not API-calls.", "currencies": "Currencies", - "stagingSource": "Use Staging datasource (for development)", + "stagingSource": "Use Staging data source (for development)", "useNostrTooltip": "Very experimental and unstable. Nostr data source is not required for Nostr Zap notifications.", - "mowMode": "Mow Suffix Mode" + "mowMode": "Mow Suffix Mode", + "suffixShareDot": "Suffix compact notation", + "section": { + "displaysAndLed": "Displays and LEDs", + "screenSettings": "Screen specific", + "dataSource": "Data source", + "extraFeatures": "Extra features", + "system": "System" + }, + "ledFlashOnZap": "LED flash on Nostr Zap", + "flFlashOnZap": "Frontlight flash on Nostr Zap", + "showAll": "Show all", + "hideAll": "Hide all" }, "control": { "systemInfo": "System info", diff --git a/src/lib/locales/es.json b/src/lib/locales/es.json index 891f5ba..121767f 100644 --- a/src/lib/locales/es.json +++ b/src/lib/locales/es.json @@ -42,7 +42,19 @@ "httpAuthPass": "Contraseña WebUI", "httpAuthText": "Solo la WebUI está protegida con contraseña, no las llamadas API.", "currencies": "Monedas", - "mowMode": "Modo de sufijo Mow" + "mowMode": "Modo de sufijo Mow", + "suffixShareDot": "Notación compacta de sufijo", + "section": { + "displaysAndLed": "Pantallas y LED", + "screenSettings": "Específico de la pantalla", + "dataSource": "fuente de datos", + "extraFeatures": "Funciones adicionales", + "system": "Sistema" + }, + "ledFlashOnZap": "LED parpadeante con Nostr Zap", + "flFlashOnZap": "Flash de luz frontal con Nostr Zap", + "showAll": "Mostrar todo", + "hideAll": "Ocultar todo" }, "control": { "turnOff": "Apagar", diff --git a/src/lib/locales/nl.json b/src/lib/locales/nl.json index f000bd1..65c120e 100644 --- a/src/lib/locales/nl.json +++ b/src/lib/locales/nl.json @@ -43,7 +43,19 @@ "httpAuthPass": "WebUI-wachtwoord", "httpAuthText": "Beveiligd enkel WebUI, niet de API.", "currencies": "Valuta's", - "mowMode": "Mow achtervoegsel" + "mowMode": "Mow achtervoegsel", + "suffixShareDot": "Achtervoegsel compacte notatie", + "section": { + "displaysAndLed": "Displays en LED's", + "screenSettings": "Schermspecifiek", + "dataSource": "Gegevensbron", + "extraFeatures": "Extra functies", + "system": "Systeem" + }, + "ledFlashOnZap": "Knipper LED bij Nostr Zap", + "flFlashOnZap": "Knipper displaylicht bij Nostr Zap", + "showAll": "Toon alles", + "hideAll": "Alles verbergen" }, "control": { "systemInfo": "Systeeminformatie", diff --git a/src/routes/Settings.svelte b/src/routes/Settings.svelte index 761c6ee..dbaf3b1 100644 --- a/src/routes/Settings.svelte +++ b/src/routes/Settings.svelte @@ -24,6 +24,7 @@ import EyeIcon from '../icons/EyeIcon.svelte'; import EyeSlashIcon from '../icons/EyeSlashIcon.svelte'; import { derived } from 'svelte/store'; + import ToggleHeader from '../components/ToggleHeader.svelte'; export let settings; @@ -196,647 +197,750 @@ } }; + const showAll = (show: boolean) => { + screenSettingsIsOpen = show; + displaysAndLedIsOpen = show; + dataSourceIsOpen = show; + extraFeaturesIsOpen = show; + systemIsOpen = show; + }; + export let xs = 12; export let sm = xs; export let md = sm; export let lg = md; export let xl = lg; export let xxl = xl; + + let screenSettingsIsOpen: boolean, + displaysAndLedIsOpen: boolean, + dataSourceIsOpen: boolean, + extraFeaturesIsOpen: boolean, + systemIsOpen: boolean; +
+ + | + +
{$_('section.settings.title', { default: 'Settings' })}
-
+ - - - - - - - - - - - - - - - {$_('time.minutes')} - - - - - - - - - {$_('time.minutes')} - - - - - - - - - {$_('time.seconds')} - - {$_('section.settings.shortAmountsWarning')} - - - - - - - - {$_('time.minutes')} - - - {$_('section.settings.tzOffsetHelpText')} - - - - - - - - - {#if $settings.hasFrontlight && !$settings.flDisable} - - - - - - - - - - - - - {/if} - {#if !$settings.flDisable && $settings.hasLightLevel} - - - - - - - {/if} - {#if $settings.bitaxeEnabled} - - - - - - - - - - {/if} - {#if 'nostrZapNotify' in $settings && $settings['nostrZapNotify']} - - - - checkValidNostrPubkey('nostrZapPubkey')} - invalid={!isValidHexPubKey($settings.nostrZapPubkey)} - bsSize={$uiSettings.inputSize} - required - minlength="64" - > - {#if !isValidHexPubKey($settings.nostrZapPubkey)} - {$_('section.settings.invalidNostrPubkey')} - {/if} - - - {/if} - {#if $settings.useNostr} - - - - checkValidNostrPubkey('nostrPubKey')} - invalid={!isValidHexPubKey($settings.nostrPubKey)} - bsSize={$uiSettings.inputSize} - > - {#if !isValidHexPubKey($settings.nostrPubKey)} - {$_('section.settings.invalidNostrPubkey')} - {/if} - - - {/if} - {#if 'nostrZapNotify' in $settings || $settings.useNostr} - - - - - - - - - - {/if} - - - - - - - - HTTPS - - - {$_('section.settings.mempoolInstanceHelpText')} - - - {#if $settings.httpAuthEnabled} - - - - - - - - - - - - - - {$_('section.settings.httpAuthText')} - - - {/if} - - - - - - - - - - - {#each wifiTxPowerMap as [key, value]} - - {/each} - - {$_('section.settings.wifiTxPowerText')} - - - - - - - - {$_('time.seconds')} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {#if $settings.hasFrontlight} - - - - {/if} - {#if $settings.hasFrontlight && !$settings.flDisable} - - - - - - - {/if} - {#if !$settings.actCurrencies} - - - - {/if} - - - - {#if $settings.nostrRelay} - - - - {$_('section.settings.useNostrTooltip')} - - - {/if} - {#if 'nostrZapNotify' in $settings} - - - - {/if} - {#if 'bitaxeEnabled' in $settings} - - - - {/if} - - - - - - - - - - {#if 'stagingSource' in $settings} - - - - {/if} - - - -

{$_('section.settings.screens')}

- {#if $settings.screens} - {#each $settings.screens as s} + - {/each} - {/if} - - {#if $settings.actCurrencies && $settings.useNostr !== true} - -

{$_('section.settings.currencies')}

- {$_('restartRequired')} - {#if $settings.availableCurrencies} - {#each $settings.availableCurrencies as c} + + + + + + + + + + + + + + + + + + + + + {#if !$settings.actCurrencies} -
- - -
+ - {/each} + {/if} +
+ +
{$_('section.settings.screens')}
+ {#if $settings.screens} + {#each $settings.screens as s} + + + + {/each} + {/if} +
+ {#if $settings.actCurrencies && $settings.useNostr !== true} + +
{$_('section.settings.currencies')}
+ {$_('restartRequired')} + {#if $settings.availableCurrencies} + {#each $settings.availableCurrencies as c} + +
+ + +
+ + {/each} + {/if} +
{/if} -
- {/if} + + + + + + + + + + + + + + + + + + + {$_('time.minutes')} + + + + + + + + + {$_('time.minutes')} + + + + + + + + + {$_('time.seconds')} + + {$_('section.settings.shortAmountsWarning')} + + + + + + + + + {#if $settings.hasFrontlight && !$settings.flDisable} + + + + + + + + + + + + + {/if} + {#if !$settings.flDisable && $settings.hasLightLevel} + + + + + + + {/if} + + + + + + + + + + + {#if $settings.hasFrontlight} + + + + {/if} + {#if $settings.hasFrontlight && !$settings.flDisable} + + + + + + + {/if} + + + + + + + + + + + + HTTPS + + + {$_('section.settings.mempoolInstanceHelpText')} + + + + + + + {#if $settings.nostrRelay} + + + + {$_('section.settings.useNostrTooltip')} + + + {/if} + {#if 'stagingSource' in $settings} + + + + {/if} + + + + + {#if $settings.bitaxeEnabled} + + + + + + + + + + {/if} + {#if 'nostrZapNotify' in $settings && $settings['nostrZapNotify']} + + + + checkValidNostrPubkey('nostrZapPubkey')} + invalid={!isValidHexPubKey($settings.nostrZapPubkey)} + bsSize={$uiSettings.inputSize} + required + minlength="64" + > + {#if !isValidHexPubKey($settings.nostrZapPubkey)} + {$_('section.settings.invalidNostrPubkey')} + {/if} + + + {/if} + {#if $settings.useNostr} + + + + checkValidNostrPubkey('nostrPubKey')} + invalid={!isValidHexPubKey($settings.nostrPubKey)} + bsSize={$uiSettings.inputSize} + > + {#if !isValidHexPubKey($settings.nostrPubKey)} + {$_('section.settings.invalidNostrPubkey')} + {/if} + + + {/if} + {#if 'nostrZapNotify' in $settings || $settings.useNostr} + + + + + + + + + + {/if} + + {#if 'bitaxeEnabled' in $settings} + + + + {/if} + {#if 'nostrZapNotify' in $settings} + + + + + + + {#if $settings.hasFrontlight && !$settings.flDisable} + + + + {/if} + {/if} + + + + + + + + + + {$_('time.minutes')} + + + {$_('section.settings.tzOffsetHelpText')} + + + {#if $settings.httpAuthEnabled} + + + + + + + + + + + + + + {$_('section.settings.httpAuthText')} + + + {/if} + + + + + + + + + + + {#each wifiTxPowerMap as [key, value]} + + {/each} + + {$_('section.settings.wifiTxPowerText')} + + + + + + + + {$_('time.seconds')} + + + + + + + + + + + + + + + + + diff --git a/src/routes/Status.svelte b/src/routes/Status.svelte index 7121106..1e76da6 100644 --- a/src/routes/Status.svelte +++ b/src/routes/Status.svelte @@ -136,7 +136,7 @@ {#if $settings.actCurrencies && $settings.ownDataSource} -
+
{#each $settings.actCurrencies as c}
-
+
{ - await page.route('*/**/api/status', async (route) => { - await route.fulfill({ json: statusJson }); - }); - - await page.route('*/**/api/show/screen/1', async (route) => { - //if (route.request().url().includes('*/**/api/show/screen/1')) { - statusJson.currentScreen = 1; - statusJson.data = ['MSCW/TIME', ' ', ' ', '2', '6', '4', '4']; - statusJson.rendered = statusJson.data; - //} - - await route.fulfill({ json: statusJson }); - }); - - await page.route('*/**/api/show/screen/2', async (route) => { - statusJson.currentScreen = 2; - statusJson.data = ['BTC/USD', '$', '3', '7', '8', '2', '4']; - statusJson.rendered = statusJson.data; - - await route.fulfill({ json: statusJson }); - }); - - await page.route('*/**/api/show/screen/4', async (route) => { - statusJson.currentScreen = 4; - statusJson.data = ['BIT/COIN', 'HALV/ING', '0/YRS', '149/DAYS', '8/HRS', '30/MINS', 'TO/GO']; - statusJson.rendered = statusJson.data; - - await route.fulfill({ json: statusJson }); - }); - - await page.route('*/**/api/settings', async (route) => { - await route.fulfill({ json: settingsJson }); - }); - - await page.route('**/events', (route) => { - const newStatus = statusJson; - newStatus.data = ['BLOCK/HEIGHT', '8', '0', '0', '8', '1', '5']; - - // Respond with a custom SSE message - route.fulfill({ - status: 200, - contentType: 'text/event-stream', - json: `${JSON.stringify(newStatus)}\n\n` - }); - }); -}); +test.beforeEach(initMock); test('index page has expected columns control, status, settings', async ({ page }) => { await page.goto('/'); @@ -181,6 +74,8 @@ test('time values can not be zero or negative', async ({ page }) => { }); test('info message when fetch eur price is enabled', async ({ page }) => { + delete (settingsJson as { actCurrencies?: string[] }).actCurrencies; + await page.goto('/'); await page.getByRole('button', { name: 'Show all' }).click(); diff --git a/tests/screenshots/viewport-screenshots.spec.ts b/tests/screenshots/viewport-screenshots.spec.ts new file mode 100644 index 0000000..9628342 --- /dev/null +++ b/tests/screenshots/viewport-screenshots.spec.ts @@ -0,0 +1,77 @@ +import { test, expect } from '@playwright/test'; + +import { initMock, settingsJson } from '../shared'; + +test.beforeEach(initMock); + +test('capture screenshots across devices', async ({ page }) => { + await page.goto('/'); + await expect(page.getByRole('heading', { name: 'Control' })).toBeVisible(); + await expect(page.getByRole('heading', { name: 'Status' })).toBeVisible(); + await expect(page.getByRole('heading', { name: 'Settings' })).toBeVisible(); + + await page.screenshot({ + path: `./test-results/screenshots/default-${test.info().project.name}.png`, + fullPage: true + }); +}); + +test('capture screenshots across devices with bitaxe screens', async ({ page }) => { + settingsJson.screens = [ + { + id: 0, + name: 'Block Height', + enabled: true + }, + { + id: 3, + name: 'Time', + enabled: true + }, + { + id: 4, + name: 'Halving countdown', + enabled: true + }, + { + id: 6, + name: 'Block Fee Rate', + enabled: true + }, + { + id: 10, + name: 'Sats per dollar', + enabled: true + }, + { + id: 20, + name: 'Ticker', + enabled: true + }, + { + id: 30, + name: 'Market Cap', + enabled: true + }, + { + id: 80, + name: 'BitAxe Hashrate', + enabled: true + }, + { + id: 81, + name: 'BitAxe Best Difficulty', + enabled: true + } + ]; + + await page.goto('/'); + await expect(page.getByRole('heading', { name: 'Control' })).toBeVisible(); + await expect(page.getByRole('heading', { name: 'Status' })).toBeVisible(); + await expect(page.getByRole('heading', { name: 'Settings' })).toBeVisible(); + + await page.screenshot({ + path: `./test-results/screenshots/bitaxe-${test.info().project.name}.png`, + fullPage: true + }); +}); diff --git a/tests/shared.ts b/tests/shared.ts new file mode 100644 index 0000000..18e7e9d --- /dev/null +++ b/tests/shared.ts @@ -0,0 +1,140 @@ +export const statusJson = { + currentScreen: 0, + numScreens: 7, + timerRunning: true, + espUptime: 4479, + espFreeHeap: 58508, + espHeapSize: 342108, + connectionStatus: { price: true, blocks: true }, + rssi: -66, + data: ['BLOCK/HEIGHT', '8', '1', '8', '0', '2', '6'], + rendered: ['BLOCK/HEIGHT', '8', '1', '8', '0', '2', '6'], + leds: [ + { red: 0, green: 0, blue: 0, hex: '#000000' }, + { red: 0, green: 0, blue: 0, hex: '#000000' }, + { red: 0, green: 0, blue: 0, hex: '#000000' }, + { red: 0, green: 0, blue: 0, hex: '#000000' } + ] +}; + +export const settingsJson = { + numScreens: 7, + fgColor: 415029, + bgColor: 0, + timerSeconds: 1800, + timerRunning: true, + minSecPriceUpd: 30, + fullRefreshMin: 60, + wpTimeout: 600, + tzOffset: 0, + useBitcoinNode: false, + mempoolInstance: 'mempool.space', + ledTestOnPower: true, + ledFlashOnUpd: true, + ledBrightness: 128, + stealFocus: true, + mcapBigChar: true, + mdnsEnabled: true, + otaEnabled: true, + fetchEurPrice: false, + hostnamePrefix: 'btclock', + hostname: 'btclock-d60b14', + ip: '192.168.20.231', + txPower: 78, + gitRev: '25d8b92bcbc8938417c140355ea3ba99ff9eb4b7', + gitTag: '3.1.9', + bitaxeEnabled: false, + bitaxeHostname: 'bitaxe1', + nostrZapNotify: true, + hwRev: 'REV_A_EPD_2_13', + fsRev: '4c5d9616212b27e3f05c35370f0befcf2c5a04b2', + nostrZapPubkey: 'b5127a08cf33616274800a4387881a9f98e04b9c37116e92de5250498635c422', + lastBuildTime: '1700666677', + screens: [ + { + id: 0, + name: 'Block Height', + enabled: true + }, + { + id: 3, + name: 'Time', + enabled: true + }, + { + id: 4, + name: 'Halving countdown', + enabled: true + }, + { + id: 6, + name: 'Block Fee Rate', + enabled: true + }, + { + id: 10, + name: 'Sats per dollar', + enabled: true + }, + { + id: 20, + name: 'Ticker', + enabled: true + }, + { + id: 30, + name: 'Market Cap', + enabled: true + } + ], + actCurrencies: ['USD', 'EUR'], + availableCurrencies: ['USD', 'EUR', 'GBP', 'JPY', 'AUD', 'CAD'] +}; + +export const initMock = async ({ page }) => { + await page.route('*/**/api/status', async (route) => { + await route.fulfill({ json: statusJson }); + }); + + await page.route('*/**/api/show/screen/1', async (route) => { + //if (route.request().url().includes('*/**/api/show/screen/1')) { + statusJson.currentScreen = 1; + statusJson.data = ['MSCW/TIME', ' ', ' ', '2', '6', '4', '4']; + statusJson.rendered = statusJson.data; + //} + + await route.fulfill({ json: statusJson }); + }); + + await page.route('*/**/api/show/screen/2', async (route) => { + statusJson.currentScreen = 2; + statusJson.data = ['BTC/USD', '$', '3', '7', '8', '2', '4']; + statusJson.rendered = statusJson.data; + + await route.fulfill({ json: statusJson }); + }); + + await page.route('*/**/api/show/screen/4', async (route) => { + statusJson.currentScreen = 4; + statusJson.data = ['BIT/COIN', 'HALV/ING', '0/YRS', '149/DAYS', '8/HRS', '30/MINS', 'TO/GO']; + statusJson.rendered = statusJson.data; + + await route.fulfill({ json: statusJson }); + }); + + await page.route('*/**/api/settings', async (route) => { + await route.fulfill({ json: settingsJson }); + }); + + await page.route('**/events', (route) => { + const newStatus = statusJson; + newStatus.data = ['BLOCK/HEIGHT', '8', '0', '0', '8', '1', '5']; + + // Respond with a custom SSE message + route.fulfill({ + status: 200, + contentType: 'text/event-stream', + json: `${JSON.stringify(newStatus)}\n\n` + }); + }); +}; From 653a39d0a339bcf3ac3365eacd2e5e8136ecf4c6 Mon Sep 17 00:00:00 2001 From: Djuri Baars Date: Thu, 12 Dec 2024 23:04:13 +0100 Subject: [PATCH 18/21] Improvements for xs screens --- playwright.screenshot.config.ts | 15 ++++++ src/lib/style/app.scss | 38 +++++++++++++- src/routes/+layout.svelte | 26 ++++++++-- src/routes/+page.svelte | 50 ++++++++++++++++--- src/routes/Control.svelte | 4 +- src/routes/Settings.svelte | 4 +- src/routes/Status.svelte | 4 +- .../screenshots/viewport-screenshots.spec.ts | 22 +++++--- vite.config.ts | 8 +++ 9 files changed, 146 insertions(+), 25 deletions(-) diff --git a/playwright.screenshot.config.ts b/playwright.screenshot.config.ts index 2eadd5f..81264a4 100644 --- a/playwright.screenshot.config.ts +++ b/playwright.screenshot.config.ts @@ -1,6 +1,7 @@ import { defineConfig, devices } from '@playwright/test'; export default defineConfig({ + reporter: 'html', use: { locale: 'en-GB', timezoneId: 'Europe/Amsterdam' @@ -31,6 +32,20 @@ export default defineConfig({ use: { viewport: { width: 1512, height: 982 } } + }, + { + name: 'MacBook Pro 14 inch', + use: { + viewport: { width: 1512, height: 982 } + } + }, + { + name: 'MacBook Pro 14 inch Firefox HiDPI', + use: { ...devices['Desktop Firefox HiDPI'], viewport: { width: 1512, height: 982 } } + }, + { + name: 'MacBook Pro 14 inch Safari', + use: { ...devices['Desktop Safari'], viewport: { width: 1512, height: 982 } } } ] }); diff --git a/src/lib/style/app.scss b/src/lib/style/app.scss index 002e5db..0703d06 100644 --- a/src/lib/style/app.scss +++ b/src/lib/style/app.scss @@ -1,6 +1,4 @@ @import '../node_modules/bootstrap/scss/functions'; -@import '../node_modules/bootstrap/scss/variables'; -@import '../node_modules/bootstrap/scss/variables-dark'; //@import "@fontsource/antonio/latin-400.css"; @import '@fontsource/ubuntu/latin-400.css'; @@ -14,6 +12,8 @@ $font-family-base: 'Ubuntu'; $font-size-base: 0.9rem; $input-font-size-sm: $font-size-base * 0.875; +@import '../node_modules/bootstrap/scss/variables'; +@import '../node_modules/bootstrap/scss/variables-dark'; // $border-radius: .675rem; @import '../node_modules/bootstrap/scss/mixins'; @@ -43,6 +43,40 @@ $input-font-size-sm: $font-size-base * 0.875; @import '../node_modules/bootstrap/scss/helpers'; @import '../node_modules/bootstrap/scss/utilities/api'; +/* Default state (xs) - sticky */ +.sticky-xs-top { + position: sticky; + top: 0; + z-index: 1020; +} + +@media (max-width: 576px) { + main { + margin-top: 25px; + } +} + +/* Remove sticky behavior for larger screens */ +@media (min-width: 576px) { + .sticky-xs-top { + position: relative; + } +} + +@include color-mode(dark) { + .navbar { + --bs-navbar-color: $light; + background-color: $dark; + } +} + +@include color-mode(light) { + .navbar { + --bs-navbar-color: $dark; + background-color: $light; + } +} + nav { margin-bottom: 15px; } diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index 0faad53..e421f5a 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -12,6 +12,7 @@ NavbarBrand, NavbarToggler } from '@sveltestrap/sveltestrap'; + import { _ } from 'svelte-i18n'; import { page } from '$app/stores'; import { locale, locales, isLoading } from 'svelte-i18n'; @@ -38,7 +39,7 @@ return flagMap[lowercaseCode]; } else { // Return null for unsupported language codes - return null; + return flagMap['en']; } }; @@ -61,8 +62,23 @@ }; - - ₿TClock + + ₿TClock + + @@ -94,4 +110,6 @@ - +
+ +
diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index b37ab13..c2e4e3b 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -3,6 +3,7 @@ import { screenSize, updateScreenSize } from '$lib/screen'; import { Container, Row, Toast, ToastBody } from '@sveltestrap/sveltestrap'; + import { replaceState } from '$app/navigation'; import { onMount } from 'svelte'; import { writable } from 'svelte/store'; @@ -16,12 +17,6 @@ bgColor: '0' }); - // let uiSettings = writable({ - // inputSize: 'sm', - // selectClass: '', - // btnSize: 'lg' - // }); - let status = writable({ data: ['L', 'O', 'A', 'D', 'I', 'N', 'G'], espFreeHeap: 0, @@ -60,7 +55,43 @@ }); }; + let sections: (HTMLElement | null)[]; + let observer: IntersectionObserver; + const SM_BREAKPOINT = 576; + + const setupObserver = () => { + if (window.innerWidth < SM_BREAKPOINT) { + observer = new IntersectionObserver( + (entries) => { + entries.forEach((entry) => { + if (entry.isIntersecting) { + const id = entry.target.id; + replaceState(`#${id}`); + + // Update nav pills + document.querySelectorAll('.nav-link').forEach((link) => { + link.classList.remove('active'); + if (link.getAttribute('href') === `#${id}`) { + link.classList.add('active'); + } + }); + } + }); + }, + { + threshold: 0.25 // Trigger when section is 50% visible + } + ); + + sections = ['control', 'status', 'settings'].map((id) => document.getElementById(id)); + + sections.forEach((section) => observer.observe(section!)); + } + }; + onMount(() => { + setupObserver(); + fetchSettingsData(); fetchStatusData(); @@ -72,6 +103,11 @@ }); function handleResize() { + if (observer) { + observer.disconnect(); + } + setupObserver(); + updateScreenSize(); } @@ -125,7 +161,9 @@ + + diff --git a/src/routes/Control.svelte b/src/routes/Control.svelte index d89ee10..25f5a44 100644 --- a/src/routes/Control.svelte +++ b/src/routes/Control.svelte @@ -105,8 +105,8 @@ export let xxl = xl; - - + + {$_('section.control.title', { default: 'Control' })} diff --git a/src/routes/Settings.svelte b/src/routes/Settings.svelte index 141c512..77c8a3d 100644 --- a/src/routes/Settings.svelte +++ b/src/routes/Settings.svelte @@ -221,8 +221,8 @@ systemIsOpen: boolean; - - + +
- - + + {$_('section.status.title', { default: 'Status' })} diff --git a/tests/screenshots/viewport-screenshots.spec.ts b/tests/screenshots/viewport-screenshots.spec.ts index 9628342..573b059 100644 --- a/tests/screenshots/viewport-screenshots.spec.ts +++ b/tests/screenshots/viewport-screenshots.spec.ts @@ -4,19 +4,23 @@ import { initMock, settingsJson } from '../shared'; test.beforeEach(initMock); -test('capture screenshots across devices', async ({ page }) => { +test('capture screenshots across devices', async ({ page }, testInfo) => { await page.goto('/'); await expect(page.getByRole('heading', { name: 'Control' })).toBeVisible(); await expect(page.getByRole('heading', { name: 'Status' })).toBeVisible(); await expect(page.getByRole('heading', { name: 'Settings' })).toBeVisible(); - await page.screenshot({ - path: `./test-results/screenshots/default-${test.info().project.name}.png`, - fullPage: true + const screenshot = await page.screenshot({ + path: `./test-results/screenshots/default-${test.info().project.name.toLowerCase().replace(' ', '_')}.png` + }); + + await testInfo.attach(`default`, { + body: screenshot, + contentType: 'image/png' }); }); -test('capture screenshots across devices with bitaxe screens', async ({ page }) => { +test('capture screenshots across devices with bitaxe screens', async ({ page }, testInfo) => { settingsJson.screens = [ { id: 0, @@ -71,7 +75,11 @@ test('capture screenshots across devices with bitaxe screens', async ({ page }) await expect(page.getByRole('heading', { name: 'Settings' })).toBeVisible(); await page.screenshot({ - path: `./test-results/screenshots/bitaxe-${test.info().project.name}.png`, - fullPage: true + path: `./test-results/screenshots/bitaxe-${test.info().project.name.toLowerCase().replace(' ', '_')}.png` + }); + + await testInfo.attach(`bitaxe`, { + path: `./test-results/screenshots/bitaxe-${test.info().project.name.toLowerCase().replace(' ', '_')}.png`, + contentType: 'image/png' }); }); diff --git a/vite.config.ts b/vite.config.ts index bb8e5b2..b2ed254 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -76,6 +76,14 @@ export default defineConfig({ } } }, + css: { + preprocessorOptions: { + scss: { + quietDeps: true, + silenceDeprecations: ['import'] + } + } + }, test: { include: ['src/**/*.{test,spec}.{js,ts}'], globals: true, From 266a99be96189bea92e0ef593f930bb92d3b5b20 Mon Sep 17 00:00:00 2001 From: Djuri Baars Date: Wed, 18 Dec 2024 00:45:26 +0100 Subject: [PATCH 19/21] Add vertical screen description option --- src/lib/locales/de.json | 3 ++- src/lib/locales/en.json | 3 ++- src/lib/locales/es.json | 3 ++- src/lib/locales/nl.json | 3 ++- src/lib/style/app.scss | 10 ++++++++-- src/routes/Rendered.svelte | 15 ++++++++------- src/routes/Settings.svelte | 9 +++++++++ src/routes/Status.svelte | 6 +++++- 8 files changed, 38 insertions(+), 14 deletions(-) diff --git a/src/lib/locales/de.json b/src/lib/locales/de.json index a26ab60..e9756ff 100644 --- a/src/lib/locales/de.json +++ b/src/lib/locales/de.json @@ -57,7 +57,8 @@ "showAll": "Alle anzeigen", "hideAll": "Alles ausblenden", "flOffWhenDark": "Displaybeleuchtung aus, wenn es dunkel ist", - "luxLightToggleText": "Zum Deaktivieren auf 0 setzen" + "luxLightToggleText": "Zum Deaktivieren auf 0 setzen", + "verticalDesc": "Vrtikale Bildschirmbeschreibung" }, "control": { "systemInfo": "Systeminfo", diff --git a/src/lib/locales/en.json b/src/lib/locales/en.json index 6e829bd..3ab90ed 100644 --- a/src/lib/locales/en.json +++ b/src/lib/locales/en.json @@ -69,7 +69,8 @@ "showAll": "Show all", "hideAll": "Hide all", "flOffWhenDark": "Frontlight off when dark", - "luxLightToggleText": "Set to 0 to disable" + "luxLightToggleText": "Set to 0 to disable", + "verticalDesc": "Use vertical screen description" }, "control": { "systemInfo": "System info", diff --git a/src/lib/locales/es.json b/src/lib/locales/es.json index eb15ced..79b6673 100644 --- a/src/lib/locales/es.json +++ b/src/lib/locales/es.json @@ -56,7 +56,8 @@ "showAll": "Mostrar todo", "hideAll": "Ocultar todo", "flOffWhenDark": "Luz de la pantalla cuando está oscuro", - "luxLightToggleText": "Establecer en 0 para desactivar" + "luxLightToggleText": "Establecer en 0 para desactivar", + "verticalDesc": "Descripción de pantalla vertical" }, "control": { "turnOff": "Apagar", diff --git a/src/lib/locales/nl.json b/src/lib/locales/nl.json index b31f7ad..eb5b5af 100644 --- a/src/lib/locales/nl.json +++ b/src/lib/locales/nl.json @@ -57,7 +57,8 @@ "showAll": "Toon alles", "hideAll": "Alles verbergen", "flOffWhenDark": "Displaylicht uit als het donker is", - "luxLightToggleText": "Stel in op 0 om uit te schakelen" + "luxLightToggleText": "Stel in op 0 om uit te schakelen", + "verticalDesc": "Verticale schermbeschrijving" }, "control": { "systemInfo": "Systeeminformatie", diff --git a/src/lib/style/app.scss b/src/lib/style/app.scss index 0703d06..8e9115c 100644 --- a/src/lib/style/app.scss +++ b/src/lib/style/app.scss @@ -158,12 +158,18 @@ nav { padding: 5px; } - .splitText div:first-child::after { + &.verticalDesc > .splitText:first-child { + .textcontainer { + transform: rotate(-90deg); + } + } + + .splitText .textcontainer :first-child::after { display: block; content: ''; margin-top: 0px; border-bottom: 2px solid; - margin-bottom: 3px; + // margin-bottom: 3px; } .splitText { diff --git a/src/routes/Rendered.svelte b/src/routes/Rendered.svelte index 4c4167b..99c3a26 100644 --- a/src/routes/Rendered.svelte +++ b/src/routes/Rendered.svelte @@ -9,7 +9,7 @@ }; export let className = 'btclock-wrapper'; - + export let verticalDesc = false; // Define the currency symbols as constants const CURRENCY_USD = '$'; const CURRENCY_EUR = '['; @@ -44,15 +44,16 @@
-
+
{#each status.data as char} {#if isSplitText(char)}
- {#if char.split('/').length} - {char.split('/')[0]} -
- {char.split('/')[1]} - {/if} +
+ {#if char.split('/').length} + {char.split('/')[0]} + {char.split('/')[1]} + {/if} +
diff --git a/src/routes/Settings.svelte b/src/routes/Settings.svelte index 77c8a3d..8130940 100644 --- a/src/routes/Settings.svelte +++ b/src/routes/Settings.svelte @@ -318,6 +318,15 @@ label={$_('section.settings.suffixShareDot')} /> + + + {#if !$settings.actCurrencies} diff --git a/src/routes/Status.svelte b/src/routes/Status.svelte index afe2c87..812ee68 100644 --- a/src/routes/Status.svelte +++ b/src/routes/Status.svelte @@ -151,7 +151,11 @@
{#if $status.data}
- +
{$_('section.status.screenCycle')}: Date: Wed, 18 Dec 2024 01:24:21 +0100 Subject: [PATCH 20/21] Add bitaxe icon and modify tests for it --- src/lib/style/app.scss | 4 ++++ src/routes/Rendered.svelte | 21 ++++++++++++++++-- static/bitaxe.webp | Bin 0 -> 2486 bytes .../screenshots/viewport-screenshots.spec.ts | 5 ++++- 4 files changed, 27 insertions(+), 3 deletions(-) create mode 100644 static/bitaxe.webp diff --git a/src/lib/style/app.scss b/src/lib/style/app.scss index 8e9115c..53eeee8 100644 --- a/src/lib/style/app.scss +++ b/src/lib/style/app.scss @@ -299,3 +299,7 @@ nav { input[type='number'] { text-align: right; } + +.lightMode .bitaxelogo { + filter: brightness(0) saturate(100%); +} diff --git a/src/routes/Rendered.svelte b/src/routes/Rendered.svelte index 99c3a26..d2beb74 100644 --- a/src/routes/Rendered.svelte +++ b/src/routes/Rendered.svelte @@ -59,7 +59,7 @@ {/each} -->
{:else if char.startsWith('mdi')} -
+
{#if char.endsWith('rocket')} {/if} @@ -69,6 +69,9 @@ {#if char.endsWith('bolt')} {/if} + {#if char.endsWith('bitaxe')} + + {/if}
{:else if char === 'STS'}
S
@@ -83,8 +86,22 @@
- diff --git a/static/bitaxe.webp b/static/bitaxe.webp new file mode 100644 index 0000000000000000000000000000000000000000..3c907c12a77647c9f742882dec2ed85e903c5d72 GIT binary patch literal 2486 zcmY*a2|QHm8~(-&V;6%4#WaYLISk3(Xa>nPsK{-(mKn)bW-_)CVaAnR%C${{ERmwR z;*u?-h}4zBwPwu{Zpn5>x7+>y&-Xj$eZKcR&-1?T`JLbIv$rrayDI>Iqv;{?ak8$H zAOK(o_YML;695w{@?i%g0I>OJpZEBOy&E65YxSUKlLwpnd0D%bb+Y?zJr*gd=6N)X_SN;R&!y0bDQQTwn9HD0XXMbxDPmcSLK^$%Vu_u`WKht9r+W(zxNc1ucymbyht z&#gYXn?it*L(Eqs$ItC^R}`08zs>VeUcBq7vO*B;&@z9oiF?NI-jUIxrP_VA-jnCu zM(u{vvgP|48ntdg8j-BR2TZG*eivWi3lfPGA+e;<*oqsU-|#k6#CU7;xe@2#3Vgx$1uTcP}A@nE#`DeaX*FCC7z zy0_MxIrI9`QnEQIN-J8d2y%%p8@s|#6R-@aAzHsjD+%XB5h|VTP(Rx~7~WrL*|3}~ zaUUv+pFW!=v&2qNot$J8!=pu3GLj<@>R;KM%pO#~&0;i)-rd@4AkBB*bHDi5oQ;Uv zQOpOuF_FJUNT>3XWrq9}Hmu!i^mo1EA?zfVH5fyRoKM{q8Fe?`x`{4M-O*26a8|+P<>iY^EtAAD*j>I%mX$(*ODZ~#Dy9RHnTuo?uctjZ+j28W} zJV5bqh1JnnC-?*QR3t3aSdmg;Xy>@#j(xlweN`Y_Pdyx%o@8^hyh^XK{~;b4B>_Tc zOyr`=?pQnB5Noi;{pt5J^-#jvGiX`#jv>CJ`kN0+MpX3;>LLZpNgjQYPxW-pP!ovF z-kgZ2oG)PhTJd!5)yR#5%17si%MhTmND9WDybvr|)O9j_2Xh~C@`H-LZfozGF`RhP z^1!fIO=s0<-dk_7dg8QyRa|6tCAFF}T!%Eqn<)}$nJ3HD$~m2LPnojqB`k&PFc3HJ zyQFy6w)}=nd$XXk6-}7(vZFf-!-g!+R&Tuyw(xN;1u9pf)X4(|bXt;4=DS-%))&9=y3 zr?21t*pt>S40@m&<4=^HOT|xD8IGc1s&2ZMugy8Twxq*!A&(=-wxacb*>_&bSXmBo zszhx}-0t*HQZr!l%t_-Ft9){%U?RD;DTr5;Dx=ZNc*MMmJkgx!9!kxenET5{fL1N? zy8e!+G>g^d_tJVPE`~Ii)0BOxuLYkHBZY@-|)4;VUUx#8pYZ3wRxc@3>ZRf+Z|=6|_Mf}{l_SWjz#jXhuc0l?`IscJdI#s};B;fvlJ!)&L+`8NBNZah z;k+=$a*b<7|GAOE>!p|Tzh*7yn_?3z!cu0soF#1Kjz%|Ro5i4Gyqw$pkw3Rm(|9!6 zu`A`Y#`iZ9ZAeibA#IWmB8yQ`CU#dOqdx`gW^#laB!#l#Z%iYP4b}JxW}!mM@X9J$ z8AVmzoZ+9Iz|l@NFU!V_)wXZzn*Incup7ukL%G*{mcxdRnJlnvx`HQ=7g*j03Pf?r z*wtTa1HzwfVkcI}bOY%% zyQ{loJ}uu5L%+8=&^l%RiS=kT{9+c_=D`63AyG7KLcp=qD&8Z*i`0UJ)lp8$bYUF< z`AHBl6@{o=Av(^j!u`@Y8{4SLZ6N#7BPogY3*lFDYHLq#5AE(O&#=bGq&}GBUEe9z z)EE2*?Bqydc`j^l@3WQPG6*y8e44H0O7Sdd)90|;xY+H%4MVk?5l-v-r9MSVHx{JB zltM*reO*UxQ&A=wYX@2GXv!U6AUf08w^9&vJ|sZbPm#!(N^Ba?m{gW{LNEEC9VTz@ zb}K+EM^fyDY~E}({9nvtv88jeCS!uF6J5}GFWcFRo-5Fue(&^{* zA&9|X;22ssKYtHMQ%_G1(!fJ_ygHYmP7Cs-y9BEH(iHzO`PYX;p}F~co~L{I`C_(w zU0nSx(v7g#twKMpfBK|*Qva*uOT&F@8t3Nc18u#5G;tcx4{xs2a4V~C>+eb7R^IYA k)-?Ra{J-4yI)>0z@&9S&pGm)ExuY5j8bUulo3SAH8~?g1Bme*a literal 0 HcmV?d00001 diff --git a/tests/screenshots/viewport-screenshots.spec.ts b/tests/screenshots/viewport-screenshots.spec.ts index 573b059..5ec5569 100644 --- a/tests/screenshots/viewport-screenshots.spec.ts +++ b/tests/screenshots/viewport-screenshots.spec.ts @@ -1,6 +1,6 @@ import { test, expect } from '@playwright/test'; -import { initMock, settingsJson } from '../shared'; +import { initMock, settingsJson, statusJson } from '../shared'; test.beforeEach(initMock); @@ -69,6 +69,9 @@ test('capture screenshots across devices with bitaxe screens', async ({ page }, } ]; + statusJson.data = ['mdi:bitaxe', '', 'mdi:pickaxe', '6', '3', '7', 'GH/S']; + statusJson.rendered = ['mdi:bitaxe', '', 'mdi:pickaxe', '6', '3', '7', 'GH/S']; + await page.goto('/'); await expect(page.getByRole('heading', { name: 'Control' })).toBeVisible(); await expect(page.getByRole('heading', { name: 'Status' })).toBeVisible(); From 85b9b17506f89696b89ab6f6e6ed231b7a8f6e91 Mon Sep 17 00:00:00 2001 From: Djuri Baars Date: Wed, 18 Dec 2024 01:28:17 +0100 Subject: [PATCH 21/21] Add alt tag to bitaxe logo --- src/routes/Rendered.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/Rendered.svelte b/src/routes/Rendered.svelte index d2beb74..d544ad8 100644 --- a/src/routes/Rendered.svelte +++ b/src/routes/Rendered.svelte @@ -70,7 +70,7 @@ {/if} {#if char.endsWith('bitaxe')} - + {/if}
{:else if char === 'STS'}