update ios project

update ios project
This commit is contained in:
Zeus
2024-07-24 11:51:39 +08:00
parent 876d355b18
commit 1bf69048f3
275 changed files with 3372 additions and 1015 deletions
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022 sail-tunnel
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+1
View File
@@ -0,0 +1 @@
include: package:flutter_lints/flutter.yaml
+13
View File
@@ -0,0 +1,13 @@
gradle-wrapper.jar
/.gradle
/captures/
/gradlew
/gradlew.bat
/local.properties
GeneratedPluginRegistrant.java
# Remember to never publicly share your keystore.
# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
key.properties
**/*.keystore
**/*.jks
+107
View File
@@ -0,0 +1,107 @@
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader ->
localProperties.load(reader)
}
}
def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '1'
}
def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
flutterVersionName = '1.0'
}
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-parcelize'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android {
compileSdkVersion 33
ndkVersion flutter.ndkVersion
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
main.jniLibs.srcDirs = ['libs', 'src/main/jniLibs']
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.sail_tunnel.sail"
// You can update the following values to match your application needs.
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration.
minSdkVersion 26
//noinspection ExpiredTargetSdkVersion
targetSdkVersion 28
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
// ndk {
// abiFilters 'armeabi', 'armeabi-v7a', 'arm64-v8a', 'x86', "x86_64"
// }
// dexOptions {
// incremental true
// javaMaxHeapSize "4g"
// preDexLibraries true
// dexInProcess = true
// }
ndk {
if (!project.hasProperty('target-platform')) {
abiFilters 'arm64-v8a', 'armeabi-v7a', 'x86_64'
} else {
def platforms = project.property('target-platform').split(',')
def platformMap = [
'android-arm' : 'armeabi-v7a',
'android-arm64': 'arm64-v8a',
'android-x86' : 'x86',
'android-x64' : 'x86_64',
]
abiFilters = platforms.stream().map({ e ->
platformMap.containsKey(e) ? platformMap[e] : e
}).toArray()
}
}
}
buildTypes {
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
}
}
}
flutter {
source '../..'
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation "com.jakewharton.timber:timber:5.0.1"
implementation 'androidx.work:work-runtime-ktx:2.7.1'
implementation 'androidx.preference:preference-ktx:1.2.0'
implementation "dnsjava:dnsjava:3.5.1"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.6.4"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1"
}
@@ -0,0 +1,20 @@
{
"version": 3,
"artifactType": {
"type": "APK",
"kind": "Directory"
},
"applicationId": "com.sail_tunnel.sail",
"variantName": "profile",
"elements": [
{
"type": "SINGLE",
"filters": [],
"attributes": [],
"versionCode": 3,
"versionName": "1.0.2",
"outputFile": "app-profile.apk"
}
],
"elementType": "File"
}
@@ -0,0 +1,10 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.sail_tunnel.sail">
<!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
</manifest>
@@ -0,0 +1,87 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.sail_tunnel.sail">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_NUMBERS" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"></uses-permission>
<uses-permission android:name="android.permission.WAKE_LOCK"></uses-permission>
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.SYSTEM_OVERLAY_WINDOW"/>
<uses-feature
android:name="android.software.leanback"
android:required="false" />
<uses-feature
android:name="android.hardware.touchscreen"
android:required="false" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission
android:name="android.permission.QUERY_ALL_PACKAGES"
/>
<application
android:label="UUVPN"
android:name="${applicationName}"
android:icon="@mipmap/app_icon"
android:largeHeap="true"
android:supportsRtl="true"
android:allowBackup="true"
android:hardwareAccelerated="false">
<!-- android:icon="@mipmap/ic_launcher"-->
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="false"
android:windowSoftInputMode="adjustResize"
>
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<service
android:name=".TunnelService"
android:enabled="true"
android:permission="android.permission.BIND_VPN_SERVICE"
android:exported="false">
<intent-filter>
<action android:name="android.net.VpnService"/>
</intent-filter>
</service>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2"/>
</application>
</manifest>
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,54 @@
package com.sail_tunnel.sail
import android.app.*
import android.content.*
import android.net.ConnectivityManager
import android.util.Log
import androidx.annotation.VisibleForTesting
import androidx.core.content.getSystemService
import kotlinx.coroutines.DEBUG_PROPERTY_NAME
import kotlinx.coroutines.DEBUG_PROPERTY_VALUE_ON
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import timber.log.Timber
import kotlin.reflect.KClass
import androidx.work.Configuration
import com.sail_tunnel.sail.utils.DeviceStorageApp
object Core : Configuration.Provider {
lateinit var app: MainActivity
@VisibleForTesting set
lateinit var configureIntent: (Context) -> PendingIntent
val activity by lazy { app.getSystemService<ActivityManager>()!! }
val connectivity by lazy { app.getSystemService<ConnectivityManager>()!! }
val deviceStorage by lazy { DeviceStorageApp(app) }
fun init(app: MainActivity, configureClass: KClass<out Any>) {
this.app = app
this.configureIntent = {
PendingIntent.getActivity(it, 0, Intent(it, configureClass.java)
.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT), PendingIntent.FLAG_IMMUTABLE)
}
// overhead of debug mode is minimal: https://github.com/Kotlin/kotlinx.coroutines/blob/f528898/docs/debugging.md#debug-mode
System.setProperty(DEBUG_PROPERTY_NAME, DEBUG_PROPERTY_VALUE_ON)
Timber.plant(object : Timber.DebugTree() {
override fun log(priority: Int, tag: String?, message: String, t: Throwable?) {
if (t == null) {
if (priority != Log.DEBUG || BuildConfig.DEBUG) Log.println(priority, tag, message)
} else {
if (priority >= Log.WARN || priority == Log.DEBUG) Log.println(priority, tag, message)
}
}
})
}
override fun getWorkManagerConfiguration() = Configuration.Builder().apply {
setDefaultProcessName(app.packageName + ":bg")
setMinimumLoggingLevel(if (BuildConfig.DEBUG) Log.VERBOSE else Log.INFO)
setExecutor { GlobalScope.launch { it.run() } }
setTaskExecutor { GlobalScope.launch { it.run() } }
}.build()
}
@@ -0,0 +1,160 @@
package com.sail_tunnel.sail
import android.content.Context
import android.content.ContextWrapper
import android.content.Intent
import android.content.IntentFilter
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
import android.net.VpnService
import android.os.BatteryManager
import android.os.Build
import android.os.Bundle
import android.util.Log
import com.sail_tunnel.sail.services.VpnState
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.android.FlutterView
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.embedding.engine.plugins.util.GeneratedPluginRegister
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugins.GeneratedPluginRegistrant
import java.io.File
class MainActivity: FlutterActivity() {
private val channel = "com.vpntunnel.vpnzeus/vpn_manager"
private fun getServiceIntent(): Intent {
return Intent(this, TunnelService::class.java)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Core.init(this, MainActivity::class)
// GeneratedPluginRegistrant.registerWith(FlutterEngine(this))
// GeneratedPluginRegister.registerGeneratedPlugins(FlutterEngine(this));
// MethodChannel(FlutterView(this), channel).setMethodCallHandler { call, result ->
// if (call.method == "getBatteryLevel") {
// val batteryLevel : Int = getBatteryLevel()
//
// if (batteryLevel != -1) {
// result.success(batteryLevel)
// } else {
// result.error("UNAVAILABLE", "Battery level not available.", null)
// }
// } else {
// Log.e("user_debug", "getBatteryLevel is not method of called")
// result.notImplemented()
// }
// }
}
private fun getBatteryLevel(): Int {
val batteryLevel: Int
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
val batteryManager = getSystemService(Context.BATTERY_SERVICE) as BatteryManager
batteryLevel = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
} else {
val intent = ContextWrapper(applicationContext).registerReceiver(null, IntentFilter(Intent.ACTION_BATTERY_CHANGED))
batteryLevel = intent!!.getIntExtra(BatteryManager.EXTRA_LEVEL, -1) * 100 / intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1)
}
return batteryLevel
}
override fun onResume() {
super.onResume()
}
override fun onPause() {
super.onPause()
}
private fun getVPNConnectionStatus(): Boolean? {
val context = this@MainActivity
val connectivityManager =
context.getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager
val networks = connectivityManager.allNetworks
//val TAG = "getVPNConnectionStatus"
//Log.i(TAG, "Network count: " + networks.size);
var hasvpn = false
for (i in 0 until networks.size) {
// connectivityManager.getNetworkCapabilities()
val caps: NetworkCapabilities? = connectivityManager.getNetworkCapabilities(networks.get(i))
hasvpn = caps?.hasTransport(NetworkCapabilities.TRANSPORT_VPN) == true
// Log.i(TAG, "Network " + i + ": " + networks.get(i).toString())
// Log.i(TAG, "VPN transport is: " + caps?.hasTransport(NetworkCapabilities.TRANSPORT_VPN))
// Log.i(TAG, "NOT_VPN capability is: " + caps?.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN) )
}
return hasvpn
// val activeNetwork = connectivityManager.activeNetwork
// val networkCapabilities = connectivityManager.getNetworkCapabilities(activeNetwork)
//
// return networkCapabilities?.hasTransport(NetworkCapabilities.TRANSPORT_VPN)
}
override fun configureFlutterEngine( flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, channel).setMethodCallHandler {
call, result ->
// This method is invoked on the main thread.
if (call.method == "getStatus") {
result.success(getVPNConnectionStatus())
} else if (call.method == "toggle") {
val intent = VpnService.prepare(this)
if (intent != null) {
startActivityForResult(intent, 0)
result.success(false)
} else {
startService(getServiceIntent())
result.success(true)
}
} else if (call.method == "getTunnelLog") {
// val context = Core.deviceStorage
// val configRoot = context.noBackupFilesDir
// val config = File(configRoot, VpnState.LEAF_LOG_FILE).readText()
// result.success(config)
} else if (call.method == "getTunnelConfiguration") {
val context = Core.deviceStorage
val configRoot = context.noBackupFilesDir
val config = File(configRoot, VpnState.CONFIG_FILE).readText()
val TAGs = "getVPNConnectionStatus"
Log.i(TAGs, config);
result.success(config)
} else if (call.method == "setTunnelConfiguration") {
try {
val context = Core.deviceStorage
val configRoot = context.noBackupFilesDir
val TAGs = "setTunnelConfiguration"
Log.i(TAGs, call.arguments.toString());
File(configRoot, VpnState.CONFIG_FILE).writeText(call.arguments.toString())
}catch (e: Exception ){
println("setTunnelConfiguration FILE NullPointerException")
}
} else if (call.method == "update") {
//
} else {
result.notImplemented()
}
}
}
override fun onActivityResult(request: Int, result: Int, data: Intent?) {
if (result == RESULT_OK) {
startService(getServiceIntent())
} else {
super.onActivityResult(request, result, data)
}
}
}
@@ -0,0 +1,251 @@
package com.sail_tunnel.sail
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.app.Service
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.graphics.BitmapFactory
import android.media.projection.MediaProjection
import android.media.projection.MediaProjectionManager
import android.net.*
import android.os.Build
import android.os.ParcelFileDescriptor
import androidx.core.app.NotificationCompat
import com.sail_tunnel.sail.net.DefaultNetworkListener
import com.sail_tunnel.sail.net.DnsResolverCompat
import com.sail_tunnel.sail.services.LocalDnsWorker
import com.sail_tunnel.sail.services.TunnelInstance
import com.sail_tunnel.sail.services.VpnState
import com.sail_tunnel.sail.utils.readableMessage
import kotlinx.coroutines.*
import java.io.File
import java.io.IOException
class TunnelService : VpnService() {
companion object {
private const val CORE_NAME = "leaf"
private const val VPN_MTU = 1500
private const val PRIVATE_VLAN4_CLIENT = "198.18.20.20"
private const val PRIVATE_VLAN4_ROUTER = "1.1.1.1"
}
inner class NullConnectionException : NullPointerException() {
override fun getLocalizedMessage() =
"Failed to start VPN service. You might need to reboot your device."
}
private val data = VpnState.Data()
private fun startRunner() {
if (Build.VERSION.SDK_INT >= 26) startForegroundService(Intent(this, javaClass))
else startService(Intent(this, javaClass))
}
private var pfd: ParcelFileDescriptor? = null
private var active = false
private var metered = false
var notification: Notification? = null
private val mResultData: Intent? = null
private val mMediaProjection: MediaProjection? = null
private val mMediaProjectionManager: MediaProjectionManager? = null
@Volatile
private var underlyingNetwork: Network? = null
set(value) {
field = value
if (active) setUnderlyingNetworks(underlyingNetworks)
}
private val underlyingNetworks
get() =
// clearing underlyingNetworks makes Android 9 consider the network to be metered
if (Build.VERSION.SDK_INT == 28 && metered) null else underlyingNetwork?.let {
arrayOf(
it
)
}
override fun onRevoke() = stopRunner()
private fun killProcesses(scope: CoroutineScope) {
data.proxy?.run {
shutdown(scope)
data.proxy = null
}
data.localDns?.shutdown(scope)
data.localDns = null
active = false
scope.launch { DefaultNetworkListener.stop(this) }
pfd?.close()
pfd = null
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
val data = data
if (data.state != VpnState.State.Stopped) return Service.START_NOT_STICKY
try {
data.proxy = TunnelInstance()
} catch (e: IllegalArgumentException) {
stopRunner(false, e.message)
return Service.START_NOT_STICKY
}
createNotificationChannel()
data.changeState(VpnState.State.Connecting)
data.connectingJob = GlobalScope.launch(Dispatchers.Main) {
try {
preInit()
startVpn()
data.changeState(VpnState.State.Connected)
} catch (_: CancellationException) {
// if the job was cancelled, it is canceller's responsibility to call stopRunner
} catch (exc: Throwable) {
stopRunner(false, exc.readableMessage)
} finally {
data.connectingJob = null
}
}
return START_NOT_STICKY
}
private fun createNotificationChannel() {
val CHANNEL_ID: String = "notification_id"
val builder = NotificationCompat.Builder(this.applicationContext,CHANNEL_ID) //获取一个Notification构造器
val nfIntent = Intent(this, MainActivity::class.java) //点击后跳转的界面,可以设置跳转数据
val pendingIntent: PendingIntent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
PendingIntent.getActivity(this, 0, nfIntent, PendingIntent.FLAG_IMMUTABLE)
} else {
PendingIntent.getActivity(this, 0, nfIntent, PendingIntent.FLAG_ONE_SHOT)
}
val intentClick = Intent(
this,MainActivity::class.java
// BroadcastReceiver::class.java
)
intentClick.action = "notification_clicked"
// intentClick.putExtra(BroadcastReceiver.TYPE, type)
val pendingIntentClick =
PendingIntent.getBroadcast(this, 0, intentClick, PendingIntent.FLAG_ONE_SHOT)
//.setContentIntent(pendingIntent) // 设置PendingIntent
builder.setContentIntent(pendingIntentClick).setLargeIcon(
BitmapFactory.decodeResource(
this.resources,
R.mipmap.app_icon_round
)
) // 设置下拉列表中的图标(大图标)
.setContentTitle("UUVPN") // 设置下拉列表里的标题
.setSmallIcon( R.mipmap.app_icon_round) // 设置状态栏内的小图标
.setContentText("正在运行...") // 设置上下文内容
.setWhen(System.currentTimeMillis()) // 设置该通知发生的时间
/*以下是对Android 8.0的适配*/
//普通notification适配
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
builder.setChannelId("notification_id")
}
//前台服务notification适配
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(
"notification_id",
"notification_name",
NotificationManager.IMPORTANCE_LOW
)
// Register the channel with the system
val notificationManager: NotificationManager =
getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannel(channel)
}
notification = builder.build() // 获取构建好的Notification
// notification.defaulte = Notification.DEFAULT_SOUND //设置为默认的声音
try {
startForeground(110, notification)
} catch (w: Exception) {
w.printStackTrace()
}
}
private suspend fun preInit() = DefaultNetworkListener.start(this) { underlyingNetwork = it }
private suspend fun rawResolver(query: ByteArray) =
// no need to listen for network here as this is only used for forwarding local DNS queries.
// retries should be attempted by client.
DnsResolverCompat.resolveRaw(underlyingNetwork ?: throw IOException("no network"), query)
private suspend fun startVpn() {
val builder = Builder()
.setConfigureIntent(Core.configureIntent(this))
.setSession(CORE_NAME)
.setMtu(VPN_MTU)
.addAddress(PRIVATE_VLAN4_CLIENT, 24)
.addDnsServer(PRIVATE_VLAN4_ROUTER)
.addRoute("0.0.0.0", 0)
active = true // possible race condition here?
builder.setUnderlyingNetworks(underlyingNetworks)
if (Build.VERSION.SDK_INT >= 29) builder.setMetered(metered)
this.pfd = builder.establish() ?: throw NullConnectionException()
val context = Core.deviceStorage
val configRoot = context.noBackupFilesDir
data.localDns = LocalDnsWorker(this::rawResolver).apply { start() }
val configFile = File(configRoot, VpnState.CONFIG_FILE)
val configContent = configFile
.readText()
.replace("{{leafLogFile}}", File(configRoot, VpnState.LEAF_LOG_FILE).absolutePath)
.replace("{{tunFd}}", this.pfd?.fd?.toLong().toString())
configFile.writeText(configContent)
data.proxy!!.start(
this,
File(Core.deviceStorage.noBackupFilesDir, "stat_main"),
configFile,
)
}
private fun stopRunner(restart: Boolean = false, msg: String? = null) {
if (data.state == VpnState.State.Stopping) return
// channge the state
data.changeState(VpnState.State.Stopping)
GlobalScope.launch(Dispatchers.Main.immediate) {
data.connectingJob?.cancelAndJoin() // ensure stop connecting first
// we use a coroutineScope here to allow clean-up in parallel
coroutineScope {
killProcesses(GlobalScope)
}
// change the state
data.changeState(VpnState.State.Stopped, msg)
// stop the service if nothing has bound to it
if (restart) startRunner() else {
stopSelf()
}
}
}
}
@@ -0,0 +1,23 @@
package com.sail_tunnel.sail.net
import android.net.LocalSocket
import kotlinx.coroutines.*
import timber.log.Timber
import java.io.File
abstract class ConcurrentLocalSocketListener(name: String, socketFile: File) : LocalSocketListener(name, socketFile),
CoroutineScope {
override val coroutineContext = Dispatchers.IO + SupervisorJob() + CoroutineExceptionHandler { _, t -> Timber.w(t) }
override fun accept(socket: LocalSocket) {
launch { super.accept(socket) }
}
override fun shutdown(scope: CoroutineScope) {
running = false
cancel()
super.shutdown(scope)
coroutineContext[Job]!!.also { job -> scope.launch { job.join() } }
}
}
@@ -0,0 +1,126 @@
package com.sail_tunnel.sail.net
import android.annotation.TargetApi
import android.net.ConnectivityManager
import android.net.Network
import android.net.NetworkCapabilities
import android.net.NetworkRequest
import android.os.Build
import android.os.Handler
import android.os.Looper
import androidx.annotation.RequiresApi
import com.sail_tunnel.sail.Core
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.channels.actor
import kotlinx.coroutines.runBlocking
import java.net.UnknownHostException
object DefaultNetworkListener {
private sealed class NetworkMessage {
class Start(val key: Any, val listener: (Network?) -> Unit) : NetworkMessage()
class Get : NetworkMessage() {
val response = CompletableDeferred<Network>()
}
class Stop(val key: Any) : NetworkMessage()
class Put(val network: Network) : NetworkMessage()
class Update(val network: Network) : NetworkMessage()
class Lost(val network: Network) : NetworkMessage()
}
private val networkActor = GlobalScope.actor<NetworkMessage>(Dispatchers.Unconfined) {
val listeners = mutableMapOf<Any, (Network?) -> Unit>()
var network: Network? = null
val pendingRequests = arrayListOf<NetworkMessage.Get>()
for (message in channel) when (message) {
is NetworkMessage.Start -> {
if (listeners.isEmpty()) register()
listeners[message.key] = message.listener
if (network != null) message.listener(network)
}
is NetworkMessage.Get -> {
check(listeners.isNotEmpty()) { "Getting network without any listeners is not supported" }
if (network == null) pendingRequests += message else message.response.complete(network)
}
is NetworkMessage.Stop -> if (listeners.isNotEmpty() && // was not empty
listeners.remove(message.key) != null && listeners.isEmpty()) {
network = null
unregister()
}
is NetworkMessage.Put -> {
network = message.network
pendingRequests.forEach { it.response.complete(message.network) }
pendingRequests.clear()
listeners.values.forEach { it(network) }
}
is NetworkMessage.Update -> if (network == message.network) listeners.values.forEach { it(network) }
is NetworkMessage.Lost -> if (network == message.network) {
network = null
listeners.values.forEach { it(null) }
}
}
}
suspend fun start(key: Any, listener: (Network?) -> Unit) = networkActor.send(NetworkMessage.Start(key, listener))
suspend fun get() = if (fallback) {
Core.connectivity.activeNetwork ?: throw UnknownHostException() // failed to listen, return current if available
} else NetworkMessage.Get().run {
networkActor.send(this)
response.await()
}
suspend fun stop(key: Any) = networkActor.send(NetworkMessage.Stop(key))
// NB: this runs in ConnectivityThread, and this behavior cannot be changed until API 26
private object Callback : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) = runBlocking { networkActor.send(NetworkMessage.Put(network)) }
override fun onCapabilitiesChanged(network: Network, networkCapabilities: NetworkCapabilities) {
// it's a good idea to refresh capabilities
runBlocking { networkActor.send(NetworkMessage.Update(network)) }
}
override fun onLost(network: Network) = runBlocking { networkActor.send(NetworkMessage.Lost(network)) }
}
private var fallback = false
private val request = NetworkRequest.Builder().apply {
addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
}.build()
private val mainHandler = Handler(Looper.getMainLooper())
/**
* Unfortunately registerDefaultNetworkCallback is going to return VPN interface since Android P DP1:
* https://android.googlesource.com/platform/frameworks/base/+/dda156ab0c5d66ad82bdcf76cda07cbc0a9c8a2e
*
* This makes doing a requestNetwork with REQUEST necessary so that we don't get ALL possible networks that
* satisfies default network capabilities but only THE default network. Unfortunately, we need to have
* android.permission.CHANGE_NETWORK_STATE to be able to call requestNetwork.
*
* Source: https://android.googlesource.com/platform/frameworks/base/+/2df4c7d/services/core/java/com/android/server/ConnectivityService.java#887
*/
private fun register() {
when (Build.VERSION.SDK_INT) {
in 31..Int.MAX_VALUE -> @TargetApi(31) {
Core.connectivity.registerBestMatchingNetworkCallback(request, Callback, mainHandler)
}
in 28 until 31 -> @TargetApi(28) { // we want REQUEST here instead of LISTEN
Core.connectivity.requestNetwork(request, Callback, mainHandler)
}
in 26 until 28 -> @TargetApi(26) {
Core.connectivity.registerDefaultNetworkCallback(Callback, mainHandler)
}
in 24 until 26 -> {
Core.connectivity.registerDefaultNetworkCallback(Callback)
}
else -> try {
fallback = false
Core.connectivity.requestNetwork(request, Callback)
} catch (e: RuntimeException) {
fallback = true // known bug on API 23: https://stackoverflow.com/a/33509180/2245107
}
}
}
private fun unregister() = Core.connectivity.unregisterNetworkCallback(Callback)
}
@@ -0,0 +1,167 @@
package com.sail_tunnel.sail.net
import android.annotation.TargetApi
import android.net.DnsResolver
import android.net.Network
import android.os.Build
import android.os.CancellationSignal
import androidx.annotation.RequiresApi
import com.sail_tunnel.sail.Core
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.asCoroutineDispatcher
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.withContext
import org.xbill.DNS.*
import java.io.IOException
import java.net.Inet4Address
import java.net.Inet6Address
import java.net.InetAddress
import java.util.concurrent.Executor
import java.util.concurrent.Executors
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
sealed class DnsResolverCompat {
companion object : DnsResolverCompat() {
private val instance by lazy {
when (Build.VERSION.SDK_INT) {
in 29..Int.MAX_VALUE -> DnsResolverCompat29
in 23 until 29 -> DnsResolverCompat23
else -> error("Unsupported API level")
}
}
override suspend fun resolve(network: Network, host: String) = instance.resolve(network, host)
override suspend fun resolveOnActiveNetwork(host: String) = instance.resolveOnActiveNetwork(host)
override suspend fun resolveRaw(network: Network, query: ByteArray) = instance.resolveRaw(network, query)
override suspend fun resolveRawOnActiveNetwork(query: ByteArray) = instance.resolveRawOnActiveNetwork(query)
// additional platform-independent DNS helpers
/**
* TTL returned from localResolver is set to 120. Android API does not provide TTL,
* so we suppose Android apps should not care about TTL either.
*/
private const val TTL = 120L
fun prepareDnsResponse(request: Message) = Message(request.header.id).apply {
header.setFlag(Flags.QR.toInt()) // this is a response
header.setFlag(Flags.RA.toInt()) // recursion available
if (request.header.getFlag(Flags.RD.toInt())) header.setFlag(Flags.RD.toInt())
request.question?.also { addRecord(it, Section.QUESTION) }
}
}
abstract suspend fun resolve(network: Network, host: String): Array<InetAddress>
abstract suspend fun resolveOnActiveNetwork(host: String): Array<InetAddress>
abstract suspend fun resolveRaw(network: Network, query: ByteArray): ByteArray
abstract suspend fun resolveRawOnActiveNetwork(query: ByteArray): ByteArray
private object DnsResolverCompat23 : DnsResolverCompat() {
/**
* This dispatcher is used for noncancellable possibly-forever-blocking operations in network IO.
*
* See also: https://issuetracker.google.com/issues/133874590
*/
private val unboundedIO by lazy {
if (Core.activity.isLowRamDevice) Dispatchers.IO
else Executors.newCachedThreadPool().asCoroutineDispatcher()
}
override suspend fun resolve(network: Network, host: String) =
withContext(unboundedIO) { network.getAllByName(host) }
override suspend fun resolveOnActiveNetwork(host: String) =
withContext(unboundedIO) { InetAddress.getAllByName(host) }
private suspend fun resolveRaw(query: ByteArray, networkSpecified: Boolean = true,
hostResolver: suspend (String) -> Array<InetAddress>): ByteArray {
val request = try {
Message(query)
} catch (e: IOException) {
throw UnsupportedOperationException(e) // unrecognized packet
}
when (val opcode = request.header.opcode) {
Opcode.QUERY -> { }
else -> throw UnsupportedOperationException("Unsupported opcode $opcode")
}
val question = request.question
val isIpv6 = when (val type = question?.type) {
Type.A -> false
Type.AAAA -> true
Type.PTR -> {
/* Android does not provide a PTR lookup API for Network prior to Android 10 */
if (networkSpecified) throw IOException(UnsupportedOperationException("Network unspecified"))
val ip = try {
ReverseMap.fromName(question.name)
} catch (e: IOException) {
throw UnsupportedOperationException(e) // unrecognized PTR name
}
val hostname = withContext(unboundedIO) { ip.hostName }.let { hostname ->
if (hostname == ip.hostAddress) null else Name.fromString("$hostname.")
}
return prepareDnsResponse(request).apply {
hostname?.let { addRecord(PTRRecord(question.name, DClass.IN, TTL, it), Section.ANSWER) }
}.toWire()
}
else -> throw UnsupportedOperationException("Unsupported query type $type")
}
val host = question.name.canonicalize().toString(true)
return prepareDnsResponse(request).apply {
for (address in hostResolver(host).asIterable().run {
if (isIpv6) filterIsInstance<Inet6Address>() else filterIsInstance<Inet4Address>()
}) addRecord(when (address) {
is Inet4Address -> ARecord(question.name, DClass.IN, TTL, address)
is Inet6Address -> AAAARecord(question.name, DClass.IN, TTL, address)
else -> error("Unsupported address $address")
}, Section.ANSWER)
}.toWire()
}
override suspend fun resolveRaw(network: Network, query: ByteArray) =
resolveRaw(query) { resolve(network, it) }
override suspend fun resolveRawOnActiveNetwork(query: ByteArray) =
resolveRaw(query, false, this::resolveOnActiveNetwork)
}
@TargetApi(29)
private object DnsResolverCompat29 : DnsResolverCompat(), Executor {
/**
* This executor will run on its caller directly. On Q beta 3 thru 4, this results in calling in main thread.
*/
override fun execute(command: Runnable) = command.run()
private val activeNetwork get() = Core.connectivity.activeNetwork ?: throw IOException("no network")
override suspend fun resolve(network: Network, host: String): Array<InetAddress> {
return suspendCancellableCoroutine { cont ->
val signal = CancellationSignal()
cont.invokeOnCancellation { signal.cancel() }
// retry should be handled by client instead
DnsResolver.getInstance().query(network, host, DnsResolver.FLAG_NO_RETRY, this,
signal, object : DnsResolver.Callback<Collection<InetAddress>> {
override fun onAnswer(answer: Collection<InetAddress>, rcode: Int) =
cont.resume(answer.toTypedArray())
override fun onError(error: DnsResolver.DnsException) = cont.resumeWithException(
IOException(error)
)
})
}
}
override suspend fun resolveOnActiveNetwork(host: String) = resolve(activeNetwork, host)
override suspend fun resolveRaw(network: Network, query: ByteArray): ByteArray {
return suspendCancellableCoroutine { cont ->
val signal = CancellationSignal()
cont.invokeOnCancellation { signal.cancel() }
DnsResolver.getInstance().rawQuery(network, query, DnsResolver.FLAG_NO_RETRY, this,
signal, object : DnsResolver.Callback<ByteArray> {
override fun onAnswer(answer: ByteArray, rcode: Int) = cont.resume(answer)
override fun onError(error: DnsResolver.DnsException) = cont.resumeWithException(
IOException(error)
)
})
}
}
override suspend fun resolveRawOnActiveNetwork(query: ByteArray) = resolveRaw(activeNetwork, query)
}
}
@@ -0,0 +1,62 @@
package com.sail_tunnel.sail.net
import android.annotation.SuppressLint
import android.net.LocalServerSocket
import android.net.LocalSocket
import android.net.LocalSocketAddress
import android.system.ErrnoException
import android.system.Os
import android.system.OsConstants
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.channels.onFailure
import kotlinx.coroutines.channels.trySendBlocking
import kotlinx.coroutines.launch
import timber.log.Timber
import java.io.File
import java.io.IOException
abstract class LocalSocketListener(name: String, socketFile: File) : Thread(name) {
private val localSocket = LocalSocket().apply {
socketFile.delete() // It's a must-have to close and reuse previous local socket.
bind(LocalSocketAddress(socketFile.absolutePath, LocalSocketAddress.Namespace.FILESYSTEM))
}
private val serverSocket = LocalServerSocket(localSocket.fileDescriptor)
private val closeChannel = Channel<Unit>(1)
@Volatile
protected var running = true
/**
* Inherited class do not need to close input/output streams as they will be closed automatically.
*/
protected open fun accept(socket: LocalSocket) = socket.use { acceptInternal(socket) }
protected abstract fun acceptInternal(socket: LocalSocket)
final override fun run() {
localSocket.use {
while (running) {
try {
accept(serverSocket.accept())
} catch (e: IOException) {
if (running) Timber.w(e)
continue
}
}
}
closeChannel.trySendBlocking(Unit).onFailure { throw it!! }
}
@SuppressLint("NewApi")
open fun shutdown(scope: CoroutineScope) {
running = false
localSocket.fileDescriptor?.apply {
// see also: https://issuetracker.google.com/issues/36945762#comment15
if (valid()) try {
Os.shutdown(this, OsConstants.SHUT_RDWR)
} catch (e: ErrnoException) {
// suppress fd inactive or already closed
if (e.errno != OsConstants.EBADF && e.errno != OsConstants.ENOTCONN) throw e.rethrowAsSocketException()
}
}
scope.launch { closeChannel.receive() }
}
}
@@ -0,0 +1,64 @@
package com.sail_tunnel.sail.services
import android.net.LocalSocket
import android.os.Build
import androidx.annotation.RequiresApi
import com.sail_tunnel.sail.Core
import com.sail_tunnel.sail.net.ConcurrentLocalSocketListener
import com.sail_tunnel.sail.net.DnsResolverCompat
import com.sail_tunnel.sail.utils.readableMessage
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.TimeoutCancellationException
import kotlinx.coroutines.launch
import timber.log.Timber
import java.io.DataInputStream
import java.io.DataOutputStream
import java.io.File
import java.io.IOException
import org.xbill.DNS.Message
import org.xbill.DNS.Rcode
class LocalDnsWorker(private val resolver: suspend (ByteArray) -> ByteArray) : ConcurrentLocalSocketListener(
"LocalDnsThread", File(Core.deviceStorage.noBackupFilesDir, "local_dns_path")
), CoroutineScope {
override fun acceptInternal(socket: LocalSocket) = error("big no no")
override fun accept(socket: LocalSocket) {
launch {
socket.use {
val input = DataInputStream(socket.inputStream)
val query = try {
ByteArray(input.readUnsignedShort()).also { input.read(it) }
} catch (e: IOException) { // connection early close possibly due to resolving timeout
return@use Timber.d(e)
}
try {
resolver(query)
} catch (e: Exception) {
when (e) {
is TimeoutCancellationException -> Timber.w("Resolving timed out")
is CancellationException -> { } // ignore
is IOException -> Timber.d(e)
is UnsupportedOperationException -> Timber.w(e.message)
else -> Timber.w(e)
}
try {
DnsResolverCompat.prepareDnsResponse(Message(query)).apply {
header.rcode = Rcode.SERVFAIL
}.toWire()
} catch (_: IOException) {
byteArrayOf() // return empty if cannot parse packet
}
}.let { response ->
try {
val output = DataOutputStream(socket.outputStream)
output.writeShort(response.size)
output.write(response)
} catch (e: IOException) {
Timber.d(e.readableMessage)
}
}
}
}
}
}
@@ -0,0 +1,89 @@
package com.sail_tunnel.sail.services
import android.net.LocalSocket
import android.os.SystemClock
import com.sail_tunnel.sail.net.LocalSocketListener
import com.sail_tunnel.sail.utils.TrafficStats
import java.io.File
import java.io.IOException
import java.nio.ByteBuffer
import java.nio.ByteOrder
class TrafficMonitor(statFile: File) {
val thread = object : LocalSocketListener("TrafficMonitor-" + statFile.name, statFile) {
private val buffer = ByteArray(16)
private val stat = ByteBuffer.wrap(buffer).order(ByteOrder.LITTLE_ENDIAN)
override fun acceptInternal(socket: LocalSocket) {
when (val read = socket.inputStream.read(buffer)) {
-1 -> return
16 -> { }
else -> throw IOException("Unexpected traffic stat length $read")
}
val tx = stat.getLong(0)
val rx = stat.getLong(8)
if (current.txTotal != tx) {
current.txTotal = tx
dirty = true
}
if (current.rxTotal != rx) {
current.rxTotal = rx
dirty = true
}
}
}.apply { start() }
val current = TrafficStats()
var out = TrafficStats()
private var timestampLast = 0L
private var dirty = false
private var persisted: TrafficStats? = null
fun requestUpdate(): Pair<TrafficStats, Boolean> {
val now = SystemClock.elapsedRealtime()
val delta = now - timestampLast
timestampLast = now
var updated = false
if (delta != 0L) {
if (dirty) {
out = current.copy().apply {
txRate = (txTotal - out.txTotal) * 1024 / delta
rxRate = (rxTotal - out.rxTotal) * 1024 / delta
}
dirty = false
updated = true
} else {
if (out.txRate != 0L) {
out.txRate = 0
updated = true
}
if (out.rxRate != 0L) {
out.rxRate = 0
updated = true
}
}
}
return Pair(out, updated)
}
fun persistStats() {
val current = current
check(persisted == null || persisted == current) { "Data loss occurred" }
persisted = current
// try {
// // profile may have host, etc. modified and thus a re-fetch is necessary (possible race condition)
// val profile = ProfileManager.getProfile(id) ?: return
// profile.tx += current.txTotal
// profile.rx += current.rxTotal
// ProfileManager.updateProfile(profile)
// } catch (e: IOException) {
// if (!DataStore.directBootAware) throw e // we should only reach here because we're in direct boot
// val profile = DirectBoot.getDeviceProfile()!!.toList().single { it.id == id }
// profile.tx += current.txTotal
// profile.rx += current.rxTotal
// profile.dirty = true
// DirectBoot.update(profile)
// DirectBoot.listenForUnlock()
// }
}
}
@@ -0,0 +1,106 @@
package com.sail_tunnel.sail.services
import android.net.LocalServerSocket
import android.net.LocalSocket
import android.net.LocalSocketAddress
import android.system.Os
import com.sail_tunnel.sail.Core
import com.sail_tunnel.sail.TunnelService
import kotlinx.coroutines.CoroutineScope
import timber.log.Timber
import java.io.File
import java.nio.ByteBuffer
import kotlin.concurrent.thread
class TunnelInstance() {
private var configFile: File? = null
var trafficMonitor: TrafficMonitor? = null
private val rtId: Int = 666
init {
System.loadLibrary("leaf")
}
private external fun leafRun(rtId: Int, configPath: String)
private external fun leafReload(rtId: Int)
private external fun leafShutdown(rtId: Int)
private external fun leafTestConfig(configPath: String)
/**
* Sensitive shadowsocks configuration file requires extra protection. It may be stored in encrypted storage or
* device storage, depending on which is currently available.
*/
fun start(
service: TunnelService,
stat: File,
configFile: File,
) {
// setup traffic monitor path
trafficMonitor = TrafficMonitor(stat)
Timber.i("start process")
val context = Core.deviceStorage
val configRoot = context.noBackupFilesDir //noBackupFilesDir
val protectPath =
File.createTempFile("socket_protect", ".sock", configRoot).absolutePath
Os.setenv("SOCKET_PROTECT_PATH", protectPath, true)
println("protectPath: $protectPath")
thread (start = true) {
val localSocket = LocalSocket()
localSocket.bind(
LocalSocketAddress(
protectPath,
LocalSocketAddress.Namespace.FILESYSTEM
)
)
val socket = LocalServerSocket(localSocket.fileDescriptor)
val buffer = ByteBuffer.allocate(4)
while (true) {
val stream = socket.accept()
buffer.clear()
val n = stream.inputStream.read(buffer.array())
System.out.write(n)
if (n == 4) {
val fd = buffer.int
if (!service.protect(fd)) {
println("protect failed")
}
buffer.clear()
buffer.putInt(0)
} else {
buffer.clear()
buffer.putInt(1)
}
stream.outputStream.write(buffer.array())
}
}
// start tunnel program
thread(start = true) {
leafRun(rtId, configFile.absolutePath)
}
}
fun shutdown(scope: CoroutineScope) {
trafficMonitor?.apply {
thread.shutdown(scope)
persistStats() // Make sure update total traffic when stopping the runner
}
trafficMonitor = null
configFile?.delete() // remove old config possibly in device storage
configFile = null
// stop tunnel program
thread(start = true, isDaemon = true) {
leafShutdown(rtId)
}
}
}
@@ -0,0 +1,32 @@
package com.sail_tunnel.sail.services
import kotlinx.coroutines.Job
object VpnState {
enum class State {
/**
* Idle state is only used by UI and will never be returned by BaseService.
*/
Idle,
Connecting,
Connected,
Stopping,
Stopped,
}
const val CONFIG_FILE = "leaf.conf"
const val LEAF_LOG_FILE = "leaf.log"
class Data internal constructor() {
var state = State.Stopped
var proxy: TunnelInstance? = null
var localDns: LocalDnsWorker? = null
var connectingJob: Job? = null
fun changeState(s: State, msg: String? = null) {
if (state == s && msg == null) return
state = s
}
}
}
@@ -0,0 +1,18 @@
package com.sail_tunnel.sail.utils
import android.annotation.SuppressLint
import android.app.Application
import android.content.Context
@SuppressLint("Registered")
class DeviceStorageApp(context: Context) : Application() {
init {
attachBaseContext(context.createDeviceProtectedStorageContext())
}
/**
* Thou shalt not get the REAL underlying application context which would no longer be operating under device
* protected storage.
*/
override fun getApplicationContext() = this
}
@@ -0,0 +1,20 @@
package com.sail_tunnel.sail.utils
import android.os.Parcelable
import kotlinx.parcelize.Parcelize
@Parcelize
data class TrafficStats(
// Bytes per second
var txRate: Long = 0L,
var rxRate: Long = 0L,
// Bytes for the current session
var txTotal: Long = 0L,
var rxTotal: Long = 0L
) : Parcelable {
operator fun plus(other: TrafficStats) = TrafficStats(
txRate + other.txRate, rxRate + other.rxRate,
txTotal + other.txTotal, rxTotal + other.rxTotal
)
}
@@ -0,0 +1,33 @@
package com.sail_tunnel.sail.utils
import android.annotation.SuppressLint
import android.os.Build
import kotlinx.coroutines.*
import java.io.FileDescriptor
import java.net.HttpURLConnection
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
val Throwable.readableMessage: String get() = localizedMessage ?: javaClass.name
/**
* https://android.googlesource.com/platform/prebuilts/runtime/+/94fec32/appcompat/hiddenapi-light-greylist.txt#9466
*/
@SuppressLint("DiscouragedPrivateApi")
private val getInt = FileDescriptor::class.java.getDeclaredMethod("getInt$")
val FileDescriptor.int get() = getInt.invoke(this) as Int
suspend fun <T> HttpURLConnection.useCancellable(block: suspend HttpURLConnection.() -> T): T {
return suspendCancellableCoroutine { cont ->
cont.invokeOnCancellation {
if (Build.VERSION.SDK_INT >= 26) disconnect() else GlobalScope.launch(Dispatchers.IO) { disconnect() }
}
GlobalScope.launch(Dispatchers.IO) {
try {
cont.resume(block())
} catch (e: Throwable) {
cont.resumeWithException(e)
}
}
}
}
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="?android:colorBackground" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@android:color/white" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>
Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>
@@ -0,0 +1,10 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.sail_tunnel.sail">
<!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
</manifest>
+31
View File
@@ -0,0 +1,31 @@
buildscript {
ext.kotlin_version = '1.6.10'
repositories {
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.1.3'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
allprojects {
repositories {
google()
mavenCentral()
}
}
rootProject.buildDir = '../build'
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
project.evaluationDependsOn(':app')
}
tasks.register("clean", Delete) {
delete rootProject.buildDir
}
+4
View File
@@ -0,0 +1,4 @@
org.gradle.jvmargs=-Xmx1536M
android.useAndroidX=true
android.enableJetifier=true
android.suppressUnsupportedCompileSdk=33
@@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip
+11
View File
@@ -0,0 +1,11 @@
include ':app'
def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
def properties = new Properties()
assert localPropertiesFile.exists()
localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
+10
View File
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<svg viewBox="0 0 36 17.2" xmlns="http://www.w3.org/2000/svg">
<linearGradient id="a" gradientUnits="userSpaceOnUse" x1="-15.5" x2="59.992" y1="10" y2="75.024" gradientTransform="matrix(1.056419, 0, 0, 1, -59.971069, -0.317375)">
<stop offset="0" stop-color="#62c"/>
<stop offset="1" stop-color="#301060"/>
</linearGradient>
<g fill="url(#a)" transform="matrix(1, 0, 0, 1, -1.853645, -1.351658)">
<path d="M 27.827 3.42 C 27.585 3.297 27.307 3.264 27.043 3.327 C 26.77 3.396 26.527 3.551 26.349 3.771 L 24.595 5.858 L 21.485 2.156 C 21.231 1.853 20.885 1.683 20.526 1.683 C 20.166 1.683 19.821 1.853 19.567 2.156 L 16.457 5.858 L 14.703 3.771 C 14.526 3.552 14.282 3.397 14.009 3.329 C 13.745 3.266 13.468 3.299 13.225 3.421 C 12.977 3.543 12.765 3.75 12.616 4.015 C 12.465 4.289 12.387 4.598 12.388 4.912 L 12.388 13.459 C 12.388 14.529 12.746 15.555 13.382 16.312 C 14.018 17.069 14.88 17.494 15.779 17.496 L 25.273 17.496 C 26.173 17.494 27.034 17.069 27.67 16.312 C 28.306 15.555 28.663 14.529 28.664 13.459 L 28.664 4.912 C 28.664 4.592 28.585 4.281 28.436 4.015 C 28.298 3.759 28.086 3.552 27.827 3.42 L 27.827 3.42 Z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

+3
View File
@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="22" fill="none" viewBox="0 0 20 22">
<path fill="#AE77FF" d="M16.64 9.39a2.112 2.112 0 00-1.925 1.25h-.97L12.69 7.478a.859.859 0 00-1.64.035l-1.454 5.086L7.721 1.593a.86.86 0 00-1.68-.067L3.704 10.64H1.25v1.718h3.125a.86.86 0 00.834-.65l1.498-5.99 1.82 10.688a.86.86 0 00.8.718h.048a.86.86 0 00.826-.625l1.737-5.845.372 1.118a.859.859 0 00.815.586h1.59a2.11 2.11 0 101.926-2.968z"/>
</svg>

After

Width:  |  Height:  |  Size: 451 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 900 600"><path fill="#EE1C25" d="M0 0h900v600H0z"/><g id="a"><path d="M449.964 299.913c-105.263-44.486-58.602-181.581 42.07-174.69-20.366 10.467-23.318 29.997-11.687 48.09 13.024 20.256-1.2 52.848-18.806 60.767-28.935 13.025-34.728 47.75-11.577 65.833z" fill="#fff"/><path d="M444.272 200.92l-5.92 9.294-2.144-10.815-10.679-2.759 9.625-5.39-.671-10.999 8.085 7.49 10.256-4.043-4.61 10.01 7.001 8.505zm6.288 97.839c-12.731-6.534-22.996-20.155-27.468-36.431-5.115-18.67-2.173-38.743 8.083-55.038l-2.208-1.394c-10.64 16.929-13.693 37.743-8.386 57.12 4.728 17.221 15.214 31.097 28.787 38.064z" fill="#EE1C25"/></g><use xlink:href="#a" transform="rotate(72 450 300)"/><use xlink:href="#a" transform="rotate(144 450 300)"/><use xlink:href="#a" transform="rotate(216 450 300)"/><use xlink:href="#a" transform="rotate(288 450 300)"/></svg>

After

Width:  |  Height:  |  Size: 927 B

+1
View File
@@ -0,0 +1 @@
<svg viewBox="0 0 900 600" xmlns="http://www.w3.org/2000/svg"><path d="m0 0h900v600h-900z" fill="#fff"/><circle cx="450" cy="300" fill="#bc002d" r="180"/></svg>

After

Width:  |  Height:  |  Size: 160 B

+1
View File
@@ -0,0 +1 @@
<svg viewBox="0 0 900 600" xmlns="http://www.w3.org/2000/svg"><g fill-rule="evenodd"><path d="m0 0h900v600h-900z" fill="#fe0000"/><path d="m0 0h450v300h-450z" fill="#000095"/></g><g fill="#fff"><path d="m225 37.5-56.25 209.928 153.678-153.678-209.928 56.25 209.928 56.25-153.678-153.678 56.25 209.928 56.25-209.928-153.678 153.678 209.928-56.25-209.928-56.25 153.678 153.678z"/><circle cx="225" cy="150" r="60" stroke="#000095" stroke-width="7.5"/></g></svg>

After

Width:  |  Height:  |  Size: 458 B

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 7410 3900"><path fill="#b22234" d="M0 0h7410v3900H0z"/><path d="M0 450h7410m0 600H0m0 600h7410m0 600H0m0 600h7410m0 600H0" stroke="#fff" stroke-width="300"/><path fill="#3c3b6e" d="M0 0h2964v2100H0z"/><g fill="#fff"><g id="d"><g id="c"><g id="e"><g id="b"><path id="a" d="M247 90l70.534 217.082-184.66-134.164h228.253L176.466 307.082z"/><use xlink:href="#a" y="420"/><use xlink:href="#a" y="840"/><use xlink:href="#a" y="1260"/></g><use xlink:href="#a" y="1680"/></g><use xlink:href="#b" x="247" y="210"/></g><use xlink:href="#c" x="494"/></g><use xlink:href="#d" x="988"/><use xlink:href="#c" x="1976"/><use xlink:href="#e" x="2470"/></g></svg>

After

Width:  |  Height:  |  Size: 741 B

Binary file not shown.
+1
View File
@@ -0,0 +1 @@
<svg fill="none" height="20" viewBox="0 0 20 20" width="20" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><clipPath id="a"><path d="m0 0h20v20h-20z"/></clipPath><g clip-path="url(#a)" fill="#ae77ff"><path d="m10 5a.833.833 0 0 0 -.833.833v4.167c0 .221.088.433.244.59l2.5 2.5a.833.833 0 0 0 1.178-1.18l-2.256-2.255v-3.822a.833.833 0 0 0 -.833-.833z"/><path d="m19.844 8.443a10 10 0 0 0 -16.862-5.597v-2.013a.833.833 0 0 0 -1.667 0v3.334a1.667 1.667 0 0 0 1.667 1.666h3.333a.833.833 0 1 0 0-1.666h-2.292a8.325 8.325 0 1 1 -2.363 6.565.818.818 0 0 0 -.826-.732.839.839 0 0 0 -.834.917 10 10 0 1 0 19.84-2.474z"/></g></svg>

After

Width:  |  Height:  |  Size: 651 B

+4
View File
@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" fill="none" viewBox="0 0 22 22">
<path fill="#B5AEBE" d="M21.484 9.6l-7.79-8.422a3.667 3.667 0 00-5.385 0L.533 9.597A1.833 1.833 0 000 10.889v8.347a2.75 2.75 0 002.75 2.75h3.667v-5.5a4.57 4.57 0 012.409-4.01l.139-.075a4.55 4.55 0 01.528-.223c.124-.045.25-.084.379-.117.129-.034.285-.065.431-.092.081-.013.156-.04.239-.049a4.53 4.53 0 01.417-.017c.014 0 .027-.005.041-.005h.017c.283.002.566.031.845.086.03.006.062.009.091.015.262.057.517.137.765.239.035.013.07.026.104.042.237.102.465.225.68.366l.102.068c.21.146.407.309.59.487l.085.086c.179.184.343.382.49.592l.062.092c.144.219.27.45.375.69l.034.092c.104.253.186.515.243.784 0 .02.007.04.01.061.06.292.09.59.09.888v5.5h3.667a2.75 2.75 0 002.75-2.75v-8.36c0-.477-.185-.934-.516-1.277z"/>
<path fill="#B5AEBE" d="M11 13.736a2.75 2.75 0 00-2.75 2.75v5.5h5.5v-5.5a2.75 2.75 0 00-2.75-2.75z"/>
</svg>

After

Width:  |  Height:  |  Size: 913 B

+3
View File
@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="17" height="15" fill="none" viewBox="0 0 17 15">
<path fill="#AE77FF" d="M3.727 15H.309V.781h3.418V15zm1.982 0V.781h4.58c1.257 0 2.386.287 3.39.86a5.934 5.934 0 012.343 2.412c.566 1.035.853 2.197.86 3.486v.654c0 1.302-.277 2.471-.83 3.506a6.03 6.03 0 01-2.325 2.422c-.996.58-2.11.872-3.34.879H5.71zM9.137 3.428v8.935h1.191c.984 0 1.739-.348 2.266-1.045.527-.703.791-1.744.791-3.125v-.615c0-1.374-.264-2.409-.79-3.105-.528-.697-1.296-1.045-2.306-1.045H9.138z"/>
</svg>

After

Width:  |  Height:  |  Size: 517 B

+1
View File
@@ -0,0 +1 @@
<svg fill="none" height="56" viewBox="0 0 56 56" width="56" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientUnits="userSpaceOnUse" x1="-4.2" x2="36.4" y1="-22.4" y2="99.4"><stop offset="0" stop-color="#62c"/><stop offset="1" stop-color="#0b0415"/></linearGradient><path clip-rule="evenodd" d="m50.423 5.823a3.865 3.865 0 0 1 2.698.329c.852.433 1.58 1.166 2.093 2.107a6.67 6.67 0 0 1 .786 3.177v30.268c-.004 3.79-1.234 7.424-3.421 10.104s-5.153 4.188-8.246 4.192h-32.666c-3.093-.005-6.059-1.512-8.246-4.192s-3.417-6.314-3.421-10.104v-30.268c0-1.131.274-2.236.787-3.177.513-.939 1.241-1.673 2.093-2.105a3.876 3.876 0 0 1 2.696-.326c.905.22 1.736.765 2.389 1.565l6.035 7.394 10.7-13.113c.877-1.072 2.064-1.674 3.3-1.674 1.237 0 2.424.602 3.3 1.674l10.7 13.113 6.034-7.394c.652-.802 1.483-1.349 2.39-1.57zm-22.42 15.18c5.95.07 10.86 4.515 11.684 10.285.072.538.107 1.111.107 1.685 0 .573-.035 1.183-.107 1.756-.789 5.268-5.018 9.426-10.358 10.071h-10.967v-18.637h3.44v15.232h7.276c3.548-.537 6.38-3.225 7.097-6.666a7.363 7.363 0 0 0 .215-1.756c0-.574-.072-1.147-.18-1.685a8.589 8.589 0 0 0 -3.225-5.125c-1.326-1.003-2.975-1.613-4.767-1.72h-9.856v-3.44h9.64z" fill="url(#a)" fill-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

+11
View File
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<svg viewBox="0 0 16.3 15.8" xmlns="http://www.w3.org/2000/svg">
<linearGradient id="a" gradientUnits="userSpaceOnUse" x1="-15.5" x2="59.992" y1="10" y2="75.024" gradientTransform="matrix(1.056419, 0, 0, 1, -60.033002, -0.422793)">
<stop offset="0" stop-color="#62c"/>
<stop offset="1" stop-color="#301060"/>
</linearGradient>
<g fill="url(#a)" transform="matrix(1, 0, 0, 1, -12.325989, -1.578)">
<path d="M 27.765 3.315 C 27.523 3.192 20.823 1.578 20.464 1.578 C 20.104 1.578 13.406 3.194 13.163 3.316 C 12.915 3.438 12.703 3.645 12.554 3.91 C 12.403 4.184 12.325 4.493 12.326 4.807 L 12.326 13.354 C 12.326 14.424 12.684 15.45 13.32 16.207 C 13.956 16.964 14.818 17.389 15.717 17.391 L 25.211 17.391 C 26.111 17.389 26.972 16.964 27.608 16.207 C 28.244 15.45 28.601 14.424 28.602 13.354 L 28.602 4.807 C 28.602 4.487 28.523 4.176 28.374 3.91 C 28.236 3.654 28.024 3.447 27.765 3.315 Z"/>
</g>
<path d="M 12.276 0.128 L 12.956 0.128 L 12.956 7.651 L 12.218 7.651 L 8.427 1.317 L 8.427 7.651 L 7.712 7.651 L 7.712 0.128 L 8.509 0.128 L 12.276 6.368 Z" transform="matrix(1.86918, 0, 0, 0.767696, -11.240033, 5.053573)" style="fill: rgb(27, 27, 27); paint-order: fill; white-space: pre;"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 179 KiB

+1
View File
@@ -0,0 +1 @@
<svg fill="none" height="48" viewBox="0 0 46 48" width="46" xmlns="http://www.w3.org/2000/svg"><g fill="#ae77ff"><path d="m13.01 7.857c-.613-1.062-1.979-1.435-2.974-.719a22.2 22.2 0 1 0 25.928 0c-.995-.716-2.361-.343-2.974.719s-.239 2.409.738 3.15a17.76 17.76 0 1 1 -21.456 0c.977-.741 1.351-2.088.738-3.15z"/><rect height="14.8" rx="2.22" width="4.44" x="20.78"/></g></svg>

After

Width:  |  Height:  |  Size: 374 B

+3
View File
@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="24" fill="none" viewBox="0 0 22 24">
<path fill="#B5AEBE" stroke="#B5AEBE" stroke-width="2" d="M1 13.75c0-1.514 1.165-2.771 2.671-2.918l.586.697c3.51 4.178 9.976 4.178 13.486 0l.586-.697C19.835 10.978 21 12.236 21 13.75v3.16c0 3.355-2.746 6.09-6.15 6.09h-7.7C3.746 23 1 20.265 1 16.91v-3.16zm14.5-8.295c0 2.452-2.007 4.454-4.5 4.454S6.5 7.907 6.5 5.455C6.5 3.002 8.507 1 11 1s4.5 2.002 4.5 4.455z"/>
</svg>

After

Width:  |  Height:  |  Size: 468 B

+4
View File
@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" width="21" height="21" fill="none" viewBox="0 0 21 21">
<path fill="#AE77FF" d="M18.406 10.58v-1.1l1.38-1.207a1.438 1.438 0 00.273-1.833l-1.696-2.875a1.438 1.438 0 00-1.243-.718 1.438 1.438 0 00-.46.071l-1.747.59c-.301-.2-.616-.38-.941-.54l-.367-1.81A1.437 1.437 0 0012.167 0H8.805a1.437 1.437 0 00-1.438 1.157L7 2.97a8.252 8.252 0 00-.949.539l-1.71-.618a1.438 1.438 0 00-.46-.043 1.438 1.438 0 00-1.244.718L.94 6.44a1.438 1.438 0 00.294 1.804l1.359 1.244v1.1l-1.359 1.207a1.437 1.437 0 00-.294 1.833l1.696 2.875a1.438 1.438 0 001.243.718c.157.002.312-.023.46-.071l1.747-.59c.301.2.616.38.941.54l.367 1.81a1.438 1.438 0 001.438 1.158h3.392a1.438 1.438 0 001.438-1.157l.366-1.812c.328-.158.645-.338.949-.539l1.74.59c.148.048.303.073.46.072a1.437 1.437 0 001.243-.72l1.638-2.874a1.437 1.437 0 00-.294-1.804l-1.359-1.244zm-1.286 5.204l-2.466-.834a6.369 6.369 0 01-1.947 1.129l-.51 2.58H8.803l-.51-2.551a6.73 6.73 0 01-1.941-1.129l-2.473.805-1.696-2.875 1.955-1.725a6.397 6.397 0 010-2.25L2.184 7.16 3.88 4.284l2.466.834a6.368 6.368 0 011.947-1.129l.51-2.58h3.393l.51 2.552a6.727 6.727 0 011.941 1.128l2.473-.805 1.696 2.875-1.955 1.725a6.397 6.397 0 010 2.25l1.955 1.775-1.696 2.875z"/>
<path fill="#AE77FF" d="M10.5 14.347a4.312 4.312 0 114.313-4.313 4.268 4.268 0 01-4.313 4.313zm0-7.188a2.81 2.81 0 00-2.875 2.875 2.81 2.81 0 002.875 2.875 2.808 2.808 0 002.875-2.875A2.809 2.809 0 0010.5 7.159z"/>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

+14
View File
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<svg viewBox="0 0 82 18" xmlns="http://www.w3.org/2000/svg">
<g transform="matrix(0.012366, 0, 0, -0.010371, -37.907673, 26.353985)" id="g10" style="">
<g transform="scale(0.1)" id="g12">
<g transform="matrix(1.4411, 0, 0, 1.4411, 32303.105469, 1475.181641)" id="g2248">
<path id="path2250" style="fill-opacity: 1; fill-rule: nonzero; stroke: none;" d="m 13914.7,14060.9 v -3973.1 c 0,-568.29 -21.3,-974.93 -63.7,-1219.88 -42.4,-244.95 -168.2,-451.6 -377.2,-619.73 -209,-168.28 -519.3,-252.31 -930.8,-252.31 -405,0 -724.3,88.96 -957.8,267.02 -233.6,177.99 -381.4,413.99 -443.4,707.93 -1.8,9.44 -3.6,19.64 -5.4,30.19 -32.3,194.78 -48.4,584.68 -48.4,1170.08 v 1354.4 l 91.6,255 552.6,1539.1 264.4,736.5 132.2,368.2 c 22.2,61.3 43.7,122.9 66.8,183.8 23.4,60.9 47.6,121.5 66.5,184 l 111,375.8 c 36.3,125.6 73.3,250.8 109,376.6 72.2,251.2 143.2,502.8 211.2,755.5 -108.4,-238.2 -213.6,-477.6 -317.7,-717.3 -52.4,-119.7 -103.6,-239.9 -155.4,-359.9 l -153.5,-360.6 c -25.1,-60.2 -45,-122.3 -65.8,-184.2 -20.8,-61.8 -43.5,-122.9 -65.3,-184.3 l -132.2,-368.2 -264.5,-736.5 -359.3,-1000.9 -91.6,-255 -606.7,-1689.7 L 9768.62,8458.65 9423.54,7497.72 9177.2,6811.58 8894.71,6024.89 8784.1,5648.93 c -36.43,-125.46 -73.28,-250.78 -109.16,-376.44 -36.22,-125.6 -71.95,-251.34 -107.55,-377.08 l -52.74,-188.95 -26.3,-94.44 -25.88,-94.65 40.31,89.44 39.77,89.66 79.45,179.3 c 52.6,119.7 104.99,239.4 156.89,359.31 52.26,119.84 103.53,239.96 155.3,359.93 l 153.77,360.49 323.85,901.88 204.98,570.95 252.66,703.56 c 74.73,-178.89 180.45,-352.44 317.05,-520.57 72.2,-88.83 153.6,-171.82 244.1,-248.98 167.5,-142.74 366.1,-265.49 596.2,-368.33 354.3,-158.35 874.4,-237.59 1560.3,-237.59 568.2,0 1028.8,72.72 1381.5,218.02 352.7,145.31 634.4,340.51 845.1,585.46 210.7,244.95 355.2,545.34 433.6,901.39 78.4,355.98 117.6,965.09 117.6,1827.31 v 3772.3 h -1450.2"/>
</g>
<g transform="scale(1.4411)" id="g2252">
<path id="path2254" style="fill-opacity: 1; fill-rule: nonzero; stroke: none;" d="M 31195.072 9019.019 L 32037.612 11365.629 L 32077.242 11475.929 L 32168.832 11730.929 L 33095.322 14311.229 L 33359.722 15047.729 L 33361.522 15052.529 L 33492.022 15415.929 C 33514.122 15477.229 33535.522 15538.829 33558.822 15599.729 C 33582.122 15660.629 33606.322 15721.229 33625.222 15783.729 L 33736.222 16159.529 C 33772.422 16285.129 33809.422 16410.329 33845.222 16536.129 C 33917.322 16787.329 33988.422 17038.929 34056.322 17291.629 C 33948.122 17053.429 33842.822 16814.029 33738.722 16574.329 C 33686.322 16454.629 33635.122 16334.429 33583.322 16214.429 L 33429.822 15853.829 C 33404.722 15793.629 33384.822 15731.529 33364.022 15669.629 C 33343.222 15607.829 33320.622 15546.729 33298.622 15485.329 L 33166.522 15117.129 L 33143.322 15052.529 L 32168.832 15052.529 L 32077.242 15052.529 L 32077.242 12083.629 L 31844.362 11435.029 L 30967.392 8992.719 C 30912.712 8989.319 30855.952 8987.509 30797.042 8987.509 C 30392.072 8987.509 30072.802 9076.469 29839.302 9254.529 C 29605.732 9432.519 29457.932 9668.519 29395.892 9962.459 C 29359.962 10145.309 29342.062 10545.409 29342.062 11162.729 L 29342.062 15052.529 L 27891.932 15052.529 L 27891.932 11221.529 C 27891.932 10418.009 27939.242 9810.559 28033.982 9399.069 C 28099.292 9121.369 28234.852 8856.019 28440.622 8602.949 C 28646.382 8349.809 28926.402 8144.059 29280.822 7985.639 C 29578.112 7852.759 29992.102 7775.659 30522.742 7754.219 L 30257.802 7016.519 L 30147.192 6640.559 C 30110.762 6515.099 30073.912 6389.779 30038.042 6264.119 C 30001.812 6138.519 29966.082 6012.779 29930.482 5887.039 L 29877.812 5698.089 L 29851.442 5603.649 L 29825.632 5508.999 L 29865.882 5598.439 L 29905.642 5688.099 L 29985.162 5867.399 C 30037.692 5987.099 30090.152 6106.799 30142.062 6226.709 C 30194.312 6346.549 30245.592 6466.669 30297.282 6586.639 L 30451.052 6947.129 L 30738.892 7748.739 L 30979.952 8419.959 L 31195.072 9019.019"/>
</g>
</g>
</g>
<path d="M 38.475 12.15 L 41.667 3.315 L 44.898 3.315 L 39.995 15.063 L 36.966 15.063 L 32.081 3.314 L 35.302 3.314 L 38.474 12.15 L 38.475 12.15 Z M 48.738 10.923 L 48.738 15.063 L 45.837 15.063 L 45.837 3.314 L 51.332 3.314 C 52.389 3.314 53.317 3.476 54.118 3.799 C 54.923 4.121 55.542 4.581 55.974 5.179 C 56.406 5.77 56.622 6.446 56.622 7.203 C 56.622 8.355 56.148 9.264 55.201 9.931 C 54.26 10.592 52.953 10.923 51.282 10.923 L 48.738 10.923 Z M 48.738 8.963 L 51.332 8.963 C 52.099 8.963 52.683 8.812 53.082 8.511 C 53.488 8.21 53.692 7.78 53.692 7.22 C 53.692 6.644 53.488 6.179 53.082 5.824 C 52.677 5.469 52.115 5.286 51.399 5.275 L 48.738 5.275 L 48.738 8.963 Z M 69.682 15.063 L 66.779 15.063 L 61.13 7.333 L 61.13 15.063 L 58.23 15.063 L 58.23 3.314 L 61.13 3.314 L 66.789 11.06 L 66.789 3.315 L 69.682 3.315 L 69.682 15.063 Z" fill="#000" style=""/>
</svg>

After

Width:  |  Height:  |  Size: 4.7 KiB

+1
View File
@@ -0,0 +1 @@
*.a filter=lfs diff=lfs merge=lfs -text
+33
View File
@@ -0,0 +1,33 @@
*.mode1v3
*.mode2v3
*.moved-aside
*.pbxuser
*.perspectivev3
**/*sync/
.sconsign.dblite
.tags*
**/.vagrant/
**/DerivedData/
Icon?
**/Pods/
**/.symlinks/
profile
xcuserdata
**/.generated/
**/build/
Flutter/App.framework
Flutter/Flutter.framework
Flutter/Flutter.podspec
Flutter/Generated.xcconfig
Flutter/app.flx
Flutter/app.zip
Flutter/flutter_assets/
Flutter/flutter_export_environment.sh
ServiceDefinitions.json
Runner/GeneratedPluginRegistrant.*
# Exceptions to above rules.
!default.mode1v3
!default.mode2v3
!default.pbxuser
!default.perspectivev3
Binary file not shown.
@@ -0,0 +1,24 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_HEADERS_FLUTTER_H_
#define FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_HEADERS_FLUTTER_H_
#import "FlutterAppDelegate.h"
#import "FlutterBinaryMessenger.h"
#import "FlutterCallbackCache.h"
#import "FlutterChannels.h"
#import "FlutterCodecs.h"
#import "FlutterDartProject.h"
#import "FlutterEngine.h"
#import "FlutterEngineGroup.h"
#import "FlutterHeadlessDartRunner.h"
#import "FlutterMacros.h"
#import "FlutterPlatformViews.h"
#import "FlutterPlugin.h"
#import "FlutterPluginAppLifeCycleDelegate.h"
#import "FlutterTexture.h"
#import "FlutterViewController.h"
#endif // FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_HEADERS_FLUTTER_H_
@@ -0,0 +1,34 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_HEADERS_FLUTTERAPPDELEGATE_H_
#define FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_HEADERS_FLUTTERAPPDELEGATE_H_
#import <UIKit/UIKit.h>
#import "FlutterMacros.h"
#import "FlutterPlugin.h"
/**
* `UIApplicationDelegate` subclass for simple apps that want default behavior.
*
* This class implements the following behaviors:
* * Status bar touches are forwarded to the key window's root view
* `FlutterViewController`, in order to trigger scroll to top.
* * Keeps the Flutter connection open in debug mode when the phone screen
* locks.
*
* App delegates for Flutter applications are *not* required to inherit from
* this class. Developers of custom app delegate classes should copy and paste
* code as necessary from FlutterAppDelegate.mm.
*/
FLUTTER_DARWIN_EXPORT
@interface FlutterAppDelegate
: UIResponder <UIApplicationDelegate, FlutterPluginRegistry, FlutterAppLifeCycleProvider>
@property(strong, nonatomic) UIWindow* window;
@end
#endif // FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_HEADERS_FLUTTERAPPDELEGATE_H_
@@ -0,0 +1,106 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_SHELL_PLATFORM_DARWIN_COMMON_FRAMEWORK_HEADERS_FLUTTERBINARYMESSENGER_H_
#define FLUTTER_SHELL_PLATFORM_DARWIN_COMMON_FRAMEWORK_HEADERS_FLUTTERBINARYMESSENGER_H_
#import <Foundation/Foundation.h>
#import "FlutterMacros.h"
NS_ASSUME_NONNULL_BEGIN
/**
* A message reply callback.
*
* Used for submitting a binary reply back to a Flutter message sender. Also used
* in for handling a binary message reply received from Flutter.
*
* @param reply The reply.
*/
typedef void (^FlutterBinaryReply)(NSData* _Nullable reply);
/**
* A strategy for handling incoming binary messages from Flutter and to send
* asynchronous replies back to Flutter.
*
* @param message The message.
* @param reply A callback for submitting an asynchronous reply to the sender.
*/
typedef void (^FlutterBinaryMessageHandler)(NSData* _Nullable message, FlutterBinaryReply reply);
typedef int64_t FlutterBinaryMessengerConnection;
@protocol FlutterTaskQueue <NSObject>
@end
/**
* A facility for communicating with the Flutter side using asynchronous message
* passing with binary messages.
*
* Implementated by:
* - `FlutterBasicMessageChannel`, which supports communication using structured
* messages.
* - `FlutterMethodChannel`, which supports communication using asynchronous
* method calls.
* - `FlutterEventChannel`, which supports commuication using event streams.
*/
FLUTTER_DARWIN_EXPORT
@protocol FlutterBinaryMessenger <NSObject>
/// TODO(gaaclarke): Remove optional when macos supports Background Platform Channels.
@optional
- (NSObject<FlutterTaskQueue>*)makeBackgroundTaskQueue;
- (FlutterBinaryMessengerConnection)
setMessageHandlerOnChannel:(NSString*)channel
binaryMessageHandler:(FlutterBinaryMessageHandler _Nullable)handler
taskQueue:(NSObject<FlutterTaskQueue>* _Nullable)taskQueue;
@required
/**
* Sends a binary message to the Flutter side on the specified channel, expecting
* no reply.
*
* @param channel The channel name.
* @param message The message.
*/
- (void)sendOnChannel:(NSString*)channel message:(NSData* _Nullable)message;
/**
* Sends a binary message to the Flutter side on the specified channel, expecting
* an asynchronous reply.
*
* @param channel The channel name.
* @param message The message.
* @param callback A callback for receiving a reply.
*/
- (void)sendOnChannel:(NSString*)channel
message:(NSData* _Nullable)message
binaryReply:(FlutterBinaryReply _Nullable)callback;
/**
* Registers a message handler for incoming binary messages from the Flutter side
* on the specified channel.
*
* Replaces any existing handler. Use a `nil` handler for unregistering the
* existing handler.
*
* @param channel The channel name.
* @param handler The message handler.
* @return An identifier that represents the connection that was just created to the channel.
*/
- (FlutterBinaryMessengerConnection)setMessageHandlerOnChannel:(NSString*)channel
binaryMessageHandler:
(FlutterBinaryMessageHandler _Nullable)handler;
/**
* Clears out a channel's message handler if that handler is still the one that
* was created as a result of
* `setMessageHandlerOnChannel:binaryMessageHandler:`.
*
* @param connection The result from `setMessageHandlerOnChannel:binaryMessageHandler:`.
*/
- (void)cleanUpConnection:(FlutterBinaryMessengerConnection)connection;
@end
NS_ASSUME_NONNULL_END
#endif // FLUTTER_SHELL_PLATFORM_DARWIN_COMMON_FRAMEWORK_HEADERS_FLUTTERBINARYMESSENGER_H_
@@ -0,0 +1,54 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_HEADERS_FLUTTERCALLBACKCACHE_H_
#define FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_HEADERS_FLUTTERCALLBACKCACHE_H_
#import <Foundation/Foundation.h>
#import "FlutterMacros.h"
/**
* An object containing the result of `FlutterCallbackCache`'s `lookupCallbackInformation`
* method.
*/
FLUTTER_DARWIN_EXPORT
@interface FlutterCallbackInformation : NSObject
/**
* The name of the callback.
*/
@property(copy) NSString* callbackName;
/**
* The class name of the callback.
*/
@property(copy) NSString* callbackClassName;
/**
* The library path of the callback.
*/
@property(copy) NSString* callbackLibraryPath;
@end
/**
* The cache containing callback information for spawning a
* `FlutterHeadlessDartRunner`.
*/
FLUTTER_DARWIN_EXPORT
@interface FlutterCallbackCache : NSObject
/**
* Returns the callback information for the given callback handle.
* This callback information can be used when spawning a
* `FlutterHeadlessDartRunner`.
*
* @param handle The handle for a callback, provided by the
* Dart method `PluginUtilities.getCallbackHandle`.
* @return A `FlutterCallbackInformation` object which contains the name of the
* callback, the name of the class in which the callback is defined, and the
* path of the library which contains the callback. If the provided handle is
* invalid, nil is returned.
*/
+ (FlutterCallbackInformation*)lookupCallbackInformation:(int64_t)handle;
@end
#endif // FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_HEADERS_FLUTTERCALLBACKCACHE_H_
@@ -0,0 +1,487 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_SHELL_PLATFORM_DARWIN_COMMON_FRAMEWORK_HEADERS_FLUTTERCHANNELS_H_
#define FLUTTER_SHELL_PLATFORM_DARWIN_COMMON_FRAMEWORK_HEADERS_FLUTTERCHANNELS_H_
#import "FlutterBinaryMessenger.h"
#import "FlutterCodecs.h"
NS_ASSUME_NONNULL_BEGIN
/**
* A message reply callback.
*
* Used for submitting a reply back to a Flutter message sender. Also used in
* the dual capacity for handling a message reply received from Flutter.
*
* @param reply The reply.
*/
typedef void (^FlutterReply)(id _Nullable reply);
/**
* A strategy for handling incoming messages from Flutter and to send
* asynchronous replies back to Flutter.
*
* @param message The message.
* @param callback A callback for submitting a reply to the sender which can be invoked from any
* thread.
*/
typedef void (^FlutterMessageHandler)(id _Nullable message, FlutterReply callback);
/**
* A channel for communicating with the Flutter side using basic, asynchronous
* message passing.
*/
FLUTTER_DARWIN_EXPORT
@interface FlutterBasicMessageChannel : NSObject
/**
* Creates a `FlutterBasicMessageChannel` with the specified name and binary
* messenger.
*
* The channel name logically identifies the channel; identically named channels
* interfere with each other's communication.
*
* The binary messenger is a facility for sending raw, binary messages to the
* Flutter side. This protocol is implemented by `FlutterEngine` and `FlutterViewController`.
*
* The channel uses `FlutterStandardMessageCodec` to encode and decode messages.
*
* @param name The channel name.
* @param messenger The binary messenger.
*/
+ (instancetype)messageChannelWithName:(NSString*)name
binaryMessenger:(NSObject<FlutterBinaryMessenger>*)messenger;
/**
* Creates a `FlutterBasicMessageChannel` with the specified name, binary
* messenger, and message codec.
*
* The channel name logically identifies the channel; identically named channels
* interfere with each other's communication.
*
* The binary messenger is a facility for sending raw, binary messages to the
* Flutter side. This protocol is implemented by `FlutterEngine` and `FlutterViewController`.
*
* @param name The channel name.
* @param messenger The binary messenger.
* @param codec The message codec.
*/
+ (instancetype)messageChannelWithName:(NSString*)name
binaryMessenger:(NSObject<FlutterBinaryMessenger>*)messenger
codec:(NSObject<FlutterMessageCodec>*)codec;
/**
* Initializes a `FlutterBasicMessageChannel` with the specified name, binary
* messenger, and message codec.
*
* The channel name logically identifies the channel; identically named channels
* interfere with each other's communication.
*
* The binary messenger is a facility for sending raw, binary messages to the
* Flutter side. This protocol is implemented by `FlutterEngine` and `FlutterViewController`.
*
* @param name The channel name.
* @param messenger The binary messenger.
* @param codec The message codec.
*/
- (instancetype)initWithName:(NSString*)name
binaryMessenger:(NSObject<FlutterBinaryMessenger>*)messenger
codec:(NSObject<FlutterMessageCodec>*)codec;
/**
* Initializes a `FlutterBasicMessageChannel` with the specified name, binary
* messenger, and message codec.
*
* The channel name logically identifies the channel; identically named channels
* interfere with each other's communication.
*
* The binary messenger is a facility for sending raw, binary messages to the
* Flutter side. This protocol is implemented by `FlutterEngine` and `FlutterViewController`.
*
* @param name The channel name.
* @param messenger The binary messenger.
* @param codec The message codec.
* @param taskQueue The FlutterTaskQueue that executes the handler (see
-[FlutterBinaryMessenger makeBackgroundTaskQueue]).
*/
- (instancetype)initWithName:(NSString*)name
binaryMessenger:(NSObject<FlutterBinaryMessenger>*)messenger
codec:(NSObject<FlutterMessageCodec>*)codec
taskQueue:(NSObject<FlutterTaskQueue>* _Nullable)taskQueue;
/**
* Sends the specified message to the Flutter side, ignoring any reply.
*
* @param message The message. Must be supported by the codec of this
* channel.
*/
- (void)sendMessage:(id _Nullable)message;
/**
* Sends the specified message to the Flutter side, expecting an asynchronous
* reply.
*
* @param message The message. Must be supported by the codec of this channel.
* @param callback A callback to be invoked with the message reply from Flutter.
*/
- (void)sendMessage:(id _Nullable)message reply:(FlutterReply _Nullable)callback;
/**
* Registers a message handler with this channel.
*
* Replaces any existing handler. Use a `nil` handler for unregistering the
* existing handler.
*
* @param handler The message handler.
*/
- (void)setMessageHandler:(FlutterMessageHandler _Nullable)handler;
/**
* Adjusts the number of messages that will get buffered when sending messages to
* channels that aren't fully set up yet. For example, the engine isn't running
* yet or the channel's message handler isn't set up on the Dart side yet.
*
* @param name The channel name.
* @param messenger The binary messenger.
* @param newSize The number of messages that will get buffered.
*/
+ (void)resizeChannelWithName:(NSString*)name
binaryMessenger:(NSObject<FlutterBinaryMessenger>*)messenger
size:(NSInteger)newSize;
/**
* Adjusts the number of messages that will get buffered when sending messages to
* channels that aren't fully set up yet. For example, the engine isn't running
* yet or the channel's message handler isn't set up on the Dart side yet.
*
* @param newSize The number of messages that will get buffered.
*/
- (void)resizeChannelBuffer:(NSInteger)newSize;
/**
* Defines whether the channel should show warning messages when discarding messages
* due to overflow.
*
* @param warns When false, the channel is expected to overflow and warning messages
* will not be shown.
* @param name The channel name.
* @param messenger The binary messenger.
*/
+ (void)setWarnsOnOverflow:(BOOL)warns
forChannelWithName:(NSString*)name
binaryMessenger:(NSObject<FlutterBinaryMessenger>*)messenger;
/**
* Defines whether the channel should show warning messages when discarding messages
* due to overflow.
*
* @param warns When false, the channel is expected to overflow and warning messages
* will not be shown.
*/
- (void)setWarnsOnOverflow:(BOOL)warns;
@end
/**
* A method call result callback.
*
* Used for submitting a method call result back to a Flutter caller. Also used in
* the dual capacity for handling a method call result received from Flutter.
*
* @param result The result.
*/
typedef void (^FlutterResult)(id _Nullable result);
/**
* A strategy for handling method calls.
*
* @param call The incoming method call.
* @param result A callback to asynchronously submit the result of the call.
* Invoke the callback with a `FlutterError` to indicate that the call failed.
* Invoke the callback with `FlutterMethodNotImplemented` to indicate that the
* method was unknown. Any other values, including `nil`, are interpreted as
* successful results. This can be invoked from any thread.
*/
typedef void (^FlutterMethodCallHandler)(FlutterMethodCall* call, FlutterResult result);
/**
* A constant used with `FlutterMethodCallHandler` to respond to the call of an
* unknown method.
*/
FLUTTER_DARWIN_EXPORT
extern NSObject const* FlutterMethodNotImplemented;
/**
* A channel for communicating with the Flutter side using invocation of
* asynchronous methods.
*/
FLUTTER_DARWIN_EXPORT
@interface FlutterMethodChannel : NSObject
/**
* Creates a `FlutterMethodChannel` with the specified name and binary messenger.
*
* The channel name logically identifies the channel; identically named channels
* interfere with each other's communication.
*
* The binary messenger is a facility for sending raw, binary messages to the
* Flutter side. This protocol is implemented by `FlutterEngine` and `FlutterViewController`.
*
* The channel uses `FlutterStandardMethodCodec` to encode and decode method calls
* and result envelopes.
*
* @param name The channel name.
* @param messenger The binary messenger.
*/
+ (instancetype)methodChannelWithName:(NSString*)name
binaryMessenger:(NSObject<FlutterBinaryMessenger>*)messenger;
/**
* Creates a `FlutterMethodChannel` with the specified name, binary messenger, and
* method codec.
*
* The channel name logically identifies the channel; identically named channels
* interfere with each other's communication.
*
* The binary messenger is a facility for sending raw, binary messages to the
* Flutter side. This protocol is implemented by `FlutterEngine` and `FlutterViewController`.
*
* @param name The channel name.
* @param messenger The binary messenger.
* @param codec The method codec.
*/
+ (instancetype)methodChannelWithName:(NSString*)name
binaryMessenger:(NSObject<FlutterBinaryMessenger>*)messenger
codec:(NSObject<FlutterMethodCodec>*)codec;
/**
* Initializes a `FlutterMethodChannel` with the specified name, binary messenger,
* and method codec.
*
* The channel name logically identifies the channel; identically named channels
* interfere with each other's communication.
*
* The binary messenger is a facility for sending raw, binary messages to the
* Flutter side. This protocol is implemented by `FlutterEngine` and `FlutterViewController`.
*
* @param name The channel name.
* @param messenger The binary messenger.
* @param codec The method codec.
*/
- (instancetype)initWithName:(NSString*)name
binaryMessenger:(NSObject<FlutterBinaryMessenger>*)messenger
codec:(NSObject<FlutterMethodCodec>*)codec;
/**
* Initializes a `FlutterMethodChannel` with the specified name, binary messenger,
* method codec, and task queue.
*
* The channel name logically identifies the channel; identically named channels
* interfere with each other's communication.
*
* The binary messenger is a facility for sending raw, binary messages to the
* Flutter side. This protocol is implemented by `FlutterEngine` and `FlutterViewController`.
*
* @param name The channel name.
* @param messenger The binary messenger.
* @param codec The method codec.
* @param taskQueue The FlutterTaskQueue that executes the handler (see
-[FlutterBinaryMessenger makeBackgroundTaskQueue]).
*/
- (instancetype)initWithName:(NSString*)name
binaryMessenger:(NSObject<FlutterBinaryMessenger>*)messenger
codec:(NSObject<FlutterMethodCodec>*)codec
taskQueue:(NSObject<FlutterTaskQueue>* _Nullable)taskQueue;
// clang-format off
/**
* Invokes the specified Flutter method with the specified arguments, expecting
* no results.
*
* @see [MethodChannel.setMethodCallHandler](https://api.flutter.dev/flutter/services/MethodChannel/setMethodCallHandler.html)
*
* @param method The name of the method to invoke.
* @param arguments The arguments. Must be a value supported by the codec of this
* channel.
*/
// clang-format on
- (void)invokeMethod:(NSString*)method arguments:(id _Nullable)arguments;
/**
* Invokes the specified Flutter method with the specified arguments, expecting
* an asynchronous result.
*
* @param method The name of the method to invoke.
* @param arguments The arguments. Must be a value supported by the codec of this
* channel.
* @param callback A callback that will be invoked with the asynchronous result.
* The result will be a `FlutterError` instance, if the method call resulted
* in an error on the Flutter side. Will be `FlutterMethodNotImplemented`, if
* the method called was not implemented on the Flutter side. Any other value,
* including `nil`, should be interpreted as successful results.
*/
- (void)invokeMethod:(NSString*)method
arguments:(id _Nullable)arguments
result:(FlutterResult _Nullable)callback;
/**
* Registers a handler for method calls from the Flutter side.
*
* Replaces any existing handler. Use a `nil` handler for unregistering the
* existing handler.
*
* @param handler The method call handler.
*/
- (void)setMethodCallHandler:(FlutterMethodCallHandler _Nullable)handler;
/**
* Adjusts the number of messages that will get buffered when sending messages to
* channels that aren't fully set up yet. For example, the engine isn't running
* yet or the channel's message handler isn't set up on the Dart side yet.
*/
- (void)resizeChannelBuffer:(NSInteger)newSize;
@end
/**
* An event sink callback.
*
* @param event The event.
*/
typedef void (^FlutterEventSink)(id _Nullable event);
/**
* A strategy for exposing an event stream to the Flutter side.
*/
FLUTTER_DARWIN_EXPORT
@protocol FlutterStreamHandler
/**
* Sets up an event stream and begin emitting events.
*
* Invoked when the first listener is registered with the Stream associated to
* this channel on the Flutter side.
*
* @param arguments Arguments for the stream.
* @param events A callback to asynchronously emit events. Invoke the
* callback with a `FlutterError` to emit an error event. Invoke the
* callback with `FlutterEndOfEventStream` to indicate that no more
* events will be emitted. Any other value, including `nil` are emitted as
* successful events.
* @return A FlutterError instance, if setup fails.
*/
- (FlutterError* _Nullable)onListenWithArguments:(id _Nullable)arguments
eventSink:(FlutterEventSink)events;
/**
* Tears down an event stream.
*
* Invoked when the last listener is deregistered from the Stream associated to
* this channel on the Flutter side.
*
* The channel implementation may call this method with `nil` arguments
* to separate a pair of two consecutive set up requests. Such request pairs
* may occur during Flutter hot restart.
*
* @param arguments Arguments for the stream.
* @return A FlutterError instance, if teardown fails.
*/
- (FlutterError* _Nullable)onCancelWithArguments:(id _Nullable)arguments;
@end
/**
* A constant used with `FlutterEventChannel` to indicate end of stream.
*/
FLUTTER_DARWIN_EXPORT
extern NSObject const* FlutterEndOfEventStream;
/**
* A channel for communicating with the Flutter side using event streams.
*/
FLUTTER_DARWIN_EXPORT
@interface FlutterEventChannel : NSObject
/**
* Creates a `FlutterEventChannel` with the specified name and binary messenger.
*
* The channel name logically identifies the channel; identically named channels
* interfere with each other's communication.
*
* The binary messenger is a facility for sending raw, binary messages to the
* Flutter side. This protocol is implemented by `FlutterViewController`.
*
* The channel uses `FlutterStandardMethodCodec` to decode stream setup and
* teardown requests, and to encode event envelopes.
*
* @param name The channel name.
* @param messenger The binary messenger.
*/
+ (instancetype)eventChannelWithName:(NSString*)name
binaryMessenger:(NSObject<FlutterBinaryMessenger>*)messenger;
/**
* Creates a `FlutterEventChannel` with the specified name, binary messenger,
* and method codec.
*
* The channel name logically identifies the channel; identically named channels
* interfere with each other's communication.
*
* The binary messenger is a facility for sending raw, binary messages to the
* Flutter side. This protocol is implemented by `FlutterViewController`.
*
* @param name The channel name.
* @param messenger The binary messenger.
* @param codec The method codec.
*/
+ (instancetype)eventChannelWithName:(NSString*)name
binaryMessenger:(NSObject<FlutterBinaryMessenger>*)messenger
codec:(NSObject<FlutterMethodCodec>*)codec;
/**
* Initializes a `FlutterEventChannel` with the specified name, binary messenger,
* and method codec.
*
* The channel name logically identifies the channel; identically named channels
* interfere with each other's communication.
*
* The binary messenger is a facility for sending raw, binary messages to the
* Flutter side. This protocol is implemented by `FlutterEngine` and `FlutterViewController`.
*
* @param name The channel name.
* @param messenger The binary messenger.
* @param codec The method codec.
*/
- (instancetype)initWithName:(NSString*)name
binaryMessenger:(NSObject<FlutterBinaryMessenger>*)messenger
codec:(NSObject<FlutterMethodCodec>*)codec;
/**
* Initializes a `FlutterEventChannel` with the specified name, binary messenger,
* method codec and task queue.
*
* The channel name logically identifies the channel; identically named channels
* interfere with each other's communication.
*
* The binary messenger is a facility for sending raw, binary messages to the
* Flutter side. This protocol is implemented by `FlutterEngine` and `FlutterViewController`.
*
* @param name The channel name.
* @param messenger The binary messenger.
* @param codec The method codec.
* @param taskQueue The FlutterTaskQueue that executes the handler (see
-[FlutterBinaryMessenger makeBackgroundTaskQueue]).
*/
- (instancetype)initWithName:(NSString*)name
binaryMessenger:(NSObject<FlutterBinaryMessenger>*)messenger
codec:(NSObject<FlutterMethodCodec>*)codec
taskQueue:(NSObject<FlutterTaskQueue>* _Nullable)taskQueue;
/**
* Registers a handler for stream setup requests from the Flutter side.
*
* Replaces any existing handler. Use a `nil` handler for unregistering the
* existing handler.
*
* @param handler The stream handler.
*/
- (void)setStreamHandler:(NSObject<FlutterStreamHandler>* _Nullable)handler;
@end
NS_ASSUME_NONNULL_END
#endif // FLUTTER_SHELL_PLATFORM_DARWIN_COMMON_FRAMEWORK_HEADERS_FLUTTERCHANNELS_H_
@@ -0,0 +1,478 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_SHELL_PLATFORM_DARWIN_COMMON_FRAMEWORK_HEADERS_FLUTTERCODECS_H_
#define FLUTTER_SHELL_PLATFORM_DARWIN_COMMON_FRAMEWORK_HEADERS_FLUTTERCODECS_H_
#import <Foundation/Foundation.h>
#import "FlutterMacros.h"
NS_ASSUME_NONNULL_BEGIN
/**
* A message encoding/decoding mechanism.
*/
FLUTTER_DARWIN_EXPORT
@protocol FlutterMessageCodec
/**
* Returns a shared instance of this `FlutterMessageCodec`.
*/
+ (instancetype)sharedInstance;
/**
* Encodes the specified message into binary.
*
* @param message The message.
* @return The binary encoding, or `nil`, if `message` was `nil`.
*/
- (NSData* _Nullable)encode:(id _Nullable)message;
/**
* Decodes the specified message from binary.
*
* @param message The message.
* @return The decoded message, or `nil`, if `message` was `nil`.
*/
- (id _Nullable)decode:(NSData* _Nullable)message;
@end
/**
* A `FlutterMessageCodec` using unencoded binary messages, represented as
* `NSData` instances.
*
* This codec is guaranteed to be compatible with the corresponding
* [BinaryCodec](https://api.flutter.dev/flutter/services/BinaryCodec-class.html)
* on the Dart side. These parts of the Flutter SDK are evolved synchronously.
*
* On the Dart side, messages are represented using `ByteData`.
*/
FLUTTER_DARWIN_EXPORT
@interface FlutterBinaryCodec : NSObject <FlutterMessageCodec>
@end
/**
* A `FlutterMessageCodec` using UTF-8 encoded `NSString` messages.
*
* This codec is guaranteed to be compatible with the corresponding
* [StringCodec](https://api.flutter.dev/flutter/services/StringCodec-class.html)
* on the Dart side. These parts of the Flutter SDK are evolved synchronously.
*/
FLUTTER_DARWIN_EXPORT
@interface FlutterStringCodec : NSObject <FlutterMessageCodec>
@end
/**
* A `FlutterMessageCodec` using UTF-8 encoded JSON messages.
*
* This codec is guaranteed to be compatible with the corresponding
* [JSONMessageCodec](https://api.flutter.dev/flutter/services/JSONMessageCodec-class.html)
* on the Dart side. These parts of the Flutter SDK are evolved synchronously.
*
* Supports values accepted by `NSJSONSerialization` plus top-level
* `nil`, `NSNumber`, and `NSString`.
*
* On the Dart side, JSON messages are handled by the JSON facilities of the
* [`dart:convert`](https://api.dartlang.org/stable/dart-convert/JSON-constant.html)
* package.
*/
FLUTTER_DARWIN_EXPORT
@interface FlutterJSONMessageCodec : NSObject <FlutterMessageCodec>
@end
/**
* A writer of the Flutter standard binary encoding.
*
* See `FlutterStandardMessageCodec` for details on the encoding.
*
* The encoding is extensible via subclasses overriding `writeValue`.
*/
FLUTTER_DARWIN_EXPORT
@interface FlutterStandardWriter : NSObject
/**
* Create a `FlutterStandardWriter` who will write to \p data.
*/
- (instancetype)initWithData:(NSMutableData*)data;
/** Write a 8-bit byte. */
- (void)writeByte:(UInt8)value;
/** Write an array of \p bytes of size \p length. */
- (void)writeBytes:(const void*)bytes length:(NSUInteger)length;
/** Write an array of bytes contained in \p data. */
- (void)writeData:(NSData*)data;
/** Write 32-bit unsigned integer that represents a \p size of a collection. */
- (void)writeSize:(UInt32)size;
/** Write zero padding until data is aligned with \p alignment. */
- (void)writeAlignment:(UInt8)alignment;
/** Write a string with UTF-8 encoding. */
- (void)writeUTF8:(NSString*)value;
/** Introspects into an object and writes its representation.
*
* Supported Data Types:
* - NSNull
* - NSNumber
* - NSString (as UTF-8)
* - FlutterStandardTypedData
* - NSArray of supported types
* - NSDictionary of supporte types
*
* NSAsserts on failure.
*/
- (void)writeValue:(id)value;
@end
/**
* A reader of the Flutter standard binary encoding.
*
* See `FlutterStandardMessageCodec` for details on the encoding.
*
* The encoding is extensible via subclasses overriding `readValueOfType`.
*/
FLUTTER_DARWIN_EXPORT
@interface FlutterStandardReader : NSObject
/**
* Create a new `FlutterStandardReader` who reads from \p data.
*/
- (instancetype)initWithData:(NSData*)data;
/** Returns YES when the reader hasn't reached the end of its data. */
- (BOOL)hasMore;
/** Reads a byte value and increments the position. */
- (UInt8)readByte;
/** Reads a sequence of byte values of \p length and increments the position. */
- (void)readBytes:(void*)destination length:(NSUInteger)length;
/** Reads a sequence of byte values of \p length and increments the position. */
- (NSData*)readData:(NSUInteger)length;
/** Reads a 32-bit unsigned integer representing a collection size and increments the position.*/
- (UInt32)readSize;
/** Advances the read position until it is aligned with \p alignment. */
- (void)readAlignment:(UInt8)alignment;
/** Read a null terminated string encoded with UTF-8/ */
- (NSString*)readUTF8;
/**
* Reads a byte for `FlutterStandardField` the decodes a value matching that type.
*
* See also: -[FlutterStandardWriter writeValue]
*/
- (nullable id)readValue;
/**
* Decodes a value matching the \p type specified.
*
* See also:
* - `FlutterStandardField`
* - `-[FlutterStandardWriter writeValue]`
*/
- (nullable id)readValueOfType:(UInt8)type;
@end
/**
* A factory of compatible reader/writer instances using the Flutter standard
* binary encoding or extensions thereof.
*/
FLUTTER_DARWIN_EXPORT
@interface FlutterStandardReaderWriter : NSObject
/**
* Create a new `FlutterStandardWriter` for writing to \p data.
*/
- (FlutterStandardWriter*)writerWithData:(NSMutableData*)data;
/**
* Create a new `FlutterStandardReader` for reading from \p data.
*/
- (FlutterStandardReader*)readerWithData:(NSData*)data;
@end
/**
* A `FlutterMessageCodec` using the Flutter standard binary encoding.
*
* This codec is guaranteed to be compatible with the corresponding
* [StandardMessageCodec](https://api.flutter.dev/flutter/services/StandardMessageCodec-class.html)
* on the Dart side. These parts of the Flutter SDK are evolved synchronously.
*
* Supported messages are acyclic values of these forms:
*
* - `nil` or `NSNull`
* - `NSNumber` (including their representation of Boolean values)
* - `NSString`
* - `FlutterStandardTypedData`
* - `NSArray` of supported values
* - `NSDictionary` with supported keys and values
*
* On the Dart side, these values are represented as follows:
*
* - `nil` or `NSNull`: null
* - `NSNumber`: `bool`, `int`, or `double`, depending on the contained value.
* - `NSString`: `String`
* - `FlutterStandardTypedData`: `Uint8List`, `Int32List`, `Int64List`, or `Float64List`
* - `NSArray`: `List`
* - `NSDictionary`: `Map`
*/
FLUTTER_DARWIN_EXPORT
@interface FlutterStandardMessageCodec : NSObject <FlutterMessageCodec>
/**
* Create a `FlutterStandardMessageCodec` who will read and write to \p readerWriter.
*/
+ (instancetype)codecWithReaderWriter:(FlutterStandardReaderWriter*)readerWriter;
@end
/**
* Command object representing a method call on a `FlutterMethodChannel`.
*/
FLUTTER_DARWIN_EXPORT
@interface FlutterMethodCall : NSObject
/**
* Creates a method call for invoking the specified named method with the
* specified arguments.
*
* @param method the name of the method to call.
* @param arguments the arguments value.
*/
+ (instancetype)methodCallWithMethodName:(NSString*)method arguments:(id _Nullable)arguments;
/**
* The method name.
*/
@property(readonly, nonatomic) NSString* method;
/**
* The arguments.
*/
@property(readonly, nonatomic, nullable) id arguments;
@end
/**
* Error object representing an unsuccessful outcome of invoking a method
* on a `FlutterMethodChannel`, or an error event on a `FlutterEventChannel`.
*/
FLUTTER_DARWIN_EXPORT
@interface FlutterError : NSObject
/**
* Creates a `FlutterError` with the specified error code, message, and details.
*
* @param code An error code string for programmatic use.
* @param message A human-readable error message.
* @param details Custom error details.
*/
+ (instancetype)errorWithCode:(NSString*)code
message:(NSString* _Nullable)message
details:(id _Nullable)details;
/**
The error code.
*/
@property(readonly, nonatomic) NSString* code;
/**
The error message.
*/
@property(readonly, nonatomic, nullable) NSString* message;
/**
The error details.
*/
@property(readonly, nonatomic, nullable) id details;
@end
/**
* Type of numeric data items encoded in a `FlutterStandardDataType`.
*
* - FlutterStandardDataTypeUInt8: plain bytes
* - FlutterStandardDataTypeInt32: 32-bit signed integers
* - FlutterStandardDataTypeInt64: 64-bit signed integers
* - FlutterStandardDataTypeFloat64: 64-bit floats
*/
typedef NS_ENUM(NSInteger, FlutterStandardDataType) {
// NOLINTBEGIN(readability-identifier-naming)
FlutterStandardDataTypeUInt8,
FlutterStandardDataTypeInt32,
FlutterStandardDataTypeInt64,
FlutterStandardDataTypeFloat32,
FlutterStandardDataTypeFloat64,
// NOLINTEND(readability-identifier-naming)
};
/**
* A byte buffer holding `UInt8`, `SInt32`, `SInt64`, or `Float64` values, used
* with `FlutterStandardMessageCodec` and `FlutterStandardMethodCodec`.
*
* Two's complement encoding is used for signed integers. IEEE754
* double-precision representation is used for floats. The platform's native
* endianness is assumed.
*/
FLUTTER_DARWIN_EXPORT
@interface FlutterStandardTypedData : NSObject
/**
* Creates a `FlutterStandardTypedData` which interprets the specified data
* as plain bytes.
*
* @param data the byte data.
*/
+ (instancetype)typedDataWithBytes:(NSData*)data;
/**
* Creates a `FlutterStandardTypedData` which interprets the specified data
* as 32-bit signed integers.
*
* @param data the byte data. The length must be divisible by 4.
*/
+ (instancetype)typedDataWithInt32:(NSData*)data;
/**
* Creates a `FlutterStandardTypedData` which interprets the specified data
* as 64-bit signed integers.
*
* @param data the byte data. The length must be divisible by 8.
*/
+ (instancetype)typedDataWithInt64:(NSData*)data;
/**
* Creates a `FlutterStandardTypedData` which interprets the specified data
* as 32-bit floats.
*
* @param data the byte data. The length must be divisible by 8.
*/
+ (instancetype)typedDataWithFloat32:(NSData*)data;
/**
* Creates a `FlutterStandardTypedData` which interprets the specified data
* as 64-bit floats.
*
* @param data the byte data. The length must be divisible by 8.
*/
+ (instancetype)typedDataWithFloat64:(NSData*)data;
/**
* The raw underlying data buffer.
*/
@property(readonly, nonatomic) NSData* data;
/**
* The type of the encoded values.
*/
@property(readonly, nonatomic, assign) FlutterStandardDataType type;
/**
* The number of value items encoded.
*/
@property(readonly, nonatomic, assign) UInt32 elementCount;
/**
* The number of bytes used by the encoding of a single value item.
*/
@property(readonly, nonatomic, assign) UInt8 elementSize;
@end
/**
* An arbitrarily large integer value, used with `FlutterStandardMessageCodec`
* and `FlutterStandardMethodCodec`.
*/
FLUTTER_DARWIN_EXPORT
FLUTTER_UNAVAILABLE("Unavailable on 2018-08-31. Deprecated on 2018-01-09. "
"FlutterStandardBigInteger was needed because the Dart 1.0 int type had no "
"size limit. With Dart 2.0, the int type is a fixed-size, 64-bit signed "
"integer. If you need to communicate larger integers, use NSString encoding "
"instead.")
@interface FlutterStandardBigInteger : NSObject
@end
/**
* A codec for method calls and enveloped results.
*
* Method calls are encoded as binary messages with enough structure that the
* codec can extract a method name `NSString` and an arguments `NSObject`,
* possibly `nil`. These data items are used to populate a `FlutterMethodCall`.
*
* Result envelopes are encoded as binary messages with enough structure that
* the codec can determine whether the result was successful or an error. In
* the former case, the codec can extract the result `NSObject`, possibly `nil`.
* In the latter case, the codec can extract an error code `NSString`, a
* human-readable `NSString` error message (possibly `nil`), and a custom
* error details `NSObject`, possibly `nil`. These data items are used to
* populate a `FlutterError`.
*/
FLUTTER_DARWIN_EXPORT
@protocol FlutterMethodCodec
/**
* Provides access to a shared instance this codec.
*
* @return The shared instance.
*/
+ (instancetype)sharedInstance;
/**
* Encodes the specified method call into binary.
*
* @param methodCall The method call. The arguments value
* must be supported by this codec.
* @return The binary encoding.
*/
- (NSData*)encodeMethodCall:(FlutterMethodCall*)methodCall;
/**
* Decodes the specified method call from binary.
*
* @param methodCall The method call to decode.
* @return The decoded method call.
*/
- (FlutterMethodCall*)decodeMethodCall:(NSData*)methodCall;
/**
* Encodes the specified successful result into binary.
*
* @param result The result. Must be a value supported by this codec.
* @return The binary encoding.
*/
- (NSData*)encodeSuccessEnvelope:(id _Nullable)result;
/**
* Encodes the specified error result into binary.
*
* @param error The error object. The error details value must be supported
* by this codec.
* @return The binary encoding.
*/
- (NSData*)encodeErrorEnvelope:(FlutterError*)error;
/**
* Deccodes the specified result envelope from binary.
*
* @param envelope The error object.
* @return The result value, if the envelope represented a successful result,
* or a `FlutterError` instance, if not.
*/
- (id _Nullable)decodeEnvelope:(NSData*)envelope;
@end
/**
* A `FlutterMethodCodec` using UTF-8 encoded JSON method calls and result
* envelopes.
*
* This codec is guaranteed to be compatible with the corresponding
* [JSONMethodCodec](https://api.flutter.dev/flutter/services/JSONMethodCodec-class.html)
* on the Dart side. These parts of the Flutter SDK are evolved synchronously.
*
* Values supported as methods arguments and result payloads are
* those supported as top-level or leaf values by `FlutterJSONMessageCodec`.
*/
FLUTTER_DARWIN_EXPORT
@interface FlutterJSONMethodCodec : NSObject <FlutterMethodCodec>
@end
/**
* A `FlutterMethodCodec` using the Flutter standard binary encoding.
*
* This codec is guaranteed to be compatible with the corresponding
* [StandardMethodCodec](https://api.flutter.dev/flutter/services/StandardMethodCodec-class.html)
* on the Dart side. These parts of the Flutter SDK are evolved synchronously.
*
* Values supported as method arguments and result payloads are those supported by
* `FlutterStandardMessageCodec`.
*/
FLUTTER_DARWIN_EXPORT
@interface FlutterStandardMethodCodec : NSObject <FlutterMethodCodec>
/**
* Create a `FlutterStandardMethodCodec` who will read and write to \p readerWriter.
*/
+ (instancetype)codecWithReaderWriter:(FlutterStandardReaderWriter*)readerWriter;
@end
NS_ASSUME_NONNULL_END
#endif // FLUTTER_SHELL_PLATFORM_DARWIN_COMMON_FRAMEWORK_HEADERS_FLUTTERCODECS_H_
@@ -0,0 +1,103 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_SHELL_PLATFORM_DARWIN_COMMON_FRAMEWORK_HEADERS_FLUTTERDARTPROJECT_H_
#define FLUTTER_SHELL_PLATFORM_DARWIN_COMMON_FRAMEWORK_HEADERS_FLUTTERDARTPROJECT_H_
#import <Foundation/Foundation.h>
#import <TargetConditionals.h>
#import "FlutterMacros.h"
NS_ASSUME_NONNULL_BEGIN
/**
* A set of Flutter and Dart assets used by a `FlutterEngine` to initialize execution.
*
*/
FLUTTER_DARWIN_EXPORT
@interface FlutterDartProject : NSObject
/**
* Initializes a Flutter Dart project from a bundle.
*
* The bundle must either contain a flutter_assets resource directory, or set the Info.plist key
* FLTAssetsPath to override that name (if you are doing a custom build using a different name).
*
* @param bundle The bundle containing the Flutter assets directory. If nil, the App framework
* created by Flutter will be used.
*/
- (instancetype)initWithPrecompiledDartBundle:(nullable NSBundle*)bundle NS_DESIGNATED_INITIALIZER;
/**
* Unavailable - use `init` instead.
*/
- (instancetype)initFromDefaultSourceForConfiguration API_UNAVAILABLE(macos)
FLUTTER_UNAVAILABLE("Use -init instead.");
/**
* Returns the default identifier for the bundle where we expect to find the Flutter Dart
* application.
*/
+ (NSString*)defaultBundleIdentifier;
/**
* An NSArray of NSStrings to be passed as command line arguments to the Dart entrypoint.
*
* If this is not explicitly set, this will default to the contents of
* [NSProcessInfo arguments], without the binary name.
*
* Set this to nil to pass no arguments to the Dart entrypoint.
*/
@property(nonatomic, nullable, copy)
NSArray<NSString*>* dartEntrypointArguments API_UNAVAILABLE(ios);
/**
* Returns the file name for the given asset. If the bundle with the identifier
* "io.flutter.flutter.app" exists, it will try use that bundle; otherwise, it
* will use the main bundle. To specify a different bundle, use
* `+lookupKeyForAsset:fromBundle`.
*
* @param asset The name of the asset. The name can be hierarchical.
* @return the file name to be used for lookup in the main bundle.
*/
+ (NSString*)lookupKeyForAsset:(NSString*)asset;
/**
* Returns the file name for the given asset.
* The returned file name can be used to access the asset in the supplied bundle.
*
* @param asset The name of the asset. The name can be hierarchical.
* @param bundle The `NSBundle` to use for looking up the asset.
* @return the file name to be used for lookup in the main bundle.
*/
+ (NSString*)lookupKeyForAsset:(NSString*)asset fromBundle:(nullable NSBundle*)bundle;
/**
* Returns the file name for the given asset which originates from the specified package.
* The returned file name can be used to access the asset in the application's main bundle.
*
* @param asset The name of the asset. The name can be hierarchical.
* @param package The name of the package from which the asset originates.
* @return the file name to be used for lookup in the main bundle.
*/
+ (NSString*)lookupKeyForAsset:(NSString*)asset fromPackage:(NSString*)package;
/**
* Returns the file name for the given asset which originates from the specified package.
* The returned file name can be used to access the asset in the specified bundle.
*
* @param asset The name of the asset. The name can be hierarchical.
* @param package The name of the package from which the asset originates.
* @param bundle The bundle to use when doing the lookup.
* @return the file name to be used for lookup in the main bundle.
*/
+ (NSString*)lookupKeyForAsset:(NSString*)asset
fromPackage:(NSString*)package
fromBundle:(nullable NSBundle*)bundle;
@end
NS_ASSUME_NONNULL_END
#endif // FLUTTER_SHELL_PLATFORM_DARWIN_COMMON_FRAMEWORK_HEADERS_FLUTTERDARTPROJECT_H_
@@ -0,0 +1,462 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_HEADERS_FLUTTERENGINE_H_
#define FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_HEADERS_FLUTTERENGINE_H_
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "FlutterBinaryMessenger.h"
#import "FlutterDartProject.h"
#import "FlutterMacros.h"
#import "FlutterPlugin.h"
#import "FlutterTexture.h"
@class FlutterViewController;
NS_ASSUME_NONNULL_BEGIN
/**
* The dart entrypoint that is associated with `main()`. This is to be used as an argument to the
* `runWithEntrypoint*` methods.
*/
// NOLINTNEXTLINE(readability-identifier-naming)
extern NSString* const FlutterDefaultDartEntrypoint;
/**
* The default Flutter initial route ("/").
*/
// NOLINTNEXTLINE(readability-identifier-naming)
extern NSString* const FlutterDefaultInitialRoute;
/**
* The FlutterEngine class coordinates a single instance of execution for a
* `FlutterDartProject`. It may have zero or one `FlutterViewController` at a
* time, which can be specified via `-setViewController:`.
* `FlutterViewController`'s `initWithEngine` initializer will automatically call
* `-setViewController:` for itself.
*
* A FlutterEngine can be created independently of a `FlutterViewController` for
* headless execution. It can also persist across the lifespan of multiple
* `FlutterViewController` instances to maintain state and/or asynchronous tasks
* (such as downloading a large file).
*
* A FlutterEngine can also be used to prewarm the Dart execution environment and reduce the
* latency of showing the Flutter screen when a `FlutterViewController` is created and presented.
* See http://flutter.dev/docs/development/add-to-app/performance for more details on loading
* performance.
*
* Alternatively, you can simply create a new `FlutterViewController` with only a
* `FlutterDartProject`. That `FlutterViewController` will internally manage its
* own instance of a FlutterEngine, but will not guarantee survival of the engine
* beyond the life of the ViewController.
*
* A newly initialized FlutterEngine will not actually run a Dart Isolate until
* either `-runWithEntrypoint:` or `-runWithEntrypoint:libraryURI` is invoked.
* One of these methods must be invoked before calling `-setViewController:`.
*/
FLUTTER_DARWIN_EXPORT
@interface FlutterEngine : NSObject <FlutterPluginRegistry>
/**
* Default initializer for a FlutterEngine.
*
* Threads created by this FlutterEngine will appear as "FlutterEngine #" in
* Instruments. The prefix can be customized using `initWithName`.
*
* The engine will execute the project located in the bundle with the identifier
* "io.flutter.flutter.app" (the default for Flutter projects).
*
* A newly initialized engine will not run until either `-runWithEntrypoint:` or
* `-runWithEntrypoint:libraryURI:` is called.
*
* FlutterEngine created with this method will have allowHeadlessExecution set to `YES`.
* This means that the engine will continue to run regardless of whether a `FlutterViewController`
* is attached to it or not, until `-destroyContext:` is called or the process finishes.
*/
- (instancetype)init;
/**
* Initialize this FlutterEngine.
*
* The engine will execute the project located in the bundle with the identifier
* "io.flutter.flutter.app" (the default for Flutter projects).
*
* A newly initialized engine will not run until either `-runWithEntrypoint:` or
* `-runWithEntrypoint:libraryURI:` is called.
*
* FlutterEngine created with this method will have allowHeadlessExecution set to `YES`.
* This means that the engine will continue to run regardless of whether a `FlutterViewController`
* is attached to it or not, until `-destroyContext:` is called or the process finishes.
*
* @param labelPrefix The label prefix used to identify threads for this instance. Should
* be unique across FlutterEngine instances, and is used in instrumentation to label
* the threads used by this FlutterEngine.
*/
- (instancetype)initWithName:(NSString*)labelPrefix;
/**
* Initialize this FlutterEngine with a `FlutterDartProject`.
*
* If the FlutterDartProject is not specified, the FlutterEngine will attempt to locate
* the project in a default location (the flutter_assets folder in the iOS application
* bundle).
*
* A newly initialized engine will not run the `FlutterDartProject` until either
* `-runWithEntrypoint:` or `-runWithEntrypoint:libraryURI:` is called.
*
* FlutterEngine created with this method will have allowHeadlessExecution set to `YES`.
* This means that the engine will continue to run regardless of whether a `FlutterViewController`
* is attached to it or not, until `-destroyContext:` is called or the process finishes.
*
* @param labelPrefix The label prefix used to identify threads for this instance. Should
* be unique across FlutterEngine instances, and is used in instrumentation to label
* the threads used by this FlutterEngine.
* @param project The `FlutterDartProject` to run.
*/
- (instancetype)initWithName:(NSString*)labelPrefix project:(nullable FlutterDartProject*)project;
/**
* Initialize this FlutterEngine with a `FlutterDartProject`.
*
* If the FlutterDartProject is not specified, the FlutterEngine will attempt to locate
* the project in a default location (the flutter_assets folder in the iOS application
* bundle).
*
* A newly initialized engine will not run the `FlutterDartProject` until either
* `-runWithEntrypoint:` or `-runWithEntrypoint:libraryURI:` is called.
*
* @param labelPrefix The label prefix used to identify threads for this instance. Should
* be unique across FlutterEngine instances, and is used in instrumentation to label
* the threads used by this FlutterEngine.
* @param project The `FlutterDartProject` to run.
* @param allowHeadlessExecution Whether or not to allow this instance to continue
* running after passing a nil `FlutterViewController` to `-setViewController:`.
*/
- (instancetype)initWithName:(NSString*)labelPrefix
project:(nullable FlutterDartProject*)project
allowHeadlessExecution:(BOOL)allowHeadlessExecution;
/**
* Initialize this FlutterEngine with a `FlutterDartProject`.
*
* If the FlutterDartProject is not specified, the FlutterEngine will attempt to locate
* the project in a default location (the flutter_assets folder in the iOS application
* bundle).
*
* A newly initialized engine will not run the `FlutterDartProject` until either
* `-runWithEntrypoint:` or `-runWithEntrypoint:libraryURI:` is called.
*
* @param labelPrefix The label prefix used to identify threads for this instance. Should
* be unique across FlutterEngine instances, and is used in instrumentation to label
* the threads used by this FlutterEngine.
* @param project The `FlutterDartProject` to run.
* @param allowHeadlessExecution Whether or not to allow this instance to continue
* running after passing a nil `FlutterViewController` to `-setViewController:`.
* @param restorationEnabled Whether state restoration is enabled. When true, the framework will
* wait for the attached view controller to provide restoration data.
*/
- (instancetype)initWithName:(NSString*)labelPrefix
project:(nullable FlutterDartProject*)project
allowHeadlessExecution:(BOOL)allowHeadlessExecution
restorationEnabled:(BOOL)restorationEnabled NS_DESIGNATED_INITIALIZER;
/**
* Runs a Dart program on an Isolate from the main Dart library (i.e. the library that
* contains `main()`), using `main()` as the entrypoint (the default for Flutter projects),
* and using "/" (the default route) as the initial route.
*
* The first call to this method will create a new Isolate. Subsequent calls will return
* immediately and have no effect.
*
* @return YES if the call succeeds in creating and running a Flutter Engine instance; NO otherwise.
*/
- (BOOL)run;
/**
* Runs a Dart program on an Isolate from the main Dart library (i.e. the library that
* contains `main()`), using "/" (the default route) as the initial route.
*
* The first call to this method will create a new Isolate. Subsequent calls will return
* immediately and have no effect.
*
* @param entrypoint The name of a top-level function from the same Dart
* library that contains the app's main() function. If this is FlutterDefaultDartEntrypoint (or
* nil) it will default to `main()`. If it is not the app's main() function, that function must
* be decorated with `@pragma(vm:entry-point)` to ensure the method is not tree-shaken by the Dart
* compiler.
* @return YES if the call succeeds in creating and running a Flutter Engine instance; NO otherwise.
*/
- (BOOL)runWithEntrypoint:(nullable NSString*)entrypoint;
/**
* Runs a Dart program on an Isolate from the main Dart library (i.e. the library that
* contains `main()`).
*
* The first call to this method will create a new Isolate. Subsequent calls will return
* immediately and have no effect.
*
* @param entrypoint The name of a top-level function from the same Dart
* library that contains the app's main() function. If this is FlutterDefaultDartEntrypoint (or
* nil), it will default to `main()`. If it is not the app's main() function, that function must
* be decorated with `@pragma(vm:entry-point)` to ensure the method is not tree-shaken by the Dart
* compiler.
* @param initialRoute The name of the initial Flutter `Navigator` `Route` to load. If this is
* FlutterDefaultInitialRoute (or nil), it will default to the "/" route.
* @return YES if the call succeeds in creating and running a Flutter Engine instance; NO otherwise.
*/
- (BOOL)runWithEntrypoint:(nullable NSString*)entrypoint
initialRoute:(nullable NSString*)initialRoute;
/**
* Runs a Dart program on an Isolate using the specified entrypoint and Dart library,
* which may not be the same as the library containing the Dart program's `main()` function.
*
* The first call to this method will create a new Isolate. Subsequent calls will return
* immediately and have no effect.
*
* @param entrypoint The name of a top-level function from a Dart library. If this is
* FlutterDefaultDartEntrypoint (or nil); this will default to `main()`. If it is not the app's
* main() function, that function must be decorated with `@pragma(vm:entry-point)` to ensure the
* method is not tree-shaken by the Dart compiler.
* @param uri The URI of the Dart library which contains the entrypoint method
* (example "package:foo_package/main.dart"). If nil, this will default to
* the same library as the `main()` function in the Dart program.
* @return YES if the call succeeds in creating and running a Flutter Engine instance; NO otherwise.
*/
- (BOOL)runWithEntrypoint:(nullable NSString*)entrypoint libraryURI:(nullable NSString*)uri;
/**
* Runs a Dart program on an Isolate using the specified entrypoint and Dart library,
* which may not be the same as the library containing the Dart program's `main()` function.
*
* The first call to this method will create a new Isolate. Subsequent calls will return
* immediately and have no effect.
*
* @param entrypoint The name of a top-level function from a Dart library. If this is
* FlutterDefaultDartEntrypoint (or nil); this will default to `main()`. If it is not the app's
* main() function, that function must be decorated with `@pragma(vm:entry-point)` to ensure the
* method is not tree-shaken by the Dart compiler.
* @param libraryURI The URI of the Dart library which contains the entrypoint
* method (example "package:foo_package/main.dart"). If nil, this will
* default to the same library as the `main()` function in the Dart program.
* @param initialRoute The name of the initial Flutter `Navigator` `Route` to load. If this is
* FlutterDefaultInitialRoute (or nil), it will default to the "/" route.
* @return YES if the call succeeds in creating and running a Flutter Engine instance; NO otherwise.
*/
- (BOOL)runWithEntrypoint:(nullable NSString*)entrypoint
libraryURI:(nullable NSString*)libraryURI
initialRoute:(nullable NSString*)initialRoute;
/**
* Runs a Dart program on an Isolate using the specified entrypoint and Dart library,
* which may not be the same as the library containing the Dart program's `main()` function.
*
* The first call to this method will create a new Isolate. Subsequent calls will return
* immediately and have no effect.
*
* @param entrypoint The name of a top-level function from a Dart library. If this is
* FlutterDefaultDartEntrypoint (or nil); this will default to `main()`. If it is not the app's
* main() function, that function must be decorated with `@pragma(vm:entry-point)` to ensure the
* method is not tree-shaken by the Dart compiler.
* @param libraryURI The URI of the Dart library which contains the entrypoint
* method (example "package:foo_package/main.dart"). If nil, this will
* default to the same library as the `main()` function in the Dart program.
* @param initialRoute The name of the initial Flutter `Navigator` `Route` to load. If this is
* FlutterDefaultInitialRoute (or nil), it will default to the "/" route.
* @param entrypointArgs Arguments passed as a list of string to Dart's entrypoint function.
* @return YES if the call succeeds in creating and running a Flutter Engine instance; NO otherwise.
*/
- (BOOL)runWithEntrypoint:(nullable NSString*)entrypoint
libraryURI:(nullable NSString*)libraryURI
initialRoute:(nullable NSString*)initialRoute
entrypointArgs:(nullable NSArray<NSString*>*)entrypointArgs;
/**
* Destroy running context for an engine.
*
* This method can be used to force the FlutterEngine object to release all resources.
* After sending this message, the object will be in an unusable state until it is deallocated.
* Accessing properties or sending messages to it will result in undefined behavior or runtime
* errors.
*/
- (void)destroyContext;
/**
* Ensures that Flutter will generate a semantics tree.
*
* This is enabled by default if certain accessibility services are turned on by
* the user, or when using a Simulator. This method allows a user to turn
* semantics on when they would not ordinarily be generated and the performance
* overhead is not a concern, e.g. for UI testing. Note that semantics should
* never be programmatically turned off, as it would potentially disable
* accessibility services an end user has requested.
*
* This method must only be called after launching the engine via
* `-runWithEntrypoint:` or `-runWithEntryPoint:libraryURI`.
*
* Although this method returns synchronously, it does not guarantee that a
* semantics tree is actually available when the method returns. It
* synchronously ensures that the next frame the Flutter framework creates will
* have a semantics tree.
*
* You can subscribe to semantics updates via `NSNotificationCenter` by adding
* an observer for the name `FlutterSemanticsUpdateNotification`. The `object`
* parameter will be the `FlutterViewController` associated with the semantics
* update. This will asynchronously fire after a semantics tree has actually
* built (which may be some time after the frame has been rendered).
*/
- (void)ensureSemanticsEnabled;
/**
* Sets the `FlutterViewController` for this instance. The FlutterEngine must be
* running (e.g. a successful call to `-runWithEntrypoint:` or `-runWithEntrypoint:libraryURI`)
* before calling this method. Callers may pass nil to remove the viewController
* and have the engine run headless in the current process.
*
* A FlutterEngine can only have one `FlutterViewController` at a time. If there is
* already a `FlutterViewController` associated with this instance, this method will replace
* the engine's current viewController with the newly specified one.
*
* Setting the viewController will signal the engine to start animations and drawing, and unsetting
* it will signal the engine to stop animations and drawing. However, neither will impact the state
* of the Dart program's execution.
*/
@property(nonatomic, weak) FlutterViewController* viewController;
/**
* The `FlutterMethodChannel` used for localization related platform messages, such as
* setting the locale.
*
* Can be nil after `destroyContext` is called.
*/
@property(nonatomic, readonly, nullable) FlutterMethodChannel* localizationChannel;
/**
* The `FlutterMethodChannel` used for navigation related platform messages.
*
* Can be nil after `destroyContext` is called.
*
* @see [Navigation
* Channel](https://api.flutter.dev/flutter/services/SystemChannels/navigation-constant.html)
* @see [Navigator Widget](https://api.flutter.dev/flutter/widgets/Navigator-class.html)
*/
@property(nonatomic, readonly) FlutterMethodChannel* navigationChannel;
/**
* The `FlutterMethodChannel` used for restoration related platform messages.
*
* Can be nil after `destroyContext` is called.
*
* @see [Restoration
* Channel](https://api.flutter.dev/flutter/services/SystemChannels/restoration-constant.html)
*/
@property(nonatomic, readonly) FlutterMethodChannel* restorationChannel;
/**
* The `FlutterMethodChannel` used for core platform messages, such as
* information about the screen orientation.
*
* Can be nil after `destroyContext` is called.
*/
@property(nonatomic, readonly) FlutterMethodChannel* platformChannel;
/**
* The `FlutterMethodChannel` used to communicate text input events to the
* Dart Isolate.
*
* Can be nil after `destroyContext` is called.
*
* @see [Text Input
* Channel](https://api.flutter.dev/flutter/services/SystemChannels/textInput-constant.html)
*/
@property(nonatomic, readonly) FlutterMethodChannel* textInputChannel;
/**
* The `FlutterBasicMessageChannel` used to communicate app lifecycle events
* to the Dart Isolate.
*
* Can be nil after `destroyContext` is called.
*
* @see [Lifecycle
* Channel](https://api.flutter.dev/flutter/services/SystemChannels/lifecycle-constant.html)
*/
@property(nonatomic, readonly) FlutterBasicMessageChannel* lifecycleChannel;
/**
* The `FlutterBasicMessageChannel` used for communicating system events, such as
* memory pressure events.
*
* Can be nil after `destroyContext` is called.
*
* @see [System
* Channel](https://api.flutter.dev/flutter/services/SystemChannels/system-constant.html)
*/
@property(nonatomic, readonly) FlutterBasicMessageChannel* systemChannel;
/**
* The `FlutterBasicMessageChannel` used for communicating user settings such as
* clock format and text scale.
*
* Can be nil after `destroyContext` is called.
*/
@property(nonatomic, readonly) FlutterBasicMessageChannel* settingsChannel;
/**
* The `FlutterBasicMessageChannel` used for communicating key events
* from physical keyboards
*
* Can be nil after `destroyContext` is called.
*/
@property(nonatomic, readonly) FlutterBasicMessageChannel* keyEventChannel;
/**
* The depcreated `NSURL` of the Dart VM Service for the service isolate.
*
* This is only set in debug and profile runtime modes, and only after the
* Dart VM Service is ready. In release mode or before the Dart VM Service has
* started, it returns `nil`.
*/
@property(nonatomic, readonly, nullable)
NSURL* observatoryUrl FLUTTER_DEPRECATED("Use vmServiceUrl instead");
/**
* The `NSURL` of the Dart VM Service for the service isolate.
*
* This is only set in debug and profile runtime modes, and only after the
* Dart VM Service is ready. In release mode or before the Dart VM Service has
* started, it returns `nil`.
*/
@property(nonatomic, readonly, nullable) NSURL* vmServiceUrl;
/**
* The `FlutterBinaryMessenger` associated with this FlutterEngine (used for communicating with
* channels).
*/
@property(nonatomic, readonly) NSObject<FlutterBinaryMessenger>* binaryMessenger;
/**
* The `FlutterTextureRegistry` associated with this FlutterEngine (used to register textures).
*/
@property(nonatomic, readonly) NSObject<FlutterTextureRegistry>* textureRegistry;
/**
* The UI Isolate ID of the engine.
*
* This property will be nil if the engine is not running.
*/
@property(nonatomic, readonly, copy, nullable) NSString* isolateId;
/**
* Whether or not GPU calls are allowed.
*
* Typically this is set when the app is backgrounded and foregrounded.
*/
@property(nonatomic, assign) BOOL isGpuDisabled;
@end
NS_ASSUME_NONNULL_END
#endif // FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_HEADERS_FLUTTERENGINE_H_
@@ -0,0 +1,115 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_HEADERS_FLUTTERENGINEGROUP_H_
#define FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_HEADERS_FLUTTERENGINEGROUP_H_
#import <Foundation/Foundation.h>
#import "FlutterEngine.h"
NS_ASSUME_NONNULL_BEGIN
/** Options that control how a FlutterEngine should be created. */
FLUTTER_DARWIN_EXPORT
@interface FlutterEngineGroupOptions : NSObject
/**
* The name of a top-level function from a Dart library. If this is FlutterDefaultDartEntrypoint
* (or nil); this will default to `main()`. If it is not the app's main() function, that function
* must be decorated with `@pragma(vm:entry-point)` to ensure themethod is not tree-shaken by the
* Dart compiler.
*/
@property(nonatomic, copy, nullable) NSString* entrypoint;
/**
* The URI of the Dart library which contains the entrypoint method. If nil, this will default to
* the same library as the `main()` function in the Dart program.
*/
@property(nonatomic, copy, nullable) NSString* libraryURI;
/**
* The name of the initial Flutter `Navigator` `Route` to load. If this is
* FlutterDefaultInitialRoute (or nil), it will default to the "/" route.
*/
@property(nonatomic, copy, nullable) NSString* initialRoute;
/**
* Arguments passed as a list of string to Dart's entrypoint function.
*/
@property(nonatomic, retain, nullable) NSArray<NSString*>* entrypointArgs;
@end
/**
* Represents a collection of FlutterEngines who share resources which allows
* them to be created with less time const and occupy less memory than just
* creating multiple FlutterEngines.
*
* Deleting a FlutterEngineGroup doesn't invalidate existing FlutterEngines, but
* it eliminates the possibility to create more FlutterEngines in that group.
*
* @warning This class is a work-in-progress and may change.
* @see https://github.com/flutter/flutter/issues/72009
*/
FLUTTER_DARWIN_EXPORT
@interface FlutterEngineGroup : NSObject
- (instancetype)init NS_UNAVAILABLE;
/**
* Initialize a new FlutterEngineGroup.
*
* @param name The name that will present in the threads shared across the
* engines in this group.
* @param project The `FlutterDartProject` that all FlutterEngines in this group
* will be executing.
*/
- (instancetype)initWithName:(NSString*)name
project:(nullable FlutterDartProject*)project NS_DESIGNATED_INITIALIZER;
/**
* Creates a running `FlutterEngine` that shares components with this group.
*
* @param entrypoint The name of a top-level function from a Dart library. If this is
* FlutterDefaultDartEntrypoint (or nil); this will default to `main()`. If it is not the app's
* main() function, that function must be decorated with `@pragma(vm:entry-point)` to ensure the
* method is not tree-shaken by the Dart compiler.
* @param libraryURI The URI of the Dart library which contains the entrypoint method. IF nil,
* this will default to the same library as the `main()` function in the Dart program.
*
* @see FlutterEngineGroup
*/
- (FlutterEngine*)makeEngineWithEntrypoint:(nullable NSString*)entrypoint
libraryURI:(nullable NSString*)libraryURI;
/**
* Creates a running `FlutterEngine` that shares components with this group.
*
* @param entrypoint The name of a top-level function from a Dart library. If this is
* FlutterDefaultDartEntrypoint (or nil); this will default to `main()`. If it is not the app's
* main() function, that function must be decorated with `@pragma(vm:entry-point)` to ensure the
* method is not tree-shaken by the Dart compiler.
* @param libraryURI The URI of the Dart library which contains the entrypoint method. IF nil,
* this will default to the same library as the `main()` function in the Dart program.
* @param initialRoute The name of the initial Flutter `Navigator` `Route` to load. If this is
* FlutterDefaultInitialRoute (or nil), it will default to the "/" route.
*
* @see FlutterEngineGroup
*/
- (FlutterEngine*)makeEngineWithEntrypoint:(nullable NSString*)entrypoint
libraryURI:(nullable NSString*)libraryURI
initialRoute:(nullable NSString*)initialRoute;
/**
* Creates a running `FlutterEngine` that shares components with this group.
*
* @param options Options that control how a FlutterEngine should be created.
*
* @see FlutterEngineGroupOptions
*/
- (FlutterEngine*)makeEngineWithOptions:(nullable FlutterEngineGroupOptions*)options;
@end
NS_ASSUME_NONNULL_END
#endif // FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_HEADERS_FLUTTERENGINEGROUP_H_
@@ -0,0 +1,97 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_HEADERS_FLUTTERHEADLESSDARTRUNNER_H_
#define FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_HEADERS_FLUTTERHEADLESSDARTRUNNER_H_
#import <Foundation/Foundation.h>
#import "FlutterBinaryMessenger.h"
#import "FlutterDartProject.h"
#import "FlutterEngine.h"
#import "FlutterMacros.h"
/**
* A callback for when FlutterHeadlessDartRunner has attempted to start a Dart
* Isolate in the background.
*
* @param success YES if the Isolate was started and run successfully, NO
* otherwise.
*/
typedef void (^FlutterHeadlessDartRunnerCallback)(BOOL success);
/**
* The deprecated FlutterHeadlessDartRunner runs Flutter Dart code with a null rasterizer,
* and no native drawing surface. It is appropriate for use in running Dart
* code e.g. in the background from a plugin.
*
* Most callers should prefer using `FlutterEngine` directly; this interface exists
* for legacy support.
*/
FLUTTER_DARWIN_EXPORT
FLUTTER_DEPRECATED("FlutterEngine should be used rather than FlutterHeadlessDartRunner")
@interface FlutterHeadlessDartRunner : FlutterEngine
/**
* Initialize this FlutterHeadlessDartRunner with a `FlutterDartProject`.
*
* If the FlutterDartProject is not specified, the FlutterHeadlessDartRunner will attempt to locate
* the project in a default location.
*
* A newly initialized engine will not run the `FlutterDartProject` until either
* `-runWithEntrypoint:` or `-runWithEntrypoint:libraryURI` is called.
*
* @param labelPrefix The label prefix used to identify threads for this instance. Should
* be unique across FlutterEngine instances
* @param projectOrNil The `FlutterDartProject` to run.
*/
- (instancetype)initWithName:(NSString*)labelPrefix project:(FlutterDartProject*)projectOrNil;
/**
* Initialize this FlutterHeadlessDartRunner with a `FlutterDartProject`.
*
* If the FlutterDartProject is not specified, the FlutterHeadlessDartRunner will attempt to locate
* the project in a default location.
*
* A newly initialized engine will not run the `FlutterDartProject` until either
* `-runWithEntrypoint:` or `-runWithEntrypoint:libraryURI` is called.
*
* @param labelPrefix The label prefix used to identify threads for this instance. Should
* be unique across FlutterEngine instances
* @param projectOrNil The `FlutterDartProject` to run.
* @param allowHeadlessExecution Must be set to `YES`.
*/
- (instancetype)initWithName:(NSString*)labelPrefix
project:(FlutterDartProject*)projectOrNil
allowHeadlessExecution:(BOOL)allowHeadlessExecution;
/**
* Initialize this FlutterHeadlessDartRunner with a `FlutterDartProject`.
*
* If the FlutterDartProject is not specified, the FlutterHeadlessDartRunner will attempt to locate
* the project in a default location.
*
* A newly initialized engine will not run the `FlutterDartProject` until either
* `-runWithEntrypoint:` or `-runWithEntrypoint:libraryURI` is called.
*
* @param labelPrefix The label prefix used to identify threads for this instance. Should
* be unique across FlutterEngine instances
* @param projectOrNil The `FlutterDartProject` to run.
* @param allowHeadlessExecution Must be set to `YES`.
* @param restorationEnabled Must be set to `NO`.
*/
- (instancetype)initWithName:(NSString*)labelPrefix
project:(FlutterDartProject*)projectOrNil
allowHeadlessExecution:(BOOL)allowHeadlessExecution
restorationEnabled:(BOOL)restorationEnabled NS_DESIGNATED_INITIALIZER;
/**
* Not recommended for use - will initialize with a default label ("io.flutter.headless")
* and the default FlutterDartProject.
*/
- (instancetype)init;
@end
#endif // FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_HEADERS_FLUTTERHEADLESSDARTRUNNER_H_
@@ -0,0 +1,48 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_SHELL_PLATFORM_DARWIN_COMMON_FRAMEWORK_HEADERS_FLUTTERMACROS_H_
#define FLUTTER_SHELL_PLATFORM_DARWIN_COMMON_FRAMEWORK_HEADERS_FLUTTERMACROS_H_
#if defined(FLUTTER_FRAMEWORK)
#define FLUTTER_DARWIN_EXPORT __attribute__((visibility("default")))
#else // defined(FLUTTER_SDK)
#define FLUTTER_DARWIN_EXPORT
#endif // defined(FLUTTER_SDK)
#ifndef NS_ASSUME_NONNULL_BEGIN
#define NS_ASSUME_NONNULL_BEGIN _Pragma("clang assume_nonnull begin")
#define NS_ASSUME_NONNULL_END _Pragma("clang assume_nonnull end")
#endif // defined(NS_ASSUME_NONNULL_BEGIN)
/**
* Indicates that the API has been deprecated for the specified reason. Code
* that uses the deprecated API will continue to work as before. However, the
* API will soon become unavailable and users are encouraged to immediately take
* the appropriate action mentioned in the deprecation message and the BREAKING
* CHANGES section present in the Flutter.h umbrella header.
*/
#define FLUTTER_DEPRECATED(msg) __attribute__((__deprecated__(msg)))
/**
* Indicates that the previously deprecated API is now unavailable. Code that
* uses the API will not work and the declaration of the API is only a stub
* meant to display the given message detailing the actions for the user to take
* immediately.
*/
#define FLUTTER_UNAVAILABLE(msg) __attribute__((__unavailable__(msg)))
#if __has_feature(objc_arc)
#define FLUTTER_ASSERT_ARC
#define FLUTTER_ASSERT_NOT_ARC #error ARC must be disabled !
#else
#define FLUTTER_ASSERT_ARC #error ARC must be enabled !
#define FLUTTER_ASSERT_NOT_ARC
#endif
#endif // FLUTTER_SHELL_PLATFORM_DARWIN_COMMON_FRAMEWORK_HEADERS_FLUTTERMACROS_H_
@@ -0,0 +1,56 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_HEADERS_FLUTTERPLATFORMVIEWS_H_
#define FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_HEADERS_FLUTTERPLATFORMVIEWS_H_
#import <UIKit/UIKit.h>
#import "FlutterCodecs.h"
#import "FlutterMacros.h"
NS_ASSUME_NONNULL_BEGIN
/**
* Wraps a `UIView` for embedding in the Flutter hierarchy
*/
@protocol FlutterPlatformView <NSObject>
/**
* Returns a reference to the `UIView` that is wrapped by this `FlutterPlatformView`.
*/
- (UIView*)view;
@end
FLUTTER_DARWIN_EXPORT
@protocol FlutterPlatformViewFactory <NSObject>
/**
* Create a `FlutterPlatformView`.
*
* Implemented by iOS code that expose a `UIView` for embedding in a Flutter app.
*
* The implementation of this method should create a new `UIView` and return it.
*
* @param frame The rectangle for the newly created `UIView` measured in points.
* @param viewId A unique identifier for this `UIView`.
* @param args Parameters for creating the `UIView` sent from the Dart side of the Flutter app.
* If `createArgsCodec` is not implemented, or if no creation arguments were sent from the Dart
* code, this will be null. Otherwise this will be the value sent from the Dart code as decoded by
* `createArgsCodec`.
*/
- (NSObject<FlutterPlatformView>*)createWithFrame:(CGRect)frame
viewIdentifier:(int64_t)viewId
arguments:(id _Nullable)args;
/**
* Returns the `FlutterMessageCodec` for decoding the args parameter of `createWithFrame`.
*
* Only needs to be implemented if `createWithFrame` needs an arguments parameter.
*/
@optional
- (NSObject<FlutterMessageCodec>*)createArgsCodec;
@end
NS_ASSUME_NONNULL_END
#endif // FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_HEADERS_FLUTTERPLATFORMVIEWS_H_
@@ -0,0 +1,448 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_HEADERS_FLUTTERPLUGIN_H_
#define FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_HEADERS_FLUTTERPLUGIN_H_
#import <UIKit/UIKit.h>
#import <UserNotifications/UNUserNotificationCenter.h>
#import "FlutterBinaryMessenger.h"
#import "FlutterChannels.h"
#import "FlutterCodecs.h"
#import "FlutterPlatformViews.h"
#import "FlutterTexture.h"
NS_ASSUME_NONNULL_BEGIN
@protocol FlutterPluginRegistrar;
@protocol FlutterPluginRegistry;
#pragma mark -
/**
* Protocol for listener of events from the UIApplication, typically a FlutterPlugin.
*/
@protocol FlutterApplicationLifeCycleDelegate <UNUserNotificationCenterDelegate>
@optional
/**
* Called if this has been registered for `UIApplicationDelegate` callbacks.
*
* @return `NO` if this vetos application launch.
*/
- (BOOL)application:(UIApplication*)application
didFinishLaunchingWithOptions:(NSDictionary*)launchOptions;
/**
* Called if this has been registered for `UIApplicationDelegate` callbacks.
*
* @return `NO` if this vetos application launch.
*/
- (BOOL)application:(UIApplication*)application
willFinishLaunchingWithOptions:(NSDictionary*)launchOptions;
/**
* Called if this has been registered for `UIApplicationDelegate` callbacks.
*/
- (void)applicationDidBecomeActive:(UIApplication*)application;
/**
* Called if this has been registered for `UIApplicationDelegate` callbacks.
*/
- (void)applicationWillResignActive:(UIApplication*)application;
/**
* Called if this has been registered for `UIApplicationDelegate` callbacks.
*/
- (void)applicationDidEnterBackground:(UIApplication*)application;
/**
* Called if this has been registered for `UIApplicationDelegate` callbacks.
*/
- (void)applicationWillEnterForeground:(UIApplication*)application;
/**
Called if this has been registered for `UIApplicationDelegate` callbacks.
*/
- (void)applicationWillTerminate:(UIApplication*)application;
/**
* Called if this has been registered for `UIApplicationDelegate` callbacks.
*/
- (void)application:(UIApplication*)application
didRegisterUserNotificationSettings:(UIUserNotificationSettings*)notificationSettings
API_DEPRECATED(
"See -[UIApplicationDelegate application:didRegisterUserNotificationSettings:] deprecation",
ios(8.0, 10.0));
/**
* Called if this has been registered for `UIApplicationDelegate` callbacks.
*/
- (void)application:(UIApplication*)application
didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken;
/**
* Called if this has been registered for `UIApplicationDelegate` callbacks.
*/
- (void)application:(UIApplication*)application
didFailToRegisterForRemoteNotificationsWithError:(NSError*)error;
/**
* Called if this has been registered for `UIApplicationDelegate` callbacks.
*
* @return `YES` if this handles the request.
*/
- (BOOL)application:(UIApplication*)application
didReceiveRemoteNotification:(NSDictionary*)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler;
/**
* Calls all plugins registered for `UIApplicationDelegate` callbacks.
*/
- (void)application:(UIApplication*)application
didReceiveLocalNotification:(UILocalNotification*)notification
API_DEPRECATED(
"See -[UIApplicationDelegate application:didReceiveLocalNotification:] deprecation",
ios(4.0, 10.0));
/**
* Called if this has been registered for `UIApplicationDelegate` callbacks.
*
* @return `YES` if this handles the request.
*/
- (BOOL)application:(UIApplication*)application
openURL:(NSURL*)url
options:(NSDictionary<UIApplicationOpenURLOptionsKey, id>*)options;
/**
* Called if this has been registered for `UIApplicationDelegate` callbacks.
*
* @return `YES` if this handles the request.
*/
- (BOOL)application:(UIApplication*)application handleOpenURL:(NSURL*)url;
/**
* Called if this has been registered for `UIApplicationDelegate` callbacks.
*
* @return `YES` if this handles the request.
*/
- (BOOL)application:(UIApplication*)application
openURL:(NSURL*)url
sourceApplication:(NSString*)sourceApplication
annotation:(id)annotation;
/**
* Called if this has been registered for `UIApplicationDelegate` callbacks.
*
* @return `YES` if this handles the request.
*/
- (BOOL)application:(UIApplication*)application
performActionForShortcutItem:(UIApplicationShortcutItem*)shortcutItem
completionHandler:(void (^)(BOOL succeeded))completionHandler
API_AVAILABLE(ios(9.0));
/**
* Called if this has been registered for `UIApplicationDelegate` callbacks.
*
* @return `YES` if this handles the request.
*/
- (BOOL)application:(UIApplication*)application
handleEventsForBackgroundURLSession:(nonnull NSString*)identifier
completionHandler:(nonnull void (^)(void))completionHandler;
/**
* Called if this has been registered for `UIApplicationDelegate` callbacks.
*
* @return `YES` if this handles the request.
*/
- (BOOL)application:(UIApplication*)application
performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler;
/**
* Called if this has been registered for `UIApplicationDelegate` callbacks.
*
* @return `YES` if this handles the request.
*/
- (BOOL)application:(UIApplication*)application
continueUserActivity:(NSUserActivity*)userActivity
restorationHandler:(void (^)(NSArray*))restorationHandler;
@end
#pragma mark -
/**
* A plugin registration callback.
*
* Used for registering plugins with additional instances of
* `FlutterPluginRegistry`.
*
* @param registry The registry to register plugins with.
*/
typedef void (*FlutterPluginRegistrantCallback)(NSObject<FlutterPluginRegistry>* registry);
#pragma mark -
/**
* Implemented by the iOS part of a Flutter plugin.
*
* Defines a set of optional callback methods and a method to set up the plugin
* and register it to be called by other application components.
*/
@protocol FlutterPlugin <NSObject, FlutterApplicationLifeCycleDelegate>
@required
/**
* Registers this plugin using the context information and callback registration
* methods exposed by the given registrar.
*
* The registrar is obtained from a `FlutterPluginRegistry` which keeps track of
* the identity of registered plugins and provides basic support for cross-plugin
* coordination.
*
* The caller of this method, a plugin registrant, is usually autogenerated by
* Flutter tooling based on declared plugin dependencies. The generated registrant
* asks the registry for a registrar for each plugin, and calls this method to
* allow the plugin to initialize itself and register callbacks with application
* objects available through the registrar protocol.
*
* @param registrar A helper providing application context and methods for
* registering callbacks.
*/
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar;
@optional
/**
* Set a callback for registering plugins to an additional `FlutterPluginRegistry`,
* including headless `FlutterEngine` instances.
*
* This method is typically called from within an application's `AppDelegate` at
* startup to allow for plugins which create additional `FlutterEngine` instances
* to register the application's plugins.
*
* @param callback A callback for registering some set of plugins with a
* `FlutterPluginRegistry`.
*/
+ (void)setPluginRegistrantCallback:(FlutterPluginRegistrantCallback)callback;
@optional
/**
* Called if this plugin has been registered to receive `FlutterMethodCall`s.
*
* @param call The method call command object.
* @param result A callback for submitting the result of the call.
*/
- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result;
@optional
/**
* Called when a plugin is being removed from a `FlutterEngine`, which is
* usually the result of the `FlutterEngine` being deallocated. This method
* provides the opportunity to do necessary cleanup.
*
* You will only receive this method if you registered your plugin instance with
* the `FlutterEngine` via `-[FlutterPluginRegistry publish:]`.
*
* @param registrar The registrar that was used to publish the plugin.
*
*/
- (void)detachFromEngineForRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar;
@end
#pragma mark -
/**
* How the UIGestureRecognizers of a platform view are blocked.
*
* UIGestureRecognizers of platform views can be blocked based on decisions made by the
* Flutter Framework (e.g. When an interact-able widget is covering the platform view).
*/
typedef enum {
// NOLINTBEGIN(readability-identifier-naming)
/**
* Flutter blocks all the UIGestureRecognizers on the platform view as soon as it
* decides they should be blocked.
*
* With this policy, only the `touchesBegan` method for all the UIGestureRecognizers is guaranteed
* to be called.
*/
FlutterPlatformViewGestureRecognizersBlockingPolicyEager,
/**
* Flutter blocks the platform view's UIGestureRecognizers from recognizing only after
* touchesEnded was invoked.
*
* This results in the platform view's UIGestureRecognizers seeing the entire touch sequence,
* but never recognizing the gesture (and never invoking actions).
*/
FlutterPlatformViewGestureRecognizersBlockingPolicyWaitUntilTouchesEnded,
// NOLINTEND(readability-identifier-naming)
} FlutterPlatformViewGestureRecognizersBlockingPolicy;
#pragma mark -
/**
* Registration context for a single `FlutterPlugin`, providing a one stop shop
* for the plugin to access contextual information and register callbacks for
* various application events.
*
* Registrars are obtained from a `FlutterPluginRegistry` which keeps track of
* the identity of registered plugins and provides basic support for cross-plugin
* coordination.
*/
@protocol FlutterPluginRegistrar <NSObject>
/**
* Returns a `FlutterBinaryMessenger` for creating Dart/iOS communication
* channels to be used by the plugin.
*
* @return The messenger.
*/
- (NSObject<FlutterBinaryMessenger>*)messenger;
/**
* Returns a `FlutterTextureRegistry` for registering textures
* provided by the plugin.
*
* @return The texture registry.
*/
- (NSObject<FlutterTextureRegistry>*)textures;
/**
* Registers a `FlutterPlatformViewFactory` for creation of platform views.
*
* Plugins expose `UIView` for embedding in Flutter apps by registering a view factory.
*
* @param factory The view factory that will be registered.
* @param factoryId A unique identifier for the factory, the Dart code of the Flutter app can use
* this identifier to request creation of a `UIView` by the registered factory.
*/
- (void)registerViewFactory:(NSObject<FlutterPlatformViewFactory>*)factory
withId:(NSString*)factoryId;
/**
* Registers a `FlutterPlatformViewFactory` for creation of platform views.
*
* Plugins can expose a `UIView` for embedding in Flutter apps by registering a view factory.
*
* @param factory The view factory that will be registered.
* @param factoryId A unique identifier for the factory, the Dart code of the Flutter app can use
* this identifier to request creation of a `UIView` by the registered factory.
* @param gestureRecognizersBlockingPolicy How UIGestureRecognizers on the platform views are
* blocked.
*
*/
- (void)registerViewFactory:(NSObject<FlutterPlatformViewFactory>*)factory
withId:(NSString*)factoryId
gestureRecognizersBlockingPolicy:
(FlutterPlatformViewGestureRecognizersBlockingPolicy)gestureRecognizersBlockingPolicy;
/**
* Publishes a value for external use of the plugin.
*
* Plugins may publish a single value, such as an instance of the
* plugin's main class, for situations where external control or
* interaction is needed.
*
* The published value will be available from the `FlutterPluginRegistry`.
* Repeated calls overwrite any previous publication.
*
* @param value The value to be published.
*/
- (void)publish:(NSObject*)value;
/**
* Registers the plugin as a receiver of incoming method calls from the Dart side
* on the specified `FlutterMethodChannel`.
*
* @param delegate The receiving object, such as the plugin's main class.
* @param channel The channel
*/
- (void)addMethodCallDelegate:(NSObject<FlutterPlugin>*)delegate
channel:(FlutterMethodChannel*)channel;
/**
* Registers the plugin as a receiver of `UIApplicationDelegate` calls.
*
* @param delegate The receiving object, such as the plugin's main class.
*/
- (void)addApplicationDelegate:(NSObject<FlutterPlugin>*)delegate
NS_EXTENSION_UNAVAILABLE_IOS("Disallowed in plugins used in app extensions");
/**
* Returns the file name for the given asset.
* The returned file name can be used to access the asset in the application's main bundle.
*
* @param asset The name of the asset. The name can be hierarchical.
* @return the file name to be used for lookup in the main bundle.
*/
- (NSString*)lookupKeyForAsset:(NSString*)asset;
/**
* Returns the file name for the given asset which originates from the specified package.
* The returned file name can be used to access the asset in the application's main bundle.
*
*
* @param asset The name of the asset. The name can be hierarchical.
* @param package The name of the package from which the asset originates.
* @return the file name to be used for lookup in the main bundle.
*/
- (NSString*)lookupKeyForAsset:(NSString*)asset fromPackage:(NSString*)package;
@end
#pragma mark -
/**
* A registry of Flutter iOS plugins.
*
* Plugins are identified by unique string keys, typically the name of the
* plugin's main class. The registry tracks plugins by this key, mapping it to
* a value published by the plugin during registration, if any. This provides a
* very basic means of cross-plugin coordination with loose coupling between
* unrelated plugins.
*
* Plugins typically need contextual information and the ability to register
* callbacks for various application events. To keep the API of the registry
* focused, these facilities are not provided directly by the registry, but by
* a `FlutterPluginRegistrar`, created by the registry in exchange for the unique
* key of the plugin.
*
* There is no implied connection between the registry and the registrar.
* Specifically, callbacks registered by the plugin via the registrar may be
* relayed directly to the underlying iOS application objects.
*/
@protocol FlutterPluginRegistry <NSObject>
/**
* Returns a registrar for registering a plugin.
*
* @param pluginKey The unique key identifying the plugin.
*/
- (nullable NSObject<FlutterPluginRegistrar>*)registrarForPlugin:(NSString*)pluginKey;
/**
* Returns whether the specified plugin has been registered.
*
* @param pluginKey The unique key identifying the plugin.
* @return `YES` if `registrarForPlugin` has been called with `pluginKey`.
*/
- (BOOL)hasPlugin:(NSString*)pluginKey;
/**
* Returns a value published by the specified plugin.
*
* @param pluginKey The unique key identifying the plugin.
* @return An object published by the plugin, if any. Will be `NSNull` if
* nothing has been published. Will be `nil` if the plugin has not been
* registered.
*/
- (nullable NSObject*)valuePublishedByPlugin:(NSString*)pluginKey;
@end
#pragma mark -
/**
* Implement this in the `UIAppDelegate` of your app to enable Flutter plugins to register
* themselves to the application life cycle events.
*
* For plugins to receive events from `UNUserNotificationCenter`, register this as the
* `UNUserNotificationCenterDelegate`.
*/
@protocol FlutterAppLifeCycleProvider <UNUserNotificationCenterDelegate>
/**
* Called when registering a new `FlutterApplicaitonLifeCycleDelegate`.
*
* See also: `-[FlutterAppDelegate addApplicationLifeCycleDelegate:]`
*/
- (void)addApplicationLifeCycleDelegate:(NSObject<FlutterApplicationLifeCycleDelegate>*)delegate;
@end
NS_ASSUME_NONNULL_END
#endif // FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_HEADERS_FLUTTERPLUGIN_H_
@@ -0,0 +1,148 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_HEADERS_FLUTTERPLUGINAPPLIFECYCLEDELEGATE_H_
#define FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_HEADERS_FLUTTERPLUGINAPPLIFECYCLEDELEGATE_H_
#import "FlutterPlugin.h"
NS_ASSUME_NONNULL_BEGIN
/**
* Propagates `UIAppDelegate` callbacks to registered plugins.
*/
FLUTTER_DARWIN_EXPORT
@interface FlutterPluginAppLifeCycleDelegate : NSObject <UNUserNotificationCenterDelegate>
/**
* Registers `delegate` to receive life cycle callbacks via this FlutterPluginAppLifeCycleDelegate
* as long as it is alive.
*
* `delegate` will only be referenced weakly.
*/
- (void)addDelegate:(NSObject<FlutterApplicationLifeCycleDelegate>*)delegate;
/**
* Calls all plugins registered for `UIApplicationDelegate` callbacks.
*
* @return `NO` if any plugin vetos application launch.
*/
- (BOOL)application:(UIApplication*)application
didFinishLaunchingWithOptions:(NSDictionary*)launchOptions;
/**
* Calls all plugins registered for `UIApplicationDelegate` callbacks.
*
* @return `NO` if any plugin vetos application launch.
*/
- (BOOL)application:(UIApplication*)application
willFinishLaunchingWithOptions:(NSDictionary*)launchOptions;
/**
* Called if this plugin has been registered for `UIApplicationDelegate` callbacks.
*/
- (void)application:(UIApplication*)application
didRegisterUserNotificationSettings:(UIUserNotificationSettings*)notificationSettings
API_DEPRECATED(
"See -[UIApplicationDelegate application:didRegisterUserNotificationSettings:] deprecation",
ios(8.0, 10.0));
/**
* Calls all plugins registered for `UIApplicationDelegate` callbacks.
*/
- (void)application:(UIApplication*)application
didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken;
/**
* Calls all plugins registered for `UIApplicationDelegate` callbacks.
*/
- (void)application:(UIApplication*)application
didFailToRegisterForRemoteNotificationsWithError:(NSError*)error;
/**
* Calls all plugins registered for `UIApplicationDelegate` callbacks.
*/
- (void)application:(UIApplication*)application
didReceiveRemoteNotification:(NSDictionary*)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler;
/**
* Calls all plugins registered for `UIApplicationDelegate` callbacks.
*/
- (void)application:(UIApplication*)application
didReceiveLocalNotification:(UILocalNotification*)notification
API_DEPRECATED(
"See -[UIApplicationDelegate application:didReceiveLocalNotification:] deprecation",
ios(4.0, 10.0));
/**
* Calls all plugins registered for `UIApplicationDelegate` callbacks in order of registration until
* some plugin handles the request.
*
* @return `YES` if any plugin handles the request.
*/
- (BOOL)application:(UIApplication*)application
openURL:(NSURL*)url
options:(NSDictionary<UIApplicationOpenURLOptionsKey, id>*)options;
/**
* Calls all plugins registered for `UIApplicationDelegate` callbacks in order of registration until
* some plugin handles the request.
*
* @return `YES` if any plugin handles the request.
*/
- (BOOL)application:(UIApplication*)application handleOpenURL:(NSURL*)url;
/**
* Calls all plugins registered for `UIApplicationDelegate` callbacks in order of registration until
* some plugin handles the request.
*
* @return `YES` if any plugin handles the request.
*/
- (BOOL)application:(UIApplication*)application
openURL:(NSURL*)url
sourceApplication:(NSString*)sourceApplication
annotation:(id)annotation;
/**
* Calls all plugins registered for `UIApplicationDelegate` callbacks.
*/
- (void)application:(UIApplication*)application
performActionForShortcutItem:(UIApplicationShortcutItem*)shortcutItem
completionHandler:(void (^)(BOOL succeeded))completionHandler
API_AVAILABLE(ios(9.0));
/**
* Calls all plugins registered for `UIApplicationDelegate` callbacks in order of registration until
* some plugin handles the request.
*
* @return `YES` if any plugin handles the request.
*/
- (BOOL)application:(UIApplication*)application
handleEventsForBackgroundURLSession:(nonnull NSString*)identifier
completionHandler:(nonnull void (^)(void))completionHandler;
/**
* Calls all plugins registered for `UIApplicationDelegate` callbacks in order of registration until
* some plugin handles the request.
*
* @returns `YES` if any plugin handles the request.
*/
- (BOOL)application:(UIApplication*)application
performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler;
/**
* Calls all plugins registered for `UIApplicationDelegate` callbacks in order of registration until
* some plugin handles the request.
*
* @return `YES` if any plugin handles the request.
*/
- (BOOL)application:(UIApplication*)application
continueUserActivity:(NSUserActivity*)userActivity
restorationHandler:(void (^)(NSArray*))restorationHandler;
@end
NS_ASSUME_NONNULL_END
#endif // FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_HEADERS_FLUTTERPLUGINAPPLIFECYCLEDELEGATE_H_
@@ -0,0 +1,62 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_SHELL_PLATFORM_DARWIN_COMMON_FRAMEWORK_HEADERS_FLUTTERTEXTURE_H_
#define FLUTTER_SHELL_PLATFORM_DARWIN_COMMON_FRAMEWORK_HEADERS_FLUTTERTEXTURE_H_
#import <CoreMedia/CoreMedia.h>
#import <Foundation/Foundation.h>
#import "FlutterMacros.h"
NS_ASSUME_NONNULL_BEGIN
FLUTTER_DARWIN_EXPORT
/**
* Represents a texture that can be shared with Flutter.
*
* See also: https://github.com/flutter/plugins/tree/master/packages/camera
*/
@protocol FlutterTexture <NSObject>
/** Copy the contents of the texture into a `CVPixelBuffer`. */
- (CVPixelBufferRef _Nullable)copyPixelBuffer;
/**
* Called when the texture is unregistered.
*
* Called on the raster thread.
*/
@optional
- (void)onTextureUnregistered:(NSObject<FlutterTexture>*)texture;
@end
FLUTTER_DARWIN_EXPORT
/**
* A collection of registered `FlutterTexture`'s.
*/
@protocol FlutterTextureRegistry <NSObject>
/**
* Registers a `FlutterTexture` for usage in Flutter and returns an id that can be used to reference
* that texture when calling into Flutter with channels. Textures must be registered on the
* platform thread. On success returns the pointer to the registered texture, else returns 0.
*/
- (int64_t)registerTexture:(NSObject<FlutterTexture>*)texture;
/**
* Notifies Flutter that the content of the previously registered texture has been updated.
*
* This will trigger a call to `-[FlutterTexture copyPixelBuffer]` on the raster thread.
*/
- (void)textureFrameAvailable:(int64_t)textureId;
/**
* Unregisters a `FlutterTexture` that has previously regeistered with `registerTexture:`. Textures
* must be unregistered on the platform thread.
*
* @param textureId The result that was previously returned from `registerTexture:`.
*/
- (void)unregisterTexture:(int64_t)textureId;
@end
NS_ASSUME_NONNULL_END
#endif // FLUTTER_SHELL_PLATFORM_DARWIN_COMMON_FRAMEWORK_HEADERS_FLUTTERTEXTURE_H_
@@ -0,0 +1,260 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_HEADERS_FLUTTERVIEWCONTROLLER_H_
#define FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_HEADERS_FLUTTERVIEWCONTROLLER_H_
#import <UIKit/UIKit.h>
#include <sys/cdefs.h>
#import "FlutterBinaryMessenger.h"
#import "FlutterDartProject.h"
#import "FlutterEngine.h"
#import "FlutterMacros.h"
#import "FlutterPlugin.h"
#import "FlutterTexture.h"
NS_ASSUME_NONNULL_BEGIN
@class FlutterEngine;
/**
* The name used for semantic update notifications via `NSNotificationCenter`.
*
* The object passed as the sender is the `FlutterViewController` associated
* with the update.
*/
FLUTTER_DARWIN_EXPORT
// NOLINTNEXTLINE(readability-identifier-naming)
extern NSNotificationName const FlutterSemanticsUpdateNotification;
/**
* A `UIViewController` implementation for Flutter views.
*
* Dart execution, channel communication, texture registration, and plugin registration are all
* handled by `FlutterEngine`. Calls on this class to those members all proxy through to the
* `FlutterEngine` attached FlutterViewController.
*
* A FlutterViewController can be initialized either with an already-running `FlutterEngine` via the
* `initWithEngine:` initializer, or it can be initialized with a `FlutterDartProject` that will be
* used to implicitly spin up a new `FlutterEngine`. Creating a `FlutterEngine` before showing a
* FlutterViewController can be used to pre-initialize the Dart VM and to prepare the isolate in
* order to reduce the latency to the first rendered frame. See
* https://flutter.dev/docs/development/add-to-app/performance for more details on loading
* latency.
*
* Holding a `FlutterEngine` independently of FlutterViewControllers can also be used to not to lose
* Dart-related state and asynchronous tasks when navigating back and forth between a
* FlutterViewController and other `UIViewController`s.
*/
FLUTTER_DARWIN_EXPORT
#ifdef __IPHONE_13_4
@interface FlutterViewController
: UIViewController <FlutterTextureRegistry, FlutterPluginRegistry, UIGestureRecognizerDelegate>
#else
@interface FlutterViewController : UIViewController <FlutterTextureRegistry, FlutterPluginRegistry>
#endif
/**
* Initializes this FlutterViewController with the specified `FlutterEngine`.
*
* The initialized viewcontroller will attach itself to the engine as part of this process.
*
* @param engine The `FlutterEngine` instance to attach to. Cannot be nil.
* @param nibName The NIB name to initialize this UIViewController with.
* @param nibBundle The NIB bundle.
*/
- (instancetype)initWithEngine:(FlutterEngine*)engine
nibName:(nullable NSString*)nibName
bundle:(nullable NSBundle*)nibBundle NS_DESIGNATED_INITIALIZER;
/**
* Initializes a new FlutterViewController and `FlutterEngine` with the specified
* `FlutterDartProject`.
*
* This will implicitly create a new `FlutterEngine` which is retrievable via the `engine` property
* after initialization.
*
* @param project The `FlutterDartProject` to initialize the `FlutterEngine` with.
* @param nibName The NIB name to initialize this UIViewController with.
* @param nibBundle The NIB bundle.
*/
- (instancetype)initWithProject:(nullable FlutterDartProject*)project
nibName:(nullable NSString*)nibName
bundle:(nullable NSBundle*)nibBundle NS_DESIGNATED_INITIALIZER;
/**
* Initializes a new FlutterViewController and `FlutterEngine` with the specified
* `FlutterDartProject` and `initialRoute`.
*
* This will implicitly create a new `FlutterEngine` which is retrievable via the `engine` property
* after initialization.
*
* @param project The `FlutterDartProject` to initialize the `FlutterEngine` with.
* @param initialRoute The initial `Navigator` route to load.
* @param nibName The NIB name to initialize this UIViewController with.
* @param nibBundle The NIB bundle.
*/
- (instancetype)initWithProject:(nullable FlutterDartProject*)project
initialRoute:(nullable NSString*)initialRoute
nibName:(nullable NSString*)nibName
bundle:(nullable NSBundle*)nibBundle NS_DESIGNATED_INITIALIZER;
/**
* Initializer that is called from loading a FlutterViewController from a XIB.
*
* See also:
* https://developer.apple.com/documentation/foundation/nscoding/1416145-initwithcoder?language=objc
*/
- (instancetype)initWithCoder:(NSCoder*)aDecoder NS_DESIGNATED_INITIALIZER;
/**
* Registers a callback that will be invoked when the Flutter view has been rendered.
* The callback will be fired only once.
*
* Replaces an existing callback. Use a `nil` callback to unregister the existing one.
*/
- (void)setFlutterViewDidRenderCallback:(void (^)(void))callback;
/**
* Returns the file name for the given asset.
* The returned file name can be used to access the asset in the application's
* main bundle.
*
* @param asset The name of the asset. The name can be hierarchical.
* @return The file name to be used for lookup in the main bundle.
*/
- (NSString*)lookupKeyForAsset:(NSString*)asset;
/**
* Returns the file name for the given asset which originates from the specified
* package.
* The returned file name can be used to access the asset in the application's
* main bundle.
*
* @param asset The name of the asset. The name can be hierarchical.
* @param package The name of the package from which the asset originates.
* @return The file name to be used for lookup in the main bundle.
*/
- (NSString*)lookupKeyForAsset:(NSString*)asset fromPackage:(NSString*)package;
/**
* Deprecated API to set initial route.
*
* Attempts to set the first route that the Flutter app shows if the Flutter
* runtime hasn't yet started. The default is "/".
*
* This method must be called immediately after `initWithProject` and has no
* effect when using `initWithEngine` if the `FlutterEngine` has already been
* run.
*
* Setting this after the Flutter started running has no effect. See `pushRoute`
* and `popRoute` to change the route after Flutter started running.
*
* This is deprecated because it needs to be called at the time of initialization
* and thus should just be in the `initWithProject` initializer. If using
* `initWithEngine`, the initial route should be set on the engine's
* initializer.
*
* @param route The name of the first route to show.
*/
- (void)setInitialRoute:(NSString*)route
FLUTTER_DEPRECATED("Use FlutterViewController initializer to specify initial route");
/**
* Instructs the Flutter Navigator (if any) to go back.
*/
- (void)popRoute;
/**
* Instructs the Flutter Navigator (if any) to push a route on to the navigation
* stack.
*
* @param route The name of the route to push to the navigation stack.
*/
- (void)pushRoute:(NSString*)route;
/**
* The `FlutterPluginRegistry` used by this FlutterViewController.
*/
- (id<FlutterPluginRegistry>)pluginRegistry;
/**
* A wrapper around UIAccessibilityIsVoiceOverRunning().
*
* As a C function, UIAccessibilityIsVoiceOverRunning() cannot be mocked in testing. Mock
* this class method to testing features depends on UIAccessibilityIsVoiceOverRunning().
*/
+ (BOOL)isUIAccessibilityIsVoiceOverRunning;
/**
* True if at least one frame has rendered and the ViewController has appeared.
*
* This property is reset to false when the ViewController disappears. It is
* guaranteed to only alternate between true and false for observers.
*/
@property(nonatomic, readonly, getter=isDisplayingFlutterUI) BOOL displayingFlutterUI;
/**
* Specifies the view to use as a splash screen. Flutter's rendering is asynchronous, so the first
* frame rendered by the Flutter application might not immediately appear when the Flutter view is
* initially placed in the view hierarchy. The splash screen view will be used as
* a replacement until the first frame is rendered.
*
* The view used should be appropriate for multiple sizes; an autoresizing mask to
* have a flexible width and height will be applied automatically.
*
* Set to nil to remove the splash screen view.
*/
@property(strong, nonatomic, nullable) UIView* splashScreenView;
/**
* Attempts to set the `splashScreenView` property from the `UILaunchStoryboardName` from the
* main bundle's `Info.plist` file. This method will not change the value of `splashScreenView`
* if it cannot find a default one from a storyboard or nib.
*
* @return `YES` if successful, `NO` otherwise.
*/
- (BOOL)loadDefaultSplashScreenView;
/**
* Controls whether the created view will be opaque or not.
*
* Default is `YES`. Note that setting this to `NO` may negatively impact performance
* when using hardware acceleration, and toggling this will trigger a re-layout of the
* view.
*/
@property(nonatomic, getter=isViewOpaque) BOOL viewOpaque;
/**
* The `FlutterEngine` instance for this view controller. This could be the engine this
* `FlutterViewController` is initialized with or a new `FlutterEngine` implicitly created if
* no engine was supplied during initialization.
*/
@property(weak, nonatomic, readonly) FlutterEngine* engine;
/**
* The `FlutterBinaryMessenger` associated with this FlutterViewController (used for communicating
* with channels).
*
* This is just a convenient way to get the |FlutterEngine|'s binary messenger.
*/
@property(nonatomic, readonly) NSObject<FlutterBinaryMessenger>* binaryMessenger;
/**
* If the `FlutterViewController` creates a `FlutterEngine`, this property
* determines if that `FlutterEngine` has `allowHeadlessExecution` set.
*
* The intention is that this is used with the XIB. Otherwise, a
* `FlutterEngine` can just be sent to the init methods.
*
* See also: `-[FlutterEngine initWithName:project:allowHeadlessExecution:]`
*/
@property(nonatomic, readonly) BOOL engineAllowHeadlessExecution;
@end
NS_ASSUME_NONNULL_END
#endif // FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_HEADERS_FLUTTERVIEWCONTROLLER_H_
+30
View File
@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>Flutter</string>
<key>CFBundleIdentifier</key>
<string>io.flutter.flutter</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>Flutter</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
<string>12.0</string>
<key>FlutterEngine</key>
<string>edd8546116457bdf1c5bdfb13ecb9463d2bb5ed4</string>
<key>ClangVersion</key>
<string>b'Fuchsia clang version 18.0.0 (https://llvm.googlesource.com/llvm-project 725656bdd885483c39f482a01ea25d67acf39c46)'</string>
</dict>
</plist>
@@ -0,0 +1,6 @@
framework module Flutter {
umbrella header "Flutter.h"
export *
module * { export * }
}
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSPrivacyTracking</key>
<false/>
<key>NSPrivacyTrackingDomains</key>
<array/>
<key>NSPrivacyCollectedDataTypes</key>
<array/>
<key>NSPrivacyAccessedAPITypes</key>
<array>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>0A2A.1</string>
<string>C617.1</string>
</array>
</dict>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategorySystemBootTime</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>35F9.1</string>
</array>
</dict>
</array>
</dict>
</plist>
@@ -0,0 +1,311 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>files</key>
<dict>
<key>Headers/Flutter.h</key>
<data>
wTPJHICwW6wxY3b87ek7ITN5kJk=
</data>
<key>Headers/FlutterAppDelegate.h</key>
<data>
zbvYFr9dywry0lMMrHuNOOaNgkY=
</data>
<key>Headers/FlutterBinaryMessenger.h</key>
<data>
ksjIMu5IPw+Q3rw2YkAx0KjxkdM=
</data>
<key>Headers/FlutterCallbackCache.h</key>
<data>
V/wkSSsyYdMoexF6wPrC3KgkL4g=
</data>
<key>Headers/FlutterChannels.h</key>
<data>
vFsZXNqjflvqKqAzsIptQaTSJho=
</data>
<key>Headers/FlutterCodecs.h</key>
<data>
sUgX1PJzkvyinL5i7nS1ro/Kd5o=
</data>
<key>Headers/FlutterDartProject.h</key>
<data>
1Ii7W6lYWZUeB6C6rtn269jAxgA=
</data>
<key>Headers/FlutterEngine.h</key>
<data>
AqVvCbPmgWMQKrRnib05Okrjbp0=
</data>
<key>Headers/FlutterEngineGroup.h</key>
<data>
D7zmZX01a5aYqFKalkcNejJ9toU=
</data>
<key>Headers/FlutterHeadlessDartRunner.h</key>
<data>
UqnnVWwQEYYX56eu7lt6dpR3LIc=
</data>
<key>Headers/FlutterMacros.h</key>
<data>
crQ9782ULebLQfIR+MbBkjB7d+k=
</data>
<key>Headers/FlutterPlatformViews.h</key>
<data>
ocQVSiAiUMYfVtZIn48LpYTJA5w=
</data>
<key>Headers/FlutterPlugin.h</key>
<data>
EARXud6pHb7ZYP8eXPDnluMqcXk=
</data>
<key>Headers/FlutterPluginAppLifeCycleDelegate.h</key>
<data>
qWHw5VIWEa0NmJ1PMhD16nlfRKk=
</data>
<key>Headers/FlutterTexture.h</key>
<data>
7nFruy6bmD9XHvbzEwfdTXE4Rkk=
</data>
<key>Headers/FlutterViewController.h</key>
<data>
n0oqDKaGwBHcAUY4+7F+z78onKc=
</data>
<key>Info.plist</key>
<data>
PKo6XwAFHgqwL3taNHqLZdj8jq0=
</data>
<key>Modules/module.modulemap</key>
<data>
wJV5dCKEGl+FAtDc8wJJh/fvKXs=
</data>
<key>PrivacyInfo.xcprivacy</key>
<data>
D+cqXttvC7E/uziGjFdqFabWd7A=
</data>
<key>icudtl.dat</key>
<data>
Ubat0LvE4LUgCwHeyl0Anx2vnzk=
</data>
</dict>
<key>files2</key>
<dict>
<key>Headers/Flutter.h</key>
<dict>
<key>hash2</key>
<data>
auaf7wPxiASCYD2ACy1dfbMJvmONwFvSz1BWYAQrrSw=
</data>
</dict>
<key>Headers/FlutterAppDelegate.h</key>
<dict>
<key>hash2</key>
<data>
o0iigVsmgwmtZfSv3X7hReDNYP5rXblslDnqq2s6UQc=
</data>
</dict>
<key>Headers/FlutterBinaryMessenger.h</key>
<dict>
<key>hash2</key>
<data>
EXDk4t+7qCpyQkar+q9WHqY9bcK8eyohCwGVtBJhMy8=
</data>
</dict>
<key>Headers/FlutterCallbackCache.h</key>
<dict>
<key>hash2</key>
<data>
0h9+vK5K+r8moTsiGBfs6+TM9Qog089afHAy3gbcwDU=
</data>
</dict>
<key>Headers/FlutterChannels.h</key>
<dict>
<key>hash2</key>
<data>
kg195C3vZLiOn8KeFQUy7DoVuA9VZDpqoBLVn64uGaI=
</data>
</dict>
<key>Headers/FlutterCodecs.h</key>
<dict>
<key>hash2</key>
<data>
ZyqlHYuZbpFevVeny9Wdl0rVFgS7szIyssSiCyaaeFM=
</data>
</dict>
<key>Headers/FlutterDartProject.h</key>
<dict>
<key>hash2</key>
<data>
Y5PEW7Tws4XpVmn15X/fdaU0d76hSeF803JlgrI20qE=
</data>
</dict>
<key>Headers/FlutterEngine.h</key>
<dict>
<key>hash2</key>
<data>
RAOC6nDhZdghbAzsIZgVeq6qPt+MUNTfm/vkUnhmZO4=
</data>
</dict>
<key>Headers/FlutterEngineGroup.h</key>
<dict>
<key>hash2</key>
<data>
OW47bgphAFby1w8jlGCDvYQnMT3W1UAKiw5oFHtY788=
</data>
</dict>
<key>Headers/FlutterHeadlessDartRunner.h</key>
<dict>
<key>hash2</key>
<data>
nmZjZpvFCXrygf4U9aPkNi8VcI7cL5AtA+CY5uUWIL0=
</data>
</dict>
<key>Headers/FlutterMacros.h</key>
<dict>
<key>hash2</key>
<data>
ebBVHSZcUnAbN4hRcYq3ttt6++z1Ybc8KVSYhVToD5k=
</data>
</dict>
<key>Headers/FlutterPlatformViews.h</key>
<dict>
<key>hash2</key>
<data>
4hl+kRU4PNNKdAHvYrliObXzSjRzow9Z18oOMRZIa0o=
</data>
</dict>
<key>Headers/FlutterPlugin.h</key>
<dict>
<key>hash2</key>
<data>
HqbvCHqKWTzs5GjLAwupqEIYVi9yf5CrMdMe31EOwUA=
</data>
</dict>
<key>Headers/FlutterPluginAppLifeCycleDelegate.h</key>
<dict>
<key>hash2</key>
<data>
+PMn+5SDj2Vd6RU8CQIt/JYl3T+8Dhp7HImqAzocoNk=
</data>
</dict>
<key>Headers/FlutterTexture.h</key>
<dict>
<key>hash2</key>
<data>
4kb25KahvBulQiElAYv/ZSbdkhkb5F/AKRZv4IjLsOw=
</data>
</dict>
<key>Headers/FlutterViewController.h</key>
<dict>
<key>hash2</key>
<data>
phm49xhui2KkRomlqtmASHuU7lmd/s3qNCQpYxC0IMc=
</data>
</dict>
<key>Modules/module.modulemap</key>
<dict>
<key>hash2</key>
<data>
0VjriRpZ7AZZaP/0mMAPMJPhi6LoMB4MhXzL5j24tGs=
</data>
</dict>
<key>PrivacyInfo.xcprivacy</key>
<dict>
<key>hash2</key>
<data>
n5XX54YqS1a2btkmvW1iLSplRagn0ZhHJ4tDjVcdQhI=
</data>
</dict>
<key>icudtl.dat</key>
<dict>
<key>hash2</key>
<data>
ZepykIMSjfzhwAcmupMrkaqvXkhza1ZE3TdHjl8odaw=
</data>
</dict>
</dict>
<key>rules</key>
<dict>
<key>^.*</key>
<true/>
<key>^.*\.lproj/</key>
<dict>
<key>optional</key>
<true/>
<key>weight</key>
<real>1000</real>
</dict>
<key>^.*\.lproj/locversion.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>1100</real>
</dict>
<key>^Base\.lproj/</key>
<dict>
<key>weight</key>
<real>1010</real>
</dict>
<key>^version.plist$</key>
<true/>
</dict>
<key>rules2</key>
<dict>
<key>.*\.dSYM($|/)</key>
<dict>
<key>weight</key>
<real>11</real>
</dict>
<key>^(.*/)?\.DS_Store$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>2000</real>
</dict>
<key>^.*</key>
<true/>
<key>^.*\.lproj/</key>
<dict>
<key>optional</key>
<true/>
<key>weight</key>
<real>1000</real>
</dict>
<key>^.*\.lproj/locversion.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>1100</real>
</dict>
<key>^Base\.lproj/</key>
<dict>
<key>weight</key>
<real>1010</real>
</dict>
<key>^Info\.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>20</real>
</dict>
<key>^PkgInfo$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>20</real>
</dict>
<key>^embedded\.provisionprofile$</key>
<dict>
<key>weight</key>
<real>20</real>
</dict>
<key>^version\.plist$</key>
<dict>
<key>weight</key>
<real>20</real>
</dict>
</dict>
</dict>
</plist>
Binary file not shown.
+26
View File
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>App</string>
<key>CFBundleIdentifier</key>
<string>io.flutter.flutter.app</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>App</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
<string>12.0</string>
</dict>
</plist>
+2
View File
@@ -0,0 +1,2 @@
#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include "Generated.xcconfig"
+2
View File
@@ -0,0 +1,2 @@
#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "Generated.xcconfig"
+35
View File
@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key>
<string>PacketTunnel</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>$(MARKETING_VERSION)</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSCameraUsageDescription</key>
<string>用于客服消息上传图片</string>
<key>NSExtension</key>
<dict>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.networkextension.packet-tunnel</string>
<key>NSExtensionPrincipalClass</key>
<string>$(PRODUCT_MODULE_NAME).PacketTunnelProvider</string>
</dict>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>用于客服消息上传图片</string>
</dict>
</plist>
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.developer.networking.networkextension</key>
<array>
<string>packet-tunnel-provider</string>
</array>
<key>com.apple.security.application-groups</key>
<array>
<string>group.com.vpntunnel.vpnzeus</string>
</array>
</dict>
</plist>
File diff suppressed because it is too large Load Diff
+44
View File
@@ -0,0 +1,44 @@
# Uncomment this line to define a global platform for your project
# platform :ios, '12.0'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
platform :ios, '14.0'
project 'Runner', {
'Debug' => :debug,
'Profile' => :release,
'Release' => :release,
}
def flutter_root
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
unless File.exist?(generated_xcode_build_settings_path)
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
end
File.foreach(generated_xcode_build_settings_path) do |line|
matches = line.match(/FLUTTER_ROOT\=(.*)/)
return matches[1].strip if matches
end
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
end
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
flutter_ios_podfile_setup
target 'Runner' do
use_frameworks!
use_modular_headers!
# pod 'Leaf', :path => 'leaf.xcframework'
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
end
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
end
end
+977
View File
@@ -0,0 +1,977 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 54;
objects = {
/* Begin PBXBuildFile section */
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
2FD21F1125A363E300F556E0 /* PacketTunnelProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FD21F1025A363E300F556E0 /* PacketTunnelProvider.swift */; };
2FD21F1625A363E300F556E0 /* PacketTunnel.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 2FD21F0D25A363E300F556E0 /* PacketTunnel.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
2FD21F2425A364B700F556E0 /* NetworkExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2FD21EF825A363AA00F556E0 /* NetworkExtension.framework */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
3E06F985293FACBB00E04D92 /* PacketTunnelProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FD21F1025A363E300F556E0 /* PacketTunnelProvider.swift */; };
3E06F989293FAFC600E04D92 /* LeafAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E06F988293FAFC600E04D92 /* LeafAdapter.swift */; };
3E06F98A293FAFC600E04D92 /* LeafAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E06F988293FAFC600E04D92 /* LeafAdapter.swift */; };
3E06F98C293FB8F600E04D92 /* TunnelConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E06F98B293FB8F600E04D92 /* TunnelConfiguration.swift */; };
3E06F98D293FB8F600E04D92 /* TunnelConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E06F98B293FB8F600E04D92 /* TunnelConfiguration.swift */; };
3EA6B274293F185700B2BABC /* FileManager+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EA6B273293F185700B2BABC /* FileManager+Helpers.swift */; };
3EA6B276293F1AC500B2BABC /* template.conf in Resources */ = {isa = PBXBuildFile; fileRef = 3EA6B275293F1AC500B2BABC /* template.conf */; };
3EA6B278293F1D1600B2BABC /* URL+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EA6B277293F1D1600B2BABC /* URL+Helpers.swift */; };
3EA6B27A293F1FAD00B2BABC /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EA6B279293F1FAD00B2BABC /* Logger.swift */; };
3EA6B27C293F68B500B2BABC /* VPNManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F50954A25A36FD0001A32D5 /* VPNManager.swift */; };
3EA6B27E293F69A400B2BABC /* VPNManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F50954A25A36FD0001A32D5 /* VPNManager.swift */; };
3EA6B27F293F6AB500B2BABC /* FileManager+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EA6B273293F185700B2BABC /* FileManager+Helpers.swift */; };
3EA6B280293F6AB900B2BABC /* URL+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EA6B277293F1D1600B2BABC /* URL+Helpers.swift */; };
3EA6B281293F6AF800B2BABC /* template.conf in Resources */ = {isa = PBXBuildFile; fileRef = 3EA6B275293F1AC500B2BABC /* template.conf */; };
3EA6B282293F6BA500B2BABC /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EA6B279293F1FAD00B2BABC /* Logger.swift */; };
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
7A31DD8228420C0B00E82EE1 /* NetworkExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2FD21EF825A363AA00F556E0 /* NetworkExtension.framework */; };
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
C09C70752C3E5685000F6E01 /* leaf.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = C0CB10F52C3275EE00A1F217 /* leaf.xcframework */; };
C09C70762C3E5685000F6E01 /* leaf.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = C0CB10F52C3275EE00A1F217 /* leaf.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
C09CB0812C50A09A0028C461 /* TESWT.m in Sources */ = {isa = PBXBuildFile; fileRef = C09CB0802C50A09A0028C461 /* TESWT.m */; };
C09CB08E2C50AEB40028C461 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C09CB08D2C50AEB40028C461 /* Flutter.framework */; };
C0CB10F62C3275EE00A1F217 /* leaf.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = C0CB10F52C3275EE00A1F217 /* leaf.xcframework */; };
DBC6F25A26C78B1D91884CE1 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4A9C0075B77637136AF52D8B /* Pods_Runner.framework */; };
E2B5FEC68AAAE043A3080A59 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4A9C0075B77637136AF52D8B /* Pods_Runner.framework */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
2FD21F1425A363E300F556E0 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 97C146E61CF9000F007C117D /* Project object */;
proxyType = 1;
remoteGlobalIDString = 2FD21F0C25A363E300F556E0;
remoteInfo = PacketTunnel;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
2FD21F0625A363AA00F556E0 /* Embed Foundation Extensions */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 12;
dstPath = "";
dstSubfolderSpec = 13;
files = (
2FD21F1625A363E300F556E0 /* PacketTunnel.appex in Embed Foundation Extensions */,
);
name = "Embed Foundation Extensions";
runOnlyForDeploymentPostprocessing = 0;
};
9705A1C41CF9048500538489 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
C09C70772C3E5685000F6E01 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
C09C70762C3E5685000F6E01 /* leaf.xcframework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
C0DAE5F52C3272280023769C /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 7;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
2F50954A25A36FD0001A32D5 /* VPNManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPNManager.swift; sourceTree = "<group>"; };
2FD21EF825A363AA00F556E0 /* NetworkExtension.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = NetworkExtension.framework; path = System/Library/Frameworks/NetworkExtension.framework; sourceTree = SDKROOT; };
2FD21F0D25A363E300F556E0 /* PacketTunnel.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = PacketTunnel.appex; sourceTree = BUILT_PRODUCTS_DIR; };
2FD21F1025A363E300F556E0 /* PacketTunnelProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PacketTunnelProvider.swift; sourceTree = "<group>"; };
2FD21F1225A363E300F556E0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
2FD21F1325A363E300F556E0 /* PacketTunnel.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = PacketTunnel.entitlements; sourceTree = "<group>"; };
2FD21F2325A364B600F556E0 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = "<group>"; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
3E06F988293FAFC600E04D92 /* LeafAdapter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LeafAdapter.swift; sourceTree = "<group>"; };
3E06F98B293FB8F600E04D92 /* TunnelConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelConfiguration.swift; sourceTree = "<group>"; };
3EA6B273293F185700B2BABC /* FileManager+Helpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FileManager+Helpers.swift"; sourceTree = "<group>"; };
3EA6B275293F1AC500B2BABC /* template.conf */ = {isa = PBXFileReference; lastKnownFileType = text; path = template.conf; sourceTree = "<group>"; };
3EA6B277293F1D1600B2BABC /* URL+Helpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "URL+Helpers.swift"; sourceTree = "<group>"; };
3EA6B279293F1FAD00B2BABC /* Logger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Logger.swift; sourceTree = "<group>"; };
4A9C0075B77637136AF52D8B /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
7F9A79C99E6BB92BFA8F918D /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
8B949A6E3580C410A6129430 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
9788364E2A66C2C5DE332140 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
C09CB07F2C50A09A0028C461 /* TESWT.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TESWT.h; sourceTree = "<group>"; };
C09CB0802C50A09A0028C461 /* TESWT.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TESWT.m; sourceTree = "<group>"; };
C09CB0832C50A0DD0028C461 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
C09CB08D2C50AEB40028C461 /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Flutter.framework; sourceTree = "<group>"; };
C0CB10F52C3275EE00A1F217 /* leaf.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = leaf.xcframework; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
2FD21F0A25A363E300F556E0 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
7A31DD8228420C0B00E82EE1 /* NetworkExtension.framework in Frameworks */,
C09C70752C3E5685000F6E01 /* leaf.xcframework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
97C146EB1CF9000F007C117D /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
C0CB10F62C3275EE00A1F217 /* leaf.xcframework in Frameworks */,
C09CB08E2C50AEB40028C461 /* Flutter.framework in Frameworks */,
2FD21F2425A364B700F556E0 /* NetworkExtension.framework in Frameworks */,
DBC6F25A26C78B1D91884CE1 /* Pods_Runner.framework in Frameworks */,
E2B5FEC68AAAE043A3080A59 /* Pods_Runner.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
2FD21F0F25A363E300F556E0 /* PacketTunnel */ = {
isa = PBXGroup;
children = (
2FD21F1225A363E300F556E0 /* Info.plist */,
2FD21F1325A363E300F556E0 /* PacketTunnel.entitlements */,
);
path = PacketTunnel;
sourceTree = "<group>";
};
3EA6B272293F183000B2BABC /* Helpers */ = {
isa = PBXGroup;
children = (
3EA6B273293F185700B2BABC /* FileManager+Helpers.swift */,
3EA6B277293F1D1600B2BABC /* URL+Helpers.swift */,
);
path = Helpers;
sourceTree = "<group>";
};
3EA6B27D293F699400B2BABC /* Shared */ = {
isa = PBXGroup;
children = (
3E06F988293FAFC600E04D92 /* LeafAdapter.swift */,
2FD21F1025A363E300F556E0 /* PacketTunnelProvider.swift */,
3EA6B272293F183000B2BABC /* Helpers */,
2F50954A25A36FD0001A32D5 /* VPNManager.swift */,
3EA6B279293F1FAD00B2BABC /* Logger.swift */,
3EA6B275293F1AC500B2BABC /* template.conf */,
3E06F98B293FB8F600E04D92 /* TunnelConfiguration.swift */,
);
path = Shared;
sourceTree = "<group>";
};
460845DE28877D00F1FA7B32 /* Pods */ = {
isa = PBXGroup;
children = (
7F9A79C99E6BB92BFA8F918D /* Pods-Runner.debug.xcconfig */,
8B949A6E3580C410A6129430 /* Pods-Runner.release.xcconfig */,
9788364E2A66C2C5DE332140 /* Pods-Runner.profile.xcconfig */,
);
path = Pods;
sourceTree = "<group>";
};
9740EEB11CF90186004384FC /* Flutter */ = {
isa = PBXGroup;
children = (
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
9740EEB21CF90195004384FC /* Debug.xcconfig */,
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
9740EEB31CF90195004384FC /* Generated.xcconfig */,
);
name = Flutter;
sourceTree = "<group>";
};
97C146E51CF9000F007C117D = {
isa = PBXGroup;
children = (
3EA6B27D293F699400B2BABC /* Shared */,
9740EEB11CF90186004384FC /* Flutter */,
97C146F01CF9000F007C117D /* Runner */,
2FD21F0F25A363E300F556E0 /* PacketTunnel */,
97C146EF1CF9000F007C117D /* Products */,
460845DE28877D00F1FA7B32 /* Pods */,
F6BCB37E43B89DAB5A76B9D0 /* Frameworks */,
);
sourceTree = "<group>";
};
97C146EF1CF9000F007C117D /* Products */ = {
isa = PBXGroup;
children = (
97C146EE1CF9000F007C117D /* Runner.app */,
2FD21F0D25A363E300F556E0 /* PacketTunnel.appex */,
);
name = Products;
sourceTree = "<group>";
};
97C146F01CF9000F007C117D /* Runner */ = {
isa = PBXGroup;
children = (
2FD21F2325A364B600F556E0 /* Runner.entitlements */,
97C146FA1CF9000F007C117D /* Main.storyboard */,
97C146FD1CF9000F007C117D /* Assets.xcassets */,
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
97C147021CF9000F007C117D /* Info.plist */,
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
C09CB0832C50A0DD0028C461 /* Runner-Bridging-Header.h */,
C09CB07F2C50A09A0028C461 /* TESWT.h */,
C09CB0802C50A09A0028C461 /* TESWT.m */,
);
path = Runner;
sourceTree = "<group>";
};
F6BCB37E43B89DAB5A76B9D0 /* Frameworks */ = {
isa = PBXGroup;
children = (
C0CB10F52C3275EE00A1F217 /* leaf.xcframework */,
C09CB08D2C50AEB40028C461 /* Flutter.framework */,
2FD21EF825A363AA00F556E0 /* NetworkExtension.framework */,
4A9C0075B77637136AF52D8B /* Pods_Runner.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
2FD21F0C25A363E300F556E0 /* PacketTunnel */ = {
isa = PBXNativeTarget;
buildConfigurationList = 2FD21F1725A363E300F556E0 /* Build configuration list for PBXNativeTarget "PacketTunnel" */;
buildPhases = (
2FD21F0925A363E300F556E0 /* Sources */,
2FD21F0A25A363E300F556E0 /* Frameworks */,
C0DAE5F52C3272280023769C /* CopyFiles */,
2FD21F0B25A363E300F556E0 /* Resources */,
C09C70772C3E5685000F6E01 /* Embed Frameworks */,
);
buildRules = (
);
dependencies = (
);
name = PacketTunnel;
productName = PacketTunnel;
productReference = 2FD21F0D25A363E300F556E0 /* PacketTunnel.appex */;
productType = "com.apple.product-type.app-extension";
};
97C146ED1CF9000F007C117D /* Runner */ = {
isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
4A4528B4E4B302F57B5EDB65 /* [CP] Check Pods Manifest.lock */,
2FD21F0625A363AA00F556E0 /* Embed Foundation Extensions */,
97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */,
9705A1C41CF9048500538489 /* Embed Frameworks */,
30B17F94E53B12A0859D0A8C /* [CP] Embed Pods Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
9740EEB61CF901F6004384FC /* Run Script */,
);
buildRules = (
);
dependencies = (
2FD21F1525A363E300F556E0 /* PBXTargetDependency */,
);
name = Runner;
productName = Runner;
productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
BuildIndependentTargetsInParallel = YES;
LastSwiftUpdateCheck = 1230;
LastUpgradeCheck = 1510;
ORGANIZATIONNAME = "";
TargetAttributes = {
2FD21F0C25A363E300F556E0 = {
CreatedOnToolsVersion = 12.3;
};
97C146ED1CF9000F007C117D = {
CreatedOnToolsVersion = 7.3.1;
LastSwiftMigration = 1100;
};
};
};
buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
compatibilityVersion = "Xcode 9.3";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 97C146E51CF9000F007C117D;
productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
97C146ED1CF9000F007C117D /* Runner */,
2FD21F0C25A363E300F556E0 /* PacketTunnel */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
2FD21F0B25A363E300F556E0 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
3EA6B276293F1AC500B2BABC /* template.conf in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
97C146EC1CF9000F007C117D /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
3EA6B281293F6AF800B2BABC /* template.conf in Resources */,
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
30B17F94E53B12A0859D0A8C /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
);
name = "Thin Binary";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin\n";
};
4A4528B4E4B302F57B5EDB65 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Run Script";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build\n";
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
2FD21F0925A363E300F556E0 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
2FD21F1125A363E300F556E0 /* PacketTunnelProvider.swift in Sources */,
3EA6B278293F1D1600B2BABC /* URL+Helpers.swift in Sources */,
3EA6B27E293F69A400B2BABC /* VPNManager.swift in Sources */,
3E06F98A293FAFC600E04D92 /* LeafAdapter.swift in Sources */,
3EA6B274293F185700B2BABC /* FileManager+Helpers.swift in Sources */,
3E06F98D293FB8F600E04D92 /* TunnelConfiguration.swift in Sources */,
3EA6B27A293F1FAD00B2BABC /* Logger.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
97C146EA1CF9000F007C117D /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
3EA6B282293F6BA500B2BABC /* Logger.swift in Sources */,
3EA6B280293F6AB900B2BABC /* URL+Helpers.swift in Sources */,
3EA6B27F293F6AB500B2BABC /* FileManager+Helpers.swift in Sources */,
3EA6B27C293F68B500B2BABC /* VPNManager.swift in Sources */,
C09CB0812C50A09A0028C461 /* TESWT.m in Sources */,
3E06F989293FAFC600E04D92 /* LeafAdapter.swift in Sources */,
3E06F985293FACBB00E04D92 /* PacketTunnelProvider.swift in Sources */,
3E06F98C293FB8F600E04D92 /* TunnelConfiguration.swift in Sources */,
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
2FD21F1525A363E300F556E0 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 2FD21F0C25A363E300F556E0 /* PacketTunnel */;
targetProxy = 2FD21F1425A363E300F556E0 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
97C146FA1CF9000F007C117D /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
97C146FB1CF9000F007C117D /* Base */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
97C147001CF9000F007C117D /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
249021D3217E4FDB00AE95B9 /* Profile */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_BITCODE = NO;
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
MODULEMAP_FILE = "${PROJECT_DIR}/LeafFFI/module.modulemap";
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
SWIFT_INCLUDE_PATHS = "${PROJECT_DIR}/LeafFFI";
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Profile;
};
249021D4217E4FDB00AE95B9 /* Profile */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 222;
DEVELOPMENT_TEAM = 26XWXKSR3B;
ENABLE_BITCODE = NO;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
"$(PROJECT_DIR)",
);
INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = UUVPN;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
MARKETING_VERSION = 2.0.0;
MODULEMAP_FILE = "${PROJECT_DIR}/LeafFFI/module.modulemap";
PRODUCT_BUNDLE_IDENTIFIER = com.vpntunnel.vpnzeus;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES;
SWIFT_INCLUDE_PATHS = "";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 1;
VERSIONING_SYSTEM = "apple-generic";
};
name = Profile;
};
2FD21F1825A363E300F556E0 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
buildSettings = {
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_ENTITLEMENTS = PacketTunnel/PacketTunnel.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 200;
DEVELOPMENT_TEAM = 26XWXKSR3B;
ENABLE_BITCODE = NO;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "i386 arm64";
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
GCC_C_LANGUAGE_STANDARD = gnu11;
INFOPLIST_FILE = PacketTunnel/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
LIBRARY_SEARCH_PATHS = "$(inherited)";
MARKETING_VERSION = 1.0.6;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.vpntunnel.vpnzeus.PacketTunnel;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_INCLUDE_PATHS = "";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
2FD21F1925A363E300F556E0 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_ENTITLEMENTS = PacketTunnel/PacketTunnel.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 200;
DEVELOPMENT_TEAM = 26XWXKSR3B;
ENABLE_BITCODE = NO;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "i386 arm64";
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
GCC_C_LANGUAGE_STANDARD = gnu11;
INFOPLIST_FILE = PacketTunnel/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
LIBRARY_SEARCH_PATHS = "$(inherited)";
MARKETING_VERSION = 1.0.6;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.vpntunnel.vpnzeus.PacketTunnel;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_INCLUDE_PATHS = "";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
2FD21F1A25A363E300F556E0 /* Profile */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_ENTITLEMENTS = PacketTunnel/PacketTunnel.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 200;
DEVELOPMENT_TEAM = 26XWXKSR3B;
ENABLE_BITCODE = NO;
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "i386 arm64";
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
GCC_C_LANGUAGE_STANDARD = gnu11;
INFOPLIST_FILE = PacketTunnel/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
LIBRARY_SEARCH_PATHS = "$(inherited)";
MARKETING_VERSION = 1.0.6;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.vpntunnel.vpnzeus.PacketTunnel;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_INCLUDE_PATHS = "";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Profile;
};
97C147031CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_BITCODE = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
MODULEMAP_FILE = "${PROJECT_DIR}/LeafFFI/module.modulemap";
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
SWIFT_INCLUDE_PATHS = "${PROJECT_DIR}/LeafFFI";
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
97C147041CF9000F007C117D /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_BITCODE = NO;
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
MODULEMAP_FILE = "${PROJECT_DIR}/LeafFFI/module.modulemap";
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_INCLUDE_PATHS = "${PROJECT_DIR}/LeafFFI";
SWIFT_OPTIMIZATION_LEVEL = "-O";
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
97C147061CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 222;
DEVELOPMENT_TEAM = 26XWXKSR3B;
ENABLE_BITCODE = NO;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
"$(PROJECT_DIR)",
);
INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = UUVPN;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
MARKETING_VERSION = 2.0.0;
MODULEMAP_FILE = "${PROJECT_DIR}/LeafFFI/module.modulemap";
PRODUCT_BUNDLE_IDENTIFIER = com.vpntunnel.vpnzeus;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES;
SWIFT_INCLUDE_PATHS = "";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 1;
VERSIONING_SYSTEM = "apple-generic";
};
name = Debug;
};
97C147071CF9000F007C117D /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 222;
DEVELOPMENT_TEAM = 26XWXKSR3B;
ENABLE_BITCODE = NO;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
"$(PROJECT_DIR)",
);
INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = UUVPN;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
MARKETING_VERSION = 2.0.0;
MODULEMAP_FILE = "${PROJECT_DIR}/LeafFFI/module.modulemap";
PRODUCT_BUNDLE_IDENTIFIER = com.vpntunnel.vpnzeus;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES;
SWIFT_INCLUDE_PATHS = "";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 1;
VERSIONING_SYSTEM = "apple-generic";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
2FD21F1725A363E300F556E0 /* Build configuration list for PBXNativeTarget "PacketTunnel" */ = {
isa = XCConfigurationList;
buildConfigurations = (
2FD21F1825A363E300F556E0 /* Debug */,
2FD21F1925A363E300F556E0 /* Release */,
2FD21F1A25A363E300F556E0 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
isa = XCConfigurationList;
buildConfigurations = (
97C147031CF9000F007C117D /* Debug */,
97C147041CF9000F007C117D /* Release */,
249021D3217E4FDB00AE95B9 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
isa = XCConfigurationList;
buildConfigurations = (
97C147061CF9000F007C117D /* Debug */,
97C147071CF9000F007C117D /* Release */,
249021D4217E4FDB00AE95B9 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 97C146E61CF9000F007C117D /* Project object */;
}
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>

Some files were not shown because too many files have changed in this diff Show More