Commit bcaf2779df42c6710e796eeaa740d0f75bbe5bbe

Authored by 权海
1 parent bdad0c11

feat(ui):添加watch静态UI

xxx

feat(ui):完成watch UI
Showing 70 changed files with 3073 additions and 579 deletions

Too many changes to show.

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

@@ -48,6 +48,16 @@ end @@ -48,6 +48,16 @@ end
48 48
49 post_install do |installer| 49 post_install do |installer|
50 installer.pods_project.targets.each do |target| 50 installer.pods_project.targets.each do |target|
  51 + is_watchos_target = target.build_configurations.any? do |config|
  52 + config.build_settings['WATCHOS_DEPLOYMENT_TARGET']
  53 + end
  54 +
  55 + next if is_watchos_target
  56 +
51 flutter_additional_ios_build_settings(target) 57 flutter_additional_ios_build_settings(target)
  58 +
  59 + target.build_configurations.each do |config|
  60 + config.build_settings['ENABLE_USER_SCRIPT_SANDBOXING'] = 'NO'
  61 + end
52 end 62 end
53 end 63 end
@@ -92,7 +92,7 @@ EXTERNAL SOURCES: @@ -92,7 +92,7 @@ EXTERNAL SOURCES:
92 :path: ".symlinks/plugins/webview_flutter_wkwebview/darwin" 92 :path: ".symlinks/plugins/webview_flutter_wkwebview/darwin"
93 93
94 SPEC CHECKSUMS: 94 SPEC CHECKSUMS:
95 - Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467 95 + Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
96 fluttertoast: 2c67e14dce98bbdb200df9e1acf610d7a6264ea1 96 fluttertoast: 2c67e14dce98bbdb200df9e1acf610d7a6264ea1
97 image_cropper: c4326ea50132b1e1564499e5d32a84f01fb03537 97 image_cropper: c4326ea50132b1e1564499e5d32a84f01fb03537
98 image_picker_ios: 7fe1ff8e34c1790d6fff70a32484959f563a928a 98 image_picker_ios: 7fe1ff8e34c1790d6fff70a32484959f563a928a
@@ -108,6 +108,6 @@ SPEC CHECKSUMS: @@ -108,6 +108,6 @@ SPEC CHECKSUMS:
108 TOCropViewController: 80b8985ad794298fb69d3341de183f33d1853654 108 TOCropViewController: 80b8985ad794298fb69d3341de183f33d1853654
109 webview_flutter_wkwebview: 1821ceac936eba6f7984d89a9f3bcb4dea99ebb2 109 webview_flutter_wkwebview: 1821ceac936eba6f7984d89a9f3bcb4dea99ebb2
110 110
111 -PODFILE CHECKSUM: 11b37be67b2ce5b4cca7654ac969f9b9789ac4bf 111 +PODFILE CHECKSUM: c331311b0ccb42e8d5cf37701560080ce4a73ef8
112 112
113 COCOAPODS: 1.16.2 113 COCOAPODS: 1.16.2
  1 +//
  2 +// DFCoupleStressHomeView.swift
  3 +// iwatch
  4 +//
  5 +// Created by 权海 on 2026/6/15.
  6 +//
  7 +
  8 +import SwiftUI
  9 +
  10 +struct DFCoupleStressHomeView: View {
  11 + var hasData: Bool = true
  12 +
  13 + var body: some View {
  14 + VStack {
  15 + DFWatchFigmaHeader(subtitle: hasData ? "我们的状态·HRV" : "我们的状态·实时")
  16 + Spacer().frame(height: 9)
  17 + HStack(spacing: 4){
  18 + DFCouplePersonCard(
  19 + kind:.overloaded,
  20 + name: "男朋友",
  21 + value: hasData ? "30ms" : "-%",
  22 + ).frame(maxWidth: .infinity)
  23 + DFCouplePersonCard(
  24 + kind: .excellent,
  25 + name: "我",
  26 + value: hasData ? "80ms" : "-%",
  27 + ).frame(maxWidth: .infinity)
  28 + }
  29 + Spacer().frame(height: 5)
  30 + HStack{
  31 + DFWatchHeartBeatCircle(progress: 0, value: nil)
  32 + .frame(width: 45, height: 44)
  33 + Spacer()
  34 + DFWatchCloseCircle(outerProgress: 0, middleProgress: 0, innerProgress: 0)
  35 + .frame(width: 44, height: 44)
  36 + Spacer()
  37 + DFWatchStepCountCircle(progress: 0, value: 0)
  38 + .frame(width: 44, height: 44)
  39 + }
  40 + }.padding(.all, 16)
  41 + }
  42 +}
  43 +
  44 +private struct DFCouplePersonCard: View {
  45 + let kind: DFWatchStressKind?
  46 + let name: String
  47 + let value: String?
  48 +
  49 + var body: some View {
  50 + VStack(spacing: 4) {
  51 + HStack{}
  52 + .frame(width: 55, height: 55)
  53 + .background(Color(hex: "#FF0000"))
  54 + Text(kind?.title ?? "等待数据")
  55 + .font(.system(size: 12, weight: .semibold))
  56 + .foregroundColor(kind?.color ?? Color(hex: "#B0B0B6"))
  57 + Text(name)
  58 + .font(.system(size: 10, weight: .medium))
  59 + .foregroundColor(.white)
  60 + Text(value ?? "--ms")
  61 + .font(.system(size: 8, weight: .light))
  62 + .foregroundColor(.white)
  63 + }
  64 + }
  65 +}
  1 +//
  2 +// File.swift
  3 +// iwatch
  4 +//
  5 +// Created by 权海 on 2026/6/15.
  6 +//
  7 +
  8 +import SwiftUI
  9 +
  10 +struct DFSingleStressHomeView: View {
  11 + var kind: DFWatchStressKind = .overloaded
  12 + var value: String? = "38ms"
  13 + var sampleTime: String = "16:06"
  14 +
  15 + private var valueDesc: String{
  16 + if let value{
  17 + return kind.title + "·" + value
  18 + }
  19 + return "等待数据"
  20 + }
  21 +
  22 + var body: some View {
  23 + ZStack(alignment: .top) {
  24 + LinearGradient(
  25 + colors: [kind.color.opacity(0.3), kind.color.opacity(0)],
  26 + startPoint: .top,
  27 + endPoint: .bottom
  28 + )
  29 + .frame(width: .infinity, height: .infinity)
  30 + VStack(spacing: 8){
  31 + DFWatchFigmaHeader(subtitle: "HRV")
  32 + .padding(.top, 16)
  33 + HStack{}
  34 + .frame(width: 78, height: 78)
  35 + .background(Color(hex: "#FF0000"))
  36 + Text(valueDesc)
  37 + .font(.system(size: 16, weight: .semibold))
  38 + .foregroundStyle(value == nil ? Color(hex: "#B0B0B6") : kind.color)
  39 + DFWatchFigmaSegmentBar(selected: kind)
  40 + .frame(height: 14)
  41 + Text(sampleTime)
  42 + .font(.system(size: 12))
  43 + .foregroundStyle(.white)
  44 + }.padding(.horizontal, value == nil ? 30 : 22)
  45 + }
  46 + }
  47 +}
  1 +//
  2 +// DFWatchCloseCircle.swift
  3 +// iwatch
  4 +//
  5 +// Created by 权海 on 2026/6/12.
  6 +//
  7 +
  8 +import SwiftUI
  9 +
  10 +struct DFWatchCloseCircle: View {
  11 + var outerProgress: CGFloat
  12 + var middleProgress: CGFloat
  13 + var innerProgress: CGFloat
  14 +
  15 + var outerColor: Color = Color(hex: "#FF5279")
  16 + var middleColor: Color = Color(hex: "#3BD49D")
  17 + var innerColor: Color = Color(hex: "#7B9BFB")
  18 +
  19 + var backgroundColor: Color = .black
  20 +
  21 + var body: some View {
  22 + GeometryReader { geometry in
  23 + let size = min(geometry.size.width, geometry.size.height)
  24 + let lineWidth: CGFloat = size * 0.13
  25 +
  26 + ZStack {
  27 + backgroundColor
  28 +
  29 + RingView(
  30 + progress: outerProgress,
  31 + color: outerColor,
  32 + lineWidth: lineWidth
  33 + )
  34 + .frame(
  35 + width: size * 0.87,
  36 + height: size * 0.87
  37 + )
  38 +
  39 + RingView(
  40 + progress: middleProgress,
  41 + color: middleColor,
  42 + lineWidth: lineWidth
  43 + )
  44 + .frame(
  45 + width: size * 0.55,
  46 + height: size * 0.55
  47 + )
  48 +
  49 + RingView(
  50 + progress: innerProgress,
  51 + color: innerColor,
  52 + lineWidth: lineWidth
  53 + )
  54 + .frame(
  55 + width: size * 0.24,
  56 + height: size * 0.24
  57 + )
  58 +
  59 + Circle()
  60 + .fill(backgroundColor)
  61 + .frame(
  62 + width: size * 0.15,
  63 + height: size * 0.15
  64 + )
  65 + }
  66 + .frame(width: size, height: size)
  67 + .clipShape(Circle())
  68 + }
  69 + .aspectRatio(1, contentMode: .fit)
  70 + }
  71 +}
  72 +struct RingView: View {
  73 + var progress: CGFloat
  74 + var color: Color
  75 + var lineWidth: CGFloat
  76 +
  77 + var body: some View {
  78 + ZStack{
  79 + Circle()
  80 + .stroke(
  81 + color,
  82 + style: StrokeStyle(
  83 + lineWidth: lineWidth,
  84 + lineCap: .round,
  85 + lineJoin: .round
  86 + )
  87 + )
  88 + .opacity(0.3)
  89 + Circle()
  90 + .trim(from: 0, to: max(0, min(progress, 1)))
  91 + .stroke(
  92 + color,
  93 + style: StrokeStyle(
  94 + lineWidth: lineWidth,
  95 + lineCap: .round,
  96 + lineJoin: .round
  97 + )
  98 + )
  99 + .rotationEffect(.degrees(-90))
  100 + }
  101 + }
  102 +}
  1 +//
  2 +// DFWatchCloseView.swift
  3 +// iwatch
  4 +//
  5 +// Created by 权海 on 2026/6/12.
  6 +//
  7 +
  8 +import SwiftUI
  9 +
  10 +
  11 +struct DFWatchCloseView: View {
  12 + let closeOnClick: (() -> Void)?
  13 + var body: some View {
  14 + Button {
  15 + closeOnClick?()
  16 + } label: {
  17 + Image(systemName: "xmark")
  18 + .fontWeight(.bold)
  19 + .tint(.white)
  20 +
  21 + }
  22 + .frame(width: 32, height: 32)
  23 + .background(.white.opacity(0.1))
  24 + .clipShape(
  25 + RoundedRectangle(cornerRadius: 16)
  26 + ).padding(.leading, 14)
  27 + }
  28 +}
  29 +
  1 +import SwiftUI
  2 +
  3 +struct DFTodayStatusOverviewFigmaView: View {
  4 + var hasData: Bool = true
  5 +
  6 + private var rows: [DFStatusOverviewRow] {
  7 + [
  8 + .init(title: "平均HRV", value: hasData ? "29" : "-", unit: "ms", icon: "waveform.path.ecg", tint: DFWatchFigmaColor.blue),
  9 + .init(title: "最新心率", value: hasData ? "79" : "-", unit: "次/分", icon: "heart.fill", tint: DFWatchFigmaColor.red),
  10 + .init(title: "步数", value: hasData ? "11198" : "-", unit: "步", icon: "figure.walk", tint: DFWatchFigmaColor.green),
  11 + .init(title: "活动记录", value: hasData ? "400" : "-", unit: "大卡", icon: "flame.fill", tint: DFWatchFigmaColor.orange)
  12 + ]
  13 + }
  14 +
  15 + var body: some View {
  16 + ZStack{
  17 + HStack{
  18 + Spacer()
  19 + }
  20 + VStack(alignment: .trailing){
  21 + Text(.now, style: .time)
  22 + .font(.system(size: 14, weight: .medium))
  23 + .foregroundColor(.white)
  24 + Text("我的今日状态")
  25 + .lineLimit(1)
  26 + .font(.system(size: 16, weight: .medium))
  27 + .minimumScaleFactor(0.7)
  28 + .foregroundColor(.white)
  29 + ScrollView {
  30 + ForEach(rows) { row in
  31 + DFStatusOverviewCard(row: row)
  32 + .padding(.bottom, 4)
  33 + }
  34 + Spacer()
  35 + .frame(height: 24)
  36 + }
  37 + }.padding(EdgeInsets(top: 10, leading: 10, bottom: 0, trailing: 10))
  38 + }
  39 + }
  40 +}
  41 +
  42 +private struct DFStatusOverviewRow: Identifiable {
  43 + let id = UUID()
  44 + let title: String
  45 + let value: String
  46 + let unit: String
  47 + let icon: String
  48 + let tint: Color
  49 +}
  50 +
  51 +private struct DFStatusOverviewCard: View {
  52 + let row: DFStatusOverviewRow
  53 +
  54 + var body: some View {
  55 + HStack(spacing: 0) {
  56 + Image(systemName: row.icon)
  57 + .frame(width: 18, height: 18)
  58 + .foregroundColor(row.tint)
  59 + Spacer()
  60 + .frame(width: 6)
  61 + Text(row.title)
  62 + .font(.system(size: 12, weight: .medium))
  63 + .lineLimit(1)
  64 + .minimumScaleFactor(0.7)
  65 + .foregroundColor(.white)
  66 + Spacer(minLength: 0)
  67 + Text(row.value)
  68 + .font(.system(size: 12, weight: .medium))
  69 + .lineLimit(1)
  70 + .minimumScaleFactor(0.7)
  71 + .foregroundColor(.white)
  72 + Spacer()
  73 + .frame(width: 2)
  74 + Text(row.unit)
  75 + .font(.system(size: 12, weight: .regular))
  76 + .lineLimit(1)
  77 + .minimumScaleFactor(0.7)
  78 + .foregroundColor(.white.opacity(0.5))
  79 + }
  80 + .padding(.horizontal, 8)
  81 + .padding(.vertical, 10)
  82 + .background(Color.white.opacity(0.10))
  83 + .clipShape(RoundedRectangle(cornerRadius: 10))
  84 + }
  85 +}
  86 +
  87 +struct DFWatchSettingsFigmaView: View {
  88 +
  89 + var body: some View {
  90 + ZStack(alignment: .topTrailing){
  91 + HStack{
  92 + Spacer()
  93 + }
  94 + VStack(alignment: .leading){
  95 + Spacer()
  96 + .frame(height: 14)
  97 + DFWatchCloseView {
  98 +
  99 + }
  100 + Spacer()
  101 + .frame(height: 6)
  102 + HStack{
  103 + Text("刷新模式")
  104 + .font(.system(size: 16, weight: .medium))
  105 + .foregroundColor(.white)
  106 + DFWatchFigmaProBadge()
  107 + Spacer()
  108 + }.padding(.leading, 16)
  109 + ScrollView {
  110 + VStack(alignment: .leading, spacing: 8) {
  111 + DFSettingOption(title: "HRV", accessory: .check)
  112 + DFSettingOption(title: "实时压力", accessory: .lock)
  113 + Text("刷新模式说明")
  114 + .font(.system(size: 9, weight: .regular))
  115 + .underline()
  116 + .foregroundColor(DFWatchFigmaColor.purpleText)
  117 + .padding(.leading, 8)
  118 + }.padding(.horizontal, 10)
  119 + .padding(.bottom, 24)
  120 + }
  121 + }
  122 + Text(.now, style: .time)
  123 + .font(.system(size: 14, weight: .medium))
  124 + .foregroundColor(.white)
  125 + .padding(.trailing, 14)
  126 + .padding(.top, 10)
  127 + }
  128 + }
  129 +}
  130 +
  131 +private enum DFSettingAccessory {
  132 + case check
  133 + case lock
  134 +}
  135 +
  136 +private struct DFSettingOption: View {
  137 + let title: String
  138 + let accessory: DFSettingAccessory
  139 +
  140 + var body: some View {
  141 + HStack {
  142 + Text(title)
  143 + .font(.system(size: 12, weight: .medium))
  144 + .foregroundColor(.white)
  145 + Spacer()
  146 + switch accessory {
  147 + case .check:
  148 + Image(systemName: "checkmark")
  149 + .font(.system(size: 15, weight: .bold))
  150 + .foregroundColor(.white)
  151 + case .lock:
  152 + Image(systemName: "lock.fill")
  153 + .font(.system(size: 15, weight: .medium))
  154 + .foregroundColor(.white.opacity(0.84))
  155 + }
  156 + }
  157 + .frame(height: 38)
  158 + .padding(.horizontal, 8)
  159 + .background(Color.white.opacity(0.10))
  160 + .clipShape(RoundedRectangle(cornerRadius: 10))
  161 + }
  162 +}
  163 +
  164 +struct DFProRequiredInfoFigmaView: View {
  165 + var body: some View {
  166 + ZStack(alignment: .topTrailing){
  167 + HStack{
  168 + Spacer()
  169 + }
  170 + VStack(alignment: .center){
  171 + Spacer()
  172 + .frame(height: 14)
  173 + HStack{
  174 + DFWatchCloseView {
  175 +
  176 + }
  177 + Spacer()
  178 + }
  179 + Spacer()
  180 + .frame(height: 6)
  181 + DFWatchFigmaProBadge()
  182 + Spacer()
  183 + .frame(height: 10)
  184 + ScrollView {
  185 + VStack(alignment: .leading, spacing: 11) {
  186 + Text("该功能需要DoubleFeel Pro会员才可使用。你可以前往手机App开通会员。")
  187 + Text("如果已经开通会员,但手表端还没有显示,可以先退出当前页面,再重新进入,会员状态通常会自动更新。")
  188 + }
  189 + .font(.system(size: 11, weight: .regular))
  190 + .foregroundColor(.white)
  191 + .lineSpacing(2)
  192 + .padding(.horizontal, 12)
  193 + .padding(.bottom, 24)
  194 + }
  195 + }
  196 + Text(.now, style: .time)
  197 + .font(.system(size: 14, weight: .medium))
  198 + .foregroundColor(.white)
  199 + .padding(.trailing, 14)
  200 + .padding(.top, 10)
  201 + }
  202 + }
  203 +}
  204 +
  205 +struct DFRefreshModeInfoFigmaView: View {
  206 + var body: some View {
  207 + ZStack(alignment: .topTrailing){
  208 + HStack{
  209 + Spacer()
  210 + }
  211 + VStack(alignment: .leading){
  212 + Spacer()
  213 + .frame(height: 14)
  214 + DFWatchCloseView {
  215 +
  216 + }
  217 + Spacer()
  218 + .frame(height: 8)
  219 + ScrollView {
  220 + VStack(alignment: .leading){
  221 + Text("HRV")
  222 + .font(.system(size: 14, weight: .medium))
  223 + .foregroundColor(.white)
  224 + Spacer()
  225 + .frame(height: 4)
  226 + Text("""
  227 + 一般情况下,Apple Watch 会每隔一段时间自动采集一次 HRV 数据。
  228 + 在佩戴稳定、身体静止或放松状态下,系统更容易获取有效 HRV 数据。
  229 + 剧烈运动、频繁活动、手表佩戴不稳定或刚解锁 Apple Watch 后,数据同步可能会延迟。
  230 + Apple Watch 与 iPhone 的健康数据同步由 Apple Health 系统完成,因此并不会始终实时更新。
  231 + """)
  232 + .font(.system(size: 9, weight: .regular))
  233 + .foregroundColor(.white.opacity(0.8))
  234 + Spacer()
  235 + .frame(height: 14)
  236 + Text("实时压力")
  237 + .font(.system(size: 14, weight: .medium))
  238 + .foregroundColor(.white)
  239 + Spacer()
  240 + .frame(height: 4)
  241 + Text("""
  242 +实时压力会结合当前 HRV、心率状态与个人历史数据动态变化。
  243 +通常情况下:
  244 + · 手机 App 会自动刷新当天综合压力状态
  245 + · Apple Watch 会显示最近一次的实时压力变化
  246 +由于 Apple Health 数据同步存在延迟,实时压力可能不会立即更新。
  247 +""")
  248 + .font(.system(size: 9, weight: .regular))
  249 + .foregroundColor(.white.opacity(0.8))
  250 + Spacer()
  251 + .frame(height: 14)
  252 + Divider()
  253 + .overlay(Color.white.opacity(0.25))
  254 + Spacer()
  255 + .frame(height: 14)
  256 + Text("""
  257 +以下情况可能导致数据延迟或暂时不可用:
  258 + · Apple Watch 处于低电量模式
  259 + · Apple Health 权限未开启
  260 + · 长时间未佩戴 Apple Watch
  261 + · 正在运动或身体频繁活动
  262 + · 手表刚解锁或刚重新佩戴
  263 + · 系统尚未完成数据同步
  264 +""")
  265 + .font(.system(size: 8, weight: .regular))
  266 + .foregroundColor(.white.opacity(0.8))
  267 + }.padding(.horizontal, 10)
  268 + .padding(.bottom, 24)
  269 + }
  270 + }
  271 + VStack(alignment: .trailing){
  272 + Text(.now, style: .time)
  273 + .font(.system(size: 14, weight: .medium))
  274 + .foregroundColor(.white)
  275 + Text("HRV")
  276 + .font(.system(size: 12, weight: .medium))
  277 + .foregroundColor(.white)
  278 + .opacity(0.6)
  279 + }
  280 + .padding(.trailing, 14)
  281 + .padding(.top, 10)
  282 + }
  283 + }
  284 +}
  285 +
  286 +struct DFWatchFigmaDetailPreviewGallery: View {
  287 + var body: some View {
  288 + TabView {
  289 + DFTodayStatusOverviewFigmaView(hasData: true)
  290 + DFTodayStatusOverviewFigmaView(hasData: false)
  291 + DFWatchSettingsFigmaView()
  292 + DFProRequiredInfoFigmaView()
  293 + DFRefreshModeInfoFigmaView()
  294 + }
  295 +#if os(watchOS)
  296 + .tabViewStyle(.verticalPage)
  297 +#else
  298 + .tabViewStyle(.page)
  299 +#endif
  300 + }
  301 +}
  302 +
  303 +#Preview("Figma watch detail states") {
  304 + DFWatchFigmaDetailPreviewGallery()
  305 +}
  1 +import SwiftUI
  2 +import UIKit
  3 +
  4 +struct DFDefaultWatchHomeView: View {
  5 + @State private var batteryLevel: Float = UIDevice.current.batteryLevel
  6 + @State private var batteryState: UIDevice.BatteryState = UIDevice.current.batteryState
  7 +
  8 + @State private var weekday: String = ""
  9 + @State private var day: String = ""
  10 +
  11 + var hasData: Bool = false
  12 + var hrvValue: String = "38ms"
  13 + var hrvTime: String = "19:04"
  14 +
  15 + var batteryColor: Color{
  16 + if batteryLevel < 0.1{
  17 + // 0
  18 + return Color(hex: "#FF0000")
  19 + }else if batteryLevel < 40{
  20 + // 25
  21 + return Color(hex: "#FF9A6E")
  22 + }else if batteryLevel < 60{
  23 + // 50
  24 + return Color(hex: "#7B9BFB")
  25 + }else if batteryLevel < 80{
  26 + // 75
  27 + return Color(hex: "#3BD49D")
  28 + }else{
  29 + // 100
  30 + return Color(hex: "#3BD49D")
  31 + }
  32 + }
  33 + var batteryImageName: String{
  34 + if batteryLevel < 0.1{
  35 + // 0
  36 + return "battery.0percent"
  37 + }else if batteryLevel < 40{
  38 + // 25
  39 + return "battery.25percent"
  40 + }else if batteryLevel < 60{
  41 + // 50
  42 + return "battery.50percent"
  43 + }else if batteryLevel < 80{
  44 + // 75
  45 + return "battery.75percent"
  46 + }else{
  47 + // 100
  48 + return "battery.100percent"
  49 + }
  50 + }
  51 +
  52 + var body: some View {
  53 + VStack{
  54 + HStack{
  55 + Image(systemName: batteryImageName)
  56 + .frame(height: 20)
  57 + .tint(batteryColor)
  58 + Spacer()
  59 + Text(weekday)
  60 + .font(.system(size: 16, weight: .medium))
  61 + .foregroundColor(DFWatchFigmaColor.purple)
  62 + Spacer().frame(width: 4)
  63 + Text(day)
  64 + .font(.system(size: 16, weight: .medium))
  65 + .foregroundColor(.white)
  66 + }
  67 + Text(.now, style: .time)
  68 + .font(.system(size: 52, weight: .medium))
  69 + .foregroundColor(.white)
  70 + .frame(height: 50)
  71 + HStack(alignment: .center){
  72 + HStack{}
  73 + .frame(width: 44, height: 44)
  74 + .background(Color(hex: "#FF0000"))
  75 + Spacer().frame(width: 14)
  76 + VStack(alignment: .leading, spacing: 0) {
  77 + Text(hasData ? "状态优秀" : "暂无数据")
  78 + .font(.system(size: 16, weight: .semibold))
  79 + .foregroundColor(hasData ? DFWatchFigmaColor.green : DFWatchFigmaColor.grayText)
  80 + Text(hasData ? "\(hrvValue)·\(hrvTime)" : "--ms·--:--")
  81 + .font(.system(size: 12, weight: .medium))
  82 + .foregroundColor(.white)
  83 + DFWatchFigmaSegmentBar(selected: nil)
  84 + .frame(height: 14)
  85 + }
  86 + }
  87 + HStack{
  88 + DFWatchHeartBeatCircle(progress: 0, value: nil)
  89 + .frame(width: 45, height: 44)
  90 + Spacer()
  91 + DFWatchCloseCircle(outerProgress: 0, middleProgress: 0, innerProgress: 0)
  92 + .frame(width: 44, height: 44)
  93 + Spacer()
  94 + DFWatchStepCountCircle(progress: 0, value: 0)
  95 + .frame(width: 44, height: 44)
  96 + }
  97 + }
  98 + .padding(.all, 15)
  99 + .onAppear {
  100 + updateDate()
  101 + updateBattery()
  102 + NotificationCenter.default.addObserver(
  103 + forName: UIDevice.batteryLevelDidChangeNotification,
  104 + object: nil,
  105 + queue: .main
  106 + ) { _ in
  107 + updateBattery()
  108 + }
  109 +
  110 + NotificationCenter.default.addObserver(
  111 + forName: UIDevice.batteryStateDidChangeNotification,
  112 + object: nil,
  113 + queue: .main
  114 + ) { _ in
  115 + updateBattery()
  116 + }
  117 + }
  118 + }
  119 +
  120 + private func updateBattery() {
  121 + UIDevice.current.isBatteryMonitoringEnabled = true
  122 + batteryLevel = UIDevice.current.batteryLevel
  123 + batteryState = UIDevice.current.batteryState
  124 + }
  125 + private func updateDate(){
  126 + let calendar = Calendar.current
  127 + let component = calendar.component(.weekday, from: .now)
  128 + weekday = calendar.shortWeekdaySymbols[component].uppercased()
  129 +
  130 + let formatter = DateFormatter()
  131 + formatter.dateFormat = "dd"
  132 + day = formatter.string(from: .now)
  133 + }
  134 +}
  1 +import SwiftUI
  2 +
  3 +enum DFWatchStressKind: String {
  4 + case excellent
  5 + case normal
  6 + case little
  7 + case overloaded
  8 +
  9 + var title: String {
  10 + switch self {
  11 + case .excellent:
  12 + return "状态优秀"
  13 + case .overloaded:
  14 + return "压力过载"
  15 + case .normal:
  16 + return "状态正常"
  17 + case .little:
  18 + return "注意压力"
  19 + }
  20 + }
  21 +
  22 + var color: Color {
  23 + switch self {
  24 + case .excellent:
  25 + return DFWatchFigmaColor.green
  26 + case .overloaded:
  27 + return DFWatchFigmaColor.red
  28 + case .normal:
  29 + return DFWatchFigmaColor.blue
  30 + case .little:
  31 + return DFWatchFigmaColor.orange
  32 + }
  33 + }
  34 +}
  35 +
  36 +enum DFWatchFigmaColor {
  37 + static let background = Color(hex: "0F0F11")
  38 + static let purple = Color(hex: "845EEE")
  39 + static let purpleText = Color(hex: "A285F4")
  40 + static let green = Color(hex: "3BD49D")
  41 + static let red = Color(hex: "FF5279")
  42 + static let orange = Color(hex: "FF9A6E")
  43 + static let blue = Color(hex: "7B9BFB")
  44 + static let grayText = Color(hex: "B0B0B6")
  45 + static let grayBar = Color(hex: "78787D")
  46 + static let pro = Color(hex: "FFDF51")
  47 +}
  48 +
  49 +struct DFWatchFigmaCanvas<Content: View>: View {
  50 + private let designSize = CGSize(width: 352, height: 430)
  51 + let content: (CGFloat) -> Content
  52 +
  53 + init(@ViewBuilder content: @escaping (CGFloat) -> Content) {
  54 + self.content = content
  55 + }
  56 +
  57 + var body: some View {
  58 + GeometryReader { proxy in
  59 + let scale = min(proxy.size.width / designSize.width, proxy.size.height / designSize.height)
  60 + ZStack {
  61 + DFWatchFigmaColor.background
  62 + content(scale)
  63 + }
  64 + .frame(width: designSize.width * scale, height: designSize.height * scale)
  65 + .position(x: proxy.size.width / 2, y: proxy.size.height / 2)
  66 + .clipped()
  67 + }
  68 + .background(DFWatchFigmaColor.background)
  69 + .ignoresSafeArea()
  70 + }
  71 +}
  72 +
  73 +extension CGFloat {
  74 + func df(_ scale: CGFloat) -> CGFloat {
  75 + self * scale
  76 + }
  77 +}
  78 +
  79 +extension Int {
  80 + func df(_ scale: CGFloat) -> CGFloat {
  81 + CGFloat(self) * scale
  82 + }
  83 +}
  84 +
  85 +extension Double {
  86 + func df(_ scale: CGFloat) -> CGFloat {
  87 + CGFloat(self) * scale
  88 + }
  89 +}
  90 +
  91 +struct DFWatchFigmaHeader: View {
  92 + var subtitle: String?
  93 +
  94 + var body: some View {
  95 + HStack {
  96 + Circle()
  97 + .fill(Color.white.opacity(0.12))
  98 + .frame(width: 32, height: 32)
  99 + .overlay(
  100 + Image(systemName: "gearshape.fill")
  101 + .font(.system(size: 14, weight: .medium))
  102 + .foregroundColor(.white)
  103 + )
  104 + Spacer()
  105 + VStack(alignment: .trailing, spacing: 1) {
  106 + Text(.now, style: .time)
  107 + .font(.system(size: 14, weight: .medium))
  108 + .foregroundColor(.white)
  109 + if let subtitle {
  110 + Text(subtitle)
  111 + .font(.system(size: 12, weight: .regular))
  112 + .foregroundColor(.white.opacity(0.6))
  113 + }
  114 + }
  115 + }
  116 + }
  117 +}
  118 +
  119 +struct DFWatchFigmaProBadge: View {
  120 + var body: some View {
  121 + HStack(spacing: 0) {
  122 + Image(systemName: "crown.fill")
  123 + .font(.system(size: 7, weight: .bold))
  124 + .frame(width: 13, height: 13)
  125 + Text("PRO")
  126 + .font(.system(size: 9, weight: .medium))
  127 + }
  128 + .foregroundColor(DFWatchFigmaColor.background)
  129 + .padding(.horizontal, 4)
  130 + .background(DFWatchFigmaColor.pro)
  131 + .clipShape(Capsule())
  132 + }
  133 +}
  134 +
  135 +struct DFWatchFigmaSegmentBar: View {
  136 + let selected: DFWatchStressKind?
  137 +
  138 + let allKinds: [DFWatchStressKind] = [.overloaded, .little, .normal, .excellent]
  139 + let spacing: CGFloat = 2
  140 +
  141 + var body: some View {
  142 + if let selected{
  143 + GeometryReader { proxy in
  144 + HStack(spacing: spacing) {
  145 + let extraWidth: CGFloat = proxy.size.width / 5
  146 + let availableWidth = proxy.size.width - CGFloat(allKinds.count - 1) * spacing - extraWidth
  147 + let itemWidth = floor(availableWidth/4)
  148 + ForEach(allKinds, id: \.rawValue){kind in
  149 + DFWatchKindBar(width: selected == kind ? (itemWidth + extraWidth) : itemWidth, kind: kind, selectedKind: selected)
  150 + }
  151 + }
  152 + }
  153 + }else{
  154 + Capsule()
  155 + .fill(Color(hex: "#78787D"))
  156 + .frame(width: .infinity, height: 8)
  157 + }
  158 + }
  159 +}
  160 +
  161 +struct DFWatchKindBar: View {
  162 + let width: CGFloat
  163 + let kind: DFWatchStressKind
  164 + let selectedKind: DFWatchStressKind
  165 +
  166 + var isSelected: Bool{
  167 + kind == selectedKind
  168 + }
  169 +
  170 + var body: some View {
  171 + ZStack{
  172 + Capsule()
  173 + .fill(kind.color)
  174 + .frame(width: width, height: 8)
  175 + if isSelected{
  176 + Capsule()
  177 + .stroke(kind.color, lineWidth: 4)
  178 + .frame(width: 14, height: 14)
  179 + .background(.black)
  180 + }
  181 + }
  182 + }
  183 +}
  184 +
  185 +struct DFWatchFigmaBottomMetrics: View {
  186 + let scale: CGFloat
  187 + var hasData: Bool
  188 + var heartRate: String = "89"
  189 + var steps: String = "2486"
  190 +
  191 + var body: some View {
  192 + ZStack {
  193 + DFMetricBubble(scale: scale, value: hasData ? heartRate : "0", icon: "heart.fill", tint: DFWatchFigmaColor.red)
  194 + .position(x: 69.df(scale), y: 362.df(scale))
  195 + DFMetricBubble(scale: scale, value: "", icon: "sparkles", tint: DFWatchFigmaColor.purple)
  196 + .position(x: 176.df(scale), y: 362.df(scale))
  197 + DFMetricBubble(scale: scale, value: hasData ? steps : "0", icon: "figure.walk", tint: DFWatchFigmaColor.green)
  198 + .position(x: 287.df(scale), y: 362.df(scale))
  199 + }
  200 + }
  201 +}
  202 +
  203 +private struct DFMetricBubble: View {
  204 + let scale: CGFloat
  205 + let value: String
  206 + let icon: String
  207 + let tint: Color
  208 +
  209 + var body: some View {
  210 + ZStack {
  211 + Circle()
  212 + .fill(Color.white.opacity(0.10))
  213 + .frame(width: 71.df(scale), height: 71.df(scale))
  214 + Circle()
  215 + .trim(from: 0, to: value.isEmpty ? 1 : 0.72)
  216 + .stroke(tint, style: StrokeStyle(lineWidth: max(1, 5.df(scale)), lineCap: .round))
  217 + .rotationEffect(.degrees(-90))
  218 + .frame(width: 63.df(scale), height: 63.df(scale))
  219 + VStack(spacing: 7.df(scale)) {
  220 + Text(value)
  221 + .font(.system(size: 18.df(scale), weight: .medium))
  222 + .foregroundColor(.white)
  223 + .opacity(value.isEmpty ? 0 : 1)
  224 + Image(systemName: icon)
  225 + .font(.system(size: 18.df(scale), weight: .semibold))
  226 + .foregroundColor(.white)
  227 + }
  228 + }
  229 + .frame(width: 82.df(scale), height: 82.df(scale))
  230 + }
  231 +}
  1 +//
  2 +// DFWatchHeartBeatCircle.swift
  3 +// iwatch
  4 +//
  5 +// Created by 权海 on 2026/6/12.
  6 +//
  7 +
  8 +import SwiftUI
  9 +
  10 +struct DFWatchHeartBeatCircle: View {
  11 + /// 0...1
  12 + var progress: CGFloat
  13 +
  14 + /// 中间显示的分数
  15 + var value: Int?
  16 +
  17 + var lineWidth: CGFloat = 6
  18 + var markerSize: CGFloat = 8
  19 +
  20 + private let gradientColors: [Color] = [
  21 + Color(hex: "#3BD49D"),
  22 + Color(hex: "#7B9BFB"),
  23 + Color(hex: "#FF9A6E"),
  24 + Color(hex: "#FF5279")
  25 + ]
  26 +
  27 + var body: some View {
  28 + GeometryReader { geometry in
  29 + let size = min(geometry.size.width, geometry.size.height)
  30 + let arcSize = size - markerSize
  31 + let startAngle: CGFloat = 90
  32 + let sweepAngle: CGFloat = 270
  33 + let rotation = 0.128 * 360
  34 +
  35 + let clampedProgress = min(max(progress, 0), 1)
  36 + let markerAngle = (startAngle + rotation) + sweepAngle * clampedProgress
  37 +
  38 + ZStack {
  39 + Color.black
  40 + // 渐变进度圆弧
  41 + Circle()
  42 + .trim(from: 0.25, to: 1)
  43 + .stroke(
  44 + AngularGradient(
  45 + gradient: Gradient(colors: gradientColors),
  46 + center: .center,
  47 + startAngle: .degrees(Double(startAngle)),
  48 + endAngle: .degrees(Double(startAngle + sweepAngle))
  49 + ),
  50 + style: StrokeStyle(
  51 + lineWidth: lineWidth,
  52 + lineCap: .round,
  53 + lineJoin: .round
  54 + )
  55 + )
  56 + .frame(width: arcSize, height: arcSize)
  57 + .rotationEffect(.degrees(rotation))
  58 + .opacity(value == nil ? 0.3 : 1)
  59 +
  60 + // 中间数值
  61 + Text("\(value ?? 0)")
  62 + .font(.system(size: 9, weight: .bold, design: .rounded))
  63 + .lineLimit(1)
  64 + .foregroundStyle(.white)
  65 + .frame(maxWidth: geometry.size.width - 20)
  66 + .minimumScaleFactor(0.8)
  67 + .offset(y: -size * 0.02)
  68 +
  69 + // 底部爱心
  70 + HeartBadgeView()
  71 + .frame(width: 10, height: 10)
  72 + .offset(y: geometry.size.height - 28)
  73 +
  74 + // 当前进度 marker
  75 + if let _ = value{
  76 + let markerPoint = pointOnCircle(
  77 + angle: markerAngle,
  78 + radius: arcSize / 2,
  79 + center: CGPoint(x: size / 2, y: size / 2)
  80 + )
  81 +
  82 + Circle()
  83 + .fill(.clear)
  84 + .frame(width: markerSize, height: markerSize)
  85 + .overlay(
  86 + Circle()
  87 + .stroke(Color.black, lineWidth: 2)
  88 + )
  89 + .position(markerPoint)
  90 + }
  91 + }
  92 + .frame(width: size, height: size)
  93 + }
  94 + .aspectRatio(1, contentMode: .fit)
  95 + }
  96 +
  97 + private func pointOnCircle(
  98 + angle: CGFloat,
  99 + radius: CGFloat,
  100 + center: CGPoint
  101 + ) -> CGPoint {
  102 + let radians = angle * .pi / 180
  103 + return CGPoint(
  104 + x: center.x + cos(radians) * radius,
  105 + y: center.y + sin(radians) * radius
  106 + )
  107 + }
  108 +}
  109 +
  110 +struct HeartBadgeView: View {
  111 + var body: some View {
  112 + ZStack {
  113 + Image(systemName: "heart.fill")
  114 + .resizable()
  115 + .scaledToFit()
  116 + .foregroundStyle(Color(hex: "#FF5279"))
  117 +
  118 + Image(systemName: "waveform.path.ecg")
  119 + .font(.system(size: 8, weight: .bold))
  120 + .minimumScaleFactor(0.9)
  121 + .foregroundStyle(.black)
  122 + .scaledToFit()
  123 + .padding(.all, 2)
  124 + }
  125 + }
  126 +}
  1 +//
  2 +// DFWatchStepCountCircle.swift
  3 +// iwatch
  4 +//
  5 +// Created by 权海 on 2026/6/12.
  6 +//
  7 +
  8 +import SwiftUI
  9 +
  10 +struct DFWatchStepCountCircle: View {
  11 + /// 0...1
  12 + var progress: CGFloat
  13 +
  14 + /// 中间显示的分数
  15 + var value: Int
  16 +
  17 + var lineWidth: CGFloat = 6
  18 + var markerSize: CGFloat = 8
  19 +
  20 + private let gradientColors: [Color] = [
  21 + Color(hex: "#845EEE"),
  22 + Color(hex: "#845EEE"),
  23 + ]
  24 +
  25 + var body: some View {
  26 + GeometryReader { geometry in
  27 + let size = min(geometry.size.width, geometry.size.height)
  28 + let arcSize = size - markerSize
  29 + let startAngle: CGFloat = 90
  30 + let sweepAngle: CGFloat = 270
  31 + let rotation = 0.128 * 360
  32 +
  33 + let clampedProgress = min(max(progress, 0), 1)
  34 +
  35 + ZStack {
  36 + Color.black
  37 + // 渐变进度圆弧
  38 + Circle()
  39 + .trim(from: 0.25, to: 1)
  40 + .stroke(
  41 + AngularGradient(
  42 + gradient: Gradient(colors: gradientColors),
  43 + center: .center,
  44 + startAngle: .degrees(Double(startAngle)),
  45 + endAngle: .degrees(Double(startAngle + sweepAngle))
  46 + ),
  47 + style: StrokeStyle(
  48 + lineWidth: lineWidth,
  49 + lineCap: .round,
  50 + lineJoin: .round
  51 + )
  52 + )
  53 + .frame(width: arcSize, height: arcSize)
  54 + .rotationEffect(.degrees(rotation))
  55 + .opacity(0.3)
  56 + Circle()
  57 + .trim(from: 0.25, to: 0.25 + progress * 3/4)
  58 + .stroke(
  59 + AngularGradient(
  60 + gradient: Gradient(colors: gradientColors),
  61 + center: .center,
  62 + startAngle: .degrees(Double(startAngle)),
  63 + endAngle: .degrees(Double(startAngle + sweepAngle))
  64 + ),
  65 + style: StrokeStyle(
  66 + lineWidth: lineWidth,
  67 + lineCap: .round,
  68 + lineJoin: .round
  69 + )
  70 + )
  71 + .frame(width: arcSize, height: arcSize)
  72 + .rotationEffect(.degrees(rotation))
  73 +
  74 + // 中间数值
  75 + Text("\(value)")
  76 + .font(.system(size: 9, weight: .bold, design: .rounded))
  77 + .lineLimit(1)
  78 + .foregroundStyle(.white)
  79 + .frame(maxWidth: geometry.size.width - 20)
  80 + .minimumScaleFactor(0.8)
  81 + .offset(y: -size * 0.02)
  82 +
  83 + // 底部爱心
  84 + FootprintsIcon(color: gradientColors.first!)
  85 + .frame(width: 14, height: 14)
  86 + .offset(y: geometry.size.height - 28)
  87 + }
  88 + .frame(width: size, height: size)
  89 + }
  90 + .aspectRatio(1, contentMode: .fit)
  91 + }
  92 +}
  93 +
  94 +struct FootprintsIcon: View {
  95 + var color: Color
  96 +
  97 + var body: some View {
  98 + Image(systemName: "shoeprints.fill")
  99 + .resizable()
  100 + .scaledToFit()
  101 + .foregroundStyle(color)
  102 + }
  103 +}
@@ -49,8 +49,8 @@ class StatusComparisonViewModel: ObservableObject { @@ -49,8 +49,8 @@ class StatusComparisonViewModel: ObservableObject {
49 49
50 private func getMyWatchTheme() { 50 private func getMyWatchTheme() {
51 // 1️⃣ 先从 UserDefaults 读取缓存 51 // 1️⃣ 先从 UserDefaults 读取缓存
52 - let defaults = UserDefaults(suiteName: "group.com.luiz.doublefeel.watchkitapp")  
53 - if let jsonString = defaults?.string(forKey: "myWatchTheme"), 52 + let defaults = AppGroupConstants.defaults
  53 + if let jsonString = defaults?.string(forKey: AppGroupConstants.Key.myWatchTheme),
54 let jsonData = jsonString.data(using: .utf8), 54 let jsonData = jsonString.data(using: .utf8),
55 let cachedModel = try? JSONDecoder().decode(WatchThemeModel.self, from: jsonData) { 55 let cachedModel = try? JSONDecoder().decode(WatchThemeModel.self, from: jsonData) {
56 // 先展示缓存数据 56 // 先展示缓存数据
@@ -87,8 +87,8 @@ class StatusComparisonViewModel: ObservableObject { @@ -87,8 +87,8 @@ class StatusComparisonViewModel: ObservableObject {
87 guard WatchUserinfoManager.share.myUserinfo?.isPaired == true else { return } 87 guard WatchUserinfoManager.share.myUserinfo?.isPaired == true else { return }
88 88
89 // 1️⃣ 先从 UserDefaults 读取缓存 89 // 1️⃣ 先从 UserDefaults 读取缓存
90 - let defaults = UserDefaults(suiteName: "group.com.luiz.doublefeel.watchkitapp")  
91 - if let jsonString = defaults?.string(forKey: "otherWatchTheme"), 90 + let defaults = AppGroupConstants.defaults
  91 + if let jsonString = defaults?.string(forKey: AppGroupConstants.Key.otherWatchTheme),
92 let jsonData = jsonString.data(using: .utf8), 92 let jsonData = jsonString.data(using: .utf8),
93 let cachedModel = try? JSONDecoder().decode(WatchThemeModel.self, from: jsonData) { 93 let cachedModel = try? JSONDecoder().decode(WatchThemeModel.self, from: jsonData) {
94 // 先展示缓存数据 94 // 先展示缓存数据
@@ -167,7 +167,7 @@ class StatusComparisonViewModel: ObservableObject { @@ -167,7 +167,7 @@ class StatusComparisonViewModel: ObservableObject {
167 guard let fileName else {return} 167 guard let fileName else {return}
168 168
169 guard let containerURL = FileManager.default.containerURL( 169 guard let containerURL = FileManager.default.containerURL(
170 - forSecurityApplicationGroupIdentifier: "group.com.luiz.doublefeel.watchkitapp" 170 + forSecurityApplicationGroupIdentifier: AppGroupConstants.identifier
171 ) else { 171 ) else {
172 print("❌ App Group 容器不存在,请检查配置") 172 print("❌ App Group 容器不存在,请检查配置")
173 return 173 return
@@ -497,18 +497,18 @@ extension WatchDataManager { @@ -497,18 +497,18 @@ extension WatchDataManager {
497 } 497 }
498 498
499 private func saveHRVValue(_ value: Double) { 499 private func saveHRVValue(_ value: Double) {
500 - let defaults = UserDefaults(suiteName: "group.com.luiz.doublefeel.watchkitapp")  
501 - defaults?.set(value, forKey: "latestHRV") 500 + let defaults = AppGroupConstants.defaults
  501 + defaults?.set(value, forKey: AppGroupConstants.Key.latestHRV)
502 } 502 }
503 503
504 private func saveHRVBaselineValue(_ value: Double?) { 504 private func saveHRVBaselineValue(_ value: Double?) {
505 - let defaults = UserDefaults(suiteName: "group.com.luiz.doublefeel.watchkitapp")  
506 - defaults?.set(value, forKey: "latestHRVBaseline") 505 + let defaults = AppGroupConstants.defaults
  506 + defaults?.set(value, forKey: AppGroupConstants.Key.latestHRVBaseline)
507 } 507 }
508 508
509 private func saveStepCountValue(_ value: Int) { 509 private func saveStepCountValue(_ value: Int) {
510 - let defaults = UserDefaults(suiteName: "group.com.luiz.doublefeel.watchkitapp")  
511 - defaults?.set(value, forKey: "latestStepCount") 510 + let defaults = AppGroupConstants.defaults
  511 + defaults?.set(value, forKey: AppGroupConstants.Key.latestStepCount)
512 } 512 }
513 } 513 }
514 514
@@ -70,7 +70,7 @@ class WatchUserinfoManager: ObservableObject { @@ -70,7 +70,7 @@ class WatchUserinfoManager: ObservableObject {
70 } 70 }
71 71
72 private func saveMyUserCharacter(_ character: Int) { 72 private func saveMyUserCharacter(_ character: Int) {
73 - let defaults = UserDefaults(suiteName: "group.com.luiz.doublefeel.watchkitapp")  
74 - defaults?.set(character, forKey: "myUserCharacter") 73 + let defaults = AppGroupConstants.defaults
  74 + defaults?.set(character, forKey: AppGroupConstants.Key.myUserCharacter)
75 } 75 }
76 } 76 }
@@ -3,12 +3,15 @@ @@ -3,12 +3,15 @@
3 archiveVersion = 1; 3 archiveVersion = 1;
4 classes = { 4 classes = {
5 }; 5 };
6 - objectVersion = 54; 6 + objectVersion = 77;
7 objects = { 7 objects = {
8 8
9 /* Begin PBXBuildFile section */ 9 /* Begin PBXBuildFile section */
10 0798E27DB95F2A823881D75A /* Pods_Runner_Watch_App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7A488EFC0BD642ED604C4E43 /* Pods_Runner_Watch_App.framework */; }; 10 0798E27DB95F2A823881D75A /* Pods_Runner_Watch_App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7A488EFC0BD642ED604C4E43 /* Pods_Runner_Watch_App.framework */; };
11 20A3C4994C9B0F60D1F3BCBE /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E8DC48B3736B7FEB548D0E65 /* Pods_Runner.framework */; }; 11 20A3C4994C9B0F60D1F3BCBE /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E8DC48B3736B7FEB548D0E65 /* Pods_Runner.framework */; };
  12 + 66FB19002FDBC80100F515B4 /* Runner Watch App/FigmaHome/DFWatchFigmaTokens.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66FB19032FDBC80100F515B4 /* Runner Watch App/FigmaHome/DFWatchFigmaTokens.swift */; };
  13 + 66FB19012FDBC80100F515B4 /* Runner Watch App/FigmaHome/DFWatchFigmaHomeViews.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66FB19042FDBC80100F515B4 /* Runner Watch App/FigmaHome/DFWatchFigmaHomeViews.swift */; };
  14 + 66FB19022FDBC80100F515B4 /* Runner Watch App/FigmaHome/DFWatchFigmaDetailViews.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66FB19052FDBC80100F515B4 /* Runner Watch App/FigmaHome/DFWatchFigmaDetailViews.swift */; };
12 66FBE58C2FDA4F0F00F515B4 /* Runner Watch App.app in Embed Watch Content */ = {isa = PBXBuildFile; fileRef = 66FBE58B2FDA4F0F00F515B4 /* Runner Watch App.app */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 15 66FBE58C2FDA4F0F00F515B4 /* Runner Watch App.app in Embed Watch Content */ = {isa = PBXBuildFile; fileRef = 66FBE58B2FDA4F0F00F515B4 /* Runner Watch App.app */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
13 /* End PBXBuildFile section */ 16 /* End PBXBuildFile section */
14 17
@@ -51,6 +54,9 @@ @@ -51,6 +54,9 @@
51 27E4D5A8995AB1EC91E7330E /* Pods-Runner Watch App.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner Watch App.debug.xcconfig"; path = "Target Support Files/Pods-Runner Watch App/Pods-Runner Watch App.debug.xcconfig"; sourceTree = "<group>"; }; 54 27E4D5A8995AB1EC91E7330E /* Pods-Runner Watch App.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner Watch App.debug.xcconfig"; path = "Target Support Files/Pods-Runner Watch App/Pods-Runner Watch App.debug.xcconfig"; sourceTree = "<group>"; };
52 4A9B7C102FDB0A1200F515B4 /* Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = "<group>"; }; 55 4A9B7C102FDB0A1200F515B4 /* Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = "<group>"; };
53 4A9B7C112FDB0A1200F515B4 /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = "<group>"; }; 56 4A9B7C112FDB0A1200F515B4 /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = "<group>"; };
  57 + 66FB19032FDBC80100F515B4 /* Runner Watch App/FigmaHome/DFWatchFigmaTokens.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Runner Watch App/FigmaHome/DFWatchFigmaTokens.swift"; sourceTree = "<group>"; };
  58 + 66FB19042FDBC80100F515B4 /* Runner Watch App/FigmaHome/DFWatchFigmaHomeViews.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Runner Watch App/FigmaHome/DFWatchFigmaHomeViews.swift"; sourceTree = "<group>"; };
  59 + 66FB19052FDBC80100F515B4 /* Runner Watch App/FigmaHome/DFWatchFigmaDetailViews.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Runner Watch App/FigmaHome/DFWatchFigmaDetailViews.swift"; sourceTree = "<group>"; };
54 66FBE57E2FDA4F0E00F515B4 /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 60 66FBE57E2FDA4F0E00F515B4 /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
55 66FBE58B2FDA4F0F00F515B4 /* Runner Watch App.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Runner Watch App.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 61 66FBE58B2FDA4F0F00F515B4 /* Runner Watch App.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Runner Watch App.app"; sourceTree = BUILT_PRODUCTS_DIR; };
56 66FBE5A72FDA518C00F515B4 /* WidgetKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WidgetKit.framework; path = System/Library/Frameworks/WidgetKit.framework; sourceTree = SDKROOT; }; 62 66FBE5A72FDA518C00F515B4 /* WidgetKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WidgetKit.framework; path = System/Library/Frameworks/WidgetKit.framework; sourceTree = SDKROOT; };
@@ -63,6 +69,13 @@ @@ -63,6 +69,13 @@
63 /* End PBXFileReference section */ 69 /* End PBXFileReference section */
64 70
65 /* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */ 71 /* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */
  72 + 66FB17B22FDB9E3200F515B4 /* Exceptions for "Runner" folder in "Runner Watch App" target */ = {
  73 + isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
  74 + membershipExceptions = (
  75 + Shared/AppGroupConstants.swift,
  76 + );
  77 + target = 66FBE58A2FDA4F0F00F515B4 /* Runner Watch App */;
  78 + };
66 66FBE6202FDA6E7600F515B4 /* Exceptions for "Runner" folder in "Runner" target */ = { 79 66FBE6202FDA6E7600F515B4 /* Exceptions for "Runner" folder in "Runner" target */ = {
67 isa = PBXFileSystemSynchronizedBuildFileExceptionSet; 80 isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
68 membershipExceptions = ( 81 membershipExceptions = (
@@ -77,14 +90,13 @@ @@ -77,14 +90,13 @@
77 isa = PBXFileSystemSynchronizedRootGroup; 90 isa = PBXFileSystemSynchronizedRootGroup;
78 exceptions = ( 91 exceptions = (
79 66FBE6202FDA6E7600F515B4 /* Exceptions for "Runner" folder in "Runner" target */, 92 66FBE6202FDA6E7600F515B4 /* Exceptions for "Runner" folder in "Runner" target */,
  93 + 66FB17B22FDB9E3200F515B4 /* Exceptions for "Runner" folder in "Runner Watch App" target */,
80 ); 94 );
81 path = Runner; 95 path = Runner;
82 sourceTree = "<group>"; 96 sourceTree = "<group>";
83 }; 97 };
84 66FBE58F2FDA4F0F00F515B4 /* Runner Watch App */ = { 98 66FBE58F2FDA4F0F00F515B4 /* Runner Watch App */ = {
85 isa = PBXFileSystemSynchronizedRootGroup; 99 isa = PBXFileSystemSynchronizedRootGroup;
86 - exceptions = (  
87 - );  
88 path = "Runner Watch App"; 100 path = "Runner Watch App";
89 sourceTree = "<group>"; 101 sourceTree = "<group>";
90 }; 102 };
@@ -119,10 +131,21 @@ @@ -119,10 +131,21 @@
119 path = Flutter; 131 path = Flutter;
120 sourceTree = "<group>"; 132 sourceTree = "<group>";
121 }; 133 };
  134 + 66FB19072FDBC80100F515B4 /* FigmaHome Preview Sources */ = {
  135 + isa = PBXGroup;
  136 + children = (
  137 + 66FB19052FDBC80100F515B4 /* Runner Watch App/FigmaHome/DFWatchFigmaDetailViews.swift */,
  138 + 66FB19042FDBC80100F515B4 /* Runner Watch App/FigmaHome/DFWatchFigmaHomeViews.swift */,
  139 + 66FB19032FDBC80100F515B4 /* Runner Watch App/FigmaHome/DFWatchFigmaTokens.swift */,
  140 + );
  141 + name = "FigmaHome Preview Sources";
  142 + sourceTree = "<group>";
  143 + };
122 66FBE5752FDA4F0E00F515B4 = { 144 66FBE5752FDA4F0E00F515B4 = {
123 isa = PBXGroup; 145 isa = PBXGroup;
124 children = ( 146 children = (
125 66FBE5BF2FDA51A300F515B4 /* doublefeel-watch-app-extensionExtension.entitlements */, 147 66FBE5BF2FDA51A300F515B4 /* doublefeel-watch-app-extensionExtension.entitlements */,
  148 + 66FB19072FDBC80100F515B4 /* FigmaHome Preview Sources */,
126 66FBE5802FDA4F0E00F515B4 /* Runner */, 149 66FBE5802FDA4F0E00F515B4 /* Runner */,
127 66FBE58F2FDA4F0F00F515B4 /* Runner Watch App */, 150 66FBE58F2FDA4F0F00F515B4 /* Runner Watch App */,
128 4A9B7C122FDB0A1200F515B4 /* Flutter */, 151 4A9B7C122FDB0A1200F515B4 /* Flutter */,
@@ -280,10 +303,14 @@ @@ -280,10 +303,14 @@
280 inputFileListPaths = ( 303 inputFileListPaths = (
281 "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist", 304 "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist",
282 ); 305 );
  306 + inputPaths = (
  307 + );
283 name = "[CP] Copy Pods Resources"; 308 name = "[CP] Copy Pods Resources";
284 outputFileListPaths = ( 309 outputFileListPaths = (
285 "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist", 310 "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist",
286 ); 311 );
  312 + outputPaths = (
  313 + );
287 runOnlyForDeploymentPostprocessing = 0; 314 runOnlyForDeploymentPostprocessing = 0;
288 shellPath = /bin/sh; 315 shellPath = /bin/sh;
289 shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; 316 shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
@@ -354,10 +381,14 @@ @@ -354,10 +381,14 @@
354 inputFileListPaths = ( 381 inputFileListPaths = (
355 "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", 382 "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
356 ); 383 );
  384 + inputPaths = (
  385 + );
357 name = "[CP] Embed Pods Frameworks"; 386 name = "[CP] Embed Pods Frameworks";
358 outputFileListPaths = ( 387 outputFileListPaths = (
359 "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", 388 "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
360 ); 389 );
  390 + outputPaths = (
  391 + );
361 runOnlyForDeploymentPostprocessing = 0; 392 runOnlyForDeploymentPostprocessing = 0;
362 shellPath = /bin/sh; 393 shellPath = /bin/sh;
363 shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; 394 shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
@@ -371,10 +402,14 @@ @@ -371,10 +402,14 @@
371 inputFileListPaths = ( 402 inputFileListPaths = (
372 "${PODS_ROOT}/Target Support Files/Pods-Runner Watch App/Pods-Runner Watch App-frameworks-${CONFIGURATION}-input-files.xcfilelist", 403 "${PODS_ROOT}/Target Support Files/Pods-Runner Watch App/Pods-Runner Watch App-frameworks-${CONFIGURATION}-input-files.xcfilelist",
373 ); 404 );
  405 + inputPaths = (
  406 + );
374 name = "[CP] Embed Pods Frameworks"; 407 name = "[CP] Embed Pods Frameworks";
375 outputFileListPaths = ( 408 outputFileListPaths = (
376 "${PODS_ROOT}/Target Support Files/Pods-Runner Watch App/Pods-Runner Watch App-frameworks-${CONFIGURATION}-output-files.xcfilelist", 409 "${PODS_ROOT}/Target Support Files/Pods-Runner Watch App/Pods-Runner Watch App-frameworks-${CONFIGURATION}-output-files.xcfilelist",
377 ); 410 );
  411 + outputPaths = (
  412 + );
378 runOnlyForDeploymentPostprocessing = 0; 413 runOnlyForDeploymentPostprocessing = 0;
379 shellPath = /bin/sh; 414 shellPath = /bin/sh;
380 shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner Watch App/Pods-Runner Watch App-frameworks.sh\"\n"; 415 shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner Watch App/Pods-Runner Watch App-frameworks.sh\"\n";
@@ -416,6 +451,9 @@ @@ -416,6 +451,9 @@
416 isa = PBXSourcesBuildPhase; 451 isa = PBXSourcesBuildPhase;
417 buildActionMask = 2147483647; 452 buildActionMask = 2147483647;
418 files = ( 453 files = (
  454 + 66FB19022FDBC80100F515B4 /* Runner Watch App/FigmaHome/DFWatchFigmaDetailViews.swift in Sources */,
  455 + 66FB19012FDBC80100F515B4 /* Runner Watch App/FigmaHome/DFWatchFigmaHomeViews.swift in Sources */,
  456 + 66FB19002FDBC80100F515B4 /* Runner Watch App/FigmaHome/DFWatchFigmaTokens.swift in Sources */,
419 ); 457 );
420 runOnlyForDeploymentPostprocessing = 0; 458 runOnlyForDeploymentPostprocessing = 0;
421 }; 459 };
@@ -567,6 +605,7 @@ @@ -567,6 +605,7 @@
567 "@executable_path/Frameworks", 605 "@executable_path/Frameworks",
568 ); 606 );
569 MARKETING_VERSION = 1.4.0; 607 MARKETING_VERSION = 1.4.0;
  608 + ONLY_ACTIVE_ARCH = YES;
570 PRODUCT_BUNDLE_IDENTIFIER = com.luiz.doublefeel.watchkitapp; 609 PRODUCT_BUNDLE_IDENTIFIER = com.luiz.doublefeel.watchkitapp;
571 PRODUCT_NAME = "$(TARGET_NAME)"; 610 PRODUCT_NAME = "$(TARGET_NAME)";
572 SDKROOT = watchos; 611 SDKROOT = watchos;
@@ -670,6 +709,7 @@ @@ -670,6 +709,7 @@
670 "@executable_path/Frameworks", 709 "@executable_path/Frameworks",
671 ); 710 );
672 MARKETING_VERSION = 2.5.0; 711 MARKETING_VERSION = 2.5.0;
  712 + ONLY_ACTIVE_ARCH = YES;
673 OTHER_LDFLAGS = ( 713 OTHER_LDFLAGS = (
674 "$(inherited)", 714 "$(inherited)",
675 "-framework", 715 "-framework",
@@ -29,6 +29,9 @@ class AppDelegate: FlutterAppDelegate { @@ -29,6 +29,9 @@ class AppDelegate: FlutterAppDelegate {
29 29
30 flutterEngine.run() 30 flutterEngine.run()
31 GeneratedPluginRegistrant.register(with: flutterEngine) 31 GeneratedPluginRegistrant.register(with: flutterEngine)
  32 + NativePigeonRegistrar.register(binaryMessenger: flutterEngine.binaryMessenger)
  33 + WatchConnectivityService.shared.activate()
  34 + HealthKitService.shared.startBackgroundObserversIfNeeded()
32 35
33 return super.application(application, didFinishLaunchingWithOptions: launchOptions) 36 return super.application(application, didFinishLaunchingWithOptions: launchOptions)
34 } 37 }
  1 +import Foundation
  2 +import HealthKit
  3 +
  4 +/// Focused HealthKit query helper. It mirrors the original SwiftUI project data
  5 +/// coverage while avoiding dependencies on the old network and user modules.
  6 +final class HealthDataReader {
  7 + private let healthStore: HKHealthStore
  8 +
  9 + init(healthStore: HKHealthStore) {
  10 + self.healthStore = healthStore
  11 +
  12 + }
  13 +
  14 + func collectRecentData(startDate: Date, endDate: Date) async throws -> NativeHealthSyncSummary {
  15 + async let hrv = fetchQuantitySamples(
  16 + identifier: .heartRateVariabilitySDNN,
  17 + dataType: .hrv,
  18 + unit: .secondUnit(with: .milli),
  19 + startDate: startDate,
  20 + endDate: endDate
  21 + )
  22 + async let heart = fetchHeartRateFamily(startDate: startDate, endDate: endDate)
  23 + async let oxygen = fetchQuantitySamples(
  24 + identifier: .oxygenSaturation,
  25 + dataType: .oxygenSaturation,
  26 + unit: .percent(),
  27 + startDate: startDate,
  28 + endDate: endDate
  29 + )
  30 + async let activeEnergy = fetchQuantitySamples(
  31 + identifier: .activeEnergyBurned,
  32 + dataType: .activeEnergy,
  33 + unit: .kilocalorie(),
  34 + startDate: startDate,
  35 + endDate: endDate
  36 + )
  37 + async let exercise = fetchQuantitySamples(
  38 + identifier: .appleExerciseTime,
  39 + dataType: .exercise,
  40 + unit: .minute(),
  41 + startDate: startDate,
  42 + endDate: endDate
  43 + )
  44 + async let stand = fetchQuantitySamples(
  45 + identifier: .appleStandTime,
  46 + dataType: .stand,
  47 + unit: .minute(),
  48 + startDate: startDate,
  49 + endDate: endDate
  50 + )
  51 + async let steps = fetchDailyCumulativeSamples(
  52 + identifier: .stepCount,
  53 + dataType: .steps,
  54 + unit: .count(),
  55 + startDate: startDate,
  56 + endDate: endDate
  57 + )
  58 + async let wristTemp = fetchQuantitySamples(
  59 + identifier: .appleSleepingWristTemperature,
  60 + dataType: .sleepingWristTemperature,
  61 + unit: .degreeCelsius(),
  62 + startDate: startDate,
  63 + endDate: endDate
  64 + )
  65 + async let respiratory = fetchQuantitySamples(
  66 + identifier: .respiratoryRate,
  67 + dataType: .respiratoryRate,
  68 + unit: HKUnit.count().unitDivided(by: .minute()),
  69 + startDate: startDate,
  70 + endDate: endDate
  71 + )
  72 + async let rhythm = fetchIrregularHeartRhythmEvents(startDate: startDate, endDate: endDate)
  73 + async let sleep = fetchSleepIntervals(startDate: startDate, endDate: endDate)
  74 +
  75 + let hrvPoints = try await hrv
  76 + let heartPoints = try await heart
  77 + let oxygenPoints = try await oxygen
  78 + let activeEnergyPoints = try await activeEnergy
  79 + let exercisePoints = try await exercise
  80 + let standPoints = try await stand
  81 + let stepPoints = try await steps
  82 + let wristTempPoints = try await wristTemp
  83 + let respiratoryPoints = try await respiratory
  84 + let rhythmPoints = try await rhythm
  85 + let sleepIntervals = try await sleep
  86 +
  87 + return NativeHealthSyncSummary(
  88 + commonCount: hrvPoints.count
  89 + + heartPoints.count
  90 + + oxygenPoints.count
  91 + + activeEnergyPoints.count
  92 + + exercisePoints.count
  93 + + standPoints.count
  94 + + stepPoints.count
  95 + + wristTempPoints.count
  96 + + respiratoryPoints.count
  97 + + rhythmPoints.count,
  98 + sleepCount: sleepIntervals.count,
  99 + startedAt: startDate,
  100 + endedAt: endDate
  101 + )
  102 + }
  103 +
  104 + func fetchLatestHRV() async throws -> Double? {
  105 + guard let type = NativeHealthTypeCatalog.quantity(.heartRateVariabilitySDNN) else {
  106 + throw NativeHealthKitError.invalidType("heartRateVariabilitySDNN")
  107 + }
  108 + let sample = try await fetchLatestQuantitySample(type: type)
  109 + return sample?.quantity.doubleValue(for: .secondUnit(with: .milli))
  110 + }
  111 +
  112 + func fetchTodayStepCount() async throws -> Int {
  113 + guard let type = NativeHealthTypeCatalog.quantity(.stepCount) else {
  114 + throw NativeHealthKitError.invalidType("stepCount")
  115 + }
  116 + let startOfDay = Calendar.current.startOfDay(for: Date())
  117 + let predicate = HKQuery.predicateForSamples(withStart: startOfDay, end: Date())
  118 +
  119 + return try await withCheckedThrowingContinuation { continuation in
  120 + let query = HKStatisticsQuery(
  121 + quantityType: type,
  122 + quantitySamplePredicate: predicate,
  123 + options: .cumulativeSum
  124 + ) { _, statistics, error in
  125 + if let error {
  126 + continuation.resume(throwing: error)
  127 + return
  128 + }
  129 + let value = statistics?.sumQuantity()?.doubleValue(for: .count()) ?? 0
  130 + continuation.resume(returning: Int(value))
  131 + }
  132 + healthStore.execute(query)
  133 + }
  134 + }
  135 +
  136 + private func fetchHeartRateFamily(startDate: Date, endDate: Date) async throws -> [NativeHealthDataPoint] {
  137 + async let heartRate = fetchQuantitySamples(
  138 + identifier: .heartRate,
  139 + dataType: .heartRate,
  140 + unit: HKUnit.count().unitDivided(by: .minute()),
  141 + startDate: startDate,
  142 + endDate: endDate
  143 + )
  144 + async let walking = fetchQuantitySamples(
  145 + identifier: .walkingHeartRateAverage,
  146 + dataType: .walkingHeartRate,
  147 + unit: HKUnit.count().unitDivided(by: .minute()),
  148 + startDate: startDate,
  149 + endDate: endDate
  150 + )
  151 + async let resting = fetchQuantitySamples(
  152 + identifier: .restingHeartRate,
  153 + dataType: .restingHeartRate,
  154 + unit: HKUnit.count().unitDivided(by: .minute()),
  155 + startDate: startDate,
  156 + endDate: endDate
  157 + )
  158 + return try await heartRate + walking + resting
  159 + }
  160 +
  161 + private func fetchQuantitySamples(
  162 + identifier: HKQuantityTypeIdentifier,
  163 + dataType: NativeHealthDataType,
  164 + unit: HKUnit,
  165 + startDate: Date,
  166 + endDate: Date
  167 + ) async throws -> [NativeHealthDataPoint] {
  168 + guard let type = NativeHealthTypeCatalog.quantity(identifier) else {
  169 + throw NativeHealthKitError.invalidType(identifier.rawValue)
  170 + }
  171 + let predicate = HKQuery.predicateForSamples(
  172 + withStart: startDate,
  173 + end: endDate,
  174 + options: .strictStartDate
  175 + )
  176 + let sort = NSSortDescriptor(key: HKSampleSortIdentifierStartDate, ascending: true)
  177 +
  178 + return try await withCheckedThrowingContinuation { continuation in
  179 + let query = HKSampleQuery(
  180 + sampleType: type,
  181 + predicate: predicate,
  182 + limit: HKObjectQueryNoLimit,
  183 + sortDescriptors: [sort]
  184 + ) { _, samples, error in
  185 + if let error {
  186 + continuation.resume(throwing: error)
  187 + return
  188 + }
  189 + let points = (samples as? [HKQuantitySample] ?? []).map { sample in
  190 + NativeHealthDataPoint(
  191 + dataType: dataType,
  192 + time: sample.startDate.timeIntervalSince1970,
  193 + value: sample.quantity.doubleValue(for: unit)
  194 + )
  195 + }
  196 + continuation.resume(returning: points)
  197 + }
  198 + healthStore.execute(query)
  199 + }
  200 + }
  201 +
  202 + private func fetchDailyCumulativeSamples(
  203 + identifier: HKQuantityTypeIdentifier,
  204 + dataType: NativeHealthDataType,
  205 + unit: HKUnit,
  206 + startDate: Date,
  207 + endDate: Date
  208 + ) async throws -> [NativeHealthDataPoint] {
  209 + guard let type = NativeHealthTypeCatalog.quantity(identifier) else {
  210 + throw NativeHealthKitError.invalidType(identifier.rawValue)
  211 + }
  212 + var interval = DateComponents()
  213 + interval.day = 1
  214 + let anchorDate = Calendar.current.startOfDay(for: startDate)
  215 + let predicate = HKQuery.predicateForSamples(withStart: startDate, end: endDate)
  216 +
  217 + return try await withCheckedThrowingContinuation { continuation in
  218 + let query = HKStatisticsCollectionQuery(
  219 + quantityType: type,
  220 + quantitySamplePredicate: predicate,
  221 + options: .cumulativeSum,
  222 + anchorDate: anchorDate,
  223 + intervalComponents: interval
  224 + )
  225 + query.initialResultsHandler = { _, collection, error in
  226 + if let error {
  227 + continuation.resume(throwing: error)
  228 + return
  229 + }
  230 + var points: [NativeHealthDataPoint] = []
  231 + collection?.enumerateStatistics(from: startDate, to: endDate) { statistics, _ in
  232 + guard let value = statistics.sumQuantity()?.doubleValue(for: unit) else { return }
  233 + points.append(
  234 + NativeHealthDataPoint(
  235 + dataType: dataType,
  236 + time: statistics.startDate.timeIntervalSince1970,
  237 + value: value
  238 + )
  239 + )
  240 + }
  241 + continuation.resume(returning: points)
  242 + }
  243 + healthStore.execute(query)
  244 + }
  245 + }
  246 +
  247 + private func fetchSleepIntervals(startDate: Date, endDate: Date) async throws -> [NativeSleepInterval] {
  248 + guard let type = NativeHealthTypeCatalog.category(.sleepAnalysis) else {
  249 + throw NativeHealthKitError.invalidType("sleepAnalysis")
  250 + }
  251 + let predicate = HKQuery.predicateForSamples(
  252 + withStart: startDate,
  253 + end: endDate,
  254 + options: .strictStartDate
  255 + )
  256 + let sort = NSSortDescriptor(key: HKSampleSortIdentifierStartDate, ascending: true)
  257 +
  258 + return try await withCheckedThrowingContinuation { continuation in
  259 + let query = HKSampleQuery(
  260 + sampleType: type,
  261 + predicate: predicate,
  262 + limit: HKObjectQueryNoLimit,
  263 + sortDescriptors: [sort]
  264 + ) { _, samples, error in
  265 + if let error {
  266 + continuation.resume(throwing: error)
  267 + return
  268 + }
  269 + let intervals = (samples as? [HKCategorySample] ?? []).map { sample in
  270 + NativeSleepInterval(
  271 + dataType: sample.value,
  272 + fromTime: sample.startDate.timeIntervalSince1970,
  273 + toTime: sample.endDate.timeIntervalSince1970
  274 + )
  275 + }
  276 + continuation.resume(returning: intervals)
  277 + }
  278 + healthStore.execute(query)
  279 + }
  280 + }
  281 +
  282 + private func fetchIrregularHeartRhythmEvents(
  283 + startDate: Date,
  284 + endDate: Date
  285 + ) async throws -> [NativeHealthDataPoint] {
  286 + guard let type = NativeHealthTypeCatalog.category(.irregularHeartRhythmEvent) else {
  287 + throw NativeHealthKitError.invalidType("irregularHeartRhythmEvent")
  288 + }
  289 + let predicate = HKQuery.predicateForSamples(
  290 + withStart: startDate,
  291 + end: endDate,
  292 + options: .strictStartDate
  293 + )
  294 + let sort = NSSortDescriptor(key: HKSampleSortIdentifierStartDate, ascending: true)
  295 +
  296 + return try await withCheckedThrowingContinuation { continuation in
  297 + let query = HKSampleQuery(
  298 + sampleType: type,
  299 + predicate: predicate,
  300 + limit: HKObjectQueryNoLimit,
  301 + sortDescriptors: [sort]
  302 + ) { _, samples, error in
  303 + if let error {
  304 + continuation.resume(throwing: error)
  305 + return
  306 + }
  307 + let points = (samples as? [HKCategorySample] ?? []).map { sample in
  308 + NativeHealthDataPoint(
  309 + dataType: .irregularHeartRhythm,
  310 + time: sample.startDate.timeIntervalSince1970,
  311 + value: Double(sample.value)
  312 + )
  313 + }
  314 + continuation.resume(returning: points)
  315 + }
  316 + healthStore.execute(query)
  317 + }
  318 + }
  319 +
  320 + private func fetchLatestQuantitySample(type: HKQuantityType) async throws -> HKQuantitySample? {
  321 + let sort = NSSortDescriptor(key: HKSampleSortIdentifierEndDate, ascending: false)
  322 + return try await withCheckedThrowingContinuation { continuation in
  323 + let query = HKSampleQuery(
  324 + sampleType: type,
  325 + predicate: nil,
  326 + limit: 1,
  327 + sortDescriptors: [sort]
  328 + ) { _, samples, error in
  329 + if let error {
  330 + continuation.resume(throwing: error)
  331 + return
  332 + }
  333 + continuation.resume(returning: samples?.first as? HKQuantitySample)
  334 + }
  335 + healthStore.execute(query)
  336 + }
  337 + }
  338 +}
  1 +import Foundation
  2 +import HealthKit
  3 +
  4 +/// Native Apple Health service for the Flutter host API.
  5 +///
  6 +/// Responsibilities:
  7 +/// - request/read HealthKit permissions
  8 +/// - read the health data types used by the original SwiftUI app
  9 +/// - keep Watch complication values fresh in the shared App Group
  10 +/// - register background observers so HealthKit changes refresh local state
  11 +final class HealthKitService {
  12 + static let shared = HealthKitService()
  13 +
  14 + private let healthStore = HKHealthStore()
  15 + private let syncStore = HealthSyncStateStore()
  16 + private lazy var reader = HealthDataReader(healthStore: healthStore)
  17 + private var observersStarted = false
  18 +
  19 + private init() {}
  20 +
  21 + var isHealthDataAvailable: Bool {
  22 + HKHealthStore.isHealthDataAvailable()
  23 + }
  24 +
  25 + func requestAuthorization(completion: @escaping (Bool, Error?) -> Void) {
  26 + guard isHealthDataAvailable else {
  27 + completion(false, NativeHealthKitError.healthDataUnavailable)
  28 + return
  29 + }
  30 +
  31 + healthStore.requestAuthorization(
  32 + toShare: NativeHealthTypeCatalog.writeTypes,
  33 + read: NativeHealthTypeCatalog.readTypes
  34 + ) { success, error in
  35 + completion(success, error)
  36 + }
  37 + }
  38 +
  39 + func shouldRequestAuthorization() async -> Bool {
  40 + guard isHealthDataAvailable else { return false }
  41 + do {
  42 + let status = try await healthStore.statusForAuthorizationRequest(
  43 + toShare: NativeHealthTypeCatalog.writeTypes,
  44 + read: NativeHealthTypeCatalog.readTypes
  45 + )
  46 + return status == .shouldRequest
  47 + } catch {
  48 + return true
  49 + }
  50 + }
  51 +
  52 + func startBackgroundObserversIfNeeded() {
  53 + guard isHealthDataAvailable, !observersStarted else { return }
  54 + observersStarted = true
  55 +
  56 + for sampleType in NativeHealthTypeCatalog.observedTypes {
  57 + enableBackgroundDelivery(for: sampleType)
  58 + let query = HKObserverQuery(sampleType: sampleType, predicate: nil) { [weak self] _, completion, error in
  59 + guard error == nil else {
  60 + completion()
  61 + return
  62 + }
  63 + Task {
  64 + await self?.handleObservedChange(sampleType)
  65 + completion()
  66 + }
  67 + }
  68 + healthStore.execute(query)
  69 + }
  70 + }
  71 +
  72 + func performLocalSync() async -> NativeHealthSyncSummary {
  73 + guard isHealthDataAvailable else {
  74 + return NativeHealthSyncSummary(commonCount: 0, sleepCount: 0, startedAt: Date(), endedAt: Date())
  75 + }
  76 +
  77 + let startDate = earliestStartDate()
  78 + let endDate = Date()
  79 +
  80 + do {
  81 + let summary = try await reader.collectRecentData(startDate: startDate, endDate: endDate)
  82 + NativeHealthDataType.allCases
  83 + .filter { $0 != .unknown }
  84 + .forEach { syncStore.save(date: endDate, for: $0) }
  85 + await refreshSharedWatchValues()
  86 + startBackgroundObserversIfNeeded()
  87 + return summary
  88 + } catch {
  89 + await refreshSharedWatchValues()
  90 + return NativeHealthSyncSummary(commonCount: 0, sleepCount: 0, startedAt: startDate, endedAt: endDate)
  91 + }
  92 + }
  93 +
  94 + func refreshSharedWatchValues() async {
  95 + do {
  96 + if let hrv = try await reader.fetchLatestHRV() {
  97 + AppGroupConstants.defaults?.set(hrv, forKey: AppGroupConstants.Key.latestHRV)
  98 + }
  99 + } catch {
  100 + // Keep the previous widget value when a single read fails.
  101 + }
  102 +
  103 + do {
  104 + let steps = try await reader.fetchTodayStepCount()
  105 + AppGroupConstants.defaults?.set(steps, forKey: AppGroupConstants.Key.latestStepCount)
  106 + } catch {
  107 + // Keep the previous widget value when a single read fails.
  108 + }
  109 + }
  110 +
  111 + private func earliestStartDate() -> Date {
  112 + NativeHealthDataType.allCases
  113 + .filter { $0 != .unknown }
  114 + .map { syncStore.startDate(for: $0) }
  115 + .min() ?? Calendar.current.startOfDay(for: Date())
  116 + }
  117 +
  118 + private func enableBackgroundDelivery(for sampleType: HKSampleType) {
  119 + let frequency: HKUpdateFrequency = sampleType.identifier == HKQuantityTypeIdentifier.stepCount.rawValue
  120 + ? .hourly
  121 + : .immediate
  122 +
  123 + healthStore.enableBackgroundDelivery(for: sampleType, frequency: frequency) { success, error in
  124 + if let error {
  125 + print("HealthKit background delivery failed: \(sampleType.identifier), \(error.localizedDescription)")
  126 + } else {
  127 + print("HealthKit background delivery \(success ? "enabled" : "not enabled"): \(sampleType.identifier)")
  128 + }
  129 + }
  130 + }
  131 +
  132 + private func handleObservedChange(_ sampleType: HKSampleType) async {
  133 + switch sampleType.identifier {
  134 + case HKQuantityTypeIdentifier.heartRateVariabilitySDNN.rawValue,
  135 + HKQuantityTypeIdentifier.stepCount.rawValue:
  136 + await refreshSharedWatchValues()
  137 + default:
  138 + break
  139 + }
  140 +
  141 + if let type = NativeHealthDataType(sampleTypeIdentifier: sampleType.identifier) {
  142 + syncStore.save(date: Date(), for: type)
  143 + }
  144 + }
  145 +}
  146 +
  147 +private extension NativeHealthDataType {
  148 + init?(sampleTypeIdentifier: String) {
  149 + switch sampleTypeIdentifier {
  150 + case HKQuantityTypeIdentifier.heartRateVariabilitySDNN.rawValue:
  151 + self = .hrv
  152 + case HKQuantityTypeIdentifier.heartRate.rawValue:
  153 + self = .heartRate
  154 + case HKQuantityTypeIdentifier.stepCount.rawValue:
  155 + self = .steps
  156 + case HKQuantityTypeIdentifier.oxygenSaturation.rawValue:
  157 + self = .oxygenSaturation
  158 + case HKQuantityTypeIdentifier.activeEnergyBurned.rawValue:
  159 + self = .activeEnergy
  160 + case HKQuantityTypeIdentifier.appleExerciseTime.rawValue:
  161 + self = .exercise
  162 + case HKQuantityTypeIdentifier.appleStandTime.rawValue:
  163 + self = .stand
  164 + case HKQuantityTypeIdentifier.appleSleepingWristTemperature.rawValue:
  165 + self = .sleepingWristTemperature
  166 + case HKQuantityTypeIdentifier.respiratoryRate.rawValue:
  167 + self = .respiratoryRate
  168 + case HKCategoryTypeIdentifier.sleepAnalysis.rawValue:
  169 + self = .sleep
  170 + case HKCategoryTypeIdentifier.irregularHeartRhythmEvent.rawValue:
  171 + self = .irregularHeartRhythm
  172 + default:
  173 + return nil
  174 + }
  175 + }
  176 +}
  177 +
  1 +import Foundation
  2 +import HealthKit
  3 +
  4 +enum NativeHealthKitError: LocalizedError {
  5 + case healthDataUnavailable
  6 + case invalidType(String)
  7 + case noData
  8 +
  9 + var errorDescription: String? {
  10 + switch self {
  11 + case .healthDataUnavailable:
  12 + return "当前设备不支持 HealthKit"
  13 + case .invalidType(let identifier):
  14 + return "无效的健康数据类型:\(identifier)"
  15 + case .noData:
  16 + return "没有找到健康数据"
  17 + }
  18 + }
  19 +}
  20 +
  21 +/// Raw values match the original SwiftUI project server contract.
  22 +enum NativeHealthDataType: Int, Codable, CaseIterable {
  23 + case unknown = 0
  24 + case hrv = 1
  25 + case heartRate = 2
  26 + case oxygenSaturation = 3
  27 + case activeEnergy = 4
  28 + case exercise = 5
  29 + case stand = 6
  30 + case steps = 7
  31 + case walkingHeartRate = 8
  32 + case restingHeartRate = 9
  33 + case sleepingHeartRate = 10
  34 + case sleepingWristTemperature = 11
  35 + case respiratoryRate = 12
  36 + case irregularHeartRhythm = 13
  37 + case sleep = 100
  38 +}
  39 +
  40 +struct NativeHealthDataPoint: Codable {
  41 + let dataType: NativeHealthDataType
  42 + let time: TimeInterval
  43 + let value: Double
  44 +}
  45 +
  46 +struct NativeSleepInterval: Codable {
  47 + let dataType: Int
  48 + let fromTime: TimeInterval
  49 + let toTime: TimeInterval
  50 +}
  51 +
  52 +struct NativeHealthSyncSummary {
  53 + var commonCount = 0
  54 + var sleepCount = 0
  55 + var startedAt: Date
  56 + var endedAt: Date
  57 +}
  58 +
  59 +enum NativeHealthTypeCatalog {
  60 + static var readTypes: Set<HKObjectType> {
  61 + var types = Set<HKObjectType>()
  62 + [
  63 + quantity(.heartRate),
  64 + quantity(.heartRateVariabilitySDNN),
  65 + quantity(.stepCount),
  66 + quantity(.oxygenSaturation),
  67 + quantity(.activeEnergyBurned),
  68 + quantity(.appleExerciseTime),
  69 + quantity(.appleStandTime),
  70 + quantity(.walkingHeartRateAverage),
  71 + quantity(.restingHeartRate),
  72 + quantity(.appleSleepingWristTemperature),
  73 + quantity(.respiratoryRate),
  74 + category(.sleepAnalysis),
  75 + category(.irregularHeartRhythmEvent),
  76 + ].compactMap { $0 }.forEach { types.insert($0) }
  77 + types.insert(HKObjectType.activitySummaryType())
  78 + return types
  79 + }
  80 +
  81 + static var writeTypes: Set<HKSampleType> {
  82 + // Kept from the original app. The current Flutter flow mostly reads data,
  83 + // but requesting this keeps the permission surface compatible.
  84 + Set([quantity(.stepCount)].compactMap { $0 })
  85 + }
  86 +
  87 + static var observedTypes: Set<HKSampleType> {
  88 + Set([
  89 + quantity(.heartRate),
  90 + quantity(.heartRateVariabilitySDNN),
  91 + quantity(.stepCount),
  92 + quantity(.oxygenSaturation),
  93 + quantity(.activeEnergyBurned),
  94 + quantity(.appleExerciseTime),
  95 + quantity(.appleStandTime),
  96 + quantity(.appleSleepingWristTemperature),
  97 + quantity(.respiratoryRate),
  98 + category(.sleepAnalysis),
  99 + category(.irregularHeartRhythmEvent),
  100 + ].compactMap { $0 })
  101 + }
  102 +
  103 + static func quantity(_ identifier: HKQuantityTypeIdentifier) -> HKQuantityType? {
  104 + HKObjectType.quantityType(forIdentifier: identifier)
  105 + }
  106 +
  107 + static func category(_ identifier: HKCategoryTypeIdentifier) -> HKCategoryType? {
  108 + HKObjectType.categoryType(forIdentifier: identifier)
  109 + }
  110 +}
  1 +import Foundation
  2 +
  3 +/// Stores the last successful local HealthKit sync boundary.
  4 +/// This is intentionally independent from the old SwiftUI user/network layer.
  5 +struct HealthSyncStateStore {
  6 + private let defaults: UserDefaults
  7 + private let keyPrefix = "native_health_sync_latest_time_"
  8 +
  9 + init(defaults: UserDefaults = .standard) {
  10 + self.defaults = defaults
  11 + }
  12 +
  13 + func lastSyncDate(for type: NativeHealthDataType) -> Date? {
  14 + let timestamp = defaults.double(forKey: key(for: type))
  15 + return timestamp > 0 ? Date(timeIntervalSince1970: timestamp) : nil
  16 + }
  17 +
  18 + func save(date: Date, for type: NativeHealthDataType) {
  19 + defaults.set(date.timeIntervalSince1970, forKey: key(for: type))
  20 + }
  21 +
  22 + func startDate(for type: NativeHealthDataType, fallbackWeeks: Int = 1) -> Date {
  23 + if let date = lastSyncDate(for: type) {
  24 + return date
  25 + }
  26 + let fallback = Calendar.current.date(byAdding: .weekOfYear, value: -fallbackWeeks, to: Date())
  27 + return Calendar.current.startOfDay(for: fallback ?? Date())
  28 + }
  29 +
  30 + private func key(for type: NativeHealthDataType) -> String {
  31 + "\(keyPrefix)\(type.rawValue)"
  32 + }
  33 +}
  34 +
@@ -26,6 +26,12 @@ @@ -26,6 +26,12 @@
26 <key>NSAllowsArbitraryLoads</key> 26 <key>NSAllowsArbitraryLoads</key>
27 <true/> 27 <true/>
28 </dict> 28 </dict>
  29 + <key>NSHealthShareUsageDescription</key>
  30 + <string>需要读取 Apple Health 中的心率、HRV、睡眠、步数、活动能量等数据,用于展示健康状态并同步到 Apple Watch。</string>
  31 + <key>NSHealthUpdateUsageDescription</key>
  32 + <string>需要写入少量健康数据权限以保持与旧版 Apple Health 同步流程兼容。</string>
  33 + <key>NSPhotoLibraryUsageDescription</key>
  34 + <string>需要从系统相册选择图片,用于创建自定义 Apple Watch 表盘主题。</string>
29 <key>UIDesignRequiresCompatibility</key> 35 <key>UIDesignRequiresCompatibility</key>
30 <true/> 36 <true/>
31 <key>CADisableMinimumFrameDurationOnPhone</key> 37 <key>CADisableMinimumFrameDurationOnPhone</key>
@@ -20,6 +20,12 @@ @@ -20,6 +20,12 @@
20 <key>NSAllowsArbitraryLoads</key> 20 <key>NSAllowsArbitraryLoads</key>
21 <true/> 21 <true/>
22 </dict> 22 </dict>
  23 + <key>NSHealthShareUsageDescription</key>
  24 + <string>需要读取 Apple Health 中的心率、HRV、睡眠、步数、活动能量等数据,用于展示健康状态并同步到 Apple Watch。</string>
  25 + <key>NSHealthUpdateUsageDescription</key>
  26 + <string>需要写入少量健康数据权限以保持与旧版 Apple Health 同步流程兼容。</string>
  27 + <key>NSPhotoLibraryUsageDescription</key>
  28 + <string>需要从系统相册选择图片,用于创建自定义 Apple Watch 表盘主题。</string>
23 <key>UIDesignRequiresCompatibility</key> 29 <key>UIDesignRequiresCompatibility</key>
24 <true/> 30 <true/>
25 <key>CADisableMinimumFrameDurationOnPhone</key> 31 <key>CADisableMinimumFrameDurationOnPhone</key>
  1 +import Foundation
  2 +
  3 +final class HealthKitHostApiImpl: HealthKitHostApi {
  4 + private let service: HealthKitService
  5 +
  6 + init(service: HealthKitService = .shared) {
  7 + self.service = service
  8 + }
  9 +
  10 + func checkHealthAppAuthorization() throws -> Bool {
  11 + service.isHealthDataAvailable && !runBlocking {
  12 + await self.service.shouldRequestAuthorization()
  13 + }
  14 + }
  15 +
  16 + func getHealthServerAuthUrl() throws -> String {
  17 + // Apple Health authorization is system-managed, not URL based.
  18 + ""
  19 + }
  20 +
  21 + func requestHealthClientAuthorization() throws -> Bool {
  22 + let result = runAuthorizationRequest()
  23 + if result.success {
  24 + service.startBackgroundObserversIfNeeded()
  25 + Task {
  26 + await service.refreshSharedWatchValues()
  27 + }
  28 + }
  29 + if let error = result.error {
  30 + throw error
  31 + }
  32 + return result.success
  33 + }
  34 +
  35 + func cancelHealthAppAuthorization() throws -> Bool {
  36 + // iOS does not let apps revoke HealthKit permission programmatically.
  37 + // Users must revoke access in Settings > Health > Data Access & Devices.
  38 + false
  39 + }
  40 +
  41 + func performHealthUpload() throws -> HealthUploadResult {
  42 + let summary = runBlocking {
  43 + await self.service.performLocalSync()
  44 + }
  45 +
  46 + return HealthUploadResult(
  47 + commonUploadSuccess: summary.commonCount >= 0,
  48 + sleepUploadSuccess: summary.sleepCount >= 0,
  49 + errorMessage: nil
  50 + )
  51 + }
  52 +
  53 + private func runAuthorizationRequest() -> (success: Bool, error: Error?) {
  54 + var result: (Bool, Error?) = (false, nil)
  55 + let semaphore = DispatchSemaphore(value: 0)
  56 + service.requestAuthorization { success, error in
  57 + result = (success, error)
  58 + semaphore.signal()
  59 + }
  60 + waitForSemaphore(semaphore)
  61 + return result
  62 + }
  63 +}
  64 +
  65 +private func runBlocking<T>(_ operation: @escaping () async -> T) -> T {
  66 + let semaphore = DispatchSemaphore(value: 0)
  67 + var result: T?
  68 + Task {
  69 + result = await operation()
  70 + semaphore.signal()
  71 + }
  72 + waitForSemaphore(semaphore)
  73 + return result!
  74 +}
  75 +
  76 +private func waitForSemaphore(_ semaphore: DispatchSemaphore) {
  77 + if Thread.isMainThread {
  78 + while semaphore.wait(timeout: .now() + 0.05) == .timedOut {
  79 + RunLoop.main.run(mode: .default, before: Date(timeIntervalSinceNow: 0.05))
  80 + }
  81 + } else {
  82 + semaphore.wait()
  83 + }
  84 +}
1 import Flutter 1 import Flutter
2 import Foundation 2 import Foundation
3 -import PhotosUI  
4 -import UIKit  
5 -import Vision  
6 -  
7 -private let unsupported = "HealthKit / WearEngine / Alipay are not supported on iOS in this build."  
8 -  
9 -final class HealthKitHostApiStub: HealthKitHostApi {  
10 - func checkHealthAppAuthorization() throws -> Bool { false }  
11 - func getHealthServerAuthUrl() throws -> String { "" }  
12 - func requestHealthClientAuthorization() throws -> Bool { false }  
13 - func cancelHealthAppAuthorization() throws -> Bool { false }  
14 - func performHealthUpload() throws -> HealthUploadResult {  
15 - HealthUploadResult(commonUploadSuccess: false, sleepUploadSuccess: false, errorMessage: unsupported)  
16 - }  
17 -}  
18 -  
19 -final class WearEngineHostApiStub: WearEngineHostApi {  
20 - func hasAvailableDevices() throws -> Bool { false }  
21 - func checkConnectedDevice() throws -> WearDeviceInfo? { nil }  
22 - func registerMessageReceiver() throws -> Bool { false }  
23 - func sendTextMessage(message: String) throws -> Bool { false }  
24 - func sendWatchSyncPayload(jsonPayload: String) throws -> Bool { false }  
25 - func pickImageAndRemoveBackground() throws -> String? {  
26 - if #available(iOS 14.0, *) {  
27 - return WatchThemeImagePicker().pickImageAndRemoveBackground()  
28 - }  
29 - return nil  
30 - }  
31 -}  
32 3
33 final class AlipayHostApiStub: AlipayHostApi { 4 final class AlipayHostApiStub: AlipayHostApi {
34 func launchAliPay(prepayData: String) throws -> AliPayResultCode { .unsupported } 5 func launchAliPay(prepayData: String) throws -> AliPayResultCode { .unsupported }
@@ -36,203 +7,10 @@ final class AlipayHostApiStub: AlipayHostApi { @@ -36,203 +7,10 @@ final class AlipayHostApiStub: AlipayHostApi {
36 7
37 enum NativePigeonRegistrar { 8 enum NativePigeonRegistrar {
38 static func register(binaryMessenger: FlutterBinaryMessenger) { 9 static func register(binaryMessenger: FlutterBinaryMessenger) {
39 - HealthKitHostApiSetup.setUp(binaryMessenger: binaryMessenger, api: HealthKitHostApiStub())  
40 - WearEngineHostApiSetup.setUp(binaryMessenger: binaryMessenger, api: WearEngineHostApiStub()) 10 + HealthKitHostApiSetup.setUp(binaryMessenger: binaryMessenger, api: HealthKitHostApiImpl())
  11 + WearEngineHostApiSetup.setUp(binaryMessenger: binaryMessenger, api: WearEngineHostApiImpl())
41 AlipayHostApiSetup.setUp(binaryMessenger: binaryMessenger, api: AlipayHostApiStub()) 12 AlipayHostApiSetup.setUp(binaryMessenger: binaryMessenger, api: AlipayHostApiStub())
42 PlatformHostApiSetup.setUp(binaryMessenger: binaryMessenger, api: PlatformHostApiImpl()) 13 PlatformHostApiSetup.setUp(binaryMessenger: binaryMessenger, api: PlatformHostApiImpl())
43 } 14 }
44 } 15 }
45 16
46 -@available(iOS 14.0, *)  
47 -private final class WatchThemeImagePicker: NSObject, PHPickerViewControllerDelegate {  
48 - private var continuation: CheckedContinuation<String?, Never>?  
49 -  
50 - func pickImageAndRemoveBackground() -> String? {  
51 - if Thread.isMainThread {  
52 - return runOnMain()  
53 - }  
54 -  
55 - var result: String?  
56 - let semaphore = DispatchSemaphore(value: 0)  
57 - DispatchQueue.main.async {  
58 - result = self.runOnMain()  
59 - semaphore.signal()  
60 - }  
61 - semaphore.wait()  
62 - return result  
63 - }  
64 -  
65 - private func runOnMain() -> String? {  
66 - var configuration = PHPickerConfiguration(photoLibrary: .shared())  
67 - configuration.filter = .images  
68 - configuration.selectionLimit = 1  
69 -  
70 - guard let presenter = UIApplication.shared.topMostViewController else {  
71 - return nil  
72 - }  
73 -  
74 - let picker = PHPickerViewController(configuration: configuration)  
75 - picker.delegate = self  
76 -  
77 - return waitForPickerResult(picker: picker, presenter: presenter)  
78 - }  
79 -  
80 - private func waitForPickerResult(  
81 - picker: PHPickerViewController,  
82 - presenter: UIViewController  
83 - ) -> String? {  
84 - var pickedPath: String?  
85 - let semaphore = DispatchSemaphore(value: 0)  
86 -  
87 - Task { @MainActor in  
88 - pickedPath = await withCheckedContinuation { continuation in  
89 - self.continuation = continuation  
90 - presenter.present(picker, animated: true)  
91 - }  
92 - semaphore.signal()  
93 - }  
94 -  
95 - while semaphore.wait(timeout: .now() + 0.05) == .timedOut {  
96 - RunLoop.main.run(mode: .default, before: Date(timeIntervalSinceNow: 0.05))  
97 - }  
98 - return pickedPath  
99 - }  
100 -  
101 - nonisolated func picker(  
102 - _ picker: PHPickerViewController,  
103 - didFinishPicking results: [PHPickerResult]  
104 - ) {  
105 - Task { @MainActor in  
106 - picker.dismiss(animated: true)  
107 -  
108 - guard let provider = results.first?.itemProvider,  
109 - provider.canLoadObject(ofClass: UIImage.self) else {  
110 - continuation?.resume(returning: nil)  
111 - continuation = nil  
112 - return  
113 - }  
114 -  
115 - provider.loadObject(ofClass: UIImage.self) { object, _ in  
116 - Task { @MainActor in  
117 - guard let image = object as? UIImage else {  
118 - self.continuation?.resume(returning: nil)  
119 - self.continuation = nil  
120 - return  
121 - }  
122 - let processed = await WatchThemeImageProcessor.removeBackground(from: image)  
123 - let path = WatchThemeImageProcessor.savePNG(processed)  
124 - self.continuation?.resume(returning: path)  
125 - self.continuation = nil  
126 - }  
127 - }  
128 - }  
129 - }  
130 -}  
131 -  
132 -private enum WatchThemeImageProcessor {  
133 - static func removeBackground(from image: UIImage) async -> UIImage {  
134 - guard #available(iOS 17.0, *),  
135 - let cgImage = image.normalizedCGImage else {  
136 - return image  
137 - }  
138 -  
139 - return await Task.detached(priority: .userInitiated) {  
140 - let request = VNGenerateForegroundInstanceMaskRequest()  
141 - let handler = VNImageRequestHandler(cgImage: cgImage)  
142 -  
143 - do {  
144 - try handler.perform([request])  
145 - guard let observation = request.results?.first else {  
146 - return image  
147 - }  
148 -  
149 - let mask = try observation.generateScaledMaskForImage(  
150 - forInstances: observation.allInstances,  
151 - from: handler  
152 - )  
153 - return composite(image: cgImage, mask: mask) ?? image  
154 - } catch {  
155 - return image  
156 - }  
157 - }.value  
158 - }  
159 -  
160 - static func savePNG(_ image: UIImage) -> String? {  
161 - guard let data = image.pngData() else { return nil }  
162 - let directory = FileManager.default.temporaryDirectory  
163 - .appendingPathComponent("watch_theme", isDirectory: true)  
164 -  
165 - do {  
166 - try FileManager.default.createDirectory(  
167 - at: directory,  
168 - withIntermediateDirectories: true  
169 - )  
170 - let file = directory.appendingPathComponent("\(UUID().uuidString).png")  
171 - try data.write(to: file, options: .atomic)  
172 - return file.path  
173 - } catch {  
174 - return nil  
175 - }  
176 - }  
177 -  
178 - private static func composite(image: CGImage, mask: CVPixelBuffer) -> UIImage? {  
179 - let ciImage = CIImage(cgImage: image)  
180 - let ciMask = CIImage(cvPixelBuffer: mask)  
181 - guard let filter = CIFilter(name: "CIBlendWithMask") else {  
182 - return nil  
183 - }  
184 - filter.setValue(ciImage, forKey: kCIInputImageKey)  
185 - filter.setValue(ciMask, forKey: kCIInputMaskImageKey)  
186 - filter.setValue(  
187 - CIImage(color: .clear).cropped(to: ciImage.extent),  
188 - forKey: kCIInputBackgroundImageKey  
189 - )  
190 -  
191 - guard let output = filter.outputImage,  
192 - let cgOutput = CIContext().createCGImage(output, from: ciImage.extent) else {  
193 - return nil  
194 - }  
195 - return UIImage(cgImage: cgOutput, scale: 1, orientation: .up)  
196 - }  
197 -}  
198 -  
199 -private extension UIImage {  
200 - var normalizedCGImage: CGImage? {  
201 - if imageOrientation == .up, let cgImage {  
202 - return cgImage  
203 - }  
204 -  
205 - let format = UIGraphicsImageRendererFormat.default()  
206 - format.scale = scale  
207 - let renderer = UIGraphicsImageRenderer(size: size, format: format)  
208 - return renderer.image { _ in  
209 - draw(in: CGRect(origin: .zero, size: size))  
210 - }.cgImage  
211 - }  
212 -}  
213 -  
214 -private extension UIApplication {  
215 - var topMostViewController: UIViewController? {  
216 - connectedScenes  
217 - .compactMap { $0 as? UIWindowScene }  
218 - .flatMap(\.windows)  
219 - .first { $0.isKeyWindow }?  
220 - .rootViewController?  
221 - .topMostPresented  
222 - }  
223 -}  
224 -  
225 -private extension UIViewController {  
226 - var topMostPresented: UIViewController {  
227 - if let presentedViewController {  
228 - return presentedViewController.topMostPresented  
229 - }  
230 - if let navigationController = self as? UINavigationController {  
231 - return navigationController.visibleViewController?.topMostPresented ?? navigationController  
232 - }  
233 - if let tabBarController = self as? UITabBarController {  
234 - return tabBarController.selectedViewController?.topMostPresented ?? tabBarController  
235 - }  
236 - return self  
237 - }  
238 -}  
  1 +import Foundation
  2 +import PhotosUI
  3 +import UIKit
  4 +import Vision
  5 +
  6 +final class WearEngineHostApiImpl: WearEngineHostApi {
  7 + private let watchService: WatchConnectivityService
  8 +
  9 + init(watchService: WatchConnectivityService = .shared) {
  10 + self.watchService = watchService
  11 + }
  12 +
  13 + func hasAvailableDevices() throws -> Bool {
  14 + watchService.hasAvailableDevices()
  15 + }
  16 +
  17 + func checkConnectedDevice() throws -> WearDeviceInfo? {
  18 + watchService.currentDeviceInfo()
  19 + }
  20 +
  21 + func registerMessageReceiver() throws -> Bool {
  22 + watchService.activate()
  23 + }
  24 +
  25 + func sendTextMessage(message: String) throws -> Bool {
  26 + watchService.sendTextMessage(message)
  27 + }
  28 +
  29 + func sendWatchSyncPayload(jsonPayload: String) throws -> Bool {
  30 + watchService.syncPayload(jsonPayload: jsonPayload)
  31 + }
  32 +
  33 + func pickImageAndRemoveBackground() throws -> String? {
  34 + if #available(iOS 14.0, *) {
  35 + return WatchThemeImagePicker().pickImageAndRemoveBackground()
  36 + }
  37 + return nil
  38 + }
  39 +}
  40 +
  41 +@available(iOS 14.0, *)
  42 +private final class WatchThemeImagePicker: NSObject, PHPickerViewControllerDelegate {
  43 + private var continuation: CheckedContinuation<String?, Never>?
  44 +
  45 + func pickImageAndRemoveBackground() -> String? {
  46 + if Thread.isMainThread {
  47 + return runOnMain()
  48 + }
  49 +
  50 + var result: String?
  51 + let semaphore = DispatchSemaphore(value: 0)
  52 + DispatchQueue.main.async {
  53 + result = self.runOnMain()
  54 + semaphore.signal()
  55 + }
  56 + semaphore.wait()
  57 + return result
  58 + }
  59 +
  60 + private func runOnMain() -> String? {
  61 + var configuration = PHPickerConfiguration(photoLibrary: .shared())
  62 + configuration.filter = .images
  63 + configuration.selectionLimit = 1
  64 +
  65 + guard let presenter = UIApplication.shared.topMostViewController else {
  66 + return nil
  67 + }
  68 +
  69 + let picker = PHPickerViewController(configuration: configuration)
  70 + picker.delegate = self
  71 +
  72 + return waitForPickerResult(picker: picker, presenter: presenter)
  73 + }
  74 +
  75 + private func waitForPickerResult(
  76 + picker: PHPickerViewController,
  77 + presenter: UIViewController
  78 + ) -> String? {
  79 + var pickedPath: String?
  80 + let semaphore = DispatchSemaphore(value: 0)
  81 +
  82 + Task { @MainActor in
  83 + pickedPath = await withCheckedContinuation { continuation in
  84 + self.continuation = continuation
  85 + presenter.present(picker, animated: true)
  86 + }
  87 + semaphore.signal()
  88 + }
  89 +
  90 + while semaphore.wait(timeout: .now() + 0.05) == .timedOut {
  91 + RunLoop.main.run(mode: .default, before: Date(timeIntervalSinceNow: 0.05))
  92 + }
  93 + return pickedPath
  94 + }
  95 +
  96 + nonisolated func picker(
  97 + _ picker: PHPickerViewController,
  98 + didFinishPicking results: [PHPickerResult]
  99 + ) {
  100 + Task { @MainActor in
  101 + picker.dismiss(animated: true)
  102 +
  103 + guard let provider = results.first?.itemProvider,
  104 + provider.canLoadObject(ofClass: UIImage.self) else {
  105 + continuation?.resume(returning: nil)
  106 + continuation = nil
  107 + return
  108 + }
  109 +
  110 + provider.loadObject(ofClass: UIImage.self) { object, _ in
  111 + Task { @MainActor in
  112 + guard let image = object as? UIImage else {
  113 + self.continuation?.resume(returning: nil)
  114 + self.continuation = nil
  115 + return
  116 + }
  117 + let processed = await WatchThemeImageProcessor.removeBackground(from: image)
  118 + let path = WatchThemeImageProcessor.savePNG(processed)
  119 + self.continuation?.resume(returning: path)
  120 + self.continuation = nil
  121 + }
  122 + }
  123 + }
  124 + }
  125 +}
  126 +
  127 +private enum WatchThemeImageProcessor {
  128 + static func removeBackground(from image: UIImage) async -> UIImage {
  129 + guard #available(iOS 17.0, *),
  130 + let cgImage = image.normalizedCGImage else {
  131 + return image
  132 + }
  133 +
  134 + return await Task.detached(priority: .userInitiated) {
  135 + let request = VNGenerateForegroundInstanceMaskRequest()
  136 + let handler = VNImageRequestHandler(cgImage: cgImage)
  137 +
  138 + do {
  139 + try handler.perform([request])
  140 + guard let observation = request.results?.first else {
  141 + return image
  142 + }
  143 +
  144 + let mask = try observation.generateScaledMaskForImage(
  145 + forInstances: observation.allInstances,
  146 + from: handler
  147 + )
  148 + return composite(image: cgImage, mask: mask) ?? image
  149 + } catch {
  150 + return image
  151 + }
  152 + }.value
  153 + }
  154 +
  155 + static func savePNG(_ image: UIImage) -> String? {
  156 + guard let data = image.pngData() else { return nil }
  157 + let directory = FileManager.default.temporaryDirectory
  158 + .appendingPathComponent("watch_theme", isDirectory: true)
  159 +
  160 + do {
  161 + try FileManager.default.createDirectory(
  162 + at: directory,
  163 + withIntermediateDirectories: true
  164 + )
  165 + let file = directory.appendingPathComponent("\(UUID().uuidString).png")
  166 + try data.write(to: file, options: .atomic)
  167 + return file.path
  168 + } catch {
  169 + return nil
  170 + }
  171 + }
  172 +
  173 + private static func composite(image: CGImage, mask: CVPixelBuffer) -> UIImage? {
  174 + let ciImage = CIImage(cgImage: image)
  175 + let ciMask = CIImage(cvPixelBuffer: mask)
  176 + guard let filter = CIFilter(name: "CIBlendWithMask") else {
  177 + return nil
  178 + }
  179 + filter.setValue(ciImage, forKey: kCIInputImageKey)
  180 + filter.setValue(ciMask, forKey: kCIInputMaskImageKey)
  181 + filter.setValue(
  182 + CIImage(color: .clear).cropped(to: ciImage.extent),
  183 + forKey: kCIInputBackgroundImageKey
  184 + )
  185 +
  186 + guard let output = filter.outputImage,
  187 + let cgOutput = CIContext().createCGImage(output, from: ciImage.extent) else {
  188 + return nil
  189 + }
  190 + return UIImage(cgImage: cgOutput, scale: 1, orientation: .up)
  191 + }
  192 +}
  193 +
  194 +private extension UIImage {
  195 + var normalizedCGImage: CGImage? {
  196 + if imageOrientation == .up, let cgImage {
  197 + return cgImage
  198 + }
  199 +
  200 + let format = UIGraphicsImageRendererFormat.default()
  201 + format.scale = scale
  202 + let renderer = UIGraphicsImageRenderer(size: size, format: format)
  203 + return renderer.image { _ in
  204 + draw(in: CGRect(origin: .zero, size: size))
  205 + }.cgImage
  206 + }
  207 +}
  208 +
  209 +private extension UIApplication {
  210 + var topMostViewController: UIViewController? {
  211 + connectedScenes
  212 + .compactMap { $0 as? UIWindowScene }
  213 + .flatMap(\.windows)
  214 + .first { $0.isKeyWindow }?
  215 + .rootViewController?
  216 + .topMostPresented
  217 + }
  218 +}
  219 +
  220 +private extension UIViewController {
  221 + var topMostPresented: UIViewController {
  222 + if let presentedViewController {
  223 + return presentedViewController.topMostPresented
  224 + }
  225 + if let navigationController = self as? UINavigationController {
  226 + return navigationController.visibleViewController?.topMostPresented ?? navigationController
  227 + }
  228 + if let tabBarController = self as? UITabBarController {
  229 + return tabBarController.selectedViewController?.topMostPresented ?? tabBarController
  230 + }
  231 + return self
  232 + }
  233 +}
  234 +
@@ -8,6 +8,10 @@ @@ -8,6 +8,10 @@
8 <true/> 8 <true/>
9 <key>com.apple.developer.healthkit.background-delivery</key> 9 <key>com.apple.developer.healthkit.background-delivery</key>
10 <true/> 10 <true/>
  11 + <key>com.apple.security.application-groups</key>
  12 + <array>
  13 + <string>group.com.luiz.doublefeel.watchkitapp</string>
  14 + </array>
11 <key>com.apple.security.cs.allow-jit</key> 15 <key>com.apple.security.cs.allow-jit</key>
12 <true/> 16 <true/>
13 <key>com.apple.security.cs.allow-unsigned-executable-memory</key> 17 <key>com.apple.security.cs.allow-unsigned-executable-memory</key>
@@ -8,5 +8,9 @@ @@ -8,5 +8,9 @@
8 <true/> 8 <true/>
9 <key>com.apple.developer.healthkit.background-delivery</key> 9 <key>com.apple.developer.healthkit.background-delivery</key>
10 <true/> 10 <true/>
  11 + <key>com.apple.security.application-groups</key>
  12 + <array>
  13 + <string>group.com.luiz.doublefeel.watchkitapp</string>
  14 + </array>
11 </dict> 15 </dict>
12 </plist> 16 </plist>
  1 +import Foundation
  2 +
  3 +/// Shared container used by the iPhone app, Watch app, and Widget extension.
  4 +/// Keep these keys aligned with `ios/Runner Watch App` and the watch extension.
  5 +enum AppGroupConstants {
  6 + static let identifier = "group.com.luiz.doublefeel.watchkitapp"
  7 +
  8 + enum Key {
  9 + static let latestHRV = "latestHRV"
  10 + static let latestHRVBaseline = "latestHRVBaseline"
  11 + static let latestStepCount = "latestStepCount"
  12 + static let myWatchTheme = "myWatchTheme"
  13 + static let otherWatchTheme = "otherWatchTheme"
  14 + static let myUserCharacter = "myUserCharacter"
  15 + }
  16 +
  17 + static var defaults: UserDefaults? {
  18 + UserDefaults(suiteName: identifier)
  19 + }
  20 +}
  21 +
  1 +import Foundation
  2 +import UIKit
  3 +import WatchConnectivity
  4 +
  5 +/// iPhone-side WatchConnectivity wrapper.
  6 +/// This keeps Flutter-facing WearEngine APIs mapped to Apple Watch behavior.
  7 +final class WatchConnectivityService: NSObject {
  8 + static let shared = WatchConnectivityService()
  9 +
  10 + private(set) var isPaired = false
  11 + private(set) var isReachable = false
  12 + private(set) var isWatchAppInstalled = false
  13 +
  14 + private override init() {
  15 + super.init()
  16 + }
  17 +
  18 + @discardableResult
  19 + func activate() -> Bool {
  20 + guard WCSession.isSupported() else { return false }
  21 + let session = WCSession.default
  22 + session.delegate = self
  23 + session.activate()
  24 + refreshState()
  25 + return true
  26 + }
  27 +
  28 + func refreshState() {
  29 + guard WCSession.isSupported() else {
  30 + isPaired = false
  31 + isReachable = false
  32 + isWatchAppInstalled = false
  33 + return
  34 + }
  35 + let session = WCSession.default
  36 + isPaired = session.isPaired
  37 + isReachable = session.isReachable
  38 + isWatchAppInstalled = session.isWatchAppInstalled
  39 + }
  40 +
  41 + func hasAvailableDevices() -> Bool {
  42 + activate()
  43 + refreshState()
  44 + return isPaired && isWatchAppInstalled
  45 + }
  46 +
  47 + func currentDeviceInfo() -> WearDeviceInfo? {
  48 + activate()
  49 + refreshState()
  50 + guard isPaired else { return nil }
  51 + return WearDeviceInfo(
  52 + deviceId: nil,
  53 + deviceName: "Apple Watch",
  54 + isConnected: isReachable && isWatchAppInstalled
  55 + )
  56 + }
  57 +
  58 + func sendTextMessage(_ message: String) -> Bool {
  59 + activate()
  60 + guard WCSession.default.isReachable else { return false }
  61 + WCSession.default.sendMessage(["message": message], replyHandler: nil) { error in
  62 + print("Watch message failed: \(error.localizedDescription)")
  63 + }
  64 + return true
  65 + }
  66 +
  67 + func syncPayload(jsonPayload: String) -> Bool {
  68 + activate()
  69 + guard let data = jsonPayload.data(using: .utf8),
  70 + let object = try? JSONSerialization.jsonObject(with: data),
  71 + let payload = object as? [String: Any] else {
  72 + return false
  73 + }
  74 +
  75 + persistThemeIfPresent(payload: payload, originalJSON: jsonPayload)
  76 +
  77 + guard WCSession.isSupported(), WCSession.default.isPaired, WCSession.default.isWatchAppInstalled else {
  78 + return false
  79 + }
  80 +
  81 + WCSession.default.transferUserInfo(payload)
  82 + try? WCSession.default.updateApplicationContext(payload)
  83 + sendWatchThemeChangedMessageIfNeeded(payload: payload)
  84 + return true
  85 + }
  86 +
  87 + func sendWatchThemeChangedMessage() {
  88 + activate()
  89 + guard WCSession.default.isReachable else { return }
  90 + WCSession.default.sendMessage(["command": "watchThemeChanged"], replyHandler: nil) { error in
  91 + print("Watch theme change message failed: \(error.localizedDescription)")
  92 + }
  93 + }
  94 +
  95 + private func sendWatchThemeChangedMessageIfNeeded(payload: [String: Any]) {
  96 + if payload["myWatchTheme"] != nil || payload["watchTheme"] != nil || payload["theme"] != nil {
  97 + sendWatchThemeChangedMessage()
  98 + }
  99 + }
  100 +
  101 + private func persistThemeIfPresent(payload: [String: Any], originalJSON: String) {
  102 + if let theme = payload["myWatchTheme"] as? String {
  103 + WatchThemeStore.shared.saveThemeJSONString(theme)
  104 + return
  105 + }
  106 +
  107 + let themeObject = payload["watchTheme"] ?? payload["theme"]
  108 + guard let themeObject,
  109 + JSONSerialization.isValidJSONObject(themeObject),
  110 + let data = try? JSONSerialization.data(withJSONObject: themeObject),
  111 + let json = String(data: data, encoding: .utf8) else {
  112 + if payload["isWatchTheme"] as? Bool == true {
  113 + WatchThemeStore.shared.saveThemeJSONString(originalJSON)
  114 + }
  115 + return
  116 + }
  117 + WatchThemeStore.shared.saveThemeJSONString(json)
  118 + }
  119 +}
  120 +
  121 +extension WatchConnectivityService: WCSessionDelegate {
  122 + func session(
  123 + _ session: WCSession,
  124 + activationDidCompleteWith activationState: WCSessionActivationState,
  125 + error: Error?
  126 + ) {
  127 + refreshState()
  128 + if let error {
  129 + print("WatchConnectivity activation failed: \(error.localizedDescription)")
  130 + }
  131 + }
  132 +
  133 + func sessionDidBecomeInactive(_ session: WCSession) {
  134 + refreshState()
  135 + }
  136 +
  137 + func sessionDidDeactivate(_ session: WCSession) {
  138 + refreshState()
  139 + session.activate()
  140 + }
  141 +
  142 + func sessionReachabilityDidChange(_ session: WCSession) {
  143 + refreshState()
  144 + }
  145 +
  146 + func session(_ session: WCSession, didReceiveMessage message: [String: Any]) {
  147 + if message["command"] as? String == "statusPulseRefresh" {
  148 + Task {
  149 + await HealthKitService.shared.refreshSharedWatchValues()
  150 + }
  151 + }
  152 + }
  153 +
  154 + func session(
  155 + _ session: WCSession,
  156 + didReceiveMessage message: [String: Any],
  157 + replyHandler: @escaping ([String: Any]) -> Void
  158 + ) {
  159 + if message["command"] as? String == "statusPulseRefresh" {
  160 + Task {
  161 + await HealthKitService.shared.refreshSharedWatchValues()
  162 + replyHandler(["success": true])
  163 + }
  164 + } else {
  165 + replyHandler(["success": true])
  166 + }
  167 + }
  168 +}
  169 +
  1 +import Foundation
  2 +
  3 +/// Shared Watch theme persistence.
  4 +/// The Watch app and Widget extension read this exact JSON string from App Group.
  5 +final class WatchThemeStore {
  6 + static let shared = WatchThemeStore()
  7 +
  8 + private init() {}
  9 +
  10 + @discardableResult
  11 + func saveThemeJSONString(_ json: String) -> Bool {
  12 + guard json.data(using: .utf8) != nil else { return false }
  13 + AppGroupConstants.defaults?.set(json, forKey: AppGroupConstants.Key.myWatchTheme)
  14 + return true
  15 + }
  16 +
  17 + func clearTheme() {
  18 + AppGroupConstants.defaults?.removeObject(forKey: AppGroupConstants.Key.myWatchTheme)
  19 + }
  20 +}
  21 +
1 -c134254776a5ccd144c8a5e627d78c10  
1 -{"buildConfigurations":[{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e98e8fb97e4d8fc6b27d73383f393c88ecd","buildSettings":{"CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/TOCropViewController","EXPANDED_CODE_SIGN_IDENTITY":"-","IBSC_MODULE":"TOCropViewController","INFOPLIST_FILE":"Target Support Files/TOCropViewController/ResourceBundle-TOCropViewControllerBundle-TOCropViewController-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"11.0","ONLY_ACTIVE_ARCH":"NO","PRODUCT_NAME":"TOCropViewControllerBundle","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e98b75d1048f68d3bb5985c770bd41c3964","name":"Debug"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e98646a08d73cb1b05edde4b2af727d2773","buildSettings":{"CLANG_ENABLE_OBJC_WEAK":"NO","CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/TOCropViewController","EXPANDED_CODE_SIGN_IDENTITY":"-","IBSC_MODULE":"TOCropViewController","INFOPLIST_FILE":"Target Support Files/TOCropViewController/ResourceBundle-TOCropViewControllerBundle-TOCropViewController-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"11.0","PRODUCT_NAME":"TOCropViewControllerBundle","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","VALIDATE_PRODUCT":"YES","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e98e9947f3bc60a9a376173a132421b2278","name":"Profile"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e98646a08d73cb1b05edde4b2af727d2773","buildSettings":{"CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/TOCropViewController","EXPANDED_CODE_SIGN_IDENTITY":"-","IBSC_MODULE":"TOCropViewController","INFOPLIST_FILE":"Target Support Files/TOCropViewController/ResourceBundle-TOCropViewControllerBundle-TOCropViewController-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"11.0","PRODUCT_NAME":"TOCropViewControllerBundle","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e983751bd601c66cda9f4c7c8b8aed619ef","name":"Release"}],"buildPhases":[{"buildFiles":[],"guid":"bfdfe7dc352907fc980b868725387e98c2917c5d20bcd9c007f37af8611de2a6","type":"com.apple.buildphase.sources"},{"buildFiles":[],"guid":"bfdfe7dc352907fc980b868725387e986afffa2cfd2f9512aa233f5cc63fb570","type":"com.apple.buildphase.frameworks"},{"buildFiles":[{"fileReference":"bfdfe7dc352907fc980b868725387e98b3f0c66e128d272bb1288ea8780dc9b4","guid":"bfdfe7dc352907fc980b868725387e9803b9b1af2d5261479f7f93af035f84ad"},{"fileReference":"bfdfe7dc352907fc980b868725387e98943d94e1dca9370afcbc7d2e9f0abbad","guid":"bfdfe7dc352907fc980b868725387e98437b8113d0c0f7efa46ee29b722c79cb"},{"fileReference":"bfdfe7dc352907fc980b868725387e98e20d522eae8962c5e533c7c249450ba1","guid":"bfdfe7dc352907fc980b868725387e9895e3b6c1100dde567d8298da959ab892"},{"fileReference":"bfdfe7dc352907fc980b868725387e9875b23b6d8bdbfaadd15a183140d79f69","guid":"bfdfe7dc352907fc980b868725387e984f33ed908452ea332941903c0411b3ef"},{"fileReference":"bfdfe7dc352907fc980b868725387e98e0f2b7de1c1bc04e1ffe46c68ce33ad8","guid":"bfdfe7dc352907fc980b868725387e9826d2fa37af38d4d77992079be9e49bbe"},{"fileReference":"bfdfe7dc352907fc980b868725387e987b5a1086ea8be4d9b051d3ce7999d172","guid":"bfdfe7dc352907fc980b868725387e98c047cfdc484f9f46ed24109dd7964cab"},{"fileReference":"bfdfe7dc352907fc980b868725387e98d2785ef910e4b678590a3f07d27b2b26","guid":"bfdfe7dc352907fc980b868725387e98f17441845b3284079bd0a8af3efb9a94"},{"fileReference":"bfdfe7dc352907fc980b868725387e98436252fbeeed3265eb2cee95eb12a14a","guid":"bfdfe7dc352907fc980b868725387e9853a0872068d9802e4e7ef5e78684536a"},{"fileReference":"bfdfe7dc352907fc980b868725387e98a143bbb2156d53dcb475bf3467818a00","guid":"bfdfe7dc352907fc980b868725387e98cd6cb21ecbed9ef5249db5427b34f309"},{"fileReference":"bfdfe7dc352907fc980b868725387e989326c93489133be54ec1c5ce883f7f95","guid":"bfdfe7dc352907fc980b868725387e987086f18c8f04746040ad04d1495e5987"},{"fileReference":"bfdfe7dc352907fc980b868725387e98ab86e2bc0e96a3e47efb5fb4938bd05b","guid":"bfdfe7dc352907fc980b868725387e98deb061d220cf256291574c978433b9bd"},{"fileReference":"bfdfe7dc352907fc980b868725387e9899763c221a73e8f5860bb7297c2ecadf","guid":"bfdfe7dc352907fc980b868725387e98fb2ce2a54d4830268408f0da53955eb2"},{"fileReference":"bfdfe7dc352907fc980b868725387e984a55026799f54413f94c8d617bcee1bc","guid":"bfdfe7dc352907fc980b868725387e98dde0ca6b9e6a722f948c8fad38c22a95"},{"fileReference":"bfdfe7dc352907fc980b868725387e98f458e319d28f436491479bf5bc69bee4","guid":"bfdfe7dc352907fc980b868725387e982d460c5e8f6550cbc140db774b40752f"},{"fileReference":"bfdfe7dc352907fc980b868725387e9871360fc12faa4a6a46c3a5000eb78525","guid":"bfdfe7dc352907fc980b868725387e9827c4023f7130ab90afc00f1434340393"},{"fileReference":"bfdfe7dc352907fc980b868725387e980aa48715923cc7d3226a6daf26d515a7","guid":"bfdfe7dc352907fc980b868725387e981c750fb4de8e6f8f5bd31359a47e1e42"},{"fileReference":"bfdfe7dc352907fc980b868725387e98fea9ee4c790269b2b255fbda65d21cd5","guid":"bfdfe7dc352907fc980b868725387e980b4535c2eb5efe032efcd7ea90b8a666"},{"fileReference":"bfdfe7dc352907fc980b868725387e98aaded417427f59091e2272bec6813a42","guid":"bfdfe7dc352907fc980b868725387e980ba4c57bb4bd7bdcd21c04570f5a2e1f"},{"fileReference":"bfdfe7dc352907fc980b868725387e98f350348517c2cecb7d07354784c3bbc9","guid":"bfdfe7dc352907fc980b868725387e9811adc361209945de86a86b7fa1d7c3f8"},{"fileReference":"bfdfe7dc352907fc980b868725387e98a7ea5aa63b71073b08e7b415f74ed663","guid":"bfdfe7dc352907fc980b868725387e98492985e800f2423459efcfef10270692"},{"fileReference":"bfdfe7dc352907fc980b868725387e98247133e54555136c6e141473046f7e08","guid":"bfdfe7dc352907fc980b868725387e983b073fd21e782463067704b20c7aecb4"},{"fileReference":"bfdfe7dc352907fc980b868725387e9852f6cd5cdac1d0f84fae787b09c92c74","guid":"bfdfe7dc352907fc980b868725387e988c218a129ee9337c6f4c9fc9c31651bf"},{"fileReference":"bfdfe7dc352907fc980b868725387e98683dc56e238d9ccd0a2cd3b2d7b2e363","guid":"bfdfe7dc352907fc980b868725387e98a48f6a439944fbae7cbacffb33bb0a8f"},{"fileReference":"bfdfe7dc352907fc980b868725387e9845f0c14bbe37bdcf2d4d3c5941ee46f5","guid":"bfdfe7dc352907fc980b868725387e98d607d60302022bf876d39aa1bd69cdf0"},{"fileReference":"bfdfe7dc352907fc980b868725387e982672050c2030427d057debb1ea0c3df9","guid":"bfdfe7dc352907fc980b868725387e9849687d7ad52891093076ae6016a26da4"},{"fileReference":"bfdfe7dc352907fc980b868725387e98f474de454e032ecc10c533fc7fe161f0","guid":"bfdfe7dc352907fc980b868725387e982151f9e4c972b8a27c807903709a5cdd"},{"fileReference":"bfdfe7dc352907fc980b868725387e98a67747b5a77b0d264643563f3e216e7c","guid":"bfdfe7dc352907fc980b868725387e981e9f0720b7996cbbc5d1fed40f0912af"},{"fileReference":"bfdfe7dc352907fc980b868725387e986721d9a64a6948ad719ee0ca618d0d98","guid":"bfdfe7dc352907fc980b868725387e98daf88f1e9c8b88debe0db8a5a7ca7fc3"},{"fileReference":"bfdfe7dc352907fc980b868725387e98917e258ffc6052c99dbd63f347526ff6","guid":"bfdfe7dc352907fc980b868725387e98af9dace882a7c96a865bcef174d45792"},{"fileReference":"bfdfe7dc352907fc980b868725387e9814511951012b4191c2433d5a379eb9a1","guid":"bfdfe7dc352907fc980b868725387e9802f8dba89062e5de6c4c276fd7aa8b36"},{"fileReference":"bfdfe7dc352907fc980b868725387e987f3b32d8f963147c42e467390e392744","guid":"bfdfe7dc352907fc980b868725387e98b89ee2bf44b66263aa19e3fe8e7ae16a"}],"guid":"bfdfe7dc352907fc980b868725387e98311b3e21fcbc0f104d22472972191841","type":"com.apple.buildphase.resources"}],"buildRules":[],"dependencies":[],"guid":"bfdfe7dc352907fc980b868725387e986dbfa2df59ddcae0f992dedaee8f3553","name":"TOCropViewController-TOCropViewControllerBundle","productReference":{"guid":"bfdfe7dc352907fc980b868725387e980e69b2358d36eb6c2616a1dbbe45f585","name":"TOCropViewControllerBundle.bundle","type":"product"},"productTypeIdentifier":"com.apple.product-type.bundle","provisioningSourceData":[{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Debug","provisioningStyle":0},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Profile","provisioningStyle":0},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Release","provisioningStyle":0}],"type":"standard"}  
1 -{"buildConfigurations":[{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e9872c3a102c2f55c6f0eee5833107fac63","buildSettings":{"CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/sqflite_darwin","EXPANDED_CODE_SIGN_IDENTITY":"-","IBSC_MODULE":"sqflite_darwin","INFOPLIST_FILE":"Target Support Files/sqflite_darwin/ResourceBundle-sqflite_darwin_privacy-sqflite_darwin-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"12.0","ONLY_ACTIVE_ARCH":"NO","PRODUCT_NAME":"sqflite_darwin_privacy","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e98c19358e0d8fc0ff82ae574564065ed6b","name":"Debug"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e98d1a455bf7417c3aeb645db18ef108a94","buildSettings":{"CLANG_ENABLE_OBJC_WEAK":"NO","CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/sqflite_darwin","EXPANDED_CODE_SIGN_IDENTITY":"-","IBSC_MODULE":"sqflite_darwin","INFOPLIST_FILE":"Target Support Files/sqflite_darwin/ResourceBundle-sqflite_darwin_privacy-sqflite_darwin-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"12.0","PRODUCT_NAME":"sqflite_darwin_privacy","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","VALIDATE_PRODUCT":"YES","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e98afb87e3af52050c61b6e42f9c8a3883b","name":"Profile"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e98d1a455bf7417c3aeb645db18ef108a94","buildSettings":{"CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/sqflite_darwin","EXPANDED_CODE_SIGN_IDENTITY":"-","IBSC_MODULE":"sqflite_darwin","INFOPLIST_FILE":"Target Support Files/sqflite_darwin/ResourceBundle-sqflite_darwin_privacy-sqflite_darwin-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"12.0","PRODUCT_NAME":"sqflite_darwin_privacy","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e98e4f2c507ffb311a50a95aa349d7e88ed","name":"Release"}],"buildPhases":[{"buildFiles":[],"guid":"bfdfe7dc352907fc980b868725387e98ac7d823da02db5d40c302ec94ea301a3","type":"com.apple.buildphase.sources"},{"buildFiles":[],"guid":"bfdfe7dc352907fc980b868725387e980633102ccc15b88a476e0ed7ba1ff323","type":"com.apple.buildphase.frameworks"},{"buildFiles":[{"fileReference":"bfdfe7dc352907fc980b868725387e98d815319f529deb57d9d10e32525da1ef","guid":"bfdfe7dc352907fc980b868725387e988dcb3837b0f66cc15fcbb54ada836554"}],"guid":"bfdfe7dc352907fc980b868725387e98451cbac7e109149bf793647b9c462224","type":"com.apple.buildphase.resources"}],"buildRules":[],"dependencies":[],"guid":"bfdfe7dc352907fc980b868725387e9883134bb5f399cb37a1eb075d4fea30d8","name":"sqflite_darwin-sqflite_darwin_privacy","productReference":{"guid":"bfdfe7dc352907fc980b868725387e9849c1d4b1200fcbf6f387f94121c7d0bf","name":"sqflite_darwin_privacy.bundle","type":"product"},"productTypeIdentifier":"com.apple.product-type.bundle","provisioningSourceData":[{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Debug","provisioningStyle":0},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Profile","provisioningStyle":0},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Release","provisioningStyle":0}],"type":"standard"}  
1 -{"buildConfigurations":[{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e98493610a1174f3f4f738833de56d1328f","buildSettings":{"CLANG_ENABLE_OBJC_WEAK":"NO","CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER":"NO","CODE_SIGN_IDENTITY[sdk=appletvos*]":"","CODE_SIGN_IDENTITY[sdk=iphoneos*]":"","CODE_SIGN_IDENTITY[sdk=watchos*]":"","CURRENT_PROJECT_VERSION":"1","DYLIB_COMPATIBILITY_VERSION":"1","DYLIB_CURRENT_VERSION":"1","DYLIB_INSTALL_NAME_BASE":"@rpath","ENABLE_BITCODE":"NO","ENABLE_MODULE_VERIFIER":"NO","ENABLE_USER_SCRIPT_SANDBOXING":"NO","EXCLUDED_ARCHS[sdk=iphoneos*]":"$(inherited) armv7","EXCLUDED_ARCHS[sdk=iphonesimulator*]":"$(inherited) i386","FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios/Flutter.xcframework/ios-arm64\" $(inherited)","FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios/Flutter.xcframework/ios-arm64_x86_64-simulator\" $(inherited)","GCC_PREFIX_HEADER":"Target Support Files/webview_flutter_wkwebview/webview_flutter_wkwebview-prefix.pch","GENERATE_INFOPLIST_FILE":"NO","INFOPLIST_FILE":"Target Support Files/webview_flutter_wkwebview/webview_flutter_wkwebview-Info.plist","INSTALL_PATH":"$(LOCAL_LIBRARY_DIR)/Frameworks","IPHONEOS_DEPLOYMENT_TARGET":"12.0","MODULEMAP_FILE":"Target Support Files/webview_flutter_wkwebview/webview_flutter_wkwebview.modulemap","ONLY_ACTIVE_ARCH":"NO","OTHER_LDFLAGS":"$(inherited) -framework Flutter","PRODUCT_MODULE_NAME":"webview_flutter_wkwebview","PRODUCT_NAME":"webview_flutter_wkwebview","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","SWIFT_ACTIVE_COMPILATION_CONDITIONS":"$(inherited) ","SWIFT_INSTALL_OBJC_HEADER":"YES","SWIFT_VERSION":"5.0","TARGETED_DEVICE_FAMILY":"1,2","VALID_ARCHS[sdk=iphonesimulator*]":"$(ARCHS_STANDARD)","VERSIONING_SYSTEM":"apple-generic","VERSION_INFO_PREFIX":""},"guid":"bfdfe7dc352907fc980b868725387e98d6da72224a0002e2c8d4ad6a4140a101","name":"Debug"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e986361f96ad5d0d9cdb22ee6aa8a152702","buildSettings":{"CLANG_ENABLE_OBJC_WEAK":"NO","CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER":"NO","CODE_SIGN_IDENTITY[sdk=appletvos*]":"","CODE_SIGN_IDENTITY[sdk=iphoneos*]":"","CODE_SIGN_IDENTITY[sdk=watchos*]":"","CURRENT_PROJECT_VERSION":"1","DYLIB_COMPATIBILITY_VERSION":"1","DYLIB_CURRENT_VERSION":"1","DYLIB_INSTALL_NAME_BASE":"@rpath","ENABLE_BITCODE":"NO","ENABLE_MODULE_VERIFIER":"NO","ENABLE_USER_SCRIPT_SANDBOXING":"NO","EXCLUDED_ARCHS[sdk=iphoneos*]":"$(inherited) armv7","EXCLUDED_ARCHS[sdk=iphonesimulator*]":"$(inherited) i386","FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios-release/Flutter.xcframework/ios-arm64\" $(inherited)","FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios-release/Flutter.xcframework/ios-arm64_x86_64-simulator\" $(inherited)","GCC_PREFIX_HEADER":"Target Support Files/webview_flutter_wkwebview/webview_flutter_wkwebview-prefix.pch","GENERATE_INFOPLIST_FILE":"NO","INFOPLIST_FILE":"Target Support Files/webview_flutter_wkwebview/webview_flutter_wkwebview-Info.plist","INSTALL_PATH":"$(LOCAL_LIBRARY_DIR)/Frameworks","IPHONEOS_DEPLOYMENT_TARGET":"12.0","MODULEMAP_FILE":"Target Support Files/webview_flutter_wkwebview/webview_flutter_wkwebview.modulemap","OTHER_LDFLAGS":"$(inherited) -framework Flutter","PRODUCT_MODULE_NAME":"webview_flutter_wkwebview","PRODUCT_NAME":"webview_flutter_wkwebview","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","SWIFT_ACTIVE_COMPILATION_CONDITIONS":"$(inherited) ","SWIFT_INSTALL_OBJC_HEADER":"YES","SWIFT_VERSION":"5.0","TARGETED_DEVICE_FAMILY":"1,2","VALIDATE_PRODUCT":"YES","VALID_ARCHS[sdk=iphonesimulator*]":"$(ARCHS_STANDARD)","VERSIONING_SYSTEM":"apple-generic","VERSION_INFO_PREFIX":""},"guid":"bfdfe7dc352907fc980b868725387e984cab3693a69eb1c553c791758183685f","name":"Profile"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e986361f96ad5d0d9cdb22ee6aa8a152702","buildSettings":{"CLANG_ENABLE_OBJC_WEAK":"NO","CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER":"NO","CODE_SIGN_IDENTITY[sdk=appletvos*]":"","CODE_SIGN_IDENTITY[sdk=iphoneos*]":"","CODE_SIGN_IDENTITY[sdk=watchos*]":"","CURRENT_PROJECT_VERSION":"1","DYLIB_COMPATIBILITY_VERSION":"1","DYLIB_CURRENT_VERSION":"1","DYLIB_INSTALL_NAME_BASE":"@rpath","ENABLE_BITCODE":"NO","ENABLE_MODULE_VERIFIER":"NO","ENABLE_USER_SCRIPT_SANDBOXING":"NO","EXCLUDED_ARCHS[sdk=iphoneos*]":"$(inherited) armv7","EXCLUDED_ARCHS[sdk=iphonesimulator*]":"$(inherited) i386","FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios-release/Flutter.xcframework/ios-arm64\" $(inherited)","FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios-release/Flutter.xcframework/ios-arm64_x86_64-simulator\" $(inherited)","GCC_PREFIX_HEADER":"Target Support Files/webview_flutter_wkwebview/webview_flutter_wkwebview-prefix.pch","GENERATE_INFOPLIST_FILE":"NO","INFOPLIST_FILE":"Target Support Files/webview_flutter_wkwebview/webview_flutter_wkwebview-Info.plist","INSTALL_PATH":"$(LOCAL_LIBRARY_DIR)/Frameworks","IPHONEOS_DEPLOYMENT_TARGET":"12.0","MODULEMAP_FILE":"Target Support Files/webview_flutter_wkwebview/webview_flutter_wkwebview.modulemap","OTHER_LDFLAGS":"$(inherited) -framework Flutter","PRODUCT_MODULE_NAME":"webview_flutter_wkwebview","PRODUCT_NAME":"webview_flutter_wkwebview","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","SWIFT_ACTIVE_COMPILATION_CONDITIONS":"$(inherited) ","SWIFT_INSTALL_OBJC_HEADER":"YES","SWIFT_VERSION":"5.0","TARGETED_DEVICE_FAMILY":"1,2","VALIDATE_PRODUCT":"YES","VALID_ARCHS[sdk=iphonesimulator*]":"$(ARCHS_STANDARD)","VERSIONING_SYSTEM":"apple-generic","VERSION_INFO_PREFIX":""},"guid":"bfdfe7dc352907fc980b868725387e98f480631d57f584ae82569893436b3d19","name":"Release"}],"buildPhases":[{"buildFiles":[{"fileReference":"bfdfe7dc352907fc980b868725387e98e100b69887046077a7bf8a9cf060b929","guid":"bfdfe7dc352907fc980b868725387e98faa2d77c0ef7eb87f7f8421e51c1b40a","headerVisibility":"public"}],"guid":"bfdfe7dc352907fc980b868725387e98a1e3dac75ef5081293a3cce12f493338","type":"com.apple.buildphase.headers"},{"buildFiles":[{"fileReference":"bfdfe7dc352907fc980b868725387e986ff29dbf77026e2fd214aacc48415f97","guid":"bfdfe7dc352907fc980b868725387e981de55d3cb88db838f3f39ff1797f33ce"},{"fileReference":"bfdfe7dc352907fc980b868725387e9820d9fff640378ae11fbdb2bba644e272","guid":"bfdfe7dc352907fc980b868725387e980d29368ece429919c8416c926d20a1b2"},{"fileReference":"bfdfe7dc352907fc980b868725387e98974b7125c3956adff996755a1b114006","guid":"bfdfe7dc352907fc980b868725387e98a435f50ff0ee12aa4ee277e694f2d126"},{"fileReference":"bfdfe7dc352907fc980b868725387e98fba6a1bdafdc072d807182e50958ac26","guid":"bfdfe7dc352907fc980b868725387e9818698cd69a8dd984343dd8261e191bfe"},{"fileReference":"bfdfe7dc352907fc980b868725387e9807fa3ed9a1c3d073fb8ed93058a7d538","guid":"bfdfe7dc352907fc980b868725387e987b439d64aac2afa2aed5d37bc7b53769"},{"fileReference":"bfdfe7dc352907fc980b868725387e9824e336744c0d7621c05a0223e51f3f66","guid":"bfdfe7dc352907fc980b868725387e9818e2a45f7d284b0dd902ab3482fc9edb"},{"fileReference":"bfdfe7dc352907fc980b868725387e9857e538de55d68f7ce78f685c1cd73410","guid":"bfdfe7dc352907fc980b868725387e98ffd34fa8ce89c4ce6d50467fae983432"},{"fileReference":"bfdfe7dc352907fc980b868725387e982da8ffef86ceaf65ed1f58ad933d36d8","guid":"bfdfe7dc352907fc980b868725387e98292490ce28c17daff90e0e782d73f784"},{"fileReference":"bfdfe7dc352907fc980b868725387e98ce9ba0fba9b5e90953d30114104d18bc","guid":"bfdfe7dc352907fc980b868725387e9834f73e42a69fc8b030848f28d070a368"},{"fileReference":"bfdfe7dc352907fc980b868725387e98a310832039952a0739ca7694f7ad758e","guid":"bfdfe7dc352907fc980b868725387e9898302af153ac1de4bd9428fca3bb8787"},{"fileReference":"bfdfe7dc352907fc980b868725387e9891936b22d4461ddb3e4165f1a75492dd","guid":"bfdfe7dc352907fc980b868725387e98ed9c33c1bf4f8fcd55bba266c67d062a"},{"fileReference":"bfdfe7dc352907fc980b868725387e9816b4b9d8465e3dd15680823043c778bb","guid":"bfdfe7dc352907fc980b868725387e98464a60c69b30cf4487e30f2e39b99e0a"},{"fileReference":"bfdfe7dc352907fc980b868725387e98ce6725437b5f43c0bd6ef1ccca2be082","guid":"bfdfe7dc352907fc980b868725387e984e94890557c10720442eefca0758fb7c"},{"fileReference":"bfdfe7dc352907fc980b868725387e986957040d9dced8053bb6e8f373a49a06","guid":"bfdfe7dc352907fc980b868725387e9801dbd92bfe45922f943df863b92756e6"},{"fileReference":"bfdfe7dc352907fc980b868725387e98a64df73b74f54e7dabd523cef6eea263","guid":"bfdfe7dc352907fc980b868725387e98695f5b329bfc5e6e8a12c3ef049fd84c"},{"fileReference":"bfdfe7dc352907fc980b868725387e985543c3a955f9d511d6e7251e7b4f383d","guid":"bfdfe7dc352907fc980b868725387e9872af5e523f4a9b056594a6e3963880d9"},{"fileReference":"bfdfe7dc352907fc980b868725387e98792b7a5a9cbe04e9c7b7d002ea638e83","guid":"bfdfe7dc352907fc980b868725387e98cabaf14c8327f9e739a1581549abcfba"},{"fileReference":"bfdfe7dc352907fc980b868725387e98e581dc86e636a128fcc7362ffedfe3b7","guid":"bfdfe7dc352907fc980b868725387e989b8f377ba0e2936c53f2b68c58a2468f"},{"fileReference":"bfdfe7dc352907fc980b868725387e9858cff6fc49e9b7824e719efa2a279eb8","guid":"bfdfe7dc352907fc980b868725387e98756f0f8bc30293af870fd37ef4e582e1"},{"fileReference":"bfdfe7dc352907fc980b868725387e980c66c03c8dc7e7282d701e3891d179cb","guid":"bfdfe7dc352907fc980b868725387e98a495bec27416fe0ef6d4c382d92bd37e"},{"fileReference":"bfdfe7dc352907fc980b868725387e98d93aa4a0ffddd857d5b5afe3f1789e0e","guid":"bfdfe7dc352907fc980b868725387e98dbe4cb3179877b97fd1cd1b9c7b0d657"},{"fileReference":"bfdfe7dc352907fc980b868725387e98755928d01ec4e183f6c6ad5dd1695876","guid":"bfdfe7dc352907fc980b868725387e98766ed63c43677a312cd576b6ecfa968c"},{"fileReference":"bfdfe7dc352907fc980b868725387e98efc85ac7c715782d5e65417979a219b9","guid":"bfdfe7dc352907fc980b868725387e9848489c7f67c84ff61cfb0ea1ec45d107"},{"fileReference":"bfdfe7dc352907fc980b868725387e988bef82569b24b5f6c612471073c56493","guid":"bfdfe7dc352907fc980b868725387e987259ad0ccd853df9dbdf20df62b01bf2"},{"fileReference":"bfdfe7dc352907fc980b868725387e98e98acb700f264a4d35f96d3e3a8e7192","guid":"bfdfe7dc352907fc980b868725387e9891cdd6b5f47999868b621c0cac86717d"},{"fileReference":"bfdfe7dc352907fc980b868725387e986bcadc9db0e23f509801ea7c18f17d3e","guid":"bfdfe7dc352907fc980b868725387e98bc9ffc416d43c25db0eba7374081cc24"},{"fileReference":"bfdfe7dc352907fc980b868725387e98272adc89cc3be2f5bac7bc2bd91672ed","guid":"bfdfe7dc352907fc980b868725387e989f67bad303f2c7a18d6663b9004e7f7f"},{"fileReference":"bfdfe7dc352907fc980b868725387e98dc6cb65d5dd165e65b7fbfcc7dc4421e","guid":"bfdfe7dc352907fc980b868725387e9862ed648bd55286684f95fcc2fdaa477b"},{"fileReference":"bfdfe7dc352907fc980b868725387e9833a097b5db2a7b844364a9486bb9616f","guid":"bfdfe7dc352907fc980b868725387e982552ba38ca9f397d8f80abfd80676bc3"},{"fileReference":"bfdfe7dc352907fc980b868725387e9811087db04d1b6ae8e562b162a7bde163","guid":"bfdfe7dc352907fc980b868725387e98d195323b373d63793cdede578ba29670"},{"fileReference":"bfdfe7dc352907fc980b868725387e987b63bd86e178dd1a4cd5fdf23764582d","guid":"bfdfe7dc352907fc980b868725387e989f08d7c9104548f24fc29052371ddadd"},{"fileReference":"bfdfe7dc352907fc980b868725387e98369effa6d8c6f49ab6a964ee2e41f64e","guid":"bfdfe7dc352907fc980b868725387e987ec55db088ddc2cfce45820bbd5664e8"},{"fileReference":"bfdfe7dc352907fc980b868725387e980a7f96f6c054a6b00bbe8edd3e5e02dc","guid":"bfdfe7dc352907fc980b868725387e9834fcf0d5ba9575313556f54273579df8"},{"fileReference":"bfdfe7dc352907fc980b868725387e9816892ac189479c50552d8df59101d469","guid":"bfdfe7dc352907fc980b868725387e980040a96cdcfcca3605783952ba372b88"},{"fileReference":"bfdfe7dc352907fc980b868725387e98d35f2da81360644fe00f5e7f5c5945d2","guid":"bfdfe7dc352907fc980b868725387e98447fdb1e6faad86182194fdfd9dfa3e4"},{"fileReference":"bfdfe7dc352907fc980b868725387e98176f3e1e76204f06691b39d943dccd53","guid":"bfdfe7dc352907fc980b868725387e982a39c7e1197817396058f11573213f14"},{"fileReference":"bfdfe7dc352907fc980b868725387e981ce32df686de5ed232b0c0ee3fcd4c2f","guid":"bfdfe7dc352907fc980b868725387e988fbe3b540434ba51c47bff24442a163e"},{"fileReference":"bfdfe7dc352907fc980b868725387e98e318650c8871ff158cbd37f8183721bc","guid":"bfdfe7dc352907fc980b868725387e98930b3ec41868a6d90b18606db9285027"},{"fileReference":"bfdfe7dc352907fc980b868725387e98386ba49f024aea24034bf28582dbecf4","guid":"bfdfe7dc352907fc980b868725387e98d259083229b4eed28de4a364a94222ca"},{"fileReference":"bfdfe7dc352907fc980b868725387e98d6c137c1d8c257e5b352ba97472bf7bf","guid":"bfdfe7dc352907fc980b868725387e981b32f3680c2b08fba50eeb04efa7482a"},{"fileReference":"bfdfe7dc352907fc980b868725387e98cb546a8f7bdc2047fbe4a99c1563566d","guid":"bfdfe7dc352907fc980b868725387e98eebbce98b73db8698586b64728bd46aa"},{"fileReference":"bfdfe7dc352907fc980b868725387e983a1098d9b7174aa713f6eb4dab0d9ad3","guid":"bfdfe7dc352907fc980b868725387e981fb47af3fa29c91f647f1ad2f650ec8d"},{"fileReference":"bfdfe7dc352907fc980b868725387e989c1cb5357bcb6e5e3a472f4e95d10dbd","guid":"bfdfe7dc352907fc980b868725387e98c65d236fa956eb88c1809b17ad57212b"}],"guid":"bfdfe7dc352907fc980b868725387e980055fbf3a11bc15129d28ebbe5cc1480","type":"com.apple.buildphase.sources"},{"buildFiles":[{"fileReference":"bfdfe7dc352907fc980b868725387e9867aa7825f197b5c58a57320b4ccdc64e","guid":"bfdfe7dc352907fc980b868725387e987ead9e15fc09a570554fa963eed1137d"}],"guid":"bfdfe7dc352907fc980b868725387e98da9cd099e7190758cfc42156c0f4e548","type":"com.apple.buildphase.frameworks"},{"buildFiles":[{"guid":"bfdfe7dc352907fc980b868725387e98b8defae1b39d33d1c1b6a7ec3e8cf51c","targetReference":"bfdfe7dc352907fc980b868725387e987c93e943aa0a38b5f6684beaf6b4a3a1"}],"guid":"bfdfe7dc352907fc980b868725387e987fd8694c1d36b88c99f78feb0d04dd25","type":"com.apple.buildphase.resources"}],"buildRules":[],"dependencies":[{"guid":"bfdfe7dc352907fc980b868725387e989da425bb6d6d5d8dbb95e4afffb82217","name":"Flutter"},{"guid":"bfdfe7dc352907fc980b868725387e987c93e943aa0a38b5f6684beaf6b4a3a1","name":"webview_flutter_wkwebview-webview_flutter_wkwebview_privacy"}],"guid":"bfdfe7dc352907fc980b868725387e988efdc4dd0ac29b43123295eca853f4ed","name":"webview_flutter_wkwebview","predominantSourceCodeLanguage":"Xcode.SourceCodeLanguage.Swift","productReference":{"guid":"bfdfe7dc352907fc980b868725387e980823710353e0487822d6da09bf8d6254","name":"webview_flutter_wkwebview.framework","type":"product"},"productTypeIdentifier":"com.apple.product-type.framework","provisioningSourceData":[{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Debug","provisioningStyle":1},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Profile","provisioningStyle":1},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Release","provisioningStyle":1}],"type":"standard"}  
1 -{"buildConfigurations":[{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e98890adb2b2b98fc70f20de16996216002","buildSettings":{"CLANG_ENABLE_OBJC_WEAK":"NO","CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER":"NO","CODE_SIGN_IDENTITY[sdk=appletvos*]":"","CODE_SIGN_IDENTITY[sdk=iphoneos*]":"","CODE_SIGN_IDENTITY[sdk=watchos*]":"","CURRENT_PROJECT_VERSION":"1","DYLIB_COMPATIBILITY_VERSION":"1","DYLIB_CURRENT_VERSION":"1","DYLIB_INSTALL_NAME_BASE":"@rpath","ENABLE_BITCODE":"NO","ENABLE_MODULE_VERIFIER":"NO","ENABLE_USER_SCRIPT_SANDBOXING":"NO","EXCLUDED_ARCHS[sdk=iphoneos*]":"$(inherited) armv7","EXCLUDED_ARCHS[sdk=iphonesimulator*]":"$(inherited) i386","FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios/Flutter.xcframework/ios-arm64\" $(inherited)","FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios/Flutter.xcframework/ios-arm64_x86_64-simulator\" $(inherited)","GCC_PREFIX_HEADER":"Target Support Files/image_picker_ios/image_picker_ios-prefix.pch","GENERATE_INFOPLIST_FILE":"NO","INFOPLIST_FILE":"Target Support Files/image_picker_ios/image_picker_ios-Info.plist","INSTALL_PATH":"$(LOCAL_LIBRARY_DIR)/Frameworks","IPHONEOS_DEPLOYMENT_TARGET":"12.0","LD_RUNPATH_SEARCH_PATHS":"$(inherited) @executable_path/Frameworks @loader_path/Frameworks","MODULEMAP_FILE":"Target Support Files/image_picker_ios/image_picker_ios.modulemap","ONLY_ACTIVE_ARCH":"NO","OTHER_LDFLAGS":"$(inherited) -framework Flutter","PRODUCT_MODULE_NAME":"image_picker_ios","PRODUCT_NAME":"image_picker_ios","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","SWIFT_ACTIVE_COMPILATION_CONDITIONS":"$(inherited) ","SWIFT_INSTALL_OBJC_HEADER":"YES","SWIFT_VERSION":"5.0","TARGETED_DEVICE_FAMILY":"1,2","VALID_ARCHS[sdk=iphonesimulator*]":"$(ARCHS_STANDARD)","VERSIONING_SYSTEM":"apple-generic","VERSION_INFO_PREFIX":""},"guid":"bfdfe7dc352907fc980b868725387e9864dece58fe8898e7f0b46391fe2d091f","name":"Debug"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e98221c7220f1a43556e154d0e84bf28676","buildSettings":{"CLANG_ENABLE_OBJC_WEAK":"NO","CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER":"NO","CODE_SIGN_IDENTITY[sdk=appletvos*]":"","CODE_SIGN_IDENTITY[sdk=iphoneos*]":"","CODE_SIGN_IDENTITY[sdk=watchos*]":"","CURRENT_PROJECT_VERSION":"1","DYLIB_COMPATIBILITY_VERSION":"1","DYLIB_CURRENT_VERSION":"1","DYLIB_INSTALL_NAME_BASE":"@rpath","ENABLE_BITCODE":"NO","ENABLE_MODULE_VERIFIER":"NO","ENABLE_USER_SCRIPT_SANDBOXING":"NO","EXCLUDED_ARCHS[sdk=iphoneos*]":"$(inherited) armv7","EXCLUDED_ARCHS[sdk=iphonesimulator*]":"$(inherited) i386","FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios-release/Flutter.xcframework/ios-arm64\" $(inherited)","FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios-release/Flutter.xcframework/ios-arm64_x86_64-simulator\" $(inherited)","GCC_PREFIX_HEADER":"Target Support Files/image_picker_ios/image_picker_ios-prefix.pch","GENERATE_INFOPLIST_FILE":"NO","INFOPLIST_FILE":"Target Support Files/image_picker_ios/image_picker_ios-Info.plist","INSTALL_PATH":"$(LOCAL_LIBRARY_DIR)/Frameworks","IPHONEOS_DEPLOYMENT_TARGET":"12.0","LD_RUNPATH_SEARCH_PATHS":"$(inherited) @executable_path/Frameworks @loader_path/Frameworks","MODULEMAP_FILE":"Target Support Files/image_picker_ios/image_picker_ios.modulemap","OTHER_LDFLAGS":"$(inherited) -framework Flutter","PRODUCT_MODULE_NAME":"image_picker_ios","PRODUCT_NAME":"image_picker_ios","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","SWIFT_ACTIVE_COMPILATION_CONDITIONS":"$(inherited) ","SWIFT_INSTALL_OBJC_HEADER":"YES","SWIFT_VERSION":"5.0","TARGETED_DEVICE_FAMILY":"1,2","VALIDATE_PRODUCT":"YES","VALID_ARCHS[sdk=iphonesimulator*]":"$(ARCHS_STANDARD)","VERSIONING_SYSTEM":"apple-generic","VERSION_INFO_PREFIX":""},"guid":"bfdfe7dc352907fc980b868725387e981b08ec94c515cc2b895c3ae9b4c03834","name":"Profile"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e98221c7220f1a43556e154d0e84bf28676","buildSettings":{"CLANG_ENABLE_OBJC_WEAK":"NO","CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER":"NO","CODE_SIGN_IDENTITY[sdk=appletvos*]":"","CODE_SIGN_IDENTITY[sdk=iphoneos*]":"","CODE_SIGN_IDENTITY[sdk=watchos*]":"","CURRENT_PROJECT_VERSION":"1","DYLIB_COMPATIBILITY_VERSION":"1","DYLIB_CURRENT_VERSION":"1","DYLIB_INSTALL_NAME_BASE":"@rpath","ENABLE_BITCODE":"NO","ENABLE_MODULE_VERIFIER":"NO","ENABLE_USER_SCRIPT_SANDBOXING":"NO","EXCLUDED_ARCHS[sdk=iphoneos*]":"$(inherited) armv7","EXCLUDED_ARCHS[sdk=iphonesimulator*]":"$(inherited) i386","FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios-release/Flutter.xcframework/ios-arm64\" $(inherited)","FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios-release/Flutter.xcframework/ios-arm64_x86_64-simulator\" $(inherited)","GCC_PREFIX_HEADER":"Target Support Files/image_picker_ios/image_picker_ios-prefix.pch","GENERATE_INFOPLIST_FILE":"NO","INFOPLIST_FILE":"Target Support Files/image_picker_ios/image_picker_ios-Info.plist","INSTALL_PATH":"$(LOCAL_LIBRARY_DIR)/Frameworks","IPHONEOS_DEPLOYMENT_TARGET":"12.0","LD_RUNPATH_SEARCH_PATHS":"$(inherited) @executable_path/Frameworks @loader_path/Frameworks","MODULEMAP_FILE":"Target Support Files/image_picker_ios/image_picker_ios.modulemap","OTHER_LDFLAGS":"$(inherited) -framework Flutter","PRODUCT_MODULE_NAME":"image_picker_ios","PRODUCT_NAME":"image_picker_ios","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","SWIFT_ACTIVE_COMPILATION_CONDITIONS":"$(inherited) ","SWIFT_INSTALL_OBJC_HEADER":"YES","SWIFT_VERSION":"5.0","TARGETED_DEVICE_FAMILY":"1,2","VALIDATE_PRODUCT":"YES","VALID_ARCHS[sdk=iphonesimulator*]":"$(ARCHS_STANDARD)","VERSIONING_SYSTEM":"apple-generic","VERSION_INFO_PREFIX":""},"guid":"bfdfe7dc352907fc980b868725387e982b03ce4519745554a82e5cffe58f25e2","name":"Release"}],"buildPhases":[{"buildFiles":[{"fileReference":"bfdfe7dc352907fc980b868725387e9887cb71ec0a197ed2946aed6024d1dad1","guid":"bfdfe7dc352907fc980b868725387e98036d5aec29b54b7dd40e90098fa1a783","headerVisibility":"public"},{"fileReference":"bfdfe7dc352907fc980b868725387e9892d65c42b66fdd6d568c50d0e873ca05","guid":"bfdfe7dc352907fc980b868725387e9884122a5495886f08a28766f6766ed12d","headerVisibility":"public"},{"fileReference":"bfdfe7dc352907fc980b868725387e988061950042bff325e12ce6e07163bdf3","guid":"bfdfe7dc352907fc980b868725387e9878792dd23cc884d01a42ee927a76af76","headerVisibility":"public"},{"fileReference":"bfdfe7dc352907fc980b868725387e98314704ab4b99c3ad78a115a96a37a641","guid":"bfdfe7dc352907fc980b868725387e98ac4ce8757c9fefe5d0b2b79262ebbaeb","headerVisibility":"public"},{"fileReference":"bfdfe7dc352907fc980b868725387e9874a54da90eac84404a6d42381d295f8d","guid":"bfdfe7dc352907fc980b868725387e9816643affd079e3f5d29a95b3d4ac8518","headerVisibility":"public"},{"fileReference":"bfdfe7dc352907fc980b868725387e984ae39a9f5ce5801d979fc71dc42040a4","guid":"bfdfe7dc352907fc980b868725387e9833ff3f2578502bb2f88e252ec33d5fb3","headerVisibility":"public"},{"fileReference":"bfdfe7dc352907fc980b868725387e986d4a8dba098c26b0e6cb26abd8e5b82f","guid":"bfdfe7dc352907fc980b868725387e9822ff4bab74a9180dcd559e6228895c11","headerVisibility":"public"},{"fileReference":"bfdfe7dc352907fc980b868725387e98001a1216fcba8a5077639ed936eedf22","guid":"bfdfe7dc352907fc980b868725387e984f06794600a72eff5e8b6bd1bfb1381c","headerVisibility":"public"}],"guid":"bfdfe7dc352907fc980b868725387e987c543487347cac13b6462fae62598e7f","type":"com.apple.buildphase.headers"},{"buildFiles":[{"fileReference":"bfdfe7dc352907fc980b868725387e981f6c3202c5e8ea43fabe23d4ac249aa8","guid":"bfdfe7dc352907fc980b868725387e9839e6fa4fb580d35845b455f3349208ed"},{"fileReference":"bfdfe7dc352907fc980b868725387e98d3353819e36d78fafa3c90288aa829a8","guid":"bfdfe7dc352907fc980b868725387e987f4d20a804f6cc54ba49f23a03bba3ff"},{"fileReference":"bfdfe7dc352907fc980b868725387e9879f3ff725c0c37a2851096c74b7aa01c","guid":"bfdfe7dc352907fc980b868725387e986de844193f467a67763cf085cbf548af"},{"fileReference":"bfdfe7dc352907fc980b868725387e98521a0cbc97fe403ba6dec7b4711eca98","guid":"bfdfe7dc352907fc980b868725387e980a470861055f808b55678e192587ba69"},{"fileReference":"bfdfe7dc352907fc980b868725387e98ef7fab25f1a8201b14fddc3cd791dc85","guid":"bfdfe7dc352907fc980b868725387e98fe1bc38033b4a880e7f645b78bb9d3b6"},{"fileReference":"bfdfe7dc352907fc980b868725387e98e866ceff35444fd643a35a36698bec12","guid":"bfdfe7dc352907fc980b868725387e98e0ab939fbafbd88342244f2b4a6d7f2e"},{"fileReference":"bfdfe7dc352907fc980b868725387e987c91f08e2ecb120f461660eb187051f2","guid":"bfdfe7dc352907fc980b868725387e986537e55fb8c991ac3f2f365064e71ccf"}],"guid":"bfdfe7dc352907fc980b868725387e98ce67561b68c83c2e24888c94da999914","type":"com.apple.buildphase.sources"},{"buildFiles":[{"fileReference":"bfdfe7dc352907fc980b868725387e9867aa7825f197b5c58a57320b4ccdc64e","guid":"bfdfe7dc352907fc980b868725387e98cf1fddec899afc6c9825c5eb5ec44493"}],"guid":"bfdfe7dc352907fc980b868725387e98434353ef3b38c3699582ee30b73fe6a8","type":"com.apple.buildphase.frameworks"},{"buildFiles":[{"guid":"bfdfe7dc352907fc980b868725387e9872ef11792920b3966776ea469c5092df","targetReference":"bfdfe7dc352907fc980b868725387e98082dc85da1fc941e5234c7cc1f11b27d"}],"guid":"bfdfe7dc352907fc980b868725387e9811e9e8a5f23273fd9234f4740a75ccb9","type":"com.apple.buildphase.resources"}],"buildRules":[],"dependencies":[{"guid":"bfdfe7dc352907fc980b868725387e989da425bb6d6d5d8dbb95e4afffb82217","name":"Flutter"},{"guid":"bfdfe7dc352907fc980b868725387e98082dc85da1fc941e5234c7cc1f11b27d","name":"image_picker_ios-image_picker_ios_privacy"}],"guid":"bfdfe7dc352907fc980b868725387e981f000f066404b97b12e9c4ca84d38d0f","name":"image_picker_ios","predominantSourceCodeLanguage":"Xcode.SourceCodeLanguage.Objective-C-Plus-Plus","productReference":{"guid":"bfdfe7dc352907fc980b868725387e988e06e8c3685b7c12032d8059f412f4cb","name":"image_picker_ios.framework","type":"product"},"productTypeIdentifier":"com.apple.product-type.framework","provisioningSourceData":[{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Debug","provisioningStyle":1},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Profile","provisioningStyle":1},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Release","provisioningStyle":1}],"type":"standard"}  
1 -{"buildConfigurations":[{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e98a6093e67eab0c95af9b59197c88a1b6b","buildSettings":{"CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER":"NO","CODE_SIGN_IDENTITY[sdk=appletvos*]":"","CODE_SIGN_IDENTITY[sdk=iphoneos*]":"","CODE_SIGN_IDENTITY[sdk=watchos*]":"","CURRENT_PROJECT_VERSION":"1","DEFINES_MODULE":"YES","DYLIB_COMPATIBILITY_VERSION":"1","DYLIB_CURRENT_VERSION":"1","DYLIB_INSTALL_NAME_BASE":"@rpath","ENABLE_BITCODE":"NO","ENABLE_MODULE_VERIFIER":"NO","ENABLE_USER_SCRIPT_SANDBOXING":"NO","EXCLUDED_ARCHS[sdk=iphoneos*]":"$(inherited) armv7","EXCLUDED_ARCHS[sdk=iphonesimulator*]":"$(inherited) i386","FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios/Flutter.xcframework/ios-arm64\" $(inherited)","FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios/Flutter.xcframework/ios-arm64_x86_64-simulator\" $(inherited)","GCC_PREFIX_HEADER":"Target Support Files/permission_handler_apple/permission_handler_apple-prefix.pch","GENERATE_INFOPLIST_FILE":"NO","INFOPLIST_FILE":"Target Support Files/permission_handler_apple/permission_handler_apple-Info.plist","INSTALL_PATH":"$(LOCAL_LIBRARY_DIR)/Frameworks","LD_RUNPATH_SEARCH_PATHS":"$(inherited) @executable_path/Frameworks @loader_path/Frameworks","MACH_O_TYPE":"staticlib","MODULEMAP_FILE":"Target Support Files/permission_handler_apple/permission_handler_apple.modulemap","ONLY_ACTIVE_ARCH":"NO","OTHER_LDFLAGS":"$(inherited) -framework Flutter","PRODUCT_MODULE_NAME":"permission_handler_apple","PRODUCT_NAME":"permission_handler_apple","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","SWIFT_ACTIVE_COMPILATION_CONDITIONS":"$(inherited) ","SWIFT_INSTALL_OBJC_HEADER":"YES","SWIFT_VERSION":"5.0","TARGETED_DEVICE_FAMILY":"1,2","VALID_ARCHS[sdk=iphonesimulator*]":"$(ARCHS_STANDARD)","VERSIONING_SYSTEM":"apple-generic","VERSION_INFO_PREFIX":""},"guid":"bfdfe7dc352907fc980b868725387e98519c0f1aabf34eacbf6f755b813f1496","name":"Debug"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e982824e3afc8d872da1d8489aeef65d25c","buildSettings":{"CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER":"NO","CODE_SIGN_IDENTITY[sdk=appletvos*]":"","CODE_SIGN_IDENTITY[sdk=iphoneos*]":"","CODE_SIGN_IDENTITY[sdk=watchos*]":"","CURRENT_PROJECT_VERSION":"1","DEFINES_MODULE":"YES","DYLIB_COMPATIBILITY_VERSION":"1","DYLIB_CURRENT_VERSION":"1","DYLIB_INSTALL_NAME_BASE":"@rpath","ENABLE_BITCODE":"NO","ENABLE_MODULE_VERIFIER":"NO","ENABLE_USER_SCRIPT_SANDBOXING":"NO","EXCLUDED_ARCHS[sdk=iphoneos*]":"$(inherited) armv7","EXCLUDED_ARCHS[sdk=iphonesimulator*]":"$(inherited) i386","FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios-release/Flutter.xcframework/ios-arm64\" $(inherited)","FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios-release/Flutter.xcframework/ios-arm64_x86_64-simulator\" $(inherited)","GCC_PREFIX_HEADER":"Target Support Files/permission_handler_apple/permission_handler_apple-prefix.pch","GENERATE_INFOPLIST_FILE":"NO","INFOPLIST_FILE":"Target Support Files/permission_handler_apple/permission_handler_apple-Info.plist","INSTALL_PATH":"$(LOCAL_LIBRARY_DIR)/Frameworks","LD_RUNPATH_SEARCH_PATHS":"$(inherited) @executable_path/Frameworks @loader_path/Frameworks","MACH_O_TYPE":"staticlib","MODULEMAP_FILE":"Target Support Files/permission_handler_apple/permission_handler_apple.modulemap","OTHER_LDFLAGS":"$(inherited) -framework Flutter","PRODUCT_MODULE_NAME":"permission_handler_apple","PRODUCT_NAME":"permission_handler_apple","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","SWIFT_ACTIVE_COMPILATION_CONDITIONS":"$(inherited) ","SWIFT_INSTALL_OBJC_HEADER":"YES","SWIFT_VERSION":"5.0","TARGETED_DEVICE_FAMILY":"1,2","VALIDATE_PRODUCT":"YES","VALID_ARCHS[sdk=iphonesimulator*]":"$(ARCHS_STANDARD)","VERSIONING_SYSTEM":"apple-generic","VERSION_INFO_PREFIX":""},"guid":"bfdfe7dc352907fc980b868725387e98ec62137b0ee28ca4265944856877be27","name":"Profile"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e982824e3afc8d872da1d8489aeef65d25c","buildSettings":{"CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER":"NO","CODE_SIGN_IDENTITY[sdk=appletvos*]":"","CODE_SIGN_IDENTITY[sdk=iphoneos*]":"","CODE_SIGN_IDENTITY[sdk=watchos*]":"","CURRENT_PROJECT_VERSION":"1","DEFINES_MODULE":"YES","DYLIB_COMPATIBILITY_VERSION":"1","DYLIB_CURRENT_VERSION":"1","DYLIB_INSTALL_NAME_BASE":"@rpath","ENABLE_BITCODE":"NO","ENABLE_MODULE_VERIFIER":"NO","ENABLE_USER_SCRIPT_SANDBOXING":"NO","EXCLUDED_ARCHS[sdk=iphoneos*]":"$(inherited) armv7","EXCLUDED_ARCHS[sdk=iphonesimulator*]":"$(inherited) i386","FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios-release/Flutter.xcframework/ios-arm64\" $(inherited)","FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios-release/Flutter.xcframework/ios-arm64_x86_64-simulator\" $(inherited)","GCC_PREFIX_HEADER":"Target Support Files/permission_handler_apple/permission_handler_apple-prefix.pch","GENERATE_INFOPLIST_FILE":"NO","INFOPLIST_FILE":"Target Support Files/permission_handler_apple/permission_handler_apple-Info.plist","INSTALL_PATH":"$(LOCAL_LIBRARY_DIR)/Frameworks","LD_RUNPATH_SEARCH_PATHS":"$(inherited) @executable_path/Frameworks @loader_path/Frameworks","MACH_O_TYPE":"staticlib","MODULEMAP_FILE":"Target Support Files/permission_handler_apple/permission_handler_apple.modulemap","OTHER_LDFLAGS":"$(inherited) -framework Flutter","PRODUCT_MODULE_NAME":"permission_handler_apple","PRODUCT_NAME":"permission_handler_apple","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","SWIFT_ACTIVE_COMPILATION_CONDITIONS":"$(inherited) ","SWIFT_INSTALL_OBJC_HEADER":"YES","SWIFT_VERSION":"5.0","TARGETED_DEVICE_FAMILY":"1,2","VALIDATE_PRODUCT":"YES","VALID_ARCHS[sdk=iphonesimulator*]":"$(ARCHS_STANDARD)","VERSIONING_SYSTEM":"apple-generic","VERSION_INFO_PREFIX":""},"guid":"bfdfe7dc352907fc980b868725387e9832ebf16d88dad2729e444c32094aa46a","name":"Release"}],"buildPhases":[{"buildFiles":[{"fileReference":"bfdfe7dc352907fc980b868725387e9884851084d3b02b53cd983fcffd818235","guid":"bfdfe7dc352907fc980b868725387e98a27a49b00be0ac981e5db9f07832563d","headerVisibility":"public"},{"fileReference":"bfdfe7dc352907fc980b868725387e982e7f7319c09f94850a0723a216d70e04","guid":"bfdfe7dc352907fc980b868725387e989878394bd4334bc5b75f69e19db62bf2","headerVisibility":"public"},{"fileReference":"bfdfe7dc352907fc980b868725387e9821ebb0fa53d0eb7ec2ab6f8ca9190624","guid":"bfdfe7dc352907fc980b868725387e98e1897e3d8aed17671192779f85b1c248","headerVisibility":"public"},{"fileReference":"bfdfe7dc352907fc980b868725387e98b5b86aa005335961c358b4a960923948","guid":"bfdfe7dc352907fc980b868725387e981450c482f5c290824d437888a184ae8b","headerVisibility":"public"},{"fileReference":"bfdfe7dc352907fc980b868725387e98cfa5ce0ae7f41afbcf0e57cd6de30680","guid":"bfdfe7dc352907fc980b868725387e98e4fc9878a7a9815c87ead588b617e13f","headerVisibility":"public"},{"fileReference":"bfdfe7dc352907fc980b868725387e9822c393317084e36f2969d86ba20820cc","guid":"bfdfe7dc352907fc980b868725387e98931f24651cd163bcb560cc6bf0293fcb","headerVisibility":"public"},{"fileReference":"bfdfe7dc352907fc980b868725387e98265b9bc576c6643489aa71c5ef563885","guid":"bfdfe7dc352907fc980b868725387e98d4cfb9e1cbc63fdd6505f85f9a29df9c","headerVisibility":"public"},{"fileReference":"bfdfe7dc352907fc980b868725387e98fb31e35e6ff05f31942d41934fa09494","guid":"bfdfe7dc352907fc980b868725387e98603cbbc70b8dca9ffe9ae016055178e4","headerVisibility":"public"},{"fileReference":"bfdfe7dc352907fc980b868725387e983e6c10cd55ac7b546e8a27a6d73df979","guid":"bfdfe7dc352907fc980b868725387e98de1a9153e9195626d2e18082bddd5583","headerVisibility":"public"},{"fileReference":"bfdfe7dc352907fc980b868725387e986788e4d437e57069fdd7150780f6a1e9","guid":"bfdfe7dc352907fc980b868725387e984a1d400fa247fcd1999957a8682fc831","headerVisibility":"public"},{"fileReference":"bfdfe7dc352907fc980b868725387e98cafca9abb3305da2511ec18f0b22ed2c","guid":"bfdfe7dc352907fc980b868725387e98d32709d3a2dbac2c57e7e408179d0866","headerVisibility":"public"},{"fileReference":"bfdfe7dc352907fc980b868725387e9828dae6c5d961eab3e33766ec57e27821","guid":"bfdfe7dc352907fc980b868725387e9852b51035de7e7268120a09bd61060c70","headerVisibility":"public"},{"fileReference":"bfdfe7dc352907fc980b868725387e985dfbcd518b00fd83791970f4f841e5e7","guid":"bfdfe7dc352907fc980b868725387e98dc02dbc796bf1a1c79ffc8c7bf3cea72","headerVisibility":"public"},{"fileReference":"bfdfe7dc352907fc980b868725387e981329cadec5aeca914b5940565930d22a","guid":"bfdfe7dc352907fc980b868725387e9851124daa4e024f512c6435eeca4166ec","headerVisibility":"public"},{"fileReference":"bfdfe7dc352907fc980b868725387e98447580bc8b8f4827c81d8360464b9e24","guid":"bfdfe7dc352907fc980b868725387e98d1ab4894e5f8a787a882b5c8c35da9b2","headerVisibility":"public"},{"fileReference":"bfdfe7dc352907fc980b868725387e98c2f59fe53444d666df46ecacb137334b","guid":"bfdfe7dc352907fc980b868725387e980ef321af2f9f2c834e49de13f3d55bc9","headerVisibility":"public"},{"fileReference":"bfdfe7dc352907fc980b868725387e986dd8eb61c9df9c78ba64a9f79cace01e","guid":"bfdfe7dc352907fc980b868725387e98f0d31a429c82f17b0991aeffa8fa048c","headerVisibility":"public"},{"fileReference":"bfdfe7dc352907fc980b868725387e988e29d9b40690bda08dda415d92f70602","guid":"bfdfe7dc352907fc980b868725387e98a42a0c118dedfd60efdbb4d16492c7b8","headerVisibility":"public"},{"fileReference":"bfdfe7dc352907fc980b868725387e98e2ab3143400e3260e6623fe39e99f7c0","guid":"bfdfe7dc352907fc980b868725387e98b3c686ca16e5bce7ed24eabc68c27a7a","headerVisibility":"public"},{"fileReference":"bfdfe7dc352907fc980b868725387e98af3e4ebd26dd264bce4333eb0e99f67c","guid":"bfdfe7dc352907fc980b868725387e9828accb1b5b23f919db719dddafe64428","headerVisibility":"public"},{"fileReference":"bfdfe7dc352907fc980b868725387e98a5999d69392be533721c9529b09cb914","guid":"bfdfe7dc352907fc980b868725387e981a70531bb3ca84e549cc6ba35f299fa1","headerVisibility":"public"},{"fileReference":"bfdfe7dc352907fc980b868725387e9830ffd03b288e713d891e12ce5bfa5613","guid":"bfdfe7dc352907fc980b868725387e98d126da608ed212ace70c11a62a0c1637","headerVisibility":"public"},{"fileReference":"bfdfe7dc352907fc980b868725387e98e3b68579772f0ba934ed8c3c170aa0ab","guid":"bfdfe7dc352907fc980b868725387e98482d9659cbec4dc229fbd14d4097dbb0","headerVisibility":"public"}],"guid":"bfdfe7dc352907fc980b868725387e986a03fa67e33d48dce94be2b8eb2259ec","type":"com.apple.buildphase.headers"},{"buildFiles":[{"fileReference":"bfdfe7dc352907fc980b868725387e9859b1324343dc055e161d6c6533ee5e14","guid":"bfdfe7dc352907fc980b868725387e989514a07acecd425069c301ac83629a34"},{"fileReference":"bfdfe7dc352907fc980b868725387e9842f3aba82f1bbbea45fa42860b997a9c","guid":"bfdfe7dc352907fc980b868725387e98c5aeecdf68b8bd150764901c66af09a9"},{"fileReference":"bfdfe7dc352907fc980b868725387e98620c548ad1ca45b7c591297d1eb7c747","guid":"bfdfe7dc352907fc980b868725387e98845832e3ddc9b9efa82804181189873f"},{"fileReference":"bfdfe7dc352907fc980b868725387e988137c4db801b52960f300f0a7f9e66e1","guid":"bfdfe7dc352907fc980b868725387e988422c8d41a531ab0e5feda22b2729450"},{"fileReference":"bfdfe7dc352907fc980b868725387e9818cfd9e6e71005df38ef34975cee4bb2","guid":"bfdfe7dc352907fc980b868725387e98032b5432a99c409a15c23484d253896f"},{"fileReference":"bfdfe7dc352907fc980b868725387e9873b0ea1c477453db2a27395853e19d20","guid":"bfdfe7dc352907fc980b868725387e988ec79e04b31e29a98b9058ffe01c7fe6"},{"fileReference":"bfdfe7dc352907fc980b868725387e98c2f696a6e8c1b05591d7b9da435e3493","guid":"bfdfe7dc352907fc980b868725387e980e70a7a6c573b1b7ccd3e1d5ab5d07e2"},{"fileReference":"bfdfe7dc352907fc980b868725387e9800e74c7905cd82d36f9960af8978f5aa","guid":"bfdfe7dc352907fc980b868725387e983e056fb9529e4b65a3f33b7e5569c272"},{"fileReference":"bfdfe7dc352907fc980b868725387e98de774a6e299c64442144c3fcc58fa595","guid":"bfdfe7dc352907fc980b868725387e980341c01be7632895d55fd1dac2b54ca7"},{"fileReference":"bfdfe7dc352907fc980b868725387e985b42d8660810a9d6b3aad933347d7e57","guid":"bfdfe7dc352907fc980b868725387e9844b9c045f1529acb68ed027e0a48b614"},{"fileReference":"bfdfe7dc352907fc980b868725387e98520970053fda1908c06476b52a119a95","guid":"bfdfe7dc352907fc980b868725387e98b1b6e64bf6811487ed4c6e1384077226"},{"fileReference":"bfdfe7dc352907fc980b868725387e985b14ce293cf32a01a773054612405a14","guid":"bfdfe7dc352907fc980b868725387e981f2b6f47d148085767ead35147c92b0a"},{"fileReference":"bfdfe7dc352907fc980b868725387e98697a7d246f5ecbb804645bdff1bd0889","guid":"bfdfe7dc352907fc980b868725387e981850b344567e5543096f0a83d9eac0b2"},{"fileReference":"bfdfe7dc352907fc980b868725387e98b232dd09cbb7ffdcc50b18242e2d54aa","guid":"bfdfe7dc352907fc980b868725387e98ff4558f6e06cbb7fbd15dd015ca18854"},{"fileReference":"bfdfe7dc352907fc980b868725387e981311af37bc86faf3e55d86273af1dd44","guid":"bfdfe7dc352907fc980b868725387e983caf79b54a68f27872c153b09b7289cb"},{"fileReference":"bfdfe7dc352907fc980b868725387e989fc0bac42f87fe89196550b76dd1d39a","guid":"bfdfe7dc352907fc980b868725387e983550715f5dc47c6e779aeb12290a7c48"},{"fileReference":"bfdfe7dc352907fc980b868725387e984e9f512a43dc9832164c7190e5793552","guid":"bfdfe7dc352907fc980b868725387e985800f051739a623bb35f7cc22cbdb0d1"},{"fileReference":"bfdfe7dc352907fc980b868725387e98f4a28458a09df40a41a85843a00b9764","guid":"bfdfe7dc352907fc980b868725387e98f2203b5d78f4ac52bb8f2618d0202e75"},{"fileReference":"bfdfe7dc352907fc980b868725387e988c71f7c3f79685b588b764a4722910f6","guid":"bfdfe7dc352907fc980b868725387e983616275298339a71f8ce5405edcae646"},{"fileReference":"bfdfe7dc352907fc980b868725387e98629dea7138da4a42b26f2cec5f668c3e","guid":"bfdfe7dc352907fc980b868725387e9859b2f7d951b31f73b36500eee5613569"},{"fileReference":"bfdfe7dc352907fc980b868725387e98572e0d97aec70a0d968a775514e32a66","guid":"bfdfe7dc352907fc980b868725387e9800fc7c6d98b1d598e7f0946391c24f5b"}],"guid":"bfdfe7dc352907fc980b868725387e98be6229230a4715433df2f8e74fbafc5b","type":"com.apple.buildphase.sources"},{"buildFiles":[{"fileReference":"bfdfe7dc352907fc980b868725387e9867aa7825f197b5c58a57320b4ccdc64e","guid":"bfdfe7dc352907fc980b868725387e980797c2152e50219ee4196549bb34f857"}],"guid":"bfdfe7dc352907fc980b868725387e984d290968aff9eafa4ed5b85c80a8c610","type":"com.apple.buildphase.frameworks"},{"buildFiles":[],"guid":"bfdfe7dc352907fc980b868725387e98fa0d11ed0b4e1a85c13d68e37d1547e0","type":"com.apple.buildphase.resources"}],"buildRules":[],"dependencies":[{"guid":"bfdfe7dc352907fc980b868725387e989da425bb6d6d5d8dbb95e4afffb82217","name":"Flutter"},{"guid":"bfdfe7dc352907fc980b868725387e9802f35ab680609a626ebd2ddd692a3822","name":"permission_handler_apple-permission_handler_apple_privacy"}],"guid":"bfdfe7dc352907fc980b868725387e98ef10255b706f98e1e88fae00855b0968","name":"permission_handler_apple","predominantSourceCodeLanguage":"Xcode.SourceCodeLanguage.Objective-C-Plus-Plus","productReference":{"guid":"bfdfe7dc352907fc980b868725387e98f8f53f8ba4165e76c7481b24262177ed","name":"permission_handler_apple.framework","type":"product"},"productTypeIdentifier":"com.apple.product-type.framework","provisioningSourceData":[{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Debug","provisioningStyle":1},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Profile","provisioningStyle":1},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Release","provisioningStyle":1}],"type":"standard"}  
1 -{"buildConfigurations":[{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e9868b77f49da4a0e0608aac8b3f5ae3e8e","buildSettings":{"CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER":"NO","CODE_SIGN_IDENTITY[sdk=appletvos*]":"","CODE_SIGN_IDENTITY[sdk=iphoneos*]":"","CODE_SIGN_IDENTITY[sdk=watchos*]":"","CURRENT_PROJECT_VERSION":"1","DYLIB_COMPATIBILITY_VERSION":"1","DYLIB_CURRENT_VERSION":"1","DYLIB_INSTALL_NAME_BASE":"@rpath","ENABLE_BITCODE":"NO","ENABLE_MODULE_VERIFIER":"NO","ENABLE_USER_SCRIPT_SANDBOXING":"NO","EXCLUDED_ARCHS[sdk=iphoneos*]":"$(inherited) armv7","EXCLUDED_ARCHS[sdk=iphonesimulator*]":"$(inherited) i386","FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios/Flutter.xcframework/ios-arm64\" $(inherited)","FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios/Flutter.xcframework/ios-arm64_x86_64-simulator\" $(inherited)","GCC_PREFIX_HEADER":"Target Support Files/fluttertoast/fluttertoast-prefix.pch","GENERATE_INFOPLIST_FILE":"NO","INFOPLIST_FILE":"Target Support Files/fluttertoast/fluttertoast-Info.plist","INSTALL_PATH":"$(LOCAL_LIBRARY_DIR)/Frameworks","LD_RUNPATH_SEARCH_PATHS":"$(inherited) @executable_path/Frameworks @loader_path/Frameworks","MODULEMAP_FILE":"Target Support Files/fluttertoast/fluttertoast.modulemap","ONLY_ACTIVE_ARCH":"NO","OTHER_LDFLAGS":"$(inherited) -framework Flutter","PRODUCT_MODULE_NAME":"fluttertoast","PRODUCT_NAME":"fluttertoast","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","SWIFT_ACTIVE_COMPILATION_CONDITIONS":"$(inherited) ","SWIFT_INSTALL_OBJC_HEADER":"YES","SWIFT_VERSION":"5.0","TARGETED_DEVICE_FAMILY":"1,2","VALID_ARCHS[sdk=iphonesimulator*]":"$(ARCHS_STANDARD)","VERSIONING_SYSTEM":"apple-generic","VERSION_INFO_PREFIX":""},"guid":"bfdfe7dc352907fc980b868725387e980d95e38372e14dc164189e9e39c87ca3","name":"Debug"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e9852dc1371d317d5fc535ff1f306279566","buildSettings":{"CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER":"NO","CODE_SIGN_IDENTITY[sdk=appletvos*]":"","CODE_SIGN_IDENTITY[sdk=iphoneos*]":"","CODE_SIGN_IDENTITY[sdk=watchos*]":"","CURRENT_PROJECT_VERSION":"1","DYLIB_COMPATIBILITY_VERSION":"1","DYLIB_CURRENT_VERSION":"1","DYLIB_INSTALL_NAME_BASE":"@rpath","ENABLE_BITCODE":"NO","ENABLE_MODULE_VERIFIER":"NO","ENABLE_USER_SCRIPT_SANDBOXING":"NO","EXCLUDED_ARCHS[sdk=iphoneos*]":"$(inherited) armv7","EXCLUDED_ARCHS[sdk=iphonesimulator*]":"$(inherited) i386","FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios-release/Flutter.xcframework/ios-arm64\" $(inherited)","FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios-release/Flutter.xcframework/ios-arm64_x86_64-simulator\" $(inherited)","GCC_PREFIX_HEADER":"Target Support Files/fluttertoast/fluttertoast-prefix.pch","GENERATE_INFOPLIST_FILE":"NO","INFOPLIST_FILE":"Target Support Files/fluttertoast/fluttertoast-Info.plist","INSTALL_PATH":"$(LOCAL_LIBRARY_DIR)/Frameworks","LD_RUNPATH_SEARCH_PATHS":"$(inherited) @executable_path/Frameworks @loader_path/Frameworks","MODULEMAP_FILE":"Target Support Files/fluttertoast/fluttertoast.modulemap","OTHER_LDFLAGS":"$(inherited) -framework Flutter","PRODUCT_MODULE_NAME":"fluttertoast","PRODUCT_NAME":"fluttertoast","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","SWIFT_ACTIVE_COMPILATION_CONDITIONS":"$(inherited) ","SWIFT_INSTALL_OBJC_HEADER":"YES","SWIFT_VERSION":"5.0","TARGETED_DEVICE_FAMILY":"1,2","VALIDATE_PRODUCT":"YES","VALID_ARCHS[sdk=iphonesimulator*]":"$(ARCHS_STANDARD)","VERSIONING_SYSTEM":"apple-generic","VERSION_INFO_PREFIX":""},"guid":"bfdfe7dc352907fc980b868725387e980c7da66ee29e77cf7e3c5ef7b6bf0505","name":"Profile"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e9852dc1371d317d5fc535ff1f306279566","buildSettings":{"CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER":"NO","CODE_SIGN_IDENTITY[sdk=appletvos*]":"","CODE_SIGN_IDENTITY[sdk=iphoneos*]":"","CODE_SIGN_IDENTITY[sdk=watchos*]":"","CURRENT_PROJECT_VERSION":"1","DYLIB_COMPATIBILITY_VERSION":"1","DYLIB_CURRENT_VERSION":"1","DYLIB_INSTALL_NAME_BASE":"@rpath","ENABLE_BITCODE":"NO","ENABLE_MODULE_VERIFIER":"NO","ENABLE_USER_SCRIPT_SANDBOXING":"NO","EXCLUDED_ARCHS[sdk=iphoneos*]":"$(inherited) armv7","EXCLUDED_ARCHS[sdk=iphonesimulator*]":"$(inherited) i386","FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios-release/Flutter.xcframework/ios-arm64\" $(inherited)","FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios-release/Flutter.xcframework/ios-arm64_x86_64-simulator\" $(inherited)","GCC_PREFIX_HEADER":"Target Support Files/fluttertoast/fluttertoast-prefix.pch","GENERATE_INFOPLIST_FILE":"NO","INFOPLIST_FILE":"Target Support Files/fluttertoast/fluttertoast-Info.plist","INSTALL_PATH":"$(LOCAL_LIBRARY_DIR)/Frameworks","LD_RUNPATH_SEARCH_PATHS":"$(inherited) @executable_path/Frameworks @loader_path/Frameworks","MODULEMAP_FILE":"Target Support Files/fluttertoast/fluttertoast.modulemap","OTHER_LDFLAGS":"$(inherited) -framework Flutter","PRODUCT_MODULE_NAME":"fluttertoast","PRODUCT_NAME":"fluttertoast","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","SWIFT_ACTIVE_COMPILATION_CONDITIONS":"$(inherited) ","SWIFT_INSTALL_OBJC_HEADER":"YES","SWIFT_VERSION":"5.0","TARGETED_DEVICE_FAMILY":"1,2","VALIDATE_PRODUCT":"YES","VALID_ARCHS[sdk=iphonesimulator*]":"$(ARCHS_STANDARD)","VERSIONING_SYSTEM":"apple-generic","VERSION_INFO_PREFIX":""},"guid":"bfdfe7dc352907fc980b868725387e985d57597ee80c97031b19d4dd216a0459","name":"Release"}],"buildPhases":[{"buildFiles":[{"fileReference":"bfdfe7dc352907fc980b868725387e983b44f07e560c85607ecdbac390035690","guid":"bfdfe7dc352907fc980b868725387e9898803a5367f403dbe7d7f50e52e158e4","headerVisibility":"public"},{"fileReference":"bfdfe7dc352907fc980b868725387e988ce5db321c5b1a0e8d45a2033460a820","guid":"bfdfe7dc352907fc980b868725387e983964f34a71d25e0ad408764637201730","headerVisibility":"public"},{"fileReference":"bfdfe7dc352907fc980b868725387e9810650f30d25a1a650eb486810140f78d","guid":"bfdfe7dc352907fc980b868725387e98c8914a1d8083fd11e9c788dbae30cb4b","headerVisibility":"public"}],"guid":"bfdfe7dc352907fc980b868725387e98f9f50c0f44c9e9758a8d2da9a3e9486d","type":"com.apple.buildphase.headers"},{"buildFiles":[{"fileReference":"bfdfe7dc352907fc980b868725387e98000117cc7e8ad3178027b29f7f6baa74","guid":"bfdfe7dc352907fc980b868725387e98732bda2bf98a69eea7b638ba5caac9e6"},{"additionalCompilerOptions":"-DOS_OBJECT_USE_OBJC=0","fileReference":"bfdfe7dc352907fc980b868725387e987d8dc557a1cefbf1c0572194540f3c91","guid":"bfdfe7dc352907fc980b868725387e98c7baa8b56c358501b9b804d1da3607c1"},{"additionalCompilerOptions":"-DOS_OBJECT_USE_OBJC=0","fileReference":"bfdfe7dc352907fc980b868725387e98be100717715b68a43bd8a6ee4411da5c","guid":"bfdfe7dc352907fc980b868725387e98434a59f227df2853d124b2eb53dbd773"}],"guid":"bfdfe7dc352907fc980b868725387e98ff7ff0914d28d25b338598e51f35a22a","type":"com.apple.buildphase.sources"},{"buildFiles":[{"fileReference":"bfdfe7dc352907fc980b868725387e9867aa7825f197b5c58a57320b4ccdc64e","guid":"bfdfe7dc352907fc980b868725387e98fb70b41caaa71fca49a76d4a80225131"}],"guid":"bfdfe7dc352907fc980b868725387e9893a2f3917413e2f83f099b893b6202f2","type":"com.apple.buildphase.frameworks"},{"buildFiles":[{"guid":"bfdfe7dc352907fc980b868725387e982a8b2134dd93f2cb1d1331e935303944","targetReference":"bfdfe7dc352907fc980b868725387e985739272bce418ef50bd06c859612bad5"}],"guid":"bfdfe7dc352907fc980b868725387e98678ff57194ccd7dfda00aac2582b17b5","type":"com.apple.buildphase.resources"}],"buildRules":[],"dependencies":[{"guid":"bfdfe7dc352907fc980b868725387e989da425bb6d6d5d8dbb95e4afffb82217","name":"Flutter"},{"guid":"bfdfe7dc352907fc980b868725387e985739272bce418ef50bd06c859612bad5","name":"fluttertoast-fluttertoast_privacy"}],"guid":"bfdfe7dc352907fc980b868725387e98839a1650b1f10605b2db52456c9e6468","name":"fluttertoast","predominantSourceCodeLanguage":"Xcode.SourceCodeLanguage.Objective-C","productReference":{"guid":"bfdfe7dc352907fc980b868725387e98f09a1b962c84d31b7bec2ec6176b5c98","name":"fluttertoast.framework","type":"product"},"productTypeIdentifier":"com.apple.product-type.framework","provisioningSourceData":[{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Debug","provisioningStyle":1},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Profile","provisioningStyle":1},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Release","provisioningStyle":1}],"type":"standard"}  
1 -{"buildConfigurations":[{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e98bef0d6c2c15f5aafe14dc460dedf3fd4","buildSettings":{"CLANG_ENABLE_OBJC_WEAK":"NO","CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER":"NO","CODE_SIGN_IDENTITY[sdk=appletvos*]":"","CODE_SIGN_IDENTITY[sdk=iphoneos*]":"","CODE_SIGN_IDENTITY[sdk=watchos*]":"","CURRENT_PROJECT_VERSION":"1","DEFINES_MODULE":"YES","DYLIB_COMPATIBILITY_VERSION":"1","DYLIB_CURRENT_VERSION":"1","DYLIB_INSTALL_NAME_BASE":"@rpath","ENABLE_BITCODE":"NO","ENABLE_MODULE_VERIFIER":"NO","ENABLE_USER_SCRIPT_SANDBOXING":"NO","EXCLUDED_ARCHS[sdk=iphoneos*]":"$(inherited) armv7","EXCLUDED_ARCHS[sdk=iphonesimulator*]":"$(inherited) i386","FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios/Flutter.xcframework/ios-arm64\" $(inherited)","FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios/Flutter.xcframework/ios-arm64_x86_64-simulator\" $(inherited)","GCC_PREFIX_HEADER":"Target Support Files/image_cropper/image_cropper-prefix.pch","GENERATE_INFOPLIST_FILE":"NO","INFOPLIST_FILE":"Target Support Files/image_cropper/image_cropper-Info.plist","INSTALL_PATH":"$(LOCAL_LIBRARY_DIR)/Frameworks","LD_RUNPATH_SEARCH_PATHS":"$(inherited) @executable_path/Frameworks @loader_path/Frameworks","MODULEMAP_FILE":"Target Support Files/image_cropper/image_cropper.modulemap","ONLY_ACTIVE_ARCH":"NO","OTHER_LDFLAGS":"$(inherited) -framework Flutter","PRODUCT_MODULE_NAME":"image_cropper","PRODUCT_NAME":"image_cropper","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","SWIFT_ACTIVE_COMPILATION_CONDITIONS":"$(inherited) ","SWIFT_INSTALL_OBJC_HEADER":"YES","SWIFT_VERSION":"5.0","TARGETED_DEVICE_FAMILY":"1,2","VALID_ARCHS[sdk=iphonesimulator*]":"$(ARCHS_STANDARD)","VERSIONING_SYSTEM":"apple-generic","VERSION_INFO_PREFIX":""},"guid":"bfdfe7dc352907fc980b868725387e98f7b93ecdbd3c8b9ea5616aa7b0d3fe18","name":"Debug"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e980fd9e2f1733e15caec480c108e2f6d49","buildSettings":{"CLANG_ENABLE_OBJC_WEAK":"NO","CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER":"NO","CODE_SIGN_IDENTITY[sdk=appletvos*]":"","CODE_SIGN_IDENTITY[sdk=iphoneos*]":"","CODE_SIGN_IDENTITY[sdk=watchos*]":"","CURRENT_PROJECT_VERSION":"1","DEFINES_MODULE":"YES","DYLIB_COMPATIBILITY_VERSION":"1","DYLIB_CURRENT_VERSION":"1","DYLIB_INSTALL_NAME_BASE":"@rpath","ENABLE_BITCODE":"NO","ENABLE_MODULE_VERIFIER":"NO","ENABLE_USER_SCRIPT_SANDBOXING":"NO","EXCLUDED_ARCHS[sdk=iphoneos*]":"$(inherited) armv7","EXCLUDED_ARCHS[sdk=iphonesimulator*]":"$(inherited) i386","FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios-release/Flutter.xcframework/ios-arm64\" $(inherited)","FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios-release/Flutter.xcframework/ios-arm64_x86_64-simulator\" $(inherited)","GCC_PREFIX_HEADER":"Target Support Files/image_cropper/image_cropper-prefix.pch","GENERATE_INFOPLIST_FILE":"NO","INFOPLIST_FILE":"Target Support Files/image_cropper/image_cropper-Info.plist","INSTALL_PATH":"$(LOCAL_LIBRARY_DIR)/Frameworks","LD_RUNPATH_SEARCH_PATHS":"$(inherited) @executable_path/Frameworks @loader_path/Frameworks","MODULEMAP_FILE":"Target Support Files/image_cropper/image_cropper.modulemap","OTHER_LDFLAGS":"$(inherited) -framework Flutter","PRODUCT_MODULE_NAME":"image_cropper","PRODUCT_NAME":"image_cropper","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","SWIFT_ACTIVE_COMPILATION_CONDITIONS":"$(inherited) ","SWIFT_INSTALL_OBJC_HEADER":"YES","SWIFT_VERSION":"5.0","TARGETED_DEVICE_FAMILY":"1,2","VALIDATE_PRODUCT":"YES","VALID_ARCHS[sdk=iphonesimulator*]":"$(ARCHS_STANDARD)","VERSIONING_SYSTEM":"apple-generic","VERSION_INFO_PREFIX":""},"guid":"bfdfe7dc352907fc980b868725387e98f138ec1c7959dd17e955c99842ba6cd3","name":"Profile"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e980fd9e2f1733e15caec480c108e2f6d49","buildSettings":{"CLANG_ENABLE_OBJC_WEAK":"NO","CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER":"NO","CODE_SIGN_IDENTITY[sdk=appletvos*]":"","CODE_SIGN_IDENTITY[sdk=iphoneos*]":"","CODE_SIGN_IDENTITY[sdk=watchos*]":"","CURRENT_PROJECT_VERSION":"1","DEFINES_MODULE":"YES","DYLIB_COMPATIBILITY_VERSION":"1","DYLIB_CURRENT_VERSION":"1","DYLIB_INSTALL_NAME_BASE":"@rpath","ENABLE_BITCODE":"NO","ENABLE_MODULE_VERIFIER":"NO","ENABLE_USER_SCRIPT_SANDBOXING":"NO","EXCLUDED_ARCHS[sdk=iphoneos*]":"$(inherited) armv7","EXCLUDED_ARCHS[sdk=iphonesimulator*]":"$(inherited) i386","FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios-release/Flutter.xcframework/ios-arm64\" $(inherited)","FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios-release/Flutter.xcframework/ios-arm64_x86_64-simulator\" $(inherited)","GCC_PREFIX_HEADER":"Target Support Files/image_cropper/image_cropper-prefix.pch","GENERATE_INFOPLIST_FILE":"NO","INFOPLIST_FILE":"Target Support Files/image_cropper/image_cropper-Info.plist","INSTALL_PATH":"$(LOCAL_LIBRARY_DIR)/Frameworks","LD_RUNPATH_SEARCH_PATHS":"$(inherited) @executable_path/Frameworks @loader_path/Frameworks","MODULEMAP_FILE":"Target Support Files/image_cropper/image_cropper.modulemap","OTHER_LDFLAGS":"$(inherited) -framework Flutter","PRODUCT_MODULE_NAME":"image_cropper","PRODUCT_NAME":"image_cropper","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","SWIFT_ACTIVE_COMPILATION_CONDITIONS":"$(inherited) ","SWIFT_INSTALL_OBJC_HEADER":"YES","SWIFT_VERSION":"5.0","TARGETED_DEVICE_FAMILY":"1,2","VALIDATE_PRODUCT":"YES","VALID_ARCHS[sdk=iphonesimulator*]":"$(ARCHS_STANDARD)","VERSIONING_SYSTEM":"apple-generic","VERSION_INFO_PREFIX":""},"guid":"bfdfe7dc352907fc980b868725387e9822ce90530c07c0eef19816e1846a2b47","name":"Release"}],"buildPhases":[{"buildFiles":[{"fileReference":"bfdfe7dc352907fc980b868725387e988def5567fb619d818c0e4033c07da2d0","guid":"bfdfe7dc352907fc980b868725387e983cd18188c90960b70b25f90c0640bc2e","headerVisibility":"public"},{"fileReference":"bfdfe7dc352907fc980b868725387e9849e25a833cb0bed5dc8ebb5539d6cb74","guid":"bfdfe7dc352907fc980b868725387e9835ba3c68c353baaaaf8a192693f9fb9c","headerVisibility":"public"}],"guid":"bfdfe7dc352907fc980b868725387e9872651d2c8d8c194c061f4d51d19b24d0","type":"com.apple.buildphase.headers"},{"buildFiles":[{"fileReference":"bfdfe7dc352907fc980b868725387e98e9ae364119d4ded1be782c9c2027f874","guid":"bfdfe7dc352907fc980b868725387e98fac879e253c603d20d42aefd7eba7e0c"},{"fileReference":"bfdfe7dc352907fc980b868725387e98c3a32b479b99fa0be5118bc2e4f2256c","guid":"bfdfe7dc352907fc980b868725387e98a90eca3f4ef58020f17eff6ee8594ca3"}],"guid":"bfdfe7dc352907fc980b868725387e984a515ab06e514badd4270f0dcfa41726","type":"com.apple.buildphase.sources"},{"buildFiles":[{"fileReference":"bfdfe7dc352907fc980b868725387e9867aa7825f197b5c58a57320b4ccdc64e","guid":"bfdfe7dc352907fc980b868725387e983584573e884ecb062bea67dd4b38239e"}],"guid":"bfdfe7dc352907fc980b868725387e988219f27d7669f834e95ed895d1bd8d70","type":"com.apple.buildphase.frameworks"},{"buildFiles":[],"guid":"bfdfe7dc352907fc980b868725387e9811cdaaa9080a7ba3ac6ee0e4bf44298c","type":"com.apple.buildphase.resources"}],"buildRules":[],"dependencies":[{"guid":"bfdfe7dc352907fc980b868725387e989da425bb6d6d5d8dbb95e4afffb82217","name":"Flutter"},{"guid":"bfdfe7dc352907fc980b868725387e987a4af56e2729cecfad7b13d62a9a5fa4","name":"TOCropViewController"}],"guid":"bfdfe7dc352907fc980b868725387e98c7508c3a173f39338f076ef697b954c4","name":"image_cropper","predominantSourceCodeLanguage":"Xcode.SourceCodeLanguage.Objective-C","productReference":{"guid":"bfdfe7dc352907fc980b868725387e98af2ff58bf1e7988af36cadaf5bb3d25c","name":"image_cropper.framework","type":"product"},"productTypeIdentifier":"com.apple.product-type.framework","provisioningSourceData":[{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Debug","provisioningStyle":1},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Profile","provisioningStyle":1},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Release","provisioningStyle":1}],"type":"standard"}  
1 -{"buildConfigurations":[{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e98c9406d4edd5339dd20198a367c290d36","buildSettings":{"CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/path_provider_foundation","EXPANDED_CODE_SIGN_IDENTITY":"-","IBSC_MODULE":"path_provider_foundation","INFOPLIST_FILE":"Target Support Files/path_provider_foundation/ResourceBundle-path_provider_foundation_privacy-path_provider_foundation-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"12.0","ONLY_ACTIVE_ARCH":"NO","PRODUCT_NAME":"path_provider_foundation_privacy","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e9815d476a49b818ac83bb7d89c034bc7b7","name":"Debug"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e988fe63e2e9f76f78e56562689e1d41ffe","buildSettings":{"CLANG_ENABLE_OBJC_WEAK":"NO","CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/path_provider_foundation","EXPANDED_CODE_SIGN_IDENTITY":"-","IBSC_MODULE":"path_provider_foundation","INFOPLIST_FILE":"Target Support Files/path_provider_foundation/ResourceBundle-path_provider_foundation_privacy-path_provider_foundation-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"12.0","PRODUCT_NAME":"path_provider_foundation_privacy","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","VALIDATE_PRODUCT":"YES","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e981373391d97c6cdcaed1361cf95934c31","name":"Profile"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e988fe63e2e9f76f78e56562689e1d41ffe","buildSettings":{"CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/path_provider_foundation","EXPANDED_CODE_SIGN_IDENTITY":"-","IBSC_MODULE":"path_provider_foundation","INFOPLIST_FILE":"Target Support Files/path_provider_foundation/ResourceBundle-path_provider_foundation_privacy-path_provider_foundation-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"12.0","PRODUCT_NAME":"path_provider_foundation_privacy","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e98652057b55c4e6ac5e390712a0bc77086","name":"Release"}],"buildPhases":[{"buildFiles":[],"guid":"bfdfe7dc352907fc980b868725387e984823a2e0fba92681cf7792666b9bb36b","type":"com.apple.buildphase.sources"},{"buildFiles":[],"guid":"bfdfe7dc352907fc980b868725387e980148385ae73e13be88316704eda5e242","type":"com.apple.buildphase.frameworks"},{"buildFiles":[{"fileReference":"bfdfe7dc352907fc980b868725387e9889c48add7124ee091ff93ea9433486b7","guid":"bfdfe7dc352907fc980b868725387e98a792d5c00bccb4df88a188da3006a680"}],"guid":"bfdfe7dc352907fc980b868725387e98ebb3c9b4117be3b1e5bd198bd9957243","type":"com.apple.buildphase.resources"}],"buildRules":[],"dependencies":[],"guid":"bfdfe7dc352907fc980b868725387e987ea64ee8d53085bf9edd1a57aaf8cbb5","name":"path_provider_foundation-path_provider_foundation_privacy","productReference":{"guid":"bfdfe7dc352907fc980b868725387e986e649604f74c414a7c2dbe5ef4cc4e75","name":"path_provider_foundation_privacy.bundle","type":"product"},"productTypeIdentifier":"com.apple.product-type.bundle","provisioningSourceData":[{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Debug","provisioningStyle":0},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Profile","provisioningStyle":0},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Release","provisioningStyle":0}],"type":"standard"}  
1 -{"buildConfigurations":[{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e9850cc7fc2d23136fb4fac488d6c47df20","buildSettings":{"ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES":"NO","CLANG_ENABLE_OBJC_WEAK":"NO","CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER":"NO","CODE_SIGN_IDENTITY[sdk=appletvos*]":"","CODE_SIGN_IDENTITY[sdk=iphoneos*]":"","CODE_SIGN_IDENTITY[sdk=watchos*]":"","CURRENT_PROJECT_VERSION":"1","DEFINES_MODULE":"YES","DYLIB_COMPATIBILITY_VERSION":"1","DYLIB_CURRENT_VERSION":"1","DYLIB_INSTALL_NAME_BASE":"@rpath","ENABLE_BITCODE":"NO","ENABLE_MODULE_VERIFIER":"NO","ENABLE_USER_SCRIPT_SANDBOXING":"NO","EXCLUDED_ARCHS[sdk=iphoneos*]":"$(inherited) armv7","EXCLUDED_ARCHS[sdk=iphonesimulator*]":"$(inherited) i386","FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios/Flutter.xcframework/ios-arm64\" $(inherited)","FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios/Flutter.xcframework/ios-arm64_x86_64-simulator\" $(inherited)","INFOPLIST_FILE":"Target Support Files/Pods-Runner/Pods-Runner-Info.plist","INSTALL_PATH":"$(LOCAL_LIBRARY_DIR)/Frameworks","IPHONEOS_DEPLOYMENT_TARGET":"13.0","LD_RUNPATH_SEARCH_PATHS":"$(inherited) @executable_path/Frameworks @loader_path/Frameworks","MACH_O_TYPE":"staticlib","MODULEMAP_FILE":"Target Support Files/Pods-Runner/Pods-Runner.modulemap","ONLY_ACTIVE_ARCH":"NO","OTHER_LDFLAGS":"$(inherited) -framework Flutter","OTHER_LIBTOOLFLAGS":"","PODS_ROOT":"$(SRCROOT)","PRODUCT_BUNDLE_IDENTIFIER":"org.cocoapods.${PRODUCT_NAME:rfc1034identifier}","PRODUCT_NAME":"$(TARGET_NAME:c99extidentifier)","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","VALID_ARCHS[sdk=iphonesimulator*]":"$(ARCHS_STANDARD)","VERSIONING_SYSTEM":"apple-generic","VERSION_INFO_PREFIX":""},"guid":"bfdfe7dc352907fc980b868725387e98a2829366523dfaca9b75e5f7a72f6254","name":"Debug"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e98dc1a21852c7a085c7dd8f65cf0fa9907","buildSettings":{"ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES":"NO","CLANG_ENABLE_OBJC_WEAK":"NO","CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER":"NO","CODE_SIGN_IDENTITY[sdk=appletvos*]":"","CODE_SIGN_IDENTITY[sdk=iphoneos*]":"","CODE_SIGN_IDENTITY[sdk=watchos*]":"","CURRENT_PROJECT_VERSION":"1","DEFINES_MODULE":"YES","DYLIB_COMPATIBILITY_VERSION":"1","DYLIB_CURRENT_VERSION":"1","DYLIB_INSTALL_NAME_BASE":"@rpath","ENABLE_BITCODE":"NO","ENABLE_MODULE_VERIFIER":"NO","ENABLE_USER_SCRIPT_SANDBOXING":"NO","EXCLUDED_ARCHS[sdk=iphoneos*]":"$(inherited) armv7","EXCLUDED_ARCHS[sdk=iphonesimulator*]":"$(inherited) i386","FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios-release/Flutter.xcframework/ios-arm64\" $(inherited)","FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios-release/Flutter.xcframework/ios-arm64_x86_64-simulator\" $(inherited)","INFOPLIST_FILE":"Target Support Files/Pods-Runner/Pods-Runner-Info.plist","INSTALL_PATH":"$(LOCAL_LIBRARY_DIR)/Frameworks","IPHONEOS_DEPLOYMENT_TARGET":"13.0","LD_RUNPATH_SEARCH_PATHS":"$(inherited) @executable_path/Frameworks @loader_path/Frameworks","MACH_O_TYPE":"staticlib","MODULEMAP_FILE":"Target Support Files/Pods-Runner/Pods-Runner.modulemap","OTHER_LDFLAGS":"$(inherited) -framework Flutter","OTHER_LIBTOOLFLAGS":"","PODS_ROOT":"$(SRCROOT)","PRODUCT_BUNDLE_IDENTIFIER":"org.cocoapods.${PRODUCT_NAME:rfc1034identifier}","PRODUCT_NAME":"$(TARGET_NAME:c99extidentifier)","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","VALIDATE_PRODUCT":"YES","VALID_ARCHS[sdk=iphonesimulator*]":"$(ARCHS_STANDARD)","VERSIONING_SYSTEM":"apple-generic","VERSION_INFO_PREFIX":""},"guid":"bfdfe7dc352907fc980b868725387e98e4a12d91909beabfb3ea44357e371c3a","name":"Profile"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e98f17abf55d75f35efcaf45a1185b085b6","buildSettings":{"ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES":"NO","CLANG_ENABLE_OBJC_WEAK":"NO","CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER":"NO","CODE_SIGN_IDENTITY[sdk=appletvos*]":"","CODE_SIGN_IDENTITY[sdk=iphoneos*]":"","CODE_SIGN_IDENTITY[sdk=watchos*]":"","CURRENT_PROJECT_VERSION":"1","DEFINES_MODULE":"YES","DYLIB_COMPATIBILITY_VERSION":"1","DYLIB_CURRENT_VERSION":"1","DYLIB_INSTALL_NAME_BASE":"@rpath","ENABLE_BITCODE":"NO","ENABLE_MODULE_VERIFIER":"NO","ENABLE_USER_SCRIPT_SANDBOXING":"NO","EXCLUDED_ARCHS[sdk=iphoneos*]":"$(inherited) armv7","EXCLUDED_ARCHS[sdk=iphonesimulator*]":"$(inherited) i386","FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios-release/Flutter.xcframework/ios-arm64\" $(inherited)","FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios-release/Flutter.xcframework/ios-arm64_x86_64-simulator\" $(inherited)","INFOPLIST_FILE":"Target Support Files/Pods-Runner/Pods-Runner-Info.plist","INSTALL_PATH":"$(LOCAL_LIBRARY_DIR)/Frameworks","IPHONEOS_DEPLOYMENT_TARGET":"13.0","LD_RUNPATH_SEARCH_PATHS":"$(inherited) @executable_path/Frameworks @loader_path/Frameworks","MACH_O_TYPE":"staticlib","MODULEMAP_FILE":"Target Support Files/Pods-Runner/Pods-Runner.modulemap","OTHER_LDFLAGS":"$(inherited) -framework Flutter","OTHER_LIBTOOLFLAGS":"","PODS_ROOT":"$(SRCROOT)","PRODUCT_BUNDLE_IDENTIFIER":"org.cocoapods.${PRODUCT_NAME:rfc1034identifier}","PRODUCT_NAME":"$(TARGET_NAME:c99extidentifier)","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","VALIDATE_PRODUCT":"YES","VALID_ARCHS[sdk=iphonesimulator*]":"$(ARCHS_STANDARD)","VERSIONING_SYSTEM":"apple-generic","VERSION_INFO_PREFIX":""},"guid":"bfdfe7dc352907fc980b868725387e98cafdf8e5f53f5249fdb699a2c3732041","name":"Release"}],"buildPhases":[{"buildFiles":[{"fileReference":"bfdfe7dc352907fc980b868725387e980ec6fbca7264a6936f2adfc48dd7f5bc","guid":"bfdfe7dc352907fc980b868725387e98c18583e54caccb23480e9ad821fcc5d4","headerVisibility":"public"}],"guid":"bfdfe7dc352907fc980b868725387e982b12e1a9514e59d182b3bdc6513b57e9","type":"com.apple.buildphase.headers"},{"buildFiles":[{"fileReference":"bfdfe7dc352907fc980b868725387e98fed0970e703d355c9aff813f280aafdc","guid":"bfdfe7dc352907fc980b868725387e98d7195027851f4e0b20d9fe9fe9ba555f"}],"guid":"bfdfe7dc352907fc980b868725387e98913f65d029169dd43df72f5d47591332","type":"com.apple.buildphase.sources"},{"buildFiles":[{"fileReference":"bfdfe7dc352907fc980b868725387e9867aa7825f197b5c58a57320b4ccdc64e","guid":"bfdfe7dc352907fc980b868725387e981d396859bc3fe6a005f0edb170134b5c"}],"guid":"bfdfe7dc352907fc980b868725387e9826f150e187da19c7d1e421741141421b","type":"com.apple.buildphase.frameworks"},{"buildFiles":[],"guid":"bfdfe7dc352907fc980b868725387e98be276f630606ffe5c387e92a6079d1a6","type":"com.apple.buildphase.resources"}],"buildRules":[],"dependencies":[{"guid":"bfdfe7dc352907fc980b868725387e989da425bb6d6d5d8dbb95e4afffb82217","name":"Flutter"},{"guid":"bfdfe7dc352907fc980b868725387e987a4af56e2729cecfad7b13d62a9a5fa4","name":"TOCropViewController"},{"guid":"bfdfe7dc352907fc980b868725387e98839a1650b1f10605b2db52456c9e6468","name":"fluttertoast"},{"guid":"bfdfe7dc352907fc980b868725387e98c7508c3a173f39338f076ef697b954c4","name":"image_cropper"},{"guid":"bfdfe7dc352907fc980b868725387e981f000f066404b97b12e9c4ca84d38d0f","name":"image_picker_ios"},{"guid":"bfdfe7dc352907fc980b868725387e9830037b09fee48cfce1f8562d753688c8","name":"path_provider_foundation"},{"guid":"bfdfe7dc352907fc980b868725387e98ef10255b706f98e1e88fae00855b0968","name":"permission_handler_apple"},{"guid":"bfdfe7dc352907fc980b868725387e9828cab1f188854e0a973e6ff6905c5ffe","name":"shared_preferences_foundation"},{"guid":"bfdfe7dc352907fc980b868725387e981304d3d2169071b3ca365b19f5340b7c","name":"sqflite_darwin"},{"guid":"bfdfe7dc352907fc980b868725387e988efdc4dd0ac29b43123295eca853f4ed","name":"webview_flutter_wkwebview"}],"guid":"bfdfe7dc352907fc980b868725387e98312b4bc59bbbe2c06c205bf4da6737f5","name":"Pods-Runner","predominantSourceCodeLanguage":"Xcode.SourceCodeLanguage.Objective-C","productReference":{"guid":"bfdfe7dc352907fc980b868725387e98699846e06e93b50cafdb00290784c775","name":"Pods_Runner.framework","type":"product"},"productTypeIdentifier":"com.apple.product-type.framework","provisioningSourceData":[{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Debug","provisioningStyle":1},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Profile","provisioningStyle":1},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Release","provisioningStyle":1}],"type":"standard"}  
1 -{"buildConfigurations":[{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e98144cd18850e477837c238075d5256ffe","buildSettings":{"ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES":"NO","CLANG_ENABLE_OBJC_WEAK":"NO","CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER":"NO","CODE_SIGN_IDENTITY[sdk=appletvos*]":"","CODE_SIGN_IDENTITY[sdk=iphoneos*]":"","CODE_SIGN_IDENTITY[sdk=watchos*]":"","CURRENT_PROJECT_VERSION":"1","DEFINES_MODULE":"YES","DYLIB_COMPATIBILITY_VERSION":"1","DYLIB_CURRENT_VERSION":"1","DYLIB_INSTALL_NAME_BASE":"@rpath","ENABLE_BITCODE":"NO","ENABLE_MODULE_VERIFIER":"NO","ENABLE_USER_SCRIPT_SANDBOXING":"NO","EXCLUDED_ARCHS[sdk=iphoneos*]":"$(inherited) armv7","EXCLUDED_ARCHS[sdk=iphonesimulator*]":"$(inherited) i386","FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios/Flutter.xcframework/ios-arm64\" $(inherited)","FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios/Flutter.xcframework/ios-arm64_x86_64-simulator\" $(inherited)","INFOPLIST_FILE":"Target Support Files/Pods-RunnerTests/Pods-RunnerTests-Info.plist","INSTALL_PATH":"$(LOCAL_LIBRARY_DIR)/Frameworks","IPHONEOS_DEPLOYMENT_TARGET":"13.0","LD_RUNPATH_SEARCH_PATHS":"$(inherited) @executable_path/Frameworks @loader_path/Frameworks","MACH_O_TYPE":"staticlib","MODULEMAP_FILE":"Target Support Files/Pods-RunnerTests/Pods-RunnerTests.modulemap","ONLY_ACTIVE_ARCH":"NO","OTHER_LDFLAGS":"$(inherited) -framework Flutter","OTHER_LIBTOOLFLAGS":"","PODS_ROOT":"$(SRCROOT)","PRODUCT_BUNDLE_IDENTIFIER":"org.cocoapods.${PRODUCT_NAME:rfc1034identifier}","PRODUCT_NAME":"$(TARGET_NAME:c99extidentifier)","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","VALID_ARCHS[sdk=iphonesimulator*]":"$(ARCHS_STANDARD)","VERSIONING_SYSTEM":"apple-generic","VERSION_INFO_PREFIX":""},"guid":"bfdfe7dc352907fc980b868725387e980029bc42f3dda39154e9cd2e8ce213da","name":"Debug"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e981b663a2c82f0220040296818ba53477e","buildSettings":{"ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES":"NO","CLANG_ENABLE_OBJC_WEAK":"NO","CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER":"NO","CODE_SIGN_IDENTITY[sdk=appletvos*]":"","CODE_SIGN_IDENTITY[sdk=iphoneos*]":"","CODE_SIGN_IDENTITY[sdk=watchos*]":"","CURRENT_PROJECT_VERSION":"1","DEFINES_MODULE":"YES","DYLIB_COMPATIBILITY_VERSION":"1","DYLIB_CURRENT_VERSION":"1","DYLIB_INSTALL_NAME_BASE":"@rpath","ENABLE_BITCODE":"NO","ENABLE_MODULE_VERIFIER":"NO","ENABLE_USER_SCRIPT_SANDBOXING":"NO","EXCLUDED_ARCHS[sdk=iphoneos*]":"$(inherited) armv7","EXCLUDED_ARCHS[sdk=iphonesimulator*]":"$(inherited) i386","FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios-release/Flutter.xcframework/ios-arm64\" $(inherited)","FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios-release/Flutter.xcframework/ios-arm64_x86_64-simulator\" $(inherited)","INFOPLIST_FILE":"Target Support Files/Pods-RunnerTests/Pods-RunnerTests-Info.plist","INSTALL_PATH":"$(LOCAL_LIBRARY_DIR)/Frameworks","IPHONEOS_DEPLOYMENT_TARGET":"13.0","LD_RUNPATH_SEARCH_PATHS":"$(inherited) @executable_path/Frameworks @loader_path/Frameworks","MACH_O_TYPE":"staticlib","MODULEMAP_FILE":"Target Support Files/Pods-RunnerTests/Pods-RunnerTests.modulemap","OTHER_LDFLAGS":"$(inherited) -framework Flutter","OTHER_LIBTOOLFLAGS":"","PODS_ROOT":"$(SRCROOT)","PRODUCT_BUNDLE_IDENTIFIER":"org.cocoapods.${PRODUCT_NAME:rfc1034identifier}","PRODUCT_NAME":"$(TARGET_NAME:c99extidentifier)","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","VALIDATE_PRODUCT":"YES","VALID_ARCHS[sdk=iphonesimulator*]":"$(ARCHS_STANDARD)","VERSIONING_SYSTEM":"apple-generic","VERSION_INFO_PREFIX":""},"guid":"bfdfe7dc352907fc980b868725387e98d15fe13ffb666b223bfd6ee9f0a6138e","name":"Profile"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e98965b92d39d30a7872295adc2841cd1b1","buildSettings":{"ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES":"NO","CLANG_ENABLE_OBJC_WEAK":"NO","CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER":"NO","CODE_SIGN_IDENTITY[sdk=appletvos*]":"","CODE_SIGN_IDENTITY[sdk=iphoneos*]":"","CODE_SIGN_IDENTITY[sdk=watchos*]":"","CURRENT_PROJECT_VERSION":"1","DEFINES_MODULE":"YES","DYLIB_COMPATIBILITY_VERSION":"1","DYLIB_CURRENT_VERSION":"1","DYLIB_INSTALL_NAME_BASE":"@rpath","ENABLE_BITCODE":"NO","ENABLE_MODULE_VERIFIER":"NO","ENABLE_USER_SCRIPT_SANDBOXING":"NO","EXCLUDED_ARCHS[sdk=iphoneos*]":"$(inherited) armv7","EXCLUDED_ARCHS[sdk=iphonesimulator*]":"$(inherited) i386","FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios-release/Flutter.xcframework/ios-arm64\" $(inherited)","FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios-release/Flutter.xcframework/ios-arm64_x86_64-simulator\" $(inherited)","INFOPLIST_FILE":"Target Support Files/Pods-RunnerTests/Pods-RunnerTests-Info.plist","INSTALL_PATH":"$(LOCAL_LIBRARY_DIR)/Frameworks","IPHONEOS_DEPLOYMENT_TARGET":"13.0","LD_RUNPATH_SEARCH_PATHS":"$(inherited) @executable_path/Frameworks @loader_path/Frameworks","MACH_O_TYPE":"staticlib","MODULEMAP_FILE":"Target Support Files/Pods-RunnerTests/Pods-RunnerTests.modulemap","OTHER_LDFLAGS":"$(inherited) -framework Flutter","OTHER_LIBTOOLFLAGS":"","PODS_ROOT":"$(SRCROOT)","PRODUCT_BUNDLE_IDENTIFIER":"org.cocoapods.${PRODUCT_NAME:rfc1034identifier}","PRODUCT_NAME":"$(TARGET_NAME:c99extidentifier)","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","VALIDATE_PRODUCT":"YES","VALID_ARCHS[sdk=iphonesimulator*]":"$(ARCHS_STANDARD)","VERSIONING_SYSTEM":"apple-generic","VERSION_INFO_PREFIX":""},"guid":"bfdfe7dc352907fc980b868725387e98d4a36e40c823f266ea5f9d0711ed6df0","name":"Release"}],"buildPhases":[{"buildFiles":[{"fileReference":"bfdfe7dc352907fc980b868725387e98e5e8bcdff29e5f8321be18f7989b4bc7","guid":"bfdfe7dc352907fc980b868725387e98ca9af5e2c54f437f9ebb0c203883ccae","headerVisibility":"public"}],"guid":"bfdfe7dc352907fc980b868725387e986e6b8bd91d07f2fb082ccd84c7dcacb1","type":"com.apple.buildphase.headers"},{"buildFiles":[{"fileReference":"bfdfe7dc352907fc980b868725387e98022654f1ff78dd844d694dba2439dab2","guid":"bfdfe7dc352907fc980b868725387e9881f185e1672aa83b98d6e30b47f8f468"}],"guid":"bfdfe7dc352907fc980b868725387e98de09b1176c796343f1f9bcd422c73402","type":"com.apple.buildphase.sources"},{"buildFiles":[{"fileReference":"bfdfe7dc352907fc980b868725387e9867aa7825f197b5c58a57320b4ccdc64e","guid":"bfdfe7dc352907fc980b868725387e98e7ac2b91ee49764a75561cf994247683"}],"guid":"bfdfe7dc352907fc980b868725387e983bb5c38e7891bdb262f8e050f7d97030","type":"com.apple.buildphase.frameworks"},{"buildFiles":[],"guid":"bfdfe7dc352907fc980b868725387e987fddc24c35656402341de288e0688015","type":"com.apple.buildphase.resources"}],"buildRules":[],"dependencies":[{"guid":"bfdfe7dc352907fc980b868725387e98312b4bc59bbbe2c06c205bf4da6737f5","name":"Pods-Runner"}],"guid":"bfdfe7dc352907fc980b868725387e98483832d3c820398e9d40e1a6904b03fe","name":"Pods-RunnerTests","predominantSourceCodeLanguage":"Xcode.SourceCodeLanguage.Objective-C","productReference":{"guid":"bfdfe7dc352907fc980b868725387e984f9f39caeddf64cc331db2b69d62aa63","name":"Pods_RunnerTests.framework","type":"product"},"productTypeIdentifier":"com.apple.product-type.framework","provisioningSourceData":[{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Debug","provisioningStyle":1},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Profile","provisioningStyle":1},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Release","provisioningStyle":1}],"type":"standard"}  
1 -{"buildConfigurations":[{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e98890adb2b2b98fc70f20de16996216002","buildSettings":{"CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/image_picker_ios","EXPANDED_CODE_SIGN_IDENTITY":"-","IBSC_MODULE":"image_picker_ios","INFOPLIST_FILE":"Target Support Files/image_picker_ios/ResourceBundle-image_picker_ios_privacy-image_picker_ios-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"12.0","ONLY_ACTIVE_ARCH":"NO","PRODUCT_NAME":"image_picker_ios_privacy","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e98c0a44ddda8105286060bf5c6003d30d7","name":"Debug"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e98221c7220f1a43556e154d0e84bf28676","buildSettings":{"CLANG_ENABLE_OBJC_WEAK":"NO","CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/image_picker_ios","EXPANDED_CODE_SIGN_IDENTITY":"-","IBSC_MODULE":"image_picker_ios","INFOPLIST_FILE":"Target Support Files/image_picker_ios/ResourceBundle-image_picker_ios_privacy-image_picker_ios-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"12.0","PRODUCT_NAME":"image_picker_ios_privacy","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","VALIDATE_PRODUCT":"YES","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e986afd31b25e8bdbe54b555b3e819bed9a","name":"Profile"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e98221c7220f1a43556e154d0e84bf28676","buildSettings":{"CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/image_picker_ios","EXPANDED_CODE_SIGN_IDENTITY":"-","IBSC_MODULE":"image_picker_ios","INFOPLIST_FILE":"Target Support Files/image_picker_ios/ResourceBundle-image_picker_ios_privacy-image_picker_ios-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"12.0","PRODUCT_NAME":"image_picker_ios_privacy","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e984409b961219dd5170e42cf8af9d37b85","name":"Release"}],"buildPhases":[{"buildFiles":[],"guid":"bfdfe7dc352907fc980b868725387e98da3c51c4c853664165580f13a6f0fc5c","type":"com.apple.buildphase.sources"},{"buildFiles":[],"guid":"bfdfe7dc352907fc980b868725387e98cf2603f400108d5d689d69e49210f9ea","type":"com.apple.buildphase.frameworks"},{"buildFiles":[{"fileReference":"bfdfe7dc352907fc980b868725387e98d81fa81818b111128bdfcbfe37fe99cc","guid":"bfdfe7dc352907fc980b868725387e986f2cd484effb79da397fd484ac7cefd7"}],"guid":"bfdfe7dc352907fc980b868725387e9848f72b017e196244386c0f13d723c588","type":"com.apple.buildphase.resources"}],"buildRules":[],"dependencies":[],"guid":"bfdfe7dc352907fc980b868725387e98082dc85da1fc941e5234c7cc1f11b27d","name":"image_picker_ios-image_picker_ios_privacy","productReference":{"guid":"bfdfe7dc352907fc980b868725387e98cba567c8a049008de84f093e54e3191c","name":"image_picker_ios_privacy.bundle","type":"product"},"productTypeIdentifier":"com.apple.product-type.bundle","provisioningSourceData":[{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Debug","provisioningStyle":0},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Profile","provisioningStyle":0},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Release","provisioningStyle":0}],"type":"standard"}  
1 -{"buildConfigurations":[{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e989b8b5e6c332d83d94a43e8bb36f14a8b","buildSettings":{"ASSETCATALOG_COMPILER_APPICON_NAME":"AppIcon","ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME":"AccentColor","CLANG_ENABLE_OBJC_WEAK":"NO","ENABLE_USER_SCRIPT_SANDBOXING":"NO","IPHONEOS_DEPLOYMENT_TARGET":"12.0","LD_RUNPATH_SEARCH_PATHS":"$(inherited) @executable_path/Frameworks","ONLY_ACTIVE_ARCH":"NO","SDKROOT":"iphoneos","TARGETED_DEVICE_FAMILY":"1,2"},"guid":"bfdfe7dc352907fc980b868725387e982cf0da236cf10d087750aa1434da9227","name":"Debug"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e98765d02cbdfd89645a23d200ad656f8af","buildSettings":{"ASSETCATALOG_COMPILER_APPICON_NAME":"AppIcon","ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME":"AccentColor","CLANG_ENABLE_OBJC_WEAK":"NO","ENABLE_USER_SCRIPT_SANDBOXING":"NO","IPHONEOS_DEPLOYMENT_TARGET":"12.0","LD_RUNPATH_SEARCH_PATHS":"$(inherited) @executable_path/Frameworks","SDKROOT":"iphoneos","TARGETED_DEVICE_FAMILY":"1,2","VALIDATE_PRODUCT":"YES"},"guid":"bfdfe7dc352907fc980b868725387e98cc28f154213fd8181aa70d4c188a8335","name":"Profile"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e98765d02cbdfd89645a23d200ad656f8af","buildSettings":{"ASSETCATALOG_COMPILER_APPICON_NAME":"AppIcon","ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME":"AccentColor","CLANG_ENABLE_OBJC_WEAK":"NO","ENABLE_USER_SCRIPT_SANDBOXING":"NO","IPHONEOS_DEPLOYMENT_TARGET":"12.0","LD_RUNPATH_SEARCH_PATHS":"$(inherited) @executable_path/Frameworks","SDKROOT":"iphoneos","TARGETED_DEVICE_FAMILY":"1,2","VALIDATE_PRODUCT":"YES"},"guid":"bfdfe7dc352907fc980b868725387e981f19fefc6e52ad9e4e005a2248234387","name":"Release"}],"buildPhases":[],"buildRules":[],"dependencies":[],"guid":"bfdfe7dc352907fc980b868725387e989da425bb6d6d5d8dbb95e4afffb82217","name":"Flutter","provisioningSourceData":[{"bundleIdentifierFromInfoPlist":"","configurationName":"Debug","provisioningStyle":0},{"bundleIdentifierFromInfoPlist":"","configurationName":"Profile","provisioningStyle":0},{"bundleIdentifierFromInfoPlist":"","configurationName":"Release","provisioningStyle":0}],"type":"aggregate"}  
1 -{"buildConfigurations":[{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e98c9406d4edd5339dd20198a367c290d36","buildSettings":{"CLANG_ENABLE_OBJC_WEAK":"NO","CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER":"NO","CODE_SIGN_IDENTITY[sdk=appletvos*]":"","CODE_SIGN_IDENTITY[sdk=iphoneos*]":"","CODE_SIGN_IDENTITY[sdk=watchos*]":"","CURRENT_PROJECT_VERSION":"1","DEFINES_MODULE":"YES","DYLIB_COMPATIBILITY_VERSION":"1","DYLIB_CURRENT_VERSION":"1","DYLIB_INSTALL_NAME_BASE":"@rpath","ENABLE_BITCODE":"NO","ENABLE_MODULE_VERIFIER":"NO","ENABLE_USER_SCRIPT_SANDBOXING":"NO","EXCLUDED_ARCHS[sdk=iphoneos*]":"$(inherited) armv7","EXCLUDED_ARCHS[sdk=iphonesimulator*]":"$(inherited) i386","FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios/Flutter.xcframework/ios-arm64\" $(inherited)","FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios/Flutter.xcframework/ios-arm64_x86_64-simulator\" $(inherited)","GCC_PREFIX_HEADER":"Target Support Files/path_provider_foundation/path_provider_foundation-prefix.pch","GENERATE_INFOPLIST_FILE":"NO","INFOPLIST_FILE":"Target Support Files/path_provider_foundation/path_provider_foundation-Info.plist","INSTALL_PATH":"$(LOCAL_LIBRARY_DIR)/Frameworks","IPHONEOS_DEPLOYMENT_TARGET":"12.0","MODULEMAP_FILE":"Target Support Files/path_provider_foundation/path_provider_foundation.modulemap","ONLY_ACTIVE_ARCH":"NO","OTHER_LDFLAGS":"$(inherited) -framework Flutter","PRODUCT_MODULE_NAME":"path_provider_foundation","PRODUCT_NAME":"path_provider_foundation","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","SWIFT_ACTIVE_COMPILATION_CONDITIONS":"$(inherited) ","SWIFT_INSTALL_OBJC_HEADER":"YES","SWIFT_VERSION":"5.0","TARGETED_DEVICE_FAMILY":"1,2","VALID_ARCHS[sdk=iphonesimulator*]":"$(ARCHS_STANDARD)","VERSIONING_SYSTEM":"apple-generic","VERSION_INFO_PREFIX":""},"guid":"bfdfe7dc352907fc980b868725387e98ab88586633079f928287f370e8b6f07b","name":"Debug"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e988fe63e2e9f76f78e56562689e1d41ffe","buildSettings":{"CLANG_ENABLE_OBJC_WEAK":"NO","CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER":"NO","CODE_SIGN_IDENTITY[sdk=appletvos*]":"","CODE_SIGN_IDENTITY[sdk=iphoneos*]":"","CODE_SIGN_IDENTITY[sdk=watchos*]":"","CURRENT_PROJECT_VERSION":"1","DEFINES_MODULE":"YES","DYLIB_COMPATIBILITY_VERSION":"1","DYLIB_CURRENT_VERSION":"1","DYLIB_INSTALL_NAME_BASE":"@rpath","ENABLE_BITCODE":"NO","ENABLE_MODULE_VERIFIER":"NO","ENABLE_USER_SCRIPT_SANDBOXING":"NO","EXCLUDED_ARCHS[sdk=iphoneos*]":"$(inherited) armv7","EXCLUDED_ARCHS[sdk=iphonesimulator*]":"$(inherited) i386","FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios-release/Flutter.xcframework/ios-arm64\" $(inherited)","FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios-release/Flutter.xcframework/ios-arm64_x86_64-simulator\" $(inherited)","GCC_PREFIX_HEADER":"Target Support Files/path_provider_foundation/path_provider_foundation-prefix.pch","GENERATE_INFOPLIST_FILE":"NO","INFOPLIST_FILE":"Target Support Files/path_provider_foundation/path_provider_foundation-Info.plist","INSTALL_PATH":"$(LOCAL_LIBRARY_DIR)/Frameworks","IPHONEOS_DEPLOYMENT_TARGET":"12.0","MODULEMAP_FILE":"Target Support Files/path_provider_foundation/path_provider_foundation.modulemap","OTHER_LDFLAGS":"$(inherited) -framework Flutter","PRODUCT_MODULE_NAME":"path_provider_foundation","PRODUCT_NAME":"path_provider_foundation","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","SWIFT_ACTIVE_COMPILATION_CONDITIONS":"$(inherited) ","SWIFT_INSTALL_OBJC_HEADER":"YES","SWIFT_VERSION":"5.0","TARGETED_DEVICE_FAMILY":"1,2","VALIDATE_PRODUCT":"YES","VALID_ARCHS[sdk=iphonesimulator*]":"$(ARCHS_STANDARD)","VERSIONING_SYSTEM":"apple-generic","VERSION_INFO_PREFIX":""},"guid":"bfdfe7dc352907fc980b868725387e9880f884b2537bd891ed54ff6e3ab7d0ee","name":"Profile"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e988fe63e2e9f76f78e56562689e1d41ffe","buildSettings":{"CLANG_ENABLE_OBJC_WEAK":"NO","CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER":"NO","CODE_SIGN_IDENTITY[sdk=appletvos*]":"","CODE_SIGN_IDENTITY[sdk=iphoneos*]":"","CODE_SIGN_IDENTITY[sdk=watchos*]":"","CURRENT_PROJECT_VERSION":"1","DEFINES_MODULE":"YES","DYLIB_COMPATIBILITY_VERSION":"1","DYLIB_CURRENT_VERSION":"1","DYLIB_INSTALL_NAME_BASE":"@rpath","ENABLE_BITCODE":"NO","ENABLE_MODULE_VERIFIER":"NO","ENABLE_USER_SCRIPT_SANDBOXING":"NO","EXCLUDED_ARCHS[sdk=iphoneos*]":"$(inherited) armv7","EXCLUDED_ARCHS[sdk=iphonesimulator*]":"$(inherited) i386","FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios-release/Flutter.xcframework/ios-arm64\" $(inherited)","FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios-release/Flutter.xcframework/ios-arm64_x86_64-simulator\" $(inherited)","GCC_PREFIX_HEADER":"Target Support Files/path_provider_foundation/path_provider_foundation-prefix.pch","GENERATE_INFOPLIST_FILE":"NO","INFOPLIST_FILE":"Target Support Files/path_provider_foundation/path_provider_foundation-Info.plist","INSTALL_PATH":"$(LOCAL_LIBRARY_DIR)/Frameworks","IPHONEOS_DEPLOYMENT_TARGET":"12.0","MODULEMAP_FILE":"Target Support Files/path_provider_foundation/path_provider_foundation.modulemap","OTHER_LDFLAGS":"$(inherited) -framework Flutter","PRODUCT_MODULE_NAME":"path_provider_foundation","PRODUCT_NAME":"path_provider_foundation","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","SWIFT_ACTIVE_COMPILATION_CONDITIONS":"$(inherited) ","SWIFT_INSTALL_OBJC_HEADER":"YES","SWIFT_VERSION":"5.0","TARGETED_DEVICE_FAMILY":"1,2","VALIDATE_PRODUCT":"YES","VALID_ARCHS[sdk=iphonesimulator*]":"$(ARCHS_STANDARD)","VERSIONING_SYSTEM":"apple-generic","VERSION_INFO_PREFIX":""},"guid":"bfdfe7dc352907fc980b868725387e9858b9d941e76db42d349048c14af0e16e","name":"Release"}],"buildPhases":[{"buildFiles":[{"fileReference":"bfdfe7dc352907fc980b868725387e986ad90640c2a87ccd2504ab539e324d34","guid":"bfdfe7dc352907fc980b868725387e98e40234757d04478dc54a213f59e845fa","headerVisibility":"public"}],"guid":"bfdfe7dc352907fc980b868725387e98450b40315711083d32b0ed949174ff28","type":"com.apple.buildphase.headers"},{"buildFiles":[{"fileReference":"bfdfe7dc352907fc980b868725387e989f750ed9e20f950ada8937f306c31206","guid":"bfdfe7dc352907fc980b868725387e98c025a6cef40a0e1fbdb6dfdf276171ba"},{"fileReference":"bfdfe7dc352907fc980b868725387e980e2570f90a57a95b7bd48b9bbed2305f","guid":"bfdfe7dc352907fc980b868725387e986dfc1b5ca512f6383be32a7124385963"},{"fileReference":"bfdfe7dc352907fc980b868725387e98616486747c74cf21aec11f2de8c74a26","guid":"bfdfe7dc352907fc980b868725387e98651a9c0b966fd508c01d94f4cad81677"}],"guid":"bfdfe7dc352907fc980b868725387e98f5d455158bacea210fd45e1a8f3245fc","type":"com.apple.buildphase.sources"},{"buildFiles":[{"fileReference":"bfdfe7dc352907fc980b868725387e9867aa7825f197b5c58a57320b4ccdc64e","guid":"bfdfe7dc352907fc980b868725387e9829f34398048903731961241124ac546e"}],"guid":"bfdfe7dc352907fc980b868725387e987ebedde198dc993f3ca38aec4ed08768","type":"com.apple.buildphase.frameworks"},{"buildFiles":[{"guid":"bfdfe7dc352907fc980b868725387e98234997a2811e55e2dfc23faf0b9d3093","targetReference":"bfdfe7dc352907fc980b868725387e987ea64ee8d53085bf9edd1a57aaf8cbb5"}],"guid":"bfdfe7dc352907fc980b868725387e98ac45f7d09c5ae0c1d8f7eb8e8ff004ab","type":"com.apple.buildphase.resources"}],"buildRules":[],"dependencies":[{"guid":"bfdfe7dc352907fc980b868725387e989da425bb6d6d5d8dbb95e4afffb82217","name":"Flutter"},{"guid":"bfdfe7dc352907fc980b868725387e987ea64ee8d53085bf9edd1a57aaf8cbb5","name":"path_provider_foundation-path_provider_foundation_privacy"}],"guid":"bfdfe7dc352907fc980b868725387e9830037b09fee48cfce1f8562d753688c8","name":"path_provider_foundation","predominantSourceCodeLanguage":"Xcode.SourceCodeLanguage.Swift","productReference":{"guid":"bfdfe7dc352907fc980b868725387e98177b75fe6f519d73b22b382cca137f1c","name":"path_provider_foundation.framework","type":"product"},"productTypeIdentifier":"com.apple.product-type.framework","provisioningSourceData":[{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Debug","provisioningStyle":1},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Profile","provisioningStyle":1},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Release","provisioningStyle":1}],"type":"standard"}  
1 -{"buildConfigurations":[{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e987429100136c7cabdb1c53ff7846a606f","buildSettings":{"CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/shared_preferences_foundation","EXPANDED_CODE_SIGN_IDENTITY":"-","IBSC_MODULE":"shared_preferences_foundation","INFOPLIST_FILE":"Target Support Files/shared_preferences_foundation/ResourceBundle-shared_preferences_foundation_privacy-shared_preferences_foundation-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"12.0","ONLY_ACTIVE_ARCH":"NO","PRODUCT_NAME":"shared_preferences_foundation_privacy","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e984b0ac60cfbf01a73090074fdbdad02ca","name":"Debug"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e9852aeec4c055e14df0bbd35d7207bef7b","buildSettings":{"CLANG_ENABLE_OBJC_WEAK":"NO","CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/shared_preferences_foundation","EXPANDED_CODE_SIGN_IDENTITY":"-","IBSC_MODULE":"shared_preferences_foundation","INFOPLIST_FILE":"Target Support Files/shared_preferences_foundation/ResourceBundle-shared_preferences_foundation_privacy-shared_preferences_foundation-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"12.0","PRODUCT_NAME":"shared_preferences_foundation_privacy","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","VALIDATE_PRODUCT":"YES","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e98497877ccb057c0b998adcc0f530ed6ce","name":"Profile"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e9852aeec4c055e14df0bbd35d7207bef7b","buildSettings":{"CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/shared_preferences_foundation","EXPANDED_CODE_SIGN_IDENTITY":"-","IBSC_MODULE":"shared_preferences_foundation","INFOPLIST_FILE":"Target Support Files/shared_preferences_foundation/ResourceBundle-shared_preferences_foundation_privacy-shared_preferences_foundation-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"12.0","PRODUCT_NAME":"shared_preferences_foundation_privacy","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e98e4724ec3436be7e4ac6868968ad6eabe","name":"Release"}],"buildPhases":[{"buildFiles":[],"guid":"bfdfe7dc352907fc980b868725387e983798725b834d0f662406381ca7bde3f2","type":"com.apple.buildphase.sources"},{"buildFiles":[],"guid":"bfdfe7dc352907fc980b868725387e98b91701758ca9639610804a99b5398a8d","type":"com.apple.buildphase.frameworks"},{"buildFiles":[{"fileReference":"bfdfe7dc352907fc980b868725387e98a7593e8608d9acecd27fab8927976749","guid":"bfdfe7dc352907fc980b868725387e98ac058063c77726eb1f0b10fdd8be15b5"}],"guid":"bfdfe7dc352907fc980b868725387e9837f959b90bb31b5e696f9a85cb667226","type":"com.apple.buildphase.resources"}],"buildRules":[],"dependencies":[],"guid":"bfdfe7dc352907fc980b868725387e98e0be3b0d5ad56f1985578b1f97431765","name":"shared_preferences_foundation-shared_preferences_foundation_privacy","productReference":{"guid":"bfdfe7dc352907fc980b868725387e98ad625504a4c1e61077bbfd33bd1d1785","name":"shared_preferences_foundation_privacy.bundle","type":"product"},"productTypeIdentifier":"com.apple.product-type.bundle","provisioningSourceData":[{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Debug","provisioningStyle":0},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Profile","provisioningStyle":0},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Release","provisioningStyle":0}],"type":"standard"}  
1 -{"buildConfigurations":[{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e98a6093e67eab0c95af9b59197c88a1b6b","buildSettings":{"CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/permission_handler_apple","EXPANDED_CODE_SIGN_IDENTITY":"-","IBSC_MODULE":"permission_handler_apple","INFOPLIST_FILE":"Target Support Files/permission_handler_apple/ResourceBundle-permission_handler_apple_privacy-permission_handler_apple-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"9.0","ONLY_ACTIVE_ARCH":"NO","PRODUCT_NAME":"permission_handler_apple_privacy","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e98ab85269e3c32dd7d46dc5b2d71a85e10","name":"Debug"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e982824e3afc8d872da1d8489aeef65d25c","buildSettings":{"CLANG_ENABLE_OBJC_WEAK":"NO","CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/permission_handler_apple","EXPANDED_CODE_SIGN_IDENTITY":"-","IBSC_MODULE":"permission_handler_apple","INFOPLIST_FILE":"Target Support Files/permission_handler_apple/ResourceBundle-permission_handler_apple_privacy-permission_handler_apple-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"9.0","PRODUCT_NAME":"permission_handler_apple_privacy","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","VALIDATE_PRODUCT":"YES","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e98339217bba3aa34a14079ebf1ecbb02d9","name":"Profile"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e982824e3afc8d872da1d8489aeef65d25c","buildSettings":{"CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/permission_handler_apple","EXPANDED_CODE_SIGN_IDENTITY":"-","IBSC_MODULE":"permission_handler_apple","INFOPLIST_FILE":"Target Support Files/permission_handler_apple/ResourceBundle-permission_handler_apple_privacy-permission_handler_apple-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"9.0","PRODUCT_NAME":"permission_handler_apple_privacy","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e9848aceabd21d4bd82521339f4bb06e5ef","name":"Release"}],"buildPhases":[{"buildFiles":[],"guid":"bfdfe7dc352907fc980b868725387e9809610ca16e4ec0b8b4d2801aac5247b5","type":"com.apple.buildphase.sources"},{"buildFiles":[],"guid":"bfdfe7dc352907fc980b868725387e98ec495162e4d17b980435a432aa070d1b","type":"com.apple.buildphase.frameworks"},{"buildFiles":[{"fileReference":"bfdfe7dc352907fc980b868725387e983baa8e01f584c554d49e2b2bb7cde084","guid":"bfdfe7dc352907fc980b868725387e98a0381af2bb4814d9d0a8e921781d06fe"}],"guid":"bfdfe7dc352907fc980b868725387e981f36d8e95984def1a3e1adcf78688e0d","type":"com.apple.buildphase.resources"}],"buildRules":[],"dependencies":[],"guid":"bfdfe7dc352907fc980b868725387e9802f35ab680609a626ebd2ddd692a3822","name":"permission_handler_apple-permission_handler_apple_privacy","productReference":{"guid":"bfdfe7dc352907fc980b868725387e983e9a904e8a35cb34b69458780be142b3","name":"permission_handler_apple_privacy.bundle","type":"product"},"productTypeIdentifier":"com.apple.product-type.bundle","provisioningSourceData":[{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Debug","provisioningStyle":0},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Profile","provisioningStyle":0},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Release","provisioningStyle":0}],"type":"standard"}  
1 -{"buildConfigurations":[{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e98e8fb97e4d8fc6b27d73383f393c88ecd","buildSettings":{"CLANG_ENABLE_OBJC_WEAK":"NO","CODE_SIGN_IDENTITY[sdk=appletvos*]":"","CODE_SIGN_IDENTITY[sdk=iphoneos*]":"","CODE_SIGN_IDENTITY[sdk=watchos*]":"","CURRENT_PROJECT_VERSION":"1","DEFINES_MODULE":"YES","DYLIB_COMPATIBILITY_VERSION":"1","DYLIB_CURRENT_VERSION":"1","DYLIB_INSTALL_NAME_BASE":"@rpath","ENABLE_MODULE_VERIFIER":"NO","ENABLE_USER_SCRIPT_SANDBOXING":"NO","GCC_PREFIX_HEADER":"Target Support Files/TOCropViewController/TOCropViewController-prefix.pch","GENERATE_INFOPLIST_FILE":"NO","INFOPLIST_FILE":"Target Support Files/TOCropViewController/TOCropViewController-Info.plist","INSTALL_PATH":"$(LOCAL_LIBRARY_DIR)/Frameworks","IPHONEOS_DEPLOYMENT_TARGET":"11.0","LD_RUNPATH_SEARCH_PATHS":"$(inherited) @executable_path/Frameworks @loader_path/Frameworks","MODULEMAP_FILE":"Target Support Files/TOCropViewController/TOCropViewController.modulemap","ONLY_ACTIVE_ARCH":"NO","PRODUCT_MODULE_NAME":"TOCropViewController","PRODUCT_NAME":"TOCropViewController","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","SWIFT_ACTIVE_COMPILATION_CONDITIONS":"$(inherited) ","SWIFT_INSTALL_OBJC_HEADER":"YES","SWIFT_VERSION":"5.0","TARGETED_DEVICE_FAMILY":"1,2","VERSIONING_SYSTEM":"apple-generic","VERSION_INFO_PREFIX":""},"guid":"bfdfe7dc352907fc980b868725387e98605c35452afc21c9738f0c6828c71d26","name":"Debug"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e98646a08d73cb1b05edde4b2af727d2773","buildSettings":{"CLANG_ENABLE_OBJC_WEAK":"NO","CODE_SIGN_IDENTITY[sdk=appletvos*]":"","CODE_SIGN_IDENTITY[sdk=iphoneos*]":"","CODE_SIGN_IDENTITY[sdk=watchos*]":"","CURRENT_PROJECT_VERSION":"1","DEFINES_MODULE":"YES","DYLIB_COMPATIBILITY_VERSION":"1","DYLIB_CURRENT_VERSION":"1","DYLIB_INSTALL_NAME_BASE":"@rpath","ENABLE_MODULE_VERIFIER":"NO","ENABLE_USER_SCRIPT_SANDBOXING":"NO","GCC_PREFIX_HEADER":"Target Support Files/TOCropViewController/TOCropViewController-prefix.pch","GENERATE_INFOPLIST_FILE":"NO","INFOPLIST_FILE":"Target Support Files/TOCropViewController/TOCropViewController-Info.plist","INSTALL_PATH":"$(LOCAL_LIBRARY_DIR)/Frameworks","IPHONEOS_DEPLOYMENT_TARGET":"11.0","LD_RUNPATH_SEARCH_PATHS":"$(inherited) @executable_path/Frameworks @loader_path/Frameworks","MODULEMAP_FILE":"Target Support Files/TOCropViewController/TOCropViewController.modulemap","PRODUCT_MODULE_NAME":"TOCropViewController","PRODUCT_NAME":"TOCropViewController","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","SWIFT_ACTIVE_COMPILATION_CONDITIONS":"$(inherited) ","SWIFT_INSTALL_OBJC_HEADER":"YES","SWIFT_VERSION":"5.0","TARGETED_DEVICE_FAMILY":"1,2","VALIDATE_PRODUCT":"YES","VERSIONING_SYSTEM":"apple-generic","VERSION_INFO_PREFIX":""},"guid":"bfdfe7dc352907fc980b868725387e988c614f91f9b72052667099c32cbe6637","name":"Profile"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e98646a08d73cb1b05edde4b2af727d2773","buildSettings":{"CLANG_ENABLE_OBJC_WEAK":"NO","CODE_SIGN_IDENTITY[sdk=appletvos*]":"","CODE_SIGN_IDENTITY[sdk=iphoneos*]":"","CODE_SIGN_IDENTITY[sdk=watchos*]":"","CURRENT_PROJECT_VERSION":"1","DEFINES_MODULE":"YES","DYLIB_COMPATIBILITY_VERSION":"1","DYLIB_CURRENT_VERSION":"1","DYLIB_INSTALL_NAME_BASE":"@rpath","ENABLE_MODULE_VERIFIER":"NO","ENABLE_USER_SCRIPT_SANDBOXING":"NO","GCC_PREFIX_HEADER":"Target Support Files/TOCropViewController/TOCropViewController-prefix.pch","GENERATE_INFOPLIST_FILE":"NO","INFOPLIST_FILE":"Target Support Files/TOCropViewController/TOCropViewController-Info.plist","INSTALL_PATH":"$(LOCAL_LIBRARY_DIR)/Frameworks","IPHONEOS_DEPLOYMENT_TARGET":"11.0","LD_RUNPATH_SEARCH_PATHS":"$(inherited) @executable_path/Frameworks @loader_path/Frameworks","MODULEMAP_FILE":"Target Support Files/TOCropViewController/TOCropViewController.modulemap","PRODUCT_MODULE_NAME":"TOCropViewController","PRODUCT_NAME":"TOCropViewController","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","SWIFT_ACTIVE_COMPILATION_CONDITIONS":"$(inherited) ","SWIFT_INSTALL_OBJC_HEADER":"YES","SWIFT_VERSION":"5.0","TARGETED_DEVICE_FAMILY":"1,2","VALIDATE_PRODUCT":"YES","VERSIONING_SYSTEM":"apple-generic","VERSION_INFO_PREFIX":""},"guid":"bfdfe7dc352907fc980b868725387e98a86be8a3d3fc9de309d9529a5e706f38","name":"Release"}],"buildPhases":[{"buildFiles":[{"fileReference":"bfdfe7dc352907fc980b868725387e98cb086915a5d7868551987b7c937b1a48","guid":"bfdfe7dc352907fc980b868725387e980a4dfaa604a5c973bd4cb5802c9855ab","headerVisibility":"public"},{"fileReference":"bfdfe7dc352907fc980b868725387e980f947dccb1ab29394d270a9013b4bf6e","guid":"bfdfe7dc352907fc980b868725387e9863499551374c1c9ce8b5b4772d95cd02","headerVisibility":"public"},{"fileReference":"bfdfe7dc352907fc980b868725387e984d282bd26faa86397beb095b7a3d376d","guid":"bfdfe7dc352907fc980b868725387e98729b04462a09cdeae6d1711d1cca87d8","headerVisibility":"public"},{"fileReference":"bfdfe7dc352907fc980b868725387e98797068857240200848cd110455f52a9a","guid":"bfdfe7dc352907fc980b868725387e98d7cc822e6ff7acf3dda3e6f4e7a05fe2","headerVisibility":"public"},{"fileReference":"bfdfe7dc352907fc980b868725387e982bff5d3fdbb96b21480273a5f509d057","guid":"bfdfe7dc352907fc980b868725387e9869aa9e264a1406d02e21ec0e12782b90","headerVisibility":"public"},{"fileReference":"bfdfe7dc352907fc980b868725387e98a10957f0a1eeea88e6ac565e960e0f93","guid":"bfdfe7dc352907fc980b868725387e988c61a099ce5bda3b8c423bda9a71d3fe","headerVisibility":"public"},{"fileReference":"bfdfe7dc352907fc980b868725387e98f0694873f1892e94bb75f8e59dedc233","guid":"bfdfe7dc352907fc980b868725387e98969de66fdf5f5ba640fa0b4fd2b1983d","headerVisibility":"public"},{"fileReference":"bfdfe7dc352907fc980b868725387e9856f118f2d46d97111b2a52e08ff662a3","guid":"bfdfe7dc352907fc980b868725387e9892aac1b38c1207e05c8972ff02b5577d","headerVisibility":"public"},{"fileReference":"bfdfe7dc352907fc980b868725387e98486b24fc8a92b9608b42c206e389e292","guid":"bfdfe7dc352907fc980b868725387e98a105d635d93b75cace7bbd27b86b8e73","headerVisibility":"public"},{"fileReference":"bfdfe7dc352907fc980b868725387e98c2614aa70647dc91f2899ce09cd44b2e","guid":"bfdfe7dc352907fc980b868725387e98fe2d3380e9a9e674f15a2ea4eea9bba1","headerVisibility":"public"},{"fileReference":"bfdfe7dc352907fc980b868725387e98822752306ed24d8224a31589482a6a19","guid":"bfdfe7dc352907fc980b868725387e98311b7b43caef2eb83b6f84d293bffd52","headerVisibility":"public"}],"guid":"bfdfe7dc352907fc980b868725387e989823e64e9e00d6500db27cd56bb64766","type":"com.apple.buildphase.headers"},{"buildFiles":[{"fileReference":"bfdfe7dc352907fc980b868725387e9820af03ccb5b9dba937543436fde51ebc","guid":"bfdfe7dc352907fc980b868725387e98f2854e2e6c4b0efdadd510b4c7df08e9"},{"fileReference":"bfdfe7dc352907fc980b868725387e98589c232ca66350220c5b2b60af419691","guid":"bfdfe7dc352907fc980b868725387e98862f204c2217ec1fd0f6c2541cb1d7d2"},{"fileReference":"bfdfe7dc352907fc980b868725387e98967f8f000fb83e0cd182b51d0c53cdd4","guid":"bfdfe7dc352907fc980b868725387e98c4192ed237fd06694e27828b8f6eaa20"},{"fileReference":"bfdfe7dc352907fc980b868725387e98e6de2b9bdc36646e78a3b258eff7e562","guid":"bfdfe7dc352907fc980b868725387e98314f445b68467d09bc944f6977d6a1e5"},{"fileReference":"bfdfe7dc352907fc980b868725387e98817bdacacaa9c1fdca41497b32908163","guid":"bfdfe7dc352907fc980b868725387e9899e94270ee0a9fc2990fe6311d9e930c"},{"fileReference":"bfdfe7dc352907fc980b868725387e9816660fd5daec56af3b08e2cb899287bc","guid":"bfdfe7dc352907fc980b868725387e9874865e6e3e9d40fd69956302ea6a16b1"},{"fileReference":"bfdfe7dc352907fc980b868725387e9846c6e6f5c86b917d65fbec9b4dd09550","guid":"bfdfe7dc352907fc980b868725387e9830df155f1ccf9cf1ff06feda787776e8"},{"fileReference":"bfdfe7dc352907fc980b868725387e98af82120dd778704d0b071247289500e0","guid":"bfdfe7dc352907fc980b868725387e98a9f944ecbfbd6276045c1acd677fdc87"},{"fileReference":"bfdfe7dc352907fc980b868725387e98ce28fe5a13c196a6e1dc960861f6321d","guid":"bfdfe7dc352907fc980b868725387e9834639a5bdb4f50681ddcc792d8385313"},{"fileReference":"bfdfe7dc352907fc980b868725387e983daa75eb91fc04928c0658f9216185f7","guid":"bfdfe7dc352907fc980b868725387e983da8a6c162fb34e1a67bb7ab1d4b8cc7"}],"guid":"bfdfe7dc352907fc980b868725387e98b973c71a5c8d9944a2711af778a2c3b6","type":"com.apple.buildphase.sources"},{"buildFiles":[{"fileReference":"bfdfe7dc352907fc980b868725387e9867aa7825f197b5c58a57320b4ccdc64e","guid":"bfdfe7dc352907fc980b868725387e98269f2208e6af9ec57440cdb8e9a1fdb7"}],"guid":"bfdfe7dc352907fc980b868725387e988710db881c4cd7a5ab2e4ff5e3783e93","type":"com.apple.buildphase.frameworks"},{"buildFiles":[{"guid":"bfdfe7dc352907fc980b868725387e981ebf3826f47dbb7fd582b4ad06af832b","targetReference":"bfdfe7dc352907fc980b868725387e986dbfa2df59ddcae0f992dedaee8f3553"}],"guid":"bfdfe7dc352907fc980b868725387e98561889aae53f203fe8d20bd552b4212b","type":"com.apple.buildphase.resources"}],"buildRules":[],"dependencies":[{"guid":"bfdfe7dc352907fc980b868725387e986dbfa2df59ddcae0f992dedaee8f3553","name":"TOCropViewController-TOCropViewControllerBundle"}],"guid":"bfdfe7dc352907fc980b868725387e987a4af56e2729cecfad7b13d62a9a5fa4","name":"TOCropViewController","predominantSourceCodeLanguage":"Xcode.SourceCodeLanguage.Objective-C-Plus-Plus","productReference":{"guid":"bfdfe7dc352907fc980b868725387e9874cf314b58ac20a75c1512ceb8885e00","name":"TOCropViewController.framework","type":"product"},"productTypeIdentifier":"com.apple.product-type.framework","provisioningSourceData":[{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Debug","provisioningStyle":1},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Profile","provisioningStyle":1},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Release","provisioningStyle":1}],"type":"standard"}  
1 -{"buildConfigurations":[{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e98493610a1174f3f4f738833de56d1328f","buildSettings":{"CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/webview_flutter_wkwebview","EXPANDED_CODE_SIGN_IDENTITY":"-","IBSC_MODULE":"webview_flutter_wkwebview","INFOPLIST_FILE":"Target Support Files/webview_flutter_wkwebview/ResourceBundle-webview_flutter_wkwebview_privacy-webview_flutter_wkwebview-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"12.0","ONLY_ACTIVE_ARCH":"NO","PRODUCT_NAME":"webview_flutter_wkwebview_privacy","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e98d80b51d8a17903a5a76f87e19f34a1cd","name":"Debug"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e986361f96ad5d0d9cdb22ee6aa8a152702","buildSettings":{"CLANG_ENABLE_OBJC_WEAK":"NO","CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/webview_flutter_wkwebview","EXPANDED_CODE_SIGN_IDENTITY":"-","IBSC_MODULE":"webview_flutter_wkwebview","INFOPLIST_FILE":"Target Support Files/webview_flutter_wkwebview/ResourceBundle-webview_flutter_wkwebview_privacy-webview_flutter_wkwebview-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"12.0","PRODUCT_NAME":"webview_flutter_wkwebview_privacy","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","VALIDATE_PRODUCT":"YES","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e98a8eb84ead72688d86e0b3cc3812ea2c5","name":"Profile"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e986361f96ad5d0d9cdb22ee6aa8a152702","buildSettings":{"CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/webview_flutter_wkwebview","EXPANDED_CODE_SIGN_IDENTITY":"-","IBSC_MODULE":"webview_flutter_wkwebview","INFOPLIST_FILE":"Target Support Files/webview_flutter_wkwebview/ResourceBundle-webview_flutter_wkwebview_privacy-webview_flutter_wkwebview-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"12.0","PRODUCT_NAME":"webview_flutter_wkwebview_privacy","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e9866813aeb060709759078e48411f62903","name":"Release"}],"buildPhases":[{"buildFiles":[],"guid":"bfdfe7dc352907fc980b868725387e98be0c772f785cd7505ee510c2c1540ffc","type":"com.apple.buildphase.sources"},{"buildFiles":[],"guid":"bfdfe7dc352907fc980b868725387e9803c584675c731ccc36f8caaf4cf90695","type":"com.apple.buildphase.frameworks"},{"buildFiles":[{"fileReference":"bfdfe7dc352907fc980b868725387e982297aecfd80c36c1baf114e37d793b48","guid":"bfdfe7dc352907fc980b868725387e98da6537bf6fc10be793f792c58fe8ceb7"}],"guid":"bfdfe7dc352907fc980b868725387e988311469bb57dac0be242a449c4d5a54c","type":"com.apple.buildphase.resources"}],"buildRules":[],"dependencies":[],"guid":"bfdfe7dc352907fc980b868725387e987c93e943aa0a38b5f6684beaf6b4a3a1","name":"webview_flutter_wkwebview-webview_flutter_wkwebview_privacy","productReference":{"guid":"bfdfe7dc352907fc980b868725387e98a0c2ea56ea4c64a4495566659e5fdb93","name":"webview_flutter_wkwebview_privacy.bundle","type":"product"},"productTypeIdentifier":"com.apple.product-type.bundle","provisioningSourceData":[{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Debug","provisioningStyle":0},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Profile","provisioningStyle":0},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Release","provisioningStyle":0}],"type":"standard"}  
1 -{"buildConfigurations":[{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e987429100136c7cabdb1c53ff7846a606f","buildSettings":{"CLANG_ENABLE_OBJC_WEAK":"NO","CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER":"NO","CODE_SIGN_IDENTITY[sdk=appletvos*]":"","CODE_SIGN_IDENTITY[sdk=iphoneos*]":"","CODE_SIGN_IDENTITY[sdk=watchos*]":"","CURRENT_PROJECT_VERSION":"1","DYLIB_COMPATIBILITY_VERSION":"1","DYLIB_CURRENT_VERSION":"1","DYLIB_INSTALL_NAME_BASE":"@rpath","ENABLE_BITCODE":"NO","ENABLE_MODULE_VERIFIER":"NO","ENABLE_USER_SCRIPT_SANDBOXING":"NO","EXCLUDED_ARCHS[sdk=iphoneos*]":"$(inherited) armv7","EXCLUDED_ARCHS[sdk=iphonesimulator*]":"$(inherited) i386","FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios/Flutter.xcframework/ios-arm64\" $(inherited)","FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios/Flutter.xcframework/ios-arm64_x86_64-simulator\" $(inherited)","GCC_PREFIX_HEADER":"Target Support Files/shared_preferences_foundation/shared_preferences_foundation-prefix.pch","GENERATE_INFOPLIST_FILE":"NO","INFOPLIST_FILE":"Target Support Files/shared_preferences_foundation/shared_preferences_foundation-Info.plist","INSTALL_PATH":"$(LOCAL_LIBRARY_DIR)/Frameworks","IPHONEOS_DEPLOYMENT_TARGET":"12.0","MODULEMAP_FILE":"Target Support Files/shared_preferences_foundation/shared_preferences_foundation.modulemap","ONLY_ACTIVE_ARCH":"NO","OTHER_LDFLAGS":"$(inherited) -framework Flutter","PRODUCT_MODULE_NAME":"shared_preferences_foundation","PRODUCT_NAME":"shared_preferences_foundation","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","SWIFT_ACTIVE_COMPILATION_CONDITIONS":"$(inherited) ","SWIFT_INSTALL_OBJC_HEADER":"YES","SWIFT_VERSION":"5.0","TARGETED_DEVICE_FAMILY":"1,2","VALID_ARCHS[sdk=iphonesimulator*]":"$(ARCHS_STANDARD)","VERSIONING_SYSTEM":"apple-generic","VERSION_INFO_PREFIX":""},"guid":"bfdfe7dc352907fc980b868725387e986f83bf1d86816a7afe713389f3b0794c","name":"Debug"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e9852aeec4c055e14df0bbd35d7207bef7b","buildSettings":{"CLANG_ENABLE_OBJC_WEAK":"NO","CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER":"NO","CODE_SIGN_IDENTITY[sdk=appletvos*]":"","CODE_SIGN_IDENTITY[sdk=iphoneos*]":"","CODE_SIGN_IDENTITY[sdk=watchos*]":"","CURRENT_PROJECT_VERSION":"1","DYLIB_COMPATIBILITY_VERSION":"1","DYLIB_CURRENT_VERSION":"1","DYLIB_INSTALL_NAME_BASE":"@rpath","ENABLE_BITCODE":"NO","ENABLE_MODULE_VERIFIER":"NO","ENABLE_USER_SCRIPT_SANDBOXING":"NO","EXCLUDED_ARCHS[sdk=iphoneos*]":"$(inherited) armv7","EXCLUDED_ARCHS[sdk=iphonesimulator*]":"$(inherited) i386","FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios-release/Flutter.xcframework/ios-arm64\" $(inherited)","FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios-release/Flutter.xcframework/ios-arm64_x86_64-simulator\" $(inherited)","GCC_PREFIX_HEADER":"Target Support Files/shared_preferences_foundation/shared_preferences_foundation-prefix.pch","GENERATE_INFOPLIST_FILE":"NO","INFOPLIST_FILE":"Target Support Files/shared_preferences_foundation/shared_preferences_foundation-Info.plist","INSTALL_PATH":"$(LOCAL_LIBRARY_DIR)/Frameworks","IPHONEOS_DEPLOYMENT_TARGET":"12.0","MODULEMAP_FILE":"Target Support Files/shared_preferences_foundation/shared_preferences_foundation.modulemap","OTHER_LDFLAGS":"$(inherited) -framework Flutter","PRODUCT_MODULE_NAME":"shared_preferences_foundation","PRODUCT_NAME":"shared_preferences_foundation","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","SWIFT_ACTIVE_COMPILATION_CONDITIONS":"$(inherited) ","SWIFT_INSTALL_OBJC_HEADER":"YES","SWIFT_VERSION":"5.0","TARGETED_DEVICE_FAMILY":"1,2","VALIDATE_PRODUCT":"YES","VALID_ARCHS[sdk=iphonesimulator*]":"$(ARCHS_STANDARD)","VERSIONING_SYSTEM":"apple-generic","VERSION_INFO_PREFIX":""},"guid":"bfdfe7dc352907fc980b868725387e98c6ce66678a98cae8c935e06602a448e0","name":"Profile"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e9852aeec4c055e14df0bbd35d7207bef7b","buildSettings":{"CLANG_ENABLE_OBJC_WEAK":"NO","CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER":"NO","CODE_SIGN_IDENTITY[sdk=appletvos*]":"","CODE_SIGN_IDENTITY[sdk=iphoneos*]":"","CODE_SIGN_IDENTITY[sdk=watchos*]":"","CURRENT_PROJECT_VERSION":"1","DYLIB_COMPATIBILITY_VERSION":"1","DYLIB_CURRENT_VERSION":"1","DYLIB_INSTALL_NAME_BASE":"@rpath","ENABLE_BITCODE":"NO","ENABLE_MODULE_VERIFIER":"NO","ENABLE_USER_SCRIPT_SANDBOXING":"NO","EXCLUDED_ARCHS[sdk=iphoneos*]":"$(inherited) armv7","EXCLUDED_ARCHS[sdk=iphonesimulator*]":"$(inherited) i386","FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios-release/Flutter.xcframework/ios-arm64\" $(inherited)","FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios-release/Flutter.xcframework/ios-arm64_x86_64-simulator\" $(inherited)","GCC_PREFIX_HEADER":"Target Support Files/shared_preferences_foundation/shared_preferences_foundation-prefix.pch","GENERATE_INFOPLIST_FILE":"NO","INFOPLIST_FILE":"Target Support Files/shared_preferences_foundation/shared_preferences_foundation-Info.plist","INSTALL_PATH":"$(LOCAL_LIBRARY_DIR)/Frameworks","IPHONEOS_DEPLOYMENT_TARGET":"12.0","MODULEMAP_FILE":"Target Support Files/shared_preferences_foundation/shared_preferences_foundation.modulemap","OTHER_LDFLAGS":"$(inherited) -framework Flutter","PRODUCT_MODULE_NAME":"shared_preferences_foundation","PRODUCT_NAME":"shared_preferences_foundation","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","SWIFT_ACTIVE_COMPILATION_CONDITIONS":"$(inherited) ","SWIFT_INSTALL_OBJC_HEADER":"YES","SWIFT_VERSION":"5.0","TARGETED_DEVICE_FAMILY":"1,2","VALIDATE_PRODUCT":"YES","VALID_ARCHS[sdk=iphonesimulator*]":"$(ARCHS_STANDARD)","VERSIONING_SYSTEM":"apple-generic","VERSION_INFO_PREFIX":""},"guid":"bfdfe7dc352907fc980b868725387e980f59bc0c0df185b08d92e2afa6f35dda","name":"Release"}],"buildPhases":[{"buildFiles":[{"fileReference":"bfdfe7dc352907fc980b868725387e983ec0af0b71e7c22c7e6379565b559d23","guid":"bfdfe7dc352907fc980b868725387e98e82259888cd400660e6ae15b115eb233","headerVisibility":"public"}],"guid":"bfdfe7dc352907fc980b868725387e9845bc282ec8aa7540f3a569c2631d21d5","type":"com.apple.buildphase.headers"},{"buildFiles":[{"fileReference":"bfdfe7dc352907fc980b868725387e98e7a271e245866241ed9115730062d18c","guid":"bfdfe7dc352907fc980b868725387e983f910a660af8b1be8c5c9c125d4adb96"},{"fileReference":"bfdfe7dc352907fc980b868725387e987877bde4a16b804bce84a03009cd4a3f","guid":"bfdfe7dc352907fc980b868725387e98489a95f2019f3ec6e0acd5ba6de8991a"},{"fileReference":"bfdfe7dc352907fc980b868725387e98c00b68f3aa242f9059f2aa57ccc6a50b","guid":"bfdfe7dc352907fc980b868725387e989af2be92c6af9962a52aabe6c4751285"}],"guid":"bfdfe7dc352907fc980b868725387e98f14b5d6b6d6b0c465e2f1e0eaa6bc1cd","type":"com.apple.buildphase.sources"},{"buildFiles":[{"fileReference":"bfdfe7dc352907fc980b868725387e9867aa7825f197b5c58a57320b4ccdc64e","guid":"bfdfe7dc352907fc980b868725387e98475ba5d87573359032e9b06fd466a003"}],"guid":"bfdfe7dc352907fc980b868725387e9859badffc37928e123e98be61f8d11d71","type":"com.apple.buildphase.frameworks"},{"buildFiles":[{"guid":"bfdfe7dc352907fc980b868725387e9872e4e537a8c9a8da179493daa4c54b77","targetReference":"bfdfe7dc352907fc980b868725387e98e0be3b0d5ad56f1985578b1f97431765"}],"guid":"bfdfe7dc352907fc980b868725387e9876fd72010a5b056ae41fa1936cd39334","type":"com.apple.buildphase.resources"}],"buildRules":[],"dependencies":[{"guid":"bfdfe7dc352907fc980b868725387e989da425bb6d6d5d8dbb95e4afffb82217","name":"Flutter"},{"guid":"bfdfe7dc352907fc980b868725387e98e0be3b0d5ad56f1985578b1f97431765","name":"shared_preferences_foundation-shared_preferences_foundation_privacy"}],"guid":"bfdfe7dc352907fc980b868725387e9828cab1f188854e0a973e6ff6905c5ffe","name":"shared_preferences_foundation","predominantSourceCodeLanguage":"Xcode.SourceCodeLanguage.Swift","productReference":{"guid":"bfdfe7dc352907fc980b868725387e9815af7ba71ce93f789a463577fc360420","name":"shared_preferences_foundation.framework","type":"product"},"productTypeIdentifier":"com.apple.product-type.framework","provisioningSourceData":[{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Debug","provisioningStyle":1},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Profile","provisioningStyle":1},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Release","provisioningStyle":1}],"type":"standard"}  
1 -{"buildConfigurations":[{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e9872c3a102c2f55c6f0eee5833107fac63","buildSettings":{"CLANG_ENABLE_OBJC_WEAK":"NO","CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER":"NO","CODE_SIGN_IDENTITY[sdk=appletvos*]":"","CODE_SIGN_IDENTITY[sdk=iphoneos*]":"","CODE_SIGN_IDENTITY[sdk=watchos*]":"","CURRENT_PROJECT_VERSION":"1","DYLIB_COMPATIBILITY_VERSION":"1","DYLIB_CURRENT_VERSION":"1","DYLIB_INSTALL_NAME_BASE":"@rpath","ENABLE_BITCODE":"NO","ENABLE_MODULE_VERIFIER":"NO","ENABLE_USER_SCRIPT_SANDBOXING":"NO","EXCLUDED_ARCHS[sdk=iphoneos*]":"$(inherited) armv7","EXCLUDED_ARCHS[sdk=iphonesimulator*]":"$(inherited) i386","FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios/Flutter.xcframework/ios-arm64\" $(inherited)","FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios/Flutter.xcframework/ios-arm64_x86_64-simulator\" $(inherited)","GCC_PREFIX_HEADER":"Target Support Files/sqflite_darwin/sqflite_darwin-prefix.pch","GENERATE_INFOPLIST_FILE":"NO","INFOPLIST_FILE":"Target Support Files/sqflite_darwin/sqflite_darwin-Info.plist","INSTALL_PATH":"$(LOCAL_LIBRARY_DIR)/Frameworks","IPHONEOS_DEPLOYMENT_TARGET":"12.0","LD_RUNPATH_SEARCH_PATHS":"$(inherited) @executable_path/Frameworks @loader_path/Frameworks","MODULEMAP_FILE":"Target Support Files/sqflite_darwin/sqflite_darwin.modulemap","ONLY_ACTIVE_ARCH":"NO","OTHER_LDFLAGS":"$(inherited) -framework Flutter","PRODUCT_MODULE_NAME":"sqflite_darwin","PRODUCT_NAME":"sqflite_darwin","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","SWIFT_ACTIVE_COMPILATION_CONDITIONS":"$(inherited) ","SWIFT_INSTALL_OBJC_HEADER":"YES","SWIFT_VERSION":"5.0","TARGETED_DEVICE_FAMILY":"1,2","VALID_ARCHS[sdk=iphonesimulator*]":"$(ARCHS_STANDARD)","VERSIONING_SYSTEM":"apple-generic","VERSION_INFO_PREFIX":""},"guid":"bfdfe7dc352907fc980b868725387e98ee49f65d26d8a0c930cc03d16e0ffcc8","name":"Debug"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e98d1a455bf7417c3aeb645db18ef108a94","buildSettings":{"CLANG_ENABLE_OBJC_WEAK":"NO","CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER":"NO","CODE_SIGN_IDENTITY[sdk=appletvos*]":"","CODE_SIGN_IDENTITY[sdk=iphoneos*]":"","CODE_SIGN_IDENTITY[sdk=watchos*]":"","CURRENT_PROJECT_VERSION":"1","DYLIB_COMPATIBILITY_VERSION":"1","DYLIB_CURRENT_VERSION":"1","DYLIB_INSTALL_NAME_BASE":"@rpath","ENABLE_BITCODE":"NO","ENABLE_MODULE_VERIFIER":"NO","ENABLE_USER_SCRIPT_SANDBOXING":"NO","EXCLUDED_ARCHS[sdk=iphoneos*]":"$(inherited) armv7","EXCLUDED_ARCHS[sdk=iphonesimulator*]":"$(inherited) i386","FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios-release/Flutter.xcframework/ios-arm64\" $(inherited)","FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios-release/Flutter.xcframework/ios-arm64_x86_64-simulator\" $(inherited)","GCC_PREFIX_HEADER":"Target Support Files/sqflite_darwin/sqflite_darwin-prefix.pch","GENERATE_INFOPLIST_FILE":"NO","INFOPLIST_FILE":"Target Support Files/sqflite_darwin/sqflite_darwin-Info.plist","INSTALL_PATH":"$(LOCAL_LIBRARY_DIR)/Frameworks","IPHONEOS_DEPLOYMENT_TARGET":"12.0","LD_RUNPATH_SEARCH_PATHS":"$(inherited) @executable_path/Frameworks @loader_path/Frameworks","MODULEMAP_FILE":"Target Support Files/sqflite_darwin/sqflite_darwin.modulemap","OTHER_LDFLAGS":"$(inherited) -framework Flutter","PRODUCT_MODULE_NAME":"sqflite_darwin","PRODUCT_NAME":"sqflite_darwin","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","SWIFT_ACTIVE_COMPILATION_CONDITIONS":"$(inherited) ","SWIFT_INSTALL_OBJC_HEADER":"YES","SWIFT_VERSION":"5.0","TARGETED_DEVICE_FAMILY":"1,2","VALIDATE_PRODUCT":"YES","VALID_ARCHS[sdk=iphonesimulator*]":"$(ARCHS_STANDARD)","VERSIONING_SYSTEM":"apple-generic","VERSION_INFO_PREFIX":""},"guid":"bfdfe7dc352907fc980b868725387e987d3fcd01a34fff9e18dec0764bcc371e","name":"Profile"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e98d1a455bf7417c3aeb645db18ef108a94","buildSettings":{"CLANG_ENABLE_OBJC_WEAK":"NO","CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER":"NO","CODE_SIGN_IDENTITY[sdk=appletvos*]":"","CODE_SIGN_IDENTITY[sdk=iphoneos*]":"","CODE_SIGN_IDENTITY[sdk=watchos*]":"","CURRENT_PROJECT_VERSION":"1","DYLIB_COMPATIBILITY_VERSION":"1","DYLIB_CURRENT_VERSION":"1","DYLIB_INSTALL_NAME_BASE":"@rpath","ENABLE_BITCODE":"NO","ENABLE_MODULE_VERIFIER":"NO","ENABLE_USER_SCRIPT_SANDBOXING":"NO","EXCLUDED_ARCHS[sdk=iphoneos*]":"$(inherited) armv7","EXCLUDED_ARCHS[sdk=iphonesimulator*]":"$(inherited) i386","FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios-release/Flutter.xcframework/ios-arm64\" $(inherited)","FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*]":"\"/Users/changshouda/Documents/flutter_flutter/bin/cache/artifacts/engine/ios-release/Flutter.xcframework/ios-arm64_x86_64-simulator\" $(inherited)","GCC_PREFIX_HEADER":"Target Support Files/sqflite_darwin/sqflite_darwin-prefix.pch","GENERATE_INFOPLIST_FILE":"NO","INFOPLIST_FILE":"Target Support Files/sqflite_darwin/sqflite_darwin-Info.plist","INSTALL_PATH":"$(LOCAL_LIBRARY_DIR)/Frameworks","IPHONEOS_DEPLOYMENT_TARGET":"12.0","LD_RUNPATH_SEARCH_PATHS":"$(inherited) @executable_path/Frameworks @loader_path/Frameworks","MODULEMAP_FILE":"Target Support Files/sqflite_darwin/sqflite_darwin.modulemap","OTHER_LDFLAGS":"$(inherited) -framework Flutter","PRODUCT_MODULE_NAME":"sqflite_darwin","PRODUCT_NAME":"sqflite_darwin","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","SWIFT_ACTIVE_COMPILATION_CONDITIONS":"$(inherited) ","SWIFT_INSTALL_OBJC_HEADER":"YES","SWIFT_VERSION":"5.0","TARGETED_DEVICE_FAMILY":"1,2","VALIDATE_PRODUCT":"YES","VALID_ARCHS[sdk=iphonesimulator*]":"$(ARCHS_STANDARD)","VERSIONING_SYSTEM":"apple-generic","VERSION_INFO_PREFIX":""},"guid":"bfdfe7dc352907fc980b868725387e984def481d54810d0de6d3335b228b2a5d","name":"Release"}],"buildPhases":[{"buildFiles":[{"fileReference":"bfdfe7dc352907fc980b868725387e986fb22dd51fa46a134940fe6eaca4c33f","guid":"bfdfe7dc352907fc980b868725387e98f74bfe561cdc142d140be02f934f1dd5","headerVisibility":"public"},{"fileReference":"bfdfe7dc352907fc980b868725387e9884ed5320049c5deacc8bdde324892932","guid":"bfdfe7dc352907fc980b868725387e98ee11ff009cad5d58df14f6726361e05e"},{"fileReference":"bfdfe7dc352907fc980b868725387e986111af286522da9c91d0a23bb43d5789","guid":"bfdfe7dc352907fc980b868725387e985b56be77fd90c95178875fbdc9759ded"},{"fileReference":"bfdfe7dc352907fc980b868725387e98f522c2c362e0cb505e091d40b601b659","guid":"bfdfe7dc352907fc980b868725387e989fb03240d74c5b16d4df2090487dd870"},{"fileReference":"bfdfe7dc352907fc980b868725387e98fb3a48ecd51a149ca81f8964ffc2a633","guid":"bfdfe7dc352907fc980b868725387e98b0a98399ea089bec6015924fca214fd0"},{"fileReference":"bfdfe7dc352907fc980b868725387e98a6073c90465ff96a450936e03863b005","guid":"bfdfe7dc352907fc980b868725387e98a561fea4089e8e9aaa7d41e004a74551"},{"fileReference":"bfdfe7dc352907fc980b868725387e984af2acc58d476c23807b931ebdc6fcea","guid":"bfdfe7dc352907fc980b868725387e98e58eb8cea732f8da9eabee06f4760c04"},{"fileReference":"bfdfe7dc352907fc980b868725387e989792f90254ab248f54bb28aad5d10b96","guid":"bfdfe7dc352907fc980b868725387e989f7af140018ee6c1e6b210b20014ceb1"},{"fileReference":"bfdfe7dc352907fc980b868725387e980a6fc4f6d4839e6b447146ca7c886bce","guid":"bfdfe7dc352907fc980b868725387e98f23c703fb2f8f96105b7661f651d76b4"},{"fileReference":"bfdfe7dc352907fc980b868725387e989592a62ecd847bb19b5cd1307f338495","guid":"bfdfe7dc352907fc980b868725387e98b842866f43a58c7f2cd4903a46020f66"},{"fileReference":"bfdfe7dc352907fc980b868725387e980af65b71df82ad9c499004407ea24610","guid":"bfdfe7dc352907fc980b868725387e986769c43d062e13d97bdb26435517a0a9","headerVisibility":"public"},{"fileReference":"bfdfe7dc352907fc980b868725387e9888ff0ca83bb270d92e95e5a3a94f5b66","guid":"bfdfe7dc352907fc980b868725387e98dcd1d6833c3ba22cff192e9c729f402d"},{"fileReference":"bfdfe7dc352907fc980b868725387e98d5ab4adf06bad8786975c988a7c1aefc","guid":"bfdfe7dc352907fc980b868725387e98a8b10f256eab576dca45253c4e5eb01a"},{"fileReference":"bfdfe7dc352907fc980b868725387e9870b0a201c6540c238e46ebd2a3e3f6e2","guid":"bfdfe7dc352907fc980b868725387e984db51d20d4b10739c36207080362307d","headerVisibility":"public"}],"guid":"bfdfe7dc352907fc980b868725387e98cc465b98567e5be1dff8b7284a07e4e3","type":"com.apple.buildphase.headers"},{"buildFiles":[{"fileReference":"bfdfe7dc352907fc980b868725387e98a3e0e5f6b6128baf5a0636ba98dd1bf7","guid":"bfdfe7dc352907fc980b868725387e985adaa6c4e40f33315ac0cec984200988"},{"fileReference":"bfdfe7dc352907fc980b868725387e98b5a595be9be31b486c76ff2f88085da9","guid":"bfdfe7dc352907fc980b868725387e9887c26a4ce919cd8e1da7ba74bc37f5e3"},{"fileReference":"bfdfe7dc352907fc980b868725387e98a0dd514539473bc748477a243ceff41d","guid":"bfdfe7dc352907fc980b868725387e98d14ae3cc83358b6ee88a1f9a4d5c6d3e"},{"fileReference":"bfdfe7dc352907fc980b868725387e9879bf3158d99ad90816a50571a9897a1b","guid":"bfdfe7dc352907fc980b868725387e983dbbed738f1be0937cd9105c2a700a04"},{"fileReference":"bfdfe7dc352907fc980b868725387e986fd10043962de1416443951e6f9a1223","guid":"bfdfe7dc352907fc980b868725387e98ea0fba00024403dbd3e85cac557df8e5"},{"fileReference":"bfdfe7dc352907fc980b868725387e9809c004b58d16a21de9d0533f0896ef75","guid":"bfdfe7dc352907fc980b868725387e9823662ee0e62201af4b56a8af77ae26e6"},{"fileReference":"bfdfe7dc352907fc980b868725387e98caf6cab5efa0d88fed7a44cb8c5eb823","guid":"bfdfe7dc352907fc980b868725387e98fed9191d2666c9cd3507583cd694c1a5"},{"fileReference":"bfdfe7dc352907fc980b868725387e98c83761c941d8fe8c3cf108bf0d3e3aa5","guid":"bfdfe7dc352907fc980b868725387e98af1eb69ffb28b93e0b654f9fa9aeec11"},{"fileReference":"bfdfe7dc352907fc980b868725387e98407416797503baf87cf9e40adefc896e","guid":"bfdfe7dc352907fc980b868725387e98e6b9ebef247a9cb276932d07fdf18195"}],"guid":"bfdfe7dc352907fc980b868725387e9837c2f0a37c50e959478519168227e455","type":"com.apple.buildphase.sources"},{"buildFiles":[{"fileReference":"bfdfe7dc352907fc980b868725387e9867aa7825f197b5c58a57320b4ccdc64e","guid":"bfdfe7dc352907fc980b868725387e982f461d51c284a55b8f869fc9092ae5dc"}],"guid":"bfdfe7dc352907fc980b868725387e98dd47f73652ff7b522b7942f6a87afd23","type":"com.apple.buildphase.frameworks"},{"buildFiles":[{"guid":"bfdfe7dc352907fc980b868725387e98d17544c34b81de618417de5f9c91b4ec","targetReference":"bfdfe7dc352907fc980b868725387e9883134bb5f399cb37a1eb075d4fea30d8"}],"guid":"bfdfe7dc352907fc980b868725387e98e60a652c76bfee084293e97b00176921","type":"com.apple.buildphase.resources"}],"buildRules":[],"dependencies":[{"guid":"bfdfe7dc352907fc980b868725387e989da425bb6d6d5d8dbb95e4afffb82217","name":"Flutter"},{"guid":"bfdfe7dc352907fc980b868725387e9883134bb5f399cb37a1eb075d4fea30d8","name":"sqflite_darwin-sqflite_darwin_privacy"}],"guid":"bfdfe7dc352907fc980b868725387e981304d3d2169071b3ca365b19f5340b7c","name":"sqflite_darwin","predominantSourceCodeLanguage":"Xcode.SourceCodeLanguage.Objective-C-Plus-Plus","productReference":{"guid":"bfdfe7dc352907fc980b868725387e98dbbec3eebed26c79cc653713be723aba","name":"sqflite_darwin.framework","type":"product"},"productTypeIdentifier":"com.apple.product-type.framework","provisioningSourceData":[{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Debug","provisioningStyle":1},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Profile","provisioningStyle":1},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Release","provisioningStyle":1}],"type":"standard"}  
1 -{"buildConfigurations":[{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e9868b77f49da4a0e0608aac8b3f5ae3e8e","buildSettings":{"CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/fluttertoast","EXPANDED_CODE_SIGN_IDENTITY":"-","IBSC_MODULE":"fluttertoast","INFOPLIST_FILE":"Target Support Files/fluttertoast/ResourceBundle-fluttertoast_privacy-fluttertoast-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"9.0","ONLY_ACTIVE_ARCH":"NO","PRODUCT_NAME":"fluttertoast_privacy","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e98e953ed566e91deecfd81b8d86775557e","name":"Debug"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e9852dc1371d317d5fc535ff1f306279566","buildSettings":{"CLANG_ENABLE_OBJC_WEAK":"NO","CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/fluttertoast","EXPANDED_CODE_SIGN_IDENTITY":"-","IBSC_MODULE":"fluttertoast","INFOPLIST_FILE":"Target Support Files/fluttertoast/ResourceBundle-fluttertoast_privacy-fluttertoast-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"9.0","PRODUCT_NAME":"fluttertoast_privacy","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","VALIDATE_PRODUCT":"YES","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e98aaf3428a047eceae78d5066e966725e2","name":"Profile"},{"baseConfigurationFileReference":"bfdfe7dc352907fc980b868725387e9852dc1371d317d5fc535ff1f306279566","buildSettings":{"CODE_SIGNING_ALLOWED":"NO","CODE_SIGNING_IDENTITY":"-","CODE_SIGNING_REQUIRED":"NO","CONFIGURATION_BUILD_DIR":"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/fluttertoast","EXPANDED_CODE_SIGN_IDENTITY":"-","IBSC_MODULE":"fluttertoast","INFOPLIST_FILE":"Target Support Files/fluttertoast/ResourceBundle-fluttertoast_privacy-fluttertoast-Info.plist","IPHONEOS_DEPLOYMENT_TARGET":"9.0","PRODUCT_NAME":"fluttertoast_privacy","SDKROOT":"iphoneos","SKIP_INSTALL":"YES","TARGETED_DEVICE_FAMILY":"1,2","WRAPPER_EXTENSION":"bundle"},"guid":"bfdfe7dc352907fc980b868725387e98f579fcd0430145ff5c26ebb561295b61","name":"Release"}],"buildPhases":[{"buildFiles":[],"guid":"bfdfe7dc352907fc980b868725387e9841303d8c9e72995b61c742fccb2bd21c","type":"com.apple.buildphase.sources"},{"buildFiles":[],"guid":"bfdfe7dc352907fc980b868725387e984d28eac7bb4cfd0b6e33b38e608751b1","type":"com.apple.buildphase.frameworks"},{"buildFiles":[{"fileReference":"bfdfe7dc352907fc980b868725387e98929a0306e3d8a8e4d4e29ee5e8aefe33","guid":"bfdfe7dc352907fc980b868725387e98eed99eb74e9521e86d82963f3fcafaa0"}],"guid":"bfdfe7dc352907fc980b868725387e98b5f9c12d7a063695e354f05b3e8b7e8e","type":"com.apple.buildphase.resources"}],"buildRules":[],"dependencies":[],"guid":"bfdfe7dc352907fc980b868725387e985739272bce418ef50bd06c859612bad5","name":"fluttertoast-fluttertoast_privacy","productReference":{"guid":"bfdfe7dc352907fc980b868725387e989d4bb598ca0a92e1d0f3a4ef0157bf7e","name":"fluttertoast_privacy.bundle","type":"product"},"productTypeIdentifier":"com.apple.product-type.bundle","provisioningSourceData":[{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Debug","provisioningStyle":0},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Profile","provisioningStyle":0},{"bundleIdentifierFromInfoPlist":"${PRODUCT_BUNDLE_IDENTIFIER}","configurationName":"Release","provisioningStyle":0}],"type":"standard"}  
1 -{"guid":"dc4b70c03e8043e50e38f2068887b1d4","name":"Pods","path":"/Users/changshouda/Documents/FlutterProject/doublefeel_flutter/ios/Pods/Pods.xcodeproj/project.xcworkspace","projects":["PROJECT@v11_mod=0c3f0943d4c7c3601816831d5458ddcd_hash=bfdfe7dc352907fc980b868725387e98plugins=1OJSG6M1FOV3XYQCBH7Z29RZ0FPR9XDE1"]}  
@@ -7,6 +7,7 @@ import '../../core/network/api/health_api.dart'; @@ -7,6 +7,7 @@ import '../../core/network/api/health_api.dart';
7 import '../../core/network/api/interaction_api.dart'; 7 import '../../core/network/api/interaction_api.dart';
8 import '../../core/network/api/obs_api.dart'; 8 import '../../core/network/api/obs_api.dart';
9 import '../../core/network/api/pay_api.dart'; 9 import '../../core/network/api/pay_api.dart';
  10 +import '../../core/network/api/theme_api.dart';
10 import '../../core/network/api/user_api.dart'; 11 import '../../core/network/api/user_api.dart';
11 import '../../core/network/api/vip_api.dart'; 12 import '../../core/network/api/vip_api.dart';
12 import '../../core/network/dio_client.dart'; 13 import '../../core/network/dio_client.dart';
@@ -86,6 +87,11 @@ void registerConfigDeps(DioClient dioClient) { @@ -86,6 +87,11 @@ void registerConfigDeps(DioClient dioClient) {
86 Get.lazyPut(() => ConfigApi(dioClient), fenix: true); 87 Get.lazyPut(() => ConfigApi(dioClient), fenix: true);
87 } 88 }
88 89
  90 +/// Watch theme API.
  91 +void registerThemeDeps(DioClient dioClient) {
  92 + Get.lazyPut(() => ThemeApi(dioClient), fenix: true);
  93 +}
  94 +
89 /// Partner interaction API and wear engine. 95 /// Partner interaction API and wear engine.
90 void registerInteractionDeps( 96 void registerInteractionDeps(
91 DioClient dioClient, 97 DioClient dioClient,
@@ -37,6 +37,7 @@ class InitialBinding extends Bindings { @@ -37,6 +37,7 @@ class InitialBinding extends Bindings {
37 registerHealthDeps(dioClient); 37 registerHealthDeps(dioClient);
38 registerPayDeps(dioClient); 38 registerPayDeps(dioClient);
39 registerConfigDeps(dioClient); 39 registerConfigDeps(dioClient);
  40 + registerThemeDeps(dioClient);
40 registerInteractionDeps(dioClient, userPrefs); 41 registerInteractionDeps(dioClient, userPrefs);
41 registerObsDeps(dioClient); 42 registerObsDeps(dioClient);
42 } 43 }
1 import 'package:get/get.dart'; 1 import 'package:get/get.dart';
2 2
  3 +import '../../../../core/network/api/theme_api.dart';
3 import '../controllers/create_watch_theme_controller.dart'; 4 import '../controllers/create_watch_theme_controller.dart';
4 import '../controllers/custom_watch_theme_preview_controller.dart'; 5 import '../controllers/custom_watch_theme_preview_controller.dart';
5 import '../controllers/watch_theme_controller.dart'; 6 import '../controllers/watch_theme_controller.dart';
@@ -8,7 +9,9 @@ import '../controllers/watch_theme_preview_controller.dart'; @@ -8,7 +9,9 @@ import '../controllers/watch_theme_preview_controller.dart';
8 class WatchThemeBinding extends Bindings { 9 class WatchThemeBinding extends Bindings {
9 @override 10 @override
10 void dependencies() { 11 void dependencies() {
11 - Get.lazyPut<WatchThemeController>(() => WatchThemeController()); 12 + Get.lazyPut<WatchThemeController>(
  13 + () => WatchThemeController(Get.find<ThemeApi>()),
  14 + );
12 } 15 }
13 } 16 }
14 17
@@ -16,7 +19,7 @@ class WatchThemePreviewBinding extends Bindings { @@ -16,7 +19,7 @@ class WatchThemePreviewBinding extends Bindings {
16 @override 19 @override
17 void dependencies() { 20 void dependencies() {
18 Get.lazyPut<WatchThemePreviewController>( 21 Get.lazyPut<WatchThemePreviewController>(
19 - () => WatchThemePreviewController(), 22 + () => WatchThemePreviewController(Get.find<ThemeApi>()),
20 ); 23 );
21 } 24 }
22 } 25 }
@@ -25,7 +28,7 @@ class CreateWatchThemeBinding extends Bindings { @@ -25,7 +28,7 @@ class CreateWatchThemeBinding extends Bindings {
25 @override 28 @override
26 void dependencies() { 29 void dependencies() {
27 Get.lazyPut<CreateWatchThemeController>( 30 Get.lazyPut<CreateWatchThemeController>(
28 - () => CreateWatchThemeController(), 31 + () => CreateWatchThemeController(Get.find<ThemeApi>()),
29 ); 32 );
30 } 33 }
31 } 34 }
@@ -34,7 +37,7 @@ class CustomWatchThemePreviewBinding extends Bindings { @@ -34,7 +37,7 @@ class CustomWatchThemePreviewBinding extends Bindings {
34 @override 37 @override
35 void dependencies() { 38 void dependencies() {
36 Get.lazyPut<CustomWatchThemePreviewController>( 39 Get.lazyPut<CustomWatchThemePreviewController>(
37 - () => CustomWatchThemePreviewController(), 40 + () => CustomWatchThemePreviewController(Get.find<ThemeApi>()),
38 ); 41 );
39 } 42 }
40 } 43 }
1 import 'package:doublefeel_flutter/app/routes/app_pages.dart'; 1 import 'package:doublefeel_flutter/app/routes/app_pages.dart';
  2 +import 'package:doublefeel_flutter/core/network/api/theme_api.dart';
  3 +import 'package:doublefeel_flutter/core/result/app_result.dart';
2 import 'package:doublefeel_flutter/core/util/app_toast.dart'; 4 import 'package:doublefeel_flutter/core/util/app_toast.dart';
3 import 'package:doublefeel_flutter/pigeon/wear_engine_api.g.dart'; 5 import 'package:doublefeel_flutter/pigeon/wear_engine_api.g.dart';
4 import 'package:flutter/material.dart'; 6 import 'package:flutter/material.dart';
@@ -8,10 +10,15 @@ import '../models/watch_theme_models.dart'; @@ -8,10 +10,15 @@ import '../models/watch_theme_models.dart';
8 import '../widgets/watch_theme_dialogs.dart'; 10 import '../widgets/watch_theme_dialogs.dart';
9 11
10 class CreateWatchThemeController extends GetxController { 12 class CreateWatchThemeController extends GetxController {
  13 + CreateWatchThemeController(this._themeApi);
  14 +
  15 + final ThemeApi _themeApi;
  16 +
11 final customThemeName = ''.obs; 17 final customThemeName = ''.obs;
12 final agreedToSubmission = true.obs; 18 final agreedToSubmission = true.obs;
13 final customStatusNames = ['状态优秀', '状态正常', '注意压力', '压力过载'].obs; 19 final customStatusNames = ['状态优秀', '状态正常', '注意压力', '压力过载'].obs;
14 final customImagePaths = RxList<String?>.filled(4, null); 20 final customImagePaths = RxList<String?>.filled(4, null);
  21 + final isSaving = false.obs;
15 late final TextEditingController themeNameController; 22 late final TextEditingController themeNameController;
16 23
17 @override 24 @override
@@ -30,9 +37,10 @@ class CreateWatchThemeController extends GetxController { @@ -30,9 +37,10 @@ class CreateWatchThemeController extends GetxController {
30 } 37 }
31 38
32 bool get canSaveCustomTheme => 39 bool get canSaveCustomTheme =>
  40 + !isSaving.value &&
33 customThemeName.value.isNotEmpty && 41 customThemeName.value.isNotEmpty &&
34 agreedToSubmission.value && 42 agreedToSubmission.value &&
35 - customImagePaths.any((path) => path != null && path.isNotEmpty); 43 + customImagePaths.every((path) => path != null && path.isNotEmpty);
36 44
37 Future<void> pickCustomImage(int index) async { 45 Future<void> pickCustomImage(int index) async {
38 try { 46 try {
@@ -81,12 +89,31 @@ class CreateWatchThemeController extends GetxController { @@ -81,12 +89,31 @@ class CreateWatchThemeController extends GetxController {
81 agreedToSubmission.toggle(); 89 agreedToSubmission.toggle();
82 } 90 }
83 91
84 - void saveCustomTheme() { 92 + Future<void> saveCustomTheme() async {
85 if (!canSaveCustomTheme) { 93 if (!canSaveCustomTheme) {
86 return; 94 return;
87 } 95 }
  96 +
  97 + isSaving.value = true;
  98 + final result = await _themeApi.createTheme(
  99 + name: customThemeName.value,
  100 + fullOfEnergyName: customStatusNames[0],
  101 + normalName: customStatusNames[1],
  102 + overpressureName: customStatusNames[3],
  103 + fullOfEnergyImage: customImagePaths[0] ?? '',
  104 + normalImage: customImagePaths[1] ?? '',
  105 + overpressureImage: customImagePaths[3] ?? customImagePaths[2] ?? '',
  106 + );
  107 + isSaving.value = false;
  108 +
  109 + if (result is! AppSuccess<void>) {
  110 + AppToast.show('主题保存失败');
  111 + return;
  112 + }
  113 +
  114 + final createdTheme = await _loadCreatedTheme();
88 Get.toNamed(Routes.WATCH_THEME_CUSTOM_PREVIEW, arguments: { 115 Get.toNamed(Routes.WATCH_THEME_CUSTOM_PREVIEW, arguments: {
89 - 'theme': _buildThemeItem(), 116 + 'theme': createdTheme ?? _buildThemeItem(),
90 }); 117 });
91 } 118 }
92 119
@@ -103,4 +130,16 @@ class CreateWatchThemeController extends GetxController { @@ -103,4 +130,16 @@ class CreateWatchThemeController extends GetxController {
103 ], 130 ],
104 ); 131 );
105 } 132 }
  133 +
  134 + Future<WatchThemeItem?> _loadCreatedTheme() async {
  135 + final result = await _themeApi.getThemeList(errorHandlingPolicy: null);
  136 + if (result is! AppSuccess<WatchThemeResponse>) {
  137 + return null;
  138 + }
  139 + final matchedThemes = result.data.themes
  140 + .where((theme) => theme.title == customThemeName.value)
  141 + .toList()
  142 + ..sort((a, b) => (b.createTime ?? 0).compareTo(a.createTime ?? 0));
  143 + return matchedThemes.firstOrNull;
  144 + }
106 } 145 }
  1 +import 'dart:convert';
  2 +
  3 +import 'package:doublefeel_flutter/core/network/api/theme_api.dart';
  4 +import 'package:doublefeel_flutter/core/result/app_result.dart';
  5 +import 'package:doublefeel_flutter/core/util/app_toast.dart';
  6 +import 'package:doublefeel_flutter/pigeon/wear_engine_api.g.dart';
1 import 'package:get/get.dart'; 7 import 'package:get/get.dart';
2 8
3 import '../models/watch_theme_models.dart'; 9 import '../models/watch_theme_models.dart';
4 import '../widgets/watch_theme_dialogs.dart'; 10 import '../widgets/watch_theme_dialogs.dart';
5 11
6 class CustomWatchThemePreviewController extends GetxController { 12 class CustomWatchThemePreviewController extends GetxController {
  13 + CustomWatchThemePreviewController(this._themeApi);
  14 +
  15 + final ThemeApi _themeApi;
  16 +
7 late final WatchThemeItem themeItem; 17 late final WatchThemeItem themeItem;
  18 + final isApplying = false.obs;
  19 + final isDeleting = false.obs;
8 20
9 @override 21 @override
10 void onInit() { 22 void onInit() {
@@ -40,11 +52,46 @@ class CustomWatchThemePreviewController extends GetxController { @@ -40,11 +52,46 @@ class CustomWatchThemePreviewController extends GetxController {
40 barrierDismissible: true, 52 barrierDismissible: true,
41 ); 53 );
42 if (shouldDelete == true) { 54 if (shouldDelete == true) {
  55 + final themeId = themeItem.id;
  56 + if (themeId == null) {
  57 + Get.back();
  58 + return;
  59 + }
  60 + isDeleting.value = true;
  61 + final result = await _themeApi.deleteTheme(themeId);
  62 + isDeleting.value = false;
  63 + if (result is! AppSuccess<void>) {
  64 + AppToast.show('删除主题失败');
  65 + return;
  66 + }
  67 + AppToast.show('已删除主题');
43 Get.back(); 68 Get.back();
44 } 69 }
45 } 70 }
46 71
47 - void addWatchFace() {  
48 - // Hook to NativeHostApiStubs when the native watch-face install flow is ready. 72 + Future<void> addWatchFace() async {
  73 + final themeId = themeItem.id;
  74 + if (themeId == null) {
  75 + AppToast.show('主题信息不完整');
  76 + return;
  77 + }
  78 +
  79 + isApplying.value = true;
  80 + final result = await _themeApi.applyTheme(themeId);
  81 + if (result is! AppSuccess<void>) {
  82 + isApplying.value = false;
  83 + AppToast.show('应用主题失败');
  84 + return;
  85 + }
  86 +
  87 + try {
  88 + await WearEngineHostApi().sendWatchSyncPayload(
  89 + jsonEncode(themeItem.toJson()),
  90 + );
  91 + } catch (_) {
  92 + // The active theme is already saved on the server.
  93 + }
  94 + isApplying.value = false;
  95 + AppToast.show('已应用主题');
49 } 96 }
50 } 97 }
1 import 'package:doublefeel_flutter/app/routes/app_pages.dart'; 1 import 'package:doublefeel_flutter/app/routes/app_pages.dart';
  2 +import 'package:doublefeel_flutter/core/network/api/theme_api.dart';
  3 +import 'package:doublefeel_flutter/core/result/app_result.dart';
2 import 'package:get/get.dart'; 4 import 'package:get/get.dart';
3 5
4 import '../models/watch_theme_models.dart'; 6 import '../models/watch_theme_models.dart';
5 7
6 class WatchThemeController extends GetxController { 8 class WatchThemeController extends GetxController {
  9 + WatchThemeController(this._themeApi);
  10 +
  11 + final ThemeApi _themeApi;
  12 +
7 final selectedOfficialIndex = 0.obs; 13 final selectedOfficialIndex = 0.obs;
8 final hasCustomThemes = false.obs; 14 final hasCustomThemes = false.obs;
9 final isPremium = false.obs; 15 final isPremium = false.obs;
  16 + final isLoadingThemes = false.obs;
  17 + final officialThemeItems = <WatchThemeItem>[...officialThemes].obs;
  18 + final customThemeItems = <WatchThemeItem>[...customThemes].obs;
10 19
11 @override 20 @override
12 void onInit() { 21 void onInit() {
@@ -16,6 +25,35 @@ class WatchThemeController extends GetxController { @@ -16,6 +25,35 @@ class WatchThemeController extends GetxController {
16 hasCustomThemes.value = args['hasCustomThemes'] == true; 25 hasCustomThemes.value = args['hasCustomThemes'] == true;
17 isPremium.value = args['isPremium'] == true || hasCustomThemes.value; 26 isPremium.value = args['isPremium'] == true || hasCustomThemes.value;
18 } 27 }
  28 + loadThemeList();
  29 + }
  30 +
  31 + Future<void> loadThemeList() async {
  32 + isLoadingThemes.value = true;
  33 + final result = await _themeApi.getThemeList(errorHandlingPolicy: null);
  34 + isLoadingThemes.value = false;
  35 +
  36 + if (result is! AppSuccess<WatchThemeResponse>) {
  37 + hasCustomThemes.value = customThemeItems.isNotEmpty;
  38 + isPremium.value = isPremium.value || hasCustomThemes.value;
  39 + return;
  40 + }
  41 +
  42 + final themes = result.data.themes;
  43 + if (themes.isEmpty) {
  44 + hasCustomThemes.value = customThemeItems.isNotEmpty;
  45 + isPremium.value = isPremium.value || hasCustomThemes.value;
  46 + return;
  47 + }
  48 +
  49 + final official = themes.where((theme) => !theme.isCustomTheme).toList();
  50 + final custom = themes.where((theme) => theme.isCustomTheme).toList();
  51 + if (official.isNotEmpty) {
  52 + officialThemeItems.assignAll(official);
  53 + }
  54 + customThemeItems.assignAll(custom);
  55 + hasCustomThemes.value = custom.isNotEmpty;
  56 + isPremium.value = isPremium.value || hasCustomThemes.value;
19 } 57 }
20 58
21 void executeBackLogic() { 59 void executeBackLogic() {
@@ -25,7 +63,7 @@ class WatchThemeController extends GetxController { @@ -25,7 +63,7 @@ class WatchThemeController extends GetxController {
25 void selectOfficialTheme(int index) { 63 void selectOfficialTheme(int index) {
26 selectedOfficialIndex.value = index; 64 selectedOfficialIndex.value = index;
27 Get.toNamed(Routes.WATCH_THEME_PREVIEW, arguments: { 65 Get.toNamed(Routes.WATCH_THEME_PREVIEW, arguments: {
28 - 'theme': officialThemes[index], 66 + 'theme': officialThemeItems[index],
29 }); 67 });
30 } 68 }
31 69
  1 +import 'dart:convert';
  2 +
  3 +import 'package:doublefeel_flutter/core/network/api/theme_api.dart';
  4 +import 'package:doublefeel_flutter/core/result/app_result.dart';
  5 +import 'package:doublefeel_flutter/core/util/app_toast.dart';
  6 +import 'package:doublefeel_flutter/pigeon/wear_engine_api.g.dart';
1 import 'package:get/get.dart'; 7 import 'package:get/get.dart';
2 8
3 import '../models/watch_theme_models.dart'; 9 import '../models/watch_theme_models.dart';
4 10
5 class WatchThemePreviewController extends GetxController { 11 class WatchThemePreviewController extends GetxController {
  12 + WatchThemePreviewController(this._themeApi);
  13 +
  14 + final ThemeApi _themeApi;
  15 +
6 late final WatchThemeItem themeItem; 16 late final WatchThemeItem themeItem;
  17 + final isApplying = false.obs;
7 18
8 @override 19 @override
9 void onInit() { 20 void onInit() {
@@ -26,7 +37,29 @@ class WatchThemePreviewController extends GetxController { @@ -26,7 +37,29 @@ class WatchThemePreviewController extends GetxController {
26 Get.back(); 37 Get.back();
27 } 38 }
28 39
29 - void addWatchFace() {  
30 - // Hook to NativeHostApiStubs when the native watch-face install flow is ready. 40 + Future<void> addWatchFace() async {
  41 + final themeId = themeItem.id;
  42 + if (themeId == null) {
  43 + AppToast.show('主题信息不完整');
  44 + return;
  45 + }
  46 +
  47 + isApplying.value = true;
  48 + final result = await _themeApi.applyTheme(themeId);
  49 + if (result is! AppSuccess<void>) {
  50 + isApplying.value = false;
  51 + AppToast.show('应用主题失败');
  52 + return;
  53 + }
  54 +
  55 + try {
  56 + await WearEngineHostApi().sendWatchSyncPayload(
  57 + jsonEncode(themeItem.toJson()),
  58 + );
  59 + } catch (_) {
  60 + // The server state has been updated; watch sync can be retried later.
  61 + }
  62 + isApplying.value = false;
  63 + AppToast.show('已应用主题');
31 } 64 }
32 } 65 }
  1 +import 'dart:ui';
  2 +
  3 +import 'package:doublefeel_flutter/app/modules/watch_theme/widgets/watch_theme_colors.dart';
  4 +
1 class WatchThemeItem { 5 class WatchThemeItem {
2 const WatchThemeItem({ 6 const WatchThemeItem({
3 this.id, 7 this.id,
  8 + this.createTime,
  9 + this.updateTime,
  10 + this.userId,
  11 + this.status,
4 this.isCustomTheme = false, 12 this.isCustomTheme = false,
5 this.isDefaultCharacter = false, 13 this.isDefaultCharacter = false,
6 required this.title, 14 required this.title,
@@ -8,11 +16,76 @@ class WatchThemeItem { @@ -8,11 +16,76 @@ class WatchThemeItem {
8 }); 16 });
9 17
10 final int? id; 18 final int? id;
  19 + final int? createTime;
  20 + final int? updateTime;
  21 + final int? userId;
  22 + final int? status;
11 final bool isDefaultCharacter; 23 final bool isDefaultCharacter;
12 final bool isCustomTheme; 24 final bool isCustomTheme;
13 final String title; 25 final String title;
14 final List<WatchThemeItemInfo> infoList; 26 final List<WatchThemeItemInfo> infoList;
15 27
  28 + factory WatchThemeItem.fromJson(Map<String, dynamic> json) {
  29 + final isDefaultTheme = json['is_default_theme'] == true;
  30 + final userId = json['user_id'] as int?;
  31 + final positiveDescription = json['positive_description'] as String?;
  32 + final normalDescription = json['normal_description'] as String?;
  33 + final negativeDescription = json['negative_description'] as String?;
  34 + final positiveImage = json['positive_image'] as String?;
  35 + final normalImage = json['normal_image'] as String?;
  36 + final negativeImage = json['negative_image'] as String?;
  37 +
  38 + return WatchThemeItem(
  39 + id: json['id'] as int?,
  40 + createTime: json['create_time'] as int?,
  41 + updateTime: json['update_time'] as int?,
  42 + userId: userId,
  43 + status: json['status'] as int?,
  44 + isDefaultCharacter: isDefaultTheme,
  45 + isCustomTheme: userId != null,
  46 + title: (json['theme_name'] as String?) ?? '自定义主题',
  47 + infoList: [
  48 + WatchThemeItemInfo(
  49 + title: positiveDescription ?? '状态优秀',
  50 + imgUrl: positiveImage,
  51 + ),
  52 + WatchThemeItemInfo(
  53 + title: normalDescription ?? '状态正常',
  54 + imgUrl: normalImage,
  55 + ),
  56 + WatchThemeItemInfo(
  57 + title: negativeDescription ?? '注意压力',
  58 + imgUrl: negativeImage,
  59 + ),
  60 + WatchThemeItemInfo(
  61 + title: negativeDescription ?? '压力过载',
  62 + imgUrl: negativeImage,
  63 + ),
  64 + ],
  65 + );
  66 + }
  67 +
  68 + Map<String, dynamic> toJson() {
  69 + final excellent = infoList.elementAtOrNull(0);
  70 + final normal = infoList.elementAtOrNull(1);
  71 + final overload = infoList.elementAtOrNull(3) ?? infoList.elementAtOrNull(2);
  72 + final json = <String, dynamic>{};
  73 + if (id != null) json['id'] = id;
  74 + if (createTime != null) json['create_time'] = createTime;
  75 + if (updateTime != null) json['update_time'] = updateTime;
  76 + if (userId != null) json['user_id'] = userId;
  77 + if (status != null) json['status'] = status;
  78 + json['theme_name'] = title;
  79 + json['is_default_theme'] = isDefaultCharacter;
  80 + json['positive_description'] = excellent?.title;
  81 + json['positive_image'] = excellent?.image;
  82 + json['normal_description'] = normal?.title;
  83 + json['normal_image'] = normal?.image;
  84 + json['negative_description'] = overload?.title;
  85 + json['negative_image'] = overload?.image;
  86 + return json;
  87 + }
  88 +
16 static WatchThemeItem empty() { 89 static WatchThemeItem empty() {
17 return WatchThemeItem( 90 return WatchThemeItem(
18 title: '自定义主题', 91 title: '自定义主题',
@@ -27,6 +100,63 @@ class WatchThemeItemInfo { @@ -27,6 +100,63 @@ class WatchThemeItemInfo {
27 final String? assetPath; 100 final String? assetPath;
28 101
29 WatchThemeItemInfo({required this.title, this.imgUrl, this.assetPath}); 102 WatchThemeItemInfo({required this.title, this.imgUrl, this.assetPath});
  103 +
  104 + String? get image => imgUrl ?? assetPath;
  105 +}
  106 +
  107 +class WatchThemeResponse {
  108 + const WatchThemeResponse({this.themes = const []});
  109 +
  110 + final List<WatchThemeItem> themes;
  111 +
  112 + factory WatchThemeResponse.fromJson(Map<String, dynamic> json) {
  113 + final rawThemes = json['themes'];
  114 + return WatchThemeResponse(
  115 + themes: rawThemes is List
  116 + ? rawThemes
  117 + .whereType<Map>()
  118 + .map((theme) => WatchThemeItem.fromJson(
  119 + Map<String, dynamic>.from(theme),
  120 + ))
  121 + .toList()
  122 + : const [],
  123 + );
  124 + }
  125 +}
  126 +
  127 +class WatchThemeUpsertRequest {
  128 + const WatchThemeUpsertRequest({
  129 + this.themeId,
  130 + required this.name,
  131 + required this.fullOfEnergyName,
  132 + required this.normalName,
  133 + required this.overpressureName,
  134 + required this.fullOfEnergyImage,
  135 + required this.normalImage,
  136 + required this.overpressureImage,
  137 + });
  138 +
  139 + final int? themeId;
  140 + final String name;
  141 + final String fullOfEnergyName;
  142 + final String normalName;
  143 + final String overpressureName;
  144 + final String fullOfEnergyImage;
  145 + final String normalImage;
  146 + final String overpressureImage;
  147 +
  148 + Map<String, dynamic> toJson() {
  149 + return {
  150 + if (themeId != null) 'theme_id': themeId,
  151 + 'theme_name': name,
  152 + 'positive_description': fullOfEnergyName,
  153 + 'positive_image': fullOfEnergyImage,
  154 + 'normal_description': normalName,
  155 + 'normal_image': normalImage,
  156 + 'negative_description': overpressureName,
  157 + 'negative_image': overpressureImage,
  158 + };
  159 + }
30 } 160 }
31 161
32 final officialThemes = <WatchThemeItem>[ 162 final officialThemes = <WatchThemeItem>[
@@ -161,3 +291,17 @@ final customThemes = <WatchThemeItem>[ @@ -161,3 +291,17 @@ final customThemes = <WatchThemeItem>[
161 ], 291 ],
162 ), 292 ),
163 ]; 293 ];
  294 +
  295 +final defaultThemeTemplates = [
  296 + WatchThemeTemplateItem(title: '状态优秀', color: WatchThemeColors.excellent),
  297 + WatchThemeTemplateItem(title: '状态正常', color: WatchThemeColors.normal),
  298 + WatchThemeTemplateItem(title: '注意压力', color: WatchThemeColors.stress),
  299 + WatchThemeTemplateItem(title: '压力过载', color: WatchThemeColors.overload),
  300 +];
  301 +
  302 +class WatchThemeTemplateItem {
  303 + final String title;
  304 + final Color color;
  305 +
  306 + WatchThemeTemplateItem({required this.title, required this.color});
  307 +}
@@ -59,7 +59,7 @@ class CreateWatchThemeView extends GetView<CreateWatchThemeController> { @@ -59,7 +59,7 @@ class CreateWatchThemeView extends GetView<CreateWatchThemeController> {
59 ), 59 ),
60 Expanded( 60 Expanded(
61 child: SingleChildScrollView( 61 child: SingleChildScrollView(
62 - physics: const ClampingScrollPhysics(), 62 + physics: const AlwaysScrollableScrollPhysics(),
63 padding: EdgeInsets.only(bottom: 28.dp), 63 padding: EdgeInsets.only(bottom: 28.dp),
64 child: Column( 64 child: Column(
65 children: [ 65 children: [
@@ -130,8 +130,7 @@ class _EditorCard extends StatelessWidget { @@ -130,8 +130,7 @@ class _EditorCard extends StatelessWidget {
130 ), 130 ),
131 ), 131 ),
132 SizedBox(height: 14.dp), 132 SizedBox(height: 14.dp),
133 - Obx(  
134 - () => GridView.builder( 133 + GridView.builder(
135 shrinkWrap: true, 134 shrinkWrap: true,
136 padding: EdgeInsets.zero, 135 padding: EdgeInsets.zero,
137 physics: const NeverScrollableScrollPhysics(), 136 physics: const NeverScrollableScrollPhysics(),
@@ -143,16 +142,17 @@ class _EditorCard extends StatelessWidget { @@ -143,16 +142,17 @@ class _EditorCard extends StatelessWidget {
143 mainAxisExtent: 170.dp, 142 mainAxisExtent: 170.dp,
144 ), 143 ),
145 itemBuilder: (context, index) { 144 itemBuilder: (context, index) {
146 - return _UploadTile( 145 + return Obx(
  146 + () => _UploadTile(
147 index: index, 147 index: index,
148 color: _statusColors[index], 148 color: _statusColors[index],
149 label: controller.customStatusNames[index], 149 label: controller.customStatusNames[index],
150 path: controller.customImagePaths[index], 150 path: controller.customImagePaths[index],
151 onPick: () => controller.pickCustomImage(index), 151 onPick: () => controller.pickCustomImage(index),
152 onRename: () => controller.showRenameStatusDialog(index), 152 onRename: () => controller.showRenameStatusDialog(index),
  153 + ),
153 ); 154 );
154 - },  
155 - ), 155 + },
156 ), 156 ),
157 SizedBox(height: 14.dp), 157 SizedBox(height: 14.dp),
158 Text( 158 Text(
@@ -235,6 +235,9 @@ class _UploadTile extends StatelessWidget { @@ -235,6 +235,9 @@ class _UploadTile extends StatelessWidget {
235 ), 235 ),
236 ), 236 ),
237 SizedBox(height: 10.dp), 237 SizedBox(height: 10.dp),
  238 + GestureDetector(
  239 + onTap: onRename,
  240 + child:
238 Row( 241 Row(
239 mainAxisAlignment: MainAxisAlignment.center, 242 mainAxisAlignment: MainAxisAlignment.center,
240 children: [ 243 children: [
@@ -246,16 +249,14 @@ class _UploadTile extends StatelessWidget { @@ -246,16 +249,14 @@ class _UploadTile extends StatelessWidget {
246 ), 249 ),
247 ), 250 ),
248 SizedBox(width: 4.dp), 251 SizedBox(width: 4.dp),
249 - GestureDetector(  
250 - onTap: onRename,  
251 - child: Icon( 252 + Icon(
252 Icons.edit_outlined, 253 Icons.edit_outlined,
253 color: const Color(0xFFA084EF), 254 color: const Color(0xFFA084EF),
254 size: 14.dp, 255 size: 14.dp,
255 ), 256 ),
256 - ),  
257 ], 257 ],
258 ), 258 ),
  259 + ),
259 ], 260 ],
260 ); 261 );
261 } 262 }
@@ -317,7 +318,7 @@ class _SaveButton extends StatelessWidget { @@ -317,7 +318,7 @@ class _SaveButton extends StatelessWidget {
317 return Opacity( 318 return Opacity(
318 opacity: enabled ? 1 : 0.4, 319 opacity: enabled ? 1 : 0.4,
319 child: GestureDetector( 320 child: GestureDetector(
320 - onTap: enabled ? controller.saveCustomTheme : null, 321 + onTap: enabled ? () => controller.saveCustomTheme() : null,
321 child: Container( 322 child: Container(
322 width: 280.dp, 323 width: 280.dp,
323 height: 48.dp, 324 height: 48.dp,
@@ -327,7 +328,7 @@ class _SaveButton extends StatelessWidget { @@ -327,7 +328,7 @@ class _SaveButton extends StatelessWidget {
327 borderRadius: BorderRadius.circular(24.dp), 328 borderRadius: BorderRadius.circular(24.dp),
328 ), 329 ),
329 child: Text( 330 child: Text(
330 - '保存主题', 331 + controller.isSaving.value ? '保存中' : '保存主题',
331 style: TextStyle( 332 style: TextStyle(
332 color: Colors.white, 333 color: Colors.white,
333 fontSize: 16.dp, 334 fontSize: 16.dp,
  1 +import 'package:doublefeel_flutter/app/modules/watch_theme/models/watch_theme_models.dart';
1 import 'package:doublefeel_flutter/core/util/size_extensions.dart'; 2 import 'package:doublefeel_flutter/core/util/size_extensions.dart';
2 import 'package:doublefeel_flutter/r.dart'; 3 import 'package:doublefeel_flutter/r.dart';
3 import 'package:flutter/material.dart'; 4 import 'package:flutter/material.dart';
@@ -114,12 +115,6 @@ class _CustomStatusPreviewCard extends StatelessWidget { @@ -114,12 +115,6 @@ class _CustomStatusPreviewCard extends StatelessWidget {
114 R.assetsImagesWatchThemeCustomStatusOverload, 115 R.assetsImagesWatchThemeCustomStatusOverload,
115 ]; 116 ];
116 117
117 - static const _colors = [  
118 - WatchThemeColors.excellent,  
119 - WatchThemeColors.normal,  
120 - WatchThemeColors.stress,  
121 - WatchThemeColors.overload,  
122 - ];  
123 118
124 @override 119 @override
125 Widget build(BuildContext context) { 120 Widget build(BuildContext context) {
@@ -150,7 +145,7 @@ class _CustomStatusPreviewCard extends StatelessWidget { @@ -150,7 +145,7 @@ class _CustomStatusPreviewCard extends StatelessWidget {
150 Text( 145 Text(
151 i < infoList.length ? infoList[i].title : '', 146 i < infoList.length ? infoList[i].title : '',
152 style: TextStyle( 147 style: TextStyle(
153 - color: _colors[i], 148 + color: defaultThemeTemplates[i].color,
154 fontSize: 12.dp, 149 fontSize: 12.dp,
155 ), 150 ),
156 ), 151 ),
1 -import 'package:doublefeel_flutter/app/modules/watch_theme/models/watch_theme_models.dart';  
2 import 'package:flutter/material.dart'; 1 import 'package:flutter/material.dart';
3 import 'package:flutter/services.dart'; 2 import 'package:flutter/services.dart';
4 import 'package:get/get.dart'; 3 import 'package:get/get.dart';
@@ -63,7 +62,7 @@ class WatchThemeView extends GetView<WatchThemeController> { @@ -63,7 +62,7 @@ class WatchThemeView extends GetView<WatchThemeController> {
63 const WatchThemeHeader(), 62 const WatchThemeHeader(),
64 const SizedBox(height: 26), 63 const SizedBox(height: 26),
65 OfficialThemeGrid( 64 OfficialThemeGrid(
66 - themes: officialThemes, 65 + themes: controller.officialThemeItems,
67 selectedIndex: 66 selectedIndex:
68 controller.selectedOfficialIndex.value, 67 controller.selectedOfficialIndex.value,
69 onThemeTap: controller.selectOfficialTheme, 68 onThemeTap: controller.selectOfficialTheme,
@@ -72,7 +71,7 @@ class WatchThemeView extends GetView<WatchThemeController> { @@ -72,7 +71,7 @@ class WatchThemeView extends GetView<WatchThemeController> {
72 CustomThemeCard( 71 CustomThemeCard(
73 isPremium: controller.isPremium.value, 72 isPremium: controller.isPremium.value,
74 hasCustomThemes: controller.hasCustomThemes.value, 73 hasCustomThemes: controller.hasCustomThemes.value,
75 - customThemes: customThemes, 74 + customThemes: controller.customThemeItems,
76 onCreateTap: controller.createCustomTheme, 75 onCreateTap: controller.createCustomTheme,
77 onThemeTap: controller.previewCustomTheme, 76 onThemeTap: controller.previewCustomTheme,
78 ), 77 ),
@@ -20,29 +20,34 @@ class StatusPreviewCard extends StatelessWidget { @@ -20,29 +20,34 @@ class StatusPreviewCard extends StatelessWidget {
20 SizedBox(height: 24.dp), 20 SizedBox(height: 24.dp),
21 Row( 21 Row(
22 mainAxisAlignment: MainAxisAlignment.spaceBetween, 22 mainAxisAlignment: MainAxisAlignment.spaceBetween,
23 - children: [  
24 - for (final item in themeItem.infoList)  
25 - Column(  
26 - children: [  
27 - WatchThemeCharacterAvatar(  
28 - size: 60,  
29 - assetPath: item.assetPath,  
30 - ),  
31 - SizedBox(height: 4.dp),  
32 - Text(  
33 - item.title,  
34 - style: TextStyle(  
35 - fontSize: 12.dp,  
36 - fontWeight: FontWeight.w400,  
37 - height: 1.25,  
38 - ),  
39 - ),  
40 - ],  
41 - ),  
42 - ], 23 + children: _previewItemView(),
43 ), 24 ),
44 ], 25 ],
45 ), 26 ),
46 ); 27 );
47 } 28 }
  29 +
  30 + List<Widget> _previewItemView() {
  31 + final infoList = themeItem.infoList;
  32 + return [
  33 + for (var i = 0; i < infoList.length; i++)
  34 + Column(
  35 + children: [
  36 + WatchThemeCharacterAvatar(
  37 + size: 60,
  38 + assetPath: infoList[i].assetPath,
  39 + ),
  40 + SizedBox(height: 4.dp),
  41 + Text(
  42 + i < infoList.length ? infoList[i].title : '',
  43 + style: TextStyle(
  44 + color: defaultThemeTemplates[i].color,
  45 + fontSize: 12.dp,
  46 + fontWeight: FontWeight.w400,
  47 + ),
  48 + ),
  49 + ],
  50 + ),
  51 + ];
  52 + }
48 } 53 }
@@ -47,7 +47,7 @@ class WatchThemeNavBar extends StatelessWidget { @@ -47,7 +47,7 @@ class WatchThemeNavBar extends StatelessWidget {
47 ), 47 ),
48 trailing == null 48 trailing == null
49 ? SizedBox( 49 ? SizedBox(
50 - width: 8.dp, 50 + width: 28.dp,
51 ) 51 )
52 : Center(child: trailing) 52 : Center(child: trailing)
53 ], 53 ],
  1 +import '../../../app/modules/watch_theme/models/watch_theme_models.dart';
  2 +import '../../error/http_error_handling_policy.dart';
  3 +import '../../result/app_result.dart';
  4 +import '../../result/safe_call.dart';
  5 +import '../api_paths.dart';
  6 +import '../dio_client.dart';
  7 +
  8 +class ThemeApi {
  9 + ThemeApi(this._dioClient);
  10 +
  11 + final DioClient _dioClient;
  12 +
  13 + Future<AppResult<void>> createTheme({
  14 + required String name,
  15 + required String fullOfEnergyName,
  16 + required String normalName,
  17 + required String overpressureName,
  18 + required String fullOfEnergyImage,
  19 + required String normalImage,
  20 + required String overpressureImage,
  21 + }) {
  22 + return safeCall(
  23 + call: () async {
  24 + await _dioClient.dio.post(
  25 + ApiPaths.watchTheme,
  26 + data: WatchThemeUpsertRequest(
  27 + name: name,
  28 + fullOfEnergyName: fullOfEnergyName,
  29 + normalName: normalName,
  30 + overpressureName: overpressureName,
  31 + fullOfEnergyImage: fullOfEnergyImage,
  32 + normalImage: normalImage,
  33 + overpressureImage: overpressureImage,
  34 + ).toJson(),
  35 + );
  36 + },
  37 + );
  38 + }
  39 +
  40 + Future<AppResult<void>> editTheme({
  41 + required int themeId,
  42 + required String name,
  43 + required String fullOfEnergyName,
  44 + required String normalName,
  45 + required String overpressureName,
  46 + required String fullOfEnergyImage,
  47 + required String normalImage,
  48 + required String overpressureImage,
  49 + }) {
  50 + return safeCall(
  51 + call: () async {
  52 + await _dioClient.dio.put(
  53 + ApiPaths.watchTheme,
  54 + data: WatchThemeUpsertRequest(
  55 + themeId: themeId,
  56 + name: name,
  57 + fullOfEnergyName: fullOfEnergyName,
  58 + normalName: normalName,
  59 + overpressureName: overpressureName,
  60 + fullOfEnergyImage: fullOfEnergyImage,
  61 + normalImage: normalImage,
  62 + overpressureImage: overpressureImage,
  63 + ).toJson(),
  64 + );
  65 + },
  66 + );
  67 + }
  68 +
  69 + Future<AppResult<WatchThemeItem>> getTheme({
  70 + required int themeId,
  71 + HttpErrorHandlingPolicy? errorHandlingPolicy =
  72 + HttpErrorHandlingPolicy.defaultPolicy,
  73 + }) {
  74 + return safeCall(
  75 + call: () async {
  76 + final response = await _dioClient.dio.get(
  77 + ApiPaths.watchTheme,
  78 + queryParameters: {'theme_id': themeId},
  79 + );
  80 + return WatchThemeItem.fromJson(response.data as Map<String, dynamic>);
  81 + },
  82 + errorHandlingPolicy: errorHandlingPolicy,
  83 + );
  84 + }
  85 +
  86 + Future<AppResult<WatchThemeResponse>> getThemeList({
  87 + HttpErrorHandlingPolicy? errorHandlingPolicy =
  88 + HttpErrorHandlingPolicy.defaultPolicy,
  89 + }) {
  90 + return safeCall(
  91 + call: () async {
  92 + final response = await _dioClient.dio.get(ApiPaths.watchThemeList);
  93 + return WatchThemeResponse.fromJson(
  94 + response.data as Map<String, dynamic>,
  95 + );
  96 + },
  97 + errorHandlingPolicy: errorHandlingPolicy,
  98 + );
  99 + }
  100 +
  101 + Future<AppResult<void>> deleteTheme(int themeId) {
  102 + return safeCall(
  103 + call: () async {
  104 + await _dioClient.dio.delete(
  105 + ApiPaths.watchTheme,
  106 + data: {'theme_id': themeId},
  107 + );
  108 + },
  109 + );
  110 + }
  111 +
  112 + Future<AppResult<WatchThemeItem>> getCurrentTheme({
  113 + bool? isOther,
  114 + HttpErrorHandlingPolicy? errorHandlingPolicy =
  115 + HttpErrorHandlingPolicy.defaultPolicy,
  116 + }) {
  117 + return safeCall(
  118 + call: () async {
  119 + final response = await _dioClient.dio.get(
  120 + ApiPaths.watchThemeActive,
  121 + queryParameters: {
  122 + if (isOther != null) 'is_other': isOther ? 1 : 0,
  123 + },
  124 + );
  125 + return WatchThemeItem.fromJson(response.data as Map<String, dynamic>);
  126 + },
  127 + errorHandlingPolicy: errorHandlingPolicy,
  128 + );
  129 + }
  130 +
  131 + Future<AppResult<void>> applyTheme(int themeId) {
  132 + return safeCall(
  133 + call: () async {
  134 + await _dioClient.dio.post(
  135 + ApiPaths.watchThemeActive,
  136 + data: {'theme_id': themeId},
  137 + );
  138 + },
  139 + );
  140 + }
  141 +
  142 + // Keep compatibility with the original Swift ThemeEndpoint spelling.
  143 + Future<AppResult<void>> appplyTheme(int themeId) => applyTheme(themeId);
  144 +}
@@ -48,4 +48,10 @@ abstract final class ApiPaths { @@ -48,4 +48,10 @@ abstract final class ApiPaths {
48 48
49 // VIP 49 // VIP
50 static const userVipInfo = '/client/doublefeel/user/vip/info/'; 50 static const userVipInfo = '/client/doublefeel/user/vip/info/';
  51 +
  52 + // Watch theme
  53 + static const watchTheme = '/client/doublefeel/theme/watch_theme/';
  54 + static const watchThemeList = '/client/doublefeel/theme/watch_theme/list/';
  55 + static const watchThemeActive =
  56 + '/client/doublefeel/theme/watch_theme/active/';
51 } 57 }
@@ -62,8 +62,7 @@ import 'app_localizations_zh.dart'; @@ -62,8 +62,7 @@ import 'app_localizations_zh.dart';
62 /// be consistent with the languages listed in the AppLocalizations.supportedLocales 62 /// be consistent with the languages listed in the AppLocalizations.supportedLocales
63 /// property. 63 /// property.
64 abstract class AppLocalizations { 64 abstract class AppLocalizations {
65 - AppLocalizations(String locale)  
66 - : localeName = intl.Intl.canonicalizedLocale(locale.toString()); 65 + AppLocalizations(String locale) : localeName = intl.Intl.canonicalizedLocale(locale.toString());
67 66
68 final String localeName; 67 final String localeName;
69 68
@@ -71,8 +70,7 @@ abstract class AppLocalizations { @@ -71,8 +70,7 @@ abstract class AppLocalizations {
71 return Localizations.of<AppLocalizations>(context, AppLocalizations); 70 return Localizations.of<AppLocalizations>(context, AppLocalizations);
72 } 71 }
73 72
74 - static const LocalizationsDelegate<AppLocalizations> delegate =  
75 - _AppLocalizationsDelegate(); 73 + static const LocalizationsDelegate<AppLocalizations> delegate = _AppLocalizationsDelegate();
76 74
77 /// A list of this localizations delegate along with the default localizations 75 /// A list of this localizations delegate along with the default localizations
78 /// delegates. 76 /// delegates.
@@ -84,8 +82,7 @@ abstract class AppLocalizations { @@ -84,8 +82,7 @@ abstract class AppLocalizations {
84 /// Additional delegates can be added by appending to this list in 82 /// Additional delegates can be added by appending to this list in
85 /// MaterialApp. This list does not have to be used at all if a custom list 83 /// MaterialApp. This list does not have to be used at all if a custom list
86 /// of delegates is preferred or required. 84 /// of delegates is preferred or required.
87 - static const List<LocalizationsDelegate<dynamic>> localizationsDelegates =  
88 - <LocalizationsDelegate<dynamic>>[ 85 + static const List<LocalizationsDelegate<dynamic>> localizationsDelegates = <LocalizationsDelegate<dynamic>>[
89 delegate, 86 delegate,
90 GlobalMaterialLocalizations.delegate, 87 GlobalMaterialLocalizations.delegate,
91 GlobalCupertinoLocalizations.delegate, 88 GlobalCupertinoLocalizations.delegate,
@@ -528,8 +525,7 @@ abstract class AppLocalizations { @@ -528,8 +525,7 @@ abstract class AppLocalizations {
528 /// 525 ///
529 /// In zh, this message translates to: 526 /// In zh, this message translates to:
530 /// **'你们现在可以查看彼此的 HRV、压力与睡眠变化,并在对方疲惫时及时送上关心。'** 527 /// **'你们现在可以查看彼此的 HRV、压力与睡眠变化,并在对方疲惫时及时送上关心。'**
531 - String  
532 - get youCanNowViewEachOtherSHrvStressLevelsAndSleepPatternsAndReachOutToCheckInWhenTheOtherPersonSeemsTired; 528 + String get youCanNowViewEachOtherSHrvStressLevelsAndSleepPatternsAndReachOutToCheckInWhenTheOtherPersonSeemsTired;
533 529
534 /// No description provided for @bindPartnerTitle. 530 /// No description provided for @bindPartnerTitle.
535 /// 531 ///
@@ -1738,8 +1734,7 @@ abstract class AppLocalizations { @@ -1738,8 +1734,7 @@ abstract class AppLocalizations {
1738 String get dailyActions; 1734 String get dailyActions;
1739 } 1735 }
1740 1736
1741 -class _AppLocalizationsDelegate  
1742 - extends LocalizationsDelegate<AppLocalizations> { 1737 +class _AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalizations> {
1743 const _AppLocalizationsDelegate(); 1738 const _AppLocalizationsDelegate();
1744 1739
1745 @override 1740 @override
@@ -1748,25 +1743,25 @@ class _AppLocalizationsDelegate @@ -1748,25 +1743,25 @@ class _AppLocalizationsDelegate
1748 } 1743 }
1749 1744
1750 @override 1745 @override
1751 - bool isSupported(Locale locale) =>  
1752 - <String>['en', 'zh'].contains(locale.languageCode); 1746 + bool isSupported(Locale locale) => <String>['en', 'zh'].contains(locale.languageCode);
1753 1747
1754 @override 1748 @override
1755 bool shouldReload(_AppLocalizationsDelegate old) => false; 1749 bool shouldReload(_AppLocalizationsDelegate old) => false;
1756 } 1750 }
1757 1751
1758 AppLocalizations lookupAppLocalizations(Locale locale) { 1752 AppLocalizations lookupAppLocalizations(Locale locale) {
  1753 +
  1754 +
1759 // Lookup logic when only language code is specified. 1755 // Lookup logic when only language code is specified.
1760 switch (locale.languageCode) { 1756 switch (locale.languageCode) {
1761 - case 'en':  
1762 - return AppLocalizationsEn();  
1763 - case 'zh':  
1764 - return AppLocalizationsZh(); 1757 + case 'en': return AppLocalizationsEn();
  1758 + case 'zh': return AppLocalizationsZh();
1765 } 1759 }
1766 1760
1767 throw FlutterError( 1761 throw FlutterError(
1768 - 'AppLocalizations.delegate failed to load unsupported locale "$locale". This is likely '  
1769 - 'an issue with the localizations generation tool. Please file an issue '  
1770 - 'on GitHub with a reproducible sample app and the gen-l10n configuration '  
1771 - 'that was used.'); 1762 + 'AppLocalizations.delegate failed to load unsupported locale "$locale". This is likely '
  1763 + 'an issue with the localizations generation tool. Please file an issue '
  1764 + 'on GitHub with a reproducible sample app and the gen-l10n configuration '
  1765 + 'that was used.'
  1766 + );
1772 } 1767 }
1 -// ignore: unused_import  
2 -import 'package:intl/intl.dart' as intl;  
3 import 'app_localizations.dart'; 1 import 'app_localizations.dart';
4 2
5 // ignore_for_file: type=lint 3 // ignore_for_file: type=lint
@@ -69,12 +67,10 @@ class AppLocalizationsEn extends AppLocalizations { @@ -69,12 +67,10 @@ class AppLocalizationsEn extends AppLocalizations {
69 String get settings => 'Settings'; 67 String get settings => 'Settings';
70 68
71 @override 69 @override
72 - String get onboardingIntroTitle =>  
73 - 'DoubleFeel is a health companion app built for Apple Watch'; 70 + String get onboardingIntroTitle => 'DoubleFeel is a health companion app built for Apple Watch';
74 71
75 @override 72 @override
76 - String get onboardingIntroBody =>  
77 - 'We hope to help you\n<em>notice changes in your mind and body, and help the people who love you</em> see when you are <em>tired or need support</em>'; 73 + String get onboardingIntroBody => 'We hope to help you\n<em>notice changes in your mind and body, and help the people who love you</em> see when you are <em>tired or need support</em>';
78 74
79 @override 75 @override
80 String get onboardingStateQuestion => 'Which of these often happens to you?'; 76 String get onboardingStateQuestion => 'Which of these often happens to you?';
@@ -86,19 +82,16 @@ class AppLocalizationsEn extends AppLocalizations { @@ -86,19 +82,16 @@ class AppLocalizationsEn extends AppLocalizations {
86 String get onboardingStateTired => 'I get tired easily'; 82 String get onboardingStateTired => 'I get tired easily';
87 83
88 @override 84 @override
89 - String get onboardingStatePoorRest =>  
90 - 'I wake up but still do not feel rested'; 85 + String get onboardingStatePoorRest => 'I wake up but still do not feel rested';
91 86
92 @override 87 @override
93 - String get onboardingStateNeedStimulants =>  
94 - 'I rely on cigarettes, alcohol, coffee, or other stimulants to stay alert'; 88 + String get onboardingStateNeedStimulants => 'I rely on cigarettes, alcohol, coffee, or other stimulants to stay alert';
95 89
96 @override 90 @override
97 String get onboardingStateNone => 'None of the above'; 91 String get onboardingStateNone => 'None of the above';
98 92
99 @override 93 @override
100 - String get onboardingStressGoalQuestion =>  
101 - 'What do you want to learn by understanding stress?'; 94 + String get onboardingStressGoalQuestion => 'What do you want to learn by understanding stress?';
102 95
103 @override 96 @override
104 String get onboardingStressGoalSource => 'Understand where stress comes from'; 97 String get onboardingStressGoalSource => 'Understand where stress comes from';
@@ -107,8 +100,7 @@ class AppLocalizationsEn extends AppLocalizations { @@ -107,8 +100,7 @@ class AppLocalizationsEn extends AppLocalizations {
107 String get onboardingStressGoalReminder => 'Get reminded when stress appears'; 100 String get onboardingStressGoalReminder => 'Get reminded when stress appears';
108 101
109 @override 102 @override
110 - String get onboardingStressGoalLovedOnes =>  
111 - 'Let people who care about me know my stress state'; 103 + String get onboardingStressGoalLovedOnes => 'Let people who care about me know my stress state';
112 104
113 @override 105 @override
114 String get onboardingStressGoalRelax => 'Understand stress and feel lighter'; 106 String get onboardingStressGoalRelax => 'Understand stress and feel lighter';
@@ -117,8 +109,7 @@ class AppLocalizationsEn extends AppLocalizations { @@ -117,8 +109,7 @@ class AppLocalizationsEn extends AppLocalizations {
117 String get onboardingStressGoalBodyTalk => 'Communicate better with my body'; 109 String get onboardingStressGoalBodyTalk => 'Communicate better with my body';
118 110
119 @override 111 @override
120 - String get onboardingReliefQuestion =>  
121 - 'Which methods do you think can ease stress?'; 112 + String get onboardingReliefQuestion => 'Which methods do you think can ease stress?';
122 113
123 @override 114 @override
124 String get onboardingReliefSleep => 'Regular sleep'; 115 String get onboardingReliefSleep => 'Regular sleep';
@@ -142,8 +133,7 @@ class AppLocalizationsEn extends AppLocalizations { @@ -142,8 +133,7 @@ class AppLocalizationsEn extends AppLocalizations {
142 String get onboardingKeyDataTitle => 'Did you know?'; 133 String get onboardingKeyDataTitle => 'Did you know?';
143 134
144 @override 135 @override
145 - String get onboardingKeyDataSubtitle =>  
146 - 'Everyone has a magical and important body metric that can help us:'; 136 + String get onboardingKeyDataSubtitle => 'Everyone has a magical and important body metric that can help us:';
147 137
148 @override 138 @override
149 String get onboardingKeyDataStress => 'Monitor stress'; 139 String get onboardingKeyDataStress => 'Monitor stress';
@@ -158,8 +148,7 @@ class AppLocalizationsEn extends AppLocalizations { @@ -158,8 +148,7 @@ class AppLocalizationsEn extends AppLocalizations {
158 String get onboardingKeyDataHabits => 'Build healthy habits'; 148 String get onboardingKeyDataHabits => 'Build healthy habits';
159 149
160 @override 150 @override
161 - String get onboardingKeyDataLovedOnes =>  
162 - 'Help important people care about your state in time'; 151 + String get onboardingKeyDataLovedOnes => 'Help important people care about your state in time';
163 152
164 @override 153 @override
165 String get onboardingTellMeWhatItIs => 'Tell me what it is!'; 154 String get onboardingTellMeWhatItIs => 'Tell me what it is!';
@@ -168,19 +157,16 @@ class AppLocalizationsEn extends AppLocalizations { @@ -168,19 +157,16 @@ class AppLocalizationsEn extends AppLocalizations {
168 String get onboardingHrvTitle => 'It is HRV, heart rate variability'; 157 String get onboardingHrvTitle => 'It is HRV, heart rate variability';
169 158
170 @override 159 @override
171 - String get onboardingHrvSubtitle =>  
172 - 'It helps us measure overall stress and health'; 160 + String get onboardingHrvSubtitle => 'It helps us measure overall stress and health';
173 161
174 @override 162 @override
175 - String get onboardingHrvDescription =>  
176 - 'Heart rate variability (HRV) is the tiny variation in time between heartbeats. It reflects autonomic nervous system activity and how the body responds to stress.'; 163 + String get onboardingHrvDescription => 'Heart rate variability (HRV) is the tiny variation in time between heartbeats. It reflects autonomic nervous system activity and how the body responds to stress.';
177 164
178 @override 165 @override
179 String get onboardingTellMeMore => 'Tell me more'; 166 String get onboardingTellMeMore => 'Tell me more';
180 167
181 @override 168 @override
182 - String get onboardingResearchTitle =>  
183 - 'Many studies show that HRV changes are closely related to how our body and mind feel'; 169 + String get onboardingResearchTitle => 'Many studies show that HRV changes are closely related to how our body and mind feel';
184 170
185 @override 171 @override
186 String get onboardingResearchFatigue => 'Physical fatigue'; 172 String get onboardingResearchFatigue => 'Physical fatigue';
@@ -198,30 +184,25 @@ class AppLocalizationsEn extends AppLocalizations { @@ -198,30 +184,25 @@ class AppLocalizationsEn extends AppLocalizations {
198 String get onboardingHealthPermissionTitle => 'Allow health data access'; 184 String get onboardingHealthPermissionTitle => 'Allow health data access';
199 185
200 @override 186 @override
201 - String get onboardingHealthPermissionBody =>  
202 - 'DoubleFeel needs connected wearable health data to send reminders, count stress moments, and provide suggestions.'; 187 + String get onboardingHealthPermissionBody => 'DoubleFeel needs connected wearable health data to send reminders, count stress moments, and provide suggestions.';
203 188
204 @override 189 @override
205 - String get onboardingHealthPermissionPrivacy =>  
206 - 'Your health data is stored locally. We do not upload any related data.'; 190 + String get onboardingHealthPermissionPrivacy => 'Your health data is stored locally. We do not upload any related data.';
207 191
208 @override 192 @override
209 String get onboardingNotificationTitle => 'Turn on notifications'; 193 String get onboardingNotificationTitle => 'Turn on notifications';
210 194
211 @override 195 @override
212 - String get onboardingNotificationSubtitle =>  
213 - 'Learn about every body change in time'; 196 + String get onboardingNotificationSubtitle => 'Learn about every body change in time';
214 197
215 @override 198 @override
216 - String get onboardingNotificationBody =>  
217 - 'After Apple Watch data updates, we can remind you in time and help you act to improve your stress state.'; 199 + String get onboardingNotificationBody => 'After Apple Watch data updates, we can remind you in time and help you act to improve your stress state.';
218 200
219 @override 201 @override
220 String get onboardingMemberTitle => 'Get an annual membership offer'; 202 String get onboardingMemberTitle => 'Get an annual membership offer';
221 203
222 @override 204 @override
223 - String get onboardingMemberBody =>  
224 - 'Start your pressure alert and health companion journey, so love and care are always present.'; 205 + String get onboardingMemberBody => 'Start your pressure alert and health companion journey, so love and care are always present.';
225 206
226 @override 207 @override
227 String get onboardingMemberOriginalPrice => 'Original ¥72.00/year'; 208 String get onboardingMemberOriginalPrice => 'Original ¥72.00/year';
@@ -236,16 +217,13 @@ class AppLocalizationsEn extends AppLocalizations { @@ -236,16 +217,13 @@ class AppLocalizationsEn extends AppLocalizations {
236 String get onboardingMemberAllOptions => 'View all purchase options'; 217 String get onboardingMemberAllOptions => 'View all purchase options';
237 218
238 @override 219 @override
239 - String get healthCompanionIsNowAvailable =>  
240 - 'Health Companion is now available'; 220 + String get healthCompanionIsNowAvailable => 'Health Companion is now available';
241 221
242 @override 222 @override
243 - String get youCanNowViewEachOtherSHrvStressLevelsAndSleepPatternsAndReachOutToCheckInWhenTheOtherPersonSeemsTired =>  
244 - 'You can now view each other\'s HRV, stress levels, and sleep patterns, and reach out to check in when the other person seems tired.'; 223 + String get youCanNowViewEachOtherSHrvStressLevelsAndSleepPatternsAndReachOutToCheckInWhenTheOtherPersonSeemsTired => 'You can now view each other\'s HRV, stress levels, and sleep patterns, and reach out to check in when the other person seems tired.';
245 224
246 @override 225 @override
247 - String get bindPartnerTitle =>  
248 - 'Add a Close Contact\nOne more person to care about your health'; 226 + String get bindPartnerTitle => 'Add a Close Contact\nOne more person to care about your health';
249 227
250 @override 228 @override
251 String get bindPartnerMyId => 'My ID'; 229 String get bindPartnerMyId => 'My ID';
@@ -284,8 +262,7 @@ class AppLocalizationsEn extends AppLocalizations { @@ -284,8 +262,7 @@ class AppLocalizationsEn extends AppLocalizations {
284 String get onboardingResearchGoodSleep => 'Good Sleep'; 262 String get onboardingResearchGoodSleep => 'Good Sleep';
285 263
286 @override 264 @override
287 - String get loginSlogan =>  
288 - 'Start your pressure alert and health companion journey\nso love and care are always present'; 265 + String get loginSlogan => 'Start your pressure alert and health companion journey\nso love and care are always present';
289 266
290 @override 267 @override
291 String get loginWithPhone => 'Sign in with Phone'; 268 String get loginWithPhone => 'Sign in with Phone';
@@ -335,15 +312,13 @@ class AppLocalizationsEn extends AppLocalizations { @@ -335,15 +312,13 @@ class AppLocalizationsEn extends AppLocalizations {
335 String get phoneLoginCodeHint => 'Enter verification code'; 312 String get phoneLoginCodeHint => 'Enter verification code';
336 313
337 @override 314 @override
338 - String get phoneLoginAutoRegisterHint =>  
339 - 'Unregistered numbers will be registered automatically'; 315 + String get phoneLoginAutoRegisterHint => 'Unregistered numbers will be registered automatically';
340 316
341 @override 317 @override
342 String get phoneLoginLoggingIn => 'Signing in...'; 318 String get phoneLoginLoggingIn => 'Signing in...';
343 319
344 @override 320 @override
345 - String get loginAgreeToTermsToast =>  
346 - 'Please read and agree to the Terms of Service and Privacy Policy first'; 321 + String get loginAgreeToTermsToast => 'Please read and agree to the Terms of Service and Privacy Policy first';
347 322
348 @override 323 @override
349 String get phoneLoginInvalidPhone => 'Invalid phone number'; 324 String get phoneLoginInvalidPhone => 'Invalid phone number';
@@ -355,12 +330,10 @@ class AppLocalizationsEn extends AppLocalizations { @@ -355,12 +330,10 @@ class AppLocalizationsEn extends AppLocalizations {
355 String get phoneLoginInvalidCode => 'Invalid verification code'; 330 String get phoneLoginInvalidCode => 'Invalid verification code';
356 331
357 @override 332 @override
358 - String get todayHealthDataAuthTitle =>  
359 - 'Unable to access heart rate health data'; 333 + String get todayHealthDataAuthTitle => 'Unable to access heart rate health data';
360 334
361 @override 335 @override
362 - String get todayHealthDataAuthDescription =>  
363 - 'DoubleFeel needs permission to access your health data to provide stress reminders, real-time stress statistics, and health suggestions. Otherwise, some app features may not work properly. Your health data is stored locally only and will not be uploaded to any server.'; 336 + String get todayHealthDataAuthDescription => 'DoubleFeel needs permission to access your health data to provide stress reminders, real-time stress statistics, and health suggestions. Otherwise, some app features may not work properly. Your health data is stored locally only and will not be uploaded to any server.';
364 337
365 @override 338 @override
366 String get todayHealthDataAuthAction => 'Authorize health data access'; 339 String get todayHealthDataAuthAction => 'Authorize health data access';
@@ -381,24 +354,19 @@ class AppLocalizationsEn extends AppLocalizations { @@ -381,24 +354,19 @@ class AppLocalizationsEn extends AppLocalizations {
381 String get todayFaqLinkNoData => 'What if the app or watch face has no data?'; 354 String get todayFaqLinkNoData => 'What if the app or watch face has no data?';
382 355
383 @override 356 @override
384 - String get todayFaqLinkHrvRealtimeUpdate =>  
385 - 'How can HRV data update in real time?'; 357 + String get todayFaqLinkHrvRealtimeUpdate => 'How can HRV data update in real time?';
386 358
387 @override 359 @override
388 - String get todayFaqLinkWatchNoStatusNotification =>  
389 - 'Why can\'t my watch receive status notifications?'; 360 + String get todayFaqLinkWatchNoStatusNotification => 'Why can\'t my watch receive status notifications?';
390 361
391 @override 362 @override
392 - String get todayFaqLinkWatchNoStatusAndInteractionNotification =>  
393 - 'Why can\'t my watch receive status and interaction notifications?'; 363 + String get todayFaqLinkWatchNoStatusAndInteractionNotification => 'Why can\'t my watch receive status and interaction notifications?';
394 364
395 @override 365 @override
396 - String get todayFaqLinkWatchFaceDataDelay =>  
397 - 'Why is watch face data delayed or not updating?'; 366 + String get todayFaqLinkWatchFaceDataDelay => 'Why is watch face data delayed or not updating?';
398 367
399 @override 368 @override
400 - String get todayFaqLinkWatchFaceBlackScreen =>  
401 - 'Why does the watch face turn black?'; 369 + String get todayFaqLinkWatchFaceBlackScreen => 'Why does the watch face turn black?';
402 370
403 @override 371 @override
404 String get todayStressStatusTitle => 'Overall stress status'; 372 String get todayStressStatusTitle => 'Overall stress status';
@@ -425,176 +393,136 @@ class AppLocalizationsEn extends AppLocalizations { @@ -425,176 +393,136 @@ class AppLocalizationsEn extends AppLocalizations {
425 String get todayStressStatusInsufficientData => 'Insufficient data'; 393 String get todayStressStatusInsufficientData => 'Insufficient data';
426 394
427 @override 395 @override
428 - String get todayStressStatusOverloadDescription =>  
429 - 'Your current HRV is much lower than your long-term average, which may indicate fatigue, high stress, or insufficient recovery. Rest is recommended.'; 396 + String get todayStressStatusOverloadDescription => 'Your current HRV is much lower than your long-term average, which may indicate fatigue, high stress, or insufficient recovery. Rest is recommended.';
430 397
431 @override 398 @override
432 - String get todayStressStatusCautionDescription =>  
433 - 'Your current HRV is below the normal range, and your body may be accumulating stress. Pay attention to rest and recovery.'; 399 + String get todayStressStatusCautionDescription => 'Your current HRV is below the normal range, and your body may be accumulating stress. Pay attention to rest and recovery.';
434 400
435 @override 401 @override
436 - String get todayStressStatusNormalDescription =>  
437 - 'Your current body state is within your normal fluctuation range.'; 402 + String get todayStressStatusNormalDescription => 'Your current body state is within your normal fluctuation range.';
438 403
439 @override 404 @override
440 - String get todayStressStatusExcellentDescription =>  
441 - 'Your current HRV is higher than your recent average, indicating better recovery and overall state.'; 405 + String get todayStressStatusExcellentDescription => 'Your current HRV is higher than your recent average, indicating better recovery and overall state.';
442 406
443 @override 407 @override
444 - String get todayStressStatusInsufficientDataDescription =>  
445 - 'There is not enough available data to accurately assess your stress state yet.'; 408 + String get todayStressStatusInsufficientDataDescription => 'There is not enough available data to accurately assess your stress state yet.';
446 409
447 @override 410 @override
448 - String get todayHrvMeasurementIntro =>  
449 - 'Apple Watch measures HRV every 2-5 hours by default. If you want to measure it manually right now, follow these steps:'; 411 + String get todayHrvMeasurementIntro => 'Apple Watch measures HRV every 2-5 hours by default. If you want to measure it manually right now, follow these steps:';
450 412
451 @override 413 @override
452 - String get todayHrvMeasurementStep1 =>  
453 - '1. Wear your Apple Watch snugly, sit down, and stay calm'; 414 + String get todayHrvMeasurementStep1 => '1. Wear your Apple Watch snugly, sit down, and stay calm';
454 415
455 @override 416 @override
456 - String get todayHrvMeasurementStep2 =>  
457 - '2. Open Mindfulness on Apple Watch and start Breathe'; 417 + String get todayHrvMeasurementStep2 => '2. Open Mindfulness on Apple Watch and start Breathe';
458 418
459 @override 419 @override
460 - String get todayHrvMeasurementStep3 =>  
461 - '3. Keep breathing steadily and wait 1-3 minutes'; 420 + String get todayHrvMeasurementStep3 => '3. Keep breathing steadily and wait 1-3 minutes';
462 421
463 @override 422 @override
464 - String get todayHrvMeasurementStep4 =>  
465 - '4. After breathing is complete, lock and unlock your iPhone once'; 423 + String get todayHrvMeasurementStep4 => '4. After breathing is complete, lock and unlock your iPhone once';
466 424
467 @override 425 @override
468 - String get todayHrvMeasurementStep5 =>  
469 - '5. Wait about one minute. StressWatch will receive and display your data'; 426 + String get todayHrvMeasurementStep5 => '5. Wait about one minute. StressWatch will receive and display your data';
470 427
471 @override 428 @override
472 - String get todayHrvMeasurementHint =>  
473 - 'Tip: Data comes from Apple Watch. After measurement, there may be delays or data may not sync immediately. If this happens, measure again and wait for the data to be read.'; 429 + String get todayHrvMeasurementHint => 'Tip: Data comes from Apple Watch. After measurement, there may be delays or data may not sync immediately. If this happens, measure again and wait for the data to be read.';
474 430
475 @override 431 @override
476 - String get todayHrvMeasurementWarning =>  
477 - 'Note: Health permissions must be enabled, and Low Power Mode must be turned off.'; 432 + String get todayHrvMeasurementWarning => 'Note: Health permissions must be enabled, and Low Power Mode must be turned off.';
478 433
479 @override 434 @override
480 String get todayStressStatusWhatTitle => 'What is overall stress status?'; 435 String get todayStressStatusWhatTitle => 'What is overall stress status?';
481 436
482 @override 437 @override
483 - String get todayStressStatusWhatDescription1 =>  
484 - 'DoubleFeel combines your HRV (heart rate variability), resting heart rate, and body-state changes from the past 30 days to assess your overall stress level.'; 438 + String get todayStressStatusWhatDescription1 => 'DoubleFeel combines your HRV (heart rate variability), resting heart rate, and body-state changes from the past 30 days to assess your overall stress level.';
485 439
486 @override 440 @override
487 - String get todayStressStatusWhatDescription2 =>  
488 - 'Because HRV fluctuates with emotions, exercise, sleep, and fatigue, a single reading has limited value. We recommend focusing on your overall stress status across the day, which is more stable and useful. It helps you understand your body state and helps close contacts notice changes in time.'; 441 + String get todayStressStatusWhatDescription2 => 'Because HRV fluctuates with emotions, exercise, sleep, and fatigue, a single reading has limited value. We recommend focusing on your overall stress status across the day, which is more stable and useful. It helps you understand your body state and helps close contacts notice changes in time.';
489 442
490 @override 443 @override
491 - String get todayStressStatusWhyHrvTitle =>  
492 - 'Why use HRV (heart rate variability)?'; 444 + String get todayStressStatusWhyHrvTitle => 'Why use HRV (heart rate variability)?';
493 445
494 @override 446 @override
495 - String get todayStressStatusWhyHrvDescription =>  
496 - 'HRV is an important metric for measuring body stress and recovery capacity.'; 447 + String get todayStressStatusWhyHrvDescription => 'HRV is an important metric for measuring body stress and recovery capacity.';
497 448
498 @override 449 @override
499 String get todayStressStatusUsually => 'In general:'; 450 String get todayStressStatusUsually => 'In general:';
500 451
501 @override 452 @override
502 - String get todayStressStatusHrvHigher =>  
503 - '· Higher HRV usually means better recovery'; 453 + String get todayStressStatusHrvHigher => '· Higher HRV usually means better recovery';
504 454
505 @override 455 @override
506 - String get todayStressStatusHrvLower =>  
507 - '· Lower HRV may indicate fatigue, stress, or insufficient sleep'; 456 + String get todayStressStatusHrvLower => '· Lower HRV may indicate fatigue, stress, or insufficient sleep';
508 457
509 @override 458 @override
510 - String get todayStressStatusHrvChangesFast =>  
511 - '· HRV changes quickly, making it useful for short-term body-state changes.'; 459 + String get todayStressStatusHrvChangesFast => '· HRV changes quickly, making it useful for short-term body-state changes.';
512 460
513 @override 461 @override
514 - String get todayStressStatusAppWatchDifferenceTitle =>  
515 - 'How are stress statuses on the phone app and Apple Watch different?'; 462 + String get todayStressStatusAppWatchDifferenceTitle => 'How are stress statuses on the phone app and Apple Watch different?';
516 463
517 @override 464 @override
518 - String get todayStressStatusAppWatchDifferenceApp =>  
519 - 'The phone app home page shows the day\'s overall stress status, combining HRV, resting heart rate, and overall trends.'; 465 + String get todayStressStatusAppWatchDifferenceApp => 'The phone app home page shows the day\'s overall stress status, combining HRV, resting heart rate, and overall trends.';
520 466
521 @override 467 @override
522 - String get todayStressStatusAppWatchDifferenceWatch =>  
523 - 'Apple Watch shows the most recent real-time stress status, which is better for quickly checking your current body changes.'; 468 + String get todayStressStatusAppWatchDifferenceWatch => 'Apple Watch shows the most recent real-time stress status, which is better for quickly checking your current body changes.';
524 469
525 @override 470 @override
526 - String get todayStressStatusWaitingDataTitle =>  
527 - 'Why does Waiting for data appear?'; 471 + String get todayStressStatusWaitingDataTitle => 'Why does Waiting for data appear?';
528 472
529 @override 473 @override
530 - String get todayStressStatusWaitingDataDescription1 =>  
531 - 'Waiting for data means the current amount of collected data is not enough to generate a reliable stress assessment.'; 474 + String get todayStressStatusWaitingDataDescription1 => 'Waiting for data means the current amount of collected data is not enough to generate a reliable stress assessment.';
532 475
533 @override 476 @override
534 - String get todayStressStatusWaitingDataDescription2 =>  
535 - 'Please keep wearing your Apple Watch and wait for the system to collect data automatically.'; 477 + String get todayStressStatusWaitingDataDescription2 => 'Please keep wearing your Apple Watch and wait for the system to collect data automatically.';
536 478
537 @override 479 @override
538 - String get todayStressStatusWaitingDataReasonsIntro =>  
539 - 'Possible reasons include:'; 480 + String get todayStressStatusWaitingDataReasonsIntro => 'Possible reasons include:';
540 481
541 @override 482 @override
542 String get todayStressStatusWaitingDataReason1 => '1. Not enough HRV samples'; 483 String get todayStressStatusWaitingDataReason1 => '1. Not enough HRV samples';
543 484
544 @override 485 @override
545 - String get todayStressStatusWaitingDataReason2 =>  
546 - '2. Missing resting heart rate data'; 486 + String get todayStressStatusWaitingDataReason2 => '2. Missing resting heart rate data';
547 487
548 @override 488 @override
549 - String get todayStressStatusWaitingDataReason3 =>  
550 - '3. Apple Watch has not been worn long enough'; 489 + String get todayStressStatusWaitingDataReason3 => '3. Apple Watch has not been worn long enough';
551 490
552 @override 491 @override
553 - String get todayStressStatusWaitingDataReason4 =>  
554 - '4. Apple Health permissions are not enabled'; 492 + String get todayStressStatusWaitingDataReason4 => '4. Apple Health permissions are not enabled';
555 493
556 @override 494 @override
557 - String get todayHrvPrincipleHowMeasureTitle =>  
558 - 'How does DoubleFeel measure stress status?'; 495 + String get todayHrvPrincipleHowMeasureTitle => 'How does DoubleFeel measure stress status?';
559 496
560 @override 497 @override
561 - String get todayHrvPrincipleHowMeasureDescription1 =>  
562 - 'When you wear Apple Watch normally, the system automatically collects your heart rate data and syncs it to Apple Health.'; 498 + String get todayHrvPrincipleHowMeasureDescription1 => 'When you wear Apple Watch normally, the system automatically collects your heart rate data and syncs it to Apple Health.';
563 499
564 @override 500 @override
565 - String get todayHrvPrincipleHowMeasureDescription2 =>  
566 - 'DoubleFeel calculates HRV (heart rate variability) indicators based on this data to assess your body stress and recovery state.'; 501 + String get todayHrvPrincipleHowMeasureDescription2 => 'DoubleFeel calculates HRV (heart rate variability) indicators based on this data to assess your body stress and recovery state.';
567 502
568 @override 503 @override
569 - String get todayHrvPrincipleHowMeasureDescription3 =>  
570 - 'HRV is sensitive to stress, fatigue, sleep, emotions, and recovery, so it helps us notice body-state changes earlier.'; 504 + String get todayHrvPrincipleHowMeasureDescription3 => 'HRV is sensitive to stress, fatigue, sleep, emotions, and recovery, so it helps us notice body-state changes earlier.';
571 505
572 @override 506 @override
573 - String get todayHrvPrincipleHowMeasureDescription4 =>  
574 - 'To make results more accurate, DoubleFeel compares your current HRV state with your own 30-day average instead of comparing it directly with other people.'; 507 + String get todayHrvPrincipleHowMeasureDescription4 => 'To make results more accurate, DoubleFeel compares your current HRV state with your own 30-day average instead of comparing it directly with other people.';
575 508
576 @override 509 @override
577 String get todayRealtimeStressWhatTitle => 'What is real-time stress?'; 510 String get todayRealtimeStressWhatTitle => 'What is real-time stress?';
578 511
579 @override 512 @override
580 - String get todayRealtimeStressWhatDescription1 =>  
581 - 'Real-time stress is a body stress indicator dynamically generated by DoubleFeel based on your current HRV, heart rate state, and changes in your personal history.'; 513 + String get todayRealtimeStressWhatDescription1 => 'Real-time stress is a body stress indicator dynamically generated by DoubleFeel based on your current HRV, heart rate state, and changes in your personal history.';
582 514
583 @override 515 @override
584 - String get todayRealtimeStressWhatDescription2 =>  
585 - 'A higher stress value means your body state is deviating more from your usual baseline and may reflect fatigue, insufficient recovery, or high stress.'; 516 + String get todayRealtimeStressWhatDescription2 => 'A higher stress value means your body state is deviating more from your usual baseline and may reflect fatigue, insufficient recovery, or high stress.';
586 517
587 @override 518 @override
588 - String get todayRealtimeStressWhatDescription3 =>  
589 - 'It helps you notice body changes faster and adjust rest, exercise, and daily rhythm in time.'; 519 + String get todayRealtimeStressWhatDescription3 => 'It helps you notice body changes faster and adjust rest, exercise, and daily rhythm in time.';
590 520
591 @override 521 @override
592 - String get todayRealtimeStressDivisionTitle =>  
593 - 'How is real-time stress divided?'; 522 + String get todayRealtimeStressDivisionTitle => 'How is real-time stress divided?';
594 523
595 @override 524 @override
596 - String get todayRealtimeStressDivisionIntro =>  
597 - 'Real-time stress is shown as a percentage:'; 525 + String get todayRealtimeStressDivisionIntro => 'Real-time stress is shown as a percentage:';
598 526
599 @override 527 @override
600 String get todayRealtimeStressExcellentRange => 'Excellent: 1%-20%'; 528 String get todayRealtimeStressExcellentRange => 'Excellent: 1%-20%';
@@ -609,103 +537,79 @@ class AppLocalizationsEn extends AppLocalizations { @@ -609,103 +537,79 @@ class AppLocalizationsEn extends AppLocalizations {
609 String get todayRealtimeStressOverloadRange => 'Stress overload: 81%-100%'; 537 String get todayRealtimeStressOverloadRange => 'Stress overload: 81%-100%';
610 538
611 @override 539 @override
612 - String get todayRealtimeStressExcellentDescription =>  
613 - 'Your recovery state is good and you are generally relaxed.'; 540 + String get todayRealtimeStressExcellentDescription => 'Your recovery state is good and you are generally relaxed.';
614 541
615 @override 542 @override
616 - String get todayRealtimeStressNormalDescription =>  
617 - 'Your body is within the normal fluctuation range.'; 543 + String get todayRealtimeStressNormalDescription => 'Your body is within the normal fluctuation range.';
618 544
619 @override 545 @override
620 - String get todayRealtimeStressCautionDescription =>  
621 - 'Your body may be accumulating stress and needs proper rest and recovery.'; 546 + String get todayRealtimeStressCautionDescription => 'Your body may be accumulating stress and needs proper rest and recovery.';
622 547
623 @override 548 @override
624 - String get todayRealtimeStressOverloadDescription =>  
625 - 'Your body stress is clearly high. Reduce load and pay attention to sleep and recovery.'; 549 + String get todayRealtimeStressOverloadDescription => 'Your body stress is clearly high. Reduce load and pay attention to sleep and recovery.';
626 550
627 @override 551 @override
628 - String get todayRealtimeStressDivisionBaseline =>  
629 - 'These ranges are adjusted dynamically based on your personal baseline and should not be directly compared between users.'; 552 + String get todayRealtimeStressDivisionBaseline => 'These ranges are adjusted dynamically based on your personal baseline and should not be directly compared between users.';
630 553
631 @override 554 @override
632 - String get todayRealtimeStressDivisionAwake =>  
633 - 'Real-time stress mainly reflects body stress changes while awake.'; 555 + String get todayRealtimeStressDivisionAwake => 'Real-time stress mainly reflects body stress changes while awake.';
634 556
635 @override 557 @override
636 - String get todayRealtimeStressLowBetterTitle =>  
637 - 'Is lower real-time stress always better?'; 558 + String get todayRealtimeStressLowBetterTitle => 'Is lower real-time stress always better?';
638 559
639 @override 560 @override
640 String get todayRealtimeStressLowBetterNo => 'Not necessarily.'; 561 String get todayRealtimeStressLowBetterNo => 'Not necessarily.';
641 562
642 @override 563 @override
643 - String get todayRealtimeStressLowBetterType =>  
644 - 'Body stress can be normal or abnormal.'; 564 + String get todayRealtimeStressLowBetterType => 'Body stress can be normal or abnormal.';
645 565
646 @override 566 @override
647 - String get todayRealtimeStressLowBetterExample =>  
648 - 'For example, real-time stress rising briefly during or after exercise is a normal recovery response. It can also rise temporarily during focused work or emotional excitement, which are normal body adjustments.'; 567 + String get todayRealtimeStressLowBetterExample => 'For example, real-time stress rising briefly during or after exercise is a normal recovery response. It can also rise temporarily during focused work or emotional excitement, which are normal body adjustments.';
649 568
650 @override 569 @override
651 - String get todayRealtimeStressLowBetterHighStress =>  
652 - 'But if stress remains high while resting, sitting for a long time, or after poor sleep, it may indicate physical fatigue, mental stress, insufficient sleep recovery, incomplete exercise recovery, too much caffeine, alcohol, stimulants, or possible discomfort.'; 570 + String get todayRealtimeStressLowBetterHighStress => 'But if stress remains high while resting, sitting for a long time, or after poor sleep, it may indicate physical fatigue, mental stress, insufficient sleep recovery, incomplete exercise recovery, too much caffeine, alcohol, stimulants, or possible discomfort.';
653 571
654 @override 572 @override
655 - String get todayRealtimeStressLowBetterTrend =>  
656 - 'DoubleFeel focuses more on your long-term trend than on a single fluctuation.'; 573 + String get todayRealtimeStressLowBetterTrend => 'DoubleFeel focuses more on your long-term trend than on a single fluctuation.';
657 574
658 @override 575 @override
659 - String get todayRealtimeStressScenarioTitle =>  
660 - 'When should HRV and real-time stress be used?'; 576 + String get todayRealtimeStressScenarioTitle => 'When should HRV and real-time stress be used?';
661 577
662 @override 578 @override
663 - String get todayRealtimeStressScenarioHrvDefault =>  
664 - 'With Apple Watch default settings, HRV updates every 2-5 hours.'; 579 + String get todayRealtimeStressScenarioHrvDefault => 'With Apple Watch default settings, HRV updates every 2-5 hours.';
665 580
666 @override 581 @override
667 - String get todayRealtimeStressScenarioRegionLimit =>  
668 - 'In some regions, Apple Watch breathing features may be limited, which can affect HRV update frequency. Turning on breathing features may also consume more battery.'; 582 + String get todayRealtimeStressScenarioRegionLimit => 'In some regions, Apple Watch breathing features may be limited, which can affect HRV update frequency. Turning on breathing features may also consume more battery.';
669 583
670 @override 584 @override
671 - String get todayRealtimeStressScenarioIntro =>  
672 - 'To address the long interval between HRV updates, DoubleFeel designed real-time stress:'; 585 + String get todayRealtimeStressScenarioIntro => 'To address the long interval between HRV updates, DoubleFeel designed real-time stress:';
673 586
674 @override 587 @override
675 - String get todayRealtimeStressScenarioUpdateEvery6Min =>  
676 - '· Real-time stress updates every 6 minutes'; 588 + String get todayRealtimeStressScenarioUpdateEvery6Min => '· Real-time stress updates every 6 minutes';
677 589
678 @override 590 @override
679 - String get todayRealtimeStressScenarioTimely =>  
680 - '· It can reflect body-state changes more promptly'; 591 + String get todayRealtimeStressScenarioTimely => '· It can reflect body-state changes more promptly';
681 592
682 @override 593 @override
683 - String get todayRealtimeStressScenarioConsistentTrend =>  
684 - '· In most cases, the real-time stress trend is consistent with the HRV trend'; 594 + String get todayRealtimeStressScenarioConsistentTrend => '· In most cases, the real-time stress trend is consistent with the HRV trend';
685 595
686 @override 596 @override
687 - String get todayRealtimeStressScenarioSummary =>  
688 - 'This lets users see long-term HRV trends while also using real-time stress as a short-term body-state reference.'; 597 + String get todayRealtimeStressScenarioSummary => 'This lets users see long-term HRV trends while also using real-time stress as a short-term body-state reference.';
689 598
690 @override 599 @override
691 - String get todayFaqNoDataTitle =>  
692 - 'What if the app or watch face has no data?'; 600 + String get todayFaqNoDataTitle => 'What if the app or watch face has no data?';
693 601
694 @override 602 @override
695 - String get todayFaqNoDataDescription1 =>  
696 - '1. Confirm that Apple Watch is on watchOS 10.0 or above and iPhone is on iOS 14 or above. You can check system versions in About.'; 603 + String get todayFaqNoDataDescription1 => '1. Confirm that Apple Watch is on watchOS 10.0 or above and iPhone is on iOS 14 or above. You can check system versions in About.';
697 604
698 @override 605 @override
699 - String get todayFaqNoDataDescription2 =>  
700 - '2. Confirm all permissions are enabled: iPhone Health > Sharing > Apps > DoubleFeel > Turn On All Permissions.'; 606 + String get todayFaqNoDataDescription2 => '2. Confirm all permissions are enabled: iPhone Health > Sharing > Apps > DoubleFeel > Turn On All Permissions.';
701 607
702 @override 608 @override
703 - String get todayFaqNoDataDescription3 =>  
704 - '3. Confirm the device is not in Low Power Mode, low battery, or worn too loosely, as these can affect data collection.'; 609 + String get todayFaqNoDataDescription3 => '3. Confirm the device is not in Low Power Mode, low battery, or worn too loosely, as these can affect data collection.';
705 610
706 @override 611 @override
707 - String get todayFaqContactPrefix =>  
708 - 'If everything above is correct, you can '; 612 + String get todayFaqContactPrefix => 'If everything above is correct, you can ';
709 613
710 @override 614 @override
711 String get todayFaqContactAction => 'contact us'; 615 String get todayFaqContactAction => 'contact us';
@@ -714,90 +618,70 @@ class AppLocalizationsEn extends AppLocalizations { @@ -714,90 +618,70 @@ class AppLocalizationsEn extends AppLocalizations {
714 String get todayFaqContactSuffix => '.'; 618 String get todayFaqContactSuffix => '.';
715 619
716 @override 620 @override
717 - String get todayFaqWatchNoNotificationTitle =>  
718 - 'Watch cannot receive status notifications?'; 621 + String get todayFaqWatchNoNotificationTitle => 'Watch cannot receive status notifications?';
719 622
720 @override 623 @override
721 - String get todayFaqWatchNoNotificationDescription1 =>  
722 - 'Apple Watch and iPhone notifications have priority rules: when your iPhone is unlocked and the screen is on, notifications only appear on the phone and will not appear on the watch.'; 624 + String get todayFaqWatchNoNotificationDescription1 => 'Apple Watch and iPhone notifications have priority rules: when your iPhone is unlocked and the screen is on, notifications only appear on the phone and will not appear on the watch.';
723 625
724 @override 626 @override
725 - String get todayFaqWatchNoNotificationDescription2 =>  
726 - 'If stress data displays and updates normally but your watch does not receive notifications, try the following:'; 627 + String get todayFaqWatchNoNotificationDescription2 => 'If stress data displays and updates normally but your watch does not receive notifications, try the following:';
727 628
728 @override 629 @override
729 - String get todayFaqWatchNoNotificationCheckPhoneNotification =>  
730 - '1. Check whether iPhone notifications are enabled (Settings > DoubleFeel > Notifications).'; 630 + String get todayFaqWatchNoNotificationCheckPhoneNotification => '1. Check whether iPhone notifications are enabled (Settings > DoubleFeel > Notifications).';
731 631
732 @override 632 @override
733 - String get todayFaqWatchNoNotificationCheckPhoneBackgroundRefresh =>  
734 - '2. Check whether iPhone Background App Refresh is enabled (Settings > DoubleFeel > Background App Refresh).'; 633 + String get todayFaqWatchNoNotificationCheckPhoneBackgroundRefresh => '2. Check whether iPhone Background App Refresh is enabled (Settings > DoubleFeel > Background App Refresh).';
735 634
736 @override 635 @override
737 - String get todayFaqWatchNoNotificationCheckWatchBackgroundRefresh =>  
738 - '3. Check whether Apple Watch Background App Refresh is enabled (Settings > General > Background App Refresh, and make sure DoubleFeel is enabled).'; 636 + String get todayFaqWatchNoNotificationCheckWatchBackgroundRefresh => '3. Check whether Apple Watch Background App Refresh is enabled (Settings > General > Background App Refresh, and make sure DoubleFeel is enabled).';
739 637
740 @override 638 @override
741 - String get todayFaqWatchNoNotificationCheckModes =>  
742 - '4. Make sure Low Power, Focus, Do Not Disturb, Theater, Sleep, and similar modes are off.'; 639 + String get todayFaqWatchNoNotificationCheckModes => '4. Make sure Low Power, Focus, Do Not Disturb, Theater, Sleep, and similar modes are off.';
743 640
744 @override 641 @override
745 - String get todayFaqWatchNoNotificationReinstall =>  
746 - '5. Reinstall DoubleFeel and restart Apple Watch and iPhone.'; 642 + String get todayFaqWatchNoNotificationReinstall => '5. Reinstall DoubleFeel and restart Apple Watch and iPhone.';
747 643
748 @override 644 @override
749 - String get todayFaqWatchFaceDelayTitle =>  
750 - 'Watch face data not updating or delayed?'; 645 + String get todayFaqWatchFaceDelayTitle => 'Watch face data not updating or delayed?';
751 646
752 @override 647 @override
753 - String get todayFaqWatchFaceDelayDescription1 =>  
754 - 'Due to Apple system limits, all watch faces, third-party or official, may have delays from a few minutes to half an hour. Developers cannot control the refresh frequency.'; 648 + String get todayFaqWatchFaceDelayDescription1 => 'Due to Apple system limits, all watch faces, third-party or official, may have delays from a few minutes to half an hour. Developers cannot control the refresh frequency.';
755 649
756 @override 650 @override
757 - String get todayFaqWatchFaceDelayIfOverOneHour =>  
758 - 'If the phone data refreshes but the watch face still has not updated after more than 1 hour:'; 651 + String get todayFaqWatchFaceDelayIfOverOneHour => 'If the phone data refreshes but the watch face still has not updated after more than 1 hour:';
759 652
760 @override 653 @override
761 - String get todayFaqWatchFaceDelayOpenWatchApp =>  
762 - 'Manually open DoubleFeel on Apple Watch and wait about 1 minute.'; 654 + String get todayFaqWatchFaceDelayOpenWatchApp => 'Manually open DoubleFeel on Apple Watch and wait about 1 minute.';
763 655
764 @override 656 @override
765 String get todayFaqWatchFaceDelayIfStill => 'If it still does not update:'; 657 String get todayFaqWatchFaceDelayIfStill => 'If it still does not update:';
766 658
767 @override 659 @override
768 - String get todayFaqWatchFaceDelayRestartApp =>  
769 - 'Close the DoubleFeel background process and restart it.'; 660 + String get todayFaqWatchFaceDelayRestartApp => 'Close the DoubleFeel background process and restart it.';
770 661
771 @override 662 @override
772 - String get todayFaqWatchFaceDelayCheckIntro =>  
773 - 'If it still does not work, check:'; 663 + String get todayFaqWatchFaceDelayCheckIntro => 'If it still does not work, check:';
774 664
775 @override 665 @override
776 - String get todayFaqWatchFaceDelayCheckData =>  
777 - '· Whether both phone and watch apps can show HRV data normally.'; 666 + String get todayFaqWatchFaceDelayCheckData => '· Whether both phone and watch apps can show HRV data normally.';
778 667
779 @override 668 @override
780 - String get todayFaqWatchFaceDelayCheckPhoneHealth =>  
781 - '· Make sure all permissions are enabled on iPhone: iOS Settings > Privacy & Security > Health > DoubleFeel.'; 669 + String get todayFaqWatchFaceDelayCheckPhoneHealth => '· Make sure all permissions are enabled on iPhone: iOS Settings > Privacy & Security > Health > DoubleFeel.';
782 670
783 @override 671 @override
784 - String get todayFaqWatchFaceDelayCheckWatchHealth =>  
785 - '· Make sure all permissions are enabled on Apple Watch: Settings > Health > Data Sources & Access > DoubleFeel.'; 672 + String get todayFaqWatchFaceDelayCheckWatchHealth => '· Make sure all permissions are enabled on Apple Watch: Settings > Health > Data Sources & Access > DoubleFeel.';
786 673
787 @override 674 @override
788 - String get todayFaqWatchFaceDelayCheckBackgroundRefresh =>  
789 - '· Confirm DoubleFeel is enabled in Apple Watch > Settings > General > Background App Refresh.'; 675 + String get todayFaqWatchFaceDelayCheckBackgroundRefresh => '· Confirm DoubleFeel is enabled in Apple Watch > Settings > General > Background App Refresh.';
790 676
791 @override 677 @override
792 - String get todayFaqWatchFaceDelayRestartWatch =>  
793 - '· If it still does not refresh automatically, restart Apple Watch. Long runtimes or high background usage may cause watch face updates to pause.'; 678 + String get todayFaqWatchFaceDelayRestartWatch => '· If it still does not refresh automatically, restart Apple Watch. Long runtimes or high background usage may cause watch face updates to pause.';
794 679
795 @override 680 @override
796 String get todayFaqWatchFaceBlackScreenTitle => 'Watch face turns black?'; 681 String get todayFaqWatchFaceBlackScreenTitle => 'Watch face turns black?';
797 682
798 @override 683 @override
799 - String get todayFaqWatchFaceBlackScreenDescription =>  
800 - 'If the custom interactive watch face turns black after being added and only shows time and date, long-press the watch face, tap Edit, swipe left to Complications, choose DoubleFeel, and add each component again as needed.'; 684 + String get todayFaqWatchFaceBlackScreenDescription => 'If the custom interactive watch face turns black after being added and only shows time and date, long-press the watch face, tap Edit, swipe left to Complications, choose DoubleFeel, and add each component again as needed.';
801 685
802 @override 686 @override
803 String get today => 'Today'; 687 String get today => 'Today';
@@ -815,19 +699,16 @@ class AppLocalizationsEn extends AppLocalizations { @@ -815,19 +699,16 @@ class AppLocalizationsEn extends AppLocalizations {
815 String get allPlans => 'All Plans'; 699 String get allPlans => 'All Plans';
816 700
817 @override 701 @override
818 - String get clickToAddTheHrvThemedWatchFace =>  
819 - 'Click to add the HRV-themed watch face'; 702 + String get clickToAddTheHrvThemedWatchFace => 'Click to add the HRV-themed watch face';
820 703
821 @override 704 @override
822 - String get stayOnTopOfYourHealthFluctuations =>  
823 - 'Stay on top of your health fluctuations'; 705 + String get stayOnTopOfYourHealthFluctuations => 'Stay on top of your health fluctuations';
824 706
825 @override 707 @override
826 String get addACloseContact => 'Add a close contact'; 708 String get addACloseContact => 'Add a close contact';
827 709
828 @override 710 @override
829 - String get oneMorePersonLookingOutForYourHealth =>  
830 - 'One more person looking out for your health'; 711 + String get oneMorePersonLookingOutForYourHealth => 'One more person looking out for your health';
831 712
832 @override 713 @override
833 String get addAFriend => 'Add a friend'; 714 String get addAFriend => 'Add a friend';
@@ -884,8 +765,7 @@ class AppLocalizationsEn extends AppLocalizations { @@ -884,8 +765,7 @@ class AppLocalizationsEn extends AppLocalizations {
884 String get questionsAndFeedback => 'Questions and Feedback'; 765 String get questionsAndFeedback => 'Questions and Feedback';
885 766
886 @override 767 @override
887 - String get ifYouWouldLikeUsToReplyPleaseProvideYourEmailAddress =>  
888 - 'If you would like us to reply, please provide your email address'; 768 + String get ifYouWouldLikeUsToReplyPleaseProvideYourEmailAddress => 'If you would like us to reply, please provide your email address';
889 769
890 @override 770 @override
891 String get uploadProof => 'Upload Proof'; 771 String get uploadProof => 'Upload Proof';
@@ -894,8 +774,7 @@ class AppLocalizationsEn extends AppLocalizations { @@ -894,8 +774,7 @@ class AppLocalizationsEn extends AppLocalizations {
894 String get frequentlyAskedQuestions => 'Frequently Asked Questions'; 774 String get frequentlyAskedQuestions => 'Frequently Asked Questions';
895 775
896 @override 776 @override
897 - String get areYouSureYouWantToDeleteYourAccount =>  
898 - 'Are you sure you want to delete your account?'; 777 + String get areYouSureYouWantToDeleteYourAccount => 'Are you sure you want to delete your account?';
899 778
900 @override 779 @override
901 String get accountSettings => 'Account Settings'; 780 String get accountSettings => 'Account Settings';