From acfdf89ade8b86923fe7942be5b0eb479bbb5e04 Mon Sep 17 00:00:00 2001 From: Nouredeen06 Date: Sat, 28 Mar 2026 14:56:54 +0300 Subject: [PATCH] - Fixed DateRangePicker when mode is singledate - added Transaction Creation/Editing/Deletion - added confirmation for transaction deletion - added app icon --- .github/workflows/build-linux.yml | 40 +- Clario/Assets/Icons/chart-bar.svg | 1 + Clario/Assets/Icons/chart-column.svg | 1 + Clario/Assets/Icons/chevron-down.svg | 1 + Clario/Assets/Icons/receipt.svg | 1 + Clario/Assets/Logo textmark.png | 0 Clario/Assets/logo-no-bg.ico | Bin 0 -> 175066 bytes Clario/Assets/logo-textmark.svg | 41 +- Clario/Behaviors/NumericInputBehavior.cs | 65 +++ Clario/Clario.csproj | 2 + Clario/Clario.parcel | 30 -- .../AccountMaskToStringConverter.cs | 2 +- Clario/CustomControls/DateRangePicker.axaml | 5 +- Clario/CustomControls/DateRangePicker.cs | 55 ++- Clario/MobileViews/MainViewMobile.axaml | 17 +- .../TransactionFormViewMobile.axaml | 440 ++++++++++++++++++ .../TransactionFormViewMobile.axaml.cs | 13 + Clario/Theme/AppTheme.axaml | 12 +- Clario/ViewModels/BudgetViewModel.cs | 2 +- Clario/ViewModels/DashboardViewModel.cs | 12 +- Clario/ViewModels/MainViewModel.cs | 58 ++- Clario/ViewModels/TransactionFormViewModel.cs | 30 +- Clario/Views/AuthView.axaml | 6 +- Clario/Views/DashboardView.axaml | 286 +++++++----- Clario/Views/MainView.axaml | 19 +- Clario/Views/MainWindow.axaml | 1 + Clario/Views/TransactionFormView.axaml | 110 ++++- Directory.Packages.props | 2 + 28 files changed, 1005 insertions(+), 247 deletions(-) create mode 100644 Clario/Assets/Icons/chart-bar.svg create mode 100644 Clario/Assets/Icons/chart-column.svg create mode 100644 Clario/Assets/Icons/chevron-down.svg create mode 100644 Clario/Assets/Icons/receipt.svg delete mode 100644 Clario/Assets/Logo textmark.png create mode 100644 Clario/Assets/logo-no-bg.ico create mode 100644 Clario/Behaviors/NumericInputBehavior.cs delete mode 100644 Clario/Clario.parcel create mode 100644 Clario/MobileViews/TransactionFormViewMobile.axaml create mode 100644 Clario/MobileViews/TransactionFormViewMobile.axaml.cs diff --git a/.github/workflows/build-linux.yml b/.github/workflows/build-linux.yml index dbd80eb..9e3b2f9 100644 --- a/.github/workflows/build-linux.yml +++ b/.github/workflows/build-linux.yml @@ -1,34 +1,42 @@ name: Build Linux on: + workflow_dispatch: push: - branches: [main] + tags: + - 'v*' jobs: - build-linux: + build: runs-on: ubuntu-latest + steps: - - uses: actions/checkout@v4 + - name: Checkout + uses: actions/checkout@v4 - name: Setup .NET uses: actions/setup-dotnet@v4 with: - dotnet-version: '9.0.x' + dotnet-version: '8.0.x' + + - name: Restore dependencies + run: dotnet restore Clario/Clario.csproj + + - name: Build + run: dotnet build Clario/Clario.csproj --configuration Release --no-restore - name: Publish - run: | - dotnet publish Clario.Desktop/Clario.Desktop.csproj \ - -r linux-x64 \ - -c Release \ - --self-contained true \ - -p:PublishSingleFile=true \ - -o ./publish/linux-x64 - - - name: Package as tar.gz - run: tar -czf Clario-linux-x64.tar.gz -C ./publish/linux-x64 . + run: dotnet publish Clario/Clario.csproj \ + --configuration Release \ + --runtime linux-x64 \ + --self-contained true \ + --output ./publish/linux \ + -p:PublishSingleFile=true \ + -p:IncludeNativeLibrariesForSelfExtract=true - name: Upload artifact uses: actions/upload-artifact@v4 with: - name: clario-linux-x64 - path: Clario-linux-x64.tar.gz \ No newline at end of file + name: Clario-linux-x64 + path: ./publish/linux + retention-days: 7 \ No newline at end of file diff --git a/Clario/Assets/Icons/chart-bar.svg b/Clario/Assets/Icons/chart-bar.svg new file mode 100644 index 0000000..f085b03 --- /dev/null +++ b/Clario/Assets/Icons/chart-bar.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/Clario/Assets/Icons/chart-column.svg b/Clario/Assets/Icons/chart-column.svg new file mode 100644 index 0000000..e750861 --- /dev/null +++ b/Clario/Assets/Icons/chart-column.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/Clario/Assets/Icons/chevron-down.svg b/Clario/Assets/Icons/chevron-down.svg new file mode 100644 index 0000000..e576b4f --- /dev/null +++ b/Clario/Assets/Icons/chevron-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/Clario/Assets/Icons/receipt.svg b/Clario/Assets/Icons/receipt.svg new file mode 100644 index 0000000..65ed153 --- /dev/null +++ b/Clario/Assets/Icons/receipt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/Clario/Assets/Logo textmark.png b/Clario/Assets/Logo textmark.png deleted file mode 100644 index e69de29..0000000 diff --git a/Clario/Assets/logo-no-bg.ico b/Clario/Assets/logo-no-bg.ico new file mode 100644 index 0000000000000000000000000000000000000000..76cb10f0c85c0f21af5e0e55476d8fa2bf8b88d2 GIT binary patch literal 175066 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 - - - - - - + + + + + + + + + - + - + - + - + - + + + + + + + + + + + + + + + + + diff --git a/Clario/Behaviors/NumericInputBehavior.cs b/Clario/Behaviors/NumericInputBehavior.cs new file mode 100644 index 0000000..e107618 --- /dev/null +++ b/Clario/Behaviors/NumericInputBehavior.cs @@ -0,0 +1,65 @@ +using System; +using System.Linq; +using Avalonia.Controls; +using Avalonia.Input; +using Avalonia.Interactivity; +using Avalonia.Xaml.Interactivity; + +namespace Clario.Behaviors; + +public class NumericInputBehavior : Behavior +{ + protected override void OnAttached() + { + base.OnAttached(); + AssociatedObject!.AddHandler(TextBox.TextInputEvent, OnTextInput, RoutingStrategies.Tunnel); + AssociatedObject.TextChanged += OnTextChanged; + } + + protected override void OnDetaching() + { + base.OnDetaching(); + AssociatedObject!.RemoveHandler(TextBox.TextInputEvent, OnTextInput); + AssociatedObject.TextChanged -= OnTextChanged; + } + + private void OnTextInput(object? sender, TextInputEventArgs e) + { + if (e.Text is null) return; + foreach (var c in e.Text) + { + if (!char.IsDigit(c) && c != '.') + { + e.Handled = true; + return; + } + } + + var current = (sender as TextBox)?.Text ?? ""; + if (e.Text.Contains('.') && current.Contains('.')) + { + e.Handled = true; + } + } + + private void OnTextChanged(object? sender, TextChangedEventArgs e) + { + if (sender is not TextBox tb) return; + var text = tb.Text ?? ""; + + var clean = new string(text.Where(c => char.IsDigit(c) || c == '.').ToArray()); + + var dotIndex = clean.IndexOf('.'); + if (dotIndex >= 0) + { + clean = clean[..(dotIndex + 1)] + clean[(dotIndex + 1)..].Replace(".", ""); + } + + if (clean != text) + { + var caret = tb.CaretIndex; + tb.Text = clean; + tb.CaretIndex = Math.Min(caret, clean.Length); + } + } +} \ No newline at end of file diff --git a/Clario/Clario.csproj b/Clario/Clario.csproj index de6fc5e..ee64c82 100644 --- a/Clario/Clario.csproj +++ b/Clario/Clario.csproj @@ -27,6 +27,8 @@ + + diff --git a/Clario/Clario.parcel b/Clario/Clario.parcel deleted file mode 100644 index f024ba8..0000000 --- a/Clario/Clario.parcel +++ /dev/null @@ -1,30 +0,0 @@ -{ - "GeneralSettings": { - "NetProjectPath": "Clario.csproj", - "ApplicationName": "Clario", - "Version": "1.0.0", - "PackageName": { - "$type": "msbuild", - "property": "AssemblyName" - }, - "AssemblyName": { - "$type": "msbuild", - "property": "AssemblyName" - } - }, - "LinuxSettings": { - "CreateBinSymlink": "True" - }, - "Win32Settings": { - "IncludeUninstaller": "True" - }, - "MacOsSettings": { - "CreateBundle": true, - "BundleIdentifier": "com.CompanyName.Clario", - "SigningCredentialsType": "AdHoc" - }, - "PublishSettings": { - "PublishSingleFile": "True", - "ExtraBuildProperties": {} - } -} \ No newline at end of file diff --git a/Clario/Converters/AccountMaskToStringConverter.cs b/Clario/Converters/AccountMaskToStringConverter.cs index 1975fa7..69911d2 100644 --- a/Clario/Converters/AccountMaskToStringConverter.cs +++ b/Clario/Converters/AccountMaskToStringConverter.cs @@ -8,7 +8,7 @@ public class AccountMaskToStringConverter : IValueConverter { public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) { - if (value is not string mask) return string.Empty; + if (value is not string mask || string.IsNullOrWhiteSpace(mask)) return string.Empty; return $"•••• {mask}"; } diff --git a/Clario/CustomControls/DateRangePicker.axaml b/Clario/CustomControls/DateRangePicker.axaml index 9c715a2..160c99d 100644 --- a/Clario/CustomControls/DateRangePicker.axaml +++ b/Clario/CustomControls/DateRangePicker.axaml @@ -9,7 +9,7 @@ - + @@ -37,7 +37,8 @@ Text="{TemplateBinding DisplayText}" FontSize="{TemplateBinding FontSize}" Foreground="{TemplateBinding Foreground}" - VerticalAlignment="Center" /> + VerticalAlignment="Center" + TextTrimming="CharacterEllipsis"/> ("PART_Button"); _popup = e.NameScope.Find("PART_Popup"); @@ -81,7 +87,7 @@ public class DateRangePicker : TemplatedControl _calendar.SelectedDatesChanged += OnCalendarDatesChanged; - // _calendar.PointerPressed + _calendar.AddHandler(PointerReleasedEvent, OnCalendarPointerReleased, RoutingStrategies.Tunnel); SyncToCalendar(); @@ -90,8 +96,45 @@ public class DateRangePicker : TemplatedControl UpdateDisplayText(); } + private void OnCalendarPointerReleased(object? sender, PointerReleasedEventArgs e) + { + if (_calendar!.SelectionMode != CalendarSelectionMode.SingleDate) return; - private void OnButtonClick(object? sender, Avalonia.Interactivity.RoutedEventArgs e) + if (_isSyncing) return; + + if (_popup is null || !_popup.IsOpen) return; + + var newDates = _calendar!.SelectedDates.OrderBy(d => d).ToList(); + + _isSyncing = true; + try + { + SelectedDates = newDates; + + + SelectedDate = newDates.Count > 0 ? newDates[0] : null; + + UpdateDisplayText(); + + + bool shouldClose = SelectionMode switch + { + CalendarSelectionMode.SingleDate => newDates.Count >= 1, + CalendarSelectionMode.SingleRange => newDates.Count >= 2, + _ => false + }; + + if (shouldClose) + _popup.IsOpen = false; + } + finally + { + _isSyncing = false; + } + } + + + private void OnButtonClick(object? sender, RoutedEventArgs e) { if (_popup is null) return; @@ -102,10 +145,12 @@ public class DateRangePicker : TemplatedControl private void OnCalendarDatesChanged(object? sender, SelectionChangedEventArgs e) { + if (_calendar!.SelectionMode == CalendarSelectionMode.SingleDate) return; + if (_isSyncing) return; - + if (_popup is null || !_popup.IsOpen) return; - Console.WriteLine("test"); + var newDates = _calendar!.SelectedDates.OrderBy(d => d).ToList(); _isSyncing = true; diff --git a/Clario/MobileViews/MainViewMobile.axaml b/Clario/MobileViews/MainViewMobile.axaml index f27b386..1221ea6 100644 --- a/Clario/MobileViews/MainViewMobile.axaml +++ b/Clario/MobileViews/MainViewMobile.axaml @@ -3,13 +3,22 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:vm="clr-namespace:Clario.ViewModels" + xmlns:views="clr-namespace:Clario.Views" + xmlns:mobileViews="clr-namespace:Clario.MobileViews" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" x:Class="Clario.MobileViews.MainViewMobile" - x:CompileBindings="False" - Classes="mobile"> + x:DataType="vm:MainViewModel" + Classes="mobile" + x:Name="MainControl"> + + + - + + @@ -65,7 +74,7 @@ VerticalAlignment="Center" Width="52" Height="52" CornerRadius="26" - Padding="0"> + Padding="0" Command="{Binding OpenAddTransactionCommand}"> diff --git a/Clario/MobileViews/TransactionFormViewMobile.axaml b/Clario/MobileViews/TransactionFormViewMobile.axaml new file mode 100644 index 0000000..d4e59f8 --- /dev/null +++ b/Clario/MobileViews/TransactionFormViewMobile.axaml @@ -0,0 +1,440 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Clario/MobileViews/TransactionFormViewMobile.axaml.cs b/Clario/MobileViews/TransactionFormViewMobile.axaml.cs new file mode 100644 index 0000000..6322d35 --- /dev/null +++ b/Clario/MobileViews/TransactionFormViewMobile.axaml.cs @@ -0,0 +1,13 @@ +using Avalonia; +using Avalonia.Controls; +using Avalonia.Markup.Xaml; + +namespace Clario.MobileViews; + +public partial class TransactionFormViewMobile : UserControl +{ + public TransactionFormViewMobile() + { + InitializeComponent(); + } +} \ No newline at end of file diff --git a/Clario/Theme/AppTheme.axaml b/Clario/Theme/AppTheme.axaml index f72f39e..68d6d9b 100644 --- a/Clario/Theme/AppTheme.axaml +++ b/Clario/Theme/AppTheme.axaml @@ -306,21 +306,21 @@ - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -168,49 +184,63 @@ Foreground="{DynamicResource TextPrimary}" /> - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + @@ -231,50 +261,64 @@ FontSize="{StaticResource FontSizeBody}" Cursor="Hand" Content="View all →" VerticalAlignment="Center" Command="{Binding ViewAllTransactionsCommand}" /> - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + diff --git a/Clario/Views/MainView.axaml b/Clario/Views/MainView.axaml index 7367057..b3168f1 100644 --- a/Clario/Views/MainView.axaml +++ b/Clario/Views/MainView.axaml @@ -91,20 +91,12 @@ + BorderThickness="0,0,1,0" Padding="16,28,16,24" IsEnabled="{Binding !IsTransactionFormVisible}"> - - - - - - - - - + + + + diff --git a/Clario/Views/MainWindow.axaml b/Clario/Views/MainWindow.axaml index 20bd1e5..6f59576 100644 --- a/Clario/Views/MainWindow.axaml +++ b/Clario/Views/MainWindow.axaml @@ -7,6 +7,7 @@ mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" MinWidth="1000" MinHeight="600" x:Class="Clario.Views.MainWindow" + Icon="../Assets/logo-no-bg.ico" Title="Clario" x:CompileBindings="False"> diff --git a/Clario/Views/TransactionFormView.axaml b/Clario/Views/TransactionFormView.axaml index 2b1cbf0..a9984c2 100644 --- a/Clario/Views/TransactionFormView.axaml +++ b/Clario/Views/TransactionFormView.axaml @@ -4,6 +4,7 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:vm="clr-namespace:Clario.ViewModels" xmlns:cc="clr-namespace:Clario.CustomControls" + xmlns:behaviors="clr-namespace:Clario.Behaviors" mc:Ignorable="d" x:Class="Clario.Views.TransactionFormView" x:DataType="vm:TransactionFormViewModel"> @@ -87,7 +88,7 @@ CommandParameter="expense"> + Width="13" Height="13" /> + Width="13" Height="13" /> @@ -141,7 +142,11 @@ Foreground="{DynamicResource TextPrimary}" Height="54" Padding="0" - VerticalContentAlignment="Center" /> + VerticalContentAlignment="Center"> + + + + - + + + + + Padding="12,10" /> - + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Directory.Packages.props b/Directory.Packages.props index 4166dc0..9c1c6cc 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -22,5 +22,7 @@ + + \ No newline at end of file