Skip to content

Commit

Permalink
feat: Change time from 12 hr to 24 and back, also began working on th…
Browse files Browse the repository at this point in the history
…e Attributes loader (not-nullptr#58)
  • Loading branch information
iLollek committed Dec 21, 2024
1 parent 5bbbb90 commit 460c338
Show file tree
Hide file tree
Showing 12 changed files with 309 additions and 16 deletions.
24 changes: 24 additions & 0 deletions Aerochat/Attributes/DisplayAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

// (iL - 21.12.2024) This is basically another abstraction layer for developers.
// Let's say you have a beautiful DropDown for the Settings, but your Enum Variable Names are pretty cryptic
// for the average End-User. With Aerochat.Attributes, you can show the user a beautiful string in the UI,
// while here in the Code you can keep your cryptic and scary sounding Names.

namespace Aerochat.Attributes
{
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
public class DisplayAttribute : Attribute
{
public string Name { get; set; }

public DisplayAttribute(string name)
{
Name = name;
}
}
}
33 changes: 33 additions & 0 deletions Aerochat/Converter/TimeFormatConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using Aerochat.Enums;
using Aerochat.Settings;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;

namespace Aerochat.Windows
{
public class TimeFormatConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is DateTime dateTime)
{
// Retrieve SelectedTimeFormat from the SettingsManager
var format = SettingsManager.Instance.SelectedTimeFormat;
string formatString = format == TimeFormat.TwentyFourHour ? "HH:mm:ss" : "h:mm tt";

return dateTime.ToString(formatString);
}
return value;
}

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
18 changes: 18 additions & 0 deletions Aerochat/Enums/TimeFormat.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Aerochat.Attributes;

namespace Aerochat.Enums
{
public enum TimeFormat
{
[Display("24-Hour Clock")]
TwentyFourHour,

[Display("12-Hour Clock (AM/PM)")]
TwelveHour
}
}
39 changes: 39 additions & 0 deletions Aerochat/Helpers/EnumHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Aerochat.Attributes;

namespace Aerochat.Helpers
{
public static class EnumHelper
{
public static string GetDisplayName(Enum enumValue)
{
var fieldInfo = enumValue.GetType()
.GetField(enumValue.ToString(), BindingFlags.Public | BindingFlags.Static);

if (fieldInfo != null)
{
var displayAttribute = fieldInfo.GetCustomAttribute<DisplayAttribute>();

if (displayAttribute != null)
{
return displayAttribute.Name;
}
}

return enumValue.ToString();
}

public static List<(string DisplayName, T EnumValue)> GetEnumDisplayList<T>() where T : Enum
{
return Enum.GetValues(typeof(T))
.Cast<T>()
.Select(e => (GetDisplayName(e), e)) // Create tuple of DisplayName and EnumValue
.ToList();
}
}
}
6 changes: 5 additions & 1 deletion Aerochat/Settings/SettingsManager.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Aerochat.ViewModels;
using Aerochat.Enums;
using Aerochat.ViewModels;
using System;
using System.IO;
using System.Linq;
Expand Down Expand Up @@ -103,6 +104,9 @@ public static void Load()
[Settings("Appearance", "Show community images in the Main View (requires restart)")]

public bool DisplayAds { get; set; } = true;

[Settings("Appearance", "Time format")]
public TimeFormat SelectedTimeFormat { get; set; } = TimeFormat.TwentyFourHour;
#endregion
}
}
5 changes: 5 additions & 0 deletions Aerochat/ViewModels/Base.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ public abstract class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler? PropertyChanged;

protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

