mirror of
https://github.com/wahyd4/Yep.git
synced 2026-08-10 21:36:49 +10:00
Merge branch 'develop' of https://github.com/CatchChat/Yep into develop
This commit is contained in:
@@ -90,6 +90,12 @@
|
||||
502AE5541AB93215005BD199 /* ProfileFooterCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 502AE5521AB93215005BD199 /* ProfileFooterCell.xib */; };
|
||||
502AE5581AB932D5005BD199 /* ProfileSectionHeaderReusableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 502AE5561AB932D5005BD199 /* ProfileSectionHeaderReusableView.swift */; };
|
||||
502AE5591AB932D5005BD199 /* ProfileSectionHeaderReusableView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 502AE5571AB932D5005BD199 /* ProfileSectionHeaderReusableView.xib */; };
|
||||
502B605A1BD1102B00D9C17E /* TitleCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 502B60581BD1102B00D9C17E /* TitleCell.swift */; settings = {ASSET_TAGS = (); }; };
|
||||
502B605B1BD1102B00D9C17E /* TitleCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 502B60591BD1102B00D9C17E /* TitleCell.xib */; settings = {ASSET_TAGS = (); }; };
|
||||
502B605F1BD112E500D9C17E /* QuickPickPhotosCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 502B605D1BD112E500D9C17E /* QuickPickPhotosCell.swift */; settings = {ASSET_TAGS = (); }; };
|
||||
502B60601BD112E500D9C17E /* QuickPickPhotosCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 502B605E1BD112E500D9C17E /* QuickPickPhotosCell.xib */; settings = {ASSET_TAGS = (); }; };
|
||||
502B60641BD1208E00D9C17E /* CameraCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 502B60621BD1208E00D9C17E /* CameraCell.swift */; settings = {ASSET_TAGS = (); }; };
|
||||
502B60651BD1208E00D9C17E /* CameraCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 502B60631BD1208E00D9C17E /* CameraCell.xib */; settings = {ASSET_TAGS = (); }; };
|
||||
503315971AC1017E0008A209 /* ChatLeftTextCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 503315951AC1017E0008A209 /* ChatLeftTextCell.swift */; };
|
||||
503315981AC1017E0008A209 /* ChatLeftTextCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 503315961AC1017E0008A209 /* ChatLeftTextCell.xib */; };
|
||||
5033159C1AC101C80008A209 /* ChatRightTextCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5033159A1AC101C80008A209 /* ChatRightTextCell.swift */; };
|
||||
@@ -214,6 +220,7 @@
|
||||
50AFBF4E1BB3A594007D19DA /* bub3.caf in Resources */ = {isa = PBXBuildFile; fileRef = 50AFBF4D1BB3A594007D19DA /* bub3.caf */; settings = {ASSET_TAGS = (); }; };
|
||||
50AFBF5F1BB4F332007D19DA /* FeedsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50AFBF5E1BB4F332007D19DA /* FeedsViewController.swift */; settings = {ASSET_TAGS = (); }; };
|
||||
50B2CA921BD0BF3800668AC6 /* FeedTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50B2CA911BD0BF3800668AC6 /* FeedTextView.swift */; settings = {ASSET_TAGS = (); }; };
|
||||
50B2CA941BD0EF7900668AC6 /* MoreMessageTypesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50B2CA931BD0EF7900668AC6 /* MoreMessageTypesView.swift */; settings = {ASSET_TAGS = (); }; };
|
||||
50B38FB71B69CD960064C132 /* Array+Yep.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50B38FB61B69CD960064C132 /* Array+Yep.swift */; };
|
||||
50B38FCC1B6B37F00064C132 /* FeedbackViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50B38FCB1B6B37F00064C132 /* FeedbackViewController.swift */; };
|
||||
50B8E6161B40F9E700C17EA1 /* YepDownloader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50B8E6151B40F9E700C17EA1 /* YepDownloader.swift */; };
|
||||
@@ -386,6 +393,12 @@
|
||||
502AE5521AB93215005BD199 /* ProfileFooterCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = ProfileFooterCell.xib; path = Views/Cells/ProfileFooter/ProfileFooterCell.xib; sourceTree = "<group>"; };
|
||||
502AE5561AB932D5005BD199 /* ProfileSectionHeaderReusableView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ProfileSectionHeaderReusableView.swift; path = Views/ReusableViews/ProfileSectionHeader/ProfileSectionHeaderReusableView.swift; sourceTree = "<group>"; };
|
||||
502AE5571AB932D5005BD199 /* ProfileSectionHeaderReusableView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = ProfileSectionHeaderReusableView.xib; path = Views/ReusableViews/ProfileSectionHeader/ProfileSectionHeaderReusableView.xib; sourceTree = "<group>"; };
|
||||
502B60581BD1102B00D9C17E /* TitleCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = TitleCell.swift; path = Views/Cells/Title/TitleCell.swift; sourceTree = "<group>"; };
|
||||
502B60591BD1102B00D9C17E /* TitleCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = TitleCell.xib; path = Views/Cells/Title/TitleCell.xib; sourceTree = "<group>"; };
|
||||
502B605D1BD112E500D9C17E /* QuickPickPhotosCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = QuickPickPhotosCell.swift; path = Views/Cells/QuickPickPhotos/QuickPickPhotosCell.swift; sourceTree = "<group>"; };
|
||||
502B605E1BD112E500D9C17E /* QuickPickPhotosCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = QuickPickPhotosCell.xib; path = Views/Cells/QuickPickPhotos/QuickPickPhotosCell.xib; sourceTree = "<group>"; };
|
||||
502B60621BD1208E00D9C17E /* CameraCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CameraCell.swift; path = Views/Cells/Camera/CameraCell.swift; sourceTree = "<group>"; };
|
||||
502B60631BD1208E00D9C17E /* CameraCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = CameraCell.xib; path = Views/Cells/Camera/CameraCell.xib; sourceTree = "<group>"; };
|
||||
503315951AC1017E0008A209 /* ChatLeftTextCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ChatLeftTextCell.swift; path = Views/Cells/ChatLeftText/ChatLeftTextCell.swift; sourceTree = "<group>"; };
|
||||
503315961AC1017E0008A209 /* ChatLeftTextCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = ChatLeftTextCell.xib; path = Views/Cells/ChatLeftText/ChatLeftTextCell.xib; sourceTree = "<group>"; };
|
||||
5033159A1AC101C80008A209 /* ChatRightTextCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ChatRightTextCell.swift; path = Views/Cells/ChatRightText/ChatRightTextCell.swift; sourceTree = "<group>"; };
|
||||
@@ -511,6 +524,7 @@
|
||||
50AFBF4D1BB3A594007D19DA /* bub3.caf */ = {isa = PBXFileReference; lastKnownFileType = file; name = bub3.caf; path = Sounds/bub3.caf; sourceTree = "<group>"; };
|
||||
50AFBF5E1BB4F332007D19DA /* FeedsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = FeedsViewController.swift; path = ViewControllers/Feeds/FeedsViewController.swift; sourceTree = "<group>"; };
|
||||
50B2CA911BD0BF3800668AC6 /* FeedTextView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = FeedTextView.swift; path = Views/TextViews/FeedTextView.swift; sourceTree = "<group>"; };
|
||||
50B2CA931BD0EF7900668AC6 /* MoreMessageTypesView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MoreMessageTypesView.swift; path = Views/MoreMessageTypes/MoreMessageTypesView.swift; sourceTree = "<group>"; };
|
||||
50B38FB61B69CD960064C132 /* Array+Yep.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "Array+Yep.swift"; path = "Extensions/Array+Yep.swift"; sourceTree = "<group>"; };
|
||||
50B38FCB1B6B37F00064C132 /* FeedbackViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = FeedbackViewController.swift; path = ViewControllers/Feedback/FeedbackViewController.swift; sourceTree = "<group>"; };
|
||||
50B8E6151B40F9E700C17EA1 /* YepDownloader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = YepDownloader.swift; path = Services/YepDownloader.swift; sourceTree = "<group>"; };
|
||||
@@ -974,6 +988,7 @@
|
||||
0AC25F041B1100F3009E6E13 /* ScrollView */,
|
||||
50E18BB81B180F8E0076C3C6 /* SayHi */,
|
||||
5019F62F1B39BFCB0000D993 /* ConversationMore */,
|
||||
50B2CA951BD0EF8A00668AC6 /* MoreMessageTypes */,
|
||||
500A0B201B451A7400D49358 /* Badge */,
|
||||
504F85AD1B4D21E400F909BE /* DiscoverFilter */,
|
||||
8409137E1B7DB178001C89D6 /* FriendRequest */,
|
||||
@@ -1037,6 +1052,9 @@
|
||||
501138331BCB62A70055A014 /* FeedConversation */,
|
||||
6A82150A1BCBE8F40011F36C /* DiscoverSkill */,
|
||||
50535D251BCE4A0A002FE1A4 /* Photo */,
|
||||
502B605C1BD1102F00D9C17E /* Title */,
|
||||
502B60611BD112EA00D9C17E /* QuickPickPhotos */,
|
||||
502B60661BD1209300D9C17E /* Camera */,
|
||||
);
|
||||
name = Cells;
|
||||
sourceTree = "<group>";
|
||||
@@ -1199,6 +1217,33 @@
|
||||
name = ProfileSectionHeader;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
502B605C1BD1102F00D9C17E /* Title */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
502B60581BD1102B00D9C17E /* TitleCell.swift */,
|
||||
502B60591BD1102B00D9C17E /* TitleCell.xib */,
|
||||
);
|
||||
name = Title;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
502B60611BD112EA00D9C17E /* QuickPickPhotos */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
502B605D1BD112E500D9C17E /* QuickPickPhotosCell.swift */,
|
||||
502B605E1BD112E500D9C17E /* QuickPickPhotosCell.xib */,
|
||||
);
|
||||
name = QuickPickPhotos;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
502B60661BD1209300D9C17E /* Camera */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
502B60621BD1208E00D9C17E /* CameraCell.swift */,
|
||||
502B60631BD1208E00D9C17E /* CameraCell.xib */,
|
||||
);
|
||||
name = Camera;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
503315991AC101830008A209 /* ChatLeftText */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -1693,6 +1738,14 @@
|
||||
name = Feed;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
50B2CA951BD0EF8A00668AC6 /* MoreMessageTypes */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
50B2CA931BD0EF7900668AC6 /* MoreMessageTypesView.swift */,
|
||||
);
|
||||
name = MoreMessageTypes;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
50B38FCD1B6B37F90064C132 /* Feedback */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -2116,6 +2169,7 @@
|
||||
502AE54F1AB93175005BD199 /* ProfileHeaderCell.xib in Resources */,
|
||||
50F5AF9A1BBBD02A0033C9BC /* FeedMediaCell.xib in Resources */,
|
||||
50A640EA1B6F45FA0050E4A3 /* DoNotDisturbPeriodCell.xib in Resources */,
|
||||
502B60651BD1208E00D9C17E /* CameraCell.xib in Resources */,
|
||||
0A8F54BB1AB67D11004AD60E /* LaunchScreen.xib in Resources */,
|
||||
5053AD511AF82A1700B3CBFA /* PickLocationCell.xib in Resources */,
|
||||
5011382D1BCB5E150055A014 /* FeedConversationDockCell.xib in Resources */,
|
||||
@@ -2123,6 +2177,7 @@
|
||||
0A8F54B81AB67D11004AD60E /* Images.xcassets in Resources */,
|
||||
50EB8CC51AE89F12001AC1EE /* ChatRightVideoCell.xib in Resources */,
|
||||
502AE5191AB70D72005BD199 /* Intro.storyboard in Resources */,
|
||||
502B60601BD112E500D9C17E /* QuickPickPhotosCell.xib in Resources */,
|
||||
504BDC151B4528A500DBD35D /* Badges.xcassets in Resources */,
|
||||
50F5AF961BBBCDA30033C9BC /* FeedMediaAddCell.xib in Resources */,
|
||||
50894D081AEDFDA2000981AF /* EditProfileMoreInfoCell.xib in Resources */,
|
||||
@@ -2135,6 +2190,7 @@
|
||||
501138321BCB62A20055A014 /* FeedConversationCell.xib in Resources */,
|
||||
848806B41B7B4E2E000C5424 /* Show.storyboard in Resources */,
|
||||
0AD7EA771AC3EEB000617758 /* PushConfig.plist in Resources */,
|
||||
502B605B1BD1102B00D9C17E /* TitleCell.xib in Resources */,
|
||||
5064F65A1B0B14420089FAD4 /* AddFriendMoreCell.xib in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
@@ -2242,6 +2298,7 @@
|
||||
50F5AF991BBBD02A0033C9BC /* FeedMediaCell.swift in Sources */,
|
||||
5023DE331AB688F600B3EE96 /* UIColor+Yep.swift in Sources */,
|
||||
503315971AC1017E0008A209 /* ChatLeftTextCell.swift in Sources */,
|
||||
50B2CA941BD0EF7900668AC6 /* MoreMessageTypesView.swift in Sources */,
|
||||
0A8F54B11AB67D11004AD60E /* AppDelegate.swift in Sources */,
|
||||
508F8FC81B0161EF00461B0B /* ProfileSeparationLineCell.swift in Sources */,
|
||||
500A0B1C1B450C2100D49358 /* EditNicknameAndBadgeViewController.swift in Sources */,
|
||||
@@ -2293,6 +2350,7 @@
|
||||
505EC81C1ADFBE1B001D27E0 /* SkillSelectionCell.swift in Sources */,
|
||||
5023DE591AB6DBC100B3EE96 /* UIImage+Yep.swift in Sources */,
|
||||
508F8FD41B01E3D100461B0B /* SocialWorkDribbbleViewController.swift in Sources */,
|
||||
502B605F1BD112E500D9C17E /* QuickPickPhotosCell.swift in Sources */,
|
||||
50AFBF5F1BB4F332007D19DA /* FeedsViewController.swift in Sources */,
|
||||
50EB8CBF1AE89ED8001AC1EE /* ChatLeftVideoCell.swift in Sources */,
|
||||
502AE5331AB86020005BD199 /* RegisterVerifyMobileViewController.swift in Sources */,
|
||||
@@ -2360,6 +2418,7 @@
|
||||
50E1D7291B870D7500D90A82 /* NSParagraphStyle+Yep.swift in Sources */,
|
||||
5023DE561AB6CA1000B3EE96 /* AvatarCache.swift in Sources */,
|
||||
5023DE371AB6979600B3EE96 /* ConversationCell.swift in Sources */,
|
||||
502B60641BD1208E00D9C17E /* CameraCell.swift in Sources */,
|
||||
502AE5351AB8649F005BD199 /* LoginByMobileViewController.swift in Sources */,
|
||||
506BB7F91AE5069500C1A2A0 /* RegisterPickSkillsSelectSkillsTransitionManager.swift in Sources */,
|
||||
50B8E6181B41340A00C17EA1 /* MessageLoadingProgressView.swift in Sources */,
|
||||
@@ -2395,6 +2454,7 @@
|
||||
6A5632931BC911CB00397B53 /* DiscoverNormalUserCell.swift in Sources */,
|
||||
5053AD5A1AF83B4200B3CBFA /* ChatLeftLocationCell.swift in Sources */,
|
||||
50A640E91B6F45FA0050E4A3 /* DoNotDisturbPeriodCell.swift in Sources */,
|
||||
502B605A1BD1102B00D9C17E /* TitleCell.swift in Sources */,
|
||||
840CD23C1B7B59D5000D2680 /* ShowStepViewController.swift in Sources */,
|
||||
508F8FD01B01D04400461B0B /* GithubRepoCell.swift in Sources */,
|
||||
50F2B97B1B2EEAF800F840CC /* NavigationTitleLabel.swift in Sources */,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="8191" systemVersion="15A284" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="Ha4-ol-D2e">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="8191" systemVersion="14F27" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="Ha4-ol-D2e">
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="8154"/>
|
||||
@@ -117,91 +117,34 @@
|
||||
<animations/>
|
||||
<items/>
|
||||
</toolbar>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="g11-Ob-rEy" userLabel="More Message Types View">
|
||||
<rect key="frame" x="0.0" y="440" width="600" height="300"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="avI-im-eEZ" userLabel="Choose Photo Button" customClass="MessageTypeButton" customModule="Yep" customModuleProvider="target">
|
||||
<rect key="frame" x="20" y="20" width="173.5" height="260"/>
|
||||
<animations/>
|
||||
<state key="normal">
|
||||
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</state>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="image" keyPath="image" value="icon_more_choose_photo"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="title" value="Choose photo"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="HcA-7v-16m" userLabel="Take Photo Button" customClass="MessageTypeButton" customModule="Yep" customModuleProvider="target">
|
||||
<rect key="frame" x="213" y="20" width="173" height="260"/>
|
||||
<animations/>
|
||||
<state key="normal">
|
||||
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</state>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="image" keyPath="image" value="icon_more_take_photo"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="title" value="Take photo"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Hg3-Ss-sqD" userLabel="Add Location Button" customClass="MessageTypeButton" customModule="Yep" customModuleProvider="target">
|
||||
<rect key="frame" x="406" y="20" width="173.5" height="260"/>
|
||||
<animations/>
|
||||
<state key="normal">
|
||||
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</state>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="image" keyPath="image" value="icon_more_add_location"/>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="title" value="Add location"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</button>
|
||||
</subviews>
|
||||
<animations/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<constraints>
|
||||
<constraint firstItem="avI-im-eEZ" firstAttribute="top" secondItem="HcA-7v-16m" secondAttribute="top" id="0y8-Xc-wgh"/>
|
||||
<constraint firstAttribute="trailing" secondItem="Hg3-Ss-sqD" secondAttribute="trailing" constant="20" id="662-1Z-vCm"/>
|
||||
<constraint firstItem="Hg3-Ss-sqD" firstAttribute="top" secondItem="HcA-7v-16m" secondAttribute="top" id="EhU-aN-fWf"/>
|
||||
<constraint firstItem="Hg3-Ss-sqD" firstAttribute="width" secondItem="HcA-7v-16m" secondAttribute="width" id="NQU-rh-0gL"/>
|
||||
<constraint firstItem="avI-im-eEZ" firstAttribute="width" secondItem="HcA-7v-16m" secondAttribute="width" id="Ngh-ef-Srv"/>
|
||||
<constraint firstItem="HcA-7v-16m" firstAttribute="leading" secondItem="avI-im-eEZ" secondAttribute="trailing" constant="20" id="T2D-2Y-aG4"/>
|
||||
<constraint firstItem="avI-im-eEZ" firstAttribute="height" secondItem="HcA-7v-16m" secondAttribute="height" id="apZ-ns-N9S"/>
|
||||
<constraint firstItem="avI-im-eEZ" firstAttribute="top" secondItem="g11-Ob-rEy" secondAttribute="top" constant="20" id="b4S-GW-ghP"/>
|
||||
<constraint firstAttribute="height" constant="300" id="faf-Xw-b0H"/>
|
||||
<constraint firstAttribute="bottom" secondItem="avI-im-eEZ" secondAttribute="bottom" constant="20" id="sv1-0R-BYO"/>
|
||||
<constraint firstItem="Hg3-Ss-sqD" firstAttribute="leading" secondItem="HcA-7v-16m" secondAttribute="trailing" constant="20" id="uSu-cr-saV"/>
|
||||
<constraint firstItem="avI-im-eEZ" firstAttribute="leading" secondItem="g11-Ob-rEy" secondAttribute="leading" constant="20" id="uke-uY-P5h"/>
|
||||
<constraint firstItem="Hg3-Ss-sqD" firstAttribute="height" secondItem="HcA-7v-16m" secondAttribute="height" id="xWM-E0-CPp"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<activityIndicatorView hidden="YES" opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" hidesWhenStopped="YES" style="gray" translatesAutoresizingMaskIntoConstraints="NO" id="CRx-AN-kmo">
|
||||
<rect key="frame" x="290" y="140" width="20" height="20"/>
|
||||
</activityIndicatorView>
|
||||
</subviews>
|
||||
<animations/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailing" secondItem="Q0w-sM-iIR" secondAttribute="trailing" id="0ei-y5-SyW"/>
|
||||
<constraint firstItem="CRx-AN-kmo" firstAttribute="top" secondItem="29r-Cg-jv3" secondAttribute="bottom" constant="120" id="6J8-UR-moy"/>
|
||||
<constraint firstAttribute="bottom" secondItem="o5R-dM-KPW" secondAttribute="bottom" id="9CY-zU-Ezq"/>
|
||||
<constraint firstItem="g11-Ob-rEy" firstAttribute="leading" secondItem="P6X-OT-hT5" secondAttribute="leading" id="B04-LV-qWQ"/>
|
||||
<constraint firstItem="Q0w-sM-iIR" firstAttribute="leading" secondItem="P6X-OT-hT5" secondAttribute="leading" id="BYY-lE-CF8"/>
|
||||
<constraint firstItem="o5R-dM-KPW" firstAttribute="leading" secondItem="P6X-OT-hT5" secondAttribute="leading" id="BjN-8c-WjM"/>
|
||||
<constraint firstItem="Gu7-gn-2ia" firstAttribute="centerX" secondItem="Q0w-sM-iIR" secondAttribute="centerX" id="MgC-bT-6sX"/>
|
||||
<constraint firstItem="CRx-AN-kmo" firstAttribute="centerX" secondItem="P6X-OT-hT5" secondAttribute="centerX" id="Qcn-oQ-vYU"/>
|
||||
<constraint firstItem="Gu7-gn-2ia" firstAttribute="width" secondItem="Q0w-sM-iIR" secondAttribute="width" id="Qru-A0-ifW"/>
|
||||
<constraint firstAttribute="bottom" secondItem="Q0w-sM-iIR" secondAttribute="bottom" constant="160" id="Sf8-1u-t01"/>
|
||||
<constraint firstItem="g11-Ob-rEy" firstAttribute="top" secondItem="Q0w-sM-iIR" secondAttribute="bottom" id="UC0-RV-osX"/>
|
||||
<constraint firstAttribute="trailing" secondItem="g11-Ob-rEy" secondAttribute="trailing" id="cB1-tg-2P7"/>
|
||||
<constraint firstItem="o5R-dM-KPW" firstAttribute="top" secondItem="P6X-OT-hT5" secondAttribute="top" id="d3q-cT-PCM"/>
|
||||
<constraint firstAttribute="trailing" secondItem="o5R-dM-KPW" secondAttribute="trailing" id="qY6-Ly-z3r"/>
|
||||
<constraint firstItem="Q0w-sM-iIR" firstAttribute="top" secondItem="Gu7-gn-2ia" secondAttribute="bottom" constant="20" id="xIr-4d-X2Q"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<connections>
|
||||
<outlet property="addLocationButton" destination="Hg3-Ss-sqD" id="WNz-XZ-VMJ"/>
|
||||
<outlet property="choosePhotoButton" destination="avI-im-eEZ" id="qkS-h6-VIM"/>
|
||||
<outlet property="activityIndicator" destination="CRx-AN-kmo" id="9hf-3a-cmE"/>
|
||||
<outlet property="conversationCollectionView" destination="o5R-dM-KPW" id="lsW-8A-zmB"/>
|
||||
<outlet property="messageToolbar" destination="Q0w-sM-iIR" id="vmQ-s1-SlQ"/>
|
||||
<outlet property="messageToolbarBottomConstraint" destination="Sf8-1u-t01" id="f02-ze-rKh"/>
|
||||
<outlet property="moreMessageTypesView" destination="g11-Ob-rEy" id="82c-V7-Cu4"/>
|
||||
<outlet property="moreMessageTypesViewHeightConstraint" destination="faf-Xw-b0H" id="wNA-e7-3wx"/>
|
||||
<outlet property="swipeUpPromptLabel" destination="Zew-F7-znc" id="4qL-BA-cWR"/>
|
||||
<outlet property="swipeUpView" destination="Gu7-gn-2ia" id="C4f-tg-leq"/>
|
||||
<outlet property="takePhotoButton" destination="HcA-7v-16m" id="yfB-gA-lxG"/>
|
||||
<segue destination="f92-fs-zdh" kind="presentation" identifier="presentMessageMedia" id="esY-9F-IrH"/>
|
||||
<segue destination="wNI-He-VjY" kind="presentation" identifier="presentPickLocation" id="8Uc-bg-xSe"/>
|
||||
<segue destination="AyC-pt-NR2" kind="show" identifier="showProfile" id="PTw-QB-dRp"/>
|
||||
@@ -302,13 +245,13 @@
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="k4j-Ub-3bn" customClass="MediaView" customModule="Yep" customModuleProvider="target">
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="k4j-Ub-3bn" customClass="MediaView" customModule="Yep" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
|
||||
<animations/>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
<gestureRecognizers/>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="2Cb-zQ-dUZ" customClass="MediaControlView" customModule="Yep" customModuleProvider="target">
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="2Cb-zQ-dUZ" customClass="MediaControlView" customModule="Yep" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="520" width="600" height="80"/>
|
||||
<animations/>
|
||||
<color key="backgroundColor" red="0.40000000600000002" green="0.80000001190000003" blue="1" alpha="1" colorSpace="calibratedRGB"/>
|
||||
@@ -887,7 +830,7 @@
|
||||
<animations/>
|
||||
<color key="backgroundColor" red="0.93725490196078431" green="0.93725490196078431" blue="0.95686274509803926" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<view key="tableHeaderView" contentMode="scaleToFill" id="3ZX-Cq-RRV">
|
||||
<rect key="frame" x="0.0" y="64" width="600" height="250"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="250"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<subviews>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="kAg-ue-69C" userLabel="Avatar Image View">
|
||||
@@ -1031,7 +974,7 @@
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" misplaced="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="IrX-gK-Zkg">
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="IrX-gK-Zkg">
|
||||
<rect key="frame" x="0.0" y="100" width="600" height="44"/>
|
||||
<animations/>
|
||||
<constraints>
|
||||
@@ -1044,7 +987,7 @@
|
||||
<action selector="activeFrom" destination="GqQ-V0-aYk" eventType="touchUpInside" id="yIG-DH-kZc"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" misplaced="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="flj-e3-cbm">
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="flj-e3-cbm">
|
||||
<rect key="frame" x="0.0" y="144" width="600" height="44"/>
|
||||
<animations/>
|
||||
<constraints>
|
||||
@@ -1057,7 +1000,7 @@
|
||||
<action selector="activeTo" destination="GqQ-V0-aYk" eventType="touchUpInside" id="90e-4a-0ZA"/>
|
||||
</connections>
|
||||
</button>
|
||||
<pickerView contentMode="scaleToFill" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="hap-y9-JVX">
|
||||
<pickerView contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="hap-y9-JVX">
|
||||
<rect key="frame" x="0.0" y="384" width="600" height="216"/>
|
||||
<animations/>
|
||||
<connections>
|
||||
@@ -1112,7 +1055,7 @@
|
||||
</connections>
|
||||
</tableView>
|
||||
<activityIndicatorView hidden="YES" opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" hidesWhenStopped="YES" style="gray" translatesAutoresizingMaskIntoConstraints="NO" id="mMi-L2-D7z">
|
||||
<rect key="frame" x="290" y="184" width="20" height="20"/>
|
||||
<rect key="frame" x="290" y="140" width="20" height="20"/>
|
||||
<animations/>
|
||||
</activityIndicatorView>
|
||||
</subviews>
|
||||
@@ -1161,18 +1104,18 @@
|
||||
</connections>
|
||||
</tableView>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="yep_icon_solo" translatesAutoresizingMaskIntoConstraints="NO" id="T5N-QV-ray">
|
||||
<rect key="frame" x="240" y="84" width="120" height="120"/>
|
||||
<rect key="frame" x="240" y="40" width="120" height="120"/>
|
||||
<animations/>
|
||||
</imageView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Yep" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="0gW-5K-DQz">
|
||||
<rect key="frame" x="275.5" y="223" width="50" height="36"/>
|
||||
<rect key="frame" x="275.5" y="179" width="50" height="36"/>
|
||||
<animations/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="30"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Version 1.0" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="102-IE-TP0">
|
||||
<rect key="frame" x="264.5" y="267" width="70.5" height="17"/>
|
||||
<rect key="frame" x="264.5" y="223" width="70.5" height="17"/>
|
||||
<animations/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||
<color key="textColor" red="0.60000002384185791" green="0.60000002384185791" blue="0.60000002384185791" alpha="1" colorSpace="calibratedRGB"/>
|
||||
@@ -1229,7 +1172,7 @@
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<prototypes>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="PodCell" textLabel="C1J-Nr-hJu" style="IBUITableViewCellStyleDefault" id="IC9-zO-JHD">
|
||||
<rect key="frame" x="0.0" y="86" width="600" height="44"/>
|
||||
<rect key="frame" x="0.0" y="22" width="600" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="IC9-zO-JHD" id="S8x-8A-E2F">
|
||||
<rect key="frame" x="0.0" y="0.0" width="567" height="43.5"/>
|
||||
@@ -1271,14 +1214,14 @@
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" misplaced="YES" text="We read every feedback" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="pdt-Vd-sD9">
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="We read every feedback" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="pdt-Vd-sD9">
|
||||
<rect key="frame" x="208" y="60" width="185" height="20.5"/>
|
||||
<animations/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" misplaced="YES" keyboardDismissMode="onDrag" translatesAutoresizingMaskIntoConstraints="NO" id="fVo-Zl-gHQ" customClass="FeedbackTextView" customModule="Yep" customModuleProvider="target">
|
||||
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" keyboardDismissMode="onDrag" translatesAutoresizingMaskIntoConstraints="NO" id="fVo-Zl-gHQ" customClass="FeedbackTextView" customModule="Yep" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="120.5" width="600" height="214.5"/>
|
||||
<animations/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
@@ -1321,7 +1264,7 @@
|
||||
<tableViewSection id="TBf-1w-J6s">
|
||||
<cells>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" rowHeight="60" id="hf0-DA-HE1">
|
||||
<rect key="frame" x="0.0" y="99" width="600" height="60"/>
|
||||
<rect key="frame" x="0.0" y="35" width="600" height="60"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="hf0-DA-HE1" id="M5n-HW-GKn">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="59.5"/>
|
||||
@@ -1350,7 +1293,7 @@
|
||||
<tableViewSection id="Osi-AX-ugj">
|
||||
<cells>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" rowHeight="250" id="rCs-Rg-jvK">
|
||||
<rect key="frame" x="0.0" y="179" width="600" height="250"/>
|
||||
<rect key="frame" x="0.0" y="115" width="600" height="250"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="rCs-Rg-jvK" id="Q18-jR-H2H">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="249.5"/>
|
||||
@@ -1855,7 +1798,7 @@
|
||||
<animations/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<view key="tableHeaderView" hidden="YES" contentMode="scaleToFill" id="TOk-uh-YYP">
|
||||
<rect key="frame" x="0.0" y="64" width="600" height="230"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="230"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<subviews>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="default_avatar" translatesAutoresizingMaskIntoConstraints="NO" id="YwC-QR-xbE" userLabel="Avatar Image View">
|
||||
@@ -2083,9 +2026,6 @@
|
||||
<image name="icon_list" width="30" height="30"/>
|
||||
<image name="icon_me" width="30" height="30"/>
|
||||
<image name="icon_me_active" width="30" height="30"/>
|
||||
<image name="icon_more_add_location" width="70" height="50"/>
|
||||
<image name="icon_more_choose_photo" width="70" height="50"/>
|
||||
<image name="icon_more_take_photo" width="70" height="50"/>
|
||||
<image name="icon_profile_phone" width="16" height="24"/>
|
||||
<image name="icon_settings" width="30" height="30"/>
|
||||
<image name="onepassword-navbar" width="23" height="23"/>
|
||||
@@ -2096,7 +2036,7 @@
|
||||
</resources>
|
||||
<inferredMetricsTieBreakers>
|
||||
<segue reference="o3b-2D-AMq"/>
|
||||
<segue reference="l4P-ds-ihU"/>
|
||||
<segue reference="X2e-mz-fLa"/>
|
||||
<segue reference="N7F-Tw-oVn"/>
|
||||
</inferredMetricsTieBreakers>
|
||||
</document>
|
||||
|
||||
@@ -128,18 +128,22 @@ class AvatarCache {
|
||||
}
|
||||
}
|
||||
|
||||
private var avatarCompletionSet = Set<AvatarCompletion>()
|
||||
private var avatarCompletions = [AvatarCompletion]()
|
||||
|
||||
private func removeAvatarCompletionsByAvatarURLString(avatarURLString: String) {
|
||||
let avatarCompletions = avatarCompletionSet.filter({ $0.avatarURLString == avatarURLString })
|
||||
avatarCompletions.forEach {
|
||||
avatarCompletionSet.remove($0)
|
||||
}
|
||||
|
||||
let completionsToRemove = avatarCompletions.filter({ $0.avatarURLString == avatarURLString })
|
||||
|
||||
completionsToRemove.forEach({
|
||||
if let index = avatarCompletions.indexOf($0) {
|
||||
avatarCompletions.removeAtIndex(index)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private func completeWithImage(image: UIImage, avatarURLString: String) {
|
||||
|
||||
for avatarCompletion in avatarCompletionSet.filter({ $0.avatarURLString == avatarURLString }) {
|
||||
for avatarCompletion in avatarCompletions.filter({ $0.avatarURLString == avatarURLString }) {
|
||||
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)) {
|
||||
let avatar = image.roundImageOfRadius(avatarCompletion.radius)
|
||||
@@ -203,9 +207,9 @@ class AvatarCache {
|
||||
removeAvatarCompletionsByAvatarURLString(avatarURLString)
|
||||
|
||||
// NOTICE: 默认在主线程添加
|
||||
avatarCompletionSet.insert(avatarCompletion)
|
||||
avatarCompletions.append(avatarCompletion)
|
||||
|
||||
if avatarCompletionSet.filter({ $0.avatarURLString == avatarURLString }).count > 1 {
|
||||
if avatarCompletions.filter({ $0.avatarURLString == avatarURLString }).count > 1 {
|
||||
// 不用做事,等着具有同样 avatarURLString 的 avatarCompletion 帮忙完成
|
||||
|
||||
} else {
|
||||
@@ -360,9 +364,9 @@ class AvatarCache {
|
||||
removeAvatarCompletionsByAvatarURLString(avatarURLString)
|
||||
|
||||
// NOTICE: 默认在主线程添加
|
||||
avatarCompletionSet.insert(avatarCompletion)
|
||||
avatarCompletions.append(avatarCompletion)
|
||||
|
||||
if avatarCompletionSet.filter({ $0.avatarURLString == avatarURLString }).count > 1 {
|
||||
if avatarCompletions.filter({ $0.avatarURLString == avatarURLString }).count > 1 {
|
||||
// 不用做事,等着具有同样 avatarURLString 的 avatarCompletion 帮忙完成
|
||||
|
||||
} else {
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "icon_more_add_contact.pdf"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "icon_more_add_location.pdf"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
BIN
Binary file not shown.
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "icon_more_choose_photo.pdf"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
BIN
Binary file not shown.
Binary file not shown.
+1
-1
@@ -2,7 +2,7 @@
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "icon_more_take_photo.pdf"
|
||||
"filename" : "icon_quick_camera.pdf"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
BIN
Binary file not shown.
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "item_less.pdf"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
},
|
||||
"properties" : {
|
||||
"template-rendering-intent" : "template"
|
||||
}
|
||||
}
|
||||
@@ -1630,7 +1630,7 @@ enum TimeDirection {
|
||||
}
|
||||
}
|
||||
|
||||
func messagesFromRecipient(recipient: Recipient, withTimeDirection timeDirection: TimeDirection, failureHandler: ((Reason, String?) -> Void)?, completion: Bool -> Void) {
|
||||
func messagesFromRecipient(recipient: Recipient, withTimeDirection timeDirection: TimeDirection, failureHandler: ((Reason, String?) -> Void)?, completion: (messageIDs: [String]) -> Void) {
|
||||
|
||||
var requestParameters = [
|
||||
"recipient_type": recipient.type.nameForServer,
|
||||
@@ -1646,32 +1646,25 @@ func messagesFromRecipient(recipient: Recipient, withTimeDirection timeDirection
|
||||
break
|
||||
}
|
||||
|
||||
let parse: JSONDictionary -> Bool? = { data in
|
||||
let parse: JSONDictionary -> [String]? = { data in
|
||||
|
||||
guard let unreadMessagesData = data["messages"] as? [JSONDictionary] else {
|
||||
return false
|
||||
guard let
|
||||
unreadMessagesData = data["messages"] as? [JSONDictionary],
|
||||
realm = try? Realm() else {
|
||||
return []
|
||||
}
|
||||
|
||||
println("messagesFromRecipient: \(recipient), \(unreadMessagesData.count)")
|
||||
//println("messagesFromRecipient: \(recipient), \(unreadMessagesData.count)")
|
||||
|
||||
dispatch_async(dispatch_get_main_queue()) {
|
||||
var messageIDs = [String]()
|
||||
|
||||
guard let realm = try? Realm() else {
|
||||
return
|
||||
for messageInfo in unreadMessagesData {
|
||||
syncMessageWithMessageInfo(messageInfo, messageAge: timeDirection.messageAge, inRealm: realm) { _messageIDs in
|
||||
messageIDs += _messageIDs
|
||||
}
|
||||
|
||||
var messageIDs = [String]()
|
||||
|
||||
for messageInfo in unreadMessagesData {
|
||||
syncMessageWithMessageInfo(messageInfo, messageAge: timeDirection.messageAge, inRealm: realm) { _messageIDs in
|
||||
messageIDs += _messageIDs
|
||||
}
|
||||
}
|
||||
|
||||
tryPostNewMessagesReceivedNotificationWithMessageIDs(messageIDs, withMessageAge: .New)
|
||||
}
|
||||
|
||||
return true
|
||||
return messageIDs
|
||||
}
|
||||
|
||||
let resource = authJsonResource(path: "/api/v1/\(recipient.type.nameForServer)/\(recipient.ID)/messages", method: .GET, requestParameters: requestParameters, parse: parse )
|
||||
|
||||
@@ -150,6 +150,57 @@ class ConversationViewController: BaseViewController {
|
||||
|
||||
lazy var moreView: ConversationMoreView = ConversationMoreView()
|
||||
|
||||
lazy var moreMessageTypesView: MoreMessageTypesView = {
|
||||
|
||||
let view = MoreMessageTypesView()
|
||||
|
||||
view.alertCanNotAccessCameraRollAction = { [weak self] in
|
||||
self?.alertCanNotAccessCameraRoll()
|
||||
}
|
||||
|
||||
view.sendImageAction = { [weak self] image in
|
||||
self?.sendImage(image)
|
||||
}
|
||||
|
||||
view.takePhotoAction = { [weak self] in
|
||||
|
||||
let openCamera: ProposerAction = { [weak self] in
|
||||
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.Camera) {
|
||||
if let strongSelf = self {
|
||||
strongSelf.imagePicker.sourceType = .Camera
|
||||
strongSelf.presentViewController(strongSelf.imagePicker, animated: true, completion: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
proposeToAccess(.Camera, agreed: openCamera, rejected: {
|
||||
self?.alertCanNotOpenCamera()
|
||||
})
|
||||
}
|
||||
|
||||
view.choosePhotoAction = { [weak self] in
|
||||
|
||||
let openCameraRoll: ProposerAction = { [weak self] in
|
||||
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.PhotoLibrary){
|
||||
if let strongSelf = self {
|
||||
strongSelf.imagePicker.sourceType = .PhotoLibrary
|
||||
strongSelf.presentViewController(strongSelf.imagePicker, animated: true, completion: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
proposeToAccess(.Photos, agreed: openCameraRoll, rejected: {
|
||||
self?.alertCanNotAccessCameraRoll()
|
||||
})
|
||||
}
|
||||
|
||||
view.pickLocationAction = { [weak self] in
|
||||
self?.performSegueWithIdentifier("presentPickLocation", sender: nil)
|
||||
}
|
||||
|
||||
return view
|
||||
}()
|
||||
|
||||
lazy var pullToRefreshView: PullToRefreshView = {
|
||||
|
||||
let pullToRefreshView = PullToRefreshView()
|
||||
@@ -208,16 +259,18 @@ class ConversationViewController: BaseViewController {
|
||||
@IBOutlet weak var messageToolbar: MessageToolbar!
|
||||
@IBOutlet weak var messageToolbarBottomConstraint: NSLayoutConstraint!
|
||||
|
||||
@IBOutlet weak var moreMessageTypesView: UIView!
|
||||
@IBOutlet weak var moreMessageTypesViewHeightConstraint: NSLayoutConstraint!
|
||||
let moreMessageTypesViewDefaultHeight: CGFloat = 110
|
||||
//@IBOutlet weak var moreMessageTypesView: UIView!
|
||||
//@IBOutlet weak var moreMessageTypesViewHeightConstraint: NSLayoutConstraint!
|
||||
//let moreMessageTypesViewDefaultHeight: CGFloat = 110
|
||||
|
||||
@IBOutlet weak var choosePhotoButton: MessageTypeButton!
|
||||
@IBOutlet weak var takePhotoButton: MessageTypeButton!
|
||||
@IBOutlet weak var addLocationButton: MessageTypeButton!
|
||||
//@IBOutlet weak var choosePhotoButton: MessageTypeButton!
|
||||
//@IBOutlet weak var takePhotoButton: MessageTypeButton!
|
||||
//@IBOutlet weak var addLocationButton: MessageTypeButton!
|
||||
|
||||
@IBOutlet weak var swipeUpView: UIView!
|
||||
@IBOutlet weak var swipeUpPromptLabel: UILabel!
|
||||
|
||||
@IBOutlet weak var activityIndicator: UIActivityIndicatorView!
|
||||
|
||||
var isTryingShowFriendRequestView = false
|
||||
|
||||
@@ -357,7 +410,7 @@ class ConversationViewController: BaseViewController {
|
||||
conversationCollectionView.addGestureRecognizer(tap)
|
||||
|
||||
messageToolbarBottomConstraint.constant = 0
|
||||
moreMessageTypesViewHeightConstraint.constant = moreMessageTypesViewDefaultHeight
|
||||
//moreMessageTypesViewHeightConstraint.constant = moreMessageTypesViewDefaultHeight
|
||||
|
||||
keyboardMan.animateWhenKeyboardAppear = { [weak self] appearPostIndex, keyboardHeight, keyboardHeightIncrement in
|
||||
|
||||
@@ -369,7 +422,7 @@ class ConversationViewController: BaseViewController {
|
||||
|
||||
// 注意第一次要减去已经有的高度偏移
|
||||
if appearPostIndex == 0 {
|
||||
strongSelf.conversationCollectionView.contentOffset.y += keyboardHeightIncrement - strongSelf.moreMessageTypesViewDefaultHeight
|
||||
strongSelf.conversationCollectionView.contentOffset.y += keyboardHeightIncrement //- strongSelf.moreMessageTypesViewDefaultHeight
|
||||
} else {
|
||||
strongSelf.conversationCollectionView.contentOffset.y += keyboardHeightIncrement
|
||||
}
|
||||
@@ -395,20 +448,11 @@ class ConversationViewController: BaseViewController {
|
||||
|
||||
if let strongSelf = self {
|
||||
|
||||
if strongSelf.messageToolbar.state == .MoreMessages {
|
||||
strongSelf.conversationCollectionView.contentOffset.y -= keyboardHeight - strongSelf.moreMessageTypesViewDefaultHeight
|
||||
strongSelf.conversationCollectionView.contentInset.bottom = strongSelf.messageToolbar.frame.height + strongSelf.moreMessageTypesViewDefaultHeight
|
||||
strongSelf.conversationCollectionView.contentOffset.y -= keyboardHeight
|
||||
strongSelf.conversationCollectionView.contentInset.bottom = strongSelf.messageToolbar.frame.height
|
||||
|
||||
strongSelf.messageToolbarBottomConstraint.constant = strongSelf.moreMessageTypesViewDefaultHeight
|
||||
strongSelf.view.layoutIfNeeded()
|
||||
|
||||
} else {
|
||||
strongSelf.conversationCollectionView.contentOffset.y -= keyboardHeight
|
||||
strongSelf.conversationCollectionView.contentInset.bottom = strongSelf.messageToolbar.frame.height
|
||||
|
||||
strongSelf.messageToolbarBottomConstraint.constant = 0
|
||||
strongSelf.view.layoutIfNeeded()
|
||||
}
|
||||
strongSelf.messageToolbarBottomConstraint.constant = 0
|
||||
strongSelf.view.layoutIfNeeded()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -424,10 +468,19 @@ class ConversationViewController: BaseViewController {
|
||||
timeDirection = .Future(minMessageID: minMessageID)
|
||||
} else {
|
||||
timeDirection = .None
|
||||
|
||||
self?.activityIndicator.startAnimating()
|
||||
}
|
||||
|
||||
messagesFromRecipient(recipient, withTimeDirection: timeDirection, failureHandler: nil, completion: { success in
|
||||
println("messagesFromRecipient: \(success)")
|
||||
messagesFromRecipient(recipient, withTimeDirection: timeDirection, failureHandler: nil, completion: { messageIDs in
|
||||
println("messagesFromRecipient: \(messageIDs.count)")
|
||||
|
||||
dispatch_async(dispatch_get_main_queue()) { [weak self] in
|
||||
|
||||
tryPostNewMessagesReceivedNotificationWithMessageIDs(messageIDs, withMessageAge: timeDirection.messageAge)
|
||||
|
||||
self?.activityIndicator.stopAnimating()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -480,61 +533,26 @@ class ConversationViewController: BaseViewController {
|
||||
|
||||
messageToolbar.conversation = conversation
|
||||
|
||||
// MARK: MessageToolbar MoreMessageTypes
|
||||
|
||||
messageToolbar.moreMessageTypesAction = { [weak self] in
|
||||
|
||||
if let window = self?.view.window {
|
||||
self?.moreMessageTypesView.showInView(window)
|
||||
|
||||
delay(0.2) {
|
||||
self?.imagePicker.hidesBarsOnTap = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: MessageToolbar State Transitions
|
||||
|
||||
messageToolbar.stateTransitionAction = { [weak self] (messageToolbar, previousState, currentState) in
|
||||
|
||||
if let strongSelf = self {
|
||||
|
||||
switch (previousState, currentState) {
|
||||
|
||||
case (.MoreMessages, .Default): fallthrough
|
||||
case (.MoreMessages, .VoiceRecord):
|
||||
|
||||
dispatch_async(dispatch_get_main_queue()) { [weak self] in
|
||||
|
||||
UIView.animateWithDuration(0.2, delay: 0.0, options: .CurveEaseInOut, animations: { _ in
|
||||
|
||||
strongSelf.conversationCollectionView.contentOffset.y -= strongSelf.moreMessageTypesViewDefaultHeight
|
||||
strongSelf.conversationCollectionView.contentInset.bottom = strongSelf.messageToolbar.frame.height
|
||||
|
||||
strongSelf.messageToolbarBottomConstraint.constant = 0
|
||||
strongSelf.view.layoutIfNeeded()
|
||||
|
||||
}, completion: { finished in
|
||||
})
|
||||
}
|
||||
|
||||
default:
|
||||
|
||||
if currentState == .MoreMessages {
|
||||
|
||||
if previousState != .BeginTextInput && previousState != .TextInputing {
|
||||
|
||||
dispatch_async(dispatch_get_main_queue()) { [weak self] in
|
||||
|
||||
UIView.animateWithDuration(0.2, delay: 0.0, options: .CurveEaseInOut, animations: { _ in
|
||||
|
||||
strongSelf.conversationCollectionView.contentOffset.y += strongSelf.moreMessageTypesViewDefaultHeight
|
||||
strongSelf.conversationCollectionView.contentInset.bottom = strongSelf.messageToolbar.frame.height + strongSelf.moreMessageTypesViewDefaultHeight
|
||||
|
||||
strongSelf.messageToolbarBottomConstraint.constant = strongSelf.moreMessageTypesViewDefaultHeight
|
||||
strongSelf.view.layoutIfNeeded()
|
||||
|
||||
}, completion: { finished in
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// touch to create (if need) for faster appear
|
||||
delay(0.2) {
|
||||
self?.imagePicker.hidesBarsOnTap = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch currentState {
|
||||
case .BeginTextInput, .MoreMessages:
|
||||
case .BeginTextInput:
|
||||
self?.tryFoldFeedView()
|
||||
default:
|
||||
break
|
||||
@@ -871,47 +889,6 @@ class ConversationViewController: BaseViewController {
|
||||
|
||||
self?.swipeUpPromptLabel.text = text
|
||||
}
|
||||
|
||||
// MARK: More Message Types
|
||||
|
||||
choosePhotoButton.title = NSLocalizedString("Choose photo", comment: "")
|
||||
choosePhotoButton.tapAction = { [weak self] in
|
||||
|
||||
let openCameraRoll: ProposerAction = { [weak self] in
|
||||
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.PhotoLibrary){
|
||||
if let strongSelf = self {
|
||||
strongSelf.imagePicker.sourceType = .PhotoLibrary
|
||||
strongSelf.presentViewController(strongSelf.imagePicker, animated: true, completion: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
proposeToAccess(.Photos, agreed: openCameraRoll, rejected: {
|
||||
self?.alertCanNotAccessCameraRoll()
|
||||
})
|
||||
}
|
||||
|
||||
takePhotoButton.title = NSLocalizedString("Take photo", comment: "")
|
||||
takePhotoButton.tapAction = { [weak self] in
|
||||
|
||||
let openCamera: ProposerAction = { [weak self] in
|
||||
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.Camera) {
|
||||
if let strongSelf = self {
|
||||
strongSelf.imagePicker.sourceType = .Camera
|
||||
strongSelf.presentViewController(strongSelf.imagePicker, animated: true, completion: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
proposeToAccess(.Camera, agreed: openCamera, rejected: {
|
||||
self?.alertCanNotOpenCamera()
|
||||
})
|
||||
}
|
||||
|
||||
addLocationButton.title = NSLocalizedString("Share location", comment: "")
|
||||
addLocationButton.tapAction = { [weak self] in
|
||||
self?.performSegueWithIdentifier("presentPickLocation", sender: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2931,7 +2908,7 @@ extension ConversationViewController: UICollectionViewDataSource, UICollectionVi
|
||||
|
||||
switch messageToolbar.state {
|
||||
|
||||
case .BeginTextInput, .TextInputing, .MoreMessages:
|
||||
case .BeginTextInput, .TextInputing:
|
||||
messageToolbar.state = .Default
|
||||
|
||||
default:
|
||||
@@ -3015,11 +2992,15 @@ extension ConversationViewController: PullToRefreshViewDelegate {
|
||||
timeDirection = .None
|
||||
}
|
||||
|
||||
messagesFromRecipient(recipient, withTimeDirection: timeDirection, failureHandler: nil, completion: { success in
|
||||
println("messagesFromRecipient: \(success)")
|
||||
messagesFromRecipient(recipient, withTimeDirection: timeDirection, failureHandler: nil, completion: { messageIDs in
|
||||
println("messagesFromRecipient: \(messageIDs.count)")
|
||||
|
||||
dispatch_async(dispatch_get_main_queue()) {
|
||||
pulllToRefreshView.endRefreshingAndDoFurtherAction() {}
|
||||
pulllToRefreshView.endRefreshingAndDoFurtherAction() {
|
||||
dispatch_async(dispatch_get_main_queue()) {
|
||||
tryPostNewMessagesReceivedNotificationWithMessageIDs(messageIDs, withMessageAge: timeDirection.messageAge)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -3036,7 +3017,7 @@ extension ConversationViewController: PullToRefreshViewDelegate {
|
||||
var newMessagesCount = strongSelf.messagesBunchCount
|
||||
|
||||
if (strongSelf.displayedMessagesRange.location - newMessagesCount) < 0 {
|
||||
newMessagesCount = strongSelf.displayedMessagesRange.location - newMessagesCount
|
||||
newMessagesCount = strongSelf.displayedMessagesRange.location
|
||||
}
|
||||
|
||||
if newMessagesCount > 0 {
|
||||
|
||||
@@ -21,15 +21,6 @@ class NewFeedViewController: UIViewController {
|
||||
@IBOutlet weak var messageTextView: UITextView!
|
||||
@IBOutlet weak var mediaCollectionView: UICollectionView!
|
||||
|
||||
lazy var imagePicker: UIImagePickerController = {
|
||||
let imagePicker = UIImagePickerController()
|
||||
imagePicker.delegate = self
|
||||
imagePicker.mediaTypes = [kUTTypeImage as String]
|
||||
imagePicker.videoQuality = .TypeMedium
|
||||
imagePicker.allowsEditing = false
|
||||
return imagePicker
|
||||
}()
|
||||
|
||||
var imageAssetSet: Set<PHAsset>?
|
||||
|
||||
var mediaImages = [UIImage]() {
|
||||
@@ -96,15 +87,6 @@ class NewFeedViewController: UIViewController {
|
||||
}
|
||||
}
|
||||
|
||||
override func viewDidAppear(animated: Bool) {
|
||||
super.viewDidAppear(animated)
|
||||
|
||||
// touch to create (if need) for faster appear
|
||||
delay(0.2) { [weak self] in
|
||||
self?.imagePicker.hidesBarsOnTap = false
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Navigation
|
||||
|
||||
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
|
||||
@@ -265,21 +247,6 @@ extension NewFeedViewController: UICollectionViewDataSource, UICollectionViewDel
|
||||
switch indexPath.section {
|
||||
|
||||
case 0:
|
||||
/*
|
||||
let openCameraRoll: ProposerAction = { [weak self] in
|
||||
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.PhotoLibrary) {
|
||||
if let strongSelf = self {
|
||||
strongSelf.imagePicker.sourceType = .SavedPhotosAlbum
|
||||
strongSelf.presentViewController(strongSelf.imagePicker, animated: true, completion: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
proposeToAccess(.Photos, agreed: openCameraRoll, rejected: { [weak self] in
|
||||
self?.alertCanNotAccessCameraRoll()
|
||||
})
|
||||
*/
|
||||
|
||||
proposeToAccess(.Photos, agreed: { [weak self] in
|
||||
self?.performSegueWithIdentifier("showPickPhotos", sender: nil)
|
||||
|
||||
@@ -297,42 +264,3 @@ extension NewFeedViewController: UICollectionViewDataSource, UICollectionViewDel
|
||||
}
|
||||
}
|
||||
|
||||
extension NewFeedViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
|
||||
|
||||
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
|
||||
|
||||
if let mediaType = info[UIImagePickerControllerMediaType] as? String {
|
||||
|
||||
if mediaType == (kUTTypeImage as String) {
|
||||
|
||||
if let image = info[UIImagePickerControllerOriginalImage] as? UIImage {
|
||||
|
||||
let imageWidth = image.size.width
|
||||
let imageHeight = image.size.height
|
||||
|
||||
let fixedImageWidth: CGFloat
|
||||
let fixedImageHeight: CGFloat
|
||||
|
||||
if imageWidth > imageHeight {
|
||||
fixedImageWidth = min(imageWidth, YepConfig.Media.imageWidth)
|
||||
fixedImageHeight = imageHeight * (fixedImageWidth / imageWidth)
|
||||
} else {
|
||||
fixedImageHeight = min(imageHeight, YepConfig.Media.imageHeight)
|
||||
fixedImageWidth = imageWidth * (fixedImageHeight / imageHeight)
|
||||
}
|
||||
|
||||
let fixedSize = CGSize(width: fixedImageWidth, height: fixedImageHeight)
|
||||
|
||||
// resize to smaller, not need fixRotation
|
||||
|
||||
if let fixedImage = image.resizeToSize(fixedSize, withInterpolationQuality: CGInterpolationQuality.Medium) {
|
||||
mediaImages.append(fixedImage)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dismissViewControllerAnimated(true, completion: nil)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,11 @@ class PickPhotosViewController: UICollectionViewController, PHPhotoLibraryChange
|
||||
layout.sectionInset = UIEdgeInsets(top: gap, left: gap, bottom: gap, right: gap)
|
||||
}
|
||||
|
||||
images = PHAsset.fetchAssetsWithMediaType(.Image, options: nil)
|
||||
let options = PHFetchOptions()
|
||||
options.sortDescriptors = [
|
||||
NSSortDescriptor(key: "creationDate", ascending: false)
|
||||
]
|
||||
images = PHAsset.fetchAssetsWithMediaType(.Image, options: options)
|
||||
imageCacheController = ImageCacheController(imageManager: imageManager, images: images, preheatSize: 1)
|
||||
|
||||
PHPhotoLibrary.sharedPhotoLibrary().registerChangeObserver(self)
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
//
|
||||
// CameraCell.swift
|
||||
// Yep
|
||||
//
|
||||
// Created by nixzhu on 15/10/16.
|
||||
// Copyright © 2015年 Catch Inc. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class CameraCell: UICollectionViewCell {
|
||||
|
||||
override func awakeFromNib() {
|
||||
super.awakeFromNib()
|
||||
|
||||
contentView.backgroundColor = UIColor.yepTintColor()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="8191" systemVersion="14F27" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES">
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="8154"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="CameraCell" id="gTV-IL-0wX" customClass="CameraCell" customModule="Yep" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="50" height="50"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
|
||||
<rect key="frame" x="0.0" y="0.0" width="50" height="50"/>
|
||||
<subviews>
|
||||
<imageView userInteractionEnabled="NO" contentMode="center" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="icon_quick_camera" translatesAutoresizingMaskIntoConstraints="NO" id="9H2-Nb-pKx">
|
||||
<rect key="frame" x="0.0" y="0.0" width="50" height="50"/>
|
||||
</imageView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
</view>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailing" secondItem="9H2-Nb-pKx" secondAttribute="trailing" id="Ebt-FV-r5v"/>
|
||||
<constraint firstItem="9H2-Nb-pKx" firstAttribute="top" secondItem="gTV-IL-0wX" secondAttribute="top" id="HKc-Mu-Gug"/>
|
||||
<constraint firstAttribute="bottom" secondItem="9H2-Nb-pKx" secondAttribute="bottom" id="c9B-Th-ydg"/>
|
||||
<constraint firstItem="9H2-Nb-pKx" firstAttribute="leading" secondItem="gTV-IL-0wX" secondAttribute="leading" id="u3H-nX-AMl"/>
|
||||
</constraints>
|
||||
</collectionViewCell>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="icon_quick_camera" width="70" height="50"/>
|
||||
</resources>
|
||||
</document>
|
||||
@@ -0,0 +1,151 @@
|
||||
//
|
||||
// QuickPickPhotosCell.swift
|
||||
// Yep
|
||||
//
|
||||
// Created by nixzhu on 15/10/16.
|
||||
// Copyright © 2015年 Catch Inc. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import Photos
|
||||
import Proposer
|
||||
|
||||
class QuickPickPhotosCell: UITableViewCell {
|
||||
|
||||
@IBOutlet weak var photosCollectionView: UICollectionView!
|
||||
|
||||
var alertCanNotAccessCameraRollAction: (() -> Void)?
|
||||
var takePhotoAction: (() -> Void)?
|
||||
var pickedPhotosAction: (Set<PHAsset> -> Void)?
|
||||
|
||||
var images: PHFetchResult?
|
||||
let imageManager = PHCachingImageManager()
|
||||
var imageCacheController: ImageCacheController!
|
||||
|
||||
var pickedImageSet = Set<PHAsset>() {
|
||||
didSet {
|
||||
pickedPhotosAction?(pickedImageSet)
|
||||
}
|
||||
}
|
||||
var completion: ((images: [UIImage], imageAssetSet: Set<PHAsset>) -> Void)?
|
||||
|
||||
let cameraCellID = "CameraCell"
|
||||
let photoCellID = "PhotoCell"
|
||||
|
||||
override func awakeFromNib() {
|
||||
super.awakeFromNib()
|
||||
|
||||
photosCollectionView.backgroundColor = UIColor.clearColor()
|
||||
photosCollectionView.registerNib(UINib(nibName: cameraCellID, bundle: nil), forCellWithReuseIdentifier: cameraCellID)
|
||||
photosCollectionView.registerNib(UINib(nibName: photoCellID, bundle: nil), forCellWithReuseIdentifier: photoCellID)
|
||||
photosCollectionView.dataSource = self
|
||||
photosCollectionView.delegate = self
|
||||
|
||||
if let layout = photosCollectionView.collectionViewLayout as? UICollectionViewFlowLayout {
|
||||
layout.itemSize = CGSize(width: 70, height: 70)
|
||||
layout.minimumInteritemSpacing = 10
|
||||
layout.sectionInset = UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 0)
|
||||
|
||||
photosCollectionView.contentInset = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 0)
|
||||
}
|
||||
|
||||
proposeToAccess(.Photos, agreed: {
|
||||
dispatch_async(dispatch_get_main_queue()) { [weak self] in
|
||||
if let strongSelf = self {
|
||||
let options = PHFetchOptions()
|
||||
options.sortDescriptors = [
|
||||
NSSortDescriptor(key: "creationDate", ascending: false)
|
||||
]
|
||||
let images = PHAsset.fetchAssetsWithMediaType(.Image, options: options)
|
||||
strongSelf.images = images
|
||||
strongSelf.imageCacheController = ImageCacheController(imageManager: strongSelf.imageManager, images: images, preheatSize: 1)
|
||||
|
||||
strongSelf.photosCollectionView.reloadData()
|
||||
}
|
||||
}
|
||||
|
||||
}, rejected: { [weak self] in
|
||||
self?.alertCanNotAccessCameraRollAction?()
|
||||
})
|
||||
}
|
||||
|
||||
override func setSelected(selected: Bool, animated: Bool) {
|
||||
super.setSelected(selected, animated: animated)
|
||||
|
||||
// Configure the view for the selected state
|
||||
}
|
||||
}
|
||||
|
||||
extension QuickPickPhotosCell: UICollectionViewDataSource, UICollectionViewDelegate {
|
||||
|
||||
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
|
||||
return 2
|
||||
}
|
||||
|
||||
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
|
||||
switch section {
|
||||
case 0:
|
||||
return 1
|
||||
case 1:
|
||||
return images?.count ?? 0
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
|
||||
|
||||
switch indexPath.section {
|
||||
|
||||
case 0:
|
||||
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(cameraCellID, forIndexPath: indexPath) as! CameraCell
|
||||
return cell
|
||||
|
||||
case 1:
|
||||
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(photoCellID, forIndexPath: indexPath) as! PhotoCell
|
||||
return cell
|
||||
|
||||
default:
|
||||
return UICollectionViewCell()
|
||||
}
|
||||
}
|
||||
|
||||
func collectionView(collectionView: UICollectionView, willDisplayCell cell: UICollectionViewCell, forItemAtIndexPath indexPath: NSIndexPath) {
|
||||
|
||||
if let cell = cell as? PhotoCell {
|
||||
cell.imageManager = imageManager
|
||||
|
||||
if let imageAsset = images?[indexPath.item] as? PHAsset {
|
||||
cell.imageAsset = imageAsset
|
||||
cell.photoPickedImageView.hidden = !pickedImageSet.contains(imageAsset)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
|
||||
|
||||
switch indexPath.section {
|
||||
|
||||
case 0:
|
||||
takePhotoAction?()
|
||||
|
||||
case 1:
|
||||
if let imageAsset = images?[indexPath.item] as? PHAsset {
|
||||
|
||||
if pickedImageSet.contains(imageAsset) {
|
||||
pickedImageSet.remove(imageAsset)
|
||||
|
||||
} else {
|
||||
pickedImageSet.insert(imageAsset)
|
||||
}
|
||||
|
||||
let cell = collectionView.cellForItemAtIndexPath(indexPath) as! PhotoCell
|
||||
cell.photoPickedImageView.hidden = !pickedImageSet.contains(imageAsset)
|
||||
}
|
||||
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="8191" systemVersion="14F27" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES">
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="8154"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="QuickPickPhotosCell" rowHeight="88" id="KGk-i7-Jjw" customClass="QuickPickPhotosCell" customModule="Yep" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="88"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="KGk-i7-Jjw" id="H2p-sc-9uM">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="87.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<collectionView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" dataMode="none" translatesAutoresizingMaskIntoConstraints="NO" id="95w-sj-Pxi">
|
||||
<rect key="frame" x="0.0" y="15" width="320" height="57.5"/>
|
||||
<collectionViewFlowLayout key="collectionViewLayout" scrollDirection="horizontal" minimumLineSpacing="10" minimumInteritemSpacing="10" id="axC-xs-FG9">
|
||||
<size key="itemSize" width="50" height="50"/>
|
||||
<size key="headerReferenceSize" width="0.0" height="0.0"/>
|
||||
<size key="footerReferenceSize" width="0.0" height="0.0"/>
|
||||
<inset key="sectionInset" minX="0.0" minY="0.0" maxX="0.0" maxY="0.0"/>
|
||||
</collectionViewFlowLayout>
|
||||
</collectionView>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="95w-sj-Pxi" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leading" id="3SC-eg-mje"/>
|
||||
<constraint firstItem="95w-sj-Pxi" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="top" constant="15" id="HBP-ep-UOY"/>
|
||||
<constraint firstAttribute="trailing" secondItem="95w-sj-Pxi" secondAttribute="trailing" id="NLc-t9-7eq"/>
|
||||
<constraint firstAttribute="bottom" secondItem="95w-sj-Pxi" secondAttribute="bottom" constant="15" id="pl8-YR-i4m"/>
|
||||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
<connections>
|
||||
<outlet property="photosCollectionView" destination="95w-sj-Pxi" id="95L-9S-3CB"/>
|
||||
</connections>
|
||||
<point key="canvasLocation" x="242" y="176"/>
|
||||
</tableViewCell>
|
||||
</objects>
|
||||
</document>
|
||||
@@ -0,0 +1,32 @@
|
||||
//
|
||||
// TitleCell.swift
|
||||
// Yep
|
||||
//
|
||||
// Created by nixzhu on 15/10/16.
|
||||
// Copyright © 2015年 Catch Inc. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class TitleCell: UITableViewCell {
|
||||
|
||||
@IBOutlet weak var singleTitleLabel: UILabel!
|
||||
|
||||
var boldEnabled = false {
|
||||
didSet {
|
||||
singleTitleLabel.font = boldEnabled ? UIFont.boldSystemFontOfSize(17) : UIFont.systemFontOfSize(17)
|
||||
}
|
||||
}
|
||||
|
||||
override func awakeFromNib() {
|
||||
super.awakeFromNib()
|
||||
// Initialization code
|
||||
}
|
||||
|
||||
override func setSelected(selected: Bool, animated: Bool) {
|
||||
super.setSelected(selected, animated: animated)
|
||||
|
||||
// Configure the view for the selected state
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="8191" systemVersion="14F27" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES">
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="8154"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="TitleCell" id="KGk-i7-Jjw" customClass="TitleCell" customModule="Yep" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="KGk-i7-Jjw" id="H2p-sc-9uM">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="PSq-Uu-HCz">
|
||||
<rect key="frame" x="10" y="11.5" width="300" height="20.5"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="PSq-Uu-HCz" firstAttribute="centerX" secondItem="H2p-sc-9uM" secondAttribute="centerX" id="0Yn-oK-RCs"/>
|
||||
<constraint firstItem="PSq-Uu-HCz" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leading" constant="10" id="HkJ-Tg-qxn"/>
|
||||
<constraint firstItem="PSq-Uu-HCz" firstAttribute="centerY" secondItem="H2p-sc-9uM" secondAttribute="centerY" id="c5R-vW-cfB"/>
|
||||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
<connections>
|
||||
<outlet property="singleTitleLabel" destination="PSq-Uu-HCz" id="nwv-qe-6hx"/>
|
||||
</connections>
|
||||
</tableViewCell>
|
||||
</objects>
|
||||
</document>
|
||||
@@ -9,11 +9,11 @@
|
||||
import UIKit
|
||||
|
||||
enum MessageToolbarState: Int, CustomStringConvertible {
|
||||
|
||||
case Default
|
||||
case BeginTextInput
|
||||
case TextInputing
|
||||
case VoiceRecord
|
||||
case MoreMessages
|
||||
|
||||
var description: String {
|
||||
switch self {
|
||||
@@ -25,8 +25,6 @@ enum MessageToolbarState: Int, CustomStringConvertible {
|
||||
return "TextInputing"
|
||||
case .VoiceRecord:
|
||||
return "VoiceRecord"
|
||||
case .MoreMessages:
|
||||
return "MoreMessages"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -113,10 +111,6 @@ class MessageToolbar: UIToolbar {
|
||||
moreButton.tintColor = UIColor.messageToolBarColor()
|
||||
|
||||
showVoiceButtonAnimation()
|
||||
|
||||
case .MoreMessages:
|
||||
moreButton.setImage(UIImage(named: "item_less"), forState: .Normal)
|
||||
moreButton.tintColor = UIColor.messageToolBarHighlightColor()
|
||||
}
|
||||
|
||||
updateHeightOfMessageTextView()
|
||||
@@ -137,7 +131,7 @@ class MessageToolbar: UIToolbar {
|
||||
|
||||
var textSendAction: ((messageToolBar: MessageToolbar) -> Void)?
|
||||
|
||||
var toggleMoreMessagesAction: ((messageToolBar: MessageToolbar) -> Void)?
|
||||
var moreMessageTypesAction: (() -> Void)?
|
||||
|
||||
var voiceRecordBeginAction: ((messageToolBar: MessageToolbar) -> Void)?
|
||||
|
||||
@@ -209,7 +203,7 @@ class MessageToolbar: UIToolbar {
|
||||
button.setImage(UIImage(named: "item_more"), forState: .Normal)
|
||||
button.tintColor = UIColor.messageToolBarColor()
|
||||
button.tintAdjustmentMode = .Normal
|
||||
button.addTarget(self, action: "toggleMoreMessages", forControlEvents: UIControlEvents.TouchUpInside)
|
||||
button.addTarget(self, action: "moreMessageTypes", forControlEvents: UIControlEvents.TouchUpInside)
|
||||
return button
|
||||
}()
|
||||
|
||||
@@ -394,14 +388,8 @@ class MessageToolbar: UIToolbar {
|
||||
}
|
||||
}
|
||||
|
||||
func toggleMoreMessages() {
|
||||
|
||||
if state != .MoreMessages {
|
||||
state = .MoreMessages
|
||||
|
||||
} else {
|
||||
state = .Default
|
||||
}
|
||||
func moreMessageTypes() {
|
||||
moreMessageTypesAction?()
|
||||
}
|
||||
|
||||
func tryVoiceRecordBegin() {
|
||||
|
||||
@@ -0,0 +1,345 @@
|
||||
//
|
||||
// MoreMessageTypesView.swift
|
||||
// Yep
|
||||
//
|
||||
// Created by nixzhu on 15/10/16.
|
||||
// Copyright © 2015年 Catch Inc. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import Photos
|
||||
|
||||
class MoreMessageTypesView: UIView {
|
||||
|
||||
let totalHeight: CGFloat = 100 + 60 * 3
|
||||
|
||||
lazy var containerView: UIView = {
|
||||
let view = UIView()
|
||||
view.backgroundColor = UIColor.clearColor()
|
||||
return view
|
||||
}()
|
||||
|
||||
let titleCellID = "TitleCell"
|
||||
let quickPickPhotosCellID = "QuickPickPhotosCell"
|
||||
|
||||
lazy var tableView: UITableView = {
|
||||
let view = UITableView()
|
||||
view.dataSource = self
|
||||
view.delegate = self
|
||||
view.rowHeight = 60
|
||||
view.scrollEnabled = false
|
||||
|
||||
view.registerNib(UINib(nibName: self.quickPickPhotosCellID, bundle: nil), forCellReuseIdentifier: self.quickPickPhotosCellID)
|
||||
view.registerNib(UINib(nibName: self.titleCellID, bundle: nil), forCellReuseIdentifier: self.titleCellID)
|
||||
return view
|
||||
}()
|
||||
|
||||
var alertCanNotAccessCameraRollAction: (() -> Void)?
|
||||
var takePhotoAction: (() -> Void)?
|
||||
var choosePhotoAction: (() -> Void)?
|
||||
var pickLocationAction: (() -> Void)?
|
||||
var sendImageAction: (UIImage -> Void)?
|
||||
|
||||
var quickPickedImageSet = Set<PHAsset>() {
|
||||
didSet {
|
||||
tableView.reloadRowsAtIndexPaths([NSIndexPath(forRow: Row.PickPhotos.rawValue, inSection: 0)], withRowAnimation: .None)
|
||||
}
|
||||
}
|
||||
|
||||
var tableViewBottomConstraint: NSLayoutConstraint?
|
||||
|
||||
func showInView(view: UIView) {
|
||||
|
||||
frame = view.bounds
|
||||
|
||||
view.addSubview(self)
|
||||
|
||||
layoutIfNeeded()
|
||||
|
||||
containerView.alpha = 1
|
||||
|
||||
UIView.animateWithDuration(0.2, delay: 0.0, options: .CurveEaseIn, animations: { _ in
|
||||
self.containerView.backgroundColor = UIColor.blackColor().colorWithAlphaComponent(0.3)
|
||||
|
||||
}, completion: { _ in
|
||||
})
|
||||
|
||||
UIView.animateWithDuration(0.2, delay: 0.1, options: .CurveEaseOut, animations: { _ in
|
||||
self.tableViewBottomConstraint?.constant = 0
|
||||
|
||||
self.layoutIfNeeded()
|
||||
|
||||
}, completion: { _ in
|
||||
})
|
||||
}
|
||||
|
||||
func hide() {
|
||||
|
||||
UIView.animateWithDuration(0.2, delay: 0.0, options: .CurveEaseIn, animations: { _ in
|
||||
self.tableViewBottomConstraint?.constant = self.totalHeight
|
||||
|
||||
self.layoutIfNeeded()
|
||||
|
||||
}, completion: { _ in
|
||||
})
|
||||
|
||||
UIView.animateWithDuration(0.2, delay: 0.1, options: .CurveEaseOut, animations: { _ in
|
||||
self.containerView.backgroundColor = UIColor.clearColor()
|
||||
|
||||
}, completion: { _ in
|
||||
self.removeFromSuperview()
|
||||
})
|
||||
}
|
||||
|
||||
func hideAndDo(afterHideAction: (() -> Void)?) {
|
||||
|
||||
UIView.animateWithDuration(0.2, delay: 0.0, options: .CurveLinear, animations: { _ in
|
||||
self.containerView.alpha = 0
|
||||
|
||||
self.tableViewBottomConstraint?.constant = self.totalHeight
|
||||
|
||||
self.layoutIfNeeded()
|
||||
|
||||
}, completion: { finished in
|
||||
self.removeFromSuperview()
|
||||
})
|
||||
|
||||
delay(0.1) {
|
||||
afterHideAction?()
|
||||
}
|
||||
}
|
||||
|
||||
var isFirstTimeBeenAddAsSubview = true
|
||||
|
||||
override func didMoveToSuperview() {
|
||||
super.didMoveToSuperview()
|
||||
|
||||
if isFirstTimeBeenAddAsSubview {
|
||||
isFirstTimeBeenAddAsSubview = false
|
||||
|
||||
makeUI()
|
||||
|
||||
let tap = UITapGestureRecognizer(target: self, action: "hide")
|
||||
containerView.addGestureRecognizer(tap)
|
||||
|
||||
tap.cancelsTouchesInView = true
|
||||
tap.delegate = self
|
||||
}
|
||||
}
|
||||
|
||||
func makeUI() {
|
||||
|
||||
addSubview(containerView)
|
||||
containerView.translatesAutoresizingMaskIntoConstraints = false
|
||||
|
||||
containerView.addSubview(tableView)
|
||||
tableView.translatesAutoresizingMaskIntoConstraints = false
|
||||
|
||||
let viewsDictionary = [
|
||||
"containerView": containerView,
|
||||
"tableView": tableView,
|
||||
]
|
||||
|
||||
// layout for containerView
|
||||
|
||||
let containerViewConstraintsH = NSLayoutConstraint.constraintsWithVisualFormat("H:|[containerView]|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: viewsDictionary)
|
||||
let containerViewConstraintsV = NSLayoutConstraint.constraintsWithVisualFormat("V:|[containerView]|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: viewsDictionary)
|
||||
|
||||
NSLayoutConstraint.activateConstraints(containerViewConstraintsH)
|
||||
NSLayoutConstraint.activateConstraints(containerViewConstraintsV)
|
||||
|
||||
// layout for tableView
|
||||
|
||||
let tableViewConstraintsH = NSLayoutConstraint.constraintsWithVisualFormat("H:|[tableView]|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: viewsDictionary)
|
||||
|
||||
let tableViewBottomConstraint = NSLayoutConstraint(item: tableView, attribute: .Bottom, relatedBy: .Equal, toItem: containerView, attribute: .Bottom, multiplier: 1.0, constant: self.totalHeight)
|
||||
|
||||
self.tableViewBottomConstraint = tableViewBottomConstraint
|
||||
|
||||
let tableViewHeightConstraint = NSLayoutConstraint(item: tableView, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0, constant: self.totalHeight)
|
||||
|
||||
NSLayoutConstraint.activateConstraints(tableViewConstraintsH)
|
||||
NSLayoutConstraint.activateConstraints([tableViewBottomConstraint, tableViewHeightConstraint])
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - UIGestureRecognizerDelegate
|
||||
|
||||
extension MoreMessageTypesView: UIGestureRecognizerDelegate {
|
||||
|
||||
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
|
||||
|
||||
if touch.view != containerView {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - UITableViewDataSource, UITableViewDelegate
|
||||
|
||||
extension MoreMessageTypesView: UITableViewDataSource, UITableViewDelegate {
|
||||
|
||||
enum Row: Int {
|
||||
|
||||
case PhotoGallery = 0
|
||||
case PickPhotos
|
||||
case Location
|
||||
case Cancel
|
||||
|
||||
var normalTitle: String {
|
||||
switch self {
|
||||
case .PhotoGallery:
|
||||
return ""
|
||||
case .PickPhotos:
|
||||
return NSLocalizedString("Pick Photos", comment: "")
|
||||
case .Location:
|
||||
return NSLocalizedString("Location", comment: "")
|
||||
case .Cancel:
|
||||
return NSLocalizedString("Cancel", comment: "")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
|
||||
return 1
|
||||
}
|
||||
|
||||
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
return 4
|
||||
}
|
||||
|
||||
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
|
||||
|
||||
if let row = Row(rawValue: indexPath.row) {
|
||||
if case .PhotoGallery = row {
|
||||
let cell = tableView.dequeueReusableCellWithIdentifier(quickPickPhotosCellID) as! QuickPickPhotosCell
|
||||
|
||||
cell.alertCanNotAccessCameraRollAction = { [weak self] in
|
||||
self?.alertCanNotAccessCameraRollAction?()
|
||||
}
|
||||
|
||||
cell.takePhotoAction = { [weak self] in
|
||||
self?.hideAndDo {
|
||||
self?.takePhotoAction?()
|
||||
}
|
||||
}
|
||||
|
||||
cell.pickedPhotosAction = { [weak self] pickedImageSet in
|
||||
self?.quickPickedImageSet = pickedImageSet
|
||||
}
|
||||
|
||||
return cell
|
||||
|
||||
} else {
|
||||
let cell = tableView.dequeueReusableCellWithIdentifier(titleCellID) as! TitleCell
|
||||
cell.singleTitleLabel.text = row.normalTitle
|
||||
cell.boldEnabled = false
|
||||
cell.singleTitleLabel.textColor = UIColor.yepTintColor()
|
||||
|
||||
if case .PickPhotos = row {
|
||||
if !quickPickedImageSet.isEmpty {
|
||||
cell.singleTitleLabel.text = String(format: NSLocalizedString("Send Photos (%d)", comment: ""), quickPickedImageSet.count)
|
||||
cell.boldEnabled = true
|
||||
}
|
||||
}
|
||||
|
||||
return cell
|
||||
}
|
||||
}
|
||||
|
||||
return UITableViewCell()
|
||||
}
|
||||
|
||||
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
|
||||
if let row = Row(rawValue: indexPath.row) {
|
||||
if case .PhotoGallery = row {
|
||||
return 100
|
||||
|
||||
} else {
|
||||
return 60
|
||||
}
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
|
||||
|
||||
tableView.deselectRowAtIndexPath(indexPath, animated: true)
|
||||
|
||||
if let row = Row(rawValue: indexPath.row) {
|
||||
switch row {
|
||||
|
||||
case .PickPhotos:
|
||||
if !quickPickedImageSet.isEmpty {
|
||||
|
||||
var images = [UIImage]()
|
||||
|
||||
let options = PHImageRequestOptions()
|
||||
options.synchronous = true
|
||||
|
||||
let imageManager = PHCachingImageManager()
|
||||
for imageAsset in quickPickedImageSet {
|
||||
|
||||
let maxSize: CGFloat = 512
|
||||
|
||||
let pixelWidth = CGFloat(imageAsset.pixelWidth)
|
||||
let pixelHeight = CGFloat(imageAsset.pixelHeight)
|
||||
|
||||
//println("pixelWidth: \(pixelWidth)")
|
||||
//println("pixelHeight: \(pixelHeight)")
|
||||
|
||||
let targetSize: CGSize
|
||||
|
||||
if pixelWidth > pixelHeight {
|
||||
let width = maxSize
|
||||
let height = floor(maxSize * (pixelHeight / pixelWidth))
|
||||
targetSize = CGSize(width: width, height: height)
|
||||
|
||||
} else {
|
||||
let height = maxSize
|
||||
let width = floor(maxSize * (pixelWidth / pixelHeight))
|
||||
targetSize = CGSize(width: width, height: height)
|
||||
}
|
||||
|
||||
//println("targetSize: \(targetSize)")
|
||||
|
||||
imageManager.requestImageForAsset(imageAsset, targetSize: targetSize, contentMode: .AspectFill, options: options) { image, info in
|
||||
if let image = image {
|
||||
println("image.size: \(image.size)")
|
||||
images.append(image)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
images.forEach {
|
||||
sendImageAction?($0)
|
||||
}
|
||||
|
||||
quickPickedImageSet.removeAll()
|
||||
|
||||
hide()
|
||||
|
||||
} else {
|
||||
hideAndDo {
|
||||
choosePhotoAction?()
|
||||
}
|
||||
}
|
||||
|
||||
case .Location:
|
||||
hideAndDo {
|
||||
pickLocationAction?()
|
||||
}
|
||||
|
||||
case .Cancel:
|
||||
hide()
|
||||
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,16 +71,18 @@ class PullToRefreshView: UIView {
|
||||
// MARK: Actions
|
||||
|
||||
func beginRefreshing() {
|
||||
|
||||
isRefreshing = true
|
||||
|
||||
UIView.animateWithDuration(0.3, delay: 0, options: .CurveEaseInOut, animations: { () -> Void in
|
||||
UIView.animateWithDuration(0.25, delay: 0, options: .CurveEaseInOut, animations: { () -> Void in
|
||||
delegate?.scrollView().contentInset.top += sceneHeight
|
||||
}, completion: { (_) -> Void in
|
||||
})
|
||||
}
|
||||
|
||||
func endRefreshingAndDoFurtherAction(furtherAction: () -> Void) {
|
||||
UIView.animateWithDuration(0.3, delay: 0, options: .CurveEaseInOut, animations: { () -> Void in
|
||||
|
||||
UIView.animateWithDuration(0.25, delay: 0, options: .CurveEaseInOut, animations: { () -> Void in
|
||||
delegate?.scrollView().contentInset.top -= sceneHeight
|
||||
|
||||
}, completion: { (_) -> Void in
|
||||
|
||||
Reference in New Issue
Block a user