Merge branch 'invites'
This commit is contained in:
commit
419ad68a8d
|
@ -42,6 +42,7 @@ namespace SparkleLib {
|
|||
public string RemoteUrl;
|
||||
public string [] ExcludeRules;
|
||||
public string [] Warnings;
|
||||
public bool IsActive { get; private set; }
|
||||
|
||||
private Thread thread;
|
||||
|
||||
|
@ -50,6 +51,7 @@ namespace SparkleLib {
|
|||
{
|
||||
TargetFolder = target_folder;
|
||||
RemoteUrl = server + "/" + remote_folder;
|
||||
IsActive = false;
|
||||
|
||||
ExcludeRules = new string [] {
|
||||
// gedit and emacs
|
||||
|
@ -125,6 +127,7 @@ namespace SparkleLib {
|
|||
// Clones the remote repository
|
||||
public void Start ()
|
||||
{
|
||||
IsActive = true;
|
||||
SparkleHelpers.DebugInfo ("Fetcher", "[" + TargetFolder + "] Fetching folder: " + RemoteUrl);
|
||||
|
||||
if (Started != null)
|
||||
|
@ -149,6 +152,7 @@ namespace SparkleLib {
|
|||
SparkleHelpers.DebugInfo ("Fetcher", "Finished");
|
||||
|
||||
EnableHostKeyCheckingForHost (host);
|
||||
IsActive = false;
|
||||
|
||||
if (Finished != null)
|
||||
Finished (Warnings);
|
||||
|
@ -157,6 +161,7 @@ namespace SparkleLib {
|
|||
SparkleHelpers.DebugInfo ("Fetcher", "Failed");
|
||||
|
||||
EnableHostKeyCheckingForHost (host);
|
||||
IsActive = false;
|
||||
|
||||
if (Failed != null)
|
||||
Failed ();
|
||||
|
|
|
@ -33,7 +33,7 @@ namespace SparkleShare {
|
|||
public SparkleSetupController Controller = new SparkleSetupController ();
|
||||
|
||||
private NSButton ContinueButton;
|
||||
private NSButton SyncButton;
|
||||
private NSButton AddButton;
|
||||
private NSButton TryAgainButton;
|
||||
private NSButton CancelButton;
|
||||
private NSButton SkipTutorialButton;
|
||||
|
@ -65,6 +65,18 @@ namespace SparkleShare {
|
|||
|
||||
public SparkleSetup () : base ()
|
||||
{
|
||||
Controller.HideWindowEvent += delegate {
|
||||
InvokeOnMainThread (delegate {
|
||||
PerformClose (this);
|
||||
});
|
||||
};
|
||||
|
||||
Controller.ShowWindowEvent += delegate {
|
||||
InvokeOnMainThread (delegate {
|
||||
OrderFrontRegardless ();
|
||||
});
|
||||
};
|
||||
|
||||
Controller.ChangePageEvent += delegate (PageType type, string [] warnings) {
|
||||
InvokeOnMainThread (delegate {
|
||||
Reset ();
|
||||
|
@ -72,6 +84,7 @@ namespace SparkleShare {
|
|||
switch (type) {
|
||||
case PageType.Setup: {
|
||||
|
||||
// TODO: Improve text
|
||||
Header = "Welcome to SparkleShare!";
|
||||
Description = "We'll need some info to mark your changes in the event log. " +
|
||||
"Don't worry, this stays between you and your peers.";
|
||||
|
@ -159,10 +172,85 @@ namespace SparkleShare {
|
|||
break;
|
||||
}
|
||||
|
||||
case PageType.Invite: {
|
||||
|
||||
Header = "You've received an invite!";
|
||||
Description = "Do you want to add this project to SparkleShare?";
|
||||
|
||||
|
||||
AddressLabel = new NSTextField () {
|
||||
Alignment = NSTextAlignment.Right,
|
||||
BackgroundColor = NSColor.WindowBackground,
|
||||
Bordered = false,
|
||||
Editable = false,
|
||||
Frame = new RectangleF (165, Frame.Height - 240, 160, 17),
|
||||
StringValue = "Address:",
|
||||
Font = SparkleUI.Font
|
||||
};
|
||||
|
||||
PathLabel = new NSTextField () {
|
||||
Alignment = NSTextAlignment.Right,
|
||||
BackgroundColor = NSColor.WindowBackground,
|
||||
Bordered = false,
|
||||
Editable = false,
|
||||
Frame = new RectangleF (165, Frame.Height - 264, 160, 17),
|
||||
StringValue = "Remote Path:",
|
||||
Font = SparkleUI.Font
|
||||
};
|
||||
|
||||
AddressTextField = new NSTextField () {
|
||||
Alignment = NSTextAlignment.Left,
|
||||
BackgroundColor = NSColor.WindowBackground,
|
||||
Bordered = false,
|
||||
Editable = false,
|
||||
Frame = new RectangleF (330, Frame.Height - 240, 260, 17),
|
||||
StringValue = Controller.PendingInvite.Address,
|
||||
Font = SparkleUI.BoldFont
|
||||
};
|
||||
|
||||
PathTextField = new NSTextField () {
|
||||
Alignment = NSTextAlignment.Left,
|
||||
BackgroundColor = NSColor.WindowBackground,
|
||||
Bordered = false,
|
||||
Editable = false,
|
||||
Frame = new RectangleF (330, Frame.Height - 264, 260, 17),
|
||||
StringValue = Controller.PendingInvite.RemotePath,
|
||||
Font = SparkleUI.BoldFont
|
||||
};
|
||||
|
||||
|
||||
ContentView.AddSubview (AddressLabel);
|
||||
ContentView.AddSubview (PathLabel);
|
||||
ContentView.AddSubview (AddressTextField);
|
||||
ContentView.AddSubview (PathTextField);
|
||||
|
||||
|
||||
CancelButton = new NSButton () {
|
||||
Title = "Cancel"
|
||||
};
|
||||
|
||||
CancelButton.Activated += delegate {
|
||||
Controller.PageCancelled ();
|
||||
};
|
||||
|
||||
AddButton = new NSButton () {
|
||||
Title = "Add"
|
||||
};
|
||||
|
||||
AddButton.Activated += delegate {
|
||||
Controller.InvitePageCompleted ();
|
||||
};
|
||||
|
||||
Buttons.Add (AddButton);
|
||||
Buttons.Add (CancelButton);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case PageType.Add: {
|
||||
|
||||
Header = "Where's your project hosted?";
|
||||
Description = "";
|
||||
Header = "Where's your project hosted?";
|
||||
Description = "";
|
||||
|
||||
AddressLabel = new NSTextField () {
|
||||
Alignment = NSTextAlignment.Left,
|
||||
|
@ -171,7 +259,7 @@ namespace SparkleShare {
|
|||
Editable = false,
|
||||
Frame = new RectangleF (190, Frame.Height - 308, 160, 17),
|
||||
StringValue = "Address:",
|
||||
Font = SparkleUI.Font
|
||||
Font = SparkleUI.BoldFont
|
||||
};
|
||||
|
||||
AddressTextField = new NSTextField () {
|
||||
|
@ -190,7 +278,7 @@ namespace SparkleShare {
|
|||
Editable = false,
|
||||
Frame = new RectangleF (190 + 196 + 16, Frame.Height - 308, 160, 17),
|
||||
StringValue = "Remote Path:",
|
||||
Font = SparkleUI.Font
|
||||
Font = SparkleUI.BoldFont
|
||||
};
|
||||
|
||||
PathTextField = new NSTextField () {
|
||||
|
@ -325,7 +413,7 @@ namespace SparkleShare {
|
|||
|
||||
Controller.UpdateAddProjectButtonEvent += delegate (bool button_enabled) {
|
||||
InvokeOnMainThread (delegate {
|
||||
SyncButton.Enabled = button_enabled;
|
||||
AddButton.Enabled = button_enabled;
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -338,28 +426,26 @@ namespace SparkleShare {
|
|||
ContentView.AddSubview (PathTextField);
|
||||
ContentView.AddSubview (PathHelpLabel);
|
||||
|
||||
SyncButton = new NSButton () {
|
||||
AddButton = new NSButton () {
|
||||
Title = "Add",
|
||||
Enabled = false
|
||||
};
|
||||
|
||||
SyncButton.Activated += delegate {
|
||||
AddButton.Activated += delegate {
|
||||
Controller.AddPageCompleted (
|
||||
AddressTextField.StringValue,
|
||||
PathTextField.StringValue
|
||||
);
|
||||
};
|
||||
|
||||
Buttons.Add (SyncButton);
|
||||
Buttons.Add (AddButton);
|
||||
|
||||
CancelButton = new NSButton () {
|
||||
Title = "Cancel"
|
||||
};
|
||||
|
||||
CancelButton.Activated += delegate {
|
||||
InvokeOnMainThread (delegate {
|
||||
PerformClose (this);
|
||||
});
|
||||
Controller.PageCancelled ();
|
||||
};
|
||||
|
||||
Buttons.Add (CancelButton);
|
||||
|
@ -505,10 +591,7 @@ namespace SparkleShare {
|
|||
};
|
||||
|
||||
FinishButton.Activated += delegate {
|
||||
InvokeOnMainThread (delegate {
|
||||
Controller.FinishedPageCompleted ();
|
||||
PerformClose (this);
|
||||
});
|
||||
Controller.FinishPageCompleted ();
|
||||
};
|
||||
|
||||
OpenFolderButton = new NSButton () {
|
||||
|
@ -655,9 +738,7 @@ namespace SparkleShare {
|
|||
};
|
||||
|
||||
FinishButton.Activated += delegate {
|
||||
InvokeOnMainThread (delegate {
|
||||
PerformClose (this);
|
||||
});
|
||||
Controller.TutorialPageCompleted ();
|
||||
};
|
||||
|
||||
string slide_image_path = Path.Combine (NSBundle.MainBundle.ResourcePath,
|
||||
|
|
|
@ -83,11 +83,6 @@ namespace SparkleShare {
|
|||
Font = SparkleUI.Font
|
||||
};
|
||||
|
||||
NSApplication.SharedApplication.ActivateIgnoringOtherApps (true);
|
||||
MakeKeyAndOrderFront (this);
|
||||
|
||||
OrderFrontRegardless ();
|
||||
|
||||
if (Program.UI != null)
|
||||
Program.UI.UpdateDockIconVisibility ();
|
||||
}
|
||||
|
@ -140,6 +135,9 @@ namespace SparkleShare {
|
|||
public override void OrderFrontRegardless ()
|
||||
{
|
||||
NSApplication.SharedApplication.AddWindowsItem (this, "SparkleShare Setup", false);
|
||||
NSApplication.SharedApplication.ActivateIgnoringOtherApps (true);
|
||||
MakeKeyAndOrderFront (this);
|
||||
|
||||
base.OrderFrontRegardless ();
|
||||
}
|
||||
|
||||
|
|
|
@ -230,26 +230,13 @@ namespace SparkleShare {
|
|||
Menu.AddItem (NSMenuItem.SeparatorItem);
|
||||
|
||||
SyncMenuItem = new NSMenuItem () {
|
||||
Title = "Add Hosted Project…",
|
||||
Title = "Add Hosted Project…",
|
||||
Enabled = true
|
||||
};
|
||||
|
||||
if (!Program.Controller.FirstRun) {
|
||||
SyncMenuItem.Activated += delegate {
|
||||
InvokeOnMainThread (delegate {
|
||||
NSApplication.SharedApplication.ActivateIgnoringOtherApps (true);
|
||||
|
||||
if (SparkleUI.Setup == null) {
|
||||
SparkleUI.Setup = new SparkleSetup ();
|
||||
SparkleUI.Setup.Controller.ShowAddPage ();
|
||||
}
|
||||
|
||||
if (!SparkleUI.Setup.IsVisible)
|
||||
SparkleUI.Setup.Controller.ShowAddPage ();
|
||||
|
||||
SparkleUI.Setup.OrderFrontRegardless ();
|
||||
SparkleUI.Setup.MakeKeyAndOrderFront (this);
|
||||
});
|
||||
Controller.AddHostedProjectClicked ();
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -262,7 +249,9 @@ namespace SparkleShare {
|
|||
};
|
||||
|
||||
if (Controller.Folders.Length > 0) {
|
||||
// TODO: move this logic
|
||||
RecentEventsMenuItem.Activated += delegate {
|
||||
// Controller.OpenRecentEventsClicked ()
|
||||
InvokeOnMainThread (delegate {
|
||||
NSApplication.SharedApplication.ActivateIgnoringOtherApps (true);
|
||||
|
||||
|
@ -304,8 +293,10 @@ namespace SparkleShare {
|
|||
Title = "About SparkleShare",
|
||||
Enabled = true
|
||||
};
|
||||
|
||||
|
||||
// TODO: move this logic
|
||||
AboutMenuItem.Activated += delegate {
|
||||
// Controller.AboutClicked ();
|
||||
InvokeOnMainThread (delegate {
|
||||
NSApplication.SharedApplication.ActivateIgnoringOtherApps (true);
|
||||
|
||||
|
|
|
@ -65,11 +65,11 @@ namespace SparkleShare {
|
|||
|
||||
StatusIcon = new SparkleStatusIcon ();
|
||||
Bubbles = new SparkleBubbles ();
|
||||
Setup = new SparkleSetup ();
|
||||
// About = new SparkleAbout ();
|
||||
|
||||
if (Program.Controller.FirstRun) {
|
||||
Setup = new SparkleSetup ();
|
||||
Setup.Controller.ShowSetupPage ();
|
||||
|
||||
Program.Controller.ShowSetupWindow (PageType.Setup);
|
||||
UpdateDockIconVisibility ();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,10 +28,8 @@ namespace SparkleShare {
|
|||
|
||||
public SparkleBubblesController ()
|
||||
{
|
||||
Program.Controller.ConflictNotificationRaised += delegate {
|
||||
ShowBubble ("Conflict detected.",
|
||||
"Don't worry, SparkleShare made a copy of each conflicting file.",
|
||||
null);
|
||||
Program.Controller.AlertNotificationRaised += delegate (string title, string message) {
|
||||
ShowBubble (title, message, null);
|
||||
};
|
||||
|
||||
Program.Controller.NotificationRaised += delegate (SparkleChangeSet change_set) {
|
||||
|
|
|
@ -40,6 +40,17 @@ namespace SparkleShare {
|
|||
public double ProgressPercentage = 0.0;
|
||||
public string ProgressSpeed = "";
|
||||
|
||||
|
||||
public event ShowSetupWindowEventHandler ShowSetupWindowEvent;
|
||||
public delegate void ShowSetupWindowEventHandler (PageType page_type);
|
||||
|
||||
public event ShowAboutWindowEventHandler ShowAboutWindowEvent;
|
||||
public delegate void ShowAboutWindowEventHandler ();
|
||||
|
||||
public event ShowEventsWindowEventHandler ShowEventsWindowEvent;
|
||||
public delegate void ShowEventsWindowEventHandler ();
|
||||
|
||||
|
||||
public event FolderFetchedEventHandler FolderFetched;
|
||||
public delegate void FolderFetchedEventHandler (string [] warnings);
|
||||
|
||||
|
@ -64,15 +75,15 @@ namespace SparkleShare {
|
|||
public event OnErrorHandler OnError;
|
||||
public delegate void OnErrorHandler ();
|
||||
|
||||
public event OnInviteHandler OnInvite;
|
||||
public delegate void OnInviteHandler (SparkleInvite invite);
|
||||
|
||||
public event ConflictNotificationRaisedHandler ConflictNotificationRaised;
|
||||
public delegate void ConflictNotificationRaisedHandler ();
|
||||
public event InviteReceivedHandler InviteReceived;
|
||||
public delegate void InviteReceivedHandler (SparkleInvite invite);
|
||||
|
||||
public event NotificationRaisedEventHandler NotificationRaised;
|
||||
public delegate void NotificationRaisedEventHandler (SparkleChangeSet change_set);
|
||||
|
||||
public event AlertNotificationRaisedEventHandler AlertNotificationRaised;
|
||||
public delegate void AlertNotificationRaisedEventHandler (string title, string message);
|
||||
|
||||
public event NoteNotificationRaisedEventHandler NoteNotificationRaised;
|
||||
public delegate void NoteNotificationRaisedEventHandler (SparkleUser user, string folder_name);
|
||||
|
||||
|
@ -126,16 +137,27 @@ namespace SparkleShare {
|
|||
FolderListChanged ();
|
||||
};
|
||||
|
||||
watcher.Created += delegate (object o, FileSystemEventArgs args) {
|
||||
if (!args.FullPath.EndsWith (".xml"))
|
||||
return;
|
||||
|
||||
SparkleInviteListener invite_listener = new SparkleInviteListener (1987);
|
||||
if (this.fetcher != null &&
|
||||
this.fetcher.IsActive) {
|
||||
|
||||
invite_listener.InviteReceived += delegate (SparkleInvite invite) {
|
||||
if (OnInvite != null && !FirstRun)
|
||||
OnInvite (invite);
|
||||
if (AlertNotificationRaised != null)
|
||||
AlertNotificationRaised ("SparkleShare Setup is busy",
|
||||
"Please try again later");
|
||||
|
||||
} else {
|
||||
if (InviteReceived != null) {
|
||||
SparkleInvite invite = new SparkleInvite (args.FullPath);
|
||||
|
||||
if (invite.Valid)
|
||||
InviteReceived (invite);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
invite_listener.Start ();
|
||||
|
||||
new Thread (new ThreadStart (PopulateRepositories)).Start ();
|
||||
}
|
||||
|
||||
|
@ -147,43 +169,11 @@ namespace SparkleShare {
|
|||
}
|
||||
|
||||
|
||||
// Uploads the user's public key to the server
|
||||
public bool AcceptInvitation (string server, string folder, string token)
|
||||
{
|
||||
// The location of the user's public key for SparkleShare
|
||||
string public_key_file_path = SparkleHelpers.CombineMore (SparkleConfig.DefaultConfig.HomePath,
|
||||
".ssh", "sparkleshare." + UserEmail + ".key.pub");
|
||||
|
||||
if (!File.Exists (public_key_file_path))
|
||||
return false;
|
||||
|
||||
StreamReader reader = new StreamReader (public_key_file_path);
|
||||
string public_key = reader.ReadToEnd ();
|
||||
reader.Close ();
|
||||
|
||||
string url = "https://" + server + "/?folder=" + folder +
|
||||
"&token=" + token + "&pubkey=" + public_key;
|
||||
|
||||
SparkleHelpers.DebugInfo ("WebRequest", url);
|
||||
|
||||
HttpWebRequest request = (HttpWebRequest) WebRequest.Create (url);
|
||||
HttpWebResponse response = (HttpWebResponse) request.GetResponse();
|
||||
|
||||
if (response.StatusCode == HttpStatusCode.OK) {
|
||||
response.Close ();
|
||||
return true;
|
||||
|
||||
} else {
|
||||
response.Close ();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public List<string> Folders {
|
||||
get {
|
||||
List<string> folders = SparkleConfig.DefaultConfig.Folders;
|
||||
folders.Sort ();
|
||||
|
||||
return folders;
|
||||
}
|
||||
}
|
||||
|
@ -194,6 +184,7 @@ namespace SparkleShare {
|
|||
List<string> hosts = SparkleConfig.DefaultConfig.HostsWithUsername;
|
||||
hosts.AddRange(SparkleConfig.DefaultConfig.Hosts);
|
||||
hosts.Sort ();
|
||||
|
||||
return hosts;
|
||||
}
|
||||
}
|
||||
|
@ -213,6 +204,28 @@ namespace SparkleShare {
|
|||
}
|
||||
|
||||
|
||||
public void ShowSetupWindow (PageType page_type)
|
||||
{
|
||||
if (ShowSetupWindowEvent != null)
|
||||
ShowSetupWindowEvent (page_type);
|
||||
}
|
||||
|
||||
|
||||
public void ShowAboutWindow ()
|
||||
{
|
||||
if (ShowAboutWindowEvent != null)
|
||||
ShowAboutWindowEvent ();
|
||||
}
|
||||
|
||||
|
||||
public void ShowEventsWindow ()
|
||||
{
|
||||
if (ShowEventsWindowEvent != null)
|
||||
ShowEventsWindowEvent ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public List<SparkleChangeSet> GetLog ()
|
||||
{
|
||||
List<SparkleChangeSet> list = new List<SparkleChangeSet> ();
|
||||
|
@ -584,7 +597,6 @@ namespace SparkleShare {
|
|||
|
||||
|
||||
repo.NewChangeSet += delegate (SparkleChangeSet change_set) {
|
||||
|
||||
if (NotificationRaised != null)
|
||||
NotificationRaised (change_set);
|
||||
};
|
||||
|
@ -596,8 +608,9 @@ namespace SparkleShare {
|
|||
};
|
||||
|
||||
repo.ConflictResolved += delegate {
|
||||
if (ConflictNotificationRaised != null)
|
||||
ConflictNotificationRaised ();
|
||||
if (AlertNotificationRaised != null)
|
||||
AlertNotificationRaised ("Conflict detected.",
|
||||
"Don't worry, SparkleShare made a copy of each conflicting file.");
|
||||
};
|
||||
|
||||
repo.SyncStatusChanged += delegate (SyncStatus status) {
|
||||
|
@ -851,7 +864,6 @@ namespace SparkleShare {
|
|||
}
|
||||
|
||||
foreach (string raw_email in emails) {
|
||||
|
||||
// Gravatar wants lowercase emails
|
||||
string email = raw_email.ToLower ();
|
||||
string avatar_file_path = Path.Combine (avatar_path, "avatar-" + email);
|
||||
|
@ -866,9 +878,6 @@ namespace SparkleShare {
|
|||
old_avatars.Add (email);
|
||||
|
||||
} catch (FileNotFoundException) {
|
||||
// FIXME: For some reason the previous File.Exists () check
|
||||
// doesn't cover all cases sometimes, so we catch any errors
|
||||
|
||||
if (old_avatars.Contains (email))
|
||||
old_avatars.Remove (email);
|
||||
}
|
||||
|
@ -876,11 +885,11 @@ namespace SparkleShare {
|
|||
|
||||
} else if (this.failed_avatars.Contains (email)) {
|
||||
break;
|
||||
|
||||
} else {
|
||||
WebClient client = new WebClient ();
|
||||
string url = "http://gravatar.com/avatar/" + GetMD5 (email) +
|
||||
".jpg?s=" + size + "&d=404";
|
||||
|
||||
try {
|
||||
// Fetch the avatar
|
||||
byte [] buffer = client.DownloadData (url);
|
||||
|
@ -900,11 +909,10 @@ namespace SparkleShare {
|
|||
SparkleHelpers.DebugInfo ("Avatar", "Failed fetching gravatar for " + email);
|
||||
|
||||
// Stop downloading further avatars if we have no internet access
|
||||
if (e.Status == WebExceptionStatus.Timeout){
|
||||
if (e.Status == WebExceptionStatus.Timeout)
|
||||
break;
|
||||
} else {
|
||||
else
|
||||
this.failed_avatars.Add (email);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,12 +16,8 @@
|
|||
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
using System.Threading;
|
||||
|
||||
using SparkleLib;
|
||||
|
||||
|
@ -29,32 +25,22 @@ namespace SparkleShare {
|
|||
|
||||
public class SparkleInvite {
|
||||
|
||||
public readonly Uri FullAddress;
|
||||
public readonly string Token;
|
||||
public string Address { get; private set; }
|
||||
public string RemotePath { get; private set; }
|
||||
public Uri AcceptUrl { get; private set; }
|
||||
|
||||
public string Host {
|
||||
public bool Valid {
|
||||
get {
|
||||
return FullAddress.Host;
|
||||
}
|
||||
}
|
||||
|
||||
public string Path {
|
||||
get {
|
||||
return FullAddress.AbsolutePath;
|
||||
return (!string.IsNullOrEmpty (Address) &&
|
||||
!string.IsNullOrEmpty (RemotePath) &&
|
||||
!string.IsNullOrEmpty (AcceptUrl.ToString ()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public SparkleInvite (string host, string path, string token)
|
||||
public SparkleInvite (string address, string remote_path, string accept_url)
|
||||
{
|
||||
if (path.StartsWith ("/"))
|
||||
path = path.Substring (1);
|
||||
|
||||
if (!host.EndsWith ("/"))
|
||||
host = host + "/";
|
||||
|
||||
FullAddress = new Uri ("ssh://" + host + path);
|
||||
Token = token;
|
||||
Initialize (address, remote_path, accept_url);
|
||||
}
|
||||
|
||||
|
||||
|
@ -63,166 +49,62 @@ namespace SparkleShare {
|
|||
XmlDocument xml_document = new XmlDocument ();
|
||||
XmlNode node;
|
||||
|
||||
string host = "", path = "", token = "";
|
||||
string address = "";
|
||||
string remote_path = "";
|
||||
string accept_url = "";
|
||||
|
||||
|
||||
try {
|
||||
xml_document.Load (xml_file_path);
|
||||
|
||||
node = xml_document.SelectSingleNode ("/sparkleshare/invite/host/text()");
|
||||
if (node != null) { host = node.Value; }
|
||||
node = xml_document.SelectSingleNode ("/sparkleshare/invite/address/text()");
|
||||
if (node != null) { address = node.Value; }
|
||||
|
||||
node = xml_document.SelectSingleNode ("/sparkleshare/invite/path/text()");
|
||||
if (node != null) { path = node.Value; }
|
||||
node = xml_document.SelectSingleNode ("/sparkleshare/invite/remote_path/text()");
|
||||
if (node != null) { remote_path = node.Value; }
|
||||
|
||||
node = xml_document.SelectSingleNode ("/sparkleshare/invite/token/text()");
|
||||
if (node != null) { token = node.Value; }
|
||||
node = xml_document.SelectSingleNode ("/sparkleshare/invite/accept_url/text()");
|
||||
if (node != null) { accept_url = node.Value; }
|
||||
|
||||
Initialize (address, remote_path, accept_url);
|
||||
|
||||
} catch (XmlException e) {
|
||||
SparkleHelpers.DebugInfo ("Invite", "Invalid XML: " + e.Message);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (path.StartsWith ("/"))
|
||||
path = path.Substring (1);
|
||||
|
||||
if (!host.EndsWith ("/"))
|
||||
host = host + "/";
|
||||
|
||||
FullAddress = new Uri ("ssh://" + host + path);
|
||||
Token = token;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class SparkleInviteListener {
|
||||
|
||||
public event InviteReceivedHandler InviteReceived;
|
||||
public delegate void InviteReceivedHandler (SparkleInvite invite);
|
||||
|
||||
private Thread thread;
|
||||
private TcpListener tcp_listener;
|
||||
|
||||
|
||||
public SparkleInviteListener (int port)
|
||||
{
|
||||
this.tcp_listener = new TcpListener (IPAddress.Loopback, port);
|
||||
this.thread = new Thread(new ThreadStart (Listen));
|
||||
}
|
||||
|
||||
|
||||
public void Start ()
|
||||
public bool Accept ()
|
||||
{
|
||||
this.thread.Start ();
|
||||
}
|
||||
WebClient web_client = new WebClient ();
|
||||
|
||||
try {
|
||||
web_client.DownloadData (AcceptUrl);
|
||||
SparkleHelpers.DebugInfo ("Invite", "Uploaded public key");
|
||||
|
||||
private void Listen ()
|
||||
{
|
||||
this.tcp_listener.Start ();
|
||||
return true;
|
||||
|
||||
while (true)
|
||||
{
|
||||
// Blocks until a client connects
|
||||
TcpClient client = this.tcp_listener.AcceptTcpClient ();
|
||||
} catch (WebException e) {
|
||||
SparkleHelpers.DebugInfo ("Invite",
|
||||
"Failed uploading public key: " + e.Message);
|
||||
|
||||
// Create a thread to handle communications
|
||||
Thread client_thread = new Thread (HandleClient);
|
||||
client_thread.Start (client);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void HandleClient (object client)
|
||||
{
|
||||
TcpClient tcp_client = (TcpClient) client;
|
||||
NetworkStream client_stream = tcp_client.GetStream ();
|
||||
private void Initialize (string address, string remote_path, string accept_url)
|
||||
{/*
|
||||
if (!remote_path.StartsWith ("/"))
|
||||
remote_path = "/" + remote_path;
|
||||
|
||||
byte [] message = new byte [4096];
|
||||
int bytes_read;
|
||||
|
||||
while (true)
|
||||
{
|
||||
bytes_read = 0;
|
||||
|
||||
try {
|
||||
// Blocks until the client sends a message
|
||||
bytes_read = client_stream.Read (message, 0, 4096);
|
||||
|
||||
} catch {
|
||||
Console.WriteLine ("Socket error...");
|
||||
}
|
||||
|
||||
// The client has disconnected
|
||||
if (bytes_read == 0)
|
||||
break;
|
||||
|
||||
ASCIIEncoding encoding = new ASCIIEncoding ();
|
||||
string received_message = encoding.GetString (message, 0, bytes_read);
|
||||
string invite_xml = "";
|
||||
|
||||
if (received_message.StartsWith (Uri.UriSchemeHttp) ||
|
||||
received_message.StartsWith (Uri.UriSchemeHttps)) {
|
||||
|
||||
WebClient web_client = new WebClient ();
|
||||
|
||||
try {
|
||||
// Fetch the invite file
|
||||
byte [] buffer = web_client.DownloadData (received_message);
|
||||
SparkleHelpers.DebugInfo ("Invite", "Received: " + received_message);
|
||||
|
||||
invite_xml = ASCIIEncoding.ASCII.GetString (buffer);
|
||||
|
||||
} catch (WebException e) {
|
||||
SparkleHelpers.DebugInfo ("Invite", "Failed downloading: " +
|
||||
received_message + " " + e.Message);
|
||||
continue;
|
||||
}
|
||||
|
||||
} else if (received_message.StartsWith (Uri.UriSchemeFile)) {
|
||||
try {
|
||||
received_message = received_message.Replace (Uri.UriSchemeFile + "://", "");
|
||||
invite_xml = File.ReadAllText (received_message);
|
||||
|
||||
} catch {
|
||||
SparkleHelpers.DebugInfo ("Invite", "Failed opening: " + received_message);
|
||||
continue;
|
||||
}
|
||||
|
||||
} else {
|
||||
SparkleHelpers.DebugInfo ("Invite",
|
||||
"Path to invite must use either the file:// or http(s):// scheme");
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
XmlDocument xml_document = new XmlDocument ();
|
||||
XmlNode node;
|
||||
|
||||
string host = "", path = "", token = "";
|
||||
|
||||
try {
|
||||
xml_document.LoadXml (invite_xml);
|
||||
|
||||
node = xml_document.SelectSingleNode ("/sparkleshare/invite/host/text()");
|
||||
if (node != null) { host = node.Value; }
|
||||
|
||||
node = xml_document.SelectSingleNode ("/sparkleshare/invite/path/text()");
|
||||
if (node != null) { path = node.Value; }
|
||||
|
||||
node = xml_document.SelectSingleNode ("/sparkleshare/invite/token/text()");
|
||||
if (node != null) { token = node.Value; }
|
||||
|
||||
} catch (XmlException e) {
|
||||
SparkleHelpers.DebugInfo ("Invite", "Invalid XML: " + received_message + " " + e.Message);
|
||||
return;
|
||||
}
|
||||
|
||||
if (InviteReceived != null)
|
||||
InviteReceived (new SparkleInvite (host, path, token));
|
||||
}
|
||||
|
||||
tcp_client.Close ();
|
||||
if (!address.EndsWith ("/"))
|
||||
address = address + "/";
|
||||
*/
|
||||
Address = address;
|
||||
RemotePath = remote_path;
|
||||
AcceptUrl = new Uri (accept_url);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
|
||||
using SparkleLib;
|
||||
|
||||
|
@ -27,6 +28,7 @@ namespace SparkleShare {
|
|||
public enum PageType {
|
||||
Setup,
|
||||
Add,
|
||||
Invite,
|
||||
Syncing,
|
||||
Error,
|
||||
Finished,
|
||||
|
@ -41,6 +43,12 @@ namespace SparkleShare {
|
|||
|
||||
public class SparkleSetupController {
|
||||
|
||||
public event ShowWindowEventHandler ShowWindowEvent;
|
||||
public delegate void ShowWindowEventHandler ();
|
||||
|
||||
public event HideWindowEventHandler HideWindowEvent;
|
||||
public delegate void HideWindowEventHandler ();
|
||||
|
||||
public event ChangePageEventHandler ChangePageEvent;
|
||||
public delegate void ChangePageEventHandler (PageType page, string [] warnings);
|
||||
|
||||
|
@ -58,12 +66,17 @@ namespace SparkleShare {
|
|||
string example_text, FieldState state);
|
||||
|
||||
public event ChangePathFieldEventHandler ChangePathFieldEvent;
|
||||
public delegate void ChangePathFieldEventHandler (string text,
|
||||
string example_text, FieldState state);
|
||||
public delegate void ChangePathFieldEventHandler (string text, string example_text, FieldState state);
|
||||
|
||||
public readonly List<SparklePlugin> Plugins = new List<SparklePlugin> ();
|
||||
public SparklePlugin SelectedPlugin;
|
||||
|
||||
public int TutorialPageNumber { get; private set; }
|
||||
public string PreviousUrl { get; private set; }
|
||||
public string PreviousAddress { get; private set; }
|
||||
public string PreviousPath { get; private set; }
|
||||
public string SyncingFolder { get; private set; }
|
||||
|
||||
|
||||
public int SelectedPluginIndex {
|
||||
get {
|
||||
|
@ -71,42 +84,6 @@ namespace SparkleShare {
|
|||
}
|
||||
}
|
||||
|
||||
public int TutorialPageNumber {
|
||||
get {
|
||||
return this.tutorial_page_number;
|
||||
}
|
||||
}
|
||||
|
||||
public string PreviousUrl {
|
||||
get {
|
||||
return this.previous_url;
|
||||
}
|
||||
}
|
||||
|
||||
public string PreviousAddress {
|
||||
get {
|
||||
return this.previous_address;
|
||||
}
|
||||
}
|
||||
|
||||
public string PreviousPath {
|
||||
get {
|
||||
return this.previous_path;
|
||||
}
|
||||
}
|
||||
|
||||
public string SyncingFolder {
|
||||
get {
|
||||
return this.syncing_folder;
|
||||
}
|
||||
}
|
||||
|
||||
public PageType PreviousPage {
|
||||
get {
|
||||
return this.previous_page;
|
||||
}
|
||||
}
|
||||
|
||||
public string GuessedUserName {
|
||||
get {
|
||||
return Program.Controller.UserName;
|
||||
|
@ -123,16 +100,14 @@ namespace SparkleShare {
|
|||
}
|
||||
|
||||
|
||||
private string previous_address = "";
|
||||
private string previous_path = "";
|
||||
private string previous_url = "";
|
||||
private string syncing_folder = "";
|
||||
private int tutorial_page_number = 1;
|
||||
private PageType previous_page;
|
||||
|
||||
|
||||
public SparkleSetupController ()
|
||||
{
|
||||
TutorialPageNumber = 1;
|
||||
PreviousAddress = "";
|
||||
PreviousPath = "";
|
||||
PreviousUrl = "";
|
||||
SyncingFolder = "";
|
||||
|
||||
string local_plugins_path = SparkleHelpers.CombineMore (
|
||||
Environment.GetFolderPath (Environment.SpecialFolder.ApplicationData),
|
||||
"sparkleshare", "plugins");
|
||||
|
@ -152,16 +127,37 @@ namespace SparkleShare {
|
|||
|
||||
SelectedPlugin = Plugins [0];
|
||||
|
||||
ChangePageEvent += delegate (PageType page, string [] warning) {
|
||||
this.previous_page = page;
|
||||
|
||||
Program.Controller.InviteReceived += delegate (SparkleInvite invite) {
|
||||
PendingInvite = invite;
|
||||
|
||||
if (ChangePageEvent != null)
|
||||
ChangePageEvent (PageType.Invite, null);
|
||||
|
||||
if (ShowWindowEvent != null)
|
||||
ShowWindowEvent ();
|
||||
};
|
||||
|
||||
|
||||
Program.Controller.ShowSetupWindowEvent += delegate (PageType page_type) {
|
||||
if (ChangePageEvent != null)
|
||||
ChangePageEvent (page_type, null);
|
||||
|
||||
if (ShowWindowEvent != null)
|
||||
ShowWindowEvent ();
|
||||
|
||||
if (page_type == PageType.Add)
|
||||
SelectedPluginChanged (SelectedPluginIndex);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
public void ShowSetupPage ()
|
||||
public void PageCancelled ()
|
||||
{
|
||||
if (ChangePageEvent != null)
|
||||
ChangePageEvent (PageType.Setup, null);
|
||||
// PendingInvite = null;
|
||||
|
||||
if (HideWindowEvent != null)
|
||||
HideWindowEvent ();
|
||||
}
|
||||
|
||||
|
||||
|
@ -192,112 +188,27 @@ namespace SparkleShare {
|
|||
}
|
||||
|
||||
|
||||
public void TutorialPageCompleted ()
|
||||
{
|
||||
this.tutorial_page_number++;
|
||||
|
||||
if (ChangePageEvent != null)
|
||||
ChangePageEvent (PageType.Tutorial, null);
|
||||
}
|
||||
|
||||
|
||||
public void TutorialSkipped ()
|
||||
{
|
||||
this.tutorial_page_number = 4;
|
||||
TutorialPageNumber = 4;
|
||||
|
||||
if (ChangePageEvent != null)
|
||||
ChangePageEvent (PageType.Tutorial, null);
|
||||
}
|
||||
|
||||
|
||||
public void ShowAddPage ()
|
||||
public void TutorialPageCompleted ()
|
||||
{
|
||||
if (ChangePageEvent != null)
|
||||
ChangePageEvent (PageType.Add, null);
|
||||
TutorialPageNumber++;
|
||||
|
||||
SelectedPluginChanged (SelectedPluginIndex);
|
||||
}
|
||||
if (TutorialPageNumber == 4) {
|
||||
if (HideWindowEvent != null)
|
||||
HideWindowEvent ();
|
||||
|
||||
|
||||
public void CheckAddPage (string address, string remote_path, int selected_plugin)
|
||||
{
|
||||
if (SelectedPluginIndex != selected_plugin)
|
||||
SelectedPluginChanged (selected_plugin);
|
||||
|
||||
address = address.Trim ();
|
||||
remote_path = remote_path.Trim ();
|
||||
|
||||
bool fields_valid = address != null && address.Trim().Length > 0 &&
|
||||
remote_path != null && remote_path.Trim().Length > 0;
|
||||
|
||||
if (UpdateAddProjectButtonEvent != null)
|
||||
UpdateAddProjectButtonEvent (fields_valid);
|
||||
}
|
||||
|
||||
|
||||
public void AddPageCompleted (string address, string path)
|
||||
{
|
||||
this.syncing_folder = Path.GetFileNameWithoutExtension (path);
|
||||
this.previous_address = address;
|
||||
this.previous_path = path;
|
||||
|
||||
if (ChangePageEvent != null)
|
||||
ChangePageEvent (PageType.Syncing, null);
|
||||
|
||||
// TODO: Remove events afterwards
|
||||
|
||||
Program.Controller.FolderFetched += delegate (string [] warnings) {
|
||||
} else {
|
||||
if (ChangePageEvent != null)
|
||||
ChangePageEvent (PageType.Finished, warnings);
|
||||
|
||||
this.previous_address = "";
|
||||
this.syncing_folder = "";
|
||||
this.previous_url = "";
|
||||
SelectedPlugin = Plugins [0];
|
||||
};
|
||||
|
||||
Program.Controller.FolderFetchError += delegate (string remote_url) {
|
||||
this.previous_url = remote_url;
|
||||
|
||||
if (ChangePageEvent != null)
|
||||
ChangePageEvent (PageType.Error, null);
|
||||
|
||||
this.syncing_folder = "";
|
||||
};
|
||||
|
||||
Program.Controller.FolderFetching += delegate (double percentage) {
|
||||
if (UpdateProgressBarEvent != null)
|
||||
UpdateProgressBarEvent (percentage);
|
||||
};
|
||||
|
||||
Program.Controller.FetchFolder (address, path);
|
||||
}
|
||||
|
||||
|
||||
public void ErrorPageCompleted ()
|
||||
{
|
||||
if (ChangePageEvent != null)
|
||||
ChangePageEvent (PageType.Add, null);
|
||||
}
|
||||
|
||||
|
||||
public void SyncingCancelled ()
|
||||
{
|
||||
Program.Controller.StopFetcher ();
|
||||
|
||||
if (ChangePageEvent != null)
|
||||
ChangePageEvent (PageType.Add, null);
|
||||
}
|
||||
|
||||
|
||||
// TODO: public void WindowClosed () { }
|
||||
|
||||
|
||||
public void FinishedPageCompleted ()
|
||||
{
|
||||
this.previous_address = "";
|
||||
this.previous_path = "";
|
||||
Program.Controller.UpdateState ();
|
||||
ChangePageEvent (PageType.Tutorial, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -332,6 +243,155 @@ namespace SparkleShare {
|
|||
}
|
||||
|
||||
|
||||
public void CheckAddPage (string address, string remote_path, int selected_plugin)
|
||||
{
|
||||
if (SelectedPluginIndex != selected_plugin)
|
||||
SelectedPluginChanged (selected_plugin);
|
||||
|
||||
address = address.Trim ();
|
||||
remote_path = remote_path.Trim ();
|
||||
|
||||
bool fields_valid = address != null && address.Trim().Length > 0 &&
|
||||
remote_path != null && remote_path.Trim().Length > 0;
|
||||
|
||||
if (UpdateAddProjectButtonEvent != null)
|
||||
UpdateAddProjectButtonEvent (fields_valid);
|
||||
}
|
||||
|
||||
|
||||
public void AddPageCompleted (string address, string path)
|
||||
{
|
||||
SyncingFolder = Path.GetFileNameWithoutExtension (path);
|
||||
PreviousAddress = address;
|
||||
PreviousPath = path;
|
||||
|
||||
if (ChangePageEvent != null)
|
||||
ChangePageEvent (PageType.Syncing, null);
|
||||
|
||||
// TODO: Remove events afterwards
|
||||
|
||||
Program.Controller.FolderFetched += delegate (string [] warnings) {
|
||||
if (ChangePageEvent != null)
|
||||
ChangePageEvent (PageType.Finished, warnings);
|
||||
|
||||
PreviousAddress = "";
|
||||
SyncingFolder = "";
|
||||
PreviousUrl = "";
|
||||
SelectedPlugin = Plugins [0];
|
||||
};
|
||||
|
||||
Program.Controller.FolderFetchError += delegate (string remote_url) {
|
||||
Thread.Sleep (1000);
|
||||
PreviousUrl = remote_url;
|
||||
|
||||
if (ChangePageEvent != null)
|
||||
ChangePageEvent (PageType.Error, null);
|
||||
|
||||
SyncingFolder = "";
|
||||
};
|
||||
|
||||
Program.Controller.FolderFetching += delegate (double percentage) {
|
||||
if (UpdateProgressBarEvent != null)
|
||||
UpdateProgressBarEvent (percentage);
|
||||
};
|
||||
|
||||
Program.Controller.FetchFolder (address, path);
|
||||
}
|
||||
|
||||
|
||||
// TODO: trailing slash should work
|
||||
public SparkleInvite PendingInvite = new SparkleInvite ("ssh://git@github.com/",
|
||||
"/hbons/Stuff", "http://www.sparkleshare.org/");
|
||||
|
||||
public void InvitePageCompleted ()
|
||||
{
|
||||
SyncingFolder = Path.GetFileNameWithoutExtension (PendingInvite.RemotePath);
|
||||
PreviousAddress = PendingInvite.Address;
|
||||
PreviousPath = PendingInvite.RemotePath;
|
||||
|
||||
if (ChangePageEvent != null)
|
||||
ChangePageEvent (PageType.Syncing, null);
|
||||
|
||||
if (!PendingInvite.Accept ()) {
|
||||
if (ChangePageEvent != null)
|
||||
ChangePageEvent (PageType.Error, null);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// TODO: Remove events afterwards
|
||||
|
||||
Program.Controller.FolderFetched += delegate (string [] warnings) {
|
||||
if (ChangePageEvent != null)
|
||||
ChangePageEvent (PageType.Finished, warnings);
|
||||
|
||||
|
||||
PreviousAddress = "";
|
||||
SyncingFolder = "";
|
||||
PreviousUrl = "";
|
||||
SelectedPlugin = Plugins [0];
|
||||
|
||||
PendingInvite = null;
|
||||
};
|
||||
|
||||
Program.Controller.FolderFetchError += delegate (string remote_url) {
|
||||
Thread.Sleep (1000);
|
||||
PreviousUrl = remote_url;
|
||||
|
||||
if (ChangePageEvent != null)
|
||||
ChangePageEvent (PageType.Error, null);
|
||||
|
||||
SyncingFolder = "";
|
||||
};
|
||||
|
||||
Program.Controller.FolderFetching += delegate (double percentage) {
|
||||
if (UpdateProgressBarEvent != null)
|
||||
UpdateProgressBarEvent (percentage);
|
||||
};
|
||||
|
||||
Program.Controller.FetchFolder (PendingInvite.Address, PendingInvite.RemotePath);
|
||||
}
|
||||
|
||||
|
||||
public void SyncingCancelled ()
|
||||
{
|
||||
Program.Controller.StopFetcher ();
|
||||
|
||||
if (ChangePageEvent == null)
|
||||
return;
|
||||
|
||||
if (PendingInvite != null)
|
||||
ChangePageEvent (PageType.Invite, null);
|
||||
else
|
||||
ChangePageEvent (PageType.Add, null);
|
||||
}
|
||||
|
||||
|
||||
public void ErrorPageCompleted ()
|
||||
{
|
||||
if (ChangePageEvent == null)
|
||||
return;
|
||||
|
||||
if (PendingInvite != null)
|
||||
ChangePageEvent (PageType.Invite, null);
|
||||
else
|
||||
ChangePageEvent (PageType.Add, null);
|
||||
}
|
||||
|
||||
|
||||
public void FinishPageCompleted ()
|
||||
{
|
||||
PreviousAddress = "";
|
||||
PreviousPath = "";
|
||||
|
||||
Program.Controller.UpdateState ();
|
||||
|
||||
if (HideWindowEvent != null)
|
||||
HideWindowEvent ();
|
||||
}
|
||||
|
||||
|
||||
private bool IsValidEmail (string email)
|
||||
{
|
||||
Regex regex = new Regex (@"^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$",
|
||||
|
|
|
@ -129,5 +129,11 @@ namespace SparkleShare {
|
|||
UpdateMenuEvent (IconState.Error);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
public void AddHostedProjectClicked ()
|
||||
{
|
||||
Program.Controller.ShowSetupWindow (PageType.Add);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue