Compare commits
4 commits
master
...
feature/wi
Author | SHA1 | Date | |
---|---|---|---|
![]() |
ddf20e262d | ||
![]() |
49afb63e3d | ||
![]() |
4a9963d89a | ||
![]() |
f4b5fa196c |
57 changed files with 2508 additions and 1668 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -36,4 +36,3 @@ SparkleShare/Windows/build/
|
|||
**/packages/*
|
||||
# except build/, which is used as an MSBuild target.
|
||||
!**/packages/build/
|
||||
|
||||
|
|
|
@ -83,10 +83,10 @@ namespace SparkleShare {
|
|||
public event Action ShowEventLogWindowEvent = delegate { };
|
||||
|
||||
public event FolderFetchedEventHandler FolderFetched = delegate { };
|
||||
public delegate void FolderFetchedEventHandler (string remote_url, string [] warnings);
|
||||
public delegate void FolderFetchedEventHandler (string remote_url);
|
||||
|
||||
public event FolderFetchErrorHandler FolderFetchError = delegate { };
|
||||
public delegate void FolderFetchErrorHandler (string remote_url, string [] errors);
|
||||
public delegate void FolderFetchErrorHandler (string remote_url, string error, string error_details);
|
||||
|
||||
public event FolderFetchingHandler FolderFetching = delegate { };
|
||||
public delegate void FolderFetchingHandler (double percentage, double speed, string information);
|
||||
|
@ -270,7 +270,7 @@ namespace SparkleShare {
|
|||
}
|
||||
|
||||
if (FirstRun) {
|
||||
ShowSetupWindow (PageType.Setup);
|
||||
ShowSetupWindow (PageType.User);
|
||||
|
||||
} else {
|
||||
new Thread (() => {
|
||||
|
@ -286,7 +286,7 @@ namespace SparkleShare {
|
|||
|
||||
public void ShowSetupWindow (PageType page_type)
|
||||
{
|
||||
ShowSetupWindowEvent (page_type);
|
||||
ShowSetupWindowEvent (PageType.User);
|
||||
}
|
||||
|
||||
|
||||
|
@ -554,13 +554,13 @@ namespace SparkleShare {
|
|||
}
|
||||
|
||||
|
||||
public void StartFetcher (SparkleFetcherInfo info)
|
||||
public void StartFetcher (FetcherInfo info)
|
||||
{
|
||||
string canonical_name = Path.GetFileName (info.RemotePath);
|
||||
string backend = info.Backend;
|
||||
string canonical_name = Path.GetFileName (info.Address.AbsolutePath);
|
||||
string backend = info.Backend;
|
||||
|
||||
if (string.IsNullOrEmpty (backend))
|
||||
backend = BaseFetcher.GetBackend (info.Address);
|
||||
backend = BaseFetcher.GetBackend (info.Address.ToString ());
|
||||
|
||||
info.TargetDirectory = Path.Combine (Config.TmpPath, canonical_name);
|
||||
|
||||
|
@ -576,8 +576,8 @@ namespace SparkleShare {
|
|||
Logger.LogInfo ("Controller",
|
||||
"Failed to load '" + backend + "' backend for '" + canonical_name + "' " + e.Message);
|
||||
|
||||
FolderFetchError (Path.Combine (info.Address, info.RemotePath).Replace (@"\", "/"),
|
||||
new string [] {"Failed to load \"" + backend + "\" backend for \"" + canonical_name + "\""});
|
||||
FolderFetchError (info.Address.ToString ().Replace (@"\", "/"),
|
||||
"Could not find backend", "\"" + backend + "\" is missing.");
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -590,10 +590,10 @@ namespace SparkleShare {
|
|||
}
|
||||
|
||||
|
||||
void FetcherFinishedDelegate (StorageType storage_type, string [] warnings)
|
||||
void FetcherFinishedDelegate (StorageType storage_type)
|
||||
{
|
||||
if (storage_type == StorageType.Unknown) {
|
||||
ShowSetupWindow (PageType.StorageSetup);
|
||||
ShowSetupWindow (PageType.Storage);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -606,10 +606,38 @@ namespace SparkleShare {
|
|||
}
|
||||
|
||||
|
||||
void FetcherFailedDelegate ()
|
||||
void FetcherFailedDelegate (FetchResult result)
|
||||
{
|
||||
FolderFetchError (this.fetcher.RemoteUrl.ToString (), this.fetcher.Errors);
|
||||
StopFetcher ();
|
||||
string error = "Something went wrong";
|
||||
string error_details = "Sorry, we're not quite sure what happened.";
|
||||
|
||||
if (result ==FetchResult.NoNetwork) {
|
||||
error = "Could not connect to the internet";
|
||||
error_details = "Please reconnect and try again.";
|
||||
}
|
||||
|
||||
if (result == FetchResult.HostNotSupported) {
|
||||
error = "Host not supported";
|
||||
error_details = "The host wasn't set up right.";
|
||||
}
|
||||
|
||||
if (result == FetchResult.HostChanged) {
|
||||
error = "The host has changed its identity";
|
||||
error_details = "Please contact its administrator.";
|
||||
}
|
||||
|
||||
if (result == FetchResult.NotAuthenticated) {
|
||||
error = "Could not authenticate";
|
||||
error_details = "Please make sure the host knows your Public Key.";
|
||||
}
|
||||
|
||||
if (result == FetchResult.UserInterrupted) {
|
||||
error = "Cancelled.";
|
||||
error_details = "";
|
||||
}
|
||||
|
||||
FolderFetchError (this.fetcher.RemoteUrl.ToString (), error, error_details);
|
||||
StopFetcher (); // TODO is this needed?
|
||||
}
|
||||
|
||||
|
||||
|
@ -688,7 +716,7 @@ namespace SparkleShare {
|
|||
RepositoriesLoaded = true;
|
||||
|
||||
FolderListChanged ();
|
||||
FolderFetched (this.fetcher.RemoteUrl.ToString (), this.fetcher.Warnings.ToArray ());
|
||||
FolderFetched (this.fetcher.RemoteUrl.ToString ()); // TODO warning handling
|
||||
|
||||
this.fetcher.Dispose ();
|
||||
this.fetcher = null;
|
||||
|
|
|
@ -73,8 +73,8 @@ namespace SparkleShare {
|
|||
string html = HTML;
|
||||
delay.Stop ();
|
||||
|
||||
if (!string.IsNullOrEmpty (html))
|
||||
UpdateContentEvent (html);
|
||||
if (!string.IsNullOrEmpty (html))
|
||||
UpdateContentEvent (html);
|
||||
|
||||
UpdateSizeInfoEvent (Size, HistorySize);
|
||||
|
||||
|
|
44
SparkleShare/Common/Page.cs
Normal file
44
SparkleShare/Common/Page.cs
Normal file
|
@ -0,0 +1,44 @@
|
|||
// SparkleShare, a collaboration and sharing tool.
|
||||
// Copyright (C) 2010 Hylke Bons <hi@planetpeanut.uk>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General private License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General private License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General private License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
using System;
|
||||
|
||||
namespace SparkleShare {
|
||||
|
||||
public abstract class Page : IDisposable {
|
||||
|
||||
protected PageController Controller;
|
||||
protected PageType? RequestedType;
|
||||
|
||||
public string Header;
|
||||
public string Description;
|
||||
|
||||
public object OptionArea;
|
||||
public object [] Buttons;
|
||||
|
||||
|
||||
public Page (PageType? page_type, PageController controller)
|
||||
{
|
||||
RequestedType = page_type;
|
||||
Controller = controller;
|
||||
}
|
||||
|
||||
|
||||
public abstract object Render ();
|
||||
public virtual void Dispose () { }
|
||||
}
|
||||
}
|
198
SparkleShare/Common/PageController.cs
Normal file
198
SparkleShare/Common/PageController.cs
Normal file
|
@ -0,0 +1,198 @@
|
|||
// SparkleShare, a collaboration and sharing tool.
|
||||
// Copyright (C) 2010 Hylke Bons <hi@planetpeanut.uk>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
|
||||
using Sparkles;
|
||||
|
||||
namespace SparkleShare {
|
||||
|
||||
public enum PageType {
|
||||
None,
|
||||
User,
|
||||
Privacy,
|
||||
Host,
|
||||
Address,
|
||||
Invite,
|
||||
Progress,
|
||||
Storage,
|
||||
CryptoSetup,
|
||||
CryptoPassword
|
||||
}
|
||||
|
||||
|
||||
public partial class PageController {
|
||||
|
||||
public bool WindowIsOpen { get; private set; }
|
||||
|
||||
public event Action ShowWindowEvent = delegate { };
|
||||
public event Action HideWindowEvent = delegate { };
|
||||
|
||||
|
||||
PageType current_page;
|
||||
const int page_delay = 1000;
|
||||
|
||||
public event ChangePageEventHandler ChangePageEvent = delegate { };
|
||||
public delegate void ChangePageEventHandler (PageType page);
|
||||
|
||||
public event PageCanContinueEventHandler PageCanContinueEvent = delegate { };
|
||||
public delegate void PageCanContinueEventHandler (PageType page_type, bool can_continue);
|
||||
|
||||
|
||||
public readonly List<Preset> Presets = new List<Preset> ();
|
||||
public Preset SelectedPreset;
|
||||
|
||||
|
||||
public Uri FetchAddress { get; private set; }
|
||||
public double ProgressBarPercentage { get; private set; }
|
||||
|
||||
|
||||
public SparkleInvite PendingInvite { get; private set; }
|
||||
|
||||
|
||||
public PageController ()
|
||||
{
|
||||
LoadPresets ();
|
||||
|
||||
ChangePageEvent += delegate (PageType page_type) {
|
||||
this.current_page = page_type;
|
||||
};
|
||||
|
||||
SparkleShare.Controller.InviteReceived += delegate (SparkleInvite invite) {
|
||||
PendingInvite = invite;
|
||||
|
||||
ChangePageEvent (PageType.Invite);
|
||||
ShowWindowEvent ();
|
||||
};
|
||||
|
||||
SparkleShare.Controller.ShowSetupWindowEvent += ShowSetupWindowEventHandler;
|
||||
}
|
||||
|
||||
|
||||
void ShowSetupWindowEventHandler (PageType page_type)
|
||||
{
|
||||
if (page_type == PageType.Storage ||
|
||||
page_type == PageType.CryptoSetup ||
|
||||
page_type == PageType.CryptoPassword) {
|
||||
|
||||
ChangePageEvent (page_type);
|
||||
return;
|
||||
}
|
||||
|
||||
if (PendingInvite != null) {
|
||||
WindowIsOpen = true;
|
||||
ShowWindowEvent ();
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.current_page == PageType.Progress ||
|
||||
this.current_page == PageType.CryptoSetup ||
|
||||
this.current_page == PageType.CryptoPassword) {
|
||||
|
||||
ShowWindowEvent ();
|
||||
return;
|
||||
}
|
||||
|
||||
if (page_type == PageType.Host) {
|
||||
if (WindowIsOpen) {
|
||||
if (this.current_page == PageType.None)
|
||||
ChangePageEvent (PageType.Host);
|
||||
|
||||
} else if (!SparkleShare.Controller.FirstRun) {
|
||||
WindowIsOpen = true;
|
||||
ChangePageEvent (PageType.Host);
|
||||
}
|
||||
|
||||
ShowWindowEvent ();
|
||||
return;
|
||||
}
|
||||
|
||||
WindowIsOpen = true;
|
||||
ChangePageEvent (page_type);
|
||||
ShowWindowEvent ();
|
||||
}
|
||||
|
||||
|
||||
public void QuitClicked ()
|
||||
{
|
||||
SparkleShare.Controller.Quit ();
|
||||
}
|
||||
|
||||
|
||||
public void CancelClicked (PageType? canceled_page)
|
||||
{
|
||||
if (canceled_page == PageType.Progress) {
|
||||
SparkleShare.Controller.StopFetcher ();
|
||||
|
||||
if (PendingInvite != null)
|
||||
ChangePageEvent (PageType.Invite);
|
||||
else
|
||||
ChangePageEvent (PageType.Host);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (canceled_page == PageType.CryptoSetup ||
|
||||
canceled_page == PageType.CryptoPassword) {
|
||||
|
||||
CancelClicked (PageType.Progress);
|
||||
return;
|
||||
}
|
||||
|
||||
Reset ();
|
||||
|
||||
WindowIsOpen = false;
|
||||
HideWindowEvent ();
|
||||
}
|
||||
|
||||
|
||||
PageType [] page_order = { PageType.User, PageType.Privacy,
|
||||
PageType.Host, PageType.Address, PageType.Progress };
|
||||
|
||||
public void BackClicked (PageType? page_type)
|
||||
{
|
||||
PageType page = (PageType) page_type;
|
||||
|
||||
int current_index = Array.IndexOf (page_order, page);
|
||||
int back_index = current_index - 1;
|
||||
|
||||
if (back_index > -1)
|
||||
ChangePageEvent (page_order [back_index]);
|
||||
}
|
||||
|
||||
|
||||
public void Reset ()
|
||||
{
|
||||
PendingInvite = null;
|
||||
SelectedPreset = Presets [0];
|
||||
FetchAddress = null;
|
||||
}
|
||||
|
||||
|
||||
public void ProgressPageCompleted ()
|
||||
{
|
||||
this.current_page = PageType.None;
|
||||
Reset ();
|
||||
|
||||
WindowIsOpen = false;
|
||||
HideWindowEvent ();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
|
||||
// SparkleShare, a collaboration and sharing tool.
|
||||
// Copyright (C) 2010 Hylke Bons <hi@planetpeanut.uk>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
using Sparkles;
|
||||
|
||||
namespace SparkleShare {
|
||||
|
||||
public partial class PageController {
|
||||
|
||||
public event AddressPagePublicKeyEventHandler AddressPagePublicKeyEvent = delegate { };
|
||||
public delegate void AddressPagePublicKeyEventHandler (bool has_key, string auth_status, string key_entry_hint);
|
||||
|
||||
|
||||
public void CheckAddressPage (string address, string remote_path)
|
||||
{
|
||||
address = address.Trim ();
|
||||
remote_path = remote_path.Trim ();
|
||||
|
||||
bool fields_valid = (!string.IsNullOrEmpty (address) &&
|
||||
!string.IsNullOrEmpty (remote_path) && !remote_path.Contains ("\""));
|
||||
|
||||
PageCanContinueEvent (PageType.Address, fields_valid);
|
||||
}
|
||||
|
||||
|
||||
public void AddressPageCompleted (string address, string remote_path)
|
||||
{
|
||||
ProgressBarPercentage = 1.0;
|
||||
ChangePageEvent (PageType.Progress);
|
||||
|
||||
address = Uri.EscapeUriString (address.Trim ());
|
||||
remote_path = remote_path.Trim ();
|
||||
|
||||
if (SelectedPreset.PathUsesLowerCase)
|
||||
remote_path = remote_path.ToLower ();
|
||||
|
||||
FetchAddress = new Uri (address + remote_path);
|
||||
|
||||
SparkleShare.Controller.FolderFetched += ProgressPageFetchedDelegate;
|
||||
SparkleShare.Controller.FolderFetchError += ProgressPageFetchErrorDelegate;
|
||||
SparkleShare.Controller.FolderFetching += ProgressPageFetchingDelegate;
|
||||
|
||||
var info = new FetcherInfo (FetchAddress) {
|
||||
Backend = SelectedPreset.Backend,
|
||||
Fingerprint = SelectedPreset.Fingerprint,
|
||||
AnnouncementsUrl = SelectedPreset.AnnouncementsUrl
|
||||
};
|
||||
|
||||
new Thread (() => { SparkleShare.Controller.StartFetcher (info); }).Start ();
|
||||
}
|
||||
|
||||
|
||||
public void CopyToClipboardClicked ()
|
||||
{
|
||||
SparkleShare.Controller.CopyToClipboard (SparkleShare.Controller.UserAuthenticationInfo.PublicKey);
|
||||
}
|
||||
}
|
||||
}
|
55
SparkleShare/Common/PageControllers/PageController.Crypto.cs
Normal file
55
SparkleShare/Common/PageControllers/PageController.Crypto.cs
Normal file
|
@ -0,0 +1,55 @@
|
|||
// SparkleShare, a collaboration and sharing tool.
|
||||
// Copyright (C) 2010 Hylke Bons <hi@planetpeanut.uk>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
using Sparkles;
|
||||
|
||||
namespace SparkleShare {
|
||||
|
||||
public partial class PageController {
|
||||
|
||||
public void CheckCryptoSetupPage (string password)
|
||||
{
|
||||
new Thread (() => {
|
||||
bool is_valid_password = (password.Length > 0 && !password.StartsWith (" ") && !password.EndsWith (" "));
|
||||
PageCanContinueEvent (PageType.CryptoSetup, is_valid_password);
|
||||
}).Start ();
|
||||
}
|
||||
|
||||
|
||||
public void CheckCryptoPasswordPage (string password)
|
||||
{
|
||||
bool is_password_correct = SparkleShare.Controller.CheckPassword (password);
|
||||
PageCanContinueEvent (PageType.CryptoPassword, is_password_correct);
|
||||
}
|
||||
|
||||
|
||||
public void CryptoPageCompleted (string password)
|
||||
{
|
||||
ProgressBarPercentage = 100.0;
|
||||
ChangePageEvent (PageType.Progress);
|
||||
|
||||
new Thread (() => {
|
||||
Thread.Sleep (page_delay);
|
||||
SparkleShare.Controller.FinishFetcher (StorageType.Encrypted, password);
|
||||
|
||||
}).Start ();
|
||||
}
|
||||
}
|
||||
}
|
114
SparkleShare/Common/PageControllers/PageController.Host.cs
Normal file
114
SparkleShare/Common/PageControllers/PageController.Host.cs
Normal file
|
@ -0,0 +1,114 @@
|
|||
// SparkleShare, a collaboration and sharing tool.
|
||||
// Copyright (C) 2010 Hylke Bons <hi@planetpeanut.uk>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
|
||||
using Sparkles;
|
||||
|
||||
namespace SparkleShare {
|
||||
|
||||
public partial class PageController {
|
||||
|
||||
void LoadPresets ()
|
||||
{
|
||||
int local_presets_count = 0;
|
||||
string local_presets_path = Preset.LocalPresetsPath;
|
||||
|
||||
if (Directory.Exists (local_presets_path))
|
||||
// Local presets go first...
|
||||
foreach (string xml_file_path in Directory.GetFiles (local_presets_path, "*.xml")) {
|
||||
Presets.Add (new Preset (xml_file_path));
|
||||
local_presets_count++;
|
||||
}
|
||||
|
||||
// ...system presets after that...
|
||||
if (Directory.Exists (SparkleShare.Controller.PresetsPath)) {
|
||||
foreach (string xml_file_path in Directory.GetFiles (SparkleShare.Controller.PresetsPath, "*.xml")) {
|
||||
// ...and "Own server" at the very top
|
||||
if (xml_file_path.EndsWith ("own-server.xml"))
|
||||
Presets.Insert (0, new Preset (xml_file_path));
|
||||
else
|
||||
Presets.Add (new Preset (xml_file_path));
|
||||
}
|
||||
}
|
||||
|
||||
SelectedPreset = Presets [0];
|
||||
}
|
||||
|
||||
|
||||
public int SelectedPresetIndex {
|
||||
get {
|
||||
return Presets.IndexOf (SelectedPreset);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void SelectedPresetChanged (int preset_index)
|
||||
{
|
||||
SelectedPreset = Presets [preset_index];
|
||||
}
|
||||
|
||||
|
||||
public void HostPageCompleted ()
|
||||
{
|
||||
ChangePageEvent (PageType.Address);
|
||||
|
||||
string host = SelectedPreset.Address;
|
||||
|
||||
if (string.IsNullOrEmpty (host)) {
|
||||
if (string.IsNullOrEmpty (SelectedPreset.Host)) {
|
||||
new Thread (() => {
|
||||
Thread.Sleep (page_delay);
|
||||
AddressPagePublicKeyEvent (false, "", SelectedPreset.KeyEntryHint);
|
||||
|
||||
}).Start ();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
host = "ssh://" + SelectedPreset.Host;
|
||||
}
|
||||
|
||||
new Thread (() => {
|
||||
bool authenticated = true;
|
||||
string auth_status = "✓ Authenticated";
|
||||
|
||||
try {
|
||||
authenticated = SSHFetcher.CanAuthenticateTo (
|
||||
new Uri (host), SparkleShare.Controller.UserAuthenticationInfo);
|
||||
|
||||
} catch (NetworkException) {
|
||||
authenticated = false;
|
||||
}
|
||||
|
||||
if (authenticated) {
|
||||
if (!string.IsNullOrEmpty (SelectedPreset.Address))
|
||||
auth_status += string.Format (" to {0}", new Uri (host).Host);
|
||||
|
||||
} else {
|
||||
string public_key = "<tt>" + SparkleShare.Controller.UserAuthenticationInfo.PublicKey.Substring (0, 40) + "…</tt>";
|
||||
auth_status = public_key;
|
||||
}
|
||||
|
||||
AddressPagePublicKeyEvent (authenticated, auth_status, SelectedPreset.KeyEntryHint);
|
||||
|
||||
}).Start ();
|
||||
}
|
||||
}
|
||||
}
|
79
SparkleShare/Common/PageControllers/PageController.Invite.cs
Normal file
79
SparkleShare/Common/PageControllers/PageController.Invite.cs
Normal file
|
@ -0,0 +1,79 @@
|
|||
// SparkleShare, a collaboration and sharing tool.
|
||||
// Copyright (C) 2010 Hylke Bons <hi@planetpeanut.uk>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
|
||||
using Sparkles;
|
||||
|
||||
namespace SparkleShare {
|
||||
|
||||
public partial class PageController {
|
||||
|
||||
public void InvitePageCompleted ()
|
||||
{
|
||||
// TODO PreviousAddress = PendingInvite.Address;
|
||||
|
||||
ChangePageEvent (PageType.Progress);
|
||||
|
||||
new Thread (() => {
|
||||
if (!PendingInvite.Accept (SparkleShare.Controller.UserAuthenticationInfo.PublicKey)) {
|
||||
FetchAddress = new Uri (PendingInvite.Address + PendingInvite.RemotePath.TrimStart ('/'));
|
||||
// TODO ChangePageEvent (PageType.Error, new string [] { "error: Failed to upload the public key" });
|
||||
return;
|
||||
}
|
||||
|
||||
SparkleShare.Controller.FolderFetched += InvitePageFetchedDelegate;
|
||||
SparkleShare.Controller.FolderFetchError += InvitePageFetchErrorDelegate;
|
||||
SparkleShare.Controller.FolderFetching += ProgressPageFetchingDelegate;
|
||||
|
||||
var info = new FetcherInfo (new Uri (Path.Combine (PendingInvite.Address, PendingInvite.RemotePath))) {
|
||||
Fingerprint = PendingInvite.Fingerprint,
|
||||
AnnouncementsUrl = PendingInvite.AnnouncementsUrl
|
||||
};
|
||||
|
||||
SparkleShare.Controller.StartFetcher (info);
|
||||
|
||||
}).Start ();
|
||||
}
|
||||
|
||||
|
||||
void InvitePageFetchedDelegate (string remote_url)
|
||||
{
|
||||
PendingInvite = null;
|
||||
|
||||
// TODO success state + warning
|
||||
|
||||
SparkleShare.Controller.FolderFetched -= ProgressPageFetchedDelegate;
|
||||
SparkleShare.Controller.FolderFetchError -= ProgressPageFetchErrorDelegate;
|
||||
SparkleShare.Controller.FolderFetching -= ProgressPageFetchingDelegate;
|
||||
}
|
||||
|
||||
|
||||
void InvitePageFetchErrorDelegate (string remote_url, string error, string error_details)
|
||||
{
|
||||
FetchAddress = new Uri (remote_url);
|
||||
|
||||
//TODO ChangePageEvent (PageType.Error, errors);
|
||||
|
||||
SparkleShare.Controller.FolderFetched -= ProgressPageFetchedDelegate;
|
||||
SparkleShare.Controller.FolderFetchError -= ProgressPageFetchErrorDelegate;
|
||||
SparkleShare.Controller.FolderFetching -= ProgressPageFetchingDelegate;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
// SparkleShare, a collaboration and sharing tool.
|
||||
// Copyright (C) 2010 Hylke Bons <hi@planetpeanut.uk>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
using System;
|
||||
|
||||
namespace SparkleShare {
|
||||
|
||||
public partial class PageController {
|
||||
|
||||
public void PrivacyPageCompleted (bool notification_service, bool crash_reports, bool gravatars)
|
||||
{
|
||||
SparkleShare.Controller.Config.SetConfigOption ("notification_service", notification_service.ToString ());
|
||||
SparkleShare.Controller.Config.SetConfigOption ("crash_reports", crash_reports.ToString ());
|
||||
SparkleShare.Controller.Config.SetConfigOption ("gravatars", gravatars.ToString ());
|
||||
|
||||
ChangePageEvent (PageType.Host);
|
||||
}
|
||||
}
|
||||
}
|
114
SparkleShare/Common/PageControllers/PageController.Progress.cs
Normal file
114
SparkleShare/Common/PageControllers/PageController.Progress.cs
Normal file
|
@ -0,0 +1,114 @@
|
|||
// SparkleShare, a collaboration and sharing tool.
|
||||
// Copyright (C) 2010 Hylke Bons <hi@planetpeanut.uk>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
using Sparkles;
|
||||
|
||||
namespace SparkleShare {
|
||||
|
||||
public partial class PageController {
|
||||
|
||||
public event ProgressPageBarEventHandler ProgressPageBarEvent = delegate { };
|
||||
|
||||
public delegate void ProgressPageBarEventHandler (bool? success,
|
||||
string status, string status_details,
|
||||
double progress, string progress_details);
|
||||
|
||||
|
||||
void ProgressPageFetchedDelegate (string remote_url)
|
||||
{
|
||||
// Create a local preset for succesfully added projects, so
|
||||
// so the user can easily use the same host again
|
||||
if (SelectedPresetIndex == 0) {
|
||||
Preset new_preset;
|
||||
Uri uri = new Uri (remote_url);
|
||||
|
||||
try {
|
||||
string address = remote_url.Replace (uri.AbsolutePath, "");
|
||||
new_preset = Preset.Create (uri.Host, address, address, "", "", "/path/to/project");
|
||||
|
||||
if (new_preset != null) {
|
||||
Presets.Insert (1, new_preset);
|
||||
Logger.LogInfo ("Controller", "Added preset for " + uri.Host);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
Logger.LogInfo ("Controller", "Failed adding preset for " + uri.Host, e);
|
||||
}
|
||||
}
|
||||
|
||||
SparkleShare.Controller.FolderFetched -= ProgressPageFetchedDelegate;
|
||||
SparkleShare.Controller.FolderFetchError -= ProgressPageFetchErrorDelegate;
|
||||
SparkleShare.Controller.FolderFetching -= ProgressPageFetchingDelegate;
|
||||
|
||||
ProgressPageBarEvent (
|
||||
success: true,
|
||||
status: "Fetched all files from " + FetchAddress, status_details: null,
|
||||
progress: 100.0, progress_details: null);
|
||||
}
|
||||
|
||||
|
||||
void ProgressPageFetchErrorDelegate (string remote_url, string error, string error_details)
|
||||
{
|
||||
FetchAddress = new Uri (remote_url);
|
||||
|
||||
ProgressPageBarEvent (
|
||||
success: false,
|
||||
status: error, status_details: error_details,
|
||||
progress: ProgressBarPercentage, progress_details: "Could not download files from " + remote_url);
|
||||
|
||||
SparkleShare.Controller.FolderFetched -= ProgressPageFetchedDelegate;
|
||||
SparkleShare.Controller.FolderFetchError -= ProgressPageFetchErrorDelegate;
|
||||
SparkleShare.Controller.FolderFetching -= ProgressPageFetchingDelegate;
|
||||
}
|
||||
|
||||
|
||||
void ProgressPageFetchingDelegate (double percentage, double speed ,string information)
|
||||
{
|
||||
ProgressBarPercentage = percentage;
|
||||
|
||||
if (speed > 0)
|
||||
information = speed.ToSize () + " – " + information;
|
||||
|
||||
ProgressPageBarEvent (
|
||||
success: null,
|
||||
status: "Getting files", status_details: null,
|
||||
progress: ProgressBarPercentage, progress_details: information);
|
||||
}
|
||||
|
||||
|
||||
public void ErrorPageCompleted ()
|
||||
{
|
||||
if (PendingInvite != null)
|
||||
ChangePageEvent (PageType.Invite);
|
||||
else
|
||||
ChangePageEvent (PageType.Address);
|
||||
}
|
||||
|
||||
|
||||
public void ShowFilesClicked ()
|
||||
{
|
||||
string folder_name = Path.GetFileName (FetchAddress.AbsolutePath);
|
||||
folder_name = folder_name.ReplaceUnderscoreWithSpace ();
|
||||
|
||||
SparkleShare.Controller.OpenSparkleShareFolder (folder_name);
|
||||
ProgressPageCompleted ();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
// SparkleShare, a collaboration and sharing tool.
|
||||
// Copyright (C) 2010 Hylke Bons <hi@planetpeanut.uk>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
using Sparkles;
|
||||
|
||||
namespace SparkleShare {
|
||||
|
||||
public partial class PageController {
|
||||
|
||||
public void StoragePageCompleted (StorageType storage_type)
|
||||
{
|
||||
if (storage_type == StorageType.Encrypted) {
|
||||
ChangePageEvent (PageType.CryptoSetup);
|
||||
return;
|
||||
}
|
||||
|
||||
ProgressBarPercentage = 100.0;
|
||||
ChangePageEvent (PageType.Progress);
|
||||
|
||||
new Thread (() => {
|
||||
Thread.Sleep (page_delay);
|
||||
SparkleShare.Controller.FinishFetcher (storage_type);
|
||||
|
||||
}).Start ();
|
||||
}
|
||||
}
|
||||
}
|
45
SparkleShare/Common/PageControllers/PageController.User.cs
Normal file
45
SparkleShare/Common/PageControllers/PageController.User.cs
Normal file
|
@ -0,0 +1,45 @@
|
|||
// SparkleShare, a collaboration and sharing tool.
|
||||
// Copyright (C) 2010 Hylke Bons <hi@planetpeanut.uk>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
using Sparkles;
|
||||
|
||||
namespace SparkleShare {
|
||||
|
||||
public partial class PageController {
|
||||
|
||||
public void CheckUserPage (string name, string email)
|
||||
{
|
||||
name = name.Trim ();
|
||||
email = email.Trim ();
|
||||
|
||||
bool fields_valid = (!string.IsNullOrEmpty (name) && email.Contains ("@"));
|
||||
PageCanContinueEvent (PageType.User, fields_valid);
|
||||
}
|
||||
|
||||
|
||||
public void UserPageCompleted (string full_name, string email)
|
||||
{
|
||||
SparkleShare.Controller.CurrentUser = new User (full_name, email);
|
||||
new Thread (() => SparkleShare.Controller.CreateStartupItem ()).Start ();
|
||||
|
||||
ChangePageEvent (PageType.Privacy);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,22 +1,23 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<sparkleshare>
|
||||
<preset>
|
||||
<info>
|
||||
<name>Bitbucket</name>
|
||||
<description>Free code hosting for Git and Mercurial</description>
|
||||
<icon>bitbucket.png</icon>
|
||||
<backend>Git</backend>
|
||||
<fingerprint>cf:35:d0:39:74:91:04:48:94:b6:e1:3c:02:29:09:60:ac:1b:1d:ac:6f:49:cd:28:8d:ec:fd:61:76:86:a7:50</fingerprint>
|
||||
</info>
|
||||
<address>
|
||||
<value>ssh://git@bitbucket.org/</value>
|
||||
<example/>
|
||||
</address>
|
||||
<path>
|
||||
<value/>
|
||||
<example>/username/project</example>
|
||||
<uses_lower_case>True</uses_lower_case>
|
||||
</path>
|
||||
</preset>
|
||||
<preset>
|
||||
<info>
|
||||
<name>Bitbucket</name>
|
||||
<description>Free code hosting for Git and Mercurial</description>
|
||||
<icon>bitbucket.png</icon>
|
||||
<backend>Git</backend>
|
||||
<host>bitbucket.org</host>
|
||||
<fingerprint>cf:35:d0:39:74:91:04:48:94:b6:e1:3c:02:29:09:60:ac:1b:1d:ac:6f:49:cd:28:8d:ec:fd:61:76:86:a7:50</fingerprint>
|
||||
</info>
|
||||
<address>
|
||||
<value>ssh://git@bitbucket.org/</value>
|
||||
<example/>
|
||||
</address>
|
||||
<path>
|
||||
<value/>
|
||||
<example>/username/project</example>
|
||||
<uses_lower_case>True</uses_lower_case>
|
||||
</path>
|
||||
<key_entry_hint>Go to <b>Settings → SSH Keys</b> on <a href="https://bitbucket.org/">bitbucket.org</a> and add this SSH key:</key_entry_hint>
|
||||
</preset>
|
||||
</sparkleshare>
|
||||
|
||||
|
|
BIN
SparkleShare/Common/Presets/github-logo.png
Normal file
BIN
SparkleShare/Common/Presets/github-logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.4 KiB |
|
@ -1,21 +1,26 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<sparkleshare>
|
||||
<preset>
|
||||
<info>
|
||||
<name>GitHub</name>
|
||||
<description>The biggest collection of Open Source projects</description>
|
||||
<icon>github.png</icon>
|
||||
<backend>Git</backend>
|
||||
<storage_type>LargeFiles</storage_type>
|
||||
<fingerprint>9d:38:5b:83:a9:17:52:92:56:1a:5e:c4:d4:81:8e:0a:ca:51:a2:64:f1:74:20:11:2e:f8:8a:c3:a1:39:49:8f</fingerprint>
|
||||
</info>
|
||||
<address>
|
||||
<value>ssh://git@github.com/</value>
|
||||
<example/>
|
||||
</address>
|
||||
<path>
|
||||
<value/>
|
||||
<example>/username/project</example>
|
||||
</path>
|
||||
</preset>
|
||||
<preset>
|
||||
<info>
|
||||
<name>GitHub</name>
|
||||
<description>The biggest collection of Open Source projects</description>
|
||||
<icon>github.png</icon>
|
||||
<logo>github-logo.png</logo>
|
||||
<backend>Git</backend>
|
||||
<host>github.com</host>
|
||||
<fingerprint>9d:38:5b:83:a9:17:52:92:56:1a:5e:c4:d4:81:8e:0a:ca:51:a2:64:f1:74:20:11:2e:f8:8a:c3:a1:39:49:8f</fingerprint>
|
||||
<storage_type>LargeFiles</storage_type>
|
||||
</info>
|
||||
<address>
|
||||
<value>ssh://git@github.com/</value>
|
||||
<example/>
|
||||
</address>
|
||||
<path>
|
||||
<value/>
|
||||
<example>/username/project</example>
|
||||
</path>
|
||||
<key>
|
||||
<hint>Go to <a href="https://github.com/settings/keys">github.com/settings/keys</a> and add this SSH key:</hint>
|
||||
</key>
|
||||
</preset>
|
||||
</sparkleshare>
|
||||
|
|
BIN
SparkleShare/Common/Presets/gitlab-logo.png
Normal file
BIN
SparkleShare/Common/Presets/gitlab-logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5 KiB |
|
@ -1,21 +1,25 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<sparkleshare>
|
||||
<preset>
|
||||
<info>
|
||||
<name>GitLab</name>
|
||||
<description>Open Source alternative to GitHub</description>
|
||||
<icon>gitlab.png</icon>
|
||||
<backend>Git</backend>
|
||||
<fingerprint>44:e4:05:bc:f4:e1:1a:b5:b8:46:e5:8b:a0:bf:6d:ab:d2:3d:cc:9e:36:7c:ae:17:cb:0c:91:b5:b3:b3:fc:44</fingerprint>
|
||||
</info>
|
||||
<address>
|
||||
<value>ssh://git@gitlab.com/</value>
|
||||
<example/>
|
||||
</address>
|
||||
<path>
|
||||
<value/>
|
||||
<example>/username/project</example>
|
||||
</path>
|
||||
</preset>
|
||||
<preset>
|
||||
<info>
|
||||
<name>GitLab</name>
|
||||
<description>Open Source alternative to GitHub</description>
|
||||
<icon>gitlab.png</icon>
|
||||
<logo>gitlab-logo.png</logo>
|
||||
<backend>Git</backend>
|
||||
<host>gitlab.com</host>
|
||||
<fingerprint>44:e4:05:bc:f4:e1:1a:b5:b8:46:e5:8b:a0:bf:6d:ab:d2:3d:cc:9e:36:7c:ae:17:cb:0c:91:b5:b3:b3:fc:44</fingerprint>
|
||||
</info>
|
||||
<address>
|
||||
<value>ssh://git@gitlab.com/</value>
|
||||
<example/>
|
||||
</address>
|
||||
<path>
|
||||
<value/>
|
||||
<example>/username/project</example>
|
||||
</path>
|
||||
<key>
|
||||
<hint>Go to <a href="https://gitlab.com/profile/keys">gitlab.com/profile/keys</a> and add this SSH key:</hint>
|
||||
</key>
|
||||
</preset>
|
||||
</sparkleshare>
|
||||
|
||||
|
|
|
@ -1,9 +1,18 @@
|
|||
preset_files = ['github.xml', 'github.png',
|
||||
'gitlab.xml', 'gitlab.png',
|
||||
'bitbucket.xml', 'bitbucket.png',
|
||||
'planio.xml', 'planio.png',
|
||||
'own-server.xml', 'own-server.png'
|
||||
]
|
||||
# Github
|
||||
preset_files = ['github.xml', 'github.png', 'github-logo.png']
|
||||
|
||||
# GitLab
|
||||
preset_files += ['gitlab.xml', 'gitlab.png', 'gitlab-logo.png']
|
||||
|
||||
# Bitbucket
|
||||
preset_files += ['bitbucket.xml', 'bitbucket.png']
|
||||
|
||||
# Planio
|
||||
preset_files += ['planio.xml', 'planio.png', 'planio-logo.png']
|
||||
|
||||
# Other
|
||||
preset_files += ['own-server.xml', 'own-server.png']
|
||||
|
||||
|
||||
install_data(
|
||||
sources: preset_files,
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<sparkleshare>
|
||||
<preset>
|
||||
<info>
|
||||
<name>Own server</name>
|
||||
<description>Everything under my control</description>
|
||||
<icon>own-server.png</icon>
|
||||
<backend>Git</backend>
|
||||
</info>
|
||||
<address>
|
||||
<value/>
|
||||
<example>ssh://[user@]hostname[:port]</example>
|
||||
</address>
|
||||
<path>
|
||||
<value/>
|
||||
<example>/path/to/project</example>
|
||||
</path>
|
||||
</preset>
|
||||
<preset>
|
||||
<info>
|
||||
<name>Own server</name>
|
||||
<description>Everything under my control</description>
|
||||
<key_entry_hint>Ask the person administrating the server to add this SSH key:</key_entry_hint>
|
||||
<icon>own-server.png</icon>
|
||||
<backend>Git</backend>
|
||||
</info>
|
||||
<address>
|
||||
<value/>
|
||||
<example>ssh://[user@]hostname[:port]</example>
|
||||
</address>
|
||||
<path>
|
||||
<value/>
|
||||
<example>/path/to/project</example>
|
||||
</path>
|
||||
</preset>
|
||||
</sparkleshare>
|
||||
|
||||
|
|
BIN
SparkleShare/Common/Presets/planio-logo.png
Normal file
BIN
SparkleShare/Common/Presets/planio-logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.9 KiB |
|
@ -1,22 +1,26 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<sparkleshare>
|
||||
<preset>
|
||||
<info>
|
||||
<name>Planio</name>
|
||||
<description>Online project management</description>
|
||||
<icon>planio.png</icon>
|
||||
<backend>Git</backend>
|
||||
<fingerprint>38:29:13:0f:7c:74:67:22:c5:a6:a6:95:b4:b8:e0:ef:3d:e0:9e:87:02:58:ff:37:2c:8b:34:5a:ed:73:5d:81</fingerprint>
|
||||
<announcements_url>tcp://sparkleshare-notifications.plan.io:443</announcements_url>
|
||||
</info>
|
||||
<address>
|
||||
<value/>
|
||||
<example>ssh://git@[account].plan.io</example>
|
||||
</address>
|
||||
<path>
|
||||
<value/>
|
||||
<example>/[account]-[project].git</example>
|
||||
</path>
|
||||
</preset>
|
||||
<preset>
|
||||
<info>
|
||||
<name>Planio</name>
|
||||
<description>Online project management</description>
|
||||
<icon>planio.png</icon>
|
||||
<logo>planio-logo.png</logo>
|
||||
<backend>Git</backend>
|
||||
<host>plan.io</host>
|
||||
<fingerprint>38:29:13:0f:7c:74:67:22:c5:a6:a6:95:b4:b8:e0:ef:3d:e0:9e:87:02:58:ff:37:2c:8b:34:5a:ed:73:5d:81</fingerprint>
|
||||
<announcements_url>tcp://sparkleshare-notifications.plan.io:443</announcements_url>
|
||||
</info>
|
||||
<address>
|
||||
<value/>
|
||||
<example>ssh://git@[account].plan.io</example>
|
||||
</address>
|
||||
<path>
|
||||
<value/>
|
||||
<example>/[account]-[project].git</example>
|
||||
</path>
|
||||
<key>
|
||||
<hint>Go to <b>My account → Public keys</b> on <a href="https://plan.io/">plan.io</a> and add this key:</hint>
|
||||
</key>
|
||||
</preset>
|
||||
</sparkleshare>
|
||||
|
||||
|
|
|
@ -1,566 +0,0 @@
|
|||
// SparkleShare, a collaboration and sharing tool.
|
||||
// Copyright (C) 2010 Hylke Bons <hi@planetpeanut.uk>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
|
||||
using Sparkles;
|
||||
|
||||
namespace SparkleShare {
|
||||
|
||||
public enum PageType {
|
||||
None,
|
||||
Setup,
|
||||
Add,
|
||||
Invite,
|
||||
Syncing,
|
||||
Error,
|
||||
Finished,
|
||||
StorageSetup,
|
||||
CryptoSetup,
|
||||
CryptoPassword
|
||||
}
|
||||
|
||||
public enum FieldState {
|
||||
Enabled,
|
||||
Disabled
|
||||
}
|
||||
|
||||
|
||||
public class SetupController {
|
||||
|
||||
public event Action ShowWindowEvent = delegate { };
|
||||
public event Action HideWindowEvent = delegate { };
|
||||
|
||||
public event ChangePageEventHandler ChangePageEvent = delegate { };
|
||||
public delegate void ChangePageEventHandler (PageType page, string [] warnings);
|
||||
|
||||
public event UpdateProgressBarEventHandler UpdateProgressBarEvent = delegate { };
|
||||
public delegate void UpdateProgressBarEventHandler (double percentage, string information);
|
||||
|
||||
public event UpdateSetupContinueButtonEventHandler UpdateSetupContinueButtonEvent = delegate { };
|
||||
public delegate void UpdateSetupContinueButtonEventHandler (bool button_enabled);
|
||||
|
||||
public event UpdateCryptoSetupContinueButtonEventHandler UpdateCryptoSetupContinueButtonEvent = delegate { };
|
||||
public delegate void UpdateCryptoSetupContinueButtonEventHandler (bool button_enabled);
|
||||
|
||||
public event UpdateCryptoPasswordContinueButtonEventHandler UpdateCryptoPasswordContinueButtonEvent = delegate { };
|
||||
public delegate void UpdateCryptoPasswordContinueButtonEventHandler (bool button_enabled);
|
||||
|
||||
public event UpdateAddProjectButtonEventHandler UpdateAddProjectButtonEvent = delegate { };
|
||||
public delegate void UpdateAddProjectButtonEventHandler (bool button_enabled);
|
||||
|
||||
public event ChangeAddressFieldEventHandler ChangeAddressFieldEvent = delegate { };
|
||||
public delegate void ChangeAddressFieldEventHandler (string text, string example_text, FieldState state);
|
||||
|
||||
public event ChangePathFieldEventHandler ChangePathFieldEvent = delegate { };
|
||||
public delegate void ChangePathFieldEventHandler (string text, string example_text, FieldState state);
|
||||
|
||||
public readonly List<Preset> Presets = new List<Preset> ();
|
||||
public Preset SelectedPreset;
|
||||
|
||||
public bool WindowIsOpen { get; private set; }
|
||||
public SparkleInvite PendingInvite { 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 double ProgressBarPercentage { get; private set; }
|
||||
|
||||
|
||||
public int SelectedPresetIndex {
|
||||
get {
|
||||
return Presets.IndexOf (SelectedPreset);
|
||||
}
|
||||
}
|
||||
|
||||
public bool FetchPriorHistory {
|
||||
get {
|
||||
return this.fetch_prior_history;
|
||||
}
|
||||
}
|
||||
|
||||
private PageType current_page;
|
||||
private string saved_address = "";
|
||||
private string saved_remote_path = "";
|
||||
private bool fetch_prior_history = false;
|
||||
|
||||
|
||||
public SetupController ()
|
||||
{
|
||||
ChangePageEvent += delegate (PageType page_type, string [] warnings) {
|
||||
this.current_page = page_type;
|
||||
};
|
||||
|
||||
PreviousAddress = "";
|
||||
PreviousPath = "";
|
||||
PreviousUrl = "";
|
||||
SyncingFolder = "";
|
||||
|
||||
string local_presets_path = Preset.LocalPresetsPath;
|
||||
int local_presets_count = 0;
|
||||
|
||||
// Import all of the presets
|
||||
if (Directory.Exists (local_presets_path))
|
||||
// Local presets go first...
|
||||
foreach (string xml_file_path in Directory.GetFiles (local_presets_path, "*.xml")) {
|
||||
Presets.Add (new Preset (xml_file_path));
|
||||
local_presets_count++;
|
||||
}
|
||||
|
||||
// ...system presets after that...
|
||||
if (Directory.Exists (SparkleShare.Controller.PresetsPath)) {
|
||||
foreach (string xml_file_path in Directory.GetFiles (SparkleShare.Controller.PresetsPath, "*.xml")) {
|
||||
// ...and "Own server" at the very top
|
||||
if (xml_file_path.EndsWith ("own-server.xml"))
|
||||
Presets.Insert (0, new Preset (xml_file_path));
|
||||
else
|
||||
Presets.Add (new Preset (xml_file_path));
|
||||
}
|
||||
}
|
||||
|
||||
SelectedPreset = Presets [0];
|
||||
|
||||
SparkleShare.Controller.InviteReceived += delegate (SparkleInvite invite) {
|
||||
PendingInvite = invite;
|
||||
|
||||
ChangePageEvent (PageType.Invite, null);
|
||||
ShowWindowEvent ();
|
||||
};
|
||||
|
||||
SparkleShare.Controller.ShowSetupWindowEvent += delegate (PageType page_type) {
|
||||
if (page_type == PageType.StorageSetup ||
|
||||
page_type == PageType.CryptoSetup ||
|
||||
page_type == PageType.CryptoPassword) {
|
||||
|
||||
ChangePageEvent (page_type, null);
|
||||
return;
|
||||
}
|
||||
|
||||
if (PendingInvite != null) {
|
||||
WindowIsOpen = true;
|
||||
ShowWindowEvent ();
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.current_page == PageType.Syncing ||
|
||||
this.current_page == PageType.Finished ||
|
||||
this.current_page == PageType.CryptoSetup ||
|
||||
this.current_page == PageType.CryptoPassword) {
|
||||
|
||||
ShowWindowEvent ();
|
||||
return;
|
||||
}
|
||||
|
||||
if (page_type == PageType.Add) {
|
||||
if (WindowIsOpen) {
|
||||
if (this.current_page == PageType.Error ||
|
||||
this.current_page == PageType.Finished ||
|
||||
this.current_page == PageType.None) {
|
||||
|
||||
ChangePageEvent (PageType.Add, null);
|
||||
}
|
||||
|
||||
} else if (!SparkleShare.Controller.FirstRun) {
|
||||
WindowIsOpen = true;
|
||||
ChangePageEvent (PageType.Add, null);
|
||||
}
|
||||
|
||||
ShowWindowEvent ();
|
||||
return;
|
||||
}
|
||||
|
||||
WindowIsOpen = true;
|
||||
ChangePageEvent (page_type, null);
|
||||
ShowWindowEvent ();
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
public void PageCancelled ()
|
||||
{
|
||||
PendingInvite = null;
|
||||
SelectedPreset = Presets [0];
|
||||
|
||||
PreviousAddress = "";
|
||||
PreviousPath = "";
|
||||
PreviousUrl = "";
|
||||
|
||||
this.saved_address = "";
|
||||
this.saved_remote_path = "";
|
||||
this.fetch_prior_history = false;
|
||||
|
||||
WindowIsOpen = false;
|
||||
HideWindowEvent ();
|
||||
}
|
||||
|
||||
|
||||
public void CheckSetupPage (string full_name, string email)
|
||||
{
|
||||
full_name = full_name.Trim ();
|
||||
email = email.Trim ();
|
||||
|
||||
bool fields_valid = (!string.IsNullOrEmpty (full_name) && IsValidEmail (email));
|
||||
UpdateSetupContinueButtonEvent (fields_valid);
|
||||
}
|
||||
|
||||
|
||||
public void SetupPageCancelled ()
|
||||
{
|
||||
SparkleShare.Controller.Quit ();
|
||||
}
|
||||
|
||||
|
||||
public void SetupPageCompleted (string full_name, string email)
|
||||
{
|
||||
SparkleShare.Controller.CurrentUser = new User (full_name, email);
|
||||
new Thread (() => SparkleShare.Controller.CreateStartupItem ()).Start ();
|
||||
|
||||
ChangePageEvent (PageType.Add, null);
|
||||
}
|
||||
|
||||
|
||||
public void HistoryItemChanged (bool fetch_prior_history)
|
||||
{
|
||||
this.fetch_prior_history = fetch_prior_history;
|
||||
}
|
||||
|
||||
|
||||
public void SelectedPresetChanged (int preset_index)
|
||||
{
|
||||
SelectedPreset = Presets [preset_index];
|
||||
|
||||
if (SelectedPreset.Address != null) {
|
||||
ChangeAddressFieldEvent (SelectedPreset.Address, "", FieldState.Disabled);
|
||||
|
||||
} else if (SelectedPreset.AddressExample != null) {
|
||||
ChangeAddressFieldEvent (this.saved_address, SelectedPreset.AddressExample, FieldState.Enabled);
|
||||
|
||||
} else {
|
||||
ChangeAddressFieldEvent (this.saved_address, "", FieldState.Enabled);
|
||||
}
|
||||
|
||||
if (SelectedPreset.Path != null) {
|
||||
ChangePathFieldEvent (SelectedPreset.Path, "", FieldState.Disabled);
|
||||
|
||||
} else if (SelectedPreset.PathExample != null) {
|
||||
ChangePathFieldEvent (this.saved_remote_path, SelectedPreset.PathExample, FieldState.Enabled);
|
||||
|
||||
} else {
|
||||
ChangePathFieldEvent (this.saved_remote_path, "", FieldState.Enabled);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void CheckAddPage (string address, string remote_path, int selected_preset)
|
||||
{
|
||||
address = address.Trim ();
|
||||
remote_path = remote_path.Trim ();
|
||||
|
||||
if (selected_preset == 0)
|
||||
this.saved_address = address;
|
||||
|
||||
this.saved_remote_path = remote_path;
|
||||
|
||||
bool fields_valid = (!string.IsNullOrEmpty (address) &&
|
||||
!string.IsNullOrEmpty (remote_path) && !remote_path.Contains ("\""));
|
||||
|
||||
UpdateAddProjectButtonEvent (fields_valid);
|
||||
}
|
||||
|
||||
|
||||
public void AddPageCompleted (string address, string remote_path)
|
||||
{
|
||||
SyncingFolder = Path.GetFileName (remote_path);
|
||||
|
||||
if (remote_path.EndsWith (".git"))
|
||||
SyncingFolder = remote_path.Substring (0, remote_path.Length - 4);
|
||||
|
||||
SyncingFolder = SyncingFolder.ReplaceUnderscoreWithSpace ();
|
||||
ProgressBarPercentage = 1.0;
|
||||
|
||||
ChangePageEvent (PageType.Syncing, null);
|
||||
|
||||
address = Uri.EscapeUriString (address.Trim ());
|
||||
remote_path = remote_path.Trim ();
|
||||
remote_path = remote_path.TrimEnd ("/".ToCharArray ());
|
||||
|
||||
if (SelectedPreset.PathUsesLowerCase)
|
||||
remote_path = remote_path.ToLower ();
|
||||
|
||||
PreviousAddress = address;
|
||||
PreviousPath = remote_path;
|
||||
|
||||
SparkleShare.Controller.FolderFetched += AddPageFetchedDelegate;
|
||||
SparkleShare.Controller.FolderFetchError += AddPageFetchErrorDelegate;
|
||||
SparkleShare.Controller.FolderFetching += SyncingPageFetchingDelegate;
|
||||
|
||||
SparkleFetcherInfo info = new SparkleFetcherInfo {
|
||||
Address = address,
|
||||
Fingerprint = SelectedPreset.Fingerprint,
|
||||
RemotePath = remote_path,
|
||||
FetchPriorHistory = this.fetch_prior_history,
|
||||
AnnouncementsUrl = SelectedPreset.AnnouncementsUrl,
|
||||
Backend = SelectedPreset.Backend
|
||||
};
|
||||
|
||||
new Thread (() => { SparkleShare.Controller.StartFetcher (info); }).Start ();
|
||||
}
|
||||
|
||||
// The following private methods are
|
||||
// delegates used by the previous method
|
||||
|
||||
private void AddPageFetchedDelegate (string remote_url, string [] warnings)
|
||||
{
|
||||
SyncingFolder = "";
|
||||
|
||||
// Create a local preset for succesfully added projects, so
|
||||
// so the user can easily use the same host again
|
||||
if (SelectedPresetIndex == 0) {
|
||||
Preset new_preset;
|
||||
Uri uri = new Uri (remote_url);
|
||||
|
||||
try {
|
||||
string address = remote_url.Replace (uri.AbsolutePath, "");
|
||||
new_preset = Preset.Create (uri.Host, address, address, "", "", "/path/to/project");
|
||||
|
||||
if (new_preset != null) {
|
||||
Presets.Insert (1, new_preset);
|
||||
Logger.LogInfo ("Controller", "Added preset for " + uri.Host);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
Logger.LogInfo ("Controller", "Failed adding preset for " + uri.Host, e);
|
||||
}
|
||||
}
|
||||
|
||||
ChangePageEvent (PageType.Finished, warnings);
|
||||
|
||||
SparkleShare.Controller.FolderFetched -= AddPageFetchedDelegate;
|
||||
SparkleShare.Controller.FolderFetchError -= AddPageFetchErrorDelegate;
|
||||
SparkleShare.Controller.FolderFetching -= SyncingPageFetchingDelegate;
|
||||
}
|
||||
|
||||
private void AddPageFetchErrorDelegate (string remote_url, string [] errors)
|
||||
{
|
||||
SyncingFolder = "";
|
||||
PreviousUrl = remote_url;
|
||||
|
||||
ChangePageEvent (PageType.Error, errors);
|
||||
|
||||
SparkleShare.Controller.FolderFetched -= AddPageFetchedDelegate;
|
||||
SparkleShare.Controller.FolderFetchError -= AddPageFetchErrorDelegate;
|
||||
SparkleShare.Controller.FolderFetching -= SyncingPageFetchingDelegate;
|
||||
}
|
||||
|
||||
private void SyncingPageFetchingDelegate (double percentage, double speed ,string information)
|
||||
{
|
||||
ProgressBarPercentage = percentage;
|
||||
|
||||
if (speed > 0)
|
||||
information = speed.ToSize () + " – " + information;
|
||||
|
||||
UpdateProgressBarEvent (ProgressBarPercentage, information);
|
||||
}
|
||||
|
||||
|
||||
public void InvitePageCompleted ()
|
||||
{
|
||||
SyncingFolder = Path.GetFileName (PendingInvite.RemotePath);
|
||||
|
||||
if (PendingInvite.RemotePath.EndsWith (".git"))
|
||||
SyncingFolder = PendingInvite.RemotePath.Substring (0, PendingInvite.RemotePath.Length - 4);
|
||||
|
||||
SyncingFolder = SyncingFolder.ReplaceUnderscoreWithSpace ();
|
||||
PreviousAddress = PendingInvite.Address;
|
||||
PreviousPath = PendingInvite.RemotePath;
|
||||
|
||||
ChangePageEvent (PageType.Syncing, null);
|
||||
|
||||
new Thread (() => {
|
||||
if (!PendingInvite.Accept (SparkleShare.Controller.UserAuthenticationInfo.PublicKey)) {
|
||||
PreviousUrl = PendingInvite.Address + PendingInvite.RemotePath.TrimStart ("/".ToCharArray ());
|
||||
ChangePageEvent (PageType.Error, new string [] { "error: Failed to upload the public key" });
|
||||
return;
|
||||
}
|
||||
|
||||
SparkleShare.Controller.FolderFetched += InvitePageFetchedDelegate;
|
||||
SparkleShare.Controller.FolderFetchError += InvitePageFetchErrorDelegate;
|
||||
SparkleShare.Controller.FolderFetching += SyncingPageFetchingDelegate;
|
||||
|
||||
SparkleFetcherInfo info = new SparkleFetcherInfo {
|
||||
Address = PendingInvite.Address,
|
||||
Fingerprint = PendingInvite.Fingerprint,
|
||||
RemotePath = PendingInvite.RemotePath,
|
||||
FetchPriorHistory = false, // TODO: checkbox on invite page
|
||||
AnnouncementsUrl = PendingInvite.AnnouncementsUrl
|
||||
};
|
||||
|
||||
SparkleShare.Controller.StartFetcher (info);
|
||||
|
||||
}).Start ();
|
||||
}
|
||||
|
||||
// The following private methods are
|
||||
// delegates used by the previous method
|
||||
|
||||
private void InvitePageFetchedDelegate (string remote_url, string [] warnings)
|
||||
{
|
||||
SyncingFolder = "";
|
||||
PendingInvite = null;
|
||||
|
||||
ChangePageEvent (PageType.Finished, warnings);
|
||||
|
||||
SparkleShare.Controller.FolderFetched -= AddPageFetchedDelegate;
|
||||
SparkleShare.Controller.FolderFetchError -= AddPageFetchErrorDelegate;
|
||||
SparkleShare.Controller.FolderFetching -= SyncingPageFetchingDelegate;
|
||||
}
|
||||
|
||||
private void InvitePageFetchErrorDelegate (string remote_url, string [] errors)
|
||||
{
|
||||
SyncingFolder = "";
|
||||
PreviousUrl = remote_url;
|
||||
|
||||
ChangePageEvent (PageType.Error, errors);
|
||||
|
||||
SparkleShare.Controller.FolderFetched -= AddPageFetchedDelegate;
|
||||
SparkleShare.Controller.FolderFetchError -= AddPageFetchErrorDelegate;
|
||||
SparkleShare.Controller.FolderFetching -= SyncingPageFetchingDelegate;
|
||||
}
|
||||
|
||||
|
||||
public void SyncingCancelled ()
|
||||
{
|
||||
SparkleShare.Controller.StopFetcher ();
|
||||
|
||||
if (PendingInvite != null)
|
||||
ChangePageEvent (PageType.Invite, null);
|
||||
else
|
||||
ChangePageEvent (PageType.Add, null);
|
||||
}
|
||||
|
||||
|
||||
public void ErrorPageCompleted ()
|
||||
{
|
||||
if (PendingInvite != null)
|
||||
ChangePageEvent (PageType.Invite, null);
|
||||
else
|
||||
ChangePageEvent (PageType.Add, null);
|
||||
}
|
||||
|
||||
|
||||
public void StoragePageCompleted (StorageType storage_type)
|
||||
{
|
||||
if (storage_type == StorageType.Encrypted) {
|
||||
ChangePageEvent (PageType.CryptoSetup, null);
|
||||
return;
|
||||
}
|
||||
|
||||
ProgressBarPercentage = 100.0;
|
||||
ChangePageEvent (PageType.Syncing, null);
|
||||
|
||||
new Thread (() => {
|
||||
Thread.Sleep (1000);
|
||||
SparkleShare.Controller.FinishFetcher (storage_type);
|
||||
|
||||
}).Start ();
|
||||
}
|
||||
|
||||
|
||||
public void CheckCryptoSetupPage (string password)
|
||||
{
|
||||
new Thread (() => {
|
||||
bool is_valid_password = (password.Length > 0 && !password.StartsWith (" ") && !password.EndsWith (" "));
|
||||
UpdateCryptoSetupContinueButtonEvent (is_valid_password);
|
||||
}).Start ();
|
||||
}
|
||||
|
||||
|
||||
public void CheckCryptoPasswordPage (string password)
|
||||
{
|
||||
bool is_password_correct = SparkleShare.Controller.CheckPassword (password);
|
||||
UpdateCryptoPasswordContinueButtonEvent (is_password_correct);
|
||||
}
|
||||
|
||||
|
||||
public void CryptoPageCancelled ()
|
||||
{
|
||||
SyncingCancelled ();
|
||||
}
|
||||
|
||||
|
||||
public void CryptoSetupPageCompleted (string password)
|
||||
{
|
||||
CryptoPasswordPageCompleted (password);
|
||||
}
|
||||
|
||||
|
||||
public void CryptoPasswordPageCompleted (string password)
|
||||
{
|
||||
ProgressBarPercentage = 100.0;
|
||||
ChangePageEvent (PageType.Syncing, null);
|
||||
|
||||
new Thread (() => {
|
||||
Thread.Sleep (1000);
|
||||
SparkleShare.Controller.FinishFetcher (StorageType.Encrypted, password);
|
||||
|
||||
}).Start ();
|
||||
}
|
||||
|
||||
|
||||
public void CopyToClipboardClicked ()
|
||||
{
|
||||
SparkleShare.Controller.CopyToClipboard (SparkleShare.Controller.UserAuthenticationInfo.PublicKey);
|
||||
}
|
||||
|
||||
|
||||
public void ShowFilesClicked ()
|
||||
{
|
||||
string folder_name = Path.GetFileName (PreviousPath);
|
||||
folder_name = folder_name.ReplaceUnderscoreWithSpace ();
|
||||
|
||||
SparkleShare.Controller.OpenSparkleShareFolder (folder_name);
|
||||
FinishPageCompleted ();
|
||||
}
|
||||
|
||||
|
||||
public void FinishPageCompleted ()
|
||||
{
|
||||
SelectedPreset = Presets [0];
|
||||
PreviousUrl = "";
|
||||
PreviousAddress = "";
|
||||
PreviousPath = "";
|
||||
|
||||
this.fetch_prior_history = false;
|
||||
this.saved_address = "";
|
||||
this.saved_remote_path = "";
|
||||
this.current_page = PageType.None;
|
||||
|
||||
WindowIsOpen = false;
|
||||
HideWindowEvent ();
|
||||
}
|
||||
|
||||
|
||||
private bool IsValidEmail (string email)
|
||||
{
|
||||
return email.Contains ("@");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -46,14 +46,14 @@ namespace SparkleShare {
|
|||
|
||||
public string StatusMessage {
|
||||
get {
|
||||
string status_message = "Waiting to sync";
|
||||
|
||||
if (!repo.LastSync.Equals (DateTime.MinValue))
|
||||
string status_message = "Ready to sync";
|
||||
|
||||
if (repo.LastSync > DateTime.MinValue)
|
||||
status_message = string.Format ("✓ Synced – Last change {0}", repo.LastSync.ToPrettyDate ());
|
||||
|
||||
if (repo.Status == SyncStatus.SyncUp)
|
||||
status_message = "Sending… " + (int) repo.ProgressPercentage + "%";
|
||||
|
||||
|
||||
if (repo.Status == SyncStatus.SyncDown)
|
||||
status_message = "Receiving… " + (int) repo.ProgressPercentage + "%";
|
||||
|
||||
|
@ -136,7 +136,7 @@ namespace SparkleShare {
|
|||
public delegate void UpdateQuitItemEventHandler (bool quit_item_enabled);
|
||||
|
||||
public IconState CurrentState = IconState.Idle;
|
||||
public string StateText = "Welcome to SparkleShare!";
|
||||
public string StateText = "Welcome to SparkleShare";
|
||||
|
||||
public ProjectInfo [] Projects = new ProjectInfo [0];
|
||||
|
||||
|
@ -147,11 +147,6 @@ namespace SparkleShare {
|
|||
}
|
||||
}
|
||||
|
||||
public bool LinkCodeItemEnabled {
|
||||
get {
|
||||
return !string.IsNullOrEmpty (SparkleShare.Controller.UserAuthenticationInfo.PublicKey);
|
||||
}
|
||||
}
|
||||
|
||||
public bool QuitItemEnabled {
|
||||
get {
|
||||
|
@ -307,13 +302,9 @@ namespace SparkleShare {
|
|||
|
||||
public void AddHostedProjectClicked ()
|
||||
{
|
||||
new Thread (() => SparkleShare.Controller.ShowSetupWindow (PageType.Add)).Start ();
|
||||
new Thread (() => SparkleShare.Controller.ShowSetupWindow (PageType.Host)).Start ();
|
||||
}
|
||||
|
||||
public void CopyToClipboardClicked ()
|
||||
{
|
||||
SparkleShare.Controller.CopyToClipboard (SparkleShare.Controller.UserAuthenticationInfo.PublicKey);
|
||||
}
|
||||
|
||||
public void AboutClicked ()
|
||||
{
|
||||
|
|
|
@ -1,704 +0,0 @@
|
|||
// SparkleShare, a collaboration and sharing tool.
|
||||
// Copyright (C) 2010 Hylke Bons <hi@planetpeanut.uk>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General private License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General private License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General private License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
using System;
|
||||
|
||||
using Gtk;
|
||||
using Mono.Unix;
|
||||
|
||||
using Sparkles;
|
||||
|
||||
namespace SparkleShare {
|
||||
|
||||
public class Setup : SetupWindow {
|
||||
|
||||
public SetupController Controller = new SetupController ();
|
||||
|
||||
|
||||
public Setup ()
|
||||
{
|
||||
Controller.HideWindowEvent += delegate {
|
||||
Application.Invoke (delegate { Hide (); });
|
||||
};
|
||||
|
||||
Controller.ShowWindowEvent += delegate {
|
||||
Application.Invoke (delegate {
|
||||
ShowAll ();
|
||||
Present ();
|
||||
});
|
||||
};
|
||||
|
||||
Controller.ChangePageEvent += delegate (PageType type, string [] warnings) {
|
||||
Application.Invoke (delegate {
|
||||
Reset ();
|
||||
ShowPage (type, warnings);
|
||||
ShowAll ();
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
public void ShowPage (PageType type, string [] warnings)
|
||||
{
|
||||
if (type == PageType.Setup) {
|
||||
Header = "Welcome to SparkleShare!";
|
||||
Description = "First off, what’s your name and email?\n(visible only to team members)";
|
||||
|
||||
Table table = new Table (2, 3, true) {
|
||||
RowSpacing = 6,
|
||||
ColumnSpacing = 6
|
||||
};
|
||||
|
||||
Label name_label = new Label ("<b>" + "Your Name:" + "</b>") {
|
||||
UseMarkup = true,
|
||||
Xalign = 1
|
||||
};
|
||||
|
||||
Entry name_entry = new Entry () {
|
||||
Xalign = 0,
|
||||
ActivatesDefault = true
|
||||
};
|
||||
|
||||
try {
|
||||
UnixUserInfo user_info = UnixUserInfo.GetRealUser ();
|
||||
|
||||
if (user_info != null && user_info.RealName != null)
|
||||
// Some systems append a series of "," for some reason, TODO: Report upstream
|
||||
name_entry.Text = user_info.RealName.TrimEnd (",".ToCharArray ());
|
||||
|
||||
} catch (ArgumentException) {
|
||||
// No username, not a big deal
|
||||
}
|
||||
|
||||
Entry email_entry = new Entry () {
|
||||
Xalign = 0,
|
||||
ActivatesDefault = true
|
||||
};
|
||||
|
||||
Label email_label = new Label ("<b>" + "Email:" + "</b>") {
|
||||
UseMarkup = true,
|
||||
Xalign = 1
|
||||
};
|
||||
|
||||
table.Attach (name_label, 0, 1, 0, 1);
|
||||
table.Attach (name_entry, 1, 2, 0, 1);
|
||||
table.Attach (email_label, 0, 1, 1, 2);
|
||||
table.Attach (email_entry, 1, 2, 1, 2);
|
||||
|
||||
VBox wrapper = new VBox (false, 9);
|
||||
wrapper.PackStart (table, true, false, 0);
|
||||
|
||||
Button cancel_button = new Button ("Cancel");
|
||||
Button continue_button = new Button ("Continue") { Sensitive = false };
|
||||
|
||||
|
||||
Controller.UpdateSetupContinueButtonEvent += delegate (bool button_enabled) {
|
||||
Application.Invoke (delegate { continue_button.Sensitive = button_enabled; });
|
||||
};
|
||||
|
||||
name_entry.Changed += delegate { Controller.CheckSetupPage (name_entry.Text, email_entry.Text); };
|
||||
email_entry.Changed += delegate { Controller.CheckSetupPage (name_entry.Text, email_entry.Text); };
|
||||
cancel_button.Clicked += delegate { Controller.SetupPageCancelled (); };
|
||||
|
||||
continue_button.Clicked += delegate {
|
||||
Controller.SetupPageCompleted (name_entry.Text, email_entry.Text);
|
||||
};
|
||||
|
||||
|
||||
AddButton (cancel_button);
|
||||
AddButton (continue_button);
|
||||
Add (wrapper);
|
||||
|
||||
Controller.CheckSetupPage (name_entry.Text, email_entry.Text);
|
||||
|
||||
if (name_entry.Text.Equals (""))
|
||||
name_entry.GrabFocus ();
|
||||
else
|
||||
email_entry.GrabFocus ();
|
||||
}
|
||||
|
||||
if (type == PageType.Add) {
|
||||
Header = "Where’s your project hosted?";
|
||||
|
||||
VBox layout_vertical = new VBox (false, 16);
|
||||
HBox layout_fields = new HBox (true, 32);
|
||||
VBox layout_address = new VBox (true, 0);
|
||||
VBox layout_path = new VBox (true, 0);
|
||||
|
||||
ListStore store = new ListStore (typeof (string), typeof (Gdk.Pixbuf), typeof (string), typeof (Preset));
|
||||
|
||||
SparkleTreeView tree_view = new SparkleTreeView (store) {
|
||||
HeadersVisible = false,
|
||||
SearchColumn = -1,
|
||||
EnableSearch = false
|
||||
};
|
||||
|
||||
ScrolledWindow scrolled_window = new ScrolledWindow () { ShadowType = ShadowType.In };
|
||||
scrolled_window.SetPolicy (PolicyType.Never, PolicyType.Automatic);
|
||||
|
||||
// Padding column
|
||||
tree_view.AppendColumn ("Padding", new Gtk.CellRendererText (), "text", 0);
|
||||
tree_view.Columns [0].Cells [0].Xpad = 8;
|
||||
|
||||
// Icon column
|
||||
tree_view.AppendColumn ("Icon", new Gtk.CellRendererPixbuf (), "pixbuf", 1);
|
||||
tree_view.Columns [1].Cells [0].Xpad = 6;
|
||||
|
||||
// Service column
|
||||
TreeViewColumn service_column = new TreeViewColumn () { Title = "Service" };
|
||||
CellRendererText service_cell = new CellRendererText () { Ypad = 12 };
|
||||
service_column.PackStart (service_cell, true);
|
||||
service_column.SetCellDataFunc (service_cell, new TreeCellDataFunc (RenderServiceColumn));
|
||||
|
||||
foreach (Preset preset in Controller.Presets) {
|
||||
store.AppendValues ("", new Gdk.Pixbuf (preset.ImagePath),
|
||||
"<span><b>" + preset.Name + "</b>\n" +
|
||||
"<span size=\"small\" fgcolor=\"" + SparkleShare.UI.SecondaryTextColor + "\">" + preset.Description + "</span>" +
|
||||
"</span>", preset);
|
||||
}
|
||||
|
||||
tree_view.AppendColumn (service_column);
|
||||
scrolled_window.Add (tree_view);
|
||||
|
||||
Entry address_entry = new Entry () {
|
||||
Text = Controller.PreviousAddress,
|
||||
Sensitive = (Controller.SelectedPreset.Address == null),
|
||||
ActivatesDefault = true
|
||||
};
|
||||
|
||||
Entry path_entry = new Entry () {
|
||||
Text = Controller.PreviousPath,
|
||||
Sensitive = (Controller.SelectedPreset.Path == null),
|
||||
ActivatesDefault = true
|
||||
};
|
||||
|
||||
tree_view.ButtonReleaseEvent += delegate {
|
||||
path_entry.GrabFocus ();
|
||||
};
|
||||
|
||||
Label address_example = new Label () {
|
||||
Xalign = 0,
|
||||
UseMarkup = true,
|
||||
Markup = "<span size=\"small\" fgcolor=\"" +
|
||||
SparkleShare.UI.SecondaryTextColor + "\">" + Controller.SelectedPreset.AddressExample + "</span>"
|
||||
};
|
||||
|
||||
Label path_example = new Label () {
|
||||
Xalign = 0,
|
||||
UseMarkup = true,
|
||||
Markup = "<span size=\"small\" fgcolor=\"" +
|
||||
SparkleShare.UI.SecondaryTextColor + "\">" + Controller.SelectedPreset.PathExample + "</span>"
|
||||
};
|
||||
|
||||
|
||||
TreeSelection default_selection = tree_view.Selection;
|
||||
TreePath default_path = new TreePath ("" + Controller.SelectedPresetIndex);
|
||||
default_selection.SelectPath (default_path);
|
||||
|
||||
tree_view.Model.Foreach (new TreeModelForeachFunc (
|
||||
delegate (ITreeModel model, TreePath path, TreeIter iter) {
|
||||
string address;
|
||||
|
||||
try {
|
||||
address = (model.GetValue (iter, 2) as Preset).Address;
|
||||
|
||||
} catch (NullReferenceException) {
|
||||
address = "";
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty (address) &&
|
||||
address.Equals (Controller.PreviousAddress)) {
|
||||
|
||||
tree_view.SetCursor (path, service_column, false);
|
||||
Preset preset = (Preset) model.GetValue (iter, 2);
|
||||
|
||||
if (preset.Address != null)
|
||||
address_entry.Sensitive = false;
|
||||
|
||||
if (preset.Path != null)
|
||||
path_entry.Sensitive = false;
|
||||
|
||||
return true;
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
));
|
||||
|
||||
layout_address.PackStart (new Label () {
|
||||
Markup = "<b>" + "Address" + "</b>",
|
||||
Xalign = 0
|
||||
}, true, true, 0);
|
||||
|
||||
layout_address.PackStart (address_entry, false, false, 0);
|
||||
layout_address.PackStart (address_example, false, false, 0);
|
||||
|
||||
path_entry.Changed += delegate {
|
||||
Controller.CheckAddPage (address_entry.Text, path_entry.Text, tree_view.SelectedRow);
|
||||
};
|
||||
|
||||
layout_path.PackStart (new Label () {
|
||||
Markup = "<b>" + "Remote Path" + "</b>",
|
||||
Xalign = 0
|
||||
}, true, true, 0);
|
||||
|
||||
layout_path.PackStart (path_entry, false, false, 0);
|
||||
layout_path.PackStart (path_example, false, false, 0);
|
||||
|
||||
layout_fields.PackStart (layout_address, true, true, 0);
|
||||
layout_fields.PackStart (layout_path, true, true, 0);
|
||||
|
||||
layout_vertical.PackStart (scrolled_window, true, true, 0);
|
||||
layout_vertical.PackStart (layout_fields, false, false, 0);
|
||||
|
||||
tree_view.ScrollToCell (new TreePath ("" + Controller.SelectedPresetIndex), null, true, 0, 0);
|
||||
|
||||
Add (layout_vertical);
|
||||
|
||||
|
||||
if (string.IsNullOrEmpty (path_entry.Text)) {
|
||||
address_entry.GrabFocus ();
|
||||
address_entry.Position = -1;
|
||||
} else {
|
||||
path_entry.GrabFocus ();
|
||||
path_entry.Position = -1;
|
||||
}
|
||||
|
||||
Button cancel_button = new Button ("Cancel");
|
||||
Button add_button = new Button ("Add") { Sensitive = false };
|
||||
|
||||
|
||||
Controller.ChangeAddressFieldEvent += delegate (string text,
|
||||
string example_text, FieldState state) {
|
||||
|
||||
Application.Invoke (delegate {
|
||||
address_entry.Text = text;
|
||||
address_entry.Sensitive = (state == FieldState.Enabled);
|
||||
address_example.Markup = "<span size=\"small\" fgcolor=\"" +
|
||||
SparkleShare.UI.SecondaryTextColor + "\">" + example_text + "</span>";
|
||||
});
|
||||
};
|
||||
|
||||
Controller.ChangePathFieldEvent += delegate (string text,
|
||||
string example_text, FieldState state) {
|
||||
|
||||
Application.Invoke (delegate {
|
||||
path_entry.Text = text;
|
||||
path_entry.Sensitive = (state == FieldState.Enabled);
|
||||
path_example.Markup = "<span size=\"small\" fgcolor=\""
|
||||
+ SparkleShare.UI.SecondaryTextColor + "\">" + example_text + "</span>";
|
||||
});
|
||||
};
|
||||
|
||||
Controller.UpdateAddProjectButtonEvent += delegate (bool button_enabled) {
|
||||
Application.Invoke (delegate { add_button.Sensitive = button_enabled; });
|
||||
};
|
||||
|
||||
|
||||
tree_view.CursorChanged += delegate (object sender, EventArgs e) {
|
||||
Controller.SelectedPresetChanged (tree_view.SelectedRow);
|
||||
};
|
||||
|
||||
address_entry.Changed += delegate {
|
||||
Controller.CheckAddPage (address_entry.Text, path_entry.Text, tree_view.SelectedRow);
|
||||
};
|
||||
|
||||
cancel_button.Clicked += delegate { Controller.PageCancelled (); };
|
||||
add_button.Clicked += delegate { Controller.AddPageCompleted (address_entry.Text, path_entry.Text); };
|
||||
|
||||
|
||||
CheckButton check_button = new CheckButton ("Fetch prior revisions") { Active = false };
|
||||
check_button.Toggled += delegate { Controller.HistoryItemChanged (check_button.Active); };
|
||||
|
||||
AddOption (check_button);
|
||||
AddButton (cancel_button);
|
||||
AddButton (add_button);
|
||||
|
||||
Controller.HistoryItemChanged (check_button.Active);
|
||||
Controller.CheckAddPage (address_entry.Text, path_entry.Text, 1);
|
||||
}
|
||||
|
||||
if (type == PageType.Invite) {
|
||||
Header = "You’ve received an invite!";
|
||||
Description = "Do you want to add this project to SparkleShare?";
|
||||
|
||||
Table table = new Table (2, 3, true) {
|
||||
RowSpacing = 6,
|
||||
ColumnSpacing = 6
|
||||
};
|
||||
|
||||
Label address_label = new Label ("Address:") { Xalign = 1 };
|
||||
Label path_label = new Label ("Remote Path:") { Xalign = 1 };
|
||||
|
||||
Label address_value = new Label ("<b>" + Controller.PendingInvite.Address + "</b>") {
|
||||
UseMarkup = true,
|
||||
Xalign = 0
|
||||
};
|
||||
|
||||
Label path_value = new Label ("<b>" + Controller.PendingInvite.RemotePath + "</b>") {
|
||||
UseMarkup = true,
|
||||
Xalign = 0
|
||||
};
|
||||
|
||||
table.Attach (address_label, 0, 1, 0, 1);
|
||||
table.Attach (address_value, 1, 2, 0, 1);
|
||||
table.Attach (path_label, 0, 1, 1, 2);
|
||||
table.Attach (path_value, 1, 2, 1, 2);
|
||||
|
||||
VBox wrapper = new VBox (false, 9);
|
||||
wrapper.PackStart (table, true, false, 0);
|
||||
|
||||
Button cancel_button = new Button ("Cancel");
|
||||
Button add_button = new Button ("Add");
|
||||
|
||||
|
||||
cancel_button.Clicked += delegate { Controller.PageCancelled (); };
|
||||
add_button.Clicked += delegate { Controller.InvitePageCompleted (); };
|
||||
|
||||
|
||||
AddButton (cancel_button);
|
||||
AddButton (add_button);
|
||||
Add (wrapper);
|
||||
}
|
||||
|
||||
if (type == PageType.Syncing) {
|
||||
Header = String.Format ("Adding project ‘{0}’…", Controller.SyncingFolder);
|
||||
Description = "This may take a while for large projects.\nIsn’t it coffee-o’clock?";
|
||||
|
||||
ProgressBar progress_bar = new ProgressBar ();
|
||||
progress_bar.Fraction = Controller.ProgressBarPercentage / 100;
|
||||
|
||||
Button cancel_button = new Button () { Label = "Cancel" };
|
||||
Button finish_button = new Button ("Finish") { Sensitive = false };
|
||||
|
||||
Label progress_label = new Label ("Preparing to fetch files…") {
|
||||
Justify = Justification.Right,
|
||||
Xalign = 1
|
||||
};
|
||||
|
||||
|
||||
Controller.UpdateProgressBarEvent += delegate (double percentage, string speed) {
|
||||
Application.Invoke (delegate {
|
||||
progress_bar.Fraction = percentage / 100;
|
||||
progress_label.Text = speed;
|
||||
});
|
||||
};
|
||||
|
||||
cancel_button.Clicked += delegate { Controller.SyncingCancelled (); };
|
||||
|
||||
|
||||
VBox bar_wrapper = new VBox (false, 0);
|
||||
bar_wrapper.PackStart (progress_bar, false, false, 21);
|
||||
bar_wrapper.PackStart (progress_label, false, true, 0);
|
||||
|
||||
Add (bar_wrapper);
|
||||
AddButton (cancel_button);
|
||||
AddButton (finish_button);
|
||||
}
|
||||
|
||||
if (type == PageType.Error) {
|
||||
Header = "Oops! Something went wrong" + "…";
|
||||
|
||||
VBox points = new VBox (false, 0);
|
||||
Image list_point_one = new Image (UserInterfaceHelpers.GetIcon ("list-point", 16));
|
||||
Image list_point_two = new Image (UserInterfaceHelpers.GetIcon ("list-point", 16));
|
||||
Image list_point_three = new Image (UserInterfaceHelpers.GetIcon ("list-point", 16));
|
||||
|
||||
Label label_one = new Label () {
|
||||
Markup = "<b>" + Controller.PreviousUrl + "</b> is the address we’ve compiled. " +
|
||||
"Does this look alright?",
|
||||
Wrap = true,
|
||||
Xalign = 0
|
||||
};
|
||||
|
||||
Label label_two = new Label () {
|
||||
Text = "Is this computer’s Client ID known by the host?",
|
||||
Wrap = true,
|
||||
Xalign = 0
|
||||
};
|
||||
|
||||
points.PackStart (new Label ("Please check the following:") { Xalign = 0 }, false, false, 6);
|
||||
|
||||
HBox point_one = new HBox (false, 0);
|
||||
point_one.PackStart (list_point_one, false, false, 0);
|
||||
point_one.PackStart (label_one, true, true, 12);
|
||||
points.PackStart (point_one, false, false, 12);
|
||||
|
||||
HBox point_two = new HBox (false, 0);
|
||||
point_two.PackStart (list_point_two, false, false, 0);
|
||||
point_two.PackStart (label_two, true, true, 12);
|
||||
points.PackStart (point_two, false, false, 12);
|
||||
|
||||
if (warnings.Length > 0) {
|
||||
string warnings_markup = "";
|
||||
|
||||
foreach (string warning in warnings)
|
||||
warnings_markup += "\n<b>" + warning + "</b>";
|
||||
|
||||
Label label_three = new Label () {
|
||||
Markup = "Here’s the raw error message:" + warnings_markup,
|
||||
Wrap = true,
|
||||
Xalign = 0
|
||||
};
|
||||
|
||||
HBox point_three = new HBox (false, 0);
|
||||
point_three.PackStart (list_point_three, false, false, 0);
|
||||
point_three.PackStart (label_three, true, true, 12);
|
||||
points.PackStart (point_three, false, false, 12);
|
||||
}
|
||||
|
||||
points.PackStart (new Label (""), true, true, 0);
|
||||
|
||||
Button cancel_button = new Button ("Cancel");
|
||||
Button try_again_button = new Button ("Retry") { Sensitive = true };
|
||||
|
||||
|
||||
cancel_button.Clicked += delegate { Controller.PageCancelled (); };
|
||||
try_again_button.Clicked += delegate { Controller.ErrorPageCompleted (); };
|
||||
|
||||
|
||||
AddButton (cancel_button);
|
||||
AddButton (try_again_button);
|
||||
Add (points);
|
||||
}
|
||||
|
||||
if (type == PageType.StorageSetup) {
|
||||
Header = string.Format ("Storage type for ‘{0}’", Controller.SyncingFolder);
|
||||
Description = "What type of storage would you like to use?";
|
||||
|
||||
VBox layout_vertical = new VBox (false, 0);
|
||||
VBox layout_radio_buttons = new VBox (false, 0) { BorderWidth = 12 };
|
||||
|
||||
foreach (StorageTypeInfo storage_type in SparkleShare.Controller.FetcherAvailableStorageTypes) {
|
||||
RadioButton radio_button = new RadioButton (null,
|
||||
storage_type.Name + "\n" + storage_type.Description);
|
||||
|
||||
(radio_button.Child as Label).Markup = string.Format(
|
||||
"<b>{0}</b>\n<span fgcolor=\"{1}\">{2}</span>",
|
||||
storage_type.Name, SparkleShare.UI.SecondaryTextColor, storage_type.Description);
|
||||
|
||||
(radio_button.Child as Label).Xpad = 9;
|
||||
|
||||
layout_radio_buttons.PackStart (radio_button, false, false, 9);
|
||||
radio_button.Group = (layout_radio_buttons.Children [0] as RadioButton).Group;
|
||||
}
|
||||
|
||||
layout_vertical.PackStart (new Label (""), true, true, 0);
|
||||
layout_vertical.PackStart (layout_radio_buttons, false, false, 0);
|
||||
layout_vertical.PackStart (new Label (""), true, true, 0);
|
||||
Add (layout_vertical);
|
||||
|
||||
Button cancel_button = new Button ("Cancel");
|
||||
Button continue_button = new Button ("Continue");
|
||||
|
||||
continue_button.Clicked += delegate {
|
||||
int checkbox_index= 0;
|
||||
foreach (RadioButton radio_button in layout_radio_buttons.Children) {
|
||||
if (radio_button.Active) {
|
||||
StorageTypeInfo selected_storage_type = SparkleShare.Controller.FetcherAvailableStorageTypes [checkbox_index];
|
||||
Controller.StoragePageCompleted (selected_storage_type.Type);
|
||||
return;
|
||||
}
|
||||
|
||||
checkbox_index++;
|
||||
}
|
||||
};
|
||||
|
||||
cancel_button.Clicked += delegate {
|
||||
Controller.SyncingCancelled ();
|
||||
};
|
||||
|
||||
AddButton (cancel_button);
|
||||
AddButton (continue_button);
|
||||
}
|
||||
|
||||
if (type == PageType.CryptoSetup || type == PageType.CryptoPassword) {
|
||||
if (type == PageType.CryptoSetup) {
|
||||
Header = string.Format ("Encryption password for ‘{0}’", Controller.SyncingFolder);
|
||||
Description = "Please a provide a strong password that you don’t use elsewhere.";
|
||||
|
||||
} else {
|
||||
Header = string.Format ("‘{0}’ contains encrypted files", Controller.SyncingFolder);
|
||||
Description = "Please enter the password to see their contents.";
|
||||
}
|
||||
|
||||
Label password_label = new Label ("<b>" + "Password" + "</b>") {
|
||||
UseMarkup = true,
|
||||
Xalign = 1
|
||||
};
|
||||
|
||||
Entry password_entry = new Entry () {
|
||||
Xalign = 0,
|
||||
Visibility = false,
|
||||
ActivatesDefault = true
|
||||
};
|
||||
|
||||
CheckButton show_password_check_button = new CheckButton ("Make visible") {
|
||||
Active = false,
|
||||
Xalign = 0,
|
||||
};
|
||||
|
||||
Table table = new Table (2, 3, true) {
|
||||
RowSpacing = 6,
|
||||
ColumnSpacing = 6
|
||||
};
|
||||
|
||||
table.Attach (password_label, 0, 1, 0, 1);
|
||||
table.Attach (password_entry, 1, 2, 0, 1);
|
||||
|
||||
table.Attach (show_password_check_button, 1, 2, 1, 2);
|
||||
|
||||
VBox wrapper = new VBox (false, 9);
|
||||
wrapper.PackStart (table, true, false, 0);
|
||||
|
||||
Image warning_image = new Image (
|
||||
UserInterfaceHelpers.GetIcon ("dialog-information", 24));
|
||||
|
||||
Label warning_label = new Label () {
|
||||
Xalign = 0,
|
||||
Wrap = true,
|
||||
Text = "This password can’t be changed later, and your files can’t be recovered if it’s forgotten."
|
||||
};
|
||||
|
||||
HBox warning_layout = new HBox (false, 0);
|
||||
warning_layout.PackStart (warning_image, false, false, 15);
|
||||
warning_layout.PackStart (warning_label, true, true, 0);
|
||||
|
||||
VBox warning_wrapper = new VBox (false, 0);
|
||||
warning_wrapper.PackStart (warning_layout, false, false, 15);
|
||||
|
||||
if (type == PageType.CryptoSetup)
|
||||
wrapper.PackStart (warning_wrapper, false, false, 0);
|
||||
|
||||
Button cancel_button = new Button ("Cancel");
|
||||
Button continue_button = new Button ("Continue") { Sensitive = false };
|
||||
|
||||
|
||||
Controller.UpdateCryptoSetupContinueButtonEvent += delegate (bool button_enabled) {
|
||||
Application.Invoke (delegate { continue_button.Sensitive = button_enabled; });
|
||||
};
|
||||
|
||||
Controller.UpdateCryptoPasswordContinueButtonEvent += delegate (bool button_enabled) {
|
||||
Application.Invoke (delegate { continue_button.Sensitive = button_enabled; });
|
||||
};
|
||||
|
||||
show_password_check_button.Toggled += delegate {
|
||||
password_entry.Visibility = !password_entry.Visibility;
|
||||
};
|
||||
|
||||
password_entry.Changed += delegate {
|
||||
if (type == PageType.CryptoSetup)
|
||||
Controller.CheckCryptoSetupPage (password_entry.Text);
|
||||
else
|
||||
Controller.CheckCryptoPasswordPage (password_entry.Text);
|
||||
};
|
||||
|
||||
cancel_button.Clicked += delegate { Controller.CryptoPageCancelled (); };
|
||||
|
||||
continue_button.Clicked += delegate {
|
||||
if (type == PageType.CryptoSetup)
|
||||
Controller.CryptoSetupPageCompleted (password_entry.Text);
|
||||
else
|
||||
Controller.CryptoPasswordPageCompleted (password_entry.Text);
|
||||
};
|
||||
|
||||
|
||||
Add (wrapper);
|
||||
|
||||
AddButton (cancel_button);
|
||||
AddButton (continue_button);
|
||||
|
||||
password_entry.GrabFocus ();
|
||||
}
|
||||
|
||||
if (type == PageType.Finished) {
|
||||
Header = "Your shared project is ready!";
|
||||
Description = "You can find the files in your SparkleShare folder.";
|
||||
|
||||
UrgencyHint = true;
|
||||
|
||||
Button show_files_button = new Button ("Show Files");
|
||||
Button finish_button = new Button ("Finish");
|
||||
|
||||
|
||||
show_files_button.Clicked += delegate { Controller.ShowFilesClicked (); };
|
||||
finish_button.Clicked += delegate { Controller.FinishPageCompleted (); };
|
||||
|
||||
|
||||
if (warnings.Length > 0) {
|
||||
Image warning_image = new Image (UserInterfaceHelpers.GetIcon ("dialog-information", 24));
|
||||
|
||||
Label warning_label = new Label (warnings [0]) {
|
||||
Xalign = 0,
|
||||
Wrap = true
|
||||
};
|
||||
|
||||
HBox warning_layout = new HBox (false, 0);
|
||||
warning_layout.PackStart (warning_image, false, false, 15);
|
||||
warning_layout.PackStart (warning_label, true, true, 0);
|
||||
|
||||
VBox warning_wrapper = new VBox (false, 0);
|
||||
warning_wrapper.PackStart (warning_layout, false, false, 0);
|
||||
|
||||
Add (warning_wrapper);
|
||||
|
||||
} else {
|
||||
Add (null);
|
||||
}
|
||||
|
||||
AddButton (show_files_button);
|
||||
AddButton (finish_button);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void RenderServiceColumn (TreeViewColumn column, CellRenderer cell,
|
||||
ITreeModel model, TreeIter iter)
|
||||
{
|
||||
string markup = (string) model.GetValue (iter, 2);
|
||||
TreeSelection selection = (column.TreeView as TreeView).Selection;
|
||||
|
||||
if (selection.IterIsSelected (iter))
|
||||
markup = markup.Replace (SparkleShare.UI.SecondaryTextColor, SparkleShare.UI.SecondaryTextColorSelected);
|
||||
else
|
||||
markup = markup.Replace (SparkleShare.UI.SecondaryTextColorSelected, SparkleShare.UI.SecondaryTextColor);
|
||||
|
||||
(cell as CellRendererText).Markup = markup;
|
||||
}
|
||||
|
||||
|
||||
private class SparkleTreeView : TreeView {
|
||||
|
||||
public int SelectedRow
|
||||
{
|
||||
get {
|
||||
TreeIter iter;
|
||||
ITreeModel model;
|
||||
|
||||
Selection.GetSelected (out model, out iter);
|
||||
return int.Parse (model.GetPath (iter).ToString ());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public SparkleTreeView (ListStore store) : base (store)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
186
SparkleShare/Linux/UserInterface/Pages/Page.Address.cs
Normal file
186
SparkleShare/Linux/UserInterface/Pages/Page.Address.cs
Normal file
|
@ -0,0 +1,186 @@
|
|||
// SparkleShare, a collaboration and sharing tool.
|
||||
// Copyright (C) 2010 Hylke Bons <hi@planetpeanut.uk>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General private License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General private License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General private License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
using System;
|
||||
|
||||
using Sparkles;
|
||||
using Gtk;
|
||||
|
||||
namespace SparkleShare {
|
||||
|
||||
public class AddressPage : Page {
|
||||
|
||||
Entry address_entry;
|
||||
DescriptionLabel address_example;
|
||||
|
||||
Entry path_entry;
|
||||
DescriptionLabel path_example;
|
||||
|
||||
Label public_key_label;
|
||||
|
||||
Button copy_button;
|
||||
Button add_button;
|
||||
|
||||
|
||||
public AddressPage (PageType page_type, PageController controller) : base (page_type, controller)
|
||||
{
|
||||
Header = "Where’s your project hosted?";
|
||||
Description = "";
|
||||
|
||||
Controller.PageCanContinueEvent += AddressPageCanContinueEventHandler;
|
||||
Controller.AddressPagePublicKeyEvent += AddressPagePublicKeyEventHandler;
|
||||
}
|
||||
|
||||
|
||||
public override void Dispose ()
|
||||
{
|
||||
Controller.PageCanContinueEvent -= AddressPageCanContinueEventHandler;
|
||||
Controller.AddressPagePublicKeyEvent -= AddressPagePublicKeyEventHandler;
|
||||
}
|
||||
|
||||
|
||||
public override object Render ()
|
||||
{
|
||||
// Address entry
|
||||
address_entry = new Entry () {
|
||||
Text = Controller.SelectedPreset.Address,
|
||||
ActivatesDefault = true
|
||||
};
|
||||
|
||||
address_example = new DescriptionLabel (Controller.SelectedPreset.AddressExample) { Xalign = 1 };
|
||||
address_entry.Changed += delegate { Controller.CheckAddressPage (address_entry.Text, path_entry.Text); };
|
||||
|
||||
VBox layout_address = new VBox (false, 6);
|
||||
|
||||
layout_address.PackStart (new Label () {
|
||||
Markup = "<b>Address</b>",
|
||||
Xalign = 0 }, true, true, 0);
|
||||
|
||||
layout_address.PackStart (address_entry, false, false, 0);
|
||||
layout_address.PackStart (address_example, false, false, 0);
|
||||
|
||||
|
||||
path_entry = new Entry () {
|
||||
Text = Controller.SelectedPreset.Path,
|
||||
ActivatesDefault = true
|
||||
};
|
||||
|
||||
path_entry.ClipboardPasted += delegate {
|
||||
try {
|
||||
path_entry.Text = new Uri (path_entry.Text).AbsolutePath;
|
||||
path_entry.Position = path_entry.Text.Length;
|
||||
|
||||
} catch {
|
||||
}
|
||||
};
|
||||
|
||||
path_example = new DescriptionLabel (Controller.SelectedPreset.Path) { Xalign = 1 };
|
||||
path_entry.Changed += delegate { Controller.CheckAddressPage (address_entry.Text, path_entry.Text); };
|
||||
|
||||
VBox layout_path = new VBox (false, 6);
|
||||
|
||||
layout_path.PackStart (new Label () {
|
||||
Markup = "<b>Remote Path</b>",
|
||||
Xalign = 0 }, true, true, 0);
|
||||
|
||||
layout_path.PackStart (path_entry, false, false, 0);
|
||||
layout_path.PackStart (path_example, false, false, 0);
|
||||
|
||||
|
||||
if (string.IsNullOrEmpty (path_entry.Text)) {
|
||||
address_entry.GrabFocus ();
|
||||
address_entry.Position = -1;
|
||||
|
||||
} else {
|
||||
path_entry.GrabFocus ();
|
||||
path_entry.Position = -1;
|
||||
}
|
||||
|
||||
|
||||
public_key_label = new Label () {
|
||||
Markup = "Authenticating…\n",
|
||||
UseMarkup = true,
|
||||
Xalign = 0,
|
||||
Yalign = 0
|
||||
};
|
||||
|
||||
copy_button = new Button ("Copy") {
|
||||
Visible = false,
|
||||
NoShowAll = true
|
||||
};
|
||||
|
||||
copy_button.Clicked += delegate {
|
||||
SparkleShare.Controller.CopyToClipboard (SparkleShare.Controller.UserAuthenticationInfo.PublicKey);
|
||||
};
|
||||
|
||||
var copy_layout = new HBox (false, 0);
|
||||
copy_layout.PackStart (copy_button, false, false, 0);
|
||||
|
||||
VBox layout_fields = new VBox (false, 0) { BorderWidth = 24 };
|
||||
layout_fields.PackStart (layout_address, false, false, 12);
|
||||
layout_fields.PackStart (layout_path, false, false, 12);
|
||||
|
||||
layout_fields.PackStart (new Label () {
|
||||
Markup = "<b>" + "Public Key" + "</b>",
|
||||
Xalign = 0,
|
||||
Yalign = 0
|
||||
}, false, false, 12);
|
||||
|
||||
layout_fields.PackStart (public_key_label, false, false, 0);
|
||||
layout_fields.PackStart (copy_layout, false, false, 12);
|
||||
|
||||
// Buttons
|
||||
Button cancel_button = new Button ("Cancel");
|
||||
add_button = new Button ("Add") { Sensitive = false };
|
||||
|
||||
cancel_button.Clicked += delegate { Controller.CancelClicked (RequestedType); };
|
||||
add_button.Clicked += delegate { Controller.AddressPageCompleted ( address_entry.Text, path_entry.Text); };
|
||||
|
||||
Button back_button = new Button ("Back");
|
||||
back_button.Clicked += delegate { Controller.BackClicked (RequestedType); };
|
||||
|
||||
Buttons = new Button [] { cancel_button, null, back_button, add_button };
|
||||
|
||||
var padding = new HBox (false, 0);
|
||||
padding.PackStart (layout_fields, true, true, 128);
|
||||
|
||||
// Layout
|
||||
return padding;
|
||||
}
|
||||
|
||||
|
||||
void AddressPagePublicKeyEventHandler (bool authenticated, string auth_status, string key_entry_hint)
|
||||
{
|
||||
Application.Invoke (delegate {
|
||||
public_key_label.Markup = auth_status;
|
||||
|
||||
if (!authenticated) {
|
||||
public_key_label.Markup = key_entry_hint + "\n" + "<span fgcolor=\"" +
|
||||
SparkleShare.UI.SecondaryTextColor + "\">" + auth_status + "</span>";
|
||||
copy_button.Show ();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
void AddressPageCanContinueEventHandler (PageType page_type, bool can_continue)
|
||||
{
|
||||
if (page_type == RequestedType)
|
||||
Application.Invoke (delegate { add_button.Sensitive = can_continue; });
|
||||
}
|
||||
}
|
||||
}
|
153
SparkleShare/Linux/UserInterface/Pages/Page.Crypto.cs
Normal file
153
SparkleShare/Linux/UserInterface/Pages/Page.Crypto.cs
Normal file
|
@ -0,0 +1,153 @@
|
|||
// SparkleShare, a collaboration and sharing tool.
|
||||
// Copyright (C) 2010 Hylke Bons <hi@planetpeanut.uk>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General private License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General private License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General private License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
using System;
|
||||
using Gtk;
|
||||
|
||||
namespace SparkleShare {
|
||||
|
||||
public class CryptoSetupPage : Page {
|
||||
|
||||
Button continue_button;
|
||||
|
||||
|
||||
public CryptoSetupPage (PageType page_type, PageController controller) : base (page_type, controller)
|
||||
{
|
||||
if (RequestedType == PageType.CryptoSetup) {
|
||||
Header = string.Format ("Encryption password for ‘{0}’", Controller.FetchAddress.AbsolutePath);
|
||||
Description = "Please a provide a strong password that you don’t use elsewhere.";
|
||||
|
||||
} else {
|
||||
Header = string.Format ("‘{0}’ contains encrypted files", Controller.FetchAddress.AbsolutePath);
|
||||
Description = "Please enter the password to see their contents.";
|
||||
}
|
||||
|
||||
Controller.PageCanContinueEvent += CryptoPageCanContinueEventHandler;
|
||||
}
|
||||
|
||||
|
||||
public override void Dispose ()
|
||||
{
|
||||
Controller.PageCanContinueEvent -= CryptoPageCanContinueEventHandler;
|
||||
}
|
||||
|
||||
|
||||
public override object Render ()
|
||||
{
|
||||
// Password entry
|
||||
Label password_label = new Label ("<b>" + "Password" + "</b>") {
|
||||
UseMarkup = true,
|
||||
Xalign = 1
|
||||
};
|
||||
|
||||
Entry password_entry = new Entry () {
|
||||
Xalign = 0,
|
||||
Visibility = false,
|
||||
ActivatesDefault = true
|
||||
};
|
||||
|
||||
password_entry.Changed += delegate {
|
||||
if (RequestedType == PageType.CryptoSetup)
|
||||
Controller.CheckCryptoSetupPage (password_entry.Text);
|
||||
else
|
||||
Controller.CheckCryptoPasswordPage (password_entry.Text);
|
||||
};
|
||||
|
||||
password_entry.GrabFocus ();
|
||||
|
||||
|
||||
// Checkbox
|
||||
CheckButton show_password_check_button = new CheckButton ("Make visible") {
|
||||
Active = false,
|
||||
Xalign = 0,
|
||||
};
|
||||
|
||||
show_password_check_button.Toggled += delegate {
|
||||
password_entry.Visibility = !password_entry.Visibility;
|
||||
};
|
||||
|
||||
|
||||
// Buttons
|
||||
Button cancel_button = new Button ("Cancel");
|
||||
cancel_button.Clicked += delegate { Controller.CancelClicked (RequestedType); };
|
||||
|
||||
continue_button = new Button ("Continue") { Sensitive = false };
|
||||
continue_button.Clicked += delegate { Controller.CryptoPageCompleted (password_entry.Text); };
|
||||
|
||||
Buttons = new Button [] { cancel_button, continue_button };
|
||||
|
||||
|
||||
// Layout
|
||||
Table table = new Table (2, 3, true) {
|
||||
RowSpacing = 6,
|
||||
ColumnSpacing = 6
|
||||
};
|
||||
|
||||
table.Attach (password_label, 0, 1, 0, 1);
|
||||
table.Attach (password_entry, 1, 2, 0, 1);
|
||||
|
||||
table.Attach (show_password_check_button, 1, 2, 1, 2);
|
||||
|
||||
VBox wrapper = new VBox (false, 9);
|
||||
wrapper.PackStart (table, true, false, 0);
|
||||
|
||||
if (RequestedType == PageType.CryptoSetup)
|
||||
wrapper.PackStart (RenderWarning (), false, false, 0);
|
||||
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
|
||||
VBox RenderWarning ()
|
||||
{
|
||||
var image = new Image (
|
||||
UserInterfaceHelpers.GetIcon ("dialog-information-symbolic", 24));
|
||||
|
||||
Label label = new Label () {
|
||||
Xalign = 0,
|
||||
Wrap = true,
|
||||
Text = "This password can’t be changed later, and your files can’t be recovered if it’s forgotten."
|
||||
};
|
||||
|
||||
|
||||
// Layout
|
||||
HBox layout = new HBox (false, 0);
|
||||
layout.PackStart (image, false, false, 16);
|
||||
layout.PackStart (label, true, true, 0);
|
||||
|
||||
VBox wrapper = new VBox (false, 0);
|
||||
wrapper.PackStart (layout, false, false, 16);
|
||||
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
|
||||
void CryptoPageCanContinueEventHandler (PageType page_type, bool can_continue)
|
||||
{
|
||||
if (page_type == RequestedType)
|
||||
Application.Invoke (delegate { continue_button.Sensitive = can_continue; });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class CryptoPasswordPage : CryptoSetupPage {
|
||||
|
||||
public CryptoPasswordPage (PageType page_type, PageController controller) : base (page_type, controller)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
169
SparkleShare/Linux/UserInterface/Pages/Page.Host.cs
Executable file
169
SparkleShare/Linux/UserInterface/Pages/Page.Host.cs
Executable file
|
@ -0,0 +1,169 @@
|
|||
// SparkleShare, a collaboration and sharing tool.
|
||||
// Copyright (C) 2010 Hylke Bons <hi@planetpeanut.uk>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General private License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General private License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General private License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
using System;
|
||||
|
||||
using Sparkles;
|
||||
using Gtk;
|
||||
|
||||
namespace SparkleShare {
|
||||
|
||||
public class HostPage : Page {
|
||||
|
||||
SparkleTreeView tree_view;
|
||||
TreeViewColumn service_column;
|
||||
|
||||
|
||||
public HostPage (PageType page_type, PageController controller) : base (page_type, controller)
|
||||
{
|
||||
Header = "Where’s your project hosted?";
|
||||
Description = "";
|
||||
}
|
||||
|
||||
|
||||
public override object Render ()
|
||||
{
|
||||
// Host selection
|
||||
ListStore store = new ListStore (typeof (string), typeof (Gdk.Pixbuf), typeof (string), typeof (Preset));
|
||||
|
||||
tree_view = new SparkleTreeView (store) {
|
||||
HeadersVisible = false,
|
||||
SearchColumn = -1,
|
||||
EnableSearch = false
|
||||
};
|
||||
|
||||
tree_view.CursorChanged += delegate { Controller.SelectedPresetChanged (tree_view.SelectedRow); };
|
||||
|
||||
|
||||
// Padding column
|
||||
tree_view.AppendColumn ("Padding", new Gtk.CellRendererText (), "text", 0);
|
||||
tree_view.Columns [0].Cells [0].Xpad = 8;
|
||||
|
||||
// Icon column
|
||||
tree_view.AppendColumn ("Icon", new Gtk.CellRendererPixbuf (), "pixbuf", 1);
|
||||
tree_view.Columns [1].Cells [0].Xpad = 6;
|
||||
|
||||
// Service column
|
||||
service_column = new TreeViewColumn () { Title = "Service" };
|
||||
CellRendererText service_cell = new CellRendererText () { Ypad = 12 };
|
||||
service_column.PackStart (service_cell, true);
|
||||
service_column.SetCellDataFunc (service_cell, new TreeCellDataFunc (RenderServiceColumn));
|
||||
tree_view.AppendColumn (service_column);
|
||||
|
||||
|
||||
// Fill the list
|
||||
foreach (Preset preset in Controller.Presets) {
|
||||
store.AppendValues ("", new Gdk.Pixbuf (preset.IconPath),
|
||||
string.Format ("<span><b>{0}</b>\n<span size='small' fgcolor='{1}'>{2}</span></span>",
|
||||
preset.Name, SparkleShare.UI.SecondaryTextColor, preset.Description),
|
||||
preset);
|
||||
}
|
||||
|
||||
|
||||
tree_view.Model.Foreach (new TreeModelForeachFunc (TreeModelForeachFuncHandler));
|
||||
|
||||
TreeSelection default_selection = tree_view.Selection;
|
||||
TreePath default_path = new TreePath ("" + Controller.SelectedPresetIndex);
|
||||
default_selection.SelectPath (default_path);
|
||||
|
||||
tree_view.ScrollToCell (new TreePath ("" + Controller.SelectedPresetIndex), null, true, 0, 0);
|
||||
|
||||
ScrolledWindow scrolled_window = new ScrolledWindow () { ShadowType = ShadowType.In };
|
||||
scrolled_window.SetPolicy (PolicyType.Never, PolicyType.Automatic);
|
||||
scrolled_window.Add (tree_view);
|
||||
|
||||
|
||||
// Buttons
|
||||
Button cancel_button = new Button ("Cancel");
|
||||
Button continue_button = new Button ("Continue");
|
||||
|
||||
cancel_button.Clicked += delegate { Controller.CancelClicked (RequestedType); };
|
||||
continue_button.Clicked += delegate { Controller.HostPageCompleted (); };
|
||||
|
||||
Button back_button = new Button ("Back");
|
||||
back_button.Clicked += delegate { Controller.BackClicked (RequestedType); };
|
||||
|
||||
Buttons = new Button [] { cancel_button, null, back_button, continue_button };
|
||||
|
||||
|
||||
// Layout
|
||||
VBox layout_vertical = new VBox (false, 16);
|
||||
layout_vertical.PackStart (scrolled_window, true, true, 0);
|
||||
|
||||
return layout_vertical;
|
||||
}
|
||||
|
||||
|
||||
void RenderServiceColumn (TreeViewColumn column, CellRenderer cell, ITreeModel model, TreeIter iter)
|
||||
{
|
||||
string markup = (string) model.GetValue (iter, 2);
|
||||
TreeSelection selection = (column.TreeView as TreeView).Selection;
|
||||
|
||||
if (selection.IterIsSelected (iter))
|
||||
markup = markup.Replace (SparkleShare.UI.SecondaryTextColor, SparkleShare.UI.SecondaryTextColorSelected);
|
||||
else
|
||||
markup = markup.Replace (SparkleShare.UI.SecondaryTextColorSelected, SparkleShare.UI.SecondaryTextColor);
|
||||
|
||||
(cell as CellRendererText).Markup = markup;
|
||||
}
|
||||
|
||||
|
||||
bool TreeModelForeachFuncHandler (ITreeModel model, TreePath path, TreeIter iter)
|
||||
{
|
||||
string address;
|
||||
|
||||
try {
|
||||
address = (model.GetValue (iter, 2) as Preset).Address;
|
||||
|
||||
} catch (NullReferenceException) {
|
||||
address = "";
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty (address) &&
|
||||
address.Equals (Controller.FetchAddress.Host)) { // TODO Check selection
|
||||
|
||||
tree_view.SetCursor (path, service_column, false);
|
||||
//Preset preset = (Preset) model.GetValue (iter, 2);
|
||||
|
||||
return true;
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class SparkleTreeView : TreeView {
|
||||
|
||||
public int SelectedRow
|
||||
{
|
||||
get {
|
||||
TreeIter iter;
|
||||
ITreeModel model;
|
||||
|
||||
Selection.GetSelected (out model, out iter);
|
||||
return int.Parse (model.GetPath (iter).ToString ());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public SparkleTreeView (ListStore store) : base (store)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
75
SparkleShare/Linux/UserInterface/Pages/Page.Invite.cs
Normal file
75
SparkleShare/Linux/UserInterface/Pages/Page.Invite.cs
Normal file
|
@ -0,0 +1,75 @@
|
|||
// SparkleShare, a collaboration and sharing tool.
|
||||
// Copyright (C) 2010 Hylke Bons <hi@planetpeanut.uk>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General private License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General private License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General private License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
using System;
|
||||
using Gtk;
|
||||
|
||||
namespace SparkleShare {
|
||||
|
||||
public class InvitePage : Page {
|
||||
|
||||
public InvitePage (PageType page_type, PageController controller) : base (page_type, controller)
|
||||
{
|
||||
Header = "You’ve received an invite!";
|
||||
Description = "Do you want to add this project to SparkleShare?";
|
||||
|
||||
|
||||
// Buttons
|
||||
Button cancel_button = new Button ("Cancel");
|
||||
Button add_button = new Button ("Add");
|
||||
|
||||
cancel_button.Clicked += delegate { Controller.CancelClicked (RequestedType); };
|
||||
add_button.Clicked += delegate { Controller.InvitePageCompleted (); };
|
||||
|
||||
Buttons = new Button [] {cancel_button, add_button };
|
||||
}
|
||||
|
||||
|
||||
public override object Render ()
|
||||
{
|
||||
// Labels
|
||||
Label address_label = new Label ("Address:") { Xalign = 1 };
|
||||
Label address_value = new Label ("<b>" + Controller.PendingInvite.Address + "</b>") {
|
||||
UseMarkup = true,
|
||||
Xalign = 0
|
||||
};
|
||||
|
||||
Label path_label = new Label ("Remote Path:") { Xalign = 1 };
|
||||
Label path_value = new Label ("<b>" + Controller.PendingInvite.RemotePath + "</b>") {
|
||||
UseMarkup = true,
|
||||
Xalign = 0
|
||||
};
|
||||
|
||||
|
||||
// Layout
|
||||
Table table = new Table (2, 3, true) {
|
||||
RowSpacing = 6,
|
||||
ColumnSpacing = 6
|
||||
};
|
||||
|
||||
table.Attach (address_label, 0, 1, 0, 1);
|
||||
table.Attach (address_value, 1, 2, 0, 1);
|
||||
table.Attach (path_label, 0, 1, 1, 2);
|
||||
table.Attach (path_value, 1, 2, 1, 2);
|
||||
|
||||
VBox wrapper = new VBox (false, 9);
|
||||
wrapper.PackStart (table, true, false, 0);
|
||||
|
||||
return wrapper;
|
||||
}
|
||||
}
|
||||
}
|
143
SparkleShare/Linux/UserInterface/Pages/Page.Privacy.cs
Normal file
143
SparkleShare/Linux/UserInterface/Pages/Page.Privacy.cs
Normal file
|
@ -0,0 +1,143 @@
|
|||
// SparkleShare, a collaboration and sharing tool.
|
||||
// Copyright (C) 2010 Hylke Bons <hi@planetpeanut.uk>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General private License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General private License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General private License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
using System;
|
||||
using Gtk;
|
||||
|
||||
namespace SparkleShare {
|
||||
|
||||
public class PrivacyPage : Page {
|
||||
|
||||
Switch notification_service_switch;
|
||||
Switch crash_reports_switch;
|
||||
Switch gravatars_switch;
|
||||
|
||||
|
||||
public PrivacyPage (PageType page_type, PageController controller) : base (page_type, controller)
|
||||
{
|
||||
Header = "Privacy Preferences";
|
||||
Description = "";
|
||||
}
|
||||
|
||||
|
||||
public override void Dispose ()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
public override object Render ()
|
||||
{
|
||||
var intro_label = new Label () {
|
||||
Text = "SparkleShare is decentralized, so no account of any sort is created.\n" +
|
||||
"However, some features can affect your privacy:",
|
||||
LineWrap = true,
|
||||
LineWrapMode = Pango.WrapMode.Word,
|
||||
MaxWidthChars = 48,
|
||||
Xalign = 0
|
||||
};
|
||||
|
||||
|
||||
HBox notification_service_layout = SwitchLayout ("Notification Service",
|
||||
"Instantly syncs when someone makes a change by sending a notification " +
|
||||
"via <a href='https://www.sparkleshare.org/'>sparkleshare.org</a>. " +
|
||||
"No personal or usage data is recorded.", recommended: true);
|
||||
|
||||
notification_service_switch = (Switch) (notification_service_layout.Children [0] as Box).Children [0];
|
||||
|
||||
|
||||
HBox crash_reports_layout = SwitchLayout ("Crash Reports",
|
||||
"In the unlikely event of a SparkleShare crash, sends an anonymized report to " +
|
||||
"the project maintainers to help fix bugs.", recommended: false);
|
||||
|
||||
crash_reports_switch = (Switch) (crash_reports_layout.Children [0] as Box).Children [0];
|
||||
|
||||
|
||||
HBox gravatars_layout = SwitchLayout ("Gravatars",
|
||||
"Uses <a href='https://www.gravatar.com/'>gravatar.com</a> to download " +
|
||||
"profile pictures.", recommended: false);
|
||||
|
||||
gravatars_switch = (Switch) (gravatars_layout.Children [0] as Box).Children [0];
|
||||
|
||||
|
||||
// Tip
|
||||
var tip_label = new Label ("You will be able to change these preferences later.") { Xalign = 0 };
|
||||
|
||||
|
||||
// Buttons
|
||||
Button quit_button = new Button ("Quit");
|
||||
quit_button.Clicked += delegate { Controller.QuitClicked (); };
|
||||
|
||||
Button back_button = new Button ("Back");
|
||||
back_button.Clicked += delegate { Controller.BackClicked (RequestedType); };
|
||||
|
||||
Button continue_button = new Button ("Continue");
|
||||
continue_button.Clicked += ContinueButtonClickedHandler;
|
||||
|
||||
Buttons = new Button [] { quit_button, null, back_button, continue_button };
|
||||
|
||||
|
||||
// Layout
|
||||
var layout = new VBox (false, 0) { MarginLeft = 32, MarginRight = 12 };
|
||||
layout.PackStart (intro_label, false, false, 32);
|
||||
|
||||
layout.PackStart (notification_service_layout, false, false, 12);
|
||||
layout.PackStart (crash_reports_layout, false, false, 12);
|
||||
layout.PackStart (gravatars_layout, false, false, 12);
|
||||
|
||||
layout.PackStart (tip_label, false, false, 32);
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
|
||||
void ContinueButtonClickedHandler (object sender, EventArgs args)
|
||||
{
|
||||
Controller.PrivacyPageCompleted (
|
||||
notification_service: notification_service_switch.Active,
|
||||
crash_reports: crash_reports_switch.Active,
|
||||
gravatars: gravatars_switch.Active);
|
||||
}
|
||||
|
||||
|
||||
HBox SwitchLayout (string title, string description, bool recommended)
|
||||
{
|
||||
var light_switch = new Switch () { Active = recommended, HeightRequest = 36 };
|
||||
string recommended_text = "";
|
||||
|
||||
if (recommended)
|
||||
recommended_text = " ‒ Recommended";
|
||||
|
||||
var label = new Label () {
|
||||
Markup = string.Format ("<b>{0}</b>{1}\n<span fgcolor='{2}'>{3}</span>",
|
||||
title, recommended_text, SparkleShare.UI.SecondaryTextColor, description),
|
||||
LineWrap = true,
|
||||
LineWrapMode = Pango.WrapMode.Word,
|
||||
MaxWidthChars = 48,
|
||||
Xalign = 0
|
||||
};
|
||||
|
||||
var box = new VBox (false, 0);
|
||||
box.PackStart (light_switch, false, false, 6);
|
||||
|
||||
var layout = new HBox (false, 0) { MarginLeft = 24 };
|
||||
layout.PackStart (box, false, false, 0);
|
||||
layout.PackStart (label, true, true, 24);
|
||||
|
||||
return layout;
|
||||
}
|
||||
}
|
||||
}
|
186
SparkleShare/Linux/UserInterface/Pages/Page.Progress.cs
Normal file
186
SparkleShare/Linux/UserInterface/Pages/Page.Progress.cs
Normal file
|
@ -0,0 +1,186 @@
|
|||
// SparkleShare, a collaboration and sharing tool.
|
||||
// Copyright (C) 2010 Hylke Bons <hi@planetpeanut.uk>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General private License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General private License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General private License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
using System;
|
||||
|
||||
using Sparkles; // TODO: remove
|
||||
using Gtk;
|
||||
|
||||
namespace SparkleShare {
|
||||
|
||||
public class ProgressPage : Page {
|
||||
|
||||
Image image;
|
||||
|
||||
Label status_label;
|
||||
Label status_details_label;
|
||||
|
||||
ProgressBar progress_bar;
|
||||
Label progress_label;
|
||||
|
||||
|
||||
public ProgressPage (PageType page_type, PageController controller) : base (page_type, controller)
|
||||
{
|
||||
Header = String.Format ("Getting files from {0}", Controller.SelectedPreset.Name);
|
||||
Description = "Depending on its size, it may be a good time to make some tea.";
|
||||
|
||||
Controller.ProgressPageBarEvent += ProgressPageBarEventHandler;
|
||||
}
|
||||
|
||||
|
||||
public override void Dispose ()
|
||||
{
|
||||
Controller.ProgressPageBarEvent -= ProgressPageBarEventHandler;
|
||||
// TODO: State handling
|
||||
}
|
||||
|
||||
|
||||
public override object Render ()
|
||||
{
|
||||
// image = new Image ();
|
||||
|
||||
// Progress bar
|
||||
progress_bar = new ProgressBar ();
|
||||
progress_bar.Fraction = Controller.ProgressBarPercentage / 100;
|
||||
|
||||
progress_label = new Label () {
|
||||
Markup = string.Format ("Getting files from <b>{0}</b>", Controller.FetchAddress.Authority),
|
||||
Xalign = 0
|
||||
};
|
||||
|
||||
|
||||
Buttons = ProgressButtons ();
|
||||
|
||||
|
||||
// UrgencyHint = true; TODO
|
||||
//VBox wrapper = new VBox (false, 0);
|
||||
|
||||
/* TODO
|
||||
|
||||
|
||||
// Buttons
|
||||
Button show_files_button = new Button ("Show Files");
|
||||
Button finish_button = new Button ("Finish");
|
||||
|
||||
show_files_button.Clicked += delegate { Controller.ShowFilesClicked (); };
|
||||
finish_button.Clicked += delegate { Controller.FinishPageCompleted (); };
|
||||
|
||||
Buttons = new Button [] { show_files_button, finish_button };
|
||||
|
||||
if (warnings.Length > 0) {
|
||||
Image warning_image = new Image (UserInterfaceHelpers.GetIcon ("dialog-information", 24));
|
||||
|
||||
Label warning_label = new Label (warnings [0]) {
|
||||
Xalign = 0,
|
||||
Wrap = true
|
||||
};
|
||||
|
||||
HBox warning_layout = new HBox (false, 0);
|
||||
warning_layout.PackStart (warning_image, false, false, 15);
|
||||
warning_layout.PackStart (warning_label, true, true, 0);
|
||||
|
||||
VBox wrapper = new VBox (false, 0);
|
||||
wrapper.PackStart (warning_layout, false, false, 0);
|
||||
|
||||
Add (wrapper);
|
||||
|
||||
} else {
|
||||
Add (null);
|
||||
}
|
||||
*/
|
||||
image = new Image (Controller.SelectedPreset.LogoPath);
|
||||
|
||||
image = new Image ("dialog-error-symbolic", (IconSize) 128);
|
||||
|
||||
status_label = new Label () { Markup = "<b>" + Header + "</b>" };
|
||||
status_details_label = new Label ("error goes here");
|
||||
|
||||
var status_layout = new VBox (false, 0);
|
||||
status_layout.PackStart (image, false, false, 12);
|
||||
status_layout.PackStart (status_label, false, false, 6);
|
||||
status_layout.PackStart (status_details_label, false, false, 0);
|
||||
|
||||
// Layout
|
||||
VBox layout = new VBox (false, 0) { BorderWidth = 48 };
|
||||
layout.PackStart (status_layout, true, true, 0);
|
||||
layout.PackStart (progress_bar, false, false, 24);
|
||||
layout.PackStart (progress_label, false, false, 0);
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
|
||||
void ProgressPageBarEventHandler (bool? success,
|
||||
string status, string status_details,
|
||||
double progress, string progress_details)
|
||||
{
|
||||
Application.Invoke (delegate {
|
||||
status_label.Markup = "<b>" + status + "</b>";
|
||||
status_details_label.Text = status_details;
|
||||
|
||||
progress_bar.Sensitive = success.GetValueOrDefault ();
|
||||
progress_bar.Fraction = progress / 100;
|
||||
progress_label.Text = progress_details;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Button [] ProgressButtons ()
|
||||
{
|
||||
var cancel_button = new Button ("Cancel");
|
||||
cancel_button.Clicked += delegate { Controller.CancelClicked (RequestedType); };
|
||||
|
||||
var back_button = new Button ("Back") { Sensitive = false };
|
||||
var done_button = new Button ("Done") { Sensitive = false };
|
||||
|
||||
return new Button [] { cancel_button, null, back_button, done_button };
|
||||
}
|
||||
|
||||
|
||||
Button [] ErrorButtons ()
|
||||
{
|
||||
var cancel_button = new Button ("Cancel");
|
||||
cancel_button.Clicked += delegate { Controller.CancelClicked (RequestedType); };
|
||||
|
||||
var back_button = new Button ("Back");
|
||||
back_button.Clicked += delegate { Controller.BackClicked (RequestedType); };
|
||||
|
||||
var retry_button = new Button ("Retry");
|
||||
retry_button.Clicked += delegate {
|
||||
// TODO
|
||||
};
|
||||
|
||||
return new Button [] { cancel_button, null, back_button, retry_button };
|
||||
}
|
||||
|
||||
|
||||
Button [] SuccessButtons ()
|
||||
{
|
||||
var open_files_button = new Button ("Open Files");
|
||||
open_files_button.Clicked += delegate {
|
||||
Controller.ShowFilesClicked (); // TODO
|
||||
};
|
||||
|
||||
var done_button = new Button ("Done");
|
||||
done_button.Clicked += delegate {
|
||||
Controller.ProgressPageCompleted ();
|
||||
};
|
||||
|
||||
return new Button [] { open_files_button, done_button };
|
||||
}
|
||||
}
|
||||
}
|
85
SparkleShare/Linux/UserInterface/Pages/Page.Storage.cs
Normal file
85
SparkleShare/Linux/UserInterface/Pages/Page.Storage.cs
Normal file
|
@ -0,0 +1,85 @@
|
|||
// SparkleShare, a collaboration and sharing tool.
|
||||
// Copyright (C) 2010 Hylke Bons <hi@planetpeanut.uk>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General private License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General private License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General private License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
using System;
|
||||
|
||||
using Sparkles;
|
||||
using Gtk;
|
||||
|
||||
namespace SparkleShare {
|
||||
|
||||
public class StoragePage : Page {
|
||||
|
||||
public StoragePage (PageType page_type, PageController controller) : base (page_type, controller)
|
||||
{
|
||||
Header = string.Format ("Storage type for ‘{0}’", Controller.FetchAddress.AbsolutePath);
|
||||
Description = "What type of storage would you like to use?";
|
||||
}
|
||||
|
||||
|
||||
public override object Render ()
|
||||
{
|
||||
// Radio buttons
|
||||
VBox radio_buttons = new VBox (false, 0) { BorderWidth = 12 };
|
||||
|
||||
foreach (StorageTypeInfo storage_type in SparkleShare.Controller.FetcherAvailableStorageTypes) {
|
||||
RadioButton radio_button = new RadioButton (null,
|
||||
storage_type.Name + "\n" + storage_type.Description);
|
||||
|
||||
(radio_button.Child as Label).Markup =
|
||||
string.Format("<b>{0}</b>\n<span fgcolor=\"{1}\">{2}</span>",
|
||||
storage_type.Name, SparkleShare.UI.SecondaryTextColor, storage_type.Description);
|
||||
|
||||
(radio_button.Child as Label).Xpad = 9;
|
||||
|
||||
radio_buttons.PackStart (radio_button, false, false, 9);
|
||||
radio_button.Group = (radio_buttons.Children [0] as RadioButton).Group;
|
||||
}
|
||||
|
||||
|
||||
// Buttons
|
||||
Button cancel_button = new Button ("Cancel");
|
||||
cancel_button.Clicked += delegate { Controller.CancelClicked (RequestedType); };
|
||||
|
||||
Button continue_button = new Button ("Continue");
|
||||
continue_button.Clicked += delegate {
|
||||
int checkbox_index= 0;
|
||||
|
||||
foreach (RadioButton radio_button in radio_buttons.Children) {
|
||||
if (radio_button.Active) {
|
||||
StorageTypeInfo selected_storage_type = SparkleShare.Controller.FetcherAvailableStorageTypes [checkbox_index];
|
||||
Controller.StoragePageCompleted (selected_storage_type.Type);
|
||||
return;
|
||||
}
|
||||
|
||||
checkbox_index++;
|
||||
}
|
||||
};
|
||||
|
||||
Buttons = new Button [] { cancel_button, continue_button };
|
||||
|
||||
|
||||
// Layout
|
||||
VBox layout = new VBox (false, 0);
|
||||
layout.PackStart (new Label (""), true, true, 0);
|
||||
layout.PackStart (radio_buttons, false, false, 0);
|
||||
layout.PackStart (new Label (""), true, true, 0);
|
||||
|
||||
return layout;
|
||||
}
|
||||
}
|
||||
}
|
145
SparkleShare/Linux/UserInterface/Pages/Page.User.cs
Normal file
145
SparkleShare/Linux/UserInterface/Pages/Page.User.cs
Normal file
|
@ -0,0 +1,145 @@
|
|||
// SparkleShare, a collaboration and sharing tool.
|
||||
// Copyright (C) 2010 Hylke Bons <hi@planetpeanut.uk>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General private License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General private License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General private License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
using System;
|
||||
|
||||
using Sparkles;
|
||||
using Gtk;
|
||||
using Mono.Unix;
|
||||
|
||||
namespace SparkleShare {
|
||||
|
||||
public class UserPage : Page {
|
||||
|
||||
Entry name_entry;
|
||||
Entry email_entry;
|
||||
|
||||
Button continue_button;
|
||||
|
||||
|
||||
public UserPage (PageType page_type, PageController controller) : base (page_type, controller)
|
||||
{
|
||||
Header = "Welcome to SparkleShare";
|
||||
Description = "Hello. Let's get you set up.";
|
||||
|
||||
Controller.PageCanContinueEvent += UserPageCanContinueEventHandler;
|
||||
}
|
||||
|
||||
|
||||
public override void Dispose ()
|
||||
{
|
||||
Controller.PageCanContinueEvent -= UserPageCanContinueEventHandler;
|
||||
}
|
||||
|
||||
|
||||
public override object Render ()
|
||||
{
|
||||
// Name
|
||||
Label name_label = new Label () {
|
||||
Markup = "<b>Name</b>",
|
||||
Xalign = 0
|
||||
};
|
||||
|
||||
name_entry = new Entry ();
|
||||
name_entry.Changed += delegate { Controller.CheckUserPage (name_entry.Text, email_entry.Text); };
|
||||
|
||||
// TODO: fill name and email when Back was pressed on privacy page
|
||||
|
||||
/* TODO broken
|
||||
try {
|
||||
UnixUserInfo user_info = UnixUserInfo.GetRealUser ();
|
||||
|
||||
if (user_info != null && user_info.RealName != null) {
|
||||
// Some systems append a series of "," for some reason
|
||||
string name = "" + user_info.RealName;
|
||||
name_entry.Text = name;
|
||||
}
|
||||
} catch (Exception) {
|
||||
// No username, not a big deal
|
||||
}
|
||||
*/
|
||||
|
||||
// Email
|
||||
Label email_label = new Label () {
|
||||
Markup = "<b>Email</b>",
|
||||
Xalign = 0
|
||||
};
|
||||
|
||||
email_entry = new Entry () { ActivatesDefault = true };
|
||||
email_entry.Changed += delegate { Controller.CheckUserPage (name_entry.Text, email_entry.Text); };
|
||||
|
||||
|
||||
var data_hint = new DescriptionLabel (
|
||||
"The following information is used to mark your changes in a project's history. " +
|
||||
"It won't be sent anywhere, but will be visible to those working on the same project.") {
|
||||
|
||||
LineWrap = true,
|
||||
LineWrapMode = Pango.WrapMode.Word,
|
||||
MaxWidthChars = 48
|
||||
|
||||
};
|
||||
|
||||
|
||||
// Buttons
|
||||
Button quit_button = new Button ("Quit");
|
||||
quit_button.Clicked += delegate { Controller.QuitClicked (); };
|
||||
|
||||
continue_button = new Button ("Continue") { Sensitive = false };
|
||||
continue_button.Clicked += delegate { Controller.UserPageCompleted (name_entry.Text, email_entry.Text); };
|
||||
|
||||
Buttons = new Button [] { quit_button, continue_button };
|
||||
|
||||
|
||||
if (name_entry.Text.Equals (""))
|
||||
name_entry.GrabFocus ();
|
||||
else
|
||||
email_entry.GrabFocus ();
|
||||
|
||||
Controller.CheckUserPage (name_entry.Text, email_entry.Text);
|
||||
|
||||
|
||||
// Layout
|
||||
VBox layout = new VBox (false, 9) { BorderWidth = 64 };
|
||||
layout.PackStart (new Label (Description) { Xalign = 0 }, false, false, 0);
|
||||
layout.PackStart (data_hint, false, false, 0);
|
||||
|
||||
VBox layout_fields = new VBox (false, 0) { BorderWidth = 32 };
|
||||
|
||||
VBox layout_name = new VBox (false, 6);
|
||||
layout_name.PackStart (name_label, false, false, 0);
|
||||
layout_name.PackStart (name_entry, false, false, 0);
|
||||
|
||||
VBox layout_email = new VBox (false, 6);
|
||||
layout_email.PackStart (email_label, false, false, 0);
|
||||
layout_email.PackStart (email_entry, false, false, 0);
|
||||
|
||||
layout_fields.PackStart (layout_name, false, false, 12);
|
||||
layout_fields.PackStart (layout_email, false, false, 12);
|
||||
|
||||
layout.PackStart (layout_fields, false, false, 0);
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
|
||||
void UserPageCanContinueEventHandler (PageType page_type, bool can_continue)
|
||||
{
|
||||
if (page_type == RequestedType)
|
||||
Application.Invoke (delegate { continue_button.Sensitive = can_continue; });
|
||||
}
|
||||
}
|
||||
}
|
76
SparkleShare/Linux/UserInterface/Setup.cs
Executable file
76
SparkleShare/Linux/UserInterface/Setup.cs
Executable file
|
@ -0,0 +1,76 @@
|
|||
// SparkleShare, a collaboration and sharing tool.
|
||||
// Copyright (C) 2010 Hylke Bons <hi@planetpeanut.uk>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General private License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General private License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General private License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
using System;
|
||||
|
||||
using Gtk;
|
||||
using Sparkles;
|
||||
|
||||
namespace SparkleShare {
|
||||
|
||||
public class Setup : SetupWindow {
|
||||
|
||||
public PageController Controller = new PageController ();
|
||||
Page active_page;
|
||||
|
||||
|
||||
public Setup ()
|
||||
{
|
||||
Controller.HideWindowEvent += () => {
|
||||
Application.Invoke (delegate {
|
||||
Hide ();
|
||||
|
||||
if (active_page != null) {
|
||||
active_page.Dispose ();
|
||||
active_page = null;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
Controller.ShowWindowEvent += () => {
|
||||
Application.Invoke (delegate {
|
||||
ShowAll ();
|
||||
Present ();
|
||||
});
|
||||
};
|
||||
|
||||
Controller.ChangePageEvent += (PageType type) => {
|
||||
Application.Invoke (delegate {
|
||||
Reset ();
|
||||
ShowPage (type);
|
||||
ShowAll ();
|
||||
Present ();
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
void ShowPage (PageType page_type)
|
||||
{
|
||||
System.Type t = System.Type.GetType ("SparkleShare." + page_type + "Page", throwOnError: true);
|
||||
Page page = (Page) Activator.CreateInstance (t, new object [] { page_type, Controller });
|
||||
|
||||
Header = page.Header;
|
||||
Description = page.Description;
|
||||
|
||||
Add (page.Render ());
|
||||
AddButtons (page.Buttons);
|
||||
|
||||
active_page = page;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -20,90 +20,45 @@ using Gtk;
|
|||
|
||||
namespace SparkleShare {
|
||||
|
||||
public class SetupWindow : Window {
|
||||
public class SetupWindow : Window {
|
||||
|
||||
private EventBox content_area;
|
||||
private EventBox option_area;
|
||||
private HBox buttons;
|
||||
public const int Spacing = 18;
|
||||
|
||||
public string Header;
|
||||
public string Description;
|
||||
|
||||
EventBox content_area;
|
||||
HBox buttons;
|
||||
|
||||
public SetupWindow () : base ("SparkleShare Setup")
|
||||
|
||||
|
||||
public SetupWindow () : base ("SparkleShare")
|
||||
{
|
||||
IconName = "org.sparkleshare.SparkleShare";
|
||||
Resizable = false;
|
||||
WindowPosition = WindowPosition.CenterAlways;
|
||||
WindowPosition = WindowPosition.Center;
|
||||
Deletable = false;
|
||||
TypeHint = Gdk.WindowTypeHint.Dialog;
|
||||
|
||||
SetSizeRequest (720, 540);
|
||||
DeleteEvent += delegate (object sender, DeleteEventArgs args) { args.RetVal = true; };
|
||||
|
||||
VBox layout_vertical = new VBox (false, 16);
|
||||
layout_vertical.BorderWidth = 16;
|
||||
VBox layout_vertical = new VBox (false, 0);
|
||||
layout_vertical.BorderWidth = Spacing;
|
||||
layout_vertical.Spacing = Spacing;
|
||||
|
||||
this.content_area = new EventBox ();
|
||||
this.option_area = new EventBox ();
|
||||
|
||||
this.buttons = CreateButtonBox ();
|
||||
|
||||
HBox layout_actions = new HBox (false , 16);
|
||||
|
||||
layout_actions.PackStart (this.option_area, true, true, 0);
|
||||
layout_actions.PackStart (this.buttons, false, false, 0);
|
||||
|
||||
layout_vertical.PackStart (this.content_area, true, true, 0);
|
||||
layout_vertical.PackStart (layout_actions, false, false, 0);
|
||||
|
||||
base.Add (layout_vertical);
|
||||
}
|
||||
|
||||
|
||||
private HBox CreateButtonBox ()
|
||||
{
|
||||
return new HBox () {
|
||||
this.buttons = new HBox () {
|
||||
BorderWidth = 0,
|
||||
Homogeneous = false,
|
||||
Spacing = 6
|
||||
};
|
||||
}
|
||||
|
||||
layout_vertical.PackStart (this.content_area, true, true, 0);
|
||||
layout_vertical.PackStart (this.buttons, false, false, 0);
|
||||
|
||||
public void AddButton (Button button)
|
||||
{
|
||||
(button.Child as Label).Xpad = 15;
|
||||
this.buttons.Add (button);
|
||||
}
|
||||
|
||||
|
||||
public void AddOption (Widget widget)
|
||||
{
|
||||
this.option_area.Add (widget);
|
||||
}
|
||||
|
||||
|
||||
new public void Add (Widget widget)
|
||||
{
|
||||
Title = Header;
|
||||
|
||||
VBox layout_vertical = new VBox (false, 0);
|
||||
|
||||
if (!string.IsNullOrEmpty (Description)) {
|
||||
Label description = new Label (Description) {
|
||||
Xalign = 0,
|
||||
LineWrap = true,
|
||||
LineWrapMode = Pango.WrapMode.WordChar
|
||||
};
|
||||
|
||||
layout_vertical.PackStart (description, false, false, 0);
|
||||
}
|
||||
|
||||
if (widget != null)
|
||||
layout_vertical.PackStart (widget, true, true, 0);
|
||||
|
||||
this.content_area.Add (layout_vertical);
|
||||
base.Add (layout_vertical);
|
||||
}
|
||||
|
||||
|
||||
|
@ -112,28 +67,47 @@ namespace SparkleShare {
|
|||
Header = "";
|
||||
Description = "";
|
||||
|
||||
if (this.option_area.Children.Length > 0)
|
||||
this.option_area.Remove (this.option_area.Children [0]);
|
||||
|
||||
if (this.content_area.Children.Length > 0)
|
||||
this.content_area.Remove (this.content_area.Children [0]);
|
||||
|
||||
foreach (Button button in this.buttons)
|
||||
foreach (Widget button in this.buttons)
|
||||
this.buttons.Remove (button);
|
||||
}
|
||||
|
||||
|
||||
public void AddButtons (object [] buttons)
|
||||
{
|
||||
if (!Array.Exists (buttons, button => button == null))
|
||||
this.buttons.PackStart (new Label (""), true, true, 0);
|
||||
|
||||
foreach (Button button in buttons) {
|
||||
if (button == null) {
|
||||
this.buttons.PackStart (new Label (""), true, true, 0);
|
||||
|
||||
} else {
|
||||
button.WidthRequest = 100;
|
||||
this.buttons.PackStart (button, false, false, 0);
|
||||
}
|
||||
}
|
||||
|
||||
var default_button = (Button) buttons [buttons.Length - 1];
|
||||
default_button.CanDefault = true;
|
||||
|
||||
default_button.StyleContext.AddClass ("suggested-action");
|
||||
Default = default_button;
|
||||
}
|
||||
|
||||
|
||||
public void Add (object widget)
|
||||
{
|
||||
if (widget != null)
|
||||
this.content_area.Add ((Widget) widget);
|
||||
}
|
||||
|
||||
|
||||
new public void ShowAll ()
|
||||
{
|
||||
if (this.buttons.Children.Length > 0) {
|
||||
Button default_button = (Button) this.buttons.Children [this.buttons.Children.Length - 1];
|
||||
|
||||
default_button.CanDefault = true;
|
||||
Default = default_button;
|
||||
default_button.StyleContext.AddClass ("suggested-action");
|
||||
}
|
||||
|
||||
Present ();
|
||||
Title = Header;
|
||||
base.ShowAll ();
|
||||
}
|
||||
}
|
|
@ -216,34 +216,9 @@ namespace SparkleShare {
|
|||
this.recent_events_item = new MenuItem ("Recent Changes…");
|
||||
this.recent_events_item.Sensitive = Controller.RecentEventsItemEnabled;
|
||||
|
||||
if (!use_appindicator)
|
||||
(folder_item.Submenu as Menu).Add (new SeparatorMenuItem ());
|
||||
|
||||
(folder_item.Submenu as Menu).Add (this.recent_events_item);
|
||||
|
||||
|
||||
this.quit_item = new MenuItem ("Quit") { Sensitive = Controller.QuitItemEnabled };
|
||||
MenuItem add_item = new MenuItem ("Sync Remote Project…");
|
||||
|
||||
MenuItem link_code_item = new MenuItem ("Computer ID");
|
||||
|
||||
if (Controller.LinkCodeItemEnabled) {
|
||||
link_code_item.Submenu = new Menu ();
|
||||
|
||||
string link_code = SparkleShare.Controller.UserAuthenticationInfo.PublicKey.Substring (0, 20) + "...";
|
||||
MenuItem code_item = new MenuItem (link_code) { Sensitive = false };
|
||||
|
||||
MenuItem copy_item = new MenuItem ("Copy to Clipboard");
|
||||
copy_item.Activated += delegate { Controller.CopyToClipboardClicked (); };
|
||||
|
||||
(link_code_item.Submenu as Menu).Add (code_item);
|
||||
|
||||
if (!use_appindicator)
|
||||
(link_code_item.Submenu as Menu).Add (new SeparatorMenuItem ());
|
||||
|
||||
(link_code_item.Submenu as Menu).Add (copy_item);
|
||||
}
|
||||
|
||||
MenuItem about_item = new MenuItem ("About SparkleShare");
|
||||
|
||||
about_item.Activated += delegate { Controller.AboutClicked (); };
|
||||
|
@ -252,9 +227,9 @@ namespace SparkleShare {
|
|||
this.quit_item.Activated += delegate { Controller.QuitClicked (); };
|
||||
|
||||
this.menu.Add (new SeparatorMenuItem ());
|
||||
this.menu.Add (this.recent_events_item);
|
||||
this.menu.Add (add_item);
|
||||
this.menu.Add (link_code_item);
|
||||
this.menu.Add (new SeparatorMenuItem ());
|
||||
this.menu.Add (new SeparatorMenuItem ());
|
||||
this.menu.Add (about_item);
|
||||
this.menu.Add (new SeparatorMenuItem ());
|
||||
this.menu.Add (this.quit_item);
|
||||
|
@ -266,7 +241,7 @@ namespace SparkleShare {
|
|||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Makes the menu visible
|
||||
void ShowMenu (object o, EventArgs args)
|
|
@ -165,5 +165,43 @@ namespace SparkleShare
|
|||
SecondaryTextColor = UserInterfaceHelpers.ColorToHex (text_color);
|
||||
SecondaryTextColorSelected = UserInterfaceHelpers.ColorToHex (text_color_selected);
|
||||
}
|
||||
|
||||
|
||||
// The bindings don't support Gtk.Widget.ScaleFactor yet
|
||||
public int ScaleFactor {
|
||||
get {
|
||||
if (scale_factor > 0)
|
||||
return scale_factor;
|
||||
|
||||
var gsettings = new Command ("gsettings", "get org.gnome.desktop.interface scaling-factor");
|
||||
string output = gsettings.StartAndReadStandardOutput ();
|
||||
|
||||
// Output: "uint32 1"
|
||||
try {
|
||||
scale_factor = Int32.Parse (output.Substring (7));
|
||||
|
||||
} catch (Exception e) {
|
||||
scale_factor = 1;
|
||||
Logger.LogInfo ("UI", "Could not determine screen scale factor: ", e);
|
||||
}
|
||||
|
||||
return scale_factor;
|
||||
}
|
||||
}
|
||||
|
||||
int scale_factor;
|
||||
|
||||
|
||||
}
|
||||
|
||||
public class DescriptionLabel : Label
|
||||
{
|
||||
public DescriptionLabel (string text) : base ()
|
||||
{
|
||||
Sensitive = false;
|
||||
Xalign = 0;
|
||||
|
||||
Markup = string.Format ("<span size='small'>{0}</span>", text);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -31,7 +31,7 @@ namespace SparkleShare {
|
|||
icon_theme.AppendSearchPath (Path.Combine (UserInterface.AssetsPath, "icons"));
|
||||
|
||||
foreach (string search_path in IconTheme.Default.SearchPath)
|
||||
icon_theme.AppendSearchPath (search_path);
|
||||
icon_theme.AppendSearchPath (search_path);
|
||||
|
||||
try {
|
||||
return icon_theme.LoadIcon (name, size, IconLookupFlags.GenericFallback);
|
||||
|
@ -51,6 +51,9 @@ namespace SparkleShare {
|
|||
|
||||
public static Image GetImage (string name)
|
||||
{
|
||||
// if (SparkleShare.UI.ScaleFactor > 1)
|
||||
// name += string.Format ("@{0}x", SparkleShare.UI.ScaleFactor);
|
||||
|
||||
string image_path = Path.Combine (UserInterface.AssetsPath, "pixmaps", name);
|
||||
return new Image (image_path);
|
||||
}
|
|
@ -5,18 +5,35 @@ sparkleshare_src = ['../Common/SparkleShare.cs',
|
|||
'../Common/BaseController.cs',
|
||||
'../Common/EventLogController.cs',
|
||||
'../Common/NoteController.cs',
|
||||
'../Common/SetupController.cs',
|
||||
'../Common/Page.cs',
|
||||
'../Common/PageController.cs',
|
||||
'../Common/PageControllers/PageController.Address.cs',
|
||||
'../Common/PageControllers/PageController.Crypto.cs',
|
||||
'../Common/PageControllers/PageController.Host.cs',
|
||||
'../Common/PageControllers/PageController.Invite.cs',
|
||||
'../Common/PageControllers/PageController.Progress.cs',
|
||||
'../Common/PageControllers/PageController.Privacy.cs',
|
||||
'../Common/PageControllers/PageController.User.cs',
|
||||
'../Common/PageControllers/PageController.Storage.cs',
|
||||
'../Common/StatusIconController.cs',
|
||||
'About.cs',
|
||||
'Bubbles.cs',
|
||||
'Controller.cs',
|
||||
'EventLog.cs',
|
||||
'Note.cs',
|
||||
'Setup.cs',
|
||||
'SetupWindow.cs',
|
||||
'StatusIcon.cs',
|
||||
'UserInterface.cs',
|
||||
'UserInterfaceHelpers.cs']
|
||||
'UserInterface/About.cs',
|
||||
'UserInterface/Bubbles.cs',
|
||||
'UserInterface/EventLog.cs',
|
||||
'UserInterface/Note.cs',
|
||||
'UserInterface/Setup.cs',
|
||||
'UserInterface/SetupWindow.cs',
|
||||
'UserInterface/StatusIcon.cs',
|
||||
'UserInterface/UserInterface.cs',
|
||||
'UserInterface/UserInterfaceHelpers.cs',
|
||||
'UserInterface/Pages/Page.Address.cs',
|
||||
'UserInterface/Pages/Page.Crypto.cs',
|
||||
'UserInterface/Pages/Page.Host.cs',
|
||||
'UserInterface/Pages/Page.Invite.cs',
|
||||
'UserInterface/Pages/Page.Privacy.cs',
|
||||
'UserInterface/Pages/Page.Progress.cs',
|
||||
'UserInterface/Pages/Page.Storage.cs',
|
||||
'UserInterface/Pages/Page.User.cs']
|
||||
|
||||
|
||||
# Startup script
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
// SparkleShare, a collaboration and sharing tool.
|
||||
// Copyright (C) 2010 Hylke Bons <hi@planetpeanut.uk>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as
|
||||
// published by the Free Software Foundation, either version 3 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
namespace Sparkles {
|
||||
|
||||
public abstract class AuthenticationInfo
|
||||
{
|
||||
}
|
||||
}
|
|
@ -22,9 +22,8 @@ using System.Threading;
|
|||
|
||||
namespace Sparkles {
|
||||
|
||||
public class SparkleFetcherInfo {
|
||||
public string Address; // TODO: Uri object
|
||||
public string RemotePath;
|
||||
public class FetcherInfo {
|
||||
public readonly Uri Address;
|
||||
|
||||
public string Fingerprint;
|
||||
|
||||
|
@ -33,22 +32,45 @@ namespace Sparkles {
|
|||
public bool FetchPriorHistory;
|
||||
|
||||
public string AnnouncementsUrl; // TODO: Uri object
|
||||
|
||||
|
||||
public FetcherInfo (Uri address)
|
||||
{
|
||||
Address = address;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public enum FetchResult {
|
||||
Unknown,
|
||||
BackendMissing,
|
||||
NoNetwork,
|
||||
HostNotSupported,
|
||||
HostChanged,
|
||||
NotAuthenticated,
|
||||
UserInterrupted,
|
||||
Success
|
||||
}
|
||||
|
||||
|
||||
public class NetworkException : Exception { }
|
||||
|
||||
|
||||
public abstract class BaseFetcher {
|
||||
|
||||
public event Action Started = delegate { };
|
||||
public event Action Failed = delegate { };
|
||||
|
||||
public event FailedEventHandler Failed = delegate { };
|
||||
public delegate void FailedEventHandler (FetchResult result);
|
||||
|
||||
public event FinishedEventHandler Finished = delegate { };
|
||||
public delegate void FinishedEventHandler (StorageType storage_type, string [] warnings);
|
||||
public delegate void FinishedEventHandler (StorageType storage_type);
|
||||
|
||||
public event ProgressChangedEventHandler ProgressChanged = delegate { };
|
||||
public delegate void ProgressChangedEventHandler (double percentage, double speed, string information);
|
||||
|
||||
|
||||
public abstract bool Fetch ();
|
||||
public abstract FetchResult Fetch ();
|
||||
public abstract void Stop ();
|
||||
public bool IsActive { get; protected set; }
|
||||
public double ProgressPercentage { get; private set; }
|
||||
|
@ -67,27 +89,10 @@ namespace Sparkles {
|
|||
public string RequiredFingerprint { get; protected set; }
|
||||
public readonly bool FetchPriorHistory;
|
||||
public string TargetFolder { get; protected set; }
|
||||
public SparkleFetcherInfo OriginalFetcherInfo;
|
||||
public FetcherInfo OriginalFetcherInfo;
|
||||
|
||||
|
||||
protected List<string> warnings = new List<string> ();
|
||||
protected List<string> errors = new List<string> ();
|
||||
|
||||
public string [] Warnings {
|
||||
get {
|
||||
return warnings.ToArray ();
|
||||
}
|
||||
}
|
||||
|
||||
public string [] Errors {
|
||||
get {
|
||||
return errors.ToArray ();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected BaseFetcher (SparkleFetcherInfo info)
|
||||
protected BaseFetcher (FetcherInfo info)
|
||||
{
|
||||
FetchedRepoStorageType = StorageType.Unknown;
|
||||
|
||||
|
@ -95,10 +100,12 @@ namespace Sparkles {
|
|||
new StorageTypeInfo (StorageType.Plain, "Plain Storage", "Nothing fancy;\nmaximum compatibility"));
|
||||
|
||||
OriginalFetcherInfo = info;
|
||||
|
||||
RequiredFingerprint = info.Fingerprint;
|
||||
FetchPriorHistory = info.FetchPriorHistory;
|
||||
string remote_path = info.RemotePath.Trim ("/".ToCharArray ());
|
||||
string address = info.Address;
|
||||
|
||||
string remote_path = info.Address.AbsolutePath.Trim ("/".ToCharArray ());
|
||||
string address = info.Address.ToString ();
|
||||
|
||||
if (address.EndsWith ("/", StringComparison.InvariantCulture))
|
||||
address = address.Substring (0, address.Length - 1);
|
||||
|
@ -130,30 +137,29 @@ namespace Sparkles {
|
|||
Directory.Delete (TargetFolder, recursive: true);
|
||||
|
||||
} catch (IOException) {
|
||||
errors.Add ("\"" + TargetFolder + "\" is read-only.");
|
||||
Failed ();
|
||||
Failed (FetchResult.Unknown);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
thread = new Thread (() => {
|
||||
if (Fetch ()) {
|
||||
FetchResult result = Fetch ();
|
||||
|
||||
if (result == FetchResult.Success) {
|
||||
Thread.Sleep (500);
|
||||
Logger.LogInfo ("Fetcher", "Finished");
|
||||
|
||||
IsActive = false;
|
||||
Finished (FetchedRepoStorageType, Warnings);
|
||||
Finished (FetchedRepoStorageType);
|
||||
|
||||
} else {
|
||||
Thread.Sleep (500);
|
||||
|
||||
if (IsActive) {
|
||||
Logger.LogInfo ("Fetcher", "Failed");
|
||||
Failed ();
|
||||
|
||||
} else {
|
||||
Logger.LogInfo ("Fetcher", "Failed: cancelled by user");
|
||||
}
|
||||
if (!IsActive)
|
||||
result = FetchResult.UserInterrupted;
|
||||
|
||||
Failed (result);
|
||||
Logger.LogInfo ("Fetcher", string.Format ("Failed ({0})", result));
|
||||
|
||||
IsActive = false;
|
||||
}
|
||||
|
|
|
@ -37,14 +37,18 @@ namespace Sparkles {
|
|||
|
||||
StartInfo.FileName = path;
|
||||
StartInfo.Arguments = args;
|
||||
|
||||
StartInfo.WorkingDirectory = Path.GetTempPath ();
|
||||
|
||||
StartInfo.CreateNoWindow = true;
|
||||
StartInfo.RedirectStandardOutput = true;
|
||||
StartInfo.RedirectStandardError = true;
|
||||
StartInfo.UseShellExecute = false;
|
||||
|
||||
StartInfo.RedirectStandardOutput = true;
|
||||
StartInfo.RedirectStandardError = true;
|
||||
|
||||
EnableRaisingEvents = true;
|
||||
|
||||
// Force set the language because we do a lot of string parsing
|
||||
SetEnvironmentVariable ("LANG", "en_US");
|
||||
}
|
||||
|
||||
|
||||
|
@ -103,8 +107,7 @@ namespace Sparkles {
|
|||
return output.TrimEnd ();
|
||||
}
|
||||
|
||||
|
||||
public void SetEnvironmentVariable (string variable, string content)
|
||||
public void SetEnvironmentVariable (string variable, string content)
|
||||
{
|
||||
if (StartInfo.EnvironmentVariables.ContainsKey (variable))
|
||||
StartInfo.EnvironmentVariables [variable] = content;
|
||||
|
|
|
@ -72,7 +72,7 @@ namespace Sparkles {
|
|||
FilePath = Path.Combine (config_path, config_file_name);
|
||||
DirectoryPath = config_path;
|
||||
|
||||
BinPath = Path.Combine (config_path, "bin");
|
||||
BinPath = Path.Combine (config_path, "bin");
|
||||
|
||||
if (!Directory.Exists (BinPath))
|
||||
Directory.CreateDirectory (BinPath);
|
||||
|
@ -328,7 +328,7 @@ namespace Sparkles {
|
|||
}
|
||||
|
||||
Save ();
|
||||
Logger.LogInfo ("Config", "Updated option " + name + ":" + content);
|
||||
Logger.LogInfo ("Config", string.Format ("Set {0} {1}:{2}", FilePath, name, content));
|
||||
}
|
||||
|
||||
|
||||
|
@ -352,7 +352,6 @@ namespace Sparkles {
|
|||
void Save ()
|
||||
{
|
||||
Save (FilePath);
|
||||
Logger.LogInfo ("Config", "Wrote to '" + FilePath + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -98,8 +98,6 @@ namespace Sparkles.Git {
|
|||
SetEnvironmentVariable ("GIT_CONFIG_NOSYSTEM", "1");
|
||||
SetEnvironmentVariable ("PREFIX", "");
|
||||
SetEnvironmentVariable ("HOME", "");
|
||||
|
||||
SetEnvironmentVariable ("LANG", "en_US");
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ namespace Sparkles.Git {
|
|||
}
|
||||
|
||||
|
||||
public GitFetcher (SparkleFetcherInfo fetcher_info, SSHAuthenticationInfo auth_info) : base (fetcher_info)
|
||||
public GitFetcher (FetcherInfo fetcher_info, SSHAuthenticationInfo auth_info) : base (fetcher_info, auth_info)
|
||||
{
|
||||
this.auth_info = auth_info;
|
||||
var uri_builder = new UriBuilder (RemoteUrl);
|
||||
|
@ -72,15 +72,17 @@ namespace Sparkles.Git {
|
|||
}
|
||||
|
||||
|
||||
public override bool Fetch ()
|
||||
public override FetchResult Fetch ()
|
||||
{
|
||||
if (!base.Fetch ())
|
||||
return false;
|
||||
FetchResult result = base.Fetch ();
|
||||
|
||||
if (result != FetchResult.Success)
|
||||
return result;
|
||||
|
||||
StorageType? storage_type = DetermineStorageType ();
|
||||
|
||||
if (storage_type == null)
|
||||
return false;
|
||||
return FetchResult.NoNetwork; // TODO: or HostNotSupported
|
||||
|
||||
FetchedRepoStorageType = (StorageType) storage_type;
|
||||
|
||||
|
@ -111,6 +113,7 @@ namespace Sparkles.Git {
|
|||
while (!output_stream.EndOfStream) {
|
||||
string line = output_stream.ReadLine ();
|
||||
|
||||
// TODO: Make ParseProgress use FetchResult
|
||||
ErrorStatus error = GitCommand.ParseProgress (line, out percentage, out speed, out information);
|
||||
|
||||
if (error != ErrorStatus.None) {
|
||||
|
@ -118,7 +121,7 @@ namespace Sparkles.Git {
|
|||
git_clone.Kill ();
|
||||
git_clone.Dispose ();
|
||||
|
||||
return false;
|
||||
return FetchResult.Unknown; // TODO
|
||||
}
|
||||
|
||||
OnProgressChanged (percentage, speed, information);
|
||||
|
@ -127,13 +130,14 @@ namespace Sparkles.Git {
|
|||
git_clone.WaitForExit ();
|
||||
|
||||
if (git_clone.ExitCode != 0)
|
||||
return false;
|
||||
return FetchResult.Unknown; // TODO
|
||||
|
||||
// Smooth out progression
|
||||
Thread.Sleep (500);
|
||||
OnProgressChanged (100, 0, "");
|
||||
Thread.Sleep (500);
|
||||
|
||||
return true;
|
||||
return FetchResult.Success;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ namespace Sparkles {
|
|||
|
||||
public class SparkleInvite : XmlDocument {
|
||||
|
||||
public string Address { get; private set; }
|
||||
public string Address { get; private set; } // TODO: uri
|
||||
public string RemotePath { get; private set; }
|
||||
public string Fingerprint { get; private set; }
|
||||
public string AcceptUrl { get; private set; }
|
||||
|
|
|
@ -32,6 +32,8 @@ namespace Sparkles {
|
|||
|
||||
new public string Name { get { return GetValue ("info", "name"); } }
|
||||
public string Description { get { return GetValue ("info", "description"); } }
|
||||
public string Host { get { return GetValue ("info", "host"); } }
|
||||
public string KeyEntryHint { get { return GetValue ("key", "hint"); } }
|
||||
public string Backend { get { return GetValue ("info", "backend"); } }
|
||||
public string Fingerprint { get { return GetValue ("info", "fingerprint"); } }
|
||||
public string AnnouncementsUrl { get { return GetValue ("info", "announcements_url"); } }
|
||||
|
@ -40,7 +42,7 @@ namespace Sparkles {
|
|||
public string Path { get { return GetValue ("path", "value"); } }
|
||||
public string PathExample { get { return GetValue ("path", "example"); } }
|
||||
|
||||
public string ImagePath {
|
||||
public string IconPath {
|
||||
get {
|
||||
string image_file_name = GetValue ("info", "icon");
|
||||
string image_path = IO.Path.Combine (preset_directory, image_file_name);
|
||||
|
@ -51,7 +53,19 @@ namespace Sparkles {
|
|||
return IO.Path.Combine (PresetsPath, image_file_name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public string LogoPath {
|
||||
get {
|
||||
string image_file_name = GetValue ("info", "logo");
|
||||
string image_path = IO.Path.Combine (preset_directory, image_file_name);
|
||||
|
||||
if (IO.File.Exists (image_path))
|
||||
return image_path;
|
||||
|
||||
return IO.Path.Combine (PresetsPath, image_file_name);
|
||||
}
|
||||
}
|
||||
|
||||
public bool PathUsesLowerCase {
|
||||
get {
|
||||
string uses_lower_case = GetValue ("path", "uses_lower_case");
|
||||
|
@ -110,14 +124,14 @@ namespace Sparkles {
|
|||
}
|
||||
|
||||
|
||||
private string GetValue (string a, string b)
|
||||
string GetValue (string a, string b)
|
||||
{
|
||||
XmlNode node = SelectSingleNode ("/sparkleshare/preset/" + a + "/" + b + "/text()");
|
||||
XmlNode node = SelectSingleNode ("/sparkleshare/preset/" + a + "/" + b);
|
||||
|
||||
if (node != null && !string.IsNullOrEmpty (node.Value))
|
||||
return node.Value;
|
||||
else
|
||||
if (node == null)
|
||||
return null;
|
||||
|
||||
return node.InnerXml;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,11 @@ using IO = System.IO;
|
|||
|
||||
namespace Sparkles {
|
||||
|
||||
public abstract class AuthenticationInfo
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
public class SSHAuthenticationInfo : AuthenticationInfo {
|
||||
|
||||
public static SSHAuthenticationInfo DefaultAuthenticationInfo;
|
||||
|
@ -82,7 +87,7 @@ namespace Sparkles {
|
|||
}
|
||||
|
||||
|
||||
bool CreateKeyPair ()
|
||||
void CreateKeyPair ()
|
||||
{
|
||||
string key_file_name = DateTime.Now.ToString ("yyyy-MM-dd_HH\\hmm") + ".key";
|
||||
string computer_name = Dns.GetHostName ();
|
||||
|
@ -108,11 +113,11 @@ namespace Sparkles {
|
|||
Logger.LogInfo ("Auth", "Created key pair: " + key_file_name);
|
||||
ImportKeys ();
|
||||
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
Logger.LogInfo ("Auth", "Could not create key pair");
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -20,48 +20,65 @@ using System.IO;
|
|||
using System.Security.Cryptography;
|
||||
|
||||
namespace Sparkles {
|
||||
|
||||
|
||||
public abstract class SSHFetcher : BaseFetcher {
|
||||
|
||||
public static string SSHKeyScan = "ssh-keyscan";
|
||||
SSHAuthenticationInfo auth_info;
|
||||
|
||||
|
||||
protected SSHFetcher (SparkleFetcherInfo info) : base (info)
|
||||
protected SSHFetcher (FetcherInfo info, SSHAuthenticationInfo auth_info) : base (info)
|
||||
{
|
||||
this.auth_info = auth_info;
|
||||
}
|
||||
|
||||
|
||||
public override bool Fetch ()
|
||||
public override FetchResult Fetch ()
|
||||
{
|
||||
bool host_key_missing = false;
|
||||
string host_key = FetchHostKey ();
|
||||
bool host_key_warning = false;
|
||||
|
||||
if (string.IsNullOrEmpty (RemoteUrl.Host) || host_key == null) {
|
||||
Logger.LogInfo ("Auth", "Could not fetch host key");
|
||||
errors.Add ("error: Could not fetch host key");
|
||||
if (host_key == null)
|
||||
host_key_missing = true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (RequiredFingerprint != null) {
|
||||
string host_fingerprint = DeriveFingerprint (host_key);
|
||||
|
||||
if (host_fingerprint == null || RequiredFingerprint!= host_fingerprint) {
|
||||
Logger.LogInfo ("Auth", "Fingerprint doesn't match");
|
||||
errors.Add ("error: Host fingerprint doesn't match");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Logger.LogInfo ("Auth", "Fingerprint matches");
|
||||
if (RequiredFingerprint == null) {
|
||||
Logger.LogInfo ("Auth", "Skipping fingerprint check"); // TODO expose to UI
|
||||
|
||||
} else {
|
||||
Logger.LogInfo ("Auth", "Skipping fingerprint check");
|
||||
host_key_warning = true;
|
||||
string host_fingerprint;
|
||||
|
||||
try {
|
||||
host_fingerprint = DeriveFingerprint (host_key);
|
||||
|
||||
} catch {
|
||||
return FetchResult.HostNotSupported;
|
||||
}
|
||||
|
||||
if (RequiredFingerprint != host_fingerprint) {
|
||||
Logger.LogInfo ("Auth", "Fingerprints don't match");
|
||||
return FetchResult.HostChanged;
|
||||
}
|
||||
|
||||
Logger.LogInfo ("Auth", "Fingerprints match");
|
||||
}
|
||||
|
||||
AcceptHostKey (host_key, host_key_warning);
|
||||
return true;
|
||||
bool authenticated;
|
||||
|
||||
try {
|
||||
authenticated = CanAuthenticateTo (RemoteUrl, this.auth_info);
|
||||
|
||||
} catch (NetworkException) {
|
||||
return FetchResult.NoNetwork;
|
||||
}
|
||||
|
||||
if (host_key_missing)
|
||||
return FetchResult.HostNotSupported;
|
||||
|
||||
if (!authenticated)
|
||||
return FetchResult.NotAuthenticated;
|
||||
|
||||
AcceptHostKey (host_key);
|
||||
return FetchResult.Success;
|
||||
}
|
||||
|
||||
|
||||
|
@ -78,32 +95,12 @@ namespace Sparkles {
|
|||
if (ssh_keyscan.ExitCode == 0 && !string.IsNullOrWhiteSpace (host_key))
|
||||
return host_key;
|
||||
|
||||
Logger.LogInfo ("Auth", "Could not fetch host key");
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
string DeriveFingerprint (string public_key)
|
||||
{
|
||||
try {
|
||||
SHA256 sha256 = new SHA256CryptoServiceProvider ();
|
||||
string key = public_key.Split (" ".ToCharArray ()) [2];
|
||||
|
||||
byte [] base64_bytes = Convert.FromBase64String (key);
|
||||
byte [] sha256_bytes = sha256.ComputeHash (base64_bytes);
|
||||
|
||||
string fingerprint = BitConverter.ToString (sha256_bytes);
|
||||
fingerprint = fingerprint.ToLower ().Replace ("-", ":");
|
||||
|
||||
return fingerprint;
|
||||
|
||||
} catch (Exception e) {
|
||||
Logger.LogInfo ("Fetcher", "Failed to create fingerprint: ", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void AcceptHostKey (string host_key, bool warn)
|
||||
void AcceptHostKey (string host_key)
|
||||
{
|
||||
string ssh_config_path = Path.Combine (Configuration.DefaultConfiguration.DirectoryPath, "ssh");
|
||||
string known_hosts_file_path = Path.Combine (ssh_config_path, "known_hosts");
|
||||
|
@ -128,11 +125,57 @@ namespace Sparkles {
|
|||
File.AppendAllText (known_hosts_file_path, host_key + "\n");
|
||||
else
|
||||
File.AppendAllText (known_hosts_file_path, "\n" + host_key + "\n");
|
||||
}
|
||||
|
||||
Logger.LogInfo ("Auth", "Accepted host key for " + host);
|
||||
|
||||
if (warn)
|
||||
warnings.Add ("The following host key has been accepted:\n" + DeriveFingerprint (host_key));
|
||||
string DeriveFingerprint (string public_key)
|
||||
{
|
||||
try {
|
||||
SHA256 sha256 = new SHA256CryptoServiceProvider ();
|
||||
string key = public_key.Split (" ".ToCharArray ()) [2];
|
||||
|
||||
byte [] base64_bytes = Convert.FromBase64String (key);
|
||||
byte [] sha256_bytes = sha256.ComputeHash (base64_bytes);
|
||||
|
||||
string fingerprint = BitConverter.ToString (sha256_bytes);
|
||||
fingerprint = fingerprint.ToLower ().Replace ("-", ":");
|
||||
|
||||
return fingerprint;
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new FormatException ("Could not derive fingerprint from " + public_key, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static bool CanAuthenticateTo (Uri host, SSHAuthenticationInfo auth_info)
|
||||
{
|
||||
if (host == null || auth_info == null)
|
||||
throw new ArgumentNullException ();
|
||||
|
||||
const string AUTH_CHECK = "Authentication succeeded";
|
||||
const string OFFLINE_CHECK = "Could not resolve hostname";
|
||||
|
||||
string server = host.Authority;
|
||||
|
||||
if (!string.IsNullOrEmpty (host.UserInfo))
|
||||
server = host.UserInfo + "@" + host.Authority;
|
||||
|
||||
string [] args = new string [] {
|
||||
"-T", // Non-interactive mode
|
||||
"-v", // Verbose output to StandardError
|
||||
"-o", "StrictHostKeyChecking=no",
|
||||
"-o", "UserKnownHostsFile=/dev/null",
|
||||
"-i", auth_info.PrivateKeyFilePath,
|
||||
server };
|
||||
|
||||
var ssh = new Command ("ssh", string.Join (" ", args));
|
||||
string output = ssh.StartAndReadStandardError ();
|
||||
|
||||
if (output.Contains (OFFLINE_CHECK))
|
||||
throw new NetworkException ();
|
||||
|
||||
return output.Contains (AUTH_CHECK);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -73,14 +73,10 @@
|
|||
<Compile Include="ListenerFactory.cs" />
|
||||
<Compile Include="Logger.cs" />
|
||||
<Compile Include="InstallationInfo.Directory.cs" />
|
||||
<Compile Include="Command.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="SSHCommand.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="SSHFetcher.cs" />
|
||||
<Compile Include="SSHAuthenticationInfo.cs" />
|
||||
<Compile Include="Command.cs" />
|
||||
<Compile Include="SSH\SSHCommand.cs" />
|
||||
<Compile Include="SSH\SSHFetcher.cs" />
|
||||
<Compile Include="SSH\SSHAuthenticationInfo.cs" />
|
||||
<Compile Include="TcpListener.cs" />
|
||||
<Compile Include="User.cs" />
|
||||
<Compile Include="InstallationInfo.cs" />
|
||||
|
|
|
@ -3,8 +3,7 @@ directory_info_file = configure_file(
|
|||
output: 'InstallationInfo.Directory.cs',
|
||||
configuration: configuration)
|
||||
|
||||
sparkles_src = ['AuthenticationInfo.cs',
|
||||
'BaseFetcher.cs',
|
||||
sparkles_src = ['BaseFetcher.cs',
|
||||
'BaseListener.cs',
|
||||
'BaseRepository.cs',
|
||||
'ChangeSet.cs',
|
||||
|
@ -17,9 +16,9 @@ sparkles_src = ['AuthenticationInfo.cs',
|
|||
'ListenerFactory.cs',
|
||||
'Logger.cs',
|
||||
'Preset.cs',
|
||||
'SSHAuthenticationInfo.cs',
|
||||
'SSHCommand.cs',
|
||||
'SSHFetcher.cs',
|
||||
'SSH/SSH.AuthenticationInfo.cs',
|
||||
'SSH/SSH.Command.cs',
|
||||
'SSH/SSH.Fetcher.cs',
|
||||
'TcpListener.cs',
|
||||
'User.cs',
|
||||
'Watcher.cs']
|
||||
|
@ -30,4 +29,3 @@ sparkles = library('Sparkles',
|
|||
cs_args: '-r:System.Xml.Linq',
|
||||
install: true,
|
||||
install_dir: install_dir)
|
||||
|
||||
|
|
|
@ -1,3 +1,2 @@
|
|||
option('ubuntu', type: 'boolean', value: false)
|
||||
option('nightly', type: 'boolean', value: false)
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue