Skip to content

Some additional code cleanup #13

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 our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
11 changes: 3 additions & 8 deletions demos/MAUITodo/Data/NodeConnector.cs
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
using PowerSync.Common.Client;
using System.Text;
using System.Text.Json;
using PowerSync.Common.Client;
using PowerSync.Common.Client.Connection;
using PowerSync.Common.DB.Crud;

namespace MAUITodo.Data;

using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;

public class NodeConnector : IPowerSyncBackendConnector
{
private string StorageFilePath => Path.Combine(FileSystem.AppDataDirectory, "user_id.txt");
Expand Down
10 changes: 6 additions & 4 deletions demos/MAUITodo/Data/PowerSyncData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ public async Task DeleteListAsync(TodoList list)
await Db.Execute("DELETE FROM todos WHERE list_id = ?", [listId]);
await Db.Execute("DELETE FROM lists WHERE id = ?", [listId]);
}

public async Task SaveItemAsync(TodoItem item)
{
if (item.ID != "")
Expand All @@ -74,22 +75,23 @@ await Db.Execute(
item.Description,
item.Completed ? 1 : 0,
item.CompletedAt!,
UserId,
item.Completed ? UserId : null,
item.ID
]);
}
else
{
await Db.Execute(
@"INSERT INTO todos
(id, list_id, description, created_at, completed, created_by, completed_at)
VALUES (uuid(), ?, ?, datetime(), ?, ?, ?)",
(id, list_id, description, created_at, created_by, completed, completed_at, completed_by)
VALUES (uuid(), ?, ?, datetime(), ?, ?, ?, ?)",
[
item.ListId,
item.Description,
item.Completed ? 1 : 0,
UserId,
item.Completed ? 1 : 0,
item.CompletedAt!,
item.Completed ? UserId : null
]);
}
}
Expand Down
10 changes: 5 additions & 5 deletions demos/MAUITodo/Models/TodoItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,20 @@ public class TodoItem
public string ListId { get; set; } = null!;

[JsonProperty("created_at")]
public string CreatedAt { get; set; }= null!;
public string CreatedAt { get; set; } = null!;

[JsonProperty("completed_at")]
public string? CompletedAt { get; set; }

[JsonProperty("description")]
public string Description { get; set; }= null!;
public string Description { get; set; } = null!;

[JsonProperty("created_by")]
public string CreatedBy { get; set; }= null!;
public string CreatedBy { get; set; } = null!;

[JsonProperty("completed_by")]
public string CompletedBy { get; set; }= null!;
public string CompletedBy { get; set; } = null!;

[JsonProperty("completed")]
public bool Completed { get; set; } = false;
public bool Completed { get; set; }
}
22 changes: 11 additions & 11 deletions demos/MAUITodo/Views/ListsPage.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace MAUITodo.Views;