protected bool SetProperty<T>(ref T field, T newValue, [CallerMemberName] string? propertyName = null)
{
if (!EqualityComparer<T>.Default.Equals(field, newValue))
Expand Down
48 changes: 41 additions & 7 deletions Aerochat/ViewModels/Message.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
using Aerochat.Hoarder;
using Aerochat.Enums;
using Aerochat.Hoarder;
using Aerochat.Settings;
using DSharpPlus;
using DSharpPlus.Entities;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
Expand All @@ -16,7 +20,6 @@ public class MessageViewModel : ViewModelBase
private UserViewModel? _author;
private string _message;
private string _rawMessage;
private DateTime _timestamp;
private ulong? _id;
private bool _ephemeral = false;
private bool _special = false;
Expand All @@ -43,11 +46,6 @@ public string RawMessage
get => _rawMessage;
set => SetProperty(ref _rawMessage, value);
}
public DateTime Timestamp
{
get => _timestamp;
set => SetProperty(ref _timestamp, value);
}
public ulong? Id
{
get => _id;
Expand Down Expand Up @@ -94,6 +92,42 @@ public DiscordMessage MessageEntity
set => SetProperty(ref _messageEntity, value);
}

public string TimestampString
{
get
{
var format = SettingsManager.Instance.SelectedTimeFormat == TimeFormat.TwentyFourHour ? "HH:mm" : "h:mm tt";
return Timestamp.ToString(format, CultureInfo.InvariantCulture); // Ensure InvariantCulture to control formatting: Otherwise we will lose the AM/PM at the end!
}
}

private DateTime _timestamp;
public DateTime Timestamp
{
get { return _timestamp; }
set
{
if (_timestamp != value)
{
_timestamp = value;
RaisePropertyChanged(nameof(Timestamp));
RaisePropertyChanged(nameof(TimestampString));
}
}
}

public virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

public event PropertyChangedEventHandler PropertyChanged;

public void RaisePropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

public ObservableCollection<AttachmentViewModel> Attachments { get; } = new();
public ObservableCollection<EmbedViewModel> Embeds { get; } = new();

Expand Down
20 changes: 19 additions & 1 deletion Aerochat/ViewModels/Settings.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
using System;
using Aerochat.Enums;
using Aerochat.Helpers;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static Vanara.PInvoke.ShlwApi;

namespace Aerochat.ViewModels
{
Expand All @@ -13,6 +16,10 @@ public class SettingViewModel : ViewModelBase
private string _name;
private string _defaultValue;

public ObservableCollection<string> EnumValues { get; set; } = new ObservableCollection<string>();
public ObservableCollection<string> TimeFormatOptions { get; set; }
public TimeFormat SelectedTimeFormat { get; set; }

public string Type
{
get => _type;
Expand All @@ -28,6 +35,17 @@ public string DefaultValue
get => _defaultValue;
set => SetProperty(ref _defaultValue, value);
}

private string _selectedEnumValue;
public string SelectedEnumValue
{
get => _selectedEnumValue;
set
{
_selectedEnumValue = value;
OnPropertyChanged();
}
}
}

public class SettingsCategory : ViewModelBase
Expand Down
9 changes: 7 additions & 2 deletions Aerochat/Windows/Chat.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,9 @@
</Style>
</Window.Style>
<Window.Resources>
<Storyboard x:Key="FadeOutStoryboard">
<local:TimeFormatConverter x:Key="TimeFormatConverter"/>

<Storyboard x:Key="FadeOutStoryboard">
<DoubleAnimation Storyboard.TargetProperty="Opacity"
To="0"
Duration="0:0:0.3"
Expand Down Expand Up @@ -909,7 +911,10 @@
</Image.Style>
</Image>
<TextBlock FontSize="13" Grid.Row="0" Text=" said (" Foreground="#525252" />
<TextBlock FontSize="13" Grid.Row="0" Text="{Binding Timestamp, StringFormat=HH:mm}" Foreground="#525252" />
<!--<TextBlock FontSize="13" Grid.Row="0" Text="{Binding Timestamp, StringFormat=HH:mm:ss}" Foreground="#525252" />-->
<TextBlock FontSize="13" Foreground="#525252">
<TextBlock FontSize="13" Grid.Row="0" Text="{Binding TimestampString}" Foreground="#525252" />
</TextBlock>
<TextBlock FontSize="13" Grid.Row="0" Text="):" Foreground="#525252" />
</StackPanel>
</StackPanel>
Expand Down
32 changes: 32 additions & 0 deletions Aerochat/Windows/Chat.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
using Timer = System.Timers.Timer;
using DSharpPlus.Exceptions;
using static Aerochat.Windows.ToolbarItem;
using Aerochat.Enums;

