From 4a22922ce69b9140769323351585df10d84e7196 Mon Sep 17 00:00:00 2001 From: Matteo Cominetti Date: Tue, 21 Jul 2015 13:37:13 +0200 Subject: [PATCH 1/2] Fixed preview in Design Mode, added version check using GitHub Release API --- Bcfier/Api/GitHubAsset.cs | 25 +++++ Bcfier/Api/GitHubAuthor.cs | 29 ++++++ Bcfier/Api/GitHubRelease.cs | 29 ++++++ Bcfier/Api/GitHubRest.cs | 83 +++++++++++++++ Bcfier/Bcf/BcfFile.cs | 108 ++++++++++---------- Bcfier/Bcfier.csproj | 7 ++ Bcfier/DesignTimeClasses/SampleBcfFile.xaml | 90 ++++++++-------- Bcfier/UserControls/BcfReportPanel.xaml | 2 +- Bcfier/UserControls/BcfReportPanel.xaml.cs | 5 + Bcfier/UserControls/BcfierPanel.xaml | 3 +- Bcfier/UserControls/BcfierPanel.xaml.cs | 63 ++++++------ Bcfier/Windows/NewVersion.xaml | 6 +- Bcfier/packages.config | 2 +- 13 files changed, 320 insertions(+), 132 deletions(-) create mode 100644 Bcfier/Api/GitHubAsset.cs create mode 100644 Bcfier/Api/GitHubAuthor.cs create mode 100644 Bcfier/Api/GitHubRelease.cs create mode 100644 Bcfier/Api/GitHubRest.cs diff --git a/Bcfier/Api/GitHubAsset.cs b/Bcfier/Api/GitHubAsset.cs new file mode 100644 index 00000000..b86e07a5 --- /dev/null +++ b/Bcfier/Api/GitHubAsset.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Bcfier.Api +{ + public class GitHubAsset + { + public string url { get; set; } + public int id { get; set; } + public string name { get; set; } + public object label { get; set; } + public GitHubAuthor uploader { get; set; } + public string content_type { get; set; } + public string state { get; set; } + public int size { get; set; } + public int download_count { get; set; } + public string created_at { get; set; } + public string updated_at { get; set; } + public string browser_download_url { get; set; } +} + } + diff --git a/Bcfier/Api/GitHubAuthor.cs b/Bcfier/Api/GitHubAuthor.cs new file mode 100644 index 00000000..7aeb2ce3 --- /dev/null +++ b/Bcfier/Api/GitHubAuthor.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Bcfier.Api +{ + public class GitHubAuthor + { + public string login { get; set; } + public int id { get; set; } + public string avatar_url { get; set; } + public string gravatar_id { get; set; } + public string url { get; set; } + public string html_url { get; set; } + public string followers_url { get; set; } + public string following_url { get; set; } + public string gists_url { get; set; } + public string starred_url { get; set; } + public string subscriptions_url { get; set; } + public string organizations_url { get; set; } + public string repos_url { get; set; } + public string events_url { get; set; } + public string received_events_url { get; set; } + public string type { get; set; } + public bool site_admin { get; set; } + } +} diff --git a/Bcfier/Api/GitHubRelease.cs b/Bcfier/Api/GitHubRelease.cs new file mode 100644 index 00000000..97d55eab --- /dev/null +++ b/Bcfier/Api/GitHubRelease.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Bcfier.Api +{ + public class GitHubRelease + { + public string url { get; set; } + public string assets_url { get; set; } + public string upload_url { get; set; } + public string html_url { get; set; } + public int id { get; set; } + public string tag_name { get; set; } + public string target_commitish { get; set; } + public string name { get; set; } + public bool draft { get; set; } + public GitHubAuthor author { get; set; } + public bool prerelease { get; set; } + public DateTime created_at { get; set; } + public DateTime published_at { get; set; } + public List assets { get; set; } + public string tarball_url { get; set; } + public string zipball_url { get; set; } + public string body { get; set; } + } +} \ No newline at end of file diff --git a/Bcfier/Api/GitHubRest.cs b/Bcfier/Api/GitHubRest.cs new file mode 100644 index 00000000..c76d70bf --- /dev/null +++ b/Bcfier/Api/GitHubRest.cs @@ -0,0 +1,83 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Windows; +using RestSharp; +using DataFormat = RestSharp.DataFormat; + +namespace Bcfier.Api +{ + public static class GitHubRest + { + internal static RestClient Client + { + get { return new RestClient(@"https://api.github.com/"); } + } + + internal static async Task> GetReleases(CancellationTokenSource cancel) + { + if (cancel.IsCancellationRequested) + return null; + + + var request = new RestRequest("repos/teocomi/bcfier/releases?access_token=ef85819857533da4a216df2ae8e6db642827e922", Method.GET); + request.AddHeader("Content-Type", "application/json"); + request.RequestFormat = DataFormat.Json; + request.OnBeforeDeserialization = resp => { resp.ContentType = "application/json"; }; + + var response = await DoTaskAsync>(request, cancel); + + return cancel.IsCancellationRequested || !CheckResponse(response, HttpStatusCode.OK) ? null : response.Data; + } + internal static async Task GetLatestRelease(CancellationTokenSource cancel) + { + if (cancel.IsCancellationRequested) + return null; + + + var request = new RestRequest("repos/teocomi/bcfier/releases/latest?access_token=ef85819857533da4a216df2ae8e6db642827e922", Method.GET); + request.AddHeader("Content-Type", "application/json"); + request.RequestFormat = DataFormat.Json; + + var response = await DoTaskAsync(request, cancel); + //if cancellation oending or invalid reponse return null, otherwise the data + return cancel.IsCancellationRequested || !CheckResponse(response, HttpStatusCode.OK) ? null : response.Data; + } + + private static async Task> DoTaskAsync(RestRequest request, CancellationTokenSource cancel) where T : class + { + IRestResponse response = null; + try + { + if (cancel != null) + response = await Client.ExecuteTaskAsync(request, cancel.Token); + } + catch (OperationCanceledException ex) + { + var gg = ex.Data; + return null; + } + return response; + } + + private static bool CheckResponse(IRestResponse response, HttpStatusCode expectedCode) + { + try + { + if (null == response || response.StatusCode != expectedCode) + return false; + } + catch (Exception ex1) + { + MessageBox.Show("exception: " + ex1); + } + return true; + } + + + } +} diff --git a/Bcfier/Bcf/BcfFile.cs b/Bcfier/Bcf/BcfFile.cs index 1c63e6b9..586fcb27 100644 --- a/Bcfier/Bcf/BcfFile.cs +++ b/Bcfier/Bcf/BcfFile.cs @@ -33,8 +33,6 @@ public BcfFile() Id = Guid.NewGuid(); TempPath = System.IO.Path.Combine(System.IO.Path.GetTempPath(), "BCFier", Id.ToString()); Issues = new ObservableCollection(); - this._view = new ListCollectionView(this.Issues); - } public bool HasBeenSaved { @@ -84,6 +82,7 @@ public ObservableCollection Issues set { _issues = value; + this._view = new ListCollectionView(this.Issues); NotifyPropertyChanged("Issues"); } } @@ -102,12 +101,15 @@ public Markup SelectedIssue } } - + public ICollectionView View { - get { return this._view; } + get + { + return this._view; + } } - + public string TextSearch { get { return _textSearch; } @@ -125,13 +127,13 @@ public string TextSearch private bool Filter(object o) { - var issue = (Markup) o; + var issue = (Markup)o; if (issue == null) return false; if (issue.Topic != null && ((issue.Topic.Title != null && issue.Topic.Title.ToLowerInvariant().Contains(TextSearch.ToLowerInvariant())) || - ( issue.Topic.Description != null && issue.Topic.Description.ToLowerInvariant().Contains(TextSearch.ToLowerInvariant()))) || + (issue.Topic.Description != null && issue.Topic.Description.ToLowerInvariant().Contains(TextSearch.ToLowerInvariant()))) || issue.Comment != null && issue.Comment.Any(x => x.Comment1.ToLowerInvariant().Contains(TextSearch.ToLowerInvariant())) - + ) return true; return false; @@ -171,7 +173,7 @@ public void RemoveView(ViewPoint view, Markup issue, bool delComm) var guid = view.Guid; issue.Viewpoints.Remove(view); //remove comments associated with that view - var viewcomments = issue.Comment.Where(x => x.Viewpoint!=null && x.Viewpoint.Guid == guid).ToList(); + var viewcomments = issue.Comment.Where(x => x.Viewpoint != null && x.Viewpoint.Guid == guid).ToList(); if (!viewcomments.Any()) return; @@ -220,61 +222,61 @@ public void MergeBcfFile(IEnumerable bcfFiles) { foreach (var bcf in bcfFiles) + { + foreach (var mergedIssue in bcf.Issues) { - foreach (var mergedIssue in bcf.Issues) + //it's a new issue + if (!Issues.Any(x => x.Topic != null && mergedIssue.Topic != null && x.Topic.Guid == mergedIssue.Topic.Guid)) { - //it's a new issue - if (!Issues.Any(x => x.Topic!=null && mergedIssue.Topic!=null && x.Topic.Guid == mergedIssue.Topic.Guid)) + string sourceDir = Path.Combine(bcf.TempPath, mergedIssue.Topic.Guid); + string destDir = Path.Combine(TempPath, mergedIssue.Topic.Guid); + + Directory.Move(sourceDir, destDir); + //update path set for binding + foreach (var view in mergedIssue.Viewpoints) { - string sourceDir = Path.Combine(bcf.TempPath, mergedIssue.Topic.Guid); - string destDir = Path.Combine(TempPath, mergedIssue.Topic.Guid); + view.SnapshotPath = Path.Combine(TempPath, mergedIssue.Topic.Guid, view.Snapshot); + } + Issues.Add(mergedIssue); - Directory.Move(sourceDir, destDir); - //update path set for binding - foreach (var view in mergedIssue.Viewpoints) + } + //it exists, let's loop comments and views + else + { + var issue = Issues.First(x => x.Topic.Guid == mergedIssue.Topic.Guid); + var newComments = mergedIssue.Comment.Where(x => issue.Comment.All(y => y.Guid != x.Guid)).ToList(); + if (newComments.Any()) + foreach (var newComment in newComments) + issue.Comment.Add(newComment); + //sort comments + issue.Comment = new ObservableCollection(issue.Comment.OrderByDescending(x => x.Date)); + + var newViews = mergedIssue.Viewpoints.Where(x => issue.Viewpoints.All(y => y.Guid != x.Guid)).ToList(); + if (newViews.Any()) + foreach (var newView in newViews) { - view.SnapshotPath = Path.Combine(TempPath, mergedIssue.Topic.Guid, view.Snapshot); + //to avoid conflicts in case both contain a snapshot.png or viewpoint.bcfv + //img to be merged + string sourceFile = newView.SnapshotPath; + //assign new safe name based on guid + newView.Snapshot = newView.Guid + ".png"; + //set new temp path for binding + newView.SnapshotPath = Path.Combine(TempPath, issue.Topic.Guid, newView.Snapshot); + //assign new safe name based on guid + newView.Viewpoint = newView.Guid + ".bcfv"; + File.Move(sourceFile, newView.SnapshotPath); + issue.Viewpoints.Add(newView); + + } - Issues.Add(mergedIssue); - - } - //it exists, let's loop comments and views - else - { - var issue = Issues.First(x => x.Topic.Guid == mergedIssue.Topic.Guid); - var newComments = mergedIssue.Comment.Where(x => issue.Comment.All(y => y.Guid != x.Guid)).ToList(); - if(newComments.Any()) - foreach (var newComment in newComments) - issue.Comment.Add(newComment); - //sort comments - issue.Comment = new ObservableCollection(issue.Comment.OrderByDescending(x=>x.Date)); - - var newViews = mergedIssue.Viewpoints.Where(x => issue.Viewpoints.All(y => y.Guid != x.Guid)).ToList(); - if (newViews.Any()) - foreach (var newView in newViews) - { - //to avoid conflicts in case both contain a snapshot.png or viewpoint.bcfv - //img to be merged - string sourceFile = newView.SnapshotPath; - //assign new safe name based on guid - newView.Snapshot = newView.Guid + ".png"; - //set new temp path for binding - newView.SnapshotPath = Path.Combine(TempPath, issue.Topic.Guid, newView.Snapshot); - //assign new safe name based on guid - newView.Viewpoint = newView.Guid + ".bcfv"; - File.Move(sourceFile, newView.SnapshotPath); - issue.Viewpoints.Add(newView); - - - } - } } - Utils.DeleteDirectory(bcf.TempPath); } + Utils.DeleteDirectory(bcf.TempPath); + } HasBeenSaved = false; - + } catch (System.Exception ex1) { diff --git a/Bcfier/Bcfier.csproj b/Bcfier/Bcfier.csproj index 70c2aaae..44c8768a 100644 --- a/Bcfier/Bcfier.csproj +++ b/Bcfier/Bcfier.csproj @@ -54,6 +54,9 @@ + + ..\packages\RestSharp.105.1.0\lib\net45\RestSharp.dll + @@ -73,6 +76,10 @@ + + + + diff --git a/Bcfier/DesignTimeClasses/SampleBcfFile.xaml b/Bcfier/DesignTimeClasses/SampleBcfFile.xaml index b52b4eb5..6c7a0029 100644 --- a/Bcfier/DesignTimeClasses/SampleBcfFile.xaml +++ b/Bcfier/DesignTimeClasses/SampleBcfFile.xaml @@ -1,51 +1,55 @@ - + - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - + - - + + \ No newline at end of file diff --git a/Bcfier/UserControls/BcfReportPanel.xaml b/Bcfier/UserControls/BcfReportPanel.xaml index 18643366..48db8b81 100644 --- a/Bcfier/UserControls/BcfReportPanel.xaml +++ b/Bcfier/UserControls/BcfReportPanel.xaml @@ -43,7 +43,7 @@ - - + + diff --git a/Bcfier/UserControls/BcfierPanel.xaml.cs b/Bcfier/UserControls/BcfierPanel.xaml.cs index d71f8013..e02fae6a 100644 --- a/Bcfier/UserControls/BcfierPanel.xaml.cs +++ b/Bcfier/UserControls/BcfierPanel.xaml.cs @@ -5,10 +5,12 @@ using System.IO; using System.Linq; using System.Net; +using System.Threading; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Xml.Linq; +using Bcfier.Api; using Bcfier.Bcf; using Bcfier.Bcf.Bcf2; using Bcfier.Data.Utils; @@ -34,6 +36,7 @@ public BcfierPanel() //top menu buttons and events NewBcfBtn.Click += delegate { _bcf.NewFile(); OnAddIssue(null,null);}; OpenBcfBtn.Click += delegate { _bcf.OpenFile(); }; + OpenProjectBtn.Click += OnOpenWebProject; SaveBcfBtn.Click += delegate { _bcf.SaveFile(SelectedBcf()); }; MergeBcfBtn.Click += delegate { _bcf.MergeFiles(SelectedBcf()); }; SettingsBtn.Click += delegate @@ -337,6 +340,11 @@ private void CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs #endregion #region events + private void OnOpenWebProject(object sender, RoutedEventArgs routedEventArgs) + { + + } + public void BcfFileClicked (string path) { _bcf.OpenFile(path); @@ -376,42 +384,37 @@ private void HelpBtnOnClick(object sender, RoutedEventArgs routedEventArgs) #endregion #region web - private void CheckUpdates() + private async void CheckUpdates() { - var webClient = new WebClient(); - webClient.DownloadStringCompleted += DownloadUpdateComplete; - webClient.DownloadStringAsync(new Uri(@"https://raw.githubusercontent.com/teocomi/BCFier/master/bcfier-update.xml")); - } - //Could be serialized to a class that binds to the UI - //Could use a json instad than XML - private void DownloadUpdateComplete(object sender, DownloadStringCompletedEventArgs e) - { - try + try { - if (e.Error == null) - { - var document = XDocument.Parse(e.Result); - string version = document.Element("Bcfier").Element("Version").Value; + var cancel = new CancellationTokenSource(); + var release = await GitHubRest.GetLatestRelease(cancel); + if (release == null) + return; - if (System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.CompareTo(Version.Parse(version)) < 0) - { - var dialog = new NewVersion(); - dialog.Description.Text = "Version " + version + " is available,\ndo you want to check it out now?"; - dialog.NewFeatures.Text = document.Element("Bcfier").Element("Changelog").Element("NewFeatures").Value; - dialog.BugFixes.Text = document.Element("Bcfier").Element("Changelog").Element("BugFixes").Value; - dialog.WindowStartupLocation = WindowStartupLocation.CenterScreen; - dialog.ShowDialog(); - if(dialog.DialogResult.HasValue && dialog.DialogResult.Value) - Process.Start(document.Element("Bcfier").Element("URL").Value); - } - } - } - catch (System.Exception ex1) + string version = release.tag_name.Replace("v",""); + + if (System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.CompareTo(Version.Parse(version)) < 0 && release.assets.Any()) { - //warning suppressed - Console.WriteLine("exception: " + ex1); + var dialog = new NewVersion(); + dialog.WindowStartupLocation = WindowStartupLocation.CenterScreen; + dialog.Description.Text = release.name + " has been released on "+ release.published_at.ToLongDateString()+"\ndo you want to check it out now?"; + //dialog.NewFeatures.Text = document.Element("Bcfier").Element("Changelog").Element("NewFeatures").Value; + //dialog.BugFixes.Text = document.Element("Bcfier").Element("Changelog").Element("BugFixes").Value; + //dialog.WindowStartupLocation = WindowStartupLocation.CenterScreen; + dialog.ShowDialog(); + if (dialog.DialogResult.HasValue && dialog.DialogResult.Value) + Process.Start(release.assets.First().browser_download_url); + } } + catch (System.Exception ex1) + { + //warning suppressed + Console.WriteLine("exception: " + ex1); + } } + #endregion #region drag&drop private void Window_DragEnter(object sender, DragEventArgs e) diff --git a/Bcfier/Windows/NewVersion.xaml b/Bcfier/Windows/NewVersion.xaml index a46d8069..7c2e0e97 100644 --- a/Bcfier/Windows/NewVersion.xaml +++ b/Bcfier/Windows/NewVersion.xaml @@ -1,7 +1,7 @@  + Title="A new BCFier is available!" SizeToContent="WidthAndHeight" MinWidth="300" Icon="../Assets/icon.ico"> @@ -11,12 +11,12 @@ - +