feat(app-invite): isolate ContactService to mobile targets
Splits the single ContactService class (which threw PlatformNotSupportedException on non-Android/iOS targets) into a platform-conditional structure: - IContactService + ContactDto: shared abstraction in src/PostIt/PostIt/Services/IContactService.cs. ViewModels depend on this; concrete providers map their native shapes to ContactDto. - ContactService.Mobile.cs: MAUI Essentials implementation, compiled only when ANDROID or IOS is defined. Wraps Contacts.Default.GetAllAsync() with permission handling and a NotImplementedInReferenceAssemblyException safety net. - ContactService.Desktop.cs: stub returning an empty list, compiled when neither ANDROID nor IOS is defined. Replaces the 'throw PlatformNotSupportedException' path so desktop targets (PostIt.Desktop, PostIt.Browser) build and run cleanly. The Microsoft.Maui.Essentials portable facade is referenced from PostIt.csproj, but it only becomes functional when the host application project (PostIt.Android, future PostIt.iOS) also references the platform-specific implementation. No tests added: per AGENTS.md, a 'stub returns empty list' test on PostIt.Tests (net10.0 desktop target) would be cosmetic and not detect the real failure mode. Android-side tests require a working PostIt.Android project, which doesn't exist yet. Future providers (Google Contacts API, Exchange, CardDAV) plug in as additional IContactService implementations selected by DI configuration.
This commit is contained in:
parent
a8c219e0fa
commit
69a660cafb
4 changed files with 120 additions and 39 deletions
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
|
||||
Loading…
Add table
Add a link
Reference in a new issue