From bb1db04df8327e4fbe9683bc66e8ae280e92555f Mon Sep 17 00:00:00 2001 From: Jing <42014615+jing332@users.noreply.github.com> Date: Sun, 14 Jan 2024 19:42:47 +0800 Subject: [PATCH] pigeon --- alist_version | 1 + android/app/build.gradle | 40 +- .../github/jing332/pigeon/GeneratedApi.java | 474 ++++++++++++++++++ .../com/github/jing332/alistflutter/App.kt | 1 - .../jing332/alistflutter/MainActivity.kt | 70 +-- .../alistflutter/bridge/AndroidBridge.kt | 30 ++ .../alistflutter/bridge/AppConfigBridge.kt | 25 + .../java/com/github/jing332/pigeon/Api.java | 42 -- lib/bridges/app_config.dart | 29 -- lib/bridges/bridge.dart | 13 - lib/bridges/event.dart | 8 - lib/generated_api.dart | 394 +++++++++++++++ lib/main.dart | 28 +- lib/pages/alist.dart | 44 +- pigeons/pigeon.dart | 38 ++ pigeons/run.cmd | 5 +- pubspec.yaml | 2 +- 17 files changed, 1052 insertions(+), 192 deletions(-) create mode 100644 alist_version create mode 100644 android/app/src/main/java/com/github/jing332/pigeon/GeneratedApi.java create mode 100644 android/app/src/main/kotlin/com/github/jing332/alistflutter/bridge/AndroidBridge.kt create mode 100644 android/app/src/main/kotlin/com/github/jing332/alistflutter/bridge/AppConfigBridge.kt delete mode 100644 android/src/main/java/com/github/jing332/pigeon/Api.java delete mode 100644 lib/bridges/app_config.dart delete mode 100644 lib/bridges/bridge.dart delete mode 100644 lib/bridges/event.dart diff --git a/alist_version b/alist_version new file mode 100644 index 0000000..459c0a2 --- /dev/null +++ b/alist_version @@ -0,0 +1 @@ +v3.30.0 \ No newline at end of file diff --git a/android/app/build.gradle b/android/app/build.gradle index b9b95ff..ef8ed5f 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -6,34 +6,35 @@ plugins { id "dev.flutter.flutter-gradle-plugin" } -def localProperties = new Properties() +def pro = new Properties() def localPropertiesFile = rootProject.file('local.properties') if (localPropertiesFile.exists()) { localPropertiesFile.withReader('UTF-8') { reader -> - localProperties.load(reader) + pro.load(reader) } } -def flutterVersionCode = localProperties.getProperty('flutter.versionCode') -if (flutterVersionCode == null) { - flutterVersionCode = '1' +static def releaseTime() { + return new Date().format("yy.MMddHH", TimeZone.getTimeZone("GMT+8")) } -def flutterVersionName = localProperties.getProperty('flutter.versionName') -if (flutterVersionName == null) { - flutterVersionName = '1.0' -} +def version = "1." + releaseTime() +def gitCommits = Integer.parseInt('git rev-list HEAD --count'.execute().text.trim()) +def alistVersion = rootProject.file("../alist_version").readLines()[0] android { namespace "com.github.jing332.alistflutter" compileSdkVersion flutter.compileSdkVersion ndkVersion flutter.ndkVersion - - - sourceSets { - main.java.srcDirs += 'src/main/kotlin' + signingConfigs { + release { + storeFile file(pro["KEY_PATH"]) + storePassword pro["KEY_PASSWORD"] + keyAlias pro["ALIAS_NAME"] + keyPassword pro["ALIAS_PASSWORD"] + } } defaultConfig { @@ -43,8 +44,15 @@ android { // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. minSdkVersion flutter.minSdkVersion targetSdkVersion flutter.targetSdkVersion - versionCode flutterVersionCode.toInteger() - versionName flutterVersionName + versionCode gitCommits + versionName version + + buildConfigField("String", "ALIST_VERSION", "\"${alistVersion}\"") + } + + + buildFeatures { + buildConfig true } @@ -73,7 +81,7 @@ android { release { // TODO: Add your own signing config for the release build. // Signing with the debug keys for now, so `flutter run --release` works. - signingConfig signingConfigs.debug + signingConfig signingConfigs.release } debug { diff --git a/android/app/src/main/java/com/github/jing332/pigeon/GeneratedApi.java b/android/app/src/main/java/com/github/jing332/pigeon/GeneratedApi.java new file mode 100644 index 0000000..d9d1fbe --- /dev/null +++ b/android/app/src/main/java/com/github/jing332/pigeon/GeneratedApi.java @@ -0,0 +1,474 @@ +// Autogenerated from Pigeon (v16.0.0), do not edit directly. +// See also: https://pub.dev/packages/pigeon + +package com.github.jing332.pigeon; + +import android.util.Log; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +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; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** Generated class from Pigeon. */ +@SuppressWarnings({"unused", "unchecked", "CodeBlock2Expr", "RedundantSuppression", "serial"}) +public class GeneratedApi { + + /** Error class for passing custom error details to Flutter via a thrown PlatformException. */ + public static class FlutterError extends RuntimeException { + + /** The error code. */ + public final String code; + + /** The error details. Must be a datatype supported by the api codec. */ + public final Object details; + + public FlutterError(@NonNull String code, @Nullable String message, @Nullable Object details) + { + super(message); + this.code = code; + this.details = details; + } + } + + @NonNull + protected static ArrayList wrapError(@NonNull Throwable exception) { + ArrayList errorList = new ArrayList(3); + if (exception instanceof FlutterError) { + FlutterError error = (FlutterError) exception; + errorList.add(error.code); + errorList.add(error.getMessage()); + errorList.add(error.details); + } else { + errorList.add(exception.toString()); + errorList.add(exception.getClass().getSimpleName()); + errorList.add( + "Cause: " + exception.getCause() + ", Stacktrace: " + Log.getStackTraceString(exception)); + } + return errorList; + } + + @NonNull + protected static FlutterError createConnectionError(@NonNull String channelName) { + return new FlutterError("channel-error", "Unable to establish connection on channel: " + channelName + ".", ""); + } + + /** Asynchronous error handling return type for non-nullable API method returns. */ + public interface Result { + /** Success case callback method for handling returns. */ + void success(@NonNull T result); + + /** Failure case callback method for handling errors. */ + void error(@NonNull Throwable error); + } + /** Asynchronous error handling return type for nullable API method returns. */ + public interface NullableResult { + /** Success case callback method for handling returns. */ + void success(@Nullable T result); + + /** Failure case callback method for handling errors. */ + void error(@NonNull Throwable error); + } + /** Asynchronous error handling return type for void API method returns. */ + public interface VoidResult { + /** Success case callback method for handling returns. */ + void success(); + + /** Failure case callback method for handling errors. */ + void error(@NonNull Throwable error); + } + /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ + public interface AppConfig { + + @NonNull + Boolean isWakeLockEnabled(); + + void setWakeLockEnabled(@NonNull Boolean enabled); + + @NonNull + Boolean isStartAtBootEnabled(); + + void setStartAtBootEnabled(@NonNull Boolean enabled); + + @NonNull + Boolean isAutoCheckUpdateEnabled(); + + void setAutoCheckUpdateEnabled(@NonNull Boolean enabled); + + /** The codec used by AppConfig. */ + static @NonNull MessageCodec getCodec() { + return new StandardMessageCodec(); + } + /**Sets up an instance of `AppConfig` to handle messages through the `binaryMessenger`. */ + static void setUp(@NonNull BinaryMessenger binaryMessenger, @Nullable AppConfig api) { + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.alist_flutter.AppConfig.isWakeLockEnabled", getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + try { + Boolean output = api.isWakeLockEnabled(); + wrapped.add(0, output); + } + catch (Throwable exception) { + ArrayList wrappedError = wrapError(exception); + wrapped = wrappedError; + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.alist_flutter.AppConfig.setWakeLockEnabled", getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + ArrayList args = (ArrayList) message; + Boolean enabledArg = (Boolean) args.get(0); + try { + api.setWakeLockEnabled(enabledArg); + wrapped.add(0, null); + } + catch (Throwable exception) { + ArrayList wrappedError = wrapError(exception); + wrapped = wrappedError; + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.alist_flutter.AppConfig.isStartAtBootEnabled", getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + try { + Boolean output = api.isStartAtBootEnabled(); + wrapped.add(0, output); + } + catch (Throwable exception) { + ArrayList wrappedError = wrapError(exception); + wrapped = wrappedError; + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.alist_flutter.AppConfig.setStartAtBootEnabled", getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + ArrayList args = (ArrayList) message; + Boolean enabledArg = (Boolean) args.get(0); + try { + api.setStartAtBootEnabled(enabledArg); + wrapped.add(0, null); + } + catch (Throwable exception) { + ArrayList wrappedError = wrapError(exception); + wrapped = wrappedError; + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.alist_flutter.AppConfig.isAutoCheckUpdateEnabled", getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + try { + Boolean output = api.isAutoCheckUpdateEnabled(); + wrapped.add(0, output); + } + catch (Throwable exception) { + ArrayList wrappedError = wrapError(exception); + wrapped = wrappedError; + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.alist_flutter.AppConfig.setAutoCheckUpdateEnabled", getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + ArrayList args = (ArrayList) message; + Boolean enabledArg = (Boolean) args.get(0); + try { + api.setAutoCheckUpdateEnabled(enabledArg); + wrapped.add(0, null); + } + catch (Throwable exception) { + ArrayList wrappedError = wrapError(exception); + wrapped = wrappedError; + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + } + } + /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ + public interface Android { + + void startService(); + + @NonNull + Boolean isRunning(); + + @NonNull + String getAListVersion(); + + @NonNull + String getVersionName(); + + @NonNull + Long getVersionCode(); + + void toast(@NonNull String msg); + + void longToast(@NonNull String msg); + + /** The codec used by Android. */ + static @NonNull MessageCodec getCodec() { + return new StandardMessageCodec(); + } + /**Sets up an instance of `Android` to handle messages through the `binaryMessenger`. */ + static void setUp(@NonNull BinaryMessenger binaryMessenger, @Nullable Android api) { + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.alist_flutter.Android.startService", getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + try { + api.startService(); + wrapped.add(0, null); + } + catch (Throwable exception) { + ArrayList wrappedError = wrapError(exception); + wrapped = wrappedError; + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.alist_flutter.Android.isRunning", getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + try { + Boolean output = api.isRunning(); + wrapped.add(0, output); + } + catch (Throwable exception) { + ArrayList wrappedError = wrapError(exception); + wrapped = wrappedError; + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.alist_flutter.Android.getAListVersion", getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + try { + String output = api.getAListVersion(); + wrapped.add(0, output); + } + catch (Throwable exception) { + ArrayList wrappedError = wrapError(exception); + wrapped = wrappedError; + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.alist_flutter.Android.getVersionName", getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + try { + String output = api.getVersionName(); + wrapped.add(0, output); + } + catch (Throwable exception) { + ArrayList wrappedError = wrapError(exception); + wrapped = wrappedError; + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.alist_flutter.Android.getVersionCode", getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + try { + Long output = api.getVersionCode(); + wrapped.add(0, output); + } + catch (Throwable exception) { + ArrayList wrappedError = wrapError(exception); + wrapped = wrappedError; + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.alist_flutter.Android.toast", getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + ArrayList args = (ArrayList) message; + String msgArg = (String) args.get(0); + try { + api.toast(msgArg); + wrapped.add(0, null); + } + catch (Throwable exception) { + ArrayList wrappedError = wrapError(exception); + wrapped = wrappedError; + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.alist_flutter.Android.longToast", getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList(); + ArrayList args = (ArrayList) message; + String msgArg = (String) args.get(0); + try { + api.longToast(msgArg); + wrapped.add(0, null); + } + catch (Throwable exception) { + ArrayList wrappedError = wrapError(exception); + wrapped = wrappedError; + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + } + } + /** Generated class from Pigeon that represents Flutter messages that can be called from Java. */ + public static class Event { + private final @NonNull BinaryMessenger binaryMessenger; + + public Event(@NonNull BinaryMessenger argBinaryMessenger) { + this.binaryMessenger = argBinaryMessenger; + } + + /** Public interface for sending reply. */ + /** The codec used by Event. */ + static @NonNull MessageCodec getCodec() { + return new StandardMessageCodec(); + } + public void onServiceStatusChanged(@NonNull Boolean isRunningArg, @NonNull VoidResult result) { + final String channelName = "dev.flutter.pigeon.alist_flutter.Event.onServiceStatusChanged"; + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, channelName, getCodec()); + channel.send( + new ArrayList(Collections.singletonList(isRunningArg)), + channelReply -> { + if (channelReply instanceof List) { + List listReply = (List) channelReply; + if (listReply.size() > 1) { + result.error(new FlutterError((String) listReply.get(0), (String) listReply.get(1), (String) listReply.get(2))); + } else { + result.success(); + } + } else { + result.error(createConnectionError(channelName)); + } + }); + } + } +} diff --git a/android/app/src/main/kotlin/com/github/jing332/alistflutter/App.kt b/android/app/src/main/kotlin/com/github/jing332/alistflutter/App.kt index a27d4c6..376fe47 100644 --- a/android/app/src/main/kotlin/com/github/jing332/alistflutter/App.kt +++ b/android/app/src/main/kotlin/com/github/jing332/alistflutter/App.kt @@ -16,6 +16,5 @@ class App : FlutterApplication() { super.onCreate() app = this - longToast("init!") } } \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/github/jing332/alistflutter/MainActivity.kt b/android/app/src/main/kotlin/com/github/jing332/alistflutter/MainActivity.kt index 540bc86..36d0217 100644 --- a/android/app/src/main/kotlin/com/github/jing332/alistflutter/MainActivity.kt +++ b/android/app/src/main/kotlin/com/github/jing332/alistflutter/MainActivity.kt @@ -7,16 +7,17 @@ import android.content.IntentFilter import android.os.Bundle import android.util.Log import androidx.localbroadcastmanager.content.LocalBroadcastManager -import com.github.jing332.alistflutter.config.AppConfig +import com.github.jing332.alistflutter.bridge.AndroidBridge +import com.github.jing332.alistflutter.bridge.AppConfigBridge import com.github.jing332.alistflutter.model.ShortCuts +import com.github.jing332.pigeon.GeneratedApi +import com.github.jing332.pigeon.GeneratedApi.VoidResult import io.flutter.embedding.android.FlutterActivity -import io.flutter.plugin.common.EventChannel import io.flutter.plugin.common.MethodCall import io.flutter.plugin.common.MethodChannel import io.flutter.plugins.GeneratedPluginRegistrant -class MainActivity : FlutterActivity(), MethodChannel.MethodCallHandler, - EventChannel.StreamHandler { +class MainActivity : FlutterActivity() { companion object { private val TAG = "MainActivity" const val BRIDGE_CHANNEL = "alistflutter/bridge" @@ -26,7 +27,7 @@ class MainActivity : FlutterActivity(), MethodChannel.MethodCallHandler, } private val receiver by lazy { MyReceiver() } - private var mEventSink: EventChannel.EventSink? = null + private var mEvent: GeneratedApi.Event? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -37,33 +38,11 @@ class MainActivity : FlutterActivity(), MethodChannel.MethodCallHandler, GeneratedPluginRegistrant.registerWith(this.flutterEngine!!) - MethodChannel(flutterEngine!!.dartExecutor.binaryMessenger, BRIDGE_CHANNEL) - .setMethodCallHandler(this) + val binaryMessage = flutterEngine!!.dartExecutor.binaryMessenger + GeneratedApi.AppConfig.setUp(binaryMessage, AppConfigBridge) + GeneratedApi.Android.setUp(binaryMessage, AndroidBridge(this)) + mEvent = GeneratedApi.Event(binaryMessage) - MethodChannel(flutterEngine!!.dartExecutor.binaryMessenger, CONFIG_CHANNEL) - .setMethodCallHandler { call, result -> - when (call.method) { - "isWakeLockEnabled" -> result.success(AppConfig.isWakeLockEnabled) - "setWakeLockEnabled" -> { - AppConfig.isWakeLockEnabled = call.arguments as Boolean - result.success(null) - } - - "isStartAtBootEnabled" -> result.success(AppConfig.isStartAtBootEnabled) - "setStartAtBootEnabled" -> { - AppConfig.isStartAtBootEnabled = call.arguments as Boolean - result.success(null) - } - - "isAutoCheckUpdateEnabled" -> result.success(AppConfig.isAutoCheckUpdateEnabled) - "setAutoCheckUpdateEnabled" -> { - AppConfig.isAutoCheckUpdateEnabled = call.arguments as Boolean - result.success(null) - } - } - } - EventChannel(flutterEngine!!.dartExecutor.binaryMessenger, EVENT_CHANNEL) - .setStreamHandler(this) } override fun onDestroy() { @@ -76,31 +55,18 @@ class MainActivity : FlutterActivity(), MethodChannel.MethodCallHandler, inner class MyReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { if (intent.action == AListService.ACTION_STATUS_CHANGED) { - mEventSink?.success(AListService.isRunning) - } - } - } + Log.e(TAG, "onReceive: ${AListService.isRunning}") + mEvent?.onServiceStatusChanged(AListService.isRunning, object : VoidResult { + override fun success() { - override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) { - when (call.method) { - "startService" -> { - Log.d(TAG, "startService") - startService(Intent(this, AListService::class.java)) - result.success(null) - } + } - "isRunning" -> result.success(AListService.isRunning) + override fun error(error: Throwable) { + } - else -> result.notImplemented() + }) + } } } - override fun onListen(arguments: Any?, events: EventChannel.EventSink?) { - mEventSink = events - } - - override fun onCancel(arguments: Any?) { - - } - } diff --git a/android/app/src/main/kotlin/com/github/jing332/alistflutter/bridge/AndroidBridge.kt b/android/app/src/main/kotlin/com/github/jing332/alistflutter/bridge/AndroidBridge.kt new file mode 100644 index 0000000..bf8866f --- /dev/null +++ b/android/app/src/main/kotlin/com/github/jing332/alistflutter/bridge/AndroidBridge.kt @@ -0,0 +1,30 @@ +package com.github.jing332.alistflutter.bridge + +import android.content.Context +import android.content.Intent +import com.github.jing332.alistflutter.AListService +import com.github.jing332.alistflutter.BuildConfig +import com.github.jing332.alistflutter.utils.ToastUtils.longToast +import com.github.jing332.alistflutter.utils.ToastUtils.toast +import com.github.jing332.pigeon.GeneratedApi + +class AndroidBridge(private val context: Context) : GeneratedApi.Android { + override fun startService() { + context.startService(Intent(context, AListService::class.java)) + } + + override fun isRunning() = AListService.isRunning + override fun getAListVersion() = BuildConfig.ALIST_VERSION + override fun getVersionName() = BuildConfig.VERSION_NAME + + override fun getVersionCode() = BuildConfig.VERSION_CODE.toLong() + + + override fun toast(msg: String) { + context.toast(msg) + } + + override fun longToast(msg: String) { + context.longToast(msg) + } +} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/github/jing332/alistflutter/bridge/AppConfigBridge.kt b/android/app/src/main/kotlin/com/github/jing332/alistflutter/bridge/AppConfigBridge.kt new file mode 100644 index 0000000..23bd389 --- /dev/null +++ b/android/app/src/main/kotlin/com/github/jing332/alistflutter/bridge/AppConfigBridge.kt @@ -0,0 +1,25 @@ +package com.github.jing332.alistflutter.bridge + +import com.github.jing332.alistflutter.config.AppConfig +import com.github.jing332.pigeon.GeneratedApi + + +object AppConfigBridge : GeneratedApi.AppConfig { + override fun isWakeLockEnabled() = AppConfig.isWakeLockEnabled + + override fun isStartAtBootEnabled() = AppConfig.isStartAtBootEnabled + + override fun isAutoCheckUpdateEnabled() = AppConfig.isAutoCheckUpdateEnabled + + override fun setAutoCheckUpdateEnabled(enabled: Boolean) { + AppConfig.isAutoCheckUpdateEnabled = enabled + } + + override fun setStartAtBootEnabled(enabled: Boolean) { + AppConfig.isStartAtBootEnabled = enabled + } + + override fun setWakeLockEnabled(enabled: Boolean) { + AppConfig.isWakeLockEnabled = enabled + } +} \ No newline at end of file diff --git a/android/src/main/java/com/github/jing332/pigeon/Api.java b/android/src/main/java/com/github/jing332/pigeon/Api.java deleted file mode 100644 index 440d7a7..0000000 --- a/android/src/main/java/com/github/jing332/pigeon/Api.java +++ /dev/null @@ -1,42 +0,0 @@ -// Autogenerated from Pigeon (v16.0.0), do not edit directly. -// See also: https://pub.dev/packages/pigeon - -package com.example.pigeon; - -import android.util.Log; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -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; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** Generated class from Pigeon. */ -@SuppressWarnings({"unused", "unchecked", "CodeBlock2Expr", "RedundantSuppression", "serial"}) -public class Api { - - /** Error class for passing custom error details to Flutter via a thrown PlatformException. */ - public static class FlutterError extends RuntimeException { - - /** The error code. */ - public final String code; - - /** The error details. Must be a datatype supported by the api codec. */ - public final Object details; - - public FlutterError(@NonNull String code, @Nullable String message, @Nullable Object details) - { - super(message); - this.code = code; - this.details = details; - } - } -} diff --git a/lib/bridges/app_config.dart b/lib/bridges/app_config.dart deleted file mode 100644 index 602cc2c..0000000 --- a/lib/bridges/app_config.dart +++ /dev/null @@ -1,29 +0,0 @@ -import 'package:flutter/services.dart'; - -abstract class AppConfig { - static const MethodChannel _channel = MethodChannel('alistflutter/config'); - - static Future isWakLockEnabled() async { - return await _channel.invokeMethod("isWakeLockEnabled"); - } - - static void setWakeLockEnabled(bool enabled) { - _channel.invokeMethod("setWakeLockEnabled", enabled); - } - - static bool isStartAtBootEnabled() { - return _channel.invokeMethod("isStartAtBootEnabled") as bool; - } - - static void setStartAtBootEnabled(bool enabled) { - _channel.invokeMethod("setStartAtBootEnabled", enabled); - } - - static bool isAutoCheckUpdateEnabled() { - return _channel.invokeMethod("isAutoCheckUpdateEnabled") as bool; - } - - static void setAutoCheckUpdateEnabled(bool enabled) { - _channel.invokeMethod("setAutoCheckUpdateEnabled", enabled); - } -} diff --git a/lib/bridges/bridge.dart b/lib/bridges/bridge.dart deleted file mode 100644 index 0af5d55..0000000 --- a/lib/bridges/bridge.dart +++ /dev/null @@ -1,13 +0,0 @@ -import 'package:flutter/services.dart'; - -abstract class Bridge { - static const MethodChannel _channel = MethodChannel('alistflutter/bridge'); - - static void startService() { - _channel.invokeMethod("startService"); - } - - static void isRunning() { - _channel.invokeMethod("isRunning"); - } -} diff --git a/lib/bridges/event.dart b/lib/bridges/event.dart deleted file mode 100644 index b006464..0000000 --- a/lib/bridges/event.dart +++ /dev/null @@ -1,8 +0,0 @@ -import 'package:flutter/services.dart'; - -abstract class Event { - static const EventChannel _eventChannel = EventChannel('alistflutter/event'); - static void onListenStreamData(onEvent, onError) { - _eventChannel.receiveBroadcastStream().listen(onEvent, onError: onError); - } -} diff --git a/lib/generated_api.dart b/lib/generated_api.dart index b069a17..5e269a3 100644 --- a/lib/generated_api.dart +++ b/lib/generated_api.dart @@ -7,3 +7,397 @@ import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer; import 'package:flutter/services.dart'; + +PlatformException _createConnectionError(String channelName) { + return PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel: "$channelName".', + ); +} + +List wrapResponse({Object? result, PlatformException? error, bool empty = false}) { + if (empty) { + return []; + } + if (error == null) { + return [result]; + } + return [error.code, error.message, error.details]; +} + +class AppConfig { + /// Constructor for [AppConfig]. 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. + AppConfig({BinaryMessenger? binaryMessenger}) + : __pigeon_binaryMessenger = binaryMessenger; + final BinaryMessenger? __pigeon_binaryMessenger; + + static const MessageCodec pigeonChannelCodec = StandardMessageCodec(); + + Future isWakeLockEnabled() async { + const String __pigeon_channelName = 'dev.flutter.pigeon.alist_flutter.AppConfig.isWakeLockEnabled'; + final BasicMessageChannel __pigeon_channel = BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send(null) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else if (__pigeon_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (__pigeon_replyList[0] as bool?)!; + } + } + + Future setWakeLockEnabled(bool enabled) async { + const String __pigeon_channelName = 'dev.flutter.pigeon.alist_flutter.AppConfig.setWakeLockEnabled'; + final BasicMessageChannel __pigeon_channel = BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send([enabled]) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else { + return; + } + } + + Future isStartAtBootEnabled() async { + const String __pigeon_channelName = 'dev.flutter.pigeon.alist_flutter.AppConfig.isStartAtBootEnabled'; + final BasicMessageChannel __pigeon_channel = BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send(null) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else if (__pigeon_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (__pigeon_replyList[0] as bool?)!; + } + } + + Future setStartAtBootEnabled(bool enabled) async { + const String __pigeon_channelName = 'dev.flutter.pigeon.alist_flutter.AppConfig.setStartAtBootEnabled'; + final BasicMessageChannel __pigeon_channel = BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send([enabled]) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else { + return; + } + } + + Future isAutoCheckUpdateEnabled() async { + const String __pigeon_channelName = 'dev.flutter.pigeon.alist_flutter.AppConfig.isAutoCheckUpdateEnabled'; + final BasicMessageChannel __pigeon_channel = BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send(null) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else if (__pigeon_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (__pigeon_replyList[0] as bool?)!; + } + } + + Future setAutoCheckUpdateEnabled(bool enabled) async { + const String __pigeon_channelName = 'dev.flutter.pigeon.alist_flutter.AppConfig.setAutoCheckUpdateEnabled'; + final BasicMessageChannel __pigeon_channel = BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send([enabled]) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else { + return; + } + } +} + +class Android { + /// Constructor for [Android]. 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. + Android({BinaryMessenger? binaryMessenger}) + : __pigeon_binaryMessenger = binaryMessenger; + final BinaryMessenger? __pigeon_binaryMessenger; + + static const MessageCodec pigeonChannelCodec = StandardMessageCodec(); + + Future startService() async { + const String __pigeon_channelName = 'dev.flutter.pigeon.alist_flutter.Android.startService'; + final BasicMessageChannel __pigeon_channel = BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send(null) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else { + return; + } + } + + Future isRunning() async { + const String __pigeon_channelName = 'dev.flutter.pigeon.alist_flutter.Android.isRunning'; + final BasicMessageChannel __pigeon_channel = BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send(null) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else if (__pigeon_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (__pigeon_replyList[0] as bool?)!; + } + } + + Future getAListVersion() async { + const String __pigeon_channelName = 'dev.flutter.pigeon.alist_flutter.Android.getAListVersion'; + final BasicMessageChannel __pigeon_channel = BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send(null) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else if (__pigeon_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (__pigeon_replyList[0] as String?)!; + } + } + + Future getVersionName() async { + const String __pigeon_channelName = 'dev.flutter.pigeon.alist_flutter.Android.getVersionName'; + final BasicMessageChannel __pigeon_channel = BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send(null) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else if (__pigeon_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (__pigeon_replyList[0] as String?)!; + } + } + + Future getVersionCode() async { + const String __pigeon_channelName = 'dev.flutter.pigeon.alist_flutter.Android.getVersionCode'; + final BasicMessageChannel __pigeon_channel = BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send(null) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else if (__pigeon_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (__pigeon_replyList[0] as int?)!; + } + } + + Future toast(String msg) async { + const String __pigeon_channelName = 'dev.flutter.pigeon.alist_flutter.Android.toast'; + final BasicMessageChannel __pigeon_channel = BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send([msg]) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else { + return; + } + } + + Future longToast(String msg) async { + const String __pigeon_channelName = 'dev.flutter.pigeon.alist_flutter.Android.longToast'; + final BasicMessageChannel __pigeon_channel = BasicMessageChannel( + __pigeon_channelName, + pigeonChannelCodec, + binaryMessenger: __pigeon_binaryMessenger, + ); + final List? __pigeon_replyList = + await __pigeon_channel.send([msg]) as List?; + if (__pigeon_replyList == null) { + throw _createConnectionError(__pigeon_channelName); + } else if (__pigeon_replyList.length > 1) { + throw PlatformException( + code: __pigeon_replyList[0]! as String, + message: __pigeon_replyList[1] as String?, + details: __pigeon_replyList[2], + ); + } else { + return; + } + } +} + +abstract class Event { + static const MessageCodec pigeonChannelCodec = StandardMessageCodec(); + + void onServiceStatusChanged(bool isRunning); + + static void setup(Event? api, {BinaryMessenger? binaryMessenger}) { + { + final BasicMessageChannel __pigeon_channel = BasicMessageChannel( + 'dev.flutter.pigeon.alist_flutter.Event.onServiceStatusChanged', pigeonChannelCodec, + binaryMessenger: binaryMessenger); + if (api == null) { + __pigeon_channel.setMessageHandler(null); + } else { + __pigeon_channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.alist_flutter.Event.onServiceStatusChanged was null.'); + final List args = (message as List?)!; + final bool? arg_isRunning = (args[0] as bool?); + assert(arg_isRunning != null, + 'Argument for dev.flutter.pigeon.alist_flutter.Event.onServiceStatusChanged was null, expected non-null bool.'); + try { + api.onServiceStatusChanged(arg_isRunning!); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); + } + }); + } + } + } +} diff --git a/lib/main.dart b/lib/main.dart index 804b3b8..4562ce1 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,7 +1,3 @@ -import 'dart:developer'; - -import 'package:alist_flutter/bridges/app_config.dart'; -import 'package:alist_flutter/bridges/bridge.dart'; import 'package:alist_flutter/pages/alist.dart'; import 'package:alist_flutter/pages/settings.dart'; import 'package:alist_flutter/pages/web.dart'; @@ -67,32 +63,9 @@ class _MyHomePageState extends State { int _selectedIndex = 0; final PageController _pageController = PageController(); - void _switch() { - Bridge.startService(); - // _text = ; - AppConfig.isWakLockEnabled().then((value) { - log("isWakLockEnabled: $value"); - setState(() { - _text = value.toString(); - }); - }); - } - @override Widget build(BuildContext context) { return Scaffold( - // appBar: AppBar( - // // TRY THIS: Try changing the color here to a specific color (to - // // Colors.amber, perhaps?) and trigger a hot reload to see the AppBar - // // change color while the other colors stay the same. - // backgroundColor: Theme - // .of(context) - // .colorScheme - // .inversePrimary, - // // Here we take the value from the MyHomePage object that was created by - // // the App.build method, and use it to set our appbar title. - // title: Text(widget.title), - // ), body: PageView.builder( itemBuilder: (context, index) { return [ @@ -101,6 +74,7 @@ class _MyHomePageState extends State { const SettingsScreen() ][index]; }, + physics: const NeverScrollableScrollPhysics(), scrollDirection: Axis.horizontal, controller: _pageController, onPageChanged: (int index) { diff --git a/lib/pages/alist.dart b/lib/pages/alist.dart index 7363ff8..f95b0ed 100644 --- a/lib/pages/alist.dart +++ b/lib/pages/alist.dart @@ -1,3 +1,4 @@ +import 'package:alist_flutter/generated_api.dart'; import 'package:alist_flutter/widgets/switch_floating_action_button.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; @@ -8,17 +9,56 @@ class AListScreen extends StatelessWidget { @override Widget build(BuildContext context) { final ui = Get.put(AListController()); - return Obx(() => Scaffold( + return Obx(() => + Scaffold( + appBar: AppBar( + backgroundColor: Theme + .of(context) + .colorScheme + .inversePrimary, + title: Text("AList - ${ui.alistVersion.value}"), + actions: [ + IconButton( + onPressed: () {}, + icon: const Icon(Icons.add_home), + ), + IconButton( + onPressed: () {}, + icon: const Icon(Icons.password), + ), + ], + ), floatingActionButton: SwitchFloatingButton( isSwitch: ui.isSwitch.value, - onSwitchChange: (s ) { + onSwitchChange: (s) { ui.isSwitch.value = s; + Android().startService(); }, ), )); } } +class MyEventReceiver extends Event { + RxBool isRunning; + + MyEventReceiver(this.isRunning); + + @override + void onServiceStatusChanged(bool b) { + isRunning.value = b; + } +} + class AListController extends GetxController { var isSwitch = false.obs; + var alistVersion = "".obs; + + @override + void onInit() { + Event.setup(MyEventReceiver(isSwitch)); + Android().getAListVersion().then((value) => alistVersion.value = value); + + super.onInit(); + } } diff --git a/pigeons/pigeon.dart b/pigeons/pigeon.dart index e69de29..69e25cc 100644 --- a/pigeons/pigeon.dart +++ b/pigeons/pigeon.dart @@ -0,0 +1,38 @@ +import 'package:pigeon/pigeon.dart'; + +@HostApi() +abstract class AppConfig { + bool isWakeLockEnabled(); + + void setWakeLockEnabled(bool enabled); + + bool isStartAtBootEnabled(); + + void setStartAtBootEnabled(bool enabled); + + bool isAutoCheckUpdateEnabled(); + + void setAutoCheckUpdateEnabled(bool enabled); +} + +@HostApi() +abstract class Android { + void startService(); + + bool isRunning(); + + String getAListVersion(); + + String getVersionName(); + + int getVersionCode(); + + void toast(String msg); + + void longToast(String msg); +} + +@FlutterApi() +abstract class Event { + void onServiceStatusChanged(bool isRunning); +} diff --git a/pigeons/run.cmd b/pigeons/run.cmd index 0f5371d..cd4e315 100644 --- a/pigeons/run.cmd +++ b/pigeons/run.cmd @@ -1,2 +1,5 @@ -flutter pub run pigeon --input pigeons/pigeon.dart --dart_out lib/generated_api.dart --java_out android/src/main/java/com/github/jing332/pigeon/Api.java --java_package "com.example.pigeon" +flutter pub run pigeon --input pigeons/pigeon.dart^ + --dart_out lib/generated_api.dart^ + --java_out android/app/src/main/java/com/github/jing332/pigeon/GeneratedApi.java^ + --java_package "com.github.jing332.pigeon" ` \ No newline at end of file diff --git a/pubspec.yaml b/pubspec.yaml index bbedf13..f8492cd 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 1.0.0+1 +version: 1.0.0+1 # 不使用此版本号 environment: sdk: '>=3.2.4 <4.0.0'