Skip to content

Commit

Permalink
Recognize and use folder labels where appropriate
Browse files Browse the repository at this point in the history
Fixes #284
  • Loading branch information
canton7 committed Jun 22, 2016
1 parent 28c9d98 commit 6f5325d
Show file tree
Hide file tree
Showing 13 changed files with 109 additions and 30 deletions.
10 changes: 5 additions & 5 deletions src/SyncTrayzor/NotifyIcon/NotifyIconViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public NotifyIconViewModel(
this.SyncthingState = this.syncthingManager.State;

this.syncthingManager.TotalConnectionStatsChanged += this.TotalConnectionStatsChanged;
this.syncthingManager.DataLoaded += this.DataLoaded;
this.syncthingManager.Folders.FoldersChanged += this.FoldersChanged;
this.syncthingManager.Folders.SyncStateChanged += this.FolderSyncStateChanged;


Expand All @@ -89,11 +89,11 @@ private void TotalConnectionStatsChanged(object sender, ConnectionStatsChangedEv
}
}

private void DataLoaded(object sender, EventArgs e)
private void FoldersChanged(object sender, EventArgs e)
{
this.Folders = new BindableCollection<FolderViewModel>(this.syncthingManager.Folders.FetchAll()
.Select(x => new FolderViewModel(x, this.processStartProvider))
.OrderBy(x => x.FolderId));
.OrderBy(x => x.FolderLabel));
}

private void FolderSyncStateChanged(object sender, FolderSyncStateChangedEventArgs e)
Expand Down Expand Up @@ -173,8 +173,8 @@ public void Dispose()
this.syncthingManager.StateChanged -= this.StateChanged;

this.syncthingManager.TotalConnectionStatsChanged -= this.TotalConnectionStatsChanged;
this.syncthingManager.DataLoaded -= this.DataLoaded;
this.syncthingManager.Folders.SyncStateChanged -= this.FolderSyncStateChanged;
this.syncthingManager.Folders.FoldersChanged -= this.FoldersChanged;

this.alertsManager.AlertsStateChanged -= this.AlertsStateChanged;

Expand All @@ -188,7 +188,7 @@ public class FolderViewModel : ICommand
private readonly Folder folder;
private readonly IProcessStartProvider processStartProvider;

public string FolderId => this.folder.FolderId;
public string FolderLabel => this.folder.Label;

public FolderViewModel(Folder folder, IProcessStartProvider processStartProvider)
{
Expand Down
2 changes: 1 addition & 1 deletion src/SyncTrayzor/NotifyIcon/TaskbarIconResources.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@
Visibility="{Binding Folders, Converter={x:Static s:BoolToVisibilityConverter.Instance}}">
<MenuItem.ItemContainerStyle>
<Style TargetType="MenuItem">
<Setter Property="Header" Value="{Binding FolderId, Converter={x:Static xaml:RemoveMnemonicsConverter.Instance}}"/>
<Setter Property="Header" Value="{Binding FolderLabel, Converter={x:Static xaml:RemoveMnemonicsConverter.Instance}}"/>
<Setter Property="Command" Value="{Binding}"/>
</Style>
</MenuItem.ItemContainerStyle>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<Window.Resources>
<CollectionViewSource x:Key="ConflictsItemsSource" Source="{Binding Conflicts}">
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="FolderId"/>
<PropertyGroupDescription PropertyName="FolderLabel"/>
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
<Style x:Key="SectionBorderStyle" TargetType="Border">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ private async void Load()
{
await this.conflictFileManager.FindConflicts(folder.Path)
.ObserveOnDispatcher(DispatcherPriority.Background)
.ForEachAsync(conflict => this.Conflicts.Add(new ConflictViewModel(conflict, folder.FolderId)), ct);
.ForEachAsync(conflict => this.Conflicts.Add(new ConflictViewModel(conflict, folder.Label)), ct);
}
catch (OperationCanceledException) { }
}
Expand Down
4 changes: 2 additions & 2 deletions src/SyncTrayzor/Pages/ConflictResolution/ConflictViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public class ConflictViewModel : PropertyChangedBase

public string InnerFolder => Path.GetFileName(this.Folder);

public string FolderId { get; }
public string FolderLabel { get; }

public BindableCollection<ConflictOptionViewModel> ConflictOptions { get; }

