deprecate and strip pref manager extension; rebuild pigeons;

This commit is contained in:
Fabian Freund
2026-04-16 08:08:26 +02:00
parent b3576d4b49
commit 560a0b51be
21 changed files with 3497 additions and 3367 deletions
@@ -125,11 +125,22 @@ Future<PreferenceSettingGroup> _preferenceSettingGroup(
@Riverpod()
class _PreferenceRepository extends _$PreferenceRepository {
final _prefManager = GeckoPrefService();
// Use BehaviorSubject instead of StreamController
late BehaviorSubject<Map<String, GeckoPref>> _prefSubject;
Future<void> _updatePrefs() async {
final prefs = await _prefManager.getAllPrefs();
final groups = await ref.read(
_preferenceSettingGroupsProvider(partition).future,
);
final prefNames = groups.values
.map((group) => group.settings.keys)
.flattened
.toList();
final prefs = prefNames.isEmpty
? <String, GeckoPref>{}
: await _prefManager.getPrefs(prefNames);
_prefSubject.add(prefs);
}
@@ -144,18 +155,28 @@ class _PreferenceRepository extends _$PreferenceRepository {
}
@override
Raw<Stream<Map<String, GeckoPref>>> build() {
Raw<Stream<Map<String, GeckoPref>>> build(
PreferencePartition partition,
) async* {
final prefCompleter = Completer();
_prefSubject = BehaviorSubject<Map<String, GeckoPref>>();
ref.onDispose(() async {
await _prefSubject.close();
});
ref.onAddListener(() async {
await _updatePrefs();
ref.onAddListener(() {
if (prefCompleter.isCompleted) {
ref.invalidateSelf();
}
});
return _prefSubject.stream;
await _updatePrefs().whenComplete(() {
prefCompleter.complete();
});
yield* _prefSubject.stream;
}
}
@@ -166,7 +187,7 @@ class UnifiedPreferenceSettingsRepository
Future<void> apply() async {
final preferenceRepository = ref.read(
_preferenceRepositoryProvider.notifier,
_preferenceRepositoryProvider(partition).notifier,
);
_statelessGroups = await ref.read(
@@ -187,7 +208,7 @@ class UnifiedPreferenceSettingsRepository
Future<void> reset() async {
final preferenceRepository = ref.read(
_preferenceRepositoryProvider.notifier,
_preferenceRepositoryProvider(partition).notifier,
);
_statelessGroups = await ref.read(
@@ -210,7 +231,7 @@ class UnifiedPreferenceSettingsRepository
_preferenceSettingGroupsProvider(partition).future,
);
final prefStream = ref.watch(_preferenceRepositoryProvider);
final prefStream = ref.watch(_preferenceRepositoryProvider(partition));
yield* prefStream.map(
(prefs) => _statelessGroups!.map(
@@ -235,7 +256,7 @@ class PreferenceSettingsGroupRepository
Future<void> apply({List<String>? filter}) async {
final preferenceRepository = ref.read(
_preferenceRepositoryProvider.notifier,
_preferenceRepositoryProvider(partition).notifier,
);
_statelessSettingGroup ??= await ref.read(
@@ -260,7 +281,7 @@ class PreferenceSettingsGroupRepository
Future<void> reset({List<String>? filter}) async {
final preferenceRepository = ref.read(
_preferenceRepositoryProvider.notifier,
_preferenceRepositoryProvider(partition).notifier,
);
_statelessSettingGroup ??= await ref.read(
@@ -288,7 +309,7 @@ class PreferenceSettingsGroupRepository
_preferenceSettingGroupProvider(partition, groupName).future,
);
final prefStream = ref.watch(_preferenceRepositoryProvider);
final prefStream = ref.watch(_preferenceRepositoryProvider(partition));
yield* prefStream.map(
(prefs) => _statelessSettingGroup!.copyWith.settings(
@@ -279,7 +279,7 @@ final class _PreferenceSettingGroupFamily extends $Family
}
@ProviderFor(_PreferenceRepository)
final _preferenceRepositoryProvider = _PreferenceRepositoryProvider._();
final _preferenceRepositoryProvider = _PreferenceRepositoryFamily._();
final class _PreferenceRepositoryProvider
extends
@@ -287,20 +287,27 @@ final class _PreferenceRepositoryProvider
_PreferenceRepository,
Raw<Stream<Map<String, GeckoPref>>>
> {
_PreferenceRepositoryProvider._()
: super(
from: null,
argument: null,
retry: null,
name: r'_preferenceRepositoryProvider',
isAutoDispose: true,
dependencies: null,
$allTransitiveDependencies: null,
);
_PreferenceRepositoryProvider._({
required _PreferenceRepositoryFamily super.from,
required PreferencePartition super.argument,
}) : super(
retry: null,
name: r'_preferenceRepositoryProvider',
isAutoDispose: true,
dependencies: null,
$allTransitiveDependencies: null,
);
@override
String debugGetCreateSourceHash() => _$_preferenceRepositoryHash();
@override
String toString() {
return r'_preferenceRepositoryProvider'
''
'($argument)';
}
@$internal
@override
_PreferenceRepository create() => _PreferenceRepository();
@@ -314,14 +321,52 @@ final class _PreferenceRepositoryProvider
),
);
}
@override
bool operator ==(Object other) {
return other is _PreferenceRepositoryProvider && other.argument == argument;
}
@override
int get hashCode {
return argument.hashCode;
}
}
String _$_preferenceRepositoryHash() =>
r'0f6812988a23407f6648e32fb1585984d2433bbc';
r'b7a0aab286dd1f8da758de5cf259ad0c14b733d9';
final class _PreferenceRepositoryFamily extends $Family
with
$ClassFamilyOverride<
_PreferenceRepository,
Raw<Stream<Map<String, GeckoPref>>>,
Raw<Stream<Map<String, GeckoPref>>>,
Raw<Stream<Map<String, GeckoPref>>>,
PreferencePartition
> {
_PreferenceRepositoryFamily._()
: super(
retry: null,
name: r'_preferenceRepositoryProvider',
dependencies: null,
$allTransitiveDependencies: null,
isAutoDispose: true,
);
_PreferenceRepositoryProvider call(PreferencePartition partition) =>
_PreferenceRepositoryProvider._(argument: partition, from: this);
@override
String toString() => r'_preferenceRepositoryProvider';
}
abstract class _$PreferenceRepository
extends $Notifier<Raw<Stream<Map<String, GeckoPref>>>> {
Raw<Stream<Map<String, GeckoPref>>> build();
late final _$args = ref.$arg as PreferencePartition;
PreferencePartition get partition => _$args;
Raw<Stream<Map<String, GeckoPref>>> build(PreferencePartition partition);
@$mustCallSuper
@override
void runBuild() {
@@ -342,7 +387,7 @@ abstract class _$PreferenceRepository
Object?,
Object?
>;
element.handleCreate(ref, build);
element.handleCreate(ref, () => build(_$args));
}
}
@@ -396,7 +441,7 @@ final class UnifiedPreferenceSettingsRepositoryProvider
}
String _$unifiedPreferenceSettingsRepositoryHash() =>
r'800e74a051113b4ebc3631b6ade55d66cb7e1af1';
r'03c8c2f247974ff32bba14b4b34857a0f14f6f37';
final class UnifiedPreferenceSettingsRepositoryFamily extends $Family
with
@@ -509,7 +554,7 @@ final class PreferenceSettingsGroupRepositoryProvider
}
String _$preferenceSettingsGroupRepositoryHash() =>
r'8e025cdea5cef8a6ea029db6f9ebcd86abf906d8';
r'b5c439643ec78094122c33983e58d0977641832a';
final class PreferenceSettingsGroupRepositoryFamily extends $Family
with
@@ -1,35 +0,0 @@
"use strict";
const { BackgroundTasksUtils } = ChromeUtils.importESModule(
"resource://gre/modules/BackgroundTasksUtils.sys.mjs"
);
const lazy = {};
ChromeUtils.defineLazyGetter(lazy, "log", () => {
let { ConsoleAPI } = ChromeUtils.importESModule(
"resource://gre/modules/Console.sys.mjs"
);
let consoleOptions = {
// tip: set maxLogLevel to "debug" and use log.debug() to create detailed
// messages during development. See LOG_LEVELS in Console.sys.mjs for details.
maxLogLevel: "error",
maxLogLevelPref: "app.update.background.loglevel",
prefix: "PrefsManager",
};
return new ConsoleAPI(consoleOptions);
});
var prefmanager = class extends ExtensionAPI {
getAPI(context) {
return {
experiments: {
prefmanager: {
async getPrefList() {
return Services.prefs.getChildList("");
}
}
}
};
}
};
@@ -1,36 +0,0 @@
'use strict';
const encoder = new TextEncoder();
const port = browser.runtime.connectNative("prefManager");
function sendJsonResultForRequest(id) {
return function (result) {
port.postMessage({
"id": id,
"status": "success",
"result": result
})
}
}
function sendErrorForRequest(id) {
return function (error) {
console.error(error);
port.postMessage({
"id": id,
"status": "error",
"error": error
});
}
}
port.onMessage.addListener(message => {
let requestId = message["id"]
switch (message["action"]) {
case "getPrefList":
browser.experiments.prefmanager.getPrefList()
.then(sendJsonResultForRequest(requestId))
.catch(sendErrorForRequest(requestId))
}
});
@@ -1,39 +0,0 @@
{
"manifest_version": 2,
"name": "Pref Manager",
"version": "1.0",
"description": "Manipulate GeckoView preferences",
"browser_specific_settings": {
"gecko": {
"id": "pref-manager@weblibre.eu"
}
},
"background": {
"scripts": [
"background.js"
]
},
"experiment_apis": {
"prefmanager": {
"schema": "schema.json",
"parent": {
"scopes": [
"addon_parent"
],
"paths": [
[
"experiments",
"prefmanager"
]
],
"script": "api.js"
}
}
},
"permissions": [
"nativeMessaging",
"nativeMessagingFromContent",
"geckoViewAddons",
"<all_urls>"
]
}
@@ -1,22 +0,0 @@
[
{
"namespace": "experiments.prefmanager",
"description": "Experimental API for updating Geckoview preferences",
"functions": [
{
"name": "getPrefList",
"type": "function",
"description": "Retrieves list of all preferences",
"async": true,
"parameters": [],
"returns": {
"array": "object",
"description": "Object containing the preferences as key-value pairs",
"items": {
"type": "string"
}
}
}
]
}
]
@@ -7,7 +7,6 @@ package eu.weblibre.flutter_mozilla_components
import android.content.Context
import eu.weblibre.flutter_mozilla_components.feature.ContainerProxyFeature
import eu.weblibre.flutter_mozilla_components.feature.CookieManagerFeature
import eu.weblibre.flutter_mozilla_components.feature.PrefManagerFeature
import eu.weblibre.flutter_mozilla_components.feature.BrowserExtensionFeature
import eu.weblibre.flutter_mozilla_components.feature.MLEngineFeature
import eu.weblibre.flutter_mozilla_components.pigeons.BounceTrackingProtectionMode
@@ -122,7 +121,6 @@ object EngineProvider {
return GeckoEngine(context, defaultSettings, runtime).also {
WebCompatFeature.install(it)
//CookieManagerFeature.install(it)
PrefManagerFeature.install(it)
ContainerProxyFeature.install(it, stateEvents)
BrowserExtensionFeature.install(it, extensionEvents)
MLEngineFeature.install(it)
@@ -8,61 +8,18 @@ package eu.weblibre.flutter_mozilla_components.api
import eu.weblibre.flutter_mozilla_components.GlobalComponents
import eu.weblibre.flutter_mozilla_components.ext.EventSequence
import eu.weblibre.flutter_mozilla_components.feature.PrefManagerFeature
import eu.weblibre.flutter_mozilla_components.feature.ResultConsumer
import eu.weblibre.flutter_mozilla_components.pigeons.GeckoPref
import eu.weblibre.flutter_mozilla_components.pigeons.GeckoPrefApi
import mozilla.components.ExperimentalAndroidComponentsApi
import mozilla.components.concept.engine.preferences.Branch
import mozilla.components.concept.engine.preferences.BrowserPrefObserverDelegate
import mozilla.components.concept.engine.preferences.BrowserPreference
import mozilla.components.support.ktx.android.org.json.toList
import org.json.JSONObject
import org.json.JSONArray
class GeckoPrefApiImpl : GeckoPrefApi, BrowserPrefObserverDelegate {
private val components by lazy {
requireNotNull(GlobalComponents.components) { "Components not initialized" }
}
private fun List<String>?.toJson(): JSONArray {
return JSONArray().apply {
this@toJson?.forEach { put(it) }
}
}
fun JSONObject.toMap(): Map<String, Any> {
val map = mutableMapOf<String, Any>()
val keys = this.keys()
while (keys.hasNext()) {
val key = keys.next()
when (val value = this.get(key)) {
is JSONObject -> map[key] = value.toMap()
// is JSONArray -> map[key] = value.toList()
// JSONObject.NULL -> map[key] = null
else -> map[key] = value
}
}
return map
}
override fun getPrefList(callback: (Result<List<String>>) -> Unit) {
PrefManagerFeature.scheduleRequest(
"getPrefList",
Unit,
object : ResultConsumer<JSONObject> {
override fun success(result: JSONObject) {
callback(Result.success(result.getJSONArray("result").toList()))
}
override fun error(errorCode: String, errorMessage: String?, errorDetails: Any?) {
callback(Result.failure(Exception("$errorCode $errorMessage $errorDetails")))
}
})
}
@OptIn(ExperimentalAndroidComponentsApi::class)
override fun getPrefs(
preferenceFilter: List<String>,
@@ -212,4 +169,4 @@ class GeckoPrefApiImpl : GeckoPrefApi, BrowserPrefObserverDelegate {
)
) { _ -> }
}
}
}
@@ -1,107 +0,0 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package eu.weblibre.flutter_mozilla_components.feature
import androidx.annotation.VisibleForTesting
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.withContext
import mozilla.components.concept.engine.webextension.MessageHandler
import mozilla.components.concept.engine.webextension.Port
import mozilla.components.concept.engine.webextension.WebExtensionRuntime
import mozilla.components.support.base.log.logger.Logger
import mozilla.components.support.webextensions.BuiltInWebExtensionController
import org.json.JSONObject
object PrefManagerFeature {
private val logger = Logger("pref-manager")
private const val PREF_MANAGER_REPORTER_EXTENSION_ID = "pref-manager@weblibre.eu"
private const val PREF_MANAGER_REPORTER_EXTENSION_URL = "resource://android/assets/extensions/pref_manager/"
private const val PREF_MANAGER_REPORTER_MESSAGING_ID = "prefManager"
private var nextRequestId: Int = 0
private val requestHandlers = HashMap<Int, ResultConsumer<JSONObject>>()
private val mutex = Mutex()
@VisibleForTesting
// This is an internal var to make it mutable for unit testing purposes only
internal var extensionController = BuiltInWebExtensionController(
PREF_MANAGER_REPORTER_EXTENSION_ID,
PREF_MANAGER_REPORTER_EXTENSION_URL,
PREF_MANAGER_REPORTER_MESSAGING_ID,
)
fun scheduleRequest(command: String, args: Any, callback: ResultConsumer<JSONObject>) {
val message = JSONObject()
message.put("action", command);
message.put("args", args)
runBlocking {
withContext(Dispatchers.Default) {
mutex.withLock {
message.put("id", nextRequestId)
requestHandlers[nextRequestId] = callback
nextRequestId += 1
extensionController.sendBackgroundMessage(message)
}
}
}
}
private class PrefManagerReporterBackgroundMessageHandler() : MessageHandler {
override fun onPortMessage(message: Any, port: Port) {
runBlocking {
withContext(Dispatchers.Default) {
mutex.withLock {
val messageJSON = message as JSONObject;
val requestId = messageJSON.getInt("id")
val status = messageJSON.getString("status")
val handler = requestHandlers.remove(requestId)
if (status == "success") {
handler?.success(message)
} else {
handler?.error(
"Pref Manager",
"Failed to perform operation",
message.getString("error")
)
}
}
}
}
}
}
/**
* Installs the web extension in the runtime through the WebExtensionRuntime install method
*
* @param runtime a WebExtensionRuntime.
* @param productName a custom product name used to automatically label reports. Defaults to
* "android-components".
*/
fun install(runtime: WebExtensionRuntime) {
extensionController.registerBackgroundMessageHandler(
PrefManagerReporterBackgroundMessageHandler(),
)
extensionController.install(
runtime,
onSuccess = {
logger.debug("Installed PrefManager webextension: ${it.id}")
},
onError = { throwable ->
logger.error("Failed to install PrefManager webextension: ", throwable)
},
)
}
}
@@ -9,14 +9,6 @@ import 'package:flutter_mozilla_components/src/pigeons/gecko.g.dart';
final _apiInstance = GeckoPrefApi();
class GeckoPrefService {
Future<List<String>> getPrefList() {
return _apiInstance.getPrefList();
}
Future<Map<String, GeckoPref>> getAllPrefs() async {
return _apiInstance.getPrefs(await getPrefList());
}
Future<Map<String, GeckoPref>> getPrefs(List<String> prefs) {
return _apiInstance.getPrefs(prefs);
}
File diff suppressed because it is too large Load Diff
@@ -1504,8 +1504,6 @@ class GeckoPref {
@HostApi()
abstract class GeckoPrefApi {
@async
List<String> getPrefList();
@async
Map<String, GeckoPref> getPrefs(List<String> preferenceFilter);
@async
@@ -1,4 +1,4 @@
// Autogenerated from Pigeon (v26.1.7), do not edit directly.
// Autogenerated from Pigeon (v26.3.2), do not edit directly.
// See also: https://pub.dev/packages/pigeon
@file:Suppress("UNCHECKED_CAST", "ArrayInDataClass")
@@ -37,36 +37,150 @@ private object TorApiPigeonUtils {
)
}
}
fun doubleEquals(a: Double, b: Double): Boolean {
// Normalize -0.0 to 0.0 and handle NaN equality.
return (if (a == 0.0) 0.0 else a) == (if (b == 0.0) 0.0 else b) || (a.isNaN() && b.isNaN())
}
fun floatEquals(a: Float, b: Float): Boolean {
// Normalize -0.0 to 0.0 and handle NaN equality.
return (if (a == 0.0f) 0.0f else a) == (if (b == 0.0f) 0.0f else b) || (a.isNaN() && b.isNaN())
}
fun doubleHash(d: Double): Int {
// Normalize -0.0 to 0.0 and handle NaN to ensure consistent hash codes.
val normalized = if (d == 0.0) 0.0 else d
val bits = java.lang.Double.doubleToLongBits(normalized)
return (bits xor (bits ushr 32)).toInt()
}
fun floatHash(f: Float): Int {
// Normalize -0.0 to 0.0 and handle NaN to ensure consistent hash codes.
val normalized = if (f == 0.0f) 0.0f else f
return java.lang.Float.floatToIntBits(normalized)
}
fun deepEquals(a: Any?, b: Any?): Boolean {
if (a === b) {
return true
}
if (a == null || b == null) {
return false
}
if (a is ByteArray && b is ByteArray) {
return a.contentEquals(b)
return a.contentEquals(b)
}
if (a is IntArray && b is IntArray) {
return a.contentEquals(b)
return a.contentEquals(b)
}
if (a is LongArray && b is LongArray) {
return a.contentEquals(b)
return a.contentEquals(b)
}
if (a is DoubleArray && b is DoubleArray) {
return a.contentEquals(b)
if (a.size != b.size) return false
for (i in a.indices) {
if (!doubleEquals(a[i], b[i])) return false
}
return true
}
if (a is FloatArray && b is FloatArray) {
if (a.size != b.size) return false
for (i in a.indices) {
if (!floatEquals(a[i], b[i])) return false
}
return true
}
if (a is Array<*> && b is Array<*>) {
return a.size == b.size &&
a.indices.all{ deepEquals(a[it], b[it]) }
if (a.size != b.size) return false
for (i in a.indices) {
if (!deepEquals(a[i], b[i])) return false
}
return true
}
if (a is List<*> && b is List<*>) {
return a.size == b.size &&
a.indices.all{ deepEquals(a[it], b[it]) }
if (a.size != b.size) return false
val iterA = a.iterator()
val iterB = b.iterator()
while (iterA.hasNext() && iterB.hasNext()) {
if (!deepEquals(iterA.next(), iterB.next())) return false
}
return true
}
if (a is Map<*, *> && b is Map<*, *>) {
return a.size == b.size && a.all {
(b as Map<Any?, Any?>).contains(it.key) &&
deepEquals(it.value, b[it.key])
if (a.size != b.size) return false
for (entry in a) {
val key = entry.key
var found = false
for (bEntry in b) {
if (deepEquals(key, bEntry.key)) {
if (deepEquals(entry.value, bEntry.value)) {
found = true
break
} else {
return false
}
}
}
if (!found) return false
}
return true
}
if (a is Double && b is Double) {
return doubleEquals(a, b)
}
if (a is Float && b is Float) {
return floatEquals(a, b)
}
return a == b
}
fun deepHash(value: Any?): Int {
return when (value) {
null -> 0
is ByteArray -> value.contentHashCode()
is IntArray -> value.contentHashCode()
is LongArray -> value.contentHashCode()
is DoubleArray -> {
var result = 1
for (item in value) {
result = 31 * result + doubleHash(item)
}
result
}
is FloatArray -> {
var result = 1
for (item in value) {
result = 31 * result + floatHash(item)
}
result
}
is Array<*> -> {
var result = 1
for (item in value) {
result = 31 * result + deepHash(item)
}
result
}
is List<*> -> {
var result = 1
for (item in value) {
result = 31 * result + deepHash(item)
}
result
}
is Map<*, *> -> {
var result = 0
for (entry in value) {
result += ((deepHash(entry.key) * 31) xor deepHash(entry.value))
}
result
}
is Double -> doubleHash(value)
is Float -> floatHash(value)
else -> value.hashCode()
}
}
}
/**
@@ -145,15 +259,25 @@ data class TorConfiguration (
)
}
override fun equals(other: Any?): Boolean {
if (other !is TorConfiguration) {
if (other == null || other.javaClass != javaClass) {
return false
}
if (this === other) {
return true
}
return TorApiPigeonUtils.deepEquals(toList(), other.toList()) }
val other = other as TorConfiguration
return TorApiPigeonUtils.deepEquals(this.transport, other.transport) && TorApiPigeonUtils.deepEquals(this.bridgeLines, other.bridgeLines) && TorApiPigeonUtils.deepEquals(this.entryNodeCountries, other.entryNodeCountries) && TorApiPigeonUtils.deepEquals(this.exitNodeCountries, other.exitNodeCountries) && TorApiPigeonUtils.deepEquals(this.strictNodes, other.strictNodes)
}
override fun hashCode(): Int = toList().hashCode()
override fun hashCode(): Int {
var result = javaClass.hashCode()
result = 31 * result + TorApiPigeonUtils.deepHash(this.transport)
result = 31 * result + TorApiPigeonUtils.deepHash(this.bridgeLines)
result = 31 * result + TorApiPigeonUtils.deepHash(this.entryNodeCountries)
result = 31 * result + TorApiPigeonUtils.deepHash(this.exitNodeCountries)
result = 31 * result + TorApiPigeonUtils.deepHash(this.strictNodes)
return result
}
}
/**
@@ -194,15 +318,25 @@ data class TorStatus (
)
}
override fun equals(other: Any?): Boolean {
if (other !is TorStatus) {
if (other == null || other.javaClass != javaClass) {
return false
}
if (this === other) {
return true
}
return TorApiPigeonUtils.deepEquals(toList(), other.toList()) }
val other = other as TorStatus
return TorApiPigeonUtils.deepEquals(this.isRunning, other.isRunning) && TorApiPigeonUtils.deepEquals(this.socksPort, other.socksPort) && TorApiPigeonUtils.deepEquals(this.bootstrapProgress, other.bootstrapProgress) && TorApiPigeonUtils.deepEquals(this.currentCircuit, other.currentCircuit) && TorApiPigeonUtils.deepEquals(this.exitNodeCountry, other.exitNodeCountry)
}
override fun hashCode(): Int = toList().hashCode()
override fun hashCode(): Int {
var result = javaClass.hashCode()
result = 31 * result + TorApiPigeonUtils.deepHash(this.isRunning)
result = 31 * result + TorApiPigeonUtils.deepHash(this.socksPort)
result = 31 * result + TorApiPigeonUtils.deepHash(this.bootstrapProgress)
result = 31 * result + TorApiPigeonUtils.deepHash(this.currentCircuit)
result = 31 * result + TorApiPigeonUtils.deepHash(this.exitNodeCountry)
return result
}
}
/**
@@ -235,15 +369,23 @@ data class TorLogMessage (
)
}
override fun equals(other: Any?): Boolean {
if (other !is TorLogMessage) {
if (other == null || other.javaClass != javaClass) {
return false
}
if (this === other) {
return true
}
return TorApiPigeonUtils.deepEquals(toList(), other.toList()) }
val other = other as TorLogMessage
return TorApiPigeonUtils.deepEquals(this.severity, other.severity) && TorApiPigeonUtils.deepEquals(this.message, other.message) && TorApiPigeonUtils.deepEquals(this.timestamp, other.timestamp)
}
override fun hashCode(): Int = toList().hashCode()
override fun hashCode(): Int {
var result = javaClass.hashCode()
result = 31 * result + TorApiPigeonUtils.deepHash(this.severity)
result = 31 * result + TorApiPigeonUtils.deepHash(this.message)
result = 31 * result + TorApiPigeonUtils.deepHash(this.timestamp)
return result
}
}
private open class TorApiPigeonCodec : StandardMessageCodec() {
override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? {
+143 -122
View File
@@ -1,20 +1,40 @@
// Autogenerated from Pigeon (v26.1.7), do not edit directly.
// Autogenerated from Pigeon (v26.3.2), do not edit directly.
// See also: https://pub.dev/packages/pigeon
// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, omit_obvious_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers
// ignore_for_file: unused_import, unused_shown_name
// ignore_for_file: type=lint
import 'dart:async';
import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List;
import 'dart:typed_data' show Float64List, Int32List, Int64List;
import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer;
import 'package:flutter/services.dart';
import 'package:meta/meta.dart' show immutable, protected, visibleForTesting;
PlatformException _createConnectionError(String channelName) {
return PlatformException(
code: 'channel-error',
message: 'Unable to establish connection on channel: "$channelName".',
);
Object? _extractReplyValueOrThrow(
List<Object?>? replyList,
String channelName, {
required bool isNullValid,
}) {
if (replyList == null) {
throw PlatformException(
code: 'channel-error',
message: 'Unable to establish connection on channel: "$channelName".',
);
} else if (replyList.length > 1) {
throw PlatformException(
code: replyList[0]! as String,
message: replyList[1] as String?,
details: replyList[2],
);
} else if (!isNullValid && (replyList.isNotEmpty && replyList[0] == null)) {
throw PlatformException(
code: 'null-error',
message: 'Host platform returned null value for non-null return value.',
);
}
return replyList.firstOrNull;
}
List<Object?> wrapResponse({Object? result, PlatformException? error, bool empty = false}) {
if (empty) {
return <Object?>[];
@@ -25,19 +45,67 @@ List<Object?> wrapResponse({Object? result, PlatformException? error, bool empty
return <Object?>[error.code, error.message, error.details];
}
bool _deepEquals(Object? a, Object? b) {
if (identical(a, b)) {
return true;
}
if (a is double && b is double) {
if (a.isNaN && b.isNaN) {
return true;
}
return a == b;
}
if (a is List && b is List) {
return a.length == b.length &&
a.indexed
.every(((int, dynamic) item) => _deepEquals(item.$2, b[item.$1]));
.every(((int, dynamic) item) => _deepEquals(item.$2, b[item.$1]));
}
if (a is Map && b is Map) {
return a.length == b.length && a.entries.every((MapEntry<Object?, Object?> entry) =>
(b as Map<Object?, Object?>).containsKey(entry.key) &&
_deepEquals(entry.value, b[entry.key]));
if (a.length != b.length) {
return false;
}
for (final MapEntry<Object?, Object?> entryA in a.entries) {
bool found = false;
for (final MapEntry<Object?, Object?> entryB in b.entries) {
if (_deepEquals(entryA.key, entryB.key)) {
if (_deepEquals(entryA.value, entryB.value)) {
found = true;
break;
} else {
return false;
}
}
}
if (!found) {
return false;
}
}
return true;
}
return a == b;
}
int _deepHash(Object? value) {
if (value is List) {
return Object.hashAll(value.map(_deepHash));
}
if (value is Map) {
int result = 0;
for (final MapEntry<Object?, Object?> entry in value.entries) {
result += (_deepHash(entry.key) * 31) ^ _deepHash(entry.value);
}
return result;
}
if (value is double && value.isNaN) {
// Normalize NaN to a consistent hash.
return 0x7FF8000000000000.hashCode;
}
if (value is double && value == 0.0) {
// Normalize -0.0 to 0.0 so they have the same hash code.
return 0.0.hashCode;
}
return value.hashCode;
}
/// Transport types for Tor connections
enum TransportType {
@@ -101,7 +169,7 @@ class TorConfiguration {
result as List<Object?>;
return TorConfiguration(
transport: result[0]! as TransportType,
bridgeLines: (result[1] as List<Object?>?)!.cast<String>(),
bridgeLines: (result[1]! as List<Object?>).cast<String>(),
entryNodeCountries: result[2] as String?,
exitNodeCountries: result[3] as String?,
strictNodes: result[4] as bool?,
@@ -117,13 +185,12 @@ class TorConfiguration {
if (identical(this, other)) {
return true;
}
return _deepEquals(encode(), other.encode());
return _deepEquals(transport, other.transport) && _deepEquals(bridgeLines, other.bridgeLines) && _deepEquals(entryNodeCountries, other.entryNodeCountries) && _deepEquals(exitNodeCountries, other.exitNodeCountries) && _deepEquals(strictNodes, other.strictNodes);
}
@override
// ignore: avoid_equals_and_hash_code_on_mutable_classes
int get hashCode => Object.hashAll(_toList())
;
int get hashCode => _deepHash(<Object?>[runtimeType, ..._toList()]);
}
/// Current Tor status
@@ -184,13 +251,12 @@ class TorStatus {
if (identical(this, other)) {
return true;
}
return _deepEquals(encode(), other.encode());
return _deepEquals(isRunning, other.isRunning) && _deepEquals(socksPort, other.socksPort) && _deepEquals(bootstrapProgress, other.bootstrapProgress) && _deepEquals(currentCircuit, other.currentCircuit) && _deepEquals(exitNodeCountry, other.exitNodeCountry);
}
@override
// ignore: avoid_equals_and_hash_code_on_mutable_classes
int get hashCode => Object.hashAll(_toList())
;
int get hashCode => _deepHash(<Object?>[runtimeType, ..._toList()]);
}
/// Log message from Tor
@@ -239,13 +305,12 @@ class TorLogMessage {
if (identical(this, other)) {
return true;
}
return _deepEquals(encode(), other.encode());
return _deepEquals(severity, other.severity) && _deepEquals(message, other.message) && _deepEquals(timestamp, other.timestamp);
}
@override
// ignore: avoid_equals_and_hash_code_on_mutable_classes
int get hashCode => Object.hashAll(_toList())
;
int get hashCode => _deepHash(<Object?>[runtimeType, ..._toList()]);
}
@@ -276,14 +341,14 @@ class _PigeonCodec extends StandardMessageCodec {
@override
Object? readValueOfType(int type, ReadBuffer buffer) {
switch (type) {
case 129:
case 129:
final value = readValue(buffer) as int?;
return value == null ? null : TransportType.values[value];
case 130:
case 130:
return TorConfiguration.decode(readValue(buffer)!);
case 131:
case 131:
return TorStatus.decode(readValue(buffer)!);
case 132:
case 132:
return TorLogMessage.decode(readValue(buffer)!);
default:
return super.readValueOfType(type, buffer);
@@ -316,22 +381,14 @@ class TorApi {
);
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(<Object?>[config]);
final pigeonVar_replyList = await pigeonVar_sendFuture 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 if (pigeonVar_replyList[0] == null) {
throw PlatformException(
code: 'null-error',
message: 'Host platform returned null value for non-null return value.',
);
} else {
return (pigeonVar_replyList[0] as int?)!;
}
final Object? pigeonVar_replyValue = _extractReplyValueOrThrow(
pigeonVar_replyList,
pigeonVar_channelName,
isNullValid: false,
)
;
return pigeonVar_replyValue! as int;
}
/// Stop Tor
@@ -344,17 +401,13 @@ class TorApi {
);
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(null);
final pigeonVar_replyList = await pigeonVar_sendFuture 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;
}
_extractReplyValueOrThrow(
pigeonVar_replyList,
pigeonVar_channelName,
isNullValid: true,
)
;
}
/// Get current status
@@ -367,22 +420,14 @@ class TorApi {
);
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(null);
final pigeonVar_replyList = await pigeonVar_sendFuture 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 if (pigeonVar_replyList[0] == null) {
throw PlatformException(
code: 'null-error',
message: 'Host platform returned null value for non-null return value.',
);
} else {
return (pigeonVar_replyList[0] as TorStatus?)!;
}
final Object? pigeonVar_replyValue = _extractReplyValueOrThrow(
pigeonVar_replyList,
pigeonVar_channelName,
isNullValid: false,
)
;
return pigeonVar_replyValue! as TorStatus;
}
/// Request a new Tor identity (new circuit)
@@ -395,17 +440,13 @@ class TorApi {
);
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(null);
final pigeonVar_replyList = await pigeonVar_sendFuture 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;
}
_extractReplyValueOrThrow(
pigeonVar_replyList,
pigeonVar_channelName,
isNullValid: true,
)
;
}
}
@@ -429,14 +470,10 @@ abstract class TorLogApi {
pigeonVar_channel.setMessageHandler(null);
} else {
pigeonVar_channel.setMessageHandler((Object? message) async {
assert(message != null,
'Argument for dev.flutter.pigeon.flutter_tor.TorLogApi.onLogMessage was null.');
final List<Object?> args = (message as List<Object?>?)!;
final TorLogMessage? arg_log = (args[0] as TorLogMessage?);
assert(arg_log != null,
'Argument for dev.flutter.pigeon.flutter_tor.TorLogApi.onLogMessage was null, expected non-null TorLogMessage.');
final List<Object?> args = message! as List<Object?>;
final TorLogMessage arg_log = args[0]! as TorLogMessage;
try {
api.onLogMessage(arg_log!);
api.onLogMessage(arg_log);
return wrapResponse(empty: true);
} on PlatformException catch (e) {
return wrapResponse(error: e);
@@ -454,14 +491,10 @@ abstract class TorLogApi {
pigeonVar_channel.setMessageHandler(null);
} else {
pigeonVar_channel.setMessageHandler((Object? message) async {
assert(message != null,
'Argument for dev.flutter.pigeon.flutter_tor.TorLogApi.onStatusChanged was null.');
final List<Object?> args = (message as List<Object?>?)!;
final TorStatus? arg_status = (args[0] as TorStatus?);
assert(arg_status != null,
'Argument for dev.flutter.pigeon.flutter_tor.TorLogApi.onStatusChanged was null, expected non-null TorStatus.');
final List<Object?> args = message! as List<Object?>;
final TorStatus arg_status = args[0]! as TorStatus;
try {
api.onStatusChanged(arg_status!);
api.onStatusChanged(arg_status);
return wrapResponse(empty: true);
} on PlatformException catch (e) {
return wrapResponse(error: e);
@@ -496,22 +529,14 @@ class IPtProxyController {
);
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(<Object?>[proxyType, proxy]);
final pigeonVar_replyList = await pigeonVar_sendFuture 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 if (pigeonVar_replyList[0] == null) {
throw PlatformException(
code: 'null-error',
message: 'Host platform returned null value for non-null return value.',
);
} else {
return (pigeonVar_replyList[0] as int?)!;
}
final Object? pigeonVar_replyValue = _extractReplyValueOrThrow(
pigeonVar_replyList,
pigeonVar_channelName,
isNullValid: false,
)
;
return pigeonVar_replyValue! as int;
}
Future<void> stop(TransportType proxyType) async {
@@ -523,16 +548,12 @@ class IPtProxyController {
);
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(<Object?>[proxyType]);
final pigeonVar_replyList = await pigeonVar_sendFuture 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;
}
_extractReplyValueOrThrow(
pigeonVar_replyList,
pigeonVar_channelName,
isNullValid: true,
)
;
}
}
@@ -1,4 +1,4 @@
// Autogenerated from Pigeon (v26.1.7), do not edit directly.
// Autogenerated from Pigeon (v26.3.2), do not edit directly.
// See also: https://pub.dev/packages/pigeon
@file:Suppress("UNCHECKED_CAST", "ArrayInDataClass")
@@ -34,36 +34,150 @@ private object LocalesPigeonUtils {
)
}
}
fun doubleEquals(a: Double, b: Double): Boolean {
// Normalize -0.0 to 0.0 and handle NaN equality.
return (if (a == 0.0) 0.0 else a) == (if (b == 0.0) 0.0 else b) || (a.isNaN() && b.isNaN())
}
fun floatEquals(a: Float, b: Float): Boolean {
// Normalize -0.0 to 0.0 and handle NaN equality.
return (if (a == 0.0f) 0.0f else a) == (if (b == 0.0f) 0.0f else b) || (a.isNaN() && b.isNaN())
}
fun doubleHash(d: Double): Int {
// Normalize -0.0 to 0.0 and handle NaN to ensure consistent hash codes.
val normalized = if (d == 0.0) 0.0 else d
val bits = java.lang.Double.doubleToLongBits(normalized)
return (bits xor (bits ushr 32)).toInt()
}
fun floatHash(f: Float): Int {
// Normalize -0.0 to 0.0 and handle NaN to ensure consistent hash codes.
val normalized = if (f == 0.0f) 0.0f else f
return java.lang.Float.floatToIntBits(normalized)
}
fun deepEquals(a: Any?, b: Any?): Boolean {
if (a === b) {
return true
}
if (a == null || b == null) {
return false
}
if (a is ByteArray && b is ByteArray) {
return a.contentEquals(b)
return a.contentEquals(b)
}
if (a is IntArray && b is IntArray) {
return a.contentEquals(b)
return a.contentEquals(b)
}
if (a is LongArray && b is LongArray) {
return a.contentEquals(b)
return a.contentEquals(b)
}
if (a is DoubleArray && b is DoubleArray) {
return a.contentEquals(b)
if (a.size != b.size) return false
for (i in a.indices) {
if (!doubleEquals(a[i], b[i])) return false
}
return true
}
if (a is FloatArray && b is FloatArray) {
if (a.size != b.size) return false
for (i in a.indices) {
if (!floatEquals(a[i], b[i])) return false
}
return true
}
if (a is Array<*> && b is Array<*>) {
return a.size == b.size &&
a.indices.all{ deepEquals(a[it], b[it]) }
if (a.size != b.size) return false
for (i in a.indices) {
if (!deepEquals(a[i], b[i])) return false
}
return true
}
if (a is List<*> && b is List<*>) {
return a.size == b.size &&
a.indices.all{ deepEquals(a[it], b[it]) }
if (a.size != b.size) return false
val iterA = a.iterator()
val iterB = b.iterator()
while (iterA.hasNext() && iterB.hasNext()) {
if (!deepEquals(iterA.next(), iterB.next())) return false
}
return true
}
if (a is Map<*, *> && b is Map<*, *>) {
return a.size == b.size && a.all {
(b as Map<Any?, Any?>).contains(it.key) &&
deepEquals(it.value, b[it.key])
if (a.size != b.size) return false
for (entry in a) {
val key = entry.key
var found = false
for (bEntry in b) {
if (deepEquals(key, bEntry.key)) {
if (deepEquals(entry.value, bEntry.value)) {
found = true
break
} else {
return false
}
}
}
if (!found) return false
}
return true
}
if (a is Double && b is Double) {
return doubleEquals(a, b)
}
if (a is Float && b is Float) {
return floatEquals(a, b)
}
return a == b
}
fun deepHash(value: Any?): Int {
return when (value) {
null -> 0
is ByteArray -> value.contentHashCode()
is IntArray -> value.contentHashCode()
is LongArray -> value.contentHashCode()
is DoubleArray -> {
var result = 1
for (item in value) {
result = 31 * result + doubleHash(item)
}
result
}
is FloatArray -> {
var result = 1
for (item in value) {
result = 31 * result + floatHash(item)
}
result
}
is Array<*> -> {
var result = 1
for (item in value) {
result = 31 * result + deepHash(item)
}
result
}
is List<*> -> {
var result = 1
for (item in value) {
result = 31 * result + deepHash(item)
}
result
}
is Map<*, *> -> {
var result = 0
for (entry in value) {
result += ((deepHash(entry.key) * 31) xor deepHash(entry.value))
}
result
}
is Double -> doubleHash(value)
is Float -> floatHash(value)
else -> value.hashCode()
}
}
}
/**
@@ -98,15 +212,22 @@ data class LocalizedResult (
)
}
override fun equals(other: Any?): Boolean {
if (other !is LocalizedResult) {
if (other == null || other.javaClass != javaClass) {
return false
}
if (this === other) {
return true
}
return LocalesPigeonUtils.deepEquals(toList(), other.toList()) }
val other = other as LocalizedResult
return LocalesPigeonUtils.deepEquals(this.languageName, other.languageName) && LocalesPigeonUtils.deepEquals(this.countryName, other.countryName)
}
override fun hashCode(): Int = toList().hashCode()
override fun hashCode(): Int {
var result = javaClass.hashCode()
result = 31 * result + LocalesPigeonUtils.deepHash(this.languageName)
result = 31 * result + LocalesPigeonUtils.deepHash(this.countryName)
return result
}
}
private open class LocalesPigeonCodec : StandardMessageCodec() {
override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? {
@@ -1,33 +1,101 @@
// Autogenerated from Pigeon (v26.1.7), do not edit directly.
// Autogenerated from Pigeon (v26.3.2), do not edit directly.
// See also: https://pub.dev/packages/pigeon
// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, omit_obvious_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers
// ignore_for_file: unused_import, unused_shown_name
// ignore_for_file: type=lint
import 'dart:async';
import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List;
import 'dart:typed_data' show Float64List, Int32List, Int64List;
import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer;
import 'package:flutter/services.dart';
import 'package:meta/meta.dart' show immutable, protected, visibleForTesting;
PlatformException _createConnectionError(String channelName) {
return PlatformException(
code: 'channel-error',
message: 'Unable to establish connection on channel: "$channelName".',
);
Object? _extractReplyValueOrThrow(
List<Object?>? replyList,
String channelName, {
required bool isNullValid,
}) {
if (replyList == null) {
throw PlatformException(
code: 'channel-error',
message: 'Unable to establish connection on channel: "$channelName".',
);
} else if (replyList.length > 1) {
throw PlatformException(
code: replyList[0]! as String,
message: replyList[1] as String?,
details: replyList[2],
);
} else if (!isNullValid && (replyList.isNotEmpty && replyList[0] == null)) {
throw PlatformException(
code: 'null-error',
message: 'Host platform returned null value for non-null return value.',
);
}
return replyList.firstOrNull;
}
bool _deepEquals(Object? a, Object? b) {
if (identical(a, b)) {
return true;
}
if (a is double && b is double) {
if (a.isNaN && b.isNaN) {
return true;
}
return a == b;
}
if (a is List && b is List) {
return a.length == b.length &&
a.indexed
.every(((int, dynamic) item) => _deepEquals(item.$2, b[item.$1]));
.every(((int, dynamic) item) => _deepEquals(item.$2, b[item.$1]));
}
if (a is Map && b is Map) {
return a.length == b.length && a.entries.every((MapEntry<Object?, Object?> entry) =>
(b as Map<Object?, Object?>).containsKey(entry.key) &&
_deepEquals(entry.value, b[entry.key]));
if (a.length != b.length) {
return false;
}
for (final MapEntry<Object?, Object?> entryA in a.entries) {
bool found = false;
for (final MapEntry<Object?, Object?> entryB in b.entries) {
if (_deepEquals(entryA.key, entryB.key)) {
if (_deepEquals(entryA.value, entryB.value)) {
found = true;
break;
} else {
return false;
}
}
}
if (!found) {
return false;
}
}
return true;
}
return a == b;
}
int _deepHash(Object? value) {
if (value is List) {
return Object.hashAll(value.map(_deepHash));
}
if (value is Map) {
int result = 0;
for (final MapEntry<Object?, Object?> entry in value.entries) {
result += (_deepHash(entry.key) * 31) ^ _deepHash(entry.value);
}
return result;
}
if (value is double && value.isNaN) {
// Normalize NaN to a consistent hash.
return 0x7FF8000000000000.hashCode;
}
if (value is double && value == 0.0) {
// Normalize -0.0 to 0.0 so they have the same hash code.
return 0.0.hashCode;
}
return value.hashCode;
}
class LocalizedResult {
LocalizedResult({
@@ -66,13 +134,12 @@ class LocalizedResult {
if (identical(this, other)) {
return true;
}
return _deepEquals(encode(), other.encode());
return _deepEquals(languageName, other.languageName) && _deepEquals(countryName, other.countryName);
}
@override
// ignore: avoid_equals_and_hash_code_on_mutable_classes
int get hashCode => Object.hashAll(_toList())
;
int get hashCode => _deepHash(<Object?>[runtimeType, ..._toList()]);
}
@@ -94,7 +161,7 @@ class _PigeonCodec extends StandardMessageCodec {
@override
Object? readValueOfType(int type, ReadBuffer buffer) {
switch (type) {
case 129:
case 129:
return LocalizedResult.decode(readValue(buffer)!);
default:
return super.readValueOfType(type, buffer);
@@ -124,21 +191,13 @@ class LocaleResolver {
);
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(<Object?>[languageTag, targetLangouageTag]);
final pigeonVar_replyList = await pigeonVar_sendFuture 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 if (pigeonVar_replyList[0] == null) {
throw PlatformException(
code: 'null-error',
message: 'Host platform returned null value for non-null return value.',
);
} else {
return (pigeonVar_replyList[0] as LocalizedResult?)!;
}
final Object? pigeonVar_replyValue = _extractReplyValueOrThrow(
pigeonVar_replyList,
pigeonVar_channelName,
isNullValid: false,
)
;
return pigeonVar_replyValue! as LocalizedResult;
}
}
@@ -1,4 +1,4 @@
// Autogenerated from Pigeon (v26.1.7), do not edit directly.
// Autogenerated from Pigeon (v26.3.2), do not edit directly.
// See also: https://pub.dev/packages/pigeon
@file:Suppress("UNCHECKED_CAST", "ArrayInDataClass")
@@ -17,36 +17,150 @@ private object IntentPigeonUtils {
fun createConnectionError(channelName: String): FlutterError {
return FlutterError("channel-error", "Unable to establish connection on channel: '$channelName'.", "") }
fun doubleEquals(a: Double, b: Double): Boolean {
// Normalize -0.0 to 0.0 and handle NaN equality.
return (if (a == 0.0) 0.0 else a) == (if (b == 0.0) 0.0 else b) || (a.isNaN() && b.isNaN())
}
fun floatEquals(a: Float, b: Float): Boolean {
// Normalize -0.0 to 0.0 and handle NaN equality.
return (if (a == 0.0f) 0.0f else a) == (if (b == 0.0f) 0.0f else b) || (a.isNaN() && b.isNaN())
}
fun doubleHash(d: Double): Int {
// Normalize -0.0 to 0.0 and handle NaN to ensure consistent hash codes.
val normalized = if (d == 0.0) 0.0 else d
val bits = java.lang.Double.doubleToLongBits(normalized)
return (bits xor (bits ushr 32)).toInt()
}
fun floatHash(f: Float): Int {
// Normalize -0.0 to 0.0 and handle NaN to ensure consistent hash codes.
val normalized = if (f == 0.0f) 0.0f else f
return java.lang.Float.floatToIntBits(normalized)
}
fun deepEquals(a: Any?, b: Any?): Boolean {
if (a === b) {
return true
}
if (a == null || b == null) {
return false
}
if (a is ByteArray && b is ByteArray) {
return a.contentEquals(b)
return a.contentEquals(b)
}
if (a is IntArray && b is IntArray) {
return a.contentEquals(b)
return a.contentEquals(b)
}
if (a is LongArray && b is LongArray) {
return a.contentEquals(b)
return a.contentEquals(b)
}
if (a is DoubleArray && b is DoubleArray) {
return a.contentEquals(b)
if (a.size != b.size) return false
for (i in a.indices) {
if (!doubleEquals(a[i], b[i])) return false
}
return true
}
if (a is FloatArray && b is FloatArray) {
if (a.size != b.size) return false
for (i in a.indices) {
if (!floatEquals(a[i], b[i])) return false
}
return true
}
if (a is Array<*> && b is Array<*>) {
return a.size == b.size &&
a.indices.all{ deepEquals(a[it], b[it]) }
if (a.size != b.size) return false
for (i in a.indices) {
if (!deepEquals(a[i], b[i])) return false
}
return true
}
if (a is List<*> && b is List<*>) {
return a.size == b.size &&
a.indices.all{ deepEquals(a[it], b[it]) }
if (a.size != b.size) return false
val iterA = a.iterator()
val iterB = b.iterator()
while (iterA.hasNext() && iterB.hasNext()) {
if (!deepEquals(iterA.next(), iterB.next())) return false
}
return true
}
if (a is Map<*, *> && b is Map<*, *>) {
return a.size == b.size && a.all {
(b as Map<Any?, Any?>).contains(it.key) &&
deepEquals(it.value, b[it.key])
if (a.size != b.size) return false
for (entry in a) {
val key = entry.key
var found = false
for (bEntry in b) {
if (deepEquals(key, bEntry.key)) {
if (deepEquals(entry.value, bEntry.value)) {
found = true
break
} else {
return false
}
}
}
if (!found) return false
}
return true
}
if (a is Double && b is Double) {
return doubleEquals(a, b)
}
if (a is Float && b is Float) {
return floatEquals(a, b)
}
return a == b
}
fun deepHash(value: Any?): Int {
return when (value) {
null -> 0
is ByteArray -> value.contentHashCode()
is IntArray -> value.contentHashCode()
is LongArray -> value.contentHashCode()
is DoubleArray -> {
var result = 1
for (item in value) {
result = 31 * result + doubleHash(item)
}
result
}
is FloatArray -> {
var result = 1
for (item in value) {
result = 31 * result + floatHash(item)
}
result
}
is Array<*> -> {
var result = 1
for (item in value) {
result = 31 * result + deepHash(item)
}
result
}
is List<*> -> {
var result = 1
for (item in value) {
result = 31 * result + deepHash(item)
}
result
}
is Map<*, *> -> {
var result = 0
for (entry in value) {
result += ((deepHash(entry.key) * 31) xor deepHash(entry.value))
}
result
}
is Double -> doubleHash(value)
is Float -> floatHash(value)
else -> value.hashCode()
}
}
}
/**
@@ -93,15 +207,26 @@ data class Intent (
)
}
override fun equals(other: Any?): Boolean {
if (other !is Intent) {
if (other == null || other.javaClass != javaClass) {
return false
}
if (this === other) {
return true
}
return IntentPigeonUtils.deepEquals(toList(), other.toList()) }
val other = other as Intent
return IntentPigeonUtils.deepEquals(this.fromPackageName, other.fromPackageName) && IntentPigeonUtils.deepEquals(this.action, other.action) && IntentPigeonUtils.deepEquals(this.data, other.data) && IntentPigeonUtils.deepEquals(this.categories, other.categories) && IntentPigeonUtils.deepEquals(this.mimeType, other.mimeType) && IntentPigeonUtils.deepEquals(this.extra, other.extra)
}
override fun hashCode(): Int = toList().hashCode()
override fun hashCode(): Int {
var result = javaClass.hashCode()
result = 31 * result + IntentPigeonUtils.deepHash(this.fromPackageName)
result = 31 * result + IntentPigeonUtils.deepHash(this.action)
result = 31 * result + IntentPigeonUtils.deepHash(this.data)
result = 31 * result + IntentPigeonUtils.deepHash(this.categories)
result = 31 * result + IntentPigeonUtils.deepHash(this.mimeType)
result = 31 * result + IntentPigeonUtils.deepHash(this.extra)
return result
}
}
private open class IntentPigeonCodec : StandardMessageCodec() {
override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? {
@@ -1,12 +1,13 @@
// Autogenerated from Pigeon (v26.1.7), do not edit directly.
// Autogenerated from Pigeon (v26.3.2), do not edit directly.
// See also: https://pub.dev/packages/pigeon
// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, omit_obvious_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers
// ignore_for_file: unused_import, unused_shown_name
// ignore_for_file: type=lint
import 'dart:async';
import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List;
import 'dart:typed_data' show Float64List, Int32List, Int64List;
import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer;
import 'package:flutter/services.dart';
import 'package:meta/meta.dart' show immutable, protected, visibleForTesting;
List<Object?> wrapResponse({Object? result, PlatformException? error, bool empty = false}) {
if (empty) {
@@ -18,19 +19,67 @@ List<Object?> wrapResponse({Object? result, PlatformException? error, bool empty
return <Object?>[error.code, error.message, error.details];
}
bool _deepEquals(Object? a, Object? b) {
if (identical(a, b)) {
return true;
}
if (a is double && b is double) {
if (a.isNaN && b.isNaN) {
return true;
}
return a == b;
}
if (a is List && b is List) {
return a.length == b.length &&
a.indexed
.every(((int, dynamic) item) => _deepEquals(item.$2, b[item.$1]));
.every(((int, dynamic) item) => _deepEquals(item.$2, b[item.$1]));
}
if (a is Map && b is Map) {
return a.length == b.length && a.entries.every((MapEntry<Object?, Object?> entry) =>
(b as Map<Object?, Object?>).containsKey(entry.key) &&
_deepEquals(entry.value, b[entry.key]));
if (a.length != b.length) {
return false;
}
for (final MapEntry<Object?, Object?> entryA in a.entries) {
bool found = false;
for (final MapEntry<Object?, Object?> entryB in b.entries) {
if (_deepEquals(entryA.key, entryB.key)) {
if (_deepEquals(entryA.value, entryB.value)) {
found = true;
break;
} else {
return false;
}
}
}
if (!found) {
return false;
}
}
return true;
}
return a == b;
}
int _deepHash(Object? value) {
if (value is List) {
return Object.hashAll(value.map(_deepHash));
}
if (value is Map) {
int result = 0;
for (final MapEntry<Object?, Object?> entry in value.entries) {
result += (_deepHash(entry.key) * 31) ^ _deepHash(entry.value);
}
return result;
}
if (value is double && value.isNaN) {
// Normalize NaN to a consistent hash.
return 0x7FF8000000000000.hashCode;
}
if (value is double && value == 0.0) {
// Normalize -0.0 to 0.0 so they have the same hash code.
return 0.0.hashCode;
}
return value.hashCode;
}
class Intent {
Intent({
@@ -74,9 +123,9 @@ class Intent {
fromPackageName: result[0] as String?,
action: result[1] as String?,
data: result[2] as String?,
categories: (result[3] as List<Object?>?)!.cast<String>(),
categories: (result[3]! as List<Object?>).cast<String>(),
mimeType: result[4] as String?,
extra: (result[5] as Map<Object?, Object?>?)!.cast<String, Object?>(),
extra: (result[5]! as Map<Object?, Object?>).cast<String, Object?>(),
);
}
@@ -89,13 +138,12 @@ class Intent {
if (identical(this, other)) {
return true;
}
return _deepEquals(encode(), other.encode());
return _deepEquals(fromPackageName, other.fromPackageName) && _deepEquals(action, other.action) && _deepEquals(data, other.data) && _deepEquals(categories, other.categories) && _deepEquals(mimeType, other.mimeType) && _deepEquals(extra, other.extra);
}
@override
// ignore: avoid_equals_and_hash_code_on_mutable_classes
int get hashCode => Object.hashAll(_toList())
;
int get hashCode => _deepHash(<Object?>[runtimeType, ..._toList()]);
}
@@ -117,7 +165,7 @@ class _PigeonCodec extends StandardMessageCodec {
@override
Object? readValueOfType(int type, ReadBuffer buffer) {
switch (type) {
case 129:
case 129:
return Intent.decode(readValue(buffer)!);
default:
return super.readValueOfType(type, buffer);
@@ -140,17 +188,11 @@ abstract class IntentEvents {
pigeonVar_channel.setMessageHandler(null);
} else {
pigeonVar_channel.setMessageHandler((Object? message) async {
assert(message != null,
'Argument for dev.flutter.pigeon.simple_intent_receiver.IntentEvents.onIntentReceived was null.');
final List<Object?> args = (message as List<Object?>?)!;
final int? arg_sequence = (args[0] as int?);
assert(arg_sequence != null,
'Argument for dev.flutter.pigeon.simple_intent_receiver.IntentEvents.onIntentReceived was null, expected non-null int.');
final Intent? arg_intent = (args[1] as Intent?);
assert(arg_intent != null,
'Argument for dev.flutter.pigeon.simple_intent_receiver.IntentEvents.onIntentReceived was null, expected non-null Intent.');
final List<Object?> args = message! as List<Object?>;
final int arg_sequence = args[0]! as int;
final Intent arg_intent = args[1]! as Intent;
try {
api.onIntentReceived(arg_sequence!, arg_intent!);
api.onIntentReceived(arg_sequence, arg_intent);
return wrapResponse(empty: true);
} on PlatformException catch (e) {
return wrapResponse(error: e);
@@ -1,4 +1,4 @@
// Autogenerated from Pigeon (v26.1.7), do not edit directly.
// Autogenerated from Pigeon (v26.3.2), do not edit directly.
// See also: https://pub.dev/packages/pigeon
@file:Suppress("UNCHECKED_CAST", "ArrayInDataClass")
@@ -1,20 +1,40 @@
// Autogenerated from Pigeon (v26.1.7), do not edit directly.
// Autogenerated from Pigeon (v26.3.2), do not edit directly.
// See also: https://pub.dev/packages/pigeon
// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, omit_obvious_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers
// ignore_for_file: unused_import, unused_shown_name
// ignore_for_file: type=lint
import 'dart:async';
import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List;
import 'dart:typed_data' show Float64List, Int32List, Int64List;
import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer;
import 'package:flutter/services.dart';
import 'package:meta/meta.dart' show immutable, protected, visibleForTesting;
PlatformException _createConnectionError(String channelName) {
return PlatformException(
code: 'channel-error',
message: 'Unable to establish connection on channel: "$channelName".',
);
Object? _extractReplyValueOrThrow(
List<Object?>? replyList,
String channelName, {
required bool isNullValid,
}) {
if (replyList == null) {
throw PlatformException(
code: 'channel-error',
message: 'Unable to establish connection on channel: "$channelName".',
);
} else if (replyList.length > 1) {
throw PlatformException(
code: replyList[0]! as String,
message: replyList[1] as String?,
details: replyList[2],
);
} else if (!isNullValid && (replyList.isNotEmpty && replyList[0] == null)) {
throw PlatformException(
code: 'null-error',
message: 'Host platform returned null value for non-null return value.',
);
}
return replyList.firstOrNull;
}
List<Object?> wrapResponse({Object? result, PlatformException? error, bool empty = false}) {
if (empty) {
return <Object?>[];
@@ -77,22 +97,14 @@ class SpeechToTextApi {
);
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(<Object?>[locale]);
final pigeonVar_replyList = await pigeonVar_sendFuture 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 if (pigeonVar_replyList[0] == null) {
throw PlatformException(
code: 'null-error',
message: 'Host platform returned null value for non-null return value.',
);
} else {
return (pigeonVar_replyList[0] as bool?)!;
}
final Object? pigeonVar_replyValue = _extractReplyValueOrThrow(
pigeonVar_replyList,
pigeonVar_channelName,
isNullValid: false,
)
;
return pigeonVar_replyValue! as bool;
}
}
@@ -116,14 +128,10 @@ abstract class SpeechToTextEvents {
pigeonVar_channel.setMessageHandler(null);
} else {
pigeonVar_channel.setMessageHandler((Object? message) async {
assert(message != null,
'Argument for dev.flutter.pigeon.speech_to_text_dialog.SpeechToTextEvents.onTextReceived was null.');
final List<Object?> args = (message as List<Object?>?)!;
final String? arg_text = (args[0] as String?);
assert(arg_text != null,
'Argument for dev.flutter.pigeon.speech_to_text_dialog.SpeechToTextEvents.onTextReceived was null, expected non-null String.');
final List<Object?> args = message! as List<Object?>;
final String arg_text = args[0]! as String;
try {
api.onTextReceived(arg_text!);
api.onTextReceived(arg_text);
return wrapResponse(empty: true);
} on PlatformException catch (e) {
return wrapResponse(error: e);