diff --git a/android/app/src/main/kotlin/io/chaldeaprjkt/boorusphere/AndroidAppEnv.kt b/android/app/src/main/kotlin/io/chaldeaprjkt/boorusphere/AndroidAppEnv.kt new file mode 100644 index 00000000..09dc2adb --- /dev/null +++ b/android/app/src/main/kotlin/io/chaldeaprjkt/boorusphere/AndroidAppEnv.kt @@ -0,0 +1,16 @@ +package io.chaldeaprjkt.boorusphere + +import AppEnv +import Env +import android.os.Build +import io.chaldeaprjkt.boorusphere.BuildConfig as BuildInfo // make sure that we use proper BuildConfig + +class AndroidAppEnv : AppEnv { + override fun get(): Env { + return Env( + versionName = BuildInfo.VERSION_NAME, + versionCode = BuildInfo.VERSION_CODE.toLong(), + sdkVersion = Build.VERSION.SDK_INT.toLong() + ) + } +} diff --git a/android/app/src/main/kotlin/io/chaldeaprjkt/boorusphere/MainActivity.kt b/android/app/src/main/kotlin/io/chaldeaprjkt/boorusphere/MainActivity.kt index 9ce3d34a..a2440b94 100644 --- a/android/app/src/main/kotlin/io/chaldeaprjkt/boorusphere/MainActivity.kt +++ b/android/app/src/main/kotlin/io/chaldeaprjkt/boorusphere/MainActivity.kt @@ -1,6 +1,5 @@ package io.chaldeaprjkt.boorusphere -import StorageUtil import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.engine.FlutterEngine @@ -8,6 +7,7 @@ class MainActivity : FlutterActivity() { override fun configureFlutterEngine(flutterEngine: FlutterEngine) { super.configureFlutterEngine(flutterEngine) + AppEnv.setUp(flutterEngine.dartExecutor.binaryMessenger, AndroidAppEnv()) StorageUtil.setUp(flutterEngine.dartExecutor.binaryMessenger, AndroidStorageUtil()) } } diff --git a/android/app/src/main/kotlin/io/chaldeaprjkt/boorusphere/pigeon/AppEnv.pi.kt b/android/app/src/main/kotlin/io/chaldeaprjkt/boorusphere/pigeon/AppEnv.pi.kt new file mode 100644 index 00000000..d39f7443 --- /dev/null +++ b/android/app/src/main/kotlin/io/chaldeaprjkt/boorusphere/pigeon/AppEnv.pi.kt @@ -0,0 +1,122 @@ +// Autogenerated from Pigeon (v9.2.5), do not edit directly. +// See also: https://pub.dev/packages/pigeon + + +import android.util.Log +import io.flutter.plugin.common.BasicMessageChannel +import io.flutter.plugin.common.BinaryMessenger +import io.flutter.plugin.common.MessageCodec +import io.flutter.plugin.common.StandardMessageCodec +import java.io.ByteArrayOutputStream +import java.nio.ByteBuffer + +private fun wrapResult(result: Any?): List { + return listOf(result) +} + +private fun wrapError(exception: Throwable): List { + if (exception is AppEnvException) { + return listOf( + exception.code, + exception.message, + exception.details + ) + } else { + return listOf( + exception.javaClass.simpleName, + exception.toString(), + "Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception) + ) + } +} + +/** + * Error class for passing custom error details to Flutter via a thrown PlatformException. + * @property code The error code. + * @property message The error message. + * @property details The error details. Must be a datatype supported by the api codec. + */ +class AppEnvException ( + val code: String, + override val message: String? = null, + val details: Any? = null +) : Throwable() + +/** Generated class from Pigeon that represents data sent in messages. */ +data class Env ( + val versionName: String, + val versionCode: Long, + val sdkVersion: Long + +) { + companion object { + @Suppress("UNCHECKED_CAST") + fun fromList(list: List): Env { + val versionName = list[0] as String + val versionCode = list[1].let { if (it is Int) it.toLong() else it as Long } + val sdkVersion = list[2].let { if (it is Int) it.toLong() else it as Long } + return Env(versionName, versionCode, sdkVersion) + } + } + fun toList(): List { + return listOf( + versionName, + versionCode, + sdkVersion, + ) + } +} +@Suppress("UNCHECKED_CAST") +private object AppEnvCodec : StandardMessageCodec() { + override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? { + return when (type) { + 128.toByte() -> { + return (readValue(buffer) as? List)?.let { + Env.fromList(it) + } + } + else -> super.readValueOfType(type, buffer) + } + } + override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { + when (value) { + is Env -> { + stream.write(128) + writeValue(stream, value.toList()) + } + else -> super.writeValue(stream, value) + } + } +} + +/** Generated interface from Pigeon that represents a handler of messages from Flutter. */ +interface AppEnv { + fun get(): Env + + companion object { + /** The codec used by AppEnv. */ + val codec: MessageCodec by lazy { + AppEnvCodec + } + /** Sets up an instance of `AppEnv` to handle messages through the `binaryMessenger`. */ + @Suppress("UNCHECKED_CAST") + fun setUp(binaryMessenger: BinaryMessenger, api: AppEnv?) { + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.AppEnv.get", codec) + if (api != null) { + channel.setMessageHandler { _, reply -> + var wrapped: List + try { + wrapped = listOf(api.get()) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + } + } +} diff --git a/lib/data/repository/env/current_env_repo.dart b/lib/data/repository/env/current_env_repo.dart index c48e7260..e63c095d 100644 --- a/lib/data/repository/env/current_env_repo.dart +++ b/lib/data/repository/env/current_env_repo.dart @@ -1,20 +1,16 @@ import 'package:boorusphere/data/repository/version/entity/app_version.dart'; import 'package:boorusphere/domain/repository/env_repo.dart'; -import 'package:device_info_plus/device_info_plus.dart'; -import 'package:package_info/package_info.dart'; +import 'package:boorusphere/pigeon/app_env.pi.dart'; class CurrentEnvRepo implements EnvRepo { - CurrentEnvRepo({required this.packageInfo, required this.androidInfo}); + CurrentEnvRepo({required this.env}); @override - final PackageInfo packageInfo; + final Env env; @override - final AndroidDeviceInfo androidInfo; + int get sdkVersion => env.sdkVersion; @override - int get sdkVersion => androidInfo.version.sdkInt; - - @override - AppVersion get appVersion => AppVersion.fromString(packageInfo.version); + AppVersion get appVersion => AppVersion.fromString(env.versionName); } diff --git a/lib/domain/provider.dart b/lib/domain/provider.dart index e7e398b4..48903ff2 100644 --- a/lib/domain/provider.dart +++ b/lib/domain/provider.dart @@ -27,10 +27,9 @@ import 'package:boorusphere/domain/repository/server_data_repo.dart'; import 'package:boorusphere/domain/repository/settings_repo.dart'; import 'package:boorusphere/domain/repository/tags_blocker_repo.dart'; import 'package:boorusphere/domain/repository/version_repo.dart'; -import 'package:device_info_plus/device_info_plus.dart'; +import 'package:boorusphere/pigeon/app_env.pi.dart'; import 'package:flutter/services.dart'; import 'package:hive/hive.dart'; -import 'package:package_info/package_info.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; part 'provider.g.dart'; @@ -41,10 +40,7 @@ EnvRepo envRepo(EnvRepoRef ref) { } Future provideEnvRepo() async { - return CurrentEnvRepo( - packageInfo: await PackageInfo.fromPlatform(), - androidInfo: await DeviceInfoPlugin().androidInfo, - ); + return CurrentEnvRepo(env: await AppEnv().get()); } @riverpod diff --git a/lib/domain/repository/env_repo.dart b/lib/domain/repository/env_repo.dart index cc5f0f2d..6b175326 100644 --- a/lib/domain/repository/env_repo.dart +++ b/lib/domain/repository/env_repo.dart @@ -1,10 +1,8 @@ import 'package:boorusphere/data/repository/version/entity/app_version.dart'; -import 'package:device_info_plus/device_info_plus.dart'; -import 'package:package_info/package_info.dart'; +import 'package:boorusphere/pigeon/app_env.pi.dart'; abstract interface class EnvRepo { - PackageInfo get packageInfo; - AndroidDeviceInfo get androidInfo; + Env get env; int get sdkVersion; AppVersion get appVersion; } diff --git a/lib/pigeon/app_env.pi.dart b/lib/pigeon/app_env.pi.dart new file mode 100644 index 00000000..fd3ef994 --- /dev/null +++ b/lib/pigeon/app_env.pi.dart @@ -0,0 +1,101 @@ +// Autogenerated from Pigeon (v9.2.5), 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 + +import 'dart:async'; +import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; + +import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer; +import 'package:flutter/services.dart'; + +class Env { + Env({ + required this.versionName, + required this.versionCode, + required this.sdkVersion, + }); + + String versionName; + + int versionCode; + + int sdkVersion; + + Object encode() { + return [ + versionName, + versionCode, + sdkVersion, + ]; + } + + static Env decode(Object result) { + result as List; + return Env( + versionName: result[0]! as String, + versionCode: result[1]! as int, + sdkVersion: result[2]! as int, + ); + } +} + +class _AppEnvCodec extends StandardMessageCodec { + const _AppEnvCodec(); + @override + void writeValue(WriteBuffer buffer, Object? value) { + if (value is Env) { + buffer.putUint8(128); + writeValue(buffer, value.encode()); + } else { + super.writeValue(buffer, value); + } + } + + @override + Object? readValueOfType(int type, ReadBuffer buffer) { + switch (type) { + case 128: + return Env.decode(readValue(buffer)!); + default: + return super.readValueOfType(type, buffer); + } + } +} + +class AppEnv { + /// Constructor for [AppEnv]. The [binaryMessenger] named argument is + /// available for dependency injection. If it is left null, the default + /// BinaryMessenger will be used which routes to the host platform. + AppEnv({BinaryMessenger? binaryMessenger}) + : _binaryMessenger = binaryMessenger; + final BinaryMessenger? _binaryMessenger; + + static const MessageCodec codec = _AppEnvCodec(); + + Future get() async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.AppEnv.get', codec, + binaryMessenger: _binaryMessenger); + final List? replyList = + await channel.send(null) as List?; + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else if (replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (replyList[0] as Env?)!; + } + } +} diff --git a/pigeons/app_env.pi.dart b/pigeons/app_env.pi.dart new file mode 100644 index 00000000..5fe4ce81 --- /dev/null +++ b/pigeons/app_env.pi.dart @@ -0,0 +1,26 @@ +import 'package:pigeon/pigeon.dart'; + +@ConfigurePigeon( + PigeonOptions( + dartOut: 'lib/pigeon/app_env.pi.dart', + kotlinOut: + 'android/app/src/main/kotlin/io/chaldeaprjkt/boorusphere/pigeon/AppEnv.pi.kt', + kotlinOptions: KotlinOptions(errorClassName: 'AppEnvException'), + ), +) +@HostApi() +abstract class AppEnv { + Env get(); +} + +class Env { + Env({ + required this.versionName, + required this.versionCode, + required this.sdkVersion, + }); + + final String versionName; + final int versionCode; + final int sdkVersion; +} diff --git a/pubspec.lock b/pubspec.lock index 9f8c6022..e7b86430 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -273,22 +273,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.0" - device_info_plus: - dependency: "direct main" - description: - name: device_info_plus - sha256: f52ab3b76b36ede4d135aab80194df8925b553686f0fa12226b4e2d658e45903 - url: "https://pub.dev" - source: hosted - version: "8.2.2" - device_info_plus_platform_interface: - dependency: transitive - description: - name: device_info_plus_platform_interface - sha256: d3b01d5868b50ae571cd1dc6e502fc94d956b665756180f7b16ead09e836fd64 - url: "https://pub.dev" - source: hosted - version: "7.0.0" dio: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 286914f6..4a83f49d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -40,7 +40,6 @@ dependencies: collection: ^1.16.0 cookie_jar: ^4.0.1 deep_pick: ^1.0.0 - device_info_plus: ^8.0.0 dio_cookie_manager: ^3.0.0 dio_smart_retry: ^5.0.0 dio: ^5.0.0