/SparkleShare/Mac/SparkleController.cs

http://github.com/hbons/SparkleShare · C# · 241 lines · 157 code · 62 blank · 22 comment · 10 complexity · 7bc6b94b06d4d53d168dba5d2525fbd1 MD5 · raw file

  1. // SparkleShare, a collaboration and sharing tool.
  2. // Copyright (C) 2010 Hylke Bons <hylkebons@gmail.com>
  3. //
  4. // This program is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License
  15. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. using System;
  17. using System.Diagnostics;
  18. using System.IO;
  19. using System.Threading;
  20. using MonoMac.Foundation;
  21. using MonoMac.AppKit;
  22. using Mono.Unix.Native;
  23. using SparkleLib;
  24. using System.Collections.Generic;
  25. namespace SparkleShare {
  26. public class SparkleController : SparkleControllerBase {
  27. public override string PluginsPath {
  28. get {
  29. return Path.Combine (NSBundle.MainBundle.ResourcePath, "Plugins");
  30. }
  31. }
  32. // We have to use our own custom made folder watcher, as
  33. // System.IO.FileSystemWatcher fails watching subfolders on Mac
  34. private SparkleMacWatcher watcher;
  35. public SparkleController () : base ()
  36. {
  37. NSApplication.Init ();
  38. // Let's use the bundled git first
  39. SparkleLib.Git.SparkleGit.GitPath = Path.Combine (NSBundle.MainBundle.ResourcePath, "git", "libexec", "git-core", "git");
  40. SparkleLib.Git.SparkleGit.ExecPath = Path.Combine (NSBundle.MainBundle.ResourcePath, "git", "libexec", "git-core");
  41. }
  42. public override void Initialize ()
  43. {
  44. base.Initialize ();
  45. SparkleRepoBase.UseCustomWatcher = true;
  46. this.watcher = new SparkleMacWatcher (Program.Controller.FoldersPath);
  47. this.watcher.Changed += OnFilesChanged;
  48. }
  49. private void OnFilesChanged (List<string> changed_files_in_basedir)
  50. {
  51. List<string> triggered_repos = new List<string> ();
  52. foreach (string file in changed_files_in_basedir) {
  53. string repo_name;
  54. int path_sep_index = file.IndexOf (Path.DirectorySeparatorChar);
  55. if (path_sep_index >= 0)
  56. repo_name = file.Substring (0, path_sep_index);
  57. else
  58. repo_name = file;
  59. repo_name = Path.GetFileNameWithoutExtension (repo_name);
  60. SparkleRepoBase repo = GetRepoByName (repo_name);
  61. if (repo == null)
  62. continue;
  63. if (!triggered_repos.Contains (repo_name)) {
  64. triggered_repos.Add (repo_name);
  65. FileActivityTask task = MacActivityTask (repo,
  66. new FileSystemEventArgs (WatcherChangeTypes.Changed, file, "Unknown"));
  67. task ();
  68. }
  69. }
  70. }
  71. private delegate void FileActivityTask ();
  72. private FileActivityTask MacActivityTask (SparkleRepoBase repo, FileSystemEventArgs fse_args) {
  73. return delegate { new Thread (() => { repo.OnFileActivity (fse_args); }).Start (); };
  74. }
  75. public override void CreateStartupItem ()
  76. {
  77. // There aren't any bindings in MonoMac to support this yet, so
  78. // we call out to an applescript to do the job
  79. Process process = new Process ();
  80. process.StartInfo.FileName = "osascript";
  81. process.StartInfo.UseShellExecute = false;
  82. process.StartInfo.Arguments = "-e 'tell application \"System Events\" to " +
  83. "make login item at end with properties {path:\"" + NSBundle.MainBundle.BundlePath + "\", hidden:false}'";
  84. process.Start ();
  85. process.WaitForExit ();
  86. SparkleLogger.LogInfo ("Controller", "Added " + NSBundle.MainBundle.BundlePath + " to login items");
  87. }
  88. public override void InstallProtocolHandler ()
  89. {
  90. // We ship SparkleShareInviteHandler.app in the bundle
  91. }
  92. public override void AddToBookmarks ()
  93. {
  94. // TODO
  95. }
  96. public override bool CreateSparkleShareFolder ()
  97. {
  98. if (!Directory.Exists (Program.Controller.FoldersPath)) {
  99. Directory.CreateDirectory (Program.Controller.FoldersPath);
  100. if (Environment.OSVersion.Version.Major >= 14) {
  101. NSWorkspace.SharedWorkspace.SetIconforFile (
  102. NSImage.ImageNamed ("sparkleshare-folder-yosemite.icns"),
  103. Program.Controller.FoldersPath, 0);
  104. } else {
  105. NSWorkspace.SharedWorkspace.SetIconforFile (
  106. NSImage.ImageNamed ("sparkleshare-folder.icns"),
  107. Program.Controller.FoldersPath, 0);
  108. }
  109. Syscall.chmod (Program.Controller.FoldersPath, (FilePermissions) 448); // 448 -> 700
  110. return true;
  111. }
  112. return false;
  113. }
  114. public override void OpenFolder (string path)
  115. {
  116. path = Uri.UnescapeDataString (path);
  117. NSWorkspace.SharedWorkspace.OpenFile (path);
  118. }
  119. public override void OpenFile (string path)
  120. {
  121. path = Uri.UnescapeDataString (path);
  122. NSWorkspace.SharedWorkspace.OpenFile (path);
  123. }
  124. public override void OpenWebsite (string url)
  125. {
  126. NSWorkspace.SharedWorkspace.OpenUrl (new NSUrl (url));
  127. }
  128. public override void CopyToClipboard (string text)
  129. {
  130. NSPasteboard.GeneralPasteboard.ClearContents ();
  131. NSPasteboard.GeneralPasteboard.SetStringForType (text, "NSStringPboardType");
  132. }
  133. private string event_log_html;
  134. public override string EventLogHTML
  135. {
  136. get {
  137. if (string.IsNullOrEmpty (this.event_log_html)) {
  138. string html_file_path = Path.Combine (NSBundle.MainBundle.ResourcePath, "HTML", "event-log.html");
  139. string jquery_file_path = Path.Combine (NSBundle.MainBundle.ResourcePath, "HTML", "jquery.js");
  140. string html = File.ReadAllText (html_file_path);
  141. string jquery = File.ReadAllText (jquery_file_path);
  142. this.event_log_html = html.Replace ("<!-- $jquery -->", jquery);
  143. }
  144. return this.event_log_html;
  145. }
  146. }
  147. private string day_entry_html;
  148. public override string DayEntryHTML
  149. {
  150. get {
  151. if (string.IsNullOrEmpty (this.day_entry_html)) {
  152. string html_file_path = Path.Combine (NSBundle.MainBundle.ResourcePath, "HTML", "day-entry.html");
  153. this.day_entry_html = File.ReadAllText (html_file_path);
  154. }
  155. return this.day_entry_html;
  156. }
  157. }
  158. private string event_entry_html;
  159. public override string EventEntryHTML
  160. {
  161. get {
  162. if (string.IsNullOrEmpty (this.event_entry_html)) {
  163. string html_file_path = Path.Combine (NSBundle.MainBundle.ResourcePath, "HTML", "event-entry.html");
  164. this.event_entry_html = File.ReadAllText (html_file_path);
  165. }
  166. return this.event_entry_html;
  167. }
  168. }
  169. public delegate void Code ();
  170. private NSObject obj = new NSObject ();
  171. public void Invoke (Code code)
  172. {
  173. using (var a = new NSAutoreleasePool ())
  174. {
  175. obj.InvokeOnMainThread (() => code ());
  176. }
  177. }
  178. }
  179. }