28.03.2022

28.03.2022
parent 44125929
......@@ -48,9 +48,18 @@
D5B0201A27C382A600C4BA4F /* Artwork.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5B0201927C382A600C4BA4F /* Artwork.swift */; };
D5C001D027DA60CB0045F6BE /* StartNavigationVCViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5C001CF27DA60CB0045F6BE /* StartNavigationVCViewController.swift */; };
D5C59AF127CFD1810013EFBB /* netwok.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5C59AF027CFD1810013EFBB /* netwok.swift */; };
D5CB9A2827ECCE9A000F8500 /* StringExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5CB9A1E27ECCE99000F8500 /* StringExtension.swift */; };
D5CB9A2927ECCE9A000F8500 /* Message.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5CB9A1F27ECCE99000F8500 /* Message.swift */; };
D5CB9A2B27ECCE9A000F8500 /* ChatRoom.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5CB9A2127ECCE99000F8500 /* ChatRoom.swift */; };
D5CB9A2C27ECCE9A000F8500 /* MessageTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5CB9A2227ECCE99000F8500 /* MessageTableViewCell.swift */; };
D5CB9A2E27ECCE9A000F8500 /* Label.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5CB9A2427ECCE99000F8500 /* Label.swift */; };
D5CB9A2F27ECCE9A000F8500 /* ChatRoomViewController+Table.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5CB9A2527ECCE99000F8500 /* ChatRoomViewController+Table.swift */; };
D5CB9A3027ECCE9A000F8500 /* Layouts.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5CB9A2627ECCE9A000F8500 /* Layouts.swift */; };
D5CB9A3127ECCE9A000F8500 /* MessageInputView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5CB9A2727ECCE9A000F8500 /* MessageInputView.swift */; };
D5CF729E27DFB3500026392B /* ListWorkViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5CF729D27DFB3500026392B /* ListWorkViewController.swift */; };
D5D6F1A627E77D4A008106EE /* DoubleElectricVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5D6F1A527E77D4A008106EE /* DoubleElectricVC.swift */; };
D5D82C8D27D21B070068A5B9 /* SettingsLauncher.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5D82C8C27D21B070068A5B9 /* SettingsLauncher.swift */; };
D5DF4AB427F0B5DE00C7DE48 /* CallProfiViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5DF4AB327F0B5DE00C7DE48 /* CallProfiViewController.swift */; };
D5E2042427CE2DD90063A514 /* ProfileViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5E2042327CE2DD90063A514 /* ProfileViewController.swift */; };
D5E2042927CE30E20063A514 /* DataProfileViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5E2042827CE30E20063A514 /* DataProfileViewController.swift */; };
D5E31B2A27BCE16700F5B87D /* PlumViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5E31B2927BCE16700F5B87D /* PlumViewController.swift */; };
......@@ -128,9 +137,18 @@
D5B0201927C382A600C4BA4F /* Artwork.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Artwork.swift; sourceTree = "<group>"; };
D5C001CF27DA60CB0045F6BE /* StartNavigationVCViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StartNavigationVCViewController.swift; sourceTree = "<group>"; };
D5C59AF027CFD1810013EFBB /* netwok.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = netwok.swift; sourceTree = "<group>"; };
D5CB9A1E27ECCE99000F8500 /* StringExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StringExtension.swift; sourceTree = "<group>"; };
D5CB9A1F27ECCE99000F8500 /* Message.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Message.swift; sourceTree = "<group>"; };
D5CB9A2127ECCE99000F8500 /* ChatRoom.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChatRoom.swift; sourceTree = "<group>"; };
D5CB9A2227ECCE99000F8500 /* MessageTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageTableViewCell.swift; sourceTree = "<group>"; };
D5CB9A2427ECCE99000F8500 /* Label.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Label.swift; sourceTree = "<group>"; };
D5CB9A2527ECCE99000F8500 /* ChatRoomViewController+Table.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "ChatRoomViewController+Table.swift"; sourceTree = "<group>"; };
D5CB9A2627ECCE9A000F8500 /* Layouts.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Layouts.swift; sourceTree = "<group>"; };
D5CB9A2727ECCE9A000F8500 /* MessageInputView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageInputView.swift; sourceTree = "<group>"; };
D5CF729D27DFB3500026392B /* ListWorkViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListWorkViewController.swift; sourceTree = "<group>"; };
D5D6F1A527E77D4A008106EE /* DoubleElectricVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DoubleElectricVC.swift; sourceTree = "<group>"; };
D5D82C8C27D21B070068A5B9 /* SettingsLauncher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsLauncher.swift; sourceTree = "<group>"; };
D5DF4AB327F0B5DE00C7DE48 /* CallProfiViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallProfiViewController.swift; sourceTree = "<group>"; };
D5E2042327CE2DD90063A514 /* ProfileViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileViewController.swift; sourceTree = "<group>"; };
D5E2042827CE30E20063A514 /* DataProfileViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataProfileViewController.swift; sourceTree = "<group>"; };
D5E31B2927BCE16700F5B87D /* PlumViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlumViewController.swift; sourceTree = "<group>"; };
......@@ -199,6 +217,7 @@
D5E2042827CE30E20063A514 /* DataProfileViewController.swift */,
D5C001CF27DA60CB0045F6BE /* StartNavigationVCViewController.swift */,
D5D6F1A527E77D4A008106EE /* DoubleElectricVC.swift */,
D5DF4AB327F0B5DE00C7DE48 /* CallProfiViewController.swift */,
);
path = VC;
sourceTree = "<group>";
......@@ -264,6 +283,7 @@
D569AB5F27B8E27A0013DCFE /* Em-call */ = {
isa = PBXGroup;
children = (
D5CB99E727ECCD09000F8500 /* Chat */,
D53F560927E62D7600C18B2A /* SmallListWorkVC.swift */,
D53F560A27E62D7600C18B2A /* SmallListWorkVC.xib */,
D53F55F827E5D0F600C18B2A /* SwipeAble */,
......@@ -318,6 +338,21 @@
path = Addition;
sourceTree = "<group>";
};
D5CB99E727ECCD09000F8500 /* Chat */ = {
isa = PBXGroup;
children = (
D5CB9A2127ECCE99000F8500 /* ChatRoom.swift */,
D5CB9A2527ECCE99000F8500 /* ChatRoomViewController+Table.swift */,
D5CB9A2427ECCE99000F8500 /* Label.swift */,
D5CB9A2627ECCE9A000F8500 /* Layouts.swift */,
D5CB9A1F27ECCE99000F8500 /* Message.swift */,
D5CB9A2727ECCE9A000F8500 /* MessageInputView.swift */,
D5CB9A2227ECCE99000F8500 /* MessageTableViewCell.swift */,
D5CB9A1E27ECCE99000F8500 /* StringExtension.swift */,
);
path = Chat;
sourceTree = "<group>";
};
D5CF729927DFB2A90026392B /* Glide */ = {
isa = PBXGroup;
children = (
......@@ -538,17 +573,23 @@
D5F0238827C4E2AA008F4146 /* ShowAlert.swift in Sources */,
D5E31B3227BCEC0900F5B87D /* CollectionViewCell.swift in Sources */,
D558EA5C27BE4A6C003C4578 /* HandmanViewController.swift in Sources */,
D5CB9A2B27ECCE9A000F8500 /* ChatRoom.swift in Sources */,
D53F55FC27E5D12700C18B2A /* SwipeableItems.swift in Sources */,
D5CF729E27DFB3500026392B /* ListWorkViewController.swift in Sources */,
D55E88FA27DE124B00DB59E7 /* Collection.swift in Sources */,
D5E2042427CE2DD90063A514 /* ProfileViewController.swift in Sources */,
D55E88F327DE124B00DB59E7 /* GlidingCollection.swift in Sources */,
D5CB9A3027ECCE9A000F8500 /* Layouts.swift in Sources */,
D5E31B2A27BCE16700F5B87D /* PlumViewController.swift in Sources */,
D55E88F627DE124B00DB59E7 /* GlidingLayout.swift in Sources */,
D5CB9A2E27ECCE9A000F8500 /* Label.swift in Sources */,
D569AB6B27B8E27A0013DCFE /* Em_call.xcdatamodeld in Sources */,
D5CB9A3127ECCE9A000F8500 /* MessageInputView.swift in Sources */,
D569AB6127B8E27A0013DCFE /* AppDelegate.swift in Sources */,
D53F560B27E62D7600C18B2A /* SmallListWorkVC.swift in Sources */,
D55E88F827DE124B00DB59E7 /* GlidingCollectionDelegate.swift in Sources */,
D5CB9A2F27ECCE9A000F8500 /* ChatRoomViewController+Table.swift in Sources */,
D5CB9A2927ECCE9A000F8500 /* Message.swift in Sources */,
D55E88F427DE124B00DB59E7 /* CollectionCell.swift in Sources */,
D55E88FB27DE124B00DB59E7 /* FileManager.swift in Sources */,
D5E31B3727BD578F00F5B87D /* PlumbersViewController.swift in Sources */,
......@@ -558,15 +599,18 @@
D59E3CE027D3B03F008A7E0C /* SettingCell.swift in Sources */,
D5B0201A27C382A600C4BA4F /* Artwork.swift in Sources */,
D55E88F927DE124B00DB59E7 /* GlidingConfig.swift in Sources */,
D5CB9A2C27ECCE9A000F8500 /* MessageTableViewCell.swift in Sources */,
D56E5D6D27C26F2500D0E4B9 /* StartViewController.swift in Sources */,
D5F0236F27C4DAD8008F4146 /* ChangePswViewController.swift in Sources */,
D5057F9D27BA5E940015C0DC /* VKBookingViewController.swift in Sources */,
D5F0236A27C4DAC2008F4146 /* RegistrationViewController.swift in Sources */,
D558EA6127BE4C65003C4578 /* EmerHandViewController.swift in Sources */,
D514860727BB7FD7006830A3 /* ChatViewController.swift in Sources */,
D5CB9A2827ECCE9A000F8500 /* StringExtension.swift in Sources */,
D5B0201527C3826800C4BA4F /* ArtworkViews.swift in Sources */,
D5C001D027DA60CB0045F6BE /* StartNavigationVCViewController.swift in Sources */,
D569AB6327B8E27A0013DCFE /* SceneDelegate.swift in Sources */,
D5DF4AB427F0B5DE00C7DE48 /* CallProfiViewController.swift in Sources */,
D5B0201027C37BBE00C4BA4F /* MainViewController.swift in Sources */,
D59E3CE527D3B37B008A7E0C /* Extensions.swift in Sources */,
D5D6F1A627E77D4A008106EE /* DoubleElectricVC.swift in Sources */,
......
......@@ -16,8 +16,8 @@
endingColumnNumber = "9223372036854775807"
startingLineNumber = "42"
endingLineNumber = "42"
landmarkName = "viewDidLoad()"
landmarkType = "7">
landmarkName = "unknown"
landmarkType = "0">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
......@@ -46,8 +46,8 @@
filePath = "Em-call/VC/MainViewController.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "227"
endingLineNumber = "227"
startingLineNumber = "214"
endingLineNumber = "214"
landmarkName = "coordinateToAdress(_:)"
landmarkType = "7">
</BreakpointContent>
......@@ -62,8 +62,8 @@
filePath = "Em-call/VC/HandmanViewController.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "216"
endingLineNumber = "216"
startingLineNumber = "227"
endingLineNumber = "227"
landmarkName = "delegateClick(text:)"
landmarkType = "7">
</BreakpointContent>
......@@ -78,8 +78,8 @@
filePath = "Em-call/VC/HandmanViewController.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "225"
endingLineNumber = "225"
startingLineNumber = "236"
endingLineNumber = "236"
landmarkName = "calendarDelegateClick(text:flagData:)"
landmarkType = "7">
</BreakpointContent>
......@@ -190,8 +190,8 @@
filePath = "Em-call/VC/MainViewController.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "107"
endingLineNumber = "107"
startingLineNumber = "91"
endingLineNumber = "91"
landmarkName = "viewDidLoad()"
landmarkType = "7">
</BreakpointContent>
......@@ -206,8 +206,8 @@
filePath = "Em-call/VC/MainViewController.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "126"
endingLineNumber = "126"
startingLineNumber = "113"
endingLineNumber = "113"
landmarkName = "viewDidAppear(_:)"
landmarkType = "7">
</BreakpointContent>
......@@ -302,10 +302,10 @@
filePath = "Em-call/VC/ElectricTableViewController.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "191"
endingLineNumber = "191"
landmarkName = "delegateClick(text:)"
landmarkType = "7">
startingLineNumber = "224"
endingLineNumber = "224"
landmarkName = "unknown"
landmarkType = "0">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
......@@ -318,8 +318,8 @@
filePath = "Em-call/VC/EmerElecricianViewController.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "25"
endingLineNumber = "25"
startingLineNumber = "24"
endingLineNumber = "24"
landmarkName = "viewDidLoad()"
landmarkType = "7">
</BreakpointContent>
......
......@@ -142,8 +142,8 @@
filePath = "Em-call/Data/SettingsLauncher.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "191"
endingLineNumber = "191"
startingLineNumber = "192"
endingLineNumber = "192"
landmarkName = "imagePickerController(_:didFinishPickingMediaWithInfo:)"
landmarkType = "7">
</BreakpointContent>
......@@ -158,8 +158,8 @@
filePath = "Em-call/VC/MainViewController.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "99"
endingLineNumber = "99"
startingLineNumber = "83"
endingLineNumber = "83"
landmarkName = "viewDidLoad()"
landmarkType = "7">
</BreakpointContent>
......@@ -174,8 +174,8 @@
filePath = "Em-call/VC/MainViewController.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "142"
endingLineNumber = "142"
startingLineNumber = "129"
endingLineNumber = "129"
landmarkName = "viewWillAppear(_:)"
landmarkType = "7">
</BreakpointContent>
......@@ -270,28 +270,12 @@
filePath = "Em-call/VC/MainViewController.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "151"
endingLineNumber = "151"
startingLineNumber = "138"
endingLineNumber = "138"
landmarkName = "viewWillDisappear(_:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "1D277C88-21DD-4FDF-8A59-20D31F1943AE"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "Em-call/Addition/ListWorkViewController.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "97"
endingLineNumber = "97"
landmarkName = "ListWorkViewController"
landmarkType = "3">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
......@@ -365,9 +349,313 @@
filePath = "Em-call/VC/MainViewController.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "120"
endingLineNumber = "120"
landmarkName = "viewDidAppear(_:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "3586903C-1BEB-46AC-9196-B1C05B3B126F"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "Em-call/Chat/ChatRoom.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "133"
endingLineNumber = "133"
landmarkName = "viewDidAppear(_:)"
landmarkName = "stream(_:handle:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "B344AF0E-FFAB-49EB-AAFE-9710D493109D"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "Em-call/Chat/ChatRoom.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "135"
endingLineNumber = "135"
landmarkName = "stream(_:handle:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "0C7245F0-D831-4851-A20A-D110D75773E3"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "Em-call/Chat/ChatRoom.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "137"
endingLineNumber = "137"
landmarkName = "stream(_:handle:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "C896D661-D060-4027-B006-8AB0ACB7BBAF"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "Em-call/Chat/ChatRoom.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "81"
endingLineNumber = "81"
landmarkName = "joinChat(username:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "3FAE08FE-E6C8-4921-8273-F6BDF688702F"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "Em-call/Chat/ChatRoom.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "94"
endingLineNumber = "94"
landmarkName = "send(message:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "113CF7DA-1BA8-4DC9-B113-0398D7502652"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "Em-call/VC/ChatViewController.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "49"
endingLineNumber = "49"
landmarkName = "viewWillDisappear(_:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "7BF1837A-022E-4B94-8149-74E8C96B61FB"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "Em-call/Chat/MessageInputView.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "64"
endingLineNumber = "64"
landmarkName = "sendTapped()"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "EB4E0CBF-0D45-4658-B307-5FD1C215E68E"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "Em-call/Chat/ChatRoom.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "91"
endingLineNumber = "91"
landmarkName = "send(message:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "BA59213A-9BDF-4BF9-A03E-9486BE8EF9CE"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "Em-call/VC/ChatViewController.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "69"
endingLineNumber = "69"
landmarkName = "sendWasTapped(message:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "74EB8168-5D51-447C-880A-8A63858021D5"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "Em-call/Chat/MessageInputView.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "43"
endingLineNumber = "43"
landmarkName = "init(frame:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "9EDCFC4A-C54C-4AFA-888D-CB16510E1436"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "Em-call/Chat/MessageInputView.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "75"
endingLineNumber = "75"
landmarkName = "layoutSubviews()"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "79698E8E-786C-46E5-B914-753311509985"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "Em-call/Chat/MessageInputView.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "87"
endingLineNumber = "87"
landmarkName = "textViewShouldEndEditing(_:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "785D0C1C-541D-4C4A-9A77-90AD516DF0E2"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "Em-call/Chat/MessageInputView.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "89"
endingLineNumber = "89"
landmarkName = "textViewShouldEndEditing(_:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "741F380F-AB6D-4BA5-8450-EED604170459"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "Em-call/Chat/MessageInputView.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "88"
endingLineNumber = "88"
landmarkName = "textViewShouldEndEditing(_:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "B1633F28-12CC-4FF1-A45B-1E8929CB12B0"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "Em-call/Chat/MessageInputView.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "77"
endingLineNumber = "77"
landmarkName = "layoutSubviews()"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "3EB9BD12-531C-41D8-9CC5-1CA726900CF0"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "Em-call/VC/ChatViewController.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "75"
endingLineNumber = "75"
landmarkName = "received(message:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "DCD65096-07DD-41D7-BA23-6C72AB46E098"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "Em-call/Chat/Layouts.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "137"
endingLineNumber = "137"
landmarkName = "layoutForJoinMessage()"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "F298AEE1-F453-4C8B-A900-C8EDA33ED320"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "Em-call/Chat/MessageInputView.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "91"
endingLineNumber = "91"
landmarkName = "textViewShouldBeginEditing(_:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "370E7CD1-C0F0-46DF-BF51-B874CF92E0FE"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "Em-call/Chat/ChatRoom.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "153"
endingLineNumber = "153"
landmarkName = "readAvailableBytes(stream:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
......
......@@ -37,50 +37,53 @@ class ListWorkViewController: UIViewController {
// view.addGestureRecognizer(gesture)
roundViews()
}
/*
@objc func panGesture(_ recognizer: UIPanGestureRecognizer) {
let translation = recognizer.translation(in: self.view)
let velocity = recognizer.velocity(in: self.view)
let y = self.view.frame.minY
if (y + translation.y >= fullView) && (y + translation.y <= partialView) {
self.view.frame = CGRect(x: 0, y: y + translation.y, width: view.frame.width, height: view.frame.height)
recognizer.setTranslation(CGPoint.zero, in: self.view)
}
if recognizer.state == .ended {
var duration = velocity.y < 0 ? Double((y - fullView) / -velocity.y) : Double((partialView - y) / velocity.y )
duration = duration > 1.3 ? 1 : duration
UIView.animate(withDuration: duration, delay: 0.0, options: [.allowUserInteraction], animations: {
if velocity.y >= 0 {
self.view.frame = CGRect(x: 0, y: self.partialView, width: self.view.frame.width, height: self.view.frame.height)
} else {
self.view.frame = CGRect(x: 0, y: self.fullView, width: self.view.frame.width, height: self.view.frame.height)
}
}, completion: { [weak self] _ in
if ( velocity.y < 0 ) {
self?.debug = 1
}
})
}
@IBAction func pressBottomPanel(_ sender: Any) {
callElectric()
}
func prepareBackgroundView(){
let blurEffect = UIBlurEffect.init(style: .dark)
let visualEffect = UIVisualEffectView.init(effect: blurEffect)
let bluredView = UIVisualEffectView.init(effect: blurEffect)
bluredView.contentView.addSubview(visualEffect)
visualEffect.frame = UIScreen.main.bounds
bluredView.frame = UIScreen.main.bounds
view.insertSubview(bluredView, at: 0)
func callElectric()
{
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc:UIViewController
if #available(iOS 13.0, *) {
vc = storyboard.instantiateViewController(identifier: "Double_ElectricVC") as! DoubleElectricVC
} else {
vc = storyboard.instantiateViewController(withIdentifier: "Double_ElectricVC")
}
self.navigationController?.push(viewController: vc)
}
@IBAction func pressWorkType_1(_ sender: Any) {
callElectric()
}
@IBAction func pressWorkType_4(_ sender: Any) {
callElectric()
}
@IBAction func pressWorkType_5(_ sender: Any) {
callElectric()
}
@IBAction func pressWorkType_6(_ sender: Any) {
callElectric()
}
@IBAction func pressWorkType_7(_ sender: Any) {
callElectric()
}
@IBAction func pressWorkType_8(_ sender: Any) {
callElectric()
}
@IBAction func pressWorkType_9(_ sender: Any) {
callElectric()
}
*/
@IBAction func pressWorkType_2(_ sender: Any) {
callElectric()
}
@IBAction func pressWorkType_3(_ sender: Any) {
callElectric()
}
func roundViews() {
view.layer.cornerRadius = 5
......@@ -92,16 +95,7 @@ class ListWorkViewController: UIViewController {
view.clipsToBounds = true
}
/*
func panGesture(recognizer: UIPanGestureRecognizer) {
let translation = recognizer.translation(in: self.view)
let y = self.view.frame.minY
self.view.frame = CGRect(x: 0, y: y + translation.y, width: view.frame.width, height: view.frame.height)
// recognizer.setTranslation(CoreGraphics.CGPointZero, in: self.view)
recognizer.setTranslation(CGPoint(x: 0, y: 0), in: self.view)
// CGRect(x: 0, y: y + translation.y, width: view.frame.width, height: view.frame.height)
}
*/
override func viewDidAppear(_ animated: Bool) {
/*
UIView.animate(withDuration: 0.6, animations: { [weak self] in
......@@ -122,9 +116,6 @@ class ListWorkViewController: UIViewController {
super.viewWillAppear(animated)
// prepareBackgroundView()
}
}
extension ListWorkViewController: UIGestureRecognizerDelegate {
......@@ -144,5 +135,59 @@ extension ListWorkViewController: UIGestureRecognizerDelegate {
return false
}
}
/*
@objc func panGesture(_ recognizer: UIPanGestureRecognizer) {
let translation = recognizer.translation(in: self.view)
let velocity = recognizer.velocity(in: self.view)
let y = self.view.frame.minY
if (y + translation.y >= fullView) && (y + translation.y <= partialView) {
self.view.frame = CGRect(x: 0, y: y + translation.y, width: view.frame.width, height: view.frame.height)
recognizer.setTranslation(CGPoint.zero, in: self.view)
}
if recognizer.state == .ended {
var duration = velocity.y < 0 ? Double((y - fullView) / -velocity.y) : Double((partialView - y) / velocity.y )
duration = duration > 1.3 ? 1 : duration
UIView.animate(withDuration: duration, delay: 0.0, options: [.allowUserInteraction], animations: {
if velocity.y >= 0 {
self.view.frame = CGRect(x: 0, y: self.partialView, width: self.view.frame.width, height: self.view.frame.height)
} else {
self.view.frame = CGRect(x: 0, y: self.fullView, width: self.view.frame.width, height: self.view.frame.height)
}
}, completion: { [weak self] _ in
if ( velocity.y < 0 ) {
self?.debug = 1
}
})
}
}
func prepareBackgroundView(){
let blurEffect = UIBlurEffect.init(style: .dark)
let visualEffect = UIVisualEffectView.init(effect: blurEffect)
let bluredView = UIVisualEffectView.init(effect: blurEffect)
bluredView.contentView.addSubview(visualEffect)
visualEffect.frame = UIScreen.main.bounds
bluredView.frame = UIScreen.main.bounds
view.insertSubview(bluredView, at: 0)
}
*/
/*
func panGesture(recognizer: UIPanGestureRecognizer) {
let translation = recognizer.translation(in: self.view)
let y = self.view.frame.minY
self.view.frame = CGRect(x: 0, y: y + translation.y, width: view.frame.width, height: view.frame.height)
// recognizer.setTranslation(CoreGraphics.CGPointZero, in: self.view)
recognizer.setTranslation(CGPoint(x: 0, y: 0), in: self.view)
// CGRect(x: 0, y: y + translation.y, width: view.frame.width, height: view.frame.height)
}
*/
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "akar-icons_arrow-left.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "eva_pin-fill.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "gg_close.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "uil_arrow-right.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
This source diff could not be displayed because it is too large. You can view the blob instead.
/// Copyright (c) 2019 Razeware LLC
///
/// 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.
///
/// Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
/// distribute, sublicense, create a derivative work, and/or sell copies of the
/// Software in any work that is designed, intended, or marketed for pedagogical or
/// instructional purposes related to programming, coding, application development,
/// or information technology. Permission for such use, copying, modification,
/// merger, publication, distribution, sublicensing, creation of derivative works,
/// or sale is expressly withheld.
///
/// 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.
import UIKit
protocol ChatRoomDelegate: class {
func received(message: Message)
}
class ChatRoom: NSObject {
//1
var inputStream: InputStream!
var outputStream: OutputStream!
weak var delegate: ChatRoomDelegate?
//2
var username = "Lex"
var startSetupNet = 0
//3
let maxReadLength = 4096
//debug
let SERVER_NO = 1
func setupNetworkCommunication() {
startSetupNet = 1
// 1
var readStream: Unmanaged<CFReadStream>?
var writeStream: Unmanaged<CFWriteStream>?
// 2
CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault,
"localhost" as CFString,
80,
&readStream,
&writeStream)
inputStream = readStream!.takeRetainedValue()
outputStream = writeStream!.takeRetainedValue()
inputStream.delegate = self
inputStream.schedule(in: .current, forMode: .common)
outputStream.schedule(in: .current, forMode: .common)
inputStream.open()
outputStream.open()
}
func joinChat(username: String) {
//1
let data = "iam:\(username)".data(using: .utf8)!
//2
self.username = username
//3
data.withUnsafeBytes {
guard let pointer = $0.baseAddress?.assumingMemoryBound(to: UInt8.self) else {
print("Error joining chat")
return
}
//4
outputStream.write(pointer, maxLength: data.count)
}
}
func send(message: String) {
if SERVER_NO == 0 {
let data = "msg:\(message)".data(using: .utf8)!
data.withUnsafeBytes {
guard let pointer = $0.baseAddress?.assumingMemoryBound(to: UInt8.self) else {
print("Error joining chat")
return
}
outputStream.write(pointer, maxLength: data.count)
}
} else {
var messageSender: MessageSender = ("Lex" == self.username) ? .ourself : .someoneElse
var msg = Message(message: message, messageSender: messageSender, username: "Lex")
delegate?.received(message: msg)
messageSender = .someoneElse
msg = Message(message: message, messageSender: messageSender, username: "Alex")
delegate?.received(message: msg)
}
}
func stopChatSession() {
if SERVER_NO == 0 {
if startSetupNet == 1 {
inputStream.close()
outputStream.close()
startSetupNet = 0
} else {
startSetupNet = 0
}
}
}
}
extension ChatRoom: StreamDelegate {
func stream(_ aStream: Stream, handle eventCode: Stream.Event) {
switch eventCode {
case .hasBytesAvailable:
print("new message received")
readAvailableBytes(stream: aStream as! InputStream)
case .endEncountered:
print("new message received")
stopChatSession()
case .errorOccurred:
print("error occurred")
case .hasSpaceAvailable:
print("has space available")
default:
print("some other event...")
}
}
private func readAvailableBytes(stream: InputStream) {
let buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: maxReadLength)
while stream.hasBytesAvailable {
let numberOfBytesRead = inputStream.read(buffer, maxLength: maxReadLength)
if numberOfBytesRead < 0, let error = stream.streamError {
print(error)
break
}
// Construct the message object
if let message = processedMessageString(buffer: buffer, length: numberOfBytesRead) {
// Notify interested parties
delegate?.received(message: message)
}
}
}
private func processedMessageString(buffer: UnsafeMutablePointer<UInt8>,
length: Int) -> Message? {
//1
guard
let stringArray = String(
bytesNoCopy: buffer,
length: length,
encoding: .utf8,
freeWhenDone: true)?.components(separatedBy: ":"),
let name = stringArray.first,
let message = stringArray.last
else {
return nil
}
//2
let messageSender: MessageSender = (name == self.username) ? .ourself : .someoneElse
//3
return Message(message: message, messageSender: messageSender, username: name)
}
}
/// Copyright (c) 2019 Razeware LLC
///
/// 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.
///
/// Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
/// distribute, sublicense, create a derivative work, and/or sell copies of the
/// Software in any work that is designed, intended, or marketed for pedagogical or
/// instructional purposes related to programming, coding, application development,
/// or information technology. Permission for such use, copying, modification,
/// merger, publication, distribution, sublicensing, creation of derivative works,
/// or sale is expressly withheld.
///
/// 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.
import UIKit
extension ChatViewController: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = MessageTableViewCell(style: .default, reuseIdentifier: "MessageCell")
cell.selectionStyle = .none
let message = messages[indexPath.row]
cell.apply(message: message)
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return messages.count
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
let height = MessageTableViewCell.height(for: messages[indexPath.row])
return height
}
func insertNewMessageCell(_ message: Message) {
messages.append(message)
let indexPath = IndexPath(row: messages.count - 1, section: 0)
tableView.beginUpdates()
tableView.insertRows(at: [indexPath], with: .bottom)
tableView.endUpdates()
tableView.scrollToRow(at: indexPath, at: .bottom, animated: true)
}
}
/// Copyright (c) 2019 Razeware LLC
///
/// 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.
///
/// Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
/// distribute, sublicense, create a derivative work, and/or sell copies of the
/// Software in any work that is designed, intended, or marketed for pedagogical or
/// instructional purposes related to programming, coding, application development,
/// or information technology. Permission for such use, copying, modification,
/// merger, publication, distribution, sublicensing, creation of derivative works,
/// or sale is expressly withheld.
///
/// 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.
import UIKit
class JoinChatViewController: UIViewController {
let logoImageView = UIImageView()
let shadowView = UIView()
// let nameTextField = TextField()
}
/*
extension JoinChatViewController: UITextFieldDelegate {
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
let chatRoomVC = ChatRoomViewController()
if let username = nameTextField.text {
chatRoomVC.username = username
}
navigationController?.pushViewController(chatRoomVC, animated: true)
return true
}
}
class TextField: UITextField {
let padding = UIEdgeInsets(top: 0, left: 16, bottom: 0, right: 8)
override func textRect(forBounds bounds: CGRect) -> CGRect {
return bounds.inset(by: padding)
}
override func placeholderRect(forBounds bounds: CGRect) -> CGRect {
return bounds.inset(by: padding)
}
override func editingRect(forBounds bounds: CGRect) -> CGRect {
return bounds.inset(by: padding)
}
}
*/
/// Copyright (c) 2019 Razeware LLC
///
/// 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.
///
/// Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
/// distribute, sublicense, create a derivative work, and/or sell copies of the
/// Software in any work that is designed, intended, or marketed for pedagogical or
/// instructional purposes related to programming, coding, application development,
/// or information technology. Permission for such use, copying, modification,
/// merger, publication, distribution, sublicensing, creation of derivative works,
/// or sale is expressly withheld.
///
/// 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.
import UIKit
class Label: UILabel {
override func drawText(in rect: CGRect) {
let insets = UIEdgeInsets.init(top: 8, left: 16, bottom: 8, right: 16)
super.drawText(in: rect.inset(by: insets))
}
}
/// Copyright (c) 2019 Razeware LLC
///
/// 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.
///
/// Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
/// distribute, sublicense, create a derivative work, and/or sell copies of the
/// Software in any work that is designed, intended, or marketed for pedagogical or
/// instructional purposes related to programming, coding, application development,
/// or information technology. Permission for such use, copying, modification,
/// merger, publication, distribution, sublicensing, creation of derivative works,
/// or sale is expressly withheld.
///
/// 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.
import UIKit
extension ChatViewController {
override func viewDidLoad() {
super.viewDidLoad()
let rightBarButtonItem = UIBarButtonItem(image: UIImage(named: "but_left"), style: .done, target: self, action: #selector(call_Method))
// Для Tab bar
self.tabBarController?.navigationItem.rightBarButtonItems = [rightBarButtonItem]
// Для NavigationController
self.navigationController?.navigationItem.rightBarButtonItems = [rightBarButtonItem]
// Обязательно! добавить @objc
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillChange(notification:)), name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
// loadViews()
}
@objc func keyboardWillChange(notification: NSNotification) {
/* if let userInfo = notification.userInfo {
let endFrame = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)!.cgRectValue
let messageBarHeight = messageInputBar.bounds.size.height
let point = CGPoint(x: messageInputBar.center.x, y: endFrame.origin.y - messageBarHeight/2.0)
let inset = UIEdgeInsets(top: 0, left: 0, bottom: endFrame.size.height, right: 0)
UIView.animate(withDuration: 0.25) {
self.messageInputBar.center = point
self.tableView.contentInset = inset
}
}*/
}
func loadViews() {
navigationItem.title = "CHAT"
//navigationItem.backBarButtonItem?.title = "Run!"
view.backgroundColor = UIColor(red: 24 / 255, green: 180 / 255, blue: 128 / 255, alpha: 1.0)
tableView.dataSource = self
tableView.delegate = self
tableView.separatorStyle = .none
view.addSubview(tableView)
view.addSubview(messageInputBar)
messageInputBar.delegate = self
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
let messageBarHeight:CGFloat = 60.0
let size = view.bounds.size
tableView.frame = CGRect(x: 0, y: 0, width: size.width, height: size.height - messageBarHeight - view.safeAreaInsets.bottom)
messageInputBar.frame = CGRect(x: 0, y: size.height - messageBarHeight - view.safeAreaInsets.bottom, width: size.width, height: messageBarHeight)
}
}
extension MessageTableViewCell {
override func layoutSubviews() {
super.layoutSubviews()
if isJoinMessage() {
layoutForJoinMessage()
} else {
// messageLabel.font = UIFont(name: "Helvetica", size: 17)
messageLabel.font = UIFont(name: "Helvetica", size: 17)
messageLabel.textColor = .darkGray
nameLabel.font = UIFont(name: "Helvetica", size: 12)
nameLabel.textColor = .lightGray
nameLabel.backgroundColor = UIColor(red: 229 / 255, green: 240 / 255, blue: 255 / 255, alpha: 1.0)
let size = messageLabel.sizeThatFits(CGSize(width: 2 * (bounds.size.width / 3), height: .greatestFiniteMagnitude))
messageLabel.frame = CGRect(x: 0, y: 0, width: size.width + 32, height: size.height + 16)
if messageSender == .ourself {
//nameLabel.isHidden = true
nameLabel.isHidden = false
nameLabel.center = CGPoint(x: nameLabel.bounds.size.width / 2.0 + 16 + 4, y: nameLabel.bounds.size.height/2.0 + 4)
messageLabel.center = CGPoint(x: messageLabel.bounds.size.width / 2.0 + 16, y: messageLabel.bounds.size.height/2.0 + nameLabel.bounds.size.height + 8)
// messageLabel.backgroundColor = .lightGray
messageLabel.backgroundColor = UIColor(red: 237 / 255, green: 237 / 255, blue: 237 / 255, alpha: 1.0)
/*
messageLabel.center = CGPoint(x: bounds.size.width - messageLabel.bounds.size.width/2.0 - 16, y: bounds.size.height/2.0)
messageLabel.backgroundColor = UIColor(red: 229 / 255, green: 240 / 255, blue: 255 / 255, alpha: 1.0) //серо-голубой
*/
} else {
nameLabel.isHidden = false
nameLabel.sizeToFit()
nameLabel.center = CGPoint(x: bounds.size.width / 2.0 + 16 + 4, y: nameLabel.bounds.size.height/2.0 + 4)
messageLabel.center = CGPoint(x: bounds.size.width - messageLabel.bounds.size.width/2.0 - 16, y: bounds.size.height/2.0)
messageLabel.backgroundColor = UIColor(red: 229 / 255, green: 240 / 255, blue: 255 / 255, alpha: 1.0) //серо-голубой
/*
nameLabel.center = CGPoint(x: nameLabel.bounds.size.width / 2.0 + 16 + 4, y: nameLabel.bounds.size.height/2.0 + 4)
messageLabel.center = CGPoint(x: messageLabel.bounds.size.width / 2.0 + 16, y: messageLabel.bounds.size.height/2.0 + nameLabel.bounds.size.height + 8)
messageLabel.backgroundColor = UIColor(red: 237 / 255, green: 237 / 255, blue: 237 / 255, alpha: 1.0)
*/
}
}
messageLabel.layer.cornerRadius = min(messageLabel.bounds.size.height / 2.0, 10)
}
func layoutForJoinMessage() {
messageLabel.font = UIFont.systemFont(ofSize: 12)
messageLabel.textColor = .lightGray
messageLabel.backgroundColor = UIColor(red: 247 / 255, green: 247 / 255, blue: 247 / 255, alpha: 1.0)
// messageLabel.backgroundColor = UIColor(red: 237 / 255, green: 237 / 255, blue: 237 / 255, alpha: 1.0)
let size = messageLabel.sizeThatFits(CGSize(width: 2 * (bounds.size.width / 3), height: .greatestFiniteMagnitude))
messageLabel.frame = CGRect(x: 0, y: 0, width: size.width + 32, height: size.height + 16)
messageLabel.center = CGPoint(x: bounds.size.width / 2, y: bounds.size.height / 2.0)
}
func isJoinMessage() -> Bool {
if let words = messageLabel.text?.components(separatedBy: " ") {
if words.count >= 2 && words[words.count - 2] == "has" && words[words.count - 1] == "joined" {
return true
}
}
return false
}
}
/// Copyright (c) 2019 Razeware LLC
///
/// 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.
///
/// Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
/// distribute, sublicense, create a derivative work, and/or sell copies of the
/// Software in any work that is designed, intended, or marketed for pedagogical or
/// instructional purposes related to programming, coding, application development,
/// or information technology. Permission for such use, copying, modification,
/// merger, publication, distribution, sublicensing, creation of derivative works,
/// or sale is expressly withheld.
///
/// 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.
import Foundation
struct Message {
let message: String
let senderUsername: String
let messageSender: MessageSender
init(message: String, messageSender: MessageSender, username: String) {
self.message = message.withoutWhitespace()
self.messageSender = messageSender
self.senderUsername = username
}
}
/// Copyright (c) 2019 Razeware LLC
///
/// 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.
///
/// Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
/// distribute, sublicense, create a derivative work, and/or sell copies of the
/// Software in any work that is designed, intended, or marketed for pedagogical or
/// instructional purposes related to programming, coding, application development,
/// or information technology. Permission for such use, copying, modification,
/// merger, publication, distribution, sublicensing, creation of derivative works,
/// or sale is expressly withheld.
///
/// 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.
import UIKit
protocol MessageInputDelegate {
func sendWasTapped(message: String)
}
class MessageInputView: UIView {
var delegate: MessageInputDelegate?
let textView = UITextView()
let sendButton = UIButton()
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = UIColor(red: 247 / 255, green: 247 / 255, blue: 247 / 255, alpha: 1.0)
textView.layer.cornerRadius = 4
textView.layer.borderColor = UIColor(red: 200 / 255, green: 200 / 255, blue: 200 / 255, alpha: 0.6).cgColor
textView.layer.borderWidth = 1
//sendButton.backgroundColor = UIColor(red: 8 / 255, green: 183 / 255, blue: 231 / 255, alpha: 1.0)
sendButton.backgroundColor = UIColor(red: 247 / 255, green: 247 / 255, blue: 247 / 255, alpha: 1.0)
sendButton.layer.cornerRadius = 4
sendButton.setTitle("Send", for: .normal)
sendButton.setTitleColor(.black, for: .normal)
sendButton.isEnabled = true
sendButton.addTarget(self, action: #selector(MessageInputView.sendTapped), for: .touchUpInside)
addSubview(textView)
addSubview(sendButton)
}
@objc func sendTapped() {
if let delegate = delegate, let message = textView.text {
delegate.sendWasTapped(message: message)
textView.text = ""
}
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
let size = bounds.size
textView.bounds = CGRect(x: 0, y: 0, width: size.width - 32 - 8 - 60, height: 40)
sendButton.bounds = CGRect(x: 0, y: 0, width: 60, height: 44)
textView.center = CGPoint(x: textView.bounds.size.width/2.0 + 16, y: bounds.size.height / 2.0)
sendButton.center = CGPoint(x: bounds.size.width - 30 - 16, y: bounds.size.height / 2.0)
}
}
extension MessageInputView: UITextViewDelegate {
func textViewShouldEndEditing(_ textView: UITextView) -> Bool {
return true
}
func textViewShouldBeginEditing(_ textView: UITextView) -> Bool {
return true
}
}
/// Copyright (c) 2019 Razeware LLC
///
/// 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.
///
/// Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
/// distribute, sublicense, create a derivative work, and/or sell copies of the
/// Software in any work that is designed, intended, or marketed for pedagogical or
/// instructional purposes related to programming, coding, application development,
/// or information technology. Permission for such use, copying, modification,
/// merger, publication, distribution, sublicensing, creation of derivative works,
/// or sale is expressly withheld.
///
/// 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.
import UIKit
enum MessageSender {
case ourself
case someoneElse
}
class MessageTableViewCell: UITableViewCell {
var messageSender: MessageSender = .ourself
let messageLabel = Label()
let nameLabel = UILabel()
func apply(message: Message) {
nameLabel.text = message.senderUsername
messageLabel.text = message.message
messageSender = message.messageSender
setNeedsLayout()
}
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
messageLabel.clipsToBounds = true
messageLabel.textColor = .white
messageLabel.numberOfLines = 0
nameLabel.textColor = .lightGray
nameLabel.font = UIFont(name: "Helvetica", size: 10)
clipsToBounds = true
addSubview(messageLabel)
addSubview(nameLabel)
}
class func height(for message: Message) -> CGFloat {
let maxSize = CGSize(width: 2*(UIScreen.main.bounds.size.width/3), height: CGFloat.greatestFiniteMagnitude)
let nameHeight = message.messageSender == .ourself ? 0 : (height(forText: message.senderUsername, fontSize: 10, maxSize: maxSize) + 4 )
let messageHeight = height(forText: message.message, fontSize: 17, maxSize: maxSize)
return nameHeight + messageHeight + 32 + 16
}
private class func height(forText text: String, fontSize: CGFloat, maxSize: CGSize) -> CGFloat {
let font = UIFont(name: "Helvetica", size: fontSize)!
let attrString = NSAttributedString(string: text, attributes:[NSAttributedString.Key.font: font,
NSAttributedString.Key.foregroundColor: UIColor.white])
let textHeight = attrString.boundingRect(with: maxSize, options: .usesLineFragmentOrigin, context: nil).size.height
return textHeight
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
/// Copyright (c) 2019 Razeware LLC
///
/// 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.
///
/// Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
/// distribute, sublicense, create a derivative work, and/or sell copies of the
/// Software in any work that is designed, intended, or marketed for pedagogical or
/// instructional purposes related to programming, coding, application development,
/// or information technology. Permission for such use, copying, modification,
/// merger, publication, distribution, sublicensing, creation of derivative works,
/// or sale is expressly withheld.
///
/// 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.
import Foundation
extension String {
func withoutWhitespace() -> String {
return self.replacingOccurrences(of: "\n", with: "")
.replacingOccurrences(of: "\r", with: "")
.replacingOccurrences(of: "\0", with: "")
}
}
/
import UIKit
protocol ChatRoomDelegate: class {
func received(message: Message)
}
class ChatRoom: NSObject {
//1
var inputStream: InputStream!
var outputStream: OutputStream!
weak var delegate: ChatRoomDelegate?
//2
var username = ""
//3
let maxReadLength = 4096
func setupNetworkCommunication() {
// 1
var readStream: Unmanaged<CFReadStream>?
var writeStream: Unmanaged<CFWriteStream>?
// 2
CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault,
"localhost" as CFString,
80,
&readStream,
&writeStream)
inputStream = readStream!.takeRetainedValue()
outputStream = writeStream!.takeRetainedValue()
inputStream.delegate = self
inputStream.schedule(in: .current, forMode: .common)
outputStream.schedule(in: .current, forMode: .common)
inputStream.open()
outputStream.open()
}
func joinChat(username: String) {
//1
let data = "iam:\(username)".data(using: .utf8)!
//2
self.username = username
//3
data.withUnsafeBytes {
guard let pointer = $0.baseAddress?.assumingMemoryBound(to: UInt8.self) else {
print("Error joining chat")
return
}
//4
outputStream.write(pointer, maxLength: data.count)
}
}
func send(message: String) {
let data = "msg:\(message)".data(using: .utf8)!
data.withUnsafeBytes {
guard let pointer = $0.baseAddress?.assumingMemoryBound(to: UInt8.self) else {
print("Error joining chat")
return
}
outputStream.write(pointer, maxLength: data.count)
}
}
func stopChatSession() {
inputStream.close()
outputStream.close()
}
}
extension ChatRoom: StreamDelegate {
func stream(_ aStream: Stream, handle eventCode: Stream.Event) {
switch eventCode {
case .hasBytesAvailable:
print("new message received")
readAvailableBytes(stream: aStream as! InputStream)
case .endEncountered:
print("new message received")
stopChatSession()
case .errorOccurred:
print("error occurred")
case .hasSpaceAvailable:
print("has space available")
default:
print("some other event...")
}
}
private func readAvailableBytes(stream: InputStream) {
let buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: maxReadLength)
while stream.hasBytesAvailable {
let numberOfBytesRead = inputStream.read(buffer, maxLength: maxReadLength)
if numberOfBytesRead < 0, let error = stream.streamError {
print(error)
break
}
// Construct the message object
if let message = processedMessageString(buffer: buffer, length: numberOfBytesRead) {
// Notify interested parties
delegate?.received(message: message)
}
}
}
private func processedMessageString(buffer: UnsafeMutablePointer<UInt8>,
length: Int) -> Message? {
//1
guard
let stringArray = String(
bytesNoCopy: buffer,
length: length,
encoding: .utf8,
freeWhenDone: true)?.components(separatedBy: ":"),
let name = stringArray.first,
let message = stringArray.last
else {
return nil
}
//2
let messageSender: MessageSender = (name == self.username) ? .ourself : .someoneElse
//3
return Message(message: message, messageSender: messageSender, username: name)
}
}
/// Copyright (c) 2019 Razeware LLC
///
/// 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.
///
/// Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
/// distribute, sublicense, create a derivative work, and/or sell copies of the
/// Software in any work that is designed, intended, or marketed for pedagogical or
/// instructional purposes related to programming, coding, application development,
/// or information technology. Permission for such use, copying, modification,
/// merger, publication, distribution, sublicensing, creation of derivative works,
/// or sale is expressly withheld.
///
/// 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.
import UIKit
extension ChatRoomViewController: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = MessageTableViewCell(style: .default, reuseIdentifier: "MessageCell")
cell.selectionStyle = .none
let message = messages[indexPath.row]
cell.apply(message: message)
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return messages.count
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
let height = MessageTableViewCell.height(for: messages[indexPath.row])
return height
}
func insertNewMessageCell(_ message: Message) {
messages.append(message)
let indexPath = IndexPath(row: messages.count - 1, section: 0)
tableView.beginUpdates()
tableView.insertRows(at: [indexPath], with: .bottom)
tableView.endUpdates()
tableView.scrollToRow(at: indexPath, at: .bottom, animated: true)
}
}
/// Copyright (c) 2019 Razeware LLC
///
/// 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.
///
/// Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
/// distribute, sublicense, create a derivative work, and/or sell copies of the
/// Software in any work that is designed, intended, or marketed for pedagogical or
/// instructional purposes related to programming, coding, application development,
/// or information technology. Permission for such use, copying, modification,
/// merger, publication, distribution, sublicensing, creation of derivative works,
/// or sale is expressly withheld.
///
/// 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.
import UIKit
class ChatRoomViewController: UIViewController {
let tableView = UITableView()
let messageInputBar = MessageInputView()
let chatRoom = ChatRoom()
var messages: [Message] = []
var username = ""
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
chatRoom.delegate = self
chatRoom.setupNetworkCommunication()
chatRoom.joinChat(username: username)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
chatRoom.stopChatSession()
}
}
//MARK - Message Input Bar
extension ChatRoomViewController: MessageInputDelegate {
func sendWasTapped(message: String) {
chatRoom.send(message: message)
}
}
extension ChatRoomViewController: ChatRoomDelegate {
func received(message: Message) {
insertNewMessageCell(message)
}
}
......@@ -52,6 +52,7 @@ class SettingsLauncher : UIViewController, UITableViewDelegate, UITableViewDataS
tableView.delegate = self
tableView.dataSource = self
tableView.delegate = self
tableView.separatorStyle = .none
imagePickerController.delegate = self
imagePickerController.allowsEditing = true
tableView.register(UITableViewCell.self, forCellReuseIdentifier: cellId)
......
/// Copyright (c) 2019 Razeware LLC
///
/// 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.
///
/// Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
/// distribute, sublicense, create a derivative work, and/or sell copies of the
/// Software in any work that is designed, intended, or marketed for pedagogical or
/// instructional purposes related to programming, coding, application development,
/// or information technology. Permission for such use, copying, modification,
/// merger, publication, distribution, sublicensing, creation of derivative works,
/// or sale is expressly withheld.
///
/// 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.
import UIKit
class JoinChatViewController: UIViewController {
let logoImageView = UIImageView()
let shadowView = UIView()
let nameTextField = TextField()
}
extension JoinChatViewController: UITextFieldDelegate {
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
let chatRoomVC = ChatRoomViewController()
if let username = nameTextField.text {
chatRoomVC.username = username
}
navigationController?.pushViewController(chatRoomVC, animated: true)
return true
}
}
class TextField: UITextField {
let padding = UIEdgeInsets(top: 0, left: 16, bottom: 0, right: 8)
override func textRect(forBounds bounds: CGRect) -> CGRect {
return bounds.inset(by: padding)
}
override func placeholderRect(forBounds bounds: CGRect) -> CGRect {
return bounds.inset(by: padding)
}
override func editingRect(forBounds bounds: CGRect) -> CGRect {
return bounds.inset(by: padding)
}
}
/// Copyright (c) 2019 Razeware LLC
///
/// 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.
///
/// Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
/// distribute, sublicense, create a derivative work, and/or sell copies of the
/// Software in any work that is designed, intended, or marketed for pedagogical or
/// instructional purposes related to programming, coding, application development,
/// or information technology. Permission for such use, copying, modification,
/// merger, publication, distribution, sublicensing, creation of derivative works,
/// or sale is expressly withheld.
///
/// 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.
import UIKit
class Label: UILabel {
override func drawText(in rect: CGRect) {
let insets = UIEdgeInsets.init(top: 8, left: 16, bottom: 8, right: 16)
super.drawText(in: rect.inset(by: insets))
}
}
/// Copyright (c) 2019 Razeware LLC
///
/// 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.
///
/// Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
/// distribute, sublicense, create a derivative work, and/or sell copies of the
/// Software in any work that is designed, intended, or marketed for pedagogical or
/// instructional purposes related to programming, coding, application development,
/// or information technology. Permission for such use, copying, modification,
/// merger, publication, distribution, sublicensing, creation of derivative works,
/// or sale is expressly withheld.
///
/// 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.
import UIKit
extension ChatRoomViewController {
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillChange(notification:)), name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
loadViews()
}
@objc func keyboardWillChange(notification: NSNotification) {
if let userInfo = notification.userInfo {
let endFrame = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)!.cgRectValue
let messageBarHeight = messageInputBar.bounds.size.height
let point = CGPoint(x: messageInputBar.center.x, y: endFrame.origin.y - messageBarHeight/2.0)
let inset = UIEdgeInsets(top: 0, left: 0, bottom: endFrame.size.height, right: 0)
UIView.animate(withDuration: 0.25) {
self.messageInputBar.center = point
self.tableView.contentInset = inset
}
}
}
func loadViews() {
navigationItem.title = "Let's Chat!"
navigationItem.backBarButtonItem?.title = "Run!"
view.backgroundColor = UIColor(red: 24 / 255, green: 180 / 255, blue: 128 / 255, alpha: 1.0)
tableView.dataSource = self
tableView.delegate = self
tableView.separatorStyle = .none
view.addSubview(tableView)
view.addSubview(messageInputBar)
messageInputBar.delegate = self
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
let messageBarHeight:CGFloat = 60.0
let size = view.bounds.size
tableView.frame = CGRect(x: 0, y: 0, width: size.width, height: size.height - messageBarHeight - view.safeAreaInsets.bottom)
messageInputBar.frame = CGRect(x: 0, y: size.height - messageBarHeight - view.safeAreaInsets.bottom, width: size.width, height: messageBarHeight)
}
}
extension JoinChatViewController {
override func viewDidLoad() {
super.viewDidLoad()
loadViews()
view.addSubview(shadowView)
view.addSubview(logoImageView)
view.addSubview(nameTextField)
}
func loadViews() {
view.backgroundColor = UIColor(red: 24/255, green: 180/255, blue: 128/255, alpha: 1.0)
navigationItem.title = "Doge Chat!"
logoImageView.image = UIImage(named: "doge")
logoImageView.layer.cornerRadius = 4
logoImageView.clipsToBounds = true
shadowView.layer.shadowColor = UIColor.black.cgColor
shadowView.layer.shadowRadius = 5
shadowView.layer.shadowOffset = CGSize(width: 0.0, height: 5.0)
shadowView.layer.shadowOpacity = 0.5
shadowView.backgroundColor = UIColor(red: 24 / 255, green: 180 / 255, blue: 128 / 255, alpha: 1.0)
nameTextField.placeholder = "What's your username?"
nameTextField.backgroundColor = .white
nameTextField.layer.cornerRadius = 4
nameTextField.delegate = self
let backItem = UIBarButtonItem()
backItem.title = "Run!"
navigationItem.backBarButtonItem = backItem
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
logoImageView.bounds = CGRect(x: 0, y: 0, width: 150, height: 150)
logoImageView.center = CGPoint(x: view.bounds.size.width / 2.0, y: logoImageView.bounds.size.height / 2.0 + view.bounds.size.height/4)
shadowView.frame = logoImageView.frame
nameTextField.bounds = CGRect(x: 0, y: 0, width: view.bounds.size.width - 40, height: 44)
nameTextField.center = CGPoint(x: view.bounds.size.width / 2.0, y: logoImageView.center.y + logoImageView.bounds.size.height / 2.0 + 20 + 22)
}
}
extension MessageTableViewCell {
override func layoutSubviews() {
super.layoutSubviews()
if isJoinMessage() {
layoutForJoinMessage()
} else {
messageLabel.font = UIFont(name: "Helvetica", size: 17)
messageLabel.textColor = .white
let size = messageLabel.sizeThatFits(CGSize(width: 2 * (bounds.size.width / 3), height: .greatestFiniteMagnitude))
messageLabel.frame = CGRect(x: 0, y: 0, width: size.width + 32, height: size.height + 16)
if messageSender == .ourself {
nameLabel.isHidden = true
messageLabel.center = CGPoint(x: bounds.size.width - messageLabel.bounds.size.width/2.0 - 16, y: bounds.size.height/2.0)
messageLabel.backgroundColor = UIColor(red: 24 / 255, green: 180 / 255, blue: 128 / 255, alpha: 1.0)
} else {
nameLabel.isHidden = false
nameLabel.sizeToFit()
nameLabel.center = CGPoint(x: nameLabel.bounds.size.width / 2.0 + 16 + 4, y: nameLabel.bounds.size.height/2.0 + 4)
messageLabel.center = CGPoint(x: messageLabel.bounds.size.width / 2.0 + 16, y: messageLabel.bounds.size.height/2.0 + nameLabel.bounds.size.height + 8)
messageLabel.backgroundColor = .lightGray
}
}
messageLabel.layer.cornerRadius = min(messageLabel.bounds.size.height / 2.0, 20)
}
func layoutForJoinMessage() {
messageLabel.font = UIFont.systemFont(ofSize: 10)
messageLabel.textColor = .lightGray
messageLabel.backgroundColor = UIColor(red: 247 / 255, green: 247 / 255, blue: 247 / 255, alpha: 1.0)
let size = messageLabel.sizeThatFits(CGSize(width: 2 * (bounds.size.width / 3), height: .greatestFiniteMagnitude))
messageLabel.frame = CGRect(x: 0, y: 0, width: size.width + 32, height: size.height + 16)
messageLabel.center = CGPoint(x: bounds.size.width / 2, y: bounds.size.height / 2.0)
}
func isJoinMessage() -> Bool {
if let words = messageLabel.text?.components(separatedBy: " ") {
if words.count >= 2 && words[words.count - 2] == "has" && words[words.count - 1] == "joined" {
return true
}
}
return false
}
}
/// Copyright (c) 2019 Razeware LLC
///
/// 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.
///
/// Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
/// distribute, sublicense, create a derivative work, and/or sell copies of the
/// Software in any work that is designed, intended, or marketed for pedagogical or
/// instructional purposes related to programming, coding, application development,
/// or information technology. Permission for such use, copying, modification,
/// merger, publication, distribution, sublicensing, creation of derivative works,
/// or sale is expressly withheld.
///
/// 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.
import Foundation
struct Message {
let message: String
let senderUsername: String
let messageSender: MessageSender
init(message: String, messageSender: MessageSender, username: String) {
self.message = message.withoutWhitespace()
self.messageSender = messageSender
self.senderUsername = username
}
}
/// Copyright (c) 2019 Razeware LLC
///
/// 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.
///
/// Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
/// distribute, sublicense, create a derivative work, and/or sell copies of the
/// Software in any work that is designed, intended, or marketed for pedagogical or
/// instructional purposes related to programming, coding, application development,
/// or information technology. Permission for such use, copying, modification,
/// merger, publication, distribution, sublicensing, creation of derivative works,
/// or sale is expressly withheld.
///
/// 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.
import UIKit
protocol MessageInputDelegate {
func sendWasTapped(message: String)
}
class MessageInputView: UIView {
var delegate: MessageInputDelegate?
let textView = UITextView()
let sendButton = UIButton()
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = UIColor(red: 247 / 255, green: 247 / 255, blue: 247 / 255, alpha: 1.0)
textView.layer.cornerRadius = 4
textView.layer.borderColor = UIColor(red: 200 / 255, green: 200 / 255, blue: 200 / 255, alpha: 0.6).cgColor
textView.layer.borderWidth = 1
sendButton.backgroundColor = UIColor(red: 8 / 255, green: 183 / 255, blue: 231 / 255, alpha: 1.0)
sendButton.layer.cornerRadius = 4
sendButton.setTitle("Send", for: .normal)
sendButton.isEnabled = true
sendButton.addTarget(self, action: #selector(MessageInputView.sendTapped), for: .touchUpInside)
addSubview(textView)
addSubview(sendButton)
}
@objc func sendTapped() {
if let delegate = delegate, let message = textView.text {
delegate.sendWasTapped(message: message)
textView.text = ""
}
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
let size = bounds.size
textView.bounds = CGRect(x: 0, y: 0, width: size.width - 32 - 8 - 60, height: 40)
sendButton.bounds = CGRect(x: 0, y: 0, width: 60, height: 44)
textView.center = CGPoint(x: textView.bounds.size.width/2.0 + 16, y: bounds.size.height / 2.0)
sendButton.center = CGPoint(x: bounds.size.width - 30 - 16, y: bounds.size.height / 2.0)
}
}
extension MessageInputView: UITextViewDelegate {
func textViewShouldEndEditing(_ textView: UITextView) -> Bool {
return true
}
}
/// Copyright (c) 2019 Razeware LLC
///
/// 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.
///
/// Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
/// distribute, sublicense, create a derivative work, and/or sell copies of the
/// Software in any work that is designed, intended, or marketed for pedagogical or
/// instructional purposes related to programming, coding, application development,
/// or information technology. Permission for such use, copying, modification,
/// merger, publication, distribution, sublicensing, creation of derivative works,
/// or sale is expressly withheld.
///
/// 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.
import UIKit
enum MessageSender {
case ourself
case someoneElse
}
class MessageTableViewCell: UITableViewCell {
var messageSender: MessageSender = .ourself
let messageLabel = Label()
let nameLabel = UILabel()
func apply(message: Message) {
nameLabel.text = message.senderUsername
messageLabel.text = message.message
messageSender = message.messageSender
setNeedsLayout()
}
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
messageLabel.clipsToBounds = true
messageLabel.textColor = .white
messageLabel.numberOfLines = 0
nameLabel.textColor = .lightGray
nameLabel.font = UIFont(name: "Helvetica", size: 10)
clipsToBounds = true
addSubview(messageLabel)
addSubview(nameLabel)
}
class func height(for message: Message) -> CGFloat {
let maxSize = CGSize(width: 2*(UIScreen.main.bounds.size.width/3), height: CGFloat.greatestFiniteMagnitude)
let nameHeight = message.messageSender == .ourself ? 0 : (height(forText: message.senderUsername, fontSize: 10, maxSize: maxSize) + 4 )
let messageHeight = height(forText: message.message, fontSize: 17, maxSize: maxSize)
return nameHeight + messageHeight + 32 + 16
}
private class func height(forText text: String, fontSize: CGFloat, maxSize: CGSize) -> CGFloat {
let font = UIFont(name: "Helvetica", size: fontSize)!
let attrString = NSAttributedString(string: text, attributes:[NSAttributedString.Key.font: font,
NSAttributedString.Key.foregroundColor: UIColor.white])
let textHeight = attrString.boundingRect(with: maxSize, options: .usesLineFragmentOrigin, context: nil).size.height
return textHeight
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
......@@ -97,7 +97,7 @@
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
</textField>
<textField opaque="NO" contentMode="scaleToFill" ambiguous="YES" contentHorizontalAlignment="left" contentVerticalAlignment="center" text="Undefined address" borderStyle="roundedRect" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="VWO-IA-oF7">
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" text="Undefined address" borderStyle="roundedRect" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="VWO-IA-oF7">
<rect key="frame" x="21" y="60" width="372" height="34"/>
<color key="backgroundColor" systemColor="systemGroupedBackgroundColor"/>
<color key="textColor" white="0.66666666669999997" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
......@@ -113,6 +113,7 @@
<constraints>
<constraint firstItem="nqP-jn-KuZ" firstAttribute="leading" secondItem="fnl-2z-Ty3" secondAttribute="leading" constant="20" id="3NQ-iu-OjB"/>
<constraint firstItem="Sc0-cO-Rk1" firstAttribute="top" secondItem="VWO-IA-oF7" secondAttribute="bottom" constant="17" id="LrC-f6-dlh"/>
<constraint firstItem="VWO-IA-oF7" firstAttribute="leading" secondItem="fnl-2z-Ty3" secondAttribute="leading" constant="21" id="OSi-y4-HpV"/>
<constraint firstItem="nqP-jn-KuZ" firstAttribute="top" secondItem="Sc0-cO-Rk1" secondAttribute="bottom" constant="20" id="QEO-iQ-tg0"/>
<constraint firstItem="Sc0-cO-Rk1" firstAttribute="centerY" secondItem="31i-Py-j20" secondAttribute="centerY" id="TDb-ta-TUf"/>
<constraint firstItem="B9M-8S-4PD" firstAttribute="leading" secondItem="fnl-2z-Ty3" secondAttribute="leading" constant="21" id="TGQ-gf-5CR"/>
......@@ -120,11 +121,17 @@
<constraint firstItem="nqP-jn-KuZ" firstAttribute="top" secondItem="i5M-Pr-FkT" secondAttribute="top" constant="169" id="Vd6-l6-D0K"/>
<constraint firstItem="nqP-jn-KuZ" firstAttribute="top" secondItem="31i-Py-j20" secondAttribute="bottom" constant="22" id="b8j-fB-CM9"/>
<constraint firstItem="fnl-2z-Ty3" firstAttribute="trailing" secondItem="Sc0-cO-Rk1" secondAttribute="trailing" constant="23" id="cTk-wz-Zap"/>
<constraint firstItem="fnl-2z-Ty3" firstAttribute="trailing" secondItem="VWO-IA-oF7" secondAttribute="trailing" constant="21" id="jLD-sB-2TI"/>
<constraint firstItem="fnl-2z-Ty3" firstAttribute="trailing" secondItem="nqP-jn-KuZ" secondAttribute="trailing" constant="20" id="jyh-hc-rAZ"/>
<constraint firstItem="Sc0-cO-Rk1" firstAttribute="leading" secondItem="31i-Py-j20" secondAttribute="trailing" constant="8" symbolic="YES" id="lT3-Dz-ylw"/>
<constraint firstItem="fnl-2z-Ty3" firstAttribute="trailing" secondItem="B9M-8S-4PD" secondAttribute="trailing" constant="21" id="mUT-4H-oJU"/>
<constraint firstItem="B9M-8S-4PD" firstAttribute="top" secondItem="nqP-jn-KuZ" secondAttribute="bottom" constant="17" id="nOE-qq-NJe"/>
</constraints>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius">
<integer key="value" value="10"/>
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
<point key="canvasLocation" x="140.57971014492756" y="87.723214285714278"/>
</view>
</objects>
......
/// Copyright (c) 2019 Razeware LLC
///
/// 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.
///
/// Notwithstanding the foregoing, you may not use, copy, modify, merge, publish,
/// distribute, sublicense, create a derivative work, and/or sell copies of the
/// Software in any work that is designed, intended, or marketed for pedagogical or
/// instructional purposes related to programming, coding, application development,
/// or information technology. Permission for such use, copying, modification,
/// merger, publication, distribution, sublicensing, creation of derivative works,
/// or sale is expressly withheld.
///
/// 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.
import Foundation
extension String {
func withoutWhitespace() -> String {
return self.replacingOccurrences(of: "\n", with: "")
.replacingOccurrences(of: "\r", with: "")
.replacingOccurrences(of: "\0", with: "")
}
}
//
// CallProfiViewController.swift
// Em-call
//
// Created by Alex Sh on 27.03.2022.
//
import UIKit
class CallProfiViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destination.
// Pass the selected object to the new view controller.
}
*/
}
......@@ -8,21 +8,28 @@
import UIKit
class ChatViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let rightBarButtonItem = UIBarButtonItem(image: UIImage(named: "but_left"), style: .done, target: self, action: #selector(call_Method))
// Для Tab bar
self.tabBarController?.navigationItem.rightBarButtonItems = [rightBarButtonItem]
// Для NavigationController
self.navigationController?.navigationItem.rightBarButtonItems = [rightBarButtonItem]
// Обязательно! добавить @objc
}
/*
"wetywet wywy ywywy w tyhy jdjd kufkfyklfyilf urstesa gesg esh sehsh",
"ghyeyrh ery etjirtijeti etj retuje rukryu rujr etyuetyet etyjtj",
"erhehet yhey thyhheheh",
"jkyujtueje ewrh ewje jet etjetyerhwrh erherh ehrhh rhrwh ewrh wh w",
"rshtrh rh srh ss hsr rhethrtsh srtghr r ryesty rtyr errysrtewreyu eju",
"drh rrhys srhsr srhsrh srtyrs srtysrtysrty srty srtysry rs",
"nh;sorkh erkltja a,ewrtlwrt vs,fnwlrwel;rjlmv LDSFoawhrpgry pipypkrae"
*/
let tableView = UITableView()
let messageInputBar = MessageInputView()
let chatRoom = ChatRoom()
var messages: [Message] = []
var username = "Alex"
var flagStartChat = 0
//debug
let SERVER_NO = 1
@objc func call_Method () {
print("Click")
}
......@@ -32,15 +39,40 @@ class ChatViewController: UIViewController {
self.navigationController?.navigationBar.barTintColor = UIColor.white
self.navigationController?.navigationBar.topItem?.title = "CHAT"
self.navigationController?.navigationItem.title = "CHAT"
chatRoom.delegate = self
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destination.
// Pass the selected object to the new view controller.
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
if flagStartChat == 1 {
chatRoom.stopChatSession()
flagStartChat = 0
}
}
@IBAction func startChat(_ sender: Any) {
flagStartChat = 1
loadViews()
if SERVER_NO == 0 {
chatRoom.setupNetworkCommunication()
chatRoom.joinChat(username: username)
}
}
*/
}
//MARK - Message Input Bar
extension ChatViewController: MessageInputDelegate {
func sendWasTapped(message: String) {
chatRoom.send(message: message)
}
}
extension ChatViewController: ChatRoomDelegate {
func received(message: Message) {
insertNewMessageCell(message)
}
}
......@@ -7,23 +7,265 @@
import UIKit
class DoubleElectricVC: UIViewController {
class DoubleElectricVC: UIViewController, UITableViewDelegate, UITableViewDataSource, UITextViewDelegate {
@IBOutlet weak var glidingView: GlidingCollection!
@IBOutlet weak var descTextView: UITextView!
fileprivate var collectionView: UICollectionView!
var selRow:Int = 0
let cellReuseIdentifier = "cell"
var address = "Unknow address"
var dateAndTime = "2022/02/23"
var contact = "+1 123 112 11 22"
var card = "**** **** **** 1234"
// private var images = [UIImage(named: "plus")!]
// private var images = [UIImage()]
fileprivate var images: [UIImage?] = []
var settingsLauncher:SettingsLauncher = SettingsLauncher()
@IBOutlet weak var addPhotoConstraint: NSLayoutConstraint!
@IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
// Register the table view cell class and its reuse id
self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: cellReuseIdentifier)
tableView.rowHeight = 45
tableView.delegate = self
tableView.dataSource = self
descTextView.delegate = self
settingsLauncher.delegate = self
setup()
glidingView.isHidden = true
// addPhotoTopConstraint.constant = 78
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
collectionView.reloadData()
collectionView.collectionViewLayout.invalidateLayout()
}
@IBAction func press_AddPhoto(_ sender: Any) {
guard let navVC = self.navigationController
else { return }
settingsLauncher.showSettings(navigVC: navVC,dispatcher:0)
glidingView.isHidden = false
addPhotoConstraint.constant = 98
}
@IBAction func pressBookNow(_ sender: Any) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc:UIViewController
if #available(iOS 13.0, *) {
vc = storyboard.instantiateViewController(identifier: "BookingVK") as! VKBookingViewController
} else {
vc = storyboard.instantiateViewController(withIdentifier: "BookingVK")
}
navigationController?.push(viewController: vc)
}
func loadImages() {
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
descTextView.resignFirstResponder()
}
// MARK: - Table view data source
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
switch section {
case 0: return 1
case 1: return 1
case 2: return 1
case 3: return 1
default: return 1
}
}
func numberOfSections(in tableView: UITableView) -> Int {
return 4
}
func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
// Создаём константу, именна через неё мы будем обращаться к свойствам и изменять их
let header = view as! UITableViewHeaderFooterView
// Установить цвет текста в label
header.textLabel?.textColor = .darkGray
// Установить цвет фона для секции
header.tintColor = UIColor.white
// Установить шрифт и размер шрифта для label
header.textLabel?.font = UIFont(name: "Helvetica-Regular", size: 15)
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
switch section {
case 0: return ("Work location")
case 1: return ("Date and Time")
case 2: return ("Your contacts")
case 3: return ("Payment")
default: return ("Work location")
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier, for: indexPath)
//let track = trackList[indexPath.row]
let section = indexPath.section
switch section {
case 0: cell.textLabel?.text = address
case 1: cell.textLabel?.text = dateAndTime
case 2: cell.textLabel?.text = contact
case 3: cell.textLabel?.text = card
default: break
}
cell.accessoryType = UITableViewCell.AccessoryType.disclosureIndicator
return cell
}
// method to run when table view cell is tapped
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("You tapped cell number \(indexPath.row).")
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let nameXibName = ["Map","Calendar"]
let section = indexPath.section
var vc:UIViewController
switch section //if indexPath.row == 0
{
case 0: vc = storyboard.instantiateViewController(withIdentifier: nameXibName[0])
(vc as! MapViewController).delegate = self
navigationController?.pushViewController(vc , animated: true)
return
case 1: vc = storyboard.instantiateViewController(withIdentifier: nameXibName[1])
(vc as! CalendarViewController).delegate = self
navigationController?.pushViewController(vc, animated: true)
return
case 2: vc = storyboard.instantiateViewController(withIdentifier: nameXibName[1])
(vc as! CalendarViewController).delegate = self
navigationController?.pushViewController(vc, animated: true)
case 3: vc = storyboard.instantiateViewController(withIdentifier: nameXibName[1])
(vc as! CalendarViewController).delegate = self
navigationController?.pushViewController(vc, animated: true)
default: return
}
}
}
extension DoubleElectricVC {
func setup() {
setupGlidingCollectionView()
}
private func setupGlidingCollectionView() {
glidingView.dataSource = self
let nib = UINib(nibName: "CollectionCell", bundle: nil)
collectionView = glidingView.collectionView
collectionView.register(nib, forCellWithReuseIdentifier: "Cell")
collectionView.delegate = self
collectionView.dataSource = self
collectionView.backgroundColor = glidingView.backgroundColor
}
/*
// MARK: - Navigation
}
// MARK: - CollectionView 🎛
extension DoubleElectricVC: UICollectionViewDataSource, UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
// let section = glidingView.expandedItemIndex
return images.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as? CollectionCell else
{ return UICollectionViewCell() }
////let section = glidingView.expandedItemIndex
if images.count>0 {
let image = images[indexPath.row]
// let image = images[0]
cell.imageView.image = image
}
cell.contentView.clipsToBounds = true
let layer = cell.layer
let config = GlidingConfig.shared
layer.shadowOffset = config.cardShadowOffset
layer.shadowColor = config.cardShadowColor.cgColor
layer.shadowOpacity = config.cardShadowOpacity
layer.shadowRadius = config.cardShadowRadius
layer.shouldRasterize = true
layer.rasterizationScale = UIScreen.main.scale
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let section = glidingView.expandedItemIndex
let item = indexPath.item
print("Selected item #\(item) in section #\(section)")
}
}
// MARK: - Gliding Collection 🎢
extension DoubleElectricVC: GlidingCollectionDatasource {
func numberOfItems(in collection: GlidingCollection) -> Int {
// return items.count
return 0
}
func glidingCollection(_ collection: GlidingCollection, itemAtIndex index: Int) -> String {
// return "– " + items[index]
return "– "
}
}
extension DoubleElectricVC:MapViewControllerDelegate {
func delegateClick(text:String) {
address = text
// NotificationCenter.default.post(name: NSNotification.Name(rawValue: "delegateClick"), object: nil)
tableView.reloadData()
}
}
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destination.
// Pass the selected object to the new view controller.
extension DoubleElectricVC:CalendarViewControllerDelegate {
func calendarDelegateClick(text:String,flagData:Int) {
switch flagData {
case 0:
dateAndTime = text
case 1:
contact = text
case 2:
card = text
default:
break
}
tableView.reloadData()
}
*/
}
extension DoubleElectricVC:SettingsLauncherDelegate {
func settingsDelegateClick(img: UIImage?,selRow:Int) {
if img != nil {
images.append(img!)
collectionView.reloadData()
}
else {
self.selRow = selRow
}
}
}
......@@ -54,8 +54,30 @@ class ElectricTableViewController:UIViewController,UITableViewDataSource, UITabl
super.viewWillAppear(animated)
collectionView.reloadData()
collectionView.collectionViewLayout.invalidateLayout()
navigationController?.navigationBar.titleTextAttributes = [.foregroundColor:UIColor(red: 0 / 255, green: 0 / 255, blue: 0 / 255, alpha: 1.0)]
title = "Electric"
let item1 = setBarButtom(str: "akar-icons_arrow-left")
self.navigationItem.setLeftBarButtonItems([item1], animated: true)
let item2 = setBarButtom(str: "gg_close")
self.navigationItem.setRightBarButtonItems([item2], animated: true)
}
func setBarButtom(str:String)->UIBarButtonItem {
let btn1 = UIButton(type: .custom)
btn1.setImage(UIImage(named: str), for: .normal)
btn1.frame = CGRect(x: 0, y: 0, width: 60, height: 60)
btn1.addTarget(self, action: #selector(self.back), for: .touchUpInside)
let item1 = UIBarButtonItem(customView: btn1)
return item1
}
@objc
func back() {
navigationController?.popViewController( animated: true)
}
@IBAction func BookNowClick(_ sender: Any) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc:UIViewController
......@@ -64,6 +86,16 @@ class ElectricTableViewController:UIViewController,UITableViewDataSource, UITabl
} else {
vc = storyboard.instantiateViewController(withIdentifier: "BookingVK")
}
let transition = CATransition()
transition.duration = 0.99
transition.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
transition.type = CATransitionType.fade //растворяется
// transition.type = CATransitionType.reveal //moving right
self.navigationController?.view.layer.add(transition, forKey: nil)
// _ = self.navigationController?.popToRootViewController(animated: false)
navigationController?.pushViewController(vc, animated: true)
}
......@@ -134,6 +166,7 @@ class ElectricTableViewController:UIViewController,UITableViewDataSource, UITabl
default: break
}
cell.accessoryType = UITableViewCell.AccessoryType.disclosureIndicator
cell.textLabel?.font = UIFont(name: "Roboto", size: 13)
return cell
}
......@@ -274,6 +307,32 @@ extension ElectricTableViewController: GlidingCollectionDatasource {
}
}
public extension UINavigationController {
/** Pop current view controller to previous view controller.
- parameter type: transition animation type.
- parameter duration: transition animation duration.
*/
func pop(transitionType type: CATransitionType = .fade, duration: CFTimeInterval = 0.3) {
// self.addTransition(transitionType: type, duration: duration)
let transition = CATransition()
transition.duration = 0.88
transition.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
transition.type = CATransitionType.fade
self.navigationController?.view.layer.add(transition, forKey: nil)
self.popViewController(animated: false)
}
/** Push a new view controller on the view controllers stack.
- parameter vc: view controller to push.
- parameter type: transition animation type.
- parameter duration: transition animation duration. */
func push(viewController vc: UIViewController, transitionType type: CATransitionType = .fade, duration: CFTimeInterval = 0.3) {
// self.addTransition(transitionType: type, duration: duration)
let transition = CATransition()
transition.duration = 0.88
transition.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
transition.type = CATransitionType.fade
self.navigationController?.view.layer.add(transition, forKey: nil)
self.pushViewController(vc, animated: false)
}
}
......@@ -14,10 +14,9 @@ class EmerElecricianViewController: UIViewController, UITableViewDataSource, UIT
var contact = "+1 123 112 11 22"
var card = "**** **** **** 1234"
@IBAction func butBackClick(_ sender: Any) {
_ = self.navigationController?.popViewController( animated: true)
}
@IBOutlet weak var tableView: UITableView!
@IBOutlet weak var addressView: UIView!
let trackList = Track.getTrackList()
let cellReuseIdentifier = "cell"
......@@ -26,12 +25,46 @@ class EmerElecricianViewController: UIViewController, UITableViewDataSource, UIT
super.viewDidLoad()
tableView.register(UITableViewCell.self, forCellReuseIdentifier: cellReuseIdentifier)
tableView.rowHeight = 65
tableView.rowHeight = 25
tableView.delegate = self
tableView.dataSource = self
addressView.layer.borderColor = UIColor.lightGray.cgColor
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
title = "Electrician emergency"
navigationController?.navigationBar.titleTextAttributes = [.foregroundColor:UIColor(red: 255 / 255, green: 94 / 255, blue: 58 / 255, alpha: 1.0)]
let item1 = setBarButtom(str: "akar-icons_arrow-left")
self.navigationItem.setLeftBarButtonItems([item1], animated: true)
let item2 = setBarButtom(str: "gg_close")
self.navigationItem.setRightBarButtonItems([item2], animated: true)
}
func setBarButtom(str:String)->UIBarButtonItem {
let btn1 = UIButton(type: .custom)
btn1.setImage(UIImage(named: str), for: .normal)
btn1.frame = CGRect(x: 0, y: 0, width: 60, height: 60)
btn1.addTarget(self, action: #selector(self.back), for: .touchUpInside)
let item1 = UIBarButtonItem(customView: btn1)
return item1
}
@objc
func back() {
navigationController?.popViewController( animated: true)
}
@IBAction func pressButtonAddress(_ sender: Any) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "Map")
(vc as! MapViewController).delegate = self
navigationController?.pushViewController(vc, animated: true)
}
@IBAction func BOOK__Click(_ sender: Any) {
@IBAction func pressBookNow(_ sender: Any) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc:UIViewController
if #available(iOS 13.0, *) {
......@@ -41,7 +74,8 @@ class EmerElecricianViewController: UIViewController, UITableViewDataSource, UIT
}
navigationController?.pushViewController(vc, animated: true)
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
//return trackList.count
return 1
......@@ -60,19 +94,19 @@ class EmerElecricianViewController: UIViewController, UITableViewDataSource, UIT
// Вызовите метод titleForHeaderInSection в TableViewController классе и добавьте в него текст
func numberOfSections(in tableView: UITableView) -> Int {
return 4
return 1
}// Default is 1 if not implemented
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
switch section {
case 0:
return ("Work location")
case 1: return ("Date and Time")
case 2: return ("Your contacts")
case 3: return ("Payment")
return ("Payment")
// case 1: return ("Date and Time")
// case 2: return ("Your contacts")
// case 3: return ("Payment")
default: return ("Work location")
} // return ("Work location")
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
......@@ -80,15 +114,15 @@ class EmerElecricianViewController: UIViewController, UITableViewDataSource, UIT
let section = indexPath.section
switch section {
case 0: cell.textLabel?.text = address
case 0: cell.textLabel?.text = card
//// cell.setSelected(true, animated: false)
// cell.textLabel?.textColor = UIColor.darkGray
// cell.textLabel?.font.pointSize = 10
// = UIFont(name: "Helvetica-Regular", size: 10)
//// cell.setSelected(false, animated: false)
case 1: cell.textLabel?.text = dateAndTime
case 2: cell.textLabel?.text = contact
case 3: cell.textLabel?.text = card
// case 1: cell.textLabel?.text = dateAndTime
// case 2: cell.textLabel?.text = contact
// case 3: cell.textLabel?.text = card
default: break
}
......@@ -107,42 +141,30 @@ class EmerElecricianViewController: UIViewController, UITableViewDataSource, UIT
switch section //if indexPath.row == 0
{
case 0:
/* if #available(iOS 13.0, *) {
case 0: /* if #available(iOS 13.0, *) {
vc = storyboard.instantiateViewController(identifier: nameXibName[indexPath.row]) as! MapViewController
} else {*/
vc = storyboard.instantiateViewController(withIdentifier: nameXibName[0])
(vc as! MapViewController).delegate = self
// let mapController:MapViewController! = MapViewController()
vc = storyboard.instantiateViewController(withIdentifier: nameXibName[1])
(vc as! CalendarViewController).delegate = self // let mapController:MapViewController! = MapViewController()
navigationController?.pushViewController(vc, animated: true)
case 1:
vc = storyboard.instantiateViewController(withIdentifier: nameXibName[1])
/* case 1: vc = storyboard.instantiateViewController(withIdentifier: nameXibName[1])
(vc as! CalendarViewController).delegate = self
navigationController?.pushViewController(vc, animated: true)
case 2:
vc = storyboard.instantiateViewController(withIdentifier: nameXibName[1])
case 2: vc = storyboard.instantiateViewController(withIdentifier: nameXibName[1])
(vc as! CalendarViewController).delegate = self
navigationController?.pushViewController(vc, animated: true)
case 3:
vc = storyboard.instantiateViewController(withIdentifier: nameXibName[1])
case 3: vc = storyboard.instantiateViewController(withIdentifier: nameXibName[1])
(vc as! CalendarViewController).delegate = self
navigationController?.pushViewController(vc, animated: true)
navigationController?.pushViewController(vc, animated: true)*/
default:
return
}
} /*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destination. // Pass the selected object to the new view controller.
}
*/
}
}
extension EmerElecricianViewController:MapViewControllerDelegate {
func delegateClick(text:String) {
address = text
// NotificationCenter.default.post(name: NSNotification.Name(rawValue: "delegateClick"), object: nil)
address = text // NotificationCenter.default.post(name: NSNotification.Name(rawValue: "delegateClick"), object: nil)
tableView.reloadData()
}
}
......
......@@ -10,8 +10,9 @@ import UIKit
class EmerHandViewController: UIViewController, UITableViewDataSource,
UITableViewDelegate
{
@IBOutlet weak var tableView: UITableView!
@IBOutlet weak var addressView: UIView!
let trackList = Track.getTrackList()
let cellReuseIdentifier = "cell"
var address = "Unknow address"
......@@ -22,58 +23,77 @@ class EmerHandViewController: UIViewController, UITableViewDataSource,
override func viewDidLoad() {
super.viewDidLoad()
title = "Emergency handyman"
navigationController?.navigationBar.titleTextAttributes = [.foregroundColor:UIColor(red: 255 / 255, green: 94 / 255, blue: 58 / 255, alpha: 1.0)]
addressView.layer.borderColor = UIColor.lightGray.cgColor
tableView.register(UITableViewCell.self, forCellReuseIdentifier: cellReuseIdentifier)
tableView.rowHeight = 45
tableView.delegate = self
tableView.dataSource = self
}
@IBAction func BOOK_Click(_ sender: Any) {
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
title = "Emergency handyman"
navigationController?.navigationBar.titleTextAttributes = [.foregroundColor:UIColor(red: 255 / 255, green: 94 / 255, blue: 58 / 255, alpha: 1.0)]
let item1 = setBarButtom(str: "akar-icons_arrow-left")
self.navigationItem.setLeftBarButtonItems([item1], animated: true)
let item2 = setBarButtom(str: "gg_close")
self.navigationItem.setRightBarButtonItems([item2], animated: true)
}
func setBarButtom(str:String)->UIBarButtonItem {
let btn1 = UIButton(type: .custom)
btn1.setImage(UIImage(named: str), for: .normal)
btn1.frame = CGRect(x: 0, y: 0, width: 60, height: 60)
btn1.addTarget(self, action: #selector(self.back), for: .touchUpInside)
let item1 = UIBarButtonItem(customView: btn1)
return item1
}
@objc
func back() {
//// self.dismiss(animated: true, completion: nil)
navigationController?.popViewController( animated: true)
}
@IBAction func pressBookNow(_ sender: Any) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc:UIViewController
if #available(iOS 13.0, *) {
vc = storyboard.instantiateViewController(identifier: "BookingVK") as! VKBookingViewController
} else {
vc = storyboard.instantiateViewController(withIdentifier: "BookingVK")
}
// navigationController?.isNavigationBarHidden = true
navigationController?.pushViewController(vc, animated: true)
} // navigationController?.isNavigationBarHidden = true
navigationController?.pushViewController(vc, animated: true)
}
//
@IBAction func butBackClick(_ sender: Any) {
_ = self.navigationController?.popViewController( animated: true)
/* let storyboard = UIStoryboard(name: "Main", bundle: nil)
weak var vc:UIViewController?
if #available(iOS 13.0, *) {
vc = storyboard.instantiateViewController(identifier: "ChildMainVC") as! VKBookingViewController
} else {
vc = storyboard.instantiateViewController(withIdentifier: "ChildMainVC")
// if vc != nil {
// }
navigationController?.pushViewController(vc!, animated: true)
}*/
@IBAction func pressButMap(_ sender: Any) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "Map")
(vc as! MapViewController).delegate = self
navigationController?.pushViewController(vc, animated: true)
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func numberOfSections(in tableView: UITableView) -> Int {
return 4
}// Default is 1 if not implemented
return 1
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
switch section {
case 0: return ("Work location")
case 1: return ("Date and Time")
case 2: return ("Your contacts")
case 3: return ("Payment")
default: return ("Work location")
} // return ("Work location")
case 0: return ("Payment")
/* case 1: return ("Date and Time") case 2: return ("Your contacts")
case 3: return ("Payment")*/
default: return ("Payment")
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
......@@ -81,10 +101,9 @@ class EmerHandViewController: UIViewController, UITableViewDataSource,
//let track = trackList[indexPath.row]
let section = indexPath.section
switch section {
case 0: cell.textLabel?.text = address
case 1: cell.textLabel?.text = dateAndTime
case 2: cell.textLabel?.text = contact
case 3: cell.textLabel?.text = card
case 0: cell.textLabel?.text = card
/* case 1: cell.textLabel?.text = dateAndTime case 2: cell.textLabel?.text = contact
case 3: cell.textLabel?.text = card*/
default: break
}
cell.accessoryType = UITableViewCell.AccessoryType.disclosureIndicator
......@@ -100,42 +119,36 @@ class EmerHandViewController: UIViewController, UITableViewDataSource,
switch section //if indexPath.row == 0
{
case 0:
vc = storyboard.instantiateViewController(withIdentifier: nameXibName[0])
(vc as! MapViewController).delegate = self
vc = storyboard.instantiateViewController(withIdentifier: nameXibName[1])
(vc as! CalendarViewController).delegate = self
navigationController?.pushViewController(vc , animated: true)
return
case 1:
vc = storyboard.instantiateViewController(withIdentifier: nameXibName[1])
/* case 1: vc = storyboard.instantiateViewController(withIdentifier: nameXibName[1])
(vc as! CalendarViewController).delegate = self
navigationController?.pushViewController(vc, animated: true)
return
case 2:
vc = storyboard.instantiateViewController(withIdentifier: nameXibName[1])
(vc as! CalendarViewController).delegate = self
navigationController?.pushViewController(vc, animated: true)
case 3:
vc = storyboard.instantiateViewController(withIdentifier: nameXibName[1])
(vc as! CalendarViewController).delegate = self
navigationController?.pushViewController(vc, animated: true)
return case 2: vc = storyboard.instantiateViewController(withIdentifier: nameXibName[1])
(vc as! CalendarViewController).delegate = self navigationController?.pushViewController(vc, animated: true)
case 3: vc = storyboard.instantiateViewController(withIdentifier: nameXibName[1])
(vc as! CalendarViewController).delegate = self navigationController?.pushViewController(vc, animated: true)*/
default: return
}
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destination.
// Pass the selected object to the new view controller.
func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
// Создаём константу, именна через неё мы будем обращаться к свойствам и изменять их
let header = view as! UITableViewHeaderFooterView
// Установить цвет текста в label
header.textLabel?.textColor = .darkGray
// Установить цвет фона для секции
header.tintColor = UIColor.white
// Установить шрифт и размер шрифта для label
header.textLabel?.font = UIFont(name: "Helvetica-Regular", size: 15)
}
*/
}
extension EmerHandViewController:MapViewControllerDelegate {
func delegateClick(text:String) {
address = text
// NotificationCenter.default.post(name: NSNotification.Name(rawValue: "delegateClick"), object: nil)
address = text // NotificationCenter.default.post(name: NSNotification.Name(rawValue: "delegateClick"), object: nil)
tableView.reloadData()
}
}
......
......@@ -76,6 +76,17 @@ class HandmanViewController: UIViewController, UITableViewDataSource,
descTextView.resignFirstResponder()
}
func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
// Создаём константу, именна через неё мы будем обращаться к свойствам и изменять их
let header = view as! UITableViewHeaderFooterView
// Установить цвет текста в label
header.textLabel?.textColor = .darkGray
// Установить цвет фона для секции
header.tintColor = UIColor.white
// Установить шрифт и размер шрифта для label
header.textLabel?.font = UIFont(name: "Helvetica-Regular", size: 15)
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
......
......@@ -54,6 +54,7 @@ class MainViewController: UIViewController, UITextFieldDelegate //, CLLocationM
} else {
self.view.alpha = 1.0
}
self.navigationController?.setNavigationBarHidden(true, animated: true)
}
@IBAction func longPress(_ sender: Any) {
......@@ -74,24 +75,7 @@ class MainViewController: UIViewController, UITextFieldDelegate //, CLLocationM
coordinateToAdress(locationTouch)
}
/*
private func setupSwipeable() {
self.swipeableView.isPanGestureInverted = true
self.swipeableView.flexibleLayout = .init(with: flexLayout, end: view.frame.height / 2)
self.swipeableView.childViewInteractionOnExpandedOnly = false
self.swipeableView.indicatorColors = (UIColor.Showcase8.colorB4,UIColor.Showcase8.colorB1)
}
private func setupChildview() {
if let characterPickerView = self.storyboard?.instantiateViewController(withIdentifier:"child_Id8") as? ShowcaseChildViewController_8 {
self.characterPickerView = characterPickerView
// plug the child view into the swipeable view
self.swipeableView.setChildView(childVC: characterPickerView, parentVC: self)
// plug the character picker delegate
characterPickerView.delegate = self
}
}
*/
override func viewDidLoad() {
super.viewDidLoad()
// setupBackButton()
......@@ -119,6 +103,9 @@ class MainViewController: UIViewController, UITextFieldDelegate //, CLLocationM
annotations.coordinate = CLLocationCoordinate2D(latitude: 51.509865, longitude: -0.118092)
mapView.addAnnotation(annotations)*/
// settingsLauncher.delegate = self
navigationController?.navigationBar.titleTextAttributes = [.foregroundColor:UIColor(red: 0 / 255, green: 0 / 255, blue: 0 / 255, alpha: 1.0)]
// let leftBarButtonItem = UIBarButtonItem(image: UIImage(contentsOfFile: "akar-icons_arrow-left"), style: .plain, target: self, action:Selector("pressEmerElectric"))
// self.navigationItem.leftBarButtonItem = leftBarButtonItem
}
override func viewDidAppear(_ animated:Bool) {
......@@ -129,7 +116,7 @@ class MainViewController: UIViewController, UITextFieldDelegate //, CLLocationM
buttonEmerElectric.isHidden = true
buttonEmerPlumber.isHidden = true
buttonEmerHandman.isHidden = true
// self.navigationController?.setNavigationBarHidden(true, animated: animated)
self.navigationController?.setNavigationBarHidden(true, animated: animated)
if bottomSheetVC != nil {
//sendSubviewToBack(_ view: UIView)
self.view.sendSubviewToBack(bottomSheetVC!.view)
......
......@@ -37,12 +37,14 @@ class MapViewController: UIViewController {
annotations.coordinate = CLLocationCoordinate2D(latitude:
51.509865, longitude: -0.118092)
mapView.addAnnotation(annotations)
navigationController?.navigationBar.titleTextAttributes = [.foregroundColor:UIColor(red: 0 / 255, green: 0 / 255, blue: 0 / 255, alpha: 1.0)]
}
override func viewDidAppear(_ animated:Bool) {
super.viewDidAppear(animated)
locationManager.checkLocationEnable()
navigationController?.navigationBar.titleTextAttributes = [.foregroundColor:UIColor(red: 0 / 255, green: 0 / 255, blue: 0 / 255, alpha: 1.0)]
}
......
......@@ -17,49 +17,82 @@ class PlumViewController: UIViewController, UITableViewDataSource,
var dateAndTime = "2022/02/23"
var contact = "+1 123 112 11 22"
var card = "**** **** **** 1234"
@IBOutlet weak var buttonBookNow: UIButton!
@IBOutlet weak var addressView: UIView!
@IBAction func pressButtonAddress(_ sender: Any) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "Map")
(vc as! MapViewController).delegate = self
navigationController?.pushViewController(vc, animated: true)
}
@IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
title = "Emergency plumbers"
navigationController?.navigationBar.titleTextAttributes = [.foregroundColor:UIColor(red: 255 / 255, green: 94 / 255, blue: 58 / 255, alpha: 1.0)]
addressView.layer.borderColor = UIColor.lightGray.cgColor
tableView.register(UITableViewCell.self, forCellReuseIdentifier: cellReuseIdentifier)
tableView.rowHeight = 45
tableView.delegate = self
tableView.dataSource = self
tableView.dataSource = self // buttonBookNow.becomeFirstResponder();
}
@IBAction func BOOK_Click(_ sender: Any) {
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
title = "Emergency plumbers"
navigationController?.navigationBar.titleTextAttributes = [.foregroundColor:UIColor(red: 255 / 255, green: 94 / 255, blue: 58 / 255, alpha: 1.0)]
let item1 = setBarButtom(str: "akar-icons_arrow-left")
self.navigationItem.setLeftBarButtonItems([item1], animated: true)
let item2 = setBarButtom(str: "gg_close")
self.navigationItem.setRightBarButtonItems([item2], animated: true)
}
func setBarButtom(str:String)->UIBarButtonItem {
let btn1 = UIButton(type: .custom)
btn1.setImage(UIImage(named: str), for: .normal)
btn1.frame = CGRect(x: 0, y: 0, width: 60, height: 60)
btn1.addTarget(self, action: #selector(self.back), for: .touchUpInside)
let item1 = UIBarButtonItem(customView: btn1)
return item1
}
@IBAction func pressBookNow(_ sender: Any) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc:UIViewController
if #available(iOS 13.0, *) {
vc = storyboard.instantiateViewController(identifier: "BookingVK") as! VKBookingViewController
} else {
vc = storyboard.instantiateViewController(withIdentifier: "BookingVK")
}
navigationController?.pushViewController(vc, animated: true)
}
// @IBAction func tapGesture(_ sender: Any) { view.endEditing(true) }
@objc
func back() { //// self.dismiss(animated: true, completion: nil)
navigationController?.popViewController( animated: true)
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// return trackList.count
return 1
}
func numberOfSections(in tableView: UITableView) -> Int {
return 4
}// Default is 1 if not implemented
return 1
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
switch section {
case 0: return ("Work location")
case 1: return ("Date and Time")
case 2: return ("Your contacts")
case 3: return ("Payment")
case 0: return ("Payment")
// case 1: return ("Date and Time") // case 2: return ("Your contacts") // case 3: return ("Payment")
default: return ("Work location")
} // return ("Work location")
}
......@@ -68,52 +101,52 @@ class PlumViewController: UIViewController, UITableViewDataSource,
let cell = tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier, for: indexPath)
let section = indexPath.section
switch section {
case 0: cell.textLabel?.text = address
case 1: cell.textLabel?.text = dateAndTime
case 2: cell.textLabel?.text = contact
case 3: cell.textLabel?.text = card
case 0: cell.textLabel?.text = card
// case 1: cell.textLabel?.text = dateAndTime // case 2: cell.textLabel?.text = contact // case 3: cell.textLabel?.text = card
default: break
}
cell.accessoryType = UITableViewCell.AccessoryType.disclosureIndicator
// }
return cell
return cell
}
// method to run when table view cell is tapped
// @available(iOS 13.0, *)
// method to run when table view cell is tapped // @available(iOS 13.0, *)
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("You tapped cell number \(indexPath.row).")
// print("You tapped cell number \(indexPath.row).")
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let nameXibName = ["Map","Calendar"]
// var indexPath = tableView.indexPathForSelectedRow!
let nameXibName = ["Map","Calendar"] // var indexPath = tableView.indexPathForSelectedRow!
let vc:UIViewController
switch indexPath.section //if indexPath.row == 0
{
case 0:
vc = storyboard.instantiateViewController(withIdentifier: nameXibName[0])
(vc as! MapViewController).delegate = self
// navigationController?.pushViewController(vc, animated: true)
case 1:
vc = storyboard.instantiateViewController(withIdentifier: nameXibName[1])
vc = storyboard.instantiateViewController(withIdentifier: nameXibName[1])
//(vc as! MapViewController).delegate = self
(vc as! CalendarViewController).delegate = self
// navigationController?.pushViewController(vc, animated: true)
case 2:
vc = storyboard.instantiateViewController(withIdentifier: nameXibName[1])
//// navigationController?.pushViewController(vc, animated: true)
/* case 1: vc = storyboard.instantiateViewController(withIdentifier: nameXibName[1])
(vc as! CalendarViewController).delegate = self
// navigationController?.pushViewController(vc, animated: true)
case 3:
vc = storyboard.instantiateViewController(withIdentifier: nameXibName[1])
case 2: vc = storyboard.instantiateViewController(withIdentifier: nameXibName[1])
(vc as! CalendarViewController).delegate = self
// navigationController?.pushViewController(vc, animated: true)
case 3: vc = storyboard.instantiateViewController(withIdentifier: nameXibName[1])
(vc as! CalendarViewController).delegate = self // navigationController?.pushViewController(vc, animated: true)
*/
default:
return
}
navigationController?.pushViewController(vc, animated: true)
}
func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
// Создаём константу, именна через неё мы будем обращаться к свойствам и изменять их
let header = view as! UITableViewHeaderFooterView
// Установить цвет текста в label
header.textLabel?.textColor = .darkGray
// Установить цвет фона для секции
header.tintColor = UIColor.white
// Установить шрифт и размер шрифта для label
header.textLabel?.font = UIFont(name: "Helvetica-Regular", size: 15)
}
}
......
......@@ -38,6 +38,24 @@ class VKBookingViewController: UIViewController,UITableViewDataSource, UITableVi
self.navigationController?.navigationItem.title = "BOOKING"
self.navigationController?.navigationBar.titleTextAttributes = [.foregroundColor : UIColor.black]
self.navigationController?.navigationBar.barTintColor = UIColor.white
let item1 = setBarButtom(str: "akar-icons_arrow-left")
self.navigationItem.setLeftBarButtonItems([item1], animated: true)
let item2 = setBarButtom(str: "gg_close")
self.navigationItem.setRightBarButtonItems([item2], animated: true)
}
func setBarButtom(str:String)->UIBarButtonItem {
let btn1 = UIButton(type: .custom)
btn1.setImage(UIImage(named: str), for: .normal)
btn1.frame = CGRect(x: 0, y: 0, width: 60, height: 60)
btn1.addTarget(self, action: #selector(self.back), for: .touchUpInside)
let item1 = UIBarButtonItem(customView: btn1)
return item1
}
@objc
func back() {
navigationController?.popViewController( animated: true)
}
@objc func segmentAction(_ segmentedControl: UISegmentedControl) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment