Toasts and Alerts

komunikácia s používateľom pomocou Toast-u a Alert dialógu, ukončenie aplikácie, zistenie platformy

Záznam z prednášky

Introduction

  • (slide) stále pracujeme na baterke

    • už nám síce pracuje (a čo je najdôležitejšie - svieti), ale to nie je všetko
    • musíme ošetriť napr. prípady, kedy bude aplikácia spustená na zariadení, ktoré nie je vybavené bleskom a teda svietiť nebude
    • a taktiež musíme vyriešiť situáciu, keď aplikácia bude spustená na Android-e, ale nebude mať práva na prístup ku blesku
    • a popri tom by bolo dobré komunikovať s používateľom a informovať ho o všetkom, k čomu došlo

Device doesn’t have a Torch

  • Prípad, kedy zariadenie nie je vybavené bleskom, bude zastupovať emulátor. Pozrime sa teda na spustenie aplikácie na ňom.

  • Ak aplikáciu spustíme, tak sa spustí normálne. Ak sa však pokúsime baterku zasvietiť, skončíme s hláškou Possible Unhandled Promise Rejection a so správou Error: Bad argument passed to camera service.

  • Táto chyba priamo súvisí s kamerou, kedy dochádza k požiadavke o jej ovládanie na zariadení, ktoré ale nemá blesk.

  • Fragment kódu, ktorý slúži na ovládanie blesku vo funkcii toggleState() teda obaľme do volania try-catch tak, ako je to uvedené v dokumentácii modulu react-native-torch. To znamená, že z funkcie musíme spraviť asynchrónnu funkciu a počkáme si na výsledok volania Torch.switchState() pomocou kľúčového slova await:

    const toggleState = async function () {
        try {
            await Torch.switchState(!isOn);
            setIsOn(!isOn);
        } catch (e) {
            console.log(e);
        }
    };

Notifying the User

  • V kóde sme síce situáciu o neexistencii blesku vyriešili bez toho, aby beh aplikácie zlyhal, musíme však o vzniknutej situácii informovať aj používateľa. Na to nám totiž rozhodne nebude stačiť vypisovanie do konzoly cez console.log().

  • Na to samozrejme môžeme použiť niekoľko spôsobov.

Toast

  • (slide) React Native’s ToastAndroid API exposes the Android platform’s ToastAndroid module as a JS module. It provides the method show(message, duration) which takes the following parameters:

    • message A string with the text to toast
    • duration The duration of the toast—either ToastAndroid.SHORT or ToastAndroid.LONG
    Android Toast
  • Upravíme kód:

    // import ToastAndroid first
    import { ToastAndroid } from "react-native";
    
    const toggleState = async function () {
        try {
            await Torch.switchState(!isOn);
            setIsOn(!isOn);
        } catch (e) {
            ToastAndroid.show(
                "No camera available. Go and buy a device \
                with some and come back later.",
                ToastAndroid.SHORT
            );
        }
    };
  • Toto však funguje len na Android-e. Aby sme to použili správne, môžeme si overiť platformu pomocou modulu Platform:

    // import Platform first
    import { Platform } from "react-native";
    
    const toggleState = async function () {
        try {
            await Torch.switchState(!isOn);
            setIsOn(!isOn);
        } catch (e) {
            if(Platform.OS === 'android'){
                ToastAndroid.show(
                    "No camera available. Go and buy a device \
                    with some and come back later.",
                    ToastAndroid.SHORT
                );
            }else{
                console.log('No camera available. Go and buy \
                a device with some and come back later.')
            }
        }
    };
  • Ak chceme, aby aplikácia fungovala multiplatformne, tak Toast asi nie je najlepší nápad, aj keď vyzerá dobre ;) Existujú však rozšírenia, pomocou ktorých je možné správanie Toast-u zabezpečiť aj na iných platformách. Napríklad react-native-simple-toast alebo react-native-toast-message.

Alert

  • (slide) Launches an alert dialog with the specified title and message.

    Alert Dialog
  • Poznáme zo štandardného JavaScript-u v prehliadači, ale v React Native reprezentuje API, ktoré funguje na platformách Android aj iOS. Existuje však rozdiel v jeho používaní na jednotlivých platformách. O tom sa dočítate v dokumentácii.

  • Obecne sa Alert skladá z:

    • titulku / nadpisu,
    • správy, a
    • voliteľne zo zoznamu tlačidiel s možnosťou vlastného ošetrenia ich stlačenia
  • Jednoduchý Alert pre náš prípad môže vyzerať nasledovne:

    // update the import for Alert
    import { Alert } from "react-native";
    
    const toggleState = async function () {
        try {
            await Torch.switchState(!isOn);
            setIsOn(!isOn);
        } catch (e) {
            Alert.alert(
                'Error', 
                'No camera available. Go and buy a device \
                with some and come back later.'
            );
        }
    };

Exit App

  • Používateľa sme teda síce upozornili, takže teraz môže klikať a šťukať a bude mu zobrazovať len Alert dialóg. To je však celkom trápne, nakoľko vlastne na existencii blesku stojí celá naša aplikácia. Vhodnejšie by bolo napríklad aplikáciu rovno vypnúť, keď príde na to, že blesk nemá.

  • Priama podpora pre vypnutie aplikácie v React Native však nie je. Túto funkcionalitu nám teda zabezpečí externý modul s názvom react-native-exit-app. Nainštalujeme ho príkazom:

    $ npm install react-native-exit-app --save

    a zlinkujeme s projektom príkazom:

    $ react-native link react-native-exit-app
  • Jej použitie je následovne veľmi jednoduché - na vhodnom mieste stačí zavolať:

    import RNExitApp from 'react-native-exit-app';
    ...
    RNExitApp.exitApp();
    ...
  • Upravíme teda kód našej aplikácie tak, že po kliknutí na tlačidlo v Alert dialógu dôjde k ukončeniu aplikácie pomocou tohto volania:

    const toggleState = async function () {
        try {
            await Torch.switchState(!isOn);
            setIsOn(!isOn);
        } catch (e) {
            Alert.alert(
                "Error",
                "No camera available. Go and buy a device \
                with some and come back later.",
                [
                    {
                        text: "Quit",
                        onPress: function () {
                            RNExitApp.exitApp();
                        },
                    },
                ]
            );
        }
    };

Test Before Run

  • Aktuálne teda funguje všetko ako má. Ak sa však zamyslíme nad fungovaním, tak nie je veľmi praktické, aby používateľ aplikáciu musel spustiť a až po kliknutí na obrázok alebo tlačidlo došlo k vyhodnoteniu, či je alebo nie je blesk k dispozícii. Toto naozaj nie je UX, ktorý by sme chceli mať.
  • Ak sa zamyslíme, tak vieme, že kód sa vykonáva v rámci funkcie zhora nadol, pričom funkcia musí vrátiť view komponentu. Ak teda na začiatku kódu vložíme fragment, ktorým overíme, či máme alebo nemáme blesk k dispozícii, vyriešili by sme tento problém.

Conclusion

  • Na to, aby sme problém so spustením špecifického kódu po spustení kontroléru vyriešili, potrebujeme poznať a porozumieť životnému cyklu kontajnera. A ten si predstavíme nabudúce.