diff --git a/Example/Podfile b/Example/Podfile index 1655c78..d81ff1e 100644 --- a/Example/Podfile +++ b/Example/Podfile @@ -1,5 +1,5 @@ use_frameworks! -platform :ios, '11.0' +platform :ios, '14.0' target 'Sentinel_Example' do pod 'Sentinel', :path => '../' diff --git a/Example/Podfile.lock b/Example/Podfile.lock index bce9558..b691d97 100644 --- a/Example/Podfile.lock +++ b/Example/Podfile.lock @@ -1,19 +1,19 @@ PODS: - - Sentinel (1.2.2): - - Sentinel/Default (= 1.2.2) - - Sentinel/Core (1.2.2) - - Sentinel/CustomLocation (1.2.2): + - Sentinel (2.0.0): + - Sentinel/Default (= 2.0.0) + - Sentinel/Core (2.0.0) + - Sentinel/CustomLocation (2.0.0): - Sentinel/Core - - Sentinel/Default (1.2.2): + - Sentinel/Default (2.0.0): - Sentinel/Core - Sentinel/CustomLocation - Sentinel/TextEditing - Sentinel/UserDefaults - - Sentinel/EmailSender (1.2.2): + - Sentinel/EmailSender (2.0.0): - Sentinel/Core - - Sentinel/TextEditing (1.2.2): + - Sentinel/TextEditing (2.0.0): - Sentinel/Core - - Sentinel/UserDefaults (1.2.2): + - Sentinel/UserDefaults (2.0.0): - Sentinel/Core DEPENDENCIES: @@ -25,8 +25,8 @@ EXTERNAL SOURCES: :path: "../" SPEC CHECKSUMS: - Sentinel: ff75b928d3f1517992ba63e7a48b18230194e737 + Sentinel: d846456bed40a8f1983534a141eb259b8fc1870f -PODFILE CHECKSUM: 9c832ffe95f37b33da45d44c34055fef22efd343 +PODFILE CHECKSUM: b4ac31ac0023145189dcb5c8e0a0491b082199f1 -COCOAPODS: 1.15.2 +COCOAPODS: 1.16.2 diff --git a/Example/Pods/Local Podspecs/Sentinel.podspec.json b/Example/Pods/Local Podspecs/Sentinel.podspec.json index 5644d97..b8fc2f6 100644 --- a/Example/Pods/Local Podspecs/Sentinel.podspec.json +++ b/Example/Pods/Local Podspecs/Sentinel.podspec.json @@ -1,11 +1,11 @@ { "name": "Sentinel", - "version": "1.2.2", + "version": "2.0.0", "summary": "Developer's toolbox for debugging applications", "description": "Sentinel is a simple library which gives developers a possibility to configure one entry point for every debug tool.\nThe idea of Sentinel is to give ability to developers to configure screen with multiple debug tools which are available via some event (e.g. shake, notification).", "homepage": "https://github.com/infinum/ios-sentinel", "license": { - "type": "MIT", + "type": "Apache 2.0", "file": "LICENSE" }, "authors": { @@ -15,11 +15,11 @@ }, "source": { "git": "https://github.com/infinum/ios-sentinel.git", - "tag": "1.2.2" + "tag": "2.0.0" }, "requires_arc": true, "platforms": { - "ios": "11.0" + "ios": "14.0" }, "swift_versions": "5.0", "resource_bundles": { diff --git a/Example/Pods/Manifest.lock b/Example/Pods/Manifest.lock index bce9558..b691d97 100644 --- a/Example/Pods/Manifest.lock +++ b/Example/Pods/Manifest.lock @@ -1,19 +1,19 @@ PODS: - - Sentinel (1.2.2): - - Sentinel/Default (= 1.2.2) - - Sentinel/Core (1.2.2) - - Sentinel/CustomLocation (1.2.2): + - Sentinel (2.0.0): + - Sentinel/Default (= 2.0.0) + - Sentinel/Core (2.0.0) + - Sentinel/CustomLocation (2.0.0): - Sentinel/Core - - Sentinel/Default (1.2.2): + - Sentinel/Default (2.0.0): - Sentinel/Core - Sentinel/CustomLocation - Sentinel/TextEditing - Sentinel/UserDefaults - - Sentinel/EmailSender (1.2.2): + - Sentinel/EmailSender (2.0.0): - Sentinel/Core - - Sentinel/TextEditing (1.2.2): + - Sentinel/TextEditing (2.0.0): - Sentinel/Core - - Sentinel/UserDefaults (1.2.2): + - Sentinel/UserDefaults (2.0.0): - Sentinel/Core DEPENDENCIES: @@ -25,8 +25,8 @@ EXTERNAL SOURCES: :path: "../" SPEC CHECKSUMS: - Sentinel: ff75b928d3f1517992ba63e7a48b18230194e737 + Sentinel: d846456bed40a8f1983534a141eb259b8fc1870f -PODFILE CHECKSUM: 9c832ffe95f37b33da45d44c34055fef22efd343 +PODFILE CHECKSUM: b4ac31ac0023145189dcb5c8e0a0491b082199f1 -COCOAPODS: 1.15.2 +COCOAPODS: 1.16.2 diff --git a/Example/Pods/Pods.xcodeproj/project.pbxproj b/Example/Pods/Pods.xcodeproj/project.pbxproj index 4a40222..8440c33 100644 --- a/Example/Pods/Pods.xcodeproj/project.pbxproj +++ b/Example/Pods/Pods.xcodeproj/project.pbxproj @@ -7,85 +7,85 @@ objects = { /* Begin PBXBuildFile section */ - 05AB55A6BC62A0A338BEABBED4CDE6C0 /* OptionSwitchTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D1FC1FB2CA22755615F62A37C6345BC /* OptionSwitchTableViewCell.swift */; }; - 0B60642A872051D58C85906229FBFEDA /* Sentinel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D80B9F1DC5452E95CC3A5EF41AFCC825 /* Sentinel.swift */; }; - 0C4019269D306392E708744DD4AC7DBA /* Sentinel-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 4452D60511129A8FAEA7813B6E7385A1 /* Sentinel-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 0E0D681E9442C38F33E1A92C5B047F78 /* CustomInfoTool.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71F0DCC041ECAD8156E23F52ADBEDA3E /* CustomInfoTool.swift */; }; - 10FB0CB37C8E8DB63D5115B0D6104A34 /* EmailSenderTool.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75F4AA20F4520ABF3CABE32553A07230 /* EmailSenderTool.swift */; }; - 11466F4958009FACA62F4758326E0664 /* ToolTableSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 978E8A23DEF1A3F6C6BEEE01D608C19E /* ToolTableSection.swift */; }; - 1224D96255A69B9E380683BEF3920004 /* NavigationToolTableCell.xib in Sources */ = {isa = PBXBuildFile; fileRef = FCE2EB823A8255FB6CFE0569F6B4C56E /* NavigationToolTableCell.xib */; }; - 1555846FBCFD3F3AD82809D1236251BF /* CustomLocationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D924EFA9A100F58C6EEC617AFA50215 /* CustomLocationViewController.swift */; }; - 1AA43EFE0B951436A9D995439FC3955C /* MemoryInfoProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 626662882F1871895D8C23A12020F397 /* MemoryInfoProvider.swift */; }; - 1EF7D76198050F8C58A7C42A07864F71 /* ApplicationTool.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47176B1B2EB5521860BD50A4E66CDD41 /* ApplicationTool.swift */; }; - 24C147D76A4A1B06597D62F830731977 /* SourceScreenProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78E094F5D9416F260775BD27751BF17C /* SourceScreenProvider.swift */; }; - 2575D52D68BFB3AE7AEF1D85A37D3730 /* CLLocationManager+CustomLocation.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1C36A135F7052FD39FCA12F876C31BA /* CLLocationManager+CustomLocation.swift */; }; - 26319041AE5F57B4B76D003DDB5DBB0B /* CustomLocationTool.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2E4F99AD4F34FD69C5724E16746B4F8C /* CustomLocationTool.swift */; }; - 277EEF184CAC2B7C848CE24B26536103 /* assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 04D293A77C27B984E3568BA4A74C9371 /* assets.xcassets */; }; - 2B85A5D064E16AC415C4FDB5D840E347 /* Tool.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3B38B06CBB96138BCE3072322526D09 /* Tool.swift */; }; - 33101FBA9CD6C060453E6D48A11B8EAA /* CPUInfoProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5734767C80518F45C3780A076AE2C39B /* CPUInfoProvider.swift */; }; - 340E47C4CE7263D01EE8CCFF18D52B4B /* SentinelTabBarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8ED87451C325BDBB98187B49F9532846 /* SentinelTabBarController.swift */; }; - 3BDC3EB6545B60F23307B52624F4CADA /* UserDefaultsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F288809E670D73236EEDD32AF0385F52 /* UserDefaultsViewController.swift */; }; - 46B86E290AEED299FD5577116F78BB3E /* Pods-Sentinel_Example-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 89C6FAA08483FA46AF62E0083A4A1ECE /* Pods-Sentinel_Example-dummy.m */; }; - 473657D546CDAF92D6F9C0E792B19B60 /* SentinelTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B84A88183D8C8478D8897E03941CE3A /* SentinelTableViewController.swift */; }; - 4B881ACC3EB405B590A7DE9E9F0B5AD3 /* DetailToolTableCell.xib in Sources */ = {isa = PBXBuildFile; fileRef = E1DD3D88EAA5B0E19D76AB2DED4D42CB /* DetailToolTableCell.xib */; }; - 5A3D76150331AA1378E52A7AD4469FE8 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EAB6F611E86A4758835A715E4B4184F6 /* Foundation.framework */; }; - 66FB1A417AF801C9D2D64C4606310135 /* UserDefaultsTool.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB2EB2A430971FEF597833432027A012 /* UserDefaultsTool.swift */; }; - 6854D870A57A83463A08B042B95B8EB0 /* UserDefaults.storyboard in Sources */ = {isa = PBXBuildFile; fileRef = 418F81F9372721938AFA1EF3CF963146 /* UserDefaults.storyboard */; }; - 732D182A7621FC474379DDF296CFB2D7 /* SentinelTabItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E76AD572469569325561B1BFB22997C /* SentinelTabItem.swift */; }; - 734DAA2EF065C3C87EA7D3E01D46203E /* UIImage+Bundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 399271B986BF07F35759398166218340 /* UIImage+Bundle.swift */; }; - 7C976162D8AA55F0635D9B6A9BF4DD38 /* TextEditingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F76E11D51FF8E682DBB040B410108B37 /* TextEditingViewController.swift */; }; - 835A1CC875C3952CC27F028417373699 /* PerformanceTool.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C4A505FC7768CC6429D806DE09992FF /* PerformanceTool.swift */; }; - 899ECC402431BD12B73393CB3673E7BF /* OptionSwitchTableViewCell.xib in Sources */ = {isa = PBXBuildFile; fileRef = F58CF055598AA1A39265E42A84471325 /* OptionSwitchTableViewCell.xib */; }; - 8DA27679E2A522DC10EF3EFFA4F6BED7 /* DetailToolTableCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F433AE1221C0C34EF5CEFF4443D7CC0B /* DetailToolTableCell.swift */; }; - 907CB1DCF4723A718AA9F51BC8A60BC3 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EAB6F611E86A4758835A715E4B4184F6 /* Foundation.framework */; }; - 90B4CE627F55D9D5555D245F7F7A871E /* NavigationToolTableCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63C6F87374E5BE3824492E440C8C533B /* NavigationToolTableCell.swift */; }; - 9F502C0688F4D9325AC72B1AD094FF9F /* SentinelInternal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 25F03579FCC17D7E4F4017B7896B9101 /* SentinelInternal.swift */; }; - A1DF74C8E2640A0A223BAC397CB1B798 /* OptionSwitchItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = DED59AABC96E80C931B8AE9E62AB1C20 /* OptionSwitchItem.swift */; }; - A25FEC28C4FFF5686CE137A033571B89 /* PerformanceInfo.storyboard in Sources */ = {isa = PBXBuildFile; fileRef = 9FFDDD993B6615D594BF12F7114C4114 /* PerformanceInfo.storyboard */; }; - A58B48B33225C272B33867336B62B548 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D245E0514AAC1A2B9A6D5EA2F383E90F /* UIKit.framework */; }; - A73E0EA9DB84A1FDF0317CD4468D6029 /* PerformanceInfoItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB923BE4FFCCB97B4A21DBEDF1D7023A /* PerformanceInfoItem.swift */; }; - AD3DEA85B614790B8CD5470E3093BB79 /* UIImage+Assets.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD5A8166FE949AD66583F3DD9FC6D0F2 /* UIImage+Assets.swift */; }; - B23641FF4898CF2A0121F8859419A180 /* Pods-Sentinel_Example-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 6CC63C249594FFB7BA2A29447E90165F /* Pods-Sentinel_Example-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B25EC552C3037243F505D4B95C7AFABB /* TextEditingTool.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8E2C86790AF40AD69290F571F8770B26 /* TextEditingTool.swift */; }; - B40BD9D6EA4805C9A0E676F6E9B2A48C /* Pods-Sentinel_Tests-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 3737F3A9AFF9607DB0AEDEEEBAB55101 /* Pods-Sentinel_Tests-dummy.m */; }; - BC6D41D6C5B4A4D3FAD732CCD9A66049 /* CustomLocationProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB705774774B32DD7D277EBF7A196E6B /* CustomLocationProvider.swift */; }; - C83AA04D10AEBD6EB6B2EE8BB8E27C04 /* Sentinel-Sentinel in Resources */ = {isa = PBXBuildFile; fileRef = 2E1AA5D1D3E95612E2BD2EA95F67C327 /* Sentinel-Sentinel */; }; - C9652C920E0F83FA431A8EDBCBEE938A /* Sentinel-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 0123519EBBADBDD3CA020E20D74CC504 /* Sentinel-dummy.m */; }; - CF604FB79DBA85F3F42C17AD23F2709F /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EAB6F611E86A4758835A715E4B4184F6 /* Foundation.framework */; }; - D45E6493FD41DD7AFDA785993EBDDA4C /* Pods-Sentinel_Tests-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = D3908B2A61F0DD8BEE4E68CA7C472C70 /* Pods-Sentinel_Tests-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - DA77B284C9752002B98FC95FF33BA58B /* ToolTableItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49579ACDDB3732224639307E23FF67C1 /* ToolTableItem.swift */; }; - DCF557C34BCA2C9CBC3C7187B007F3E3 /* MailData.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7B50E56512DF4FE3C282876E7C50698 /* MailData.swift */; }; - DD9E8478B694ABBF79A137993AD037A3 /* Sentinel.storyboard in Sources */ = {isa = PBXBuildFile; fileRef = 426DE0FE6910431B22E09536514A584B /* Sentinel.storyboard */; }; - DEE491BE61118EF69DE9BFFC95278521 /* Trigger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 949F18898FCB7FECE333FDD3C228B214 /* Trigger.swift */; }; - E0CB49456E0712E2D62904CB05363E69 /* PerformanceInfoTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88108BDB5A44D116EDCBBE34998E349C /* PerformanceInfoTableViewCell.swift */; }; - E4CA7F6F3C0223AC1AF6617FAD2A031A /* PerformanceInfoTableViewCell.xib in Sources */ = {isa = PBXBuildFile; fileRef = 325939692C21D25F13B44608763F7A58 /* PerformanceInfoTableViewCell.xib */; }; - E7256F07482ED9F92DCB954F895F0065 /* SystemInfoProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = A717C851D9595C11E64523BD7AC7A0A8 /* SystemInfoProvider.swift */; }; - E7B4EB42519269AF1BE2B291B15C926D /* ToolTable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B89409BDEAD1944C09A82B1D064EFC0 /* ToolTable.swift */; }; - E854580C1249D2DDBBE456850EE3DA11 /* TextEditing.storyboard in Sources */ = {isa = PBXBuildFile; fileRef = B7552DF7B596D3A829EAABC526A54227 /* TextEditing.storyboard */; }; - E93B07FAC749E40D2F350B585A7DB749 /* DeviceTool.swift in Sources */ = {isa = PBXBuildFile; fileRef = 437E26734FC551BC25697D55C7692056 /* DeviceTool.swift */; }; - EA97067A7F7FD0E23CA2FB782957D469 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 105731A6C88AA834631D0ACC8DB9ECB5 /* PrivacyInfo.xcprivacy */; }; - EAD8A81B57AB96EE157D6A5B8D931DC8 /* SentinelUIKitExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90C5F5B38BB1B4151E6BFDAFC77D4142 /* SentinelUIKitExtensions.swift */; }; - EEA0E6F5B41AE5F1D726554F8ED88EC0 /* SentinelTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD9EA9F4B4F1245665D161EC7498B2EE /* SentinelTab.swift */; }; - EF6123DF138FE896691229B582EEDA42 /* PreferencesTool.swift in Sources */ = {isa = PBXBuildFile; fileRef = F630E66CB142E3122D77616F6F122EA0 /* PreferencesTool.swift */; }; - FBF78676F8A7D41539A080DBEC595918 /* CustomLocation.storyboard in Sources */ = {isa = PBXBuildFile; fileRef = CC354FAD6744714772330A3CD30282B9 /* CustomLocation.storyboard */; }; + 005473C0AFEB79655BF6E4F4B400F545 /* Sentinel-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 054D3991200D83DFD5D340CF70BDE5CB /* Sentinel-dummy.m */; }; + 0207938303F4B09B48174B79120233BB /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8193349D819536E58C58A34C1B7DF545 /* Foundation.framework */; }; + 023262667F2527137B5AC417825F2B0D /* CustomLocationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5EDF15A7C2FB8637F4490E961B3EA5B2 /* CustomLocationView.swift */; }; + 059F787A59D49D4E9A81C3EA15F6E86A /* SentinelTabItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83EA438F56AF149B25540E9CDC01A9D3 /* SentinelTabItem.swift */; }; + 0D9C654F905AE538990D61D3B7E77BC9 /* EmailSenderTool.swift in Sources */ = {isa = PBXBuildFile; fileRef = 764239ED7CC3E8BC9586A187578ADD8F /* EmailSenderTool.swift */; }; + 0ED0A08227958A4951C614F6BC2CEC46 /* UserDefaultsTool.swift in Sources */ = {isa = PBXBuildFile; fileRef = E070A95877CAE8810B1AAB62E9C6441F /* UserDefaultsTool.swift */; }; + 0F1EAE11E488F618A3994F7EF0551720 /* UserDefaultsToolView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 569C8139885224C286C98ED89F816668 /* UserDefaultsToolView.swift */; }; + 1B388BC5A1412C7B5F27984B22D7A736 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8193349D819536E58C58A34C1B7DF545 /* Foundation.framework */; }; + 1CD052257A420FAAC70A4CAE5342EA11 /* Pods-Sentinel_Tests-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = D3908B2A61F0DD8BEE4E68CA7C472C70 /* Pods-Sentinel_Tests-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 207A5BAFEA9939902095DE15C51F92B8 /* PreferencesTool.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BDE761CF048886F8B8A0D6E5FFF44F4 /* PreferencesTool.swift */; }; + 24F6FE7875CC475211B856A0A1D8D5B0 /* Pods-Sentinel_Example-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 89C6FAA08483FA46AF62E0083A4A1ECE /* Pods-Sentinel_Example-dummy.m */; }; + 2B3A705A66176EF8795CFA1F0574F178 /* OptionSwitchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AEA4E34B70D9646CB4D747D9FEF9384 /* OptionSwitchView.swift */; }; + 2BD27E9BB4961B0DBD1475A60E64C1B7 /* CustomToolTableItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 244C746A4F5BA5CA9C75CB98A95427BC /* CustomToolTableItem.swift */; }; + 2F69E19201D8DF1597AF96A4BE46C780 /* SystemInfoProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 289BAB60952AADB226FF966E863DA302 /* SystemInfoProvider.swift */; }; + 2F6A95F16D7A3CE719475E09B635D3CB /* Sentinel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C54A17AFD399512F10D64665A5602027 /* Sentinel.swift */; }; + 3E20C49FAD685F1F6B45D0A72754354C /* PerformanceToolView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A19215F357F44C188882A0B628DFCA0E /* PerformanceToolView.swift */; }; + 43CC1082F5FA0C1CAA5A2328AB3F9EC0 /* TextEditingToolView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 361FC3862B02304CC2280B0B71E2BC46 /* TextEditingToolView.swift */; }; + 43E4F58BF88D8C0E5578DFA7A48E4B51 /* Image+Assets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B58D5D7B6470E1D7AF0641BD1C6375E /* Image+Assets.swift */; }; + 4956CDA9E114EDB786824DFCB5C2A41E /* CustomLocationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D9090F7B3CD6C372EC6FA3C5684B09D /* CustomLocationViewController.swift */; }; + 4CB1A01069A3B23E3A80600EB12B3FBB /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 4CAF6C687E6F8E3372704DA5E71B53E3 /* PrivacyInfo.xcprivacy */; }; + 4E61D90AFD03B7916676214441139DB1 /* Sentinel-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = E88A032177B257E384D84618DC2AE6C4 /* Sentinel-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 53D5078E20CAE5C1922B65E43BF9310F /* NavigationToolTableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AB6585D835E3A27D6CE8B68795FB56F9 /* NavigationToolTableView.swift */; }; + 55B6B0615B9CCC9CD56AE81BC34198F8 /* Tool.swift in Sources */ = {isa = PBXBuildFile; fileRef = 68CB5732D85B08E7D9508D62FBCB5519 /* Tool.swift */; }; + 5A210F0D0137B7C094242C17CC0B4EBF /* Pods-Sentinel_Tests-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 3737F3A9AFF9607DB0AEDEEEBAB55101 /* Pods-Sentinel_Tests-dummy.m */; }; + 5C0DA88EB8AC1A0E427C846AA234FAA5 /* PerformanceInfoItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06FFE2BA37A9DEDCAF6B2D40DF1AA835 /* PerformanceInfoItem.swift */; }; + 5D215B249442FC8B3483C15AD67CB1A7 /* DeviceTool.swift in Sources */ = {isa = PBXBuildFile; fileRef = C138DA13E2E55FCFDEF83AC818C2F17D /* DeviceTool.swift */; }; + 60CE0F964941ED5E766083354AFEAAEB /* SentinelTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4492E38B85A8FB5EF61F368982D24225 /* SentinelTab.swift */; }; + 6178879BA6BAABF7C9980D93F2A491F9 /* SentinelUIKitExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6BFCC6BF0BC1D639B210FB88B2F626EC /* SentinelUIKitExtensions.swift */; }; + 6B90FB8143A54B61700E4B1CB4FC6485 /* CustomLocationTool.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07EAD7DA6327ACA542B0F40E2C959B33 /* CustomLocationTool.swift */; }; + 73C72D35F3A1F77EA1D01AF0A786CC96 /* TextEditingTool.swift in Sources */ = {isa = PBXBuildFile; fileRef = D443B8AECAC90A02B03A2D3FF45C8C04 /* TextEditingTool.swift */; }; + 76BF7AF791BECF7848B65B803897BF6E /* MemoryInfoProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7847C54724D878771D2E00452D513095 /* MemoryInfoProvider.swift */; }; + 7A0DD883715A97DFC9754E5B149DC937 /* PerformanceInfoViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD331ABA61F940F1A7687445F3280FC2 /* PerformanceInfoViewModel.swift */; }; + 7F7EE868B8CAC146975F08D521B24A98 /* ToolTable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D273BEDE8FE8146E0D63B5F50751B45 /* ToolTable.swift */; }; + 8BB2E721FB6763E941FB63DF56EEF73F /* OptionSwitchItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87300A646F557036DD842F90C6C89414 /* OptionSwitchItem.swift */; }; + 92D0995AFE329EACAAA7DA66B90CB864 /* CustomInfoToolSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E7B5AB3C25917BCB4F2BACF733CAAAA /* CustomInfoToolSection.swift */; }; + 987236C1287444991C8016F0EBAEA1F5 /* ToolTableItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4918A781C339372C0BD8B0DA907E75F7 /* ToolTableItem.swift */; }; + 9FAC0C47ECDF4024148974DD821CA373 /* TitleValueView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C343D531FDB3EDD51527E0E3451A06C /* TitleValueView.swift */; }; + A206332F26FFF44AE37677FBA5BEEAC3 /* CustomInfoTool.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03247281412A1863370F775E18894969 /* CustomInfoTool.swift */; }; + A6E75D64743FF38C7529C1046D61D6B1 /* SentinelInternal.swift in Sources */ = {isa = PBXBuildFile; fileRef = B58B735CF79ADAA5A96CF1B653989CD9 /* SentinelInternal.swift */; }; + A8649AEED79F696CE022F7BD785E18E7 /* UserDefaultsToolViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 14A443FD05C04A923E7DD27BB103BBE6 /* UserDefaultsToolViewModel.swift */; }; + AA1B2C49B57DD9BF66F794CA80881C6E /* EmailSenderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A2A80E9E861F3776D224E50A1ABA63E5 /* EmailSenderView.swift */; }; + AE156CD0EE4AEC4C92531B82B3351068 /* Sentinel-Sentinel in Resources */ = {isa = PBXBuildFile; fileRef = 2E1AA5D1D3E95612E2BD2EA95F67C327 /* Sentinel-Sentinel */; }; + B62DE8EA56AAF47E58C04FDEB90492E0 /* CustomLocationProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09D3F046CEF486E0A9A4DE8922F35BF5 /* CustomLocationProvider.swift */; }; + C356D6D05DB281868BBCA398FDD2B5A8 /* MailData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C2CCAF9E916572214DCDFEFC3125CDB /* MailData.swift */; }; + C85764914BD02C5A249F48249437A917 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8193349D819536E58C58A34C1B7DF545 /* Foundation.framework */; }; + CBBBCAFCC8D62CEB7AC6F4602361802A /* CLLocationManager+CustomLocation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AABF748D2535AD78BE07F05CEA6E5A8 /* CLLocationManager+CustomLocation.swift */; }; + CFB1E9415B69536DB199E796B34E491D /* assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 65DC4A4FC2681CFF1F2FEA7086BBE6C9 /* assets.xcassets */; }; + D2B6AB8B102E1600802DA49CD8097BD9 /* SentinelTabBarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E488155D0FA8936E9AF44365697FDA15 /* SentinelTabBarView.swift */; }; + D3143FBCE8822356D2F93C7055CF3F69 /* Trigger.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFAB175E65C63BC1297D0D71DC550898 /* Trigger.swift */; }; + D3B12C93E7B782E316F07D4CEBFF6119 /* ToolTableSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38E3B64F88AF6BCC39A62DF6BFA7EE27 /* ToolTableSection.swift */; }; + D63812169E8A5CBB9D562EB31DC49AA7 /* SourceScreenProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4E86D2AC79156431365732D986710D1 /* SourceScreenProvider.swift */; }; + D746D5ECC29E62D6B222764CE3091CED /* PerformanceTool.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9CCA13B5FAB3C5EADEF6934E3AD1CAA8 /* PerformanceTool.swift */; }; + D77CFA9389950CECA6909F309249B60B /* CustomLocation.storyboard in Sources */ = {isa = PBXBuildFile; fileRef = 66C655FB71F2226582E424553A4794A1 /* CustomLocation.storyboard */; }; + D87E6290718F92138B492630F2A7B85E /* CPUInfoProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F979923D85629761105B642B6C011BC /* CPUInfoProvider.swift */; }; + DEC865A4A1FC21892EF1C737F8575226 /* ApplicationTool.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7CBA79D3738D8B41902BC91E3AB5A0F /* ApplicationTool.swift */; }; + DF42907C03E108163DE9C6C72127D667 /* SentinelListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A385843ED2D09D955AA16284F2521C8 /* SentinelListView.swift */; }; + E049996F2D77232D5EF9C8FE325C4FC9 /* TextEditingToolViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D3C92B69AACF472AED12FCC6C7626F32 /* TextEditingToolViewModel.swift */; }; + E2A6A1FA414E59E753D69A860B83EA2E /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ECF4CA3AF5536D14B4E015504E7AEEC0 /* UIKit.framework */; }; + EA52ABDDEF8CC52BA606701ED27937B8 /* NavigationToolTableItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D60229C8B8E9E90442D225B853A728D /* NavigationToolTableItem.swift */; }; + ECBAA3B892D2D58FFAEB362EE6C4F23E /* Pods-Sentinel_Example-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 6CC63C249594FFB7BA2A29447E90165F /* Pods-Sentinel_Example-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + F5FDC90AA853CA0C39F4F7741666A609 /* EmailSenderErrorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A4E75CA6AD0FCBAB3A0A4F3CA7917A7D /* EmailSenderErrorView.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ - 09B1ED28F6C43537557FDDDCD037916D /* PBXContainerItemProxy */ = { + 18DF10A0C285A2DF81A04FDE829964C0 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; remoteGlobalIDString = 8ACB6013C7A59AFAD22BD744A5CEE9FE; remoteInfo = "Sentinel-Sentinel"; }; - 50989D6A0F20DD0F78CDBC9D79F4C4E8 /* PBXContainerItemProxy */ = { + 4E0AC4479FA3066F2644D8EB9AB35F09 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; remoteGlobalIDString = F402433F0FA4E4D3D7AF80AFBDD40215; remoteInfo = Sentinel; }; - A3C4EA648F7BCEA6C547EA967387D1F6 /* PBXContainerItemProxy */ = { + 94A4DC63F50CBF58FA59FA569BF74303 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; @@ -95,123 +95,123 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ - 0123519EBBADBDD3CA020E20D74CC504 /* Sentinel-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Sentinel-dummy.m"; sourceTree = ""; }; - 04D293A77C27B984E3568BA4A74C9371 /* assets.xcassets */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = folder.assetcatalog; path = assets.xcassets; sourceTree = ""; }; - 105731A6C88AA834631D0ACC8DB9ECB5 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; - 1E76AD572469569325561B1BFB22997C /* SentinelTabItem.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SentinelTabItem.swift; sourceTree = ""; }; - 25F03579FCC17D7E4F4017B7896B9101 /* SentinelInternal.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SentinelInternal.swift; sourceTree = ""; }; + 03247281412A1863370F775E18894969 /* CustomInfoTool.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CustomInfoTool.swift; path = Sentinel/Classes/Core/CustomInfoTool.swift; sourceTree = ""; }; + 054D3991200D83DFD5D340CF70BDE5CB /* Sentinel-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Sentinel-dummy.m"; sourceTree = ""; }; + 06FFE2BA37A9DEDCAF6B2D40DF1AA835 /* PerformanceInfoItem.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PerformanceInfoItem.swift; sourceTree = ""; }; + 07EAD7DA6327ACA542B0F40E2C959B33 /* CustomLocationTool.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CustomLocationTool.swift; path = Sentinel/Classes/CustomLocation/CustomLocationTool.swift; sourceTree = ""; }; + 09D3F046CEF486E0A9A4DE8922F35BF5 /* CustomLocationProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CustomLocationProvider.swift; sourceTree = ""; }; + 0AEA4E34B70D9646CB4D747D9FEF9384 /* OptionSwitchView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = OptionSwitchView.swift; sourceTree = ""; }; + 0FD645F8FDA590A1283B3F4FE9543FAC /* Sentinel.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Sentinel.debug.xcconfig; sourceTree = ""; }; + 14A443FD05C04A923E7DD27BB103BBE6 /* UserDefaultsToolViewModel.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = UserDefaultsToolViewModel.swift; path = Sentinel/Classes/UserDefaults/UserDefaultsToolViewModel.swift; sourceTree = ""; }; + 150A2CBF0BFC9AAA5B3971B86BDA8C1C /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; path = LICENSE; sourceTree = ""; }; + 1E7B5AB3C25917BCB4F2BACF733CAAAA /* CustomInfoToolSection.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CustomInfoToolSection.swift; path = Sentinel/Classes/Core/CustomInfoToolSection.swift; sourceTree = ""; }; + 244C746A4F5BA5CA9C75CB98A95427BC /* CustomToolTableItem.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CustomToolTableItem.swift; sourceTree = ""; }; + 289BAB60952AADB226FF966E863DA302 /* SystemInfoProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SystemInfoProvider.swift; sourceTree = ""; }; + 2C343D531FDB3EDD51527E0E3451A06C /* TitleValueView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = TitleValueView.swift; sourceTree = ""; }; 2E1AA5D1D3E95612E2BD2EA95F67C327 /* Sentinel-Sentinel */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; name = "Sentinel-Sentinel"; path = Sentinel.bundle; sourceTree = BUILT_PRODUCTS_DIR; }; - 2E4F99AD4F34FD69C5724E16746B4F8C /* CustomLocationTool.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CustomLocationTool.swift; path = Sentinel/Classes/CustomLocation/CustomLocationTool.swift; sourceTree = ""; }; - 2E98A32570B59CCDC9F10FE0827754A8 /* Sentinel.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Sentinel.release.xcconfig; sourceTree = ""; }; - 325939692C21D25F13B44608763F7A58 /* PerformanceInfoTableViewCell.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; path = PerformanceInfoTableViewCell.xib; sourceTree = ""; }; + 31F545C3F7C7B36DE7382B13328068B8 /* Sentinel.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = Sentinel.modulemap; sourceTree = ""; }; + 361FC3862B02304CC2280B0B71E2BC46 /* TextEditingToolView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TextEditingToolView.swift; path = Sentinel/Classes/TextEditing/TextEditingToolView.swift; sourceTree = ""; }; 3737F3A9AFF9607DB0AEDEEEBAB55101 /* Pods-Sentinel_Tests-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-Sentinel_Tests-dummy.m"; sourceTree = ""; }; - 399271B986BF07F35759398166218340 /* UIImage+Bundle.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIImage+Bundle.swift"; path = "Sentinel/Classes/Core/UIImage+Bundle.swift"; sourceTree = ""; }; - 418F81F9372721938AFA1EF3CF963146 /* UserDefaults.storyboard */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.storyboard; name = UserDefaults.storyboard; path = Sentinel/Classes/UserDefaults/UserDefaults.storyboard; sourceTree = ""; }; - 426DE0FE6910431B22E09536514A584B /* Sentinel.storyboard */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.storyboard; path = Sentinel.storyboard; sourceTree = ""; }; - 437E26734FC551BC25697D55C7692056 /* DeviceTool.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = DeviceTool.swift; sourceTree = ""; }; - 4452D60511129A8FAEA7813B6E7385A1 /* Sentinel-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Sentinel-umbrella.h"; sourceTree = ""; }; - 47176B1B2EB5521860BD50A4E66CDD41 /* ApplicationTool.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ApplicationTool.swift; sourceTree = ""; }; - 49579ACDDB3732224639307E23FF67C1 /* ToolTableItem.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ToolTableItem.swift; path = Sentinel/Classes/Core/ToolTableItem.swift; sourceTree = ""; }; - 4B84A88183D8C8478D8897E03941CE3A /* SentinelTableViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SentinelTableViewController.swift; sourceTree = ""; }; - 4B89409BDEAD1944C09A82B1D064EFC0 /* ToolTable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ToolTable.swift; path = Sentinel/Classes/Core/ToolTable.swift; sourceTree = ""; }; - 4C4A505FC7768CC6429D806DE09992FF /* PerformanceTool.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PerformanceTool.swift; sourceTree = ""; }; + 38E3B64F88AF6BCC39A62DF6BFA7EE27 /* ToolTableSection.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ToolTableSection.swift; path = Sentinel/Classes/Core/ToolTableSection.swift; sourceTree = ""; }; + 4492E38B85A8FB5EF61F368982D24225 /* SentinelTab.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SentinelTab.swift; sourceTree = ""; }; + 4918A781C339372C0BD8B0DA907E75F7 /* ToolTableItem.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ToolTableItem.swift; path = Sentinel/Classes/Core/ToolTableItem.swift; sourceTree = ""; }; + 4BDE761CF048886F8B8A0D6E5FFF44F4 /* PreferencesTool.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PreferencesTool.swift; sourceTree = ""; }; + 4CAF6C687E6F8E3372704DA5E71B53E3 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; + 4F979923D85629761105B642B6C011BC /* CPUInfoProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CPUInfoProvider.swift; sourceTree = ""; }; 55CD7B5D6B41371E48802E60F2D85413 /* Pods-Sentinel_Example-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-Sentinel_Example-acknowledgements.markdown"; sourceTree = ""; }; - 5734767C80518F45C3780A076AE2C39B /* CPUInfoProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CPUInfoProvider.swift; sourceTree = ""; }; - 5CABB67CC6EA83AA9F45A7E22F03BC5E /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; path = README.md; sourceTree = ""; }; - 5D1FC1FB2CA22755615F62A37C6345BC /* OptionSwitchTableViewCell.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = OptionSwitchTableViewCell.swift; sourceTree = ""; }; - 626662882F1871895D8C23A12020F397 /* MemoryInfoProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = MemoryInfoProvider.swift; sourceTree = ""; }; - 63C6F87374E5BE3824492E440C8C533B /* NavigationToolTableCell.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = NavigationToolTableCell.swift; sourceTree = ""; }; + 569C8139885224C286C98ED89F816668 /* UserDefaultsToolView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = UserDefaultsToolView.swift; path = Sentinel/Classes/UserDefaults/UserDefaultsToolView.swift; sourceTree = ""; }; + 5EDF15A7C2FB8637F4490E961B3EA5B2 /* CustomLocationView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CustomLocationView.swift; path = Sentinel/Classes/CustomLocation/CustomLocationView.swift; sourceTree = ""; }; 65C9954C4CF9EB181467C37DE9785CCF /* Pods-Sentinel_Tests */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = "Pods-Sentinel_Tests"; path = Pods_Sentinel_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 65DC4A4FC2681CFF1F2FEA7086BBE6C9 /* assets.xcassets */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = folder.assetcatalog; path = assets.xcassets; sourceTree = ""; }; + 66C655FB71F2226582E424553A4794A1 /* CustomLocation.storyboard */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.storyboard; name = CustomLocation.storyboard; path = Sentinel/Classes/CustomLocation/CustomLocation.storyboard; sourceTree = ""; }; + 68CB5732D85B08E7D9508D62FBCB5519 /* Tool.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Tool.swift; path = Sentinel/Classes/Core/Tool.swift; sourceTree = ""; }; 6A2FAB1C2CA0327702BEBE0ED264FD12 /* Pods-Sentinel_Tests-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-Sentinel_Tests-acknowledgements.markdown"; sourceTree = ""; }; + 6B58D5D7B6470E1D7AF0641BD1C6375E /* Image+Assets.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "Image+Assets.swift"; sourceTree = ""; }; + 6BFCC6BF0BC1D639B210FB88B2F626EC /* SentinelUIKitExtensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SentinelUIKitExtensions.swift; sourceTree = ""; }; 6CC63C249594FFB7BA2A29447E90165F /* Pods-Sentinel_Example-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-Sentinel_Example-umbrella.h"; sourceTree = ""; }; - 71F0DCC041ECAD8156E23F52ADBEDA3E /* CustomInfoTool.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CustomInfoTool.swift; path = Sentinel/Classes/Core/CustomInfoTool.swift; sourceTree = ""; }; - 72216E79692E18558D345C8D92606137 /* Sentinel.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = Sentinel.modulemap; sourceTree = ""; }; - 74FF88B4F7AF82EB7C6152CF78BAF6E0 /* ResourceBundle-Sentinel-Sentinel-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "ResourceBundle-Sentinel-Sentinel-Info.plist"; sourceTree = ""; }; - 75F4AA20F4520ABF3CABE32553A07230 /* EmailSenderTool.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = EmailSenderTool.swift; path = Sentinel/Classes/EmailSender/EmailSenderTool.swift; sourceTree = ""; }; - 788EE74F754CE9BCC6905FF3EF4D4D5E /* Sentinel-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Sentinel-prefix.pch"; sourceTree = ""; }; - 78E094F5D9416F260775BD27751BF17C /* SourceScreenProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SourceScreenProvider.swift; path = Sentinel/Classes/Core/SourceScreenProvider.swift; sourceTree = ""; }; - 7D924EFA9A100F58C6EEC617AFA50215 /* CustomLocationViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CustomLocationViewController.swift; path = Sentinel/Classes/CustomLocation/CustomLocationViewController.swift; sourceTree = ""; }; - 84B7ED3A06CE15CCA34FBC84F3157D3C /* Sentinel.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; path = Sentinel.podspec; sourceTree = ""; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; - 85BC350766D86BCFF06AFDCA2F596D1A /* Sentinel.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Sentinel.debug.xcconfig; sourceTree = ""; }; - 88108BDB5A44D116EDCBBE34998E349C /* PerformanceInfoTableViewCell.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PerformanceInfoTableViewCell.swift; sourceTree = ""; }; + 6D1D7D0DE1BCC5E4BCE4831433CFB933 /* Sentinel.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; path = Sentinel.podspec; sourceTree = ""; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + 6D9090F7B3CD6C372EC6FA3C5684B09D /* CustomLocationViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CustomLocationViewController.swift; path = Sentinel/Classes/CustomLocation/CustomLocationViewController.swift; sourceTree = ""; }; + 764239ED7CC3E8BC9586A187578ADD8F /* EmailSenderTool.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = EmailSenderTool.swift; path = Sentinel/Classes/EmailSender/EmailSenderTool.swift; sourceTree = ""; }; + 7847C54724D878771D2E00452D513095 /* MemoryInfoProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = MemoryInfoProvider.swift; sourceTree = ""; }; + 7A385843ED2D09D955AA16284F2521C8 /* SentinelListView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SentinelListView.swift; sourceTree = ""; }; + 7AABF748D2535AD78BE07F05CEA6E5A8 /* CLLocationManager+CustomLocation.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "CLLocationManager+CustomLocation.swift"; sourceTree = ""; }; + 8193349D819536E58C58A34C1B7DF545 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS18.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; + 83EA438F56AF149B25540E9CDC01A9D3 /* SentinelTabItem.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SentinelTabItem.swift; sourceTree = ""; }; + 87300A646F557036DD842F90C6C89414 /* OptionSwitchItem.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = OptionSwitchItem.swift; sourceTree = ""; }; 89C6FAA08483FA46AF62E0083A4A1ECE /* Pods-Sentinel_Example-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-Sentinel_Example-dummy.m"; sourceTree = ""; }; 8C131C23A2981681C44E4F97E273B562 /* Pods-Sentinel_Tests.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-Sentinel_Tests.modulemap"; sourceTree = ""; }; - 8E2C86790AF40AD69290F571F8770B26 /* TextEditingTool.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TextEditingTool.swift; path = Sentinel/Classes/TextEditing/TextEditingTool.swift; sourceTree = ""; }; - 8ED87451C325BDBB98187B49F9532846 /* SentinelTabBarController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SentinelTabBarController.swift; sourceTree = ""; }; - 90C5F5B38BB1B4151E6BFDAFC77D4142 /* SentinelUIKitExtensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SentinelUIKitExtensions.swift; sourceTree = ""; }; + 8D60229C8B8E9E90442D225B853A728D /* NavigationToolTableItem.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = NavigationToolTableItem.swift; sourceTree = ""; }; 9127529398114DBEE725B2F92658F523 /* Pods-Sentinel_Tests-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-Sentinel_Tests-acknowledgements.plist"; sourceTree = ""; }; - 949F18898FCB7FECE333FDD3C228B214 /* Trigger.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Trigger.swift; path = Sentinel/Classes/Core/Trigger.swift; sourceTree = ""; }; + 92B6DE9216A96312D821F3ABB6299DDD /* Sentinel-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Sentinel-prefix.pch"; sourceTree = ""; }; 9569796757499011EED7D03B408B6F1A /* Pods-Sentinel_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-Sentinel_Tests.release.xcconfig"; sourceTree = ""; }; - 978E8A23DEF1A3F6C6BEEE01D608C19E /* ToolTableSection.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ToolTableSection.swift; path = Sentinel/Classes/Core/ToolTableSection.swift; sourceTree = ""; }; + 9C2CCAF9E916572214DCDFEFC3125CDB /* MailData.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MailData.swift; path = Sentinel/Classes/EmailSender/MailData.swift; sourceTree = ""; }; + 9CCA13B5FAB3C5EADEF6934E3AD1CAA8 /* PerformanceTool.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PerformanceTool.swift; sourceTree = ""; }; + 9D273BEDE8FE8146E0D63B5F50751B45 /* ToolTable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ToolTable.swift; path = Sentinel/Classes/Core/ToolTable.swift; sourceTree = ""; }; 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; - 9FFDDD993B6615D594BF12F7114C4114 /* PerformanceInfo.storyboard */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.storyboard; path = PerformanceInfo.storyboard; sourceTree = ""; }; - A264BA9D9B5D48D6568495F47A1A50DB /* Sentinel-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Sentinel-Info.plist"; sourceTree = ""; }; + A19215F357F44C188882A0B628DFCA0E /* PerformanceToolView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PerformanceToolView.swift; sourceTree = ""; }; + A2A80E9E861F3776D224E50A1ABA63E5 /* EmailSenderView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = EmailSenderView.swift; path = Sentinel/Classes/EmailSender/EmailSenderView.swift; sourceTree = ""; }; + A4E75CA6AD0FCBAB3A0A4F3CA7917A7D /* EmailSenderErrorView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = EmailSenderErrorView.swift; path = Sentinel/Classes/EmailSender/EmailSenderErrorView.swift; sourceTree = ""; }; A66CE977C2A4DD6409F650637CBD401F /* Pods-Sentinel_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-Sentinel_Example.debug.xcconfig"; sourceTree = ""; }; - A717C851D9595C11E64523BD7AC7A0A8 /* SystemInfoProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SystemInfoProvider.swift; sourceTree = ""; }; - A7B50E56512DF4FE3C282876E7C50698 /* MailData.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MailData.swift; path = Sentinel/Classes/EmailSender/MailData.swift; sourceTree = ""; }; + A7CBA79D3738D8B41902BC91E3AB5A0F /* ApplicationTool.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ApplicationTool.swift; sourceTree = ""; }; + AB6585D835E3A27D6CE8B68795FB56F9 /* NavigationToolTableView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = NavigationToolTableView.swift; sourceTree = ""; }; + ABBEDD505241543CED3BD523CC43C117 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; path = README.md; sourceTree = ""; }; B14684E93C90965E041B3092E4D0C959 /* Pods-Sentinel_Example-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-Sentinel_Example-frameworks.sh"; sourceTree = ""; }; B27D12816652F5CE8F68FECC2498878C /* Pods-Sentinel_Example.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-Sentinel_Example.modulemap"; sourceTree = ""; }; - B7552DF7B596D3A829EAABC526A54227 /* TextEditing.storyboard */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.storyboard; name = TextEditing.storyboard; path = Sentinel/Classes/TextEditing/TextEditing.storyboard; sourceTree = ""; }; - BB705774774B32DD7D277EBF7A196E6B /* CustomLocationProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CustomLocationProvider.swift; sourceTree = ""; }; + B58B735CF79ADAA5A96CF1B653989CD9 /* SentinelInternal.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SentinelInternal.swift; sourceTree = ""; }; + C138DA13E2E55FCFDEF83AC818C2F17D /* DeviceTool.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = DeviceTool.swift; sourceTree = ""; }; C3831A0EE07DA0231A8F1CB9F738F429 /* Pods-Sentinel_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-Sentinel_Tests.debug.xcconfig"; sourceTree = ""; }; C3969767F71788948A392AAED1152725 /* Pods-Sentinel_Tests-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-Sentinel_Tests-Info.plist"; sourceTree = ""; }; - C3B38B06CBB96138BCE3072322526D09 /* Tool.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Tool.swift; path = Sentinel/Classes/Core/Tool.swift; sourceTree = ""; }; - CC354FAD6744714772330A3CD30282B9 /* CustomLocation.storyboard */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.storyboard; name = CustomLocation.storyboard; path = Sentinel/Classes/CustomLocation/CustomLocation.storyboard; sourceTree = ""; }; - CD5A8166FE949AD66583F3DD9FC6D0F2 /* UIImage+Assets.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "UIImage+Assets.swift"; sourceTree = ""; }; - CD9EA9F4B4F1245665D161EC7498B2EE /* SentinelTab.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SentinelTab.swift; sourceTree = ""; }; - D1C36A135F7052FD39FCA12F876C31BA /* CLLocationManager+CustomLocation.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "CLLocationManager+CustomLocation.swift"; sourceTree = ""; }; - D245E0514AAC1A2B9A6D5EA2F383E90F /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.0.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; + C54A17AFD399512F10D64665A5602027 /* Sentinel.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Sentinel.swift; path = Sentinel/Classes/Core/Sentinel.swift; sourceTree = ""; }; + CD331ABA61F940F1A7687445F3280FC2 /* PerformanceInfoViewModel.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PerformanceInfoViewModel.swift; sourceTree = ""; }; + D0C0A487A2724010394018F49CEAADF2 /* ResourceBundle-Sentinel-Sentinel-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "ResourceBundle-Sentinel-Sentinel-Info.plist"; sourceTree = ""; }; D3908B2A61F0DD8BEE4E68CA7C472C70 /* Pods-Sentinel_Tests-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-Sentinel_Tests-umbrella.h"; sourceTree = ""; }; - D80B9F1DC5452E95CC3A5EF41AFCC825 /* Sentinel.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Sentinel.swift; path = Sentinel/Classes/Core/Sentinel.swift; sourceTree = ""; }; + D3C92B69AACF472AED12FCC6C7626F32 /* TextEditingToolViewModel.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TextEditingToolViewModel.swift; path = Sentinel/Classes/TextEditing/TextEditingToolViewModel.swift; sourceTree = ""; }; + D443B8AECAC90A02B03A2D3FF45C8C04 /* TextEditingTool.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TextEditingTool.swift; path = Sentinel/Classes/TextEditing/TextEditingTool.swift; sourceTree = ""; }; DA6F656ACB4F354E2B0B0D8829821734 /* Sentinel */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Sentinel; path = Sentinel.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - DED59AABC96E80C931B8AE9E62AB1C20 /* OptionSwitchItem.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = OptionSwitchItem.swift; sourceTree = ""; }; - E1DD3D88EAA5B0E19D76AB2DED4D42CB /* DetailToolTableCell.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; path = DetailToolTableCell.xib; sourceTree = ""; }; - EAB6F611E86A4758835A715E4B4184F6 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; - EB2EB2A430971FEF597833432027A012 /* UserDefaultsTool.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = UserDefaultsTool.swift; path = Sentinel/Classes/UserDefaults/UserDefaultsTool.swift; sourceTree = ""; }; + DD2143883292C0381027CEF446EE828C /* Sentinel.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Sentinel.release.xcconfig; sourceTree = ""; }; + E070A95877CAE8810B1AAB62E9C6441F /* UserDefaultsTool.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = UserDefaultsTool.swift; path = Sentinel/Classes/UserDefaults/UserDefaultsTool.swift; sourceTree = ""; }; + E16C994003CA13CF3B5989501EA81DF2 /* Sentinel-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Sentinel-Info.plist"; sourceTree = ""; }; + E488155D0FA8936E9AF44365697FDA15 /* SentinelTabBarView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SentinelTabBarView.swift; sourceTree = ""; }; + E88A032177B257E384D84618DC2AE6C4 /* Sentinel-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Sentinel-umbrella.h"; sourceTree = ""; }; + ECF4CA3AF5536D14B4E015504E7AEEC0 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS18.0.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; F0C518BCD254C6BED6EDFAA897D668F7 /* Pods-Sentinel_Example-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-Sentinel_Example-acknowledgements.plist"; sourceTree = ""; }; - F288809E670D73236EEDD32AF0385F52 /* UserDefaultsViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = UserDefaultsViewController.swift; path = Sentinel/Classes/UserDefaults/UserDefaultsViewController.swift; sourceTree = ""; }; - F433AE1221C0C34EF5CEFF4443D7CC0B /* DetailToolTableCell.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = DetailToolTableCell.swift; sourceTree = ""; }; F4A9B14258CE10FBC253BB5B34DAAE75 /* Pods-Sentinel_Example */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = "Pods-Sentinel_Example"; path = Pods_Sentinel_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - F58CF055598AA1A39265E42A84471325 /* OptionSwitchTableViewCell.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; path = OptionSwitchTableViewCell.xib; sourceTree = ""; }; - F630E66CB142E3122D77616F6F122EA0 /* PreferencesTool.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PreferencesTool.swift; sourceTree = ""; }; + F4E86D2AC79156431365732D986710D1 /* SourceScreenProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SourceScreenProvider.swift; path = Sentinel/Classes/Core/SourceScreenProvider.swift; sourceTree = ""; }; F6D219D153A366859D6A80F165E2D93E /* Pods-Sentinel_Example-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-Sentinel_Example-Info.plist"; sourceTree = ""; }; - F76E11D51FF8E682DBB040B410108B37 /* TextEditingViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = TextEditingViewController.swift; path = Sentinel/Classes/TextEditing/TextEditingViewController.swift; sourceTree = ""; }; - FB923BE4FFCCB97B4A21DBEDF1D7023A /* PerformanceInfoItem.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PerformanceInfoItem.swift; sourceTree = ""; }; FCD5716A347A57C5EB37EDE8EE5438D4 /* Pods-Sentinel_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-Sentinel_Example.release.xcconfig"; sourceTree = ""; }; - FCE2EB823A8255FB6CFE0569F6B4C56E /* NavigationToolTableCell.xib */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.xib; path = NavigationToolTableCell.xib; sourceTree = ""; }; - FDF5902098718AF762920A0440A13C16 /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; path = LICENSE; sourceTree = ""; }; + FFAB175E65C63BC1297D0D71DC550898 /* Trigger.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Trigger.swift; path = Sentinel/Classes/Core/Trigger.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ - 6A36C98EB471CED862E3A32FB79C16FD /* Frameworks */ = { + 225AADEE43E1365731CAC509CED2318A /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 5A3D76150331AA1378E52A7AD4469FE8 /* Foundation.framework in Frameworks */, + C85764914BD02C5A249F48249437A917 /* Foundation.framework in Frameworks */, + E2A6A1FA414E59E753D69A860B83EA2E /* UIKit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 732A12BB6ACE2EB6C7F2B95C39C96EA6 /* Frameworks */ = { + 35E463148D7B3E8093225C4962C0E56A /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - CF604FB79DBA85F3F42C17AD23F2709F /* Foundation.framework in Frameworks */, - A58B48B33225C272B33867336B62B548 /* UIKit.framework in Frameworks */, + 0207938303F4B09B48174B79120233BB /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - B4276B654DB7B973A0E992D1E1EB7E65 /* Frameworks */ = { + C8B2E7689D23E6F7B46FC1D15914E60C /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 907CB1DCF4723A718AA9F51BC8A60BC3 /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - CF54F4489E00F0D524EF3A45683F57B9 /* Frameworks */ = { + D0B54A79E3668D0DD6FAD2DF9D40A95B /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 1B388BC5A1412C7B5F27984B22D7A736 /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -237,43 +237,38 @@ 1628BF05B4CAFDCC3549A101F5A10A17 /* Frameworks */ = { isa = PBXGroup; children = ( - 59DA5C1F72E1D5BABC43EACBA672C3BA /* iOS */, + 1DE6440B6853131A80C53DDA34375AAB /* iOS */, ); name = Frameworks; sourceTree = ""; }; - 2256A00E7C65D53C0CB5C9A9ECF1FA03 /* CustomLocation */ = { + 1DE6440B6853131A80C53DDA34375AAB /* iOS */ = { isa = PBXGroup; children = ( - CC354FAD6744714772330A3CD30282B9 /* CustomLocation.storyboard */, - 2E4F99AD4F34FD69C5724E16746B4F8C /* CustomLocationTool.swift */, - 7D924EFA9A100F58C6EEC617AFA50215 /* CustomLocationViewController.swift */, - 9A0CB3C6C079750C02C11D7A526D1532 /* Internal */, + 8193349D819536E58C58A34C1B7DF545 /* Foundation.framework */, + ECF4CA3AF5536D14B4E015504E7AEEC0 /* UIKit.framework */, ); - name = CustomLocation; - sourceTree = ""; - }; - 29ED0C536ED9C040984499B45EB2DE30 /* PreferencesInfo */ = { - isa = PBXGroup; - children = ( - DED59AABC96E80C931B8AE9E62AB1C20 /* OptionSwitchItem.swift */, - 5D1FC1FB2CA22755615F62A37C6345BC /* OptionSwitchTableViewCell.swift */, - F58CF055598AA1A39265E42A84471325 /* OptionSwitchTableViewCell.xib */, - F630E66CB142E3122D77616F6F122EA0 /* PreferencesTool.swift */, - ); - name = PreferencesInfo; - path = Sentinel/Classes/Core/PreferencesInfo; + name = iOS; sourceTree = ""; }; - 2EF8BB810CF39F4BD3D9E6B3FE37DE28 /* Internal */ = { + 371991F8251D88900F67B4133B857FC9 /* Core */ = { isa = PBXGroup; children = ( - 5734767C80518F45C3780A076AE2C39B /* CPUInfoProvider.swift */, - 626662882F1871895D8C23A12020F397 /* MemoryInfoProvider.swift */, - A717C851D9595C11E64523BD7AC7A0A8 /* SystemInfoProvider.swift */, + 03247281412A1863370F775E18894969 /* CustomInfoTool.swift */, + 1E7B5AB3C25917BCB4F2BACF733CAAAA /* CustomInfoToolSection.swift */, + C54A17AFD399512F10D64665A5602027 /* Sentinel.swift */, + F4E86D2AC79156431365732D986710D1 /* SourceScreenProvider.swift */, + 68CB5732D85B08E7D9508D62FBCB5519 /* Tool.swift */, + 9D273BEDE8FE8146E0D63B5F50751B45 /* ToolTable.swift */, + 4918A781C339372C0BD8B0DA907E75F7 /* ToolTableItem.swift */, + 38E3B64F88AF6BCC39A62DF6BFA7EE27 /* ToolTableSection.swift */, + FFAB175E65C63BC1297D0D71DC550898 /* Trigger.swift */, + 9FFC4F1C0E7AAE70CC63B12A8F6462A8 /* Internal */, + 9398195837455B1ED7D9506FBA48C5DB /* PerformanceInfo */, + F0828A76E0F1931BDCBFB78D259A61B6 /* PreferencesInfo */, + D218884B31D6085351E5F2DB69D7399E /* ToolTableItems */, ); - name = Internal; - path = Internal; + name = Core; sourceTree = ""; }; 3B6DABB2E8626700366F9EF97244A591 /* Products */ = { @@ -287,98 +282,56 @@ name = Products; sourceTree = ""; }; - 3F5E9F47062A1944B879561B68DABB15 /* ToolTableItems */ = { + 40FC8E3C048E9F466AD7377241282B55 /* UserDefaults */ = { isa = PBXGroup; children = ( - F433AE1221C0C34EF5CEFF4443D7CC0B /* DetailToolTableCell.swift */, - E1DD3D88EAA5B0E19D76AB2DED4D42CB /* DetailToolTableCell.xib */, - 63C6F87374E5BE3824492E440C8C533B /* NavigationToolTableCell.swift */, - FCE2EB823A8255FB6CFE0569F6B4C56E /* NavigationToolTableCell.xib */, + E070A95877CAE8810B1AAB62E9C6441F /* UserDefaultsTool.swift */, + 569C8139885224C286C98ED89F816668 /* UserDefaultsToolView.swift */, + 14A443FD05C04A923E7DD27BB103BBE6 /* UserDefaultsToolViewModel.swift */, ); - name = ToolTableItems; - path = Sentinel/Classes/Core/ToolTableItems; - sourceTree = ""; - }; - 4611FEA8E947DCC8A84D2E0EEEDDD680 /* Assets */ = { - isa = PBXGroup; - children = ( - 04D293A77C27B984E3568BA4A74C9371 /* assets.xcassets */, - ); - name = Assets; - path = Sentinel/Assets; - sourceTree = ""; - }; - 523F538C95490357FD0D47BF6DE15EF5 /* TextEditing */ = { - isa = PBXGroup; - children = ( - B7552DF7B596D3A829EAABC526A54227 /* TextEditing.storyboard */, - 8E2C86790AF40AD69290F571F8770B26 /* TextEditingTool.swift */, - F76E11D51FF8E682DBB040B410108B37 /* TextEditingViewController.swift */, - ); - name = TextEditing; + name = UserDefaults; sourceTree = ""; }; - 59DA5C1F72E1D5BABC43EACBA672C3BA /* iOS */ = { + 51F41FD0E0ECCEBDEA5B6E66757D47F2 /* CustomLocation */ = { isa = PBXGroup; children = ( - EAB6F611E86A4758835A715E4B4184F6 /* Foundation.framework */, - D245E0514AAC1A2B9A6D5EA2F383E90F /* UIKit.framework */, + 66C655FB71F2226582E424553A4794A1 /* CustomLocation.storyboard */, + 07EAD7DA6327ACA542B0F40E2C959B33 /* CustomLocationTool.swift */, + 5EDF15A7C2FB8637F4490E961B3EA5B2 /* CustomLocationView.swift */, + 6D9090F7B3CD6C372EC6FA3C5684B09D /* CustomLocationViewController.swift */, + 794F3CB09C0A91515DB0B406677897BE /* Internal */, ); - name = iOS; + name = CustomLocation; sourceTree = ""; }; - 731F199886C41AA2F363F168A765CAEC /* Core */ = { + 7296C4078B8A43C3865F88ECBE3FFCE1 /* SupportingFiles */ = { isa = PBXGroup; children = ( - 71F0DCC041ECAD8156E23F52ADBEDA3E /* CustomInfoTool.swift */, - D80B9F1DC5452E95CC3A5EF41AFCC825 /* Sentinel.swift */, - 78E094F5D9416F260775BD27751BF17C /* SourceScreenProvider.swift */, - C3B38B06CBB96138BCE3072322526D09 /* Tool.swift */, - 4B89409BDEAD1944C09A82B1D064EFC0 /* ToolTable.swift */, - 49579ACDDB3732224639307E23FF67C1 /* ToolTableItem.swift */, - 978E8A23DEF1A3F6C6BEEE01D608C19E /* ToolTableSection.swift */, - 949F18898FCB7FECE333FDD3C228B214 /* Trigger.swift */, - 399271B986BF07F35759398166218340 /* UIImage+Bundle.swift */, - 7ECBE6B9453803658EC8887A4BD2A02F /* Internal */, - E28A24EB1446DDA19003FA33AD60F186 /* PerformanceInfo */, - 29ED0C536ED9C040984499B45EB2DE30 /* PreferencesInfo */, - 3F5E9F47062A1944B879561B68DABB15 /* ToolTableItems */, + 4CAF6C687E6F8E3372704DA5E71B53E3 /* PrivacyInfo.xcprivacy */, ); - name = Core; + name = SupportingFiles; + path = Sentinel/SupportingFiles; sourceTree = ""; }; - 7ECBE6B9453803658EC8887A4BD2A02F /* Internal */ = { + 794F3CB09C0A91515DB0B406677897BE /* Internal */ = { isa = PBXGroup; children = ( - 47176B1B2EB5521860BD50A4E66CDD41 /* ApplicationTool.swift */, - 437E26734FC551BC25697D55C7692056 /* DeviceTool.swift */, - 426DE0FE6910431B22E09536514A584B /* Sentinel.storyboard */, - 25F03579FCC17D7E4F4017B7896B9101 /* SentinelInternal.swift */, - CD9EA9F4B4F1245665D161EC7498B2EE /* SentinelTab.swift */, - 8ED87451C325BDBB98187B49F9532846 /* SentinelTabBarController.swift */, - 1E76AD572469569325561B1BFB22997C /* SentinelTabItem.swift */, - 4B84A88183D8C8478D8897E03941CE3A /* SentinelTableViewController.swift */, - 90C5F5B38BB1B4151E6BFDAFC77D4142 /* SentinelUIKitExtensions.swift */, - CD5A8166FE949AD66583F3DD9FC6D0F2 /* UIImage+Assets.swift */, + 7AABF748D2535AD78BE07F05CEA6E5A8 /* CLLocationManager+CustomLocation.swift */, + 09D3F046CEF486E0A9A4DE8922F35BF5 /* CustomLocationProvider.swift */, ); name = Internal; - path = Sentinel/Classes/Core/Internal; + path = Sentinel/Classes/CustomLocation/Internal; sourceTree = ""; }; - 7F6C9DEBCC0734B335910A52B9999058 /* Support Files */ = { + 8DF3DA28BB759D6C1FF7231E5BC39293 /* EmailSender */ = { isa = PBXGroup; children = ( - 74FF88B4F7AF82EB7C6152CF78BAF6E0 /* ResourceBundle-Sentinel-Sentinel-Info.plist */, - 72216E79692E18558D345C8D92606137 /* Sentinel.modulemap */, - 0123519EBBADBDD3CA020E20D74CC504 /* Sentinel-dummy.m */, - A264BA9D9B5D48D6568495F47A1A50DB /* Sentinel-Info.plist */, - 788EE74F754CE9BCC6905FF3EF4D4D5E /* Sentinel-prefix.pch */, - 4452D60511129A8FAEA7813B6E7385A1 /* Sentinel-umbrella.h */, - 85BC350766D86BCFF06AFDCA2F596D1A /* Sentinel.debug.xcconfig */, - 2E98A32570B59CCDC9F10FE0827754A8 /* Sentinel.release.xcconfig */, + A4E75CA6AD0FCBAB3A0A4F3CA7917A7D /* EmailSenderErrorView.swift */, + 764239ED7CC3E8BC9586A187578ADD8F /* EmailSenderTool.swift */, + A2A80E9E861F3776D224E50A1ABA63E5 /* EmailSenderView.swift */, + 9C2CCAF9E916572214DCDFEFC3125CDB /* MailData.swift */, ); - name = "Support Files"; - path = "Example/Pods/Target Support Files/Sentinel"; + name = EmailSender; sourceTree = ""; }; 8F691C6054F4434031502E1A992CC026 /* Pods-Sentinel_Example */ = { @@ -398,59 +351,70 @@ path = "Target Support Files/Pods-Sentinel_Example"; sourceTree = ""; }; - 975898DA80E84FA0358D24F8DA77C864 /* SupportingFiles */ = { + 9398195837455B1ED7D9506FBA48C5DB /* PerformanceInfo */ = { isa = PBXGroup; children = ( - 105731A6C88AA834631D0ACC8DB9ECB5 /* PrivacyInfo.xcprivacy */, + 9CCA13B5FAB3C5EADEF6934E3AD1CAA8 /* PerformanceTool.swift */, + BC4793F55562A32E3E29B6D0A206C582 /* Internal */, + A5E0B9B720CDCF5D6165D1E043994092 /* Items */, ); - name = SupportingFiles; - path = Sentinel/SupportingFiles; + name = PerformanceInfo; + path = Sentinel/Classes/Core/PerformanceInfo; sourceTree = ""; }; - 9A0CB3C6C079750C02C11D7A526D1532 /* Internal */ = { + 9FFC4F1C0E7AAE70CC63B12A8F6462A8 /* Internal */ = { isa = PBXGroup; children = ( - D1C36A135F7052FD39FCA12F876C31BA /* CLLocationManager+CustomLocation.swift */, - BB705774774B32DD7D277EBF7A196E6B /* CustomLocationProvider.swift */, + A7CBA79D3738D8B41902BC91E3AB5A0F /* ApplicationTool.swift */, + C138DA13E2E55FCFDEF83AC818C2F17D /* DeviceTool.swift */, + 6B58D5D7B6470E1D7AF0641BD1C6375E /* Image+Assets.swift */, + B58B735CF79ADAA5A96CF1B653989CD9 /* SentinelInternal.swift */, + 7A385843ED2D09D955AA16284F2521C8 /* SentinelListView.swift */, + 4492E38B85A8FB5EF61F368982D24225 /* SentinelTab.swift */, + E488155D0FA8936E9AF44365697FDA15 /* SentinelTabBarView.swift */, + 83EA438F56AF149B25540E9CDC01A9D3 /* SentinelTabItem.swift */, + 6BFCC6BF0BC1D639B210FB88B2F626EC /* SentinelUIKitExtensions.swift */, ); name = Internal; - path = Sentinel/Classes/CustomLocation/Internal; + path = Sentinel/Classes/Core/Internal; sourceTree = ""; }; - 9E8363BB2D4962FED58B9BC9B3FB4FBA /* EmailSender */ = { + A2B319D55D6989C411AD5862AB07914D /* Pod */ = { isa = PBXGroup; children = ( - 75F4AA20F4520ABF3CABE32553A07230 /* EmailSenderTool.swift */, - A7B50E56512DF4FE3C282876E7C50698 /* MailData.swift */, + 150A2CBF0BFC9AAA5B3971B86BDA8C1C /* LICENSE */, + ABBEDD505241543CED3BD523CC43C117 /* README.md */, + 6D1D7D0DE1BCC5E4BCE4831433CFB933 /* Sentinel.podspec */, ); - name = EmailSender; + name = Pod; sourceTree = ""; }; - B25CAE0BFCB1D4287EBDEC4F19912C11 /* Items */ = { + A5E0B9B720CDCF5D6165D1E043994092 /* Items */ = { isa = PBXGroup; children = ( - FB923BE4FFCCB97B4A21DBEDF1D7023A /* PerformanceInfoItem.swift */, - 88108BDB5A44D116EDCBBE34998E349C /* PerformanceInfoTableViewCell.swift */, - 325939692C21D25F13B44608763F7A58 /* PerformanceInfoTableViewCell.xib */, + 06FFE2BA37A9DEDCAF6B2D40DF1AA835 /* PerformanceInfoItem.swift */, + CD331ABA61F940F1A7687445F3280FC2 /* PerformanceInfoViewModel.swift */, + A19215F357F44C188882A0B628DFCA0E /* PerformanceToolView.swift */, ); name = Items; path = Items; sourceTree = ""; }; - B92553240CB6C7A3CCDB6DE90D05FC38 /* UserDefaults */ = { + BC4793F55562A32E3E29B6D0A206C582 /* Internal */ = { isa = PBXGroup; children = ( - 418F81F9372721938AFA1EF3CF963146 /* UserDefaults.storyboard */, - EB2EB2A430971FEF597833432027A012 /* UserDefaultsTool.swift */, - F288809E670D73236EEDD32AF0385F52 /* UserDefaultsViewController.swift */, + 4F979923D85629761105B642B6C011BC /* CPUInfoProvider.swift */, + 7847C54724D878771D2E00452D513095 /* MemoryInfoProvider.swift */, + 289BAB60952AADB226FF966E863DA302 /* SystemInfoProvider.swift */, ); - name = UserDefaults; + name = Internal; + path = Internal; sourceTree = ""; }; C335E5C2868F0138935753918A40894D /* Development Pods */ = { isa = PBXGroup; children = ( - D8A89B16AD8B34BC2E224A754741F862 /* Sentinel */, + EB51F8D053D8DE1161A307A9FA1F47D9 /* Sentinel */, ); name = "Development Pods"; sourceTree = ""; @@ -466,21 +430,41 @@ ); sourceTree = ""; }; - D8A89B16AD8B34BC2E224A754741F862 /* Sentinel */ = { + D218884B31D6085351E5F2DB69D7399E /* ToolTableItems */ = { isa = PBXGroup; children = ( - 4611FEA8E947DCC8A84D2E0EEEDDD680 /* Assets */, - 731F199886C41AA2F363F168A765CAEC /* Core */, - 2256A00E7C65D53C0CB5C9A9ECF1FA03 /* CustomLocation */, - 9E8363BB2D4962FED58B9BC9B3FB4FBA /* EmailSender */, - E9ECEE0E3754E45C075FE6E83CAF8169 /* Pod */, - 7F6C9DEBCC0734B335910A52B9999058 /* Support Files */, - 975898DA80E84FA0358D24F8DA77C864 /* SupportingFiles */, - 523F538C95490357FD0D47BF6DE15EF5 /* TextEditing */, - B92553240CB6C7A3CCDB6DE90D05FC38 /* UserDefaults */, + 244C746A4F5BA5CA9C75CB98A95427BC /* CustomToolTableItem.swift */, + 8D60229C8B8E9E90442D225B853A728D /* NavigationToolTableItem.swift */, + AB6585D835E3A27D6CE8B68795FB56F9 /* NavigationToolTableView.swift */, + 2C343D531FDB3EDD51527E0E3451A06C /* TitleValueView.swift */, ); - name = Sentinel; - path = ../..; + name = ToolTableItems; + path = Sentinel/Classes/Core/ToolTableItems; + sourceTree = ""; + }; + D44022199ADF300DA716109FF6814928 /* Assets */ = { + isa = PBXGroup; + children = ( + 65DC4A4FC2681CFF1F2FEA7086BBE6C9 /* assets.xcassets */, + ); + name = Assets; + path = Sentinel/Assets; + sourceTree = ""; + }; + DA38B96AECB8E9102D384FFCB4FF5D03 /* Support Files */ = { + isa = PBXGroup; + children = ( + D0C0A487A2724010394018F49CEAADF2 /* ResourceBundle-Sentinel-Sentinel-Info.plist */, + 31F545C3F7C7B36DE7382B13328068B8 /* Sentinel.modulemap */, + 054D3991200D83DFD5D340CF70BDE5CB /* Sentinel-dummy.m */, + E16C994003CA13CF3B5989501EA81DF2 /* Sentinel-Info.plist */, + 92B6DE9216A96312D821F3ABB6299DDD /* Sentinel-prefix.pch */, + E88A032177B257E384D84618DC2AE6C4 /* Sentinel-umbrella.h */, + 0FD645F8FDA590A1283B3F4FE9543FAC /* Sentinel.debug.xcconfig */, + DD2143883292C0381027CEF446EE828C /* Sentinel.release.xcconfig */, + ); + name = "Support Files"; + path = "Example/Pods/Target Support Files/Sentinel"; sourceTree = ""; }; E1BF3393363293FA2C5AF0C96D0A5677 /* Targets Support Files */ = { @@ -492,52 +476,68 @@ name = "Targets Support Files"; sourceTree = ""; }; - E28A24EB1446DDA19003FA33AD60F186 /* PerformanceInfo */ = { + EB51F8D053D8DE1161A307A9FA1F47D9 /* Sentinel */ = { isa = PBXGroup; children = ( - 9FFDDD993B6615D594BF12F7114C4114 /* PerformanceInfo.storyboard */, - 4C4A505FC7768CC6429D806DE09992FF /* PerformanceTool.swift */, - 2EF8BB810CF39F4BD3D9E6B3FE37DE28 /* Internal */, - B25CAE0BFCB1D4287EBDEC4F19912C11 /* Items */, + D44022199ADF300DA716109FF6814928 /* Assets */, + 371991F8251D88900F67B4133B857FC9 /* Core */, + 51F41FD0E0ECCEBDEA5B6E66757D47F2 /* CustomLocation */, + 8DF3DA28BB759D6C1FF7231E5BC39293 /* EmailSender */, + A2B319D55D6989C411AD5862AB07914D /* Pod */, + DA38B96AECB8E9102D384FFCB4FF5D03 /* Support Files */, + 7296C4078B8A43C3865F88ECBE3FFCE1 /* SupportingFiles */, + F0B9AAD6A9ABD69697E7E2DAC3090377 /* TextEditing */, + 40FC8E3C048E9F466AD7377241282B55 /* UserDefaults */, ); - name = PerformanceInfo; - path = Sentinel/Classes/Core/PerformanceInfo; + name = Sentinel; + path = ../..; sourceTree = ""; }; - E9ECEE0E3754E45C075FE6E83CAF8169 /* Pod */ = { + F0828A76E0F1931BDCBFB78D259A61B6 /* PreferencesInfo */ = { isa = PBXGroup; children = ( - FDF5902098718AF762920A0440A13C16 /* LICENSE */, - 5CABB67CC6EA83AA9F45A7E22F03BC5E /* README.md */, - 84B7ED3A06CE15CCA34FBC84F3157D3C /* Sentinel.podspec */, + 87300A646F557036DD842F90C6C89414 /* OptionSwitchItem.swift */, + 0AEA4E34B70D9646CB4D747D9FEF9384 /* OptionSwitchView.swift */, + 4BDE761CF048886F8B8A0D6E5FFF44F4 /* PreferencesTool.swift */, ); - name = Pod; + name = PreferencesInfo; + path = Sentinel/Classes/Core/PreferencesInfo; + sourceTree = ""; + }; + F0B9AAD6A9ABD69697E7E2DAC3090377 /* TextEditing */ = { + isa = PBXGroup; + children = ( + D443B8AECAC90A02B03A2D3FF45C8C04 /* TextEditingTool.swift */, + 361FC3862B02304CC2280B0B71E2BC46 /* TextEditingToolView.swift */, + D3C92B69AACF472AED12FCC6C7626F32 /* TextEditingToolViewModel.swift */, + ); + name = TextEditing; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ - 3B19E1D417C8C90527124E8B4033661B /* Headers */ = { + 2440D773E8F682B608D8A4DBEFE07BA6 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 0C4019269D306392E708744DD4AC7DBA /* Sentinel-umbrella.h in Headers */, + 1CD052257A420FAAC70A4CAE5342EA11 /* Pods-Sentinel_Tests-umbrella.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; - 3EC64EA64D8E33FCF69E2B74755F1093 /* Headers */ = { + 7AF71DF48D821252373AD51029368341 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - D45E6493FD41DD7AFDA785993EBDDA4C /* Pods-Sentinel_Tests-umbrella.h in Headers */, + 4E61D90AFD03B7916676214441139DB1 /* Sentinel-umbrella.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; - B88E538BF3CE3AA1E440DF87C98A9A82 /* Headers */ = { + B2A9AE79CC1A516C1D961C3EE1D21B23 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - B23641FF4898CF2A0121F8859419A180 /* Pods-Sentinel_Example-umbrella.h in Headers */, + ECBAA3B892D2D58FFAEB362EE6C4F23E /* Pods-Sentinel_Example-umbrella.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -546,17 +546,17 @@ /* Begin PBXNativeTarget section */ 254C1FBF05728FD8BE3AFCBC3F313646 /* Pods-Sentinel_Example */ = { isa = PBXNativeTarget; - buildConfigurationList = 97CECA2C7429160E40B79AEC0BE6A8F4 /* Build configuration list for PBXNativeTarget "Pods-Sentinel_Example" */; + buildConfigurationList = 9CA9FF59475346B1062C7120ABD2EE5B /* Build configuration list for PBXNativeTarget "Pods-Sentinel_Example" */; buildPhases = ( - B88E538BF3CE3AA1E440DF87C98A9A82 /* Headers */, - 24A49347F70E68823834794F4EF96E05 /* Sources */, - B4276B654DB7B973A0E992D1E1EB7E65 /* Frameworks */, - 9C3D8D7A448B8CD972F380C3EFED34BB /* Resources */, + B2A9AE79CC1A516C1D961C3EE1D21B23 /* Headers */, + 2746ED3EC2F620374AA0F466FB97B506 /* Sources */, + D0B54A79E3668D0DD6FAD2DF9D40A95B /* Frameworks */, + 9BB69AC09292F2FD038F82019E068227 /* Resources */, ); buildRules = ( ); dependencies = ( - 4402548340139BB2D705578AF2E7B911 /* PBXTargetDependency */, + 6324315EE57FC54332427A7469FB3059 /* PBXTargetDependency */, ); name = "Pods-Sentinel_Example"; productName = Pods_Sentinel_Example; @@ -565,17 +565,17 @@ }; 456B9E0EFF5B252F2D01BD09BEE7094C /* Pods-Sentinel_Tests */ = { isa = PBXNativeTarget; - buildConfigurationList = 974D76B44E958BAAE90264833D7E7D59 /* Build configuration list for PBXNativeTarget "Pods-Sentinel_Tests" */; + buildConfigurationList = 90A20A902093842EAA6A5881461A2736 /* Build configuration list for PBXNativeTarget "Pods-Sentinel_Tests" */; buildPhases = ( - 3EC64EA64D8E33FCF69E2B74755F1093 /* Headers */, - 79692FDF8C2D1BD09C5CBD4016EC0191 /* Sources */, - 6A36C98EB471CED862E3A32FB79C16FD /* Frameworks */, - 2910D6CC878E5FFB93FDAA0AF21A8630 /* Resources */, + 2440D773E8F682B608D8A4DBEFE07BA6 /* Headers */, + ABE7EBBC64A9E0D16DD5C7656B5DEDC1 /* Sources */, + 35E463148D7B3E8093225C4962C0E56A /* Frameworks */, + 95451725A399C85BBB01541C60E89EA5 /* Resources */, ); buildRules = ( ); dependencies = ( - 42F9DB61D7A4031107EEB1AC26B6ABE6 /* PBXTargetDependency */, + CC20807E7AEF5F806A155DED7A2894E7 /* PBXTargetDependency */, ); name = "Pods-Sentinel_Tests"; productName = Pods_Sentinel_Tests; @@ -584,11 +584,11 @@ }; 8ACB6013C7A59AFAD22BD744A5CEE9FE /* Sentinel-Sentinel */ = { isa = PBXNativeTarget; - buildConfigurationList = DF3C6469DC778636EB72AFD53909FF79 /* Build configuration list for PBXNativeTarget "Sentinel-Sentinel" */; + buildConfigurationList = C7D7F55693077F87F0DE4D7CD917EAD0 /* Build configuration list for PBXNativeTarget "Sentinel-Sentinel" */; buildPhases = ( - CDE71B9F09D69A8A12212240DFC34D77 /* Sources */, - CF54F4489E00F0D524EF3A45683F57B9 /* Frameworks */, - 2F9C06F455510D24312436A0DDA0A3E8 /* Resources */, + 6385A91D592F3FF22481AAAE942A69E5 /* Sources */, + C8B2E7689D23E6F7B46FC1D15914E60C /* Frameworks */, + 53688DB5DA246D29B8CD5F65CC23C0D1 /* Resources */, ); buildRules = ( ); @@ -601,17 +601,17 @@ }; F402433F0FA4E4D3D7AF80AFBDD40215 /* Sentinel */ = { isa = PBXNativeTarget; - buildConfigurationList = CB98FC08DF1B1DB646351C60E8BFE554 /* Build configuration list for PBXNativeTarget "Sentinel" */; + buildConfigurationList = 7EEDB746BA035EDA0A9605558B36D651 /* Build configuration list for PBXNativeTarget "Sentinel" */; buildPhases = ( - 3B19E1D417C8C90527124E8B4033661B /* Headers */, - 539612E9BBF0A4C91AAD8496E94C67FE /* Sources */, - 732A12BB6ACE2EB6C7F2B95C39C96EA6 /* Frameworks */, - 8C7019DAA49E3D53047C9328290EF4FB /* Resources */, + 7AF71DF48D821252373AD51029368341 /* Headers */, + FD1761CF2B9927631BD9B9F9B5784683 /* Sources */, + 225AADEE43E1365731CAC509CED2318A /* Frameworks */, + 15C6CE3FD4A4943887272691071FE2E3 /* Resources */, ); buildRules = ( ); dependencies = ( - 714723919996FC0F6746EB12199ACEBC /* PBXTargetDependency */, + 3A76A313C742A25AE157B1A6E0530231 /* PBXTargetDependency */, ); name = Sentinel; productName = Sentinel; @@ -624,8 +624,8 @@ BFDFE7DC352907FC980B868725387E98 /* Project object */ = { isa = PBXProject; attributes = { - LastSwiftUpdateCheck = 1500; - LastUpgradeCheck = 1500; + LastSwiftUpdateCheck = 1600; + LastUpgradeCheck = 1600; }; buildConfigurationList = 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */; compatibilityVersion = "Xcode 3.2"; @@ -637,6 +637,7 @@ ); mainGroup = CF1408CF629C7361332E53B88F7BD30C; minimizedProjectReferenceProxies = 0; + preferredProjectObjectVersion = 77; productRefGroup = 3B6DABB2E8626700366F9EF97244A591 /* Products */; projectDirPath = ""; projectRoot = ""; @@ -650,31 +651,31 @@ /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ - 2910D6CC878E5FFB93FDAA0AF21A8630 /* Resources */ = { + 15C6CE3FD4A4943887272691071FE2E3 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + AE156CD0EE4AEC4C92531B82B3351068 /* Sentinel-Sentinel in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 2F9C06F455510D24312436A0DDA0A3E8 /* Resources */ = { + 53688DB5DA246D29B8CD5F65CC23C0D1 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 277EEF184CAC2B7C848CE24B26536103 /* assets.xcassets in Resources */, - EA97067A7F7FD0E23CA2FB782957D469 /* PrivacyInfo.xcprivacy in Resources */, + CFB1E9415B69536DB199E796B34E491D /* assets.xcassets in Resources */, + 4CB1A01069A3B23E3A80600EB12B3FBB /* PrivacyInfo.xcprivacy in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 8C7019DAA49E3D53047C9328290EF4FB /* Resources */ = { + 95451725A399C85BBB01541C60E89EA5 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - C83AA04D10AEBD6EB6B2EE8BB8E27C04 /* Sentinel-Sentinel in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 9C3D8D7A448B8CD972F380C3EFED34BB /* Resources */ = { + 9BB69AC09292F2FD038F82019E068227 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( @@ -684,112 +685,178 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ - 24A49347F70E68823834794F4EF96E05 /* Sources */ = { + 2746ED3EC2F620374AA0F466FB97B506 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 46B86E290AEED299FD5577116F78BB3E /* Pods-Sentinel_Example-dummy.m in Sources */, + 24F6FE7875CC475211B856A0A1D8D5B0 /* Pods-Sentinel_Example-dummy.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 539612E9BBF0A4C91AAD8496E94C67FE /* Sources */ = { + 6385A91D592F3FF22481AAAE942A69E5 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 1EF7D76198050F8C58A7C42A07864F71 /* ApplicationTool.swift in Sources */, - 2575D52D68BFB3AE7AEF1D85A37D3730 /* CLLocationManager+CustomLocation.swift in Sources */, - 33101FBA9CD6C060453E6D48A11B8EAA /* CPUInfoProvider.swift in Sources */, - 0E0D681E9442C38F33E1A92C5B047F78 /* CustomInfoTool.swift in Sources */, - FBF78676F8A7D41539A080DBEC595918 /* CustomLocation.storyboard in Sources */, - BC6D41D6C5B4A4D3FAD732CCD9A66049 /* CustomLocationProvider.swift in Sources */, - 26319041AE5F57B4B76D003DDB5DBB0B /* CustomLocationTool.swift in Sources */, - 1555846FBCFD3F3AD82809D1236251BF /* CustomLocationViewController.swift in Sources */, - 8DA27679E2A522DC10EF3EFFA4F6BED7 /* DetailToolTableCell.swift in Sources */, - 4B881ACC3EB405B590A7DE9E9F0B5AD3 /* DetailToolTableCell.xib in Sources */, - E93B07FAC749E40D2F350B585A7DB749 /* DeviceTool.swift in Sources */, - 10FB0CB37C8E8DB63D5115B0D6104A34 /* EmailSenderTool.swift in Sources */, - DCF557C34BCA2C9CBC3C7187B007F3E3 /* MailData.swift in Sources */, - 1AA43EFE0B951436A9D995439FC3955C /* MemoryInfoProvider.swift in Sources */, - 90B4CE627F55D9D5555D245F7F7A871E /* NavigationToolTableCell.swift in Sources */, - 1224D96255A69B9E380683BEF3920004 /* NavigationToolTableCell.xib in Sources */, - A1DF74C8E2640A0A223BAC397CB1B798 /* OptionSwitchItem.swift in Sources */, - 05AB55A6BC62A0A338BEABBED4CDE6C0 /* OptionSwitchTableViewCell.swift in Sources */, - 899ECC402431BD12B73393CB3673E7BF /* OptionSwitchTableViewCell.xib in Sources */, - A25FEC28C4FFF5686CE137A033571B89 /* PerformanceInfo.storyboard in Sources */, - A73E0EA9DB84A1FDF0317CD4468D6029 /* PerformanceInfoItem.swift in Sources */, - E0CB49456E0712E2D62904CB05363E69 /* PerformanceInfoTableViewCell.swift in Sources */, - E4CA7F6F3C0223AC1AF6617FAD2A031A /* PerformanceInfoTableViewCell.xib in Sources */, - 835A1CC875C3952CC27F028417373699 /* PerformanceTool.swift in Sources */, - EF6123DF138FE896691229B582EEDA42 /* PreferencesTool.swift in Sources */, - DD9E8478B694ABBF79A137993AD037A3 /* Sentinel.storyboard in Sources */, - 0B60642A872051D58C85906229FBFEDA /* Sentinel.swift in Sources */, - C9652C920E0F83FA431A8EDBCBEE938A /* Sentinel-dummy.m in Sources */, - 9F502C0688F4D9325AC72B1AD094FF9F /* SentinelInternal.swift in Sources */, - EEA0E6F5B41AE5F1D726554F8ED88EC0 /* SentinelTab.swift in Sources */, - 340E47C4CE7263D01EE8CCFF18D52B4B /* SentinelTabBarController.swift in Sources */, - 732D182A7621FC474379DDF296CFB2D7 /* SentinelTabItem.swift in Sources */, - 473657D546CDAF92D6F9C0E792B19B60 /* SentinelTableViewController.swift in Sources */, - EAD8A81B57AB96EE157D6A5B8D931DC8 /* SentinelUIKitExtensions.swift in Sources */, - 24C147D76A4A1B06597D62F830731977 /* SourceScreenProvider.swift in Sources */, - E7256F07482ED9F92DCB954F895F0065 /* SystemInfoProvider.swift in Sources */, - E854580C1249D2DDBBE456850EE3DA11 /* TextEditing.storyboard in Sources */, - B25EC552C3037243F505D4B95C7AFABB /* TextEditingTool.swift in Sources */, - 7C976162D8AA55F0635D9B6A9BF4DD38 /* TextEditingViewController.swift in Sources */, - 2B85A5D064E16AC415C4FDB5D840E347 /* Tool.swift in Sources */, - E7B4EB42519269AF1BE2B291B15C926D /* ToolTable.swift in Sources */, - DA77B284C9752002B98FC95FF33BA58B /* ToolTableItem.swift in Sources */, - 11466F4958009FACA62F4758326E0664 /* ToolTableSection.swift in Sources */, - DEE491BE61118EF69DE9BFFC95278521 /* Trigger.swift in Sources */, - AD3DEA85B614790B8CD5470E3093BB79 /* UIImage+Assets.swift in Sources */, - 734DAA2EF065C3C87EA7D3E01D46203E /* UIImage+Bundle.swift in Sources */, - 6854D870A57A83463A08B042B95B8EB0 /* UserDefaults.storyboard in Sources */, - 66FB1A417AF801C9D2D64C4606310135 /* UserDefaultsTool.swift in Sources */, - 3BDC3EB6545B60F23307B52624F4CADA /* UserDefaultsViewController.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 79692FDF8C2D1BD09C5CBD4016EC0191 /* Sources */ = { + ABE7EBBC64A9E0D16DD5C7656B5DEDC1 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - B40BD9D6EA4805C9A0E676F6E9B2A48C /* Pods-Sentinel_Tests-dummy.m in Sources */, + 5A210F0D0137B7C094242C17CC0B4EBF /* Pods-Sentinel_Tests-dummy.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - CDE71B9F09D69A8A12212240DFC34D77 /* Sources */ = { + FD1761CF2B9927631BD9B9F9B5784683 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + DEC865A4A1FC21892EF1C737F8575226 /* ApplicationTool.swift in Sources */, + CBBBCAFCC8D62CEB7AC6F4602361802A /* CLLocationManager+CustomLocation.swift in Sources */, + D87E6290718F92138B492630F2A7B85E /* CPUInfoProvider.swift in Sources */, + A206332F26FFF44AE37677FBA5BEEAC3 /* CustomInfoTool.swift in Sources */, + 92D0995AFE329EACAAA7DA66B90CB864 /* CustomInfoToolSection.swift in Sources */, + D77CFA9389950CECA6909F309249B60B /* CustomLocation.storyboard in Sources */, + B62DE8EA56AAF47E58C04FDEB90492E0 /* CustomLocationProvider.swift in Sources */, + 6B90FB8143A54B61700E4B1CB4FC6485 /* CustomLocationTool.swift in Sources */, + 023262667F2527137B5AC417825F2B0D /* CustomLocationView.swift in Sources */, + 4956CDA9E114EDB786824DFCB5C2A41E /* CustomLocationViewController.swift in Sources */, + 2BD27E9BB4961B0DBD1475A60E64C1B7 /* CustomToolTableItem.swift in Sources */, + 5D215B249442FC8B3483C15AD67CB1A7 /* DeviceTool.swift in Sources */, + F5FDC90AA853CA0C39F4F7741666A609 /* EmailSenderErrorView.swift in Sources */, + 0D9C654F905AE538990D61D3B7E77BC9 /* EmailSenderTool.swift in Sources */, + AA1B2C49B57DD9BF66F794CA80881C6E /* EmailSenderView.swift in Sources */, + 43E4F58BF88D8C0E5578DFA7A48E4B51 /* Image+Assets.swift in Sources */, + C356D6D05DB281868BBCA398FDD2B5A8 /* MailData.swift in Sources */, + 76BF7AF791BECF7848B65B803897BF6E /* MemoryInfoProvider.swift in Sources */, + EA52ABDDEF8CC52BA606701ED27937B8 /* NavigationToolTableItem.swift in Sources */, + 53D5078E20CAE5C1922B65E43BF9310F /* NavigationToolTableView.swift in Sources */, + 8BB2E721FB6763E941FB63DF56EEF73F /* OptionSwitchItem.swift in Sources */, + 2B3A705A66176EF8795CFA1F0574F178 /* OptionSwitchView.swift in Sources */, + 5C0DA88EB8AC1A0E427C846AA234FAA5 /* PerformanceInfoItem.swift in Sources */, + 7A0DD883715A97DFC9754E5B149DC937 /* PerformanceInfoViewModel.swift in Sources */, + D746D5ECC29E62D6B222764CE3091CED /* PerformanceTool.swift in Sources */, + 3E20C49FAD685F1F6B45D0A72754354C /* PerformanceToolView.swift in Sources */, + 207A5BAFEA9939902095DE15C51F92B8 /* PreferencesTool.swift in Sources */, + 2F6A95F16D7A3CE719475E09B635D3CB /* Sentinel.swift in Sources */, + 005473C0AFEB79655BF6E4F4B400F545 /* Sentinel-dummy.m in Sources */, + A6E75D64743FF38C7529C1046D61D6B1 /* SentinelInternal.swift in Sources */, + DF42907C03E108163DE9C6C72127D667 /* SentinelListView.swift in Sources */, + 60CE0F964941ED5E766083354AFEAAEB /* SentinelTab.swift in Sources */, + D2B6AB8B102E1600802DA49CD8097BD9 /* SentinelTabBarView.swift in Sources */, + 059F787A59D49D4E9A81C3EA15F6E86A /* SentinelTabItem.swift in Sources */, + 6178879BA6BAABF7C9980D93F2A491F9 /* SentinelUIKitExtensions.swift in Sources */, + D63812169E8A5CBB9D562EB31DC49AA7 /* SourceScreenProvider.swift in Sources */, + 2F69E19201D8DF1597AF96A4BE46C780 /* SystemInfoProvider.swift in Sources */, + 73C72D35F3A1F77EA1D01AF0A786CC96 /* TextEditingTool.swift in Sources */, + 43CC1082F5FA0C1CAA5A2328AB3F9EC0 /* TextEditingToolView.swift in Sources */, + E049996F2D77232D5EF9C8FE325C4FC9 /* TextEditingToolViewModel.swift in Sources */, + 9FAC0C47ECDF4024148974DD821CA373 /* TitleValueView.swift in Sources */, + 55B6B0615B9CCC9CD56AE81BC34198F8 /* Tool.swift in Sources */, + 7F7EE868B8CAC146975F08D521B24A98 /* ToolTable.swift in Sources */, + 987236C1287444991C8016F0EBAEA1F5 /* ToolTableItem.swift in Sources */, + D3B12C93E7B782E316F07D4CEBFF6119 /* ToolTableSection.swift in Sources */, + D3143FBCE8822356D2F93C7055CF3F69 /* Trigger.swift in Sources */, + 0ED0A08227958A4951C614F6BC2CEC46 /* UserDefaultsTool.swift in Sources */, + 0F1EAE11E488F618A3994F7EF0551720 /* UserDefaultsToolView.swift in Sources */, + A8649AEED79F696CE022F7BD785E18E7 /* UserDefaultsToolViewModel.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - 42F9DB61D7A4031107EEB1AC26B6ABE6 /* PBXTargetDependency */ = { + 3A76A313C742A25AE157B1A6E0530231 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = "Pods-Sentinel_Example"; - target = 254C1FBF05728FD8BE3AFCBC3F313646 /* Pods-Sentinel_Example */; - targetProxy = A3C4EA648F7BCEA6C547EA967387D1F6 /* PBXContainerItemProxy */; + name = "Sentinel-Sentinel"; + target = 8ACB6013C7A59AFAD22BD744A5CEE9FE /* Sentinel-Sentinel */; + targetProxy = 18DF10A0C285A2DF81A04FDE829964C0 /* PBXContainerItemProxy */; }; - 4402548340139BB2D705578AF2E7B911 /* PBXTargetDependency */ = { + 6324315EE57FC54332427A7469FB3059 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = Sentinel; target = F402433F0FA4E4D3D7AF80AFBDD40215 /* Sentinel */; - targetProxy = 50989D6A0F20DD0F78CDBC9D79F4C4E8 /* PBXContainerItemProxy */; + targetProxy = 4E0AC4479FA3066F2644D8EB9AB35F09 /* PBXContainerItemProxy */; }; - 714723919996FC0F6746EB12199ACEBC /* PBXTargetDependency */ = { + CC20807E7AEF5F806A155DED7A2894E7 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - name = "Sentinel-Sentinel"; - target = 8ACB6013C7A59AFAD22BD744A5CEE9FE /* Sentinel-Sentinel */; - targetProxy = 09B1ED28F6C43537557FDDDCD037916D /* PBXContainerItemProxy */; + name = "Pods-Sentinel_Example"; + target = 254C1FBF05728FD8BE3AFCBC3F313646 /* Pods-Sentinel_Example */; + targetProxy = 94A4DC63F50CBF58FA59FA569BF74303 /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ - 13A78DA6E6A56671CD973F594611C71C /* Release */ = { + 4BC7450F9457737EE3E637BA155B56F7 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 9569796757499011EED7D03B408B6F1A /* Pods-Sentinel_Tests.release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + 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; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "POD_CONFIGURATION_DEBUG=1", + "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 = 14.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRIP_INSTALLED_PRODUCT = NO; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + SYMROOT = "${SRCROOT}/../build"; + }; + name = Debug; + }; + 5C94F7A32534FCE7C135C91C9FAD2A11 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = FCD5716A347A57C5EB37EDE8EE5438D4 /* Pods-Sentinel_Example.release.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; ARCHS = "$(ARCHS_STANDARD_64_BIT)"; @@ -802,12 +869,14 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "Target Support Files/Pods-Sentinel_Tests/Pods-Sentinel_Tests-Info.plist"; + ENABLE_MODULE_VERIFIER = NO; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + INFOPLIST_FILE = "Target Support Files/Pods-Sentinel_Example/Pods-Sentinel_Example-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-Sentinel_Tests/Pods-Sentinel_Tests.modulemap"; + MODULEMAP_FILE = "Target Support Files/Pods-Sentinel_Example/Pods-Sentinel_Example.modulemap"; OTHER_LDFLAGS = ""; OTHER_LIBTOOLFLAGS = ""; PODS_ROOT = "$(SRCROOT)"; @@ -822,9 +891,71 @@ }; name = Release; }; - 3857D0D2353C5DD7BAE50AC092DDAEDF /* Release */ = { + 8B5A46FF8D3C1289CDEE3BAFACABCD2A /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = FCD5716A347A57C5EB37EDE8EE5438D4 /* Pods-Sentinel_Example.release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + 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"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "POD_CONFIGURATION_RELEASE=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 = 14.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRIP_INSTALLED_PRODUCT = NO; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_VERSION = 5.0; + SYMROOT = "${SRCROOT}/../build"; + }; + name = Release; + }; + A363C5C3F9207F74B4278ED582B7C7C3 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = C3831A0EE07DA0231A8F1CB9F738F429 /* Pods-Sentinel_Tests.debug.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; ARCHS = "$(ARCHS_STANDARD_64_BIT)"; @@ -837,12 +968,14 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "Target Support Files/Pods-Sentinel_Example/Pods-Sentinel_Example-Info.plist"; + ENABLE_MODULE_VERIFIER = NO; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + INFOPLIST_FILE = "Target Support Files/Pods-Sentinel_Tests/Pods-Sentinel_Tests-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-Sentinel_Example/Pods-Sentinel_Example.modulemap"; + MODULEMAP_FILE = "Target Support Files/Pods-Sentinel_Tests/Pods-Sentinel_Tests.modulemap"; OTHER_LDFLAGS = ""; OTHER_LIBTOOLFLAGS = ""; PODS_ROOT = "$(SRCROOT)"; @@ -851,15 +984,31 @@ SDKROOT = iphoneos; SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Release; + name = Debug; }; - 64091E9E6879CB5A2A0BCAE70F776F56 /* Release */ = { + B2073376AEA87361831424C8B5D9074F /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 2E98A32570B59CCDC9F10FE0827754A8 /* Sentinel.release.xcconfig */; + baseConfigurationReference = 0FD645F8FDA590A1283B3F4FE9543FAC /* Sentinel.debug.xcconfig */; + buildSettings = { + CODE_SIGNING_ALLOWED = NO; + CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/Sentinel"; + IBSC_MODULE = Sentinel; + INFOPLIST_FILE = "Target Support Files/Sentinel/ResourceBundle-Sentinel-Sentinel-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; + PRODUCT_NAME = Sentinel; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + WRAPPER_EXTENSION = bundle; + }; + name = Debug; + }; + B64ACC71C25FDC20DF35413319349994 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 0FD645F8FDA590A1283B3F4FE9543FAC /* Sentinel.debug.xcconfig */; buildSettings = { ARCHS = "$(ARCHS_STANDARD_64_BIT)"; CLANG_ENABLE_OBJC_WEAK = NO; @@ -871,10 +1020,13 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = NO; + ENABLE_USER_SCRIPT_SANDBOXING = NO; GCC_PREFIX_HEADER = "Target Support Files/Sentinel/Sentinel-prefix.pch"; + GENERATE_INFOPLIST_FILE = NO; INFOPLIST_FILE = "Target Support Files/Sentinel/Sentinel-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MODULEMAP_FILE = "Target Support Files/Sentinel/Sentinel.modulemap"; PRODUCT_MODULE_NAME = Sentinel; @@ -882,19 +1034,18 @@ SDKROOT = iphoneos; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_INSTALL_OBJC_HEADER = YES; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Release; + name = Debug; }; - 6E0E0ACED00A7B13F1FEDF53FD89CEE7 /* Debug */ = { + B73E6828FFE64454E0C2A16C70EFE11C /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = A66CE977C2A4DD6409F650637CBD401F /* Pods-Sentinel_Example.debug.xcconfig */; + baseConfigurationReference = DD2143883292C0381027CEF446EE828C /* Sentinel.release.xcconfig */; buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; ARCHS = "$(ARCHS_STANDARD_64_BIT)"; CLANG_ENABLE_OBJC_WEAK = NO; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; @@ -905,28 +1056,32 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "Target Support Files/Pods-Sentinel_Example/Pods-Sentinel_Example-Info.plist"; + ENABLE_MODULE_VERIFIER = NO; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_PREFIX_HEADER = "Target Support Files/Sentinel/Sentinel-prefix.pch"; + GENERATE_INFOPLIST_FILE = NO; + INFOPLIST_FILE = "Target Support Files/Sentinel/Sentinel-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-Sentinel_Example/Pods-Sentinel_Example.modulemap"; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PODS_ROOT = "$(SRCROOT)"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; - PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + MODULEMAP_FILE = "Target Support Files/Sentinel/Sentinel.modulemap"; + PRODUCT_MODULE_NAME = Sentinel; + PRODUCT_NAME = Sentinel; SDKROOT = iphoneos; SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_INSTALL_OBJC_HEADER = YES; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Debug; + name = Release; }; - 78A91C60D8060771A8B9E1559EC533F3 /* Debug */ = { + C23F87347931498744F9B3572B773799 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = C3831A0EE07DA0231A8F1CB9F738F429 /* Pods-Sentinel_Tests.debug.xcconfig */; + baseConfigurationReference = A66CE977C2A4DD6409F650637CBD401F /* Pods-Sentinel_Example.debug.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; ARCHS = "$(ARCHS_STANDARD_64_BIT)"; @@ -939,12 +1094,14 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "Target Support Files/Pods-Sentinel_Tests/Pods-Sentinel_Tests-Info.plist"; + ENABLE_MODULE_VERIFIER = NO; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + INFOPLIST_FILE = "Target Support Files/Pods-Sentinel_Example/Pods-Sentinel_Example-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-Sentinel_Tests/Pods-Sentinel_Tests.modulemap"; + MODULEMAP_FILE = "Target Support Files/Pods-Sentinel_Example/Pods-Sentinel_Example.modulemap"; OTHER_LDFLAGS = ""; OTHER_LIBTOOLFLAGS = ""; PODS_ROOT = "$(SRCROOT)"; @@ -958,10 +1115,28 @@ }; name = Debug; }; - 79544938D977454AEF34B2BF195B6254 /* Debug */ = { + D9BA9B6B6F8C571A7BB1938A44549A99 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DD2143883292C0381027CEF446EE828C /* Sentinel.release.xcconfig */; + buildSettings = { + CODE_SIGNING_ALLOWED = NO; + CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/Sentinel"; + IBSC_MODULE = Sentinel; + INFOPLIST_FILE = "Target Support Files/Sentinel/ResourceBundle-Sentinel-Sentinel-Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; + PRODUCT_NAME = Sentinel; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + WRAPPER_EXTENSION = bundle; + }; + name = Release; + }; + E69E0C313D2A1104DDC45EEF4BB53FF4 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 85BC350766D86BCFF06AFDCA2F596D1A /* Sentinel.debug.xcconfig */; + baseConfigurationReference = 9569796757499011EED7D03B408B6F1A /* Pods-Sentinel_Tests.release.xcconfig */; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; ARCHS = "$(ARCHS_STANDARD_64_BIT)"; CLANG_ENABLE_OBJC_WEAK = NO; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; @@ -972,230 +1147,72 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/Sentinel/Sentinel-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/Sentinel/Sentinel-Info.plist"; + ENABLE_MODULE_VERIFIER = NO; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + INFOPLIST_FILE = "Target Support Files/Pods-Sentinel_Tests/Pods-Sentinel_Tests-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/Sentinel/Sentinel.modulemap"; - PRODUCT_MODULE_NAME = Sentinel; - PRODUCT_NAME = Sentinel; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-Sentinel_Tests/Pods-Sentinel_Tests.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SDKROOT = iphoneos; SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; - SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Debug; - }; - 8EAADA685C653013073154463DB7484E /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 2E98A32570B59CCDC9F10FE0827754A8 /* Sentinel.release.xcconfig */; - buildSettings = { - CODE_SIGNING_ALLOWED = NO; - CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/Sentinel"; - IBSC_MODULE = Sentinel; - INFOPLIST_FILE = "Target Support Files/Sentinel/ResourceBundle-Sentinel-Sentinel-Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; - PRODUCT_NAME = Sentinel; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - TARGETED_DEVICE_FAMILY = "1,2"; - WRAPPER_EXTENSION = bundle; - }; name = Release; }; - 903A0004D3E6651EFD5D2E16214D101B /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - 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"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREPROCESSOR_DEFINITIONS = ( - "POD_CONFIGURATION_RELEASE=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 = 11.0; - MTL_ENABLE_DEBUG_INFO = NO; - MTL_FAST_MATH = YES; - PRODUCT_NAME = "$(TARGET_NAME)"; - STRIP_INSTALLED_PRODUCT = NO; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_OPTIMIZATION_LEVEL = "-O"; - SWIFT_VERSION = 5.0; - SYMROOT = "${SRCROOT}/../build"; - }; - name = Release; - }; - B4EFE046ACF8F37157F6E322C7FCFC28 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - 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; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "POD_CONFIGURATION_DEBUG=1", - "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 = 11.0; - MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; - MTL_FAST_MATH = YES; - ONLY_ACTIVE_ARCH = YES; - PRODUCT_NAME = "$(TARGET_NAME)"; - STRIP_INSTALLED_PRODUCT = NO; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - SYMROOT = "${SRCROOT}/../build"; - }; - name = Debug; - }; - FA7D9A0C9FCBFCCBA50391B1B88CF78B /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 85BC350766D86BCFF06AFDCA2F596D1A /* Sentinel.debug.xcconfig */; - buildSettings = { - CODE_SIGNING_ALLOWED = NO; - CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/Sentinel"; - IBSC_MODULE = Sentinel; - INFOPLIST_FILE = "Target Support Files/Sentinel/ResourceBundle-Sentinel-Sentinel-Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; - PRODUCT_NAME = Sentinel; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - TARGETED_DEVICE_FAMILY = "1,2"; - WRAPPER_EXTENSION = bundle; - }; - name = Debug; - }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */ = { isa = XCConfigurationList; buildConfigurations = ( - B4EFE046ACF8F37157F6E322C7FCFC28 /* Debug */, - 903A0004D3E6651EFD5D2E16214D101B /* Release */, + 4BC7450F9457737EE3E637BA155B56F7 /* Debug */, + 8B5A46FF8D3C1289CDEE3BAFACABCD2A /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 974D76B44E958BAAE90264833D7E7D59 /* Build configuration list for PBXNativeTarget "Pods-Sentinel_Tests" */ = { + 7EEDB746BA035EDA0A9605558B36D651 /* Build configuration list for PBXNativeTarget "Sentinel" */ = { isa = XCConfigurationList; buildConfigurations = ( - 78A91C60D8060771A8B9E1559EC533F3 /* Debug */, - 13A78DA6E6A56671CD973F594611C71C /* Release */, + B64ACC71C25FDC20DF35413319349994 /* Debug */, + B73E6828FFE64454E0C2A16C70EFE11C /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 97CECA2C7429160E40B79AEC0BE6A8F4 /* Build configuration list for PBXNativeTarget "Pods-Sentinel_Example" */ = { + 90A20A902093842EAA6A5881461A2736 /* Build configuration list for PBXNativeTarget "Pods-Sentinel_Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( - 6E0E0ACED00A7B13F1FEDF53FD89CEE7 /* Debug */, - 3857D0D2353C5DD7BAE50AC092DDAEDF /* Release */, + A363C5C3F9207F74B4278ED582B7C7C3 /* Debug */, + E69E0C313D2A1104DDC45EEF4BB53FF4 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - CB98FC08DF1B1DB646351C60E8BFE554 /* Build configuration list for PBXNativeTarget "Sentinel" */ = { + 9CA9FF59475346B1062C7120ABD2EE5B /* Build configuration list for PBXNativeTarget "Pods-Sentinel_Example" */ = { isa = XCConfigurationList; buildConfigurations = ( - 79544938D977454AEF34B2BF195B6254 /* Debug */, - 64091E9E6879CB5A2A0BCAE70F776F56 /* Release */, + C23F87347931498744F9B3572B773799 /* Debug */, + 5C94F7A32534FCE7C135C91C9FAD2A11 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - DF3C6469DC778636EB72AFD53909FF79 /* Build configuration list for PBXNativeTarget "Sentinel-Sentinel" */ = { + C7D7F55693077F87F0DE4D7CD917EAD0 /* Build configuration list for PBXNativeTarget "Sentinel-Sentinel" */ = { isa = XCConfigurationList; buildConfigurations = ( - FA7D9A0C9FCBFCCBA50391B1B88CF78B /* Debug */, - 8EAADA685C653013073154463DB7484E /* Release */, + B2073376AEA87361831424C8B5D9074F /* Debug */, + D9BA9B6B6F8C571A7BB1938A44549A99 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; diff --git a/Example/Pods/Target Support Files/Pods-Sentinel_Example/Pods-Sentinel_Example-acknowledgements.markdown b/Example/Pods/Target Support Files/Pods-Sentinel_Example/Pods-Sentinel_Example-acknowledgements.markdown index 5ccac97..56f5c33 100644 --- a/Example/Pods/Target Support Files/Pods-Sentinel_Example/Pods-Sentinel_Example-acknowledgements.markdown +++ b/Example/Pods/Target Support Files/Pods-Sentinel_Example/Pods-Sentinel_Example-acknowledgements.markdown @@ -3,24 +3,206 @@ This application makes use of the following third party libraries: ## Sentinel -Copyright (c) 2020 vlaho.poluta@infinum.hr - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. Generated by CocoaPods - https://cocoapods.org diff --git a/Example/Pods/Target Support Files/Pods-Sentinel_Example/Pods-Sentinel_Example-acknowledgements.plist b/Example/Pods/Target Support Files/Pods-Sentinel_Example/Pods-Sentinel_Example-acknowledgements.plist index 5a8436d..08701b1 100644 --- a/Example/Pods/Target Support Files/Pods-Sentinel_Example/Pods-Sentinel_Example-acknowledgements.plist +++ b/Example/Pods/Target Support Files/Pods-Sentinel_Example/Pods-Sentinel_Example-acknowledgements.plist @@ -14,28 +14,210 @@ FooterText - Copyright (c) 2020 vlaho.poluta@infinum.hr <vlaho.poluta@infinum.hr> - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. License - MIT + Apache 2.0 Title Sentinel Type diff --git a/Example/Pods/Target Support Files/Pods-Sentinel_Example/Pods-Sentinel_Example.debug.xcconfig b/Example/Pods/Target Support Files/Pods-Sentinel_Example/Pods-Sentinel_Example.debug.xcconfig index c041164..89d9de3 100644 --- a/Example/Pods/Target Support Files/Pods-Sentinel_Example/Pods-Sentinel_Example.debug.xcconfig +++ b/Example/Pods/Target Support Files/Pods-Sentinel_Example/Pods-Sentinel_Example.debug.xcconfig @@ -6,6 +6,7 @@ HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Sentinel/Sen LD_RUNPATH_SEARCH_PATHS = $(inherited) /usr/lib/swift '@executable_path/Frameworks' '@loader_path/Frameworks' LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift OTHER_LDFLAGS = $(inherited) -framework "Sentinel" -framework "UIKit" +OTHER_MODULE_VERIFIER_FLAGS = $(inherited) "-F${PODS_CONFIGURATION_BUILD_DIR}/Sentinel" OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS PODS_BUILD_DIR = ${BUILD_DIR} PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) diff --git a/Example/Pods/Target Support Files/Pods-Sentinel_Example/Pods-Sentinel_Example.release.xcconfig b/Example/Pods/Target Support Files/Pods-Sentinel_Example/Pods-Sentinel_Example.release.xcconfig index c041164..89d9de3 100644 --- a/Example/Pods/Target Support Files/Pods-Sentinel_Example/Pods-Sentinel_Example.release.xcconfig +++ b/Example/Pods/Target Support Files/Pods-Sentinel_Example/Pods-Sentinel_Example.release.xcconfig @@ -6,6 +6,7 @@ HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Sentinel/Sen LD_RUNPATH_SEARCH_PATHS = $(inherited) /usr/lib/swift '@executable_path/Frameworks' '@loader_path/Frameworks' LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift OTHER_LDFLAGS = $(inherited) -framework "Sentinel" -framework "UIKit" +OTHER_MODULE_VERIFIER_FLAGS = $(inherited) "-F${PODS_CONFIGURATION_BUILD_DIR}/Sentinel" OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS PODS_BUILD_DIR = ${BUILD_DIR} PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) diff --git a/Example/Pods/Target Support Files/Sentinel/ResourceBundle-Sentinel-Sentinel-Info.plist b/Example/Pods/Target Support Files/Sentinel/ResourceBundle-Sentinel-Sentinel-Info.plist index 55f1117..87cfcb5 100644 --- a/Example/Pods/Target Support Files/Sentinel/ResourceBundle-Sentinel-Sentinel-Info.plist +++ b/Example/Pods/Target Support Files/Sentinel/ResourceBundle-Sentinel-Sentinel-Info.plist @@ -13,7 +13,7 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 1.2.2 + 2.0.0 CFBundleSignature ???? CFBundleVersion diff --git a/Example/Pods/Target Support Files/Sentinel/Sentinel-Info.plist b/Example/Pods/Target Support Files/Sentinel/Sentinel-Info.plist index 957b090..6efd186 100644 --- a/Example/Pods/Target Support Files/Sentinel/Sentinel-Info.plist +++ b/Example/Pods/Target Support Files/Sentinel/Sentinel-Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 1.2.2 + 2.0.0 CFBundleSignature ???? CFBundleVersion diff --git a/Example/Sentinel.xcodeproj/project.pbxproj b/Example/Sentinel.xcodeproj/project.pbxproj index 77b83b4..09bd06f 100644 --- a/Example/Sentinel.xcodeproj/project.pbxproj +++ b/Example/Sentinel.xcodeproj/project.pbxproj @@ -7,6 +7,8 @@ objects = { /* Begin PBXBuildFile section */ + 377E92762D0C4D660075DFB8 /* ColorChangeToolView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 377E92752D0C4D660075DFB8 /* ColorChangeToolView.swift */; }; + 377E92782D0C4F280075DFB8 /* ColorChangeToolTableItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 377E92772D0C4F280075DFB8 /* ColorChangeToolTableItem.swift */; }; 607FACD61AFB9204008FA782 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACD51AFB9204008FA782 /* AppDelegate.swift */; }; 607FACD81AFB9204008FA782 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACD71AFB9204008FA782 /* ViewController.swift */; }; 607FACDB1AFB9204008FA782 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 607FACD91AFB9204008FA782 /* Main.storyboard */; }; @@ -29,6 +31,8 @@ /* Begin PBXFileReference section */ 1C1442853648AB442AF2A524 /* Pods-Sentinel_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Sentinel_Tests.debug.xcconfig"; path = "Target Support Files/Pods-Sentinel_Tests/Pods-Sentinel_Tests.debug.xcconfig"; sourceTree = ""; }; + 377E92752D0C4D660075DFB8 /* ColorChangeToolView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorChangeToolView.swift; sourceTree = ""; }; + 377E92772D0C4F280075DFB8 /* ColorChangeToolTableItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorChangeToolTableItem.swift; sourceTree = ""; }; 4FC51A772513952F00E98846 /* Sentinel_Example-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Sentinel_Example-Bridging-Header.h"; sourceTree = ""; }; 607FACD01AFB9204008FA782 /* Sentinel_Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Sentinel_Example.app; sourceTree = BUILT_PRODUCTS_DIR; }; 607FACD41AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -47,7 +51,7 @@ A2E62755C38902FFAC4E9A7A /* Pods-Sentinel_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Sentinel_Tests.release.xcconfig"; path = "Target Support Files/Pods-Sentinel_Tests/Pods-Sentinel_Tests.release.xcconfig"; sourceTree = ""; }; A5CD9E5D6B215DE1B7DAD54D /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = ""; }; ADE62A678F3EFBCFB5F548B7 /* Pods-Sentinel_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Sentinel_Example.release.xcconfig"; path = "Target Support Files/Pods-Sentinel_Example/Pods-Sentinel_Example.release.xcconfig"; sourceTree = ""; }; - CBB6C51C3843F1DB480D9EE0 /* Sentinel.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = Sentinel.podspec; path = ../Sentinel.podspec; sourceTree = ""; }; + CBB6C51C3843F1DB480D9EE0 /* Sentinel.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = Sentinel.podspec; path = ../Sentinel.podspec; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -101,6 +105,8 @@ 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */, 607FACD31AFB9204008FA782 /* Supporting Files */, 4FC51A772513952F00E98846 /* Sentinel_Example-Bridging-Header.h */, + 377E92752D0C4D660075DFB8 /* ColorChangeToolView.swift */, + 377E92772D0C4F280075DFB8 /* ColorChangeToolTableItem.swift */, ); name = "Example for Sentinel"; path = Sentinel; @@ -337,6 +343,8 @@ files = ( 607FACD81AFB9204008FA782 /* ViewController.swift in Sources */, 607FACD61AFB9204008FA782 /* AppDelegate.swift in Sources */, + 377E92762D0C4D660075DFB8 /* ColorChangeToolView.swift in Sources */, + 377E92782D0C4F280075DFB8 /* ColorChangeToolTableItem.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -425,7 +433,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = "iOS 14.0"; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -474,7 +482,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = "iOS 14.0"; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; @@ -491,6 +499,7 @@ CLANG_ENABLE_MODULES = YES; DEVELOPMENT_TEAM = 5F5M64F878; INFOPLIST_FILE = Sentinel/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; MODULE_NAME = ExampleApp; PRODUCT_BUNDLE_IDENTIFIER = "com.infinum.demo.Sentinel-Example"; @@ -510,6 +519,7 @@ CLANG_ENABLE_MODULES = YES; DEVELOPMENT_TEAM = 5F5M64F878; INFOPLIST_FILE = Sentinel/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; MODULE_NAME = ExampleApp; PRODUCT_BUNDLE_IDENTIFIER = "com.infinum.demo.Sentinel-Example"; @@ -534,6 +544,7 @@ "$(inherited)", ); INFOPLIST_FILE = Tests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -552,6 +563,7 @@ "$(inherited)", ); INFOPLIST_FILE = Tests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; diff --git a/Example/Sentinel/AppDelegate.swift b/Example/Sentinel/AppDelegate.swift index 4ba152b..6ea5347 100644 --- a/Example/Sentinel/AppDelegate.swift +++ b/Example/Sentinel/AppDelegate.swift @@ -32,23 +32,31 @@ enum AppSwitches { } private extension AppDelegate { - + func setupSentinel() { let configuration = Sentinel.Configuration( trigger: Triggers.shake, tools: [ UserDefaultsTool(), baseUrlTool, - CustomLocationTool() -// CollarTool(), -// LoggieTool() + CustomLocationTool(), + colorChangeTool ], preferences: optionSwitchItems ) - + Sentinel.shared.setup(with: configuration) } - + + var colorChangeTool: Tool { + ToolTable( + name: "Color Change Tool", + sections: [ + ToolTableSection(title: "Color change", items: [.custom(ColorChangeToolTableItem())]) + ] + ) + } + var baseUrlTool: Tool { TextEditingTool( name: "Base URL", @@ -58,33 +66,39 @@ private extension AppDelegate { userDefaultsKey: "base_url_user_defaults_key" ) } - - var optionSwitchItems: [OptionSwitchItem] { - [ - OptionSwitchItem( - name: "Analytics", - setter: { AppSwitches.analyticsEnabled = $0 }, - getter: { AppSwitches.analyticsEnabled }, - userDefaults: .standard, - userDefaultsKey: "com.infinum.sentinel.optionSwitch.analytics" - ), - OptionSwitchItem( - name: "Crashlytics", - setter: { AppSwitches.crashlyticsEnabled = $0 }, - getter: { AppSwitches.crashlyticsEnabled }, - userDefaults: .standard, - userDefaultsKey: "com.infinum.sentinel.optionSwitch.crashlytics" - ), - OptionSwitchItem( - name: "Logging", - setter: { AppSwitches.loggingEnabled = $0 }, - getter: { AppSwitches.loggingEnabled }, - userDefaults: .standard, - userDefaultsKey: "com.infinum.sentinel.optionSwitch.logging" - ), - ] + + var optionSwitchItems: [ToolTableSection] { + [ + .init( + title: "UserDefaults flags", + items: [ + .toggle( + ToggleToolItem( + title: "Analytics", + userDefaults: .standard, + userDefaultsKey: "com.infinum.sentinel.optionSwitch.analytics" + ) + ), + .toggle( + ToggleToolItem( + title: "Crashlytics", + setter: { AppSwitches.crashlyticsEnabled = $0 }, + getter: { AppSwitches.crashlyticsEnabled } + ) + ), + .toggle( + ToggleToolItem( + title: "Logging", + userDefaults: .standard, + userDefaultsKey: "com.infinum.sentinel.optionSwitch.logging" + ) + ) + ] + ) + + ] } - + } diff --git a/Example/Sentinel/ColorChangeToolTableItem.swift b/Example/Sentinel/ColorChangeToolTableItem.swift new file mode 100644 index 0000000..33b3349 --- /dev/null +++ b/Example/Sentinel/ColorChangeToolTableItem.swift @@ -0,0 +1,21 @@ +// +// ColorChangeToolTableItem.swift +// Sentinel_Example +// +// Created by Zvonimir Medak on 13.12.2024.. +// Copyright © 2024 CocoaPods. All rights reserved. +// + +import Sentinel +import SwiftUI + +struct ColorChangeToolTableItem: CustomToolTableItem { + + var title: String { + "Color change" + } + + var content: any View { + ColorChangeToolView() + } +} diff --git a/Example/Sentinel/ColorChangeToolView.swift b/Example/Sentinel/ColorChangeToolView.swift new file mode 100644 index 0000000..47015e0 --- /dev/null +++ b/Example/Sentinel/ColorChangeToolView.swift @@ -0,0 +1,24 @@ +// +// ColorChangeToolView.swift +// Sentinel_Example +// +// Created by Zvonimir Medak on 13.12.2024.. +// Copyright © 2024 CocoaPods. All rights reserved. +// + +import SwiftUI + +struct ColorChangeToolView: View { + + @State var isBlue: Bool = false + + var body: some View { + HStack(spacing: 16) { + (isBlue ? Color.blue : Color.red) + .frame(maxWidth: .infinity, alignment: .leading) + + Button("Change color") { isBlue.toggle() } + } + } + +} diff --git a/Package.swift b/Package.swift index 5539b69..c99f075 100644 --- a/Package.swift +++ b/Package.swift @@ -6,7 +6,7 @@ import PackageDescription let package = Package( name: "Sentinel", platforms: [ - .iOS(.v11) + .iOS(.v14) ], products: [ .library( diff --git a/Sentinel.podspec b/Sentinel.podspec index 161bcb2..5bd83bd 100644 --- a/Sentinel.podspec +++ b/Sentinel.podspec @@ -24,7 +24,7 @@ Pod::Spec.new do |s| s.requires_arc = true s.platform = :ios s.swift_version = '5.0' - s.ios.deployment_target = '11.0' + s.ios.deployment_target = '14.0' s.resource_bundles = { 'Sentinel' => ['Sentinel/Assets/**/*', 'Sentinel/SupportingFiles/PrivacyInfo.xcprivacy'], } diff --git a/Sentinel/Classes/Core/CustomInfoTool.swift b/Sentinel/Classes/Core/CustomInfoTool.swift index 6c854f1..2d4bae7 100644 --- a/Sentinel/Classes/Core/CustomInfoTool.swift +++ b/Sentinel/Classes/Core/CustomInfoTool.swift @@ -5,15 +5,15 @@ // Created by Vlaho Poluta on 30/07/2020. // -import UIKit +import SwiftUI + +/// Tool which gives the ability to show info + value pairs +public struct CustomInfoTool: Tool { -@objcMembers -public class CustomInfoTool: NSObject, Tool { - // MARK: - Public properties public let name: String - + // MARK: - Internal properties let info: [Section] @@ -24,57 +24,30 @@ public class CustomInfoTool: NSObject, Tool { self.name = name self.info = info } - - // MARK: - Public properties - - public func presentPreview(from viewController: UIViewController) { - let toolTable = createToolTable(with: info) - toolTable.presentPreview(from: viewController) +} + +// MARK: - UI + +public extension CustomInfoTool { + + var content: any View { + SentinelListView(title: name, items: createToolTable(with: info).sections) } - // MARK: - Internal methods +} + +// MARK: - Helpers + +extension CustomInfoTool { func createToolTable(with info: [Section]) -> ToolTable { let sections = info.map { (section) in ToolTableSection( title: section.title, - items: section.items.map { DetailToolTableItem(title: $0.title, detail: $0.value) } + items: section.items.map { .customInfo($0) } ) } return ToolTable(name: name, sections: sections) } -} -extension CustomInfoTool { - - public class Section { - - // MARK: - Internal properties - - let title: String? - let items: [Item] - - // MARK: - Lifecycle - - public init(title: String? = nil, items: [Item]) { - self.title = title - self.items = items - } - } - - public class Item { - - // MARK: - Internal properties - - let title: String - let value: String - - // MARK: - Lifecycle - - public init(title: String, value: String) { - self.title = title - self.value = value - } - } - } diff --git a/Sentinel/Classes/Core/CustomInfoToolSection.swift b/Sentinel/Classes/Core/CustomInfoToolSection.swift new file mode 100644 index 0000000..30543c3 --- /dev/null +++ b/Sentinel/Classes/Core/CustomInfoToolSection.swift @@ -0,0 +1,62 @@ +// +// CustomInfoToolSection.swift +// Sentinel +// +// Created by Zvonimir Medak on 18.12.2024.. +// + +import Foundation + +public extension CustomInfoTool { + + /// Section Item for the CustomInfoTool which expects CustomInfoTool.Item for its items + struct Section { + + // MARK: - Internal properties + + let title: String? + let items: [Item] + + // MARK: - Lifecycle + + public init(title: String? = nil, items: [Item]) { + self.title = title + self.items = items + } + } + + /// Row Item for the CustomInfoTool which will show a title + value pair + struct Item { + + // MARK: - Internal properties + + let title: String + let value: String + + // MARK: - Lifecycle + + public init(title: String, value: String) { + self.title = title + self.value = value + } + } + +} + +// MARK: - Equatable conformance + +extension CustomInfoTool.Item: Equatable { + + public static func == (lhs: CustomInfoTool.Item, rhs: CustomInfoTool.Item) -> Bool { + lhs.title == rhs.title + } +} + +// MARK: - Identifiable conformance + +extension CustomInfoTool.Item: Identifiable { + + public var id: String { + title + } +} diff --git a/Sentinel/Classes/Core/Internal/ApplicationTool.swift b/Sentinel/Classes/Core/Internal/ApplicationTool.swift index 234691d..93f72ad 100644 --- a/Sentinel/Classes/Core/Internal/ApplicationTool.swift +++ b/Sentinel/Classes/Core/Internal/ApplicationTool.swift @@ -6,17 +6,22 @@ // import Foundation -import UIKit +import SwiftUI + +/// Tool which shows Plist information about the App +struct ApplicationTool: Tool { + + // MARK: - Public properties + + public var name: String { tool.name } -class ApplicationTool: Tool { - // MARK: - Lifecycle - + public init() {} // MARK: - Private properties - - private lazy var tool = CustomInfoTool( + + private let tool = CustomInfoTool( name: "Application", info: [ CustomInfoTool.Section( @@ -38,37 +43,36 @@ class ApplicationTool: Tool { ) ] ) - - // MARK: - Internal properties +} + +// MARK: - Extensions + +// MARK: - UI + +extension ApplicationTool { var toolTable: ToolTable { - return tool.createToolTable(with: tool.info) + tool.createToolTable(with: tool.info) } - - // MARK: - Public properties - public var name: String { tool.name } - - // MARK: - Public methods - - public func presentPreview(from viewController: UIViewController) { - tool.presentPreview(from: viewController) + var content: any View { + SentinelListView(title: name, items: toolTable.sections) } } -// MARK: - Internal extension +// MARK: - Info helpers extension ApplicationTool { - func stringFromPlist(for key: CFString) -> String { + static func stringFromPlist(for key: CFString) -> String { stringFromPlist(for: key as String) } - func stringFromPlist(for key: String) -> String { + static func stringFromPlist(for key: String) -> String { Bundle.main.object(forInfoDictionaryKey: key).map { String(describing: $0) } ?? "" } - var bundleAllInfos: [CustomInfoTool.Item] { + static var bundleAllInfos: [CustomInfoTool.Item] { Bundle.main.infoDictionary? .map { CustomInfoTool.Item(title: $0.key, value: String(describing: $0.value)) } ?? [] diff --git a/Sentinel/Classes/Core/Internal/DeviceTool.swift b/Sentinel/Classes/Core/Internal/DeviceTool.swift index 9642ff8..6b24e15 100644 --- a/Sentinel/Classes/Core/Internal/DeviceTool.swift +++ b/Sentinel/Classes/Core/Internal/DeviceTool.swift @@ -5,10 +5,14 @@ // Created by Zvonimir Medak on 30.09.2021.. // -import Foundation -import UIKit +import SwiftUI -class DeviceTool: Tool { +/// Tool which shows current device information +struct DeviceTool: Tool { + + // MARK: - Public properties + + public var name: String { tool.name } // MARK: - Lifecycle @@ -16,7 +20,7 @@ class DeviceTool: Tool { // MARK: - Private properties - private lazy var tool = CustomInfoTool( + private let tool = CustomInfoTool( name: "Device", info: [ CustomInfoTool.Section(title: "Device", items: [ @@ -29,47 +33,43 @@ class DeviceTool: Tool { ]) ]) - // MARK: - Internal properties +} - var toolTable: ToolTable { - return tool.createToolTable(with: tool.info) - } +// MARK: - UI - // MARK: - Private properties +extension DeviceTool { - private var systemVersion: String { - "\(UIDevice.current.systemName) \(UIDevice.current.systemVersion)" + var toolTable: ToolTable { + tool.createToolTable(with: tool.info) } - // MARK: - Public properties - - public var name: String { tool.name } - - // MARK: - Public methods - - public func presentPreview(from viewController: UIViewController) { - tool.presentPreview(from: viewController) + var content: any View { + SentinelListView(title: name, items: toolTable.sections) } } -// MARK: - Private extension +// MARK: - Info helpers private extension DeviceTool { - var batteryState: String { + static var systemVersion: String { + "\(UIDevice.current.systemName) \(UIDevice.current.systemVersion)" + } + + static var batteryState: String { switch UIDevice.current.batteryState { case .charging: - return "Charging at: \(calculateBatteryPercentage(with: UIDevice.current.batteryLevel.description))%" + "Charging at: \(calculateBatteryPercentage(with: UIDevice.current.batteryLevel.description))%" case .full: - return "Full" + "Full" case .unplugged: - return "\(calculateBatteryPercentage(with: UIDevice.current.batteryLevel.description))%" + "\(calculateBatteryPercentage(with: UIDevice.current.batteryLevel.description))%" default: - return "Unknown" + "Unknown" } } - func calculateBatteryPercentage(with amount: String) -> String { + static func calculateBatteryPercentage(with amount: String) -> String { guard let batteryLevel = Double(amount) else { return "Unknown" } return "\(batteryLevel * 100.0)" } diff --git a/Sentinel/Classes/Core/Internal/Image+Assets.swift b/Sentinel/Classes/Core/Internal/Image+Assets.swift new file mode 100644 index 0000000..e4e5980 --- /dev/null +++ b/Sentinel/Classes/Core/Internal/Image+Assets.swift @@ -0,0 +1,59 @@ +// +// Image+Assets.swift +// Sentinel +// +// Created by Zvonimir Medak on 10.12.2024.. +// + +import SwiftUI + +// There's an issue with the generated assets, and local cocoapods which should be resolved in Xcode 16.1 +extension Image { + enum SentinelImages{} +} + +extension Image.SentinelImages { + static var device = Image.load(using: "device") + static var application = Image.load(using: "application") + static var tools = Image.load(using: "tools") + static var preferences = Image.load(using: "preferences") + static var performance = Image.load(using: "performance") +} + +extension Image { + + /// Tries to load an image with the provided name. Defaults to nil if the Image is not available + /// - Parameters: + /// - name: Name of the image which will be fetched + static func load(using name: String) -> Image? { + let frameworkBundle = Bundle(for: Sentinel.self) + guard let frameworkURL = frameworkBundle.resourceURL else { return nil } + return fetchImage(using: name, with: frameworkURL) + } + + /// Tries to load an image with the provided name. If the image is not available, the app will default to the provided image. + /// - Parameters: + /// - name: Name of the image which will be fetched + /// - image: Image which the function will default to if the Image with the provided name wasn not found + static func load(using name: String, defaultTo image: Image = .init(systemName: "circle.fill")) -> Image { + let frameworkBundle = Bundle(for: Sentinel.self) + guard let frameworkURL = frameworkBundle.resourceURL else { return image } + return fetchImage(using: name, with: frameworkURL) + } +} + +private extension Image { + + static func fetchImage(using name: String, with frameworkURL: URL) -> Image { + let bundleURL = frameworkURL.appendingPathComponent("Sentinel.bundle") + + #if SWIFT_PACKAGE + let resourceBundle = Bundle.sentinel + #else + let resourceBundle = Bundle(url: bundleURL) + #endif + + return Image(name, bundle: resourceBundle) + } +} + diff --git a/Sentinel/Classes/Core/Internal/Sentinel.storyboard b/Sentinel/Classes/Core/Internal/Sentinel.storyboard deleted file mode 100644 index 3f981b7..0000000 --- a/Sentinel/Classes/Core/Internal/Sentinel.storyboard +++ /dev/null @@ -1,90 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Sentinel/Classes/Core/Internal/SentinelInternal.swift b/Sentinel/Classes/Core/Internal/SentinelInternal.swift index d71a8d3..295f2fd 100644 --- a/Sentinel/Classes/Core/Internal/SentinelInternal.swift +++ b/Sentinel/Classes/Core/Internal/SentinelInternal.swift @@ -5,7 +5,7 @@ // Created by Vlaho Poluta on 30/07/2020. // -import UIKit +import SwiftUI extension Sentinel { @@ -17,40 +17,28 @@ extension Sentinel { /// - viewController: The view controller from where will the Sentinel be presented. func present( tools: [Tool], - preferences: [OptionSwitchItem], + preferences: [ToolTableSection], on viewController: UIViewController ) { let tabItems = createTabItems( with: tools, - preferences: preferences, - viewController: viewController + preferences: preferences ) - let tabBarController = UIStoryboard.sentinel - .instantiateViewController(ofType: SentinelTabBarController.self) - let preselectedTabIndex = preselectedTabIndex( - for: .tools(items: []), - tabItems: tabItems - ) - tabBarController.setupViewControllers( - with: tabItems.map { $0.viewController }, - preselectedIndex: preselectedTabIndex - ) - tabBarController.title = "Sentinel" - let navController = UINavigationController(rootViewController: tabBarController) - viewController.present(navController, animated: true) + let tabBarController = UIHostingController(rootView: SentinelTabBarView(tabs: tabItems)) + viewController.present(tabBarController, animated: true) } } -// MARK: - Private extension +// MARK: - Helpers private extension Sentinel { + func createTabItems( with tools: [Tool], - preferences: [OptionSwitchItem], - viewController: UIViewController + preferences: [ToolTableSection] ) -> [SentinelTabItem] { - return [ + [ SentinelTabItem(tab: .device), SentinelTabItem(tab: .application), SentinelTabItem(tab: .tools(items: tools)), @@ -60,7 +48,7 @@ private extension Sentinel { } func preselectedTabIndex(for tab: SentinelTab, tabItems: [SentinelTabItem]) -> Int { - return tabItems + tabItems .enumerated() .first(where: { guard case .tools = $0.element.tab else { return false } diff --git a/Sentinel/Classes/Core/Internal/SentinelListView.swift b/Sentinel/Classes/Core/Internal/SentinelListView.swift new file mode 100644 index 0000000..9f1524d --- /dev/null +++ b/Sentinel/Classes/Core/Internal/SentinelListView.swift @@ -0,0 +1,44 @@ +// +// SentinelListView.swift +// Sentinel +// +// Created by Zvonimir Medak on 08.11.2024.. +// + +import SwiftUI + +struct SentinelListView: View { + + let title: String + let items: [ToolTableSection] + + var body: some View { + List(items, id: \.id) { section in + Section { + if let title = section.title { + Text(title) + } + + ForEach(section.items) { item in + switch item { + case .navigation(let item): + NavigationLink { + AnyView(item.didSelect()) + } label: { + NavigationToolTableView(item: item) + } + case .toggle(let item): + OptionSwitchView(item: item) + case .customInfo(let item): + TitleValueView(item: item) + case .performance(let item): + PerformanceToolView(viewModel: .init(item: item)) + case .custom(let item): + AnyView(item.content) + } + } + } + } + .navigationTitle(title) + } +} diff --git a/Sentinel/Classes/Core/Internal/SentinelTab.swift b/Sentinel/Classes/Core/Internal/SentinelTab.swift index 24eea3a..b339b7b 100644 --- a/Sentinel/Classes/Core/Internal/SentinelTab.swift +++ b/Sentinel/Classes/Core/Internal/SentinelTab.swift @@ -11,6 +11,6 @@ enum SentinelTab { case device case application case tools(items: [Tool]) - case preferences(items: [OptionSwitchItem]) + case preferences(items: [ToolTableSection]) case performance } diff --git a/Sentinel/Classes/Core/Internal/SentinelTabBarController.swift b/Sentinel/Classes/Core/Internal/SentinelTabBarController.swift deleted file mode 100644 index 944dc2f..0000000 --- a/Sentinel/Classes/Core/Internal/SentinelTabBarController.swift +++ /dev/null @@ -1,52 +0,0 @@ -// -// SentinelTabBarController.swift -// Sentinel -// -// Created by Zvonimir Medak on 28.09.2021.. -// - -import UIKit - -final class SentinelTabBarController: UITabBarController { - - // MARK: - Private properties - - private var didPreselectAction = false - private var preselectedIndex: Int? - - // MARK: - Lifecycle - - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - - setPreselectedActionIfNeeded() - } - - @IBAction func close(_ sender: Any) { - if (navigationController?.viewControllers.count ?? 0) > 1 { - navigationController?.popViewController(animated: true) - } else { - dismiss(animated: true) - } - } -} - -extension SentinelTabBarController { - - func setupViewControllers(with viewControllers: [UIViewController], preselectedIndex: Int) { - self.viewControllers = viewControllers - self.preselectedIndex = preselectedIndex - } -} - -// MARK: - Private methods - - -private extension SentinelTabBarController { - - func setPreselectedActionIfNeeded() { - defer { didPreselectAction = true } - guard !didPreselectAction else { return } - // Preselect Tools tab - selectedIndex = preselectedIndex ?? 0 - } -} diff --git a/Sentinel/Classes/Core/Internal/SentinelTabBarView.swift b/Sentinel/Classes/Core/Internal/SentinelTabBarView.swift new file mode 100644 index 0000000..c845708 --- /dev/null +++ b/Sentinel/Classes/Core/Internal/SentinelTabBarView.swift @@ -0,0 +1,50 @@ +// +// SentinelTabBarView.swift +// Sentinel +// +// Created by Zvonimir Medak on 08.11.2024.. +// + +import SwiftUI + +enum Tab { + case device + case application + case tools + case preferences + case performance +} + +struct SentinelTabBarView: View { + + @State var selectedTab: Tab = .tools + let tabs: [SentinelTabItem] + + var body: some View { + NavigationView { + TabView(selection: $selectedTab) { + ForEach(tabs, id: \.barItemTitle) { tab in + SentinelListView(title: tab.barItemTitle, items: tab.sections) + .tabItem { TabBarView(tab: tab) } + } + } + } + .navigationTitle("Sentinel") + } +} + +private struct TabBarView: View { + + let tab: SentinelTabItem + + var body: some View { + VStack(spacing: 5) { + if let image = tab.barItemImage { + image + .renderingMode(.template) + } + + Text(tab.barItemTitle) + } + } +} diff --git a/Sentinel/Classes/Core/Internal/SentinelTabItem.swift b/Sentinel/Classes/Core/Internal/SentinelTabItem.swift index c1ce410..e9e63e3 100644 --- a/Sentinel/Classes/Core/Internal/SentinelTabItem.swift +++ b/Sentinel/Classes/Core/Internal/SentinelTabItem.swift @@ -5,7 +5,7 @@ // Created by Milos on 24.8.22.. // -import UIKit +import SwiftUI struct SentinelTabItem { @@ -14,34 +14,11 @@ struct SentinelTabItem { init(tab: SentinelTab) { self.tab = tab } - - var viewController: UIViewController { - switch tab { - case .device: - let deviceVC = SentinelTableViewController.create(with: toolTable) - deviceVC.tabBarItem = tabBarItem - return deviceVC - case .application: - let applicationVC = SentinelTableViewController.create(with: toolTable) - applicationVC.tabBarItem = tabBarItem - return applicationVC - case .tools: - let toolsVC = SentinelTableViewController.create(with: toolTable) - toolsVC.tabBarItem = tabBarItem - return toolsVC - case .preferences: - let preferencesVC = SentinelTableViewController.create(with: toolTable) - preferencesVC.tabBarItem = tabBarItem - return preferencesVC - case .performance: - let performanceVC = SentinelTableViewController.create(with: toolTable) - performanceVC.tabBarItem = tabBarItem - return performanceVC - } - } } -private extension SentinelTabItem { +// MARK: - Helpers + +extension SentinelTabItem { var barItemTitle: String { switch tab { @@ -58,33 +35,24 @@ private extension SentinelTabItem { } } - var barItemImage: UIImage { + var barItemImage: Image? { switch tab { - case .device: - guard let image = UIImage.SentinelImages.device else { return UIImage() } - return image - case .application: - guard let image = UIImage.SentinelImages.application else { return UIImage() } - return image - case .tools: - guard let image = UIImage.SentinelImages.tools else { return UIImage() } - return image - case .preferences: - guard let image = UIImage.SentinelImages.preferences else { return UIImage() } - return image - case .performance: - guard let image = UIImage.SentinelImages.performance else { return UIImage() } - return image + case .device: .SentinelImages.device + case .application: .SentinelImages.application + case .tools: .SentinelImages.tools + case .preferences: .SentinelImages.preferences + case .performance: .SentinelImages.performance } } - var tabBarItem: UITabBarItem { - return UITabBarItem( - title: barItemTitle, - image: barItemImage, - selectedImage: barItemImage - ) + var sections: [ToolTableSection] { + toolTable.sections } +} + +// MARK: - Private helpers + +private extension SentinelTabItem { var toolTable: ToolTable { switch tab { @@ -98,7 +66,7 @@ private extension SentinelTabItem { return toolTable case .tools(let items): let navigationItems = items - .map { NavigationToolTableItem(title: $0.name, navigate: $0.presentPreview(from:)) } + .map { tool in ToolTableItem.navigation(.init(title: tool.name, didSelect: { tool.content })) } let section = ToolTableSection(title: barItemTitle, items: navigationItems) let toolTable = ToolTable(name: barItemTitle, sections: [section]) return toolTable diff --git a/Sentinel/Classes/Core/Internal/SentinelTableViewController.swift b/Sentinel/Classes/Core/Internal/SentinelTableViewController.swift deleted file mode 100644 index 94fa04d..0000000 --- a/Sentinel/Classes/Core/Internal/SentinelTableViewController.swift +++ /dev/null @@ -1,75 +0,0 @@ -// -// SentinelTableViewController.swift -// Sentinel -// -// Created by Vlaho Poluta on 30/07/2020. -// - -import UIKit - -class SentinelTableViewController: UIViewController { - - @IBOutlet private var tableView: UITableView! - private var toolTable: ToolTable! - - static func create(with toolTable: ToolTable) -> SentinelTableViewController { - let viewController = UIStoryboard.sentinel.instantiateViewController(ofType: Self.self) - viewController.toolTable = toolTable - return viewController - } - - override func viewDidLoad() { - super.viewDidLoad() - title = toolTable.name - toolTable.sections - .flatMap { $0.items } - .forEach { $0.register?(at: tableView) } - if (navigationController?.viewControllers.count ?? 0) > 1 { - navigationItem.rightBarButtonItems = nil - } - } -} - -extension SentinelTableViewController: UITableViewDelegate { - - func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { - return toolTable[indexPath].height ?? UITableView.automaticDimension - } - - func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat { - return toolTable[indexPath].estimatedHeight ?? 44.0 - } - - func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - tableView.deselectRow(at: indexPath, animated: true) - toolTable[indexPath].didSelect?(from: self) - } -} - -extension SentinelTableViewController: UITableViewDataSource { - - func numberOfSections(in tableView: UITableView) -> Int { - toolTable.sections.count - } - - func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - toolTable.sections[section].items.count - } - - func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - toolTable[indexPath].cell(from: tableView, at: indexPath) - } - - func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { - toolTable[section].title - } -} - -extension ToolTable { - subscript(index: Int) -> ToolTableSection { - sections[index] - } - subscript(indexPath: IndexPath) -> ToolTableItem { - sections[indexPath.section].items[indexPath.row] - } -} diff --git a/Sentinel/Classes/Core/Internal/SentinelUIKitExtensions.swift b/Sentinel/Classes/Core/Internal/SentinelUIKitExtensions.swift index d5d9cd4..7018de5 100644 --- a/Sentinel/Classes/Core/Internal/SentinelUIKitExtensions.swift +++ b/Sentinel/Classes/Core/Internal/SentinelUIKitExtensions.swift @@ -19,21 +19,8 @@ extension Bundle { extension UIStoryboard { static var sentinel: UIStoryboard { UIStoryboard(name: "Sentinel", bundle: .sentinel) } - + func instantiateViewController(ofType type: T.Type) -> T { instantiateViewController(withIdentifier: String(describing: T.self)) as! T } } - -extension UITableView { - - func dequeueReusableCell(ofType type: T.Type, for indexPath: IndexPath) -> T { - return dequeueReusableCell(withIdentifier: String(describing: type), for: indexPath) as! T - } - - func registerNib(cellOfType cellType: T.Type) { - let identifier = String(describing: T.self) - register(UINib(nibName: identifier, bundle: .sentinel), forCellReuseIdentifier: identifier) - } -} - diff --git a/Sentinel/Classes/Core/Internal/UIImage+Assets.swift b/Sentinel/Classes/Core/Internal/UIImage+Assets.swift deleted file mode 100644 index 68afe09..0000000 --- a/Sentinel/Classes/Core/Internal/UIImage+Assets.swift +++ /dev/null @@ -1,20 +0,0 @@ -// -// UIImage+Assets.swift -// Sentinel -// -// Created by Zvonimir Medak on 15.11.2021.. -// - -import UIKit - -extension UIImage { - enum SentinelImages{} -} - -extension UIImage.SentinelImages { - static var device = UIImage.load(fromBundleNamed: "device") - static var application = UIImage.load(fromBundleNamed: "application") - static var tools = UIImage.load(fromBundleNamed: "tools") - static var preferences = UIImage.load(fromBundleNamed: "preferences") - static var performance = UIImage.load(fromBundleNamed: "performance") -} diff --git a/Sentinel/Classes/Core/PerformanceInfo/Internal/CPUInfoProvider.swift b/Sentinel/Classes/Core/PerformanceInfo/Internal/CPUInfoProvider.swift index 8930ae4..f7b2b81 100644 --- a/Sentinel/Classes/Core/PerformanceInfo/Internal/CPUInfoProvider.swift +++ b/Sentinel/Classes/Core/PerformanceInfo/Internal/CPUInfoProvider.swift @@ -7,18 +7,20 @@ import Foundation -class CPUInfoProvider { - +struct CPUInfoProvider { + + /// Fetches the number of cores the devices has var numberOfCores: Int { - return ProcessInfo().processorCount + ProcessInfo().processorCount } - + + /// Fetches the percentage of the CPU currently being used by the App var currentUsage: Double { var totalUsageOfCPU: Double = 0.0 var threadsList: thread_act_array_t? var threadsCount = mach_msg_type_number_t(0) let threadsResult = withUnsafeMutablePointer(to: &threadsList) { - return $0.withMemoryRebound(to: thread_act_array_t?.self, capacity: 1) { + $0.withMemoryRebound(to: thread_act_array_t?.self, capacity: 1) { task_threads(mach_task_self_, $0, &threadsCount) } } diff --git a/Sentinel/Classes/Core/PerformanceInfo/Internal/MemoryInfoProvider.swift b/Sentinel/Classes/Core/PerformanceInfo/Internal/MemoryInfoProvider.swift index c4023c8..98d48a6 100644 --- a/Sentinel/Classes/Core/PerformanceInfo/Internal/MemoryInfoProvider.swift +++ b/Sentinel/Classes/Core/PerformanceInfo/Internal/MemoryInfoProvider.swift @@ -12,8 +12,9 @@ struct MemoryUsage { let total: Int64 } -class MemoryInfoProvider { - +struct MemoryInfoProvider { + + /// Fetches the current memory usage of the App var currentUsage: MemoryUsage { var taskInfo = task_vm_info_data_t() var count = mach_msg_type_number_t(MemoryLayout.size) / 4 diff --git a/Sentinel/Classes/Core/PerformanceInfo/Internal/SystemInfoProvider.swift b/Sentinel/Classes/Core/PerformanceInfo/Internal/SystemInfoProvider.swift index 07afff4..58ce066 100644 --- a/Sentinel/Classes/Core/PerformanceInfo/Internal/SystemInfoProvider.swift +++ b/Sentinel/Classes/Core/PerformanceInfo/Internal/SystemInfoProvider.swift @@ -7,8 +7,9 @@ import Foundation -class SystemInfoProvider { +struct SystemInfoProvider { + /// Fetches the active time of the app var uptime: String { secondsToHoursMinutesSeconds(interval: ProcessInfo().systemUptime) } @@ -30,6 +31,6 @@ private extension SystemInfoProvider { } func formattedTime(from value: Int) -> String { - return value < 10 ? "0\(value)" : "\(value)" + value < 10 ? "0\(value)" : "\(value)" } } diff --git a/Sentinel/Classes/Core/PerformanceInfo/Items/PerformanceInfoItem.swift b/Sentinel/Classes/Core/PerformanceInfo/Items/PerformanceInfoItem.swift index f2aa5a5..fe12328 100644 --- a/Sentinel/Classes/Core/PerformanceInfo/Items/PerformanceInfoItem.swift +++ b/Sentinel/Classes/Core/PerformanceInfo/Items/PerformanceInfoItem.swift @@ -5,9 +5,11 @@ // Created by Nikola Majcen on 18/11/2020. // -import UIKit +import Foundation -class PerformanceInfoItem: NSObject { +/// Item for the PerformanceTool +/// Contains a title and a valueDidChange closure which updates the value every time the timer sends an event +public struct PerformanceInfoItem { // MARK: - Internal properties @@ -22,17 +24,20 @@ class PerformanceInfoItem: NSObject { } } -// MARK: - ToolTableItem +// MARK: - Equatable conformance -extension PerformanceInfoItem: ToolTableItem { +extension PerformanceInfoItem: Equatable { - public func cell(from tableView: UITableView, at indexPath: IndexPath) -> UITableViewCell { - let cell = tableView.dequeueReusableCell(ofType: PerformanceInfoTableViewCell.self, for: indexPath) - cell.configure(with: self) - return cell + public static func == (lhs: PerformanceInfoItem, rhs: PerformanceInfoItem) -> Bool { + lhs.title == rhs.title } +} + +// MARK: - Identifiable conformance + +extension PerformanceInfoItem: Identifiable { - public func register(at tableView: UITableView) { - tableView.registerNib(cellOfType: PerformanceInfoTableViewCell.self) + public var id: String { + title } } diff --git a/Sentinel/Classes/Core/PerformanceInfo/Items/PerformanceInfoTableViewCell.swift b/Sentinel/Classes/Core/PerformanceInfo/Items/PerformanceInfoTableViewCell.swift deleted file mode 100644 index 0e46bb2..0000000 --- a/Sentinel/Classes/Core/PerformanceInfo/Items/PerformanceInfoTableViewCell.swift +++ /dev/null @@ -1,65 +0,0 @@ -// -// PerformanceInfoTableViewCell.swift -// Sentinel -// -// Created by Nikola Majcen on 02/10/2020. -// - -import UIKit - -class PerformanceInfoTableViewCell: UITableViewCell { - - // MARK: - IBOutlets - - @IBOutlet private weak var titleLabel: UILabel! - @IBOutlet private weak var valueLabel: UILabel! - - // MARK: - Private properties - - private var valueDidChange: (() -> String)? - private var timer: Timer? - - // MARK: - Lifecycle - - override func awakeFromNib() { - super.awakeFromNib() - initializeTimer() - } - - override func prepareForReuse() { - super.prepareForReuse() - invalidateTimer() - initializeTimer() - } - - // MARK: - Internal methods - - func configure(with item: PerformanceInfoItem) { - self.valueDidChange = item.valueDidChange - titleLabel.text = item.title - valueLabel.text = item.valueDidChange() - } -} - -// MARK: - Private methods - -private extension PerformanceInfoTableViewCell { - - func initializeTimer() { - timer = Timer.scheduledTimer( - timeInterval: 1.0, - target: self, - selector: #selector(updatePerformanceInfo), - userInfo: nil, - repeats: true - ) - } - - func invalidateTimer() { - timer?.invalidate() - } - - @objc func updatePerformanceInfo() { - valueLabel.text = valueDidChange?() ?? "--" - } -} diff --git a/Sentinel/Classes/Core/PerformanceInfo/Items/PerformanceInfoTableViewCell.xib b/Sentinel/Classes/Core/PerformanceInfo/Items/PerformanceInfoTableViewCell.xib deleted file mode 100644 index 09bbd8a..0000000 --- a/Sentinel/Classes/Core/PerformanceInfo/Items/PerformanceInfoTableViewCell.xib +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Sentinel/Classes/Core/PerformanceInfo/Items/PerformanceInfoViewModel.swift b/Sentinel/Classes/Core/PerformanceInfo/Items/PerformanceInfoViewModel.swift new file mode 100644 index 0000000..c79d52b --- /dev/null +++ b/Sentinel/Classes/Core/PerformanceInfo/Items/PerformanceInfoViewModel.swift @@ -0,0 +1,62 @@ +// +// PerformanceInfoViewModel.swift +// Sentinel +// +// Created by Zvonimir Medak on 28.11.2024.. +// + +import Foundation + +final class PerformanceInfoViewModel: ObservableObject { + + // MARK: - Internal properties + + @Published var value: String + let item: PerformanceInfoItem + + // MARK: - Private properties + + private var timer: Timer? + + // MARK: - Init + + init(item: PerformanceInfoItem) { + self.item = item + value = item.valueDidChange() + } +} + +// MARK: - Internal methods + +extension PerformanceInfoViewModel { + + func startTimer() { + invalidateTimer() + initializeTimer() + } +} + +// MARK: - Timer helpers + +private extension PerformanceInfoViewModel { + + func initializeTimer() { + timer = Timer.scheduledTimer( + timeInterval: 1.0, + target: self, + selector: #selector(updatePerformanceInfo), + userInfo: nil, + repeats: true + ) + } + + func invalidateTimer() { + timer?.invalidate() + } + + @objc + func updatePerformanceInfo() { + value = item.valueDidChange() + } + +} diff --git a/Sentinel/Classes/Core/PerformanceInfo/Items/PerformanceToolView.swift b/Sentinel/Classes/Core/PerformanceInfo/Items/PerformanceToolView.swift new file mode 100644 index 0000000..6adf8f2 --- /dev/null +++ b/Sentinel/Classes/Core/PerformanceInfo/Items/PerformanceToolView.swift @@ -0,0 +1,25 @@ +// +// PerformanceToolView.swift +// Sentinel +// +// Created by Zvonimir Medak on 28.11.2024.. +// + +import SwiftUI + +struct PerformanceToolView: View { + + @ObservedObject var viewModel: PerformanceInfoViewModel + + var body: some View { + HStack(spacing: 10) { + Text(viewModel.item.title) + .font(.system(size: 13, weight: .bold)) + + Text(viewModel.value) + .font(.system(size: 13, weight: .regular)) + .frame(maxWidth: .infinity, alignment: .trailing) + } + .onAppear { viewModel.startTimer() } + } +} diff --git a/Sentinel/Classes/Core/PerformanceInfo/PerformanceInfo.storyboard b/Sentinel/Classes/Core/PerformanceInfo/PerformanceInfo.storyboard deleted file mode 100644 index bcbc1de..0000000 --- a/Sentinel/Classes/Core/PerformanceInfo/PerformanceInfo.storyboard +++ /dev/null @@ -1,94 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Sentinel/Classes/Core/PerformanceInfo/PerformanceTool.swift b/Sentinel/Classes/Core/PerformanceInfo/PerformanceTool.swift index e853503..15444cc 100644 --- a/Sentinel/Classes/Core/PerformanceInfo/PerformanceTool.swift +++ b/Sentinel/Classes/Core/PerformanceInfo/PerformanceTool.swift @@ -5,10 +5,11 @@ // Created by Nikola Majcen on 02/10/2020. // -import UIKit +import SwiftUI + +/// Tool which shows the current state of the CPU, memory, system and App duration +struct PerformanceTool: Tool { -class PerformanceTool: Tool { - // MARK: - Public properties public let name: String @@ -18,18 +19,18 @@ class PerformanceTool: Tool { public init(name: String = "Performance") { self.name = name } +} - // MARK: - Internal properties +// MARK: - UI + +extension PerformanceTool { var toolTable: ToolTable { - return createToolTable() + createToolTable() } - // MARK: - Public methods - - public func presentPreview(from viewController: UIViewController) { - let toolTable = createToolTable() - toolTable.presentPreview(from: viewController) + var content: any View { + SentinelListView(title: name, items: toolTable.sections) } } @@ -51,8 +52,8 @@ private extension PerformanceTool { func cpuInfoItems() -> [ToolTableItem] { let cpuInfo = CPUInfoProvider() return [ - PerformanceInfoItem(title: "CPU Usage", valueDidChange: { String(format: "%.2f%%", cpuInfo.currentUsage) }), - PerformanceInfoItem(title: "Number of cores", valueDidChange: { String(format: "%d", cpuInfo.numberOfCores) }) + .performance(.init(title: "CPU Usage", valueDidChange: { String(format: "%.2f%%", cpuInfo.currentUsage) })), + .performance(PerformanceInfoItem(title: "Number of cores", valueDidChange: { String(format: "%d", cpuInfo.numberOfCores) })) ] } @@ -61,14 +62,14 @@ private extension PerformanceTool { let used = ByteCountFormatter.string(fromByteCount: memoryInfo.currentUsage.used, countStyle: .file) let total = ByteCountFormatter.string(fromByteCount: memoryInfo.currentUsage.total, countStyle: .file) return [ - PerformanceInfoItem(title: "Memory usage", valueDidChange: { "\(used) / \(total)" }) + .performance(PerformanceInfoItem(title: "Memory usage", valueDidChange: { "\(used) / \(total)" })) ] } func systemInfoItems() -> [ToolTableItem] { let systemInfo = SystemInfoProvider() return [ - PerformanceInfoItem(title: "Uptime", valueDidChange: { systemInfo.uptime }) + .performance(PerformanceInfoItem(title: "Uptime", valueDidChange: { systemInfo.uptime })) ] } diff --git a/Sentinel/Classes/Core/PreferencesInfo/OptionSwitchItem.swift b/Sentinel/Classes/Core/PreferencesInfo/OptionSwitchItem.swift index b7dc073..f19379a 100644 --- a/Sentinel/Classes/Core/PreferencesInfo/OptionSwitchItem.swift +++ b/Sentinel/Classes/Core/PreferencesInfo/OptionSwitchItem.swift @@ -5,88 +5,75 @@ // Created by Nikola Majcen on 02/10/2020. // -import UIKit +import Foundation -/// Provides option to change enabled state of the feature. -@objcMembers -public class OptionSwitchItem: NSObject { - - // MARK: - Internal properties - - /// Name of the item - let name: String - /// This function is called when value is changed. - /// - /// It should be used to change the current variable value. - let setter: (Bool) -> () - /// This function is called when value needs to be read. - /// - /// It should be used to provide the current variable value. - let getter: () -> (Bool) - - // MARK: - Private properties - - private let userDefaults: UserDefaults - private let userDefaultsKey: String? +/// Item which will be shown in the PreferencesTool +/// Provides a switch which can save/fetch values from the UserDefaults or some other setter/getter which can be specified. +public struct ToggleToolItem { + let title: String + let setter: ((Bool) -> ())? + let getter: (() -> Bool)? + let userDefaults: UserDefaults + let userDefaultsKey: String? - // MARK: - Lifecycle - public init( - name: String, - setter: @escaping (Bool) -> (), - getter: @escaping () -> (Bool), + title: String, userDefaults: UserDefaults = .standard, - userDefaultsKey: String? + userDefaultsKey: String ) { - self.name = name - self.setter = setter - self.getter = getter + self.title = title self.userDefaults = userDefaults self.userDefaultsKey = userDefaultsKey - super.init() - loadStoredValue() + setter = nil + getter = nil } - - // MARK: - Internal methods - - /// Changes current enabled state of the feature. - /// - /// This is mostly used inside option switch module - /// but it is also exposed for external change. - @objc(changeToValue:) - func change(to value: Bool) { - store(newValue: value) - } -} -extension OptionSwitchItem: ToolTableItem { - - public func cell(from tableView: UITableView, at indexPath: IndexPath) -> UITableViewCell { - let cell = tableView.dequeueReusableCell(ofType: OptionSwitchTableViewCell.self, for: indexPath) - cell.configure(with: self) - return cell - } - - public func register(at tableView: UITableView) { - tableView.registerNib(cellOfType: OptionSwitchTableViewCell.self) + public init( + title: String, + setter: @escaping (Bool) -> (), + getter: @escaping () -> Bool + ) { + self.title = title + self.getter = getter + self.setter = setter + userDefaults = .standard + userDefaultsKey = nil } } -// MARK: - Private methods +// MARK: - Helpres + +extension ToggleToolItem { -private extension OptionSwitchItem { - - func store(newValue: Bool) { - if let key = userDefaultsKey { - userDefaults.set(newValue, forKey: key) + func change(to value: Bool) { + if let userDefaultsKey { + userDefaults.set(value, forKey: userDefaultsKey) } - setter(newValue) + setter?(value) } - - func loadStoredValue() { + + func loadStoredValue() -> Bool { guard let key = userDefaultsKey, let value = userDefaults.object(forKey: key) as? Bool - else { return } - setter(value) + else { return getter?() ?? false } + return value + } +} + +// MARK: - Equatable conformance + +extension ToggleToolItem: Equatable { + + public static func == (lhs: ToggleToolItem, rhs: ToggleToolItem) -> Bool { + lhs.title == rhs.title + } +} + +// MARK: - Identifiable conformance + +extension ToggleToolItem: Identifiable { + + public var id: String { + title } } diff --git a/Sentinel/Classes/Core/PreferencesInfo/OptionSwitchTableViewCell.swift b/Sentinel/Classes/Core/PreferencesInfo/OptionSwitchTableViewCell.swift deleted file mode 100644 index c2aaa76..0000000 --- a/Sentinel/Classes/Core/PreferencesInfo/OptionSwitchTableViewCell.swift +++ /dev/null @@ -1,34 +0,0 @@ -// -// OptionSwitchTableViewCell.swift -// Sentinel -// -// Created by Nikola Majcen on 02/10/2020. -// - -import UIKit - -class OptionSwitchTableViewCell: UITableViewCell { - - // MARK: - IBOutlets - - @IBOutlet private weak var titleLabel: UILabel! - @IBOutlet private weak var optionSwitch: UISwitch! - - // MARK: - Private properties - - private var optionSwitchActionHandler: ((Bool) -> Void)? - - // MARK: - Public methods - - func configure(with item: OptionSwitchItem) { - titleLabel.text = item.name - optionSwitch.isOn = item.getter() - optionSwitchActionHandler = { item.change(to: $0) } - } - - // MARK: - IBActions - - @IBAction func optionSwitchHandler(_ sender: UISwitch) { - optionSwitchActionHandler?(sender.isOn) - } -} diff --git a/Sentinel/Classes/Core/PreferencesInfo/OptionSwitchTableViewCell.xib b/Sentinel/Classes/Core/PreferencesInfo/OptionSwitchTableViewCell.xib deleted file mode 100644 index 50b6409..0000000 --- a/Sentinel/Classes/Core/PreferencesInfo/OptionSwitchTableViewCell.xib +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Sentinel/Classes/Core/PreferencesInfo/OptionSwitchView.swift b/Sentinel/Classes/Core/PreferencesInfo/OptionSwitchView.swift new file mode 100644 index 0000000..222d6ce --- /dev/null +++ b/Sentinel/Classes/Core/PreferencesInfo/OptionSwitchView.swift @@ -0,0 +1,35 @@ +// +// OptionSwitchView.swift +// Sentinel +// +// Created by Zvonimir Medak on 27.11.2024.. +// + +import SwiftUI + +struct OptionSwitchView: View { + + @State var value: Bool + let title: String + let onValueChanged: (Bool) -> Void + + var body: some View { + Toggle(isOn: $value) { + Text(title) + .font(.system(size: 13, weight: .bold)) + .frame(maxWidth: .infinity, alignment: .leading) + } + .onChange(of: value) { onValueChanged($0) } + } +} + +// MARK: - Helpers + +extension OptionSwitchView { + + init(item: ToggleToolItem) { + value = item.loadStoredValue() + title = item.title + onValueChanged = item.change(to:) + } +} diff --git a/Sentinel/Classes/Core/PreferencesInfo/PreferencesTool.swift b/Sentinel/Classes/Core/PreferencesInfo/PreferencesTool.swift index 30b219d..e73efb9 100644 --- a/Sentinel/Classes/Core/PreferencesInfo/PreferencesTool.swift +++ b/Sentinel/Classes/Core/PreferencesInfo/PreferencesTool.swift @@ -5,49 +5,46 @@ // Created by Nikola Majcen on 02/10/2020. // -import UIKit +import SwiftUI + +/// Tool which gives the user ability to change environment variables in the application. +/// Options are grouped into sections for a better overview of different types of preferences. +struct PreferencesTool: Tool { -/// Provides functionality which gives the user ability -/// to change environment variables in the application. -class PreferencesTool: Tool { - // MARK: - Public properties public let name: String // MARK: - Private properties - private let items: [OptionSwitchItem] + private let items: [ToolTableSection] - // MARK: - Internal properties - - var toolTable: ToolTable { - return createToolTable(with: items) - } - // MARK: - Lifecycle - public init(name: String = "Preferences", items: [OptionSwitchItem]) { + public init(name: String = "Preferences", items: [ToolTableSection]) { self.name = name self.items = items } - - // MARK: - Public methods - - public func presentPreview(from viewController: UIViewController) { - let toolTable = createToolTable(with: items) - toolTable.presentPreview(from: viewController) +} + +// MARK: - UI + +extension PreferencesTool { + + var toolTable: ToolTable { + createToolTable(with: items) + } + + var content: any View { + SentinelListView(title: name, items: toolTable.sections) } } // MARK: - Private extension private extension PreferencesTool { - func createToolTable(with items: [OptionSwitchItem]) -> ToolTable { - let section = ToolTableSection( - title: nil, - items: items - ) - return ToolTable(name: name, sections: [section]) + + func createToolTable(with items: [ToolTableSection]) -> ToolTable { + ToolTable(name: name, sections: items) } } diff --git a/Sentinel/Classes/Core/Sentinel.swift b/Sentinel/Classes/Core/Sentinel.swift index d0cdaf9..b69f007 100644 --- a/Sentinel/Classes/Core/Sentinel.swift +++ b/Sentinel/Classes/Core/Sentinel.swift @@ -9,11 +9,10 @@ import Foundation /// Defines singleton instance of the Sentinel. /// -/// The Sentinel can be configured with different configurations and based on -/// the configuration used will be triggered from different events and show different tools. -@objcMembers -public class Sentinel: NSObject { - +/// The Sentinel can be configured with different configurations. Based on +/// the provided configuration, Sentinel will be triggered from different events and show different tools. +public final class Sentinel { + // MARK: - Internal properties var configuration: Configuration? @@ -21,21 +20,13 @@ public class Sentinel: NSObject { // MARK: - Public properties /// Singleton instance of the Sentinel. - @objc(sharedInstance) public static let shared = Sentinel() - // MARK: - Lifecycle - - private override init() { - super.init() - } - // MARK: - Public methods /// Setups the Sentinel with provided configuration. /// /// - Parameter configuration: The configuration used to setup current instance of the Sentinel. - @objc(setupWithConfiguration:) public func setup(with configuration: Configuration) { self.configuration = configuration configuration.trigger.subscribe { [weak self] in @@ -43,31 +34,32 @@ public class Sentinel: NSObject { self?.present(tools: configuration.tools, preferences: configuration.preferences, on: viewController) } } - - // MARK: - Inner classes - +} + +// MARK: - Configuration + +public extension Sentinel { + /// Defines configuration used to define Sentinel. /// /// Based on the provided properties, Sentinel will be shown based on different event /// and it will show different tools. - @objcMembers - @objc(Configuration) - public class Configuration: NSObject { - + struct Configuration { + // MARK: - Public properties - + /// The trigger event which starts the Sentinel. public let trigger: Trigger - + /// The screen used for presenting the Sentinel. public let sourceScreenProvider: SourceScreenProvider - + /// Tools which are available from the Sentinel. public let tools: [Tool] /// Items which are shown on preferences screen - public let preferences: [OptionSwitchItem] - + public let preferences: [ToolTableSection] + // MARK: - Lifecycle /// Creates a new configuration. @@ -76,18 +68,17 @@ public class Sentinel: NSObject { /// - trigger: The trigger event which opens the Sentinel. /// - sourceScreenProvider: The screen from which Sentinel can be presented. /// - tools: Tools available from the Sentinel. - /// - preferences: items which can allow or deny an activity inside the app + /// - preferences: Section items which can allow or deny an activity inside the app public init( trigger: Trigger, sourceScreenProvider: SourceScreenProvider = SourceScreenProviders.default, tools: [Tool], - preferences: [OptionSwitchItem] = [] + preferences: [ToolTableSection] = [] ) { self.trigger = trigger self.sourceScreenProvider = sourceScreenProvider self.tools = tools self.preferences = preferences - super.init() } } } diff --git a/Sentinel/Classes/Core/SourceScreenProvider.swift b/Sentinel/Classes/Core/SourceScreenProvider.swift index 5174b8c..83ad21a 100644 --- a/Sentinel/Classes/Core/SourceScreenProvider.swift +++ b/Sentinel/Classes/Core/SourceScreenProvider.swift @@ -8,34 +8,24 @@ import UIKit /// Defines source screen which will be used to present Sentinel when triggered. -@objc -public protocol SourceScreenProvider: NSObjectProtocol { +public protocol SourceScreenProvider { /// The view controller used for presenting the Sentinel. var viewControllerForShowingTools: UIViewController? { get } } /// Provides possible source screens used for presenting the Sentinel. -@objcMembers -public class SourceScreenProviders: NSObject { - +public enum SourceScreenProviders { + // MARK: - Public providers /// Default source screen provider. - @objc(defaultProvider) public static var `default`: SourceScreenProvider { DefaultSourceScreenProvider() } - - // MARK: - Lifecycle - - private override init() { - super.init() - } } /// Defines default source screen provider used for presenting the Sentinel. -@objcMembers -public class DefaultSourceScreenProvider: NSObject, SourceScreenProvider { - +public struct DefaultSourceScreenProvider: SourceScreenProvider { + // MARK: - Public properties public var viewControllerForShowingTools: UIViewController? { topMostController() } @@ -43,7 +33,14 @@ public class DefaultSourceScreenProvider: NSObject, SourceScreenProvider { // MARK: - Private methods private func topMostController() -> UIViewController? { - guard let window = UIApplication.shared.keyWindow, let rootViewController = window.rootViewController else { + let keyWindow = UIApplication.shared.connectedScenes + .filter { $0.activationState == .foregroundActive } + .compactMap { $0 as? UIWindowScene } + .first?.windows + .filter(\.isKeyWindow) + .first + + guard let window = keyWindow, let rootViewController = window.rootViewController else { return nil } @@ -53,13 +50,6 @@ public class DefaultSourceScreenProvider: NSObject, SourceScreenProvider { topController = newTopController } - if - let navController = topController as? UINavigationController, - navController.visibleViewController is SentinelTabBarController - { - return nil - } - return topController } } diff --git a/Sentinel/Classes/Core/Tool.swift b/Sentinel/Classes/Core/Tool.swift index 28b6451..5d7a76b 100644 --- a/Sentinel/Classes/Core/Tool.swift +++ b/Sentinel/Classes/Core/Tool.swift @@ -5,17 +5,14 @@ // Created by Vlaho Poluta on 30/07/2020. // -import UIKit +import SwiftUI -/// Defines tool behaviour. -@objc +/// Defines tool behaviour and the content View. public protocol Tool { /// The name of the tool. var name: String { get } - /// Presents the tool view controller from provided view controller. - /// - /// - Parameter viewController: The view controller used for presenting tool view controller. - @objc(presentPreviewFromViewController:) - func presentPreview(from viewController: UIViewController) + + /// Tool's content View + @ViewBuilder var content: any View { get } } diff --git a/Sentinel/Classes/Core/ToolTable.swift b/Sentinel/Classes/Core/ToolTable.swift index 8a57d77..26ba8a3 100644 --- a/Sentinel/Classes/Core/ToolTable.swift +++ b/Sentinel/Classes/Core/ToolTable.swift @@ -5,11 +5,10 @@ // Created by Vlaho Poluta on 30/07/2020. // -import UIKit +import SwiftUI /// Defines tool datasouce which can present different tool sections. -@objcMembers -public class ToolTable: NSObject, Tool { +public struct ToolTable: Tool { // MARK: - Public properties @@ -23,26 +22,22 @@ public class ToolTable: NSObject, Tool { // MARK: - Lifecycle /// Creates an instance of the tool table. - init(name: String, sections: [ToolTableSection]) { + public init(name: String, sections: [ToolTableSection]) { self.name = name self.sections = sections - super.init() } - - // MARK: - Public methods - - public func presentPreview(from viewController: UIViewController) { - presentPreview(from: viewController, push: true) + + public init(name: String, items: [ToolTableItem]) { + self.name = name + self.sections = [ToolTableSection(items: items)] } - - @objc(presentPreviewFromViewController:push:) - public func presentPreview(from viewController: UIViewController, push: Bool) { - let sentinelController = SentinelTableViewController.create(with: self) - if let navController = viewController.navigationController, push { - navController.pushViewController(sentinelController, animated: true) - } else { - let navContoller = UINavigationController(rootViewController: sentinelController) - viewController.present(navContoller, animated: true) - } +} + +// MARK: - UI + +public extension ToolTable { + + var content: any View { + SentinelListView(title: name, items: sections) } } diff --git a/Sentinel/Classes/Core/ToolTableItem.swift b/Sentinel/Classes/Core/ToolTableItem.swift index 238a8c8..1139f26 100644 --- a/Sentinel/Classes/Core/ToolTableItem.swift +++ b/Sentinel/Classes/Core/ToolTableItem.swift @@ -5,41 +5,30 @@ // Created by Nikola Majcen on 29/09/2020. // -import UIKit +import SwiftUI -/// Defines tool item behaviour and appearance. -@objc -public protocol ToolTableItem: NSObjectProtocol { - - /// Cell used for the item representation. - /// - /// - Parameters: - /// - tableView: The table view which from which item is available. - /// - indexPath: The index path in the table view from where cell should be fetched. - @objc(cellFromTableView:atIndexPath:) - func cell(from tableView: UITableView, at indexPath: IndexPath) -> UITableViewCell - - /// The height of the item. - /// - /// If not defined, a default value is used as `UITableView.automaticDimension`. - @objc - optional var height: CGFloat { get } - - /// The estimated height of the item. - /// - /// If not defined, a default value is used as `44.0`. - @objc - optional var estimatedHeight: CGFloat { get } - - /// Registers the item to the provided table view. - /// - /// - Parameter tableView: The table view which shows the items. - @objc(registerAtTableView:) - optional func register(at tableView: UITableView) - - /// It is called when the item is selected. - /// - /// - Parameter viewController: The view controller from which the item has been selected. - @objc(didSelectFromViewController:) - optional func didSelect(from viewController: UIViewController) +/// Enum with predefined Views which can be used with the ToolTable. +/// Navigation, Toggle, CustomInfo, and Performance have predefined Views. +/// In case a custom view is needed use the Custom case with a custom Item which conforms to CustomToolTableItem. +public enum ToolTableItem { + case navigation(NavigationToolItem) + case toggle(ToggleToolItem) + case customInfo(CustomInfoTool.Item) + case performance(PerformanceInfoItem) + case custom(any CustomToolTableItem) +} + +// MARK: - Identifiable conformance + +extension ToolTableItem: Identifiable { + + public var id: String { + switch self { + case .navigation(let item): item.id + case .toggle(let item): item.id + case .customInfo(let item): item.id + case .performance(let item): item.id + case .custom(let item): item.id + } + } } diff --git a/Sentinel/Classes/Core/ToolTableItems/CustomToolTableItem.swift b/Sentinel/Classes/Core/ToolTableItems/CustomToolTableItem.swift new file mode 100644 index 0000000..1a449ce --- /dev/null +++ b/Sentinel/Classes/Core/ToolTableItems/CustomToolTableItem.swift @@ -0,0 +1,20 @@ +// +// CustomToolTableItem.swift +// Sentinel +// +// Created by Zvonimir Medak on 13.12.2024.. +// + +import SwiftUI + +/// Item protocol which can be used with ToolTable to show a custom UI +public protocol CustomToolTableItem: Identifiable, Equatable { + var title: String { get } + @ViewBuilder var content: any View { get } +} + +// MARK: - Identifiable helper + +public extension CustomToolTableItem { + var id: String { title } +} diff --git a/Sentinel/Classes/Core/ToolTableItems/DetailToolTableCell.swift b/Sentinel/Classes/Core/ToolTableItems/DetailToolTableCell.swift deleted file mode 100644 index 2b55150..0000000 --- a/Sentinel/Classes/Core/ToolTableItems/DetailToolTableCell.swift +++ /dev/null @@ -1,53 +0,0 @@ -// -// DetailToolTableCell.swift -// Sentinel -// -// Created by Vlaho Poluta on 30/07/2020. -// - -import UIKit - -@objcMembers -public class DetailToolTableItem: NSObject { - - // MARK: - Internal properties - - let title: String - let detail: String - - // MARK: - Lifecycle - - public init(title: String, detail: String) { - self.title = title - self.detail = detail - super.init() - } -} - -// MARK: - ToolTableItem - -extension DetailToolTableItem: ToolTableItem { - - public func register(at tableView: UITableView) { - tableView.registerNib(cellOfType: DetailToolTableCell.self) - } - - public func cell(from tableView: UITableView, at indexPath: IndexPath) -> UITableViewCell { - let cell = tableView.dequeueReusableCell(ofType: DetailToolTableCell.self, for: indexPath) - cell.configure(with: self) - return cell - } -} - -class DetailToolTableCell: UITableViewCell { - - @IBOutlet weak var titleLabel: UILabel! - @IBOutlet weak var valueLabel: UILabel! - - // MARK: - Internal methods - - func configure(with item: DetailToolTableItem) { - titleLabel?.text = item.title - valueLabel?.text = item.detail - } -} diff --git a/Sentinel/Classes/Core/ToolTableItems/DetailToolTableCell.xib b/Sentinel/Classes/Core/ToolTableItems/DetailToolTableCell.xib deleted file mode 100644 index dff5249..0000000 --- a/Sentinel/Classes/Core/ToolTableItems/DetailToolTableCell.xib +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Sentinel/Classes/Core/ToolTableItems/NavigationToolTableCell.swift b/Sentinel/Classes/Core/ToolTableItems/NavigationToolTableCell.swift deleted file mode 100644 index 369334e..0000000 --- a/Sentinel/Classes/Core/ToolTableItems/NavigationToolTableCell.swift +++ /dev/null @@ -1,53 +0,0 @@ -// -// NavigationToolTableCell.swift -// Sentinel -// -// Created by Vlaho Poluta on 30/07/2020. -// - -import UIKit - -@objcMembers -public class NavigationToolTableItem: NSObject { - - // MARK: - Internal properties - - let title: String - let navigate: (UIViewController) -> () - - // MARK: - Lifecycle - - public init(title: String, navigate: @escaping (UIViewController) -> ()) { - self.title = title - self.navigate = navigate - } -} - -// MARK: - ToolTableItem - -extension NavigationToolTableItem: ToolTableItem { - - public func register(at tableView: UITableView) { - tableView.registerNib(cellOfType: NavigationToolTableCell.self) - } - - public func cell(from tableView: UITableView, at indexPath: IndexPath) -> UITableViewCell { - let cell = tableView.dequeueReusableCell(ofType: NavigationToolTableCell.self, for: indexPath) - cell.configure(with: self) - return cell - } - - public func didSelect(from viewController: UIViewController) { - navigate(viewController); - } -} - -class NavigationToolTableCell: UITableViewCell { - - // MARK: - Internal methods - - func configure(with item: NavigationToolTableItem) { - textLabel?.text = item.title - } - -} diff --git a/Sentinel/Classes/Core/ToolTableItems/NavigationToolTableCell.xib b/Sentinel/Classes/Core/ToolTableItems/NavigationToolTableCell.xib deleted file mode 100644 index bff513d..0000000 --- a/Sentinel/Classes/Core/ToolTableItems/NavigationToolTableCell.xib +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Sentinel/Classes/Core/ToolTableItems/NavigationToolTableItem.swift b/Sentinel/Classes/Core/ToolTableItems/NavigationToolTableItem.swift new file mode 100644 index 0000000..6c76a67 --- /dev/null +++ b/Sentinel/Classes/Core/ToolTableItems/NavigationToolTableItem.swift @@ -0,0 +1,32 @@ +// +// NavigationToolTableItem.swift +// Sentinel +// +// Created by Zvonimir Medak on 13.12.2024.. +// + +import SwiftUI + +/// Item which has a title, and by tapping on it will lead to another screen +public struct NavigationToolItem { + let title: String + let didSelect: () -> any View +} + +// MARK: - Equatable conformance + +extension NavigationToolItem: Equatable { + + public static func == (lhs: NavigationToolItem, rhs: NavigationToolItem) -> Bool { + lhs.title == rhs.title + } +} + +// MARK: - Identifiable conformance + +extension NavigationToolItem: Identifiable { + + public var id: String { + title + } +} diff --git a/Sentinel/Classes/Core/ToolTableItems/NavigationToolTableView.swift b/Sentinel/Classes/Core/ToolTableItems/NavigationToolTableView.swift new file mode 100644 index 0000000..ab554be --- /dev/null +++ b/Sentinel/Classes/Core/ToolTableItems/NavigationToolTableView.swift @@ -0,0 +1,35 @@ +// +// NavigationToolTableView.swift +// Sentinel +// +// Created by Zvonimir Medak on 27.11.2024.. +// + +import SwiftUI + +struct NavigationToolTableView: View { + + let title: String + let didSelect: () -> any View + + var body: some View { + HStack(spacing: 10) { + Text(title) + .font(.system(size: 13, weight: .bold)) + .foregroundColor(.black) + .frame(maxWidth: .infinity, alignment: .leading) + } + .frame(maxWidth: .infinity, alignment: .leading) + } + +} + +// MARK: - Helpers + +extension NavigationToolTableView { + + init(item: NavigationToolItem) { + title = item.title + didSelect = item.didSelect + } +} diff --git a/Sentinel/Classes/Core/ToolTableItems/TitleValueView.swift b/Sentinel/Classes/Core/ToolTableItems/TitleValueView.swift new file mode 100644 index 0000000..5a4665f --- /dev/null +++ b/Sentinel/Classes/Core/ToolTableItems/TitleValueView.swift @@ -0,0 +1,35 @@ +// +// TitleValueView.swift +// Sentinel +// +// Created by Zvonimir Medak on 27.11.2024.. +// + +import SwiftUI + +struct TitleValueView: View { + + let title: String + let value: String + + var body: some View { + HStack(spacing: 10) { + Text(title) + .font(.system(size: 13, weight: .bold)) + + Text(value) + .font(.system(size: 13, weight: .regular)) + .frame(maxWidth: .infinity, alignment: .trailing) + } + } +} + +// MARK: - Helpers + +extension TitleValueView { + + init(item: CustomInfoTool.Item) { + title = item.title + value = item.value + } +} diff --git a/Sentinel/Classes/Core/ToolTableSection.swift b/Sentinel/Classes/Core/ToolTableSection.swift index f259094..7dd6169 100644 --- a/Sentinel/Classes/Core/ToolTableSection.swift +++ b/Sentinel/Classes/Core/ToolTableSection.swift @@ -8,9 +8,12 @@ import Foundation /// Represents tool section in the tool table view. -@objcMembers -public class ToolTableSection: NSObject { - +public struct ToolTableSection: Identifiable { + + // MARK: - Public properties + + public let id: String + // MARK: - Internal properties /// The title of the section. @@ -20,11 +23,10 @@ public class ToolTableSection: NSObject { let items: [ToolTableItem] // MARK: - Lifecycle - - /// Creates an instance of the section. + public init(title: String? = nil, items: [ToolTableItem]) { self.title = title self.items = items - super.init() + id = title ?? UUID().uuidString } } diff --git a/Sentinel/Classes/Core/Trigger.swift b/Sentinel/Classes/Core/Trigger.swift index 71349f9..177b5ac 100644 --- a/Sentinel/Classes/Core/Trigger.swift +++ b/Sentinel/Classes/Core/Trigger.swift @@ -8,44 +8,30 @@ import UIKit /// Defines interaction with trigger. -@objc -public protocol Trigger: NSObjectProtocol { +public protocol Trigger { /// Subscribes to the triggering event. /// /// - Parameter events: The block which will be called when notification arrives. - @objc(subscribeOnEvents:) func subscribe(on events: @escaping () -> ()) } /// Provides different trigger types based on the event which makes the trigger. -@objcMembers -public class Triggers: NSObject { - - // MARK: - Public triggers - +public enum Triggers { /// The trigger type which is triggered on the shake event. public static var shake: Trigger { ShakeTrigger() } - + /// The trigger type which is triggered on the screenshot event. public static var screenshot: Trigger { ScreenshotTrigger() } - + /// The trigger type which is triggered on the specified notification name. - @objc(notificationForName:) public static func notification(forName name: Notification.Name) -> Trigger { NotificationTrigger(notificationName: name) } - - // MARK: - Lifecycle - - private override init() { - super.init() - } } /// Defines trigger which is triggered when on the notification event. -@objcMembers -public class NotificationTrigger: NSObject, Trigger { +public final class NotificationTrigger: Trigger { // MARK: - Private properties @@ -64,7 +50,6 @@ public class NotificationTrigger: NSObject, Trigger { public init(notificationName: Notification.Name, queue: OperationQueue = .main) { self.notificationName = notificationName self.queue = queue - super.init() setup() } @@ -93,9 +78,8 @@ public class NotificationTrigger: NSObject, Trigger { } /// Defines trigger which is triggered when on the screenshot event. -@objcMembers -public class ScreenshotTrigger: NSObject, Trigger { - +public final class ScreenshotTrigger: Trigger { + // MARK: - Internal properties let notificationTrigger: NotificationTrigger @@ -103,9 +87,8 @@ public class ScreenshotTrigger: NSObject, Trigger { // MARK: - Lifecycle /// Creates an instance of the screenshot trigger. - public override init() { + public init() { notificationTrigger = NotificationTrigger(notificationName: UIApplication.userDidTakeScreenshotNotification) - super.init() } // MARK: - Public methods @@ -116,9 +99,8 @@ public class ScreenshotTrigger: NSObject, Trigger { } /// Defines trigger which is triggered when on the shake event. -@objcMembers -public class ShakeTrigger: NSObject, Trigger { - +public final class ShakeTrigger: Trigger { + // MARK: - Internal properties let notificationTrigger: NotificationTrigger @@ -126,10 +108,9 @@ public class ShakeTrigger: NSObject, Trigger { // MARK: - Lifecycle /// Creates an instance of the shake trigger. - public override init() { + public init() { UIApplication.classInit notificationTrigger = NotificationTrigger(notificationName: .shakeMotionDetected) - super.init() } // MARK: - Public methods diff --git a/Sentinel/Classes/Core/UIImage+Bundle.swift b/Sentinel/Classes/Core/UIImage+Bundle.swift deleted file mode 100644 index 0d5d666..0000000 --- a/Sentinel/Classes/Core/UIImage+Bundle.swift +++ /dev/null @@ -1,26 +0,0 @@ -// -// UIImage+Bundle.swift -// Sentinel -// -// Created by Zvonimir Medak on 30.09.2021.. -// - -import UIKit - -extension UIImage { - - static func load(fromBundleNamed name: String) -> UIImage? { - let frameworkBundle = Bundle(for: Sentinel.self) - guard let frameworkURL = frameworkBundle.resourceURL else { return nil } - let bundleURL = frameworkURL.appendingPathComponent("Sentinel.bundle") - - #if SWIFT_PACKAGE - let resourceBundle = Bundle.sentinel - #else - let resourceBundle = Bundle(url: bundleURL) - #endif - - return UIImage(named: name, in: resourceBundle, compatibleWith: nil) - } -} - diff --git a/Sentinel/Classes/CustomLocation/CustomLocationTool.swift b/Sentinel/Classes/CustomLocation/CustomLocationTool.swift index d253e40..1d57557 100644 --- a/Sentinel/Classes/CustomLocation/CustomLocationTool.swift +++ b/Sentinel/Classes/CustomLocation/CustomLocationTool.swift @@ -5,16 +5,13 @@ // Created by Nikola Majcen on 01/10/2020. // -import UIKit +import SwiftUI /// Tool which gives the ability to change current user location. /// -/// When changing the user location, keep in mind that -/// every location change will be applied after -/// the application is restarted. -@objcMembers -public class CustomLocationTool: NSObject, Tool { - +/// Chaniging the user location will be applied after the application has been restarted. +public struct CustomLocationTool: Tool { + // MARK: - Public properties public let name: String @@ -22,20 +19,20 @@ public class CustomLocationTool: NSObject, Tool { // MARK: - Internal properties let locationProvider: CustomLocationProvider - + // MARK: - Lifecycle public init(name: String = "Custom Location", userDefaults: UserDefaults = .standard) { self.name = name self.locationProvider = CustomLocationProvider(userDefaults: userDefaults) } - - // MARK: - Public methods - - public func presentPreview(from viewController: UIViewController) { - let customLocationViewController = CustomLocationViewController.create( - locationProvider: locationProvider - ) - viewController.navigationController?.pushViewController(customLocationViewController, animated: true) +} + +// MARK: - UI + +public extension CustomLocationTool { + + var content: any View { + CustomLocationView(locationProvider: locationProvider) } } diff --git a/Sentinel/Classes/CustomLocation/CustomLocationView.swift b/Sentinel/Classes/CustomLocation/CustomLocationView.swift new file mode 100644 index 0000000..ef4ab0e --- /dev/null +++ b/Sentinel/Classes/CustomLocation/CustomLocationView.swift @@ -0,0 +1,21 @@ +// +// CustomLocationView.swift +// Sentinel +// +// Created by Zvonimir Medak on 10.12.2024.. +// + +import SwiftUI + +struct CustomLocationView: UIViewControllerRepresentable { + + let locationProvider: CustomLocationProvider + + func makeUIViewController(context: Context) -> some UIViewController { + CustomLocationViewController.create(locationProvider: locationProvider) + } + + func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) { + // Nothing to do here + } +} diff --git a/Sentinel/Classes/CustomLocation/CustomLocationViewController.swift b/Sentinel/Classes/CustomLocation/CustomLocationViewController.swift index 9662a28..e54b847 100644 --- a/Sentinel/Classes/CustomLocation/CustomLocationViewController.swift +++ b/Sentinel/Classes/CustomLocation/CustomLocationViewController.swift @@ -13,8 +13,8 @@ extension UIStoryboard { static var customLocation: UIStoryboard { UIStoryboard(name: "CustomLocation", bundle: .sentinel) } } -class CustomLocationViewController: UIViewController { - +final class CustomLocationViewController: UIViewController { + fileprivate enum AlertDelay: Double { case normal = 0.33 case long = 0.67 @@ -75,6 +75,8 @@ class CustomLocationViewController: UIViewController { } } +// MARK: - CLLocationManagerDelegate conformance + extension CustomLocationViewController: CLLocationManagerDelegate { func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { @@ -91,8 +93,12 @@ extension CustomLocationViewController: CLLocationManagerDelegate { } } +// MARK: - MKMapViewDelegate conformance + extension CustomLocationViewController: MKMapViewDelegate { } +// MARK: - UITextFieldDelegate conformance + extension CustomLocationViewController: UITextFieldDelegate { func textFieldShouldReturn(_ textField: UITextField) -> Bool { @@ -177,8 +183,8 @@ private extension CustomLocationViewController { } func coordinate(from text: String?) -> Double? { - guard let string = text, !string.isEmpty, let value = Double(string) else { return nil } - return value + guard let string = text, !string.isEmpty else { return nil } + return Double(string) } func showAlert(title: String, message: String, actionTitle: String, delay: AlertDelay) { @@ -216,7 +222,7 @@ private extension CustomLocationViewController { @objc func addCustomLocation(longGesture: UIGestureRecognizer) { let isEnabled = locationProvider?.isCustomLocationUsageEnabled ?? false - if !isEnabled { return } + guard isEnabled else { return } let touchPoint = longGesture.location(in: mapView) let newCoordinates = mapView.convert(touchPoint, toCoordinateFrom: mapView) latitudeTextField.text = "\(newCoordinates.latitude)" @@ -253,20 +259,14 @@ private extension CustomLocationViewController { func handleInfoLabelVisibility() { let isEnabled = locationProvider?.isCustomLocationUsageEnabled ?? false - if isEnabled { - gestureInfoLabel.isHidden = false - } else { - gestureInfoLabel.isHidden = true - } + gestureInfoLabel.isHidden = !isEnabled } func checkForExistingCoordinates() { guard let latitude = coordinate(from: latitudeTextField.text), let longitude = coordinate(from: longitudeTextField.text) - else { - return - } + else { return } let coordinates = CLLocationCoordinate2D(latitude: latitude, longitude: longitude) addPinToLocation(using: coordinates) } diff --git a/Sentinel/Classes/CustomLocation/Internal/CLLocationManager+CustomLocation.swift b/Sentinel/Classes/CustomLocation/Internal/CLLocationManager+CustomLocation.swift index 344b3ad..f65ccdc 100644 --- a/Sentinel/Classes/CustomLocation/Internal/CLLocationManager+CustomLocation.swift +++ b/Sentinel/Classes/CustomLocation/Internal/CLLocationManager+CustomLocation.swift @@ -12,7 +12,7 @@ extension CLLocationManager { @objc func startUpdatingCustomLocation() { guard let tools = Sentinel.shared.configuration?.tools.compactMap({ $0 as? CustomLocationTool }) else { return } - let locations = tools.compactMap({ $0.locationProvider.customLocation }) + let locations = tools.compactMap(\.locationProvider.customLocation) delegate?.locationManager?(self, didUpdateLocations: locations) } } diff --git a/Sentinel/Classes/CustomLocation/Internal/CustomLocationProvider.swift b/Sentinel/Classes/CustomLocation/Internal/CustomLocationProvider.swift index c44ce36..beecc2e 100644 --- a/Sentinel/Classes/CustomLocation/Internal/CustomLocationProvider.swift +++ b/Sentinel/Classes/CustomLocation/Internal/CustomLocationProvider.swift @@ -8,16 +8,12 @@ import Foundation import CoreLocation -class CustomLocationProvider { - - // MARK: - Constants - - private class Constants { - private init() { } - - static let locationMockEnabledKey = "com.infinum.sentinel.locationMock.enabled" - static let locationMockLocationKey = "com.infinum.sentinel.locationMock.location" - } +private enum Constants { + static let locationMockEnabledKey = "com.infinum.sentinel.locationMock.enabled" + static let locationMockLocationKey = "com.infinum.sentinel.locationMock.location" +} + +struct CustomLocationProvider { // MARK: - Private properties @@ -29,10 +25,10 @@ class CustomLocationProvider { self.userDefaults = userDefaults } - // MARK: - Public methods + // MARK: - Internal methods var isCustomLocationUsageEnabled: Bool { - return userDefaults.bool(forKey: Constants.locationMockEnabledKey) + userDefaults.bool(forKey: Constants.locationMockEnabledKey) } var customLocation: CLLocation? { @@ -57,7 +53,7 @@ class CustomLocationProvider { private extension CustomLocationProvider { - private func swizzleCustomLocationMethods() { + func swizzleCustomLocationMethods() { guard let originalMethod = class_getInstanceMethod(CLLocationManager.self, #selector(CLLocationManager.startUpdatingLocation)), let swizzledMethod = class_getInstanceMethod(CLLocationManager.self, #selector(CLLocationManager.startUpdatingCustomLocation)) diff --git a/Sentinel/Classes/EmailSender/EmailSenderErrorView.swift b/Sentinel/Classes/EmailSender/EmailSenderErrorView.swift new file mode 100644 index 0000000..ab94324 --- /dev/null +++ b/Sentinel/Classes/EmailSender/EmailSenderErrorView.swift @@ -0,0 +1,28 @@ +// +// EmailSenderErrorView.swift +// Sentinel +// +// Created by Zvonimir Medak on 13.01.2025.. +// + +import SwiftUI + +struct EmailSenderErrorView: View { + + let alertTitle: String + let alertMessage: String + + var body: some View { + VStack(spacing: 10) { + Text(alertTitle) + .font(.system(size: 17, weight: .bold)) + .multilineTextAlignment(.center) + + Text(alertMessage) + .font(.system(size: 14, weight: .regular)) + .multilineTextAlignment(.center) + } + .frame(maxHeight: .infinity, alignment: .top) + .padding() + } +} diff --git a/Sentinel/Classes/EmailSender/EmailSenderTool.swift b/Sentinel/Classes/EmailSender/EmailSenderTool.swift index dd65c3a..e0027d0 100644 --- a/Sentinel/Classes/EmailSender/EmailSenderTool.swift +++ b/Sentinel/Classes/EmailSender/EmailSenderTool.swift @@ -5,22 +5,23 @@ // Created by Antonijo Bezmalinovic on 22.11.2023.. // -import Foundation +import SwiftUI import MessageUI +/// Error representation of the EmailSender failing to show public enum EmailSenderUnavailableError: Error { case unavailable case custom(title: String, message: String) } -@objcMembers -public final class EmailSenderTool: NSObject, Tool { +/// Tool which gives you the ability to easily integrate email sending with the MessageUI +public struct EmailSenderTool: Tool { - // MARK: - Public properties - + // MARK: - Public properties public var name: String - // MARK: - Private properties - + // MARK: - Private properties private let getter: () -> (MailData) @@ -50,8 +51,7 @@ public final class EmailSenderTool: NSObject, Tool { /// - Parameters: /// - getter: A callback function that returns `MailData` for the email to be sent. /// - name: The name for the Email Sender tool. Defaults to "Email Sender". - /// - alertTitle: The title of the alert that appears if the device is not configured to send emails. Defaults to "Email Not Available". - /// - alertMessage: The message of the alert that appears if the device is not configured to send emails. Defaults to "Your device is not configured to send emails. Please set up an email account in Mail app or use another device." + /// - alertText: The message of the alert that appears if the device is not configured to send emails. Defaults to "Your device is not configured to send emails. Please set up an email account in Mail app or use another device." /// /// - Note: Ensure that the device is configured to send emails, or the user will be prompted with the specified alert. public init( @@ -70,78 +70,17 @@ public final class EmailSenderTool: NSObject, Tool { self.alertTitle = title self.alertMessage = message } - - super.init() } } -// MARK: - Private extension - - public extension EmailSenderTool { - - func presentPreview(from viewController: UIViewController) { - presentEmailSender(viewController: viewController) - } -} - -extension EmailSenderTool: MFMailComposeViewControllerDelegate { - - public func mailComposeController( - _ controller: MFMailComposeViewController, - didFinishWith result: MFMailComposeResult, - error: Error? - ) { - controller.dismiss(animated: true) - } -} -// MARK: - Private extension - - -private extension EmailSenderTool { - - func presentEmailSender(viewController: UIViewController) { - guard MFMailComposeViewController.canSendMail() else { - showEmailAlert(from: viewController) - return + var content: any View { + if EmailSenderView.canSendEmail() { + EmailSenderView(mailData: getter()) + } else { + EmailSenderErrorView(alertTitle: alertTitle, alertMessage: alertMessage) } - showSendEmail(from: viewController) - } - - func showSendEmail(from viewController: UIViewController) { - - let mailData = getter() - - let mail = MFMailComposeViewController() - mail.mailComposeDelegate = self - mail.setToRecipients(mailData.recipients) - mail.setCcRecipients(mailData.ccRecipients) - mail.setBccRecipients(mailData.bccRecipients) - mail.setSubject(mailData.subject) - mail.setMessageBody(mailData.message, isHTML: mailData.isHTML) - - mailData - .attachments - .forEach { - mail.addAttachmentData( - $0.data, - mimeType: $0.mimeType, - fileName: $0.fileName - ) - } - - viewController.present(mail, animated: true) } - - func showEmailAlert(from viewController: UIViewController) { - let alert = UIAlertController( - title: alertTitle, - message: alertMessage, - preferredStyle: .alert - ) - let okAction = UIAlertAction(title: "OK", style: .default) - alert.addAction(okAction) - - viewController.present(alert, animated: true) - } } diff --git a/Sentinel/Classes/EmailSender/EmailSenderView.swift b/Sentinel/Classes/EmailSender/EmailSenderView.swift new file mode 100644 index 0000000..6e4bfb4 --- /dev/null +++ b/Sentinel/Classes/EmailSender/EmailSenderView.swift @@ -0,0 +1,71 @@ +// +// EmailSenderView.swift +// Sentinel +// +// Created by Zvonimir Medak on 10.12.2024.. +// + +import SwiftUI +import MessageUI + +struct EmailSenderView: UIViewControllerRepresentable { + + @Environment(\.presentationMode) var presentationMode + @State var showError: Bool = false + + let mailData: MailData + + func makeUIViewController(context: Context) -> some UIViewController { + let mail = MFMailComposeViewController() + mail.mailComposeDelegate = context.coordinator + mail.setToRecipients(mailData.recipients) + mail.setCcRecipients(mailData.ccRecipients) + mail.setBccRecipients(mailData.bccRecipients) + mail.setSubject(mailData.subject) + mail.setMessageBody(mailData.message, isHTML: mailData.isHTML) + + mailData + .attachments + .forEach { + mail.addAttachmentData( + $0.data, + mimeType: $0.mimeType, + fileName: $0.fileName + ) + } + + return mail as UIViewController + } + + func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) { + // Nothing to do here + } + + static func canSendEmail() -> Bool { + MFMailComposeViewController.canSendMail() + } +} + +extension EmailSenderView { + + final class Coordinator: NSObject, MFMailComposeViewControllerDelegate { + var parent: EmailSenderView + + init(_ parent: EmailSenderView) { + self.parent = parent + } + + func mailComposeController( + _ controller: MFMailComposeViewController, + didFinishWith result: MFMailComposeResult, + error: Error? + ) { + parent.presentationMode.wrappedValue.dismiss() + } + } + + func makeCoordinator() -> Coordinator { + Coordinator(self) + } + +} diff --git a/Sentinel/Classes/EmailSender/MailData.swift b/Sentinel/Classes/EmailSender/MailData.swift index bcd3c2b..dada691 100644 --- a/Sentinel/Classes/EmailSender/MailData.swift +++ b/Sentinel/Classes/EmailSender/MailData.swift @@ -7,6 +7,7 @@ import Foundation +/// Item which represents the mail attachment public struct Attachment { let data: Data diff --git a/Sentinel/Classes/TextEditing/TextEditing.storyboard b/Sentinel/Classes/TextEditing/TextEditing.storyboard deleted file mode 100644 index 9591c9d..0000000 --- a/Sentinel/Classes/TextEditing/TextEditing.storyboard +++ /dev/null @@ -1,90 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Sentinel/Classes/TextEditing/TextEditingTool.swift b/Sentinel/Classes/TextEditing/TextEditingTool.swift index 39447f2..a716116 100644 --- a/Sentinel/Classes/TextEditing/TextEditingTool.swift +++ b/Sentinel/Classes/TextEditing/TextEditingTool.swift @@ -5,19 +5,21 @@ // Created by Vlaho Poluta on 31/07/2020. // -import UIKit +import SwiftUI + +/// Tool which gives you the ability to edit a property on the fly +/// +/// The property can be edited in the UserDefaults or by setting a custom setter/getter +public struct TextEditingTool: Tool { -@objcMembers -public class TextEditingTool: NSObject, Tool { - // MARK: - Public properties public let name: String - + // MARK: - Private properties - private let setter: (String) -> () - private let getter: () -> (String) + private let setter: (String) -> Void + private let getter: () -> String private let userDefaults: UserDefaults private let userDefaultsKey: String? @@ -35,19 +37,16 @@ public class TextEditingTool: NSObject, Tool { self.getter = getter self.userDefaults = userDefaults self.userDefaultsKey = userDefaultsKey - super.init() loadStoredValue() } - - // MARK: - Public methods - - public func presentPreview(from viewController: UIViewController) { - let textEditing = TextEditingViewController.create( - withTitle: name, - setter: store(newValue:), - getter: getter - ) - viewController.navigationController?.pushViewController(textEditing, animated: true) +} + +// MARK: - UI + +public extension TextEditingTool { + + var content: any View { + TextEditingToolView(viewModel: .init(value: getter(), title: name, didPressSave: store(newValue:))) } } diff --git a/Sentinel/Classes/TextEditing/TextEditingToolView.swift b/Sentinel/Classes/TextEditing/TextEditingToolView.swift new file mode 100644 index 0000000..b0b945e --- /dev/null +++ b/Sentinel/Classes/TextEditing/TextEditingToolView.swift @@ -0,0 +1,30 @@ +// +// TextEditingToolView.swift +// Sentinel +// +// Created by Zvonimir Medak on 28.11.2024.. +// + +import SwiftUI + +struct TextEditingToolView: View { + + @Environment(\.presentationMode) var presentationMode: Binding + @ObservedObject var viewModel: TextEditingToolViewModel + + var body: some View { + VStack(spacing: 10) { + TextField(viewModel.title, text: $viewModel.value) + .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading) + + Button(action: { + viewModel.didPressSave(viewModel.value) + presentationMode.wrappedValue.dismiss() + }) { + Text("Save") + } + } + .padding(.horizontal, 16) + .navigationTitle(viewModel.title) + } +} diff --git a/Sentinel/Classes/TextEditing/TextEditingToolViewModel.swift b/Sentinel/Classes/TextEditing/TextEditingToolViewModel.swift new file mode 100644 index 0000000..31552e9 --- /dev/null +++ b/Sentinel/Classes/TextEditing/TextEditingToolViewModel.swift @@ -0,0 +1,25 @@ +// +// TextEditingToolViewModel.swift +// Sentinel +// +// Created by Zvonimir Medak on 28.11.2024.. +// + +import Foundation + +final class TextEditingToolViewModel: ObservableObject { + + // MARK: - Internal properties + + @Published var value: String + let title: String + let didPressSave: (String) -> Void + + // MARK: - Init + + init(value: String, title: String, didPressSave: @escaping (String) -> Void) { + self.value = value + self.title = title + self.didPressSave = didPressSave + } +} diff --git a/Sentinel/Classes/TextEditing/TextEditingViewController.swift b/Sentinel/Classes/TextEditing/TextEditingViewController.swift deleted file mode 100644 index 9a37a5e..0000000 --- a/Sentinel/Classes/TextEditing/TextEditingViewController.swift +++ /dev/null @@ -1,55 +0,0 @@ -// -// TextEditingViewController.swift -// Sentinel -// -// Created by Vlaho Poluta on 31/07/2020. -// - -import UIKit - -extension UIStoryboard { - static var textEditing: UIStoryboard { UIStoryboard(name: "TextEditing", bundle: .sentinel) } -} - -class TextEditingViewController: UIViewController { - - // MARK: - Private properties - - private var name: String! - private var setter: ((String) -> ())! - private var getter: (() -> (String))! - - // MARK: - IBOutlets - - @IBOutlet private var titleLabel: UILabel! - @IBOutlet private var valueTextView: UITextView! - - // MARK: - Internal methods - - static func create( - withTitle name: String, - setter: @escaping (String) -> (), - getter: @escaping () -> (String) - ) -> TextEditingViewController { - let viewController = UIStoryboard.textEditing.instantiateViewController(ofType: TextEditingViewController.self) - viewController.name = name - viewController.setter = setter - viewController.getter = getter - return viewController - } - - // MARK: - Lifecycle - - override func viewDidLoad() { - super.viewDidLoad() - titleLabel.text = name - valueTextView.text = getter() - } - - // MARK: - IBActions - - @IBAction private func didSelectSave() { - setter(valueTextView.text) - navigationController?.popViewController(animated: true) - } -} diff --git a/Sentinel/Classes/UserDefaults/UserDefaults.storyboard b/Sentinel/Classes/UserDefaults/UserDefaults.storyboard deleted file mode 100644 index 568dfcc..0000000 --- a/Sentinel/Classes/UserDefaults/UserDefaults.storyboard +++ /dev/null @@ -1,96 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Sentinel/Classes/UserDefaults/UserDefaultsTool.swift b/Sentinel/Classes/UserDefaults/UserDefaultsTool.swift index 0e8caa6..4fda500 100644 --- a/Sentinel/Classes/UserDefaults/UserDefaultsTool.swift +++ b/Sentinel/Classes/UserDefaults/UserDefaultsTool.swift @@ -5,11 +5,11 @@ // Created by Vlaho Poluta on 30/07/2020. // -import UIKit +import SwiftUI + +/// Tool which gives the ability to list out all of the UserDefaults properties and delete them +public struct UserDefaultsTool: Tool { -@objcMembers -public class UserDefaultsTool: NSObject, Tool { - // MARK: - Public properties public let name: String @@ -24,29 +24,34 @@ public class UserDefaultsTool: NSObject, Tool { self.name = name self.userDefaults = userDefaults } - - // MARK: - Public methods - - public func presentPreview(from viewController: UIViewController) { - let toolTable = createToolTable(with: userDefaults, viewController: viewController) - toolTable.presentPreview(from: viewController) +} + +// MARK: - UI + +public extension UserDefaultsTool { + + var content: any View { + SentinelListView(title: name, items: createToolTable(with: userDefaults).sections) } } // MARK: - Internal methods private extension UserDefaultsTool { - func createToolTable(with userDefaults: UserDefaults, viewController: UIViewController) -> ToolTable { - let items = userDefaults.dictionaryRepresentation().map { (key, value) in - NavigationToolTableItem(title: key) { (viewControoler) in - let userDefaultsViewController = UserDefaultsViewController.create( - withTitle: key, - details: String(describing: value) + + func createToolTable(with userDefaults: UserDefaults) -> ToolTable { + let items = userDefaults.dictionaryRepresentation() + .sorted { $0.key < $1.key } + .map { (key, value) in + ToolTableItem.navigation( + NavigationToolItem( + title: key, + didSelect: { + UserDefaultsToolView(viewModel: .init(value: String(describing: value), title: key, userDefaults: userDefaults)) + } + ) ) - viewController.navigationController?.pushViewController(userDefaultsViewController, animated: true) } - } - .sorted { $0.title < $1.title } let section = ToolTableSection(items: items) return ToolTable(name: name, sections: [section]) diff --git a/Sentinel/Classes/UserDefaults/UserDefaultsToolView.swift b/Sentinel/Classes/UserDefaults/UserDefaultsToolView.swift new file mode 100644 index 0000000..d4fc1ce --- /dev/null +++ b/Sentinel/Classes/UserDefaults/UserDefaultsToolView.swift @@ -0,0 +1,33 @@ +// +// UserDefaultsToolView.swift +// Sentinel +// +// Created by Zvonimir Medak on 28.11.2024.. +// + +import SwiftUI + +struct UserDefaultsToolView: View { + + @Environment(\.presentationMode) var presentationMode: Binding + @ObservedObject var viewModel: UserDefaultsToolViewModel + + var body: some View { + VStack(spacing: 10) { + Text(viewModel.value) + .contextMenu(ContextMenu(menuItems: { + Button("Copy", action: { + UIPasteboard.general.string = viewModel.value + }) + })) + .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading) + + Button(action: { + viewModel.didPressDelete() + presentationMode.wrappedValue.dismiss() + }, label: { Text("Delete") }) + } + .padding(.horizontal, 16) + .navigationTitle(viewModel.title) + } +} diff --git a/Sentinel/Classes/UserDefaults/UserDefaultsToolViewModel.swift b/Sentinel/Classes/UserDefaults/UserDefaultsToolViewModel.swift new file mode 100644 index 0000000..7c2af91 --- /dev/null +++ b/Sentinel/Classes/UserDefaults/UserDefaultsToolViewModel.swift @@ -0,0 +1,36 @@ +// +// UserDefaultsToolViewModel.swift +// Sentinel +// +// Created by Zvonimir Medak on 28.11.2024.. +// + +import Foundation + +final class UserDefaultsToolViewModel: ObservableObject { + + // MARK: - Internal properties + + let value: String + let title: String + let userDefaults: UserDefaults + + // MARK: - Init + + init(value: String, title: String, userDefaults: UserDefaults = .standard) { + self.value = value + self.title = title + self.userDefaults = userDefaults + } + +} + +// MARK: - Internal methods + +extension UserDefaultsToolViewModel { + + func didPressDelete() { + UserDefaults.standard.removeObject(forKey: title) + } + +} diff --git a/Sentinel/Classes/UserDefaults/UserDefaultsViewController.swift b/Sentinel/Classes/UserDefaults/UserDefaultsViewController.swift deleted file mode 100644 index 25b0bf9..0000000 --- a/Sentinel/Classes/UserDefaults/UserDefaultsViewController.swift +++ /dev/null @@ -1,50 +0,0 @@ -// -// UserDefaultsViewController.swift -// Sentinel -// -// Created by Vlaho Poluta on 30/07/2020. -// - -import UIKit - -extension UIStoryboard { - static var userDefaults: UIStoryboard { UIStoryboard(name: "UserDefaults", bundle: .sentinel) } -} - -class UserDefaultsViewController: UIViewController { - - // MARK: - Private properties - - private var text: String! - private var details: String! - - // MARK: - IBOutlets - - @IBOutlet private var titleLabel: UILabel! - @IBOutlet private var detailsTextView: UITextView! - - // MARK: - Internal methods - - static func create(withTitle title: String, details: String) -> UserDefaultsViewController { - let viewController = UIStoryboard.userDefaults.instantiateViewController(ofType: UserDefaultsViewController.self) - viewController.text = title - viewController.details = details - return viewController - } - - // MARK: - Lifecycle - - override func viewDidLoad() { - super.viewDidLoad() - titleLabel.text = text - detailsTextView.text = details - } - - // MARK: - Actions - - @IBAction func didSelectDelete(_ sender: Any) { - guard let key = titleLabel.text else { return } - UserDefaults.standard.removeObject(forKey: key) - navigationController?.popViewController(animated: true) - } -}