-
Notifications
You must be signed in to change notification settings - Fork 3
feat: add mock UI for file syncing listing #60
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
+1,337
−74
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,188 @@ | ||
using System; | ||
using System.Linq; | ||
using Windows.Foundation.Collections; | ||
using Windows.UI.Xaml.Markup; | ||
using Microsoft.UI.Xaml; | ||
using Microsoft.UI.Xaml.Data; | ||
using Microsoft.UI.Xaml.Media; | ||
|
||
namespace Coder.Desktop.App.Converters; | ||
|
||
// This file uses manual DependencyProperty properties rather than | ||
// DependencyPropertyGenerator since it doesn't seem to work properly with | ||
// generics. | ||
|
||
/// <summary> | ||
/// An item in a DependencyObjectSelector. Each item has a key and a value. | ||
/// The default item in a DependencyObjectSelector will be the only item | ||
/// with a null key. | ||
/// </summary> | ||
/// <typeparam name="TK">Key type</typeparam> | ||
/// <typeparam name="TV">Value type</typeparam> | ||
public class DependencyObjectSelectorItem<TK, TV> : DependencyObject | ||
where TK : IEquatable<TK> | ||
{ | ||
public static readonly DependencyProperty KeyProperty = | ||
DependencyProperty.Register(nameof(Key), | ||
typeof(TK?), | ||
typeof(DependencyObjectSelectorItem<TK, TV>), | ||
new PropertyMetadata(null)); | ||
|
||
public static readonly DependencyProperty ValueProperty = | ||
DependencyProperty.Register(nameof(Value), | ||
typeof(TV?), | ||
typeof(DependencyObjectSelectorItem<TK, TV>), | ||
new PropertyMetadata(null)); | ||
|
||
public TK? Key | ||
{ | ||
get => (TK?)GetValue(KeyProperty); | ||
set => SetValue(KeyProperty, value); | ||
} | ||
|
||
public TV? Value | ||
{ | ||
get => (TV?)GetValue(ValueProperty); | ||
set => SetValue(ValueProperty, value); | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// Allows selecting between multiple value references based on a selected | ||
/// key. This allows for dynamic mapping of model values to other objects. | ||
/// The main use case is for selecting between other bound values, which | ||
/// you cannot do with a simple ValueConverter. | ||
/// </summary> | ||
/// <typeparam name="TK">Key type</typeparam> | ||
/// <typeparam name="TV">Value type</typeparam> | ||
[ContentProperty(Name = nameof(References))] | ||
public class DependencyObjectSelector<TK, TV> : DependencyObject | ||
where TK : IEquatable<TK> | ||
{ | ||
public static readonly DependencyProperty ReferencesProperty = | ||
DependencyProperty.Register(nameof(References), | ||
typeof(DependencyObjectCollection), | ||
typeof(DependencyObjectSelector<TK, TV>), | ||
new PropertyMetadata(null, ReferencesPropertyChanged)); | ||
|
||
public static readonly DependencyProperty SelectedKeyProperty = | ||
DependencyProperty.Register(nameof(SelectedKey), | ||
typeof(TK?), | ||
typeof(DependencyObjectSelector<TK, TV>), | ||
new PropertyMetadata(null, SelectedKeyPropertyChanged)); | ||
|
||
public static readonly DependencyProperty SelectedObjectProperty = | ||
DependencyProperty.Register(nameof(SelectedObject), | ||
typeof(TV?), | ||
typeof(DependencyObjectSelector<TK, TV>), | ||
new PropertyMetadata(null)); | ||
|
||
public DependencyObjectCollection? References | ||
{ | ||
get => (DependencyObjectCollection?)GetValue(ReferencesProperty); | ||
set | ||
{ | ||
// Ensure unique keys and that the values are DependencyObjectSelectorItem<K, V>. | ||
if (value != null) | ||
{ | ||
var items = value.OfType<DependencyObjectSelectorItem<TK, TV>>().ToArray(); | ||
var keys = items.Select(i => i.Key).Distinct().ToArray(); | ||
if (keys.Length != value.Count) | ||
throw new ArgumentException("ObservableCollection Keys must be unique."); | ||
} | ||
|
||
SetValue(ReferencesProperty, value); | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// The key of the selected item. This should be bound to a property on | ||
/// the model. | ||
/// </summary> | ||
public TK? SelectedKey | ||
{ | ||
get => (TK?)GetValue(SelectedKeyProperty); | ||
set => SetValue(SelectedKeyProperty, value); | ||
} | ||
|
||
/// <summary> | ||
/// The selected object. This can be read from to get the matching | ||
/// object for the selected key. If the selected key doesn't match any | ||
/// object, this will be the value of the null key. If there is no null | ||
/// key, this will be null. | ||
/// </summary> | ||
public TV? SelectedObject | ||
{ | ||
get => (TV?)GetValue(SelectedObjectProperty); | ||
set => SetValue(SelectedObjectProperty, value); | ||
} | ||
|
||
public DependencyObjectSelector() | ||
{ | ||
References = []; | ||
} | ||
|
||
private void UpdateSelectedObject() | ||
{ | ||
if (References != null) | ||
{ | ||
// Look for a matching item a matching key, or fallback to the null | ||
// key. | ||
var references = References.OfType<DependencyObjectSelectorItem<TK, TV>>().ToArray(); | ||
var item = references | ||
.FirstOrDefault(i => | ||
(i.Key == null && SelectedKey == null) || | ||
(i.Key != null && SelectedKey != null && i.Key!.Equals(SelectedKey!))) | ||
?? references.FirstOrDefault(i => i.Key == null); | ||
if (item is not null) | ||
{ | ||
// Bind the SelectedObject property to the reference's Value. | ||
// If the underlying Value changes, it will propagate to the | ||
// SelectedObject. | ||
BindingOperations.SetBinding | ||
( | ||
this, | ||
SelectedObjectProperty, | ||
new Binding | ||
{ | ||
Source = item, | ||
Path = new PropertyPath(nameof(DependencyObjectSelectorItem<TK, TV>.Value)), | ||
} | ||
); | ||
return; | ||
} | ||
} | ||
|
||
ClearValue(SelectedObjectProperty); | ||
} | ||
|
||
// Called when the References property is replaced. | ||
private static void ReferencesPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args) | ||
{ | ||
var self = obj as DependencyObjectSelector<TK, TV>; | ||
if (self == null) return; | ||
var oldValue = args.OldValue as DependencyObjectCollection; | ||
if (oldValue != null) | ||
oldValue.VectorChanged -= self.OnVectorChangedReferences; | ||
var newValue = args.NewValue as DependencyObjectCollection; | ||
if (newValue != null) | ||
newValue.VectorChanged += self.OnVectorChangedReferences; | ||
} | ||
|
||
// Called when the References collection changes without being replaced. | ||
private void OnVectorChangedReferences(IObservableVector<DependencyObject> sender, IVectorChangedEventArgs args) | ||
{ | ||
UpdateSelectedObject(); | ||
} | ||
|
||
// Called when SelectedKey changes. | ||
private static void SelectedKeyPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args) | ||
{ | ||
var self = obj as DependencyObjectSelector<TK, TV>; | ||
self?.UpdateSelectedObject(); | ||
} | ||
} | ||
|
||
public sealed class StringToBrushSelectorItem : DependencyObjectSelectorItem<string, Brush>; | ||
|
||
public sealed class StringToBrushSelector : DependencyObjectSelector<string, Brush>; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
using System; | ||
using Microsoft.UI.Xaml.Data; | ||
|
||
namespace Coder.Desktop.App.Converters; | ||
|
||
public class FriendlyByteConverter : IValueConverter | ||
deansheather marked this conversation as resolved.
Show resolved
Hide resolved
|
||
{ | ||
private static readonly string[] Suffixes = ["B", "KB", "MB", "GB", "TB", "PB", "EB"]; | ||
|
||
public object Convert(object value, Type targetType, object parameter, string language) | ||
{ | ||
switch (value) | ||
{ | ||
case int i: | ||
if (i < 0) i = 0; | ||
return FriendlyBytes((ulong)i); | ||
case uint ui: | ||
return FriendlyBytes(ui); | ||
case long l: | ||
if (l < 0) l = 0; | ||
return FriendlyBytes((ulong)l); | ||
case ulong ul: | ||
return FriendlyBytes(ul); | ||
default: | ||
return FriendlyBytes(0); | ||
} | ||
} | ||
|
||
public object ConvertBack(object value, Type targetType, object parameter, string language) | ||
{ | ||
throw new NotImplementedException(); | ||
} | ||
|
||
public static string FriendlyBytes(ulong bytes) | ||
{ | ||
if (bytes == 0) | ||
return $"0 {Suffixes[0]}"; | ||
|
||
var place = System.Convert.ToInt32(Math.Floor(Math.Log(bytes, 1024))); | ||
var num = Math.Round(bytes / Math.Pow(1024, place), 1); | ||
return $"{num} {Suffixes[place]}"; | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
using System; | ||
using Microsoft.UI.Xaml.Data; | ||
|
||
namespace Coder.Desktop.App.Converters; | ||
|
||
public class InverseBoolConverter : IValueConverter | ||
{ | ||
public object Convert(object value, Type targetType, object parameter, string language) | ||
{ | ||
return value is false; | ||
} | ||
|
||
public object ConvertBack(object value, Type targetType, object parameter, string language) | ||
{ | ||
throw new NotImplementedException(); | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
using Microsoft.UI.Xaml; | ||
|
||
namespace Coder.Desktop.App.Converters; | ||
|
||
public partial class InverseBoolToVisibilityConverter : BoolToObjectConverter | ||
{ | ||
public InverseBoolToVisibilityConverter() | ||
{ | ||
TrueValue = Visibility.Collapsed; | ||
FalseValue = Visibility.Visible; | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.