import 'dart:io'; import 'package:flutter/services.dart'; class TvPickerHandler { final String packageName; final String label; const TvPickerHandler({ required this.packageName, required this.label, }); } class TvMediaPickerUnavailable implements Exception { final String message; final List handlers; const TvMediaPickerUnavailable({ required this.message, required this.handlers, }); } class TvMediaPickerService { TvMediaPickerService._(); static final TvMediaPickerService instance = TvMediaPickerService._(); static const MethodChannel _channel = MethodChannel('jamshalat/tv_media_picker'); Future> pickImages({ required bool allowMultiple, }) async { if (!Platform.isAndroid) return const []; try { final raw = await _channel.invokeMethod>( 'pickImages', {'allowMultiple': allowMultiple}, ); if (raw == null) return const []; return raw .map((item) => item?.toString() ?? '') .where((path) => path.isNotEmpty) .toList(growable: false); } on PlatformException catch (error) { if (error.code == 'NO_PICKER') { throw TvMediaPickerUnavailable( message: error.message ?? 'Tidak ada aplikasi pemilih file yang kompatibel di perangkat.', handlers: _parseHandlers(error.details), ); } rethrow; } } Future> listPickers() async { if (!Platform.isAndroid) return const []; final raw = await _channel.invokeMethod>('listPickers'); return _parseHandlers(raw); } List _parseHandlers(dynamic raw) { if (raw is! List) return const []; final handlers = []; for (final item in raw) { if (item is! Map) continue; final packageName = item['packageName']?.toString() ?? ''; final label = item['label']?.toString() ?? ''; if (packageName.isEmpty) continue; handlers.add( TvPickerHandler( packageName: packageName, label: label.isEmpty ? packageName : label, ), ); } return handlers; } }