iOS: degrade gracefully where the Android-only native services are missing
Share/pick/sync calls and streams no longer throw MissingPluginException at startup; upload/download/sync-now show 'X isn't available on this platform yet'. Offline/sync mirror dir no longer uses the Android-only external dir. Info.plist: Face ID and photo library usage strings. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5.5
parent
813c613249
commit
d008185f98
@@ -1,3 +1,4 @@
|
||||
import 'package:flutter/services.dart';
|
||||
import '../providers/session_controller.dart';
|
||||
|
||||
/// The "get this account's auth header, or bail" guard every native-
|
||||
@@ -21,3 +22,57 @@ Map<String, String> baseChannelArgs(SessionController session) {
|
||||
'authHeader': requireAuthHeader(session),
|
||||
};
|
||||
}
|
||||
|
||||
/// Thrown by user-triggered native services (upload, download, sync now...)
|
||||
/// on a platform whose native side isn't implemented yet - the message is
|
||||
/// shown to the user as-is, e.g. in a snackbar.
|
||||
class NativeServiceUnavailable implements Exception {
|
||||
final String feature;
|
||||
|
||||
const NativeServiceUnavailable(this.feature);
|
||||
|
||||
@override
|
||||
String toString() => "$feature isn't available on this platform yet.";
|
||||
}
|
||||
|
||||
/// Calls [method], treating a missing native implementation (no
|
||||
/// `MethodChannel` handler registered, as on iOS until each service is
|
||||
/// built there) as "nothing to report": returns null instead of throwing
|
||||
/// `MissingPluginException`. For cold-start checks, scheduling and other
|
||||
/// calls nobody is waiting on.
|
||||
Future<T?> invokeIfAvailable<T>(
|
||||
MethodChannel channel,
|
||||
String method, [
|
||||
Object? arguments,
|
||||
]) async {
|
||||
try {
|
||||
return await channel.invokeMethod<T>(method, arguments);
|
||||
} on MissingPluginException {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// Like [invokeIfAvailable], but for an action the user just asked for:
|
||||
/// throws [NativeServiceUnavailable] naming [feature] rather than silently
|
||||
/// doing nothing.
|
||||
Future<T?> invokeOrExplain<T>(
|
||||
MethodChannel channel,
|
||||
String method,
|
||||
String feature, [
|
||||
Object? arguments,
|
||||
]) async {
|
||||
try {
|
||||
return await channel.invokeMethod<T>(method, arguments);
|
||||
} on MissingPluginException {
|
||||
throw NativeServiceUnavailable(feature);
|
||||
}
|
||||
}
|
||||
|
||||
/// [channel]'s broadcast stream mapped through [convert], with the
|
||||
/// "no native implementation" error dropped - the stream just never emits.
|
||||
Stream<T> quietEvents<T>(EventChannel channel, T Function(dynamic) convert) {
|
||||
return channel
|
||||
.receiveBroadcastStream()
|
||||
.handleError((Object _) {}, test: (e) => e is MissingPluginException)
|
||||
.map(convert);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user