git.iko.soy/dashared/GDproject
on master help sign in
Channels: preview bag left. Added new view for adding hashtags. Some minor changes in api.
commit6850d7679c0a8609cd3a84a56e4d9ec931f7fcea authorDarya Rednikina <rednikina.com@yandex.ru> dateFri 3 May 2019, 15:38 (7 years ago) parent24023c7
9 files changed+345−61
GDproject.xcodeproj/project.pbxproj+4 GDproject/Base.lproj/Main.storyboard+104−12 GDproject/Constants.swift+2 GDproject/Controller/ News and channels/AddToChannelVC.swift+41−26 GDproject/Controller/ News and channels/ChannelViewController.swift+16−10 GDproject/Controller/ News and channels/NewPostViewController.swift+22−4 GDproject/Controller/ News and channels/TaggsSelectionViewController.swift+106 GDproject/Controller/Coordinators/ChannelsCoordinator.swift+20 GDproject/Simple model/Model.swift+30−9
GDproject.xcodeproj/project.pbxproj+4
@@ -9,6 +9,7 @@
99/* Begin PBXBuildFile section */
1010 1210A0BB223940310080686D /* SimplifiedChannelsList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1210A0BA223940310080686D /* SimplifiedChannelsList.swift */; };
1111 121A8972226B1EAC005EE599 /* AnonimousChannelController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 121A8971226B1EAC005EE599 /* AnonimousChannelController.swift */; };
12+ 1220FF94227C41270092C6BC /* TaggsSelectionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1220FF93227C41270092C6BC /* TaggsSelectionViewController.swift */; };
1213 123E37A5221F1B3200F6E42A /* LogInViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 123E37A4221F1B3200F6E42A /* LogInViewController.swift */; };
1314 123E37A7221F1DD700F6E42A /* MainController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 123E37A6221F1DD700F6E42A /* MainController.swift */; };
1415 124CC7032221C00C009DF531 /* Model.swift in Sources */ = {isa = PBXBuildFile; fileRef = 124CC7022221C00C009DF531 /* Model.swift */; };
@@ -102,6 +103,7 @@
102103/* Begin PBXFileReference section */
103104 1210A0BA223940310080686D /* SimplifiedChannelsList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimplifiedChannelsList.swift; sourceTree = "<group>"; };
104105 121A8971226B1EAC005EE599 /* AnonimousChannelController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnonimousChannelController.swift; sourceTree = "<group>"; };
106+ 1220FF93227C41270092C6BC /* TaggsSelectionViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaggsSelectionViewController.swift; sourceTree = "<group>"; };
105107 123E37A4221F1B3200F6E42A /* LogInViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogInViewController.swift; sourceTree = "<group>"; };
106108 123E37A6221F1DD700F6E42A /* MainController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainController.swift; sourceTree = "<group>"; };
107109 124CC7022221C00C009DF531 /* Model.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Model.swift; sourceTree = "<group>"; };
@@ -311,6 +313,7 @@
311313 isa = PBXGroup;
312314 children = (
313315 1261BB92227B364C003898CF /* ChannelViewController.swift */,
316+ 1220FF93227C41270092C6BC /* TaggsSelectionViewController.swift */,
314317 1261BB94227B3991003898CF /* AddToChannelVC.swift */,
315318 12D7D134221C42B700B35452 /* ChannelController.swift */,
316319 121A8971226B1EAC005EE599 /* AnonimousChannelController.swift */,
@@ -411,6 +414,7 @@
411414 files = (
412415 129320072279B5690035C7B3 /* MessagesCoordinator.swift in Sources */,
413416 124CC7032221C00C009DF531 /* Model.swift in Sources */,
417+ 1220FF94227C41270092C6BC /* TaggsSelectionViewController.swift in Sources */,
414418 12F3D6B0224106F700A69214 /* TabbarController.swift in Sources */,
415419 12E36DD522156559006FCDD7 /* MyStackView.swift in Sources */,
416420 12D7D137221D78E800B35452 /* Channel.swift in Sources */,
GDproject/Base.lproj/Main.storyboard+104−12
@@ -379,33 +379,35 @@
379379 <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
380380 <subviews>
381381 <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="aRT-Du-PVE">
382− <rect key="frame" x="0.0" y="55" width="375" height="612"/>
382+ <rect key="frame" x="0.0" y="62" width="375" height="605"/>
383383 <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
384384 </view>
385− <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="368-bf-QU6">
386− <rect key="frame" x="0.0" y="20" width="375" height="35"/>
387− <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
385+ <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="bHv-9b-9uA">
386+ <rect key="frame" x="16" y="32" width="343" height="30"/>
388387 <constraints>
389− <constraint firstAttribute="height" constant="35" id="5ER-su-0Yf"/>
388+ <constraint firstAttribute="height" constant="30" id="QPs-3f-AfA"/>
390389 </constraints>
391− </view>
390+ <state key="normal" title="Edit hashtags"/>
391+ <connections>
392+ <action selector="chooseTags:" destination="uED-wX-77j" eventType="touchUpInside" id="jvf-w2-K2f"/>
393+ </connections>
394+ </button>
392395 </subviews>
393396 <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
394397 <constraints>
395398 <constraint firstItem="wxD-Ek-mgv" firstAttribute="trailing" secondItem="aRT-Du-PVE" secondAttribute="trailing" id="2ee-e8-G7A"/>
396− <constraint firstItem="368-bf-QU6" firstAttribute="leading" secondItem="wxD-Ek-mgv" secondAttribute="leading" id="9Rl-wh-kZf"/>
399+ <constraint firstItem="aRT-Du-PVE" firstAttribute="top" secondItem="bHv-9b-9uA" secondAttribute="bottom" id="6As-MU-bEh"/>
400+ <constraint firstItem="bHv-9b-9uA" firstAttribute="leading" secondItem="wxD-Ek-mgv" secondAttribute="leading" constant="16" id="OIV-hF-TBs"/>
401+ <constraint firstItem="bHv-9b-9uA" firstAttribute="top" secondItem="wxD-Ek-mgv" secondAttribute="top" constant="12" id="REt-Jv-IfH"/>
397402 <constraint firstItem="aRT-Du-PVE" firstAttribute="leading" secondItem="wxD-Ek-mgv" secondAttribute="leading" id="UBy-Ch-zSL"/>
398− <constraint firstItem="aRT-Du-PVE" firstAttribute="top" secondItem="368-bf-QU6" secondAttribute="bottom" id="WaE-kh-6w3"/>
399− <constraint firstItem="368-bf-QU6" firstAttribute="top" secondItem="wxD-Ek-mgv" secondAttribute="top" id="aI9-JQ-7dq"/>
400− <constraint firstItem="368-bf-QU6" firstAttribute="trailing" secondItem="wxD-Ek-mgv" secondAttribute="trailing" id="haz-0r-Cud"/>
403+ <constraint firstItem="wxD-Ek-mgv" firstAttribute="trailing" secondItem="bHv-9b-9uA" secondAttribute="trailing" constant="16" id="Ufp-mQ-Xeo"/>
401404 <constraint firstItem="wxD-Ek-mgv" firstAttribute="bottom" secondItem="aRT-Du-PVE" secondAttribute="bottom" id="x3f-eb-ACt"/>
402405 </constraints>
403406 <viewLayoutGuide key="safeArea" id="wxD-Ek-mgv"/>
404407 </view>
405408 <connections>
406409 <outlet property="bottomTextViewConstraint" destination="x3f-eb-ACt" id="ktT-im-InH"/>
407− <outlet property="view1" destination="aRT-Du-PVE" id="m3d-kW-vqW"/>
408− <outlet property="viewForTags" destination="368-bf-QU6" id="M5s-RZ-Fq7"/>
410+ <outlet property="view1" destination="aRT-Du-PVE" id="DXD-HR-NcE"/>
409411 </connections>
410412 </viewController>
411413 <placeholder placeholderIdentifier="IBFirstResponder" id="3fd-7N-vPg" userLabel="First Responder" sceneMemberID="firstResponder"/>
@@ -430,6 +432,96 @@
430432 </objects>
431433 <point key="canvasLocation" x="3444" y="129.98500749625188"/>
432434 </scene>
435+ <!--Taggs Selection View Controller-->
436+ <scene sceneID="74G-Lc-cqT">
437+ <objects>
438+ <viewController storyboardIdentifier="TaggsSelectionViewController" id="rQl-ri-9O8" customClass="TaggsSelectionViewController" customModule="GDproject" customModuleProvider="target" sceneMemberID="viewController">
439+ <view key="view" contentMode="scaleToFill" id="k3T-8B-NVf">
440+ <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
441+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
442+ <subviews>
443+ <containerView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="yeR-J3-ysT">
444+ <rect key="frame" x="16" y="131" width="343" height="142"/>
445+ <constraints>
446+ <constraint firstAttribute="height" constant="142" id="1By-sC-rMT"/>
447+ </constraints>
448+ </containerView>
449+ <containerView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="lEu-rZ-H6U">
450+ <rect key="frame" x="16" y="306" width="343" height="184"/>
451+ <constraints>
452+ <constraint firstAttribute="height" constant="184" id="F0W-3R-hCj"/>
453+ </constraints>
454+ </containerView>
455+ <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">
456+ <rect key="frame" x="16" y="28" width="73" height="21"/>
457+ <constraints>
458+ <constraint firstAttribute="height" constant="21" id="KZW-ld-K8d"/>
459+ </constraints>
460+ <fontDescription key="fontDescription" type="system" pointSize="17"/>
461+ <color key="textColor" red="0.43529411759999997" green="0.4431372549" blue="0.47450980390000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
462+ <nil key="highlightedColor"/>
463+ </label>
464+ <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">
465+ <rect key="frame" x="16" y="106" width="126" height="21"/>
466+ <constraints>
467+ <constraint firstAttribute="height" constant="21" id="ZJb-Aw-bLx"/>
468+ </constraints>
469+ <fontDescription key="fontDescription" type="system" pointSize="17"/>
470+ <color key="textColor" red="0.43529411759999997" green="0.4431372549" blue="0.47450980390000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
471+ <nil key="highlightedColor"/>
472+ </label>
473+ <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">
474+ <rect key="frame" x="16" y="281" width="101" height="21"/>
475+ <constraints>
476+ <constraint firstAttribute="height" constant="21" id="aT7-BK-i42"/>
477+ </constraints>
478+ <fontDescription key="fontDescription" type="system" pointSize="17"/>
479+ <color key="textColor" red="0.43529411759999997" green="0.4431372549" blue="0.47450980390000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
480+ <nil key="highlightedColor"/>
481+ </label>
482+ <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">
483+ <rect key="frame" x="16" y="57" width="343" height="30"/>
484+ <constraints>
485+ <constraint firstAttribute="height" constant="30" id="dBr-rd-Cg8"/>
486+ </constraints>
487+ <nil key="textColor"/>
488+ <fontDescription key="fontDescription" type="system" pointSize="14"/>
489+ <textInputTraits key="textInputTraits"/>
490+ </textField>
491+ </subviews>
492+ <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
493+ <constraints>
494+ <constraint firstItem="hvS-Ix-A23" firstAttribute="top" secondItem="BgX-NT-7NG" secondAttribute="bottom" constant="19" id="17U-ae-Gxa"/>
495+ <constraint firstItem="Oc2-oW-bST" firstAttribute="trailing" secondItem="yeR-J3-ysT" secondAttribute="trailing" constant="16" id="9gG-QD-LG4"/>
496+ <constraint firstItem="lxp-KC-Iua" firstAttribute="top" secondItem="yeR-J3-ysT" secondAttribute="bottom" constant="8" id="C3R-dM-Fzj"/>
497+ <constraint firstItem="uXC-Rm-Hek" firstAttribute="leading" secondItem="Oc2-oW-bST" secondAttribute="leading" constant="16" id="E6w-kw-7Uo"/>
498+ <constraint firstItem="Oc2-oW-bST" firstAttribute="trailing" secondItem="hvS-Ix-A23" secondAttribute="trailing" constant="233" id="GLM-Fj-UeZ"/>
499+ <constraint firstItem="Oc2-oW-bST" firstAttribute="trailing" secondItem="lxp-KC-Iua" secondAttribute="trailing" constant="258" id="Pbc-Ul-Bqf"/>
500+ <constraint firstItem="Oc2-oW-bST" firstAttribute="trailing" secondItem="uXC-Rm-Hek" secondAttribute="trailing" constant="286" id="Uc1-pS-uKg"/>
501+ <constraint firstItem="lEu-rZ-H6U" firstAttribute="top" secondItem="lxp-KC-Iua" secondAttribute="bottom" constant="4" id="aew-vr-F7L"/>
502+ <constraint firstItem="uXC-Rm-Hek" firstAttribute="top" secondItem="Oc2-oW-bST" secondAttribute="top" constant="8" id="dGW-ps-wNH"/>
503+ <constraint firstItem="lxp-KC-Iua" firstAttribute="leading" secondItem="Oc2-oW-bST" secondAttribute="leading" constant="16" id="gmr-z4-RMQ"/>
504+ <constraint firstItem="BgX-NT-7NG" firstAttribute="top" secondItem="uXC-Rm-Hek" secondAttribute="bottom" constant="8" id="jqp-Lv-waU"/>
505+ <constraint firstItem="yeR-J3-ysT" firstAttribute="top" secondItem="hvS-Ix-A23" secondAttribute="bottom" constant="4" id="nZ3-oH-0AF"/>
506+ <constraint firstItem="Oc2-oW-bST" firstAttribute="trailing" secondItem="BgX-NT-7NG" secondAttribute="trailing" constant="16" id="pPk-Ih-GDO"/>
507+ <constraint firstItem="yeR-J3-ysT" firstAttribute="leading" secondItem="Oc2-oW-bST" secondAttribute="leading" constant="16" id="qBn-xg-Ioc"/>
508+ <constraint firstItem="lEu-rZ-H6U" firstAttribute="leading" secondItem="Oc2-oW-bST" secondAttribute="leading" constant="16" id="qCJ-rc-qBq"/>
509+ <constraint firstItem="Oc2-oW-bST" firstAttribute="trailing" secondItem="lEu-rZ-H6U" secondAttribute="trailing" constant="16" id="vaR-Zr-5nI"/>
510+ <constraint firstItem="hvS-Ix-A23" firstAttribute="leading" secondItem="Oc2-oW-bST" secondAttribute="leading" constant="16" id="vcb-xj-bM8"/>
511+ <constraint firstItem="BgX-NT-7NG" firstAttribute="leading" secondItem="Oc2-oW-bST" secondAttribute="leading" constant="16" id="xOL-J4-JIV"/>
512+ </constraints>
513+ <viewLayoutGuide key="safeArea" id="Oc2-oW-bST"/>
514+ </view>
515+ <connections>
516+ <outlet property="addTagsTextField" destination="BgX-NT-7NG" id="3vt-U9-NYI"/>
517+ <outlet property="searchContainerView" destination="yeR-J3-ysT" id="SzT-fM-A6H"/>
518+ <outlet property="testContainer" destination="lEu-rZ-H6U" id="DTe-9O-VAi"/>
519+ </connections>
520+ </viewController>
521+ <placeholder placeholderIdentifier="IBFirstResponder" id="eoH-1e-A6A" userLabel="First Responder" sceneMemberID="firstResponder"/>
522+ </objects>
523+ <point key="canvasLocation" x="4293.6000000000004" y="132.68365817091455"/>
524+ </scene>
433525 <!--Messages View Controller-->
434526 <scene sceneID="WSW-fr-Vf8">
435527 <objects>
GDproject/Constants.swift+2
@@ -59,5 +59,7 @@ let channelViewControllerId = "ChannelViewController"
5959
6060let addToChannelVCId = "AddToChannelVC"
6161
62+let taggsSelectionViewController = "TaggsSelectionViewController"
63+
6264let blueSystemColor = UIColor(red: 0, green: 137/255, blue: 249/255, alpha: 0.5)
6365
GDproject/Controller/ News and channels/AddToChannelVC.swift+41−26
@@ -15,35 +15,42 @@ enum DataSourse{
1515class AddToChannelVC: UITableViewController {
1616
1717 var channel: Model.Channels?
18− var dataSourse: DataSourse = .people
1918 weak var update: UpdatableChannel?
2019
2120 // data sources for people and hashtags
2221 var dataSourcePeople: [Model.Users] = Model.Channels.fullPeople
23− var fullTags: [String] = CompletionTree.getCompletion(tree: Model.hashTagTree!, word: "")
24−
2522
2623 var reloadtable: Bool = false {
2724 didSet{
2825 tableView.reloadData()
2926 }
3027 }
28+
29+ var filteredDataSource = [Model.Users]()
30+
31+ func filterContentForSearchText(_ searchText: String, scope: String = "All")
32+ {
33+ filteredDataSource = dataSourcePeople.filter { $0.fullName().lowercased().contains(searchText.lowercased()) }
34+ tableView.reloadData()
35+ }
3136
3237 let searchC = UISearchController(searchResultsController: nil)
3338
3439 override func viewDidLoad() {
3540 super.viewDidLoad()
3641
42+ navigationItem.title = "People"
3743 tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
3844 self.navigationItem.searchController = searchC
3945 navigationItem.largeTitleDisplayMode = .never
4046 self.navigationItem.hidesSearchBarWhenScrolling = false
41−
47+ definesPresentationContext = true
48+ searchC.searchResultsUpdater = self
49+ searchC.obscuresBackgroundDuringPresentation = false
4250 }
4351
4452 override func viewWillDisappear(_ animated: Bool) {
4553 super.viewWillDisappear(animated)
46−
4754 update?.updateChannel(with: channel!)
4855 }
4956 // MARK: - Table view data source
@@ -52,12 +59,19 @@ class AddToChannelVC: UITableViewController {
5259 return 1
5360 }
5461
62+ var isFiltering: Bool {
63+ return searchC.isActive && !searchBarIsEmpty()
64+ }
65+
66+ func searchBarIsEmpty() -> Bool {
67+ return searchC.searchBar.text?.isEmpty ?? true
68+ }
69+
5570 override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
56− switch dataSourse {
57− case .people:
71+ if isFiltering {
72+ return filteredDataSource.count
73+ } else {
5874 return dataSourcePeople.count
59− default:
60− return fullTags.count
6175 }
6276 }
6377
@@ -65,17 +79,16 @@ class AddToChannelVC: UITableViewController {
6579 {
6680 let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
6781
68− switch dataSourse {
69− case .people:
70− cell.textLabel?.text = dataSourcePeople[indexPath.row].fullName()
71− if channel!.people.contains(dataSourcePeople[indexPath.row].id) {
82+ if isFiltering{
83+ cell.textLabel?.text = filteredDataSource[indexPath.row].fullName()
84+ if channel!.people.contains(filteredDataSource[indexPath.row].id) {
7285 cell.backgroundColor = #colorLiteral(red: 0.4745098054, green: 0.8392156959, blue: 0.9764705896, alpha: 1)
7386 } else {
7487 cell.backgroundColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)
7588 }
76− default:
77− cell.textLabel?.text = "# \(fullTags[indexPath.row])"
78− if channel!.tags.contains(fullTags[indexPath.row]) {
89+ } else {
90+ cell.textLabel?.text = dataSourcePeople[indexPath.row].fullName()
91+ if channel!.people.contains(dataSourcePeople[indexPath.row].id) {
7992 cell.backgroundColor = #colorLiteral(red: 0.4745098054, green: 0.8392156959, blue: 0.9764705896, alpha: 1)
8093 } else {
8194 cell.backgroundColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)
@@ -89,29 +102,31 @@ class AddToChannelVC: UITableViewController {
89102
90103 override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
91104 if let cell = tableView.cellForRow(at: indexPath) {
92− switch dataSourse {
93− case .people:
105+ if isFiltering{
94106 if cell.backgroundColor == #colorLiteral(red: 0.4745098054, green: 0.8392156959, blue: 0.9764705896, alpha: 1) {
95− let filtered = channel!.people.filter{ $0 != dataSourcePeople[indexPath.row].id }
107+ let filtered = channel!.people.filter{ $0 != filteredDataSource[indexPath.row].id }
96108 channel?.people = filtered
97109 cell.backgroundColor = #colorLiteral(red: 0.9999960065, green: 1, blue: 1, alpha: 1)
98110 } else {
99− channel?.people.append(dataSourcePeople[indexPath.row].id)
111+ channel?.people.append(filteredDataSource[indexPath.row].id)
100112 cell.backgroundColor = #colorLiteral(red: 0.4745098054, green: 0.8392156959, blue: 0.9764705896, alpha: 1)
101113 }
102− default: //tags
114+ } else {
103115 if cell.backgroundColor == #colorLiteral(red: 0.4745098054, green: 0.8392156959, blue: 0.9764705896, alpha: 1) {
104− let filtered = channel!.tags.filter{
105− !fullTags[indexPath.row].contains($0)
106− }
107− channel?.tags = filtered
116+ let filtered = channel!.people.filter{ $0 != dataSourcePeople[indexPath.row].id }
117+ channel?.people = filtered
108118 cell.backgroundColor = #colorLiteral(red: 0.9999960065, green: 1, blue: 1, alpha: 1)
109119 } else {
110− channel?.tags.append(fullTags[indexPath.row])
120+ channel?.people.append(dataSourcePeople[indexPath.row].id)
111121 cell.backgroundColor = #colorLiteral(red: 0.4745098054, green: 0.8392156959, blue: 0.9764705896, alpha: 1)
112122 }
113123 }
114124 }
115125 }
126+}
116127
128+extension AddToChannelVC : UISearchResultsUpdating {
129+ func updateSearchResults(for searchController: UISearchController) {
130+ filterContentForSearchText(searchController.searchBar.text!)
131+ }
117132}
GDproject/Controller/ News and channels/ChannelViewController.swift+16−10
@@ -16,7 +16,15 @@ protocol UpdatableChannel: class{
1616 func updateChannel(with channel: Model.Channels)
1717}
1818
19−class ChannelViewController: UITableViewController, UpdatableName, UpdatableChannel {
19+class ChannelViewController: UITableViewController, UpdatableName, UpdatableChannel, TagsReceiver
20+{
21+ var onChoosingHashTags: (([String]?)->())?
22+
23+ var onChoosingPeople: ((Model.Channels?)->())?
24+
25+ func receiveTags(tags: [String]) {
26+ self.channel?.tags = tags
27+ }
2028
2129 func updateName(with name: String){
2230 channel?.name = name
@@ -34,7 +42,7 @@ class ChannelViewController: UITableViewController, UpdatableName, UpdatableChan
3442 override func viewDidLoad()
3543 {
3644 super.viewDidLoad()
37−
45+ tableView.keyboardDismissMode = .onDrag
3846 navigationItem.rightBarButtonItems = [ UIBarButtonItem(barButtonSystemItem: .play, target: self, action: #selector(showPreview)), self.editButtonItem]
3947 navigationItem.largeTitleDisplayMode = .never
4048 tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
@@ -160,15 +168,13 @@ class ChannelViewController: UITableViewController, UpdatableName, UpdatableChan
160168
161169 override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
162170 {
163− if indexPath.row == 0 && indexPath.section != 0
171+ if indexPath.row == 0 && indexPath.section == 1
164172 {
165− let vc = storyboard?.instantiateViewController(withIdentifier: addToChannelVCId) as! AddToChannelVC
166−
167− vc.dataSourse = indexPath.section == 1 ? .people : .tags
168− vc.channel = channel
169− vc.update = self
170−
171− navigationController?.pushViewController(vc, animated: true)
173+ onChoosingPeople?(channel)
174+ }
175+
176+ if indexPath.row == 0 && indexPath.section == 2 {
177+ onChoosingHashTags?(channel?.tags)
172178 }
173179 }
174180}
GDproject/Controller/ News and channels/NewPostViewController.swift+22−4
@@ -10,20 +10,38 @@ import UIKit
1010import Cartography
1111import Marklight
1212import TinyConstraints
13+import TaggerKit
1314// import WSTagsField
1415
15−class NewPostViewController: UIViewController, UITextViewDelegate {
16+class NewPostViewController: UIViewController, UITextViewDelegate, TagsReceiver
17+{
18+ func receiveTags(tags: [String]) {
19+ currentTags = tags
20+ }
1621
1722 @IBOutlet weak var view1: UIView!
1823
19− @IBOutlet weak var viewForTags: UIView!
24+ var currentTags: [String] = []
25+
26+ // We want the whole experience, let's create two TKCollectionViews
27+ let productTags = TKCollectionView()
28+
29+ @IBAction func chooseTags(_ sender: UIButton) {
30+ let vc = storyboard?.instantiateViewController(withIdentifier: taggsSelectionViewController) as! TaggsSelectionViewController
31+
32+ NewPostViewController.draft = textView.text
33+ vc.receiver = self
34+ vc.currentTags = currentTags
35+
36+ navigationController?.pushViewController(vc, animated: true)
37+ }
2038
2139 // fileprivate let tagsField = WSTagsField()
2240 // Keep strong instance of the `NSTextStorage` subclass
2341 let textStorage = MarklightTextStorage()
2442
2543 static var draft: String = ""
26− static var hashTagsDraft: [String] = []
44+ static var hashTagsDraft: [String] = ["tt"]
2745
2846 var textView: UITextView!
2947
@@ -213,7 +231,7 @@ class NewPostViewController: UIViewController, UITextViewDelegate {
213231 var indexOfPost = 0
214232 // MARK:- new post
215233 @objc func newPost(){
216− Model.createAndPublish(body: [Model.Attachments(markdown: textView!.text)], tags: /*tagsField.tags.map { $0.text }*/ [])
234+ Model.createAndPublish(body: [Model.Attachments(markdown: textView!.text)], tags: currentTags)
217235 // adding row to uiTableView after adding new post
218236 // myProtocol?.addPost(post: p)
219237 moveBackToParentVC?()
GDproject/Controller/ News and channels/TaggsSelectionViewController.swiftnew file+106
@@ -0,0 +1,106 @@
1+//
2+// TaggsSelectionViewController.swift
3+// GDproject
4+//
5+// Created by cstore on 03/05/2019.
6+// Copyright © 2019 drHSE. All rights reserved.
7+//
8+
9+import UIKit
10+import TaggerKit
11+
12+protocol TagsReceiver: class {
13+ func receiveTags(tags: [String])
14+}
15+
16+class TaggsSelectionViewController: UIViewController {
17+
18+ @IBOutlet weak var addTagsTextField: TKTextField!
19+
20+ @IBOutlet weak var searchContainerView: UIView!
21+
22+ @IBOutlet weak var testContainer: UIView!
23+
24+ // We want the whole experience, let's create two TKCollectionViews
25+ let productTags = TKCollectionView()
26+ let allTags = TKCollectionView()
27+
28+ var currentTags: [String]?
29+ weak var receiver: TagsReceiver?
30+
31+ // MARK: - Lifecycle Methods
32+ override func viewDidLoad() {
33+ super.viewDidLoad()
34+
35+ navigationItem.title = "Hashtags"
36+ addTagsTextField.delegate = self
37+ // Customisation example
38+ // testCollection.customFont = UIFont.boldSystemFont(ofSize: 14) // Custom font
39+ // testCollection.customCornerRadius = 14.0 // Corner radius of tags
40+ // testCollection.customSpacing = 20.0 // Spacing between cells
41+ // testCollection.customBackgroundColor = UIColor.red // Background of cells
42+
43+
44+ // These are the tags already added by the user, give an aray of strings to the collection
45+ if let tags = currentTags {
46+ productTags.tags = tags
47+ }
48+ // These are intended to be all the tags the user has added in the app, which are going to be filtered
49+ allTags.tags = CompletionTree.getCompletion(tree: Model.hashTagTree!, word: "")
50+
51+ /*
52+ We set this collection's action to .removeTag,
53+ becasue these are supposed to be the tags the user has already added
54+ */
55+ productTags.action = .removeTag
56+
57+
58+ // Set the current controller as the delegate of both collections
59+ productTags.delegate = self
60+ allTags.delegate = self
61+
62+ // "testCollection" takes the tags sent by "searchCollection"
63+ allTags.receiver = productTags
64+
65+ // The tags in "searchCollection" are going to be added, so we set the action to addTag
66+ allTags.action = .addTag
67+
68+
69+ // Set the sender and receiver of the TextField
70+ addTagsTextField.sender = allTags
71+ addTagsTextField.receiver = productTags
72+
73+ add(productTags, toView: testContainer)
74+ add(allTags, toView: searchContainerView)
75+ }
76+
77+ override func viewWillDisappear(_ animated: Bool) {
78+ super.viewWillDisappear(animated)
79+ if let receiver = receiver{
80+ receiver.receiveTags(tags: productTags.tags)
81+ }
82+ }
83+
84+ /*
85+ These methods come from UIViewController now conforming to TKCollectionViewDelegate,
86+ You use these to do whatever you want when a tag is added or removed (e.g. save to file, etc)
87+ */
88+ override func tagIsBeingAdded(name: String?) {
89+ // Example: save testCollection.tags to UserDefault
90+ print("added \(name!)")
91+ }
92+
93+ override func tagIsBeingRemoved(name: String?) {
94+ print("removed \(name!)")
95+ }
96+}
97+
98+// textField deletage to close keyboard on return
99+extension TaggsSelectionViewController: UITextFieldDelegate
100+{
101+ func textFieldShouldReturn(_ textField: UITextField) -> Bool
102+ {
103+ self.view.endEditing(true)
104+ return false
105+ }
106+}
GDproject/Controller/Coordinators/ChannelsCoordinator.swift+20
@@ -55,6 +55,26 @@ class ChannelsCoordinator: BaseCoordinator{
5555 let vc = self.presentNewsController(with: ch, previewMode: true)
5656 mainContentVC?.navigationController?.pushViewController(vc, animated: true)
5757 }
58+
59+ // to go for choosing hashtags
60+ mainContentVC.onChoosingHashTags = { [weak mainContentVC, unowned self] ch in
61+ let vc = self.storyboard.instantiateViewController(withIdentifier: taggsSelectionViewController) as! TaggsSelectionViewController
62+
63+ vc.currentTags = ch
64+ vc.receiver = mainContentVC
65+
66+ self.navigationController?.pushViewController(vc, animated: true)
67+ }
68+
69+ mainContentVC.onChoosingPeople = { [weak mainContentVC, unowned self] channel in
70+ let vc = self.storyboard.instantiateViewController(withIdentifier: addToChannelVCId) as! AddToChannelVC
71+
72+ vc.channel = channel
73+ vc.update = mainContentVC
74+
75+ self.navigationController?.pushViewController(vc, animated: true)
76+ }
77+
5878 mainContentVC.channel = channel
5979 return mainContentVC
6080 }
GDproject/Simple model/Model.swift+30−9
@@ -41,6 +41,15 @@ class Model{
4141 static let channelsGetAnonURL = URL(string: "\(baseUrl)/channels/getAnonymous")!
4242 static let complexURL = URL(string: "\(baseUrl)/complex")!
4343 static let hashTagTreeURL = URL(string: "\(baseUrl)/tagCompletions")!
44+ static let createGroupChatURL = URL(string: "\(baseUrl)/chats/createGroupChat")!
45+ static let chatsGetAllURL = URL(string: "\(baseUrl)/chats/getAll")!
46+ static let getGroupChatURL = URL(string: "\(baseUrl)/chats/getGroupChat")!
47+ static let leaveGroupChatURL = URL(string: "\(baseUrl)/chats/leaveGroupChat")!
48+ static let updateGroupChatURL = URL(string: "\(baseUrl)/chats/updateGroupChat")!
49+ static let messagesGetGroupChatURL = URL(string: "\(baseUrl)/messages/get/groupChat")! //r
50+ static let messagesSendURL = URL(string: "\(baseUrl)/messages/send")!
51+ static let messagesUserChatURL = URL(string: "\(baseUrl)/messages/userChat")!
52+
4453
4554 struct QueryPosts: Codable {
4655 var users: [Int: Users]
@@ -212,15 +221,25 @@ class Model{
212221 }
213222 }
214223
215− struct PostsLastRequest<T: Codable>: Codable {
224+ struct GeneralRequest<T: Codable>: Codable
225+ {
226+ var direction: String
216227 var limit: Int
217228 var exclusiveFrom: Int?
218229 var request: T
219230
231+ init(direction: String = "backward", limit: Int, exclusiveFrom: Int?, request: T) {
232+ self.direction = direction
233+ self.limit = limit
234+ self.exclusiveFrom = exclusiveFrom
235+ self.request = request
236+ }
237+
220238 enum CodingKeys: String, CodingKey {
221239 case limit
222240 case exclusiveFrom
223241 case request
242+ case direction
224243 }
225244
226245 func encode(to encoder: Encoder) throws {
@@ -228,12 +247,13 @@ class Model{
228247 try container.encode(limit, forKey: .limit)
229248 try container.encode(exclusiveFrom, forKey: .exclusiveFrom)
230249 try container.encode(request, forKey: .request)
250+ try container.encode(direction, forKey: .direction)
231251 }
232252 }
233253
234254 static func getLast(on limit: Int = 10, from pointInTime: Int? = nil, completion: @escaping (((users:[Int: Users], posts:[Posts]))->()))
235255 {
236− let postRequest = PostsLastRequest<[Int]>(limit: limit, exclusiveFrom: pointInTime, request: [])
256+ let postRequest = GeneralRequest<[Int]>(limit: limit, exclusiveFrom: pointInTime, request: [])
237257
238258 var request = URLRequest(url: postsLastURL)
239259 request.httpBody = try? JSONEncoder().encode(postRequest)
@@ -275,14 +295,15 @@ class Model{
275295 }
276296 }
277297
298+// static func requestForPosts(limit: Int = 10, ){
299+//
300+// }
278301
279− static func getPostsForUser(with id: Int, completion: @escaping (([Posts])->())){
280− let json = [
281− "request" : id,
282− "limit": 10
283− ]
302+ static func getPostsForUser(for limit: Int = 10, from pointInTime: Int? = nil, with id: Int, completion: @escaping (([Posts])->()))
303+ {
304+ let postsRequest = GeneralRequest<Int>(limit: limit, exclusiveFrom: pointInTime, request: id)
284305
285− let jsonData = try? JSONSerialization.data(withJSONObject: json)
306+ let jsonData = try? JSONEncoder().encode(postsRequest)
286307
287308 var request = URLRequest(url: postsForUserURL)
288309 request.httpMethod = "POST"
@@ -338,7 +359,7 @@ class Model{
338359 // get channel (with id): in responce -- PostQuery
339360 static func getChannel(with channelId: Int, on limit: Int = 10, from pointInTime: Int? = nil, completion: @escaping (((users:[Int: Users], posts:[Posts]))->()))
340361 {
341− let postRequest = PostsLastRequest<Int>(limit: limit, exclusiveFrom: pointInTime, request: channelId)
362+ let postRequest = GeneralRequest<Int>(limit: limit, exclusiveFrom: pointInTime, request: channelId)
342363 let jsonData = try? JSONEncoder().encode(postRequest)
343364
344365 var request = URLRequest(url: channelsGetURL)