Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions 9.0/Apps/DeveloperBalance/AppShell.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@
SegmentWidth="40" SegmentHeight="40">
<sf:SfSegmentedControl.ItemsSource>
<x:Array Type="{x:Type sf:SfSegmentItem}">
<sf:SfSegmentItem ImageSource="{StaticResource IconLight}"/>
<sf:SfSegmentItem ImageSource="{StaticResource IconDark}"/>
<sf:SfSegmentItem ImageSource="{StaticResource IconLight}" SemanticProperties.Description="Light mode"/>
<sf:SfSegmentItem ImageSource="{StaticResource IconDark}" SemanticProperties.Description="Dark mode"/>
</x:Array>
</sf:SfSegmentedControl.ItemsSource>
</sf:SfSegmentedControl>
Expand Down
3 changes: 3 additions & 0 deletions 9.0/Apps/DeveloperBalance/AppShell.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ public AppShell()
InitializeComponent();
var currentTheme = Application.Current!.RequestedTheme;
ThemeSegmentedControl.SelectedIndex = currentTheme == AppTheme.Light ? 0 : 1;
#if ANDROID || WINDOWS
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why only on Android and Windows?

SemanticProperties.SetDescription(ThemeSegmentedControl, "Theme selection");
#endif
}
public static async Task DisplaySnackbarAsync(string message)
{
Expand Down
33 changes: 33 additions & 0 deletions 9.0/Apps/DeveloperBalance/Data/TagRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,12 @@ public async Task<int> SaveItemAsync(Tag item, int projectID)
await Init();
await SaveItemAsync(item);

var isAssociated = await IsAssociated(item, projectID);
if (isAssociated)
{
return 0; // No need to save again if already associated
}

await using var connection = new SqliteConnection(Constants.DatabasePath);
await connection.OpenAsync();

Expand All @@ -212,6 +218,33 @@ public async Task<int> SaveItemAsync(Tag item, int projectID)
return await saveCmd.ExecuteNonQueryAsync();
}

/// <summary>
/// Checks if a tag is already associated with a specific project.
/// </summary>
/// <param name="item">The tag to save.</param>
/// <param name="projectID">The ID of the project.</param>
/// <returns>If tag is already associated with this project</returns>
async Task<bool> IsAssociated(Tag item, int projectID)
{
await Init();
await SaveItemAsync(item);

await using var connection = new SqliteConnection(Constants.DatabasePath);
await connection.OpenAsync();

// First check if the association already exists
var checkCmd = connection.CreateCommand();
checkCmd.CommandText = @"
SELECT COUNT(*) FROM ProjectsTags
WHERE ProjectID = @projectID AND TagID = @tagID";
checkCmd.Parameters.AddWithValue("@projectID", projectID);
checkCmd.Parameters.AddWithValue("@tagID", item.ID);

int existingCount = Convert.ToInt32(await checkCmd.ExecuteScalarAsync());

return existingCount != 0;
}

/// <summary>
/// Deletes a tag from the database.
/// </summary>
Expand Down
9 changes: 5 additions & 4 deletions 9.0/Apps/DeveloperBalance/DeveloperBalance.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net9.0-android;net9.0-ios;net9.0-maccatalyst</TargetFrameworks>
Expand All @@ -21,13 +21,14 @@
<Nullable>enable</Nullable>
<!-- https://github.com/CommunityToolkit/Maui/issues/2205 -->
<NoWarn>XC0103</NoWarn>
<MauiVersion>9.0.60</MauiVersion>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we just remove this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing it we are going to use 9.1.1 and requires to downgrade the Toolkit, but we use something from the latest versions.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

