- no stubs for iOS and macOS yet Signed-off-by: Peter Siegmund <developer@mars3142.org>
This commit is contained in:
@@ -49,9 +49,13 @@ android {
|
||||
|
||||
testLogging {
|
||||
events "passed", "skipped", "failed", "standardOut", "standardError"
|
||||
outputs.upToDateWhen {false}
|
||||
outputs.upToDateWhen { false }
|
||||
showStandardStreams = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buildFeatures {
|
||||
buildConfig = true
|
||||
}
|
||||
}
|
||||
+399
-3
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2026, Org Mars3142
|
||||
// Copyright (c) 2026, mars3142
|
||||
// Autogenerated from Pigeon (v26.3.4), do not edit directly.
|
||||
// See also: https://pub.dev/packages/pigeon
|
||||
@file:Suppress("UNCHECKED_CAST", "ArrayInDataClass")
|
||||
@@ -34,6 +34,150 @@ private object MessagesPigeonUtils {
|
||||
)
|
||||
}
|
||||
}
|
||||
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)
|
||||
}
|
||||
if (a is IntArray && b is IntArray) {
|
||||
return a.contentEquals(b)
|
||||
}
|
||||
if (a is LongArray && b is LongArray) {
|
||||
return a.contentEquals(b)
|
||||
}
|
||||
if (a is DoubleArray && b is DoubleArray) {
|
||||
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<*>) {
|
||||
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<*>) {
|
||||
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<*, *>) {
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -47,12 +191,126 @@ class FlutterError (
|
||||
override val message: String? = null,
|
||||
val details: Any? = null
|
||||
) : RuntimeException()
|
||||
|
||||
/** Generated class from Pigeon that represents data sent in messages. */
|
||||
data class App (
|
||||
val packageName: String,
|
||||
val appName: String,
|
||||
val installedBy: String,
|
||||
val icon: ByteArray
|
||||
)
|
||||
{
|
||||
companion object {
|
||||
fun fromList(pigeonVar_list: List<Any?>): App {
|
||||
val packageName = pigeonVar_list[0] as String
|
||||
val appName = pigeonVar_list[1] as String
|
||||
val installedBy = pigeonVar_list[2] as String
|
||||
val icon = pigeonVar_list[3] as ByteArray
|
||||
return App(packageName, appName, installedBy, icon)
|
||||
}
|
||||
}
|
||||
fun toList(): List<Any?> {
|
||||
return listOf(
|
||||
packageName,
|
||||
appName,
|
||||
installedBy,
|
||||
icon,
|
||||
)
|
||||
}
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other == null || other.javaClass != javaClass) {
|
||||
return false
|
||||
}
|
||||
if (this === other) {
|
||||
return true
|
||||
}
|
||||
val other = other as App
|
||||
return MessagesPigeonUtils.deepEquals(this.packageName, other.packageName) && MessagesPigeonUtils.deepEquals(this.appName, other.appName) && MessagesPigeonUtils.deepEquals(this.installedBy, other.installedBy) && MessagesPigeonUtils.deepEquals(this.icon, other.icon)
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = javaClass.hashCode()
|
||||
result = 31 * result + MessagesPigeonUtils.deepHash(this.packageName)
|
||||
result = 31 * result + MessagesPigeonUtils.deepHash(this.appName)
|
||||
result = 31 * result + MessagesPigeonUtils.deepHash(this.installedBy)
|
||||
result = 31 * result + MessagesPigeonUtils.deepHash(this.icon)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
/** Generated class from Pigeon that represents data sent in messages. */
|
||||
data class Toast (
|
||||
val app: App,
|
||||
val message: String,
|
||||
val timestamp: Long,
|
||||
val duration: Long
|
||||
)
|
||||
{
|
||||
companion object {
|
||||
fun fromList(pigeonVar_list: List<Any?>): Toast {
|
||||
val app = pigeonVar_list[0] as App
|
||||
val message = pigeonVar_list[1] as String
|
||||
val timestamp = pigeonVar_list[2] as Long
|
||||
val duration = pigeonVar_list[3] as Long
|
||||
return Toast(app, message, timestamp, duration)
|
||||
}
|
||||
}
|
||||
fun toList(): List<Any?> {
|
||||
return listOf(
|
||||
app,
|
||||
message,
|
||||
timestamp,
|
||||
duration,
|
||||
)
|
||||
}
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other == null || other.javaClass != javaClass) {
|
||||
return false
|
||||
}
|
||||
if (this === other) {
|
||||
return true
|
||||
}
|
||||
val other = other as Toast
|
||||
return MessagesPigeonUtils.deepEquals(this.app, other.app) && MessagesPigeonUtils.deepEquals(this.message, other.message) && MessagesPigeonUtils.deepEquals(this.timestamp, other.timestamp) && MessagesPigeonUtils.deepEquals(this.duration, other.duration)
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = javaClass.hashCode()
|
||||
result = 31 * result + MessagesPigeonUtils.deepHash(this.app)
|
||||
result = 31 * result + MessagesPigeonUtils.deepHash(this.message)
|
||||
result = 31 * result + MessagesPigeonUtils.deepHash(this.timestamp)
|
||||
result = 31 * result + MessagesPigeonUtils.deepHash(this.duration)
|
||||
return result
|
||||
}
|
||||
}
|
||||
private open class MessagesPigeonCodec : StandardMessageCodec() {
|
||||
override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? {
|
||||
return super.readValueOfType(type, buffer)
|
||||
return when (type) {
|
||||
129.toByte() -> {
|
||||
return (readValue(buffer) as? List<Any?>)?.let {
|
||||
App.fromList(it)
|
||||
}
|
||||
}
|
||||
130.toByte() -> {
|
||||
return (readValue(buffer) as? List<Any?>)?.let {
|
||||
Toast.fromList(it)
|
||||
}
|
||||
}
|
||||
else -> super.readValueOfType(type, buffer)
|
||||
}
|
||||
}
|
||||
override fun writeValue(stream: ByteArrayOutputStream, value: Any?) {
|
||||
super.writeValue(stream, value)
|
||||
when (value) {
|
||||
is App -> {
|
||||
stream.write(129)
|
||||
writeValue(stream, value.toList())
|
||||
}
|
||||
is Toast -> {
|
||||
stream.write(130)
|
||||
writeValue(stream, value.toList())
|
||||
}
|
||||
else -> super.writeValue(stream, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,6 +318,13 @@ private open class MessagesPigeonCodec : StandardMessageCodec() {
|
||||
/** Generated interface from Pigeon that represents a handler of messages from Flutter. */
|
||||
interface ToasterUtilsApi {
|
||||
fun getPlatformName(callback: (Result<String?>) -> Unit)
|
||||
fun getInstalledApps(callback: (Result<List<App>>) -> Unit)
|
||||
fun getInstalledApp(packageName: String, callback: (Result<App?>) -> Unit)
|
||||
fun getToasts(packageName: String, callback: (Result<List<Toast>>) -> Unit)
|
||||
fun getToastFiltered(packageName: String, from: Long, callback: (Result<List<Toast>>) -> Unit)
|
||||
fun isServiceRunning(callback: (Result<Boolean>) -> Unit)
|
||||
fun showSettings(callback: (Result<Unit>) -> Unit)
|
||||
fun exampleToast(callback: (Result<Unit>) -> Unit)
|
||||
|
||||
companion object {
|
||||
/** The codec used by ToasterUtilsApi. */
|
||||
@@ -88,6 +353,137 @@ interface ToasterUtilsApi {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.toaster_utils.ToasterUtilsApi.getInstalledApps$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { _, reply ->
|
||||
api.getInstalledApps{ result: Result<List<App>> ->
|
||||
val error = result.exceptionOrNull()
|
||||
if (error != null) {
|
||||
reply.reply(MessagesPigeonUtils.wrapError(error))
|
||||
} else {
|
||||
val data = result.getOrNull()
|
||||
reply.reply(MessagesPigeonUtils.wrapResult(data))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.toaster_utils.ToasterUtilsApi.getInstalledApp$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { message, reply ->
|
||||
val args = message as List<Any?>
|
||||
val packageNameArg = args[0] as String
|
||||
api.getInstalledApp(packageNameArg) { result: Result<App?> ->
|
||||
val error = result.exceptionOrNull()
|
||||
if (error != null) {
|
||||
reply.reply(MessagesPigeonUtils.wrapError(error))
|
||||
} else {
|
||||
val data = result.getOrNull()
|
||||
reply.reply(MessagesPigeonUtils.wrapResult(data))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.toaster_utils.ToasterUtilsApi.getToasts$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { message, reply ->
|
||||
val args = message as List<Any?>
|
||||
val packageNameArg = args[0] as String
|
||||
api.getToasts(packageNameArg) { result: Result<List<Toast>> ->
|
||||
val error = result.exceptionOrNull()
|
||||
if (error != null) {
|
||||
reply.reply(MessagesPigeonUtils.wrapError(error))
|
||||
} else {
|
||||
val data = result.getOrNull()
|
||||
reply.reply(MessagesPigeonUtils.wrapResult(data))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.toaster_utils.ToasterUtilsApi.getToastFiltered$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { message, reply ->
|
||||
val args = message as List<Any?>
|
||||
val packageNameArg = args[0] as String
|
||||
val fromArg = args[1] as Long
|
||||
api.getToastFiltered(packageNameArg, fromArg) { result: Result<List<Toast>> ->
|
||||
val error = result.exceptionOrNull()
|
||||
if (error != null) {
|
||||
reply.reply(MessagesPigeonUtils.wrapError(error))
|
||||
} else {
|
||||
val data = result.getOrNull()
|
||||
reply.reply(MessagesPigeonUtils.wrapResult(data))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.toaster_utils.ToasterUtilsApi.isServiceRunning$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { _, reply ->
|
||||
api.isServiceRunning{ result: Result<Boolean> ->
|
||||
val error = result.exceptionOrNull()
|
||||
if (error != null) {
|
||||
reply.reply(MessagesPigeonUtils.wrapError(error))
|
||||
} else {
|
||||
val data = result.getOrNull()
|
||||
reply.reply(MessagesPigeonUtils.wrapResult(data))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.toaster_utils.ToasterUtilsApi.showSettings$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { _, reply ->
|
||||
api.showSettings{ result: Result<Unit> ->
|
||||
val error = result.exceptionOrNull()
|
||||
if (error != null) {
|
||||
reply.reply(MessagesPigeonUtils.wrapError(error))
|
||||
} else {
|
||||
reply.reply(MessagesPigeonUtils.wrapResult(null))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.toaster_utils.ToasterUtilsApi.exampleToast$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { _, reply ->
|
||||
api.exampleToast{ result: Result<Unit> ->
|
||||
val error = result.exceptionOrNull()
|
||||
if (error != null) {
|
||||
reply.reply(MessagesPigeonUtils.wrapError(error))
|
||||
} else {
|
||||
reply.reply(MessagesPigeonUtils.wrapResult(null))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
channel.setMessageHandler(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+48
-3
@@ -1,14 +1,20 @@
|
||||
package org.mars3142
|
||||
|
||||
import App
|
||||
import Toast
|
||||
import ToasterUtilsApi
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.provider.Settings
|
||||
import io.flutter.embedding.engine.plugins.FlutterPlugin
|
||||
|
||||
class ToasterUtilsPlugin : FlutterPlugin, ToasterUtilsApi {
|
||||
companion object {
|
||||
private const val TAG = "ToasterUtilsPlugin"
|
||||
}
|
||||
private var context: Context? = null
|
||||
|
||||
override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) {
|
||||
context = binding.applicationContext
|
||||
ToasterUtilsApi.setUp(binding.binaryMessenger, this)
|
||||
}
|
||||
|
||||
@@ -19,4 +25,43 @@ class ToasterUtilsPlugin : FlutterPlugin, ToasterUtilsApi {
|
||||
override fun getPlatformName(callback: (Result<String?>) -> Unit) {
|
||||
callback(Result.success("Android ${android.os.Build.VERSION.RELEASE}"))
|
||||
}
|
||||
|
||||
override fun getInstalledApps(callback: (Result<List<App>>) -> Unit) {
|
||||
callback(Result.success(emptyList()))
|
||||
}
|
||||
|
||||
override fun getInstalledApp(packageName: String, callback: (Result<App?>) -> Unit) {
|
||||
callback(Result.success(null))
|
||||
}
|
||||
|
||||
override fun getToasts(packageName: String, callback: (Result<List<Toast>>) -> Unit) {
|
||||
callback(Result.success(emptyList()))
|
||||
}
|
||||
|
||||
override fun getToastFiltered(
|
||||
packageName: String,
|
||||
from: Long,
|
||||
callback: (Result<List<Toast>>) -> Unit
|
||||
) {
|
||||
callback(Result.success(emptyList()))
|
||||
}
|
||||
|
||||
override fun isServiceRunning(callback: (Result<Boolean>) -> Unit) {
|
||||
callback(Result.success(true))
|
||||
}
|
||||
|
||||
override fun showSettings(callback: (Result<Unit>) -> Unit) {
|
||||
context?.startActivity(Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS))
|
||||
callback(Result.success(Unit))
|
||||
}
|
||||
|
||||
override fun exampleToast(callback: (Result<Unit>) -> Unit) {
|
||||
context?.let { ctx ->
|
||||
Handler(Looper.getMainLooper()).post {
|
||||
android.widget.Toast.makeText(ctx, R.string.example_toast, android.widget.Toast.LENGTH_LONG)
|
||||
.show()
|
||||
}
|
||||
}
|
||||
callback(Result.success(Unit))
|
||||
}
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
package org.mars3142.toaster.database
|
||||
|
||||
import android.content.Context
|
||||
import android.database.sqlite.SQLiteDatabase
|
||||
import android.database.sqlite.SQLiteOpenHelper
|
||||
import android.util.Log
|
||||
|
||||
class DatabaseHelper(context: Context?) :
|
||||
SQLiteOpenHelper(context, DATABASE_NAME, null, DATABASE_VERSION) {
|
||||
|
||||
companion object {
|
||||
private const val DATABASE_NAME = "toaster.db3"
|
||||
private const val DATABASE_VERSION = 1
|
||||
private const val TAG = "DatabaseHelper"
|
||||
}
|
||||
|
||||
override fun onCreate(db: SQLiteDatabase) {
|
||||
Log.v(TAG, "create database")
|
||||
ToasterTable.onCreate(db)
|
||||
}
|
||||
|
||||
override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
|
||||
Log.v(TAG, "Upgrading database from version $oldVersion to $newVersion")
|
||||
ToasterTable.onUpgrade(db, oldVersion, newVersion)
|
||||
}
|
||||
|
||||
override fun onDowngrade(db: SQLiteDatabase?, oldVersion: Int, newVersion: Int) {
|
||||
Log.v(TAG, "Downgrading database from version $oldVersion to $newVersion")
|
||||
ToasterTable.onDowngrade(db, oldVersion, newVersion)
|
||||
}
|
||||
}
|
||||
+164
@@ -0,0 +1,164 @@
|
||||
package org.mars3142.toaster.database
|
||||
|
||||
import android.content.ContentProvider
|
||||
import android.content.ContentUris
|
||||
import android.content.ContentValues
|
||||
import android.content.UriMatcher
|
||||
import android.database.Cursor
|
||||
import android.database.SQLException
|
||||
import android.database.sqlite.SQLiteQueryBuilder
|
||||
import android.net.Uri
|
||||
import android.provider.BaseColumns
|
||||
import android.util.Log
|
||||
import io.flutter.BuildConfig
|
||||
|
||||
class ToasterProvider : ContentProvider() {
|
||||
|
||||
companion object {
|
||||
const val AUTHORITY: String = "org.mars3142.toaster"
|
||||
|
||||
private val TAG = ToasterProvider::class.java.simpleName
|
||||
private const val TOASTER = 1
|
||||
private const val TOASTER_ID = 2
|
||||
private const val PACKAGE = 3
|
||||
|
||||
private val toasterMap = hashMapOf<String?, String?>(
|
||||
BaseColumns._ID to BaseColumns._ID,
|
||||
ToasterTable.TIMESTAMP to ToasterTable.TIMESTAMP,
|
||||
ToasterTable.MESSAGE to ToasterTable.MESSAGE,
|
||||
ToasterTable.PACKAGE to ToasterTable.PACKAGE,
|
||||
ToasterTable.VERSIONCODE to ToasterTable.VERSIONCODE,
|
||||
ToasterTable.VERSIONNAME to ToasterTable.VERSIONNAME,
|
||||
BaseColumns._COUNT to BaseColumns._COUNT,
|
||||
)
|
||||
|
||||
private val packageMap = hashMapOf<String?, String?>(
|
||||
ToasterTable.PACKAGE to ToasterTable.PACKAGE,
|
||||
)
|
||||
|
||||
private val mUriMatcher = UriMatcher(UriMatcher.NO_MATCH).apply {
|
||||
addURI(AUTHORITY, "toaster", TOASTER)
|
||||
addURI(AUTHORITY, "toaster/#", TOASTER_ID)
|
||||
addURI(AUTHORITY, "packages", PACKAGE)
|
||||
}
|
||||
}
|
||||
|
||||
private var dbHelper: DatabaseHelper? = null
|
||||
|
||||
override fun onCreate(): Boolean {
|
||||
dbHelper = DatabaseHelper(context)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun query(
|
||||
uri: Uri,
|
||||
projection: Array<String?>?,
|
||||
selection: String?,
|
||||
selectionArgs: Array<String?>?,
|
||||
sortOrder: String?
|
||||
): Cursor? {
|
||||
if (BuildConfig.DEBUG) {
|
||||
Log.v(TAG, "query: uri=$uri projection=${projection.contentToString()} selection=[$selection] args=${selectionArgs.contentToString()} order=[$sortOrder]")
|
||||
}
|
||||
|
||||
val queryBuilder = SQLiteQueryBuilder()
|
||||
val effectiveSortOrder = when (mUriMatcher.match(uri)) {
|
||||
TOASTER -> {
|
||||
queryBuilder.tables = ToasterTable.TABLENAME
|
||||
queryBuilder.projectionMap = toasterMap
|
||||
sortOrder ?: "${ToasterTable.TIMESTAMP} DESC"
|
||||
}
|
||||
TOASTER_ID -> {
|
||||
queryBuilder.tables = ToasterTable.TABLENAME
|
||||
queryBuilder.projectionMap = toasterMap
|
||||
queryBuilder.appendWhere("${BaseColumns._ID} = ${uri.lastPathSegment}")
|
||||
sortOrder
|
||||
}
|
||||
PACKAGE -> {
|
||||
queryBuilder.tables = ToasterTable.TABLENAME
|
||||
queryBuilder.projectionMap = packageMap
|
||||
queryBuilder.isDistinct = true
|
||||
sortOrder ?: "${ToasterTable.PACKAGE} ASC"
|
||||
}
|
||||
else -> throw IllegalArgumentException("Unknown URI: $uri")
|
||||
}
|
||||
|
||||
val database = dbHelper?.readableDatabase ?: return null
|
||||
val cursor = queryBuilder.query(database, projection, selection, selectionArgs, null, null, effectiveSortOrder)
|
||||
context?.let { cursor?.setNotificationUri(it.contentResolver, uri) }
|
||||
return cursor
|
||||
}
|
||||
|
||||
override fun getType(uri: Uri): String {
|
||||
if (BuildConfig.DEBUG) Log.v(TAG, "getType: uri=$uri")
|
||||
return when (mUriMatcher.match(uri)) {
|
||||
TOASTER -> ToasterTable.CONTENT_TYPE
|
||||
TOASTER_ID -> ToasterTable.CONTENT_ITEM_TYPE
|
||||
else -> throw IllegalArgumentException("Unknown URI: $uri")
|
||||
}
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
override fun insert(uri: Uri, initialValues: ContentValues?): Uri? {
|
||||
if (BuildConfig.DEBUG) Log.v(TAG, "insert: uri=$uri initialValues=[$initialValues]")
|
||||
|
||||
if (mUriMatcher.match(uri) != TOASTER) throw IllegalArgumentException("Unknown URI: $uri")
|
||||
|
||||
val values = initialValues?.let { ContentValues(it) } ?: ContentValues()
|
||||
val rowId = dbHelper?.writableDatabase?.insert(ToasterTable.TABLENAME, null, values) ?: 0L
|
||||
if (rowId > 0) {
|
||||
context?.contentResolver?.notifyChange(uri, null)
|
||||
return ContentUris.withAppendedId(ToasterTable.TOASTER_URI, rowId)
|
||||
}
|
||||
throw SQLException("Failed to insert row into $uri")
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
override fun delete(uri: Uri, selection: String?, selectionArgs: Array<String?>?): Int {
|
||||
if (BuildConfig.DEBUG) {
|
||||
Log.v(TAG, "delete: uri=$uri selection=[$selection] args=${selectionArgs.contentToString()}")
|
||||
}
|
||||
|
||||
val database = dbHelper?.writableDatabase ?: return 0
|
||||
val count = when (mUriMatcher.match(uri)) {
|
||||
TOASTER -> database.delete(ToasterTable.TABLENAME, selection, selectionArgs)
|
||||
TOASTER_ID -> {
|
||||
val finalWhere = buildString {
|
||||
append("${BaseColumns._ID} = ${uri.lastPathSegment}")
|
||||
if (selection != null) append(" AND $selection")
|
||||
}
|
||||
database.delete(ToasterTable.TABLENAME, finalWhere, selectionArgs)
|
||||
}
|
||||
else -> throw IllegalArgumentException("Unknown URI: $uri")
|
||||
}
|
||||
context?.contentResolver?.notifyChange(uri, null)
|
||||
return count
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
override fun update(
|
||||
uri: Uri,
|
||||
values: ContentValues?,
|
||||
selection: String?,
|
||||
selectionArgs: Array<String?>?
|
||||
): Int {
|
||||
if (BuildConfig.DEBUG) {
|
||||
Log.v(TAG, "update: uri=$uri values=[$values] selection=[$selection] args=${selectionArgs.contentToString()}")
|
||||
}
|
||||
|
||||
val database = dbHelper?.writableDatabase ?: return 0
|
||||
val count = when (mUriMatcher.match(uri)) {
|
||||
TOASTER -> database.update(ToasterTable.TABLENAME, values, selection, selectionArgs)
|
||||
TOASTER_ID -> {
|
||||
val finalWhere = buildString {
|
||||
append("${BaseColumns._ID} = ${uri.lastPathSegment}")
|
||||
if (selection != null) append(" AND $selection")
|
||||
}
|
||||
database.update(ToasterTable.TABLENAME, values, finalWhere, selectionArgs)
|
||||
}
|
||||
else -> throw IllegalArgumentException("Unknown URI: $uri")
|
||||
}
|
||||
context?.contentResolver?.notifyChange(uri, null)
|
||||
return count
|
||||
}
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
package org.mars3142.toaster.database
|
||||
|
||||
import android.content.ContentResolver
|
||||
import android.database.SQLException
|
||||
import android.database.sqlite.SQLiteDatabase
|
||||
import android.net.Uri
|
||||
import android.provider.BaseColumns
|
||||
import androidx.core.net.toUri
|
||||
|
||||
object ToasterTable : BaseColumns {
|
||||
const val TABLENAME: String = "toaster"
|
||||
const val TIMESTAMP: String = "timestamp"
|
||||
const val PACKAGE: String = "package"
|
||||
const val MESSAGE: String = "message"
|
||||
const val VERSIONCODE: String = "version_code"
|
||||
const val VERSIONNAME: String = "version_name"
|
||||
val TOASTER_URI: Uri = "content://${ToasterProvider.AUTHORITY}/toaster".toUri()
|
||||
val PACKAGE_URI: Uri = "content://${ToasterProvider.AUTHORITY}/packages".toUri()
|
||||
val CONTENT_TYPE: String = "${ContentResolver.CURSOR_DIR_BASE_TYPE}/vnd.mars3142.content.toaster"
|
||||
val CONTENT_ITEM_TYPE: String = "${ContentResolver.CURSOR_ITEM_BASE_TYPE}/vnd.mars3142.content.toaster"
|
||||
|
||||
fun onCreate(db: SQLiteDatabase) {
|
||||
db.execSQL(
|
||||
"""
|
||||
CREATE TABLE $TABLENAME (${BaseColumns._ID} INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
$TIMESTAMP LONG, $PACKAGE TEXT, $MESSAGE TEXT, $VERSIONCODE INTEGER,
|
||||
$VERSIONNAME TEXT );
|
||||
"""
|
||||
)
|
||||
}
|
||||
|
||||
fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
|
||||
if (newVersion > oldVersion) {
|
||||
when (oldVersion) {
|
||||
0 -> try {
|
||||
db.execSQL("ALTER TABLE $TABLENAME ADD COLUMN $VERSIONCODE INTEGER;")
|
||||
db.execSQL("ALTER TABLE $TABLENAME ADD COLUMN $VERSIONNAME TEXT;")
|
||||
} catch (ex: SQLException) {
|
||||
// upgrade already done
|
||||
}
|
||||
|
||||
else -> {
|
||||
db.execSQL("DROP TABLE IF EXISTS $TABLENAME")
|
||||
onCreate(db)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
fun onDowngrade(db: SQLiteDatabase?, oldVersion: Int, newVersion: Int) {}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
package org.mars3142.toaster.services
|
||||
|
||||
import android.accessibilityservice.AccessibilityService
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Notification
|
||||
import android.content.ContentValues
|
||||
import android.content.Intent
|
||||
import android.util.Log
|
||||
import android.view.accessibility.AccessibilityEvent
|
||||
import org.mars3142.toaster.database.ToasterTable
|
||||
|
||||
@SuppressLint("AccessibilityPolicy")
|
||||
class ToasterService : AccessibilityService() {
|
||||
companion object {
|
||||
private val TAG = ToasterService::class.java.simpleName
|
||||
}
|
||||
|
||||
override fun onAccessibilityEvent(event: AccessibilityEvent) {
|
||||
if (event.eventType != AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED) {
|
||||
Log.d(TAG, "Unexpected event type")
|
||||
return
|
||||
}
|
||||
if (event.parcelableData !is Notification) return
|
||||
|
||||
val message = event.text.joinToString("\n") { it.toString() }
|
||||
val cv = ContentValues().apply {
|
||||
put(ToasterTable.PACKAGE, event.packageName as String?)
|
||||
put(ToasterTable.MESSAGE, message)
|
||||
put(ToasterTable.TIMESTAMP, System.currentTimeMillis())
|
||||
}
|
||||
contentResolver.insert(ToasterTable.TOASTER_URI, cv)
|
||||
sendBroadcast(Intent("org.mars3142.toaster.APPWIDGET_UPDATE"))
|
||||
}
|
||||
|
||||
override fun onInterrupt() {}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="example_toast">This is just an example toast.</string>
|
||||
</resources>
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2026, Org Mars3142
|
||||
// Copyright (c) 2026, mars3142
|
||||
// Autogenerated from Pigeon (v26.3.4), do not edit directly.
|
||||
// See also: https://pub.dev/packages/pigeon
|
||||
// ignore_for_file: unused_import, unused_shown_name
|
||||
@@ -35,6 +35,178 @@ Object? _extractReplyValueOrThrow(
|
||||
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]));
|
||||
}
|
||||
if (a is Map && b is Map) {
|
||||
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 App {
|
||||
App({
|
||||
required this.packageName,
|
||||
required this.appName,
|
||||
required this.installedBy,
|
||||
required this.icon,
|
||||
});
|
||||
|
||||
String packageName;
|
||||
|
||||
String appName;
|
||||
|
||||
String installedBy;
|
||||
|
||||
Uint8List icon;
|
||||
|
||||
List<Object?> _toList() {
|
||||
return <Object?>[
|
||||
packageName,
|
||||
appName,
|
||||
installedBy,
|
||||
icon,
|
||||
];
|
||||
}
|
||||
|
||||
Object encode() {
|
||||
return _toList(); }
|
||||
|
||||
static App decode(Object result) {
|
||||
result as List<Object?>;
|
||||
return App(
|
||||
packageName: result[0]! as String,
|
||||
appName: result[1]! as String,
|
||||
installedBy: result[2]! as String,
|
||||
icon: result[3]! as Uint8List,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
// ignore: avoid_equals_and_hash_code_on_mutable_classes
|
||||
bool operator ==(Object other) {
|
||||
if (other is! App || other.runtimeType != runtimeType) {
|
||||
return false;
|
||||
}
|
||||
if (identical(this, other)) {
|
||||
return true;
|
||||
}
|
||||
return _deepEquals(packageName, other.packageName) && _deepEquals(appName, other.appName) && _deepEquals(installedBy, other.installedBy) && _deepEquals(icon, other.icon);
|
||||
}
|
||||
|
||||
@override
|
||||
// ignore: avoid_equals_and_hash_code_on_mutable_classes
|
||||
int get hashCode => _deepHash(<Object?>[runtimeType, ..._toList()]);
|
||||
}
|
||||
|
||||
class Toast {
|
||||
Toast({
|
||||
required this.app,
|
||||
required this.message,
|
||||
required this.timestamp,
|
||||
required this.duration,
|
||||
});
|
||||
|
||||
App app;
|
||||
|
||||
String message;
|
||||
|
||||
int timestamp;
|
||||
|
||||
int duration;
|
||||
|
||||
List<Object?> _toList() {
|
||||
return <Object?>[
|
||||
app,
|
||||
message,
|
||||
timestamp,
|
||||
duration,
|
||||
];
|
||||
}
|
||||
|
||||
Object encode() {
|
||||
return _toList(); }
|
||||
|
||||
static Toast decode(Object result) {
|
||||
result as List<Object?>;
|
||||
return Toast(
|
||||
app: result[0]! as App,
|
||||
message: result[1]! as String,
|
||||
timestamp: result[2]! as int,
|
||||
duration: result[3]! as int,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
// ignore: avoid_equals_and_hash_code_on_mutable_classes
|
||||
bool operator ==(Object other) {
|
||||
if (other is! Toast || other.runtimeType != runtimeType) {
|
||||
return false;
|
||||
}
|
||||
if (identical(this, other)) {
|
||||
return true;
|
||||
}
|
||||
return _deepEquals(app, other.app) && _deepEquals(message, other.message) && _deepEquals(timestamp, other.timestamp) && _deepEquals(duration, other.duration);
|
||||
}
|
||||
|
||||
@override
|
||||
// ignore: avoid_equals_and_hash_code_on_mutable_classes
|
||||
int get hashCode => _deepHash(<Object?>[runtimeType, ..._toList()]);
|
||||
}
|
||||
|
||||
|
||||
class _PigeonCodec extends StandardMessageCodec {
|
||||
@@ -44,6 +216,12 @@ class _PigeonCodec extends StandardMessageCodec {
|
||||
if (value is int) {
|
||||
buffer.putUint8(4);
|
||||
buffer.putInt64(value);
|
||||
} else if (value is App) {
|
||||
buffer.putUint8(129);
|
||||
writeValue(buffer, value.encode());
|
||||
} else if (value is Toast) {
|
||||
buffer.putUint8(130);
|
||||
writeValue(buffer, value.encode());
|
||||
} else {
|
||||
super.writeValue(buffer, value);
|
||||
}
|
||||
@@ -52,6 +230,10 @@ class _PigeonCodec extends StandardMessageCodec {
|
||||
@override
|
||||
Object? readValueOfType(int type, ReadBuffer buffer) {
|
||||
switch (type) {
|
||||
case 129:
|
||||
return App.decode(readValue(buffer)!);
|
||||
case 130:
|
||||
return Toast.decode(readValue(buffer)!);
|
||||
default:
|
||||
return super.readValueOfType(type, buffer);
|
||||
}
|
||||
@@ -89,4 +271,135 @@ class ToasterUtilsApi {
|
||||
;
|
||||
return pigeonVar_replyValue as String?;
|
||||
}
|
||||
|
||||
Future<List<App>> getInstalledApps() async {
|
||||
final pigeonVar_channelName = 'dev.flutter.pigeon.toaster_utils.ToasterUtilsApi.getInstalledApps$pigeonVar_messageChannelSuffix';
|
||||
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
||||
pigeonVar_channelName,
|
||||
pigeonChannelCodec,
|
||||
binaryMessenger: pigeonVar_binaryMessenger,
|
||||
);
|
||||
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(null);
|
||||
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
|
||||
|
||||
final Object? pigeonVar_replyValue = _extractReplyValueOrThrow(
|
||||
pigeonVar_replyList,
|
||||
pigeonVar_channelName,
|
||||
isNullValid: false,
|
||||
)
|
||||
;
|
||||
return (pigeonVar_replyValue! as List<Object?>).cast<App>();
|
||||
}
|
||||
|
||||
Future<App?> getInstalledApp(String packageName) async {
|
||||
final pigeonVar_channelName = 'dev.flutter.pigeon.toaster_utils.ToasterUtilsApi.getInstalledApp$pigeonVar_messageChannelSuffix';
|
||||
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
||||
pigeonVar_channelName,
|
||||
pigeonChannelCodec,
|
||||
binaryMessenger: pigeonVar_binaryMessenger,
|
||||
);
|
||||
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(<Object?>[packageName]);
|
||||
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
|
||||
|
||||
final Object? pigeonVar_replyValue = _extractReplyValueOrThrow(
|
||||
pigeonVar_replyList,
|
||||
pigeonVar_channelName,
|
||||
isNullValid: true,
|
||||
)
|
||||
;
|
||||
return pigeonVar_replyValue as App?;
|
||||
}
|
||||
|
||||
Future<List<Toast>> getToasts(String packageName) async {
|
||||
final pigeonVar_channelName = 'dev.flutter.pigeon.toaster_utils.ToasterUtilsApi.getToasts$pigeonVar_messageChannelSuffix';
|
||||
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
||||
pigeonVar_channelName,
|
||||
pigeonChannelCodec,
|
||||
binaryMessenger: pigeonVar_binaryMessenger,
|
||||
);
|
||||
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(<Object?>[packageName]);
|
||||
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
|
||||
|
||||
final Object? pigeonVar_replyValue = _extractReplyValueOrThrow(
|
||||
pigeonVar_replyList,
|
||||
pigeonVar_channelName,
|
||||
isNullValid: false,
|
||||
)
|
||||
;
|
||||
return (pigeonVar_replyValue! as List<Object?>).cast<Toast>();
|
||||
}
|
||||
|
||||
Future<List<Toast>> getToastFiltered(String packageName, int from) async {
|
||||
final pigeonVar_channelName = 'dev.flutter.pigeon.toaster_utils.ToasterUtilsApi.getToastFiltered$pigeonVar_messageChannelSuffix';
|
||||
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
||||
pigeonVar_channelName,
|
||||
pigeonChannelCodec,
|
||||
binaryMessenger: pigeonVar_binaryMessenger,
|
||||
);
|
||||
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(<Object?>[packageName, from]);
|
||||
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
|
||||
|
||||
final Object? pigeonVar_replyValue = _extractReplyValueOrThrow(
|
||||
pigeonVar_replyList,
|
||||
pigeonVar_channelName,
|
||||
isNullValid: false,
|
||||
)
|
||||
;
|
||||
return (pigeonVar_replyValue! as List<Object?>).cast<Toast>();
|
||||
}
|
||||
|
||||
Future<bool> isServiceRunning() async {
|
||||
final pigeonVar_channelName = 'dev.flutter.pigeon.toaster_utils.ToasterUtilsApi.isServiceRunning$pigeonVar_messageChannelSuffix';
|
||||
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
||||
pigeonVar_channelName,
|
||||
pigeonChannelCodec,
|
||||
binaryMessenger: pigeonVar_binaryMessenger,
|
||||
);
|
||||
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(null);
|
||||
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
|
||||
|
||||
final Object? pigeonVar_replyValue = _extractReplyValueOrThrow(
|
||||
pigeonVar_replyList,
|
||||
pigeonVar_channelName,
|
||||
isNullValid: false,
|
||||
)
|
||||
;
|
||||
return pigeonVar_replyValue! as bool;
|
||||
}
|
||||
|
||||
Future<void> showSettings() async {
|
||||
final pigeonVar_channelName = 'dev.flutter.pigeon.toaster_utils.ToasterUtilsApi.showSettings$pigeonVar_messageChannelSuffix';
|
||||
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
||||
pigeonVar_channelName,
|
||||
pigeonChannelCodec,
|
||||
binaryMessenger: pigeonVar_binaryMessenger,
|
||||
);
|
||||
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(null);
|
||||
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
|
||||
|
||||
_extractReplyValueOrThrow(
|
||||
pigeonVar_replyList,
|
||||
pigeonVar_channelName,
|
||||
isNullValid: true,
|
||||
)
|
||||
;
|
||||
}
|
||||
|
||||
Future<void> exampleToast() async {
|
||||
final pigeonVar_channelName = 'dev.flutter.pigeon.toaster_utils.ToasterUtilsApi.exampleToast$pigeonVar_messageChannelSuffix';
|
||||
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
||||
pigeonVar_channelName,
|
||||
pigeonChannelCodec,
|
||||
binaryMessenger: pigeonVar_binaryMessenger,
|
||||
);
|
||||
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(null);
|
||||
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
|
||||
|
||||
_extractReplyValueOrThrow(
|
||||
pigeonVar_replyList,
|
||||
pigeonVar_channelName,
|
||||
isNullValid: true,
|
||||
)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
Copyright (c) 2026, Org Mars3142
|
||||
Copyright (c) 2026, mars3142
|
||||
|
||||
@@ -16,4 +16,43 @@ import 'package:pigeon/pigeon.dart';
|
||||
abstract class ToasterUtilsApi {
|
||||
@async
|
||||
String? getPlatformName();
|
||||
|
||||
@async
|
||||
List<App> getInstalledApps();
|
||||
|
||||
@async
|
||||
App? getInstalledApp(String packageName);
|
||||
|
||||
@async
|
||||
List<Toast> getToasts(String packageName);
|
||||
|
||||
@async
|
||||
List<Toast> getToastFiltered(String packageName, int from);
|
||||
|
||||
@async
|
||||
bool isServiceRunning();
|
||||
|
||||
@async
|
||||
void showSettings();
|
||||
|
||||
@async
|
||||
void exampleToast();
|
||||
}
|
||||
|
||||
class App {
|
||||
const App(this.packageName, this.appName, this.installedBy, this.icon);
|
||||
|
||||
final String packageName;
|
||||
final String appName;
|
||||
final String installedBy;
|
||||
final Uint8List icon;
|
||||
}
|
||||
|
||||
class Toast {
|
||||
const Toast(this.app, this.message, this.timestamp, this.duration);
|
||||
|
||||
final App app;
|
||||
final String message;
|
||||
final int timestamp;
|
||||
final int duration;
|
||||
}
|
||||
|
||||
+342
-1
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2026, Org mars3142
|
||||
// Copyright (c) 2026, mars3142
|
||||
// Autogenerated from Pigeon (v26.3.4), do not edit directly.
|
||||
// See also: https://pub.dev/packages/pigeon
|
||||
|
||||
@@ -65,11 +65,233 @@ private func nilOrValue<T>(_ value: Any?) -> T? {
|
||||
return value as! T?
|
||||
}
|
||||
|
||||
private func doubleEqualsMessages(_ lhs: Double, _ rhs: Double) -> Bool {
|
||||
return (lhs.isNaN && rhs.isNaN) || lhs == rhs
|
||||
}
|
||||
|
||||
private func doubleHashMessages(_ value: Double, _ hasher: inout Hasher) {
|
||||
if value.isNaN {
|
||||
hasher.combine(0x7FF8000000000000)
|
||||
} else {
|
||||
// Normalize -0.0 to 0.0
|
||||
hasher.combine(value == 0 ? 0 : value)
|
||||
}
|
||||
}
|
||||
|
||||
func deepEqualsMessages(_ lhs: Any?, _ rhs: Any?) -> Bool {
|
||||
let cleanLhs = nilOrValue(lhs) as Any?
|
||||
let cleanRhs = nilOrValue(rhs) as Any?
|
||||
switch (cleanLhs, cleanRhs) {
|
||||
case (nil, nil):
|
||||
return true
|
||||
|
||||
case (nil, _), (_, nil):
|
||||
return false
|
||||
|
||||
case (let lhs as AnyObject, let rhs as AnyObject) where lhs === rhs:
|
||||
return true
|
||||
|
||||
case is (Void, Void):
|
||||
return true
|
||||
|
||||
case (let lhsArray, let rhsArray) as ([Any?], [Any?]):
|
||||
guard lhsArray.count == rhsArray.count else { return false }
|
||||
for (index, element) in lhsArray.enumerated() {
|
||||
if !deepEqualsMessages(element, rhsArray[index]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
|
||||
case (let lhsArray, let rhsArray) as ([Double], [Double]):
|
||||
guard lhsArray.count == rhsArray.count else { return false }
|
||||
for (index, element) in lhsArray.enumerated() {
|
||||
if !doubleEqualsMessages(element, rhsArray[index]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
|
||||
case (let lhsDictionary, let rhsDictionary) as ([AnyHashable: Any?], [AnyHashable: Any?]):
|
||||
guard lhsDictionary.count == rhsDictionary.count else { return false }
|
||||
for (lhsKey, lhsValue) in lhsDictionary {
|
||||
var found = false
|
||||
for (rhsKey, rhsValue) in rhsDictionary {
|
||||
if deepEqualsMessages(lhsKey, rhsKey) {
|
||||
if deepEqualsMessages(lhsValue, rhsValue) {
|
||||
found = true
|
||||
break
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
if !found { return false }
|
||||
}
|
||||
return true
|
||||
|
||||
case (let lhs as Double, let rhs as Double):
|
||||
return doubleEqualsMessages(lhs, rhs)
|
||||
|
||||
case (let lhsHashable, let rhsHashable) as (AnyHashable, AnyHashable):
|
||||
return lhsHashable == rhsHashable
|
||||
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func deepHashMessages(value: Any?, hasher: inout Hasher) {
|
||||
let cleanValue = nilOrValue(value) as Any?
|
||||
if let cleanValue = cleanValue {
|
||||
if let doubleValue = cleanValue as? Double {
|
||||
doubleHashMessages(doubleValue, &hasher)
|
||||
} else if let valueList = cleanValue as? [Any?] {
|
||||
for item in valueList {
|
||||
deepHashMessages(value: item, hasher: &hasher)
|
||||
}
|
||||
} else if let valueList = cleanValue as? [Double] {
|
||||
for item in valueList {
|
||||
doubleHashMessages(item, &hasher)
|
||||
}
|
||||
} else if let valueDict = cleanValue as? [AnyHashable: Any?] {
|
||||
var result = 0
|
||||
for (key, value) in valueDict {
|
||||
var entryKeyHasher = Hasher()
|
||||
deepHashMessages(value: key, hasher: &entryKeyHasher)
|
||||
var entryValueHasher = Hasher()
|
||||
deepHashMessages(value: value, hasher: &entryValueHasher)
|
||||
result = result &+ ((entryKeyHasher.finalize() &* 31) ^ entryValueHasher.finalize())
|
||||
}
|
||||
hasher.combine(result)
|
||||
} else if let hashableValue = cleanValue as? AnyHashable {
|
||||
hasher.combine(hashableValue)
|
||||
} else {
|
||||
hasher.combine(String(describing: cleanValue))
|
||||
}
|
||||
} else {
|
||||
hasher.combine(0)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Generated class from Pigeon that represents data sent in messages.
|
||||
struct App: Hashable {
|
||||
var packageName: String
|
||||
var appName: String
|
||||
var installedBy: String
|
||||
var icon: FlutterStandardTypedData
|
||||
|
||||
|
||||
// swift-format-ignore: AlwaysUseLowerCamelCase
|
||||
static func fromList(_ pigeonVar_list: [Any?]) -> App? {
|
||||
let packageName = pigeonVar_list[0] as! String
|
||||
let appName = pigeonVar_list[1] as! String
|
||||
let installedBy = pigeonVar_list[2] as! String
|
||||
let icon = pigeonVar_list[3] as! FlutterStandardTypedData
|
||||
|
||||
return App(
|
||||
packageName: packageName,
|
||||
appName: appName,
|
||||
installedBy: installedBy,
|
||||
icon: icon
|
||||
)
|
||||
}
|
||||
func toList() -> [Any?] {
|
||||
return [
|
||||
packageName,
|
||||
appName,
|
||||
installedBy,
|
||||
icon,
|
||||
]
|
||||
}
|
||||
static func == (lhs: App, rhs: App) -> Bool {
|
||||
if Swift.type(of: lhs) != Swift.type(of: rhs) {
|
||||
return false
|
||||
}
|
||||
return deepEqualsMessages(lhs.packageName, rhs.packageName) && deepEqualsMessages(lhs.appName, rhs.appName) && deepEqualsMessages(lhs.installedBy, rhs.installedBy) && deepEqualsMessages(lhs.icon, rhs.icon)
|
||||
}
|
||||
|
||||
func hash(into hasher: inout Hasher) {
|
||||
hasher.combine("App")
|
||||
deepHashMessages(value: packageName, hasher: &hasher)
|
||||
deepHashMessages(value: appName, hasher: &hasher)
|
||||
deepHashMessages(value: installedBy, hasher: &hasher)
|
||||
deepHashMessages(value: icon, hasher: &hasher)
|
||||
}
|
||||
}
|
||||
|
||||
/// Generated class from Pigeon that represents data sent in messages.
|
||||
struct Toast: Hashable {
|
||||
var app: App
|
||||
var message: String
|
||||
var timestamp: Int64
|
||||
var duration: Int64
|
||||
|
||||
|
||||
// swift-format-ignore: AlwaysUseLowerCamelCase
|
||||
static func fromList(_ pigeonVar_list: [Any?]) -> Toast? {
|
||||
let app = pigeonVar_list[0] as! App
|
||||
let message = pigeonVar_list[1] as! String
|
||||
let timestamp = pigeonVar_list[2] as! Int64
|
||||
let duration = pigeonVar_list[3] as! Int64
|
||||
|
||||
return Toast(
|
||||
app: app,
|
||||
message: message,
|
||||
timestamp: timestamp,
|
||||
duration: duration
|
||||
)
|
||||
}
|
||||
func toList() -> [Any?] {
|
||||
return [
|
||||
app,
|
||||
message,
|
||||
timestamp,
|
||||
duration,
|
||||
]
|
||||
}
|
||||
static func == (lhs: Toast, rhs: Toast) -> Bool {
|
||||
if Swift.type(of: lhs) != Swift.type(of: rhs) {
|
||||
return false
|
||||
}
|
||||
return deepEqualsMessages(lhs.app, rhs.app) && deepEqualsMessages(lhs.message, rhs.message) && deepEqualsMessages(lhs.timestamp, rhs.timestamp) && deepEqualsMessages(lhs.duration, rhs.duration)
|
||||
}
|
||||
|
||||
func hash(into hasher: inout Hasher) {
|
||||
hasher.combine("Toast")
|
||||
deepHashMessages(value: app, hasher: &hasher)
|
||||
deepHashMessages(value: message, hasher: &hasher)
|
||||
deepHashMessages(value: timestamp, hasher: &hasher)
|
||||
deepHashMessages(value: duration, hasher: &hasher)
|
||||
}
|
||||
}
|
||||
|
||||
private class MessagesPigeonCodecReader: FlutterStandardReader {
|
||||
override func readValue(ofType type: UInt8) -> Any? {
|
||||
switch type {
|
||||
case 129:
|
||||
return App.fromList(self.readValue() as! [Any?])
|
||||
case 130:
|
||||
return Toast.fromList(self.readValue() as! [Any?])
|
||||
default:
|
||||
return super.readValue(ofType: type)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class MessagesPigeonCodecWriter: FlutterStandardWriter {
|
||||
override func writeValue(_ value: Any) {
|
||||
if let value = value as? App {
|
||||
super.writeByte(129)
|
||||
super.writeValue(value.toList())
|
||||
} else if let value = value as? Toast {
|
||||
super.writeByte(130)
|
||||
super.writeValue(value.toList())
|
||||
} else {
|
||||
super.writeValue(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class MessagesPigeonCodecReaderWriter: FlutterStandardReaderWriter {
|
||||
@@ -90,6 +312,13 @@ class MessagesPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable {
|
||||
/// Generated protocol from Pigeon that represents a handler of messages from Flutter.
|
||||
protocol ToasterUtilsApi {
|
||||
func getPlatformName(completion: @escaping (Result<String?, Error>) -> Void)
|
||||
func getInstalledApps(completion: @escaping (Result<[App], Error>) -> Void)
|
||||
func getInstalledApp(packageName: String, completion: @escaping (Result<App?, Error>) -> Void)
|
||||
func getToasts(packageName: String, completion: @escaping (Result<[Toast], Error>) -> Void)
|
||||
func getToastFiltered(packageName: String, from: Int64, completion: @escaping (Result<[Toast], Error>) -> Void)
|
||||
func isServiceRunning(completion: @escaping (Result<Bool, Error>) -> Void)
|
||||
func showSettings(completion: @escaping (Result<Void, Error>) -> Void)
|
||||
func exampleToast(completion: @escaping (Result<Void, Error>) -> Void)
|
||||
}
|
||||
|
||||
/// Generated setup class from Pigeon to handle messages through the `binaryMessenger`.
|
||||
@@ -113,5 +342,117 @@ class ToasterUtilsApiSetup {
|
||||
} else {
|
||||
getPlatformNameChannel.setMessageHandler(nil)
|
||||
}
|
||||
let getInstalledAppsChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.toaster_utils.ToasterUtilsApi.getInstalledApps\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
getInstalledAppsChannel.setMessageHandler { _, reply in
|
||||
api.getInstalledApps { result in
|
||||
switch result {
|
||||
case .success(let res):
|
||||
reply(wrapResult(res))
|
||||
case .failure(let error):
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
getInstalledAppsChannel.setMessageHandler(nil)
|
||||
}
|
||||
let getInstalledAppChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.toaster_utils.ToasterUtilsApi.getInstalledApp\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
getInstalledAppChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let packageNameArg = args[0] as! String
|
||||
api.getInstalledApp(packageName: packageNameArg) { result in
|
||||
switch result {
|
||||
case .success(let res):
|
||||
reply(wrapResult(res))
|
||||
case .failure(let error):
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
getInstalledAppChannel.setMessageHandler(nil)
|
||||
}
|
||||
let getToastsChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.toaster_utils.ToasterUtilsApi.getToasts\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
getToastsChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let packageNameArg = args[0] as! String
|
||||
api.getToasts(packageName: packageNameArg) { result in
|
||||
switch result {
|
||||
case .success(let res):
|
||||
reply(wrapResult(res))
|
||||
case .failure(let error):
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
getToastsChannel.setMessageHandler(nil)
|
||||
}
|
||||
let getToastFilteredChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.toaster_utils.ToasterUtilsApi.getToastFiltered\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
getToastFilteredChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let packageNameArg = args[0] as! String
|
||||
let fromArg = args[1] as! Int64
|
||||
api.getToastFiltered(packageName: packageNameArg, from: fromArg) { result in
|
||||
switch result {
|
||||
case .success(let res):
|
||||
reply(wrapResult(res))
|
||||
case .failure(let error):
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
getToastFilteredChannel.setMessageHandler(nil)
|
||||
}
|
||||
let isServiceRunningChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.toaster_utils.ToasterUtilsApi.isServiceRunning\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
isServiceRunningChannel.setMessageHandler { _, reply in
|
||||
api.isServiceRunning { result in
|
||||
switch result {
|
||||
case .success(let res):
|
||||
reply(wrapResult(res))
|
||||
case .failure(let error):
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
isServiceRunningChannel.setMessageHandler(nil)
|
||||
}
|
||||
let showSettingsChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.toaster_utils.ToasterUtilsApi.showSettings\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
showSettingsChannel.setMessageHandler { _, reply in
|
||||
api.showSettings { result in
|
||||
switch result {
|
||||
case .success:
|
||||
reply(wrapResult(nil))
|
||||
case .failure(let error):
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
showSettingsChannel.setMessageHandler(nil)
|
||||
}
|
||||
let exampleToastChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.toaster_utils.ToasterUtilsApi.exampleToast\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
exampleToastChannel.setMessageHandler { _, reply in
|
||||
api.exampleToast { result in
|
||||
switch result {
|
||||
case .success:
|
||||
reply(wrapResult(nil))
|
||||
case .failure(let error):
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
exampleToastChannel.setMessageHandler(nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2026, Org mars3142
|
||||
// Copyright (c) 2026, mars3142
|
||||
// Autogenerated from Pigeon (v26.3.4), do not edit directly.
|
||||
// See also: https://pub.dev/packages/pigeon
|
||||
// ignore_for_file: unused_import, unused_shown_name
|
||||
@@ -35,6 +35,178 @@ Object? _extractReplyValueOrThrow(
|
||||
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]));
|
||||
}
|
||||
if (a is Map && b is Map) {
|
||||
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 App {
|
||||
App({
|
||||
required this.packageName,
|
||||
required this.appName,
|
||||
required this.installedBy,
|
||||
required this.icon,
|
||||
});
|
||||
|
||||
String packageName;
|
||||
|
||||
String appName;
|
||||
|
||||
String installedBy;
|
||||
|
||||
Uint8List icon;
|
||||
|
||||
List<Object?> _toList() {
|
||||
return <Object?>[
|
||||
packageName,
|
||||
appName,
|
||||
installedBy,
|
||||
icon,
|
||||
];
|
||||
}
|
||||
|
||||
Object encode() {
|
||||
return _toList(); }
|
||||
|
||||
static App decode(Object result) {
|
||||
result as List<Object?>;
|
||||
return App(
|
||||
packageName: result[0]! as String,
|
||||
appName: result[1]! as String,
|
||||
installedBy: result[2]! as String,
|
||||
icon: result[3]! as Uint8List,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
// ignore: avoid_equals_and_hash_code_on_mutable_classes
|
||||
bool operator ==(Object other) {
|
||||
if (other is! App || other.runtimeType != runtimeType) {
|
||||
return false;
|
||||
}
|
||||
if (identical(this, other)) {
|
||||
return true;
|
||||
}
|
||||
return _deepEquals(packageName, other.packageName) && _deepEquals(appName, other.appName) && _deepEquals(installedBy, other.installedBy) && _deepEquals(icon, other.icon);
|
||||
}
|
||||
|
||||
@override
|
||||
// ignore: avoid_equals_and_hash_code_on_mutable_classes
|
||||
int get hashCode => _deepHash(<Object?>[runtimeType, ..._toList()]);
|
||||
}
|
||||
|
||||
class Toast {
|
||||
Toast({
|
||||
required this.app,
|
||||
required this.message,
|
||||
required this.timestamp,
|
||||
required this.duration,
|
||||
});
|
||||
|
||||
App app;
|
||||
|
||||
String message;
|
||||
|
||||
int timestamp;
|
||||
|
||||
int duration;
|
||||
|
||||
List<Object?> _toList() {
|
||||
return <Object?>[
|
||||
app,
|
||||
message,
|
||||
timestamp,
|
||||
duration,
|
||||
];
|
||||
}
|
||||
|
||||
Object encode() {
|
||||
return _toList(); }
|
||||
|
||||
static Toast decode(Object result) {
|
||||
result as List<Object?>;
|
||||
return Toast(
|
||||
app: result[0]! as App,
|
||||
message: result[1]! as String,
|
||||
timestamp: result[2]! as int,
|
||||
duration: result[3]! as int,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
// ignore: avoid_equals_and_hash_code_on_mutable_classes
|
||||
bool operator ==(Object other) {
|
||||
if (other is! Toast || other.runtimeType != runtimeType) {
|
||||
return false;
|
||||
}
|
||||
if (identical(this, other)) {
|
||||
return true;
|
||||
}
|
||||
return _deepEquals(app, other.app) && _deepEquals(message, other.message) && _deepEquals(timestamp, other.timestamp) && _deepEquals(duration, other.duration);
|
||||
}
|
||||
|
||||
@override
|
||||
// ignore: avoid_equals_and_hash_code_on_mutable_classes
|
||||
int get hashCode => _deepHash(<Object?>[runtimeType, ..._toList()]);
|
||||
}
|
||||
|
||||
|
||||
class _PigeonCodec extends StandardMessageCodec {
|
||||
@@ -44,6 +216,12 @@ class _PigeonCodec extends StandardMessageCodec {
|
||||
if (value is int) {
|
||||
buffer.putUint8(4);
|
||||
buffer.putInt64(value);
|
||||
} else if (value is App) {
|
||||
buffer.putUint8(129);
|
||||
writeValue(buffer, value.encode());
|
||||
} else if (value is Toast) {
|
||||
buffer.putUint8(130);
|
||||
writeValue(buffer, value.encode());
|
||||
} else {
|
||||
super.writeValue(buffer, value);
|
||||
}
|
||||
@@ -52,6 +230,10 @@ class _PigeonCodec extends StandardMessageCodec {
|
||||
@override
|
||||
Object? readValueOfType(int type, ReadBuffer buffer) {
|
||||
switch (type) {
|
||||
case 129:
|
||||
return App.decode(readValue(buffer)!);
|
||||
case 130:
|
||||
return Toast.decode(readValue(buffer)!);
|
||||
default:
|
||||
return super.readValueOfType(type, buffer);
|
||||
}
|
||||
@@ -89,4 +271,135 @@ class ToasterUtilsApi {
|
||||
;
|
||||
return pigeonVar_replyValue as String?;
|
||||
}
|
||||
|
||||
Future<List<App>> getInstalledApps() async {
|
||||
final pigeonVar_channelName = 'dev.flutter.pigeon.toaster_utils.ToasterUtilsApi.getInstalledApps$pigeonVar_messageChannelSuffix';
|
||||
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
||||
pigeonVar_channelName,
|
||||
pigeonChannelCodec,
|
||||
binaryMessenger: pigeonVar_binaryMessenger,
|
||||
);
|
||||
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(null);
|
||||
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
|
||||
|
||||
final Object? pigeonVar_replyValue = _extractReplyValueOrThrow(
|
||||
pigeonVar_replyList,
|
||||
pigeonVar_channelName,
|
||||
isNullValid: false,
|
||||
)
|
||||
;
|
||||
return (pigeonVar_replyValue! as List<Object?>).cast<App>();
|
||||
}
|
||||
|
||||
Future<App?> getInstalledApp(String packageName) async {
|
||||
final pigeonVar_channelName = 'dev.flutter.pigeon.toaster_utils.ToasterUtilsApi.getInstalledApp$pigeonVar_messageChannelSuffix';
|
||||
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
||||
pigeonVar_channelName,
|
||||
pigeonChannelCodec,
|
||||
binaryMessenger: pigeonVar_binaryMessenger,
|
||||
);
|
||||
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(<Object?>[packageName]);
|
||||
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
|
||||
|
||||
final Object? pigeonVar_replyValue = _extractReplyValueOrThrow(
|
||||
pigeonVar_replyList,
|
||||
pigeonVar_channelName,
|
||||
isNullValid: true,
|
||||
)
|
||||
;
|
||||
return pigeonVar_replyValue as App?;
|
||||
}
|
||||
|
||||
Future<List<Toast>> getToasts(String packageName) async {
|
||||
final pigeonVar_channelName = 'dev.flutter.pigeon.toaster_utils.ToasterUtilsApi.getToasts$pigeonVar_messageChannelSuffix';
|
||||
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
||||
pigeonVar_channelName,
|
||||
pigeonChannelCodec,
|
||||
binaryMessenger: pigeonVar_binaryMessenger,
|
||||
);
|
||||
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(<Object?>[packageName]);
|
||||
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
|
||||
|
||||
final Object? pigeonVar_replyValue = _extractReplyValueOrThrow(
|
||||
pigeonVar_replyList,
|
||||
pigeonVar_channelName,
|
||||
isNullValid: false,
|
||||
)
|
||||
;
|
||||
return (pigeonVar_replyValue! as List<Object?>).cast<Toast>();
|
||||
}
|
||||
|
||||
Future<List<Toast>> getToastFiltered(String packageName, int from) async {
|
||||
final pigeonVar_channelName = 'dev.flutter.pigeon.toaster_utils.ToasterUtilsApi.getToastFiltered$pigeonVar_messageChannelSuffix';
|
||||
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
||||
pigeonVar_channelName,
|
||||
pigeonChannelCodec,
|
||||
binaryMessenger: pigeonVar_binaryMessenger,
|
||||
);
|
||||
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(<Object?>[packageName, from]);
|
||||
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
|
||||
|
||||
final Object? pigeonVar_replyValue = _extractReplyValueOrThrow(
|
||||
pigeonVar_replyList,
|
||||
pigeonVar_channelName,
|
||||
isNullValid: false,
|
||||
)
|
||||
;
|
||||
return (pigeonVar_replyValue! as List<Object?>).cast<Toast>();
|
||||
}
|
||||
|
||||
Future<bool> isServiceRunning() async {
|
||||
final pigeonVar_channelName = 'dev.flutter.pigeon.toaster_utils.ToasterUtilsApi.isServiceRunning$pigeonVar_messageChannelSuffix';
|
||||
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
||||
pigeonVar_channelName,
|
||||
pigeonChannelCodec,
|
||||
binaryMessenger: pigeonVar_binaryMessenger,
|
||||
);
|
||||
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(null);
|
||||
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
|
||||
|
||||
final Object? pigeonVar_replyValue = _extractReplyValueOrThrow(
|
||||
pigeonVar_replyList,
|
||||
pigeonVar_channelName,
|
||||
isNullValid: false,
|
||||
)
|
||||
;
|
||||
return pigeonVar_replyValue! as bool;
|
||||
}
|
||||
|
||||
Future<void> showSettings() async {
|
||||
final pigeonVar_channelName = 'dev.flutter.pigeon.toaster_utils.ToasterUtilsApi.showSettings$pigeonVar_messageChannelSuffix';
|
||||
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
||||
pigeonVar_channelName,
|
||||
pigeonChannelCodec,
|
||||
binaryMessenger: pigeonVar_binaryMessenger,
|
||||
);
|
||||
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(null);
|
||||
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
|
||||
|
||||
_extractReplyValueOrThrow(
|
||||
pigeonVar_replyList,
|
||||
pigeonVar_channelName,
|
||||
isNullValid: true,
|
||||
)
|
||||
;
|
||||
}
|
||||
|
||||
Future<void> exampleToast() async {
|
||||
final pigeonVar_channelName = 'dev.flutter.pigeon.toaster_utils.ToasterUtilsApi.exampleToast$pigeonVar_messageChannelSuffix';
|
||||
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
||||
pigeonVar_channelName,
|
||||
pigeonChannelCodec,
|
||||
binaryMessenger: pigeonVar_binaryMessenger,
|
||||
);
|
||||
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(null);
|
||||
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
|
||||
|
||||
_extractReplyValueOrThrow(
|
||||
pigeonVar_replyList,
|
||||
pigeonVar_channelName,
|
||||
isNullValid: true,
|
||||
)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
Copyright (c) 2026, Org mars3142
|
||||
Copyright (c) 2026, mars3142
|
||||
|
||||
@@ -16,4 +16,43 @@ import 'package:pigeon/pigeon.dart';
|
||||
abstract class ToasterUtilsApi {
|
||||
@async
|
||||
String? getPlatformName();
|
||||
|
||||
@async
|
||||
List<App> getInstalledApps();
|
||||
|
||||
@async
|
||||
App? getInstalledApp(String packageName);
|
||||
|
||||
@async
|
||||
List<Toast> getToasts(String packageName);
|
||||
|
||||
@async
|
||||
List<Toast> getToastFiltered(String packageName, int from);
|
||||
|
||||
@async
|
||||
bool isServiceRunning();
|
||||
|
||||
@async
|
||||
void showSettings();
|
||||
|
||||
@async
|
||||
void exampleToast();
|
||||
}
|
||||
|
||||
class App {
|
||||
const App(this.packageName, this.appName, this.installedBy, this.icon);
|
||||
|
||||
final String packageName;
|
||||
final String appName;
|
||||
final String installedBy;
|
||||
final Uint8List icon;
|
||||
}
|
||||
|
||||
class Toast {
|
||||
const Toast(this.app, this.message, this.timestamp, this.duration);
|
||||
|
||||
final App app;
|
||||
final String message;
|
||||
final int timestamp;
|
||||
final int duration;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2026, Org mars3142
|
||||
// Copyright (c) 2026, mars3142
|
||||
// Autogenerated from Pigeon (v26.3.4), do not edit directly.
|
||||
// See also: https://pub.dev/packages/pigeon
|
||||
// ignore_for_file: unused_import, unused_shown_name
|
||||
@@ -35,6 +35,178 @@ Object? _extractReplyValueOrThrow(
|
||||
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]));
|
||||
}
|
||||
if (a is Map && b is Map) {
|
||||
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 App {
|
||||
App({
|
||||
required this.packageName,
|
||||
required this.appName,
|
||||
required this.installedBy,
|
||||
required this.icon,
|
||||
});
|
||||
|
||||
String packageName;
|
||||
|
||||
String appName;
|
||||
|
||||
String installedBy;
|
||||
|
||||
Uint8List icon;
|
||||
|
||||
List<Object?> _toList() {
|
||||
return <Object?>[
|
||||
packageName,
|
||||
appName,
|
||||
installedBy,
|
||||
icon,
|
||||
];
|
||||
}
|
||||
|
||||
Object encode() {
|
||||
return _toList(); }
|
||||
|
||||
static App decode(Object result) {
|
||||
result as List<Object?>;
|
||||
return App(
|
||||
packageName: result[0]! as String,
|
||||
appName: result[1]! as String,
|
||||
installedBy: result[2]! as String,
|
||||
icon: result[3]! as Uint8List,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
// ignore: avoid_equals_and_hash_code_on_mutable_classes
|
||||
bool operator ==(Object other) {
|
||||
if (other is! App || other.runtimeType != runtimeType) {
|
||||
return false;
|
||||
}
|
||||
if (identical(this, other)) {
|
||||
return true;
|
||||
}
|
||||
return _deepEquals(packageName, other.packageName) && _deepEquals(appName, other.appName) && _deepEquals(installedBy, other.installedBy) && _deepEquals(icon, other.icon);
|
||||
}
|
||||
|
||||
@override
|
||||
// ignore: avoid_equals_and_hash_code_on_mutable_classes
|
||||
int get hashCode => _deepHash(<Object?>[runtimeType, ..._toList()]);
|
||||
}
|
||||
|
||||
class Toast {
|
||||
Toast({
|
||||
required this.app,
|
||||
required this.message,
|
||||
required this.timestamp,
|
||||
required this.duration,
|
||||
});
|
||||
|
||||
App app;
|
||||
|
||||
String message;
|
||||
|
||||
int timestamp;
|
||||
|
||||
int duration;
|
||||
|
||||
List<Object?> _toList() {
|
||||
return <Object?>[
|
||||
app,
|
||||
message,
|
||||
timestamp,
|
||||
duration,
|
||||
];
|
||||
}
|
||||
|
||||
Object encode() {
|
||||
return _toList(); }
|
||||
|
||||
static Toast decode(Object result) {
|
||||
result as List<Object?>;
|
||||
return Toast(
|
||||
app: result[0]! as App,
|
||||
message: result[1]! as String,
|
||||
timestamp: result[2]! as int,
|
||||
duration: result[3]! as int,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
// ignore: avoid_equals_and_hash_code_on_mutable_classes
|
||||
bool operator ==(Object other) {
|
||||
if (other is! Toast || other.runtimeType != runtimeType) {
|
||||
return false;
|
||||
}
|
||||
if (identical(this, other)) {
|
||||
return true;
|
||||
}
|
||||
return _deepEquals(app, other.app) && _deepEquals(message, other.message) && _deepEquals(timestamp, other.timestamp) && _deepEquals(duration, other.duration);
|
||||
}
|
||||
|
||||
@override
|
||||
// ignore: avoid_equals_and_hash_code_on_mutable_classes
|
||||
int get hashCode => _deepHash(<Object?>[runtimeType, ..._toList()]);
|
||||
}
|
||||
|
||||
|
||||
class _PigeonCodec extends StandardMessageCodec {
|
||||
@@ -44,6 +216,12 @@ class _PigeonCodec extends StandardMessageCodec {
|
||||
if (value is int) {
|
||||
buffer.putUint8(4);
|
||||
buffer.putInt64(value);
|
||||
} else if (value is App) {
|
||||
buffer.putUint8(129);
|
||||
writeValue(buffer, value.encode());
|
||||
} else if (value is Toast) {
|
||||
buffer.putUint8(130);
|
||||
writeValue(buffer, value.encode());
|
||||
} else {
|
||||
super.writeValue(buffer, value);
|
||||
}
|
||||
@@ -52,6 +230,10 @@ class _PigeonCodec extends StandardMessageCodec {
|
||||
@override
|
||||
Object? readValueOfType(int type, ReadBuffer buffer) {
|
||||
switch (type) {
|
||||
case 129:
|
||||
return App.decode(readValue(buffer)!);
|
||||
case 130:
|
||||
return Toast.decode(readValue(buffer)!);
|
||||
default:
|
||||
return super.readValueOfType(type, buffer);
|
||||
}
|
||||
@@ -89,4 +271,135 @@ class ToasterUtilsApi {
|
||||
;
|
||||
return pigeonVar_replyValue as String?;
|
||||
}
|
||||
|
||||
Future<List<App>> getInstalledApps() async {
|
||||
final pigeonVar_channelName = 'dev.flutter.pigeon.toaster_utils.ToasterUtilsApi.getInstalledApps$pigeonVar_messageChannelSuffix';
|
||||
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
||||
pigeonVar_channelName,
|
||||
pigeonChannelCodec,
|
||||
binaryMessenger: pigeonVar_binaryMessenger,
|
||||
);
|
||||
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(null);
|
||||
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
|
||||
|
||||
final Object? pigeonVar_replyValue = _extractReplyValueOrThrow(
|
||||
pigeonVar_replyList,
|
||||
pigeonVar_channelName,
|
||||
isNullValid: false,
|
||||
)
|
||||
;
|
||||
return (pigeonVar_replyValue! as List<Object?>).cast<App>();
|
||||
}
|
||||
|
||||
Future<App?> getInstalledApp(String packageName) async {
|
||||
final pigeonVar_channelName = 'dev.flutter.pigeon.toaster_utils.ToasterUtilsApi.getInstalledApp$pigeonVar_messageChannelSuffix';
|
||||
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
||||
pigeonVar_channelName,
|
||||
pigeonChannelCodec,
|
||||
binaryMessenger: pigeonVar_binaryMessenger,
|
||||
);
|
||||
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(<Object?>[packageName]);
|
||||
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
|
||||
|
||||
final Object? pigeonVar_replyValue = _extractReplyValueOrThrow(
|
||||
pigeonVar_replyList,
|
||||
pigeonVar_channelName,
|
||||
isNullValid: true,
|
||||
)
|
||||
;
|
||||
return pigeonVar_replyValue as App?;
|
||||
}
|
||||
|
||||
Future<List<Toast>> getToasts(String packageName) async {
|
||||
final pigeonVar_channelName = 'dev.flutter.pigeon.toaster_utils.ToasterUtilsApi.getToasts$pigeonVar_messageChannelSuffix';
|
||||
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
||||
pigeonVar_channelName,
|
||||
pigeonChannelCodec,
|
||||
binaryMessenger: pigeonVar_binaryMessenger,
|
||||
);
|
||||
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(<Object?>[packageName]);
|
||||
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
|
||||
|
||||
final Object? pigeonVar_replyValue = _extractReplyValueOrThrow(
|
||||
pigeonVar_replyList,
|
||||
pigeonVar_channelName,
|
||||
isNullValid: false,
|
||||
)
|
||||
;
|
||||
return (pigeonVar_replyValue! as List<Object?>).cast<Toast>();
|
||||
}
|
||||
|
||||
Future<List<Toast>> getToastFiltered(String packageName, int from) async {
|
||||
final pigeonVar_channelName = 'dev.flutter.pigeon.toaster_utils.ToasterUtilsApi.getToastFiltered$pigeonVar_messageChannelSuffix';
|
||||
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
||||
pigeonVar_channelName,
|
||||
pigeonChannelCodec,
|
||||
binaryMessenger: pigeonVar_binaryMessenger,
|
||||
);
|
||||
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(<Object?>[packageName, from]);
|
||||
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
|
||||
|
||||
final Object? pigeonVar_replyValue = _extractReplyValueOrThrow(
|
||||
pigeonVar_replyList,
|
||||
pigeonVar_channelName,
|
||||
isNullValid: false,
|
||||
)
|
||||
;
|
||||
return (pigeonVar_replyValue! as List<Object?>).cast<Toast>();
|
||||
}
|
||||
|
||||
Future<bool> isServiceRunning() async {
|
||||
final pigeonVar_channelName = 'dev.flutter.pigeon.toaster_utils.ToasterUtilsApi.isServiceRunning$pigeonVar_messageChannelSuffix';
|
||||
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
||||
pigeonVar_channelName,
|
||||
pigeonChannelCodec,
|
||||
binaryMessenger: pigeonVar_binaryMessenger,
|
||||
);
|
||||
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(null);
|
||||
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
|
||||
|
||||
final Object? pigeonVar_replyValue = _extractReplyValueOrThrow(
|
||||
pigeonVar_replyList,
|
||||
pigeonVar_channelName,
|
||||
isNullValid: false,
|
||||
)
|
||||
;
|
||||
return pigeonVar_replyValue! as bool;
|
||||
}
|
||||
|
||||
Future<void> showSettings() async {
|
||||
final pigeonVar_channelName = 'dev.flutter.pigeon.toaster_utils.ToasterUtilsApi.showSettings$pigeonVar_messageChannelSuffix';
|
||||
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
||||
pigeonVar_channelName,
|
||||
pigeonChannelCodec,
|
||||
binaryMessenger: pigeonVar_binaryMessenger,
|
||||
);
|
||||
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(null);
|
||||
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
|
||||
|
||||
_extractReplyValueOrThrow(
|
||||
pigeonVar_replyList,
|
||||
pigeonVar_channelName,
|
||||
isNullValid: true,
|
||||
)
|
||||
;
|
||||
}
|
||||
|
||||
Future<void> exampleToast() async {
|
||||
final pigeonVar_channelName = 'dev.flutter.pigeon.toaster_utils.ToasterUtilsApi.exampleToast$pigeonVar_messageChannelSuffix';
|
||||
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
||||
pigeonVar_channelName,
|
||||
pigeonChannelCodec,
|
||||
binaryMessenger: pigeonVar_binaryMessenger,
|
||||
);
|
||||
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(null);
|
||||
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
|
||||
|
||||
_extractReplyValueOrThrow(
|
||||
pigeonVar_replyList,
|
||||
pigeonVar_channelName,
|
||||
isNullValid: true,
|
||||
)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
+342
-1
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2026, Org mars3142
|
||||
// Copyright (c) 2026, mars3142
|
||||
// Autogenerated from Pigeon (v26.3.4), do not edit directly.
|
||||
// See also: https://pub.dev/packages/pigeon
|
||||
|
||||
@@ -65,11 +65,233 @@ private func nilOrValue<T>(_ value: Any?) -> T? {
|
||||
return value as! T?
|
||||
}
|
||||
|
||||
private func doubleEqualsMessages(_ lhs: Double, _ rhs: Double) -> Bool {
|
||||
return (lhs.isNaN && rhs.isNaN) || lhs == rhs
|
||||
}
|
||||
|
||||
private func doubleHashMessages(_ value: Double, _ hasher: inout Hasher) {
|
||||
if value.isNaN {
|
||||
hasher.combine(0x7FF8000000000000)
|
||||
} else {
|
||||
// Normalize -0.0 to 0.0
|
||||
hasher.combine(value == 0 ? 0 : value)
|
||||
}
|
||||
}
|
||||
|
||||
func deepEqualsMessages(_ lhs: Any?, _ rhs: Any?) -> Bool {
|
||||
let cleanLhs = nilOrValue(lhs) as Any?
|
||||
let cleanRhs = nilOrValue(rhs) as Any?
|
||||
switch (cleanLhs, cleanRhs) {
|
||||
case (nil, nil):
|
||||
return true
|
||||
|
||||
case (nil, _), (_, nil):
|
||||
return false
|
||||
|
||||
case (let lhs as AnyObject, let rhs as AnyObject) where lhs === rhs:
|
||||
return true
|
||||
|
||||
case is (Void, Void):
|
||||
return true
|
||||
|
||||
case (let lhsArray, let rhsArray) as ([Any?], [Any?]):
|
||||
guard lhsArray.count == rhsArray.count else { return false }
|
||||
for (index, element) in lhsArray.enumerated() {
|
||||
if !deepEqualsMessages(element, rhsArray[index]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
|
||||
case (let lhsArray, let rhsArray) as ([Double], [Double]):
|
||||
guard lhsArray.count == rhsArray.count else { return false }
|
||||
for (index, element) in lhsArray.enumerated() {
|
||||
if !doubleEqualsMessages(element, rhsArray[index]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
|
||||
case (let lhsDictionary, let rhsDictionary) as ([AnyHashable: Any?], [AnyHashable: Any?]):
|
||||
guard lhsDictionary.count == rhsDictionary.count else { return false }
|
||||
for (lhsKey, lhsValue) in lhsDictionary {
|
||||
var found = false
|
||||
for (rhsKey, rhsValue) in rhsDictionary {
|
||||
if deepEqualsMessages(lhsKey, rhsKey) {
|
||||
if deepEqualsMessages(lhsValue, rhsValue) {
|
||||
found = true
|
||||
break
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
if !found { return false }
|
||||
}
|
||||
return true
|
||||
|
||||
case (let lhs as Double, let rhs as Double):
|
||||
return doubleEqualsMessages(lhs, rhs)
|
||||
|
||||
case (let lhsHashable, let rhsHashable) as (AnyHashable, AnyHashable):
|
||||
return lhsHashable == rhsHashable
|
||||
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func deepHashMessages(value: Any?, hasher: inout Hasher) {
|
||||
let cleanValue = nilOrValue(value) as Any?
|
||||
if let cleanValue = cleanValue {
|
||||
if let doubleValue = cleanValue as? Double {
|
||||
doubleHashMessages(doubleValue, &hasher)
|
||||
} else if let valueList = cleanValue as? [Any?] {
|
||||
for item in valueList {
|
||||
deepHashMessages(value: item, hasher: &hasher)
|
||||
}
|
||||
} else if let valueList = cleanValue as? [Double] {
|
||||
for item in valueList {
|
||||
doubleHashMessages(item, &hasher)
|
||||
}
|
||||
} else if let valueDict = cleanValue as? [AnyHashable: Any?] {
|
||||
var result = 0
|
||||
for (key, value) in valueDict {
|
||||
var entryKeyHasher = Hasher()
|
||||
deepHashMessages(value: key, hasher: &entryKeyHasher)
|
||||
var entryValueHasher = Hasher()
|
||||
deepHashMessages(value: value, hasher: &entryValueHasher)
|
||||
result = result &+ ((entryKeyHasher.finalize() &* 31) ^ entryValueHasher.finalize())
|
||||
}
|
||||
hasher.combine(result)
|
||||
} else if let hashableValue = cleanValue as? AnyHashable {
|
||||
hasher.combine(hashableValue)
|
||||
} else {
|
||||
hasher.combine(String(describing: cleanValue))
|
||||
}
|
||||
} else {
|
||||
hasher.combine(0)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Generated class from Pigeon that represents data sent in messages.
|
||||
struct App: Hashable {
|
||||
var packageName: String
|
||||
var appName: String
|
||||
var installedBy: String
|
||||
var icon: FlutterStandardTypedData
|
||||
|
||||
|
||||
// swift-format-ignore: AlwaysUseLowerCamelCase
|
||||
static func fromList(_ pigeonVar_list: [Any?]) -> App? {
|
||||
let packageName = pigeonVar_list[0] as! String
|
||||
let appName = pigeonVar_list[1] as! String
|
||||
let installedBy = pigeonVar_list[2] as! String
|
||||
let icon = pigeonVar_list[3] as! FlutterStandardTypedData
|
||||
|
||||
return App(
|
||||
packageName: packageName,
|
||||
appName: appName,
|
||||
installedBy: installedBy,
|
||||
icon: icon
|
||||
)
|
||||
}
|
||||
func toList() -> [Any?] {
|
||||
return [
|
||||
packageName,
|
||||
appName,
|
||||
installedBy,
|
||||
icon,
|
||||
]
|
||||
}
|
||||
static func == (lhs: App, rhs: App) -> Bool {
|
||||
if Swift.type(of: lhs) != Swift.type(of: rhs) {
|
||||
return false
|
||||
}
|
||||
return deepEqualsMessages(lhs.packageName, rhs.packageName) && deepEqualsMessages(lhs.appName, rhs.appName) && deepEqualsMessages(lhs.installedBy, rhs.installedBy) && deepEqualsMessages(lhs.icon, rhs.icon)
|
||||
}
|
||||
|
||||
func hash(into hasher: inout Hasher) {
|
||||
hasher.combine("App")
|
||||
deepHashMessages(value: packageName, hasher: &hasher)
|
||||
deepHashMessages(value: appName, hasher: &hasher)
|
||||
deepHashMessages(value: installedBy, hasher: &hasher)
|
||||
deepHashMessages(value: icon, hasher: &hasher)
|
||||
}
|
||||
}
|
||||
|
||||
/// Generated class from Pigeon that represents data sent in messages.
|
||||
struct Toast: Hashable {
|
||||
var app: App
|
||||
var message: String
|
||||
var timestamp: Int64
|
||||
var duration: Int64
|
||||
|
||||
|
||||
// swift-format-ignore: AlwaysUseLowerCamelCase
|
||||
static func fromList(_ pigeonVar_list: [Any?]) -> Toast? {
|
||||
let app = pigeonVar_list[0] as! App
|
||||
let message = pigeonVar_list[1] as! String
|
||||
let timestamp = pigeonVar_list[2] as! Int64
|
||||
let duration = pigeonVar_list[3] as! Int64
|
||||
|
||||
return Toast(
|
||||
app: app,
|
||||
message: message,
|
||||
timestamp: timestamp,
|
||||
duration: duration
|
||||
)
|
||||
}
|
||||
func toList() -> [Any?] {
|
||||
return [
|
||||
app,
|
||||
message,
|
||||
timestamp,
|
||||
duration,
|
||||
]
|
||||
}
|
||||
static func == (lhs: Toast, rhs: Toast) -> Bool {
|
||||
if Swift.type(of: lhs) != Swift.type(of: rhs) {
|
||||
return false
|
||||
}
|
||||
return deepEqualsMessages(lhs.app, rhs.app) && deepEqualsMessages(lhs.message, rhs.message) && deepEqualsMessages(lhs.timestamp, rhs.timestamp) && deepEqualsMessages(lhs.duration, rhs.duration)
|
||||
}
|
||||
|
||||
func hash(into hasher: inout Hasher) {
|
||||
hasher.combine("Toast")
|
||||
deepHashMessages(value: app, hasher: &hasher)
|
||||
deepHashMessages(value: message, hasher: &hasher)
|
||||
deepHashMessages(value: timestamp, hasher: &hasher)
|
||||
deepHashMessages(value: duration, hasher: &hasher)
|
||||
}
|
||||
}
|
||||
|
||||
private class MessagesPigeonCodecReader: FlutterStandardReader {
|
||||
override func readValue(ofType type: UInt8) -> Any? {
|
||||
switch type {
|
||||
case 129:
|
||||
return App.fromList(self.readValue() as! [Any?])
|
||||
case 130:
|
||||
return Toast.fromList(self.readValue() as! [Any?])
|
||||
default:
|
||||
return super.readValue(ofType: type)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class MessagesPigeonCodecWriter: FlutterStandardWriter {
|
||||
override func writeValue(_ value: Any) {
|
||||
if let value = value as? App {
|
||||
super.writeByte(129)
|
||||
super.writeValue(value.toList())
|
||||
} else if let value = value as? Toast {
|
||||
super.writeByte(130)
|
||||
super.writeValue(value.toList())
|
||||
} else {
|
||||
super.writeValue(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class MessagesPigeonCodecReaderWriter: FlutterStandardReaderWriter {
|
||||
@@ -90,6 +312,13 @@ class MessagesPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable {
|
||||
/// Generated protocol from Pigeon that represents a handler of messages from Flutter.
|
||||
protocol ToasterUtilsApi {
|
||||
func getPlatformName(completion: @escaping (Result<String?, Error>) -> Void)
|
||||
func getInstalledApps(completion: @escaping (Result<[App], Error>) -> Void)
|
||||
func getInstalledApp(packageName: String, completion: @escaping (Result<App?, Error>) -> Void)
|
||||
func getToasts(packageName: String, completion: @escaping (Result<[Toast], Error>) -> Void)
|
||||
func getToastFiltered(packageName: String, from: Int64, completion: @escaping (Result<[Toast], Error>) -> Void)
|
||||
func isServiceRunning(completion: @escaping (Result<Bool, Error>) -> Void)
|
||||
func showSettings(completion: @escaping (Result<Void, Error>) -> Void)
|
||||
func exampleToast(completion: @escaping (Result<Void, Error>) -> Void)
|
||||
}
|
||||
|
||||
/// Generated setup class from Pigeon to handle messages through the `binaryMessenger`.
|
||||
@@ -113,5 +342,117 @@ class ToasterUtilsApiSetup {
|
||||
} else {
|
||||
getPlatformNameChannel.setMessageHandler(nil)
|
||||
}
|
||||
let getInstalledAppsChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.toaster_utils.ToasterUtilsApi.getInstalledApps\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
getInstalledAppsChannel.setMessageHandler { _, reply in
|
||||
api.getInstalledApps { result in
|
||||
switch result {
|
||||
case .success(let res):
|
||||
reply(wrapResult(res))
|
||||
case .failure(let error):
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
getInstalledAppsChannel.setMessageHandler(nil)
|
||||
}
|
||||
let getInstalledAppChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.toaster_utils.ToasterUtilsApi.getInstalledApp\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
getInstalledAppChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let packageNameArg = args[0] as! String
|
||||
api.getInstalledApp(packageName: packageNameArg) { result in
|
||||
switch result {
|
||||
case .success(let res):
|
||||
reply(wrapResult(res))
|
||||
case .failure(let error):
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
getInstalledAppChannel.setMessageHandler(nil)
|
||||
}
|
||||
let getToastsChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.toaster_utils.ToasterUtilsApi.getToasts\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
getToastsChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let packageNameArg = args[0] as! String
|
||||
api.getToasts(packageName: packageNameArg) { result in
|
||||
switch result {
|
||||
case .success(let res):
|
||||
reply(wrapResult(res))
|
||||
case .failure(let error):
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
getToastsChannel.setMessageHandler(nil)
|
||||
}
|
||||
let getToastFilteredChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.toaster_utils.ToasterUtilsApi.getToastFiltered\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
getToastFilteredChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let packageNameArg = args[0] as! String
|
||||
let fromArg = args[1] as! Int64
|
||||
api.getToastFiltered(packageName: packageNameArg, from: fromArg) { result in
|
||||
switch result {
|
||||
case .success(let res):
|
||||
reply(wrapResult(res))
|
||||
case .failure(let error):
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
getToastFilteredChannel.setMessageHandler(nil)
|
||||
}
|
||||
let isServiceRunningChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.toaster_utils.ToasterUtilsApi.isServiceRunning\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
isServiceRunningChannel.setMessageHandler { _, reply in
|
||||
api.isServiceRunning { result in
|
||||
switch result {
|
||||
case .success(let res):
|
||||
reply(wrapResult(res))
|
||||
case .failure(let error):
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
isServiceRunningChannel.setMessageHandler(nil)
|
||||
}
|
||||
let showSettingsChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.toaster_utils.ToasterUtilsApi.showSettings\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
showSettingsChannel.setMessageHandler { _, reply in
|
||||
api.showSettings { result in
|
||||
switch result {
|
||||
case .success:
|
||||
reply(wrapResult(nil))
|
||||
case .failure(let error):
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
showSettingsChannel.setMessageHandler(nil)
|
||||
}
|
||||
let exampleToastChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.toaster_utils.ToasterUtilsApi.exampleToast\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
exampleToastChannel.setMessageHandler { _, reply in
|
||||
api.exampleToast { result in
|
||||
switch result {
|
||||
case .success:
|
||||
reply(wrapResult(nil))
|
||||
case .failure(let error):
|
||||
reply(wrapError(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
exampleToastChannel.setMessageHandler(nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
Copyright (c) 2026, Org mars3142
|
||||
Copyright (c) 2026, mars3142
|
||||
|
||||
@@ -16,4 +16,43 @@ import 'package:pigeon/pigeon.dart';
|
||||
abstract class ToasterUtilsApi {
|
||||
@async
|
||||
String? getPlatformName();
|
||||
|
||||
@async
|
||||
List<App> getInstalledApps();
|
||||
|
||||
@async
|
||||
App? getInstalledApp(String packageName);
|
||||
|
||||
@async
|
||||
List<Toast> getToasts(String packageName);
|
||||
|
||||
@async
|
||||
List<Toast> getToastFiltered(String packageName, int from);
|
||||
|
||||
@async
|
||||
bool isServiceRunning();
|
||||
|
||||
@async
|
||||
void showSettings();
|
||||
|
||||
@async
|
||||
void exampleToast();
|
||||
}
|
||||
|
||||
class App {
|
||||
const App(this.packageName, this.appName, this.installedBy, this.icon);
|
||||
|
||||
final String packageName;
|
||||
final String appName;
|
||||
final String installedBy;
|
||||
final Uint8List icon;
|
||||
}
|
||||
|
||||
class Toast {
|
||||
const Toast(this.app, this.message, this.timestamp, this.duration);
|
||||
|
||||
final App app;
|
||||
final String message;
|
||||
final int timestamp;
|
||||
final int duration;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user