Initial commit

This commit is contained in:
Djuri 2024-03-17 18:35:26 +01:00
commit ba5370c7ca
36 changed files with 4122 additions and 0 deletions

5
src/lib/config.ts Normal file
View file

@ -0,0 +1,5 @@
import * as publicEnv from '$env/static/public';
export const PUBLIC_BASE_URL: string = Object.hasOwn(publicEnv, 'PUBLIC_BASE_URL')
? publicEnv.PUBLIC_BASE_URL
: '';

17
src/lib/i18n/index.ts Normal file
View file

@ -0,0 +1,17 @@
import { browser } from '$app/environment';
import { init, register } from 'svelte-i18n';
const defaultLocale = 'en';
register('en', () => import('../locales/en.json'));
register('nl', () => import('../locales/nl.json'));
register('es', () => import('../locales/es.json'));
init({
fallbackLocale: defaultLocale,
initialLocale: browser
? browser && localStorage.getItem('locale')
? localStorage.getItem('locale')
: window.navigator.language.slice(0, 2)
: defaultLocale
});

1
src/lib/index.ts Normal file
View file

@ -0,0 +1 @@
// place files you want to import through the `$lib` alias in this folder.

95
src/lib/locales/en.json Normal file
View file

@ -0,0 +1,95 @@
{
"section": {
"settings": {
"title": "Settings",
"textColor": "Text color",
"preview": "Preview",
"backgroundColor": "Background color",
"ledPowerOnTest": "LED power-on test",
"ledFlashOnBlock": "LED flash on new block",
"timePerScreen": "Time per screen",
"ledBrightness": "LED brightness",
"timezoneOffset": "Timezone offset",
"timeBetweenPriceUpdates": "Time between price updates",
"fullRefreshEvery": "Full refresh every",
"mempoolnstance": "Mempool Instance",
"hostnamePrefix": "Hostname prefix",
"StealFocusOnNewBlock": "Steal focus on new block",
"useBigCharsMcap": "Use big characters for market cap",
"useBlkCountdown": "Blocks countdown for halving",
"useSatsSymbol": "Use sats symbol",
"suffixPrice": "Suffix price format",
"disableLeds": "Disable all LEDs effects",
"otaUpdates": "OTA updates",
"enableMdns": "mDNS",
"fetchEuroPrice": "Fetch € price",
"shortAmountsWarning": "Short amounts might shorten lifespan of the displays",
"tzOffsetHelpText": "A restart is required to apply TZ offset.",
"screens": "Screens",
"wifiTxPowerText": "In most cases this does not need to be set.",
"wifiTxPower": "WiFi TX power",
"settingsSaved": "Settings saved",
"errorSavingSettings": "Error saving settings"
},
"lines": {
"TIME": "Time",
"DATE": "Date",
"SATSPERUNIT": "Sats per unit (Moscow time)",
"FIATPRICE": "Fiat Price",
"BLOCKHEIGHT": "Block Height",
"MEMPOOL_FEES": "Mempool Fees (summary)",
"MEMPOOL_FEES_MEDIAN": "Mempool Fees (median)",
"HALVING_COUNTDOWN": "Halving Countdown (blocks)",
"MARKETCAP": "Market Cap"
},
"control": {
"systemInfo": "System info",
"version": "Version",
"buildTime": "Build time",
"ledColor": "LED color",
"turnOff": "Turn off",
"setColor": "Set color",
"showText": "Show text",
"text": "Text",
"title": "Control",
"hostname": "Hostname"
},
"status": {
"title": "Status",
"screenCycle": "Screen cycle",
"memoryFree": "Memory free",
"wsPriceConnection": "WS Price connection",
"wsMempoolConnection": "WS Mempool.space connection",
"fetchEuroNote": "If you use \"Fetch € price\" the WS Price connection will show ❌ since it uses another data source.",
"uptime": "Uptime",
"wifiSignalStrength": "WiFi Signal strength"
}
},
"colors": {
"black": "Black",
"white": "White"
},
"time": {
"minutes": "minutes",
"seconds": "seconds"
},
"restartRequired": "restart required",
"button": {
"save": "Save",
"reset": "Reset",
"restart": "Restart",
"forceFullRefresh": "Force full refresh"
},
"timer": {
"running": "running",
"stopped": "stopped"
},
"sections": {
"control": {
"keepSameColor": "Keep same color"
}
},
"rssiBar": {
"tooltip": "Values > -67 dBm are considered good. > -30 dBm is amazing"
}
}