aw yea :-(

Well, we will hopefully be releasing 9.0.81 here soon into workloads

<MauiEnableXamlCBindingWithSourceCompilation>true</MauiEnableXamlCBindingWithSourceCompilation>

<!-- Display name -->
<ApplicationTitle>DeveloperBalance</ApplicationTitle>

<!-- App Identifier -->
<ApplicationId>com.companyname.developerbalance</ApplicationId>
<ApplicationId>com.companyname.developerbalance</ApplicationId>

<!-- Versions -->
<ApplicationDisplayVersion>1.0</ApplicationDisplayVersion>
Expand Down Expand Up @@ -63,7 +64,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Maui.Controls" Version="9.0.40" />
<PackageReference Include="Microsoft.Maui.Controls" Version="$(MauiVersion)" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="9.0.0" />
</ItemGroup>

Expand All @@ -72,7 +73,7 @@
<PackageReference Include="CommunityToolkit.Maui" Version="11.1.1" />
<PackageReference Include="Microsoft.Data.Sqlite.Core" Version="8.0.8" />
<PackageReference Include="SQLitePCLRaw.bundle_green" Version="2.1.10" />
<PackageReference Include="Syncfusion.Maui.Toolkit" Version="1.0.4" />
<PackageReference Include="Syncfusion.Maui.Toolkit" Version="1.0.5" />
</ItemGroup>

</Project>
20 changes: 18 additions & 2 deletions 9.0/Apps/DeveloperBalance/MauiProgram.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using CommunityToolkit.Maui;
using Microsoft.Extensions.Logging;
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Platform;
using Syncfusion.Maui.Toolkit.Hosting;

namespace DeveloperBalance;
Expand All @@ -16,9 +18,23 @@ public static MauiApp CreateMauiApp()
.ConfigureMauiHandlers(handlers =>
{
#if IOS || MACCATALYST
handlers.AddHandler<Microsoft.Maui.Controls.CollectionView, Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2>();
handlers.AddHandler<Microsoft.Maui.Controls.CollectionView, Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2>();
#endif
})
#if WINDOWS
Microsoft.Maui.Controls.Handlers.Items.CollectionViewHandler.Mapper.AppendToMapping("KeyboardAccessibleCollectionView", (handler, view) =>
{
handler.PlatformView.SingleSelectionFollowsFocus = false;
});

Microsoft.Maui.Handlers.ContentViewHandler.Mapper.AppendToMapping(nameof(Pages.Controls.CategoryChart), (handler, view) =>
{
if (view is Pages.Controls.CategoryChart && handler.PlatformView is ContentPanel contentPanel)
{
contentPanel.IsTabStop = true;
}
});
#endif
})
.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
Expand Down
7 changes: 5 additions & 2 deletions 9.0/Apps/DeveloperBalance/PageModels/MainPageModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ public partial class MainPageModel : ObservableObject, IProjectTaskPageModel
[ObservableProperty]
private string _today = DateTime.Now.ToString("dddd, MMM d");

[ObservableProperty]
private Project? selectedProject;

public bool HasCompletedTasks
=> Tasks?.Any(t => t.IsCompleted) ?? false;

Expand Down Expand Up @@ -149,8 +152,8 @@ private Task AddTask()
=> Shell.Current.GoToAsync($"task");

[RelayCommand]
private Task NavigateToProject(Project project)
=> Shell.Current.GoToAsync($"project?id={project.ID}");
private Task? NavigateToProject(Project project)
=> project is null ? null : Shell.Current.GoToAsync($"project?id={project.ID}");

[RelayCommand]
private Task NavigateToTask(ProjectTask task)
Expand Down
49 changes: 32 additions & 17 deletions 9.0/Apps/DeveloperBalance/PageModels/ProjectDetailPageModel.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using DeveloperBalance.Models;
using System.Collections.ObjectModel;
using System.Windows.Input;

namespace DeveloperBalance.PageModels;

Expand Down Expand Up @@ -34,14 +36,16 @@ public partial class ProjectDetailPageModel : ObservableObject, IQueryAttributab
[ObservableProperty]
private List<Tag> _allTags = [];

public IList<object> SelectedTags { get; set; } = new List<object>();

[ObservableProperty]
private IconData _icon;

[ObservableProperty]
bool _isBusy;

[ObservableProperty]
private List<IconData> _icons = new List<IconData>
private List<IconData> _icons = new List<IconData>
{
new IconData { Icon = FluentUI.ribbon_24_regular, Description = "Ribbon Icon" },
new IconData { Icon = FluentUI.ribbon_star_24_regular, Description = "Ribbon Star Icon" },
Expand Down Expand Up @@ -135,6 +139,10 @@ private async Task LoadData(int id)
foreach (var tag in allTags)
{
tag.IsSelected = _project.Tags.Any(t => t.ID == tag.ID);
if (tag.IsSelected)
{
SelectedTags.Add(tag);
}
}
AllTags = new(allTags);
}
Expand Down Expand Up @@ -173,14 +181,11 @@ private async Task Save()
_project.Icon = Icon.Icon ?? FluentUI.ribbon_24_regular;
await _projectRepository.SaveItemAsync(_project);

if (_project.IsNullOrNew())
foreach (var tag in AllTags)
{
foreach (var tag in AllTags)
if (tag.IsSelected)
{
if (tag.IsSelected)
{
await _tagRepository.SaveItemAsync(tag, _project.ID);
}
await _tagRepository.SaveItemAsync(tag, _project.ID);
}
}

Expand Down Expand Up @@ -235,7 +240,7 @@ private Task NavigateToTask(ProjectTask task) =>
Shell.Current.GoToAsync($"task?id={task.ID}");

[RelayCommand]
private async Task ToggleTag(Tag tag)
internal async Task ToggleTag(Tag tag)
{
tag.IsSelected = !tag.IsSelected;

Expand All @@ -244,20 +249,15 @@ private async Task ToggleTag(Tag tag)
if (tag.IsSelected)
{
await _tagRepository.SaveItemAsync(tag, _project.ID);
AllTags = new(AllTags);
await AnnouncementHelper.Announce($"{tag.Title} selected");
}
else
{
await _tagRepository.DeleteItemAsync(tag, _project.ID);
AllTags = new(AllTags);
await AnnouncementHelper.Announce($"{tag.Title} unselected");
}
}
else
{
AllTags = new(AllTags);
}

AllTags = new(AllTags);
await AnnouncementHelper.Announce($"{tag.Title} {(tag.IsSelected ? "selected" : "unselected")}");
}

