diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..dc5c981972f2240ba620ca3b4f5bb9108d8157d9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ + +.DS_Store +PrivacyDemo.xcodeproj/project.xcworkspace/xcuserdata/ahmedshehata.xcuserdatad/UserInterfaceState.xcuserstate diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..8551215fa5b651bb93a247cde5ab89d4b8f5f7e6 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +Copyright (c) 2022, xx network SEZC + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/PrivacyDemo.xcodeproj/project.pbxproj b/PrivacyDemo.xcodeproj/project.pbxproj index 9b8442d2c0d79735fbcd0946466a9d2ed5c83a16..5d93d38b038a661bff1be327a3b7f05dc90a08d4 100644 --- a/PrivacyDemo.xcodeproj/project.pbxproj +++ b/PrivacyDemo.xcodeproj/project.pbxproj @@ -23,6 +23,8 @@ 6CB9D340284EBFC6000D53C1 /* Password+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CB9D33F284EBFC6000D53C1 /* Password+Extension.swift */; }; 6CB9D342284EF4B9000D53C1 /* FAQ.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CB9D341284EF4B9000D53C1 /* FAQ.swift */; }; 6CB9D346284F0CE5000D53C1 /* MessageContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CB9D345284F0CE5000D53C1 /* MessageContent.swift */; }; + 6CC614C128754E5200354B01 /* ProviderNameConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CC614C028754E5200354B01 /* ProviderNameConstants.swift */; }; + 6CCAB02028750CDC0018315C /* RequestTypeConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CCAB01F28750CDC0018315C /* RequestTypeConstants.swift */; }; 6CE7BA57284930A0003DE341 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CE7BA56284930A0003DE341 /* AppDelegate.swift */; }; 6CE7BA59284930A0003DE341 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CE7BA58284930A0003DE341 /* SceneDelegate.swift */; }; 6CE7BA60284930A2003DE341 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6CE7BA5F284930A2003DE341 /* Assets.xcassets */; }; @@ -54,6 +56,8 @@ 6CB9D33F284EBFC6000D53C1 /* Password+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Password+Extension.swift"; sourceTree = "<group>"; }; 6CB9D341284EF4B9000D53C1 /* FAQ.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAQ.swift; sourceTree = "<group>"; }; 6CB9D345284F0CE5000D53C1 /* MessageContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageContent.swift; sourceTree = "<group>"; }; + 6CC614C028754E5200354B01 /* ProviderNameConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProviderNameConstants.swift; sourceTree = "<group>"; }; + 6CCAB01F28750CDC0018315C /* RequestTypeConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RequestTypeConstants.swift; sourceTree = "<group>"; }; 6CE7BA53284930A0003DE341 /* PrivacyDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PrivacyDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 6CE7BA56284930A0003DE341 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; }; 6CE7BA58284930A0003DE341 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; }; @@ -197,6 +201,8 @@ 6CE7BA84284979B5003DE341 /* ColorsConstants.swift */, 6CE7BA8928497A43003DE341 /* AppConstants.swift */, 6CE7BA8B28497CDD003DE341 /* StoryboardConstants.swift */, + 6CCAB01F28750CDC0018315C /* RequestTypeConstants.swift */, + 6CC614C028754E5200354B01 /* ProviderNameConstants.swift */, ); path = Constants; sourceTree = "<group>"; @@ -327,6 +333,7 @@ buildActionMask = 2147483647; files = ( 6CE7BA57284930A0003DE341 /* AppDelegate.swift in Sources */, + 6CCAB02028750CDC0018315C /* RequestTypeConstants.swift in Sources */, 6CABA00D284D509A00F0200B /* ProvidersViewController.swift in Sources */, 6CB9D339284EAED3000D53C1 /* ElixxirHandler.swift in Sources */, 6CE7BA7828493DFC003DE341 /* ChatViewController.swift in Sources */, @@ -335,6 +342,7 @@ 6CE7BA85284979B5003DE341 /* ColorsConstants.swift in Sources */, 6CB9D342284EF4B9000D53C1 /* FAQ.swift in Sources */, 6CB9D33C284EBF02000D53C1 /* AlertsHandler.swift in Sources */, + 6CC614C128754E5200354B01 /* ProviderNameConstants.swift in Sources */, 6CB9D340284EBFC6000D53C1 /* Password+Extension.swift in Sources */, 6CB9D33E284EBF79000D53C1 /* LoadingIndicatorHandler.swift in Sources */, 6CB9D346284F0CE5000D53C1 /* MessageContent.swift in Sources */, @@ -412,7 +420,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 15.4; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; @@ -466,7 +474,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 15.4; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; SDKROOT = iphoneos; @@ -482,12 +490,15 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; + CURRENT_PROJECT_VERSION = 2; + DEVELOPMENT_TEAM = S6JDM2WW29; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = PrivacyDemo/AppResources/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = "Shielded Help"; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; INFOPLIST_KEY_UIMainStoryboardFile = Splash; + INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; LD_RUNPATH_SEARCH_PATHS = ( @@ -495,7 +506,7 @@ "@executable_path/Frameworks", ); MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.elixxir.PrivacyDemo.PrivacyDemo; + PRODUCT_BUNDLE_IDENTIFIER = com.elixxir.shieldedhelp; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; @@ -509,12 +520,15 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; + CURRENT_PROJECT_VERSION = 2; + DEVELOPMENT_TEAM = S6JDM2WW29; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = PrivacyDemo/AppResources/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = "Shielded Help"; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; INFOPLIST_KEY_UIMainStoryboardFile = Splash; + INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; LD_RUNPATH_SEARCH_PATHS = ( @@ -522,7 +536,7 @@ "@executable_path/Frameworks", ); MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.elixxir.PrivacyDemo.PrivacyDemo; + PRODUCT_BUNDLE_IDENTIFIER = com.elixxir.shieldedhelp; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; @@ -566,7 +580,7 @@ isa = XCRemoteSwiftPackageReference; repositoryURL = "https://git.xx.network/elixxir/elixxir-dapps-sdk-swift"; requirement = { - branch = integration; + branch = main; kind = branch; }; }; diff --git a/PrivacyDemo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/PrivacyDemo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index fd6a8d94733f241a9ab9dee6413a66a555f10870..c7810b8a72889dd2d7c54f836ed9e36f21abd18a 100644 --- a/PrivacyDemo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/PrivacyDemo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -5,8 +5,8 @@ "kind" : "remoteSourceControl", "location" : "https://git.xx.network/elixxir/elixxir-dapps-sdk-swift", "state" : { - "branch" : "integration", - "revision" : "a03c3e4393b7008600ab0a61266289773dec6909" + "branch" : "main", + "revision" : "f428d6b3c5416783779968a6121f0a0678ac911f" } }, { diff --git a/PrivacyDemo.xcodeproj/project.xcworkspace/xcuserdata/ahmedshehata.xcuserdatad/UserInterfaceState.xcuserstate b/PrivacyDemo.xcodeproj/project.xcworkspace/xcuserdata/ahmedshehata.xcuserdatad/UserInterfaceState.xcuserstate index fab6dd70ff9622c5b325813e8aedea17b098ddd2..51a88d6e0270dad36a564c12284a2c285d2115b3 100644 Binary files a/PrivacyDemo.xcodeproj/project.xcworkspace/xcuserdata/ahmedshehata.xcuserdatad/UserInterfaceState.xcuserstate and b/PrivacyDemo.xcodeproj/project.xcworkspace/xcuserdata/ahmedshehata.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/PrivacyDemo.xcodeproj/xcuserdata/ahmedshehata.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/PrivacyDemo.xcodeproj/xcuserdata/ahmedshehata.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist index 194e69ed4f13baf589fc60d43fc231c907d95bcd..7eafca7b1805ccfc0f96f988734ed868cd9db9af 100644 --- a/PrivacyDemo.xcodeproj/xcuserdata/ahmedshehata.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +++ b/PrivacyDemo.xcodeproj/xcuserdata/ahmedshehata.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -3,4 +3,118 @@ uuid = "11772AE9-A52D-4B02-92ED-3C9FB13D23BE" type = "1" version = "2.0"> + <Breakpoints> + <BreakpointProxy + BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint"> + <BreakpointContent + uuid = "47C5D786-B61E-47A7-AAE3-8FE75941290B" + shouldBeEnabled = "No" + ignoreCount = "0" + continueAfterRunningActions = "No" + filePath = "PrivacyDemo/Chat/ChatViewController.swift" + startingColumnNumber = "9223372036854775807" + endingColumnNumber = "9223372036854775807" + startingLineNumber = "168" + endingLineNumber = "168" + landmarkName = "handleError(_:)" + landmarkType = "7"> + </BreakpointContent> + </BreakpointProxy> + <BreakpointProxy + BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint"> + <BreakpointContent + uuid = "3F6894AF-21B3-4F30-AC90-E2F8F32166AC" + shouldBeEnabled = "No" + ignoreCount = "0" + continueAfterRunningActions = "No" + filePath = "PrivacyDemo/Chat/ChatViewController.swift" + startingColumnNumber = "9223372036854775807" + endingColumnNumber = "9223372036854775807" + startingLineNumber = "340" + endingLineNumber = "340" + landmarkName = "didSelectURL(_:)" + landmarkType = "9"> + </BreakpointContent> + </BreakpointProxy> + <BreakpointProxy + BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint"> + <BreakpointContent + uuid = "BE0B1388-23FC-425C-8A54-2B63535F28E2" + shouldBeEnabled = "Yes" + ignoreCount = "0" + continueAfterRunningActions = "No" + filePath = "PrivacyDemo/Chat/ChatViewController.swift" + startingColumnNumber = "9223372036854775807" + endingColumnNumber = "9223372036854775807" + startingLineNumber = "198" + endingLineNumber = "198" + landmarkName = "setSuggestedProviderValues(from:)" + landmarkType = "7"> + </BreakpointContent> + </BreakpointProxy> + <BreakpointProxy + BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint"> + <BreakpointContent + uuid = "51E9DF34-9929-4107-93CA-A1B3AF258AFC" + shouldBeEnabled = "Yes" + ignoreCount = "0" + continueAfterRunningActions = "No" + filePath = "PrivacyDemo/PrivateProviders/ProvidersViewController.swift" + startingColumnNumber = "9223372036854775807" + endingColumnNumber = "9223372036854775807" + startingLineNumber = "206" + endingLineNumber = "206" + landmarkName = "setupProvidersButtonMenu(initialSelection:)" + landmarkType = "7"> + </BreakpointContent> + </BreakpointProxy> + <BreakpointProxy + BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint"> + <BreakpointContent + uuid = "9E1AC49C-AFBA-4B55-9927-EB937625FFCC" + shouldBeEnabled = "Yes" + ignoreCount = "0" + continueAfterRunningActions = "No" + filePath = "PrivacyDemo/PrivateProviders/ProvidersViewController.swift" + startingColumnNumber = "9223372036854775807" + endingColumnNumber = "9223372036854775807" + startingLineNumber = "132" + endingLineNumber = "132" + landmarkName = "prefillIfNecessary()" + landmarkType = "7"> + <Locations> + <Location + uuid = "9E1AC49C-AFBA-4B55-9927-EB937625FFCC - d21fedeed63f3745" + shouldBeEnabled = "Yes" + ignoreCount = "0" + continueAfterRunningActions = "No" + symbolName = "PrivacyDemo.ProvidersViewController.prefillIfNecessary() -> ()" + moduleName = "PrivacyDemo" + usesParentBreakpointCondition = "Yes" + urlString = "file:///Users/ahmedshehata/XR/elixxir-dapp-demo/PrivacyDemo/PrivateProviders/ProvidersViewController.swift" + startingColumnNumber = "9223372036854775807" + endingColumnNumber = "9223372036854775807" + startingLineNumber = "132" + endingLineNumber = "132" + offsetFromSymbolStart = "136"> + </Location> + <Location + uuid = "9E1AC49C-AFBA-4B55-9927-EB937625FFCC - d21fedeed63f3745" + shouldBeEnabled = "Yes" + ignoreCount = "0" + continueAfterRunningActions = "No" + symbolName = "PrivacyDemo.ProvidersViewController.prefillIfNecessary() -> ()" + moduleName = "PrivacyDemo" + usesParentBreakpointCondition = "Yes" + urlString = "file:///Users/ahmedshehata/XR/elixxir-dapp-demo/PrivacyDemo/PrivateProviders/ProvidersViewController.swift" + startingColumnNumber = "9223372036854775807" + endingColumnNumber = "9223372036854775807" + startingLineNumber = "132" + endingLineNumber = "132" + offsetFromSymbolStart = "196"> + </Location> + </Locations> + </BreakpointContent> + </BreakpointProxy> + </Breakpoints> </Bucket> diff --git a/PrivacyDemo/AppResources/Base.lproj/LaunchScreen.storyboard b/PrivacyDemo/AppResources/Base.lproj/LaunchScreen.storyboard index c295d37af1822a1888d4a8b5a67d1f992220984a..aa8dea1cdc2c39a06e2d40bdca38586b9cdbd540 100644 --- a/PrivacyDemo/AppResources/Base.lproj/LaunchScreen.storyboard +++ b/PrivacyDemo/AppResources/Base.lproj/LaunchScreen.storyboard @@ -20,13 +20,13 @@ <rect key="frame" x="28.333333333333343" y="326.66666666666669" width="333.33333333333326" height="200.66666666666669"/> <subviews> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Shielded Help" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="VEv-7L-Rqy"> - <rect key="frame" x="20" y="19.999999999999996" width="293.33333333333331" height="34.666666666666657"/> - <fontDescription key="fontDescription" name="Menlo-Bold" family="Menlo" pointSize="40"/> + <rect key="frame" x="20" y="20" width="293.33333333333331" height="72.333333333333329"/> + <fontDescription key="fontDescription" name="Helvetica-Bold" family="Helvetica" pointSize="40"/> <nil key="textColor"/> <nil key="highlightedColor"/> </label> <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="Shield" translatesAutoresizingMaskIntoConstraints="NO" id="OAP-yW-yO6"> - <rect key="frame" x="107.66666666666669" y="62.666666666666629" width="118" height="118"/> + <rect key="frame" x="126.66666666666669" y="100.33333333333331" width="80" height="80.333333333333314"/> <constraints> <constraint firstAttribute="width" secondItem="OAP-yW-yO6" secondAttribute="height" multiplier="1:1" id="T6P-YG-bf7"/> </constraints> @@ -34,6 +34,7 @@ </subviews> <color key="backgroundColor" systemColor="systemBackgroundColor"/> <constraints> + <constraint firstItem="OAP-yW-yO6" firstAttribute="height" secondItem="Lif-fS-EPO" secondAttribute="height" multiplier="0.4" id="BFQ-Cg-M0c"/> <constraint firstAttribute="bottom" secondItem="OAP-yW-yO6" secondAttribute="bottom" constant="20.000000000000057" id="FeM-WW-YQn"/> <constraint firstItem="VEv-7L-Rqy" firstAttribute="top" secondItem="Lif-fS-EPO" secondAttribute="top" constant="20" symbolic="YES" id="GDZ-fj-fQl"/> <constraint firstItem="OAP-yW-yO6" firstAttribute="centerX" secondItem="Lif-fS-EPO" secondAttribute="centerX" id="Mll-dB-W8F"/> diff --git a/PrivacyDemo/Chat/ChatViewController.swift b/PrivacyDemo/Chat/ChatViewController.swift index 62c54ed3d8e036af2e62ee5ba63244c88078d893..748a3e467dba5558738262675676fbd4d0588f59 100644 --- a/PrivacyDemo/Chat/ChatViewController.swift +++ b/PrivacyDemo/Chat/ChatViewController.swift @@ -2,6 +2,7 @@ import UIKit import MessageKit import InputBarAccessoryView import ElixxirDAppsSDK +import SafariServices class ChatViewController: MessagesViewController { @@ -9,11 +10,15 @@ class ChatViewController: MessagesViewController { private lazy var messageList: [ChatMessage] = [] private let helperUser = User(senderId: Constants.helperUserId, - displayName: "Your anonymouse helper") + displayName: "Your anonymous helper") private let currentUser = User(senderId: Constants.currentUserId, displayName: "You") private var connection: Connection? private var loadingIndicator: LoadingIndicatorView! + private var suggestedProviders = [String: (name:String?, requestType: String?, code: String?)?]() + private let receivedChatMessageAttributes = [NSAttributedString.Key.font: UIFont(name: "Helvetica", size: 16.0)!] + private let sentChatMessageAttributes = [NSAttributedString.Key.font: UIFont(name: "Helvetica", size: 16.0)!, + NSAttributedString.Key.foregroundColor: UIColor.white] // MARK: - Lifecycle @@ -37,12 +42,12 @@ class ChatViewController: MessagesViewController { // MARK: - SDK func sendE2EMessage(message: String) { - DispatchQueue.global(qos: .background).async { [weak self] in + DispatchQueue.global(qos: .userInteractive).async { [weak self] in guard let self = self else { return } do { let sendReport = try self.connection!.send(messageType: 1, payload: Data(message.utf8)) - try ElixxirHandler.shared.client!.waitForDelivery(roundList: sendReport, timeoutMS: 30_000) { result in + try ElixxirHandler.shared.client!.waitForDelivery(report: sendReport, timeoutMS: 30_000) { result in DispatchQueue.main.async { [weak self] in guard let self = self else { return } self.handleMessageDeliveryResult(result, message: message) @@ -60,15 +65,16 @@ class ChatViewController: MessagesViewController { print("JK E2E delivered with roundResults reposne ",roundResults) messageInputBar.sendButton.stopAnimating() messageInputBar.inputTextView.placeholder = "Aa" - let message = ChatMessage(kind: .text(message), user: currentUser, messageId: UUID().uuidString, date: Date.now) - insertMessage(message) + let attributedMessage = NSAttributedString(string: message, attributes: sentChatMessageAttributes) + let chatMessage = ChatMessage(kind: .attributedText(attributedMessage), user: currentUser, messageId: UUID().uuidString, date: Date.now) + insertMessage(chatMessage) case .notDelivered: self.handleError("Message sending timed out, please try again.") } } func listenToMessages() { - DispatchQueue.global(qos: .background).async { [weak self] in + DispatchQueue.global(qos: .userInteractive).async { [weak self] in guard let self = self else { return } self.connection!.listen(messageType: 1) { message in DispatchQueue.main.async { [weak self] in @@ -79,10 +85,22 @@ class ChatViewController: MessagesViewController { } } - func handleReceivedMessage(_ message: Data) { - let msg = try! JSONDecoder().decode(Message.self, from: message) - let payload = String(decoding: msg.payload, as: UTF8.self) - let chatMessage = ChatMessage(kind: .text(payload), + func handleReceivedMessage(_ message: Message) { + let payload = String(decoding: message.payload, as: UTF8.self) + let pattern = "<[^\"]+>" + var replacement = "@Provider" + if let rangeOfValues = payload.range(of: pattern, options: .regularExpression) { + let valuesText = payload[rangeOfValues] + let name = setSuggestedProviderValues(from: valuesText) + replacement = "@\(name)" + } + let formattedPayload = payload.replacingOccurrences( + of: pattern, + with: replacement, + options: .regularExpression + ) + let attributedPayload = NSAttributedString(string: formattedPayload, attributes: receivedChatMessageAttributes) + let chatMessage = ChatMessage(kind: .attributedText(attributedPayload), user: self.helperUser, messageId: UUID().uuidString, date: .now) @@ -90,13 +108,15 @@ class ChatViewController: MessagesViewController { } func initConnection() { - loadingIndicator.startAnimating(inView: self.view, shouldDisableInteraction: true, text: "Initiating...") - DispatchQueue.global(qos: .background).async { [weak self] in + loadingIndicator.startAnimating(inView: self.view, shouldDisableInteraction: true, text: "Initiating & securing connection") + DispatchQueue.global(qos: .userInteractive).async { [weak self] in guard let self = self else { return } do { + let clientE2E = try ClientE2ELogin.live(with: ElixxirHandler.shared.client!) + self.connection = try ElixxirHandler.shared.client!.connect(withAuthentication: false, recipientContact: Data(Constants.chatRecipentContact.utf8), - myIdentity: ElixxirHandler.shared.myIdentityMarshalled) + e2eId: clientE2E.getId()) DispatchQueue.main.async { [weak self] in guard let self = self else { return } self.loadingIndicator.stopAnimating() @@ -121,6 +141,7 @@ class ChatViewController: MessagesViewController { messagesCollectionView.messagesDataSource = self messagesCollectionView.messagesLayoutDelegate = self messagesCollectionView.messagesDisplayDelegate = self + messagesCollectionView.messageCellDelegate = self messagesCollectionView.contentInset.top = 40 scrollsToLastItemOnKeyboardBeginsEditing = true maintainPositionOnInputBarHeightChanged = true @@ -148,8 +169,8 @@ class ChatViewController: MessagesViewController { } func loadFirstMessages() { - let welcomeText = "Welcome to the anonymouse help chat" - let welcomeMessage = ChatMessage(kind: .text(welcomeText), + let welcomeText = NSAttributedString(string: "Welcome to Shielded Help. We're glad you're here. You will be connected to a live hotline representative within the next few minutes.", attributes: receivedChatMessageAttributes) + let welcomeMessage = ChatMessage(kind: .attributedText(welcomeText), user: self.helperUser, messageId: UUID().uuidString, date: .now) @@ -170,6 +191,18 @@ class ChatViewController: MessagesViewController { }) } + // Extracts values from format <name:req:code> + func setSuggestedProviderValues(from text: Substring) -> String { + let text = String(text) + let suggestedProviderValues = text.components(separatedBy: ":") + let name = String(suggestedProviderValues[0].dropFirst()) + let requestType = suggestedProviderValues[1] + let code = String(suggestedProviderValues[2].dropLast()) + let displayName = name.filter {!$0.isWhitespace} + suggestedProviders[displayName] = (name.lowercased().filter {!$0.isWhitespace},requestType,code) + return displayName + } + func isLastSectionVisible() -> Bool { guard !messageList.isEmpty else { return false } let lastIndexPath = IndexPath(item: 0, section: messageList.count - 1) @@ -209,7 +242,7 @@ extension ChatViewController: MessagesDataSource { func cellTopLabelAttributedText(for message: MessageType, at indexPath: IndexPath) -> NSAttributedString? { if isTimeLabelVisible(at: indexPath) { - return NSAttributedString(string: MessageKitDateFormatter.shared.string(from: message.sentDate), attributes: [NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 10), NSAttributedString.Key.foregroundColor: UIColor.darkGray]) + return NSAttributedString(string: MessageKitDateFormatter.shared.string(from: message.sentDate), attributes: [NSAttributedString.Key.font: UIFont(name: "Helvetica Bold", size: 10.0)!, NSAttributedString.Key.foregroundColor: UIColor.darkGray]) } return nil } @@ -217,7 +250,7 @@ extension ChatViewController: MessagesDataSource { func messageTopLabelAttributedText(for message: MessageType, at indexPath: IndexPath) -> NSAttributedString? { if !isPreviousMessageSameSender(at: indexPath) { let name = message.sender.displayName - return NSAttributedString(string: name, attributes: [NSAttributedString.Key.font: UIFont.preferredFont(forTextStyle: .caption1)]) + return NSAttributedString(string: name, attributes: [NSAttributedString.Key.font: UIFont(name: "Helvetica", size: 10.0)!]) } return nil } @@ -248,7 +281,7 @@ extension ChatViewController: InputBarAccessoryViewDelegate { inputBar.inputTextView.text = String() inputBar.invalidatePlugins() inputBar.sendButton.startAnimating() - inputBar.inputTextView.placeholder = "Sending..." + inputBar.inputTextView.placeholder = "Sending via secure channel..." inputBar.inputTextView.resignFirstResponder() sendE2EMessage(message: textToSend ?? "") } @@ -282,4 +315,39 @@ extension ChatViewController: MessagesDisplayDelegate, MessagesLayoutDelegate { func messageTopLabelHeight(for message: MessageType, at indexPath: IndexPath, in messagesCollectionView: MessagesCollectionView) -> CGFloat { return !isPreviousMessageSameSender(at: indexPath) ? 20 : 0 } + + func enabledDetectors(for message: MessageType, at indexPath: IndexPath, in messagesCollectionView: MessagesCollectionView) -> [DetectorType] { + if !isFromCurrentSender(message: message) { + return [.url,.mention] + } + return [.url] + } + + func detectorAttributes(for detector: DetectorType, and message: MessageType, at indexPath: IndexPath) -> [NSAttributedString.Key : Any] { + if detector == .mention && !isFromCurrentSender(message: message) { + return [NSAttributedString.Key.font: UIFont(name: "Helvetica", size: 14.0)!, + NSAttributedString.Key.foregroundColor: Constants.AppColors.appMainColor] + } + return [NSAttributedString.Key.foregroundColor : Constants.AppColors.appMainColor] + } +} + +// MARK: - Message Cell Delegate + +extension ChatViewController: MessageCellDelegate { + func didSelectURL(_ url: URL) { + let safariController = SFSafariViewController(url: url) + present(safariController, animated: true, completion: nil) + } + + func didSelectMention(_ mention: String) { + let providerName = String(mention.dropFirst()) + if let provider = suggestedProviders[providerName] { + let providersStoryBoard = UIStoryboard(name: Constants.Storyboard.providers, bundle: nil) + guard let providersViewController = providersStoryBoard.instantiateViewController(withIdentifier: Constants.StoryboardId.providersViewController) as? ProvidersViewController else { return } + providersViewController.suggestedProvider = provider + self.present(providersViewController, animated: true) + } + } } + diff --git a/PrivacyDemo/FAQ/FAQs.storyboard b/PrivacyDemo/FAQ/FAQs.storyboard index 4cb1e20dc9283a3f9dbb9c1aa94b48a6549ab05c..9d0363b08e1a9a05ad9b464b035e8c003bb069aa 100644 --- a/PrivacyDemo/FAQ/FAQs.storyboard +++ b/PrivacyDemo/FAQ/FAQs.storyboard @@ -20,15 +20,15 @@ <rect key="frame" x="0.0" y="34" width="414" height="100"/> <subviews> <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="Shield" translatesAutoresizingMaskIntoConstraints="NO" id="gNr-b7-xEt"> - <rect key="frame" x="147" y="25" width="50" height="50"/> + <rect key="frame" x="144.5" y="25" width="50" height="50"/> <constraints> <constraint firstAttribute="height" constant="50" id="OXv-4y-wkU"/> <constraint firstAttribute="width" secondItem="gNr-b7-xEt" secondAttribute="height" multiplier="1:1" id="ttb-SA-9bu"/> </constraints> </imageView> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="FAQs" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="JeP-Cg-jmC"> - <rect key="frame" x="202" y="35" width="60.5" height="30"/> - <fontDescription key="fontDescription" name="Menlo-Bold" family="Menlo" pointSize="25"/> + <rect key="frame" x="199.5" y="35.5" width="65.5" height="29"/> + <fontDescription key="fontDescription" name="Helvetica-Bold" family="Helvetica" pointSize="25"/> <nil key="textColor"/> <nil key="highlightedColor"/> </label> @@ -58,13 +58,13 @@ <subviews> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="Question one example text goes here?" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Ty7-T3-nJf"> <rect key="frame" x="10" y="10" width="334" height="47"/> - <fontDescription key="fontDescription" name="Menlo-Bold" family="Menlo" pointSize="15"/> + <fontDescription key="fontDescription" name="Helvetica-Bold" family="Helvetica" pointSize="15"/> <nil key="textColor"/> <nil key="highlightedColor"/> </label> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="Question one example text goes here?" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="xNY-uE-eR2"> <rect key="frame" x="10" y="65" width="334" height="47"/> - <fontDescription key="fontDescription" name="Menlo-Regular" family="Menlo" pointSize="11"/> + <fontDescription key="fontDescription" name="Helvetica" family="Helvetica" pointSize="11"/> <nil key="textColor"/> <nil key="highlightedColor"/> </label> diff --git a/PrivacyDemo/Home/Home.storyboard b/PrivacyDemo/Home/Home.storyboard index 6269dab514672bd9c013eed89e81de82d44fc15d..847ba910a8fa01467df64f9cd98c42d2541b53cb 100644 --- a/PrivacyDemo/Home/Home.storyboard +++ b/PrivacyDemo/Home/Home.storyboard @@ -27,6 +27,7 @@ <fragment content="Anonymous Chat"> <attributes> <font key="NSFont" size="24" name="Menlo-Bold"/> + <paragraphStyle key="NSParagraphStyle" alignment="center" lineBreakMode="wordWrapping" baseWritingDirection="natural" tighteningFactorForTruncation="0.0"/> </attributes> </fragment> </attributedString> @@ -41,10 +42,10 @@ <state key="normal" title="Button"/> <buttonConfiguration key="configuration" style="filled"> <attributedString key="attributedTitle"> - <fragment content="Private Provider"> + <fragment content="Connect to a Provider"> <attributes> - <font key="NSFont" size="24" name="Menlo-Bold"/> - <paragraphStyle key="NSParagraphStyle" alignment="natural" lineBreakMode="wordWrapping" baseWritingDirection="natural" tighteningFactorForTruncation="0.0"/> + <font key="NSFont" size="24" name="Helvetica-Bold"/> + <paragraphStyle key="NSParagraphStyle" alignment="center" lineBreakMode="wordWrapping" baseWritingDirection="natural" tighteningFactorForTruncation="0.0"/> </attributes> </fragment> </attributedString> @@ -61,8 +62,9 @@ <attributedString key="attributedTitle"> <fragment content="FAQs"> <attributes> - <font key="NSFont" size="24" name="Menlo-Bold"/> - <paragraphStyle key="NSParagraphStyle" alignment="natural" lineBreakMode="wordWrapping" baseWritingDirection="natural" tighteningFactorForTruncation="0.0"/> + <color key="NSColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="displayP3"/> + <font key="NSFont" size="24" name="Helvetica-Bold"/> + <paragraphStyle key="NSParagraphStyle" alignment="center" lineBreakMode="wordWrapping" baseWritingDirection="natural" tighteningFactorForTruncation="0.0"/> </attributes> </fragment> </attributedString> @@ -74,9 +76,9 @@ </button> </subviews> </stackView> - <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Shielded Help" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="xeW-u6-UsM"> - <rect key="frame" x="50" y="173" width="314" height="47"/> - <fontDescription key="fontDescription" name="Menlo-Bold" family="Menlo" pointSize="40"/> + <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Shielded Help" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="xeW-u6-UsM"> + <rect key="frame" x="50" y="174" width="314" height="46"/> + <fontDescription key="fontDescription" name="Helvetica-Bold" family="Helvetica" pointSize="40"/> <nil key="textColor"/> <nil key="highlightedColor"/> </label> diff --git a/PrivacyDemo/PrivateProviders/Model/MessageContent.swift b/PrivacyDemo/PrivateProviders/Model/MessageContent.swift index a9581a4ff8f82677481d4a2ba9f484afc70cf38f..bc18fd3815c47c6dc1905f59ebda8ca47592b9e4 100644 --- a/PrivacyDemo/PrivateProviders/Model/MessageContent.swift +++ b/PrivacyDemo/PrivateProviders/Model/MessageContent.swift @@ -4,16 +4,22 @@ public struct MessageContent: Equatable { public init( name: String, xxmessengerUsername: String, - message: String + message: String, + code: String? = nil, + date: String? = nil ) { self.name = name self.xxmessengerUsername = xxmessengerUsername self.message = message + self.code = code + self.date = date } public var name: String? public var xxmessengerUsername: String? public var message: String? + public var code: String? + public var date: String? } extension MessageContent: Codable { @@ -21,6 +27,8 @@ extension MessageContent: Codable { case name = "name" case xxmessengerUsername = "xxmessengerUsername" case message = "message" + case code = "code" + case date = "date" } public init(from decoder: Decoder) throws { @@ -28,5 +36,7 @@ extension MessageContent: Codable { name = try container.decodeIfPresent(String.self, forKey: .name) xxmessengerUsername = try container.decodeIfPresent(String.self, forKey: .xxmessengerUsername) message = try container.decodeIfPresent(String.self, forKey: .message) + code = try container.decodeIfPresent(String.self, forKey: .code) + date = try container.decodeIfPresent(String.self, forKey: .date) } } diff --git a/PrivacyDemo/PrivateProviders/Providers.storyboard b/PrivacyDemo/PrivateProviders/Providers.storyboard index bbad0bf9476ba1abd2df78ad5c482c2d3bf36a6e..71b7c1a570233510f15cf251cd6e402218899e2d 100644 --- a/PrivacyDemo/PrivateProviders/Providers.storyboard +++ b/PrivacyDemo/PrivateProviders/Providers.storyboard @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="20037" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="Y6W-OH-hqX"> - <device id="retina6_1" orientation="portrait" appearance="light"/> + <device id="retina4_0" orientation="portrait" appearance="light"/> <dependencies> <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="20020"/> <capability name="Safe area layout guides" minToolsVersion="9.0"/> @@ -13,68 +13,138 @@ <objects> <viewController storyboardIdentifier="ProvidersViewController" id="Y6W-OH-hqX" customClass="ProvidersViewController" customModule="PrivacyDemo" customModuleProvider="target" sceneMemberID="viewController"> <view key="view" contentMode="scaleToFill" id="5EZ-qb-Rvc"> - <rect key="frame" x="0.0" y="0.0" width="414" height="896"/> + <rect key="frame" x="0.0" y="0.0" width="320" height="568"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <subviews> - <textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" textAlignment="natural" translatesAutoresizingMaskIntoConstraints="NO" id="Vww-MZ-8MO"> - <rect key="frame" x="41.5" y="341" width="331" height="224"/> - <color key="backgroundColor" systemColor="systemBackgroundColor"/> - <color key="textColor" red="0.68235294117647061" green="0.68235294117647061" blue="0.69803921568627447" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> - <fontDescription key="fontDescription" name="Menlo-Regular" family="Menlo" pointSize="18"/> - <textInputTraits key="textInputTraits" autocapitalizationType="sentences"/> - </textView> - <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="dXz-cC-kkF" userLabel="SendMessage"> - <rect key="frame" x="41.5" y="601" width="331" height="60"/> - <constraints> - <constraint firstAttribute="height" constant="60" id="W00-F5-5jk"/> - </constraints> - <state key="normal" title="Button"/> - <buttonConfiguration key="configuration" style="filled"> - <attributedString key="attributedTitle"> - <fragment content="Send Message"> - <attributes> - <font key="NSFont" size="24" name="Menlo-Bold"/> - <paragraphStyle key="NSParagraphStyle" alignment="natural" lineBreakMode="wordWrapping" baseWritingDirection="natural" tighteningFactorForTruncation="0.0"/> - </attributes> - </fragment> - </attributedString> - <color key="baseBackgroundColor" red="0.99607843139999996" green="0.46666666670000001" blue="0.31764705879999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> - </buttonConfiguration> - <connections> - <action selector="sendMessageButton:" destination="Y6W-OH-hqX" eventType="touchUpInside" id="vjJ-de-fEy"/> - </connections> - </button> - <button opaque="NO" contentMode="scaleAspectFit" contentHorizontalAlignment="left" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="raM-TN-zb4"> - <rect key="frame" x="41.5" y="207" width="232.5" height="30"/> + <scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" showsHorizontalScrollIndicator="NO" translatesAutoresizingMaskIntoConstraints="NO" id="207-KC-jJc"> + <rect key="frame" x="0.0" y="100" width="320" height="468"/> + <subviews> + <textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" textAlignment="natural" translatesAutoresizingMaskIntoConstraints="NO" id="Vww-MZ-8MO"> + <rect key="frame" x="20" y="561" width="280" height="136.5"/> + <color key="backgroundColor" systemColor="systemBackgroundColor"/> + <color key="textColor" red="0.68235294117647061" green="0.68235294117647061" blue="0.69803921568627447" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> + <fontDescription key="fontDescription" name="Helvetica" family="Helvetica" pointSize="18"/> + <textInputTraits key="textInputTraits" autocapitalizationType="sentences"/> + </textView> + <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="dXz-cC-kkF" userLabel="SendMessage"> + <rect key="frame" x="20" y="733.5" width="280" height="60"/> + <constraints> + <constraint firstAttribute="height" constant="60" id="W00-F5-5jk"/> + </constraints> + <state key="normal" title="Button"/> + <buttonConfiguration key="configuration" style="filled"> + <attributedString key="attributedTitle"> + <fragment content="Send Message"> + <attributes> + <font key="NSFont" size="24" name="Helvetica-Bold"/> + <paragraphStyle key="NSParagraphStyle" alignment="natural" lineBreakMode="wordWrapping" baseWritingDirection="natural" tighteningFactorForTruncation="0.0"/> + </attributes> + </fragment> + </attributedString> + <color key="baseBackgroundColor" red="0.99607843139999996" green="0.46666666670000001" blue="0.31764705879999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> + </buttonConfiguration> + <connections> + <action selector="sendMessageButton:" destination="Y6W-OH-hqX" eventType="touchUpInside" id="vjJ-de-fEy"/> + </connections> + </button> + <button opaque="NO" contentMode="scaleAspectFit" contentHorizontalAlignment="left" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="raM-TN-zb4"> + <rect key="frame" x="20" y="20" width="199.5" height="30"/> + <constraints> + <constraint firstAttribute="height" constant="30" id="IBe-eV-O5x"/> + </constraints> + <color key="tintColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> + <state key="normal" title="Button"/> + <buttonConfiguration key="configuration" style="plain" image="DropDown" imagePlacement="trailing" imagePadding="10"> + <attributedString key="attributedTitle"> + <fragment content="Select providers"> + <attributes> + <font key="NSFont" size="18" name="Helvetica-Bold"/> + <paragraphStyle key="NSParagraphStyle" alignment="natural" lineBreakMode="wordWrapping" baseWritingDirection="natural" tighteningFactorForTruncation="0.0"/> + </attributes> + </fragment> + </attributedString> + </buttonConfiguration> + </button> + <button opaque="NO" contentMode="scaleAspectFit" contentHorizontalAlignment="left" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="BAb-jC-Suy"> + <rect key="frame" x="20" y="60" width="172.5" height="30"/> + <constraints> + <constraint firstAttribute="height" constant="30" id="JcI-mw-Jgy"/> + </constraints> + <color key="tintColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> + <state key="normal" title="Button"/> + <buttonConfiguration key="configuration" style="plain" image="DropDown" imagePlacement="trailing" imagePadding="10"> + <attributedString key="attributedTitle"> + <fragment content="Request type"> + <attributes> + <font key="NSFont" size="18" name="Helvetica-Bold"/> + <paragraphStyle key="NSParagraphStyle" alignment="natural" lineBreakMode="wordWrapping" baseWritingDirection="natural" tighteningFactorForTruncation="0.0"/> + </attributes> + </fragment> + </attributedString> + </buttonConfiguration> + </button> + <stackView opaque="NO" contentMode="center" axis="vertical" alignment="top" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="GfZ-Tv-X5x"> + <rect key="frame" x="20" y="100" width="280" height="445"/> + <subviews> + <datePicker contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" datePickerMode="dateAndTime" minuteInterval="1" style="compact" translatesAutoresizingMaskIntoConstraints="NO" id="24c-bd-huV"> + <rect key="frame" x="0.0" y="0.0" width="280" height="313"/> + </datePicker> + <textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="Your name" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="zDu-Pl-IVh"> + <rect key="frame" x="0.0" y="323" width="266.5" height="34"/> + <fontDescription key="fontDescription" name="Helvetica" family="Helvetica" pointSize="18"/> + <textInputTraits key="textInputTraits"/> + </textField> + <textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="Your xx messenger username" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="fht-oq-DuJ"> + <rect key="frame" x="0.0" y="367" width="266.5" height="34"/> + <fontDescription key="fontDescription" name="Helvetica" family="Helvetica" pointSize="18"/> + <textInputTraits key="textInputTraits"/> + </textField> + <textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="Code (Optional)" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="UCN-AH-edz"> + <rect key="frame" x="0.0" y="411" width="266.5" height="34"/> + <fontDescription key="fontDescription" name="Helvetica" family="Helvetica" pointSize="18"/> + <textInputTraits key="textInputTraits"/> + </textField> + </subviews> + <constraints> + <constraint firstItem="UCN-AH-edz" firstAttribute="width" secondItem="fht-oq-DuJ" secondAttribute="width" id="04Q-Wf-ySl"/> + <constraint firstItem="zDu-Pl-IVh" firstAttribute="width" secondItem="fht-oq-DuJ" secondAttribute="width" id="bKv-jX-fw1"/> + </constraints> + </stackView> + </subviews> <constraints> - <constraint firstAttribute="height" constant="30" id="IBe-eV-O5x"/> + <constraint firstItem="raM-TN-zb4" firstAttribute="leading" secondItem="Vww-MZ-8MO" secondAttribute="leading" id="5IO-oG-Q5U"/> + <constraint firstItem="GfZ-Tv-X5x" firstAttribute="leading" secondItem="207-KC-jJc" secondAttribute="leading" id="5Yu-vE-XKo"/> + <constraint firstItem="raM-TN-zb4" firstAttribute="trailing" relation="lessThanOrEqual" secondItem="Vww-MZ-8MO" secondAttribute="trailing" id="BMA-PB-Mnd"/> + <constraint firstItem="BAb-jC-Suy" firstAttribute="top" secondItem="raM-TN-zb4" secondAttribute="bottom" constant="10" id="DIU-EY-Bbk"/> + <constraint firstItem="BAb-jC-Suy" firstAttribute="leading" secondItem="Vww-MZ-8MO" secondAttribute="leading" id="DUK-XX-dbH"/> + <constraint firstAttribute="bottom" secondItem="dXz-cC-kkF" secondAttribute="bottom" constant="20" symbolic="YES" id="FKs-XM-bMF"/> + <constraint firstItem="GfZ-Tv-X5x" firstAttribute="top" secondItem="BAb-jC-Suy" secondAttribute="bottom" constant="10" id="G2l-2m-BzO"/> + <constraint firstItem="dXz-cC-kkF" firstAttribute="top" secondItem="Vww-MZ-8MO" secondAttribute="bottom" constant="36" id="HdW-kh-HMW"/> + <constraint firstItem="dXz-cC-kkF" firstAttribute="leading" secondItem="Vww-MZ-8MO" secondAttribute="leading" id="J3x-M9-7Qr"/> + <constraint firstItem="raM-TN-zb4" firstAttribute="top" secondItem="207-KC-jJc" secondAttribute="top" constant="20" symbolic="YES" id="Q7k-qx-WXG"/> + <constraint firstItem="dXz-cC-kkF" firstAttribute="trailing" secondItem="Vww-MZ-8MO" secondAttribute="trailing" id="QUv-cC-4Ac"/> + <constraint firstAttribute="trailing" secondItem="GfZ-Tv-X5x" secondAttribute="trailing" id="TTn-st-9M0"/> + <constraint firstItem="Vww-MZ-8MO" firstAttribute="top" secondItem="GfZ-Tv-X5x" secondAttribute="bottom" constant="16" id="Tm2-PC-Loe"/> + <constraint firstItem="Vww-MZ-8MO" firstAttribute="leading" secondItem="GfZ-Tv-X5x" secondAttribute="leading" id="Y3E-uZ-BgW"/> + <constraint firstItem="Vww-MZ-8MO" firstAttribute="trailing" secondItem="GfZ-Tv-X5x" secondAttribute="trailing" id="jQV-f2-sXz"/> + <constraint firstItem="BAb-jC-Suy" firstAttribute="trailing" relation="lessThanOrEqual" secondItem="Vww-MZ-8MO" secondAttribute="trailing" id="tsm-T1-38I"/> </constraints> - <color key="tintColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> - <state key="normal" title="Button"/> - <buttonConfiguration key="configuration" style="plain" image="DropDown" imagePlacement="trailing" imagePadding="10"> - <attributedString key="attributedTitle"> - <fragment content="Select providers"> - <attributes> - <font key="NSFont" size="18" name="Menlo-Bold"/> - <paragraphStyle key="NSParagraphStyle" alignment="natural" lineBreakMode="wordWrapping" baseWritingDirection="natural" tighteningFactorForTruncation="0.0"/> - </attributes> - </fragment> - </attributedString> - </buttonConfiguration> - </button> + <viewLayoutGuide key="contentLayoutGuide" id="CHi-rC-iOK"/> + <viewLayoutGuide key="frameLayoutGuide" id="4XX-Zs-1Pl"/> + </scrollView> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="vOM-Mw-K7C"> - <rect key="frame" x="0.0" y="44" width="414" height="100"/> + <rect key="frame" x="0.0" y="0.0" width="320" height="100"/> <subviews> <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="Shield" translatesAutoresizingMaskIntoConstraints="NO" id="8G1-Iy-COh"> - <rect key="frame" x="112" y="25" width="50" height="50"/> + <rect key="frame" x="74.5" y="25" width="50" height="50"/> <constraints> <constraint firstAttribute="height" constant="50" id="K2o-uo-3pr"/> <constraint firstAttribute="width" secondItem="8G1-Iy-COh" secondAttribute="height" multiplier="1:1" id="UVi-Mc-J0N"/> </constraints> </imageView> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Provider" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Elu-Y7-8Yc"> - <rect key="frame" x="167" y="35.5" width="120.5" height="29.5"/> - <fontDescription key="fontDescription" name="Menlo-Bold" family="Menlo" pointSize="25"/> + <rect key="frame" x="129.5" y="35.5" width="101.5" height="29"/> + <fontDescription key="fontDescription" name="Helvetica-Bold" family="Helvetica" pointSize="25"/> <nil key="textColor"/> <nil key="highlightedColor"/> </label> @@ -88,45 +158,30 @@ <constraint firstItem="Elu-Y7-8Yc" firstAttribute="centerY" secondItem="8G1-Iy-COh" secondAttribute="centerY" id="myG-Ln-kwb"/> </constraints> </view> - <textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="Your xx messenger username" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="fht-oq-DuJ"> - <rect key="frame" x="41.5" y="291" width="331" height="34"/> - <fontDescription key="fontDescription" name="Menlo-Regular" family="Menlo" pointSize="18"/> - <textInputTraits key="textInputTraits"/> - </textField> - <textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="Your name" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="zDu-Pl-IVh"> - <rect key="frame" x="41.5" y="247" width="331" height="34"/> - <fontDescription key="fontDescription" name="Menlo-Regular" family="Menlo" pointSize="18"/> - <textInputTraits key="textInputTraits"/> - </textField> </subviews> <viewLayoutGuide key="safeArea" id="vDu-zF-Fre"/> <color key="backgroundColor" systemColor="systemBackgroundColor"/> <constraints> - <constraint firstItem="dXz-cC-kkF" firstAttribute="top" secondItem="Vww-MZ-8MO" secondAttribute="bottom" constant="36" id="68U-0w-jBi"/> - <constraint firstItem="fht-oq-DuJ" firstAttribute="leading" secondItem="Vww-MZ-8MO" secondAttribute="leading" id="7Sj-YL-8yk"/> - <constraint firstItem="Vww-MZ-8MO" firstAttribute="centerX" secondItem="vDu-zF-Fre" secondAttribute="centerX" id="9eH-eW-R82"/> - <constraint firstItem="zDu-Pl-IVh" firstAttribute="trailing" secondItem="fht-oq-DuJ" secondAttribute="trailing" id="HNJ-Z0-GyF"/> - <constraint firstItem="raM-TN-zb4" firstAttribute="width" relation="lessThanOrEqual" secondItem="Vww-MZ-8MO" secondAttribute="width" id="Ie9-F6-ue2"/> - <constraint firstItem="dXz-cC-kkF" firstAttribute="width" secondItem="Vww-MZ-8MO" secondAttribute="width" id="J5l-SC-nru"/> - <constraint firstItem="fht-oq-DuJ" firstAttribute="top" secondItem="zDu-Pl-IVh" secondAttribute="bottom" constant="10" id="Lvh-B1-c3o"/> - <constraint firstItem="Vww-MZ-8MO" firstAttribute="top" secondItem="fht-oq-DuJ" secondAttribute="bottom" constant="16" id="O71-nW-5zY"/> - <constraint firstItem="Vww-MZ-8MO" firstAttribute="centerY" secondItem="vDu-zF-Fre" secondAttribute="centerY" id="PQ0-WF-UfT"/> - <constraint firstItem="Vww-MZ-8MO" firstAttribute="width" secondItem="5EZ-qb-Rvc" secondAttribute="width" multiplier="0.8" id="RyW-x9-mFT"/> - <constraint firstItem="fht-oq-DuJ" firstAttribute="trailing" secondItem="Vww-MZ-8MO" secondAttribute="trailing" id="VtU-ov-bNd"/> + <constraint firstItem="207-KC-jJc" firstAttribute="leading" secondItem="vDu-zF-Fre" secondAttribute="leading" id="0g2-XH-C0g"/> + <constraint firstItem="vDu-zF-Fre" firstAttribute="trailing" secondItem="GfZ-Tv-X5x" secondAttribute="trailing" constant="20" id="1Sv-k8-bi6"/> + <constraint firstItem="GfZ-Tv-X5x" firstAttribute="leading" secondItem="vDu-zF-Fre" secondAttribute="leading" constant="20" id="ByN-7E-WEW"/> + <constraint firstItem="Vww-MZ-8MO" firstAttribute="height" secondItem="5EZ-qb-Rvc" secondAttribute="height" multiplier="0.24" id="PIq-po-ROC"/> + <constraint firstItem="vDu-zF-Fre" firstAttribute="trailing" secondItem="207-KC-jJc" secondAttribute="trailing" id="Qcg-Js-NFJ"/> <constraint firstItem="vOM-Mw-K7C" firstAttribute="centerX" secondItem="vDu-zF-Fre" secondAttribute="centerX" id="cN6-hE-XFm"/> - <constraint firstItem="Vww-MZ-8MO" firstAttribute="height" secondItem="5EZ-qb-Rvc" secondAttribute="height" multiplier="0.25" id="dQr-ea-6cw"/> - <constraint firstItem="dXz-cC-kkF" firstAttribute="centerX" secondItem="Vww-MZ-8MO" secondAttribute="centerX" id="eN1-Tq-eiq"/> - <constraint firstItem="zDu-Pl-IVh" firstAttribute="centerX" secondItem="fht-oq-DuJ" secondAttribute="centerX" id="lmD-mP-820"/> <constraint firstItem="vOM-Mw-K7C" firstAttribute="width" secondItem="vDu-zF-Fre" secondAttribute="width" id="oNX-QH-d9U"/> <constraint firstItem="vOM-Mw-K7C" firstAttribute="top" secondItem="vDu-zF-Fre" secondAttribute="top" id="pgu-fk-f1w"/> - <constraint firstItem="zDu-Pl-IVh" firstAttribute="top" secondItem="raM-TN-zb4" secondAttribute="bottom" constant="10" id="r7n-PX-fSu"/> - <constraint firstItem="raM-TN-zb4" firstAttribute="leading" secondItem="Vww-MZ-8MO" secondAttribute="leading" id="tvX-5Y-pVY"/> + <constraint firstItem="207-KC-jJc" firstAttribute="top" secondItem="vOM-Mw-K7C" secondAttribute="bottom" id="qpN-k5-j0U"/> + <constraint firstItem="207-KC-jJc" firstAttribute="bottom" secondItem="vDu-zF-Fre" secondAttribute="bottom" id="tTp-L6-9tA"/> </constraints> </view> <connections> + <outlet property="codeTextField" destination="UCN-AH-edz" id="zFZ-9Q-xQs"/> + <outlet property="datePickerView" destination="24c-bd-huV" id="2dF-ij-tMC"/> + <outlet property="fieldsStackView" destination="GfZ-Tv-X5x" id="xW6-zz-j9p"/> <outlet property="messageTextView" destination="Vww-MZ-8MO" id="oAL-41-38h"/> <outlet property="nameTextField" destination="zDu-Pl-IVh" id="cTW-62-ghk"/> <outlet property="selectProviderButton" destination="raM-TN-zb4" id="hrj-fE-bQN"/> + <outlet property="selectRequestTypeButton" destination="BAb-jC-Suy" id="W5R-VD-gIj"/> <outlet property="xxmessengerTextField" destination="fht-oq-DuJ" id="QYB-Vd-Px6"/> </connections> </viewController> diff --git a/PrivacyDemo/PrivateProviders/ProvidersViewController.swift b/PrivacyDemo/PrivateProviders/ProvidersViewController.swift index dbe0c983f38c0776daf32d8d867ff8cde504a495..c5a53cde5eeb3b03e78e236badf1ae04abd21d2d 100644 --- a/PrivacyDemo/PrivateProviders/ProvidersViewController.swift +++ b/PrivacyDemo/PrivateProviders/ProvidersViewController.swift @@ -6,23 +6,32 @@ class ProvidersViewController: UIViewController { // MARK: - Outlets + @IBOutlet weak var fieldsStackView: UIStackView! + @IBOutlet weak var selectRequestTypeButton: UIButton! @IBOutlet weak var messageTextView: UITextView! @IBOutlet weak var selectProviderButton: UIButton! @IBOutlet weak var xxmessengerTextField: UITextField! @IBOutlet weak var nameTextField: UITextField! + @IBOutlet weak var datePickerView: UIDatePicker! + @IBOutlet weak var codeTextField: UITextField! + + // MARK: - Public properties + + public var suggestedProvider: (name:String?, requestType: String?, code: String?)? + // MARK: - Private properties - private let messageTextViewPlaceholder = "Type your message here to send it anonymously to your selected provider" + private let messageTextViewPlaceholder = "Type your message here to send it securely to your selected provider" private var connection: Connection? private var loadingIndicator: LoadingIndicatorView! + private var requestType = Constants.RequestType.appointment // MARK: - View LifeCycle override func viewDidLoad() { super.viewDidLoad() setupUI() - initConnection(with: Constants.restlikeRecipentContact1) } override func viewWillDisappear(_ animated: Bool) { @@ -39,7 +48,7 @@ class ProvidersViewController: UIViewController { func sendRestLikeMessage(name: String, username: String, message: String) { let requetToSend = createRequest(name: name, username: username, message: message) - DispatchQueue.global(qos: .background).async { [weak self] in + DispatchQueue.global(qos: .userInteractive).async { [weak self] in guard let self = self else { return } do { let restLikeRequestSender = RestlikeRequestSender.live(authenticated: false) @@ -57,31 +66,45 @@ class ProvidersViewController: UIViewController { } } - func createRequest(name: String, username: String, message: String) -> Data { - let content = MessageContent(name: name, xxmessengerUsername: username, message: message) + func createRequest(name: String, username: String, message: String) -> RestlikeMessage { + var uri = String() + var date: String? + if requestType == .request { + uri = Constants.requestURI + date = nil + } else { + uri = Constants.appointmentURI + date = datePickerView.date.formatted(date: .abbreviated, time: .shortened) + } + let content = MessageContent(name: name, + xxmessengerUsername: username, + message: message, + code: codeTextField.text, + date: date) let contentEncoded = try! JSONEncoder().encode(content) let restLikeMessage = RestlikeMessage(version: 0, headers: Data("".utf8), content: contentEncoded, method: 1, - uri: "xx://provider", + uri: uri, error: "") - return try! JSONEncoder().encode(restLikeMessage) + return restLikeMessage } func initConnection(with providerIdentity: String) { - loadingIndicator.startAnimating(inView: self.view, shouldDisableInteraction: true, text: "Initiating...") - DispatchQueue.global(qos: .background).async { [weak self] in + loadingIndicator.startAnimating(inView: self.view, shouldDisableInteraction: true, text: "Initiating & securing connection") + DispatchQueue.global(qos: .userInteractive).async { [weak self] in guard let self = self else { return } do { if self.connection != nil { try self.connection!.close() } + let clientE2E = try ClientE2ELogin.live(with: ElixxirHandler.shared.client!) self.connection = try ElixxirHandler.shared.client!.connect(withAuthentication: false, recipientContact: Data(providerIdentity.utf8), - myIdentity: ElixxirHandler.shared.myIdentityMarshalled) + e2eId: clientE2E.getId()) DispatchQueue.main.async { [weak self] in guard let self = self else { return } self.loadingIndicator.stopAnimating() @@ -100,6 +123,28 @@ class ProvidersViewController: UIViewController { setupMessageTextView() setupTextFields() setupProvidersButton() + setupRequestTypeButton() + setupDatePickerView() + prefillIfNecessary() + } + + func prefillIfNecessary() { + guard let suggestedProvider = suggestedProvider else { + setupProvidersButtonMenu() + return + } + if let requestType = suggestedProvider.requestType, let type = Constants.RequestType(rawValue: requestType) { + setupRequestTypeButtonMenu(initialSelection: type) + + } + if let code = suggestedProvider.code { + codeTextField.text = code + } + if let name = suggestedProvider.name, let providerName = Constants.ProviderNames(rawValue: name) { + setupProvidersButtonMenu(initialSelection: providerName) + } else { + setupProvidersButtonMenu() + } } func setupMessageTextView() { @@ -110,6 +155,13 @@ class ProvidersViewController: UIViewController { setMessageTextViewPlaceholder() } + func setupDatePickerView() { + let minDate = Calendar.current.date(byAdding: .day, value: +1, to: Date()) + datePickerView.minimumDate = minDate + datePickerView.maximumDate = Calendar.current.date(byAdding: .month, value: +1, to: Date()) + datePickerView.setDate(minDate!, animated: true) + } + func setupTextFields() { nameTextField.layer.borderWidth = 0.5 nameTextField.layer.borderColor = Constants.AppColors.appBlackColor.cgColor @@ -117,18 +169,27 @@ class ProvidersViewController: UIViewController { xxmessengerTextField.layer.borderWidth = 0.5 xxmessengerTextField.layer.borderColor = Constants.AppColors.appBlackColor.cgColor xxmessengerTextField.layer.cornerRadius = 5.0 + codeTextField.layer.borderWidth = 0.5 + codeTextField.layer.borderColor = Constants.AppColors.appBlackColor.cgColor + codeTextField.layer.cornerRadius = 5.0 } func setupProvidersButton() { selectProviderButton.layer.borderWidth = 0.5 selectProviderButton.layer.borderColor = Constants.AppColors.appBlackColor.cgColor selectProviderButton.layer.cornerRadius = 5.0 - setupProvidersButtonMenu() - selectProviderButton.changesSelectionAsPrimaryAction = true - selectProviderButton.showsMenuAsPrimaryAction = true } - func setupProvidersButtonMenu() { + func setupRequestTypeButton() { + selectRequestTypeButton.layer.borderWidth = 0.5 + selectRequestTypeButton.layer.borderColor = Constants.AppColors.appBlackColor.cgColor + selectRequestTypeButton.layer.cornerRadius = 5.0 + setupRequestTypeButtonMenu() + selectRequestTypeButton.changesSelectionAsPrimaryAction = true + selectRequestTypeButton.showsMenuAsPrimaryAction = true + } + + func setupProvidersButtonMenu(initialSelection: Constants.ProviderNames = .provider1) { let providerOneAction = UIAction(title: "Provider 1", handler: { [weak self] (action: UIAction) in guard let self = self else { return } self.initConnection(with: Constants.restlikeRecipentContact1) @@ -141,8 +202,42 @@ class ProvidersViewController: UIViewController { guard let self = self else { return } self.initConnection(with: Constants.restlikeRecipentContact3) }) - let providersMenu = UIMenu(title: "", options: .displayInline, children: [providerOneAction, providerTwoAction, providerThreeAction]) + var menuChildren = [UIMenuElement]() + if initialSelection == .provider1 { + menuChildren = [providerOneAction, providerTwoAction, providerThreeAction] + self.initConnection(with: Constants.restlikeRecipentContact1) + } else if initialSelection == .provider2 { + menuChildren = [providerTwoAction, providerOneAction, providerThreeAction] + self.initConnection(with: Constants.restlikeRecipentContact2) + } else if initialSelection == .provider3 { + menuChildren = [providerThreeAction, providerOneAction, providerTwoAction, ] + self.initConnection(with: Constants.restlikeRecipentContact3) + } + let providersMenu = UIMenu(title: "", options: .displayInline, children: menuChildren) selectProviderButton.menu = providersMenu + selectProviderButton.changesSelectionAsPrimaryAction = true + selectProviderButton.showsMenuAsPrimaryAction = true + } + + func setupRequestTypeButtonMenu(initialSelection: Constants.RequestType = .appointment) { + let requestAction = UIAction(title: "Request", handler: { [weak self] (action: UIAction) in + guard let self = self else { return } + self.updateUIForRequestType(.request) + }) + let appointmentAction = UIAction(title: "Appointment", handler: { [weak self] (action: UIAction) in + guard let self = self else { return } + self.updateUIForRequestType(.appointment) + }) + var menuChildren = [UIMenuElement]() + if initialSelection == .appointment { + menuChildren = [appointmentAction, requestAction] + updateUIForRequestType(.appointment) + } else { + menuChildren = [requestAction, appointmentAction] + updateUIForRequestType(.request) + } + let requestTypesMenu = UIMenu(title: "", options: .displayInline, children: menuChildren) + selectRequestTypeButton.menu = requestTypesMenu } func setMessageTextViewPlaceholder() { @@ -172,30 +267,38 @@ class ProvidersViewController: UIViewController { @IBAction func sendMessageButton(_ sender: Any) { view.endEditing(true) guard connection != nil else { - AlertsHandler.shared.showAlert(in: self, title: "Error", message: "A connection is being created, please try again later") + AlertsHandler.shared.showAlert(in: self, title: "Error", message: "A secure connection is being created, please try again later") return } guard let name = nameTextField.text, let username = xxmessengerTextField.text, let message = messageTextView.text, message != messageTextViewPlaceholder else { AlertsHandler.shared.showAlert(in: self, title: "Error", - message: "All fields are mandatory") + message: "Name and Message fields are mandatory") return } - loadingIndicator.startAnimating(inView: self.view, shouldDisableInteraction: true, text: "Sending...") + loadingIndicator.startAnimating(inView: self.view, shouldDisableInteraction: true, text: "Sending through secure channel") sendRestLikeMessage(name: name, username: username, message: message) } // MARK: - Helpers - func handleResponse(_ response: Data) { - do { - let message = try JSONDecoder().decode(RestlikeMessage.self, from: response) - let content = String(decoding: message.content!, as: UTF8.self) - loadingIndicator.stopAnimating() - AlertsHandler.shared.showAlert(in: self, title: "Success!", message: content) - } catch (let error) { - handleError(error.localizedDescription) + func handleResponse(_ response: RestlikeMessage) { + guard let responseMessageData = response.content else { + handleError("Empty response") + return + } + let responseMessage = String(decoding: responseMessageData, as: UTF8.self) + loadingIndicator.stopAnimating() + AlertsHandler.shared.showAlert(in: self, title: "Success ✅", message: responseMessage ) + } + + func updateUIForRequestType( _ type: Constants.RequestType) { + self.requestType = type + if type == .request { + self.fieldsStackView.removeArrangedSubview(self.datePickerView) + } else { + self.fieldsStackView.insertArrangedSubview(self.datePickerView, at: 0) } } } diff --git a/PrivacyDemo/Shared/Constants/AppConstants.swift b/PrivacyDemo/Shared/Constants/AppConstants.swift index 1d78a9b4468d668bcc9af6a838f3d97a38c72eed..df1ee7d8d90f15220ca60561f9a30828308a0d7a 100644 --- a/PrivacyDemo/Shared/Constants/AppConstants.swift +++ b/PrivacyDemo/Shared/Constants/AppConstants.swift @@ -1,8 +1,10 @@ enum Constants { static let helperUserId = "helperUserId" static let currentUserId = "currentUserId" - static let restlikeRecipentContact1 = "<xxc(2)2hbFZO100M/Ez0hs8VmDhz/damrQaFrD00YKQ0D6bdsDkAZiB9kZo+Dl3ZV7qL8KjTfjD/JOYqoiD2+8LEeiJE9Gs8W4o42CwDuB4j1SeEdoailWEMGfFZN1/f+ekelnSpMXFsJwiOS3V71ABqqqHscXDPKwW28jB9y/lKu3+egIggQtu2wcZFxZH+i6djrumFMhbpso1YKARVlotw8KlTPFu5XyZWYXwtFqhAMapY/IfDesQ6EDZS42G2c8RilGZKPPpatJzdvZVklh214OcBVjHixGY/eTi5NteyWddbG6GfyGyL7o/14q0VpnGUSaRPdHChfmetTJSdHFVcYRTXZR0LtAiLn3xZjGiv7hgR/vf+sek3GtZD9Xfvne/6MotJEKWXUxnKEuBIQjbkY0QDf43a62VzAcaxR6rCOZne0Lju5izB3GUWdfRmmPDGO4TVGqRCctMqGPyt6kadVoBT0VGxpx+ib/1uzM0A8lcs5TsaT+vuIeurYjginj8L8/yIxPXaNxWKq5FsvDUr6goWGCNmbWCXNdQx5YddqiliU7i8iTO4kVLimsjgAAAgA77W6a0Ty6I84GZWU2cEuXzA==xxc>" - static let restlikeRecipentContact2 = "<xxc(2)bKdnNxhdt9zn4k289I8DRe/ivUfSORt9Mu6qBOPZzOADkAZiB9kZo+Dl3Rf7jvn1nonhao4F4EanQj7qDrDUa4MPvdno+06RaY7YO9MgnMGUTZwfKkNwWYGygAUGR6/KFCbjJm8ElFzxV0lO/pKH6jYxQfPfHy0reALK7HmHmugFiufBiNDrq9G1dpXlqziiXA6E3ypXZNqE7JwF5QBFL87K2KuZxYMBBiFkbtqCFPcsQe/w4p8cbn1MlmhKJooD2XWe6MRVYF8lgrddmv1yqymg6fgn85usF1pgRAREYFqUawIvUU0eEKvOQKtlw1jf6Jo8ujtNJ+DbpTz8CxDh3Xb/nInKwV7IzKjVXAyB7tJv6A3SNrr94N4MrX99NFe6zYCiqbxDdQ4tHzABOzOlTdSwnXl7GBWdHHfmSu2CqrH4MBzf5ka93/Wx91UoNUN5HBak+WxC7m6vc+5NJkMAmJyp/9vH3gOEHa/VW0wCGzFJznStiQmayA1eaCzPvck/1qNpJIy5UTgiqkQhF65+OFKjg1pV/kNe1zz7lf5QjfBZ9fS6wkD9yvPDaAAAAgA7VwTH7U6UlSlreTjGDE8Tlw==xxc>" - static let restlikeRecipentContact3 = "<xxc(2)DrJkB6ZkJuUQnYUHuD0mhinEljftAHqgbYaNZsKgfs0DkAZiB9kZo+Dl3eOV7F5C13jtMlPfOza96+VDcfvE6Tb/LzEpwo1dGyhyDvIIoLBMHwqQKgVu4WQV+S0JQjcipGifBFVzOL8/eOY/6mUd+QPTvVGCqjSznc7jIswts1eyXAAh1q2acD7/i6H6YkKLll6RCfplPM8S6eFNeAkv/sNSvha0c5vG45e7xGx2welkBk9gZeRZcrk5ujJ6QEzHXAV6a2tY/AfncxLfYEHcAxhtWXZ5Jt9/Mnbt0EAoa4wIYpymwQCPIbj59a0UN91+VrLeU7qG0tB012zRR0cBorLRKGlEpbZjsEpixdgk8WHvXRwuGhnNt3OI1YTflQFwnGJBXOR4hfjze5M57wxmwk69KVRpL8Ti9QUxPCPdSvqcsLJP6iTn5vNUkIrU2aBKKeWPm/xx89ogOmcBpM9BET3U7aoAhOt2p64GAyDbRXSE54jmn8hGQN0krTlpv7n3GyO9tdD7TsEFtCERhjCDhX+wDmaCLBt/+34w5b2yLT261QMLsaf0U1C8AAAAAgA7MySITSJY9K5kqDri4PqUQg==xxc>" - static let chatRecipentContact = "<xxc(2)0pUtZWXUWcM3DiehwBSyOV8v6zt+0ljPTfNasM25JogDkAZiB9kZo+Dl3eDk09HOEXCOhL8HZA3MUwsW1r5CxKpAgB+G36Yn//VOgMEi3p5pAs/NJSdR9X9gc3P9qgOD1/OeHD4VPYJRIP94mnQYpERx75zY3JBcnWo33ttimDc2OxcGbHaUW95hGp19hCfyH7Gyi4Y9BQWIYfl9+8rKbuhm23TPVyB1UWo8PAlPZzfzSUDHKrys5Q4mIUBvmbWQEIOVsTIXLrXRYfXetZwfJPa0L5LAkcwkhLgHm52T8riKvAaWzfHuy5dxoun7ZgXhGTPrfMT8aBjQxlzAwDVbCikRfIr5/PINP/QFCMLjEgzO8O72LNCGyrWrGIY/NVwJtV9F52KSoDc2ekFEI+PCODnfVnpTfPfnrcyCVHarjbjgWXeSezZC228phijN4+RUOpAAGm0wrBTxd2CgGcgXkh7s1FdnJJVedXCUmCpV71CluQw3pdWs+xFgaOS4Bya2ZgeCgkJ2VP2CLJGEBczv9rdA6Cw3T+B6qpEv2lKd+0SkuTwBPWFRy22YVwAAAgA7rdCx8oMNgZkEpV0IiK2uSQ==xxc>" + static let requestURI = "xx://provider/requests" + static let appointmentURI = "xx://provider/appointments" + static let restlikeRecipentContact1 = "<xxc(2)aakkOnCayqcWCru/bzZ9f4DGN1MLCNpI1RvPzXGOFS8DkAZiB9kZo+Dl3V7SSfdh1wTxu8rSdlntmvAjVgU88Y6ClXocWGm+Fz9d+J4GjrIB/upTIJYO7JOsBWOTlZLjaf4dOZmUvD/ClEwsDBOidE5ONqaueyF3Rkt6S9/Q0EOqddi/DxTrmqdnoqHnst23edcioSrR2T4PmjIKFW6PNLNl19N4nNJ0WmLhrIDSngHlkpGiOmSy+1I7fS+tkgklSd5qT4Dous5Sk/aqq+39Wy6TbCYFr/9vA6yAkvNR+5D8y9HvHC2lfSWZWZvZW9OYn2qrGxAf40+5bpOBEMV+d5yrfSGBZ4dWNA28wQv/TsAul8F1XJwrLX4ATsRtSE6Lk6oUdkpyKpcvv+9UAtszSDzyJzziTHCytRe/O/82PXNN3hZ4Aa8KN4+aAmG1iRGNa8PkeEfVuGdmPVo6Noin9uH6qf+dLTGa6oh2gRIAIzWOqJwJYadgDwxBiOYkH/7L4S2tvipebKIDgAR3Nxhje0p+OLJb8kIrosBnVBm/kyUnGtwrrz8i5FwniAAAAgA7N3gGMUkidWO2UoEoaNax9Q==xxc>" + static let restlikeRecipentContact2 = "<xxc(2)uCKAXMPRXHtNMb6hW3aEQnu74+Qqd6663D3WC9q1hJkDkAZiB9kZo+Dl3ZVTScnqlFbKk8hBoU7GZE5eIHVB3Rmi67H05RNmjwYGVb4VLRTvanwwAcin88Nskst8Mz5H9Mw2jY/nqp2NFMq0LFNOtZ+kYZQGHVoGt8qFaxUbwi5FTXm9bCVyBY6x+FlEIPjic2L0MvBv/ZL84Lqp5C2/k20XF57bDzE43JA5aRxxJQ9u+vMN0nM1bvWNufs5OX00+DdQV6B/1zmvmzkjKuNWQUEmgaz3MTfW533pDPmrEpk/oIkXSIHyiG/u1WdG8RAOXqRsPF27SRo1kLgAwTZ+pX0I0Zfy5lya/tqYxEYpwTDku0j0DMP1gURkG/BhFARixyXqW4XeWQ9o8rhL3LPaFKAddv9+qlnsl57V5S5q+BFIGM40JWpmz/jkYu/LJtx1KqtOb3EGb4mOQxb8BQvqkwuDT7AD1VECs/bi91dCSlfXg49y5xlOVd69dYLQU6ZWAdMSNNPsG7AScDekGDYwArzq8PkjWAgSF4jRYKxr/sT2Q/pHJTzx1NZ/sAAAAgA7Rjn1zHjf3GGdfjBHDCXZyg==xxc>" + static let restlikeRecipentContact3 = "<xxc(2)teNZ3zghgS4pPuvdITXXn2bqD/LzyYqk9K0KCM7rF0kDkAZiB9kZo+Dl3dybxTYtq7ID0MJ3lHC5GhbomZirBZvvvQm3uQq6vZjQFmJHV7F+W/G4ZS80oAlU9xYrPCvNQcTiXKyLZNihU0pIhc+6ewxgJlveBvoq0WOMYLRpezRRvv/tEMbRbeks5d5pja2ouuDj/IWpQOYDdCUM9gwaJvjb4ZETTvtkIw+YUG0g/hYXX0nF1gi0ePxFy0CoYBV72LxyIBqYrc8WVu2Hcsv8+PYW3OdGuMQ0m46OyyLJfd+htooPs/JIOxmoVFh2S2kaDwAc6iBKy7dKpikp3yXqo2iVUXgtL7m40Hk9b1DhTPEEg2poGiD7rdhN8+BxCdMzD/PvsSpntIBQ0VOnIEwOGczwv8ecQwNzIt2UtwoVdcNuOs9TSN9JsGlC3K62kkCRaaDdcv9qWMFT4WLIsenziERfLUNB2jMUa3/9C2DfT9jq0t9Ae5JRZfjq7KKPOTxIcT/mUvziIFpji2jmP2oGFeUH6zQ/alAacHnb+8c6MV0J5QtgLiv3eRcgEwAAAgA7L4wMZwVtzV9XTm/+LJ/6WQ==xxc>" + static let chatRecipentContact = "<xxc(2)YFf/QbnaOGr3UyApJEoK5/EGqHn3VJ2e6jKYIU115G4DkAZiB9kZo+Dl3T50l1sso0jEqISzn2P/AqH6osJ8w1Xm00qeHOsJmwBkUJifgzAXpBOva904I8DCOZqtm8l2qGHtjP7zwrpmXGbzf0/OoVso1jzuAp8h4/OT1m+LYXyYY6XUyzhmsEMrRpnwflJ38ItMtXL6LUkQaI5f/vOXCZOLTrXV+/IVR7B8Cj0UoT5aEM0l/9SEfFAMZ3Uu6vdJi7aKlPjdP7NnZi2ERM1gr0jF/j5mp5kRHhuqOnCMRhMcglsIjM8RxfFfL2AaYRS68tRRylDz4oVH5UxPJ/m2+ACw47PuHB1AL7UwzV0pzmD8JpLqveu8bXLW+uKAvLLLxw8poVonW5kshGZgMG9din3LkEQFgbfth+seYPkwV00lFF29xKcW4Min0ZHRm/J979keqD04/J9AaVc+r75yMkOIsfrSZAOVR4WGp2P7syy+GoPPOXfjDoluQz7xXXgRll4jeZ2fO6Gql5RPYkF9LApA9Sn46CoA7aqidaEcP6qMHx9HUdUdaFTPXgAAAgA7RCZoHZFnJK1dvwa0WFWPhg==xxc>" } diff --git a/PrivacyDemo/Shared/Constants/ProviderNameConstants.swift b/PrivacyDemo/Shared/Constants/ProviderNameConstants.swift new file mode 100644 index 0000000000000000000000000000000000000000..6c5d901c803fb1101742303da8057a055d0885a9 --- /dev/null +++ b/PrivacyDemo/Shared/Constants/ProviderNameConstants.swift @@ -0,0 +1,8 @@ +import UIKit +extension Constants { + enum ProviderNames: String { + case provider1 = "providerone" + case provider2 = "providertwo" + case provider3 = "providerthree" + } +} diff --git a/PrivacyDemo/Shared/Constants/RequestTypeConstants.swift b/PrivacyDemo/Shared/Constants/RequestTypeConstants.swift new file mode 100644 index 0000000000000000000000000000000000000000..9761f5030203799da9314b692712d6772990cbd5 --- /dev/null +++ b/PrivacyDemo/Shared/Constants/RequestTypeConstants.swift @@ -0,0 +1,7 @@ +import UIKit +extension Constants { + enum RequestType: String { + case request = "req" + case appointment = "apt" + } +} diff --git a/PrivacyDemo/Shared/ElixxirHandler/ElixxirHandler.swift b/PrivacyDemo/Shared/ElixxirHandler/ElixxirHandler.swift index 229303f021b0268d382f3c91afc32df030d155b6..d028c3db7c3f7962b807246577fafda2c1659cba 100644 --- a/PrivacyDemo/Shared/ElixxirHandler/ElixxirHandler.swift +++ b/PrivacyDemo/Shared/ElixxirHandler/ElixxirHandler.swift @@ -5,27 +5,23 @@ final class ElixxirHandler { static let shared = ElixxirHandler() private var clientStorage: ClientStorage! var client: Client! - var myIdentityMarshalled: Data! private init(){ clientStorage = ClientStorage.live(passwordStorage: .keychain) } func initClient(completion: @escaping (Error?) -> Void ) { - DispatchQueue.global(qos: .background).async { + DispatchQueue.global(qos: .userInteractive).async { [weak self] in + guard let self = self else { return } do { if self.clientStorage.hasStoredClient() { self.client = try self.clientStorage.loadClient() - self.myIdentityMarshalled = try self.client.makeIdentity() } else { self.client = try self.clientStorage.createClient() - self.myIdentityMarshalled = try self.client.makeIdentity() } - DispatchQueue.main.async { completion(nil) } - } catch (let error) { DispatchQueue.main.async { completion(error) diff --git a/PrivacyDemo/Shared/Helpers/LoadingIndicatorHandler.swift b/PrivacyDemo/Shared/Helpers/LoadingIndicatorHandler.swift index 03da9c20b84f2c06e2843e06139c1c4fd6816965..88a9e7829c9941d87b32730fc6bce54794a38a60 100644 --- a/PrivacyDemo/Shared/Helpers/LoadingIndicatorHandler.swift +++ b/PrivacyDemo/Shared/Helpers/LoadingIndicatorHandler.swift @@ -5,13 +5,13 @@ struct LoadingIndicatorView { private var view: NVActivityIndicatorView! private var label: UILabel? - init(frame: CGRect = CGRect(x: UIScreen.main.bounds.midX-50, - y: UIScreen.main.bounds.midY-50, - width: 100.0, - height: 100.0), + init(frame: CGRect = CGRect(x: UIScreen.main.bounds.midX-100, + y: UIScreen.main.bounds.midY-100, + width: 200.0, + height: 200.0), color: UIColor = Constants.AppColors.appMainColor, type: NVActivityIndicatorType = .ballScaleRippleMultiple, - padding: CGFloat = 20.0, + padding: CGFloat = 50.0, background: UIColor = .white, cornerRadius: CGFloat = 10.0) { self.view = NVActivityIndicatorView(frame: frame, @@ -43,11 +43,12 @@ struct LoadingIndicatorView { } private func createLabel(_ text: String) -> UILabel { - let label = UILabel(frame: CGRect(x: self.view.frame.minX, y: self.view.frame.maxY-20, width: self.view.bounds.width, height: 20)) - label.font = UIFont(name: "Menlo", size: 10.0)! + let label = UILabel(frame: CGRect(x: self.view.frame.minX, y: self.view.frame.maxY-50, width: self.view.bounds.width, height: 50)) + label.font = UIFont(name: "Menlo", size: 12.0)! label.textColor = .black label.textAlignment = .center label.text = text + label.numberOfLines = 0 return label } } diff --git a/PrivacyDemo/Splash/Splash.storyboard b/PrivacyDemo/Splash/Splash.storyboard index 1d006885626a422021c2fbfee05cf7f03ea535b9..979ac2ed782cf6602a3ffb8b11a6a1532205e69b 100644 --- a/PrivacyDemo/Splash/Splash.storyboard +++ b/PrivacyDemo/Splash/Splash.storyboard @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="20037" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="Y6W-OH-hqX"> - <device id="retina6_0" orientation="portrait" appearance="light"/> + <device id="retina5_9" orientation="portrait" appearance="light"/> <dependencies> <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="20020"/> <capability name="Safe area layout guides" minToolsVersion="9.0"/> @@ -13,20 +13,20 @@ <objects> <viewController storyboardIdentifier="SplashViewController" id="Y6W-OH-hqX" customClass="SplashViewController" customModule="PrivacyDemo" customModuleProvider="target" sceneMemberID="viewController"> <view key="view" contentMode="scaleToFill" id="5EZ-qb-Rvc"> - <rect key="frame" x="0.0" y="0.0" width="390" height="844"/> + <rect key="frame" x="0.0" y="0.0" width="375" height="812"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <subviews> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="PhY-jf-b1c"> - <rect key="frame" x="39" y="321.66666666666669" width="312" height="211.00000000000006"/> + <rect key="frame" x="37.666666666666657" y="313.66666666666669" width="300" height="194.66666666666669"/> <subviews> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Shielded Help" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="UBa-19-Yu1"> - <rect key="frame" x="20" y="20" width="272" height="45"/> - <fontDescription key="fontDescription" name="Menlo-Bold" family="Menlo" pointSize="40"/> + <rect key="frame" x="20" y="20" width="260" height="68.666666666666671"/> + <fontDescription key="fontDescription" name="Helvetica-Bold" family="Helvetica" pointSize="40"/> <nil key="textColor"/> <nil key="highlightedColor"/> </label> <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="Shield" translatesAutoresizingMaskIntoConstraints="NO" id="D7F-Eb-J26"> - <rect key="frame" x="97" y="73" width="118" height="118"/> + <rect key="frame" x="111" y="96.666666666666629" width="77.666666666666686" height="78"/> <constraints> <constraint firstAttribute="width" secondItem="D7F-Eb-J26" secondAttribute="height" multiplier="1:1" id="2ms-fm-Oqg"/> </constraints> @@ -36,6 +36,7 @@ <constraints> <constraint firstAttribute="bottom" secondItem="D7F-Eb-J26" secondAttribute="bottom" constant="20.000000000000057" id="6O4-Ra-2Tl"/> <constraint firstItem="D7F-Eb-J26" firstAttribute="top" secondItem="UBa-19-Yu1" secondAttribute="bottom" constant="8" symbolic="YES" id="B4g-WV-dci"/> + <constraint firstItem="D7F-Eb-J26" firstAttribute="height" secondItem="PhY-jf-b1c" secondAttribute="height" multiplier="0.4" id="KAc-d0-9oB"/> <constraint firstAttribute="trailing" secondItem="UBa-19-Yu1" secondAttribute="trailing" constant="20" symbolic="YES" id="WTq-eX-9BT"/> <constraint firstItem="UBa-19-Yu1" firstAttribute="top" secondItem="PhY-jf-b1c" secondAttribute="top" constant="20" symbolic="YES" id="X9g-iq-vPs"/> <constraint firstItem="D7F-Eb-J26" firstAttribute="centerX" secondItem="PhY-jf-b1c" secondAttribute="centerX" id="cBC-BW-go2"/> @@ -47,7 +48,7 @@ <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> <constraints> <constraint firstItem="PhY-jf-b1c" firstAttribute="width" secondItem="5EZ-qb-Rvc" secondAttribute="width" multiplier="0.8" id="CpH-Np-Kaf"/> - <constraint firstItem="PhY-jf-b1c" firstAttribute="height" secondItem="5EZ-qb-Rvc" secondAttribute="height" multiplier="0.25" id="HXv-O6-yzw"/> + <constraint firstItem="PhY-jf-b1c" firstAttribute="height" secondItem="5EZ-qb-Rvc" secondAttribute="height" multiplier="0.24" id="HXv-O6-yzw"/> <constraint firstItem="PhY-jf-b1c" firstAttribute="centerX" secondItem="vDu-zF-Fre" secondAttribute="centerX" id="ct5-ri-gX9"/> <constraint firstItem="PhY-jf-b1c" firstAttribute="centerY" secondItem="vDu-zF-Fre" secondAttribute="centerY" id="o35-bW-hCF"/> </constraints> diff --git a/README.md b/README.md index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..acad6215fd65b191385ba13203c2aab08351ab1d 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,17 @@ +# Privacy demo by Elixxir + +This is an example of how to build an app with the [ElixxirSDK](https://git.xx.network/elixxir/elixxir-dapps-sdk-swift) to send `E2E` messages and send `RestLike` messsage. + + +## 📘 Usage + +Set values in `AppConstants.swift` for the 4 constants `restlikeRecipentContact1` `restlikeRecipentContact2` `restlikeRecipentContact3` and `chatRecipentContact` + +You need to get these value from your remote or server. You can know more about it [here](https://xxdk-dev.xx.network) + + +## 📄 License + +Copyright © 2022 xx network SEZC + +[License](LICENSE)