82
src/lib/locales/es.json Normal file
View file

@ -0,0 +1,82 @@
{
"section": {
"settings": {
"title": "Configuración",
"textColor": "Color de texto",
"backgroundColor": "Color de fondo",
"ledBrightness": "Brillo LED",
"screens": "Pantallas",
"shortAmountsWarning": "Pequeñas cantidades pueden acortar la vida útil de los displays",
"fullRefreshEvery": "Actualización completa cada",
"timePerScreen": "Tiempo por pantalla",
"tzOffsetHelpText": "Es necesario reiniciar para aplicar la compensación.",
"timezoneOffset": "Compensación de zona horaria",
"StealFocusOnNewBlock": "Presta atención al nuevo bloque",
"ledFlashOnBlock": "El LED parpadea con un bloque nuevo",
"useBigCharsMcap": "Utilice caracteres grandes para la market cap",
"useBlkCountdown": "Cuenta regresiva en bloques",
"useSatsSymbol": "Usar símbolo sats",
"fetchEuroPrice": "Obtener precio en €",
"timeBetweenPriceUpdates": "Tiempo entre actualizaciones de precios",
"ledPowerOnTest": "Prueba de encendido del LED",
"enableMdns": "mDNS",
"hostnamePrefix": "Prefijo de nombre de host",
"mempoolnstance": "Instancia de Mempool",
"suffixPrice": "Precio con sufijos",
"disableLeds": "Desactivar efectos de LED",
"otaUpdates": "Actualización por aire",
"wifiTxPowerText": "En la mayoría de los casos no es necesario configurar esto.",
"settingsSaved": "Configuración guardada",
"errorSavingSettings": "Error al guardar la configuración"
},
"control": {
"turnOff": "Apagar",
"setColor": "Establecer el color",
"version": "Versión",
"ledColor": "color del LED",
"systemInfo": "Info del sistema",
"showText": "Mostrar texto",
"text": "Texto",
"title": "Control",
"buildTime": "Tiempo de compilación",
"hostname": "Nombre del host"
},
"status": {
"memoryFree": "Memoria RAM libre",
"wsPriceConnection": "Conexión WebSocket Precio",
"wsMempoolConnection": "Conexión WebSocket Mempool.space",
"screenCycle": "Ciclo de pantalla",
"uptime": "Tiempo de funcionamiento",
"fetchEuroNote": "Si utiliza \"Obtener precio en €\", la conexión de Precio WS mostrará ❌ ya que utiliza otra fuente de datos.",
"title": "Estado",
"wifiSignalStrength": "Fuerza de la señal WiFi"
}
},
"button": {
"save": "Guardar",
"reset": "Restaurar",
"restart": "Reiniciar",
"forceFullRefresh": "Forzar refresco"
},
"colors": {
"black": "Negro",
"white": "Blanco"
},
"restartRequired": "reinicio requerido",
"time": {
"minutes": "minutos",
"seconds": "segundos"
},
"timer": {
"running": "funcionando",
"stopped": "detenido"
},
"sections": {
"control": {
"keepSameColor": "Mantén el mismo color"
}
},
"rssiBar": {
"tooltip": "Se consideran buenos valores > -67 dBm. > -30 dBm es increíble"
}
}

82
src/lib/locales/nl.json Normal file
View file

