Ship native iOS app, Wiki/TTS backend, and skeleton loading UX.

Replace the WebView shell with SwiftUI screens, add account-scoped Wiki and TTS APIs with adaptive review and photo scan support, and keep web/iOS pages usable while data loads asynchronously.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
john
2026-06-08 15:13:59 +08:00
parent db5465c646
commit 05e173b293
115 changed files with 12709 additions and 1212 deletions
+194 -44
View File
@@ -10,24 +10,72 @@
A10000010000000000000001 /* WordLoopApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = A10000020000000000000001 /* WordLoopApp.swift */; };
A10000010000000000000002 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A10000020000000000000002 /* ContentView.swift */; };
A10000010000000000000003 /* ServerEnvironment.swift in Sources */ = {isa = PBXBuildFile; fileRef = A10000020000000000000003 /* ServerEnvironment.swift */; };
A10000010000000000000004 /* ServerGatewayView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A10000020000000000000004 /* ServerGatewayView.swift */; };
A10000010000000000000005 /* WordLoopWebView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A10000020000000000000005 /* WordLoopWebView.swift */; };
A10000010000000000000006 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A10000020000000000000006 /* Assets.xcassets */; };
A10000010000000000000008 /* www in Resources */ = {isa = PBXBuildFile; fileRef = A10000020000000000000008 /* www */; };
A10000010000000000000009 /* BundleWebSchemeHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = A10000020000000000000009 /* BundleWebSchemeHandler.swift */; };
B20000010000000000000001 /* AppModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = B20000020000000000000001 /* AppModels.swift */; };
B20000010000000000000002 /* KeychainHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = B20000020000000000000002 /* KeychainHelper.swift */; };
B20000010000000000000003 /* AuthManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = B20000020000000000000003 /* AuthManager.swift */; };
B20000010000000000000004 /* APIClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = B20000020000000000000004 /* APIClient.swift */; };
B20000010000000000000005 /* TTSService.swift in Sources */ = {isa = PBXBuildFile; fileRef = B20000020000000000000005 /* TTSService.swift */; };
B20000010000000000000006 /* Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = B20000020000000000000006 /* Theme.swift */; };
B20000010000000000000007 /* LoginView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B20000020000000000000007 /* LoginView.swift */; };
B20000010000000000000008 /* RegisterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B20000020000000000000008 /* RegisterView.swift */; };
B20000010000000000000009 /* MainTabView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B20000020000000000000009 /* MainTabView.swift */; };
B2000001000000000000000A /* DashboardView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2000002000000000000000A /* DashboardView.swift */; };
B2000001000000000000000B /* QuizCardView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2000002000000000000000B /* QuizCardView.swift */; };
B2000001000000000000000C /* DailyQuizView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2000002000000000000000C /* DailyQuizView.swift */; };
B2000001000000000000000D /* SpellQuizView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2000002000000000000000D /* SpellQuizView.swift */; };
B2000001000000000000000E /* ErrorBankView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2000002000000000000000E /* ErrorBankView.swift */; };
B2000001000000000000000F /* MemoryCurveChartView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2000002000000000000000F /* MemoryCurveChartView.swift */; };
B20000010000000000000010 /* WordLibraryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B20000020000000000000010 /* WordLibraryView.swift */; };
B20000010000000000000011 /* MemoryCoachView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B20000020000000000000011 /* MemoryCoachView.swift */; };
B20000010000000000000012 /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B20000020000000000000012 /* SettingsView.swift */; };
B20000010000000000000013 /* AccumulationSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B20000020000000000000013 /* AccumulationSettingsView.swift */; };
B20000010000000000000014 /* BookSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B20000020000000000000014 /* BookSettingsView.swift */; };
B20000010000000000000015 /* AccountSettingsViews.swift in Sources */ = {isa = PBXBuildFile; fileRef = B20000020000000000000015 /* AccountSettingsViews.swift */; };
B20000010000000000000016 /* TranslateSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = B20000020000000000000016 /* TranslateSheet.swift */; };
B20000010000000000000017 /* PhotoImportView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B20000020000000000000017 /* PhotoImportView.swift */; };
B20000010000000000000018 /* WordGraphCanvasView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B20000020000000000000018 /* WordGraphCanvasView.swift */; };
B20000010000000000000019 /* FloatingActionsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B20000020000000000000019 /* FloatingActionsView.swift */; };
B2000001000000000000001A /* AppNavigator.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2000002000000000000001A /* AppNavigator.swift */; };
B2000001000000000000001B /* DraggableFab.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2000002000000000000001B /* DraggableFab.swift */; };
B2000001000000000000001C /* TranslateInlineFab.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2000002000000000000001C /* TranslateInlineFab.swift */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
A10000020000000000000001 /* WordLoopApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WordLoopApp.swift; sourceTree = "<group>"; };
A10000020000000000000002 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
A10000020000000000000003 /* ServerEnvironment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerEnvironment.swift; sourceTree = "<group>"; };
A10000020000000000000004 /* ServerGatewayView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerGatewayView.swift; sourceTree = "<group>"; };
A10000020000000000000005 /* WordLoopWebView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WordLoopWebView.swift; sourceTree = "<group>"; };
A10000020000000000000006 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
A10000020000000000000007 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
A10000020000000000000008 /* www */ = {isa = PBXFileReference; lastKnownFileType = folder; path = www; sourceTree = "<group>"; };
A10000020000000000000009 /* BundleWebSchemeHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BundleWebSchemeHandler.swift; sourceTree = "<group>"; };
A10000030000000000000001 /* WordLoop.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = WordLoop.app; sourceTree = BUILT_PRODUCTS_DIR; };
B20000020000000000000001 /* AppModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppModels.swift; sourceTree = "<group>"; };
B20000020000000000000002 /* KeychainHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeychainHelper.swift; sourceTree = "<group>"; };
B20000020000000000000003 /* AuthManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthManager.swift; sourceTree = "<group>"; };
B20000020000000000000004 /* APIClient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = APIClient.swift; sourceTree = "<group>"; };
B20000020000000000000005 /* TTSService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TTSService.swift; sourceTree = "<group>"; };
B20000020000000000000006 /* Theme.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Theme.swift; sourceTree = "<group>"; };
B20000020000000000000007 /* LoginView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginView.swift; sourceTree = "<group>"; };
B20000020000000000000008 /* RegisterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RegisterView.swift; sourceTree = "<group>"; };
B20000020000000000000009 /* MainTabView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainTabView.swift; sourceTree = "<group>"; };
B2000002000000000000000A /* DashboardView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DashboardView.swift; sourceTree = "<group>"; };
B2000002000000000000000B /* QuizCardView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuizCardView.swift; sourceTree = "<group>"; };
B2000002000000000000000C /* DailyQuizView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DailyQuizView.swift; sourceTree = "<group>"; };
B2000002000000000000000D /* SpellQuizView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpellQuizView.swift; sourceTree = "<group>"; };
B2000002000000000000000E /* ErrorBankView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorBankView.swift; sourceTree = "<group>"; };
B2000002000000000000000F /* MemoryCurveChartView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MemoryCurveChartView.swift; sourceTree = "<group>"; };
B20000020000000000000010 /* WordLibraryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WordLibraryView.swift; sourceTree = "<group>"; };
B20000020000000000000011 /* MemoryCoachView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MemoryCoachView.swift; sourceTree = "<group>"; };
B20000020000000000000012 /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = "<group>"; };
B20000020000000000000013 /* AccumulationSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccumulationSettingsView.swift; sourceTree = "<group>"; };
B20000020000000000000014 /* BookSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookSettingsView.swift; sourceTree = "<group>"; };
B20000020000000000000015 /* AccountSettingsViews.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountSettingsViews.swift; sourceTree = "<group>"; };
B20000020000000000000016 /* TranslateSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TranslateSheet.swift; sourceTree = "<group>"; };
B20000020000000000000017 /* PhotoImportView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoImportView.swift; sourceTree = "<group>"; };
B20000020000000000000018 /* WordGraphCanvasView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WordGraphCanvasView.swift; sourceTree = "<group>"; };
B20000020000000000000019 /* FloatingActionsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FloatingActionsView.swift; sourceTree = "<group>"; };
B2000002000000000000001A /* AppNavigator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppNavigator.swift; sourceTree = "<group>"; };
B2000002000000000000001B /* DraggableFab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DraggableFab.swift; sourceTree = "<group>"; };
B2000002000000000000001C /* TranslateInlineFab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TranslateInlineFab.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -55,10 +103,10 @@
A10000020000000000000001 /* WordLoopApp.swift */,
A10000020000000000000002 /* ContentView.swift */,
A10000050000000000000004 /* Models */,
B20000050000000000000001 /* Theme */,
A10000050000000000000005 /* Views */,
A10000050000000000000006 /* Services */,
A10000020000000000000006 /* Assets.xcassets */,
A10000020000000000000008 /* www */,
A10000020000000000000007 /* Info.plist */,
);
path = WordLoop;
@@ -76,6 +124,7 @@
isa = PBXGroup;
children = (
A10000020000000000000003 /* ServerEnvironment.swift */,
B20000020000000000000001 /* AppModels.swift */,
);
path = Models;
sourceTree = "<group>";
@@ -83,8 +132,15 @@
A10000050000000000000005 /* Views */ = {
isa = PBXGroup;
children = (
A10000020000000000000004 /* ServerGatewayView.swift */,
A10000020000000000000005 /* WordLoopWebView.swift */,
B20000050000000000000002 /* Auth */,
B20000050000000000000003 /* Main */,
B20000050000000000000004 /* Quiz */,
B20000050000000000000005 /* Words */,
B20000050000000000000006 /* Coach */,
B20000050000000000000007 /* Settings */,
B20000050000000000000008 /* Translate */,
B20000050000000000000009 /* Import */,
B2000005000000000000000B /* Components */,
);
path = Views;
sourceTree = "<group>";
@@ -92,11 +148,107 @@
A10000050000000000000006 /* Services */ = {
isa = PBXGroup;
children = (
A10000020000000000000009 /* BundleWebSchemeHandler.swift */,
B20000020000000000000002 /* KeychainHelper.swift */,
B20000020000000000000003 /* AuthManager.swift */,
B2000002000000000000001A /* AppNavigator.swift */,
B20000020000000000000004 /* APIClient.swift */,
B20000020000000000000005 /* TTSService.swift */,
);
path = Services;
sourceTree = "<group>";
};
B20000050000000000000001 /* Theme */ = {
isa = PBXGroup;
children = (
B20000020000000000000006 /* Theme.swift */,
);
path = Theme;
sourceTree = "<group>";
};
B20000050000000000000002 /* Auth */ = {
isa = PBXGroup;
children = (
B20000020000000000000007 /* LoginView.swift */,
B20000020000000000000008 /* RegisterView.swift */,
);
path = Auth;
sourceTree = "<group>";
};
B20000050000000000000003 /* Main */ = {
isa = PBXGroup;
children = (
B20000020000000000000009 /* MainTabView.swift */,
B2000002000000000000000A /* DashboardView.swift */,
B20000020000000000000019 /* FloatingActionsView.swift */,
);
path = Main;
sourceTree = "<group>";
};
B20000050000000000000004 /* Quiz */ = {
isa = PBXGroup;
children = (
B2000002000000000000000B /* QuizCardView.swift */,
B2000002000000000000000C /* DailyQuizView.swift */,
B2000002000000000000000D /* SpellQuizView.swift */,
B2000002000000000000000E /* ErrorBankView.swift */,
);
path = Quiz;
sourceTree = "<group>";
};
B20000050000000000000005 /* Words */ = {
isa = PBXGroup;
children = (
B2000002000000000000000F /* MemoryCurveChartView.swift */,
B20000020000000000000010 /* WordLibraryView.swift */,
B20000020000000000000018 /* WordGraphCanvasView.swift */,
);
path = Words;
sourceTree = "<group>";
};
B20000050000000000000006 /* Coach */ = {
isa = PBXGroup;
children = (
B20000020000000000000011 /* MemoryCoachView.swift */,
);
path = Coach;
sourceTree = "<group>";
};
B20000050000000000000007 /* Settings */ = {
isa = PBXGroup;
children = (
B20000020000000000000012 /* SettingsView.swift */,
B20000020000000000000013 /* AccumulationSettingsView.swift */,
B20000020000000000000014 /* BookSettingsView.swift */,
B20000020000000000000015 /* AccountSettingsViews.swift */,
);
path = Settings;
sourceTree = "<group>";
};
B20000050000000000000008 /* Translate */ = {
isa = PBXGroup;
children = (
B20000020000000000000016 /* TranslateSheet.swift */,
B2000002000000000000001C /* TranslateInlineFab.swift */,
);
path = Translate;
sourceTree = "<group>";
};
B20000050000000000000009 /* Import */ = {
isa = PBXGroup;
children = (
B20000020000000000000017 /* PhotoImportView.swift */,
);
path = Import;
sourceTree = "<group>";
};
B2000005000000000000000B /* Components */ = {
isa = PBXGroup;
children = (
B2000002000000000000001B /* DraggableFab.swift */,
);
path = Components;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@@ -104,7 +256,6 @@
isa = PBXNativeTarget;
buildConfigurationList = A10000090000000000000003 /* Build configuration list for PBXNativeTarget "WordLoop" */;
buildPhases = (
A100000C0000000000000001 /* Build Web Assets */,
A10000070000000000000001 /* Sources */,
A10000040000000000000001 /* Frameworks */,
A10000080000000000000001 /* Resources */,
@@ -158,37 +309,11 @@
buildActionMask = 2147483647;
files = (
A10000010000000000000006 /* Assets.xcassets in Resources */,
A10000010000000000000008 /* www in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
A100000C0000000000000001 /* Build Web Assets */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"$(SRCROOT)/../scripts/build-web-assets.sh",
"$(SRCROOT)/../../frontend/package.json",
);
name = "Build Web Assets";
outputFileListPaths = (
);
outputPaths = (
"$(SRCROOT)/WordLoop/www/index.html",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/bash;
shellScript = "set -euo pipefail\nexport PATH=\"/usr/local/bin:/opt/homebrew/bin:${PATH}\"\nbash \"${SRCROOT}/../scripts/build-web-assets.sh\"\n";
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
A10000070000000000000001 /* Sources */ = {
isa = PBXSourcesBuildPhase;
@@ -197,9 +322,34 @@
A10000010000000000000001 /* WordLoopApp.swift in Sources */,
A10000010000000000000002 /* ContentView.swift in Sources */,
A10000010000000000000003 /* ServerEnvironment.swift in Sources */,
A10000010000000000000004 /* ServerGatewayView.swift in Sources */,
A10000010000000000000005 /* WordLoopWebView.swift in Sources */,
A10000010000000000000009 /* BundleWebSchemeHandler.swift in Sources */,
B20000010000000000000001 /* AppModels.swift in Sources */,
B20000010000000000000002 /* KeychainHelper.swift in Sources */,
B20000010000000000000003 /* AuthManager.swift in Sources */,
B20000010000000000000004 /* APIClient.swift in Sources */,
B20000010000000000000005 /* TTSService.swift in Sources */,
B20000010000000000000006 /* Theme.swift in Sources */,
B20000010000000000000007 /* LoginView.swift in Sources */,
B20000010000000000000008 /* RegisterView.swift in Sources */,
B20000010000000000000009 /* MainTabView.swift in Sources */,
B2000001000000000000000A /* DashboardView.swift in Sources */,
B2000001000000000000000B /* QuizCardView.swift in Sources */,
B2000001000000000000000C /* DailyQuizView.swift in Sources */,
B2000001000000000000000D /* SpellQuizView.swift in Sources */,
B2000001000000000000000E /* ErrorBankView.swift in Sources */,
B2000001000000000000000F /* MemoryCurveChartView.swift in Sources */,
B20000010000000000000010 /* WordLibraryView.swift in Sources */,
B20000010000000000000011 /* MemoryCoachView.swift in Sources */,
B20000010000000000000012 /* SettingsView.swift in Sources */,
B20000010000000000000013 /* AccumulationSettingsView.swift in Sources */,
B20000010000000000000014 /* BookSettingsView.swift in Sources */,
B20000010000000000000015 /* AccountSettingsViews.swift in Sources */,
B20000010000000000000016 /* TranslateSheet.swift in Sources */,
B20000010000000000000017 /* PhotoImportView.swift in Sources */,
B20000010000000000000018 /* WordGraphCanvasView.swift in Sources */,
B20000010000000000000019 /* FloatingActionsView.swift in Sources */,
B2000001000000000000001A /* AppNavigator.swift in Sources */,
B2000001000000000000001B /* DraggableFab.swift in Sources */,
B2000001000000000000001C /* TranslateInlineFab.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -346,7 +496,7 @@
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
IPHONEOS_DEPLOYMENT_TARGET = 16.2;
IPHONEOS_DEPLOYMENT_TARGET = 17.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
@@ -375,7 +525,7 @@
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
IPHONEOS_DEPLOYMENT_TARGET = 16.2;
IPHONEOS_DEPLOYMENT_TARGET = 17.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",