From 423ff363f61e0626ad1fee30aba5fef51fcb97ee Mon Sep 17 00:00:00 2001 From: elliwood Date: Thu, 14 Aug 2025 19:49:54 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8A=A8=E6=95=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .DS_Store | Bin 0 -> 6148 bytes .gitignore | 0 wake.xcodeproj/project.pbxproj | 375 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/swiftpm/Package.resolved | 15 + .../IDEFindNavigatorScopes.plist | 5 + .../UserInterfaceState.xcuserstate | Bin 0 -> 50856 bytes .../xcdebugger/Breakpoints_v2.xcbkptlist | 6 + .../xcschemes/xcschememanagement.plist | 14 + wake/.DS_Store | Bin 0 -> 6148 bytes wake/ContentView.swift | 228 +++++++++++ wake/Utils/.DS_Store | Bin 0 -> 6148 bytes wake/Utils/LoginURLSession.swift | 94 +++++ wake/Utils/NetWork.swift | 34 ++ wake/Utils/PasswordLogin.swift | 49 +++ wake/Utils/User.swift | 31 ++ wake/View/.DS_Store | Bin 0 -> 6148 bytes wake/View/Components/.DS_Store | Bin 0 -> 6148 bytes wake/View/Components/Button.swift | 114 ++++++ wake/View/Components/SheetModal.swift | 55 +++ wake/View/Components/TextInput.swift | 50 +++ wake/View/Login/.DS_Store | Bin 0 -> 6148 bytes wake/View/Login/Login.swift | 270 +++++++++++++ wake/View/Owner/.DS_Store | Bin 0 -> 6148 bytes wake/View/Owner/ModalContentView.swift | 111 ++++++ wake/View/Owner/SettingsView.swift | 201 ++++++++++ wake/WakeApp.swift | 29 ++ 27 files changed, 1688 insertions(+) create mode 100644 .DS_Store create mode 100644 .gitignore create mode 100644 wake.xcodeproj/project.pbxproj create mode 100644 wake.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 wake.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved create mode 100644 wake.xcodeproj/project.xcworkspace/xcuserdata/elliwood.xcuserdatad/IDEFindNavigatorScopes.plist create mode 100644 wake.xcodeproj/project.xcworkspace/xcuserdata/elliwood.xcuserdatad/UserInterfaceState.xcuserstate create mode 100644 wake.xcodeproj/xcuserdata/elliwood.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist create mode 100644 wake.xcodeproj/xcuserdata/elliwood.xcuserdatad/xcschemes/xcschememanagement.plist create mode 100644 wake/.DS_Store create mode 100644 wake/ContentView.swift create mode 100644 wake/Utils/.DS_Store create mode 100644 wake/Utils/LoginURLSession.swift create mode 100644 wake/Utils/NetWork.swift create mode 100644 wake/Utils/PasswordLogin.swift create mode 100644 wake/Utils/User.swift create mode 100644 wake/View/.DS_Store create mode 100644 wake/View/Components/.DS_Store create mode 100644 wake/View/Components/Button.swift create mode 100644 wake/View/Components/SheetModal.swift create mode 100644 wake/View/Components/TextInput.swift create mode 100644 wake/View/Login/.DS_Store create mode 100644 wake/View/Login/Login.swift create mode 100644 wake/View/Owner/.DS_Store create mode 100644 wake/View/Owner/ModalContentView.swift create mode 100644 wake/View/Owner/SettingsView.swift create mode 100644 wake/WakeApp.swift diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..127ee7651969dcc8abfb9150d15e632c8a76531f GIT binary patch literal 6148 zcmeHK&2G~`5S~o~aa4hF0IA27df*a4S}N3viwWrq)CdlMQaiR%nDnkG3TD433jSBFyYf?oaT~KoU`9(#RmeXGEQZ%-jw{Ew*mbdM_4bD{+ zOvCA{?1z)r+zg6Lg#wik@lxIi83YK-QW^!m!JoxtP_ndfRPH}$izQie}aOM5gZk5fMjruyO{BFU=CcHIq($FiZ4e_cVW>bu750cB3>|rC>wJr~K|?2@XU28x z%)*{fgq|IFsmn?D23_kEa0=X1V9Rtny#F8n{QQ5D;2NjEA64Kxh%b3( literal 0 HcmV?d00001 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/wake.xcodeproj/project.pbxproj b/wake.xcodeproj/project.pbxproj new file mode 100644 index 0000000..7cf4d17 --- /dev/null +++ b/wake.xcodeproj/project.pbxproj @@ -0,0 +1,375 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 77; + objects = { + +/* Begin PBXBuildFile section */ + AB8773632E4E04400071CB53 /* .gitignore in Resources */ = {isa = PBXBuildFile; fileRef = AB8773622E4E040E0071CB53 /* .gitignore */; }; + ABB4E2182E4B761400660198 /* Alamofire in Frameworks */ = {isa = PBXBuildFile; productRef = ABB4E2172E4B761400660198 /* Alamofire */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + ABB4E21C2E4B763200660198 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + AB8773622E4E040E0071CB53 /* .gitignore */ = {isa = PBXFileReference; lastKnownFileType = text; path = .gitignore; sourceTree = ""; }; + ABB4E2082E4B75D900660198 /* wake.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = wake.app; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFileSystemSynchronizedRootGroup section */ + ABB4E20A2E4B75D900660198 /* wake */ = { + isa = PBXFileSystemSynchronizedRootGroup; + path = wake; + sourceTree = ""; + }; +/* End PBXFileSystemSynchronizedRootGroup section */ + +/* Begin PBXFrameworksBuildPhase section */ + ABB4E2052E4B75D900660198 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ABB4E2182E4B761400660198 /* Alamofire in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + ABB4E1FF2E4B75D900660198 = { + isa = PBXGroup; + children = ( + AB8773622E4E040E0071CB53 /* .gitignore */, + ABB4E20A2E4B75D900660198 /* wake */, + ABB4E2092E4B75D900660198 /* Products */, + ); + sourceTree = ""; + }; + ABB4E2092E4B75D900660198 /* Products */ = { + isa = PBXGroup; + children = ( + ABB4E2082E4B75D900660198 /* wake.app */, + ); + name = Products; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + ABB4E2072E4B75D900660198 /* wake */ = { + isa = PBXNativeTarget; + buildConfigurationList = ABB4E2132E4B75DF00660198 /* Build configuration list for PBXNativeTarget "wake" */; + buildPhases = ( + ABB4E2042E4B75D900660198 /* Sources */, + ABB4E2052E4B75D900660198 /* Frameworks */, + ABB4E2062E4B75D900660198 /* Resources */, + ABB4E21C2E4B763200660198 /* Embed Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + fileSystemSynchronizedGroups = ( + ABB4E20A2E4B75D900660198 /* wake */, + ); + name = wake; + packageProductDependencies = ( + ABB4E2172E4B761400660198 /* Alamofire */, + ); + productName = wake; + productReference = ABB4E2082E4B75D900660198 /* wake.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + ABB4E2002E4B75D900660198 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastSwiftUpdateCheck = 1640; + LastUpgradeCheck = 1640; + TargetAttributes = { + ABB4E2072E4B75D900660198 = { + CreatedOnToolsVersion = 16.4; + }; + }; + }; + buildConfigurationList = ABB4E2032E4B75D900660198 /* Build configuration list for PBXProject "wake" */; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = ABB4E1FF2E4B75D900660198; + minimizedProjectReferenceProxies = 1; + packageReferences = ( + ABB4E2162E4B761400660198 /* XCRemoteSwiftPackageReference "Alamofire" */, + ); + preferredProjectObjectVersion = 77; + productRefGroup = ABB4E2092E4B75D900660198 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + ABB4E2072E4B75D900660198 /* wake */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + ABB4E2062E4B75D900660198 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + AB8773632E4E04400071CB53 /* .gitignore in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + ABB4E2042E4B75D900660198 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + ABB4E2112E4B75DF00660198 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = GB3VPJ54BD; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 18.5; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + ABB4E2122E4B75DF00660198 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = GB3VPJ54BD; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 18.5; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + ABB4E2142E4B75DF00660198 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = GB3VPJ54BD; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchScreen_Generation = YES; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.memowake.wake; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + ABB4E2152E4B75DF00660198 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = GB3VPJ54BD; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchScreen_Generation = YES; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.memowake.wake; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + ABB4E2032E4B75D900660198 /* Build configuration list for PBXProject "wake" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + ABB4E2112E4B75DF00660198 /* Debug */, + ABB4E2122E4B75DF00660198 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + ABB4E2132E4B75DF00660198 /* Build configuration list for PBXNativeTarget "wake" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + ABB4E2142E4B75DF00660198 /* Debug */, + ABB4E2152E4B75DF00660198 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + +/* Begin XCRemoteSwiftPackageReference section */ + ABB4E2162E4B761400660198 /* XCRemoteSwiftPackageReference "Alamofire" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/Alamofire/Alamofire.git"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 5.10.2; + }; + }; +/* End XCRemoteSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + ABB4E2172E4B761400660198 /* Alamofire */ = { + isa = XCSwiftPackageProductDependency; + package = ABB4E2162E4B761400660198 /* XCRemoteSwiftPackageReference "Alamofire" */; + productName = Alamofire; + }; +/* End XCSwiftPackageProductDependency section */ + }; + rootObject = ABB4E2002E4B75D900660198 /* Project object */; +} diff --git a/wake.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/wake.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/wake.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/wake.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/wake.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved new file mode 100644 index 0000000..8c6ea58 --- /dev/null +++ b/wake.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -0,0 +1,15 @@ +{ + "originHash" : "e8f130fe30ac6cdc940ef06ee1e8535e9f46ffee6aeead1722b9525562f6ce08", + "pins" : [ + { + "identity" : "alamofire", + "kind" : "remoteSourceControl", + "location" : "https://github.com/Alamofire/Alamofire.git", + "state" : { + "revision" : "513364f870f6bfc468f9d2ff0a95caccc10044c5", + "version" : "5.10.2" + } + } + ], + "version" : 3 +} diff --git a/wake.xcodeproj/project.xcworkspace/xcuserdata/elliwood.xcuserdatad/IDEFindNavigatorScopes.plist b/wake.xcodeproj/project.xcworkspace/xcuserdata/elliwood.xcuserdatad/IDEFindNavigatorScopes.plist new file mode 100644 index 0000000..5dd5da8 --- /dev/null +++ b/wake.xcodeproj/project.xcworkspace/xcuserdata/elliwood.xcuserdatad/IDEFindNavigatorScopes.plist @@ -0,0 +1,5 @@ + + + + + diff --git a/wake.xcodeproj/project.xcworkspace/xcuserdata/elliwood.xcuserdatad/UserInterfaceState.xcuserstate b/wake.xcodeproj/project.xcworkspace/xcuserdata/elliwood.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000000000000000000000000000000000000..ff3dd1d96b4033ca450cda520ab37b90b11f4195 GIT binary patch literal 50856 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 + + diff --git a/wake.xcodeproj/xcuserdata/elliwood.xcuserdatad/xcschemes/xcschememanagement.plist b/wake.xcodeproj/xcuserdata/elliwood.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..a4c98a3 --- /dev/null +++ b/wake.xcodeproj/xcuserdata/elliwood.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,14 @@ + + + + + SchemeUserState + + wake.xcscheme_^#shared#^_ + + orderHint + 0 + + + + diff --git a/wake/.DS_Store b/wake/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..f26cef212aa4fe75c09ccdf6bcc1a97fcf41496d GIT binary patch literal 6148 zcmeH~L2uJA6vyo?r7jhy2atBOgt%2Aq0`v3ODIL+yui=|s5DEpMWk`nq~uUl%7GJH z_ypYe2uS+|9CqL5;XT`HowW#w10d!n*?;Hxy}15av1>vI?M@?)kQO0?K|ytHLbb-Q zAIpkuXwPj>D&LWXMK%r-5w65qhb3SM{CfoO+pUooBquRRi241Vh2td7a@W0}8=Fq; zMxE7Jlf4N}MG@qKe42F!lUMlkT!>u>sC8Jb)R1hib zIMQxuy_8STFlH2G$4Lmk5W@|3a^eNYVl-A+&9Bwok?8gGHpV_Y`*u{n|NZgRi0Bs) z<5P14++fY|-v^U45$Oqd@s~N|5Efua3S$HPI}70Lwt2^OmkZF@`Hclw%*VvPa8}_T zotpqm^x*$eQ|K4DBe4X(uD^=?GlVSRUV)B%*V*(J#G2O`f}Oi1U&zQwU$c314dOUs7j^!ia}L6__>brwU$a%I-zo8c#j^L z>Kh7`ql2Hza6)~hwzdQ;fhvJb_1MDm|LM=~|J5Y>WC>UT{}lo1^nzX&rlil-mC4~* v%b~o5f`)OWQkepkK8|GrkK!#T(x8uH1Ju`ADg_Ui{UabT*vb<4qXd2cbk4-H literal 0 HcmV?d00001 diff --git a/wake/ContentView.swift b/wake/ContentView.swift new file mode 100644 index 0000000..268de74 --- /dev/null +++ b/wake/ContentView.swift @@ -0,0 +1,228 @@ +import SwiftUI + +// 自定义从左向右的过渡动画 +extension AnyTransition { + static var slideFromLeading: AnyTransition { + .asymmetric( + insertion: .move(edge: .trailing).combined(with: .opacity), + removal: .move(edge: .leading).combined(with: .opacity) + ) + } +} + +// 1. 定义路由 +enum Route: Hashable { + case settings +} + +struct ContentView: View { + @State private var showModal = false + @State private var showSettings = false + @State private var navigationPath = NavigationPath() + @State private var contentOffset: CGFloat = 0 + + var body: some View { + NavigationStack(path: $navigationPath) { + // 添加动画修饰符到 NavigationStack + let _ = Self._printChanges() + let _ = print("Navigation path changed: \(navigationPath)") + + ZStack { + VStack { + VStack(spacing: 20) { + // This spacer ensures content stays below the status bar + Spacer().frame(height: UIApplication.shared.windows.first?.safeAreaInsets.top ?? 0) + // 顶部栏 + HStack { + Spacer() + Button(action: { + withAnimation(.spring(response: 0.5, dampingFraction: 0.8)) { + showModal = true + } + }) { + Image(systemName: "gearshape") + .font(.title2) + .padding() + } + } + Spacer() + } + .frame(maxWidth: .infinity, maxHeight: .infinity) + .background(Color(.systemBackground)) + .offset(x: showModal ? UIScreen.main.bounds.width * 0.35 : 0) + .animation(.spring(response: 0.5, dampingFraction: 0.8), value: showModal) + .edgesIgnoringSafeArea(.all) + } + // 添加半透明遮罩层 + if showModal { + Color.black.opacity(0.4) + .edgesIgnoringSafeArea(.all) + .onTapGesture { + withAnimation(.spring(response: 0.5, dampingFraction: 0.8)) { + showModal = false + } + } + .transition(.opacity) + } + + // Modal with animation - will be pushed off-screen by SettingsView + SlideInModal(isPresented: $showModal, onDismiss: { + withAnimation(.spring(response: 0.5, dampingFraction: 0.8)) { + showModal = false + } + }) { + // Modal content + // Modal content with offset for SettingsView + VStack(spacing: 20) { + // 用户信息区域 + HStack(alignment: .center, spacing: 16) { + // 头像 + Image(systemName: "person.circle.fill") + .resizable() + .aspectRatio(contentMode: .fill) + .frame(width: 60, height: 60) + .foregroundColor(.blue) + .clipShape(Circle()) + + // 姓名和ID + VStack(alignment: .leading, spacing: 4) { + Text("用户名") + .font(.headline) + .foregroundColor(.primary) + + Text("ID: 12345678") + .font(.subheadline) + .foregroundColor(.secondary) + } + + Spacer() + } + .padding(.horizontal, 16) + .padding(.top, 16) + + VStack(alignment: .leading, spacing: 8) { + Text("会员等级") + .font(.headline) + .foregroundColor(.primary) + Text("会员时间") + .font(.subheadline) + .foregroundColor(.secondary) + Text("会员中心") + .font(.subheadline) + .foregroundColor(.secondary) + } + .frame(maxWidth: .infinity, alignment: .leading) + .padding(16) + .background(Color(red: 0.92, green: 0.92, blue: 0.92)) + .cornerRadius(10) + .padding(.horizontal, 16) + + VStack(spacing: 12) { + // memories + Button(action: { + print("memories") + }) { + HStack(spacing: 16) { + Image(systemName: "crown.fill") + .foregroundColor(.orange) + .frame(width: 24, height: 24) + + Text("My Memories") + .font(.headline) + .foregroundColor(.primary) + + Spacer() + } + .padding() + .cornerRadius(10) + .contentShape(Rectangle()) // 使整个区域可点击 + } + .buttonStyle(PlainButtonStyle()) // 移除按钮默认样式 + + // Box + Button(action: { + print("Box") + }) { + HStack(spacing: 16) { + Image(systemName: "clock.fill") + .foregroundColor(.blue) + .frame(width: 24, height: 24) + Text("My Bind Box") + .font(.headline) + .foregroundColor(.primary) + + Spacer() + } + .padding() + .cornerRadius(10) + .contentShape(Rectangle()) // 使整个区域可点击 + } + .buttonStyle(PlainButtonStyle()) // 移除按钮默认样式 + + // setting + Button(action: { + withAnimation(.spring(response: 0.5, dampingFraction: 0.8)) { + showSettings = true + } + }) { + HStack(spacing: 16) { + Image(systemName: "person.circle.fill") + .foregroundColor(.purple) + .frame(width: 24, height: 24) + Text("Setting") + .font(.headline) + .foregroundColor(.primary) + Spacer() + Image(systemName: "chevron.right") + .foregroundColor(.gray) + } + .padding() + .background(Color(.systemBackground)) + .cornerRadius(10) + .contentShape(Rectangle()) // 使整个区域可点击 + } + .buttonStyle(PlainButtonStyle()) // 移除按钮默认样式 + } + .padding(.horizontal, 16) + // 这里可以添加其他设置项 + Spacer() + } + .padding(.vertical, 8) + } + + // Apply offset to the entire modal when SettingsView is shown + .offset(x: showSettings ? UIScreen.main.bounds.width : 0) + .animation(.spring(response: 0.5, dampingFraction: 0.8), value: showSettings) + + ZStack { + // Semi-transparent overlay for settings + if showSettings { + Color.black.opacity(0.4) + .edgesIgnoringSafeArea(.all) + .onTapGesture { + withAnimation(.spring(response: 0.5, dampingFraction: 0.8)) { + showSettings = false + } + } + .transition(.opacity) + } + + // Full screen settings view with slide animation + if showSettings { + SettingsView(isPresented: $showSettings) + .transition(.move(edge: .leading)) + .zIndex(1) // Ensure it's above other content + .onAppear { + // Reset the navigation path when settings appear + navigationPath.removeLast(navigationPath.count) + } + } + } + .animation(.spring(response: 0.5, dampingFraction: 0.8), value: showSettings) + } + } + } +} +#Preview { + ContentView() +} diff --git a/wake/Utils/.DS_Store b/wake/Utils/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5008ddfcf53c02e82d7eee2e57c38e5672ef89f6 GIT binary patch literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0 不能直接 Codable,这里用 AnyCodable 简化 +//enum AnyCodable: Codable {} + +func passwordLogin(username: String, password: String) { + guard let url = URL(string: "http://192.168.31.156:31646/api/v1/iam/login/password-login") else { + print("❌ 无效的URL") + return + } + + // 1. 创建 URLRequest + var request = URLRequest(url: url) + request.httpMethod = "POST" + + // 2. 设置请求头 + request.setValue("application/json", forHTTPHeaderField: "Content-Type") + // 如果接口需要,也可以加 User-Agent 或其他 header + request.setValue("iOS App", forHTTPHeaderField: "User-Agent") + + // 3. 准备参数 + let parameters = [ + "account": username, + "password": password + ] + + // 4. 将参数编码为 JSON + do { + request.httpBody = try JSONSerialization.data(withJSONObject: parameters, options: []) + } catch { + print("❌ 参数序列化失败: \(error)") + return + } + + // 5. 发送请求 + let task = URLSession.shared.dataTask(with: request) { data, response, error in + // 回调在后台线程,更新 UI 需切主线程 + DispatchQueue.main.async { + if let error = error { + print("网络错误: \(error)") + return + } + + // 检查状态码 + if let httpResponse = response as? HTTPURLResponse { + print("状态码: \(httpResponse.statusCode)") + + if httpResponse.statusCode == 404 { + print("⚠️ 接口未找到,请确认:") + print("1. 后端服务是否正在运行?") + print("2. IP 和端口是否正确?") + print("3. 网络是否在同一局域网?") + return + } else if httpResponse.statusCode != 200 { + print("服务器错误: \(httpResponse.statusCode)") + } + } + + // 处理返回数据 + guard let data = data else { + print("❌ 无返回数据") + return + } + + // 打印原始响应(调试用) + if let jsonString = String(data: data, encoding: .utf8) { + print("响应内容: \(jsonString)") + } + + // 尝试解析为 JSON 字典 + do { + if let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] { + print("解析成功: \(json)") + + // 如果你有明确的模型,可以用 JSONDecoder 解码 LoginResponse + // let decoder = JSONDecoder() + // let loginResult = try decoder.decode(LoginResponse.self, from: data) + } + } catch { + print("❌ JSON 解析失败: \(error)") + } + } + } + + // 启动请求 + task.resume() +} diff --git a/wake/Utils/NetWork.swift b/wake/Utils/NetWork.swift new file mode 100644 index 0000000..0cdffc9 --- /dev/null +++ b/wake/Utils/NetWork.swift @@ -0,0 +1,34 @@ +import SwiftUI + +class Network: ObservableObject { + @Published var users: [User] = [] + + func getUsers() { + guard let url = URL(string: "http://192.168.31.156:31646/api/iam/login/password-login") else { fatalError("Missing URL") } + + let urlRequest = URLRequest(url: url) + + let dataTask = URLSession.shared.dataTask(with: urlRequest) { (data, response, error) in + if let error = error { + print("Request error: ", error) + return + } + + guard let response = response as? HTTPURLResponse else { return } + + if response.statusCode == 200 { + guard let data = data else { return } + DispatchQueue.main.async { + do { + let decodedUsers = try JSONDecoder().decode([User].self, from: data) + self.users = decodedUsers + } catch let error { + print("Error decoding: ", error) + } + } + } + } + + dataTask.resume() + } +} diff --git a/wake/Utils/PasswordLogin.swift b/wake/Utils/PasswordLogin.swift new file mode 100644 index 0000000..72e1426 --- /dev/null +++ b/wake/Utils/PasswordLogin.swift @@ -0,0 +1,49 @@ +import Foundation // 必须导入 + +struct LoginResponse: Codable { + let token: String? + let error: String? +} + +func callLoginAPI() { + // 1. 创建 URL + let urlString = "http://192.168.31.156:31646/api/v1/iam/login/password-login" + guard let url = URL(string: urlString) else { + print("Invalid URL") + return + } + + // 2. 准备请求体 + let body = ["username": "testUser", "password": "test123"] + guard let jsonData = try? JSONSerialization.data(withJSONObject: body) else { + print("JSON encoding failed") + return + } + print(jsonData) + // 3. 配置请求 + var request = URLRequest(url: url) + request.httpMethod = "POST" + request.setValue("application/json", forHTTPHeaderField: "Content-Type") + request.httpBody = jsonData + print(request) + // 4. 发送请求 + let task = URLSession.shared.dataTask(with: request) { data, response, error in + if let error = error { + print("Error: \(error.localizedDescription)") + return + } + + guard let data = data else { + print("No data received") + return + } + + do { + let result = try JSONDecoder().decode(LoginResponse.self, from: data) + print("Token: \(result.token ?? "nil")") + } catch { + print("Decoding error: \(error)") + } + } + task.resume() +} diff --git a/wake/Utils/User.swift b/wake/Utils/User.swift new file mode 100644 index 0000000..2587619 --- /dev/null +++ b/wake/Utils/User.swift @@ -0,0 +1,31 @@ +import Foundation + +struct User: Identifiable, Decodable { + var id: Int + var name: String + var username: String + var email: String + var address: Address + var phone: String + var website: String + var company: Company + + struct Address: Decodable { + var street: String + var suite: String + var city: String + var zipcode: String + var geo: Geo + + struct Geo: Decodable { + var lat: String + var lng: String + } + } + + struct Company: Decodable { + var name: String + var catchPhrase: String + var bs: String + } +} diff --git a/wake/View/.DS_Store b/wake/View/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..e3d77d1f1deea5264e1b74653f5d7c2dc7a867a1 GIT binary patch literal 6148 zcmeHK-HOvd6h6}*H{C_-g$un5h!;Y^v|YurH`#8zQv@S=p;DVo=?0TbXwnT>3b}S) zWglSQVBf&!@tm1iO=t>&;1-z!XTHgtbLQte%uEIV*l6kX0NMaxpb|Frv8WKTlWs^& zwLCy%q7M!c%urKEHoSF%Wr!=tV_=nvOjb2aQ+UGr%0e7$ZNhmW2fzny#y!iayD zWHLN^gxptn3zt}_T$`7i1uo8&0xKPYdCxiHVJv%k@@<=6$j4(vl5zFy=BoMl=489C z_s72Rd2xK3rcpW13uh4pJes4O*3yJmn8G>u5Z!h92E7-UKFj*c^c7ZAOj@D2oT|?2 zG7ZH9)$>|VmkBDwhx~V1sy)iduyBAP(Hkjv1DV)Gi{gYSXy-)j8{=T-W~L{k8PE*e zH3M`$n5cxd!d#*_Ip*)a7TJ?*EtD-~Z(x{iPYu4E$FNu*TRK zk8nxqZrxZM-L)p_7gQ4R%O#2sEYx)@Ds&ZhP=%n)qza;~FqeoeDEdc0(4Y&=z&~Z+ ECw>mv#Q*>R literal 0 HcmV?d00001 diff --git a/wake/View/Components/.DS_Store b/wake/View/Components/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..98fe9e1fc9997b1c0d75f69353f98f1eee833cc6 GIT binary patch literal 6148 zcmeHK%}T>S5Z>*NZYhNx6nb0`Zw1>bYVi_dJ$N;u2bJ2GqQNv9+SD9MA!mId-@rHU zEqn)Oe=4o@=cYwwVD_7xo!QNP3A-6W2(^b^oscpign>%T6rlM;&+wWGmclu!9=WMGjQkmmyjm1r4EHL9Zn8dU-S=D@84Y*|al9B$Aum}-O(5UNuFbt*L_ z2G!}{=O)fFm}=DNgqq@mnw6=kP^elR=I1J$P)j4W$N(}h%Rp9l%kus|{JQ?1O~M{B zfDHUA257G3v~1Xtxm)KpC+}JgdIc&)#-$qHQ@~JHF~rKNxB{vK{9GD Void // 点击回调(无参数) + + // MARK: - 主体视图 + var body: some View { + Button(action: { + if !isLoading { // 防止加载时触发 + action() + } + }) { + if isLoading { + // 显示加载动画 + HStack { + ProgressView() // iOS 加载指示器 + .progressViewStyle(CircularProgressViewStyle(tint: .white)) + Text("加载中...") + } + } else { + Text(text) + .fontWeight(.medium) + } + } + .font(font(for: size)) + .padding(padding(for: size)) + .frame(maxWidth: fullWidth ? .infinity : (width(for: size))) + .background(backgroundColor) + .foregroundColor(.white) + .cornerRadius(8) + .overlay( + // 次要按钮:只显示边框 + RoundedRectangle(cornerRadius: 8) + .stroke(borderColor, lineWidth: 2) + .opacity(type == .secondary ? 1 : 0) + ) + .disabled(isLoading) // 加载时禁用点击 + .opacity(isLoading ? 0.8 : 1.0) + } + + // MARK: - 计算属性:背景色 + private var backgroundColor: Color { + switch type { + case .primary: + return .blue + case .secondary: + return .clear + case .danger: + return .red + } + } + + // MARK: - 计算属性:边框色 + private var borderColor: Color { + switch type { + case .secondary: + return .gray + default: + return .clear + } + } + + // MARK: - 辅助函数:字体 + private func font(for size: ButtonSize) -> Font { + switch size { + case .small: + return .caption + case .medium: + return .subheadline + case .large: + return .headline + } + } + + // MARK: - 辅助函数:内边距 + private func padding(for size: ButtonSize) -> EdgeInsets { + let horizontal = CGFloat(16) + let vertical: CGFloat + switch size { + case .small: + vertical = 6 + case .medium: + vertical = 10 + case .large: + vertical = 14 + } + return EdgeInsets(top: vertical, leading: horizontal, bottom: vertical, trailing: horizontal) + } + + // MARK: - 辅助函数:固定宽度(非全宽时) + private func width(for size: ButtonSize) -> CGFloat? { + return nil // 自适应宽度,除非你想要固定值 + } +} diff --git a/wake/View/Components/SheetModal.swift b/wake/View/Components/SheetModal.swift new file mode 100644 index 0000000..a2bcdde --- /dev/null +++ b/wake/View/Components/SheetModal.swift @@ -0,0 +1,55 @@ +import SwiftUI + +struct SlideInModal: View { + @Binding var isPresented: Bool + let onDismiss: () -> Void + let content: () -> Content + + // 动画配置 - 更慢的动画 + private let animation = Animation.spring( + response: 0.8, // 增加响应时间使动画更慢 + dampingFraction: 0.6, // 减少阻尼系数使弹跳更明显 + blendDuration: 0.8 // 增加混合时间使过渡更平滑 + ) + + var body: some View { + ZStack(alignment: .leading) { + // 遮罩背景 + if isPresented { + Color.black + .opacity(0.5) + .edgesIgnoringSafeArea(.all) + .transition(.opacity) + .zIndex(1) + .onTapGesture { + withAnimation(animation) { + isPresented = false + onDismiss() + } + } + + // 弹窗内容 + VStack(spacing: 0) { + // 顶部安全区域占位 + Color.clear + .frame(height: UIApplication.shared.windows.first?.safeAreaInsets.top ?? 0) + + // 内容区域 + content() + .frame(maxWidth: .infinity, maxHeight: .infinity) + .padding(.bottom, UIApplication.shared.windows.first?.safeAreaInsets.bottom ?? 0) + } + .frame(width: UIScreen.main.bounds.width * 0.8) + .frame(maxHeight: .infinity) + .background(Color(.systemBackground)) + .edgesIgnoringSafeArea(.vertical) + .offset(x: isPresented ? 0 : -UIScreen.main.bounds.width) + .zIndex(2) + .transition(.move(edge: .leading)) + .animation(animation, value: isPresented) + } + } + .frame(maxWidth: .infinity, maxHeight: .infinity) + .edgesIgnoringSafeArea(.all) + } +} \ No newline at end of file diff --git a/wake/View/Components/TextInput.swift b/wake/View/Components/TextInput.swift new file mode 100644 index 0000000..7bbe8eb --- /dev/null +++ b/wake/View/Components/TextInput.swift @@ -0,0 +1,50 @@ +import SwiftUI + +// 输入框类型枚举(更优雅的方式) +enum TextFieldType { + case username + case password + case number + case email + case text +} + +struct CustomTextField: View { + // MARK: - 属性 + let placeholder: String + let type: TextFieldType + + // 双向绑定的值(关键!) + @Binding var value: String + + // MARK: - 主体视图 + var body: some View { + Group { // 使用 Group 统一修饰符 + if type == .password { + // 密码框 + SecureField(placeholder, text: $value) + } else { + // 普通文本框 + TextField(placeholder, text: $value) + .textInputAutocapitalization(.never) // 关闭自动大写 + .disableAutocorrection(true) // 关闭自动纠错 + } + } + .padding() + .background(Color(.systemGray6)) + .cornerRadius(8) + .keyboardType(keyboardType(for: type)) // 设置键盘类型 + } + + // MARK: - 根据类型返回键盘类型 + private func keyboardType(for type: TextFieldType) -> UIKeyboardType { + switch type { + case .number: + return .numberPad + case .email: + return .emailAddress + default: + return .default + } + } +} diff --git a/wake/View/Login/.DS_Store b/wake/View/Login/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..dfa523b02f7213c6ee13b48117b9d37a16dd5fa4 GIT binary patch literal 6148 zcmeHKOHKnZ47E#DMJbMz$Kp!eV;Jbyrph=jxf z6=X}vb7DK6H<~0SB3>LebD|j$btr-?N<*Z(X_~n66v#Tp^KLs|J(OYJ80I{?WbK!9 zM}@ZZM6LCIvJR#1*SoStO!sKmIX>&hxv)s)B)FAQ%V+e$D{y zY?1EDFzR3+7zhSF7?ATJp$KNjYN$sCDop`^@{Cr2F1dunB**Mn4Pk+>g#s;{tygoY<2O_L<+47uMM^eo}YhY#4Pg5DbhNxUl9-?*AoznP!qd4vAJU5Dfe? z26)=9`UN)Sck7q!$z7XJ?omXH1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0 Void + @Environment(\.dismiss) private var dismissModal + + var body: some View { + VStack(spacing: 20) { + // 用户信息 + HStack(alignment: .center, spacing: 16) { + Image(systemName: "person.circle.fill") + .resizable() + .aspectRatio(contentMode: .fill) + .frame(width: 60, height: 60) + .foregroundColor(.blue) + .clipShape(Circle()) + + VStack(alignment: .leading, spacing: 4) { + Text("用户名") + .font(.headline) + Text("ID: 12345678") + .font(.subheadline) + .foregroundColor(.secondary) + } + + Spacer() + } + .padding(.horizontal, 16) + .padding(.top, 16) + + // 会员区域 + VStack(alignment: .leading, spacing: 8) { + Text("会员等级").font(.headline) + Text("会员时间").font(.subheadline).foregroundColor(.secondary) + Text("会员中心").font(.subheadline).foregroundColor(.secondary) + } + .frame(maxWidth: .infinity, alignment: .leading) + .padding(16) + .background(Color(red: 0.92, green: 0.92, blue: 0.92)) + .cornerRadius(10) + .padding(.horizontal, 16) + + // 功能按钮 + VStack(spacing: 12) { + ModalButton(icon: "crown.fill", color: .orange, text: "My Memories") + ModalButton(icon: "clock.fill", color: .blue, text: "My Bind Box") + + // 跳转设置页 + Button(action: { + goBack() + DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { + // 模拟从左边滑入的效果 + } + }) { + HStack(spacing: 16) { + Image(systemName: "person.circle.fill") + .foregroundColor(.purple) + .frame(width: 24, height: 24) + Text("Setting") + .font(.headline) + .foregroundColor(.primary) + Spacer() + Image(systemName: "chevron.right") + .foregroundColor(.gray) + } + .padding() + .background(Color(.systemBackground)) + .cornerRadius(10) + } + .buttonStyle(PlainButtonStyle()) + } + .padding(.horizontal, 16) + + Spacer() + } + .padding(.vertical, 8) + } +} + +// MARK: - 按钮组件 +struct ModalButton: View { + let icon: String + let color: Color + let text: String + let action: () -> Void + + init(icon: String, color: Color, text: String, action: @escaping () -> Void = {}) { + self.icon = icon + self.color = color + self.text = text + self.action = action + } + + var body: some View { + Button(action: action) { + HStack(spacing: 16) { + Image(systemName: icon) + .foregroundColor(color) + .frame(width: 24, height: 24) + Text(text) + .font(.headline) + .foregroundColor(.primary) + Spacer() + } + .padding() + .background(Color(.systemBackground)) + .cornerRadius(10) + } + .buttonStyle(PlainButtonStyle()) + } +} diff --git a/wake/View/Owner/SettingsView.swift b/wake/View/Owner/SettingsView.swift new file mode 100644 index 0000000..d49e3ef --- /dev/null +++ b/wake/View/Owner/SettingsView.swift @@ -0,0 +1,201 @@ +import SwiftUI + +struct SettingsView: View { + @Environment(\.dismiss) private var dismiss + @State private var isAppeared = false + @Binding var isPresented: Bool + + // Animation configuration + private let animation = Animation.spring( + response: 0.8, + dampingFraction: 0.6, + blendDuration: 0.8 + ) + + var body: some View { + VStack(spacing: 0) { + // Custom navigation bar + HStack { + Button(action: { + withAnimation(.spring(response: 0.5, dampingFraction: 0.8)) { + isPresented = false + } + }) { + HStack(spacing: 4) { + Image(systemName: "chevron.left") + .font(.system(size: 17, weight: .semibold)) + Text("Back") + } + .foregroundColor(.blue) + .padding() + } + Spacer() + Text("Settings") + .font(.headline) + .padding() + Spacer() + // Invisible view to balance the layout + Color.clear + .frame(width: 44, height: 44) + } + .background(Color(.systemBackground)) + + // Settings content + List(0..<1) { _ in + // This empty section ensures proper spacing + Section { + EmptyView() + } header: { + EmptyView() + } + // Add an invisible section header to remove extra top padding + Section(header: EmptyView()) { + EmptyView() + } + // Account & Security + HStack { + Color.clear + .frame(width: 12, height: 24) + .background(Color(.systemBackground)) + Image(systemName: "person.crop.circle") + .font(.system(size: 24)) + .foregroundColor(.gray) + Text("Account & Security") + Spacer() + Image(systemName: "chevron.right") + .foregroundColor(.gray) + Color.clear + .frame(width: 12, height: 24) + .background(Color(.systemBackground)) + } + .listRowBackground(Color(.systemBackground)) + + // Permission Management + HStack { + Color.clear + .frame(width: 12, height: 24) + .background(Color(.systemBackground)) + Image(systemName: "lock.shield") + .font(.system(size: 24)) + .foregroundColor(.gray) + Text("Permission Management") + Spacer() + Image(systemName: "chevron.right") + .foregroundColor(.gray) + Color.clear + .frame(width: 12, height: 24) + .background(Color(.systemBackground)) + } + .listRowBackground(Color(.systemBackground)) + + // Support & Service + HStack { + Color.clear + .frame(width: 12, height: 24) + .background(Color(.systemBackground)) + Image(systemName: "questionmark.circle") + .font(.system(size: 24)) + .foregroundColor(.gray) + Text("Support & Service") + Spacer() + Image(systemName: "chevron.right") + .foregroundColor(.gray) + Color.clear + .frame(width: 12, height: 24) + .background(Color(.systemBackground)) + } + .listRowBackground(Color(.systemBackground)) + + // About Us + HStack { + Color.clear + .frame(width: 12, height: 24) + .background(Color(.systemBackground)) + Image(systemName: "info.circle") + .font(.system(size: 24)) + .foregroundColor(.gray) + Text("About Us") + Spacer() + Image(systemName: "chevron.right") + .foregroundColor(.gray) + Color.clear + .frame(width: 12, height: 24) + .background(Color(.systemBackground)) + } + .listRowBackground(Color(.systemBackground)) + } + .listStyle(GroupedListStyle()) + .navigationTitle("Setting") + .navigationBarTitleDisplayMode(.inline) + .frame(maxWidth: .infinity, maxHeight: .infinity) + .background(Color(.systemGray6)) + .environment(\.horizontalSizeClass, .regular) + .environment(\.defaultMinListRowHeight, 50) + .listRowInsets(EdgeInsets()) + .onAppear { + // Remove extra separators below the list + UITableView.appearance().tableFooterView = UIView() + // Remove separator inset + UITableView.appearance().separatorInset = .zero + // Remove extra space at the top of the table view + UITableView.appearance().contentInset = .zero + } + .toolbar { + ToolbarItem(placement: .navigationBarLeading) { + Button(action: { + withAnimation(.spring(response: 0.5, dampingFraction: 0.8)) { + isAppeared = false + } + // Delay the dismiss to allow the animation to complete + DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { + isPresented = false + } + }) { + HStack(spacing: 4) { + Image(systemName: "chevron.left") + .font(.system(size: 16, weight: .medium)) + .foregroundColor(.blue) + Text("Back") + .font(.system(size: 17, weight: .regular)) + .foregroundColor(.blue) + } + } + } + } + .animation(animation, value: isAppeared) + } + +} +} + +// MARK: - Preview +#Preview { + NavigationView { + SettingsView(isPresented: .constant(true)) + } +} + +// MARK: - Subviews +struct AccountSecurityView: View { + var body: some View { + Text("Account & Security") + } +} + +struct PermissionManagementView: View { + var body: some View { + Text("Permission Management") + } +} + +struct SupportServiceView: View { + var body: some View { + Text("Support & Service") + } +} + +struct AboutUsView: View { + var body: some View { + Text("About Us") + } +} diff --git a/wake/WakeApp.swift b/wake/WakeApp.swift new file mode 100644 index 0000000..84b8be9 --- /dev/null +++ b/wake/WakeApp.swift @@ -0,0 +1,29 @@ +// +// WakeApp.swift +// Wake +// +// Created by elliwood on 2025/8/11. +// + +import SwiftUI + +@main +struct WakeApp: App { + var body: some Scene { + WindowGroup { + ContentView() +// SettingsView() + // 导航栏按钮 + // TabView{ + // ContentView() + // .tabItem{ + // Label("wake", systemImage: "book") + // } + // SettingView() + // .tabItem{ + // Label("setting", systemImage: "gear") + // } + // } + } + } +}