@ -0,0 +1,82 @@
{
"section": {
"settings": {
"title": "Instellingen",
"textColor": "Tekstkleur",
"backgroundColor": "Achtergrondkleur",
"timeBetweenPriceUpdates": "Tijd tussen prijs updates",
"timezoneOffset": "Tijdzone afwijking",
"ledBrightness": "LED helderheid",
"timePerScreen": "Tijd per scherm",
"fullRefreshEvery": "Volledig verversen elke",
"shortAmountsWarning": "Lage waardes verkorten mogelijk levensduur schermen",
"tzOffsetHelpText": "Herstart nodig voor toepassen afwijking.",
"enableMdns": "mDNS",
"ledPowerOnTest": "LED test bij aanzetten",
"StealFocusOnNewBlock": "Pak aandacht bij nieuw blok",
"ledFlashOnBlock": "Knipper led bij nieuw blok",
"useBigCharsMcap": "Gebruik grote tekens bij market cap",
"useBlkCountdown": "Blocks aftellen voor halving",
"useSatsSymbol": "Gebruik sats symbol",
"fetchEuroPrice": "Toon € prijs",
"screens": "Schermen",
"hostnamePrefix": "Hostnaam voorvoegsel",
"mempoolnstance": "Mempool instantie",
"suffixPrice": "Achtervoegsel prijs formaat",
"disableLeds": "Alle LEDs effecten uit",
"otaUpdates": "OTA updates",
"wifiTxPower": "WiFi TX power",
"wifiTxPowerText": "Meestal hoeft dit niet aangepast te worden.",
"settingsSaved": "Instellingen opgeslagen",
"errorSavingSettings": "Fout bij opslaan instellingen"
},
"control": {
"systemInfo": "Systeeminformatie",
"version": "Versie",
"buildTime": "Bouwtijd",
"setColor": "Kleur instellen",
"turnOff": "Uitzetten",
"ledColor": "LED kleur",
"showText": "Toon tekst",
"text": "Tekst",
"title": "Besturing"
},
"status": {
"title": "Status",
"memoryFree": "Geheugen vrij",
"screenCycle": "Scherm cyclus",
"wsPriceConnection": "WS Prijs verbinding",
"wsMempoolConnection": "WS Mempool.space verbinding",
"fetchEuroNote": "Wanneer je \"Toon € prijs\" aanzet, zal de prijsverbinding als ❌ verbroken getoond worden vanwege het gebruik van een andere bron.",
"uptime": "Uptime",
"wifiSignalStrength": "WiFi signaalsterkte"
}
},
"colors": {
"black": "Zwart",
"white": "Wit"
},
"time": {
"minutes": "minuten",
"seconds": "seconden"
},
"restartRequired": "herstart nodig",
"button": {
"save": "Opslaan",
"reset": "Herstel",
"restart": "Herstart",
"forceFullRefresh": "Forceer scherm verversen"
},
"timer": {
"running": "actief",
"stopped": "gestopt"
},
"sections": {
"control": {
"keepSameColor": "Behoud zelfde kleur"
}
},
"rssiBar": {
"tooltip": "Waarden > -67 dBm zijn goed. > -30 dBm is verbazingwekkend"
}
}

68
src/lib/strftime.ts Normal file
View file

@ -0,0 +1,68 @@
import { format, parse, isValid } from 'date-fns';
export function strftime(formatString: string, dateString?: string): string {
const placeholders: { [key: string]: string } = {
'%a': 'EEE',
'%A': 'EEEE',
'%b': 'MMM',
'%B': 'MMMM',
'%c': 'EEE MMM dd HH:mm:ss yyyy',
'%C': '',
'%d': 'dd',
'%D': 'MM/dd/yy',
'%e': 'd',
'%F': 'yyyy-MM-dd',
'%g': '',
'%G': '',
'%h': 'MMM',
'%H': 'HH',
'%I': 'hh',
'%j': 'DDD',
'%k': 'H',
'%l': 'h',
'%m': 'MM',
'%M': 'mm',
'%n': '\n',
'%p': 'a',
'%P': 'a',
'%r': 'hh:mm:ss a',
'%R': 'HH:mm',
'%s': '',
'%S': 'ss',
'%t': '\t',
'%T': 'HH:mm:ss',
'%u': 'E',
'%U': '',
'%V': '',
'%w': 'e',
'%W': '',
'%x': 'MM/dd/yy',
'%X': 'HH:mm:ss',
'%y': 'yy',
'%Y': 'yyyy',
'%z': 'xxx',
'%Z': 'zzz',
'%%': '%'
};
let convertedFormatString = formatString;
if (!convertedFormatString) {
return '';
}
for (const placeholder in placeholders) {
if (Object.prototype.hasOwnProperty.call(placeholders, placeholder)) {
convertedFormatString = convertedFormatString.replace(placeholder, placeholders[placeholder]);
}
}
let parsedDate;
if (dateString && isValid(parse(dateString, 'yyyy-MM-dd', new Date()))) {
parsedDate = parse(dateString, 'yyyy-MM-dd', new Date());
} else {
parsedDate = new Date();
}
return format(parsedDate, convertedFormatString);
}

195
src/lib/style/app.scss Normal file
View file

