/SparkleShare/Mac/SparkleController.cs
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 17 18using System; 19using System.Diagnostics; 20using System.IO; 21using System.Threading; 22 23using MonoMac.Foundation; 24using MonoMac.AppKit; 25 26using Mono.Unix.Native; 27using SparkleLib; 28using System.Collections.Generic; 29 30namespace SparkleShare { 31 32 public class SparkleController : SparkleControllerBase { 33 34 public override string PluginsPath { 35 get { 36 return Path.Combine (NSBundle.MainBundle.ResourcePath, "Plugins"); 37 } 38 } 39 40 // We have to use our own custom made folder watcher, as 41 // System.IO.FileSystemWatcher fails watching subfolders on Mac 42 private SparkleMacWatcher watcher; 43 44 45 public SparkleController () : base () 46 { 47 NSApplication.Init (); 48 49 // Let's use the bundled git first 50 SparkleLib.Git.SparkleGit.GitPath = Path.Combine (NSBundle.MainBundle.ResourcePath, "git", "libexec", "git-core", "git"); 51 SparkleLib.Git.SparkleGit.ExecPath = Path.Combine (NSBundle.MainBundle.ResourcePath, "git", "libexec", "git-core"); 52 } 53 54 55 public override void Initialize () 56 { 57 base.Initialize (); 58 59 SparkleRepoBase.UseCustomWatcher = true; 60 this.watcher = new SparkleMacWatcher (Program.Controller.FoldersPath); 61 62 this.watcher.Changed += OnFilesChanged; 63 } 64 65 66 private void OnFilesChanged (List<string> changed_files_in_basedir) 67 { 68 List<string> triggered_repos = new List<string> (); 69 70 foreach (string file in changed_files_in_basedir) { 71 string repo_name; 72 int path_sep_index = file.IndexOf (Path.DirectorySeparatorChar); 73 74 if (path_sep_index >= 0) 75 repo_name = file.Substring (0, path_sep_index); 76 else 77 repo_name = file; 78 79 repo_name = Path.GetFileNameWithoutExtension (repo_name); 80 SparkleRepoBase repo = GetRepoByName (repo_name); 81 82 if (repo == null) 83 continue; 84 85 if (!triggered_repos.Contains (repo_name)) { 86 triggered_repos.Add (repo_name); 87 88 FileActivityTask task = MacActivityTask (repo, 89 new FileSystemEventArgs (WatcherChangeTypes.Changed, file, "Unknown")); 90 91 task (); 92 } 93 94 } 95 } 96 97 private delegate void FileActivityTask (); 98 99 private FileActivityTask MacActivityTask (SparkleRepoBase repo, FileSystemEventArgs fse_args) { 100 return delegate { new Thread (() => { repo.OnFileActivity (fse_args); }).Start (); }; 101 } 102 103 104 public override void CreateStartupItem () 105 { 106 // There aren't any bindings in MonoMac to support this yet, so 107 // we call out to an applescript to do the job 108 Process process = new Process (); 109 process.StartInfo.FileName = "osascript"; 110 process.StartInfo.UseShellExecute = false; 111 process.StartInfo.Arguments = "-e 'tell application \"System Events\" to " + 112 "make login item at end with properties {path:\"" + NSBundle.MainBundle.BundlePath + "\", hidden:false}'"; 113 114 process.Start (); 115 process.WaitForExit (); 116 117 SparkleLogger.LogInfo ("Controller", "Added " + NSBundle.MainBundle.BundlePath + " to login items"); 118 } 119 120 121 public override void InstallProtocolHandler () 122 { 123 // We ship SparkleShareInviteHandler.app in the bundle 124 } 125 126 127 public override void AddToBookmarks () 128 { 129 // TODO 130 } 131 132 133 public override bool CreateSparkleShareFolder () 134 { 135 if (!Directory.Exists (Program.Controller.FoldersPath)) { 136 Directory.CreateDirectory (Program.Controller.FoldersPath); 137 138 if (Environment.OSVersion.Version.Major >= 14) { 139 NSWorkspace.SharedWorkspace.SetIconforFile ( 140 NSImage.ImageNamed ("sparkleshare-folder-yosemite.icns"), 141 Program.Controller.FoldersPath, 0); 142 143 } else { 144 NSWorkspace.SharedWorkspace.SetIconforFile ( 145 NSImage.ImageNamed ("sparkleshare-folder.icns"), 146 Program.Controller.FoldersPath, 0); 147 } 148 149 Syscall.chmod (Program.Controller.FoldersPath, (FilePermissions) 448); // 448 -> 700 150 151 return true; 152 } 153 154 return false; 155 } 156 157 158 public override void OpenFolder (string path) 159 { 160 path = Uri.UnescapeDataString (path); 161 NSWorkspace.SharedWorkspace.OpenFile (path); 162 } 163 164 165 public override void OpenFile (string path) 166 { 167 path = Uri.UnescapeDataString (path); 168 NSWorkspace.SharedWorkspace.OpenFile (path); 169 } 170 171 172 public override void OpenWebsite (string url) 173 { 174 NSWorkspace.SharedWorkspace.OpenUrl (new NSUrl (url)); 175 } 176 177 178 public override void CopyToClipboard (string text) 179 { 180 NSPasteboard.GeneralPasteboard.ClearContents (); 181 NSPasteboard.GeneralPasteboard.SetStringForType (text, "NSStringPboardType"); 182 } 183 184 185 private string event_log_html; 186 public override string EventLogHTML 187 { 188 get { 189 if (string.IsNullOrEmpty (this.event_log_html)) { 190 string html_file_path = Path.Combine (NSBundle.MainBundle.ResourcePath, "HTML", "event-log.html"); 191 string jquery_file_path = Path.Combine (NSBundle.MainBundle.ResourcePath, "HTML", "jquery.js"); 192 string html = File.ReadAllText (html_file_path); 193 string jquery = File.ReadAllText (jquery_file_path); 194 this.event_log_html = html.Replace ("<!-- $jquery -->", jquery); 195 } 196 197 return this.event_log_html; 198 } 199 } 200 201 202 private string day_entry_html; 203 public override string DayEntryHTML 204 { 205 get { 206 if (string.IsNullOrEmpty (this.day_entry_html)) { 207 string html_file_path = Path.Combine (NSBundle.MainBundle.ResourcePath, "HTML", "day-entry.html"); 208 this.day_entry_html = File.ReadAllText (html_file_path); 209 } 210 211 return this.day_entry_html; 212 } 213 } 214 215 216 private string event_entry_html; 217 public override string EventEntryHTML 218 { 219 get { 220 if (string.IsNullOrEmpty (this.event_entry_html)) { 221 string html_file_path = Path.Combine (NSBundle.MainBundle.ResourcePath, "HTML", "event-entry.html"); 222 this.event_entry_html = File.ReadAllText (html_file_path); 223 } 224 225 return this.event_entry_html; 226 } 227 } 228 229 230 public delegate void Code (); 231 private NSObject obj = new NSObject (); 232 233 public void Invoke (Code code) 234 { 235 using (var a = new NSAutoreleasePool ()) 236 { 237 obj.InvokeOnMainThread (() => code ()); 238 } 239 } 240 } 241}