git.iko.soy/dashared/GDproject
on master help sign in
Channels: pull request #3 from dashared/developer

Channels are added

commitf5ee61b7182d9983d7618d85afc3fe08d23774b2 authorDarya Rednikina <31587869+dashared@users.noreply.github.com> dateSat 23 Feb 2019, 17:16 (8 years ago) parentcb2b3ac13f2878
27 files changed+1134−243
GDproject.xcodeproj/project.pbxproj+57−18 GDproject/Base.lproj/Main.storyboard+179−36 GDproject/Constants.swift+25−3 GDproject/Controller/ News and channels/ChannelController.swift+226 GDproject/Controller/ News and channels/ChannelListController.swift+185 GDproject/Controller/ News and channels/ChannelsCoordinator.swift+55 GDproject/Controller/News/FullPostController.swift → GDproject/Controller/ News and channels/FullPostController.swift GDproject/Controller/News/NewPostViewController.swift → GDproject/Controller/ News and channels/NewPostViewController.swift+15−17 GDproject/Controller/News/NewsController.swift → GDproject/Controller/ News and channels/NewsController.swift+64−36 GDproject/Controller/News/NewsVC.swift → GDproject/Controller/ News and channels/NewsVC.swift+5−33 GDproject/Controller/News/PostViewCell.swift → GDproject/Controller/ News and channels/PostViewCell.swift GDproject/Controller/Coordinator tab bar?/TabbarCoordinator.swift+13 GDproject/Controller/LogInViewController.swift+138 GDproject/Controller/News/ChannelsController.swift−35 GDproject/Controller/News/HeaderNewsChannels.swift−54 GDproject/Controller/BasicInfoCell.swift → GDproject/Controller/Profile/BasicInfoCell.swift GDproject/Controller/BasicInfoController.swift → GDproject/Controller/Profile/BasicInfoController.swift GDproject/Controller/InfoCell.swift → GDproject/Controller/Profile/InfoCell.swift GDproject/Controller/InviteViewController.swift → GDproject/Controller/Profile/InviteViewController.swift GDproject/Controller/ProfileViewController.swift → GDproject/Controller/Profile/ProfileViewController.swift+2−3 GDproject/Controller/SettingsViewController.swift → GDproject/Controller/Profile/SettingsViewController.swift GDproject/DataStorage.swift+45 GDproject/Extentions.swift+22 GDproject/MainController.swift+44 GDproject/Simple model/Channel.swift+35 GDproject/Supporting files/AppDelegate.swift+17−5 GDproject/Supporting files/Base.lproj/LaunchScreen.storyboard+7−3
GDproject.xcodeproj/project.pbxproj+57−18
@@ -7,9 +7,17 @@
77 objects = {
88
99/* Begin PBXBuildFile section */
10+ 123E37A5221F1B3200F6E42A /* LogInViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 123E37A4221F1B3200F6E42A /* LogInViewController.swift */; };
11+ 123E37A7221F1DD700F6E42A /* MainController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 123E37A6221F1DD700F6E42A /* MainController.swift */; };
1012 125BD57D22171D2A008A3575 /* ProfileViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 125BD57C22171D2A008A3575 /* ProfileViewController.swift */; };
1113 125BD57F22171D73008A3575 /* Extentions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 125BD57E22171D73008A3575 /* Extentions.swift */; };
1214 125BD5812217314A008A3575 /* NewsVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 125BD5802217314A008A3575 /* NewsVC.swift */; };
15+ 1288B5CE221F1158002BE6B1 /* DataStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1288B5CD221F1158002BE6B1 /* DataStorage.swift */; };
16+ 1291BE2D2221312D009D3F23 /* ChannelsCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1291BE2C2221312C009D3F23 /* ChannelsCoordinator.swift */; };
17+ 1291BE342221569B009D3F23 /* TabbarCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1291BE332221569B009D3F23 /* TabbarCoordinator.swift */; };
18+ 12D7D133221C321600B35452 /* ChannelListController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12D7D132221C321600B35452 /* ChannelListController.swift */; };
19+ 12D7D135221C42B700B35452 /* ChannelController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12D7D134221C42B700B35452 /* ChannelController.swift */; };
20+ 12D7D137221D78E800B35452 /* Channel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12D7D136221D78E800B35452 /* Channel.swift */; };
1321 12DB7FD722181CD20096878E /* BasicInfoController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12DB7FD622181CD20096878E /* BasicInfoController.swift */; };
1422 12DB7FD922181E660096878E /* BasicInfoCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12DB7FD822181E660096878E /* BasicInfoCell.swift */; };
1523 12DB7FDB2218590C0096878E /* InfoCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12DB7FDA2218590C0096878E /* InfoCell.swift */; };
@@ -29,8 +37,6 @@
2937 12E36DC0221441DB006FCDD7 /* Marklight.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 12E36DB222143D4E006FCDD7 /* Marklight.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
3038 12E36DC2221441E1006FCDD7 /* MarkdownKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 12E36DB022143D47006FCDD7 /* MarkdownKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
3139 12E36DC4221441EA006FCDD7 /* Cartography.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 12E36DAE22143D40006FCDD7 /* Cartography.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
32− 12E36DC622144266006FCDD7 /* HeaderNewsChannels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12E36DC522144266006FCDD7 /* HeaderNewsChannels.swift */; };
33− 12E36DC822144374006FCDD7 /* ChannelsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12E36DC722144374006FCDD7 /* ChannelsController.swift */; };
3440 12E36DCA22144635006FCDD7 /* NewPostViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12E36DC922144635006FCDD7 /* NewPostViewController.swift */; };
3541 12E36DCC22144725006FCDD7 /* PostViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12E36DCB22144725006FCDD7 /* PostViewCell.swift */; };
3642 12E36DCE22144756006FCDD7 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12E36DCD22144756006FCDD7 /* Constants.swift */; };
@@ -60,9 +66,17 @@
6066/* End PBXCopyFilesBuildPhase section */
6167
6268/* Begin PBXFileReference section */
69+ 123E37A4221F1B3200F6E42A /* LogInViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogInViewController.swift; sourceTree = "<group>"; };
70+ 123E37A6221F1DD700F6E42A /* MainController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainController.swift; sourceTree = "<group>"; };
6371 125BD57C22171D2A008A3575 /* ProfileViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileViewController.swift; sourceTree = "<group>"; };
6472 125BD57E22171D73008A3575 /* Extentions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Extentions.swift; sourceTree = "<group>"; };
6573 125BD5802217314A008A3575 /* NewsVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewsVC.swift; sourceTree = "<group>"; };
74+ 1288B5CD221F1158002BE6B1 /* DataStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataStorage.swift; sourceTree = "<group>"; };
75+ 1291BE2C2221312C009D3F23 /* ChannelsCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChannelsCoordinator.swift; sourceTree = "<group>"; };
76+ 1291BE332221569B009D3F23 /* TabbarCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabbarCoordinator.swift; sourceTree = "<group>"; };
77+ 12D7D132221C321600B35452 /* ChannelListController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChannelListController.swift; sourceTree = "<group>"; };
78+ 12D7D134221C42B700B35452 /* ChannelController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChannelController.swift; sourceTree = "<group>"; };
79+ 12D7D136221D78E800B35452 /* Channel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Channel.swift; sourceTree = "<group>"; };
6680 12DB7FD622181CD20096878E /* BasicInfoController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BasicInfoController.swift; sourceTree = "<group>"; };
6781 12DB7FD822181E660096878E /* BasicInfoCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BasicInfoCell.swift; sourceTree = "<group>"; };
6882 12DB7FDA2218590C0096878E /* InfoCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfoCell.swift; sourceTree = "<group>"; };
@@ -81,8 +95,6 @@
8195 12E36DB422143D54006FCDD7 /* TinyConstraints.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = TinyConstraints.framework; path = Carthage/Build/iOS/TinyConstraints.framework; sourceTree = "<group>"; };
8296 12E36DB62214400A006FCDD7 /* Post.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Post.swift; sourceTree = "<group>"; };
8397 12E36DB822144016006FCDD7 /* User.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = User.swift; sourceTree = "<group>"; };
84− 12E36DC522144266006FCDD7 /* HeaderNewsChannels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeaderNewsChannels.swift; sourceTree = "<group>"; };
85− 12E36DC722144374006FCDD7 /* ChannelsController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChannelsController.swift; sourceTree = "<group>"; };
8698 12E36DC922144635006FCDD7 /* NewPostViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewPostViewController.swift; sourceTree = "<group>"; };
8799 12E36DCB22144725006FCDD7 /* PostViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostViewCell.swift; sourceTree = "<group>"; };
88100 12E36DCD22144756006FCDD7 /* Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = "<group>"; };
@@ -107,6 +119,27 @@
107119/* End PBXFrameworksBuildPhase section */
108120
109121/* Begin PBXGroup section */
122+ 1288B5CC221F0EFE002BE6B1 /* Profile */ = {
123+ isa = PBXGroup;
124+ children = (
125+ 125BD57C22171D2A008A3575 /* ProfileViewController.swift */,
126+ 12DB7FDE221877160096878E /* InviteViewController.swift */,
127+ 12DB7FDC221872F80096878E /* SettingsViewController.swift */,
128+ 12DB7FD622181CD20096878E /* BasicInfoController.swift */,
129+ 12DB7FDA2218590C0096878E /* InfoCell.swift */,
130+ 12DB7FD822181E660096878E /* BasicInfoCell.swift */,
131+ );
132+ path = Profile;
133+ sourceTree = "<group>";
134+ };
135+ 1291BE32222154C3009D3F23 /* Coordinator tab bar? */ = {
136+ isa = PBXGroup;
137+ children = (
138+ 1291BE332221569B009D3F23 /* TabbarCoordinator.swift */,
139+ );
140+ path = "Coordinator tab bar?";
141+ sourceTree = "<group>";
142+ };
110143 12E36D8F221424EA006FCDD7 = {
111144 isa = PBXGroup;
112145 children = (
@@ -132,6 +165,8 @@
132165 12E36D9A221424EA006FCDD7 /* GDproject */ = {
133166 isa = PBXGroup;
134167 children = (
168+ 1288B5CD221F1158002BE6B1 /* DataStorage.swift */,
169+ 123E37A6221F1DD700F6E42A /* MainController.swift */,
135170 12E36DCF22145923006FCDD7 /* Controller */,
136171 12E36DCD22144756006FCDD7 /* Constants.swift */,
137172 125BD57E22171D73008A3575 /* Extentions.swift */,
@@ -148,6 +183,7 @@
148183 isa = PBXGroup;
149184 children = (
150185 12E36DB62214400A006FCDD7 /* Post.swift */,
186+ 12D7D136221D78E800B35452 /* Channel.swift */,
151187 12E36DB822144016006FCDD7 /* User.swift */,
152188 );
153189 path = "Simple model";
@@ -166,29 +202,27 @@
166202 12E36DCF22145923006FCDD7 /* Controller */ = {
167203 isa = PBXGroup;
168204 children = (
169− 125BD57C22171D2A008A3575 /* ProfileViewController.swift */,
170− 12DB7FDE221877160096878E /* InviteViewController.swift */,
171− 12DB7FDC221872F80096878E /* SettingsViewController.swift */,
172− 12DB7FD622181CD20096878E /* BasicInfoController.swift */,
173− 12DB7FDA2218590C0096878E /* InfoCell.swift */,
174− 12DB7FD822181E660096878E /* BasicInfoCell.swift */,
175− 12E36DD322156519006FCDD7 /* News */,
205+ 1291BE32222154C3009D3F23 /* Coordinator tab bar? */,
206+ 123E37A4221F1B3200F6E42A /* LogInViewController.swift */,
207+ 1288B5CC221F0EFE002BE6B1 /* Profile */,
208+ 12E36DD322156519006FCDD7 /* News and channels */,
176209 );
177210 path = Controller;
178211 sourceTree = "<group>";
179212 };
180− 12E36DD322156519006FCDD7 /* News */ = {
213+ 12E36DD322156519006FCDD7 /* News and channels */ = {
181214 isa = PBXGroup;
182215 children = (
216+ 12D7D134221C42B700B35452 /* ChannelController.swift */,
217+ 12D7D132221C321600B35452 /* ChannelListController.swift */,
183218 12E36DC922144635006FCDD7 /* NewPostViewController.swift */,
184219 12E36DD022148122006FCDD7 /* FullPostController.swift */,
185− 12E36DC522144266006FCDD7 /* HeaderNewsChannels.swift */,
186− 12E36DC722144374006FCDD7 /* ChannelsController.swift */,
187220 12E36D9D221424EA006FCDD7 /* NewsController.swift */,
221+ 1291BE2C2221312C009D3F23 /* ChannelsCoordinator.swift */,
188222 125BD5802217314A008A3575 /* NewsVC.swift */,
189223 12E36DCB22144725006FCDD7 /* PostViewCell.swift */,
190224 );
191− path = News;
225+ path = " News and channels";
192226 sourceTree = "<group>";
193227 };
194228 12E36DDA221594B1006FCDD7 /* Frameworks */ = {
@@ -271,25 +305,30 @@
271305 buildActionMask = 2147483647;
272306 files = (
273307 12E36DD522156559006FCDD7 /* MyStackView.swift in Sources */,
274− 12E36DC822144374006FCDD7 /* ChannelsController.swift in Sources */,
308+ 12D7D137221D78E800B35452 /* Channel.swift in Sources */,
275309 12E36DB922144016006FCDD7 /* User.swift in Sources */,
276310 125BD5812217314A008A3575 /* NewsVC.swift in Sources */,
277311 12E36DB72214400A006FCDD7 /* Post.swift in Sources */,
278312 12DB7FDF221877160096878E /* InviteViewController.swift in Sources */,
279313 12E36DCA22144635006FCDD7 /* NewPostViewController.swift in Sources */,
280314 12E36D9E221424EA006FCDD7 /* NewsController.swift in Sources */,
281− 12E36DC622144266006FCDD7 /* HeaderNewsChannels.swift in Sources */,
282315 12E36DCC22144725006FCDD7 /* PostViewCell.swift in Sources */,
316+ 123E37A5221F1B3200F6E42A /* LogInViewController.swift in Sources */,
283317 125BD57F22171D73008A3575 /* Extentions.swift in Sources */,
318+ 12D7D133221C321600B35452 /* ChannelListController.swift in Sources */,
319+ 1291BE342221569B009D3F23 /* TabbarCoordinator.swift in Sources */,
320+ 1291BE2D2221312D009D3F23 /* ChannelsCoordinator.swift in Sources */,
284321 12E36DD122148122006FCDD7 /* FullPostController.swift in Sources */,
322+ 1288B5CE221F1158002BE6B1 /* DataStorage.swift in Sources */,
285323 125BD57D22171D2A008A3575 /* ProfileViewController.swift in Sources */,
286324 12DB7FDB2218590C0096878E /* InfoCell.swift in Sources */,
287325 12DB7FD922181E660096878E /* BasicInfoCell.swift in Sources */,
326+ 12D7D135221C42B700B35452 /* ChannelController.swift in Sources */,
288327 12E36D9C221424EA006FCDD7 /* AppDelegate.swift in Sources */,
289328 12DB7FD722181CD20096878E /* BasicInfoController.swift in Sources */,
290329 12E36DCE22144756006FCDD7 /* Constants.swift in Sources */,
291330 12DB7FDD221872F80096878E /* SettingsViewController.swift in Sources */,
292−
331+ 123E37A7221F1DD700F6E42A /* MainController.swift in Sources */,
293332 );
294333 runOnlyForDeploymentPostprocessing = 0;
295334 };
GDproject/Base.lproj/Main.storyboard+179−36
@@ -1,5 +1,5 @@
11<?xml version="1.0" encoding="UTF-8"?>
2−<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="IeP-4W-8LT">
2+<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">
33 <device id="retina4_7" orientation="portrait">
44 <adaptation id="fullscreen"/>
55 </device>
@@ -11,37 +11,6 @@
1111 <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
1212 </dependencies>
1313 <scenes>
14− <!--News Controller-->
15− <scene sceneID="tne-QT-ifu">
16− <objects>
17− <viewController id="BYZ-38-t0r" customClass="NewsController" customModule="GDproject" customModuleProvider="target" sceneMemberID="viewController">
18− <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
19− <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
20− <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
21− <subviews>
22− <tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="bdn-EE-6KU">
23− <rect key="frame" x="0.0" y="116" width="375" height="502"/>
24− <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
25− </tableView>
26− </subviews>
27− <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
28− <constraints>
29− <constraint firstItem="bdn-EE-6KU" firstAttribute="leading" secondItem="6Tk-OE-BBY" secondAttribute="leading" id="Mwc-qc-ZfA"/>
30− <constraint firstItem="bdn-EE-6KU" firstAttribute="top" secondItem="6Tk-OE-BBY" secondAttribute="top" id="dww-F7-g9y"/>
31− <constraint firstItem="6Tk-OE-BBY" firstAttribute="trailing" secondItem="bdn-EE-6KU" secondAttribute="trailing" id="wlT-ZO-QGd"/>
32− <constraint firstItem="6Tk-OE-BBY" firstAttribute="bottom" secondItem="bdn-EE-6KU" secondAttribute="bottom" id="yXX-zW-vb8"/>
33− </constraints>
34− <viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
35− </view>
36− <navigationItem key="navigationItem" largeTitleDisplayMode="always" id="caN-kg-RZ4"/>
37− <connections>
38− <outlet property="tableView" destination="bdn-EE-6KU" id="O4Z-at-Hzw"/>
39− </connections>
40− </viewController>
41− <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
42− </objects>
43− <point key="canvasLocation" x="2015.2" y="132.68365817091455"/>
44− </scene>
4514 <!--Profile View Controller-->
4615 <scene sceneID="rQ6-TM-V7T">
4716 <objects>
@@ -245,6 +214,104 @@
245214 </objects>
246215 <point key="canvasLocation" x="2803" y="1756"/>
247216 </scene>
217+ <!--Channel List Controller-->
218+ <scene sceneID="4eb-Jz-gcx">
219+ <objects>
220+ <tableViewController storyboardIdentifier="ChannelListController" id="VzJ-FE-nbt" customClass="ChannelListController" customModule="GDproject" customModuleProvider="target" sceneMemberID="viewController">
221+ <tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" id="5RL-OH-B9N">
222+ <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
223+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
224+ <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
225+ <prototypes>
226+ <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="none" indentationWidth="10" reuseIdentifier="ChannelCell" textLabel="MAo-lZ-MFd" detailTextLabel="KTs-9K-R13" style="IBUITableViewCellStyleSubtitle" id="65E-UC-AJO">
227+ <rect key="frame" x="0.0" y="28" width="375" height="44"/>
228+ <autoresizingMask key="autoresizingMask"/>
229+ <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="65E-UC-AJO" id="N5k-ip-WkW">
230+ <rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
231+ <autoresizingMask key="autoresizingMask"/>
232+ <subviews>
233+ <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Title" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="MAo-lZ-MFd">
234+ <rect key="frame" x="16" y="5" width="33.5" height="20.5"/>
235+ <autoresizingMask key="autoresizingMask"/>
236+ <fontDescription key="fontDescription" type="system" pointSize="17"/>
237+ <nil key="textColor"/>
238+ <nil key="highlightedColor"/>
239+ </label>
240+ <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Subtitle" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="KTs-9K-R13">
241+ <rect key="frame" x="16" y="25.5" width="44" height="14.5"/>
242+ <autoresizingMask key="autoresizingMask"/>
243+ <fontDescription key="fontDescription" type="system" pointSize="12"/>
244+ <nil key="textColor"/>
245+ <nil key="highlightedColor"/>
246+ </label>
247+ </subviews>
248+ </tableViewCellContentView>
249+ </tableViewCell>
250+ </prototypes>
251+ <connections>
252+ <outlet property="dataSource" destination="VzJ-FE-nbt" id="XQW-UU-t6A"/>
253+ <outlet property="delegate" destination="VzJ-FE-nbt" id="xee-fv-SfO"/>
254+ </connections>
255+ </tableView>
256+ </tableViewController>
257+ <placeholder placeholderIdentifier="IBFirstResponder" id="9RU-Bp-4K5" userLabel="First Responder" sceneMemberID="firstResponder"/>
258+ </objects>
259+ <point key="canvasLocation" x="2708" y="-597"/>
260+ </scene>
261+ <!--Channel Controller-->
262+ <scene sceneID="ugM-Od-pJd">
263+ <objects>
264+ <viewController storyboardIdentifier="ChannelController" id="SgI-bH-MqV" customClass="ChannelController" customModule="GDproject" customModuleProvider="target" sceneMemberID="viewController">
265+ <view key="view" contentMode="scaleToFill" id="edj-KS-H90">
266+ <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
267+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
268+ <subviews>
269+ <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="5My-GH-WDq">
270+ <rect key="frame" x="0.0" y="20" width="375" height="54"/>
271+ <subviews>
272+ <textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="Title" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="VFE-We-ctc">
273+ <rect key="frame" x="16" y="12" width="343" height="30"/>
274+ <color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
275+ <fontDescription key="fontDescription" type="system" pointSize="14"/>
276+ <textInputTraits key="textInputTraits"/>
277+ </textField>
278+ </subviews>
279+ <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
280+ <constraints>
281+ <constraint firstAttribute="height" constant="54" id="AX7-No-rwt"/>
282+ <constraint firstItem="VFE-We-ctc" firstAttribute="leading" secondItem="5My-GH-WDq" secondAttribute="leading" constant="16" id="HBN-OE-miW"/>
283+ <constraint firstItem="VFE-We-ctc" firstAttribute="top" secondItem="5My-GH-WDq" secondAttribute="top" constant="12" id="N8q-hz-5yP"/>
284+ <constraint firstAttribute="bottom" secondItem="VFE-We-ctc" secondAttribute="bottom" constant="12" id="jqO-53-maF"/>
285+ <constraint firstAttribute="trailing" secondItem="VFE-We-ctc" secondAttribute="trailing" constant="16" id="zYt-AY-R9F"/>
286+ </constraints>
287+ </view>
288+ <tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="fye-z6-WKO">
289+ <rect key="frame" x="0.0" y="74" width="375" height="593"/>
290+ <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
291+ </tableView>
292+ </subviews>
293+ <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
294+ <constraints>
295+ <constraint firstItem="fye-z6-WKO" firstAttribute="top" secondItem="5My-GH-WDq" secondAttribute="bottom" id="73C-jP-zKv"/>
296+ <constraint firstItem="C5s-a1-LTb" firstAttribute="bottom" secondItem="fye-z6-WKO" secondAttribute="bottom" id="HUf-vU-oDj"/>
297+ <constraint firstItem="fye-z6-WKO" firstAttribute="leading" secondItem="C5s-a1-LTb" secondAttribute="leading" id="Hbj-fv-SB5"/>
298+ <constraint firstItem="5My-GH-WDq" firstAttribute="top" secondItem="C5s-a1-LTb" secondAttribute="top" id="Ms5-z0-6i1"/>
299+ <constraint firstItem="5My-GH-WDq" firstAttribute="trailing" secondItem="C5s-a1-LTb" secondAttribute="trailing" id="Pt4-do-bce"/>
300+ <constraint firstItem="5My-GH-WDq" firstAttribute="leading" secondItem="C5s-a1-LTb" secondAttribute="leading" id="pgz-uB-BfM"/>
301+ <constraint firstItem="C5s-a1-LTb" firstAttribute="trailing" secondItem="fye-z6-WKO" secondAttribute="trailing" id="zHE-tP-Siv"/>
302+ </constraints>
303+ <viewLayoutGuide key="safeArea" id="C5s-a1-LTb"/>
304+ </view>
305+ <connections>
306+ <outlet property="tableView" destination="fye-z6-WKO" id="S11-YV-PU6"/>
307+ <outlet property="textField" destination="VFE-We-ctc" id="6pP-P4-zg8"/>
308+ <outlet property="viewww" destination="5My-GH-WDq" id="SS0-Mi-QWf"/>
309+ </connections>
310+ </viewController>
311+ <placeholder placeholderIdentifier="IBFirstResponder" id="fzv-8a-15V" userLabel="First Responder" sceneMemberID="firstResponder"/>
312+ </objects>
313+ <point key="canvasLocation" x="3560.8000000000002" y="-597.75112443778119"/>
314+ </scene>
248315 <!--New Post View Controller-->
249316 <scene sceneID="TVK-xu-UdJ">
250317 <objects>
@@ -294,10 +361,53 @@
294361 </objects>
295362 <point key="canvasLocation" x="3444" y="129.98500749625188"/>
296363 </scene>
364+ <!--Log In View Controller-->
365+ <scene sceneID="Pkd-pB-bQs">
366+ <objects>
367+ <viewController storyboardIdentifier="LogInController" id="ZCz-70-hDh" customClass="LogInViewController" customModule="GDproject" customModuleProvider="target" sceneMemberID="viewController">
368+ <view key="view" contentMode="scaleToFill" id="1q2-4g-KZs">
369+ <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
370+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
371+ <subviews>
372+ <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="12" translatesAutoresizingMaskIntoConstraints="NO" id="UwC-m5-jA5">
373+ <rect key="frame" x="16" y="100" width="343" height="83"/>
374+ <subviews>
375+ <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">
376+ <rect key="frame" x="0.0" y="0.0" width="343" height="41"/>
377+ <fontDescription key="fontDescription" type="boldSystem" pointSize="34"/>
378+ <nil key="textColor"/>
379+ <nil key="highlightedColor"/>
380+ </label>
381+ <textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="Mail" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="mFP-WG-jY5">
382+ <rect key="frame" x="0.0" y="53" width="343" height="30"/>
383+ <color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
384+ <nil key="textColor"/>
385+ <fontDescription key="fontDescription" type="system" pointSize="14"/>
386+ <textInputTraits key="textInputTraits"/>
387+ </textField>
388+ </subviews>
389+ </stackView>
390+ </subviews>
391+ <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
392+ <constraints>
393+ <constraint firstItem="UwC-m5-jA5" firstAttribute="leading" secondItem="LOR-Yw-0FU" secondAttribute="leading" constant="16" id="M6z-nU-H40"/>
394+ <constraint firstItem="LOR-Yw-0FU" firstAttribute="trailing" secondItem="UwC-m5-jA5" secondAttribute="trailing" constant="16" id="jST-rr-MMX"/>
395+ <constraint firstItem="UwC-m5-jA5" firstAttribute="top" secondItem="LOR-Yw-0FU" secondAttribute="top" constant="80" id="rvy-Ii-bwS"/>
396+ </constraints>
397+ <viewLayoutGuide key="safeArea" id="LOR-Yw-0FU"/>
398+ </view>
399+ <connections>
400+ <outlet property="mailTextField" destination="mFP-WG-jY5" id="7SN-qe-DDm"/>
401+ </connections>
402+ </viewController>
403+ <placeholder placeholderIdentifier="IBFirstResponder" id="6e8-oo-bbc" userLabel="First Responder" sceneMemberID="firstResponder"/>
404+ </objects>
405+ <point key="canvasLocation" x="-466" y="-821"/>
406+ </scene>
297407 <!--Posts-->
298408 <scene sceneID="RSd-UJ-34B">
299409 <objects>
300− <navigationController automaticallyAdjustsScrollViewInsets="NO" id="NuV-ZG-ld2" sceneMemberID="viewController">
410+ <navigationController storyboardIdentifier="navChannels" automaticallyAdjustsScrollViewInsets="NO" id="NuV-ZG-ld2" sceneMemberID="viewController">
301411 <tabBarItem key="tabBarItem" title="Posts" id="dH2-sL-YsR"/>
302412 <toolbarItems/>
303413 <navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" largeTitles="YES" id="6qB-3A-tuL">
@@ -306,17 +416,37 @@
306416 </navigationBar>
307417 <nil name="viewControllers"/>
308418 <connections>
309− <segue destination="BYZ-38-t0r" kind="relationship" relationship="rootViewController" id="ehh-1b-ZGK"/>
419+ <segue destination="Nqc-TI-ueQ" kind="relationship" relationship="rootViewController" id="2BZ-i4-uIE"/>
310420 </connections>
311421 </navigationController>
312422 <placeholder placeholderIdentifier="IBFirstResponder" id="POV-5T-jeQ" userLabel="First Responder" sceneMemberID="firstResponder"/>
313423 </objects>
314424 <point key="canvasLocation" x="1088.8" y="132.68365817091455"/>
315425 </scene>
426+ <!--News Controller-->
427+ <scene sceneID="eR7-97-LRL">
428+ <objects>
429+ <tableViewController storyboardIdentifier="NewsController" id="Nqc-TI-ueQ" customClass="NewsController" customModule="GDproject" customModuleProvider="target" sceneMemberID="viewController">
430+ <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">
431+ <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
432+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
433+ <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
434+ <color key="sectionIndexBackgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
435+ <connections>
436+ <outlet property="dataSource" destination="Nqc-TI-ueQ" id="bu5-tQ-7lb"/>
437+ <outlet property="delegate" destination="Nqc-TI-ueQ" id="kTM-Be-8qb"/>
438+ </connections>
439+ </tableView>
440+ <navigationItem key="navigationItem" id="b8E-6f-hLM"/>
441+ </tableViewController>
442+ <placeholder placeholderIdentifier="IBFirstResponder" id="c9d-Kh-itI" userLabel="First Responder" sceneMemberID="firstResponder"/>
443+ </objects>
444+ <point key="canvasLocation" x="1880" y="136"/>
445+ </scene>
316446 <!--Profile-->
317447 <scene sceneID="dJj-Hp-Wa9">
318448 <objects>
319− <navigationController automaticallyAdjustsScrollViewInsets="NO" id="tae-5q-wvT" sceneMemberID="viewController">
449+ <navigationController storyboardIdentifier="navPosts" automaticallyAdjustsScrollViewInsets="NO" id="tae-5q-wvT" sceneMemberID="viewController">
320450 <tabBarItem key="tabBarItem" title="Profile" id="lYy-LQ-AcR"/>
321451 <toolbarItems/>
322452 <navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" largeTitles="YES" id="q3a-ph-c8V">
@@ -332,10 +462,23 @@
332462 </objects>
333463 <point key="canvasLocation" x="1089" y="958"/>
334464 </scene>
465+ <!--Navigation Controller-->
466+ <scene sceneID="r0M-xH-UwU">
467+ <objects>
468+ <navigationController id="609-2j-gc9" sceneMemberID="viewController">
469+ <navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="Ah8-NU-AsD">
470+ <rect key="frame" x="0.0" y="20" width="375" height="44"/>
471+ <autoresizingMask key="autoresizingMask"/>
472+ </navigationBar>
473+ </navigationController>
474+ <placeholder placeholderIdentifier="IBFirstResponder" id="Raj-78-jlT" userLabel="First Responder" sceneMemberID="firstResponder"/>
475+ </objects>
476+ <point key="canvasLocation" x="-2242" y="68"/>
477+ </scene>
335478 <!--Tab Bar Controller-->
336479 <scene sceneID="HCR-WO-p7g">
337480 <objects>
338− <tabBarController automaticallyAdjustsScrollViewInsets="NO" id="IeP-4W-8LT" sceneMemberID="viewController">
481+ <tabBarController storyboardIdentifier="TabBar" automaticallyAdjustsScrollViewInsets="NO" id="IeP-4W-8LT" sceneMemberID="viewController">
339482 <toolbarItems/>
340483 <tabBar key="tabBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="3pl-mU-U30">
341484 <rect key="frame" x="0.0" y="0.0" width="1000" height="1000"/>
GDproject/Constants.swift+25−3
@@ -6,16 +6,38 @@
66// Copyright © 2019 drHSE. All rights reserved.
77//
88
9−//constant for cell in posts NewsController.swift
9+/// constant for cell in posts NewsController.swift
1010let postCellId = "PostCell"
11−// constant for segmented controll in NewsController.swift and ChannelsController.swift
11+
12+/// constant for segmented controll in NewsController.swift and ChannelsController.swift
1213let headerNewsChannelsVC = "HeaderSegmentedControll"
13−// for transitioning to full post view
14+
15+/// for transitioning to full post view
1416let fullPostControllerId = "FullPostController"
1517
18+/// constant for dequing basic cell
1619let basicInfoCellId = "BasicInfoCell"
1720
21+/// constant for dequing info cell
1822let infoCellId = "InfoCell"
1923
24+/// constant for switching to view controller for invitations
2025let inviteVC = "InviteViewController"
2126
27+/// constant for dequing basic cell
28+let channelCellId = "ChannelCell"
29+
30+/// constant for switching to channel list view controller for choosing channel
31+let channelListControllerId = "ChannelListController"
32+
33+/// constant for dequing channel item cell
34+let itemCellId = "ItemCell"
35+
36+/// constant for switching to view controller to add or edit one channel
37+let channelControllerId = "ChannelController"
38+
39+/// constant for switching to news controller
40+let newsController = "NewsController"
41+
42+/// constant for switching to view controller for log in app
43+let logInController = "LogInController"
GDproject/Controller/ News and channels/ChannelController.swiftnew file+226
@@ -0,0 +1,226 @@
1+//
2+// ChannelController.swift
3+// GDproject
4+//
5+// Created by cstore on 19/02/2019.
6+// Copyright © 2019 drHSE. All rights reserved.
7+//
8+
9+import UIKit
10+
11+protocol DataDelegate {
12+ func passData(for row: Int, channel: Channel)
13+}
14+
15+class ChannelController: UIViewController, UITableViewDelegate, UITableViewDataSource, UITextFieldDelegate, UISearchBarDelegate
16+{
17+ @IBOutlet weak var tableView: UITableView!
18+
19+ var index: Int?
20+ var channel: Channel?
21+ var myProtocol: DataDelegate?
22+
23+ var dataSource: [String] = []
24+
25+ var fullPeople: [String] = ["Other Ann", "Other Ilya", "Other Kostya", "Pasha", "Valera"]
26+
27+ var fullTags: [String] = ["# happy", "# sad", "# meme", "# shershakov", "# pupsik"]
28+
29+ @IBOutlet weak var viewww: UIView!
30+
31+ @IBOutlet weak var textField: UITextField!
32+
33+ override func viewDidLoad() {
34+ super.viewDidLoad()
35+ tableView.delegate = self
36+ tableView.dataSource = self
37+ dataSource = channel!.people
38+ tableView.register(UITableViewCell.self, forCellReuseIdentifier: itemCellId)
39+ tableView.reloadData()
40+ textField.delegate = self
41+ searchBar.delegate = self
42+ searchBar.selectedScopeButtonIndex = 0
43+ navigationItem.title = channel?.title
44+ textField.placeholder = channel?.title
45+ textField.addTarget(self, action: #selector(changedText(_:)), for: .editingChanged)
46+ }
47+
48+ @objc func changedText(_ textField: UITextField){
49+ navigationItem.title = textField.text
50+ channel?.title = textField.text!
51+ myProtocol?.passData(for: index!, channel: channel!)
52+ }
53+
54+ func numberOfSections(in tableView: UITableView) -> Int {
55+ return 1
56+ }
57+
58+ func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
59+ return dataSource.count
60+ }
61+
62+ func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
63+ if searchBar.isFirstResponder {
64+ if let cell = tableView.cellForRow(at: indexPath)
65+ {
66+
67+ if cell.accessoryType == .none{
68+ switch searchBar.selectedScopeButtonIndex{
69+ case 0:
70+ channel?.people.append(dataSource[indexPath.row])
71+ print("people = \(channel!.people)")
72+ case 1:
73+ channel?.hashtags.append(dataSource[indexPath.row])
74+ print("hashtags = \(channel!.hashtags)")
75+ default:
76+ break
77+ }
78+
79+ cell.accessoryType = .checkmark
80+ } else {
81+ cell.accessoryType = .none
82+
83+ switch searchBar.selectedScopeButtonIndex{
84+ case 0:
85+ channel?.people = channel!.people.filter({ (s) -> Bool in
86+ !fullPeople[indexPath.row].contains(s)
87+ })
88+ // TODO: dataPass
89+ case 1:
90+ channel?.hashtags = channel!.hashtags.filter({ (s) -> Bool in
91+ !fullTags[indexPath.row].contains(s)
92+ })
93+ // TODO: dataPass
94+ default:
95+ break
96+ }
97+ }
98+ }
99+ } else
100+ {
101+ tableView.beginUpdates()
102+ dataSource.remove(at: indexPath.row)
103+ switch searchBar.selectedScopeButtonIndex{
104+ case 0:
105+ channel?.people.remove(at: indexPath.row)
106+ // TODO: dataPass
107+ case 1:
108+ channel?.hashtags.remove(at: indexPath.row)
109+ // TODO: dataPass
110+ default:
111+ break
112+ }
113+ tableView.deleteRows(at: [indexPath], with: .none)
114+ tableView.endUpdates()
115+ }
116+ }
117+
118+ func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
119+ let cell = tableView.dequeueReusableCell(withIdentifier: itemCellId, for: indexPath)
120+
121+ cell.textLabel?.text = dataSource[indexPath.row]
122+ cell.selectionStyle = .none
123+
124+ if channel!.hashtags.contains(dataSource[indexPath.row]) || channel!.people.contains(dataSource[indexPath.row])
125+ {
126+ cell.accessoryType = .checkmark
127+ } else {
128+ cell.accessoryType = .none
129+ }
130+
131+ return cell
132+ }
133+
134+ func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
135+ return 100
136+ }
137+
138+ let searchBar: UISearchBar = {
139+ let searchBar = UISearchBar(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 70))
140+ searchBar.showsScopeBar = true
141+ searchBar.showsCancelButton = true
142+ searchBar.scopeButtonTitles = ["People", "Tags"]
143+ return searchBar
144+ }()
145+
146+ func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView?
147+ {
148+ let view = UIView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 70))
149+
150+ if flag {
151+ searchBar.selectedScopeButtonIndex = 1
152+ } else {
153+ searchBar.selectedScopeButtonIndex = 0
154+ }
155+
156+ view.addSubview(searchBar)
157+ return view
158+ }
159+
160+ func textFieldShouldReturn(_ textField: UITextField) -> Bool
161+ {
162+ textField.resignFirstResponder()
163+ return true
164+ }
165+
166+ func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
167+ if searchText.isEmpty {
168+ dataSource = searchBar.selectedScopeButtonIndex == 0 ? fullPeople : fullTags
169+ tableView.reloadData()
170+ } else {
171+ filterTableView(ind: searchBar.selectedScopeButtonIndex, text: searchText)
172+ }
173+ }
174+
175+ func filterTableView(ind: Int, text: String){
176+ switch ind {
177+ case 0:
178+ dataSource = fullPeople.filter({ (s) -> Bool in
179+ s.lowercased().contains(text.lowercased())
180+ })
181+ tableView.reloadData()
182+ case 1:
183+ dataSource = fullTags.filter({ (s) -> Bool in
184+ s.lowercased().contains(text.lowercased())
185+ })
186+ tableView.reloadData()
187+ default:
188+ break
189+ }
190+ }
191+
192+ var flag = false
193+
194+ func searchBar(_ searchBar: UISearchBar, selectedScopeButtonIndexDidChange selectedScope: Int) {
195+ if searchBar.isFirstResponder {
196+ dataSource = searchBar.selectedScopeButtonIndex == 0 ? fullPeople : fullTags
197+ flag = searchBar.selectedScopeButtonIndex == 0 ? false : true
198+ if (!(searchBar.text?.isEmpty ?? true))
199+ {
200+ filterTableView(ind: selectedScope, text: searchBar.text!)
201+ }
202+ tableView.reloadData()
203+ } else if !(searchBar.isFirstResponder){
204+ dataSource = searchBar.selectedScopeButtonIndex == 0 ? channel!.people : channel!.hashtags
205+ flag = searchBar.selectedScopeButtonIndex == 0 ? false : true
206+ tableView.reloadData()
207+ }
208+ }
209+
210+ func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
211+ dataSource = searchBar.selectedScopeButtonIndex == 0 ? channel!.people : channel!.hashtags
212+ flag = searchBar.selectedScopeButtonIndex == 0 ? false : true
213+ tableView.reloadData()
214+ }
215+
216+ func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
217+ dataSource = searchBar.selectedScopeButtonIndex == 0 ? fullPeople : fullTags
218+ flag = searchBar.selectedScopeButtonIndex == 0 ? false : true
219+ tableView.reloadData()
220+ }
221+
222+ func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
223+ searchBar.text = ""
224+ searchBar.resignFirstResponder()
225+ }
226+}
GDproject/Controller/ News and channels/ChannelListController.swiftnew file+185
@@ -0,0 +1,185 @@
1+//
2+// ChannelListController.swift
3+// GDproject
4+//
5+// Created by cstore on 19/02/2019.
6+// Copyright © 2019 drHSE. All rights reserved.
7+//
8+
9+import UIKit
10+
11+struct ChannelData{
12+ var title = String()
13+ var subtitle = String()
14+}
15+
16+// TODO: make search controller availiable
17+class ChannelListController: UITableViewController, DataDelegate {
18+
19+ // MARK: - Output -
20+ var onChannelSelected: ((Channel) -> Void)?
21+
22+ // MARK:- filter search controller
23+ var filteredDataSource = [Channel]()
24+
25+ var myProtocol: DataDelegate?
26+ var displayingChannel: Channel?
27+
28+ var isFiltering: Bool {
29+ return searchController.isActive && !searchBarIsEmpty()
30+ }
31+
32+ func searchBarIsEmpty() -> Bool {
33+ return searchController.searchBar.text?.isEmpty ?? true
34+ }
35+
36+ func filterContentForSearchText(_ searchText: String, scope: String = "All")
37+ {
38+ filteredDataSource = ChannelListController.dataSource.filter({(keys : Channel) -> Bool in
39+ return keys.title.lowercased().contains(searchText.lowercased())
40+ })
41+
42+ tableView.reloadData()
43+ }
44+
45+ func passData(for row: Int, channel: Channel) {
46+ ChannelListController.dataSource[row] = channel
47+ }
48+
49+ var searchController = UISearchController(searchResultsController: nil)
50+
51+ override func viewDidLoad() {
52+ super.viewDidLoad()
53+ setUpNavigationBar()
54+ navigationItem.title = "Channels"
55+ searchController.searchResultsUpdater = self
56+ searchController.obscuresBackgroundDuringPresentation = false
57+ searchController.searchBar.placeholder = "Search channel"
58+ navigationItem.searchController = searchController
59+ definesPresentationContext = true
60+ }
61+
62+ func setUpNavigationBar(){
63+ navigationController?.navigationItem.largeTitleDisplayMode = .always
64+ navigationItem.rightBarButtonItems = [UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(addChannel))]
65+ }
66+
67+ override func viewWillAppear(_ animated: Bool)
68+ {
69+ super.viewWillAppear(animated)
70+ searchController.isActive = false
71+ tableView.reloadData()
72+ }
73+
74+ @objc func addChannel()
75+ {
76+ // insertion
77+ tableView.beginUpdates()
78+ ChannelListController.dataSource.insert(Channel(title: "Untitled", subtitle: "No", hashtags: [], people: [], posts: []), at: 1)
79+ tableView.insertRows(at: [IndexPath(row: 1, section: 0)], with: .none)
80+ tableView.endUpdates()
81+
82+ // editing mode is on automatically
83+ let vc = storyboard?.instantiateViewController(withIdentifier: channelControllerId) as! ChannelController
84+ vc.index = 1
85+ vc.myProtocol = self
86+ vc.channel = ChannelListController.dataSource[1]
87+ navigationController?.pushViewController(vc, animated: true)
88+ }
89+
90+ static var dataSource : [Channel] = [
91+ Channel(title: "General", subtitle: "All posts", hashtags: ["All"], people: ["All"], posts: []),
92+ Channel(title: "Title", subtitle: "subtitle", hashtags: ["# sad", "# happy"], people: ["Seva", "Andrey"], posts: [Post(dataArray: [.text("Le Lorem Ipsum est simplement du faux texte employé dans la composition et la mise en page avant impression. Le Lorem Ipsum est le faux texte standard.")], from: User(name: "vbogomazova", id: 2, fullName: "Богомазова Вероника Львовна"), date: "14.02.19 в 12:05")]),
93+ Channel(title: "Title2", subtitle: "subtitle2", hashtags: ["# studyhard", "# university"], people: ["Pasha", "Olya", "Andrey", "Ilya"], posts:
94+ [
95+ Post(dataArray: [.text("L'avantage du Lorem Ipsum sur un texte générique comme 'Du texte. Du texte. Du texte.' est qu'il possède une distribution de lettres plus ou moins normale.")], from: User(name: "vbogomazova", id: 2, fullName: "Богомазова Вероника Львовна"), date: "14.02.19 в 12:05"),
96+ Post(dataArray: [.text("par accident, souvent intentionnellement (histoire d'y rajouter de petits clins d'oeil, voire des phrases embarassantes).")], from: User(name: "vbogomazova", id: 2, fullName: "Богомазова Вероника Львовна"), date: "14.02.19 в 12:05")
97+ ]),
98+ Channel(title: "Title3", subtitle: "subtitle3", hashtags: ["# lol", "# meme", "# hehe"], people: ["Superman"], posts: [Post(dataArray: [.text("Ipsum est le faux texte standard de l'imprimerie depuis les années 1500, quand un imprimeur anonyme assembla ensemble des morceaux de texte pour réaliser un livre spécimen de polices de texte. Il n'a pas fait que survivre cinq siècles, mais s'est aussi adapté à la bureautique informatique, sans que son contenu n'en soit modifié.")], from: User(name: "vbogomazova", id: 2, fullName: "Богомазова Вероника Львовна"), date: "14.02.19 в 12:05")])
99+ ]
100+
101+ override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
102+ if isFiltering {
103+ return filteredDataSource.count
104+ } else {
105+ return ChannelListController.dataSource.count
106+ }
107+ }
108+
109+ override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
110+ {
111+
112+ let cell = tableView.dequeueReusableCell(withIdentifier: channelCellId, for: indexPath)
113+
114+
115+ if isFiltering{
116+ cell.textLabel?.text = filteredDataSource[indexPath.row].title
117+ cell.detailTextLabel?.text = filteredDataSource[indexPath.row].subtitle
118+ } else {
119+ cell.textLabel?.text = ChannelListController.dataSource[indexPath.row].title
120+ cell.detailTextLabel?.text = ChannelListController.dataSource[indexPath.row].subtitle
121+ }
122+
123+ return cell
124+ }
125+
126+
127+ override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
128+ switch indexPath.row {
129+ case 0:
130+ return false
131+ default:
132+ return true
133+ }
134+ }
135+
136+ override func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]?
137+ {
138+
139+ let editButton = UITableViewRowAction(style: .normal, title: "Edit") { [weak self] (action, indexPath) in
140+ let vc = self?.storyboard?.instantiateViewController(withIdentifier: channelControllerId) as! ChannelController
141+ vc.index = indexPath.row
142+ vc.myProtocol = self!
143+ vc.channel = ChannelListController.dataSource[indexPath.row]
144+ self?.navigationController?.pushViewController(vc, animated: true)
145+ }
146+ editButton.backgroundColor = .green
147+
148+
149+ let deleteButton = UITableViewRowAction(style: .normal, title: "Delete") { [weak self] (action, indexPath) in
150+ if (ChannelListController.dataSource[indexPath.row] == self!.displayingChannel!)
151+ {
152+ self?.myProtocol?.passData(for: 0, channel: ChannelListController.dataSource[0])
153+ }
154+ self?.tableView.beginUpdates()
155+ ChannelListController.dataSource.remove(at: indexPath.row)
156+ self?.tableView.deleteRows(at: [indexPath], with: .none)
157+ self?.tableView.endUpdates()
158+ }
159+ deleteButton.backgroundColor = .red
160+
161+
162+ return [editButton, deleteButton]
163+ }
164+
165+ // TODO: remove popping
166+ override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
167+ {
168+ if isFiltering {
169+ //onChannelSelected?(filteredDataSource[indexPath.row])
170+ myProtocol?.passData(for: 0, channel: filteredDataSource[indexPath.row])
171+ navigationController?.popViewController(animated: true)
172+ } else {
173+ myProtocol?.passData(for: 0, channel: ChannelListController.dataSource[indexPath.row])
174+ navigationController?.popViewController(animated: true)
175+ //onChannelSelected?(ChannelListController.dataSource[indexPath.row])
176+ }
177+ }
178+}
179+
180+
181+extension ChannelListController : UISearchResultsUpdating {
182+ func updateSearchResults(for searchController: UISearchController) {
183+ filterContentForSearchText(searchController.searchBar.text!)
184+ }
185+}
GDproject/Controller/ News and channels/ChannelsCoordinator.swiftnew file+55
@@ -0,0 +1,55 @@
1+//
2+// ChannelsCoordinator.swift
3+// GDproject
4+//
5+// Created by cstore on 23/02/2019.
6+// Copyright © 2019 drHSE. All rights reserved.
7+//
8+
9+import Foundation
10+import UIKit
11+
12+final class ChannelsCoordinator{
13+
14+ // MARK: - Properties
15+ private var channel: Channel { didSet { updateInterfaces() } }
16+ private weak var navigationController: UINavigationController?
17+
18+ // MARK:- Init
19+ init(currentChannel: Channel, navigationController: UINavigationController) {
20+ self.channel = currentChannel
21+ self.navigationController = navigationController
22+ }
23+
24+ func start(){
25+ showCurrentChannel()
26+ }
27+
28+ // MARK: - Private implementation
29+ private func showListOfChannels(){
30+ let controller = UIStoryboard.makeChannelsListController()
31+ controller.onChannelSelected = { [weak self] channel
32+ in
33+ self?.channel = channel
34+ _ = self?.navigationController?.popViewController(animated: true)
35+ }
36+ navigationController?.pushViewController(controller, animated: true)
37+ }
38+
39+ private func showCurrentChannel(){
40+ let controller = UIStoryboard.makeNewsController()
41+ controller.channel = channel
42+ controller.onSelectChannel = { [weak self] in
43+ self?.showListOfChannels()
44+ }
45+ navigationController?.setViewControllers([controller], animated: false)
46+ //navigationController?.pushViewController(controller, animated: false)
47+ }
48+
49+ // MARK:- update only viewControllers which are depandable on chosen channel
50+ private func updateInterfaces() {
51+ navigationController?.viewControllers.forEach {
52+ ($0 as? UpdateableWithChannel)?.channel = channel
53+ }
54+ }
55+}
GDproject/Controller/News/FullPostController.swift → GDproject/Controller/ News and channels/FullPostController.swiftrenamed

