浏览代码

选中加展示

南鑫林 5 年之前
父节点
当前提交
76b86b0f9a
共有 37 个文件被更改,包括 1665 次插入825 次删除
  1. 62 62
      RainbowPlanet/RainbowPlanet.xcodeproj/project.pbxproj
  2. 318 0
      RainbowPlanet/RainbowPlanet/Modules/PublishModule/PhotoPicker/TLPhotoPicker/CustomCameraCell.swift
  3. 0 0
      RainbowPlanet/RainbowPlanet/Modules/PublishModule/PhotoPicker/TLPhotoPicker/KSVideoPlayerView/KSVideoLayer.h
  4. 0 0
      RainbowPlanet/RainbowPlanet/Modules/PublishModule/PhotoPicker/TLPhotoPicker/KSVideoPlayerView/KSVideoLayer.m
  5. 0 0
      RainbowPlanet/RainbowPlanet/Modules/PublishModule/PhotoPicker/TLPhotoPicker/KSVideoPlayerView/KSVideoPlayerBaseView.h
  6. 0 0
      RainbowPlanet/RainbowPlanet/Modules/PublishModule/PhotoPicker/TLPhotoPicker/KSVideoPlayerView/KSVideoPlayerBaseView.m
  7. 174 0
      RainbowPlanet/RainbowPlanet/Modules/PublishModule/PhotoPicker/TLPhotoPicker/PhotoCaptureDelegate.swift
  8. 77 0
      RainbowPlanet/RainbowPlanet/Modules/PublishModule/PhotoPicker/TLPhotoPicker/PreviewView.swift
  9. 0 0
      RainbowPlanet/RainbowPlanet/Modules/PublishModule/PhotoPicker/TLPhotoPicker/SynchronizedDictionary.swift
  10. 0 0
      RainbowPlanet/RainbowPlanet/Modules/PublishModule/PhotoPicker/TLPhotoPicker/TLAlbumPopView.swift
  11. 0 0
      RainbowPlanet/RainbowPlanet/Modules/PublishModule/PhotoPicker/TLPhotoPicker/TLAssetCollection+Extension.swift
  12. 0 0
      RainbowPlanet/RainbowPlanet/Modules/PublishModule/PhotoPicker/TLPhotoPicker/TLAssetsCollection.swift
  13. 0 0
      RainbowPlanet/RainbowPlanet/Modules/PublishModule/PhotoPicker/TLPhotoPicker/TLBundle.swift
  14. 0 0
      RainbowPlanet/RainbowPlanet/Modules/PublishModule/PhotoPicker/TLPhotoPicker/TLCollectionTableViewCell.swift
  15. 391 0
      RainbowPlanet/RainbowPlanet/Modules/PublishModule/PhotoPicker/TLPhotoPicker/TLPhontoPreviewView.swift
  16. 34 10
      RainbowPlanet/RainbowPlanet/Tools/PhotoPicker/TLPhotoPicker/TLPhotoCollectionViewCell.swift
  17. 1 1
      RainbowPlanet/RainbowPlanet/Tools/PhotoPicker/TLPhotoPicker/TLPhotoLibrary.swift
  18. 55 0
      RainbowPlanet/RainbowPlanet/Modules/PublishModule/PhotoPicker/TLPhotoPicker/TLPhotopickerProtocol.swift
  19. 203 197
      RainbowPlanet/RainbowPlanet/Tools/PhotoPicker/TLPhotoPicker/TLPhotosPickerViewController.swift
  20. 53 0
      RainbowPlanet/RainbowPlanet/Modules/PublishModule/PhotoPicker/TLPhotoPickerResources/CustomCameraCell.xib
  21. 0 0
      RainbowPlanet/RainbowPlanet/Modules/PublishModule/PhotoPicker/TLPhotoPickerResources/TLCollectionTableViewCell.xib
  22. 40 34
      RainbowPlanet/RainbowPlanet/Tools/PhotoPicker/TLPhotoPickerResources/TLPhotoCollectionViewCell.xib
  23. 二进制
      RainbowPlanet/RainbowPlanet/Modules/PublishModule/PhotoPicker/TLPhotoPickerResources/TLPhotoPickerController.bundle/arrow.png
  24. 0 0
      RainbowPlanet/RainbowPlanet/Modules/PublishModule/PhotoPicker/TLPhotoPickerResources/TLPhotoPickerController.bundle/camera@3x.png
  25. 0 0
      RainbowPlanet/RainbowPlanet/Modules/PublishModule/PhotoPicker/TLPhotoPickerResources/TLPhotoPickerController.bundle/insertPhotoMaterial@3x.png
  26. 二进制
      RainbowPlanet/RainbowPlanet/Modules/PublishModule/PhotoPicker/TLPhotoPickerResources/TLPhotoPickerController.bundle/pop_arrow.png
  27. 二进制
      RainbowPlanet/RainbowPlanet/Modules/PublishModule/PhotoPicker/TLPhotoPickerResources/TLPhotoPickerController.bundle/video.png
  28. 68 0
      RainbowPlanet/RainbowPlanet/Modules/PublishModule/PhotoPicker/TLPhotoPickerResources/TLPhotosPickerViewController.xib
  29. 0 124
      RainbowPlanet/RainbowPlanet/Modules/PublishModule/PublishMediaPicker/ViewController/PublishMediaPickerViewController.swift
  30. 158 24
      RainbowPlanet/RainbowPlanet/Modules/PublishModule/PublishViewController.swift
  31. 10 10
      RainbowPlanet/RainbowPlanet/Modules/RegisterLoginModule/RegisterLogin/ViewController/RegisterLoginViewController.swift
  32. 二进制
      RainbowPlanet/RainbowPlanet/Supporting Files/CommunityModule.xcassets/100.imageset/100.png
  33. 21 0
      RainbowPlanet/RainbowPlanet/Supporting Files/CommunityModule.xcassets/100.imageset/Contents.json
  34. 0 39
      RainbowPlanet/RainbowPlanet/Tools/PhotoPicker/TLPhotoPicker/PhotoPickerManager.swift
  35. 0 86
      RainbowPlanet/RainbowPlanet/Tools/PhotoPicker/TLPhotoPicker/TLPhotoPickerManager.swift
  36. 0 17
      RainbowPlanet/RainbowPlanet/Tools/PhotoPicker/TLPhotoPicker/TLPhotopickerDataSourcesProtocol.swift
  37. 0 221
      RainbowPlanet/RainbowPlanet/Tools/PhotoPicker/TLPhotoPickerResources/TLPhotosPickerViewController.xib

+ 62 - 62
RainbowPlanet/RainbowPlanet.xcodeproj/project.pbxproj

@@ -326,23 +326,25 @@
 		A7AA9F6322C62B270086498B /* CommunityRecommnendViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7AA9F6222C62B270086498B /* CommunityRecommnendViewController.swift */; };
 		A7AA9F6522C63DCD0086498B /* CommunityFollowFeedModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7AA9F6422C63DCD0086498B /* CommunityFollowFeedModel.swift */; };
 		A7AA9F6722C640F10086498B /* CommunityRecommendFeedModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7AA9F6622C640F10086498B /* CommunityRecommendFeedModel.swift */; };
-		A7AD2744230F88250099B3E0 /* PublishMediaPickerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7AD2743230F88250099B3E0 /* PublishMediaPickerViewController.swift */; };
 		A7AD2756230F8D7D0099B3E0 /* TLCollectionTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = A7AD2747230F8D7C0099B3E0 /* TLCollectionTableViewCell.xib */; };
 		A7AD2757230F8D7D0099B3E0 /* TLPhotoPickerController.bundle in Resources */ = {isa = PBXBuildFile; fileRef = A7AD2748230F8D7C0099B3E0 /* TLPhotoPickerController.bundle */; };
 		A7AD2758230F8D7D0099B3E0 /* TLPhotoCollectionViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = A7AD2749230F8D7C0099B3E0 /* TLPhotoCollectionViewCell.xib */; };
 		A7AD2759230F8D7D0099B3E0 /* TLPhotosPickerViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = A7AD274A230F8D7C0099B3E0 /* TLPhotosPickerViewController.xib */; };
-		A7AD275A230F8D7D0099B3E0 /* TLPhotoLibrary.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7AD274C230F8D7C0099B3E0 /* TLPhotoLibrary.swift */; };
-		A7AD275B230F8D7D0099B3E0 /* TLPhotopickerDataSourcesProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7AD274D230F8D7C0099B3E0 /* TLPhotopickerDataSourcesProtocol.swift */; };
-		A7AD275C230F8D7D0099B3E0 /* TLCollectionTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7AD274E230F8D7C0099B3E0 /* TLCollectionTableViewCell.swift */; };
-		A7AD275D230F8D7D0099B3E0 /* TLBundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7AD274F230F8D7C0099B3E0 /* TLBundle.swift */; };
-		A7AD275E230F8D7D0099B3E0 /* TLAlbumPopView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7AD2750230F8D7C0099B3E0 /* TLAlbumPopView.swift */; };
-		A7AD275F230F8D7D0099B3E0 /* TLPhotoCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7AD2751230F8D7C0099B3E0 /* TLPhotoCollectionViewCell.swift */; };
-		A7AD2760230F8D7D0099B3E0 /* SynchronizedDictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7AD2752230F8D7C0099B3E0 /* SynchronizedDictionary.swift */; };
-		A7AD2761230F8D7D0099B3E0 /* TLAssetCollection+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7AD2753230F8D7C0099B3E0 /* TLAssetCollection+Extension.swift */; };
-		A7AD2762230F8D7D0099B3E0 /* TLPhotosPickerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7AD2754230F8D7C0099B3E0 /* TLPhotosPickerViewController.swift */; };
-		A7AD2763230F8D7D0099B3E0 /* TLAssetsCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7AD2755230F8D7C0099B3E0 /* TLAssetsCollection.swift */; };
-		A7AD2765230F9A470099B3E0 /* TLPhotoPickerManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7AD2764230F9A470099B3E0 /* TLPhotoPickerManager.swift */; };
-		A7AD2768230F9C460099B3E0 /* PhotoPickerManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7AD2767230F9C460099B3E0 /* PhotoPickerManager.swift */; };
+		A7AD277F2310D1E40099B3E0 /* TLPhotoLibrary.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7AD27752310D1E20099B3E0 /* TLPhotoLibrary.swift */; };
+		A7AD27802310D1E40099B3E0 /* TLPhotosPickerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7AD27762310D1E20099B3E0 /* TLPhotosPickerViewController.swift */; };
+		A7AD27812310D1E40099B3E0 /* TLPhotopickerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7AD27772310D1E30099B3E0 /* TLPhotopickerProtocol.swift */; };
+		A7AD27822310D1E40099B3E0 /* TLCollectionTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7AD27782310D1E30099B3E0 /* TLCollectionTableViewCell.swift */; };
+		A7AD27832310D1E40099B3E0 /* SynchronizedDictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7AD27792310D1E30099B3E0 /* SynchronizedDictionary.swift */; };
+		A7AD27842310D1E40099B3E0 /* TLPhotoCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7AD277A2310D1E30099B3E0 /* TLPhotoCollectionViewCell.swift */; };
+		A7AD27852310D1E40099B3E0 /* TLBundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7AD277B2310D1E30099B3E0 /* TLBundle.swift */; };
+		A7AD27862310D1E40099B3E0 /* TLAssetsCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7AD277C2310D1E40099B3E0 /* TLAssetsCollection.swift */; };
+		A7AD27872310D1E40099B3E0 /* TLAlbumPopView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7AD277D2310D1E40099B3E0 /* TLAlbumPopView.swift */; };
+		A7AD27882310D1E40099B3E0 /* TLAssetCollection+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7AD277E2310D1E40099B3E0 /* TLAssetCollection+Extension.swift */; };
+		A7AD278A2310D44B0099B3E0 /* CustomCameraCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7AD27892310D44B0099B3E0 /* CustomCameraCell.swift */; };
+		A7AD278C2310D4560099B3E0 /* CustomCameraCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = A7AD278B2310D4560099B3E0 /* CustomCameraCell.xib */; };
+		A7AD278F2310D51F0099B3E0 /* PhotoCaptureDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7AD278D2310D51F0099B3E0 /* PhotoCaptureDelegate.swift */; };
+		A7AD27902310D51F0099B3E0 /* PreviewView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7AD278E2310D51F0099B3E0 /* PreviewView.swift */; };
+		A7AD27922312B7050099B3E0 /* TLPhontoPreviewView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7AD27912312B7050099B3E0 /* TLPhontoPreviewView.swift */; };
 		A7B4E71F228131720012914A /* ProductSlidingLeftRightCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7B4E71E228131720012914A /* ProductSlidingLeftRightCollectionViewCell.swift */; };
 		A7B4E721228151F40012914A /* ProductFloorTitleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7B4E720228151F40012914A /* ProductFloorTitleView.swift */; };
 		A7B4E723228154750012914A /* ProductFloorBannerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7B4E722228154750012914A /* ProductFloorBannerView.swift */; };
