Skip to content

Refactor CameraView.CaptureImage, CameraView.StartCameraPreview and CameraView.StopCameraPreview #2655

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

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
853cc36
Remove `CommunityToolkit.Maui.Core.Primitives` namespace
TheCodeTraveler May 6, 2025
2e799b9
Properly await Tasks
TheCodeTraveler May 6, 2025
0278fd3
Remove unused namespaces
TheCodeTraveler May 6, 2025
a6151b6
Remove `IAsynchronousHandler`
TheCodeTraveler May 6, 2025
c66df13
Update CameraViewHandler.shared.cs
TheCodeTraveler May 6, 2025
ddf4994
Update CameraViewHandler.shared.cs
TheCodeTraveler May 6, 2025
3547111
Remove unnecessary null checks
TheCodeTraveler May 6, 2025
2df36fb
Fix Sample App Compiler Error
TheCodeTraveler May 6, 2025
7ff9c41
Update src/CommunityToolkit.Maui.Camera/Views/CameraView.shared.cs
TheCodeTraveler May 6, 2025
d3b3935
Refactor StopCameraPreview
TheCodeTraveler May 6, 2025
348d6c9
Merge branch 'Refactor-CameraView.CaptureImage,-StartCameraPreview-an…
TheCodeTraveler May 6, 2025
6d881ec
Refactor `ICameraView`
TheCodeTraveler May 6, 2025
40dd627
Update Unit Tests
TheCodeTraveler May 6, 2025
e094680
Remove invalid XML comment
TheCodeTraveler May 6, 2025
1689f14
Update CameraManager.tizen.cs
TheCodeTraveler May 6, 2025
40437f4
`dotnet format`
TheCodeTraveler May 6, 2025
ed3cd56
Revert `StopCameraPreview.StopCameraPreview`
TheCodeTraveler May 6, 2025
b65f784
Update CameraViewDefaults.shared.cs
TheCodeTraveler May 6, 2025
8996040
Merge branch 'main' into Refactor-CameraView.CaptureImage,-StartCamer…
TheCodeTraveler May 29, 2025
63ed8c2
Merge branch 'main' into Refactor-CameraView.CaptureImage,-StartCamer…
TheCodeTraveler Jun 1, 2025
27d4835
Merge branch 'main' into Refactor-CameraView.CaptureImage,-StartCamer…
ne0rrmatrix Jun 4, 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
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using System.Diagnostics;
using CommunityToolkit.Maui.Core;
using CommunityToolkit.Maui.Sample.ViewModels.Views;
using CommunityToolkit.Maui.Views;

namespace CommunityToolkit.Maui.Sample.Pages.Views;

Expand Down
1 change: 0 additions & 1 deletion src/CommunityToolkit.Maui.Camera/CameraInfo.shared.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System.Text;
using CommunityToolkit.Maui.Core.Primitives;

#if IOS || MACCATALYST
using AVFoundation;
Expand Down
1 change: 0 additions & 1 deletion src/CommunityToolkit.Maui.Camera/CameraManager.android.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
using AndroidX.Camera.Lifecycle;
using AndroidX.Core.Content;
using AndroidX.Lifecycle;
using CommunityToolkit.Maui.Core.Primitives;
using CommunityToolkit.Maui.Extensions;
using Java.Lang;
using Java.Util.Concurrent;
Expand Down
1 change: 0 additions & 1 deletion src/CommunityToolkit.Maui.Camera/CameraManager.macios.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System.Diagnostics;
using AVFoundation;
using CommunityToolkit.Maui.Core.Primitives;
using CommunityToolkit.Maui.Extensions;
using CoreMedia;
using Foundation;
Expand Down
2 changes: 0 additions & 2 deletions src/CommunityToolkit.Maui.Camera/CameraManager.net.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
using CommunityToolkit.Maui.Core.Primitives;

namespace CommunityToolkit.Maui.Core;

partial class CameraManager
Expand Down
4 changes: 1 addition & 3 deletions src/CommunityToolkit.Maui.Camera/CameraManager.shared.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using CommunityToolkit.Maui.Core.Primitives;

namespace CommunityToolkit.Maui.Core;
namespace CommunityToolkit.Maui.Core;

