implemented selection api
This commit is contained in:
@@ -2,11 +2,77 @@ import 'dart:async';
|
|||||||
|
|
||||||
import 'package:flutter_mozilla_components/flutter_mozilla_components.dart';
|
import 'package:flutter_mozilla_components/flutter_mozilla_components.dart';
|
||||||
import 'package:lensai/core/logger.dart';
|
import 'package:lensai/core/logger.dart';
|
||||||
|
import 'package:lensai/features/bangs/domain/providers.dart';
|
||||||
import 'package:lensai/features/geckoview/domain/providers/tab_session.dart';
|
import 'package:lensai/features/geckoview/domain/providers/tab_session.dart';
|
||||||
|
import 'package:lensai/features/geckoview/domain/repositories/tab.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
import 'package:share_plus/share_plus.dart';
|
||||||
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
|
||||||
part 'providers.g.dart';
|
part 'providers.g.dart';
|
||||||
|
|
||||||
|
@Riverpod(keepAlive: true)
|
||||||
|
GeckoSelectionActionService selectionActionService(
|
||||||
|
SelectionActionServiceRef ref,
|
||||||
|
) {
|
||||||
|
final service = GeckoSelectionActionService.setUp();
|
||||||
|
|
||||||
|
unawaited(
|
||||||
|
service.setActions([
|
||||||
|
SearchAction((text) async {
|
||||||
|
final defaultSearchBang =
|
||||||
|
await ref.read(kagiSearchBangDataProvider.future);
|
||||||
|
|
||||||
|
if (defaultSearchBang != null) {
|
||||||
|
await ref
|
||||||
|
.read(tabRepositoryProvider.notifier)
|
||||||
|
.addTab(url: defaultSearchBang.getUrl(text));
|
||||||
|
} else {
|
||||||
|
logger.e('No default search bang found');
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
PrivateSearchAction((text) async {
|
||||||
|
final defaultSearchBang =
|
||||||
|
await ref.read(kagiSearchBangDataProvider.future);
|
||||||
|
|
||||||
|
if (defaultSearchBang != null) {
|
||||||
|
await ref.read(tabRepositoryProvider.notifier).addTab(
|
||||||
|
url: defaultSearchBang.getUrl(text),
|
||||||
|
private: true,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
logger.e('No default search bang found');
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
ShareAction((text) async {
|
||||||
|
await Share.share(text);
|
||||||
|
}),
|
||||||
|
CallAction((text) async {
|
||||||
|
final uri = Uri.tryParse('tel:${text.replaceAll(' ', '')}');
|
||||||
|
|
||||||
|
if (uri != null) {
|
||||||
|
final canLaunch = await canLaunchUrl(uri);
|
||||||
|
if (canLaunch) {
|
||||||
|
await launchUrl(uri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
EmailAction((text) async {
|
||||||
|
final uri = Uri.tryParse('mailto:$text');
|
||||||
|
|
||||||
|
if (uri != null) {
|
||||||
|
final canLaunch = await canLaunchUrl(uri);
|
||||||
|
if (canLaunch) {
|
||||||
|
await launchUrl(uri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
|
||||||
|
return service;
|
||||||
|
}
|
||||||
|
|
||||||
@Riverpod(keepAlive: true)
|
@Riverpod(keepAlive: true)
|
||||||
GeckoEventService eventService(EventServiceRef ref) {
|
GeckoEventService eventService(EventServiceRef ref) {
|
||||||
final service = GeckoEventService.setUp();
|
final service = GeckoEventService.setUp();
|
||||||
@@ -54,6 +120,6 @@ class EngineReadyState extends _$EngineReadyState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Riverpod()
|
@Riverpod()
|
||||||
TabSession selectedTabSessionNotifier(SelectedTabSessionNotifierRef ref) {
|
Raw<TabSession> selectedTabSessionNotifier(SelectedTabSessionNotifierRef ref) {
|
||||||
return ref.watch(tabSessionProvider(null).notifier);
|
return ref.watch(tabSessionProvider(null).notifier);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,23 @@ part of 'providers.dart';
|
|||||||
// RiverpodGenerator
|
// RiverpodGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
|
String _$selectionActionServiceHash() =>
|
||||||
|
r'c150f6003dcea80b18fc063dd998ab45ce27d1a1';
|
||||||
|
|
||||||
|
/// See also [selectionActionService].
|
||||||
|
@ProviderFor(selectionActionService)
|
||||||
|
final selectionActionServiceProvider =
|
||||||
|
Provider<GeckoSelectionActionService>.internal(
|
||||||
|
selectionActionService,
|
||||||
|
name: r'selectionActionServiceProvider',
|
||||||
|
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
||||||
|
? null
|
||||||
|
: _$selectionActionServiceHash,
|
||||||
|
dependencies: null,
|
||||||
|
allTransitiveDependencies: null,
|
||||||
|
);
|
||||||
|
|
||||||
|
typedef SelectionActionServiceRef = ProviderRef<GeckoSelectionActionService>;
|
||||||
String _$eventServiceHash() => r'5aa357fdf0d217677a9a66ecb50417ac18929cad';
|
String _$eventServiceHash() => r'5aa357fdf0d217677a9a66ecb50417ac18929cad';
|
||||||
|
|
||||||
/// See also [eventService].
|
/// See also [eventService].
|
||||||
@@ -21,12 +38,12 @@ final eventServiceProvider = Provider<GeckoEventService>.internal(
|
|||||||
|
|
||||||
typedef EventServiceRef = ProviderRef<GeckoEventService>;
|
typedef EventServiceRef = ProviderRef<GeckoEventService>;
|
||||||
String _$selectedTabSessionNotifierHash() =>
|
String _$selectedTabSessionNotifierHash() =>
|
||||||
r'1b0fe1afa87c0b09fc8407ceb91946fffaef5214';
|
r'ea9959e871dd0c3a8b80152eafe726c925094106';
|
||||||
|
|
||||||
/// See also [selectedTabSessionNotifier].
|
/// See also [selectedTabSessionNotifier].
|
||||||
@ProviderFor(selectedTabSessionNotifier)
|
@ProviderFor(selectedTabSessionNotifier)
|
||||||
final selectedTabSessionNotifierProvider =
|
final selectedTabSessionNotifierProvider =
|
||||||
AutoDisposeProvider<TabSession>.internal(
|
AutoDisposeProvider<Raw<TabSession>>.internal(
|
||||||
selectedTabSessionNotifier,
|
selectedTabSessionNotifier,
|
||||||
name: r'selectedTabSessionNotifierProvider',
|
name: r'selectedTabSessionNotifierProvider',
|
||||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
||||||
@@ -36,7 +53,7 @@ final selectedTabSessionNotifierProvider =
|
|||||||
allTransitiveDependencies: null,
|
allTransitiveDependencies: null,
|
||||||
);
|
);
|
||||||
|
|
||||||
typedef SelectedTabSessionNotifierRef = AutoDisposeProviderRef<TabSession>;
|
typedef SelectedTabSessionNotifierRef = AutoDisposeProviderRef<Raw<TabSession>>;
|
||||||
String _$engineReadyStateHash() => r'c682333e2e07cf0635aa7ae793a2088ca648c950';
|
String _$engineReadyStateHash() => r'c682333e2e07cf0635aa7ae793a2088ca648c950';
|
||||||
|
|
||||||
/// See also [EngineReadyState].
|
/// See also [EngineReadyState].
|
||||||
|
|||||||
@@ -607,7 +607,12 @@ class BrowserScreen extends HookConsumerWidget {
|
|||||||
SafeArea(
|
SafeArea(
|
||||||
child: Stack(
|
child: Stack(
|
||||||
children: [
|
children: [
|
||||||
GeckoView(
|
Consumer(
|
||||||
|
builder: (context, ref, child) {
|
||||||
|
//Initialize dependencies
|
||||||
|
ref.watch(selectionActionServiceProvider);
|
||||||
|
|
||||||
|
return GeckoView(
|
||||||
preInitializationStep: () async {
|
preInitializationStep: () async {
|
||||||
await ref
|
await ref
|
||||||
.read(eventServiceProvider)
|
.read(eventServiceProvider)
|
||||||
@@ -623,6 +628,8 @@ class BrowserScreen extends HookConsumerWidget {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
Positioned(
|
Positioned(
|
||||||
bottom: 0,
|
bottom: 0,
|
||||||
|
|||||||
+1
-4
@@ -8,7 +8,6 @@ import android.view.View
|
|||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import eu.lensai.flutter_mozilla_components.feature.DefaultSelectionActionDelegate
|
import eu.lensai.flutter_mozilla_components.feature.DefaultSelectionActionDelegate
|
||||||
import eu.lensai.flutter_mozilla_components.integration.ReaderViewIntegration
|
import eu.lensai.flutter_mozilla_components.integration.ReaderViewIntegration
|
||||||
import eu.lensai.flutter_mozilla_components.pigeons.SelectionAction
|
|
||||||
import mozilla.components.browser.thumbnails.BrowserThumbnails
|
import mozilla.components.browser.thumbnails.BrowserThumbnails
|
||||||
import mozilla.components.concept.engine.EngineView
|
import mozilla.components.concept.engine.EngineView
|
||||||
import mozilla.components.feature.media.fullscreen.MediaSessionFullscreenFeature
|
import mozilla.components.feature.media.fullscreen.MediaSessionFullscreenFeature
|
||||||
@@ -31,9 +30,7 @@ class BrowserFragment(private val context: Context) : BaseBrowserFragment(), Use
|
|||||||
|
|
||||||
override fun createEngine(components: Components): EngineView {
|
override fun createEngine(components: Components): EngineView {
|
||||||
return components.engine.createView(context).apply {
|
return components.engine.createView(context).apply {
|
||||||
// selectionActionDelegate = DefaultSelectionActionDelegate(
|
selectionActionDelegate = components.selectionAction
|
||||||
// components.selectionAction
|
|
||||||
// )
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -15,7 +15,6 @@ import eu.lensai.flutter_mozilla_components.pigeons.HistoryState
|
|||||||
import eu.lensai.flutter_mozilla_components.pigeons.ReaderViewController
|
import eu.lensai.flutter_mozilla_components.pigeons.ReaderViewController
|
||||||
import eu.lensai.flutter_mozilla_components.pigeons.ReaderableState
|
import eu.lensai.flutter_mozilla_components.pigeons.ReaderableState
|
||||||
import eu.lensai.flutter_mozilla_components.pigeons.SecurityInfoState
|
import eu.lensai.flutter_mozilla_components.pigeons.SecurityInfoState
|
||||||
import eu.lensai.flutter_mozilla_components.pigeons.SelectionAction
|
|
||||||
import eu.lensai.flutter_mozilla_components.pigeons.TabContentState
|
import eu.lensai.flutter_mozilla_components.pigeons.TabContentState
|
||||||
import kotlinx.coroutines.FlowPreview
|
import kotlinx.coroutines.FlowPreview
|
||||||
import kotlinx.coroutines.flow.debounce
|
import kotlinx.coroutines.flow.debounce
|
||||||
@@ -35,6 +34,7 @@ import mozilla.components.concept.engine.DefaultSettings
|
|||||||
import mozilla.components.concept.engine.Engine
|
import mozilla.components.concept.engine.Engine
|
||||||
import mozilla.components.concept.engine.EngineView
|
import mozilla.components.concept.engine.EngineView
|
||||||
import mozilla.components.concept.engine.mediaquery.PreferredColorScheme
|
import mozilla.components.concept.engine.mediaquery.PreferredColorScheme
|
||||||
|
import mozilla.components.concept.engine.selection.SelectionActionDelegate
|
||||||
import mozilla.components.concept.fetch.Client
|
import mozilla.components.concept.fetch.Client
|
||||||
import mozilla.components.feature.addons.AddonManager
|
import mozilla.components.feature.addons.AddonManager
|
||||||
import mozilla.components.feature.addons.amo.AMOAddonsProvider
|
import mozilla.components.feature.addons.amo.AMOAddonsProvider
|
||||||
@@ -79,7 +79,7 @@ open class DefaultComponents(
|
|||||||
private val applicationContext: Context,
|
private val applicationContext: Context,
|
||||||
val flutterEvents: GeckoStateEvents,
|
val flutterEvents: GeckoStateEvents,
|
||||||
val readerViewController: ReaderViewController,
|
val readerViewController: ReaderViewController,
|
||||||
val selectionAction: SelectionAction,
|
val selectionAction: SelectionActionDelegate,
|
||||||
) {
|
) {
|
||||||
companion object {
|
companion object {
|
||||||
const val SAMPLE_BROWSER_PREFERENCES = "sample_browser_preferences"
|
const val SAMPLE_BROWSER_PREFERENCES = "sample_browser_preferences"
|
||||||
|
|||||||
+16
-7
@@ -9,20 +9,23 @@ import eu.lensai.flutter_mozilla_components.api.GeckoCookieApiImpl
|
|||||||
import eu.lensai.flutter_mozilla_components.api.GeckoEngineSettingsApiImpl
|
import eu.lensai.flutter_mozilla_components.api.GeckoEngineSettingsApiImpl
|
||||||
import eu.lensai.flutter_mozilla_components.api.GeckoFindApiImpl
|
import eu.lensai.flutter_mozilla_components.api.GeckoFindApiImpl
|
||||||
import eu.lensai.flutter_mozilla_components.api.GeckoIconsApiImpl
|
import eu.lensai.flutter_mozilla_components.api.GeckoIconsApiImpl
|
||||||
|
import eu.lensai.flutter_mozilla_components.api.GeckoSelectionActionControllerImpl
|
||||||
import eu.lensai.flutter_mozilla_components.api.GeckoSessionApiImpl
|
import eu.lensai.flutter_mozilla_components.api.GeckoSessionApiImpl
|
||||||
import eu.lensai.flutter_mozilla_components.api.GeckoTabsApiImpl
|
import eu.lensai.flutter_mozilla_components.api.GeckoTabsApiImpl
|
||||||
import eu.lensai.flutter_mozilla_components.feature.CookieManagerFeature
|
import eu.lensai.flutter_mozilla_components.feature.CookieManagerFeature
|
||||||
|
import eu.lensai.flutter_mozilla_components.feature.DefaultSelectionActionDelegate
|
||||||
import eu.lensai.flutter_mozilla_components.pigeons.GeckoBrowserApi
|
import eu.lensai.flutter_mozilla_components.pigeons.GeckoBrowserApi
|
||||||
import eu.lensai.flutter_mozilla_components.pigeons.GeckoCookieApi
|
import eu.lensai.flutter_mozilla_components.pigeons.GeckoCookieApi
|
||||||
import eu.lensai.flutter_mozilla_components.pigeons.GeckoEngineSettingsApi
|
import eu.lensai.flutter_mozilla_components.pigeons.GeckoEngineSettingsApi
|
||||||
import eu.lensai.flutter_mozilla_components.pigeons.GeckoFindApi
|
import eu.lensai.flutter_mozilla_components.pigeons.GeckoFindApi
|
||||||
import eu.lensai.flutter_mozilla_components.pigeons.GeckoIconsApi
|
import eu.lensai.flutter_mozilla_components.pigeons.GeckoIconsApi
|
||||||
|
import eu.lensai.flutter_mozilla_components.pigeons.GeckoSelectionActionController
|
||||||
|
import eu.lensai.flutter_mozilla_components.pigeons.GeckoSelectionActionEvents
|
||||||
import eu.lensai.flutter_mozilla_components.pigeons.GeckoSessionApi
|
import eu.lensai.flutter_mozilla_components.pigeons.GeckoSessionApi
|
||||||
import eu.lensai.flutter_mozilla_components.pigeons.GeckoStateEvents
|
import eu.lensai.flutter_mozilla_components.pigeons.GeckoStateEvents
|
||||||
import eu.lensai.flutter_mozilla_components.pigeons.GeckoTabsApi
|
import eu.lensai.flutter_mozilla_components.pigeons.GeckoTabsApi
|
||||||
import eu.lensai.flutter_mozilla_components.pigeons.ReaderViewController
|
import eu.lensai.flutter_mozilla_components.pigeons.ReaderViewController
|
||||||
import eu.lensai.flutter_mozilla_components.pigeons.ReaderViewEvents
|
import eu.lensai.flutter_mozilla_components.pigeons.ReaderViewEvents
|
||||||
import eu.lensai.flutter_mozilla_components.pigeons.SelectionAction
|
|
||||||
|
|
||||||
import io.flutter.embedding.engine.plugins.FlutterPlugin
|
import io.flutter.embedding.engine.plugins.FlutterPlugin
|
||||||
import io.flutter.embedding.engine.plugins.activity.ActivityAware
|
import io.flutter.embedding.engine.plugins.activity.ActivityAware
|
||||||
@@ -30,6 +33,7 @@ import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
|
|||||||
import mozilla.components.browser.engine.gecko.GeckoEngine
|
import mozilla.components.browser.engine.gecko.GeckoEngine
|
||||||
import mozilla.components.browser.engine.gecko.fetch.GeckoViewFetchClient
|
import mozilla.components.browser.engine.gecko.fetch.GeckoViewFetchClient
|
||||||
import mozilla.components.concept.engine.Engine
|
import mozilla.components.concept.engine.Engine
|
||||||
|
import mozilla.components.concept.engine.selection.SelectionActionDelegate
|
||||||
import mozilla.components.experiment.NimbusExperimentDelegate
|
import mozilla.components.experiment.NimbusExperimentDelegate
|
||||||
import mozilla.components.feature.webcompat.WebCompatFeature
|
import mozilla.components.feature.webcompat.WebCompatFeature
|
||||||
import mozilla.components.lib.crash.handler.CrashHandlerService
|
import mozilla.components.lib.crash.handler.CrashHandlerService
|
||||||
@@ -45,7 +49,7 @@ class Components(
|
|||||||
private val applicationContext: Context,
|
private val applicationContext: Context,
|
||||||
flutterEvents: GeckoStateEvents,
|
flutterEvents: GeckoStateEvents,
|
||||||
readerViewController: ReaderViewController,
|
readerViewController: ReaderViewController,
|
||||||
selectionAction: SelectionAction,
|
selectionAction: SelectionActionDelegate,
|
||||||
) : DefaultComponents(
|
) : DefaultComponents(
|
||||||
applicationContext,
|
applicationContext,
|
||||||
flutterEvents,
|
flutterEvents,
|
||||||
@@ -97,10 +101,12 @@ class FlutterMozillaComponentsPlugin: FlutterPlugin, ActivityAware {
|
|||||||
_flutterPluginBinding = flutterPluginBinding
|
_flutterPluginBinding = flutterPluginBinding
|
||||||
|
|
||||||
_flutterEvents = GeckoStateEvents(_flutterPluginBinding.binaryMessenger)
|
_flutterEvents = GeckoStateEvents(_flutterPluginBinding.binaryMessenger)
|
||||||
|
val selectionActionEvents = GeckoSelectionActionEvents(_flutterPluginBinding.binaryMessenger)
|
||||||
|
|
||||||
|
val selectionActionDelegate = DefaultSelectionActionDelegate(selectionActionEvents)
|
||||||
|
|
||||||
val readerViewController =
|
val readerViewController =
|
||||||
ReaderViewController(_flutterPluginBinding.binaryMessenger)
|
ReaderViewController(_flutterPluginBinding.binaryMessenger)
|
||||||
val selectionActionDelegate = SelectionAction(_flutterPluginBinding.binaryMessenger)
|
|
||||||
|
|
||||||
GlobalComponents.setUp(
|
GlobalComponents.setUp(
|
||||||
flutterPluginBinding.applicationContext,
|
flutterPluginBinding.applicationContext,
|
||||||
@@ -109,10 +115,6 @@ class FlutterMozillaComponentsPlugin: FlutterPlugin, ActivityAware {
|
|||||||
selectionActionDelegate
|
selectionActionDelegate
|
||||||
)
|
)
|
||||||
|
|
||||||
val intent = Intent(flutterPluginBinding.applicationContext, NotificationActivity::class.java)
|
|
||||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
|
||||||
flutterPluginBinding.applicationContext.startActivity(intent)
|
|
||||||
|
|
||||||
GeckoBrowserApi.setUp(_flutterPluginBinding.binaryMessenger, GeckoBrowserApiImpl {
|
GeckoBrowserApi.setUp(_flutterPluginBinding.binaryMessenger, GeckoBrowserApiImpl {
|
||||||
showNativeFragment()
|
showNativeFragment()
|
||||||
})
|
})
|
||||||
@@ -123,11 +125,18 @@ class FlutterMozillaComponentsPlugin: FlutterPlugin, ActivityAware {
|
|||||||
GeckoIconsApi.setUp(_flutterPluginBinding.binaryMessenger, GeckoIconsApiImpl())
|
GeckoIconsApi.setUp(_flutterPluginBinding.binaryMessenger, GeckoIconsApiImpl())
|
||||||
GeckoCookieApi.setUp(_flutterPluginBinding.binaryMessenger, GeckoCookieApiImpl())
|
GeckoCookieApi.setUp(_flutterPluginBinding.binaryMessenger, GeckoCookieApiImpl())
|
||||||
GeckoFindApi.setUp(_flutterPluginBinding.binaryMessenger, GeckoFindApiImpl())
|
GeckoFindApi.setUp(_flutterPluginBinding.binaryMessenger, GeckoFindApiImpl())
|
||||||
|
GeckoSelectionActionController.setUp(_flutterPluginBinding.binaryMessenger, GeckoSelectionActionControllerImpl(
|
||||||
|
selectionActionDelegate
|
||||||
|
))
|
||||||
|
|
||||||
ReaderViewEvents.setUp(
|
ReaderViewEvents.setUp(
|
||||||
_flutterPluginBinding.binaryMessenger,
|
_flutterPluginBinding.binaryMessenger,
|
||||||
GlobalComponents.components!!.readerViewEvents
|
GlobalComponents.components!!.readerViewEvents
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val intent = Intent(flutterPluginBinding.applicationContext, NotificationActivity::class.java)
|
||||||
|
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
flutterPluginBinding.applicationContext.startActivity(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showNativeFragment() {
|
private fun showNativeFragment() {
|
||||||
|
|||||||
+2
-2
@@ -3,11 +3,11 @@ package eu.lensai.flutter_mozilla_components
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import eu.lensai.flutter_mozilla_components.pigeons.GeckoStateEvents
|
import eu.lensai.flutter_mozilla_components.pigeons.GeckoStateEvents
|
||||||
import eu.lensai.flutter_mozilla_components.pigeons.ReaderViewController
|
import eu.lensai.flutter_mozilla_components.pigeons.ReaderViewController
|
||||||
import eu.lensai.flutter_mozilla_components.pigeons.SelectionAction
|
|
||||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import mozilla.components.concept.engine.selection.SelectionActionDelegate
|
||||||
import mozilla.components.feature.addons.update.GlobalAddonDependencyProvider
|
import mozilla.components.feature.addons.update.GlobalAddonDependencyProvider
|
||||||
import mozilla.components.support.base.facts.Facts
|
import mozilla.components.support.base.facts.Facts
|
||||||
import mozilla.components.support.base.facts.processor.LogFactProcessor
|
import mozilla.components.support.base.facts.processor.LogFactProcessor
|
||||||
@@ -35,7 +35,7 @@ object GlobalComponents {
|
|||||||
applicationContext: Context,
|
applicationContext: Context,
|
||||||
flutterEvents: GeckoStateEvents,
|
flutterEvents: GeckoStateEvents,
|
||||||
readerViewController: ReaderViewController,
|
readerViewController: ReaderViewController,
|
||||||
selectionAction: SelectionAction
|
selectionAction: SelectionActionDelegate
|
||||||
) {
|
) {
|
||||||
val newComponents = Components(
|
val newComponents = Components(
|
||||||
applicationContext,
|
applicationContext,
|
||||||
|
|||||||
+13
@@ -0,0 +1,13 @@
|
|||||||
|
package eu.lensai.flutter_mozilla_components.api
|
||||||
|
|
||||||
|
import eu.lensai.flutter_mozilla_components.feature.DefaultSelectionActionDelegate
|
||||||
|
import eu.lensai.flutter_mozilla_components.pigeons.CustomSelectionAction
|
||||||
|
import eu.lensai.flutter_mozilla_components.pigeons.GeckoSelectionActionController
|
||||||
|
|
||||||
|
class GeckoSelectionActionControllerImpl(
|
||||||
|
private val selectionActionDelegate: DefaultSelectionActionDelegate
|
||||||
|
) : GeckoSelectionActionController {
|
||||||
|
override fun setActions(actions: List<CustomSelectionAction>) {
|
||||||
|
selectionActionDelegate.actions = actions.associateBy { it.id }
|
||||||
|
}
|
||||||
|
}
|
||||||
+31
-33
@@ -1,51 +1,49 @@
|
|||||||
package eu.lensai.flutter_mozilla_components.feature
|
package eu.lensai.flutter_mozilla_components.feature
|
||||||
|
|
||||||
import eu.lensai.flutter_mozilla_components.pigeons.SelectionAction
|
import android.util.Patterns
|
||||||
import kotlinx.coroutines.runBlocking
|
import eu.lensai.flutter_mozilla_components.pigeons.CustomSelectionAction
|
||||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
import eu.lensai.flutter_mozilla_components.pigeons.GeckoSelectionActionEvents
|
||||||
|
import eu.lensai.flutter_mozilla_components.pigeons.SelectionPattern
|
||||||
import mozilla.components.concept.engine.selection.SelectionActionDelegate
|
import mozilla.components.concept.engine.selection.SelectionActionDelegate
|
||||||
import kotlin.coroutines.resume
|
|
||||||
|
|
||||||
class DefaultSelectionActionDelegate(
|
class DefaultSelectionActionDelegate(
|
||||||
private val selectionAction: SelectionAction
|
private val selectionActionEvents: GeckoSelectionActionEvents,
|
||||||
|
private val actionSorter: ((Array<String>) -> Array<String>)? = null,
|
||||||
) : SelectionActionDelegate {
|
) : SelectionActionDelegate {
|
||||||
override fun getActionTitle(id: String): CharSequence? = runBlocking {
|
var actions: Map<String, CustomSelectionAction> = emptyMap();
|
||||||
suspendCancellableCoroutine { continuation ->
|
|
||||||
selectionAction.getActionTitle(id) { result ->
|
override fun getActionTitle(id: String): CharSequence? {
|
||||||
continuation.resume(result.getOrNull())
|
return actions[id]?.title;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getAllActions(): Array<String> {
|
||||||
|
return actions.values.map { x -> x.id }.toTypedArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isActionAvailable(id: String, selectedText: String): Boolean {
|
||||||
|
val action = actions[id];
|
||||||
|
if (action != null) {
|
||||||
|
return when(action.pattern) {
|
||||||
|
SelectionPattern.PHONE -> Patterns.PHONE.matcher(selectedText.trim()).matches()
|
||||||
|
SelectionPattern.EMAIL -> Patterns.EMAIL_ADDRESS.matcher(selectedText.trim()).matches()
|
||||||
|
null -> true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getAllActions(): Array<String> = runBlocking {
|
return false
|
||||||
suspendCancellableCoroutine { continuation ->
|
|
||||||
selectionAction.getAllActions() { result ->
|
|
||||||
continuation.resume(result.getOrNull()!!.toTypedArray())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun isActionAvailable(id: String, selectedText: String): Boolean = runBlocking {
|
override fun performAction(id: String, selectedText: String): Boolean {
|
||||||
suspendCancellableCoroutine { continuation ->
|
val action = actions[id];
|
||||||
selectionAction.isActionAvailable(id, selectedText) { result ->
|
if (action != null) {
|
||||||
continuation.resume(result.getOrNull()!!)
|
selectionActionEvents.performSelectionAction(id, selectedText) { _ -> }
|
||||||
}
|
return true
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun performAction(id: String, selectedText: String): Boolean = runBlocking {
|
return false
|
||||||
suspendCancellableCoroutine { continuation ->
|
|
||||||
selectionAction.performAction(id, selectedText) { result ->
|
|
||||||
continuation.resume(result.getOrNull()!!)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun sortedActions(actions: Array<String>): Array<String> = runBlocking {
|
override fun sortedActions(actions: Array<String>): Array<String> {
|
||||||
suspendCancellableCoroutine { continuation ->
|
return actionSorter?.invoke(actions) ?: actions
|
||||||
selectionAction.sortedActions(actions.toList()) { result ->
|
|
||||||
continuation.resume(result.getOrNull()!!.toTypedArray())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+140
-161
@@ -132,6 +132,17 @@ enum class CookieSameSiteStatus(val raw: Int) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum class SelectionPattern(val raw: Int) {
|
||||||
|
PHONE(0),
|
||||||
|
EMAIL(1);
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun ofRaw(raw: Int): SelectionPattern? {
|
||||||
|
return values().firstOrNull { it.raw == raw }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Translation options that map to the Gecko Translations Options.
|
* Translation options that map to the Gecko Translations Options.
|
||||||
*
|
*
|
||||||
@@ -889,6 +900,30 @@ data class FindResultState (
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Generated class from Pigeon that represents data sent in messages. */
|
||||||
|
data class CustomSelectionAction (
|
||||||
|
val id: String,
|
||||||
|
val title: String,
|
||||||
|
val pattern: SelectionPattern? = null
|
||||||
|
)
|
||||||
|
{
|
||||||
|
companion object {
|
||||||
|
fun fromList(pigeonVar_list: List<Any?>): CustomSelectionAction {
|
||||||
|
val id = pigeonVar_list[0] as String
|
||||||
|
val title = pigeonVar_list[1] as String
|
||||||
|
val pattern = pigeonVar_list[2] as SelectionPattern?
|
||||||
|
return CustomSelectionAction(id, title, pattern)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fun toList(): List<Any?> {
|
||||||
|
return listOf(
|
||||||
|
id,
|
||||||
|
title,
|
||||||
|
pattern,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
private open class GeckoPigeonCodec : StandardMessageCodec() {
|
private open class GeckoPigeonCodec : StandardMessageCodec() {
|
||||||
override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? {
|
override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? {
|
||||||
return when (type) {
|
return when (type) {
|
||||||
@@ -918,120 +953,130 @@ private open class GeckoPigeonCodec : StandardMessageCodec() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
134.toByte() -> {
|
134.toByte() -> {
|
||||||
return (readValue(buffer) as? List<Any?>)?.let {
|
return (readValue(buffer) as Long?)?.let {
|
||||||
TranslationOptions.fromList(it)
|
SelectionPattern.ofRaw(it.toInt())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
135.toByte() -> {
|
135.toByte() -> {
|
||||||
return (readValue(buffer) as? List<Any?>)?.let {
|
return (readValue(buffer) as? List<Any?>)?.let {
|
||||||
ReaderState.fromList(it)
|
TranslationOptions.fromList(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
136.toByte() -> {
|
136.toByte() -> {
|
||||||
return (readValue(buffer) as? List<Any?>)?.let {
|
return (readValue(buffer) as? List<Any?>)?.let {
|
||||||
LastMediaAccessState.fromList(it)
|
ReaderState.fromList(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
137.toByte() -> {
|
137.toByte() -> {
|
||||||
return (readValue(buffer) as? List<Any?>)?.let {
|
return (readValue(buffer) as? List<Any?>)?.let {
|
||||||
HistoryMetadataKey.fromList(it)
|
LastMediaAccessState.fromList(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
138.toByte() -> {
|
138.toByte() -> {
|
||||||
return (readValue(buffer) as? List<Any?>)?.let {
|
return (readValue(buffer) as? List<Any?>)?.let {
|
||||||
PackageCategoryValue.fromList(it)
|
HistoryMetadataKey.fromList(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
139.toByte() -> {
|
139.toByte() -> {
|
||||||
return (readValue(buffer) as? List<Any?>)?.let {
|
return (readValue(buffer) as? List<Any?>)?.let {
|
||||||
ExternalPackage.fromList(it)
|
PackageCategoryValue.fromList(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
140.toByte() -> {
|
140.toByte() -> {
|
||||||
return (readValue(buffer) as? List<Any?>)?.let {
|
return (readValue(buffer) as? List<Any?>)?.let {
|
||||||
LoadUrlFlagsValue.fromList(it)
|
ExternalPackage.fromList(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
141.toByte() -> {
|
141.toByte() -> {
|
||||||
return (readValue(buffer) as? List<Any?>)?.let {
|
return (readValue(buffer) as? List<Any?>)?.let {
|
||||||
SourceValue.fromList(it)
|
LoadUrlFlagsValue.fromList(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
142.toByte() -> {
|
142.toByte() -> {
|
||||||
return (readValue(buffer) as? List<Any?>)?.let {
|
return (readValue(buffer) as? List<Any?>)?.let {
|
||||||
TabState.fromList(it)
|
SourceValue.fromList(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
143.toByte() -> {
|
143.toByte() -> {
|
||||||
return (readValue(buffer) as? List<Any?>)?.let {
|
return (readValue(buffer) as? List<Any?>)?.let {
|
||||||
RecoverableTab.fromList(it)
|
TabState.fromList(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
144.toByte() -> {
|
144.toByte() -> {
|
||||||
return (readValue(buffer) as? List<Any?>)?.let {
|
return (readValue(buffer) as? List<Any?>)?.let {
|
||||||
RecoverableBrowserState.fromList(it)
|
RecoverableTab.fromList(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
145.toByte() -> {
|
145.toByte() -> {
|
||||||
return (readValue(buffer) as? List<Any?>)?.let {
|
return (readValue(buffer) as? List<Any?>)?.let {
|
||||||
IconRequest.fromList(it)
|
RecoverableBrowserState.fromList(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
146.toByte() -> {
|
146.toByte() -> {
|
||||||
return (readValue(buffer) as? List<Any?>)?.let {
|
return (readValue(buffer) as? List<Any?>)?.let {
|
||||||
ResourceSize.fromList(it)
|
IconRequest.fromList(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
147.toByte() -> {
|
147.toByte() -> {
|
||||||
return (readValue(buffer) as? List<Any?>)?.let {
|
return (readValue(buffer) as? List<Any?>)?.let {
|
||||||
Resource.fromList(it)
|
ResourceSize.fromList(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
148.toByte() -> {
|
148.toByte() -> {
|
||||||
return (readValue(buffer) as? List<Any?>)?.let {
|
return (readValue(buffer) as? List<Any?>)?.let {
|
||||||
IconResult.fromList(it)
|
Resource.fromList(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
149.toByte() -> {
|
149.toByte() -> {
|
||||||
return (readValue(buffer) as? List<Any?>)?.let {
|
return (readValue(buffer) as? List<Any?>)?.let {
|
||||||
CookiePartitionKey.fromList(it)
|
IconResult.fromList(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
150.toByte() -> {
|
150.toByte() -> {
|
||||||
return (readValue(buffer) as? List<Any?>)?.let {
|
return (readValue(buffer) as? List<Any?>)?.let {
|
||||||
Cookie.fromList(it)
|
CookiePartitionKey.fromList(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
151.toByte() -> {
|
151.toByte() -> {
|
||||||
return (readValue(buffer) as? List<Any?>)?.let {
|
return (readValue(buffer) as? List<Any?>)?.let {
|
||||||
HistoryItem.fromList(it)
|
Cookie.fromList(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
152.toByte() -> {
|
152.toByte() -> {
|
||||||
return (readValue(buffer) as? List<Any?>)?.let {
|
return (readValue(buffer) as? List<Any?>)?.let {
|
||||||
HistoryState.fromList(it)
|
HistoryItem.fromList(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
153.toByte() -> {
|
153.toByte() -> {
|
||||||
return (readValue(buffer) as? List<Any?>)?.let {
|
return (readValue(buffer) as? List<Any?>)?.let {
|
||||||
ReaderableState.fromList(it)
|
HistoryState.fromList(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
154.toByte() -> {
|
154.toByte() -> {
|
||||||
return (readValue(buffer) as? List<Any?>)?.let {
|
return (readValue(buffer) as? List<Any?>)?.let {
|
||||||
SecurityInfoState.fromList(it)
|
ReaderableState.fromList(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
155.toByte() -> {
|
155.toByte() -> {
|
||||||
return (readValue(buffer) as? List<Any?>)?.let {
|
return (readValue(buffer) as? List<Any?>)?.let {
|
||||||
TabContentState.fromList(it)
|
SecurityInfoState.fromList(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
156.toByte() -> {
|
156.toByte() -> {
|
||||||
|
return (readValue(buffer) as? List<Any?>)?.let {
|
||||||
|
TabContentState.fromList(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
157.toByte() -> {
|
||||||
return (readValue(buffer) as? List<Any?>)?.let {
|
return (readValue(buffer) as? List<Any?>)?.let {
|
||||||
FindResultState.fromList(it)
|
FindResultState.fromList(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
158.toByte() -> {
|
||||||
|
return (readValue(buffer) as? List<Any?>)?.let {
|
||||||
|
CustomSelectionAction.fromList(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
else -> super.readValueOfType(type, buffer)
|
else -> super.readValueOfType(type, buffer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1057,98 +1102,106 @@ private open class GeckoPigeonCodec : StandardMessageCodec() {
|
|||||||
stream.write(133)
|
stream.write(133)
|
||||||
writeValue(stream, value.raw)
|
writeValue(stream, value.raw)
|
||||||
}
|
}
|
||||||
is TranslationOptions -> {
|
is SelectionPattern -> {
|
||||||
stream.write(134)
|
stream.write(134)
|
||||||
writeValue(stream, value.toList())
|
writeValue(stream, value.raw)
|
||||||
}
|
}
|
||||||
is ReaderState -> {
|
is TranslationOptions -> {
|
||||||
stream.write(135)
|
stream.write(135)
|
||||||
writeValue(stream, value.toList())
|
writeValue(stream, value.toList())
|
||||||
}
|
}
|
||||||
is LastMediaAccessState -> {
|
is ReaderState -> {
|
||||||
stream.write(136)
|
stream.write(136)
|
||||||
writeValue(stream, value.toList())
|
writeValue(stream, value.toList())
|
||||||
}
|
}
|
||||||
is HistoryMetadataKey -> {
|
is LastMediaAccessState -> {
|
||||||
stream.write(137)
|
stream.write(137)
|
||||||
writeValue(stream, value.toList())
|
writeValue(stream, value.toList())
|
||||||
}
|
}
|
||||||
is PackageCategoryValue -> {
|
is HistoryMetadataKey -> {
|
||||||
stream.write(138)
|
stream.write(138)
|
||||||
writeValue(stream, value.toList())
|
writeValue(stream, value.toList())
|
||||||
}
|
}
|
||||||
is ExternalPackage -> {
|
is PackageCategoryValue -> {
|
||||||
stream.write(139)
|
stream.write(139)
|
||||||
writeValue(stream, value.toList())
|
writeValue(stream, value.toList())
|
||||||
}
|
}
|
||||||
is LoadUrlFlagsValue -> {
|
is ExternalPackage -> {
|
||||||
stream.write(140)
|
stream.write(140)
|
||||||
writeValue(stream, value.toList())
|
writeValue(stream, value.toList())
|
||||||
}
|
}
|
||||||
is SourceValue -> {
|
is LoadUrlFlagsValue -> {
|
||||||
stream.write(141)
|
stream.write(141)
|
||||||
writeValue(stream, value.toList())
|
writeValue(stream, value.toList())
|
||||||
}
|
}
|
||||||
is TabState -> {
|
is SourceValue -> {
|
||||||
stream.write(142)
|
stream.write(142)
|
||||||
writeValue(stream, value.toList())
|
writeValue(stream, value.toList())
|
||||||
}
|
}
|
||||||
is RecoverableTab -> {
|
is TabState -> {
|
||||||
stream.write(143)
|
stream.write(143)
|
||||||
writeValue(stream, value.toList())
|
writeValue(stream, value.toList())
|
||||||
}
|
}
|
||||||
is RecoverableBrowserState -> {
|
is RecoverableTab -> {
|
||||||
stream.write(144)
|
stream.write(144)
|
||||||
writeValue(stream, value.toList())
|
writeValue(stream, value.toList())
|
||||||
}
|
}
|
||||||
is IconRequest -> {
|
is RecoverableBrowserState -> {
|
||||||
stream.write(145)
|
stream.write(145)
|
||||||
writeValue(stream, value.toList())
|
writeValue(stream, value.toList())
|
||||||
}
|
}
|
||||||
is ResourceSize -> {
|
is IconRequest -> {
|
||||||
stream.write(146)
|
stream.write(146)
|
||||||
writeValue(stream, value.toList())
|
writeValue(stream, value.toList())
|
||||||
}
|
}
|
||||||
is Resource -> {
|
is ResourceSize -> {
|
||||||
stream.write(147)
|
stream.write(147)
|
||||||
writeValue(stream, value.toList())
|
writeValue(stream, value.toList())
|
||||||
}
|
}
|
||||||
is IconResult -> {
|
is Resource -> {
|
||||||
stream.write(148)
|
stream.write(148)
|
||||||
writeValue(stream, value.toList())
|
writeValue(stream, value.toList())
|
||||||
}
|
}
|
||||||
is CookiePartitionKey -> {
|
is IconResult -> {
|
||||||
stream.write(149)
|
stream.write(149)
|
||||||
writeValue(stream, value.toList())
|
writeValue(stream, value.toList())
|
||||||
}
|
}
|
||||||
is Cookie -> {
|
is CookiePartitionKey -> {
|
||||||
stream.write(150)
|
stream.write(150)
|
||||||
writeValue(stream, value.toList())
|
writeValue(stream, value.toList())
|
||||||
}
|
}
|
||||||
is HistoryItem -> {
|
is Cookie -> {
|
||||||
stream.write(151)
|
stream.write(151)
|
||||||
writeValue(stream, value.toList())
|
writeValue(stream, value.toList())
|
||||||
}
|
}
|
||||||
is HistoryState -> {
|
is HistoryItem -> {
|
||||||
stream.write(152)
|
stream.write(152)
|
||||||
writeValue(stream, value.toList())
|
writeValue(stream, value.toList())
|
||||||
}
|
}
|
||||||
is ReaderableState -> {
|
is HistoryState -> {
|
||||||
stream.write(153)
|
stream.write(153)
|
||||||
writeValue(stream, value.toList())
|
writeValue(stream, value.toList())
|
||||||
}
|
}
|
||||||
is SecurityInfoState -> {
|
is ReaderableState -> {
|
||||||
stream.write(154)
|
stream.write(154)
|
||||||
writeValue(stream, value.toList())
|
writeValue(stream, value.toList())
|
||||||
}
|
}
|
||||||
is TabContentState -> {
|
is SecurityInfoState -> {
|
||||||
stream.write(155)
|
stream.write(155)
|
||||||
writeValue(stream, value.toList())
|
writeValue(stream, value.toList())
|
||||||
}
|
}
|
||||||
is FindResultState -> {
|
is TabContentState -> {
|
||||||
stream.write(156)
|
stream.write(156)
|
||||||
writeValue(stream, value.toList())
|
writeValue(stream, value.toList())
|
||||||
}
|
}
|
||||||
|
is FindResultState -> {
|
||||||
|
stream.write(157)
|
||||||
|
writeValue(stream, value.toList())
|
||||||
|
}
|
||||||
|
is CustomSelectionAction -> {
|
||||||
|
stream.write(158)
|
||||||
|
writeValue(stream, value.toList())
|
||||||
|
}
|
||||||
else -> super.writeValue(stream, value)
|
else -> super.writeValue(stream, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2454,133 +2507,59 @@ class ReaderViewController(private val binaryMessenger: BinaryMessenger, private
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/** Generated class from Pigeon that represents Flutter messages that can be called from Kotlin. */
|
/** Generated interface from Pigeon that represents a handler of messages from Flutter. */
|
||||||
class SelectionAction(private val binaryMessenger: BinaryMessenger, private val messageChannelSuffix: String = "") {
|
interface GeckoSelectionActionController {
|
||||||
|
fun setActions(actions: List<CustomSelectionAction>)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
/** The codec used by SelectionAction. */
|
/** The codec used by GeckoSelectionActionController. */
|
||||||
|
val codec: MessageCodec<Any?> by lazy {
|
||||||
|
GeckoPigeonCodec()
|
||||||
|
}
|
||||||
|
/** Sets up an instance of `GeckoSelectionActionController` to handle messages through the `binaryMessenger`. */
|
||||||
|
@JvmOverloads
|
||||||
|
fun setUp(binaryMessenger: BinaryMessenger, api: GeckoSelectionActionController?, messageChannelSuffix: String = "") {
|
||||||
|
val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else ""
|
||||||
|
run {
|
||||||
|
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.flutter_mozilla_components.GeckoSelectionActionController.setActions$separatedMessageChannelSuffix", codec)
|
||||||
|
if (api != null) {
|
||||||
|
channel.setMessageHandler { message, reply ->
|
||||||
|
val args = message as List<Any?>
|
||||||
|
val actionsArg = args[0] as List<CustomSelectionAction>
|
||||||
|
val wrapped: List<Any?> = try {
|
||||||
|
api.setActions(actionsArg)
|
||||||
|
listOf(null)
|
||||||
|
} catch (exception: Throwable) {
|
||||||
|
wrapError(exception)
|
||||||
|
}
|
||||||
|
reply.reply(wrapped)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
channel.setMessageHandler(null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/** Generated class from Pigeon that represents Flutter messages that can be called from Kotlin. */
|
||||||
|
class GeckoSelectionActionEvents(private val binaryMessenger: BinaryMessenger, private val messageChannelSuffix: String = "") {
|
||||||
|
companion object {
|
||||||
|
/** The codec used by GeckoSelectionActionEvents. */
|
||||||
val codec: MessageCodec<Any?> by lazy {
|
val codec: MessageCodec<Any?> by lazy {
|
||||||
GeckoPigeonCodec()
|
GeckoPigeonCodec()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/**
|
fun performSelectionAction(idArg: String, selectedTextArg: String, callback: (Result<Unit>) -> Unit)
|
||||||
* Gets Strings representing all possible selection actions.
|
|
||||||
*
|
|
||||||
* @returns String IDs for each action that could possibly be shown in the context menu. This
|
|
||||||
* array must include all actions, available or not, and must not change over the class lifetime.
|
|
||||||
*/
|
|
||||||
fun getAllActions(callback: (Result<List<String>>) -> Unit)
|
|
||||||
{
|
{
|
||||||
val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else ""
|
val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else ""
|
||||||
val channelName = "dev.flutter.pigeon.flutter_mozilla_components.SelectionAction.getAllActions$separatedMessageChannelSuffix"
|
val channelName = "dev.flutter.pigeon.flutter_mozilla_components.GeckoSelectionActionEvents.performSelectionAction$separatedMessageChannelSuffix"
|
||||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, channelName, codec)
|
|
||||||
channel.send(null) {
|
|
||||||
if (it is List<*>) {
|
|
||||||
if (it.size > 1) {
|
|
||||||
callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?)))
|
|
||||||
} else if (it[0] == null) {
|
|
||||||
callback(Result.failure(FlutterError("null-error", "Flutter api returned null value for non-null return value.", "")))
|
|
||||||
} else {
|
|
||||||
val output = it[0] as List<String>
|
|
||||||
callback(Result.success(output))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
callback(Result.failure(createConnectionError(channelName)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Checks if an action can be shown on a new selection context menu.
|
|
||||||
*
|
|
||||||
* @returns whether or not the the custom action with the id of [id] is currently available
|
|
||||||
* which may be informed by [selectedText].
|
|
||||||
*/
|
|
||||||
fun isActionAvailable(idArg: String, selectedTextArg: String, callback: (Result<Boolean>) -> Unit)
|
|
||||||
{
|
|
||||||
val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else ""
|
|
||||||
val channelName = "dev.flutter.pigeon.flutter_mozilla_components.SelectionAction.isActionAvailable$separatedMessageChannelSuffix"
|
|
||||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, channelName, codec)
|
val channel = BasicMessageChannel<Any?>(binaryMessenger, channelName, codec)
|
||||||
channel.send(listOf(idArg, selectedTextArg)) {
|
channel.send(listOf(idArg, selectedTextArg)) {
|
||||||
if (it is List<*>) {
|
if (it is List<*>) {
|
||||||
if (it.size > 1) {
|
if (it.size > 1) {
|
||||||
callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?)))
|
callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?)))
|
||||||
} else if (it[0] == null) {
|
|
||||||
callback(Result.failure(FlutterError("null-error", "Flutter api returned null value for non-null return value.", "")))
|
|
||||||
} else {
|
} else {
|
||||||
val output = it[0] as Boolean
|
callback(Result.success(Unit))
|
||||||
callback(Result.success(output))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
callback(Result.failure(createConnectionError(channelName)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Gets a title to be shown in the selection context menu.
|
|
||||||
*
|
|
||||||
* @returns the text that should be shown on the action.
|
|
||||||
*/
|
|
||||||
fun getActionTitle(idArg: String, callback: (Result<String?>) -> Unit)
|
|
||||||
{
|
|
||||||
val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else ""
|
|
||||||
val channelName = "dev.flutter.pigeon.flutter_mozilla_components.SelectionAction.getActionTitle$separatedMessageChannelSuffix"
|
|
||||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, channelName, codec)
|
|
||||||
channel.send(listOf(idArg)) {
|
|
||||||
if (it is List<*>) {
|
|
||||||
if (it.size > 1) {
|
|
||||||
callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?)))
|
|
||||||
} else {
|
|
||||||
val output = it[0] as String?
|
|
||||||
callback(Result.success(output))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
callback(Result.failure(createConnectionError(channelName)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Should perform the action with the id of [id].
|
|
||||||
*
|
|
||||||
* @returns [true] if the action was consumed.
|
|
||||||
*/
|
|
||||||
fun performAction(idArg: String, selectedTextArg: String, callback: (Result<Boolean>) -> Unit)
|
|
||||||
{
|
|
||||||
val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else ""
|
|
||||||
val channelName = "dev.flutter.pigeon.flutter_mozilla_components.SelectionAction.performAction$separatedMessageChannelSuffix"
|
|
||||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, channelName, codec)
|
|
||||||
channel.send(listOf(idArg, selectedTextArg)) {
|
|
||||||
if (it is List<*>) {
|
|
||||||
if (it.size > 1) {
|
|
||||||
callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?)))
|
|
||||||
} else if (it[0] == null) {
|
|
||||||
callback(Result.failure(FlutterError("null-error", "Flutter api returned null value for non-null return value.", "")))
|
|
||||||
} else {
|
|
||||||
val output = it[0] as Boolean
|
|
||||||
callback(Result.success(output))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
callback(Result.failure(createConnectionError(channelName)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Takes in a list of actions and sorts them.
|
|
||||||
*
|
|
||||||
* @returns the sorted list.
|
|
||||||
*/
|
|
||||||
fun sortedActions(actionsArg: List<String>, callback: (Result<List<String>>) -> Unit)
|
|
||||||
{
|
|
||||||
val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else ""
|
|
||||||
val channelName = "dev.flutter.pigeon.flutter_mozilla_components.SelectionAction.sortedActions$separatedMessageChannelSuffix"
|
|
||||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, channelName, codec)
|
|
||||||
channel.send(listOf(actionsArg)) {
|
|
||||||
if (it is List<*>) {
|
|
||||||
if (it.size > 1) {
|
|
||||||
callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?)))
|
|
||||||
} else if (it[0] == null) {
|
|
||||||
callback(Result.failure(FlutterError("null-error", "Flutter api returned null value for non-null return value.", "")))
|
|
||||||
} else {
|
|
||||||
val output = it[0] as List<String>
|
|
||||||
callback(Result.success(output))
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
callback(Result.failure(createConnectionError(channelName)))
|
callback(Result.failure(createConnectionError(channelName)))
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
//export 'src/domain/services/gecko_browser.dart';
|
//export 'src/domain/services/gecko_browser.dart';
|
||||||
export 'src/data/models/load_url_flags.dart';
|
export 'src/data/models/load_url_flags.dart';
|
||||||
export 'src/data/models/source.dart';
|
export 'src/data/models/source.dart';
|
||||||
|
export 'src/domain/entities/default_selection_actions.dart';
|
||||||
export 'src/domain/services/gecko_cookie.dart';
|
export 'src/domain/services/gecko_cookie.dart';
|
||||||
export 'src/domain/services/gecko_engine_settings.dart';
|
export 'src/domain/services/gecko_engine_settings.dart';
|
||||||
export 'src/domain/services/gecko_event.dart';
|
export 'src/domain/services/gecko_event.dart';
|
||||||
export 'src/domain/services/gecko_find_in_page.dart';
|
export 'src/domain/services/gecko_find_in_page.dart';
|
||||||
export 'src/domain/services/gecko_icon.dart';
|
export 'src/domain/services/gecko_icon.dart';
|
||||||
export 'src/domain/services/gecko_readerable.dart';
|
export 'src/domain/services/gecko_readerable.dart';
|
||||||
|
export 'src/domain/services/gecko_selection_action.dart';
|
||||||
export 'src/domain/services/gecko_session.dart';
|
export 'src/domain/services/gecko_session.dart';
|
||||||
export 'src/domain/services/gecko_tab.dart';
|
export 'src/domain/services/gecko_tab.dart';
|
||||||
export 'src/geckoview_widget.dart';
|
export 'src/geckoview_widget.dart';
|
||||||
|
|||||||
+61
@@ -0,0 +1,61 @@
|
|||||||
|
import 'package:flutter_mozilla_components/src/pigeons/gecko.g.dart';
|
||||||
|
|
||||||
|
typedef PerformAction = void Function(String selectedText);
|
||||||
|
|
||||||
|
class BaseSelectionAction extends CustomSelectionAction {
|
||||||
|
final PerformAction performAction;
|
||||||
|
|
||||||
|
BaseSelectionAction({
|
||||||
|
required super.id,
|
||||||
|
required super.title,
|
||||||
|
required this.performAction,
|
||||||
|
super.pattern,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
class CallAction extends BaseSelectionAction {
|
||||||
|
CallAction(PerformAction action)
|
||||||
|
: super(
|
||||||
|
id: 'CUSTOM_CONTEXT_MENU_CALL',
|
||||||
|
title: 'Call',
|
||||||
|
pattern: SelectionPattern.phone,
|
||||||
|
performAction: action,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class EmailAction extends BaseSelectionAction {
|
||||||
|
EmailAction(PerformAction action)
|
||||||
|
: super(
|
||||||
|
id: 'CUSTOM_CONTEXT_MENU_EMAIL',
|
||||||
|
title: 'Email',
|
||||||
|
pattern: SelectionPattern.email,
|
||||||
|
performAction: action,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class SearchAction extends BaseSelectionAction {
|
||||||
|
SearchAction(PerformAction action)
|
||||||
|
: super(
|
||||||
|
id: 'CUSTOM_CONTEXT_MENU_SEARCH',
|
||||||
|
title: 'Search',
|
||||||
|
performAction: action,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class PrivateSearchAction extends BaseSelectionAction {
|
||||||
|
PrivateSearchAction(PerformAction action)
|
||||||
|
: super(
|
||||||
|
id: 'CUSTOM_CONTEXT_MENU_SEARCH_PRIVATELY',
|
||||||
|
title: 'Private Search',
|
||||||
|
performAction: action,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class ShareAction extends BaseSelectionAction {
|
||||||
|
ShareAction(PerformAction action)
|
||||||
|
: super(
|
||||||
|
id: 'CUSTOM_CONTEXT_MENU_SHARE',
|
||||||
|
title: 'Share',
|
||||||
|
performAction: action,
|
||||||
|
);
|
||||||
|
}
|
||||||
+38
@@ -0,0 +1,38 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:flutter_mozilla_components/src/domain/entities/default_selection_actions.dart';
|
||||||
|
import 'package:flutter_mozilla_components/src/pigeons/gecko.g.dart';
|
||||||
|
|
||||||
|
final _apiInstance = GeckoSelectionActionController();
|
||||||
|
|
||||||
|
class GeckoSelectionActionService extends GeckoSelectionActionEvents {
|
||||||
|
final GeckoSelectionActionController _api;
|
||||||
|
|
||||||
|
List<BaseSelectionAction> _actions;
|
||||||
|
|
||||||
|
List<BaseSelectionAction> get actions => _actions;
|
||||||
|
|
||||||
|
Future<void> setActions(List<BaseSelectionAction> value) async {
|
||||||
|
_actions = value;
|
||||||
|
await _api.setActions(actions);
|
||||||
|
}
|
||||||
|
|
||||||
|
GeckoSelectionActionService.setUp({
|
||||||
|
BinaryMessenger? binaryMessenger,
|
||||||
|
String messageChannelSuffix = '',
|
||||||
|
GeckoSelectionActionController? api,
|
||||||
|
}) : _api = api ?? _apiInstance,
|
||||||
|
_actions = [] {
|
||||||
|
GeckoSelectionActionEvents.setUp(
|
||||||
|
this,
|
||||||
|
binaryMessenger: binaryMessenger,
|
||||||
|
messageChannelSuffix: messageChannelSuffix,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void performSelectionAction(String id, String selectedText) {
|
||||||
|
_actions.firstWhere((x) => x.id == id).performAction(selectedText);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -78,6 +78,11 @@ enum CookieSameSiteStatus {
|
|||||||
unspecified,
|
unspecified,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum SelectionPattern {
|
||||||
|
phone,
|
||||||
|
email,
|
||||||
|
}
|
||||||
|
|
||||||
/// Translation options that map to the Gecko Translations Options.
|
/// Translation options that map to the Gecko Translations Options.
|
||||||
///
|
///
|
||||||
/// @property downloadModel If the necessary models should be downloaded on request. If false, then
|
/// @property downloadModel If the necessary models should be downloaded on request. If false, then
|
||||||
@@ -986,6 +991,37 @@ class FindResultState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class CustomSelectionAction {
|
||||||
|
CustomSelectionAction({
|
||||||
|
required this.id,
|
||||||
|
required this.title,
|
||||||
|
this.pattern,
|
||||||
|
});
|
||||||
|
|
||||||
|
String id;
|
||||||
|
|
||||||
|
String title;
|
||||||
|
|
||||||
|
SelectionPattern? pattern;
|
||||||
|
|
||||||
|
Object encode() {
|
||||||
|
return <Object?>[
|
||||||
|
id,
|
||||||
|
title,
|
||||||
|
pattern,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
static CustomSelectionAction decode(Object result) {
|
||||||
|
result as List<Object?>;
|
||||||
|
return CustomSelectionAction(
|
||||||
|
id: result[0]! as String,
|
||||||
|
title: result[1]! as String,
|
||||||
|
pattern: result[2] as SelectionPattern?,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class _PigeonCodec extends StandardMessageCodec {
|
class _PigeonCodec extends StandardMessageCodec {
|
||||||
const _PigeonCodec();
|
const _PigeonCodec();
|
||||||
@@ -1009,75 +1045,81 @@ class _PigeonCodec extends StandardMessageCodec {
|
|||||||
} else if (value is CookieSameSiteStatus) {
|
} else if (value is CookieSameSiteStatus) {
|
||||||
buffer.putUint8(133);
|
buffer.putUint8(133);
|
||||||
writeValue(buffer, value.index);
|
writeValue(buffer, value.index);
|
||||||
} else if (value is TranslationOptions) {
|
} else if (value is SelectionPattern) {
|
||||||
buffer.putUint8(134);
|
buffer.putUint8(134);
|
||||||
writeValue(buffer, value.encode());
|
writeValue(buffer, value.index);
|
||||||
} else if (value is ReaderState) {
|
} else if (value is TranslationOptions) {
|
||||||
buffer.putUint8(135);
|
buffer.putUint8(135);
|
||||||
writeValue(buffer, value.encode());
|
writeValue(buffer, value.encode());
|
||||||
} else if (value is LastMediaAccessState) {
|
} else if (value is ReaderState) {
|
||||||
buffer.putUint8(136);
|
buffer.putUint8(136);
|
||||||
writeValue(buffer, value.encode());
|
writeValue(buffer, value.encode());
|
||||||
} else if (value is HistoryMetadataKey) {
|
} else if (value is LastMediaAccessState) {
|
||||||
buffer.putUint8(137);
|
buffer.putUint8(137);
|
||||||
writeValue(buffer, value.encode());
|
writeValue(buffer, value.encode());
|
||||||
} else if (value is PackageCategoryValue) {
|
} else if (value is HistoryMetadataKey) {
|
||||||
buffer.putUint8(138);
|
buffer.putUint8(138);
|
||||||
writeValue(buffer, value.encode());
|
writeValue(buffer, value.encode());
|
||||||
} else if (value is ExternalPackage) {
|
} else if (value is PackageCategoryValue) {
|
||||||
buffer.putUint8(139);
|
buffer.putUint8(139);
|
||||||
writeValue(buffer, value.encode());
|
writeValue(buffer, value.encode());
|
||||||
} else if (value is LoadUrlFlagsValue) {
|
} else if (value is ExternalPackage) {
|
||||||
buffer.putUint8(140);
|
buffer.putUint8(140);
|
||||||
writeValue(buffer, value.encode());
|
writeValue(buffer, value.encode());
|
||||||
} else if (value is SourceValue) {
|
} else if (value is LoadUrlFlagsValue) {
|
||||||
buffer.putUint8(141);
|
buffer.putUint8(141);
|
||||||
writeValue(buffer, value.encode());
|
writeValue(buffer, value.encode());
|
||||||
} else if (value is TabState) {
|
} else if (value is SourceValue) {
|
||||||
buffer.putUint8(142);
|
buffer.putUint8(142);
|
||||||
writeValue(buffer, value.encode());
|
writeValue(buffer, value.encode());
|
||||||
} else if (value is RecoverableTab) {
|
} else if (value is TabState) {
|
||||||
buffer.putUint8(143);
|
buffer.putUint8(143);
|
||||||
writeValue(buffer, value.encode());
|
writeValue(buffer, value.encode());
|
||||||
} else if (value is RecoverableBrowserState) {
|
} else if (value is RecoverableTab) {
|
||||||
buffer.putUint8(144);
|
buffer.putUint8(144);
|
||||||
writeValue(buffer, value.encode());
|
writeValue(buffer, value.encode());
|
||||||
} else if (value is IconRequest) {
|
} else if (value is RecoverableBrowserState) {
|
||||||
buffer.putUint8(145);
|
buffer.putUint8(145);
|
||||||
writeValue(buffer, value.encode());
|
writeValue(buffer, value.encode());
|
||||||
} else if (value is ResourceSize) {
|
} else if (value is IconRequest) {
|
||||||
buffer.putUint8(146);
|
buffer.putUint8(146);
|
||||||
writeValue(buffer, value.encode());
|
writeValue(buffer, value.encode());
|
||||||
} else if (value is Resource) {
|
} else if (value is ResourceSize) {
|
||||||
buffer.putUint8(147);
|
buffer.putUint8(147);
|
||||||
writeValue(buffer, value.encode());
|
writeValue(buffer, value.encode());
|
||||||
} else if (value is IconResult) {
|
} else if (value is Resource) {
|
||||||
buffer.putUint8(148);
|
buffer.putUint8(148);
|
||||||
writeValue(buffer, value.encode());
|
writeValue(buffer, value.encode());
|
||||||
} else if (value is CookiePartitionKey) {
|
} else if (value is IconResult) {
|
||||||
buffer.putUint8(149);
|
buffer.putUint8(149);
|
||||||
writeValue(buffer, value.encode());
|
writeValue(buffer, value.encode());
|
||||||
} else if (value is Cookie) {
|
} else if (value is CookiePartitionKey) {
|
||||||
buffer.putUint8(150);
|
buffer.putUint8(150);
|
||||||
writeValue(buffer, value.encode());
|
writeValue(buffer, value.encode());
|
||||||
} else if (value is HistoryItem) {
|
} else if (value is Cookie) {
|
||||||
buffer.putUint8(151);
|
buffer.putUint8(151);
|
||||||
writeValue(buffer, value.encode());
|
writeValue(buffer, value.encode());
|
||||||
} else if (value is HistoryState) {
|
} else if (value is HistoryItem) {
|
||||||
buffer.putUint8(152);
|
buffer.putUint8(152);
|
||||||
writeValue(buffer, value.encode());
|
writeValue(buffer, value.encode());
|
||||||
} else if (value is ReaderableState) {
|
} else if (value is HistoryState) {
|
||||||
buffer.putUint8(153);
|
buffer.putUint8(153);
|
||||||
writeValue(buffer, value.encode());
|
writeValue(buffer, value.encode());
|
||||||
} else if (value is SecurityInfoState) {
|
} else if (value is ReaderableState) {
|
||||||
buffer.putUint8(154);
|
buffer.putUint8(154);
|
||||||
writeValue(buffer, value.encode());
|
writeValue(buffer, value.encode());
|
||||||
} else if (value is TabContentState) {
|
} else if (value is SecurityInfoState) {
|
||||||
buffer.putUint8(155);
|
buffer.putUint8(155);
|
||||||
writeValue(buffer, value.encode());
|
writeValue(buffer, value.encode());
|
||||||
} else if (value is FindResultState) {
|
} else if (value is TabContentState) {
|
||||||
buffer.putUint8(156);
|
buffer.putUint8(156);
|
||||||
writeValue(buffer, value.encode());
|
writeValue(buffer, value.encode());
|
||||||
|
} else if (value is FindResultState) {
|
||||||
|
buffer.putUint8(157);
|
||||||
|
writeValue(buffer, value.encode());
|
||||||
|
} else if (value is CustomSelectionAction) {
|
||||||
|
buffer.putUint8(158);
|
||||||
|
writeValue(buffer, value.encode());
|
||||||
} else {
|
} else {
|
||||||
super.writeValue(buffer, value);
|
super.writeValue(buffer, value);
|
||||||
}
|
}
|
||||||
@@ -1102,51 +1144,56 @@ class _PigeonCodec extends StandardMessageCodec {
|
|||||||
final int? value = readValue(buffer) as int?;
|
final int? value = readValue(buffer) as int?;
|
||||||
return value == null ? null : CookieSameSiteStatus.values[value];
|
return value == null ? null : CookieSameSiteStatus.values[value];
|
||||||
case 134:
|
case 134:
|
||||||
return TranslationOptions.decode(readValue(buffer)!);
|
final int? value = readValue(buffer) as int?;
|
||||||
|
return value == null ? null : SelectionPattern.values[value];
|
||||||
case 135:
|
case 135:
|
||||||
return ReaderState.decode(readValue(buffer)!);
|
return TranslationOptions.decode(readValue(buffer)!);
|
||||||
case 136:
|
case 136:
|
||||||
return LastMediaAccessState.decode(readValue(buffer)!);
|
return ReaderState.decode(readValue(buffer)!);
|
||||||
case 137:
|
case 137:
|
||||||
return HistoryMetadataKey.decode(readValue(buffer)!);
|
return LastMediaAccessState.decode(readValue(buffer)!);
|
||||||
case 138:
|
case 138:
|
||||||
return PackageCategoryValue.decode(readValue(buffer)!);
|
return HistoryMetadataKey.decode(readValue(buffer)!);
|
||||||
case 139:
|
case 139:
|
||||||
return ExternalPackage.decode(readValue(buffer)!);
|
return PackageCategoryValue.decode(readValue(buffer)!);
|
||||||
case 140:
|
case 140:
|
||||||
return LoadUrlFlagsValue.decode(readValue(buffer)!);
|
return ExternalPackage.decode(readValue(buffer)!);
|
||||||
case 141:
|
case 141:
|
||||||
return SourceValue.decode(readValue(buffer)!);
|
return LoadUrlFlagsValue.decode(readValue(buffer)!);
|
||||||
case 142:
|
case 142:
|
||||||
return TabState.decode(readValue(buffer)!);
|
return SourceValue.decode(readValue(buffer)!);
|
||||||
case 143:
|
case 143:
|
||||||
return RecoverableTab.decode(readValue(buffer)!);
|
return TabState.decode(readValue(buffer)!);
|
||||||
case 144:
|
case 144:
|
||||||
return RecoverableBrowserState.decode(readValue(buffer)!);
|
return RecoverableTab.decode(readValue(buffer)!);
|
||||||
case 145:
|
case 145:
|
||||||
return IconRequest.decode(readValue(buffer)!);
|
return RecoverableBrowserState.decode(readValue(buffer)!);
|
||||||
case 146:
|
case 146:
|
||||||
return ResourceSize.decode(readValue(buffer)!);
|
return IconRequest.decode(readValue(buffer)!);
|
||||||
case 147:
|
case 147:
|
||||||
return Resource.decode(readValue(buffer)!);
|
return ResourceSize.decode(readValue(buffer)!);
|
||||||
case 148:
|
case 148:
|
||||||
return IconResult.decode(readValue(buffer)!);
|
return Resource.decode(readValue(buffer)!);
|
||||||
case 149:
|
case 149:
|
||||||
return CookiePartitionKey.decode(readValue(buffer)!);
|
return IconResult.decode(readValue(buffer)!);
|
||||||
case 150:
|
case 150:
|
||||||
return Cookie.decode(readValue(buffer)!);
|
return CookiePartitionKey.decode(readValue(buffer)!);
|
||||||
case 151:
|
case 151:
|
||||||
return HistoryItem.decode(readValue(buffer)!);
|
return Cookie.decode(readValue(buffer)!);
|
||||||
case 152:
|
case 152:
|
||||||
return HistoryState.decode(readValue(buffer)!);
|
return HistoryItem.decode(readValue(buffer)!);
|
||||||
case 153:
|
case 153:
|
||||||
return ReaderableState.decode(readValue(buffer)!);
|
return HistoryState.decode(readValue(buffer)!);
|
||||||
case 154:
|
case 154:
|
||||||
return SecurityInfoState.decode(readValue(buffer)!);
|
return ReaderableState.decode(readValue(buffer)!);
|
||||||
case 155:
|
case 155:
|
||||||
return TabContentState.decode(readValue(buffer)!);
|
return SecurityInfoState.decode(readValue(buffer)!);
|
||||||
case 156:
|
case 156:
|
||||||
|
return TabContentState.decode(readValue(buffer)!);
|
||||||
|
case 157:
|
||||||
return FindResultState.decode(readValue(buffer)!);
|
return FindResultState.decode(readValue(buffer)!);
|
||||||
|
case 158:
|
||||||
|
return CustomSelectionAction.decode(readValue(buffer)!);
|
||||||
default:
|
default:
|
||||||
return super.readValueOfType(type, buffer);
|
return super.readValueOfType(type, buffer);
|
||||||
}
|
}
|
||||||
@@ -2735,155 +2782,69 @@ abstract class ReaderViewController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class SelectionAction {
|
class GeckoSelectionActionController {
|
||||||
|
/// Constructor for [GeckoSelectionActionController]. 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.
|
||||||
|
GeckoSelectionActionController({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''})
|
||||||
|
: pigeonVar_binaryMessenger = binaryMessenger,
|
||||||
|
pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : '';
|
||||||
|
final BinaryMessenger? pigeonVar_binaryMessenger;
|
||||||
|
|
||||||
static const MessageCodec<Object?> pigeonChannelCodec = _PigeonCodec();
|
static const MessageCodec<Object?> pigeonChannelCodec = _PigeonCodec();
|
||||||
|
|
||||||
/// Gets Strings representing all possible selection actions.
|
final String pigeonVar_messageChannelSuffix;
|
||||||
///
|
|
||||||
/// @returns String IDs for each action that could possibly be shown in the context menu. This
|
|
||||||
/// array must include all actions, available or not, and must not change over the class lifetime.
|
|
||||||
List<String> getAllActions();
|
|
||||||
|
|
||||||
/// Checks if an action can be shown on a new selection context menu.
|
Future<void> setActions(List<CustomSelectionAction> actions) async {
|
||||||
///
|
final String pigeonVar_channelName = 'dev.flutter.pigeon.flutter_mozilla_components.GeckoSelectionActionController.setActions$pigeonVar_messageChannelSuffix';
|
||||||
/// @returns whether or not the the custom action with the id of [id] is currently available
|
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
|
||||||
/// which may be informed by [selectedText].
|
pigeonVar_channelName,
|
||||||
bool isActionAvailable(String id, String selectedText);
|
pigeonChannelCodec,
|
||||||
|
binaryMessenger: pigeonVar_binaryMessenger,
|
||||||
|
);
|
||||||
|
final List<Object?>? pigeonVar_replyList =
|
||||||
|
await pigeonVar_channel.send(<Object?>[actions]) as List<Object?>?;
|
||||||
|
if (pigeonVar_replyList == null) {
|
||||||
|
throw _createConnectionError(pigeonVar_channelName);
|
||||||
|
} else if (pigeonVar_replyList.length > 1) {
|
||||||
|
throw PlatformException(
|
||||||
|
code: pigeonVar_replyList[0]! as String,
|
||||||
|
message: pigeonVar_replyList[1] as String?,
|
||||||
|
details: pigeonVar_replyList[2],
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Gets a title to be shown in the selection context menu.
|
abstract class GeckoSelectionActionEvents {
|
||||||
///
|
static const MessageCodec<Object?> pigeonChannelCodec = _PigeonCodec();
|
||||||
/// @returns the text that should be shown on the action.
|
|
||||||
String? getActionTitle(String id);
|
|
||||||
|
|
||||||
/// Should perform the action with the id of [id].
|
void performSelectionAction(String id, String selectedText);
|
||||||
///
|
|
||||||
/// @returns [true] if the action was consumed.
|
|
||||||
bool performAction(String id, String selectedText);
|
|
||||||
|
|
||||||
/// Takes in a list of actions and sorts them.
|
static void setUp(GeckoSelectionActionEvents? api, {BinaryMessenger? binaryMessenger, String messageChannelSuffix = '',}) {
|
||||||
///
|
|
||||||
/// @returns the sorted list.
|
|
||||||
List<String> sortedActions(List<String> actions);
|
|
||||||
|
|
||||||
static void setUp(SelectionAction? api, {BinaryMessenger? binaryMessenger, String messageChannelSuffix = '',}) {
|
|
||||||
messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : '';
|
messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : '';
|
||||||
{
|
{
|
||||||
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
|
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
|
||||||
'dev.flutter.pigeon.flutter_mozilla_components.SelectionAction.getAllActions$messageChannelSuffix', pigeonChannelCodec,
|
'dev.flutter.pigeon.flutter_mozilla_components.GeckoSelectionActionEvents.performSelectionAction$messageChannelSuffix', pigeonChannelCodec,
|
||||||
binaryMessenger: binaryMessenger);
|
|
||||||
if (api == null) {
|
|
||||||
pigeonVar_channel.setMessageHandler(null);
|
|
||||||
} else {
|
|
||||||
pigeonVar_channel.setMessageHandler((Object? message) async {
|
|
||||||
try {
|
|
||||||
final List<String> output = api.getAllActions();
|
|
||||||
return wrapResponse(result: output);
|
|
||||||
} on PlatformException catch (e) {
|
|
||||||
return wrapResponse(error: e);
|
|
||||||
} catch (e) {
|
|
||||||
return wrapResponse(error: PlatformException(code: 'error', message: e.toString()));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
{
|
|
||||||
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
|
|
||||||
'dev.flutter.pigeon.flutter_mozilla_components.SelectionAction.isActionAvailable$messageChannelSuffix', pigeonChannelCodec,
|
|
||||||
binaryMessenger: binaryMessenger);
|
binaryMessenger: binaryMessenger);
|
||||||
if (api == null) {
|
if (api == null) {
|
||||||
pigeonVar_channel.setMessageHandler(null);
|
pigeonVar_channel.setMessageHandler(null);
|
||||||
} else {
|
} else {
|
||||||
pigeonVar_channel.setMessageHandler((Object? message) async {
|
pigeonVar_channel.setMessageHandler((Object? message) async {
|
||||||
assert(message != null,
|
assert(message != null,
|
||||||
'Argument for dev.flutter.pigeon.flutter_mozilla_components.SelectionAction.isActionAvailable was null.');
|
'Argument for dev.flutter.pigeon.flutter_mozilla_components.GeckoSelectionActionEvents.performSelectionAction was null.');
|
||||||
final List<Object?> args = (message as List<Object?>?)!;
|
final List<Object?> args = (message as List<Object?>?)!;
|
||||||
final String? arg_id = (args[0] as String?);
|
final String? arg_id = (args[0] as String?);
|
||||||
assert(arg_id != null,
|
assert(arg_id != null,
|
||||||
'Argument for dev.flutter.pigeon.flutter_mozilla_components.SelectionAction.isActionAvailable was null, expected non-null String.');
|
'Argument for dev.flutter.pigeon.flutter_mozilla_components.GeckoSelectionActionEvents.performSelectionAction was null, expected non-null String.');
|
||||||
final String? arg_selectedText = (args[1] as String?);
|
final String? arg_selectedText = (args[1] as String?);
|
||||||
assert(arg_selectedText != null,
|
assert(arg_selectedText != null,
|
||||||
'Argument for dev.flutter.pigeon.flutter_mozilla_components.SelectionAction.isActionAvailable was null, expected non-null String.');
|
'Argument for dev.flutter.pigeon.flutter_mozilla_components.GeckoSelectionActionEvents.performSelectionAction was null, expected non-null String.');
|
||||||
try {
|
try {
|
||||||
final bool output = api.isActionAvailable(arg_id!, arg_selectedText!);
|
api.performSelectionAction(arg_id!, arg_selectedText!);
|
||||||
return wrapResponse(result: output);
|
return wrapResponse(empty: true);
|
||||||
} on PlatformException catch (e) {
|
|
||||||
return wrapResponse(error: e);
|
|
||||||
} catch (e) {
|
|
||||||
return wrapResponse(error: PlatformException(code: 'error', message: e.toString()));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
{
|
|
||||||
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
|
|
||||||
'dev.flutter.pigeon.flutter_mozilla_components.SelectionAction.getActionTitle$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.SelectionAction.getActionTitle was null.');
|
|
||||||
final List<Object?> args = (message as List<Object?>?)!;
|
|
||||||
final String? arg_id = (args[0] as String?);
|
|
||||||
assert(arg_id != null,
|
|
||||||
'Argument for dev.flutter.pigeon.flutter_mozilla_components.SelectionAction.getActionTitle was null, expected non-null String.');
|
|
||||||
try {
|
|
||||||
final String? output = api.getActionTitle(arg_id!);
|
|
||||||
return wrapResponse(result: output);
|
|
||||||
} on PlatformException catch (e) {
|
|
||||||
return wrapResponse(error: e);
|
|
||||||
} catch (e) {
|
|
||||||
return wrapResponse(error: PlatformException(code: 'error', message: e.toString()));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
{
|
|
||||||
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
|
|
||||||
'dev.flutter.pigeon.flutter_mozilla_components.SelectionAction.performAction$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.SelectionAction.performAction was null.');
|
|
||||||
final List<Object?> args = (message as List<Object?>?)!;
|
|
||||||
final String? arg_id = (args[0] as String?);
|
|
||||||
assert(arg_id != null,
|
|
||||||
'Argument for dev.flutter.pigeon.flutter_mozilla_components.SelectionAction.performAction was null, expected non-null String.');
|
|
||||||
final String? arg_selectedText = (args[1] as String?);
|
|
||||||
assert(arg_selectedText != null,
|
|
||||||
'Argument for dev.flutter.pigeon.flutter_mozilla_components.SelectionAction.performAction was null, expected non-null String.');
|
|
||||||
try {
|
|
||||||
final bool output = api.performAction(arg_id!, arg_selectedText!);
|
|
||||||
return wrapResponse(result: output);
|
|
||||||
} on PlatformException catch (e) {
|
|
||||||
return wrapResponse(error: e);
|
|
||||||
} catch (e) {
|
|
||||||
return wrapResponse(error: PlatformException(code: 'error', message: e.toString()));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
{
|
|
||||||
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
|
|
||||||
'dev.flutter.pigeon.flutter_mozilla_components.SelectionAction.sortedActions$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.SelectionAction.sortedActions was null.');
|
|
||||||
final List<Object?> args = (message as List<Object?>?)!;
|
|
||||||
final List<String>? arg_actions = (args[0] as List<Object?>?)?.cast<String>();
|
|
||||||
assert(arg_actions != null,
|
|
||||||
'Argument for dev.flutter.pigeon.flutter_mozilla_components.SelectionAction.sortedActions was null, expected non-null List<String>.');
|
|
||||||
try {
|
|
||||||
final List<String> output = api.sortedActions(arg_actions!);
|
|
||||||
return wrapResponse(result: output);
|
|
||||||
} on PlatformException catch (e) {
|
} on PlatformException catch (e) {
|
||||||
return wrapResponse(error: e);
|
return wrapResponse(error: e);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|||||||
@@ -469,6 +469,16 @@ class FindResultState {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum SelectionPattern { phone, email }
|
||||||
|
|
||||||
|
class CustomSelectionAction {
|
||||||
|
final String id;
|
||||||
|
final String title;
|
||||||
|
final SelectionPattern? pattern;
|
||||||
|
|
||||||
|
CustomSelectionAction(this.id, this.title, this.pattern);
|
||||||
|
}
|
||||||
|
|
||||||
// /// Represents all the different supported types of data that can be found from long clicking
|
// /// Represents all the different supported types of data that can be found from long clicking
|
||||||
// /// an element.
|
// /// an element.
|
||||||
// sealed class HitResult {
|
// sealed class HitResult {
|
||||||
@@ -816,32 +826,12 @@ abstract class ReaderViewController {
|
|||||||
void appearanceButtonVisibility(bool visible);
|
void appearanceButtonVisibility(bool visible);
|
||||||
}
|
}
|
||||||
|
|
||||||
@FlutterApi()
|
@HostApi()
|
||||||
abstract class SelectionAction {
|
abstract class GeckoSelectionActionController {
|
||||||
/// Gets Strings representing all possible selection actions.
|
void setActions(List<CustomSelectionAction> actions);
|
||||||
///
|
}
|
||||||
/// @returns String IDs for each action that could possibly be shown in the context menu. This
|
|
||||||
/// array must include all actions, available or not, and must not change over the class lifetime.
|
@FlutterApi()
|
||||||
List<String> getAllActions();
|
abstract class GeckoSelectionActionEvents {
|
||||||
|
void performSelectionAction(String id, String selectedText);
|
||||||
/// Checks if an action can be shown on a new selection context menu.
|
|
||||||
///
|
|
||||||
/// @returns whether or not the the custom action with the id of [id] is currently available
|
|
||||||
/// which may be informed by [selectedText].
|
|
||||||
bool isActionAvailable(String id, String selectedText);
|
|
||||||
|
|
||||||
/// Gets a title to be shown in the selection context menu.
|
|
||||||
///
|
|
||||||
/// @returns the text that should be shown on the action.
|
|
||||||
String? getActionTitle(String id);
|
|
||||||
|
|
||||||
/// Should perform the action with the id of [id].
|
|
||||||
///
|
|
||||||
/// @returns [true] if the action was consumed.
|
|
||||||
bool performAction(String id, String selectedText);
|
|
||||||
|
|
||||||
/// Takes in a list of actions and sorts them.
|
|
||||||
///
|
|
||||||
/// @returns the sorted list.
|
|
||||||
List<String> sortedActions(List<String> actions);
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user