diff --git a/.eslintignore b/.eslintignore
new file mode 100644
index 0000000..a42df6d
--- /dev/null
+++ b/.eslintignore
@@ -0,0 +1,14 @@
+.DS_Store
+node_modules
+/build
+/.svelte-kit
+/package
+.env
+.env.*
+!.env.example
+dist
+build_gz
+# Ignore files for PNPM, NPM and YARN
+pnpm-lock.yaml
+package-lock.json
+yarn.lock
diff --git a/.eslintrc.cjs b/.eslintrc.cjs
new file mode 100644
index 0000000..1105b14
--- /dev/null
+++ b/.eslintrc.cjs
@@ -0,0 +1,33 @@
+module.exports = {
+ root: true,
+ extends: [
+ 'eslint:recommended',
+ 'plugin:@typescript-eslint/recommended',
+ 'plugin:svelte/recommended',
+ 'prettier'
+ ],
+ parser: '@typescript-eslint/parser',
+ plugins: ['@typescript-eslint'],
+ parserOptions: {
+ sourceType: 'module',
+ ecmaVersion: 2020,
+ extraFileExtensions: ['.svelte']
+ },
+ env: {
+ browser: true,
+ es2017: true,
+ node: true
+ },
+ rules: {
+ 'no-empty': ['error', { allowEmptyCatch: true }]
+ },
+ overrides: [
+ {
+ files: ['*.svelte'],
+ parser: 'svelte-eslint-parser',
+ parserOptions: {
+ parser: '@typescript-eslint/parser'
+ }
+ }
+ ]
+};
diff --git a/.forgejo/workflows/build.yaml b/.forgejo/workflows/build.yaml
deleted file mode 100644
index f6899f2..0000000
--- a/.forgejo/workflows/build.yaml
+++ /dev/null
@@ -1,132 +0,0 @@
-on:
- push:
- branches:
- - main
- pull_request:
-
-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:
- token: ${{ secrets.GH_TOKEN }}
- node-version: lts/*
- cache: yarn
- cache-dependency-path: '**/yarn.lock'
- - uses: actions/cache@v4
- with:
- path: |
- ~/.cache/pip
- ~/node_modules
- ~/.cache/ms-playwright
- key: ${{ runner.os }}-pio-playwright-${{ hashFiles('**/yarn.lock') }}
- - 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
- if: steps.cache.outputs.cache-hit != 'true'
- run: npx playwright install --with-deps
- - name: Run Playwright tests
- run: npx playwright test
- - name: Build WebUI
- run: yarn build
-
- # The following steps only run on push to main
- - name: Get current block
- if: github.event_name == 'push' && github.ref == 'refs/heads/main'
- 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=410000
-
- # 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
- if: github.event_name == 'push' && github.ref == 'refs/heads/main'
- run: tar czf webui.tgz --strip-components=1 dist
- - name: Build LittleFS
- run: |
- set -e
- /tmp/mklittlefs/mklittlefs -c build_gz -s 410000 output/littlefs.bin
- - name: Upload artifacts
- if: github.event_name == 'push' && github.ref == 'refs/heads/main'
- 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.6.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
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index c44914e..a5ca2ac 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -10,6 +10,3 @@ updates:
schedule:
interval: 'daily'
versioning-strategy: 'increase-if-necessary'
- ignore:
- - dependency-name: '*'
- update-types: ['version-update:semver-major']
diff --git a/.github/workflows/workflow.yml b/.github/workflows/workflow.yml
index 310777b..f6aad5d 100644
--- a/.github/workflows/workflow.yml
+++ b/.github/workflows/workflow.yml
@@ -100,9 +100,7 @@ jobs:
- 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
+ run: /tmp/mklittlefs/mklittlefs -c build_gz -s 409600 output/littlefs.bin
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
diff --git a/README.md b/README.md
index 7913f27..805bfa1 100644
--- a/README.md
+++ b/README.md
@@ -1,11 +1,10 @@
# BTClock WebUI
-[](https://git.btclock.dev/btclock/webui/releases/latest)
-[](https://git.btclock.dev/btclock/webui/actions?workflow=build.yaml&actor=0&status=0)
+[](https://github.com/btclock/webui2/actions/workflows/workflow.yml)
The web user-interface for the BTClock, based on Svelte-kit. It uses Bootstrap for the lay-out.
-
+

## Developing
@@ -31,11 +30,7 @@ Make sure the postinstall script is ran, because otherwise the filenames are to
## Deploying
-To upload the firmware to the BTClock, you need to GZIP all the files. You can use the python script `gzip_build.py` for that:
-
-```bash
-python3 gzip_build.py
-```
+To upload the firmware to the BTClock, you need to GZIP all the files. You can use the python script `gzip_build.py` for that.
Then you can make a `LittleFS.bin` with mklittlefs:
diff --git a/doc/screenshot-dark.webp b/doc/screenshot-dark.webp
index 64f26d2..a225afe 100644
Binary files a/doc/screenshot-dark.webp and b/doc/screenshot-dark.webp differ
diff --git a/doc/screenshot-light.webp b/doc/screenshot-light.webp
deleted file mode 100644
index d5fad73..0000000
Binary files a/doc/screenshot-light.webp and /dev/null differ
diff --git a/doc/screenshot.webp b/doc/screenshot.webp
new file mode 100644
index 0000000..0a5d87e
Binary files /dev/null and b/doc/screenshot.webp differ
diff --git a/eslint.config.js b/eslint.config.js
deleted file mode 100644
index 62dbd03..0000000
--- a/eslint.config.js
+++ /dev/null
@@ -1,33 +0,0 @@
-import js from '@eslint/js';
-import ts from 'typescript-eslint';
-import svelte from 'eslint-plugin-svelte';
-import prettier from 'eslint-config-prettier';
-import globals from 'globals';
-
-/** @type {import('eslint').Linter.Config[]} */
-export default [
- js.configs.recommended,
- ...ts.configs.recommended,
- ...svelte.configs['flat/recommended'],
- prettier,
- ...svelte.configs['flat/prettier'],
- {
- languageOptions: {
- globals: {
- ...globals.browser,
- ...globals.node
- }
- }
- },
- {
- files: ['**/*.svelte'],
- languageOptions: {
- parserOptions: {
- parser: ts.parser
- }
- }
- },
- {
- ignores: ['build/', '.svelte-kit/', 'dist/']
- }
-];
diff --git a/package.json b/package.json
index 8596a5c..b09337b 100644
--- a/package.json
+++ b/package.json
@@ -5,69 +5,65 @@
"scripts": {
"dev": "vite dev",
"build": "vite build",
- "build:test": "vite build --config vite.config.test.ts",
"preview": "vite preview",
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
"lint": "prettier --check . && eslint .",
"format": "prettier --write .",
"postinstall": "patch-package",
- "test": "prettier --write . && eslint . && npm run test:integration && npm run test:unit",
+ "test": "npm run test:integration && npm run test:unit",
"test:integration": "playwright test",
- "test:screenshots": "playwright test -c playwright.screenshot.config.ts",
- "doc:update-screenshots": "playwright test -c playwright.doc-screenshot.config.ts",
"test:unit": "vitest"
},
"devDependencies": {
"@rollup/plugin-json": "^6.0.1",
- "@sveltejs/adapter-auto": "^3.0.0",
- "@sveltejs/adapter-static": "^3.0.0",
- "@sveltejs/kit": "^2.0.0",
+ "@sveltejs/adapter-auto": "^2.0.0",
+ "@sveltejs/adapter-static": "^2.0.3",
+ "@sveltejs/kit": "^1.27.4",
"@sveltejs/vite-plugin-svelte": "^3.0.1",
"@testing-library/svelte": "^5.2.1",
"@types/swagger-ui": "^3.52.4",
- "@typescript-eslint/eslint-plugin": "^8.7.0",
- "@typescript-eslint/parser": "^8.7.0",
- "@vitest/ui": "^2.0.5",
- "eslint": "^9.11.0",
- "eslint-config-prettier": "^9.1.0",
- "eslint-plugin-svelte": "^2.36.0",
+ "@typescript-eslint/eslint-plugin": "^8.4.0",
+ "@typescript-eslint/parser": "^8.4.0",
+ "@vitest/ui": "^0.34.6",
+ "eslint": "^8.28.0",
+ "eslint-config-prettier": "^9.0.0",
+ "eslint-plugin-svelte": "^2.30.0",
"jsdom": "^25.0.0",
- "prettier": "^3.3.3",
- "prettier-plugin-svelte": "^3.2.6",
- "rollup-plugin-visualizer": "^5.12.0",
- "sass": "^1.79.3",
- "sharp": "^0.33.5",
- "svelte": "^4.2.19",
- "svelte-check": "^4.0.2",
- "svelte-preprocess": "^6.0.2",
- "tslib": "^2.7.0",
- "typescript": "^5.5.4",
- "typescript-eslint": "^8.7.0",
- "vite": "^5.4.7",
- "vitest": "^2.1.1"
+ "prettier": "^3.0.0",
+ "prettier-plugin-svelte": "^3.0.0",
+ "sass": "^1.69.5",
+ "svelte": "^4.0.5",
+ "svelte-check": "^3.6.0",
+ "svelte-preprocess": "^5.1.1",
+ "tslib": "^2.4.1",
+ "typescript": "^5.0.0",
+ "vite": "^5.4.2",
+ "vitest": "^2.0.5",
+ "vitest-github-actions-reporter": "^0.11.0"
},
"type": "module",
"dependencies": {
- "@fontsource/antonio": "^5.1.0",
- "@fontsource/oswald": "^5.1.0",
- "@fontsource/ubuntu": "^5.1.0",
+ "@fontsource/antonio": "^5.0.17",
+ "@fontsource/oswald": "^5.0.17",
+ "@fontsource/ubuntu": "^5.0.8",
"@noble/secp256k1": "^2.1.0",
"@playwright/test": "^1.46.0",
- "@popperjs/core": "^2.11.8",
- "@sveltestrap/sveltestrap": "^6.2.7",
"@testing-library/jest-dom": "^6.5.0",
- "bootstrap": "^5.3.3",
+ "bootstrap": "^5.3.2",
"bootstrap-icons": "^1.11.3",
- "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"
+ "svelte-i18n": "^4.0.0",
+ "sveltestrap": "^5.11.2",
+ "swagger-ui": "^5.10.0"
},
"resolutions": {
"es5-ext": ">=0.10.64",
+ "undici": ">=5.28.4",
"ws": ">=8.18.0",
+ "axios": ">=1.7.7",
"micromatch": ">=4.0.8"
- }
+ },
+ "packageManager": "yarn@1.22.21+sha1.1959a18351b811cdeedbd484a8f86c3cc3bbaf72"
}
diff --git a/patches/@sveltejs+kit+2.16.0+001+initial.patch b/patches/@sveltejs+kit+1.30.4.patch
similarity index 66%
rename from patches/@sveltejs+kit+2.16.0+001+initial.patch
rename to patches/@sveltejs+kit+1.30.4.patch
index 7fb98b1..a008413 100644
--- a/patches/@sveltejs+kit+2.16.0+001+initial.patch
+++ b/patches/@sveltejs+kit+1.30.4.patch
@@ -1,17 +1,17 @@
diff --git a/node_modules/@sveltejs/kit/src/exports/vite/index.js b/node_modules/@sveltejs/kit/src/exports/vite/index.js
-index ddbe746..1d926a4 100644
+index a7a886d..d3433b5 100644
--- a/node_modules/@sveltejs/kit/src/exports/vite/index.js
+++ b/node_modules/@sveltejs/kit/src/exports/vite/index.js
-@@ -658,9 +658,9 @@ async function kit({ svelte_config }) {
+@@ -561,9 +561,9 @@ function kit({ svelte_config }) {
+ input,
output: {
- format: inline ? 'iife' : 'esm',
- name: `__sveltekit_${version_hash}.app`,
+ format: 'esm',
- entryFileNames: ssr ? '[name].js' : `${prefix}/[name].[hash].${ext}`,
-- chunkFileNames: ssr ? 'chunks/[name].js' : `${prefix}/chunks/[hash].${ext}`,
+- chunkFileNames: ssr ? 'chunks/[name].js' : `${prefix}/chunks/[name].[hash].${ext}`,
- assetFileNames: `${prefix}/assets/[name].[hash][extname]`,
+ entryFileNames: ssr ? '[name].js' : `${prefix}/[hash].${ext}`,
-+ chunkFileNames: ssr ? 'chunks/[name].js' : `${prefix}/c[hash].${ext}`,
-+ assetFileNames: `${prefix}/a[hash][extname]`,
++ chunkFileNames: ssr ? 'chunks/[name].js' : `${prefix}/chunks/[hash].${ext}`,
++ assetFileNames: `${prefix}/assets/[hash][extname]`,
hoistTransitiveImports: false,
- sourcemapIgnoreList,
- manualChunks: split ? undefined : () => 'bundle',
+ sourcemapIgnoreList
+ },
diff --git a/playwright.config.ts b/playwright.config.ts
index 461f3c2..d60d61c 100644
--- a/playwright.config.ts
+++ b/playwright.config.ts
@@ -6,11 +6,11 @@ const config: PlaywrightTestConfig = {
timezoneId: 'Europe/Amsterdam'
},
webServer: {
- command: 'npm run build:test && npm run preview',
+ command: 'npm run build && npm run preview',
port: 4173
},
reporter: process.env.CI ? 'github' : 'list',
- testDir: 'tests/playwright',
+ testDir: 'tests',
testMatch: /(.+\.)?(test|spec)\.[jt]s/
};
diff --git a/playwright.doc-screenshot.config.ts b/playwright.doc-screenshot.config.ts
deleted file mode 100644
index f052338..0000000
--- a/playwright.doc-screenshot.config.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-import { defineConfig } from '@playwright/test';
-
-export default defineConfig({
- use: {
- locale: 'en-GB',
- timezoneId: 'Europe/Amsterdam'
- },
- webServer: {
- command: 'yarn build && yarn preview',
- port: 4173
- },
- testDir: './tests/doc-screenshots',
- outputDir: './test-results/screenshots',
- projects: [
- {
- name: 'Light Mode',
- use: {
- viewport: { width: 1440, height: 900 },
- colorScheme: 'light'
- }
- },
- {
- name: 'Dark Mode',
- use: { viewport: { width: 1440, height: 900 }, colorScheme: 'dark' }
- }
- ]
-});
diff --git a/playwright.screenshot.config.ts b/playwright.screenshot.config.ts
deleted file mode 100644
index f4272ff..0000000
--- a/playwright.screenshot.config.ts
+++ /dev/null
@@ -1,67 +0,0 @@
-import { defineConfig, devices } from '@playwright/test';
-
-export default defineConfig({
- reporter: 'html',
- use: {
- locale: 'en-GB',
- timezoneId: 'Europe/Amsterdam'
- },
- webServer: {
- command: 'npm run build && npm run preview',
- port: 4173
- },
- testDir: './tests/screenshots',
- outputDir: './test-results/screenshots',
- projects: [
- {
- name: 'MacBook Air 13 inch',
- use: {
- viewport: { width: 1440, height: 900 }
- }
- },
- {
- name: 'iPhone 14 Pro',
- use: { ...devices['iPhone 14 Pro'] }
- },
- {
- name: 'iPhone 15 Pro Landscape',
- use: { ...devices['iPhone 15 Pro Landscape'] }
- },
- {
- name: 'MacBook Pro 14 inch',
- use: {
- viewport: { width: 1512, height: 982 }
- }
- },
- {
- name: 'MacBook Pro 14 inch NL locale',
- use: {
- viewport: { width: 1512, height: 982 },
- locale: 'nl'
- }
- },
- {
- name: 'MacBook Pro 14 inch nl-NL locale',
- use: {
- viewport: { width: 1512, height: 982 },
- locale: 'nl-NL'
- }
- },
- {
- 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 } }
- },
- {
- name: 'MacBook Pro 14 inch Safari Dark Mode',
- use: {
- ...devices['Desktop Safari'],
- viewport: { width: 1512, height: 982 },
- colorScheme: 'dark'
- }
- }
- ]
-});
diff --git a/renovate.json b/renovate.json
deleted file mode 100644
index 7dca1ca..0000000
--- a/renovate.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "$schema": "https://docs.renovatebot.com/renovate-schema.json",
- "extends": ["config:recommended"],
- "packageRules": [
- {
- "matchUpdateTypes": ["major"],
- "enabled": false,
- "matchPackageNames": ["*"]
- }
- ],
- "npm": {
- "rangeStrategy": "update-lockfile"
- }
-}
diff --git a/src/icons/EyeIcon.svelte b/src/icons/EyeIcon.svelte
new file mode 100644
index 0000000..dd7513a
--- /dev/null
+++ b/src/icons/EyeIcon.svelte
@@ -0,0 +1,13 @@
+
diff --git a/src/icons/EyeSlashIcon.svelte b/src/icons/EyeSlashIcon.svelte
new file mode 100644
index 0000000..bf45888
--- /dev/null
+++ b/src/icons/EyeSlashIcon.svelte
@@ -0,0 +1,18 @@
+
diff --git a/src/lib/components/ColorSchemeSwitcher.svelte b/src/lib/components/ColorSchemeSwitcher.svelte
deleted file mode 100644
index 9d7e32a..0000000
--- a/src/lib/components/ColorSchemeSwitcher.svelte
+++ /dev/null
@@ -1,53 +0,0 @@
-
-
-
-
- {theme === 'auto' ? '🌗' : theme === 'dark' ? '🌙' : '☀️'}
-
-
- setTheme('light')}
- >☀️ Light
- setTheme('dark')}>🌙 Dark
- setTheme('auto')}>🌗 Auto
-
-
diff --git a/src/lib/components/Placeholder.svelte b/src/lib/components/Placeholder.svelte
deleted file mode 100644
index 3eecfdc..0000000
--- a/src/lib/components/Placeholder.svelte
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
- {valueToCheck ? value : ''}
-
diff --git a/src/lib/components/SettingsInput.svelte b/src/lib/components/SettingsInput.svelte
deleted file mode 100644
index 01738e6..0000000
--- a/src/lib/components/SettingsInput.svelte
+++ /dev/null
@@ -1,65 +0,0 @@
-
-
-
-
-
-
-
- {#if suffix}
- {suffix}
- {/if}
-
-
- {#if helpText}
- {helpText}
- {/if}
-
-
diff --git a/src/lib/components/SettingsSelect.svelte b/src/lib/components/SettingsSelect.svelte
deleted file mode 100644
index ef34fec..0000000
--- a/src/lib/components/SettingsSelect.svelte
+++ /dev/null
@@ -1,34 +0,0 @@
-
-
-
-
-
-
- {#each options as [key, val]}
-
- {/each}
-
- {#if helpText}
- {helpText}
- {/if}
-
-
diff --git a/src/lib/components/SettingsSwitch.svelte b/src/lib/components/SettingsSwitch.svelte
deleted file mode 100644
index 27a3156..0000000
--- a/src/lib/components/SettingsSwitch.svelte
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
-
-
diff --git a/src/lib/components/ToggleHeader.svelte b/src/lib/components/ToggleHeader.svelte
deleted file mode 100644
index acc8d3b..0000000
--- a/src/lib/components/ToggleHeader.svelte
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-
- (isOpen = !isOpen)}
- tabindex="0"
- on:keypress={() => (isOpen = !isOpen)}
- >
- {#if isOpen}
-
- {:else}
-
- {/if}
- {header}
-
-
-
-
-
diff --git a/src/lib/components/index.ts b/src/lib/components/index.ts
deleted file mode 100644
index b026c1c..0000000
--- a/src/lib/components/index.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-export { default as SettingsSwitch } from './SettingsSwitch.svelte';
-export { default as SettingsInput } from './SettingsInput.svelte';
-export { default as SettingsSelect } from './SettingsSelect.svelte';
-export { default as ToggleHeader } from './ToggleHeader.svelte';
-export { default as ColorSchemeSwitcher } from './ColorSchemeSwitcher.svelte';
-export { default as Placeholder } from './Placeholder.svelte';
diff --git a/src/lib/components/settings/DataSourceSettings.svelte b/src/lib/components/settings/DataSourceSettings.svelte
deleted file mode 100644
index 5891573..0000000
--- a/src/lib/components/settings/DataSourceSettings.svelte
+++ /dev/null
@@ -1,142 +0,0 @@
-
-
-
-
-
-
- Data Source
-
-
-
-
-
-
-
-
- {#if $settings.nostrRelay}
-
-
-
- {/if}
-
-
-
-
-
-
-
-
- {#if $settings.dataSource === DataSourceType.THIRD_PARTY_SOURCE}
-
-
-
- HTTPS
-
-
- {/if}
-
- {#if $settings.dataSource === DataSourceType.NOSTR_SOURCE}
-
- checkValidNostrPubkey('nostrPubKey')}
- onInput={() => checkValidNostrPubkey('nostrPubKey')}
- />
- {/if}
-
- {#if $settings.dataSource === DataSourceType.CUSTOM_SOURCE}
-
-
- {/if}
-
-
diff --git a/src/lib/components/settings/DisplaySettings.svelte b/src/lib/components/settings/DisplaySettings.svelte
deleted file mode 100644
index 0edaad0..0000000
--- a/src/lib/components/settings/DisplaySettings.svelte
+++ /dev/null
@@ -1,206 +0,0 @@
-
-
-
-
-
-
-
-
- ($settings.timePerScreen = Number(e.target.value))}
- type="number"
- min={1}
- step={1}
- required={true}
- suffix={$_('time.minutes')}
- size={$uiSettings.inputSize}
- />
-
-
-
-
-
-
- {#if $settings.hasFrontlight && !$settings.flDisable}
-
-
-
- {/if}
-
- {#if !$settings.flDisable && $settings.hasLightLevel}
-
- {/if}
-
-
-
-
-
-
-
-
- {#if $settings.hasFrontlight}
-
- {/if}
-
- {#if $settings.hasFrontlight && !$settings.flDisable}
-
-
-
-
- {#if $settings.hasLightLevel}
-
- {/if}
- {/if}
-
-
-
diff --git a/src/lib/components/settings/ExtraFeaturesSettings.svelte b/src/lib/components/settings/ExtraFeaturesSettings.svelte
deleted file mode 100644
index 95cc470..0000000
--- a/src/lib/components/settings/ExtraFeaturesSettings.svelte
+++ /dev/null
@@ -1,321 +0,0 @@
-
-
-
-
-
-
- {#if $settings.dnd.timeBasedEnabled}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {/if}
-
-
- {#if 'bitaxeEnabled' in $settings}
-
-
- BitAxe
-
- {#if $settings.bitaxeEnabled}
-
-
-
- {/if}
-
-
- {/if}
-
-
- {#if 'miningPoolStats' in $settings}
-
-
- Mining Pool stats
-
- {#if $settings.miningPoolStats}
-
- {#if $settings.miningPoolName === 'local_public_pool'}
-
-
-
- {/if}
-
- {/if}
-
-
- {/if}
-
-
- {#if 'nostrZapNotify' in $settings}
-
-
- Nostr
-
-
- {#if $settings.nostrZapNotify}
-
-
- {#if $settings.hasFrontlight && !$settings.flDisable}
-
- {/if}
-
-
-
-
- checkValidNostrPubkey('nostrZapPubkey')}
- onInput={() => checkValidNostrPubkey('nostrZapPubkey')}
- />
- {/if}
-
-
- {/if}
-
-
diff --git a/src/lib/components/settings/ScreenSpecificSettings.svelte b/src/lib/components/settings/ScreenSpecificSettings.svelte
deleted file mode 100644
index bae67df..0000000
--- a/src/lib/components/settings/ScreenSpecificSettings.svelte
+++ /dev/null
@@ -1,126 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {#if !$settings.actCurrencies}
-
- {/if}
-
-
- {$_('section.settings.screens')}
- {#if $settings.screens}
- {#each $settings.screens as s}
-
- {/each}
- {/if}
-
- {#if $settings.actCurrencies && $settings.dataSource == DataSourceType.BTCLOCK_SOURCE}
-
- {$_('section.settings.currencies')}
- {$_('restartRequired')}
- {#if $settings.availableCurrencies}
- {#each $settings.availableCurrencies as c}
-
-
-
-
-
-
- {/each}
- {/if}
-
- {/if}
-
-
diff --git a/src/lib/components/settings/SystemSettings.svelte b/src/lib/components/settings/SystemSettings.svelte
deleted file mode 100644
index f774c8f..0000000
--- a/src/lib/components/settings/SystemSettings.svelte
+++ /dev/null
@@ -1,98 +0,0 @@
-
-
-
-
- ($settings.tzString = value)}
- size={$uiSettings.inputSize}
- />
-
- {#if $settings.httpAuthEnabled}
-
-
-
-
- {/if}
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/lib/components/settings/TimezoneSelector.svelte b/src/lib/components/settings/TimezoneSelector.svelte
deleted file mode 100644
index f76ddd6..0000000
--- a/src/lib/components/settings/TimezoneSelector.svelte
+++ /dev/null
@@ -1,56 +0,0 @@
-
-
-
-
-
-
-
- {#each timezones as tz}
-
- {/each}
-
-
-
- {$_('section.settings.tzOffsetHelpText')}
-
-
diff --git a/src/lib/components/settings/index.ts b/src/lib/components/settings/index.ts
deleted file mode 100644
index 6ddfa7c..0000000
--- a/src/lib/components/settings/index.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-export { default as ScreenSpecificSettings } from './ScreenSpecificSettings.svelte';
-export { default as DisplaySettings } from './DisplaySettings.svelte';
-export { default as DataSourceSettings } from './DataSourceSettings.svelte';
-export { default as ExtraFeaturesSettings } from './ExtraFeaturesSettings.svelte';
-export { default as SystemSettings } from './SystemSettings.svelte';
diff --git a/src/lib/i18n/en.json b/src/lib/i18n/en.json
deleted file mode 100644
index e69de29..0000000
diff --git a/src/lib/i18n/index.ts b/src/lib/i18n/index.ts
index fa817a7..2959787 100644
--- a/src/lib/i18n/index.ts
+++ b/src/lib/i18n/index.ts
@@ -8,23 +8,11 @@ register('nl', () => import('../locales/nl.json'));
register('es', () => import('../locales/es.json'));
register('de', () => import('../locales/de.json'));
-const getInitialLocale = () => {
- if (!browser) return defaultLocale;
-
- // Check localStorage first
- const storedLocale = localStorage.getItem('locale');
- if (storedLocale) return storedLocale;
-
- // Get browser locale and normalize it
- const browserLocale = window.navigator.language;
- const normalizedLocale = browserLocale.split('-')[0].toLowerCase();
-
- // Check if we support this locale
- const supportedLocales = ['en', 'nl', 'es', 'de'];
- return supportedLocales.includes(normalizedLocale) ? normalizedLocale : defaultLocale;
-};
-
init({
fallbackLocale: defaultLocale,
- initialLocale: getInitialLocale()
+ initialLocale: browser
+ ? browser && localStorage.getItem('locale')
+ ? localStorage.getItem('locale')
+ : window.navigator.language.slice(0, 2)
+ : defaultLocale
});
diff --git a/src/lib/locales/de.json b/src/lib/locales/de.json
index 6671619..9ece840 100644
--- a/src/lib/locales/de.json
+++ b/src/lib/locales/de.json
@@ -30,7 +30,7 @@
"wifiTxPower": "WiFi-TX-Leistung",
"settingsSaved": "Einstellungen gespeichert",
"errorSavingSettings": "Fehler beim Speichern der Einstellungen",
- "ownDataSource": "BTClock-Datenquelle",
+ "ownDataSource": "BTClock-Datenquelle verwenden",
"flAlwaysOn": "Displaybeleuchtung immer an",
"flEffectDelay": "Displaybeleuchtungeffekt Geschwindigkeit",
"flFlashOnUpd": "Displaybeleuchting bei neuem Block",
@@ -41,40 +41,7 @@
"flDisable": "Displaybeleuchtung deaktivieren",
"httpAuthUser": "WebUI-Benutzername",
"httpAuthPass": "WebUI-Passwort",
- "httpAuthText": "Schützt nur die WebUI mit einem Passwort, nicht API-Aufrufe.",
- "currencies": "Währungen",
- "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",
- "flOffWhenDark": "Displaybeleuchtung aus, wenn es dunkel ist",
- "luxLightToggleText": "Zum Deaktivieren auf 0 setzen",
- "verticalDesc": "Vrtikale Bildschirmbeschreibung",
- "enableDebugLog": "Debug-Protokoll aktivieren",
- "bitaxeEnabled": "BitAxe-Integration aktivieren",
- "miningPoolStats": "Mining-Pool-Statistiken Integration Aktivieren",
- "nostrZapNotify": "Nostr Zap-Benachrichtigungen aktivieren",
- "thirdPartySource": "mempool.space/coincap.io Verwenden",
- "dataSource": {
- "nostr": "Nostr-Verlag",
- "custom": "Benutzerdefinierter dataquelle"
- },
- "fontName": "Schriftart",
- "timeBasedDnd": "Aktivieren Sie den Zeitplan „Bitte nicht stören“.",
- "dndStartHour": "Startstunde",
- "dndStartMinute": "Startminute",
- "dndEndHour": "Endstunde",
- "dndEndMinute": "Schlussminute",
- "screenRestoreZap": "Vorherigen Bildschirmzustand nach Zap wieder herstellen (Verwendet {setting} Einstellung)"
+ "httpAuthText": "Schützt nur die WebUI mit einem Passwort, nicht API-Aufrufe."
},
"control": {
"systemInfo": "Systeminfo",
@@ -89,8 +56,7 @@
"hostname": "Hostname",
"frontlight": "Displaybeleuchtung",
"turnOn": "Einschalten",
- "flashFrontlight": "Blinken",
- "fwCommitMismatch": "Die Firmware -Version unterscheidet sich von der WebUI -Version, dies kann zu Problemen führen."
+ "flashFrontlight": "Blinken"
},
"status": {
"title": "Status",
@@ -103,9 +69,7 @@
"wifiSignalStrength": "WiFi-Signalstärke",
"wsDataConnection": "BTClock-Datenquelle verbindung",
"lightSensor": "Lichtsensor",
- "nostrConnection": "Nostr Relay-Verbindung",
- "doNotDisturb": "Bitte nicht stören",
- "timeBasedDnd": "Zeitbasierter Zeitplan"
+ "nostrConnection": "Nostr Relay-Verbindung"
},
"firmwareUpdater": {
"fileUploadSuccess": "Datei erfolgreich hochgeladen, Gerät neu gestartet. WebUI in {countdown} Sekunden neu geladen",
@@ -116,9 +80,7 @@
"swUpdateAvailable": "Eine neuere Version ist verfügbar!",
"latestVersion": "Letzte Version",
"releaseDate": "Veröffentlichungsdatum",
- "viewRelease": "Veröffentlichung anzeigen",
- "autoUpdate": "Update installieren (experimentell)",
- "autoUpdateInProgress": "Automatische Aktualisierung läuft, bitte warten..."
+ "viewRelease": "Veröffentlichung anzeigen"
}
},
"colors": {
diff --git a/src/lib/locales/en.json b/src/lib/locales/en.json
index 40476d8..2d85180 100644
--- a/src/lib/locales/en.json
+++ b/src/lib/locales/en.json
@@ -29,7 +29,7 @@
"wifiTxPower": "WiFi TX power",
"settingsSaved": "Settings saved",
"errorSavingSettings": "Error saving settings",
- "ownDataSource": "BTClock data source",
+ "ownDataSource": "Use BTClock data source",
"flMaxBrightness": "Frontlight brightness",
"flAlwaysOn": "Frontlight always on",
"flEffectDelay": "Frontlight effect speed",
@@ -40,13 +40,10 @@
"nostrPubKey": "Nostr source pubkey",
"nostrZapKey": "Nostr zap pubkey",
"nostrRelay": "Nostr Relay",
- "nostrZapNotify": "Enable Nostr Zap Notifications",
- "useNostr": "Use Nostr data source",
+ "nostrZapNotify": "Nostr Zap Notifications",
+ "useNostr": "Use Nostr datasource",
"bitaxeHostname": "BitAxe hostname or IP",
- "bitaxeEnabled": "Enable BitAxe-integration",
- "miningPoolStats": "Enable Mining Pool Stats integration",
- "miningPoolName": "Mining Pool",
- "miningPoolUser": "Mining Pool username or api key",
+ "bitaxeEnabled": "Enable BitAxe",
"nostrZapPubkey": "Nostr Zap pubkey",
"invalidNostrPubkey": "Invalid Nostr pubkey, note that your pubkey does NOT start with npub.",
"convertingValidNpub": "Converting valid npub to pubkey",
@@ -54,44 +51,7 @@
"httpAuthEnabled": "Require authentication for WebUI",
"httpAuthUser": "WebUI Username",
"httpAuthPass": "WebUI Password",
- "httpAuthText": "Only password-protects WebUI, not API-calls.",
- "currencies": "Currencies",
- "customSource": "Use custom data source endpoint",
- "useNostrTooltip": "Very experimental and unstable. Nostr data source is not required for Nostr Zap notifications.",
- "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",
- "flOffWhenDark": "Frontlight off when dark",
- "luxLightToggleText": "Set to 0 to disable",
- "verticalDesc": "Use vertical screen description",
- "enableDebugLog": "Enable Debug-log",
- "dataSource": {
- "label": "Data Source",
- "btclock": "BTClock Data Source",
- "thirdParty": "mempool.space/Kraken",
- "nostr": "Nostr publisher",
- "custom": "Custom Endpoint"
- },
- "thirdPartySource": "Use mempool.space/coincap.io",
- "ceDisableSSL": "Disable SSL",
- "ceEndpoint": "Endpoint hostname",
- "fontName": "Font",
- "timeBasedDnd": "Enable Do Not Disturb time schedule",
- "dndStartHour": "Start hour",
- "dndStartMinute": "Start minute",
- "dndEndHour": "End hour",
- "dndEndMinute": "End minute",
- "screenRestoreZap": "Restore previous screen state after zap (Uses {setting} setting)"
+ "httpAuthText": "Only password-protects WebUI, not API-calls."
},
"control": {
"systemInfo": "System info",
@@ -108,8 +68,7 @@
"turnOn": "Turn on",
"flashFrontlight": "Flash",
"firmwareUpdate": "Firmware update",
- "fwCommit": "Firmware commit",
- "fwCommitMismatch": "The firmware version is different from the WebUI version, this might cause problems. "
+ "fwCommit": "Firmware commit"
},
"status": {
"title": "Status",
@@ -122,9 +81,7 @@
"wifiSignalStrength": "WiFi Signal strength",
"wsDataConnection": "BTClock data-source connection",
"lightSensor": "Light sensor",
- "nostrConnection": "Nostr Relay connection",
- "doNotDisturb": "Do not disturb",
- "timeBasedDnd": "Time-based schedule"
+ "nostrConnection": "Nostr Relay connection"
},
"firmwareUpdater": {
"fileUploadFailed": "File upload failed. Make sure you have selected the correct file and try again.",
@@ -135,9 +92,7 @@
"swUpToDate": "You are up to date.",
"latestVersion": "Latest Version",
"releaseDate": "Release Date",
- "viewRelease": "View Release",
- "autoUpdate": "Install update (experimental)",
- "autoUpdateInProgress": "Auto-update in progress, please wait..."
+ "viewRelease": "View Release"
}
},
"colors": {
diff --git a/src/lib/locales/es.json b/src/lib/locales/es.json
index e9edba5..af5cc35 100644
--- a/src/lib/locales/es.json
+++ b/src/lib/locales/es.json
@@ -28,7 +28,7 @@
"wifiTxPowerText": "En la mayoría de los casos no es necesario configurar esto.",
"settingsSaved": "Configuración guardada",
"errorSavingSettings": "Error al guardar la configuración",
- "ownDataSource": "fuente de datos BTClock",
+ "ownDataSource": "Utilice la fuente de datos BTClock",
"flMaxBrightness": "Brillo de luz de la pantalla",
"flAlwaysOn": "Luz de la pantalla siempre encendida",
"flEffectDelay": "Velocidad del efecto de luz de la pantalla",
@@ -40,40 +40,7 @@
"flDisable": "Desactivar luz de la pantalla",
"httpAuthUser": "Nombre de usuario WebUI",
"httpAuthPass": "Contraseña WebUI",
- "httpAuthText": "Solo la WebUI está protegida con contraseña, no las llamadas API.",
- "currencies": "Monedas",
- "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",
- "flOffWhenDark": "Luz de la pantalla cuando está oscuro",
- "luxLightToggleText": "Establecer en 0 para desactivar",
- "verticalDesc": "Descripción de pantalla vertical",
- "enableDebugLog": "Habilitar registro de depuración",
- "bitaxeEnabled": "Habilitar la integración de BitAxe",
- "miningPoolStats": "Habilitar la integración de estadísticas del grupo minero",
- "nostrZapNotify": "Habilitar notificaciones de Nostr Zap",
- "thirdPartySource": "Utilice mempool.space/coincap.io",
- "dataSource": {
- "nostr": "editorial nostr",
- "custom": "Punto final personalizado"
- },
- "fontName": "Fuente",
- "timeBasedDnd": "Habilitar el horario de No molestar",
- "dndStartHour": "Hora de inicio",
- "dndStartMinute": "Minuto de inicio",
- "dndEndHour": "Hora final",
- "dndEndMinute": "Minuto final",
- "screenRestoreZap": "Restaurar el estado de pantalla anterior después de Zap (Usa la configuración {setting})"
+ "httpAuthText": "Solo la WebUI está protegida con contraseña, no las llamadas API."
},
"control": {
"turnOff": "Apagar",
@@ -88,8 +55,7 @@
"hostname": "Nombre del host",
"turnOn": "Encender",
"frontlight": "Luz de la pantalla",
- "flashFrontlight": "Luz intermitente",
- "fwCommitMismatch": "La versión de firmware es diferente de la versión WebUI, esto podría causar problemas."
+ "flashFrontlight": "Luz intermitente"
},
"status": {
"memoryFree": "Memoria RAM libre",
@@ -102,9 +68,7 @@
"wifiSignalStrength": "Fuerza de la señal WiFi",
"wsDataConnection": "Conexión de fuente de datos BTClock",
"lightSensor": "Sensor de luz",
- "nostrConnection": "Conexión de relé Nostr",
- "doNotDisturb": "No molestar",
- "timeBasedDnd": "Horario basado en el tiempo"
+ "nostrConnection": "Conexión de relé Nostr"
},
"firmwareUpdater": {
"fileUploadSuccess": "Archivo cargado exitosamente, reiniciando el dispositivo. Recargando WebUI en {countdown} segundos",
@@ -115,9 +79,7 @@
"swUpdateAvailable": "¡Una nueva versión está disponible!",
"latestVersion": "Ultima versión",
"releaseDate": "Fecha de lanzamiento",
- "viewRelease": "Ver lanzamiento",
- "autoUpdate": "Instalar actualización (experimental)",
- "autoUpdateInProgress": "Actualización automática en progreso, espere..."
+ "viewRelease": "Ver lanzamiento"
}
},
"button": {
diff --git a/src/lib/locales/nl.json b/src/lib/locales/nl.json
index 8b6bd64..eab8ea7 100644
--- a/src/lib/locales/nl.json
+++ b/src/lib/locales/nl.json
@@ -41,31 +41,7 @@
"flDisable": "Schakel Displaylicht uit",
"httpAuthUser": "WebUI-gebruikersnaam",
"httpAuthPass": "WebUI-wachtwoord",
- "httpAuthText": "Beveiligd enkel WebUI, niet de API.",
- "currencies": "Valuta's",
- "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",
- "flOffWhenDark": "Displaylicht uit als het donker is",
- "luxLightToggleText": "Stel in op 0 om uit te schakelen",
- "verticalDesc": "Verticale schermbeschrijving",
- "fontName": "Lettertype",
- "timeBasedDnd": "Schakel het tijdschema Niet storen in",
- "dndStartHour": "Begin uur",
- "dndStartMinute": "Beginminuut",
- "dndEndHour": "Eind uur",
- "dndEndMinute": "Einde minuut",
- "screenRestoreZap": "Herstel vorige schermstatus na zap (Gebruikt {setting} instelling)"
+ "httpAuthText": "Beveiligd enkel WebUI, niet de API."
},
"control": {
"systemInfo": "Systeeminformatie",
@@ -79,8 +55,7 @@
"title": "Besturing",
"frontlight": "Displaylicht",
"turnOn": "Aanzetten",
- "flashFrontlight": "Knipper",
- "fwCommitMismatch": "De firmwareversie verschilt van de WebUI -versie, dit kan problemen veroorzaken."
+ "flashFrontlight": "Knipper"
},
"status": {
"title": "Status",
@@ -93,9 +68,7 @@
"wifiSignalStrength": "WiFi signaalsterkte",
"wsDataConnection": "BTClock-gegevensbron verbinding",
"lightSensor": "Licht sensor",
- "nostrConnection": "Nostr Relay-verbinding",
- "doNotDisturb": "Niet storen",
- "timeBasedDnd": "Op tijd gebaseerd schema"
+ "nostrConnection": "Nostr Relay-verbinding"
},
"firmwareUpdater": {
"fileUploadSuccess": "Bestand geüpload, apparaat herstart. WebUI opnieuw geladen over {countdown} seconden",
@@ -106,9 +79,7 @@
"swUpdateAvailable": "Een nieuwere versie is beschikbaar!",
"latestVersion": "Laatste versie",
"releaseDate": "Datum van publicatie",
- "viewRelease": "Bekijk publicatie",
- "autoUpdate": "Update installeren (experimenteel)",
- "autoUpdateInProgress": "Automatische update wordt uitgevoerd. Even geduld a.u.b...."
+ "viewRelease": "Bekijk publicatie"
}
},
"colors": {
diff --git a/src/lib/style/app.scss b/src/lib/style/app.scss
index dd3d50a..c8b6e52 100644
--- a/src/lib/style/app.scss
+++ b/src/lib/style/app.scss
@@ -1,33 +1,17 @@
-@use '@fontsource/ubuntu/scss/mixins' as Ubuntu;
-@use '@fontsource/antonio/scss/mixins' as Antonio;
-
@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";
-
-@include Ubuntu.faces(
- $subsets: latin,
- $weights: 400,
- $formats: 'woff2',
- $directory: '@fontsource/ubuntu/files'
-);
-
-@include Antonio.faces(
- $subsets: latin,
- $weights: 400,
- $formats: 'woff2',
- $directory: '@fontsource/antonio/files'
-);
-
+@import '@fontsource/ubuntu/latin-400.css';
+@import '@fontsource/oswald/latin-400.css';
@import './satsymbol';
-$color-mode-type: data;
+$color-mode-type: media-query;
$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';
@@ -42,7 +26,7 @@ $input-font-size-sm: $font-size-base * 0.875;
@import '../node_modules/bootstrap/scss/forms';
@import '../node_modules/bootstrap/scss/buttons';
@import '../node_modules/bootstrap/scss/button-group';
-//@import '../node_modules/bootstrap/scss/pagination';
+@import '../node_modules/bootstrap/scss/pagination';
@import '../node_modules/bootstrap/scss/dropdown';
@@ -53,46 +37,10 @@ $input-font-size-sm: $font-size-base * 0.875;
@import '../node_modules/bootstrap/scss/tooltip';
@import '../node_modules/bootstrap/scss/toasts';
@import '../node_modules/bootstrap/scss/alert';
-@import '../node_modules/bootstrap/scss/placeholders';
-@import '../node_modules/bootstrap/scss/spinners';
@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;
}
@@ -103,23 +51,6 @@ nav {
.btn-group-sm .btn {
font-size: 0.8rem;
- // text-overflow: ellipsis;
- // white-space: nowrap;
- // overflow: hidden;
- // width: 4rem;
-}
-
-.btn-group-sm {
- display: flex !important;
- flex-wrap: wrap !important;
- gap: 0.25rem !important;
-}
-
-/* Remove the border radius override that Bootstrap applies */
-.btn-group-sm > .btn {
- border-radius: 0.25rem !important;
- margin: 0 !important;
- position: relative !important;
}
#customText {
@@ -130,8 +61,8 @@ nav {
.btclock {
background: #000;
display: flex;
- font-size: calc(2vw + 2vh);
- font-family: 'Antonio', sans-serif;
+ font-size: calc(3vw + 3vh);
+ font-family: 'Oswald', sans-serif;
font-weight: 400;
padding: 10px;
gap: 10px;
@@ -145,7 +76,7 @@ nav {
align-items: center;
justify-content: center;
text-align: center;
- padding: 10px 10px 15px 10px;
+ padding: 10px;
width: calc(12vw + 12vh); /* Set a dynamic width based on viewport */
aspect-ratio: 1 / 1.5; /* Maintain a 1:1 aspect ratio */
@@ -159,10 +90,6 @@ nav {
}
}
- .digit.sats {
- padding-top: 35px;
- }
-
.mediumText {
font-size: calc(1.25vw + 1.25vh);
}
@@ -171,25 +98,19 @@ nav {
flex-direction: column; /* Stack the text and line vertically */
align-items: center;
justify-content: space-around; /* Distribute items with space between */
- padding: 5px;
+ padding: 10px;
}
- &.verticalDesc > .splitText:first-child {
- .textcontainer {
- transform: rotate(-90deg);
- }
- }
-
- .splitText .textcontainer :first-child::after {
+ .splitText div:first-child::after {
display: block;
content: '';
margin-top: 0px;
border-bottom: 2px solid;
- // margin-bottom: 3px;
+ margin-bottom: 3px;
}
.splitText {
- font-size: calc(0.3vw + 1vh);
+ font-size: calc(0.5vw + 1vh);
.top-text,
.bottom-text {
@@ -301,52 +222,3 @@ nav {
#firmwareUploadProgress {
@extend .my-2;
}
-
-.sats {
- font-family: 'Satoshi Symbol';
-}
-
-.currencyCode {
- width: 20%;
- text-align: center;
- display: inline-block;
-}
-
-input[type='number'] {
- text-align: right;
-}
-
-.lightMode .bitaxelogo {
- filter: brightness(0) saturate(100%);
-}
-
-.connection-lost-overlay {
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- background-color: rgba(0, 0, 0, 0.75);
- z-index: 1050;
- display: flex;
- justify-content: center;
- align-items: center;
-
- .overlay-content {
- background-color: rgba(255, 255, 255, 0.75);
-
- padding: 0.5rem;
- border-radius: 0.5rem;
- text-align: center;
-
- i {
- font-size: 1rem;
- color: $danger;
- margin-bottom: 1rem;
- }
-
- h4 {
- margin-bottom: 0.5rem;
- }
- }
-}
diff --git a/src/lib/style/satsymbol.scss b/src/lib/style/satsymbol.scss
index 9b7eefd..f761701 100644
--- a/src/lib/style/satsymbol.scss
+++ b/src/lib/style/satsymbol.scss
@@ -1,6 +1,8 @@
@font-face {
font-family: 'Satoshi Symbol';
- src: url('/fonts/Satoshi_Symbol.woff2') format('woff2');
+ src:
+ url('/fonts/Satoshi_Symbol.woff2') format('woff2'),
+ url('/fonts/Satoshi_Symbol.woff') format('woff');
font-weight: normal;
font-style: normal;
font-display: swap;
diff --git a/src/lib/types/dataSource.ts b/src/lib/types/dataSource.ts
deleted file mode 100644
index ffadd46..0000000
--- a/src/lib/types/dataSource.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-export enum DataSourceType {
- BTCLOCK_SOURCE = 0,
- THIRD_PARTY_SOURCE = 1,
- NOSTR_SOURCE = 2,
- CUSTOM_SOURCE = 3
-}
diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte
index 0f1cc8a..ac940e7 100644
--- a/src/routes/+layout.svelte
+++ b/src/routes/+layout.svelte
@@ -9,15 +9,11 @@
NavItem,
NavLink,
Navbar,
- NavbarBrand,
- NavbarToggler
- } from '@sveltestrap/sveltestrap';
- import { _ } from 'svelte-i18n';
+ NavbarBrand
+ } from 'sveltestrap';
import { page } from '$app/stores';
import { locale, locales, isLoading } from 'svelte-i18n';
- import { ColorSchemeSwitcher } from '$lib/components';
- import { derived } from 'svelte/store';
export const setLocale = (lang: string) => () => {
locale.set(lang);
@@ -40,67 +36,37 @@
return flagMap[lowercaseCode];
} else {
// Return null for unsupported language codes
- return flagMap['en'];
+ return null;
}
};
let languageNames = {};
- const currentLocale = derived(locale, ($locale) => $locale || 'en');
-
locale.subscribe(() => {
- const localeToUse = $locale || 'en';
- let newLanguageNames = new Intl.DisplayNames([localeToUse], { type: 'language' });
+ if ($locale) {
+ let newLanguageNames = new Intl.DisplayNames([$locale], { type: 'language' });
- for (let l of $locales) {
- languageNames[l] = newLanguageNames.of(l) || l;
+ for (let l of $locales) {
+ languageNames[l] = newLanguageNames.of(l);
+ }
}
});
-
- let isOpen = false;
-
- const toggle = () => {
- isOpen = !isOpen;
- };
-
- ₿TClock
-
-
-
-
-
+
+ ₿TClock
+
{#if !$isLoading}
-
- {getFlagEmoji($currentLocale)}
- {languageNames[$currentLocale] || 'English'}
+
+ {getFlagEmoji($locale)} {languageNames[$locale]}
{#each $locales as locale}
{/if}
-
-
-
-
+
diff --git a/src/routes/+layout.ts b/src/routes/+layout.ts
index 3c7d853..4497634 100644
--- a/src/routes/+layout.ts
+++ b/src/routes/+layout.ts
@@ -6,15 +6,10 @@ import { locale, waitLocale } from 'svelte-i18n';
import type { LayoutLoad } from './$types';
export const load: LayoutLoad = async () => {
- if (browser) {
- if (localStorage.getItem('locale')) {
- locale.set(localStorage.getItem('locale'));
- } else {
- // Normalize the browser locale
- const browserLocale = window.navigator.language.split('-')[0].toLowerCase();
- const supportedLocales = ['en', 'nl', 'es', 'de'];
- locale.set(supportedLocales.includes(browserLocale) ? browserLocale : 'en');
- }
+ if (browser && localStorage.getItem('locale')) {
+ locale.set(localStorage.getItem('locale'));
+ } else if (browser) {
+ locale.set(window.navigator.language);
}
await waitLocale();
};
diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte
index 5971a12..af0fc9e 100644
--- a/src/routes/+page.svelte
+++ b/src/routes/+page.svelte
@@ -2,8 +2,7 @@
import { PUBLIC_BASE_URL } from '$lib/config';
import { screenSize, updateScreenSize } from '$lib/screen';
- import { Container, Row, Toast, ToastBody } from '@sveltestrap/sveltestrap';
- import { replaceState } from '$app/navigation';
+ import { Container, Row, Toast, ToastBody } from 'sveltestrap';
import { onMount } from 'svelte';
import { writable } from 'svelte/store';
@@ -13,10 +12,15 @@
import { uiSettings } from '$lib/uiSettings';
let settings = writable({
- isLoaded: false,
- timePerScreen: 0
+ fgColor: '0'
});
+ // let uiSettings = writable({
+ // inputSize: 'sm',
+ // selectClass: '',
+ // btnSize: 'lg'
+ // });
+
let status = writable({
data: ['L', 'O', 'A', 'D', 'I', 'N', 'G'],
espFreeHeap: 0,
@@ -25,126 +29,48 @@
price: false,
blocks: false
},
- leds: [],
- isUpdating: false
+ leds: []
});
- const fetchStatusData = async () => {
- const res = await fetch(`${PUBLIC_BASE_URL}/api/status`, { credentials: 'same-origin' });
-
- if (!res.ok) {
- console.error('Error fetching status data:', res.statusText);
- return false;
- }
-
- const data = await res.json();
- status.set(data);
- return true;
+ const fetchStatusData = () => {
+ fetch(`${PUBLIC_BASE_URL}/api/status`, { credentials: 'same-origin' })
+ .then((res) => res.json())
+ .then((data) => {
+ status.set(data);
+ });
};
- const fetchSettingsData = async () => {
- const res = await fetch(PUBLIC_BASE_URL + `/api/settings`, { credentials: 'same-origin' });
+ const fetchSettingsData = () => {
+ fetch(PUBLIC_BASE_URL + `/api/settings`, { credentials: 'same-origin' })
+ .then((res) => res.json())
+ .then((data) => {
+ data.fgColor = String(data.fgColor);
+ data.bgColor = String(data.bgColor);
+ data.timePerScreen = data.timerSeconds / 60;
- if (!res.ok) {
- console.error('Error fetching settings data:', res.statusText);
- return;
- }
-
- const data = await res.json();
-
- data.fgColor = String(data.fgColor);
- data.bgColor = String(data.bgColor);
- data.timePerScreen = data.timerSeconds / 60;
-
- if (data.fgColor > 65535) {
- data.fgColor = '65535';
- }
-
- if (data.bgColor > 65535) {
- data.bgColor = '65535';
- }
- settings.set(data);
- };
-
- 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
+ if (data.fgColor > 65535) {
+ data.fgColor = '65535';
}
- );
- sections = ['control', 'status', 'settings'].map((id) => document.getElementById(id));
-
- sections.forEach((section) => observer.observe(section!));
- }
+ if (data.bgColor > 65535) {
+ data.bgColor = '65535';
+ }
+ settings.set(data);
+ });
};
- onMount(async () => {
- setupObserver();
+ onMount(() => {
+ fetchSettingsData();
+ fetchStatusData();
- const connectEventSource = () => {
- const evtSource = new EventSource(`${PUBLIC_BASE_URL}/events`);
+ const evtSource = new EventSource(`${PUBLIC_BASE_URL}/events`);
- evtSource.addEventListener('status', (e) => {
- let dataObj = JSON.parse(e.data);
- status.update((s) => ({ ...s, isUpdating: true }));
- status.set(dataObj);
- });
-
- evtSource.addEventListener('message', (e) => {
- if (e.data == 'closing') {
- console.log('EventSource closing');
- status.update((s) => ({ ...s, isUpdating: false }));
- evtSource.close(); // Close the current connection
- setTimeout(connectEventSource, 5000);
- }
- });
-
- evtSource.addEventListener('error', (e) => {
- console.error('EventSource failed:', e);
- status.update((s) => ({ ...s, isUpdating: false }));
- evtSource.close(); // Close the current connection
- setTimeout(connectEventSource, 1000);
- });
- };
-
- try {
- await fetchSettingsData();
- if (await fetchStatusData()) {
- settings.update((s) => ({ ...s, isLoaded: true }));
- connectEventSource();
- }
- } catch (error) {
- console.log('Error fetching data:', error);
- }
+ evtSource.addEventListener('status', (e) => {
+ let dataObj = JSON.parse(e.data);
+ status.set(dataObj);
+ });
function handleResize() {
- if (observer) {
- observer.disconnect();
- }
- setupObserver();
-
updateScreenSize();
}
@@ -196,11 +122,9 @@
-
-
-
+
+
-
diff --git a/src/routes/Control.svelte b/src/routes/Control.svelte
index c4e96c1..9874b11 100644
--- a/src/routes/Control.svelte
+++ b/src/routes/Control.svelte
@@ -13,12 +13,10 @@
Form,
Input,
Label,
- Row,
- Alert
- } from '@sveltestrap/sveltestrap';
+ Row
+ } from 'sveltestrap';
import FirmwareUpdater from './FirmwareUpdater.svelte';
import { uiSettings } from '$lib/uiSettings';
- import { Placeholder } from '$lib/components';
export let settings = {};
@@ -107,8 +105,8 @@
export let xxl = xl;
-
-
+
+
{$_('section.control.title', { default: 'Control' })}
@@ -216,22 +214,16 @@
{/if}
- {$_('section.control.buildTime')}:
+ {$_('section.control.buildTime')}: {new Date(
+ $settings.lastBuildTime * 1000
+ ).toLocaleString()}
- IP:
- HW revision:
- {$_('section.control.fwCommit')}:
- WebUI commit:
- {$_('section.control.hostname')}:
+ IP: {$settings.ip}
+ HW revision: {$settings.hwRev}
+ {$_('section.control.fwCommit')}: {$settings.gitRev}
+ WebUI commit: {$settings.fsRev}
+ {$_('section.control.hostname')}: {$settings.hostname}
- {#if $settings.gitRev != $settings.fsRev}
-
- ⚠️ {$_('warning')}: {$_('section.control.fwCommitMismatch')}
-
- {/if}
{$_('section.control.firmwareUpdate')}
-
+
{/if}
diff --git a/src/routes/FirmwareUpdater.svelte b/src/routes/FirmwareUpdater.svelte
index 06f4d0e..74839a3 100644
--- a/src/routes/FirmwareUpdater.svelte
+++ b/src/routes/FirmwareUpdater.svelte
@@ -1,15 +1,12 @@
-{#if latestVersion && latestVersion != 'error'}
+{#if latestVersion}
{$_('section.firmwareUpdater.latestVersion')}: {latestVersion} - {$_(
'section.firmwareUpdater.releaseDate'
)}: {releaseDate} -
{$_('section.firmwareUpdater.viewRelease')}
{#if isNewerVersionAvailable}
- {#if !$status.isOTAUpdating}
- {$_('section.firmwareUpdater.swUpdateAvailable')} -
- {$_('section.firmwareUpdater.autoUpdate')}.
- {:else}
- {$_('section.firmwareUpdater.autoUpdateInProgress')}
- {/if}
+ {$_('section.firmwareUpdater.swUpdateAvailable')}
{:else}
{$_('section.firmwareUpdater.swUpToDate')}
{/if}
-{:else if latestVersion == 'error'}
- Error loading version, try again later.
{:else}
Loading...
{/if}
-{#if !$status.isOTAUpdating}
-
- {#if firmwareUploadProgress > 0}
-
+
+
+ handleFileChange(e, (file) => (firmwareUploadFile = file))}
+ name="update"
+ class="form-control"
+ accept=".bin"
+ />
+
+
+
- {/if}
- {#if firmwareUploadSuccess}
-
{$_('section.firmwareUpdater.fileUploadSuccess', { values: { countdown: $countdown } })}
-
- {/if}
-
- {#if firmwareUploadError}
-
{$_('section.firmwareUpdater.fileUploadFailed')}
+
+
+ handleFileChange(e, (file) => (firmwareWebUiFile = file))}
+ accept=".bin"
+ />
+
+
+
- {/if}
-
⚠️ {$_('warning')}: {$_('section.firmwareUpdater.firmwareUpdateText')}
+
+{#if firmwareUploadProgress > 0}
+
{/if}
+{#if firmwareUploadSuccess}
+
{$_('section.firmwareUpdater.fileUploadSuccess', { values: { countdown: $countdown } })}
+
+{/if}
+
+{#if firmwareUploadError}
+
{$_('section.firmwareUpdater.fileUploadFailed')}
+{/if}
+
⚠️ {$_('warning')}: {$_('section.firmwareUpdater.firmwareUpdateText')}
diff --git a/src/routes/Rendered.svelte b/src/routes/Rendered.svelte
index e4a1783..b29cf27 100644
--- a/src/routes/Rendered.svelte
+++ b/src/routes/Rendered.svelte
@@ -9,57 +9,24 @@
};
export let className = 'btclock-wrapper';
- export let verticalDesc = false;
- // Define the currency symbols as constants
- const CURRENCY_USD = '$';
- const CURRENCY_EUR = '[';
- const CURRENCY_GBP = ']';
- const CURRENCY_JPY = '^';
- const CURRENCY_AUD = '_';
- //const CURRENCY_CHF = '_';
- const CURRENCY_CAD = '`';
-
- function getCurrencySymbol(input: string): string {
- // Split the string into an array of characters to process each one
- return input
- .split('')
- .map((char) => {
- switch (char) {
- case CURRENCY_EUR:
- return '€'; // Euro symbol
- case CURRENCY_GBP:
- return '£'; // Pound symbol
- case CURRENCY_JPY:
- return '¥'; // Yen symbol
- case CURRENCY_AUD:
- case CURRENCY_CAD:
- case CURRENCY_USD:
- return '$'; // Dollar symbol
- default:
- return char; // Return the original character if no match
- }
- })
- .join(''); // Join the array back into a string
- }
-
+
{#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}
{:else if char.startsWith('mdi')}
-
+
{#if char.endsWith('rocket')}
{/if}
@@ -69,12 +36,6 @@
{#if char.endsWith('bolt')}
{/if}
- {#if char.endsWith('bitaxe')}
-

- {/if}
- {#if char.endsWith('miningpool')}
-
Mining Pool Logo
- {/if}
{:else if char === 'STS'}
S
@@ -83,32 +44,14 @@
{:else if char.length === 0 || char === ' '}
{:else}
-
{getCurrencySymbol(char)}
+
{char}
{/if}
{/each}
-
diff --git a/src/routes/Settings.svelte b/src/routes/Settings.svelte
index 16de960..a607883 100644
--- a/src/routes/Settings.svelte
+++ b/src/routes/Settings.svelte
@@ -1,6 +1,9 @@
-
-
+
+
-
-
-
- |
-
-
-
- {$_('section.settings.title')}
+ {$_('section.settings.title', { default: 'Settings' })}
- {#if $settings.isLoaded === false}
-
- {:else}
-
diff --git a/src/routes/Status.svelte b/src/routes/Status.svelte
index a659af0..b34f33b 100644
--- a/src/routes/Status.svelte
+++ b/src/routes/Status.svelte
@@ -15,9 +15,8 @@
Progress,
Tooltip,
Row
- } from '@sveltestrap/sveltestrap';
+ } from 'sveltestrap';
import Rendered from './Rendered.svelte';
- import { DataSourceType } from '$lib/types/dataSource';
export let settings;
export let status: writable