/// <summary>
/// A class that manages the camera functionality.
Expand All @@ -15,9 +13,9 @@
/// <exception cref="NullReferenceException">Thrown when no <see cref="CameraProvider"/> can be resolved.</exception>
/// <exception cref="InvalidOperationException">Thrown when there are no cameras available.</exception>
partial class CameraManager(
IMauiContext mauiContext,

Check warning on line 16 in src/CommunityToolkit.Maui.Camera/CameraManager.shared.cs

View workflow job for this annotation

GitHub Actions / Run Benchmarks (macos-15)

Parameter 'mauiContext' is unread.

Check warning on line 16 in src/CommunityToolkit.Maui.Camera/CameraManager.shared.cs

View workflow job for this annotation

GitHub Actions / Run Benchmarks (windows-latest)

Parameter 'mauiContext' is unread.
ICameraView cameraView,

Check warning on line 17 in src/CommunityToolkit.Maui.Camera/CameraManager.shared.cs

View workflow job for this annotation

GitHub Actions / Run Benchmarks (macos-15)

Parameter 'cameraView' is unread.

Check warning on line 17 in src/CommunityToolkit.Maui.Camera/CameraManager.shared.cs

View workflow job for this annotation

GitHub Actions / Run Benchmarks (windows-latest)

Parameter 'cameraView' is unread.
ICameraProvider cameraProvider,

Check warning on line 18 in src/CommunityToolkit.Maui.Camera/CameraManager.shared.cs

View workflow job for this annotation

GitHub Actions / Run Benchmarks (macos-15)

Parameter 'cameraProvider' is unread.

Check warning on line 18 in src/CommunityToolkit.Maui.Camera/CameraManager.shared.cs

View workflow job for this annotation

GitHub Actions / Run Benchmarks (windows-latest)

Parameter 'cameraProvider' is unread.
Action onLoaded) : IDisposable
{
internal Action OnLoaded { get; } = onLoaded;
Expand Down
2 changes: 0 additions & 2 deletions src/CommunityToolkit.Maui.Camera/CameraManager.tizen.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
using CommunityToolkit.Maui.Core.Primitives;

namespace CommunityToolkit.Maui.Core;

partial class CameraManager
Expand Down
2 changes: 0 additions & 2 deletions src/CommunityToolkit.Maui.Camera/CameraManager.windows.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
using System.Runtime.Versioning;
using CommunityToolkit.Maui.Core.Primitives;
using CommunityToolkit.Maui.Extensions;
using Microsoft.Maui.Controls.PlatformConfiguration;
using Microsoft.UI.Xaml.Controls;
using Windows.Media.Capture;
using Windows.Media.Capture.Frames;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
using Android.Content.PM;
using AndroidX.Camera.Core;
using CommunityToolkit.Maui.Core;
using CommunityToolkit.Maui.Core.Primitives;

namespace CommunityToolkit.Maui.Extensions;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using AVFoundation;
using CommunityToolkit.Maui.Core;
using CommunityToolkit.Maui.Core.Primitives;

namespace CommunityToolkit.Maui.Extensions;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,7 @@ public partial class CameraViewHandler : ViewHandler<ICameraView, NativePlatform
/// The currently defined mappings between commands on the <see cref="ICameraView"/> and
/// commands on the <see cref="NativePlatformCameraPreviewView"/>.
/// </summary>
public static CommandMapper<ICameraView, CameraViewHandler> CommandMapper = new(ViewCommandMapper)
{
[nameof(ICameraView.CaptureImage)] = MapCaptureImage,
[nameof(ICameraView.StartCameraPreview)] = MapStartCameraPreview,
[nameof(ICameraView.StopCameraPreview)] = MapStopCameraPreview
};
public static CommandMapper<ICameraView, CameraViewHandler> CommandMapper = new(ViewCommandMapper);

readonly ICameraProvider cameraProvider = IPlatformApplication.Current?.Services.GetRequiredService<ICameraProvider>() ?? throw new CameraException($"{nameof(CameraProvider)} not found");

Expand Down Expand Up @@ -66,6 +61,9 @@ public void Dispose()
GC.SuppressFinalize(this);
}

