diff --git a/README.md b/README.md
index e957dd6..d1eb4c8 100644
--- a/README.md
+++ b/README.md
@@ -19,7 +19,9 @@
## 🧐 What is it ?
-Gaimon is a **very simple** & **easy to use** plugin to include **Haptic feedback** in your app. It support custom pattern with `.ahap` file support.
+Gaimon is a **very simple** & **easy to use** plugin to include **Haptic feedback** in your app. It supports custom patterns with `.ahap` file support.
+
+While the custom haptic patterns and native actions are implemented for **iOS** and **Android**, Gaimon is safe to compile and use on **any platform** (Web, macOS, Windows, Linux, etc.). On unsupported platforms, it degrades gracefully by failing silently (no-op) and returning `false` for `canSupportsHaptic`.
diff --git a/example/pubspec.lock b/example/pubspec.lock
index 119f022..dc8c263 100644
--- a/example/pubspec.lock
+++ b/example/pubspec.lock
@@ -134,10 +134,10 @@ packages:
dependency: transitive
description:
name: meta
- sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394"
+ sha256: "1741988757a65eb6b36abe716829688cf01910bbf91c34354ff7ec1c3de2b349"
url: "https://pub.dev"
source: hosted
- version: "1.17.0"
+ version: "1.18.0"
path:
dependency: transitive
description:
@@ -195,10 +195,10 @@ packages:
dependency: transitive
description:
name: test_api
- sha256: "8161c84903fd860b26bfdefb7963b3f0b68fee7adea0f59ef805ecca346f0c7a"
+ sha256: "949a932224383300f01be9221c39180316445ecb8e7547f70a41a35bf421fb9e"
url: "https://pub.dev"
source: hosted
- version: "0.7.10"
+ version: "0.7.11"
vector_math:
dependency: transitive
description:
diff --git a/lib/gaimon.dart b/lib/gaimon.dart
index b254aa5..187d3a2 100644
--- a/lib/gaimon.dart
+++ b/lib/gaimon.dart
@@ -1,28 +1,47 @@
import 'dart:async';
import 'dart:io';
+import 'package:flutter/foundation.dart' show kIsWeb;
import 'package:flutter/services.dart';
import 'package:gaimon/ahap_to_waveform_converter.dart';
class Gaimon {
static const MethodChannel _channel = MethodChannel('gaimon');
+ static bool get _isAndroid => !kIsWeb && Platform.isAndroid;
+ static bool get _isIOS => !kIsWeb && Platform.isIOS;
+ static bool get _supportsMethodChannel => _isAndroid || _isIOS;
+
/// check if the device can vibrate or not
static Future get canSupportsHaptic async {
- return await _channel.invokeMethod('canSupportsHaptic');
+ if (!_supportsMethodChannel) return false;
+ try {
+ return await _channel.invokeMethod('canSupportsHaptic') ?? false;
+ } catch (_) {
+ return false;
+ }
}
/// generate a selection impact vibration
static void selection() => HapticFeedback.selectionClick();
/// generate an error impact vibration
- static void error() => _channel.invokeMethod('error');
+ static void error() {
+ if (!_supportsMethodChannel) return;
+ _channel.invokeMethod('error');
+ }
/// generate a success impact vibration
- static void success() => _channel.invokeMethod('success');
+ static void success() {
+ if (!_supportsMethodChannel) return;
+ _channel.invokeMethod('success');
+ }
/// generate a warning impact vibration
- static void warning() => _channel.invokeMethod('warning');
+ static void warning() {
+ if (!_supportsMethodChannel) return;
+ _channel.invokeMethod('warning');
+ }
/// generate a heavy impact vibration
static void heavy() => HapticFeedback.heavyImpact();
@@ -34,15 +53,26 @@ class Gaimon {
static void light() => HapticFeedback.lightImpact();
/// generate a rigid impact vibration
- static void rigid() => _channel.invokeMethod('rigid');
+ static void rigid() {
+ if (!_supportsMethodChannel) return;
+ _channel.invokeMethod('rigid');
+ }
/// generate a soft impact vibration
- static void soft() => _channel.invokeMethod('soft');
+ static void soft() {
+ if (!_supportsMethodChannel) return;
+ _channel.invokeMethod('soft');
+ }
/// generate a custom pattern impact vibration
- static void patternFromData(String data) => Platform.isAndroid
- ? _patternFromAhapToWaveform(data)
- : _channel.invokeMethod('pattern', {'data': data});
+ static void patternFromData(String data) {
+ if (!_supportsMethodChannel) return;
+ if (_isAndroid) {
+ _patternFromAhapToWaveform(data);
+ } else {
+ _channel.invokeMethod('pattern', {'data': data});
+ }
+ }
static void _patternFromAhapToWaveform(String data) {
final waveform = ahapToWaveform(data);
@@ -50,16 +80,23 @@ class Gaimon {
}
/// stop any ongoing vibration
- static void stop() => _channel.invokeMethod('stop');
+ static void stop() {
+ if (!_supportsMethodChannel) return;
+ _channel.invokeMethod('stop');
+ }
/// generate a custom pattern impact vibration from waveform (android only)
static void patternFromWaveForm(
List timings,
List amplitudes,
bool repeat,
- ) => _channel.invokeMethod('pattern', {
- 'timings': timings,
- 'amplitudes': amplitudes,
- 'repeat': repeat,
- });
+ ) {
+ if (!_supportsMethodChannel) return;
+ _channel.invokeMethod('pattern', {
+ 'timings': timings,
+ 'amplitudes': amplitudes,
+ 'repeat': repeat,
+ });
+ }
}
+
diff --git a/test/gaimon_test.dart b/test/gaimon_test.dart
new file mode 100644
index 0000000..528c8f4
--- /dev/null
+++ b/test/gaimon_test.dart
@@ -0,0 +1,28 @@
+import 'package:flutter_test/flutter_test.dart';
+import 'package:gaimon/gaimon.dart';
+
+void main() {
+ TestWidgetsFlutterBinding.ensureInitialized();
+
+ group('Gaimon Multi-platform Safety Tests', () {
+ test('canSupportsHaptic returns false on unsupported platform (macOS/test environment)', () async {
+ final supportsHaptic = await Gaimon.canSupportsHaptic;
+ expect(supportsHaptic, isFalse);
+ });
+
+ test('calling haptic actions does not throw on unsupported platforms', () {
+ expect(() => Gaimon.selection(), returnsNormally);
+ expect(() => Gaimon.error(), returnsNormally);
+ expect(() => Gaimon.success(), returnsNormally);
+ expect(() => Gaimon.warning(), returnsNormally);
+ expect(() => Gaimon.heavy(), returnsNormally);
+ expect(() => Gaimon.medium(), returnsNormally);
+ expect(() => Gaimon.light(), returnsNormally);
+ expect(() => Gaimon.rigid(), returnsNormally);
+ expect(() => Gaimon.soft(), returnsNormally);
+ expect(() => Gaimon.patternFromData('{}'), returnsNormally);
+ expect(() => Gaimon.patternFromWaveForm([100], [128], false), returnsNormally);
+ expect(() => Gaimon.stop(), returnsNormally);
+ });
+ });
+}