Expand All @@ -37,7 +37,7 @@ public class ConflictViewModel : PropertyChangedBase
public ConflictViewModel(ConflictSet conflictSet, string folderName)
{
this.ConflictSet = conflictSet;
this.FolderId = folderName;
this.FolderLabel = folderName;

this.ConflictOptions = new BindableCollection<ConflictOptionViewModel>(this.ConflictSet.Conflicts.Select(x => new ConflictOptionViewModel(x)));

Expand Down
2 changes: 1 addition & 1 deletion src/SyncTrayzor/Pages/Settings/SettingsView.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@
lvlm:ListViewLayoutManager.Enabled="True">
<ListView.View>
<GridView AllowsColumnReorder="False">
<GridViewColumn Header="{l:Loc SettingsView_WatchedFolders_Header_Folder}" DisplayMemberBinding="{Binding FolderName}" lvlm:RangeColumn.IsFillColumn="True"/>
<GridViewColumn Header="{l:Loc SettingsView_WatchedFolders_Header_Folder}" DisplayMemberBinding="{Binding FolderLabel}" lvlm:RangeColumn.IsFillColumn="True"/>
<GridViewColumn>
<GridViewColumn.Header>
<CheckBox IsChecked="{Binding AreAllFoldersWatched}" Content="{l:Loc SettingsView_WatchedFolders_Header_Watched}" Margin="4,0,5,0"/>
Expand Down
29 changes: 22 additions & 7 deletions src/SyncTrayzor/Pages/Settings/SettingsViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@
using System.Windows;
using System.IO;
using SyncTrayzor.Services.Metering;
using SyncTrayzor.Syncthing.Folders;

namespace SyncTrayzor.Pages.Settings
{
public class FolderSettings : PropertyChangedBase
{
public string FolderName { get; set; }
public string FolderId { get; set; }
public string FolderLabel { get; set; }
public bool IsWatched { get; set; }
public bool IsNotified { get; set; }
}
Expand Down Expand Up @@ -258,13 +260,26 @@ private void LoadFromSyncthingStartupData()
{
var configuration = this.configurationProvider.Load();

// We have to merge two sources of data: the folder settings from config, and the actual folder
// configuration from Syncthing (which we use to get the folder label). They should be in sync...

this.FolderSettings.Clear();
this.FolderSettings.AddRange(configuration.Folders.OrderByDescending(x => x.ID).Select(x => new FolderSettings()

var folderSettings = configuration.Folders.Select(x =>
{
FolderName = x.ID,
IsWatched = x.IsWatched,
IsNotified = x.NotificationsEnabled,
}));
Folder folder;
this.syncthingManager.Folders.TryFetchById(x.ID, out folder);

return new FolderSettings()
{
FolderId = x.ID,
FolderLabel = folder?.Label ?? x.ID,
IsWatched = x.IsWatched,
IsNotified = x.NotificationsEnabled,
};
});
this.FolderSettings.AddRange(folderSettings.OrderBy(x => x.FolderLabel));

this.NotifyOfPropertyChange(nameof(this.FolderSettings));

this.SyncthingDebugFacilities.Clear();
Expand Down Expand Up @@ -343,7 +358,7 @@ public void Save()
settingItem.SaveValue(configuration);
}

configuration.Folders = this.FolderSettings.Select(x => new FolderConfiguration(x.FolderName, x.IsWatched, x.IsNotified)).ToList();
configuration.Folders = this.FolderSettings.Select(x => new FolderConfiguration(x.FolderId, x.IsWatched, x.IsNotified)).ToList();
// The ConfigurationApplicator will propagate this to the DebugFacilitiesManager
configuration.SyncthingDebugFacilities = this.SyncthingDebugFacilities.Where(x => x.IsEnabled).Select(x => x.Name).ToList();
});
Expand Down
2 changes: 1 addition & 1 deletion src/SyncTrayzor/Services/AlertsManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ private void OnAlertsStateChanged()
private void FolderErrorsChanged(object sender, FolderErrorsChangedEventArgs e)
{
var folders = this.syncthingManager.Folders.FetchAll();
this._foldersWithFailedTransferFiles = folders.Where(x => x.FolderErrors.Any()).Select(x => x.FolderId).ToList().AsReadOnly();
this._foldersWithFailedTransferFiles = folders.Where(x => x.FolderErrors.Any()).Select(x => x.Label).ToList().AsReadOnly();

this.OnAlertsStateChanged();
}
Expand Down
4 changes: 2 additions & 2 deletions src/SyncTrayzor/Services/Conflicts/ConflictFileWatcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ private void StartWatchers(IReadOnlyCollection<Folder> folders)
{
foreach (var folder in folders)
{
logger.Debug("Starting watcher for folder: {0}", folder.FolderId);
logger.Debug("Starting watcher for folder: {0} ({1})", folder.FolderId, folder.Label);

var watcher = this.fileWatcherFactory.Create(FileWatcherMode.CreatedOrDeleted, folder.Path, this.FolderExistenceCheckingInterval, this.conflictFileManager.ConflictPattern);
watcher.PathChanged += this.PathChanged;
Expand Down Expand Up @@ -240,7 +240,7 @@ private async Task ScanFoldersAsync(IReadOnlyCollection<Folder> folders)

foreach (var folder in folders)
{
logger.Debug("Scanning folder {0} ({1}) for conflict files", folder.FolderId, folder.Path);
logger.Debug("Scanning folder {0} ({1}) ({2}) for conflict files", folder.FolderId, folder.Label, folder.Path);

var options = await this.conflictFileManager.FindConflicts(folder.Path)
.SelectMany(conflict => conflict.Conflicts)
Expand Down
5 changes: 4 additions & 1 deletion src/SyncTrayzor/Syncthing/ApiClient/Config.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ public class ConfigFolder : IEquatable<ConfigFolder>
[JsonProperty("id")]
public string ID { get; set; }

[JsonProperty("label")]
public string Label { get; set; }

[JsonProperty("path")]
public string Path { get; set; }

Expand Down Expand Up @@ -61,7 +64,7 @@ public bool Equals(ConfigFolder other)

public override string ToString()
{
return $"<Folder id={this.ID} path={this.Path} devices=[{String.Join(", ", this.Devices)}] rescalinterval={this.RescanInterval} invalid={this.Invalid}>";
return $"<Folder id={this.ID} label={this.Label} path={this.Path} devices=[{String.Join(", ", this.Devices)}] rescalinterval={this.RescanInterval} invalid={this.Invalid}>";
}
}

Expand Down
37 changes: 34 additions & 3 deletions src/SyncTrayzor/Syncthing/Folders/Folder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ public class Folder : IEquatable<Folder>
private readonly object syncRoot = new object();

public string FolderId { get; }
public string Label { get; }
public string Path { get; }

private FolderSyncState _syncState;
Expand All @@ -36,9 +37,10 @@ public IReadOnlyList<FolderError> FolderErrors
}


public Folder(string folderId, string path, FolderSyncState syncState, FolderStatus status)
public Folder(string folderId, string label, string path, FolderSyncState syncState, FolderStatus status)
{
this.FolderId = folderId;
this.Label = String.IsNullOrWhiteSpace(label) ? folderId : label;
this.Path = path;
this.SyncState = syncState;
this.syncingPaths = new HashSet<string>();
Expand Down Expand Up @@ -92,12 +94,41 @@ public bool Equals(Folder other)
if (Object.ReferenceEquals(other, null))
return false;

return this.FolderId == other.FolderId;
lock (this.syncRoot)
{
return this.FolderId == other.FolderId &&
this.Label == other.Label &&
this.Path == other.Path &&
this.SyncState == other.SyncState &&
this.Status == other.Status &&
this.FolderErrors.SequenceEqual(other.FolderErrors) &&
this.syncingPaths.SetEquals(other.syncingPaths);
}
}

public override int GetHashCode()
{
return this.FolderId.GetHashCode();
unchecked
{
lock (this.syncRoot)
{
int hash = 17;
hash = hash * 23 + this.FolderId.GetHashCode();
hash = hash * 23 + this.Label.GetHashCode();
hash = hash * 23 + this.SyncState.GetHashCode();
hash = hash * 23 + this.Status.GetHashCode();
hash = hash * 23 + this.syncingPaths.GetHashCode();
foreach (var folderError in this.FolderErrors)
{
hash = hash * 23 + folderError.GetHashCode();
}
foreach (var syncingPath in this.syncingPaths)
{
hash = hash * 23 + syncingPath.GetHashCode();
}
return hash;
}
}
}
}
}
33 changes: 31 additions & 2 deletions src/SyncTrayzor/Syncthing/Folders/FolderError.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
namespace SyncTrayzor.Syncthing.Folders
using System;