namespace Aerochat.Windows
{
Expand Down Expand Up @@ -731,6 +732,10 @@ public Chat(ulong id, bool allowDefault = false)
};
ViewModel.Messages.CollectionChanged += UpdateHiddenInfo;
TypingUsers.CollectionChanged += TypingUsers_CollectionChanged;

// (iL - 20.12.2024) Subscribe to settings changes for live update
SettingsManager.Instance.PropertyChanged += OnSettingsChanged;

Closing += Chat_Closing;
Loaded += Chat_Loaded;
Discord.Client.TypingStarted += OnType;
Expand All @@ -745,6 +750,33 @@ public Chat(ulong id, bool allowDefault = false)
DrawingCanvas.Strokes.StrokesChanged += Strokes_StrokesChanged;
}

private void OnSettingsChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(SettingsManager.Instance.SelectedTimeFormat))
{
Dispatcher.Invoke(() =>
{
foreach (var message in ViewModel.Messages)
{
// Update each message
message.RaisePropertyChanged(nameof(MessageViewModel.TimestampString));
}

// Force the collection to refresh
// (iL - 21.12.2024) I know that this is a really shitty way to force the UI to update,
// but I wasn't able to implement the live updating any other way after
// fooling around with it for an hour.
// Maybe you have a better idea? :-)
var tempMessages = ViewModel.Messages.ToList();
ViewModel.Messages.Clear();
foreach (var msg in tempMessages)
{
ViewModel.Messages.Add(msg);
}
});
}
}

private async Task OnVoiceStateUpdated(DiscordClient sender, DSharpPlus.EventArgs.VoiceStateUpdateEventArgs args)
{
if (args.Guild.Id != Channel.Guild?.Id) return;
Expand Down
27 changes: 27 additions & 0 deletions Aerochat/Windows/Settings.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Margin="0,4,0,0">
<!-- For Boolean Settings -->
<StackPanel Orientation="Horizontal">
<StackPanel.Style>
<Style TargetType="StackPanel">
Expand All @@ -128,6 +129,8 @@
<TextBlock Text="{Binding Name}" />
</CheckBox>
</StackPanel>

<!-- For Integer Settings -->
<StackPanel>
<StackPanel.Style>
<Style TargetType="StackPanel">
Expand All @@ -142,8 +145,32 @@
<TextBlock Margin="0,8,0,4" Text="{Binding Name}" />
<TextBox TextChanged="TextBox_TextChanged" Tag="{Binding Name}" Text="{Binding DefaultValue}" PreviewTextInput="TextBox_PreviewTextInput" VerticalContentAlignment="Center" Width="150" Height="22" HorizontalAlignment="Left" />
</StackPanel>

<!-- For Enum Settings -->
<StackPanel>
<StackPanel.Style>
<Style TargetType="StackPanel">
<Setter Property="Visibility" Value="Collapsed" />
<Style.Triggers>
<DataTrigger Binding="{Binding Type}" Value="Enum">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
<TextBlock Margin="0,8,0,4" Text="{Binding Name}" />
<ComboBox
SelectionChanged="ComboBox_SelectionChanged"
SelectedItem="{Binding SelectedEnumValue, Mode=TwoWay}"
Tag="{Binding Name}"
ItemsSource="{Binding EnumValues}"
Width="150"
Height="22"
HorizontalAlignment="Left" />
</StackPanel>
</Grid>
</DataTemplate>

</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
Expand Down
Loading

0 comments on commit 460c338

Please sign in to comment.