git.iko.soy/dashared/GDproject
on master help sign in
Merge pull request #2 from dashared/developer

profile from v0.2

commitcb2b3ac4f7e3303f8877857732fd101da35f4a31 authorDarya Rednikina <31587869+dashared@users.noreply.github.com> dateSun 17 Feb 2019, 14:33 (8 years ago) parent3c5c0623a24fe0
22 files changed+1632−18
GDproject.xcodeproj/project.pbxproj+39−6 GDproject/Base.lproj/Main.storyboard+250−7 GDproject/Constants.swift+7 GDproject/Controller/BasicInfoCell.swift+39 GDproject/Controller/BasicInfoController.swift+75 GDproject/Controller/InfoCell.swift+44 GDproject/Controller/InviteViewController.swift+140 GDproject/Controller/News/ChannelsController.swift+35 GDproject/Controller/News/FullPostController.swift+103 GDproject/Controller/News/HeaderNewsChannels.swift+54 GDproject/Controller/News/NewPostViewController.swift+257 GDproject/Controller/News/NewsController.swift+164 GDproject/Controller/News/NewsVC.swift+86 GDproject/Controller/News/PostViewCell.swift+50−2 GDproject/Controller/ProfileViewController.swift+144 GDproject/Controller/SettingsViewController.swift+49 GDproject/Extentions.swift+36 GDproject/MyStackView.swift+27 GDproject/Simple model/Post.swift+9−1 GDproject/Simple model/User.swift+3−2 GDproject/Supporting files/Assets.xcassets/kitten.imageset/Contents.json+21 GDproject/Supporting files/Assets.xcassets/kitten.imageset/s1200-2.jpeg
GDproject.xcodeproj/project.pbxproj+39−6
@@ -7,6 +7,14 @@
77 objects = {
88
99/* Begin PBXBuildFile section */
10+ 125BD57D22171D2A008A3575 /* ProfileViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 125BD57C22171D2A008A3575 /* ProfileViewController.swift */; };
11+ 125BD57F22171D73008A3575 /* Extentions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 125BD57E22171D73008A3575 /* Extentions.swift */; };
12+ 125BD5812217314A008A3575 /* NewsVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 125BD5802217314A008A3575 /* NewsVC.swift */; };
13+ 12DB7FD722181CD20096878E /* BasicInfoController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12DB7FD622181CD20096878E /* BasicInfoController.swift */; };
14+ 12DB7FD922181E660096878E /* BasicInfoCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12DB7FD822181E660096878E /* BasicInfoCell.swift */; };
15+ 12DB7FDB2218590C0096878E /* InfoCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12DB7FDA2218590C0096878E /* InfoCell.swift */; };
16+ 12DB7FDD221872F80096878E /* SettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12DB7FDC221872F80096878E /* SettingsViewController.swift */; };
17+ 12DB7FDF221877160096878E /* InviteViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12DB7FDE221877160096878E /* InviteViewController.swift */; };
1018 12E36D9C221424EA006FCDD7 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12E36D9B221424EA006FCDD7 /* AppDelegate.swift */; };
1119 12E36D9E221424EA006FCDD7 /* NewsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12E36D9D221424EA006FCDD7 /* NewsController.swift */; };
1220 12E36DA1221424EA006FCDD7 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 12E36D9F221424EA006FCDD7 /* Main.storyboard */; };
@@ -52,6 +60,14 @@
5260/* End PBXCopyFilesBuildPhase section */
5361
5462/* Begin PBXFileReference section */
63+ 125BD57C22171D2A008A3575 /* ProfileViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileViewController.swift; sourceTree = "<group>"; };
64+ 125BD57E22171D73008A3575 /* Extentions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Extentions.swift; sourceTree = "<group>"; };
65+ 125BD5802217314A008A3575 /* NewsVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewsVC.swift; sourceTree = "<group>"; };
66+ 12DB7FD622181CD20096878E /* BasicInfoController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BasicInfoController.swift; sourceTree = "<group>"; };
67+ 12DB7FD822181E660096878E /* BasicInfoCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BasicInfoCell.swift; sourceTree = "<group>"; };
68+ 12DB7FDA2218590C0096878E /* InfoCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfoCell.swift; sourceTree = "<group>"; };
69+ 12DB7FDC221872F80096878E /* SettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewController.swift; sourceTree = "<group>"; };
70+ 12DB7FDE221877160096878E /* InviteViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InviteViewController.swift; sourceTree = "<group>"; };
5571 12E36D98221424EA006FCDD7 /* GDproject.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = GDproject.app; sourceTree = BUILT_PRODUCTS_DIR; };
5672 12E36D9B221424EA006FCDD7 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
5773 12E36D9D221424EA006FCDD7 /* NewsController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewsController.swift; sourceTree = "<group>"; };
@@ -118,6 +134,8 @@
118134 children = (
119135 12E36DCF22145923006FCDD7 /* Controller */,
120136 12E36DCD22144756006FCDD7 /* Constants.swift */,
137+ 125BD57E22171D73008A3575 /* Extentions.swift */,
138+ 12E36DD422156559006FCDD7 /* MyStackView.swift */,
121139 12E36DBB2214402B006FCDD7 /* Supporting files */,
122140 12E36DBA2214401B006FCDD7 /* Simple model */,
123141 12E36D9F221424EA006FCDD7 /* Main.storyboard */,
@@ -148,13 +166,13 @@
148166 12E36DCF22145923006FCDD7 /* Controller */ = {
149167 isa = PBXGroup;
150168 children = (
151− 12E36DD422156559006FCDD7 /* MyStackView.swift */,
152− 12E36DD022148122006FCDD7 /* FullPostController.swift */,
153− 12E36DC522144266006FCDD7 /* HeaderNewsChannels.swift */,
154− 12E36DC722144374006FCDD7 /* ChannelsController.swift */,
155− 12E36D9D221424EA006FCDD7 /* NewsController.swift */,
169+ 125BD57C22171D2A008A3575 /* ProfileViewController.swift */,
170+ 12DB7FDE221877160096878E /* InviteViewController.swift */,
171+ 12DB7FDC221872F80096878E /* SettingsViewController.swift */,
172+ 12DB7FD622181CD20096878E /* BasicInfoController.swift */,
173+ 12DB7FDA2218590C0096878E /* InfoCell.swift */,
174+ 12DB7FD822181E660096878E /* BasicInfoCell.swift */,
156175 12E36DD322156519006FCDD7 /* News */,
157− 12E36DC922144635006FCDD7 /* NewPostViewController.swift */,
158176 );
159177 path = Controller;
160178 sourceTree = "<group>";
@@ -162,6 +180,12 @@
162180 12E36DD322156519006FCDD7 /* News */ = {
163181 isa = PBXGroup;
164182 children = (
183+ 12E36DC922144635006FCDD7 /* NewPostViewController.swift */,
184+ 12E36DD022148122006FCDD7 /* FullPostController.swift */,
185+ 12E36DC522144266006FCDD7 /* HeaderNewsChannels.swift */,
186+ 12E36DC722144374006FCDD7 /* ChannelsController.swift */,
187+ 12E36D9D221424EA006FCDD7 /* NewsController.swift */,
188+ 125BD5802217314A008A3575 /* NewsVC.swift */,
165189 12E36DCB22144725006FCDD7 /* PostViewCell.swift */,
166190 );
167191 path = News;
@@ -249,14 +273,23 @@
249273 12E36DD522156559006FCDD7 /* MyStackView.swift in Sources */,
250274 12E36DC822144374006FCDD7 /* ChannelsController.swift in Sources */,
251275 12E36DB922144016006FCDD7 /* User.swift in Sources */,
276+ 125BD5812217314A008A3575 /* NewsVC.swift in Sources */,
252277 12E36DB72214400A006FCDD7 /* Post.swift in Sources */,
278+ 12DB7FDF221877160096878E /* InviteViewController.swift in Sources */,
253279 12E36DCA22144635006FCDD7 /* NewPostViewController.swift in Sources */,
254280 12E36D9E221424EA006FCDD7 /* NewsController.swift in Sources */,
255281 12E36DC622144266006FCDD7 /* HeaderNewsChannels.swift in Sources */,
256282 12E36DCC22144725006FCDD7 /* PostViewCell.swift in Sources */,
283+ 125BD57F22171D73008A3575 /* Extentions.swift in Sources */,
257284 12E36DD122148122006FCDD7 /* FullPostController.swift in Sources */,
285+ 125BD57D22171D2A008A3575 /* ProfileViewController.swift in Sources */,
286+ 12DB7FDB2218590C0096878E /* InfoCell.swift in Sources */,
287+ 12DB7FD922181E660096878E /* BasicInfoCell.swift in Sources */,
258288 12E36D9C221424EA006FCDD7 /* AppDelegate.swift in Sources */,
289+ 12DB7FD722181CD20096878E /* BasicInfoController.swift in Sources */,
259290 12E36DCE22144756006FCDD7 /* Constants.swift in Sources */,
291+ 12DB7FDD221872F80096878E /* SettingsViewController.swift in Sources */,
292+
260293 );
261294 runOnlyForDeploymentPostprocessing = 0;
262295 };
GDproject/Base.lproj/Main.storyboard+250−7
@@ -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="NuV-ZG-ld2">
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">
33 <device id="retina4_7" orientation="portrait">
44 <adaptation id="fullscreen"/>
55 </device>
@@ -7,6 +7,7 @@
77 <deployment identifier="iOS"/>
88 <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/>
99 <capability name="Safe area layout guides" minToolsVersion="9.0"/>
10+ <capability name="Stack View standard spacing" minToolsVersion="9.0"/>
1011 <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
1112 </dependencies>
1213 <scenes>
@@ -19,7 +20,7 @@
1920 <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
2021 <subviews>
2122 <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">
22− <rect key="frame" x="0.0" y="116" width="375" height="551"/>
23+ <rect key="frame" x="0.0" y="116" width="375" height="502"/>
2324 <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
2425 </tableView>
2526 </subviews>
@@ -39,7 +40,210 @@
3940 </viewController>
4041 <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
4142 </objects>
42− <point key="canvasLocation" x="1076" y="132.68365817091455"/>
43+ <point key="canvasLocation" x="2015.2" y="132.68365817091455"/>
44+ </scene>
45+ <!--Profile View Controller-->
46+ <scene sceneID="rQ6-TM-V7T">
47+ <objects>
48+ <viewController storyboardIdentifier="ProfileViewController" id="R4D-Ao-uvG" customClass="ProfileViewController" customModule="GDproject" customModuleProvider="target" sceneMemberID="viewController">
49+ <view key="view" contentMode="scaleToFill" id="N0n-wL-Y5j">
50+ <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
51+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
52+ <subviews>
53+ <tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="cay-ea-rTl">
54+ <rect key="frame" x="0.0" y="116" width="375" height="502"/>
55+ <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
56+ <view key="tableHeaderView" contentMode="scaleToFill" id="kFZ-3c-OFY">
57+ <rect key="frame" x="0.0" y="0.0" width="375" height="199"/>
58+ <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
59+ <subviews>
60+ <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="93Q-rB-JKk">
61+ <rect key="frame" x="16" y="16" width="100" height="100"/>
62+ <constraints>
63+ <constraint firstAttribute="width" constant="100" id="3Xq-K8-0jL"/>
64+ <constraint firstAttribute="height" constant="100" id="d83-z4-p3p"/>
65+ </constraints>
66+ </imageView>
67+ <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="equalSpacing" spacingType="standard" translatesAutoresizingMaskIntoConstraints="NO" id="HD1-1N-Rae">
68+ <rect key="frame" x="136" y="16" width="223" height="100"/>
69+ <subviews>
70+ <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="equalSpacing" spacingType="standard" translatesAutoresizingMaskIntoConstraints="NO" id="OJ4-19-keW">
71+ <rect key="frame" x="0.0" y="0.0" width="223" height="49"/>
72+ <subviews>
73+ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="vff-nz-u6X">
74+ <rect key="frame" x="0.0" y="0.0" width="223" height="21.5"/>
75+ <fontDescription key="fontDescription" type="boldSystem" pointSize="18"/>
76+ <nil key="textColor"/>
77+ <nil key="highlightedColor"/>
78+ </label>
79+ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="umX-IO-ePK">
80+ <rect key="frame" x="0.0" y="29.5" width="223" height="19.5"/>
81+ <fontDescription key="fontDescription" type="system" pointSize="16"/>
82+ <nil key="textColor"/>
83+ <nil key="highlightedColor"/>
84+ </label>
85+ </subviews>
86+ </stackView>
87+ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ypY-U6-bJm">
88+ <rect key="frame" x="0.0" y="83" width="223" height="17"/>
89+ <fontDescription key="fontDescription" type="system" pointSize="14"/>
90+ <nil key="textColor"/>
91+ <nil key="highlightedColor"/>
92+ </label>
93+ </subviews>
94+ <constraints>
95+ <constraint firstAttribute="height" constant="100" id="8vI-3o-mkr"/>
96+ </constraints>
97+ </stackView>
98+ <stackView opaque="NO" contentMode="scaleToFill" distribution="equalSpacing" spacingType="standard" translatesAutoresizingMaskIntoConstraints="NO" id="hFb-Uj-GwE">
99+ <rect key="frame" x="16" y="124" width="343" height="30"/>
100+ <subviews>
101+ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="vCL-BI-I2h">
102+ <rect key="frame" x="0.0" y="0.0" width="35.5" height="30"/>
103+ <fontDescription key="fontDescription" type="system" pointSize="14"/>
104+ <nil key="textColor"/>
105+ <nil key="highlightedColor"/>
106+ </label>
107+ <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="yir-N6-Q6f">
108+ <rect key="frame" x="297" y="0.0" width="46" height="30"/>
109+ <state key="normal" title="Button"/>
110+ </button>
111+ </subviews>
112+ </stackView>
113+ <segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="vC8-pT-qzP">
114+ <rect key="frame" x="16" y="161" width="343" height="29"/>
115+ <segments>
116+ <segment title="Posts"/>
117+ <segment title="Basic Info"/>
118+ </segments>
119+ <connections>
120+ <action selector="valueChanged:" destination="R4D-Ao-uvG" eventType="valueChanged" id="KpK-xZ-KhE"/>
121+ </connections>
122+ </segmentedControl>
123+ </subviews>
124+ <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
125+ <constraints>
126+ <constraint firstAttribute="trailing" secondItem="vC8-pT-qzP" secondAttribute="trailing" constant="16" id="1pN-90-cEV"/>
127+ <constraint firstItem="93Q-rB-JKk" firstAttribute="top" secondItem="kFZ-3c-OFY" secondAttribute="top" constant="16" id="5r9-SM-GHQ"/>
128+ <constraint firstAttribute="bottom" secondItem="vC8-pT-qzP" secondAttribute="bottom" constant="10" id="7gm-xL-uhs"/>
129+ <constraint firstItem="vC8-pT-qzP" firstAttribute="top" secondItem="hFb-Uj-GwE" secondAttribute="bottom" constant="7" id="GC2-zv-hp0"/>
130+ <constraint firstItem="hFb-Uj-GwE" firstAttribute="leading" secondItem="kFZ-3c-OFY" secondAttribute="leading" constant="16" id="HWn-2I-NvS"/>
131+ <constraint firstAttribute="trailing" secondItem="hFb-Uj-GwE" secondAttribute="trailing" constant="16" id="MHn-bJ-vkd"/>
132+ <constraint firstItem="HD1-1N-Rae" firstAttribute="leading" secondItem="93Q-rB-JKk" secondAttribute="trailing" constant="20" id="Zmg-ZS-Eyy"/>
133+ <constraint firstItem="93Q-rB-JKk" firstAttribute="leading" secondItem="kFZ-3c-OFY" secondAttribute="leading" constant="16" id="f3K-RA-5qe"/>
134+ <constraint firstAttribute="trailing" secondItem="HD1-1N-Rae" secondAttribute="trailing" constant="16" id="qT1-ct-8ed"/>
135+ <constraint firstItem="HD1-1N-Rae" firstAttribute="top" secondItem="kFZ-3c-OFY" secondAttribute="top" constant="16" id="zZe-Oe-Okw"/>
136+ <constraint firstItem="vC8-pT-qzP" firstAttribute="leading" secondItem="kFZ-3c-OFY" secondAttribute="leading" constant="16" id="zrN-AS-TUX"/>
137+ </constraints>
138+ </view>
139+ </tableView>
140+ </subviews>
141+ <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
142+ <constraints>
143+ <constraint firstItem="cay-ea-rTl" firstAttribute="leading" secondItem="HGw-oo-OLI" secondAttribute="leading" id="37r-TE-87A"/>
144+ <constraint firstItem="HGw-oo-OLI" firstAttribute="trailing" secondItem="cay-ea-rTl" secondAttribute="trailing" id="LF0-J4-EyT"/>
145+ <constraint firstItem="cay-ea-rTl" firstAttribute="top" secondItem="HGw-oo-OLI" secondAttribute="top" id="Me6-du-vNl"/>
146+ <constraint firstItem="HGw-oo-OLI" firstAttribute="bottom" secondItem="cay-ea-rTl" secondAttribute="bottom" id="YBy-bu-FUY"/>
147+ </constraints>
148+ <viewLayoutGuide key="safeArea" id="HGw-oo-OLI"/>
149+ </view>
150+ <navigationItem key="navigationItem" id="jN7-hp-Zl8"/>
151+ <connections>
152+ <outlet property="facultyLabel" destination="ypY-U6-bJm" id="88V-uI-Rt8"/>
153+ <outlet property="nameLabel" destination="umX-IO-ePK" id="bY9-BV-XG2"/>
154+ <outlet property="newMessageButton" destination="yir-N6-Q6f" id="B3W-6Z-FLK"/>
155+ <outlet property="placeLabel" destination="vCL-BI-I2h" id="r5C-RE-QOe"/>
156+ <outlet property="profileImageView" destination="93Q-rB-JKk" id="Q3z-aT-aGK"/>
157+ <outlet property="profileView" destination="kFZ-3c-OFY" id="aJd-83-7kt"/>
158+ <outlet property="segmentedControl" destination="vC8-pT-qzP" id="9en-ed-hiM"/>
159+ <outlet property="surnameLabel" destination="vff-nz-u6X" id="je2-H8-N6i"/>
160+ <outlet property="tableView" destination="cay-ea-rTl" id="RlG-PF-8DP"/>
161+ </connections>
162+ </viewController>
163+ <placeholder placeholderIdentifier="IBFirstResponder" id="sap-zV-B7l" userLabel="First Responder" sceneMemberID="firstResponder"/>
164+ </objects>
165+ <point key="canvasLocation" x="2013.5999999999999" y="957.57121439280365"/>
166+ </scene>
167+ <!--Settings View Controller-->
168+ <scene sceneID="WVn-Qy-9tO">
169+ <objects>
170+ <tableViewController storyboardIdentifier="SettingsViewController" id="zy1-9Z-5P6" customClass="SettingsViewController" customModule="GDproject" customModuleProvider="target" sceneMemberID="viewController">
171+ <tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" id="VhJ-pr-aLb">
172+ <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
173+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
174+ <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
175+ <prototypes>
176+ <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="SettingsCell" textLabel="QDL-KY-T1r" style="IBUITableViewCellStyleDefault" id="IGo-n9-HiV">
177+ <rect key="frame" x="0.0" y="28" width="375" height="44"/>
178+ <autoresizingMask key="autoresizingMask"/>
179+ <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="IGo-n9-HiV" id="gMT-ei-M43">
180+ <rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
181+ <autoresizingMask key="autoresizingMask"/>
182+ <subviews>
183+ <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Title" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="QDL-KY-T1r">
184+ <rect key="frame" x="16" y="0.0" width="343" height="43.5"/>
185+ <autoresizingMask key="autoresizingMask"/>
186+ <fontDescription key="fontDescription" type="system" pointSize="17"/>
187+ <nil key="textColor"/>
188+ <nil key="highlightedColor"/>
189+ </label>
190+ </subviews>
191+ </tableViewCellContentView>
192+ </tableViewCell>
193+ </prototypes>
194+ <connections>
195+ <outlet property="dataSource" destination="zy1-9Z-5P6" id="7hY-TM-IK0"/>
196+ <outlet property="delegate" destination="zy1-9Z-5P6" id="J9r-Hh-aVU"/>
197+ </connections>
198+ </tableView>
199+ </tableViewController>
200+ <placeholder placeholderIdentifier="IBFirstResponder" id="xdg-ZK-4Jv" userLabel="First Responder" sceneMemberID="firstResponder"/>
201+ </objects>
202+ <point key="canvasLocation" x="1986" y="1756"/>
203+ </scene>
204+ <!--Invite View Controller-->
205+ <scene sceneID="DcO-6Y-Iko">
206+ <objects>
207+ <viewController storyboardIdentifier="InviteViewController" id="UFZ-Q3-pIW" customClass="InviteViewController" customModule="GDproject" customModuleProvider="target" sceneMemberID="viewController">
208+ <view key="view" contentMode="scaleToFill" id="Tex-e4-Huf">
209+ <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
210+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
211+ <subviews>
212+ <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="fillProportionally" spacing="12" translatesAutoresizingMaskIntoConstraints="NO" id="Oc6-Ho-qfI">
213+ <rect key="frame" x="16" y="100" width="343" height="83"/>
214+ <subviews>
215+ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Invite:" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="D2l-JD-WXP">
216+ <rect key="frame" x="0.0" y="0.0" width="343" height="41"/>
217+ <fontDescription key="fontDescription" type="boldSystem" pointSize="34"/>
218+ <nil key="textColor"/>
219+ <nil key="highlightedColor"/>
220+ </label>
221+ <textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="Bk1-tC-5g3">
222+ <rect key="frame" x="0.0" y="53" width="343" height="30"/>
223+ <color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
224+ <nil key="textColor"/>
225+ <fontDescription key="fontDescription" type="system" pointSize="14"/>
226+ <textInputTraits key="textInputTraits"/>
227+ </textField>
228+ </subviews>
229+ </stackView>
230+ </subviews>
231+ <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
232+ <constraints>
233+ <constraint firstItem="Oc6-Ho-qfI" firstAttribute="top" secondItem="WUm-xh-PeM" secondAttribute="top" constant="80" id="2uM-Ya-0qT"/>
234+ <constraint firstItem="WUm-xh-PeM" firstAttribute="trailing" secondItem="Oc6-Ho-qfI" secondAttribute="trailing" constant="16" id="DAS-R5-CYz"/>
235+ <constraint firstItem="Oc6-Ho-qfI" firstAttribute="leading" secondItem="WUm-xh-PeM" secondAttribute="leading" constant="16" id="vTc-Zq-XMS"/>
236+ </constraints>
237+ <viewLayoutGuide key="safeArea" id="WUm-xh-PeM"/>
238+ </view>
239+ <connections>
240+ <outlet property="inviteLabel" destination="D2l-JD-WXP" id="g0g-Oo-uzs"/>
241+ <outlet property="mailTextField" destination="Bk1-tC-5g3" id="JQ3-v9-MK6"/>
242+ </connections>
243+ </viewController>
244+ <placeholder placeholderIdentifier="IBFirstResponder" id="t8a-Sv-mbh" userLabel="First Responder" sceneMemberID="firstResponder"/>
245+ </objects>
246+ <point key="canvasLocation" x="2803" y="1756"/>
43247 </scene>
44248 <!--New Post View Controller-->
45249 <scene sceneID="TVK-xu-UdJ">
@@ -70,7 +274,7 @@
70274 </viewController>
71275 <placeholder placeholderIdentifier="IBFirstResponder" id="3fd-7N-vPg" userLabel="First Responder" sceneMemberID="firstResponder"/>
72276 </objects>
73− <point key="canvasLocation" x="1773" y="132"/>
277+ <point key="canvasLocation" x="2711.1999999999998" y="131.78410794602701"/>
74278 </scene>
75279 <!--Full Post Controller-->
76280 <scene sceneID="nNH-1Q-jks">
@@ -88,12 +292,13 @@
88292 </tableViewController>
89293 <placeholder placeholderIdentifier="IBFirstResponder" id="CP8-RO-wn0" userLabel="First Responder" sceneMemberID="firstResponder"/>
90294 </objects>
91− <point key="canvasLocation" x="2506" y="130"/>
295+ <point key="canvasLocation" x="3444" y="129.98500749625188"/>
92296 </scene>
93− <!--Navigation Controller-->
297+ <!--Posts-->
94298 <scene sceneID="RSd-UJ-34B">
95299 <objects>
96300 <navigationController automaticallyAdjustsScrollViewInsets="NO" id="NuV-ZG-ld2" sceneMemberID="viewController">
301+ <tabBarItem key="tabBarItem" title="Posts" id="dH2-sL-YsR"/>
97302 <toolbarItems/>
98303 <navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" largeTitles="YES" id="6qB-3A-tuL">
99304 <rect key="frame" x="0.0" y="20" width="375" height="96"/>
@@ -106,7 +311,45 @@
106311 </navigationController>
107312 <placeholder placeholderIdentifier="IBFirstResponder" id="POV-5T-jeQ" userLabel="First Responder" sceneMemberID="firstResponder"/>
108313 </objects>
109− <point key="canvasLocation" x="150" y="133"/>
314+ <point key="canvasLocation" x="1088.8" y="132.68365817091455"/>
315+ </scene>
316+ <!--Profile-->
317+ <scene sceneID="dJj-Hp-Wa9">
318+ <objects>
319+ <navigationController automaticallyAdjustsScrollViewInsets="NO" id="tae-5q-wvT" sceneMemberID="viewController">
320+ <tabBarItem key="tabBarItem" title="Profile" id="lYy-LQ-AcR"/>
321+ <toolbarItems/>
322+ <navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" largeTitles="YES" id="q3a-ph-c8V">
323+ <rect key="frame" x="0.0" y="20" width="375" height="96"/>
324+ <autoresizingMask key="autoresizingMask"/>
325+ </navigationBar>
326+ <nil name="viewControllers"/>
327+ <connections>
328+ <segue destination="R4D-Ao-uvG" kind="relationship" relationship="rootViewController" id="aF6-zK-hCB"/>
329+ </connections>
330+ </navigationController>
331+ <placeholder placeholderIdentifier="IBFirstResponder" id="Fvm-qf-2Ve" userLabel="First Responder" sceneMemberID="firstResponder"/>
332+ </objects>
333+ <point key="canvasLocation" x="1089" y="958"/>
334+ </scene>
335+ <!--Tab Bar Controller-->
336+ <scene sceneID="HCR-WO-p7g">
337+ <objects>
338+ <tabBarController automaticallyAdjustsScrollViewInsets="NO" id="IeP-4W-8LT" sceneMemberID="viewController">
339+ <toolbarItems/>
340+ <tabBar key="tabBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="3pl-mU-U30">
341+ <rect key="frame" x="0.0" y="0.0" width="1000" height="1000"/>
342+ <autoresizingMask key="autoresizingMask"/>
343+ <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
344+ </tabBar>
345+ <connections>
346+ <segue destination="NuV-ZG-ld2" kind="relationship" relationship="viewControllers" id="XuX-8s-fZU"/>
347+ <segue destination="tae-5q-wvT" kind="relationship" relationship="viewControllers" id="wCJ-4N-lfC"/>
348+ </connections>
349+ </tabBarController>
350+ <placeholder placeholderIdentifier="IBFirstResponder" id="gcF-2V-bfC" userLabel="First Responder" sceneMemberID="firstResponder"/>
351+ </objects>
352+ <point key="canvasLocation" x="-466" y="641"/>
110353 </scene>
111354 </scenes>
112355</document>
GDproject/Constants.swift+7
@@ -12,3 +12,10 @@ let postCellId = "PostCell"
1212let headerNewsChannelsVC = "HeaderSegmentedControll"
1313// for transitioning to full post view
1414let fullPostControllerId = "FullPostController"
15+
16+let basicInfoCellId = "BasicInfoCell"
17+
18+let infoCellId = "InfoCell"
19+
20+let inviteVC = "InviteViewController"
21+
GDproject/Controller/BasicInfoCell.swiftnew file+39
@@ -0,0 +1,39 @@
1+//
2+// BasicInfoCell.swift
3+// NewsFeed
4+//
5+// Created by cstore on 23/01/2019.
6+// Copyright © 2019 drHSE. All rights reserved.
7+//
8+
9+import UIKit
10+import TinyConstraints
11+
12+class BasicInfoCell: UITableViewCell{
13+
14+ var titleLabel: UILabel = {
15+ let label = UILabel()
16+ label.font = UIFont.boldSystemFont(ofSize: 16)
17+ label.textColor = .black
18+ return label
19+ }()
20+
21+ override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
22+ super.init(style: style, reuseIdentifier: reuseIdentifier)
23+ }
24+
25+ func setUpView(){
26+ addSubview(titleLabel)
27+ titleLabel.horizontalToSuperview(insets: .left(16) + .right(16))
28+ titleLabel.verticalToSuperview(insets: .top(8) + .bottom(8))
29+ }
30+
31+ required init?(coder aDecoder: NSCoder) {
32+ fatalError("init(coder:) has not been implemented")
33+ }
34+
35+ func fill(title: String){
36+ setUpView()
37+ titleLabel.text = title
38+ }
39+}
GDproject/Controller/BasicInfoController.swiftnew file+75
@@ -0,0 +1,75 @@
1+//
2+// BasicInfoController.swift
3+// GDproject
4+//
5+// Created by cstore on 16/02/2019.
6+// Copyright © 2019 drHSE. All rights reserved.
7+//
8+
9+import UIKit
10+
11+struct CellData{
12+ var opened = Bool()
13+ var title = String()
14+ var sectionData = [String]()
15+}
16+
17+class BasicInfoController: UIViewController, UITableViewDelegate, UITableViewDataSource {
18+
19+ var dataSourse: [CellData] = [
20+ CellData(opened: false, title: "Phone", sectionData: ["+7 901 733 01 79"]),
21+ CellData(opened: false, title: "Mail", sectionData: ["vbogomazova@edu.hse.ru"]),
22+ CellData(opened: false, title: "Research ID", sectionData: ["4567834336789456737"]),
23+ CellData(opened: false, title: "Published", sectionData: ["Это будет очень длинное название книги 1, чтобы сделать проверку", "Книга 2", "Книга 3"]),
24+ CellData(opened: false, title: "Courses", sectionData: ["Курс 1", "Курс 2"]),
25+ CellData(opened: false, title: "Link", sectionData: ["https://wwww.hse.ru"])
26+ ]
27+
28+ func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
29+ if (dataSourse[section].opened){
30+ return dataSourse[section].sectionData.count + 1
31+ } else {
32+ return 1
33+ }
34+ }
35+
36+ func numberOfSections(in tableView: UITableView) -> Int {
37+ return dataSourse.count
38+ }
39+
40+ func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
41+ if indexPath.row == 0 {
42+ let cell = tableView.dequeueReusableCell(withIdentifier: basicInfoCellId, for: indexPath) as! BasicInfoCell
43+ cell.fill(title: dataSourse[indexPath.section].title)
44+ cell.accessoryType = .disclosureIndicator
45+ cell.selectionStyle = .none
46+ return cell
47+ } else {
48+ let cell = tableView.dequeueReusableCell(withIdentifier: infoCellId, for: indexPath) as! InfoCell
49+ cell.fill(title: dataSourse[indexPath.section].sectionData[indexPath.row - 1])
50+ cell.selectionStyle = .none
51+ return cell
52+ }
53+ }
54+
55+ func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
56+ if indexPath.row == 0 {
57+ if dataSourse[indexPath.section].opened {
58+ dataSourse[indexPath.section].opened = false
59+ let section = IndexSet.init(integer: indexPath.section)
60+ tableView.reloadSections(section, with: .none)
61+ } else {
62+ dataSourse[indexPath.section].opened = true
63+ let section = IndexSet.init(integer: indexPath.section)
64+ tableView.reloadSections(section, with: .none)
65+ }
66+ }
67+ }
68+ func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
69+ return UITableView.automaticDimension
70+ }
71+
72+ func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
73+ return 100.0
74+ }
75+}
GDproject/Controller/InfoCell.swiftnew file+44
@@ -0,0 +1,44 @@
1+//
2+// BasicInfoCell.swift
3+// NewsFeed
4+//
5+// Created by cstore on 23/01/2019.
6+// Copyright © 2019 drHSE. All rights reserved.
7+//
8+
9+import UIKit
10+import TinyConstraints
11+
12+class InfoCell: UITableViewCell{
13+
14+ var textView: UITextView = {
15+ let label = UITextView()
16+ label.font = UIFont.systemFont(ofSize: 16)
17+ label.sizeToFit()
18+ label.isScrollEnabled = false
19+ label.isUserInteractionEnabled = false
20+ label.isEditable = false
21+ label.textColor = .black
22+ return label
23+ }()
24+
25+ override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
26+ super.init(style: style, reuseIdentifier: reuseIdentifier)
27+ }
28+
29+ func setUpView()
30+ {
31+ addSubview(textView)
32+ textView.horizontalToSuperview(insets: .left(32) + .right(16))
33+ textView.verticalToSuperview(insets: .top(8) + .bottom(8))
34+ }
35+
36+ required init?(coder aDecoder: NSCoder) {
37+ fatalError("init(coder:) has not been implemented")
38+ }
39+
40+ func fill(title: String){
41+ setUpView()
42+ textView.text = title
43+ }
44+}
GDproject/Controller/InviteViewController.swiftnew file+140
@@ -0,0 +1,140 @@
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 InviteViewController: UIViewController {
12+
13+ @IBOutlet weak var mailTextField: UITextField!
14+
15+ @IBOutlet weak var inviteLabel: UILabel!
16+
17+ static let titleColor = UIColor(red: 0, green: 137/255, blue: 249/255, alpha: 0.5)
18+
19+ var bottomConstraint: NSLayoutConstraint?
20+
21+ let logInButton: UIButton = {
22+ let button = UIButton(type: .system)
23+ button.setTitle("Invite", for: .normal)
24+ button.setTitleColor(titleColor, for: .normal)
25+ button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 16)
26+ button.isEnabled = false
27+ button.addTarget(self, action: #selector(activateLogInProcess), for: .touchUpInside)
28+ return button
29+ }()
30+
31+ let keyboardBar: UIView = {
32+ let view = UIView()
33+ view.backgroundColor = .white
34+ return view
35+ }()
36+
37+ override func viewDidLoad() {
38+ super.viewDidLoad()
39+ setUpView()
40+ configureTapgesture()
41+ }
42+
43+ override func viewWillAppear(_ animated: Bool) {
44+ super.viewWillAppear(animated)
45+ // MARK:- uncomment when mail registration will be availiable
46+ //self.navigationController?.setNavigationBarHidden(true, animated: animated)
47+
48+
49+ navigationController?.navigationBar.prefersLargeTitles = false
50+ }
51+
52+ override func viewWillDisappear(_ animated: Bool) {
53+ super.viewWillDisappear(animated)
54+ // MARK:- uncomment when mail registration will be availiable
55+ //self.navigationController?.setNavigationBarHidden(false, animated: animated)
56+ }
57+
58+ private func configureTapgesture(){
59+ let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTap))
60+ view.addGestureRecognizer(tapGesture)
61+ }
62+
63+ @objc func handleTap(){
64+ view.endEditing(true)
65+ }
66+
67+ @objc func activateLogInProcess(){
68+ if logInButton.isEnabled {
69+ // instead of transporting user for new vc, make him a sign that everything was complete
70+ inviteLabel.text?.append(" ✅")
71+ view.endEditing(true)
72+ }
73+ }
74+
75+ func setUpView(){
76+ mailTextField.delegate = self
77+ view.addSubview(keyboardBar)
78+
79+ view.addConstraintsWithFormat(format: "H:|[v0]|", views: keyboardBar)
80+ view.addConstraintsWithFormat(format: "V:[v0(50)]", views: keyboardBar)
81+
82+ setUpBarComponents()
83+
84+ bottomConstraint = NSLayoutConstraint(item: keyboardBar, attribute: .bottom, relatedBy: .equal, toItem: view.safeAreaLayoutGuide, attribute: .bottom, multiplier: 1, constant: 0)
85+ view.addConstraint(bottomConstraint!)
86+
87+ // for keyboard notifications
88+ NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardNotifications), name: UIResponder.keyboardWillShowNotification, object: nil)
89+
90+ NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardNotifications), name: UIResponder.keyboardWillHideNotification, object: nil)
91+
92+ // for log in button notifications
93+ NotificationCenter.default.addObserver(self, selector: #selector(inputDidChanged), name: UITextField.textDidChangeNotification, object: mailTextField)
94+
95+ NotificationCenter.default.addObserver(self, selector: #selector(inputDidChanged), name: UITextField.textDidBeginEditingNotification, object: mailTextField)
96+ }
97+
98+
99+ @objc func inputDidChanged(notification: NSNotification){
100+ if mailTextField.text?.isEmpty ?? true
101+ {
102+ logInButton.isEnabled = false
103+ logInButton.setTitleColor(InviteViewController.titleColor.withAlphaComponent(0.5), for: .normal)
104+ }
105+ else
106+ {
107+ logInButton.isEnabled = true
108+ logInButton.setTitleColor(InviteViewController.titleColor.withAlphaComponent(1), for: .normal)
109+ }
110+ }
111+
112+ @objc func handleKeyboardNotifications(notification: NSNotification){
113+ if let userInfo = notification.userInfo{
114+ // UIKeyboardFrameEndUserInfoKey
115+ let keyBoardFrame = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
116+ bottomConstraint?.constant = notification.name == UIResponder.keyboardWillShowNotification ? -keyBoardFrame.height+view.safeAreaInsets.bottom : 0
117+
118+ UIView.animate(withDuration: 0, delay: 0, options: .curveEaseOut, animations: {
119+ self.view.layoutIfNeeded()
120+ }) { (completed) in
121+
122+ }
123+ }
124+ }
125+
126+ func setUpBarComponents(){
127+ keyboardBar.addSubview(logInButton)
128+ keyboardBar.addConstraintsWithFormat(format: "H:[v0(60)]-16-|", views: logInButton)
129+ keyboardBar.addConstraintsWithFormat(format: "V:|[v0]|", views: logInButton)
130+ }
131+}
132+
133+
134+extension InviteViewController: UITextFieldDelegate{
135+ func textFieldShouldReturn(_ textField: UITextField) -> Bool
136+ {
137+ textField.resignFirstResponder()
138+ return true
139+ }
140+}
GDproject/Controller/News/ChannelsController.swiftnew file+35
@@ -0,0 +1,35 @@
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/FullPostController.swiftnew file+103
@@ -0,0 +1,103 @@
1+//
2+// FullPostViewController.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 FullPostController: UITableViewController {
13+
14+ var post: Post?
15+
16+ override func viewDidLoad() {
17+ super.viewDidLoad()
18+
19+ tableView.register(PostViewCell.self, forCellReuseIdentifier: postCellId)
20+
21+ setUpNavigationBar()
22+ tableView.separatorStyle = .none
23+
24+
25+ }
26+
27+ func setUpNavigationBar(){
28+ navigationController?.navigationBar.prefersLargeTitles = false
29+ navigationItem.title = "\(post?.fromUser.login ?? "")"
30+ navigationItem.rightBarButtonItems = [UIBarButtonItem(barButtonSystemItem: .action, target: self, action: #selector(self.options))]
31+ }
32+
33+ @objc func options(){
34+ // drafts
35+ // saved
36+
37+ let optionMenu = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
38+ let editAction = UIAlertAction(title: "Send via message", style: .default)
39+ let shareAction = UIAlertAction(title: "Send via project", style: .default)
40+ let settingsAction = UIAlertAction(title: "Copy link", style: .default)
41+ let cancelAction = UIAlertAction(title: "Cancel", style: .cancel)
42+
43+ optionMenu.addAction(editAction)
44+ optionMenu.addAction(shareAction)
45+ optionMenu.addAction(settingsAction)
46+ optionMenu.addAction(cancelAction)
47+
48+ self.present(optionMenu, animated: true, completion: nil)
49+ }
50+ // MARK: - Table view data source
51+
52+ override func numberOfSections(in tableView: UITableView) -> Int {
53+ // #warning Incomplete implementation, return the number of sections
54+ return 2
55+ }
56+
57+
58+ override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView?
59+ {
60+ switch section {
61+ case 0:
62+ let v = UIView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 1))
63+ v.backgroundColor = .white
64+ return v
65+ default:
66+ return nil
67+ }
68+ }
69+
70+
71+ override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
72+ switch section {
73+ case 0:
74+ return 1
75+ default:
76+ return 0
77+ }
78+ }
79+
80+ override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
81+ {
82+ switch section {
83+ case 0:
84+ return 1
85+ case 1:
86+ return post?.comments.count ?? 0
87+ default:
88+ return 0
89+ }
90+ }
91+
92+ override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
93+ {
94+ // TODO: make different cells for sections with switch
95+
96+ let cell = tableView.dequeueReusableCell(withIdentifier: postCellId) as! PostViewCell
97+
98+ cell.fill(with: post!.dataArray, true, post: post!)
99+ cell.selectionStyle = .none
100+ return cell
101+ }
102+
103+}
GDproject/Controller/News/HeaderNewsChannels.swiftnew file+54
@@ -0,0 +1,54 @@
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/News/NewPostViewController.swiftnew file+257
@@ -0,0 +1,257 @@
1+//
2+// NewPostViewController.swift
3+// GDproject
4+//
5+// Created by cstore on 05/02/2019.
6+// Copyright © 2019 drHSE. All rights reserved.
7+//
8+
9+import UIKit
10+import Cartography
11+import Marklight
12+import TinyConstraints
13+
14+class NewPostViewController: UIViewController, UITextViewDelegate {
15+
16+ @IBOutlet weak var view1: UIView!
17+ // Keep strong instance of the `NSTextStorage` subclass
18+ let textStorage = MarklightTextStorage()
19+
20+ weak var parentVC: NewsController?
21+
22+ static var draft: String = ""
23+ var textView: UITextView!
24+
25+ // buttons for attaching images
26+ var accessoryView: UIView = {
27+ let view = UIView()
28+ view.backgroundColor = .white
29+ return view
30+ }()
31+
32+ var addEquasion: UIButton = {
33+ var button = UIButton(type: .detailDisclosure)
34+ button.addTarget(self, action: #selector(addMathBrackets), for: .touchUpInside)
35+ return button
36+ }()
37+
38+ // stack view where buttons will be places
39+ var stackAccessoryView: UIStackView?
40+ // Connect the view1's bottom layout constraint to react to keyboard movements
41+
42+ @IBOutlet weak var bottomTextViewConstraint: NSLayoutConstraint!
43+
44+
45+ override func viewDidLoad()
46+ {
47+ super.viewDidLoad()
48+ setUpMD()
49+ setUpTextView()
50+ setUpAccessoryView()
51+ }
52+
53+ override func viewWillAppear(_ animated: Bool) {
54+ super.viewWillAppear(animated)
55+
56+ navigationController?.navigationBar.prefersLargeTitles = false
57+ navigationItem.title = "New post"
58+ textView.text = NewPostViewController.draft
59+ }
60+
61+ func setUpAccessoryView(){
62+ let views = [UIButton(type: .contactAdd),addEquasion]
63+ stackAccessoryView = UIStackView(arrangedSubviews: views)
64+
65+ stackAccessoryView?.alignment = .fill
66+ stackAccessoryView?.distribution = .equalSpacing
67+
68+ view1.addSubview(accessoryView)
69+ accessoryView.addSubview(stackAccessoryView!)
70+ accessoryView.height(40)
71+
72+ let separatorView = UIView()
73+ separatorView.backgroundColor = #colorLiteral(red: 0.8039215803, green: 0.8039215803, blue: 0.8039215803, alpha: 1)
74+ accessoryView.addSubview(separatorView)
75+ separatorView.height(1)
76+ separatorView.edgesToSuperview(excluding: .bottom)
77+
78+ accessoryView.edgesToSuperview(excluding: [.top])
79+ stackAccessoryView!.edgesToSuperview(insets: .left(16) + .right(16) + .top(1))
80+ }
81+
82+ func setUpTextView(){
83+ view.addConstraint(bottomTextViewConstraint)
84+ view1.addSubview(textView)
85+ textView.edgesToSuperview(insets: .top(8) + .left(8) + .bottom(40+8) + .right(8))
86+
87+ if #available(iOS 11.0, *) {
88+ textView.smartDashesType = .no
89+ textView.smartQuotesType = .no
90+ }
91+
92+ textView.isScrollEnabled = true
93+
94+ guard let bottomTextViewConstraint = bottomTextViewConstraint else { return }
95+ view.addConstraint(bottomTextViewConstraint)
96+
97+ // Add a beautiful padding to the `UITextView` content
98+ textView.textContainerInset = UIEdgeInsets(top: 4, left: 4, bottom: 4, right: 4)
99+ textView.delegate = self
100+ magicForKeyboardChanges()
101+ }
102+
103+
104+ func magicForKeyboardChanges()
105+ {
106+ /////////////////////////////
107+ // We do some magic to resize the `UITextView` to react the the keyboard size change (appearance, disappearance, ecc)
108+ NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardNotifications), name: UIResponder.keyboardWillShowNotification, object: nil)
109+
110+ NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardNotifications), name: UIResponder.keyboardWillHideNotification, object: nil)
111+
112+ // 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") {
115+ CATransaction.setCompletionBlock({ () -> Void in
116+ self.scrollToCaret(self.textView, animated: false)
117+ })
118+ } else {
119+ self.scrollToCaret(self.textView, animated: false)
120+ }
121+ }
122+
123+ }
124+
125+ @objc func handleKeyboardNotifications(notification: NSNotification){
126+ if let userInfo = notification.userInfo{
127+ // UIKeyboardFrameEndUserInfoKey
128+ let keyBoardFrame = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
129+ bottomTextViewConstraint?.constant = notification.name == UIResponder.keyboardWillShowNotification ? keyBoardFrame.height : 0
130+ print(bottomTextViewConstraint!.constant)
131+
132+ UIView.animate(withDuration: 0, delay: 0, options: .curveEaseOut, animations: {
133+ self.view.layoutIfNeeded()
134+ }) { (completed) in
135+
136+ }
137+ }
138+ }
139+
140+ @objc func attachPhoto(){
141+
142+ }
143+
144+
145+ @objc func addMathBrackets()
146+ {
147+ if textView.text.count != 0 && textView.text.last != "\n" {
148+ textView.insertText("\n\\[\n ")
149+ }
150+ else {
151+ textView.insertText("\\[\n ")
152+ }
153+
154+ if let selectedRange = textView.selectedTextRange
155+ {
156+ textView.insertText("\n\\]\n")
157+
158+ if let newPosition = textView.position(from: selectedRange.start, offset: 0)
159+ {
160+ // set the new position
161+ textView.selectedTextRange = textView.textRange(from: newPosition, to: newPosition)
162+ }
163+ }
164+ }
165+
166+ func setUpMD(){
167+ textStorage.marklightTextProcessor.codeColor = UIColor.orange
168+ textStorage.marklightTextProcessor.quoteColor = UIColor.darkGray
169+ textStorage.marklightTextProcessor.syntaxColor = UIColor.blue
170+ textStorage.marklightTextProcessor.codeFontName = "Courier"
171+ textStorage.marklightTextProcessor.fontTextStyle = UIFont.TextStyle.subheadline.rawValue
172+ textStorage.marklightTextProcessor.hideSyntax = false
173+
174+ let layoutManager = NSLayoutManager()
175+
176+ // Assign the `UITextView`'s `NSLayoutManager` to the `NSTextStorage` subclass
177+ textStorage.addLayoutManager(layoutManager)
178+
179+ let textContainer = NSTextContainer()
180+ layoutManager.addTextContainer(textContainer)
181+
182+ textView = UITextView(frame: view.bounds, textContainer: textContainer)
183+ }
184+
185+ // MARK:- new post
186+ @objc func newPost(){
187+ let p = Post(dataArray: [.text(textView.text)], from: User(name: "Сева", id: 5, fullName: "Сева Леонидович"), date: "12.01.19")
188+
189+
190+ // 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()
197+ moveBackToParentVC()
198+ // somewhere here i will be sending server notifications about new post arrival
199+ }
200+
201+ @objc func actionSaveDraft(){
202+ let optionMenu = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
203+
204+ let saveAction = UIAlertAction(title: "Save draft", style: .default)
205+ {
206+ _ in
207+ NewPostViewController.draft = self.textView.text
208+ self.moveBackToParentVC()
209+ }
210+
211+ let deleteAction = UIAlertAction(title: "Delete draft", style: .destructive)
212+ {
213+ (_)
214+ in
215+ NewPostViewController.draft = ""
216+ self.moveBackToParentVC()
217+ }
218+
219+ let cancelAction = UIAlertAction(title: "Cancel", style: .cancel)
220+
221+ optionMenu.addAction(saveAction)
222+ optionMenu.addAction(deleteAction)
223+ optionMenu.addAction(cancelAction)
224+
225+ self.present(optionMenu, animated: true, completion: nil)
226+ }
227+
228+ @objc func closeView()
229+ {
230+ actionSaveDraft()
231+ }
232+
233+ func moveBackToParentVC(){
234+ let transition = CATransition()
235+ transition.duration = 0.5
236+ transition.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
237+ transition.type = CATransitionType.reveal
238+ transition.subtype = CATransitionSubtype.fromBottom
239+ navigationController?.view.layer.add(transition, forKey: nil)
240+ navigationController?.popViewController(animated: false)
241+ textView!.resignFirstResponder()
242+ }
243+
244+
245+
246+
247+ func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange) -> Bool {
248+ print("Should interact with: \(URL)")
249+ return true
250+ }
251+
252+ func scrollToCaret(_ textView: UITextView, animated: Bool) {
253+ var rect = textView.caretRect(for: textView.selectedTextRange!.end)
254+ rect.size.height = rect.size.height + textView.textContainerInset.bottom
255+ textView.scrollRectToVisible(rect, animated: animated)
256+ }
257+}
GDproject/Controller/News/NewsController.swiftnew file+164
@@ -0,0 +1,164 @@
1+//
2+// ViewController.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+// MARK:- Controller with posts and channels availiable.
13+// Search is availiable within every table (posts and channels). Has button-functionality for boths post and chnnels
14+class NewsController: UIViewController
15+{
16+
17+ @IBOutlet weak var tableView: UITableView!
18+
19+ var searchController = UISearchController(searchResultsController: nil)
20+
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")]
22+
23+ var news = NewsVC()
24+ var channels = ChannelsController()
25+
26+ override func viewDidLoad()
27+ {
28+ 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
34+
35+ news.type = .NEWS("Posts", "Channels")
36+
37+ tableView.delegate = news
38+ tableView.dataSource = news
39+ tableView.reloadData()
40+
41+
42+
43+ setUpNavigationItemsforPosts()
44+ searchController.searchBar.placeholder = "Search anything"
45+
46+ navigationItem.searchController = searchController
47+ definesPresentationContext = true
48+
49+ setUpBanner()
50+ }
51+
52+ override func viewWillAppear(_ animated: Bool) {
53+ super.viewWillAppear(animated)
54+ navigationController?.navigationBar.prefersLargeTitles = true
55+ }
56+
57+ func setUpNavigationItemsforPosts(){
58+ navigationItem.title = "Posts"
59+ navigationItem.rightBarButtonItems = [UIBarButtonItem(barButtonSystemItem: .compose, target: self, action: #selector(self.writePost(_:)))]
60+ tableView.delegate = news
61+ tableView.dataSource = news
62+ tableView.reloadData()
63+ }
64+
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()
71+ }
72+
73+ @objc func writePost(_ barItem: UIBarButtonItem)
74+ {
75+ let vc = storyboard?.instantiateViewController(withIdentifier: "NewPostViewController") as! NewPostViewController
76+
77+ vc.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Post", style: .plain, target: vc, action: #selector(vc.newPost))
78+ vc.navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Close", style: .plain, target: vc, action: #selector(vc.closeView))
79+
80+ vc.parentVC = self
81+
82+ let transition = CATransition()
83+ transition.duration = 0.5
84+ transition.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
85+ transition.type = CATransitionType.moveIn
86+ transition.subtype = CATransitionSubtype.fromTop
87+ navigationController?.view.layer.add(transition, forKey: nil)
88+ navigationController?.pushViewController(vc, animated: false)
89+ }
90+
91+ @objc func addChannel(){
92+ print("Add channel")
93+ }
94+
95+ // for animating the banner
96+ var topConstraint: NSLayoutConstraint?
97+
98+ let bannerView: UIView = {
99+ let view = UIView()
100+ view.backgroundColor = .blue
101+ view.layer.cornerRadius = 25.0
102+ view.clipsToBounds = true
103+ return view
104+ }()
105+
106+ let statusLabel: UILabel = {
107+ let label = UILabel()
108+ label.text = "-"
109+ label.textColor = .white
110+ label.textAlignment = .center
111+ return label
112+ }()
113+
114+ private func setUpBanner()
115+ {
116+ view.addSubview(bannerView)
117+ bannerView.addSubview(statusLabel)
118+ statusLabel.edgesToSuperview()
119+
120+ let tap = UITapGestureRecognizer(target: self, action: #selector(handleTap(sender:)))
121+
122+ bannerView.addGestureRecognizer(tap)
123+ topConstraint = NSLayoutConstraint(item: bannerView, attribute: .top, relatedBy: .equal, toItem: view.safeAreaLayoutGuide, attribute: .top, multiplier: 1, constant: -300)
124+ view.addConstraint(topConstraint!)
125+
126+ bannerView.edgesToSuperview(excluding: [.bottom, .top, .left], insets: .right(20), usingSafeArea: true)
127+ bannerView.height(50)
128+ bannerView.width(50)
129+ }
130+
131+ // when table is scrolling no deletion is availiable
132+ @objc func handleTap(sender: UITapGestureRecognizer? = nil) {
133+ let indexPath = IndexPath(row: 0, section: 0)
134+ self.tableView.scrollToRow(at: indexPath, at: .top, animated: true)
135+// isBannerVisible = false
136+// changeConstraint(isVisible: false)
137+ }
138+
139+ // animation for banner
140+ func changeConstraint(isVisible: Bool){
141+ topConstraint?.constant = isVisible ? 50 : -300
142+
143+ UIView.animate(withDuration: 0.5, delay: 0, options: .curveEaseOut, animations: {
144+ self.view.layoutIfNeeded()
145+ }) { (completed) in
146+
147+ }
148+ }
149+
150+ var isBannerVisible: Bool = false
151+
152+ func scrollViewDidScroll(_ scrollView: UIScrollView) {
153+ print(scrollView.contentOffset.y)
154+ if scrollView.contentOffset.y >= 50 && !isBannerVisible{
155+ isBannerVisible = true
156+ changeConstraint(isVisible: true)
157+ }
158+
159+ if isBannerVisible && scrollView.contentOffset.y == 0{
160+ isBannerVisible = false
161+ changeConstraint(isVisible: false)
162+ }
163+ }
164+}
GDproject/Controller/News/NewsVC.swiftnew file+86
@@ -0,0 +1,86 @@
1+//
2+// NewsVC.swift
3+// GDproject
4+//
5+// Created by cstore on 15/02/2019.
6+// Copyright © 2019 drHSE. All rights reserved.
7+//
8+
9+import UIKit
10+
11+class NewsVC: UIViewController, UITableViewDelegate, UITableViewDataSource{
12+
13+ var dataSourse: [Post] = []
14+
15+ var type: HeaderType = .NONE
16+
17+ var viewController: UIViewController?
18+
19+ func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
20+ {
21+ tableView.deselectRow(at: indexPath, animated: true)
22+
23+ let vc = viewController!.storyboard!.instantiateViewController(withIdentifier: fullPostControllerId) as! FullPostController
24+
25+ vc.post = dataSourse[indexPath.row]
26+ viewController!.navigationController!.pushViewController(vc, animated: true)
27+ }
28+
29+ func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
30+ return dataSourse.count
31+ }
32+
33+ func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
34+ {
35+ let cell = tableView.dequeueReusableCell(withIdentifier: postCellId, for: indexPath) as! PostViewCell
36+
37+ cell.fill(with: dataSourse[indexPath.row].dataArray, false, post: dataSourse[indexPath.row])
38+ cell.selectionStyle = .none
39+ return cell
40+ }
41+
42+ func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
43+ return UITableView.automaticDimension
44+ }
45+
46+ func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
47+ return 100.0
48+ }
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+
78+}
79+
80+
81+enum HeaderType {
82+ case NONE
83+ case NEWS(String, String)
84+ case PROFILE(String, String)
85+ case BASIC_INFO(String, String)
86+}
GDproject/Controller/News/PostViewCell.swift+50−2
@@ -69,9 +69,11 @@ class PostViewCell: UITableViewCell
6969
7070 var views: [UIView] = []
7171 var data : [UIImage] = []
72+ var post: Post?
7273
73− func fill(with info: [Media], _ isFullVersoin: Bool)
74+ func fill(with info: [Media], _ isFullVersoin: Bool, post: Post)
7475 {
76+ self.post = post
7577 // important
7678 contentView.subviews.forEach({ $0.removeFromSuperview() })
7779
@@ -99,6 +101,50 @@ class PostViewCell: UITableViewCell
99101 //nameStackView.height(46)
100102 nameStackView.edgesToSuperview(excluding: .bottom, insets: .left(20) + .right(20) + .top(8))
101103
104+ let mainView = UIView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 30))
105+
106+ let scrollView = UIScrollView()
107+
108+ scrollView.backgroundColor = .white
109+
110+ mainView.addSubview(scrollView)
111+ scrollView.edgesToSuperview()
112+
113+ scrollView.showsHorizontalScrollIndicator = false
114+
115+ var buttons: [UIButton] = []
116+ for hash in post!.hashtags {
117+ let button = UIButton()
118+ button.setTitle("#" + hash, for: .normal)
119+ //button.backgroundColor = #colorLiteral(red: 0.8039215803, green: 0.8039215803, blue: 0.8039215803, alpha: 1)
120+ //button.layer.cornerRadius = 10
121+ button.titleLabel?.font = UIFont.monospacedDigitSystemFont(ofSize: 15, weight: .semibold)
122+ button.setTitleColor(#colorLiteral(red: 0, green: 0.4784313725, blue: 1, alpha: 1), for: .normal)
123+ buttons.append(button)
124+ }
125+
126+ let stackViewHashTags = UIStackView(arrangedSubviews: buttons)
127+
128+ scrollView.addSubview(stackViewHashTags)
129+
130+ stackViewHashTags.axis = .horizontal
131+ stackViewHashTags.spacing = 17
132+
133+ // edgesToSuperview(insets: .left(20) + .top(10) + .right(20))
134+ stackViewHashTags.horizontalToSuperview(insets: .left(20) + .right(20))
135+ stackViewHashTags.verticalToSuperview()
136+
137+ stackViewHashTags.distribution = .fillProportionally
138+ stackViewHashTags.alignment = .center
139+
140+ scrollView.contentSize = CGSize(width: 500, height: 30)
141+
142+
143+ contentView.addSubview(mainView)
144+ mainView.edgesToSuperview(excluding: [.top, .bottom])
145+ mainView.topToBottom(of: nameStackView, offset: 5)
146+ mainView.height(30)
147+
102148 let stackView = MyStackView(arrangedSubviews: views)
103149 stackView.isFull = full
104150 stackView.axis = .vertical
@@ -106,7 +152,9 @@ class PostViewCell: UITableViewCell
106152 if !full {
107153 stackView.height(300, relation: .equalOrLess, isActive: true)
108154 }
109− stackView.topToBottom(of: nameStackView, offset: 16, relation: .equal, isActive: true)
155+
156+ stackView.topToBottom(of: mainView, offset: 0, relation: .equal, isActive: true)
157+
110158 stackView.edgesToSuperview(excluding: [.top, .bottom], insets: .left(16) + .right(16))
111159
112160 let commentsSharesStackView = UIStackView(arrangedSubviews: [ commentsLabel, shareButton])
GDproject/Controller/ProfileViewController.swiftnew file+144
@@ -0,0 +1,144 @@
1+//
2+// ProfileViewController.swift
3+// GDproject
4+//
5+// Created by cstore on 15/02/2019.
6+// Copyright © 2019 drHSE. All rights reserved.
7+//
8+
9+import UIKit
10+import TinyConstraints
11+
12+class ProfileViewController: UIViewController
13+{
14+
15+ @IBOutlet weak var segmentedControl: UISegmentedControl!
16+
17+ @IBOutlet weak var profileView: UIView!
18+
19+ @IBOutlet weak var tableView: UITableView!
20+
21+ @IBOutlet weak var profileImageView: UIImageView!
22+
23+ @IBOutlet weak var surnameLabel: UILabel!
24+
25+ @IBOutlet weak var nameLabel: UILabel!
26+
27+ @IBOutlet weak var facultyLabel: UILabel!
28+
29+ @IBOutlet weak var placeLabel: UILabel!
30+
31+ @IBOutlet weak var newMessageButton: UIButton!
32+
33+
34+ func fill(with user: User){
35+ self.facultyLabel.text = user.faculty ?? ""
36+ self.nameLabel.text = "\(user.initials.name) \(user.initials.optional ?? "")"
37+ self.surnameLabel.text = user.initials.surname
38+ self.profileImageView.image = #imageLiteral(resourceName: "kitten").roundedImage
39+ self.placeLabel.text = user.placeOfWork
40+ }
41+
42+ var user: User = User(surname: "Богомазова", name: "Вероника", optional: "Львовна", emailName: "vbogomazova", id: 2, place: "📍Москва, Кочновский пр. 3", faculty: "Методист: Факультет Компьютерных наук")
43+
44+ let basicInfo = BasicInfoController()
45+ let posts = NewsVC()
46+
47+ override func viewDidLoad()
48+ {
49+ super.viewDidLoad()
50+
51+ posts.type = .NONE
52+
53+ 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. .")])]
54+
55+ // basicInfo.dataSourse =
56+
57+ posts.viewController = self
58+
59+ tableView.register(HeaderNewsChannels.self, forCellReuseIdentifier: headerNewsChannelsVC)
60+
61+ tableView.register(PostViewCell.self, forCellReuseIdentifier: postCellId)
62+
63+ tableView.register(BasicInfoCell.self, forCellReuseIdentifier: basicInfoCellId)
64+
65+ tableView.register(InfoCell.self, forCellReuseIdentifier: infoCellId)
66+
67+ posts.viewController = self
68+
69+ fill(with: user)
70+ tableView.delegate = posts
71+ tableView.dataSource = posts
72+ tableView.reloadData()
73+ }
74+
75+ override func viewWillAppear(_ animated: Bool) {
76+ setUpNavigarionBar()
77+ }
78+
79+ func setUpNavigarionBar(){
80+ navigationController?.navigationBar.prefersLargeTitles = true
81+ navigationItem.title = user.login
82+ let uibarbutton = UIBarButtonItem(title: "More", style: .plain, target: self, action: #selector(showInformation))
83+ navigationItem.rightBarButtonItems = [uibarbutton]
84+ navigationItem.largeTitleDisplayMode = .always
85+ }
86+
87+
88+ let copyLink: UIAlertAction = {
89+ let b = UIAlertAction(title: "Copy link", style: .default)
90+ return b
91+ }()
92+
93+ @objc func showInformation(){
94+
95+ // drafts
96+ // saved
97+
98+ let optionMenu = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
99+ let editAction = UIAlertAction(title: "Edit profile", style: .default)
100+ let settingsAction = UIAlertAction(title: "Setting", style: .default)
101+ { [weak self] (_) in
102+
103+ let vc = self?.storyboard?.instantiateViewController(withIdentifier: "SettingsViewController") as! SettingsViewController
104+ self?.navigationController?.pushViewController(vc, animated: true)
105+ }
106+
107+ let cancelAction = UIAlertAction(title: "Cancel", style: .cancel)
108+ let shareAction = UIAlertAction(title: "Share", style: .default)
109+
110+ optionMenu.addAction(editAction)
111+ optionMenu.addAction(settingsAction)
112+ optionMenu.addAction(copyLink)
113+ optionMenu.addAction(shareAction)
114+ optionMenu.addAction(cancelAction)
115+
116+ self.present(optionMenu, animated: true, completion: nil)
117+ }
118+
119+
120+ @IBAction func valueChanged(_ sender: UISegmentedControl) {
121+ let index = sender.selectedSegmentIndex
122+
123+ switch index {
124+ case 0:
125+ changeToPosts()
126+ case 1:
127+ changeToBasicInfo()
128+ default:
129+ break
130+ }
131+ }
132+
133+ func changeToPosts(){
134+ tableView.delegate = posts
135+ tableView.dataSource = posts
136+ tableView.reloadData()
137+ }
138+
139+ func changeToBasicInfo(){
140+ tableView.delegate = basicInfo
141+ tableView.dataSource = basicInfo
142+ tableView.reloadData()
143+ }
144+}
GDproject/Controller/SettingsViewController.swiftnew file+49
@@ -0,0 +1,49 @@
1+//
2+// SettingsViewController.swift
3+// GDproject
4+//
5+// Created by cstore on 16/02/2019.
6+// Copyright © 2019 drHSE. All rights reserved.
7+//
8+
9+import UIKit
10+
11+class SettingsViewController: UITableViewController {
12+
13+ var dataSourse: [String] = ["Пригласить преподавателя"]
14+
15+ override func viewDidLoad() {
16+ super.viewDidLoad()
17+ navigationItem.title = "Settings"
18+ }
19+
20+ // MARK: - Table view data source
21+
22+ override func viewWillAppear(_ animated: Bool) {
23+ super.viewWillAppear(animated)
24+
25+ navigationController?.navigationBar.prefersLargeTitles = true
26+ }
27+
28+
29+ override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
30+ return dataSourse.count
31+ }
32+
33+ override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
34+ if dataSourse[indexPath.row] == "Пригласить преподавателя" {
35+ let vc = storyboard?.instantiateViewController(withIdentifier: inviteVC) as! InviteViewController
36+ navigationController?.pushViewController(vc, animated: true)
37+ }
38+ }
39+
40+
41+ override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
42+ {
43+ let cell = tableView.dequeueReusableCell(withIdentifier: "SettingsCell", for: indexPath)
44+ cell.textLabel?.text = dataSourse[indexPath.row]
45+ cell.selectionStyle = .none
46+ return cell
47+ }
48+
49+}
GDproject/Extentions.swiftnew file+36
@@ -0,0 +1,36 @@
1+//
2+// Extentions.swift
3+// GDproject
4+//
5+// Created by cstore on 15/02/2019.
6+// Copyright © 2019 drHSE. All rights reserved.
7+//
8+
9+import UIKit
10+
11+extension UIImage{
12+ var roundedImage: UIImage {
13+ let rect = CGRect(origin:CGPoint(x: 0, y: 0), size: self.size)
14+ UIGraphicsBeginImageContextWithOptions(self.size, false, 1)
15+ UIBezierPath(
16+ roundedRect: rect,
17+ cornerRadius: self.size.height
18+ ).addClip()
19+ self.draw(in: rect)
20+ return UIGraphicsGetImageFromCurrentImageContext()!
21+ }
22+}
23+
24+extension UIView
25+{
26+ func addConstraintsWithFormat(format: String, views: UIView...){
27+ var viewsDictionary = [String: UIView]()
28+ for (index, view) in views.enumerated(){
29+ let key = "v\(index)"
30+ viewsDictionary[key] = view
31+ view.translatesAutoresizingMaskIntoConstraints = false
32+ }
33+
34+ addConstraints(NSLayoutConstraint.constraints(withVisualFormat: format, options: NSLayoutConstraint.FormatOptions(), metrics: nil, views: viewsDictionary))
35+ }
36+}
GDproject/MyStackView.swiftnew file+27
@@ -0,0 +1,27 @@
1+//
2+// MyStackView.swift
3+// GDproject
4+//
5+// Created by cstore on 14/02/2019.
6+// Copyright © 2019 drHSE. All rights reserved.
7+//
8+
9+import UIKit
10+
11+class MyStackView: UIStackView {
12+
13+ var isFull: Bool = true
14+
15+
16+ override var bounds: CGRect {
17+ didSet{
18+ if frame.height == 300 && !isFull {
19+ let gradientLayer = CAGradientLayer()
20+ gradientLayer.colors = [UIColor(displayP3Red: 255, green: 255, blue: 255, alpha: 0).cgColor, UIColor.white.cgColor]
21+ gradientLayer.startPoint = CGPoint(x: 0.5, y: 0.5)
22+ gradientLayer.frame = self.bounds
23+ self.layer.addSublayer(gradientLayer)
24+ }
25+ }
26+ }
27+}
GDproject/Simple model/Post.swift+9−1
@@ -13,7 +13,8 @@ struct Post {
1313 var dataArray: [Media]
1414 var fromUser: User
1515 var atDate: String
16− var comments: [Comment]
16+ var comments: [Comment] = []
17+
1718 var hashtags: [String] = ["ФКН", "Подбельский", "НИУВШЭ", "Шершаков", "ПАД", "Интересное","Мемы","Забавное","Учеба","Наука"]
1819
1920 init(dataArray: [Media], from: User, date: String, comments: [Comment] = [])
@@ -23,6 +24,13 @@ struct Post {
2324 atDate = date
2425 self.comments = comments
2526 }
27+
28+ init(dataArray: [Media]) {
29+ self.dataArray = dataArray
30+ fromUser = User(name: "vbogomazova", id: 2, fullName: "Богомазова Вероника Львовна")
31+ atDate = "23.03.19 в 23:33"
32+ }
33+
2634}
2735
2836
GDproject/Simple model/User.swift+3−2
@@ -13,11 +13,12 @@ struct User {
1313 //var photo: UIImage? = #imageLiteral(resourceName: "image")
1414 var login: String
1515 var id: Int
16− var surname: String?
1716 var fullName: String
18− var initials: (surname: String, name: String, optional: String?)?
17+ var initials: (surname: String, name: String, optional: String?) = ("Богомазова","Вероника","Львовна")
1918 var placeOfWork: String?
2019 var faculty: String?
20+ let posts: [Post] = []
21+
2122
2223 init(name: String, id: Int, fullName: String) {
2324 self.login = name
GDproject/Supporting files/Assets.xcassets/kitten.imageset/Contents.jsonnew file+21
@@ -0,0 +1,21 @@
1+{
2+ "images" : [
3+ {
4+ "idiom" : "universal",
5+ "filename" : "s1200-2.jpeg",
6+ "scale" : "1x"
7+ },
8+ {
9+ "idiom" : "universal",
10+ "scale" : "2x"
11+ },
12+ {
13+ "idiom" : "universal",
14+ "scale" : "3x"
15+ }
16+ ],
17+ "info" : {
18+ "version" : 1,
19+ "author" : "xcode"
20+ }
21+}
GDproject/Supporting files/Assets.xcassets/kitten.imageset/s1200-2.jpegnew file

Binary file not shown.