public partial class ListsPage : ContentPage
public partial class ListsPage
{
private readonly PowerSyncData database;

Expand Down Expand Up @@ -46,7 +46,7 @@ protected override async void OnAppearing()

private async void OnAddClicked(object sender, EventArgs e)
{
string name = await DisplayPromptAsync("New List", "Enter list name:");
var name = await DisplayPromptAsync("New List", "Enter list name:");
if (!string.IsNullOrWhiteSpace(name))
{
var list = new TodoList { Name = name };
Expand All @@ -56,16 +56,16 @@ private async void OnAddClicked(object sender, EventArgs e)

private async void OnDeleteClicked(object sender, EventArgs e)
{
var button = (Button)sender;
var list = (TodoList)button.CommandParameter;

bool confirm = await DisplayAlert("Confirm Delete",
$"Are you sure you want to delete the list '{list.Name}'?",
"Yes", "No");

if (confirm)
if (sender is Button button && button.CommandParameter is TodoList list)
{
await database.DeleteListAsync(list);
var confirm = await DisplayAlert("Confirm Delete",
$"Are you sure you want to delete the list '{list.Name}'?",
"Yes", "No");

if (confirm)
{
await database.DeleteListAsync(list);
}
}
}

Expand Down
44 changes: 22 additions & 22 deletions demos/MAUITodo/Views/TodoListPage.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace MAUITodo.Views;

public partial class TodoListPage : ContentPage
public partial class TodoListPage
{
private readonly PowerSyncData database;
private readonly TodoList selectedList;
Expand Down Expand Up @@ -38,11 +38,11 @@ protected override async void OnAppearing()

private async void OnAddClicked(object sender, EventArgs e)
{
string description = await DisplayPromptAsync("New Todo", "Enter todo description:");
var description = await DisplayPromptAsync("New Todo", "Enter todo description:");
if (!string.IsNullOrWhiteSpace(description))
{
var todo = new TodoItem
{
var todo = new TodoItem
{
Description = description,
ListId = selectedList.ID
};
Expand All @@ -52,30 +52,30 @@ private async void OnAddClicked(object sender, EventArgs e)

private async void OnDeleteClicked(object sender, EventArgs e)
{
var button = (Button)sender;
var todo = (TodoItem)button.CommandParameter;

bool confirm = await DisplayAlert("Confirm Delete",
$"Are you sure you want to delete '{todo.Description}'?",
"Yes", "No");

if (confirm)
if (sender is Button button && button.CommandParameter is TodoItem todo)
{
await database.DeleteItemAsync(todo);
var confirm = await DisplayAlert("Confirm Delete",
$"Are you sure you want to delete '{todo.Description}'?",
"Yes", "No");

if (confirm)
{
await database.DeleteItemAsync(todo);
}
}
}

private async void OnCheckBoxChanged(object sender, CheckedChangedEventArgs e)
{
if (sender is CheckBox checkBox &&
checkBox.Parent?.Parent?.BindingContext is TodoItem todo)
if (sender is CheckBox checkBox && checkBox.Parent?.Parent?.BindingContext is TodoItem todo)
{
if (e.Value == true && todo.CompletedAt == null)
if (e.Value && todo.CompletedAt == null)
{
todo.Completed = e.Value;
todo.CompletedAt = DateTime.UtcNow.ToString("o");
todo.CompletedAt = DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss");
Copy link
Collaborator

@Chriztiaan Chriztiaan Jul 8, 2025

Choose a reason for hiding this comment

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

This is likely the only issue I have. Since we use the ISO format across our demos.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Well, maybe - but then it seems like you'd have to do something like this:

    public async Task SaveItemAsync(TodoItem item)
    {
        if (item.ID != "")
        {
            await Db.Execute(
                @"UPDATE todos 
                  SET description = ?, 
                  completed = ?, 
                  completed_at = CASE 
                    WHEN ? = 1 AND ? IS NULL THEN datetime() 
                    ELSE NULL 
                  END,
                  completed_by = ?
                  WHERE id = ?",
                [
                    item.Description,
                    item.Completed ? 1 : 0,
                    item.Completed ? 1 : 0,
                    item.CompletedAt,
                    item.Completed ? UserId : null,
                    item.ID
                ]);
        }
        else
        {
            await Db.Execute(
                @"INSERT INTO todos 
                  (id, list_id, description, created_at, created_by, completed, completed_at, completed_by)
                  VALUES (uuid(), ?, ?, datetime(), ?, ?, 
                  CASE 
                    WHEN ? = 1 AND ? IS NULL THEN datetime() 
                    ELSE NULL 
                  END, ?)",
                [
                    item.ListId,
                    item.Description,
                    UserId,
                    item.Completed ? 1 : 0,
                    item.Completed ? 1 : 0,
                    item.CompletedAt,
                    item.Completed ? UserId : null
                ]);
        }
    }

because you only want to set CompletedAt if the item is newly marked as Completed; and to my mind that's too much business logic in the database class.

FYI I changed that date formatting in the code-behind to make it consistent with the format that datetime() is writing.

Copy link
Collaborator

Choose a reason for hiding this comment

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

An alternative would be to add a dedicated method that has sql intended only for marking as complete I guess (which would also use datetime()).

await database.SaveItemAsync(todo);
} else if (e.Value == false && todo.CompletedAt != null)
}
else if (e.Value == false && todo.CompletedAt != null)
{
todo.Completed = e.Value;
todo.CompletedAt = null; // Uncheck, clear completed time
Expand All @@ -88,16 +88,16 @@ private async void OnItemSelected(object sender, SelectionChangedEventArgs e)
{
if (e.CurrentSelection.FirstOrDefault() is TodoItem selectedItem)
{
string newDescription = await DisplayPromptAsync("Edit Todo",
"Enter new description:",
var newDescription = await DisplayPromptAsync("Edit Todo",
"Enter new description:",
initialValue: selectedItem.Description);

if (!string.IsNullOrWhiteSpace(newDescription))
{
selectedItem.Description = newDescription;
await database.SaveItemAsync(selectedItem);
}

TodoItemsCollection.SelectedItem = null;
}
}
Expand Down