Merge branch 'master' into gettext-cs
Conflicts: SparkleLib/Git/SparkleRepoGit.cs
This commit is contained in:
commit
d096c39e5d
11
NEWS
11
NEWS
|
@ -1,3 +1,14 @@
|
|||
0.8.1 for Linux and Mac (Sun Jan 29):
|
||||
|
||||
Hylke:
|
||||
- Disable the Quit menu item when a sync is going on
|
||||
- Show remote url when hovering project names in the log
|
||||
- Fix the event log on Linux
|
||||
- Allow server ports to be specified once again
|
||||
- Open Folder button after setup now takes you to SparkleShare/subfolder
|
||||
- Close event log on Cmd+W on Mac
|
||||
|
||||
|
||||
0.8.0 for Linux and Mac (Sun Jan 22):
|
||||
|
||||
Hylke:
|
||||
|
|
|
@ -51,7 +51,7 @@ namespace SparkleLib {
|
|||
if (!uri.Scheme.Equals ("ssh") &&
|
||||
!uri.Scheme.Equals ("git")) {
|
||||
|
||||
uri = new Uri ("ssh://" + server);
|
||||
uri = new Uri ("ssh://" + uri);
|
||||
}
|
||||
|
||||
|
||||
|
@ -72,8 +72,10 @@ namespace SparkleLib {
|
|||
uri = new Uri ("ssh://git@gnome.org/git" + uri.AbsolutePath);
|
||||
|
||||
} else {
|
||||
if (string.IsNullOrEmpty (uri.UserInfo))
|
||||
uri = new Uri (uri.Scheme + "://git@" + uri.Host + uri.AbsolutePath);
|
||||
if (string.IsNullOrEmpty (uri.UserInfo)) {
|
||||
uri = new Uri (uri.Scheme + "://git@" + uri.Host + ":" + uri.Port + uri.AbsolutePath);
|
||||
uri = new Uri (uri.ToString ().Replace (":-1", ""));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -221,75 +223,11 @@ namespace SparkleLib {
|
|||
SparkleHelpers.CombineMore (this.target_folder, ".git", "info"));
|
||||
|
||||
// File that lists the files we want git to ignore
|
||||
string exlude_rules_file_path = Path.Combine (info.FullName, "exclude");
|
||||
TextWriter writer = new StreamWriter (exlude_rules_file_path);
|
||||
string exclude_rules_file_path = Path.Combine (info.FullName, "exclude");
|
||||
TextWriter writer = new StreamWriter (exclude_rules_file_path);
|
||||
|
||||
// gedit and emacs
|
||||
writer.WriteLine ("*~");
|
||||
|
||||
// Firefox and Chromium temporary download files
|
||||
writer.WriteLine ("*.part");
|
||||
writer.WriteLine ("*.crdownload");
|
||||
|
||||
// vi(m)
|
||||
writer.WriteLine (".*.sw[a-z]");
|
||||
writer.WriteLine ("*.un~");
|
||||
writer.WriteLine ("*.swp");
|
||||
writer.WriteLine ("*.swo");
|
||||
|
||||
// KDE
|
||||
writer.WriteLine (".directory");
|
||||
|
||||
// Mac OS X
|
||||
writer.WriteLine (".DS_Store");
|
||||
writer.WriteLine ("Icon?");
|
||||
writer.WriteLine ("._*");
|
||||
writer.WriteLine (".Spotlight-V100");
|
||||
writer.WriteLine (".Trashes");
|
||||
|
||||
// Omnigraffle
|
||||
writer.WriteLine ("*(Autosaved).graffle");
|
||||
|
||||
// Windows
|
||||
writer.WriteLine ("Thumbs.db");
|
||||
writer.WriteLine ("Desktop.ini");
|
||||
|
||||
// MS Office
|
||||
writer.WriteLine ("~*.tmp");
|
||||
writer.WriteLine ("~*.TMP");
|
||||
writer.WriteLine ("*~*.tmp");
|
||||
writer.WriteLine ("*~*.TMP");
|
||||
writer.WriteLine ("~*.ppt");
|
||||
writer.WriteLine ("~*.PPT");
|
||||
writer.WriteLine ("~*.pptx");
|
||||
writer.WriteLine ("~*.PPTX");
|
||||
writer.WriteLine ("~*.xls");
|
||||
writer.WriteLine ("~*.XLS");
|
||||
writer.WriteLine ("~*.xlsx");
|
||||
writer.WriteLine ("~*.XLSX");
|
||||
writer.WriteLine ("~*.doc");
|
||||
writer.WriteLine ("~*.DOC");
|
||||
writer.WriteLine ("~*.docx");
|
||||
writer.WriteLine ("~*.DOCX");
|
||||
|
||||
// CVS
|
||||
writer.WriteLine ("*/CVS/*");
|
||||
writer.WriteLine (".cvsignore");
|
||||
writer.WriteLine ("*/.cvsignore");
|
||||
|
||||
// Subversion
|
||||
writer.WriteLine ("/.svn/*");
|
||||
writer.WriteLine ("*/.svn/*");
|
||||
|
||||
// Mercurial
|
||||
writer.WriteLine ("/.hg/*");
|
||||
writer.WriteLine ("*/.hg/*");
|
||||
writer.WriteLine ("*/.hgignore");
|
||||
|
||||
// Bazaar
|
||||
writer.WriteLine ("/.bzr/*");
|
||||
writer.WriteLine ("*/.bzr/*");
|
||||
writer.WriteLine ("*/.bzrignore");
|
||||
foreach (string exclude_rule in ExcludeRules)
|
||||
writer.WriteLine (exclude_rule);
|
||||
|
||||
writer.Close ();
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@ namespace SparkleLib {
|
|||
StartInfo.RedirectStandardOutput = true;
|
||||
StartInfo.UseShellExecute = false;
|
||||
StartInfo.WorkingDirectory = path;
|
||||
StartInfo.CreateNoWindow = true;
|
||||
|
||||
if (!string.IsNullOrEmpty (ExecPath))
|
||||
StartInfo.Arguments = "--exec-path=\"" + ExecPath + "\" " + args;
|
||||
|
|
|
@ -26,8 +26,9 @@ namespace SparkleLib {
|
|||
|
||||
public class SparkleRepoGit : SparkleRepoBase {
|
||||
|
||||
public SparkleRepoGit (string path, SparkleBackend backend) :
|
||||
base (path, backend) { }
|
||||
public SparkleRepoGit (string path) : base (path)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
private string identifier = null;
|
||||
|
@ -71,7 +72,7 @@ namespace SparkleLib {
|
|||
|
||||
public override double Size {
|
||||
get {
|
||||
string file_path = SparkleHelpers.CombineMore (LocalPath, ".git", "repo_size");
|
||||
string file_path = new string [] {LocalPath, ".git", "repo_size"}.Combine ();
|
||||
|
||||
try {
|
||||
return double.Parse (File.ReadAllText (file_path));
|
||||
|
@ -85,7 +86,7 @@ namespace SparkleLib {
|
|||
|
||||
public override double HistorySize {
|
||||
get {
|
||||
string file_path = SparkleHelpers.CombineMore(LocalPath, ".git", "repo_history_size");
|
||||
string file_path = new string [] {LocalPath, ".git", "repo_history_size"}.Combine ();
|
||||
|
||||
try {
|
||||
return double.Parse (File.ReadAllText (file_path));
|
||||
|
@ -105,8 +106,8 @@ namespace SparkleLib {
|
|||
double history_size = CalculateSize (
|
||||
new DirectoryInfo (Path.Combine (LocalPath, ".git")));
|
||||
|
||||
string size_file_path = SparkleHelpers.CombineMore(LocalPath, ".git", "repo_size");
|
||||
string history_size_file_path = SparkleHelpers.CombineMore(LocalPath, ".git", "repo_history_size");
|
||||
string size_file_path = new string [] {LocalPath, ".git", "repo_size"}.Combine ();
|
||||
string history_size_file_path = new string [] {LocalPath, ".git", "repo_history_size"}.Combine ();
|
||||
|
||||
File.WriteAllText (size_file_path, size.ToString ());
|
||||
File.WriteAllText (history_size_file_path, history_size.ToString ());
|
||||
|
@ -169,7 +170,7 @@ namespace SparkleLib {
|
|||
public override bool CheckForRemoteChanges ()
|
||||
{
|
||||
SparkleHelpers.DebugInfo ("Git", "[" + Name + "] Checking for remote changes...");
|
||||
SparkleGit git = new SparkleGit (LocalPath, "ls-remote origin master");
|
||||
SparkleGit git = new SparkleGit (LocalPath, "ls-remote " + Url + " master");
|
||||
|
||||
git.Start ();
|
||||
git.WaitForExit ();
|
||||
|
@ -201,7 +202,7 @@ namespace SparkleLib {
|
|||
|
||||
SparkleGit git = new SparkleGit (LocalPath,
|
||||
"push --progress " + // Redirects progress stats to standarderror
|
||||
"origin master");
|
||||
Url + " master");
|
||||
|
||||
git.StartInfo.RedirectStandardError = true;
|
||||
git.Start ();
|
||||
|
@ -258,7 +259,7 @@ namespace SparkleLib {
|
|||
|
||||
public override bool SyncDown ()
|
||||
{
|
||||
SparkleGit git = new SparkleGit (LocalPath, "fetch --progress");
|
||||
SparkleGit git = new SparkleGit (LocalPath, "fetch --progress " + Url);
|
||||
|
||||
git.StartInfo.RedirectStandardError = true;
|
||||
git.Start ();
|
||||
|
@ -623,11 +624,12 @@ namespace SparkleLib {
|
|||
if (match.Success) {
|
||||
SparkleChangeSet change_set = new SparkleChangeSet ();
|
||||
|
||||
change_set.Folder = Name;
|
||||
change_set.Revision = match.Groups [1].Value;
|
||||
change_set.User.Name = match.Groups [2].Value;
|
||||
change_set.User.Email = match.Groups [3].Value;
|
||||
change_set.IsMagical = is_merge_commit;
|
||||
change_set.Folder = Name;
|
||||
change_set.Revision = match.Groups [1].Value;
|
||||
change_set.User.Name = match.Groups [2].Value;
|
||||
change_set.User.Email = match.Groups [3].Value;
|
||||
change_set.IsMagical = is_merge_commit;
|
||||
change_set.Url = Url;
|
||||
|
||||
change_set.Timestamp = new DateTime (int.Parse (match.Groups [4].Value),
|
||||
int.Parse (match.Groups [5].Value), int.Parse (match.Groups [6].Value),
|
||||
|
|
|
@ -9,6 +9,7 @@ SOURCES = \
|
|||
SparkleBackend.cs \
|
||||
SparkleChangeSet.cs \
|
||||
SparkleConfig.cs \
|
||||
SparkleExtensions.cs \
|
||||
SparkleFetcherBase.cs \
|
||||
SparkleHelpers.cs \
|
||||
SparkleListenerBase.cs \
|
||||
|
|
|
@ -30,6 +30,7 @@ namespace SparkleLib {
|
|||
public DateTime Timestamp;
|
||||
public DateTime FirstTimestamp;
|
||||
public bool IsMagical = false;
|
||||
public Uri Url;
|
||||
|
||||
public List<string> Added = new List<string> ();
|
||||
public List<string> Deleted = new List<string> ();
|
||||
|
|
35
SparkleLib/SparkleExtensions.cs
Executable file
35
SparkleLib/SparkleExtensions.cs
Executable file
|
@ -0,0 +1,35 @@
|
|||
// SparkleShare, a collaboration and sharing tool.
|
||||
// Copyright (C) 2010 Hylke Bons (hylkebons@gmail.com)
|
||||
//
|
||||
// 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;
|
||||
|
||||
namespace SparkleLib {
|
||||
|
||||
public static class Extensions {
|
||||
|
||||
public static string Combine (this String [] parts)
|
||||
{
|
||||
string new_path = "";
|
||||
|
||||
foreach (string part in parts)
|
||||
new_path = Path.Combine (new_path, part);
|
||||
|
||||
return new_path;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -16,8 +16,8 @@
|
|||
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Security.AccessControl;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
|
@ -37,22 +37,94 @@ namespace SparkleLib {
|
|||
public event FailedEventHandler Failed;
|
||||
public event ProgressChangedEventHandler ProgressChanged;
|
||||
|
||||
public string [] ExcludeRules;
|
||||
|
||||
protected string target_folder;
|
||||
protected string remote_url;
|
||||
|
||||
private Thread thread;
|
||||
|
||||
|
||||
|
||||
public SparkleFetcherBase (string server, string remote_folder, string target_folder)
|
||||
{
|
||||
this.target_folder = target_folder;
|
||||
this.remote_url = server + "/" + remote_folder;
|
||||
|
||||
ExcludeRules = new string [] {
|
||||
// gedit and emacs
|
||||
"*~",
|
||||
|
||||
// Firefox and Chromium temporary download files
|
||||
"*.part",
|
||||
"*.crdownload",
|
||||
|
||||
// vi(m)
|
||||
".*.sw[a-z]",
|
||||
"*.un~",
|
||||
"*.swp",
|
||||
"*.swo",
|
||||
|
||||
// KDE
|
||||
".directory",
|
||||
|
||||
// Mac OS X
|
||||
".DS_Store",
|
||||
"Icon?",
|
||||
"._*",
|
||||
".Spotlight-V100",
|
||||
".Trashes",
|
||||
|
||||
// Omnigraffle
|
||||
"*(Autosaved).graffle",
|
||||
|
||||
// Windows
|
||||
"Thumbs.db",
|
||||
"Desktop.ini",
|
||||
|
||||
// MS Office
|
||||
"~*.tmp",
|
||||
"~*.TMP",
|
||||
"*~*.tmp",
|
||||
"*~*.TMP",
|
||||
"~*.ppt",
|
||||
"~*.PPT",
|
||||
"~*.pptx",
|
||||
"~*.PPTX",
|
||||
"~*.xls",
|
||||
"~*.XLS",
|
||||
"~*.xlsx",
|
||||
"~*.XLSX",
|
||||
"~*.doc",
|
||||
"~*.DOC",
|
||||
"~*.docx",
|
||||
"~*.DOCX",
|
||||
|
||||
// CVS
|
||||
"*/CVS/*",
|
||||
".cvsignore",
|
||||
"*/.cvsignore",
|
||||
|
||||
// Subversion
|
||||
"/.svn/*",
|
||||
"*/.svn/*",
|
||||
|
||||
// Mercurial
|
||||
"/.hg/*",
|
||||
"*/.hg/*",
|
||||
"*/.hgignore",
|
||||
|
||||
// Bazaar
|
||||
"/.bzr/*",
|
||||
"*/.bzr/*",
|
||||
"*/.bzrignore"
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
public abstract bool Fetch ();
|
||||
public abstract string [] Warnings { get; }
|
||||
|
||||
|
||||
// Clones the remote repository
|
||||
public void Start ()
|
||||
{
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
<Compile Include="SparkleBackend.cs" />
|
||||
<Compile Include="SparkleConfig.cs" />
|
||||
<Compile Include="SparkleWatcher.cs" />
|
||||
<Compile Include="SparkleExtensions.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<ProjectExtensions>
|
||||
|
|
|
@ -64,7 +64,7 @@ namespace SparkleLib {
|
|||
SparkleHelpers.DebugInfo ("ListenerFactory",
|
||||
"Refered to existing listener for " + announce_uri);
|
||||
|
||||
listener.AlsoListenTo (folder_identifier);
|
||||
listener.AlsoListenToBase (folder_identifier);
|
||||
return (SparkleListenerBase) listener;
|
||||
}
|
||||
}
|
||||
|
@ -90,40 +90,52 @@ namespace SparkleLib {
|
|||
// listens for change notifications
|
||||
public abstract class SparkleListenerBase {
|
||||
|
||||
// We've connected to the server
|
||||
public event ConnectedEventHandler Connected;
|
||||
public delegate void ConnectedEventHandler ();
|
||||
|
||||
// We've disconnected from the server
|
||||
public event DisconnectedEventHandler Disconnected;
|
||||
public delegate void DisconnectedEventHandler ();
|
||||
|
||||
// We've been notified about a remote
|
||||
// change by the channel
|
||||
public event AnnouncementEventHandler Announcement;
|
||||
public delegate void AnnouncementEventHandler (SparkleAnnouncement announcement);
|
||||
public event ReceivedEventHandler Received;
|
||||
public delegate void ReceivedEventHandler (SparkleAnnouncement announcement);
|
||||
|
||||
public readonly Uri Server;
|
||||
|
||||
|
||||
public abstract void Connect ();
|
||||
public abstract void Announce (SparkleAnnouncement announcent);
|
||||
public abstract void AlsoListenTo (string folder_identifier);
|
||||
public abstract bool IsConnected { get; }
|
||||
public abstract bool IsConnecting { get; }
|
||||
protected abstract void Announce (SparkleAnnouncement announcent);
|
||||
protected abstract void AlsoListenTo (string folder_identifier);
|
||||
|
||||
|
||||
protected List<string> channels = new List<string> ();
|
||||
protected Dictionary<string,List<SparkleAnnouncement>> recent_announcements = new Dictionary<string, List<SparkleAnnouncement>> ();
|
||||
protected int max_recent_announcements = 10;
|
||||
protected Dictionary<string, SparkleAnnouncement> queue_up = new Dictionary<string, SparkleAnnouncement> ();
|
||||
protected Dictionary<string,SparkleAnnouncement> queue_down = new Dictionary<string, SparkleAnnouncement> ();
|
||||
protected bool is_connecting;
|
||||
protected Uri server;
|
||||
protected Timer reconnect_timer = new Timer { Interval = 60 * 1000, Enabled = true };
|
||||
|
||||
|
||||
private int max_recent_announcements = 10;
|
||||
|
||||
private Dictionary<string, List<SparkleAnnouncement>> recent_announcements =
|
||||
new Dictionary<string, List<SparkleAnnouncement>> ();
|
||||
|
||||
private Dictionary<string, SparkleAnnouncement> queue_up =
|
||||
new Dictionary<string, SparkleAnnouncement> ();
|
||||
|
||||
private Dictionary<string, SparkleAnnouncement> queue_down =
|
||||
new Dictionary<string, SparkleAnnouncement> ();
|
||||
|
||||
private Timer reconnect_timer = new Timer {
|
||||
Interval = 60 * 1000,
|
||||
Enabled = true
|
||||
};
|
||||
|
||||
|
||||
public SparkleListenerBase (Uri server, string folder_identifier)
|
||||
{
|
||||
this.server = server;
|
||||
Server = server;
|
||||
this.channels.Add (folder_identifier);
|
||||
|
||||
this.reconnect_timer.Elapsed += delegate {
|
||||
if (!IsConnected && !this.is_connecting)
|
||||
if (!IsConnected && !IsConnecting)
|
||||
Reconnect ();
|
||||
};
|
||||
|
||||
|
@ -133,29 +145,46 @@ namespace SparkleLib {
|
|||
|
||||
public void AnnounceBase (SparkleAnnouncement announcement)
|
||||
{
|
||||
if (!this.IsRecentAnnounement (announcement)) {
|
||||
if (!IsRecentAnnouncement (announcement)) {
|
||||
if (IsConnected) {
|
||||
SparkleHelpers.DebugInfo ("Listener",
|
||||
"Announcing message " + announcement.Message + " to " + announcement.FolderIdentifier + " on " + this.server);
|
||||
"Announcing message " + announcement.Message + " to " +
|
||||
announcement.FolderIdentifier + " on " + Server);
|
||||
|
||||
Announce (announcement);
|
||||
this.AddRecentAnnouncement (announcement);
|
||||
AddRecentAnnouncement (announcement);
|
||||
|
||||
} else {
|
||||
SparkleHelpers.DebugInfo ("Listener", "Can't send message to " + this.server + ". Queuing message");
|
||||
SparkleHelpers.DebugInfo ("Listener",
|
||||
"Can't send message to " +
|
||||
Server + ". Queuing message");
|
||||
|
||||
this.queue_up [announcement.FolderIdentifier] = announcement;
|
||||
}
|
||||
|
||||
} else {
|
||||
SparkleHelpers.DebugInfo ("Listener",
|
||||
"Already processed message " + announcement.Message + " to " + announcement.FolderIdentifier + " from " + this.server);
|
||||
"Already processed message " + announcement.Message + " to " +
|
||||
announcement.FolderIdentifier + " from " + Server);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void AlsoListenToBase (string channel)
|
||||
{
|
||||
if (!this.channels.Contains (channel) && IsConnected) {
|
||||
SparkleHelpers.DebugInfo ("Listener",
|
||||
"Subscribing to channel " + channel);
|
||||
|
||||
this.channels.Add (channel);
|
||||
AlsoListenTo (channel);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void Reconnect ()
|
||||
{
|
||||
SparkleHelpers.DebugInfo ("Listener", "Trying to reconnect to " + this.server);
|
||||
SparkleHelpers.DebugInfo ("Listener", "Trying to reconnect to " + Server);
|
||||
Connect ();
|
||||
}
|
||||
|
||||
|
@ -168,7 +197,8 @@ namespace SparkleLib {
|
|||
Connected ();
|
||||
|
||||
if (this.queue_up.Count > 0) {
|
||||
SparkleHelpers.DebugInfo ("Listener", "Delivering " + this.queue_up.Count + " queued messages...");
|
||||
SparkleHelpers.DebugInfo ("Listener",
|
||||
"Delivering " + this.queue_up.Count + " queued messages...");
|
||||
|
||||
foreach (KeyValuePair<string, SparkleAnnouncement> item in this.queue_up) {
|
||||
SparkleAnnouncement announcement = item.Value;
|
||||
|
@ -192,34 +222,46 @@ namespace SparkleLib {
|
|||
public void OnAnnouncement (SparkleAnnouncement announcement)
|
||||
{
|
||||
SparkleHelpers.DebugInfo ("Listener",
|
||||
"Got message " + announcement.Message + " from " + announcement.FolderIdentifier + " on " + this.server);
|
||||
"Got message " + announcement.Message + " from " +
|
||||
announcement.FolderIdentifier + " on " + Server);
|
||||
|
||||
if (IsRecentAnnounement(announcement) ){
|
||||
if (IsRecentAnnouncement (announcement)) {
|
||||
SparkleHelpers.DebugInfo ("Listener",
|
||||
"Ignoring previously processed message " + announcement.Message +
|
||||
" from " + announcement.FolderIdentifier + " on " + this.server);
|
||||
" from " + announcement.FolderIdentifier + " on " + Server);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
SparkleHelpers.DebugInfo ("Listener",
|
||||
"Processing message " + announcement.Message + " from " + announcement.FolderIdentifier + " on " + this.server);
|
||||
"Processing message " + announcement.Message + " from " +
|
||||
announcement.FolderIdentifier + " on " + Server);
|
||||
|
||||
AddRecentAnnouncement (announcement);
|
||||
this.queue_down [announcement.FolderIdentifier] = announcement;
|
||||
|
||||
if (Announcement != null)
|
||||
Announcement (announcement);
|
||||
if (Received != null)
|
||||
Received (announcement);
|
||||
}
|
||||
|
||||
|
||||
private bool IsRecentAnnounement (SparkleAnnouncement announcement)
|
||||
public virtual void Dispose ()
|
||||
{
|
||||
if (!HasRecentAnnouncements (announcement.FolderIdentifier)) {
|
||||
this.reconnect_timer.Dispose ();
|
||||
}
|
||||
|
||||
|
||||
private bool IsRecentAnnouncement (SparkleAnnouncement announcement)
|
||||
{
|
||||
if (!this.recent_announcements
|
||||
.ContainsKey (announcement.FolderIdentifier)) {
|
||||
|
||||
return false;
|
||||
|
||||
} else {
|
||||
foreach (SparkleAnnouncement recent_announcement in GetRecentAnnouncements (announcement.FolderIdentifier)) {
|
||||
foreach (SparkleAnnouncement recent_announcement in
|
||||
GetRecentAnnouncements (announcement.FolderIdentifier)) {
|
||||
|
||||
if (recent_announcement.Message.Equals (announcement.Message))
|
||||
return true;
|
||||
}
|
||||
|
@ -240,39 +282,15 @@ namespace SparkleLib {
|
|||
|
||||
private void AddRecentAnnouncement (SparkleAnnouncement announcement)
|
||||
{
|
||||
List<SparkleAnnouncement> recent_announcements = this.GetRecentAnnouncements (announcement.FolderIdentifier);
|
||||
List<SparkleAnnouncement> recent_announcements =
|
||||
GetRecentAnnouncements (announcement.FolderIdentifier);
|
||||
|
||||
if (!IsRecentAnnounement (announcement))
|
||||
if (!IsRecentAnnouncement (announcement))
|
||||
recent_announcements.Add (announcement);
|
||||
|
||||
if (recent_announcements.Count > this.max_recent_announcements)
|
||||
recent_announcements.RemoveRange (0, (recent_announcements.Count - this.max_recent_announcements));
|
||||
}
|
||||
|
||||
|
||||
private bool HasRecentAnnouncements (string folder_identifier)
|
||||
{
|
||||
return this.recent_announcements.ContainsKey (folder_identifier);
|
||||
}
|
||||
|
||||
|
||||
public virtual void Dispose ()
|
||||
{
|
||||
this.reconnect_timer.Dispose ();
|
||||
}
|
||||
|
||||
|
||||
public Uri Server {
|
||||
get {
|
||||
return this.server;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public bool IsConnecting {
|
||||
get {
|
||||
return this.is_connecting;
|
||||
}
|
||||
recent_announcements.RemoveRange (0,
|
||||
(recent_announcements.Count - this.max_recent_announcements));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,30 +28,31 @@ namespace SparkleLib {
|
|||
|
||||
public class SparkleListenerTcp : SparkleListenerBase {
|
||||
|
||||
private Thread thread;
|
||||
|
||||
// these are shared
|
||||
private readonly Object mutex = new Object();
|
||||
private Socket socket;
|
||||
private bool connected;
|
||||
private Object socket_lock = new Object ();
|
||||
private Thread thread;
|
||||
private bool is_connected = false;
|
||||
private bool is_connecting = false;
|
||||
|
||||
|
||||
public SparkleListenerTcp (Uri server, string folder_identifier) :
|
||||
base (server, folder_identifier)
|
||||
{
|
||||
base.channels.Add (folder_identifier);
|
||||
this.connected = false;
|
||||
}
|
||||
|
||||
|
||||
public override bool IsConnected {
|
||||
get {
|
||||
bool result = false;
|
||||
lock (this.socket_lock)
|
||||
return this.is_connected;
|
||||
}
|
||||
}
|
||||
|
||||
lock (this.mutex) {
|
||||
result = this.connected;
|
||||
}
|
||||
|
||||
return result;
|
||||
public override bool IsConnecting {
|
||||
get {
|
||||
lock (this.socket_lock)
|
||||
return this.is_connecting;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -61,21 +62,29 @@ namespace SparkleLib {
|
|||
{
|
||||
SparkleHelpers.DebugInfo ("ListenerTcp", "Connecting to " + Server.Host);
|
||||
|
||||
base.is_connecting = true;
|
||||
this.is_connecting = true;
|
||||
|
||||
this.thread = new Thread (
|
||||
new ThreadStart (delegate {
|
||||
try {
|
||||
// Connect and subscribe to the channel
|
||||
int port = Server.Port;
|
||||
if (port < 0) port = 9999;
|
||||
|
||||
lock (this.mutex) {
|
||||
this.socket = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||
if (port < 0)
|
||||
port = 9999;
|
||||
|
||||
|
||||
lock (this.socket_lock) {
|
||||
this.socket = new Socket (AddressFamily.InterNetwork,
|
||||
SocketType.Stream, ProtocolType.Tcp) {
|
||||
|
||||
ReceiveTimeout = 30 * 1000
|
||||
};
|
||||
|
||||
this.socket.Connect (Server.Host, port);
|
||||
|
||||
base.is_connecting = false;
|
||||
this.connected = true;
|
||||
this.is_connecting = false;
|
||||
this.is_connected = true;
|
||||
|
||||
OnConnected ();
|
||||
|
||||
|
@ -85,6 +94,7 @@ namespace SparkleLib {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
byte [] bytes = new byte [4096];
|
||||
|
||||
// List to the channels, this blocks the thread
|
||||
|
@ -93,20 +103,26 @@ namespace SparkleLib {
|
|||
|
||||
if (bytes_read > 0) {
|
||||
string received = Encoding.UTF8.GetString (bytes);
|
||||
string line = received.Substring (0, received.IndexOf ("\n"));
|
||||
string line = received.Substring (0, received.IndexOf ("\n"));
|
||||
|
||||
if (!line.Contains ("!"))
|
||||
continue;
|
||||
|
||||
string folder_identifier = line.Substring (0, line.IndexOf ("!"));
|
||||
string message = this.CleanMessage (line.Substring (line.IndexOf ("!") + 1));
|
||||
if (!folder_identifier.Equals("debug") &&
|
||||
!String.IsNullOrEmpty(message))
|
||||
string message = CleanMessage (line.Substring (line.IndexOf ("!") + 1));
|
||||
|
||||
if (!folder_identifier.Equals ("debug") &&
|
||||
!String.IsNullOrEmpty (message)) {
|
||||
|
||||
OnAnnouncement (new SparkleAnnouncement (folder_identifier, message));
|
||||
}
|
||||
|
||||
} else {
|
||||
SparkleHelpers.DebugInfo ("ListenerTcp", "Error on socket");
|
||||
|
||||
lock (this.mutex) {
|
||||
lock (this.socket_lock) {
|
||||
this.socket.Close ();
|
||||
this.connected = false;
|
||||
this.is_connected = false;
|
||||
|
||||
OnDisconnected ();
|
||||
}
|
||||
|
@ -117,6 +133,8 @@ namespace SparkleLib {
|
|||
|
||||
} catch (SocketException e) {
|
||||
SparkleHelpers.DebugInfo ("ListenerTcp", "Could not connect to " + Server + ": " + e.Message);
|
||||
this.is_connected = false;
|
||||
this.is_connecting = false;
|
||||
|
||||
OnDisconnected ();
|
||||
}
|
||||
|
@ -127,46 +145,44 @@ namespace SparkleLib {
|
|||
}
|
||||
|
||||
|
||||
public override void AlsoListenTo (string folder_identifier)
|
||||
protected override void AlsoListenTo (string folder_identifier)
|
||||
{
|
||||
string channel = folder_identifier;
|
||||
string to_send = "subscribe " + folder_identifier + "\n";
|
||||
|
||||
if (!base.channels.Contains (channel)) {
|
||||
base.channels.Add (channel);
|
||||
|
||||
if (IsConnected) {
|
||||
SparkleHelpers.DebugInfo ("ListenerTcp", "Subscribing to channel " + channel);
|
||||
|
||||
string to_send = "subscribe " + folder_identifier + "\n";
|
||||
|
||||
try {
|
||||
lock (this.mutex) {
|
||||
this.socket.Send (Encoding.UTF8.GetBytes (to_send));
|
||||
}
|
||||
|
||||
} catch (SocketException e) {
|
||||
SparkleHelpers.DebugInfo ("ListenerTcp", "Could not connect to " + Server + ": " + e.Message);
|
||||
OnDisconnected ();
|
||||
}
|
||||
try {
|
||||
lock (this.socket_lock) {
|
||||
this.socket.Send (Encoding.UTF8.GetBytes (to_send));
|
||||
}
|
||||
|
||||
} catch (SocketException e) {
|
||||
SparkleHelpers.DebugInfo ("ListenerTcp",
|
||||
"Could not connect to " + Server + ": " + e.Message);
|
||||
|
||||
this.is_connected = false;
|
||||
this.is_connecting = false;
|
||||
|
||||
OnDisconnected ();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public override void Announce (SparkleAnnouncement announcement)
|
||||
protected override void Announce (SparkleAnnouncement announcement)
|
||||
{
|
||||
string to_send = "announce " + announcement.FolderIdentifier
|
||||
+ " " + announcement.Message + "\n";
|
||||
|
||||
try {
|
||||
|
||||
lock (this.mutex) {
|
||||
lock (this.socket_lock)
|
||||
this.socket.Send (Encoding.UTF8.GetBytes (to_send));
|
||||
}
|
||||
} catch (SocketException e) {
|
||||
SparkleHelpers.DebugInfo ("ListenerTcp", "Could not connect to " + Server + ": " + e.Message);
|
||||
|
||||
OnDisconnected ();
|
||||
} catch (SocketException e) {
|
||||
SparkleHelpers.DebugInfo ("ListenerTcp",
|
||||
"Could not connect to " + Server + ": " + e.Message);
|
||||
|
||||
this.is_connected = false;
|
||||
this.is_connecting = false;
|
||||
|
||||
OnDisconnected ();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -175,12 +191,16 @@ namespace SparkleLib {
|
|||
{
|
||||
this.thread.Abort ();
|
||||
this.thread.Join ();
|
||||
|
||||
base.Dispose ();
|
||||
}
|
||||
|
||||
private string CleanMessage(string message)
|
||||
|
||||
private string CleanMessage (string message)
|
||||
{
|
||||
return message.Trim ().Replace ("\n", "").Replace ("\0", "");
|
||||
return message.Trim ()
|
||||
.Replace ("\n", "")
|
||||
.Replace ("\0", "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,9 +57,9 @@ namespace SparkleLib {
|
|||
protected bool is_buffering = false;
|
||||
protected bool server_online = true;
|
||||
|
||||
public readonly SparkleBackend Backend;
|
||||
public readonly string LocalPath;
|
||||
public readonly string Name;
|
||||
public readonly Uri Url;
|
||||
|
||||
public abstract bool AnyDifferences { get; }
|
||||
public abstract string Identifier { get; }
|
||||
|
@ -92,11 +92,12 @@ namespace SparkleLib {
|
|||
public event ChangesDetectedEventHandler ChangesDetected;
|
||||
|
||||
|
||||
public SparkleRepoBase (string path, SparkleBackend backend)
|
||||
public SparkleRepoBase (string path)
|
||||
{
|
||||
LocalPath = path;
|
||||
Name = Path.GetFileName (LocalPath);
|
||||
Backend = backend;
|
||||
LocalPath = path;
|
||||
Name = Path.GetFileName (LocalPath);
|
||||
Url = new Uri (SparkleConfig.DefaultConfig.GetUrlForFolder (Name));
|
||||
|
||||
this.poll_interval = this.short_interval;
|
||||
|
||||
SyncStatusChanged += delegate (SyncStatus status) {
|
||||
|
@ -298,7 +299,7 @@ namespace SparkleLib {
|
|||
};
|
||||
|
||||
// Fetch changes when there is a message in the irc channel
|
||||
this.listener.Announcement += delegate (SparkleAnnouncement announcement) {
|
||||
this.listener.Received += delegate (SparkleAnnouncement announcement) {
|
||||
string identifier = Identifier;
|
||||
|
||||
if (announcement.FolderIdentifier.Equals (identifier) &&
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
EXTRA_DIST = \
|
||||
config \
|
||||
AppDelegate.cs \
|
||||
Growl.framework \
|
||||
Growl.plist \
|
||||
|
|
|
@ -46,6 +46,8 @@ namespace SparkleShare {
|
|||
private NSTextField size_label_value;
|
||||
private NSTextField history_label;
|
||||
private NSTextField history_label_value;
|
||||
private NSButton hidden_close_button;
|
||||
|
||||
|
||||
public SparkleEventLog (IntPtr handle) : base (handle) { }
|
||||
|
||||
|
@ -68,6 +70,19 @@ namespace SparkleShare {
|
|||
BackingType = NSBackingStore.Buffered;
|
||||
|
||||
|
||||
this.hidden_close_button = new NSButton () {
|
||||
Frame = new RectangleF (0, 0, 0, 0),
|
||||
KeyEquivalentModifierMask = NSEventModifierMask.CommandKeyMask,
|
||||
KeyEquivalent = "w"
|
||||
};
|
||||
|
||||
this.hidden_close_button.Activated += delegate {
|
||||
PerformClose (this);
|
||||
};
|
||||
|
||||
ContentView.AddSubview (this.hidden_close_button);
|
||||
|
||||
|
||||
this.size_label = new NSTextField () {
|
||||
Alignment = NSTextAlignment.Right,
|
||||
BackgroundColor = NSColor.WindowBackground,
|
||||
|
@ -237,7 +252,7 @@ namespace SparkleShare {
|
|||
|
||||
|
||||
public class SparkleEventsDelegate : NSWindowDelegate {
|
||||
|
||||
|
||||
public override bool WindowShouldClose (NSObject sender)
|
||||
{
|
||||
(sender as SparkleEventLog).OrderOut (this);
|
||||
|
|
|
@ -462,10 +462,9 @@ namespace SparkleShare {
|
|||
|
||||
case PageType.Finished: {
|
||||
|
||||
Header = "Project succesfully added!";
|
||||
Description = "Now you can access the files from " +
|
||||
"‘" + Controller.SyncingFolder + "’ in " +
|
||||
"your SparkleShare folder.";
|
||||
Header = "Project ‘" + Path.GetFileName (Controller.PreviousPath) +
|
||||
"’ succesfully added!";
|
||||
Description = "Access the files from your SparkleShare folder.";
|
||||
|
||||
if (warnings != null) {
|
||||
WarningImage = NSImage.ImageNamed ("NSCaution");
|
||||
|
@ -505,7 +504,7 @@ namespace SparkleShare {
|
|||
};
|
||||
|
||||
OpenFolderButton.Activated += delegate {
|
||||
Program.Controller.OpenSparkleShareFolder (Controller.SyncingFolder);
|
||||
Program.Controller.OpenSparkleShareFolder (Path.GetFileName (Controller.PreviousPath));
|
||||
};
|
||||
|
||||
Buttons.Add (FinishButton);
|
||||
|
|
|
@ -87,7 +87,9 @@ namespace SparkleShare {
|
|||
MakeKeyAndOrderFront (this);
|
||||
|
||||
OrderFrontRegardless ();
|
||||
Program.UI.UpdateDockIconVisibility ();
|
||||
|
||||
if (Program.UI != null)
|
||||
Program.UI.UpdateDockIconVisibility ();
|
||||
}
|
||||
|
||||
|
||||
|
@ -146,7 +148,9 @@ namespace SparkleShare {
|
|||
{
|
||||
base.OrderOut (this);
|
||||
NSApplication.SharedApplication.RemoveWindowsItem (this);
|
||||
Program.UI.UpdateDockIconVisibility ();
|
||||
|
||||
if (Program.UI != null)
|
||||
Program.UI.UpdateDockIconVisibility ();
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<RootNamespace>SparkleShare</RootNamespace>
|
||||
<AssemblyName>SparkleShare</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<ReleaseVersion>0.8.0</ReleaseVersion>
|
||||
<ReleaseVersion>0.8.1</ReleaseVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
|
|
|
@ -16,6 +16,6 @@ Global
|
|||
EndGlobalSection
|
||||
GlobalSection(MonoDevelopProperties) = preSolution
|
||||
StartupItem = SparkleShare.csproj
|
||||
version = 0.8.0
|
||||
version = 0.8.1
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
|
@ -91,6 +91,15 @@ namespace SparkleShare {
|
|||
Menu.Delegate = new SparkleStatusIconMenuDelegate ();
|
||||
}
|
||||
|
||||
Controller.UpdateQuitItemEvent += delegate (bool quit_item_enabled) {
|
||||
InvokeOnMainThread (delegate {
|
||||
if (QuitMenuItem != null) {
|
||||
QuitMenuItem.Enabled = quit_item_enabled;
|
||||
StatusItem.Menu.Update ();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
Controller.UpdateMenuEvent += delegate (IconState state) {
|
||||
InvokeOnMainThread (delegate {
|
||||
using (var a = new NSAutoreleasePool ()) {
|
||||
|
@ -137,6 +146,8 @@ namespace SparkleShare {
|
|||
|
||||
break;
|
||||
}
|
||||
|
||||
StatusItem.Menu.Update ();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
@ -310,8 +321,8 @@ namespace SparkleShare {
|
|||
|
||||
|
||||
QuitMenuItem = new NSMenuItem () {
|
||||
Title = "Quit",
|
||||
Enabled = true
|
||||
Title = "Quit",
|
||||
Enabled = Controller.QuitItemEnabled
|
||||
};
|
||||
|
||||
QuitMenuItem.Activated += delegate {
|
||||
|
|
|
@ -69,6 +69,8 @@ namespace SparkleShare {
|
|||
if (Program.Controller.FirstRun) {
|
||||
Setup = new SparkleSetup ();
|
||||
Setup.Controller.ShowSetupPage ();
|
||||
|
||||
UpdateDockIconVisibility ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ namespace SparkleShare {
|
|||
public SparkleBubblesController ()
|
||||
{
|
||||
Program.Controller.ConflictNotificationRaised += delegate {
|
||||
ShowBubble ("Ouch! Mid-air collision!",
|
||||
ShowBubble ("Conflict detected.",
|
||||
"Don't worry, SparkleShare made a copy of each conflicting file.",
|
||||
null);
|
||||
};
|
||||
|
|
|
@ -262,8 +262,7 @@ namespace SparkleShare {
|
|||
public abstract string EventLogHTML { get; }
|
||||
public abstract string DayEntryHTML { get; }
|
||||
public abstract string EventEntryHTML { get; }
|
||||
|
||||
|
||||
|
||||
public string GetHTMLLog (List<SparkleChangeSet> change_sets)
|
||||
{
|
||||
List <ActivityDay> activity_days = new List <ActivityDay> ();
|
||||
|
@ -456,6 +455,7 @@ namespace SparkleShare {
|
|||
.Replace ("<!-- $event-avatar-url -->", change_set_avatar)
|
||||
.Replace ("<!-- $event-time -->", timestamp)
|
||||
.Replace ("<!-- $event-folder -->", change_set.Folder)
|
||||
.Replace ("<!-- $event-url -->", change_set.Url.ToString ())
|
||||
.Replace ("<!-- $event-revision -->", change_set.Revision)
|
||||
.Replace ("<!-- $event-folder-color -->", AssignColor (change_set.Folder))
|
||||
.Replace ("<!-- $event-comments -->", comments);
|
||||
|
@ -570,16 +570,23 @@ namespace SparkleShare {
|
|||
// Adds a repository to the list of repositories
|
||||
private void AddRepository (string folder_path)
|
||||
{
|
||||
if (folder_path.Equals (SparkleConfig.DefaultConfig.TmpPath))
|
||||
return;
|
||||
SparkleRepoBase repo = null;
|
||||
string folder_name = Path.GetFileName (folder_path);
|
||||
string backend = SparkleConfig.DefaultConfig.GetBackendForFolder (folder_name);
|
||||
|
||||
string folder_name = Path.GetFileName (folder_path);
|
||||
string backend = SparkleConfig.DefaultConfig.GetBackendForFolder (folder_name);
|
||||
try {
|
||||
repo = (SparkleRepoBase) Activator.CreateInstance (
|
||||
Type.GetType ("SparkleLib.SparkleRepo" + backend + ", SparkleLib"),
|
||||
folder_path
|
||||
);
|
||||
|
||||
} catch {
|
||||
SparkleHelpers.DebugInfo ("Controller",
|
||||
"Failed to load \"" + backend + "\" backend for \"" + folder_name + "\"");
|
||||
|
||||
if (backend == null)
|
||||
return;
|
||||
|
||||
SparkleRepoBase repo = new SparkleRepoGit (folder_path, SparkleBackend.DefaultBackend);
|
||||
}
|
||||
|
||||
|
||||
repo.NewChangeSet += delegate (SparkleChangeSet change_set) {
|
||||
|
||||
|
@ -624,6 +631,7 @@ namespace SparkleShare {
|
|||
UpdateState ();
|
||||
};
|
||||
|
||||
|
||||
Repositories.Add (repo);
|
||||
repo.Initialize ();
|
||||
}
|
||||
|
@ -770,6 +778,7 @@ namespace SparkleShare {
|
|||
process.StartInfo.UseShellExecute = false;
|
||||
process.StartInfo.FileName = "ssh-add";
|
||||
process.StartInfo.Arguments = "\"" + key_file_path + "\"";
|
||||
process.StartInfo.CreateNoWindow = true;
|
||||
|
||||
process.Start ();
|
||||
process.WaitForExit ();
|
||||
|
@ -817,7 +826,7 @@ namespace SparkleShare {
|
|||
string key_file_path = Path.Combine (keys_path, key_file_name);
|
||||
|
||||
if (File.Exists (key_file_path)) {
|
||||
SparkleHelpers.DebugInfo ("Config", "Key already exists ('" + key_file_name + "'), " +
|
||||
SparkleHelpers.DebugInfo ("Auth", "Key already exists ('" + key_file_name + "'), " +
|
||||
"leaving it untouched");
|
||||
return;
|
||||
}
|
||||
|
@ -830,10 +839,11 @@ namespace SparkleShare {
|
|||
EnableRaisingEvents = true
|
||||
};
|
||||
|
||||
process.StartInfo.WorkingDirectory = keys_path;
|
||||
process.StartInfo.UseShellExecute = false;
|
||||
process.StartInfo.WorkingDirectory = keys_path;
|
||||
process.StartInfo.UseShellExecute = false;
|
||||
process.StartInfo.RedirectStandardOutput = true;
|
||||
process.StartInfo.FileName = "ssh-keygen";
|
||||
process.StartInfo.FileName = "ssh-keygen";
|
||||
process.StartInfo.CreateNoWindow = true;
|
||||
|
||||
// -t is the crypto type
|
||||
// -P is the password (none)
|
||||
|
@ -843,8 +853,8 @@ namespace SparkleShare {
|
|||
process.Start ();
|
||||
process.WaitForExit ();
|
||||
|
||||
SparkleHelpers.DebugInfo ("Config", "Created private key '" + key_file_name + "'");
|
||||
SparkleHelpers.DebugInfo ("Config", "Created public key '" + key_file_name + ".pub'");
|
||||
SparkleHelpers.DebugInfo ("Auth", "Created private key '" + key_file_name + "'");
|
||||
SparkleHelpers.DebugInfo ("Auth", "Created public key '" + key_file_name + ".pub'");
|
||||
|
||||
// Add some restrictions to what the key can
|
||||
// do when uploaded to the server
|
||||
|
@ -877,7 +887,7 @@ namespace SparkleShare {
|
|||
|
||||
if (!Directory.Exists (avatar_path)) {
|
||||
Directory.CreateDirectory (avatar_path);
|
||||
SparkleHelpers.DebugInfo ("Config", "Created '" + avatar_path + "'");
|
||||
SparkleHelpers.DebugInfo ("Avatar", "Created '" + avatar_path + "'");
|
||||
}
|
||||
|
||||
foreach (string raw_email in emails) {
|
||||
|
@ -923,11 +933,11 @@ namespace SparkleShare {
|
|||
lock (this.avatar_lock)
|
||||
File.WriteAllBytes (avatar_file_path, buffer);
|
||||
|
||||
SparkleHelpers.DebugInfo ("Controller", "Fetched gravatar for " + email);
|
||||
SparkleHelpers.DebugInfo ("Avatar", "Fetched gravatar for " + email);
|
||||
}
|
||||
|
||||
} catch (WebException e) {
|
||||
SparkleHelpers.DebugInfo ("Controller", "Failed fetching gravatar for " + email);
|
||||
SparkleHelpers.DebugInfo ("Avatar", "Failed fetching gravatar for " + email);
|
||||
|
||||
// Stop downloading further avatars if we have no internet access
|
||||
if (e.Status == WebExceptionStatus.Timeout){
|
||||
|
@ -971,7 +981,7 @@ namespace SparkleShare {
|
|||
|
||||
public void FetchFolder (string server, string remote_folder)
|
||||
{
|
||||
server = server.Trim ();
|
||||
server = server.Trim ();
|
||||
remote_folder = remote_folder.Trim ();
|
||||
|
||||
string tmp_path = SparkleConfig.DefaultConfig.TmpPath;
|
||||
|
@ -980,26 +990,42 @@ namespace SparkleShare {
|
|||
File.SetAttributes (tmp_path, File.GetAttributes (tmp_path) | FileAttributes.Hidden);
|
||||
}
|
||||
|
||||
|
||||
// Strip the '.git' from the name
|
||||
string canonical_name = Path.GetFileNameWithoutExtension (remote_folder);
|
||||
string tmp_folder = Path.Combine (tmp_path, canonical_name);
|
||||
string backend = Path.GetExtension (remote_folder);
|
||||
|
||||
string backend = null;
|
||||
if (!string.IsNullOrEmpty (backend)) {
|
||||
backend = backend.Substring (1);
|
||||
|
||||
/* if (remote_folder.EndsWith (".hg")) {
|
||||
remote_folder = remote_folder.Substring (0, (remote_folder.Length - 3));
|
||||
fetcher = new SparkleFetcherHg (server, remote_folder, tmp_folder);
|
||||
backend = "Hg";
|
||||
char [] letters = backend.ToCharArray ();
|
||||
letters [0] = char.ToUpper (letters [0]);
|
||||
backend = new string (letters);
|
||||
|
||||
} else if (remote_folder.EndsWith (".scp")) {
|
||||
remote_folder = remote_folder.Substring (0, (remote_folder.Length - 4));
|
||||
fetcher = new SparkleFetcherScp (server, remote_folder, tmp_folder);
|
||||
backend = "Scp";
|
||||
|
||||
} else {*/
|
||||
this.fetcher = new SparkleFetcherGit (server, remote_folder, tmp_folder);
|
||||
} else {
|
||||
backend = "Git";
|
||||
//}
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
this.fetcher = (SparkleFetcherBase) Activator.CreateInstance (
|
||||
Type.GetType ("SparkleLib.SparkleFetcher" + backend + ", SparkleLib"),
|
||||
server,
|
||||
remote_folder,
|
||||
tmp_folder
|
||||
);
|
||||
|
||||
} catch {
|
||||
SparkleHelpers.DebugInfo ("Controller",
|
||||
"Failed to load \"" + backend + "\" backend for \"" + canonical_name + "\"");
|
||||
|
||||
if (FolderFetchError != null)
|
||||
FolderFetchError (Path.Combine (server, remote_folder));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool target_folder_exists = Directory.Exists (
|
||||
Path.Combine (SparkleConfig.DefaultConfig.FoldersPath, canonical_name));
|
||||
|
@ -1046,7 +1072,6 @@ namespace SparkleShare {
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
this.fetcher.Failed += delegate {
|
||||
if (FolderFetchError != null)
|
||||
FolderFetchError (this.fetcher.RemoteUrl);
|
||||
|
@ -1057,7 +1082,6 @@ namespace SparkleShare {
|
|||
Directory.Delete (tmp_path, true);
|
||||
};
|
||||
|
||||
|
||||
this.fetcher.ProgressChanged += delegate (double percentage) {
|
||||
if (FolderFetching != null)
|
||||
FolderFetching (percentage);
|
||||
|
|
|
@ -174,8 +174,9 @@ namespace SparkleShare {
|
|||
TreeIter iter;
|
||||
this.combo_box.GetActiveIter (out iter);
|
||||
string selection = (string) this.combo_box.Model.GetValue (iter, 0);
|
||||
TreePath path = this.combo_box.Model.GetPath (iter);
|
||||
|
||||
if (selection.Equals (_("All Folders")))
|
||||
if (path.Indices [0] == 0)
|
||||
Controller.SelectedFolder = null;
|
||||
else
|
||||
Controller.SelectedFolder = selection;
|
||||
|
@ -224,7 +225,7 @@ namespace SparkleShare {
|
|||
|
||||
Application.Invoke (delegate {
|
||||
this.spinner.Stop ();
|
||||
this.web_view.LoadString (html, null, null, "file:///");
|
||||
this.web_view.LoadString (html, null, null, "file://");
|
||||
this.content_wrapper.Remove (this.content_wrapper.Child);
|
||||
this.content_wrapper.Add (this.scrolled_window);
|
||||
this.content_wrapper.ShowAll ();
|
||||
|
|
|
@ -66,8 +66,8 @@ namespace SparkleShare {
|
|||
|
||||
// A short delay is less annoying than
|
||||
// a flashing window
|
||||
if (watch.ElapsedMilliseconds < 500)
|
||||
Thread.Sleep (500 - (int) watch.ElapsedMilliseconds);
|
||||
if (watch.ElapsedMilliseconds < 750)
|
||||
Thread.Sleep (750 - (int) watch.ElapsedMilliseconds);
|
||||
|
||||
if (UpdateContentEvent != null)
|
||||
UpdateContentEvent (html);
|
||||
|
|
|
@ -441,20 +441,21 @@ namespace SparkleShare {
|
|||
UrgencyHint = true;
|
||||
|
||||
if (!HasToplevelFocus) {
|
||||
string title = String.Format (_("‘{0}’ has been successfully added"), Controller.SyncingFolder);
|
||||
string title = _("Project successfully added!");
|
||||
string subtext = "";
|
||||
|
||||
SparkleUI.Bubbles.Controller.ShowBubble (title, subtext, null);
|
||||
}
|
||||
|
||||
Header = _("Project successfully added!");
|
||||
Header = _("Project ‘" + System.IO.Path.GetFileName (Controller.PreviousPath) +
|
||||
"’ successfully added!");
|
||||
Description = _("Access the files from your SparkleShare folder.");
|
||||
|
||||
// A button that opens the synced folder
|
||||
Button open_folder_button = new Button (_("Open Folder"));
|
||||
|
||||
open_folder_button.Clicked += delegate {
|
||||
Program.Controller.OpenSparkleShareFolder (Controller.SyncingFolder);
|
||||
Program.Controller.OpenSparkleShareFolder (System.IO.Path.GetFileName (Controller.PreviousPath));
|
||||
};
|
||||
|
||||
Button finish_button = new Button (_("Finish"));
|
||||
|
|
|
@ -33,11 +33,13 @@ namespace SparkleShare {
|
|||
|
||||
public SparkleStatusIconController Controller = new SparkleStatusIconController ();
|
||||
|
||||
// TODO: fix case
|
||||
private Timer Animation;
|
||||
private Gdk.Pixbuf [] AnimationFrames;
|
||||
private int FrameNumber;
|
||||
private string StateText;
|
||||
private Menu Menu;
|
||||
private MenuItem quit_item;
|
||||
|
||||
#if HAVE_APP_INDICATOR
|
||||
private ApplicationIndicator indicator;
|
||||
|
@ -78,58 +80,70 @@ namespace SparkleShare {
|
|||
|
||||
CreateMenu ();
|
||||
|
||||
|
||||
Controller.UpdateQuitItemEvent += delegate (bool quit_item_enabled) {
|
||||
Application.Invoke (delegate {
|
||||
if (this.quit_item != null) {
|
||||
this.quit_item.Sensitive = quit_item_enabled;
|
||||
Menu.ShowAll ();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
Controller.UpdateMenuEvent += delegate (IconState state) {
|
||||
Application.Invoke (delegate {
|
||||
switch (state) {
|
||||
case IconState.Idle:
|
||||
switch (state) {
|
||||
case IconState.Idle:
|
||||
|
||||
Animation.Stop ();
|
||||
Animation.Stop ();
|
||||
|
||||
if (Controller.Folders.Length == 0)
|
||||
StateText = _("Welcome to SparkleShare!");
|
||||
else
|
||||
StateText = _("Up to date") + Controller.FolderSize;
|
||||
if (Controller.Folders.Length == 0)
|
||||
StateText = _("Welcome to SparkleShare!");
|
||||
else
|
||||
StateText = _("Up to date") + Controller.FolderSize;
|
||||
|
||||
#if HAVE_APP_INDICATOR
|
||||
this.indicator.IconName = "process-syncing-sparkleshare-i";
|
||||
#else
|
||||
this.status_icon.Pixbuf = AnimationFrames [0];
|
||||
#endif
|
||||
#if HAVE_APP_INDICATOR
|
||||
this.indicator.IconName = "process-syncing-sparkleshare-i";
|
||||
#else
|
||||
this.status_icon.Pixbuf = AnimationFrames [0];
|
||||
#endif
|
||||
|
||||
UpdateStateText ();
|
||||
CreateMenu ();
|
||||
UpdateStateText ();
|
||||
CreateMenu ();
|
||||
|
||||
break;
|
||||
break;
|
||||
|
||||
case IconState.Syncing:
|
||||
case IconState.Syncing:
|
||||
|
||||
StateText = _("Syncing… ") +
|
||||
Controller.ProgressPercentage + "% " +
|
||||
Controller.ProgressSpeed;
|
||||
StateText = _("Syncing… ") +
|
||||
Controller.ProgressPercentage + "% " +
|
||||
Controller.ProgressSpeed;
|
||||
|
||||
UpdateStateText ();
|
||||
UpdateStateText ();
|
||||
|
||||
if (!Animation.Enabled)
|
||||
Animation.Start ();
|
||||
if (!Animation.Enabled)
|
||||
Animation.Start ();
|
||||
|
||||
break;
|
||||
break;
|
||||
|
||||
case IconState.Error:
|
||||
case IconState.Error:
|
||||
|
||||
Animation.Stop ();
|
||||
Animation.Stop ();
|
||||
|
||||
StateText = _("Not everything is synced");
|
||||
UpdateStateText ();
|
||||
CreateMenu ();
|
||||
|
||||
#if HAVE_APP_INDICATOR
|
||||
this.indicator.IconName = "sparkleshare-syncing-error";
|
||||
#else
|
||||
this.status_icon.Pixbuf = SparkleUIHelpers.GetIcon ("sparkleshare-syncing-error", 24);
|
||||
#endif
|
||||
StateText = _("Not everything is synced");
|
||||
UpdateStateText ();
|
||||
CreateMenu ();
|
||||
|
||||
break;
|
||||
}
|
||||
#if HAVE_APP_INDICATOR
|
||||
this.indicator.IconName = "sparkleshare-syncing-error";
|
||||
#else
|
||||
this.status_icon.Pixbuf = SparkleUIHelpers.GetIcon ("sparkleshare-syncing-error", 24);
|
||||
#endif
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
Menu.ShowAll ();
|
||||
});
|
||||
};
|
||||
}
|
||||
|
@ -311,13 +325,15 @@ namespace SparkleShare {
|
|||
Menu.Add (new SeparatorMenuItem ());
|
||||
|
||||
// A menu item that quits the application
|
||||
MenuItem quit_item = new MenuItem (_("Quit"));
|
||||
this.quit_item = new MenuItem (_("Quit")) {
|
||||
Sensitive = Controller.QuitItemEnabled
|
||||
};
|
||||
|
||||
quit_item.Activated += delegate {
|
||||
this.quit_item.Activated += delegate {
|
||||
Program.Controller.Quit ();
|
||||
};
|
||||
|
||||
Menu.Add (quit_item);
|
||||
Menu.Add (this.quit_item);
|
||||
Menu.ShowAll ();
|
||||
|
||||
#if HAVE_APP_INDICATOR
|
||||
|
|
|
@ -38,6 +38,9 @@ namespace SparkleShare {
|
|||
public event UpdateMenuEventHandler UpdateMenuEvent;
|
||||
public delegate void UpdateMenuEventHandler (IconState state);
|
||||
|
||||
public event UpdateQuitItemEventHandler UpdateQuitItemEvent;
|
||||
public delegate void UpdateQuitItemEventHandler (bool quit_item_enabled);
|
||||
|
||||
public IconState CurrentState = IconState.Idle;
|
||||
|
||||
public string [] Folders {
|
||||
|
@ -76,6 +79,14 @@ namespace SparkleShare {
|
|||
}
|
||||
}
|
||||
|
||||
public bool QuitItemEnabled {
|
||||
get {
|
||||
return (CurrentState != IconState.Syncing &&
|
||||
CurrentState != IconState.SyncingDown &&
|
||||
CurrentState != IconState.SyncingUp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public SparkleStatusIconController ()
|
||||
{
|
||||
|
@ -89,6 +100,9 @@ namespace SparkleShare {
|
|||
if (CurrentState != IconState.Error)
|
||||
CurrentState = IconState.Idle;
|
||||
|
||||
if (UpdateQuitItemEvent != null)
|
||||
UpdateQuitItemEvent (QuitItemEnabled);
|
||||
|
||||
if (UpdateMenuEvent != null)
|
||||
UpdateMenuEvent (CurrentState);
|
||||
};
|
||||
|
@ -97,6 +111,9 @@ namespace SparkleShare {
|
|||
Program.Controller.OnSyncing += delegate {
|
||||
CurrentState = IconState.Syncing;
|
||||
|
||||
if (UpdateQuitItemEvent != null)
|
||||
UpdateQuitItemEvent (QuitItemEnabled);
|
||||
|
||||
if (UpdateMenuEvent != null)
|
||||
UpdateMenuEvent (IconState.Syncing);
|
||||
};
|
||||
|
@ -105,6 +122,9 @@ namespace SparkleShare {
|
|||
Program.Controller.OnError += delegate {
|
||||
CurrentState = IconState.Error;
|
||||
|
||||
if (UpdateQuitItemEvent != null)
|
||||
UpdateQuitItemEvent (QuitItemEnabled);
|
||||
|
||||
if (UpdateMenuEvent != null)
|
||||
UpdateMenuEvent (IconState.Error);
|
||||
};
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
if [[ $UID -eq 0 ]]; then
|
||||
echo "Cannot run as root. Things would go utterly wrong."
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
dnl Process this file with autoconf to produce a configure script.
|
||||
m4_define([sparkleshare_version],
|
||||
[0.8.0])
|
||||
[0.8.1])
|
||||
|
||||
m4_define([sparkleshare_asm_version],
|
||||
[0.8.0])
|
||||
[0.8.1])
|
||||
|
||||
AC_PREREQ([2.54])
|
||||
AC_INIT([SparkleShare], sparkleshare_version)
|
||||
AM_INIT_AUTOMAKE([1.11 dist-bzip2 dist-zip foreign tar-ustar])
|
||||
AM_INIT_AUTOMAKE([1.11 dist-bzip2 dist-zip foreign tar-pax])
|
||||
AM_MAINTAINER_MODE
|
||||
|
||||
dnl Export Version Info
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<div class='event-entry' style='background-image: url("<!-- $event-avatar-url -->");'>
|
||||
<div class='event-user-name'><!-- $event-user-name --></div>
|
||||
<div class='event-folder'><!-- $event-folder --></div>
|
||||
<div class='event-folder'><!-- $event-folder --><span><!-- $event-url --></span></div>
|
||||
|
||||
<!-- $event-entry-content -->
|
||||
|
||||
|
|
|
@ -88,23 +88,23 @@
|
|||
|
||||
<style>
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: #fff;
|
||||
color: <!-- $body-color -->;
|
||||
font-size: <!-- $body-font-size -->;
|
||||
font-family: <!-- $body-font-family -->;
|
||||
margin: 0;
|
||||
padding: 18px;
|
||||
background-color: #fafafa;
|
||||
color: <!-- $body-color -->;
|
||||
font-size: <!-- $body-font-size -->;
|
||||
font-family: <!-- $body-font-family -->;
|
||||
margin: 0;
|
||||
padding: 18px;
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
|
||||
small {
|
||||
font-size: <!-- $small-font-size -->;
|
||||
color: <!-- $secondary-font-color -->;
|
||||
color: <!-- $secondary-font-color -->;
|
||||
}
|
||||
|
||||
.moved-arrow {
|
||||
|
@ -152,23 +152,45 @@
|
|||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
||||
.event-folder {
|
||||
float: right;
|
||||
color: <!-- $secondary-font-color -->;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.event-folder span {
|
||||
display: none
|
||||
}
|
||||
|
||||
.event-folder:hover span {
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
right: 0;
|
||||
background-color: rgba(20, 20, 20, 0.8);
|
||||
color: #fafafa;
|
||||
padding: 7px 12px;
|
||||
border-radius: 5px;
|
||||
font-family: sans-serif;
|
||||
font-size: 12px;
|
||||
float:right;
|
||||
}
|
||||
|
||||
|
||||
.event-entry {
|
||||
margin-bottom: 24px;
|
||||
padding-bottom: 24px;
|
||||
border-bottom: 1px <!-- $secondary-font-color --> solid;
|
||||
width: 95%;
|
||||
border-bottom: 1px #ddd solid;
|
||||
width: 99%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
padding-left: 72px;
|
||||
padding-right: 12px;
|
||||
background-repeat: no-repeat;
|
||||
background-position: 12px top;
|
||||
display: block;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.action {
|
||||
|
@ -209,16 +231,16 @@
|
|||
|
||||
dd {
|
||||
display: none;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
width: 90%;
|
||||
padding: 0;
|
||||
padding-top: 2px;
|
||||
padding-bottom: 2px;
|
||||
padding-left: 20px;
|
||||
margin: 0;
|
||||
margin-bottom: 1px;
|
||||
background-repeat: no-repeat;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
width: 90%;
|
||||
padding: 0;
|
||||
padding-top: 2px;
|
||||
padding-bottom: 2px;
|
||||
padding-left: 20px;
|
||||
margin: 0;
|
||||
margin-bottom: 1px;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center left;
|
||||
}
|
||||
|
||||
|
@ -252,17 +274,17 @@
|
|||
position: relative;
|
||||
top: 0;
|
||||
left: 0;
|
||||
float: left;
|
||||
margin-right: 12px;
|
||||
width: 48px;
|
||||
background-image: url('<!-- $no-buddy-icon-background-image -->');
|
||||
background-repeat: no-repeat;
|
||||
float: left;
|
||||
margin-right: 12px;
|
||||
width: 48px;
|
||||
background-image: url('<!-- $no-buddy-icon-background-image -->');
|
||||
background-repeat: no-repeat;
|
||||
background-position: top center;
|
||||
}
|
||||
|
||||
.buddy-icon {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
}
|
||||
|
||||
.comments {
|
||||
|
@ -295,23 +317,23 @@
|
|||
}
|
||||
|
||||
.comment-textarea {
|
||||
box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
width: 100%;
|
||||
height: 3em;
|
||||
padding-bottom: 6px;
|
||||
width: 100%;
|
||||
height: 3em;
|
||||
padding-bottom: 6px;
|
||||
}
|
||||
|
||||
.comments-section {
|
||||
box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
width: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.comments-wrapper {
|
||||
box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
width: 100%;
|
||||
width: 100%;
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue