diff --git a/android/app/build.gradle b/android/app/build.gradle
index f360f667e5..640d7a1fdb 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -77,6 +77,7 @@ android {
// https://developer.android.com/reference/tools/gradle-api/8.5/com/android/build/api/dsl/Lint
checkAllWarnings = true
warningsAsErrors = true
+ baseline = file("lint-baseline.xml")
}
}
diff --git a/android/app/lint-baseline.xml b/android/app/lint-baseline.xml
new file mode 100644
index 0000000000..006b010637
--- /dev/null
+++ b/android/app/lint-baseline.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
diff --git a/android/app/src/main/kotlin/com/zulip/flutter/Notifications.g.kt b/android/app/src/main/kotlin/com/zulip/flutter/Notifications.g.kt
index 1776f4bab4..f4862e2b0b 100644
--- a/android/app/src/main/kotlin/com/zulip/flutter/Notifications.g.kt
+++ b/android/app/src/main/kotlin/com/zulip/flutter/Notifications.g.kt
@@ -1,4 +1,4 @@
-// Autogenerated from Pigeon (v25.0.0), do not edit directly.
+// Autogenerated from Pigeon (v25.3.1), do not edit directly.
// See also: https://pub.dev/packages/pigeon
@file:Suppress("UNCHECKED_CAST", "ArrayInDataClass")
@@ -13,25 +13,57 @@ import io.flutter.plugin.common.StandardMethodCodec
import io.flutter.plugin.common.StandardMessageCodec
import java.io.ByteArrayOutputStream
import java.nio.ByteBuffer
+private object NotificationsPigeonUtils {
-private fun wrapResult(result: Any?): List {
- return listOf(result)
-}
+ fun wrapResult(result: Any?): List {
+ return listOf(result)
+ }
-private fun wrapError(exception: Throwable): List {
- return if (exception is FlutterError) {
- listOf(
- exception.code,
- exception.message,
- exception.details
- )
- } else {
- listOf(
- exception.javaClass.simpleName,
- exception.toString(),
- "Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception)
- )
+ fun wrapError(exception: Throwable): List {
+ return if (exception is FlutterError) {
+ listOf(
+ exception.code,
+ exception.message,
+ exception.details
+ )
+ } else {
+ listOf(
+ exception.javaClass.simpleName,
+ exception.toString(),
+ "Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception)
+ )
+ }
+ }
+ fun deepEquals(a: Any?, b: Any?): Boolean {
+ 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) {
+ return a.contentEquals(b)
+ }
+ if (a is Array<*> && b is Array<*>) {
+ return a.size == b.size &&
+ a.indices.all{ deepEquals(a[it], b[it]) }
+ }
+ if (a is List<*> && b is List<*>) {
+ return a.size == b.size &&
+ a.indices.all{ deepEquals(a[it], b[it]) }
+ }
+ if (a is Map<*, *> && b is Map<*, *>) {
+ return a.size == b.size && a.all {
+ (b as Map).containsKey(it.key) &&
+ deepEquals(it.value, b[it.key])
+ }
+ }
+ return a == b
}
+
}
/**
@@ -89,6 +121,16 @@ data class NotificationChannel (
vibrationPattern,
)
}
+ override fun equals(other: Any?): Boolean {
+ if (other !is NotificationChannel) {
+ return false
+ }
+ if (this === other) {
+ return true
+ }
+ return NotificationsPigeonUtils.deepEquals(toList(), other.toList()) }
+
+ override fun hashCode(): Int = toList().hashCode()
}
/**
@@ -122,6 +164,16 @@ data class AndroidIntent (
flags,
)
}
+ override fun equals(other: Any?): Boolean {
+ if (other !is AndroidIntent) {
+ return false
+ }
+ if (this === other) {
+ return true
+ }
+ return NotificationsPigeonUtils.deepEquals(toList(), other.toList()) }
+
+ override fun hashCode(): Int = toList().hashCode()
}
/**
@@ -156,6 +208,16 @@ data class PendingIntent (
flags,
)
}
+ override fun equals(other: Any?): Boolean {
+ if (other !is PendingIntent) {
+ return false
+ }
+ if (this === other) {
+ return true
+ }
+ return NotificationsPigeonUtils.deepEquals(toList(), other.toList()) }
+
+ override fun hashCode(): Int = toList().hashCode()
}
/**
@@ -180,6 +242,16 @@ data class InboxStyle (
summaryText,
)
}
+ override fun equals(other: Any?): Boolean {
+ if (other !is InboxStyle) {
+ return false
+ }
+ if (this === other) {
+ return true
+ }
+ return NotificationsPigeonUtils.deepEquals(toList(), other.toList()) }
+
+ override fun hashCode(): Int = toList().hashCode()
}
/**
@@ -220,6 +292,16 @@ data class Person (
name,
)
}
+ override fun equals(other: Any?): Boolean {
+ if (other !is Person) {
+ return false
+ }
+ if (this === other) {
+ return true
+ }
+ return NotificationsPigeonUtils.deepEquals(toList(), other.toList()) }
+
+ override fun hashCode(): Int = toList().hashCode()
}
/**
@@ -250,6 +332,16 @@ data class MessagingStyleMessage (
person,
)
}
+ override fun equals(other: Any?): Boolean {
+ if (other !is MessagingStyleMessage) {
+ return false
+ }
+ if (this === other) {
+ return true
+ }
+ return NotificationsPigeonUtils.deepEquals(toList(), other.toList()) }
+
+ override fun hashCode(): Int = toList().hashCode()
}
/**
@@ -283,6 +375,16 @@ data class MessagingStyle (
isGroupConversation,
)
}
+ override fun equals(other: Any?): Boolean {
+ if (other !is MessagingStyle) {
+ return false
+ }
+ if (this === other) {
+ return true
+ }
+ return NotificationsPigeonUtils.deepEquals(toList(), other.toList()) }
+
+ override fun hashCode(): Int = toList().hashCode()
}
/**
@@ -310,6 +412,16 @@ data class Notification (
extras,
)
}
+ override fun equals(other: Any?): Boolean {
+ if (other !is Notification) {
+ return false
+ }
+ if (this === other) {
+ return true
+ }
+ return NotificationsPigeonUtils.deepEquals(toList(), other.toList()) }
+
+ override fun hashCode(): Int = toList().hashCode()
}
/**
@@ -340,6 +452,16 @@ data class StatusBarNotification (
notification,
)
}
+ override fun equals(other: Any?): Boolean {
+ if (other !is StatusBarNotification) {
+ return false
+ }
+ if (this === other) {
+ return true
+ }
+ return NotificationsPigeonUtils.deepEquals(toList(), other.toList()) }
+
+ override fun hashCode(): Int = toList().hashCode()
}
/**
@@ -380,6 +502,16 @@ data class StoredNotificationSound (
contentUrl,
)
}
+ override fun equals(other: Any?): Boolean {
+ if (other !is StoredNotificationSound) {
+ return false
+ }
+ if (this === other) {
+ return true
+ }
+ return NotificationsPigeonUtils.deepEquals(toList(), other.toList()) }
+
+ override fun hashCode(): Int = toList().hashCode()
}
private open class NotificationsPigeonCodec : StandardMessageCodec() {
override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? {
@@ -605,7 +737,7 @@ interface AndroidNotificationHostApi {
api.createNotificationChannel(channelArg)
listOf(null)
} catch (exception: Throwable) {
- wrapError(exception)
+ NotificationsPigeonUtils.wrapError(exception)
}
reply.reply(wrapped)
}
@@ -620,7 +752,7 @@ interface AndroidNotificationHostApi {
val wrapped: List = try {
listOf(api.getNotificationChannels())
} catch (exception: Throwable) {
- wrapError(exception)
+ NotificationsPigeonUtils.wrapError(exception)
}
reply.reply(wrapped)
}
@@ -638,7 +770,7 @@ interface AndroidNotificationHostApi {
api.deleteNotificationChannel(channelIdArg)
listOf(null)
} catch (exception: Throwable) {
- wrapError(exception)
+ NotificationsPigeonUtils.wrapError(exception)
}
reply.reply(wrapped)
}
@@ -653,7 +785,7 @@ interface AndroidNotificationHostApi {
val wrapped: List = try {
listOf(api.listStoredSoundsInNotificationsDirectory())
} catch (exception: Throwable) {
- wrapError(exception)
+ NotificationsPigeonUtils.wrapError(exception)
}
reply.reply(wrapped)
}
@@ -671,7 +803,7 @@ interface AndroidNotificationHostApi {
val wrapped: List = try {
listOf(api.copySoundResourceToMediaStore(targetFileDisplayNameArg, sourceResourceNameArg))
} catch (exception: Throwable) {
- wrapError(exception)
+ NotificationsPigeonUtils.wrapError(exception)
}
reply.reply(wrapped)
}
@@ -703,7 +835,7 @@ interface AndroidNotificationHostApi {
api.notify(tagArg, idArg, autoCancelArg, channelIdArg, colorArg, contentIntentArg, contentTextArg, contentTitleArg, extrasArg, groupKeyArg, inboxStyleArg, isGroupSummaryArg, messagingStyleArg, numberArg, smallIconResourceNameArg)
listOf(null)
} catch (exception: Throwable) {
- wrapError(exception)
+ NotificationsPigeonUtils.wrapError(exception)
}
reply.reply(wrapped)
}
@@ -720,7 +852,7 @@ interface AndroidNotificationHostApi {
val wrapped: List = try {
listOf(api.getActiveNotificationMessagingStyleByTag(tagArg))
} catch (exception: Throwable) {
- wrapError(exception)
+ NotificationsPigeonUtils.wrapError(exception)
}
reply.reply(wrapped)
}
@@ -737,7 +869,7 @@ interface AndroidNotificationHostApi {
val wrapped: List = try {
listOf(api.getActiveNotifications(desiredExtrasArg))
} catch (exception: Throwable) {
- wrapError(exception)
+ NotificationsPigeonUtils.wrapError(exception)
}
reply.reply(wrapped)
}
@@ -756,7 +888,7 @@ interface AndroidNotificationHostApi {
api.cancel(tagArg, idArg)
listOf(null)
} catch (exception: Throwable) {
- wrapError(exception)
+ NotificationsPigeonUtils.wrapError(exception)
}
reply.reply(wrapped)
}
diff --git a/android/app/src/main/kotlin/com/zulip/flutter/ZulipPlugin.kt b/android/app/src/main/kotlin/com/zulip/flutter/ZulipPlugin.kt
index eb332d786f..e91b7deafd 100644
--- a/android/app/src/main/kotlin/com/zulip/flutter/ZulipPlugin.kt
+++ b/android/app/src/main/kotlin/com/zulip/flutter/ZulipPlugin.kt
@@ -19,6 +19,7 @@ import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import androidx.core.graphics.drawable.IconCompat
import io.flutter.embedding.engine.plugins.FlutterPlugin
+import androidx.core.net.toUri
private const val TAG = "ZulipPlugin"
@@ -64,7 +65,7 @@ private class AndroidNotificationHost(val context: Context)
channel.name?.let { setName(it) }
channel.lightsEnabled?.let { setLightsEnabled(it) }
channel.soundUrl?.let {
- setSound(Uri.parse(it),
+ setSound(it.toUri(),
AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_NOTIFICATION).build())
}
channel.vibrationPattern?.let { setVibrationPattern(it) }
@@ -199,7 +200,7 @@ private class AndroidNotificationHost(val context: Context)
it.requestCode.toInt(),
it.intent.let { intent -> Intent(
intent.action,
- Uri.parse(intent.dataUrl),
+ intent.dataUrl.toUri(),
context,
MainActivity::class.java
).apply {
diff --git a/android/gradle.properties b/android/gradle.properties
index b0202e3120..e9d14e8cb1 100644
--- a/android/gradle.properties
+++ b/android/gradle.properties
@@ -6,11 +6,11 @@ android.enableJetifier=true
# Defining them here makes them available both in
# settings.gradle and in the build.gradle files.
-agpVersion=8.5.2
+agpVersion=8.9.1
# Generally update this to the version found in recent releases
# of Android Studio, as listed in this table:
# https://kotlinlang.org/docs/releases.html#release-details
# A helpful discussion is at:
# https://stackoverflow.com/a/74425347
-kotlinVersion=2.0.10
+kotlinVersion=2.1.20
diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties
index 545935f33c..479cd23287 100644
--- a/android/gradle/wrapper/gradle-wrapper.properties
+++ b/android/gradle/wrapper/gradle-wrapper.properties
@@ -6,7 +6,7 @@
# the wrapper is the one from the new Gradle too.)
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-all.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index ea92d3df55..c0db288bed 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -37,31 +37,31 @@ PODS:
- file_picker (0.0.1):
- DKImagePickerController/PhotoGallery
- Flutter
- - Firebase/CoreOnly (11.8.0):
- - FirebaseCore (~> 11.8.0)
- - Firebase/Messaging (11.8.0):
+ - Firebase/CoreOnly (11.10.0):
+ - FirebaseCore (~> 11.10.0)
+ - Firebase/Messaging (11.10.0):
- Firebase/CoreOnly
- - FirebaseMessaging (~> 11.8.0)
- - firebase_core (3.12.1):
- - Firebase/CoreOnly (= 11.8.0)
+ - FirebaseMessaging (~> 11.10.0)
+ - firebase_core (3.13.0):
+ - Firebase/CoreOnly (= 11.10.0)
- Flutter
- - firebase_messaging (15.2.4):
- - Firebase/Messaging (= 11.8.0)
+ - firebase_messaging (15.2.5):
+ - Firebase/Messaging (= 11.10.0)
- firebase_core
- Flutter
- - FirebaseCore (11.8.1):
- - FirebaseCoreInternal (~> 11.8.0)
+ - FirebaseCore (11.10.0):
+ - FirebaseCoreInternal (~> 11.10.0)
- GoogleUtilities/Environment (~> 8.0)
- GoogleUtilities/Logger (~> 8.0)
- - FirebaseCoreInternal (11.8.0):
+ - FirebaseCoreInternal (11.10.0):
- "GoogleUtilities/NSData+zlib (~> 8.0)"
- - FirebaseInstallations (11.8.0):
- - FirebaseCore (~> 11.8.0)
+ - FirebaseInstallations (11.10.0):
+ - FirebaseCore (~> 11.10.0)
- GoogleUtilities/Environment (~> 8.0)
- GoogleUtilities/UserDefaults (~> 8.0)
- PromisesObjC (~> 2.4)
- - FirebaseMessaging (11.8.0):
- - FirebaseCore (~> 11.8.0)
+ - FirebaseMessaging (11.10.0):
+ - FirebaseCore (~> 11.10.0)
- FirebaseInstallations (~> 11.0)
- GoogleDataTransport (~> 10.0)
- GoogleUtilities/AppDelegateSwizzler (~> 8.0)
@@ -124,6 +124,8 @@ PODS:
- sqlite3/common
- sqlite3/fts5 (3.49.1):
- sqlite3/common
+ - sqlite3/math (3.49.1):
+ - sqlite3/common
- sqlite3/perf-threadsafe (3.49.1):
- sqlite3/common
- sqlite3/rtree (3.49.1):
@@ -134,6 +136,7 @@ PODS:
- sqlite3 (~> 3.49.1)
- sqlite3/dbstatvtab
- sqlite3/fts5
+ - sqlite3/math
- sqlite3/perf-threadsafe
- sqlite3/rtree
- SwiftyGif (5.4.5)
@@ -212,35 +215,35 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/wakelock_plus/ios"
SPEC CHECKSUMS:
- app_settings: 58017cd26b604ae98c3e65acbdd8ba173703cc82
- device_info_plus: bf2e3232933866d73fe290f2942f2156cdd10342
+ app_settings: 5127ae0678de1dcc19f2293271c51d37c89428b2
+ device_info_plus: 21fcca2080fbcd348be798aa36c3e5ed849eefbe
DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c
DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
- file_picker: b159e0c068aef54932bb15dc9fd1571818edaf49
- Firebase: d80354ed7f6df5f9aca55e9eb47cc4b634735eaf
- firebase_core: ac395f994af4e28f6a38b59e05a88ca57abeb874
- firebase_messaging: 7e223f4ee7ca053bf4ce43748e84a6d774ec9728
- FirebaseCore: 99fe0c4b44a39f37d99e6404e02009d2db5d718d
- FirebaseCoreInternal: df24ce5af28864660ecbd13596fc8dd3a8c34629
- FirebaseInstallations: 6c963bd2a86aca0481eef4f48f5a4df783ae5917
- FirebaseMessaging: 487b634ccdf6f7b7ff180fdcb2a9935490f764e8
+ file_picker: a0560bc09d61de87f12d246fc47d2119e6ef37be
+ Firebase: 1fe1c0a7d9aaea32efe01fbea5f0ebd8d70e53a2
+ firebase_core: 2d4534e7b489907dcede540c835b48981d890943
+ firebase_messaging: 75bc93a4df25faccad67f6662ae872ac9ae69b64
+ FirebaseCore: 8344daef5e2661eb004b177488d6f9f0f24251b7
+ FirebaseCoreInternal: ef4505d2afb1d0ebbc33162cb3795382904b5679
+ FirebaseInstallations: 9980995bdd06ec8081dfb6ab364162bdd64245c3
+ FirebaseMessaging: 2b9f56aa4ed286e1f0ce2ee1d413aabb8f9f5cb9
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
GoogleUtilities: 26a3abef001b6533cf678d3eb38fd3f614b7872d
- image_picker_ios: c560581cceedb403a6ff17f2f816d7fea1421fc1
- integration_test: 252f60fa39af5e17c3aa9899d35d908a0721b573
+ image_picker_ios: 7fe1ff8e34c1790d6fff70a32484959f563a928a
+ integration_test: 4a889634ef21a45d28d50d622cf412dc6d9f586e
nanopb: fad817b59e0457d11a5dfbde799381cd727c1275
- package_info_plus: c0502532a26c7662a62a356cebe2692ec5fe4ec4
- path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46
+ package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499
+ path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
SDWebImage: f84b0feeb08d2d11e6a9b843cb06d75ebf5b8868
- share_plus: 8b6f8b3447e494cca5317c8c3073de39b3600d1f
+ share_plus: 50da8cb520a8f0f65671c6c6a99b3617ed10a58a
sqlite3: fc1400008a9b3525f5914ed715a5d1af0b8f4983
- sqlite3_flutter_libs: cc304edcb8e1d8c595d1b08c7aeb46a47691d9db
+ sqlite3_flutter_libs: f6acaa2172e6bb3e2e70c771661905080e8ebcf2
SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4
- url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe
- video_player_avfoundation: 7c6c11d8470e1675df7397027218274b6d2360b3
- wakelock_plus: 373cfe59b235a6dd5837d0fb88791d2f13a90d56
+ url_launcher_ios: 694010445543906933d732453a59da0a173ae33d
+ video_player_avfoundation: 2cef49524dd1f16c5300b9cd6efd9611ce03639b
+ wakelock_plus: 04623e3f525556020ebd4034310f20fe7fda8b49
PODFILE CHECKSUM: 7ed5116924b3be7e8fb75f7aada61e057028f5c7
diff --git a/lib/host/android_notifications.g.dart b/lib/host/android_notifications.g.dart
index bc29b2d794..5f46d154e9 100644
--- a/lib/host/android_notifications.g.dart
+++ b/lib/host/android_notifications.g.dart
@@ -1,4 +1,4 @@
-// Autogenerated from Pigeon (v25.0.0), do not edit directly.
+// Autogenerated from Pigeon (v25.3.1), do not edit directly.
// See also: https://pub.dev/packages/pigeon
// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers
@@ -14,6 +14,20 @@ PlatformException _createConnectionError(String channelName) {
message: 'Unable to establish connection on channel: "$channelName".',
);
}
+bool _deepEquals(Object? a, Object? 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) {
+ return a.length == b.length && a.entries.every((MapEntry