public ServerEvents(WebShellFolderServer server) { if (server == null) { throw new ArgumentNullException(nameof(server)); } Server = server; // build SignalR connection _connection = new HubConnectionBuilder() .WithUrl(WebApi.RootUrl + "events") .WithAutomaticReconnect() .Build(); _connection.Closed += async(error) => { // restart await Task.Delay(new Random().Next(0, 5) * 1000).ConfigureAwait(false); await _connection.StartAsync().ConfigureAwait(false); }; // must match server's IFileSystemEvents method signature // Change(Guid id, Guid itemId, Guid parentId, WatcherChangeTypes types, DateTime creationTimeUtc, string oldName); _connection.On <Guid, Guid, Guid, WatcherChangeTypes, DateTime, string, Guid?>("Change", (id, itemId, parentId, type, creationTimeUtc, oldName, oldParentId) => { // invalidate the cache using server information // note we don't force files update. this will be done when the use opens it server.Log(System.Diagnostics.TraceLevel.Warning, "UpdateCache id: " + id + " itemId: " + itemId + " parentId: " + parentId + " type: " + type + " oldName: " + oldName + " oldParentId: " + oldParentId); WebApi.UpdateCache(itemId, parentId, type); // tell the Shell that this pidl has changed // which will eventually call back in views that may be opened to our folders var item = server.GetItem(itemId); if (item != null) { if (item.IsFolder) { switch (type) { case WatcherChangeTypes.Changed: ShellUtilities.ChangeNotify(SHCNE.SHCNE_UPDATEDIR, 0, item.IdList); break; case WatcherChangeTypes.Created: ShellUtilities.ChangeNotify(SHCNE.SHCNE_MKDIR, 0, item.IdList); break; case WatcherChangeTypes.Deleted: ShellUtilities.ChangeNotify(SHCNE.SHCNE_RMDIR, 0, item.IdList); break; case WatcherChangeTypes.Renamed: ShellUtilities.ChangeNotify(SHCNE.SHCNE_RENAMEFOLDER, 0, item.IdList); break; } } else { switch (type) { case WatcherChangeTypes.Changed: ShellUtilities.ChangeNotify(SHCNE.SHCNE_UPDATEITEM, 0, item.IdList); break; case WatcherChangeTypes.Created: ShellUtilities.ChangeNotify(SHCNE.SHCNE_CREATE, 0, item.IdList); break; case WatcherChangeTypes.Deleted: ShellUtilities.ChangeNotify(SHCNE.SHCNE_DELETE, 0, item.IdList); break; case WatcherChangeTypes.Renamed: ShellUtilities.ChangeNotify(SHCNE.SHCNE_RENAMEITEM, 0, item.IdList); break; } } } item = server.GetItem(parentId); if (item != null) { ShellUtilities.ChangeNotify(SHCNE.SHCNE_UPDATEDIR, 0, item.IdList); } }); _connection.StartAsync(); }
private void OnWatcherEvent(object sender, LocalFileSystemWatcherEventArgs e) { // basic checks if (!IOUtilities.PathIsChildOrEqual(WebApi.LocalDirectory.FullName, e.Path)) { return; } // skip some well known files (office, etc.) if (!ConsiderForRemote(Path.GetFileName(e.Path))) { return; } var isDir = IOUtilities.PathIsDirectory(e.Path); Server.Log(TraceLevel.Verbose, "Action:" + e.Action + " Get remote item for local: " + e.Path); var item = Server.GetRemoteItem(e.Path); if (item != null) { if (e.Action == WatcherChangeTypes.Deleted) { // a delete in a local file doesn't mean a delete in the server ShellUtilities.ChangeNotify(SHCNE.SHCNE_UPDATEITEM, 0, item.IdList); } else if (e.Action == WatcherChangeTypes.Changed) { ShellUtilities.ChangeNotify(isDir ? SHCNE.SHCNE_UPDATEDIR : SHCNE.SHCNE_UPDATEITEM, 0, item.IdList); if (!isDir) { SynchronizeFile(e.Path); } } else if (e.Action == WatcherChangeTypes.Renamed) { ShellUtilities.ChangeNotify(isDir ? SHCNE.SHCNE_RENAMEFOLDER : SHCNE.SHCNE_RENAMEITEM, 0, item.IdList); if (!isDir) { SynchronizeFile(e.Path); } } // else create do nothing } else // try parent { var parentPath = Path.GetDirectoryName(e.Path); item = Server.GetRemoteItem(parentPath); if (item != null) { // new item creation in the local directories? could come from the "New ..." menu in virtual folder's context // we don't use created just changed if (e.Action != WatcherChangeTypes.Deleted && e.Action != WatcherChangeTypes.Created && item is IObjectWithApiItem owa) { var atts = IOUtilities.PathGetAttributes(e.Path); if (atts.HasValue && !atts.Value.HasFlag(FileAttributes.Directory) && !atts.Value.HasFlag(FileAttributes.Hidden) && !atts.Value.HasFlag(FileAttributes.System)) { WebApi.CreateAsync(owa.ApiItem.Id, e.Path, null, atts.Value); } } ShellUtilities.ChangeNotify(SHCNE.SHCNE_UPDATEDIR, 0, item.IdList); } } }
private void OnChangeNotifierNotify(object sender, ChangeNotifyEventArgs e) { // get our equivalent item if (e.FileSystemPath1 != null) { // is it really about us? if (e.FileSystemPath1.StartsWith(RootPath, StringComparison.OrdinalIgnoreCase)) { // get relative path and normalize a bit var relPath1 = IOUtilities.PathRemoveStartSlash(e.FileSystemPath1.Substring(RootPath.Length)); // build a PIDL corresponding to our namespace from a file system path (not in our namespace) // and get/update the corresponding ShellItem from the cache, if it exists. ShellItem item; ShellItemIdList idl; switch (e.Event) { case SHCNE.SHCNE_DELETE: case SHCNE.SHCNE_RMDIR: idl = ShellItemIdList.FromFileSystem(RootPhysical.IdList, relPath1, e.Event == SHCNE.SHCNE_RMDIR ? FileAttributes.Directory : FileAttributes.Normal); item = Server.GetFromCache(idl); if (item != null) { item.NotifyDelete(); Server.RemoveFromCache(item.IdList); } break; case SHCNE.SHCNE_RENAMEFOLDER: case SHCNE.SHCNE_RENAMEITEM: idl = ShellItemIdList.FromFileSystem(RootPhysical.IdList, relPath1, e.Event == SHCNE.SHCNE_RENAMEFOLDER ? FileAttributes.Directory : FileAttributes.Normal); item = Server.GetFromCache(idl); if (item != null) { Server.RemoveFromCache(item.IdList); } // 1 is previous, 2 is new var relPath2 = IOUtilities.PathRemoveStartSlash(e.FileSystemPath2.Substring(RootPath.Length)); var idl2 = ShellItemIdList.FromFileSystem(RootPhysical.IdList, relPath2, e.Event == SHCNE.SHCNE_RENAMEFOLDER ? FileAttributes.Directory : FileAttributes.Normal); ShellUtilities.ChangeNotify(e.Event, 0, idl, idl2); break; case SHCNE.SHCNE_UPDATEITEM: case SHCNE.SHCNE_UPDATEDIR: idl = ShellItemIdList.FromFileSystem(RootPhysical.IdList, relPath1, e.Event == SHCNE.SHCNE_UPDATEDIR ? FileAttributes.Directory : FileAttributes.Normal); item = Server.GetFromCache(idl); if (item != null) { item.NotifyUpdate(); } break; case SHCNE.SHCNE_CREATE: case SHCNE.SHCNE_MKDIR: idl = ShellItemIdList.FromFileSystem(RootPhysical.IdList, relPath1, e.Event == SHCNE.SHCNE_MKDIR ? FileAttributes.Directory : FileAttributes.Normal); item = Server.GetFromCache(idl); if (item != null) // item should in general be null (creation) { item.NotifyCreate(); } else { ShellUtilities.ChangeNotify(e.Event, 0, idl); } break; } } } }