Nová verze Portálu občana už nezpůsobuje okamžité doručení datových zpráv

4. 12. 2023
Doba čtení: 15 minut

Sdílet

Notifikace od portálu o nově dodaných datových zprávách, stejně jako jejich automatická archivace, už nezpůsobují jejich okamžité doručení. Zvláště archivace tak získává na užitečnosti. Ještě je ale třeba odstranit některé nově vyvolané dětské nemoci.

Jak jste si již mohli sami všimnout (či nedávno přečíst zde na Lupě či v tiskové zprávě DIA), Portál občana prošel velkým redesignem svého uživatelského rozhraní. Zda je to změna k lepšímu, či k horšímu, nechám na vašem posouzení – v tomto článku bych se rád věnoval změnám ve fungování Portálu, které se mi podařilo detekovat. Týkají se hlavně, ale nikoli výlučně, propojení portálu s datovými schránkami.

Zde je nejprve stručný výčet změn, které by měly být trvalé:

  • zapnuté notifikace o datových zprávách, dodaných do datové schránky, již nezpůsobují jejich prakticky okamžité doručení, jako tomu bylo až dosud. Nová verze Portálu občana tak konečně začala využívat možnost, kterou datové schránky inzerovaly již delší dobu
  • také automatická archivace datových zpráv v připojených datových schránkách již nezpůsobuje jejich doručení. Nově k ní nedochází ihned s dodáním datové zprávy, ale až 3 týdny poté, co je zpráva systémem považována za doručenou
  • byl zrušen dashboard s možností připojování konkrétních dlaždic, náhradou lze využít vyhledávání a zařazení konkrétních služeb mezi oblíbené
  • nově je dostupné vyhledávání jak v rámci samotného portálu (např. pro nalezení konkrétní služby), tak i v rámci metadat datových zpráv
  • byl zrušen obecný kalendář s možností vkládání vlastních událostí
  • dosavadní verze portálu u jednotlivých datových zpráv ukazovala primárně datum a čas jejich doručení. Nově ukazuje čas jejich dodání. Čas (domnělého) doručení se ukáže až na rozkliknutí
  • byla zrušena možnost seskupování datových zpráv do konverzací
  • vydána byla nová uživatelská příručka

Kromě toho došlo k dalším změnám, které jsou ale spíše chybami, resp. dětskými nemocemi, a podle vyjádření agentury DIA by měly být odstraněny. Jde zejména o to, že:

  • některé úkony trvají extrémně dlouho. Například na stažení souboru v příloze datové zprávy si počkáte celou minutu (spíše ale ještě dříve dojdete k závěru, že „to zatuhlo“). Ještě horší je to u antivirové kontroly přílohy, přidávané k nově vytvářené datové zprávě, ta trvá dokonce déle než dvě celé minuty
  • archivované datové zprávy se nedají stáhnout. Dá se s nimi pracovat, tedy číst jejich obsah a stahovat přílohy (což trvá onu celou minutu a něco navíc), ale nedají se stáhnout jako celek (jako ZFO). Prý ale nejde o záměr, nýbrž o nedopatření, které by mělo být napraveno
  • do nově vytvářených datových zpráv není možné přidávat přílohy s formáty pro externí elektronické podpisy, pečeti a časová razítka (např. cer, crt, p7s atd.), které nejsou uvedeny v příslušné vyhlášce, ale jako přípustné je zmiňuje stanovisko MV ČR a Provozní řád ISDS. I toto by mělo být v řešení.

A možná ještě několik poznámek k tomu, co se s redesignem nezměnilo:

  • připojit k portálu lze více datových schránek: všechny vlastní datové schránky FO a PFO („vlastní“ ve smyslu držitele). Dále DS PO, pokud je v nich uživatel oprávněnou osobou. Mezi připojenými datovými schránkami se lze jednoduše a rychle přepínat. Notifikace a archivaci datových zpráv v jednotlivých připojených schránkách lze nastavovat individuálně.
  • archivace datových zpráv, stejně jako jednotlivých dokumentů (souborů) funguje nadále jen jako prosté úložiště (tj. nedělá nic pro udržování digitální kontinuity)
  • při vkládání certifikátů do základního registru obyvatel se stále nijak nekontroluje, komu certifikát patří. Takže do svého účtu můžete vložit i cizí kvalifikovaný certifikát.

Pro hodnocení změn designu si dovolím připojit ještě dva obrázky: na prvním vidíte původní design z doby spuštění Portálu občana (v polovině roku 2018, podrobněji zde) a na druhém jeho aktuální podobu. V obou případech s velkou, střední a nejmenší šířkou responzivního designu.

Autor: Jiří Peterka

Již na první pohled je patrný rozdíl v zobrazování obsahu datové schránky hned na úvodní stránce: zatímco dříve jste ihned viděli i několik starších datových zpráv (včetně již přečtených), nově vidíte jen ty, které jste dosud nečetli. Což jsou nejčastěji ty, jejichž doručení jste svým přihlášením do Portálu občana právě způsobili. Ale nemusí tomu tak být, mohly být doručeny již dříve (např. fikcí či vaším přihlášením do klientského portálu datových schránek). Jen jste si je dosud neotevřeli, takže jsou považovány za nepřečtené. Pro zobrazení již přečtených datových zpráv již musíte přejít do svých datových schránek. Ty jsou mimochodem všude označovány familiárněji jako „datovky“, a nikoli již jako datové schránky.