@ -0,0 +1,195 @@
@import '../node_modules/bootstrap/scss/functions';
@import '../node_modules/bootstrap/scss/variables';
@import '../node_modules/bootstrap/scss/variables-dark';
@import '@fontsource/libre-franklin';
@font-face {
font-family: 'orangeclock-icons';
src:
url('/subset-orangeclock-icons.woff2') format('woff2'),
url('/subset-orangeclock-icons.woff') format('woff');
font-weight: normal;
font-style: normal;
font-display: swap;
}
.icon {
font-family: 'orangeclock-icons';
}
$form-range-track-bg: #fff;
$color-mode-type: media-query;
$font-family-base: 'Ubuntu';
$font-size-base: 0.9rem;
//$font-size-sm: $font-size-base * .875 !default;
//$form-label-font-size: $font-size-base * .575 !default;
//$input-btn-font-size-sm: 0.4rem;
//$form-label-font-size: 0.4rem;
$input-font-size-sm: $font-size-base * 0.875;
// $border-radius: .675rem;
@import '../node_modules/bootstrap/scss/mixins';
@import '../node_modules/bootstrap/scss/maps';
@import '../node_modules/bootstrap/scss/utilities';
@import '../node_modules/bootstrap/scss/root';
@import '../node_modules/bootstrap/scss/reboot';
@import '../node_modules/bootstrap/scss/type';
@import '../node_modules/bootstrap/scss/containers';
@import '../node_modules/bootstrap/scss/grid';
@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/dropdown';
@import '../node_modules/bootstrap/scss/navbar';
@import '../node_modules/bootstrap/scss/nav';
@import '../node_modules/bootstrap/scss/card';
@import '../node_modules/bootstrap/scss/progress';
@import '../node_modules/bootstrap/scss/tooltip';
@import '../node_modules/bootstrap/scss/toasts';
@import '../node_modules/bootstrap/scss/helpers';
@import '../node_modules/bootstrap/scss/utilities/api';
@include media-breakpoint-down(xl) {
html {
font-size: 85%;
}
button.btn,
input[type='button'].btn,
input[type='submit'].btn,
input[type='reset'].btn {
@include button-size(
$btn-padding-y-sm,
$btn-padding-x-sm,
$font-size-sm,
$btn-border-radius-sm
);
}
}
@include media-breakpoint-down(lg) {
html {
font-size: 75%;
}
}
nav {
margin-bottom: 15px;
}
.splitText div:first-child::after {
display: block;
content: '';
margin-top: 0px;
border-bottom: 2px solid;
margin-bottom: 3px;
}
#screen-wrapper {
margin: 0 auto;
display: flex;
width: 75%; /* Container takes up full width */
max-width: 75%; /* Ensure it doesn't exceed the available width */
position: relative; /* Establishes the containing block for absolute positioning */
// background-color: lightgray; /* Optional: Just for visualization */
}
.ar-wrapper {
// padding-top: calc(122 / 250 * 100%); /* Aspect ratio: height / width * 100% */
// position: relative;
// width: 100%; /* Ensure the wrapper takes up full width */
padding-top: calc(122 / 250 * 100%); /* Aspect ratio: height / width * 100% */
position: relative;
width: 100%; /* Ensure the wrapper takes up full width */
}
.oc-screen {
position: absolute; /* Position content absolutely within the wrapper */
top: 0;
left: 0;
right: 0;
bottom: 0;
display: flex;
justify-content: center;
align-items: center;
text-align: center;
font-size: 16px;
color: black;
// border: 1px solid darkgray;
background: lightgrey;
// border-radius: 5px;
// padding: 10px;
// margin: 0 auto;
// display: flex;
flex-direction: column;
// flex-wrap: nowrap;
// justify-content: center;
// align-items: center;
// align-content: center;
font-family: 'Libre Franklin';
font-weight: 600;
.oc-row .icon {
display: inline-block;
font-weight: normal;
font-size: 90%;
}
.oc-row:nth-child(1) {
font-size: 1.5vw;
display: block;
flex-grow: 0;
flex-shrink: 1;
flex-basis: auto;
align-self: auto;
order: 0;
}
.oc-row:nth-child(2) {
font-size: 3vw;
display: block;
font-weight: bold;
flex-grow: 0;
flex-shrink: 1;
flex-basis: auto;
align-self: auto;
order: 0;
}
.oc-row:nth-child(3) {
font-size: 2vw;
display: block;
flex-grow: 0;
flex-shrink: 1;
flex-basis: auto;
align-self: auto;
order: 0;
}
}
#customText {
text-transform: uppercase;
}
.system_info {
padding: 0;
li {
list-style: none;
}
}
.card-title {
margin-bottom: 0;
}
.navbar-brand {
font-style: italic;
font-weight: 600;
}