From 7d2e74d9e350aea703a83af87669626deaea49ba Mon Sep 17 00:00:00 2001 From: Aryan Parashar Date: Tue, 17 Oct 2023 16:37:55 +0530 Subject: [PATCH 1/3] Update SimpleHapticsController.iOS.cs New functions of single and double clicks have been added in the code for better expreince --- .../Haptics/SimpleHapticsController.iOS.cs | 102 ++++++++++-------- 1 file changed, 60 insertions(+), 42 deletions(-) diff --git a/src/Uno.UWP/Devices/Haptics/SimpleHapticsController.iOS.cs b/src/Uno.UWP/Devices/Haptics/SimpleHapticsController.iOS.cs index 6aaacb9967f5..eb9e2a64cc6e 100644 --- a/src/Uno.UWP/Devices/Haptics/SimpleHapticsController.iOS.cs +++ b/src/Uno.UWP/Devices/Haptics/SimpleHapticsController.iOS.cs @@ -1,48 +1,66 @@ -#nullable enable - -using System; -using System.Collections.Generic; -using UIKit; +public class HapticFeedbackManager +{ + private DateTime? lastClickTime = null; -#nullable enable + public IReadOnlyList SupportedFeedback { get; } = new SimpleHapticsControllerFeedback[] + { + new SimpleHapticsControllerFeedback(KnownSimpleHapticsControllerWaveforms.Click, TimeSpan.FromMilliseconds(100)), + new SimpleHapticsControllerFeedback(KnownSimpleHapticsControllerWaveforms.Press, TimeSpan.FromMilliseconds(300)), + new SimpleHapticsControllerFeedback(KnownSimpleHapticsControllerWaveforms.Click, TimeSpan.FromMilliseconds(50)), // Single Click + new SimpleHapticsControllerFeedback(KnownSimpleHapticsControllerWaveforms.Click, TimeSpan.FromMilliseconds(150)), // Double Click + }; -namespace Windows.Devices.Haptics -{ - public partial class SimpleHapticsController - { - public IReadOnlyList SupportedFeedback { get; } = new SimpleHapticsControllerFeedback[] - { - new SimpleHapticsControllerFeedback(KnownSimpleHapticsControllerWaveforms.Click, TimeSpan.FromMilliseconds(100)), - new SimpleHapticsControllerFeedback(KnownSimpleHapticsControllerWaveforms.Press, TimeSpan.FromMilliseconds(300)) - }; + public void SendHapticFeedback(SimpleHapticsControllerFeedback feedback) + { + if (feedback is null) + { + throw new ArgumentNullException(nameof(feedback)); + } - public void SendHapticFeedback(SimpleHapticsControllerFeedback feedback) - { - if (feedback is null) - { - throw new ArgumentNullException(nameof(feedback)); - } + var impactStyle = FeedbackToImpactStyle(feedback); + using var impact = new UIImpactFeedbackGenerator(impactStyle); + impact.Prepare(); - var impactStyle = FeedbackToImpactStyle(feedback); - using var impact = new UIImpactFeedbackGenerator(impactStyle); - impact.Prepare(); - impact.ImpactOccurred(); - } + if (feedback.Duration.TotalMilliseconds <= 100) + { + // Single Click + impact.ImpactOccurred(); + } + else if (feedback.Duration.TotalMilliseconds <= 200) + { + // Potential Double Click - Check time interval with last click + if (lastClickTime.HasValue && (DateTime.Now - lastClickTime.Value).TotalMilliseconds < 200) + { + // Double Click + impact.ImpactOccurred(); + } + else + { + // Treat as a single click if not a double click + lastClickTime = DateTime.Now; + impact.ImpactOccurred(); + } + } + else + { + // Handle other feedback types as before + impact.ImpactOccurred(); + } + } - private UIImpactFeedbackStyle FeedbackToImpactStyle(SimpleHapticsControllerFeedback feedback) - { - if (feedback.Waveform == KnownSimpleHapticsControllerWaveforms.Click) - { - return UIImpactFeedbackStyle.Light; - } - else if (feedback.Waveform == KnownSimpleHapticsControllerWaveforms.Press) - { - return UIImpactFeedbackStyle.Medium; - } - else - { - throw new NotSupportedException("Unsupported feedback waveform"); - } - } - } + private UIImpactFeedbackStyle FeedbackToImpactStyle(SimpleHapticsControllerFeedback feedback) + { + if (feedback.Waveform == KnownSimpleHapticsControllerWaveforms.Click) + { + return UIImpactFeedbackStyle.Light; + } + else if (feedback.Waveform == KnownSimpleHapticsControllerWaveforms.Press) + { + return UIImpactFeedbackStyle.Medium; + } + else + { + throw new NotSupportedException("Unsupported feedback waveform"); + } + } } From a9dae28d8068f1d6bc87267468837f24ec5924f9 Mon Sep 17 00:00:00 2001 From: Aryan Parashar Date: Tue, 17 Oct 2023 17:18:44 +0530 Subject: [PATCH 2/3] Update SimpleHapticsController.macOS.cs added the press, single click and double click features in the macOS file of the SimpleHapticsController --- .../Haptics/SimpleHapticsController.macOS.cs | 67 ++++++++++++------- 1 file changed, 44 insertions(+), 23 deletions(-) diff --git a/src/Uno.UWP/Devices/Haptics/SimpleHapticsController.macOS.cs b/src/Uno.UWP/Devices/Haptics/SimpleHapticsController.macOS.cs index c1bd423fdcb1..64ea216949bc 100644 --- a/src/Uno.UWP/Devices/Haptics/SimpleHapticsController.macOS.cs +++ b/src/Uno.UWP/Devices/Haptics/SimpleHapticsController.macOS.cs @@ -1,4 +1,4 @@ -#nullable enable +#nullable enable using System; using System.Collections.Generic; @@ -6,28 +6,49 @@ namespace Windows.Devices.Haptics { - public partial class SimpleHapticsController - { - public IReadOnlyList SupportedFeedback { get; } = new SimpleHapticsControllerFeedback[] - { - new SimpleHapticsControllerFeedback(KnownSimpleHapticsControllerWaveforms.Press, TimeSpan.FromMilliseconds(300)) - }; + public partial class SimpleHapticsController + { + public IReadOnlyList SupportedFeedback { get; } = new SimpleHapticsControllerFeedback[] + { + new SimpleHapticsControllerFeedback(KnownSimpleHapticsControllerWaveforms.Click, TimeSpan.FromMilliseconds(100)), // Single Click + new SimpleHapticsControllerFeedback(KnownSimpleHapticsControllerWaveforms.Click, TimeSpan.FromMilliseconds(150)), // Double Click + new SimpleHapticsControllerFeedback(KnownSimpleHapticsControllerWaveforms.Press, TimeSpan.FromMilliseconds(300)) + }; - public void SendHapticFeedback(SimpleHapticsControllerFeedback feedback) - { - if (feedback is null) - { - throw new ArgumentNullException(nameof(feedback)); - } + public void SendHapticFeedback(SimpleHapticsControllerFeedback feedback) + { + if (feedback is null) + { + throw new ArgumentNullException(nameof(feedback)); + } - if (feedback.Waveform != KnownSimpleHapticsControllerWaveforms.Press) - { - throw new NotSupportedException("Unsupported feedback waveform"); - } - - NSHapticFeedbackManager.DefaultPerformer.PerformFeedback( - NSHapticFeedbackPattern.Generic, - NSHapticFeedbackPerformanceTime.Default); - } - } + if (feedback.Waveform == KnownSimpleHapticsControllerWaveforms.Click) + { + // Determine if it's a single click or double click based on the duration + if (feedback.Duration.TotalMilliseconds <= 100) + { + // Single Click + NSHapticFeedbackManager.DefaultPerformer.PerformFeedback(NSHapticFeedbackPattern.Generic, NSHapticFeedbackPerformanceTime.Default); + } + else if (feedback.Duration.TotalMilliseconds <= 200) + { + // Double Click + NSHapticFeedbackManager.DefaultPerformer.PerformFeedback(NSHapticFeedbackPattern.Generic, NSHapticFeedbackPerformanceTime.Default); + NSHapticFeedbackManager.DefaultPerformer.PerformFeedback(NSHapticFeedbackPattern.Generic, NSHapticFeedbackPerformanceTime.Default); + } + else + { + throw new NotSupportedException("Unsupported feedback duration for Click waveform"); + } + } + else if (feedback.Waveform == KnownSimpleHapticsControllerWaveforms.Press) + { + NSHapticFeedbackManager.DefaultPerformer.PerformFeedback(NSHapticFeedbackPattern.Generic, NSHapticFeedbackPerformanceTime.Default); + } + else + { + throw new NotSupportedException("Unsupported feedback waveform"); + } + } + } } From a942ba26fe102b83867fc5040142d2e0cab13f46 Mon Sep 17 00:00:00 2001 From: Aryan Parashar Date: Tue, 17 Oct 2023 17:24:25 +0530 Subject: [PATCH 3/3] Update SimpleHapticsController.Android.cs features been included for the android version as well iun the base code for the PR to egt merged --- .../SimpleHapticsController.Android.cs | 127 +++++++++--------- 1 file changed, 66 insertions(+), 61 deletions(-) diff --git a/src/Uno.UWP/Devices/Haptics/SimpleHapticsController.Android.cs b/src/Uno.UWP/Devices/Haptics/SimpleHapticsController.Android.cs index 853b362aecfa..069817313bad 100644 --- a/src/Uno.UWP/Devices/Haptics/SimpleHapticsController.Android.cs +++ b/src/Uno.UWP/Devices/Haptics/SimpleHapticsController.Android.cs @@ -1,12 +1,11 @@ -#nullable enable -#pragma warning disable CS0618 // obsolete members +#nullable enable +#program warning disable CS0618 // obsolete members using System; using System.Collections.Generic; using Android.App; using Android.Views; using Android.Provider; - using Uno.Extensions; using Uno.UI; using PhoneVibrationDevice = Windows.Phone.Devices.Notification.VibrationDevice; @@ -14,65 +13,71 @@ namespace Windows.Devices.Haptics { - public partial class SimpleHapticsController - { - public IReadOnlyList SupportedFeedback { get; } = new SimpleHapticsControllerFeedback[] - { - new SimpleHapticsControllerFeedback(KnownSimpleHapticsControllerWaveforms.Click, TimeSpan.FromMilliseconds(100)), - new SimpleHapticsControllerFeedback(KnownSimpleHapticsControllerWaveforms.Press, TimeSpan.FromMilliseconds(300)) - }; + public partial class SimpleHapticsController + { + public IReadOnlyList SupportedFeedback { get; } = new SimpleHapticsControllerFeedback[] + { + new SimpleHapticsControllerFeedback(KnownSimpleHapticsControllerWaveforms.Press, TimeSpan.FromMilliseconds(300)), + new SimpleHapticsControllerFeedback(KnownSimpleHapticsControllerWaveforms.Click, TimeSpan.FromMilliseconds(100)), // Single Click + new SimpleHapticsControllerFeedback(KnownSimpleHapticsControllerWaveforms.Click, TimeSpan.FromMilliseconds(150)) // Double Click + }; - public void SendHapticFeedback(SimpleHapticsControllerFeedback feedback) - { - if (feedback is null) - { - throw new ArgumentNullException(nameof(feedback)); - } + public void SendHapticFeedback(SimpleHapticsControllerFeedback feedback) + { + if (feedback is null) + { + throw new ArgumentNullException(nameof(feedback)); + } - if (ContextHelper.Current == null) - { - throw new InvalidOperationException($"Context must be initialized before {nameof(SendHapticFeedback)} is called."); - } - try - { - var activity = (Activity)ContextHelper.Current; - var androidFeedback = FeedbackToAndroidFeedback(feedback); -#pragma warning disable CA1422 // Validate platform compatibility - bool hapticFeedbackEnabled = Settings.System.GetInt(activity.ContentResolver, Settings.System.HapticFeedbackEnabled, 0) != 0; -#pragma warning restore CA1422 // Validate platform compatibility - if (hapticFeedbackEnabled) - { - var executed = activity.Window?.DecorView.PerformHapticFeedback(androidFeedback) ?? false; - if (!executed && PhoneVibrationDevice.GetDefault() is { } vibrationDevice) - { - // Fall back to VibrationDevice - vibrationDevice.Vibrate(feedback.Duration); - } - } - } - catch (Exception ex) - { - if (this.Log().IsEnabled(LogLevel.Error)) - { - this.Log().LogError($"Could not send haptic feedback: {ex}"); - } - } - } + Vibrator vibrator = (Vibrator)Android.App.Application.Context.GetSystemService(Android.Content.Context.VibratorService); - private static FeedbackConstants FeedbackToAndroidFeedback(SimpleHapticsControllerFeedback feedback) - { - if (feedback.Waveform == KnownSimpleHapticsControllerWaveforms.Click) - { - return FeedbackConstants.ContextClick; - } - else if (feedback.Waveform == KnownSimpleHapticsControllerWaveforms.Press) - { - return FeedbackConstants.LongPress; - } - else - { - throw new NotSupportedException("Unsupported feedback waveform"); - } - } - } + if (feedback.Waveform == KnownSimpleHapticsControllerWaveforms.Press) + { + if (vibrator.HasVibrator) + { + vibrator.Vibrate((long)feedback.Duration.TotalMilliseconds); + } + else + { + throw new NotSupportedException("Device does not support vibration"); + } + } + else if (feedback.Waveform == KnownSimpleHapticsControllerWaveforms.Click) + { + if (feedback.Duration.TotalMilliseconds <= 100) + { + // Single Click + if (vibrator.HasVibrator) + { + vibrator.Vibrate(VibrationEffect.CreateOneShot((long)feedback.Duration.TotalMilliseconds, VibrationEffect.DefaultAmplitude)); + } + else + { + throw new NotSupportedException("Device does not support vibration"); + } + } + else if (feedback.Duration.TotalMilliseconds <= 200) + { + // Double Click + if (vibrator.HasVibrator) + { + long[] pattern = { 0, (long)feedback.Duration.TotalMilliseconds, 50, (long)feedback.Duration.TotalMilliseconds }; + vibrator.Vibrate(VibrationEffect.CreateWaveform(pattern, -1)); + } + else + { + throw new NotSupportedException("Device does not support vibration"); + } + } + else + { + throw new NotSupportedException("Unsupported feedback duration for Click waveform"); + } + } + else + { + throw new NotSupportedException("Unsupported feedback waveform"); + } + } + } }