From da0f3d53a5805752298a7c019eb9e2d44175ab33 Mon Sep 17 00:00:00 2001 From: Hylke Bons Date: Sun, 14 Oct 2012 14:21:22 +0100 Subject: [PATCH] early working version of history recycle logic + mac Save As dialog --- SparkleLib/Git/SparkleRepoGit.cs | 23 ++-- SparkleLib/SparkleRepoBase.cs | 2 +- SparkleLib/SparkleWrappers.cs | 1 + SparkleShare/Common/HTML/event-log.html | 49 ++++++++- SparkleShare/Mac/SparkleEventLog.cs | 24 +++- SparkleShare/SparkleEventLogController.cs | 128 +++++++++++++++++++++- 6 files changed, 214 insertions(+), 13 deletions(-) diff --git a/SparkleLib/Git/SparkleRepoGit.cs b/SparkleLib/Git/SparkleRepoGit.cs index b92e7e89..96caf38d 100644 --- a/SparkleLib/Git/SparkleRepoGit.cs +++ b/SparkleLib/Git/SparkleRepoGit.cs @@ -539,7 +539,7 @@ namespace SparkleLib.Git { } - public override void RevertFile (string path, string revision) + public override void RestoreFile (string path, string revision, string target_file_path) { if (path == null) throw new ArgumentNullException ("path"); @@ -614,7 +614,7 @@ namespace SparkleLib.Git { path = path.Replace ("\\", "/"); git = new SparkleGit (LocalPath, "log -" + count + " --raw --find-renames --date=iso " + - "--format=medium --no-color --no-merges -- " + path); + "--format=medium --no-color --no-merges -- \"" + path + "\""); } string output = git.StartAndReadStandardOutput (); @@ -681,13 +681,16 @@ namespace SparkleLib.Git { if (entry_line.StartsWith (":")) { string type_letter = entry_line [37].ToString (); string file_path = entry_line.Substring (39); - - if (file_path.EndsWith (".empty")) - file_path = file_path.Substring (0, file_path.Length - ".empty".Length); + bool change_is_folder = false; if (file_path.Equals (".sparkleshare")) continue; + if (file_path.EndsWith (".empty")) { + file_path = file_path.Substring (0, file_path.Length - ".empty".Length); + change_is_folder = true; + } + file_path = EnsureSpecialCharacters (file_path); file_path = file_path.Replace ("\\\"", "\""); @@ -702,15 +705,20 @@ namespace SparkleLib.Git { file_path = file_path.Replace ("\\\"", "\""); to_file_path = to_file_path.Replace ("\\\"", "\""); - if (file_path.EndsWith (".empty")) + if (file_path.EndsWith (".empty")) { file_path = file_path.Substring (0, file_path.Length - 6); + change_is_folder = true; + } - if (to_file_path.EndsWith (".empty")) + if (to_file_path.EndsWith (".empty")) { to_file_path = to_file_path.Substring (0, to_file_path.Length - 6); + change_is_folder = true; + } change_set.Changes.Add ( new SparkleChange () { Path = file_path, + IsFolder = change_is_folder, MovedToPath = to_file_path, Timestamp = change_set.Timestamp, Type = SparkleChangeType.Moved @@ -730,6 +738,7 @@ namespace SparkleLib.Git { change_set.Changes.Add ( new SparkleChange () { Path = file_path, + IsFolder = change_is_folder, Timestamp = change_set.Timestamp, Type = change_type } diff --git a/SparkleLib/SparkleRepoBase.cs b/SparkleLib/SparkleRepoBase.cs index f0b26be6..4c0e4ec3 100755 --- a/SparkleLib/SparkleRepoBase.cs +++ b/SparkleLib/SparkleRepoBase.cs @@ -56,7 +56,7 @@ namespace SparkleLib { public abstract bool SyncDown (); public abstract List GetChangeSets (int count); public abstract List GetChangeSets (string path, int count); - public abstract void RevertFile (string path, string revision); + public abstract void RestoreFile (string path, string revision, string target_file_path); public event SyncStatusChangedEventHandler SyncStatusChanged = delegate { }; public delegate void SyncStatusChangedEventHandler (SyncStatus new_status); diff --git a/SparkleLib/SparkleWrappers.cs b/SparkleLib/SparkleWrappers.cs index bf60ddcf..6e328ae5 100644 --- a/SparkleLib/SparkleWrappers.cs +++ b/SparkleLib/SparkleWrappers.cs @@ -47,6 +47,7 @@ namespace SparkleLib { public SparkleChangeType Type; public DateTime Timestamp; + public bool IsFolder = false; public string Path; public string MovedToPath; diff --git a/SparkleShare/Common/HTML/event-log.html b/SparkleShare/Common/HTML/event-log.html index 368d5722..0e5bd3ab 100755 --- a/SparkleShare/Common/HTML/event-log.html +++ b/SparkleShare/Common/HTML/event-log.html @@ -76,7 +76,7 @@ cursor: pointer; } - small { + small, small a { font-size: ; color: ; } @@ -152,7 +152,52 @@ .moved { background-image: url(''); - } + } + + table { + padding: 18px 32px; + width: 100%; + } + + td { + padding: 0; + margin: 0; + } + + td.name { + width: 45%; + } + + td.time { + font-size: ; + color: ; + padding-right: 9px; + width: 20px; + padding-top: 2px; + } + + td.date { + font-size: ; + color: ; + text-align: right; + padding-right: 6px; + padding-top: 2px; + } + + td.restore { + text-align: right; + } + + td.avatar { + width: 32px; + } + + td.avatar img { + margin-top: 2px; + border-radius: 3px; + width: 24px; + height: 24px; + } diff --git a/SparkleShare/Mac/SparkleEventLog.cs b/SparkleShare/Mac/SparkleEventLog.cs index 34cd8b8e..cdf4fe48 100755 --- a/SparkleShare/Mac/SparkleEventLog.cs +++ b/SparkleShare/Mac/SparkleEventLog.cs @@ -228,7 +228,7 @@ namespace SparkleShare { }); } }; - + Controller.UpdateSizeInfoEvent += delegate (string size, string history_size) { using (var a = new NSAutoreleasePool ()) { @@ -238,6 +238,27 @@ namespace SparkleShare { }); } }; + + Controller.ShowSaveDialogEvent += delegate (string file_name, string target_folder_path) { + using (var a = new NSAutoreleasePool ()) + { + InvokeOnMainThread (() => { + // TODO: Make this a sheet + NSSavePanel panel = new NSSavePanel () { + DirectoryUrl = new NSUrl (target_folder_path, true), + NameFieldStringValue = file_name, + ParentWindow = this, + Title = "Restore from History", + PreventsApplicationTerminationWhenModal = false + }; + + if ((NSPanelButtonType) panel.RunModal ()== NSPanelButtonType.Ok) + Controller.SaveDialogCompleted ("f"); + else + Controller.SaveDialogCancelled (); + }); + } + }; } @@ -346,6 +367,7 @@ namespace SparkleShare { html = html.Replace ("", "13.4px"); html = html.Replace ("", "#bbb"); html = html.Replace ("", "#ddd"); + html = html.Replace ("", "10px"); html = html.Replace ("", "#f5f5f5"); html = html.Replace ("", "#0085cf"); html = html.Replace ("", "#009ff8"); diff --git a/SparkleShare/SparkleEventLogController.cs b/SparkleShare/SparkleEventLogController.cs index e6b7d5e7..67540d09 100755 --- a/SparkleShare/SparkleEventLogController.cs +++ b/SparkleShare/SparkleEventLogController.cs @@ -19,6 +19,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; +using System.Text.RegularExpressions; using System.Threading; using SparkleLib; @@ -36,12 +37,16 @@ namespace SparkleShare { public event UpdateChooserEventHandler UpdateChooserEvent = delegate { }; public delegate void UpdateChooserEventHandler (string [] folders); - + public event UpdateSizeInfoEventHandler UpdateSizeInfoEvent = delegate { }; public delegate void UpdateSizeInfoEventHandler (string size, string history_size); + + public event ShowSaveDialogEventHandler ShowSaveDialogEvent = delegate { }; + public delegate void ShowSaveDialogEventHandler (string file_name, string target_folder_path); private string selected_folder; + private RevisionInfo restore_revision_info; public bool WindowIsOpen { get; private set; } @@ -220,10 +225,113 @@ namespace SparkleShare { } else if (url.StartsWith ("http")) { Program.Controller.OpenWebsite (url); + + + } else if (url.StartsWith ("restore://") && this.restore_revision_info == null) { + Regex regex = new Regex ("restore://(.+)/([a-f0-9]+)/(.+)", RegexOptions.Compiled); + Match match = regex.Match (url); + + if (match.Success) { + this.restore_revision_info = new RevisionInfo () { + Folder = new SparkleFolder (match.Groups [1].Value), + Revision = match.Groups [2].Value, + FilePath = match.Groups [3].Value + }; + + string file_name = Path.GetFileNameWithoutExtension (this.restore_revision_info.FilePath) + + " (restored)" + Path.GetExtension (this.restore_revision_info.FilePath); + + string target_folder_path = Path.Combine (this.restore_revision_info.Folder.FullPath, + Path.GetDirectoryName (this.restore_revision_info.FilePath)); + + ShowSaveDialogEvent (file_name, target_folder_path); + + } else { + // TODO: remove + Program.UI.Bubbles.Controller.ShowBubble ("no match", url, ""); + } + + + } else if (url.StartsWith ("history://")) { + string html = ""; + string folder = url.Replace ("history://", "").Split ("/".ToCharArray ()) [0]; + string path = url.Replace ("history://" + folder + "/", ""); + + // TODO: put html into page + + foreach (SparkleRepoBase repo in Program.Controller.Repositories) { + if (repo.Name.Equals (folder)) { + List change_sets = repo.GetChangeSets (path, 30); + + html += "
Revisions for “" + + Path.GetFileName (path) + "”
"; + + + html += ""; + + int count = 0; + foreach (SparkleChangeSet change_set in change_sets) { + count++; + if (count == 1) + continue; + + foreach (SparkleChange change in change_set.Changes) { + if (change.Type == SparkleChangeType.Deleted && change.Path.Equals (path)) + continue; // TODO: in repo? + } + + string change_set_avatar = Program.Controller.GetAvatar (change_set.User.Email, 24); + + if (change_set_avatar != null) + change_set_avatar = "file://" + change_set_avatar.Replace ("\\", "/"); + else + change_set_avatar = "file:///user-icon-default.png"; + + html += "" + + "" + + "" + + "" + + "" + + "" + + ""; + + count++; + } + + + html += "
" + change_set.User.Name + "" + change_set.Timestamp.ToString ("d MMM yyyy") + "" + change_set.Timestamp.ToString ("HH:mm") + "Restore...
"; + + break; + } + } + + + UpdateContentEvent (Program.Controller.EventLogHTML.Replace ("", html)); } } + public void SaveDialogCompleted (string target_file_path) + { + foreach (SparkleRepoBase repo in Program.Controller.Repositories) { + if (repo.Name.Equals (this.restore_revision_info.Folder.Name)) { + repo.RestoreFile (this.restore_revision_info.FilePath, + this.restore_revision_info.Revision, target_file_path); + + break; + } + } + + this.restore_revision_info = null; + } + + + public void SaveDialogCancelled () + { + this.restore_revision_info = null; + } + + private List GetLog () { List list = new List (); @@ -307,7 +415,16 @@ namespace SparkleShare { foreach (SparkleChange change in change_set.Changes) { if (change.Type != SparkleChangeType.Moved) { event_entry += "
"; - event_entry += "" + change.Timestamp.ToString ("HH:mm") +"  "; + + if (!change.IsFolder) { + event_entry += "" + change.Timestamp.ToString ("HH:mm") + + "  "; + + } else { + event_entry += "" + change.Timestamp.ToString ("HH:mm") + "  "; + } + event_entry += FormatBreadCrumbs (change_set.Folder.FullPath, change.Path); event_entry += "
"; @@ -444,5 +561,12 @@ namespace SparkleShare { Date = new DateTime (date_time.Year, date_time.Month, date_time.Day); } } + + + private class RevisionInfo { + public SparkleFolder Folder; + public string FilePath; + public string Revision; + } } }