Some people ask me if there are some helpers available to perform various tasks such manipulating settings, local storage, etc.
There are no built-in helpers but for the current Windows 8 application I’m working, I’ve developed some of them and I wanted to share them with the community (note that this helpers are available in Javascript but it should not be hard to translate them in C#):
(function () {
“use strict”;
var applicationData = Windows.Storage.ApplicationData.current;
function hasSetting(key) {
return new WinJS.Promise(function (complete, error, progress) {
var result = applicationData.roamingSettings.values.hasKey(key);
complete(result);
});
}
function getSetting(key) {
return new WinJS.Promise(function (complete, error, progress) {
hasSetting(key).then(function (found) {
if (found) {
var result = applicationData.roamingSettings.values[key];
complete(result);
}
else {
complete(false);
}
});
});
}
function addSetting(key, value) {
return new WinJS.Promise(function (complete, error, progress) {
var result = applicationData.roamingSettings.values.insert(key, value);
complete(result);
});
}
function removeSetting(key) {
return new WinJS.Promise(function (complete, error, progress) {
applicationData.roamingSettings.values.remove(key);
complete();
});
}
function updateSetting(key, value) {
return new WinJS.Promise(function (complete, error, progress) {
hasSetting(key).then(function (result) {
if (result) {
removeSetting(key).then(function () {
addSetting(key, value).then(function (addResult) {
complete(addResult);
});
});
}
else {
addSetting(key, value).then(function (result) {
complete(result);
});
}
});
});
}
function clearSettings() {
return new WinJS.Promise(function (complete, error, progress) {
applicationData.roamingSettings.values.clear();
complete();
});
}
WinJS.Namespace.define(“SettingsHelper”, {
HasSetting: hasSetting,
GetSetting: getSetting,
AddSetting: addSetting,
RemoveSetting: removeSetting,
UpdateSetting: updateSetting,
ClearSettings: clearSettings
});
})();
(function () {
“use strict”;
var applicationData = Windows.Storage.ApplicationData.current;
var localFolder = applicationData.localFolder;
function hasSavedContent(file) {
return new WinJS.Promise(function (complete, error, progress) {
localFolder.getFileAsync(file).then(function (file) {
complete(true);
}, function () {
complete(false);
});
});
}
function saveToCache(file, content) {
return new WinJS.Promise(function (complete, error, progress) {
localFolder.createFileAsync(file, Windows.Storage.CreationCollisionOption.replaceExisting)
.then(function (file) {
file.openAsync(Windows.Storage.FileAccessMode.readWrite).then(function (stream) {
var writer = new Windows.Storage.Streams.DataWriter(stream.getOutputStreamAt(0));
writer.writeString(content);
writer.storeAsync().then(function () {
writer.flushAsync().then(function () {
complete();
});
});
});
});
});
}
function getFromCache(file) {
return new WinJS.Promise(function (complete, error, progress) {
hasSavedContent().then(function (exists) {
if (exists) {
localFolder.getFileAsync(file).then(function (file) {
file.openReadAsync().then(function (stream) {
var reader = new Windows.Storage.Streams.DataReader(stream.getInputStreamAt(0));
reader.loadAsync(stream.size).then(function (fileLength) {
var jsonContentAsString = reader.readString(fileLength);
complete(jsonContentAsString);
});
});
});
}
else {
complete();
}
});
});
}
function deleteCache(file) {
return new WinJS.Promise(function (complete, error, progress) {
hasSavedContent().then(function (exists) {
if (exists) {
localFolder.getFileAsync(file).then(function (file) {
if (file) {
file.deleteAsync().then(function () {
complete();
});
}
else {
complete();
}
})
}
else {
complete();
}
});
});
}
WinJS.Namespace.define(“StorageHelper”, {
HasSavedContent: hasSavedContent,
SaveToCache: saveToCache,
GetFromCache: getFromCache,
DeleteCache: deleteCache
});
})();
(function () {
“use strict”;
function updateMainTile() {
return new WinJS.Promise(function (complete, error, progress) {
complete();
});
}
function addSecondTile(tileId, name, image) {
return new WinJS.Promise(function (complete, error, progress) {
var tile = new Windows.UI.StartScreen.SecondaryTile(tileId);
tile.shortName = name;
tile.displayName = name;
tile.arguments = tileId;
tile.tileOptions = Windows.UI.StartScreen.TileOptions.showNameOnWideLogo;
//var uri = parseUri(image);
//var imageLocalUri = tileId + “_” + uri.file;
var imageLocalUri = tileId + “.jpg”;
rescaleImage2(image, 150, 150, imageLocalUri.replace(“.jpg”, “_uri.jpg”), false).then(function (uriLogo) {
rescaleImage2(image, 310, 150, imageLocalUri.replace(“.jpg”, “_wide.jpg”), false).then(function (wideLogo) {
tile.logo = new Windows.Foundation.Uri(uriLogo);
tile.wideLogo = new Windows.Foundation.Uri(wideLogo);
tile.requestCreateAsync().then(function (isPinned) {
if (isPinned) {
_updateSecondaryTile(tileId, name, uriLogo, wideLogo);
}
complete(isPinned);
});
});
});
});
}
function updateSecondaryTile(tileId, name, image) {
return new WinJS.Promise(function (complete, error, progress) {
isPinned(tileId).then(function (isPinned) {
if (isPinned) {
var tileToUpdate = new Windows.UI.StartScreen.SecondaryTile(tileId);
tileToUpdate.shortName = name;
tileToUpdate.displayName = name;
tileToUpdate.arguments = tileId;
tileToUpdate.tileOptions = Windows.UI.StartScreen.TileOptions.showNameOnWideLogo;
//var uri = parseUri(image);
//var imageLocalUri = tileId + “_” + uri.file;
var imageLocalUri = tileId + “.jpg”;
rescaleImage2(image, 150, 150, imageLocalUri.replace(“.jpg”, “_uri.jpg”), false).then(function (uriLogo) {
rescaleImage2(image, 310, 150, imageLocalUri.replace(“.jpg”, “_wide.jpg”), false).then(function (wideLogo) {
tileToUpdate.logo = new Windows.Foundation.Uri(uriLogo);
tileToUpdate.wideLogo = new Windows.Foundation.Uri(wideLogo);
_updateSecondaryTile(tileId, name, uriLogo, wideLogo);
complete();
});
});
}
else {
complete();
}
});
});
}
function _updateSecondaryTile(tileId, name, uriLogo, wideLogo) {
// Square tile
var tileXml = Windows.UI.Notifications.TileUpdateManager.getTemplateContent(Windows.UI.Notifications.TileTemplateType.tileSquarePeekImageAndText04);
var imageXml = tileXml.getElementsByTagName(“image”);
imageXml.item(0).attributes.getNamedItem(“src”).innerText = uriLogo;
var textXml = tileXml.getElementsByTagName(“text”);
textXml.item(0).innerText = name;
// Wide tile
var wideTileXml = Windows.UI.Notifications.TileUpdateManager.getTemplateContent(Windows.UI.Notifications.TileTemplateType.tileWidePeekImage03);
imageXml = wideTileXml.getElementsByTagName(“image”);
imageXml.item(0).attributes.getNamedItem(“src”).innerText = wideLogo;
textXml = wideTileXml.getElementsByTagName(“text”);
textXml.item(0).innerText = name;
// Merge both xml to get one tile
var mergedNode = tileXml.importNode(wideTileXml.getElementsByTagName(“binding”).item(0), true);
tileXml.getElementsByTagName(“visual”).item(0).appendChild(mergedNode);
var notificationUpdater = Windows.UI.Notifications.TileUpdateManager.createTileUpdaterForSecondaryTile(tileId);
notificationUpdater.clear();
notificationUpdater.enableNotificationQueue(true);
var tileNotification = Windows.UI.Notifications.TileNotification(tileXml);
tileNotification.tag = tileId;
notificationUpdater.update(tileNotification);
}
function removeSecondTile(tileId) {
return new WinJS.Promise(function (complete, error, progress) {
isPinned(tileId).then(function (isPinned) {
if (isPinned) {
var tileToDelete = new Windows.UI.StartScreen.SecondaryTile(tileId);
tileToDelete.requestDeleteAsync().then(function (isUnPinned) {
complete(isUnPinned);
});
}
else {
complete();
}
});
});
}
function isPinned(tileId) {
return new WinJS.Promise(function (complete, error, progress) {
var isPinned = Windows.UI.StartScreen.SecondaryTile.exists(tileId);
complete(isPinned);
});
}
function rescaleImage2(src, destinationWidth, destinationHeight, localfilename) {
return new WinJS.Promise(function (complete, error, progress) {
var Imaging = Windows.Graphics.Imaging;
WinJS.xhr({ url: src, responseType: “blob” }).then(function (request) {
var imageStream = request.response;
var fileName = new Date().getTime() + “_” + parseUri(src).file
Windows.Storage.ApplicationData.current.localFolder.createFileAsync(fileName, Windows.Storage.CreationCollisionOption.replaceExisting).then(function (rootFile) {
rootFile.openAsync(Windows.Storage.FileAccessMode.readWrite).then(function (stream) {
Windows.Storage.Streams.RandomAccessStream.copyAsync(imageStream.msDetachStream(), stream).then(function () {
stream.flushAsync().then(function () {
stream.close();
Windows.Storage.ApplicationData.current.localFolder.getFileAsync(fileName).then(function(file){
file.openReadAsync().then(function (stream) {
Imaging.BitmapDecoder.createAsync(stream).then(function (bd) {
var transform = new Windows.Graphics.Imaging.BitmapTransform();
transform.scaledHeight = destinationHeight;
transform.scaledWidth = destinationWidth;
bd.getPixelDataAsync(Imaging.BitmapPixelFormat.rgba8, Imaging.BitmapAlphaMode.straight, transform, Imaging.ExifOrientationMode.respectExifOrientation, Imaging.ColorManagementMode.doNotColorManage).then(function (pdp) {
var pixelData = pdp.detachPixelData();
Windows.Storage.ApplicationData.current.localFolder.createFileAsync(localfilename,
Windows.Storage.CreationCollisionOption.replaceExisting).then(function (file) {
file.openAsync(Windows.Storage.FileAccessMode.readWrite).then(function (stream) {
Imaging.BitmapEncoder.createAsync(Imaging.BitmapEncoder.pngEncoderId, stream).then(function (encoder) {
encoder.setPixelData(Imaging.BitmapPixelFormat.rgba8, Imaging.BitmapAlphaMode.straight, destinationWidth, destinationHeight, 96, 96, pixelData);
encoder.flushAsync().then(function () {
stream.flushAsync().then(function () {
stream.close();
rootFile.deleteAsync().done(function () {
if (complete)
complete(“ms-appdata:///local/” + localfilename.replace(“\\”, “/”));
});
});
});
});
});
});
});
});
});
});
});
});
});
});
});
});
}
// parseUri 1.2.2
// (c) Steven Levithan <stevenlevithan.com>
// MIT License
function parseUri (str) {
var o = parseUri.options,
m = o.parser[o.strictMode ? "strict" : "loose"].exec(str),
uri = {},
i = 14;
while (i–) uri[o.key[i]] = m[i] || “”;
uri[o.q.name] = {};
uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) {
if ($1) uri[o.q.name][$1] = $2;
});
return uri;
}
parseUri.options = {
strictMode: false,
key: ["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],
q: {
name: “queryKey”,
parser: /(?:^|&)([^&=]*)=?([^&]*)/g
},
parser: {
strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,
loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/
}
};
WinJS.Namespace.define(“TilesManager”, {
UpdateMainTile: updateMainTile,
AddSecondTile: addSecondTile,
UpdateSecondaryTile: updateSecondaryTile,
RemoveSecondTile: removeSecondTile,
IsPinned: isPinned,
RescaleImage: rescaleImage2
});
})();
(this last one is probably the one you’ll want to modify a bit, depending to the kind of tile you’ll want to use in your application)
Be aware that there might be some bugs or issues with the code so feel free to let me a comment if you have a fix !