Admin-Ka macOS 1.0.0 — app native SwiftUI (WKWebView) notarisée, identité Ka
- shell SwiftUI natif macOS enveloppant administration-ka.com (cookie persistant, liens externes → navigateur, panneaux JS natifs pour confirm/bypass) - icône + splash pastille Ka, fenêtre redimensionnable, hardened runtime - signé Developer ID Application + notarisé (notarytool via clé API ASC) + stapled + DMG Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
19 changed files +659 −0
added
.gitignore
+7 −0
@@ -0,0 +1,7 @@ | |||||
| 1 | +.DS_Store | ||||
| 2 | +build/ | ||||
| 3 | +DerivedData/ | ||||
| 4 | +dist/ | ||||
| 5 | +*.xcuserstate | ||||
| 6 | +xcuserdata/ | ||||
| 7 | +screenshots/ | ||||
added
AdminKaMac.xcodeproj/project.pbxproj
+339 −0
@@ -0,0 +1,339 @@ | |||||
| 1 | +// !$*UTF8*$! | ||||
| 2 | +{ | ||||
| 3 | + archiveVersion = 1; | ||||
| 4 | + classes = { | ||||
| 5 | + }; | ||||
| 6 | + objectVersion = 77; | ||||
| 7 | + objects = { | ||||
| 8 | + | ||||
| 9 | +/* Begin PBXBuildFile section */ | ||||
| 10 | + 82BA6DA43D75AB5CDF765360 /* AdminKaMacApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1BE00C7998B3AE9281938C8 /* AdminKaMacApp.swift */; }; | ||||
| 11 | + A2299018D551DE323C453439 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 02C21000306216EFA864AC79 /* Assets.xcassets */; }; | ||||
| 12 | + AA4AB8779667D82483FAF045 /* RootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6A456697E2205919C39C44B /* RootView.swift */; }; | ||||
| 13 | + AE613712E51ECADC4D983C00 /* Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E7EA81E05D09A3B32940539 /* Theme.swift */; }; | ||||
| 14 | + E574FBC46EA6ED96B8196E1C /* WebView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C8E8B6E60526309BC2B9243 /* WebView.swift */; }; | ||||
| 15 | +/* End PBXBuildFile section */ | ||||
| 16 | + | ||||
| 17 | +/* Begin PBXFileReference section */ | ||||
| 18 | + 02C21000306216EFA864AC79 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; }; | ||||
| 19 | + 5D4FBD2391C5AA22EC0D3742 /* AdminKaMac.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AdminKaMac.app; sourceTree = BUILT_PRODUCTS_DIR; }; | ||||
| 20 | + 5E7EA81E05D09A3B32940539 /* Theme.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Theme.swift; sourceTree = "<group>"; }; | ||||
| 21 | + 8C8E8B6E60526309BC2B9243 /* WebView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebView.swift; sourceTree = "<group>"; }; | ||||
| 22 | + B00B669430E6EA7BF4185289 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; }; | ||||
| 23 | + B1BE00C7998B3AE9281938C8 /* AdminKaMacApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdminKaMacApp.swift; sourceTree = "<group>"; }; | ||||
| 24 | + CA0F4A21CCC1477D4A5A60A6 /* AdminKaMac.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = AdminKaMac.entitlements; sourceTree = "<group>"; }; | ||||
| 25 | + E6A456697E2205919C39C44B /* RootView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RootView.swift; sourceTree = "<group>"; }; | ||||
| 26 | +/* End PBXFileReference section */ | ||||
| 27 | + | ||||
| 28 | +/* Begin PBXGroup section */ | ||||
| 29 | + 250ED03615C8C0848BF90A43 /* Products */ = { | ||||
| 30 | + isa = PBXGroup; | ||||
| 31 | + children = ( | ||||
| 32 | + 5D4FBD2391C5AA22EC0D3742 /* AdminKaMac.app */, | ||||
| 33 | + ); | ||||
| 34 | + name = Products; | ||||
| 35 | + sourceTree = "<group>"; | ||||
| 36 | + }; | ||||
| 37 | + 7A72F9E8B22A3A6F48B7CA35 /* Sources */ = { | ||||
| 38 | + isa = PBXGroup; | ||||
| 39 | + children = ( | ||||
| 40 | + CA0F4A21CCC1477D4A5A60A6 /* AdminKaMac.entitlements */, | ||||
| 41 | + B1BE00C7998B3AE9281938C8 /* AdminKaMacApp.swift */, | ||||
| 42 | + B00B669430E6EA7BF4185289 /* Info.plist */, | ||||
| 43 | + E6A456697E2205919C39C44B /* RootView.swift */, | ||||
| 44 | + 5E7EA81E05D09A3B32940539 /* Theme.swift */, | ||||
| 45 | + 8C8E8B6E60526309BC2B9243 /* WebView.swift */, | ||||
| 46 | + ); | ||||
| 47 | + path = Sources; | ||||
| 48 | + sourceTree = "<group>"; | ||||
| 49 | + }; | ||||
| 50 | + B39C7C2CA1E0D8B5F2EAB354 = { | ||||
| 51 | + isa = PBXGroup; | ||||
| 52 | + children = ( | ||||
| 53 | + E5ABD6EDCFF9EC4DE2BF91C6 /* Resources */, | ||||
| 54 | + 7A72F9E8B22A3A6F48B7CA35 /* Sources */, | ||||
| 55 | + 250ED03615C8C0848BF90A43 /* Products */, | ||||
| 56 | + ); | ||||
| 57 | + sourceTree = "<group>"; | ||||
| 58 | + }; | ||||
| 59 | + E5ABD6EDCFF9EC4DE2BF91C6 /* Resources */ = { | ||||
| 60 | + isa = PBXGroup; | ||||
| 61 | + children = ( | ||||
| 62 | + 02C21000306216EFA864AC79 /* Assets.xcassets */, | ||||
| 63 | + ); | ||||
| 64 | + path = Resources; | ||||
| 65 | + sourceTree = "<group>"; | ||||
| 66 | + }; | ||||
| 67 | +/* End PBXGroup section */ | ||||
| 68 | + | ||||
| 69 | +/* Begin PBXNativeTarget section */ | ||||
| 70 | + F9853118CD34A10A9B8E4F90 /* AdminKaMac */ = { | ||||
| 71 | + isa = PBXNativeTarget; | ||||
| 72 | + buildConfigurationList = 37792F69F119471FA311BAB8 /* Build configuration list for PBXNativeTarget "AdminKaMac" */; | ||||
| 73 | + buildPhases = ( | ||||
| 74 | + 7008F5E82F8952C5A7C036B7 /* Sources */, | ||||
| 75 | + C2FB09DFDC9F286E4B1ECB79 /* Resources */, | ||||
| 76 | + ); | ||||
| 77 | + buildRules = ( | ||||
| 78 | + ); | ||||
| 79 | + dependencies = ( | ||||
| 80 | + ); | ||||
| 81 | + name = AdminKaMac; | ||||
| 82 | + packageProductDependencies = ( | ||||
| 83 | + ); | ||||
| 84 | + productName = AdminKaMac; | ||||
| 85 | + productReference = 5D4FBD2391C5AA22EC0D3742 /* AdminKaMac.app */; | ||||
| 86 | + productType = "com.apple.product-type.application"; | ||||
| 87 | + }; | ||||
| 88 | +/* End PBXNativeTarget section */ | ||||
| 89 | + | ||||
| 90 | +/* Begin PBXProject section */ | ||||
| 91 | + FB566ECDA392935EE6C8E20F /* Project object */ = { | ||||
| 92 | + isa = PBXProject; | ||||
| 93 | + attributes = { | ||||
| 94 | + BuildIndependentTargetsInParallel = YES; | ||||
| 95 | + LastUpgradeCheck = 1430; | ||||
| 96 | + TargetAttributes = { | ||||
| 97 | + F9853118CD34A10A9B8E4F90 = { | ||||
| 98 | + DevelopmentTeam = 3YM54G49SN; | ||||
| 99 | + ProvisioningStyle = Manual; | ||||
| 100 | + }; | ||||
| 101 | + }; | ||||
| 102 | + }; | ||||
| 103 | + buildConfigurationList = A6EFFDB2CC27831A956303CB /* Build configuration list for PBXProject "AdminKaMac" */; | ||||
| 104 | + developmentRegion = en; | ||||
| 105 | + hasScannedForEncodings = 0; | ||||
| 106 | + knownRegions = ( | ||||
| 107 | + Base, | ||||
| 108 | + en, | ||||
| 109 | + ); | ||||
| 110 | + mainGroup = B39C7C2CA1E0D8B5F2EAB354; | ||||
| 111 | + minimizedProjectReferenceProxies = 1; | ||||
| 112 | + preferredProjectObjectVersion = 77; | ||||
| 113 | + productRefGroup = 250ED03615C8C0848BF90A43 /* Products */; | ||||
| 114 | + projectDirPath = ""; | ||||
| 115 | + projectRoot = ""; | ||||
| 116 | + targets = ( | ||||
| 117 | + F9853118CD34A10A9B8E4F90 /* AdminKaMac */, | ||||
| 118 | + ); | ||||
| 119 | + }; | ||||
| 120 | +/* End PBXProject section */ | ||||
| 121 | + | ||||
| 122 | +/* Begin PBXResourcesBuildPhase section */ | ||||
| 123 | + C2FB09DFDC9F286E4B1ECB79 /* Resources */ = { | ||||
| 124 | + isa = PBXResourcesBuildPhase; | ||||
| 125 | + buildActionMask = 2147483647; | ||||
| 126 | + files = ( | ||||
| 127 | + A2299018D551DE323C453439 /* Assets.xcassets in Resources */, | ||||
| 128 | + ); | ||||
| 129 | + runOnlyForDeploymentPostprocessing = 0; | ||||
| 130 | + }; | ||||
| 131 | +/* End PBXResourcesBuildPhase section */ | ||||
| 132 | + | ||||
| 133 | +/* Begin PBXSourcesBuildPhase section */ | ||||
| 134 | + 7008F5E82F8952C5A7C036B7 /* Sources */ = { | ||||
| 135 | + isa = PBXSourcesBuildPhase; | ||||
| 136 | + buildActionMask = 2147483647; | ||||
| 137 | + files = ( | ||||
| 138 | + 82BA6DA43D75AB5CDF765360 /* AdminKaMacApp.swift in Sources */, | ||||
| 139 | + AA4AB8779667D82483FAF045 /* RootView.swift in Sources */, | ||||
| 140 | + AE613712E51ECADC4D983C00 /* Theme.swift in Sources */, | ||||
| 141 | + E574FBC46EA6ED96B8196E1C /* WebView.swift in Sources */, | ||||
| 142 | + ); | ||||
| 143 | + runOnlyForDeploymentPostprocessing = 0; | ||||
| 144 | + }; | ||||
| 145 | +/* End PBXSourcesBuildPhase section */ | ||||
| 146 | + | ||||
| 147 | +/* Begin XCBuildConfiguration section */ | ||||
| 148 | + 47C2705EB0F5CFC9CED0406F /* Release */ = { | ||||
| 149 | + isa = XCBuildConfiguration; | ||||
| 150 | + buildSettings = { | ||||
| 151 | + ALWAYS_SEARCH_USER_PATHS = NO; | ||||
| 152 | + CLANG_ANALYZER_NONNULL = YES; | ||||
| 153 | + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; | ||||
| 154 | + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; | ||||
| 155 | + CLANG_CXX_LIBRARY = "libc++"; | ||||
| 156 | + CLANG_ENABLE_MODULES = YES; | ||||
| 157 | + CLANG_ENABLE_OBJC_ARC = YES; | ||||
| 158 | + CLANG_ENABLE_OBJC_WEAK = YES; | ||||
| 159 | + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; | ||||
| 160 | + CLANG_WARN_BOOL_CONVERSION = YES; | ||||
| 161 | + CLANG_WARN_COMMA = YES; | ||||
| 162 | + CLANG_WARN_CONSTANT_CONVERSION = YES; | ||||
| 163 | + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; | ||||
| 164 | + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; | ||||
| 165 | + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; | ||||
| 166 | + CLANG_WARN_EMPTY_BODY = YES; | ||||
| 167 | + CLANG_WARN_ENUM_CONVERSION = YES; | ||||
| 168 | + CLANG_WARN_INFINITE_RECURSION = YES; | ||||
| 169 | + CLANG_WARN_INT_CONVERSION = YES; | ||||
| 170 | + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; | ||||
| 171 | + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; | ||||
| 172 | + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; | ||||
| 173 | + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; | ||||
| 174 | + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; | ||||
| 175 | + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; | ||||
| 176 | + CLANG_WARN_STRICT_PROTOTYPES = YES; | ||||
| 177 | + CLANG_WARN_SUSPICIOUS_MOVE = YES; | ||||
| 178 | + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; | ||||
| 179 | + CLANG_WARN_UNREACHABLE_CODE = YES; | ||||
| 180 | + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; | ||||
| 181 | + COPY_PHASE_STRIP = NO; | ||||
| 182 | + CURRENT_PROJECT_VERSION = 1; | ||||
| 183 | + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; | ||||
| 184 | + DEVELOPMENT_TEAM = 3YM54G49SN; | ||||
| 185 | + ENABLE_NS_ASSERTIONS = NO; | ||||
| 186 | + ENABLE_STRICT_OBJC_MSGSEND = YES; | ||||
| 187 | + GCC_C_LANGUAGE_STANDARD = gnu11; | ||||
| 188 | + GCC_NO_COMMON_BLOCKS = YES; | ||||
| 189 | + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; | ||||
| 190 | + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; | ||||
| 191 | + GCC_WARN_UNDECLARED_SELECTOR = YES; | ||||
| 192 | + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; | ||||
| 193 | + GCC_WARN_UNUSED_FUNCTION = YES; | ||||
| 194 | + GCC_WARN_UNUSED_VARIABLE = YES; | ||||
| 195 | + MACOSX_DEPLOYMENT_TARGET = 13.0; | ||||
| 196 | + MARKETING_VERSION = 1.0.0; | ||||
| 197 | + MTL_ENABLE_DEBUG_INFO = NO; | ||||
| 198 | + MTL_FAST_MATH = YES; | ||||
| 199 | + PRODUCT_NAME = "$(TARGET_NAME)"; | ||||
| 200 | + SDKROOT = macosx; | ||||
| 201 | + SWIFT_COMPILATION_MODE = wholemodule; | ||||
| 202 | + SWIFT_OPTIMIZATION_LEVEL = "-O"; | ||||
| 203 | + SWIFT_VERSION = 5.0; | ||||
| 204 | + }; | ||||
| 205 | + name = Release; | ||||
| 206 | + }; | ||||
| 207 | + 9F641E359B9E74716ED4B9E5 /* Release */ = { | ||||
| 208 | + isa = XCBuildConfiguration; | ||||
| 209 | + buildSettings = { | ||||
| 210 | + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; | ||||
| 211 | + CODE_SIGN_ENTITLEMENTS = Sources/AdminKaMac.entitlements; | ||||
| 212 | + CODE_SIGN_IDENTITY = "Developer ID Application"; | ||||
| 213 | + CODE_SIGN_STYLE = Manual; | ||||
| 214 | + COMBINE_HIDPI_IMAGES = YES; | ||||
| 215 | + ENABLE_HARDENED_RUNTIME = YES; | ||||
| 216 | + INFOPLIST_FILE = Sources/Info.plist; | ||||
| 217 | + LD_RUNPATH_SEARCH_PATHS = ( | ||||
| 218 | + "$(inherited)", | ||||
| 219 | + "@executable_path/../Frameworks", | ||||
| 220 | + ); | ||||
| 221 | + MACOSX_DEPLOYMENT_TARGET = 13.0; | ||||
| 222 | + PRODUCT_BUNDLE_IDENTIFIER = com.groupeka.adminkamac; | ||||
| 223 | + PRODUCT_NAME = "Admin-Ka"; | ||||
| 224 | + SDKROOT = macosx; | ||||
| 225 | + }; | ||||
| 226 | + name = Release; | ||||
| 227 | + }; | ||||
| 228 | + CA399800D52E645C7E657403 /* Debug */ = { | ||||
| 229 | + isa = XCBuildConfiguration; | ||||
| 230 | + buildSettings = { | ||||
| 231 | + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; | ||||
| 232 | + CODE_SIGN_ENTITLEMENTS = Sources/AdminKaMac.entitlements; | ||||
| 233 | + CODE_SIGN_IDENTITY = "Developer ID Application"; | ||||
| 234 | + CODE_SIGN_STYLE = Manual; | ||||
| 235 | + COMBINE_HIDPI_IMAGES = YES; | ||||
| 236 | + ENABLE_HARDENED_RUNTIME = YES; | ||||
| 237 | + INFOPLIST_FILE = Sources/Info.plist; | ||||
| 238 | + LD_RUNPATH_SEARCH_PATHS = ( | ||||
| 239 | + "$(inherited)", | ||||
| 240 | + "@executable_path/../Frameworks", | ||||
| 241 | + ); | ||||
| 242 | + MACOSX_DEPLOYMENT_TARGET = 13.0; | ||||
| 243 | + PRODUCT_BUNDLE_IDENTIFIER = com.groupeka.adminkamac; | ||||
| 244 | + PRODUCT_NAME = "Admin-Ka"; | ||||
| 245 | + SDKROOT = macosx; | ||||
| 246 | + }; | ||||
| 247 | + name = Debug; | ||||
| 248 | + }; | ||||
| 249 | + E5F59090737C7E513CCF4FB1 /* Debug */ = { | ||||
| 250 | + isa = XCBuildConfiguration; | ||||
| 251 | + buildSettings = { | ||||
| 252 | + ALWAYS_SEARCH_USER_PATHS = NO; | ||||
| 253 | + CLANG_ANALYZER_NONNULL = YES; | ||||
| 254 | + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; | ||||
| 255 | + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; | ||||
| 256 | + CLANG_CXX_LIBRARY = "libc++"; | ||||
| 257 | + CLANG_ENABLE_MODULES = YES; | ||||
| 258 | + CLANG_ENABLE_OBJC_ARC = YES; | ||||
| 259 | + CLANG_ENABLE_OBJC_WEAK = YES; | ||||
| 260 | + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; | ||||
| 261 | + CLANG_WARN_BOOL_CONVERSION = YES; | ||||
| 262 | + CLANG_WARN_COMMA = YES; | ||||
| 263 | + CLANG_WARN_CONSTANT_CONVERSION = YES; | ||||
| 264 | + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; | ||||
| 265 | + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; | ||||
| 266 | + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; | ||||
| 267 | + CLANG_WARN_EMPTY_BODY = YES; | ||||
| 268 | + CLANG_WARN_ENUM_CONVERSION = YES; | ||||
| 269 | + CLANG_WARN_INFINITE_RECURSION = YES; | ||||
| 270 | + CLANG_WARN_INT_CONVERSION = YES; | ||||
| 271 | + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; | ||||
| 272 | + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; | ||||
| 273 | + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; | ||||
| 274 | + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; | ||||
| 275 | + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; | ||||
| 276 | + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; | ||||
| 277 | + CLANG_WARN_STRICT_PROTOTYPES = YES; | ||||
| 278 | + CLANG_WARN_SUSPICIOUS_MOVE = YES; | ||||
| 279 | + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; | ||||
| 280 | + CLANG_WARN_UNREACHABLE_CODE = YES; | ||||
| 281 | + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; | ||||
| 282 | + COPY_PHASE_STRIP = NO; | ||||
| 283 | + CURRENT_PROJECT_VERSION = 1; | ||||
| 284 | + DEBUG_INFORMATION_FORMAT = dwarf; | ||||
| 285 | + DEVELOPMENT_TEAM = 3YM54G49SN; | ||||
| 286 | + ENABLE_STRICT_OBJC_MSGSEND = YES; | ||||
| 287 | + ENABLE_TESTABILITY = YES; | ||||
| 288 | + GCC_C_LANGUAGE_STANDARD = gnu11; | ||||
| 289 | + GCC_DYNAMIC_NO_PIC = NO; | ||||
| 290 | + GCC_NO_COMMON_BLOCKS = YES; | ||||
| 291 | + GCC_OPTIMIZATION_LEVEL = 0; | ||||
| 292 | + GCC_PREPROCESSOR_DEFINITIONS = ( | ||||
| 293 | + "$(inherited)", | ||||
| 294 | + "DEBUG=1", | ||||
| 295 | + ); | ||||
| 296 | + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; | ||||
| 297 | + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; | ||||
| 298 | + GCC_WARN_UNDECLARED_SELECTOR = YES; | ||||
| 299 | + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; | ||||
| 300 | + GCC_WARN_UNUSED_FUNCTION = YES; | ||||
| 301 | + GCC_WARN_UNUSED_VARIABLE = YES; | ||||
| 302 | + MACOSX_DEPLOYMENT_TARGET = 13.0; | ||||
| 303 | + MARKETING_VERSION = 1.0.0; | ||||
| 304 | + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; | ||||
| 305 | + MTL_FAST_MATH = YES; | ||||
| 306 | + ONLY_ACTIVE_ARCH = YES; | ||||
| 307 | + PRODUCT_NAME = "$(TARGET_NAME)"; | ||||
| 308 | + SDKROOT = macosx; | ||||
| 309 | + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; | ||||
| 310 | + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; | ||||
| 311 | + SWIFT_VERSION = 5.0; | ||||
| 312 | + }; | ||||
| 313 | + name = Debug; | ||||
| 314 | + }; | ||||
| 315 | +/* End XCBuildConfiguration section */ | ||||
| 316 | + | ||||
| 317 | +/* Begin XCConfigurationList section */ | ||||
| 318 | + 37792F69F119471FA311BAB8 /* Build configuration list for PBXNativeTarget "AdminKaMac" */ = { | ||||
| 319 | + isa = XCConfigurationList; | ||||
| 320 | + buildConfigurations = ( | ||||
| 321 | + CA399800D52E645C7E657403 /* Debug */, | ||||
| 322 | + 9F641E359B9E74716ED4B9E5 /* Release */, | ||||
| 323 | + ); | ||||
| 324 | + defaultConfigurationIsVisible = 0; | ||||
| 325 | + defaultConfigurationName = Debug; | ||||
| 326 | + }; | ||||
| 327 | + A6EFFDB2CC27831A956303CB /* Build configuration list for PBXProject "AdminKaMac" */ = { | ||||
| 328 | + isa = XCConfigurationList; | ||||
| 329 | + buildConfigurations = ( | ||||
| 330 | + E5F59090737C7E513CCF4FB1 /* Debug */, | ||||
| 331 | + 47C2705EB0F5CFC9CED0406F /* Release */, | ||||
| 332 | + ); | ||||
| 333 | + defaultConfigurationIsVisible = 0; | ||||
| 334 | + defaultConfigurationName = Debug; | ||||
| 335 | + }; | ||||
| 336 | +/* End XCConfigurationList section */ | ||||
| 337 | + }; | ||||
| 338 | + rootObject = FB566ECDA392935EE6C8E20F /* Project object */; | ||||
| 339 | +} | ||||
added
AdminKaMac.xcodeproj/project.xcworkspace/contents.xcworkspacedata
+7 −0
@@ -0,0 +1,7 @@ | |||||
| 1 | +<?xml version="1.0" encoding="UTF-8"?> | ||||
| 2 | +<Workspace | ||||
| 3 | + version = "1.0"> | ||||
| 4 | + <FileRef | ||||
| 5 | + location = "self:"> | ||||
| 6 | + </FileRef> | ||||
| 7 | +</Workspace> | ||||
added
Resources/Assets.xcassets/AppIcon.appiconset/Contents.json
+15 −0
@@ -0,0 +1,15 @@ | |||||
| 1 | +{ | ||||
| 2 | + "images" : [ | ||||
| 3 | + {"idiom":"mac","scale":"1x","size":"16x16","filename":"icon_16.png"}, | ||||
| 4 | + {"idiom":"mac","scale":"2x","size":"16x16","filename":"icon_32.png"}, | ||||
| 5 | + {"idiom":"mac","scale":"1x","size":"32x32","filename":"icon_32.png"}, | ||||
| 6 | + {"idiom":"mac","scale":"2x","size":"32x32","filename":"icon_64.png"}, | ||||
| 7 | + {"idiom":"mac","scale":"1x","size":"128x128","filename":"icon_128.png"}, | ||||
| 8 | + {"idiom":"mac","scale":"2x","size":"128x128","filename":"icon_256.png"}, | ||||
| 9 | + {"idiom":"mac","scale":"1x","size":"256x256","filename":"icon_256.png"}, | ||||
| 10 | + {"idiom":"mac","scale":"2x","size":"256x256","filename":"icon_512.png"}, | ||||
| 11 | + {"idiom":"mac","scale":"1x","size":"512x512","filename":"icon_512.png"}, | ||||
| 12 | + {"idiom":"mac","scale":"2x","size":"512x512","filename":"icon_1024.png"} | ||||
| 13 | + ], | ||||
| 14 | + "info" : { "author" : "xcode", "version" : 1 } | ||||
| 15 | +} | ||||
added
Resources/Assets.xcassets/AppIcon.appiconset/icon_1024.png
+0 −0
Binary file not shown.
added
Resources/Assets.xcassets/AppIcon.appiconset/icon_128.png
+0 −0
Binary file not shown.
added
Resources/Assets.xcassets/AppIcon.appiconset/icon_16.png
+0 −0
Binary file not shown.
added
Resources/Assets.xcassets/AppIcon.appiconset/icon_256.png
+0 −0
Binary file not shown.
added
Resources/Assets.xcassets/AppIcon.appiconset/icon_32.png
+0 −0
Binary file not shown.
added
Resources/Assets.xcassets/AppIcon.appiconset/icon_512.png
+0 −0
Binary file not shown.
added
Resources/Assets.xcassets/AppIcon.appiconset/icon_64.png
+0 −0
Binary file not shown.
added
Resources/Assets.xcassets/Contents.json
+1 −0
@@ -0,0 +1 @@ | |||||
| 1 | +{ "info" : { "author" : "xcode", "version" : 1 } } | ||||
added
Sources/AdminKaMac.entitlements
+6 −0
@@ -0,0 +1,6 @@ | |||||
| 1 | +<?xml version="1.0" encoding="UTF-8"?> | ||||
| 2 | +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||||
| 3 | +<plist version="1.0"><dict> | ||||
| 4 | + <key>com.apple.security.app-sandbox</key><false/> | ||||
| 5 | + <key>com.apple.security.network.client</key><true/> | ||||
| 6 | +</dict></plist> | ||||
added
Sources/AdminKaMacApp.swift
+14 −0
@@ -0,0 +1,14 @@ | |||||
| 1 | +import SwiftUI | ||||
| 2 | + | ||||
| 3 | +@main | ||||
| 4 | +struct AdminKaMacApp: App { | ||||
| 5 | + var body: some Scene { | ||||
| 6 | + WindowGroup { | ||||
| 7 | + RootView() | ||||
| 8 | + .frame(minWidth: 420, idealWidth: 520, maxWidth: .infinity, | ||||
| 9 | + minHeight: 640, idealHeight: 860, maxHeight: .infinity) | ||||
| 10 | + } | ||||
| 11 | + .windowResizability(.contentSize) | ||||
| 12 | + .commands { CommandGroup(replacing: .newItem) {} } | ||||
| 13 | + } | ||||
| 14 | +} | ||||
added
Sources/Info.plist
+33 −0
@@ -0,0 +1,33 @@ | |||||
| 1 | +<?xml version="1.0" encoding="UTF-8"?> | ||||
| 2 | +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||||
| 3 | +<plist version="1.0"> | ||||
| 4 | +<dict> | ||||
| 5 | + <key>CFBundleDevelopmentRegion</key> | ||||
| 6 | + <string>$(DEVELOPMENT_LANGUAGE)</string> | ||||
| 7 | + <key>CFBundleDisplayName</key> | ||||
| 8 | + <string>Admin-Ka</string> | ||||
| 9 | + <key>CFBundleExecutable</key> | ||||
| 10 | + <string>$(EXECUTABLE_NAME)</string> | ||||
| 11 | + <key>CFBundleIdentifier</key> | ||||
| 12 | + <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> | ||||
| 13 | + <key>CFBundleInfoDictionaryVersion</key> | ||||
| 14 | + <string>6.0</string> | ||||
| 15 | + <key>CFBundleName</key> | ||||
| 16 | + <string>$(PRODUCT_NAME)</string> | ||||
| 17 | + <key>CFBundlePackageType</key> | ||||
| 18 | + <string>APPL</string> | ||||
| 19 | + <key>CFBundleShortVersionString</key> | ||||
| 20 | + <string>1.0.0</string> | ||||
| 21 | + <key>CFBundleVersion</key> | ||||
| 22 | + <string>1</string> | ||||
| 23 | + <key>LSMinimumSystemVersion</key> | ||||
| 24 | + <string>13.0</string> | ||||
| 25 | + <key>NSAppTransportSecurity</key> | ||||
| 26 | + <dict> | ||||
| 27 | + <key>NSAllowsArbitraryLoads</key> | ||||
| 28 | + <false/> | ||||
| 29 | + </dict> | ||||
| 30 | + <key>NSHumanReadableCopyright</key> | ||||
| 31 | + <string>© 2026 Simon-Pierre Boucher — Groupe KA</string> | ||||
| 32 | +</dict> | ||||
| 33 | +</plist> | ||||
added
Sources/RootView.swift
+65 −0
@@ -0,0 +1,65 @@ | |||||
| 1 | +import SwiftUI | ||||
| 2 | + | ||||
| 3 | +struct RootView: View { | ||||
| 4 | + @StateObject private var model = WebModel() | ||||
| 5 | + @State private var showSplash = true | ||||
| 6 | + | ||||
| 7 | + var body: some View { | ||||
| 8 | + ZStack { | ||||
| 9 | + Ka.bg.ignoresSafeArea() | ||||
| 10 | + WebView(model: model).opacity(model.loaded ? 1 : 0) | ||||
| 11 | + | ||||
| 12 | + if !model.loaded && !model.failed { | ||||
| 13 | + VStack(spacing: 0) { | ||||
| 14 | + GeometryReader { geo in | ||||
| 15 | + Rectangle().fill(Ka.orange) | ||||
| 16 | + .frame(width: geo.size.width * max(0.04, model.progress), height: 3) | ||||
| 17 | + .animation(.easeOut(duration: 0.25), value: model.progress) | ||||
| 18 | + }.frame(height: 3) | ||||
| 19 | + Spacer() | ||||
| 20 | + } | ||||
| 21 | + } | ||||
| 22 | + if showSplash { splash.transition(.opacity) } | ||||
| 23 | + if model.failed { offline } | ||||
| 24 | + } | ||||
| 25 | + .onChange(of: model.loaded) { loaded in | ||||
| 26 | + if loaded { | ||||
| 27 | + DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) { | ||||
| 28 | + withAnimation(.easeInOut(duration: 0.4)) { showSplash = false } | ||||
| 29 | + } | ||||
| 30 | + } | ||||
| 31 | + } | ||||
| 32 | + } | ||||
| 33 | + | ||||
| 34 | + private var splash: some View { | ||||
| 35 | + ZStack { | ||||
| 36 | + Ka.bg.ignoresSafeArea() | ||||
| 37 | + VStack(spacing: 16) { | ||||
| 38 | + KaMark(size: 88) | ||||
| 39 | + Text("Admin-Ka").font(.system(size: 24, weight: .heavy, design: .rounded)).foregroundColor(Ka.ink) | ||||
| 40 | + Text("Console Claude Code · Groupe KA") | ||||
| 41 | + .font(.system(size: 13, weight: .semibold, design: .rounded)).foregroundColor(Ka.muted) | ||||
| 42 | + if !model.failed { ProgressView().controlSize(.small).padding(.top, 4) } | ||||
| 43 | + } | ||||
| 44 | + } | ||||
| 45 | + } | ||||
| 46 | + | ||||
| 47 | + private var offline: some View { | ||||
| 48 | + ZStack { | ||||
| 49 | + Ka.bg.ignoresSafeArea() | ||||
| 50 | + VStack(spacing: 14) { | ||||
| 51 | + KaMark(size: 68) | ||||
| 52 | + Text("Hors ligne").font(.system(size: 20, weight: .heavy, design: .rounded)).foregroundColor(Ka.ink) | ||||
| 53 | + Text("Impossible de joindre administration-ka.com") | ||||
| 54 | + .font(.system(size: 13, weight: .medium, design: .rounded)).foregroundColor(Ka.muted) | ||||
| 55 | + Button { | ||||
| 56 | + showSplash = true; model.reload() | ||||
| 57 | + } label: { | ||||
| 58 | + Text("Réessayer").font(.system(size: 14, weight: .heavy, design: .rounded)) | ||||
| 59 | + .foregroundColor(Ka.ink).padding(.horizontal, 22).padding(.vertical, 10) | ||||
| 60 | + .background(Capsule().fill(Ka.orange).overlay(Capsule().strokeBorder(Ka.ink, lineWidth: 2))) | ||||
| 61 | + }.buttonStyle(.plain).padding(.top, 4) | ||||
| 62 | + } | ||||
| 63 | + } | ||||
| 64 | + } | ||||
| 65 | +} | ||||
added
Sources/Theme.swift
+34 −0
@@ -0,0 +1,34 @@ | |||||
| 1 | +import SwiftUI | ||||
| 2 | + | ||||
| 3 | +enum Ka { | ||||
| 4 | + static let bg = Color(hex: 0xF2F1EC) | ||||
| 5 | + static let card = Color(hex: 0xFCFBF8) | ||||
| 6 | + static let ink = Color(hex: 0x1A1611) | ||||
| 7 | + static let orange = Color(hex: 0xF97316) | ||||
| 8 | + static let muted = Color(hex: 0x6D675C) | ||||
| 9 | + static let url = URL(string: "https://www.administration-ka.com")! | ||||
| 10 | +} | ||||
| 11 | + | ||||
| 12 | +extension Color { | ||||
| 13 | + init(hex: UInt, alpha: Double = 1) { | ||||
| 14 | + self.init(.sRGB, | ||||
| 15 | + red: Double((hex >> 16) & 0xff) / 255, | ||||
| 16 | + green: Double((hex >> 8) & 0xff) / 255, | ||||
| 17 | + blue: Double(hex & 0xff) / 255, | ||||
| 18 | + opacity: alpha) | ||||
| 19 | + } | ||||
| 20 | +} | ||||
| 21 | + | ||||
| 22 | +struct KaMark: View { | ||||
| 23 | + var size: CGFloat = 84 | ||||
| 24 | + var body: some View { | ||||
| 25 | + RoundedRectangle(cornerRadius: size * 0.28, style: .continuous) | ||||
| 26 | + .fill(Ka.orange) | ||||
| 27 | + .overlay(RoundedRectangle(cornerRadius: size * 0.28, style: .continuous) | ||||
| 28 | + .strokeBorder(Ka.ink, lineWidth: max(2, size * 0.035))) | ||||
| 29 | + .overlay(Text("Ka") | ||||
| 30 | + .font(.system(size: size * 0.42, weight: .heavy, design: .rounded)) | ||||
| 31 | + .foregroundColor(Ka.ink)) | ||||
| 32 | + .frame(width: size, height: size) | ||||
| 33 | + } | ||||
| 34 | +} | ||||
added
Sources/WebView.swift
+98 −0
@@ -0,0 +1,98 @@ | |||||
| 1 | +import SwiftUI | ||||
| 2 | +import WebKit | ||||
| 3 | +import AppKit | ||||
| 4 | + | ||||
| 5 | +final class WebModel: ObservableObject { | ||||
| 6 | + @Published var progress: Double = 0 | ||||
| 7 | + @Published var loaded = false | ||||
| 8 | + @Published var failed = false | ||||
| 9 | + var webView: WKWebView? | ||||
| 10 | + func reload() { | ||||
| 11 | + failed = false; loaded = false; progress = 0 | ||||
| 12 | + if let wv = webView { if wv.url == nil { wv.load(URLRequest(url: Ka.url)) } else { wv.reload() } } | ||||
| 13 | + } | ||||
| 14 | +} | ||||
| 15 | + | ||||
| 16 | +struct WebView: NSViewRepresentable { | ||||
| 17 | + @ObservedObject var model: WebModel | ||||
| 18 | + | ||||
| 19 | + func makeCoordinator() -> Coordinator { Coordinator(model: model) } | ||||
| 20 | + | ||||
| 21 | + func makeNSView(context: Context) -> WKWebView { | ||||
| 22 | + let cfg = WKWebViewConfiguration() | ||||
| 23 | + cfg.websiteDataStore = .default() // cookie de session persistant | ||||
| 24 | + cfg.defaultWebpagePreferences.allowsContentJavaScript = true | ||||
| 25 | + let wv = WKWebView(frame: .zero, configuration: cfg) | ||||
| 26 | + wv.navigationDelegate = context.coordinator | ||||
| 27 | + wv.uiDelegate = context.coordinator | ||||
| 28 | + wv.setValue(false, forKey: "drawsBackground") // fond transparent → crème | ||||
| 29 | + wv.customUserAgent = "AdminKa-macOS/1.0 (Groupe KA console)" | ||||
| 30 | + context.coordinator.observe(wv) | ||||
| 31 | + model.webView = wv | ||||
| 32 | + wv.load(URLRequest(url: Ka.url)) | ||||
| 33 | + return wv | ||||
| 34 | + } | ||||
| 35 | + | ||||
| 36 | + func updateNSView(_ nsView: WKWebView, context: Context) {} | ||||
| 37 | + | ||||
| 38 | + final class Coordinator: NSObject, WKNavigationDelegate, WKUIDelegate { | ||||
| 39 | + let model: WebModel | ||||
| 40 | + private var obs: NSKeyValueObservation? | ||||
| 41 | + init(model: WebModel) { self.model = model } | ||||
| 42 | + | ||||
| 43 | + func observe(_ wv: WKWebView) { | ||||
| 44 | + obs = wv.observe(\.estimatedProgress, options: [.new]) { [weak self] wv, _ in | ||||
| 45 | + DispatchQueue.main.async { self?.model.progress = wv.estimatedProgress } | ||||
| 46 | + } | ||||
| 47 | + } | ||||
| 48 | + func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { | ||||
| 49 | + DispatchQueue.main.async { | ||||
| 50 | + withAnimation(.easeOut(duration: 0.35)) { self.model.loaded = true } | ||||
| 51 | + self.model.failed = false | ||||
| 52 | + } | ||||
| 53 | + } | ||||
| 54 | + func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) { fail(error) } | ||||
| 55 | + func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) { fail(error) } | ||||
| 56 | + private func fail(_ error: Error) { | ||||
| 57 | + if (error as NSError).code == NSURLErrorCancelled { return } | ||||
| 58 | + DispatchQueue.main.async { self.model.failed = true } | ||||
| 59 | + } | ||||
| 60 | + | ||||
| 61 | + // liens externes → navigateur par défaut | ||||
| 62 | + func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, | ||||
| 63 | + decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) { | ||||
| 64 | + if let url = navigationAction.request.url, let host = url.host, | ||||
| 65 | + navigationAction.navigationType == .linkActivated, host != Ka.url.host { | ||||
| 66 | + NSWorkspace.shared.open(url); decisionHandler(.cancel); return | ||||
| 67 | + } | ||||
| 68 | + decisionHandler(.allow) | ||||
| 69 | + } | ||||
| 70 | + func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, | ||||
| 71 | + for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? { | ||||
| 72 | + if let url = navigationAction.request.url { NSWorkspace.shared.open(url) } | ||||
| 73 | + return nil | ||||
| 74 | + } | ||||
| 75 | + | ||||
| 76 | + // --- Panneaux JS natifs (confirm() indispensable pour le mode BYPASS) --- | ||||
| 77 | + func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, | ||||
| 78 | + initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void) { | ||||
| 79 | + let a = NSAlert(); a.messageText = "Admin-Ka"; a.informativeText = message; a.addButton(withTitle: "OK") | ||||
| 80 | + a.runModal(); completionHandler() | ||||
| 81 | + } | ||||
| 82 | + func webView(_ webView: WKWebView, runJavaScriptConfirmPanelWithMessage message: String, | ||||
| 83 | + initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (Bool) -> Void) { | ||||
| 84 | + let a = NSAlert(); a.messageText = "Admin-Ka"; a.informativeText = message | ||||
| 85 | + a.addButton(withTitle: "OK"); a.addButton(withTitle: "Annuler") | ||||
| 86 | + completionHandler(a.runModal() == .alertFirstButtonReturn) | ||||
| 87 | + } | ||||
| 88 | + func webView(_ webView: WKWebView, runJavaScriptTextInputPanelWithPrompt prompt: String, | ||||
| 89 | + defaultText: String?, initiatedByFrame frame: WKFrameInfo, | ||||
| 90 | + completionHandler: @escaping (String?) -> Void) { | ||||
| 91 | + let a = NSAlert(); a.messageText = "Admin-Ka"; a.informativeText = prompt | ||||
| 92 | + a.addButton(withTitle: "OK"); a.addButton(withTitle: "Annuler") | ||||
| 93 | + let tf = NSTextField(frame: NSRect(x: 0, y: 0, width: 260, height: 24)); tf.stringValue = defaultText ?? "" | ||||
| 94 | + a.accessoryView = tf | ||||
| 95 | + completionHandler(a.runModal() == .alertFirstButtonReturn ? tf.stringValue : nil) | ||||
| 96 | + } | ||||
| 97 | + } | ||||
| 98 | +} | ||||
added
project.yml
+40 −0
@@ -0,0 +1,40 @@ | |||||
| 1 | +name: AdminKaMac | ||||
| 2 | +options: | ||||
| 3 | + bundleIdPrefix: com.groupeka | ||||
| 4 | + deploymentTarget: | ||||
| 5 | + macOS: "13.0" | ||||
| 6 | + createIntermediateGroups: true | ||||
| 7 | +settings: | ||||
| 8 | + base: | ||||
| 9 | + MARKETING_VERSION: "1.0.0" | ||||
| 10 | + CURRENT_PROJECT_VERSION: "1" | ||||
| 11 | + DEVELOPMENT_TEAM: "3YM54G49SN" | ||||
| 12 | + SWIFT_VERSION: "5.0" | ||||
| 13 | +targets: | ||||
| 14 | + AdminKaMac: | ||||
| 15 | + type: application | ||||
| 16 | + platform: macOS | ||||
| 17 | + sources: | ||||
| 18 | + - Sources | ||||
| 19 | + - Resources | ||||
| 20 | + info: | ||||
| 21 | + path: Sources/Info.plist | ||||
| 22 | + properties: | ||||
| 23 | + CFBundleDisplayName: Admin-Ka | ||||
| 24 | + CFBundleShortVersionString: "1.0.0" | ||||
| 25 | + CFBundleVersion: "1" | ||||
| 26 | + LSMinimumSystemVersion: "13.0" | ||||
| 27 | + NSHumanReadableCopyright: "© 2026 Simon-Pierre Boucher — Groupe KA" | ||||
| 28 | + NSAppTransportSecurity: | ||||
| 29 | + NSAllowsArbitraryLoads: false | ||||
| 30 | + settings: | ||||
| 31 | + base: | ||||
| 32 | + PRODUCT_BUNDLE_IDENTIFIER: com.groupeka.adminkamac | ||||
| 33 | + PRODUCT_NAME: Admin-Ka | ||||
| 34 | + ASSETCATALOG_COMPILER_APPICON_NAME: AppIcon | ||||
| 35 | + ENABLE_HARDENED_RUNTIME: "YES" | ||||
| 36 | + CODE_SIGN_STYLE: Manual | ||||
| 37 | + CODE_SIGN_IDENTITY: "Developer ID Application" | ||||
| 38 | + COMBINE_HIDPI_IMAGES: "YES" | ||||
| 39 | + MACOSX_DEPLOYMENT_TARGET: "13.0" | ||||
| 40 | + CODE_SIGN_ENTITLEMENTS: Sources/AdminKaMac.entitlements | ||||
| 41 | |||||