garage_auth, garage_entitlements, garage_iap and garage_ui, moved out of Garage-Services and Metro-Map-Maker into one public repo. MIT, one readme, docs under docs/. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013F4NWNvYcdeSgqbWMT1VQ7
51 lines
1.5 KiB
Dart
51 lines
1.5 KiB
Dart
// ignore_for_file: avoid_web_libraries_in_flutter
|
|
|
|
import "dart:js_interop";
|
|
import "dart:js_interop_unsafe";
|
|
|
|
import "package:flutter/widgets.dart";
|
|
|
|
// EyeDropper is a chromium-only api at the time of writing (no firefox, no
|
|
// safari), hence the feature check rather than just assuming its there on web.
|
|
// https://developer.mozilla.org/en-US/docs/Web/API/EyeDropper
|
|
|
|
@JS("EyeDropper")
|
|
extension type _EyeDropper._(JSObject _) implements JSObject {
|
|
external _EyeDropper();
|
|
|
|
external JSPromise<_EyeDropperResult> open();
|
|
}
|
|
|
|
extension type _EyeDropperResult._(JSObject _) implements JSObject {
|
|
external String get sRGBHex;
|
|
}
|
|
|
|
Future<bool> nativeEyedropperAvailable() async =>
|
|
globalContext.has("EyeDropper");
|
|
|
|
Future<Color?> pickNativeScreenColor() async {
|
|
try {
|
|
final result = await _EyeDropper().open().toDart;
|
|
return _parseHex(result.sRGBHex);
|
|
} catch (error, stack) {
|
|
// cancelling with escape rejects the promise with an AbortError, so this
|
|
// path is completely normal - still worth a line in the console though.
|
|
debugPrint("eyedropper: web pick ended without a colour: $error\n$stack");
|
|
return null;
|
|
}
|
|
}
|
|
|
|
Color? _parseHex(String value) {
|
|
final hex = value.replaceAll("#", "");
|
|
if (hex.length != 6) {
|
|
debugPrint("eyedropper: unexpected sRGBHex \"$value\"");
|
|
return null;
|
|
}
|
|
final parsed = int.tryParse(hex, radix: 16);
|
|
if (parsed == null) {
|
|
debugPrint("eyedropper: could not parse sRGBHex \"$value\"");
|
|
return null;
|
|
}
|
|
return Color(0xFF000000 | parsed);
|
|
}
|