internal CameraManager CameraManager => cameraManager
?? throw new InvalidOperationException($"{nameof(CameraManager)} cannot be used until the native view has been created");

/// <summary>
/// Creates a platform-specific view that will be rendered on that platform.
/// </summary>
Expand All @@ -74,7 +72,7 @@ protected override NativePlatformCameraPreviewView CreatePlatformView()
ArgumentNullException.ThrowIfNull(MauiContext);
cameraManager = new(MauiContext, VirtualView, cameraProvider, () => Init(VirtualView));

return (NativePlatformCameraPreviewView)cameraManager.CreatePlatformView();
return (NativePlatformCameraPreviewView)CameraManager.CreatePlatformView();

// When camera is loaded(switched), map the current flash mode to the platform view,
// reset the zoom factor to 1
Expand All @@ -90,8 +88,8 @@ protected override async void ConnectHandler(NativePlatformCameraPreviewView pla
{
base.ConnectHandler(platformView);

await (cameraManager?.ArePermissionsGranted() ?? Task.CompletedTask);
await (cameraManager?.ConnectCamera(CancellationToken.None) ?? Task.CompletedTask);
await CameraManager.ArePermissionsGranted();
await CameraManager.ConnectCamera(CancellationToken.None);
await cameraProvider.RefreshAvailableCameras(CancellationToken.None);
}

Expand Down Expand Up @@ -121,55 +119,38 @@ static async void MapIsAvailable(CameraViewHandler handler, ICameraView view)
static void MapIsAvailable(CameraViewHandler handler, ICameraView view)
#endif
{
var cameraAvailability = (ICameraView)handler.VirtualView;
var cameraView = (ICameraView)handler.VirtualView;

#if ANDROID
cameraAvailability.UpdateAvailability(handler.Context);
cameraView.UpdateAvailability(handler.Context);
#elif WINDOWS
await cameraAvailability.UpdateAvailability(CancellationToken.None);
await cameraView.UpdateAvailability(CancellationToken.None);
#elif IOS || MACCATALYST
cameraAvailability.UpdateAvailability();
cameraView.UpdateAvailability();
#elif TIZEN
throw new NotSupportedException("Tizen is not yet supported");
#elif NET
throw new NotSupportedException("A specific platform is required, eg net-ios, net-android, net-maccatalyst, net-windows");
#endif
}

static async void MapCaptureImage(CameraViewHandler handler, ICameraView view, object? arg3)
{
await (handler.cameraManager?.TakePicture(CancellationToken.None) ?? ValueTask.CompletedTask);
view.HandlerCompleteTCS.SetResult();
}

static async void MapStartCameraPreview(CameraViewHandler handler, ICameraView view, object? arg3)
{
await (handler.cameraManager?.StartCameraPreview(CancellationToken.None) ?? Task.CompletedTask);
view.HandlerCompleteTCS.SetResult();
}

static async void MapImageCaptureResolution(CameraViewHandler handler, ICameraView view)
{
await (handler.cameraManager?.UpdateCaptureResolution(view.ImageCaptureResolution, CancellationToken.None) ?? ValueTask.CompletedTask);
await handler.CameraManager.UpdateCaptureResolution(view.ImageCaptureResolution, CancellationToken.None);
}

static async void MapSelectedCamera(CameraViewHandler handler, ICameraView view)
{
await (handler.cameraManager?.UpdateCurrentCamera(view.SelectedCamera, CancellationToken.None) ?? ValueTask.CompletedTask);
}

static void MapStopCameraPreview(CameraViewHandler handler, ICameraView view, object? arg3)
{
handler.cameraManager?.StopCameraPreview();
await handler.CameraManager.UpdateCurrentCamera(view.SelectedCamera, CancellationToken.None);
}

static void MapCameraFlashMode(CameraViewHandler handler, ICameraView view)
{
handler.cameraManager?.UpdateFlashMode(view.CameraFlashMode);
handler.CameraManager.UpdateFlashMode(view.CameraFlashMode);
}

static void MapZoomFactor(CameraViewHandler handler, ICameraView view)
{
handler.cameraManager?.UpdateZoom(view.ZoomFactor);
handler.CameraManager.UpdateZoom(view.ZoomFactor);
}
}

