Compare commits
2 commits
a4792a7a83
...
6e5355afea
| Author | SHA1 | Date | |
|---|---|---|---|
|
6e5355afea |
|||
|
c64d11e198 |
5 changed files with 125 additions and 1 deletions
|
|
@ -14,6 +14,7 @@
|
||||||
<PackageVersion Include="CommunityToolkit.Mvvm" Version="8.4.2" />
|
<PackageVersion Include="CommunityToolkit.Mvvm" Version="8.4.2" />
|
||||||
<PackageVersion Include="Material.Avalonia" Version="3.17.0" />
|
<PackageVersion Include="Material.Avalonia" Version="3.17.0" />
|
||||||
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="10.0.9" />
|
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="10.0.9" />
|
||||||
|
<PackageVersion Include="Microsoft.Maui.Essentials" Version="10.0.90" />
|
||||||
<PackageVersion Include="Xamarin.AndroidX.Browser" Version="1.8.0" />
|
<PackageVersion Include="Xamarin.AndroidX.Browser" Version="1.8.0" />
|
||||||
<PackageVersion Include="Xamarin.AndroidX.Core.SplashScreen" Version="1.2.0" />
|
<PackageVersion Include="Xamarin.AndroidX.Core.SplashScreen" Version="1.2.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,13 @@
|
||||||
<TargetFramework>net10.0</TargetFramework>
|
<TargetFramework>net10.0</TargetFramework>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<LangVersion>latest</LangVersion>
|
<LangVersion>latest</LangVersion>
|
||||||
|
<UseMaui>true</UseMaui>
|
||||||
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
|
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
|
||||||
<AssemblyVersion>1.0.1.0</AssemblyVersion>
|
<AssemblyVersion>1.0.1.0</AssemblyVersion>
|
||||||
<FileVersion>1.0.1.0</FileVersion>
|
<FileVersion>1.0.1.0</FileVersion>
|
||||||
<InformationalVersion>1.0.1-5+Branch.main.Sha.0617fc6bda7151c70559d87177e2dcfb1b60995f</InformationalVersion>
|
<InformationalVersion>1.0.1-5+Branch.main.Sha.0617fc6bda7151c70559d87177e2dcfb1b60995f</InformationalVersion>
|
||||||
<Version>1.0.1-5</Version>
|
<Version>1.0.1-5</Version>
|
||||||
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<AvaloniaResource Include="Assets\**" />
|
<AvaloniaResource Include="Assets\**" />
|
||||||
|
|
@ -24,6 +26,7 @@
|
||||||
<PackageReference Include="CommunityToolkit.Mvvm" />
|
<PackageReference Include="CommunityToolkit.Mvvm" />
|
||||||
<PackageReference Include="IdentityModel.OidcClient" />
|
<PackageReference Include="IdentityModel.OidcClient" />
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" />
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection" />
|
||||||
|
<PackageReference Include="Microsoft.Maui.Essentials" />
|
||||||
<ProjectReference Include="../../Yavsc.Abstract/Yavsc.Abstract.csproj" />
|
<ProjectReference Include="../../Yavsc.Abstract/Yavsc.Abstract.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
@ -39,4 +42,4 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="GitVersion.MsBuild" />
|
<PackageReference Include="GitVersion.MsBuild" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
||||||
27
src/PostIt/PostIt/Services/ContactService.Desktop.cs
Normal file
27
src/PostIt/PostIt/Services/ContactService.Desktop.cs
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
#if !ANDROID && !IOS
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace PostIt.Services;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Desktop stub for IContactService.
|
||||||
|
///
|
||||||
|
/// On desktop targets (Linux, macOS, Windows) MAUI Essentials
|
||||||
|
/// Contacts.Default throws NotImplementedInReferenceAssemblyException,
|
||||||
|
/// so we short-circuit with an empty list rather than trying to
|
||||||
|
/// call into the portable facade at runtime.
|
||||||
|
///
|
||||||
|
/// Future provider plug-ins (Google Contacts API, Exchange EWS,
|
||||||
|
/// CardDAV) can either replace this stub on a per-OS basis or
|
||||||
|
/// live behind their own IContactService implementation that the
|
||||||
|
/// DI container selects by configuration.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class ContactService : IContactService
|
||||||
|
{
|
||||||
|
public Task<IReadOnlyList<ContactDto>> GetDeviceContactsAsync(CancellationToken ct = default)
|
||||||
|
=> Task.FromResult<IReadOnlyList<ContactDto>>(Array.Empty<ContactDto>());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
64
src/PostIt/PostIt/Services/ContactService.Mobile.cs
Normal file
64
src/PostIt/PostIt/Services/ContactService.Mobile.cs
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
#if ANDROID || IOS
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.Maui.ApplicationModel.Communication;
|
||||||
|
using Microsoft.Maui.ApplicationModel;
|
||||||
|
using Microsoft.Maui.Devices;
|
||||||
|
|
||||||
|
namespace PostIt.Services;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Mobile implementation backed by MAUI Essentials Contacts.Default.
|
||||||
|
///
|
||||||
|
/// Compiled only for ANDROID and IOS. On desktop targets, see
|
||||||
|
/// ContactService.Desktop.cs (the stub that wins at compile time).
|
||||||
|
///
|
||||||
|
/// Note: at runtime, this class throws
|
||||||
|
/// NotImplementedInReferenceAssemblyException unless the host
|
||||||
|
/// application project also references the platform-specific
|
||||||
|
/// Microsoft.Maui.Essentials implementation (typically the
|
||||||
|
/// PostIt.Android project). On iOS the same is required via
|
||||||
|
/// PostIt.iOS. On desktop the stub is used and this file is excluded.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class ContactService : IContactService
|
||||||
|
{
|
||||||
|
public async Task<IReadOnlyList<ContactDto>> GetDeviceContactsAsync(CancellationToken ct = default)
|
||||||
|
{
|
||||||
|
if (DeviceInfo.Current.Platform == DevicePlatform.Unknown)
|
||||||
|
return Array.Empty<ContactDto>();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var status = await Permissions.RequestAsync<Permissions.ContactsRead>();
|
||||||
|
if (status != PermissionStatus.Granted)
|
||||||
|
return Array.Empty<ContactDto>();
|
||||||
|
|
||||||
|
var contacts = await Contacts.Default.GetAllAsync();
|
||||||
|
if (contacts is null) return Array.Empty<ContactDto>();
|
||||||
|
|
||||||
|
var result = new List<ContactDto>();
|
||||||
|
foreach (var c in contacts)
|
||||||
|
{
|
||||||
|
var emails = new List<string>();
|
||||||
|
if (c.Emails is not null)
|
||||||
|
{
|
||||||
|
foreach (var e in c.Emails)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(e.EmailAddress))
|
||||||
|
emails.Add(e.EmailAddress);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result.Add(new ContactDto(c.Id, c.DisplayName ?? string.Empty, emails));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
System.Diagnostics.Debug.WriteLine($"ContactService: {ex.Message}");
|
||||||
|
return Array.Empty<ContactDto>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
29
src/PostIt/PostIt/Services/IContactService.cs
Normal file
29
src/PostIt/PostIt/Services/IContactService.cs
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace PostIt.Services;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Abstraction over device contact providers (MAUI Essentials on mobile,
|
||||||
|
/// future Google/Exchange/IMAP providers).
|
||||||
|
///
|
||||||
|
/// Implementations live next to this file in platform-conditional
|
||||||
|
/// source files: ContactService.Mobile.cs (ANDROID/IOS) and
|
||||||
|
/// ContactService.Desktop.cs (everything else).
|
||||||
|
/// </summary>
|
||||||
|
public interface IContactService
|
||||||
|
{
|
||||||
|
Task<IReadOnlyList<ContactDto>> GetDeviceContactsAsync(CancellationToken ct = default);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Platform-neutral contact DTO. Source-of-truth shape for the UI layer;
|
||||||
|
/// concrete providers (MAUI Essentials today, Google Contacts API later)
|
||||||
|
/// map to this type.
|
||||||
|
/// </summary>
|
||||||
|
public sealed record ContactDto(
|
||||||
|
string Id,
|
||||||
|
string DisplayName,
|
||||||
|
IReadOnlyList<string> Emails);
|
||||||
Loading…
Add table
Add a link
Reference in a new issue