early working version of history recycle logic + mac Save As dialog

This commit is contained in:
Hylke Bons 2012-10-14 14:21:22 +01:00
parent d601521618
commit da0f3d53a5
6 changed files with 214 additions and 13 deletions

View file

@ -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
}

View file

@ -56,7 +56,7 @@ namespace SparkleLib {
public abstract bool SyncDown ();
public abstract List<SparkleChangeSet> GetChangeSets (int count);
public abstract List<SparkleChangeSet> 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);

View file

@ -47,6 +47,7 @@ namespace SparkleLib {
public SparkleChangeType Type;
public DateTime Timestamp;
public bool IsFolder = false;
public string Path;
public string MovedToPath;

View file

@ -76,7 +76,7 @@
cursor: pointer;
}
small {
small, small a {
font-size: <!-- $small-font-size -->;
color: <!-- $secondary-font-color -->;
}
@ -152,7 +152,52 @@
.moved {
background-image: url('<!-- $document-moved-background-image -->');
}
}
table {
padding: 18px 32px;
width: 100%;
}
td {
padding: 0;
margin: 0;
}
td.name {
width: 45%;
}
td.time {
font-size: <!-- $small-font-size -->;
color: <!-- $secondary-font-color -->;
padding-right: 9px;
width: 20px;
padding-top: 2px;
}
td.date {
font-size: <!-- $small-font-size -->;
color: <!-- $secondary-font-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;
}
</style>
</head>
<body oncontextmenu="return false;">

View file

@ -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 ("<!-- $body-font-size -->", "13.4px");
html = html.Replace ("<!-- $secondary-font-color -->", "#bbb");
html = html.Replace ("<!-- $small-color -->", "#ddd");
html = html.Replace ("<!-- $small-font-size -->", "10px");
html = html.Replace ("<!-- $day-entry-header-background-color -->", "#f5f5f5");
html = html.Replace ("<!-- $a-color -->", "#0085cf");
html = html.Replace ("<!-- $a-hover-color -->", "#009ff8");

View file

@ -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<SparkleChangeSet> change_sets = repo.GetChangeSets (path, 30);
html += "<div class='day-entry-header'>Revisions for &ldquo;"
+ Path.GetFileName (path) + "&rdquo;</div>";
html += "<table>";
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://<!-- $pixmaps-path -->/user-icon-default.png";
html += "<tr>" +
"<td class='avatar'><img src='" + change_set_avatar + "'></td>" +
"<td class='name'><b>" + change_set.User.Name + "</b></td>" +
"<td class='date'>" + change_set.Timestamp.ToString ("d MMM yyyy") + "</td>" +
"<td class='time'>" + change_set.Timestamp.ToString ("HH:mm") + "</td>" +
"<td class='restore'><a href='restore://" + change_set.Folder.Name + "/" + change_set.Revision + "/" + path + "' title='restore://" + change_set.Folder.Name + "/" + change_set.Revision + "/" + path + "'>Restore...</a></td>" +
"</tr>";
count++;
}
html += "</table>";
break;
}
}
UpdateContentEvent (Program.Controller.EventLogHTML.Replace ("<!-- $event-log-content -->", 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<SparkleChangeSet> GetLog ()
{
List<SparkleChangeSet> list = new List<SparkleChangeSet> ();
@ -307,7 +415,16 @@ namespace SparkleShare {
foreach (SparkleChange change in change_set.Changes) {
if (change.Type != SparkleChangeType.Moved) {
event_entry += "<dd class='" + change.Type.ToString ().ToLower () + "'>";
event_entry += "<small>" + change.Timestamp.ToString ("HH:mm") +"</small> &nbsp;";
if (!change.IsFolder) {
event_entry += "<small><a href=\"history://" + change_set.Folder.Name + "/" +
change.Path + "\" title=\"View revisions\">" + change.Timestamp.ToString ("HH:mm") +
"</a></small> &nbsp;";
} else {
event_entry += "<small>" + change.Timestamp.ToString ("HH:mm") + "</small> &nbsp;";
}
event_entry += FormatBreadCrumbs (change_set.Folder.FullPath, change.Path);
event_entry += "</dd>";
@ -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;
}
}
}