This file was deleted.

33 changes: 15 additions & 18 deletions src/CommunityToolkit.Maui.Camera/Interfaces/ICameraView.shared.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
using CommunityToolkit.Maui.Camera;
using CommunityToolkit.Maui.Core.Primitives;

namespace CommunityToolkit.Maui.Core;
namespace CommunityToolkit.Maui.Core;

/// <summary>
/// Represents a visual element that provides the ability to show a camera preview and capture images.
/// </summary>
public interface ICameraView : IView, IAsynchronousHandler
public interface ICameraView : IView
{
/// <summary>
/// Gets the <see cref="CameraFlashMode"/>.
Expand Down Expand Up @@ -51,18 +48,6 @@ public interface ICameraView : IView, IAsynchronousHandler
/// </summary>
bool IsBusy { get; internal set; }

/// <summary>
/// Occurs when an image is captured by the camera.
/// </summary>
/// <param name="imageData">The image data held within a <see cref="Stream"/>.</param>
void OnMediaCaptured(Stream imageData);

/// <summary>
/// Occurs when an image capture fails.
/// </summary>
/// <param name="failureReason">A string containing the reason why the capture attempt failed.</param>
void OnMediaCapturedFailed(string failureReason);

/// <summary>
/// Triggers the camera to capture an image.
/// </summary>
Expand All @@ -79,7 +64,7 @@ public interface ICameraView : IView, IAsynchronousHandler
/// To customize the behavior of starting the camera preview, consider overriding the behavior through
/// <c>CameraViewHandler.CommandMapper.ReplaceMapping(nameof(ICameraView.StartCameraPreview), ADD YOUR METHOD);</c>.
/// </remarks>
ValueTask StartCameraPreview(CancellationToken token);
Task StartCameraPreview(CancellationToken token);

/// <summary>
/// Stops the camera preview.
Expand All @@ -96,4 +81,16 @@ public interface ICameraView : IView, IAsynchronousHandler
/// <param name="token"></param>
/// <returns></returns>
ValueTask<IReadOnlyList<CameraInfo>> GetAvailableCameras(CancellationToken token);

/// <summary>
/// Occurs when an image is captured by the camera.
/// </summary>
/// <param name="imageData">The image data held within a <see cref="Stream"/>.</param>
internal void OnMediaCaptured(Stream imageData);

/// <summary>
/// Occurs when an image capture fails.
/// </summary>
/// <param name="failureReason">A string containing the reason why the capture attempt failed.</param>
internal void OnMediaCapturedFailed(string failureReason);
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace CommunityToolkit.Maui.Core.Primitives;
namespace CommunityToolkit.Maui.Core;

/// <summary>
/// Enumeration of the possible flash modes supported by the camera.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace CommunityToolkit.Maui.Core.Primitives;
namespace CommunityToolkit.Maui.Core;

/// <summary>
/// Enumeration of the possible positions that a camera can be placed.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
using System.ComponentModel;
using System.Runtime.Versioning;
using System.Windows.Input;
using CommunityToolkit.Maui.Core.Primitives;
using CommunityToolkit.Maui.Views;

namespace CommunityToolkit.Maui.Core;

/// <summary>Default Values for <see cref="ICameraView"/>"/></summary>
Expand Down Expand Up @@ -47,18 +47,18 @@
internal static Command<CancellationToken> CreateCaptureImageCommand(BindableObject bindable)
{
var cameraView = (CameraView)bindable;
return new(async token => await cameraView.CaptureImage(token).ConfigureAwait(false));

Check warning on line 50 in src/CommunityToolkit.Maui.Camera/Primitives/CameraViewDefaults.shared.cs

View workflow job for this annotation

GitHub Actions / Run Benchmarks (macos-15)

This call site is reachable on: 'android' 21.0 and later, 'ios', 'maccatalyst', 'tizen', 'windows' 10.0.10240.0 and later. 'CameraView.CaptureImage(CancellationToken)' is only supported on: 'android' 21.0 and later, 'ios', 'maccatalyst', 'windows' 10.0.10240.0 and later. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1416)

Check warning on line 50 in src/CommunityToolkit.Maui.Camera/Primitives/CameraViewDefaults.shared.cs

View workflow job for this annotation

GitHub Actions / Run Benchmarks (windows-latest)

This call site is reachable on: 'android' 21.0 and later, 'ios', 'maccatalyst', 'tizen', 'windows' 10.0.10240.0 and later. 'CameraView.CaptureImage(CancellationToken)' is only supported on: 'android' 21.0 and later, 'ios', 'maccatalyst', 'windows' 10.0.10240.0 and later. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1416)
}

