Skip to content

Commit

Permalink
Changed tiles logic
Browse files Browse the repository at this point in the history
- Fixed possible NullReferenceExceptions in the Background agent
- Moved some tuff into own library to allow sharing it with the
background agent class
- Changed tile updating to run fully on the phone
- Changed primary tile to support wide tiles:
! Still needs a medium and small icon
- Known issue: The constructor deletes the tile images for debug
purposes. A debug build will not have back background images after the
background task has run. This behaviour is not present in release
builds.
- Moved notification formatting into own helper class
- In app notifications are now full text if only one notification is
present
  • Loading branch information
ChrisK91 committed Sep 8, 2013
1 parent 1f8187e commit 4ab01c4
Show file tree
Hide file tree
Showing 23 changed files with 500 additions and 192 deletions.
60 changes: 10 additions & 50 deletions SparklrWP Background Agent/ScheduledAgent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,33 +60,6 @@ protected async override void OnInvoke(ScheduledTask task)
byte[] passbyts = ProtectedData.Unprotect((byte[])IsolatedStorageSettings.ApplicationSettings["password"], null);
string password = Encoding.UTF8.GetString(passbyts, 0, passbyts.Length);

Func<Notification, String> textGenerator = (not) =>
{
if (not.type == 1)
{
if (not.body == "")
{
return "{0} likes this post.";
}
else
{
return "{0} commented " + not.body + ".";
}
}
else if (not.type == 2)
{
return "{0} mentioned you.";
}
else if (not.type == 3)
{
return "{0} messaged you.";
}
else
{
return "{0} did something to you.";
}
};

LoginEventArgs loginArgs = await client.LoginAsync(username, password);
if (loginArgs.IsSuccessful)
{
Expand Down Expand Up @@ -123,32 +96,17 @@ protected async override void OnInvoke(ScheduledTask task)
if (unargs.IsSuccessful)
{

foreach (ShellTile til in ShellTile.ActiveTiles)
{
//Update only primary tile
if (til.NavigationUri.ToString() == "/")
{
Mangopollo.Tiles.FlipTileData data = new Mangopollo.Tiles.FlipTileData();
data.Title = "Sparklr*";
data.Title = "Sparklr*";
data.BackgroundImage = new Uri("/Background.png", UriKind.Relative);
//TODO?: change to not use external server? Update text only instead?
//Known bug: client.Usernames[strm.notifications[0].from] causes a Outofrange exception
//data.BackBackgroundImage = new Uri("http://til.eaterofcorps.es/?url=http%3A%2F%2Fd.sparklr.me%2Fi%2F" + strm.notifications[0].from + ".jpg&text=" + Uri.EscapeDataString(String.Format(textGenerator(strm.notifications[0]), client.Usernames[strm.notifications[0].from])));
til.Update(data);

//We can only have one primary tile --> break
break;
}
}
SparklrWP.Utils.TilesCreator.UpdatePrimaryTile(false, client);

foreach (Notification not in strm.notifications)
{
ShellToast notif = new ShellToast();
notif.Title = "Sparklr*";
//notif.Content = String.Format(textGenerator(not), client.Usernames[not.from]);
notif.Content = await SparklrWP.Utils.NotificationHelpers.Format(not.type, not.body, not.from, client);
notif.NavigationUri = new Uri("/Pages/MainPage.xaml?notification=" + not.id, UriKind.Relative);
notif.Show();

if (!String.IsNullOrEmpty(notif.Content))
notif.Show();
}
}
else
Expand All @@ -157,9 +115,11 @@ protected async override void OnInvoke(ScheduledTask task)
{
ShellToast notif = new ShellToast();
notif.Title = "Sparklr*";
notif.Content = String.Format(textGenerator(not), "Someone");
notif.Content = await SparklrWP.Utils.NotificationHelpers.Format(not.type, not.body, not.from, client);
notif.NavigationUri = new Uri("/Pages/MainPage.xaml?notification=" + not.id, UriKind.Relative);
notif.Show();

if (!String.IsNullOrEmpty(notif.Content))
notif.Show();
}
}
}
Expand All @@ -169,7 +129,7 @@ protected async override void OnInvoke(ScheduledTask task)
{
ShellToast notif = new ShellToast();
notif.Title = "Sparklr*";
notif.Content = String.Format(textGenerator(not), "Someone");
notif.Content = await SparklrWP.Utils.NotificationHelpers.Format(not.type, not.body, not.from, client);
notif.NavigationUri = new Uri("/Pages/MainPage.xaml?notification=" + not.id, UriKind.Relative);
notif.Show();
}
Expand Down
7 changes: 7 additions & 0 deletions SparklrWP Background Agent/SparklrWP Background Agent.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@
<Project>{ACE8C69F-6016-407E-8232-3027DF9CD9F2}</Project>
<Name>SparklrLib</Name>
</ProjectReference>
<ProjectReference Include="..\SparklrWP.Utils\SparklrWP.Utils.csproj">
<Project>{B1D8510B-6F57-44A3-B6F3-191BB9F68BA0}</Project>
<Name>SparklrWP.Utils</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
Expand All @@ -104,6 +108,9 @@
<SubType>Designer</SubType>
</Page>
</ItemGroup>
<ItemGroup>
<WCFMetadata Include="Service References\" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Microsoft\Silverlight for Phone\$(TargetFrameworkVersion)\Microsoft.Silverlight.$(TargetFrameworkProfile).Overrides.targets" />
<Import Project="$(MSBuildExtensionsPath)\Microsoft\Silverlight for Phone\$(TargetFrameworkVersion)\Microsoft.Silverlight.CSharp.targets" />
<ProjectExtensions />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
extern alias ImageToolsDLL;
using ImageToolsDLL::ImageTools;
using ImageTools;
using System;
using System.IO;
using System.IO.IsolatedStorage;
using System.Threading.Tasks;
using System.Windows.Media.Imaging;
using SparklrWP.Utils;

