Skip to content

feat: MAUI support #9

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

Draft
wants to merge 29 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
cfbfe07
Added setup for MAUI app, before PS is working on it.
Chriztiaan Mar 11, 2025
c9bf567
Merge branch 'main' into maui
Chriztiaan Apr 10, 2025
447cc76
Merge branch 'main' into maui
Chriztiaan May 27, 2025
2c678a1
Added initial Maui package that has extension loading code and factory.
Chriztiaan Jun 5, 2025
d6d60a3
Fixed factory not working. Initial stab for loading extensions via MA…
Chriztiaan Jun 5, 2025
ace6dbf
Setup code for MAUI.
Chriztiaan Jun 9, 2025
a0750d4
Removed unsupported MAUI platforms from Demo.
Chriztiaan Jun 10, 2025
f5bf19e
Ensuring runtimes/platforms are applied to their specific builds. Set…
Chriztiaan Jun 10, 2025
28d6b9b
Priming changelogs.
Chriztiaan Jun 10, 2025
7877784
Clearing mac catalyst support from demo.
Chriztiaan Jun 11, 2025
2c78052
Converted Demo to Lists+Todos design.
Chriztiaan Jun 11, 2025
eb658d3
Changing datamodel to look similar to PowerSync App schema.
Chriztiaan Jun 11, 2025
067d126
Swapped in PowerSync db over base sqlite database.
Chriztiaan Jun 11, 2025
9b0830e
Can show data syncs between demos.
Chriztiaan Jun 11, 2025
f091b52
wip
Chriztiaan Jun 11, 2025
3c223b4
Moved both pages to use a watch query.
Chriztiaan Jun 12, 2025
ad8d205
General cleanup.
Chriztiaan Jun 12, 2025
480e35b
Added sql console. Cleanup.
Chriztiaan Jun 13, 2025
ff93bd7
Working on releasing of dev packages.
Chriztiaan Jun 13, 2025
0494423
Fixing selection issue on Android for list.
Chriztiaan Jun 13, 2025
73cc017
Filter todos by list
benitav Jun 13, 2025
dff49b8
Add Readme
benitav Jun 13, 2025
a29eb7e
Add psql note
benitav Jun 13, 2025
98b53e2
Hook up self-host-demo client with MAUI demo
benitav Jun 13, 2025
df00aea
Update readme with inspection notes
benitav Jun 13, 2025
924e8fe
Fixed connection retry crashing due to serialization issue.
Chriztiaan Jun 14, 2025
0a86c0a
Merge branch 'maui' of https://github.com/powersync-ja/powersync-dotn…
Chriztiaan Jun 14, 2025
f69e0ea
New dev release.
Chriztiaan Jun 14, 2025
d85d796
Remove known issues
benitav Jun 16, 2025
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
33 changes: 23 additions & 10 deletions .github/workflows/dev-packages.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# The version is pulled from the CHANGELOG.md file of the package.
# Add a `-dev.xxx` suffix to the version.
# Add a `-dev.xxx` suffix to the version. Example: `0.0.1-dev.1`
name: Create Dev Release

on: workflow_dispatch
Expand All @@ -24,17 +24,30 @@ jobs:
- name: Restore dependencies
run: dotnet restore

- name: Extract Version from CHANGELOG.md
- name: Extract Common Package Version from CHANGELOG.md
id: extract_version
shell: bash
run: |
VERSION=$(awk '/^## [0-9]+\.[0-9]+\.[0-9]+-dev(\.[0-9]+)?$/ {print $2; exit}' PowerSync/PowerSync.Common/CHANGELOG.md)
echo "Detected Version: $VERSION"
echo "VERSION=$VERSION" >> $GITHUB_ENV
COMMON_VERSION=$(awk '/^## [0-9]+\.[0-9]+\.[0-9]+-dev(\.[0-9]+)?$/ {print $2; exit}' PowerSync/PowerSync.Common/CHANGELOG.md)
echo "Detected Version: $COMMON_VERSION"
echo "VERSION=$COMMON_VERSION" >> $GITHUB_ENV