internal static Command<CancellationToken> CreateStartCameraPreviewCommand(BindableObject bindable)
{
var cameraView = (CameraView)bindable;
return new(async token => await cameraView.StartCameraPreview(token).ConfigureAwait(false));

Check warning on line 56 in src/CommunityToolkit.Maui.Camera/Primitives/CameraViewDefaults.shared.cs

View workflow job for this annotation

GitHub Actions / Run Benchmarks (macos-15)

This call site is reachable on: 'android' 21.0 and later, 'ios', 'maccatalyst', 'tizen', 'windows' 10.0.10240.0 and later. 'CameraView.StartCameraPreview(CancellationToken)' is only supported on: 'android' 21.0 and later, 'ios', 'maccatalyst', 'windows' 10.0.10240.0 and later. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1416)

Check warning on line 56 in src/CommunityToolkit.Maui.Camera/Primitives/CameraViewDefaults.shared.cs

View workflow job for this annotation

GitHub Actions / Run Benchmarks (windows-latest)

This call site is reachable on: 'android' 21.0 and later, 'ios', 'maccatalyst', 'tizen', 'windows' 10.0.10240.0 and later. 'CameraView.StartCameraPreview(CancellationToken)' is only supported on: 'android' 21.0 and later, 'ios', 'maccatalyst', 'windows' 10.0.10240.0 and later. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1416)
}

internal static ICommand CreateStopCameraPreviewCommand(BindableObject bindable)
{
var cameraView = (CameraView)bindable;
return new Command(token => cameraView.StopCameraPreview());
return new Command(_ => cameraView.StopCameraPreview());

Check warning on line 62 in src/CommunityToolkit.Maui.Camera/Primitives/CameraViewDefaults.shared.cs

View workflow job for this annotation

GitHub Actions / Run Benchmarks (macos-15)

This call site is reachable on: 'android' 21.0 and later, 'ios', 'maccatalyst', 'tizen', 'windows' 10.0.10240.0 and later. 'CameraView.StopCameraPreview()' is only supported on: 'android' 21.0 and later, 'ios', 'maccatalyst', 'windows' 10.0.10240.0 and later. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1416)

Check warning on line 62 in src/CommunityToolkit.Maui.Camera/Primitives/CameraViewDefaults.shared.cs

View workflow job for this annotation

GitHub Actions / Run Benchmarks (windows-latest)

This call site is reachable on: 'android' 21.0 and later, 'ios', 'maccatalyst', 'tizen', 'windows' 10.0.10240.0 and later. 'CameraView.StopCameraPreview()' is only supported on: 'android' 21.0 and later, 'ios', 'maccatalyst', 'windows' 10.0.10240.0 and later. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1416)
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace CommunityToolkit.Maui.Views;
namespace CommunityToolkit.Maui.Core;

/// <summary>
/// Event args containing all contextual information related to a media capture failure event.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace CommunityToolkit.Maui.Views;
namespace CommunityToolkit.Maui.Core;

/// <summary>
/// Event args containing all contextual information related to media capture event.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
using AndroidX.Camera.Core;
using AndroidX.Camera.Lifecycle;
using AndroidX.Core.Content;
using CommunityToolkit.Maui.Core.Primitives;
using Java.Lang;

namespace CommunityToolkit.Maui.Core;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using AVFoundation;
using CommunityToolkit.Maui.Core.Primitives;
using CoreMedia;
using CoreVideo;
using UIKit;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using CommunityToolkit.Maui.Core.Primitives;

using CommunityToolkit.Maui.Extensions;
using Windows.Devices.Enumeration;
using Windows.Media.Capture;
Expand Down
Loading
Loading