version 1.0.0
This commit is contained in:
@@ -5,6 +5,8 @@ elle peut démarrer automatiquement la journée et proposer sa clôture. Chaque
|
|||||||
commence là où la précédente s’est terminée. Les journées clôturées ont un
|
commence là où la précédente s’est terminée. Les journées clôturées ont un
|
||||||
récapitulatif concis, prêt à être recopié dans un registre papier.
|
récapitulatif concis, prêt à être recopié dans un registre papier.
|
||||||
|
|
||||||
|
Version actuelle de l’application : **1.0.0**.
|
||||||
|
|
||||||
Conçue pour l’extérieur : contraste élevé, grandes zones tactiles et utilisable
|
Conçue pour l’extérieur : contraste élevé, grandes zones tactiles et utilisable
|
||||||
avec des gants. Les données sont enregistrées localement dans IndexedDB. Une
|
avec des gants. Les données sont enregistrées localement dans IndexedDB. Une
|
||||||
synchronisation facultative chiffrée de bout en bout les partage entre appareils
|
synchronisation facultative chiffrée de bout en bout les partage entre appareils
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ the app is open, it can start a workday automatically and prompt to close it. Ea
|
|||||||
task starts when the previous one ends. Closed days have concise summaries ready to
|
task starts when the previous one ends. Closed days have concise summaries ready to
|
||||||
copy into a paper logbook.
|
copy into a paper logbook.
|
||||||
|
|
||||||
|
Current application version: **1.0.0**.
|
||||||
|
|
||||||
Designed for outdoor use: high contrast, large touch targets, and usable with gloves.
|
Designed for outdoor use: high contrast, large touch targets, and usable with gloves.
|
||||||
Data is stored locally in IndexedDB. Optional end-to-end encrypted synchronization
|
Data is stored locally in IndexedDB. Optional end-to-end encrypted synchronization
|
||||||
shares it between authorized devices without requiring an email address or password.
|
shares it between authorized devices without requiring an email address or password.
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ http://{$SITE_ADDRESS} {
|
|||||||
# If a browser is allowed to serve sw.js from its own cache, a new build is
|
# If a browser is allowed to serve sw.js from its own cache, a new build is
|
||||||
# never discovered and the in-app update prompt can never fire — the app would
|
# never discovered and the in-app update prompt can never fire — the app would
|
||||||
# silently freeze on whatever version it first installed.
|
# silently freeze on whatever version it first installed.
|
||||||
@volatile path / /index.html /sw.js /manifest.webmanifest
|
@volatile path / /index.html /sw.js /manifest.webmanifest /app-version.json
|
||||||
header @volatile Cache-Control "no-cache, must-revalidate"
|
header @volatile Cache-Control "no-cache, must-revalidate"
|
||||||
|
|
||||||
# Content-hashed filenames; the name changes whenever the bytes do.
|
# Content-hashed filenames; the name changes whenever the bytes do.
|
||||||
|
|||||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "pardis",
|
"name": "pardis",
|
||||||
"version": "0.8.0",
|
"version": "1.0.0",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "pardis",
|
"name": "pardis",
|
||||||
"version": "0.8.0",
|
"version": "1.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@hpke/core": "^1.9.0",
|
"@hpke/core": "^1.9.0",
|
||||||
"@zxing/browser": "^0.2.1",
|
"@zxing/browser": "^0.2.1",
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "pardis",
|
"name": "pardis",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.8.0",
|
"version": "1.0.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
import { loadBackupStatus } from './lib/backup-state.svelte.js';
|
import { loadBackupStatus } from './lib/backup-state.svelte.js';
|
||||||
import { go, router } from './lib/router.svelte.js';
|
import { go, router } from './lib/router.svelte.js';
|
||||||
import { loadSettings, settings } from './lib/settings.svelte.js';
|
import { loadSettings, settings } from './lib/settings.svelte.js';
|
||||||
import { needsRefresh, applyUpdate } from './lib/updates.svelte.js';
|
import { needsRefresh, availableVersion, applyUpdate } from './lib/updates.svelte.js';
|
||||||
import Resume from './routes/Resume.svelte';
|
import Resume from './routes/Resume.svelte';
|
||||||
import Settings from './routes/Settings.svelte';
|
import Settings from './routes/Settings.svelte';
|
||||||
import Today from './routes/Today.svelte';
|
import Today from './routes/Today.svelte';
|
||||||
@@ -105,7 +105,7 @@
|
|||||||
<!-- Only offered while no day is running, so an update can never interrupt
|
<!-- Only offered while no day is running, so an update can never interrupt
|
||||||
a day in progress. -->
|
a day in progress. -->
|
||||||
<div class="update">
|
<div class="update">
|
||||||
<span>Mise à jour disponible</span>
|
<span>Mise à jour disponible{#if availableVersion.value} (v{availableVersion.value}){/if}</span>
|
||||||
<button type="button" disabled={dayState.importing} onclick={applyUpdate}>Installer</button>
|
<button type="button" disabled={dayState.importing} onclick={applyUpdate}>Installer</button>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
@@ -13,6 +13,19 @@ import { registerSW } from 'virtual:pwa-register';
|
|||||||
const CHECK_INTERVAL = 60 * 60 * 1000;
|
const CHECK_INTERVAL = 60 * 60 * 1000;
|
||||||
|
|
||||||
export const needsRefresh = $state({ value: false });
|
export const needsRefresh = $state({ value: false });
|
||||||
|
export const availableVersion = $state({ value: '' });
|
||||||
|
|
||||||
|
async function loadAvailableVersion() {
|
||||||
|
availableVersion.value = '';
|
||||||
|
try {
|
||||||
|
const response = await fetch('/app-version.json', { cache: 'no-store' });
|
||||||
|
if (!response.ok) return;
|
||||||
|
const result = await response.json();
|
||||||
|
if (typeof result.version === 'string') availableVersion.value = result.version;
|
||||||
|
} catch {
|
||||||
|
// The update prompt remains useful if a proxy briefly makes version data unavailable.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** @type {(reloadPage?: boolean) => Promise<void>} */
|
/** @type {(reloadPage?: boolean) => Promise<void>} */
|
||||||
let update = async () => {};
|
let update = async () => {};
|
||||||
@@ -22,6 +35,7 @@ if (typeof window !== 'undefined') {
|
|||||||
immediate: true,
|
immediate: true,
|
||||||
onNeedRefresh() {
|
onNeedRefresh() {
|
||||||
needsRefresh.value = true;
|
needsRefresh.value = true;
|
||||||
|
void loadAvailableVersion();
|
||||||
},
|
},
|
||||||
onRegisteredSW(_url, registration) {
|
onRegisteredSW(_url, registration) {
|
||||||
if (!registration) return;
|
if (!registration) return;
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
enregistre les journées, les tâches, les clients, les repas et les pauses,
|
enregistre les journées, les tâches, les clients, les repas et les pauses,
|
||||||
puis prépare un récapitulatif à consulter ou à copier.
|
puis prépare un récapitulatif à consulter ou à copier.
|
||||||
</p>
|
</p>
|
||||||
|
<p class="dim">Version 1.0.0</p>
|
||||||
<p>L'application, son code source, et le service de synchronisation sont fournis gratuitement et
|
<p>L'application, son code source, et le service de synchronisation sont fournis gratuitement et
|
||||||
sans aucune garantie.</p>
|
sans aucune garantie.</p>
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,21 @@
|
|||||||
|
import { readFileSync } from 'node:fs';
|
||||||
import { svelte } from '@sveltejs/vite-plugin-svelte';
|
import { svelte } from '@sveltejs/vite-plugin-svelte';
|
||||||
import { defineConfig } from 'vite';
|
import { defineConfig } from 'vite';
|
||||||
import { VitePWA } from 'vite-plugin-pwa';
|
import { VitePWA } from 'vite-plugin-pwa';
|
||||||
|
|
||||||
|
const { version: appVersion } = JSON.parse(readFileSync(new URL('./package.json', import.meta.url), 'utf8'));
|
||||||
|
|
||||||
|
const appVersionAsset = {
|
||||||
|
name: 'pardis-app-version',
|
||||||
|
generateBundle() {
|
||||||
|
this.emitFile({
|
||||||
|
type: 'asset',
|
||||||
|
fileName: 'app-version.json',
|
||||||
|
source: JSON.stringify({ version: appVersion }),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
server: {
|
server: {
|
||||||
host: '0.0.0.0',
|
host: '0.0.0.0',
|
||||||
@@ -9,6 +23,7 @@ export default defineConfig({
|
|||||||
},
|
},
|
||||||
preview: { proxy: { '/api/sync': 'http://127.0.0.1:3001' } },
|
preview: { proxy: { '/api/sync': 'http://127.0.0.1:3001' } },
|
||||||
plugins: [
|
plugins: [
|
||||||
|
appVersionAsset,
|
||||||
svelte(),
|
svelte(),
|
||||||
VitePWA({
|
VitePWA({
|
||||||
// Never `autoUpdate`: a worker swap mid-day reloads the page under the
|
// Never `autoUpdate`: a worker swap mid-day reloads the page under the
|
||||||
|
|||||||
Reference in New Issue
Block a user