From ca793f7ff4c49dd6c7bb512bcb9590d5e8ed652b Mon Sep 17 00:00:00 2001 From: Kenneth van Ewijk Date: Wed, 20 Jan 2016 14:33:12 +0100 Subject: [PATCH] Upload and share photo --- YJMPD-UWP/App.xaml.cs | 24 +++++------ YJMPD-UWP/Assets/Error.png | Bin 0 -> 3814 bytes YJMPD-UWP/Assets/about-button.png | Bin 2194 -> 0 bytes YJMPD-UWP/Assets/settings-button.png | Bin 2576 -> 0 bytes YJMPD-UWP/Assets/start-button2.png | Bin 1864 -> 0 bytes .../Helpers/EventArgs/PhotoTakenEventArgs.cs | 4 +- YJMPD-UWP/Model/ApiHandler.cs | 19 +++++++-- YJMPD-UWP/Model/GameHandler.cs | 17 ++++++-- YJMPD-UWP/Model/NetworkHandler.cs | 2 + YJMPD-UWP/Model/PhotoHandler.cs | 17 +++++--- YJMPD-UWP/ViewModels/PhotoVM.cs | 40 ++++++++++++++++-- YJMPD-UWP/Views/PhotoView.xaml | 20 ++++----- YJMPD-UWP/YJMPD-UWP.csproj | 4 +- 13 files changed, 103 insertions(+), 44 deletions(-) create mode 100644 YJMPD-UWP/Assets/Error.png delete mode 100644 YJMPD-UWP/Assets/about-button.png delete mode 100644 YJMPD-UWP/Assets/settings-button.png delete mode 100644 YJMPD-UWP/Assets/start-button2.png diff --git a/YJMPD-UWP/App.xaml.cs b/YJMPD-UWP/App.xaml.cs index f20b1ca..30a4bb3 100644 --- a/YJMPD-UWP/App.xaml.cs +++ b/YJMPD-UWP/App.xaml.cs @@ -20,23 +20,23 @@ namespace YJMPD_UWP // ======================= // SINGLETONS // ======================= - private static GeoHandler geohandler = new GeoHandler(); + private static PhotoHandler photohandler = new PhotoHandler(); - public static GeoHandler Geo + public static PhotoHandler Photo { get { - return geohandler; + return photohandler; } } - private static CompassHandler compasshandler = new CompassHandler(); + private static GameHandler gamehandler = new GameHandler(); - public static CompassHandler Compass + public static GameHandler Game { get { - return compasshandler; + return gamehandler; } } @@ -60,23 +60,23 @@ namespace YJMPD_UWP } } - private static GameHandler gamehandler = new GameHandler(); + private static GeoHandler geohandler = new GeoHandler(); - public static GameHandler Game + public static GeoHandler Geo { get { - return gamehandler; + return geohandler; } } - private static PhotoHandler photohandler = new PhotoHandler(); + private static CompassHandler compasshandler = new CompassHandler(); - public static PhotoHandler Photo + public static CompassHandler Compass { get { - return photohandler; + return compasshandler; } } diff --git a/YJMPD-UWP/Assets/Error.png b/YJMPD-UWP/Assets/Error.png new file mode 100644 index 0000000000000000000000000000000000000000..ebbe972d1b6602c2f75b443c3675bc11d11768b3 GIT binary patch literal 3814 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 SendPicture(string url) + { + JObject obj = JObject.FromObject(new + { + command = Command.PictureUrl.ToString(), + pictureurl = url + }); await App.Network.Write(obj.ToString(Formatting.None)); return true; diff --git a/YJMPD-UWP/Model/GameHandler.cs b/YJMPD-UWP/Model/GameHandler.cs index 84de13d..517c634 100644 --- a/YJMPD-UWP/Model/GameHandler.cs +++ b/YJMPD-UWP/Model/GameHandler.cs @@ -53,6 +53,12 @@ namespace YJMPD_UWP.Model { Players = new List(); Status = GameStatus.STOPPED; + App.Photo.OnPhotoTaken += Photo_OnPhotoTaken; + } + + private void Photo_OnPhotoTaken(object sender, PhotoTakenEventArgs e) + { + App.Api.SendPicture(e.Photo); } public void AddPlayer(string username) @@ -78,6 +84,12 @@ namespace YJMPD_UWP.Model UpdateGameStatus(GameStatus.WAITING); } + public void MoveToStarted() + { + App.Navigate(typeof(GameView)); + UpdateGameStatus(GameStatus.STARTED); + } + public void RemovePlayer(string username) { for(int i=Players.Count-1; i>=0; i--) @@ -179,10 +191,7 @@ namespace YJMPD_UWP.Model App.Navigate(typeof(WaitingView)); break; case GameStatus.STARTED: - if (Selected && App.Photo.Photo == null) - App.Navigate(typeof(PhotoView)); - else - App.Navigate(typeof(GameView)); + App.Navigate(typeof(GameView)); break; case GameStatus.ENDED: App.Navigate(typeof(ScoreView)); diff --git a/YJMPD-UWP/Model/NetworkHandler.cs b/YJMPD-UWP/Model/NetworkHandler.cs index 6ba5c3f..7ad9bd9 100644 --- a/YJMPD-UWP/Model/NetworkHandler.cs +++ b/YJMPD-UWP/Model/NetworkHandler.cs @@ -58,6 +58,8 @@ namespace YJMPD_UWP.Model if (Status != NetworkStatus.CONNECTED) return false; + Debug.WriteLine(data); + dout.WriteString(data + Environment.NewLine); await dout.StoreAsync(); await dout.FlushAsync(); diff --git a/YJMPD-UWP/Model/PhotoHandler.cs b/YJMPD-UWP/Model/PhotoHandler.cs index ce87dc0..50c86d0 100644 --- a/YJMPD-UWP/Model/PhotoHandler.cs +++ b/YJMPD-UWP/Model/PhotoHandler.cs @@ -1,6 +1,8 @@ using System; +using System.Collections.Generic; using System.Diagnostics; using System.IO; +using System.Linq; using System.Net.Http; using System.Threading.Tasks; using Windows.Graphics.Imaging; @@ -17,7 +19,7 @@ namespace YJMPD_UWP.Model public delegate void OnPhotoTakenHandler(object sender, PhotoTakenEventArgs e); public event OnPhotoTakenHandler OnPhotoTaken; - public SoftwareBitmapSource Photo { get; private set; } + public string Photo { get; private set; } public PhotoHandler() { @@ -29,7 +31,7 @@ namespace YJMPD_UWP.Model Photo = null; } - private void UpdatePhotoTaken(SoftwareBitmapSource photo) + public void UpdatePhotoTaken(string photo) { Photo = photo; @@ -63,9 +65,9 @@ namespace YJMPD_UWP.Model SoftwareBitmapSource bitmapSource = new SoftwareBitmapSource(); await bitmapSource.SetBitmapAsync(softwareBitmapBGR8); - await UploadImage(stream.AsStream()); + string photoURL = await UploadImage(stream.AsStream()); - UpdatePhotoTaken(bitmapSource); + UpdatePhotoTaken(photoURL); } public async Task UploadImage(Stream file) @@ -79,8 +81,11 @@ namespace YJMPD_UWP.Model { var response = await hc.PostAsync(url, postdata); response.EnsureSuccessStatusCode(); - Debug.WriteLine(await response.Content.ReadAsStringAsync()); - return await response.Content.ReadAsStringAsync(); + string imageurl = await response.Content.ReadAsStringAsync(); + string imageid = new List(imageurl.Split('/')).Last(); + + return imageurl + "/" + imageid; + } catch { diff --git a/YJMPD-UWP/ViewModels/PhotoVM.cs b/YJMPD-UWP/ViewModels/PhotoVM.cs index 583a089..149a91a 100644 --- a/YJMPD-UWP/ViewModels/PhotoVM.cs +++ b/YJMPD-UWP/ViewModels/PhotoVM.cs @@ -1,20 +1,49 @@ -using Windows.UI.Xaml.Media; +using System; +using System.Diagnostics; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Media; +using Windows.UI.Xaml.Media.Imaging; namespace YJMPD_UWP.ViewModels { public class PhotoVM : TemplateVM { - private ImageSource photo; + private string photo; + + DispatcherTimer timer; + int secondsleft = 60; public PhotoVM() : base("Photo") { App.Photo.OnPhotoTaken += Photo_OnPhotoTaken; + photo = App.Photo.Photo; + + timer = new DispatcherTimer(); + timer.Interval = TimeSpan.FromSeconds(1); + timer.Tick += Timer_Tick; + + if (ControlsVisible) + timer.Start(); + } + + private void Timer_Tick(object sender, object e) + { + NotifyPropertyChanged(nameof(TimeOut)); + + secondsleft--; + if(secondsleft <= 0) + { + App.Game.Stop(); + } } private void Photo_OnPhotoTaken(object sender, Helpers.EventArgs.PhotoTakenEventArgs e) { dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => { + timer.Stop(); + secondsleft = 60; + photo = e.Photo; NotifyPropertyChanged(nameof(Photo)); NotifyPropertyChanged(nameof(PhotoVisible)); @@ -42,7 +71,7 @@ namespace YJMPD_UWP.ViewModels { get { - return "Take a photo within 1 minute"; + return "Take a photo within " + secondsleft + " seconds"; } } @@ -50,7 +79,10 @@ namespace YJMPD_UWP.ViewModels { get { - return photo; + if (photo == null || photo == "") + return new BitmapImage(new Uri("ms-appx:///Assets/Error.png")); + + return new BitmapImage(new Uri(photo)); } } } diff --git a/YJMPD-UWP/Views/PhotoView.xaml b/YJMPD-UWP/Views/PhotoView.xaml index 08dfff9..4a5fe53 100644 --- a/YJMPD-UWP/Views/PhotoView.xaml +++ b/YJMPD-UWP/Views/PhotoView.xaml @@ -11,14 +11,14 @@ - - - - - - -