Autor: Jiří Peterka

Srovnání obou obrázků ukazuje i náhradu původního dashboardu s dlaždicemi novou možností zařadit konkrétní položky nabídky mezi oblíbené. Rozdíl je v tom, že nově si pořadí jejich zobrazování určuje portál sám. A při novém přihlášení vám vždy ukáže nabídku „Vše“, takže do nabídky „Oblíbené“ musíte pokaždé přejít sami.

Pojďme nyní k některým dalším změnám podrobněji.

Propojení s datovými schránkami

Významná změna, ke které došlo souběžně se změnou designu Portálu občana, je ve způsobu propojení tohoto portálu s datovými schránkami. To stále zůstává založeno na principu, že Portál občana se chová vůči datovým schránkám jako externí aplikace, která se pravidelně přihlašuje k vaší datové schránce a může s ní pracovat. To jí stále musíte odsouhlasit, v rámci připojování („přidávání“) své datové schránky k portálu.

Autor: Jiří Peterka

Následně bude aplikace Portálu občana uvedena mezi „jinými externími aplikacemi“, které mají přístup do vaší datové schránky. Poznáte ji „snadno“, prezentuje se jako datová schránka yukd8p7, která patří agentuře DIA.

Autor: Jiří Peterka

Důležitý je ale způsob fungování tohoto propojení. Až dosud to bylo tak, že každé přihlášení aplikace portálu způsobovalo doručení všech dosud nedoručených datových zpráv ve vaší datové schránce. 

A jelikož k takovémuto přihlášení docházelo pravidelně, v relativně krátkých intervalech, mělo to velmi významný důsledek: pokud jste toto propojení využívali, Portál občana způsoboval automatické doručení každé datové zprávy dodané do vaší datové schránky. A to prakticky okamžitě (plus minus onen krátký interval). Nikoli fikcí doručení, ale z pohledu systémových událostí a jejich záznamu (např. v doručenkách) přihlášením oprávněné osoby. Takže ani z doručenky se nedalo poznat, zda jste se skutečně přihlásili vy, nebo aplikace Portálu občana. 

Popisované propojení bylo ze strany Portálu občana využíváno ke třem účelům, resp. službám pro uživatele portálu:

  • pro notifikace (e-mailem či SMS) o datových zprávách, nově dodaných do datové schránky,
  • pro automatickou archivaci datové zprávy (její stažení do úložiště na Portálu občana)
  • pro přeposlání celé datové zprávy (včetně obsahu) na e-mail (podrobněji)

Pro druhou a třetí z právě uvedených služeb je nutné získat celou datovou zprávu, což následně umožňuje seznámení s jejím obsahem, takže efektu doručení (pokud k němu ještě nedošlo) se zde nedá dost dobře vyhnout. Ale u notifikací nikoli: pouhé oznámení o tom, že vám byla nějaká datová zpráva dodána do vaší datové schránky, ještě nemusí způsobovat její doručení. Mimochodem, obdobná notifikace, ale zasílaná přímo od systému datových schránek, doručení nikdy nezpůsobovala.

Pravdou je, že pokud si v dosavadní verzi portálu někdo chtěl zapnout ony notifikace, byl na popisovaný efekt okamžitého doručení důrazně upozorněn a musel jej odsouhlasit.

Autor: Jiří Peterka

Na druhou stranu: jaký měla takováto služba (notifikace od Portálu občana) smysl, když existovala její alternativa (notifikace přímo od datových schránek), která popisovaný problém s efektem doručení nemá?

Nehledě na to, že v rámci nápovědy k datovým schránkám již docela dlouho visí text, který vyznívá tak, že Portál občana svými notifikacemi doručení nezpůsobuje. A toto vyznění je umocněno konstatováním, že je zbytečné si zapínat notifikace přímo od datových schránek.

Autor: Jiří Peterka

Nicméně při důkladnějším čtení je možné dojít k závěru, že popisována je pouze možnost (nezpůsobovat doručení), a nikoli to, že Portál občana tuto možnost již skutečně využívá. A on ji dosud skutečně nevyužíval – a začal s tím až nyní, po svém redesignu.

Jak nyní fungují notifikace od Portálu občana?

Nově tedy notifikace od Portálu občana doručení datové zprávy nezpůsobují. A že to tak v praxi skutečně funguje, ukazuje příklad datové zprávy na následujícím obrázku. Je na něm datová zpráva dodaná do datové schránky ve čtvrtek 30. listopadu 2023 ve 20.35. Notifikace přímo od datových schránek (na obrázku nejníže) přišla e-mailem o minutu později, od Portálu občana o deset minut později. K doručení (a to skutečným přihlášením oprávněné osoby) došlo až o den později, a to 1. prosince 2023.

Autor: Jiří Peterka

Má tedy nyní smysl dát na výše citovanou nápovědu samotných datových schránek, na ono „Z logiky věci vyplývá, že v tomto nastavení je zbytečné zapínat notifikace v ISDS“, a raději využívat notifikace od Portálu občana? Když už nově nezpůsobují doručení?

Alespoň podle mého názoru ještě ne: notifikace přímo od ISDS jsou přeci jen obsažnější. Najdete v nich např. identifikátor datové zprávy i to, že jde o zprávu určenou do vlastních rukou, což v notifikaci od Portálu občana nenajdete. Notifikace přímo od systému datových schránek obsahuje také poučení pro příjemce, je opatřena (pouze) uznávanou elektronickou pečetí systému datových schránek a neklame uživatele tvrzením, že již došlo k doručení datové zprávy (jako to dělá notifikace od Portálu občana).