namespace SparklrWP.Utils.Caching
{
Expand Down Expand Up @@ -68,7 +68,7 @@ static Image()
if (true)
{
ClearImageCache();
App.logger.log("Deleted cache content because DEBUG flag was set");
Globals.log("Deleted cache content because DEBUG flag was set");
}
#endif

Expand All @@ -77,11 +77,11 @@ static Image()
{
storage.CreateDirectory(CacheFolder);
#if DEBUG
App.logger.log("Created folder {0}", CacheFolder);
Globals.log("Created folder {0}", CacheFolder);
#endif
}
#if DEBUG
App.logger.log("Isolated storage is using {0} of {1} bytes", storage.AvailableFreeSpace, storage.Quota);
Globals.log("Isolated storage is using {0} of {1} bytes", storage.AvailableFreeSpace, storage.Quota);
#endif
}
}
Expand All @@ -103,7 +103,7 @@ public static void ClearImageCache()
string fileName = Path.Combine(CacheFolder, file);
storage.DeleteFile(fileName);
#if DEBUG
App.logger.log("Deleted cache file {0}", fileName);
Globals.log("Deleted cache file {0}", fileName);
#endif
}
}
Expand Down Expand Up @@ -131,7 +131,7 @@ public static int CleanImageCache()
{
storage.DeleteFile(fileName);
#if DEBUG
App.logger.log("Deleted {0} from cache because it expired.", fileName);
Globals.log("Deleted {0} from cache because it expired.", fileName);
#endif
}
}
Expand All @@ -143,7 +143,7 @@ public static int CleanImageCache()
{
storage.DeleteFile(filenames[i]);
#if DEBUG
App.logger.log("Deleted {0} from cache because we exceed our specified capacity.", filenames[i]);
Globals.log("Deleted {0} from cache because we exceed our specified capacity.", filenames[i]);
#endif
}
}
Expand Down Expand Up @@ -176,7 +176,7 @@ public async static Task<object> LoadCachedImageFromUrlAsync<T>(Uri url)
if (typeof(T) == typeof(ExtendedImage))
{
//We want to load a animated GIF file. These don't support caching so we can load it directly.
return await Utils.Helpers.LoadExtendedImageFromUrlAsync(url);
return await Imaging.Helpers.LoadExtendedImageFromUrlAsync(url);
}
else if (typeof(T) == typeof(BitmapImage))
{
Expand All @@ -192,14 +192,14 @@ public async static Task<object> LoadCachedImageFromUrlAsync<T>(Uri url)
{
cachedImage.SetSource(cachedFile);
#if DEBUG
App.logger.log("Loaded image {0} from cached file {1}", url, file);
Globals.log("Loaded image {0} from cached file {1}", url, file);
#endif
return cachedImage;
}
}
else
{
BitmapImage loadedImage = await Helpers.LoadImageFromUrlAsync(url);
BitmapImage loadedImage = await Imaging.Helpers.LoadImageFromUrlAsync(url);
saveImageToCache(loadedImage, file, storage);
return loadedImage;
}
Expand All @@ -215,7 +215,7 @@ public async static Task<object> LoadCachedImageFromUrlAsync<T>(Uri url)
if (e is IOException)
{
#if DEBUG
App.logger.log("Error loading from cache: {0}", url);
Globals.log("Error loading from cache: {0}", url);
#endif
}
#if DEBUG
Expand All @@ -242,7 +242,7 @@ private static void saveImageToCache(BitmapImage image, string filename, Isolate
bitmap.SaveJpeg(cachedFile, bitmap.PixelWidth, bitmap.PixelHeight, 0, 80);

#if DEBUG
App.logger.log("Created cached file {0}", filename);
Globals.log("Created cached file {0}", filename);
#endif
}
}
Expand Down
15 changes: 15 additions & 0 deletions SparklrWP.Utils/Globals.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@