- name: Run Pack
run: dotnet pack -c Release -o ${{ github.workspace }}/output
- name: Run Pack For Common
run: dotnet pack PowerSync/PowerSync.Common -c Release -o ${{ github.workspace }}/output

- name: Run Push
run: dotnet nuget push ${{ github.workspace }}\output\*.nupkg --source https://api.nuget.org/v3/index.json --api-key ${{ secrets.NUGET_API_KEY }}

- name: Run Push For Common
run: dotnet nuget push ${{ github.workspace }}\output\PowerSync.Common*.nupkg --source https://api.nuget.org/v3/index.json --api-key ${{ secrets.NUGET_API_KEY }}

- name: Extract MAUI Package Version from CHANGELOG.md
id: extract_maui_version
shell: bash
run: |
MAUI_VERSION=$(awk '/^## [0-9]+\.[0-9]+\.[0-9]+-dev(\.[0-9]+)?$/ {print $2; exit}' PowerSync/PowerSync.Maui/CHANGELOG.md)
echo "Detected Version: $MAUI_VERSION"
echo "VERSION=$MAUI_VERSION" >> $GITHUB_ENV

- name: Run Pack For MAUI
run: dotnet pack PowerSync/PowerSync.Maui -c Release -o ${{ github.workspace }}/output

- name: Run Push For MAUI
run: dotnet nuget push ${{ github.workspace }}\output\PowerSync.Maui*.nupkg --source https://api.nuget.org/v3/index.json --api-key ${{ secrets.NUGET_API_KEY }}
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,9 @@ TestResults/
*.dylib
*.dll
*.so

*.xcframework
.env
*NativeLibs

# Ignore user id file
user_id.txt
8 changes: 8 additions & 0 deletions PowerSync/PowerSync.Common/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
# PowerSync.Common Changelog

## 0.0.2-dev.2


## 0.0.2-alpha.3
- Minor changes to accommodate PowerSync.MAUI package extension.

## 0.0.2-alpha.2

- Updated core extension to v0.3.14
Expand Down
9 changes: 2 additions & 7 deletions PowerSync/PowerSync.Common/Client/PowerSyncDatabase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,6 @@ public class DBAdapterSource(IDBAdapter Adapter) : IDatabaseSource
public IDBAdapter Adapter { get; init; } = Adapter;
}

public class OpenFactorySource(ISQLOpenFactory Factory) : IDatabaseSource
{
public ISQLOpenFactory Factory { get; init; } = Factory;
}

public class PowerSyncDatabaseOptions() : BasePowerSyncDatabaseOptions()
{
/// <summary>
Expand Down Expand Up @@ -115,9 +110,9 @@ public PowerSyncDatabase(PowerSyncDatabaseOptions options)
{
Database = adapterSource.Adapter;
}
else if (options.Database is OpenFactorySource factorySource)
else if (options.Database is ISQLOpenFactory factorySource)
{
Database = factorySource.Factory.OpenDatabase();
Database = factorySource.OpenDatabase();
}
else if (options.Database is SQLOpenOptions openOptions)
{
Expand Down
2 changes: 1 addition & 1 deletion PowerSync/PowerSync.Common/Client/SQLOpenFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public class SQLOpenOptions : IDatabaseSource
public string? DbLocation { get; set; }
}

public interface ISQLOpenFactory
public interface ISQLOpenFactory: IDatabaseSource
{
/// <summary>
/// Opens a connection adapter to a SQLite Database.
Expand Down
10 changes: 8 additions & 2 deletions PowerSync/PowerSync.Common/DB/Crud/SyncStatus.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,24 @@ public class SyncDataFlowStatus
[JsonProperty("uploading")]
public bool Uploading { get; set; } = false;

[JsonProperty("downloadError")]
public string? DownloadErrorMessage => DownloadError?.Message;

[JsonProperty("uploadError")]
public string? UploadErrorMessage => UploadError?.Message;

/// <summary>
/// Error during downloading (including connecting).
/// Cleared on the next successful data download.
/// </summary>
[JsonProperty("downloadError")]
[JsonIgnore]
public Exception? DownloadError { get; set; } = null;

/// <summary>
/// Error during uploading.
/// Cleared on the next successful upload.
/// </summary>
[JsonProperty("uploadError")]
[JsonIgnore]
public Exception? UploadError { get; set; } = null;
}

Expand Down
2 changes: 1 addition & 1 deletion PowerSync/PowerSync.Common/MDSQLite/MDSQLiteAdapter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ private static SqliteConnection OpenDatabase(string dbFilename)
return connection;
}