Datum a čas dodání, místo doručení

Na předchozím obrázku si můžete všimnout ještě jedné zajímavé věci: že Portál občana primárně zobrazuje čas dodání datové zprávy do datové schránky (v zeleném rámečku) místo času doručení (v červeném rámečku). Tedy času, ke kterému si systém datových schránek myslí, že bylo doručeno.

Když byl Portál občana v roce 2018 spuštěn, bylo tomu stejně, ale později přešel na zobrazování data a času doručení. No a nyní se tedy znovu vrací k zobrazování data a času dodání. Chcete-li se dostat k údaji o doručení, musíte se k němu proklikat: v přehledech zpráv jsou jen data jejich dodání, a tak si musíte nejprve zobrazit samotnou zprávu a v ní si pak rozkliknout nabídku „Více informací“ (na předchozím obrázku je již rozkliknuta, viz „Méně informací“ v modrém rámečku).

Srovnání předchozího a nynějšího stavu na jedné a téže datové zprávě ukazuje následující obrázek (zeleně je opět vyznačeno dodání, červeně doručení).

Autor: Jiří Peterka

Podle vyjádření DIA je to záměr:

Stejně jako e-mailoví klienti i my primárně zobrazujeme informaci o tom, kdy datová zpráva uživateli do datové schránky přišla, tedy čas dodání. Informace o času doručení je uživatelům nadále dostupná při zobrazení datové zprávy po kliknutí na Více informací. Jelikož víme, že tyto dva pojmy jsou pro občany hůře pochopitelné, přidali jsme k nim vysvětlivky, aby byly jasnější.

Můj názor na volbu mezi dodáním a doručením je jiný. Prezentované datum a čas doručení je sice „názorem stroje“, který se nemusí shodovat s výsledkem právního posouzení toho, zda a kdy došlo k řádnému a platnému doručení. Například kvůli problému doručování do nesprávné datové schránky, což „stroj“ nedokáže posoudit.

Nicméně v případě datových schránek fyzických a právnických osob, o které zde jde, je pro začátek nejrůznějších dob a lhůt (obvykle na reakci, splnění nějaké povinnosti, možnosti odvolat se atd.) rozhodující právě okamžik doručení, a nikoli okamžik dodání. Ten by byl rozhodující v případě datových schránek OVM, ale o ty se zde nejedná.

Co se (ne)dozvíte od kterého portálu?

Připomeňme si v této souvislosti, že to, co se o datových zprávách dozvíte na Portálu občana, je výrazně omezeno oproti tomu, co se o nich dozvíte přímo v datových schránkách, resp. na jejich klientském portálu. Například doručenky na Portálu občana vůbec nenajdete. Nedozvíte se ani to, kdo vám datovou zprávu poslal – ale jen to, ze které datové schránky vám ji poslal. 

To na klientském portálu se standardně dozvíte alespoň to, v jaké roli vystupoval ten, kdo vám datovou zprávu z oné datové schránky poslal. Zda se jednalo o některou oprávněnou osobu, pověřenou osobu, administrátora, či spisovou aplikaci. A pokud se odesílající osoba rozhodla vystoupit z anonymity a povolila připojení údajů o své identitě k odesílané zprávě, uvidíte je pouze v klientském portálu datových schránek, ale v Portálu občana opět nikoli. Tam se dozvíte pouze to, ze které datové schránky vám něco přišlo, a kdo je držitelem této schránky. Nic víc.

Na následujícím obrázku vidíte příklad datové zprávy, kterou z odesílající datové schránky odeslala pověřená osoba. Tedy někdo jiný než držitel, resp. zde držitelka této schránky. V horní části obrázku je pohled na datovou zprávu z klientského portálu datových schránek, ve kterém je kromě držitelky datové schránky (červeně) vždy vidět i role odesílající osoby (zeleně). A zde konkrétně jsou vidět také údaje o konkrétní pověřené osobě, které odesílající osoba nechala (dobrovolně) připojit k odesílané datové zprávě. Je zde také uveden čas doručení (podtrženo černě).

Autor: Jiří Peterka

Ve spodní části obrázku je stejná zpráva pohledem Portálu občana. Pokud si rozkliknete údaj v kolonce „odesilatel“, dozvíte se jen to, kdo je držitelkou datové schránky, ze které byla zpráva odeslána. Ale nedozvíte se nic o tom, kdo ji odeslal. Ani zda to byla oprávněná osoba (což by zde byla držitelka), či některá pověřená osoba, případně administrátor. A principiálně vyloučena není ani elektronická aplikace. Navíc je vám zde primárně prezentován čas dodání datové zprávy (nikoli jejího doručení).  

Neměli bychom tedy zapomínat na to, že systém datových schránek je skutečně tím, co o sobě sám říká: systémem datových schránek, resp. systémem pro přenos datových zpráv mezi datovými schránkami. Nikoli systémem pro přenos datových zpráv mezi osobami. Takže odesilatelem i adresátem jsou z jeho pohledu vždy datové schránky. Nikoli konkrétní uživatelé, které systém datových schránek na odesílající straně označuje jako odesílající osoby a na straně příjmu to jsou pro něj jen blíže neurčené osoby, které svým přihlášením způsobily doručení. Skrze klientský portál a z doručenek se standardně dozvíte jen role odesílajících osob a osob, které způsobily doručení (a konkrétní identitu odesílajících osob jen tehdy, pokud si to tyto osoby explicitně vyžádaly). To skrze Portál občana se o nich nedozvíte nic.

