mirror of
https://github.com/dashared/GDproject.git
synced 2024-11-29 02:54:30 +03:00
commit
2d942f3ce6
8
Cartfile
8
Cartfile
@ -2,6 +2,8 @@ github "robb/Cartography"
|
||||
github "ivanbruel/MarkdownKit"
|
||||
github "roberthein/TinyConstraints"
|
||||
github "macteo/Marklight"
|
||||
github "ElaWorkshop/TagListView"
|
||||
github "Alamofire/Alamofire" "5.0.0-beta.2"
|
||||
github "whitesmith/WSTagsField"
|
||||
github "Alamofire/Alamofire" "5.0.0-beta.5"
|
||||
github "52inc/Pulley"
|
||||
github "HeroTransitions/Hero"
|
||||
github "ReactiveCocoa/ReactiveCocoa" ~> 9.0
|
||||
github "ZaidSA/TaggerKit" "bb826a7"
|
@ -8,21 +8,36 @@
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
1210A0BB223940310080686D /* SimplifiedChannelsList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1210A0BA223940310080686D /* SimplifiedChannelsList.swift */; };
|
||||
123AD0E3223C1C3900326173 /* WSTagsField.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 123AD0E2223C1C3900326173 /* WSTagsField.framework */; };
|
||||
123AD0E5223C1C4300326173 /* WSTagsField.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 123AD0E2223C1C3900326173 /* WSTagsField.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
121A8972226B1EAC005EE599 /* TagsSuggestionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 121A8971226B1EAC005EE599 /* TagsSuggestionController.swift */; };
|
||||
1220FF94227C41270092C6BC /* TaggsSelectionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1220FF93227C41270092C6BC /* TaggsSelectionViewController.swift */; };
|
||||
123589FD22899339002F8028 /* MessageViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 123589FC22899339002F8028 /* MessageViewCell.swift */; };
|
||||
123E37A5221F1B3200F6E42A /* LogInViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 123E37A4221F1B3200F6E42A /* LogInViewController.swift */; };
|
||||
123E37A7221F1DD700F6E42A /* MainController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 123E37A6221F1DD700F6E42A /* MainController.swift */; };
|
||||
124CC7032221C00C009DF531 /* Model.swift in Sources */ = {isa = PBXBuildFile; fileRef = 124CC7022221C00C009DF531 /* Model.swift */; };
|
||||
124CC7052221C2BB009DF531 /* Alamofire.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 124CC7042221C2BA009DF531 /* Alamofire.framework */; };
|
||||
124CC7072221C2C3009DF531 /* Alamofire.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 124CC7042221C2BA009DF531 /* Alamofire.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
1253867D2223DC9F00CC5EA7 /* RepeatingTimer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1253867C2223DC9F00CC5EA7 /* RepeatingTimer.swift */; };
|
||||
125A9A8A2285C3DA00513E2A /* CodeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 125A9A892285C3DA00513E2A /* CodeViewController.swift */; };
|
||||
125A9A8E2286068A00513E2A /* RegisterTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 125A9A8D2286068A00513E2A /* RegisterTableViewController.swift */; };
|
||||
125A9A90228609C500513E2A /* InititalsViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 125A9A8F228609C500513E2A /* InititalsViewCell.swift */; };
|
||||
125A9A922286100800513E2A /* FacultyTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 125A9A912286100800513E2A /* FacultyTableViewController.swift */; };
|
||||
125BD57D22171D2A008A3575 /* ProfileViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 125BD57C22171D2A008A3575 /* ProfileViewController.swift */; };
|
||||
125BD57F22171D73008A3575 /* Extentions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 125BD57E22171D73008A3575 /* Extentions.swift */; };
|
||||
125BD5812217314A008A3575 /* NewsVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 125BD5802217314A008A3575 /* NewsVC.swift */; };
|
||||
1261BB93227B364C003898CF /* ChannelViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1261BB92227B364C003898CF /* ChannelViewController.swift */; };
|
||||
1261BB95227B3991003898CF /* AddToChannelVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1261BB94227B3991003898CF /* AddToChannelVC.swift */; };
|
||||
1261BB9E227B793D003898CF /* ChatInfoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1261BB9D227B793D003898CF /* ChatInfoViewController.swift */; };
|
||||
12758257227F1401001F291F /* DialogViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12758256227F1401001F291F /* DialogViewController.swift */; };
|
||||
1288B5CE221F1158002BE6B1 /* DataStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1288B5CD221F1158002BE6B1 /* DataStorage.swift */; };
|
||||
1291BE2D2221312D009D3F23 /* ChannelsCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1291BE2C2221312C009D3F23 /* ChannelsCoordinator.swift */; };
|
||||
1291BE342221569B009D3F23 /* TabbarCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1291BE332221569B009D3F23 /* TabbarCoordinator.swift */; };
|
||||
1291BE3622218DBF009D3F23 /* LogInCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1291BE3522218DBF009D3F23 /* LogInCoordinator.swift */; };
|
||||
129320042279B4270035C7B3 /* MessagesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 129320032279B4270035C7B3 /* MessagesViewController.swift */; };
|
||||
129320072279B5690035C7B3 /* MessagesCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 129320062279B5690035C7B3 /* MessagesCoordinator.swift */; };
|
||||
129320092279C3B50035C7B3 /* PeopleToWriteViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 129320082279C3B50035C7B3 /* PeopleToWriteViewController.swift */; };
|
||||
1293200D2279D7310035C7B3 /* CompletionTree.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1293200C2279D7310035C7B3 /* CompletionTree.swift */; };
|
||||
1298810B227F13840032ACA3 /* DialogCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1298810A227F13840032ACA3 /* DialogCell.swift */; };
|
||||
12BA4B9B224101A400DF93D7 /* ApplicationCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12BA4B9A224101A400DF93D7 /* ApplicationCoordinator.swift */; };
|
||||
12BA4B9D224101E700DF93D7 /* BaseCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12BA4B9C224101E700DF93D7 /* BaseCoordinator.swift */; };
|
||||
12BA4B9F224102B700DF93D7 /* LogInCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12BA4B9E224102B700DF93D7 /* LogInCoordinator.swift */; };
|
||||
12CE7D6F227B94B10024B6E8 /* TaggerKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 12CE7D6E227B94B00024B6E8 /* TaggerKit.framework */; };
|
||||
12CE7D71227B94B50024B6E8 /* TaggerKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 12CE7D6E227B94B00024B6E8 /* TaggerKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
12D7D133221C321600B35452 /* ChannelListController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12D7D132221C321600B35452 /* ChannelListController.swift */; };
|
||||
12D7D135221C42B700B35452 /* ChannelController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12D7D134221C42B700B35452 /* ChannelController.swift */; };
|
||||
12D7D137221D78E800B35452 /* Channel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12D7D136221D78E800B35452 /* Channel.swift */; };
|
||||
@ -36,39 +51,54 @@
|
||||
12E36DA1221424EA006FCDD7 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 12E36D9F221424EA006FCDD7 /* Main.storyboard */; };
|
||||
12E36DA3221424ED006FCDD7 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 12E36DA2221424ED006FCDD7 /* Assets.xcassets */; };
|
||||
12E36DA6221424ED006FCDD7 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 12E36DA4221424ED006FCDD7 /* LaunchScreen.storyboard */; };
|
||||
12E36DAF22143D40006FCDD7 /* Cartography.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 12E36DAE22143D40006FCDD7 /* Cartography.framework */; };
|
||||
12E36DB322143D4E006FCDD7 /* Marklight.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 12E36DB222143D4E006FCDD7 /* Marklight.framework */; };
|
||||
12E36DB522143D54006FCDD7 /* TinyConstraints.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 12E36DB422143D54006FCDD7 /* TinyConstraints.framework */; };
|
||||
12E36DB72214400A006FCDD7 /* Post.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12E36DB62214400A006FCDD7 /* Post.swift */; };
|
||||
12E36DB922144016006FCDD7 /* User.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12E36DB822144016006FCDD7 /* User.swift */; };
|
||||
12E36DBD221441D5006FCDD7 /* TinyConstraints.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 12E36DB422143D54006FCDD7 /* TinyConstraints.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
12E36DC0221441DB006FCDD7 /* Marklight.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 12E36DB222143D4E006FCDD7 /* Marklight.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
12E36DC2221441E1006FCDD7 /* MarkdownKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 12E36DB022143D47006FCDD7 /* MarkdownKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
12E36DC4221441EA006FCDD7 /* Cartography.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 12E36DAE22143D40006FCDD7 /* Cartography.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
12E36DCA22144635006FCDD7 /* NewPostViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12E36DC922144635006FCDD7 /* NewPostViewController.swift */; };
|
||||
12E36DCC22144725006FCDD7 /* PostViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12E36DCB22144725006FCDD7 /* PostViewCell.swift */; };
|
||||
12E36DCE22144756006FCDD7 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12E36DCD22144756006FCDD7 /* Constants.swift */; };
|
||||
12E36DD122148122006FCDD7 /* FullPostController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12E36DD022148122006FCDD7 /* FullPostController.swift */; };
|
||||
12E36DD522156559006FCDD7 /* MyStackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12E36DD422156559006FCDD7 /* MyStackView.swift */; };
|
||||
12E36DD8221594A9006FCDD7 /* TagListView.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 12E36DD622159493006FCDD7 /* TagListView.framework */; };
|
||||
12E36DD9221594A9006FCDD7 /* TagListView.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 12E36DD622159493006FCDD7 /* TagListView.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
12E36DDB221594B1006FCDD7 /* MarkdownKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 12E36DB022143D47006FCDD7 /* MarkdownKit.framework */; };
|
||||
12F3D6B0224106F700A69214 /* TabbarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12F3D6AF224106F700A69214 /* TabbarController.swift */; };
|
||||
12F3D6B22241097B00A69214 /* ProfileCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12F3D6B12241097B00A69214 /* ProfileCoordinator.swift */; };
|
||||
12FDAC7C226B5E2900995B4E /* Marklight.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 12FDAC75226B5E2800995B4E /* Marklight.framework */; };
|
||||
12FDAC7D226B5E2900995B4E /* Result.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 12FDAC76226B5E2800995B4E /* Result.framework */; };
|
||||
12FDAC7E226B5E2900995B4E /* Cartography.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 12FDAC77226B5E2900995B4E /* Cartography.framework */; };
|
||||
12FDAC81226B5E2900995B4E /* MarkdownKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 12FDAC7A226B5E2900995B4E /* MarkdownKit.framework */; };
|
||||
12FDAC84226B5E3700995B4E /* Alamofire.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 12FDAC79226B5E2900995B4E /* Alamofire.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
12FDAC88226B5E4800995B4E /* Alamofire.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 12FDAC79226B5E2900995B4E /* Alamofire.framework */; };
|
||||
12FDAC8A226B5E4B00995B4E /* Cartography.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 12FDAC77226B5E2900995B4E /* Cartography.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
12FDAC8B226B5E4E00995B4E /* Hero.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 12FDAC78226B5E2900995B4E /* Hero.framework */; };
|
||||
12FDAC8C226B5E4E00995B4E /* Hero.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 12FDAC78226B5E2900995B4E /* Hero.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
12FDAC8E226B5E5000995B4E /* MarkdownKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 12FDAC7A226B5E2900995B4E /* MarkdownKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
12FDAC90226B5E5200995B4E /* Marklight.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 12FDAC75226B5E2800995B4E /* Marklight.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
12FDAC91226B5E5400995B4E /* Pulley.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 12FDAC7B226B5E2900995B4E /* Pulley.framework */; };
|
||||
12FDAC92226B5E5400995B4E /* Pulley.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 12FDAC7B226B5E2900995B4E /* Pulley.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
12FDAC94226B5E5600995B4E /* Result.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 12FDAC76226B5E2800995B4E /* Result.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
12FDAC96226B61C400995B4E /* TinyConstraints.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 12FDAC95226B61C400995B4E /* TinyConstraints.framework */; };
|
||||
12FDAC98226B61CB00995B4E /* TinyConstraints.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 12FDAC95226B61C400995B4E /* TinyConstraints.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
12FDAC9B226B652C00995B4E /* ReactiveSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 12FDAC99226B652400995B4E /* ReactiveSwift.framework */; };
|
||||
12FDAC9C226B652C00995B4E /* ReactiveSwift.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 12FDAC99226B652400995B4E /* ReactiveSwift.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
12FDAC9F226B9E7C00995B4E /* ReactiveCocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 12FDAC9D226B9E7600995B4E /* ReactiveCocoa.framework */; };
|
||||
12FDACA0226B9E7C00995B4E /* ReactiveCocoa.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 12FDAC9D226B9E7600995B4E /* ReactiveCocoa.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
12E36DBE221441D5006FCDD7 /* Embed Frameworks */ = {
|
||||
12FDAC85226B5E3700995B4E /* Embed Frameworks */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "";
|
||||
dstSubfolderSpec = 10;
|
||||
files = (
|
||||
12E36DC0221441DB006FCDD7 /* Marklight.framework in Embed Frameworks */,
|
||||
124CC7072221C2C3009DF531 /* Alamofire.framework in Embed Frameworks */,
|
||||
12E36DC4221441EA006FCDD7 /* Cartography.framework in Embed Frameworks */,
|
||||
12E36DD9221594A9006FCDD7 /* TagListView.framework in Embed Frameworks */,
|
||||
12E36DBD221441D5006FCDD7 /* TinyConstraints.framework in Embed Frameworks */,
|
||||
123AD0E5223C1C4300326173 /* WSTagsField.framework in Embed Frameworks */,
|
||||
12E36DC2221441E1006FCDD7 /* MarkdownKit.framework in Embed Frameworks */,
|
||||
12FDAC8E226B5E5000995B4E /* MarkdownKit.framework in Embed Frameworks */,
|
||||
12FDAC98226B61CB00995B4E /* TinyConstraints.framework in Embed Frameworks */,
|
||||
12FDAC94226B5E5600995B4E /* Result.framework in Embed Frameworks */,
|
||||
12FDAC84226B5E3700995B4E /* Alamofire.framework in Embed Frameworks */,
|
||||
12FDAC8A226B5E4B00995B4E /* Cartography.framework in Embed Frameworks */,
|
||||
12FDAC9C226B652C00995B4E /* ReactiveSwift.framework in Embed Frameworks */,
|
||||
12FDAC92226B5E5400995B4E /* Pulley.framework in Embed Frameworks */,
|
||||
12FDAC8C226B5E4E00995B4E /* Hero.framework in Embed Frameworks */,
|
||||
12FDAC90226B5E5200995B4E /* Marklight.framework in Embed Frameworks */,
|
||||
12CE7D71227B94B50024B6E8 /* TaggerKit.framework in Embed Frameworks */,
|
||||
12FDACA0226B9E7C00995B4E /* ReactiveCocoa.framework in Embed Frameworks */,
|
||||
);
|
||||
name = "Embed Frameworks";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
@ -77,19 +107,35 @@
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
1210A0BA223940310080686D /* SimplifiedChannelsList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimplifiedChannelsList.swift; sourceTree = "<group>"; };
|
||||
123AD0E2223C1C3900326173 /* WSTagsField.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WSTagsField.framework; path = Carthage/Build/iOS/WSTagsField.framework; sourceTree = "<group>"; };
|
||||
121A8971226B1EAC005EE599 /* TagsSuggestionController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TagsSuggestionController.swift; sourceTree = "<group>"; };
|
||||
1220FF93227C41270092C6BC /* TaggsSelectionViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaggsSelectionViewController.swift; sourceTree = "<group>"; };
|
||||
123589FC22899339002F8028 /* MessageViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageViewCell.swift; sourceTree = "<group>"; };
|
||||
123E37A4221F1B3200F6E42A /* LogInViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogInViewController.swift; sourceTree = "<group>"; };
|
||||
123E37A6221F1DD700F6E42A /* MainController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainController.swift; sourceTree = "<group>"; };
|
||||
124CC7022221C00C009DF531 /* Model.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Model.swift; sourceTree = "<group>"; };
|
||||
124CC7042221C2BA009DF531 /* Alamofire.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Alamofire.framework; path = Carthage/Build/iOS/Alamofire.framework; sourceTree = "<group>"; };
|
||||
1253867C2223DC9F00CC5EA7 /* RepeatingTimer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RepeatingTimer.swift; sourceTree = "<group>"; };
|
||||
125A9A892285C3DA00513E2A /* CodeViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CodeViewController.swift; sourceTree = "<group>"; };
|
||||
125A9A8D2286068A00513E2A /* RegisterTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RegisterTableViewController.swift; sourceTree = "<group>"; };
|
||||
125A9A8F228609C500513E2A /* InititalsViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InititalsViewCell.swift; sourceTree = "<group>"; };
|
||||
125A9A912286100800513E2A /* FacultyTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FacultyTableViewController.swift; sourceTree = "<group>"; };
|
||||
125BD57C22171D2A008A3575 /* ProfileViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileViewController.swift; sourceTree = "<group>"; };
|
||||
125BD57E22171D73008A3575 /* Extentions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Extentions.swift; sourceTree = "<group>"; };
|
||||
125BD5802217314A008A3575 /* NewsVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewsVC.swift; sourceTree = "<group>"; };
|
||||
1261BB92227B364C003898CF /* ChannelViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChannelViewController.swift; sourceTree = "<group>"; };
|
||||
1261BB94227B3991003898CF /* AddToChannelVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddToChannelVC.swift; sourceTree = "<group>"; };
|
||||
1261BB9D227B793D003898CF /* ChatInfoViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatInfoViewController.swift; sourceTree = "<group>"; };
|
||||
12758256227F1401001F291F /* DialogViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DialogViewController.swift; sourceTree = "<group>"; };
|
||||
1288B5CD221F1158002BE6B1 /* DataStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataStorage.swift; sourceTree = "<group>"; };
|
||||
1291BE2C2221312C009D3F23 /* ChannelsCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChannelsCoordinator.swift; sourceTree = "<group>"; };
|
||||
1291BE332221569B009D3F23 /* TabbarCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabbarCoordinator.swift; sourceTree = "<group>"; };
|
||||
1291BE3522218DBF009D3F23 /* LogInCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogInCoordinator.swift; sourceTree = "<group>"; };
|
||||
129320032279B4270035C7B3 /* MessagesViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessagesViewController.swift; sourceTree = "<group>"; };
|
||||
129320062279B5690035C7B3 /* MessagesCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessagesCoordinator.swift; sourceTree = "<group>"; };
|
||||
129320082279C3B50035C7B3 /* PeopleToWriteViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = PeopleToWriteViewController.swift; path = GDproject/Controller/Messages/PeopleToWriteViewController.swift; sourceTree = SOURCE_ROOT; };
|
||||
1293200C2279D7310035C7B3 /* CompletionTree.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompletionTree.swift; sourceTree = "<group>"; };
|
||||
1298810A227F13840032ACA3 /* DialogCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DialogCell.swift; sourceTree = "<group>"; };
|
||||
12BA4B9A224101A400DF93D7 /* ApplicationCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApplicationCoordinator.swift; sourceTree = "<group>"; };
|
||||
12BA4B9C224101E700DF93D7 /* BaseCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseCoordinator.swift; sourceTree = "<group>"; };
|
||||
12BA4B9E224102B700DF93D7 /* LogInCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogInCoordinator.swift; sourceTree = "<group>"; };
|
||||
12CE7D6E227B94B00024B6E8 /* TaggerKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = TaggerKit.framework; path = Carthage/Build/iOS/TaggerKit.framework; sourceTree = "<group>"; };
|
||||
12D7D132221C321600B35452 /* ChannelListController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChannelListController.swift; sourceTree = "<group>"; };
|
||||
12D7D134221C42B700B35452 /* ChannelController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChannelController.swift; sourceTree = "<group>"; };
|
||||
12D7D136221D78E800B35452 /* Channel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Channel.swift; sourceTree = "<group>"; };
|
||||
@ -105,18 +151,24 @@
|
||||
12E36DA2221424ED006FCDD7 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
12E36DA5221424ED006FCDD7 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
12E36DA7221424ED006FCDD7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
12E36DAE22143D40006FCDD7 /* Cartography.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cartography.framework; path = Carthage/Build/iOS/Cartography.framework; sourceTree = "<group>"; };
|
||||
12E36DB022143D47006FCDD7 /* MarkdownKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MarkdownKit.framework; path = Carthage/Build/iOS/MarkdownKit.framework; sourceTree = "<group>"; };
|
||||
12E36DB222143D4E006FCDD7 /* Marklight.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Marklight.framework; path = Carthage/Build/iOS/Marklight.framework; sourceTree = "<group>"; };
|
||||
12E36DB422143D54006FCDD7 /* TinyConstraints.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = TinyConstraints.framework; path = Carthage/Build/iOS/TinyConstraints.framework; sourceTree = "<group>"; };
|
||||
12E36DB62214400A006FCDD7 /* Post.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Post.swift; sourceTree = "<group>"; };
|
||||
12E36DB822144016006FCDD7 /* User.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = User.swift; sourceTree = "<group>"; };
|
||||
12E36DC922144635006FCDD7 /* NewPostViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewPostViewController.swift; sourceTree = "<group>"; };
|
||||
12E36DCB22144725006FCDD7 /* PostViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostViewCell.swift; sourceTree = "<group>"; };
|
||||
12E36DCD22144756006FCDD7 /* Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = "<group>"; };
|
||||
12E36DD022148122006FCDD7 /* FullPostController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FullPostController.swift; sourceTree = "<group>"; };
|
||||
12E36DD422156559006FCDD7 /* MyStackView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyStackView.swift; sourceTree = "<group>"; };
|
||||
12E36DD622159493006FCDD7 /* TagListView.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = TagListView.framework; path = Carthage/Build/iOS/TagListView.framework; sourceTree = "<group>"; };
|
||||
12F3D6AF224106F700A69214 /* TabbarController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabbarController.swift; sourceTree = "<group>"; };
|
||||
12F3D6B12241097B00A69214 /* ProfileCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileCoordinator.swift; sourceTree = "<group>"; };
|
||||
12FDAC75226B5E2800995B4E /* Marklight.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Marklight.framework; path = Carthage/Build/iOS/Marklight.framework; sourceTree = "<group>"; };
|
||||
12FDAC76226B5E2800995B4E /* Result.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Result.framework; path = Carthage/Build/iOS/Result.framework; sourceTree = "<group>"; };
|
||||
12FDAC77226B5E2900995B4E /* Cartography.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cartography.framework; path = Carthage/Build/iOS/Cartography.framework; sourceTree = "<group>"; };
|
||||
12FDAC78226B5E2900995B4E /* Hero.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Hero.framework; path = Carthage/Build/iOS/Hero.framework; sourceTree = "<group>"; };
|
||||
12FDAC79226B5E2900995B4E /* Alamofire.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Alamofire.framework; path = Carthage/Build/iOS/Alamofire.framework; sourceTree = "<group>"; };
|
||||
12FDAC7A226B5E2900995B4E /* MarkdownKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MarkdownKit.framework; path = Carthage/Build/iOS/MarkdownKit.framework; sourceTree = "<group>"; };
|
||||
12FDAC7B226B5E2900995B4E /* Pulley.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Pulley.framework; path = Carthage/Build/iOS/Pulley.framework; sourceTree = "<group>"; };
|
||||
12FDAC95226B61C400995B4E /* TinyConstraints.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = TinyConstraints.framework; path = Carthage/Build/iOS/TinyConstraints.framework; sourceTree = "<group>"; };
|
||||
12FDAC99226B652400995B4E /* ReactiveSwift.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ReactiveSwift.framework; path = Carthage/Build/iOS/ReactiveSwift.framework; sourceTree = "<group>"; };
|
||||
12FDAC9D226B9E7600995B4E /* ReactiveCocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ReactiveCocoa.framework; path = Carthage/Build/iOS/ReactiveCocoa.framework; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
@ -124,13 +176,17 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
12E36DB522143D54006FCDD7 /* TinyConstraints.framework in Frameworks */,
|
||||
124CC7052221C2BB009DF531 /* Alamofire.framework in Frameworks */,
|
||||
12E36DDB221594B1006FCDD7 /* MarkdownKit.framework in Frameworks */,
|
||||
12E36DD8221594A9006FCDD7 /* TagListView.framework in Frameworks */,
|
||||
12E36DAF22143D40006FCDD7 /* Cartography.framework in Frameworks */,
|
||||
123AD0E3223C1C3900326173 /* WSTagsField.framework in Frameworks */,
|
||||
12E36DB322143D4E006FCDD7 /* Marklight.framework in Frameworks */,
|
||||
12FDAC7C226B5E2900995B4E /* Marklight.framework in Frameworks */,
|
||||
12FDAC96226B61C400995B4E /* TinyConstraints.framework in Frameworks */,
|
||||
12FDAC91226B5E5400995B4E /* Pulley.framework in Frameworks */,
|
||||
12FDAC9F226B9E7C00995B4E /* ReactiveCocoa.framework in Frameworks */,
|
||||
12FDAC88226B5E4800995B4E /* Alamofire.framework in Frameworks */,
|
||||
12FDAC81226B5E2900995B4E /* MarkdownKit.framework in Frameworks */,
|
||||
12FDAC7D226B5E2900995B4E /* Result.framework in Frameworks */,
|
||||
12FDAC9B226B652C00995B4E /* ReactiveSwift.framework in Frameworks */,
|
||||
12FDAC7E226B5E2900995B4E /* Cartography.framework in Frameworks */,
|
||||
12CE7D6F227B94B10024B6E8 /* TaggerKit.framework in Frameworks */,
|
||||
12FDAC8B226B5E4E00995B4E /* Hero.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -150,33 +206,68 @@
|
||||
path = Profile;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
1291BE32222154C3009D3F23 /* Coordinator tab bar? */ = {
|
||||
1291BE32222154C3009D3F23 /* Coordinators */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
12BA4B9A224101A400DF93D7 /* ApplicationCoordinator.swift */,
|
||||
129320062279B5690035C7B3 /* MessagesCoordinator.swift */,
|
||||
12F3D6AF224106F700A69214 /* TabbarController.swift */,
|
||||
12F3D6B12241097B00A69214 /* ProfileCoordinator.swift */,
|
||||
12BA4B9E224102B700DF93D7 /* LogInCoordinator.swift */,
|
||||
12BA4B9C224101E700DF93D7 /* BaseCoordinator.swift */,
|
||||
1291BE2C2221312C009D3F23 /* ChannelsCoordinator.swift */,
|
||||
1291BE332221569B009D3F23 /* TabbarCoordinator.swift */,
|
||||
);
|
||||
path = "Coordinator tab bar?";
|
||||
path = Coordinators;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
1291BE3722218DC4009D3F23 /* Log In */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
125A9A912286100800513E2A /* FacultyTableViewController.swift */,
|
||||
125A9A8F228609C500513E2A /* InititalsViewCell.swift */,
|
||||
125A9A8D2286068A00513E2A /* RegisterTableViewController.swift */,
|
||||
125A9A892285C3DA00513E2A /* CodeViewController.swift */,
|
||||
123E37A4221F1B3200F6E42A /* LogInViewController.swift */,
|
||||
1291BE3522218DBF009D3F23 /* LogInCoordinator.swift */,
|
||||
);
|
||||
path = "Log In";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
129320052279B4300035C7B3 /* Messages */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
1261BB9D227B793D003898CF /* ChatInfoViewController.swift */,
|
||||
129320082279C3B50035C7B3 /* PeopleToWriteViewController.swift */,
|
||||
1298810C227F138C0032ACA3 /* Dialog */,
|
||||
129320032279B4270035C7B3 /* MessagesViewController.swift */,
|
||||
123589FC22899339002F8028 /* MessageViewCell.swift */,
|
||||
);
|
||||
path = Messages;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
1298810C227F138C0032ACA3 /* Dialog */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
12758256227F1401001F291F /* DialogViewController.swift */,
|
||||
1298810A227F13840032ACA3 /* DialogCell.swift */,
|
||||
);
|
||||
path = Dialog;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
12E36D8F221424EA006FCDD7 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
123AD0E2223C1C3900326173 /* WSTagsField.framework */,
|
||||
124CC7042221C2BA009DF531 /* Alamofire.framework */,
|
||||
12E36DD622159493006FCDD7 /* TagListView.framework */,
|
||||
12E36DB422143D54006FCDD7 /* TinyConstraints.framework */,
|
||||
12E36DB222143D4E006FCDD7 /* Marklight.framework */,
|
||||
12E36DB022143D47006FCDD7 /* MarkdownKit.framework */,
|
||||
12E36DAE22143D40006FCDD7 /* Cartography.framework */,
|
||||
12CE7D6E227B94B00024B6E8 /* TaggerKit.framework */,
|
||||
12FDAC9D226B9E7600995B4E /* ReactiveCocoa.framework */,
|
||||
12FDAC99226B652400995B4E /* ReactiveSwift.framework */,
|
||||
12FDAC95226B61C400995B4E /* TinyConstraints.framework */,
|
||||
12FDAC79226B5E2900995B4E /* Alamofire.framework */,
|
||||
12FDAC77226B5E2900995B4E /* Cartography.framework */,
|
||||
12FDAC78226B5E2900995B4E /* Hero.framework */,
|
||||
12FDAC7A226B5E2900995B4E /* MarkdownKit.framework */,
|
||||
12FDAC75226B5E2800995B4E /* Marklight.framework */,
|
||||
12FDAC7B226B5E2900995B4E /* Pulley.framework */,
|
||||
12FDAC76226B5E2800995B4E /* Result.framework */,
|
||||
12E36D9A221424EA006FCDD7 /* GDproject */,
|
||||
12E36D99221424EA006FCDD7 /* Products */,
|
||||
12E36DDA221594B1006FCDD7 /* Frameworks */,
|
||||
@ -212,9 +303,9 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
124CC7022221C00C009DF531 /* Model.swift */,
|
||||
1293200C2279D7310035C7B3 /* CompletionTree.swift */,
|
||||
12E36DB62214400A006FCDD7 /* Post.swift */,
|
||||
12D7D136221D78E800B35452 /* Channel.swift */,
|
||||
12E36DB822144016006FCDD7 /* User.swift */,
|
||||
);
|
||||
path = "Simple model";
|
||||
sourceTree = "<group>";
|
||||
@ -232,8 +323,8 @@
|
||||
12E36DCF22145923006FCDD7 /* Controller */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
1253867C2223DC9F00CC5EA7 /* RepeatingTimer.swift */,
|
||||
1291BE32222154C3009D3F23 /* Coordinator tab bar? */,
|
||||
1291BE32222154C3009D3F23 /* Coordinators */,
|
||||
129320052279B4300035C7B3 /* Messages */,
|
||||
1291BE3722218DC4009D3F23 /* Log In */,
|
||||
1288B5CC221F0EFE002BE6B1 /* Profile */,
|
||||
12E36DD322156519006FCDD7 /* News and channels */,
|
||||
@ -244,13 +335,16 @@
|
||||
12E36DD322156519006FCDD7 /* News and channels */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
1261BB92227B364C003898CF /* ChannelViewController.swift */,
|
||||
1220FF93227C41270092C6BC /* TaggsSelectionViewController.swift */,
|
||||
1261BB94227B3991003898CF /* AddToChannelVC.swift */,
|
||||
12D7D134221C42B700B35452 /* ChannelController.swift */,
|
||||
121A8971226B1EAC005EE599 /* TagsSuggestionController.swift */,
|
||||
12D7D132221C321600B35452 /* ChannelListController.swift */,
|
||||
1210A0BA223940310080686D /* SimplifiedChannelsList.swift */,
|
||||
12E36DC922144635006FCDD7 /* NewPostViewController.swift */,
|
||||
12E36DD022148122006FCDD7 /* FullPostController.swift */,
|
||||
12E36D9D221424EA006FCDD7 /* NewsController.swift */,
|
||||
1291BE2C2221312C009D3F23 /* ChannelsCoordinator.swift */,
|
||||
125BD5802217314A008A3575 /* NewsVC.swift */,
|
||||
12E36DCB22144725006FCDD7 /* PostViewCell.swift */,
|
||||
);
|
||||
@ -274,7 +368,7 @@
|
||||
12E36D94221424EA006FCDD7 /* Sources */,
|
||||
12E36D95221424EA006FCDD7 /* Frameworks */,
|
||||
12E36D96221424EA006FCDD7 /* Resources */,
|
||||
12E36DBE221441D5006FCDD7 /* Embed Frameworks */,
|
||||
12FDAC85226B5E3700995B4E /* Embed Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
@ -297,6 +391,11 @@
|
||||
TargetAttributes = {
|
||||
12E36D97221424EA006FCDD7 = {
|
||||
CreatedOnToolsVersion = 10.1;
|
||||
SystemCapabilities = {
|
||||
com.apple.Keychain = {
|
||||
enabled = 0;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
@ -336,31 +435,49 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
129320072279B5690035C7B3 /* MessagesCoordinator.swift in Sources */,
|
||||
124CC7032221C00C009DF531 /* Model.swift in Sources */,
|
||||
125A9A90228609C500513E2A /* InititalsViewCell.swift in Sources */,
|
||||
1220FF94227C41270092C6BC /* TaggsSelectionViewController.swift in Sources */,
|
||||
12F3D6B0224106F700A69214 /* TabbarController.swift in Sources */,
|
||||
12E36DD522156559006FCDD7 /* MyStackView.swift in Sources */,
|
||||
12D7D137221D78E800B35452 /* Channel.swift in Sources */,
|
||||
1291BE3622218DBF009D3F23 /* LogInCoordinator.swift in Sources */,
|
||||
12E36DB922144016006FCDD7 /* User.swift in Sources */,
|
||||
1210A0BB223940310080686D /* SimplifiedChannelsList.swift in Sources */,
|
||||
125BD5812217314A008A3575 /* NewsVC.swift in Sources */,
|
||||
12E36DB72214400A006FCDD7 /* Post.swift in Sources */,
|
||||
12DB7FDF221877160096878E /* InviteViewController.swift in Sources */,
|
||||
121A8972226B1EAC005EE599 /* TagsSuggestionController.swift in Sources */,
|
||||
1293200D2279D7310035C7B3 /* CompletionTree.swift in Sources */,
|
||||
12E36DCA22144635006FCDD7 /* NewPostViewController.swift in Sources */,
|
||||
1261BB9E227B793D003898CF /* ChatInfoViewController.swift in Sources */,
|
||||
12E36D9E221424EA006FCDD7 /* NewsController.swift in Sources */,
|
||||
1298810B227F13840032ACA3 /* DialogCell.swift in Sources */,
|
||||
125A9A922286100800513E2A /* FacultyTableViewController.swift in Sources */,
|
||||
125A9A8E2286068A00513E2A /* RegisterTableViewController.swift in Sources */,
|
||||
123589FD22899339002F8028 /* MessageViewCell.swift in Sources */,
|
||||
12E36DCC22144725006FCDD7 /* PostViewCell.swift in Sources */,
|
||||
123E37A5221F1B3200F6E42A /* LogInViewController.swift in Sources */,
|
||||
125BD57F22171D73008A3575 /* Extentions.swift in Sources */,
|
||||
12D7D133221C321600B35452 /* ChannelListController.swift in Sources */,
|
||||
125A9A8A2285C3DA00513E2A /* CodeViewController.swift in Sources */,
|
||||
1291BE342221569B009D3F23 /* TabbarCoordinator.swift in Sources */,
|
||||
129320092279C3B50035C7B3 /* PeopleToWriteViewController.swift in Sources */,
|
||||
12BA4B9B224101A400DF93D7 /* ApplicationCoordinator.swift in Sources */,
|
||||
1291BE2D2221312D009D3F23 /* ChannelsCoordinator.swift in Sources */,
|
||||
12E36DD122148122006FCDD7 /* FullPostController.swift in Sources */,
|
||||
129320042279B4270035C7B3 /* MessagesViewController.swift in Sources */,
|
||||
12758257227F1401001F291F /* DialogViewController.swift in Sources */,
|
||||
1288B5CE221F1158002BE6B1 /* DataStorage.swift in Sources */,
|
||||
12BA4B9F224102B700DF93D7 /* LogInCoordinator.swift in Sources */,
|
||||
12F3D6B22241097B00A69214 /* ProfileCoordinator.swift in Sources */,
|
||||
125BD57D22171D2A008A3575 /* ProfileViewController.swift in Sources */,
|
||||
1253867D2223DC9F00CC5EA7 /* RepeatingTimer.swift in Sources */,
|
||||
1261BB95227B3991003898CF /* AddToChannelVC.swift in Sources */,
|
||||
12DB7FDB2218590C0096878E /* InfoCell.swift in Sources */,
|
||||
12DB7FD922181E660096878E /* BasicInfoCell.swift in Sources */,
|
||||
1261BB93227B364C003898CF /* ChannelViewController.swift in Sources */,
|
||||
12D7D135221C42B700B35452 /* ChannelController.swift in Sources */,
|
||||
12E36D9C221424EA006FCDD7 /* AppDelegate.swift in Sources */,
|
||||
12BA4B9D224101E700DF93D7 /* BaseCoordinator.swift in Sources */,
|
||||
12DB7FD722181CD20096878E /* BasicInfoController.swift in Sources */,
|
||||
12E36DCE22144756006FCDD7 /* Constants.swift in Sources */,
|
||||
12DB7FDD221872F80096878E /* SettingsViewController.swift in Sources */,
|
||||
@ -510,6 +627,7 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_TEAM = 9Z6LFGKA9G;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
@ -521,9 +639,10 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = rednikina.com.drHSE.GDproject;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = rednikina.com.drHSE.GDproject.sos;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 4.2;
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Debug;
|
||||
@ -532,6 +651,7 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_TEAM = 9Z6LFGKA9G;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
@ -543,9 +663,10 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = rednikina.com.drHSE.GDproject;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = rednikina.com.drHSE.GDproject.sos;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 4.2;
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Release;
|
||||
|
@ -1,16 +1,30 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="609-2j-gc9">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14490.49"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="Stack View standard spacing" minToolsVersion="9.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--Chats-->
|
||||
<scene sceneID="bZ2-fw-XBE">
|
||||
<objects>
|
||||
<navigationController id="gt4-mD-66Q" sceneMemberID="viewController">
|
||||
<tabBarItem key="tabBarItem" title="Chats" image="chat" id="ZPm-j1-3dy"/>
|
||||
<navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="XiY-wd-750">
|
||||
<rect key="frame" x="0.0" y="20" width="375" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</navigationBar>
|
||||
</navigationController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="4yT-77-90q" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="1089" y="481"/>
|
||||
</scene>
|
||||
<!--Profile View Controller-->
|
||||
<scene sceneID="rQ6-TM-V7T">
|
||||
<objects>
|
||||
@ -20,7 +34,7 @@
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="cay-ea-rTl">
|
||||
<rect key="frame" x="0.0" y="116" width="375" height="502"/>
|
||||
<rect key="frame" x="0.0" y="20" width="375" height="647"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<view key="tableHeaderView" contentMode="scaleToFill" id="kFZ-3c-OFY">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="199"/>
|
||||
@ -76,6 +90,9 @@
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="yir-N6-Q6f">
|
||||
<rect key="frame" x="246" y="0.0" width="97" height="30"/>
|
||||
<state key="normal" title="New message"/>
|
||||
<connections>
|
||||
<action selector="sendMessage:" destination="R4D-Ao-uvG" eventType="touchUpInside" id="tQc-5f-SU3"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
</stackView>
|
||||
@ -131,7 +148,7 @@
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="sap-zV-B7l" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="2013.5999999999999" y="957.57121439280365"/>
|
||||
<point key="canvasLocation" x="1884" y="1216"/>
|
||||
</scene>
|
||||
<!--Settings View Controller-->
|
||||
<scene sceneID="WVn-Qy-9tO">
|
||||
@ -168,7 +185,7 @@
|
||||
</tableViewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="xdg-ZK-4Jv" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="1986" y="1756"/>
|
||||
<point key="canvasLocation" x="1980" y="1979"/>
|
||||
</scene>
|
||||
<!--Invite View Controller-->
|
||||
<scene sceneID="DcO-6Y-Iko">
|
||||
@ -212,7 +229,251 @@
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="t8a-Sv-mbh" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="2803" y="1756"/>
|
||||
<point key="canvasLocation" x="2799" y="1979"/>
|
||||
</scene>
|
||||
<!--Code View Controller-->
|
||||
<scene sceneID="VW5-ny-vaB">
|
||||
<objects>
|
||||
<viewController storyboardIdentifier="CodeViewController" id="Lz1-1J-ywG" customClass="CodeViewController" customModule="GDproject" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="Rud-1x-pKL">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Enter the code you received via mail" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="hE6-cQ-NbO">
|
||||
<rect key="frame" x="50" y="47" width="275.5" height="20.5"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<stackView opaque="NO" contentMode="scaleToFill" spacing="12" translatesAutoresizingMaskIntoConstraints="NO" id="2Gj-pC-RZ2">
|
||||
<rect key="frame" x="37.5" y="99" width="300" height="58"/>
|
||||
<subviews>
|
||||
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="_" textAlignment="center" adjustsFontSizeToFit="NO" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="744-t1-YNn">
|
||||
<rect key="frame" x="0.0" y="0.0" width="40" height="58"/>
|
||||
<nil key="textColor"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="45"/>
|
||||
<textInputTraits key="textInputTraits" keyboardType="numberPad"/>
|
||||
</textField>
|
||||
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="_" textAlignment="center" adjustsFontSizeToFit="NO" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="jcR-jp-s7a">
|
||||
<rect key="frame" x="52" y="0.0" width="40" height="58"/>
|
||||
<nil key="textColor"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="45"/>
|
||||
<textInputTraits key="textInputTraits" keyboardType="numberPad"/>
|
||||
</textField>
|
||||
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="_" textAlignment="center" adjustsFontSizeToFit="NO" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="YKO-0M-KD8">
|
||||
<rect key="frame" x="104" y="0.0" width="40" height="58"/>
|
||||
<nil key="textColor"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="45"/>
|
||||
<textInputTraits key="textInputTraits" keyboardType="numberPad"/>
|
||||
</textField>
|
||||
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="_" textAlignment="center" adjustsFontSizeToFit="NO" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="SmG-Ae-oOs">
|
||||
<rect key="frame" x="156" y="0.0" width="40" height="58"/>
|
||||
<nil key="textColor"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="45"/>
|
||||
<textInputTraits key="textInputTraits" keyboardType="numberPad"/>
|
||||
</textField>
|
||||
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="_" textAlignment="center" adjustsFontSizeToFit="NO" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="vaP-rO-NZW">
|
||||
<rect key="frame" x="208" y="0.0" width="40" height="58"/>
|
||||
<nil key="textColor"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="45"/>
|
||||
<textInputTraits key="textInputTraits" keyboardType="numberPad"/>
|
||||
</textField>
|
||||
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="_" textAlignment="center" adjustsFontSizeToFit="NO" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="qDh-32-HSn">
|
||||
<rect key="frame" x="260" y="0.0" width="40" height="58"/>
|
||||
<nil key="textColor"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="45"/>
|
||||
<textInputTraits key="textInputTraits" keyboardType="numberPad"/>
|
||||
</textField>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="58" id="5tl-bI-7tm"/>
|
||||
<constraint firstItem="YKO-0M-KD8" firstAttribute="width" secondItem="744-t1-YNn" secondAttribute="width" id="E7r-rk-4Mb"/>
|
||||
<constraint firstItem="SmG-Ae-oOs" firstAttribute="width" secondItem="744-t1-YNn" secondAttribute="width" id="Hkd-L6-qkf"/>
|
||||
<constraint firstItem="qDh-32-HSn" firstAttribute="width" secondItem="744-t1-YNn" secondAttribute="width" id="Koj-e5-Dof"/>
|
||||
<constraint firstItem="vaP-rO-NZW" firstAttribute="width" secondItem="744-t1-YNn" secondAttribute="width" id="Vzl-ZY-3yI"/>
|
||||
<constraint firstItem="jcR-jp-s7a" firstAttribute="width" secondItem="744-t1-YNn" secondAttribute="width" id="bDe-cA-CGi"/>
|
||||
<constraint firstAttribute="width" constant="300" id="gWy-t0-k14"/>
|
||||
</constraints>
|
||||
</stackView>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="lCU-OF-giE">
|
||||
<rect key="frame" x="0.0" y="617" width="375" height="50"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="AMw-Yp-yMs">
|
||||
<rect key="frame" x="327" y="8" width="32" height="30"/>
|
||||
<state key="normal" title="Next"/>
|
||||
<connections>
|
||||
<action selector="whereToGoNext:" destination="Lz1-1J-ywG" eventType="touchUpInside" id="1OA-n8-Gky"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="bottom" secondItem="AMw-Yp-yMs" secondAttribute="bottom" constant="12" id="7qy-qR-6jm"/>
|
||||
<constraint firstItem="AMw-Yp-yMs" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="lCU-OF-giE" secondAttribute="leading" constant="20" symbolic="YES" id="Bqz-qr-CNW"/>
|
||||
<constraint firstAttribute="height" constant="50" id="Dyu-H3-S3f"/>
|
||||
<constraint firstAttribute="trailing" secondItem="AMw-Yp-yMs" secondAttribute="trailing" constant="16" id="N19-bz-XCw"/>
|
||||
<constraint firstItem="AMw-Yp-yMs" firstAttribute="top" secondItem="lCU-OF-giE" secondAttribute="top" constant="8" id="u6d-3F-1Y5"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstItem="hE6-cQ-NbO" firstAttribute="top" secondItem="xwd-51-foC" secondAttribute="top" constant="27" id="8Gx-SH-Pc0"/>
|
||||
<constraint firstItem="2Gj-pC-RZ2" firstAttribute="top" secondItem="hE6-cQ-NbO" secondAttribute="bottom" constant="31.5" id="DEY-u8-rFj"/>
|
||||
<constraint firstItem="lCU-OF-giE" firstAttribute="leading" secondItem="xwd-51-foC" secondAttribute="leading" id="HFt-0X-LMb"/>
|
||||
<constraint firstItem="lCU-OF-giE" firstAttribute="trailing" secondItem="xwd-51-foC" secondAttribute="trailing" id="Z71-jX-S5Q"/>
|
||||
<constraint firstItem="2Gj-pC-RZ2" firstAttribute="centerX" secondItem="xwd-51-foC" secondAttribute="centerX" id="aSr-QZ-LuB"/>
|
||||
<constraint firstItem="hE6-cQ-NbO" firstAttribute="centerX" secondItem="xwd-51-foC" secondAttribute="centerX" id="oFz-CS-SSk"/>
|
||||
<constraint firstItem="lCU-OF-giE" firstAttribute="bottom" secondItem="xwd-51-foC" secondAttribute="bottom" id="vMF-KP-eIa"/>
|
||||
</constraints>
|
||||
<viewLayoutGuide key="safeArea" id="xwd-51-foC"/>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="bottomConstraint" destination="vMF-KP-eIa" id="a15-El-XZs"/>
|
||||
<outlet property="f1" destination="744-t1-YNn" id="kaQ-nt-ubz"/>
|
||||
<outlet property="f2" destination="jcR-jp-s7a" id="tjD-L6-nis"/>
|
||||
<outlet property="f3" destination="YKO-0M-KD8" id="QHg-UM-Bta"/>
|
||||
<outlet property="f4" destination="SmG-Ae-oOs" id="bwy-JB-My7"/>
|
||||
<outlet property="f5" destination="vaP-rO-NZW" id="rNh-iH-648"/>
|
||||
<outlet property="f6" destination="qDh-32-HSn" id="h4g-QY-abI"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="y6E-3d-hPA" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="4381.6000000000004" y="1961.4692653673164"/>
|
||||
</scene>
|
||||
<!--Register Table View Controller-->
|
||||
<scene sceneID="h6T-rh-iCS">
|
||||
<objects>
|
||||
<tableViewController storyboardIdentifier="RegisterTableViewController" id="gZg-8R-SiJ" customClass="RegisterTableViewController" customModule="GDproject" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="grouped" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="18" sectionFooterHeight="18" id="yDm-gG-Zw0">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
|
||||
<prototypes>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="cell111" textLabel="bby-bf-qyX" style="IBUITableViewCellStyleDefault" id="Ybe-Vg-GR0">
|
||||
<rect key="frame" x="0.0" y="55.5" width="375" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="Ybe-Vg-GR0" id="OZG-F0-QqJ">
|
||||
<rect key="frame" x="0.0" y="0.0" width="341" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Add faculty" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="bby-bf-qyX">
|
||||
<rect key="frame" x="16" y="0.0" width="324" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="facultyCell" textLabel="8Xf-Sx-eEe" detailTextLabel="Vjg-Il-F07" style="IBUITableViewCellStyleSubtitle" id="xJW-zY-MeC">
|
||||
<rect key="frame" x="0.0" y="99.5" width="375" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="xJW-zY-MeC" id="hnt-oe-CHh">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Add faculty" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="8Xf-Sx-eEe">
|
||||
<rect key="frame" x="16" y="5" width="87" height="20.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Subtitle" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Vjg-Il-F07">
|
||||
<rect key="frame" x="16" y="25.5" width="44" height="14.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="12"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="nameCell" id="VPG-zq-xMh" customClass="InititalsViewCell" customModule="GDproject" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="143.5" width="375" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="VPG-zq-xMh" id="jrO-rB-x0c">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="Name" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="hwQ-St-DAp">
|
||||
<rect key="frame" x="16" y="7" width="343" height="30"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="30" id="QXw-Sf-Hnk"/>
|
||||
</constraints>
|
||||
<nil key="textColor"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<textInputTraits key="textInputTraits"/>
|
||||
</textField>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="bottom" secondItem="hwQ-St-DAp" secondAttribute="bottom" constant="6.5" id="3Kb-PR-ZPu"/>
|
||||
<constraint firstItem="hwQ-St-DAp" firstAttribute="top" secondItem="jrO-rB-x0c" secondAttribute="top" constant="7" id="CyQ-kQ-mce"/>
|
||||
<constraint firstAttribute="trailing" secondItem="hwQ-St-DAp" secondAttribute="trailing" constant="16" id="HKq-mF-8h9"/>
|
||||
<constraint firstItem="hwQ-St-DAp" firstAttribute="leading" secondItem="jrO-rB-x0c" secondAttribute="leading" constant="16" id="NoW-FW-Q6L"/>
|
||||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
<connections>
|
||||
<outlet property="initialsTextField" destination="hwQ-St-DAp" id="VU3-m6-FnI"/>
|
||||
</connections>
|
||||
</tableViewCell>
|
||||
</prototypes>
|
||||
<connections>
|
||||
<outlet property="dataSource" destination="gZg-8R-SiJ" id="OVm-5H-nyP"/>
|
||||
<outlet property="delegate" destination="gZg-8R-SiJ" id="khe-nG-0w4"/>
|
||||
</connections>
|
||||
</tableView>
|
||||
</tableViewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="0cS-ao-ZWH" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="5925.6000000000004" y="2041.529235382309"/>
|
||||
</scene>
|
||||
<!--Faculty Table View Controller-->
|
||||
<scene sceneID="WcK-wN-L0e">
|
||||
<objects>
|
||||
<tableViewController storyboardIdentifier="FacultyTableViewController" id="wiz-jF-9HF" customClass="FacultyTableViewController" customModule="GDproject" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" id="Iny-a7-zjv">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<prototypes>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="F" textLabel="mSQ-7c-C8A" detailTextLabel="YuF-0p-znr" style="IBUITableViewCellStyleSubtitle" id="Otu-BR-9o9">
|
||||
<rect key="frame" x="0.0" y="28" width="375" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="Otu-BR-9o9" id="2Vm-f8-txH">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Title" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="mSQ-7c-C8A">
|
||||
<rect key="frame" x="16" y="5" width="33.5" height="20.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Subtitle" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="YuF-0p-znr">
|
||||
<rect key="frame" x="16" y="25.5" width="44" height="14.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="12"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
</prototypes>
|
||||
<connections>
|
||||
<outlet property="dataSource" destination="wiz-jF-9HF" id="db0-qR-UJy"/>
|
||||
<outlet property="delegate" destination="wiz-jF-9HF" id="i3e-Uc-EfR"/>
|
||||
</connections>
|
||||
</tableView>
|
||||
</tableViewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="Kkr-Cr-ZiV" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="6804" y="2044"/>
|
||||
</scene>
|
||||
<!--Simplified Channels List-->
|
||||
<scene sceneID="gAa-jy-vpG">
|
||||
@ -354,7 +615,7 @@
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="fzv-8a-15V" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="3560.8000000000002" y="-597.75112443778119"/>
|
||||
<point key="canvasLocation" x="3577" y="-598"/>
|
||||
</scene>
|
||||
<!--New Post View Controller-->
|
||||
<scene sceneID="TVK-xu-UdJ">
|
||||
@ -365,33 +626,35 @@
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="aRT-Du-PVE">
|
||||
<rect key="frame" x="0.0" y="55" width="375" height="612"/>
|
||||
<rect key="frame" x="0.0" y="62" width="375" height="605"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="368-bf-QU6">
|
||||
<rect key="frame" x="0.0" y="20" width="375" height="35"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="bHv-9b-9uA">
|
||||
<rect key="frame" x="16" y="32" width="343" height="30"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="35" id="5ER-su-0Yf"/>
|
||||
<constraint firstAttribute="height" constant="30" id="QPs-3f-AfA"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<state key="normal" title="Edit hashtags"/>
|
||||
<connections>
|
||||
<action selector="chooseTags:" destination="uED-wX-77j" eventType="touchUpInside" id="jvf-w2-K2f"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstItem="wxD-Ek-mgv" firstAttribute="trailing" secondItem="aRT-Du-PVE" secondAttribute="trailing" id="2ee-e8-G7A"/>
|
||||
<constraint firstItem="368-bf-QU6" firstAttribute="leading" secondItem="wxD-Ek-mgv" secondAttribute="leading" id="9Rl-wh-kZf"/>
|
||||
<constraint firstItem="aRT-Du-PVE" firstAttribute="top" secondItem="bHv-9b-9uA" secondAttribute="bottom" id="6As-MU-bEh"/>
|
||||
<constraint firstItem="bHv-9b-9uA" firstAttribute="leading" secondItem="wxD-Ek-mgv" secondAttribute="leading" constant="16" id="OIV-hF-TBs"/>
|
||||
<constraint firstItem="bHv-9b-9uA" firstAttribute="top" secondItem="wxD-Ek-mgv" secondAttribute="top" constant="12" id="REt-Jv-IfH"/>
|
||||
<constraint firstItem="aRT-Du-PVE" firstAttribute="leading" secondItem="wxD-Ek-mgv" secondAttribute="leading" id="UBy-Ch-zSL"/>
|
||||
<constraint firstItem="aRT-Du-PVE" firstAttribute="top" secondItem="368-bf-QU6" secondAttribute="bottom" id="WaE-kh-6w3"/>
|
||||
<constraint firstItem="368-bf-QU6" firstAttribute="top" secondItem="wxD-Ek-mgv" secondAttribute="top" id="aI9-JQ-7dq"/>
|
||||
<constraint firstItem="368-bf-QU6" firstAttribute="trailing" secondItem="wxD-Ek-mgv" secondAttribute="trailing" id="haz-0r-Cud"/>
|
||||
<constraint firstItem="wxD-Ek-mgv" firstAttribute="trailing" secondItem="bHv-9b-9uA" secondAttribute="trailing" constant="16" id="Ufp-mQ-Xeo"/>
|
||||
<constraint firstItem="wxD-Ek-mgv" firstAttribute="bottom" secondItem="aRT-Du-PVE" secondAttribute="bottom" id="x3f-eb-ACt"/>
|
||||
</constraints>
|
||||
<viewLayoutGuide key="safeArea" id="wxD-Ek-mgv"/>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="bottomTextViewConstraint" destination="x3f-eb-ACt" id="ktT-im-InH"/>
|
||||
<outlet property="view1" destination="aRT-Du-PVE" id="m3d-kW-vqW"/>
|
||||
<outlet property="viewForTags" destination="368-bf-QU6" id="M5s-RZ-Fq7"/>
|
||||
<outlet property="view1" destination="aRT-Du-PVE" id="DXD-HR-NcE"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="3fd-7N-vPg" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
@ -416,54 +679,352 @@
|
||||
</objects>
|
||||
<point key="canvasLocation" x="3444" y="129.98500749625188"/>
|
||||
</scene>
|
||||
<!--Log In View Controller-->
|
||||
<scene sceneID="Pkd-pB-bQs">
|
||||
<!--Taggs Selection View Controller-->
|
||||
<scene sceneID="74G-Lc-cqT">
|
||||
<objects>
|
||||
<viewController storyboardIdentifier="LogInController" id="ZCz-70-hDh" customClass="LogInViewController" customModule="GDproject" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="1q2-4g-KZs">
|
||||
<viewController storyboardIdentifier="TaggsSelectionViewController" id="rQl-ri-9O8" customClass="TaggsSelectionViewController" customModule="GDproject" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="k3T-8B-NVf">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="12" translatesAutoresizingMaskIntoConstraints="NO" id="UwC-m5-jA5">
|
||||
<rect key="frame" x="16" y="100" width="343" height="83"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Log In" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="efn-ze-jca">
|
||||
<rect key="frame" x="0.0" y="0.0" width="343" height="41"/>
|
||||
<fontDescription key="fontDescription" type="boldSystem" pointSize="34"/>
|
||||
<nil key="textColor"/>
|
||||
<containerView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="yeR-J3-ysT">
|
||||
<rect key="frame" x="16" y="131" width="343" height="142"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="142" id="1By-sC-rMT"/>
|
||||
</constraints>
|
||||
</containerView>
|
||||
<containerView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="lEu-rZ-H6U">
|
||||
<rect key="frame" x="16" y="306" width="343" height="184"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="184" id="F0W-3R-hCj"/>
|
||||
</constraints>
|
||||
</containerView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Add tags:" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="uXC-Rm-Hek">
|
||||
<rect key="frame" x="16" y="28" width="73" height="21"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="21" id="KZW-ld-K8d"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" red="0.43529411759999997" green="0.4431372549" blue="0.47450980390000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="Mail" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="mFP-WG-jY5">
|
||||
<rect key="frame" x="0.0" y="53" width="343" height="30"/>
|
||||
<color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Suggested tags:" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="hvS-Ix-A23">
|
||||
<rect key="frame" x="16" y="106" width="126" height="21"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="21" id="ZJb-Aw-bLx"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" red="0.43529411759999997" green="0.4431372549" blue="0.47450980390000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Chosen tags:" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="lxp-KC-Iua">
|
||||
<rect key="frame" x="16" y="281" width="101" height="21"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="21" id="aT7-BK-i42"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" red="0.43529411759999997" green="0.4431372549" blue="0.47450980390000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="BgX-NT-7NG" customClass="TKTextField" customModule="TaggerKit">
|
||||
<rect key="frame" x="16" y="57" width="343" height="30"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="30" id="dBr-rd-Cg8"/>
|
||||
</constraints>
|
||||
<nil key="textColor"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||
<textInputTraits key="textInputTraits"/>
|
||||
</textField>
|
||||
</subviews>
|
||||
</stackView>
|
||||
<activityIndicatorView opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" style="gray" translatesAutoresizingMaskIntoConstraints="NO" id="K3b-gv-JPp">
|
||||
<rect key="frame" x="177.5" y="333.5" width="20" height="20"/>
|
||||
</activityIndicatorView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstItem="UwC-m5-jA5" firstAttribute="leading" secondItem="LOR-Yw-0FU" secondAttribute="leading" constant="16" id="M6z-nU-H40"/>
|
||||
<constraint firstItem="K3b-gv-JPp" firstAttribute="centerY" secondItem="LOR-Yw-0FU" secondAttribute="centerY" id="eOp-yQ-n28"/>
|
||||
<constraint firstItem="K3b-gv-JPp" firstAttribute="centerX" secondItem="LOR-Yw-0FU" secondAttribute="centerX" id="gdW-VU-pE8"/>
|
||||
<constraint firstItem="LOR-Yw-0FU" firstAttribute="trailing" secondItem="UwC-m5-jA5" secondAttribute="trailing" constant="16" id="jST-rr-MMX"/>
|
||||
<constraint firstItem="UwC-m5-jA5" firstAttribute="top" secondItem="LOR-Yw-0FU" secondAttribute="top" constant="80" id="rvy-Ii-bwS"/>
|
||||
<constraint firstItem="hvS-Ix-A23" firstAttribute="top" secondItem="BgX-NT-7NG" secondAttribute="bottom" constant="19" id="17U-ae-Gxa"/>
|
||||
<constraint firstItem="Oc2-oW-bST" firstAttribute="trailing" secondItem="yeR-J3-ysT" secondAttribute="trailing" constant="16" id="9gG-QD-LG4"/>
|
||||
<constraint firstItem="lxp-KC-Iua" firstAttribute="top" secondItem="yeR-J3-ysT" secondAttribute="bottom" constant="8" id="C3R-dM-Fzj"/>
|
||||
<constraint firstItem="uXC-Rm-Hek" firstAttribute="leading" secondItem="Oc2-oW-bST" secondAttribute="leading" constant="16" id="E6w-kw-7Uo"/>
|
||||
<constraint firstItem="Oc2-oW-bST" firstAttribute="trailing" secondItem="hvS-Ix-A23" secondAttribute="trailing" constant="233" id="GLM-Fj-UeZ"/>
|
||||
<constraint firstItem="Oc2-oW-bST" firstAttribute="trailing" secondItem="lxp-KC-Iua" secondAttribute="trailing" constant="258" id="Pbc-Ul-Bqf"/>
|
||||
<constraint firstItem="Oc2-oW-bST" firstAttribute="trailing" secondItem="uXC-Rm-Hek" secondAttribute="trailing" constant="286" id="Uc1-pS-uKg"/>
|
||||
<constraint firstItem="lEu-rZ-H6U" firstAttribute="top" secondItem="lxp-KC-Iua" secondAttribute="bottom" constant="4" id="aew-vr-F7L"/>
|
||||
<constraint firstItem="uXC-Rm-Hek" firstAttribute="top" secondItem="Oc2-oW-bST" secondAttribute="top" constant="8" id="dGW-ps-wNH"/>
|
||||
<constraint firstItem="lxp-KC-Iua" firstAttribute="leading" secondItem="Oc2-oW-bST" secondAttribute="leading" constant="16" id="gmr-z4-RMQ"/>
|
||||
<constraint firstItem="BgX-NT-7NG" firstAttribute="top" secondItem="uXC-Rm-Hek" secondAttribute="bottom" constant="8" id="jqp-Lv-waU"/>
|
||||
<constraint firstItem="yeR-J3-ysT" firstAttribute="top" secondItem="hvS-Ix-A23" secondAttribute="bottom" constant="4" id="nZ3-oH-0AF"/>
|
||||
<constraint firstItem="Oc2-oW-bST" firstAttribute="trailing" secondItem="BgX-NT-7NG" secondAttribute="trailing" constant="16" id="pPk-Ih-GDO"/>
|
||||
<constraint firstItem="yeR-J3-ysT" firstAttribute="leading" secondItem="Oc2-oW-bST" secondAttribute="leading" constant="16" id="qBn-xg-Ioc"/>
|
||||
<constraint firstItem="lEu-rZ-H6U" firstAttribute="leading" secondItem="Oc2-oW-bST" secondAttribute="leading" constant="16" id="qCJ-rc-qBq"/>
|
||||
<constraint firstItem="Oc2-oW-bST" firstAttribute="trailing" secondItem="lEu-rZ-H6U" secondAttribute="trailing" constant="16" id="vaR-Zr-5nI"/>
|
||||
<constraint firstItem="hvS-Ix-A23" firstAttribute="leading" secondItem="Oc2-oW-bST" secondAttribute="leading" constant="16" id="vcb-xj-bM8"/>
|
||||
<constraint firstItem="BgX-NT-7NG" firstAttribute="leading" secondItem="Oc2-oW-bST" secondAttribute="leading" constant="16" id="xOL-J4-JIV"/>
|
||||
</constraints>
|
||||
<viewLayoutGuide key="safeArea" id="LOR-Yw-0FU"/>
|
||||
<viewLayoutGuide key="safeArea" id="Oc2-oW-bST"/>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="indicatorView" destination="K3b-gv-JPp" id="mSR-QU-VZQ"/>
|
||||
<outlet property="mailTextField" destination="mFP-WG-jY5" id="7SN-qe-DDm"/>
|
||||
<outlet property="addTagsTextField" destination="BgX-NT-7NG" id="3vt-U9-NYI"/>
|
||||
<outlet property="searchContainerView" destination="yeR-J3-ysT" id="SzT-fM-A6H"/>
|
||||
<outlet property="testContainer" destination="lEu-rZ-H6U" id="DTe-9O-VAi"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="6e8-oo-bbc" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="eoH-1e-A6A" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="-466" y="-821"/>
|
||||
<point key="canvasLocation" x="4293.6000000000004" y="132.68365817091455"/>
|
||||
</scene>
|
||||
<!--Messages View Controller-->
|
||||
<scene sceneID="WSW-fr-Vf8">
|
||||
<objects>
|
||||
<tableViewController storyboardIdentifier="MessagesViewController" id="KLf-CK-diQ" customClass="MessagesViewController" customModule="GDproject" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" id="13B-QX-K78">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<prototypes>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="MessageViewCell" rowHeight="78" id="67C-fT-WEV" customClass="MessageViewCell" customModule="GDproject" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="28" width="375" height="78"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="67C-fT-WEV" id="O3b-Xv-UNk">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="77.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="xAY-IF-RpX">
|
||||
<rect key="frame" x="229" y="11" width="130" height="15"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" relation="greaterThanOrEqual" constant="130" id="f99-ZF-f8h"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="12"/>
|
||||
<color key="textColor" white="0.66666666669999997" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="FG3-gU-0r1">
|
||||
<rect key="frame" x="16" y="11" width="46" height="22"/>
|
||||
<fontDescription key="fontDescription" type="system" weight="semibold" pointSize="18"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="nTy-rK-XTr">
|
||||
<rect key="frame" x="16" y="49" width="343" height="18"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="15"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="nTy-rK-XTr" firstAttribute="top" secondItem="xAY-IF-RpX" secondAttribute="bottom" constant="23" id="09Y-aK-nD9"/>
|
||||
<constraint firstItem="FG3-gU-0r1" firstAttribute="top" secondItem="O3b-Xv-UNk" secondAttribute="topMargin" id="4Hp-d5-9An"/>
|
||||
<constraint firstItem="xAY-IF-RpX" firstAttribute="top" secondItem="O3b-Xv-UNk" secondAttribute="topMargin" id="G4f-oJ-7ud"/>
|
||||
<constraint firstItem="nTy-rK-XTr" firstAttribute="trailing" secondItem="O3b-Xv-UNk" secondAttribute="trailingMargin" id="MaE-VM-KhL"/>
|
||||
<constraint firstItem="nTy-rK-XTr" firstAttribute="leading" secondItem="O3b-Xv-UNk" secondAttribute="leadingMargin" id="OIX-rY-Leo"/>
|
||||
<constraint firstItem="nTy-rK-XTr" firstAttribute="top" secondItem="FG3-gU-0r1" secondAttribute="bottom" constant="16" id="Qdj-s3-t60"/>
|
||||
<constraint firstItem="nTy-rK-XTr" firstAttribute="bottom" secondItem="O3b-Xv-UNk" secondAttribute="bottomMargin" id="Rv3-Mz-Aed"/>
|
||||
<constraint firstItem="FG3-gU-0r1" firstAttribute="leading" secondItem="O3b-Xv-UNk" secondAttribute="leadingMargin" id="iN1-KG-dYn"/>
|
||||
<constraint firstItem="xAY-IF-RpX" firstAttribute="trailing" secondItem="O3b-Xv-UNk" secondAttribute="trailingMargin" id="opV-4x-VCk"/>
|
||||
<constraint firstItem="xAY-IF-RpX" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="FG3-gU-0r1" secondAttribute="trailing" constant="4" id="x9r-sM-t4x"/>
|
||||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
<connections>
|
||||
<outlet property="dateLabel" destination="xAY-IF-RpX" id="fcz-re-BXk"/>
|
||||
<outlet property="dialogName" destination="FG3-gU-0r1" id="gd7-ND-wCi"/>
|
||||
<outlet property="lastMessagePreview" destination="nTy-rK-XTr" id="Cmo-IJ-2r0"/>
|
||||
</connections>
|
||||
</tableViewCell>
|
||||
</prototypes>
|
||||
<connections>
|
||||
<outlet property="dataSource" destination="KLf-CK-diQ" id="LjF-Uw-Xhq"/>
|
||||
<outlet property="delegate" destination="KLf-CK-diQ" id="yJZ-wH-O3v"/>
|
||||
</connections>
|
||||
</tableView>
|
||||
</tableViewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="fu3-z4-EY7" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="2681" y="918"/>
|
||||
</scene>
|
||||
<!--People To Write View Controller-->
|
||||
<scene sceneID="6Td-bq-Ebf">
|
||||
<objects>
|
||||
<tableViewController storyboardIdentifier="PeopleToWriteViewController" id="rUc-Tv-hWE" customClass="PeopleToWriteViewController" customModule="GDproject" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" allowsSelectionDuringEditing="YES" allowsMultipleSelection="YES" allowsMultipleSelectionDuringEditing="YES" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" id="PDb-NB-Ey6">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<prototypes>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="peopleToWriteCell" textLabel="e4H-yo-W57" style="IBUITableViewCellStyleDefault" id="5ue-Sf-Blf">
|
||||
<rect key="frame" x="0.0" y="28" width="375" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="5ue-Sf-Blf" id="8Dr-YE-x7M">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Title" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="e4H-yo-W57">
|
||||
<rect key="frame" x="16" y="0.0" width="343" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
</prototypes>
|
||||
<connections>
|
||||
<outlet property="dataSource" destination="rUc-Tv-hWE" id="cuc-oZ-Sna"/>
|
||||
<outlet property="delegate" destination="rUc-Tv-hWE" id="hw6-6X-Rlx"/>
|
||||
</connections>
|
||||
</tableView>
|
||||
</tableViewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="Zp5-b5-nn2" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="3614" y="938"/>
|
||||
</scene>
|
||||
<!--Chat Info View Controller-->
|
||||
<scene sceneID="1br-Xg-fR9">
|
||||
<objects>
|
||||
<tableViewController storyboardIdentifier="ChatInfoViewController" id="Rfd-Hp-Qqv" customClass="ChatInfoViewController" customModule="GDproject" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="grouped" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="18" sectionFooterHeight="18" id="Rvg-ok-cnE">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
|
||||
<prototypes>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="cell" textLabel="EdJ-of-2FG" style="IBUITableViewCellStyleDefault" id="hl5-Uc-R53">
|
||||
<rect key="frame" x="0.0" y="55.5" width="375" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="hl5-Uc-R53" id="Oy5-4e-dPI">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Title" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="EdJ-of-2FG">
|
||||
<rect key="frame" x="16" y="0.0" width="343" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
</prototypes>
|
||||
<sections/>
|
||||
<connections>
|
||||
<outlet property="dataSource" destination="Rfd-Hp-Qqv" id="ThC-G8-che"/>
|
||||
<outlet property="delegate" destination="Rfd-Hp-Qqv" id="1WG-zg-Ahf"/>
|
||||
</connections>
|
||||
</tableView>
|
||||
</tableViewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="KPW-41-EQd" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="5057" y="938"/>
|
||||
</scene>
|
||||
<!--Tags Suggestion Controller-->
|
||||
<scene sceneID="gfS-IA-vBj">
|
||||
<objects>
|
||||
<tableViewController storyboardIdentifier="TagsSuggestionController" id="shX-JH-apo" customClass="TagsSuggestionController" customModule="GDproject" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" id="jTj-mU-lli">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<prototypes>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="none" indentationWidth="10" reuseIdentifier="cell" textLabel="Lbu-Z7-fTN" style="IBUITableViewCellStyleDefault" id="pnl-jg-9DL">
|
||||
<rect key="frame" x="0.0" y="28" width="375" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="pnl-jg-9DL" id="Vsm-Ic-k7e">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Title" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Lbu-Z7-fTN">
|
||||
<rect key="frame" x="16" y="0.0" width="343" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
</prototypes>
|
||||
<connections>
|
||||
<outlet property="dataSource" destination="shX-JH-apo" id="a9b-xm-VIg"/>
|
||||
<outlet property="delegate" destination="shX-JH-apo" id="Cg4-aC-E7h"/>
|
||||
</connections>
|
||||
</tableView>
|
||||
</tableViewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="RsJ-xx-GJW" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="5925" y="1339"/>
|
||||
</scene>
|
||||
<!--Channel View Controller-->
|
||||
<scene sceneID="myW-UY-uGB">
|
||||
<objects>
|
||||
<tableViewController storyboardIdentifier="ChannelViewController" id="M45-Em-JMM" customClass="ChannelViewController" customModule="GDproject" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="grouped" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="18" sectionFooterHeight="18" id="poy-7L-m8s">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
|
||||
<prototypes>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="titleCell" id="x0n-Is-bsF" customClass="TitleCell" customModule="GDproject" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="55.5" width="375" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="x0n-Is-bsF" id="5aI-NN-BRQ">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="Name the channel" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="jTk-cs-cpn">
|
||||
<rect key="frame" x="16" y="7" width="343" height="30"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="30" id="ZDL-Wx-W4e"/>
|
||||
</constraints>
|
||||
<nil key="textColor"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<textInputTraits key="textInputTraits"/>
|
||||
</textField>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailing" secondItem="jTk-cs-cpn" secondAttribute="trailing" constant="16" id="KLT-Mg-Igg"/>
|
||||
<constraint firstAttribute="bottom" secondItem="jTk-cs-cpn" secondAttribute="bottom" constant="6.5" id="Yuh-81-wLm"/>
|
||||
<constraint firstItem="jTk-cs-cpn" firstAttribute="leading" secondItem="5aI-NN-BRQ" secondAttribute="leading" constant="16" id="tx2-BD-LW1"/>
|
||||
<constraint firstItem="jTk-cs-cpn" firstAttribute="top" secondItem="5aI-NN-BRQ" secondAttribute="top" constant="7" id="ufD-Sr-H0c"/>
|
||||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
<connections>
|
||||
<outlet property="titleLabel" destination="jTk-cs-cpn" id="ysU-SK-thv"/>
|
||||
</connections>
|
||||
</tableViewCell>
|
||||
</prototypes>
|
||||
<sections/>
|
||||
<connections>
|
||||
<outlet property="dataSource" destination="M45-Em-JMM" id="zIt-LL-u3B"/>
|
||||
<outlet property="delegate" destination="M45-Em-JMM" id="8oD-9d-gx0"/>
|
||||
</connections>
|
||||
</tableView>
|
||||
</tableViewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="W3K-lW-jpq" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="5844" y="448"/>
|
||||
</scene>
|
||||
<!--Add To ChannelVC-->
|
||||
<scene sceneID="Qir-mq-wma">
|
||||
<objects>
|
||||
<tableViewController storyboardIdentifier="AddToChannelVC" id="sZD-zJ-IzQ" customClass="AddToChannelVC" customModule="GDproject" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" id="yj4-wM-mw1">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<prototypes>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="none" indentationWidth="10" id="xMi-Gz-AGg">
|
||||
<rect key="frame" x="0.0" y="28" width="375" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="xMi-Gz-AGg" id="Lj0-2E-Ai9">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
</prototypes>
|
||||
<connections>
|
||||
<outlet property="dataSource" destination="sZD-zJ-IzQ" id="RJA-hG-8Bd"/>
|
||||
<outlet property="delegate" destination="sZD-zJ-IzQ" id="zlr-yK-CDk"/>
|
||||
</connections>
|
||||
</tableView>
|
||||
</tableViewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="kT3-kK-tSX" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="6548" y="448"/>
|
||||
</scene>
|
||||
<!--Posts-->
|
||||
<scene sceneID="RSd-UJ-34B">
|
||||
@ -476,33 +1037,10 @@
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</navigationBar>
|
||||
<nil name="viewControllers"/>
|
||||
<connections>
|
||||
<segue destination="Nqc-TI-ueQ" kind="relationship" relationship="rootViewController" id="2BZ-i4-uIE"/>
|
||||
</connections>
|
||||
</navigationController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="POV-5T-jeQ" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="1088.8" y="132.68365817091455"/>
|
||||
</scene>
|
||||
<!--News Controller-->
|
||||
<scene sceneID="eR7-97-LRL">
|
||||
<objects>
|
||||
<tableViewController storyboardIdentifier="NewsController" id="Nqc-TI-ueQ" customClass="NewsController" customModule="GDproject" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" id="hwA-SE-xpS">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<color key="sectionIndexBackgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<connections>
|
||||
<outlet property="dataSource" destination="Nqc-TI-ueQ" id="bu5-tQ-7lb"/>
|
||||
<outlet property="delegate" destination="Nqc-TI-ueQ" id="kTM-Be-8qb"/>
|
||||
</connections>
|
||||
</tableView>
|
||||
<navigationItem key="navigationItem" largeTitleDisplayMode="always" id="b8E-6f-hLM"/>
|
||||
</tableViewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="c9d-Kh-itI" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="1880" y="136"/>
|
||||
<point key="canvasLocation" x="1089" y="-306"/>
|
||||
</scene>
|
||||
<!--Profile-->
|
||||
<scene sceneID="dJj-Hp-Wa9">
|
||||
@ -515,31 +1053,15 @@
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</navigationBar>
|
||||
<nil name="viewControllers"/>
|
||||
<connections>
|
||||
<segue destination="R4D-Ao-uvG" kind="relationship" relationship="rootViewController" id="aF6-zK-hCB"/>
|
||||
</connections>
|
||||
</navigationController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="Fvm-qf-2Ve" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="1089" y="958"/>
|
||||
<point key="canvasLocation" x="1015" y="1216"/>
|
||||
</scene>
|
||||
<!--Navigation Controller-->
|
||||
<scene sceneID="r0M-xH-UwU">
|
||||
<objects>
|
||||
<navigationController storyboardIdentifier="root" id="609-2j-gc9" sceneMemberID="viewController">
|
||||
<navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="Ah8-NU-AsD">
|
||||
<rect key="frame" x="0.0" y="20" width="375" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</navigationBar>
|
||||
</navigationController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="Raj-78-jlT" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="-2242" y="68"/>
|
||||
</scene>
|
||||
<!--Tab Bar Controller-->
|
||||
<!--Tabbar Controller-->
|
||||
<scene sceneID="HCR-WO-p7g">
|
||||
<objects>
|
||||
<tabBarController storyboardIdentifier="TabBar" automaticallyAdjustsScrollViewInsets="NO" id="IeP-4W-8LT" sceneMemberID="viewController">
|
||||
<tabBarController storyboardIdentifier="TabbarController" automaticallyAdjustsScrollViewInsets="NO" id="IeP-4W-8LT" customClass="TabbarController" customModule="GDproject" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<toolbarItems/>
|
||||
<tabBar key="tabBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="3pl-mU-U30">
|
||||
<rect key="frame" x="0.0" y="0.0" width="1000" height="1000"/>
|
||||
@ -548,6 +1070,7 @@
|
||||
</tabBar>
|
||||
<connections>
|
||||
<segue destination="NuV-ZG-ld2" kind="relationship" relationship="viewControllers" id="XuX-8s-fZU"/>
|
||||
<segue destination="gt4-mD-66Q" kind="relationship" relationship="viewControllers" id="QM3-FF-LMu"/>
|
||||
<segue destination="tae-5q-wvT" kind="relationship" relationship="viewControllers" id="wCJ-4N-lfC"/>
|
||||
</connections>
|
||||
</tabBarController>
|
||||
@ -555,9 +1078,40 @@
|
||||
</objects>
|
||||
<point key="canvasLocation" x="-466" y="641"/>
|
||||
</scene>
|
||||
<!--News Controller-->
|
||||
<scene sceneID="kf1-SJ-kcp">
|
||||
<objects>
|
||||
<viewController storyboardIdentifier="NewsController" id="R7p-5c-Vzl" customClass="NewsController" customModule="GDproject" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="Kx5-cu-FC2">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="5IP-vK-phq">
|
||||
<rect key="frame" x="0.0" y="20" width="375" height="647"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
</tableView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstItem="5IP-vK-phq" firstAttribute="top" secondItem="qGo-Sq-Oz2" secondAttribute="top" id="HvO-w8-yYd"/>
|
||||
<constraint firstItem="5IP-vK-phq" firstAttribute="leading" secondItem="qGo-Sq-Oz2" secondAttribute="leading" id="NTk-fa-llk"/>
|
||||
<constraint firstItem="qGo-Sq-Oz2" firstAttribute="bottom" secondItem="5IP-vK-phq" secondAttribute="bottom" id="mAj-tJ-R30"/>
|
||||
<constraint firstItem="qGo-Sq-Oz2" firstAttribute="trailing" secondItem="5IP-vK-phq" secondAttribute="trailing" id="pcE-yb-fxC"/>
|
||||
</constraints>
|
||||
<viewLayoutGuide key="safeArea" id="qGo-Sq-Oz2"/>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="tableView" destination="5IP-vK-phq" id="EQe-eC-W7P"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="6Lk-UL-mQL" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="5426" y="-235"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
<resources>
|
||||
<image name="1" width="30" height="30"/>
|
||||
<image name="5" width="30" height="30"/>
|
||||
<image name="chat" width="30" height="30"/>
|
||||
</resources>
|
||||
</document>
|
||||
|
@ -6,6 +6,7 @@
|
||||
// Copyright © 2019 drHSE. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
/// constant for cell in posts NewsController.swift
|
||||
let postCellId = "PostCell"
|
||||
|
||||
@ -42,7 +43,29 @@ let newsController = "NewsController"
|
||||
/// constant for switching to view controller for log in app
|
||||
let logInController = "LogInController"
|
||||
|
||||
/// constant for getting to messages
|
||||
let messagesViewControllerId = "MessagesViewController"
|
||||
|
||||
/// constant for displaying list of people to send message to
|
||||
let peopleToWriteVC = "PeopleToWriteViewController"
|
||||
|
||||
let dialogVC = "DialogViewController"
|
||||
|
||||
let profileViewController = "ProfileViewController"
|
||||
|
||||
let simplifiedChannelsList = "SimplifiedChannelsList"
|
||||
|
||||
let channelViewControllerId = "ChannelViewController"
|
||||
|
||||
let addToChannelVCId = "AddToChannelVC"
|
||||
|
||||
let taggsSelectionViewController = "TaggsSelectionViewController"
|
||||
|
||||
let dialogViewController = "DialogViewController"
|
||||
|
||||
let tagsSuggestionController = "TagsSuggestionController"
|
||||
|
||||
let chatInfoViewController = "ChatInfoViewController"
|
||||
|
||||
let blueSystemColor = UIColor(red: 0, green: 137/255, blue: 249/255, alpha: 0.5)
|
||||
|
||||
|
132
GDproject/Controller/ News and channels/AddToChannelVC.swift
Normal file
132
GDproject/Controller/ News and channels/AddToChannelVC.swift
Normal file
@ -0,0 +1,132 @@
|
||||
//
|
||||
// AddToChannelVC.swift
|
||||
// GDproject
|
||||
//
|
||||
// Created by cstore on 02/05/2019.
|
||||
// Copyright © 2019 drHSE. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
enum DataSourse{
|
||||
case people, tags
|
||||
}
|
||||
|
||||
class AddToChannelVC: UITableViewController {
|
||||
|
||||
var channel: Model.Channels?
|
||||
weak var update: UpdatableChannel?
|
||||
|
||||
// data sources for people and hashtags
|
||||
var dataSourcePeople: [Model.Users] = Model.Channels.fullPeople
|
||||
|
||||
var reloadtable: Bool = false {
|
||||
didSet{
|
||||
tableView.reloadData()
|
||||
}
|
||||
}
|
||||
|
||||
var filteredDataSource = [Model.Users]()
|
||||
|
||||
func filterContentForSearchText(_ searchText: String, scope: String = "All")
|
||||
{
|
||||
filteredDataSource = dataSourcePeople.filter { $0.fullName().lowercased().contains(searchText.lowercased()) }
|
||||
tableView.reloadData()
|
||||
}
|
||||
|
||||
let searchC = UISearchController(searchResultsController: nil)
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
navigationItem.title = "People"
|
||||
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
|
||||
self.navigationItem.searchController = searchC
|
||||
navigationItem.largeTitleDisplayMode = .never
|
||||
self.navigationItem.hidesSearchBarWhenScrolling = false
|
||||
definesPresentationContext = true
|
||||
searchC.searchResultsUpdater = self
|
||||
searchC.obscuresBackgroundDuringPresentation = false
|
||||
}
|
||||
|
||||
override func viewWillDisappear(_ animated: Bool) {
|
||||
super.viewWillDisappear(animated)
|
||||
update?.updateChannel(with: channel!)
|
||||
}
|
||||
// MARK: - Table view data source
|
||||
|
||||
override func numberOfSections(in tableView: UITableView) -> Int {
|
||||
return 1
|
||||
}
|
||||
|
||||
var isFiltering: Bool {
|
||||
return searchC.isActive && !searchBarIsEmpty()
|
||||
}
|
||||
|
||||
func searchBarIsEmpty() -> Bool {
|
||||
return searchC.searchBar.text?.isEmpty ?? true
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
if isFiltering {
|
||||
return filteredDataSource.count
|
||||
} else {
|
||||
return dataSourcePeople.count
|
||||
}
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
|
||||
{
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
|
||||
|
||||
if isFiltering{
|
||||
cell.textLabel?.text = filteredDataSource[indexPath.row].fullName()
|
||||
if channel!.people.contains(filteredDataSource[indexPath.row].id) {
|
||||
cell.backgroundColor = #colorLiteral(red: 0.4745098054, green: 0.8392156959, blue: 0.9764705896, alpha: 1)
|
||||
} else {
|
||||
cell.backgroundColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)
|
||||
}
|
||||
} else {
|
||||
cell.textLabel?.text = dataSourcePeople[indexPath.row].fullName()
|
||||
if channel!.people.contains(dataSourcePeople[indexPath.row].id) {
|
||||
cell.backgroundColor = #colorLiteral(red: 0.4745098054, green: 0.8392156959, blue: 0.9764705896, alpha: 1)
|
||||
} else {
|
||||
cell.backgroundColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)
|
||||
}
|
||||
}
|
||||
|
||||
cell.selectionStyle = .none
|
||||
|
||||
return cell
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
if let cell = tableView.cellForRow(at: indexPath) {
|
||||
if isFiltering{
|
||||
if cell.backgroundColor == #colorLiteral(red: 0.4745098054, green: 0.8392156959, blue: 0.9764705896, alpha: 1) {
|
||||
let filtered = channel!.people.filter{ $0 != filteredDataSource[indexPath.row].id }
|
||||
channel?.people = filtered
|
||||
cell.backgroundColor = #colorLiteral(red: 0.9999960065, green: 1, blue: 1, alpha: 1)
|
||||
} else {
|
||||
channel?.people.append(filteredDataSource[indexPath.row].id)
|
||||
cell.backgroundColor = #colorLiteral(red: 0.4745098054, green: 0.8392156959, blue: 0.9764705896, alpha: 1)
|
||||
}
|
||||
} else {
|
||||
if cell.backgroundColor == #colorLiteral(red: 0.4745098054, green: 0.8392156959, blue: 0.9764705896, alpha: 1) {
|
||||
let filtered = channel!.people.filter{ $0 != dataSourcePeople[indexPath.row].id }
|
||||
channel?.people = filtered
|
||||
cell.backgroundColor = #colorLiteral(red: 0.9999960065, green: 1, blue: 1, alpha: 1)
|
||||
} else {
|
||||
channel?.people.append(dataSourcePeople[indexPath.row].id)
|
||||
cell.backgroundColor = #colorLiteral(red: 0.4745098054, green: 0.8392156959, blue: 0.9764705896, alpha: 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension AddToChannelVC : UISearchResultsUpdating {
|
||||
func updateSearchResults(for searchController: UISearchController) {
|
||||
filterContentForSearchText(searchController.searchBar.text!)
|
||||
}
|
||||
}
|
@ -25,7 +25,7 @@ class ChannelController: UIViewController, UITableViewDelegate, UITableViewDataS
|
||||
var channel: Model.Channels?
|
||||
var myProtocol: DataDelegate?
|
||||
|
||||
var fullTags: [String] = Array(Model.Channels.fullTags)
|
||||
var fullTags: [String] = CompletionTree.getCompletion(tree: Model.hashTagTree!, word: "")
|
||||
|
||||
var dataSourcePeople: [Model.Users] = []
|
||||
|
||||
@ -33,6 +33,9 @@ class ChannelController: UIViewController, UITableViewDelegate, UITableViewDataS
|
||||
|
||||
var activeDataSource: ActiveTable = .people
|
||||
|
||||
// func to show preview of the current channel
|
||||
var onShowingPreview: ((Model.Channels)->())?
|
||||
|
||||
@IBOutlet weak var viewww: UIView!
|
||||
|
||||
@IBOutlet weak var textField: UITextField!
|
||||
@ -61,16 +64,33 @@ class ChannelController: UIViewController, UITableViewDelegate, UITableViewDataS
|
||||
|
||||
// TODO: update channel
|
||||
override func viewWillDisappear(_ animated: Bool) {
|
||||
|
||||
defer {
|
||||
super.viewWillDisappear(animated)
|
||||
}
|
||||
|
||||
guard let _ = self.navigationController?.viewControllers.lastIndex(of: self) else {
|
||||
if let _ = channel?.id { print("update")
|
||||
Model.updateChannel(with: channel!)
|
||||
} else { print("create")
|
||||
Model.createChannel(with: channel!)
|
||||
//Model.createChannel(with: channel!)
|
||||
}
|
||||
return
|
||||
}
|
||||
// nou
|
||||
}
|
||||
|
||||
@objc func showPreview(){
|
||||
if let channel = channel {
|
||||
onShowingPreview?(channel)
|
||||
}
|
||||
}
|
||||
|
||||
func setUpController(){
|
||||
|
||||
// setting up the preview button for the editing or created channel
|
||||
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Preview", style: .done, target: self, action: #selector(showPreview))
|
||||
|
||||
tableView.delegate = self
|
||||
tableView.dataSource = self
|
||||
tableView.register(UITableViewCell.self, forCellReuseIdentifier: itemCellId)
|
||||
@ -232,9 +252,7 @@ class ChannelController: UIViewController, UITableViewDelegate, UITableViewDataS
|
||||
}
|
||||
tableView.reloadData()
|
||||
case 1:
|
||||
dataSourceTags = fullTags.filter({ (s) -> Bool in
|
||||
s.lowercased().contains(text.lowercased())
|
||||
})
|
||||
dataSourceTags = CompletionTree.getCompletion(tree: Model.hashTagTree!, word: text)
|
||||
tableView.reloadData()
|
||||
default:
|
||||
break
|
||||
|
@ -13,16 +13,20 @@ struct ChannelData{
|
||||
var subtitle = String()
|
||||
}
|
||||
|
||||
protocol ChannelListData: class {
|
||||
func reloadData (with channels: [Model.Channels])
|
||||
}
|
||||
|
||||
// TODO: make search controller availiable
|
||||
class ChannelListController: UITableViewController, DataDelegate {
|
||||
class ChannelListController: UITableViewController {
|
||||
|
||||
// MARK: - Output -
|
||||
var onChannelSelected: ((Model.Channels) -> Void)?
|
||||
var onEditingModeBegins: ((Model.Channels, IndexPath)->Void)?
|
||||
|
||||
// MARK: - filter search controller
|
||||
var filteredDataSource = [Model.Channels]()
|
||||
|
||||
var myProtocol: DataDelegate?
|
||||
var displayingChannel: Model.Channels?
|
||||
|
||||
var toReload: Bool = false {
|
||||
@ -80,7 +84,7 @@ class ChannelListController: UITableViewController, DataDelegate {
|
||||
askForUpdates()
|
||||
}
|
||||
|
||||
private func askForUpdates(){
|
||||
func askForUpdates(){
|
||||
Model.channelsList { [weak self] (channels) in
|
||||
self?.dataSource = [ChannelListController.generalChannel] + channels
|
||||
self?.toReload = true
|
||||
@ -89,17 +93,14 @@ class ChannelListController: UITableViewController, DataDelegate {
|
||||
|
||||
override func viewWillAppear(_ animated: Bool) {
|
||||
super.viewWillAppear(true)
|
||||
askForUpdates()
|
||||
//askForUpdates()
|
||||
tabBarController?.tabBar.isHidden = false
|
||||
}
|
||||
|
||||
@objc func addChannel()
|
||||
{
|
||||
// editing mode is on automatically
|
||||
let vc = storyboard?.instantiateViewController(withIdentifier: channelControllerId) as! ChannelController
|
||||
vc.index = 1
|
||||
vc.myProtocol = self
|
||||
vc.channel = Model.Channels(people: [], name: "Untitled", tags: [])
|
||||
navigationController?.pushViewController(vc, animated: true)
|
||||
onEditingModeBegins?(Model.Channels(people: [], name: "Untitled", id: 0, tags: []),IndexPath(row: 1, section: 0))
|
||||
}
|
||||
|
||||
static let generalChannel = Model.Channels(people: [], name: "General", id: -1, tags: [])
|
||||
@ -143,16 +144,11 @@ class ChannelListController: UITableViewController, DataDelegate {
|
||||
|
||||
override func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]?
|
||||
{
|
||||
|
||||
let editButton = UITableViewRowAction(style: .normal, title: "Edit") { [weak self] (action, indexPath) in
|
||||
let vc = self?.storyboard?.instantiateViewController(withIdentifier: channelControllerId) as! ChannelController
|
||||
vc.index = indexPath.row
|
||||
vc.myProtocol = self!
|
||||
vc.channel = self?.dataSource[indexPath.row]
|
||||
self?.navigationController?.pushViewController(vc, animated: true)
|
||||
let editButton = UITableViewRowAction(style: .normal, title: "Edit") { [unowned self] (rowAction, indexPath) in
|
||||
self.onEditingModeBegins?(self.dataSource[indexPath.row], indexPath)
|
||||
}
|
||||
editButton.backgroundColor = #colorLiteral(red: 0.8039215803, green: 0.8039215803, blue: 0.8039215803, alpha: 1)
|
||||
|
||||
editButton.backgroundColor = #colorLiteral(red: 0.8039215803, green: 0.8039215803, blue: 0.8039215803, alpha: 1)
|
||||
|
||||
let deleteButton = UITableViewRowAction(style: .normal, title: "Delete") { [weak self] (action, indexPath) in
|
||||
|
||||
@ -160,10 +156,6 @@ class ChannelListController: UITableViewController, DataDelegate {
|
||||
print("хз что тут делать при успехе")
|
||||
})
|
||||
|
||||
if (self!.dataSource[indexPath.row].id == self!.displayingChannel?.id ?? -1)
|
||||
{
|
||||
self?.myProtocol?.passData(for: 0, channel: self!.dataSource[0])
|
||||
}
|
||||
self?.tableView.beginUpdates()
|
||||
self?.dataSource.remove(at: indexPath.row)
|
||||
self?.tableView.deleteRows(at: [indexPath], with: .none)
|
||||
@ -175,17 +167,12 @@ class ChannelListController: UITableViewController, DataDelegate {
|
||||
return [editButton, deleteButton]
|
||||
}
|
||||
|
||||
// TODO: remove popping
|
||||
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
|
||||
{
|
||||
if isFiltering {
|
||||
//onChannelSelected?(filteredDataSource[indexPath.row])
|
||||
myProtocol?.passData(for: 0, channel: filteredDataSource[indexPath.row])
|
||||
navigationController?.popViewController(animated: true)
|
||||
onChannelSelected?(filteredDataSource[indexPath.row])
|
||||
} else {
|
||||
myProtocol?.passData(for: 0, channel: dataSource[indexPath.row])
|
||||
navigationController?.popViewController(animated: true)
|
||||
//onChannelSelected?(ChannelListController.dataSource[indexPath.row])
|
||||
onChannelSelected?(dataSource[indexPath.row])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,208 @@
|
||||
//
|
||||
// ChannelViewController.swift
|
||||
// MessageApp
|
||||
//
|
||||
// Created by cstore on 02/05/2019.
|
||||
// Copyright © 2019 drHSE. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
protocol UpdatableName: class{
|
||||
func updateName(with name: String)
|
||||
}
|
||||
|
||||
protocol UpdatableChannel: class{
|
||||
func updateChannel(with channel: Model.Channels)
|
||||
}
|
||||
|
||||
class ChannelViewController: UITableViewController, UpdatableName, UpdatableChannel, TagsReceiver
|
||||
{
|
||||
var onChoosingHashTags: (([String]?)->())?
|
||||
|
||||
var onChoosingPeople: ((Model.Channels?)->())?
|
||||
|
||||
func receiveTags(tags: [String]) {
|
||||
self.channel?.tags = tags
|
||||
}
|
||||
|
||||
func updateName(with name: String){
|
||||
channel?.name = name
|
||||
}
|
||||
|
||||
func updateChannel(with channel: Model.Channels) {
|
||||
self.channel = channel
|
||||
}
|
||||
|
||||
var channel: Model.Channels?
|
||||
|
||||
// func to show preview of the current channel
|
||||
var onShowingPreview: ((Model.Channels)->())?
|
||||
|
||||
override func viewDidLoad()
|
||||
{
|
||||
super.viewDidLoad()
|
||||
tableView.keyboardDismissMode = .onDrag
|
||||
navigationItem.rightBarButtonItems = [ UIBarButtonItem(barButtonSystemItem: .play, target: self, action: #selector(showPreview)), self.editButtonItem]
|
||||
navigationItem.largeTitleDisplayMode = .never
|
||||
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
|
||||
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "searchCell")
|
||||
}
|
||||
|
||||
override func viewWillAppear(_ animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
tableView.reloadData()
|
||||
}
|
||||
|
||||
override func viewWillDisappear(_ animated: Bool) {
|
||||
|
||||
defer {
|
||||
super.viewWillDisappear(animated)
|
||||
}
|
||||
|
||||
guard let _ = self.navigationController?.viewControllers.lastIndex(of: self) else
|
||||
{
|
||||
if let id = channel?.id, id != 0
|
||||
{
|
||||
Model.updateChannel(with: channel!)
|
||||
} else {
|
||||
Model.createChannel(with: channel!) {
|
||||
[weak self] in
|
||||
self?.showAlertOn(result: $0)
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
// nou
|
||||
}
|
||||
|
||||
@objc func showPreview()
|
||||
{
|
||||
if let channel = channel {
|
||||
onShowingPreview?(channel)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Table view data source
|
||||
|
||||
override func numberOfSections(in tableView: UITableView) -> Int {
|
||||
return 3
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
switch section {
|
||||
case 1:
|
||||
return (channel?.people.count ?? 0) + 1
|
||||
case 2:
|
||||
return (channel?.tags.count ?? 0) + 1
|
||||
default:
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
|
||||
switch section {
|
||||
case 1:
|
||||
return "People"
|
||||
case 2:
|
||||
return "Tags"
|
||||
default:
|
||||
return "Title"
|
||||
}
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||
|
||||
switch indexPath.section{
|
||||
case 1 , 2:
|
||||
return whichCell(tableView, cellForRowAt: indexPath)
|
||||
default:
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "titleCell") as! TitleCell
|
||||
|
||||
cell.fill(title: channel?.name)
|
||||
cell.update = self
|
||||
|
||||
return cell
|
||||
}
|
||||
}
|
||||
|
||||
private func whichCell(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
|
||||
{
|
||||
let row = indexPath.row
|
||||
let section = indexPath.section
|
||||
|
||||
if row == 0
|
||||
{
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "searchCell")!
|
||||
cell.textLabel?.text = "Add more"
|
||||
cell.accessoryType = .disclosureIndicator
|
||||
return cell
|
||||
}
|
||||
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
|
||||
|
||||
if section == 1 {
|
||||
cell.textLabel?.text = "👤 \(Model.Channels.fullPeopleDict[channel?.people[row-1] ?? 0]!.fullName())"
|
||||
} else {
|
||||
cell.textLabel?.text = "# \(channel!.tags[row-1])"
|
||||
}
|
||||
|
||||
return cell
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath)
|
||||
{
|
||||
if editingStyle == UITableViewCell.EditingStyle.delete
|
||||
{
|
||||
if indexPath.section == 1 {
|
||||
channel?.people.remove(at: indexPath.row-1)
|
||||
} else {
|
||||
channel?.tags.remove(at: indexPath.row-1)
|
||||
}
|
||||
}
|
||||
|
||||
tableView.reloadData()
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
|
||||
if indexPath.row == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
|
||||
{
|
||||
if indexPath.row == 0 && indexPath.section == 1
|
||||
{
|
||||
onChoosingPeople?(channel)
|
||||
}
|
||||
|
||||
if indexPath.row == 0 && indexPath.section == 2 {
|
||||
onChoosingHashTags?(channel?.tags)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class TitleCell: UITableViewCell, UITextFieldDelegate {
|
||||
|
||||
@IBOutlet weak var titleLabel: UITextField!
|
||||
|
||||
weak var update: UpdatableName?
|
||||
|
||||
override func awakeFromNib() {
|
||||
super.awakeFromNib()
|
||||
}
|
||||
|
||||
func fill(title: String?){
|
||||
titleLabel.text = title
|
||||
titleLabel.addTarget(self, action: #selector(changedText(_:)), for: .editingChanged)
|
||||
}
|
||||
|
||||
@objc func changedText(_ textField: UITextField){
|
||||
update?.updateName(with: textField.text!)
|
||||
}
|
||||
}
|
@ -1,55 +0,0 @@
|
||||
//
|
||||
// ChannelsCoordinator.swift
|
||||
// GDproject
|
||||
//
|
||||
// Created by cstore on 23/02/2019.
|
||||
// Copyright © 2019 drHSE. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import UIKit
|
||||
|
||||
final class ChannelsCoordinator{
|
||||
|
||||
// MARK: - Properties
|
||||
private var channel: Model.Channels { didSet { updateInterfaces() } }
|
||||
private weak var navigationController: UINavigationController?
|
||||
|
||||
// MARK:- Init
|
||||
init(currentChannel: Model.Channels, navigationController: UINavigationController) {
|
||||
self.channel = currentChannel
|
||||
self.navigationController = navigationController
|
||||
}
|
||||
|
||||
func start(){
|
||||
showCurrentChannel()
|
||||
}
|
||||
|
||||
// MARK: - Private implementation
|
||||
private func showListOfChannels(){
|
||||
let controller = UIStoryboard.makeChannelsListController()
|
||||
controller.onChannelSelected = { [weak self] channel
|
||||
in
|
||||
self?.channel = channel
|
||||
_ = self?.navigationController?.popViewController(animated: true)
|
||||
}
|
||||
navigationController?.pushViewController(controller, animated: true)
|
||||
}
|
||||
|
||||
private func showCurrentChannel(){
|
||||
let controller = UIStoryboard.makeNewsController()
|
||||
controller.channel = channel
|
||||
controller.onSelectChannel = { [weak self] in
|
||||
self?.showListOfChannels()
|
||||
}
|
||||
navigationController?.setViewControllers([controller], animated: false)
|
||||
//navigationController?.pushViewController(controller, animated: false)
|
||||
}
|
||||
|
||||
// MARK:- update only viewControllers which are depandable on chosen channel
|
||||
private func updateInterfaces() {
|
||||
navigationController?.viewControllers.forEach {
|
||||
($0 as? UpdateableWithChannel)?.channel = channel
|
||||
}
|
||||
}
|
||||
}
|
@ -25,27 +25,10 @@ class FullPostController: UITableViewController {
|
||||
|
||||
func setUpNavigationBar(){
|
||||
navigationItem.largeTitleDisplayMode = .never
|
||||
navigationItem.title = "\(post?.authorId ?? 0)"
|
||||
navigationItem.rightBarButtonItems = [UIBarButtonItem(barButtonSystemItem: .action, target: self, action: #selector(self.options))]
|
||||
navigationItem.title = "Post"
|
||||
}
|
||||
|
||||
@objc func options(){
|
||||
// drafts
|
||||
// saved
|
||||
|
||||
let optionMenu = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
|
||||
let editAction = UIAlertAction(title: "Send via message", style: .default)
|
||||
let shareAction = UIAlertAction(title: "Send via project", style: .default)
|
||||
let settingsAction = UIAlertAction(title: "Copy link", style: .default)
|
||||
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel)
|
||||
|
||||
optionMenu.addAction(editAction)
|
||||
optionMenu.addAction(shareAction)
|
||||
optionMenu.addAction(settingsAction)
|
||||
optionMenu.addAction(cancelAction)
|
||||
|
||||
self.present(optionMenu, animated: true, completion: nil)
|
||||
}
|
||||
// MARK: - Table view data source
|
||||
|
||||
override func numberOfSections(in tableView: UITableView) -> Int {
|
||||
@ -102,6 +85,7 @@ class FullPostController: UITableViewController {
|
||||
cell.onUserDisplay = { [weak self] (id) in
|
||||
let vc = self?.storyboard!.instantiateViewController(withIdentifier: profileViewController) as! ProfileViewController
|
||||
vc.idProfile = id
|
||||
|
||||
self?.navigationController?.pushViewController(vc, animated: true)
|
||||
}
|
||||
default:
|
||||
|
@ -10,21 +10,36 @@ import UIKit
|
||||
import Cartography
|
||||
import Marklight
|
||||
import TinyConstraints
|
||||
import WSTagsField
|
||||
import TaggerKit
|
||||
// import WSTagsField
|
||||
|
||||
class NewPostViewController: UIViewController, UITextViewDelegate {
|
||||
class NewPostViewController: UIViewController, UITextViewDelegate, TagsReceiver
|
||||
{
|
||||
func receiveTags(tags: [String]) {
|
||||
currentTags = tags
|
||||
}
|
||||
|
||||
@IBOutlet weak var view1: UIView!
|
||||
|
||||
@IBOutlet weak var viewForTags: UIView!
|
||||
var currentTags: [String] = []
|
||||
|
||||
fileprivate let tagsField = WSTagsField()
|
||||
// We want the whole experience, let's create two TKCollectionViews
|
||||
let productTags = TKCollectionView()
|
||||
|
||||
@IBAction func chooseTags(_ sender: UIButton) {
|
||||
let vc = storyboard?.instantiateViewController(withIdentifier: taggsSelectionViewController) as! TaggsSelectionViewController
|
||||
|
||||
NewPostViewController.draft = textView.text
|
||||
vc.receiver = self
|
||||
vc.currentTags = currentTags
|
||||
|
||||
navigationController?.pushViewController(vc, animated: true)
|
||||
}
|
||||
|
||||
// fileprivate let tagsField = WSTagsField()
|
||||
// Keep strong instance of the `NSTextStorage` subclass
|
||||
let textStorage = MarklightTextStorage()
|
||||
|
||||
weak var parentVC: NewsController?
|
||||
var myProtocol: NewPostDelegate?
|
||||
|
||||
static var draft: String = ""
|
||||
static var hashTagsDraft: [String] = [ ]
|
||||
|
||||
@ -57,11 +72,11 @@ class NewPostViewController: UIViewController, UITextViewDelegate {
|
||||
|
||||
setUpMD()
|
||||
setUpTextView()
|
||||
setUpAccessoryView()
|
||||
setUpTagsView()
|
||||
// setUpAccessoryView()
|
||||
//setUpTagsView()
|
||||
}
|
||||
|
||||
func setUpTagsView(){
|
||||
/* func setUpTagsView(){
|
||||
tagsField.frame = viewForTags.bounds
|
||||
viewForTags.addSubview(tagsField)
|
||||
|
||||
@ -89,15 +104,16 @@ class NewPostViewController: UIViewController, UITextViewDelegate {
|
||||
tagsField.acceptTagOption = .space
|
||||
|
||||
textFieldEvents()
|
||||
}
|
||||
}*/
|
||||
|
||||
override func viewWillAppear(_ animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
|
||||
navigationController?.navigationBar.prefersLargeTitles = false
|
||||
//navigationController?.navigationBar.prefersLargeTitles = false
|
||||
navigationItem.largeTitleDisplayMode = .never
|
||||
navigationItem.title = "New post"
|
||||
textView.text = NewPostViewController.draft
|
||||
tagsField.addTags(NewPostViewController.hashTagsDraft)
|
||||
// tagsField.addTags(NewPostViewController.hashTagsDraft)
|
||||
|
||||
}
|
||||
|
||||
@ -125,7 +141,7 @@ class NewPostViewController: UIViewController, UITextViewDelegate {
|
||||
func setUpTextView(){
|
||||
view.addConstraint(bottomTextViewConstraint)
|
||||
view1.addSubview(textView)
|
||||
textView.edgesToSuperview(insets: .top(8) + .left(8) + .bottom(40+8) + .right(8))
|
||||
textView.edgesToSuperview(insets: .top(8) + .left(8) + .bottom(8) + .right(8))
|
||||
|
||||
if #available(iOS 11.0, *) {
|
||||
textView.smartDashesType = .no
|
||||
@ -194,7 +210,7 @@ class NewPostViewController: UIViewController, UITextViewDelegate {
|
||||
}
|
||||
|
||||
func setUpMD(){
|
||||
textStorage.marklightTextProcessor.codeColor = UIColor.orange
|
||||
textStorage.marklightTextProcessor.codeColor = UIColor.gray
|
||||
textStorage.marklightTextProcessor.quoteColor = UIColor.darkGray
|
||||
textStorage.marklightTextProcessor.syntaxColor = UIColor.blue
|
||||
textStorage.marklightTextProcessor.codeFontName = "Courier"
|
||||
@ -216,10 +232,27 @@ class NewPostViewController: UIViewController, UITextViewDelegate {
|
||||
var indexOfPost = 0
|
||||
// MARK:- new post
|
||||
@objc func newPost(){
|
||||
Model.createAndPublish(body: [Model.Attachments(markdown: textView!.text)], tags: tagsField.tags.map { $0.text })
|
||||
self.navigationItem.title = "Sending..."
|
||||
Model.createAndPublish(body: [Model.Attachments(markdown: textView!.text)], tags: currentTags) {
|
||||
[weak self] in
|
||||
|
||||
switch $0 {
|
||||
case .success1, .success:
|
||||
NewPostViewController.draft = ""
|
||||
NewPostViewController.hashTagsDraft = []
|
||||
self?.moveBackToParentVC?()
|
||||
default:
|
||||
self?.showAlertOn(result: $0)
|
||||
self?.navigationItem.title = "New post"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// NewPostViewController.draft = ""
|
||||
// NewPostViewController.hashTagsDraft = []
|
||||
// adding row to uiTableView after adding new post
|
||||
// myProtocol?.addPost(post: p)
|
||||
moveBackToParentVC()
|
||||
// moveBackToParentVC?()
|
||||
// somewhere here i will be sending server notifications about new post arrival
|
||||
}
|
||||
|
||||
@ -231,8 +264,8 @@ class NewPostViewController: UIViewController, UITextViewDelegate {
|
||||
[weak self]
|
||||
_ in
|
||||
NewPostViewController.draft = self?.textView.text ?? ""
|
||||
NewPostViewController.hashTagsDraft = self?.tagsField.tags.map { $0.text } ?? []
|
||||
self?.moveBackToParentVC()
|
||||
NewPostViewController.hashTagsDraft = self?.currentTags ?? []
|
||||
self?.moveBackToParentVC?()
|
||||
}
|
||||
|
||||
let deleteAction = UIAlertAction(title: "Delete draft", style: .destructive)
|
||||
@ -241,7 +274,7 @@ class NewPostViewController: UIViewController, UITextViewDelegate {
|
||||
in
|
||||
NewPostViewController.draft = ""
|
||||
NewPostViewController.hashTagsDraft = []
|
||||
self?.moveBackToParentVC()
|
||||
self?.moveBackToParentVC?()
|
||||
}
|
||||
|
||||
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel)
|
||||
@ -258,16 +291,7 @@ class NewPostViewController: UIViewController, UITextViewDelegate {
|
||||
actionSaveDraft()
|
||||
}
|
||||
|
||||
func moveBackToParentVC(){
|
||||
let transition = CATransition()
|
||||
transition.duration = 0.5
|
||||
transition.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
|
||||
transition.type = CATransitionType.reveal
|
||||
transition.subtype = CATransitionSubtype.fromBottom
|
||||
navigationController?.view.layer.add(transition, forKey: nil)
|
||||
navigationController?.popViewController(animated: false)
|
||||
textView!.resignFirstResponder()
|
||||
}
|
||||
var moveBackToParentVC: (()->())?
|
||||
|
||||
|
||||
func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange) -> Bool {
|
||||
@ -281,7 +305,7 @@ class NewPostViewController: UIViewController, UITextViewDelegate {
|
||||
textView.scrollRectToVisible(rect, animated: animated)
|
||||
}
|
||||
|
||||
fileprivate func textFieldEvents() {
|
||||
/*fileprivate func textFieldEvents() {
|
||||
tagsField.onDidAddTag = { _, _ in
|
||||
print("onDidAddTag")
|
||||
}
|
||||
@ -305,16 +329,16 @@ class NewPostViewController: UIViewController, UITextViewDelegate {
|
||||
tagsField.onDidUnselectTagView = { _, tagView in
|
||||
print("Unselect \(tagView)")
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
|
||||
extension NewPostViewController: UITextFieldDelegate {
|
||||
|
||||
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
|
||||
if textField == tagsField {
|
||||
/*if textField == tagsField {
|
||||
textView.becomeFirstResponder()
|
||||
}
|
||||
}*/
|
||||
return true
|
||||
}
|
||||
|
||||
|
@ -12,72 +12,49 @@ import Cartography
|
||||
|
||||
protocol UpdateableWithChannel: class {
|
||||
var channel: Model.Channels? { get set }
|
||||
func updateChannel(on channel: Model.Channels)
|
||||
}
|
||||
protocol NewPostDelegate {
|
||||
func addPost(post: Post)
|
||||
}
|
||||
|
||||
protocol UpdateableWithUser: class {
|
||||
var user: Model.Users? { get set }
|
||||
}
|
||||
// MARK:- Controller with posts and channels availiable.
|
||||
// Search is availiable within every table (posts and channels). Has button-functionality for boths post and chnnels
|
||||
class NewsController: UITableViewController, UISearchControllerDelegate, NewPostDelegate, UpdateableWithChannel, DataDelegate
|
||||
class NewsController: UIViewController, UISearchControllerDelegate, UpdateableWithChannel, UISearchResultsUpdating
|
||||
{
|
||||
func passData(for row: Int, channel: Model.Channels) {
|
||||
if channel.id == -1{
|
||||
self.channel = nil
|
||||
} else {
|
||||
func updateChannel(on channel: Model.Channels) {
|
||||
self.channel = channel
|
||||
}
|
||||
news.currChannel = channel
|
||||
decideWhatChannelDisplay()
|
||||
}
|
||||
|
||||
var dictionary: [Int: Model.Users]? {
|
||||
didSet {
|
||||
var changedChannelName: ((String)->())?
|
||||
|
||||
var newPosts: [Model.Posts] = []
|
||||
@IBOutlet weak var tableView: UITableView!
|
||||
|
||||
posts!.forEach({ (post) in
|
||||
|
||||
newPosts.append(Model.Posts(body: post.body, authorId: post.authorId, id: post.id, user: dictionary![post.authorId]!, date: post.updated, tags: post.tags))
|
||||
|
||||
post.tags.forEach { Model.Channels.fullTags.insert($0) }
|
||||
|
||||
})
|
||||
|
||||
|
||||
news.dataSourse = newPosts
|
||||
tableView.reloadData()
|
||||
}
|
||||
}
|
||||
|
||||
var posts: [Model.Posts]? {
|
||||
didSet{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
var channel: Model.Channels? {
|
||||
didSet {
|
||||
navigationItem.title = channel?.name ?? ""
|
||||
}
|
||||
}
|
||||
var channel: Model.Channels?
|
||||
var anonymousChannel: (users: [Int: Model.Users], posts: [Model.Posts])?
|
||||
|
||||
// MARK: - Output -
|
||||
var onSelectChannel: (() -> Void)?
|
||||
|
||||
func addPost(post: Post) {
|
||||
//news.dataSourse.insert(post, at: 0)
|
||||
}
|
||||
|
||||
var searchController = UISearchController(searchResultsController: nil)
|
||||
var searchController: UISearchController?
|
||||
|
||||
var news = NewsVC()
|
||||
var type: HeaderType? = .NEWS
|
||||
|
||||
var refreshContr = UIRefreshControl()
|
||||
|
||||
override func viewDidLoad()
|
||||
{
|
||||
super.viewDidLoad()
|
||||
|
||||
let updater = TagsSuggestionController()
|
||||
updater.delegate = self
|
||||
searchController = UISearchController(searchResultsController: updater)
|
||||
navigationItem.largeTitleDisplayMode = .always
|
||||
|
||||
navigationController?.navigationBar.prefersLargeTitles = true
|
||||
navigationItem.title = "Loading ..."
|
||||
tableView.refreshControl = refreshContr
|
||||
// Configure Refresh Control
|
||||
@ -86,22 +63,23 @@ class NewsController: UITableViewController, UISearchControllerDelegate, NewPost
|
||||
tableView.register(PostViewCell.self, forCellReuseIdentifier: postCellId)
|
||||
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
|
||||
|
||||
// setUpSearchContr()
|
||||
setUpSearchContr()
|
||||
|
||||
// navigationItem.
|
||||
news.viewController = self
|
||||
news.type = .NEWS
|
||||
news.type = type == .NEWS ? .NEWS : type!
|
||||
news.currChannel = channel
|
||||
|
||||
setUpNavigationItemsforPosts()
|
||||
|
||||
//setUpBanner()
|
||||
}
|
||||
|
||||
func setUpSearchContr(){
|
||||
searchController.delegate = self
|
||||
searchController.obscuresBackgroundDuringPresentation = false
|
||||
searchController?.delegate = self
|
||||
searchController?.obscuresBackgroundDuringPresentation = false
|
||||
navigationItem.searchController = searchController
|
||||
definesPresentationContext = true
|
||||
searchController.searchBar.placeholder = "Search anything"
|
||||
searchController?.searchResultsUpdater = self
|
||||
searchController?.searchBar.placeholder = "Search tags"
|
||||
}
|
||||
|
||||
@objc func refreshPostsData( _ ff: UIRefreshControl) {
|
||||
@ -112,19 +90,9 @@ class NewsController: UITableViewController, UISearchControllerDelegate, NewPost
|
||||
print("news clear")
|
||||
}
|
||||
|
||||
let label : UILabel = {
|
||||
let label = UILabel()
|
||||
label.text = "No posts to display yet!"
|
||||
label.font = UIFont.systemFont(ofSize: 18)
|
||||
label.textColor = .black
|
||||
label.isHidden = true
|
||||
label.numberOfLines = 0
|
||||
return label
|
||||
}()
|
||||
|
||||
override func viewWillAppear(_ animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
searchController.isActive = false
|
||||
searchController?.isActive = false
|
||||
// TODO:- display something if no posts are availiable
|
||||
|
||||
decideWhatChannelDisplay()
|
||||
@ -133,128 +101,59 @@ class NewsController: UITableViewController, UISearchControllerDelegate, NewPost
|
||||
}
|
||||
|
||||
func decideWhatChannelDisplay(){
|
||||
if let channel = channel, let id = channel.id {
|
||||
|
||||
Model.getChannel(with: id) { [weak self] in
|
||||
self?.posts = $0.posts
|
||||
self?.dictionary = $0.users
|
||||
switch type! {
|
||||
case .NEWS, .NONE:
|
||||
if let channel = channel, let id = channel.id, id != -1 {
|
||||
|
||||
Model.getAnonymousChannel(by: channel) { [weak self] in
|
||||
self?.news.dataSourse = $0.posts
|
||||
self?.news.dictionary = $0.users
|
||||
self?.refreshContr.endRefreshing()
|
||||
self?.changedChannelName?(channel.name)
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
Model.getLast { [weak self] in
|
||||
self?.posts = $0.posts
|
||||
self?.dictionary = $0.users
|
||||
self?.news.dataSourse = $0.posts
|
||||
self?.news.dictionary = $0.users
|
||||
self?.refreshContr.endRefreshing()
|
||||
self?.navigationItem.title = "General"
|
||||
self?.changedChannelName?("General")
|
||||
}
|
||||
}
|
||||
default:
|
||||
refreshContr.endRefreshing()
|
||||
break
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func setUpNavigationItemsforPosts(){
|
||||
navigationItem.rightBarButtonItems = [UIBarButtonItem(barButtonSystemItem: .compose, target: self, action: #selector(self.writePost(_:))),UIBarButtonItem(barButtonSystemItem: .search, target: self, action: #selector(self.showChannels(_:)))
|
||||
]
|
||||
tableView.delegate = news
|
||||
tableView.dataSource = news
|
||||
tableView.reloadData()
|
||||
}
|
||||
|
||||
// MARK:- attempt with coordinator
|
||||
@objc func showChannels(_ barItem: UIBarButtonItem){
|
||||
let vc = UIStoryboard.makeChannelsListController()
|
||||
vc.myProtocol = self
|
||||
vc.displayingChannel = channel
|
||||
self.navigationController?.pushViewController(vc, animated: true)
|
||||
}
|
||||
|
||||
@objc func writePost(_ barItem: UIBarButtonItem)
|
||||
func updateSearchResults(for searchController: UISearchController)
|
||||
{
|
||||
let vc = storyboard?.instantiateViewController(withIdentifier: "NewPostViewController") as! NewPostViewController
|
||||
|
||||
vc.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Post", style: .plain, target: vc, action: #selector(vc.newPost))
|
||||
vc.navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Close", style: .plain, target: vc, action: #selector(vc.closeView))
|
||||
|
||||
vc.myProtocol = self
|
||||
|
||||
let transition = CATransition()
|
||||
transition.duration = 0.5
|
||||
transition.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
|
||||
transition.type = CATransitionType.moveIn
|
||||
transition.subtype = CATransitionSubtype.fromTop
|
||||
navigationController?.view.layer.add(transition, forKey: nil)
|
||||
navigationController?.pushViewController(vc, animated: false)
|
||||
}
|
||||
|
||||
// for animating the banner
|
||||
var topConstraint: NSLayoutConstraint?
|
||||
|
||||
let bannerView: UIView = {
|
||||
let view = UIView()
|
||||
view.backgroundColor = .blue
|
||||
view.layer.cornerRadius = 25.0
|
||||
view.clipsToBounds = true
|
||||
return view
|
||||
}()
|
||||
|
||||
let statusLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.text = "-"
|
||||
label.textColor = .white
|
||||
label.textAlignment = .center
|
||||
return label
|
||||
}()
|
||||
|
||||
// MARK:- banner
|
||||
private func setUpBanner()
|
||||
{
|
||||
view.addSubview(bannerView)
|
||||
bannerView.addSubview(statusLabel)
|
||||
statusLabel.edgesToSuperview()
|
||||
|
||||
let tap = UITapGestureRecognizer(target: self, action: #selector(handleTap(sender:)))
|
||||
|
||||
bannerView.addGestureRecognizer(tap)
|
||||
topConstraint = NSLayoutConstraint(item: bannerView, attribute: .top, relatedBy: .equal, toItem: view.safeAreaLayoutGuide, attribute: .top, multiplier: 1, constant: -300)
|
||||
view.addConstraint(topConstraint!)
|
||||
|
||||
bannerView.edgesToSuperview(excluding: [.bottom, .top, .left], insets: .right(20), usingSafeArea: true)
|
||||
bannerView.height(50)
|
||||
bannerView.width(50)
|
||||
}
|
||||
|
||||
// when table is scrolling no deletion is availiable
|
||||
@objc func handleTap(sender: UITapGestureRecognizer? = nil) {
|
||||
let indexPath = IndexPath(row: 0, section: 0)
|
||||
self.tableView.scrollToRow(at: indexPath, at: .top, animated: true)
|
||||
// isBannerVisible = false
|
||||
// changeConstraint(isVisible: false)
|
||||
}
|
||||
|
||||
// animation for banner
|
||||
func changeConstraint(isVisible: Bool){
|
||||
topConstraint?.constant = isVisible ? 50 : -300
|
||||
|
||||
UIView.animate(withDuration: 0.5, delay: 0, options: .curveEaseOut, animations: {
|
||||
self.view.layoutIfNeeded()
|
||||
}) { (completed) in
|
||||
let filteredData = CompletionTree.getCompletion(tree: Model.hashTagTree!, word: searchController.searchBar.text?.lowercased() ?? "")
|
||||
|
||||
// Apply the filtered results to the search results table.
|
||||
if let resultsController = searchController.searchResultsController as? TagsSuggestionController {
|
||||
resultsController.suggestions = filteredData
|
||||
resultsController.tableView.reloadData()
|
||||
}
|
||||
}
|
||||
|
||||
var isBannerVisible: Bool = false
|
||||
|
||||
override func scrollViewDidScroll(_ scrollView: UIScrollView) {
|
||||
print(scrollView.contentOffset.y)
|
||||
if scrollView.contentOffset.y >= 50 && !isBannerVisible{
|
||||
isBannerVisible = true
|
||||
changeConstraint(isVisible: true)
|
||||
func willPresentSearchController(_ searchController: UISearchController) {
|
||||
searchController.searchResultsController?.view.isHidden = false;
|
||||
}
|
||||
|
||||
if isBannerVisible && scrollView.contentOffset.y == 0{
|
||||
isBannerVisible = false
|
||||
changeConstraint(isVisible: false)
|
||||
}
|
||||
func didPresentSearchController(_ searchController: UISearchController) {
|
||||
searchController.searchResultsController?.view.isHidden = false;
|
||||
}
|
||||
|
||||
func didDismissSearchController(_ searchController: UISearchController) {
|
||||
searchController.searchBar.text = ""
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,9 @@ struct PostCellData{
|
||||
|
||||
let markdownParser = MarkdownParser(font: UIFont.systemFont(ofSize: 16))
|
||||
markdownParser.enabledElements = .disabledAutomaticLink
|
||||
markdownParser.code.textBackgroundColor = #colorLiteral(red: 0.8039215803, green: 0.8039215803, blue: 0.8039215803, alpha: 1)
|
||||
markdownParser.code.font = UIFont(name: "Menlo", size: 16)
|
||||
markdownParser.code.textBackgroundColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)
|
||||
markdownParser.code.color = #colorLiteral(red: 0.2549019754, green: 0.2745098174, blue: 0.3019607961, alpha: 1)
|
||||
|
||||
return markdownParser.parse(markdown)
|
||||
}
|
||||
@ -27,12 +29,30 @@ struct PostCellData{
|
||||
|
||||
class NewsVC: UIViewController, UITableViewDelegate, UITableViewDataSource {
|
||||
|
||||
|
||||
var onChannelDidChange: ((([Int: Model.Users],[Model.Posts]))->())?
|
||||
|
||||
var onFullPost: ((HeaderType, Model.Posts)->())?
|
||||
|
||||
var dictionary: [Int: Model.Users] = [:] {
|
||||
didSet {
|
||||
|
||||
dataSourse = dataSourse.map {
|
||||
var copy = $0
|
||||
copy.user = dictionary[$0.authorId]
|
||||
return copy
|
||||
}
|
||||
|
||||
(viewController as? NewsController)?.tableView.reloadData()
|
||||
(viewController as? ProfileViewController)?.tableView.reloadData()
|
||||
}
|
||||
}
|
||||
|
||||
var currChannel : Model.Channels?
|
||||
|
||||
var dataSourse: [Model.Posts] = [] {
|
||||
didSet {
|
||||
cellDataSourse = []
|
||||
dataSourse.forEach { (item) in
|
||||
cellDataSourse.append(PostCellData(attributedData: PostCellData.create(with: item.body)))
|
||||
}
|
||||
cellDataSourse = dataSourse.map { PostCellData(attributedData: PostCellData.create(with: $0.body)) }
|
||||
}
|
||||
}
|
||||
|
||||
@ -48,11 +68,7 @@ class NewsVC: UIViewController, UITableViewDelegate, UITableViewDataSource{
|
||||
|
||||
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
|
||||
{
|
||||
tableView.deselectRow(at: indexPath, animated: true)
|
||||
let vc = viewController!.storyboard!.instantiateViewController(withIdentifier: fullPostControllerId) as! FullPostController
|
||||
vc.type = type
|
||||
vc.post = dataSourse[indexPath.row]
|
||||
viewController!.navigationController!.pushViewController(vc, animated: true)
|
||||
onFullPost?(type, dataSourse[indexPath.row])
|
||||
}
|
||||
|
||||
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
@ -72,9 +88,14 @@ class NewsVC: UIViewController, UITableViewDelegate, UITableViewDataSource{
|
||||
vc.idProfile = id
|
||||
self?.viewController!.navigationController!.pushViewController(vc, animated: true)
|
||||
}
|
||||
case .NONE:
|
||||
|
||||
cell.onAnonymousChannelDisplay = {
|
||||
[weak self] in
|
||||
(self?.viewController as? UpdateableWithChannel)?.updateChannel(on: Model.Channels(people: [], name: $0, id: 0, tags: [$0]))
|
||||
}
|
||||
default:
|
||||
cell.onUserDisplay = { (id) in
|
||||
print("tapped when profile is open already \(id)")
|
||||
print("tapped when profile is opened already \(id)")
|
||||
}
|
||||
}
|
||||
|
||||
@ -89,10 +110,37 @@ class NewsVC: UIViewController, UITableViewDelegate, UITableViewDataSource{
|
||||
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
|
||||
return 100.0
|
||||
}
|
||||
|
||||
var prevLast = -1
|
||||
|
||||
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath)
|
||||
{
|
||||
// pagination
|
||||
if indexPath.row == cellDataSourse.count - 1 && prevLast != indexPath.row
|
||||
{
|
||||
if let ch = currChannel, let id = ch.id, id != -1 {
|
||||
// check this!
|
||||
Model.getAnonymousChannel(by: ch, exclusiveFrom: dataSourse.last?.id) { [weak self] in
|
||||
self?.dataSourse.append(contentsOf: $0.posts)
|
||||
$0.users.forEach { self?.dictionary[$0.key] = $0.value }
|
||||
}
|
||||
|
||||
} else {
|
||||
// check this!
|
||||
Model.getLast(on: 10, from: dataSourse.last?.id )
|
||||
{ [weak self] in
|
||||
self?.dataSourse.append(contentsOf: $0.posts)
|
||||
$0.users.forEach { self?.dictionary[$0.key] = $0.value }
|
||||
}
|
||||
}
|
||||
|
||||
prevLast = indexPath.row
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum HeaderType {
|
||||
case NONE
|
||||
case NEWS
|
||||
case ANONYMOUS
|
||||
}
|
||||
|
@ -8,13 +8,15 @@
|
||||
|
||||
import UIKit
|
||||
import Cartography
|
||||
import MarkdownKit
|
||||
import TinyConstraints
|
||||
|
||||
class PostViewCell: UITableViewCell
|
||||
{
|
||||
|
||||
var onUserDisplay: ((Int)->())?
|
||||
|
||||
var onAnonymousChannelDisplay: ((String)->())?
|
||||
|
||||
let nameLabel: UIButton = {
|
||||
let button = UIButton()
|
||||
button.setTitleColor(.black, for: .normal)
|
||||
@ -40,6 +42,7 @@ class PostViewCell: UITableViewCell
|
||||
|
||||
let shareButton: UIButton = {
|
||||
let button = UIButton(type: UIButton.ButtonType.detailDisclosure)
|
||||
button.isHidden = true
|
||||
return button
|
||||
}()
|
||||
|
||||
@ -84,7 +87,7 @@ class PostViewCell: UITableViewCell
|
||||
nameLabel.setTitle("\(post.user?.firstName ?? "") \(post.user?.lastName ?? "")", for: .normal)
|
||||
nameLabel.addTarget(self, action: #selector(displayProfile), for: .touchUpInside)
|
||||
if let user = post.user{
|
||||
fullNameLabel.text = "\(user.firstName) \(user.middleName) \(user.lastName)"
|
||||
fullNameLabel.text = "\(user.faculty.name)"
|
||||
}
|
||||
else {
|
||||
fullNameLabel.text = "\(post.authorId)"
|
||||
@ -120,8 +123,8 @@ class PostViewCell: UITableViewCell
|
||||
for hash in hashtags {
|
||||
let button = UIButton()
|
||||
button.setTitle("#" + hash, for: .normal)
|
||||
//button.backgroundColor = #colorLiteral(red: 0.8039215803, green: 0.8039215803, blue: 0.8039215803, alpha: 1)
|
||||
//button.layer.cornerRadius = 10
|
||||
button.addTarget(self, action: #selector(setAnonymousChannel(on:)), for: .touchUpInside)
|
||||
// button.addGestureRecognizer(longPressRecognizer)
|
||||
button.titleLabel?.font = UIFont.monospacedDigitSystemFont(ofSize: 15, weight: .semibold)
|
||||
button.setTitleColor(#colorLiteral(red: 0, green: 0.4784313725, blue: 1, alpha: 1), for: .normal)
|
||||
buttons.append(button)
|
||||
@ -179,7 +182,13 @@ class PostViewCell: UITableViewCell
|
||||
}
|
||||
|
||||
@objc func displayProfile(){
|
||||
print("buttonTapped")
|
||||
onUserDisplay?(post!.authorId)
|
||||
if let id = post?.authorId {
|
||||
onUserDisplay?(id)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func setAnonymousChannel(on button: UIButton){
|
||||
print("\(button.titleLabel?.text ?? "nothing")")
|
||||
onAnonymousChannelDisplay?(String(button.titleLabel!.text!.dropFirst()))
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,106 @@
|
||||
//
|
||||
// TaggsSelectionViewController.swift
|
||||
// GDproject
|
||||
//
|
||||
// Created by cstore on 03/05/2019.
|
||||
// Copyright © 2019 drHSE. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import TaggerKit
|
||||
|
||||
protocol TagsReceiver: class {
|
||||
func receiveTags(tags: [String])
|
||||
}
|
||||
|
||||
class TaggsSelectionViewController: UIViewController {
|
||||
|
||||
@IBOutlet weak var addTagsTextField: TKTextField!
|
||||
|
||||
@IBOutlet weak var searchContainerView: UIView!
|
||||
|
||||
@IBOutlet weak var testContainer: UIView!
|
||||
|
||||
// We want the whole experience, let's create two TKCollectionViews
|
||||
let productTags = TKCollectionView()
|
||||
let allTags = TKCollectionView()
|
||||
|
||||
var currentTags: [String]?
|
||||
weak var receiver: TagsReceiver?
|
||||
|
||||
// MARK: - Lifecycle Methods
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
navigationItem.title = "Hashtags"
|
||||
addTagsTextField.delegate = self
|
||||
// Customisation example
|
||||
// testCollection.customFont = UIFont.boldSystemFont(ofSize: 14) // Custom font
|
||||
// testCollection.customCornerRadius = 14.0 // Corner radius of tags
|
||||
// testCollection.customSpacing = 20.0 // Spacing between cells
|
||||
// testCollection.customBackgroundColor = UIColor.red // Background of cells
|
||||
|
||||
|
||||
// These are the tags already added by the user, give an aray of strings to the collection
|
||||
if let tags = currentTags {
|
||||
productTags.tags = tags
|
||||
}
|
||||
// These are intended to be all the tags the user has added in the app, which are going to be filtered
|
||||
allTags.tags = CompletionTree.getCompletion(tree: Model.hashTagTree!, word: "")
|
||||
|
||||
/*
|
||||
We set this collection's action to .removeTag,
|
||||
becasue these are supposed to be the tags the user has already added
|
||||
*/
|
||||
productTags.action = .removeTag
|
||||
|
||||
|
||||
// Set the current controller as the delegate of both collections
|
||||
productTags.delegate = self
|
||||
allTags.delegate = self
|
||||
|
||||
// "testCollection" takes the tags sent by "searchCollection"
|
||||
allTags.receiver = productTags
|
||||
|
||||
// The tags in "searchCollection" are going to be added, so we set the action to addTag
|
||||
allTags.action = .addTag
|
||||
|
||||
|
||||
// Set the sender and receiver of the TextField
|
||||
addTagsTextField.sender = allTags
|
||||
addTagsTextField.receiver = productTags
|
||||
|
||||
add(productTags, toView: testContainer)
|
||||
add(allTags, toView: searchContainerView)
|
||||
}
|
||||
|
||||
override func viewWillDisappear(_ animated: Bool) {
|
||||
super.viewWillDisappear(animated)
|
||||
if let receiver = receiver{
|
||||
receiver.receiveTags(tags: productTags.tags)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
These methods come from UIViewController now conforming to TKCollectionViewDelegate,
|
||||
You use these to do whatever you want when a tag is added or removed (e.g. save to file, etc)
|
||||
*/
|
||||
override func tagIsBeingAdded(name: String?) {
|
||||
// Example: save testCollection.tags to UserDefault
|
||||
print("added \(name!)")
|
||||
}
|
||||
|
||||
override func tagIsBeingRemoved(name: String?) {
|
||||
print("removed \(name!)")
|
||||
}
|
||||
}
|
||||
|
||||
// textField deletage to close keyboard on return
|
||||
extension TaggsSelectionViewController: UITextFieldDelegate
|
||||
{
|
||||
func textFieldShouldReturn(_ textField: UITextField) -> Bool
|
||||
{
|
||||
self.view.endEditing(true)
|
||||
return false
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
//
|
||||
// AnonimousChannelController.swift
|
||||
// GDproject
|
||||
//
|
||||
// Created by cstore on 20/04/2019.
|
||||
// Copyright © 2019 drHSE. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class TagsSuggestionController: UITableViewController
|
||||
{
|
||||
weak var delegate: UpdateableWithChannel?
|
||||
|
||||
var suggestions = [String]()
|
||||
var channel: Model.Channels?
|
||||
|
||||
override func viewDidLoad()
|
||||
{
|
||||
super.viewDidLoad()
|
||||
if let tree = Model.hashTagTree {
|
||||
suggestions = CompletionTree.getCompletion(tree: tree, word: "")
|
||||
print(suggestions)
|
||||
}
|
||||
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
|
||||
tableView.reloadData()
|
||||
}
|
||||
|
||||
override func numberOfSections(in tableView: UITableView) -> Int {
|
||||
return 1
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
return suggestions.count
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
|
||||
{
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
|
||||
cell.textLabel?.text = suggestions[indexPath.row]
|
||||
|
||||
return cell
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
|
||||
{
|
||||
channel = Model.Channels(people: [], name: "\(self.suggestions[indexPath.row])", id: 0, tags: [self.suggestions[indexPath.row]])
|
||||
|
||||
delegate?.updateChannel(on: channel!)
|
||||
self.dismiss(animated: true)
|
||||
}
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
import UIKit
|
||||
|
||||
class TabbarCoordinator{
|
||||
var window: UIWindow!
|
||||
|
||||
func start(){
|
||||
let tabbar = UIStoryboard.tabBarController()
|
||||
window.rootViewController = tabbar
|
||||
}
|
||||
|
||||
init(window: UIWindow) {
|
||||
self.window = window
|
||||
}
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
//
|
||||
// ApplicationCoordinator.swift
|
||||
// RxSwift
|
||||
//
|
||||
// Created by cstore on 04/03/2019.
|
||||
// Copyright © 2019 drHSE. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import UIKit
|
||||
|
||||
|
||||
|
||||
fileprivate enum LaunchInstructor {
|
||||
case main, auth
|
||||
|
||||
static func configure(
|
||||
isAutorized: Bool = DataStorage.standard.isLoggedIn) -> LaunchInstructor {
|
||||
|
||||
if isAutorized{
|
||||
return .main
|
||||
} else {
|
||||
return .auth
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final class ApplicationCoordinator: BaseCoordinator{
|
||||
private var window: UIWindow!
|
||||
|
||||
init(window: UIWindow) {
|
||||
self.window = window
|
||||
}
|
||||
|
||||
private var instructor: LaunchInstructor {
|
||||
return LaunchInstructor.configure()
|
||||
}
|
||||
|
||||
override func start() {
|
||||
switch instructor {
|
||||
case .auth: runAuthFlow()
|
||||
case .main: runMainFlow()
|
||||
}
|
||||
}
|
||||
|
||||
private func runAuthFlow() {
|
||||
let coordinator = LogInCoordinator(window: window)
|
||||
coordinator.didEndFlow = { [weak self, weak coordinator] in
|
||||
self?.start()
|
||||
self?.removeDependency(coordinator)
|
||||
}
|
||||
addDependency(coordinator)
|
||||
coordinator.start()
|
||||
}
|
||||
|
||||
private func runMainFlow() {
|
||||
let storyboard = UIStoryboard(name: "Main", bundle: nil)
|
||||
let tabBar = storyboard.instantiateViewController(withIdentifier: "TabbarController") as! TabbarController
|
||||
let coordinator = TabBarCoordinator(tabbarView: tabBar, window: window!)
|
||||
|
||||
coordinator.didEndFlow = { [weak self, weak coordinator] in
|
||||
self?.start()
|
||||
self?.removeDependency(coordinator)
|
||||
}
|
||||
|
||||
addDependency(coordinator)
|
||||
coordinator.start()
|
||||
}
|
||||
}
|
47
GDproject/Controller/Coordinators/BaseCoordinator.swift
Normal file
47
GDproject/Controller/Coordinators/BaseCoordinator.swift
Normal file
@ -0,0 +1,47 @@
|
||||
//
|
||||
// BaseCoordinator.swift
|
||||
// RxSwift
|
||||
//
|
||||
// Created by cstore on 02/03/2019.
|
||||
// Copyright © 2019 drHSE. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import UIKit
|
||||
|
||||
protocol Coordinator: class {
|
||||
func start()
|
||||
}
|
||||
|
||||
class BaseCoordinator: Coordinator {
|
||||
|
||||
var childCoordinators: [Coordinator] = []
|
||||
|
||||
func start() {
|
||||
|
||||
}
|
||||
|
||||
// add only unique object
|
||||
func addDependency(_ coordinator: Coordinator) {
|
||||
guard !childCoordinators.contains(where: { $0 === coordinator }) else { return }
|
||||
childCoordinators.append(coordinator)
|
||||
}
|
||||
|
||||
func removeDependency(_ coordinator: Coordinator?) {
|
||||
guard
|
||||
childCoordinators.isEmpty == false,
|
||||
let coordinator = coordinator
|
||||
else { return }
|
||||
|
||||
// Clear child-coordinators recursively
|
||||
if let coordinator = coordinator as? BaseCoordinator, !coordinator.childCoordinators.isEmpty {
|
||||
coordinator.childCoordinators
|
||||
.filter({ $0 !== coordinator })
|
||||
.forEach({ coordinator.removeDependency($0) })
|
||||
}
|
||||
for (index, element) in childCoordinators.enumerated() where element === coordinator {
|
||||
childCoordinators.remove(at: index)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
139
GDproject/Controller/Coordinators/ChannelsCoordinator.swift
Normal file
139
GDproject/Controller/Coordinators/ChannelsCoordinator.swift
Normal file
@ -0,0 +1,139 @@
|
||||
//
|
||||
// ChannelsCoordinator.swift
|
||||
// RxSwift
|
||||
//
|
||||
// Created by cstore on 03/03/2019.
|
||||
// Copyright © 2019 drHSE. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import UIKit
|
||||
import Pulley
|
||||
|
||||
class ChannelsCoordinator: BaseCoordinator{
|
||||
let storyboard = UIStoryboard(name: "Main", bundle: nil)
|
||||
private weak var navigationController: UINavigationController?
|
||||
|
||||
init(nc: UINavigationController) {
|
||||
self.navigationController = nc
|
||||
navigationController?.navigationItem.largeTitleDisplayMode = .always
|
||||
}
|
||||
|
||||
override func start() {
|
||||
show()
|
||||
}
|
||||
|
||||
private func show() {
|
||||
|
||||
let channels = storyboard.instantiateViewController(withIdentifier: channelListControllerId) as! ChannelListController
|
||||
|
||||
channels.onChannelSelected = { [unowned self]
|
||||
(channel) in
|
||||
self.navigationController?.pushViewController(self.presentNewsController(with: channel), animated: true)
|
||||
}
|
||||
|
||||
channels.askForUpdates()
|
||||
|
||||
channels.onEditingModeBegins = { [unowned self] (channel, indexPath) in
|
||||
let vc = self.presentChannelController(with: channel)
|
||||
self.navigationController?.pushViewController(vc, animated: true)
|
||||
vc.tabBarController?.tabBar.isHidden = true
|
||||
}
|
||||
|
||||
let nc = presentNewsController()
|
||||
navigationController?.setViewControllers([channels, nc], animated: false)
|
||||
}
|
||||
|
||||
/// Function that presents channel controller
|
||||
///
|
||||
/// - Parameter channel: channel that needs to be displayed
|
||||
func presentChannelController(with channel: Model.Channels? = nil) -> ChannelViewController {
|
||||
let mainContentVC = storyboard.instantiateViewController(withIdentifier: channelViewControllerId) as! ChannelViewController
|
||||
|
||||
// to show preview we need to instantiate newsController but with different functionality
|
||||
mainContentVC.onShowingPreview = { [weak mainContentVC, unowned self] ch in
|
||||
let vc = self.presentNewsController(with: ch, previewMode: true)
|
||||
mainContentVC?.navigationController?.pushViewController(vc, animated: true)
|
||||
}
|
||||
|
||||
// to go for choosing hashtags
|
||||
mainContentVC.onChoosingHashTags = { [weak mainContentVC, unowned self] ch in
|
||||
let vc = self.storyboard.instantiateViewController(withIdentifier: taggsSelectionViewController) as! TaggsSelectionViewController
|
||||
|
||||
vc.currentTags = ch
|
||||
vc.receiver = mainContentVC
|
||||
|
||||
self.navigationController?.pushViewController(vc, animated: true)
|
||||
}
|
||||
|
||||
mainContentVC.onChoosingPeople = { [weak mainContentVC, unowned self] channel in
|
||||
let vc = self.storyboard.instantiateViewController(withIdentifier: addToChannelVCId) as! AddToChannelVC
|
||||
|
||||
vc.channel = channel
|
||||
vc.update = mainContentVC
|
||||
|
||||
self.navigationController?.pushViewController(vc, animated: true)
|
||||
}
|
||||
|
||||
mainContentVC.channel = channel
|
||||
return mainContentVC
|
||||
}
|
||||
|
||||
func presentNewsController(with channel: Model.Channels? = nil, previewMode: Bool = false) -> NewsController
|
||||
{
|
||||
let mainContentVC = storyboard.instantiateViewController(withIdentifier: newsController) as! NewsController
|
||||
mainContentVC.channel = channel
|
||||
|
||||
if !previewMode {
|
||||
mainContentVC.news.onFullPost = {
|
||||
[weak self] (type,post) in
|
||||
|
||||
let vc = self?.storyboard.instantiateViewController(withIdentifier: fullPostControllerId) as! FullPostController
|
||||
vc.type = type
|
||||
vc.post = post
|
||||
self?.navigationController!.pushViewController(vc, animated: true)
|
||||
}
|
||||
|
||||
mainContentVC.news.onChannelDidChange = {
|
||||
print("anon with \($0.0.count) users")
|
||||
}
|
||||
|
||||
mainContentVC.navigationItem.rightBarButtonItems = [UIBarButtonItem(barButtonSystemItem: .compose, target: self, action: #selector(writePost(_:)))
|
||||
]
|
||||
}
|
||||
|
||||
mainContentVC.changedChannelName = {
|
||||
[weak mainContentVC] (title) in mainContentVC?.navigationItem.title = title
|
||||
}
|
||||
|
||||
return mainContentVC
|
||||
}
|
||||
|
||||
@objc private func writePost(_ barItem: UIBarButtonItem)
|
||||
{
|
||||
let vc = storyboard.instantiateViewController(withIdentifier: "NewPostViewController") as! NewPostViewController
|
||||
|
||||
vc.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Post", style: .plain, target: vc, action: #selector(vc.newPost))
|
||||
vc.navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Close", style: .plain, target: vc, action: #selector(vc.closeView))
|
||||
|
||||
let transition = CATransition()
|
||||
transition.duration = 0.5
|
||||
transition.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
|
||||
transition.type = CATransitionType.moveIn
|
||||
transition.subtype = CATransitionSubtype.fromTop
|
||||
navigationController?.view.layer.add(transition, forKey: nil)
|
||||
navigationController?.pushViewController(vc, animated: false)
|
||||
|
||||
vc.moveBackToParentVC = {
|
||||
[weak self] in
|
||||
|
||||
let transition = CATransition()
|
||||
transition.duration = 0.5
|
||||
transition.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
|
||||
transition.type = CATransitionType.reveal
|
||||
transition.subtype = CATransitionSubtype.fromBottom
|
||||
self?.navigationController?.view.layer.add(transition, forKey: nil)
|
||||
self?.navigationController?.popViewController(animated: false)
|
||||
}
|
||||
}
|
||||
}
|
70
GDproject/Controller/Coordinators/LogInCoordinator.swift
Normal file
70
GDproject/Controller/Coordinators/LogInCoordinator.swift
Normal file
@ -0,0 +1,70 @@
|
||||
//
|
||||
// LogInCoordinator.swift
|
||||
// RxSwift
|
||||
//
|
||||
// Created by cstore on 01/03/2019.
|
||||
// Copyright © 2019 drHSE. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class LogInCoordinator: BaseCoordinator {
|
||||
|
||||
let storyboard = UIStoryboard(name: "Main", bundle: nil)
|
||||
|
||||
var didEndFlow: (()->())?
|
||||
var window: UIWindow!
|
||||
var navigationController: UINavigationController?
|
||||
|
||||
init(window: UIWindow) {
|
||||
self.window = window
|
||||
self.window?.rootViewController = UINavigationController()
|
||||
self.navigationController = window.rootViewController as? UINavigationController
|
||||
}
|
||||
|
||||
override func start(){
|
||||
let logInVC = LogInViewController()
|
||||
logInVC.authenticate = { [weak self, weak logInVC] (email) in
|
||||
|
||||
DataStorage.standard.setEmail(email: email)
|
||||
Model.authenticate(with: email) { [weak self]
|
||||
(authStatus) in
|
||||
|
||||
print(authStatus.userStatus)
|
||||
|
||||
if (authStatus.userStatus == "invalid") {
|
||||
logInVC?.presentAlertInvalidCode()
|
||||
}
|
||||
else if (authStatus.userStatus == "canRegister") { // register form
|
||||
self?.presentRegisterVC()
|
||||
} else { // validation code
|
||||
self?.presentViewControllerForCodeInput()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
navigationController?.pushViewController(logInVC, animated: false)
|
||||
}
|
||||
|
||||
func presentViewControllerForCodeInput()
|
||||
{
|
||||
let vc = storyboard.instantiateViewController(withIdentifier: "CodeViewController") as! CodeViewController
|
||||
self.navigationController?.pushViewController(vc, animated: true)
|
||||
vc.onSuccessLogIn = {
|
||||
[weak self] in self?.didEndFlow?()
|
||||
}
|
||||
}
|
||||
|
||||
func presentRegisterVC(){
|
||||
|
||||
let vc1 = storyboard.instantiateViewController(withIdentifier: "RegisterTableViewController") as! RegisterTableViewController
|
||||
|
||||
vc1.onRegistration = { [weak self] in
|
||||
self?.presentViewControllerForCodeInput()
|
||||
}
|
||||
|
||||
self.navigationController?.pushViewController(vc1, animated: true)
|
||||
}
|
||||
|
||||
|
||||
}
|
87
GDproject/Controller/Coordinators/MessagesCoordinator.swift
Normal file
87
GDproject/Controller/Coordinators/MessagesCoordinator.swift
Normal file
@ -0,0 +1,87 @@
|
||||
//
|
||||
// MessagesCoordinator.swift
|
||||
// GDproject
|
||||
//
|
||||
// Created by cstore on 01/05/2019.
|
||||
// Copyright © 2019 drHSE. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
import Foundation
|
||||
import UIKit
|
||||
|
||||
class MessagesCoordinator: BaseCoordinator {
|
||||
|
||||
var didEndSession: (()->())?
|
||||
|
||||
let storyboard = UIStoryboard(name: "Main", bundle: nil)
|
||||
private weak var navigationController: UINavigationController?
|
||||
|
||||
init(nc: UINavigationController) {
|
||||
self.navigationController = nc
|
||||
}
|
||||
|
||||
override func start() {
|
||||
show()
|
||||
}
|
||||
|
||||
private func show(){
|
||||
let vc = storyboard.instantiateViewController(withIdentifier: messagesViewControllerId) as! MessagesViewController
|
||||
|
||||
// choose person to write message to
|
||||
vc.onUserDisplayList = { [weak vc, unowned self] in
|
||||
|
||||
let newVC = self.storyboard.instantiateViewController(withIdentifier: peopleToWriteVC) as! PeopleToWriteViewController
|
||||
|
||||
newVC.whatToDoWithSelection = { [weak newVC, weak self] people in
|
||||
newVC?.navigationController?.popViewController(animated: true)
|
||||
|
||||
// detect is it a user or group dialog
|
||||
let count = people.count
|
||||
if count == 1 {
|
||||
|
||||
let user = people.first!.key
|
||||
let createdDialog = Model.Dialog.userChat(Model.UserChat(user: user))
|
||||
|
||||
let vc = DialogViewController()
|
||||
vc.users = Model.Channels.fullPeopleDict
|
||||
vc.dialog = createdDialog
|
||||
self?.navigationController?.pushViewController(vc, animated: true)
|
||||
|
||||
} else {
|
||||
var group = Model.Group(users: people, name: "Untitled", id: 0)
|
||||
group.users[DataStorage.standard.getUserId()] = Model.UserPermission(isAdmin: true)
|
||||
|
||||
Model.createGroupChat(from: group, completion: { [weak self] id in
|
||||
|
||||
let newVC1 = DialogViewController()
|
||||
group.id = id
|
||||
newVC1.users = Model.Channels.fullPeopleDict
|
||||
newVC1.dialog = Model.Dialog.groupChat(Model.GroupChat(group: group))
|
||||
self?.navigationController?.pushViewController(newVC1, animated: true)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
vc?.navigationController?.pushViewController(newVC, animated: true)
|
||||
}
|
||||
|
||||
vc.onDialogDisplay = { [weak vc] in
|
||||
|
||||
let newVC = DialogViewController()
|
||||
newVC.dialog = $0.dialog
|
||||
newVC.users = $0.users
|
||||
newVC.onUserDisplay = { [weak self] id in
|
||||
|
||||
let vc = self?.storyboard.instantiateViewController(withIdentifier: profileViewController) as! ProfileViewController
|
||||
vc.idProfile = id
|
||||
self?.navigationController!.pushViewController(vc, animated: true)
|
||||
|
||||
}
|
||||
|
||||
vc?.navigationController?.pushViewController(newVC, animated: true)
|
||||
}
|
||||
|
||||
navigationController?.viewControllers = [vc]
|
||||
}
|
||||
}
|
60
GDproject/Controller/Coordinators/ProfileCoordinator.swift
Normal file
60
GDproject/Controller/Coordinators/ProfileCoordinator.swift
Normal file
@ -0,0 +1,60 @@
|
||||
//
|
||||
// ProfileCoordinator.swift
|
||||
// RxSwift
|
||||
//
|
||||
// Created by cstore on 02/03/2019.
|
||||
// Copyright © 2019 drHSE. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import UIKit
|
||||
|
||||
class ProfileCoordinator: BaseCoordinator {
|
||||
|
||||
var didEndSession: (()->())?
|
||||
|
||||
private weak var navigationController: UINavigationController?
|
||||
|
||||
init(nc: UINavigationController) {
|
||||
self.navigationController = nc
|
||||
}
|
||||
|
||||
override func start() {
|
||||
show()
|
||||
}
|
||||
|
||||
private func show() {
|
||||
let storyboard = UIStoryboard(name: "Main", bundle: nil)
|
||||
let profile = storyboard.instantiateViewController(withIdentifier: "ProfileViewController") as! ProfileViewController
|
||||
|
||||
profile.logOut = {
|
||||
Model.logout() {
|
||||
[weak self] in
|
||||
|
||||
DataStorage.standard.setIsLoggedIn(value: false, with: 0)
|
||||
self?.didEndSession?()
|
||||
}
|
||||
}
|
||||
|
||||
profile.deleteAllSessions = {
|
||||
Model.deactivateAll() {
|
||||
[weak self] in
|
||||
|
||||
DataStorage.standard.setIsLoggedIn(value: false, with: 0)
|
||||
self?.didEndSession?()
|
||||
}
|
||||
}
|
||||
|
||||
profile.onSettings = { [weak self, weak storyboard, weak profile] in
|
||||
|
||||
let vc = storyboard?.instantiateViewController(withIdentifier: "RegisterTableViewController") as! RegisterTableViewController
|
||||
vc.delegate = profile
|
||||
vc.userActive = profile?.user
|
||||
|
||||
self?.navigationController?.pushViewController(vc, animated: true)
|
||||
}
|
||||
|
||||
|
||||
navigationController?.setViewControllers([profile], animated: false)
|
||||
}
|
||||
}
|
50
GDproject/Controller/Coordinators/TabbarController.swift
Normal file
50
GDproject/Controller/Coordinators/TabbarController.swift
Normal file
@ -0,0 +1,50 @@
|
||||
//
|
||||
// TabbarController.swift
|
||||
// RxSwift
|
||||
//
|
||||
// Created by cstore on 03/03/2019.
|
||||
// Copyright © 2019 drHSE. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import UIKit
|
||||
|
||||
protocol TabbarView: class {
|
||||
var onChannelsFlowSelect: ((UINavigationController) -> ())? { get set }
|
||||
var onProfileFlowSelect: ((UINavigationController) -> ())? { get set }
|
||||
var onMessagesFlowSelect: ((UINavigationController) -> ())? { get set }
|
||||
var onViewDidLoad: ((UINavigationController) -> ())? { get set }
|
||||
}
|
||||
|
||||
final class TabbarController: UITabBarController, UITabBarControllerDelegate, TabbarView {
|
||||
|
||||
|
||||
var onChannelsFlowSelect: ((UINavigationController) -> ())?
|
||||
var onProfileFlowSelect: ((UINavigationController) -> ())?
|
||||
var onMessagesFlowSelect: ((UINavigationController) -> ())?
|
||||
|
||||
var onViewDidLoad: ((UINavigationController) -> ())?
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
delegate = self
|
||||
if let controller = customizableViewControllers?.first as? UINavigationController {
|
||||
onViewDidLoad?(controller)
|
||||
}
|
||||
}
|
||||
|
||||
func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController)
|
||||
{
|
||||
|
||||
guard let controller = viewControllers?[selectedIndex] as? UINavigationController else { return }
|
||||
|
||||
if selectedIndex == 0 {
|
||||
onChannelsFlowSelect?(controller)
|
||||
} else if selectedIndex == 2 {
|
||||
onProfileFlowSelect?(controller)
|
||||
} else {
|
||||
onMessagesFlowSelect?(controller)
|
||||
}
|
||||
}
|
||||
}
|
68
GDproject/Controller/Coordinators/TabbarCoordinator.swift
Normal file
68
GDproject/Controller/Coordinators/TabbarCoordinator.swift
Normal file
@ -0,0 +1,68 @@
|
||||
//
|
||||
// TabBarCoordinator.swift
|
||||
// RxSwift
|
||||
//
|
||||
// Created by cstore on 02/03/2019.
|
||||
// Copyright © 2019 drHSE. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import UIKit
|
||||
|
||||
|
||||
class TabBarCoordinator: BaseCoordinator {
|
||||
|
||||
var didEndFlow: (()->())?
|
||||
|
||||
private let tabbarView: TabbarView
|
||||
private weak var window: UIWindow?
|
||||
|
||||
init(tabbarView: TabbarView, window: UIWindow) {
|
||||
self.tabbarView = tabbarView
|
||||
self.window = window
|
||||
}
|
||||
|
||||
override func start() {
|
||||
tabbarView.onViewDidLoad = runChannelsFlow()
|
||||
tabbarView.onChannelsFlowSelect = runChannelsFlow()
|
||||
tabbarView.onProfileFlowSelect = runProfileFlow()
|
||||
tabbarView.onMessagesFlowSelect = runMessagesFlow()
|
||||
window?.rootViewController = tabbarView as! TabbarController
|
||||
}
|
||||
|
||||
private func runChannelsFlow() -> ((UINavigationController) -> ())
|
||||
{
|
||||
return { [unowned self] navController in
|
||||
if navController.viewControllers.isEmpty == true {
|
||||
let channelCoordinator = ChannelsCoordinator(nc: navController)
|
||||
self.addDependency(channelCoordinator)
|
||||
channelCoordinator.start()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func runMessagesFlow() -> ((UINavigationController) -> ()){
|
||||
return { [unowned self] navController in
|
||||
if navController.viewControllers.isEmpty == true {
|
||||
let messagesCoordinator = MessagesCoordinator(nc: navController)
|
||||
self.addDependency(messagesCoordinator)
|
||||
messagesCoordinator.start()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func runProfileFlow() -> ((UINavigationController) -> ())
|
||||
{
|
||||
return { [unowned self] navController in
|
||||
if navController.viewControllers.isEmpty == true {
|
||||
let profileCoordinator = ProfileCoordinator(nc: navController)
|
||||
profileCoordinator.didEndSession = { [weak self, weak profileCoordinator] in
|
||||
self?.removeDependency(profileCoordinator)
|
||||
self?.didEndFlow?()
|
||||
}
|
||||
self.addDependency(profileCoordinator)
|
||||
profileCoordinator.start()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
144
GDproject/Controller/Log In/CodeViewController.swift
Normal file
144
GDproject/Controller/Log In/CodeViewController.swift
Normal file
@ -0,0 +1,144 @@
|
||||
//
|
||||
// CodeViewController.swift
|
||||
// GDproject
|
||||
//
|
||||
// Created by cstore on 10/05/2019.
|
||||
// Copyright © 2019 drHSE. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import TinyConstraints
|
||||
|
||||
class CodeViewController: UIViewController {
|
||||
|
||||
@IBOutlet weak var f1: UITextField!
|
||||
@IBOutlet weak var f2: UITextField!
|
||||
@IBOutlet weak var f3: UITextField!
|
||||
@IBOutlet weak var f4: UITextField!
|
||||
@IBOutlet weak var f5: UITextField!
|
||||
@IBOutlet weak var f6: UITextField!
|
||||
|
||||
var loading = UIActivityIndicatorView(style: .gray)
|
||||
|
||||
var onSuccessLogIn: (()->())?
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
setUpConstraint()
|
||||
|
||||
navigationItem.title = DataStorage.standard.getEmail()
|
||||
|
||||
f1.addTarget(self, action: #selector(textFiledDidChange(textField:)), for: .editingChanged)
|
||||
f2.addTarget(self, action: #selector(textFiledDidChange(textField:)), for: .editingChanged)
|
||||
f3.addTarget(self, action: #selector(textFiledDidChange(textField:)), for: .editingChanged)
|
||||
f4.addTarget(self, action: #selector(textFiledDidChange(textField:)), for: .editingChanged)
|
||||
f5.addTarget(self, action: #selector(textFiledDidChange(textField:)), for: .editingChanged)
|
||||
f6.addTarget(self, action: #selector(textFiledDidChange(textField:)), for: .editingChanged)
|
||||
}
|
||||
|
||||
override func viewWillDisappear(_ animated: Bool) {
|
||||
super.viewWillDisappear(animated)
|
||||
|
||||
loading.stopAnimating()
|
||||
}
|
||||
|
||||
override func viewWillAppear(_ animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
|
||||
f1.becomeFirstResponder()
|
||||
}
|
||||
|
||||
@objc func textFiledDidChange(textField: UITextField) {
|
||||
let text = textField.text
|
||||
|
||||
// only 1 char
|
||||
if text?.utf16.count == 1 {
|
||||
switch textField {
|
||||
case f1:
|
||||
f2.becomeFirstResponder()
|
||||
case f2:
|
||||
f3.becomeFirstResponder()
|
||||
case f3:
|
||||
f4.becomeFirstResponder()
|
||||
case f4:
|
||||
f5.becomeFirstResponder()
|
||||
case f5:
|
||||
f6.becomeFirstResponder()
|
||||
case f6:
|
||||
f6.resignFirstResponder()
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func presentAlertInvalidData(with text: String)
|
||||
{
|
||||
let alert = UIAlertController(title: "Invalid code", message: text, preferredStyle: .alert)
|
||||
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
|
||||
self.present(alert, animated: true, completion: nil)
|
||||
|
||||
loading.stopAnimating()
|
||||
}
|
||||
|
||||
@IBOutlet weak var bottomConstraint: NSLayoutConstraint!
|
||||
|
||||
@IBAction func whereToGoNext(_ sender: UIButton)
|
||||
{
|
||||
guard let f1t = f1.text, let f2t = f2.text, let f3t = f3.text, let f4t = f4.text, let f5t = f5.text, let f6t = f6.text else {
|
||||
presentAlertInvalidData(with: "Some fields are missing");
|
||||
return
|
||||
}
|
||||
|
||||
if f1t.isEmpty || f2t.isEmpty || f3t.isEmpty || f4t.isEmpty || f5t.isEmpty || f6t.isEmpty {
|
||||
presentAlertInvalidData(with: "Some fields are missing");
|
||||
return
|
||||
}
|
||||
|
||||
let code = "\(f1.text!)\(f2.text!)\(f3.text!)\(f4.text!)\(f5.text!)\(f6.text!)"
|
||||
if let codeToInt = Int(code)
|
||||
{
|
||||
loading.startAnimating()
|
||||
Model.verify(with: codeToInt) { [weak self] in
|
||||
// if everything is okay we can authemticicate
|
||||
if !$0 {
|
||||
self?.presentAlertInvalidData(with: "Wrong code. Try again!")
|
||||
self?.loading.stopAnimating()
|
||||
return
|
||||
} else {
|
||||
// Model.authemticiateMe
|
||||
Model.authenticateMe { [weak self] (res) in
|
||||
if res {
|
||||
self?.onSuccessLogIn?()
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func setUpConstraint()
|
||||
{
|
||||
self.view.addSubview(loading)
|
||||
loading.centerInSuperview()
|
||||
// for keyboard notifications
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardNotifications), name: UIResponder.keyboardWillShowNotification, object: nil)
|
||||
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardNotifications), name: UIResponder.keyboardWillHideNotification, object: nil)
|
||||
}
|
||||
|
||||
@objc func handleKeyboardNotifications(notification: NSNotification){
|
||||
if let userInfo = notification.userInfo {
|
||||
// UIKeyboardFrameEndUserInfoKey
|
||||
let keyBoardFrame = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
|
||||
bottomConstraint.constant = notification.name == UIResponder.keyboardWillShowNotification ? keyBoardFrame.height - self.view.safeAreaInsets.bottom : 0
|
||||
|
||||
UIView.animate(withDuration: 0, delay: 0, options: .curveEaseOut, animations: {
|
||||
self.view.layoutIfNeeded()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
}
|
88
GDproject/Controller/Log In/FacultyTableViewController.swift
Normal file
88
GDproject/Controller/Log In/FacultyTableViewController.swift
Normal file
@ -0,0 +1,88 @@
|
||||
//
|
||||
// FacultyTableViewController.swift
|
||||
// GDproject
|
||||
//
|
||||
// Created by cstore on 10/05/2019.
|
||||
// Copyright © 2019 drHSE. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
protocol ChosenFactulty: class {
|
||||
func onChooseFaculty(faculty: Model.Faculty)
|
||||
}
|
||||
|
||||
class FacultyTableViewController: UITableViewController {
|
||||
|
||||
weak var delegate: ChosenFactulty?
|
||||
|
||||
var currentFaculties: [Model.Faculty] = []{
|
||||
didSet {
|
||||
tableView.reloadData()
|
||||
}
|
||||
}
|
||||
|
||||
var isFiltering: Bool {
|
||||
return searchController.isActive && !searchBarIsEmpty()
|
||||
}
|
||||
|
||||
func searchBarIsEmpty() -> Bool {
|
||||
return searchController.searchBar.text?.isEmpty ?? true
|
||||
}
|
||||
|
||||
var searchController = UISearchController(searchResultsController: nil)
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
self.navigationItem.title = "Faculties"
|
||||
self.navigationItem.searchController = searchController
|
||||
self.navigationItem.hidesSearchBarWhenScrolling = false
|
||||
searchController.obscuresBackgroundDuringPresentation = false
|
||||
|
||||
setUpTimer()
|
||||
}
|
||||
|
||||
func setUpTimer(){
|
||||
Timer.scheduledTimer(withTimeInterval: 2, repeats: true) { (timer) in
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
|
||||
if self!.isFiltering {
|
||||
Model.searchFaculty(string: (self?.searchController.searchBar.text)!) { [weak self] in
|
||||
self?.currentFaculties = $0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Table view data source
|
||||
|
||||
override func numberOfSections(in tableView: UITableView) -> Int {
|
||||
return 1
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
return currentFaculties.count
|
||||
}
|
||||
|
||||
|
||||
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
|
||||
{
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "F", for: indexPath)
|
||||
|
||||
cell.textLabel?.text = currentFaculties[indexPath.row].name
|
||||
cell.detailTextLabel?.text = currentFaculties[indexPath.row].campusName
|
||||
cell.selectionStyle = .none
|
||||
|
||||
return cell
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
delegate?.onChooseFaculty(faculty: currentFaculties[indexPath.row])
|
||||
searchController.dismiss(animated: true, completion: nil)
|
||||
self.navigationController?.popViewController(animated: true)
|
||||
}
|
||||
|
||||
}
|
23
GDproject/Controller/Log In/InititalsViewCell.swift
Normal file
23
GDproject/Controller/Log In/InititalsViewCell.swift
Normal file
@ -0,0 +1,23 @@
|
||||
//
|
||||
// InititalsViewCell.swift
|
||||
// GDproject
|
||||
//
|
||||
// Created by cstore on 10/05/2019.
|
||||
// Copyright © 2019 drHSE. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class InititalsViewCell: UITableViewCell {
|
||||
|
||||
@IBOutlet weak var initialsTextField: UITextField!
|
||||
|
||||
override func awakeFromNib() {
|
||||
super.awakeFromNib()
|
||||
// Initialization code
|
||||
}
|
||||
|
||||
func fill(with name: String){
|
||||
initialsTextField.text = name
|
||||
}
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
//
|
||||
// LogInCoordinator.swift
|
||||
// GDproject
|
||||
//
|
||||
// Created by cstore on 23/02/2019.
|
||||
// Copyright © 2019 drHSE. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class LogInCoordinator{
|
||||
|
||||
private weak var navigationController: UINavigationController?
|
||||
private var window: UIWindow!
|
||||
// MARK:- Init
|
||||
init(navigationController: UINavigationController, window: UIWindow) {
|
||||
self.navigationController = navigationController
|
||||
self.window = window
|
||||
}
|
||||
|
||||
func start(){
|
||||
showLogInPage()
|
||||
}
|
||||
|
||||
// MARK: - Private implementation
|
||||
// private func showStatusPage(){
|
||||
// let controller = TabbarCoordinator(window: window)
|
||||
// controller.start()
|
||||
// }
|
||||
|
||||
private func showLogInPage(){
|
||||
let controller = UIStoryboard.makeLogIn()
|
||||
|
||||
controller.onLogIn = {
|
||||
(id) in Model.authenticate(with: id) {
|
||||
(res) in
|
||||
|
||||
if (res) { DataStorage.standard.setUserKey(with: id) }
|
||||
else { DataStorage.standard.setUserKey(with: 0) }
|
||||
|
||||
controller.authenticateSucceeded = res
|
||||
}
|
||||
}
|
||||
|
||||
navigationController?.pushViewController(controller, animated: false)
|
||||
}
|
||||
|
||||
}
|
@ -1,128 +1,135 @@
|
||||
//
|
||||
// LogInViewController.swift
|
||||
// NewsFeed
|
||||
// RxSwift
|
||||
//
|
||||
// Created by cstore on 20/01/2019.
|
||||
// Created by cstore on 01/03/2019.
|
||||
// Copyright © 2019 drHSE. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import TinyConstraints
|
||||
import ReactiveSwift
|
||||
import ReactiveCocoa
|
||||
import Result
|
||||
|
||||
class LogInViewController: UIViewController {
|
||||
|
||||
@IBOutlet weak var mailTextField: UITextField!
|
||||
var loading = UIActivityIndicatorView(style: .gray)
|
||||
|
||||
@IBOutlet weak var indicatorView: UIActivityIndicatorView!
|
||||
var authenticate: ((String)->())?
|
||||
|
||||
var onLogIn: ((Int)->())?
|
||||
|
||||
var authenticateSucceeded: Bool? {
|
||||
didSet {
|
||||
if !authenticateSucceeded! {
|
||||
indicatorView.stopAnimating()
|
||||
indicatorView.isHidden = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static let titleColor = UIColor(red: 0, green: 137/255, blue: 249/255, alpha: 0.5)
|
||||
|
||||
var bottomConstraint: NSLayoutConstraint?
|
||||
|
||||
let logInButton: UIButton = {
|
||||
let button = UIButton(type: .system)
|
||||
button.setTitle("Log In", for: .normal)
|
||||
button.setTitleColor(titleColor, for: .normal)
|
||||
button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 16)
|
||||
button.isEnabled = false
|
||||
button.addTarget(self, action: #selector(activateLogInProcess), for: .touchUpInside)
|
||||
return button
|
||||
}()
|
||||
|
||||
let keyboardBar: UIView = {
|
||||
let view = UIView()
|
||||
view.backgroundColor = .white
|
||||
return view
|
||||
}()
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
setUpView()
|
||||
configureTapgesture()
|
||||
}
|
||||
|
||||
override func viewWillAppear(_ animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
func presentAlertInvalidCode()
|
||||
{
|
||||
let alert = UIAlertController(title: "Invalid email", message: "Try again. Use @hse.ru mail.", preferredStyle: .alert)
|
||||
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
|
||||
self.present(alert, animated: true, completion: nil)
|
||||
mailTextField.text = ""
|
||||
loading.stopAnimating()
|
||||
}
|
||||
|
||||
override func viewWillDisappear(_ animated: Bool) {
|
||||
super.viewWillDisappear(animated)
|
||||
|
||||
loading.stopAnimating()
|
||||
}
|
||||
|
||||
private func configureTapgesture(){
|
||||
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTap))
|
||||
view.addGestureRecognizer(tapGesture)
|
||||
}
|
||||
let logInLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.text = "Log In"
|
||||
label.textColor = .black
|
||||
label.font = UIFont.boldSystemFont(ofSize: 34)
|
||||
return label
|
||||
}()
|
||||
|
||||
let mailTextField: UITextField = {
|
||||
let textField = UITextField()
|
||||
textField.backgroundColor = #colorLiteral(red: 0.937254902, green: 0.937254902, blue: 0.9568627451, alpha: 1)
|
||||
textField.placeholder = "Mail"
|
||||
textField.borderStyle = .roundedRect
|
||||
textField.textColor = .black
|
||||
textField.autocorrectionType = UITextAutocorrectionType.no
|
||||
textField.autocapitalizationType = UITextAutocapitalizationType.none
|
||||
textField.clearButtonMode = .always
|
||||
return textField
|
||||
}()
|
||||
|
||||
let logInButton: UIButton = {
|
||||
let button = UIButton(type: .system)
|
||||
button.setTitle("Log In", for: .normal)
|
||||
button.setTitleColor(blueSystemColor, for: .normal)
|
||||
button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 16)
|
||||
button.addTarget(self, action: #selector(handleTap), for: .touchUpInside)
|
||||
button.isEnabled = false
|
||||
return button
|
||||
}()
|
||||
|
||||
@objc func handleTap(){
|
||||
view.endEditing(true)
|
||||
loading.startAnimating()
|
||||
authenticate?(mailTextField.text!)
|
||||
}
|
||||
|
||||
@objc func activateLogInProcess(){
|
||||
if logInButton.isEnabled {
|
||||
// MARK:- when log in is succeeded do I need to go there?
|
||||
if let id = Int(mailTextField.text!){
|
||||
indicatorView.isHidden = false
|
||||
indicatorView.startAnimating()
|
||||
onLogIn?(id)
|
||||
view.endEditing(true)
|
||||
} else {
|
||||
logInButton.isEnabled = false
|
||||
logInButton.setTitleColor(LogInViewController.titleColor.withAlphaComponent(0.5), for: .normal)
|
||||
}
|
||||
}
|
||||
}
|
||||
private lazy var keyboardBar = UIView()
|
||||
private lazy var contentView = UIView()
|
||||
private var bottomConstraint: NSLayoutConstraint?
|
||||
|
||||
func setUpView(){
|
||||
indicatorView.isHidden = true
|
||||
mailTextField.delegate = self
|
||||
view.addSubview(keyboardBar)
|
||||
// logIn stack with textField and label
|
||||
view.addSubview(contentView)
|
||||
view.addSubview(loading)
|
||||
|
||||
view.addConstraintsWithFormat(format: "H:|[v0]|", views: keyboardBar)
|
||||
view.addConstraintsWithFormat(format: "V:[v0(50)]", views: keyboardBar)
|
||||
loading.centerInSuperview()
|
||||
|
||||
setUpBarComponents()
|
||||
|
||||
configureKeyboardBehavior()
|
||||
contentView.edgesToSuperview(excluding: .bottom, insets: .left(16) + .right(16) + .top(80), usingSafeArea: true)
|
||||
let views = [logInLabel, mailTextField]
|
||||
contentView.stack(views, axis: .vertical, spacing: 10)
|
||||
}
|
||||
|
||||
func configureKeyboardBehavior(){
|
||||
func configureKeyboard(){
|
||||
|
||||
mailTextField.keyboardType = .emailAddress
|
||||
// configure keyboardBar setUp
|
||||
view.addSubview(keyboardBar)
|
||||
keyboardBar.height(50)
|
||||
keyboardBar.edgesToSuperview(excluding: [.top,.bottom])
|
||||
bottomConstraint = NSLayoutConstraint(item: keyboardBar, attribute: .bottom, relatedBy: .equal, toItem: view.safeAreaLayoutGuide, attribute: .bottom, multiplier: 1, constant: 0)
|
||||
view.addConstraint(bottomConstraint!)
|
||||
|
||||
// configure keyboardBar components
|
||||
keyboardBar.addSubview(logInButton)
|
||||
logInButton.height(50)
|
||||
logInButton.rightToSuperview(view.rightAnchor, offset: -16, relation: .equal, isActive: true)
|
||||
|
||||
}
|
||||
|
||||
func logicOfLogInInputValidation() -> ((String?)->()) {
|
||||
|
||||
let logic: ((String?)->()) = { [weak self] (someText) in
|
||||
if let text = someText, !text.isEmpty, text.contains("@") {
|
||||
self?.logInButton.isEnabled = true
|
||||
} else {
|
||||
self?.logInButton.isEnabled = false
|
||||
}
|
||||
}
|
||||
|
||||
return logic
|
||||
}
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
self.view.backgroundColor = .white
|
||||
setUpView()
|
||||
configureKeyboard()
|
||||
|
||||
let mailFieldValuesSignal: Signal<String, NoError> = mailTextField.reactive.continuousTextValues
|
||||
|
||||
mailFieldValuesSignal.observeValues(logicOfLogInInputValidation())
|
||||
|
||||
// for keyboard notifications
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardNotifications), name: UIResponder.keyboardWillShowNotification, object: nil)
|
||||
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardNotifications), name: UIResponder.keyboardWillHideNotification, object: nil)
|
||||
|
||||
// for log in button notifications
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(inputDidChanged), name: UITextField.textDidChangeNotification, object: mailTextField)
|
||||
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(inputDidChanged), name: UITextField.textDidBeginEditingNotification, object: mailTextField)
|
||||
}
|
||||
|
||||
@objc func inputDidChanged(notification: NSNotification){
|
||||
if mailTextField.text?.isEmpty ?? true
|
||||
{
|
||||
logInButton.isEnabled = false
|
||||
logInButton.setTitleColor(LogInViewController.titleColor.withAlphaComponent(0.5), for: .normal)
|
||||
}
|
||||
else
|
||||
{
|
||||
logInButton.isEnabled = true
|
||||
logInButton.setTitleColor(LogInViewController.titleColor.withAlphaComponent(1), for: .normal)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func handleKeyboardNotifications(notification: NSNotification){
|
||||
if let userInfo = notification.userInfo{
|
||||
@ -136,18 +143,13 @@ class LogInViewController: UIViewController {
|
||||
}
|
||||
}
|
||||
|
||||
func setUpBarComponents(){
|
||||
keyboardBar.addSubview(logInButton)
|
||||
keyboardBar.addConstraintsWithFormat(format: "H:[v0(60)]-16-|", views: logInButton)
|
||||
keyboardBar.addConstraintsWithFormat(format: "V:|[v0]|", views: logInButton)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extension LogInViewController: UITextFieldDelegate{
|
||||
func textFieldShouldReturn(_ textField: UITextField) -> Bool
|
||||
{
|
||||
textField.resignFirstResponder()
|
||||
return true
|
||||
extension UIButton {
|
||||
override open var isEnabled: Bool {
|
||||
didSet {
|
||||
let color = isEnabled ? self.titleLabel?.textColor.withAlphaComponent(1) : self.titleLabel?.textColor.withAlphaComponent(0.5)
|
||||
self.setTitleColor(color, for: .normal)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
198
GDproject/Controller/Log In/RegisterTableViewController.swift
Normal file
198
GDproject/Controller/Log In/RegisterTableViewController.swift
Normal file
@ -0,0 +1,198 @@
|
||||
//
|
||||
// RegisterTableViewController.swift
|
||||
// GDproject
|
||||
//
|
||||
// Created by cstore on 10/05/2019.
|
||||
// Copyright © 2019 drHSE. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class RegisterTableViewController: UITableViewController, ChosenFactulty
|
||||
{
|
||||
|
||||
func presentAlertInvalidData(message: String)
|
||||
{
|
||||
let alert = UIAlertController(title: "Invalid data", message: message, preferredStyle: .alert)
|
||||
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
|
||||
self.present(alert, animated: true, completion: nil)
|
||||
}
|
||||
|
||||
func onChooseFaculty(faculty: Model.Faculty) {
|
||||
self.faculty = faculty
|
||||
tableView.reloadData()
|
||||
}
|
||||
|
||||
weak var delegate: UpdateUser?
|
||||
|
||||
var onRegistration: (()->())?
|
||||
|
||||
var faculty: Model.Faculty?
|
||||
var user: Model.NewRegistration = Model.NewRegistration(email: DataStorage.standard.getEmail()!, firstName: nil, middleName: nil, lastName: nil, faculty: nil)
|
||||
|
||||
var userActive: Model.Users? {
|
||||
didSet {
|
||||
if let userA = userActive {
|
||||
user.firstName = userA.firstName
|
||||
user.middleName = userA.middleName
|
||||
user.lastName = userA.lastName
|
||||
|
||||
faculty = userA.faculty
|
||||
self.updateUserIfCan = true
|
||||
tableView.reloadData()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var updateUserIfCan: Bool = false
|
||||
|
||||
override func viewDidLoad()
|
||||
{
|
||||
super.viewDidLoad()
|
||||
|
||||
navigationItem.largeTitleDisplayMode = .never
|
||||
tableView.keyboardDismissMode = .interactive
|
||||
navigationItem.title = user.email
|
||||
navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(endRegistration))
|
||||
}
|
||||
|
||||
|
||||
@objc func endRegistration()
|
||||
{
|
||||
let fieldsMissing = "Some fields are missing. Add more information"
|
||||
updateUser()
|
||||
guard let faculty = faculty else { presentAlertInvalidData(message: fieldsMissing); return }
|
||||
|
||||
user.faculty = faculty.url
|
||||
|
||||
guard let name = user.firstName else { presentAlertInvalidData(message: fieldsMissing); return }
|
||||
guard let middle = user.middleName else { presentAlertInvalidData(message: fieldsMissing); return }
|
||||
guard let last = user.lastName else { presentAlertInvalidData(message: fieldsMissing); return }
|
||||
|
||||
if updateUserIfCan {
|
||||
guard let delegate = delegate else { return }
|
||||
guard var userA = userActive else { return }
|
||||
|
||||
// updating current
|
||||
userA.firstName = name
|
||||
userA.faculty = faculty
|
||||
userA.middleName = middle
|
||||
userA.lastName = last
|
||||
|
||||
Model.userUpdate(with: user) { [weak self] in
|
||||
|
||||
if $0 {
|
||||
delegate.updateUserObj(with: userA)
|
||||
self?.navigationController?.popViewController(animated: true)
|
||||
} else {
|
||||
self?.presentAlertInvalidData(message: "Something went wrong! Try again")
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
|
||||
Model.register(object: user)
|
||||
{ [weak self] in
|
||||
self?.onRegistration?()
|
||||
}
|
||||
}
|
||||
}
|
||||
// MARK: - Table view data source
|
||||
|
||||
override func numberOfSections(in tableView: UITableView) -> Int {
|
||||
return 2
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
|
||||
switch section {
|
||||
case 0:
|
||||
return 3
|
||||
default:
|
||||
if let _ = faculty {
|
||||
return 2
|
||||
} else {
|
||||
return 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String?
|
||||
{
|
||||
switch section {
|
||||
case 0:
|
||||
return "Initials"
|
||||
default:
|
||||
return "Faculty"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
|
||||
{
|
||||
switch indexPath.section {
|
||||
case 0:
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "nameCell", for: indexPath) as! InititalsViewCell
|
||||
switch indexPath.row{
|
||||
case 0:
|
||||
if let name = user.firstName {
|
||||
cell.fill(with: name)
|
||||
} else {
|
||||
cell.initialsTextField.placeholder = "First name"
|
||||
}
|
||||
case 1:
|
||||
if let name = user.middleName {
|
||||
cell.fill(with: name)
|
||||
} else {
|
||||
cell.initialsTextField.placeholder = "Middle name"
|
||||
}
|
||||
default:
|
||||
if let name = user.lastName {
|
||||
cell.fill(with: name)
|
||||
} else {
|
||||
cell.initialsTextField.placeholder = "Last name"
|
||||
}
|
||||
}
|
||||
cell.selectionStyle = .none
|
||||
return cell
|
||||
default:
|
||||
switch indexPath.row {
|
||||
case 0:
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "cell111", for: indexPath)
|
||||
cell.selectionStyle = .none
|
||||
return cell
|
||||
default:
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "facultyCell", for: indexPath)
|
||||
cell.textLabel?.text = faculty!.name
|
||||
cell.detailTextLabel?.text = faculty!.campusName
|
||||
cell.selectionStyle = .none
|
||||
return cell
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
if indexPath.section == 1 && indexPath.row == 0 {
|
||||
|
||||
updateUser()
|
||||
|
||||
let vc = storyboard?.instantiateViewController(withIdentifier: "FacultyTableViewController") as! FacultyTableViewController
|
||||
|
||||
vc.delegate = self
|
||||
|
||||
self.navigationController?.pushViewController(vc, animated: true)
|
||||
}
|
||||
}
|
||||
|
||||
func updateUser(){
|
||||
guard let cell = tableView.cellForRow(at: IndexPath(row: 0, section: 0)) as? InititalsViewCell else {return}
|
||||
guard let cell1 = tableView.cellForRow(at: IndexPath(row: 1, section: 0)) as? InititalsViewCell else {return}
|
||||
guard let cell2 = tableView.cellForRow(at: IndexPath(row: 2, section: 0)) as? InititalsViewCell else {return}
|
||||
|
||||
user.firstName = cell.initialsTextField.text!
|
||||
user.middleName = cell1.initialsTextField.text!
|
||||
user.lastName = cell2.initialsTextField.text!
|
||||
}
|
||||
|
||||
}
|
308
GDproject/Controller/Messages/ChatInfoViewController.swift
Normal file
308
GDproject/Controller/Messages/ChatInfoViewController.swift
Normal file
@ -0,0 +1,308 @@
|
||||
//
|
||||
// ChatInfoViewController.swift
|
||||
// GDproject
|
||||
//
|
||||
// Created by cstore on 02/05/2019.
|
||||
// Copyright © 2019 drHSE. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
/// Class for displaying chat info
|
||||
///
|
||||
class ChatInfoViewController: UITableViewController {
|
||||
|
||||
enum PersonStatus{
|
||||
case admin
|
||||
case ordinary
|
||||
}
|
||||
|
||||
weak var delegate: UpdatableGroup?
|
||||
|
||||
var groupChat: Model.Group? {
|
||||
didSet{
|
||||
if let groupChat = groupChat {
|
||||
usersArray = groupChat.users.map { $0.key }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var usersArray: [Int] = [] {
|
||||
didSet {
|
||||
tableView.reloadData()
|
||||
}
|
||||
}
|
||||
|
||||
var users: [Int: Model.Users] = [:]
|
||||
|
||||
func canIEditThisChat() -> PersonStatus
|
||||
{
|
||||
let myId = UserDefaults.standard.integer(forKey: UserDefaultsKeys.id.rawValue)
|
||||
|
||||
if let groupChatUserPermission = groupChat?.users[myId]?.isAdmin {
|
||||
return groupChatUserPermission ? .admin : .ordinary
|
||||
}
|
||||
|
||||
return .ordinary
|
||||
}
|
||||
|
||||
var myPermissions: PersonStatus = .ordinary
|
||||
|
||||
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
|
||||
myPermissions = canIEditThisChat()
|
||||
tableView.reloadData()
|
||||
|
||||
switch myPermissions {
|
||||
case .admin:
|
||||
navigationItem.rightBarButtonItem = self.editButtonItem
|
||||
default:
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Table view data source
|
||||
|
||||
override func numberOfSections(in tableView: UITableView) -> Int {
|
||||
return 3
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
switch section {
|
||||
case 0:
|
||||
return 1
|
||||
case 1:
|
||||
return 1
|
||||
default:
|
||||
return usersArray.count + (myPermissions == .ordinary ? 0 : 1)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
|
||||
{
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
|
||||
|
||||
if indexPath.row == 0 {
|
||||
switch indexPath.section {
|
||||
case 0:
|
||||
cell.textLabel?.text = groupChat!.name
|
||||
cell.selectionStyle = .none
|
||||
return cell
|
||||
case 1:
|
||||
cell.textLabel?.text = "Leave chat"
|
||||
cell.textLabel?.textColor = #colorLiteral(red: 1, green: 0.1491314173, blue: 0, alpha: 1)
|
||||
cell.selectionStyle = .none
|
||||
return cell
|
||||
default:
|
||||
switch myPermissions{
|
||||
case .admin:
|
||||
cell.textLabel?.text = "Add participants"
|
||||
cell.accessoryType = .disclosureIndicator
|
||||
case .ordinary:
|
||||
cell.textLabel?.text = name(for: users[usersArray[indexPath.row]])
|
||||
}
|
||||
cell.selectionStyle = .none
|
||||
return cell
|
||||
}
|
||||
}
|
||||
|
||||
switch myPermissions{
|
||||
case .admin:
|
||||
cell.textLabel?.text = name(for: users[usersArray[indexPath.row-1]])
|
||||
case .ordinary:
|
||||
cell.textLabel?.text = name(for: users[usersArray[indexPath.row]])
|
||||
}
|
||||
cell.selectionStyle = .none
|
||||
return cell
|
||||
}
|
||||
|
||||
private func name(for user: Model.Users?) -> String {
|
||||
if let user = user, let perm = groupChat?.users[user.id]?.isAdmin {
|
||||
if perm {
|
||||
return "🤴🏻 \(user.fullName())"
|
||||
}
|
||||
return "👤 \(user.fullName())"
|
||||
}
|
||||
|
||||
return "left"
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String?
|
||||
{
|
||||
switch section {
|
||||
case 0:
|
||||
return "Title"
|
||||
case 1:
|
||||
return "Opportunities"
|
||||
default:
|
||||
return "Participants"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func editName(for cell: UITableViewCell){
|
||||
let alert = UIAlertController(title: "Are you sure?", message: "Title:", preferredStyle: .alert)
|
||||
|
||||
let action1 = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
|
||||
|
||||
alert.addTextField { [weak self] (tf) in
|
||||
tf.textColor = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)
|
||||
tf.text = self?.groupChat?.name
|
||||
}
|
||||
|
||||
let action2 = UIAlertAction(title: "OK", style: .default) { [unowned self] _ in
|
||||
let name = alert.textFields?.first?.text
|
||||
cell.textLabel?.text = name
|
||||
self.groupChat?.name = name!
|
||||
Model.updateGroupChat(with: self.groupChat!)
|
||||
self.delegate?.updateGroup(with: self.groupChat!)
|
||||
}
|
||||
|
||||
alert.addAction(action1)
|
||||
alert.addAction(action2)
|
||||
|
||||
present(alert, animated: true, completion: nil)
|
||||
}
|
||||
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
|
||||
{
|
||||
guard let groupChat = groupChat else {
|
||||
return
|
||||
}
|
||||
|
||||
guard let cell = tableView.cellForRow(at: indexPath) else {
|
||||
return
|
||||
}
|
||||
|
||||
if indexPath.row == 0 {
|
||||
switch indexPath.section{
|
||||
case 0:
|
||||
switch myPermissions{
|
||||
case .admin:
|
||||
editName(for: cell)
|
||||
default:
|
||||
break
|
||||
}
|
||||
case 1:
|
||||
Model.leaveGroupChat(id: groupChat.id) {
|
||||
[weak self] in
|
||||
self?.navigationController?.popViewController(animated: true)
|
||||
}
|
||||
default:
|
||||
switch myPermissions{
|
||||
case .admin:
|
||||
showUserChoiceVC()
|
||||
default:
|
||||
showParticipantPage(with: usersArray[indexPath.row])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if indexPath.section == 2 && indexPath.row != 0 {
|
||||
switch myPermissions{
|
||||
case .admin:
|
||||
showParticipantPage(with: usersArray[indexPath.row-1])
|
||||
default:
|
||||
showParticipantPage(with: usersArray[indexPath.row])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var onUserDiplay: ((Int)->())?
|
||||
|
||||
func showParticipantPage(with user: Int?) {
|
||||
if let user = user {
|
||||
onUserDiplay?(user)
|
||||
}
|
||||
}
|
||||
|
||||
func showUserChoiceVC()
|
||||
{
|
||||
let vc = storyboard?.instantiateViewController(withIdentifier: peopleToWriteVC) as! PeopleToWriteViewController
|
||||
|
||||
vc.whatToDoWithSelection = { [weak self, weak vc] mapa in
|
||||
|
||||
mapa.forEach { self?.users[$0.key] = Model.Channels.fullPeopleDict[$0.key] }
|
||||
mapa.forEach { self?.groupChat?.users[$0.key] = $0.value }
|
||||
vc?.navigationController?.popViewController(animated: true)
|
||||
}
|
||||
|
||||
navigationController?.pushViewController(vc, animated: true)
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath)
|
||||
{
|
||||
if editingStyle == UITableViewCell.EditingStyle.delete {
|
||||
groupChat?.users[usersArray[indexPath.row-1]] = nil
|
||||
}
|
||||
|
||||
tableView.reloadData()
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
|
||||
if indexPath.row == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]?
|
||||
{
|
||||
let editButton = UITableViewRowAction(style: .normal, title: "Promote") { [unowned self] (rowAction, indexPath) in
|
||||
|
||||
self.tableView.beginUpdates()
|
||||
self.groupChat?.users[self.usersArray[indexPath.row-1]]?.isAdmin = true
|
||||
self.tableView.reloadRows(at: [indexPath], with: .none)
|
||||
self.tableView.endUpdates()
|
||||
}
|
||||
|
||||
editButton.backgroundColor = #colorLiteral(red: 0.476841867, green: 0.5048075914, blue: 1, alpha: 1)
|
||||
|
||||
let restrictButton = UITableViewRowAction(style: .normal, title: "Restrict") { [unowned self] (rowAction, indexPath) in
|
||||
|
||||
self.tableView.beginUpdates()
|
||||
self.groupChat?.users[self.usersArray[indexPath.row-1]]?.isAdmin = false
|
||||
self.tableView.reloadRows(at: [indexPath], with: .none)
|
||||
self.tableView.endUpdates()
|
||||
}
|
||||
|
||||
restrictButton.backgroundColor = #colorLiteral(red: 0.8039215803, green: 0.8039215803, blue: 0.8039215803, alpha: 1)
|
||||
|
||||
let deleteButton = UITableViewRowAction(style: .normal, title: "Delete") { [unowned self] (action, indexPath) in
|
||||
|
||||
self.tableView.beginUpdates()
|
||||
self.groupChat?.users[self.usersArray[indexPath.row-1]] = nil
|
||||
self.tableView.deleteRows(at: [indexPath], with: .none)
|
||||
self.tableView.endUpdates()
|
||||
}
|
||||
|
||||
deleteButton.backgroundColor = #colorLiteral(red: 1, green: 0.1491314173, blue: 0, alpha: 1)
|
||||
|
||||
return [editButton, restrictButton, deleteButton]
|
||||
}
|
||||
|
||||
/// update chatInfo
|
||||
override func viewWillDisappear(_ animated: Bool) {
|
||||
|
||||
defer {
|
||||
super.viewWillDisappear(animated)
|
||||
}
|
||||
|
||||
guard let _ = self.navigationController?.viewControllers.lastIndex(of: self) else {
|
||||
switch myPermissions {
|
||||
case .ordinary:
|
||||
return
|
||||
case .admin:
|
||||
Model.updateGroupChat(with: groupChat!)
|
||||
delegate?.updateGroup(with: groupChat!)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
132
GDproject/Controller/Messages/Dialog/DialogCell.swift
Normal file
132
GDproject/Controller/Messages/Dialog/DialogCell.swift
Normal file
@ -0,0 +1,132 @@
|
||||
//
|
||||
// DialogCell.swift
|
||||
// GDproject
|
||||
//
|
||||
// Created by cstore on 05/05/2019.
|
||||
// Copyright © 2019 drHSE. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import TinyConstraints
|
||||
import MarkdownKit
|
||||
|
||||
class DialogCell: UITableViewCell {
|
||||
|
||||
let nameLabel: UIButton = {
|
||||
let button = UIButton()
|
||||
button.setTitleColor(.black, for: .normal)
|
||||
button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 16)
|
||||
button.contentHorizontalAlignment = UIControl.ContentHorizontalAlignment.left
|
||||
return button
|
||||
}()
|
||||
|
||||
@objc func displayProfile()
|
||||
{
|
||||
if let id = self.user?.id {
|
||||
print("diplay")
|
||||
onUserDisplay?(id)
|
||||
}
|
||||
}
|
||||
|
||||
var onUserDisplay: ((Int)->())?
|
||||
|
||||
|
||||
let timeLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = UIFont.systemFont(ofSize: 9)
|
||||
label.textAlignment = NSTextAlignment.right
|
||||
label.textColor = #colorLiteral(red: 0.4352941176, green: 0.4431372549, blue: 0.4745098039, alpha: 1)
|
||||
return label
|
||||
}()
|
||||
|
||||
func createTextView(with text: NSAttributedString, _ isSelectable: Bool) -> UITextView
|
||||
{
|
||||
let textView = UITextView()
|
||||
textView.isScrollEnabled = false
|
||||
textView.isEditable = false
|
||||
textView.sizeToFit()
|
||||
|
||||
if isSelectable {
|
||||
textView.isSelectable = true
|
||||
} else {
|
||||
textView.isUserInteractionEnabled = false
|
||||
}
|
||||
|
||||
textView.attributedText = text
|
||||
return textView
|
||||
}
|
||||
|
||||
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?)
|
||||
{
|
||||
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
||||
}
|
||||
|
||||
required init?(coder aDecoder: NSCoder)
|
||||
{
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
var user: Model.Users? {
|
||||
didSet{
|
||||
nameLabel.setTitle(user!.fullName(), for: .normal)
|
||||
}
|
||||
}
|
||||
|
||||
var textView: UITextView!
|
||||
|
||||
func fill(with markdownText: NSAttributedString, byUser: Model.Users, when: String)
|
||||
{
|
||||
let myId = DataStorage.standard.getUserId()
|
||||
// important
|
||||
contentView.subviews.forEach({ $0.removeFromSuperview() })
|
||||
|
||||
nameLabel.addTarget(self, action: #selector(displayProfile), for: .touchUpInside)
|
||||
|
||||
self.user = byUser
|
||||
textView = createTextView(with: markdownText, true)
|
||||
textView.layer.cornerRadius = 10
|
||||
textView.clipsToBounds = true
|
||||
|
||||
self.contentView.addSubview(textView)
|
||||
self.contentView.addSubview(timeLabel)
|
||||
|
||||
timeLabel.text = when.getDate()
|
||||
textView.width(min: 50, max: self.contentView.bounds.width-70, priority: .required, isActive: true)
|
||||
|
||||
if myId == byUser.id
|
||||
{
|
||||
layoutMyMessage()
|
||||
} else {
|
||||
layOutOtherMessage()
|
||||
}
|
||||
}
|
||||
|
||||
func layOutOtherMessage(){
|
||||
self.contentView.addSubview(nameLabel)
|
||||
|
||||
nameLabel.setTitle(user!.fullName(), for: .normal)
|
||||
|
||||
nameLabel.edgesToSuperview(excluding: .bottom, insets: .top(4) + .left(8))
|
||||
textView.edgesToSuperview(excluding: [.top, .right] , insets: .left(8) + .bottom(20))
|
||||
textView.topToBottom(of: nameLabel)
|
||||
|
||||
textView.backgroundColor = #colorLiteral(red: 0.8039215803, green: 0.8039215803, blue: 0.8039215803, alpha: 1)
|
||||
textView.textColor = .white
|
||||
timeLabel.edgesToSuperview(excluding: .top, insets: .right(70) + .left(8))
|
||||
timeLabel.topToBottom(of: textView, offset: 4)
|
||||
timeLabel.textAlignment = .left
|
||||
}
|
||||
|
||||
func layoutMyMessage()
|
||||
{
|
||||
textView.edgesToSuperview(excluding: .left, insets: .right(8) + .bottom(20) + .top(4))
|
||||
textView.backgroundColor = UIColor(red:0.08, green:0.49, blue:0.98, alpha:1.0)
|
||||
textView.textColor = .white
|
||||
timeLabel.edgesToSuperview(excluding: .top, insets: .left(70) + .right(8))
|
||||
timeLabel.topToBottom(of: textView, offset: 4)
|
||||
timeLabel.textAlignment = .right
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
340
GDproject/Controller/Messages/Dialog/DialogViewController.swift
Normal file
340
GDproject/Controller/Messages/Dialog/DialogViewController.swift
Normal file
@ -0,0 +1,340 @@
|
||||
//
|
||||
// DialogViewController.swift
|
||||
// GDproject
|
||||
//
|
||||
// Created by cstore on 01/05/2019.
|
||||
// Copyright © 2019 drHSE. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import TinyConstraints
|
||||
import Marklight
|
||||
|
||||
protocol UpdatableGroup:class {
|
||||
func updateGroup(with group: Model.Group)
|
||||
}
|
||||
|
||||
class DialogViewController: UIViewController, UpdatableGroup, UITableViewDelegate, UITableViewDataSource
|
||||
{
|
||||
var onUserDisplay: ((Int)->())?
|
||||
|
||||
var tableView: UITableView = UITableView()
|
||||
|
||||
func updateGroup(with group: Model.Group){
|
||||
self.groupChat?.group = group
|
||||
setTitleForGroup(groupChat: groupChat!)
|
||||
}
|
||||
|
||||
let cellId = "cell3"
|
||||
var onInfoShow: (()->())?
|
||||
|
||||
var dialog: Model.Dialog? {
|
||||
didSet{
|
||||
switch dialog! {
|
||||
case .groupChat(let chat):
|
||||
self.groupChat = chat
|
||||
case .userChat(let chat):
|
||||
self.userChat = chat
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var groupChat: Model.GroupChat?
|
||||
var userChat: Model.UserChat?
|
||||
|
||||
var users: [Int: Model.Users]?
|
||||
|
||||
var groupId: Int?
|
||||
|
||||
var cellData: [PostCellData] = [] {
|
||||
didSet {
|
||||
tableView.reloadData()
|
||||
canBePaginated = true
|
||||
}
|
||||
}
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
setConstraints()
|
||||
magicForKeyboardChanges()
|
||||
|
||||
self.tableView.delegate = self
|
||||
self.tableView.dataSource = self
|
||||
|
||||
tableView.setContentOffset(CGPoint(x: 0, y: 50), animated: false)
|
||||
|
||||
navigationItem.largeTitleDisplayMode = .never
|
||||
|
||||
tableView.keyboardDismissMode = .onDrag
|
||||
tableView.separatorStyle = .none
|
||||
tableView.register(DialogCell.self, forCellReuseIdentifier: cellId)
|
||||
tableView.transform = CGAffineTransform(scaleX: 1, y: -1)
|
||||
tableView.contentInsetAdjustmentBehavior = .never
|
||||
tableView.contentOffset = CGPoint(x: 0, y: 30)
|
||||
|
||||
if let groupChat = groupChat {
|
||||
setTitleForGroup(groupChat: groupChat)
|
||||
} else if let userChat = userChat{
|
||||
setTitleForChat(userChat: userChat)
|
||||
}
|
||||
}
|
||||
|
||||
var messageSendView: UIView = {
|
||||
let view = UIView()
|
||||
view.backgroundColor = #colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
|
||||
return view
|
||||
}()
|
||||
|
||||
var messageTextView: UITextView =
|
||||
{
|
||||
let textStorage = MarklightTextStorage()
|
||||
textStorage.marklightTextProcessor.codeColor = UIColor.orange
|
||||
textStorage.marklightTextProcessor.quoteColor = UIColor.darkGray
|
||||
textStorage.marklightTextProcessor.syntaxColor = UIColor.blue
|
||||
textStorage.marklightTextProcessor.codeFontName = "Courier"
|
||||
textStorage.marklightTextProcessor.fontTextStyle = UIFont.TextStyle.subheadline.rawValue
|
||||
textStorage.marklightTextProcessor.hideSyntax = false
|
||||
|
||||
let layoutManager = NSLayoutManager()
|
||||
|
||||
// Assign the `UITextView`'s `NSLayoutManager` to the `NSTextStorage` subclass
|
||||
//textStorage.addLayoutManager(textView.layoutManager)
|
||||
textStorage.addLayoutManager(layoutManager)
|
||||
|
||||
let textContainer = NSTextContainer()
|
||||
layoutManager.addTextContainer(textContainer)
|
||||
|
||||
let textView = UITextView(frame: CGRect.zero, textContainer: textContainer)
|
||||
textView.isEditable = true
|
||||
textView.isScrollEnabled = true
|
||||
textView.backgroundColor = .white
|
||||
return textView
|
||||
}()
|
||||
|
||||
var sendButton: UIButton = {
|
||||
let button = UIButton()
|
||||
button.setTitle("Send", for: .normal)
|
||||
button.setTitleColor(.blue, for: .normal)
|
||||
button.titleLabel?.font = UIFont.systemFont(ofSize: 17, weight: .semibold)
|
||||
button.addTarget(self, action: #selector(sendMessage), for: .touchUpInside)
|
||||
return button
|
||||
}()
|
||||
|
||||
@objc func sendMessage()
|
||||
{
|
||||
var destination: Model.MessageDestination?
|
||||
|
||||
if let group = groupChat {
|
||||
destination = Model.MessageDestination.groupChatDestination(group.group.id)
|
||||
} else if let user = userChat {
|
||||
destination = Model.MessageDestination.userChatDestination(user.user)
|
||||
}
|
||||
|
||||
if let destination = destination
|
||||
{
|
||||
Model.sendMessage(message: Model.SendMessage(body: Model.Attachments(markdown: messageTextView.text), destination: destination)) { [unowned self] in
|
||||
|
||||
switch $0 {
|
||||
case .success, .success1:
|
||||
self.getMessagesNew(for: self.dialog!)
|
||||
self.messageTextView.text = ""
|
||||
default:
|
||||
self.showAlertOn(result: $0)
|
||||
}
|
||||
}
|
||||
|
||||
prevLast = -1
|
||||
}
|
||||
}
|
||||
|
||||
var lineView: UIView = {
|
||||
let view = UIView()
|
||||
view.backgroundColor = #colorLiteral(red: 0.6000000238, green: 0.6000000238, blue: 0.6000000238, alpha: 1)
|
||||
return view
|
||||
}()
|
||||
|
||||
var bottomConstraint: NSLayoutConstraint!
|
||||
|
||||
func setConstraints(){
|
||||
self.view.addSubview(tableView)
|
||||
self.view.addSubview(messageSendView)
|
||||
|
||||
messageSendView.addSubview(messageTextView)
|
||||
messageSendView.addSubview(sendButton)
|
||||
messageSendView.addSubview(lineView)
|
||||
|
||||
messageSendView.edgesToSuperview(excluding: [.top,.bottom])
|
||||
|
||||
bottomConstraint = NSLayoutConstraint(item: messageSendView, attribute: .bottom, relatedBy: .equal, toItem: self.view.safeAreaLayoutGuide, attribute: .bottom, multiplier: 1, constant: 0)
|
||||
view.addConstraint(bottomConstraint)
|
||||
|
||||
messageSendView.height(60)
|
||||
|
||||
sendButton.edgesToSuperview(excluding: .left)
|
||||
sendButton.width(60)
|
||||
|
||||
lineView.edgesToSuperview(excluding: .bottom)
|
||||
lineView.height(0.5)
|
||||
|
||||
messageTextView.edgesToSuperview(excluding: .right)
|
||||
messageTextView.rightToLeft(of: sendButton)
|
||||
|
||||
tableView.edgesToSuperview(excluding: .bottom)
|
||||
tableView.bottomToTop(of: messageSendView)
|
||||
|
||||
self.view.layoutSubviews()
|
||||
}
|
||||
|
||||
func magicForKeyboardChanges()
|
||||
{
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardNotifications), name: UIResponder.keyboardWillShowNotification, object: nil)
|
||||
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardNotifications), name: UIResponder.keyboardWillHideNotification, object: nil)
|
||||
}
|
||||
|
||||
@objc func handleKeyboardNotifications(notification: NSNotification){
|
||||
if let userInfo = notification.userInfo{
|
||||
// UIKeyboardFrameEndUserInfoKey
|
||||
|
||||
let keyBoardFrame = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
|
||||
|
||||
bottomConstraint.constant = notification.name == UIResponder.keyboardWillShowNotification ? -(keyBoardFrame.height) + self.view.safeAreaInsets.bottom : 0
|
||||
|
||||
UIView.animate(withDuration: 0, delay: 0, options: .curveEaseOut, animations: {
|
||||
self.view.layoutIfNeeded()
|
||||
}) { (completed) in
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func setTitleForChat(userChat: Model.UserChat){
|
||||
navigationItem.title = "\(users![userChat.user]!.fullName())"
|
||||
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "👤", style: .plain, target: self, action: #selector(showPersonPage))
|
||||
}
|
||||
|
||||
@objc func showPersonPage(){
|
||||
if let id = userChat?.user{
|
||||
onUserDisplay?(id)
|
||||
}
|
||||
}
|
||||
|
||||
func setTitleForGroup(groupChat: Model.GroupChat){
|
||||
navigationItem.title = "\(groupChat.group.name)"
|
||||
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Info", style: .plain, target: self, action: #selector(moveToInfoVC))
|
||||
}
|
||||
|
||||
// onInfoShow
|
||||
@objc func moveToInfoVC(){
|
||||
let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: chatInfoViewController) as! ChatInfoViewController
|
||||
|
||||
vc.delegate = self
|
||||
vc.users = users!
|
||||
vc.onUserDiplay = onUserDisplay
|
||||
|
||||
if let groupChat = groupChat {
|
||||
vc.groupChat = groupChat.group
|
||||
}
|
||||
|
||||
navigationController?.pushViewController(vc, animated: true)
|
||||
}
|
||||
|
||||
var currentMessagesInChat: [Model.LastMessage] = [] {
|
||||
didSet
|
||||
{
|
||||
cellData = currentMessagesInChat.map { PostCellData(attributedData: PostCellData.create(with: [$0.body])) }
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Table view data source
|
||||
|
||||
func numberOfSections(in tableView: UITableView) -> Int {
|
||||
return 1
|
||||
}
|
||||
|
||||
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
return cellData.count
|
||||
}
|
||||
|
||||
override func viewWillAppear(_ animated: Bool)
|
||||
{
|
||||
super.viewWillAppear(animated)
|
||||
tabBarController?.tabBar.isHidden = true
|
||||
|
||||
if let dialog = dialog {
|
||||
getMessagesNew(for: dialog)
|
||||
}
|
||||
}
|
||||
|
||||
func getMessages(for dialog: Model.Dialog, starting from: Int? = nil)
|
||||
{
|
||||
switch dialog {
|
||||
case .groupChat(let groupChat):
|
||||
Model.getMessagesFor(typeOfChat: Model.Dialog.groupChat(groupChat), chat: groupChat.group.id, exclusiveFrom: from)
|
||||
{ [weak self] in
|
||||
self?.currentMessagesInChat.append(contentsOf: $0)
|
||||
}
|
||||
case .userChat(let userChat):
|
||||
Model.getMessagesFor(typeOfChat: Model.Dialog.userChat(userChat), chat: userChat.user, exclusiveFrom: from)
|
||||
{ [weak self] in
|
||||
self?.currentMessagesInChat.append(contentsOf: $0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func getMessagesNew(for dialog: Model.Dialog, starting from: Int? = nil)
|
||||
{
|
||||
switch dialog {
|
||||
case .groupChat(let groupChat):
|
||||
Model.getMessagesFor(typeOfChat: Model.Dialog.groupChat(groupChat), chat: groupChat.group.id, exclusiveFrom: from)
|
||||
{ [weak self] in
|
||||
self?.currentMessagesInChat = $0
|
||||
}
|
||||
case .userChat(let userChat):
|
||||
Model.getMessagesFor(typeOfChat: Model.Dialog.userChat(userChat), chat: userChat.user, exclusiveFrom: from)
|
||||
{ [weak self] in
|
||||
self?.currentMessagesInChat = $0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
|
||||
{
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath) as! DialogCell
|
||||
|
||||
//In cellForRowAtIndexPath
|
||||
cell.transform = CGAffineTransform(scaleX: 1, y: -1)
|
||||
cell.selectionStyle = .none
|
||||
|
||||
|
||||
if let user = users?[currentMessagesInChat[indexPath.row].author]
|
||||
{
|
||||
cell.fill(with: cellData[indexPath.row].attributedData, byUser: user, when: currentMessagesInChat[indexPath.row].time)
|
||||
|
||||
cell.onUserDisplay = onUserDisplay
|
||||
}
|
||||
|
||||
return cell
|
||||
}
|
||||
|
||||
var prevLast = -1
|
||||
var canBePaginated = false
|
||||
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath)
|
||||
{
|
||||
if indexPath.row == cellData.count - 1 && prevLast != indexPath.row && canBePaginated && cellData.count >= 24
|
||||
{
|
||||
print("exclusiveFrom \(currentMessagesInChat.last?.id ?? 0)")
|
||||
if let dialog = dialog
|
||||
{
|
||||
getMessages(for: dialog, starting: currentMessagesInChat.last?.id)
|
||||
}
|
||||
|
||||
prevLast = indexPath.row
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
38
GDproject/Controller/Messages/MessageViewCell.swift
Normal file
38
GDproject/Controller/Messages/MessageViewCell.swift
Normal file
@ -0,0 +1,38 @@
|
||||
//
|
||||
// MessageViewCell.swift
|
||||
// GDproject
|
||||
//
|
||||
// Created by cstore on 13/05/2019.
|
||||
// Copyright © 2019 drHSE. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class MessageViewCell: UITableViewCell {
|
||||
|
||||
@IBOutlet weak var dialogName: UILabel!
|
||||
|
||||
@IBOutlet weak var lastMessagePreview: UILabel!
|
||||
|
||||
@IBOutlet weak var dateLabel: UILabel!
|
||||
|
||||
override func awakeFromNib() {
|
||||
super.awakeFromNib()
|
||||
// Initialization code
|
||||
}
|
||||
|
||||
func fill(with dialog: Model.Dialog, user: Model.Users? = nil)
|
||||
{
|
||||
switch dialog {
|
||||
|
||||
case .groupChat(let group):
|
||||
dialogName.text = group.group.name
|
||||
lastMessagePreview.text = group.lastMessage?.body.markdown
|
||||
dateLabel.text = group.lastMessage?.time.getDate()
|
||||
case .userChat(let userChat):
|
||||
dialogName.text = "👤 \(user!.fullName())"
|
||||
lastMessagePreview.text = userChat.lastMessage?.body.markdown
|
||||
dateLabel.text = userChat.lastMessage?.time.getDate()
|
||||
}
|
||||
}
|
||||
}
|
181
GDproject/Controller/Messages/MessagesViewController.swift
Normal file
181
GDproject/Controller/Messages/MessagesViewController.swift
Normal file
@ -0,0 +1,181 @@
|
||||
//
|
||||
// MessagesViewController.swift
|
||||
// GDproject
|
||||
//
|
||||
// Created by cstore on 01/05/2019.
|
||||
// Copyright © 2019 drHSE. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
protocol SelectableDialog: class {
|
||||
func openDialog(with dialog: Model.Dialog)
|
||||
}
|
||||
|
||||
class MessagesViewController: UITableViewController, UISearchControllerDelegate, UISearchResultsUpdating, SelectableDialog {
|
||||
|
||||
func openDialog(with dialog: Model.Dialog) {
|
||||
onDialogDisplay?((dialog, users))
|
||||
}
|
||||
|
||||
func updateSearchResults(for searchController: UISearchController) {
|
||||
|
||||
let filteredData = currentActiveDialogs
|
||||
let inputText = searchController.searchBar.text ?? ""
|
||||
|
||||
let filteredResults = filteredData.filter {
|
||||
|
||||
switch $0 {
|
||||
case .groupChat(let gropuChat):
|
||||
return gropuChat.group.name.contains(inputText)
|
||||
|
||||
case .userChat(let userChat):
|
||||
let user = users[userChat.user]
|
||||
guard let u = user else { return false }
|
||||
return u.fullName().contains(inputText)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Apply the filtered results to the search results table.
|
||||
if let resultsController = searchController.searchResultsController as? SuggestedDialogsTableViewController {
|
||||
resultsController.users = users
|
||||
resultsController.currentDialogs = filteredResults
|
||||
resultsController.tableView.reloadData()
|
||||
}
|
||||
}
|
||||
|
||||
// curreent Active which can be displayed
|
||||
var currentActiveDialogs: [Model.Dialog] = [] {
|
||||
didSet {
|
||||
tableView.reloadData()
|
||||
}
|
||||
}
|
||||
|
||||
func setUpSearchContr(){
|
||||
|
||||
searchController?.delegate = self
|
||||
searchController?.obscuresBackgroundDuringPresentation = true
|
||||
navigationItem.searchController = searchController
|
||||
definesPresentationContext = true
|
||||
searchController?.searchResultsUpdater = self
|
||||
searchController?.searchBar.placeholder = "Search dialogs"
|
||||
|
||||
}
|
||||
|
||||
// curreent users
|
||||
var users: [Int: Model.Users] = [:]
|
||||
|
||||
var onUserDisplayList: (()->())?
|
||||
|
||||
var onDialogDisplay: (((dialog: Model.Dialog, users: [Int:Model.Users]))->())?
|
||||
|
||||
var searchController: UISearchController?
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
let updater = SuggestedDialogsTableViewController()
|
||||
|
||||
updater.delegate = self
|
||||
searchController = UISearchController(searchResultsController: updater)
|
||||
|
||||
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
|
||||
self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Write", style: .plain, target: self, action: #selector(choosePerson))
|
||||
|
||||
self.navigationItem.title = "Messages"
|
||||
// self.navigationItem.largeTitleDisplayMode = .always
|
||||
setUpSearchContr()
|
||||
navigationController?.navigationBar.prefersLargeTitles = true
|
||||
self.navigationItem.hidesSearchBarWhenScrolling = false
|
||||
}
|
||||
|
||||
@objc func choosePerson(){
|
||||
onUserDisplayList?()
|
||||
}
|
||||
|
||||
override func viewWillAppear(_ animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
tabBarController?.tabBar.isHidden = false
|
||||
Model.getChatAll { [weak self] in
|
||||
self?.currentActiveDialogs = $0.0
|
||||
self?.users = $0.1
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Table view data source
|
||||
override func numberOfSections(in tableView: UITableView) -> Int {
|
||||
return 1
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
return currentActiveDialogs.count
|
||||
}
|
||||
|
||||
|
||||
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
|
||||
{
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "MessageViewCell", for: indexPath) as! MessageViewCell
|
||||
|
||||
switch currentActiveDialogs[indexPath.row].self {
|
||||
case .groupChat:
|
||||
cell.fill(with: currentActiveDialogs[indexPath.row])
|
||||
case .userChat(let userChat):
|
||||
cell.fill(with: currentActiveDialogs[indexPath.row], user: users[userChat.user])
|
||||
}
|
||||
|
||||
return cell
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
let tuple = (currentActiveDialogs[indexPath.row],users)
|
||||
onDialogDisplay?(tuple)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class SuggestedDialogsTableViewController: UITableViewController {
|
||||
|
||||
var idCell = "cell"
|
||||
|
||||
var users: [Int: Model.Users] = [:]
|
||||
|
||||
weak var delegate: SelectableDialog?
|
||||
|
||||
var currentDialogs: [Model.Dialog] = []
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
tableView.register(UITableViewCell.self, forCellReuseIdentifier: idCell)
|
||||
tableView.reloadData()
|
||||
}
|
||||
|
||||
override func numberOfSections(in tableView: UITableView) -> Int {
|
||||
return 1
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
return currentDialogs.count
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
|
||||
{
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: idCell, for: indexPath)
|
||||
|
||||
switch currentDialogs[indexPath.row] {
|
||||
case .groupChat(let groupChat):
|
||||
cell.textLabel?.text = groupChat.group.name
|
||||
case .userChat(let userChat):
|
||||
cell.textLabel?.text = users[userChat.user]?.fullName()
|
||||
}
|
||||
|
||||
cell.accessoryType = .disclosureIndicator
|
||||
return cell
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
delegate?.openDialog(with: currentDialogs[indexPath.row])
|
||||
// self.dismiss(animated: true)
|
||||
}
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
//
|
||||
// PeopleToWriteViewController.swift
|
||||
// GDproject
|
||||
//
|
||||
// Created by cstore on 01/05/2019.
|
||||
// Copyright © 2019 drHSE. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class PeopleToWriteViewController: UITableViewController {
|
||||
|
||||
// TODO: - edit button when it's used for selection
|
||||
var whatToDoWithSelection: (([Int: Model.UserPermission])->())?
|
||||
|
||||
let searchC = UISearchController(searchResultsController: nil)
|
||||
|
||||
let users = Model.Channels.fullPeople
|
||||
|
||||
var chosenUsers: [Int: Model.UserPermission] = [:]
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
tableView.isEditing = true
|
||||
self.navigationItem.title = "People"
|
||||
|
||||
self.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(newMessage))
|
||||
|
||||
self.navigationItem.largeTitleDisplayMode = .never
|
||||
self.navigationItem.searchController = searchC
|
||||
self.navigationItem.hidesSearchBarWhenScrolling = false
|
||||
}
|
||||
|
||||
override func setEditing(_ editing: Bool, animated: Bool) {
|
||||
super.setEditing(true, animated: animated)
|
||||
}
|
||||
|
||||
override func numberOfSections(in tableView: UITableView) -> Int {
|
||||
return 1
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
return users.count
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
chosenUsers[users[indexPath.row].id] = Model.UserPermission(isAdmin: false)
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
|
||||
{
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "peopleToWriteCell", for: indexPath)
|
||||
|
||||
cell.textLabel?.text = users[indexPath.row].fullName()
|
||||
|
||||
return cell
|
||||
}
|
||||
|
||||
@objc func newMessage()
|
||||
{
|
||||
if chosenUsers.count != 0
|
||||
{
|
||||
whatToDoWithSelection?(chosenUsers)
|
||||
}
|
||||
}
|
||||
}
|
@ -16,14 +16,17 @@ struct CellData{
|
||||
|
||||
class BasicInfoController: UIViewController, UITableViewDelegate, UITableViewDataSource {
|
||||
|
||||
var dataSourse: [CellData] = [
|
||||
CellData(opened: false, title: "Phone", sectionData: ["+7 901 733 01 79"]),
|
||||
CellData(opened: false, title: "Mail", sectionData: ["vbogomazova@edu.hse.ru"]),
|
||||
CellData(opened: false, title: "Research ID", sectionData: ["4567834336789456737"]),
|
||||
CellData(opened: false, title: "Published", sectionData: ["Это будет очень длинное название книги 1, чтобы сделать проверку", "Книга 2", "Книга 3"]),
|
||||
CellData(opened: false, title: "Courses", sectionData: ["Курс 1", "Курс 2"]),
|
||||
CellData(opened: false, title: "Link", sectionData: ["https://wwww.hse.ru"])
|
||||
]
|
||||
var userInfo: Model.Users? {
|
||||
didSet {
|
||||
if let userInfo = userInfo {
|
||||
dataSourse = [CellData(opened: false, title: "Contacts", sectionData: [userInfo.email, userInfo.faculty.address]),
|
||||
CellData(opened: false, title: "Faculty", sectionData: [userInfo.faculty.campusName, userInfo.faculty.name, userInfo.faculty.address, userInfo.faculty.path]),
|
||||
CellData(opened: false, title: "Interests", sectionData: userInfo.faculty.tags)]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var dataSourse: [CellData] = [ ]
|
||||
|
||||
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
if (dataSourse[section].opened) {
|
||||
@ -45,8 +48,10 @@ class BasicInfoController: UIViewController, UITableViewDelegate, UITableViewDat
|
||||
cell.selectionStyle = .none
|
||||
return cell
|
||||
} else {
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
|
||||
cell.textLabel?.text = dataSourse[indexPath.section].sectionData[indexPath.row - 1]
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: infoCellId, for: indexPath) as! InfoCell
|
||||
cell.fill(title: dataSourse[indexPath.section].sectionData[indexPath.row - 1])
|
||||
cell.accessoryType = .none
|
||||
cell.selectionStyle = .none
|
||||
return cell
|
||||
}
|
||||
}
|
||||
|
@ -16,8 +16,9 @@ class InfoCell: UITableViewCell{
|
||||
label.font = UIFont.systemFont(ofSize: 16)
|
||||
label.sizeToFit()
|
||||
label.isScrollEnabled = false
|
||||
label.isUserInteractionEnabled = false
|
||||
// label.isUserInteractionEnabled = false
|
||||
label.isEditable = false
|
||||
label.dataDetectorTypes = .all
|
||||
label.textColor = .black
|
||||
return label
|
||||
}()
|
||||
|
@ -9,8 +9,17 @@
|
||||
import UIKit
|
||||
import TinyConstraints
|
||||
|
||||
class ProfileViewController: UIViewController
|
||||
protocol UpdateUser: class {
|
||||
func updateUserObj(with user: Model.Users)
|
||||
}
|
||||
|
||||
class ProfileViewController: UIViewController, UpdateUser
|
||||
{
|
||||
func updateUserObj(with user: Model.Users)
|
||||
{
|
||||
self.user = user
|
||||
Model.Channels.fullPeopleDict[user.id] = user
|
||||
}
|
||||
|
||||
@IBOutlet weak var segmentedControl: UISegmentedControl!
|
||||
|
||||
@ -30,14 +39,33 @@ class ProfileViewController: UIViewController
|
||||
|
||||
@IBOutlet weak var newMessageButton: UIButton!
|
||||
|
||||
var protoDictionary: [Int: UIImage] = [9: #imageLiteral(resourceName: "9"), 5051: #imageLiteral(resourceName: "5051"), 69: #imageLiteral(resourceName: "69"), 42: #imageLiteral(resourceName: "42")]
|
||||
var logOut: (()->())?
|
||||
|
||||
func fill(with user: Model.Users){
|
||||
self.facultyLabel.text = "Студент: Факультет Компьютерных Наук"
|
||||
var deleteAllSessions: (()->())?
|
||||
|
||||
var onSettings: (()->())?
|
||||
|
||||
@IBAction func sendMessage(_ sender: UIButton)
|
||||
{
|
||||
if let userId = idProfile
|
||||
{
|
||||
let createdDialog = Model.Dialog.userChat(Model.UserChat(user: userId))
|
||||
let vc = DialogViewController()
|
||||
vc.users = Model.Channels.fullPeopleDict
|
||||
vc.dialog = createdDialog
|
||||
self.navigationController?.pushViewController(vc, animated: true)
|
||||
}
|
||||
}
|
||||
|
||||
var protoDictionary: [String: UIImage] = ["135213": #imageLiteral(resourceName: "9"), "135288": #imageLiteral(resourceName: "5051"), "22723" : #imageLiteral(resourceName: "69"), "135083": #imageLiteral(resourceName: "42")]
|
||||
|
||||
func fill(with user: Model.Users)
|
||||
{
|
||||
self.facultyLabel.text = user.faculty.name
|
||||
self.nameLabel.text = "\(user.firstName) \(user.middleName)"
|
||||
self.surnameLabel.text = "\(user.lastName)"
|
||||
self.profileImageView.image = protoDictionary[user.id]?.roundedImage
|
||||
self.placeLabel.text = "📍Москва, Кочновский пр.3"
|
||||
self.profileImageView.image = protoDictionary[user.faculty.campusCode]?.roundedImage
|
||||
self.placeLabel.text = "📍\(user.faculty.address)"
|
||||
if user.id == DataStorage.standard.getUserId() {
|
||||
newMessageButton.isHidden = true
|
||||
} else {
|
||||
@ -47,39 +75,54 @@ class ProfileViewController: UIViewController
|
||||
|
||||
var user: Model.Users? {
|
||||
didSet {
|
||||
self.fill(with: user!)
|
||||
Model.getPostsForUser(with: user!.id) { [weak self] (posts) in
|
||||
self?.dataSourse = posts
|
||||
if let user = user {
|
||||
self.fill(with: user)
|
||||
navigationItem.title = "\(user.firstName) \(user.lastName)"
|
||||
} else if let id = idProfile {
|
||||
Model.getUsers(for: [id]) { [unowned self ] in
|
||||
self.user = $0[id]
|
||||
}
|
||||
navigationItem.title = "\(user!.firstName) \(user!.lastName)"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var channel: Model.Channels? {
|
||||
didSet {
|
||||
self.update()
|
||||
}
|
||||
}
|
||||
|
||||
func update()
|
||||
{
|
||||
Model.getAnonymousChannel(by: channel!) { [unowned self] in
|
||||
self.posts.dataSourse = $0.posts
|
||||
self.posts.dictionary = $0.users
|
||||
self.user = $0.users[self.idProfile!]
|
||||
}
|
||||
}
|
||||
|
||||
var basicInfo = BasicInfoController()
|
||||
var posts = NewsVC()
|
||||
|
||||
var dataSourse: [Model.Posts]?{
|
||||
didSet{
|
||||
|
||||
var newPosts: [Model.Posts] = []
|
||||
|
||||
dataSourse?.forEach({ (post) in
|
||||
newPosts.append(Model.Posts(body: post.body, authorId: post.authorId, id: post.id, user: user!, date: post.updated, tags: post.tags))
|
||||
})
|
||||
|
||||
self.posts.dataSourse = newPosts
|
||||
tableView.reloadData()
|
||||
}
|
||||
}
|
||||
|
||||
override func viewDidLoad()
|
||||
{
|
||||
super.viewDidLoad()
|
||||
|
||||
|
||||
if idProfile == nil {
|
||||
idProfile = DataStorage.standard.getUserId()
|
||||
}
|
||||
|
||||
posts.viewController = self
|
||||
posts.type = .NONE
|
||||
posts.currChannel = channel
|
||||
|
||||
posts.onFullPost = {
|
||||
[weak self] (type,post) in
|
||||
|
||||
let vc = self?.storyboard?.instantiateViewController(withIdentifier: fullPostControllerId) as! FullPostController
|
||||
vc.type = type
|
||||
vc.post = post
|
||||
self?.navigationController!.pushViewController(vc, animated: true)
|
||||
}
|
||||
|
||||
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
|
||||
|
||||
@ -96,54 +139,91 @@ class ProfileViewController: UIViewController
|
||||
tableView.reloadData()
|
||||
}
|
||||
|
||||
var idProfile: Int?
|
||||
var idProfile: Int? {
|
||||
didSet {
|
||||
channel = Model.Channels(people: [idProfile!], name: "", id: 0, tags: [])
|
||||
}
|
||||
}
|
||||
|
||||
override func viewWillAppear(_ animated: Bool) {
|
||||
tabBarController?.tabBar.isHidden = false
|
||||
|
||||
if idProfile == nil {
|
||||
idProfile = DataStorage.standard.getUserId()
|
||||
}
|
||||
user = Model.Channels.fullPeopleDict[idProfile!]
|
||||
|
||||
if let id = idProfile {
|
||||
if let user = Model.idUser[id] {
|
||||
self.user = user
|
||||
} else {
|
||||
Model.getUsers(for: [id]) { [weak self] (dic) in
|
||||
self?.user = dic[id]
|
||||
}
|
||||
}
|
||||
|
||||
// requst for postsforuser was here. moved because of concrr
|
||||
}
|
||||
update()
|
||||
|
||||
setUpNavigarionBar()
|
||||
}
|
||||
|
||||
func setUpNavigarionBar(){
|
||||
navigationController?.navigationBar.prefersLargeTitles = true
|
||||
//navigationItem.title = "\(user?.id ?? 0)"
|
||||
// navigationController?.navigationBar.prefersLargeTitles = true
|
||||
let uibarbutton = UIBarButtonItem(title: "More", style: .plain, target: self, action: #selector(showInformation))
|
||||
navigationItem.rightBarButtonItems = [uibarbutton]
|
||||
navigationItem.largeTitleDisplayMode = .always
|
||||
}
|
||||
|
||||
|
||||
let copyLink: UIAlertAction = {
|
||||
let b = UIAlertAction(title: "Copy link", style: .default)
|
||||
return b
|
||||
}()
|
||||
|
||||
@objc func showInformation(){
|
||||
|
||||
// drafts
|
||||
// saved
|
||||
|
||||
let optionMenu = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
|
||||
let channelAction = UIAlertAction(title: "Add to a channel", style: .default){
|
||||
|
||||
|
||||
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel)
|
||||
|
||||
|
||||
if idProfile == DataStorage.standard.getUserId() {
|
||||
let logoutAction = UIAlertAction(title: "Log out", style: .destructive)
|
||||
{ [weak self] (_) in
|
||||
|
||||
if let logOut = self?.logOut {
|
||||
logOut()
|
||||
} else {
|
||||
Model.logout() {
|
||||
DataStorage.standard.setIsLoggedIn(value: false, with: 0)
|
||||
(UIApplication.shared.delegate as! AppDelegate).relaunch()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let deleetAllSessionsAction = UIAlertAction(title: "Delete all sessions", style: .destructive)
|
||||
{ [weak self] _ in
|
||||
|
||||
if let delete = self?.deleteAllSessions {
|
||||
delete()
|
||||
} else {
|
||||
Model.deactivateAll() {
|
||||
DataStorage.standard.setIsLoggedIn(value: false, with: 0)
|
||||
(UIApplication.shared.delegate as! AppDelegate).relaunch()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let settingsAction = UIAlertAction(title: "Edit profile", style: .default)
|
||||
{ [weak self] (_) in
|
||||
|
||||
if let settings = self?.onSettings{
|
||||
settings()
|
||||
} else {
|
||||
let vc = self?.storyboard?.instantiateViewController(withIdentifier: "RegisterTableViewController") as! RegisterTableViewController
|
||||
vc.delegate = self
|
||||
vc.userActive = self?.user
|
||||
|
||||
self?.navigationController?.pushViewController(vc, animated: true)
|
||||
}
|
||||
}
|
||||
|
||||
optionMenu.addAction(settingsAction)
|
||||
optionMenu.addAction(logoutAction)
|
||||
optionMenu.addAction(deleetAllSessionsAction)
|
||||
} else {
|
||||
let channelAction = UIAlertAction(title: "Add to a channel", style: .default)
|
||||
{
|
||||
[weak self] (_) in
|
||||
|
||||
let vc = self?.storyboard?.instantiateViewController(withIdentifier: simplifiedChannelsList) as! SimplifiedChannelsList
|
||||
|
||||
vc.user = self?.user!
|
||||
vc.user = self?.user
|
||||
|
||||
let transition = CATransition()
|
||||
transition.duration = 0.5
|
||||
@ -153,26 +233,11 @@ class ProfileViewController: UIViewController
|
||||
self?.navigationController?.view.layer.add(transition, forKey: nil)
|
||||
self?.navigationController?.pushViewController(vc, animated: false)
|
||||
}
|
||||
let settingsAction = UIAlertAction(title: "Setting", style: .default)
|
||||
{ [weak self] (_) in
|
||||
|
||||
let vc = self?.storyboard?.instantiateViewController(withIdentifier: "SettingsViewController") as! SettingsViewController
|
||||
self?.navigationController?.pushViewController(vc, animated: true)
|
||||
}
|
||||
|
||||
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel)
|
||||
let logoutAction = UIAlertAction(title: "Log out", style: .destructive)
|
||||
{
|
||||
(_) in
|
||||
DataStorage.standard.setIsLoggedIn(value: false, with: 0)
|
||||
}
|
||||
|
||||
optionMenu.addAction(channelAction)
|
||||
optionMenu.addAction(settingsAction)
|
||||
optionMenu.addAction(copyLink)
|
||||
optionMenu.addAction(logoutAction)
|
||||
optionMenu.addAction(cancelAction)
|
||||
}
|
||||
|
||||
optionMenu.addAction(cancelAction)
|
||||
self.present(optionMenu, animated: true, completion: nil)
|
||||
}
|
||||
|
||||
@ -202,6 +267,7 @@ class ProfileViewController: UIViewController
|
||||
func changeToBasicInfo(){
|
||||
tableView.delegate = basicInfo
|
||||
tableView.dataSource = basicInfo
|
||||
basicInfo.userInfo = self.user
|
||||
tableView.reloadData()
|
||||
}
|
||||
}
|
||||
|
@ -1,59 +0,0 @@
|
||||
/// RepeatingTimer mimics the API of DispatchSourceTimer but in a way that prevents
|
||||
/// crashes that occur from calling resume multiple times on a timer that is
|
||||
/// already resumed (noted by https://github.com/SiftScience/sift-ios/issues/52
|
||||
|
||||
import Foundation
|
||||
|
||||
class RepeatingTimer {
|
||||
|
||||
let timeInterval: TimeInterval
|
||||
|
||||
init(timeInterval: TimeInterval) {
|
||||
self.timeInterval = timeInterval
|
||||
}
|
||||
|
||||
private lazy var timer: DispatchSourceTimer = {
|
||||
let t = DispatchSource.makeTimerSource()
|
||||
t.schedule(deadline: .now() + self.timeInterval, repeating: self.timeInterval)
|
||||
t.setEventHandler(handler: { [weak self] in
|
||||
self?.eventHandler?()
|
||||
})
|
||||
return t
|
||||
}()
|
||||
|
||||
var eventHandler: (() -> Void)?
|
||||
|
||||
private enum State {
|
||||
case suspended
|
||||
case resumed
|
||||
}
|
||||
|
||||
private var state: State = .suspended
|
||||
|
||||
deinit {
|
||||
timer.setEventHandler {}
|
||||
timer.cancel()
|
||||
/*
|
||||
If the timer is suspended, calling cancel without resuming
|
||||
triggers a crash. This is documented here https://forums.developer.apple.com/thread/15902
|
||||
*/
|
||||
resume()
|
||||
eventHandler = nil
|
||||
}
|
||||
|
||||
func resume() {
|
||||
if state == .resumed {
|
||||
return
|
||||
}
|
||||
state = .resumed
|
||||
timer.resume()
|
||||
}
|
||||
|
||||
func suspend() {
|
||||
if state == .suspended {
|
||||
return
|
||||
}
|
||||
state = .suspended
|
||||
timer.suspend()
|
||||
}
|
||||
}
|
@ -37,18 +37,17 @@ class DataStorage{
|
||||
return UserDefaults.standard.integer(forKey: UserDefaultsKeys.id.rawValue)
|
||||
}
|
||||
|
||||
func setEmail(email: String) {
|
||||
UserDefaults.standard.set(email, forKey: UserDefaultsKeys.email.rawValue)
|
||||
}
|
||||
|
||||
func getEmail() -> String? {
|
||||
return UserDefaults.standard.string(forKey: UserDefaultsKeys.email.rawValue)
|
||||
}
|
||||
/**
|
||||
Function to determine is user logged in already or not
|
||||
*/
|
||||
var isLoggedIn: Bool = UserDefaults.standard.bool(forKey: UserDefaultsKeys.loggedIn.rawValue) {
|
||||
didSet{
|
||||
if isLoggedIn && getUserId() != 0 {
|
||||
(UIApplication.shared.delegate as? AppDelegate)?.tabCoordinator.start()
|
||||
} else {
|
||||
(UIApplication.shared.delegate as? AppDelegate)?.logInAgain()
|
||||
}
|
||||
}
|
||||
}
|
||||
var isLoggedIn: Bool = UserDefaults.standard.bool(forKey: UserDefaultsKeys.loggedIn.rawValue)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -57,4 +56,5 @@ class DataStorage{
|
||||
enum UserDefaultsKeys: String{
|
||||
case loggedIn
|
||||
case id
|
||||
case email
|
||||
}
|
||||
|
@ -60,3 +60,50 @@ extension UIStoryboard {
|
||||
return UIStoryboard.userEdit.instantiateViewController(withIdentifier: logInController) as! LogInViewController
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extension String {
|
||||
func getDate() -> String
|
||||
{
|
||||
let dateFormatter = DateFormatter()
|
||||
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"//this your string date format
|
||||
dateFormatter.timeZone = TimeZone(abbreviation: "UTC")
|
||||
let date = dateFormatter.date(from: self)
|
||||
|
||||
dateFormatter.dateFormat = "MMM d, yyyy HH:mm" ///this is what you want to convert format
|
||||
dateFormatter.timeZone = NSTimeZone.local
|
||||
let timeStamp = dateFormatter.string(from: date!)
|
||||
|
||||
return timeStamp
|
||||
}
|
||||
}
|
||||
|
||||
extension UIViewController {
|
||||
func showAlertOn(result: ResultR) {
|
||||
|
||||
let message: String
|
||||
|
||||
switch result {
|
||||
case .impossibleContent:
|
||||
message = "Impossible content"
|
||||
case .exceededContent:
|
||||
message = "The content exceeded"
|
||||
case .longContent:
|
||||
message = "The content is too long"
|
||||
case .badAccess:
|
||||
message = "Try reloading the page again"
|
||||
case .alreadyRegistered:
|
||||
message = "User is already registered"
|
||||
case .tooMuchToAdd:
|
||||
message = "Limit of channels exceeded"
|
||||
case .success, .success1:
|
||||
return
|
||||
default:
|
||||
message = "Something went wrong"
|
||||
}
|
||||
|
||||
let alert = UIAlertController(title: "Error", message: message, preferredStyle: .alert)
|
||||
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
|
||||
self.present(alert, animated: true, completion: nil)
|
||||
}
|
||||
}
|
||||
|
44
GDproject/Simple model/CompletionTree.swift
Normal file
44
GDproject/Simple model/CompletionTree.swift
Normal file
@ -0,0 +1,44 @@
|
||||
//
|
||||
// CompletionTree.swift
|
||||
// GDproject
|
||||
//
|
||||
// Created by cstore on 01/05/2019.
|
||||
// Copyright © 2019 drHSE. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
struct CompletionTree: Codable {
|
||||
var value: String?
|
||||
var subtree: [String : CompletionTree]
|
||||
|
||||
static func getCompletion(tree: CompletionTree, word: String) -> [String] {
|
||||
if word == "" {
|
||||
return getValues(tree: tree)
|
||||
}
|
||||
|
||||
let character = String(word.first!)
|
||||
|
||||
if tree.subtree[character] == nil {
|
||||
return []
|
||||
} else {
|
||||
return getCompletion(tree: tree.subtree[character]!, word: String(word.dropFirst()))
|
||||
}
|
||||
}
|
||||
|
||||
static func getValues(tree: CompletionTree) -> [String]
|
||||
{
|
||||
var out = [String]()
|
||||
|
||||
if let treeVal = tree.value {
|
||||
out.append(treeVal)
|
||||
}
|
||||
|
||||
for (_, subtree) in tree.subtree {
|
||||
out += getValues(tree: subtree)
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -9,31 +9,6 @@
|
||||
import Foundation
|
||||
import UIKit
|
||||
|
||||
struct Post {
|
||||
var dataArray: [Media]
|
||||
var fromUser: User
|
||||
var atDate: String
|
||||
var comments: [Comment] = []
|
||||
|
||||
var hashtags: [String] = ["ФКН", "Подбельский", "НИУВШЭ", "Шершаков", "ПАД", "Интересное","Мемы","Забавное","Учеба","Наука"]
|
||||
|
||||
init(dataArray: [Media], from: User, date: String, comments: [Comment] = [])
|
||||
{
|
||||
self.dataArray = dataArray
|
||||
fromUser = from
|
||||
atDate = date
|
||||
self.comments = comments
|
||||
}
|
||||
|
||||
init(dataArray: [Media]) {
|
||||
self.dataArray = dataArray
|
||||
fromUser = User(name: "vbogomazova", id: 2, fullName: "Богомазова Вероника Львовна")
|
||||
atDate = "23.03.19 в 23:33"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
enum Media{
|
||||
case text(String)
|
||||
case image([UIImage])
|
||||
@ -41,7 +16,6 @@ enum Media{
|
||||
}
|
||||
|
||||
struct Comment {
|
||||
var from: User
|
||||
var atTime: String
|
||||
var withData: String
|
||||
}
|
||||
|
@ -1,41 +0,0 @@
|
||||
//
|
||||
// User.swift
|
||||
// NewsFeed
|
||||
//
|
||||
// Created by cstore on 12/01/2019.
|
||||
// Copyright © 2019 drHSE. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import UIKit
|
||||
|
||||
struct User {
|
||||
//var photo: UIImage? = #imageLiteral(resourceName: "image")
|
||||
var login: String
|
||||
var id: Int
|
||||
var fullName: String
|
||||
var initials: (surname: String, name: String, optional: String?) = ("Богомазова","Вероника","Львовна")
|
||||
var placeOfWork: String?
|
||||
var faculty: String?
|
||||
let posts: [Post] = []
|
||||
|
||||
|
||||
init(name: String, id: Int, fullName: String) {
|
||||
self.login = name
|
||||
self.id = id
|
||||
self.fullName = fullName
|
||||
}
|
||||
|
||||
init(surname: String, name: String, optional: String?, emailName: String, id: Int, place: String?, faculty: String?)
|
||||
{
|
||||
self.id = id
|
||||
self.login = emailName
|
||||
self.initials = (surname, name, optional)
|
||||
|
||||
self.fullName = "\(surname) \(name) \(optional ?? "")"
|
||||
self.placeOfWork = place
|
||||
if let f = faculty {
|
||||
self.faculty = f
|
||||
}
|
||||
}
|
||||
}
|
@ -12,57 +12,28 @@ import UIKit
|
||||
class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
|
||||
|
||||
var coordinator: LogInCoordinator!
|
||||
var tabCoordinator: TabbarCoordinator!
|
||||
|
||||
var window: UIWindow?
|
||||
var rootController: UINavigationController? {
|
||||
return self.window!.rootViewController as? UINavigationController
|
||||
}
|
||||
|
||||
func logInAgain(){
|
||||
let root = UIStoryboard.navRoot()
|
||||
window?.rootViewController = root
|
||||
window?.makeKeyAndVisible()
|
||||
coordinator = LogInCoordinator(navigationController: root, window: UIApplication.shared.keyWindow!)
|
||||
coordinator!.start()
|
||||
}
|
||||
var appCoordinator: ApplicationCoordinator!
|
||||
|
||||
|
||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool
|
||||
{
|
||||
coordinator = LogInCoordinator(navigationController: rootController!, window: window!)
|
||||
tabCoordinator = TabbarCoordinator(window: window!)
|
||||
// TODO:- determine what to do here: log in or tabbar
|
||||
if DataStorage.standard.isLoggedIn {
|
||||
tabCoordinator.start()
|
||||
} else {
|
||||
coordinator.start()
|
||||
window = UIWindow(frame: UIScreen.main.bounds)
|
||||
window?.makeKeyAndVisible()
|
||||
|
||||
// window?.rootViewController = UINavigationController()
|
||||
Model.getCompl { (complTree) in
|
||||
Model.hashTagTree = complTree
|
||||
}
|
||||
|
||||
appCoordinator = ApplicationCoordinator(window: window!)
|
||||
appCoordinator.start()
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func applicationWillResignActive(_ application: UIApplication) {
|
||||
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
|
||||
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
|
||||
}
|
||||
|
||||
func applicationDidEnterBackground(_ application: UIApplication) {
|
||||
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
|
||||
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
|
||||
}
|
||||
|
||||
func applicationWillEnterForeground(_ application: UIApplication) {
|
||||
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
|
||||
}
|
||||
|
||||
func applicationDidBecomeActive(_ application: UIApplication) {
|
||||
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
|
||||
}
|
||||
|
||||
func applicationWillTerminate(_ application: UIApplication) {
|
||||
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
|
||||
func relaunch(){
|
||||
appCoordinator.start()
|
||||
}
|
||||
}
|
||||
|
||||
|
21
GDproject/Supporting files/Assets.xcassets/chat.imageset/Contents.json
vendored
Normal file
21
GDproject/Supporting files/Assets.xcassets/chat.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "chat.pdf",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
GDproject/Supporting files/Assets.xcassets/chat.imageset/chat.pdf
vendored
Normal file
BIN
GDproject/Supporting files/Assets.xcassets/chat.imageset/chat.pdf
vendored
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user