Skip to content

Commit

Permalink
Refactor MainViewModel and Introduce Services for Better Separation o…
Browse files Browse the repository at this point in the history
…f Concerns
  • Loading branch information
mateusz-kierepka-hl committed Dec 28, 2024
1 parent 9b24d93 commit 7526cd0
Show file tree
Hide file tree
Showing 12 changed files with 383 additions and 70 deletions.
1 change: 1 addition & 0 deletions .idea/.idea.ChatAAC/.idea/avalonia.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file added ChatAAC/Assets/favorite-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
19 changes: 19 additions & 0 deletions ChatAAC/Converters/BooleanToBrushConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using System;
using Avalonia.Data.Converters;
using Avalonia.Media;

namespace ChatAAC.Converters;

public class BooleanToBrushConverter : IValueConverter
{
public object Convert(object? value, Type targetType, object? parameter, System.Globalization.CultureInfo culture)
{
return value is bool and true ? Brushes.LightYellow : // Highlight favorites
Brushes.Transparent;
}

public object ConvertBack(object? value, Type targetType, object? parameter, System.Globalization.CultureInfo culture)
{
throw new NotSupportedException();
}
}
42 changes: 42 additions & 0 deletions ChatAAC/Lang/Resources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 21 additions & 0 deletions ChatAAC/Lang/Resources.en.resx
Original file line number Diff line number Diff line change
Expand Up @@ -213,4 +213,25 @@
<data name="AboutCloseButtonAutomation" xml:space="preserve">
<value>Close button</value>
</data>
<data name="SortNewestToOldestButton" xml:space="preserve">
<value>Sort Newest to Oldest</value>
</data>
<data name="SpeakSelectedEntryButton" xml:space="preserve">
<value>Odczytaj wybrany wpis</value>
</data>
<data name="CloseButton" xml:space="preserve">
<value>Close</value>
</data>
<data name="HistoryWindowTitle" xml:space="preserve">
<value>History of entries</value>
</data>
<data name="SortOldestToNewestButton" xml:space="preserve">
<value>Sort Oldest to Newest</value>
</data>
<data name="SortFavoritesButton" xml:space="preserve">
<value>Sort by favorites</value>
</data>
<data name="FavoriteButton" xml:space="preserve">
<value>Favorite</value>
</data>
</root>
21 changes: 21 additions & 0 deletions ChatAAC/Lang/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -219,4 +219,25 @@
<data name="AboutCloseButtonAutomation" xml:space="preserve">
<value>Przycisk zamknięcia</value>
</data>
<data name="SortNewestToOldestButton" xml:space="preserve">
<value>Sortuj od najnowszych</value>
</data>
<data name="SpeakSelectedEntryButton" xml:space="preserve">
<value>Read Selected Entry</value>
</data>
<data name="CloseButton" xml:space="preserve">
<value>Zamknij</value>
</data>
<data name="HistoryWindowTitle" xml:space="preserve">
<value>Historia wpisów</value>
</data>
<data name="SortOldestToNewestButton" xml:space="preserve">
<value>Sortuj od najstarszych</value>
</data>
<data name="SortFavoritesButton" xml:space="preserve">
<value>Sortuj wg ulubionych</value>
</data>
<data name="FavoriteButton" xml:space="preserve">
<value>Ulubiony</value>
</data>
</root>
27 changes: 24 additions & 3 deletions ChatAAC/Models/AiResponse.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,30 @@
using System;
using ReactiveUI;

namespace ChatAAC.Models;

public class AiResponse(string responseText)
public class AiResponse(string responseText) : ReactiveObject
{
public string ResponseText { get; set; } = responseText;
public DateTime Timestamp { get; set; } = DateTime.Now;
private string _responseText = responseText;
private bool _isFavorite;
private DateTime _timestamp = DateTime.Now;

public string ResponseText
{
get => _responseText;
set => this.RaiseAndSetIfChanged(ref _responseText, value);
}

public DateTime Timestamp
{
get => _timestamp;
set => this.RaiseAndSetIfChanged(ref _timestamp, value);
}


public bool IsFavorite
{
get => _isFavorite;
set => this.RaiseAndSetIfChanged(ref _isFavorite, value);
}
}
53 changes: 53 additions & 0 deletions ChatAAC/Services/HistoryService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
using System;
using System.Collections.ObjectModel;
using System.IO;
using System.Text.Json;
using ChatAAC.Models;

public class HistoryService
{
public ObservableCollection<AiResponse> HistoryItems { get; } = new();
public string HistoryFilePath { get; } = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "ChatAAC", "ai_response_history.json");