namespace SyncTrayzor.Syncthing.Folders
{
public class FolderError
public class FolderError : IEquatable<FolderError>
{
public string Error { get; }
public string Path { get; }
Expand All @@ -10,5 +12,32 @@ public FolderError(string error, string path)
this.Error = error;
this.Path = path;
}

public bool Equals(FolderError other)
{
if (Object.ReferenceEquals(this, other))
return true;
if (Object.ReferenceEquals(other, null))
return false;

return this.Error == other.Error &&
this.Path == other.Path;
}

public override bool Equals(object obj)
{
return this.Equals(obj as FolderError);
}

public override int GetHashCode()
{
unchecked
{
int hash = 17;
hash = hash * 23 + this.Error.GetHashCode();
hash = hash * 23 + this.Path.GetHashCode();
return hash;
}
}
}
}
7 changes: 4 additions & 3 deletions src/SyncTrayzor/Syncthing/Folders/SyncthingFolderManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ public async Task ReloadFoldersAsync(Config config, string tilde, CancellationTo
var existingFolders = this.folders;

// Maybe nothing changed?
if (existingFolders.Values.SequenceEqual(folders))
if (new HashSet<Folder>(existingFolders.Values).SetEquals(folders))
return;

var changeNotifications = new List<Action>();
Expand All @@ -123,7 +123,8 @@ public async Task ReloadFoldersAsync(Config config, string tilde, CancellationTo
changeNotifications.Add(() => this.OnStatusChanged(folder, folder.Status));
existingFolder.SyncState = folder.SyncState;
}
newFolders[folder.FolderId] = existingFolder;
// Things like the label may have changed, so need to use the new folder instance
newFolders[folder.FolderId] = folder;
}
else
{
Expand Down Expand Up @@ -160,7 +161,7 @@ private async Task<IEnumerable<Folder>> FetchFoldersAsync(Config config, string
if (path.StartsWith("~"))
path = Path.Combine(tilde, path.Substring(1).TrimStart(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar));

return new Folder(folder.ID, path, syncState, status);
return new Folder(folder.ID, folder.Label, path, syncState, status);
});

cancellationToken.ThrowIfCancellationRequested();
Expand Down

0 comments on commit 6f5325d

Please sign in to comment.