Jak za jeden týden připravit kompletní aplikaci pro Windows 8 s použitím technologií HTML5, CSS3 a JavaScript – den 4

MyWindows.cz

home archív foto video win8dev kontakt

Jak za jeden týden připravit kompletní aplikaci pro Windows 8 s použitím technologií HTML5, CSS3 a JavaScript – den 4

Toto je poslední část naší série. Opravdu poslední článek publikuji, až bude k dispozici systém Release Preview, abych vám poskytl aktualizovanou verzi, ale z hlediska funkcí můžete tuto verzi považovat za kompletní.

Předchozí články naleznete zde:

A jako obvykle je kompletní řešení k dispozici zde: http://www.catuhe.com/msdn/urza/day4.zip

Celý projekt byl následně aktualizován pro Release Preview verzi Windows 8 (z Customer Preview), pro kompletní seriál (dny 0 - 4, bude popsáno v dalších článcích), je k dispozici zde: http://mywindows.cz/media/urza/UrzaGatherer.zip

V tomto článku se dozvíte, jak pomocí služby Skydrive (prostřednictvím sady Live SDK: Stáhnout sadu Live SDK) můžete ukládat stav sbírky uživatele.

Celý seznam sbírky je na web uložen jako soubor JSON (viz Den 0). Stav sbírky bude uložen jako další soubor JSON. Pokud se bude seznam karet vyvíjet, nebude to mít tedy dopad na stav sbírky. Tento soubor JSON bude uložen do úložiště uživatele ve službě SkyDrive.

Přidání souboru se stavem sbírky

Na stránku rozšíření je nutné přidat kontextový panel aplikace, pomocí něhož uživatel může vybrat kartu a označit, zda ji momentálně má ve své sbírce:

Na panelu aplikace přibudou následující nové ovládací prvky:

<button data-win-control="WinJS.UI.AppBarCommand"
data-win-options="{id:'checkButton',section:'selection'}"> </button> <button data-win-control="WinJS.UI.AppBarCommand"
data-win-options="{id:'uncheckButton',section:'selection'}"> </button> <hr data-win-control="WinJS.UI.AppBarCommand"
data-win-options="{type:'separator',section:'selection'}" /> <button data-win-control="WinJS.UI.AppBarCommand"
data-win-options="{id:'checkAllButton',section:'selection'}"> </button> <button data-win-control="WinJS.UI.AppBarCommand"
data-win-options="{id:'uncheckAllButton',section:'selection'}"> </button>

Pro všechna tlačítka je atribut section nastaven na hodnotu selection, aby se zobrazila v levé části panelu aplikace (v kontextové části). Když uživatel klikne pravým tlačítkem myši na položku v ovládacím prvku listView (nebo po ní potáhne prstem dolů), knihovna WinJS zobrazí panel aplikace, na kterém budou aktivní všechna kontextová tlačítka. V opačném případě se zobrazí pouze tlačítka umístěná v globální části.

Samozřejmě nesmíte zapomenout aktivovat vícenásobný výběr v ovládacím prvku listView:

listView.selectionMode = WinJS.UI.SelectionMode.multi;

Kliknutí na tato tlačítka povede k volání jedné z následujících funkcí:

var removeFromCollection = function (tab) {
    if (!UrzaGatherer.UserData) {
        showWarning();
        return;
    }

    for (var index = 0; index < (tab ? tab.length : filtered.length); index++) {
        var card = filtered.getAt(tab ? tab[index] : index);

        card.isChecked = false;

        if (card.checkElement)
            WinJS.Utilities.addClass(card.checkElement, "hidden");

        delete UrzaGatherer.UserData[card.id];
    };

    var listView = document.querySelector(".cardsList").winControl;
    listView.selection.clear();

    if (document.getElementById("checkFilter").selectedIndex > 0)
        that.updateLayout(document, appView.value);

    UrzaGatherer.Skydrive.UploadUserFile();

    document.querySelector(".appBar").winControl.hide();
};

var addToCollection = function (tab) {
    if (!UrzaGatherer.UserData) {
        showWarning();
        return;
    }

    for (var index = 0; index < (tab ? tab.length : filtered.length); index++) {
        var card = filtered.getAt(tab ? tab[index] : index);

        card.isChecked = true;

        if (card.checkElement)
            WinJS.Utilities.removeClass(card.checkElement, "hidden");

        UrzaGatherer.UserData[card.id] = true;
    };

    var listView = document.querySelector(".cardsList").winControl;
    listView.selection.clear();

    if (document.getElementById("checkFilter").selectedIndex > 0)
        that.updateLayout(document, appView.value);

    UrzaGatherer.Skydrive.UploadUserFile();

    document.querySelector(".appBar").winControl.hide();
};