[RelayCommand]
Expand All @@ -280,4 +280,19 @@ private async Task CleanTasks()
OnPropertyChanged(nameof(HasCompletedTasks));
await AppShell.DisplayToastAsync("All cleaned up!");
}
}

[RelayCommand]
private async Task SelectionChanged(object parameter)
{
if (parameter is IEnumerable<object> enumerableParameter)
{
var changed = enumerableParameter.OfType<Tag>().ToList();

if (changed.Count == 0 && SelectedTags is not null)
changed = SelectedTags.OfType<Tag>().Except(enumerableParameter.OfType<Tag>()).ToList();

if (changed.Count == 1)
await ToggleTag(changed[0]);
}
}
}
8 changes: 5 additions & 3 deletions 9.0/Apps/DeveloperBalance/PageModels/ProjectListPageModel.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#nullable disable
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using DeveloperBalance.Data;
Expand All @@ -14,6 +13,9 @@ public partial class ProjectListPageModel : ObservableObject
[ObservableProperty]
private List<Project> _projects = [];

[ObservableProperty]
private Project? selectedProject;

public ProjectListPageModel(ProjectRepository projectRepository)
{
_projectRepository = projectRepository;
Expand All @@ -26,8 +28,8 @@ private async Task Appearing()
}

[RelayCommand]
Task NavigateToProject(Project project)
=> Shell.Current.GoToAsync($"project?id={project.ID}");
Task? NavigateToProject(Project project)
=> project is null ? null : Shell.Current.GoToAsync($"project?id={project.ID}");

[RelayCommand]
async Task AddProject()
Expand Down
7 changes: 4 additions & 3 deletions 9.0/Apps/DeveloperBalance/Pages/Controls/CategoryChart.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,15 @@
HeightRequest="{OnIdiom 300, Phone=200}"
Style="{StaticResource CardStyle}">
<shimmer:SfShimmer
AutomationProperties.IsInAccessibleTree="False"
BackgroundColor="Transparent"
VerticalOptions="FillAndExpand"
VerticalOptions="Fill"
IsActive ="{Binding IsBusy}">
<shimmer:SfShimmer.CustomView>
<Grid>
<BoxView
CornerRadius="12"
VerticalOptions="FillAndExpand"
VerticalOptions="Fill"
Style="{StaticResource ShimmerCustomViewStyle}"/>
</Grid>
</shimmer:SfShimmer.CustomView>
Expand All @@ -38,7 +39,7 @@
<Label Text="{Binding Item.Title}" TextColor="{AppThemeBinding
Light={StaticResource DarkOnLightBackground},
Dark={StaticResource LightOnDarkBackground}}" FontSize="{OnIdiom 18, Phone=14}"/>
<Label Text=" : " TextColor="{AppThemeBinding
<Label Text=": " TextColor="{AppThemeBinding
Light={StaticResource DarkOnLightBackground},
Dark={StaticResource LightOnDarkBackground}}" FontSize="{OnIdiom 18, Phone=14}"/>
<Label Text="{Binding Item.Count}" TextColor="{AppThemeBinding
Expand Down
7 changes: 3 additions & 4 deletions 9.0/Apps/DeveloperBalance/Pages/Controls/ProjectCardView.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,10 @@
xmlns:shimmer="clr-namespace:Syncfusion.Maui.Toolkit.Shimmer;assembly=Syncfusion.Maui.Toolkit"
x:Class="DeveloperBalance.Pages.Controls.ProjectCardView"
Style="{StaticResource CardStyle}"
SemanticProperties.Description="{Binding Name, StringFormat='{0} Project'}"
SemanticProperties.Description="{Binding Name, StringFormat='{0}'}"
x:DataType="models:Project">
<shimmer:SfShimmer
BackgroundColor="Transparent"
VerticalOptions="FillAndExpand"
IsActive="{Binding IsBusy, Source={RelativeSource AncestorType={x:Type pageModels:MainPageModel}}, x:DataType=pageModels:IProjectTaskPageModel}">
<shimmer:SfShimmer.CustomView>
<VerticalStackLayout Spacing="15">
Expand Down Expand Up @@ -48,13 +47,13 @@
</Image>
<Label Text="{Binding Name}" TextColor="{StaticResource Gray400}" FontSize="14" TextTransform="Uppercase"/>
<Label Text="{Binding Description}" LineBreakMode="WordWrap"/>
<HorizontalStackLayout Spacing="15" BindableLayout.ItemsSource="{Binding Tags}">
<FlexLayout Wrap="Wrap" Direction="Row" AlignItems="Start" JustifyContent="Start" BindableLayout.ItemsSource="{Binding Tags}">
<BindableLayout.ItemTemplate>
<DataTemplate x:DataType="models:Tag">
<controls:TagView />
</DataTemplate>
</BindableLayout.ItemTemplate>
</HorizontalStackLayout>
</FlexLayout>
</VerticalStackLayout>
</shimmer:SfShimmer.Content>
</shimmer:SfShimmer>
Expand Down
Loading
Loading