namespace SparklrWP.Utils
{
public static class Globals
{
public delegate void LoggingDelegate(string format, params object[] objects);
public static LoggingDelegate LoggingFunction;

internal static void log(string format, params object[] objects)
{
if (LoggingFunction != null)
LoggingFunction(format, objects);
}
}
}
112 changes: 112 additions & 0 deletions SparklrWP.Utils/Helpers.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
using ImageTools;
using System;
using System.IO;
using System.Net;
using System.Threading.Tasks;
using System.Windows.Media.Imaging;

namespace SparklrWP.Utils.Imaging
{
public static class Helpers
{
/// <summary>
/// Initializes the Helper class
/// </summary>
static Helpers()
{
ImageToolsHelper.InitializeImageTools();
}

/// <summary>
/// Loads an extended image from an Url asynchronously
/// </summary>
/// <param name="location">The location of the image</param>
/// <returns>A BitmapImage, that can be set as a source</returns>
public static async Task<ExtendedImage> LoadExtendedImageFromUrlAsync(Uri location)
{
WebClient client = new WebClient();
ExtendedImage image = new ExtendedImage();
Stream source = await client.OpenReadTaskAsync(location);

if (location.ToString().EndsWith("gif", StringComparison.InvariantCultureIgnoreCase))
{
image.SetSource(source);

TaskCompletionSource<ExtendedImage> imageLoaded = new TaskCompletionSource<ExtendedImage>();

EventHandler loadingCompleteHandler = new EventHandler((sender, e) =>
{
imageLoaded.SetResult(image);
});

EventHandler<UnhandledExceptionEventArgs> loadingFailedHandler = new EventHandler<UnhandledExceptionEventArgs>((sender, e) =>
{
imageLoaded.SetResult(image);
#if DEBUG
if (System.Diagnostics.Debugger.IsAttached)
System.Diagnostics.Debugger.Break();
#endif
});



image.LoadingCompleted += loadingCompleteHandler;
image.LoadingFailed += loadingFailedHandler;

image = await imageLoaded.Task;

//Remove handlers, otherwise the object might be kept in the memory
image.LoadingCompleted -= loadingCompleteHandler;
image.LoadingFailed -= loadingFailedHandler;
}
else
{
BitmapImage bmp = new BitmapImage();
bmp.SetSource(source);
WriteableBitmap writeable = new WriteableBitmap(bmp);
image = ImageExtensions.ToImage(writeable);
}

source.Close();
return image;
}

/// <summary>
/// Loads an extended image from an Url asynchronously
/// </summary>
/// <param name="location">The location of the image</param>
/// <returns>A BitmapImage, that can be set as a source</returns>
public static Task<ExtendedImage> LoadExtendedImageFromUrlAsync(string location)
{
return LoadExtendedImageFromUrlAsync(new Uri(location));
}

/// <summary>
/// Loads an image from an Url asynchronously
/// </summary>
/// <param name="location">The location of the image</param>
/// <returns>A BitmapImage, that can be set as a source</returns>
public static Task<BitmapImage> LoadImageFromUrlAsync(Uri location)
{
TaskCompletionSource<BitmapImage> loadingTask = new TaskCompletionSource<BitmapImage>();
SmartDispatcher.BeginInvoke(async () =>
{
WebClient client = new WebClient();
BitmapImage image = new BitmapImage();
image.SetSource(await client.OpenReadTaskAsync(location));
loadingTask.SetResult(image);
});
return loadingTask.Task;
}

/// <summary>
/// Loads an image from an Url asynchronously
/// </summary>
/// <param name="location">The location of the image</param>
/// <returns>A BitmapImage, that can be set as a source</returns>
public static Task<BitmapImage> LoadImageFromUrlAsync(string location)
{
return LoadImageFromUrlAsync(new Uri(location));
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
extern alias ImageToolsDLL;
using ImageToolsDLL::ImageTools.IO;
using ImageToolsDLL::ImageTools.IO.Gif;
using ImageTools.IO;
using ImageTools.IO.Gif;

namespace SparklrWP.Utils
{
Expand Down

0 comments on commit 4ab01c4

Please sign in to comment.