diff --git a/app/Core/Konstanty.php b/app/Core/Konstanty.php index 8dbe568..d5f3c95 100644 --- a/app/Core/Konstanty.php +++ b/app/Core/Konstanty.php @@ -10,6 +10,6 @@ final class Konstanty * Verze aplikace. * @var string */ - public const verze = '1.1'; + public const verze = '1.2'; } \ No newline at end of file diff --git a/app/Presentation/@layout.latte b/app/Presentation/@layout.latte index f8ae3c6..6116ffd 100644 --- a/app/Presentation/@layout.latte +++ b/app/Presentation/@layout.latte @@ -3,6 +3,13 @@ + + + + + + + {* bootstrap: *} @@ -86,6 +93,11 @@ {block scripts} + {/block} diff --git a/www/.htaccess b/www/.htaccess index 199409c..f1a64be 100644 --- a/www/.htaccess +++ b/www/.htaccess @@ -35,6 +35,8 @@ Require all granted RewriteRule . index.php [L] +AddType application/manifest+json .webmanifest + # Enable gzip compression for text files AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css application/javascript application/json application/xml application/rss+xml image/svg+xml diff --git a/www/apple-touch-icon.png b/www/apple-touch-icon.png new file mode 100644 index 0000000..9e6a2d1 Binary files /dev/null and b/www/apple-touch-icon.png differ diff --git a/www/css/base.css b/www/css/base.css index ceda774..6fc1743 100644 --- a/www/css/base.css +++ b/www/css/base.css @@ -334,7 +334,7 @@ body:has(#map[data-max]) { border: 2px solid #1d4f91; background: #2652a8; color: #fff; - font-size: clamp(1.2rem, 4.6vw, 1.5rem); + font-size: clamp(1.6rem, 6vw, 2rem); font-weight: 800; line-height: 1; text-decoration: none; @@ -400,7 +400,7 @@ body:has(#map[data-max]) { } .home-obvod { - font-size: 1.4rem; + font-size: 1.9rem; } } @@ -529,12 +529,12 @@ body:has(#map[data-max]) { } .menu-znacka { - width: 2rem; - height: 2rem; - border-radius: 50%; - border: 2px solid #1d4f91; - background: #2652a8; + width: 2.15rem; + height: 2.15rem; + flex: 0 0 auto; + border-radius: 0.55rem; box-shadow: 0 3px 8px rgba(29, 79, 145, 0.28); + background: #2652a8 url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Crect width='512' height='512' rx='112' fill='%232652a8'/%3E%3Crect x='26' y='26' width='460' height='460' rx='96' fill='none' stroke='%231d4f91' stroke-width='18'/%3E%3Cg transform='translate(128 116) scale(10.7)' fill='none' stroke='%23fff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M18 8c0 3.613-3.869 7.429-5.393 8.795a1 1 0 0 1-1.214 0C9.87 15.429 6 11.613 6 8a6 6 0 0 1 12 0'/%3E%3Ccircle cx='12' cy='8' r='2'/%3E%3Cpath d='M8.714 14h-3.71a1 1 0 0 0-.948.683l-2.004 6A1 1 0 0 0 3 22h18a1 1 0 0 0 .948-1.316l-2-6a1 1 0 0 0-.949-.684h-3.712'/%3E%3C/g%3E%3C/svg%3E") center / cover no-repeat; } #menu .navbar-nav { @@ -1151,8 +1151,14 @@ body:has(#map[data-max]) { border-color: #78909c; } +html:has(.hranice-lista) { + height: 100%; + overflow: hidden; +} + body:has(.hranice-lista) { height: 100vh; + height: 100dvh; display: flex; flex-direction: column; overflow: hidden; @@ -1166,6 +1172,7 @@ body:has(.hranice-lista) #map { .hranice-lista { display: flex; + flex: 0 0 auto; flex-wrap: wrap; align-items: center; justify-content: space-between; @@ -1175,6 +1182,15 @@ body:has(.hranice-lista) #map { border-top: 1px solid #c5ddf6; } +/* Android často nahlásí safe-area-inset-bottom = 0, dokud se telefon neotočí. + Tlačítka pak skončí pod systémovou lištou. Na dotykovém displeji proto + necháme dole vždy aspoň místo na tu lištu. */ +@media (hover: none) and (pointer: coarse) { + .hranice-lista { + padding-bottom: max(3.5rem, calc(0.75rem + env(safe-area-inset-bottom))); + } +} + .hranice-napoveda { margin: 0; flex: 1 1 18rem; diff --git a/www/favicon.ico b/www/favicon.ico index b20cfd0..a6a01b8 100644 Binary files a/www/favicon.ico and b/www/favicon.ico differ diff --git a/www/icon-192.png b/www/icon-192.png new file mode 100644 index 0000000..d09c381 Binary files /dev/null and b/www/icon-192.png differ diff --git a/www/icon-512.png b/www/icon-512.png new file mode 100644 index 0000000..d0a9247 Binary files /dev/null and b/www/icon-512.png differ diff --git a/www/icons/icon-192.png b/www/icons/icon-192.png new file mode 100644 index 0000000..d09c381 Binary files /dev/null and b/www/icons/icon-192.png differ diff --git a/www/icons/icon-512.png b/www/icons/icon-512.png new file mode 100644 index 0000000..d0a9247 Binary files /dev/null and b/www/icons/icon-512.png differ diff --git a/www/icons/icon-maskable-192.png b/www/icons/icon-maskable-192.png new file mode 100644 index 0000000..1e54023 Binary files /dev/null and b/www/icons/icon-maskable-192.png differ diff --git a/www/icons/icon-maskable-512.png b/www/icons/icon-maskable-512.png new file mode 100644 index 0000000..9ddd8a9 Binary files /dev/null and b/www/icons/icon-maskable-512.png differ diff --git a/www/icons/obvody-maskable.svg b/www/icons/obvody-maskable.svg new file mode 100644 index 0000000..5cf2e19 --- /dev/null +++ b/www/icons/obvody-maskable.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/www/icons/obvody.svg b/www/icons/obvody.svg new file mode 100644 index 0000000..439d865 --- /dev/null +++ b/www/icons/obvody.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/www/js/hranice.js b/www/js/hranice.js index 82a544b..5ea465d 100644 --- a/www/js/hranice.js +++ b/www/js/hranice.js @@ -12,7 +12,32 @@ var obvodId = mapaEl.getAttribute('data-obvod'); var geojsonUrl = mapaEl.getAttribute('data-geojson'); var podklady = MapovePodklady.vytvor(); - var map = L.map(mapaEl, { + var map = null; + + // Na mobilu je 100vh vyšší než viditelná plocha, dokud se nezmění orientace. + function srovnejObrazovku() { + var vv = window.visualViewport; + var vyska = (vv && vv.height) ? vv.height : window.innerHeight; + var px = Math.round(vyska) + 'px'; + document.documentElement.style.height = px; + document.body.style.height = px; + if (map) { + map.invalidateSize({ pan: false }); + } + } + + srovnejObrazovku(); + window.addEventListener('resize', srovnejObrazovku); + window.addEventListener('orientationchange', function () { + window.setTimeout(srovnejObrazovku, 150); + }); + window.addEventListener('pageshow', srovnejObrazovku); + if (window.visualViewport) { + window.visualViewport.addEventListener('resize', srovnejObrazovku); + } + window.setTimeout(srovnejObrazovku, 300); + + map = L.map(mapaEl, { center: [50.853501146, 14.8425], zoom: 14, layers: [MapovePodklady.vychozi(podklady)], diff --git a/www/manifest.json b/www/manifest.json new file mode 100644 index 0000000..ca72038 --- /dev/null +++ b/www/manifest.json @@ -0,0 +1,22 @@ +{ + "short_name": "Obvody", + "name": "Obvody", + "icons": [ + { + "src": "/icon-192.png", + "type": "image/png", + "sizes": "192x192" + }, + { + "src": "/icon-512.png", + "type": "image/png", + "sizes": "512x512" + } + ], + "start_url": "/", + "background_color": "#e3f2fd", + "display": "standalone", + "scope": "/", + "theme_color": "#2652a8", + "lang": "cs" +} diff --git a/www/sw.js b/www/sw.js new file mode 100644 index 0000000..c7de747 --- /dev/null +++ b/www/sw.js @@ -0,0 +1,11 @@ +self.addEventListener('install', function () { + self.skipWaiting(); +}); + +self.addEventListener('activate', function (event) { + event.waitUntil(self.clients.claim()); +}); + +self.addEventListener('fetch', function (event) { + event.respondWith(fetch(event.request)); +});