private void LoadExtension(SqliteConnection db)
protected virtual void LoadExtension(SqliteConnection db)
{
string extensionPath = PowerSyncPathResolver.GetNativeLibraryPath(AppContext.BaseDirectory);
db.EnableExtensions(true);
Expand Down
4 changes: 2 additions & 2 deletions PowerSync/PowerSync.Common/MDSQLite/MDSQLiteDBOpenFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ public class MDSQLiteOpenFactoryOptions : SQLOpenOptions
public MDSQLiteOptions? SqliteOptions { get; set; }
}

public class MDSqliteDBOpenFactory : ISQLOpenFactory
public class MDSQLiteDBOpenFactory : ISQLOpenFactory
{
private readonly MDSQLiteOpenFactoryOptions options;

public MDSqliteDBOpenFactory(MDSQLiteOpenFactoryOptions options)
public MDSQLiteDBOpenFactory(MDSQLiteOpenFactoryOptions options)
{
this.options = options;
}
Expand Down
15 changes: 8 additions & 7 deletions PowerSync/PowerSync.Common/PowerSync.Common.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>netstandard2.0;net6.0;net8.0;net9.0</TargetFrameworks>
<TargetFrameworks>netstandard2.0;net6.0;net8.0;net9.0;net8.0-ios;net8.0-android</TargetFrameworks>
<LangVersion>12</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
Expand All @@ -19,6 +19,7 @@
<PackageIcon>icon.png</PackageIcon>
<NoWarn>NU5100</NoWarn>
<PackageReadmeFile>README.md</PackageReadmeFile>
<DefaultItemExcludes>$(DefaultItemExcludes);runtimes/**/*.*;</DefaultItemExcludes>
</PropertyGroup>

<ItemGroup>
Expand All @@ -29,20 +30,20 @@
<PackageReference Include="Nito.AsyncEx" Version="5.1.2" />
<PackageReference Include="System.Threading.Channels" Version="8.0.0" />
</ItemGroup>

<!-- For monorepo, test if we can remove this in monorepo -->
<ItemGroup>

<!-- Check allows us to skip for all MAUI targets-->
<!-- For monorepo-->
<ItemGroup Condition="!$(TargetFramework.Contains('-'))">
<Content Include="runtimes\**\*.*">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>

<!-- For releasing runtimes -->
<ItemGroup>
<ItemGroup Condition="!$(TargetFramework.Contains('-'))">
<None Include="runtimes\**\*.*" Pack="true" PackagePath="runtimes\" />
</ItemGroup>



<ItemGroup>
<None Include="..\..\icon.png" Pack="true" PackagePath=""/>
<None Include="README.md" Pack="true" PackagePath=""/>
Expand Down
9 changes: 9 additions & 0 deletions PowerSync/PowerSync.Maui/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# PowerSync.Maui Changelog

## 0.0.1-dev.2

- Introduce package. Support for iOS/Android use cases.

### Platform Runtime Support Added
* MAUI iOS
* MAUI Android
57 changes: 57 additions & 0 deletions PowerSync/PowerSync.Maui/PowerSync.Maui.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>netstandard2.0;net6.0;net8.0;net9.0;net8.0-ios;net8.0-android</TargetFrameworks>
<LangVersion>12</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<PackageId>PowerSync.Maui</PackageId>
<Title>PowerSync.Maui</Title>
<Description>PowerSync.Maui is a package that enables MAUI usage for PowerSync</Description>
<Authors>PowerSync</Authors>
<owners>powersync</owners>
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
<RepositoryUrl>https://github.com/powersync-ja/powersync-dotnet</RepositoryUrl>
<PackageProjectUrl>https://powersync.com</PackageProjectUrl>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<PackageReleaseNotes>https://github.com/powersync-ja/powersync-dotnet/PowerSync/PowerSync.Maui/CHANGELOG.md</PackageReleaseNotes>
<PackageTags>powersync local-first local-storage state-management offline sql db persistence sqlite sync </PackageTags>
<PackageIcon>icon.png</PackageIcon>
<NoWarn>NU5100</NoWarn>
<PackageReadmeFile>README.md</PackageReadmeFile>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\PowerSync.Common\PowerSync.Common.csproj" />
</ItemGroup>

<ItemGroup>
<None Include="..\..\icon.png" Pack="true" PackagePath=""/>
<None Include="README.md" Pack="true" PackagePath=""/>
<None Update="Platforms\Android\Resources\values\colors.xml">
<SubType>Designer</SubType>
</None>
</ItemGroup>

<!-- For monorepo-->
<ItemGroup Condition="$(TargetFramework.Contains('-android'))">
<Content Include="Platforms\Android\**\*.*">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>

<ItemGroup Condition="$(TargetFramework.Contains('-ios'))">
<Content Include="Platforms\iOS\NativeLibs\powersync-sqlite-core.xcframework\**\*.*">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>

<!-- For releasing runtimes -->
<ItemGroup Condition="$(TargetFramework.Contains('-android'))">
<None Include="Platforms\Android\**\*.*" Pack="true" PackagePath="Platforms\Android" />
</ItemGroup>

<ItemGroup Condition="$(TargetFramework.Contains('-ios'))">
<None Include="Platforms\iOS\NativeLibs\powersync-sqlite-core.xcframework\**\*.*" Pack="true" PackagePath="Platforms\iOS" />
</ItemGroup>
</Project>
5 changes: 5 additions & 0 deletions PowerSync/PowerSync.Maui/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# PowerSync SDK .NET MAUI

## Usage

TBD Factory Example
42 changes: 42 additions & 0 deletions PowerSync/PowerSync.Maui/SQLite/MAUISQLiteAdapter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
namespace PowerSync.Maui.SQLite;

using Microsoft.Data.Sqlite;
using PowerSync.Common.MDSQLite;

// iOS specific imports
#if IOS
using Foundation;
#endif

public class MAUISQLiteAdapter : MDSQLiteAdapter
{
public MAUISQLiteAdapter(MDSQLiteAdapterOptions options) : base(options)
{
}

protected override void LoadExtension(SqliteConnection db)
{
db.EnableExtensions(true);

#if IOS
LoadExtensionIOS(db);
#elif ANDROID
db.LoadExtension("libpowersync");
#endif
}

private void LoadExtensionIOS(SqliteConnection db)
{
#if IOS
var bundlePath = Foundation.NSBundle.MainBundle.BundlePath;
var filePath =
Path.Combine(bundlePath, "Frameworks", "powersync-sqlite-core.framework", "powersync-sqlite-core");

using var loadExtension = db.CreateCommand();
loadExtension.CommandText = "SELECT load_extension(@path, @entryPoint)";
loadExtension.Parameters.AddWithValue("@path", filePath);
loadExtension.Parameters.AddWithValue("@entryPoint", "sqlite3_powersync_init");
loadExtension.ExecuteNonQuery();
#endif
}
}
26 changes: 26 additions & 0 deletions PowerSync/PowerSync.Maui/SQLite/MAUISQLiteDBOpenFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using PowerSync.Common.DB;

namespace PowerSync.Maui.SQLite;

using PowerSync.Common.Client;
using PowerSync.Common.MDSQLite;


public class MAUISQLiteDBOpenFactory : ISQLOpenFactory
{
private readonly MDSQLiteOpenFactoryOptions options;

public MAUISQLiteDBOpenFactory(MDSQLiteOpenFactoryOptions options)
{
this.options = options;
}

public IDBAdapter OpenDatabase()
{
return new MAUISQLiteAdapter(new MDSQLiteAdapterOptions
{
Name = options.DbFilename,
SqliteOptions = options.SqliteOptions
});
}
}
Loading