Obě funkce kontrolují, zda existuje objekt UrzaGatherer.UserData, který představuje aktuální stav sbírky uživatele. Funkce pracují pouze s položkami na určité záložce, pokud je záložka předána jako parametr. V opačném případě pracují s celým rozšířením.

Přidání položky do sbírky uživatele se podobá přidání vlastnosti, jejíž název je jedinečné ID karty:

UrzaGatherer.UserData[card.id] = true;

Celá sbírka uživatele je tedy jeden velký objekt, jehož vlastnosti odpovídají kartám, které uživatel vlastní . Takový objekt lze snadno serializovat pomocí funkce JSON.stringify.

Pro snadný přístup má karta také vlastnost isChecked.

Připojení ke službě SkyDrive

Aby bylo možné sledovat stav sbírky uživatele, je nutné ji uložit na bezpečném místě. Pro tyto účely můžete jako centrální úložiště použít službu SkyDrive (přirozeně se souhlasem uživatele).

K tomu je zapotřebí stáhnout sadu Live SDK a přidat na ni odkaz ve svém projektu:

Poté je nutné přidat odkaz na soubor JavaScript:

    <script src="///LiveSDKHTML/js/wl.js"></script>

Ze všeho nejdříve musíte uživateli umožnit připojení ke službám Live:

var init = function () {
    var onStatusChange = function (e) {
        WL.getLoginStatus(function (response) {
            if (response.status == "notConnected") {
                connect();
            }
        });
    };

    WL.Event.subscribe("auth.login", getUserFile);
    WL.Event.subscribe("auth.statusChange", onStatusChange);

    WL.init({
        scope: ["wl.signin", "wl.skydrive_update"]
    });
};

Tento kód může být volán prostřednictvím tlačítka ve vaší aplikaci (doporučuji ho umístit do rohu aplikace a jeho kopii do podokna nastavení).

Jak vidíte, kód přihlašuje odběr dvou událostí: auth.login a auth.statusChange. Když je uživatel připojen, je nutné volat funkci getUserFile (seznámíte se s ní v další části článku). Když se stav změní na notConnected, je nutné volat kód pro připojení:

var connect = function () {
    if (UrzaGatherer.Skydrive.OnConnecting)
        UrzaGatherer.Skydrive.OnConnecting();

    WL.login({
        scope: ["wl.signin", "wl.skydrive_update"]
    }).then(function (response) {
        getUserFile();
    }, function (responseFailed) {

        if (responseFailed.error == "access_denied") {
        }
        else {
            if (UrzaGatherer.Skydrive.OnFailed)
                UrzaGatherer.Skydrive.OnFailed();
        }
    });
};

Definoval jsem několik událostí, které umožňují zobrazit během připojování zpětnou vazbu v uživatelském rozhraní. Funkce WL.login zobrazují ovládací prvek, který uživatele žádá o svolení k přihlášení ke službám Live (wl.signin) a k přístupu k jeho účtu služby SkyDrive (wl.skydrive_update).

Pokud uživatel souhlas neposkytne, můžete vyvolat událost, která zajistí synchronizaci uživatelského rozhraní.

Pokud uživatel svolení udělí, je volán následující kód:

var getUserFile = function () {
    UrzaGatherer.UserLogged = true;

    // Creating folder
    WL.api({
        path: "me/skydrive",
        method: "POST",
        body: {
            "name": "UrzaGatherer",
            "description": "UrzaGatherer repository folder"
        }
    }).then(
            function (response) {
                Windows.Storage.ApplicationData.current.roamingSettings.values["folderID"] = response.id;
                getFileOnline();
            },
            function (responseFailed) {
                if (responseFailed.error.code != "resource_already_exists") {
                    getFileOffline();
                    if (UrzaGatherer.Skydrive.OnFailed)
                        UrzaGatherer.Skydrive.OnFailed();
                }
                else {
                    getFileOnline();
                }
            }
        );
};

Tato funkce vytváří složku pro aplikaci UrzaGatherer v úložišti služby SkyDrive a pokouší se získat sbírku uživatele. Pokud dojde k chybě, pokusí se získat místní kopii sbírky.

Pro získání online verze je volán následující kód:

var getFileOnline = function () {
    var fileID = Windows.Storage.ApplicationData.current.roamingSettings.values["fileID"];

    if (!fileID) {
        getFileOffline();
        return;
    }

    // Get file info
    WL.api({
        path: fileID,
        method: "GET"
    }).then(
            function (response) {
                var distantVersion = parseInt(response.description ? response.description : "-1");
                var localVersion = currentUserFileVersion();

                // Download file
                if (localVersion < distantVersion) {
                    Windows.Storage.ApplicationData.current.localFolder.createFileAsync(
                    	filename, Windows.Storage.CreationCollisionOption.replaceExisting).then(function (file) {
                        WL.download({
                            path: fileID,
                            file_output: file
                        }).then(
                        function (response) {
                            getFileOffline();
                        },
                        function (responseFailed) {
                            getFileOffline();
                        }
                    );
                    });
                    return;
                }
                getFileOffline();
            },
            function (responseFailed) {
                getFileOffline();
            }
        );
};

