- Notifications
You must be signed in to change notification settings - Fork3
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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Changes fromall commits
File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading.Please reload this page.
Jump to
Uh oh!
There was an error while loading.Please reload this page.
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
Uh oh!
There was an error while loading.Please reload this page.
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 | ||
spikecurtis marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
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>; |
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 resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
{ | ||
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]}"; | ||
} | ||
} |
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(); | ||
} | ||
} |
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; | ||
} | ||
} |
Uh oh!
There was an error while loading.Please reload this page.
Uh oh!
There was an error while loading.Please reload this page.