Automatická archivace datových zpráv v novém

Vraťme se ale ještě k důsledkům změn toho, jak funguje propojení mezi Portálem občana a samotnými datovými schránkami. Tyto změny totiž umožnily napravit i to, jak na portálu dosud fungovala automatická archivace datových zpráv. Nikoli ta „ruční“, kdy si uživatel sám řekl, kdy a které své datové zprávy chce stáhnout do té části úložiště na Portálu občana (aktuálně o velikosti 1 GB), která je určena pro datové zprávy. Tam problém nebyl, jednalo se o již doručené datové zprávy.

Problém byl u té varianty archivace, v rámci které portál stahoval do úložiště všechny nové datové zprávy ihned – a to v okamžiku, kdy se o jejich existenci sám dozvěděl (oním pravidelným přihlašováním). A sám také způsobil jejich doručení.

Proto také byl uživatel dříve při zapnutí automatické archivace důrazně varován a musel odsouhlasit, že to způsobí doručení. Viz následující obrázek.

Autor: Jiří Peterka

Nově už je tomu jinak a k automatické archivaci by mělo docházet až tři týdny po doručení datové zprávy.

Autor: Jiří Peterka

Zda to tak v praxi skutečně funguje, zjistím až za ony tři týdny. Nicméně „ruční“ archivace funguje stejně jako doposud, způsobem, který jsem popisoval zde na Lupě v seriálu o digitální kontinuitě. Tedy tak, že v okamžiku archivace (technicky stažení) datové zprávy do úložiště/archivu dochází k připojení pečeti a druhého (výstupního) časového razítka. To pak zůstává beze změny, stejně jako celá datová zpráva.

Což znamená, že v okamžiku následného stahování datové zprávy z archivu je na ní původní pečeť a (výstupní) časové razítko, připojené v době stahování zprávy do archivu. Nikoli „čerstvá“ pečeť a aktuální časové razítko, jako je tomu při stahování zprávy z placeného datového trezoru přímo v datových schránkách.

Nicméně i přesto, že Portál občana nedělá nic pro udržení digitální kontinuity, má nyní – alespoň podle mého názoru – smysl automatickou archivaci využívat. Když pro nic jiného, tak kvůli tomu, abyste se k obsahu svých starších datových zpráv dostali vy sami. Digitální kontinuitu potřebujete k tomu, abyste své starší datové zprávy, resp. jejich obsah, mohli předkládat někomu jinému a ten je nemohl odmítat kvůli jejich „zestárnutí“ (nemožnosti spoléhat se na ně, když už se nedá ověřit platnost jejich podpisů a/nebo pečetí).

Ještě si dodejme, že k okamžitému doručení nadále dochází v případě, kdy si uživatel vyžádá přeposílání celých datových zpráv (tj. včetně jejich obsahu) na svůj e-mail. Zde to ani jinak nejde. A na důsledky je uživatel i nadále upozorňován a musí je odsouhlasit.

Autor: Jiří Peterka

Zapomněli na tlačítko?

S archivem datových zpráv na nové verzi Portálu občana je (snad jen prozatím) spojena jedna kuriózní věc: lze je do tohoto archivu vkládat, ale už ne stahovat. Tedy ne celé datové zprávy (jako soubory ve formátu ZFO). Dá se číst obsah datové zprávy a jdou stahovat její přílohy – ale nikoli celá datová zpráva jako taková.

A ještě přesněji: nedá se stáhnout z nového webového rozhraní Portálu občana. Dá se stále stáhnout pomocí aktuální verze mobilní aplikace Gov.cz.

Nejprve mě napadlo, zda nejde o záměr, který by mohl souviset právě s (neřešeným) problémem digitální kontinuity. Ale podle vyjádření agentury DIA to záměr není:

Zde se jedná o nedopatření, za které se omlouváme. Aktuálně pracujeme na tom, aby v archivovaných datových zprávách byla možnost stažení zprávy ve formátu ZFO doplněna jako v původním designu Portálu občana. Pokud by ovšem uživatel nyní potřeboval z Portálu občana jeho archivovanou datovou zprávu ve formátu ZFO, může nadále přistupovat do Portálu občana i prostřednictvím mobilní aplikace Gov.cz, kde ještě re-design nebyl implementován, a zde archivovanou datovou zprávu ve formátu ZFO stáhnout.

Tak doufejme, že se již brzy podaří obnovit původní funkčnost.

Další změny ještě přijdou

Popisované změny na Portálu občana určitě nejsou poslední. Již brzy, a to s přelomem letošního a nového roku, bychom se měli dočkat předvoje unijní peněženky digitální identity (EU Digital Identity Wallet) v podobě našich národních (a proprietárních) eDokladů. No a jejich „obsluha“ ze strany držitelů dokladů by měla být řešena právě prostřednictvím Portálu občana, se kterým bude mobilní aplikace pro eDoklady propojena. Takže Portál občana bude muset získat k tomu potřebné nové funkce.

Tisková zpráva agentury DIA, vydaná u příležitosti redesignu, zmiňuje ještě další plánované přírůstky:

WT100_25_SE

Další novinky budou zahrnovat např. upozornění na změnu bodového konta řidiče, online registraci do systému DROZD, výpis z evidence občanských průkazů a cestovních pasů nebo možnost odesílat velké datové zprávy o velikosti až 100 MB.