Všimněte si, že po načtení souboru je automaticky vytvořena místní kopie.

Možná jste si také všimli, že je udržováno číslo verze souboru, které umožňuje zjistit, zda je verze na serveru novější než místní verze.

V případě chyby může následující kód načíst místní kopii (pokud existuje):

var getFileOffline = function () {
    Windows.Storage.ApplicationData.current.localFolder.getFileAsync(filename).then(function (file) {
        // On success
        Windows.Storage.FileIO.readTextAsync(file).then(function (data) {
            if (data)
                UrzaGatherer.UserData = JSON.parse(data);
            else
                UrzaGatherer.UserData = {};

            if (UrzaGatherer.Skydrive.OnConnected && UrzaGatherer.UserLogged)
                UrzaGatherer.Skydrive.OnConnected();

            if (UrzaGatherer.Skydrive.OnDataAvailable)
                UrzaGatherer.Skydrive.OnDataAvailable();
        });
    }, function () {
        // On error
        Windows.Storage.ApplicationData.current.localFolder.createFileAsync(
        	filename, Windows.Storage.CreationCollisionOption.replaceExisting).then(function (file) {
            UrzaGatherer.UserData = {};
            Windows.Storage.FileIO.writeTextAsync(file, JSON.stringify(UrzaGatherer.UserData));
            Windows.Storage.ApplicationData.current.localSettings.values["userFileVersion"] = 
currentUserFileVersion() + 1; if (UrzaGatherer.Skydrive.OnConnected && UrzaGatherer.UserLogged) UrzaGatherer.Skydrive.OnConnected(); if (UrzaGatherer.Skydrive.OnDataAvailable) UrzaGatherer.Skydrive.OnDataAvailable(); }); }); };

Pokud systém nemůže získat místní kopii, je vytvořena prázdná verze.

Aktualizace sbírky uživatele ve službě SkyDrive

Na závěr může aplikace volat následující kód pro uložení sbírky uživatele v úložišti služby SkyDrive:

var uploadUserFile = function (deferral) {
    Windows.Storage.ApplicationData.current.localFolder.createFileAsync(filename, 
    	Windows.Storage.CreationCollisionOption.replaceExisting).then(function (file) {
        Windows.Storage.FileIO.writeTextAsync(file, JSON.stringify(UrzaGatherer.UserData)).then(function () {
            var folderID = Windows.Storage.ApplicationData.current.roamingSettings.values["folderID"];
            Windows.Storage.ApplicationData.current.localSettings.values["userFileVersion"] 
= currentUserFileVersion() + 1; WL.upload({ path: folderID, file_name: file.name, file_input: file, overwrite: true }).then( function (response) { Windows.Storage.ApplicationData.current.roamingSettings.values["fileID"] = response.id; updateDistantFileVersion(currentUserFileVersion()); if (deferral) deferral.complete(); }, function (responseFailed) { if (deferral) deferral.complete(); } ); }); }); };

Po uložení souboru je aktualizováno místní číslo verze souboru a také číslo ve službě SkyDrive:

var updateDistantFileVersion = function (version) {
    var fileID = Windows.Storage.ApplicationData.current.roamingSettings.values["fileID"];
    if (!fileID)
        return;
    WL.api({
        path: fileID,
        method: "PUT",
        body: {
            description: version
        }
    }).done();
};

Jak vidíte, nevelká sada rozhraní API umožňuje vytvářet data ve službě SkyDrive, číst je a zapisovat. Uživatelské rozhraní pro připojení poskytuje samotná sada SDK, a proto jej můžete opravdu snadno integrovat do své vlastní aplikace.

S použitím předem definovaných ovládacích prvků můžete dokonce zobrazit tlačítko pro připojení/odpojení.

Pokračování příště

Nyní máte k dispozici kompletní aplikaci splňující požadavky systému Windows 8, která vám může pomoci vytvořit svou vlastní oceňovanou aplikaci. Po uvedení verze Release Preview (na začátku června) publikuji poslední článek, který vám ukáže, jak portovat váš kód.

Až bude k dispozici verze Release Preview, publikuji aplikaci UrzaGatherer na webu Windows Store. Přidal jsem další vizuální funkce, jako je například karta dne, dynamické pozadí nebo spousta působivých animací:

Nenechte si tedy ujít konečnou verzi.


Anglický originál tohoto článku od David Catuhe je dostupný na MSDN.


win8 soutěž win8 vývoj

Komentáře

  1. 1 Adam Kalisz 28.06.12, 21:33:23

    Pěkný seriál! Díky

Nový komentář

Pro přidání komentáře se musíte  registrovat Facebookem. Je to snadné a bezpečné.