public void LoadHistory()
{
if (!File.Exists(HistoryFilePath)) return;

try
{
var json = File.ReadAllText(HistoryFilePath);
var history = JsonSerializer.Deserialize<ObservableCollection<AiResponse>>(json);
if (history != null)
foreach (var item in history)
HistoryItems.Add(item);
}
catch (Exception ex)
{
Console.WriteLine($"Error loading history: {ex.Message}");
}
}

public void SaveHistory()
{
try
{
var directory = Path.GetDirectoryName(HistoryFilePath);
if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory))
Directory.CreateDirectory(directory);

var options = new JsonSerializerOptions { WriteIndented = true };
var json = JsonSerializer.Serialize(HistoryItems, options);
File.WriteAllText(HistoryFilePath, json);
}
catch (Exception ex)
{
Console.WriteLine($"Error saving history: {ex.Message}");
}
}

public void AddToHistory(AiResponse response)
{
HistoryItems.Add(response);
SaveHistory();
}
}
101 changes: 101 additions & 0 deletions ChatAAC/ViewModels/HistoryViewModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
using System;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using ReactiveUI;
using System.Reactive;
using System.Text.Json;
using System.Threading.Tasks;
using ChatAAC.Models;
using ChatAAC.Services;

namespace ChatAAC.ViewModels
{
public class HistoryViewModel : ReactiveObject
{
public ObservableCollection<AiResponse> HistoryItems { get; }
public AiResponse? SelectedHistoryItem { get; set; }

public HistoryViewModel(ObservableCollection<AiResponse> historyItems, string historyPath)
{
HistoryItems = historyItems;
HistoryFilePath = historyPath;

SortNewestToOldestCommand = ReactiveCommand.Create(SortNewestToOldest);
SortOldestToNewestCommand = ReactiveCommand.Create(SortOldestToNewest);
SortFavoritesCommand = ReactiveCommand.Create(SortFavorites);
ToggleFavoriteCommand = ReactiveCommand.Create<AiResponse>(ToggleFavorite);
SpeakSelectedEntryCommand = ReactiveCommand.Create(SpeakSelectedEntry);
SelectionChangedCommand = ReactiveCommand.CreateFromTask<AiResponse>(OnSelectionChanged);
}

private string HistoryFilePath { get; set; }

public ReactiveCommand<Unit, Unit> SortNewestToOldestCommand { get; }
public ReactiveCommand<Unit, Unit> SortOldestToNewestCommand { get; }
public ReactiveCommand<Unit, Unit> SortFavoritesCommand { get; }
public ReactiveCommand<AiResponse, Unit> ToggleFavoriteCommand { get; }
public ReactiveCommand<Unit, Task> SpeakSelectedEntryCommand { get; }
public ReactiveCommand<AiResponse, Unit> SelectionChangedCommand { get; }
private void SortNewestToOldest()
{
var sorted = HistoryItems.OrderByDescending(item => item.Timestamp).ToList();
HistoryItems.Clear();
foreach (var item in sorted)
HistoryItems.Add(item);
}

private void SortOldestToNewest()
{
var sorted = HistoryItems.OrderBy(item => item.Timestamp).ToList();
HistoryItems.Clear();
foreach (var item in sorted)
HistoryItems.Add(item);
}

private void SortFavorites()
{
var sorted = HistoryItems.OrderByDescending(item => item.IsFavorite).ThenByDescending(item => item.Timestamp).ToList();
HistoryItems.Clear();
foreach (var item in sorted)
HistoryItems.Add(item);
}

private void ToggleFavorite(AiResponse item)
{
item.IsFavorite = !item.IsFavorite; // Toggle favorite status
SaveHistory();
}

private void SaveHistory()
{
try
{
var directory = Path.GetDirectoryName(HistoryFilePath);
if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory))
Directory.CreateDirectory(directory);

var options = new JsonSerializerOptions { WriteIndented = true };
var json = JsonSerializer.Serialize(HistoryItems, options);
File.WriteAllText(HistoryFilePath, json);
}
catch (Exception ex)
{
Console.WriteLine($"Error saving history: {ex.Message}");
}
}
private async Task OnSelectionChanged(AiResponse item)
{
await SpeakSelectedEntry(); // Speak the selected item when changed
}
private async Task SpeakSelectedEntry()
{
if (SelectedHistoryItem == null)
return;

// Implement TTS for the selected history item
var ttsService = new TtsService(); // Replace with actual TTS service
await ttsService.SpeakAsync(SelectedHistoryItem.ResponseText);
}
}
}
Loading

0 comments on commit 7526cd0

Please sign in to comment.