Snad se to vše stihne včas, protože přelom roku se rychle blíží. Ostatně, nová verze mobilní aplikace Gov.cz, která byla ještě na nedávné konferenci „Navigace světem digitalizace“ slibována na prosinec, bude mít (podle aktuálních informací z DIA) zpoždění. A bude přejmenována:

kompletní re-design mobilní aplikace Gov.cz byl posunut z druhé poloviny prosince na leden 2024 s novým názvem Portál občana

Ostatně, proč vydávat v prosinci novou verzi mobilní aplikace a v lednu ji nahradit ještě novější verzí, která by již podporovala obsluhu eDokladů? 

  • Chcete mít Lupu bez bannerů?
  • Chcete dostávat speciální týdenní newsletter o zákulisí českého internetu?
  • Chcete mít k dispozici strojové přepisy podcastů?
  • Chcete získat slevu 1 000 Kč na jednu z našich konferencí?

Staňte se naším podporovatelem

Autor článku

Autor byl dlouho nezávislým konzultantem a publicistou, 10 let byl členem Rady ČTÚ. 35 let působil také jako pedagog na MFF UK v Praze.

'; document.getElementById('preroll-iframe').onload = function () { setupIframe(); } prerollContainer = document.getElementsByClassName('preroll-container-iframe')[0]; } function setupIframe() { prerollDocument = document.getElementById('preroll-iframe').contentWindow.document; let el = prerollDocument.createElement('style'); prerollDocument.head.appendChild(el); el.innerText = "#adContainer>div:nth-of-type(1),#adContainer>div:nth-of-type(1) > iframe { width: 99% !important;height: 99% !important;max-width: 100%;}#videoContent,body{ width:100vw;height:100vh}body{ font-family:'Helvetica Neue',Arial,sans-serif}#videoContent{ overflow:hidden;background:#000}#adMuteBtn{ width:35px;height:35px;border:0;background:0 0;display:none;position:absolute;fill:rgba(230,230,230,1);bottom:20px;right:25px}"; videoContent = prerollDocument.getElementById('contentElement'); videoContent.style.display = 'none'; videoContent.volume = 1; videoContent.muted = false; const playPromise = videoContent.play(); if (playPromise !== undefined) { playPromise.then(function () { console.log('PREROLL sound allowed'); // setUpIMA(true); videoContent.volume = 1; videoContent.muted = false; setUpIMA(); }).catch(function () { console.log('PREROLL sound forbidden'); videoContent.volume = 0; videoContent.muted = true; setUpIMA(); }); } } function setupDimensions() { prerollWidth = Math.min(iinfoPrerollPosition.offsetWidth, 480); prerollHeight = Math.min(iinfoPrerollPosition.offsetHeight, 320); } function setUpIMA() { google.ima.settings.setDisableCustomPlaybackForIOS10Plus(true); google.ima.settings.setLocale('cs'); google.ima.settings.setNumRedirects(10); // Create the ad display container. createAdDisplayContainer(); // Create ads loader. adsLoader = new google.ima.AdsLoader(adDisplayContainer); // Listen and respond to ads loaded and error events. adsLoader.addEventListener( google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, onAdsManagerLoaded, false); adsLoader.addEventListener( google.ima.AdErrorEvent.Type.AD_ERROR, onAdError, false); // An event listener to tell the SDK that our content video // is completed so the SDK can play any post-roll ads. const contentEndedListener = function () { adsLoader.contentComplete(); }; videoContent.onended = contentEndedListener; // Request video ads. const adsRequest = new google.ima.AdsRequest(); adsRequest.adTagUrl = iinfoVastUrls[iinfoVastUrlIndex]; console.log('Preroll advert: ' + iinfoVastUrls[iinfoVastUrlIndex]); videoContent.muted = false; videoContent.volume = 1; // Specify the linear and nonlinear slot sizes. This helps the SDK to // select the correct creative if multiple are returned. // adsRequest.linearAdSlotWidth = prerollWidth; // adsRequest.linearAdSlotHeight = prerollHeight; adsRequest.nonLinearAdSlotWidth = 0; adsRequest.nonLinearAdSlotHeight = 0; adsLoader.requestAds(adsRequest); } function createAdDisplayContainer() { // We assume the adContainer is the DOM id of the element that will house // the ads. prerollDocument.getElementById('videoContent').style.display = 'none'; adDisplayContainer = new google.ima.AdDisplayContainer( prerollDocument.getElementById('adContainer'), videoContent); } function unmutePrerollAdvert() { adVolume = !adVolume; if (adVolume) { adsManager.setVolume(0.3); prerollDocument.getElementById('adMuteBtn').innerHTML = ''; } else { adsManager.setVolume(0); prerollDocument.getElementById('adMuteBtn').innerHTML = ''; } } function onAdsManagerLoaded(adsManagerLoadedEvent) { // Get the ads manager. const adsRenderingSettings = new google.ima.AdsRenderingSettings(); adsRenderingSettings.restoreCustomPlaybackStateOnAdBreakComplete = true; adsRenderingSettings.loadVideoTimeout = 12000; // videoContent should be set to the content video element. adsManager = adsManagerLoadedEvent.getAdsManager(videoContent, adsRenderingSettings); // Add listeners to the required events. adsManager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, onAdError); adsManager.addEventListener( google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED, onContentPauseRequested); adsManager.addEventListener( google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED, onContentResumeRequested); adsManager.addEventListener( google.ima.AdEvent.Type.ALL_ADS_COMPLETED, onAdEvent); // Listen to any additional events, if necessary. adsManager.addEventListener(google.ima.AdEvent.Type.LOADED, onAdEvent); adsManager.addEventListener(google.ima.AdEvent.Type.STARTED, onAdEvent); adsManager.addEventListener(google.ima.AdEvent.Type.COMPLETE, onAdEvent); playAds(); } function playAds() { // Initialize the container. Must be done through a user action on mobile // devices. videoContent.load(); adDisplayContainer.initialize(); // setupDimensions(); try { // Initialize the ads manager. Ad rules playlist will start at this time. adsManager.init(1920, 1080, google.ima.ViewMode.NORMAL); // Call play to start showing the ad. Single video and overlay ads will // start at this time; the call will be ignored for ad rules. adsManager.start(); // window.addEventListener('resize', function (event) { // if (adsManager) { // setupDimensions(); // adsManager.resize(prerollWidth, prerollHeight, google.ima.ViewMode.NORMAL); // } // }); } catch (adError) { // An error may be thrown if there was a problem with the VAST response. // videoContent.play(); } } function onAdEvent(adEvent) { const ad = adEvent.getAd(); console.log('Preroll event: ' + adEvent.type); switch (adEvent.type) { case google.ima.AdEvent.Type.LOADED: if (!ad.isLinear()) { videoContent.play(); } prerollDocument.getElementById('adContainer').style.width = '100%'; prerollDocument.getElementById('adContainer').style.maxWidth = '640px'; prerollDocument.getElementById('adContainer').style.height = '360px'; break; case google.ima.AdEvent.Type.STARTED: window.addEventListener('scroll', onActiveView); if (ad.isLinear()) { intervalTimer = setInterval( function () { // Example: const remainingTime = adsManager.getRemainingTime(); // adsManager.pause(); }, 300); // every 300ms } prerollDocument.getElementById('adMuteBtn').style.display = 'block'; break; case google.ima.AdEvent.Type.ALL_ADS_COMPLETED: if (ad.isLinear()) { clearInterval(intervalTimer); } if (prerollLastError === 303) { playYtVideo(); } break; case google.ima.AdEvent.Type.COMPLETE: if (ad.isLinear()) { clearInterval(intervalTimer); } playYtVideo(); break; } } function onAdError(adErrorEvent) { console.log(adErrorEvent.getError()); prerollLastError = adErrorEvent.getError().getErrorCode(); if (!loadNext()) { playYtVideo(); } } function loadNext() { iinfoVastUrlIndex++; if (iinfoVastUrlIndex < iinfoVastUrls.length) { iinfoPrerollPosition.remove(); playPrerollAd(); } else { return false; } adVolume = 1; return true; } function onContentPauseRequested() { videoContent.pause(); } function onContentResumeRequested() { videoContent.play(); } function onActiveView() { if (prerollContainer) { const containerOffset = prerollContainer.getBoundingClientRect(); const windowHeight = window.innerHeight; if (containerOffset.top < windowHeight/1 && containerOffset.bottom > 0.0) { if (prerollPaused) { adsManager.resume(); prerollPaused = false; } return true; } else { if (!prerollPaused) { adsManager.pause(); prerollPaused = true; } } } return false; } function playYtVideo() { iinfoPrerollPosition.remove(); youtubeIframe.style.display = 'block'; youtubeIframe.src += '&autoplay=1&mute=1'; } }
Upozorníme vás na články, které by vám neměly uniknout (maximálně 2x týdně).
'; document.getElementById('outstream-iframe').onload = function () { setupIframe(); } replayScreen = document.getElementById('iinfoOutstreamReplay'); iinfoOutstreamPosition = document.getElementById('iinfoOutstreamPosition'); outstreamContainer = document.getElementsByClassName('outstream-container')[0]; setupReplayScreen(); } function setupIframe() { outstreamDocument = document.getElementById('outstream-iframe').contentWindow.document; let el = outstreamDocument.createElement('style'); outstreamDocument.head.appendChild(el); el.innerText = "#adContainer>div:nth-of-type(1),#adContainer>div:nth-of-type(1) > iframe { width: 99% !important;height: 99% !important;max-width: 100%;}#videoContent,body{ width:100vw;height:100vh}body{ font-family:'Helvetica Neue',Arial,sans-serif}#videoContent{ overflow:hidden;background:#000}#adMuteBtn{ width:35px;height:35px;border:0;background:0 0;display:none;position:absolute;fill:rgba(230,230,230,1);bottom:-5px;right:25px}"; videoContent = outstreamDocument.getElementById('contentElement'); videoContent.style.display = 'none'; videoContent.volume = 1; videoContent.muted = false; if ( location.href.indexOf('rejstriky.finance.cz') !== -1 || location.href.indexOf('finance-rejstrik') !== -1 || location.href.indexOf('firmy.euro.cz') !== -1 || location.href.indexOf('euro-rejstrik') !== -1 || location.href.indexOf('/rejstrik/') !== -1 || location.href.indexOf('/rejstrik-firem/') !== -1) { outstreamDirectPlayed = true; soundAllowed = true; iinfoVastUrlIndex = 0; } if (!outstreamDirectPlayed) { console.log('OUTSTREAM direct'); setUpIMA(true); } else { if (soundAllowed) { const playPromise = videoContent.play(); if (playPromise !== undefined) { playPromise.then(function () { console.log('OUTSTREAM sound allowed'); setUpIMA(false); }).catch(function () { console.log('OUTSTREAM sound forbidden'); renderBanner(); }); } } else { renderBanner(); } } } function getWrapper() { let articleWrapper = document.querySelector('.rs-outstream-placeholder'); // Outstream Placeholder from RedSys manipulation if (articleWrapper && articleWrapper.style.display !== 'block') { articleWrapper.innerHTML = ""; articleWrapper.style.display = 'block'; } // Don't render OutStream on homepages if (articleWrapper === null) { if (document.querySelector('body.p-index')) { return null; } } if (articleWrapper === null) { articleWrapper = document.getElementById('iinfo-outstream'); } if (articleWrapper === null) { articleWrapper = document.querySelector('.layout-main__content .detail__article p:nth-of-type(6)'); } if (articleWrapper === null) { // Euro, Autobible, Zdravi articleWrapper = document.querySelector('.o-article .o-article__text p:nth-of-type(6)'); } if (articleWrapper === null) { articleWrapper = document.getElementById('sidebar'); } if (!articleWrapper) { console.error("Outstream wrapper of article was not found."); } return articleWrapper; } function setupDimensions() { outstreamWidth = Math.min(iinfoOutstreamPosition.offsetWidth, 480); outstreamHeight = Math.min(iinfoOutstreamPosition.offsetHeight, 320); } /** * Sets up IMA ad display container, ads loader, and makes an ad request. */ function setUpIMA(direct) { google.ima.settings.setDisableCustomPlaybackForIOS10Plus(true); google.ima.settings.setLocale('cs'); google.ima.settings.setNumRedirects(10); // Create the ad display container. createAdDisplayContainer(); // Create ads loader. adsLoader = new google.ima.AdsLoader(adDisplayContainer); // Listen and respond to ads loaded and error events. adsLoader.addEventListener( google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, onAdsManagerLoaded, false); adsLoader.addEventListener( google.ima.AdErrorEvent.Type.AD_ERROR, onAdError, false); // An event listener to tell the SDK that our content video // is completed so the SDK can play any post-roll ads. const contentEndedListener = function () { adsLoader.contentComplete(); }; videoContent.onended = contentEndedListener; // Request video ads. const adsRequest = new google.ima.AdsRequest(); if (direct) { adsRequest.adTagUrl = directVast; console.log('Outstream DIRECT CAMPAING advert: ' + directVast); videoContent.muted = true; videoContent.volume = 0; outstreamDirectPlayed = true; } else { adsRequest.adTagUrl = iinfoVastUrls[iinfoVastUrlIndex]; console.log('Outstream advert: ' + iinfoVastUrls[iinfoVastUrlIndex]); videoContent.muted = false; videoContent.volume = 1; } // Specify the linear and nonlinear slot sizes. This helps the SDK to // select the correct creative if multiple are returned. // adsRequest.linearAdSlotWidth = outstreamWidth; // adsRequest.linearAdSlotHeight = outstreamHeight; adsRequest.nonLinearAdSlotWidth = 0; adsRequest.nonLinearAdSlotHeight = 0; adsLoader.requestAds(adsRequest); } function setupReplayScreen() { replayScreen.addEventListener('click', function () { iinfoOutstreamPosition.remove(); iinfoVastUrlIndex = 0; outstreamInit(); }); } /** * Sets the 'adContainer' div as the IMA ad display container. */ function createAdDisplayContainer() { // We assume the adContainer is the DOM id of the element that will house // the ads. outstreamDocument.getElementById('videoContent').style.display = 'none'; adDisplayContainer = new google.ima.AdDisplayContainer( outstreamDocument.getElementById('adContainer'), videoContent); } function unmuteAdvert() { adVolume = !adVolume; if (adVolume) { adsManager.setVolume(0.3); outstreamDocument.getElementById('adMuteBtn').innerHTML = ''; } else { adsManager.setVolume(0); outstreamDocument.getElementById('adMuteBtn').innerHTML = ''; } } /** * Loads the video content and initializes IMA ad playback. */ function playAds() { // Initialize the container. Must be done through a user action on mobile // devices. videoContent.load(); adDisplayContainer.initialize(); // setupDimensions(); try { // Initialize the ads manager. Ad rules playlist will start at this time. adsManager.init(1920, 1080, google.ima.ViewMode.NORMAL); // Call play to start showing the ad. Single video and overlay ads will // start at this time; the call will be ignored for ad rules. adsManager.start(); // window.addEventListener('resize', function (event) { // if (adsManager) { // setupDimensions(); // adsManager.resize(outstreamWidth, outstreamHeight, google.ima.ViewMode.NORMAL); // } // }); } catch (adError) { // An error may be thrown if there was a problem with the VAST response. // videoContent.play(); } } /** * Handles the ad manager loading and sets ad event listeners. * @param { !google.ima.AdsManagerLoadedEvent } adsManagerLoadedEvent */ function onAdsManagerLoaded(adsManagerLoadedEvent) { // Get the ads manager. const adsRenderingSettings = new google.ima.AdsRenderingSettings(); adsRenderingSettings.restoreCustomPlaybackStateOnAdBreakComplete = true; adsRenderingSettings.loadVideoTimeout = 12000; // videoContent should be set to the content video element. adsManager = adsManagerLoadedEvent.getAdsManager(videoContent, adsRenderingSettings); // Add listeners to the required events. adsManager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, onAdError); adsManager.addEventListener( google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED, onContentPauseRequested); adsManager.addEventListener( google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED, onContentResumeRequested); adsManager.addEventListener( google.ima.AdEvent.Type.ALL_ADS_COMPLETED, onAdEvent); // Listen to any additional events, if necessary. adsManager.addEventListener(google.ima.AdEvent.Type.LOADED, onAdEvent); adsManager.addEventListener(google.ima.AdEvent.Type.STARTED, onAdEvent); adsManager.addEventListener(google.ima.AdEvent.Type.COMPLETE, onAdEvent); playAds(); } /** * Handles actions taken in response to ad events. * @param { !google.ima.AdEvent } adEvent */ function onAdEvent(adEvent) { // Retrieve the ad from the event. Some events (for example, // ALL_ADS_COMPLETED) don't have ad object associated. const ad = adEvent.getAd(); console.log('Outstream event: ' + adEvent.type); switch (adEvent.type) { case google.ima.AdEvent.Type.LOADED: // This is the first event sent for an ad - it is possible to // determine whether the ad is a video ad or an overlay. if (!ad.isLinear()) { // Position AdDisplayContainer correctly for overlay. // Use ad.width and ad.height. videoContent.play(); } outstreamDocument.getElementById('adContainer').style.width = '100%'; outstreamDocument.getElementById('adContainer').style.maxWidth = '640px'; outstreamDocument.getElementById('adContainer').style.height = '360px'; break; case google.ima.AdEvent.Type.STARTED: window.addEventListener('scroll', onActiveView); // This event indicates the ad has started - the video player // can adjust the UI, for example display a pause button and // remaining time. if (ad.isLinear()) { // For a linear ad, a timer can be started to poll for // the remaining time. intervalTimer = setInterval( function () { // Example: const remainingTime = adsManager.getRemainingTime(); // adsManager.pause(); }, 300); // every 300ms } outstreamDocument.getElementById('adMuteBtn').style.display = 'block'; break; case google.ima.AdEvent.Type.ALL_ADS_COMPLETED: if (ad.isLinear()) { clearInterval(intervalTimer); } if (outstreamLastError === 303) { if (isBanner) { renderBanner(); } else { replayScreen.style.display = 'flex'; } } break; case google.ima.AdEvent.Type.COMPLETE: // This event indicates the ad has finished - the video player // can perform appropriate UI actions, such as removing the timer for // remaining time detection. if (ad.isLinear()) { clearInterval(intervalTimer); } if (isBanner) { renderBanner(); } else { replayScreen.style.display = 'flex'; } break; } } /** * Handles ad errors. * @param { !google.ima.AdErrorEvent } adErrorEvent */ function onAdError(adErrorEvent) { // Handle the error logging. console.log(adErrorEvent.getError()); outstreamLastError = adErrorEvent.getError().getErrorCode(); if (!loadNext()) { renderBanner(); } } function renderBanner() { if (isBanner) { console.log('Outstream: Render Banner'); iinfoOutstreamPosition.innerHTML = ""; iinfoOutstreamPosition.style.height = "330px"; iinfoOutstreamPosition.appendChild(bannerDiv); } else { console.log('Outstream: Banner is not set'); } } function loadNext() { iinfoVastUrlIndex++; if (iinfoVastUrlIndex < iinfoVastUrls.length) { iinfoOutstreamPosition.remove(); outstreamInit(); } else { return false; } adVolume = 1; return true; } /** * Pauses video content and sets up ad UI. */ function onContentPauseRequested() { videoContent.pause(); // This function is where you should setup UI for showing ads (for example, // display ad timer countdown, disable seeking and more.) // setupUIForAds(); } /** * Resumes video content and removes ad UI. */ function onContentResumeRequested() { videoContent.play(); // This function is where you should ensure that your UI is ready // to play content. It is the responsibility of the Publisher to // implement this function when necessary. // setupUIForContent(); } function onActiveView() { if (outstreamContainer) { const containerOffset = outstreamContainer.getBoundingClientRect(); const windowHeight = window.innerHeight; if (containerOffset.top < windowHeight/1 && containerOffset.bottom > 0.0) { if (outstreamPaused) { adsManager.resume(); outstreamPaused = false; } return true; } else { if (!outstreamPaused) { adsManager.pause(); outstreamPaused = true; } } } return false; } let outstreamInitInterval; if (typeof cpexPackage !== "undefined") { outstreamInitInterval = setInterval(tryToInitializeOutstream, 100); } else { const wrapper = getWrapper(); if (wrapper) { let outstreamInitialized = false; window.addEventListener('scroll', () => { if (!outstreamInitialized) { const containerOffset = wrapper.getBoundingClientRect(); const windowHeight = window.innerHeight; if (containerOffset.top < windowHeight / 1 && containerOffset.bottom > 0.0) { outstreamInit(); outstreamInitialized = true; } } }); } } function tryToInitializeOutstream() { const wrapper = getWrapper(); if (wrapper) { const containerOffset = wrapper.getBoundingClientRect(); const windowHeight = window.innerHeight; if (containerOffset.top < windowHeight / 1 && containerOffset.bottom > 0.0) { if (cpexPackage.adserver.displayed) { clearInterval(outstreamInitInterval); outstreamInit(); } } } else { clearInterval(outstreamInitInterval); } } }
OSZAR »