Commit 1ac8d16e07f6b87e47859d6b26724461890332aa

Authored by 常守达
0 parents

init

Showing 100 changed files with 4291 additions and 0 deletions

Too many changes to show.

To preserve performance only 100 of 100+ files are displayed.

# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.build/
.buildlog/
.history
.svn/
.swiftpm/
migrate_working_dir/
# IntelliJ related
*.iml
*.ipr
*.iws
.idea/
# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/
# Flutter/Dart/Pub related
**/doc/api/
**/ios/Flutter/.last_build_id
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.pub-cache/
.pub/
/build/
# Symbolication related
app.*.symbols
# Obfuscation related
app.*.map.json
# Android Studio will place build artifacts here
/android/app/debug
/android/app/profile
/android/app/release
... ...
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.
version:
revision: "50e8dd668fbc8a752eb904e9c1b4f3a995498d13"
channel: "[user-branch]"
project_type: app
# Tracks metadata for the flutter migrate command
migration:
platforms:
- platform: root
create_revision: 50e8dd668fbc8a752eb904e9c1b4f3a995498d13
base_revision: 50e8dd668fbc8a752eb904e9c1b4f3a995498d13
- platform: android
create_revision: 50e8dd668fbc8a752eb904e9c1b4f3a995498d13
base_revision: 50e8dd668fbc8a752eb904e9c1b4f3a995498d13
- platform: ios
create_revision: 50e8dd668fbc8a752eb904e9c1b4f3a995498d13
base_revision: 50e8dd668fbc8a752eb904e9c1b4f3a995498d13
- platform: ohos
create_revision: 50e8dd668fbc8a752eb904e9c1b4f3a995498d13
base_revision: 50e8dd668fbc8a752eb904e9c1b4f3a995498d13
# User provided section
# List of Local paths (relative to this file) that should be
# ignored by the migrate tool.
#
# Files that are not part of the templates will be ignored by default.
unmanaged_files:
- 'lib/main.dart'
- 'ios/Runner.xcodeproj/project.pbxproj'
... ...
# doublefeel_flutter
A new Flutter project.
## Getting Started
This project is a starting point for a Flutter application.
A few resources to get you started if this is your first Flutter project:
- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
For help getting started with Flutter development, view the
[online documentation](https://docs.flutter.dev/), which offers tutorials,
samples, guidance on mobile development, and a full API reference.
... ...
# This file configures the analyzer, which statically analyzes Dart code to
# check for errors, warnings, and lints.
#
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
# invoked from the command line by running `flutter analyze`.
# The following line activates a set of recommended lints for Flutter apps,
# packages, and plugins designed to encourage good coding practices.
include: package:flutter_lints/flutter.yaml
analyzer:
exclude:
- lib/**/*.g.dart
- lib/app/routes/app_routes.dart
linter:
# The lint rules applied to this project can be customized in the
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
# included above or to enable additional rules. A list of all available lints
# and their documentation is published at https://dart.dev/lints.
#
# Instead of disabling a lint rule for the entire project in the
# section below, it can also be suppressed for a single line of code
# or a specific dart file by using the `// ignore: name_of_lint` and
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
# producing the lint.
rules:
# avoid_print: false # Uncomment to disable the `avoid_print` rule
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options
... ...
gradle-wrapper.jar
/.gradle
/captures/
/gradlew
/gradlew.bat
/local.properties
GeneratedPluginRegistrant.java
# Remember to never publicly share your keystore.
# See https://flutter.dev/to/reference-keystore
key.properties
**/*.keystore
**/*.jks
... ...
{"agcgw_all":{"SG":"connect-dra.dbankcloud.cn","SG_back":"connect-dra.hispace.hicloud.com","CN":"connect-drcn.dbankcloud.cn","CN_back":"connect-drcn.hispace.hicloud.com","RU":"connect-drru.hispace.dbankcloud.ru","RU_back":"connect-drru.hispace.dbankcloud.cn","DE":"connect-dre.dbankcloud.cn","DE_back":"connect-dre.hispace.hicloud.com"},"websocketgw_all":{"SG":"connect-ws-dra.hispace.dbankcloud.cn","SG_back":"connect-ws-dra.hispace.dbankcloud.com","CN":"connect-ws-drcn.hispace.dbankcloud.cn","CN_back":"connect-ws-drcn.hispace.dbankcloud.com","RU":"connect-ws-drru.hispace.dbankcloud.ru","RU_back":"connect-ws-drru.hispace.dbankcloud.cn","DE":"connect-ws-dre.hispace.dbankcloud.cn","DE_back":"connect-ws-dre.hispace.dbankcloud.com"},"client":{"cp_id":"900086000022307512","product_id":"461323198430851343","client_id":"1811673616249541056","client_secret":"88747662DC6FB467CDAE57C91D183E6E242AC40ACA10252310F0546CC136DB3C","project_id":"461323198430851343","app_id":"115627281","api_key":"DgEDAGFcIuuhc7kxg5R79OsFU2qRQ9nEQ+1EK8ENbMlStWgsruPnPHo6ix7N/TWt1RkdpOHHtjZKxFNAR97f9DiXK3gUeSjq5WTeog==","package_name":"com.doublefeel.app"},"oauth_client":{"client_id":"115627281","client_type":1},"app_info":{"app_id":"115627281","package_name":"com.doublefeel.app"},"configuration_version":"3.0","appInfos":[{"package_name":"com.doublefeel.app","client":{"app_id":"115627281"},"app_info":{"package_name":"com.doublefeel.app","app_id":"115627281"},"oauth_client":{"client_type":1,"client_id":"115627281"}}]}
\ No newline at end of file
... ...
plugins {
id "com.android.application"
id "kotlin-android"
id "dev.flutter.flutter-gradle-plugin"
}
android {
namespace = "com.doublefeel.app"
compileSdk = flutter.compileSdkVersion
ndkVersion = flutter.ndkVersion
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = JavaVersion.VERSION_1_8
}
defaultConfig {
applicationId = "com.doublefeel.app"
minSdk = 29
targetSdk = flutter.targetSdkVersion
versionCode = flutter.versionCode
versionName = flutter.versionName
}
buildTypes {
release {
signingConfig = signingConfigs.debug
}
}
}
flutter {
source = "../.."
}
dependencies {
implementation "androidx.activity:activity-ktx:1.8.2"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.22"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3"
implementation "com.alipay.sdk:alipaysdk-android:15.8.38"
implementation "com.huawei.hms:health:6.15.0.300"
implementation "com.huawei.hms:wearengine:5.0.3.304"
implementation "com.huawei.hihealth:hihealthkit:6.7.0.300"
}
... ...
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<queries>
<package android:name="com.huawei.health" />
</queries>
<application
android:label="DoubleFeel"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:taskAffinity=""
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
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>
<!-- 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" />
<meta-data
android:name="com.huawei.hms.client.appid"
android:value="115627281" />
</application>
<!-- Required to query activities that can process text, see:
https://developer.android.com/training/package-visibility and
https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT.
In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
<queries>
<intent>
<action android:name="android.intent.action.PROCESS_TEXT"/>
<data android:mimeType="text/plain"/>
</intent>
</queries>
</manifest>
... ...
package com.doublefeel.app
import android.content.Intent
import androidx.activity.result.contract.ActivityResultContracts
import com.doublefeel.app.native.AlipayHostApiImpl
import com.doublefeel.app.native.HealthKitHostApiImpl
import com.doublefeel.app.native.WearEngineHostApiImpl
import com.doublefeel.app.pigeon.HealthKitHostApi
import com.doublefeel.app.pigeon.alipay.AlipayHostApi
import com.doublefeel.app.pigeon.wear.WearEngineHostApi
import io.flutter.embedding.android.FlutterFragmentActivity
import io.flutter.embedding.engine.FlutterEngine
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit
import java.util.concurrent.atomic.AtomicBoolean
class MainActivity : FlutterFragmentActivity() {
private var healthAuthLatch: CountDownLatch? = null
private val healthAuthGranted = AtomicBoolean(false)
private val healthClientAuthLauncher = registerForActivityResult(
ActivityResultContracts.StartActivityForResult(),
) { result ->
healthAuthGranted.set(result.resultCode == RESULT_OK)
healthAuthLatch?.countDown()
}
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
MainActivityHolder.activity = this
val messenger = flutterEngine.dartExecutor.binaryMessenger
HealthKitHostApi.setUp(messenger, HealthKitHostApiImpl(this))
WearEngineHostApi.setUp(messenger, WearEngineHostApiImpl(applicationContext))
AlipayHostApi.setUp(messenger, AlipayHostApiImpl(this))
}
override fun onDestroy() {
if (MainActivityHolder.activity === this) {
MainActivityHolder.activity = null
}
super.onDestroy()
}
fun launchHealthClientAuth(intent: Intent): Boolean {
healthAuthGranted.set(false)
healthAuthLatch = CountDownLatch(1)
healthClientAuthLauncher.launch(intent)
return healthAuthLatch?.await(120, TimeUnit.SECONDS) == true && healthAuthGranted.get()
}
}
object MainActivityHolder {
var activity: MainActivity? = null
}
... ...
package com.doublefeel.app.native
import com.alipay.sdk.app.PayTask
import com.doublefeel.app.MainActivity
import com.doublefeel.app.pigeon.alipay.AliPayResultCode
import com.doublefeel.app.pigeon.alipay.AlipayHostApi
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
/** Alipay SDK host implementation for Pigeon. */
class AlipayHostApiImpl(
private val activity: MainActivity,
) : AlipayHostApi {
override fun launchAliPay(prepayData: String): AliPayResultCode {
return runBlocking {
withContext(Dispatchers.IO) {
runCatching {
val payTask = PayTask(activity)
val result = payTask.payV2(prepayData, true)
when (result["resultStatus"]) {
"9000" -> AliPayResultCode.SUCCESS
"6001" -> AliPayResultCode.CANCEL
else -> AliPayResultCode.ERROR
}
}.getOrElse { AliPayResultCode.ERROR }
}
}
}
}
... ...
package com.doublefeel.app.native
import com.doublefeel.app.MainActivity
import com.doublefeel.app.pigeon.HealthKitHostApi
import com.doublefeel.app.pigeon.HealthUploadResult
class HealthKitHostApiImpl(
private val activity: MainActivity,
) : HealthKitHostApi {
override fun checkHealthAppAuthorization(): Boolean {
return HuaweiHealthBridge.checkHealthAppAuthorization(activity.applicationContext)
}
override fun getHealthServerAuthUrl(): String {
return HuaweiHealthBridge.getHealthServerAuthUrl()
}
override fun requestHealthClientAuthorization(): Boolean {
return HuaweiHealthBridge.requestClientAuthorization(activity)
}
override fun cancelHealthAppAuthorization(): Boolean {
return HuaweiHealthBridge.cancelHealthAppAuthorization(activity)
}
override fun performHealthUpload(): HealthUploadResult {
return HealthUploadResult(
commonUploadSuccess = false,
sleepUploadSuccess = false,
errorMessage = "Native bulk upload runs via Dart HealthKitUploadService; HMS read bridge pending",
)
}
}
... ...
package com.doublefeel.app.native
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.net.Uri
import androidx.core.net.toUri
import com.doublefeel.app.MainActivity
import com.huawei.hihealthkit.data.store.HiHealthDataStore
import com.huawei.hms.hihealth.HuaweiHiHealth
import com.huawei.hms.hihealth.SettingController
import com.huawei.hms.hihealth.data.Scopes
import com.huawei.hihealthkit.data.HiHealthExtendScope
import java.util.UUID
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine
import kotlinx.coroutines.runBlocking
/** Huawei Health Kit authorization and data bridge. */
object HuaweiHealthBridge {
private const val APP_ID_HUAWEI = "115627281"
private const val CALLBACK_URL_HUAWEI =
"https://h5hosting.dbankcdn.com/cch5/healthkit/oauth-h5/oauth-callback.html"
private val scopes = arrayOf(
Scopes.HEALTHKIT_HEARTRATE_READ,
Scopes.HEALTHKIT_CALORIES_READ,
Scopes.HEALTHKIT_STEP_READ,
Scopes.HEALTHKIT_SLEEP_READ,
Scopes.HEALTHKIT_OXYGEN_SATURATION_READ,
Scopes.HEALTHKIT_STRENGTH_READ,
Scopes.HEALTHKIT_HISTORYDATA_OPEN_MONTH,
"https://www.huawei.com/healthkit/activehours.read",
HiHealthExtendScope.HEALTHKIT_EXTEND_REALTIME_HEART_READ,
)
private val fullScopes = scopes + arrayOf("openid", "profile")
fun getHealthServerAuthUrl(): String {
val uri = "https://oauth-login.cloud.huawei.com/oauth2/v3/authorize".toUri()
return uri.buildUpon()
.appendQueryParameter("client_id", APP_ID_HUAWEI)
.appendQueryParameter("response_type", "code")
.appendQueryParameter("redirect_uri", CALLBACK_URL_HUAWEI)
.appendQueryParameter("scope", fullScopes.joinToString(" "))
.appendQueryParameter("state", UUID.randomUUID().toString())
.appendQueryParameter("display", "touch")
.appendQueryParameter("access_type", "offline")
.build()
.toString()
}
fun createClientAuthIntent(context: Context): Intent? {
return runCatching {
val settingController = HuaweiHiHealth.getSettingController(context)
settingController.requestAuthorizationIntent(fullScopes, true)
}.getOrNull()
}
fun checkHealthAppAuthorization(context: Context): Boolean {
return runBlocking {
suspendCoroutine { continuation ->
try {
val settingController = HuaweiHiHealth.getSettingController(context)
settingController.healthAppAuthorization
.addOnSuccessListener { result -> continuation.resume(result) }
.addOnFailureListener { continuation.resume(false) }
} catch (_: Throwable) {
continuation.resume(false)
}
}
}
}
fun requestClientAuthorization(activity: MainActivity): Boolean {
val intent = createClientAuthIntent(activity) ?: return false
return activity.launchHealthClientAuth(intent)
}
fun cancelHealthAppAuthorization(activity: Activity): Boolean {
return runBlocking {
suspendCoroutine { continuation ->
try {
val consentsController = HuaweiHiHealth.getConsentsController(activity)
consentsController.cancelAuthorization(false)
.addOnSuccessListener { continuation.resume(true) }
.addOnFailureListener { continuation.resume(false) }
} catch (_: Throwable) {
continuation.resume(false)
}
}
}
}
}
... ...
package com.doublefeel.app.native
import android.content.Context
import com.huawei.wearengine.HiWear
import com.huawei.wearengine.device.Device
import com.huawei.wearengine.p2p.Message
import com.huawei.wearengine.p2p.P2pClient
import com.huawei.wearengine.p2p.SendCallback
import java.nio.charset.StandardCharsets
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine
import kotlinx.coroutines.runBlocking
/** Huawei Wear Engine P2P bridge. */
object HuaweiWearBridge {
private const val WATCH_APP_PACKAGE = "com.doublefeel.watchapp"
private const val WATCH_APP_FINGER_PRINT =
"${WATCH_APP_PACKAGE}_BETLDdeS3sjRDIkykOBVVAAyTWNBAdgYY0Y5lSEnZl2oH1xo1aHKtSolvrcbUWbu1vbD3JknBBRLJHgYhqI6lXo="
fun hasAvailableDevices(context: Context): Boolean {
return runBlocking {
suspendCoroutine { continuation ->
runCatching {
HiWear.getDeviceClient(context)
.hasAvailableDevices()
.addOnSuccessListener { continuation.resume(it) }
.addOnFailureListener { continuation.resume(false) }
}.onFailure { continuation.resume(false) }
}
}
}
fun getConnectedDevice(context: Context): Device? {
return runBlocking {
suspendCoroutine { continuation ->
runCatching {
HiWear.getDeviceClient(context)
.bondedDevices
.addOnSuccessListener { devices ->
continuation.resume(devices?.firstOrNull { it.isConnected })
}
.addOnFailureListener { continuation.resume(null) }
}.onFailure { continuation.resume(null) }
}
}
}
fun registerMessageReceiver(context: Context, device: Device): Boolean {
return runBlocking {
suspendCoroutine { continuation ->
runCatching {
val p2pClient = HiWear.getP2pClient(context).apply {
setPeerPkgName(WATCH_APP_PACKAGE)
setPeerFingerPrint(WATCH_APP_FINGER_PRINT)
}
p2pClient.registerReceiver(device) { _ -> }
.addOnSuccessListener { continuation.resume(true) }
.addOnFailureListener { continuation.resume(false) }
}.onFailure { continuation.resume(false) }
}
}
}
fun sendTextMessage(context: Context, device: Device, text: String): Boolean {
return runBlocking {
suspendCoroutine { continuation ->
runCatching {
val p2pClient = HiWear.getP2pClient(context).apply {
setPeerPkgName(WATCH_APP_PACKAGE)
setPeerFingerPrint(WATCH_APP_FINGER_PRINT)
}
val message = Message.Builder()
.setPayload(text.toByteArray(StandardCharsets.UTF_8))
.build()
p2pClient.send(device, message, object : SendCallback {
override fun onSendResult(resultCode: Int) {
continuation.resume(resultCode == 200 || resultCode == 202)
}
override fun onSendProgress(progress: Long) {}
}).addOnFailureListener { continuation.resume(false) }
}.onFailure { continuation.resume(false) }
}
}
}
fun isWatchAppInstalled(context: Context, device: Device): Boolean {
return runBlocking {
suspendCoroutine { continuation ->
runCatching {
HiWear.getP2pClient(context)
.isAppInstalled(device, WATCH_APP_PACKAGE)
.addOnSuccessListener { continuation.resume(it) }
.addOnFailureListener { continuation.resume(false) }
}.onFailure { continuation.resume(false) }
}
}
}
}
... ...
package com.doublefeel.app.native
import android.content.Context
import com.doublefeel.app.pigeon.wear.WearDeviceInfo
import com.doublefeel.app.pigeon.wear.WearEngineHostApi
import com.huawei.wearengine.device.Device
class WearEngineHostApiImpl(
private val context: Context,
) : WearEngineHostApi {
private var connectedDevice: Device? = null
override fun hasAvailableDevices(): Boolean {
return HuaweiWearBridge.hasAvailableDevices(context)
}
override fun checkConnectedDevice(): WearDeviceInfo? {
val device = HuaweiWearBridge.getConnectedDevice(context)
if (device == null) {
connectedDevice = null
return null
}
if (HuaweiWearBridge.isWatchAppInstalled(context, device)) {
connectedDevice = device
return WearDeviceInfo(
deviceId = device.uuid,
deviceName = device.name,
isConnected = device.isConnected,
)
}
connectedDevice = null
return null
}
override fun registerMessageReceiver(): Boolean {
val device = connectedDevice ?: HuaweiWearBridge.getConnectedDevice(context)
if (device == null) {
return false
}
connectedDevice = device
return HuaweiWearBridge.registerMessageReceiver(context, device)
}
override fun sendTextMessage(message: String): Boolean {
val device = connectedDevice ?: return false
return HuaweiWearBridge.sendTextMessage(context, device, message)
}
override fun sendWatchSyncPayload(jsonPayload: String): Boolean {
return sendTextMessage(jsonPayload)
}
}
... ...
// // Copyright 2013 The Flutter Authors. All rights reserved.
// Autogenerated from Pigeon (v25.5.0), do not edit directly.
// See also: https://pub.dev/packages/pigeon
@file:Suppress("UNCHECKED_CAST", "ArrayInDataClass")
package com.doublefeel.app.pigeon.alipay
import android.util.Log
import io.flutter.plugin.common.BasicMessageChannel
import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.common.EventChannel
import io.flutter.plugin.common.MessageCodec
import io.flutter.plugin.common.StandardMethodCodec
import io.flutter.plugin.common.StandardMessageCodec
import java.io.ByteArrayOutputStream
import java.nio.ByteBuffer
private object AlipayApiPigeonUtils {
fun wrapResult(result: Any?): List<Any?> {
return listOf(result)
}
fun wrapError(exception: Throwable): List<Any?> {
return if (exception is FlutterError) {
listOf(
exception.code,
exception.message,
exception.details
)
} else {
listOf(
exception.javaClass.simpleName,
exception.toString(),
"Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception)
)
}
}
}
/**
* Error class for passing custom error details to Flutter via a thrown PlatformException.
* @property code The error code.
* @property message The error message.
* @property details The error details. Must be a datatype supported by the api codec.
*/
class FlutterError (
val code: String,
override val message: String? = null,
val details: Any? = null
) : Throwable()
/** Alipay payment result codes. */
enum class AliPayResultCode(val raw: Int) {
SUCCESS(0),
CANCEL(1),
ERROR(2),
UNSUPPORTED(3);
companion object {
fun ofRaw(raw: Int): AliPayResultCode? {
return values().firstOrNull { it.raw == raw }
}
}
}
private open class AlipayApiPigeonCodec : StandardMessageCodec() {
override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? {
return when (type) {
129.toByte() -> {
return (readValue(buffer) as Long?)?.let {
AliPayResultCode.ofRaw(it.toInt())
}
}
else -> super.readValueOfType(type, buffer)
}
}
override fun writeValue(stream: ByteArrayOutputStream, value: Any?) {
when (value) {
is AliPayResultCode -> {
stream.write(129)
writeValue(stream, value.raw)
}
else -> super.writeValue(stream, value)
}
}
}
/** Generated interface from Pigeon that represents a handler of messages from Flutter. */
interface AlipayHostApi {
fun launchAliPay(prepayData: String): AliPayResultCode
companion object {
/** The codec used by AlipayHostApi. */
val codec: MessageCodec<Any?> by lazy {
AlipayApiPigeonCodec()
}
/** Sets up an instance of `AlipayHostApi` to handle messages through the `binaryMessenger`. */
@JvmOverloads
fun setUp(binaryMessenger: BinaryMessenger, api: AlipayHostApi?, messageChannelSuffix: String = "") {
val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else ""
run {
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.doublefeel_flutter.AlipayHostApi.launchAliPay$separatedMessageChannelSuffix", codec)
if (api != null) {
channel.setMessageHandler { message, reply ->
val args = message as List<Any?>
val prepayDataArg = args[0] as String
val wrapped: List<Any?> = try {
listOf(api.launchAliPay(prepayDataArg))
} catch (exception: Throwable) {
AlipayApiPigeonUtils.wrapError(exception)
}
reply.reply(wrapped)
}
} else {
channel.setMessageHandler(null)
}
}
}
}
}
... ...
// // Copyright 2013 The Flutter Authors. All rights reserved.
// Autogenerated from Pigeon (v25.5.0), do not edit directly.
// See also: https://pub.dev/packages/pigeon
@file:Suppress("UNCHECKED_CAST", "ArrayInDataClass")
package com.doublefeel.app.pigeon
import android.util.Log
import io.flutter.plugin.common.BasicMessageChannel
import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.common.EventChannel
import io.flutter.plugin.common.MessageCodec
import io.flutter.plugin.common.StandardMethodCodec
import io.flutter.plugin.common.StandardMessageCodec
import java.io.ByteArrayOutputStream
import java.nio.ByteBuffer
private object HealthKitApiPigeonUtils {
fun wrapResult(result: Any?): List<Any?> {
return listOf(result)
}
fun wrapError(exception: Throwable): List<Any?> {
return if (exception is FlutterError) {
listOf(
exception.code,
exception.message,
exception.details
)
} else {
listOf(
exception.javaClass.simpleName,
exception.toString(),
"Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception)
)
}
}
fun deepEquals(a: Any?, b: Any?): Boolean {
if (a is ByteArray && b is ByteArray) {
return a.contentEquals(b)
}
if (a is IntArray && b is IntArray) {
return a.contentEquals(b)
}
if (a is LongArray && b is LongArray) {
return a.contentEquals(b)
}
if (a is DoubleArray && b is DoubleArray) {
return a.contentEquals(b)
}
if (a is Array<*> && b is Array<*>) {
return a.size == b.size &&
a.indices.all{ deepEquals(a[it], b[it]) }
}
if (a is List<*> && b is List<*>) {
return a.size == b.size &&
a.indices.all{ deepEquals(a[it], b[it]) }
}
if (a is Map<*, *> && b is Map<*, *>) {
return a.size == b.size && a.all {
(b as Map<Any?, Any?>).containsKey(it.key) &&
deepEquals(it.value, b[it.key])
}
}
return a == b
}
}
/**
* Error class for passing custom error details to Flutter via a thrown PlatformException.
* @property code The error code.
* @property message The error message.
* @property details The error details. Must be a datatype supported by the api codec.
*/
class FlutterError (
val code: String,
override val message: String? = null,
val details: Any? = null
) : Throwable()
/** Generated class from Pigeon that represents data sent in messages. */
data class HealthUploadResult (
val commonUploadSuccess: Boolean,
val sleepUploadSuccess: Boolean,
val errorMessage: String? = null
)
{
companion object {
fun fromList(pigeonVar_list: List<Any?>): HealthUploadResult {
val commonUploadSuccess = pigeonVar_list[0] as Boolean
val sleepUploadSuccess = pigeonVar_list[1] as Boolean
val errorMessage = pigeonVar_list[2] as String?
return HealthUploadResult(commonUploadSuccess, sleepUploadSuccess, errorMessage)
}
}
fun toList(): List<Any?> {
return listOf(
commonUploadSuccess,
sleepUploadSuccess,
errorMessage,
)
}
override fun equals(other: Any?): Boolean {
if (other !is HealthUploadResult) {
return false
}
if (this === other) {
return true
}
return HealthKitApiPigeonUtils.deepEquals(toList(), other.toList()) }
override fun hashCode(): Int = toList().hashCode()
}
private open class HealthKitApiPigeonCodec : StandardMessageCodec() {
override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? {
return when (type) {
129.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
HealthUploadResult.fromList(it)
}
}
else -> super.readValueOfType(type, buffer)
}
}
override fun writeValue(stream: ByteArrayOutputStream, value: Any?) {
when (value) {
is HealthUploadResult -> {
stream.write(129)
writeValue(stream, value.toList())
}
else -> super.writeValue(stream, value)
}
}
}
/** Generated interface from Pigeon that represents a handler of messages from Flutter. */
interface HealthKitHostApi {
fun checkHealthAppAuthorization(): Boolean
fun getHealthServerAuthUrl(): String
/** Opens Huawei Health client authorization UI. Returns whether user granted. */
fun requestHealthClientAuthorization(): Boolean
fun cancelHealthAppAuthorization(): Boolean
/** Runs native health read and server upload pipeline. */
fun performHealthUpload(): HealthUploadResult
companion object {
/** The codec used by HealthKitHostApi. */
val codec: MessageCodec<Any?> by lazy {
HealthKitApiPigeonCodec()
}
/** Sets up an instance of `HealthKitHostApi` to handle messages through the `binaryMessenger`. */
@JvmOverloads
fun setUp(binaryMessenger: BinaryMessenger, api: HealthKitHostApi?, messageChannelSuffix: String = "") {
val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else ""
run {
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.doublefeel_flutter.HealthKitHostApi.checkHealthAppAuthorization$separatedMessageChannelSuffix", codec)
if (api != null) {
channel.setMessageHandler { _, reply ->
val wrapped: List<Any?> = try {
listOf(api.checkHealthAppAuthorization())
} catch (exception: Throwable) {
HealthKitApiPigeonUtils.wrapError(exception)
}
reply.reply(wrapped)
}
} else {
channel.setMessageHandler(null)
}
}
run {
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.doublefeel_flutter.HealthKitHostApi.getHealthServerAuthUrl$separatedMessageChannelSuffix", codec)
if (api != null) {
channel.setMessageHandler { _, reply ->
val wrapped: List<Any?> = try {
listOf(api.getHealthServerAuthUrl())
} catch (exception: Throwable) {
HealthKitApiPigeonUtils.wrapError(exception)
}
reply.reply(wrapped)
}
} else {
channel.setMessageHandler(null)
}
}
run {
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.doublefeel_flutter.HealthKitHostApi.requestHealthClientAuthorization$separatedMessageChannelSuffix", codec)
if (api != null) {
channel.setMessageHandler { _, reply ->
val wrapped: List<Any?> = try {
listOf(api.requestHealthClientAuthorization())
} catch (exception: Throwable) {
HealthKitApiPigeonUtils.wrapError(exception)
}
reply.reply(wrapped)
}
} else {
channel.setMessageHandler(null)
}
}
run {
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.doublefeel_flutter.HealthKitHostApi.cancelHealthAppAuthorization$separatedMessageChannelSuffix", codec)
if (api != null) {
channel.setMessageHandler { _, reply ->
val wrapped: List<Any?> = try {
listOf(api.cancelHealthAppAuthorization())
} catch (exception: Throwable) {
HealthKitApiPigeonUtils.wrapError(exception)
}
reply.reply(wrapped)
}
} else {
channel.setMessageHandler(null)
}
}
run {
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.doublefeel_flutter.HealthKitHostApi.performHealthUpload$separatedMessageChannelSuffix", codec)
if (api != null) {
channel.setMessageHandler { _, reply ->
val wrapped: List<Any?> = try {
listOf(api.performHealthUpload())
} catch (exception: Throwable) {
HealthKitApiPigeonUtils.wrapError(exception)
}
reply.reply(wrapped)
}
} else {
channel.setMessageHandler(null)
}
}
}
}
}
... ...
// // Copyright 2013 The Flutter Authors. All rights reserved.
// Autogenerated from Pigeon (v25.5.0), do not edit directly.
// See also: https://pub.dev/packages/pigeon
@file:Suppress("UNCHECKED_CAST", "ArrayInDataClass")
package com.doublefeel.app.pigeon.wear
import android.util.Log
import io.flutter.plugin.common.BasicMessageChannel
import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.common.EventChannel
import io.flutter.plugin.common.MessageCodec
import io.flutter.plugin.common.StandardMethodCodec
import io.flutter.plugin.common.StandardMessageCodec
import java.io.ByteArrayOutputStream
import java.nio.ByteBuffer
private object WearEngineApiPigeonUtils {
fun wrapResult(result: Any?): List<Any?> {
return listOf(result)
}
fun wrapError(exception: Throwable): List<Any?> {
return if (exception is FlutterError) {
listOf(
exception.code,
exception.message,
exception.details
)
} else {
listOf(
exception.javaClass.simpleName,
exception.toString(),
"Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception)
)
}
}
fun deepEquals(a: Any?, b: Any?): Boolean {
if (a is ByteArray && b is ByteArray) {
return a.contentEquals(b)
}
if (a is IntArray && b is IntArray) {
return a.contentEquals(b)
}
if (a is LongArray && b is LongArray) {
return a.contentEquals(b)
}
if (a is DoubleArray && b is DoubleArray) {
return a.contentEquals(b)
}
if (a is Array<*> && b is Array<*>) {
return a.size == b.size &&
a.indices.all{ deepEquals(a[it], b[it]) }
}
if (a is List<*> && b is List<*>) {
return a.size == b.size &&
a.indices.all{ deepEquals(a[it], b[it]) }
}
if (a is Map<*, *> && b is Map<*, *>) {
return a.size == b.size && a.all {
(b as Map<Any?, Any?>).containsKey(it.key) &&
deepEquals(it.value, b[it.key])
}
}
return a == b
}
}
/**
* Error class for passing custom error details to Flutter via a thrown PlatformException.
* @property code The error code.
* @property message The error message.
* @property details The error details. Must be a datatype supported by the api codec.
*/
class FlutterError (
val code: String,
override val message: String? = null,
val details: Any? = null
) : Throwable()
/** Generated class from Pigeon that represents data sent in messages. */
data class WearDeviceInfo (
val deviceId: String? = null,
val deviceName: String? = null,
val isConnected: Boolean? = null
)
{
companion object {
fun fromList(pigeonVar_list: List<Any?>): WearDeviceInfo {
val deviceId = pigeonVar_list[0] as String?
val deviceName = pigeonVar_list[1] as String?
val isConnected = pigeonVar_list[2] as Boolean?
return WearDeviceInfo(deviceId, deviceName, isConnected)
}
}
fun toList(): List<Any?> {
return listOf(
deviceId,
deviceName,
isConnected,
)
}
override fun equals(other: Any?): Boolean {
if (other !is WearDeviceInfo) {
return false
}
if (this === other) {
return true
}
return WearEngineApiPigeonUtils.deepEquals(toList(), other.toList()) }
override fun hashCode(): Int = toList().hashCode()
}
private open class WearEngineApiPigeonCodec : StandardMessageCodec() {
override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? {
return when (type) {
129.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let {
WearDeviceInfo.fromList(it)
}
}
else -> super.readValueOfType(type, buffer)
}
}
override fun writeValue(stream: ByteArrayOutputStream, value: Any?) {
when (value) {
is WearDeviceInfo -> {
stream.write(129)
writeValue(stream, value.toList())
}
else -> super.writeValue(stream, value)
}
}
}
/** Generated interface from Pigeon that represents a handler of messages from Flutter. */
interface WearEngineHostApi {
fun hasAvailableDevices(): Boolean
fun checkConnectedDevice(): WearDeviceInfo?
fun registerMessageReceiver(): Boolean
fun sendTextMessage(message: String): Boolean
fun sendWatchSyncPayload(jsonPayload: String): Boolean
companion object {
/** The codec used by WearEngineHostApi. */
val codec: MessageCodec<Any?> by lazy {
WearEngineApiPigeonCodec()
}
/** Sets up an instance of `WearEngineHostApi` to handle messages through the `binaryMessenger`. */
@JvmOverloads
fun setUp(binaryMessenger: BinaryMessenger, api: WearEngineHostApi?, messageChannelSuffix: String = "") {
val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else ""
run {
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.doublefeel_flutter.WearEngineHostApi.hasAvailableDevices$separatedMessageChannelSuffix", codec)
if (api != null) {
channel.setMessageHandler { _, reply ->
val wrapped: List<Any?> = try {
listOf(api.hasAvailableDevices())
} catch (exception: Throwable) {
WearEngineApiPigeonUtils.wrapError(exception)
}
reply.reply(wrapped)
}
} else {
channel.setMessageHandler(null)
}
}
run {
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.doublefeel_flutter.WearEngineHostApi.checkConnectedDevice$separatedMessageChannelSuffix", codec)
if (api != null) {
channel.setMessageHandler { _, reply ->
val wrapped: List<Any?> = try {
listOf(api.checkConnectedDevice())
} catch (exception: Throwable) {
WearEngineApiPigeonUtils.wrapError(exception)
}
reply.reply(wrapped)
}
} else {
channel.setMessageHandler(null)
}
}
run {
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.doublefeel_flutter.WearEngineHostApi.registerMessageReceiver$separatedMessageChannelSuffix", codec)
if (api != null) {
channel.setMessageHandler { _, reply ->
val wrapped: List<Any?> = try {
listOf(api.registerMessageReceiver())
} catch (exception: Throwable) {
WearEngineApiPigeonUtils.wrapError(exception)
}
reply.reply(wrapped)
}
} else {
channel.setMessageHandler(null)
}
}
run {
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.doublefeel_flutter.WearEngineHostApi.sendTextMessage$separatedMessageChannelSuffix", codec)
if (api != null) {
channel.setMessageHandler { message, reply ->
val args = message as List<Any?>
val messageArg = args[0] as String
val wrapped: List<Any?> = try {
listOf(api.sendTextMessage(messageArg))
} catch (exception: Throwable) {
WearEngineApiPigeonUtils.wrapError(exception)
}
reply.reply(wrapped)
}
} else {
channel.setMessageHandler(null)
}
}
run {
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.doublefeel_flutter.WearEngineHostApi.sendWatchSyncPayload$separatedMessageChannelSuffix", codec)
if (api != null) {
channel.setMessageHandler { message, reply ->
val args = message as List<Any?>
val jsonPayloadArg = args[0] as String
val wrapped: List<Any?> = try {
listOf(api.sendWatchSyncPayload(jsonPayloadArg))
} catch (exception: Throwable) {
WearEngineApiPigeonUtils.wrapError(exception)
}
reply.reply(wrapped)
}
} else {
channel.setMessageHandler(null)
}
}
}
}
}
... ...
<?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>
... ...
<?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>
... ...
<?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>
... ...
<?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>
... ...
allprojects {
repositories {
google()
mavenCentral()
maven { url "https://developer.huawei.com/repo/" }
maven { url "https://mirrors.huaweicloud.com/repository/maven/" }
maven { url "https://jitpack.io" }
}
}
rootProject.buildDir = "../build"
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
project.evaluationDependsOn(":app")
}
tasks.register("clean", Delete) {
delete rootProject.buildDir
}
... ...
org.gradle.jvmargs=-Xmx4G -XX:MaxMetaspaceSize=2G -XX:+HeapDumpOnOutOfMemoryError
android.useAndroidX=true
android.enableJetifier=true
... ...
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-all.zip
... ...
pluginManagement {
def flutterSdkPath = {
def properties = new Properties()
file("local.properties").withInputStream { properties.load(it) }
def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
return flutterSdkPath
}()
includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
repositories {
google()
mavenCentral()
gradlePluginPortal()
maven { url "https://developer.huawei.com/repo/" }
}
}
plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id "com.android.application" version "8.3.2" apply false
id "org.jetbrains.kotlin.android" version "1.8.22" apply false
}
include ":app"
... ...
No preview for this file type
<svg preserveAspectRatio="none" width="100%" height="100%" overflow="visible" style="display: block;" viewBox="0 0 76.3555 45.7217" fill="none" xmlns="http://www.w3.org/2000/svg">
<path id="Subtract" d="M57.6094 0C57.6094 2.52513 59.6565 4.57227 62.1816 4.57227C64.6278 4.57216 66.6256 2.65105 66.748 0.235352L66.7539 0H70.8682C73.8982 0 76.3553 2.45629 76.3555 5.48633V40.2354C76.3553 43.2654 73.8982 45.7217 70.8682 45.7217H66.7539C66.7538 43.1967 64.7066 41.1495 62.1816 41.1494C59.6565 41.1494 57.6094 43.1966 57.6094 45.7217H5.48633C2.45638 45.7215 0.000155327 43.2653 0 40.2354V5.48633C0.000145425 2.45638 2.45638 0.000147154 5.48633 0H57.6094Z" fill="var(--fill-0, #916DF7)"/>
</svg>
... ...
targets:
$default:
builders:
json_serializable:
options:
explicit_to_json: true
include_if_null: false
... ...
**/dgph
*.mode1v3
*.mode2v3
*.moved-aside
*.pbxuser
*.perspectivev3
**/*sync/
.sconsign.dblite
.tags*
**/.vagrant/
**/DerivedData/
Icon?
**/Pods/
**/.symlinks/
profile
xcuserdata
**/.generated/
Flutter/App.framework
Flutter/Flutter.framework
Flutter/Flutter.podspec
Flutter/Generated.xcconfig
Flutter/ephemeral/
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
... ...
<?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>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>13.0</string>
</dict>
</plist>
... ...
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include "Generated.xcconfig"
... ...
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "Generated.xcconfig"
... ...
platform :ios, '13.0'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
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!
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
target 'RunnerTests' do
inherit! :search_paths
end
end
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
end
end
... ...
PODS:
- Flutter (1.0.0)
- image_cropper (0.0.4):
- Flutter
- TOCropViewController (~> 2.7.4)
- image_picker_ios (0.0.1):
- Flutter
- path_provider_foundation (0.0.1):
- Flutter
- FlutterMacOS
- permission_handler_apple (9.3.0):
- Flutter
- shared_preferences_foundation (0.0.1):
- Flutter
- FlutterMacOS
- sqflite_darwin (0.0.4):
- Flutter
- FlutterMacOS
- TOCropViewController (2.7.4)
- webview_flutter_wkwebview (0.0.1):
- Flutter
- FlutterMacOS
DEPENDENCIES:
- Flutter (from `Flutter`)
- image_cropper (from `.symlinks/plugins/image_cropper/ios`)
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
- sqflite_darwin (from `.symlinks/plugins/sqflite_darwin/darwin`)
- webview_flutter_wkwebview (from `.symlinks/plugins/webview_flutter_wkwebview/darwin`)
SPEC REPOS:
trunk:
- TOCropViewController
EXTERNAL SOURCES:
Flutter:
:path: Flutter
image_cropper:
:path: ".symlinks/plugins/image_cropper/ios"
image_picker_ios:
:path: ".symlinks/plugins/image_picker_ios/ios"
path_provider_foundation:
:path: ".symlinks/plugins/path_provider_foundation/darwin"
permission_handler_apple:
:path: ".symlinks/plugins/permission_handler_apple/ios"
shared_preferences_foundation:
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
sqflite_darwin:
:path: ".symlinks/plugins/sqflite_darwin/darwin"
webview_flutter_wkwebview:
:path: ".symlinks/plugins/webview_flutter_wkwebview/darwin"
SPEC CHECKSUMS:
Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
image_cropper: c4326ea50132b1e1564499e5d32a84f01fb03537
image_picker_ios: 7fe1ff8e34c1790d6fff70a32484959f563a928a
path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
permission_handler_apple: 4ed2196e43d0651e8ff7ca3483a069d469701f2d
shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7
sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0
TOCropViewController: 80b8985ad794298fb69d3341de183f33d1853654
webview_flutter_wkwebview: 1821ceac936eba6f7984d89a9f3bcb4dea99ebb2
PODFILE CHECKSUM: ade96bceabe3919b69c16573938e4268fe3a6c9d
COCOAPODS: 1.16.2
... ...
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 54;
objects = {
/* Begin PBXBuildFile section */
0D37801EADFB01D2BF214330 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D813EFE9B8AFD28D707C26F9 /* Pods_Runner.framework */; };
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
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 */; };
DF01A2B41CF9000F007C001 /* HealthKitApi.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF01A2B31CF9000F007C001 /* HealthKitApi.swift */; };
DF01A2B41CF9000F007C002 /* WearEngineApi.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF01A2B31CF9000F007C002 /* WearEngineApi.swift */; };
DF01A2B41CF9000F007C003 /* AlipayApi.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF01A2B31CF9000F007C003 /* AlipayApi.swift */; };
DF01A2B41CF9000F007C004 /* NativeHostApiStubs.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF01A2B31CF9000F007C004 /* NativeHostApiStubs.swift */; };
DF01A2B41CF9000F007C005 /* PigeonShared.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF01A2B31CF9000F007C005 /* PigeonShared.swift */; };
EA47CAD80DF77F162CC86851 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FD2FC62391A106A0C6E9CF39 /* Pods_RunnerTests.framework */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 97C146E61CF9000F007C117D /* Project object */;
proxyType = 1;
remoteGlobalIDString = 97C146ED1CF9000F007C117D;
remoteInfo = Runner;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
9705A1C41CF9048500538489 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
0D1CEDE9C3295903C8FCF702 /* 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>"; };
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>"; };
2ECF3C9772810B1582D524F4 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = "<group>"; };
331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
5620C49637B3BA24A7B2A069 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = "<group>"; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
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>"; };
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>"; };
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>"; };
98740F53C55D411DD8809A3F /* 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>"; };
9D26AF01D43E742248474B60 /* 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>"; };
D0BB543595814545A916196E /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = "<group>"; };
D813EFE9B8AFD28D707C26F9 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
DF01A2B31CF9000F007C001 /* HealthKitApi.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HealthKitApi.swift; sourceTree = "<group>"; };
DF01A2B31CF9000F007C002 /* WearEngineApi.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WearEngineApi.swift; sourceTree = "<group>"; };
DF01A2B31CF9000F007C003 /* AlipayApi.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlipayApi.swift; sourceTree = "<group>"; };
DF01A2B31CF9000F007C004 /* NativeHostApiStubs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NativeHostApiStubs.swift; sourceTree = "<group>"; };
DF01A2B31CF9000F007C005 /* PigeonShared.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PigeonShared.swift; sourceTree = "<group>"; };
FD2FC62391A106A0C6E9CF39 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
71910C375FB994D0ECBC6E88 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
EA47CAD80DF77F162CC86851 /* Pods_RunnerTests.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
97C146EB1CF9000F007C117D /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
0D37801EADFB01D2BF214330 /* Pods_Runner.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
331C8082294A63A400263BE5 /* RunnerTests */ = {
isa = PBXGroup;
children = (
331C807B294A618700263BE5 /* RunnerTests.swift */,
);
path = RunnerTests;
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 = (
9740EEB11CF90186004384FC /* Flutter */,
97C146F01CF9000F007C117D /* Runner */,
97C146EF1CF9000F007C117D /* Products */,
331C8082294A63A400263BE5 /* RunnerTests */,
A46DE786AD5506CE018A4A59 /* Pods */,
97D312C4F82913758AF2C32D /* Frameworks */,
);
sourceTree = "<group>";
};
97C146EF1CF9000F007C117D /* Products */ = {
isa = PBXGroup;
children = (
97C146EE1CF9000F007C117D /* Runner.app */,
331C8081294A63A400263BE5 /* RunnerTests.xctest */,
);
name = Products;
sourceTree = "<group>";
};
97C146F01CF9000F007C117D /* Runner */ = {
isa = PBXGroup;
children = (
97C146FA1CF9000F007C117D /* Main.storyboard */,
97C146FD1CF9000F007C117D /* Assets.xcassets */,
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
97C147021CF9000F007C117D /* Info.plist */,
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
DF01A2B51CF9000F007C001 /* Pigeon */,
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
);
path = Runner;
sourceTree = "<group>";
};
97D312C4F82913758AF2C32D /* Frameworks */ = {
isa = PBXGroup;
children = (
D813EFE9B8AFD28D707C26F9 /* Pods_Runner.framework */,
FD2FC62391A106A0C6E9CF39 /* Pods_RunnerTests.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
A46DE786AD5506CE018A4A59 /* Pods */ = {
isa = PBXGroup;
children = (
0D1CEDE9C3295903C8FCF702 /* Pods-Runner.debug.xcconfig */,
9D26AF01D43E742248474B60 /* Pods-Runner.release.xcconfig */,
98740F53C55D411DD8809A3F /* Pods-Runner.profile.xcconfig */,
D0BB543595814545A916196E /* Pods-RunnerTests.debug.xcconfig */,
2ECF3C9772810B1582D524F4 /* Pods-RunnerTests.release.xcconfig */,
5620C49637B3BA24A7B2A069 /* Pods-RunnerTests.profile.xcconfig */,
);
name = Pods;
path = Pods;
sourceTree = "<group>";
};
DF01A2B51CF9000F007C001 /* Pigeon */ = {
isa = PBXGroup;
children = (
DF01A2B31CF9000F007C005 /* PigeonShared.swift */,
DF01A2B31CF9000F007C001 /* HealthKitApi.swift */,
DF01A2B31CF9000F007C002 /* WearEngineApi.swift */,
DF01A2B31CF9000F007C003 /* AlipayApi.swift */,
DF01A2B31CF9000F007C004 /* NativeHostApiStubs.swift */,
);
path = Pigeon;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
331C8080294A63A400263BE5 /* RunnerTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
buildPhases = (
FA6A63AA7E44E76FF1168BF2 /* [CP] Check Pods Manifest.lock */,
331C807D294A63A400263BE5 /* Sources */,
331C807F294A63A400263BE5 /* Resources */,
71910C375FB994D0ECBC6E88 /* Frameworks */,
);
buildRules = (
);
dependencies = (
331C8086294A63A400263BE5 /* PBXTargetDependency */,
);
name = RunnerTests;
productName = RunnerTests;
productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
97C146ED1CF9000F007C117D /* Runner */ = {
isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
30EE1EAEF04FCF17330C508E /* [CP] Check Pods Manifest.lock */,
9740EEB61CF901F6004384FC /* Run Script */,
97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */,
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
2CBFB5724AAC059A33245577 /* [CP] Embed Pods Frameworks */,
91949B6425377114094461C0 /* [CP] Copy Pods Resources */,
);
buildRules = (
);
dependencies = (
);
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;
LastUpgradeCheck = 1510;
ORGANIZATIONNAME = "";
TargetAttributes = {
331C8080294A63A400263BE5 = {
CreatedOnToolsVersion = 14.0;
TestTargetID = 97C146ED1CF9000F007C117D;
};
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 */,
331C8080294A63A400263BE5 /* RunnerTests */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
331C807F294A63A400263BE5 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
97C146EC1CF9000F007C117D /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
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 */
2CBFB5724AAC059A33245577 /* [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;
};
30EE1EAEF04FCF17330C508E /* [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;
};
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";
};
91949B6425377114094461C0 /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Copy Pods Resources";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\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";
};
FA6A63AA7E44E76FF1168BF2 /* [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-RunnerTests-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;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
331C807D294A63A400263BE5 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
97C146EA1CF9000F007C117D /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
DF01A2B41CF9000F007C005 /* PigeonShared.swift in Sources */,
DF01A2B41CF9000F007C001 /* HealthKitApi.swift in Sources */,
DF01A2B41CF9000F007C002 /* WearEngineApi.swift in Sources */,
DF01A2B41CF9000F007C003 /* AlipayApi.swift in Sources */,
DF01A2B41CF9000F007C004 /* NativeHostApiStubs.swift in Sources */,
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
331C8086294A63A400263BE5 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 97C146ED1CF9000F007C117D /* Runner */;
targetProxy = 331C8085294A63A400263BE5 /* 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;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
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_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_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
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 = 13.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Profile;
};
249021D4217E4FDB00AE95B9 /* Profile */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = ZRPLMC329K;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.luiz.doublefeel;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = Profile;
};
331C8088294A63A400263BE5 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = D0BB543595814545A916196E /* Pods-RunnerTests.debug.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.luiz.doublefeel.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
};
name = Debug;
};
331C8089294A63A400263BE5 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 2ECF3C9772810B1582D524F4 /* Pods-RunnerTests.release.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.luiz.doublefeel.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
};
name = Release;
};
331C808A294A63A400263BE5 /* Profile */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 5620C49637B3BA24A7B2A069 /* Pods-RunnerTests.profile.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.luiz.doublefeel.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
};
name = Profile;
};
97C147031CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
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_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_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
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 = 13.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
97C147041CF9000F007C117D /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
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_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_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
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 = 13.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
97C147061CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = ZRPLMC329K;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.luiz.doublefeel;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = Debug;
};
97C147071CF9000F007C117D /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = ZRPLMC329K;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.luiz.doublefeel;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
331C8088294A63A400263BE5 /* Debug */,
331C8089294A63A400263BE5 /* Release */,
331C808A294A63A400263BE5 /* 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 */;
}
... ...
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>
... ...
<?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>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
... ...
<?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>PreviewsEnabled</key>
<false/>
</dict>
</plist>
... ...
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1510"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
shouldUseLaunchSchemeArgsEnv = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</MacroExpansion>
<Testables>
<TestableReference
skipped = "NO"
parallelizable = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "331C8080294A63A400263BE5"
BuildableName = "RunnerTests.xctest"
BlueprintName = "RunnerTests"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
enableGPUValidationMode = "1"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Profile"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
... ...
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:Runner.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace>
... ...
<?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>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
... ...
<?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>PreviewsEnabled</key>
<false/>
</dict>
</plist>
... ...
import Flutter
import UIKit
@main
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
if let controller = window?.rootViewController as? FlutterViewController {
NativePigeonRegistrar.register(binaryMessenger: controller.binaryMessenger)
}
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
... ...
{
"images" : [
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "Icon-App-20x20@2x.png",
"scale" : "2x"
},
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "Icon-App-20x20@3x.png",
"scale" : "3x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@1x.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@2x.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@3x.png",
"scale" : "3x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-App-40x40@2x.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-App-40x40@3x.png",
"scale" : "3x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-App-60x60@2x.png",
"scale" : "2x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-App-60x60@3x.png",
"scale" : "3x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "Icon-App-20x20@1x.png",
"scale" : "1x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "Icon-App-20x20@2x.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-App-29x29@1x.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-App-29x29@2x.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-App-40x40@1x.png",
"scale" : "1x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-App-40x40@2x.png",
"scale" : "2x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-App-76x76@1x.png",
"scale" : "1x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-App-76x76@2x.png",
"scale" : "2x"
},
{
"size" : "83.5x83.5",
"idiom" : "ipad",
"filename" : "Icon-App-83.5x83.5@2x.png",
"scale" : "2x"
},
{
"size" : "1024x1024",
"idiom" : "ios-marketing",
"filename" : "Icon-App-1024x1024@1x.png",
"scale" : "1x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
... ...
{
"images" : [
{
"idiom" : "universal",
"filename" : "LaunchImage.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "LaunchImage@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "LaunchImage@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
... ...
# Launch Screen Assets
You can customize the launch screen with your own desired assets by replacing the image files in this directory.
You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
\ No newline at end of file
... ...
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="Ydg-fD-yQy"/>
<viewControllerLayoutGuide type="bottom" id="xbc-2k-c8Z"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4">
</imageView>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="1a2-6s-vTC"/>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="4X2-HB-R7a"/>
</constraints>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
<resources>
<image name="LaunchImage" width="168" height="185"/>
</resources>
</document>
... ...
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
</dependencies>
<scenes>
<!--Flutter View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="FlutterViewController" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
</scene>
</scenes>
</document>
... ...
<?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>Doublefeel Flutter</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>doublefeel_flutter</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>$(FLUTTER_BUILD_NAME)</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>$(FLUTTER_BUILD_NUMBER)</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
</dict>
</plist>
... ...
// // Copyright 2013 The Flutter Authors. All rights reserved.
// Autogenerated from Pigeon (v25.5.0), do not edit directly.
// See also: https://pub.dev/packages/pigeon
import Foundation
#if os(iOS)
import Flutter
#elseif os(macOS)
import FlutterMacOS
#else
#error("Unsupported platform.")
#endif
private func wrapResult(_ result: Any?) -> [Any?] {
return [result]
}
private func wrapError(_ error: Any) -> [Any?] {
if let pigeonError = error as? PigeonError {
return [
pigeonError.code,
pigeonError.message,
pigeonError.details,
]
}
if let flutterError = error as? FlutterError {
return [
flutterError.code,
flutterError.message,
flutterError.details,
]
}
return [
"\(error)",
"\(type(of: error))",
"Stacktrace: \(Thread.callStackSymbols)",
]
}
private func isNullish(_ value: Any?) -> Bool {
return value is NSNull || value == nil
}
private func nilOrValue<T>(_ value: Any?) -> T? {
if value is NSNull { return nil }
return value as! T?
}
/// Alipay payment result codes.
enum AliPayResultCode: Int {
case success = 0
case cancel = 1
case error = 2
case unsupported = 3
}
private class AlipayApiPigeonCodecReader: FlutterStandardReader {
override func readValue(ofType type: UInt8) -> Any? {
switch type {
case 129:
let enumResultAsInt: Int? = nilOrValue(self.readValue() as! Int?)
if let enumResultAsInt = enumResultAsInt {
return AliPayResultCode(rawValue: enumResultAsInt)
}
return nil
default:
return super.readValue(ofType: type)
}
}
}
private class AlipayApiPigeonCodecWriter: FlutterStandardWriter {
override func writeValue(_ value: Any) {
if let value = value as? AliPayResultCode {
super.writeByte(129)
super.writeValue(value.rawValue)
} else {
super.writeValue(value)
}
}
}
private class AlipayApiPigeonCodecReaderWriter: FlutterStandardReaderWriter {
override func reader(with data: Data) -> FlutterStandardReader {
return AlipayApiPigeonCodecReader(data: data)
}
override func writer(with data: NSMutableData) -> FlutterStandardWriter {
return AlipayApiPigeonCodecWriter(data: data)
}
}
class AlipayApiPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable {
static let shared = AlipayApiPigeonCodec(readerWriter: AlipayApiPigeonCodecReaderWriter())
}
/// Generated protocol from Pigeon that represents a handler of messages from Flutter.
protocol AlipayHostApi {
func launchAliPay(prepayData: String) throws -> AliPayResultCode
}
/// Generated setup class from Pigeon to handle messages through the `binaryMessenger`.
class AlipayHostApiSetup {
static var codec: FlutterStandardMessageCodec { AlipayApiPigeonCodec.shared }
/// Sets up an instance of `AlipayHostApi` to handle messages through the `binaryMessenger`.
static func setUp(binaryMessenger: FlutterBinaryMessenger, api: AlipayHostApi?, messageChannelSuffix: String = "") {
let channelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : ""
let launchAliPayChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.doublefeel_flutter.AlipayHostApi.launchAliPay\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
if let api = api {
launchAliPayChannel.setMessageHandler { message, reply in
let args = message as! [Any?]
let prepayDataArg = args[0] as! String
do {
let result = try api.launchAliPay(prepayData: prepayDataArg)
reply(wrapResult(result))
} catch {
reply(wrapError(error))
}
}
} else {
launchAliPayChannel.setMessageHandler(nil)
}
}
}
... ...
// // Copyright 2013 The Flutter Authors. All rights reserved.
// Autogenerated from Pigeon (v25.5.0), do not edit directly.
// See also: https://pub.dev/packages/pigeon
import Foundation
#if os(iOS)
import Flutter
#elseif os(macOS)
import FlutterMacOS
#else
#error("Unsupported platform.")
#endif
private func wrapResult(_ result: Any?) -> [Any?] {
return [result]
}
private func wrapError(_ error: Any) -> [Any?] {
if let pigeonError = error as? PigeonError {
return [
pigeonError.code,
pigeonError.message,
pigeonError.details,
]
}
if let flutterError = error as? FlutterError {
return [
flutterError.code,
flutterError.message,
flutterError.details,
]
}
return [
"\(error)",
"\(type(of: error))",
"Stacktrace: \(Thread.callStackSymbols)",
]
}
private func isNullish(_ value: Any?) -> Bool {
return value is NSNull || value == nil
}
private func nilOrValue<T>(_ value: Any?) -> T? {
if value is NSNull { return nil }
return value as! T?
}
func deepEqualsHealthKitApi(_ lhs: Any?, _ rhs: Any?) -> Bool {
let cleanLhs = nilOrValue(lhs) as Any?
let cleanRhs = nilOrValue(rhs) as Any?
switch (cleanLhs, cleanRhs) {
case (nil, nil):
return true
case (nil, _), (_, nil):
return false
case is (Void, Void):
return true
case let (cleanLhsHashable, cleanRhsHashable) as (AnyHashable, AnyHashable):
return cleanLhsHashable == cleanRhsHashable
case let (cleanLhsArray, cleanRhsArray) as ([Any?], [Any?]):
guard cleanLhsArray.count == cleanRhsArray.count else { return false }
for (index, element) in cleanLhsArray.enumerated() {
if !deepEqualsHealthKitApi(element, cleanRhsArray[index]) {
return false
}
}
return true
case let (cleanLhsDictionary, cleanRhsDictionary) as ([AnyHashable: Any?], [AnyHashable: Any?]):
guard cleanLhsDictionary.count == cleanRhsDictionary.count else { return false }
for (key, cleanLhsValue) in cleanLhsDictionary {
guard cleanRhsDictionary.index(forKey: key) != nil else { return false }
if !deepEqualsHealthKitApi(cleanLhsValue, cleanRhsDictionary[key]!) {
return false
}
}
return true
default:
// Any other type shouldn't be able to be used with pigeon. File an issue if you find this to be untrue.
return false
}
}
func deepHashHealthKitApi(value: Any?, hasher: inout Hasher) {
if let valueList = value as? [AnyHashable] {
for item in valueList { deepHashHealthKitApi(value: item, hasher: &hasher) }
return
}
if let valueDict = value as? [AnyHashable: AnyHashable] {
for key in valueDict.keys {
hasher.combine(key)
deepHashHealthKitApi(value: valueDict[key]!, hasher: &hasher)
}
return
}
if let hashableValue = value as? AnyHashable {
hasher.combine(hashableValue.hashValue)
}
return hasher.combine(String(describing: value))
}
/// Generated class from Pigeon that represents data sent in messages.
struct HealthUploadResult: Hashable {
var commonUploadSuccess: Bool
var sleepUploadSuccess: Bool
var errorMessage: String? = nil
// swift-format-ignore: AlwaysUseLowerCamelCase
static func fromList(_ pigeonVar_list: [Any?]) -> HealthUploadResult? {
let commonUploadSuccess = pigeonVar_list[0] as! Bool
let sleepUploadSuccess = pigeonVar_list[1] as! Bool
let errorMessage: String? = nilOrValue(pigeonVar_list[2])
return HealthUploadResult(
commonUploadSuccess: commonUploadSuccess,
sleepUploadSuccess: sleepUploadSuccess,
errorMessage: errorMessage
)
}
func toList() -> [Any?] {
return [
commonUploadSuccess,
sleepUploadSuccess,
errorMessage,
]
}
static func == (lhs: HealthUploadResult, rhs: HealthUploadResult) -> Bool {
return deepEqualsHealthKitApi(lhs.toList(), rhs.toList()) }
func hash(into hasher: inout Hasher) {
deepHashHealthKitApi(value: toList(), hasher: &hasher)
}
}
private class HealthKitApiPigeonCodecReader: FlutterStandardReader {
override func readValue(ofType type: UInt8) -> Any? {
switch type {
case 129:
return HealthUploadResult.fromList(self.readValue() as! [Any?])
default:
return super.readValue(ofType: type)
}
}
}
private class HealthKitApiPigeonCodecWriter: FlutterStandardWriter {
override func writeValue(_ value: Any) {
if let value = value as? HealthUploadResult {
super.writeByte(129)
super.writeValue(value.toList())
} else {
super.writeValue(value)
}
}
}
private class HealthKitApiPigeonCodecReaderWriter: FlutterStandardReaderWriter {
override func reader(with data: Data) -> FlutterStandardReader {
return HealthKitApiPigeonCodecReader(data: data)
}
override func writer(with data: NSMutableData) -> FlutterStandardWriter {
return HealthKitApiPigeonCodecWriter(data: data)
}
}
class HealthKitApiPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable {
static let shared = HealthKitApiPigeonCodec(readerWriter: HealthKitApiPigeonCodecReaderWriter())
}
/// Generated protocol from Pigeon that represents a handler of messages from Flutter.
protocol HealthKitHostApi {
func checkHealthAppAuthorization() throws -> Bool
func getHealthServerAuthUrl() throws -> String
/// Opens Huawei Health client authorization UI. Returns whether user granted.
func requestHealthClientAuthorization() throws -> Bool
func cancelHealthAppAuthorization() throws -> Bool
/// Runs native health read and server upload pipeline.
func performHealthUpload() throws -> HealthUploadResult
}
/// Generated setup class from Pigeon to handle messages through the `binaryMessenger`.
class HealthKitHostApiSetup {
static var codec: FlutterStandardMessageCodec { HealthKitApiPigeonCodec.shared }
/// Sets up an instance of `HealthKitHostApi` to handle messages through the `binaryMessenger`.
static func setUp(binaryMessenger: FlutterBinaryMessenger, api: HealthKitHostApi?, messageChannelSuffix: String = "") {
let channelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : ""
let checkHealthAppAuthorizationChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.doublefeel_flutter.HealthKitHostApi.checkHealthAppAuthorization\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
if let api = api {
checkHealthAppAuthorizationChannel.setMessageHandler { _, reply in
do {
let result = try api.checkHealthAppAuthorization()
reply(wrapResult(result))
} catch {
reply(wrapError(error))
}
}
} else {
checkHealthAppAuthorizationChannel.setMessageHandler(nil)
}
let getHealthServerAuthUrlChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.doublefeel_flutter.HealthKitHostApi.getHealthServerAuthUrl\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
if let api = api {
getHealthServerAuthUrlChannel.setMessageHandler { _, reply in
do {
let result = try api.getHealthServerAuthUrl()
reply(wrapResult(result))
} catch {
reply(wrapError(error))
}
}
} else {
getHealthServerAuthUrlChannel.setMessageHandler(nil)
}
/// Opens Huawei Health client authorization UI. Returns whether user granted.
let requestHealthClientAuthorizationChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.doublefeel_flutter.HealthKitHostApi.requestHealthClientAuthorization\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
if let api = api {
requestHealthClientAuthorizationChannel.setMessageHandler { _, reply in
do {
let result = try api.requestHealthClientAuthorization()
reply(wrapResult(result))
} catch {
reply(wrapError(error))
}
}
} else {
requestHealthClientAuthorizationChannel.setMessageHandler(nil)
}
let cancelHealthAppAuthorizationChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.doublefeel_flutter.HealthKitHostApi.cancelHealthAppAuthorization\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
if let api = api {
cancelHealthAppAuthorizationChannel.setMessageHandler { _, reply in
do {
let result = try api.cancelHealthAppAuthorization()
reply(wrapResult(result))
} catch {
reply(wrapError(error))
}
}
} else {
cancelHealthAppAuthorizationChannel.setMessageHandler(nil)
}
/// Runs native health read and server upload pipeline.
let performHealthUploadChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.doublefeel_flutter.HealthKitHostApi.performHealthUpload\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
if let api = api {
performHealthUploadChannel.setMessageHandler { _, reply in
do {
let result = try api.performHealthUpload()
reply(wrapResult(result))
} catch {
reply(wrapError(error))
}
}
} else {
performHealthUploadChannel.setMessageHandler(nil)
}
}
}
... ...
import Foundation
import Flutter
private let unsupported = "HealthKit / WearEngine / Alipay are not supported on iOS in this build."
final class HealthKitHostApiStub: HealthKitHostApi {
func checkHealthAppAuthorization() throws -> Bool { false }
func getHealthServerAuthUrl() throws -> String { "" }
func requestHealthClientAuthorization() throws -> Bool { false }
func cancelHealthAppAuthorization() throws -> Bool { false }
func performHealthUpload() throws -> HealthUploadResult {
HealthUploadResult(commonUploadSuccess: false, sleepUploadSuccess: false, errorMessage: unsupported)
}
}
final class WearEngineHostApiStub: WearEngineHostApi {
func hasAvailableDevices() throws -> Bool { false }
func checkConnectedDevice() throws -> WearDeviceInfo? { nil }
func registerMessageReceiver() throws -> Bool { false }
func sendTextMessage(message: String) throws -> Bool { false }
func sendWatchSyncPayload(jsonPayload: String) throws -> Bool { false }
}
final class AlipayHostApiStub: AlipayHostApi {
func launchAliPay(prepayData: String) throws -> AliPayResultCode { .unsupported }
}
enum NativePigeonRegistrar {
static func register(binaryMessenger: FlutterBinaryMessenger) {
HealthKitHostApiSetup.setUp(binaryMessenger: binaryMessenger, api: HealthKitHostApiStub())
WearEngineHostApiSetup.setUp(binaryMessenger: binaryMessenger, api: WearEngineHostApiStub())
AlipayHostApiSetup.setUp(binaryMessenger: binaryMessenger, api: AlipayHostApiStub())
}
}
... ...
// Shared Pigeon types for all generated API files in this target.
// Pigeon emits PigeonError in every swiftOut file; only one definition is allowed per module.
import Foundation
/// Error class for passing custom error details to Dart side.
final class PigeonError: Error {
let code: String
let message: String?
let details: Sendable?
init(code: String, message: String?, details: Sendable?) {
self.code = code
self.message = message
self.details = details
}
var localizedDescription: String {
return
"PigeonError(code: \(code), message: \(message ?? "<nil>"), details: \(details ?? "<nil>")"
}
}
... ...
// // Copyright 2013 The Flutter Authors. All rights reserved.
// Autogenerated from Pigeon (v25.5.0), do not edit directly.
// See also: https://pub.dev/packages/pigeon
import Foundation
#if os(iOS)
import Flutter
#elseif os(macOS)
import FlutterMacOS
#else
#error("Unsupported platform.")
#endif
private func wrapResult(_ result: Any?) -> [Any?] {
return [result]
}
private func wrapError(_ error: Any) -> [Any?] {
if let pigeonError = error as? PigeonError {
return [
pigeonError.code,
pigeonError.message,
pigeonError.details,
]
}
if let flutterError = error as? FlutterError {
return [
flutterError.code,
flutterError.message,
flutterError.details,
]
}
return [
"\(error)",
"\(type(of: error))",
"Stacktrace: \(Thread.callStackSymbols)",
]
}
private func isNullish(_ value: Any?) -> Bool {
return value is NSNull || value == nil
}
private func nilOrValue<T>(_ value: Any?) -> T? {
if value is NSNull { return nil }
return value as! T?
}
func deepEqualsWearEngineApi(_ lhs: Any?, _ rhs: Any?) -> Bool {
let cleanLhs = nilOrValue(lhs) as Any?
let cleanRhs = nilOrValue(rhs) as Any?
switch (cleanLhs, cleanRhs) {
case (nil, nil):
return true
case (nil, _), (_, nil):
return false
case is (Void, Void):
return true
case let (cleanLhsHashable, cleanRhsHashable) as (AnyHashable, AnyHashable):
return cleanLhsHashable == cleanRhsHashable
case let (cleanLhsArray, cleanRhsArray) as ([Any?], [Any?]):
guard cleanLhsArray.count == cleanRhsArray.count else { return false }
for (index, element) in cleanLhsArray.enumerated() {
if !deepEqualsWearEngineApi(element, cleanRhsArray[index]) {
return false
}
}
return true
case let (cleanLhsDictionary, cleanRhsDictionary) as ([AnyHashable: Any?], [AnyHashable: Any?]):
guard cleanLhsDictionary.count == cleanRhsDictionary.count else { return false }
for (key, cleanLhsValue) in cleanLhsDictionary {
guard cleanRhsDictionary.index(forKey: key) != nil else { return false }
if !deepEqualsWearEngineApi(cleanLhsValue, cleanRhsDictionary[key]!) {
return false
}
}
return true
default:
// Any other type shouldn't be able to be used with pigeon. File an issue if you find this to be untrue.
return false
}
}
func deepHashWearEngineApi(value: Any?, hasher: inout Hasher) {
if let valueList = value as? [AnyHashable] {
for item in valueList { deepHashWearEngineApi(value: item, hasher: &hasher) }
return
}
if let valueDict = value as? [AnyHashable: AnyHashable] {
for key in valueDict.keys {
hasher.combine(key)
deepHashWearEngineApi(value: valueDict[key]!, hasher: &hasher)
}
return
}
if let hashableValue = value as? AnyHashable {
hasher.combine(hashableValue.hashValue)
}
return hasher.combine(String(describing: value))
}
/// Generated class from Pigeon that represents data sent in messages.
struct WearDeviceInfo: Hashable {
var deviceId: String? = nil
var deviceName: String? = nil
var isConnected: Bool? = nil
// swift-format-ignore: AlwaysUseLowerCamelCase
static func fromList(_ pigeonVar_list: [Any?]) -> WearDeviceInfo? {
let deviceId: String? = nilOrValue(pigeonVar_list[0])
let deviceName: String? = nilOrValue(pigeonVar_list[1])
let isConnected: Bool? = nilOrValue(pigeonVar_list[2])
return WearDeviceInfo(
deviceId: deviceId,
deviceName: deviceName,
isConnected: isConnected
)
}
func toList() -> [Any?] {
return [
deviceId,
deviceName,
isConnected,
]
}
static func == (lhs: WearDeviceInfo, rhs: WearDeviceInfo) -> Bool {
return deepEqualsWearEngineApi(lhs.toList(), rhs.toList()) }
func hash(into hasher: inout Hasher) {
deepHashWearEngineApi(value: toList(), hasher: &hasher)
}
}
private class WearEngineApiPigeonCodecReader: FlutterStandardReader {
override func readValue(ofType type: UInt8) -> Any? {
switch type {
case 129:
return WearDeviceInfo.fromList(self.readValue() as! [Any?])
default:
return super.readValue(ofType: type)
}
}
}
private class WearEngineApiPigeonCodecWriter: FlutterStandardWriter {
override func writeValue(_ value: Any) {
if let value = value as? WearDeviceInfo {
super.writeByte(129)
super.writeValue(value.toList())
} else {
super.writeValue(value)
}
}
}
private class WearEngineApiPigeonCodecReaderWriter: FlutterStandardReaderWriter {
override func reader(with data: Data) -> FlutterStandardReader {
return WearEngineApiPigeonCodecReader(data: data)
}
override func writer(with data: NSMutableData) -> FlutterStandardWriter {
return WearEngineApiPigeonCodecWriter(data: data)
}
}
class WearEngineApiPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable {
static let shared = WearEngineApiPigeonCodec(readerWriter: WearEngineApiPigeonCodecReaderWriter())
}
/// Generated protocol from Pigeon that represents a handler of messages from Flutter.
protocol WearEngineHostApi {
func hasAvailableDevices() throws -> Bool
func checkConnectedDevice() throws -> WearDeviceInfo?
func registerMessageReceiver() throws -> Bool
func sendTextMessage(message: String) throws -> Bool
func sendWatchSyncPayload(jsonPayload: String) throws -> Bool
}
/// Generated setup class from Pigeon to handle messages through the `binaryMessenger`.
class WearEngineHostApiSetup {
static var codec: FlutterStandardMessageCodec { WearEngineApiPigeonCodec.shared }
/// Sets up an instance of `WearEngineHostApi` to handle messages through the `binaryMessenger`.
static func setUp(binaryMessenger: FlutterBinaryMessenger, api: WearEngineHostApi?, messageChannelSuffix: String = "") {
let channelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : ""
let hasAvailableDevicesChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.doublefeel_flutter.WearEngineHostApi.hasAvailableDevices\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
if let api = api {
hasAvailableDevicesChannel.setMessageHandler { _, reply in
do {
let result = try api.hasAvailableDevices()
reply(wrapResult(result))
} catch {
reply(wrapError(error))
}
}
} else {
hasAvailableDevicesChannel.setMessageHandler(nil)
}
let checkConnectedDeviceChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.doublefeel_flutter.WearEngineHostApi.checkConnectedDevice\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
if let api = api {
checkConnectedDeviceChannel.setMessageHandler { _, reply in
do {
let result = try api.checkConnectedDevice()
reply(wrapResult(result))
} catch {
reply(wrapError(error))
}
}
} else {
checkConnectedDeviceChannel.setMessageHandler(nil)
}
let registerMessageReceiverChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.doublefeel_flutter.WearEngineHostApi.registerMessageReceiver\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
if let api = api {
registerMessageReceiverChannel.setMessageHandler { _, reply in
do {
let result = try api.registerMessageReceiver()
reply(wrapResult(result))
} catch {
reply(wrapError(error))
}
}
} else {
registerMessageReceiverChannel.setMessageHandler(nil)
}
let sendTextMessageChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.doublefeel_flutter.WearEngineHostApi.sendTextMessage\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
if let api = api {
sendTextMessageChannel.setMessageHandler { message, reply in
let args = message as! [Any?]
let messageArg = args[0] as! String
do {
let result = try api.sendTextMessage(message: messageArg)
reply(wrapResult(result))
} catch {
reply(wrapError(error))
}
}
} else {
sendTextMessageChannel.setMessageHandler(nil)
}
let sendWatchSyncPayloadChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.doublefeel_flutter.WearEngineHostApi.sendWatchSyncPayload\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
if let api = api {
sendWatchSyncPayloadChannel.setMessageHandler { message, reply in
let args = message as! [Any?]
let jsonPayloadArg = args[0] as! String
do {
let result = try api.sendWatchSyncPayload(jsonPayload: jsonPayloadArg)
reply(wrapResult(result))
} catch {
reply(wrapError(error))
}
}
} else {
sendWatchSyncPayloadChannel.setMessageHandler(nil)
}
}
}
... ...
#import "GeneratedPluginRegistrant.h"
... ...
import Flutter
import UIKit
import XCTest
class RunnerTests: XCTestCase {
func testExample() {
// If you add code to the Runner application, consider adding tests here.
// See https://developer.apple.com/documentation/xctest for more information about using XCTest.
}
}
... ...
arb-dir: lib/l10n
template-arb-file: app_zh.arb
output-class: AppLocalizations
output-dir: lib/l10n/gen
output-localization-file: app_localizations.dart
source-language: zh
synthetic-package: false
\ No newline at end of file
... ...
import 'package:get/get.dart';
import '../../core/config/app_environment_config.dart';
import '../../core/error/app_error_handler.dart';
import '../../core/network/api/config_api.dart';
import '../../core/network/api/health_api.dart';
import '../../core/network/api/interaction_api.dart';
import '../../core/network/api/obs_api.dart';
import '../../core/network/api/pay_api.dart';
import '../../core/network/api/user_api.dart';
import '../../core/network/api/vip_api.dart';
import '../../core/network/dio_client.dart';
import '../../core/services/health_kit_upload_service.dart';
import '../../core/services/im_service.dart';
import '../../core/services/obs_upload_service.dart';
import '../../core/services/push_service.dart';
import '../../core/services/thinking_data_service.dart';
import '../../core/services/user_state_service.dart';
import '../../core/services/wear_engine_service.dart';
import '../../data/local/user_preferences_storage.dart';
/// App-wide infrastructure (error handling, config, network client).
void registerCoreDeps({
required AppEnvironmentConfig environmentConfig,
required UserPreferencesStorage userPreferencesStorage,
}) {
Get.put(AppErrorHandler(), permanent: true);
Get.put(environmentConfig, permanent: true);
Get.put(userPreferencesStorage, permanent: true);
Get.put(
DioClient(
Get.find<AppEnvironmentConfig>(),
Get.find<UserPreferencesStorage>(),
),
permanent: true,
);
}
/// User session, auth APIs, and login-side SDK wiring.
void registerUserSessionDeps() {
final dioClient = Get.find<DioClient>();
final userPrefs = Get.find<UserPreferencesStorage>();
Get.put(UserApi(dioClient), permanent: true);
Get.put(VipApi(dioClient), permanent: true);
Get.put<ImService>(ImServiceStub(), permanent: true);
Get.put(
ThinkingDataService(Get.find<AppEnvironmentConfig>()),
permanent: true,
);
Get.put(PushService(Get.find<UserApi>()), permanent: true);
Get.put(
UserStateService(
userPrefs,
Get.find<UserApi>(),
Get.find<ImService>(),
Get.find<PushService>(),
Get.find<ThinkingDataService>(),
),
permanent: true,
);
}
/// Health data API and upload pipeline (lazy, recreated after dispose).
void registerHealthDeps(DioClient dioClient) {
Get.lazyPut(() => HealthApi(dioClient), fenix: true);
Get.lazyPut(
() => HealthKitUploadService(Get.find<HealthApi>()),
fenix: true,
);
}
/// Payment API.
void registerPayDeps(DioClient dioClient) {
Get.lazyPut(() => PayApi(dioClient), fenix: true);
}
/// Remote config API.
void registerConfigDeps(DioClient dioClient) {
Get.lazyPut(() => ConfigApi(dioClient), fenix: true);
}
/// Partner interaction API and wear engine.
void registerInteractionDeps(
DioClient dioClient,
UserPreferencesStorage userPrefs,
) {
Get.lazyPut(() => InteractionApi(dioClient), fenix: true);
Get.lazyPut(
() => WearEngineService(
userPrefs,
Get.find<HealthApi>(),
Get.find<InteractionApi>(),
),
fenix: true,
);
}
/// Object storage upload API and service.
void registerObsDeps(DioClient dioClient) {
Get.lazyPut(() => ObsApi(dioClient), fenix: true);
Get.lazyPut(() => ObsUploadService(Get.find<ObsApi>()), fenix: true);
}
... ...
import 'package:get/get.dart';
import '../../core/config/app_environment_config.dart';
import '../../core/network/dio_client.dart';
import '../../data/local/user_preferences_storage.dart';
import 'dependency_registrars.dart';
/// Core dependencies required at cold start (splash + session).
class InitialBinding extends Bindings {
InitialBinding({
required this.environmentConfig,
required this.userPreferencesStorage,
});
final AppEnvironmentConfig environmentConfig;
final UserPreferencesStorage userPreferencesStorage;
@override
void dependencies() {
registerCoreDeps(
environmentConfig: environmentConfig,
userPreferencesStorage: userPreferencesStorage,
);
registerUserSessionDeps();
final dioClient = Get.find<DioClient>();
final userPrefs = Get.find<UserPreferencesStorage>();
registerHealthDeps(dioClient);
registerPayDeps(dioClient);
registerConfigDeps(dioClient);
registerInteractionDeps(dioClient, userPrefs);
registerObsDeps(dioClient);
}
}
... ...
import 'package:flutter/widgets.dart';
import 'package:get/get.dart';
import '../../core/config/app_environment_config.dart';
import '../../core/logging/app_logger.dart';
import '../../core/services/user_state_service.dart';
import '../../data/local/local_storage.dart';
import '../../data/local/user_preferences_storage.dart';
import '../bindings/initial_binding.dart';
/// Application startup before [runApp].
abstract final class AppBootstrap {
static Future<void> init() async {
WidgetsFlutterBinding.ensureInitialized();
AppLogger.init();
final local = await LocalStorage.open();
final environmentConfig = AppEnvironmentConfig(local);
await environmentConfig.init();
final userPreferencesStorage =
UserPreferencesStorage(local.sharedPreferences);
await userPreferencesStorage.init();
InitialBinding(
environmentConfig: environmentConfig,
userPreferencesStorage: userPreferencesStorage,
).dependencies();
if (local.termsAgreed) {
await Get.find<UserStateService>().initializeSdks();
}
}
}
... ...
import 'package:doublefeel_flutter/l10n/l10n_extensions.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'routes/app_pages.dart';
class DoubleFeelApp extends StatelessWidget {
const DoubleFeelApp({super.key});
@override
Widget build(BuildContext context) {
return GetMaterialApp(
title: context.l10n.appName,
initialRoute: AppPages.initialRoute,
getPages: AppPages.routes,
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
localeResolutionCallback: (deviceLocale, supportedLocales) {
if (deviceLocale == null) return const Locale('zh');
for (final locale in supportedLocales) {
if (locale.languageCode == deviceLocale.languageCode) {
return locale;
}
}
return const Locale('zh');
},
);
}
}
... ...
import 'package:get/get.dart';
import '../controllers/bind_partner_controller.dart';
class BindPartnerBinding extends Bindings {
@override
void dependencies() {
Get.put(BindPartnerController());
}
}
... ...
import 'package:doublefeel_flutter/app/routes/app_pages.dart';
import 'package:doublefeel_flutter/core/services/user_state_service.dart';
import 'package:doublefeel_flutter/data/local/user_preferences_storage.dart';
import 'package:flutter/widgets.dart';
import 'package:get/get.dart';
class BindPartnerController extends GetxController {
final TextEditingController partnerIdController = TextEditingController();
final RxString partnerIdInput = ''.obs;
final RxBool isSubmitting = false.obs;
final RxString myInviteCode = 'AC1192'.obs;
@override
void onInit() {
super.onInit();
partnerIdController.addListener(() {
partnerIdInput.value = partnerIdController.text.trim();
});
}
@override
void onClose() {
partnerIdController.dispose();
super.onClose();
}
bool get canSubmit => partnerIdInput.value.isNotEmpty;
void onShareMyCode() {}
Future<void> onSubmitPartnerId() async {
if (!canSubmit || isSubmitting.value) return;
isSubmitting.value = true;
try {
final userStateService = Get.find<UserStateService>();
final partnerId = partnerIdInput.value;
if (!userStateService.isVip) {
Get.offAllNamed(AppRoutes.userOnboarding, arguments: {
'type': "MembershipOfferPage",
'needBindSuccessGuide': true
});
} else {
Get.offAllNamed(AppRoutes.home);
}
} catch (e) {
} finally {
isSubmitting.value = false;
}
}
void onSkip() {
final userStateService = Get.find<UserStateService>();
if (!userStateService.isVip) {
Get.offAllNamed(AppRoutes.userOnboarding, arguments: {
'type': "MembershipOfferPage",
'needBindSuccessGuide': false
});
} else {
Get.offAllNamed(AppRoutes.home);
}
}
}
... ...
import 'package:doublefeel_flutter/app/widget/dash_divider.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import '../../../../l10n/l10n_extensions.dart';
import '../controllers/bind_partner_controller.dart';
class BindPartnerView extends GetView<BindPartnerController> {
const BindPartnerView({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
resizeToAvoidBottomInset: true,
body: PopScope(
canPop: false,
child: Stack(
children: [
_buildGradientBackground(),
Container(
padding:
EdgeInsets.only(top: MediaQuery.paddingOf(context).top + 4),
child: ListView(
physics: const ClampingScrollPhysics(),
children: [
_buildTitle(context),
SizedBox(height: 28),
_buildCardArea(context),
SizedBox(height: 58),
_buildSkipButton(context),
],
),
),
Positioned(
top: MediaQuery.paddingOf(context).top + 92,
left: 0,
child: Opacity(
opacity: 0.40,
child: Container(
width: 133,
height: 124,
decoration: BoxDecoration(color: const Color(0xFFFF0000)),
),
),
),
Positioned(
top: MediaQuery.paddingOf(context).top + 532,
right: 0,
child: Opacity(
opacity: 0.40,
child: Container(
width: 133,
height: 124,
decoration: BoxDecoration(color: const Color(0xFFFF0000)),
),
),
),
],
),
),
);
}
/// 渐变背景
Widget _buildGradientBackground() {
return Positioned.fill(
child: Container(
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
stops: [0.0, 0.25, 0.75, 1.0],
colors: [
Color(0xFFE6DBFF),
Color(0xFFEDE4FF),
Color(0xFFEEE6FF),
Color(0xFFF9F6FF),
],
),
),
),
);
}
/// 标题文字
Widget _buildTitle(BuildContext context) {
return Padding(
padding: EdgeInsets.symmetric(horizontal: 37),
child: Text(
context.l10n.bindPartnerTitle,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w600,
color: const Color(0xFF0F0F11),
height: 1.4,
),
),
);
}
Widget _buildCardArea(BuildContext context) {
return Container(
margin: EdgeInsets.symmetric(horizontal: 24),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(20),
boxShadow: [
BoxShadow(
color: const Color(0xFF845EEE).withValues(alpha: 0.08),
blurRadius: 24,
offset: const Offset(0, 8),
),
],
),
child: Column(
children: [
SizedBox(height: 28),
_buildMyInfoSection(context),
SizedBox(height: 40),
_buildOrDivider(context),
SizedBox(height: 28),
_buildInputSection(context),
SizedBox(height: 16),
// 继续按钮
Container(
padding: EdgeInsets.symmetric(horizontal: 32),
child: Obx(() {
return _buildPrimaryButton(
label: context.l10n.continueButton,
onTap: controller.onSubmitPartnerId,
enabled: controller.canSubmit && !controller.isSubmitting.value,
isLoading: controller.isSubmitting.value,
primaryColor: const Color(0xFFFF9A6E),
);
}),
),
SizedBox(height: 40),
],
),
);
}
Widget _buildMyInfoSection(BuildContext context) {
return Padding(
padding: EdgeInsets.symmetric(horizontal: 32),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
// 标签
Text(
context.l10n.bindPartnerMyId,
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w400,
color: const Color(0xFF0F0F11),
),
),
SizedBox(height: 13),
Obx(() {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
controller.myInviteCode.value,
style: TextStyle(
fontSize: 32,
fontWeight: FontWeight.w600,
color: const Color(0xFF845EEE),
height: 1.4,
),
),
SizedBox(width: 8),
// 复制图标按钮
GestureDetector(
onTap: () {
Clipboard.setData(
ClipboardData(text: controller.myInviteCode.value),
);
},
child: Container(
width: 20,
height: 20,
decoration: BoxDecoration(
color: const Color(0xFFF0F0F6),
borderRadius: BorderRadius.circular(6),
),
child: Icon(
Icons.copy_rounded,
size: 12,
color: const Color(0xFF845EEE),
),
),
),
],
);
}),
SizedBox(height: 26),
// 分享按钮
_buildPrimaryButton(
label: context.l10n.bindPartnerShareMyCode,
onTap: controller.onShareMyCode,
enabled: true,
),
],
),
);
}
Widget _buildOrDivider(BuildContext context) {
return Row(
children: [
Expanded(
child: Padding(
padding: const EdgeInsets.only(left: 27),
child: DashedDivider(),
),
),
Container(
width: 36,
height: 36,
decoration: const BoxDecoration(
color: Color(0xFFEDE5FF),
shape: BoxShape.circle,
),
alignment: Alignment.center,
child: Text(
context.l10n.bindPartnerOr,
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w400,
color: const Color(0xFF845EEE),
),
),
),
Expanded(
child: Padding(
padding: const EdgeInsets.only(right: 27),
child: DashedDivider(),
),
),
],
);
}
/// 输入伙伴 ID 区域
Widget _buildInputSection(BuildContext context) {
return Padding(
padding: EdgeInsets.symmetric(horizontal: 32),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
// 标签
Text(
context.l10n.bindPartnerContactId,
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w400,
color: const Color(0xFF0F0F11),
),
),
SizedBox(height: 16),
// 输入框
Container(
height: 52,
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(color: const Color(0xFFF0F0F6), width: 1),
borderRadius: BorderRadius.circular(27),
),
child: TextField(
controller: controller.partnerIdController,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 32,
fontWeight: FontWeight.w400,
color: const Color(0xFF0F0F11),
),
decoration: InputDecoration(
hintText: context.l10n.bindPartnerInputHint,
hintStyle: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w400,
color: const Color(0xFFD0D0D2),
),
border: InputBorder.none,
contentPadding: EdgeInsets.symmetric(horizontal: 20),
),
),
),
],
),
);
}
/// 通用主按钮
Widget _buildPrimaryButton({
required String label,
required VoidCallback onTap,
bool enabled = true,
bool isLoading = false,
Color primaryColor = const Color(0xFF845EEE),
}) {
return GestureDetector(
onTap: enabled ? onTap : null,
child: Container(
width: double.infinity,
height: 40,
decoration: BoxDecoration(
color: enabled ? primaryColor : primaryColor.withValues(alpha: 0.3),
borderRadius: BorderRadius.circular(100),
),
alignment: Alignment.center,
child: isLoading
? SizedBox(
width: 18,
height: 18,
child: const CircularProgressIndicator(
strokeWidth: 2,
valueColor: AlwaysStoppedAnimation<Color>(Colors.white),
),
)
: Text(
label,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
color: Colors.white,
),
),
),
);
}
/// 底部"下次再说"按钮
Widget _buildSkipButton(BuildContext context) {
return GestureDetector(
onTap: controller.onSkip,
behavior: HitTestBehavior.opaque,
child: Container(
width: 280,
height: 48,
alignment: Alignment.center,
child: Text(
context.l10n.bindPartnerSkip,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
color: const Color(0xFFA1A0A5),
),
),
),
);
}
}
... ...
import 'package:get/get.dart';
import '../controllers/home_controller.dart';
import '../controllers/today_controller.dart';
class HomeBinding extends Bindings {
@override
void dependencies() {
Get.lazyPut<HomeController>(() => HomeController(), fenix: true);
Get.lazyPut<TodayController>(() => TodayController(), fenix: true);
// 其他 tab 的 controller 后续在此添加
// Get.lazyPut<TrendController>(() => TrendController(), fenix: true);
// Get.lazyPut<FriendsController>(() => FriendsController(), fenix: true);
// Get.lazyPut<MyController>(() => MyController(), fenix: true);
}
}
... ...
import 'package:doublefeel_flutter/core/services/user_state_service.dart';
import 'package:get/get.dart';
class HomeController extends GetxController {
final UserStateService userStateService = Get.find<UserStateService>();
/// 当前选中的底部 tab 索引
final selectedIndex = 0.obs;
/// 当前选中的日期(Today tab 使用)
final selectedDate = DateTime.now().obs;
void changeTab(int index) {
selectedIndex.value = index;
}
void changeDate(DateTime date) {
selectedDate.value = date;
}
}
... ...
import 'package:doublefeel_flutter/core/services/user_state_service.dart';
import 'package:get/get.dart';
/// 每日行动 item 数据模型
class DailyActionItem {
final String label;
final String value;
final String unit;
final String? subValue;
final String? subUnit;
const DailyActionItem({
required this.label,
required this.value,
required this.unit,
this.subValue,
this.subUnit,
});
}
/// HRV 趋势数据点
class HrvDataPoint {
final double hour; // 0.0 ~ 24.0
final double hrv;
const HrvDataPoint({required this.hour, required this.hrv});
}
/// HRV tooltip 标注点
class HrvAnnotation {
final double hour;
final double hrv;
final String stateLabel; // e.g. "状态优秀"
final String detail; // e.g. "HRV 23ms · 11:28"
const HrvAnnotation({
required this.hour,
required this.hrv,
required this.stateLabel,
required this.detail,
});
}
class TodayController extends GetxController {
final UserStateService userStateService = Get.find<UserStateService>();
// ── 压力状态 ─────────────────────────────
final stressLabel = '状态正常'.obs;
// ── HRV 表盘引导 Banner ───────────────────
final showHrvAdBanner = true.obs;
void dismissHrvAdBanner() => showHrvAdBanner.value = false;
// ── HRV 数字 + 心率 ───────────────────────
final avgHrv = 46.obs;
final restingHeartRate = 63.obs;
// ── HRV 趋势图 ────────────────────────────
final List<HrvDataPoint> hrvChartData = const [
HrvDataPoint(hour: 0, hrv: 30),
HrvDataPoint(hour: 1, hrv: 45),
HrvDataPoint(hour: 2, hrv: 40),
HrvDataPoint(hour: 3, hrv: 55),
HrvDataPoint(hour: 4, hrv: 50),
HrvDataPoint(hour: 5, hrv: 60),
HrvDataPoint(hour: 6, hrv: 65),
HrvDataPoint(hour: 7, hrv: 70),
HrvDataPoint(hour: 8, hrv: 62),
HrvDataPoint(hour: 9, hrv: 58),
HrvDataPoint(hour: 10, hrv: 75),
HrvDataPoint(hour: 11, hrv: 80),
HrvDataPoint(hour: 12, hrv: 72),
HrvDataPoint(hour: 13, hrv: 68),
HrvDataPoint(hour: 14, hrv: 55),
HrvDataPoint(hour: 15, hrv: 50),
HrvDataPoint(hour: 16, hrv: 45),
HrvDataPoint(hour: 17, hrv: 42),
HrvDataPoint(hour: 18, hrv: 38),
];
final List<HrvAnnotation> hrvAnnotations = const [
HrvAnnotation(
hour: 11,
hrv: 80,
stateLabel: '状态优秀',
detail: 'HRV 23ms · 11:28',
),
];
// ── 每日行动 ──────────────────────────────
final List<DailyActionItem> dailyActions = const [
DailyActionItem(
label: '睡眠',
value: '7',
unit: 'h',
subValue: '32',
subUnit: 'min',
),
DailyActionItem(
label: '健身',
value: '45',
unit: 'min',
),
DailyActionItem(
label: '步数',
value: '8,234',
unit: '步',
),
];
}
... ...
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../controllers/home_controller.dart';
import '../widgets/df_tab_bar.dart';
import 'tabs/today_tab.dart';
import 'tabs/trend_tab.dart';
import 'tabs/friends_tab.dart';
import 'tabs/my_tab.dart';
class HomePage extends GetView<HomeController> {
const HomePage({super.key});
static const _tabs = [
TodayTab(),
TrendTab(),
FriendsTab(),
MyTab(),
];
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color(0xFFF5F2FF),
// 不使用系统 AppBar,Today 页自带状态栏适配
extendBody: true, // 让内容延伸到 bottomNavigationBar 下方
extendBodyBehindAppBar: true,
body: Obx(
() => IndexedStack(
index: controller.selectedIndex.value,
children: _tabs,
),
),
bottomNavigationBar: Obx(
() => DfTabBar(
selectedIndex: controller.selectedIndex.value,
onTap: controller.changeTab,
),
),
);
}
}
... ...
import 'package:flutter/material.dart';
class FriendsTab extends StatelessWidget {
const FriendsTab({super.key});
@override
Widget build(BuildContext context) {
return const Center(
child: Text('好友', style: TextStyle(fontSize: 20, color: Color(0xFF0F0F11))),
);
}
}
... ...