major update

This commit is contained in:
Fabian Freund
2025-03-03 15:15:05 +01:00
parent 200c82a442
commit 20bdc4df3e
103 changed files with 2664 additions and 783 deletions
@@ -7,7 +7,7 @@ class GeckoBrowserService {
GeckoBrowserService({GeckoBrowserApi? api}) : _api = api ?? _apiInstance;
Future<void> showNativeFragment() {
Future<bool> showNativeFragment() {
return _api.showNativeFragment();
}
@@ -0,0 +1,56 @@
import 'dart:async';
import 'package:flutter/services.dart';
import 'package:flutter_mozilla_components/src/domain/entities/turndown_result.dart';
import 'package:flutter_mozilla_components/src/extensions/subject.dart';
import 'package:flutter_mozilla_components/src/pigeons/gecko.g.dart';
import 'package:rxdart/rxdart.dart';
final _apiInstance = GeckoBrowserExtensionApi();
class GeckoBrowserExtensionService extends BrowserExtensionEvents {
final _feedRequest = BehaviorSubject<String>();
Stream<String> get feedRequested => _feedRequest.stream;
static Future<List<TurndownResults>> turndownHtml(
List<String> htmlList,
) async {
final markdownResult = await _apiInstance.getMarkdown(htmlList);
final results =
markdownResult
.cast()
.map(
(result) => TurndownResults(
// ignore: avoid_dynamic_calls valid
markdown: result['fullContentMarkdown'] as String,
// ignore: avoid_dynamic_calls valid
plain: result['fullContentPlain'] as String,
),
)
.toList();
return results;
}
GeckoBrowserExtensionService.setUp({
BinaryMessenger? binaryMessenger,
String messageChannelSuffix = '',
}) {
BrowserExtensionEvents.setUp(
this,
binaryMessenger: binaryMessenger,
messageChannelSuffix: messageChannelSuffix,
);
}
@override
void onFeedRequested(int timestamp, String url) {
_feedRequest.addWhenMoreRecent(timestamp, null, url);
}
void dispose() {
unawaited(_feedRequest.close());
}
}
@@ -1,25 +0,0 @@
import 'package:flutter_mozilla_components/src/domain/entities/turndown_result.dart';
import 'package:flutter_mozilla_components/src/pigeons/gecko.g.dart';
final _apiInstance = GeckoTurndownApi();
class GeckoTurndownService {
Future<List<TurndownResults>> turndownHtml(List<String> htmlList) async {
final markdownResult = await _apiInstance.getMarkdown(htmlList);
final results =
markdownResult
.cast()
.map(
(result) => TurndownResults(
// ignore: avoid_dynamic_calls valid
markdown: result['fullContentMarkdown'] as String,
// ignore: avoid_dynamic_calls valid
plain: result['fullContentPlain'] as String,
),
)
.toList();
return results;
}
}
@@ -43,6 +43,29 @@ class _GeckoViewState extends State<GeckoView> {
});
}
Future<bool> _showNativeFragment({
int maxRetries = 100,
/// Default ist about one frame
Duration retryDelay = const Duration(milliseconds: 1000 ~/ 60),
}) async {
for (int attempt = 0; attempt < maxRetries; attempt++) {
final result = await browserService.showNativeFragment();
if (result) {
debugPrint('Fragment ATTACHED after $attempt tries');
return true;
}
if (attempt < maxRetries - 1) {
await Future.delayed(retryDelay);
}
}
debugPrint('Fragment FAILED after $maxRetries tries');
return false;
}
@override
Widget build(BuildContext context) {
return PlatformViewLink(
@@ -68,13 +91,8 @@ class _GeckoViewState extends State<GeckoView> {
SchedulerBinding.instance.addPostFrameCallback((_) async {
await widget.preInitializationStep?.call();
await Future.delayed(
//Wait for two more frames just to be sure view has been initialized
Duration(milliseconds: ((1000 / 60) * 2).toInt()),
).whenComplete(() async {
await browserService.showNativeFragment();
await widget.postInitializationStep?.call();
});
await _showNativeFragment();
await widget.postInitializationStep?.call();
});
})
// ignore: discarded_futures that hos it is done in docs
@@ -1983,7 +1983,7 @@ class GeckoBrowserApi {
final String pigeonVar_messageChannelSuffix;
Future<void> showNativeFragment() async {
Future<bool> showNativeFragment() async {
final String pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoBrowserApi.showNativeFragment$pigeonVar_messageChannelSuffix';
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
pigeonVar_channelName,
@@ -2001,8 +2001,13 @@ class GeckoBrowserApi {
message: pigeonVar_replyList[1] as String?,
details: pigeonVar_replyList[2],
);
} else if (pigeonVar_replyList[0] == null) {
throw PlatformException(
code: 'null-error',
message: 'Host platform returned null value for non-null return value.',
);
} else {
return;
return (pigeonVar_replyList[0] as bool?)!;
}
}
@@ -3123,11 +3128,11 @@ class GeckoPrefApi {
}
}
class GeckoTurndownApi {
/// Constructor for [GeckoTurndownApi]. The [binaryMessenger] named argument is
class GeckoBrowserExtensionApi {
/// Constructor for [GeckoBrowserExtensionApi]. The [binaryMessenger] named argument is
/// available for dependency injection. If it is left null, the default
/// BinaryMessenger will be used which routes to the host platform.
GeckoTurndownApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''})
GeckoBrowserExtensionApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''})
: pigeonVar_binaryMessenger = binaryMessenger,
pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : '';
final BinaryMessenger? pigeonVar_binaryMessenger;
@@ -3137,7 +3142,7 @@ class GeckoTurndownApi {
final String pigeonVar_messageChannelSuffix;
Future<List<Object>> getMarkdown(List<String> htmlList) async {
final String pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoTurndownApi.getMarkdown$pigeonVar_messageChannelSuffix';
final String pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoBrowserExtensionApi.getMarkdown$pigeonVar_messageChannelSuffix';
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
pigeonVar_channelName,
pigeonChannelCodec,
@@ -4529,3 +4534,41 @@ class GeckoDownloadsApi {
}
}
}
abstract class BrowserExtensionEvents {
static const MessageCodec<Object?> pigeonChannelCodec = _PigeonCodec();
void onFeedRequested(int timestamp, String url);
static void setUp(BrowserExtensionEvents? api, {BinaryMessenger? binaryMessenger, String messageChannelSuffix = '',}) {
messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : '';
{
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.flutter_mozilla_components.BrowserExtensionEvents.onFeedRequested$messageChannelSuffix', pigeonChannelCodec,
binaryMessenger: binaryMessenger);
if (api == null) {
pigeonVar_channel.setMessageHandler(null);
} else {
pigeonVar_channel.setMessageHandler((Object? message) async {
assert(message != null,
'Argument for dev.flutter.pigeon.flutter_mozilla_components.BrowserExtensionEvents.onFeedRequested was null.');
final List<Object?> args = (message as List<Object?>?)!;
final int? arg_timestamp = (args[0] as int?);
assert(arg_timestamp != null,
'Argument for dev.flutter.pigeon.flutter_mozilla_components.BrowserExtensionEvents.onFeedRequested was null, expected non-null int.');
final String? arg_url = (args[1] as String?);
assert(arg_url != null,
'Argument for dev.flutter.pigeon.flutter_mozilla_components.BrowserExtensionEvents.onFeedRequested was null, expected non-null String.');
try {
api.onFeedRequested(arg_timestamp!, arg_url!);
return wrapResponse(empty: true);
} on PlatformException catch (e) {
return wrapResponse(error: e);
} catch (e) {
return wrapResponse(error: PlatformException(code: 'error', message: e.toString()));
}
});
}
}
}
}