The content is the same.

GDproject/Controller/News/NewPostViewController.swift → GDproject/Controller/ News and channels/NewPostViewController.swiftrenamed+15−17
@@ -18,6 +18,7 @@ class NewPostViewController: UIViewController, UITextViewDelegate {
1818 let textStorage = MarklightTextStorage()
1919
2020 weak var parentVC: NewsController?
21+ var myProtocol: NewPostDelegate?
2122
2223 static var draft: String = ""
2324 var textView: UITextView!
@@ -110,13 +111,13 @@ class NewPostViewController: UIViewController, UITextViewDelegate {
110111 NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardNotifications), name: UIResponder.keyboardWillHideNotification, object: nil)
111112
112113 // Partial fixes to a long standing bug, to keep the caret inside the `UITextView` always visible
113− NotificationCenter.default.addObserver(forName: UITextView.textDidChangeNotification, object: textView, queue: OperationQueue.main) { (notification) -> Void in
114− if self.textView.textStorage.string.hasSuffix("\n") {
114+ NotificationCenter.default.addObserver(forName: UITextView.textDidChangeNotification, object: textView, queue: OperationQueue.main) { [weak self] (notification) -> Void in
115+ if self!.textView.textStorage.string.hasSuffix("\n") {
115116 CATransaction.setCompletionBlock({ () -> Void in
116− self.scrollToCaret(self.textView, animated: false)
117+ self!.scrollToCaret(self!.textView, animated: false)
117118 })
118119 } else {
119− self.scrollToCaret(self.textView, animated: false)
120+ self!.scrollToCaret(self!.textView, animated: false)
120121 }
121122 }
122123
@@ -125,8 +126,11 @@ class NewPostViewController: UIViewController, UITextViewDelegate {
125126 @objc func handleKeyboardNotifications(notification: NSNotification){
126127 if let userInfo = notification.userInfo{
127128 // UIKeyboardFrameEndUserInfoKey
129+
128130 let keyBoardFrame = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
129− bottomTextViewConstraint?.constant = notification.name == UIResponder.keyboardWillShowNotification ? keyBoardFrame.height : 0
131+
132+ bottomTextViewConstraint?.constant = notification.name == UIResponder.keyboardWillShowNotification ? keyBoardFrame.height - tabBarController!.tabBar.frame.height : 0
133+
130134 print(bottomTextViewConstraint!.constant)
131135
132136 UIView.animate(withDuration: 0, delay: 0, options: .curveEaseOut, animations: {
@@ -188,12 +192,7 @@ class NewPostViewController: UIViewController, UITextViewDelegate {
188192
189193
190194 // adding row to uiTableView after adding new post
191− guard let vc = parentVC else {return}
192− vc.tableView.beginUpdates()
193− let indexPath1: IndexPath = IndexPath(row: 0, section: 0)
194− vc.dataSourse.insert(p, at: 0)
195− vc.tableView.insertRows(at: [indexPath1], with: .fade)
196− vc.tableView.endUpdates()
195+ myProtocol?.addPost(post: p)
197196 moveBackToParentVC()
198197 // somewhere here i will be sending server notifications about new post arrival
199198 }
@@ -203,17 +202,18 @@ class NewPostViewController: UIViewController, UITextViewDelegate {
203202
204203 let saveAction = UIAlertAction(title: "Save draft", style: .default)
205204 {
205+ [weak self]
206206 _ in
207− NewPostViewController.draft = self.textView.text
208− self.moveBackToParentVC()
207+ NewPostViewController.draft = self?.textView.text ?? ""
208+ self?.moveBackToParentVC()
209209 }
210210
211211 let deleteAction = UIAlertAction(title: "Delete draft", style: .destructive)
212212 {
213− (_)
213+ [weak self] (_)
214214 in
215215 NewPostViewController.draft = ""
216− self.moveBackToParentVC()
216+ self?.moveBackToParentVC()
217217 }
218218
219219 let cancelAction = UIAlertAction(title: "Cancel", style: .cancel)
@@ -242,8 +242,6 @@ class NewPostViewController: UIViewController, UITextViewDelegate {
242242 }
243243
244244
245−
246−
247245 func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange) -> Bool {
248246 print("Should interact with: \(URL)")
249247 return true
GDproject/Controller/News/NewsController.swift → GDproject/Controller/ News and channels/NewsController.swiftrenamed+64−36
@@ -8,66 +8,97 @@
88
99import UIKit
1010import TinyConstraints
11+import Cartography
12+
13+protocol UpdateableWithChannel: class {
14+ var channel: Channel? { get set }
15+}
16+protocol NewPostDelegate {
17+ func addPost(post: Post)
18+}
1119
1220// MARK:- Controller with posts and channels availiable.
1321// Search is availiable within every table (posts and channels). Has button-functionality for boths post and chnnels
14−class NewsController: UIViewController
22+class NewsController: UITableViewController, UISearchControllerDelegate, NewPostDelegate, UpdateableWithChannel, DataDelegate
1523{
16−
17− @IBOutlet weak var tableView: UITableView!
24+ func passData(for row: Int, channel: Channel) {
25+ self.channel = channel
26+ }
1827
19− var searchController = UISearchController(searchResultsController: nil)
28+ var channel: Channel?{
29+ didSet{
30+ news.dataSourse = channel?.posts ?? []
31+ navigationItem.title = channel?.title ?? ""
32+ }
33+ }
2034
21− var dataSourse: [Post] = [Post(dataArray: [.text("Le Lorem Ipsum est simplement du faux texte employé dans la composition et la mise en page avant impression. Le Lorem Ipsum est le faux texte standard de l'imprimerie depuis les années 1500, quand un imprimeur anonyme assembla ensemble des morceaux de texte pour réaliser un livre spécimen de polices de texte. Il n'a pas fait que survivre cinq siècles, mais s'est aussi adapté à la bureautique informatique, sans que son contenu n'en soit modifié. Il a été popularisé dans les années 1960 grâce à la vente de feuilles Letraset contenant des passages du Lorem Ipsum, et, plus récemment, par son inclusion dans des applications de mise en page de texte, comme Aldus PageMaker. \n On sait depuis longtemps que travailler avec du texte lisible et contenant du sens est source de distractions, et empêche de se concentrer sur la mise en page elle-même. L'avantage du Lorem Ipsum sur un texte générique comme 'Du texte. Du texte. Du texte.' est qu'il possède une distribution de lettres plus ou moins normale, et en tout cas comparable avec celle du français standard. De nombreuses suites logicielles de mise en page ou éditeurs de sites Web ont fait du Lorem Ipsum leur faux texte par défaut, et une recherche pour 'Lorem Ipsum' vous conduira vers de nombreux sites qui n'en sont encore qu'à leur phase de construction. Plusieurs versions sont apparues avec le temps, parfois par accident, souvent intentionnellement (histoire d'y rajouter de petits clins d'oeil, voire des phrases embarassantes).")], from: User(name: "vbogomazova", id: 2, fullName: "Богомазова Вероника Львовна"), date: "14.02.19 в 12:05")]
35+ // MARK: - Output -
36+ var onSelectChannel: (() -> Void)?
37+
38+ func addPost(post: Post) {
39+ news.dataSourse.insert(post, at: 0)
40+ }
2241
42+ var searchController = UISearchController(searchResultsController: nil)
43+
2344 var news = NewsVC()
24− var channels = ChannelsController()
2545
2646 override func viewDidLoad()
2747 {
2848 super.viewDidLoad()
29− tableView.register(HeaderNewsChannels.self, forCellReuseIdentifier: headerNewsChannelsVC)
30− tableView.register(PostViewCell.self, forCellReuseIdentifier: postCellId)
31−
32− news.dataSourse = dataSourse
33− news.viewController = self
49+ channel = ChannelListController.dataSource[0]
3450
35− news.type = .NEWS("Posts", "Channels")
51+ tableView.register(PostViewCell.self, forCellReuseIdentifier: postCellId)
52+ tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
3653
37− tableView.delegate = news
38− tableView.dataSource = news
39− tableView.reloadData()
54+ searchController.delegate = self
55+ searchController.obscuresBackgroundDuringPresentation = false
56+ navigationItem.searchController = searchController
57+ definesPresentationContext = true
58+ searchController.searchBar.placeholder = "Search anything"
4059
60+ news.dataSourse = channel!.posts
61+ news.viewController = self
4162
63+ news.type = .NONE
4264
4365 setUpNavigationItemsforPosts()
44− searchController.searchBar.placeholder = "Search anything"
45−
46− navigationItem.searchController = searchController
47− definesPresentationContext = true
48−
49− setUpBanner()
66+
67+ //setUpBanner()
5068 }
5169
70+
71+ let label : UILabel = {
72+ let label = UILabel()
73+ label.text = "No posts to display yet!"
74+ label.font = UIFont.systemFont(ofSize: 18)
75+ label.textColor = .black
76+ label.isHidden = true
77+ label.numberOfLines = 0
78+ return label
79+ }()
80+
5281 override func viewWillAppear(_ animated: Bool) {
5382 super.viewWillAppear(animated)
54− navigationController?.navigationBar.prefersLargeTitles = true
83+ searchController.isActive = false
84+ // TODO:- display something if no posts are availiable
85+ tableView.reloadData()
5586 }
5687
5788 func setUpNavigationItemsforPosts(){
58− navigationItem.title = "Posts"
59− navigationItem.rightBarButtonItems = [UIBarButtonItem(barButtonSystemItem: .compose, target: self, action: #selector(self.writePost(_:)))]
89+ navigationItem.rightBarButtonItems = [UIBarButtonItem(barButtonSystemItem: .compose, target: self, action: #selector(self.writePost(_:))),UIBarButtonItem(barButtonSystemItem: .search, target: self, action: #selector(self.showChannels(_:)))
90+ ]
6091 tableView.delegate = news
6192 tableView.dataSource = news
6293 tableView.reloadData()
6394 }
6495
65− func setUpNavigationItemsForChannels(){
66− navigationItem.title = "Channels"
67− navigationItem.rightBarButtonItems = [UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(addChannel))]
68− tableView.delegate = channels
69− tableView.dataSource = channels
70− tableView.reloadData()
96+ // MARK:- attempt with coordinator
97+ @objc func showChannels(_ barItem: UIBarButtonItem){
98+ let vc = UIStoryboard.makeChannelsListController()
99+ vc.myProtocol = self
100+ vc.displayingChannel = channel
101+ self.navigationController?.pushViewController(vc, animated: true)
71102 }
72103
73104 @objc func writePost(_ barItem: UIBarButtonItem)
@@ -77,7 +108,7 @@ class NewsController: UIViewController
77108 vc.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Post", style: .plain, target: vc, action: #selector(vc.newPost))
78109 vc.navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Close", style: .plain, target: vc, action: #selector(vc.closeView))
79110
80− vc.parentVC = self
111+ vc.myProtocol = self
81112
82113 let transition = CATransition()
83114 transition.duration = 0.5
@@ -88,10 +119,6 @@ class NewsController: UIViewController
88119 navigationController?.pushViewController(vc, animated: false)
89120 }
90121
91− @objc func addChannel(){
92− print("Add channel")
93− }
94−
95122 // for animating the banner
96123 var topConstraint: NSLayoutConstraint?
97124
@@ -111,6 +138,7 @@ class NewsController: UIViewController
111138 return label
112139 }()
113140
141+ // MARK:- banner
114142 private func setUpBanner()
115143 {
116144 view.addSubview(bannerView)
@@ -149,7 +177,7 @@ class NewsController: UIViewController
149177
150178 var isBannerVisible: Bool = false
151179
152− func scrollViewDidScroll(_ scrollView: UIScrollView) {
180+ override func scrollViewDidScroll(_ scrollView: UIScrollView) {
153181 print(scrollView.contentOffset.y)
154182 if scrollView.contentOffset.y >= 50 && !isBannerVisible{
155183 isBannerVisible = true
GDproject/Controller/News/NewsVC.swift → GDproject/Controller/ News and channels/NewsVC.swiftrenamed+5−33
@@ -16,10 +16,13 @@ class NewsVC: UIViewController, UITableViewDelegate, UITableViewDataSource{
1616
1717 var viewController: UIViewController?
1818
19+ func numberOfSections(in tableView: UITableView) -> Int {
20+ return 1
21+ }
22+
1923 func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
2024 {
2125 tableView.deselectRow(at: indexPath, animated: true)
22−
2326 let vc = viewController!.storyboard!.instantiateViewController(withIdentifier: fullPostControllerId) as! FullPostController
2427
2528 vc.post = dataSourse[indexPath.row]
@@ -46,41 +49,10 @@ class NewsVC: UIViewController, UITableViewDelegate, UITableViewDataSource{
4649 func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
4750 return 100.0
4851 }
49−
50− func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
51− switch type {
52− case .NONE:
53− return 0
54− default:
55− return 46
56− }
57− }
58−
59− func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView?
60− {
61− let cell = tableView.dequeueReusableCell(withIdentifier: headerNewsChannelsVC) as! HeaderNewsChannels
62−
63− cell.vc = viewController as? NewsController
64− cell.vcProfile = viewController as? ProfileViewController
65−
66− let view = UIView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 46.0))
67− view.addSubview(cell)
68− cell.edgesToSuperview()
69−
70− switch type {
71− case .NONE:
72− return nil
73− default:
74− return view
75− }
76− }
77−
7852}
7953
8054
8155enum HeaderType {
8256 case NONE
83− case NEWS(String, String)
84− case PROFILE(String, String)
85− case BASIC_INFO(String, String)
57+ case NEWS
8658}
GDproject/Controller/News/PostViewCell.swift → GDproject/Controller/ News and channels/PostViewCell.swiftrenamed

The content is the same.

GDproject/Controller/Coordinator tab bar?/TabbarCoordinator.swiftnew file+13
@@ -0,0 +1,13 @@
1+import UIKit
2+
3+class TabbarCoordinator{
4+ var window: UIWindow!
5+
6+ func start(){
7+ window.rootViewController = UIStoryboard.tabBarController()
8+ }
9+
10+ init(window: UIWindow) {
11+ self.window = window
12+ }
13+}
GDproject/Controller/LogInViewController.swiftnew file+138
@@ -0,0 +1,138 @@
1+//
2+// LogInViewController.swift
3+// NewsFeed
4+//
5+// Created by cstore on 20/01/2019.
6+// Copyright © 2019 drHSE. All rights reserved.
7+//
8+
9+import UIKit
10+
11+class LogInViewController: UIViewController {
12+
13+ @IBOutlet weak var mailTextField: UITextField!
14+
15+ static let titleColor = UIColor(red: 0, green: 137/255, blue: 249/255, alpha: 0.5)
16+
17+ var bottomConstraint: NSLayoutConstraint?
18+
19+ let logInButton: UIButton = {
20+ let button = UIButton(type: .system)
21+ button.setTitle("Log In", for: .normal)
22+ button.setTitleColor(titleColor, for: .normal)
23+ button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 16)
24+ button.isEnabled = false
25+ button.addTarget(self, action: #selector(activateLogInProcess), for: .touchUpInside)
26+ return button
27+ }()
28+
29+ let keyboardBar: UIView = {
30+ let view = UIView()
31+ view.backgroundColor = .white
32+ return view
33+ }()
34+
35+ override func viewDidLoad() {
36+ super.viewDidLoad()
37+ setUpView()
38+ configureTapgesture()
39+ }
40+
41+ override func viewWillAppear(_ animated: Bool) {
42+ super.viewWillAppear(animated)
43+ // MARK:- uncomment when mail registration will be availiable
44+ //self.navigationController?.setNavigationBarHidden(true, animated: animated)
45+ }
46+
47+ override func viewWillDisappear(_ animated: Bool) {
48+ super.viewWillDisappear(animated)
49+ // MARK:- uncomment when mail registration will be availiable
50+ //self.navigationController?.setNavigationBarHidden(false, animated: animated)
51+ }
52+
53+ private func configureTapgesture(){
54+ let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTap))
55+ view.addGestureRecognizer(tapGesture)
56+ }
57+
58+ @objc func handleTap(){
59+ view.endEditing(true)
60+ }
61+
62+ @objc func activateLogInProcess(){
63+ if logInButton.isEnabled {
64+ // MARK:- when log in is succeeded do I need to go there?
65+ let vc = storyboard!.instantiateViewController(withIdentifier: newsController) as! NewsController
66+ present(vc, animated: true) {
67+ print("logged in")
68+ }
69+ DataStorage.standard.setIsLoggedIn(value: true)
70+ view.endEditing(true)
71+ }
72+ }
73+
74+ func setUpView(){
75+ mailTextField.delegate = self
76+ view.addSubview(keyboardBar)
77+
78+ view.addConstraintsWithFormat(format: "H:|[v0]|", views: keyboardBar)
79+ view.addConstraintsWithFormat(format: "V:[v0(50)]", views: keyboardBar)
80+
81+ setUpBarComponents()
82+
83+ bottomConstraint = NSLayoutConstraint(item: keyboardBar, attribute: .bottom, relatedBy: .equal, toItem: view.safeAreaLayoutGuide, attribute: .bottom, multiplier: 1, constant: 0)
84+ view.addConstraint(bottomConstraint!)
85+
86+ // for keyboard notifications
87+ NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardNotifications), name: UIResponder.keyboardWillShowNotification, object: nil)
88+
89+ NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardNotifications), name: UIResponder.keyboardWillHideNotification, object: nil)
90+
91+ // for log in button notifications
92+ NotificationCenter.default.addObserver(self, selector: #selector(inputDidChanged), name: UITextField.textDidChangeNotification, object: mailTextField)
93+
94+ NotificationCenter.default.addObserver(self, selector: #selector(inputDidChanged), name: UITextField.textDidBeginEditingNotification, object: mailTextField)
95+ }
96+
97+ @objc func inputDidChanged(notification: NSNotification){
98+ if mailTextField.text?.isEmpty ?? true
99+ {
100+ logInButton.isEnabled = false
101+ logInButton.setTitleColor(LogInViewController.titleColor.withAlphaComponent(0.5), for: .normal)
102+ }
103+ else
104+ {
105+ logInButton.isEnabled = true
106+ logInButton.setTitleColor(LogInViewController.titleColor.withAlphaComponent(1), for: .normal)
107+ }
108+ }
109+
110+ @objc func handleKeyboardNotifications(notification: NSNotification){
111+ if let userInfo = notification.userInfo{
112+ // UIKeyboardFrameEndUserInfoKey
113+ let keyBoardFrame = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
114+ bottomConstraint?.constant = notification.name == UIResponder.keyboardWillShowNotification ? -keyBoardFrame.height+view.safeAreaInsets.bottom : 0
115+
116+ UIView.animate(withDuration: 0, delay: 0, options: .curveEaseOut, animations: {
117+ self.view.layoutIfNeeded()
118+ }) { (completed) in
119+
120+ }
121+ }
122+ }
123+
124+ func setUpBarComponents(){
125+ keyboardBar.addSubview(logInButton)
126+ keyboardBar.addConstraintsWithFormat(format: "H:[v0(60)]-16-|", views: logInButton)
127+ keyboardBar.addConstraintsWithFormat(format: "V:|[v0]|", views: logInButton)
128+ }
129+}
130+
131+
132+extension LogInViewController: UITextFieldDelegate{
133+ func textFieldShouldReturn(_ textField: UITextField) -> Bool
134+ {
135+ textField.resignFirstResponder()
136+ return true
137+ }
138+}
GDproject/Controller/News/ChannelsController.swiftdeleted−35
@@ -1,35 +0,0 @@
1−//
2−// PostTable.swift
3−// GDproject
4−//
5−// Created by cstore on 13/02/2019.
6−// Copyright © 2019 drHSE. All rights reserved.
7−//
8−
9−import UIKit
10−
11−class ChannelsController: UITableViewController {
12−
13− override func viewDidLoad() {
14− super.viewDidLoad()
15−
16− // Uncomment the following line to preserve selection between presentations
17− // self.clearsSelectionOnViewWillAppear = false
18−
19− // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
20− // self.navigationItem.rightBarButtonItem = self.editButtonItem
21− }
22−
23− // MARK: - Table view data source
24−
25− override func numberOfSections(in tableView: UITableView) -> Int {
26− // #warning Incomplete implementation, return the number of sections
27− return 0
28− }
29−
30− override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
31− // #warning Incomplete implementation, return the number of rows
32− return 0
33− }
34−
35−}
GDproject/Controller/News/HeaderNewsChannels.swiftdeleted−54
@@ -1,54 +0,0 @@
1−//
2−// HeaderNewsChannels.swift
3−// GDproject
4−//
5−// Created by cstore on 13/02/2019.
6−// Copyright © 2019 drHSE. All rights reserved.
7−//
8−
9−import UIKit
10−import TinyConstraints
11−
12−class HeaderNewsChannels: UITableViewCell {
13−
14− weak var tableView: UITableView?
15−
16− weak var vc: NewsController?
17− weak var vcProfile: ProfileViewController?
18−
19−
20− override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
21− super.init(style: style, reuseIdentifier: reuseIdentifier)
22− backgroundColor = .white
23− setUpCell()
24− }
25−
26− required init?(coder aDecoder: NSCoder) {
27− super.init(coder: aDecoder)
28− }
29−
30− func setUpCell(){
31−
32− addSubview(postsChannelsSegment)
33− postsChannelsSegment.selectedSegmentIndex = 0
34− postsChannelsSegment.addTarget(self, action: #selector(changedValue), for: .valueChanged)
35− postsChannelsSegment.edgesToSuperview(insets: .left(16) + .right(16) + .top(8) + .bottom(8))
36− }
37−
38− // Initialize
39− var postsChannelsSegment: UISegmentedControl = UISegmentedControl(items: ["Posts", "Channels"])
40−
41− @objc func changedValue(_ sender: UISegmentedControl) {
42− let index = sender.selectedSegmentIndex
43−
44− switch index {
45− case 0:
46− vc?.setUpNavigationItemsforPosts()
47− case 1:
48− vc?.setUpNavigationItemsForChannels()
49− default:
50− break
51− }
52− }
53−}
54−
GDproject/Controller/BasicInfoCell.swift → GDproject/Controller/Profile/BasicInfoCell.swiftrenamed

The content is the same.

GDproject/Controller/BasicInfoController.swift → GDproject/Controller/Profile/BasicInfoController.swiftrenamed

The content is the same.

GDproject/Controller/InfoCell.swift → GDproject/Controller/Profile/InfoCell.swiftrenamed

The content is the same.

GDproject/Controller/InviteViewController.swift → GDproject/Controller/Profile/InviteViewController.swiftrenamed

The content is the same.

GDproject/Controller/ProfileViewController.swift → GDproject/Controller/Profile/ProfileViewController.swiftrenamed+2−3
@@ -48,15 +48,14 @@ class ProfileViewController: UIViewController
4848 {
4949 super.viewDidLoad()
5050
51− posts.type = .NONE
52−
5351 posts.dataSourse = [Post(dataArray: [.text("Le Lorem Ipsum est simplement du faux texte employé dans la composition et la mise en page avant impression. Le Lorem Ipsum est le faux texte standard de l'imprimerie depuis les années 1500, quand un imprimeur anonyme assembla ensemble des morceaux de texte pour réaliser un livre spécimen de polices de texte. comme Aldus PageMaker. est qu'il possède une distribution de lettres plus ou moins normale, et en tout cas comparable avec celle du français standard. De nombreuses suites logicielles de mise en page ou éditeurs de sites Web ont fait du Lorem Ipsum leur faux texte par défaut, et une recherche pour 'Lorem Ipsum' vous conduira vers de nombreux sites qui n'en sont encore qu'à leur phase de construction. Plusieurs versions sont apparues avec le temps, parfois par accident, souvent intentionnellement (histoire d'y rajouter de petits clins d'oeil, voire des phrases embarassantes).")]), Post(dataArray: [.text("Il n'a pas fait que survivre cinq siècles, mais s'est aussi adapté à la bureautique informatique, sans que son contenu n'en soit modifié. Il a été popularisé dans les années 1960 grâce à la vente de feuilles Letraset contenant des passages du Lorem Ipsum, et, plus récemment, par son inclusion dans des applications de mise en page de texte, comme Aldus PageMaker. .")])]
5452
5553 // basicInfo.dataSourse =
5654
5755 posts.viewController = self
56+ posts.type = .NONE
5857
59− tableView.register(HeaderNewsChannels.self, forCellReuseIdentifier: headerNewsChannelsVC)
58+ tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
6059
6160 tableView.register(PostViewCell.self, forCellReuseIdentifier: postCellId)
6261
GDproject/Controller/SettingsViewController.swift → GDproject/Controller/Profile/SettingsViewController.swiftrenamed

The content is the same.

GDproject/DataStorage.swiftnew file+45
@@ -0,0 +1,45 @@
1+//
2+// DataStorage.swift
3+// GDproject
4+//
5+// Created by cstore on 21/02/2019.
6+// Copyright © 2019 drHSE. All rights reserved.
7+//
8+
9+import Foundation
10+
11+/**
12+ _DataStorage_ class is aimed to store user private settings
13+ to display correct data after user leaving the app
14+ */
15+class DataStorage{
16+
17+ private init(){}
18+
19+ static let standard = DataStorage()
20+
21+ // add channel
22+
23+ // delete channel
24+
25+ /**
26+ Function for setting log in status of user
27+ */
28+ func setIsLoggedIn(value: Bool){
29+ UserDefaults.standard.set(value, forKey: UserDefaultsKeys.loggedIn.rawValue)
30+ }
31+
32+ /**
33+ Function to determine is user logged in already or not
34+ */
35+ func isLoggedIn() -> Bool {
36+ return UserDefaults.standard.bool(forKey: UserDefaultsKeys.loggedIn.rawValue)
37+ }
38+}
39+
40+/**
41+ Enum to store UserDefaults keys for getting and setting values
42+ */
43+enum UserDefaultsKeys: String{
44+ case loggedIn
45+}
GDproject/Extentions.swift+22
@@ -34,3 +34,25 @@ extension UIView
3434 addConstraints(NSLayoutConstraint.constraints(withVisualFormat: format, options: NSLayoutConstraint.FormatOptions(), metrics: nil, views: viewsDictionary))
3535 }
3636}
37+
38+
39+extension UIStoryboard {
40+
41+ private static let userEdit = UIStoryboard(name: "Main", bundle: nil)
42+
43+ class func makeChannelsListController() -> ChannelListController {
44+ return UIStoryboard.userEdit.instantiateViewController(withIdentifier: channelListControllerId) as! ChannelListController
45+ }
46+
47+ class func makeNewsController() -> NewsController {
48+ return UIStoryboard.userEdit.instantiateViewController(withIdentifier: newsController) as! NewsController
49+ }
50+
51+ class func tabBarController() -> UITabBarController{
52+ return UIStoryboard.userEdit.instantiateViewController(withIdentifier: "TabBar") as! UITabBarController
53+ }
54+
55+ class func navChannels() ->UINavigationController{
56+ return UIStoryboard.userEdit.instantiateViewController(withIdentifier: "navChannels") as! UINavigationController
57+ }
58+}
GDproject/MainController.swiftnew file+44
@@ -0,0 +1,44 @@
1+//
2+// MainController.swift
3+// GDproject
4+//
5+// Created by cstore on 21/02/2019.
6+// Copyright © 2019 drHSE. All rights reserved.
7+//
8+
9+import UIKit
10+
11+class MainController: UINavigationController {
12+
13+ override func viewDidLoad() {
14+ super.viewDidLoad()
15+
16+// if false {
17+// perform(#selector(showLogInController), with: nil, afterDelay: 0.01)
18+// } else {
19+// perform(#selector(fhfh), with: nil, afterDelay: 0.01)
20+//
21+// }
22+ }
23+
24+// @objc func showLogInController(){
25+// let vc = storyboard!.instantiateViewController(withIdentifier: logInController) as! LogInViewController
26+// present(vc, animated: true) {
27+// print("opportunity to log in")
28+// }
29+// }
30+
31+// @objc func fhfh(){
32+//
33+// let newsController = NC()
34+// viewControllers = [newsController]
35+// }
36+// override func viewDidAppear(_ animated: Bool) {
37+// super.viewDidAppear(animated)
38+//
39+//
40+// }
41+}
42+
43+
44+
GDproject/Simple model/Channel.swiftnew file+35
@@ -0,0 +1,35 @@
1+//
2+// Channel.swift
3+// GDproject
4+//
5+// Created by cstore on 20/02/2019.
6+// Copyright © 2019 drHSE. All rights reserved.
7+//
8+
9+import Foundation
10+
11+class Channel: Equatable {
12+ static func == (lhs: Channel, rhs: Channel) -> Bool {
13+ return (lhs.title == rhs.title &&
14+ lhs.subtitle == rhs.subtitle &&
15+ lhs.people == rhs.people &&
16+ lhs.hashtags == rhs.hashtags)
17+ }
18+
19+ var title = String()
20+ var subtitle = String()
21+
22+ var hashtags: [String] = []
23+ var people: [String] = []
24+
25+ var posts: [Post] = []
26+
27+ init(title: String, subtitle: String, hashtags: [String], people: [String], posts: [Post])
28+ {
29+ self.title = title
30+ self.subtitle = subtitle
31+ self.people = people
32+ self.hashtags = hashtags
33+ self.posts = posts
34+ }
35+}
GDproject/Supporting files/AppDelegate.swift+17−5
@@ -11,11 +11,25 @@ import UIKit
1111@UIApplicationMain
1212class AppDelegate: UIResponder, UIApplicationDelegate {
1313
14+ var coordinator: ChannelsCoordinator!
15+ var tabCoordinator: TabbarCoordinator!
16+
1417 var window: UIWindow?
18+ var rootController: UINavigationController? {
19+ return self.window!.rootViewController as? UINavigationController
20+ }
1521
16−
17− func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
18− // Override point for customization after application launch.
22+ private func makeCoordinator(with: UINavigationController) -> ChannelsCoordinator {
23+ return ChannelsCoordinator(currentChannel: Channel(title: "example", subtitle: "ex", hashtags: ["none"], people: ["none"], posts: []), navigationController: with)
24+ }
25+
26+ func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool
27+ {
28+
29+ // TODO:- determine what to do here: log in or tabbar
30+ tabCoordinator = TabbarCoordinator(window: window!)
31+ tabCoordinator.start()
32+
1933 return true
2034 }
2135
@@ -40,7 +54,5 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
4054 func applicationWillTerminate(_ application: UIApplication) {
4155 // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
4256 }
43−
44−
4557}
4658
GDproject/Supporting files/Base.lproj/LaunchScreen.storyboard+7−3
@@ -1,7 +1,11 @@
1−<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2−<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
1+<?xml version="1.0" encoding="UTF-8"?>
2+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
3+ <device id="retina4_7" orientation="portrait">
4+ <adaptation id="fullscreen"/>
5+ </device>
36 <dependencies>
4− <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
7+ <deployment identifier="iOS"/>
8+ <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/>
59 <capability name="Safe area layout guides" minToolsVersion="9.0"/>
610 <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
711 </dependencies>