@@ -1075,23 +1077,25 @@
 		A7AA9F6222C62B270086498B /* CommunityRecommnendViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommunityRecommnendViewController.swift; sourceTree = "<group>"; };
 		A7AA9F6422C63DCD0086498B /* CommunityFollowFeedModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CommunityFollowFeedModel.swift; sourceTree = "<group>"; };
 		A7AA9F6622C640F10086498B /* CommunityRecommendFeedModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CommunityRecommendFeedModel.swift; sourceTree = "<group>"; };
-		A7AD2743230F88250099B3E0 /* PublishMediaPickerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PublishMediaPickerViewController.swift; sourceTree = "<group>"; };
 		A7AD2747230F8D7C0099B3E0 /* TLCollectionTableViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = TLCollectionTableViewCell.xib; sourceTree = "<group>"; };
 		A7AD2748230F8D7C0099B3E0 /* TLPhotoPickerController.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = TLPhotoPickerController.bundle; sourceTree = "<group>"; };
 		A7AD2749230F8D7C0099B3E0 /* TLPhotoCollectionViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = TLPhotoCollectionViewCell.xib; sourceTree = "<group>"; };
 		A7AD274A230F8D7C0099B3E0 /* TLPhotosPickerViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = TLPhotosPickerViewController.xib; sourceTree = "<group>"; };
-		A7AD274C230F8D7C0099B3E0 /* TLPhotoLibrary.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TLPhotoLibrary.swift; sourceTree = "<group>"; };
-		A7AD274D230F8D7C0099B3E0 /* TLPhotopickerDataSourcesProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TLPhotopickerDataSourcesProtocol.swift; sourceTree = "<group>"; };
-		A7AD274E230F8D7C0099B3E0 /* TLCollectionTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TLCollectionTableViewCell.swift; sourceTree = "<group>"; };
-		A7AD274F230F8D7C0099B3E0 /* TLBundle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TLBundle.swift; sourceTree = "<group>"; };
-		A7AD2750230F8D7C0099B3E0 /* TLAlbumPopView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TLAlbumPopView.swift; sourceTree = "<group>"; };
-		A7AD2751230F8D7C0099B3E0 /* TLPhotoCollectionViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TLPhotoCollectionViewCell.swift; sourceTree = "<group>"; };
-		A7AD2752230F8D7C0099B3E0 /* SynchronizedDictionary.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SynchronizedDictionary.swift; sourceTree = "<group>"; };
-		A7AD2753230F8D7C0099B3E0 /* TLAssetCollection+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "TLAssetCollection+Extension.swift"; sourceTree = "<group>"; };
-		A7AD2754230F8D7C0099B3E0 /* TLPhotosPickerViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TLPhotosPickerViewController.swift; sourceTree = "<group>"; };
-		A7AD2755230F8D7C0099B3E0 /* TLAssetsCollection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TLAssetsCollection.swift; sourceTree = "<group>"; };
-		A7AD2764230F9A470099B3E0 /* TLPhotoPickerManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TLPhotoPickerManager.swift; sourceTree = "<group>"; };
-		A7AD2767230F9C460099B3E0 /* PhotoPickerManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoPickerManager.swift; sourceTree = "<group>"; };
+		A7AD27752310D1E20099B3E0 /* TLPhotoLibrary.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TLPhotoLibrary.swift; sourceTree = "<group>"; };
+		A7AD27762310D1E20099B3E0 /* TLPhotosPickerViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TLPhotosPickerViewController.swift; sourceTree = "<group>"; };
+		A7AD27772310D1E30099B3E0 /* TLPhotopickerProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TLPhotopickerProtocol.swift; sourceTree = "<group>"; };
+		A7AD27782310D1E30099B3E0 /* TLCollectionTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TLCollectionTableViewCell.swift; sourceTree = "<group>"; };
+		A7AD27792310D1E30099B3E0 /* SynchronizedDictionary.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SynchronizedDictionary.swift; sourceTree = "<group>"; };
+		A7AD277A2310D1E30099B3E0 /* TLPhotoCollectionViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TLPhotoCollectionViewCell.swift; sourceTree = "<group>"; };
+		A7AD277B2310D1E30099B3E0 /* TLBundle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TLBundle.swift; sourceTree = "<group>"; };
+		A7AD277C2310D1E40099B3E0 /* TLAssetsCollection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TLAssetsCollection.swift; sourceTree = "<group>"; };
+		A7AD277D2310D1E40099B3E0 /* TLAlbumPopView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TLAlbumPopView.swift; sourceTree = "<group>"; };
+		A7AD277E2310D1E40099B3E0 /* TLAssetCollection+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "TLAssetCollection+Extension.swift"; sourceTree = "<group>"; };
+		A7AD27892310D44B0099B3E0 /* CustomCameraCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomCameraCell.swift; sourceTree = "<group>"; };
+		A7AD278B2310D4560099B3E0 /* CustomCameraCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = CustomCameraCell.xib; sourceTree = "<group>"; };
+		A7AD278D2310D51F0099B3E0 /* PhotoCaptureDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PhotoCaptureDelegate.swift; sourceTree = "<group>"; };
+		A7AD278E2310D51F0099B3E0 /* PreviewView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PreviewView.swift; sourceTree = "<group>"; };
+		A7AD27912312B7050099B3E0 /* TLPhontoPreviewView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TLPhontoPreviewView.swift; sourceTree = "<group>"; };
 		A7B4E71E228131720012914A /* ProductSlidingLeftRightCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductSlidingLeftRightCollectionViewCell.swift; sourceTree = "<group>"; };
 		A7B4E720228151F40012914A /* ProductFloorTitleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductFloorTitleView.swift; sourceTree = "<group>"; };
 		A7B4E722228154750012914A /* ProductFloorBannerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductFloorBannerView.swift; sourceTree = "<group>"; };
@@ -3414,7 +3418,6 @@
 		A77F2CBC2232022A001BD3F6 /* Tools */ = {
 			isa = PBXGroup;
 			children = (
-				A7AD2745230F8D7C0099B3E0 /* PhotoPicker */,
 				A7EE6E1323055A6000628D39 /* MemoryManager */,
 				A7EF3E112303EB6C001E4D26 /* GuidePageView */,
 				A76068F122E4B0ED008DF18F /* UImage+Gif */,
@@ -3779,14 +3782,6 @@
 			path = Router;
 			sourceTree = "<group>";
 		};
-		A7AD273D230F87E50099B3E0 /* ViewController */ = {
-			isa = PBXGroup;
-			children = (
-				A7AD2743230F88250099B3E0 /* PublishMediaPickerViewController.swift */,
-			);
-			path = ViewController;
-			sourceTree = "<group>";
-		};
 		A7AD2745230F8D7C0099B3E0 /* PhotoPicker */ = {
 			isa = PBXGroup;
 			children = (
@@ -3802,6 +3797,7 @@
 				A7AD2747230F8D7C0099B3E0 /* TLCollectionTableViewCell.xib */,
 				A7AD2748230F8D7C0099B3E0 /* TLPhotoPickerController.bundle */,
 				A7AD2749230F8D7C0099B3E0 /* TLPhotoCollectionViewCell.xib */,
+				A7AD278B2310D4560099B3E0 /* CustomCameraCell.xib */,
 				A7AD274A230F8D7C0099B3E0 /* TLPhotosPickerViewController.xib */,
 			);
 			path = TLPhotoPickerResources;
@@ -3810,18 +3806,21 @@
 		A7AD274B230F8D7C0099B3E0 /* TLPhotoPicker */ = {
 			isa = PBXGroup;
 			children = (
-				A7AD274C230F8D7C0099B3E0 /* TLPhotoLibrary.swift */,
-				A7AD274D230F8D7C0099B3E0 /* TLPhotopickerDataSourcesProtocol.swift */,
-				A7AD274E230F8D7C0099B3E0 /* TLCollectionTableViewCell.swift */,
-				A7AD274F230F8D7C0099B3E0 /* TLBundle.swift */,
-				A7AD2750230F8D7C0099B3E0 /* TLAlbumPopView.swift */,
-				A7AD2751230F8D7C0099B3E0 /* TLPhotoCollectionViewCell.swift */,
-				A7AD2752230F8D7C0099B3E0 /* SynchronizedDictionary.swift */,
-				A7AD2753230F8D7C0099B3E0 /* TLAssetCollection+Extension.swift */,
-				A7AD2754230F8D7C0099B3E0 /* TLPhotosPickerViewController.swift */,
-				A7AD2755230F8D7C0099B3E0 /* TLAssetsCollection.swift */,
-				A7AD2764230F9A470099B3E0 /* TLPhotoPickerManager.swift */,
-				A7AD2767230F9C460099B3E0 /* PhotoPickerManager.swift */,
+				A7AD27762310D1E20099B3E0 /* TLPhotosPickerViewController.swift */,
+				A7AD277A2310D1E30099B3E0 /* TLPhotoCollectionViewCell.swift */,
+				A7AD27912312B7050099B3E0 /* TLPhontoPreviewView.swift */,
+				A7AD27792310D1E30099B3E0 /* SynchronizedDictionary.swift */,
+				A7AD277D2310D1E40099B3E0 /* TLAlbumPopView.swift */,
+				A7AD277E2310D1E40099B3E0 /* TLAssetCollection+Extension.swift */,
+				A7AD277C2310D1E40099B3E0 /* TLAssetsCollection.swift */,
+				A7AD277B2310D1E30099B3E0 /* TLBundle.swift */,
+				A7AD27782310D1E30099B3E0 /* TLCollectionTableViewCell.swift */,
+				A7AD27752310D1E20099B3E0 /* TLPhotoLibrary.swift */,
+				A7AD27772310D1E30099B3E0 /* TLPhotopickerProtocol.swift */,
+				A7AD278D2310D51F0099B3E0 /* PhotoCaptureDelegate.swift */,
+				A7AD278E2310D51F0099B3E0 /* PreviewView.swift */,
+				A7AD27892310D44B0099B3E0 /* CustomCameraCell.swift */,
+				BD12B6A422B502C200AEB10B /* KSVideoPlayerView */,
 			);
 			path = TLPhotoPicker;
 			sourceTree = "<group>";
@@ -5076,6 +5075,7 @@
 		BD12B67122B4E96100AEB10B /* PublishModule */ = {
 			isa = PBXGroup;
 			children = (
+				A7AD2745230F8D7C0099B3E0 /* PhotoPicker */,
 				BD929CCD22B904A30098C139 /* PublishViewController.swift */,
 				BDE376C922C1B5350055E2EA /* AliyunVideo */,
 				BD12B67222B4E99800AEB10B /* PublishMediaPicker */,
@@ -5092,7 +5092,6 @@
 		BD12B67222B4E99800AEB10B /* PublishMediaPicker */ = {
 			isa = PBXGroup;
 			children = (
-				A7AD273D230F87E50099B3E0 /* ViewController */,
 				BD12B68722B4F28F00AEB10B /* KSExtension.swift */,
 				BD12B67522B4ECE200AEB10B /* Controller */,
 				BD12B67622B4ED8800AEB10B /* Model */,
@@ -5122,7 +5121,6 @@
 		BD12B67922B4EE1A00AEB10B /* View */ = {
 			isa = PBXGroup;
 			children = (
-				BD12B6A422B502C200AEB10B /* KSVideoPlayerView */,
 				BD12B68222B4EFF000AEB10B /* KSMediaPickerView.swift */,
 				BD12B69D22B4FAF000AEB10B /* KSMediaPickerNavigationView.swift */,
 				BD12B69222B4F68400AEB10B /* KSMediaPickerCollectionView.h */,
@@ -6055,6 +6053,7 @@
 				A7EF3E102303DAEE001E4D26 /* Launch Screen.storyboard in Resources */,
 				BDD54A2522C31D5F005BBE19 /* music.json in Resources */,
 				A76068E922E4922F008DF18F /* Skittles.json in Resources */,
+				A7AD278C2310D4560099B3E0 /* CustomCameraCell.xib in Resources */,
 				A71AF0BE226F1792001730FE /* ShoppingMallModule.xcassets in Resources */,
 				A7778C9722438F5D00C7C47A /* AlipaySDK.bundle in Resources */,
 				BDD54A2722C31D60005BBE19 /* tail.png in Resources */,
@@ -6172,7 +6171,6 @@
 				A72A72BA22321DE000B21995 /* Extension+String.swift in Sources */,
 				BDAF83B222B3B67D0004BCC3 /* RecommendCommentFooter.swift in Sources */,
 				A7EE6E102305487700628D39 /* ThumbnailsManager.swift in Sources */,
-				A7AD2744230F88250099B3E0 /* PublishMediaPickerViewController.swift in Sources */,
 				A70B8430228FF6D400882BC5 /* ProductCartCountModel.swift in Sources */,
 				A770E5ED22D4298100CBD0A4 /* CommentReplyView.swift in Sources */,
 				A77F2CA02231FE45001BD3F6 /* BaseWebViewController.swift in Sources */,
@@ -6213,7 +6211,7 @@
 				BD13B6DB22BA03BC008BB323 /* PublishAddressPOIView.swift in Sources */,
 				A72A72BE22321DE000B21995 /* Extension+RxTimer.swift in Sources */,
 				BD61225F22C3561C00D3F513 /* AliyunMagicCameraView.m in Sources */,
-				A7AD2760230F8D7D0099B3E0 /* SynchronizedDictionary.swift in Sources */,
+				A7AD27832310D1E40099B3E0 /* SynchronizedDictionary.swift in Sources */,
 				A770E61422D6625700CBD0A4 /* ShareCommunityView.swift in Sources */,
 				A7F2D6CB22B0E4270093000B /* CommunityRecommendFollowCollectionViewCell.swift in Sources */,
 				BDF47D7E22827C3F00941AB9 /* ProductSlidingTopBottomCollectionViewCell.swift in Sources */,
@@ -6277,13 +6275,13 @@
 				A7636AC52268139C00374F9E /* LocationViewController.swift in Sources */,
 				A73A56DB22DC9AB5004920FE /* UpdateVersionModel.swift in Sources */,
 				A7D46090227617D200A5A54E /* SQLModel.swift in Sources */,
-				A7AD275A230F8D7D0099B3E0 /* TLPhotoLibrary.swift in Sources */,
 				A790706522B9DFAD008CE279 /* TextLimitTool.m in Sources */,
 				A72C01222275404A0065E0C3 /* ProvinceCityAreaModel.swift in Sources */,
 				A7FF1579228C82CE00A85748 /* OrderDetailViewController.swift in Sources */,
 				A7FF159C228D9E3D00A85748 /* OrderRefundDetailModel.swift in Sources */,
 				A76B786922CE04940047EC1B /* CommunityRecommendDetailHTMLTableViewCell.swift in Sources */,
 				A7C3DD1C226422D200FA262E /* SwiftMoyaNetWorkServiceSMS.swift in Sources */,
+				A7AD27802310D1E40099B3E0 /* TLPhotosPickerViewController.swift in Sources */,
 				BDF862A2228E41CC000DEF84 /* OrderLogisticsInfoCell.swift in Sources */,
 				A72623D322C1FFD100AEF875 /* CommunityPostMyModel.swift in Sources */,
 				A770E5F522D5BC2000CBD0A4 /* ShareCommonStr.swift in Sources */,
@@ -6320,7 +6318,6 @@
 				A7F2D6DD22B2536F0093000B /* CardContentPicVideoCollectionViewCell.swift in Sources */,
 				A72623D922C2F8B100AEF875 /* MessageHomeOneCollectionViewCell.swift in Sources */,
 				A75B782822DEC708007B986A /* SepcialTwoTypeLayout.swift in Sources */,
-				A7AD275C230F8D7D0099B3E0 /* TLCollectionTableViewCell.swift in Sources */,
 				BD7AB83622841A8B0030646A /* ShoppingCartPayOrderItemCell.swift in Sources */,
 				A71AA519227219D7008FF1A5 /* EditExpressAddressViewController.swift in Sources */,
 				A7FF1568228C6E2300A85748 /* OrderDeliveryModeAndTimeTableViewCell.swift in Sources */,
@@ -6329,7 +6326,6 @@
 				A71738A822897E96000AEA6A /* SwiftMoyaNetWorkServiceShop.swift in Sources */,
 				BD20F1CD2283C51300677D8E /* OrderFinishPayController.swift in Sources */,
 				A729B5B022671310004AE098 /* MobileLoginView.swift in Sources */,
-				A7AD2768230F9C460099B3E0 /* PhotoPickerManager.swift in Sources */,
 				A71AA50C2272126A008FF1A5 /* EditAddressFooterView.swift in Sources */,
 				A70B2C35228815F700B2449F /* ProductDetailProductSkuLabelCollectionViewCell.swift in Sources */,
 				A70B2C60228870CE00B2449F /* ShopSectionHeaderView.swift in Sources */,
@@ -6347,7 +6343,6 @@
 				A7B4E721228151F40012914A /* ProductFloorTitleView.swift in Sources */,
 				A729B5AD2266FF45004AE098 /* BindPhoneNumberView.swift in Sources */,
 				A75C474E22938B3900139C0C /* OrderFreightTableViewCell.swift in Sources */,
-				A7AD2761230F8D7D0099B3E0 /* TLAssetCollection+Extension.swift in Sources */,
 				A7FF1592228C918100A85748 /* OrderRefunddetailsStatusTableViewCell.swift in Sources */,
 				BD12B67822B4ED9200AEB10B /* KSMediaPickerOutputModel.swift in Sources */,
 				A7CC74E62270628B003C4F38 /* DeliveryMethodTypeModel.swift in Sources */,
@@ -6356,6 +6351,7 @@
 				A71CAB3722C9A40A00D908A8 /* TotalBeanModel.swift in Sources */,
 				A743229B22B8C1510017C367 /* AppStoreManager.swift in Sources */,
 				A7EE6E1223055A5A00628D39 /* MemoryManager.swift in Sources */,
+				A7AD27842310D1E40099B3E0 /* TLPhotoCollectionViewCell.swift in Sources */,
 				BD61225422C355C800D3F513 /* AliyunMagicCameraViewController.m in Sources */,
 				BDAF83A222B330540004BCC3 /* RecommendSimilarCell.swift in Sources */,
 				BDAA40FD228E9CD600CF841D /* OrderApplyRefundPhoneCell.swift in Sources */,
@@ -6377,7 +6373,6 @@
 				BD13B6DF22BA03BC008BB323 /* PublishTopicHeaderView.swift in Sources */,
 				A7778CB82244E97A00C7C47A /* BindPhoneNumberViewController.swift in Sources */,
 				A754150F224CACF9002480B5 /* SwiftSign.swift in Sources */,
-				A7AD275F230F8D7D0099B3E0 /* TLPhotoCollectionViewCell.swift in Sources */,
 				A71AF0BA226F00F8001730FE /* SearchResultView.swift in Sources */,
 				A77F2CB52232010F001BD3F6 /* ShoppingMallViewController.swift in Sources */,
 				A7D77DEB22DDC5900048D5F6 /* RedemptionAreaFSPagerViewCell.swift in Sources */,
@@ -6389,6 +6384,7 @@
 				A7DC467F22783A47001F3EFC /* EditExpressAddressTableViewCell.swift in Sources */,
 				A7A98E4522804C63005306E9 /* ShoppingMallSepcialCollectionViewCell.swift in Sources */,
 				A7AA9F6722C640F10086498B /* CommunityRecommendFeedModel.swift in Sources */,
+				A7AD27902310D51F0099B3E0 /* PreviewView.swift in Sources */,
 				A7824B082271F53A00ABA381 /* EditSetDefaultTableViewCell.swift in Sources */,
 				A77F2CC3223203BA001BD3F6 /* AppDelegate+Window.swift in Sources */,
 				A7824B062271F25400ABA381 /* EditAddressTableViewCell.swift in Sources */,
@@ -6410,15 +6406,14 @@
 				A7A98E0B227EBD04005306E9 /* CategorySearchView.swift in Sources */,
 				A72A73142232475E00B21995 /* AlipayManager.swift in Sources */,
 				A7824B042271F10300ABA381 /* EditSelfMentionContactsView.swift in Sources */,
-				A7AD275D230F8D7D0099B3E0 /* TLBundle.swift in Sources */,
 				A7274C5B228EE636000E3A07 /* LBXScanViewController.swift in Sources */,
 				BD0FAA5322C4750A00DDFB37 /* AliyunCoverPickView.m in Sources */,
 				A7FF1566228C6DF200A85748 /* OrderShopAndStatusTableViewCell.swift in Sources */,
 				A7A98E332280272A005306E9 /* ShoppingMallBannerTableViewCell.swift in Sources */,
 				A790706122B9C294008CE279 /* ModifyDataNickNameSignView.swift in Sources */,
-				A7AD2763230F8D7D0099B3E0 /* TLAssetsCollection.swift in Sources */,
 				BD12204622AF997E0051C7C2 /* MessageListTableCell.swift in Sources */,
 				BDF862AA228E43A4000DEF84 /* OrderCommentTableViewCell.swift in Sources */,
+				A7AD27862310D1E40099B3E0 /* TLAssetsCollection.swift in Sources */,
 				A7B4E754228278320012914A /* ShoppingMallFloorTableViewCell.swift in Sources */,
 				A74322AB22B900F00017C367 /* CommunityFindFriendsView.swift in Sources */,
 				BD3474F522857B85000908C5 /* CommonPayHeader.swift in Sources */,
@@ -6500,6 +6495,7 @@
 				A770E61522D6625700CBD0A4 /* ShareView.swift in Sources */,
 				A7F2D6D722B1ED370093000B /* CardContentUserTableViewCell.swift in Sources */,
 				A7CC751A22716254003C4F38 /* SetTableViewCell.swift in Sources */,
+				A7AD27812310D1E40099B3E0 /* TLPhotopickerProtocol.swift in Sources */,
 				BD20F1D32283D0ED00677D8E /* OrderFinishPaySuccessCell.swift in Sources */,
 				A7E19FAC22BA2D01009BCCE1 /* SearchTopicListViewController.swift in Sources */,
 				A71AA52822732173008FF1A5 /* SwiftMoyaNetWorkServiceConfig.swift in Sources */,
@@ -6507,6 +6503,7 @@
 				A70B2C4322883B4E00B2449F /* ProductDetailShopTableViewCell.swift in Sources */,
 				A70B2C102286A3BC00B2449F /* ProductDetailModel.swift in Sources */,
 				A7A17E5F22A0CEF200B7A77E /* SwiftMoyaNetWorkManagerTools.swift in Sources */,
+				A7AD278F2310D51F0099B3E0 /* PhotoCaptureDelegate.swift in Sources */,
 				A72A72A922321DE000B21995 /* NumberKeyboard.swift in Sources */,
 				BD108C9422A60C2100837DAB /* HGImageCollectionViewController.swift in Sources */,
 				A70B2C272286C5D600B2449F /* ProductDetailFSPagerViewCell.swift in Sources */,
@@ -6556,6 +6553,7 @@
 				A7A98E09227EB8DD005306E9 /* CategoryView.swift in Sources */,
 				A75B782A22DEC8B3007B986A /* RedemptionAreaSpecialTwoTableViewCell.swift in Sources */,
 				BD0F61F822CAFC8B004650FB /* CommunityVideoAuthModel.swift in Sources */,
+				A7AD278A2310D44B0099B3E0 /* CustomCameraCell.swift in Sources */,
 				A7D07CC122B73F0200186014 /* OtherPersonalCenterViewController.swift in Sources */,
 				A7CC75362271AC14003C4F38 /* AddressManagerView.swift in Sources */,
 				A7146349228EFCE20066099B /* ORSKUDataFilter.m in Sources */,
@@ -6571,12 +6569,12 @@
 				A7BB685922696B9200AB07A2 /* SelfRecommendationCollectionViewCell.swift in Sources */,
 				BD61231522C3749800D3F513 /* AliyunPathManager.m in Sources */,
 				BD12B69A22B4FA8400AEB10B /* KSMediaPickerSelectIndicator.swift in Sources */,
-				A7AD2762230F8D7D0099B3E0 /* TLPhotosPickerViewController.swift in Sources */,
 				A7636AC822682BAF00374F9E /* LocationView.swift in Sources */,
 				BD61227C22C35C7F00D3F513 /* AliyunMediaConfig.m in Sources */,
 				A738D205225AF90D00EEE860 /* WeChatpayOrderModel.swift in Sources */,
 				A7F2D6BD22B09F930093000B /* CommunityNavigationBarView.swift in Sources */,
 				A7274C5C228EE636000E3A07 /* LBXScanLineAnimation.swift in Sources */,
+				A7AD277F2310D1E40099B3E0 /* TLPhotoLibrary.swift in Sources */,
 				A739121A229F75F50033177E /* JXPagingMainTableView.swift in Sources */,
 				A7C2566F22CB7A0C00420828 /* CommunityPostDetailModel.swift in Sources */,
 				A7CC7524227190FB003C4F38 /* AccountSecurityView.swift in Sources */,
@@ -6608,6 +6606,7 @@
 				A76068F322E4B11B008DF18F /* UIImage+Gif.swift in Sources */,
 				A775CBFE2237493600EBDCF8 /* ShoppingMallNavigationBarView.swift in Sources */,
 				A71AA5212272E527008FF1A5 /* Extension+UINavigationController.swift in Sources */,
+				A7AD27822310D1E40099B3E0 /* TLCollectionTableViewCell.swift in Sources */,
 				BD981A8F22C9FEEF0043D951 /* CommunityPublishModel.swift in Sources */,
 				A7D5F22D22BB689700F8E9AF /* WKWebViewEnum.swift in Sources */,
 				A7D07CD222B784B800186014 /* UserPersonalCenterHeaderView.swift in Sources */,
@@ -6676,7 +6675,6 @@
 				A7274C5D228EE636000E3A07 /* LBXScanViewStyle.swift in Sources */,
 				A73911B3229ECE340033177E /* UICollectionViewLeftAlignedLayout.m in Sources */,
 				A7A98E1B227EEE49005306E9 /* SpecialView.swift in Sources */,
-				A7AD275B230F8D7D0099B3E0 /* TLPhotopickerDataSourcesProtocol.swift in Sources */,
 				BDF47D7A228271F600941AB9 /* ShoppingCartView.swift in Sources */,
 				A7824AFB2271EA2600ABA381 /* SelfMentionContactsListView.swift in Sources */,
 				A72A72AB22321DE000B21995 /* SwiftProgressHUD.swift in Sources */,
@@ -6699,13 +6697,13 @@
 				A70B2C3E228825B100B2449F /* ProductDetailEvaluationTableViewCell.swift in Sources */,
 				A7DAB33322D881F5005B964E /* H5RouterModuleType.swift in Sources */,
 				A7EF3E132303EB7C001E4D26 /* GuidePageView.swift in Sources */,
+				A7AD27852310D1E40099B3E0 /* TLBundle.swift in Sources */,
 				A79057022276C9770037F823 /* SetPasswordModel.swift in Sources */,
 				BD12B68022B4EF2600AEB10B /* KSMediaPickerViewImageCell.swift in Sources */,
 				A7274C5A228EE636000E3A07 /* LBXScanView.swift in Sources */,
 				A7FF1560228C693D00A85748 /* OrderViewController.swift in Sources */,
 				A729B5B42267254B004AE098 /* PasswordLoginViewController.swift in Sources */,
 				A7B4E7582282897B0012914A /* ProductFloorLeftHeaderCollectionReusableView.swift in Sources */,
-				A7AD2765230F9A470099B3E0 /* TLPhotoPickerManager.swift in Sources */,
 				A7D4608E227616F800A5A54E /* SQLiteManager.swift in Sources */,
 				A78A5F7822FAC7F000DD1764 /* SetGenderModel.swift in Sources */,
 				A70B2C6B2288815300B2449F /* PickHeaderView.swift in Sources */,
@@ -6740,9 +6738,11 @@
 				A71AF0A6226EDDC8001730FE /* SearchViewController.swift in Sources */,
 				BD20F1CF2283CE2300677D8E /* OrderFinishPayView.swift in Sources */,
 				BD13B6DC22BA03BC008BB323 /* SearchAddrNavigationbarView.swift in Sources */,
+				A7AD27922312B7050099B3E0 /* TLPhontoPreviewView.swift in Sources */,
 				A757849D22C1CBF400D4DB61 /* SwiftMoyaNetWorkH5Manager.swift in Sources */,
 				A7C2567E22CD90D700420828 /* CommunityPostReplysModel.swift in Sources */,
 				A7A98E4322804851005306E9 /* ShoppingMallSepcialFlowLayout.swift in Sources */,
+				A7AD27872310D1E40099B3E0 /* TLAlbumPopView.swift in Sources */,
 				BDE376E622C22D2B0055E2EA /* AlivcDefine.m in Sources */,
 				BD12B69422B4F68400AEB10B /* KSMediaPickerCollectionView.m in Sources */,
 				BD12204122AF8E320051C7C2 /* MessagePlanetNotiTableCell.swift in Sources */,
@@ -6754,6 +6754,7 @@
 				A757849F22C1CEA900D4DB61 /* FollowStatusModel.swift in Sources */,
 				A7CC751F227190C5003C4F38 /* AccountSecurityViewController.swift in Sources */,
 				BD13B6C422BA034D008BB323 /* PublishEditDefaultCollectionCell.swift in Sources */,
+				A7AD27882310D1E40099B3E0 /* TLAssetCollection+Extension.swift in Sources */,
 				A770E5E022CF19FA00CBD0A4 /* CommunityRouterModuleType.swift in Sources */,
 				BD29A92E228F99780018CFC3 /* OrderCommentParameterModel.swift in Sources */,
 				A7284440224DFACD00F82F30 /* InfoModel.swift in Sources */,
@@ -6767,7 +6768,6 @@
 				A7D5F22922BB686200F8E9AF /* BaseJSWebBaseViewController.swift in Sources */,
 				BD20F1CB2283C12000677D8E /* ShoppingCartListNoneItemCell.swift in Sources */,
 				A7B4E756228281620012914A /* ShoppingMallSlidingLeftRightBgCollectionViewCell.swift in Sources */,
-				A7AD275E230F8D7D0099B3E0 /* TLAlbumPopView.swift in Sources */,
 				BD1FC18122B08D7A00D55081 /* CommunityMyFollowTopicCell.swift in Sources */,
 				A7C0FDE722B4A38500BC1E86 /* CardContentCommentListTableViewCell.swift in Sources */,
 				A757C92E22744ACE00226355 /* AddressManagerListModel.swift in Sources */,

+ 318 - 0
RainbowPlanet/RainbowPlanet/Modules/PublishModule/PhotoPicker/TLPhotoPicker/CustomCameraCell.swift

@@ -0,0 +1,318 @@
+//
+//  CustomCameraCell.swift
+//  TLPhotoPicker_Example
+//
+//  Created by wade.hawk on 2017. 10. 27..
+//  Copyright © 2017년 CocoaPods. All rights reserved.
+//
+
+import Foundation
+import AVFoundation
+import Photos
+
+@available(iOS 10.2, *)
+class CustomCameraCell: TLPhotoCollectionViewCell, AVCaptureFileOutputRecordingDelegate {
+    // MARK: Session Management
+    private enum SessionSetupResult {
+        case success
+        case notAuthorized
+        case configurationFailed
+    }
+    
+    private let session = AVCaptureSession()
+    private var isSessionRunning = false
+    private let sessionQueue = DispatchQueue(label: "session queue") // Communicate with the session and other session objects on this queue.
+    private var setupResult: SessionSetupResult = .success
+    var videoDeviceInput: AVCaptureDeviceInput!
+    
+    @IBOutlet private weak var previewView: PreviewView!
+    override func awakeFromNib() {
+        super.awakeFromNib()
+        if Platform.isSimulator {
+            return
+        }
+        previewView.session = session
+        /*
+         Check video authorization status. Video access is required and audio
+         access is optional. If audio access is denied, audio is not recorded
+         during movie recording.
+         */
+        switch AVCaptureDevice.authorizationStatus(for: .video) {
+        case .authorized:
+            // The user has previously granted access to the camera.
+            break
+            
+        case .notDetermined:
+            /*
+             The user has not yet been presented with the option to grant
+             video access. We suspend the session queue to delay session
+             setup until the access request has completed.
+             
+             Note that audio access will be implicitly requested when we
+             create an AVCaptureDeviceInput for audio during session setup.
+             */
+            sessionQueue.suspend()
+            AVCaptureDevice.requestAccess(for: .video, completionHandler: { granted in
+                if !granted {
+                    self.setupResult = .notAuthorized
+                }
+                self.sessionQueue.resume()
+            })
+            
+        default:
+            // The user has previously denied access.
+            setupResult = .notAuthorized
+        }
+        
+        /*
+         Setup the capture session.
+         In general it is not safe to mutate an AVCaptureSession or any of its
+         inputs, outputs, or connections from multiple threads at the same time.
+         
+         Why not do all of this on the main queue?
+         Because AVCaptureSession.startRunning() is a blocking call which can
+         take a long time. We dispatch session setup to the sessionQueue so
+         that the main queue isn't blocked, which keeps the UI responsive.
+         */
+        sessionQueue.async {
+            self.configureSession()
+        }
+    }
+    
+    override func willDisplayCell() {
+        super.willDisplayCell()
+        if Platform.isSimulator {
+            return
+        }
+        sessionQueue.async { [weak self] in
+            guard let `self` = self else { return }
+            switch self.setupResult {
+            case .success:
+                // Only setup observers and start the session running if setup succeeded.
+                self.session.startRunning()
+                self.isSessionRunning = self.session.isRunning
+            default:
+                break
+            }
+        }
+    }
+    
+    override func endDisplayingCell() {
+        if Platform.isSimulator {
+            return
+        }
+        sessionQueue.async { [weak self] in
+            guard let `self` = self else { return }
+            if self.setupResult == .success {
+                self.session.stopRunning()
+                self.isSessionRunning = self.session.isRunning
+            }
+        }
+        super.endDisplayingCell()
+    }
+    
+    // Call this on the session queue.
+    private func configureSession() {
+        if setupResult != .success {
+            return
+        }
+        
+        session.beginConfiguration()
+        session.sessionPreset = .photo
+        do {
+            var defaultVideoDevice: AVCaptureDevice?
+            
+            // Choose the back dual camera if available, otherwise default to a wide angle camera.
+            if let dualCameraDevice = AVCaptureDevice.default(.builtInDualCamera, for: .video, position: .back) {
+                defaultVideoDevice = dualCameraDevice
+            } else if let backCameraDevice = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back) {
+                // If the back dual camera is not available, default to the back wide angle camera.
+                defaultVideoDevice = backCameraDevice
+            } else if let frontCameraDevice = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .front) {
+                /*
+                 In some cases where users break their phones, the back wide angle camera is not available.
+                 In this case, we should default to the front wide angle camera.
+                 */
+                defaultVideoDevice = frontCameraDevice
+            }
+            
+            let videoDeviceInput = try AVCaptureDeviceInput(device: defaultVideoDevice!)
+            
+            if session.canAddInput(videoDeviceInput) {
+                session.addInput(videoDeviceInput)
+                self.videoDeviceInput = videoDeviceInput
+                
+                DispatchQueue.main.async {
+                    /*
+                     Why are we dispatching this to the main queue?
+                     Because AVCaptureVideoPreviewLayer is the backing layer for PreviewView and UIView
+                     can only be manipulated on the main thread.
+                     Note: As an exception to the above rule, it is not necessary to serialize video orientation changes
+                     on the AVCaptureVideoPreviewLayer’s connection with other session manipulation.
+                     
+                     Use the status bar orientation as the initial video orientation. Subsequent orientation changes are
+                     handled by CameraViewController.viewWillTransition(to:with:).
+                     */
+                    let statusBarOrientation = UIApplication.shared.statusBarOrientation
+                    var initialVideoOrientation: AVCaptureVideoOrientation = .portrait
+                    if statusBarOrientation != .unknown {
+                        if let videoOrientation = AVCaptureVideoOrientation(rawValue: statusBarOrientation.rawValue) {
+                            initialVideoOrientation = videoOrientation
+                        }
+                    }
+                    self.previewView.videoPreviewLayer.connection?.videoOrientation = initialVideoOrientation
+                }
+            } else {
+                print("Could not add video device input to the session")
+                setupResult = .configurationFailed
+                session.commitConfiguration()
+                return
+            }
+        } catch {
+            print("Could not create video device input: \(error)")
+            setupResult = .configurationFailed
+            session.commitConfiguration()
+            return
+        }
+        // Add photo output.
+        if session.canAddOutput(photoOutput) {
+            session.addOutput(photoOutput)
+            photoOutput.isHighResolutionCaptureEnabled = true
+        } else {
+            print("Could not add photo output to the session")
+            setupResult = .configurationFailed
+            session.commitConfiguration()
+            return
+        }
+        
+        session.commitConfiguration()
+    }
+    
+    private enum CaptureMode: Int {
+        case photo = 0
+        case movie = 1
+    }
+    
+    // MARK: Device Configuration
+    let videoDeviceDiscoverySession = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera, .builtInDualCamera],
+                                                                               mediaType: .video, position: .unspecified)
+
+    // MARK: Capturing Photos
+    
+
+    let photoOutput = AVCapturePhotoOutput()
+    
+    var inProgressPhotoCaptureDelegates = [Int64: PhotoCaptureProcessor]()
+
+    override func selectedCell() {
+        let videoPreviewLayerOrientation = previewView.videoPreviewLayer.connection?.videoOrientation
+        
+        sessionQueue.async {
+            // Update the photo output's connection to match the video orientation of the video preview layer.
+            if let photoOutputConnection = self.photoOutput.connection(with: .video) {
+                photoOutputConnection.videoOrientation = videoPreviewLayerOrientation!
+            }
+            
+            var photoSettings = AVCapturePhotoSettings()
+            // Capture HEIF photo when supported, with flash set to auto and high resolution photo enabled.
+            if #available(iOS 11.0, *) {
+                if  self.photoOutput.availablePhotoCodecTypes.contains(.hevc) {
+                    photoSettings = AVCapturePhotoSettings(format: [AVVideoCodecKey: AVVideoCodecType.hevc])
+                }
+            } else {
+                // Fallback on earlier versions
+            }
+            
+            if self.videoDeviceInput.device.isFlashAvailable {
+                photoSettings.flashMode = .auto
+            }
+            
+            photoSettings.isHighResolutionPhotoEnabled = true
+            if !photoSettings.__availablePreviewPhotoPixelFormatTypes.isEmpty {
+                photoSettings.previewPhotoFormat = [kCVPixelBufferPixelFormatTypeKey as String: photoSettings.__availablePreviewPhotoPixelFormatTypes.first!]
+            }
+            
+            // Use a separate object for the photo capture delegate to isolate each capture life cycle.
+            let photoCaptureProcessor = PhotoCaptureProcessor(with: photoSettings, willCapturePhotoAnimation: {
+                DispatchQueue.main.async {
+                    self.previewView.videoPreviewLayer.opacity = 0
+                    UIView.animate(withDuration: 0.25) {
+                        self.previewView.videoPreviewLayer.opacity = 1
+                    }
+                }
+            }, livePhotoCaptureHandler: { capturing in
+            }, completionHandler: { photoCaptureProcessor in
+                // When the capture is complete, remove a reference to the photo capture delegate so it can be deallocated.
+                self.sessionQueue.async {
+                    self.inProgressPhotoCaptureDelegates[photoCaptureProcessor.requestedPhotoSettings.uniqueID] = nil
+                }
+            })
+            self.inProgressPhotoCaptureDelegates[photoCaptureProcessor.requestedPhotoSettings.uniqueID] = photoCaptureProcessor
+            self.photoOutput.capturePhoto(with: photoSettings, delegate: photoCaptureProcessor)
+        }
+    }
+
+    func fileOutput(_ output: AVCaptureFileOutput, didStartRecordingTo fileURL: URL, from connections: [AVCaptureConnection]) {
+        // Enable the Record button to let the user stop the recording.
+    }
+
+    func fileOutput(_ output: AVCaptureFileOutput, didFinishRecordingTo outputFileURL: URL, from connections: [AVCaptureConnection], error: Error?) {
+        func cleanUp() {
+            let path = outputFileURL.path
+            if FileManager.default.fileExists(atPath: path) {
+                do {
+                    try FileManager.default.removeItem(atPath: path)
+                } catch {
+                    print("Could not remove file at url: \(outputFileURL)")
+                }
+            }
+        }
+        
+        var success = true
+        
+        if error != nil {
+            print("Movie file finishing error: \(String(describing: error))")
+            success = (((error! as NSError).userInfo[AVErrorRecordingSuccessfullyFinishedKey] as AnyObject).boolValue)!
+        }
+        
+        if success {
+            // Check authorization status.
+            PHPhotoLibrary.requestAuthorization { status in
+                if status == .authorized {
+                    // Save the movie file to the photo library and cleanup.
+                    PHPhotoLibrary.shared().performChanges({
+                        let options = PHAssetResourceCreationOptions()
+                        options.shouldMoveFile = true
+                        let creationRequest = PHAssetCreationRequest.forAsset()
+                        creationRequest.addResource(with: .video, fileURL: outputFileURL, options: options)
+                    }, completionHandler: { success, error in
+                        if !success {
+                            print("Could not save movie to photo library: \(String(describing: error))")
+                        }
+                        cleanUp()
+                    }
+                    )
+                } else {
+                    cleanUp()
+                }
+            }
+        } else {
+            cleanUp()
+        }
+    }
+}
+
+@available(iOS 10.0, *)
+extension AVCaptureDevice.DiscoverySession {
+    var uniqueDevicePositionsCount: Int {
+        var uniqueDevicePositions: [AVCaptureDevice.Position] = []
+        
+        for device in devices {
+            if !uniqueDevicePositions.contains(device.position) {
+                uniqueDevicePositions.append(device.position)
+            }
+        }
+        
+        return uniqueDevicePositions.count
+    }
+}

RainbowPlanet/RainbowPlanet/Modules/PublishModule/PublishMediaPicker/View/KSVideoPlayerView/KSVideoLayer.h → RainbowPlanet/RainbowPlanet/Modules/PublishModule/PhotoPicker/TLPhotoPicker/KSVideoPlayerView/KSVideoLayer.h


RainbowPlanet/RainbowPlanet/Modules/PublishModule/PublishMediaPicker/View/KSVideoPlayerView/KSVideoLayer.m → RainbowPlanet/RainbowPlanet/Modules/PublishModule/PhotoPicker/TLPhotoPicker/KSVideoPlayerView/KSVideoLayer.m


RainbowPlanet/RainbowPlanet/Modules/PublishModule/PublishMediaPicker/View/KSVideoPlayerView/KSVideoPlayerBaseView.h → RainbowPlanet/RainbowPlanet/Modules/PublishModule/PhotoPicker/TLPhotoPicker/KSVideoPlayerView/KSVideoPlayerBaseView.h


RainbowPlanet/RainbowPlanet/Modules/PublishModule/PublishMediaPicker/View/KSVideoPlayerView/KSVideoPlayerBaseView.m → RainbowPlanet/RainbowPlanet/Modules/PublishModule/PhotoPicker/TLPhotoPicker/KSVideoPlayerView/KSVideoPlayerBaseView.m


+ 174 - 0
RainbowPlanet/RainbowPlanet/Modules/PublishModule/PhotoPicker/TLPhotoPicker/PhotoCaptureDelegate.swift

@@ -0,0 +1,174 @@
+/*
+ See LICENSE.txt for this sample’s licensing information.
+ Sample code project: AVCam-iOS: Using AVFoundation to Capture Images and Movies
+ Version: 7.1
+ 
+ IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2017 Apple Inc. All Rights Reserved.
+ 
+ Abstract:
+ Application preview view.
+ */
+import AVFoundation
+import Photos
+
+@available(iOS 10.2, *)
+class PhotoCaptureProcessor: NSObject {
+    private(set) var requestedPhotoSettings: AVCapturePhotoSettings
+    
+    private let willCapturePhotoAnimation: () -> Void
+    
+    private let livePhotoCaptureHandler: (Bool) -> Void
+    
+    private let completionHandler: (PhotoCaptureProcessor) -> Void
+    
+    private var photoData: Data?
+    
+    private var livePhotoCompanionMovieURL: URL?
+    
+    init(with requestedPhotoSettings: AVCapturePhotoSettings,
+         willCapturePhotoAnimation: @escaping () -> Void,
+         livePhotoCaptureHandler: @escaping (Bool) -> Void,
+         completionHandler: @escaping (PhotoCaptureProcessor) -> Void) {
+        self.requestedPhotoSettings = requestedPhotoSettings
+        self.willCapturePhotoAnimation = willCapturePhotoAnimation
+        self.livePhotoCaptureHandler = livePhotoCaptureHandler
+        self.completionHandler = completionHandler
+    }
+    
+    private func didFinish() {
+        if let livePhotoCompanionMoviePath = livePhotoCompanionMovieURL?.path {
+            if FileManager.default.fileExists(atPath: livePhotoCompanionMoviePath) {
+                do {
+                    try FileManager.default.removeItem(atPath: livePhotoCompanionMoviePath)
+                } catch {
+                    print("Could not remove file at url: \(livePhotoCompanionMoviePath)")
+                }
+            }
+        }
+        
+        completionHandler(self)
+    }
+    
+}
+
+@available(iOS 10.2, *)
+extension PhotoCaptureProcessor: AVCapturePhotoCaptureDelegate {
+    /*
+     This extension includes all the delegate callbacks for AVCapturePhotoCaptureDelegate protocol
+     */
+    
+    func photoOutput(_ output: AVCapturePhotoOutput, willBeginCaptureFor resolvedSettings: AVCaptureResolvedPhotoSettings) {
+        if resolvedSettings.livePhotoMovieDimensions.width > 0 && resolvedSettings.livePhotoMovieDimensions.height > 0 {
+            livePhotoCaptureHandler(true)
+        }
+    }
+    
+    func photoOutput(_ output: AVCapturePhotoOutput, willCapturePhotoFor resolvedSettings: AVCaptureResolvedPhotoSettings) {
+        willCapturePhotoAnimation()
+    }
+    
+    @available(iOS 11.0, *)
+    func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
+        
+        if let error = error {
+            print("Error capturing photo: \(error)")
+        } else {
+            photoData = photo.fileDataRepresentation()
+        }
+    }
+    func photoOutput(_ output: AVCapturePhotoOutput, didFinishRecordingLivePhotoMovieForEventualFileAt outputFileURL: URL, resolvedSettings: AVCaptureResolvedPhotoSettings) {
+        livePhotoCaptureHandler(false)
+    }
+    
+    func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingLivePhotoToMovieFileAt outputFileURL: URL, duration: CMTime, photoDisplayTime: CMTime, resolvedSettings: AVCaptureResolvedPhotoSettings, error: Error?) {
+        if error != nil {
+            print("Error processing live photo companion movie: \(String(describing: error))")
+            return
+        }
+        livePhotoCompanionMovieURL = outputFileURL
+    }
+    
+    func photoOutput(_ output: AVCapturePhotoOutput, didFinishCaptureFor resolvedSettings: AVCaptureResolvedPhotoSettings, error: Error?) {
+        if let error = error {
+            print("Error capturing photo: \(error)")
+            didFinish()
+            return
+        }
+        
+        guard let photoData = photoData else {
+            print("No photo data resource")
+            didFinish()
+            return
+        }
+        
+        PHPhotoLibrary.requestAuthorization { status in
+            if status == .authorized {
+                PHPhotoLibrary.shared().performChanges({
+                    let options = PHAssetResourceCreationOptions()
+                    let creationRequest = PHAssetCreationRequest.forAsset()
+                    if #available(iOS 11.0, *) {
+                        options.uniformTypeIdentifier = self.requestedPhotoSettings.processedFileType.map { $0.rawValue }
+                    } else {
+                        // Fallback on earlier versions
+                    }
+                    creationRequest.addResource(with: .photo, data: photoData, options: options)
+                    
+                    if let livePhotoCompanionMovieURL = self.livePhotoCompanionMovieURL {
+                        let livePhotoCompanionMovieFileResourceOptions = PHAssetResourceCreationOptions()
+                        livePhotoCompanionMovieFileResourceOptions.shouldMoveFile = true
+                        creationRequest.addResource(with: .pairedVideo, fileURL: livePhotoCompanionMovieURL, options: livePhotoCompanionMovieFileResourceOptions)
+                    }
+                    
+                }, completionHandler: { _, error in
+                    if let error = error {
+                        print("Error occurered while saving photo to photo library: \(error)")
+                    }
+                    
+                    self.didFinish()
+                }
+                )
+            } else {
+                self.didFinish()
+            }
+        }
+    }
+}
+

+ 77 - 0
RainbowPlanet/RainbowPlanet/Modules/PublishModule/PhotoPicker/TLPhotoPicker/PreviewView.swift

@@ -0,0 +1,77 @@
+/*
+ See LICENSE.txt for this sample’s licensing information.
+ Sample code project: AVCam-iOS: Using AVFoundation to Capture Images and Movies
+ Version: 7.1
+ 
+ IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2017 Apple Inc. All Rights Reserved.
+
+ Abstract:
+ Application preview view.
+ */
+
+import UIKit
+import AVFoundation
+
+class PreviewView: UIView {
+    var videoPreviewLayer: AVCaptureVideoPreviewLayer {
+        guard let layer = layer as? AVCaptureVideoPreviewLayer else {
+            fatalError("Expected `AVCaptureVideoPreviewLayer` type for layer. Check PreviewView.layerClass implementation.")
+        }
+        layer.videoGravity = .resizeAspectFill
+        return layer
+    }
+    
+    var session: AVCaptureSession? {
+        get {
+            return videoPreviewLayer.session
+        }
+        set {
+            videoPreviewLayer.session = newValue
+        }
+    }
+    
+    // MARK: UIView
+    
+    override class var layerClass: AnyClass {
+        return AVCaptureVideoPreviewLayer.self
+    }
+}
+

RainbowPlanet/RainbowPlanet/Tools/PhotoPicker/TLPhotoPicker/SynchronizedDictionary.swift → RainbowPlanet/RainbowPlanet/Modules/PublishModule/PhotoPicker/TLPhotoPicker/SynchronizedDictionary.swift


RainbowPlanet/RainbowPlanet/Tools/PhotoPicker/TLPhotoPicker/TLAlbumPopView.swift → RainbowPlanet/RainbowPlanet/Modules/PublishModule/PhotoPicker/TLPhotoPicker/TLAlbumPopView.swift


RainbowPlanet/RainbowPlanet/Tools/PhotoPicker/TLPhotoPicker/TLAssetCollection+Extension.swift → RainbowPlanet/RainbowPlanet/Modules/PublishModule/PhotoPicker/TLPhotoPicker/TLAssetCollection+Extension.swift


RainbowPlanet/RainbowPlanet/Tools/PhotoPicker/TLPhotoPicker/TLAssetsCollection.swift → RainbowPlanet/RainbowPlanet/Modules/PublishModule/PhotoPicker/TLPhotoPicker/TLAssetsCollection.swift


RainbowPlanet/RainbowPlanet/Tools/PhotoPicker/TLPhotoPicker/TLBundle.swift → RainbowPlanet/RainbowPlanet/Modules/PublishModule/PhotoPicker/TLPhotoPicker/TLBundle.swift


RainbowPlanet/RainbowPlanet/Tools/PhotoPicker/TLPhotoPicker/TLCollectionTableViewCell.swift → RainbowPlanet/RainbowPlanet/Modules/PublishModule/PhotoPicker/TLPhotoPicker/TLCollectionTableViewCell.swift


+ 391 - 0
RainbowPlanet/RainbowPlanet/Modules/PublishModule/PhotoPicker/TLPhotoPicker/TLPhontoPreviewView.swift

@@ -0,0 +1,391 @@
+//
+//  TLPhontoPreviewView.swift
+//  RainbowPlanet
+//
+//  Created by 南鑫林 on 2019/8/25.
+//  Copyright © 2019 RainbowPlanet. All rights reserved.
+//
+
+import UIKit
+import PhotosUI
+import Kingfisher
+
+extension TLPhontoPreviewView {
+    
+    private class scrollView: UIScrollView, UIScrollViewDelegate {
+        
+        private enum imageDirection {
+            case equal
+            case transversal
+            case lengthwise
+        }
+        
+        required init?(coder aDecoder: NSCoder) {
+            fatalError("init(coder:) has not been implemented")
+        }
+        
+        public let imageView = UIImageView()
+        
+        override init(frame: CGRect) {
+            super.init(frame: frame)
+            backgroundColor = .clear
+            showsVerticalScrollIndicator = false
+            showsHorizontalScrollIndicator = false
+            alwaysBounceVertical = true
+            alwaysBounceHorizontal = true
+            maximumZoomScale = 3.0
+            clipsToBounds = true
+            if #available(iOS 11.0, *) {
+                contentInsetAdjustmentBehavior = .never
+            }
+            addSubview(imageView)
+            delegate = self
+        }
+        
+        private var _isSquare = false
+        
+        override open var frame: CGRect {
+            set {
+                if frame.size != newValue.size {
+                    let windowSize = newValue.size
+                    _isSquare = floor(windowSize.width) == floor(windowSize.height)
+                    _imageDirection = _imageDirection(from: _imageSize, windowSize)
+                }
+                if _isNeedLayoutSubviews {
+                    zoomScale = 1.0
+                    contentOffset = .zero
+                }
+                super.frame = newValue
+            }
+            get {
+                return super.frame
+            }
+        }
+        
+        private var _isNeedLayoutSubviews = true
+        
+        public func set(frame: CGRect, isNeedLayoutSubviews: Bool) {
+            _isNeedLayoutSubviews = isNeedLayoutSubviews
+            self.frame = frame
+        }
+        
+        open var itemModel: KSMediaPickerItemModel? {
+            didSet {
+                guard let k_itemModel = itemModel else {
+                    return
+                }
+                let asset = k_itemModel.asset
+                let floatWidth = CGFloat(asset.pixelWidth)
+                let floatHeight = CGFloat(asset.pixelHeight)
+                _imageSize = CGSize(width: floatWidth, height: floatHeight)
+            }
+        }
+        
+        var _imageSize = CGSize.zero {
+            didSet {
+                _imageDirection = _imageDirection(from: _imageSize, frame.size)
+                _isNeedLayoutSubviews = true
+                setNeedsLayout()
+            }
+        }
+        
+        override func layoutSubviews() {
+            super.layoutSubviews()
+            guard _isNeedLayoutSubviews || imageView.frame.size == .zero else {
+                return
+            }
+            _isNeedLayoutSubviews = false
+            let offset: CGPoint
+            if _imageDirection == .equal {
+                imageView.frame = bounds
+                offset = .zero
+            } else if _imageSize != .zero {
+                let windowSize = frame.size
+                let windowWidth = windowSize.width
+                let windowHeight = windowSize.height
+                let floatZore = CGFloat(0.0)
+                let viewX: CGFloat
+                let viewY: CGFloat
+                let viewW: CGFloat
+                let viewH: CGFloat
+                
+                let imageWidth = _imageSize.width
+                let imageHeight = _imageSize.height
+                
+                if _imageDirection == .transversal {
+                    viewH = windowHeight
+                    viewW = imageWidth/imageHeight*viewH
+                    viewY = floatZore
+                    viewX = (windowWidth-viewW)*0.5
+                } else {
+                    viewW = windowWidth
+                    viewH = imageHeight/imageWidth*viewW
+                    viewX = floatZore
+                    viewY = (windowHeight-viewH)*0.5
+                }
+                imageView.frame = CGRect(origin: .zero, size: CGSize(width: viewW, height: viewH))
+                offset = CGPoint(x: -viewX, y: -viewY)
+            } else {
+                offset = .zero
+            }
+            contentSize = imageView.frame.size
+            zoomScale = itemModel?.zoomScale ?? 1.0
+            contentOffset = itemModel?.contentOffset ?? offset
+            
+            let minimumZoomScale: CGFloat
+            if _isSquare {
+                switch _imageDirection {
+                case .equal:
+                    minimumZoomScale = 1.0
+                    break
+                case .transversal:
+                    minimumZoomScale = frame.size.width/imageView.frame.size.width
+                    break
+                case .lengthwise:
+                    minimumZoomScale = frame.size.height/imageView.frame.size.height
+                    break
+                }
+            } else {
+                minimumZoomScale = 1.0
+            }
+            self.minimumZoomScale = minimumZoomScale
+        }
+        
+        private func _imageDirection(from imageSize: CGSize, _ superSize: CGSize) -> TLPhontoPreviewView.scrollView.imageDirection {
+            let superWidth = floor(superSize.width)
+            let superHeight = floor(superSize.height)
+            let imageWidth = floor(imageSize.width)
+            let imageHeight = floor(imageSize.height)
+            let constrainImageHeight = floor(imageHeight/imageWidth*superWidth)
+            let dirction: TLPhontoPreviewView.scrollView.imageDirection
+            if superHeight == constrainImageHeight {
+                dirction = .equal
+            } else {
+                let maxHeight = max(superHeight, constrainImageHeight)
+                if maxHeight == superHeight {
+                    dirction = .transversal
+                } else {
+                    dirction = .lengthwise
+                }
+            }
+            return dirction
+        }
+        
+        private var _imageDirection = TLPhontoPreviewView.scrollView.imageDirection.equal
+        
+        func viewForZooming(in scrollView: UIScrollView) -> UIView? {
+            return imageView
+        }
+        
+        func scrollViewDidZoom(_ scrollView: UIScrollView) {
+            let contentSize = scrollView.contentSize
+            let contentSizeWidth = floor(contentSize.width)
+            let contentSizeHeight = floor(contentSize.height)
+            let size = scrollView.frame.size
+            
+            var center = scrollView.center
+            if contentSizeWidth >= floor(size.width) {
+                center.x = contentSizeWidth*0.5
+            }
+            if contentSizeHeight >= floor(size.height) {
+                center.y = contentSizeHeight*0.5
+            }
+            imageView.center = center
+        }
+    }
+}
+
+import Photos
+
+open class TLPhontoPreviewView: UIView {
+    
+    required public init?(coder aDecoder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+    
+    private var _photoLibrary = TLPhotoLibrary()
+    
+    private let _videoView = {() -> KSVideoPlayerBaseView in
+        let videoView = KSVideoPlayerBaseView()
+        videoView.videoGravity = .resizeAspect
+        videoView.videoPlaybackFinished = {[weak videoView] in
+            videoView?.play()
+        }
+        videoView.isHidden = true
+        return videoView
+    }()
+    
+    private let _scrollview = TLPhontoPreviewView.scrollView()
+    
+    private let _changeSizeButton = {() -> UIButton in
+        let changeSizeButton = UIButton(type: .custom)
+        changeSizeButton.setImage(UIImage(named: "icon_mediaPicker_preview_nocut"), for: .normal)
+        changeSizeButton.setImage(UIImage(named: "icon_mediaPicker_preview_cut"), for: .selected)
+        changeSizeButton.backgroundColor = .clear
+        return changeSizeButton
+    }()
+    
+    override public init(frame: CGRect) {
+        super.init(frame: frame)
+        backgroundColor = .black
+        clipsToBounds = true
+        addSubview(_scrollview)
+        
+        _changeSizeButton.addTarget(self, action: #selector(_didClick(changeSizeButton:)), for: .touchUpInside)
+        addSubview(_changeSizeButton)
+        
+        addSubview(_videoView)
+    }
+    
+    override open func layoutSubviews() {
+        super.layoutSubviews()
+        let bounds = self.bounds
+        _videoView.frame = bounds
+        
+        let windowSize = bounds.size
+        let windowWidth = windowSize.width
+        let windowHeight = windowSize.height
+        
+        let scrollviewSize = _scrollview.frame.size
+        var viewW = scrollviewSize.width
+        var viewH = scrollviewSize.height
+        var viewX = (windowWidth-viewW)*0.5
+        var viewY = (windowHeight-viewH)*0.5
+        _scrollview.frame = CGRect(x: viewX, y: viewY, width: viewW, height: viewH)
+        
+        viewW = 30.0
+        viewH = viewW
+        viewX = CGFloat(10.0)
+        viewY = windowHeight-viewH-10.0
+        _changeSizeButton.frame = CGRect(x: viewX, y: viewY, width: viewW, height: viewH)
+        //        _changeSizeButton.layer.cornerRadius = viewH*0.5
+    }
+    
+    @objc private func _didClick(changeSizeButton: UIButton) {
+        let isChangedSize = changeSizeButton.isSelected
+        changeSizeButton.isSelected = !isChangedSize
+        let frame: CGRect
+        if isChangedSize {
+            frame = bounds
+        } else {
+            let windowSize = bounds.size
+            let windowWidth = windowSize.width
+            let windowHeight = windowSize.height
+            
+            let viewW = _minScrollViewSize.width
+            let viewH = _minScrollViewSize.height
+            let viewX = (windowWidth-viewW)*0.5
+            let viewY = (windowHeight-viewH)*0.5
+            frame = CGRect(x: viewX, y: viewY, width: viewW, height: viewH)
+        }
+        UIView.animate(withDuration: 0.2, delay: 0.0, usingSpringWithDamping: 1.0, initialSpringVelocity: 1.0, options: .layoutSubviews, animations: {[weak self] in
+            self?._scrollview.set(frame: frame, isNeedLayoutSubviews: true)
+            }, completion: nil)
+    }
+    
+    static private let _minScale = CGFloat(3.0/4.0)
+    
+    private var _minScrollViewSize = CGSize.zero
+    private var _normalScrollViewSize = CGSize.zero
+    
+    var _asset : TLPHAsset? {
+        didSet {
+            guard let asset = _asset else {
+                return
+            }
+            if asset.type == .video {
+                _videoView.isHidden = false
+                _scrollview.isHidden = true
+                _changeSizeButton.isHidden = true
+                _ = _photoLibrary.videoAsset(asset: asset.phAsset!, size: CGSize(width: kScreenWidth, height: kScreenWidth), progressBlock: { (double, error, unsafeMutablePointer, dict) in
+                    
+                }) { [weak self] (avPlayerItem, dict) in
+                    guard let videoView = self?._videoView else {
+                        return
+                    }
+                    if Thread.current.isMainThread {
+                        videoView.playerItem = avPlayerItem
+                        videoView.play()
+                    } else {
+                        DispatchQueue.main.async {
+                            videoView.playerItem = avPlayerItem
+                            videoView.play()
+                        }
+                    }
+                }
+            }else if asset.type == .photo || asset.type == .livePhoto  {
+                let mainSize = UIScreen.main.bounds.size
+                _videoView.isHidden = true
+                if _videoView.isPlaying {
+                    _videoView.pause()
+                }
+                _scrollview.isHidden = false
+                let pixelWidth = asset.phAsset?.pixelWidth
+                let pixelHeight = asset.phAsset?.pixelHeight
+                
+                _scrollview._imageSize = CGSize(width: pixelWidth ?? 0, height: pixelHeight ?? 0)
+                
+                let windowWidth = mainSize.width
+                if _isStandard {
+                    _normalScrollViewSize = CGSize(width: windowWidth, height: windowWidth)
+                    if pixelWidth == pixelHeight {
+                        _changeSizeButton.isHidden = true
+                        _minScrollViewSize = _normalScrollViewSize
+                    } else {
+                        _changeSizeButton.isHidden = false
+                        let maxWidth = max(pixelHeight ?? 0, pixelWidth ?? 0)
+                        let minScale = TLPhontoPreviewView._minScale
+                        let floatWidth = CGFloat(pixelWidth ?? 0)
+                        let floatHeight = CGFloat(pixelHeight ?? 0)
+                        let scrollViewSize: CGSize
+                        if maxWidth == pixelWidth {//横向
+                            let scale = floatHeight/floatWidth
+                            let minHeight: CGFloat
+                            let minWidth = windowWidth
+                            if scale > minScale {
+                                minHeight = floor(floatHeight*minWidth/floatWidth)
+                            } else {
+                                minHeight = floor(minWidth*minScale)
+                            }
+                            scrollViewSize = CGSize(width: minWidth, height: minHeight)
+                        } else {//纵向
+                            let scale = floatWidth/floatHeight
+                            let minWidth: CGFloat
+                            let minHeight = windowWidth
+                            if scale > minScale {
+                                minWidth = floor(floatWidth*minHeight/floatHeight)
+                            } else {
+                                minWidth = floor(minHeight*minScale)
+                            }
+                            scrollViewSize = CGSize(width: minWidth, height: minHeight)
+                        }
+                        _minScrollViewSize = scrollViewSize
+                    }
+                } else {
+                    _changeSizeButton.isHidden = true
+                }
+                _scrollview.set(frame: CGRect(origin: .zero, size: _changeSizeButton.isSelected ? _minScrollViewSize : _normalScrollViewSize), isNeedLayoutSubviews: true)
+                setNeedsLayout()
+                self._scrollview.imageView.image = asset.fullResolutionImage
+            }
+        }
+    }
+    
+    private var _isStandard = true
+    
+    open var isStandard: Bool {
+        return _isStandard
+    }
+    
+    public func videoPlay() {
+        if !_videoView.isHidden {
+            _videoView.play()
+        }
+    }
+    public func videoPause() {
+        if !_videoView.isHidden || _videoView.isPlaying {
+            _videoView.pause()
+        }
+    }
+}
+

+ 34 - 10
RainbowPlanet/RainbowPlanet/Tools/PhotoPicker/TLPhotoPicker/TLPhotoCollectionViewCell.swift

@@ -40,14 +40,14 @@ open class TLPhotoCollectionViewCell: UICollectionViewCell {
     @IBOutlet open var durationLabel: UILabel?
     @IBOutlet open var indicator: UIActivityIndicatorView?
     @IBOutlet open var selectedView: UIView?
-    @IBOutlet open var selectedHeight: NSLayoutConstraint?
+    @IBOutlet open var noSelectedView: UIView?
     @IBOutlet open var orderLabel: UILabel?
     @IBOutlet open var orderBgView: UIView?
+
     
     var configure = TLPhotosPickerConfigure() {
         didSet {
             self.selectedView?.layer.borderColor = self.configure.selectedColor.cgColor
-            self.orderBgView?.backgroundColor = self.configure.selectedColor
             self.videoIconImageView?.image = self.configure.videoIcon
         }
     }
@@ -57,7 +57,7 @@ open class TLPhotoCollectionViewCell: UICollectionViewCell {
     open var duration: TimeInterval? {
         didSet {
             guard let duration = self.duration else { return }
-            self.selectedHeight?.constant = -10
+//            self.selectedHeight?.constant = -10
             self.durationLabel?.text = timeFormatted(timeInterval: duration)
         }
     }
@@ -87,18 +87,25 @@ open class TLPhotoCollectionViewCell: UICollectionViewCell {
     @objc open var selectedAsset: Bool = false {
         willSet(newValue) {
             self.selectedView?.isHidden = !newValue
-            self.durationView?.backgroundColor = newValue ? self.configure.selectedColor : UIColor(red: 0, green: 0, blue: 0, alpha: 0.6)
             if !newValue {
                 self.orderLabel?.text = ""
+            }else {
+                self.orderLabel?.isHidden = false
             }
         }
     }
     
+    
+    /// 转换时长
+    ///
+    /// - Parameter timeInterval: 时长
+    /// - Returns: 时长字符串
     @objc open func timeFormatted(timeInterval: TimeInterval) -> String {
         let seconds: Int = lround(timeInterval)
         var hour: Int = 0
         var minute: Int = Int(seconds/60)
         let second: Int = seconds % 60
+        
         if minute > 59 {
             hour = minute / 60
             minute = minute % 60
@@ -106,6 +113,8 @@ open class TLPhotoCollectionViewCell: UICollectionViewCell {
         } else {
             return String(format: "%d:%02d", minute, second)
         }
+        
+        
     }
     
     @objc open func popScaleAnim() {
@@ -145,7 +154,7 @@ open class TLPhotoCollectionViewCell: UICollectionViewCell {
     }
     
     deinit {
-//        print("deinit TLPhotoCollectionViewCell")
+        NXLLog("deinit")
     }
     
     override open func awakeFromNib() {
@@ -153,10 +162,17 @@ open class TLPhotoCollectionViewCell: UICollectionViewCell {
         self.playerView?.playerLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill
         self.livePhotoView?.isHidden = true
         self.durationView?.isHidden = true
+        self.durationView?.backgroundColor = UIColor.clear
         self.selectedView?.isHidden = true
-        self.selectedView?.layer.borderWidth = 10
-        self.selectedView?.layer.cornerRadius = 15
-        self.orderBgView?.layer.cornerRadius = 2
+        self.selectedView?.layer.borderWidth = 1.5
+        self.selectedView?.backgroundColor = kThemeColor.withAlphaComponent(0.2)
+
+        self.videoIconImageView?.isHidden = true
+        self.orderBgView?.layer.borderWidth = 1.5
+        self.orderBgView?.layer.cornerRadius = self.orderBgView!.width/2
+        self.orderBgView?.layer.borderColor = kffffffColor.cgColor
+        self.orderBgView?.backgroundColor = UIColor.init(hexString: "000000", alpha: 0.2)
+        self.orderLabel?.isHidden = true
         self.videoIconImageView?.image = self.configure.videoIcon
         if #available(iOS 11.0, *) {
             self.imageView?.accessibilityIgnoresInvertColors = true
@@ -172,8 +188,16 @@ open class TLPhotoCollectionViewCell: UICollectionViewCell {
         self.livePhotoView?.isHidden = true
         self.livePhotoView?.delegate = nil
         self.durationView?.isHidden = true
-        self.durationView?.backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.6)
-        self.selectedHeight?.constant = 10
+        self.durationView?.backgroundColor = UIColor.clear
+        self.videoIconImageView?.isHidden = true
         self.selectedAsset = false
     }
+    
+
+    open override var isSelected: Bool {
+        didSet {
+            self.selectedView?.isHidden = !self.isSelected
+        }
+    }
+    
 }

+ 1 - 1
RainbowPlanet/RainbowPlanet/Tools/PhotoPicker/TLPhotoPicker/TLPhotoLibrary.swift

@@ -23,7 +23,7 @@ class TLPhotoLibrary {
     }()
     
     deinit {
-        NXLLog("deinit TLPhotoLibrary")
+        //        print("deinit TLPhotoLibrary")
     }
     
     @discardableResult

+ 55 - 0
RainbowPlanet/RainbowPlanet/Modules/PublishModule/PhotoPicker/TLPhotoPicker/TLPhotopickerProtocol.swift

@@ -0,0 +1,55 @@
+//
+//  TLPhotopickerDataSourcesProtocol.swift
+//  TLPhotoPicker
+//
+//  Created by wade.hawk on 21/01/2019.
+//
+
+import Foundation
+import Photos
+
+protocol TLPhotopickerDataSourcesProtocol {
+    func headerReferenceSize() -> CGSize
+    func footerReferenceSize() -> CGSize
+    func registerSupplementView(collectionView: UICollectionView)
+    func supplementIdentifier(kind: String) -> String
+    func configure(supplement view: UICollectionReusableView, section: (title: String, assets: [TLPHAsset]))
+}
+
+protocol TLPhotosPickerViewControllerDelegate: class {
+    func dismissPhotoPicker(withPHAssets: [PHAsset])
+    func dismissPhotoPicker(withTLPHAssets: [TLPHAsset])
+    func dismissComplete()
+    func photoPickerDidCancel()
+    func canSelectAsset(phAsset: PHAsset) -> Bool
+    func didExceedMaximumNumberOfSelection(picker: TLPhotosPickerViewController)
+    func handleNoAlbumPermissions(picker: TLPhotosPickerViewController)
+    func handleNoCameraPermissions(picker: TLPhotosPickerViewController)
+}
+
+extension TLPhotosPickerViewControllerDelegate {
+    public func deninedAuthoization() { }
+    public func dismissPhotoPicker(withPHAssets: [PHAsset]) { }
+    public func dismissPhotoPicker(withTLPHAssets: [TLPHAsset]) { }
+    public func dismissComplete() { }
+    public func photoPickerDidCancel() { }
+    public func canSelectAsset(phAsset: PHAsset) -> Bool { return true }
+    public func didExceedMaximumNumberOfSelection(picker: TLPhotosPickerViewController) { }
+    public func handleNoAlbumPermissions(picker: TLPhotosPickerViewController) { }
+    public func handleNoCameraPermissions(picker: TLPhotosPickerViewController) { }
+}
+
+//for log
+protocol TLPhotosPickerLogDelegate: class {
+    func selectedCameraCell(picker: TLPhotosPickerViewController)
+    func deselectedPhoto(picker: TLPhotosPickerViewController, at: Int)
+    func selectedPhoto(picker: TLPhotosPickerViewController, at: Int)
+    func selectedAlbum(picker: TLPhotosPickerViewController, title: String, at: Int)
+}
+
+extension TLPhotosPickerLogDelegate {
+    func selectedCameraCell(picker: TLPhotosPickerViewController) { }
+    func deselectedPhoto(picker: TLPhotosPickerViewController, at: Int) { }
+    func selectedPhoto(picker: TLPhotosPickerViewController, at: Int) { }
+    func selectedAlbum(picker: TLPhotosPickerViewController, collections: [TLAssetsCollection], at: Int) { }
+}

+ 203 - 197
RainbowPlanet/RainbowPlanet/Tools/PhotoPicker/TLPhotoPicker/TLPhotosPickerViewController.swift

@@ -10,25 +10,84 @@ import UIKit
 import Photos
 import PhotosUI
 import MobileCoreServices
+import JXSegmentedView
 
-open class TLPhotosPickerViewController: UIViewController {
-    @IBOutlet open var navigationBar: UINavigationBar!
-    @IBOutlet open var titleView: UIView!
-    @IBOutlet open var titleLabel: UILabel!
-    @IBOutlet open var subTitleStackView: UIStackView!
-    @IBOutlet open var subTitleLabel: UILabel!
-    @IBOutlet open var subTitleArrowImageView: UIImageView!
-    @IBOutlet open var albumPopView: TLAlbumPopView!
-    @IBOutlet open var collectionView: UICollectionView!
-    @IBOutlet open var indicator: UIActivityIndicatorView!
-    @IBOutlet open var popArrowImageView: UIImageView!
-    @IBOutlet open var customNavItem: UINavigationItem!
-    @IBOutlet open var doneButton: UIBarButtonItem!
-    @IBOutlet open var cancelButton: UIBarButtonItem!
-    @IBOutlet open var navigationBarTopConstraint: NSLayoutConstraint!
-    @IBOutlet open var emptyView: UIView!
-    @IBOutlet open var emptyImageView: UIImageView!
-    @IBOutlet open var emptyMessageLabel: UILabel!
+public struct TLPhotosPickerConfigure {
+    public var defaultCameraRollTitle = "Camera Roll"
+    public var tapHereToChange = "Tap here to change"
+    public var cancelTitle = "Cancel"
+    public var doneTitle = "Done"
+    public var emptyMessage = "No albums"
+    public var emptyImage: UIImage? = nil
+    public var usedCameraButton = true
+    public var usedPrefetch = false
+    public var allowedLivePhotos = true
+    public var allowedVideo = true
+    public var allowedAlbumCloudShared = false
+    public var allowedVideoRecording = true
+    public var recordingVideoQuality: UIImagePickerController.QualityType = .typeMedium
+    public var maxVideoDuration:TimeInterval? = nil
+    public var minSeconds:Int = 0
+    public var autoPlay = true
+    public var muteAudio = true
+    public var mediaType: PHAssetMediaType? = nil
+    public var numberOfColumn = 3
+    public var singleSelectedMode = false
+    public var maxSelectedAssets: Int? = nil
+    public var fetchOption: PHFetchOptions? = nil
+    public var fetchCollectionOption: [FetchCollectionType: PHFetchOptions] = [:]
+    public var selectedColor = kThemeColor
+    public var cameraBgColor = UIColor(red: 221/255, green: 223/255, blue: 226/255, alpha: 1)
+    public var cameraIcon = TLBundle.podBundleImage(named: "camera")
+    public var videoIcon = TLBundle.podBundleImage(named: "video")
+    public var placeholderIcon = TLBundle.podBundleImage(named: "insertPhotoMaterial")
+    public var nibSet: (nibName: String, bundle:Bundle)? = nil
+    public var cameraCellNibSet: (nibName: String, bundle:Bundle)? = nil
+    public var fetchCollectionTypes: [(PHAssetCollectionType,PHAssetCollectionSubtype)]? = nil
+    public var groupByFetch: PHFetchedResultGroupedBy? = nil
+    public var supportedInterfaceOrientations: UIInterfaceOrientationMask = .portrait
+    public var popup: [PopupConfigure] = []
+    public init() {
+        
+    }
+}
+
+public enum FetchCollectionType {
+    case assetCollections(PHAssetCollectionType)
+    case topLevelUserCollections
+}
+
+extension FetchCollectionType: Hashable {
+    private var identifier: String {
+        switch self {
+        case let .assetCollections(collectionType):
+            return "assetCollections\(collectionType.rawValue)"
+        case .topLevelUserCollections:
+            return "topLevelUserCollections"
+        }
+    }
+    
+    public func hash(into hasher: inout Hasher) {
+        hasher.combine(self.identifier)
+    }
+}
+
+public enum PopupConfigure {
+    case animation(TimeInterval)
+}
+
+public struct Platform {
+    public static var isSimulator: Bool {
+        return TARGET_OS_SIMULATOR != 0 // Use this line in Xcode 7 or newer
+    }
+}
+
+
+class TLPhotosPickerViewController: BaseViewController {
+    @IBOutlet var collectionView: UICollectionView!
+    @IBOutlet var indicator: UIActivityIndicatorView!
+    @IBOutlet var collectionViewBottomConstrain: NSLayoutConstraint!
+    @IBOutlet weak var topViewTopBottomConstrain: NSLayoutConstraint!
     
     public weak var delegate: TLPhotosPickerViewControllerDelegate? = nil
     public weak var logDelegate: TLPhotosPickerLogDelegate? = nil
@@ -36,6 +95,13 @@ open class TLPhotosPickerViewController: UIViewController {
     public var configure = TLPhotosPickerConfigure()
     public var customDataSouces: TLPhotopickerDataSourcesProtocol? = nil
     
+    public var selectIndexPath: IndexPath? = IndexPath(item: 0, section: 0)
+    fileprivate var isFirst = true
+    
+    var previewView : TLPhontoPreviewView?
+
+    
+    
     private var usedCameraButton: Bool {
         get {
             return self.configure.usedCameraButton
@@ -148,10 +214,6 @@ open class TLPhotosPickerViewController: UIViewController {
         if self.thumbnailSize == CGSize.zero {
             initItemSize()
         }
-        if #available(iOS 11.0, *) {
-        } else if self.navigationBarTopConstraint.constant == 0 {
-            self.navigationBarTopConstraint.constant = 20
-        }
     }
     
     override open func viewWillAppear(_ animated: Bool) {
@@ -215,7 +277,7 @@ extension TLPhotosPickerViewController {
             return
         }
         let count = CGFloat(self.configure.numberOfColumn)
-        let width = (self.view.frame.size.width-(5*(count-1)))/count
+        let width = (self.view.frame.size.width-(1*(count-1)))/count
         self.thumbnailSize = CGSize(width: width, height: width)
         layout.itemSize = self.thumbnailSize
         self.collectionView.collectionViewLayout = layout
@@ -223,7 +285,28 @@ extension TLPhotosPickerViewController {
         self.cameraImage = centerAtRect(image: self.configure.cameraIcon, rect: CGRect(x: 0, y: 0, width: width, height: width), bgColor: self.configure.cameraBgColor)
     }
     
+    
     @objc open func makeUI() {
+        let previewView = TLPhontoPreviewView(frame: CGRect(x: 0, y: kNavBarTotalHeight, width: kScreenWidth, height: kScreenWidth))
+        view.addSubview(previewView)
+        self.previewView = previewView
+        navigationBar.wr_setRightButton(title: "完成", titleColor: k999999Color)
+        navigationBar.wr_setBottomLineHidden(hidden: true)
+        self.topViewTopBottomConstrain.constant = kNavBarTotalHeight
+        self.collectionViewBottomConstrain.constant = -(kSafeTabBarHeight + 48)
+        /// 返回
+        navigationBar.onClickLeftButton = {
+            [weak self] in
+            self?.stopPlay()
+            self?.dismiss(done: false)
+        }
+        /// 完成
+        navigationBar.onClickRightButton = {
+            [weak self] in
+            self?.stopPlay()
+            self?.dismiss(done: true)
+        }
+        
         registerNib(nibName: "TLPhotoCollectionViewCell", bundle: TLBundle.bundle())
         if let nibSet = self.configure.nibSet {
             registerNib(nibName: nibSet.nibName, bundle: nibSet.bundle)
@@ -232,20 +315,6 @@ extension TLPhotosPickerViewController {
             registerNib(nibName: nibSet.nibName, bundle: nibSet.bundle)
         }
         self.indicator.startAnimating()
-        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(titleTap))
-        self.titleView.addGestureRecognizer(tapGesture)
-        self.titleLabel.text = self.configure.defaultCameraRollTitle
-        self.subTitleLabel.text = self.configure.tapHereToChange
-        self.cancelButton.title = self.configure.cancelTitle
-        self.doneButton.title = self.configure.doneTitle
-        self.doneButton.setTitleTextAttributes([NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: UIFont.labelFontSize)], for: .normal)
-        self.emptyView.isHidden = true
-        self.emptyImageView.image = self.configure.emptyImage
-        self.emptyMessageLabel.text = self.configure.emptyMessage
-        self.albumPopView.tableView.delegate = self
-        self.albumPopView.tableView.dataSource = self
-        self.popArrowImageView.image = TLBundle.podBundleImage(named: "pop_arrow")
-        self.subTitleArrowImageView.image = TLBundle.podBundleImage(named: "arrow")
         if #available(iOS 10.0, *), self.usedPrefetch {
             self.collectionView.isPrefetchingEnabled = true
             self.collectionView.prefetchDataSource = self
@@ -259,11 +328,6 @@ extension TLPhotosPickerViewController {
         self.customDataSouces?.registerSupplementView(collectionView: self.collectionView)
     }
     
-    private func updateTitle() {
-        guard self.focusedCollection != nil else { return }
-        self.titleLabel.text = self.focusedCollection?.title
-    }
-    
     private func reloadCollectionView() {
         guard self.focusedCollection != nil else {
             return
@@ -280,19 +344,6 @@ extension TLPhotosPickerViewController {
         }
     }
     
-    private func reloadTableView() {
-        let count = min(5, self.collections.count)
-        var frame = self.albumPopView.popupView.frame
-        frame.size.height = CGFloat(count * 75)
-        self.albumPopView.popupViewHeight.constant = CGFloat(count * 75)
-        UIView.animate(withDuration: self.albumPopView.show ? 0.1:0) {
-            self.albumPopView.popupView.frame = frame
-            self.albumPopView.setNeedsLayout()
-        }
-        self.albumPopView.tableView.reloadData()
-        self.albumPopView.setupPopupFrame()
-    }
-    
     private func initPhotoLibrary() {
         if PHPhotoLibrary.authorizationStatus() == .authorized {
             self.photoLibrary.delegate = self
@@ -318,22 +369,6 @@ extension TLPhotosPickerViewController {
         return self.collections[section].phAssetCollection
     }
     
-    private func focused(collection: TLAssetsCollection) {
-        func resetRequest() {
-            cancelAllImageAssets()
-        }
-        resetRequest()
-        self.collections[getfocusedIndex()].recentPosition = self.collectionView.contentOffset
-        var reloadIndexPaths = [IndexPath(row: getfocusedIndex(), section: 0)]
-        self.focusedCollection = collection
-        self.focusedCollection?.fetchResult = self.photoLibrary.fetchResult(collection: collection, configure: self.configure)
-        reloadIndexPaths.append(IndexPath(row: getfocusedIndex(), section: 0))
-        self.albumPopView.tableView.reloadRows(at: reloadIndexPaths, with: .none)
-        self.albumPopView.show(false, duration: self.configure.popup.duration)
-        self.updateTitle()
-        self.reloadCollectionView()
-        self.collectionView.contentOffset = collection.recentPosition
-    }
     
     private func cancelAllImageAssets() {
         self.requestIDs.forEach{ (indexPath, requestID) in
@@ -342,22 +377,6 @@ extension TLPhotosPickerViewController {
         self.requestIDs.removeAll()
     }
     
-    // User Action
-    @objc func titleTap() {
-        guard collections.count > 0 else { return }
-        self.albumPopView.show(self.albumPopView.isHidden, duration: self.configure.popup.duration)
-    }
-    
-    @IBAction open func cancelButtonTap() {
-        self.stopPlay()
-        self.dismiss(done: false)
-    }
-    
-    @IBAction open func doneButtonTap() {
-        self.stopPlay()
-        self.dismiss(done: true)
-    }
-    
     private func dismiss(done: Bool) {
         if done {
             #if swift(>=4.1)
@@ -376,10 +395,8 @@ extension TLPhotosPickerViewController {
             self.delegate?.photoPickerDidCancel()
             self.didCancel?()
         }
-        self.dismiss(animated: true) { [weak self] in
-            self?.delegate?.dismissComplete()
-            self?.dismissCompletion?()
-        }
+        self.delegate?.dismissComplete()
+        self.dismissCompletion?()
     }
     
     private func canSelect(phAsset: PHAsset) -> Bool {
@@ -394,7 +411,6 @@ extension TLPhotosPickerViewController {
     private func focusFirstCollection() {
         if self.focusedCollection == nil, let collection = self.collections.first {
             self.focusedCollection = collection
-            self.updateTitle()
             self.reloadCollectionView()
         }
     }
@@ -406,18 +422,12 @@ extension TLPhotosPickerViewController: TLPhotoLibraryDelegate {
         self.collections = [collection]
         self.focusFirstCollection()
         self.indicator.stopAnimating()
-        self.reloadTableView()
     }
     
     func loadCompleteAllCollection(collections: [TLAssetsCollection]) {
         self.collections = collections
         self.focusFirstCollection()
-        let isEmpty = self.collections.count == 0
-        self.subTitleStackView.isHidden = isEmpty
-        self.emptyView.isHidden = !isEmpty
-        self.emptyImageView.isHidden = self.emptyImageView.image == nil
         self.indicator.stopAnimating()
-        self.reloadTableView()
         self.registerChangeObserver()
     }
 }
@@ -672,7 +682,6 @@ extension TLPhotosPickerViewController: PHPhotoLibraryChangeObserver {
             }
             if let collection = self.focusedCollection {
                 self.collections[self.getfocusedIndex()] = collection
-                self.albumPopView.tableView.reloadRows(at: [IndexPath(row: self.getfocusedIndex(), section: 0)], with: .none)
             }
         }
     }
@@ -703,60 +712,79 @@ extension TLPhotosPickerViewController: UICollectionViewDelegate,UICollectionVie
     
     //Delegate
     open func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
-        guard let collection = self.focusedCollection, let cell = self.collectionView.cellForItem(at: indexPath) as? TLPhotoCollectionViewCell else { return }
-        let isCameraRow = collection.useCameraButton && indexPath.section == 0 && indexPath.row == 0
-        if isCameraRow {
-            if Platform.isSimulator {
-                print("not supported by the simulator.")
-                return
-            }else {
-                if self.configure.cameraCellNibSet?.nibName != nil {
-                    cell.selectedCell()
-                }else {
-                    showCameraIfAuthorized()
-                }
-                self.logDelegate?.selectedCameraCell(picker: self)
-                return
-            }
+        
+        guard let collection = self.focusedCollection else { return }
+        // 第一是否选择
+        if isFirst {
+            isFirst = false
         }
-        guard var asset = collection.getTLAsset(at: indexPath), let phAsset = asset.phAsset else { return }
-        cell.popScaleAnim()
-        if let index = self.selectedAssets.firstIndex(where: { $0.phAsset == asset.phAsset }) {
-        //deselect
-            self.logDelegate?.deselectedPhoto(picker: self, at: indexPath.row)
-            self.selectedAssets.remove(at: index)
-            #if swift(>=4.1)
-            self.selectedAssets = self.selectedAssets.enumerated().compactMap({ (offset,asset) -> TLPHAsset? in
-                var asset = asset
-                asset.selectedOrder = offset + 1
-                return asset
-            })
-            #else
-            self.selectedAssets = self.selectedAssets.enumerated().flatMap({ (offset,asset) -> TLPHAsset? in
-                var asset = asset
-                asset.selectedOrder = offset + 1
-                return asset
-            })
-            #endif
-            cell.selectedAsset = false
-            cell.stopPlay()
-            self.orderUpdateCells()
-            if self.playRequestID?.indexPath == indexPath {
-                stopPlay()
-            }
-        }else {
-        //select
-            self.logDelegate?.selectedPhoto(picker: self, at: indexPath.row)
-            guard !maxCheck() else { return }
-            guard canSelect(phAsset: phAsset) else { return }
-            asset.selectedOrder = self.selectedAssets.count + 1
-            self.selectedAssets.append(asset)
-            cell.selectedAsset = true
-            cell.orderLabel?.text = "\(asset.selectedOrder)"
-            if asset.type != .photo, self.configure.autoPlay {
-                playVideo(asset: asset, indexPath: indexPath)
-            }
+        guard let asset = collection.getTLAsset(at: indexPath) else { return }
+
+        if self.selectIndexPath != indexPath {
+            self.previewView?._asset = asset
         }
+        self.selectIndexPath = indexPath
+
+
+//        guard let collection = self.focusedCollection, let cell = self.collectionView.cellForItem(at: indexPath) as? TLPhotoCollectionViewCell else { return }
+
+//        if cell.noSelectedView!.isHidden {
+//            let isCameraRow = collection.useCameraButton && indexPath.section == 0 && indexPath.row == 0
+//            if isCameraRow {
+//                if Platform.isSimulator {
+//                    print("not supported by the simulator.")
+//                    return
+//                }else {
+//                    if self.configure.cameraCellNibSet?.nibName != nil {
+//                        cell.selectedCell()
+//                    }else {
+//                        showCameraIfAuthorized()
+//                    }
+//                    self.logDelegate?.selectedCameraCell(picker: self)
+//                    return
+//                }
+//            }
+//            guard var asset = collection.getTLAsset(at: indexPath), let phAsset = asset.phAsset else { return }
+        
+//            //点击动画
+//    //        cell.popScaleAnim()
+//            if let index = self.selectedAssets.firstIndex(where: { $0.phAsset == asset.phAsset }) {
+//            //deselect
+//                self.logDelegate?.deselectedPhoto(picker: self, at: indexPath.row)
+//                self.selectedAssets.remove(at: index)
+//                #if swift(>=4.1)
+//                self.selectedAssets = self.selectedAssets.enumerated().compactMap({ (offset,asset) -> TLPHAsset? in
+//                    var asset = asset
+//                    asset.selectedOrder = offset + 1
+//                    return asset
+//                })
+//                #else
+//                self.selectedAssets = self.selectedAssets.enumerated().flatMap({ (offset,asset) -> TLPHAsset? in
+//                    var asset = asset
+//                    asset.selectedOrder = offset + 1
+//                    return asset
+//                })
+//                #endif
+//                cell.selectedAsset = false
+//                cell.stopPlay()
+//                self.orderUpdateCells()
+//                if self.playRequestID?.indexPath == indexPath {
+//                    stopPlay()
+//                }
+//            }else {
+//            //select
+//                self.logDelegate?.selectedPhoto(picker: self, at: indexPath.row)
+//                guard !maxCheck() else { return }
+//                guard canSelect(phAsset: phAsset) else { return }
+//                asset.selectedOrder = self.selectedAssets.count + 1
+//                self.selectedAssets.append(asset)
+//                cell.selectedAsset = true
+//                cell.orderLabel?.text = "\(asset.selectedOrder)"
+//                if asset.type != .photo, self.configure.autoPlay {
+//                    playVideo(asset: asset, indexPath: indexPath)
+//                }
+//            }
+//        }
     }
     
     open func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
@@ -820,6 +848,11 @@ extension TLPhotosPickerViewController: UICollectionViewDelegate,UICollectionVie
                             if self.allowedVideo {
                                 cell?.durationView?.isHidden = asset.type != .video
                                 cell?.duration = asset.type == .video ? phAsset.duration : nil
+                                if lround(phAsset.duration) < self.configure.minSeconds &&  cell?.durationView?.isHidden == false {
+                                    cell?.noSelectedView?.isHidden = false
+                                }else {
+                                    cell?.noSelectedView?.isHidden = true
+                                }
                             }
                             if complete {
                                 self.requestIDs.removeValue(forKey: indexPath)
@@ -839,8 +872,13 @@ extension TLPhotosPickerViewController: UICollectionViewDelegate,UICollectionVie
                                 cell?.imageView?.image = image
                                 cell?.update(with: phAsset)
                                 if self.allowedVideo {
-                                    cell?.durationView?.isHidden = asset.type != .video
-                                    cell?.duration = asset.type == .video ? phAsset.duration : nil
+                                    cell?.durationView?.isHidden = (asset.type != .video)
+                                    cell?.duration = (asset.type == .video) ? phAsset.duration : nil
+                                    if lround(phAsset.duration) < self.configure.minSeconds &&  cell?.durationView?.isHidden == false {
+                                        cell?.noSelectedView?.isHidden = false
+                                    }else {
+                                        cell?.noSelectedView?.isHidden = true
+                                    }
                                 }
                                 if complete {
                                     self.requestIDs.removeValue(forKey: indexPath)
@@ -862,6 +900,11 @@ extension TLPhotosPickerViewController: UICollectionViewDelegate,UICollectionVie
         UIView.transition(with: cell, duration: 0.1, options: .curveEaseIn, animations: {
             cell.alpha = 1
         }, completion: nil)
+        if indexPath.row == 0 && isFirst {
+            cell.isSelected = true
+            self.collectionView.selectItem(at: self.selectIndexPath, animated: false, scrollPosition: UICollectionView.ScrollPosition.top)
+            self.previewView?._asset = asset
+        }
         return cell
     }
     
@@ -930,6 +973,7 @@ extension TLPhotosPickerViewController: UICollectionViewDelegate,UICollectionVie
             }
         }
     }
+    
 }
 
 // MARK: - CustomDataSources for supplementary view
@@ -962,51 +1006,13 @@ extension TLPhotosPickerViewController: UICollectionViewDelegateFlowLayout {
     }
 }
 
-// MARK: - UITableView datasource & delegate
-extension TLPhotosPickerViewController: UITableViewDelegate,UITableViewDataSource {
-    //delegate
-    open func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
-        self.logDelegate?.selectedAlbum(picker: self, title: self.collections[indexPath.row].title, at: indexPath.row)
-        self.focused(collection: self.collections[indexPath.row])
+// MARK: - JXSegmentedDelegate
+extension TLPhotosPickerViewController : JXSegmentedListContainerViewListDelegate {
+    public func listView() -> UIView {
+        return view
     }
-    
-    //datasource
-    open func numberOfSections(in tableView: UITableView) -> Int {
-        return 1
-    }
-    
-    open func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
-        return self.collections.count
-    }
-    
-    open func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
-        let cell = tableView.dequeueReusableCell(withIdentifier: "TLCollectionTableViewCell", for: indexPath) as! TLCollectionTableViewCell
-        let collection = self.collections[indexPath.row]
-        cell.titleLabel.text = collection.title
-        cell.subTitleLabel.text = "\(collection.fetchResult?.count ?? 0)"
-        if let phAsset = collection.getAsset(at: collection.useCameraButton ? 1 : 0) {
-            let scale = UIScreen.main.scale
-            let size = CGSize(width: 80*scale, height: 80*scale)
-            self.photoLibrary.imageAsset(asset: phAsset, size: size, completionBlock: { [weak cell] (image,complete) in
-                DispatchQueue.main.async {
-                    cell?.thumbImageView.image = image
-                }
-            })
-        }
-        cell.accessoryType = getfocusedIndex() == indexPath.row ? .checkmark : .none
-        cell.selectionStyle = .none
-        return cell
+    public func listDidAppear() {
     }
-}
-
-extension Array where Element == PopupConfigure {
-    var duration: TimeInterval {
-        var result: TimeInterval = 0.1
-        self.compactMap{ $0 as? PopupConfigure }.forEach{
-            if case let .animation(duration) = $0 {
-                result = duration
-            }
-        }
-        return result
+    public func listDidDisappear() {
     }
 }

+ 53 - 0
RainbowPlanet/RainbowPlanet/Modules/PublishModule/PhotoPicker/TLPhotoPickerResources/CustomCameraCell.xib

@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="13196" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
+    <device id="retina4_7" orientation="portrait">
+        <adaptation id="fullscreen"/>
+    </device>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13174"/>
+        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </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="CustomCameraCell" id="yXg-PX-cBI" userLabel="CustomCameraCell" customClass="CustomCameraCell" customModule="TLPhotoPicker_Example" customModuleProvider="target">
+            <rect key="frame" x="0.0" y="0.0" width="100" height="100"/>
+            <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+            <view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
+                <rect key="frame" x="0.0" y="0.0" width="100" height="100"/>
+                <autoresizingMask key="autoresizingMask"/>
+                <subviews>
+                    <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="OEa-vx-nyF" customClass="PreviewView" customModule="TLPhotoPicker_Example" customModuleProvider="target">
+                        <rect key="frame" x="0.0" y="0.0" width="100" height="100"/>
+                        <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
+                    </view>
+                    <imageView userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="100" translatesAutoresizingMaskIntoConstraints="NO" id="IbX-QH-EmX">
+                        <rect key="frame" x="24.5" y="37" width="50" height="25"/>
+                        <constraints>
+                            <constraint firstAttribute="width" constant="50" id="WeH-wk-mnf"/>
+                            <constraint firstAttribute="height" constant="25" id="fg0-xR-Kit"/>
+                        </constraints>
+                    </imageView>
+                </subviews>
+            </view>
+            <constraints>
+                <constraint firstAttribute="trailing" secondItem="OEa-vx-nyF" secondAttribute="trailing" id="1q8-NV-mi4"/>
+                <constraint firstAttribute="bottom" secondItem="OEa-vx-nyF" secondAttribute="bottom" id="8M9-xE-Sfw"/>
+                <constraint firstItem="IbX-QH-EmX" firstAttribute="centerX" secondItem="sl5-A7-gYS" secondAttribute="centerX" id="PGI-5k-d7B"/>
+                <constraint firstItem="OEa-vx-nyF" firstAttribute="top" secondItem="yXg-PX-cBI" secondAttribute="top" id="TFO-Hn-Zvg"/>
+                <constraint firstItem="OEa-vx-nyF" firstAttribute="leading" secondItem="yXg-PX-cBI" secondAttribute="leading" id="aPC-Pg-0LQ"/>
+                <constraint firstItem="IbX-QH-EmX" firstAttribute="centerY" secondItem="sl5-A7-gYS" secondAttribute="centerY" id="bQT-vE-AZ8"/>
+            </constraints>
+            <viewLayoutGuide key="safeArea" id="sl5-A7-gYS"/>
+            <connections>
+                <outlet property="previewView" destination="OEa-vx-nyF" id="egv-bz-BnD"/>
+            </connections>
+            <point key="canvasLocation" x="32" y="-10"/>
+        </collectionViewCell>
+    </objects>
+    <resources>
+        <image name="100" width="50" height="50"/>
+    </resources>
+</document>

RainbowPlanet/RainbowPlanet/Tools/PhotoPicker/TLPhotoPickerResources/TLCollectionTableViewCell.xib → RainbowPlanet/RainbowPlanet/Modules/PublishModule/PhotoPicker/TLPhotoPickerResources/TLCollectionTableViewCell.xib


+ 40 - 34
RainbowPlanet/RainbowPlanet/Tools/PhotoPicker/TLPhotoPickerResources/TLPhotoCollectionViewCell.xib

@@ -1,17 +1,17 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="12120" systemVersion="16E195" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
     <device id="retina4_7" orientation="portrait">
         <adaptation id="fullscreen"/>
     </device>
     <dependencies>
         <deployment identifier="iOS"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12088"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14490.49"/>
         <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
     </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="TLPhotoCollectionViewCell" id="IF3-4e-v0j" customClass="TLPhotoCollectionViewCell" customModule="TLPhotoPicker" customModuleProvider="target">
+        <collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="TLPhotoCollectionViewCell" id="IF3-4e-v0j" customClass="TLPhotoCollectionViewCell" customModule="RainbowPlanet" customModuleProvider="target">
             <rect key="frame" x="0.0" y="0.0" width="100" height="100"/>
             <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
             <view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
@@ -33,41 +33,37 @@
                             <constraint firstAttribute="height" constant="25" id="XvY-Ee-EA2"/>
                         </constraints>
                     </imageView>
-                    <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="apl-2Q-Hz7" customClass="TLPlayerView" customModule="TLPhotoPicker" customModuleProvider="target">
+                    <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="apl-2Q-Hz7" customClass="TLPlayerView" customModule="RainbowPlanet" customModuleProvider="target">
                         <rect key="frame" x="0.0" y="0.0" width="100" height="100"/>
                         <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
                     </view>
-                    <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="d1a-KW-Ta4">
-                        <rect key="frame" x="-5" y="-5" width="110" height="110"/>
+                    <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="hbA-dR-I09">
+                        <rect key="frame" x="72" y="6" width="22" height="22"/>
                         <subviews>
-                            <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="hbA-dR-I09">
-                                <rect key="frame" x="75" y="5" width="30" height="30"/>
-                                <subviews>
-                                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="1" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Weu-ef-IZ5">
-                                        <rect key="frame" x="1.5" y="8" width="25" height="16"/>
-                                        <constraints>
-                                            <constraint firstAttribute="width" relation="greaterThanOrEqual" constant="25" id="YMX-0Z-bfm"/>
-                                        </constraints>
-                                        <fontDescription key="fontDescription" type="system" weight="semibold" pointSize="13"/>
-                                        <color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
-                                        <nil key="highlightedColor"/>
-                                    </label>
-                                </subviews>
-                                <color key="backgroundColor" red="0.27843137254901962" green="0.47058823529411764" blue="0.85098039215686272" alpha="1" colorSpace="calibratedRGB"/>
+                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="1" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Weu-ef-IZ5">
+                                <rect key="frame" x="0.0" y="0.0" width="22" height="22"/>
                                 <constraints>
-                                    <constraint firstAttribute="height" constant="30" id="8ln-g5-eHL"/>
-                                    <constraint firstItem="Weu-ef-IZ5" firstAttribute="leading" secondItem="hbA-dR-I09" secondAttribute="leading" constant="1.5" id="Yw3-zp-UZQ"/>
-                                    <constraint firstAttribute="trailing" secondItem="Weu-ef-IZ5" secondAttribute="trailing" constant="3.5" id="jsL-aw-IED"/>
-                                    <constraint firstItem="Weu-ef-IZ5" firstAttribute="centerY" secondItem="hbA-dR-I09" secondAttribute="centerY" constant="1" id="nUh-b3-s9s"/>
+                                    <constraint firstAttribute="width" constant="22" id="YMX-0Z-bfm"/>
                                 </constraints>
-                            </view>
+                                <fontDescription key="fontDescription" type="system" weight="semibold" pointSize="13"/>
+                                <color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
+                                <nil key="highlightedColor"/>
+                            </label>
                         </subviews>
-                        <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
+                        <color key="backgroundColor" red="0.27843137254901962" green="0.47058823529411764" blue="0.85098039215686272" alpha="1" colorSpace="calibratedRGB"/>
                         <constraints>
-                            <constraint firstAttribute="trailing" secondItem="hbA-dR-I09" secondAttribute="trailing" constant="5" id="hjj-HC-A4B"/>
-                            <constraint firstItem="hbA-dR-I09" firstAttribute="top" secondItem="d1a-KW-Ta4" secondAttribute="top" constant="5" id="xJ1-j7-RX7"/>
+                            <constraint firstAttribute="bottom" secondItem="Weu-ef-IZ5" secondAttribute="bottom" id="7bq-sF-B2u"/>
+                            <constraint firstAttribute="width" constant="22" id="Hod-zO-nZN"/>
+                            <constraint firstAttribute="trailing" secondItem="Weu-ef-IZ5" secondAttribute="trailing" id="KAX-uN-lIv"/>
+                            <constraint firstAttribute="height" constant="22" id="QIN-2H-KTL"/>
+                            <constraint firstItem="Weu-ef-IZ5" firstAttribute="top" secondItem="hbA-dR-I09" secondAttribute="top" id="Yiz-Jt-Vx2"/>
+                            <constraint firstItem="Weu-ef-IZ5" firstAttribute="leading" secondItem="hbA-dR-I09" secondAttribute="leading" id="sXm-jF-nJk"/>
                         </constraints>
                     </view>
+                    <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="d1a-KW-Ta4">
+                        <rect key="frame" x="0.0" y="0.0" width="100" height="100"/>
+                        <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
+                    </view>
                     <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="aju-ob-KlZ">
                         <rect key="frame" x="0.0" y="75" width="100" height="25"/>
                         <subviews>
@@ -94,6 +90,10 @@
                             <constraint firstAttribute="trailing" secondItem="zNx-FC-5V2" secondAttribute="trailing" constant="5" id="uhl-Y8-3g5"/>
                         </constraints>
                     </view>
+                    <view hidden="YES" userInteractionEnabled="NO" alpha="0.69999999999999996" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="FEL-h5-jvm">
+                        <rect key="frame" x="0.0" y="0.0" width="100" height="100"/>
+                        <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                    </view>
                     <activityIndicatorView hidden="YES" opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" hidesWhenStopped="YES" style="gray" translatesAutoresizingMaskIntoConstraints="NO" id="DZc-ag-e55">
                         <rect key="frame" x="40" y="40" width="20" height="20"/>
                     </activityIndicatorView>
@@ -107,6 +107,7 @@
                 <constraint firstAttribute="trailing" secondItem="0cR-fZ-1bW" secondAttribute="trailing" id="9sd-Ea-EBO"/>
                 <constraint firstAttribute="trailing" secondItem="vfk-Ao-TKR" secondAttribute="trailing" id="BZ0-ZG-uW5"/>
                 <constraint firstAttribute="bottom" secondItem="TGh-wt-hcR" secondAttribute="bottom" constant="5" id="Ba1-Z6-ypz"/>
+                <constraint firstAttribute="trailing" secondItem="hbA-dR-I09" secondAttribute="trailing" constant="6" id="CKZ-Dp-2w9"/>
                 <constraint firstItem="0cR-fZ-1bW" firstAttribute="leading" secondItem="IF3-4e-v0j" secondAttribute="leading" id="DXe-M9-mxX"/>
                 <constraint firstItem="aju-ob-KlZ" firstAttribute="leading" secondItem="IF3-4e-v0j" secondAttribute="leading" id="FDl-UE-XVM"/>
                 <constraint firstItem="apl-2Q-Hz7" firstAttribute="top" secondItem="IF3-4e-v0j" secondAttribute="top" id="JlA-ya-cf3"/>
@@ -114,14 +115,19 @@
                 <constraint firstAttribute="trailing" secondItem="TGh-wt-hcR" secondAttribute="trailing" constant="5" id="Meo-q5-HyZ"/>
                 <constraint firstItem="vfk-Ao-TKR" firstAttribute="leading" secondItem="IF3-4e-v0j" secondAttribute="leading" id="NOQ-KU-fHD"/>
                 <constraint firstItem="vfk-Ao-TKR" firstAttribute="top" secondItem="IF3-4e-v0j" secondAttribute="top" id="NrV-wc-c3q"/>
-                <constraint firstItem="d1a-KW-Ta4" firstAttribute="height" secondItem="IF3-4e-v0j" secondAttribute="height" constant="10" id="VMJ-Qp-D4N"/>
+                <constraint firstAttribute="bottom" secondItem="FEL-h5-jvm" secondAttribute="bottom" id="OHo-QO-DqX"/>
+                <constraint firstItem="FEL-h5-jvm" firstAttribute="top" secondItem="IF3-4e-v0j" secondAttribute="top" id="UZE-HD-qV4"/>
+                <constraint firstItem="d1a-KW-Ta4" firstAttribute="height" secondItem="IF3-4e-v0j" secondAttribute="height" id="VMJ-Qp-D4N"/>
                 <constraint firstItem="apl-2Q-Hz7" firstAttribute="leading" secondItem="IF3-4e-v0j" secondAttribute="leading" id="bsL-0J-0Y5"/>
-                <constraint firstItem="d1a-KW-Ta4" firstAttribute="width" secondItem="IF3-4e-v0j" secondAttribute="width" constant="10" id="clS-DI-jvL"/>
-                <constraint firstItem="d1a-KW-Ta4" firstAttribute="top" secondItem="IF3-4e-v0j" secondAttribute="top" constant="-5" id="d3r-HZ-6We"/>
+                <constraint firstItem="d1a-KW-Ta4" firstAttribute="width" secondItem="IF3-4e-v0j" secondAttribute="width" id="clS-DI-jvL"/>
+                <constraint firstItem="hbA-dR-I09" firstAttribute="top" secondItem="IF3-4e-v0j" secondAttribute="top" constant="6" id="cox-pe-Udx"/>
+                <constraint firstItem="d1a-KW-Ta4" firstAttribute="top" secondItem="IF3-4e-v0j" secondAttribute="top" id="d3r-HZ-6We"/>
                 <constraint firstItem="DZc-ag-e55" firstAttribute="centerX" secondItem="IF3-4e-v0j" secondAttribute="centerX" id="fnn-1c-fSn"/>
+                <constraint firstAttribute="trailing" secondItem="FEL-h5-jvm" secondAttribute="trailing" id="jTi-pR-jF5"/>
                 <constraint firstItem="DZc-ag-e55" firstAttribute="centerY" secondItem="IF3-4e-v0j" secondAttribute="centerY" id="qZc-2h-nOx"/>
-                <constraint firstItem="d1a-KW-Ta4" firstAttribute="leading" secondItem="IF3-4e-v0j" secondAttribute="leading" constant="-5" id="sOj-ms-Oo3"/>
+                <constraint firstItem="d1a-KW-Ta4" firstAttribute="leading" secondItem="IF3-4e-v0j" secondAttribute="leading" id="sOj-ms-Oo3"/>
                 <constraint firstItem="0cR-fZ-1bW" firstAttribute="top" secondItem="IF3-4e-v0j" secondAttribute="top" id="sSC-fd-MoT"/>
+                <constraint firstItem="FEL-h5-jvm" firstAttribute="leading" secondItem="IF3-4e-v0j" secondAttribute="leading" id="sYJ-Ey-xX3"/>
                 <constraint firstAttribute="bottom" secondItem="0cR-fZ-1bW" secondAttribute="bottom" id="xzA-tS-EVK"/>
             </constraints>
             <connections>
@@ -131,14 +137,14 @@
                 <outlet property="indicator" destination="DZc-ag-e55" id="R3y-XL-0SY"/>
                 <outlet property="liveBadgeImageView" destination="TGh-wt-hcR" id="cry-3P-rLI"/>
                 <outlet property="livePhotoView" destination="vfk-Ao-TKR" id="uvj-l1-wcp"/>
+                <outlet property="noSelectedView" destination="FEL-h5-jvm" id="tdZ-CE-7W2"/>
                 <outlet property="orderBgView" destination="hbA-dR-I09" id="cQo-BP-xh1"/>
                 <outlet property="orderLabel" destination="Weu-ef-IZ5" id="B3t-X5-o3a"/>
                 <outlet property="playerView" destination="apl-2Q-Hz7" id="vTI-ie-mcV"/>
-                <outlet property="selectedHeight" destination="VMJ-Qp-D4N" id="uVe-tQ-4q5"/>
                 <outlet property="selectedView" destination="d1a-KW-Ta4" id="c31-4y-72g"/>
                 <outlet property="videoIconImageView" destination="Uzf-HJ-aUY" id="d7e-Bl-181"/>
             </connections>
-            <point key="canvasLocation" x="32" y="-10"/>
+            <point key="canvasLocation" x="32" y="-10.794602698650676"/>
         </collectionViewCell>
     </objects>
 </document>

二进制
RainbowPlanet/RainbowPlanet/Modules/PublishModule/PhotoPicker/TLPhotoPickerResources/TLPhotoPickerController.bundle/arrow.png


RainbowPlanet/RainbowPlanet/Tools/PhotoPicker/TLPhotoPickerResources/TLPhotoPickerController.bundle/camera@3x.png → RainbowPlanet/RainbowPlanet/Modules/PublishModule/PhotoPicker/TLPhotoPickerResources/TLPhotoPickerController.bundle/camera@3x.png


RainbowPlanet/RainbowPlanet/Tools/PhotoPicker/TLPhotoPickerResources/TLPhotoPickerController.bundle/insertPhotoMaterial@3x.png → RainbowPlanet/RainbowPlanet/Modules/PublishModule/PhotoPicker/TLPhotoPickerResources/TLPhotoPickerController.bundle/insertPhotoMaterial@3x.png


二进制
RainbowPlanet/RainbowPlanet/Modules/PublishModule/PhotoPicker/TLPhotoPickerResources/TLPhotoPickerController.bundle/pop_arrow.png


二进制
RainbowPlanet/RainbowPlanet/Modules/PublishModule/PhotoPicker/TLPhotoPickerResources/TLPhotoPickerController.bundle/video.png


+ 68 - 0
RainbowPlanet/RainbowPlanet/Modules/PublishModule/PhotoPicker/TLPhotoPickerResources/TLPhotosPickerViewController.xib

@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
+    <device id="retina4_7" orientation="portrait">
+        <adaptation id="fullscreen"/>
+    </device>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14490.49"/>
+        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="TLPhotosPickerViewController" customModule="RainbowPlanet" customModuleProvider="target">
+            <connections>
+                <outlet property="collectionView" destination="4gR-Bn-quP" id="ZOF-qU-cpd"/>
+                <outlet property="collectionViewBottomConstrain" destination="qqE-w2-Tsc" id="FS3-hV-la8"/>
+                <outlet property="indicator" destination="AEv-G6-dRI" id="coA-3n-07e"/>
+                <outlet property="topViewTopBottomConstrain" destination="cal-KK-WHJ" id="XNx-1u-FWw"/>
+                <outlet property="view" destination="Zyk-dI-msE" id="dxK-gh-unF"/>
+            </connections>
+        </placeholder>
+        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
+        <view contentMode="scaleToFill" id="Zyk-dI-msE">
+            <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
+            <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+            <subviews>
+                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="86M-sc-XP7">
+                    <rect key="frame" x="0.0" y="0.0" width="375" height="375"/>
+                    <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                    <constraints>
+                        <constraint firstAttribute="width" secondItem="86M-sc-XP7" secondAttribute="height" multiplier="1:1" id="Pwg-oc-6sf"/>
+                    </constraints>
+                </view>
+                <collectionView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" dataMode="prototypes" translatesAutoresizingMaskIntoConstraints="NO" id="4gR-Bn-quP">
+                    <rect key="frame" x="0.0" y="375" width="375" height="292"/>
+                    <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
+                    <collectionViewFlowLayout key="collectionViewLayout" minimumLineSpacing="1" minimumInteritemSpacing="1" id="VDa-Pp-VBq">
+                        <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>
+                    <connections>
+                        <outlet property="dataSource" destination="-1" id="6fE-SF-z6F"/>
+                        <outlet property="delegate" destination="-1" id="pjZ-sM-fyY"/>
+                    </connections>
+                </collectionView>
+                <activityIndicatorView hidden="YES" opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" hidesWhenStopped="YES" style="gray" translatesAutoresizingMaskIntoConstraints="NO" id="AEv-G6-dRI">
+                    <rect key="frame" x="177.5" y="323.5" width="20" height="20"/>
+                </activityIndicatorView>
+            </subviews>
+            <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+            <constraints>
+                <constraint firstItem="AEv-G6-dRI" firstAttribute="centerX" secondItem="Zyk-dI-msE" secondAttribute="centerX" id="44C-fd-MVc"/>
+                <constraint firstItem="86M-sc-XP7" firstAttribute="leading" secondItem="HLR-WT-D3I" secondAttribute="leading" id="6om-vh-bwT"/>
+                <constraint firstItem="4gR-Bn-quP" firstAttribute="top" secondItem="86M-sc-XP7" secondAttribute="bottom" id="LPA-2k-jcU"/>
+                <constraint firstAttribute="trailing" secondItem="4gR-Bn-quP" secondAttribute="trailing" id="M6b-2G-2m1"/>
+                <constraint firstItem="AEv-G6-dRI" firstAttribute="centerY" secondItem="Zyk-dI-msE" secondAttribute="centerY" id="aLU-u9-ALA"/>
+                <constraint firstItem="86M-sc-XP7" firstAttribute="top" secondItem="Zyk-dI-msE" secondAttribute="top" id="cal-KK-WHJ"/>
+                <constraint firstItem="HLR-WT-D3I" firstAttribute="trailing" secondItem="86M-sc-XP7" secondAttribute="trailing" id="iA9-TJ-fym"/>
+                <constraint firstItem="4gR-Bn-quP" firstAttribute="leading" secondItem="Zyk-dI-msE" secondAttribute="leading" id="kb7-vy-yTu"/>
+                <constraint firstItem="4gR-Bn-quP" firstAttribute="bottom" secondItem="Zyk-dI-msE" secondAttribute="bottom" id="qqE-w2-Tsc"/>
+            </constraints>
+            <viewLayoutGuide key="safeArea" id="HLR-WT-D3I"/>
+            <point key="canvasLocation" x="32.799999999999997" y="52.623688155922046"/>
+        </view>
+    </objects>
+</document>

+ 0 - 124
RainbowPlanet/RainbowPlanet/Modules/PublishModule/PublishMediaPicker/ViewController/PublishMediaPickerViewController.swift

@@ -1,124 +0,0 @@
-//
-//  PublishMediaPickerViewController.swift
-//  RainbowPlanet
-//
-//  Created by 南鑫林 on 2019/8/23.
-//  Copyright © 2019 RainbowPlanet. All rights reserved.
-//
-
-import UIKit
-import JXSegmentedView
-import Photos
-import PhotosUI
-import MobileCoreServices
-
-//public protocol PublishMediaPickerViewControllerDelegate: class {
-//    func dismissPhotoPicker(withPHAssets: [PHAsset])
-//    func dismissPhotoPicker(withTLPHAssets: [TLPHAsset])
-//    func dismissComplete()
-//    func photoPickerDidCancel()
-//    func canSelectAsset(phAsset: PHAsset) -> Bool
-//    func didExceedMaximumNumberOfSelection(picker: PublishMediaPickerViewController)
-//    func handleNoAlbumPermissions(picker: PublishMediaPickerViewController)
-//    func handleNoCameraPermissions(picker: PublishMediaPickerViewController)
-//}
-//
-//extension PublishMediaPickerViewControllerDelegate {
-//    public func deninedAuthoization() { }
-//    public func dismissPhotoPicker(withPHAssets: [PHAsset]) { }
-//    public func dismissPhotoPicker(withTLPHAssets: [TLPHAsset]) { }
-//    public func dismissComplete() { }
-//    public func photoPickerDidCancel() { }
-//    public func canSelectAsset(phAsset: PHAsset) -> Bool { return true }
-//    public func didExceedMaximumNumberOfSelection(picker: PublishMediaPickerViewController) { }
-//    public func handleNoAlbumPermissions(picker: PublishMediaPickerViewController) { }
-//    public func handleNoCameraPermissions(picker: PublishMediaPickerViewController) { }
-//}
-//
-////for log
-//public protocol PublishMediaPickerLogDelegate: class {
-//    func selectedCameraCell(picker: PublishMediaPickerViewController)
-//    func deselectedPhoto(picker: PublishMediaPickerViewController, at: Int)
-//    func selectedPhoto(picker: PublishMediaPickerViewController, at: Int)
-//    func selectedAlbum(picker: PublishMediaPickerViewController, title: String, at: Int)
-//}
-//
-//extension PublishMediaPickerLogDelegate {
-//    func selectedCameraCell(picker: PublishMediaPickerViewController) { }
-//    func deselectedPhoto(picker: PublishMediaPickerViewController, at: Int) { }
-//    func selectedPhoto(picker: PublishMediaPickerViewController, at: Int) { }
-//    func selectedAlbum(picker: PublishMediaPickerViewController, collections: [TLAssetsCollection], at: Int) { }
-//}
-
-class PublishMediaPickerViewController: BaseViewController {
-    
-    deinit {
-        NXLLog("deinit")
-    }
-    
-    /// 最大视频个数
-    var maxVideoCount: UInt? = nil
-    /// 最大图片个数
-    var maxPictureCount: UInt? = nil
-    
-    /// 返回
-    typealias DismissClosure = () -> Void
-    var dismissClosure: DismissClosure?
-    
-    /// 完成
-    typealias CompleteClosure = () -> Void
-    var completeClosure: CompleteClosure?
-
-    override func viewDidLoad() {
-        super.viewDidLoad()
-        setupViews()
-        setupLayouts()
-        setupData()
-    }
-    
-    override func setupViews() {
-        navigationBar.wr_setRightButton(title: "完成", titleColor: k999999Color)
-    }
-    
-    override func setupLayouts() {
-        
-    }
-    
-    override func setupData() {
-        /// 返回
-        navigationBar.onClickLeftButton = {
-            [weak self] in
-            if let dismissClosure = self?.dismissClosure {
-                dismissClosure()
-            }
-        }
-        /// 完成
-        navigationBar.onClickRightButton = {
-            [weak self] in
-            if let completeClosure = self?.completeClosure {
-                completeClosure()
-            }
-        }
-    }
-    
-//    lazy var <#property name#>: <#type name#> = {
-//        <#statements#>
-//        return <#value#>
-//    }()
-    
-    
-
-}
-
-// MARK: - JXSegmentedDelegate
-extension PublishMediaPickerViewController : JXSegmentedListContainerViewListDelegate {
-    public func listView() -> UIView {
-        return view
-    }
-    public func listDidAppear() {
-//        (view as! KSMediaPickerView).previewView.videoPlay()
-    }
-    public func listDidDisappear() {
-//        (view as! KSMediaPickerView).previewView.videoPause()
-    }
-}

+ 158 - 24
RainbowPlanet/RainbowPlanet/Modules/PublishModule/PublishViewController.swift

@@ -47,6 +47,8 @@ class PublishViewController: BaseViewController {
         return cropMediaConfig!
     }
     
+    var selectedAssets = [TLPHAsset]()
+    
     override func viewDidLoad() {
         super.viewDidLoad()
         setupViews()
@@ -207,34 +209,36 @@ extension PublishViewController :JXSegmentedListContainerViewDataSource {
     func listContainerView(_ listContainerView: JXSegmentedListContainerView, initListAt index: Int) -> JXSegmentedListContainerViewListDelegate {
         switch index {
         case 0:
-            let mediaVc = KSMediaPickerController(maxVideoItemCount: 1, maxPictureItemCount: 9)
-            mediaVc.dismissClosure = {
-                [weak self] in
-                self?.dismiss(animated: true, completion: nil)
-            }
-            mediaVc.cropClosure = {
-                [weak self] (vItemModel) in
-                self?.getAvUrlAssetAndCrop(vItemModel)
-            }
-            mediaVc.pubImgClosure = {
-                [weak self] (imageArray) in
-                let pubVc = PublishEditController()
-                pubVc.imageArr = imageArray
-                self?.navigationController?.pushViewController(pubVc, animated: true)
-            }
-            return mediaVc
-//            let publishMediaPickerVC = PublishMediaPickerViewController()
-//            publishMediaPickerVC.maxVideoCount = 1
-//            publishMediaPickerVC.maxPictureCount = 9
-//            publishMediaPickerVC.dismissClosure = {
+//            let mediaVc = KSMediaPickerController(maxVideoItemCount: 1, maxPictureItemCount: 9)
+//            mediaVc.dismissClosure = {
 //                [weak self] in
 //                self?.dismiss(animated: true, completion: nil)
 //            }
-//            publishMediaPickerVC.completeClosure = {
-//
+//            mediaVc.cropClosure = {
+//                [weak self] (vItemModel) in
+//                self?.getAvUrlAssetAndCrop(vItemModel)
 //            }
-//
-//            return publishMediaPickerVC
+//            mediaVc.pubImgClosure = {
+//                [weak self] (imageArray) in
+//                let pubVc = PublishEditController()
+//                pubVc.imageArr = imageArray
+//                self?.navigationController?.pushViewController(pubVc, animated: true)
+//            }
+//            return mediaVc
+            let publishMediaPickerVC = TLPhotosPickerViewController()
+            publishMediaPickerVC.delegate = self
+            publishMediaPickerVC.didExceedMaximumNumberOfSelection = { [weak self] (picker) in
+//                self?.showExceededMaximumAlert(vc: picker)
+            }
+            var configure = TLPhotosPickerConfigure()
+            configure.numberOfColumn = 4
+            configure.usedCameraButton = false
+            configure.maxSelectedAssets = 9
+            configure.minSeconds = 3
+            publishMediaPickerVC.configure = configure
+            publishMediaPickerVC.selectedAssets = self.selectedAssets
+            publishMediaPickerVC.logDelegate = self
+            return publishMediaPickerVC
         case 1:
             let videoVc = AliyunMagicCameraViewController()
             videoVc.quVideo = mediaConfig
@@ -286,6 +290,136 @@ extension PublishViewController :JXSegmentedListContainerViewDataSource {
     }
 }
 
+extension PublishViewController: TLPhotosPickerViewControllerDelegate {
+    func deninedAuthoization() {
+        
+    }
+    func dismissPhotoPicker(withPHAssets: [PHAsset]) {
+        self.dismiss(animated: true, completion: nil)
+    }
+    func dismissPhotoPicker(withTLPHAssets: [TLPHAsset]) {
+        // use selected order, fullresolution image
+        self.selectedAssets = withTLPHAssets
+        getFirstSelectedImage()
+        //iCloud or video
+        //        getAsyncCopyTemporaryFile()
+    }
+    func dismissComplete() {
+        self.dismiss(animated: true) {
+            
+        }
+    }
+    func photoPickerDidCancel() {
+        self.dismiss(animated: true, completion: nil)
+    }
+    func canSelectAsset(phAsset: PHAsset) -> Bool {
+        return true
+    }
+    func didExceedMaximumNumberOfSelection(picker: TLPhotosPickerViewController) {
+        self.showExceededMaximumAlert(vc: picker)
+
+    }
+    func handleNoAlbumPermissions(picker: TLPhotosPickerViewController) {
+        self.dismiss(animated: true) {
+            let alert = UIAlertController(title: "", message: "Denied albums permissions granted", preferredStyle: .alert)
+            alert.addAction(UIAlertAction(title: "Ok", style: .default, handler: nil))
+            self.present(alert, animated: true, completion: nil)
+        }
+    }
+    func handleNoCameraPermissions(picker: TLPhotosPickerViewController) {
+        let alert = UIAlertController(title: "", message: "Denied camera permissions granted", preferredStyle: .alert)
+        alert.addAction(UIAlertAction(title: "Ok", style: .default, handler: nil))
+        self.present(alert, animated: true, completion: nil)
+    }
+
+    func exportVideo() {
+        if let asset = self.selectedAssets.first, asset.type == .video {
+            asset.exportVideoFile(progressBlock: { (progress) in
+                print(progress)
+            }) { (url, mimeType) in
+                print("completion\(url)")
+                print(mimeType)
+            }
+        }
+    }
+    
+    func getAsyncCopyTemporaryFile() {
+        if let asset = self.selectedAssets.first {
+            asset.tempCopyMediaFile(convertLivePhotosToJPG: false, progressBlock: { (progress) in
+                print(progress)
+            }, completionBlock: { (url, mimeType) in
+                print("completion\(url)")
+                print(mimeType)
+            })
+        }
+    }
+    
+    func getFirstSelectedImage() {
+        if let asset = self.selectedAssets.first {
+            if asset.type == .video {
+                asset.videoSize(completion: { [weak self] (size) in
+//                    self?.label.text = "video file size\(size)"
+                })
+                return
+            }
+            if let image = asset.fullResolutionImage {
+                print(image)
+//                self.label.text = "local storage image"
+//                self.imageView.image = image
+            }else {
+                print("Can't get image at local storage, try download image")
+                asset.cloudImageDownload(progressBlock: { [weak self] (progress) in
+                    DispatchQueue.main.async {
+//                        self?.label.text = "download \(100*progress)%"
+                        print(progress)
+                    }
+                    }, completionBlock: { [weak self] (image) in
+                        if let image = image {
+                            //use image
+                            DispatchQueue.main.async {
+//                                self?.label.text = "complete download"
+//                                self?.imageView.image = image
+                            }
+                        }
+                })
+            }
+        }
+    }
+    
+    func showExceededMaximumAlert(vc: UIViewController) {
+        
+        let alert = UIAlertController(title: "", message: "Exceed Maximum Number Of Selection", preferredStyle: .alert)
+        alert.addAction(UIAlertAction(title: "Ok", style: .default, handler: nil))
+        vc.present(alert, animated: true, completion: nil)
+    }
+    
+    func showUnsatisifiedSizeAlert(vc: UIViewController) {
+        let alert = UIAlertController(title: "Oups!", message: "The required size is: 300 x 300", preferredStyle: .alert)
+        alert.addAction(UIAlertAction(title: "Ok", style: .default, handler: nil))
+        vc.present(alert, animated: true, completion: nil)
+    }
+}
+
+extension PublishViewController: TLPhotosPickerLogDelegate {
+    //For Log User Interaction
+    func selectedCameraCell(picker: TLPhotosPickerViewController) {
+        print("selectedCameraCell")
+    }
+    
+    func selectedPhoto(picker: TLPhotosPickerViewController, at: Int) {
+        print("selectedPhoto")
+    }
+    
+    func deselectedPhoto(picker: TLPhotosPickerViewController, at: Int) {
+        print("deselectedPhoto")
+    }
+    
+    func selectedAlbum(picker: TLPhotosPickerViewController, title: String, at: Int) {
+        print("selectedAlbum")
+    }
+}
+
+
 // MARK: - AliyunCropViewControllerDelegate
 extension PublishViewController: AliyunCropViewControllerDelegate {
     func cropViewControllerExit() {

+ 10 - 10
RainbowPlanet/RainbowPlanet/Modules/RegisterLoginModule/RegisterLogin/ViewController/RegisterLoginViewController.swift

@@ -176,10 +176,10 @@ class RegisterLoginViewController: BaseViewController {
         let videoURL = URL(fileURLWithPath: filePath!)
         //定义一个playerItem,并监听相关的通知
         let playerItem = AVPlayerItem(url: videoURL)
-        NotificationCenter.default.addObserver(self,
-                                               selector: #selector(playerDidFinishPlaying),
-                                               name: NSNotification.Name.AVPlayerItemDidPlayToEndTime,
-                                               object: playerItem)
+//        NotificationCenter.default.addObserver(self,
+//                                               selector: #selector(playerDidFinishPlaying),
+//                                               name: NSNotification.Name.AVPlayerItemDidPlayToEndTime,
+//                                               object: playerItem)
         let player = AVPlayer(playerItem: playerItem)
         //设置大小和位置(全屏)
         let playerLayer = AVPlayerLayer(player: player)
@@ -190,12 +190,12 @@ class RegisterLoginViewController: BaseViewController {
         return player
     }()
     
-    @objc func playerDidFinishPlaying(notification:Notification) {
-        
-        player.seek(to: .zero, toleranceBefore: .zero, toleranceAfter: .zero) {[weak self] (finished) in
-            self?.player.play()
-        }
-    }
+//    @objc func playerDidFinishPlaying(notification:Notification) {
+//
+//        player.seek(to: .zero, toleranceBefore: .zero, toleranceAfter: .zero) {[weak self] (finished) in
+//            self?.player.play()
+//        }
+//    }
     
     //第三方登录
     func tripartiteLogin(platformType:UMSocialPlatformType,loginType:LoginType) {

二进制
RainbowPlanet/RainbowPlanet/Supporting Files/CommunityModule.xcassets/100.imageset/100.png


+ 21 - 0
RainbowPlanet/RainbowPlanet/Supporting Files/CommunityModule.xcassets/100.imageset/Contents.json

@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "100.png",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}

+ 0 - 39
RainbowPlanet/RainbowPlanet/Tools/PhotoPicker/TLPhotoPicker/PhotoPickerManager.swift

@@ -1,39 +0,0 @@
-//
-//  File.swift
-//  RainbowPlanet
-//
-//  Created by 南鑫林 on 2019/8/23.
-//  Copyright © 2019 RainbowPlanet. All rights reserved.
-//
-
-import Foundation
-
-public enum FetchCollectionType {
-    case assetCollections(PHAssetCollectionType)
-    case topLevelUserCollections
-}
-
-extension FetchCollectionType: Hashable {
-    private var identifier: String {
-        switch self {
-        case let .assetCollections(collectionType):
-            return "assetCollections\(collectionType.rawValue)"
-        case .topLevelUserCollections:
-            return "topLevelUserCollections"
-        }
-    }
-    
-    public func hash(into hasher: inout Hasher) {
-        hasher.combine(self.identifier)
-    }
-}
-
-public enum PopupConfigure {
-    case animation(TimeInterval)
-}
-
-public struct Platform {
-    public static var isSimulator: Bool {
-        return TARGET_OS_SIMULATOR != 0 // Use this line in Xcode 7 or newer
-    }
-}

+ 0 - 86
RainbowPlanet/RainbowPlanet/Tools/PhotoPicker/TLPhotoPicker/TLPhotoPickerManager.swift

@@ -1,86 +0,0 @@
-//
-//  TLPhotoPickerManager.swift
-//  RainbowPlanet
-//
-//  Created by 南鑫林 on 2019/8/23.
-//  Copyright © 2019 RainbowPlanet. All rights reserved.
-//
-
-import UIKit
-
-public protocol TLPhotosPickerViewControllerDelegate: class {
-    func dismissPhotoPicker(withPHAssets: [PHAsset])
-    func dismissPhotoPicker(withTLPHAssets: [TLPHAsset])
-    func dismissComplete()
-    func photoPickerDidCancel()
-    func canSelectAsset(phAsset: PHAsset) -> Bool
-    func didExceedMaximumNumberOfSelection(picker: TLPhotosPickerViewController)
-    func handleNoAlbumPermissions(picker: TLPhotosPickerViewController)
-    func handleNoCameraPermissions(picker: TLPhotosPickerViewController)
-}
-
-extension TLPhotosPickerViewControllerDelegate {
-    public func deninedAuthoization() { }
-    public func dismissPhotoPicker(withPHAssets: [PHAsset]) { }
-    public func dismissPhotoPicker(withTLPHAssets: [TLPHAsset]) { }
-    public func dismissComplete() { }
-    public func photoPickerDidCancel() { }
-    public func canSelectAsset(phAsset: PHAsset) -> Bool { return true }
-    public func didExceedMaximumNumberOfSelection(picker: TLPhotosPickerViewController) { }
-    public func handleNoAlbumPermissions(picker: TLPhotosPickerViewController) { }
-    public func handleNoCameraPermissions(picker: TLPhotosPickerViewController) { }
-}
-
-//for log
-public protocol TLPhotosPickerLogDelegate: class {
-    func selectedCameraCell(picker: TLPhotosPickerViewController)
-    func deselectedPhoto(picker: TLPhotosPickerViewController, at: Int)
-    func selectedPhoto(picker: TLPhotosPickerViewController, at: Int)
-    func selectedAlbum(picker: TLPhotosPickerViewController, title: String, at: Int)
-}
-
-extension TLPhotosPickerLogDelegate {
-    func selectedCameraCell(picker: TLPhotosPickerViewController) { }
-    func deselectedPhoto(picker: TLPhotosPickerViewController, at: Int) { }
-    func selectedPhoto(picker: TLPhotosPickerViewController, at: Int) { }
-    func selectedAlbum(picker: TLPhotosPickerViewController, collections: [TLAssetsCollection], at: Int) { }
-}
-
-public struct TLPhotosPickerConfigure {
-    public var defaultCameraRollTitle = "Camera Roll"
-    public var tapHereToChange = "Tap here to change"
-    public var cancelTitle = "Cancel"
-    public var doneTitle = "Done"
-    public var emptyMessage = "No albums"
-    public var emptyImage: UIImage? = nil
-    public var usedCameraButton = true
-    public var usedPrefetch = false
-    public var allowedLivePhotos = true
-    public var allowedVideo = true
-    public var allowedAlbumCloudShared = false
-    public var allowedVideoRecording = true
-    public var recordingVideoQuality: UIImagePickerController.QualityType = .typeMedium
-    public var maxVideoDuration:TimeInterval? = nil
-    public var autoPlay = true
-    public var muteAudio = true
-    public var mediaType: PHAssetMediaType? = nil
-    public var numberOfColumn = 3
-    public var singleSelectedMode = false
-    public var maxSelectedAssets: Int? = nil
-    public var fetchOption: PHFetchOptions? = nil
-    public var fetchCollectionOption: [FetchCollectionType: PHFetchOptions] = [:]
-    public var selectedColor = UIColor(red: 88/255, green: 144/255, blue: 255/255, alpha: 1.0)
-    public var cameraBgColor = UIColor(red: 221/255, green: 223/255, blue: 226/255, alpha: 1)
-    public var cameraIcon = TLBundle.podBundleImage(named: "camera")
-    public var videoIcon = TLBundle.podBundleImage(named: "video")
-    public var placeholderIcon = TLBundle.podBundleImage(named: "insertPhotoMaterial")
-    public var nibSet: (nibName: String, bundle:Bundle)? = nil
-    public var cameraCellNibSet: (nibName: String, bundle:Bundle)? = nil
-    public var fetchCollectionTypes: [(PHAssetCollectionType,PHAssetCollectionSubtype)]? = nil
-    public var groupByFetch: PHFetchedResultGroupedBy? = nil
-    public var supportedInterfaceOrientations: UIInterfaceOrientationMask = .portrait
-    public var popup: [PopupConfigure] = []
-    public init() {
-        
-    }
-}

+ 0 - 17
RainbowPlanet/RainbowPlanet/Tools/PhotoPicker/TLPhotoPicker/TLPhotopickerDataSourcesProtocol.swift

@@ -1,17 +0,0 @@
-//
-//  TLPhotopickerDataSourcesProtocol.swift
-//  TLPhotoPicker
-//
-//  Created by wade.hawk on 21/01/2019.
-//
-
-import Foundation
-import Photos
-
-public protocol TLPhotopickerDataSourcesProtocol {
-    func headerReferenceSize() -> CGSize
-    func footerReferenceSize() -> CGSize
-    func registerSupplementView(collectionView: UICollectionView)
-    func supplementIdentifier(kind: String) -> String
-    func configure(supplement view: UICollectionReusableView, section: (title: String, assets: [TLPHAsset]))
-}

+ 0 - 221
RainbowPlanet/RainbowPlanet/Tools/PhotoPicker/TLPhotoPickerResources/TLPhotosPickerViewController.xib

@@ -1,221 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14113" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
-    <device id="retina4_7" orientation="portrait">
-        <adaptation id="fullscreen"/>
-    </device>
-    <dependencies>
-        <deployment identifier="iOS"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14088"/>
-        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
-        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
-    </dependencies>
-    <objects>
-        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="TLPhotosPickerViewController" customModule="TLPhotoPicker" customModuleProvider="target">
-            <connections>
-                <outlet property="albumPopView" destination="Jcn-hC-Umh" id="c3n-m9-wfd"/>
-                <outlet property="cancelButton" destination="sqJ-Z7-zxj" id="J6u-hz-ePK"/>
-                <outlet property="collectionView" destination="4gR-Bn-quP" id="ZOF-qU-cpd"/>
-                <outlet property="customNavItem" destination="5CU-MZ-p1K" id="ih7-d3-nco"/>
-                <outlet property="doneButton" destination="daA-Ag-vVv" id="P53-fy-Sbh"/>
-                <outlet property="emptyImageView" destination="YDZ-o1-AXT" id="TVN-0v-aQc"/>
-                <outlet property="emptyMessageLabel" destination="7qj-q4-rHC" id="Bcp-Hu-lEY"/>
-                <outlet property="emptyView" destination="HPm-Vc-F86" id="4FT-XL-9ql"/>
-                <outlet property="indicator" destination="AEv-G6-dRI" id="coA-3n-07e"/>
-                <outlet property="navigationBar" destination="X8O-Gg-slz" id="Sp9-g1-r4y"/>
-                <outlet property="navigationBarTopConstraint" destination="IKp-hS-tTy" id="MFH-eP-0tb"/>
-                <outlet property="popArrowImageView" destination="5zn-je-qLx" id="6k9-cH-vcU"/>
-                <outlet property="subTitleArrowImageView" destination="b7w-7R-rco" id="IjY-7S-Zz1"/>
-                <outlet property="subTitleLabel" destination="DON-iU-Cox" id="ZyB-O9-EcR"/>
-                <outlet property="subTitleStackView" destination="kgt-Cn-AXg" id="Vcc-hP-iqe"/>
-                <outlet property="titleLabel" destination="xuG-bc-Oq9" id="2o0-aN-au6"/>
-                <outlet property="titleView" destination="VAz-Py-dsa" id="deY-US-9Jh"/>
-                <outlet property="view" destination="Zyk-dI-msE" id="dxK-gh-unF"/>
-            </connections>
-        </placeholder>
-        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
-        <view contentMode="scaleToFill" id="Zyk-dI-msE">
-            <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
-            <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
-            <subviews>
-                <navigationBar contentMode="scaleToFill" translucent="NO" translatesAutoresizingMaskIntoConstraints="NO" id="X8O-Gg-slz">
-                    <rect key="frame" x="0.0" y="20" width="375" height="44"/>
-                    <items>
-                        <navigationItem id="5CU-MZ-p1K">
-                            <nil key="title"/>
-                            <barButtonItem key="leftBarButtonItem" title="Cancel" id="sqJ-Z7-zxj">
-                                <connections>
-                                    <action selector="cancelButtonTap" destination="-1" id="dm0-Ur-I5r"/>
-                                </connections>
-                            </barButtonItem>
-                            <view key="titleView" contentMode="scaleToFill" id="VAz-Py-dsa">
-                                <rect key="frame" x="87.5" y="0.0" width="200" height="44"/>
-                                <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
-                                <subviews>
-                                    <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" alignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="Ql8-7f-9Uk">
-                                        <rect key="frame" x="0.0" y="0.0" width="200" height="44"/>
-                                        <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="xuG-bc-Oq9">
-                                                <rect key="frame" x="79.5" y="0.0" width="41.5" height="19.5"/>
-                                                <fontDescription key="fontDescription" type="system" weight="semibold" pointSize="16"/>
-                                                <nil key="textColor"/>
-                                                <nil key="highlightedColor"/>
-                                            </label>
-                                            <stackView opaque="NO" contentMode="scaleToFill" alignment="center" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="kgt-Cn-AXg">
-                                                <rect key="frame" x="78" y="19.5" width="44.5" height="24.5"/>
-                                                <subviews>
-                                                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="DON-iU-Cox">
-                                                        <rect key="frame" x="0.0" y="5.5" width="29.5" height="13.5"/>
-                                                        <fontDescription key="fontDescription" type="system" weight="medium" pointSize="11"/>
-                                                        <nil key="textColor"/>
-                                                        <nil key="highlightedColor"/>
-                                                    </label>
-                                                    <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="b7w-7R-rco">
-                                                        <rect key="frame" x="34.5" y="7.5" width="10" height="10"/>
-                                                        <constraints>
-                                                            <constraint firstAttribute="width" priority="999" constant="10" id="7bM-Da-Q8A"/>
-                                                            <constraint firstAttribute="height" priority="999" constant="10" id="OHz-gp-CQp"/>
-                                                        </constraints>
-                                                    </imageView>
-                                                </subviews>
-                                            </stackView>
-                                        </subviews>
-                                    </stackView>
-                                </subviews>
-                                <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
-                                <constraints>
-                                    <constraint firstAttribute="trailing" secondItem="Ql8-7f-9Uk" secondAttribute="trailing" id="Vv5-au-j7y"/>
-                                    <constraint firstAttribute="bottom" secondItem="Ql8-7f-9Uk" secondAttribute="bottom" id="XNk-yU-iZJ"/>
-                                    <constraint firstItem="Ql8-7f-9Uk" firstAttribute="top" secondItem="VAz-Py-dsa" secondAttribute="top" id="h9o-f1-oRa"/>
-                                    <constraint firstItem="Ql8-7f-9Uk" firstAttribute="leading" secondItem="VAz-Py-dsa" secondAttribute="leading" id="j8K-5o-bAh"/>
-                                </constraints>
-                            </view>
-                            <barButtonItem key="rightBarButtonItem" title="Done" id="daA-Ag-vVv">
-                                <connections>
-                                    <action selector="doneButtonTap" destination="-1" id="BzF-rn-rn4"/>
-                                </connections>
-                            </barButtonItem>
-                        </navigationItem>
-                    </items>
-                </navigationBar>
-                <collectionView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" dataMode="prototypes" translatesAutoresizingMaskIntoConstraints="NO" id="4gR-Bn-quP">
-                    <rect key="frame" x="0.0" y="64" width="375" height="603"/>
-                    <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
-                    <collectionViewFlowLayout key="collectionViewLayout" minimumLineSpacing="5" minimumInteritemSpacing="5" id="VDa-Pp-VBq">
-                        <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>
-                    <connections>
-                        <outlet property="dataSource" destination="-1" id="6fE-SF-z6F"/>
-                        <outlet property="delegate" destination="-1" id="pjZ-sM-fyY"/>
-                    </connections>
-                </collectionView>
-                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="HPm-Vc-F86">
-                    <rect key="frame" x="0.0" y="64" width="375" height="603"/>
-                    <subviews>
-                        <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" alignment="center" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="gi6-Sw-3Zf">
-                            <rect key="frame" x="137.5" y="239" width="100" height="125.5"/>
-                            <subviews>
-                                <imageView userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="YDZ-o1-AXT">
-                                    <rect key="frame" x="0.0" y="0.0" width="100" height="100"/>
-                                    <constraints>
-                                        <constraint firstAttribute="width" priority="999" constant="100" id="VUj-VB-7Kr"/>
-                                        <constraint firstAttribute="height" priority="999" constant="100" id="jBo-WN-gZr"/>
-                                    </constraints>
-                                </imageView>
-                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="7qj-q4-rHC">
-                                    <rect key="frame" x="29" y="105" width="42" height="20.5"/>
-                                    <fontDescription key="fontDescription" type="system" pointSize="17"/>
-                                    <nil key="textColor"/>
-                                    <nil key="highlightedColor"/>
-                                </label>
-                            </subviews>
-                        </stackView>
-                    </subviews>
-                    <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
-                    <constraints>
-                        <constraint firstItem="gi6-Sw-3Zf" firstAttribute="centerX" secondItem="HPm-Vc-F86" secondAttribute="centerX" id="FpA-96-esN"/>
-                        <constraint firstItem="gi6-Sw-3Zf" firstAttribute="centerY" secondItem="HPm-Vc-F86" secondAttribute="centerY" id="L0c-BG-65l"/>
-                    </constraints>
-                </view>
-                <activityIndicatorView hidden="YES" opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" hidesWhenStopped="YES" style="gray" translatesAutoresizingMaskIntoConstraints="NO" id="AEv-G6-dRI">
-                    <rect key="frame" x="177" y="323" width="20" height="20"/>
-                </activityIndicatorView>
-                <view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Jcn-hC-Umh" customClass="TLAlbumPopView" customModule="TLPhotoPicker" customModuleProvider="target">
-                    <rect key="frame" x="0.0" y="64" width="375" height="603"/>
-                    <subviews>
-                        <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="GKD-We-AdT">
-                            <rect key="frame" x="0.0" y="0.0" width="375" height="603"/>
-                            <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.29999999999999999" colorSpace="calibratedRGB"/>
-                        </view>
-                        <view clipsSubviews="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="eL2-gJ-b87">
-                            <rect key="frame" x="1" y="17" width="373" height="130"/>
-                            <subviews>
-                                <tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" showsHorizontalScrollIndicator="NO" showsVerticalScrollIndicator="NO" style="plain" separatorStyle="default" rowHeight="75" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="grw-Nk-Sxr">
-                                    <rect key="frame" x="10" y="0.0" width="363" height="130"/>
-                                    <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
-                                </tableView>
-                            </subviews>
-                            <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
-                            <constraints>
-                                <constraint firstItem="grw-Nk-Sxr" firstAttribute="top" secondItem="eL2-gJ-b87" secondAttribute="top" id="DAx-an-6Qt"/>
-                                <constraint firstAttribute="height" constant="130" id="cet-yf-3jU"/>
-                                <constraint firstAttribute="trailing" secondItem="grw-Nk-Sxr" secondAttribute="trailing" id="nM5-IG-MPJ"/>
-                                <constraint firstItem="grw-Nk-Sxr" firstAttribute="leading" secondItem="eL2-gJ-b87" secondAttribute="leading" constant="10" id="o4b-cS-L3T"/>
-                                <constraint firstAttribute="bottom" secondItem="grw-Nk-Sxr" secondAttribute="bottom" id="sPK-1G-qLo"/>
-                            </constraints>
-                        </view>
-                        <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="5zn-je-qLx">
-                            <rect key="frame" x="180" y="10" width="14" height="7"/>
-                            <constraints>
-                                <constraint firstAttribute="height" constant="7" id="eZN-nB-EHu"/>
-                                <constraint firstAttribute="width" constant="14" id="hWo-ji-iBX"/>
-                            </constraints>
-                        </imageView>
-                    </subviews>
-                    <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
-                    <constraints>
-                        <constraint firstItem="GKD-We-AdT" firstAttribute="top" secondItem="Jcn-hC-Umh" secondAttribute="top" id="83h-bg-tAJ"/>
-                        <constraint firstAttribute="trailing" secondItem="eL2-gJ-b87" secondAttribute="trailing" constant="1" id="IMh-Wh-897"/>
-                        <constraint firstItem="5zn-je-qLx" firstAttribute="centerX" secondItem="Jcn-hC-Umh" secondAttribute="centerX" id="LpE-mT-MxA"/>
-                        <constraint firstItem="eL2-gJ-b87" firstAttribute="top" secondItem="Jcn-hC-Umh" secondAttribute="top" constant="17" id="XtI-9R-CFm"/>
-                        <constraint firstItem="GKD-We-AdT" firstAttribute="leading" secondItem="Jcn-hC-Umh" secondAttribute="leading" id="krq-3L-sxU"/>
-                        <constraint firstItem="eL2-gJ-b87" firstAttribute="top" secondItem="5zn-je-qLx" secondAttribute="bottom" id="tM4-Tb-JsI"/>
-                        <constraint firstItem="eL2-gJ-b87" firstAttribute="leading" secondItem="Jcn-hC-Umh" secondAttribute="leading" constant="1" id="v5O-lt-eKe"/>
-                        <constraint firstAttribute="bottom" secondItem="GKD-We-AdT" secondAttribute="bottom" id="x4Q-bm-MrY"/>
-                        <constraint firstAttribute="trailing" secondItem="GKD-We-AdT" secondAttribute="trailing" id="xdF-2b-pOS"/>
-                    </constraints>
-                    <connections>
-                        <outlet property="bgView" destination="GKD-We-AdT" id="ymr-tp-YBW"/>
-                        <outlet property="popupView" destination="eL2-gJ-b87" id="xgf-xj-Rd4"/>
-                        <outlet property="popupViewHeight" destination="cet-yf-3jU" id="OS3-MZ-s9c"/>
-                        <outlet property="tableView" destination="grw-Nk-Sxr" id="Y3k-8m-iJp"/>
-                    </connections>
-                </view>
-            </subviews>
-            <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
-            <constraints>
-                <constraint firstItem="HPm-Vc-F86" firstAttribute="bottom" secondItem="HLR-WT-D3I" secondAttribute="bottom" id="0AS-35-SWm"/>
-                <constraint firstItem="AEv-G6-dRI" firstAttribute="centerX" secondItem="Zyk-dI-msE" secondAttribute="centerX" id="44C-fd-MVc"/>
-                <constraint firstItem="X8O-Gg-slz" firstAttribute="leading" secondItem="Zyk-dI-msE" secondAttribute="leading" id="4Ud-fp-qD2"/>
-                <constraint firstItem="4gR-Bn-quP" firstAttribute="top" secondItem="X8O-Gg-slz" secondAttribute="bottom" id="CZx-xl-GLa"/>
-                <constraint firstItem="X8O-Gg-slz" firstAttribute="top" secondItem="HLR-WT-D3I" secondAttribute="top" id="IKp-hS-tTy"/>
-                <constraint firstItem="Jcn-hC-Umh" firstAttribute="top" secondItem="X8O-Gg-slz" secondAttribute="bottom" id="KdD-nT-6tf"/>
-                <constraint firstItem="HPm-Vc-F86" firstAttribute="leading" secondItem="HLR-WT-D3I" secondAttribute="leading" id="M3L-CU-HdQ"/>
-                <constraint firstAttribute="trailing" secondItem="4gR-Bn-quP" secondAttribute="trailing" id="M6b-2G-2m1"/>
-                <constraint firstAttribute="trailing" secondItem="Jcn-hC-Umh" secondAttribute="trailing" id="Njh-ZO-lnq"/>
-                <constraint firstAttribute="bottom" secondItem="Jcn-hC-Umh" secondAttribute="bottom" id="NxH-d8-b65"/>
-                <constraint firstItem="HPm-Vc-F86" firstAttribute="top" secondItem="X8O-Gg-slz" secondAttribute="bottom" id="YyG-QW-0ZP"/>
-                <constraint firstItem="AEv-G6-dRI" firstAttribute="centerY" secondItem="Zyk-dI-msE" secondAttribute="centerY" id="aLU-u9-ALA"/>
-                <constraint firstItem="Jcn-hC-Umh" firstAttribute="leading" secondItem="Zyk-dI-msE" secondAttribute="leading" id="aY7-Ml-cd3"/>
-                <constraint firstItem="HPm-Vc-F86" firstAttribute="trailing" secondItem="HLR-WT-D3I" secondAttribute="trailing" id="aoA-8G-xDA"/>
-                <constraint firstItem="4gR-Bn-quP" firstAttribute="leading" secondItem="Zyk-dI-msE" secondAttribute="leading" id="kb7-vy-yTu"/>
-                <constraint firstItem="4gR-Bn-quP" firstAttribute="bottom" secondItem="HLR-WT-D3I" secondAttribute="bottom" id="qqE-w2-Tsc"/>
-                <constraint firstAttribute="trailing" secondItem="X8O-Gg-slz" secondAttribute="trailing" id="yWV-L2-0f4"/>
-            </constraints>
-            <viewLayoutGuide key="safeArea" id="HLR-WT-D3I"/>
-            <point key="canvasLocation" x="33.5" y="53.5"/>
-        </view>
-    </objects>
-</document>