Created base svelte app

This commit is contained in:
Samuel Ortion 2022-09-15 21:01:10 +02:00
parent f7b3629dd0
commit 3e30d3dafa
24 changed files with 7307 additions and 57 deletions

6
package-lock.json generated
View File

@ -1,6 +0,0 @@
{
"name": "openfoodfacts-client",
"lockfileVersion": 2,
"requires": true,
"packages": {}
}

View File

@ -1 +0,0 @@
{}

View File

@ -1,13 +1,19 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/off-logo.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>OpenFoodFacts Client</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/icons/off-logo.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="OpenFoodFacts web application. Learn more about the product you eat.">
<meta name="theme-color" content="orange">
<link rel="apple-touch-icon" sizes="180x180" href="/icons/apple-touch-icon.png" />
<title>OpenFoodFacts Client</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>

6909
www/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -15,7 +15,8 @@
"@sveltejs/vite-plugin-svelte": "^1.0.2",
"html5-qrcode": "^2.2.1",
"svelte": "^3.49.0",
"vite": "^3.1.0"
"vite": "^3.1.0",
"vite-plugin-pwa": "^0.12.7"
},
"dependencies": {
"axios": "^0.27.2"

View File

@ -0,0 +1,97 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="200"
height="200"
viewBox="0 0 200 200"
version="1.1"
id="svg2229"
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
sodipodi:docname="logo.svg"
inkscape:export-filename="../../icons/android-chrome-112x112.png"
inkscape:export-xdpi="53.759998"
inkscape:export-ydpi="53.759998"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview2231"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="1"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
showgrid="false"
inkscape:zoom="1.7117941"
inkscape:cx="68.641433"
inkscape:cy="109.24211"
inkscape:window-width="1920"
inkscape:window-height="1011"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" />
<defs
id="defs2226" />
<g
inkscape:label="Calque 1"
inkscape:groupmode="layer"
id="layer1">
<g
id="g2113"
transform="translate(-125.215,-69.1)">
<g
id="g2105">
<path
class="f"
d="m 176.13,171.7 c 0,-27.11 21.97,-49.08 49.08,-49.08 27.11,0 49.08,21.97 49.08,49.08 z"
id="path2095"
style="fill:#ff8c14" />
<path
class="e"
d="m 261.85,171.7 c 0,20.24 -16.4,36.64 -36.64,36.64 -20.24,0 -36.64,-16.4 -36.64,-36.64 z"
id="path2097"
style="fill:#ffffff" />
<circle
class="h"
cx="241.83"
cy="140"
r="2.7"
id="circle2099"
style="fill:#8c3c00" />
<circle
class="h"
cx="254.98"
cy="152.07001"
r="2.7"
id="circle2101"
style="fill:#8c3c00" />
<circle
class="h"
cx="240.11"
cy="155.02"
r="2.7"
id="circle2103"
style="fill:#8c3c00" />
</g>
<path
d="m 201.41,214.6 -8.72,20.82 11.48,4.81 8.8,-21 c 3.92,1.01 8.02,1.55 12.25,1.55 27.06,0 49.08,-22.02 49.08,-49.08 h -12.44 c 0,20.2 -16.44,36.64 -36.64,36.64 -20.2,0 -36.64,-16.44 -36.64,-36.64 h -12.44 c 0,18.43 10.22,34.51 25.28,42.9 z"
id="path2107" />
<path
class="c"
d="m 245.51,97.97 c -9.65,0 -18.04,5.38 -22.35,13.3 3.32,3.09 5.83,7.05 7.13,11.52 11.23,-2.52 19.66,-12.45 19.86,-24.39 -1.5,-0.28 -3.05,-0.43 -4.63,-0.43 z"
id="path2109"
style="fill:#00641e" />
<path
class="d"
d="m 205.84,104.44 c -1.91,0 -3.77,0.22 -5.56,0.62 3.07,10.61 12.85,18.37 24.45,18.37 1.91,0 3.77,-0.22 5.56,-0.62 -3.07,-10.61 -12.85,-18.37 -24.45,-18.37 z"
id="path2111"
style="fill:#00961e" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@ -1,9 +1,11 @@
<script>
import offLogo from './assets/off-logo.svg';
import BarcodeIcon from './assets/barcode.svg';
import OFF from './components/OFF.svelte';
import Scanner from './components/Scanner.svelte';
import Card from './components/Card.svelte';
import offLogo from './assets/icons/off-logo.svg';
import BarcodeIcon from './assets/icons/barcode.svg';
import svelteIcon from './assets/icons/svelte.svg';
import OFF from './lib/OFF.svelte';
import Scanner from './lib/Scanner.svelte';
import Card from './lib/Card.svelte';
import SW from './lib/SW.svelte';
import { onMount } from 'svelte';
@ -23,41 +25,65 @@
barcode = result;
showCard = true;
}
</script>
<main class="dark">
<div>
<a href="/">
<img src={offLogo} class="logo" alt="Open Food Facts Logo" />
</a>
</div>
<h1>OpenFoodFacts Client</h1>
<div class="content flex flex-col grow">
<header>
<div>
<a href="/">
<img src={offLogo} class="logo" alt="Open Food Facts Logo" />
</a>
</div>
<h1>OpenFoodFacts Client</h1>
</header>
<main class="placeholder">
<div id="card" />
<div id="card" />
<div class="reader">
{#if showScanner}
<Scanner onClose={stopScanner} onResult={scannerResult} />
{/if}
</div>
<div class="product">
{#if showCard}
<Card barcode={barcode} />
{/if}
</div>
<div class="reader">
{#if showScanner}
<Scanner onClose={stopScanner} onResult={scannerResult} />
{/if}
</div>
<div class="product">
{#if showCard}
<Card {barcode} />
{/if}
</div>
</main>
<nav class="menu bottom nav-bar">
<ul>
<li>
<button class="nav-item" title="Scan barcode" on:click={ () => showScanner = true }>
<img class="icon" src={BarcodeIcon} alt="Barcode icon" />
<button
class="nav-item"
title="Scan barcode"
on:click={() => (showScanner = true)}
>
<img class="monochrome icon" src={BarcodeIcon} alt="Barcode icon" />
</button>
</li>
</ul>
</nav>
</main>
</div>
<footer class="flex flex-row align-between">
<p>
<span class="copyleft">🄯</span>
2022 - <a href="https://samuel.ortion.fr/">Samulus.i.n</a>.
</p>
<p>
Made with &hearts; and
<a href="https://svelte.dev">
<img class="svelte icon" src={svelteIcon} alt="Svelte.js icon" />
</a>.
<a
href="https://forge.chapril.org/UncleSamulus/openfoodfacts-client/"
title="OpenFoodFacts Client source code">View source</a
>.
</p>
<p>
Based on data from <a href="https://openfoodfacts.org/">OpenFoodFacts</a>.
</p>
</footer>
<style>
.logo {
@ -81,7 +107,17 @@
list-style: none;
}
.icon {
filter: invert(1);
@media (prefers-color-scheme: dark) {
.monochrome {
filter: invert(1);
}
}
.svelte.icon {
height: 1em;
width: 1em;
}
.placeholder {
min-height: 25vh;
}
</style>

View File

@ -79,3 +79,30 @@ button:focus-visible {
background-color: #f9f9f9;
}
}
p {
padding: 0 1em;
}
.flex {
display: flex;
}
.flex-col {
flex-direction: column;
}
.flex-row {
flex-direction: row;
}
.grow {
flex-grow: 1;
}
#app {
min-height: 100vh;
display: flex;
flex-direction: column;
padding: 0;
}

View File

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -0,0 +1,97 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="200"
height="200"
viewBox="0 0 200 200"
version="1.1"
id="svg2229"
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
sodipodi:docname="logo.svg"
inkscape:export-filename="off-logo.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview2231"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="1"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
showgrid="false"
inkscape:zoom="1.7117941"
inkscape:cx="77.69626"
inkscape:cy="109.24211"
inkscape:window-width="1920"
inkscape:window-height="1011"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" />
<defs
id="defs2226" />
<g
inkscape:label="Calque 1"
inkscape:groupmode="layer"
id="layer1">
<g
id="g2113"
transform="translate(-125.215,-69.1)">
<g
id="g2105">
<path
class="f"
d="m 176.13,171.7 c 0,-27.11 21.97,-49.08 49.08,-49.08 27.11,0 49.08,21.97 49.08,49.08 z"
id="path2095"
style="fill:#ff8c14" />
<path
class="e"
d="m 261.85,171.7 c 0,20.24 -16.4,36.64 -36.64,36.64 -20.24,0 -36.64,-16.4 -36.64,-36.64 z"
id="path2097"
style="fill:#ffffff" />
<circle
class="h"
cx="241.83"
cy="140"
r="2.7"
id="circle2099"
style="fill:#8c3c00" />
<circle
class="h"
cx="254.98"
cy="152.07001"
r="2.7"
id="circle2101"
style="fill:#8c3c00" />
<circle
class="h"
cx="240.11"
cy="155.02"
r="2.7"
id="circle2103"
style="fill:#8c3c00" />
</g>
<path
d="m 201.41,214.6 -8.72,20.82 11.48,4.81 8.8,-21 c 3.92,1.01 8.02,1.55 12.25,1.55 27.06,0 49.08,-22.02 49.08,-49.08 h -12.44 c 0,20.2 -16.44,36.64 -36.64,36.64 -20.2,0 -36.64,-16.44 -36.64,-36.64 h -12.44 c 0,18.43 10.22,34.51 25.28,42.9 z"
id="path2107" />
<path
class="c"
d="m 245.51,97.97 c -9.65,0 -18.04,5.38 -22.35,13.3 3.32,3.09 5.83,7.05 7.13,11.52 11.23,-2.52 19.66,-12.45 19.86,-24.39 -1.5,-0.28 -3.05,-0.43 -4.63,-0.43 z"
id="path2109"
style="fill:#00641e" />
<path
class="d"
d="m 205.84,104.44 c -1.91,0 -3.77,0.22 -5.56,0.62 3.07,10.61 12.85,18.37 24.45,18.37 1.91,0 3.77,-0.22 5.56,-0.62 -3.07,-10.61 -12.85,-18.37 -24.45,-18.37 z"
id="path2111"
style="fill:#00961e" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 43 KiB

View File

Before

Width:  |  Height:  |  Size: 73 KiB

After

Width:  |  Height:  |  Size: 73 KiB

View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

View File

@ -9,6 +9,9 @@
id="svg2229"
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
sodipodi:docname="off-logo.svg"
inkscape:export-filename="off-logo.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
@ -19,16 +22,16 @@
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pageopacity="1"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
showgrid="false"
inkscape:zoom="1.7117941"
inkscape:cx="86.458998"
inkscape:cx="77.40417"
inkscape:cy="109.24211"
inkscape:window-width="1280"
inkscape:window-height="987"
inkscape:window-width="1920"
inkscape:window-height="1011"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="26.6" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 308"><path fill="#FF3E00" d="M239.682 40.707C211.113-.182 154.69-12.301 113.895 13.69L42.247 59.356a82.198 82.198 0 0 0-37.135 55.056a86.566 86.566 0 0 0 8.536 55.576a82.425 82.425 0 0 0-12.296 30.719a87.596 87.596 0 0 0 14.964 66.244c28.574 40.893 84.997 53.007 125.787 27.016l71.648-45.664a82.182 82.182 0 0 0 37.135-55.057a86.601 86.601 0 0 0-8.53-55.577a82.409 82.409 0 0 0 12.29-30.718a87.573 87.573 0 0 0-14.963-66.244"></path><path fill="#FFF" d="M106.889 270.841c-23.102 6.007-47.497-3.036-61.103-22.648a52.685 52.685 0 0 1-9.003-39.85a49.978 49.978 0 0 1 1.713-6.693l1.35-4.115l3.671 2.697a92.447 92.447 0 0 0 28.036 14.007l2.663.808l-.245 2.659a16.067 16.067 0 0 0 2.89 10.656a17.143 17.143 0 0 0 18.397 6.828a15.786 15.786 0 0 0 4.403-1.935l71.67-45.672a14.922 14.922 0 0 0 6.734-9.977a15.923 15.923 0 0 0-2.713-12.011a17.156 17.156 0 0 0-18.404-6.832a15.78 15.78 0 0 0-4.396 1.933l-27.35 17.434a52.298 52.298 0 0 1-14.553 6.391c-23.101 6.007-47.497-3.036-61.101-22.649a52.681 52.681 0 0 1-9.004-39.849a49.428 49.428 0 0 1 22.34-33.114l71.664-45.677a52.218 52.218 0 0 1 14.563-6.398c23.101-6.007 47.497 3.036 61.101 22.648a52.685 52.685 0 0 1 9.004 39.85a50.559 50.559 0 0 1-1.713 6.692l-1.35 4.116l-3.67-2.693a92.373 92.373 0 0 0-28.037-14.013l-2.664-.809l.246-2.658a16.099 16.099 0 0 0-2.89-10.656a17.143 17.143 0 0 0-18.398-6.828a15.786 15.786 0 0 0-4.402 1.935l-71.67 45.674a14.898 14.898 0 0 0-6.73 9.975a15.9 15.9 0 0 0 2.709 12.012a17.156 17.156 0 0 0 18.404 6.832a15.841 15.841 0 0 0 4.402-1.935l27.345-17.427a52.147 52.147 0 0 1 14.552-6.397c23.101-6.006 47.497 3.037 61.102 22.65a52.681 52.681 0 0 1 9.003 39.848a49.453 49.453 0 0 1-22.34 33.12l-71.664 45.673a52.218 52.218 0 0 1-14.563 6.398"></path></svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

47
www/src/lib/SW.svelte Normal file
View File

@ -0,0 +1,47 @@
<script>
import {useRegisterSW} from 'virtual:pwa-register/svelte';
import { slide } from 'svelte/transition';
const {offlineReady, needRefresh, updateServiceWorker} = useRegisterSW({
onRegistered(swr) {
console.log(`SW registered: ${swr}`);
},
onRegisterError(error) {
console.log('SW registration error', error);
},
onOfflineReady() {
console.log('SW ready for offline')
setTimeout(() => close(), 5000)
}
});
function close() {
offlineReady.set(false)
needRefresh.set(false)
}
$: toast = $offlineReady || $needRefresh;
</script>
{#if toast}
<div class="fixed right-0 bottom-0 m-4 p-6 rounded shadow z-[100] bg-white border-blue-500 border max-w-sm" in:slide out:slide
role="alert">
<div class="mb-4">
<span>&#127881;</span>
{#if $offlineReady}
<span>
This site is ready to use offline.
</span>
{:else}
<span>
A new version of this site is available! Click the reload button to update.
</span>
{/if}
</div>
{#if $needRefresh}
<button class="button m-0" on:click={() => updateServiceWorker(true)}>
Reload
</button>
{/if}
<button class="button m-0" on:click={close}>
Close
</button>
</div>
{/if}

View File

@ -21,7 +21,12 @@
},
onScanSuccess,
onScanFailure
);
).catch((err) => {
console.debug("Could not start the scanner");
console.error(err);
onClose();
return;
});
scanning = true;
}

View File

@ -1,7 +1,37 @@
import { defineConfig } from 'vite'
import { svelte } from '@sveltejs/vite-plugin-svelte'
import { VitePWA } from 'vite-plugin-pwa'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [svelte()]
plugins: [
svelte(),
VitePWA({
registerType: 'autoUpdate',
includeAssets: ['icons/*.png', 'assets/*.svg'],
manifest: {
name: 'Open Food Facts Client',
short_name: 'OFF-Client',
description: 'Scan food barcode, and learn infos about the product. Make a better choice during your shopping.',
theme_color: 'orange',
display: 'standalone',
start_url: '/',
strategies: 'injectManifest',
icons: [
{
src: '/icons/android-chrome-192x192.png',
sizes: '192x192',
type: 'image/png',
purpose: 'any maskable'
},
{
src: '/icons/android-chrome-512x512.png',
sizes: '512x512',
type: 'image/png',
purpose: 'any maskable'
}
]
}
})
]
})