diff --git a/HXPhotoPickerExample.xcodeproj/project.pbxproj b/HXPhotoPickerExample.xcodeproj/project.pbxproj index 0215c11e..fc4a6c06 100644 --- a/HXPhotoPickerExample.xcodeproj/project.pbxproj +++ b/HXPhotoPickerExample.xcodeproj/project.pbxproj @@ -158,6 +158,26 @@ 7B8629AA237D0F8D00F8A584 /* EventKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7B8629A9237D0F8C00F8A584 /* EventKit.framework */; }; 7B8629AC237D0F9400F8A584 /* Contacts.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7B8629AB237D0F9400F8A584 /* Contacts.framework */; }; 7B8629AE237D0FAA00F8A584 /* AddressBook.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7B8629AD237D0FAA00F8A584 /* AddressBook.framework */; }; + 7B881B9926B8D5BE00CC44CC /* UIDevice+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B881B8426B8D5BE00CC44CC /* UIDevice+Extension.swift */; }; + 7B881B9A26B8D5BF00CC44CC /* UIFont+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B881B8526B8D5BE00CC44CC /* UIFont+Extension.swift */; }; + 7B881B9B26B8D5BF00CC44CC /* UIView+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B881B8626B8D5BE00CC44CC /* UIView+Extension.swift */; }; + 7B881B9C26B8D5BF00CC44CC /* UIImage+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B881B8726B8D5BE00CC44CC /* UIImage+Extension.swift */; }; + 7B881B9D26B8D5BF00CC44CC /* String+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B881B8826B8D5BE00CC44CC /* String+Extension.swift */; }; + 7B881B9E26B8D5BF00CC44CC /* RowTypeRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B881B8926B8D5BE00CC44CC /* RowTypeRule.swift */; }; + 7B881B9F26B8D5BF00CC44CC /* Core+UIColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B881B8A26B8D5BE00CC44CC /* Core+UIColor.swift */; }; + 7B881BA026B8D5BF00CC44CC /* WeChatMometViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B881B8C26B8D5BE00CC44CC /* WeChatMometViewController.swift */; }; + 7B881BA126B8D5BF00CC44CC /* EditorConfigurationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B881B8D26B8D5BE00CC44CC /* EditorConfigurationViewController.swift */; }; + 7B881BA226B8D5BF00CC44CC /* PickerResultViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B881B8E26B8D5BE00CC44CC /* PickerResultViewController.swift */; }; + 7B881BA326B8D5BF00CC44CC /* AvatarPickerConfigurationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B881B8F26B8D5BE00CC44CC /* AvatarPickerConfigurationViewController.swift */; }; + 7B881BA426B8D5BF00CC44CC /* HomeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B881B9026B8D5BE00CC44CC /* HomeViewController.swift */; }; + 7B881BA526B8D5BF00CC44CC /* CustomPickerCellViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B881B9126B8D5BE00CC44CC /* CustomPickerCellViewController.swift */; }; + 7B881BA626B8D5BF00CC44CC /* PickerColorConfigurationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B881B9226B8D5BE00CC44CC /* PickerColorConfigurationViewController.swift */; }; + 7B881BA726B8D5BF00CC44CC /* PickerConfigurationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B881B9326B8D5BE00CC44CC /* PickerConfigurationViewController.swift */; }; + 7B881BA826B8D5BF00CC44CC /* PickerResultViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7B881B9426B8D5BE00CC44CC /* PickerResultViewController.xib */; }; + 7B881BA926B8D5BF00CC44CC /* ConfigurationViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B881B9626B8D5BE00CC44CC /* ConfigurationViewCell.swift */; }; + 7B881BAA26B8D5BF00CC44CC /* ProgressHUD.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B881B9726B8D5BE00CC44CC /* ProgressHUD.swift */; }; + 7B881BAB26B8D5BF00CC44CC /* CustomPickerCellView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B881B9826B8D5BE00CC44CC /* CustomPickerCellView.swift */; }; + 7B881BAD26B8E0B800CC44CC /* Reachability.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B881BAC26B8E0B700CC44CC /* Reachability.swift */; }; 7B8BFB1C2585191D00510339 /* HXPhotoPicker.podspec in Resources */ = {isa = PBXBuildFile; fileRef = 7B8BFB1B2585191D00510339 /* HXPhotoPicker.podspec */; }; 7BAF876124C14D5C00ACAF85 /* HXCameraBottomView.m in Sources */ = {isa = PBXBuildFile; fileRef = 7BAF876024C14D5C00ACAF85 /* HXCameraBottomView.m */; }; 7BB613BF26A01B9700D38EBD /* 野孩子.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 7BB613AF26A01B9700D38EBD /* 野孩子.mp3 */; }; @@ -176,25 +196,6 @@ 7BB613CC26A01B9700D38EBD /* 时光正好 in Resources */ = {isa = PBXBuildFile; fileRef = 7BB613BC26A01B9700D38EBD /* 时光正好 */; }; 7BB613CD26A01B9700D38EBD /* 世间美好与你环环相扣.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 7BB613BD26A01B9700D38EBD /* 世间美好与你环环相扣.mp3 */; }; 7BB613CE26A01B9700D38EBD /* 少女的祈祷.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 7BB613BE26A01B9700D38EBD /* 少女的祈祷.mp3 */; }; - 7BB613E626A01BD800D38EBD /* UIDevice+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BB613D126A01BD800D38EBD /* UIDevice+Extension.swift */; }; - 7BB613E726A01BD800D38EBD /* UIFont+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BB613D226A01BD800D38EBD /* UIFont+Extension.swift */; }; - 7BB613E826A01BD800D38EBD /* UIView+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BB613D326A01BD800D38EBD /* UIView+Extension.swift */; }; - 7BB613E926A01BD800D38EBD /* UIImage+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BB613D426A01BD800D38EBD /* UIImage+Extension.swift */; }; - 7BB613EA26A01BD800D38EBD /* String+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BB613D526A01BD800D38EBD /* String+Extension.swift */; }; - 7BB613EB26A01BD800D38EBD /* RowTypeRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BB613D626A01BD800D38EBD /* RowTypeRule.swift */; }; - 7BB613EC26A01BD800D38EBD /* Core+UIColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BB613D726A01BD800D38EBD /* Core+UIColor.swift */; }; - 7BB613ED26A01BD800D38EBD /* EditorConfigurationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BB613D926A01BD800D38EBD /* EditorConfigurationViewController.swift */; }; - 7BB613EE26A01BD800D38EBD /* AvatarPickerResultViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BB613DA26A01BD800D38EBD /* AvatarPickerResultViewController.swift */; }; - 7BB613EF26A01BD800D38EBD /* PickerResultViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BB613DB26A01BD800D38EBD /* PickerResultViewController.swift */; }; - 7BB613F026A01BD800D38EBD /* AvatarPickerConfigurationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BB613DC26A01BD800D38EBD /* AvatarPickerConfigurationViewController.swift */; }; - 7BB613F126A01BD800D38EBD /* HomeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BB613DD26A01BD800D38EBD /* HomeViewController.swift */; }; - 7BB613F226A01BD800D38EBD /* CustomPickerCellViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BB613DE26A01BD800D38EBD /* CustomPickerCellViewController.swift */; }; - 7BB613F326A01BD800D38EBD /* PickerColorConfigurationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BB613DF26A01BD800D38EBD /* PickerColorConfigurationViewController.swift */; }; - 7BB613F426A01BD800D38EBD /* PickerConfigurationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BB613E026A01BD800D38EBD /* PickerConfigurationViewController.swift */; }; - 7BB613F526A01BD800D38EBD /* PickerResultViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7BB613E126A01BD800D38EBD /* PickerResultViewController.xib */; }; - 7BB613F626A01BD800D38EBD /* ConfigurationViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BB613E326A01BD800D38EBD /* ConfigurationViewCell.swift */; }; - 7BB613F726A01BD800D38EBD /* ProgressHUD.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BB613E426A01BD800D38EBD /* ProgressHUD.swift */; }; - 7BB613F826A01BD800D38EBD /* CustomPickerCellView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BB613E526A01BD800D38EBD /* CustomPickerCellView.swift */; }; 7BC371522505D25000E2D05C /* HXPhotoEditGraffitiColorSizeView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7BC3713A2505D24E00E2D05C /* HXPhotoEditGraffitiColorSizeView.xib */; }; 7BC371532505D25000E2D05C /* HXPhotoEditStickerTrashView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7BC3713B2505D24E00E2D05C /* HXPhotoEditStickerTrashView.xib */; }; 7BC371542505D25000E2D05C /* HXPhotoEditMosaicView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7BC3713C2505D24E00E2D05C /* HXPhotoEditMosaicView.xib */; }; @@ -670,6 +671,26 @@ 7B8629A9237D0F8C00F8A584 /* EventKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = EventKit.framework; path = System/Library/Frameworks/EventKit.framework; sourceTree = SDKROOT; }; 7B8629AB237D0F9400F8A584 /* Contacts.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Contacts.framework; path = System/Library/Frameworks/Contacts.framework; sourceTree = SDKROOT; }; 7B8629AD237D0FAA00F8A584 /* AddressBook.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AddressBook.framework; path = System/Library/Frameworks/AddressBook.framework; sourceTree = SDKROOT; }; + 7B881B8426B8D5BE00CC44CC /* UIDevice+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIDevice+Extension.swift"; sourceTree = ""; }; + 7B881B8526B8D5BE00CC44CC /* UIFont+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIFont+Extension.swift"; sourceTree = ""; }; + 7B881B8626B8D5BE00CC44CC /* UIView+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIView+Extension.swift"; sourceTree = ""; }; + 7B881B8726B8D5BE00CC44CC /* UIImage+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIImage+Extension.swift"; sourceTree = ""; }; + 7B881B8826B8D5BE00CC44CC /* String+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String+Extension.swift"; sourceTree = ""; }; + 7B881B8926B8D5BE00CC44CC /* RowTypeRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RowTypeRule.swift; sourceTree = ""; }; + 7B881B8A26B8D5BE00CC44CC /* Core+UIColor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Core+UIColor.swift"; sourceTree = ""; }; + 7B881B8C26B8D5BE00CC44CC /* WeChatMometViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WeChatMometViewController.swift; sourceTree = ""; }; + 7B881B8D26B8D5BE00CC44CC /* EditorConfigurationViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EditorConfigurationViewController.swift; sourceTree = ""; }; + 7B881B8E26B8D5BE00CC44CC /* PickerResultViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PickerResultViewController.swift; sourceTree = ""; }; + 7B881B8F26B8D5BE00CC44CC /* AvatarPickerConfigurationViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AvatarPickerConfigurationViewController.swift; sourceTree = ""; }; + 7B881B9026B8D5BE00CC44CC /* HomeViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HomeViewController.swift; sourceTree = ""; }; + 7B881B9126B8D5BE00CC44CC /* CustomPickerCellViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomPickerCellViewController.swift; sourceTree = ""; }; + 7B881B9226B8D5BE00CC44CC /* PickerColorConfigurationViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PickerColorConfigurationViewController.swift; sourceTree = ""; }; + 7B881B9326B8D5BE00CC44CC /* PickerConfigurationViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PickerConfigurationViewController.swift; sourceTree = ""; }; + 7B881B9426B8D5BE00CC44CC /* PickerResultViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = PickerResultViewController.xib; sourceTree = ""; }; + 7B881B9626B8D5BE00CC44CC /* ConfigurationViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConfigurationViewCell.swift; sourceTree = ""; }; + 7B881B9726B8D5BE00CC44CC /* ProgressHUD.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProgressHUD.swift; sourceTree = ""; }; + 7B881B9826B8D5BE00CC44CC /* CustomPickerCellView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomPickerCellView.swift; sourceTree = ""; }; + 7B881BAC26B8E0B700CC44CC /* Reachability.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Reachability.swift; sourceTree = ""; }; 7B8BFB1B2585191D00510339 /* HXPhotoPicker.podspec */ = {isa = PBXFileReference; lastKnownFileType = text; path = HXPhotoPicker.podspec; sourceTree = SOURCE_ROOT; }; 7B8EED1A24D7C2C600957B3C /* HXPhotoTypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HXPhotoTypes.h; sourceTree = ""; }; 7BAF875F24C14D5C00ACAF85 /* HXCameraBottomView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HXCameraBottomView.h; sourceTree = ""; }; @@ -690,25 +711,6 @@ 7BB613BC26A01B9700D38EBD /* 时光正好 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "时光正好"; sourceTree = ""; }; 7BB613BD26A01B9700D38EBD /* 世间美好与你环环相扣.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = "世间美好与你环环相扣.mp3"; sourceTree = ""; }; 7BB613BE26A01B9700D38EBD /* 少女的祈祷.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = "少女的祈祷.mp3"; sourceTree = ""; }; - 7BB613D126A01BD800D38EBD /* UIDevice+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIDevice+Extension.swift"; sourceTree = ""; }; - 7BB613D226A01BD800D38EBD /* UIFont+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIFont+Extension.swift"; sourceTree = ""; }; - 7BB613D326A01BD800D38EBD /* UIView+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIView+Extension.swift"; sourceTree = ""; }; - 7BB613D426A01BD800D38EBD /* UIImage+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIImage+Extension.swift"; sourceTree = ""; }; - 7BB613D526A01BD800D38EBD /* String+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String+Extension.swift"; sourceTree = ""; }; - 7BB613D626A01BD800D38EBD /* RowTypeRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RowTypeRule.swift; sourceTree = ""; }; - 7BB613D726A01BD800D38EBD /* Core+UIColor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Core+UIColor.swift"; sourceTree = ""; }; - 7BB613D926A01BD800D38EBD /* EditorConfigurationViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EditorConfigurationViewController.swift; sourceTree = ""; }; - 7BB613DA26A01BD800D38EBD /* AvatarPickerResultViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AvatarPickerResultViewController.swift; sourceTree = ""; }; - 7BB613DB26A01BD800D38EBD /* PickerResultViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PickerResultViewController.swift; sourceTree = ""; }; - 7BB613DC26A01BD800D38EBD /* AvatarPickerConfigurationViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AvatarPickerConfigurationViewController.swift; sourceTree = ""; }; - 7BB613DD26A01BD800D38EBD /* HomeViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HomeViewController.swift; sourceTree = ""; }; - 7BB613DE26A01BD800D38EBD /* CustomPickerCellViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomPickerCellViewController.swift; sourceTree = ""; }; - 7BB613DF26A01BD800D38EBD /* PickerColorConfigurationViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PickerColorConfigurationViewController.swift; sourceTree = ""; }; - 7BB613E026A01BD800D38EBD /* PickerConfigurationViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PickerConfigurationViewController.swift; sourceTree = ""; }; - 7BB613E126A01BD800D38EBD /* PickerResultViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = PickerResultViewController.xib; sourceTree = ""; }; - 7BB613E326A01BD800D38EBD /* ConfigurationViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConfigurationViewCell.swift; sourceTree = ""; }; - 7BB613E426A01BD800D38EBD /* ProgressHUD.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProgressHUD.swift; sourceTree = ""; }; - 7BB613E526A01BD800D38EBD /* CustomPickerCellView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomPickerCellView.swift; sourceTree = ""; }; 7BB9FDFB24D500DB00C9A6F1 /* HXPhotoViewProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HXPhotoViewProtocol.h; sourceTree = ""; }; 7BC3713A2505D24E00E2D05C /* HXPhotoEditGraffitiColorSizeView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = HXPhotoEditGraffitiColorSizeView.xib; sourceTree = ""; }; 7BC3713B2505D24E00E2D05C /* HXPhotoEditStickerTrashView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = HXPhotoEditStickerTrashView.xib; sourceTree = ""; }; @@ -882,8 +884,9 @@ 7B3EDEBF255E185900937B4A /* Swift */ = { isa = PBXGroup; children = ( - 7BB613CF26A01BD800D38EBD /* Classes */, + 7B881B8226B8D5BE00CC44CC /* Classes */, 7B3EDEC0255E185900937B4A /* AppDelegate.swift */, + 7B881BAC26B8E0B700CC44CC /* Reachability.swift */, 7B3EDEC6255E185900937B4A /* Main.storyboard */, 7B3EDEC9255E185B00937B4A /* Assets.xcassets */, 7BB613AE26A01B9700D38EBD /* Music */, @@ -1221,77 +1224,77 @@ name = "Supporting Files"; sourceTree = ""; }; - 7BB613AE26A01B9700D38EBD /* Music */ = { + 7B881B8226B8D5BE00CC44CC /* Classes */ = { isa = PBXGroup; children = ( - 7BB613AF26A01B9700D38EBD /* 野孩子.mp3 */, - 7BB613B026A01B9700D38EBD /* 嘉宾 */, - 7BB613B126A01B9700D38EBD /* 无赖.mp3 */, - 7BB613B226A01B9700D38EBD /* 爱你.mp3 */, - 7BB613B326A01B9700D38EBD /* 少女的祈祷 */, - 7BB613B426A01B9700D38EBD /* 时光正好.mp3 */, - 7BB613B526A01B9700D38EBD /* 嘉宾.mp3 */, - 7BB613B626A01B9700D38EBD /* 天外来物.mp3 */, - 7BB613B726A01B9700D38EBD /* 世间美好与你环环相扣 */, - 7BB613B826A01B9700D38EBD /* 爱你 */, - 7BB613B926A01B9700D38EBD /* 天外来物 */, - 7BB613BA26A01B9700D38EBD /* 野孩子 */, - 7BB613BB26A01B9700D38EBD /* 无赖 */, - 7BB613BC26A01B9700D38EBD /* 时光正好 */, - 7BB613BD26A01B9700D38EBD /* 世间美好与你环环相扣.mp3 */, - 7BB613BE26A01B9700D38EBD /* 少女的祈祷.mp3 */, + 7B881B8326B8D5BE00CC44CC /* Extension */, + 7B881B8B26B8D5BE00CC44CC /* Controller */, + 7B881B9526B8D5BE00CC44CC /* View */, ); - path = Music; + path = Classes; sourceTree = ""; }; - 7BB613CF26A01BD800D38EBD /* Classes */ = { + 7B881B8326B8D5BE00CC44CC /* Extension */ = { isa = PBXGroup; children = ( - 7BB613D826A01BD800D38EBD /* Controller */, - 7BB613D026A01BD800D38EBD /* Extension */, - 7BB613E226A01BD800D38EBD /* View */, + 7B881B8426B8D5BE00CC44CC /* UIDevice+Extension.swift */, + 7B881B8526B8D5BE00CC44CC /* UIFont+Extension.swift */, + 7B881B8626B8D5BE00CC44CC /* UIView+Extension.swift */, + 7B881B8726B8D5BE00CC44CC /* UIImage+Extension.swift */, + 7B881B8826B8D5BE00CC44CC /* String+Extension.swift */, + 7B881B8926B8D5BE00CC44CC /* RowTypeRule.swift */, + 7B881B8A26B8D5BE00CC44CC /* Core+UIColor.swift */, ); - path = Classes; + path = Extension; sourceTree = ""; }; - 7BB613D026A01BD800D38EBD /* Extension */ = { + 7B881B8B26B8D5BE00CC44CC /* Controller */ = { isa = PBXGroup; children = ( - 7BB613D726A01BD800D38EBD /* Core+UIColor.swift */, - 7BB613D626A01BD800D38EBD /* RowTypeRule.swift */, - 7BB613D526A01BD800D38EBD /* String+Extension.swift */, - 7BB613D126A01BD800D38EBD /* UIDevice+Extension.swift */, - 7BB613D226A01BD800D38EBD /* UIFont+Extension.swift */, - 7BB613D426A01BD800D38EBD /* UIImage+Extension.swift */, - 7BB613D326A01BD800D38EBD /* UIView+Extension.swift */, + 7B881B8F26B8D5BE00CC44CC /* AvatarPickerConfigurationViewController.swift */, + 7B881B9126B8D5BE00CC44CC /* CustomPickerCellViewController.swift */, + 7B881B8D26B8D5BE00CC44CC /* EditorConfigurationViewController.swift */, + 7B881B9026B8D5BE00CC44CC /* HomeViewController.swift */, + 7B881B9226B8D5BE00CC44CC /* PickerColorConfigurationViewController.swift */, + 7B881B9326B8D5BE00CC44CC /* PickerConfigurationViewController.swift */, + 7B881B8E26B8D5BE00CC44CC /* PickerResultViewController.swift */, + 7B881B9426B8D5BE00CC44CC /* PickerResultViewController.xib */, + 7B881B8C26B8D5BE00CC44CC /* WeChatMometViewController.swift */, ); - path = Extension; + path = Controller; sourceTree = ""; }; - 7BB613D826A01BD800D38EBD /* Controller */ = { + 7B881B9526B8D5BE00CC44CC /* View */ = { isa = PBXGroup; children = ( - 7BB613DC26A01BD800D38EBD /* AvatarPickerConfigurationViewController.swift */, - 7BB613DA26A01BD800D38EBD /* AvatarPickerResultViewController.swift */, - 7BB613DE26A01BD800D38EBD /* CustomPickerCellViewController.swift */, - 7BB613D926A01BD800D38EBD /* EditorConfigurationViewController.swift */, - 7BB613DD26A01BD800D38EBD /* HomeViewController.swift */, - 7BB613DF26A01BD800D38EBD /* PickerColorConfigurationViewController.swift */, - 7BB613E026A01BD800D38EBD /* PickerConfigurationViewController.swift */, - 7BB613DB26A01BD800D38EBD /* PickerResultViewController.swift */, - 7BB613E126A01BD800D38EBD /* PickerResultViewController.xib */, + 7B881B9626B8D5BE00CC44CC /* ConfigurationViewCell.swift */, + 7B881B9726B8D5BE00CC44CC /* ProgressHUD.swift */, + 7B881B9826B8D5BE00CC44CC /* CustomPickerCellView.swift */, ); - path = Controller; + path = View; sourceTree = ""; }; - 7BB613E226A01BD800D38EBD /* View */ = { + 7BB613AE26A01B9700D38EBD /* Music */ = { isa = PBXGroup; children = ( - 7BB613E326A01BD800D38EBD /* ConfigurationViewCell.swift */, - 7BB613E526A01BD800D38EBD /* CustomPickerCellView.swift */, - 7BB613E426A01BD800D38EBD /* ProgressHUD.swift */, + 7BB613AF26A01B9700D38EBD /* 野孩子.mp3 */, + 7BB613B026A01B9700D38EBD /* 嘉宾 */, + 7BB613B126A01B9700D38EBD /* 无赖.mp3 */, + 7BB613B226A01B9700D38EBD /* 爱你.mp3 */, + 7BB613B326A01B9700D38EBD /* 少女的祈祷 */, + 7BB613B426A01B9700D38EBD /* 时光正好.mp3 */, + 7BB613B526A01B9700D38EBD /* 嘉宾.mp3 */, + 7BB613B626A01B9700D38EBD /* 天外来物.mp3 */, + 7BB613B726A01B9700D38EBD /* 世间美好与你环环相扣 */, + 7BB613B826A01B9700D38EBD /* 爱你 */, + 7BB613B926A01B9700D38EBD /* 天外来物 */, + 7BB613BA26A01B9700D38EBD /* 野孩子 */, + 7BB613BB26A01B9700D38EBD /* 无赖 */, + 7BB613BC26A01B9700D38EBD /* 时光正好 */, + 7BB613BD26A01B9700D38EBD /* 世间美好与你环环相扣.mp3 */, + 7BB613BE26A01B9700D38EBD /* 少女的祈祷.mp3 */, ); - path = View; + path = Music; sourceTree = ""; }; 7BD52EC124FE250E00AE3D7C /* HXPhotoPickerFramework */ = { @@ -1518,7 +1521,7 @@ 7BB613CB26A01B9700D38EBD /* 无赖 in Resources */, 7BB613C326A01B9700D38EBD /* 少女的祈祷 in Resources */, 7BB613C126A01B9700D38EBD /* 无赖.mp3 in Resources */, - 7BB613F526A01BD800D38EBD /* PickerResultViewController.xib in Resources */, + 7B881BA826B8D5BF00CC44CC /* PickerResultViewController.xib in Resources */, 7BB613CC26A01B9700D38EBD /* 时光正好 in Resources */, 7B3EDECD255E185B00937B4A /* LaunchScreen.storyboard in Resources */, 7BB613C426A01B9700D38EBD /* 时光正好.mp3 in Resources */, @@ -1660,25 +1663,26 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 7BB613E726A01BD800D38EBD /* UIFont+Extension.swift in Sources */, - 7BB613F826A01BD800D38EBD /* CustomPickerCellView.swift in Sources */, - 7BB613EB26A01BD800D38EBD /* RowTypeRule.swift in Sources */, - 7BB613F726A01BD800D38EBD /* ProgressHUD.swift in Sources */, - 7BB613EF26A01BD800D38EBD /* PickerResultViewController.swift in Sources */, + 7B881B9A26B8D5BF00CC44CC /* UIFont+Extension.swift in Sources */, + 7B881BAB26B8D5BF00CC44CC /* CustomPickerCellView.swift in Sources */, + 7B881B9E26B8D5BF00CC44CC /* RowTypeRule.swift in Sources */, + 7B881BAA26B8D5BF00CC44CC /* ProgressHUD.swift in Sources */, + 7B881BA226B8D5BF00CC44CC /* PickerResultViewController.swift in Sources */, + 7B881BA026B8D5BF00CC44CC /* WeChatMometViewController.swift in Sources */, 7B3EDEC1255E185900937B4A /* AppDelegate.swift in Sources */, - 7BB613ED26A01BD800D38EBD /* EditorConfigurationViewController.swift in Sources */, - 7BB613E926A01BD800D38EBD /* UIImage+Extension.swift in Sources */, - 7BB613E826A01BD800D38EBD /* UIView+Extension.swift in Sources */, - 7BB613F426A01BD800D38EBD /* PickerConfigurationViewController.swift in Sources */, - 7BB613EA26A01BD800D38EBD /* String+Extension.swift in Sources */, - 7BB613F026A01BD800D38EBD /* AvatarPickerConfigurationViewController.swift in Sources */, - 7BB613F226A01BD800D38EBD /* CustomPickerCellViewController.swift in Sources */, - 7BB613EC26A01BD800D38EBD /* Core+UIColor.swift in Sources */, - 7BB613EE26A01BD800D38EBD /* AvatarPickerResultViewController.swift in Sources */, - 7BB613F126A01BD800D38EBD /* HomeViewController.swift in Sources */, - 7BB613F626A01BD800D38EBD /* ConfigurationViewCell.swift in Sources */, - 7BB613F326A01BD800D38EBD /* PickerColorConfigurationViewController.swift in Sources */, - 7BB613E626A01BD800D38EBD /* UIDevice+Extension.swift in Sources */, + 7B881B9C26B8D5BF00CC44CC /* UIImage+Extension.swift in Sources */, + 7B881B9B26B8D5BF00CC44CC /* UIView+Extension.swift in Sources */, + 7B881BA726B8D5BF00CC44CC /* PickerConfigurationViewController.swift in Sources */, + 7B881B9D26B8D5BF00CC44CC /* String+Extension.swift in Sources */, + 7B881BA326B8D5BF00CC44CC /* AvatarPickerConfigurationViewController.swift in Sources */, + 7B881BA526B8D5BF00CC44CC /* CustomPickerCellViewController.swift in Sources */, + 7B881B9F26B8D5BF00CC44CC /* Core+UIColor.swift in Sources */, + 7B881BA126B8D5BF00CC44CC /* EditorConfigurationViewController.swift in Sources */, + 7B881BA426B8D5BF00CC44CC /* HomeViewController.swift in Sources */, + 7B881BA926B8D5BF00CC44CC /* ConfigurationViewCell.swift in Sources */, + 7B881BA626B8D5BF00CC44CC /* PickerColorConfigurationViewController.swift in Sources */, + 7B881BAD26B8E0B800CC44CC /* Reachability.swift in Sources */, + 7B881B9926B8D5BE00CC44CC /* UIDevice+Extension.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Podfile b/Podfile index fe68705a..f43c53a7 100644 --- a/Podfile +++ b/Podfile @@ -12,5 +12,5 @@ end target "HXPHPickerExample" do platform:ios,'10.0' use_frameworks! - pod 'HXPHPicker/Full', '~> 1.1.3' + pod 'HXPHPicker', '~> 1.1.6' end diff --git a/Podfile.lock b/Podfile.lock index d06e8ab1..93b6f949 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -1,18 +1,22 @@ PODS: - - HXPHPicker/Core (1.1.3) - - HXPHPicker/Editor (1.1.3): + - HXPHPicker (1.1.6): + - HXPHPicker/Full (= 1.1.6) + - HXPHPicker/Core (1.1.6) + - HXPHPicker/Editor (1.1.6): - HXPHPicker/Core - - HXPHPicker/Full (1.1.3): + - HXPHPicker/Full (1.1.6): + - HXPHPicker/Lite + - Kingfisher (~> 6.0) + - HXPHPicker/Lite (1.1.6): - HXPHPicker/Core - HXPHPicker/Editor - HXPHPicker/Picker - - Kingfisher (~> 6.0) - - HXPHPicker/Picker (1.1.3): + - HXPHPicker/Picker (1.1.6): - HXPHPicker/Core - - Kingfisher (6.3.0) + - Kingfisher (6.3.1) DEPENDENCIES: - - HXPHPicker/Full (~> 1.1.3) + - HXPHPicker (~> 1.1.6) SPEC REPOS: https://github.com/CocoaPods/Specs.git: @@ -20,9 +24,9 @@ SPEC REPOS: - Kingfisher SPEC CHECKSUMS: - HXPHPicker: 11fc8a93a606bd531a195afd7ef42f0ff660888a - Kingfisher: 6c3df386db71d82c0817a429d2c9421a77396529 + HXPHPicker: 47f055335107393179201e009e90d32582596e91 + Kingfisher: 016c8b653a35add51dd34a3aba36b580041acc74 -PODFILE CHECKSUM: ee6c2e3ceb139b50e450afa3e8781766ddff9c0a +PODFILE CHECKSUM: 29189cca6a3135688a8bb227d9d3797866608f28 COCOAPODS: 1.10.1 diff --git a/Pods/HXPHPicker/README.md b/Pods/HXPHPicker/README.md index 0136f0d3..947932bf 100644 --- a/Pods/HXPHPicker/README.md +++ b/Pods/HXPHPicker/README.md @@ -28,8 +28,8 @@ - [x] 支持滑动选择 - [x] 编辑图片(支持动图、网络资源) - [x] 涂鸦 - - [ ] 贴纸 - - [ ] 文字 + - [x] 贴纸 + - [x] 文字 - [x] 裁剪 - [x] 马赛克 - [x] 滤镜 @@ -67,7 +67,7 @@ ```swift dependencies: [ - .package(url: "https://github.com/SilenceLove/HXPHPicker.git", .upToNextMajor(from: "1.1.3")) + .package(url: "https://github.com/SilenceLove/HXPHPicker.git", .upToNextMajor(from: "1.1.6")) ] ``` @@ -89,6 +89,8 @@ github "SilenceLove/HXPHPicker" ## 使用方法 +> 我们在 [Wiki](https://github.com/SilenceLove/HXPHPicker/wiki) 中提供了更详细的使用说明。 + ### 准备工作 按需在你的 Info.plist 中添加以下键值: @@ -153,13 +155,10 @@ extension ViewController: PhotoPickerControllerDelegate { | 版本 | 发布时间 | Xcode | Swift | iOS | | ---- | ---- | ---- | ---- | ---- | +| [v1.1.6](https://github.com/SilenceLove/HXPHPicker/blob/main/Documentation/RELEASE_NOTE.md#116) | 2021-08-02 | 12.5.1 | 5.3 | 10.0+ | +| [v1.1.5](https://github.com/SilenceLove/HXPHPicker/blob/main/Documentation/RELEASE_NOTE.md#115) | 2021-07-28 | 12.5.1 | 5.3 | 10.0+ | +| [v1.1.4](https://github.com/SilenceLove/HXPHPicker/blob/main/Documentation/RELEASE_NOTE.md#114) | 2021-07-16 | 12.5.1 | 5.3 | 10.0+ | | [v1.1.3](https://github.com/SilenceLove/HXPHPicker/blob/main/Documentation/RELEASE_NOTE.md#113) | 2021-07-14 | 12.5.1 | 5.3 | 10.0+ | -| [v1.1.2](https://github.com/SilenceLove/HXPHPicker/blob/main/Documentation/RELEASE_NOTE.md#112) | 2021-06-30 | 12.5.1 | 5.3 | 10.0+ | -| [v1.1.1](https://github.com/SilenceLove/HXPHPicker/blob/main/Documentation/RELEASE_NOTE.md#111) | 2021-06-17 | 12.2 | 5.3 | 10.0+ | -| [v1.1.0](https://github.com/SilenceLove/HXPHPicker/blob/main/Documentation/RELEASE_NOTE.md#110) | 2021-06-08 | 12.2 | 5.3 | 10.0+ | -| [v1.0.9](https://github.com/SilenceLove/HXPHPicker/blob/main/Documentation/RELEASE_NOTE.md#109) | 2021-06-04 | 12.2 | 5.3 | 10.0+ | -| [v1.0.8](https://github.com/SilenceLove/HXPHPicker/blob/main/Documentation/RELEASE_NOTE.md#108) | 2021-05-20 | 12.2 | 5.3 | 9.0+ | -| [v1.0.7](https://github.com/SilenceLove/HXPHPicker/blob/main/Documentation/RELEASE_NOTE.md#107) | 2021-05-17 | 12.2 | 5.3 | 9.0+ | ## 版权协议 diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Core/Config/BaseConfiguration.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Core/Config/BaseConfiguration.swift index 7229c339..15a77478 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Core/Config/BaseConfiguration.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Core/Config/BaseConfiguration.swift @@ -27,5 +27,20 @@ open class BaseConfiguration { /// 支持的方向 public var supportedInterfaceOrientations: UIInterfaceOrientationMask = .all - public init() { } + /// 加载指示器类型 + public var indicatorType: IndicatorType = .circle { + didSet { PhotoManager.shared.indicatorType = indicatorType } + } + + public init() { PhotoManager.shared.indicatorType = indicatorType } +} + +public extension BaseConfiguration { + /// 加载指示器类型 + enum IndicatorType { + /// 渐变圆环 + case circle + /// 系统菊花 + case system + } } diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Core/Config/SelectBoxConfiguration.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Core/Config/SelectBoxConfiguration.swift index 5d5609ce..84480228 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Core/Config/SelectBoxConfiguration.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Core/Config/SelectBoxConfiguration.swift @@ -35,7 +35,7 @@ public class SelectBoxConfiguration { /// 选中之后的 勾勾 颜色 public lazy var tickColor: UIColor = { - return UIColor.white + return .white }() /// 暗黑风格下选中之后的 勾勾 颜色 @@ -45,12 +45,12 @@ public class SelectBoxConfiguration { /// 未选中时框框中间的颜色 public lazy var backgroundColor: UIColor = { - return UIColor.black.withAlphaComponent(0.4) + return .black.withAlphaComponent(0.4) }() /// 暗黑风格下未选中时框框中间的颜色 public lazy var darkBackgroundColor : UIColor = { - return UIColor.black.withAlphaComponent(0.2) + return .black.withAlphaComponent(0.2) }() /// 选中之后的背景颜色 diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Core/Extension/Core+CALayer.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Core/Extension/Core+CALayer.swift index c0f5fbe9..29f73807 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Core/Extension/Core+CALayer.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Core/Extension/Core+CALayer.swift @@ -8,8 +8,15 @@ import UIKit extension CALayer { - func convertedToImage() -> UIImage? { - UIGraphicsBeginImageContextWithOptions(frame.size, false, UIScreen.main.scale) + func convertedToImage(size: CGSize = .zero, + scale: CGFloat = UIScreen.main.scale) -> UIImage? { + var toSize: CGSize + if size.equalTo(.zero) { + toSize = frame.size + }else { + toSize = size + } + UIGraphicsBeginImageContextWithOptions(toSize, false, scale) let context = UIGraphicsGetCurrentContext() render(in: context!) let image = UIGraphicsGetImageFromCurrentImageContext() diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Core/Extension/Core+Dictionary.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Core/Extension/Core+Dictionary.swift index 8f94b629..2b36d97a 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Core/Extension/Core+Dictionary.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Core/Extension/Core+Dictionary.swift @@ -24,9 +24,12 @@ extension Dictionary { } return false } + var error: Error? { + self[AnyHashable(PHImageErrorKey) as! Key] as? Error + } /// 判断资源是否下载错误 var isError: Bool { - return self[AnyHashable(PHImageErrorKey) as! Key] != nil + self[AnyHashable(PHImageErrorKey) as! Key] != nil } /// 判断资源下载得到的是否为退化的 @@ -39,6 +42,6 @@ extension Dictionary { /// 判断资源是否下载完成 var downloadFinined: Bool { - return !isCancel && !isError && !isDegraded + !isCancel && !isError && !isDegraded } } diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Core/Extension/Core+PHAsset.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Core/Extension/Core+PHAsset.swift index 5a05cf88..0bac8d61 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Core/Extension/Core+PHAsset.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Core/Extension/Core+PHAsset.swift @@ -45,9 +45,14 @@ public extension PHAsset { options.isSynchronous = true options.deliveryMode = .fastFormat options.resizeMode = .fast - AssetManager.requestImageData(for: self, options: options) { (imageData, dataUTI, orientation, info) in - if imageData == nil && AssetManager.assetIsInCloud(for: info) { - isICloud = true + AssetManager.requestImageData(for: self, options: options) { (result) in + switch result { + case .failure(let error): + if AssetManager.assetIsInCloud(for: error.info) { + isICloud = true + } + default: + break } } }else if mediaType == PHAssetMediaType.video { diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Core/Extension/Core+String.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Core/Extension/Core+String.swift index 65d62533..0b68e8d9 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Core/Extension/Core+String.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Core/Extension/Core+String.swift @@ -11,22 +11,19 @@ import CommonCrypto extension String { - var localized: String { - get { - Bundle.localizedString(for: self) - } - } + var localized: String { Bundle.localizedString(for: self) } - var color: UIColor { - get { - UIColor.init(hexString: self) - } - } + var color: UIColor { UIColor.init(hexString: self) } - var image: UIImage? { - get { - UIImage.image(for: self) + var image: UIImage? { UIImage.image(for: self) } + + var lrc: String? { + var lrcString : String? + if let bundle = PhotoManager.shared.bundle, + let path = bundle.path(forResource: "musics", ofType: nil) { + lrcString = try? String(contentsOfFile: path + "/" + self) } + return lrcString } static func fileName(suffix: String) -> String { @@ -37,7 +34,7 @@ extension String { fileName.append(String(format: "%d", arguments: [nowDate])) fileName.append(String(format: "%d", arguments: [arc4random()%10000])) - return fileName.md5() + "." + suffix + return suffix.isEmpty ? fileName.md5() : fileName.md5() + "." + suffix } func md5() -> String { let str = self.cString(using: String.Encoding.utf8) @@ -53,6 +50,12 @@ extension String { return String(format: hash as String) } + func size(ofAttributes attributes: [NSAttributedString.Key: Any], maxWidth: CGFloat, maxHeight: CGFloat) -> CGSize { + let constraintRect = CGSize(width: maxWidth, height: maxHeight) + let boundingBox = self.boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, attributes:attributes, context: nil) + return boundingBox.size + } + /// 字符串宽度 /// - Parameters: /// - size: 字体大小 @@ -68,9 +71,7 @@ extension String { /// - maxHeight: 最大高度 /// - Returns: 字符串宽度 func width(ofFont font: UIFont, maxHeight: CGFloat) -> CGFloat { - let constraintRect = CGSize(width: CGFloat(MAXFLOAT), height: maxHeight) - let boundingBox = self.boundingRect(with: constraintRect, options: NSStringDrawingOptions.usesLineFragmentOrigin, attributes: [NSAttributedString.Key.font: font], context: nil) - return boundingBox.size.width + return size(ofAttributes: [NSAttributedString.Key.font: font], maxWidth: CGFloat(MAXFLOAT), maxHeight: maxHeight).width } /// 字符串高度 @@ -88,9 +89,7 @@ extension String { /// - maxWidth: 最大宽度 /// - Returns: 高度 func height(ofFont font: UIFont, maxWidth: CGFloat) -> CGFloat { - let constraintRect = CGSize(width: maxWidth, height: CGFloat(MAXFLOAT)) - let boundingBox = self.boundingRect(with: constraintRect, options: NSStringDrawingOptions.usesLineFragmentOrigin, attributes: [NSAttributedString.Key.font: font], context: nil) - return boundingBox.size.height + return size(ofAttributes: [NSAttributedString.Key.font: font], maxWidth: maxWidth, maxHeight: CGFloat(MAXFLOAT)).height } subscript(_ indexs: ClosedRange) -> String { diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Core/Extension/Core+UIImage.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Core/Extension/Core+UIImage.swift index 97fdca65..1e7cc669 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Core/Extension/Core+UIImage.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Core/Extension/Core+UIImage.swift @@ -86,7 +86,6 @@ extension UIImage { UIGraphicsEndImageContext() return image } - class func image(for color: UIColor?, havingSize: CGSize, radius: CGFloat = 0) -> UIImage? { if let color = color { let rect: CGRect @@ -295,7 +294,7 @@ extension UIImage { UIGraphicsBeginImageContextWithOptions(size, false, scale) draw(in: CGRect(origin: .zero, size: size)) for image in images { - image.draw(in: CGRect(origin: .zero, size: image.size)) + image.draw(in: CGRect(origin: .zero, size: size)) } let mergeImage = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Core/Model/AppearanceStyle.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Core/Model/AppearanceStyle.swift index cbd7202b..1512603f 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Core/Model/AppearanceStyle.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Core/Model/AppearanceStyle.swift @@ -8,7 +8,10 @@ import Foundation public enum AppearanceStyle: Int { - case varied = 0 //!< 跟随系统变化 - case normal = 1 //!< 正常风格,不会跟随系统变化 - case dark = 2 //!< 暗黑风格 + /// 跟随系统变化 + case varied = 0 + /// 正常风格,不会跟随系统变化 + case normal = 1 + /// 暗黑风格 + case dark = 2 } diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Core/Model/PhotoError.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Core/Model/PhotoError.swift index b2c180f8..42662f9f 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Core/Model/PhotoError.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Core/Model/PhotoError.swift @@ -8,14 +8,56 @@ import Foundation public enum PhotoError: LocalizedError { - case error(message: String) + + public enum `Type` { + case imageEmpty + case videoEmpty + case exportFailed + } + + case error(type: Type , message: String) } public extension PhotoError { var errorDescription: String? { switch self { - case let .error(message): + case let .error(_, message): return message } } } + +public enum AssetError: Error { + /// 写入文件失败 + case fileWriteFailed + /// 导出失败 + case exportFailed(Error?) + /// 无效的 Data + case invalidData + /// phAsset为空 + case invalidPHAsset + /// 网络地址为空 + case networkURLIsEmpty + /// 本地地址为空 + case localURLIsEmpty + /// 类型错误,例:本来是 .photo 却去获取 videoURL + case typeError + /// 从系统相册获取数据失败, [AnyHashable : Any]?: 系统获取失败的信息 + case requestFailed([AnyHashable : Any]?) + /// 需要同步ICloud上的资源 + case needSyncICloud + /// 同步ICloud失败 + case syncICloudFailed([AnyHashable : Any]?) + /// 指定地址存在其他文件,删除已存在的文件时发生错误 + case removeFileFailed + /// PHAssetResource 为空 + case assetResourceIsEmpty + /// PHAssetResource写入数据错误 + case assetResourceWriteDataFailed(Error) + /// 导出livePhoto里的图片地址失败 + case exportLivePhotoImageURLFailed(Error?) + /// 导出livePhoto里的视频地址失败 + case exportLivePhotoVideoURLFailed(Error?) + /// 导出livePhoto里的地址失败(图片失败信息,视频失败信息) + case exportLivePhotoURLFailed(Error?, Error?) +} diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Core/Util/AssetManager+AVAsset.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Core/Util/AssetManager+AVAsset.swift index 239ee397..f14a53af 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Core/Util/AssetManager+AVAsset.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Core/Util/AssetManager+AVAsset.swift @@ -8,9 +8,20 @@ import UIKit import Photos -public typealias AVAssetResultHandler = (AVAsset?, AVAudioMix?, [AnyHashable : Any]?) -> Void public extension AssetManager { + typealias AVAssetResultHandler = (Result) -> Void + + struct AVAssetResult { + public let avAsset: AVAsset + public let avAudioMix: AVAudioMix? + public let info: [AnyHashable : Any]? + } + + struct AVAssetError: Error { + public let info: [AnyHashable : Any]? + public let error: AssetError + } /// 请求获取AVAsset,如果资源在iCloud上会自动请求下载iCloud上的资源 /// - Parameters: @@ -24,34 +35,38 @@ public extension AssetManager { deliveryMode: PHVideoRequestOptionsDeliveryMode = .automatic, iCloudHandler: ((PHImageRequestID) -> Void)?, progressHandler: PHAssetImageProgressHandler?, - resultHandler: @escaping (AVAsset?, AVAudioMix?, [AnyHashable : Any]?, Bool) -> Void) -> PHImageRequestID { + resultHandler: @escaping AVAssetResultHandler) -> PHImageRequestID { let version = PHVideoRequestOptionsVersion.current - return requestAVAsset(for: asset, version: version, deliveryMode: deliveryMode, isNetworkAccessAllowed: false, progressHandler: progressHandler) { (avAsset, audioMix, info) in + return requestAVAsset(for: asset, version: version, deliveryMode: deliveryMode, isNetworkAccessAllowed: false, progressHandler: progressHandler) { (result) in DispatchQueue.main.async { - if self.assetDownloadFinined(for: info) { - if avAsset?.isPlayable == false { + switch result { + case .success(let avResult): + if avResult.avAsset.isPlayable == false { self.requestAVAsset(for: asset, deliveryMode: .highQualityFormat, iCloudHandler: iCloudHandler, progressHandler: progressHandler, resultHandler: resultHandler) }else { - resultHandler(avAsset, audioMix, info, true) + resultHandler(.success(avResult)) } - }else { - if self.assetIsInCloud(for: info) { - let iCloudRequestID = self.requestAVAsset(for: asset, version: version, deliveryMode: deliveryMode, isNetworkAccessAllowed: true, progressHandler: progressHandler) { (avAsset, audioMix, info) in + case .failure(let error): + switch error.error { + case .needSyncICloud: + let iCloudRequestID = self.requestAVAsset(for: asset, version: version, deliveryMode: deliveryMode, isNetworkAccessAllowed: true, progressHandler: progressHandler) { (result) in DispatchQueue.main.async { - if self.assetDownloadFinined(for: info) { - if avAsset?.isPlayable == false { + switch result { + case .success(let avResult): + if avResult.avAsset.isPlayable == false { self.requestAVAsset(for: asset, deliveryMode: .highQualityFormat, iCloudHandler: iCloudHandler, progressHandler: progressHandler, resultHandler: resultHandler) }else { - resultHandler(avAsset, audioMix, info, true) + resultHandler(.success(avResult)) } - }else { - resultHandler(avAsset, audioMix, info, false) + case .failure(let error): + resultHandler(.failure(.init(info: error.info, error: .syncICloudFailed(error.info)))) } } } iCloudHandler?(iCloudRequestID) - }else { - resultHandler(avAsset, audioMix, info, false) + default: + resultHandler(.failure(error)) + break } } } @@ -89,6 +104,18 @@ public extension AssetManager { class func requestAVAsset(for asset: PHAsset, options: PHVideoRequestOptions, resultHandler: @escaping AVAssetResultHandler) -> PHImageRequestID { - return PHImageManager.default().requestAVAsset(forVideo: asset, options: options, resultHandler: resultHandler) + return PHImageManager.default().requestAVAsset(forVideo: asset, options: options) { avAsset, avAudioMix, info in + DispatchQueue.main.async { + if self.assetDownloadFinined(for: info) && avAsset != nil { + resultHandler(.success(.init(avAsset: avAsset!, avAudioMix: avAudioMix, info: info))) + }else { + if self.assetIsInCloud(for: info) { + resultHandler(.failure(.init(info: info, error: .needSyncICloud))) + return + } + resultHandler(.failure(.init(info: info, error: .requestFailed(info)))) + } + } + } } } diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Core/Util/AssetManager+AVAssetExportSession.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Core/Util/AssetManager+AVAssetExportSession.swift index 564fff83..0fbbcfb8 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Core/Util/AssetManager+AVAssetExportSession.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Core/Util/AssetManager+AVAssetExportSession.swift @@ -85,12 +85,19 @@ public extension AssetManager { class func exportVideoURL(forVideo asset: PHAsset, toFile fileURL:URL, exportPreset: String, - completionHandler: @escaping (URL?, Error?) -> Void) { - requestAVAsset(for: asset, iCloudHandler: nil, progressHandler: nil) { (avAsset, avAudioMix, info, success) in - if let avAsset = avAsset { - self.exportVideoURL(forVideo: avAsset, toFile: fileURL, exportPreset: exportPreset, completionHandler: completionHandler) - }else { - completionHandler(nil, info?[PHImageErrorKey] as? Error) + completionHandler: @escaping (Result) -> Void) { + requestAVAsset(for: asset, iCloudHandler: nil, progressHandler: nil) { (result) in + switch result { + case .success(let avResult): + self.exportVideoURL(forVideo: avResult.avAsset, toFile: fileURL, exportPreset: exportPreset) { videoURL, error in + if let videoURL = videoURL { + completionHandler(.success(videoURL)) + }else { + completionHandler(.failure(.init(info: avResult.info, error: .exportFailed(error)))) + } + } + case .failure(let error): + completionHandler(.failure(error)) } } } diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Core/Util/AssetManager+ImageData.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Core/Util/AssetManager+ImageData.swift index 31096e52..bbc77688 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Core/Util/AssetManager+ImageData.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Core/Util/AssetManager+ImageData.swift @@ -8,12 +8,20 @@ import UIKit import Photos -/// imageData,dataUTI,Orientation,info -public typealias ImageDataResultHandler = (Data?, String?, UIImage.Orientation, [AnyHashable : Any]?) -> Void -/// imageData,dataUTI,Orientation,info,fetchSuccess -public typealias ImageDataFetchCompletion = (Data?, String?, UIImage.Orientation, [AnyHashable : Any]?, Bool) -> Void - public extension AssetManager { + typealias ImageDataResultHandler = (Result) -> Void + + struct ImageDataResult { + public let imageData: Data + public let dataUTI: String + public let imageOrientation: UIImage.Orientation + public let info: [AnyHashable : Any]? + } + + struct ImageDataError: Error { + public let info: [AnyHashable : Any]? + public let error: AssetError + } /// 请求imageData,如果资源在iCloud上会自动请求下载iCloud上的资源 注意处理 HEIC格式 /// - Parameters: @@ -27,22 +35,31 @@ public extension AssetManager { version: PHImageRequestOptionsVersion, iCloudHandler: ((PHImageRequestID) -> Void)?, progressHandler: PHAssetImageProgressHandler?, - resultHandler: @escaping ImageDataFetchCompletion) -> PHImageRequestID { - return requestImageData(for: asset, version: version, isNetworkAccessAllowed: false, progressHandler: progressHandler) { (data, dataUTI, imageOrientation, info) in + resultHandler: @escaping ImageDataResultHandler) -> PHImageRequestID { + return requestImageData(for: asset, version: version, isNetworkAccessAllowed: false, progressHandler: progressHandler) { (result) in DispatchQueue.main.async { - if self.assetDownloadFinined(for: info) { - resultHandler(data, dataUTI, imageOrientation, info, true) - }else { - if self.assetIsInCloud(for: info) { - let iCloudRequestID = self.requestImageData(for: asset, version: version, isNetworkAccessAllowed: true, progressHandler: progressHandler, resultHandler: { (data, dataUTI, imageOrientation, info) in + switch result { + case .failure(let error): + switch error.error { + case .needSyncICloud: + let iCloudRequestID = self.requestImageData(for: asset, version: version, isNetworkAccessAllowed: true, progressHandler: progressHandler, resultHandler: { (result) in DispatchQueue.main.async { - resultHandler(data, dataUTI, imageOrientation, info, self.assetDownloadFinined(for: info)) + switch result { + case .success(_): + resultHandler(result) + case .failure(let error): + resultHandler(.failure(.init(info: error.info, error: .syncICloudFailed(error.info)))) + } } }) iCloudHandler?(iCloudRequestID) - }else { - resultHandler(data, dataUTI, imageOrientation, info, false) + default: + resultHandler(.failure(error)) + break } + default: + resultHandler(result) + break } } } @@ -89,23 +106,45 @@ public extension AssetManager { } else { sureOrientation = .up; } - + func result() { + if let imageData = imageData, self.assetDownloadFinined(for: info) { + resultHandler(.success(.init(imageData: imageData, dataUTI: dataUTI!, imageOrientation: sureOrientation, info: info))) + return + } + + if let inICloud = info?.inICloud, inICloud { + resultHandler(.failure(.init(info: info, error: .needSyncICloud))) + }else { + resultHandler(.failure(.init(info: info, error: .requestFailed(info)))) + } + } if DispatchQueue.isMain { - resultHandler(imageData, dataUTI, sureOrientation, info) + result() }else { DispatchQueue.main.async { - resultHandler(imageData, dataUTI, sureOrientation, info) + result() } } } } else { // Fallback on earlier versions return PHImageManager.default().requestImageData(for: asset, options: options) { (imageData, dataUTI, imageOrientation, info) in + func result() { + if let imageData = imageData { + resultHandler(.success(.init(imageData: imageData, dataUTI: dataUTI!, imageOrientation: imageOrientation, info: info))) + return + } + if let inICloud = info?.inICloud, inICloud { + resultHandler(.failure(.init(info: info, error: .needSyncICloud))) + }else { + resultHandler(.failure(.init(info: info, error: .requestFailed(info)))) + } + } if DispatchQueue.isMain { - resultHandler(imageData, dataUTI, imageOrientation, info) + result() }else { DispatchQueue.main.async { - resultHandler(imageData, dataUTI, imageOrientation, info) + result() } } } diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Core/Util/AssetManager+ImageURL.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Core/Util/AssetManager+ImageURL.swift index 290f6542..a8903499 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Core/Util/AssetManager+ImageURL.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Core/Util/AssetManager+ImageURL.swift @@ -8,10 +8,9 @@ import UIKit import Photos -public typealias ImageURLResultHandler = (URL?) -> Void - // MARK: 获取图片地址 public extension AssetManager { + typealias ImageURLResultHandler = (Result) -> Void /// 请求获取图片地址 /// - Parameters: @@ -44,13 +43,17 @@ public extension AssetManager { resultHandler: @escaping ImageURLResultHandler) { asset.checkAdjustmentStatus { (isAdjusted) in if isAdjusted { - self.requestImageData(for: asset, version: .current, iCloudHandler: nil, progressHandler: nil) { (imageData, _, _, _, downloadSuccess) in - if let imageData = imageData, - let imageURL = PhotoTools.write(toFile: fileURL, imageData: imageData) { - resultHandler(imageURL) - return + self.requestImageData(for: asset, version: .current, iCloudHandler: nil, progressHandler: nil) { (result) in + switch result { + case .success(let dataResult): + if let imageURL = PhotoTools.write(toFile: fileURL, imageData: dataResult.imageData) { + resultHandler(.success(imageURL)) + }else { + resultHandler(.failure(.fileWriteFailed)) + } + case .failure(let error): + resultHandler(.failure(error.error)) } - resultHandler(nil) } }else { var imageResource: PHAssetResource? @@ -61,11 +64,11 @@ public extension AssetManager { } } if imageResource == nil { - resultHandler(nil) + resultHandler(.failure(.assetResourceIsEmpty)) return } if !PhotoTools.removeFile(fileURL: fileURL) { - resultHandler(nil) + resultHandler(.failure(.removeFileFailed)) return } let imageURL = fileURL @@ -74,9 +77,9 @@ public extension AssetManager { PHAssetResourceManager.default().writeData(for: imageResource!, toFile: imageURL, options: options) { (error) in DispatchQueue.main.async { if error == nil { - resultHandler(imageURL) + resultHandler(.success(imageURL)) }else { - resultHandler(nil) + resultHandler(.failure(.assetResourceWriteDataFailed(error!))) } } } diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Core/Util/AssetManager+LivePhotoURL.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Core/Util/AssetManager+LivePhotoURL.swift index 438464fc..765cbd8e 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Core/Util/AssetManager+LivePhotoURL.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Core/Util/AssetManager+LivePhotoURL.swift @@ -20,12 +20,12 @@ public extension AssetManager { } progressHandler: { (progress, error, stop, info) in } resultHandler: { (livePhoto, info, downloadSuccess) in if livePhoto == nil { - completionHandler(.allError(PhotoError.error(message: "livePhoto为nil,获取失败"), PhotoError.error(message: "livePhoto为nil,获取失败"))) + completionHandler(.allError(PhotoError.error(type: .imageEmpty, message: "livePhoto为nil,获取失败"), PhotoError.error(type: .videoEmpty, message: "livePhoto为nil,获取失败"))) return } let assetResources: [PHAssetResource] = PHAssetResource.assetResources(for: livePhoto!) if assetResources.isEmpty { - completionHandler(.allError(PhotoError.error(message: "assetResources为nil,获取失败"), PhotoError.error(message: "assetResources为nil,获取失败"))) + completionHandler(.allError(PhotoError.error(type: .imageEmpty, message: "assetResources为nil,获取失败"), PhotoError.error(type: .videoEmpty, message: "assetResources为nil,获取失败"))) return } let options = PHAssetResourceRequestOptions.init() @@ -94,7 +94,7 @@ public extension AssetManager { } } else { // Fallback on earlier versions - completionHandler(.allError(PhotoError.error(message: "系统版本低于9.1"), PhotoError.error(message: "系统版本低于9.1"))) + completionHandler(.allError(PhotoError.error(type: .imageEmpty, message: "系统版本低于9.1"), PhotoError.error(type: .videoEmpty, message: "系统版本低于9.1"))) } } @@ -111,16 +111,16 @@ public extension AssetManager { } progressHandler: { (progress, error, stop, info) in } resultHandler: { (livePhoto, info, downloadSuccess) in if livePhoto == nil { - completionHandler(nil, .allError(PhotoError.error(message: "livePhoto为nil,获取失败"), PhotoError.error(message: "livePhoto为nil,获取失败"))) + completionHandler(nil, .allError(PhotoError.error(type: .imageEmpty, message: "livePhoto为nil,获取失败"), PhotoError.error(type: .videoEmpty, message: "livePhoto为nil,获取失败"))) return } let assetResources: [PHAssetResource] = PHAssetResource.assetResources(for: livePhoto!) if assetResources.isEmpty { - completionHandler(nil, .allError(PhotoError.error(message: "assetResources为nil,获取失败"), PhotoError.error(message: "assetResources为nil,获取失败"))) + completionHandler(nil, .allError(PhotoError.error(type: .imageEmpty, message: "assetResources为nil,获取失败"), PhotoError.error(type: .videoEmpty, message: "assetResources为nil,获取失败"))) return } if !PhotoTools.removeFile(fileURL: fileURL) { - completionHandler(nil, .allError(PhotoError.error(message: "指定的地址已存在"), PhotoError.error(message: "指定的地址已存在"))) + completionHandler(nil, .allError(PhotoError.error(type: .imageEmpty, message: "指定的地址已存在"), PhotoError.error(type: .videoEmpty, message: "指定的地址已存在"))) return } let videoURL = fileURL @@ -153,7 +153,7 @@ public extension AssetManager { } } else { // Fallback on earlier versions - completionHandler(nil, .allError(PhotoError.error(message: "系统版本低于9.1"), PhotoError.error(message: "系统版本低于9.1"))) + completionHandler(nil, .allError(PhotoError.error(type: .imageEmpty, message: "系统版本低于9.1"), PhotoError.error(type: .videoEmpty, message: "系统版本低于9.1"))) } } // MARK: 获取LivePhoto里的图片地址和视频地址 @@ -166,12 +166,12 @@ public extension AssetManager { } progressHandler: { (progress, error, stop, info) in } resultHandler: { (livePhoto, info, downloadSuccess) in if livePhoto == nil { - completionHandler(.allError(PhotoError.error(message: "livePhoto为nil,获取失败"), PhotoError.error(message: "livePhoto为nil,获取失败"))) + completionHandler(.allError(PhotoError.error(type: .imageEmpty, message: "livePhoto为nil,获取失败"), PhotoError.error(type: .videoEmpty, message: "livePhoto为nil,获取失败"))) return } let assetResources: [PHAssetResource] = PHAssetResource.assetResources(for: livePhoto!) if assetResources.isEmpty { - completionHandler(.allError(PhotoError.error(message: "assetResources为nil,获取失败"), PhotoError.error(message: "assetResources为nil,获取失败"))) + completionHandler(.allError(PhotoError.error(type: .imageEmpty, message: "assetResources为nil,获取失败"), PhotoError.error(type: .videoEmpty, message: "assetResources为nil,获取失败"))) return } let options = PHAssetResourceRequestOptions.init() @@ -238,7 +238,7 @@ public extension AssetManager { } } else { // Fallback on earlier versions - completionHandler(.allError(PhotoError.error(message: "系统版本低于9.1"), PhotoError.error(message: "系统版本低于9.1"))) + completionHandler(.allError(PhotoError.error(type: .imageEmpty, message: "系统版本低于9.1"), PhotoError.error(type: .videoEmpty, message: "系统版本低于9.1"))) } } } diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Core/Util/AssetManager+VideoURL.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Core/Util/AssetManager+VideoURL.swift index d33e0660..96f977e5 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Core/Util/AssetManager+VideoURL.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Core/Util/AssetManager+VideoURL.swift @@ -8,11 +8,11 @@ import UIKit import Photos -public typealias VideoURLResultHandler = (URL?) -> Void - // MARK: 获取视频地址 public extension AssetManager { + typealias VideoURLResultHandler = (Result) -> Void + /// 请求获取视频地址 /// - Parameters: /// - asset: 对应的 PHAsset 数据 @@ -21,7 +21,7 @@ public extension AssetManager { resultHandler: @escaping VideoURLResultHandler) { requestAVAsset(for: asset) { (reqeustID) in } progressHandler: { (progress, error, stop, info) in - } resultHandler: { (avAsset, audioMix, info, downloadSuccess) in + } resultHandler: { (_) in self.requestVideoURL(mp4Format: asset, resultHandler: resultHandler) } } @@ -46,12 +46,14 @@ public extension AssetManager { resultHandler: @escaping VideoURLResultHandler) { asset.checkAdjustmentStatus { (isAdjusted) in if isAdjusted { - self.requestAVAsset(for: asset, iCloudHandler: nil, progressHandler: nil) { (avAsset, audioMix, info, success) in - if let urlAsset = avAsset as? AVURLAsset, - PhotoTools.copyFile(at: urlAsset.url, to: fileURL) { - resultHandler(fileURL) - }else { - if let avAsset = avAsset { + self.requestAVAsset(for: asset, iCloudHandler: nil, progressHandler: nil) { (result) in + switch result { + case .success(let avResult): + let avAsset = avResult.avAsset + if let urlAsset = avAsset as? AVURLAsset, + PhotoTools.copyFile(at: urlAsset.url, to: fileURL) { + resultHandler(.success(fileURL)) + }else { var presetName: String let presets = AVAssetExportSession.exportPresets(compatibleWith: avAsset) if presets.contains(AVAssetExportPresetHighestQuality) { @@ -69,16 +71,16 @@ public extension AssetManager { DispatchQueue.main.async { switch exportSession?.status { case .completed: - resultHandler(fileURL) + resultHandler(.success(fileURL)) case .failed, .cancelled: - resultHandler(nil) + resultHandler(.failure(.exportFailed(exportSession?.error))) default: break } } }) - return } - resultHandler(nil) + case .failure(let error): + resultHandler(.failure(error.error)) } } }else { @@ -89,11 +91,11 @@ public extension AssetManager { } } if videoResource == nil { - resultHandler(nil) + resultHandler(.failure(.assetResourceIsEmpty)) return } if !PhotoTools.removeFile(fileURL: fileURL) { - resultHandler(nil) + resultHandler(.failure(.removeFileFailed)) return } let videoURL = fileURL @@ -102,9 +104,9 @@ public extension AssetManager { PHAssetResourceManager.default().writeData(for: videoResource!, toFile: videoURL, options: options) { (error) in DispatchQueue.main.async { if error == nil { - resultHandler(videoURL) + resultHandler(.success(videoURL)) }else { - resultHandler(nil) + resultHandler(.failure(.assetResourceWriteDataFailed(error!))) } } } diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Core/Util/PhotoManager+Audio.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Core/Util/PhotoManager+Audio.swift index fbbab277..4d34edeb 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Core/Util/PhotoManager+Audio.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Core/Util/PhotoManager+Audio.swift @@ -10,7 +10,7 @@ import AVKit extension PhotoManager: AVAudioPlayerDelegate { @discardableResult - func playMusic(filePath path: String, finished: @escaping () -> Void) -> Bool { + public func playMusic(filePath path: String, finished: @escaping () -> Void) -> Bool { audioPlayFinish = finished let url = URL(fileURLWithPath: path) if let currentURL = audioPlayer?.url, @@ -32,12 +32,16 @@ extension PhotoManager: AVAudioPlayerDelegate { } } - func stopPlayMusic() { + public func stopPlayMusic() { audioPlayer?.stop() audioPlayer = nil audioPlayFinish = nil } + public func changeAudioPlayerVolume(_ volume: Float) { + audioPlayer?.volume = volume + } + public func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) { if flag { diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Core/Util/PhotoManager+Download.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Core/Util/PhotoManager+Download.swift index 4f1582a1..fc79d4f2 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Core/Util/PhotoManager+Download.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Core/Util/PhotoManager+Download.swift @@ -11,10 +11,38 @@ extension PhotoManager: URLSessionDownloadDelegate { @discardableResult public func downloadTask(with url: URL, - progress: @escaping (Double, URLSessionDownloadTask) -> Void, - completionHandler: @escaping (URL?, Error?) -> Void) -> URLSessionDownloadTask { + toFile fileURL: URL? = nil, + ext: Any? = nil, + progress: ((Double, URLSessionDownloadTask) -> Void)? = nil, + completionHandler: @escaping (URL?, Error?, Any?) -> Void) -> URLSessionDownloadTask { let key = url.absoluteString - downloadProgresss[key] = progress + if key.hasSuffix("mp4") && PhotoTools.isCached(forVideo: key) { + let videoURL = PhotoTools.getVideoCacheURL(for: key) + if let fileURL = fileURL, + videoURL.absoluteString != fileURL.absoluteString { + PhotoTools.copyFile(at: videoURL, to: fileURL) + } + completionHandler(fileURL, nil, ext) + return URLSessionDownloadTask() + } + if key.hasSuffix("mp3") && PhotoTools.isCached(forAudio: key) { + let audioURL = PhotoTools.getAudioTmpURL(for: key) + if let fileURL = fileURL, + audioURL.absoluteString != fileURL.absoluteString { + PhotoTools.copyFile(at: audioURL, to: fileURL) + } + completionHandler(fileURL, nil, ext) + return URLSessionDownloadTask() + } + if let fileURL = fileURL { + downloadFileURLs[key] = fileURL + } + if let ext = ext { + downloadExts[key] = ext + } + if let progress = progress { + downloadProgresss[key] = progress + } downloadCompletions[key] = completionHandler if let task = downloadTasks[key] { if task.state == .suspended { @@ -35,6 +63,7 @@ extension PhotoManager: URLSessionDownloadDelegate { return } task?.suspend() + downloadExts.removeValue(forKey: key) downloadCompletions.removeValue(forKey: key) downloadProgresss.removeValue(forKey: key) } @@ -43,6 +72,8 @@ extension PhotoManager: URLSessionDownloadDelegate { let key = url.absoluteString let task = downloadTasks[key] task?.cancel() + downloadExts.removeValue(forKey: key) + downloadFileURLs.removeValue(forKey: key) downloadCompletions.removeValue(forKey: key) downloadProgresss.removeValue(forKey: key) downloadTasks.removeValue(forKey: key) @@ -59,32 +90,52 @@ extension PhotoManager: URLSessionDownloadDelegate { public func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) { let responseURL = downloadTask.currentRequest!.url! - let completionHandler = downloadCompletions[responseURL.absoluteString] + let key = responseURL.absoluteString + let completionHandler = downloadCompletions[key] + let ext = downloadExts[key] if let httpResponse = downloadTask.response as? HTTPURLResponse, httpResponse.statusCode != 200 { PhotoTools.removeFile(fileURL: location) DispatchQueue.main.async { - completionHandler?(nil, nil) + completionHandler?(nil, nil, ext) } return } - let videoURL = PhotoTools.getVideoCacheURL(for: responseURL.absoluteString) - do { - PhotoTools.removeFile(fileURL: videoURL) - try FileManager.default.moveItem(at: location, to: videoURL) + if let url = downloadFileURLs[key] { + PhotoTools.removeFile(fileURL: url) + try? FileManager.default.moveItem(at: location, to: url) DispatchQueue.main.async { - completionHandler?(videoURL, nil) + completionHandler?(url, nil, ext) } - return - } catch { } - self.removeTask(responseURL) + }else { + var url: URL + if key.hasSuffix("mp4") { + let videoURL = PhotoTools.getVideoCacheURL(for: key) + PhotoTools.removeFile(fileURL: videoURL) + try? FileManager.default.moveItem(at: location, to: videoURL) + url = videoURL + }else if key.hasSuffix("mp3") { + let audioURL = PhotoTools.getAudioTmpURL(for: key) + PhotoTools.removeFile(fileURL: audioURL) + try? FileManager.default.moveItem(at: location, to: audioURL) + url = audioURL + }else { + url = location + } + DispatchQueue.main.async { + completionHandler?(url, nil, ext) + } + } + removeTask(responseURL) } public func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) { let responseURL = task.currentRequest!.url! + let key = responseURL.absoluteString + let ext = downloadExts[key] if let error = error { - let completionHandler = downloadCompletions[responseURL.absoluteString] + let completionHandler = downloadCompletions[key] DispatchQueue.main.async { - completionHandler?(nil, error) + completionHandler?(nil, error, ext) } } self.removeTask(responseURL) diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Core/Util/PhotoManager.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Core/Util/PhotoManager.swift index 9edea913..1ac21472 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Core/Util/PhotoManager.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Core/Util/PhotoManager.swift @@ -50,6 +50,8 @@ public class PhotoManager: NSObject { var bundle: Bundle? /// 是否使用了自定义的语言 var isCustomLanguage: Bool = false + /// 加载指示器类型 + var indicatorType: BaseConfiguration.IndicatorType = .circle lazy var downloadSession: URLSession = { let session = URLSession.init(configuration: .default, delegate: self, delegateQueue: nil) @@ -62,14 +64,13 @@ public class PhotoManager: NSObject { }() var audioPlayer: AVAudioPlayer? - var audioPlayFinish: (() -> Void)? var downloadTasks: [String : URLSessionDownloadTask] = [:] - - var downloadCompletions: [String : (URL?, Error?) -> Void] = [:] - + var downloadCompletions: [String : (URL?, Error?, Any?) -> Void] = [:] var downloadProgresss: [String : (Double, URLSessionDownloadTask) -> Void] = [:] + var downloadFileURLs: [String : URL] = [:] + var downloadExts: [String : Any] = [:] private override init() { super.init() diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Core/Util/PhotoTools+File.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Core/Util/PhotoTools+File.swift index 568a3ba5..404a2de2 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Core/Util/PhotoTools+File.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Core/Util/PhotoTools+File.swift @@ -48,22 +48,43 @@ extension PhotoTools { /// 获取视频缓存文件夹路径 public class func getVideoCacheFolderPath() -> String { var cachePath = getSystemCacheFolderPath() - cachePath.append(contentsOf: "/com.silence.HXPHPicker.videoCache") + cachePath.append(contentsOf: "/com.silence.HXPHPicker/videoCache") return cachePath } + public class func getAudioTmpFolderPath() -> String { + var tmpPath = NSTemporaryDirectory() + tmpPath.append(contentsOf: "com.silence.HXPHPicker/audioCache") + return tmpPath + } + + /// 删除缓存 + public class func removeCache() { + removeVideoCache() + removeAudioCache() + } + /// 删除视频缓存 + @discardableResult public class func removeVideoCache() -> Bool { return removeFile(filePath: getVideoCacheFolderPath()) } + /// 删除音频临时缓存 + @discardableResult + public class func removeAudioCache() -> Bool { + return removeFile(filePath: getAudioTmpFolderPath()) + } + /// 获取视频缓存文件大小 + @discardableResult public class func getVideoCacheFileSize() -> Int { return folderSize(atPath: getVideoCacheFolderPath()) } /// 获取视频缓存文件地址 /// - Parameter key: 生成文件的key + @discardableResult public class func getVideoCacheURL(for key: String) -> URL { var cachePath = getVideoCacheFolderPath() let fileManager = FileManager.default @@ -76,15 +97,35 @@ extension PhotoTools { return URL.init(fileURLWithPath: cachePath) } + @discardableResult + public class func getAudioTmpURL(for key: String) -> URL { + var cachePath = getAudioTmpFolderPath() + let fileManager = FileManager.default + if !fileManager.fileExists(atPath: cachePath) { + try? fileManager.createDirectory(atPath: cachePath, withIntermediateDirectories: true, attributes: nil) + } + cachePath.append(contentsOf: "/" + key.md5() + ".mp3") + return URL.init(fileURLWithPath: cachePath) + } + /// 视频是否有缓存 /// - Parameter key: 对应视频的key + @discardableResult public class func isCached(forVideo key: String) -> Bool { let fileManager = FileManager.default let filePath = getVideoCacheURL(for: key).path return fileManager.fileExists(atPath: filePath) } + @discardableResult + public class func isCached(forAudio key: String) -> Bool { + let fileManager = FileManager.default + let filePath = getAudioTmpURL(for: key).path + return fileManager.fileExists(atPath: filePath) + } + /// 获取对应后缀的临时路径 + @discardableResult public class func getTmpURL(for suffix: String) -> URL { var tmpPath = NSTemporaryDirectory() tmpPath.append(contentsOf: String.fileName(suffix: suffix)) @@ -92,6 +133,7 @@ extension PhotoTools { return tmpURL } /// 获取图片临时路径 + @discardableResult public class func getImageTmpURL(_ imageContentType: ImageContentType = .jpg) -> URL { var suffix: String switch imageContentType { @@ -107,10 +149,12 @@ extension PhotoTools { return getTmpURL(for: suffix) } /// 获取视频临时路径 + @discardableResult public class func getVideoTmpURL() -> URL { return getTmpURL(for: "mp4") } /// 将UIImage转换成Data + @discardableResult public class func getImageData(for image: UIImage?) -> Data? { if let pngData = image?.pngData() { return pngData @@ -120,6 +164,7 @@ extension PhotoTools { return nil } + @discardableResult class func write(toFile fileURL:URL? = nil, image: UIImage?) -> URL? { if let imageData = getImageData(for: image) { return write(toFile: fileURL, imageData: imageData) @@ -127,6 +172,7 @@ extension PhotoTools { return nil } + @discardableResult class func write(toFile fileURL:URL? = nil, imageData: Data) -> URL? { let imageURL = fileURL == nil ? getImageTmpURL(imageData.isGif ? .gif : .jpg) : fileURL! do { @@ -140,6 +186,7 @@ extension PhotoTools { } } + @discardableResult class func copyFile(at srcURL: URL, to dstURL: URL) -> Bool { if srcURL.path == dstURL.path { return true diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Core/Util/PhotoTools.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Core/Util/PhotoTools.swift index cceae5e5..65b780b6 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Core/Util/PhotoTools.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Core/Util/PhotoTools.swift @@ -12,8 +12,6 @@ import Photos import Kingfisher #endif -public typealias statusHandler = (PHAuthorizationStatus) -> () - public class PhotoTools { /// 跳转系统设置界面 @@ -90,12 +88,30 @@ public class PhotoTools { }else if time < 60 { return String.init(format: "00:%d", arguments: [time]) }else { - let min = Int(time / 60) + var min = Int(time / 60) let sec = time - (min * 60) - if sec < 10 { - return String.init(format: "%d:0%d", arguments: [min,sec]) + if min < 60 { + if sec < 10 { + return String.init(format: "%d:0%d", arguments: [min,sec]) + }else { + return String.init(format: "%d:%d", arguments: [min,sec]) + } }else { - return String.init(format: "%d:%d", arguments: [min,sec]) + let hour = Int(min / 60) + min -= hour * 60 + if min < 10 { + if sec < 10 { + return String.init(format: "%d:0%d:0%d", arguments: [hour,min,sec]) + }else { + return String.init(format: "%d:0%d:%d", arguments: [hour,min,sec]) + } + }else { + if sec < 10 { + return String.init(format: "%d:%d:0%d", arguments: [hour,min,sec]) + }else { + return String.init(format: "%d:%d:%d", arguments: [hour,min,sec]) + } + } } } } @@ -216,7 +232,7 @@ public class PhotoTools { if supportedTypeArray.contains(AVFileType.mp4) { exportSession.outputFileType = .mp4 }else if supportedTypeArray.isEmpty { - completion(nil, PhotoError.error(message: "不支持导出该类型视频")) + completion(nil, PhotoError.error(type: .exportFailed, message: "不支持导出该类型视频")) return }else { exportSession.outputFileType = supportedTypeArray.first @@ -237,11 +253,11 @@ public class PhotoTools { } }) }else { - completion(nil, PhotoError.error(message: "不支持导出该类型视频")) + completion(nil, PhotoError.error(type: .exportFailed, message: "不支持导出该类型视频")) return } }else { - completion(nil, PhotoError.error(message: "设备不支持导出:" + presentName)) + completion(nil, PhotoError.error(type: .exportFailed, message: "设备不支持导出:" + presentName)) return } } diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Core/View/ProgressHUD.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Core/View/ProgressHUD.swift index 98e50868..5a998467 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Core/View/ProgressHUD.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Core/View/ProgressHUD.swift @@ -37,10 +37,17 @@ class ProgressHUD: UIView { return blurEffectView }() - lazy var indicatorView : UIActivityIndicatorView = { - let indicatorView = UIActivityIndicatorView.init(style: .whiteLarge) - indicatorView.hidesWhenStopped = true - return indicatorView + lazy var indicatorView : UIView = { + if PhotoManager.shared.indicatorType == .circle { + let indicatorView = ProgressIndefiniteView(frame: CGRect(origin: .zero, size: CGSize(width: 45, height: 45))) + indicatorView.startAnimating() + return indicatorView + }else { + let indicatorView = UIActivityIndicatorView.init(style: .whiteLarge) + indicatorView.hidesWhenStopped = true + indicatorView.startAnimating() + return indicatorView + } }() lazy var textLb: UILabel = { @@ -132,11 +139,13 @@ class ProgressHUD: UIView { UIView.animate(withDuration: 0.25) { self.backgroundView.alpha = 0 } completion: { (finished) in + self.indicatorView._stopAnimating() self.removeFromSuperview() } }else { - self.backgroundView.alpha = 0 + backgroundView.alpha = 0 removeFromSuperview() + indicatorView._stopAnimating() } } func updateText(text: String) { @@ -164,7 +173,6 @@ class ProgressHUD: UIView { let centenrX = textMaxWidth / 2 textLb.centerX = centenrX if mode == .indicator { - indicatorView.startAnimating() indicatorView.centerX = centenrX if text != nil { textLb.y = indicatorView.frame.maxY + 10 @@ -272,3 +280,115 @@ class ProgressHUD: UIView { fatalError("init(coder:) has not been implemented") } } + + +class ProgressIndefiniteView: UIView { + + lazy var circleLayer: CAShapeLayer = { + let lineWidth: CGFloat = 3 + let circleLayer = CAShapeLayer() + circleLayer.frame = bounds + circleLayer.contentsScale = UIScreen.main.scale + circleLayer.strokeColor = UIColor.white.cgColor + circleLayer.fillColor = UIColor.clear.cgColor + circleLayer.lineCap = .round + circleLayer.lineJoin = .bevel + circleLayer.lineWidth = lineWidth + let path = UIBezierPath(arcCenter: CGPoint(x: width * 0.5, y: height * 0.5), + radius: width * 0.5 - lineWidth * 0.5, + startAngle: -CGFloat.pi * 0.5, + endAngle: -CGFloat.pi * 0.5 + CGFloat.pi * 4, + clockwise: true) + circleLayer.path = path.cgPath + circleLayer.mask = maskLayer + return circleLayer + }() + + lazy var maskLayer: CALayer = { + let maskLayer = CALayer() + maskLayer.contentsScale = UIScreen.main.scale + maskLayer.frame = bounds + let topLayer = CAGradientLayer.init() + topLayer.frame = CGRect(x: width * 0.5, y: 0, width: width * 0.5, height: height) + topLayer.colors = [ + UIColor.white.withAlphaComponent(0.8).cgColor, + UIColor.white.withAlphaComponent(0.4).cgColor + ] + topLayer.startPoint = CGPoint(x: 0, y: 0); + topLayer.endPoint = CGPoint(x: 0, y: 1); + maskLayer.addSublayer(topLayer) + let bottomLayer = CAGradientLayer.init() + bottomLayer.frame = CGRect(x: 0, y: 0, width: width * 0.5, height: height) + bottomLayer.colors = [ + UIColor.white.withAlphaComponent(0.4).cgColor, + UIColor.white.withAlphaComponent(0).cgColor + ] + bottomLayer.startPoint = CGPoint(x: 0, y: 1); + bottomLayer.endPoint = CGPoint(x: 0, y: 0); + maskLayer.addSublayer(bottomLayer) + return maskLayer + }() + var isAnimating: Bool = false + + override func willMove(toSuperview newSuperview: UIView?) { + super.willMove(toSuperview: newSuperview) + if newSuperview != nil { + layer.addSublayer(circleLayer) + }else { + circleLayer.removeFromSuperlayer() + _stopAnimating() + } + } + func startAnimating() { + if isAnimating { return } + isAnimating = true + let duration: CFTimeInterval = 0.5 + let animation = CABasicAnimation(keyPath: "transform.rotation") + animation.fromValue = 0 + animation.toValue = CGFloat.pi * 2 + animation.duration = duration + animation.repeatCount = MAXFLOAT + animation.isRemovedOnCompletion = false + animation.timingFunction = CAMediaTimingFunction(name: .linear) + circleLayer.mask?.add(animation, forKey: nil) + + let animationGroup = CAAnimationGroup() + animationGroup.duration = duration + animationGroup.repeatCount = MAXFLOAT + animationGroup.isRemovedOnCompletion = false + animationGroup.timingFunction = CAMediaTimingFunction(name: .linear) + + let strokeStartAnimation = CABasicAnimation(keyPath: "strokeStart") + strokeStartAnimation.fromValue = 0.015 + strokeStartAnimation.toValue = 0.515 + + let strokeEndAnimation = CABasicAnimation(keyPath: "strokeEnd") + strokeEndAnimation.fromValue = 0.485 + strokeEndAnimation.toValue = 0.985 + + animationGroup.animations = [strokeStartAnimation, strokeEndAnimation] + circleLayer.add(animationGroup, forKey: nil) + } + func stopAnimating() { + if !isAnimating { return } + maskLayer.removeAllAnimations() + isAnimating = false + } +} + +fileprivate extension UIView { + func _startAnimating() { + if let indefiniteView = self as? ProgressIndefiniteView { + indefiniteView.startAnimating() + }else if let indefiniteView = self as? UIActivityIndicatorView { + indefiniteView.startAnimating() + } + } + func _stopAnimating() { + if let indefiniteView = self as? ProgressIndefiniteView { + indefiniteView.stopAnimating() + }else if let indefiniteView = self as? UIActivityIndicatorView { + indefiniteView.stopAnimating() + } + } +} diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Core/View/SelectBoxView.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Core/View/SelectBoxView.swift index 1d8aac0c..00b9d7c7 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Core/View/SelectBoxView.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Core/View/SelectBoxView.swift @@ -138,7 +138,7 @@ public class SelectBoxView: UIControl { } public override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { - if CGRect(x: -15, y: -15, width: width + 30, height: height + 30).contains(point) { + if isUserInteractionEnabled && CGRect(x: -15, y: -15, width: width + 30, height: height + 30).contains(point) { return self } return super.hitTest(point, with: event) diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Editor/Config/PhotoEditorConfiguration.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/Config/PhotoEditorConfiguration.swift index 81a4f683..39a9a9e6 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Editor/Config/PhotoEditorConfiguration.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/Config/PhotoEditorConfiguration.swift @@ -10,6 +10,9 @@ import UIKit /// 旋转会重置所有编辑效果 open class PhotoEditorConfiguration: EditorConfiguration { + /// 控制画笔、贴图...导出之后清晰程度 + public var scale: CGFloat = 2 + /// 编辑器默认状态 public var state: PhotoEditorViewController.State = .normal @@ -20,19 +23,23 @@ open class PhotoEditorConfiguration: EditorConfiguration { public lazy var toolView: EditorToolViewConfiguration = { let config = EditorToolViewConfiguration.init() let graffiti = EditorToolOptions(imageName: "hx_editor_tools_graffiti", - type: .graffiti) + type: .graffiti) + let chartlet = EditorToolOptions(imageName: "hx_editor_photo_tools_emoji", + type: .chartlet) + let text = EditorToolOptions(imageName: "hx_editor_photo_tools_text", + type: .text) let crop = EditorToolOptions(imageName: "hx_editor_photo_crop", - type: .cropping) + type: .cropping) let mosaic = EditorToolOptions(imageName: "hx_editor_tools_mosaic", - type: .mosaic) + type: .mosaic) let filter = EditorToolOptions(imageName: "hx_editor_tools_filter", - type: .filter) - config.toolOptions = [graffiti, crop, mosaic, filter] + type: .filter) + config.toolOptions = [graffiti, chartlet, text, crop, mosaic, filter] return config }() /// 画笔颜色数组 - public lazy var brushColors: [String] = ["#ffffff", "#2B2B2B", "#FA5150", "#FEC200", "#07C160", "#10ADFF", "#6467EF"] + public lazy var brushColors: [String] = PhotoTools.defaultColors() /// 默认画笔颜色索引 public var defaultBrushColorIndex: Int = 2 @@ -40,14 +47,58 @@ open class PhotoEditorConfiguration: EditorConfiguration { /// 画笔宽度 public var brushLineWidth: CGFloat = 5 + /// 贴图 + public lazy var chartlet: ChartletConfig = .init() + + public class ChartletConfig { + public enum LoadScene { + /// cell显示时 + case cellDisplay + /// 滚动停止时 + case scrollStop + } + /// 弹窗高度 + public var viewHeight: CGFloat = UIScreen.main.bounds.height * 0.5 + /// 每行显示个数 + public var rowCount: Int = UIDevice.isPad ? 6 : 5 + /// 加载时机 + public var loadScene: LoadScene = .cellDisplay + /// 贴图标题 + public var titles: [EditorChartlet] = [] + } + + /// 文本 + public lazy var text: TextConfig = .init() + + public class TextConfig { + /// 文本颜色数组 + public lazy var colors: [String] = PhotoTools.defaultColors() + /// 确定按钮背景颜色、文本光标颜色 + public lazy var tintColor: UIColor = .systemTintColor + /// 文本字体 + public lazy var font: UIFont = .boldSystemFont(ofSize: 25) + /// 最大字数限制,0为不限制 + public var maximumLimitTextLength: Int = 0 + /// 文本视图推出样式 + public lazy var modalPresentationStyle: UIModalPresentationStyle = { + if #available(iOS 13.0, *) { + return .automatic + } else { + return .fullScreen + } + }() + + public init() { } + } + /// 裁剪配置 - public lazy var cropConfig: PhotoCroppingConfiguration = .init() + public lazy var cropping: PhotoCroppingConfiguration = .init() /// 裁剪确认视图配置 public lazy var cropConfimView: CropConfirmViewConfiguration = .init() /// 滤镜配置 - public lazy var filterConfig: FilterConfig = .init(infos: PhotoTools.defaultFilters()) + public lazy var filter: FilterConfig = .init(infos: PhotoTools.defaultFilters()) public struct FilterConfig { /// 滤镜信息 @@ -62,9 +113,9 @@ open class PhotoEditorConfiguration: EditorConfiguration { } /// 马赛克配置 - public lazy var mosaicConfig: MosaicConfig = .init(mosaicWidth: 20, - mosaiclineWidth: 25, - smearWidth: 30) + public lazy var mosaic: MosaicConfig = .init(mosaicWidth: 20, + mosaiclineWidth: 25, + smearWidth: 30) public struct MosaicConfig { /// 生成马赛克的大小 diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Editor/Config/VideoEditorConfiguration.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/Config/VideoEditorConfiguration.swift index 122d9b71..37579279 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Editor/Config/VideoEditorConfiguration.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/Config/VideoEditorConfiguration.swift @@ -19,14 +19,20 @@ open class VideoEditorConfiguration: EditorConfiguration { public var mustBeTailored: Bool = true /// 配乐配置 - public lazy var musicConfig: MusicConfig = .init(infos: []) + public lazy var music: MusicConfig = .init() - public struct MusicConfig { + public class MusicConfig { + /// 显示搜索 + public var showSearch: Bool = true + /// 完成按钮背景颜色、搜索框光标颜色 + public var tintColor: UIColor = .systemTintColor + /// 搜索框的 placeholder + public var placeholder: String = "" /// 配乐信息 - public let infos: [VideoEditorMusicInfo] - public init(infos: [VideoEditorMusicInfo]) { - self.infos = infos - } + /// 也可通过代理回调设置 + /// func videoEditorViewController(_ videoEditorViewController: VideoEditorViewController, loadMusic completionHandler: @escaping ([VideoEditorMusicInfo]) -> Void) -> Bool + public var infos: [VideoEditorMusicInfo] = [] + public init() { } } /// 裁剪配置 @@ -52,7 +58,7 @@ open class VideoEditorConfiguration: EditorConfiguration { config.exportPresetName = exportPresetName config.defaultState = defaultState config.mustBeTailored = mustBeTailored - config.musicConfig = musicConfig + config.music = music config.cropping = cropping config.cropView = cropView config.toolView = toolView diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Editor/Controller/EditorController.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/Controller/EditorController.swift index 8f6dc85b..7f32e658 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Editor/Controller/EditorController.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/Controller/EditorController.swift @@ -15,15 +15,11 @@ import Kingfisher open class EditorController: UINavigationController { public weak var photoEditorDelegate: PhotoEditorViewControllerDelegate? { - didSet { - photoEditor?.delegate = photoEditorDelegate - } + didSet { photoEditor?.delegate = photoEditorDelegate } } public weak var videoEditorDelegate: VideoEditorViewControllerDelegate? { - didSet { - videoEditor?.delegate = videoEditorDelegate - } + didSet { videoEditor?.delegate = videoEditorDelegate } } public var photoEditor: PhotoEditorViewController? { @@ -44,11 +40,13 @@ open class EditorController: UINavigationController { /// - config: 编辑配置 public init(image: UIImage, editResult: PhotoEditResult? = nil, - config: PhotoEditorConfiguration) { + config: PhotoEditorConfiguration, + delegate: PhotoEditorViewControllerDelegate? = nil) { editorType = .photo self.config = config super.init(nibName: nil, bundle: nil) let photoEditorVC = PhotoEditorViewController.init(image: image, editResult: editResult, config: config) + photoEditorVC.delegate = delegate self.viewControllers = [photoEditorVC] } @@ -59,11 +57,11 @@ open class EditorController: UINavigationController { /// - config: 编辑配置 public init(imageData: Data, editResult: PhotoEditResult? = nil, - config: PhotoEditorConfiguration) { + config: PhotoEditorConfiguration, + delegate: PhotoEditorViewControllerDelegate? = nil) { editorType = .photo self.config = config super.init(nibName: nil, bundle: nil) - let image: UIImage #if canImport(Kingfisher) image = DefaultImageProcessor.default.process(item: .data(imageData), options: .init([]))! @@ -71,6 +69,7 @@ open class EditorController: UINavigationController { image = UIImage.init(data: imageData)! #endif let photoEditorVC = PhotoEditorViewController.init(image: image, editResult: editResult, config: config) + photoEditorVC.delegate = delegate self.viewControllers = [photoEditorVC] } @@ -78,11 +77,13 @@ open class EditorController: UINavigationController { /// 编辑网络图片 public init(networkImageURL: URL, editResult: PhotoEditResult? = nil, - config: PhotoEditorConfiguration) { + config: PhotoEditorConfiguration, + delegate: PhotoEditorViewControllerDelegate? = nil) { editorType = .photo self.config = config super.init(nibName: nil, bundle: nil) let photoEditorVC = PhotoEditorViewController.init(networkImageURL: networkImageURL, editResult: editResult, config: config) + photoEditorVC.delegate = delegate self.viewControllers = [photoEditorVC] } #endif @@ -94,8 +95,12 @@ open class EditorController: UINavigationController { /// - config: 编辑配置 public convenience init(videoURL: URL, editResult: VideoEditResult? = nil, - config: VideoEditorConfiguration) { - self.init(avAsset: AVAsset.init(url: videoURL), editResult: editResult, config: config) + config: VideoEditorConfiguration, + delegate: VideoEditorViewControllerDelegate? = nil) { + self.init(avAsset: AVAsset.init(url: videoURL), + editResult: editResult, + config: config, + delegate: delegate) } /// 编辑 AVAsset @@ -105,11 +110,13 @@ open class EditorController: UINavigationController { /// - config: 编辑配置 public init(avAsset: AVAsset, editResult: VideoEditResult? = nil, - config: VideoEditorConfiguration) { + config: VideoEditorConfiguration, + delegate: VideoEditorViewControllerDelegate? = nil) { editorType = .video self.config = config super.init(nibName: nil, bundle: nil) let videoEditorVC = VideoEditorViewController.init(avAsset: avAsset, editResult: editResult, config: config) + videoEditorVC.delegate = delegate self.viewControllers = [videoEditorVC] } @@ -120,11 +127,13 @@ open class EditorController: UINavigationController { /// - config: 编辑配置 public init(networkVideoURL: URL, editResult: VideoEditResult? = nil, - config: VideoEditorConfiguration) { + config: VideoEditorConfiguration, + delegate: VideoEditorViewControllerDelegate? = nil) { editorType = .video self.config = config super.init(nibName: nil, bundle: nil) let videoEditorVC = VideoEditorViewController.init(networkVideoURL: networkVideoURL, editResult: editResult, config: config) + videoEditorVC.delegate = delegate self.viewControllers = [videoEditorVC] } @@ -136,11 +145,14 @@ open class EditorController: UINavigationController { /// - config: 编辑配置 public init(photoAsset: PhotoAsset, editResult: VideoEditResult? = nil, - config: VideoEditorConfiguration) { + config: VideoEditorConfiguration, + delegate: VideoEditorViewControllerDelegate? = nil) { editorType = .video self.config = config super.init(nibName: nil, bundle: nil) - let videoEditorVC = VideoEditorViewController.init(photoAsset: photoAsset, editResult: editResult, config: config) + let videoEditorVC = VideoEditorViewController.init(photoAsset: photoAsset, + editResult: editResult, config: config) + videoEditorVC.delegate = delegate self.viewControllers = [videoEditorVC] } @@ -151,11 +163,15 @@ open class EditorController: UINavigationController { /// - config: 编辑配置 public init(photoAsset: PhotoAsset, editResult: PhotoEditResult? = nil, - config: PhotoEditorConfiguration) { + config: PhotoEditorConfiguration, + delegate: PhotoEditorViewControllerDelegate? = nil) { editorType = .photo self.config = config super.init(nibName: nil, bundle: nil) - let photoEditorVC = PhotoEditorViewController.init(photoAsset: photoAsset, editResult: editResult, config: config) + let photoEditorVC = PhotoEditorViewController.init(photoAsset: photoAsset, + editResult: editResult, + config: config) + photoEditorVC.delegate = delegate self.viewControllers = [photoEditorVC] } #endif diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Editor/Controller/EditorStickerTextViewController.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/Controller/EditorStickerTextViewController.swift new file mode 100644 index 00000000..cd71232b --- /dev/null +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/Controller/EditorStickerTextViewController.swift @@ -0,0 +1,126 @@ +// +// EditorStickerTextViewController.swift +// HXPHPicker +// +// Created by Slience on 2021/7/22. +// + +import UIKit + +protocol EditorStickerTextViewControllerDelegate: AnyObject { + func stickerTextViewController(_ controller: EditorStickerTextViewController, didFinish stickerText: EditorStickerText) + func stickerTextViewController(_ controller: EditorStickerTextViewController, didFinish stickerItem: EditorStickerItem) +} + +class EditorStickerTextController: UINavigationController { + override var preferredStatusBarStyle: UIStatusBarStyle { + .lightContent + } +} + +class EditorStickerTextViewController: BaseViewController { + weak var delegate: EditorStickerTextViewControllerDelegate? + let config: PhotoEditorConfiguration.TextConfig + let stickerItem: EditorStickerItem? + init(config: PhotoEditorConfiguration.TextConfig, + stickerItem: EditorStickerItem? = nil) { + self.config = config + self.stickerItem = stickerItem + super.init(nibName: nil, bundle: nil) + } + + lazy var bgView: UIVisualEffectView = { + let effext = UIBlurEffect(style: .dark) + let view = UIVisualEffectView.init(effect: effext) + return view + }() + + lazy var cancelButton: UIButton = { + let button = UIButton(type: .system) + button.setTitle("取消".localized, for: .normal) + button.setTitleColor(.white, for: .normal) + button.titleLabel?.font = UIFont.systemFont(ofSize: 17) + button.size = CGSize(width: 60, height: 30) + button.addTarget(self, action: #selector(didCancelButtonClick), for: .touchUpInside) + return button + }() + + @objc func didCancelButtonClick() { + dismiss(animated: true, completion: nil) + } + + lazy var finishButton: UIButton = { + let button = UIButton(type: .system) + let text = "完成".localized + button.setTitle(text, for: .normal) + button.setTitleColor(.white, for: .normal) + button.titleLabel?.font = UIFont.systemFont(ofSize: 17) + var textWidth = text.width(ofFont: .systemFont(ofSize: 17), maxHeight: 30) + if textWidth < 60 { + textWidth = 60 + }else { + textWidth += 10 + } + button.size = CGSize(width: textWidth, height: 30) + button.setBackgroundImage(UIImage.image(for: config.tintColor, havingSize: button.size, radius: 3), for: .normal) + button.addTarget(self, action: #selector(didFinishButtonClick), for: .touchUpInside) + return button + }() + + @objc func didFinishButtonClick() { + if let image = textView.textImage(), !textView.text.isEmpty { + let stickerText = EditorStickerText(image: image, text: textView.text, textColor: textView.currentSelectedColor, showBackgroud: textView.showBackgroudColor) + if stickerItem != nil { + let stickerItem = EditorStickerItem(image: image, text: stickerText) + delegate?.stickerTextViewController(self, didFinish: stickerItem) + }else { + delegate?.stickerTextViewController(self, didFinish: stickerText) + } + } + textView.textView.resignFirstResponder() + dismiss(animated: true, completion: nil) + } + + lazy var textView: EditorStickerTextView = { + let view = EditorStickerTextView(config: config, stickerText: stickerItem?.text) + return view + }() + + override func viewDidLoad() { + super.viewDidLoad() + + view.backgroundColor = .clear + navigationController?.view.backgroundColor = .clear + + navigationItem.leftBarButtonItem = UIBarButtonItem(customView: cancelButton) + navigationItem.rightBarButtonItem = UIBarButtonItem(customView: finishButton) + view.addSubview(bgView) + view.addSubview(textView) + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + navigationController?.navigationBar.shadowImage = UIImage.image(for: UIColor.clear, havingSize: .zero) + navigationController?.navigationBar.setBackgroundImage(UIImage.image(for: UIColor.clear, havingSize: .zero), for: .default) + navigationController?.navigationBar.barTintColor = .clear + navigationController?.navigationBar.backgroundColor = .clear + } + + + override func viewDidLayoutSubviews() { + super.viewDidLayoutSubviews() + bgView.frame = view.bounds + textView.x = 0 + textView.y = navigationController?.navigationBar.frame.maxY ?? UIDevice.navigationBarHeight + textView.width = view.width + textView.height = view.height - textView.y + } + + override var preferredStatusBarStyle: UIStatusBarStyle { + .lightContent + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Editor/Controller/PhotoEditorViewController+Animation.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/Controller/PhotoEditorViewController+Animation.swift index 94654b86..4c96859a 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Editor/Controller/PhotoEditorViewController+Animation.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/Controller/PhotoEditorViewController+Animation.swift @@ -8,6 +8,16 @@ import UIKit extension PhotoEditorViewController { + func showChartletView() { + UIView.animate(withDuration: 0.25) { + self.setChartletViewFrame() + } + } + func hiddenChartletView() { + UIView.animate(withDuration: 0.25) { + self.setChartletViewFrame() + } + } func showFilterView() { UIView.animate(withDuration: 0.25) { @@ -96,6 +106,8 @@ extension PhotoEditorViewController { }else if option.type == .mosaic { mosaicToolView.isHidden = false } + }else { + imageView.stickerEnabled = true } UIView.animate(withDuration: 0.25) { self.toolView.alpha = 1 diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Editor/Controller/PhotoEditorViewController+Export.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/Controller/PhotoEditorViewController+Export.swift index cdbca29e..558a7824 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Editor/Controller/PhotoEditorViewController+Export.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/Controller/PhotoEditorViewController+Export.swift @@ -13,8 +13,9 @@ extension PhotoEditorViewController { imageView.imageResizerView.hasCropping || imageView.canUndoDraw || imageView.canUndoMosaic || - imageView.hasFilter { - + imageView.hasFilter || + imageView.hasSticker { + imageView.deselectedSticker() ProgressHUD.showLoading(addedTo: view, animated: true) imageView.cropping { [weak self] (result) in guard let self = self else { return } diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Editor/Controller/PhotoEditorViewController+Request.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/Controller/PhotoEditorViewController+Request.swift index 84d7706e..5c095dc4 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Editor/Controller/PhotoEditorViewController+Request.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/Controller/PhotoEditorViewController+Request.swift @@ -81,31 +81,39 @@ extension PhotoEditorViewController { photoAsset.requestImageData(filterEditor: true, iCloudHandler: nil, progressHandler: nil) { - [weak self] (asset, imageData, imageOrientation, info) in + [weak self] asset, result in guard let self = self else { return } - let image = UIImage.init(data: imageData)?.scaleSuitableSize() - DispatchQueue.global().async { - self.filterHDImageHandler(image: image!) - DispatchQueue.main.async { - ProgressHUD.hide(forView: self.view, animated: true) - self.requestAssetCompletion(image: image!) + switch result { + case .success(let dataResult): + let image = UIImage.init(data: dataResult.imageData)?.scaleSuitableSize() + DispatchQueue.global().async { + self.filterHDImageHandler(image: image!) + DispatchQueue.main.async { + ProgressHUD.hide(forView: self.view, animated: true) + self.requestAssetCompletion(image: image!) + } + } + case .failure(let error): + ProgressHUD.hide(forView: self.view, animated: true) + if let inICloud = error.info?.inICloud { + self.requestAssetFailure(isICloud: inICloud) + }else { + self.requestAssetFailure(isICloud: false) } } - } failure: { [weak self] (asset, info) in - ProgressHUD.hide(forView: self?.view, animated: true) - self?.requestAssetFailure() } return } - photoAsset.requestAssetImageURL(filterEditor: true) { - [weak self] (imageUrl) in + photoAsset.requestAssetImageURL(filterEditor: true) { [weak self] result in guard let self = self else { return } - DispatchQueue.global().async { - if let imageUrl = imageUrl { + switch result { + case .success(let response): + DispatchQueue.global().async { + let imageURL = response.url #if canImport(Kingfisher) if self.photoAsset.isGifAsset == true { do { - let imageData = try Data.init(contentsOf: imageUrl) + let imageData = try Data.init(contentsOf: imageURL) if let gifImage = DefaultImageProcessor.default.process(item: .data(imageData), options: .init([])) { self.filterHDImageHandler(image: gifImage) DispatchQueue.main.async { @@ -117,7 +125,7 @@ extension PhotoEditorViewController { }catch {} } #endif - if let image = UIImage.init(contentsOfFile: imageUrl.path)?.scaleSuitableSize() { + if let image = UIImage.init(contentsOfFile: imageURL.path)?.scaleSuitableSize() { self.filterHDImageHandler(image: image) DispatchQueue.main.async { ProgressHUD.hide(forView: self.view, animated: true) @@ -126,10 +134,10 @@ extension PhotoEditorViewController { return } } - DispatchQueue.main.async { - ProgressHUD.hide(forView: self.view, animated: true) - self.requestAssetFailure() - } + case .failure(_): + ProgressHUD.hide(forView: self.view, animated: true) + self.requestAssetFailure(isICloud: false) + break } } } @@ -156,7 +164,7 @@ extension PhotoEditorViewController { } } }else { - self.requestAssetFailure() + self.requestAssetFailure(isICloud: false) } } } @@ -179,9 +187,10 @@ extension PhotoEditorViewController { setFilterImage() setImage(image) } - func requestAssetFailure() { + func requestAssetFailure(isICloud: Bool) { ProgressHUD.hide(forView: view, animated: true) - PhotoTools.showConfirm(viewController: self, title: "提示".localized, message: "图片获取失败!".localized, actionTitle: "确定".localized) { (alertAction) in + let text = isICloud ? "iCloud同步失败" : "图片获取失败!" + PhotoTools.showConfirm(viewController: self, title: "提示".localized, message: text.localized, actionTitle: "确定".localized) { (alertAction) in self.didBackClick() } } @@ -195,35 +204,52 @@ extension PhotoEditorViewController { return } } - var value: Float = 0 - var minSize: CGFloat = min(UIScreen.main.bounds.width, UIScreen.main.bounds.height) - DispatchQueue.main.sync { - value = filterView.sliderView.value - if !view.size.equalTo(.zero) { - minSize = min(view.width, view.height) * 2 + var hasMosaic = false + var hasFilter = false + for option in config.toolView.toolOptions { + if option.type == .filter { + hasFilter = true + }else if option.type == .mosaic { + hasMosaic = true } } - if image.width > minSize { - let thumbnailScale = minSize / image.width - thumbnailImage = image.scaleImage(toScale: thumbnailScale) - } - if thumbnailImage == nil { - thumbnailImage = image + var value: Float = 0 + if hasFilter { + var minSize: CGFloat = min(UIScreen.main.bounds.width, UIScreen.main.bounds.height) + DispatchQueue.main.sync { + value = filterView.sliderView.value + if !view.size.equalTo(.zero) { + minSize = min(view.width, view.height) * 2 + } + } + if image.width > minSize { + let thumbnailScale = minSize / image.width + thumbnailImage = image.scaleImage(toScale: thumbnailScale) + } + if thumbnailImage == nil { + thumbnailImage = image + } } - if let filter = editResult?.editedData.filter { + if let filter = editResult?.editedData.filter, hasFilter { var newImage: UIImage? - if !config.filterConfig.infos.isEmpty { - let info = config.filterConfig.infos[filter.sourceIndex] + if !config.filter.infos.isEmpty { + let info = config.filter.infos[filter.sourceIndex] newImage = info.filterHandler(thumbnailImage, image, value, .touchUpInside) } if let newImage = newImage { filterHDImage = newImage - mosaicImage = newImage.mosaicImage(level: config.mosaicConfig.mosaicWidth) + if hasMosaic { + mosaicImage = newImage.mosaicImage(level: config.mosaic.mosaicWidth) + } } }else { - mosaicImage = thumbnailImage.mosaicImage(level: config.mosaicConfig.mosaicWidth) + if hasMosaic { + mosaicImage = thumbnailImage.mosaicImage(level: config.mosaic.mosaicWidth) + } + } + if hasFilter { + filterImage = image.scaleToFillSize(size: CGSize(width: 80, height: 80), equalRatio: true) } - filterImage = image.scaleToFillSize(size: CGSize(width: 80, height: 80), equalRatio: true) } func setFilterImage() { if let image = filterHDImage { diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Editor/Controller/PhotoEditorViewController.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/Controller/PhotoEditorViewController.swift index c10b0a6b..2db9ff58 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Editor/Controller/PhotoEditorViewController.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/Controller/PhotoEditorViewController.swift @@ -18,13 +18,31 @@ public protocol PhotoEditorViewControllerDelegate: AnyObject { /// - Parameters: /// - photoEditorViewController: 对应的 PhotoEditorViewController /// - result: 编辑后的数据 - func photoEditorViewController(_ photoEditorViewController: PhotoEditorViewController, didFinish result: PhotoEditResult) + func photoEditorViewController(_ photoEditorViewController: PhotoEditorViewController, + didFinish result: PhotoEditResult) /// 点击完成按钮,但是照片未编辑 /// - Parameters: /// - photoEditorViewController: 对应的 PhotoEditorViewController func photoEditorViewController(didFinishWithUnedited photoEditorViewController: PhotoEditorViewController) + /// 加载贴图标题资源 + /// - Parameters: + /// - photoEditorViewController: 对应的 PhotoEditorViewController + /// - loadTitleChartlet: 传入标题数组 + func photoEditorViewController(_ photoEditorViewController: PhotoEditorViewController, + loadTitleChartlet response: @escaping EditorTitleChartletResponse) + /// 加载贴图资源 + /// - Parameters: + /// - photoEditorViewController: 对应的 PhotoEditorViewController + /// - titleChartlet: 对应配置的 title + /// - titleIndex: 对应配置的 title 的位置索引 + /// - response: 传入 title索引 和 贴图数据 + func photoEditorViewController(_ photoEditorViewController: PhotoEditorViewController, + titleChartlet: EditorChartlet, + titleIndex: Int, + loadChartletList response: @escaping EditorChartletListResponse) + /// 取消编辑 /// - Parameter photoEditorViewController: 对应的 PhotoEditorViewController func photoEditorViewController(didCancel photoEditorViewController: PhotoEditorViewController) @@ -33,6 +51,23 @@ public extension PhotoEditorViewControllerDelegate { func photoEditorViewController(_ photoEditorViewController: PhotoEditorViewController, didFinish result: PhotoEditResult) {} func photoEditorViewController(didFinishWithUnedited photoEditorViewController: PhotoEditorViewController) {} func photoEditorViewController(didCancel photoEditorViewController: PhotoEditorViewController) {} + func photoEditorViewController(_ photoEditorViewController: PhotoEditorViewController, + loadTitleChartlet response: @escaping EditorTitleChartletResponse) { + #if canImport(Kingfisher) + let titles = PhotoTools.defaultTitleChartlet() + response(titles) + #endif + } + func photoEditorViewController(_ photoEditorViewController: PhotoEditorViewController, + titleChartlet: EditorChartlet, + titleIndex: Int, + loadChartletList response: @escaping EditorChartletListResponse) { + /// 默认加载这些贴图 + #if canImport(Kingfisher) + let chartletList = PhotoTools.defaultNetworkChartlet() + response(titleIndex, chartletList) + #endif + } } open class PhotoEditorViewController: BaseViewController { @@ -46,7 +81,7 @@ open class PhotoEditorViewController: BaseViewController { public private(set) var image: UIImage! /// 资源类型 - public let assetType: EditorController.AssetType + public let sourceType: EditorController.SourceType /// 当前编辑状态 public private(set) var state: State = .normal @@ -64,7 +99,7 @@ open class PhotoEditorViewController: BaseViewController { config: PhotoEditorConfiguration) { PhotoManager.shared.appearanceStyle = config.appearanceStyle PhotoManager.shared.createLanguageBundle(languageType: config.languageType) - assetType = .local + sourceType = .local self.image = image self.config = config self.editResult = editResult @@ -85,7 +120,7 @@ open class PhotoEditorViewController: BaseViewController { config: PhotoEditorConfiguration) { PhotoManager.shared.appearanceStyle = config.appearanceStyle PhotoManager.shared.createLanguageBundle(languageType: config.languageType) - assetType = .picker + sourceType = .picker requestType = 1 needRequest = true self.config = config @@ -109,7 +144,7 @@ open class PhotoEditorViewController: BaseViewController { config: PhotoEditorConfiguration) { PhotoManager.shared.appearanceStyle = config.appearanceStyle PhotoManager.shared.createLanguageBundle(languageType: config.languageType) - assetType = .network + sourceType = .network requestType = 2 needRequest = true self.networkImageURL = networkImageURL @@ -131,17 +166,14 @@ open class PhotoEditorViewController: BaseViewController { lazy var imageView: PhotoEditorView = { let imageView = PhotoEditorView.init(config: config) imageView.editorDelegate = self - let singleTap = UITapGestureRecognizer.init(target: self, action: #selector(singleTap(tap:))) - imageView.addGestureRecognizer(singleTap) return imageView }() var topViewIsHidden: Bool = false - @objc func singleTap(tap: UITapGestureRecognizer) { + @objc func singleTap() { if state == .cropping { return } - if isFilter { - isFilter = false + func resetOtherOption() { if let option = currentToolOption { if option.type == .graffiti { imageView.drawEnabled = true @@ -150,9 +182,20 @@ open class PhotoEditorViewController: BaseViewController { } } showTopView() + } + if isFilter { + isFilter = false + resetOtherOption() hiddenFilterView() return } + if showChartlet { + imageView.isEnabled = true + showChartlet = false + resetOtherOption() + hiddenChartletView() + return + } if topViewIsHidden { showTopView() }else { @@ -214,15 +257,21 @@ open class PhotoEditorViewController: BaseViewController { view.isHidden = true return view }() + var showChartlet: Bool = false + lazy var chartletView: EditorChartletView = { + let view = EditorChartletView(config: config.chartlet) + view.delegate = self + return view + }() lazy var cropToolView: PhotoEditorCropToolView = { var showRatios = true - if config.cropConfig.fixedRatio || config.cropConfig.isRoundCrop { + if config.cropping.fixedRatio || config.cropping.isRoundCrop { showRatios = false } let view = PhotoEditorCropToolView.init(showRatios: showRatios) view.delegate = self - view.themeColor = config.cropConfig.aspectRatioSelectedColor + view.themeColor = config.cropping.aspectRatioSelectedColor view.alpha = 0 view.isHidden = true return view @@ -239,7 +288,7 @@ open class PhotoEditorViewController: BaseViewController { lazy var filterView: PhotoEditorFilterView = { let filter = editResult?.editedData.filter let value = editResult?.editedData.filterValue - let view = PhotoEditorFilterView.init(filterConfig: config.filterConfig, + let view = PhotoEditorFilterView.init(filterConfig: config.filter, sourceIndex: filter?.sourceIndex ?? -1, value: value ?? 0) view.delegate = self @@ -253,6 +302,16 @@ open class PhotoEditorViewController: BaseViewController { open override func viewDidLoad() { super.viewDidLoad() + let singleTap = UITapGestureRecognizer.init(target: self, action: #selector(singleTap)) + singleTap.delegate = self + view.addGestureRecognizer(singleTap) + view.isExclusiveTouch = true + view.backgroundColor = .black + view.clipsToBounds = true + view.addSubview(imageView) + view.addSubview(toolView) + view.addSubview(cropConfirmView) + view.addSubview(cropToolView) if config.fixedCropState { state = .cropping toolView.alpha = 0 @@ -261,16 +320,11 @@ open class PhotoEditorViewController: BaseViewController { topView.isHidden = true }else { state = config.state + view.addSubview(brushColorView) + view.addSubview(chartletView) + view.addSubview(mosaicToolView) + view.addSubview(filterView) } - view.backgroundColor = .black - view.clipsToBounds = true - view.addSubview(imageView) - view.addSubview(toolView) - view.addSubview(brushColorView) - view.addSubview(cropConfirmView) - view.addSubview(cropToolView) - view.addSubview(mosaicToolView) - view.addSubview(filterView) view.layer.addSublayer(topMaskLayer) view.addSubview(topView) if needRequest { @@ -288,8 +342,12 @@ open class PhotoEditorViewController: BaseViewController { } } open override func deviceOrientationWillChanged(notify: Notification) { + if showChartlet { + singleTap() + } imageView.undoAllDraw() imageView.undoAllMosaic() + imageView.undoAllSticker() brushColorView.canUndo = imageView.canUndoDraw mosaicToolView.canUndo = imageView.canUndoMosaic imageView.reset(false) @@ -325,6 +383,7 @@ open class PhotoEditorViewController: BaseViewController { brushColorView.frame = cropToolView.frame mosaicToolView.frame = brushColorView.frame cropToolView.updateContentInset() + setChartletViewFrame() setFilterViewFrame() if !imageView.frame.equalTo(view.bounds) && !imageView.frame.isEmpty && !imageViewDidChange { imageView.frame = view.bounds @@ -359,6 +418,17 @@ open class PhotoEditorViewController: BaseViewController { imageViewDidChange = true } } + func setChartletViewFrame() { + var viewHeight = config.chartlet.viewHeight + if viewHeight > view.height { + viewHeight = view.height * 0.6 + } + if showChartlet { + chartletView.frame = CGRect(x: 0, y: view.height - viewHeight - UIDevice.bottomMargin, width: view.width, height: viewHeight + UIDevice.bottomMargin) + }else { + chartletView.frame = CGRect(x: 0, y: view.height, width: view.width, height: viewHeight + UIDevice.bottomMargin) + } + } func setFilterViewFrame() { if isFilter { filterView.frame = CGRect(x: 0, y: view.height - 150 - UIDevice.bottomMargin, width: view.width, height: 150 + UIDevice.bottomMargin) @@ -400,7 +470,8 @@ extension PhotoEditorViewController: EditorToolViewDelegate { exportResources() } func toolView(_ toolView: EditorToolView, didSelectItemAt model: EditorToolOptions) { - if model.type == .graffiti { + switch model.type { + case .graffiti: currentToolOption = nil imageView.mosaicEnabled = false hiddenMosaicToolView() @@ -408,18 +479,38 @@ extension PhotoEditorViewController: EditorToolViewDelegate { toolView.stretchMask = imageView.drawEnabled toolView.layoutSubviews() if imageView.drawEnabled { + imageView.stickerEnabled = false showBrushColorView() currentToolOption = model }else { + imageView.stickerEnabled = true hiddenBrushColorView() } - }else if model.type == .cropping { + case .chartlet: + chartletView.firstRequest() + imageView.deselectedSticker() imageView.drawEnabled = false imageView.mosaicEnabled = false + imageView.stickerEnabled = false + imageView.isEnabled = false + showChartlet = true + hidenTopView() + showChartletView() + case .text: + imageView.deselectedSticker() + let textVC = EditorStickerTextViewController(config: config.text) + textVC.delegate = self + let nav = EditorStickerTextController(rootViewController: textVC) + nav.modalPresentationStyle = config.text.modalPresentationStyle + present(nav, animated: true, completion: nil) + case .cropping: + imageView.drawEnabled = false + imageView.mosaicEnabled = false + imageView.stickerEnabled = false state = .cropping imageView.startCropping(true) croppingAction() - }else if model.type == .mosaic { + case .mosaic: currentToolOption = nil imageView.drawEnabled = false hiddenBrushColorView() @@ -427,17 +518,22 @@ extension PhotoEditorViewController: EditorToolViewDelegate { toolView.stretchMask = imageView.mosaicEnabled toolView.layoutSubviews() if imageView.mosaicEnabled { + imageView.stickerEnabled = false showMosaicToolView() currentToolOption = model }else { + imageView.stickerEnabled = true hiddenMosaicToolView() } - }else if model.type == .filter { + case .filter: imageView.drawEnabled = false imageView.mosaicEnabled = false + imageView.stickerEnabled = false isFilter = true hidenTopView() showFilterView() + default: + break } } } @@ -524,6 +620,14 @@ extension PhotoEditorViewController: PhotoEditorViewDelegate { brushColorView.canUndo = editorView.canUndoDraw mosaicToolView.canUndo = editorView.canUndoMosaic } + func editorView(_ editorView: PhotoEditorView, updateStickerText item: EditorStickerItem) { + let textVC = EditorStickerTextViewController(config: config.text, + stickerItem: item) + textVC.delegate = self + let nav = EditorStickerTextController(rootViewController: textVC) + nav.modalPresentationStyle = config.text.modalPresentationStyle + present(nav, animated: true, completion: nil) + } } extension PhotoEditorViewController: PhotoEditorCropToolViewDelegate { @@ -568,9 +672,9 @@ extension PhotoEditorViewController: PhotoEditorFilterViewDelegate { let value = filterView.sliderView.value let lastImage = imageView.image DispatchQueue.global().async { - let filterInfo = self.config.filterConfig.infos[atItem] + let filterInfo = self.config.filter.infos[atItem] if let newImage = filterInfo.filterHandler(self.thumbnailImage, lastImage, value, .touchUpInside) { - let mosaicImage = newImage.mosaicImage(level: self.config.mosaicConfig.mosaicWidth) + let mosaicImage = newImage.mosaicImage(level: self.config.mosaic.mosaicWidth) DispatchQueue.main.sync { ProgressHUD.hide(forView: self.view, animated: true) self.imageView.updateImage(newImage) @@ -587,23 +691,72 @@ extension PhotoEditorViewController: PhotoEditorFilterViewDelegate { } func filterView(_ filterView: PhotoEditorFilterView, didChanged value: Float) { - let filterInfo = config.filterConfig.infos[filterView.currentSelectedIndex - 1] + let filterInfo = config.filter.infos[filterView.currentSelectedIndex - 1] if let newImage = filterInfo.filterHandler(thumbnailImage, imageView.image, value, .valueChanged) { imageView.updateImage(newImage) imageView.imageResizerView.filterValue = value if mosaicToolView.canUndo { - let mosaicImage = newImage.mosaicImage(level: config.mosaicConfig.mosaicWidth) + let mosaicImage = newImage.mosaicImage(level: config.mosaic.mosaicWidth) imageView.setMosaicOriginalImage(mosaicImage) } } } func filterView(_ filterView: PhotoEditorFilterView, touchUpInside value: Float) { - let filterInfo = config.filterConfig.infos[filterView.currentSelectedIndex - 1] + let filterInfo = config.filter.infos[filterView.currentSelectedIndex - 1] if let newImage = filterInfo.filterHandler(thumbnailImage, imageView.image, value, .touchUpInside) { imageView.updateImage(newImage) imageView.imageResizerView.filterValue = value - let mosaicImage = newImage.mosaicImage(level: config.mosaicConfig.mosaicWidth) + let mosaicImage = newImage.mosaicImage(level: config.mosaic.mosaicWidth) imageView.setMosaicOriginalImage(mosaicImage) } } } + +extension PhotoEditorViewController: UIGestureRecognizerDelegate { + public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool { + if touch.view is EditorStickerContentView { + return false + } + if let isDescendant = touch.view?.isDescendant(of: imageView), isDescendant { + return true + } + return false + } + public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool { + true + } +} + +extension PhotoEditorViewController: EditorStickerTextViewControllerDelegate { + func stickerTextViewController(_ controller: EditorStickerTextViewController, didFinish stickerItem: EditorStickerItem) { + imageView.updateSticker(item: stickerItem) + } + + func stickerTextViewController(_ controller: EditorStickerTextViewController, didFinish stickerText: EditorStickerText) { + let item = EditorStickerItem(image: stickerText.image, text: stickerText) + imageView.addSticker(item: item, isSelected: false) + } +} + +extension PhotoEditorViewController: EditorChartletViewDelegate { + func chartletView(_ chartletView: EditorChartletView, loadTitleChartlet response: @escaping ([EditorChartlet]) -> Void) { + delegate?.photoEditorViewController(self, loadTitleChartlet: response) + } + func chartletView(backClick chartletView: EditorChartletView) { + singleTap() + } + func chartletView(_ chartletView: EditorChartletView, + titleChartlet: EditorChartlet, + titleIndex: Int, + loadChartletList response: @escaping (Int, [EditorChartlet]) -> Void) { + delegate?.photoEditorViewController(self, + titleChartlet: titleChartlet, + titleIndex: titleIndex, + loadChartletList: response) + } + func chartletView(_ chartletView: EditorChartletView, didSelectImage image: UIImage) { + let item = EditorStickerItem(image: image, text: nil) + imageView.addSticker(item: item, isSelected: false) + singleTap() + } +} diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Editor/Controller/VideoEditorViewController.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/Controller/VideoEditorViewController.swift index e012f848..071518a2 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Editor/Controller/VideoEditorViewController.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/Controller/VideoEditorViewController.swift @@ -31,7 +31,26 @@ public protocol VideoEditorViewControllerDelegate: AnyObject { /// - Parameters: /// - videoEditorViewController: 对应的 VideoEditorViewController /// - completionHandler: 传入配乐信息 - func videoEditorViewController(_ videoEditorViewController: VideoEditorViewController, loadMusic completionHandler: @escaping ([VideoEditorMusicInfo]) -> Void) -> Bool + func videoEditorViewController(_ videoEditorViewController: VideoEditorViewController, + loadMusic completionHandler: @escaping ([VideoEditorMusicInfo]) -> Void) -> Bool + + /// 搜索配乐信息 + /// - Parameters: + /// - videoEditorViewController: 对应的 VideoEditorViewController + /// - text: 搜索的文字内容 + /// - completion: 传入配乐信息,是否需要加载更多 + func videoEditorViewController(_ videoEditorViewController: VideoEditorViewController, + didSearch text: String?, + completionHandler: @escaping ([VideoEditorMusicInfo], Bool) -> Void) + + /// 加载更多配乐信息 + /// - Parameters: + /// - videoEditorViewController: 对应的 VideoEditorViewController + /// - text: 搜索的文字内容 + /// - completion: 传入配乐信息,是否还有更多数据 + func videoEditorViewController(_ videoEditorViewController: VideoEditorViewController, + loadMore text: String?, + completionHandler: @escaping ([VideoEditorMusicInfo], Bool) -> Void) /// 取消编辑 /// - Parameter videoEditorViewController: 对应的 VideoEditorViewController @@ -42,7 +61,25 @@ public extension VideoEditorViewControllerDelegate { func videoEditorViewController(_ videoEditorViewController: VideoEditorViewController, didFinish result: VideoEditResult) {} func videoEditorViewController(didFinishWithUnedited videoEditorViewController: VideoEditorViewController) {} func videoEditorViewController(shouldClickMusicTool videoEditorViewController: VideoEditorViewController) -> Bool { true } - func videoEditorViewController(_ videoEditorViewController: VideoEditorViewController, loadMusic completionHandler: @escaping ([VideoEditorMusicInfo]) -> Void) -> Bool { false } + func videoEditorViewController(_ videoEditorViewController: VideoEditorViewController, loadMusic completionHandler: @escaping ([VideoEditorMusicInfo]) -> Void) -> Bool { + var infos: [VideoEditorMusicInfo] = [] + if let audioURL = URL(string: "http://tsnrhapp.oss-cn-hangzhou.aliyuncs.com/chartle/%E5%A4%A9%E5%A4%96%E6%9D%A5%E7%89%A9.mp3"), + let lrc = "天外来物".lrc { + let info = VideoEditorMusicInfo(audioURL: audioURL, lrc: lrc) + infos.append(info) + } + return false + } + func videoEditorViewController(_ videoEditorViewController: VideoEditorViewController, + didSearch text: String?, + completionHandler: @escaping ([VideoEditorMusicInfo], Bool) -> Void) { + completionHandler([], false) + } + func videoEditorViewController(_ videoEditorViewController: VideoEditorViewController, + loadMore text: String?, + completionHandler: @escaping ([VideoEditorMusicInfo], Bool) -> Void) { + completionHandler([], false) + } func videoEditorViewController(didCancel videoEditorViewController: VideoEditorViewController) {} } @@ -59,7 +96,7 @@ open class VideoEditorViewController: BaseViewController { public private(set) var state: State /// 资源类型 - public let assetType: EditorController.AssetType + public let sourceType: EditorController.SourceType /// 在视频未获取成功之前展示的视频封面 public var coverImage: UIImage? @@ -69,11 +106,25 @@ open class VideoEditorViewController: BaseViewController { /// 当前配乐的音频路径 public var backgroundMusicPath: String? { - didSet { - toolView.reloadMusic(isSelected: backgroundMusicPath != nil) - } + didSet { toolView.reloadMusic(isSelected: backgroundMusicPath != nil) } + } + + /// 配乐音量 + public var backgroundMusicVolume: Float = 1 { + didSet { PhotoManager.shared.changeAudioPlayerVolume(backgroundMusicVolume) } } + /// 播放视频 + public func playVideo() { startPlayTimer() } + + /// 视频原声音量 + public var videoVolume: Float = 1 { + didSet { playerView.player.volume = videoVolume } + } + + /// 界面消失之后取消下载网络视频 + public var viewDidDisappearCancelDownload = true + /// 上一次的编辑数据 public private(set) var editResult: VideoEditResult? @@ -106,7 +157,7 @@ open class VideoEditorViewController: BaseViewController { } needRequest = true requestType = 3 - self.assetType = .local + self.sourceType = .local self.editResult = editResult self.state = config.defaultState self.config = config @@ -132,7 +183,7 @@ open class VideoEditorViewController: BaseViewController { } requestType = 2 needRequest = true - self.assetType = .network + self.sourceType = .network self.editResult = editResult self.state = config.defaultState self.config = config @@ -162,7 +213,7 @@ open class VideoEditorViewController: BaseViewController { } requestType = 1 needRequest = true - self.assetType = .picker + sourceType = .picker self.editResult = editResult self.state = config.defaultState self.config = config @@ -199,6 +250,10 @@ open class VideoEditorViewController: BaseViewController { if state != .normal { return } + if isSearchMusic { + hideSearchMusicView() + return + } if isMusicState { isMusicState = false updateMusicView() @@ -240,11 +295,17 @@ open class VideoEditorViewController: BaseViewController { return playerView }() lazy var musicView: VideoEditorMusicView = { - let view = VideoEditorMusicView.init(musicInfos: config.musicConfig.infos) + let view = VideoEditorMusicView.init(config: config.music) + view.delegate = self + return view + }() + lazy var searchMusicView: VideoEditorSearchMusicView = { + let view = VideoEditorSearchMusicView(config: config.music) view.delegate = self return view }() var isMusicState = false + var isSearchMusic = false lazy var cropView: VideoEditorCropView = { let cropView : VideoEditorCropView if needRequest { @@ -320,6 +381,7 @@ open class VideoEditorViewController: BaseViewController { view.addSubview(cropConfirmView) view.addSubview(toolView) view.addSubview(musicView) + view.addSubview(searchMusicView) view.layer.addSublayer(topMaskLayer) view.addSubview(topView) if needRequest { @@ -336,12 +398,11 @@ open class VideoEditorViewController: BaseViewController { if let editResult = editResult { didEdited = true if let cropData = editResult.cropData { - playerView.playStartTime = CMTimeMakeWithSeconds(cropData.startTime, - preferredTimescale: cropData.preferredTimescale) + playerView.playStartTime = CMTimeMakeWithSeconds(cropData.startTime, preferredTimescale: cropData.preferredTimescale) playerView.playEndTime = CMTimeMakeWithSeconds(cropData.endTime, preferredTimescale: cropData.preferredTimescale) - rotateBeforeStorageData = cropData.cropingData - rotateBeforeData = cropData.cropRectData + rotateBeforeStorageData = (cropData.cropingData.offsetX, cropData.cropingData.validX, cropData.cropingData.validWidth) + rotateBeforeData = (cropData.cropRectData.offsetX, cropData.cropRectData.validX, cropData.cropRectData.validWidth) } } } @@ -367,6 +428,7 @@ open class VideoEditorViewController: BaseViewController { rotateBeforeData = cropView.getRotateBeforeData() playerView.pause() musicView.reset() + searchMusicView.deselect() backgroundMusicPath = nil stopPlayTimer() } @@ -391,6 +453,10 @@ open class VideoEditorViewController: BaseViewController { cropConfirmView.frame = toolView.frame scrollView.frame = view.bounds setMusicViewFrame() + setSearchMusicViewFrame() + if orientationDidChange { + searchMusicView.reloadData() + } if needRequest { firstLayoutSubviews = false if reqeustAssetCompletion { @@ -444,13 +510,24 @@ open class VideoEditorViewController: BaseViewController { } } func setMusicViewFrame() { - let musicHeight: CGFloat = 180 + let musicHeight: CGFloat = 190 if !isMusicState { musicView.frame = CGRect(x: 0, y: view.height, width: view.width, height: musicHeight + UIDevice.bottomMargin) }else { musicView.frame = CGRect(x: 0, y: view.height - musicHeight - UIDevice.bottomMargin, width: view.width, height: musicHeight + UIDevice.bottomMargin) } } + func setSearchMusicViewFrame() { + var viewHeight: CGFloat = view.height * 0.75 + UIDevice.bottomMargin + if !UIDevice.isPad && !UIDevice.isPortrait { + viewHeight = view.height * 0.85 + UIDevice.bottomMargin + } + if !isSearchMusic { + searchMusicView.frame = CGRect(x: 0, y: view.height, width: view.width, height: viewHeight) + }else { + searchMusicView.frame = CGRect(x: 0, y: view.height - viewHeight, width: view.width, height: viewHeight) + } + } func rotateAfterSetStorageData(offsetXScale: CGFloat, validXScale: CGFloat, validWithScale: CGFloat) { let insert = cropView.collectionView.contentInset @@ -499,13 +576,14 @@ open class VideoEditorViewController: BaseViewController { super.viewDidDisappear(animated) stopAllOperations() } - func stopAllOperations() { + public func stopAllOperations() { stopPlayTimer() PhotoManager.shared.stopPlayMusic() - if let url = networkVideoURL { + if let url = networkVideoURL, viewDidDisappearCancelDownload { PhotoManager.shared.suspendTask(url) networkVideoURL = nil } + viewDidDisappearCancelDownload = true } open override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) @@ -531,30 +609,35 @@ extension VideoEditorViewController { downloadNetworkVideo() return } - let loadingView = ProgressHUD.showLoading(addedTo: view, text: "视频加载中".localized, animated: true) + let loadingView = ProgressHUD.showLoading(addedTo: view, text: nil, animated: true) view.bringSubviewToFront(topView) assetRequestID = photoAsset.requestAVAsset(filterEditor: true, deliveryMode: .highQualityFormat) { [weak self] (photoAsset, requestID) in self?.assetRequestID = requestID + loadingView?.updateText(text: "正在同步iCloud".localized + "...") } progressHandler: { (photoAsset, progress) in if progress > 0 { - loadingView?.updateText(text: "视频加载中".localized + "(" + String(Int(progress * 100)) + "%)") + loadingView?.updateText(text: "正在同步iCloud".localized + "(" + String(Int(progress * 100)) + "%)") } } success: { [weak self] (photoAsset, avAsset, info) in ProgressHUD.hide(forView: self?.view, animated: false) self?.avAsset = avAsset self?.reqeustAssetCompletion = true self?.assetRequestComplete() - } failure: { [weak self] (photoAsset, info) in - if info?.isCancel != true { + } failure: { [weak self] (photoAsset, info, error) in + if let info = info, !info.isCancel { ProgressHUD.hide(forView: self?.view, animated: false) - self?.assetRequestFailure() + if info.inICloud { + self?.assetRequestFailure(message: "iCloud同步失败".localized) + }else { + self?.assetRequestFailure() + } } } } #endif - func assetRequestFailure() { - PhotoTools.showConfirm(viewController: self, title: "提示".localized, message: "视频获取失败!".localized, actionTitle: "确定".localized) { (alertAction) in + func assetRequestFailure(message: String = "视频获取失败!".localized) { + PhotoTools.showConfirm(viewController: self, title: "提示".localized, message: message, actionTitle: "确定".localized) { (alertAction) in self.backAction() } } @@ -577,13 +660,14 @@ extension VideoEditorViewController { setPlayerViewFrame() } if let editResult = editResult { - playerView.player.volume = editResult.hideVideoSoundTrack ? 0 : 1 - musicView.originalSoundButton.isSelected = !editResult.hideVideoSoundTrack + playerView.player.volume = editResult.videoSoundVolume + musicView.originalSoundButton.isSelected = editResult.videoSoundVolume > 0 if let audioURL = editResult.backgroundMusicURL { backgroundMusicPath = audioURL.path musicView.backgroundButton.isSelected = true PhotoManager.shared.playMusic(filePath: audioURL.path) { } + backgroundMusicVolume = editResult.backgroundMusicVolume } } } @@ -602,11 +686,12 @@ extension VideoEditorViewController { } loadingView = ProgressHUD.showLoading(addedTo: view, text: "视频下载中".localized, animated: true) view.bringSubviewToFront(topView) - PhotoManager.shared.downloadTask(with: videoURL) { [weak self] (progress, task) in + PhotoManager.shared.downloadTask(with: videoURL) { + [weak self] (progress, task) in if progress > 0 { self?.loadingView?.updateText(text: "视频下载中".localized + "(" + String(Int(progress * 100)) + "%)") } - } completionHandler: { [weak self] (url, error) in + } completionHandler: { [weak self] (url, error, _) in if let url = url { #if HXPICKER_ENABLE_PICKER if let photoAsset = self?.photoAsset { @@ -779,9 +864,9 @@ extension VideoEditorViewController: EditorToolViewDelegate { } PhotoTools.videoAddBackgroundMusic(forVideo: videoURL, audioURL: audioURL, - hasOriginalSound: playerView.player.volume == 0 ? false : true, - presentName: config.exportPresetName) { - [weak self] (url) in + audioVolume: backgroundMusicVolume, + originalAudioVolume: playerView.player.volume, + presentName: config.exportPresetName) { [weak self] (url) in if let url = url { self?.editFinishCallBack(url) self?.backAction() @@ -807,8 +892,8 @@ extension VideoEditorViewController: EditorToolViewDelegate { cropData = VideoCropData.init(startTime: startTime.seconds, endTime: endTime.seconds, preferredTimescale: avAsset.duration.timescale, - cropingData: rotateBeforeStorageData, - cropRectData: rotateBeforeData) + cropingData: .init(offsetX: rotateBeforeStorageData.0, validX: rotateBeforeStorageData.1, validWidth: rotateBeforeStorageData.2), + cropRectData: .init(offsetX: rotateBeforeData.0, validX: rotateBeforeData.1, validWidth: rotateBeforeData.2)) } var backgroundMusicURL: URL? if let audioPath = backgroundMusicPath { @@ -816,8 +901,9 @@ extension VideoEditorViewController: EditorToolViewDelegate { } let editResult = VideoEditResult.init(editedURL: videoURL, cropData: cropData, + videoSoundVolume: playerView.player.volume, backgroundMusicURL: backgroundMusicURL, - hideVideoSoundTrack: playerView.player.volume == 0 ? true : false) + backgroundMusicVolume: backgroundMusicVolume) delegate?.videoEditorViewController(self, didFinish: editResult) } func toolView(_ toolView: EditorToolView, didSelectItemAt model: EditorToolOptions) { @@ -953,7 +1039,7 @@ extension VideoEditorViewController: EditorCropConfirmViewDelegate { } } } - +// MARK: VideoEditorMusicViewDelegate extension VideoEditorViewController: VideoEditorMusicViewDelegate { func musicView(_ musicView: VideoEditorMusicView, didSelectMusic audioPath: String?) { backgroundMusicPath = audioPath @@ -961,6 +1047,13 @@ extension VideoEditorViewController: VideoEditorMusicViewDelegate { func musicView(deselectMusic musicView: VideoEditorMusicView) { backgroundMusicPath = nil } + func musicView(didSearchButton musicView: VideoEditorMusicView) { + searchMusicView.searchView.becomeFirstResponder() + isSearchMusic = true + UIView.animate(withDuration: 0.25) { + self.setSearchMusicViewFrame() + } + } func musicView(_ musicView: VideoEditorMusicView, didOriginalSoundButtonClick isSelected: Bool) { if isSelected { playerView.player.volume = 1 @@ -969,3 +1062,39 @@ extension VideoEditorViewController: VideoEditorMusicViewDelegate { } } } +// MARK: VideoEditorSearchMusicViewDelegate +extension VideoEditorViewController: VideoEditorSearchMusicViewDelegate { + func searchMusicView(didCancelClick searchMusicView: VideoEditorSearchMusicView) { + hideSearchMusicView() + } + func searchMusicView(didFinishClick searchMusicView: VideoEditorSearchMusicView) { + hideSearchMusicView(deselect: false) + } + func searchMusicView(_ searchMusicView: VideoEditorSearchMusicView, didSelectItem audioPath: String?) { + musicView.reset() + musicView.backgroundButton.isSelected = true + backgroundMusicPath = audioPath + } + func searchMusicView(_ searchMusicView: VideoEditorSearchMusicView, didSearch text: String?, completion: @escaping ([VideoEditorMusicInfo], Bool) -> Void) { + delegate?.videoEditorViewController(self, didSearch: text, completionHandler: completion) + } + func searchMusicView(_ searchMusicView: VideoEditorSearchMusicView, loadMore text: String?, completion: @escaping ([VideoEditorMusicInfo], Bool) -> Void) { + delegate?.videoEditorViewController(self, loadMore: text, completionHandler: completion) + } + func searchMusicView(deselectItem searchMusicView: VideoEditorSearchMusicView) { + backgroundMusicPath = nil + musicView.backgroundButton.isSelected = false + } + func hideSearchMusicView(deselect: Bool = true) { + searchMusicView.endEditing(true) + isSearchMusic = false + UIView.animate(withDuration: 0.25) { + self.setSearchMusicViewFrame() + } completion: { _ in + if deselect { + self.searchMusicView.deselect() + } + self.searchMusicView.clearData() + } + } +} diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Editor/Model/EditorChartlet.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/Model/EditorChartlet.swift new file mode 100644 index 00000000..373155c5 --- /dev/null +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/Model/EditorChartlet.swift @@ -0,0 +1,73 @@ +// +// EditorChartlet.swift +// HXPHPicker +// +// Created by Slience on 2021/7/26. +// + +import UIKit + + +public typealias EditorTitleChartletResponse = ([EditorChartlet]) -> Void +public typealias EditorChartletListResponse = (Int, [EditorChartlet]) -> Void + +public struct EditorChartlet { + + /// 贴图对应的 UIImage 对象 + public let image: UIImage? + + #if canImport(Kingfisher) + /// 贴图对应的 网络地址 + public let url: URL? + #endif + + public let ext: Any? + + public init(image: UIImage?, + ext: Any? = nil) { + self.image = image + #if canImport(Kingfisher) + self.url = nil + #endif + self.ext = ext + } + + #if canImport(Kingfisher) + public init(url: URL?, + ext: Any? = nil) { + self.url = url + self.image = nil + self.ext = ext + } + #endif +} + + +class EditorChartletTitle { + + /// 标题图标 对应的 UIImage 数据 + let image: UIImage? + + #if canImport(Kingfisher) + /// 标题图标 对应的 网络地址 + let url: URL? + #endif + + init(image: UIImage?) { + self.image = image + #if canImport(Kingfisher) + self.url = nil + #endif + } + + #if canImport(Kingfisher) + init(url: URL?) { + self.url = url + self.image = nil + } + #endif + + var isSelected: Bool = false + var isLoading: Bool = false + var chartletList: [EditorChartlet] = [] +} diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Editor/Model/EditorType.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/Model/EditorType.swift index b95737b2..b23d82bd 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Editor/Model/EditorType.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/Model/EditorType.swift @@ -13,7 +13,7 @@ public extension EditorController { case video } - enum AssetType { + enum SourceType { /// 本地 case local /// 网络 @@ -49,6 +49,12 @@ public extension EditorToolOptions { /// photo - 涂鸦 case graffiti + /// photo - 贴图 + case chartlet + + /// photo - 文本 + case text + /// photo - 马赛克 case mosaic @@ -107,7 +113,7 @@ extension PhotoEditorView { } extension EditorImageResizerView { - enum MirrorType { + enum MirrorType: Int, Codable { case none case horizontal } diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Editor/Model/PhotoEditorFilter.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/Model/PhotoEditorFilter.swift index bbffe44d..19c75bee 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Editor/Model/PhotoEditorFilter.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/Model/PhotoEditorFilter.swift @@ -6,7 +6,6 @@ // import UIKit -import CoreImage /// 需要添加滤镜的原始图片、上一次添加滤镜的图片,value,event public typealias PhotoEditorFilterHandler = (UIImage, UIImage?, Float, PhotoEditorFilterInfo.Event) -> UIImage? @@ -25,7 +24,7 @@ public struct PhotoEditorFilterInfo { /// 设置 -1 则代表不显示滑块 public let defaultValue: Float - /// 滤镜处理器,传入未添加滤镜的图片,返回添加滤镜之后的图片 + /// 滤镜处理器,内部会传入未添加滤镜的图片,返回添加滤镜之后的图片 public let filterHandler: PhotoEditorFilterHandler public init(filterName: String, @@ -37,7 +36,7 @@ public struct PhotoEditorFilterInfo { } } -class PhotoEditorFilter: Equatable { +class PhotoEditorFilter: Equatable, Codable { let filterName: String let defaultValue: Float diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Editor/Model/VideoEditorMusic.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/Model/VideoEditorMusic.swift index 7c8c45b8..f9c8553d 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Editor/Model/VideoEditorMusic.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/Model/VideoEditorMusic.swift @@ -8,30 +8,32 @@ import UIKit public struct VideoEditorMusicInfo { - /// 音频文件路径 - public let audioPath: String - /// 歌词lrc路径 - public let lrcPath: String - public init(audioPath: String, - lrcPath: String) { - self.audioPath = audioPath - self.lrcPath = lrcPath + /// 音频文件本地/网络地址(MP3格式) + public let audioURL: URL + /// 歌词lrc内容(包含歌名和歌手名的话会显示) + public let lrc: String + public init(audioURL: URL, + lrc: String) { + self.audioURL = audioURL + self.lrc = lrc } } class VideoEditorMusic: Equatable { - let audioPath: String - let lrcPath: String - init(audioPath: String, - lrcPath: String) { - self.audioPath = audioPath - self.lrcPath = lrcPath + let audioURL: URL + let lrc: String + init(audioURL: URL, + lrc: String) { + self.audioURL = audioURL + self.lrc = lrc } var isLoading: Bool = false + var isSelected: Bool = false var metaData: [String: String] = [:] var lyrics: [VideoEditorLyric] = [] + var lyricIsEmpty = false var songName: String? { metaData["ti"] } var singer: String? { metaData["ar"] } var time: TimeInterval? { @@ -44,12 +46,6 @@ class VideoEditorMusic: Equatable { } func parseLrc() { - let lrc: String - do { - lrc = try String(contentsOfFile: lrcPath) - } catch { - return - } let lines = lrc.replacingOccurrences(of: "\r", with: "").components(separatedBy: "\n") let tags = ["ti", "ar", "al", "by", "offset", "t_time"] let pattern1 = "(\\[\\d{0,2}:\\d{0,2}([.|:]\\d{0,3})?\\])" @@ -125,6 +121,10 @@ class VideoEditorMusic: Equatable { } } lyrics = sorted + if lyrics.isEmpty { + lyricIsEmpty = true + lyrics.append(.init(lyric: "此歌曲暂无歌词,请您欣赏".localized)) + } } func lyric(at range: NSRange) -> [VideoEditorLyric] { diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Editor/PhotoEditResult.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/PhotoEditResult.swift index 03b74af8..0484f804 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Editor/PhotoEditResult.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/PhotoEditResult.swift @@ -9,7 +9,7 @@ import UIKit public struct PhotoEditResult { - public enum ImageType { + public enum ImageType: Int, Codable { /// 静态图 case normal /// 动图 @@ -30,16 +30,17 @@ public struct PhotoEditResult { let editedData: PhotoEditData } -struct PhotoEditData { +struct PhotoEditData: Codable { let isPortrait: Bool let cropData: PhotoEditCropData? let brushData: [PhotoEditorBrushData] let filter: PhotoEditorFilter? let filterValue: Float let mosaicData: [PhotoEditorMosaicData] + let stickerData: EditorStickerData? } -struct PhotoEditCropData { +struct PhotoEditCropData: Codable { let cropSize: CGSize let zoomScale: CGFloat let contentInset: UIEdgeInsets @@ -51,3 +52,33 @@ struct PhotoEditCropData { let transform: CGAffineTransform let mirrorType: EditorImageResizerView.MirrorType } + +extension PhotoEditResult: Codable { + enum CodingKeys: CodingKey { + case editedImage + case editedImageURL + case imageType + case editedData + } + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + let imageData = try container.decode(Data.self, forKey: .editedImage) + editedImage = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(imageData) as! UIImage + editedImageURL = try container.decode(URL.self, forKey: .editedImageURL) + imageType = try container.decode(ImageType.self, forKey: .imageType) + editedData = try container.decode(PhotoEditData.self, forKey: .editedData) + } + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + if #available(iOS 11.0, *) { + let imageData = try NSKeyedArchiver.archivedData(withRootObject: editedImage, requiringSecureCoding: false) + try container.encode(imageData, forKey: .editedImage) + } else { + let imageData = NSKeyedArchiver.archivedData(withRootObject: editedImage) + try container.encode(imageData, forKey: .editedImage) + } + try container.encode(editedImageURL, forKey: .editedImageURL) + try container.encode(imageType, forKey: .imageType) + try container.encode(editedData, forKey: .editedData) + } +} diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Editor/Util/Editor+PhotoTools.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/Util/Editor+PhotoTools.swift index 4d495b43..a8e336da 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Editor/Util/Editor+PhotoTools.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/Util/Editor+PhotoTools.swift @@ -70,74 +70,134 @@ extension PhotoTools { return getFrameDuration(from: gifInfo) } + public class func defaultColors() -> [String] { + ["#ffffff", "#2B2B2B", "#FA5150", "#FEC200", "#07C160", "#10ADFF", "#6467EF"] + } + + #if canImport(Kingfisher) + public class func defaultTitleChartlet() -> [EditorChartlet] { + let title = EditorChartlet( + url: URL(string: "http://tsnrhapp.oss-cn-hangzhou.aliyuncs.com/chartle/xxy_s_highlighted.png") + ) + return [title] + } + + public class func defaultNetworkChartlet() -> [EditorChartlet] { + var chartletList: [EditorChartlet] = [] + for index in 1...40 { + let urlString = "http://tsnrhapp.oss-cn-hangzhou.aliyuncs.com/chartle/xxy" + String(index) + ".png" + let chartlet = EditorChartlet( + url: .init(string: urlString) + ) + chartletList.append(chartlet) + } + return chartletList + } + #endif + /// 默认滤镜 public class func defaultFilters() -> [PhotoEditorFilterInfo] { return [ - PhotoEditorFilterInfo(filterName: "老电影".localized, - defaultValue: 1) { + PhotoEditorFilterInfo( + filterName: "老电影".localized, + defaultValue: 1 + ) { (image, lastImage, value, event) in if event == .touchUpInside { return oldMovie(image, value: value) } return nil }, - PhotoEditorFilterInfo(filterName: "怀旧".localized, - defaultValue: -1) { + PhotoEditorFilterInfo( + filterName: "怀旧".localized, + defaultValue: -1 + ) { (image, _, _, _) in image.filter(name: "CIPhotoEffectInstant", - parameters: [:]) + parameters: [:] + ) }, - PhotoEditorFilterInfo(filterName: "黑白".localized, - defaultValue: -1) { + PhotoEditorFilterInfo( + filterName: "黑白".localized, + defaultValue: -1) { (image, _, _, _) in image.filter(name: "CIPhotoEffectNoir", - parameters: [:]) + parameters: [:] + ) }, - PhotoEditorFilterInfo(filterName: "色调".localized, - defaultValue: -1) { + PhotoEditorFilterInfo( + filterName: "色调".localized, + defaultValue: -1 + ) { (image, _, _, _) in image.filter(name: "CIPhotoEffectTonal", - parameters: [:]) + parameters: [:] + ) }, - PhotoEditorFilterInfo(filterName: "模糊".localized, - defaultValue: 0.5) { + PhotoEditorFilterInfo( + filterName: "模糊".localized, + defaultValue: 0.5 + ) { (image, lastImage, value, event) in if event == .touchUpInside { - return image.filter(name: "CIGaussianBlur", - parameters: [ - kCIInputRadiusKey: NSNumber(value: 10 * value) - ]) + return image.filter( + name: "CIGaussianBlur", + parameters: [ + kCIInputRadiusKey: NSNumber(value: 10 * value) + ] + ) } return nil }, - PhotoEditorFilterInfo(filterName: "岁月".localized, - defaultValue: -1) { + PhotoEditorFilterInfo( + filterName: "岁月".localized, + defaultValue: -1 + ) { (image, _, _, _) in - image.filter(name: "CIPhotoEffectTransfer", - parameters: [:]) + image.filter( + name: "CIPhotoEffectTransfer", + parameters: [:] + ) }, - PhotoEditorFilterInfo(filterName: "单色".localized, - defaultValue: -1) { + PhotoEditorFilterInfo( + filterName: "单色".localized, + defaultValue: -1 + ) { (image, _, _, _) in - image.filter(name: "CIPhotoEffectMono", parameters: [:]) + image.filter( + name: "CIPhotoEffectMono", + parameters: [:] + ) }, - PhotoEditorFilterInfo(filterName: "褪色".localized, - defaultValue: -1) { + PhotoEditorFilterInfo( + filterName: "褪色".localized, + defaultValue: -1 + ) { (image, _, _, _) in - image.filter(name: "CIPhotoEffectFade", - parameters: [:]) + image.filter( + name: "CIPhotoEffectFade", + parameters: [:] + ) }, - PhotoEditorFilterInfo(filterName: "冲印".localized, - defaultValue: -1) { + PhotoEditorFilterInfo( + filterName: "冲印".localized, + defaultValue: -1 + ) { (image, _, _, _) in - image.filter(name: "CIPhotoEffectProcess", - parameters: [:]) + image.filter( + name: "CIPhotoEffectProcess", + parameters: [:] + ) }, - PhotoEditorFilterInfo(filterName: "铬黄".localized, - defaultValue: -1) { + PhotoEditorFilterInfo( + filterName: "铬黄".localized, + defaultValue: -1 + ) { (image, _, _, _) in - image.filter(name: "CIPhotoEffectChrome", - parameters: [:]) + image.filter( + name: "CIPhotoEffectChrome", + parameters: [:] + ) } ] } @@ -184,12 +244,14 @@ extension PhotoTools { /// - Parameters: /// - videoURL: 视频地址 /// - audioURL: 需要添加的音频地址 - /// - hasOriginalSound: 是否有原声 + /// - audioVolume: 需要添加的音频音量 + /// - originalAudioVolume: 视频原始音频音量 /// - presentName: 导出质量 /// - completion: 添加完成 class func videoAddBackgroundMusic(forVideo videoURL: URL, audioURL: URL?, - hasOriginalSound: Bool, + audioVolume: Float, + originalAudioVolume: Float, presentName: String, completion: @escaping (URL?) -> Void) { let outputURL = getVideoTmpURL() @@ -229,18 +291,17 @@ extension PhotoTools { } } newAudioInputParams = AVMutableAudioMixInputParameters(track: newAudioTrack) - newAudioInputParams?.setVolumeRamp(fromStartVolume: 1, toEndVolume: 1, timeRange: CMTimeRangeMake(start: .zero, duration: videoAsset.duration)) + newAudioInputParams?.setVolumeRamp(fromStartVolume: audioVolume, toEndVolume: audioVolume, timeRange: CMTimeRangeMake(start: .zero, duration: videoAsset.duration)) newAudioInputParams?.trackID = newAudioTrack?.trackID ?? kCMPersistentTrackID_Invalid } - if let originalVoiceTrack = mixComposition.addMutableTrack(withMediaType: .audio, preferredTrackID: kCMPersistentTrackID_Invalid), - (hasOriginalSound || (!hasOriginalSound && audioURL == nil)) { + if let originalVoiceTrack = mixComposition.addMutableTrack(withMediaType: .audio, preferredTrackID: kCMPersistentTrackID_Invalid) { if let audioTrack = videoAsset.tracks(withMediaType: .audio).first { try originalVoiceTrack.insertTimeRange(videoTimeRange, of: audioTrack, at: .zero) } - let volue: Float = !hasOriginalSound && audioURL == nil ? 0 : 1 + let volume: Float = originalAudioVolume let originalAudioInputParams = AVMutableAudioMixInputParameters(track: originalVoiceTrack) - originalAudioInputParams.setVolumeRamp(fromStartVolume: volue, toEndVolume: volue, timeRange: CMTimeRangeMake(start: .zero, duration: videoAsset.duration)) + originalAudioInputParams.setVolumeRamp(fromStartVolume: volume, toEndVolume: volume, timeRange: CMTimeRangeMake(start: .zero, duration: videoAsset.duration)) originalAudioInputParams.trackID = originalVoiceTrack.trackID if let newAudioInputParams = newAudioInputParams { audioMix.inputParameters = [newAudioInputParams, originalAudioInputParams] diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Editor/VideoEditResult.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/VideoEditResult.swift index 8bf6ccd9..eceda7b1 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Editor/VideoEditResult.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/VideoEditResult.swift @@ -25,19 +25,23 @@ public struct VideoEditResult { /// 视频时长 秒 public let videoDuration: TimeInterval + /// 原视频音量 + public let videoSoundVolume: Float + /// 背景音乐地址 public let backgroundMusicURL: URL? - /// 隐藏视频原声 - public let hideVideoSoundTrack: Bool + /// 背景音乐音量 + public let backgroundMusicVolume: Float /// 裁剪数据 public let cropData: VideoCropData? public init(editedURL: URL, cropData: VideoCropData?, + videoSoundVolume: Float, backgroundMusicURL: URL?, - hideVideoSoundTrack: Bool) { + backgroundMusicVolume: Float) { editedFileSize = editedURL.fileSize videoDuration = PhotoTools.getVideoDuration(videoURL: editedURL) @@ -45,12 +49,13 @@ public struct VideoEditResult { coverImage = PhotoTools.getVideoThumbnailImage(videoURL: editedURL, atTime: 0.1) self.editedURL = editedURL self.cropData = cropData + self.videoSoundVolume = videoSoundVolume self.backgroundMusicURL = backgroundMusicURL - self.hideVideoSoundTrack = hideVideoSoundTrack + self.backgroundMusicVolume = backgroundMusicVolume } } -public struct VideoCropData { +public struct VideoCropData: Codable { /// 编辑的开始时间 public let startTime: TimeInterval @@ -64,23 +69,83 @@ public struct VideoCropData { /// 0:offsetX ,CollectionView的offset.x /// 1:validX ,裁剪框的x /// 2:validWidth ,裁剪框的宽度 - public let cropingData: (CGFloat, CGFloat, CGFloat) + public let cropingData: CropData /// 裁剪框的位置大小比例 /// 0:offsetX ,CollectionView的offset.x /// 1:validX ,裁剪框的x /// 2:validWidth ,裁剪框的宽度 - public let cropRectData: (CGFloat, CGFloat, CGFloat) + public let cropRectData: CropData public init(startTime: TimeInterval, endTime: TimeInterval, preferredTimescale: Int32, - cropingData: (CGFloat, CGFloat, CGFloat), - cropRectData: (CGFloat, CGFloat, CGFloat)) { + cropingData: CropData, + cropRectData: CropData) { self.startTime = startTime self.endTime = endTime self.preferredTimescale = preferredTimescale self.cropingData = cropingData self.cropRectData = cropRectData } + + public struct CropData: Codable { + let offsetX: CGFloat + let validX: CGFloat + let validWidth: CGFloat + } +} + +extension VideoEditResult: Codable { + + enum CodingKeys: String, CodingKey { + case editedURL + case coverImage + case editedFileSize + case videoTime + case videoDuration + case videoSoundVolume + case backgroundMusicURL + case backgroundMusicVolume + case cropData + } + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + editedURL = try container.decode(URL.self, forKey: .editedURL) + if let coverImageData = try container.decodeIfPresent(Data.self, forKey: .coverImage) { + coverImage = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(coverImageData) as? UIImage + }else { + coverImage = nil + } + editedFileSize = try container.decode(Int.self, forKey: .editedFileSize) + videoTime = try container.decode(String.self, forKey: .videoTime) + videoDuration = try container.decode(TimeInterval.self, forKey: .videoDuration) + videoSoundVolume = try container.decode(Float.self, forKey: .videoSoundVolume) + backgroundMusicURL = try container.decodeIfPresent(URL.self, forKey: .backgroundMusicURL) + backgroundMusicVolume = try container.decode(Float.self, forKey: .backgroundMusicVolume) + cropData = try container.decode(VideoCropData.self, forKey: .cropData) + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(editedURL, forKey: .editedURL) + try container.encode(editedFileSize, forKey: .editedFileSize) + try container.encode(videoTime, forKey: .videoTime) + try container.encode(videoDuration, forKey: .videoDuration) + try container.encode(videoSoundVolume, forKey: .videoSoundVolume) + try container.encode(backgroundMusicURL, forKey: .backgroundMusicURL) + try container.encode(backgroundMusicVolume, forKey: .backgroundMusicVolume) + try container.encode(cropData, forKey: .cropData) + + if let image = coverImage { + if #available(iOS 11.0, *) { + let imageData = try NSKeyedArchiver.archivedData(withRootObject: image, requiringSecureCoding: false) + try container.encode(imageData, forKey: .coverImage) + } else { + // Fallback on earlier versions + let imageData = NSKeyedArchiver.archivedData(withRootObject: image) + try container.encode(imageData, forKey: .coverImage) + } + } + } } diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/EditorChartletView.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/EditorChartletView.swift new file mode 100644 index 00000000..b5114ce0 --- /dev/null +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/EditorChartletView.swift @@ -0,0 +1,476 @@ +// +// EditorChartletView.swift +// HXPHPicker +// +// Created by Slience on 2021/7/24. +// + +import UIKit +#if canImport(Kingfisher) +import Kingfisher +#endif + +protocol EditorChartletViewDelegate: AnyObject { + func chartletView(backClick chartletView: EditorChartletView) + func chartletView(_ chartletView: EditorChartletView, + loadTitleChartlet response: @escaping EditorTitleChartletResponse) + func chartletView(_ chartletView: EditorChartletView, + titleChartlet: EditorChartlet, + titleIndex: Int, + loadChartletList response: @escaping EditorChartletListResponse) + func chartletView(_ chartletView: EditorChartletView, didSelectImage image: UIImage) +} + +class EditorChartletView: UIView { + weak var delegate: EditorChartletViewDelegate? + lazy var loadingView: UIActivityIndicatorView = { + let view = UIActivityIndicatorView(style: .white) + view.hidesWhenStopped = true + return view + }() + lazy var titleBgView: UIVisualEffectView = { + let effect = UIBlurEffect(style: .dark) + let view = UIVisualEffectView(effect: effect) + return view + }() + lazy var bgView: UIVisualEffectView = { + let effect = UIBlurEffect(style: .dark) + let view = UIVisualEffectView(effect: effect) + return view + }() + lazy var backButton: UIButton = { + let button = UIButton(type: .system) + button.tintColor = .white + button.setImage("hx_photo_edit_pull_down".image, for: .normal) + button.addTarget(self, action: #selector(didBackButtonClick), for: .touchUpInside) + return button + }() + @objc func didBackButtonClick() { + delegate?.chartletView(backClick: self) + } + lazy var titleFlowLayout: UICollectionViewFlowLayout = { + let flowLayout = UICollectionViewFlowLayout() + flowLayout.scrollDirection = .horizontal + flowLayout.minimumLineSpacing = 15 + flowLayout.minimumInteritemSpacing = 0 + return flowLayout + }() + lazy var titleView: UICollectionView = { + let view = UICollectionView(frame: .zero, collectionViewLayout: titleFlowLayout) + view.backgroundColor = .clear + view.dataSource = self + view.delegate = self + view.showsVerticalScrollIndicator = false + view.showsHorizontalScrollIndicator = false + if #available(iOS 11.0, *) { + view.contentInsetAdjustmentBehavior = .never + } + view.register(EditorChartletViewCell.self, forCellWithReuseIdentifier: "EditorChartletViewCellTitleID") + return view + }() + lazy var listFlowLayout: UICollectionViewFlowLayout = { + let flowLayout = UICollectionViewFlowLayout() + flowLayout.scrollDirection = .horizontal + flowLayout.minimumLineSpacing = 0 + flowLayout.minimumInteritemSpacing = 0 + return flowLayout + }() + + lazy var listView: UICollectionView = { + let view = UICollectionView.init(frame: .zero, collectionViewLayout: listFlowLayout) + view.backgroundColor = .clear + view.dataSource = self + view.delegate = self + view.showsVerticalScrollIndicator = false + view.showsHorizontalScrollIndicator = false + view.isPagingEnabled = true + if #available(iOS 11.0, *) { + view.contentInsetAdjustmentBehavior = .never + } + view.register(EditorChartletViewListCell.self, forCellWithReuseIdentifier: "EditorChartletViewListCell_ID") + return view + }() + let config: PhotoEditorConfiguration.ChartletConfig + var titles: [EditorChartletTitle] = [] + var selectedTitleIndex: Int = 0 + var configTitles: [EditorChartlet] = [] + init(config: PhotoEditorConfiguration.ChartletConfig) { + self.config = config + super.init(frame: .zero) + setupTitles(config.titles) + addSubview(bgView) + addSubview(listView) + addSubview(titleBgView) + addSubview(titleView) + addSubview(backButton) + addSubview(loadingView) + } + + func setupTitles(_ titleChartlets: [EditorChartlet]) { + configTitles = titleChartlets + for (index, title) in titleChartlets.enumerated() { + let titleChartlet: EditorChartletTitle + if let image = title.image { + titleChartlet = EditorChartletTitle(image: image) + }else { + #if canImport(Kingfisher) + if let url = title.url { + titleChartlet = EditorChartletTitle(url: url) + }else { + titleChartlet = .init(image: "hx_picker_album_empty".image) + } + #else + titleChartlet = .init(image: "hx_picker_album_empty".image) + #endif + } + if index == 0 { + titleChartlet.isSelected = true + } + titles.append(titleChartlet) + } + } + + override func layoutSubviews() { + super.layoutSubviews() + titleBgView.frame = CGRect(x: 0, y: 0, width: width, height: 50) + backButton.frame = CGRect(x: width - 50 - UIDevice.rightMargin, y: 0, width: 50, height: 50) + bgView.frame = CGRect(x: 0, y: titleBgView.frame.maxY, width: width, height: height - titleBgView.height) + titleView.frame = CGRect(x: 0, y: 0, width: width, height: 50) + titleView.contentInset = UIEdgeInsets(top: 5, left: 15 + UIDevice.leftMargin, bottom: 5, right: backButton.width + UIDevice.rightMargin) + listView.frame = bounds + loadingView.center = CGPoint(x: width * 0.5, y: height * 0.5) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} + +extension EditorChartletView: UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout, EditorChartletViewListCellDelegate { + func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + return titles.count + } + + func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + if collectionView == titleView { + let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "EditorChartletViewCellTitleID", for: indexPath) as! EditorChartletViewCell + let titleChartlet = titles[indexPath.item] + cell.titleChartlet = titleChartlet + return cell + }else { + let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "EditorChartletViewListCell_ID", for: indexPath) as! EditorChartletViewListCell + cell.rowCount = config.rowCount + cell.delegate = self + return cell + } + } + + func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { + if collectionView == titleView { + return CGSize(width: 40, height: 40) + }else { + return listView.size + } + } + func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) { + if collectionView != listView { + return + } + if config.loadScene == .cellDisplay { + requestData(index: indexPath.item) + } + let titleChartlet = titles[indexPath.item] + if !titleChartlet.chartletList.isEmpty || !titleChartlet.isLoading { + let listCell = cell as! EditorChartletViewListCell + listCell.chartletList = titleChartlet.chartletList + return + } + let listCell = cell as! EditorChartletViewListCell + listCell.startLoading() + } + func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell, forItemAt indexPath: IndexPath) { + if collectionView != listView { + return + } + let listCell = cell as! EditorChartletViewListCell + listCell.stopLoad() + } + func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { + collectionView.deselectItem(at: indexPath, animated: false) + if collectionView == titleView { + listView.scrollToItem(at: indexPath, at: .centeredHorizontally, animated: false) + requestData(index: indexPath.item) + } + } + func scrollViewDidScroll(_ scrollView: UIScrollView) { + if scrollView != listView { + return + } + let currentIndex = currentIndex() + if currentIndex == selectedTitleIndex { + return + } + let indexPath = IndexPath(item: currentIndex, section: 0) + titleView.scrollToItem(at: indexPath, at: .centeredHorizontally, animated: true) + let titleCell = titleView.cellForItem(at: indexPath) as? EditorChartletViewCell + titleCell?.isSelectedTitle = true + titles[currentIndex].isSelected = true + + let selectedCell = titleView.cellForItem(at: IndexPath(item: selectedTitleIndex, section: 0)) as? EditorChartletViewCell + selectedCell?.isSelectedTitle = false + titles[selectedTitleIndex].isSelected = false + + selectedTitleIndex = currentIndex + } + func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { + if scrollView != listView { + return + } + if config.loadScene == .scrollStop { + requestData(index: currentIndex()) + } + } + + func currentIndex() -> Int { + let offsetX = listView.contentOffset.x + (listView.width) * 0.5 + var currentIndex = Int(offsetX / listView.width) + if currentIndex > titles.count - 1 { + currentIndex = titles.count - 1 + } + if currentIndex < 0 { + currentIndex = 0 + } + return currentIndex + } + + func requestData(index: Int) { + let titleChartle = titles[index] + if !titleChartle.chartletList.isEmpty || titleChartle.isLoading || configTitles.isEmpty { + return + } + titleChartle.isLoading = true + delegate?.chartletView(self, + titleChartlet: configTitles[index], + titleIndex: index, + loadChartletList: { [weak self] item, chartletList in + guard let self = self else { return } + titleChartle.isLoading = false + self.titles[item].chartletList = chartletList + let cell = self.listView.cellForItem(at: IndexPath(item: index, section: 0)) as? EditorChartletViewListCell + cell?.chartletList = titleChartle.chartletList + cell?.stopLoad() + }) + } + func firstRequest() { + if titles.isEmpty { + loadingView.startAnimating() + delegate?.chartletView(self, loadTitleChartlet: { [weak self] titleChartlets in + guard let self = self else { return } + self.loadingView.stopAnimating() + self.setupTitles(titleChartlets) + if self.config.loadScene == .scrollStop { + self.requestData(index: 0) + } + self.titleView.reloadData() + self.listView.reloadData() + }) + return + } + requestData(index: 0) + } + func listCell(_ cell: EditorChartletViewListCell, didSelectImage image: UIImage) { + delegate?.chartletView(self, didSelectImage: image) + } +} + +protocol EditorChartletViewListCellDelegate: AnyObject { + func listCell(_ cell: EditorChartletViewListCell, didSelectImage image: UIImage) +} + +class EditorChartletViewListCell: UICollectionViewCell, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout { + weak var delegate: EditorChartletViewListCellDelegate? + lazy var loadingView: UIActivityIndicatorView = { + let view = UIActivityIndicatorView(style: .white) + view.hidesWhenStopped = true + return view + }() + + lazy var flowLayout: UICollectionViewFlowLayout = { + let flowLayout = UICollectionViewFlowLayout() + flowLayout.scrollDirection = .vertical + flowLayout.minimumLineSpacing = 15 + flowLayout.minimumInteritemSpacing = 15 + return flowLayout + }() + lazy var collectionView: UICollectionView = { + let view = UICollectionView.init(frame: .zero, collectionViewLayout: flowLayout) + view.backgroundColor = .clear + view.dataSource = self + view.delegate = self + view.showsHorizontalScrollIndicator = false + if #available(iOS 11.0, *) { + view.contentInsetAdjustmentBehavior = .never + } + view.register(EditorChartletViewCell.self, forCellWithReuseIdentifier: "EditorChartletViewListCellID") + return view + }() + var rowCount: Int = 4 + var chartletList: [EditorChartlet] = [] { + didSet { + collectionView.reloadData() + resetOffset() + } + } + + func resetOffset() { + collectionView.contentOffset = CGPoint(x: -collectionView.contentInset.left, y: -collectionView.contentInset.top) + } + + func startLoading() { + loadingView.startAnimating() + } + func stopLoad() { + loadingView.stopAnimating() + } + + override init(frame: CGRect) { + super.init(frame: frame) + contentView.addSubview(collectionView) + contentView.addSubview(loadingView) + } + + func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + return chartletList.count + } + + func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "EditorChartletViewListCellID", for: indexPath) as! EditorChartletViewCell + cell.chartlet = chartletList[indexPath.item] + return cell + } + + func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { + let rowCount = !UIDevice.isPortrait && !UIDevice.isPad ? 7 : CGFloat(self.rowCount) + let margin = collectionView.contentInset.left + collectionView.contentInset.right + let spacing = flowLayout.minimumLineSpacing * (rowCount - 1) + let itemWidth = (width - margin - spacing) / rowCount + return CGSize(width: itemWidth, height: itemWidth) + } + + func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { + collectionView.deselectItem(at: indexPath, animated: false) + let cell = collectionView.cellForItem(at: indexPath) as! EditorChartletViewCell + #if canImport(Kingfisher) + if let image = cell.chartlet.image { + delegate?.listCell(self, didSelectImage: image) + }else if let url = cell.chartlet.url { + PhotoTools.downloadNetworkImage(with: url, options: [.backgroundDecode], completionHandler: { [weak self] (image) in + guard let self = self else { return } + if let image = image { + self.delegate?.listCell(self, didSelectImage: image) + } + }) + } + #else + if let image = cell.chartlet.image { + delegate?.listCell(self, didSelectImage: image) + } + #endif + } + + override func layoutSubviews() { + super.layoutSubviews() + collectionView.frame = bounds + loadingView.center = CGPoint(x: width * 0.5, y: height * 0.5) + collectionView.contentInset = UIEdgeInsets(top: 60, left: 15 + UIDevice.leftMargin, bottom: 15 + UIDevice.bottomMargin, right: 15 + UIDevice.rightMargin) + collectionView.scrollIndicatorInsets = UIEdgeInsets(top: 60, left: UIDevice.leftMargin, bottom: 15 + UIDevice.bottomMargin, right: UIDevice.rightMargin) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} + +class EditorChartletViewCell: UICollectionViewCell { + lazy var selectedBgView: UIVisualEffectView = { + let effect = UIBlurEffect(style: .dark) + let view = UIVisualEffectView(effect: effect) + view.isHidden = true + view.layer.cornerRadius = 5 + view.layer.masksToBounds = true + return view + }() + + lazy var imageView: UIImageView = { + let view = UIImageView() + view.contentMode = .scaleAspectFit + view.clipsToBounds = true + return view + }() + + var titleChartlet: EditorChartletTitle! { + didSet { + selectedBgView.isHidden = !titleChartlet.isSelected + #if canImport(Kingfisher) + setupImage(image: titleChartlet.image, url: titleChartlet.url) + #else + setupImage(image: titleChartlet.image) + #endif + } + } + + var isSelectedTitle: Bool = false { + didSet { + titleChartlet.isSelected = isSelectedTitle + selectedBgView.isHidden = !titleChartlet.isSelected + } + } + + var chartlet: EditorChartlet! { + didSet { + #if canImport(Kingfisher) + setupImage(image: chartlet.image, url: chartlet.url) + #else + setupImage(image: chartlet.image) + #endif + } + } + + func setupImage(image: UIImage?, url: URL? = nil) { + imageView.image = nil + #if canImport(Kingfisher) + if let image = image { + imageView.image = image + }else if let url = url { + imageView.kf.indicatorType = .activity + (imageView.kf.indicator?.view as? UIActivityIndicatorView)?.color = .white + let processor = DownsamplingImageProcessor(size: CGSize(width: width * 2, height: height * 2)) + imageView.kf.setImage(with: url, options: [.cacheOriginalImage, .processor(processor), .backgroundDecode]) + } + #else + if let image = image { + imageView.image = image + } + #endif + } + + override init(frame: CGRect) { + super.init(frame: frame) + contentView.addSubview(selectedBgView) + contentView.addSubview(imageView) + } + override func layoutSubviews() { + super.layoutSubviews() + selectedBgView.frame = bounds + if titleChartlet != nil { + imageView.size = CGSize(width: 25, height: 25) + imageView.center = CGPoint(x: width * 0.5, y: height * 0.5) + }else { + imageView.frame = bounds + } + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/EditorStickerContentView.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/EditorStickerContentView.swift new file mode 100644 index 00000000..6a7b325b --- /dev/null +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/EditorStickerContentView.swift @@ -0,0 +1,165 @@ +// +// EditorStickerContentView.swift +// HXPHPicker +// +// Created by Slience on 2021/7/20. +// + +import UIKit + +struct EditorStickerText { + let image: UIImage + let text: String + let textColor: UIColor + let showBackgroud: Bool +} + +struct EditorStickerItem { + let image: UIImage + let text: EditorStickerText? + var frame: CGRect { + var width = UIScreen.main.bounds.width - 80 + if text != nil { + width = UIScreen.main.bounds.width - 30 + } + let height = width + var itemWidth: CGFloat = 0 + var itemHeight: CGFloat = 0 + let imageWidth = image.width + var imageHeight = image.height + if imageWidth > width { + imageHeight = width / imageWidth * imageHeight + } + if imageHeight > height { + itemWidth = height / image.height * imageWidth + itemHeight = height + }else { + if imageWidth > width { + itemWidth = width + }else { + itemWidth = imageWidth + } + itemHeight = imageHeight + } + return CGRect(x: 0, y: 0, width: itemWidth, height: itemHeight) + } +} + +extension EditorStickerText: Codable { + enum CodingKeys: CodingKey { + case image + case text + case textColor + case showBackgroud + } + + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + let imageData = try container.decode(Data.self, forKey: .image) + image = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(imageData) as! UIImage + text = try container.decode(String.self, forKey: .text) + let colorData = try container.decode(Data.self, forKey: .textColor) + textColor = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(colorData) as! UIColor + showBackgroud = try container.decode(Bool.self, forKey: .showBackgroud) + } + func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + if #available(iOS 11.0, *) { + let imageData = try NSKeyedArchiver.archivedData(withRootObject: image, requiringSecureCoding: false) + try container.encode(imageData, forKey: .image) + let colorData = try NSKeyedArchiver.archivedData(withRootObject: textColor, requiringSecureCoding: false) + try container.encode(colorData, forKey: .textColor) + } else { + let imageData = NSKeyedArchiver.archivedData(withRootObject: image) + try container.encode(imageData, forKey: .image) + let colorData = NSKeyedArchiver.archivedData(withRootObject: textColor) + try container.encode(colorData, forKey: .textColor) + } + try container.encode(text, forKey: .text) + try container.encode(showBackgroud, forKey: .showBackgroud) + } +} + +extension EditorStickerItem: Codable { + enum CodingKeys: CodingKey { + case image + case hasText + case text + } + + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + let imageData = try container.decode(Data.self, forKey: .image) + image = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(imageData) as! UIImage + let hasText = try container.decode(Bool.self, forKey: .hasText) + if hasText { + text = try container.decode(EditorStickerText.self, forKey: .text) + }else { + text = nil + } + } + func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + if #available(iOS 11.0, *) { + let imageData = try NSKeyedArchiver.archivedData(withRootObject: image, requiringSecureCoding: false) + try container.encode(imageData, forKey: .image) + } else { + let imageData = NSKeyedArchiver.archivedData(withRootObject: image) + try container.encode(imageData, forKey: .image) + } + if let text = text { + try container.encode(text, forKey: .text) + try container.encode(true, forKey: .hasText) + }else { + try container.encode(false, forKey: .hasText) + } + } +} + +class EditorStickerContentView: UIView { + + lazy var imageView: UIImageView = { + let view = UIImageView(image: item.image) + view.contentMode = .scaleAspectFill + view.clipsToBounds = true + return view + }() + var item: EditorStickerItem + init(item: EditorStickerItem) { + self.item = item + super.init(frame: item.frame) + addSubview(imageView) + } + func update(item: EditorStickerItem) { + self.item = item + frame = item.frame + imageView.image = item.image + } + override func addGestureRecognizer(_ gestureRecognizer: UIGestureRecognizer) { + gestureRecognizer.delegate = self + super.addGestureRecognizer(gestureRecognizer) + } + override func layoutSubviews() { + super.layoutSubviews() + imageView.frame = bounds + } + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} + +extension EditorStickerContentView: UIGestureRecognizerDelegate { + func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool { + if otherGestureRecognizer.delegate is PhotoEditorViewController { + return false + } + if otherGestureRecognizer is UITapGestureRecognizer || gestureRecognizer is UITapGestureRecognizer { + return true + } + if let view = gestureRecognizer.view, view == self, + let otherView = otherGestureRecognizer.view, otherView == self { + return true + } + return false + } +} diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/EditorStickerItemView.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/EditorStickerItemView.swift new file mode 100644 index 00000000..cd94deb0 --- /dev/null +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/EditorStickerItemView.swift @@ -0,0 +1,363 @@ +// +// EditorStickerItemView.swift +// HXPHPicker +// +// Created by Slience on 2021/7/20. +// + +import UIKit + +protocol EditorStickerItemViewDelegate: AnyObject { + func stickerItemView(shouldTouchBegan itemView: EditorStickerItemView) -> Bool + func stickerItemView(didTouchBegan itemView: EditorStickerItemView) + func stickerItemView(touchEnded itemView: EditorStickerItemView) + func stickerItemView(_ itemView: EditorStickerItemView, updateStickerText item: EditorStickerItem) + func stickerItemView(_ itemView: EditorStickerItemView, tapGestureRecognizerNotInScope point: CGPoint) + func stickerItemView(_ itemView: EditorStickerItemView, panGestureRecognizerChanged panGR: UIPanGestureRecognizer) + func stickerItemView(panGestureRecognizerEnded itemView: EditorStickerItemView) -> Bool + func stickerItemView(_ itemView: EditorStickerItemView, moveToCenter rect: CGRect) -> Bool + func stickerItemView(_ itemView: EditorStickerItemView, maxScale itemSize: CGSize) -> CGFloat + func stickerItemView(_ itemView: EditorStickerItemView, minScale itemSize: CGSize) -> CGFloat +} + +class EditorStickerItemView: UIView { + weak var delegate: EditorStickerItemViewDelegate? + lazy var contentView: EditorStickerContentView = { + let view = EditorStickerContentView(item: item) + view.center = center + return view + }() + var item: EditorStickerItem + + var scale: CGFloat + var touching: Bool = false + + var isSelected: Bool = false { + willSet { + if isSelected == newValue { + return + } + if item.text != nil { + layer.shadowColor = newValue ? UIColor.black.withAlphaComponent(0.8).cgColor : UIColor.clear.cgColor + } + layer.cornerRadius = newValue ? 1 / scale : 0 + layer.borderWidth = newValue ? 1 / scale : 0 + isUserInteractionEnabled = newValue + + if newValue { + update(size: contentView.item.frame.size) + }else { + firstTouch = false + } + } + } + var itemMargin: CGFloat = 20 + + var initialScale: CGFloat = 1 + var initialPoint: CGPoint = .zero + var initialRadian: CGFloat = 0 + + init(item: EditorStickerItem, scale: CGFloat) { + self.item = item + self.scale = scale + let rect = CGRect(x: 0, y: 0, width: item.frame.width + itemMargin / scale, height: item.frame.height + itemMargin / scale) + super.init(frame: rect) + addSubview(contentView) + if item.text != nil { + layer.shadowColor = UIColor.black.withAlphaComponent(0.8).cgColor + } + + layer.borderColor = UIColor.white.cgColor + layer.shadowOpacity = 0.3 + layer.shadowOffset = CGSize(width: 0, height: 0) + layer.shadowRadius = 1 + initGestures() + } + override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { + let view = super.hitTest(point, with: event) + if bounds.contains(point) { + return contentView + } + return view + } + func initGestures() { + contentView.isUserInteractionEnabled = true + let tapGR = UITapGestureRecognizer(target: self, action: #selector(contentViewTapClick(tapGR:))) + contentView.addGestureRecognizer(tapGR) + let panGR = UIPanGestureRecognizer(target: self, action: #selector(contentViewPanClick(panGR:))) + contentView.addGestureRecognizer(panGR) + let pinchGR = UIPinchGestureRecognizer(target: self, action: #selector(contentViewPinchClick(pinchGR:))) + contentView.addGestureRecognizer(pinchGR) + let rotationGR = UIRotationGestureRecognizer(target: self, action: #selector(contentViewRotationClick(rotationGR:))) + contentView.addGestureRecognizer(rotationGR) + } + + @objc func contentViewTapClick(tapGR: UITapGestureRecognizer) { + if let shouldTouch = delegate?.stickerItemView(shouldTouchBegan: self), !shouldTouch { + return + } + let point = tapGR.location(in: self) + if !contentView.frame.contains(point) { + delegate?.stickerItemView(self, tapGestureRecognizerNotInScope: point) + isSelected = false + return + } + if firstTouch && isSelected && item.text != nil && !touching { + delegate?.stickerItemView(self, updateStickerText: item) + } + firstTouch = true + } + @objc func contentViewPanClick(panGR: UIPanGestureRecognizer) { + if let shouldTouch = delegate?.stickerItemView(shouldTouchBegan: self), !shouldTouch { + return + } + switch panGR.state { + case .began: + touching = true + firstTouch = true + delegate?.stickerItemView(didTouchBegan: self) + isSelected = true + initialPoint = self.center + case .changed: + let point = panGR.translation(in: superview) + center = CGPoint(x: initialPoint.x + point.x, y: initialPoint.y + point.y) + delegate?.stickerItemView(self, panGestureRecognizerChanged: panGR) + case .ended, .cancelled, .failed: + touching = false + var isDelete = false + if let panIsDelete = delegate?.stickerItemView(panGestureRecognizerEnded: self) { + isDelete = panIsDelete + } + self.delegate?.stickerItemView(touchEnded: self) + let rect = convert(contentView.frame, to: superview?.viewController()?.view) + if let moveToCenter = delegate?.stickerItemView(self, moveToCenter: rect), !isDelete { + let keyWindow = UIApplication.shared.keyWindow + if let view = keyWindow, moveToCenter, + let viewCenter = superview?.convert(CGPoint(x: view.width * 0.5, y: view.height * 0.5), from: view){ + UIView.animate(withDuration: 0.25) { + self.center = viewCenter + } + } + } + default: + break + } + } + @objc func contentViewPinchClick(pinchGR: UIPinchGestureRecognizer) { + if let shouldTouch = delegate?.stickerItemView(shouldTouchBegan: self), !shouldTouch { + return + } + switch pinchGR.state { + case .began: + touching = true + firstTouch = true + delegate?.stickerItemView(didTouchBegan: self) + isSelected = true + initialScale = pinchScale + update(pinchScale: initialScale * pinchGR.scale, isPinch: true, isMirror: true) + case .changed: + update(pinchScale: initialScale * pinchGR.scale, isPinch: true, isMirror: true) + case .ended, .cancelled, .failed: + touching = false + delegate?.stickerItemView(touchEnded: self) + default: + break + } + if pinchGR.state == .began && pinchGR.state == .changed { + pinchGR.scale = 1 + } + } + @objc func contentViewRotationClick(rotationGR: UIRotationGestureRecognizer) { + if let shouldTouch = delegate?.stickerItemView(shouldTouchBegan: self), !shouldTouch { + return + } + switch rotationGR.state { + case .began: + firstTouch = true + touching = true + isSelected = true + delegate?.stickerItemView(didTouchBegan: self) + initialRadian = radian + rotationGR.rotation = 0 + case .changed: + if let superView = superview, superView is EditorStickerView { + if superMirrorType == .none { + if mirrorType == .horizontal { + radian = initialRadian - rotationGR.rotation + }else { + radian = initialRadian + rotationGR.rotation + } + }else { + if mirrorType == .horizontal { + radian = initialRadian - rotationGR.rotation + }else { + radian = initialRadian + rotationGR.rotation + } + } + }else { + if superMirrorType == .none { + if mirrorType == .horizontal { + radian = initialRadian - rotationGR.rotation + }else { + radian = initialRadian + rotationGR.rotation + } + }else { + if mirrorType == .horizontal { + radian = initialRadian - rotationGR.rotation + }else { + radian = initialRadian + rotationGR.rotation + } + } + } + update(pinchScale: pinchScale, rotation: radian, isMirror: true) + case .ended, .cancelled, .failed: + touching = false + delegate?.stickerItemView(touchEnded: self) + rotationGR.rotation = 0 + default: + break + } + } + var firstTouch: Bool = false + var radian: CGFloat = 0 + var pinchScale: CGFloat = 1 + var mirrorType: EditorImageResizerView.MirrorType = .none + var superMirrorType: EditorImageResizerView.MirrorType = .none + var superAngle: CGFloat = 0 + func update(pinchScale: CGFloat, + rotation: CGFloat = CGFloat(MAXFLOAT), + isInitialize: Bool = false, + isPinch: Bool = false, + isMirror: Bool = false) { + if rotation != CGFloat(MAXFLOAT) { + radian = rotation + } + var minScale = 0.2 / scale + var maxScale = 3.0 / scale + if let min = delegate?.stickerItemView(self, minScale: item.frame.size) { + minScale = min / scale + } + if let max = delegate?.stickerItemView(self, maxScale: item.frame.size) { + maxScale = max / scale + } + if isInitialize { + self.pinchScale = pinchScale + }else { + if isPinch { + if pinchScale > maxScale { + if pinchScale < initialScale { + self.pinchScale = pinchScale + }else { + if initialScale < maxScale { + self.pinchScale = min(max(pinchScale, minScale), maxScale) + }else { + self.pinchScale = initialScale + } + } + }else if pinchScale < minScale { + if pinchScale > initialScale { + self.pinchScale = pinchScale + }else { + if minScale < initialScale { + self.pinchScale = min(max(pinchScale, minScale), maxScale) + }else { + self.pinchScale = initialScale + } + } + }else { + self.pinchScale = min(max(pinchScale, minScale), maxScale) + } + }else { + self.pinchScale = pinchScale + } + } + transform = .identity + var margin = itemMargin / scale + if touching { + margin *= scale + contentView.transform = .init(scaleX: self.pinchScale * scale, y: self.pinchScale * scale) + }else { + contentView.transform = .init(scaleX: self.pinchScale, y: self.pinchScale) + } + var rect = frame + rect.origin.x += (rect.width - (contentView.width + margin)) / 2 + rect.origin.y += (rect.height - (contentView.height + margin)) / 2 + rect.size.width = contentView.width + margin + rect.size.height = contentView.height + margin + frame = rect + + contentView.center = CGPoint(x: rect.width * 0.5, y: rect.height * 0.5) + if isMirror { + if let superView = superview, superView is EditorStickerView { + if superMirrorType == .none { + if mirrorType == .horizontal { + transform = transform.scaledBy(x: -1, y: 1) + } + }else { + if mirrorType == .none { + transform = transform.scaledBy(x: -1, y: 1) + } + } + }else { + if superMirrorType == .none { + if mirrorType == .horizontal { + if superAngle.truncatingRemainder(dividingBy: 180) != 0 { + transform = transform.scaledBy(x: 1, y: -1) + }else { + transform = transform.scaledBy(x: -1, y: 1) + } + } + }else { + if mirrorType == .horizontal { + transform = transform.scaledBy(x: -1, y: 1) + }else { + if superAngle.truncatingRemainder(dividingBy: 180) != 0 { + transform = transform.scaledBy(x: -1, y: -1) + }else { + transform = transform.scaledBy(x: 1, y: 1) + } + } + } + } + } + transform = transform.rotated(by: radian) + if isSelected { + if touching { + layer.borderWidth = 1 + layer.cornerRadius = 1 + }else { + layer.borderWidth = 1 / scale + layer.cornerRadius = 1 / scale + } + } + } + func update(item: EditorStickerItem) { + self.item = item + contentView.update(item: item) + update(size: item.frame.size, isMirror: true) + } + func update(size: CGSize, isMirror: Bool = false) { + let center = self.center + var frame = frame + frame.size = CGSize(width: size.width + itemMargin / scale, height: size.height + itemMargin / scale) + self.frame = frame + self.center = center + + contentView.transform = .identity + transform = .identity + + contentView.size = size + contentView.center = CGPoint(x: width * 0.5, y: height * 0.5) + update(pinchScale: pinchScale, rotation: radian, isMirror: isMirror) + } + func resetRotaion() { + update(pinchScale: pinchScale, rotation: radian, isMirror: true) + } + override func layoutSubviews() { + super.layoutSubviews() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/EditorStickerTextView.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/EditorStickerTextView.swift new file mode 100644 index 00000000..d83bae03 --- /dev/null +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/EditorStickerTextView.swift @@ -0,0 +1,518 @@ +// +// EditorStickerTextView.swift +// HXPHPicker +// +// Created by Slience on 2021/7/22. +// + +import UIKit + +class EditorStickerTextView: UIView { + let config: PhotoEditorConfiguration.TextConfig + lazy var textView: UITextView = { + let textView = UITextView() + textView.backgroundColor = .clear + textView.delegate = self + textView.layoutManager.delegate = self + textView.textContainerInset = UIEdgeInsets(top: 15, left: 15, bottom: 15, right: 15) + textView.contentInset = .zero + + textView.becomeFirstResponder() + return textView + }() + + var text: String { + textView.text + } + + lazy var textButton: UIButton = { + let button = UIButton(type: .custom) + button.setImage("hx_editor_photo_text_normal".image, for: .normal) + button.setImage("hx_editor_photo_text_selected".image, for: .selected) + button.addTarget(self, action: #selector(didTextButtonClick(button:)), for: .touchUpInside) + return button + }() + var currentSelectedIndex: Int = 0 { + didSet { + collectionView.scrollToItem(at: IndexPath(item: currentSelectedIndex, section: 0), at: .centeredHorizontally, animated: true) + } + } + var currentSelectedColor: UIColor = .clear + @objc func didTextButtonClick(button: UIButton) { + button.isSelected = !button.isSelected + showBackgroudColor = button.isSelected + useBgColor = currentSelectedColor + if button.isSelected { + if currentSelectedColor.isWhite { + changeTextColor(color: .black) + }else { + changeTextColor(color: .white) + } + }else { + changeTextColor(color: currentSelectedColor) + } + } + + lazy var flowLayout: UICollectionViewFlowLayout = { + let flowLayout = UICollectionViewFlowLayout() + flowLayout.scrollDirection = .horizontal + flowLayout.minimumInteritemSpacing = 5 + flowLayout.itemSize = CGSize(width: 37, height: 37) + return flowLayout + }() + + lazy var collectionView: UICollectionView = { + let collectionView = UICollectionView(frame: .zero, collectionViewLayout: flowLayout) + collectionView.backgroundColor = .clear + collectionView.dataSource = self + collectionView.delegate = self + collectionView.showsVerticalScrollIndicator = false + collectionView.showsHorizontalScrollIndicator = false + if #available(iOS 11.0, *) { + collectionView.contentInsetAdjustmentBehavior = .never + } + collectionView.register(PhotoEditorBrushColorViewCell.self, forCellWithReuseIdentifier: "EditorStickerTextViewCellID") + return collectionView + }() + + var typingAttributes: [NSAttributedString.Key : Any] = [:] + var stickerText: EditorStickerText? + + var showBackgroudColor: Bool = false + var useBgColor: UIColor = .clear + var textIsDelete: Bool = false + var textLayer: EditorStickerTextLayer? + var rectArray: [CGRect] = [] + var blankWidth: CGFloat = 22 + var layerRadius: CGFloat = 8 + var keyboardFrame: CGRect = .zero + var maxIndex: Int = 0 + + init(config: PhotoEditorConfiguration.TextConfig, + stickerText: EditorStickerText?) { + self.config = config + self.stickerText = stickerText + super.init(frame: .zero) + addSubview(textView) + addSubview(textButton) + addSubview(collectionView) + setupTextConfig() + setupStickerText() + setupTextColors() + addKeyboardNotificaition() + } + + func setupStickerText() { + if let text = stickerText { + showBackgroudColor = text.showBackgroud + textView.text = text.text + textButton.isSelected = text.showBackgroud + } + setupTextAttributes() + } + + func setupTextConfig() { + textView.tintColor = config.tintColor + textView.font = config.font + } + + func setupTextAttributes() { + let paragraphStyle = NSMutableParagraphStyle() + paragraphStyle.lineSpacing = 8 + let attributes = [NSAttributedString.Key.font: config.font, + NSAttributedString.Key.paragraphStyle: paragraphStyle] + typingAttributes = attributes + textView.attributedText = NSAttributedString(string: stickerText?.text ?? "", attributes: attributes) + } + + func setupTextColors() { + for (index, colorHex) in config.colors.enumerated() { + let color = colorHex.color + if let text = stickerText { + if color == text.textColor { + if text.showBackgroud { + if color.isWhite { + changeTextColor(color: .black) + }else { + changeTextColor(color: .white) + } + useBgColor = color + }else { + changeTextColor(color: color) + } + currentSelectedColor = color + currentSelectedIndex = index + collectionView.selectItem(at: IndexPath(item: currentSelectedIndex, section: 0), animated: true, scrollPosition: .centeredHorizontally) + } + }else { + if index == 0 { + changeTextColor(color: color) + currentSelectedColor = color + currentSelectedIndex = index + collectionView.selectItem(at: IndexPath(item: currentSelectedIndex, section: 0), animated: true, scrollPosition: .centeredHorizontally) + } + } + } + if textButton.isSelected { + drawTextBackgroudColor() + } + } + + func addKeyboardNotificaition() { + NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillAppearance), name: UIResponder.keyboardWillShowNotification, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillDismiss), name: UIResponder.keyboardWillHideNotification, object: nil) + } + + @objc func keyboardWillAppearance(notifi: Notification) { + guard let info = notifi.userInfo, + let duration = info[UIResponder.keyboardAnimationDurationUserInfoKey] as? TimeInterval, + let keyboardFrame = info[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect else { + return + } + self.keyboardFrame = keyboardFrame + UIView.animate(withDuration: duration) { + self.layoutSubviews() + } + } + + @objc func keyboardWillDismiss(notifi: Notification) { + guard let info = notifi.userInfo, + let duration = info[UIResponder.keyboardAnimationDurationUserInfoKey] as? TimeInterval else { + return + } + keyboardFrame = .zero + UIView.animate(withDuration: duration) { + self.layoutSubviews() + } + } + + override func layoutSubviews() { + super.layoutSubviews() + flowLayout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 12 + UIDevice.rightMargin) + textButton.frame = CGRect(x: UIDevice.leftMargin, y: height - (keyboardFrame.equalTo(.zero) ? UIDevice.bottomMargin + 50 : 50 + keyboardFrame.height), width: 50, height: 50) + collectionView.frame = CGRect(x: textButton.frame.maxX, y: textButton.y, width: width - textButton.width, height: 50) + textView.frame = CGRect(x: 10, y: 0, width: width - 20, height: textButton.y) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + deinit { + NotificationCenter.default.removeObserver(self) + } +} + +extension EditorStickerTextView { + + func createTextBackgroundLayer(path: CGPath) -> EditorStickerTextLayer { + let textLayer = EditorStickerTextLayer() + textLayer.path = path + textLayer.lineWidth = 0 + let color = showBackgroudColor ? useBgColor.cgColor : UIColor.clear.cgColor + textLayer.strokeColor = color + textLayer.fillColor = color + return textLayer + } + + func changeTextColor(color: UIColor) { + textView.textColor = color + typingAttributes[NSAttributedString.Key.foregroundColor] = color + textView.typingAttributes = typingAttributes + } + + func preProccess() { + maxIndex = 0 + if rectArray.count < 2 { + return + } + for (index, _) in rectArray.enumerated() { + if index > 0 { + maxIndex = index + processRect(index: index) + } + } + } + + func processRect(index: Int) { + if rectArray.count < 2 || index < 1 || index > maxIndex { + return + } + var last = rectArray[index - 1] + var cur = rectArray[index] + if cur.width <= blankWidth || last.width <= blankWidth { + return + } + var t1 = false + var t2 = false + if cur.minX > last.minX { + if cur.minX - last.minX < 2 * layerRadius { + cur = CGRect(x: last.minX, y: cur.minY, width: cur.width, height: cur.height) + t1 = true + } + }else if cur.minX < last.minX { + if last.minX - cur.minX < 2 * layerRadius { + cur = CGRect(x: last.minX, y: cur.minY, width: cur.width, height: cur.height) + t1 = true + } + } + if cur.maxX > last.maxX { + let poor = cur.maxX - last.maxX + if poor < 2 * layerRadius { + last = CGRect(x: last.minX, y: last.minY, width: cur.width, height: last.height) + t2 = true + } + } + if cur.maxX < last.maxX { + let poor = last.maxX - cur.maxX + if poor < 2 * layerRadius { + cur = CGRect(x: cur.minX, y: cur.minY, width: last.width, height: cur.height) + t1 = true + } + } + if t1 { + rectArray[index] = cur + processRect(index: index + 1) + } + if t2 { + rectArray[index - 1] = last + processRect(index: index - 1) + } + } + + func drawBackgroundPath(rects: [CGRect]) -> UIBezierPath { + self.rectArray = rects + preProccess() + let path = UIBezierPath() + var bezierPath: UIBezierPath? + var startPoint: CGPoint = .zero + for (index, rect) in rectArray.enumerated() { + if rect.width <= blankWidth { + continue + } + let loctionX = rect.minX + let loctionY = rect.minY + var half = false + if bezierPath == nil { + bezierPath = .init() + startPoint = CGPoint(x: loctionX, y: loctionY + layerRadius) + bezierPath?.move(to: startPoint) + bezierPath?.addArc(withCenter: CGPoint(x: loctionX + layerRadius, y: loctionY + layerRadius), radius: layerRadius, startAngle: CGFloat.pi, endAngle: 1.5 * CGFloat.pi, clockwise: true) + bezierPath?.addLine(to: CGPoint(x: rect.maxX - layerRadius, y: loctionY)) + bezierPath?.addArc(withCenter: CGPoint(x: rect.maxX - layerRadius, y: loctionY + layerRadius), radius: layerRadius, startAngle: 1.5 * CGFloat.pi, endAngle: 0, clockwise: true) + }else { + let lastRect = rectArray[index - 1] + var nextRect: CGRect? + if lastRect.maxX > rect.maxX { + if index + 1 < rectArray.count { + nextRect = rectArray[index + 1] + if nextRect!.width > blankWidth && nextRect!.maxX > rect.maxX{ + half = true + } + } + if half { + let radius = (nextRect!.minY - lastRect.maxY) / 2 + let centerY = nextRect!.minY - radius + bezierPath?.addArc(withCenter: CGPoint(x: rect.maxX + radius, y: centerY), radius: radius, startAngle: -CGFloat.pi * 0.5, endAngle: -CGFloat.pi * 1.5, clockwise: false) + }else { + bezierPath?.addArc(withCenter: CGPoint(x: rect.maxX + layerRadius, y: lastRect.maxY + layerRadius), radius: layerRadius, startAngle: -CGFloat.pi * 0.5, endAngle: -CGFloat.pi, clockwise: false) + } + }else if lastRect.maxX == rect.maxX { + bezierPath?.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY - layerRadius)) + }else { + bezierPath?.addArc(withCenter: CGPoint(x: rect.maxX - layerRadius, y: rect.minY + layerRadius), radius: layerRadius, startAngle: CGFloat.pi * 1.5, endAngle: 0, clockwise: true) + } + } + var hasNext = false + if index + 1 < rectArray.count { + let nextRect = rectArray[index + 1] + if nextRect.width > blankWidth { + if rect.maxX > nextRect.maxX { + let point = CGPoint(x: rect.maxX, y: rect.maxY - layerRadius) + if let currentPoint = bezierPath?.currentPoint, point.equalTo(currentPoint) { + bezierPath?.addArc(withCenter: CGPoint(x: rect.maxX - layerRadius, y: rect.maxY - layerRadius), radius: layerRadius, startAngle: 0, endAngle: CGFloat.pi * 0.5, clockwise: true) + }else { + bezierPath?.addLine(to: point) + bezierPath?.addArc(withCenter: CGPoint(x: rect.maxX - layerRadius, y: rect.maxY - layerRadius), radius: layerRadius, startAngle: 0, endAngle: CGFloat.pi * 0.5, clockwise: true) + } + bezierPath?.addLine(to: CGPoint(x: nextRect.maxX + layerRadius, y: rect.maxY)) + }else if rect.maxX == nextRect.maxX { + bezierPath?.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY)) + }else { + if !half { + let point = CGPoint(x: rect.maxX, y: nextRect.minY - layerRadius) + if let currentPoint = bezierPath?.currentPoint, point.equalTo(currentPoint) { + bezierPath?.addArc(withCenter: CGPoint(x: currentPoint.x + layerRadius, y: currentPoint.y), radius: layerRadius, startAngle: -CGFloat.pi, endAngle: -CGFloat.pi * 1.5, clockwise: false) + }else { + bezierPath?.addLine(to: point) + bezierPath?.addArc(withCenter: CGPoint(x: rect.maxX + layerRadius, y: nextRect.minY - layerRadius), radius: layerRadius, startAngle: -CGFloat.pi, endAngle: -CGFloat.pi * 1.5, clockwise: false) + } + } + bezierPath?.addLine(to: CGPoint(x: nextRect.maxX - layerRadius, y: nextRect.minY)) + } + hasNext = true + } + } + if !hasNext { + bezierPath?.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY - layerRadius)) + bezierPath?.addArc(withCenter: CGPoint(x: rect.maxX - layerRadius, y: rect.maxY - layerRadius), radius: layerRadius, startAngle: 0, endAngle: CGFloat.pi * 0.5, clockwise: true) + bezierPath?.addLine(to: CGPoint(x: rect.minX + layerRadius, y: rect.maxY)) + bezierPath?.addArc(withCenter: CGPoint(x: rect.minX + layerRadius, y: rect.maxY - layerRadius), radius: layerRadius, startAngle: CGFloat.pi * 0.5, endAngle: CGFloat.pi, clockwise: true) + bezierPath?.addLine(to: CGPoint(x: rect.minX, y: startPoint.y)) + if let bezierPath = bezierPath { + path.append(bezierPath) + } + bezierPath = nil + } + } + return path + } + + func drawTextBackgroudColor() { + if textView.text.isEmpty { + textLayer?.path = nil + return + } + var rectArray: [CGRect] = [] + let layoutManager = textView.layoutManager + let numberOfGlyphs = layoutManager.numberOfGlyphs + var currentGlyph = 0 + while currentGlyph < numberOfGlyphs { + var glyphRange = NSRange() + var usedRect = layoutManager.lineFragmentUsedRect(forGlyphAt: currentGlyph, effectiveRange: &glyphRange) + currentGlyph = NSMaxRange(glyphRange) + var nextIsEmpty = true + var lastLineIsEmpty = false + if currentGlyph < numberOfGlyphs { + let nextRange = layoutManager.range(ofNominallySpacedGlyphsContaining: currentGlyph) + var nextLocation = nextRange.location + var nextCount = nextLocation + nextRange.length + if nextCount > text.count { nextCount = text.count } + if nextLocation > nextCount { nextLocation = nextCount } + if nextLocation + nextCount > 0 { + let nextString = text[nextLocation.. CGFloat { + let newSize = textView.sizeThatFits(view.size) + return newSize.width + } + + func textImage() -> UIImage? { + textView.tintColor = .clear + for subView in textView.subviews { + if let textClass = NSClassFromString("_UITextContainerView"), subView.isKind(of: textClass) { + let size = CGSize(width: textMaximumWidth(view: subView), height: subView.height) + let image = subView.layer.convertedToImage(size: size) + subView.layer.contents = nil + return image + } + } + return nil + } +} + +extension EditorStickerTextView: UITextViewDelegate { + func textViewDidChange(_ textView: UITextView) { + textView.typingAttributes = typingAttributes + if textIsDelete { + drawTextBackgroudColor() + textIsDelete = false + } + if !textView.text.isEmpty { + if textView.text.count > config.maximumLimitTextLength && + config.maximumLimitTextLength > 0 { + let text = textView.text[.. Bool { + if text.isEmpty { + textIsDelete = true + } + return true + } +} + +extension EditorStickerTextView: NSLayoutManagerDelegate { + func layoutManager(_ layoutManager: NSLayoutManager, didCompleteLayoutFor textContainer: NSTextContainer?, atEnd layoutFinishedFlag: Bool) { + if layoutFinishedFlag { + drawTextBackgroudColor() + } + } +} + +extension EditorStickerTextView: UICollectionViewDataSource, UICollectionViewDelegate { + func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + config.colors.count + } + func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "EditorStickerTextViewCellID", for: indexPath) as! PhotoEditorBrushColorViewCell + cell.colorHex = config.colors[indexPath.item] + return cell + } + func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { + if currentSelectedIndex == indexPath.item { + return + } + collectionView.deselectItem(at: IndexPath(item: currentSelectedIndex, section: 0), animated: true) + let color = config.colors[indexPath.item].color + currentSelectedColor = color + currentSelectedIndex = indexPath.item + if showBackgroudColor { + useBgColor = color + if color.isWhite { + changeTextColor(color: .black) + }else { + changeTextColor(color: .white) + } + }else { + changeTextColor(color: color) + } + } +} + +class EditorStickerTextLayer: CAShapeLayer { +} diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/EditorStickerTrashView.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/EditorStickerTrashView.swift new file mode 100644 index 00000000..7f95453c --- /dev/null +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/EditorStickerTrashView.swift @@ -0,0 +1,76 @@ +// +// EditorStickerTrashView.swift +// HXPHPicker +// +// Created by Slience on 2021/7/22. +// + +import UIKit + +class EditorStickerTrashView: UIView { + lazy var bgView: UIVisualEffectView = { + let effect = UIBlurEffect(style: .dark) + let view = UIVisualEffectView(effect: effect) + return view + }() + + lazy var redView: UIView = { + let view = UIView() + view.isHidden = true + view.backgroundColor = "FF5653".color + return view + }() + + lazy var imageView: UIImageView = { + let imageView = UIImageView(image: "hx_editor_photo_trash_close".image) + imageView.size = imageView.image?.size ?? .zero + return imageView + }() + + lazy var textLb: UILabel = { + let textLb = UILabel() + textLb.text = "拖动到此处删除".localized + textLb.textColor = .white + textLb.textAlignment = .center + textLb.font = UIFont.systemFont(ofSize: 14) + textLb.adjustsFontSizeToFitWidth = true + return textLb + }() + + var inArea: Bool = false { + didSet { + bgView.isHidden = inArea + redView.isHidden = !inArea + imageView.image = inArea ? "hx_editor_photo_trash_open".image : "hx_editor_photo_trash_close".image + imageView.size = imageView.image?.size ?? .zero + imageView.centerX = width * 0.5 + textLb.text = inArea ? "松手即可删除".localized : "拖动到此处删除".localized + } + } + override init(frame: CGRect) { + super.init(frame: frame) + addSubview(bgView) + addSubview(redView) + addSubview(imageView) + addSubview(textLb) + layer.cornerRadius = 10 + layer.masksToBounds = true + } + + override func layoutSubviews() { + super.layoutSubviews() + bgView.frame = bounds + redView.frame = bounds + imageView.y = height * 0.5 - imageView.height + imageView.centerX = width * 0.5 + + textLb.y = height * 0.5 + 8 + textLb.x = 5 + textLb.width = width - 10 + textLb.height = 15 + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/EditorStickerView.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/EditorStickerView.swift new file mode 100644 index 00000000..c6d00828 --- /dev/null +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/EditorStickerView.swift @@ -0,0 +1,486 @@ +// +// EditorStickerView.swift +// HXPHPicker +// +// Created by Slience on 2021/7/20. +// + +import UIKit + +protocol EditorStickerViewDelegate: AnyObject { + func stickerView(touchBegan stickerView: EditorStickerView) + func stickerView(touchEnded stickerView: EditorStickerView) + func stickerView(_ stickerView: EditorStickerView, moveToCenter rect: CGRect) -> Bool + func stickerView(_ stickerView: EditorStickerView, minScale itemSize: CGSize) -> CGFloat + func stickerView(_ stickerView: EditorStickerView, maxScale itemSize: CGSize) -> CGFloat + func stickerView(_ stickerView: EditorStickerView, updateStickerText item: EditorStickerItem) +} + +class EditorStickerView: UIView { + weak var delegate: EditorStickerViewDelegate? + var scale: CGFloat = 1 { + didSet { + for subView in subviews { + if let itemView = subView as? EditorStickerItemView { + itemView.scale = scale + } + } + } + } + var touching: Bool = false + var enabled: Bool { + get { + isUserInteractionEnabled + } + set { + if !newValue { + deselectedSticker() + } + isUserInteractionEnabled = newValue + } + } + var count: Int { + subviews.count + } + + var selectView: EditorStickerItemView? { + willSet { + if let selectView = selectView, + let selectSuperView = selectView.superview, + selectSuperView == UIApplication.shared.keyWindow { + readdItemView(itemView: selectView) + } + } + } + lazy var trashView: EditorStickerTrashView = { + let view = EditorStickerTrashView(frame: CGRect(x: 0, y: 0, width: 180, height: 80)) + view.centerX = UIScreen.main.bounds.width * 0.5 + view.y = UIScreen.main.bounds.height + view.alpha = 0 + return view + }() + var trashViewDidRemove: Bool = false + var trashViewIsVisible: Bool = false + + override init(frame: CGRect) { + super.init(frame: frame) + clipsToBounds = true + isUserInteractionEnabled = true + } + override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { + let view = super.hitTest(point, with: event) + if touching { + return view + } + if let view = view, view is EditorStickerContentView { + if let selectView = selectView { + var rect = selectView.frame + rect = CGRect(x: rect.minX - 35, y: rect.minY - 35, width: rect.width + 70, height: rect.height + 70) + if rect.contains(point) { + return selectView.contentView + } + } + if let itemView = view.superview as? EditorStickerItemView { + if itemView != selectView { + deselectedSticker() + } + itemView.isSelected = true + bringSubviewToFront(itemView) + itemView.resetRotaion() + selectView = itemView + } + }else { + if let selectView = selectView { + var rect = selectView.frame + rect = CGRect(x: rect.minX - 35, y: rect.minY - 35, width: rect.width + 70, height: rect.height + 70) + if rect.contains(point) { + return selectView.contentView + } + } + deselectedSticker() + } + return view + } + + func update(item: EditorStickerItem) { + selectView?.update(item: item) + } + + var beforeItemArg: CGFloat = 0 + var currentItemArg: CGFloat = 0 + var addWindowCompletion: Bool = false + var angle: CGFloat = 0 + var currentItemDegrees: CGFloat = 0 + var hasImpactFeedback: Bool = false + var mirrorType: EditorImageResizerView.MirrorType = .none { + willSet { + for subView in subviews { + if let itemView = subView as? EditorStickerItemView { + if newValue == .none { + if mirrorType == .horizontal { + if itemView.mirrorType == .none { + itemView.mirrorType = .horizontal + }else { + itemView.mirrorType = .none + } + } + }else { + if mirrorType == .none { + if itemView.mirrorType == .none { + itemView.mirrorType = .horizontal + }else { + itemView.mirrorType = .none + } + } + } + itemView.superMirrorType = newValue + itemView.superAngle = angle + } + } + } + } + + @discardableResult + func add(sticker item: EditorStickerItem, isSelected: Bool) -> EditorStickerItemView { + selectView?.isSelected = false + let itemView = EditorStickerItemView.init(item: item, scale: scale) + itemView.delegate = self + var pScale: CGFloat + if item.text == nil { + let ratio: CGFloat = 0.5 + var width = self.width * self.scale + var height = self.height * self.scale + if width > UIScreen.main.bounds.width { + width = UIScreen.main.bounds.width + } + if height > UIScreen.main.bounds.height { + height = UIScreen.main.bounds.height + } + pScale = min(ratio * width / itemView.width, ratio * height / itemView.height) + }else { + pScale = min(min(self.width * self.scale - 40, itemView.width) / itemView.width, min(self.height * self.scale - 40, itemView.height) / itemView.height) + } + itemView.superAngle = angle + itemView.superMirrorType = mirrorType + var radians = angleRadians() + if mirrorType == .none { + radians = -radians + }else { + if angle.truncatingRemainder(dividingBy: 180) == 0 { + radians = -radians + } + } + itemView.isSelected = isSelected + if let keyWindow = UIApplication.shared.keyWindow { + itemView.center = convert(keyWindow.center, from: keyWindow) + } + itemView.firstTouch = isSelected + addSubview(itemView) + itemView.update(pinchScale: pScale / self.scale, rotation: radians, isMirror: true) + if isSelected { + selectView = itemView + } + return itemView + } + func deselectedSticker() { + selectView?.isSelected = false + selectView = nil + } + func removeAllSticker() { + deselectedSticker() + for subView in subviews { + if let itemView = subView as? EditorStickerItemView { + itemView.removeFromSuperview() + } + } + } + func resetItemView(itemView: EditorStickerItemView) { + if addWindowCompletion { + addWindowCompletion = false + readdItemView(itemView: itemView) + } + } + func readdItemView(itemView: EditorStickerItemView) { + let arg = itemView.radian - currentItemArg + if let rect = UIApplication.shared.keyWindow?.convert(itemView.frame, to: self) { + itemView.frame = rect + } + addSubview(itemView) + if mirrorType == .none { + itemView.update(pinchScale: itemView.pinchScale, rotation: itemView.radian - currentItemDegrees, isMirror: true) + }else { + itemView.update(pinchScale: itemView.pinchScale, rotation: beforeItemArg + arg, isMirror: true) + } + } + + func windowAdd(itemView : EditorStickerItemView) { + beforeItemArg = itemView.radian + addWindowCompletion = true + let radians = angleRadians() + currentItemDegrees = radians + let rect = convert(itemView.frame, to: UIApplication.shared.keyWindow) + itemView.frame = rect + UIApplication.shared.keyWindow?.addSubview(itemView) + if mirrorType == .none { + itemView.update(pinchScale: itemView.pinchScale, rotation: itemView.radian + radians, isMirror: true) + }else { + if itemView.mirrorType == .horizontal { + itemView.update(pinchScale: itemView.pinchScale, rotation: itemView.radian + radians, isMirror: true) + }else { + if angle.truncatingRemainder(dividingBy: 180) != 0 { + itemView.update(pinchScale: itemView.pinchScale, rotation: itemView.radian + radians, isMirror: true) + }else { + itemView.update(pinchScale: itemView.pinchScale, rotation: itemView.radian - radians, isMirror: true) + } + } + } + currentItemArg = itemView.radian + } + + func mirrorTransForm(radians: CGFloat) -> CGAffineTransform { + let transfrom = CGAffineTransform(scaleX: -1, y: 1) + switch radians { + case 0: + return transfrom + case CGFloat.pi / 2, -CGFloat.pi / 2: + return transfrom.rotated(by: CGFloat.pi / 2) + case CGFloat.pi, -CGFloat.pi: + return transfrom.rotated(by: CGFloat.pi) + case CGFloat.pi / 2 * 3, -CGFloat.pi / 2 * 3: + return transfrom.rotated(by: -CGFloat.pi / 2) + default: + return transfrom + } + } + + func angleRadians() -> CGFloat { + switch angle { + case 90: + return CGFloat.pi / 2 + case -90: + return -CGFloat.pi / 2 + case 180: + return CGFloat.pi + case -180: + return -CGFloat.pi + case 270: + return CGFloat.pi / 2 * 3 + case -270: + return -CGFloat.pi / 2 * 3 + default: + return 0 + } + } + + func showTrashView() { + trashViewDidRemove = false + trashViewIsVisible = true + UIView.animate(withDuration: 0.25) { + self.trashView.y = UIScreen.main.bounds.height - UIDevice.bottomMargin - 20 - self.trashView.height + self.trashView.alpha = 1 + } completion: { _ in + if !self.trashViewIsVisible { + self.trashView.y = UIScreen.main.bounds.height + self.trashView.alpha = 0 + } + } + } + + @objc func hideTrashView() { + trashViewIsVisible = false + trashViewDidRemove = true + UIView.animate(withDuration: 0.25) { + self.trashView.y = UIScreen.main.bounds.height + self.trashView.alpha = 0 + self.selectView?.alpha = 1 + } completion: { _ in + if !self.trashViewIsVisible { + self.trashView.removeFromSuperview() + self.trashView.inArea = false + }else { + self.trashView.y = UIScreen.main.bounds.height - UIDevice.bottomMargin - 20 - self.trashView.height + self.trashView.alpha = 1 + } + } + + } + + func stickerData() -> EditorStickerData? { + var datas: [EditorStickerItemData] = [] + for subView in subviews { + if let itemView = subView as? EditorStickerItemView { + let centerScale = CGPoint(x: itemView.centerX / width, y: itemView.centerY / height) + let itemData = EditorStickerItemData(item: itemView.item, pinchScale: itemView.pinchScale, rotation: itemView.radian, centerScale: centerScale, mirrorType: itemView.mirrorType, superMirrorType: itemView.superMirrorType, superAngel: itemView.superAngle) + datas.append(itemData) + } + } + if datas.isEmpty { + return nil + } + let stickerData = EditorStickerData(items: datas, mirrorType: mirrorType, angel: angle) + return stickerData + } + func setStickerData(stickerData: EditorStickerData, viewSize: CGSize) { + mirrorType = stickerData.mirrorType + angle = stickerData.angel + for itemData in stickerData.items { + let itemView = add(sticker: itemData.item, isSelected: false) + itemView.mirrorType = itemData.mirrorType + itemView.superMirrorType = itemData.superMirrorType + itemView.superAngle = itemData.superAngel + itemView.update(pinchScale: itemData.pinchScale, rotation: itemData.rotation, isInitialize: true, isMirror: true) + itemView.center = CGPoint(x: viewSize.width * itemData.centerScale.x, y: viewSize.height * itemData.centerScale.y) + } + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} + +extension EditorStickerView: EditorStickerItemViewDelegate { + func stickerItemView(_ itemView: EditorStickerItemView, updateStickerText item: EditorStickerItem) { + delegate?.stickerView(self, updateStickerText: item) + } + + func stickerItemView(shouldTouchBegan itemView: EditorStickerItemView) -> Bool { + if let selectView = selectView, itemView != selectView { + return false + } + return true + } + + func stickerItemView(didTouchBegan itemView: EditorStickerItemView) { + touching = true + delegate?.stickerView(touchBegan: self) + if let selectView = selectView, selectView != itemView { + selectView.isSelected = false + self.selectView = itemView + }else if selectView == nil { + selectView = itemView + } + if !addWindowCompletion { + windowAdd(itemView: itemView) + } + if !trashViewIsVisible { + UIApplication.shared.keyWindow?.addSubview(trashView) + showTrashView() + } + } + + func stickerItemView(touchEnded itemView: EditorStickerItemView) { + delegate?.stickerView(touchEnded: self) + if let selectView = selectView, selectView != itemView { + selectView.isSelected = false + self.selectView = itemView + }else if selectView == nil { + selectView = itemView + } + resetItemView(itemView: itemView) + if trashViewIsVisible { + hideTrashView() + } + touching = false + } + func stickerItemView(_ itemView: EditorStickerItemView, tapGestureRecognizerNotInScope point: CGPoint) { + if let selectView = selectView, itemView == selectView { + self.selectView = nil + let cPoint = itemView.convert(point, to: self) + for subView in subviews { + if let itemView = subView as? EditorStickerItemView { + if itemView.frame.contains(cPoint) { + itemView.isSelected = true + self.selectView = itemView + bringSubviewToFront(itemView) + itemView.resetRotaion() + return + } + } + } + } + } + + func stickerItemView(_ itemView: EditorStickerItemView, panGestureRecognizerChanged panGR: UIPanGestureRecognizer) { + let point = panGR.location(in: UIApplication.shared.keyWindow) + if trashView.frame.contains(point) && !trashViewDidRemove { + trashView.inArea = true + if !hasImpactFeedback { + UIView.animate(withDuration: 0.25) { + self.selectView?.alpha = 0.4 + } + perform(#selector(hideTrashView), with: nil, afterDelay: 1.2) + let shake = UIImpactFeedbackGenerator(style: .medium) + shake.prepare() + shake.impactOccurred() + hasImpactFeedback = true + } + }else { + UIView.animate(withDuration: 0.2) { + self.selectView?.alpha = 1 + } + UIView.cancelPreviousPerformRequests(withTarget: self) + hasImpactFeedback = false + trashView.inArea = false + } + } + func stickerItemView(_ itemView: EditorStickerItemView, moveToCenter rect: CGRect) -> Bool { + if let moveToCenter = delegate?.stickerView(self, moveToCenter: rect) { + return moveToCenter + } + return false + } + func stickerItemView(panGestureRecognizerEnded itemView: EditorStickerItemView) -> Bool { + let inArea = trashView.inArea + if inArea { + addWindowCompletion = false + trashView.inArea = false + UIView.animate(withDuration: 0.25) { + itemView.alpha = 0 + } completion: { _ in + itemView.removeFromSuperview() + } + selectView = nil + }else { + if let selectView = selectView, selectView != itemView { + selectView.isSelected = false + self.selectView = itemView + }else if selectView == nil { + selectView = itemView + } + resetItemView(itemView: itemView) + } + if addWindowCompletion { + hideTrashView() + } + return inArea + } + func stickerItemView(_ itemView: EditorStickerItemView, maxScale itemSize: CGSize) -> CGFloat { + if let maxScale = delegate?.stickerView(self, maxScale: itemSize) { + return maxScale + } + return 5 + } + + func stickerItemView(_ itemView: EditorStickerItemView, minScale itemSize: CGSize) -> CGFloat { + if let minScale = delegate?.stickerView(self, minScale: itemSize) { + return minScale + } + return 0.2 + } +} + +struct EditorStickerData: Codable { + let items: [EditorStickerItemData] + let mirrorType: EditorImageResizerView.MirrorType + let angel: CGFloat +} + +struct EditorStickerItemData: Codable { + let item: EditorStickerItem + let pinchScale: CGFloat + let rotation: CGFloat + let centerScale: CGPoint + let mirrorType: EditorImageResizerView.MirrorType + let superMirrorType: EditorImageResizerView.MirrorType + let superAngel: CGFloat +} diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/EditorToolView.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/EditorToolView.swift index 36e2e7db..225fee10 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/EditorToolView.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/EditorToolView.swift @@ -12,6 +12,12 @@ protocol EditorToolViewDelegate: NSObjectProtocol { func toolView(didFinishButtonClick toolView: EditorToolView) } +class EditorToolScrollView: UICollectionView { + override func touchesShouldCancel(in view: UIView) -> Bool { + true + } +} + class EditorToolView: UIView { weak var delegate: EditorToolViewDelegate? var config: EditorToolViewConfiguration @@ -41,8 +47,9 @@ class EditorToolView: UIView { return flowLayout }() - lazy var collectionView: UICollectionView = { - let collectionView = UICollectionView.init(frame: CGRect(x: 0, y: 0, width: 0, height: 50), collectionViewLayout: flowLayout) + lazy var collectionView: EditorToolScrollView = { + let collectionView = EditorToolScrollView.init(frame: CGRect(x: 0, y: 0, width: 0, height: 50), collectionViewLayout: flowLayout) + collectionView.delaysContentTouches = false collectionView.backgroundColor = .clear collectionView.dataSource = self collectionView.delegate = self @@ -130,7 +137,7 @@ class EditorToolView: UIView { } } -extension EditorToolView: UICollectionViewDataSource, UICollectionViewDelegate { +extension EditorToolView: UICollectionViewDataSource, UICollectionViewDelegate, EditorToolViewCellDelegate { func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { config.toolOptions.count } @@ -138,6 +145,7 @@ extension EditorToolView: UICollectionViewDataSource, UICollectionViewDelegate { func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "EditorToolViewCellID", for: indexPath) as! EditorToolViewCell let model = config.toolOptions[indexPath.item] + cell.delegate = self cell.boxColor = config.musicSelectedColor if model.type == .music { cell.showBox = musicCellShowBox @@ -146,11 +154,27 @@ extension EditorToolView: UICollectionViewDataSource, UICollectionViewDelegate { } cell.selectedColor = config.toolSelectedColor cell.model = model + if model.type == .graffiti || model.type == .mosaic { + if let selectedIndexPath = currentSelectedIndexPath, + selectedIndexPath.item == indexPath.item { + cell.isSelectedImageView = true + }else { + cell.isSelectedImageView = false + } + }else { + cell.isSelectedImageView = false + } return cell } func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { - collectionView.deselectItem(at: indexPath, animated: true) + collectionView.deselectItem(at: indexPath, animated: false) + } + + func toolViewCell(didClick cell: EditorToolViewCell) { + guard let indexPath = collectionView.indexPath(for: cell) else { + return + } let option = config.toolOptions[indexPath.item] if option.type == .graffiti || option.type == .mosaic { if let selectedIndexPath = currentSelectedIndexPath, @@ -164,5 +188,4 @@ extension EditorToolView: UICollectionViewDataSource, UICollectionViewDelegate { } delegate?.toolView(self, didSelectItemAt: option) } - } diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/EditorToolViewCell.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/EditorToolViewCell.swift index d93aab33..b3134b79 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/EditorToolViewCell.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/EditorToolViewCell.swift @@ -7,7 +7,12 @@ import UIKit +protocol EditorToolViewCellDelegate: AnyObject { + func toolViewCell(didClick cell: EditorToolViewCell) +} + class EditorToolViewCell: UICollectionViewCell { + weak var delegate: EditorToolViewCellDelegate? lazy var boxView: SelectBoxView = { let view = SelectBoxView.init(frame: CGRect(x: 0, y: 0, width: 12, height: 12)) view.isHidden = true @@ -19,11 +24,17 @@ class EditorToolViewCell: UICollectionViewCell { return view }() - lazy var imageView: UIImageView = { - let imageView = UIImageView.init() - return imageView + lazy var button: UIButton = { + let button = UIButton(type: .system) + button.addTarget(self, action: #selector(didButtonClick), for: .touchUpInside) + button.tintColor = .white + return button }() + @objc func didButtonClick() { + delegate?.toolViewCell(didClick: self) + } + var showBox: Bool = false { didSet { boxView.isSelected = showBox @@ -39,22 +50,21 @@ class EditorToolViewCell: UICollectionViewCell { var model: EditorToolOptions! { didSet { - imageView.image = UIImage.image(for: model.imageName)?.withRenderingMode(.alwaysTemplate) - imageView.tintColor = .white + let image = UIImage.image(for: model.imageName)?.withRenderingMode(.alwaysTemplate) + button.setImage(image, for: .normal) } } - var selectedColor: UIColor? var isSelectedImageView: Bool = false { didSet { - imageView.tintColor = isSelectedImageView ? selectedColor : .white + button.tintColor = isSelectedImageView ? selectedColor : .white } } override init(frame: CGRect) { super.init(frame: frame) - addSubview(imageView) - addSubview(boxView) + contentView.addSubview(button) + contentView.addSubview(boxView) } required init?(coder: NSCoder) { @@ -63,10 +73,10 @@ class EditorToolViewCell: UICollectionViewCell { override func layoutSubviews() { super.layoutSubviews() - imageView.size = imageView.image?.size ?? .zero - imageView.center = CGPoint(x: width * 0.5, y: height * 0.5) - - boxView.x = imageView.frame.maxX - boxView.width * 0.5 - boxView.y = imageView.frame.maxY - boxView.height + 3 + button.frame = bounds + if let image = button.image(for: .normal) { + boxView.x = width * 0.5 + image.width * 0.5 - boxView.width * 0.5 + boxView.y = height * 0.5 + image.height * 0.5 - boxView.height + 3 + } } } diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/Photo/EditorImageResizerView.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/Photo/EditorImageResizerView.swift index d3d17a7b..f2dc1229 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/Photo/EditorImageResizerView.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/Photo/EditorImageResizerView.swift @@ -20,6 +20,18 @@ protocol EditorImageResizerViewDelegate: AnyObject { func imageResizerView(didEndZooming imageResizerView: EditorImageResizerView) } +class PhotoEditorContainerView: UIView { + override func point(inside point: CGPoint, with event: UIEvent?) -> Bool { + true + } +} + +class PhotoEditorScrollView: UIScrollView { + override func point(inside point: CGPoint, with event: UIEvent?) -> Bool { + true + } +} + class EditorImageResizerView: UIView { enum ImageOrientation { @@ -32,11 +44,12 @@ class EditorImageResizerView: UIView { deinit { // print("deinit", self) } + var exportScale: CGFloat = UIScreen.main.scale /// 裁剪配置 var cropConfig: PhotoCroppingConfiguration weak var delegate: EditorImageResizerViewDelegate? - lazy var containerView: UIView = { - let containerView = UIView.init() + lazy var containerView: PhotoEditorContainerView = { + let containerView = PhotoEditorContainerView.init() containerView.addSubview(scrollView) updateScrollView() containerView.addSubview(maskBgView) @@ -45,8 +58,8 @@ class EditorImageResizerView: UIView { return containerView }() - lazy var scrollView: UIScrollView = { - let scrollView = UIScrollView.init(frame: .zero) + lazy var scrollView: PhotoEditorScrollView = { + let scrollView = PhotoEditorScrollView.init(frame: .zero) scrollView.delegate = self scrollView.minimumZoomScale = 1.0 scrollView.maximumZoomScale = 20.0 @@ -64,6 +77,41 @@ class EditorImageResizerView: UIView { let mosaicConfig: PhotoEditorConfiguration.MosaicConfig lazy var imageView: PhotoEditorContentView = { let imageView = PhotoEditorContentView.init(mosaicConfig: mosaicConfig) + imageView.itemViewMoveToCenter = { [weak self] rect -> Bool in + guard let self = self, let view = self.viewController()?.view else { return false } + var newRect = self.convert(self.bounds, to: view) + if newRect.width > view.width { + newRect.origin.x = 0 + newRect.size.width = view.width + } + if newRect.height > view.height { + newRect.origin.y = 0 + newRect.size.height = view.height + } + let marginWidth = rect.width - 20 + let marginHeight = rect.height - 20 + if CGRect(x: newRect.minX - marginWidth, y: newRect.minY - marginHeight, width: newRect.width + marginWidth * 2, height: newRect.height + marginHeight * 2).contains(rect) { + return false + } + return true + } + imageView.stickerMinScale = { [weak self] itemSize -> CGFloat in + min(35 / itemSize.width, 35 / itemSize.height) + } + imageView.stickerMaxScale = { [weak self] itemSize -> CGFloat in + guard let self = self, let view = self.viewController()?.view else { return 0 } + var newRect = self.convert(self.bounds, to: view) + if newRect.width > view.width { + newRect.origin.x = 0 + newRect.size.width = view.width + } + if newRect.height > view.height { + newRect.origin.y = 0 + newRect.size.height = view.height + } + let maxScale = min(itemSize.width, itemSize.height) + return max((newRect.width + 35) / maxScale, (newRect.height + 35) / maxScale) + } return imageView }() @@ -93,7 +141,11 @@ class EditorImageResizerView: UIView { /// 当前状态 var state: PhotoEditorView.State = .normal /// 当前镜像类型 - var mirrorType: MirrorType = .none + var mirrorType: MirrorType = .none { + didSet { + imageView.stickerView.mirrorType = mirrorType + } + } /// imageview原始宽高 var baseImageSize: CGSize = .zero /// 图片宽高比例 @@ -128,7 +180,11 @@ class EditorImageResizerView: UIView { var currentAspectRatio: CGSize = .zero /// 是否固定比例 var isFixedRatio: Bool = false - var currentAngle: CGFloat = 0 + var currentAngle: CGFloat = 0 { + didSet { + imageView.stickerView.angle = currentAngle + } + } var rotating: Bool = false var mirroring: Bool = false @@ -137,6 +193,10 @@ class EditorImageResizerView: UIView { get { imageView.drawView.enabled } set { imageView.drawView.enabled = newValue } } + var stickerEnabled: Bool { + get { imageView.stickerView.enabled } + set { imageView.stickerView.enabled = newValue } + } var mosaicEnabled: Bool { get { imageView.mosaicView.enabled } set { imageView.mosaicView.enabled = newValue } @@ -177,12 +237,14 @@ class EditorImageResizerView: UIView { mirrorType: oldMirrorType) } let mosaicData = imageView.mosaicView.getMosaicData() + let stickerData = imageView.stickerView.stickerData() let editedData = PhotoEditData.init(isPortrait: UIDevice.isPortrait, cropData: cropData, brushData: brushData, filter: filter, filterValue: filterValue, - mosaicData: mosaicData) + mosaicData: mosaicData, + stickerData: stickerData) return editedData } func setCropData(cropData: PhotoEditCropData) { @@ -203,6 +265,14 @@ class EditorImageResizerView: UIView { let offsetY = baseImageSize.height * cropData.offsetScale.y * oldZoomScale - scrollViewContentInset.top oldContentOffset = CGPoint(x: offsetX, y: offsetY) oldMaskRect = rect + + imageView.stickerView.angle = oldAngle + imageView.stickerView.mirrorType = oldMirrorType + } + func setStickerData(stickerData: EditorStickerData?) { + if let stickerData = stickerData { + imageView.stickerView.setStickerData(stickerData: stickerData, viewSize: imageView.bounds.size) + } } func setBrushData(brushData: [PhotoEditorBrushData]) { if !brushData.isEmpty { @@ -865,19 +935,35 @@ class EditorImageResizerView: UIView { self.imageView.drawView.layer.contents = nil } } + DispatchQueue.main.sync { + if self.imageView.stickerView.count > 0 { + if let image = self.imageView.stickerView.layer.convertedToImage() { + otherImages.append(image) + } + self.imageView.stickerView.layer.contents = nil + } + } var otherImage: UIImage? = nil if !otherImages.isEmpty { otherImage = UIImage.merge(images: otherImages)?.scaleToFillSize(size: inputImage.size) } + var crop_Rect = cropRect + if exportScale != inputImage.scale && otherImage != nil { + let scale = exportScale / inputImage.scale + crop_Rect.origin.x *= scale + crop_Rect.origin.y *= scale + crop_Rect.size.width *= scale + crop_Rect.size.height *= scale + } if let option = inputImage.animateImageFrame() { var images = [UIImage]() var delays = [Double]() for (index, image) in option.0.enumerated() { var currentImage = image - if let otherImage = otherImage, let newImage = image.merge(images: [otherImage], scale: image.scale) { + if let otherImage = otherImage, let newImage = image.merge(images: [otherImage], scale: exportScale) { currentImage = newImage } - if let newImage = cropImage(currentImage, toRect: cropRect, viewWidth: viewWidth, viewHeight: viewHeight) { + if let newImage = cropImage(currentImage, toRect: crop_Rect, viewWidth: viewWidth, viewHeight: viewHeight) { images.append(newImage) delays.append(option.1[index]) } @@ -887,10 +973,11 @@ class EditorImageResizerView: UIView { } return nil } - if let otherImage = otherImage, let image = inputImage.merge(images: [otherImage], scale: inputImage.scale) { + if let otherImage = otherImage, let image = inputImage.merge(images: [otherImage], scale: exportScale) { inputImage = image } - if let image = cropImage(inputImage, toRect: cropRect, viewWidth: viewWidth, viewHeight: viewHeight), let imageURL = PhotoTools.write(image: image) { + if let image = cropImage(inputImage, toRect: crop_Rect, viewWidth: viewWidth, viewHeight: viewHeight), + let imageURL = PhotoTools.write(image: image) { if let thumbnailImage = image.scaleImage(toScale: 0.6) { return (thumbnailImage, imageURL, .normal) } diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/Photo/PhotoEditorBrushColorView.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/Photo/PhotoEditorBrushColorView.swift index 38756089..4dce8030 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/Photo/PhotoEditorBrushColorView.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/Photo/PhotoEditorBrushColorView.swift @@ -128,7 +128,7 @@ class PhotoEditorBrushColorViewCell: UICollectionViewCell { didSet { UIView.animate(withDuration: 0.2) { self.colorBgView.transform = self.isSelected ? .init(scaleX: 1.2, y: 1.2) : .identity - self.colorView.transform = self.isSelected ? .init(scaleX: 1.1, y: 1.1) : .identity + self.colorView.transform = self.isSelected ? .init(scaleX: 1.25, y: 1.25) : .identity } } } diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/Photo/PhotoEditorContentView.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/Photo/PhotoEditorContentView.swift index d2996555..85027240 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/Photo/PhotoEditorContentView.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/Photo/PhotoEditorContentView.swift @@ -13,12 +13,19 @@ import Kingfisher protocol PhotoEditorContentViewDelegate: AnyObject { func contentView(drawViewBeganDraw contentView: PhotoEditorContentView) func contentView(drawViewEndDraw contentView: PhotoEditorContentView) + func contentView(_ contentView: PhotoEditorContentView, updateStickerText item: EditorStickerItem) } class PhotoEditorContentView: UIView { weak var delegate: PhotoEditorContentViewDelegate? + var itemViewMoveToCenter: ((CGRect) -> Bool)? + + var stickerMinScale: ((CGSize) -> CGFloat)? + + var stickerMaxScale: ((CGSize) -> CGFloat)? + lazy var imageView: UIImageView = { var imageView: UIImageView #if canImport(Kingfisher) @@ -35,6 +42,7 @@ class PhotoEditorContentView: UIView { didSet { drawView.scale = zoomScale mosaicView.scale = zoomScale + stickerView.scale = zoomScale } } lazy var drawView: PhotoEditorDrawView = { @@ -47,6 +55,11 @@ class PhotoEditorContentView: UIView { view.delegate = self return view }() + lazy var stickerView: EditorStickerView = { + let view = EditorStickerView(frame: .zero) + view.delegate = self + return view + }() let mosaicConfig: PhotoEditorConfiguration.MosaicConfig @@ -56,6 +69,7 @@ class PhotoEditorContentView: UIView { addSubview(imageView) addSubview(mosaicView) addSubview(drawView) + addSubview(stickerView) } func setMosaicOriginalImage(_ image: UIImage?) { mosaicView.originalImage = image @@ -74,6 +88,7 @@ class PhotoEditorContentView: UIView { imageView.frame = bounds drawView.frame = bounds mosaicView.frame = bounds + stickerView.frame = bounds } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") @@ -88,6 +103,38 @@ extension PhotoEditorContentView: PhotoEditorDrawViewDelegate { delegate?.contentView(drawViewEndDraw: self) } } +extension PhotoEditorContentView: EditorStickerViewDelegate { + func stickerView(_ stickerView: EditorStickerView, updateStickerText item: EditorStickerItem) { + delegate?.contentView(self, updateStickerText: item) + } + + func stickerView(touchBegan stickerView: EditorStickerView) { + delegate?.contentView(drawViewBeganDraw: self) + } + func stickerView(touchEnded stickerView: EditorStickerView) { + delegate?.contentView(drawViewEndDraw: self) + } + func stickerView(_ stickerView: EditorStickerView, moveToCenter rect: CGRect) -> Bool { + if let moveToCenter = itemViewMoveToCenter?(rect) { + return moveToCenter + } + return false + } + + func stickerView(_ stickerView: EditorStickerView, minScale itemSize: CGSize) -> CGFloat { + if let minScale = stickerMinScale?(itemSize) { + return minScale + } + return 0.2 + } + + func stickerView(_ stickerView: EditorStickerView, maxScale itemSize: CGSize) -> CGFloat { + if let maxScale = stickerMaxScale?(itemSize) { + return maxScale + } + return 5 + } +} extension PhotoEditorContentView: PhotoEditorMosaicViewDelegate { func mosaicView(_ mosaicView: PhotoEditorMosaicView, splashColor atPoint: CGPoint) -> UIColor? { imageView.color(for: atPoint) diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/Photo/PhotoEditorDrawView.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/Photo/PhotoEditorDrawView.swift index 82aa4f8c..701cabbd 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/Photo/PhotoEditorDrawView.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/Photo/PhotoEditorDrawView.swift @@ -164,6 +164,36 @@ struct PhotoEditorBrushData { let lineWidth: CGFloat } +extension PhotoEditorBrushData: Codable { + enum CodingKeys: String, CodingKey { + case color + case points + case lineWidth + } + + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + let colorData = try container.decode(Data.self, forKey: .color) + color = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(colorData) as! UIColor + points = try container.decode([CGPoint].self, forKey: .points) + lineWidth = try container.decode(CGFloat.self, forKey: .lineWidth) + } + + func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + if #available(iOS 11.0, *) { + let colorData = try NSKeyedArchiver.archivedData(withRootObject: color, requiringSecureCoding: false) + try container.encode(colorData, forKey: .color) + } else { + // Fallback on earlier versions + let colorData = NSKeyedArchiver.archivedData(withRootObject: color) + try container.encode(colorData, forKey: .color) + } + try container.encode(points, forKey: .points) + try container.encode(lineWidth, forKey: .lineWidth) + } +} + class PhotoEditorBrushPath: UIBezierPath { var color: UIColor? var points: [CGPoint] = [] diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/Photo/PhotoEditorFilterView.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/Photo/PhotoEditorFilterView.swift index b19691af..555782c2 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/Photo/PhotoEditorFilterView.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/Photo/PhotoEditorFilterView.swift @@ -174,6 +174,8 @@ extension PhotoEditorFilterView: UICollectionViewDataSource, UICollectionViewDel currentFilter.isSelected = false if let currentCell = collectionView.cellForItem(at: IndexPath(item: currentSelectedIndex, section: 0)) as? PhotoEditorFilterViewCell { currentCell.updateSelectedView(true) + }else { + collectionView.reloadItems(at: [IndexPath(item: currentSelectedIndex, section: 0)]) } if let cell = collectionView.cellForItem(at: indexPath) as? PhotoEditorFilterViewCell { cell.filter.isSelected = true @@ -196,7 +198,10 @@ extension PhotoEditorFilterView: PhotoEditorFilterViewCellDelegate { if let image = image, let index = filters.firstIndex(of: cell.filter) { let filterInfo = filterConfig.infos[index - 1] - return filterInfo.filterHandler(image, cell.imageView.image, filterInfo.defaultValue, .touchUpInside) + return filterInfo.filterHandler(image, + cell.imageView.image, + filterInfo.defaultValue, + .touchUpInside) } return nil } diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/Photo/PhotoEditorMosaicView.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/Photo/PhotoEditorMosaicView.swift index b5d90241..baeb9c28 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/Photo/PhotoEditorMosaicView.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/Photo/PhotoEditorMosaicView.swift @@ -16,7 +16,7 @@ protocol PhotoEditorMosaicViewDelegate: AnyObject { } class PhotoEditorMosaicView: UIView, UIGestureRecognizerDelegate { - enum MosaicType { + enum MosaicType: Int, Codable { case mosaic case smear } @@ -389,3 +389,38 @@ struct PhotoEditorMosaicData { let lineWidth: CGFloat let angles: [CGFloat] } +extension PhotoEditorMosaicData: Codable { + enum CodingKeys: String, CodingKey { + case type + case points + case colors + case lineWidth + case angles + } + + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + type = try container.decode(PhotoEditorMosaicView.MosaicType.self, forKey: .type) + points = try container.decode([CGPoint].self, forKey: .points) + let colorDatas = try container.decode(Data.self, forKey: .colors) + colors = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(colorDatas) as! [UIColor] + lineWidth = try container.decode(CGFloat.self, forKey: .lineWidth) + angles = try container.decode([CGFloat].self, forKey: .angles) + } + + func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(type, forKey: .type) + try container.encode(points, forKey: .points) + if #available(iOS 11.0, *) { + let colorDatas = try NSKeyedArchiver.archivedData(withRootObject: colors, requiringSecureCoding: false) + try container.encode(colorDatas, forKey: .colors) + } else { + // Fallback on earlier versions + let colorDatas = NSKeyedArchiver.archivedData(withRootObject: colors) + try container.encode(colorDatas, forKey: .colors) + } + try container.encode(lineWidth, forKey: .lineWidth) + try container.encode(angles, forKey: .angles) + } +} diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/Photo/PhotoEditorView.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/Photo/PhotoEditorView.swift index 9bbd76a0..59a63971 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/Photo/PhotoEditorView.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/Photo/PhotoEditorView.swift @@ -17,13 +17,15 @@ protocol PhotoEditorViewDelegate: AnyObject { func editorView(drawViewBeganDraw editorView: PhotoEditorView) func editorView(drawViewEndDraw editorView: PhotoEditorView) + func editorView(_ editorView: PhotoEditorView, updateStickerText item: EditorStickerItem) } class PhotoEditorView: UIScrollView, UIGestureRecognizerDelegate { weak var editorDelegate: PhotoEditorViewDelegate? lazy var imageResizerView: EditorImageResizerView = { - let imageResizerView = EditorImageResizerView.init(cropConfig: config.cropConfig, - mosaicConfig: config.mosaicConfig) + let imageResizerView = EditorImageResizerView.init(cropConfig: config.cropping, + mosaicConfig: config.mosaic) + imageResizerView.exportScale = config.scale imageResizerView.imageView.drawView.lineColor = config.brushColors[config.defaultBrushColorIndex].color imageResizerView.imageView.drawView.lineWidth = config.brushLineWidth imageResizerView.delegate = self @@ -35,7 +37,6 @@ class PhotoEditorView: UIScrollView, UIGestureRecognizerDelegate { didSet { imageResizerView.zoomScale = zoomScale } } - /// 裁剪配置 var config: PhotoEditorConfiguration var state: State = .normal @@ -45,10 +46,21 @@ class PhotoEditorView: UIScrollView, UIGestureRecognizerDelegate { var image: UIImage? { imageResizerView.imageView.image } + var isEnabled: Bool = false { + didSet { + imageResizerView.isUserInteractionEnabled = isEnabled + isScrollEnabled = isEnabled + } + } + var drawEnabled: Bool { get { imageResizerView.drawEnabled } set { imageResizerView.drawEnabled = newValue } } + var stickerEnabled: Bool { + get { imageResizerView.stickerEnabled } + set { imageResizerView.stickerEnabled = newValue } + } var mosaicEnabled: Bool { get { imageResizerView.mosaicEnabled } set { imageResizerView.mosaicEnabled = newValue } @@ -61,6 +73,7 @@ class PhotoEditorView: UIScrollView, UIGestureRecognizerDelegate { } var canUndoDraw: Bool { imageResizerView.imageView.drawView.canUndo } var canUndoMosaic: Bool { imageResizerView.imageView.mosaicView.canUndo } + var hasSticker: Bool { imageResizerView.imageView.stickerView.count > 0 } var hasFilter: Bool { imageResizerView.filter != nil } init(config: PhotoEditorConfiguration) { @@ -126,8 +139,9 @@ class PhotoEditorView: UIScrollView, UIGestureRecognizerDelegate { } imageResizerView.setBrushData(brushData: editedData.brushData) imageResizerView.setMosaicData(mosaicData: editedData.mosaicData) + imageResizerView.setStickerData(stickerData: editedData.stickerData) updateImageViewFrame() - if config.cropConfig.isRoundCrop { + if config.cropping.isRoundCrop { imageResizerView.layer.cornerRadius = cropSize.width * 0.5 } } @@ -197,7 +211,7 @@ class PhotoEditorView: UIScrollView, UIGestureRecognizerDelegate { guard let self = self else { return } self.imageResizerView.zoomScale = self.zoomScale self.editorDelegate?.editorView(didDisappearCrop: self) - if self.config.cropConfig.isRoundCrop { + if self.config.cropping.isRoundCrop { self.imageResizerView.layer.cornerRadius = self.cropSize.width * 0.5 } completion?() @@ -238,6 +252,15 @@ class PhotoEditorView: UIScrollView, UIGestureRecognizerDelegate { func mirrorHorizontally(animated: Bool) { imageResizerView.mirrorHorizontally(animated: animated) } + func addSticker(item: EditorStickerItem, isSelected: Bool) { + imageResizerView.imageView.stickerView.add(sticker: item, isSelected: isSelected) + } + func updateSticker(item: EditorStickerItem) { + imageResizerView.imageView.stickerView.update(item: item) + } + func deselectedSticker() { + imageResizerView.imageView.stickerView.deselectedSticker() + } func orientationDidChange() { cropSize = .zero @@ -257,6 +280,9 @@ class PhotoEditorView: UIScrollView, UIGestureRecognizerDelegate { func undoAllMosaic() { imageResizerView.imageView.mosaicView.undoAll() } + func undoAllSticker() { + imageResizerView.imageView.stickerView.removeAllSticker() + } override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { let view = super.hitTest(point, with: event) @@ -309,6 +335,9 @@ extension PhotoEditorView: UIScrollViewDelegate { } } extension PhotoEditorView: PhotoEditorContentViewDelegate { + func contentView(_ contentView: PhotoEditorContentView, updateStickerText item: EditorStickerItem) { + editorDelegate?.editorView(self, updateStickerText: item) + } func contentView(drawViewBeganDraw contentView: PhotoEditorContentView) { editorDelegate?.editorView(drawViewBeganDraw: self) } diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/Video/VideoEditorMusicAnimationView.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/Video/VideoEditorMusicAnimationView.swift index 03b98cbe..d604f35f 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/Video/VideoEditorMusicAnimationView.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/Video/VideoEditorMusicAnimationView.swift @@ -50,6 +50,9 @@ class VideoEditorMusicAnimationView: UIView { } } func startAnimation() { + if isAnimatoning { + return + } isAnimatoning = true for shapeLayer in animationLayers { shapeLayer.removeAllAnimations() diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/Video/VideoEditorMusicView.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/Video/VideoEditorMusicView.swift index f9810bfa..2c4a1469 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/Video/VideoEditorMusicView.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/Video/VideoEditorMusicView.swift @@ -10,6 +10,7 @@ import UIKit protocol VideoEditorMusicViewDelegate: AnyObject { func musicView(_ musicView: VideoEditorMusicView, didSelectMusic audioPath: String?) func musicView(deselectMusic musicView: VideoEditorMusicView) + func musicView(didSearchButton musicView: VideoEditorMusicView) func musicView(_ musicView: VideoEditorMusicView, didOriginalSoundButtonClick isSelected: Bool) } @@ -30,6 +31,29 @@ class VideoEditorMusicView: UIView { layer.borderWidth = 0.0 return layer }() + lazy var searchBgView: UIVisualEffectView = { + let visualEffect = UIBlurEffect.init(style: .light) + let view = UIVisualEffectView.init(effect: visualEffect) + view.layer.cornerRadius = 15 + view.layer.masksToBounds = true + view.contentView.addSubview(searchButton) + return view + }() + lazy var searchButton: UIButton = { + let button = UIButton(type: .system) + button.setImage("hx_editor_video_music_search".image?.withRenderingMode(.alwaysTemplate), for: .normal) + button.setTitle("搜索".localized, for: .normal) + button.imageEdgeInsets = UIEdgeInsets(top: 0, left: -3, bottom: 0, right: 0) + button.titleEdgeInsets = UIEdgeInsets(top: 0, left: 3, bottom: 0, right: 0) + button.titleLabel?.font = .mediumPingFang(ofSize: 14) + button.tintColor = .white + button.imageView?.tintColor = .white + button.addTarget(self, action: #selector(didSearchButtonClick), for: .touchUpInside) + return button + }() + @objc func didSearchButtonClick() { + delegate?.musicView(didSearchButton: self) + } lazy var flowLayout: UICollectionViewFlowLayout = { let flowLayout = UICollectionViewFlowLayout.init() flowLayout.scrollDirection = .horizontal @@ -103,30 +127,42 @@ class VideoEditorMusicView: UIView { var pageWidth: CGFloat = 0 var selectedIndex: Int = -1 var currentPlayIndex: Int = -2 + var beforeIsSelect = false var musics: [VideoEditorMusic] = [] - init(musicInfos: [VideoEditorMusicInfo]) { + let config: VideoEditorConfiguration.MusicConfig + init(config: VideoEditorConfiguration.MusicConfig) { + self.config = config super.init(frame: .zero) - setMusics(infos: musicInfos) + setMusics(infos: config.infos) layer.addSublayer(bgMaskLayer) addSubview(collectionView) + if config.showSearch { + addSubview(searchBgView) + } addSubview(backgroundButton) addSubview(originalSoundButton) NotificationCenter.default.addObserver(self, selector: #selector(appDidEnterBackground), name: UIApplication.didEnterBackgroundNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(appDidEnterPlayGround), name: UIApplication.didBecomeActiveNotification, object: nil) } @objc func appDidEnterBackground() { + if backgroundButton.isSelected && currentPlayIndex != -2 { + beforeIsSelect = true + } stopMusic() } @objc func appDidEnterPlayGround() { - if backgroundButton.isSelected { + if backgroundButton.isSelected && beforeIsSelect { playMusic() + }else { + backgroundButton.isSelected = false } + beforeIsSelect = false } func setMusics(infos: [VideoEditorMusicInfo]) { var musicArray: [VideoEditorMusic] = [] for musicInfo in infos { - let music = VideoEditorMusic(audioPath: musicInfo.audioPath, - lrcPath: musicInfo.lrcPath) + let music = VideoEditorMusic(audioURL: musicInfo.audioURL, + lrc: musicInfo.lrc) musicArray.append(music) } musics = musicArray @@ -162,8 +198,8 @@ class VideoEditorMusicView: UIView { if !musics.isEmpty { return } - let loadMusic = VideoEditorMusic(audioPath: "", - lrcPath: "") + let loadMusic = VideoEditorMusic(audioURL: URL(fileURLWithPath: ""), + lrc: "") loadMusic.isLoading = true musics = [loadMusic] collectionView.reloadData() @@ -178,10 +214,17 @@ class VideoEditorMusicView: UIView { super.layoutSubviews() bgMaskLayer.frame = bounds let margin: CGFloat = 30 + let searchTextWidth = searchButton.currentTitle?.width(ofFont: UIFont.mediumPingFang(ofSize: 14), maxHeight: 30) ?? 0 + var searchButtonWidth = searchTextWidth + (searchButton.currentImage?.width ?? 0) + 20 + if searchButtonWidth < 65 { + searchButtonWidth = 65 + } + searchBgView.frame = CGRect(x: UIDevice.leftMargin + margin, y: 0, width: searchButtonWidth, height: 30) + searchButton.frame = searchBgView.bounds pageWidth = width - margin * 2 - UIDevice.leftMargin - UIDevice.rightMargin + flowLayout.minimumLineSpacing - collectionView.frame = CGRect(x: 0, y: 0, width: width, height: 140) - flowLayout.sectionInset = UIEdgeInsets(top: 15, left: margin + UIDevice.leftMargin, bottom: 5, right: margin + UIDevice.rightMargin) - flowLayout.itemSize = CGSize(width: pageWidth - flowLayout.minimumLineSpacing, height: collectionView.height - 50) + collectionView.frame = CGRect(x: 0, y: searchBgView.frame.maxY + 15, width: width, height: 90) + flowLayout.sectionInset = UIEdgeInsets(top: 0, left: margin + UIDevice.leftMargin, bottom: 0, right: margin + UIDevice.rightMargin) + flowLayout.itemSize = CGSize(width: pageWidth - flowLayout.minimumLineSpacing, height: collectionView.height) setBottomButtonFrame() } func setBottomButtonFrame() { @@ -194,9 +237,9 @@ class VideoEditorMusicView: UIView { let originalTextWidth = originalSoundButton.currentTitle?.width(ofFont: UIFont.mediumPingFang(ofSize: 16), maxHeight: buttonHeight) ?? 0 let originalButtonWidth = imageWidth + originalTextWidth + 10 let margin: CGFloat = 20 - backgroundButton.frame = CGRect(x: width * 0.5 - margin - bgButtonWidth, y: collectionView.frame.maxY, width: bgButtonWidth, height: buttonHeight) + backgroundButton.frame = CGRect(x: width * 0.5 - margin - bgButtonWidth, y: collectionView.frame.maxY + 20, width: bgButtonWidth, height: buttonHeight) - originalSoundButton.frame = CGRect(x: width * 0.5 + margin, y: collectionView.frame.maxY, width: originalButtonWidth, height: buttonHeight) + originalSoundButton.frame = CGRect(x: width * 0.5 + margin, y: collectionView.frame.maxY + 20, width: originalButtonWidth, height: buttonHeight) if musics.isEmpty { originalSoundButton.centerX = width * 0.5 @@ -279,25 +322,30 @@ extension VideoEditorMusicView: UICollectionViewDataSource, UICollectionViewDele if cell?.music.isLoading == true { return } - cell?.playMusic() + cell?.playMusic(completion: { [weak self] path in + guard let self = self else { return } + self.backgroundButton.isSelected = true + let shake = UIImpactFeedbackGenerator(style: .light) + shake.prepare() + shake.impactOccurred() + self.delegate?.musicView(self, didSelectMusic: path) + }) currentPlayIndex = selectedIndex - backgroundButton.isSelected = true - let shake = UIImpactFeedbackGenerator(style: .light) - shake.prepare() - shake.impactOccurred() - delegate?.musicView(self, didSelectMusic: cell?.music.audioPath) } func stopMusic() { - if currentPlayIndex >= 0 { - let beforeCell = collectionView.cellForItem(at: IndexPath(item: currentPlayIndex, section: 0)) as? VideoEditorMusicViewCell - if beforeCell?.music.isLoading == true { + if let beforeCell = collectionView.cellForItem(at: IndexPath(item: currentPlayIndex, section: 0)) as? VideoEditorMusicViewCell { + if beforeCell.music.isLoading == true { return } - beforeCell?.stopMusic() - currentPlayIndex = -2 + beforeCell.stopMusic() }else { + if currentPlayIndex >= 0 { + let url = musics[currentPlayIndex].audioURL + PhotoManager.shared.suspendTask(url) + } PhotoManager.shared.stopPlayMusic() } + currentPlayIndex = -2 delegate?.musicView(deselectMusic: self) } } @@ -311,13 +359,16 @@ class VideoEditorMusicViewCell: UICollectionViewCell { view.contentView.addSubview(musicIconView) return view }() - + lazy var songNameLb: UILabel = { + let label = UILabel() + label.font = .mediumPingFang(ofSize: 16) + return label + }() lazy var animationView: VideoEditorMusicAnimationView = { let view = VideoEditorMusicAnimationView() view.isHidden = true return view }() - lazy var flowLayout: UICollectionViewFlowLayout = { let flowLayout = UICollectionViewFlowLayout.init() flowLayout.scrollDirection = .horizontal @@ -381,41 +432,161 @@ class VideoEditorMusicViewCell: UICollectionViewCell { if music.lyrics.isEmpty { music.parseLrc() } + if let songName = music.songName, !songName.isEmpty, + let singer = music.singer, !singer.isEmpty { + songNameLb.text = songName + " - " + singer + }else { + songNameLb.text = music.songName + } collectionView.reloadData() - resetStatus() + if music.isSelected { + playMusic { _ in } + }else { + resetStatus() + } } } var isPlaying: Bool = false var playTimer: DispatchSourceTimer? - func playMusic() { + func checkNetworkURL() -> Bool { + if checkLocalURL() { + return false + } + if let scheme = music.audioURL.scheme { + if scheme == "http" || scheme == "https" { + return true + } + } + return UIApplication.shared.canOpenURL(music.audioURL) + } + func checkLocalURL() -> Bool { + FileManager.default.fileExists(atPath: music.audioURL.path) + } + func playMusic(completion: @escaping (String) -> Void) { + hideLoading() + if checkLocalURL() { + completion(music.audioURL.path) + didPlay(audioPath: music.audioURL.path) + music.isSelected = true + }else if checkNetworkURL() { + let key = music.audioURL.absoluteString + let audioTmpURL = PhotoTools.getAudioTmpURL(for: key) + if PhotoTools.isCached(forAudio: key) { + completion(audioTmpURL.path) + didPlay(audioPath: audioTmpURL.path) + music.isSelected = true + return + } + showLoading() + PhotoManager.shared.downloadTask( + with: music.audioURL, + toFile: audioTmpURL, + ext: music + ) { + audioURL, error, ext in + self.hideLoading() + if let audioURL = audioURL, + let music = ext as? VideoEditorMusic { + completion(audioURL.path) + if music == self.music { + self.didPlay(audioPath: audioURL.path) + }else { + PhotoManager.shared.playMusic(filePath: audioURL.path) {} + } + music.isSelected = true + }else { + self.resetStatus() + } + } + }else { + resetStatus() + } + } + func showLoading() { + loadingView.style = .gray + loadingView.isHidden = false + loadingView.startAnimating() + let visualEffect = UIBlurEffect.init(style: .extraLight) + bgView.effect = visualEffect + musicIconView.tintColor = "#333333".color + songNameLb.textColor = "#333333".color + songNameLb.isHidden = true + collectionView.isHidden = true + } + func hideLoading() { + songNameLb.isHidden = false + collectionView.isHidden = false + loadingView.isHidden = true + loadingView.stopAnimating() + } + func didPlay(audioPath: String) { isPlaying = true let visualEffect = UIBlurEffect.init(style: .extraLight) bgView.effect = visualEffect musicIconView.tintColor = "#333333".color + songNameLb.textColor = "#333333".color animationView.startAnimation() animationView.isHidden = false collectionView.reloadData() - let startPoint = -(width - 15) - if PhotoManager.shared.playMusic(filePath: music.audioPath, finished: { [weak self] in - self?.setPreciseContentOffset(x: startPoint, y: 0) - }) { - if let time = PhotoManager.shared.audioPlayer?.duration { - scrollLyric(time: time) - }else if let time = music.time { - scrollLyric(time: time) - }else if let time = music.lyrics.last?.startTime { - scrollLyric(time: time + 5) + let startPointX = -(width - 15) + if music.isSelected { + playTimer?.cancel() + if music.lyricIsEmpty { + DispatchQueue.main.async { + self.scrollLyric(time: 10) + } + return + } + PhotoManager.shared.audioPlayFinish = { [weak self] in + guard let self = self else { return } + if self.music.lyricIsEmpty { + return + } + self.setPreciseContentOffset(x: startPointX, y: 0) + } + DispatchQueue.main.async { + guard let time = PhotoManager.shared.audioPlayer?.currentTime, + let duration = PhotoManager.shared.audioPlayer?.duration else { + return + } + let timeScale = CGFloat(time / duration) + let maxOffsetX = self.collectionView.contentSize.width - self.width + (self.width - 15) - startPointX + let timeOffsetX = maxOffsetX * timeScale + startPointX + self.setPreciseContentOffset(x: timeOffsetX, y: 0) + self.scrollLyric(time: duration) + } + }else { + if PhotoManager.shared.playMusic(filePath: audioPath, finished: { [weak self] in + guard let self = self else { return } + if self.music.lyricIsEmpty { + return + } + self.setPreciseContentOffset(x: startPointX, y: 0) + }) { + if music.lyricIsEmpty { + scrollLyric(time: 10) + return + } + if let time = PhotoManager.shared.audioPlayer?.duration { + scrollLyric(time: time) + }else if let time = music.time { + scrollLyric(time: time) + }else if let time = music.lyrics.last?.startTime { + scrollLyric(time: time + 5) + } } } } func scrollLyric(time: TimeInterval) { playTimer?.cancel() - let startPoint = -(width - 15) - collectionView.setContentOffset(CGPoint(x: startPoint, y: 0), animated: false) - let maxOffsetX = self.collectionView.contentSize.width - width + (width - 15) + let startPointX = -(width - 15) + if !music.isSelected { + collectionView.setContentOffset(CGPoint(x: startPointX, y: 0), animated: false) + } + let maxOffsetX = collectionView.contentSize.width - width + (width - 15) let duration: TimeInterval = 0.005 - let marginX = (maxOffsetX - startPoint) / CGFloat(time * (1 / duration)) + let marginX = (maxOffsetX - startPointX) / CGFloat(time * (1 / duration)) let playTimer = DispatchSource.makeTimerSource() playTimer.schedule(deadline: .now(), repeating: .milliseconds(5), leeway: .milliseconds(0)) playTimer.setEventHandler(handler: { [weak self] in @@ -423,6 +594,9 @@ class VideoEditorMusicViewCell: UICollectionViewCell { DispatchQueue.main.sync { let offsetX = self.collectionView.contentOffset.x if offsetX >= maxOffsetX { + if self.music.lyricIsEmpty { + self.setPreciseContentOffset(x: startPointX, y: 0) + } return } self.setPreciseContentOffset(x: offsetX + marginX, y: 0) @@ -438,14 +612,21 @@ class VideoEditorMusicViewCell: UICollectionViewCell { } func stopMusic() { + music.isSelected = false + if checkNetworkURL() { + PhotoManager.shared.suspendTask(music.audioURL) + } PhotoManager.shared.stopPlayMusic() resetStatus() } func resetStatus() { isPlaying = false + songNameLb.isHidden = false + collectionView.isHidden = false let visualEffect = UIBlurEffect.init(style: .light) bgView.effect = visualEffect musicIconView.tintColor = .white + songNameLb.textColor = .white animationView.isHidden = true animationView.stopAnimation() collectionView.reloadData() @@ -458,6 +639,7 @@ class VideoEditorMusicViewCell: UICollectionViewCell { contentView.addSubview(shadeView) contentView.addSubview(loadingView) contentView.addSubview(animationView) + contentView.addSubview(songNameLb) } required init?(coder: NSCoder) { @@ -470,6 +652,10 @@ class VideoEditorMusicViewCell: UICollectionViewCell { musicIconView.x = 15 musicIconView.y = 15 animationView.frame = CGRect(x: width - 60, y: 20, width: 20, height: 15) + songNameLb.x = musicIconView.frame.maxX + 10 + songNameLb.width = animationView.x - 10 - songNameLb.x + songNameLb.height = 20 + songNameLb.centerY = musicIconView.centerY shadeView.frame = CGRect(x: 0, y: musicIconView.frame.maxY + 10, width: width, height: height - musicIconView.frame.maxY - 20) collectionView.frame = shadeView.bounds maskLayer.frame = CGRect(x: 10, y: 0, width: shadeView.width - 20, height: shadeView.height) @@ -503,7 +689,7 @@ class VideoEditorMusicLyricViewCell: UICollectionViewCell { lazy var lyricLb: UILabel = { let label = UILabel.init() - label.font = UIFont.mediumPingFang(ofSize: 16) + label.font = .mediumPingFang(ofSize: 16) label.textColor = .white return label }() diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/Video/VideoEditorSearchMusicView.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/Video/VideoEditorSearchMusicView.swift new file mode 100644 index 00000000..7216738f --- /dev/null +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Editor/View/Video/VideoEditorSearchMusicView.swift @@ -0,0 +1,426 @@ +// +// VideoEditorSearchMusicView.swift +// HXPHPicker +// +// Created by Slience on 2021/7/29. +// + +import UIKit + +protocol VideoEditorSearchMusicViewDelegate: AnyObject { + func searchMusicView(didCancelClick searchMusicView: VideoEditorSearchMusicView) + func searchMusicView(didFinishClick searchMusicView: VideoEditorSearchMusicView) + func searchMusicView(_ searchMusicView: VideoEditorSearchMusicView, + didSelectItem audioPath: String?) + func searchMusicView(_ searchMusicView: VideoEditorSearchMusicView, + didSearch text: String?, + completion: @escaping ([VideoEditorMusicInfo], Bool) -> Void) + func searchMusicView(_ searchMusicView: VideoEditorSearchMusicView, + loadMore text: String?, + completion: @escaping ([VideoEditorMusicInfo], Bool) -> Void) + func searchMusicView(deselectItem searchMusicView: VideoEditorSearchMusicView) +} + +class VideoEditorSearchMusicView: UIView { + weak var delegate: VideoEditorSearchMusicViewDelegate? + lazy var loadBgView: UIView = { + let view = UIView() + view.addSubview(loadingView) + return view + }() + lazy var loadingView: UIActivityIndicatorView = { + let view = UIActivityIndicatorView(style: .white) + view.hidesWhenStopped = true + return view + }() + lazy var bgView: UIVisualEffectView = { + let visualEffect = UIBlurEffect.init(style: .dark) + let view = UIVisualEffectView.init(effect: visualEffect) + return view + }() + lazy var topView: UIView = { + let view = UIView() + view.addSubview(cancelButton) + view.addSubview(titleLb) + view.addSubview(finishButton) + return view + }() + lazy var titleLb: UILabel = { + let label = UILabel() + label.text = "背景音乐".localized + label.textColor = .white + label.textAlignment = .center + label.font = .mediumPingFang(ofSize: 17) + return label + }() + lazy var cancelButton: UIButton = { + let button = UIButton(type: .system) + button.setTitle("取消".localized, for: .normal) + button.setTitleColor(.white, for: .normal) + button.titleLabel?.font = UIFont.systemFont(ofSize: 17) + button.addTarget(self, action: #selector(didCancelButtonClick), for: .touchUpInside) + return button + }() + @objc func didCancelButtonClick() { + delegate?.searchMusicView(didCancelClick: self) + } + lazy var finishButton: UIButton = { + let button = UIButton(type: .system) + let title = "完成".localized + let font = UIFont.systemFont(ofSize: 16) + let image = UIImage.image(for: config.tintColor, havingSize: CGSize(width: title.width(ofFont: font, maxHeight: 35), height: 30), radius: 3) + let disabledImage = UIImage.image(for: .white.withAlphaComponent(0.2), havingSize: CGSize(width: title.width(ofFont: font, maxHeight: 30), height: 30), radius: 3) + button.setTitle(title, for: .normal) + button.setTitleColor(.white, for: .normal) + button.setTitleColor(.white.withAlphaComponent(0.6), for: .disabled) + button.setBackgroundImage(image, for: .normal) + button.setBackgroundImage(disabledImage, for: .disabled) + button.titleLabel?.font = font + button.isEnabled = false + button.addTarget(self, action: #selector(didFinishButtonClick), for: .touchUpInside) + return button + }() + @objc func didFinishButtonClick() { + delegate?.searchMusicView(didFinishClick: self) + currentSelectItem = -1 + } + lazy var searchBgView: UIVisualEffectView = { + let visualEffect = UIBlurEffect.init(style: .light) + let view = UIVisualEffectView.init(effect: visualEffect) + view.layer.cornerRadius = 10 + view.layer.masksToBounds = true + view.alpha = 0.5 + return view + }() + lazy var searchView: SearchView = { + let view = SearchView() + view.textColor = .white + view.tintColor = config.tintColor + view.attributedPlaceholder = NSAttributedString(string: config.placeholder.isEmpty ? "搜索歌名".localized : config.placeholder, attributes: [.font: UIFont.systemFont(ofSize: 17), .foregroundColor: UIColor.white.withAlphaComponent(0.4)]) + view.font = .systemFont(ofSize: 17) + view.clearButtonMode = .whileEditing + view.returnKeyType = .search + let searchIcon = UIImageView() + searchIcon.image = "hx_editor_video_music_search".image?.withRenderingMode(.alwaysTemplate) + searchIcon.tintColor = .white.withAlphaComponent(0.4) + view.leftView = searchIcon + view.leftViewMode = .always + view.layer.cornerRadius = 10 + view.layer.masksToBounds = true + view.delegate = self + return view + }() + lazy var flowLayout: UICollectionViewFlowLayout = { + let flowLayout = UICollectionViewFlowLayout.init() + flowLayout.scrollDirection = .vertical + flowLayout.minimumLineSpacing = 15 + flowLayout.minimumInteritemSpacing = 0 + return flowLayout + }() + lazy var collectionView: UICollectionView = { + let collectionView = UICollectionView.init(frame: CGRect(x: 0, y: 0, width: 0, height: 90), collectionViewLayout: flowLayout) + collectionView.backgroundColor = .clear + collectionView.dataSource = self + collectionView.delegate = self + collectionView.showsHorizontalScrollIndicator = false + if #available(iOS 11.0, *) { + collectionView.contentInsetAdjustmentBehavior = .never + } + collectionView.register(VideoEditorMusicViewCell.self, forCellWithReuseIdentifier: "VideoEditorMusicViewCellID") + return collectionView + }() + lazy var noMoreView: UIView = { + let view = UIView() + view.layer.addSublayer(noMoreLine) + return view + }() + lazy var noMoreLine: CAShapeLayer = { + let noMoreLine = CAShapeLayer() + noMoreLine.contentsScale = UIScreen.main.scale + noMoreLine.fillColor = UIColor.white.withAlphaComponent(0.5).cgColor + noMoreLine.strokeColor = UIColor.white.withAlphaComponent(0.5).cgColor + noMoreLine.lineCap = .round + noMoreLine.lineJoin = .round + noMoreLine.lineWidth = 1 + return noMoreLine + }() + var currentSelectItem: Int = -1 + var musics: [VideoEditorMusic] = [] + var isLoading = false + var isLoadMore = false + var hasMore = false + let config: VideoEditorConfiguration.MusicConfig + init(config: VideoEditorConfiguration.MusicConfig) { + self.config = config + super.init(frame: .zero) + musics = getMusics(infos: config.infos) + addSubview(bgView) + addSubview(topView) + addSubview(searchBgView) + addSubview(searchView) + addSubview(collectionView) + NotificationCenter.default.addObserver(self, selector: #selector(appDidEnterBackground), name: UIApplication.didEnterBackgroundNotification, object: nil) + } + @objc func appDidEnterBackground() { + deselect() + } + func deselect() { + if currentSelectItem >= 0 { + if let cell = collectionView.cellForItem(at: IndexPath(item: currentSelectItem, section: 0)) as? VideoEditorMusicViewCell { + cell.stopMusic() + }else { + musics[currentSelectItem].isSelected = false + let url = musics[currentSelectItem].audioURL + PhotoManager.shared.suspendTask(url) + PhotoManager.shared.stopPlayMusic() + } + currentSelectItem = -1 + delegate?.searchMusicView(deselectItem: self) + } + finishButton.isEnabled = false + } + func clearData() { + searchView.text = nil + musics.removeAll() + stopLoading() + removeNoMore() + collectionView.reloadData() + finishButton.isEnabled = false + } + func reloadData() { + collectionView.reloadData() + DispatchQueue.main.async { + self.setupCollectionInset() + } + } + func getMusics(infos: [VideoEditorMusicInfo]) -> [VideoEditorMusic] { + var musicArray: [VideoEditorMusic] = [] + for musicInfo in infos { + let music = VideoEditorMusic(audioURL: musicInfo.audioURL, + lrc: musicInfo.lrc) + musicArray.append(music) + } + return musicArray + } + override func layoutSubviews() { + super.layoutSubviews() + bgView.frame = bounds + topView.frame = CGRect(x: 0, y: 0, width: width, height: 50) + titleLb.width = titleLb.text?.width(ofFont: titleLb.font, maxHeight: 50) ?? 0 + titleLb.height = 50 + titleLb.centerX = width * 0.5 + titleLb.y = 0 + cancelButton.frame = CGRect(x: 12 + UIDevice.leftMargin, y: 0, width: 0, height: 50) + cancelButton.width = cancelButton.currentTitle?.width(ofFont: cancelButton.titleLabel!.font, maxHeight: 50) ?? 0 + finishButton.width = (finishButton.currentTitle?.width(ofFont: finishButton.titleLabel!.font, maxHeight: 50) ?? 0) + 20 + if finishButton.width < 55 { + finishButton.width = 55 + } + finishButton.height = 30 + finishButton.centerY = topView.height * 0.5 + finishButton.x = width - UIDevice.rightMargin - 12 - finishButton.width + + searchView.frame = CGRect(x: 12 + UIDevice.leftMargin, y: topView.frame.maxY + 12, width: width - 24 - UIDevice.leftMargin - UIDevice.rightMargin, height: 35) + searchBgView.frame = searchView.frame + + setupCollectionInset() + collectionView.frame = CGRect(x: 0, y: searchView.frame.maxY + 12, width: width, height: height - searchView.frame.maxY - 12) + } + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + deinit { + NotificationCenter.default.removeObserver(self) + } + class SearchView: UITextField { + override func leftViewRect(forBounds bounds: CGRect) -> CGRect { + let rect = super.leftViewRect(forBounds: bounds) + return CGRect(x: (height - rect.width) * 0.5, y: (height - rect.height) * 0.5, width: rect.width, height: rect.height) + } + override func textRect(forBounds bounds: CGRect) -> CGRect { + var rect = super.textRect(forBounds: bounds) + let leftViewRect = leftViewRect(forBounds: bounds) + rect.origin.x += leftViewRect.minX + rect.size.width -= leftViewRect.minX + return rect + } + override func editingRect(forBounds bounds: CGRect) -> CGRect { + var rect = super.editingRect(forBounds: bounds) + let leftViewRect = leftViewRect(forBounds: bounds) + rect.origin.x += leftViewRect.minX + rect.size.width -= leftViewRect.minX + return rect + } + override func layoutSubviews() { + super.layoutSubviews() + for view in subviews { + if let button = view as? UIButton { + button.setImage(button.image(for: .normal)?.withRenderingMode(.alwaysTemplate), for: .normal) + button.tintColor = .white.withAlphaComponent(0.4) + } + } + } + } +} +extension VideoEditorSearchMusicView: UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout { + func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + musics.count + } + func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "VideoEditorMusicViewCellID", for: indexPath) as! VideoEditorMusicViewCell + cell.music = musics[indexPath.item] + return cell + } + func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { + collectionView.deselectItem(at: indexPath, animated: false) + if currentSelectItem == indexPath.item { + return + } + if currentSelectItem >= 0 { + if let lastCell = collectionView.cellForItem(at: IndexPath(item: currentSelectItem, section: 0)) as? VideoEditorMusicViewCell { + lastCell.stopMusic() + }else { + musics[currentSelectItem].isSelected = false + let url = musics[currentSelectItem].audioURL + PhotoManager.shared.suspendTask(url) + PhotoManager.shared.stopPlayMusic() + } + } + let cell = collectionView.cellForItem(at: indexPath) as! VideoEditorMusicViewCell + cell.playMusic { [weak self] path in + guard let self = self else { return } + let shake = UIImpactFeedbackGenerator(style: .light) + shake.prepare() + shake.impactOccurred() + self.delegate?.searchMusicView(self, didSelectItem: path) + } + currentSelectItem = indexPath.item + finishButton.isEnabled = true + } + func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { + CGSize(width: width - collectionView.contentInset.left - collectionView.contentInset.right, height: 90) + } + func scrollViewDidScroll(_ scrollView: UIScrollView) { + let offsetY = scrollView.contentOffset.y + let contentHeight = scrollView.contentSize.height + let maxOffsetY = contentHeight - scrollView.height + scrollView.contentInset.bottom + if offsetY > maxOffsetY - 100 && hasMore { + if !isLoadMore && !isLoading && !musics.isEmpty { + isLoadMore = true + startLoading(isMore: true) + delegate?.searchMusicView(self, loadMore: searchView.text, completion: { + [weak self] musicInfos, hasMore in + guard let self = self else { return } + self.stopLoading() + let musics = self.getMusics(infos: musicInfos) + self.musics.append(contentsOf: musics) + self.collectionView.reloadData() + DispatchQueue.main.async { + if !hasMore { + self.addNoMore() + }else { + self.removeNoMore() + } + } + self.hasMore = hasMore + self.isLoadMore = false + }) + } + } + } + func setupCollectionInset() { + let top: CGFloat = 10 + let left = UIDevice.leftMargin + 12 + let bottom = UIDevice.bottomMargin + 60 + let right = UIDevice.rightMargin + 12 + if isLoading { + if !isLoadMore { + collectionView.contentInset = UIEdgeInsets(top: top + 40, left: left, bottom: bottom, right: right) + loadBgView.frame = CGRect(x: 0, y: -40, width: collectionView.width - left - right, height: 40) + }else { + collectionView.contentInset = UIEdgeInsets(top: top, left: left, bottom: bottom + 40, right: right) + loadBgView.frame = CGRect(x: 0, y: collectionView.contentSize.height + top + 10, width: collectionView.width - left - right, height: 40) + } + }else { + collectionView.contentInset = UIEdgeInsets(top: top, left: left, bottom: bottom, right: right) + if !hasMore { + noMoreView.frame = CGRect(x: 0, y: collectionView.contentSize.height + top + 10, width: collectionView.width - left - right, height: 40) + updateMoreLine() + } + } + } +} +extension VideoEditorSearchMusicView: UITextFieldDelegate { + func textFieldShouldReturn(_ textField: UITextField) -> Bool { + endEditing(true) + isLoadMore = false + stopLoading() + removeNoMore() + deselect() + clearData() + startLoading(isMore: false) + delegate?.searchMusicView(self, didSearch: textField.text, completion: { + [weak self] musicInfos, hasMore in + guard let self = self else { return } + self.stopLoading() + let musics = self.getMusics(infos: musicInfos) + self.musics.append(contentsOf: musics) + self.collectionView.reloadData() + DispatchQueue.main.async { + if !hasMore { + self.addNoMore() + }else { + self.removeNoMore() + } + } + self.hasMore = hasMore + }) + return true + } + + func startLoading(isMore: Bool) { + isLoading = true + let top: CGFloat = 10 + let left = UIDevice.leftMargin + 12 + let bottom = UIDevice.bottomMargin + 60 + let right = UIDevice.rightMargin + 12 + if !isMore { + collectionView.contentInset = UIEdgeInsets(top: top + 40, left: left, bottom: bottom, right: right) + loadBgView.frame = CGRect(x: 0, y: -40, width: collectionView.width - left - right, height: 40) + }else { + collectionView.contentInset = UIEdgeInsets(top: top, left: left, bottom: bottom, right: right) + loadBgView.frame = CGRect(x: 0, y: collectionView.contentSize.height + top + 10, width: collectionView.width - left - right, height: 40) + } + loadingView.startAnimating() + loadingView.centerX = loadBgView.width * 0.5 + collectionView.addSubview(loadBgView) + } + func stopLoading() { + isLoading = false + collectionView.contentInset = UIEdgeInsets(top: 10, left: UIDevice.leftMargin + 12, bottom: UIDevice.bottomMargin + 60, right: UIDevice.rightMargin + 12) + loadingView.stopAnimating() + loadBgView.removeFromSuperview() + } + func addNoMore() { + let top: CGFloat = 10 + let left = UIDevice.leftMargin + 12 + let bottom = UIDevice.bottomMargin + 60 + let right = UIDevice.rightMargin + 12 + collectionView.contentInset = UIEdgeInsets(top: top, left: left, bottom: bottom, right: right) + noMoreView.frame = CGRect(x: 0, y: collectionView.contentSize.height + top + 10, width: collectionView.width - left - right, height: 40) + updateMoreLine() + collectionView.addSubview(noMoreView) + } + func removeNoMore() { + noMoreView.removeFromSuperview() + } + func updateMoreLine() { + let arcCenter = CGPoint(x: noMoreView.width * 0.5, y: 10) + let path = UIBezierPath(arcCenter: arcCenter, radius: 1, startAngle: 0, endAngle: CGFloat.pi * 2, clockwise: true) + path.move(to: CGPoint(x: arcCenter.x - 10, y: arcCenter.y)) + path.addLine(to: CGPoint(x: arcCenter.x - 110, y: arcCenter.y)) + path.move(to: CGPoint(x: arcCenter.x + 10, y: arcCenter.y)) + path.addLine(to: CGPoint(x: arcCenter.x + 110, y: arcCenter.y)) + noMoreLine.path = path.cgPath + } +} diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Config/AlbumListConfiguration.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Config/AlbumListConfiguration.swift index a9ee9b28..ae98d054 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Config/AlbumListConfiguration.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Config/AlbumListConfiguration.swift @@ -12,34 +12,22 @@ import UIKit public class AlbumListConfiguration { /// 可访问权限下的提示语颜色 - public lazy var limitedStatusPromptColor: UIColor = { - return "#999999".color - }() + public lazy var limitedStatusPromptColor: UIColor = "#999999".color /// 暗黑风格可访问权限下的提示语颜色 - public lazy var limitedStatusPromptDarkColor: UIColor = { - return "#999999".color - }() + public lazy var limitedStatusPromptDarkColor: UIColor = "#999999".color /// 当相册里没有资源时的相册名称 - public lazy var emptyAlbumName: String = { - return "所有照片" - }() + public lazy var emptyAlbumName: String = "所有照片" /// 当相册里没有资源时的封面图片名 - public lazy var emptyCoverImageName: String = { - return "hx_picker_album_empty" - }() + public lazy var emptyCoverImageName: String = "hx_picker_album_empty" /// 列表背景颜色 - public lazy var backgroundColor : UIColor = { - return UIColor.white - }() + public lazy var backgroundColor : UIColor = .white /// 暗黑风格下列表背景颜色 - public lazy var backgroundDarkColor : UIColor = { - return "#2E2F30".color - }() + public lazy var backgroundDarkColor : UIColor = "#2E2F30".color /// 自定义cell,继承 AlbumViewCell 加以修改 public var customCellClass: AlbumViewCell.Type? @@ -48,72 +36,46 @@ public class AlbumListConfiguration { public var cellHeight : CGFloat = 100 /// cell背景颜色 - public lazy var cellBackgroundColor: UIColor = { - return UIColor.white - }() + public lazy var cellBackgroundColor: UIColor = .white /// 暗黑风格下cell背景颜色 - public lazy var cellbackgroundDarkColor : UIColor = { - return "#2E2F30".color - }() + public lazy var cellbackgroundDarkColor : UIColor = "#2E2F30".color /// cell选中时的颜色 public var cellSelectedColor : UIColor? /// 暗黑风格下cell选中时的颜色 - public lazy var cellSelectedDarkColor : UIColor = { - return UIColor.init(red: 0.125, green: 0.125, blue: 0.125, alpha: 1) - }() + public lazy var cellSelectedDarkColor : UIColor = .init(red: 0.125, green: 0.125, blue: 0.125, alpha: 1) /// 相册名称颜色 - public lazy var albumNameColor : UIColor = { - return .black - }() + public lazy var albumNameColor : UIColor = .black /// 暗黑风格下相册名称颜色 - public lazy var albumNameDarkColor : UIColor = { - return .white - }() + public lazy var albumNameDarkColor : UIColor = .white /// 相册名称字体 - public lazy var albumNameFont : UIFont = { - return UIFont.mediumPingFang(ofSize: 15) - }() + public lazy var albumNameFont : UIFont = .mediumPingFang(ofSize: 15) /// 照片数量颜色 - public lazy var photoCountColor : UIColor = { - return "#999999".color - }() + public lazy var photoCountColor : UIColor = "#999999".color /// 暗黑风格下相册名称颜色 - public lazy var photoCountDarkColor : UIColor = { - return "#dadada".color - }() + public lazy var photoCountDarkColor : UIColor = "#dadada".color /// 照片数量字体 - public lazy var photoCountFont : UIFont = { - return UIFont.mediumPingFang(ofSize: 12) - }() + public lazy var photoCountFont : UIFont = .mediumPingFang(ofSize: 12) /// 分隔线颜色 - public lazy var separatorLineColor: UIColor = { - return "#eeeeee".color - }() + public lazy var separatorLineColor: UIColor = "#eeeeee".color /// 暗黑风格下分隔线颜色 - public lazy var separatorLineDarkColor : UIColor = { - return "#434344".color.withAlphaComponent(0.6) - }() + public lazy var separatorLineDarkColor : UIColor = "#434344".color.withAlphaComponent(0.6) /// 选中勾勾的颜色 - public lazy var tickColor: UIColor = { - return "#333333".color - }() + public lazy var tickColor: UIColor = "#333333".color /// 暗黑风格选中勾勾的颜色 - public lazy var tickDarkColor : UIColor = { - return "#ffffff".color - }() + public lazy var tickDarkColor : UIColor = "#ffffff".color public init() { } } diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Config/AlbumTitleViewConfiguration.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Config/AlbumTitleViewConfiguration.swift index 195086bc..660f976b 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Config/AlbumTitleViewConfiguration.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Config/AlbumTitleViewConfiguration.swift @@ -18,24 +18,16 @@ public class AlbumTitleViewConfiguration { public var backgroudDarkColor: UIColor? /// 箭头背景颜色 - public lazy var arrowBackgroundColor: UIColor = { - return "#333333".color - }() + public lazy var arrowBackgroundColor: UIColor = "#333333".color /// 箭头颜色 - public lazy var arrowColor: UIColor = { - return "#ffffff".color - }() + public lazy var arrowColor: UIColor = "#ffffff".color /// 暗黑风格下箭头背景颜色 - public lazy var arrowBackgroudDarkColor: UIColor = { - return "#ffffff".color - }() + public lazy var arrowBackgroudDarkColor: UIColor = "#ffffff".color /// 暗黑风格下箭头颜色 - public lazy var arrowDarkColor: UIColor = { - return "#333333".color - }() + public lazy var arrowDarkColor: UIColor = "#333333".color public init() { } } diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Config/EmptyViewConfiguration.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Config/EmptyViewConfiguration.swift index 2d3bfbdc..2a3beb80 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Config/EmptyViewConfiguration.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Config/EmptyViewConfiguration.swift @@ -12,24 +12,16 @@ import UIKit public class EmptyViewConfiguration { /// 标题颜色 - public lazy var titleColor: UIColor = { - return "#666666".color - }() + public lazy var titleColor: UIColor = "#666666".color /// 暗黑风格下标题颜色 - public lazy var titleDarkColor: UIColor = { - return "#ffffff".color - }() + public lazy var titleDarkColor: UIColor = "#ffffff".color /// 子标题颜色 - public lazy var subTitleColor: UIColor = { - return "#999999".color - }() + public lazy var subTitleColor: UIColor = "#999999".color /// 暗黑风格下子标题颜色 - public lazy var subTitleDarkColor: UIColor = { - return "#dadada".color - }() + public lazy var subTitleDarkColor: UIColor = "#dadada".color public init() { } } diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Config/NotAuthorizedConfiguration.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Config/NotAuthorizedConfiguration.swift index 4b6b5c66..3436aa00 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Config/NotAuthorizedConfiguration.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Config/NotAuthorizedConfiguration.swift @@ -12,64 +12,40 @@ import UIKit public class NotAuthorizedConfiguration { /// 背景颜色 - public lazy var backgroundColor: UIColor = { - return UIColor.white - }() + public lazy var backgroundColor: UIColor = .white /// 暗黑风格下的背景颜色 - public lazy var darkBackgroundColor: UIColor = { - return "#2E2F30".color - }() + public lazy var darkBackgroundColor: UIColor = "#2E2F30".color /// 关闭按钮图片名 - public lazy var closeButtonImageName: String = { - return "hx_picker_notAuthorized_close" - }() + public lazy var closeButtonImageName: String = "hx_picker_notAuthorized_close" /// 暗黑风格下的关闭按钮图片名 - public lazy var closeButtonDarkImageName: String = { - return "hx_picker_notAuthorized_close_dark" - }() + public lazy var closeButtonDarkImageName: String = "hx_picker_notAuthorized_close_dark" /// 标题颜色 - public lazy var titleColor: UIColor = { - return UIColor.black - }() + public lazy var titleColor: UIColor = .black /// 暗黑风格下的标题颜色 - public lazy var titleDarkColor: UIColor = { - return .white - }() + public lazy var titleDarkColor: UIColor = .white /// 子标题颜色 - public lazy var subTitleColor: UIColor = { - return "#444444".color - }() + public lazy var subTitleColor: UIColor = "#444444".color /// 暗黑风格下的子标题颜色 - public lazy var darkSubTitleColor: UIColor = { - return .white - }() + public lazy var darkSubTitleColor: UIColor = .white /// 跳转按钮背景颜色 - public lazy var jumpButtonBackgroundColor: UIColor = { - return "#333333".color - }() + public lazy var jumpButtonBackgroundColor: UIColor = "#333333".color /// 暗黑风格下跳转按钮背景颜色 - public lazy var jumpButtonDarkBackgroundColor: UIColor = { - return .white - }() + public lazy var jumpButtonDarkBackgroundColor: UIColor = .white /// 跳转按钮文字颜色 - public lazy var jumpButtonTitleColor: UIColor = { - return "#ffffff".color - }() + public lazy var jumpButtonTitleColor: UIColor = "#ffffff".color /// 暗黑风格下跳转按钮文字颜色 - public lazy var jumpButtonTitleDarkColor: UIColor = { - return "#333333".color - }() + public lazy var jumpButtonTitleDarkColor: UIColor = "#333333".color public init() { } } diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Config/PhotoListCellConfiguration.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Config/PhotoListCellConfiguration.swift index d974062b..457f76a1 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Config/PhotoListCellConfiguration.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Config/PhotoListCellConfiguration.swift @@ -31,9 +31,7 @@ public class PhotoListCellConfiguration { /// 缩略图的清晰度,越大越清楚,越小越模糊 /// 为0时,默认为 cell.width * 2 public var targetWidth: CGFloat = 0 { - didSet { - PhotoManager.shared.targetWidth = targetWidth - } + didSet { PhotoManager.shared.targetWidth = targetWidth } } /// cell在不可选择状态下是否显示禁用遮罩 @@ -47,9 +45,7 @@ public class PhotoListCellConfiguration { public var selectBoxRightMargin: CGFloat = 5 /// 选择框相关配置 - public lazy var selectBox: SelectBoxConfiguration = { - return SelectBoxConfiguration.init() - }() + public lazy var selectBox: SelectBoxConfiguration = .init() - public init() { } + public init() { PhotoManager.shared.targetWidth = targetWidth } } diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Config/PhotoListConfiguration.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Config/PhotoListConfiguration.swift index 98302f62..b9d5479d 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Config/PhotoListConfiguration.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Config/PhotoListConfiguration.swift @@ -11,20 +11,13 @@ import UIKit // MARK: 照片列表配置类 public class PhotoListConfiguration { /// 相册标题视图配置 - public lazy var titleViewConfig: AlbumTitleViewConfiguration = { - let titleViewConfig = AlbumTitleViewConfiguration.init() - return titleViewConfig - }() + public lazy var titleView: AlbumTitleViewConfiguration = .init() /// 背景颜色 - public lazy var backgroundColor : UIColor = { - return UIColor.white - }() + public lazy var backgroundColor : UIColor = .white /// 暗黑风格下背景颜色 - public lazy var backgroundDarkColor : UIColor = { - return "#2E2F30".color - }() + public lazy var backgroundDarkColor : UIColor = "#2E2F30".color /// 取消按钮的配置只有当 albumShowMode = .popup 时有效 /// 取消按钮类型 @@ -64,28 +57,19 @@ public class PhotoListConfiguration { public var autoSwipeBottomAreaHeight: CGFloat = 100 /// cell相关配置 - public lazy var cell: PhotoListCellConfiguration = { - return PhotoListCellConfiguration.init() - }() + public lazy var cell: PhotoListCellConfiguration = .init() /// 底部视图相关配置 - public lazy var bottomView: PickerBottomViewConfiguration = { - let config = PickerBottomViewConfiguration.init() - return config - }() + public lazy var bottomView: PickerBottomViewConfiguration = .init() /// 允许添加相机 public var allowAddCamera: Bool = true /// 相机cell配置 - public lazy var cameraCell: PhotoListCameraCellConfiguration = { - return PhotoListCameraCellConfiguration.init() - }() + public lazy var cameraCell: PhotoListCameraCellConfiguration = .init() /// 相机配置 - public lazy var camera: CameraConfiguration = { - return CameraConfiguration.init() - }() + public lazy var camera: CameraConfiguration = .init() /// 拍照完成后是否选择 public var takePictureCompletionToSelected: Bool = true @@ -97,9 +81,7 @@ public class PhotoListConfiguration { public var customAlbumName: String? /// 没有资源时展示的相关配置 - public lazy var emptyView : EmptyViewConfiguration = { - return EmptyViewConfiguration.init() - }() + public lazy var emptyView : EmptyViewConfiguration = .init() public init() { } } diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Config/PickerBottomViewConfiguration.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Config/PickerBottomViewConfiguration.swift index 1309e46a..09429eb7 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Config/PickerBottomViewConfiguration.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Config/PickerBottomViewConfiguration.swift @@ -30,14 +30,10 @@ public class PickerBottomViewConfiguration { public var previewButtonHidden: Bool = false /// 预览按钮标题颜色 - public lazy var previewButtonTitleColor: UIColor = { - return .systemTintColor - }() + public lazy var previewButtonTitleColor: UIColor = .systemTintColor /// 暗黑风格下预览按钮标题颜色 - public lazy var previewButtonTitleDarkColor: UIColor = { - return .white - }() + public lazy var previewButtonTitleDarkColor: UIColor = .white /// 预览按钮禁用下的标题颜色 public var previewButtonDisableTitleColor: UIColor? @@ -49,14 +45,11 @@ public class PickerBottomViewConfiguration { public var originalButtonHidden : Bool = false /// 原图按钮标题颜色 - public lazy var originalButtonTitleColor: UIColor = { - return .systemTintColor - }() + public lazy var originalButtonTitleColor: UIColor = .systemTintColor /// 暗黑风格下预览按钮标题颜色 - public lazy var originalButtonTitleDarkColor: UIColor = { - return .white - }() + public lazy var originalButtonTitleDarkColor: UIColor = .white + /// 显示原图文件大小 public var showOriginalFileSize: Bool = true @@ -88,44 +81,28 @@ public class PickerBottomViewConfiguration { }() /// 完成按钮标题颜色 - public lazy var finishButtonTitleColor: UIColor = { - return UIColor.white - }() + public lazy var finishButtonTitleColor: UIColor = .white /// 暗黑风格下完成按钮标题颜色 - public lazy var finishButtonTitleDarkColor: UIColor = { - return .black - }() + public lazy var finishButtonTitleDarkColor: UIColor = .black /// 完成按钮禁用下的标题颜色 - public lazy var finishButtonDisableTitleColor: UIColor = { - return UIColor.white.withAlphaComponent(0.6) - }() + public lazy var finishButtonDisableTitleColor: UIColor = .white.withAlphaComponent(0.6) /// 暗黑风格下完成按钮禁用下的标题颜色 - public lazy var finishButtonDisableTitleDarkColor: UIColor = { - return UIColor.black.withAlphaComponent(0.6) - }() + public lazy var finishButtonDisableTitleDarkColor: UIColor = .black.withAlphaComponent(0.6) /// 完成按钮选中时的背景颜色 - public lazy var finishButtonBackgroundColor: UIColor = { - return .systemTintColor - }() + public lazy var finishButtonBackgroundColor: UIColor = .systemTintColor /// 暗黑风格下完成按钮选中时的背景颜色 - public lazy var finishButtonDarkBackgroundColor: UIColor = { - return .white - }() + public lazy var finishButtonDarkBackgroundColor: UIColor = .white /// 完成按钮禁用时的背景颜色 - public lazy var finishButtonDisableBackgroundColor: UIColor = { - return .systemTintColor - }() + public lazy var finishButtonDisableBackgroundColor: UIColor = .systemTintColor /// 暗黑风格下完成按钮禁用时的背景颜色 - public lazy var finishButtonDisableDarkBackgroundColor: UIColor = { - return UIColor.white.withAlphaComponent(0.4) - }() + public lazy var finishButtonDisableDarkBackgroundColor: UIColor = .white.withAlphaComponent(0.4) /// 未选择资源时是否禁用完成按钮 public var disableFinishButtonWhenNotSelected: Bool = true @@ -136,14 +113,10 @@ public class PickerBottomViewConfiguration { public var editButtonHidden: Bool = true /// 编辑按钮标题颜色 - public lazy var editButtonTitleColor: UIColor = { - return .systemTintColor - }() + public lazy var editButtonTitleColor: UIColor = .systemTintColor /// 暗黑风格下编辑按钮标题颜色 - public lazy var editButtonTitleDarkColor: UIColor = { - return .white - }() + public lazy var editButtonTitleDarkColor: UIColor = .white /// 编辑按钮禁用下的标题颜色 public var editButtonDisableTitleColor: UIColor? @@ -154,34 +127,22 @@ public class PickerBottomViewConfiguration { public var showPrompt: Bool = true /// 提示图标颜色 - public lazy var promptIconColor: UIColor = { - return .systemTintColor - }() + public lazy var promptIconColor: UIColor = .systemTintColor /// 暗黑风格下提示图标颜色 - public lazy var promptIconDarkColor: UIColor = { - return .white - }() + public lazy var promptIconDarkColor: UIColor = .white /// 提示语颜色 - public lazy var promptTitleColor: UIColor = { - return .systemTintColor - }() + public lazy var promptTitleColor: UIColor = .systemTintColor /// 暗黑风格下提示语颜色 - public lazy var promptTitleDarkColor: UIColor = { - return .white - }() + public lazy var promptTitleDarkColor: UIColor = .white /// 提示语颜色 - public lazy var promptArrowColor: UIColor = { - return .systemTintColor - }() + public lazy var promptArrowColor: UIColor = .systemTintColor /// 暗黑风格下提示语颜色 - public lazy var promptArrowDarkColor: UIColor = { - return .white - }() + public lazy var promptArrowDarkColor: UIColor = .white /// 显示已选资源 public var showSelectedView: Bool = false @@ -190,9 +151,7 @@ public class PickerBottomViewConfiguration { public var customSelectedViewCellClass: PhotoPreviewSelectedViewCell.Type? /// 已选资源选中的勾勾颜色 - public lazy var selectedViewTickColor: UIColor = { - return .white - }() + public lazy var selectedViewTickColor: UIColor = .white public init() { } } diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Config/PickerConfiguration.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Config/PickerConfiguration.swift index 901e7a41..b64b13c0 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Config/PickerConfiguration.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Config/PickerConfiguration.swift @@ -24,6 +24,12 @@ open class PickerConfiguration: BaseConfiguration { /// 允许加载系统照片库 public var allowLoadPhotoLibrary: Bool = true + /// 选择照片时,先判断是否在iCloud上。如果在iCloud上会先同步iCloud上的资源 + /// 如果在断网或者系统iCloud出错的情况下: + /// true: 选择失败 + /// fasle: 获取原始图片会失败 + public var allowSyncICloudWhenSelectPhoto : Bool = true + /// 相册展示模式 public var albumShowMode: AlbumShowMode = .normal @@ -72,7 +78,7 @@ open class PickerConfiguration: BaseConfiguration { /// 视频编辑配置 public lazy var videoEditor: VideoEditorConfiguration = .init() - /// 图片编辑配置 + /// 照片编辑配置 public lazy var photoEditor: PhotoEditorConfiguration = .init() #endif @@ -107,22 +113,14 @@ open class PickerConfiguration: BaseConfiguration { public var navigationDarkTintColor: UIColor = UIColor.white /// 相册列表配置 - public lazy var albumList : AlbumListConfiguration = { - return AlbumListConfiguration.init() - }() + public lazy var albumList : AlbumListConfiguration = .init() /// 照片列表配置 - public lazy var photoList: PhotoListConfiguration = { - return PhotoListConfiguration.init() - }() + public lazy var photoList: PhotoListConfiguration = .init() /// 预览界面配置 - public lazy var previewView: PreviewViewConfiguration = { - return PreviewViewConfiguration.init() - }() + public lazy var previewView: PreviewViewConfiguration = .init() /// 未授权提示界面相关配置 - public lazy var notAuthorized : NotAuthorizedConfiguration = { - return NotAuthorizedConfiguration.init() - }() + public lazy var notAuthorized : NotAuthorizedConfiguration = .init() } diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Config/PreviewViewConfiguration.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Config/PreviewViewConfiguration.swift index 76fa00ac..5c447001 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Config/PreviewViewConfiguration.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Config/PreviewViewConfiguration.swift @@ -14,21 +14,19 @@ public class PreviewViewConfiguration { /// 自定义视频Cell public var customVideoCellClass: PreviewVideoViewCell.Type? + /// 网络视频加载方式 + public var loadNetworkVideoMode: PhotoAsset.LoadNetworkVideoMode = .download { + didSet { PhotoManager.shared.loadNetworkVideoMode = loadNetworkVideoMode } + } + /// 背景颜色 - public lazy var backgroundColor : UIColor = { - return .white - }() + public lazy var backgroundColor : UIColor = .white /// 暗黑风格下背景颜色 - public lazy var backgroundDarkColor : UIColor = { - return .black - }() + public lazy var backgroundDarkColor : UIColor = .black /// 选择框配置 - public lazy var selectBox: SelectBoxConfiguration = { - let config = SelectBoxConfiguration.init() - return config - }() + public lazy var selectBox: SelectBoxConfiguration = .init() /// 视频播放类型 public var videoPlayType: PhotoPreviewViewController.VideoPlayType = .normal @@ -64,5 +62,5 @@ public class PreviewViewConfiguration { /// 暗黑模式下取消按钮图片名 public var cancelDarkImageName: String = "hx_picker_photolist_cancel" - public init() { } + public init() { PhotoManager.shared.loadNetworkVideoMode = loadNetworkVideoMode } } diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Controller/PhotoPickerController.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Controller/PhotoPickerController.swift index 24390cb8..2860069e 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Controller/PhotoPickerController.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Controller/PhotoPickerController.swift @@ -79,15 +79,15 @@ open class PhotoPickerController: UINavigationController { /// 相册列表控制器 public func albumViewController() -> AlbumViewController? { - return getViewController(for: AlbumViewController.self) as? AlbumViewController + getViewController(for: AlbumViewController.self) as? AlbumViewController } /// 照片选择控制器 public func pickerViewController() -> PhotoPickerViewController? { - return getViewController(for: PhotoPickerViewController.self) as? PhotoPickerViewController + getViewController(for: PhotoPickerViewController.self) as? PhotoPickerViewController } /// 照片预览控制器 public func previewViewController() -> PhotoPreviewViewController? { - return getViewController(for: PhotoPreviewViewController.self) as? PhotoPreviewViewController + getViewController(for: PhotoPreviewViewController.self) as? PhotoPreviewViewController } /// 当前处于的外部预览 @@ -95,12 +95,14 @@ open class PhotoPickerController: UINavigationController { /// 选择资源初始化 /// - Parameter config: 相关配置 - public convenience init(picker config: PickerConfiguration) { - self.init(config: config) + public convenience init(picker config: PickerConfiguration, + delegate: PhotoPickerControllerDelegate? = nil) { + self.init(config: config, delegate: delegate) } /// 选择资源初始化 /// - Parameter config: 相关配置 - public init(config: PickerConfiguration) { + public init(config: PickerConfiguration, + delegate: PhotoPickerControllerDelegate? = nil) { PhotoManager.shared.appearanceStyle = config.appearanceStyle PhotoManager.shared.createLanguageBundle(languageType: config.languageType) self.config = config @@ -111,6 +113,7 @@ open class PhotoPickerController: UINavigationController { singleVideo = true } super.init(nibName: nil, bundle: nil) + pickerDelegate = delegate var photoVC : UIViewController if config.albumShowMode == .normal { photoVC = AlbumViewController.init() @@ -127,12 +130,14 @@ open class PhotoPickerController: UINavigationController { /// - modalPresentationStyle: 默认 custom 样式,框架自带动画效果 public init(preview config: PickerConfiguration, currentIndex: Int, - modalPresentationStyle: UIModalPresentationStyle = .custom) { + modalPresentationStyle: UIModalPresentationStyle = .custom, + delegate: PhotoPickerControllerDelegate? = nil) { PhotoManager.shared.appearanceStyle = config.appearanceStyle PhotoManager.shared.createLanguageBundle(languageType: config.languageType) self.config = config isPreviewAsset = true super.init(nibName: nil, bundle: nil) + pickerDelegate = delegate let vc = PhotoPreviewViewController.init() vc.isExternalPreview = true vc.currentPreviewIndex = currentIndex @@ -199,6 +204,9 @@ open class PhotoPickerController: UINavigationController { public override func viewDidLoad() { super.viewDidLoad() + PhotoManager.shared.targetWidth = config.photoList.cell.targetWidth + PhotoManager.shared.indicatorType = config.indicatorType + PhotoManager.shared.loadNetworkVideoMode = config.previewView.loadNetworkVideoMode configColor() navigationBar.isTranslucent = config.navigationBarIsTranslucent selectOptions = config.selectOptions @@ -227,7 +235,10 @@ open class PhotoPickerController: UINavigationController { } public override var preferredStatusBarStyle: UIStatusBarStyle { - config.statusBarStyle + if PhotoManager.isDark { + return .lightContent + } + return config.statusBarStyle } public override var prefersStatusBarHidden: Bool { if config.prefersStatusBarHidden { @@ -609,17 +620,20 @@ extension PhotoPickerController { photoAsset.checkAdjustmentStatus { (isAdjusted, asset) in if isAdjusted { if asset.mediaType == .photo { - asset.requestImageData(iCloudHandler: nil, progressHandler: nil) { (sAsset, imageData, imageOrientation, info) in - sAsset.updateFileSize(imageData.count) - totalFileSize += sAsset.fileSize - total += 1 - if total == self.selectedAssetArray.count { - calculationCompletion(totalFileSize) - } - } failure: { (sAsset, info) in - total += 1 - if total == self.selectedAssetArray.count { - calculationCompletion(totalFileSize) + asset.requestImageData(iCloudHandler: nil, progressHandler: nil) { sAsset, result in + switch result { + case .success(let dataResult): + sAsset.updateFileSize(dataResult.imageData.count) + totalFileSize += sAsset.fileSize + total += 1 + if total == self.selectedAssetArray.count { + calculationCompletion(totalFileSize) + } + case .failure(_): + total += 1 + if total == self.selectedAssetArray.count { + calculationCompletion(totalFileSize) + } } } }else { @@ -631,7 +645,7 @@ extension PhotoPickerController { if total == self.selectedAssetArray.count { calculationCompletion(totalFileSize) } - } failure: { (sAsset, info) in + } failure: { (sAsset, info, error) in total += 1 if total == self.selectedAssetArray.count { calculationCompletion(totalFileSize) diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Controller/PhotoPickerControllerProtocol.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Controller/PhotoPickerControllerProtocol.swift index 79ef08ec..baf4ed93 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Controller/PhotoPickerControllerProtocol.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Controller/PhotoPickerControllerProtocol.swift @@ -80,6 +80,29 @@ public protocol PhotoPickerControllerDelegate: AnyObject { atIndex: Int) -> Bool #if HXPICKER_ENABLE_EDITOR + + /// 照片编辑器加载贴图标题资源 + /// - Parameters: + /// - pickerController: 对应的 PhotoPickerController + /// - photoEditorViewController: 对应的 PhotoEditorViewController + /// - loadTitleChartlet: 传入标题数组 + func pickerController(_ pickerController: PhotoPickerController, + loadTitleChartlet photoEditorViewController: PhotoEditorViewController, + response: @escaping EditorTitleChartletResponse) + + /// 照片编辑器加载贴图资源 + /// - Parameters: + /// - pickerController: 对应的 PhotoPickerController + /// - photoEditorViewController: 对应的 PhotoEditorViewController + /// - titleChartlet: 对应配置的 title + /// - titleIndex: 对应配置的 title 的位置索引 + /// - response: 传入 title索引 和 贴图数据 + func pickerController(_ pickerController: PhotoPickerController, + loadChartletList photoEditorViewController: PhotoEditorViewController, + titleChartlet: EditorChartlet, + titleIndex: Int, + response: @escaping EditorChartletListResponse) + /// 视频编辑器,将要点击工具栏音乐按钮 /// - Parameters: /// - pickerController: 对应的 PhotoPickerController @@ -96,6 +119,26 @@ public protocol PhotoPickerControllerDelegate: AnyObject { func pickerController(_ pickerController: PhotoPickerController, videoEditor videoEditorViewController: VideoEditorViewController, loadMusic completionHandler: @escaping ([VideoEditorMusicInfo]) -> Void) -> Bool + + /// 视频编辑器搜索配乐信息 + /// - Parameters: + /// - videoEditorViewController: 对应的 VideoEditorViewController + /// - text: 搜索的文字内容 + /// - completion: 传入配乐信息,是否需要加载更多 + func pickerController(_ pickerController: PhotoPickerController, + videoEditor videoEditorViewController: VideoEditorViewController, + didSearch text: String?, + completionHandler: @escaping ([VideoEditorMusicInfo], Bool) -> Void) + + /// 视频编辑器加载更多配乐信息 + /// - Parameters: + /// - videoEditorViewController: 对应的 VideoEditorViewController + /// - text: 搜索的文字内容 + /// - completion: 传入配乐信息,是否还有更多数据 + func pickerController(_ pickerController: PhotoPickerController, + videoEditor videoEditorViewController: VideoEditorViewController, + loadMore text: String?, + completionHandler: @escaping ([VideoEditorMusicInfo], Bool) -> Void) #endif /// Asset 编辑完后调用 @@ -125,6 +168,15 @@ public protocol PhotoPickerControllerDelegate: AnyObject { previewSingleClick photoAsset: PhotoAsset, atIndex: Int) + /// 预览界面长按操作 + /// - Parameters: + /// - pickerController: 对应的 PhotoPickerController + /// - photoAsset: 对应显示的 PhotoAsset 数据 + /// - atIndex: 对应显示的位置 + func pickerController(_ pickerController: PhotoPickerController, + previewLongPressClick photoAsset: PhotoAsset, + atIndex: Int) + /// 预览界面将要删除 Asset /// - Parameters: /// - pickerController: 对应的 PhotoPickerController @@ -238,12 +290,52 @@ public extension PhotoPickerControllerDelegate { func pickerController(_ pickerController: PhotoPickerController, shouldEditAsset photoAsset: PhotoAsset, atIndex: Int) -> Bool { true } #if HXPICKER_ENABLE_EDITOR + func pickerController(_ pickerController: PhotoPickerController, + loadTitleChartlet photoEditorViewController: PhotoEditorViewController, + response: @escaping EditorTitleChartletResponse) { + #if canImport(Kingfisher) + let titles = PhotoTools.defaultTitleChartlet() + response(titles) + #endif + } + func pickerController(_ pickerController: PhotoPickerController, + loadChartletList photoEditorViewController: PhotoEditorViewController, + titleChartlet: EditorChartlet, + titleIndex: Int, + response: @escaping EditorChartletListResponse) { + /// 默认加载这些贴图 + #if canImport(Kingfisher) + let chartletList = PhotoTools.defaultNetworkChartlet() + response(titleIndex, chartletList) + #endif + } func pickerController(_ pickerController: PhotoPickerController, videoEditorShouldClickMusicTool videoEditorViewController: VideoEditorViewController) -> Bool { true } func pickerController(_ pickerController: PhotoPickerController, videoEditor videoEditorViewController: VideoEditorViewController, - loadMusic completionHandler: @escaping ([VideoEditorMusicInfo]) -> Void) -> Bool { false } + loadMusic completionHandler: @escaping ([VideoEditorMusicInfo]) -> Void) -> Bool { + var infos: [VideoEditorMusicInfo] = [] + if let audioURL = URL(string: "http://tsnrhapp.oss-cn-hangzhou.aliyuncs.com/chartle/%E5%A4%A9%E5%A4%96%E6%9D%A5%E7%89%A9.mp3"), + let lrc = "天外来物".lrc { + let info = VideoEditorMusicInfo(audioURL: audioURL, lrc: lrc) + infos.append(info) + } + completionHandler(infos) + return false + } + func pickerController(_ pickerController: PhotoPickerController, + videoEditor videoEditorViewController: VideoEditorViewController, + didSearch text: String?, + completionHandler: @escaping ([VideoEditorMusicInfo], Bool) -> Void) { + completionHandler([], false) + } + func pickerController(_ pickerController: PhotoPickerController, + videoEditor videoEditorViewController: VideoEditorViewController, + loadMore text: String?, + completionHandler: @escaping ([VideoEditorMusicInfo], Bool) -> Void) { + completionHandler([], false) + } #endif func pickerController(_ pickerController: PhotoPickerController, didEditAsset photoAsset: PhotoAsset, atIndex: Int) { } @@ -254,6 +346,10 @@ public extension PhotoPickerControllerDelegate { previewSingleClick photoAsset: PhotoAsset, atIndex: Int) { } + func pickerController(_ pickerController: PhotoPickerController, + previewLongPressClick photoAsset: PhotoAsset, + atIndex: Int) { } + func pickerController(_ pickerController: PhotoPickerController, previewShouldDeleteAsset photoAsset: PhotoAsset, atIndex: Int) -> Bool { true } func pickerController(_ pickerController: PhotoPickerController, previewDidDeleteAsset photoAsset: PhotoAsset, atIndex: Int) { } diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Controller/PhotoPickerViewController+SwipeSelect.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Controller/PhotoPickerViewController+SwipeSelect.swift index 820a5a53..bad2bce9 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Controller/PhotoPickerViewController+SwipeSelect.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Controller/PhotoPickerViewController+SwipeSelect.swift @@ -236,12 +236,15 @@ extension PhotoPickerViewController { if item >= assets.count && !needOffset { return } + guard let pickerController = pickerController else { + return + } var showHUD = false - if let pickerController = pickerController { - let photoAsset = getPhotoAsset(for: item) - if photoAsset.isSelected != isSelected { - if isSelected { - if pickerController.canSelectAsset(for: photoAsset, showHUD: false) { + let photoAsset = getPhotoAsset(for: item) + if photoAsset.isSelected != isSelected { + if isSelected { + func addAsset(showTip: Bool) { + if pickerController.canSelectAsset(for: photoAsset, showHUD: showTip) { pickerController.addedPhotoAsset(photoAsset: photoAsset) if let cell = getCell(for: item) { cell.updateSelectedState(isSelected: isSelected, animated: false) @@ -249,18 +252,30 @@ extension PhotoPickerViewController { }else { showHUD = true } - }else { - pickerController.removePhotoAsset(photoAsset: photoAsset) - if let cell = getCell(for: item) { - cell.updateSelectedState(isSelected: isSelected, animated: false) + } + let inICloud = photoAsset.checkICloundStatus(allowSyncPhoto: pickerController.config.allowSyncICloudWhenSelectPhoto, completion: { isSuccess in + if isSuccess { + addAsset(showTip: true) } + }) + if inICloud { + swipeSelectPanGR?.isEnabled = false + clearSwipeSelectData() + swipeSelectPanGR?.isEnabled = true + }else { + addAsset(showTip: false) + } + }else { + pickerController.removePhotoAsset(photoAsset: photoAsset) + if let cell = getCell(for: item) { + cell.updateSelectedState(isSelected: isSelected, animated: false) } } - bottomView.updateFinishButtonTitle() } - if pickerController!.selectArrayIsFull() && showHUD { + bottomView.updateFinishButtonTitle() + if pickerController.selectArrayIsFull() && showHUD { swipeSelectPanGR?.isEnabled = false - ProgressHUD.showWarning(addedTo: navigationController?.view, text: String.init(format: "已达到最大选择数".localized, arguments: [pickerController!.config.maximumSelectedPhotoCount]), animated: true, delayHide: 1.5) + ProgressHUD.showWarning(addedTo: navigationController?.view, text: String.init(format: "已达到最大选择数".localized, arguments: [pickerController.config.maximumSelectedPhotoCount]), animated: true, delayHide: 1.5) clearSwipeSelectData() swipeSelectPanGR?.isEnabled = true } diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Controller/PhotoPickerViewController.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Controller/PhotoPickerViewController.swift index f7dce18b..887f20cc 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Controller/PhotoPickerViewController.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Controller/PhotoPickerViewController.swift @@ -96,7 +96,7 @@ public class PhotoPickerViewController: BaseViewController { return titleLabel }() lazy var titleView: AlbumTitleView = { - let titleView = AlbumTitleView.init(config: config.titleViewConfig) + let titleView = AlbumTitleView.init(config: config.titleView) titleView.addTarget(self, action: #selector(didTitleViewClick(control:)), for: .touchUpInside) return titleView }() @@ -703,25 +703,27 @@ extension PhotoPickerViewController: UICollectionViewDelegate { } } func openEditor(_ photoAsset: PhotoAsset, _ cell: PhotoPickerBaseViewCell?) { - #if HXPICKER_ENABLE_EDITOR if photoAsset.mediaType == .video { openVideoEditor(photoAsset: photoAsset, coverImage: cell?.imageView.image) }else { openPhotoEditor(photoAsset: photoAsset) } - #endif } @discardableResult func openPhotoEditor(photoAsset: PhotoAsset) -> Bool { + guard let pickerController = pickerController, + photoAsset.mediaType == .photo else { + return false + } + if !pickerController.shouldEditAsset(photoAsset: photoAsset, atIndex: assets.firstIndex(of: photoAsset) ?? 0) { + return false + } #if HXPICKER_ENABLE_EDITOR && HXPICKER_ENABLE_PICKER - if let pickerController = pickerController, photoAsset.mediaType == .photo , - pickerController.config.editorOptions.contains(.photo) { - if !pickerController.shouldEditAsset(photoAsset: photoAsset, atIndex: assets.firstIndex(of: photoAsset) ?? 0) { - return false - } + if pickerController.config.editorOptions.contains(.photo) { let config = pickerController.config.photoEditor config.languageType = pickerController.config.languageType config.appearanceStyle = pickerController.config.appearanceStyle + config.indicatorType = pickerController.config.indicatorType let photoEditorVC = PhotoEditorViewController.init(photoAsset: photoAsset, editResult: photoAsset.photoEdit, config: config) photoEditorVC.delegate = self navigationController?.pushViewController(photoEditorVC, animated: true) @@ -732,12 +734,14 @@ extension PhotoPickerViewController: UICollectionViewDelegate { } @discardableResult func openVideoEditor(photoAsset: PhotoAsset, coverImage: UIImage? = nil) -> Bool { + guard let pickerController = pickerController, photoAsset.mediaType == .video else { + return false + } + if !pickerController.shouldEditAsset(photoAsset: photoAsset, atIndex: assets.firstIndex(of: photoAsset) ?? 0) { + return false + } #if HXPICKER_ENABLE_EDITOR && HXPICKER_ENABLE_PICKER - if let pickerController = pickerController, photoAsset.mediaType == .video , - pickerController.config.editorOptions.contains(.video) { - if !pickerController.shouldEditAsset(photoAsset: photoAsset, atIndex: assets.firstIndex(of: photoAsset) ?? 0) { - return false - } + if pickerController.config.editorOptions.contains(.video) { let isExceedsTheLimit = pickerController.videoDurationExceedsTheLimit(photoAsset: photoAsset) let config: VideoEditorConfiguration if isExceedsTheLimit { @@ -749,6 +753,7 @@ extension PhotoPickerViewController: UICollectionViewDelegate { } config.languageType = pickerController.config.languageType config.appearanceStyle = pickerController.config.appearanceStyle + config.indicatorType = pickerController.config.indicatorType let videoEditorVC = VideoEditorViewController.init(photoAsset: photoAsset, editResult: photoAsset.videoEdit, config: config) videoEditorVC.coverImage = coverImage; videoEditorVC.delegate = self @@ -806,6 +811,16 @@ extension PhotoPickerViewController: PhotoEditorViewControllerDelegate { bottomView.updateFinishButtonTitle() } } + public func photoEditorViewController(_ photoEditorViewController: PhotoEditorViewController, loadTitleChartlet response: @escaping ([EditorChartlet]) -> Void) { + if let pickerController = pickerController { + pickerController.pickerDelegate?.pickerController(pickerController, loadTitleChartlet: photoEditorViewController, response: response) + } + } + public func photoEditorViewController(_ photoEditorViewController: PhotoEditorViewController, titleChartlet: EditorChartlet, titleIndex: Int, loadChartletList response: @escaping (Int, [EditorChartlet]) -> Void) { + if let pickerController = pickerController { + pickerController.pickerDelegate?.pickerController(pickerController, loadChartletList: photoEditorViewController, titleChartlet: titleChartlet, titleIndex: titleIndex, response: response) + } + } public func photoEditorViewController(didCancel photoEditorViewController: PhotoEditorViewController) { } @@ -826,6 +841,16 @@ extension PhotoPickerViewController: VideoEditorViewControllerDelegate { } return false } + public func videoEditorViewController(_ videoEditorViewController: VideoEditorViewController, didSearch text: String?, completionHandler: @escaping ([VideoEditorMusicInfo], Bool) -> Void) { + if let pickerController = pickerController { + pickerController.pickerDelegate?.pickerController(pickerController, videoEditor: videoEditorViewController, didSearch: text, completionHandler: completionHandler) + } + } + public func videoEditorViewController(_ videoEditorViewController: VideoEditorViewController, loadMore text: String?, completionHandler: @escaping ([VideoEditorMusicInfo], Bool) -> Void) { + if let pickerController = pickerController { + pickerController.pickerDelegate?.pickerController(pickerController, videoEditor: videoEditorViewController, loadMore: text, completionHandler: completionHandler) + } + } public func videoEditorViewController(_ videoEditorViewController: VideoEditorViewController, didFinish result: VideoEditResult) { let photoAsset = videoEditorViewController.photoAsset! photoAsset.videoEdit = result @@ -852,12 +877,21 @@ extension PhotoPickerViewController: VideoEditorViewControllerDelegate { } public func videoEditorViewController(didFinishWithUnedited videoEditorViewController: VideoEditorViewController) { let photoAsset = videoEditorViewController.photoAsset! + let beforeHasEdit = photoAsset.videoEdit != nil + photoAsset.videoEdit = nil + if beforeHasEdit { + pickerController?.didEditAsset(photoAsset: photoAsset, atIndex: assets.firstIndex(of: photoAsset) ?? 0) + } if (photoAsset.mediaType == .video && videoLoadSingleCell) || !isMultipleSelect { if pickerController!.canSelectAsset(for: photoAsset, showHUD: true) { pickerController!.singleFinishCallback(for: photoAsset) } return } + if beforeHasEdit { + let cell = getCell(for: photoAsset) + cell?.photoAsset = photoAsset + } if !photoAsset.isSelected { if pickerController!.addedPhotoAsset(photoAsset: photoAsset) { updateCellSelectedTitle() @@ -1088,16 +1122,26 @@ extension PhotoPickerViewController: PhotoPickerViewCellDelegate { // 选中 #if HXPICKER_ENABLE_EDITOR if cell.photoAsset.mediaType == .video && - pickerController!.videoDurationExceedsTheLimit(photoAsset: cell.photoAsset){ + pickerController!.videoDurationExceedsTheLimit(photoAsset: cell.photoAsset) && pickerController!.config.editorOptions.isVideo { if pickerController!.canSelectAsset(for: cell.photoAsset, showHUD: true) { openVideoEditor(photoAsset: cell.photoAsset, coverImage: cell.imageView.image) } return } #endif - if pickerController!.addedPhotoAsset(photoAsset: cell.photoAsset) { - cell.updateSelectedState(isSelected: true, animated: true) - updateCellSelectedTitle() + func addAsset() { + if pickerController!.addedPhotoAsset(photoAsset: cell.photoAsset) { + cell.updateSelectedState(isSelected: true, animated: true) + updateCellSelectedTitle() + } + } + let inICloud = cell.photoAsset.checkICloundStatus(allowSyncPhoto: pickerController!.config.allowSyncICloudWhenSelectPhoto, completion: { isSuccess in + if isSuccess { + addAsset() + } + }) + if !inICloud { + addAsset() } } bottomView.updateFinishButtonTitle() diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Controller/PhotoPreviewViewController.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Controller/PhotoPreviewViewController.swift index 13610947..ca15a1dc 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Controller/PhotoPreviewViewController.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Controller/PhotoPreviewViewController.swift @@ -175,6 +175,9 @@ public class PhotoPreviewViewController: BaseViewController { return .fade } public override var preferredStatusBarStyle: UIStatusBarStyle { + if PhotoManager.isDark { + return .lightContent + } return pickerController?.config.statusBarStyle ?? .default } public override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { @@ -185,7 +188,6 @@ public class PhotoPreviewViewController: BaseViewController { } } } - deinit { NotificationCenter.default.removeObserver(self) } @@ -387,22 +389,39 @@ extension PhotoPreviewViewController { // 选中 #if HXPICKER_ENABLE_EDITOR if photoAsset.mediaType == .video && - pickerController!.videoDurationExceedsTheLimit(photoAsset: photoAsset) { + pickerController!.videoDurationExceedsTheLimit(photoAsset: photoAsset) && + pickerController!.config.editorOptions.isVideo { if pickerController!.canSelectAsset(for: photoAsset, showHUD: true) { openEditor(photoAsset) } return } #endif - if pickerController!.addedPhotoAsset(photoAsset: photoAsset) { - canUpdate = true - if config.bottomView.showSelectedView && isMultipleSelect && config.showBottomView { - bottomView.selectedView.insertPhotoAsset(photoAsset: photoAsset) + func addAsset() { + if pickerController!.addedPhotoAsset(photoAsset: photoAsset) { + canUpdate = true + if config.bottomView.showSelectedView && isMultipleSelect && config.showBottomView { + bottomView.selectedView.insertPhotoAsset(photoAsset: photoAsset) + } + if beforeIsEmpty { + bottomNeedAnimated = true + } } - if beforeIsEmpty { - bottomNeedAnimated = true + } + let inICloud = photoAsset.checkICloundStatus(allowSyncPhoto: pickerController!.config.allowSyncICloudWhenSelectPhoto) { isSuccess in + if isSuccess { + addAsset() + if canUpdate { + self.updateSelectBox(photoAsset: photoAsset, + isSelected: isSelected, + pickerUpdateCell: pickerUpdateCell, + bottomNeedAnimated: bottomNeedAnimated) + } } } + if !inICloud { + addAsset() + } }else { // 取消选中 pickerController?.removePhotoAsset(photoAsset: photoAsset) @@ -425,28 +444,38 @@ extension PhotoPreviewViewController { canUpdate = true } if canUpdate { - if config.bottomView.showSelectedView && isMultipleSelect && config.showBottomView { - if bottomNeedAnimated { - UIView.animate(withDuration: 0.25) { - self.configBottomViewFrame() - self.bottomView.layoutSubviews() - } - }else { - configBottomViewFrame() + updateSelectBox(photoAsset: photoAsset, + isSelected: isSelected, + pickerUpdateCell: pickerUpdateCell, + bottomNeedAnimated: bottomNeedAnimated) + } + } + + func updateSelectBox(photoAsset: PhotoAsset, + isSelected: Bool, + pickerUpdateCell: Bool, + bottomNeedAnimated: Bool) { + if config.bottomView.showSelectedView && isMultipleSelect && config.showBottomView { + if bottomNeedAnimated { + UIView.animate(withDuration: 0.25) { + self.configBottomViewFrame() + self.bottomView.layoutSubviews() } + }else { + configBottomViewFrame() } - updateSelectBox(isSelected, photoAsset: photoAsset) - selectBoxControl.isSelected = isSelected - delegate?.previewViewController(self, didSelectBox: photoAsset, isSelected: isSelected, updateCell: pickerUpdateCell) - if config.showBottomView { - bottomView.updateFinishButtonTitle() - } - selectBoxControl.layer.removeAnimation(forKey: "SelectControlAnimation") - let keyAnimation = CAKeyframeAnimation.init(keyPath: "transform.scale") - keyAnimation.duration = 0.3 - keyAnimation.values = [1.2, 0.8, 1.1, 0.9, 1.0] - selectBoxControl.layer.add(keyAnimation, forKey: "SelectControlAnimation") } + updateSelectBox(isSelected, photoAsset: photoAsset) + selectBoxControl.isSelected = isSelected + delegate?.previewViewController(self, didSelectBox: photoAsset, isSelected: isSelected, updateCell: pickerUpdateCell) + if config.showBottomView { + bottomView.updateFinishButtonTitle() + } + selectBoxControl.layer.removeAnimation(forKey: "SelectControlAnimation") + let keyAnimation = CAKeyframeAnimation.init(keyPath: "transform.scale") + keyAnimation.duration = 0.3 + keyAnimation.values = [1.2, 0.8, 1.1, 0.9, 1.0] + selectBoxControl.layer.add(keyAnimation, forKey: "SelectControlAnimation") } func updateSelectBox(_ isSelected: Bool, photoAsset: PhotoAsset) { @@ -615,7 +644,7 @@ extension PhotoPreviewViewController: PhotoPreviewViewCellDelegate { if currentCell?.photoAsset.mediaType == .video && config.singleClickCellAutoPlayVideo { currentCell?.scrollContentView.videoView.startPlay() } - videoCell?.hiddenToolView() + videoCell?.hideToolView() } if config.showBottomView { UIView.animate(withDuration: 0.25) { @@ -628,6 +657,11 @@ extension PhotoPreviewViewController: PhotoPreviewViewCellDelegate { pickerController.pickerDelegate?.pickerController(pickerController, previewSingleClick: cell.photoAsset, atIndex: currentPreviewIndex) } } + func cell(longPress cell: PhotoPreviewViewCell) { + if let pickerController = pickerController { + pickerController.pickerDelegate?.pickerController(pickerController, previewLongPressClick: cell.photoAsset, atIndex: currentPreviewIndex) + } + } func photoCell(networkImagedownloadSuccess photoCell: PhotoPreviewViewCell) { #if canImport(Kingfisher) @@ -662,35 +696,36 @@ extension PhotoPreviewViewController: PhotoPickerBottomViewDelegate { return } #if HXPICKER_ENABLE_EDITOR && HXPICKER_ENABLE_PICKER - if photoAsset.mediaType == .video { + guard let pickerConfig = pickerController?.config else { + return + } + if photoAsset.mediaType == .video && pickerConfig.editorOptions.isVideo { let cell = getCell(for: currentPreviewIndex) cell?.scrollContentView.stopVideo() - if let config = pickerController?.config { - let videoEditorConfig: VideoEditorConfiguration - let isExceedsTheLimit = pickerController?.videoDurationExceedsTheLimit(photoAsset: photoAsset) - if isExceedsTheLimit == true { - videoEditorConfig = config.videoEditor.mutableCopy() as! VideoEditorConfiguration - videoEditorConfig.defaultState = .cropping - videoEditorConfig.mustBeTailored = true - }else { - videoEditorConfig = config.videoEditor - } - videoEditorConfig.languageType = config.languageType - videoEditorConfig.appearanceStyle = config.appearanceStyle - let videoEditorVC = VideoEditorViewController.init(photoAsset: photoAsset, editResult: photoAsset.videoEdit, config: videoEditorConfig) - videoEditorVC.coverImage = cell?.scrollContentView.imageView.image - videoEditorVC.delegate = self - navigationController?.pushViewController(videoEditorVC, animated: true) - } - }else { - if let config = pickerController?.config { - let photoEditorConfig = config.photoEditor - photoEditorConfig.languageType = config.languageType - photoEditorConfig.appearanceStyle = config.appearanceStyle - let photoEditorVC = PhotoEditorViewController.init(photoAsset: photoAsset, editResult: photoAsset.photoEdit, config: photoEditorConfig) - photoEditorVC.delegate = self - navigationController?.pushViewController(photoEditorVC, animated: true) - } + let videoEditorConfig: VideoEditorConfiguration + let isExceedsTheLimit = pickerController?.videoDurationExceedsTheLimit(photoAsset: photoAsset) + if isExceedsTheLimit == true { + videoEditorConfig = pickerConfig.videoEditor.mutableCopy() as! VideoEditorConfiguration + videoEditorConfig.defaultState = .cropping + videoEditorConfig.mustBeTailored = true + }else { + videoEditorConfig = pickerConfig.videoEditor + } + videoEditorConfig.languageType = pickerConfig.languageType + videoEditorConfig.appearanceStyle = pickerConfig.appearanceStyle + videoEditorConfig.indicatorType = pickerConfig.indicatorType + let videoEditorVC = VideoEditorViewController.init(photoAsset: photoAsset, editResult: photoAsset.videoEdit, config: videoEditorConfig) + videoEditorVC.coverImage = cell?.scrollContentView.imageView.image + videoEditorVC.delegate = self + navigationController?.pushViewController(videoEditorVC, animated: true) + }else if pickerConfig.editorOptions.isPhoto { + let photoEditorConfig = pickerConfig.photoEditor + photoEditorConfig.languageType = pickerConfig.languageType + photoEditorConfig.appearanceStyle = pickerConfig.appearanceStyle + photoEditorConfig.indicatorType = pickerConfig.indicatorType + let photoEditorVC = PhotoEditorViewController.init(photoAsset: photoAsset, editResult: photoAsset.photoEdit, config: photoEditorConfig) + photoEditorVC.delegate = self + navigationController?.pushViewController(photoEditorVC, animated: true) } #endif } @@ -709,26 +744,39 @@ extension PhotoPreviewViewController: PhotoPickerBottomViewDelegate { let photoAsset = previewAssets[currentPreviewIndex] #if HXPICKER_ENABLE_EDITOR if photoAsset.mediaType == .video && - pickerController.videoDurationExceedsTheLimit(photoAsset: photoAsset) { + pickerController.videoDurationExceedsTheLimit(photoAsset: photoAsset) && + pickerController.config.editorOptions.isVideo { if pickerController.canSelectAsset(for: photoAsset, showHUD: true) { openEditor(photoAsset) } return } #endif - if !isMultipleSelect { - pickerController.singleFinishCallback(for: photoAsset) - }else { - if videoLoadSingleCell { + func addAsset() { + if !isMultipleSelect { if pickerController.canSelectAsset(for: photoAsset, showHUD: true) { pickerController.singleFinishCallback(for: photoAsset) } }else { - if pickerController.addedPhotoAsset(photoAsset: photoAsset) { - pickerController.finishCallback() + if videoLoadSingleCell { + if pickerController.canSelectAsset(for: photoAsset, showHUD: true) { + pickerController.singleFinishCallback(for: photoAsset) + } + }else { + if pickerController.addedPhotoAsset(photoAsset: photoAsset) { + pickerController.finishCallback() + } } } } + let inICloud = photoAsset.checkICloundStatus(allowSyncPhoto: pickerController.config.allowSyncICloudWhenSelectPhoto) { isSuccess in + if isSuccess { + addAsset() + } + } + if !inICloud { + addAsset() + } } func bottomView(_ bottomView: PhotoPickerBottomView, didOriginalButtonClick isOriginal: Bool) { delegate?.previewViewController(self, didOriginalButton: isOriginal) @@ -785,6 +833,9 @@ extension PhotoPreviewViewController: PhotoEditorViewControllerDelegate { let photoAsset = photoEditorViewController.photoAsset! let beforeHasEdit = photoAsset.photoEdit != nil photoAsset.photoEdit = nil; + if beforeHasEdit { + pickerController?.didEditAsset(photoAsset: photoAsset, atIndex: currentPreviewIndex) + } if !isMultipleSelect { if pickerController!.canSelectAsset(for: photoAsset, showHUD: true) { pickerController?.singleFinishCallback(for: photoAsset) @@ -795,11 +846,20 @@ extension PhotoPreviewViewController: PhotoEditorViewControllerDelegate { didSelectBoxControlClick() } if beforeHasEdit { - pickerController?.didEditAsset(photoAsset: photoAsset, atIndex: currentPreviewIndex) reloadCell(for: photoAsset) } delegate?.previewViewController(self, editAssetFinished: photoAsset) } + public func photoEditorViewController(_ photoEditorViewController: PhotoEditorViewController, loadTitleChartlet response: @escaping ([EditorChartlet]) -> Void) { + if let pickerController = pickerController { + pickerController.pickerDelegate?.pickerController(pickerController, loadTitleChartlet: photoEditorViewController, response: response) + } + } + public func photoEditorViewController(_ photoEditorViewController: PhotoEditorViewController, titleChartlet: EditorChartlet, titleIndex: Int, loadChartletList response: @escaping (Int, [EditorChartlet]) -> Void) { + if let pickerController = pickerController { + pickerController.pickerDelegate?.pickerController(pickerController, loadChartletList: photoEditorViewController, titleChartlet: titleChartlet, titleIndex: titleIndex, response: response) + } + } public func photoEditorViewController(didCancel photoEditorViewController: PhotoEditorViewController) { } @@ -820,6 +880,16 @@ extension PhotoPreviewViewController: VideoEditorViewControllerDelegate { } return false } + public func videoEditorViewController(_ videoEditorViewController: VideoEditorViewController, didSearch text: String?, completionHandler: @escaping ([VideoEditorMusicInfo], Bool) -> Void) { + if let pickerController = pickerController { + pickerController.pickerDelegate?.pickerController(pickerController, videoEditor: videoEditorViewController, didSearch: text, completionHandler: completionHandler) + } + } + public func videoEditorViewController(_ videoEditorViewController: VideoEditorViewController, loadMore text: String?, completionHandler: @escaping ([VideoEditorMusicInfo], Bool) -> Void) { + if let pickerController = pickerController { + pickerController.pickerDelegate?.pickerController(pickerController, videoEditor: videoEditorViewController, loadMore: text, completionHandler: completionHandler) + } + } public func videoEditorViewController(_ videoEditorViewController: VideoEditorViewController, didFinish result: VideoEditResult) { let photoAsset = videoEditorViewController.photoAsset! photoAsset.videoEdit = result @@ -842,12 +912,20 @@ extension PhotoPreviewViewController: VideoEditorViewControllerDelegate { } public func videoEditorViewController(didFinishWithUnedited videoEditorViewController: VideoEditorViewController) { let photoAsset = videoEditorViewController.photoAsset! + let beforeHasEdit = photoAsset.videoEdit != nil + photoAsset.videoEdit = nil; + if beforeHasEdit { + pickerController?.didEditAsset(photoAsset: photoAsset, atIndex: currentPreviewIndex) + } if videoLoadSingleCell || !isMultipleSelect { if pickerController!.canSelectAsset(for: photoAsset, showHUD: true) { pickerController?.singleFinishCallback(for: photoAsset) } return } + if beforeHasEdit { + reloadCell(for: photoAsset) + } if !photoAsset.isSelected { didSelectBoxControlClick() } diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Extension/Picker+PhotoAsset.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Extension/Picker+PhotoAsset.swift index d427fd12..5972a709 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Extension/Picker+PhotoAsset.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Extension/Picker+PhotoAsset.swift @@ -28,4 +28,54 @@ extension PhotoAsset { } completion(false, self) } + + func checkICloundStatus(allowSyncPhoto : Bool, + completion: @escaping (Bool) -> Void) -> Bool { + guard let phAsset = phAsset else { + return false + } + if mediaType == .photo && !allowSyncPhoto { + return false + } + if downloadStatus != .succeed && phAsset.inICloud { + let keyWindow = UIApplication.shared.keyWindow + var loadingView: ProgressHUD? + if mediaType == .photo { + requestImageData { _, _ in + loadingView = ProgressHUD.showLoading(addedTo: keyWindow, text: "正在同步iCloud".localized + "...", animated: true) + } progressHandler: { _, progress in + loadingView?.updateText(text: "正在同步iCloud".localized + "(" + String(Int(progress * 100)) + "%)") + } resultHandler: { _, result in + switch result { + case .success(_): + ProgressHUD.hide(forView: keyWindow, animated: true) + loadingView = nil + completion(true) + case .failure(_): + ProgressHUD.hide(forView: keyWindow, animated: false) + ProgressHUD.showWarning(addedTo: keyWindow, text: "iCloud同步失败".localized, animated: true, delayHide: 1.5) + loadingView = nil + completion(false) + } + } + }else if mediaType == .video { + requestAVAsset { _, _ in + loadingView = ProgressHUD.showLoading(addedTo: keyWindow, text: "正在同步iCloud".localized + "...", animated: true) + } progressHandler: { _, progress in + loadingView?.updateText(text: "正在同步iCloud".localized + "(" + String(Int(progress * 100)) + "%)") + } success: { _, _, _ in + ProgressHUD.hide(forView: keyWindow, animated: true) + loadingView = nil + completion(true) + } failure: { _, _, _ in + ProgressHUD.hide(forView: keyWindow, animated: false) + ProgressHUD.showWarning(addedTo: keyWindow, text: "iCloud同步失败".localized, animated: true, delayHide: 1.5) + loadingView = nil + completion(false) + } + } + return true + } + return false + } } diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Model/LocalAsset.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Model/LocalAsset.swift index d2dd8f1a..cb91a77c 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Model/LocalAsset.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Model/LocalAsset.swift @@ -37,3 +37,68 @@ public struct LocalVideoAsset { self.duration = duration } } + +extension LocalImageAsset: Codable { + enum CodingKeys: CodingKey { + case image + case imageData + case imageURL + } + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + if let data = try container.decodeIfPresent(Data.self, forKey: .image) { + image = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data) as? UIImage + }else { + image = nil + } + imageURL = try container.decodeIfPresent(URL.self, forKey: .imageURL) + imageData = try container.decodeIfPresent(Data.self, forKey: .imageData) + } + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + if let image = image { + if #available(iOS 11.0, *) { + let data = try NSKeyedArchiver.archivedData(withRootObject: image, requiringSecureCoding: false) + try container.encode(data, forKey: .image) + } else { + let data = NSKeyedArchiver.archivedData(withRootObject: image) + try container.encode(data, forKey: .image) + } + } + try container.encode(imageURL, forKey: .imageURL) + try container.encode(imageData, forKey: .imageData) + } +} + + +extension LocalVideoAsset: Codable { + enum CodingKeys: CodingKey { + case videoURL + case image + case duration + } + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + videoURL = try container.decode(URL.self, forKey: .videoURL) + if let data = try container.decodeIfPresent(Data.self, forKey: .image) { + image = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data) as? UIImage + }else { + image = nil + } + duration = try container.decode(TimeInterval.self, forKey: .duration) + } + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(videoURL, forKey: .videoURL) + if let image = image { + if #available(iOS 11.0, *) { + let data = try NSKeyedArchiver.archivedData(withRootObject: image, requiringSecureCoding: false) + try container.encode(data, forKey: .image) + } else { + let data = NSKeyedArchiver.archivedData(withRootObject: image) + try container.encode(data, forKey: .image) + } + } + try container.encode(duration, forKey: .duration) + } +} diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Model/NetworkAsset.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Model/NetworkAsset.swift index f20a97e0..c54abc71 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Model/NetworkAsset.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Model/NetworkAsset.swift @@ -9,7 +9,7 @@ import UIKit #if canImport(Kingfisher) import Kingfisher -public struct NetworkImageAsset { +public struct NetworkImageAsset: Codable { /// 占位图 public var placeholder: String? @@ -95,3 +95,47 @@ public struct NetworkVideoAsset { } #endif } + +extension NetworkVideoAsset: Codable { + enum CodingKeys: CodingKey { + case videoURL + case duration + case coverImage + case fileSize + #if canImport(Kingfisher) + case coverImageURL + #endif + } + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + videoURL = try container.decode(URL.self, forKey: .videoURL) + duration = try container.decode(TimeInterval.self, forKey: .duration) + if let imageData = try container.decodeIfPresent(Data.self, forKey: .coverImage) { + coverImage = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(imageData) as? UIImage + }else { + coverImage = nil + } + fileSize = try container.decode(Int.self, forKey: .fileSize) + #if canImport(Kingfisher) + coverImageURL = try container.decodeIfPresent(URL.self, forKey: .coverImageURL) + #endif + } + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(videoURL, forKey: .videoURL) + try container.encode(duration, forKey: .duration) + if let image = coverImage { + if #available(iOS 11.0, *) { + let imageData = try NSKeyedArchiver.archivedData(withRootObject: image, requiringSecureCoding: false) + try container.encode(imageData, forKey: .coverImage) + } else { + let imageData = NSKeyedArchiver.archivedData(withRootObject: image) + try container.encode(imageData, forKey: .coverImage) + } + } + try container.encode(fileSize, forKey: .fileSize) + #if canImport(Kingfisher) + try container.encode(coverImageURL, forKey: .coverImageURL) + #endif + } +} diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Model/PhotoAsset+Codable.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Model/PhotoAsset+Codable.swift new file mode 100644 index 00000000..25cc8b78 --- /dev/null +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Model/PhotoAsset+Codable.swift @@ -0,0 +1,104 @@ +// +// PhotoAsset+Codable.swift +// HXPHPicker +// +// Created by Slience on 2021/7/27. +// + +import UIKit + +extension PhotoAsset { + struct Simplify: Codable { + public let phLocalIdentifier: String? + public let localImageAsset: LocalImageAsset? + public let localVideoAsset: LocalVideoAsset? + public let networkVideoAsset: NetworkVideoAsset? + + #if canImport(Kingfisher) + public let networkImageAsset: NetworkImageAsset? + #endif + + #if HXPICKER_ENABLE_EDITOR + /// 图片编辑数据 + public let photoEdit: PhotoEditResult? + + /// 视频编辑数据 + public let videoEdit: VideoEditResult? + #endif + } + + /// 编码 + /// - Returns: 编码之后的数据 + public func encode() -> Data? { + let simplify: Simplify + #if HXPICKER_ENABLE_EDITOR + #if canImport(Kingfisher) + simplify = Simplify(phLocalIdentifier: phAsset?.localIdentifier, + localImageAsset: localImageAsset, + localVideoAsset: localVideoAsset, + networkVideoAsset: networkVideoAsset, + networkImageAsset: networkImageAsset, + photoEdit: photoEdit, + videoEdit: videoEdit) + #else + simplify = Simplify(phLocalIdentifier: phAsset?.localIdentifier, + localImageAsset: localImageAsset, + localVideoAsset: localVideoAsset, + networkVideoAsset: networkVideoAsset, + photoEdit: photoEdit, + videoEdit: videoEdit) + #endif + #else + #if canImport(Kingfisher) + simplify = Simplify(phLocalIdentifier: phAsset?.localIdentifier, + localImageAsset: localImageAsset, + localVideoAsset: localVideoAsset, + networkVideoAsset: networkVideoAsset, + networkImageAsset: networkImageAsset) + #else + simplify = Simplify(phLocalIdentifier: phAsset?.localIdentifier, + localImageAsset: localImageAsset, + localVideoAsset: localVideoAsset, + networkVideoAsset: networkVideoAsset) + #endif + #endif + let encoder = JSONEncoder() + let data = try? encoder.encode(simplify) + return data + } + + /// 解码 + /// - Parameter data: 之前编码得到的数据 + /// - Returns: 对应的 PhotoAsset 对象 + public class func decoder(data: Data) -> PhotoAsset? { + var photoAsset: PhotoAsset? = nil + do { + let decoder = JSONDecoder() + let simplify = try decoder.decode(Simplify.self, from: data) + if let phLocalIdentifier = simplify.phLocalIdentifier { + if let phAsset = AssetManager.fetchAsset(withLocalIdentifier: phLocalIdentifier) { + photoAsset = PhotoAsset(asset: phAsset) + } + }else if let localImageAsset = simplify.localImageAsset { + photoAsset = PhotoAsset(localImageAsset: localImageAsset) + }else if let localVideoAsset = simplify.localVideoAsset { + photoAsset = PhotoAsset(localVideoAsset: localVideoAsset) + }else if let networkVideoAsset = simplify.networkVideoAsset { + photoAsset = PhotoAsset(networkVideoAsset: networkVideoAsset) + }else { + #if canImport(Kingfisher) + if let networkImageAsset = simplify.networkImageAsset { + photoAsset = PhotoAsset(networkImageAsset: networkImageAsset) + } + #endif + } + #if HXPICKER_ENABLE_EDITOR + photoAsset?.photoEdit = simplify.photoEdit + photoAsset?.videoEdit = simplify.videoEdit + #endif + } catch { + print(error) + } + return photoAsset + } +} diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Model/PhotoAsset+Network.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Model/PhotoAsset+Network.swift index a48e5fb5..3562ad28 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Model/PhotoAsset+Network.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Model/PhotoAsset+Network.swift @@ -8,22 +8,25 @@ import UIKit #if canImport(Kingfisher) import Kingfisher - #endif public extension PhotoAsset { #if canImport(Kingfisher) /// 获取网络图片的地址,编辑过就是本地地址,未编辑就是网络地址 - /// - Parameter resultHandler: 地址、是否为网络地址 - func getNetworkImageURL(resultHandler: @escaping (URL?, Bool) -> Void) { + /// - Parameter resultHandler: 图片地址、是否为网络地址 + func getNetworkImageURL(resultHandler: AssetURLCompletion) { #if HXPICKER_ENABLE_EDITOR if let photoEdit = photoEdit { - resultHandler(photoEdit.editedImageURL, false) + resultHandler(.success(.init(url: photoEdit.editedImageURL, urlType: .local, mediaType: .photo))) return } #endif - resultHandler(networkImageAsset?.originalURL, true) + if let url = networkImageAsset?.originalURL { + resultHandler(.success(.init(url: url, urlType: .network, mediaType: .photo))) + }else { + resultHandler(.failure(.networkURLIsEmpty)) + } } /// 获取网络图片 @@ -60,14 +63,18 @@ public extension PhotoAsset { #endif /// 获取网络视频的地址,编辑过就是本地地址,未编辑就是网络地址 - /// - Parameter resultHandler: 地址、是否为网络地址 - func getNetworkVideoURL(resultHandler: @escaping (URL?, Bool) -> Void) { + /// - Parameter resultHandler: 视频地址、是否为网络地址 + func getNetworkVideoURL(resultHandler: AssetURLCompletion) { #if HXPICKER_ENABLE_EDITOR if let videoEdit = videoEdit { - resultHandler(videoEdit.editedURL, false) + resultHandler(.success(.init(url: videoEdit.editedURL, urlType: .local, mediaType: .video))) return } #endif - resultHandler(networkVideoAsset?.videoURL, true) + if let url = networkVideoAsset?.videoURL { + resultHandler(.success(.init(url: url, urlType: .network, mediaType: .video))) + }else { + resultHandler(.failure(.networkURLIsEmpty)) + } } } diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Model/PhotoAsset+Request.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Model/PhotoAsset+Request.swift index 88b0299c..8fcfb3a6 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Model/PhotoAsset+Request.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Model/PhotoAsset+Request.swift @@ -8,17 +8,22 @@ import UIKit import Photos - // MARK: Request Photo public extension PhotoAsset { + struct ImageDataResult { + let imageData: Data + let imageOrientation: UIImage.Orientation + let info: [AnyHashable : Any]? + } + /// 获取原始图片地址 /// 网络图片获取方法 getNetworkImageURL /// - Parameters: /// - fileURL: 指定图片的本地地址 /// - resultHandler: 获取结果 func requestImageURL(toFile fileURL:URL? = nil, - resultHandler: @escaping (URL?) -> Void) { + resultHandler: @escaping AssetURLCompletion) { if phAsset == nil { requestLocalImageURL(toFile: fileURL, resultHandler: resultHandler) return @@ -31,7 +36,7 @@ public extension PhotoAsset { func requestImage(completion: ((UIImage?, PhotoAsset) -> Void)?) -> PHImageRequestID? { #if HXPICKER_ENABLE_EDITOR if let photoEdit = photoEdit { - completion?(photoEdit.editedImage, self) + completion?(UIImage(contentsOfFile: photoEdit.editedImageURL.path), self) return nil } if let videoEdit = videoEdit { @@ -49,15 +54,16 @@ public extension PhotoAsset { options.resizeMode = .fast options.deliveryMode = .highQualityFormat options.isNetworkAccessAllowed = true - return AssetManager.requestImageData(for: phAsset!, version: isGifAsset ? .original : .current, iCloudHandler: nil, progressHandler: nil) { (imageData, dataUTI, imageOrientation, info, success) in - if let imageData = imageData { - var image = UIImage.init(data: imageData) + return AssetManager.requestImageData(for: phAsset!, version: isGifAsset ? .original : .current, iCloudHandler: nil, progressHandler: nil) { (result) in + switch result { + case .success(let dataResult): + var image = UIImage.init(data: dataResult.imageData) if image?.imageOrientation != UIImage.Orientation.up { image = image?.normalizedImage() } image = image?.scaleImage(toScale: 0.5) completion?(image, self) - }else { + case .failure(_): completion?(nil, self) } } @@ -100,35 +106,34 @@ public extension PhotoAsset { func requestImageData(filterEditor: Bool = false, iCloudHandler: PhotoAssetICloudHandler?, progressHandler: PhotoAssetProgressHandler?, - success: ((PhotoAsset, Data, UIImage.Orientation, [AnyHashable : Any]?) -> Void)?, - failure: PhotoAssetFailureHandler?) -> PHImageRequestID { + resultHandler: ((PhotoAsset, Result) -> Void)?) -> PHImageRequestID { #if HXPICKER_ENABLE_EDITOR if let photoEdit = photoEdit, !filterEditor { do { let imageData = try Data.init(contentsOf: photoEdit.editedImageURL) - success?(self, imageData, photoEdit.editedImage.imageOrientation, nil) + resultHandler?(self, .success(.init(imageData: imageData, imageOrientation: photoEdit.editedImage.imageOrientation, info: nil))) }catch { - failure?(self, nil) + resultHandler?(self, .failure(.init(info: nil, error: .invalidData))) } return 0 } if let videoEdit = videoEdit, !filterEditor { let imageData = PhotoTools.getImageData(for: videoEdit.coverImage) if let imageData = imageData { - success?(self, imageData, videoEdit.coverImage!.imageOrientation, nil) + resultHandler?(self, .success(.init(imageData: imageData, imageOrientation: videoEdit.coverImage!.imageOrientation, info: nil))) }else { - failure?(self, nil) + resultHandler?(self, .failure(.init(info: nil, error: .invalidData))) } return 0 } #endif if phAsset == nil { - requestlocalImageData { (imageData, photoAsset) in - if let imageData = imageData { - let image = UIImage.init(data: imageData) - success?(photoAsset, imageData, image!.imageOrientation, nil) - }else { - failure?(photoAsset, nil) + requestlocalImageData { photoAsset, result in + switch result { + case .success(let imageResult): + resultHandler?(photoAsset, .success(.init(imageData: imageResult.imageData, imageOrientation: imageResult.imageOrientation, info: nil))) + case .failure(let error): + resultHandler?(photoAsset, .failure(error)) } } return 0 @@ -138,28 +143,29 @@ public extension PhotoAsset { version = .original } downloadStatus = .downloading - return AssetManager.requestImageData(for: phAsset!, version: version, iCloudHandler: { (iCloudRequestID) in + return AssetManager.requestImageData(for: phAsset!, version: version) { iCloudRequestID in iCloudHandler?(self, iCloudRequestID) - }, progressHandler: { (progress, error, stop, info) in + } progressHandler: { progress, error, stop, info in self.downloadProgress = progress DispatchQueue.main.async { progressHandler?(self, progress) } - }, resultHandler: { (data, dataUTI, imageOrientation, info, downloadSuccess) in - if downloadSuccess { + } resultHandler: { result in + switch result { + case .success(let dataResult): self.downloadProgress = 1 self.downloadStatus = .succeed - success?(self, data!, imageOrientation, info) - }else { - if AssetManager.assetCancelDownload(for: info) { + resultHandler?(self, .success(.init(imageData: dataResult.imageData, imageOrientation: dataResult.imageOrientation, info: dataResult.info))) + case .failure(let error): + if AssetManager.assetCancelDownload(for: error.info) { self.downloadStatus = .canceled }else { self.downloadProgress = 0 self.downloadStatus = .failed } - failure?(self, info) + resultHandler?(self, .failure(error)) } - }) + } } } @@ -180,7 +186,7 @@ public extension PhotoAsset { success: ((PhotoAsset, PHLivePhoto, [AnyHashable : Any]?) -> Void)?, failure: PhotoAssetFailureHandler?) -> PHImageRequestID { if phAsset == nil { - failure?(self, nil) + failure?(self, nil, .invalidPHAsset) return 0 } downloadStatus = .downloading @@ -203,10 +209,44 @@ public extension PhotoAsset { self.downloadProgress = 0 self.downloadStatus = .failed } - failure?(self, info) + failure?(self, info, .requestFailed(info)) } } } + + func requestLivePhotoURL(completion: @escaping (Result) -> Void) { + #if HXPICKER_ENABLE_EDITOR + if let photoEdit = photoEdit { + completion(.success(.init(url: photoEdit.editedImageURL, urlType: .local, mediaType: .photo, livePhoto: nil))) + return + } + #endif + guard let phAsset = phAsset else { + completion(.failure(.invalidPHAsset)) + return + } + var imageURL: URL? + var videoURL: URL? + AssetManager.requestLivePhoto(contentURL: phAsset) { url in + imageURL = url + } videoHandler: { url in + videoURL = url + } completionHandler: { error in + if let error = error { + switch error { + case .allError(let imageError, let videoError): + completion(.failure(.exportLivePhotoURLFailed(imageError, videoError))) + case .imageError(let error): + completion(.failure(.exportLivePhotoImageURLFailed(error))) + case .videoError(let error): + completion(.failure(.exportLivePhotoVideoURLFailed(error))) + } + }else { + completion(.success(.init(url: imageURL!, urlType: .local, mediaType: .photo, livePhoto: .init(imageURL: imageURL!, videoURL: videoURL!)))) + } + } + + } } @@ -221,16 +261,12 @@ public extension PhotoAsset { /// - resultHandler: 获取结果 func requestVideoURL(toFile fileURL:URL? = nil, exportPreset: String? = nil, - resultHandler: @escaping (URL?) -> Void) { + resultHandler: @escaping AssetURLCompletion) { if phAsset == nil { - requestLocalVideoURL { (videoURL, photoAsset) in - resultHandler(videoURL) - } + requestLocalVideoURL(toFile: fileURL, resultHandler: resultHandler) return } - requestAssetVideoURL(toFile: fileURL, - exportPreset: exportPreset, - resultHandler: resultHandler) + requestAssetVideoURL(toFile: fileURL, exportPreset: exportPreset, resultHandler: resultHandler) } /// 请求AVAsset,如果资源在iCloud上会自动下载。如果需要更细节的处理请查看 PHAssetManager+Asset @@ -258,7 +294,7 @@ public extension PhotoAsset { }else if let networkVideoURL = networkVideoAsset?.videoURL { success?(self, AVAsset.init(url: networkVideoURL), nil) }else { - failure?(self, nil) + failure?(self, nil, .invalidPHAsset) } return 0 } @@ -270,19 +306,20 @@ public extension PhotoAsset { DispatchQueue.main.async { progressHandler?(self, progress) } - } resultHandler: { (avAsset, audioMix, info, downloadSuccess) in - if downloadSuccess { + } resultHandler: { (result) in + switch result { + case .success(let avResult): self.downloadProgress = 1 self.downloadStatus = .succeed - success?(self, avAsset!, info) - }else { - if AssetManager.assetCancelDownload(for: info) { + success?(self, avResult.avAsset, avResult.info) + case .failure(let error): + if AssetManager.assetCancelDownload(for: error.info) { self.downloadStatus = .canceled }else { self.downloadProgress = 0 self.downloadStatus = .failed } - failure?(self, info) + failure?(self, error.info, error.error) } } } diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Model/PhotoAsset+URL.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Model/PhotoAsset+URL.swift new file mode 100644 index 00000000..e88a1168 --- /dev/null +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Model/PhotoAsset+URL.swift @@ -0,0 +1,92 @@ +// +// PhotoAsset+URL.swift +// HXPHPicker +// +// Created by Slience on 2021/7/19. +// + +import UIKit + +public extension PhotoAsset { + + typealias AssetURLCompletion = (Result) -> Void + + struct AssetURLResult { + public enum URLType { + /// 本地 + case local + /// 网络 + case network + } + /// 地址 + public let url: URL + /// URL类型 + public let urlType: URLType + /// 媒体类型 + public let mediaType: PhotoAsset.MediaType + + /// LivePhoto里包含的资源 + /// selectOptions 需包含 livePhoto + public let livePhoto: LivePhotoResult? + + public struct LivePhotoResult { + /// 图片地址 + public let imageURL: URL + /// 视频地址 + public let videoURL: URL + } + + init(url: URL, + urlType: URLType, + mediaType: PhotoAsset.MediaType, + livePhoto: LivePhotoResult? = nil) { + self.url = url + self.urlType = urlType + self.mediaType = mediaType + self.livePhoto = livePhoto + } + } + + /// 获取url + /// - completion: result + func getAssetURL(completion: @escaping AssetURLCompletion) { + if mediaType == .photo { + if mediaSubType == .livePhoto { + getLivePhotoURL(completion: completion) + return + } + getImageURL(completion: completion) + }else { + getVideoURL(completion: completion) + } + } + + /// 获取图片url + /// - completion: result + func getImageURL(completion: @escaping AssetURLCompletion) { + #if canImport(Kingfisher) + if isNetworkAsset { + getNetworkImageURL(resultHandler: completion) + return + } + #endif + requestImageURL(resultHandler: completion) + } + + /// 获取视频url + /// - Parameters: + /// - exportPreset: 导出质量,不传获取的就是原始视频 + /// - completion: result + func getVideoURL(exportPreset: String? = nil, + completion: @escaping AssetURLCompletion) { + if isNetworkAsset { + getNetworkVideoURL(resultHandler: completion) + return + } + requestVideoURL(exportPreset: exportPreset, resultHandler: completion) + } + + func getLivePhotoURL(completion: @escaping AssetURLCompletion) { + requestLivePhotoURL(completion: completion) + } +} diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Model/PhotoAsset.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Model/PhotoAsset.swift index 1b134e15..df5f820f 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Model/PhotoAsset.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Model/PhotoAsset.swift @@ -11,7 +11,7 @@ import Photos public typealias PhotoAssetICloudHandler = (PhotoAsset, PHImageRequestID) -> Void public typealias PhotoAssetProgressHandler = (PhotoAsset, Double) -> Void -public typealias PhotoAssetFailureHandler = (PhotoAsset, [AnyHashable : Any]?) -> Void +public typealias PhotoAssetFailureHandler = (PhotoAsset, [AnyHashable : Any]?, AssetError) -> Void open class PhotoAsset: Equatable { @@ -411,7 +411,7 @@ extension PhotoAsset { func getOriginalImage() -> UIImage? { #if HXPICKER_ENABLE_EDITOR if let photoEdit = photoEdit { - return photoEdit.editedImage + return UIImage(contentsOfFile: photoEdit.editedImageURL.path) } if let videoEdit = videoEdit { return videoEdit.coverImage @@ -439,13 +439,16 @@ extension PhotoAsset { options.version = .original } var originalImage: UIImage? - AssetManager.requestImageData(for: phAsset!, options: options) { (imageData, dataUTI, orientation, info) in - if let imageData = imageData { - originalImage = UIImage.init(data: imageData) + AssetManager.requestImageData(for: phAsset!, options: options) { (result) in + switch result { + case .success(let dataResult): + originalImage = UIImage.init(data: dataResult.imageData) if let imageCount = originalImage?.images?.count, self.mediaSubType != .imageAnimated, self.phAsset!.isImageAnimated, imageCount > 1 { // 原始图片是动图,但是设置的是不显示动图,所以在这里处理一下 originalImage = originalImage?.images?.first } + default: + break } } return originalImage @@ -504,39 +507,47 @@ extension PhotoAsset { } return size } - func requestlocalImageData(resultHandler: @escaping (Data?, PhotoAsset) -> Void) { + func requestlocalImageData(resultHandler: ((PhotoAsset, Result) -> Void)?) { #if HXPICKER_ENABLE_EDITOR if let photoEdit = photoEdit { do { let imageData = try Data.init(contentsOf: photoEdit.editedImageURL) - resultHandler(imageData, self) + resultHandler?(self, .success(.init(imageData: imageData, imageOrientation: photoEdit.editedImage.imageOrientation, info: nil))) }catch { - resultHandler(nil, self) + resultHandler?(self, .failure(.init(info: nil, error: .invalidData))) } return } if let videoEdit = videoEdit { - resultHandler(PhotoTools.getImageData(for: videoEdit.coverImage), self) + if let imageData = PhotoTools.getImageData(for: videoEdit.coverImage) { + resultHandler?(self, .success(.init(imageData: imageData, imageOrientation: videoEdit.coverImage!.imageOrientation, info: nil))) + }else { + resultHandler?(self, .failure(.init(info: nil, error: .invalidData))) + } return } #endif if phAsset == nil { DispatchQueue.global().async { if let imageData = self.localImageAsset?.imageData { - resultHandler(imageData, self) + let image = UIImage(data: imageData) + DispatchQueue.main.async { + resultHandler?(self, .success(.init(imageData: imageData, imageOrientation: image!.imageOrientation, info: nil))) + } return }else if let imageURL = self.localImageAsset?.imageURL { do { let imageData = try Data.init(contentsOf: imageURL) + let image = UIImage(data: imageData) DispatchQueue.main.async { - resultHandler(imageData, self) + resultHandler?(self, .success(.init(imageData: imageData, imageOrientation: image!.imageOrientation, info: nil))) } return }catch { } - }else if let localImage = self.localImageAsset?.image { - let imageData = PhotoTools.getImageData(for: localImage) + }else if let localImage = self.localImageAsset?.image, + let imageData = PhotoTools.getImageData(for: localImage) { DispatchQueue.main.async { - resultHandler(imageData, self) + resultHandler?(self, .success(.init(imageData: imageData, imageOrientation: localImage.imageOrientation, info: nil))) } return }else { @@ -545,62 +556,68 @@ extension PhotoAsset { self.getNetworkImage { (image) in if let imageData = image?.kf.gifRepresentation() { DispatchQueue.main.async { - resultHandler(imageData, self) + resultHandler?(self, .success(.init(imageData: imageData, imageOrientation: image!.imageOrientation, info: nil))) } return } - let imageData = PhotoTools.getImageData(for: image) - DispatchQueue.main.async { - resultHandler(imageData, self) + if let imageData = PhotoTools.getImageData(for: image) { + DispatchQueue.main.async { + resultHandler?(self, .success(.init(imageData: imageData, imageOrientation: image!.imageOrientation, info: nil))) + } + return } } - return #endif } } DispatchQueue.main.async { - resultHandler(nil, self) + resultHandler?(self, .failure(.init(info: nil, error: .invalidData))) } } } } /// 获取本地图片地址 - func requestLocalImageURL(toFile fileURL:URL? = nil, resultHandler: @escaping (URL?) -> Void) { + func requestLocalImageURL(toFile fileURL:URL? = nil, resultHandler: @escaping AssetURLCompletion) { #if HXPICKER_ENABLE_EDITOR if let photoEdit = photoEdit { if let fileURL = fileURL { if PhotoTools.copyFile(at: photoEdit.editedImageURL, to: fileURL) { - resultHandler(fileURL) + resultHandler(.success(.init(url: fileURL, urlType: .local, mediaType: .photo))) }else { - resultHandler(nil) + resultHandler(.failure(.fileWriteFailed)) } return } - resultHandler(photoEdit.editedImageURL) + resultHandler(.success(.init(url: photoEdit.editedImageURL, urlType: .local, mediaType: .photo))) return } #endif if let localImageURL = getLocalImageAssetURL() { if let fileURL = fileURL { if PhotoTools.copyFile(at: localImageURL, to: fileURL) { - resultHandler(fileURL) + resultHandler(.success(.init(url: fileURL, urlType: .local, mediaType: .photo))) }else { - resultHandler(nil) + resultHandler(.failure(.fileWriteFailed)) } return } - resultHandler(localImageURL) + resultHandler(.success(.init(url: localImageURL, urlType: .local, mediaType: .photo))) return } DispatchQueue.global().async { if let imageData = self.getLocalImageData() { - let imageURL = PhotoTools.write(toFile: fileURL, imageData: imageData) - DispatchQueue.main.async { - resultHandler(imageURL) + if let imageURL = PhotoTools.write(toFile: fileURL, imageData: imageData) { + DispatchQueue.main.async { + resultHandler(.success(.init(url: imageURL, urlType: .local, mediaType: .photo))) + } + }else { + DispatchQueue.main.async { + resultHandler(.failure(.fileWriteFailed)) + } } }else { DispatchQueue.main.async { - resultHandler(nil) + resultHandler(.failure(.invalidData)) } } } @@ -613,7 +630,7 @@ extension PhotoAsset { func requestLocalImage(urlType: DonwloadURLType = .original, resultHandler: @escaping (UIImage?, PhotoAsset) -> Void) { #if HXPICKER_ENABLE_EDITOR if let photoEdit = photoEdit { - resultHandler(photoEdit.editedImage, self) + resultHandler(UIImage(contentsOfFile: photoEdit.editedImageURL.path), self) return } if let videoEdit = videoEdit { @@ -665,24 +682,24 @@ extension PhotoAsset { /// 获取本地/网络视频地址 func requestLocalVideoURL(toFile fileURL:URL? = nil, - resultHandler: @escaping (URL?, PhotoAsset) -> Void) { + resultHandler: AssetURLCompletion) { #if HXPICKER_ENABLE_EDITOR if let videoEdit = videoEdit { if let fileURL = fileURL { if PhotoTools.copyFile(at: videoEdit.editedURL, to: fileURL) { - resultHandler(fileURL, self) + resultHandler(.success(.init(url: fileURL, urlType: .local, mediaType: .video))) }else { - resultHandler(nil, self) + resultHandler(.failure(.fileWriteFailed)) } return } - resultHandler(videoEdit.editedURL, self) + resultHandler(.success(.init(url: videoEdit.editedURL, urlType: .network, mediaType: .video))) return } #endif if phAsset == nil { if mediaType == .photo { - resultHandler(nil, self) + resultHandler(.failure(.typeError)) }else { var videoURL: URL? = nil if isNetworkAsset { @@ -695,57 +712,82 @@ extension PhotoAsset { } if let fileURL = fileURL, let videoURL = videoURL { if PhotoTools.copyFile(at: videoURL, to: fileURL) { - resultHandler(fileURL, self) + resultHandler(.success(.init(url: fileURL, urlType: .local, mediaType: .video))) }else { - resultHandler(nil, self) + resultHandler(.failure(.fileWriteFailed)) } }else { - resultHandler(videoURL, self) + if let videoURL = videoURL { + resultHandler(.success(.init(url: videoURL, urlType: .local, mediaType: .video))) + }else { + if isNetworkAsset { + getNetworkVideoURL(resultHandler: resultHandler) + }else { + resultHandler(.failure(.localURLIsEmpty)) + } + } } } } } - func requestAssetImageURL(toFile fileURL:URL? = nil, filterEditor: Bool = false, resultHandler: @escaping (URL?) -> Void) { + func requestAssetImageURL(toFile fileURL:URL? = nil, filterEditor: Bool = false, resultHandler: @escaping AssetURLCompletion) { #if HXPICKER_ENABLE_EDITOR if let photoEdit = photoEdit, !filterEditor { if let fileURL = fileURL { if PhotoTools.copyFile(at: photoEdit.editedImageURL, to: fileURL) { - resultHandler(fileURL) + resultHandler(.success(.init(url: fileURL, urlType: .local, mediaType: .photo))) }else { - resultHandler(nil) + resultHandler(.failure(.fileWriteFailed)) } return } - resultHandler(photoEdit.editedImageURL) + resultHandler(.success(.init(url: photoEdit.editedImageURL, urlType: .local, mediaType: .photo))) return } if let videoEdit = videoEdit { DispatchQueue.global().async { - var imageURL: URL? if let imageData = PhotoTools.getImageData(for: videoEdit.coverImage) { - imageURL = PhotoTools.write(toFile: fileURL, imageData: imageData) - } - DispatchQueue.main.async { - resultHandler(imageURL) + if let imageURL = PhotoTools.write(toFile: fileURL, imageData: imageData) { + DispatchQueue.main.async { + resultHandler(.success(.init(url: imageURL, urlType: .local, mediaType: .photo))) + } + }else { + DispatchQueue.main.async { + resultHandler(.failure(.fileWriteFailed)) + } + } + }else { + DispatchQueue.main.async { + resultHandler(.failure(.invalidData)) + } } } return } #endif if phAsset == nil { - resultHandler(nil) + resultHandler(.failure(.invalidPHAsset)) return } if mediaType == .video { - requestImageData(iCloudHandler: nil, progressHandler: nil) { (photoAsset, imageData, imageOrientation, info) in - DispatchQueue.global().async { - let imageURL = PhotoTools.write(toFile: fileURL, imageData: imageData) - DispatchQueue.main.async { - resultHandler(imageURL) + requestImageData(iCloudHandler: nil, progressHandler: nil) { photoAsset, result in + switch result { + case .success(let dataResult): + let imageData = dataResult.imageData + DispatchQueue.global().async { + if let imageURL = PhotoTools.write(toFile: fileURL, imageData: imageData) { + DispatchQueue.main.async { + resultHandler(.success(.init(url: imageURL, urlType: .local, mediaType: .photo))) + } + }else { + DispatchQueue.main.async { + resultHandler(.failure(.fileWriteFailed)) + } + } } + case .failure(let error): + resultHandler(.failure(error.error)) } - } failure: { (photoAsset, ino) in - resultHandler(nil) } return } @@ -762,60 +804,86 @@ extension PhotoAsset { imageFileURL = PhotoTools.getTmpURL(for: suffix) } let isGif = phAsset!.isImageAnimated - AssetManager.requestImageURL(for: phAsset!, toFile: imageFileURL) { (imageURL) in - if let imageURL = imageURL, isGif, self.mediaSubType != .imageAnimated { - // 本质上是gif,需要变成静态图 - do { - let imageData = PhotoTools.getImageData(for: UIImage.init(contentsOfFile: imageURL.path)) - if FileManager.default.fileExists(atPath: imageURL.path) { - try FileManager.default.removeItem(at: imageURL) + AssetManager.requestImageURL(for: phAsset!, toFile: imageFileURL) { (result) in + switch result { + case .success(let imageURL): + if isGif && self.mediaSubType != .imageAnimated { + // 本质上是gif,需要变成静态图 + do { + let imageData = PhotoTools.getImageData(for: UIImage.init(contentsOfFile: imageURL.path)) + if FileManager.default.fileExists(atPath: imageURL.path) { + try FileManager.default.removeItem(at: imageURL) + } + try imageData?.write(to: imageURL) + resultHandler(.success(.init(url: imageURL, urlType: .local, mediaType: .photo))) + } catch { + resultHandler(.failure(.fileWriteFailed)) } - try imageData?.write(to: imageURL) - resultHandler(imageURL) - } catch { - resultHandler(nil) + }else { + resultHandler(.success(.init(url: imageURL, urlType: .local, mediaType: .photo))) } - }else { - resultHandler(imageURL) + case .failure(let error): + resultHandler(.failure(error)) } } } func requestAssetVideoURL(toFile fileURL:URL? = nil, exportPreset: String? = nil, - resultHandler: @escaping (URL?) -> Void) { + resultHandler: @escaping AssetURLCompletion) { #if HXPICKER_ENABLE_EDITOR if let videoEdit = videoEdit { if let fileURL = fileURL { if PhotoTools.copyFile(at: videoEdit.editedURL, to: fileURL) { - resultHandler(fileURL) + resultHandler(.success(.init(url: fileURL, urlType: .local, mediaType: .video))) }else { - resultHandler(nil) + resultHandler(.failure(.fileWriteFailed)) } return } - resultHandler(videoEdit.editedURL) + resultHandler(.success(.init(url: videoEdit.editedURL, urlType: .local, mediaType: .video))) return } #endif + guard let phAsset = phAsset else { + resultHandler(.failure(.invalidPHAsset)) + return + } let toFile = fileURL == nil ? PhotoTools.getVideoTmpURL() : fileURL! if let exportPreset = exportPreset { - AssetManager.exportVideoURL(forVideo: phAsset!, toFile: toFile, exportPreset: exportPreset) { (videoURL, error) in - resultHandler(nil) + AssetManager.exportVideoURL(forVideo: phAsset, toFile: toFile, exportPreset: exportPreset) { (result) in + switch result { + case .success(let videoURL): + resultHandler(.success(.init(url: videoURL, urlType: .local, mediaType: .video))) + case .failure(let error): + resultHandler(.failure(error.error)) + } } return } if mediaSubType == .livePhoto { - AssetManager.requestLivePhoto(videoURL: phAsset!, toFile: toFile) { (videoURL, error) in - resultHandler(videoURL) + let assetHandler: (URL?, Error?) -> Void = { videoURL, error in + if let videoURL = videoURL { + resultHandler(.success(.init(url: videoURL, urlType: .local, mediaType: .video))) + }else { + resultHandler(.failure(.exportFailed(error))) + } + } + AssetManager.requestLivePhoto(videoURL: phAsset, toFile: toFile) { (videoURL, error) in + assetHandler(videoURL, nil) } }else { if mediaType == .photo { - resultHandler(nil) + resultHandler(.failure(.typeError)) return } - AssetManager.requestVideoURL(for: phAsset!, toFile: toFile) { (videoURL) in - resultHandler(videoURL) + AssetManager.requestVideoURL(for: phAsset, toFile: toFile) { (result) in + switch result { + case .success(let videoURL): + resultHandler(.success(.init(url: videoURL, urlType: .local, mediaType: .video))) + case .failure(let error): + resultHandler(.failure(error)) + } } } } diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Model/PickerTypes.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Model/PickerTypes.swift index ee6deb4a..7448f03f 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Model/PickerTypes.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Model/PickerTypes.swift @@ -51,7 +51,7 @@ public enum SelectionTapAction: Equatable { case quickSelect /// 打开编辑器 - /// - 点击资源时会进入编辑界面 + /// - 点击资源时如果可以编辑的话,就会进入编辑界面 case openEditor } @@ -150,6 +150,14 @@ public extension PhotoAsset { case canceled //!< 取消下载 case failed //!< 下载失败 } + + /// 网络视频加载方式 + enum LoadNetworkVideoMode { + /// 先下载 + case download + /// 直接播放 + case play + } } public enum AlbumShowMode: Int { diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/PickerResult.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/PickerResult.swift index 71081ef4..c43956d6 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/PickerResult.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/PickerResult.swift @@ -49,7 +49,7 @@ public struct PickerResult { /// - videoURLHandler: 每一次获取视频地址都会触发 /// - completionHandler: 全部获取完成(失败的不会添加) public func getVideoURL(exportPreset: String = AVAssetExportPresetMediumQuality, - videoURLHandler: @escaping (URL?, PhotoAsset, Int) -> Void, + videoURLHandler: @escaping (Result, PhotoAsset, Int) -> Void, completionHandler: @escaping ([URL]) -> Void) { let group = DispatchGroup.init() let queue = DispatchQueue.init(label: "hxphpicker.get.videoURL") @@ -57,11 +57,14 @@ public struct PickerResult { for (index, photoAsset) in photoAssets.enumerated() { queue.async(group: group, execute: DispatchWorkItem.init(block: { let semaphore = DispatchSemaphore.init(value: 0) - photoAsset.requestVideoURL(exportPreset: exportPreset) { (videoURL) in - videoURLHandler(videoURL, photoAsset, index) - if let videoURL = videoURL { - videoURLs.append(videoURL) + photoAsset.getVideoURL(exportPreset: exportPreset) { result in + switch result { + case .success(let response): + videoURLs.append(response.url) + case .failure(_): + break } + videoURLHandler(result, photoAsset, index) semaphore.signal() } semaphore.wait() @@ -76,30 +79,32 @@ public struct PickerResult { /// 不包括网络资源,如果网络资源编辑过则会获取 /// - Parameters: /// - options: 获取的类型 - /// photo 视频获取的是封面图片地址,LivePhoto获取的URL为封面图片地址 - /// video LivePhoto获取的URL为内部视频地址,会过滤其他图片 - /// LivePhoto如果编辑过,获取的只会是编辑后的图片URL /// - completion: result public func getURLs(options: Options = .any, completion: @escaping ([URL]) -> Void) { var urls: [URL] = [] - getURLs(options: options) { (url, isNetwork, index, mediaType) in - if let url = url, !isNetwork { - urls.append(url) + getURLs(options: options) { result, photoAsset, index in + switch result { + case .success(let response): + if response.urlType == .local { + urls.append(response.url) + } + case .failure(_): + break } - } completionHandler: { (_) in + } completionHandler: { _ in completion(urls) } } - /// 获取已选资源的地址 + /// 获取已选资源的地址(原图) /// 包括网络图片 /// - Parameters: /// - options: 获取的类型 - /// - handler: 获取到url的回调 (地址,是否网络资源,对应的位置下标,类型) + /// - handler: 获取到url的回调 /// - completionHandler: 全部获取完成 public func getURLs(options: Options = .any, - urlReceivedHandler handler: @escaping (URL?, Bool, Int, PhotoAsset.MediaType) -> Void, + urlReceivedHandler handler: @escaping (Result, PhotoAsset, Int) -> Void, completionHandler: @escaping ([URL]) -> Void) { let group = DispatchGroup.init() let queue = DispatchQueue.init(label: "hxphpicker.request.urls") @@ -120,43 +125,29 @@ public struct PickerResult { mediatype = .photo } #endif + let resultHandler: PhotoAsset.AssetURLCompletion = { result in + switch result { + case .success(let respone): + urls.append(respone.url) + case .failure(_): + break + } + handler(result, photoAsset, index) + semaphore.signal() + } if mediatype == .photo { - #if canImport(Kingfisher) - if photoAsset.isNetworkAsset { - photoAsset.getNetworkImageURL { (url, isNetwork) in - if let url = url { - urls.append(url) - } - handler(url, isNetwork, index, .photo) - semaphore.signal() + if photoAsset.mediaSubType == .livePhoto { + photoAsset.getLivePhotoURL { result in + resultHandler(result) } - return - } - #endif - photoAsset.requestImageURL { (url) in - if let url = url { - urls.append(url) + }else { + photoAsset.getImageURL { result in + resultHandler(result) } - handler(url, false, index, .photo) - semaphore.signal() } }else { - if photoAsset.isNetworkAsset { - photoAsset.getNetworkVideoURL { (url, isNetwork) in - if let url = url { - urls.append(url) - } - handler(url, isNetwork, index, .video) - semaphore.signal() - } - return - } - photoAsset.requestVideoURL { (url) in - if let url = url { - urls.append(url) - } - handler(url, false, index, .video) - semaphore.signal() + photoAsset.getVideoURL { result in + resultHandler(result) } } semaphore.wait() diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Transition/PickerInteractiveTransition.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Transition/PickerInteractiveTransition.swift index 97f6a22f..026ab2ad 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Transition/PickerInteractiveTransition.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Transition/PickerInteractiveTransition.swift @@ -124,18 +124,31 @@ class PickerInteractiveTransition: UIPercentDrivenInteractiveTransition, UIGestu backgroundView.alpha = alpha let toVC = transitionContext?.viewController(forKey: .to) as? PhotoPickerViewController if !previewViewController.statusBarShouldBeHidden { - previewViewController.bottomView.alpha = alpha + let hasPreviewMask = previewViewController.bottomView.mask != nil + if hasPreviewMask { + var bottomViewAlpha = 1 - scale * 1.5 + if bottomViewAlpha < 0 { + bottomViewAlpha = 0 + } + previewViewController.bottomView.alpha = bottomViewAlpha + }else { + previewViewController.bottomView.alpha = alpha + } if type == .pop { - if previewViewController.bottomView.mask != nil { - let maskY = 70 * (1 - alpha) + var maskScale = 1 - scale * 2.85 + if maskScale < 0 { + maskScale = 0 + } + if hasPreviewMask { + let maskY = 70 * (1 - maskScale) let maskWidth = previewViewController.bottomView.width let maskHeight = previewViewController.bottomView.height - maskY previewViewController.bottomView.mask?.frame = CGRect(x: 0, y: maskY, width: maskWidth, height: maskHeight) } if toVC?.bottomView.mask != nil { - let maskY = 70 * alpha + let maskY = 70 * maskScale let maskWidth = previewViewController.bottomView.width - let maskHeight = 50 + UIDevice.bottomMargin + 70 * (1 - alpha) + let maskHeight = 50 + UIDevice.bottomMargin + 70 * (1 - maskScale) toVC?.bottomView.mask?.frame = CGRect(x: 0, y: maskY, width: maskWidth, height: maskHeight) } diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Transition/PickerTransition.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Transition/PickerTransition.swift index 0788ccb5..0bb4adc9 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Transition/PickerTransition.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Transition/PickerTransition.swift @@ -156,16 +156,18 @@ class PickerTransition: NSObject, UIViewControllerAnimatedTransitioning { let pickerController = previewVC?.pickerController let maskHeight = 50 + UIDevice.bottomMargin var previewShowSelectedView = false - if previewVC?.config.bottomView.showSelectedView == true && - pickerController?.config.selectMode == .multiple { - if pickerController?.selectedAssetArray.isEmpty == false { + if let previewVC = previewVC, + previewVC.config.bottomView.showSelectedView, + let pickerController = pickerController, + pickerController.config.selectMode == .multiple { + if pickerController.selectedAssetArray.isEmpty == false { previewShowSelectedView = true if !pickerShowParompt { let maskY: CGFloat = type == .push ? 70 : 0 let maskHeight: CGFloat = type == .push ? 50 + UIDevice.bottomMargin : 120 + UIDevice.bottomMargin let maskView = UIView.init(frame: CGRect(x: 0, y: maskY, width: contentView.width, height: maskHeight)) maskView.backgroundColor = .white - previewVC?.bottomView.mask = maskView + previewVC.bottomView.mask = maskView } } } @@ -176,29 +178,42 @@ class PickerTransition: NSObject, UIViewControllerAnimatedTransitioning { maskView.backgroundColor = .white pickerVC?.bottomView.mask = maskView } - UIView.animate(withDuration: transitionDuration(using: transitionContext) - 0.125) { + let duration = transitionDuration(using: transitionContext) + UIView.animate(withDuration: duration - 0.15) { if self.type == .push { - previewVC?.bottomView.alpha = 1 + contentView.backgroundColor = backgroundColor?.withAlphaComponent(1) + }else if self.type == .pop { + contentView.backgroundColor = backgroundColor?.withAlphaComponent(0) + } + } + if type == .push { + UIView.animate(withDuration: duration - 0.2, delay: 0, options: [.curveEaseIn]) { if previewVC?.bottomView.mask != nil { previewVC?.bottomView.mask?.frame = CGRect(x: 0, y: 0, width: contentView.width, height: maskHeight + 70) } if pickerVC?.bottomView.mask != nil { pickerVC?.bottomView.mask?.frame = CGRect(x: 0, y: 70, width: contentView.width, height: maskHeight) } - contentView.backgroundColor = backgroundColor?.withAlphaComponent(1) - }else if self.type == .pop { - previewVC?.bottomView.alpha = 0 + } completion: { _ in } + let alphaDuration = previewVC?.bottomView.mask == nil ? duration - 0.15 : 0.15 + UIView.animate(withDuration: alphaDuration) { + previewVC?.bottomView.alpha = 1 + } + }else if type == .pop { + UIView.animate(withDuration: duration - 0.2, delay: 0, options: [.curveLinear]) { if previewVC?.bottomView.mask != nil { previewVC?.bottomView.mask?.frame = CGRect(x: 0, y: 70, width: contentView.width, height: maskHeight + 70) } if pickerVC?.bottomView.mask != nil { pickerVC?.bottomView.mask?.frame = CGRect(x: 0, y: 0, width: contentView.width, height: maskHeight + 70) } - contentView.backgroundColor = backgroundColor?.withAlphaComponent(0) - } + } completion: { _ in } + UIView.animate(withDuration: duration - 0.15, delay: 0.125, options: []) { + previewVC?.bottomView.alpha = 0 + } completion: { _ in } } - UIView.animate(withDuration: transitionDuration(using: transitionContext), delay: 0, usingSpringWithDamping: 0.8, initialSpringVelocity: 0, options: [.layoutSubviews, .curveEaseOut]) { + UIView.animate(withDuration: duration, delay: 0, usingSpringWithDamping: 0.8, initialSpringVelocity: 0, options: [.layoutSubviews, .curveEaseOut]) { if self.type == .push { self.pushImageView.frame = rect }else if self.type == .pop { @@ -400,17 +415,24 @@ class PickerTransition: NSObject, UIViewControllerAnimatedTransitioning { let options = PHImageRequestOptions.init() options.resizeMode = .fast options.isSynchronous = false - requestID = AssetManager.requestImageData(for: asset, options: options) { (imageData, dataUTI, imageOrientation, info) in - if imageData != nil { - var image: UIImage? - if imageOrientation != .up { - image = UIImage.init(data: imageData!)?.normalizedImage() - }else { - image = UIImage.init(data: imageData!) - } - DispatchQueue.main.async { - self.pushImageView.image = image + requestID = AssetManager.requestImageData(for: asset, options: options) { (result) in + var info: [AnyHashable : Any]? = nil + switch result { + case .success(let dataResult): + info = dataResult.info + DispatchQueue.global().async { + var image: UIImage? + if dataResult.imageOrientation != .up { + image = UIImage.init(data: dataResult.imageData)?.normalizedImage() + }else { + image = UIImage.init(data: dataResult.imageData) + } + DispatchQueue.main.async { + self.pushImageView.image = image + } } + case .failure(let error): + info = error.info } if AssetManager.assetDownloadFinined(for: info) || AssetManager.assetCancelDownload(for: info){ diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Util/Picker+PhotoManager.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Util/Picker+PhotoManager.swift index 97fafd72..10f83736 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Util/Picker+PhotoManager.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Util/Picker+PhotoManager.swift @@ -13,6 +13,7 @@ import PhotosUI extension PhotoManager { struct AssociatedKeys { static var targetWidthKey: String = "targetWidth" + static var loadNetworkVideoMode: String = "loadNetworkVideoMode" } var targetWidth: CGFloat { get { @@ -22,6 +23,15 @@ extension PhotoManager { objc_setAssociatedObject(self, &AssociatedKeys.targetWidthKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) } } + /// 网络视频加载方式 + public var loadNetworkVideoMode: PhotoAsset.LoadNetworkVideoMode { + get { + objc_getAssociatedObject(self, &AssociatedKeys.loadNetworkVideoMode) as? PhotoAsset.LoadNetworkVideoMode ?? .download + } + set { + objc_setAssociatedObject(self, &AssociatedKeys.loadNetworkVideoMode, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) + } + } var cameraAlbumLocalIdentifierSelectOptions : PickerAssetOptions? { let identifierType = UserDefaults.standard.integer(forKey: PhotoManager.CameraAlbumLocal.identifierType.rawValue) diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Util/Picker+PhotoTools.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Util/Picker+PhotoTools.swift index 5a2cbda7..78d57220 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Util/Picker+PhotoTools.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/Util/Picker+PhotoTools.swift @@ -16,12 +16,10 @@ extension PhotoTools { /// - status: 权限类型 public class func showNotAuthorizedAlert(viewController : UIViewController? , status : PHAuthorizationStatus) { - if viewController == nil { - return - } + guard let vc = viewController else { return } if status == .denied || status == .restricted { - showAlert(viewController: viewController, title: "无法访问相册中照片".localized, message: "当前无照片访问权限,建议前往系统设置,\n允许访问「照片」中的「所有照片」。".localized, leftActionTitle: "取消".localized, leftHandler: {_ in }, rightActionTitle: "前往系统设置".localized) { (alertAction) in + showAlert(viewController: vc, title: "无法访问相册中照片".localized, message: "当前无照片访问权限,建议前往系统设置,\n允许访问「照片」中的「所有照片」。".localized, leftActionTitle: "取消".localized, leftHandler: {_ in }, rightActionTitle: "前往系统设置".localized) { (alertAction) in openSettingsURL() } } @@ -29,10 +27,8 @@ extension PhotoTools { /// 显示没有相机权限弹窗 public class func showNotCameraAuthorizedAlert(viewController : UIViewController?) { - if viewController == nil { - return - } - showAlert(viewController: viewController, title: "无法使用相机功能".localized, message: "请前往系统设置中,允许访问「相机」。".localized, leftActionTitle: "取消".localized, leftHandler: {_ in }, rightActionTitle: "前往系统设置".localized) { (alertAction) in + guard let vc = viewController else { return } + showAlert(viewController: vc, title: "无法使用相机功能".localized, message: "请前往系统设置中,允许访问「相机」。".localized, leftActionTitle: "取消".localized, leftHandler: {_ in }, rightActionTitle: "前往系统设置".localized) { (alertAction) in openSettingsURL() } } @@ -102,7 +98,6 @@ extension PhotoTools { } return albumName } - public class func getVideoCoverImage(for photoAsset: PhotoAsset, completionHandler: @escaping (PhotoAsset, UIImage) -> Void) { if photoAsset.mediaType == .video { var url: URL? @@ -190,6 +185,7 @@ extension PhotoTools { return String.init(format: "%dB", arguments: [bytes]) } } + /// 获取和微信主题一致的配置 public class func getWXPickerConfig(isMoment: Bool = false) -> PickerConfiguration { let config = PickerConfiguration.init() @@ -227,9 +223,9 @@ extension PhotoTools { config.photoList.cancelPosition = .left config.photoList.cancelType = .image - config.photoList.titleViewConfig.backgroundColor = UIColor.gray.withAlphaComponent(0.3) - config.photoList.titleViewConfig.arrowBackgroundColor = "#B2B2B2".color - config.photoList.titleViewConfig.arrowColor = "#2E2F30".color + config.photoList.titleView.backgroundColor = UIColor.gray.withAlphaComponent(0.3) + config.photoList.titleView.arrowBackgroundColor = "#B2B2B2".color + config.photoList.titleView.arrowColor = "#2E2F30".color config.photoList.cell.targetWidth = 250 config.photoList.cell.selectBox.selectedBackgroundColor = "#07C160".color @@ -289,15 +285,17 @@ extension PhotoTools { config.videoEditor.toolView.finishButtonDarkBackgroundColor = "#07C160".color config.videoEditor.toolView.toolSelectedColor = "#07C160".color config.videoEditor.toolView.musicSelectedColor = "#07C160".color + config.videoEditor.music.tintColor = "#07C160".color config.photoEditor.toolView.toolSelectedColor = "#07C160".color config.photoEditor.toolView.finishButtonBackgroundColor = "#07C160".color config.photoEditor.toolView.finishButtonDarkBackgroundColor = "#07C160".color config.photoEditor.cropConfimView.finishButtonBackgroundColor = "#07C160".color config.photoEditor.cropConfimView.finishButtonDarkBackgroundColor = "#07C160".color - config.photoEditor.cropConfig.aspectRatioSelectedColor = "#07C160".color - config.photoEditor.filterConfig = .init(infos: defaultFilters(), + config.photoEditor.cropping.aspectRatioSelectedColor = "#07C160".color + config.photoEditor.filter = .init(infos: defaultFilters(), selectedColor: "#07C160".color) + config.photoEditor.text.tintColor = "#07C160".color #endif config.notAuthorized.closeButtonImageName = "hx_picker_notAuthorized_close_dark" diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/View/Cell/PhotoPreviewViewCell.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/View/Cell/PhotoPreviewViewCell.swift index 60baf574..c4704036 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/View/Cell/PhotoPreviewViewCell.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/View/Cell/PhotoPreviewViewCell.swift @@ -13,6 +13,7 @@ import ImageIO protocol PhotoPreviewViewCellDelegate: NSObjectProtocol { func cell(singleTap cell: PhotoPreviewViewCell) + func cell(longPress cell: PhotoPreviewViewCell) func photoCell(networkImagedownloadSuccess photoCell: PhotoPreviewViewCell) func photoCell(networkImagedownloadFailed photoCell: PhotoPreviewViewCell) } @@ -46,6 +47,8 @@ open class PhotoPreviewViewCell: UICollectionViewCell, UIScrollViewDelegate { singleTap.require(toFail: doubleTap) scrollView.addGestureRecognizer(doubleTap) scrollView.addSubview(scrollContentView) + let longPress = UILongPressGestureRecognizer(target: self, action: #selector(longPressClick(longPress:))) + scrollView.addGestureRecognizer(longPress) return scrollView }() @@ -127,6 +130,11 @@ open class PhotoPreviewViewCell: UICollectionViewCell, UIScrollViewDelegate { scrollView.zoom(to: CGRect(x: touchPoint.x - zoomWidth / 2, y: touchPoint.y - zoomHeight / 2, width: zoomWidth, height: zoomHeight), animated: true) } } + @objc func longPressClick(longPress: UILongPressGestureRecognizer) { + if longPress.state == .began { + delegate?.cell(longPress: self) + } + } public func viewForZooming(in scrollView: UIScrollView) -> UIView? { return scrollContentView } diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/View/Cell/PreviewVideoControlViewCell.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/View/Cell/PreviewVideoControlViewCell.swift index 5f4d1bab..242bc199 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/View/Cell/PreviewVideoControlViewCell.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/View/Cell/PreviewVideoControlViewCell.swift @@ -64,7 +64,7 @@ public class PreviewVideoControlViewCell: PreviewVideoViewCell, PreviewVideoSlid maskLayer.isHidden = false } } - public override func hiddenToolView() { + public override func hideToolView() { if sliderView.alpha == 1 { UIView.animate(withDuration: 0.15) { self.sliderView.alpha = 0 @@ -78,6 +78,16 @@ public class PreviewVideoControlViewCell: PreviewVideoViewCell, PreviewVideoSlid maskLayer.isHidden = true } } + public override func showMask() { + if maskLayer.isHidden { + maskLayer.isHidden = false + } + } + public override func hideMask() { + if !maskLayer.isHidden { + maskLayer.isHidden = true + } + } func videoSliderView(_ videoSliderView: PreviewVideoSliderView, didChangedPlayDuration duration: CGFloat, state: SliderView.Event) { seek(to: TimeInterval(duration), isPlay: state == .touchUpInSide) diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/View/Cell/PreviewVideoViewCell.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/View/Cell/PreviewVideoViewCell.swift index 70ea6123..d984ced7 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/View/Cell/PreviewVideoViewCell.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/View/Cell/PreviewVideoViewCell.swift @@ -113,7 +113,17 @@ open class PreviewVideoViewCell: PhotoPreviewViewCell, PhotoPreviewContentViewDe } /// 隐藏工具视图(例如滑动条) - open func hiddenToolView() { + open func hideToolView() { + + } + + /// 显示遮罩层 + open func showMask() { + + } + + /// 隐藏遮罩层 + open func hideMask() { } @@ -165,6 +175,10 @@ extension PreviewVideoViewCell: PhotoPreviewVideoViewDelegate { showToolView() } + func videoView(_ videoView: VideoPlayerView, isPlaybackLikelyToKeepUp: Bool) { + playButton.isHidden = !isPlaybackLikelyToKeepUp + } + func videoView(hidePlayButton videoView: VideoPlayerView) { if playButton.alpha == 1 { UIView.animate(withDuration: 0.15) { @@ -175,6 +189,12 @@ extension PreviewVideoViewCell: PhotoPreviewVideoViewDelegate { } } } - hiddenToolView() + hideToolView() + } + func videoView(showMaskView videoView: VideoPlayerView) { + showMask() + } + func videoView(hideMaskView videoView: VideoPlayerView) { + hideMask() } } diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/View/PhotoPreviewContentView.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/View/PhotoPreviewContentView.swift index 51422e28..d1c3b62c 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/View/PhotoPreviewContentView.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/View/PhotoPreviewContentView.swift @@ -69,7 +69,7 @@ class PhotoPreviewContentView: UIView, PHLivePhotoViewDelegate { var currentLoadAssetLocalIdentifier: String? var photoAsset: PhotoAsset! { didSet { - requestFailed(info: [PHImageCancelledKey : 1]) + requestFailed(info: [PHImageCancelledKey : 1], isICloud: false) setAnimatedImageCompletion = false switch photoAsset.mediaSubType { case .livePhoto: @@ -99,12 +99,12 @@ class PhotoPreviewContentView: UIView, PHLivePhotoViewDelegate { requestCompletion = true #if canImport(Kingfisher) if photoAsset.mediaSubType != .networkVideo { - showLoadingView() + showLoadingView(text: "正在下载") } imageView.setImage(for: photoAsset, urlType: .original) { [weak self] (receivedData, totolData) in if let mediaSubType = self?.photoAsset.mediaSubType, mediaSubType != .networkVideo { let percentage = Double(receivedData) / Double(totolData) - self?.requestUpdateProgress(progress: percentage) + self?.requestUpdateProgress(progress: percentage, isICloud: false) } } completionHandler: { [weak self] (image, error, photoAsset) in guard let self = self else { return } @@ -115,7 +115,7 @@ class PhotoPreviewContentView: UIView, PHLivePhotoViewDelegate { self.updateContentSize(image: image) self.delegate?.contentView(networkImagedownloadSuccess: self) }else { - self.requestFailed(info: nil) + self.requestFailed(info: nil, isICloud: false) } }else { if let image = image { @@ -156,6 +156,7 @@ class PhotoPreviewContentView: UIView, PHLivePhotoViewDelegate { } #endif if let videoURL = photoAsset.networkVideoAsset?.videoURL { + videoView.isNetwork = false let key = videoURL.absoluteString if PhotoTools.isCached(forVideo: key) { let url = PhotoTools.getVideoCacheURL(for: key) @@ -163,16 +164,23 @@ class PhotoPreviewContentView: UIView, PHLivePhotoViewDelegate { networkVideoRequestCompletion(url) return } + if PhotoManager.shared.loadNetworkVideoMode == .play { + videoView.isNetwork = true + networkVideoRequestCompletion(videoURL) + return + } if loadingView == nil { ProgressHUD.hide(forView: superview?.superview, animated: false) - showLoadingView() + showLoadingView(text: "正在下载") }else { loadingView?.isHidden = false } networkVideoLoading = true - PhotoManager.shared.downloadTask(with: videoURL) { [weak self] (progress, task) in - self?.requestUpdateProgress(progress: progress) - } completionHandler: { [weak self] (url, error) in + PhotoManager.shared.downloadTask( + with: videoURL) { + [weak self] (progress, task) in + self?.requestUpdateProgress(progress: progress, isICloud: false) + } completionHandler: { [weak self] (url, error, _) in guard let self = self else { return } @@ -189,9 +197,9 @@ class PhotoPreviewContentView: UIView, PHLivePhotoViewDelegate { self.networkVideoRequestCompletion(url) }else { if let error = error as NSError?, error.code == NSURLErrorCancelled { - self.requestFailed(info: [PHImageCancelledKey : 1]) + self.requestFailed(info: [PHImageCancelledKey : 1], isICloud: false) }else { - self.requestFailed(info: nil) + self.requestFailed(info: nil, isICloud: false) } } } @@ -248,7 +256,7 @@ class PhotoPreviewContentView: UIView, PHLivePhotoViewDelegate { canRequest = false UIApplication.shared.isNetworkActivityIndicatorVisible = true if loadingView == nil { - loadingView = ProgressHUD.showLoading(addedTo: superview?.superview, text: "正在下载".localized + "(" + String(Int(photoAsset.downloadProgress * 100)) + "%)", animated: true) + loadingView = ProgressHUD.showLoading(addedTo: superview?.superview, text: "正在同步iCloud".localized + "(" + String(Int(photoAsset.downloadProgress * 100)) + "%)", animated: true) } }else { UIApplication.shared.isNetworkActivityIndicatorVisible = false @@ -310,41 +318,44 @@ class PhotoPreviewContentView: UIView, PHLivePhotoViewDelegate { return } #endif - requestID = photoAsset.requestImageData(iCloudHandler: { [weak self] (asset, iCloudRequestID) in + requestID = photoAsset.requestImageData(iCloudHandler: { [weak self] asset, iCloudRequestID in if asset == self?.photoAsset { self?.requestShowDonwloadICloudHUD(iCloudRequestID: iCloudRequestID) } - }, progressHandler: { [weak self] (asset, progress) in + }, progressHandler: { [weak self] asset, progress in if asset == self?.photoAsset { - self?.requestUpdateProgress(progress: progress) + self?.requestUpdateProgress(progress: progress, isICloud: true) } - }, success: { [weak self] (asset, imageData, imageOrientation, info) in + }, resultHandler: { [weak self] asset, result in guard let self = self else { return } - if asset.mediaSubType.isGif { - if asset == self.photoAsset { - self.requestSucceed() - self.imageView.setImageData(imageData) - self.setAnimatedImageCompletion = true - self.requestID = nil - self.requestCompletion = true - } - }else { - DispatchQueue.global().async { - var image = UIImage.init(data: imageData) - image = image?.scaleSuitableSize() - DispatchQueue.main.async { - if asset == self.photoAsset { - self.requestSucceed() - self.imageView.setImage(image, animated: true) - self.requestID = nil - self.requestCompletion = true + switch result { + case .success(let dataResult): + if asset.mediaSubType.isGif { + if asset == self.photoAsset { + self.requestSucceed() + self.imageView.setImageData(dataResult.imageData) + self.setAnimatedImageCompletion = true + self.requestID = nil + self.requestCompletion = true + } + }else { + DispatchQueue.global().async { + var image = UIImage.init(data: dataResult.imageData) + image = image?.scaleSuitableSize() + DispatchQueue.main.async { + if asset == self.photoAsset { + self.requestSucceed() + self.imageView.setImage(image, animated: true) + self.requestID = nil + self.requestCompletion = true + } } } } - } - }, failure: { [weak self] (asset, info) in - if asset == self?.photoAsset { - self?.requestFailed(info: info) + case .failure(let error): + if asset == self.photoAsset { + self.requestFailed(info: error.info, isICloud: true) + } } }) } @@ -364,7 +375,7 @@ class PhotoPreviewContentView: UIView, PHLivePhotoViewDelegate { } }, progressHandler: { [weak self](asset, progress) in if asset == self?.photoAsset { - self?.requestUpdateProgress(progress: progress) + self?.requestUpdateProgress(progress: progress, isICloud: true) } }, success: { [weak self] (asset, livePhoto, info) in if asset == self?.photoAsset { @@ -377,9 +388,9 @@ class PhotoPreviewContentView: UIView, PHLivePhotoViewDelegate { self?.requestID = nil self?.requestCompletion = true } - }, failure: { [weak self] (asset, info) in + }, failure: { [weak self] (asset, info, error) in if asset == self?.photoAsset { - self?.requestFailed(info: info) + self?.requestFailed(info: info, isICloud: true) } }) } @@ -390,7 +401,7 @@ class PhotoPreviewContentView: UIView, PHLivePhotoViewDelegate { } }, progressHandler: { [weak self] (asset, progress) in if asset == self?.photoAsset { - self?.requestUpdateProgress(progress: progress) + self?.requestUpdateProgress(progress: progress, isICloud: true) } }, success: { [weak self] (asset, avAsset, info) in if asset == self?.photoAsset { @@ -405,9 +416,9 @@ class PhotoPreviewContentView: UIView, PHLivePhotoViewDelegate { self?.requestID = nil self?.requestCompletion = true } - }, failure: { [weak self] (asset, info) in + }, failure: { [weak self] (asset, info, error) in if asset == self?.photoAsset { - self?.requestFailed(info: info) + self?.requestFailed(info: info, isICloud: true) } }) } @@ -415,13 +426,14 @@ class PhotoPreviewContentView: UIView, PHLivePhotoViewDelegate { UIApplication.shared.isNetworkActivityIndicatorVisible = true requestID = iCloudRequestID currentLoadAssetLocalIdentifier = photoAsset.phAsset?.localIdentifier - showLoadingView() + showLoadingView(text: "正在同步iCloud") } - func requestUpdateProgress(progress: Double) { - loadingView?.updateText(text: "正在下载".localized + "(" + String(Int(progress * 100)) + "%)") + func requestUpdateProgress(progress: Double, isICloud: Bool) { + let text = isICloud ? "正在同步iCloud" : "正在下载" + loadingView?.updateText(text: text.localized + "(" + String(Int(progress * 100)) + "%)") } - func showLoadingView() { - loadingView = ProgressHUD.showLoading(addedTo: superview?.superview, text: "正在下载".localized, animated: true) + func showLoadingView(text: String) { + loadingView = ProgressHUD.showLoading(addedTo: superview?.superview, text: text.localized, animated: true) } func resetLoadingState() { UIApplication.shared.isNetworkActivityIndicatorVisible = false @@ -432,12 +444,13 @@ class PhotoPreviewContentView: UIView, PHLivePhotoViewDelegate { resetLoadingState() ProgressHUD.hide(forView: superview?.superview, animated: true) } - func requestFailed(info: [AnyHashable : Any]?, isCancel: Bool = false) { + func requestFailed(info: [AnyHashable : Any]?, isICloud: Bool) { loadingView?.removeFromSuperview() resetLoadingState() - if !AssetManager.assetCancelDownload(for: info) { - ProgressHUD.hide(forView: superview?.superview, animated: true) - ProgressHUD.showWarning(addedTo: superview?.superview, text: "下载失败".localized, animated: true, delayHide: 2) + if let info = info, !info.isCancel { + let text = (info.inICloud && isICloud) ? "iCloud同步失败" : "下载失败" + ProgressHUD.hide(forView: superview?.superview, animated: false) + ProgressHUD.showWarning(addedTo: superview?.superview, text: text.localized, animated: true, delayHide: 2) } } func cancelRequest() { @@ -478,7 +491,7 @@ class PhotoPreviewContentView: UIView, PHLivePhotoViewDelegate { if photoAsset.mediaType == .video { if photoAsset.isNetworkAsset && !requestNetworkCompletion { cancelRequest() - requestFailed(info: [PHImageCancelledKey : 1]) + requestFailed(info: [PHImageCancelledKey : 1], isICloud: false) }else { videoView.stopPlay() } @@ -489,6 +502,8 @@ class PhotoPreviewContentView: UIView, PHLivePhotoViewDelegate { if photoAsset.isNetworkAsset { if requestNetworkCompletion { videoView.showPlayButton() + }else { + videoView.showMaskView() } }else { videoView.showPlayButton() @@ -503,6 +518,8 @@ class PhotoPreviewContentView: UIView, PHLivePhotoViewDelegate { if photoAsset.isNetworkAsset { if requestNetworkCompletion { videoView.hiddenPlayButton() + }else { + videoView.hiddenMaskView() } }else { videoView.hiddenPlayButton() diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/View/PhotoPreviewVideoView.swift b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/View/PhotoPreviewVideoView.swift index 68d6726a..76c53a4e 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Picker/View/PhotoPreviewVideoView.swift +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Picker/View/PhotoPreviewVideoView.swift @@ -14,6 +14,10 @@ protocol PhotoPreviewVideoViewDelegate: AnyObject { func videoView(stopPlay videoView: VideoPlayerView) func videoView(showPlayButton videoView: VideoPlayerView) func videoView(hidePlayButton videoView: VideoPlayerView) + func videoView(showMaskView videoView: VideoPlayerView) + func videoView(hideMaskView videoView: VideoPlayerView) + + func videoView(_ videoView: VideoPlayerView, isPlaybackLikelyToKeepUp: Bool) func videoView(resetPlay videoView: VideoPlayerView) func videoView(_ videoView: VideoPlayerView, readyToPlay duration: CGFloat) @@ -23,10 +27,15 @@ protocol PhotoPreviewVideoViewDelegate: AnyObject { class PhotoPreviewVideoView: VideoPlayerView { weak var delegate: PhotoPreviewVideoViewDelegate? + var isNetwork: Bool = false override var avAsset: AVAsset? { didSet { do { try AVAudioSession.sharedInstance().setCategory(.playback) } catch {} delegate?.videoView(showPlayButton: self) + if isNetwork && PhotoManager.shared.loadNetworkVideoMode == .play { + delegate?.videoView(self, isPlaybackLikelyToKeepUp: false) + loadingView = ProgressHUD.showLoading(addedTo: self, animated: true) + } delegate?.videoView(resetPlay: self) let playerItem = AVPlayerItem.init(asset: avAsset!) player.replaceCurrentItem(with: playerItem) @@ -34,7 +43,7 @@ class PhotoPreviewVideoView: VideoPlayerView { addedPlayerObservers() } } - + var loadingView: ProgressHUD? var isPlaying: Bool = false var didEnterBackground: Bool = false var enterPlayGroundShouldPlay: Bool = false @@ -84,11 +93,18 @@ class PhotoPreviewVideoView: VideoPlayerView { } func hiddenPlayButton() { ProgressHUD.hide(forView: self, animated: true) + loadingView = nil delegate?.videoView(hidePlayButton: self) } func showPlayButton() { delegate?.videoView(showPlayButton: self) } + func hiddenMaskView() { + delegate?.videoView(hideMaskView: self) + } + func showMaskView() { + delegate?.videoView(showMaskView: self) + } func cancelPlayer() { if player.currentItem != nil { stopPlay() @@ -106,6 +122,7 @@ class PhotoPreviewVideoView: VideoPlayerView { playerLayer.player = nil removePlayerObservers() ProgressHUD.hide(forView: self, animated: true) + loadingView = nil } } func addedPlayerObservers() { @@ -147,8 +164,9 @@ class PhotoPreviewVideoView: VideoPlayerView { switch playerItem.status { case AVPlayerItem.Status.readyToPlay: // 可以播放了 - ProgressHUD.hide(forView: self, animated: true) delegate?.videoView(self, readyToPlay: CGFloat(CMTimeGetSeconds(playerItem.duration))) + loadingView?.isHidden = true + delegate?.videoView(self, isPlaybackLikelyToKeepUp: true) if playbackTimeObserver == nil { playbackTimeObserver = player.addPeriodicTimeObserver(forInterval: CMTimeMake(value: 1, timescale: 10), queue: .main) { [weak self] (time) in guard let self = self else { return } @@ -177,12 +195,18 @@ class PhotoPreviewVideoView: VideoPlayerView { }else if keyPath == "playbackBufferEmpty" { }else if keyPath == "playbackLikelyToKeepUp" { - if !player.currentItem!.isPlaybackLikelyToKeepUp { - // 缓冲完成 - ProgressHUD.showLoading(addedTo: self, animated: true) - }else { + let isPlaybackLikelyToKeepUp = player.currentItem!.isPlaybackLikelyToKeepUp + delegate?.videoView(self, isPlaybackLikelyToKeepUp: isPlaybackLikelyToKeepUp) + if !isPlaybackLikelyToKeepUp { // 缓冲中 - ProgressHUD.hide(forView: self, animated: true) + if loadingView == nil { + loadingView = ProgressHUD.showLoading(addedTo: self, animated: true) + }else { + loadingView?.isHidden = false + } + }else { + // 缓冲完成 + loadingView?.isHidden = true } } }else if object is AVPlayerLayer && keyPath == "readyForDisplay" { diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/en.lproj/Localizable.strings b/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/en.lproj/Localizable.strings index 3c02ca08..2ecc1277 100644 Binary files a/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/en.lproj/Localizable.strings and b/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/en.lproj/Localizable.strings differ diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/id.lproj/Localizable.strings b/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/id.lproj/Localizable.strings index aba32620..d1526a6d 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/id.lproj/Localizable.strings +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/id.lproj/Localizable.strings @@ -57,6 +57,14 @@ "暂无配乐" = "Tidak ada soundtrack"; "配乐" = "Soundtrack"; "视频原声" = "Soundtrack video"; +"正在同步iCloud" = "Sinkronisasi iCloud"; +"iCloud同步失败" = "Sinkronisasi iCloud gagal"; +"拖动到此处删除" = "Seret ke sini untuk menghapus"; +"松手即可删除" = "Lepaskan untuk menghapus"; +"搜索" = "Cari"; +"背景音乐" = "Musik"; +"搜索歌名" = "Cari judul lagu"; +"此歌曲暂无歌词,请您欣赏" = "Tidak ada lirik untuk lagu ini, selamat menikmati"; "HXAlbumCameraRoll" = "Semua foto"; "HXAlbumPanoramas" = "gambar panorama"; diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/images/hx_editor_photo_text_normal@2x.png b/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/images/hx_editor_photo_text_normal@2x.png new file mode 100755 index 00000000..06a4b2ca Binary files /dev/null and b/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/images/hx_editor_photo_text_normal@2x.png differ diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/images/hx_editor_photo_text_normal@3x.png b/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/images/hx_editor_photo_text_normal@3x.png new file mode 100755 index 00000000..b3f4fa1e Binary files /dev/null and b/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/images/hx_editor_photo_text_normal@3x.png differ diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/images/hx_editor_photo_text_selected@2x.png b/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/images/hx_editor_photo_text_selected@2x.png new file mode 100755 index 00000000..36b9af27 Binary files /dev/null and b/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/images/hx_editor_photo_text_selected@2x.png differ diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/images/hx_editor_photo_text_selected@3x.png b/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/images/hx_editor_photo_text_selected@3x.png new file mode 100755 index 00000000..3f05d61d Binary files /dev/null and b/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/images/hx_editor_photo_text_selected@3x.png differ diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/images/hx_editor_photo_tools_emoji@2x.png b/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/images/hx_editor_photo_tools_emoji@2x.png new file mode 100755 index 00000000..e8db5edd Binary files /dev/null and b/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/images/hx_editor_photo_tools_emoji@2x.png differ diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/images/hx_editor_photo_tools_emoji@3x.png b/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/images/hx_editor_photo_tools_emoji@3x.png new file mode 100755 index 00000000..fbec5936 Binary files /dev/null and b/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/images/hx_editor_photo_tools_emoji@3x.png differ diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/images/hx_editor_photo_tools_text@2x.png b/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/images/hx_editor_photo_tools_text@2x.png new file mode 100755 index 00000000..bbb226ca Binary files /dev/null and b/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/images/hx_editor_photo_tools_text@2x.png differ diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/images/hx_editor_photo_tools_text@3x.png b/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/images/hx_editor_photo_tools_text@3x.png new file mode 100755 index 00000000..31fbef4c Binary files /dev/null and b/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/images/hx_editor_photo_tools_text@3x.png differ diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/images/hx_editor_photo_trash_close@2x.png b/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/images/hx_editor_photo_trash_close@2x.png new file mode 100755 index 00000000..9fa97094 Binary files /dev/null and b/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/images/hx_editor_photo_trash_close@2x.png differ diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/images/hx_editor_photo_trash_close@3x.png b/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/images/hx_editor_photo_trash_close@3x.png new file mode 100755 index 00000000..ce1043c1 Binary files /dev/null and b/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/images/hx_editor_photo_trash_close@3x.png differ diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/images/hx_editor_photo_trash_open@2x.png b/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/images/hx_editor_photo_trash_open@2x.png new file mode 100755 index 00000000..54bf5939 Binary files /dev/null and b/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/images/hx_editor_photo_trash_open@2x.png differ diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/images/hx_editor_photo_trash_open@3x.png b/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/images/hx_editor_photo_trash_open@3x.png new file mode 100755 index 00000000..df2d4027 Binary files /dev/null and b/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/images/hx_editor_photo_trash_open@3x.png differ diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/images/hx_editor_video_music_search@2x.png b/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/images/hx_editor_video_music_search@2x.png new file mode 100755 index 00000000..632de08f Binary files /dev/null and b/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/images/hx_editor_video_music_search@2x.png differ diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/images/hx_editor_video_music_search@3x.png b/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/images/hx_editor_video_music_search@3x.png new file mode 100755 index 00000000..c80f4ddb Binary files /dev/null and b/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/images/hx_editor_video_music_search@3x.png differ diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/images/hx_photo_edit_pull_down@2x.png b/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/images/hx_photo_edit_pull_down@2x.png new file mode 100755 index 00000000..a35bd1e1 Binary files /dev/null and b/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/images/hx_photo_edit_pull_down@2x.png differ diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/images/hx_photo_edit_pull_down@3x.png b/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/images/hx_photo_edit_pull_down@3x.png new file mode 100755 index 00000000..1f40003c Binary files /dev/null and b/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/images/hx_photo_edit_pull_down@3x.png differ diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/ja.lproj/Localizable.strings b/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/ja.lproj/Localizable.strings index 3c570cee..063f76d2 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/ja.lproj/Localizable.strings +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/ja.lproj/Localizable.strings @@ -56,6 +56,14 @@ "暂无配乐" = "サウンドトラックなし"; "配乐" = "サウンドトラック"; "视频原声" = "ビデオサウンドトラック"; +"正在同步iCloud" = "ICloud同期"; +"iCloud同步失败" = "iCloudの同期に失敗しました"; +"拖动到此处删除" = "ここにドラッグして削除します"; +"松手即可删除" = "削除するために行こう"; +"搜索" = "探す"; +"背景音乐" = "サウンドトラック"; +"搜索歌名" = "曲名を検索"; +"此歌曲暂无歌词,请您欣赏" = "この曲には歌詞がありませんので、お楽しみください"; "HXAlbumCameraRoll" = "カメラロール"; "HXAlbumPanoramas" = "パノラマ"; diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/ko.lproj/Localizable.strings b/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/ko.lproj/Localizable.strings index df54af64..66ceb414 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/ko.lproj/Localizable.strings +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/ko.lproj/Localizable.strings @@ -56,6 +56,14 @@ "暂无配乐" = "사운드 트랙 없음"; "配乐" = "사운드 트랙"; "视频原声" = "비디오 사운드 트랙"; +"正在同步iCloud" = "iCloud 동기화"; +"iCloud同步失败" = "iCloud 동기화 실패"; +"拖动到此处删除" = "삭제하려면 여기로 드래그하세요."; +"松手即可删除" = "삭제하러 가자"; +"搜索" = "검색"; +"背景音乐" = "사운드 트랙"; +"搜索歌名" = "노래 제목 검색"; +"此歌曲暂无歌词,请您欣赏" = "이 노래에는 가사가 없습니다, 즐겨주세요"; "HXAlbumCameraRoll" = "모든 사진"; "HXAlbumPanoramas" = "파노라마 사진"; diff --git "a/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/musics/\345\244\251\345\244\226\346\235\245\347\211\251" "b/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/musics/\345\244\251\345\244\226\346\235\245\347\211\251" new file mode 100644 index 00000000..5bf86467 --- /dev/null +++ "b/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/musics/\345\244\251\345\244\226\346\235\245\347\211\251" @@ -0,0 +1,7 @@ +[ti:天外来物] +你像 天外来物一样 求之不得 +你在世俗里的名字 不重要了 +正好 我隐藏的人格是契而不舍 +直到蜂拥而至的人都透明了 +我在 不近又不远处 +用明天换你 靠近我 diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/th.lproj/Localizable.strings b/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/th.lproj/Localizable.strings index 1bdf0fda..3ebd6c81 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/th.lproj/Localizable.strings +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/th.lproj/Localizable.strings @@ -56,6 +56,14 @@ "暂无配乐" = "ไม่มีเพลงประกอบ"; "配乐" = "ซาวด์แทร็ก"; "视频原声" = "ซาวด์แทร็กวิดีโอ"; +"正在同步iCloud" = "iCloud సమకాలీకరిస్తోంది"; +"iCloud同步失败" = "iCloud సమకాలీకరణ విఫలమైంది"; +"拖动到此处删除" = "ลากมาที่นี่เพื่อลบ"; +"松手即可删除" = "ให้ไปลบ"; +"搜索" = "ค้นหา"; +"背景音乐" = "ซาวด์แทร็ก"; +"搜索歌名" = "ค้นหาชื่อเพลง"; +"此歌曲暂无歌词,请您欣赏" = "เพลงนี้ไม่มีเนื้อเพลง ขอให้สนุก"; "HXAlbumCameraRoll" = "รูปภาพทั้งหมด"; "HXAlbumPanoramas" = "ภาพพาโนรามา"; diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/zh-Hans.lproj/Localizable.strings b/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/zh-Hans.lproj/Localizable.strings index 38320124..dba3cf21 100644 Binary files a/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/zh-Hans.lproj/Localizable.strings and b/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/zh-Hans.lproj/Localizable.strings differ diff --git a/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/zh-Hant.lproj/Localizable.strings b/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/zh-Hant.lproj/Localizable.strings index 55f7a757..98dadbd9 100644 --- a/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/zh-Hant.lproj/Localizable.strings +++ b/Pods/HXPHPicker/Sources/HXPHPicker/Resources/HXPHPicker.bundle/zh-Hant.lproj/Localizable.strings @@ -57,6 +57,14 @@ "暂无配乐" = "暫無配樂"; "配乐" = "配樂"; "视频原声" = "視頻原聲"; +"正在同步iCloud" = "正在同步iCloud"; +"iCloud同步失败" = "iCloud同步失敗"; +"拖动到此处删除" = "拖動到此處刪除"; +"松手即可删除" = "鬆手即可刪除"; +"搜索" = "搜索"; +"背景音乐" = "背景音樂"; +"搜索歌名" = "搜索歌名"; +"此歌曲暂无歌词,请您欣赏" = "此歌曲暫無歌詞,請您欣賞"; "HXAlbumCameraRoll" = "所有照片"; "HXAlbumPanoramas" = "全景照片"; diff --git a/Pods/Kingfisher/Sources/SwiftUI/ImageBinder.swift b/Pods/Kingfisher/Sources/SwiftUI/ImageBinder.swift index f383f28f..23fe0328 100644 --- a/Pods/Kingfisher/Sources/SwiftUI/ImageBinder.swift +++ b/Pods/Kingfisher/Sources/SwiftUI/ImageBinder.swift @@ -50,8 +50,16 @@ extension KFImage { var isLoaded: Binding - @Published var loaded = false - @Published var loadedImage: KFCrossPlatformImage? = nil + var loaded = false { + willSet { + objectWillChange.send() + } + } + var loadedImage: KFCrossPlatformImage? = nil { + willSet { + objectWillChange.send() + } + } @available(*, deprecated, message: "The `options` version is deprecated And will be removed soon.") init(source: Source?, options: KingfisherOptionsInfo? = nil, isLoaded: Binding) { diff --git a/Pods/Kingfisher/Sources/SwiftUI/KFImage.swift b/Pods/Kingfisher/Sources/SwiftUI/KFImage.swift index dabb47ed..58276a6a 100644 --- a/Pods/Kingfisher/Sources/SwiftUI/KFImage.swift +++ b/Pods/Kingfisher/Sources/SwiftUI/KFImage.swift @@ -161,6 +161,7 @@ struct KFImageRenderer: View { } /// Declares the content and behavior of this view. + @ViewBuilder var body: some View { if let image = binder.loadedImage { configurations diff --git a/Pods/Manifest.lock b/Pods/Manifest.lock index d06e8ab1..93b6f949 100644 --- a/Pods/Manifest.lock +++ b/Pods/Manifest.lock @@ -1,18 +1,22 @@ PODS: - - HXPHPicker/Core (1.1.3) - - HXPHPicker/Editor (1.1.3): + - HXPHPicker (1.1.6): + - HXPHPicker/Full (= 1.1.6) + - HXPHPicker/Core (1.1.6) + - HXPHPicker/Editor (1.1.6): - HXPHPicker/Core - - HXPHPicker/Full (1.1.3): + - HXPHPicker/Full (1.1.6): + - HXPHPicker/Lite + - Kingfisher (~> 6.0) + - HXPHPicker/Lite (1.1.6): - HXPHPicker/Core - HXPHPicker/Editor - HXPHPicker/Picker - - Kingfisher (~> 6.0) - - HXPHPicker/Picker (1.1.3): + - HXPHPicker/Picker (1.1.6): - HXPHPicker/Core - - Kingfisher (6.3.0) + - Kingfisher (6.3.1) DEPENDENCIES: - - HXPHPicker/Full (~> 1.1.3) + - HXPHPicker (~> 1.1.6) SPEC REPOS: https://github.com/CocoaPods/Specs.git: @@ -20,9 +24,9 @@ SPEC REPOS: - Kingfisher SPEC CHECKSUMS: - HXPHPicker: 11fc8a93a606bd531a195afd7ef42f0ff660888a - Kingfisher: 6c3df386db71d82c0817a429d2c9421a77396529 + HXPHPicker: 47f055335107393179201e009e90d32582596e91 + Kingfisher: 016c8b653a35add51dd34a3aba36b580041acc74 -PODFILE CHECKSUM: ee6c2e3ceb139b50e450afa3e8781766ddff9c0a +PODFILE CHECKSUM: 29189cca6a3135688a8bb227d9d3797866608f28 COCOAPODS: 1.10.1 diff --git a/Pods/Pods.xcodeproj/project.pbxproj b/Pods/Pods.xcodeproj/project.pbxproj index 5d9f7495..8a89a654 100644 --- a/Pods/Pods.xcodeproj/project.pbxproj +++ b/Pods/Pods.xcodeproj/project.pbxproj @@ -7,243 +7,254 @@ objects = { /* Begin PBXBuildFile section */ - 00338F3D5F82E147543464AD98C7F1E2 /* PhotoEditorDrawView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1A5151C93FB53BF11EACE400D3A731D /* PhotoEditorDrawView.swift */; }; - 005C63FED0B832EFA98EF8CE64BB24FA /* ImageCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = C11E0F29122AC9F7339A1462FDD4D9B9 /* ImageCache.swift */; }; - 01B738C1CAB2145CC6C45D95023DA2D9 /* EditorType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 334D1DCE7985A1C03D5E2F8A157E08E0 /* EditorType.swift */; }; - 038966D6375558DF19856B155F48AB31 /* EditorToolViewConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDAA1BAE55A5E39451124EE003C59D1A /* EditorToolViewConfiguration.swift */; }; - 038F8395233DE0369D8A2BA07F35B6B4 /* VideoPlayerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D72BAFE08AD4646F7426D9168E57588A /* VideoPlayerView.swift */; }; - 0443E6EBDAA758C06C04199187F7CA55 /* Delegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB65976E1F0710E684127792006DF1D4 /* Delegate.swift */; }; - 050A5ACCD0D3BE90FD570A7719CFAB3C /* Core+UIImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 890E7EFC6AF7BBE7960EA22FF17CBC49 /* Core+UIImageView.swift */; }; - 052A6FDA74DB688EADBC5EAFC57C0587 /* ImageDrawing.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF58F49EBCA386B0EF516C3557F8ECA9 /* ImageDrawing.swift */; }; - 05584212F6F2C514D72746FF8B3A331C /* Placeholder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 803B9838178D0559BE20DB81795C0379 /* Placeholder.swift */; }; - 06003243D6F2B1B89B59629AD75231A8 /* EditorImageResizerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92B15CDBEAFF705823B43C168FFC30F6 /* EditorImageResizerView.swift */; }; - 07DDD0CCEBFF49AF76827D9745BD6043 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF71B739F7A0F8F1F47C4E6F3C9B945E /* Foundation.framework */; }; - 07E903EF2CE075711F0ABD6E120F2D4B /* VideoEditorCropViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28805DA79279D39C9E775A3C83679CEB /* VideoEditorCropViewCell.swift */; }; - 099A7527DD851CF7B140A722500BED3B /* VideoEditorViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4852514CAA80364B32BE45D4609601D1 /* VideoEditorViewController.swift */; }; - 0A42EC0D57457C873B3EA264EDD1A65E /* KFOptionsSetter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 636F5C4CDDDCA53B0257D2C60617DCD4 /* KFOptionsSetter.swift */; }; - 0BA606564CF9D9788B71FE17B26EE2BA /* PhotoManager+Download.swift in Sources */ = {isa = PBXBuildFile; fileRef = B88513158CCCF5FC56759E5802F83DE3 /* PhotoManager+Download.swift */; }; - 0C5314C5297A558D653F4F2D5EF23F58 /* SizeExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6FC78B1FC94C1B1D29105230125C063E /* SizeExtensions.swift */; }; - 0CCF4FACECA0A5EE2BA385AF3469C786 /* PhotoPickerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A29336BB5E87AB2B535EBC9E33BBC28 /* PhotoPickerViewController.swift */; }; - 0D2A946D1FB48ACE590D624B751E53F6 /* PhotoEditorCropToolModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C754E497022D097EF2A113AADABDF9B /* PhotoEditorCropToolModel.swift */; }; - 0F382FBE040805464373238F861EF123 /* AssetManager+LivePhoto.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4789F562F464012923FC30183A2741A7 /* AssetManager+LivePhoto.swift */; }; - 119256589CFF0B98856EA6DBC18B566C /* EditorToolView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD6464CDD2E4B2FAF5661A075B8090EE /* EditorToolView.swift */; }; - 11A94BB931C8EB4C5F5D364348FDFC40 /* KingfisherOptionsInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BD376D40FEDDF1041AD3ED8722D34E6 /* KingfisherOptionsInfo.swift */; }; - 11C6FEEBE6CD821D27005CA24D3D1A99 /* DeniedAuthorizationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AFAA52721AA4872285B203DE209D42A /* DeniedAuthorizationView.swift */; }; - 19D2F029DA9C548BBF0A0DE4D8ADE39E /* VideoCroppingConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2572F6B184769B86544433ECB4E7CB07 /* VideoCroppingConfiguration.swift */; }; - 1AB945BFDE9B8D1E92B94F368673E48C /* AlbumTitleViewConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB5B0C5872FE958E4C477AB6D0FA495 /* AlbumTitleViewConfiguration.swift */; }; - 1C990327AA693C5BAEC2BE121A6F4B6E /* Resource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A396B7E18DCDBD197E7732A0F4FEBA4 /* Resource.swift */; }; - 1D5BD0A8211247DFA5F45F497EE786ED /* EditorImageResizerMaskView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DE117DEE9BC8FBEAF25DCC404A55C0D /* EditorImageResizerMaskView.swift */; }; - 1E14073745A1038B091A0D7E6004A940 /* ImageFormat.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DC889CE6056F86A66BF6041B2F2C989 /* ImageFormat.swift */; }; - 227D3540141EE2A6C4626CC945E22DD6 /* KFImageOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 235EC98F01016FC89379B96C9A378C02 /* KFImageOptions.swift */; }; - 23A8196697B18BF780966632E503BEB3 /* PhotoEditorFilterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E08650E661A65D8AFF34727D04C6DD9E /* PhotoEditorFilterView.swift */; }; - 23CB1CAF9617823EA2BC06204EA3DB37 /* PhotoEditorViewController+Request.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29F07941959855158988322CC0B2146B /* PhotoEditorViewController+Request.swift */; }; - 242ED845EE9F258D178093CFA03A199D /* PhotoEditorViewController+Export.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49326A675DE29F1A0F9803D2E75A51F4 /* PhotoEditorViewController+Export.swift */; }; - 269DFDEDD6FAF08A53D3F3160B2C1654 /* PhotoAsset+Network.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A726DE17A03F99C4F2A95D4E7C45FBE /* PhotoAsset+Network.swift */; }; - 27BFCC56B874A93E895B41B13A2C55F8 /* ImageProcessor.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2A7512ED739726CA517F36C54B774B5 /* ImageProcessor.swift */; }; - 29590F1FFE753B7431DACA250E3B8D57 /* Core+PHAssetCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 688A16315FA65A47A86E08E0474EA870 /* Core+PHAssetCollection.swift */; }; - 29917F619F40E9F8AD6168DE49C6928C /* ImageDataProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = D626DEE33E886F43389E4D4C0C06944C /* ImageDataProvider.swift */; }; - 2A73A7F0B740ABD90B7A825307FAD9E4 /* GIFAnimatedImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82BFE36A1B02653C5120C6BB84EEDF9F /* GIFAnimatedImage.swift */; }; - 2C30C162FC0BF1C9F940CCECFC1D6561 /* TVMonogramView+Kingfisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 574F83FDDB83A7182533B1D9ABD5CA05 /* TVMonogramView+Kingfisher.swift */; }; - 2E2F7BE1C7A6BBA68DAD48C523D888DC /* CameraViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46A41212FDA74FB99EA30F3724F33AF5 /* CameraViewController.swift */; }; - 311F503D66F657FE86397A5598083374 /* Picker+UIImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E09AB868F28C37D80342CD9A8C37C390 /* Picker+UIImageView.swift */; }; - 3157CFBD2D898E8D3D0071024F317DDE /* NSButton+Kingfisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB472E8F2E6A8CC9C84EABA31140924B /* NSButton+Kingfisher.swift */; }; - 316E7A0A8EF75D05D535388D84C7B98A /* Filter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64859EB840E1B0ADB4524B39239AC173 /* Filter.swift */; }; - 31D16C8DBF9162547C369FD431C49828 /* AssetManager+Image.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF2CE9ADEBD524066BB454888BF5C597 /* AssetManager+Image.swift */; }; - 3299ACFF02931BB0B85CAB8D63351C9C /* EditorController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A96275918A0C8AE4AFDE89364F13CEE7 /* EditorController.swift */; }; - 3503C7426CCD60FF0172CA645963527B /* PickerInteractiveTransition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 68474C198A87E5997989EF6105F7CDA8 /* PickerInteractiveTransition.swift */; }; - 3F0860723E69F242FAE43CEFA57B4EFC /* Core+UIImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 478A78BD12272959D6D0C7C507437A97 /* Core+UIImage.swift */; }; - 3FD47105E23BDC6628AAF8932B153D15 /* PreviewPhotoViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A5224346D4E0C403876184DA83D02B2 /* PreviewPhotoViewCell.swift */; }; - 41847DEA614F7FCB9F1853AC6B404C2E /* EmptyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F1DE1AB74246D67AB35992D09686534 /* EmptyView.swift */; }; - 425E8203EA327EB5A495E7F52306CA1B /* PhotoPreviewViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A32037254E41EF30ECF6E30B3B2155F /* PhotoPreviewViewCell.swift */; }; - 42FEC53E19FBBFAD2193F6A2CD970670 /* PhotoEditorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6726B45A690D709E558A34EB87B86CC1 /* PhotoEditorView.swift */; }; - 4397EA9660E3044D0D85071FF770EA10 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF71B739F7A0F8F1F47C4E6F3C9B945E /* Foundation.framework */; }; - 4593B3CEE4ABA9BC43E4D74C5BEEF7FC /* Core+String.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A676EEE2F99A99BBE1F05A3FEFB6E4F /* Core+String.swift */; }; - 45CA29CCB33E113557A6394BE832E145 /* NSTextAttachment+Kingfisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B81DECD774F3D4D9429BE878A52C23E /* NSTextAttachment+Kingfisher.swift */; }; - 48326ACE15B73B3BCA0B4FAD506FB971 /* CustomLanguage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 93C6D6596A5CE21A3B66EB401BA0787E /* CustomLanguage.swift */; }; - 49FCE13B20C3371630371C4F73D9F775 /* PreviewLivePhotoViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DA2046F0F15237DEC99B2E540F33A02 /* PreviewLivePhotoViewCell.swift */; }; - 4A90DA3DF1A6ECF2C27EF0C826F24673 /* PhotoListCameraCellConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2B6A3CC5B150A69213DFC957AFBCF1B0 /* PhotoListCameraCellConfiguration.swift */; }; - 4AC5D58C33BB3A6CF79E8324B4A613AD /* ImageProgressive.swift in Sources */ = {isa = PBXBuildFile; fileRef = A62F1D833E4B0698EFC61B95E6A3F744 /* ImageProgressive.swift */; }; - 4B734407952D73B98E5C09223D8DAA10 /* PhotoEditorBrushColorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CAA1C6552AEAF1E552935EDDF916435 /* PhotoEditorBrushColorView.swift */; }; - 4DCCA9E6EC1C9713C27DBC7E4684C551 /* NotAuthorizedConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B3C9D20F25D671AC5B9A148A47154D5 /* NotAuthorizedConfiguration.swift */; }; + 020EA4A55E4A5EB7ADA799CD1D5AE25E /* VideoCroppingConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6864336E8793E888F675FD96FF5EA904 /* VideoCroppingConfiguration.swift */; }; + 03D167F5E85EF78ECE38AF54B6673A80 /* UIButton+Kingfisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 455B6FD135B9DBCECA5E79C46697AD33 /* UIButton+Kingfisher.swift */; }; + 0419619E78C7AA0A03F5F18024F7C182 /* PhotoManager+Language.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06F7E3B1CD9CAA408FCF727E7CFFFE8C /* PhotoManager+Language.swift */; }; + 0576490B2BDAD8F6818E31F149021195 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CA88A8AF447A5943F95AF07C7654F716 /* CFNetwork.framework */; }; + 07A0915E70AD7F2B1637ED67255BC7BA /* VideoEditorSearchMusicView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E2B8887898AA7C497D1A6FEAEA2AC8E /* VideoEditorSearchMusicView.swift */; }; + 07FF52EDCE463651E87750F9CB3D7D6D /* Core+UIDevice.swift in Sources */ = {isa = PBXBuildFile; fileRef = B7D393D34E48D9283DF87A12A2627BF4 /* Core+UIDevice.swift */; }; + 088650FE877F96F652722927980C7915 /* RedirectHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31608F4F2C2474D9D9CA8EC4C9272FE8 /* RedirectHandler.swift */; }; + 08ECFAD1A0CE52199F186F7D8D0947E4 /* PhotoManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FCA564D8B180872B0243FCDF544FDB7 /* PhotoManager.swift */; }; + 0B6E1F59E3F71B1219E43E78231C0C6A /* PhotoTools.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5BDDEB666AF9858765B4C5C2E03009D /* PhotoTools.swift */; }; + 0BA99B841A76DD1D8076BFB57CC88A89 /* PhotoPickerController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE3F44E74E5B0303460502CCFEB39EE6 /* PhotoPickerController.swift */; }; + 0C873B1DB4912ED36067ABA9848DC56F /* AlbumListConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9401BB7294394D430784BD8A95C19BC /* AlbumListConfiguration.swift */; }; + 0E867F4AB19E3B1B1D0F7F45655A2654 /* Placeholder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 803B9838178D0559BE20DB81795C0379 /* Placeholder.swift */; }; + 0FDDD131B4E3A69256610F98D3CA35E9 /* EditorStickerContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EE004AFA99195590A76014C2A986081 /* EditorStickerContentView.swift */; }; + 105CCB2F2F2B7449F62A5E2D136D9B72 /* SelectBoxConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDABEFFCBC7D4F3E556B386942CFD67D /* SelectBoxConfiguration.swift */; }; + 1329C2F3309BB9F7C69E94ED8401D3F0 /* EditorChartlet.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9BB05A6E5F210ED0D2F2D9B8618D1AE /* EditorChartlet.swift */; }; + 139D486A1CF941D45083C9C37DB5F155 /* PhotoPickerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CFF9A9F38CE216F9BCAB2468D5D33B2A /* PhotoPickerViewController.swift */; }; + 1587B6C55E51FC011FA32271827825E9 /* EditorStickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C5BD47EFE09F886E090A3663AD12226 /* EditorStickerView.swift */; }; + 162A9F7C4B470B9536271B0D3E799BFB /* VideoEditorPlayerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBF965A931D668DD9C27E4D57C9D32DE /* VideoEditorPlayerView.swift */; }; + 178647C0E3B21871FE0EF850BEF6EE7A /* PhotoPreviewContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 793B46377505158FB3FA3993B1F26B7A /* PhotoPreviewContentView.swift */; }; + 17A6A1E624415423B39E369F085020EF /* Picker+UIViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE27C9D0A29943792024F87E3844C4E3 /* Picker+UIViewController.swift */; }; + 17E49A0562A5F422B556E6D0EF9869EB /* PhotoPreviewSelectedView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13C3AA2223DCB5B690D31BDE0E9B10FE /* PhotoPreviewSelectedView.swift */; }; + 1A4EF2979C7AF1FB6F6F6051C3514249 /* NSButton+Kingfisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB472E8F2E6A8CC9C84EABA31140924B /* NSButton+Kingfisher.swift */; }; + 1B42946AAC11291D6EECF38EC980FA70 /* BaseConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 357701EDDEE245E85839081476097A71 /* BaseConfiguration.swift */; }; + 1D45BD4E40C57EDF5DB30981F5681790 /* PhotoEditorMosaicView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C90FD1C9FAB44FCAE623AEE8C235FB05 /* PhotoEditorMosaicView.swift */; }; + 1D61371A4CA7A1A0F4BFC6720E643373 /* AlbumTitleArrowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A821BDB5B2A2CF8AC91E4F7A59F6089D /* AlbumTitleArrowView.swift */; }; + 1E8743A6E1873A64675E3E53A2FEB4E6 /* SessionDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA5491FE4C2D5C5CECDCECA9AE640584 /* SessionDelegate.swift */; }; + 1FE1EF5A4CD3B435194947FAE0256F0D /* Core+String.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28B90775923927775FA22268513B4D38 /* Core+String.swift */; }; + 21891499532DFFDF5935C58274F45785 /* Core+UIView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09405FB889DF0D6EB6CFE76DAF940ACE /* Core+UIView.swift */; }; + 22F0C76165005CA8E322DDF2342B64BE /* PhotoAsset+Request.swift in Sources */ = {isa = PBXBuildFile; fileRef = 200797C27E58C7EAE62945E52003E6D6 /* PhotoAsset+Request.swift */; }; + 23EA95889A46324844633D170B69C659 /* EmptyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95834E4813296F15D42AFB5C8FCC36BD /* EmptyView.swift */; }; + 23EAE9B74639B5F473D411B812209423 /* VideoEditorMusicView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C778D7FF696B8B3929C66CF06F93BA9 /* VideoEditorMusicView.swift */; }; + 2460619C1816BB0715F0CC0D11B44902 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF71B739F7A0F8F1F47C4E6F3C9B945E /* Foundation.framework */; }; + 24D7330EDBCC0F09B9495782948C9B3C /* KFImageOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 235EC98F01016FC89379B96C9A378C02 /* KFImageOptions.swift */; }; + 2633CDECE715E52AD3000C043AA2A1BF /* ImageProgressive.swift in Sources */ = {isa = PBXBuildFile; fileRef = A62F1D833E4B0698EFC61B95E6A3F744 /* ImageProgressive.swift */; }; + 26AEA7767936D23BB69B66F8B802211F /* Core+Dictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B431BF357DC6E21D6492CFEA10AB872 /* Core+Dictionary.swift */; }; + 27FBC4B3C209118DD51E7CB6042270B3 /* PickerConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2417C93289DBB418D2664E0013FA0907 /* PickerConfiguration.swift */; }; + 295479D14EC2EB13C7FB5F1503994C40 /* PhotoEditorFilterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FEA074AB7BA3AF49CD342C40DC638CB /* PhotoEditorFilterView.swift */; }; + 2BC932D572A7355D9BAAEAA5319D5834 /* HXPHPicker-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 0E0F1CF360C4FBD2915F628914AC723C /* HXPHPicker-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 2CB03D5CC83D6C5FDBB0C6F50BB3741A /* PickerTransition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A3127A758A3F0C0F5E00C1B60BE235F /* PickerTransition.swift */; }; + 2D3ECF3256C907C546DA9735039B85A1 /* Photos.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C6928EC52A16376108CACDBEBAA774F /* Photos.framework */; }; + 32C2F93851943589D3871EFDE3DCA445 /* EditorStickerTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 194F9FFAA2823CF7D508CB4DE27E0634 /* EditorStickerTextView.swift */; }; + 33604909CF38A6F79153447A3CCEAA72 /* PhotoAsset.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21CC892E6F1BBE9457A2D7D5F1405A50 /* PhotoAsset.swift */; }; + 33ACFCF442A7FE946AA016BADF1ED725 /* PhotosUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0DFEFB85B8D69EC95DA13127B05085EE /* PhotosUI.framework */; }; + 3426E91F4DF25D553C3D8AFA85D0D7E0 /* EditorImageResizerControlView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C26BB434BF14419E1286FC52D083D50 /* EditorImageResizerControlView.swift */; }; + 3553408BBB85CC5114B36012B6DF97C3 /* Image.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8AD2839A5327532E0A5CAD720F73099 /* Image.swift */; }; + 36568CEF9C3DAEDDEE32A5AC99845D81 /* VideoEditorMusic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 964AC6105B2F228667606A7E878EC767 /* VideoEditorMusic.swift */; }; + 36F89D0EB2D3F90EC90FB365B7C1312E /* PreviewVideoControlViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4EF7C9F1003DF37C35C784CBD74FA4B /* PreviewVideoControlViewCell.swift */; }; + 37C8BB1D62DF96866B6E452C1076D875 /* KFOptionsSetter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 636F5C4CDDDCA53B0257D2C60617DCD4 /* KFOptionsSetter.swift */; }; + 380404B9538385ECFB95BE60462EDEF2 /* LanguageType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 130F8F4988095CCA5E5073DB439F400A /* LanguageType.swift */; }; + 3876CA6A7E7ABEE8BA4884AE71B26A89 /* PhotoPreviewViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50A982AD2004E27721F97D1CA59F821E /* PhotoPreviewViewCell.swift */; }; + 3B0B1E849C333D90BD1EE7CFC922D3BC /* Indicator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E678D061152320522BA2A9B126A6F8C /* Indicator.swift */; }; + 3B239997D3D87C1DE23EDE2CE6E1EDCA /* Box.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A5ED54FE8C5DA5F6544AE3D040E27E4 /* Box.swift */; }; + 3E0CD1623DBC41F1E64C3314B545CCBB /* PhotoPickerBaseViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75CA110961A55D00B90D2A8C35DFDD67 /* PhotoPickerBaseViewCell.swift */; }; + 3E89A7D00E0A4EEB0C6C1D85610F911A /* Resource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A396B7E18DCDBD197E7732A0F4FEBA4 /* Resource.swift */; }; + 3FB1C2B6A500E1A1DDE5813482159AC2 /* KF.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AD4CC80D5778FB3376CF363868F97E9 /* KF.swift */; }; + 3FB494D26807423F35FCA1F0A990BC96 /* HXPHPicker-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 0662662518A6290FC8C1A722A9CF987A /* HXPHPicker-dummy.m */; }; + 3FD784B7FD9790C5F0EB31FEFE32E308 /* PickerResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B18E64A636AF66F9411A62E99C511CB /* PickerResult.swift */; }; + 40F945E01879132C571D71E78C345D79 /* VideoPlayerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C70744E46D235762935B383CD84373ED /* VideoPlayerView.swift */; }; + 43880AA089E44A66789645EC7DF6B0D6 /* PhotoPreviewSelectedViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6E753BF4DC689F4ECAEF1290641355D /* PhotoPreviewSelectedViewCell.swift */; }; + 45518BEA82699257CE99C6ACC3A1EB33 /* KingfisherOptionsInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BD376D40FEDDF1041AD3ED8722D34E6 /* KingfisherOptionsInfo.swift */; }; + 460D87AC137DFFD50C2FC22A8BA3A455 /* Editor+PhotoTools.swift in Sources */ = {isa = PBXBuildFile; fileRef = E7D4BBD8DFCFCEC0DD7436685B346AEE /* Editor+PhotoTools.swift */; }; + 46C5A5B606303D1200C39860C3CF8C12 /* AssetManager+AssetCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 067D5101BD1A005C8A914F9696E02C12 /* AssetManager+AssetCollection.swift */; }; + 4705BA3F8B1C39D3468C564612E606EF /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 076583A24FEFF346EEAD16B805234FCB /* UIKit.framework */; }; + 4A8ABF437DBF2C8D3E065C2D49CF4E3E /* AssetManager+ImageData.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0D1AEBFA85DFAAE174E81C5C8420FA9 /* AssetManager+ImageData.swift */; }; + 4B110EE96D701ABA0AA09D9EFA6106A0 /* ImageDownloader.swift in Sources */ = {isa = PBXBuildFile; fileRef = F26C814FEFAFBCF3830A5F27E639C958 /* ImageDownloader.swift */; }; + 4C9788C77C25FF7A6198A52DC367BC6E /* CameraViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5C463BBF002FE01B6CD6FE4CC3D2F84 /* CameraViewController.swift */; }; + 4EAEB61C036B7E6C822EFBAB88FDF772 /* EditorController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0984B48E1917B8D20588117A5422D7F8 /* EditorController.swift */; }; + 4FAC4E007D31FBBEDE104543F5504153 /* AssetManager+AVAsset.swift in Sources */ = {isa = PBXBuildFile; fileRef = A65122D5FAF94B582526F068E163CABB /* AssetManager+AVAsset.swift */; }; + 4FDE368B5194C5D6FC3FC29CDC8330D8 /* VideoEditorViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D9AEDAEC3BDDD906F5EBABA0945250C /* VideoEditorViewController.swift */; }; + 4FFD67E51C0800E739383F4A42E922DC /* ImageContentType.swift in Sources */ = {isa = PBXBuildFile; fileRef = B502D0AF6DA8DF74CB65F21CA80C095D /* ImageContentType.swift */; }; 501F87B4507A9D1CFDE79D5C5FE4CCD8 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF71B739F7A0F8F1F47C4E6F3C9B945E /* Foundation.framework */; }; - 50AFC5402E645D6DD51CF067E1C531CA /* AlbumViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 622A7AEEC8EF9858A240F890A5628DF3 /* AlbumViewCell.swift */; }; - 5134D0BC6B8D169393447A1E0DF30260 /* Source.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74142C17714428C2B056654FC8480D7E /* Source.swift */; }; - 5313F1D73BAA23C8DC8C3C155D0D1D38 /* Picker+PhotoManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC8B9253A80AF8325CA6FB2DECD32CEA /* Picker+PhotoManager.swift */; }; - 54E8C14F831B4EB36766E8CD80B15897 /* PhotoEditorViewController+Animation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B25A28755D202E5829F73CBBB87EA68 /* PhotoEditorViewController+Animation.swift */; }; - 5524F3DC0630E9DDAB2E1C9966DDA0B1 /* Core+UIColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E7ED23FB2F6C711FC0C9A4DA50B8290 /* Core+UIColor.swift */; }; - 55AECF7637265A5ED8B04A8F7A58D385 /* UIButton+Kingfisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 455B6FD135B9DBCECA5E79C46697AD33 /* UIButton+Kingfisher.swift */; }; - 55D30D05A4C3776DA25A571A09CC0838 /* Core+Bundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28E0147A913D85F3F6A23FC33C8FDC32 /* Core+Bundle.swift */; }; - 56143A9BB75D3B05B8254DB947DDFE03 /* BaseConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4067FCFD0137862596BF9CCCC45B520 /* BaseConfiguration.swift */; }; - 576116FCC35F47444B869BB6A8ED0B1E /* VideoEditorMusic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46AFEFEC9572D73F2670FD1471847EB4 /* VideoEditorMusic.swift */; }; - 590C93F4CCB66C4BB4DC87D09C8C018C /* MemoryStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44EB32C6F0F69E0C6D73EEE192EBEE50 /* MemoryStorage.swift */; }; - 5C276F9FAEEE34773972E39E23BC126C /* PhotoPickerViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7C48AC132FFF36BA1B19AC52457D00 /* PhotoPickerViewCell.swift */; }; - 5C524FF251AD7DE63C583009E78D4475 /* Kingfisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 685C1A1F8C91B4094AFA8691254D72E5 /* Kingfisher.swift */; }; - 5C9D188782C95778B295C4F7DAD533FD /* BaseViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9508308A31AC567C83718C4F064C5195 /* BaseViewController.swift */; }; - 5CA02BB2CE79B62B480DC7EED795CE29 /* SelectBoxConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A9209C818ED6E1F1DFCAD317C6FAF7A /* SelectBoxConfiguration.swift */; }; - 5DB4AD89AD4EBECE158AEB87F084547A /* ExtensionHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = F26BBE04D00F18EF379EA2D8F3F76ED0 /* ExtensionHelpers.swift */; }; - 5EB00E4C6D46C1CF6698E8B66E5AAE9B /* AssetManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEEA33EA3D93522BB858E2B400DE568E /* AssetManager.swift */; }; + 5088AA1470ED6896BF2F1C5C55817247 /* Core+PHAsset.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2031A7C728C7A69FF24AF9CD69785785 /* Core+PHAsset.swift */; }; + 5133EC52E4877176301FC6B4C2334A09 /* EditorToolView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D5B0AC3D0F8E972EE384C4694E98215 /* EditorToolView.swift */; }; + 5250ED6D85FC2A26C30DBA2A4670F841 /* Core+URL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91FB523C544F0FAE04EE01666E96D5C6 /* Core+URL.swift */; }; + 52D86762420BEC903909A5A7CB993033 /* EditorChartletView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C9EB2FD1D24644738C1DDDF90C15176 /* EditorChartletView.swift */; }; + 53BF6E1EC42A9598A185AB0AA1494319 /* PickerInteractiveTransition.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF50DEBE3BC46AB48E86E2A87AA8254C /* PickerInteractiveTransition.swift */; }; + 54643F5F61A6799C89CA19F74199A548 /* SessionDataTask.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6412FC162B13556AC831867D400FA4D6 /* SessionDataTask.swift */; }; + 549802C464729955C5FED1332381DA1E /* PhotoEditorCropToolView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A6570757C0042B74807A527EF6D3052 /* PhotoEditorCropToolView.swift */; }; + 55AFABF00C90B571211832EBCE00A180 /* PhotoTools+File.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D97219B6BD6B8164DE061C3150E5DB4 /* PhotoTools+File.swift */; }; + 57E8D4367B9289D6280CA613C958FCDE /* DiskStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 783EC77C14F4B9C72F5F44509EC897ED /* DiskStorage.swift */; }; + 597E75C47B63A0B5AE12EBFD0E4115E1 /* Core+UIColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E75F2BADFD9C9A1D757BF931E235FAE /* Core+UIColor.swift */; }; + 5B50F271B7B4D1AD5E9DB4F701ABE32C /* AuthenticationChallengeResponsable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 165B89A1618AD2C9EC3471DF9110D8D6 /* AuthenticationChallengeResponsable.swift */; }; + 5E3B62C5B99C91608C8385668BC12956 /* Core+UIImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20F9D58158F64CD21D168B9BCAB9BBAD /* Core+UIImageView.swift */; }; + 5E4C61C32C2CC97C94F8D436A4CD77AC /* PhotoEditorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8138B689CFE3AFEEEE63A451915B3564 /* PhotoEditorView.swift */; }; + 5E810323E7C7EBE90591637409BAD8C6 /* AlbumViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32FBAF8B97108508BBF67F354009C9DD /* AlbumViewCell.swift */; }; 5F475B0DAE6EF3BA9ADA42B56F37BC72 /* Pods-HXPHPickerExample-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = AF6CE43DEB87601C10DEB3FFF34A2570 /* Pods-HXPHPickerExample-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 623765696268F7CA1EB22B7CD2E5F0E5 /* Core+UIDevice.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC1D06F8F8A9A5254A84014E10162059 /* Core+UIDevice.swift */; }; - 62429E93624E786E3D912A362226477B /* Core+Data.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DB4BC85761011473A365686A6806B07 /* Core+Data.swift */; }; - 62576256D25669602C3CFC9153EAED1E /* PreviewViewConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC1D69AE8602A539A85DBDE7AE6CB27B /* PreviewViewConfiguration.swift */; }; - 629B919C04E7752CA258929E137EB63B /* AlbumListConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = D21BD73027CF44C6BED97C7AA0D0083F /* AlbumListConfiguration.swift */; }; - 636D7AF27C42F3F71B4763C2FFA127D8 /* DiskStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 783EC77C14F4B9C72F5F44509EC897ED /* DiskStorage.swift */; }; - 64B8B02A00316C4949CFD39833D283D7 /* String+MD5.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEFDBA477B6F8B96759550E649D020D3 /* String+MD5.swift */; }; - 698619BBABA2BD11360F34EEB88CA956 /* PhotoAssetCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F79F16D3A44897480990D7FF64C5895 /* PhotoAssetCollection.swift */; }; - 6A95A41A81D05388EDEBB975679874A9 /* Runtime.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF82715186FC43646CCDE8B5A9B75524 /* Runtime.swift */; }; - 6B328D4292DF38990299F740187F37AF /* HXPHPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 692781CC1099A4A6F1FE188A1A39EF5B /* HXPHPicker.swift */; }; - 6DA4B82A9D02428F909B6A962380BC04 /* PhotoPreviewSelectedView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 563425CB7D1694773F59DCE917385445 /* PhotoPreviewSelectedView.swift */; }; - 6FDC36915339B16F86D2319C68EF1A1E /* CameraConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6B31C520BDE90F0E4660338BCF321C7D /* CameraConfiguration.swift */; }; - 703B1B250D62A703F19184829B499696 /* SessionDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA5491FE4C2D5C5CECDCECA9AE640584 /* SessionDelegate.swift */; }; - 715A9D29EB414F1672871AA05928E7BA /* ImageDownloaderDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DB8EED1C5ED86CF23C451AD85D5ACF3 /* ImageDownloaderDelegate.swift */; }; - 7212066203ADA297D7DCD78D55502CAA /* VideoEditResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85AEE49BE66EE5DDFE7A24DE45426D21 /* VideoEditResult.swift */; }; - 73222682715748539925444A4CC4ED21 /* PhotoPanGestureRecognizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D19604CBBDF0009BFE40E3E27679CD24 /* PhotoPanGestureRecognizer.swift */; }; - 752D5D109D6ED65AF100DFFE766AA42F /* Editor+PhotoTools.swift in Sources */ = {isa = PBXBuildFile; fileRef = 440B4B2232CAD0176D354214FF89F590 /* Editor+PhotoTools.swift */; }; - 76568D0A88C5A37CE292E25C21B2966B /* PhotoPickerBaseViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 407AE5F5426D0C24AFEBF692B224F738 /* PhotoPickerBaseViewCell.swift */; }; - 7773E7B6D510E7D021CD5FEBB3BB203B /* VideoEditorFrameMaskView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67261FF3C5F6BE90491DD8FBEC806B71 /* VideoEditorFrameMaskView.swift */; }; - 77F039C0975017867D92A5D8965FE34F /* PhotoCroppingConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAE7F809DA36DD7EB68C544C3E22811C /* PhotoCroppingConfiguration.swift */; }; - 798EE8946BA09D8EEA226D1D3E65B888 /* PhotoEditorMosaicToolView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 433775A97C99D7EC1558C62FE54DE366 /* PhotoEditorMosaicToolView.swift */; }; - 7A5729A963AE9B96122A0EAAF68312AD /* AssetManager+AssetCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA94CECB93BDBEC3604957BBD28190C9 /* AssetManager+AssetCollection.swift */; }; - 7AC76880EB6A35B97D831A3164A1294D /* AuthenticationChallengeResponsable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 165B89A1618AD2C9EC3471DF9110D8D6 /* AuthenticationChallengeResponsable.swift */; }; - 7AF6771DC3B6CED1CCB3190905EEFCA3 /* Editor+UIImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = B112C5DD2089296DAFD840326F0C85C0 /* Editor+UIImage.swift */; }; - 7C1072E1FBD4AD209EF77F2DDE97429D /* PreviewVideoControlViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6677C1F9671029C339103F88B6A7518E /* PreviewVideoControlViewCell.swift */; }; + 5FC9E13E4BE61D9C6604029F33E8DEB5 /* PhotoAssetCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78A990770ECD2450090AACF6937A7FC8 /* PhotoAssetCollection.swift */; }; + 609456BCB1A76E23B178D2A0C513BBB6 /* NetworkAsset.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E342829A41C6362D74A97C7B68E8B3A /* NetworkAsset.swift */; }; + 60E3D7BBC4AB90661AEF25C2651E7698 /* TVMonogramView+Kingfisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 574F83FDDB83A7182533B1D9ABD5CA05 /* TVMonogramView+Kingfisher.swift */; }; + 611DA9D55BD6F6B60E240BD7015FE136 /* AlbumView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C9C7812B380470644F66A932626C6A2 /* AlbumView.swift */; }; + 62EA2F1B8672A809B46FA95BF9B5C91B /* Storage.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4A4E9D17CFB6CD3E87B02CBB62A4B33 /* Storage.swift */; }; + 63EB3DB2B07E78D0D2696E829D2EE89C /* VideoEditorCropViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46936DB194A78211EACC9434C7564626 /* VideoEditorCropViewCell.swift */; }; + 66830060E7340BFC3BBD82B4FBB52FD5 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF71B739F7A0F8F1F47C4E6F3C9B945E /* Foundation.framework */; }; + 68B1720972180974525033A5907A529D /* EditorToolViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55BE8C50DAE322D6879995049D67F0E6 /* EditorToolViewCell.swift */; }; + 68F74C6EE8516D5FCDA949457C85DB35 /* EditorCropConfirmView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A59F7C6F400F5F0199C9DC26E4365DF /* EditorCropConfirmView.swift */; }; + 6A30F45A3EA2950E78B392E34F4F033C /* PhotoEditorViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DDE0043633422897202310C3D628F45 /* PhotoEditorViewController.swift */; }; + 6C103EA8E1110938A48C5B733704D08A /* LocalAsset.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CDB75D22B5CD9CB120C940FA1417075 /* LocalAsset.swift */; }; + 6E189CAE53DA9E4F644B7FD70E0EDA1C /* PhotoManager+Audio.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B1B6DC206B2566D105FADA1EDCCCAB3 /* PhotoManager+Audio.swift */; }; + 6E756B256C47C1C5562D0DE860B7D599 /* Editor+UIImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85A32ECAB16EB52AFB3B144CBB5CDD1E /* Editor+UIImageView.swift */; }; + 6FE901ADBFE3CBB72150D18A9A8D08D1 /* EditorType.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC8D0A8FBB166F0B760A03E76DF00CD2 /* EditorType.swift */; }; + 72E79BD62EC20C38EFDE3773A996C635 /* RetryStrategy.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD4AF271F2F5F7E36C3324DBF2EFD73F /* RetryStrategy.swift */; }; + 735A5013A2EFAD2E792807C352119A8F /* AssetManager+LivePhoto.swift in Sources */ = {isa = PBXBuildFile; fileRef = 25BDA27B1F9CB254542F4EB05308DDC2 /* AssetManager+LivePhoto.swift */; }; + 74B6343C976E88AD7383A63E3DB75647 /* ImageBinder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A600FC003AF50C0E9396D3F32C0DBAE /* ImageBinder.swift */; }; + 7544DD93AED9DCD354E9AEE6D9BEE305 /* ExtensionHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = F26BBE04D00F18EF379EA2D8F3F76ED0 /* ExtensionHelpers.swift */; }; + 76D62CF6FC1488EC033801D21940AD21 /* AppearanceStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CB4883DF7F4726E4F8552533FCF2D06 /* AppearanceStyle.swift */; }; + 7716A54E234B52A8B1390C028602BF01 /* AlbumTickView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CCAE54011723B9D1CAC576CB8FAD496 /* AlbumTickView.swift */; }; + 7759E111BF0FD9A58A76433F9B910F94 /* VideoEditorConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = B37E34968FF4C9E754E9DBD75F2B1116 /* VideoEditorConfiguration.swift */; }; + 77C8BF6BAD39835741B60C86DDA0BE0D /* PreviewViewConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2424CB8B3A8EAD348907F16762FC981 /* PreviewViewConfiguration.swift */; }; + 7807D90D3A02C723B01A456BB724294E /* Picker+PhotoManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D26F48DD9580641912BB27C678E2A07E /* Picker+PhotoManager.swift */; }; + 781EAB655CA305D4D2462870A8C78CD3 /* Picker+UIImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D832A474A922ABCB4DD2404EA5BE944A /* Picker+UIImageView.swift */; }; + 787AA8408D4903F5615E7FD305C08512 /* Picker+PhotoTools.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF3616C052A86582F38076ABD8305A20 /* Picker+PhotoTools.swift */; }; + 797E1FC177B7F803F8F542F5D0202823 /* GIFImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44EF4EC7B4D2A8C23F53A251BFF6752F /* GIFImageView.swift */; }; + 79FC96B7255860AC96F7673DE7318251 /* Kingfisher-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = A91D9D790AADDF14B73DBCAFC93AF139 /* Kingfisher-dummy.m */; }; + 7A6270C6161816A37F4FF264D73D0EE6 /* ImageTransition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49018C17822EDBBF1884E2E006CBF261 /* ImageTransition.swift */; }; + 7BFDCB0AB3C6228163454A0122A67BD6 /* String+MD5.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEFDBA477B6F8B96759550E649D020D3 /* String+MD5.swift */; }; + 7C481630D02964F4A44DDC2647358D17 /* VideoEditorFrameMaskView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 603CD0956C8179CED00CD985F9A76D17 /* VideoEditorFrameMaskView.swift */; }; + 7C50D92E8C8C88C9DD2CF1BF52EA9A76 /* GIFAnimatedImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82BFE36A1B02653C5120C6BB84EEDF9F /* GIFAnimatedImage.swift */; }; 7CA7302EC3D12C5E65601AA7919064B6 /* Pods-HXPHPickerExample-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 763CEB42B991A31F53E79BAE64BF0D84 /* Pods-HXPHPickerExample-dummy.m */; }; - 7DD545680D729CFBA70B3A1AA6A57B2D /* LivePhotoError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2056E7A211D4556EBA9699FB628661B7 /* LivePhotoError.swift */; }; - 8043324938E91735769B23B4CCA44F77 /* AVAssetImageDataProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44057F66C5C77C9B40B6CF9C8BD32AB3 /* AVAssetImageDataProvider.swift */; }; - 8149F4FE1363F453890D381A8A473737 /* ImageBinder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A600FC003AF50C0E9396D3F32C0DBAE /* ImageBinder.swift */; }; - 842322EE64A7B5EBF89F89332877B817 /* KingfisherError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C68E3B655283C5ADCD7D12044A2BD03 /* KingfisherError.swift */; }; - 8635594B8F55BED4205D34314E661FC0 /* PhotoEditorFilter.swift in Sources */ = {isa = PBXBuildFile; fileRef = ACF9CEB85ED171BE18D3860150E50D88 /* PhotoEditorFilter.swift */; }; - 86C07B02A1195143341C64EEE58A469E /* EditorImageResizerControlView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85F908541FE319223EEB696EC7130852 /* EditorImageResizerControlView.swift */; }; - 89388C9A40A7747C4BA50DE00390D086 /* PhotoPreviewSelectedViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 14473A4D04E43FB55A342C3672829644 /* PhotoPreviewSelectedViewCell.swift */; }; - 8A35C6B192FB212B16B72BCC9690915A /* PhotoListCellConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C584C14838C0813940BD3D7437CD6B0 /* PhotoListCellConfiguration.swift */; }; - 8ACA0761F20640E1EBEA4DC1FDD48EA7 /* PhotoListConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = D06882E3535F72030E939C29E21B17BF /* PhotoListConfiguration.swift */; }; - 8BE0629C8F06A5E546E9A0F5A7D2A492 /* FormatIndicatedCacheSerializer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 120393950CD497675338B3E1C9EB8B4F /* FormatIndicatedCacheSerializer.swift */; }; - 8CAC5FC27179F135AF242D41132C9EEE /* ImageTransition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49018C17822EDBBF1884E2E006CBF261 /* ImageTransition.swift */; }; - 8D0484E61C49B3CCE8813F74FE24321D /* Core+DispatchQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD5233B5ACF9B9672AA3AE6C355FF3E9 /* Core+DispatchQueue.swift */; }; - 8D624ACA08FCB438A9DDEDDE26227601 /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 149514E97BAF548B300815CC102F02D3 /* Accelerate.framework */; }; - 8D8C4F46D776DAB6A3B71DBC71485902 /* Picker+PhotoAsset.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F3FBB0051619CE6CC673EAD87D1940E /* Picker+PhotoAsset.swift */; }; - 8E84CC64780B1836225593EE471ECEDA /* EditorConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 930641217CE7625ADB374829A94CCA81 /* EditorConfiguration.swift */; }; - 8FB9A1648EEBA50A101D298EB13ED3E2 /* Kingfisher.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2502A860F0A5D1C292E6E8F48D02A606 /* Kingfisher.framework */; }; - 9074713D3EE739A9759A47516C3388D1 /* PhotoManager+Language.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB5691815F77BF894DB9C887C2F9231F /* PhotoManager+Language.swift */; }; - 90E11FBF49BCD3B7AEF6C38146817896 /* CropConfirmViewConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4ACC2DF1D1BF3200F0D5D263A1F405DB /* CropConfirmViewConfiguration.swift */; }; - 916846A7516CCA437809B19BA1A91F5B /* PhotoPickerController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CE26138680D4ED69EA35BA9E5EDDFDF /* PhotoPickerController.swift */; }; - 9309134E89EC613E07DC68FB303D350C /* AlbumTickView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20513BAF16D62230CAE551868C98675 /* AlbumTickView.swift */; }; - 9491BD5BE854440690205764C55AA51A /* PhotoPickerViewController+SwipeSelect.swift in Sources */ = {isa = PBXBuildFile; fileRef = 274D10D8BF7692BA4FE1A10BDDB40188 /* PhotoPickerViewController+SwipeSelect.swift */; }; - 94B9629812E39F9549BB609CBF716848 /* PickerBottomViewConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = FB78885389B2F94B85F99BB123138879 /* PickerBottomViewConfiguration.swift */; }; - 97AAFE6AD88A3AF29A42965ECC9A9EAE /* AppearanceStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CB7911DD2178CE74C965635DDCF814C /* AppearanceStyle.swift */; }; - 988AB39B0A4B3979280E04AB36732573 /* AlbumViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 93787EA42D0CB0E0DB7D3E5CFC95CCE0 /* AlbumViewController.swift */; }; - 994F4E5ADA2D6713741B8F8E02189DF8 /* Storage.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4A4E9D17CFB6CD3E87B02CBB62A4B33 /* Storage.swift */; }; - 9AB7F1490108CD7240E4D0C4B74F6741 /* CacheSerializer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CE68A4E643E473D0E784A8FA2A7E71D /* CacheSerializer.swift */; }; - 9B395164BC3C685D33B3D75CAB3CAB53 /* ImageView+Kingfisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = A19355BD23C3F1BD773CBCF0894CFD4E /* ImageView+Kingfisher.swift */; }; - 9B73B6FF0FB5382008A957BFA1B7E7B5 /* EditorToolViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DD0466B10B0558368BF1C65D70E2EFB /* EditorToolViewCell.swift */; }; - 9B8666F269756288DD1240BE7755F523 /* PhotosUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0DFEFB85B8D69EC95DA13127B05085EE /* PhotosUI.framework */; }; - 9BB50D9DEC61DBE55023247658591290 /* Core+PHAsset.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D24914BBAD96BEC89719F3CAD50D605 /* Core+PHAsset.swift */; }; - 9E2915E7A13B7C54F557BBCA31D68172 /* KFImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012C6C8D971C249854A1F7DD76702EA1 /* KFImage.swift */; }; - 9E330B945E4A187A39691B93498537ED /* NetworkAsset.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAF0BE88CF2FD74AF5588F55CD6D76C3 /* NetworkAsset.swift */; }; - A07CB9EBB03F2054E4EB5E91F621A8DE /* AssetManager+LivePhotoURL.swift in Sources */ = {isa = PBXBuildFile; fileRef = E65DA63DD4AD4E432FAD881813877823 /* AssetManager+LivePhotoURL.swift */; }; - A1AEAFB890D9D43080CD9BC9B0400A3B /* Editor+UIImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D9BFD4E9DD6EE91B400C568802A731F /* Editor+UIImageView.swift */; }; - A31A83BE603C9622763E0F2B1E0FE292 /* VideoEditorCropView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07B5BC0DCE286D3ACA675FCAECE8F641 /* VideoEditorCropView.swift */; }; - A4B51104D86C0966893651D23EE761B6 /* LocalAsset.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60433D7514CF80497C4891C8F6FA49A6 /* LocalAsset.swift */; }; - A54081DDED58482833ADAE0F49F26676 /* AssetManager+AVAsset.swift in Sources */ = {isa = PBXBuildFile; fileRef = 399EF8348A2B332A84400E8075EA42A6 /* AssetManager+AVAsset.swift */; }; - A555A68F52A8EAD989E40F5D92D76699 /* AssetManager+ImageURL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7378427FDA946DF5B716338C86805FE1 /* AssetManager+ImageURL.swift */; }; - A73D0C131526B571A16DFC6AC36719E5 /* EditorToolOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A98566174094B340F2EED50D8D01CC7 /* EditorToolOptions.swift */; }; - A7F8C60F22227E0C42CF7A27EE4656EA /* ProgressImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32E577CB345214F9D6E8E9AD4CCFC928 /* ProgressImageView.swift */; }; - A8B186222182CBB7F1366BDD4A3116A3 /* ImageContentType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AB50CCAEE13DBBDE49A969469366978 /* ImageContentType.swift */; }; - AAA4DEA8A44AB55FA2BD37687E2EFFB6 /* PhotoPreviewContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9941EF650C94303373933DCB0374B042 /* PhotoPreviewContentView.swift */; }; - AADC8491F654A9998E5E2614DB583C61 /* AnimatedImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97F844DC348A2765E002617A3E8219A3 /* AnimatedImageView.swift */; }; - ABAFCADF4B1F105DD5F8B478BF8FE299 /* VideoEditorPlayerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40565C0E5DF5F1754DDB4BC58488CA8A /* VideoEditorPlayerView.swift */; }; - AC2E403578F6DAA216520439630EF6D0 /* PhotoManager+Audio.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EB1CEAC38537E23AF5B9EEF4224CC28 /* PhotoManager+Audio.swift */; }; - AE05DC1B821550CE78ADF28ABBBA56BC /* GraphicsContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 59181372FE2D9AA0C9258A82C9B4E08A /* GraphicsContext.swift */; }; - AED2FEC0F5BFADFB2505CF5B6FE4E0B2 /* Kingfisher-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = A91D9D790AADDF14B73DBCAFC93AF139 /* Kingfisher-dummy.m */; }; - AFBBE2117422FD49A7AFC14AEDFE217B /* PhotoEditResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = E23FF50CBEF9896F69F8C33C30A0109F /* PhotoEditResult.swift */; }; - B0B200F35509242200121DFD8A71A160 /* CallbackQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 932030BAAFCCE92F8F74AAC8BDE262DA /* CallbackQueue.swift */; }; - B0F1C8C1EFCB027EF51F1C90C04A2800 /* Box.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A5ED54FE8C5DA5F6544AE3D040E27E4 /* Box.swift */; }; - B12C803CCE9A970706A690C2741F7F27 /* PhotoEditorCropToolView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C3042A1C731FA1D1F809D292A9DCF78 /* PhotoEditorCropToolView.swift */; }; - B1B3C3D647A8DB3D67E961896C61F882 /* VideoEditorConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2EC251D36D9079F779067D48D0750946 /* VideoEditorConfiguration.swift */; }; - B280C949DDF9D549731AF1C598CCF9F1 /* ImagePrefetcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0D1FF42A8AD7FE58E8E8CAA3624C117 /* ImagePrefetcher.swift */; }; - B3C775AEB56C0373F519E5AC31495887 /* PickerTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A53D58E9CA25D13DD8BF367063D444B /* PickerTypes.swift */; }; - B5452D06EA8F0FA2B76F4CA5851BD3E0 /* RetryStrategy.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD4AF271F2F5F7E36C3324DBF2EFD73F /* RetryStrategy.swift */; }; - B57412E02A43D260681220B7CA512831 /* PhotoPickerBottomView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39495AB0F9B887AFACB5C7CEE8AFBF53 /* PhotoPickerBottomView.swift */; }; - B94506476A9DFD76DA50C057C96E7864 /* Picker+PhotoTools.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1278BEDF9340DEF89E35C3AA316E50B9 /* Picker+PhotoTools.swift */; }; - B9EA11C9E0E9220D95BE1A11D9ACEADE /* Photos.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C6928EC52A16376108CACDBEBAA774F /* Photos.framework */; }; - BAB4B5F0F708D8D7A77D65A689F10833 /* RedirectHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31608F4F2C2474D9D9CA8EC4C9272FE8 /* RedirectHandler.swift */; }; - BEC72EA390EBF57606126D2B8694CE66 /* Core+CALayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1EE561EF370C515FF47278EE93FD9EE /* Core+CALayer.swift */; }; - BF2201896CF1479700394E989F728F4A /* ImageModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91610E715C8B8695F02B8352CC6C1C95 /* ImageModifier.swift */; }; - C009A9CCD79C1C930FCC296B393D8B84 /* RequestModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = BAF505057CA7719DD20860C6B607AB19 /* RequestModifier.swift */; }; - C28C4720D62A993897AAF4156B6910E3 /* AssetManager+ImageData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 832E000FACA6AD9958B6822E85D157BC /* AssetManager+ImageData.swift */; }; - C3B8BB6A464123E12749E41C42CA7A68 /* PickerConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BD7BEECB15A0E197A4C7FC3F3536B5E /* PickerConfiguration.swift */; }; - C40330052161D5B1451616A0749F40EB /* PhotoAsset.swift in Sources */ = {isa = PBXBuildFile; fileRef = C813900019839F0CB70608F2F3CDB23C /* PhotoAsset.swift */; }; - C4B37D549AD8E84B06B0EE2751B4A4AE /* PhotoPreviewViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77BC73F398E8C855D1B45CB97FDD7BC3 /* PhotoPreviewViewController.swift */; }; - C5D3D6D13C4A496F8AD3086E56071695 /* HXPHPicker.bundle in Resources */ = {isa = PBXBuildFile; fileRef = F54610899D0457A64E9CF06BD1A9CB13 /* HXPHPicker.bundle */; }; - C5EC1C4482BA70E9AD148853BB5DE251 /* AlbumView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDBA3B9B2A3A5A8429A5E40D8189F85E /* AlbumView.swift */; }; - C67A799566A361E17C1B001EB35830AC /* PhotoEditorContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 14EA16CB3672F9ECFC825BFE03542467 /* PhotoEditorContentView.swift */; }; - C7E1E72828608CA75568B28281B7283D /* AssetManager+VideoURL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28C3604C69772C27DD79C7BE69E40200 /* AssetManager+VideoURL.swift */; }; - C962F2A83A365AB35DC0A7ECC2E7B144 /* PreviewVideoViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFCAF459B63CB461D420ECA303B2D6D9 /* PreviewVideoViewCell.swift */; }; - CC80FE337DD5E8F1C38B6758F81C0567 /* ProgressHUD.swift in Sources */ = {isa = PBXBuildFile; fileRef = 347CBBFB5B67E48EEAB7CF3C25E42653 /* ProgressHUD.swift */; }; - CC9BB4E0DB2A96D433EF2D9C558BA694 /* WKInterfaceImage+Kingfisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83C46EBB94B2DF6B435144D05BF0A331 /* WKInterfaceImage+Kingfisher.swift */; }; - CE36694881ADED5E8545B2874709B00E /* PickerTransition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56E702AA502667D742CB245D322D6AD0 /* PickerTransition.swift */; }; - CFECA6FD0CBE4C2600A054B56342820B /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC2A668332C08973296C3E1D60EE54A2 /* Result.swift */; }; - D14F97AC47A554CC340E97F5EA2870D0 /* ImageDownloader.swift in Sources */ = {isa = PBXBuildFile; fileRef = F26C814FEFAFBCF3830A5F27E639C958 /* ImageDownloader.swift */; }; - D3504C0066F7E032A4241F9D08EB1191 /* ImageDataProcessor.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED9410EF4B36DD248DA96CA6179A23C5 /* ImageDataProcessor.swift */; }; - D3BEFA5551502BB15839DDC4DBB17DA6 /* PhotoEditorConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B0556648367EF7BE0BBDA2C2DE33EB5 /* PhotoEditorConfiguration.swift */; }; - D4BE2BF268794034BC873C5697767581 /* PhotoTools+File.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C5D81B2769F3E2F9633C5F73B50C5F3 /* PhotoTools+File.swift */; }; - D71A449EE428E83E0A9929F6298BFA4E /* PhotoPickerSelectableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE155CEA770DE8908844B4751507F566 /* PhotoPickerSelectableViewCell.swift */; }; - D8735E1A0E2C163B658452A72C57CBD6 /* Picker+UIViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1064B2319FF1C94864B2CE729285F9B8 /* Picker+UIViewController.swift */; }; - D8A13ADBFBE2CC69B60A9FEB063BC005 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 076583A24FEFF346EEAD16B805234FCB /* UIKit.framework */; }; - DB452964085755719A4EFBC2927740BC /* Kingfisher-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 578326974025F0EA83D68C1CCA4D05D5 /* Kingfisher-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - DD3D33CF95D12F03D62901F82EDF6892 /* EditorCropConfirmView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 562321E3DBAA38414FA20AEDF5EA214C /* EditorCropConfirmView.swift */; }; - DE7B9075AE4019B159CF5ED8E3033145 /* EmptyViewConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AE851F339FBCED4B53662017B5E7FC7 /* EmptyViewConfiguration.swift */; }; - DE982596DE1BF157C1D3E080D908F62E /* PhotoError.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1C97C36F6828D4797C004539D3D31E8 /* PhotoError.swift */; }; - DF627F7A09CAD7B64D1FACCFCC4DF3E9 /* AssetManager+Authorization.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C8BEA4AE65FAE282E599E49304003A4 /* AssetManager+Authorization.swift */; }; - DF83E1117DFD6586FA953D88DAEE5D9E /* AssetManager+AVAssetExportSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = 868C8FA5D842678E85DEB2612008F42C /* AssetManager+AVAssetExportSession.swift */; }; - E004165DAADCE810F7DB431BB2DAAC23 /* PhotoManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21238D3AD6B82A27C7FDDE411816C9E9 /* PhotoManager.swift */; }; - E00EBD8D05FAEF43E0A635EB513963C1 /* KF.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AD4CC80D5778FB3376CF363868F97E9 /* KF.swift */; }; - E1CC3B4A5805D447A92D7098653F2A0C /* PhotoTools.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C446E94E2154761F17EA4E3FC15163D /* PhotoTools.swift */; }; - E1DBF6743011B7D4D5662ECCBA84A91C /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CA88A8AF447A5943F95AF07C7654F716 /* CFNetwork.framework */; }; - E1EA414B4CB5CAAADAEF1C11B8E7B559 /* SelectBoxView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 00CA69F728A555325DA084E0234B3A50 /* SelectBoxView.swift */; }; - E2ABD61C4DD752D58BFA8935294D5FD4 /* Indicator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E678D061152320522BA2A9B126A6F8C /* Indicator.swift */; }; - E43919F194110BBFD2A02D2A711EA234 /* AlbumTitleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 435165BD18BE952E53ED4496283BEA2A /* AlbumTitleView.swift */; }; - E64DD7C71134EA792E31F82618B1DB8A /* KingfisherManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6FB240C8C04CC2A7F305F6A27A8A9D0C /* KingfisherManager.swift */; }; - E762932881E044CB4875C358BC1247B3 /* PhotoAsset+Request.swift in Sources */ = {isa = PBXBuildFile; fileRef = 99DA44C4AA4F687FC6AE64DB7411C7BB /* PhotoAsset+Request.swift */; }; - E7CC9880CD9ABA88C346E93A7AD7F232 /* PhotoEditorMosaicView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 393CD8E55D303D5416D741CEDFC7AE48 /* PhotoEditorMosaicView.swift */; }; - E97E9A295FE2AE93CBC73A5469390FEF /* SessionDataTask.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6412FC162B13556AC831867D400FA4D6 /* SessionDataTask.swift */; }; - E9D17314462863455C45F8019C65CEDA /* PhotoEditorViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7769420A27CAC894C5724E42564AE82F /* PhotoEditorViewController.swift */; }; + 7ED480945ED8DA17DBCEAF75DCA0ADA8 /* ImageProcessor.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2A7512ED739726CA517F36C54B774B5 /* ImageProcessor.swift */; }; + 7EFDC706CC94DCA239557D732B5AB10A /* NotAuthorizedConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A1A1AD2E31935C4069D180698D4B300 /* NotAuthorizedConfiguration.swift */; }; + 7F5CAB06843CFC9E068820A2DC3D10F1 /* AlbumTitleViewConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = B35583C68EDF828E55A5B909CE97E60C /* AlbumTitleViewConfiguration.swift */; }; + 803C8CE75562090DAE5D7A4CA40E1074 /* PhotoListCellConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75E6A612C39CD25A693B862022E1E861 /* PhotoListCellConfiguration.swift */; }; + 814430C0EE52BD375FF69CC51AA9FEB8 /* MemoryStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44EB32C6F0F69E0C6D73EEE192EBEE50 /* MemoryStorage.swift */; }; + 81645640A5520231D6E141B11DC71CE1 /* Core+DispatchQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BED76A0F3AB74CD3E2060A361D516CC /* Core+DispatchQueue.swift */; }; + 838217014E56CBF64E6BCF795277C17C /* PickerTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8E94E14400898B18B1EB176526DB9420 /* PickerTypes.swift */; }; + 84F2219C0F7FACB75AD2B81DEF9768B4 /* EditorImageResizerMaskView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DCAC90FCDF67BB7420B528333888A71 /* EditorImageResizerMaskView.swift */; }; + 854E8DBC96B7C04F1EDE6F82634EBD6C /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC2A668332C08973296C3E1D60EE54A2 /* Result.swift */; }; + 8648DD1D27BD991CDA555CC605959080 /* Core+Data.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9C4F29EDC2D5EA82CA16D831E0B6F24 /* Core+Data.swift */; }; + 869AF52FE033B5E15C1AF6C6F1CF98F8 /* Filter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64859EB840E1B0ADB4524B39239AC173 /* Filter.swift */; }; + 8967B1298688386541ADCBED7217CDBC /* SizeExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6FC78B1FC94C1B1D29105230125C063E /* SizeExtensions.swift */; }; + 8A9AFCA8F716CA06BFB885F9C99E82F2 /* Core+UIImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C21CCC463978FD90835D06157C0F0A41 /* Core+UIImage.swift */; }; + 8B113234FB4A866B9F70D076FFFD3AEA /* AVAssetImageDataProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44057F66C5C77C9B40B6CF9C8BD32AB3 /* AVAssetImageDataProvider.swift */; }; + 8C21DFAE814D3D8525280708E39CBE5B /* EmptyViewConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = ABDE32A6D86C86F774CE63D72A29F33F /* EmptyViewConfiguration.swift */; }; + 8C8BDFF216DE12E1D1F6CEE8F74B1E2A /* PhotoPickerControllerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4221C82F020312B9ABABFC4625E574D4 /* PhotoPickerControllerProtocol.swift */; }; + 8D545B568D65C54C7B7D61DD04255637 /* PhotoEditorViewController+Animation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 393D1A2C20CED9E766A07B87F987EF5F /* PhotoEditorViewController+Animation.swift */; }; + 93368B7B05E3A813F2BD10396B8A66AB /* PhotoEditorCropToolModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C96763AAEA238547056A5E47A0724E1 /* PhotoEditorCropToolModel.swift */; }; + 93CECEEE40B49CA8E8646BE918495D42 /* PickerBottomViewConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A6C56626C1C22322F7454CA10D9D947 /* PickerBottomViewConfiguration.swift */; }; + 93E69810EE11007048B9D1E26456083D /* PhotoEditorViewController+Request.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3EEBD8B7D2B99F3EB22F51AF071CE35 /* PhotoEditorViewController+Request.swift */; }; + 9579D82AE68CC88199FB637E4E662067 /* AnimatedImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97F844DC348A2765E002617A3E8219A3 /* AnimatedImageView.swift */; }; + 95C5D3C281663A8A34B49D39519F9AC4 /* EditorConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AE83272ABB8F7BE9A624B5D73185FFA /* EditorConfiguration.swift */; }; + 96A8E934DCBB01D8C01D52F284CB8A6A /* PhotoEditorContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FAC9361D156824AC15428F16BF61EE6 /* PhotoEditorContentView.swift */; }; + 974D213654CF414053144CDEB7006DE2 /* RequestModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = BAF505057CA7719DD20860C6B607AB19 /* RequestModifier.swift */; }; + 97781F95C4B7FCD9A6B1B623EF70477E /* EditorStickerTrashView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 640ED6DA1D830AE84C026E59A5A0A089 /* EditorStickerTrashView.swift */; }; + 984FF16C92999E5E3F1B30B9518FFAC4 /* LivePhotoError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2529D5686E3CA4F08BA564C0D5D71403 /* LivePhotoError.swift */; }; + 998C8394F7B6A2A12A721A4296BCA31C /* BaseViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 531EEF01BF14E556D3BF4E84DAC9FCB2 /* BaseViewController.swift */; }; + 9A5150B93A7AE324EDFB80D93B95D9D9 /* AlbumTitleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFFA27C9ED669FF64D29F60F6B5B0274 /* AlbumTitleView.swift */; }; + 9B2BED9A1B5B19576030784EBD528FDD /* VideoEditorMusicAnimationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40CEA5DD7A853F6B5BE36A6EA1F48FCD /* VideoEditorMusicAnimationView.swift */; }; + 9B619D7E216337541D6C09858484FD4D /* Runtime.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF82715186FC43646CCDE8B5A9B75524 /* Runtime.swift */; }; + 9D9E6F0413FA459195D0114BB059D721 /* EditorStickerItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED56BC152265BC047FBBFF628A7FE04D /* EditorStickerItemView.swift */; }; + 9E6F7DAF1D8CE6A8B973F1BC17683C7C /* Kingfisher.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2502A860F0A5D1C292E6E8F48D02A606 /* Kingfisher.framework */; }; + 9FC6E2CB0A0042958753D6227619ED18 /* ImageDataProcessor.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED9410EF4B36DD248DA96CA6179A23C5 /* ImageDataProcessor.swift */; }; + A01E4A1EFF57C54F97858659F34904BB /* AssetManager+AVAssetExportSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7556215365F7415A0C3CB7D2340BDB6 /* AssetManager+AVAssetExportSession.swift */; }; + A02F8A13DF9C8952A32C5CBFF4C0E866 /* Core+PHAssetCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11529B77A8050B2C53CC45D8075176E9 /* Core+PHAssetCollection.swift */; }; + A3425538BB4D35127BEAB4E4345F3BD4 /* PhotoEditorMosaicToolView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F2032572C9F787B59664C732AF01595D /* PhotoEditorMosaicToolView.swift */; }; + A39F1855BE4B33A5FB3E7D3C138A6326 /* Editor+UIImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B2928135BDA49032CE7C48A71B99AC8 /* Editor+UIImage.swift */; }; + A3BB637A1C697DDD25AE12A979726B8B /* KingfisherError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C68E3B655283C5ADCD7D12044A2BD03 /* KingfisherError.swift */; }; + A493E1475E7FBCA4FE3E36712F4EC3D0 /* EditorImageResizerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F14DE66B4E355A94782F996E6DAFBEB /* EditorImageResizerView.swift */; }; + A5CE440D715C784A74BEBB5C7AFB3DE2 /* CustomLanguage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06820DCDBB2A25DC1B048442B04CE108 /* CustomLanguage.swift */; }; + A8E7B90F6A6F1E48394B35740B3CCC4B /* WKInterfaceImage+Kingfisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83C46EBB94B2DF6B435144D05BF0A331 /* WKInterfaceImage+Kingfisher.swift */; }; + A9899A068ECD5F3810E6998D3DD415E7 /* PreviewPhotoViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFDCB9B82E208AA6A69A9F49DAF14549 /* PreviewPhotoViewCell.swift */; }; + AADCCFAD443D97C1F033E15AED37FE5F /* HXPHPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94354ED183F6FDBBAD76319C22F8E0E6 /* HXPHPicker.swift */; }; + AEC3E6D8E32C26A9DB9AEF427D3425D6 /* ProgressImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD19B924DF5EBB6FA318331966BE818B /* ProgressImageView.swift */; }; + B0DC1E39940C7486F0D596443E8061F7 /* CropConfirmViewConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82F74FDC712BFDE6509B6E79F037D141 /* CropConfirmViewConfiguration.swift */; }; + B15D2E8B1EBBFC7CD654E2EE999F857F /* EditorToolViewConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 601E50F79FCB543B83354FEDAC5DD99F /* EditorToolViewConfiguration.swift */; }; + B1D7F03D8BE5579DFF61754E0F8D1089 /* AssetManager+Image.swift in Sources */ = {isa = PBXBuildFile; fileRef = 562873123116F153C238FBC76B789ADC /* AssetManager+Image.swift */; }; + B2D56AA9B691AEDC91403E0D29EF5873 /* AssetManager+VideoURL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 778C2F66B7672CC04E6C9CF4CD600C1A /* AssetManager+VideoURL.swift */; }; + B2E52DA137487D10E4D41B8EA2D6839D /* CacheSerializer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CE68A4E643E473D0E784A8FA2A7E71D /* CacheSerializer.swift */; }; + B4F80FA3CF53686695C9A00777FB40BC /* HXPHPicker.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 7B05A3B63B09302EC01FD1DB831D63E6 /* HXPHPicker.bundle */; }; + B6D60155FC9171F171BDD35D6FFE0430 /* GraphicsContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 59181372FE2D9AA0C9258A82C9B4E08A /* GraphicsContext.swift */; }; + BA05DBB552919B860B50815C40A74274 /* Core+UIFont.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67C0F210CA2203D043BA26DAAC26B62B /* Core+UIFont.swift */; }; + BBD5D0BBBD0B5B7643E342E494F663B2 /* PhotoEditorConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7774CD23C7037BD21F3774D56A2CCA08 /* PhotoEditorConfiguration.swift */; }; + BCD566578AF7490F2EA43136342FBF6B /* AssetManager+LivePhotoURL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 925AB67D69D139C4CA3936AC6D7CA86C /* AssetManager+LivePhotoURL.swift */; }; + BFA21F8FC5B7359E415F295D3FC68895 /* AssetManager+ImageURL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D79002CD77B4E701030F2586A87818F /* AssetManager+ImageURL.swift */; }; + C0A433620EC92C6C1F2773EF0ADA14C1 /* ImageCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = C11E0F29122AC9F7339A1462FDD4D9B9 /* ImageCache.swift */; }; + C1081D7D2DAFB981699C3FA4445901ED /* ImageFormat.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DC889CE6056F86A66BF6041B2F2C989 /* ImageFormat.swift */; }; + C158FFC0DEC9C12B72793335DF68C42C /* NSTextAttachment+Kingfisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B81DECD774F3D4D9429BE878A52C23E /* NSTextAttachment+Kingfisher.swift */; }; + C5466E46FC92A6C76FF8BBEFA9B4101B /* PhotoPickerViewController+SwipeSelect.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E7B8A98BDCD775D95A65561CB633988 /* PhotoPickerViewController+SwipeSelect.swift */; }; + C7600CE2AAB4E8771DFFCAB7D20C107C /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 149514E97BAF548B300815CC102F02D3 /* Accelerate.framework */; }; + CCAD386E55B5A4D7F3C4BAB512CE564B /* EditorStickerTextViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A4A77CE2F054070C1EC646B504A7E27D /* EditorStickerTextViewController.swift */; }; + CD49E913230C9E39E1FB4B3F0924958A /* ImageDownloaderDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DB8EED1C5ED86CF23C451AD85D5ACF3 /* ImageDownloaderDelegate.swift */; }; + CD6FE7C22133F548ED833A2F5187F771 /* PhotoAsset+Codable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C90D008920575AFDBAB1E440D6846285 /* PhotoAsset+Codable.swift */; }; + CE73AA7A30E9E144590EB8E4345E760E /* ImageModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91610E715C8B8695F02B8352CC6C1C95 /* ImageModifier.swift */; }; + CF7C19428C8AA00EF5E46953962CD748 /* PhotoEditResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = ACD0ED004361D4FB1A8A3A4C789F9F36 /* PhotoEditResult.swift */; }; + CFD908027CF25361E3C6B9E8CCE2CEA2 /* PhotoPickerViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F43676462AFA99D7CA9A029E51372ED1 /* PhotoPickerViewCell.swift */; }; + D0AD2A4EA83479DCA89D922A78EF9E41 /* PhotoAsset+URL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20FA873B324A5E85740C531E13CFCFCB /* PhotoAsset+URL.swift */; }; + D1182ED1DCFD17A68B2CCF423DC166BF /* PreviewLivePhotoViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 547272275970D4CE23C428E23093CC37 /* PreviewLivePhotoViewCell.swift */; }; + D202DE78FF054C75156FAED3E052DD40 /* PhotoListConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0695CF13DF659A9995256DA724C9F2C5 /* PhotoListConfiguration.swift */; }; + D2589DDA1844AEC2442ADEEF1D260FAC /* PhotoManager+Download.swift in Sources */ = {isa = PBXBuildFile; fileRef = A566C25E75296EF7C4633A6B69326371 /* PhotoManager+Download.swift */; }; + D34EDE04C16DF0F63D25FF04BE074943 /* PhotoCroppingConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE752415B71C6B20179128E19513AD63 /* PhotoCroppingConfiguration.swift */; }; + D4753539AAA5FF82CC30B50B71497136 /* Core+Bundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71812356610599E70B089E7AC48C42B6 /* Core+Bundle.swift */; }; + D56F4F1E6A1B5FB1C4CB93971D0E8EAD /* EditorToolOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20C424910C56FC8369CE2F1BB9DD9A99 /* EditorToolOptions.swift */; }; + D5B93E117475B4099A3F671B39C40A12 /* AssetManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5493ECCBC7EE357FB08A312C5187DA7 /* AssetManager.swift */; }; + D6FB5258A326AB85E346F5720EA478C6 /* PhotoPreviewViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6FB653B8C90C89078F860D375DD46741 /* PhotoPreviewViewController.swift */; }; + D8924C0DA4F8782C016B0EFE494528A5 /* CallbackQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 932030BAAFCCE92F8F74AAC8BDE262DA /* CallbackQueue.swift */; }; + D8EB3FC1D33F8B83D72FCC30FFBFA074 /* PhotoAsset+Network.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA8235D2AEA9034EBA2CAB7C44A4C739 /* PhotoAsset+Network.swift */; }; + D9E974B9341636BC643C7A8DA173B120 /* Kingfisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 685C1A1F8C91B4094AFA8691254D72E5 /* Kingfisher.swift */; }; + DABA772FDB25ABCF98234C1D56D4A8B6 /* Picker+PhotoAsset.swift in Sources */ = {isa = PBXBuildFile; fileRef = 922AB5F39B78FAE087B4877B51BDD90D /* Picker+PhotoAsset.swift */; }; + DAF0DA7AEB8ADB78DB49460DFEF62EF6 /* CameraConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5DA54C12769FCD2DD2E24256B7F8F72 /* CameraConfiguration.swift */; }; + DB5E17E749AB87855A28F0077FCD5D79 /* PhotoError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 99B5F52EA74DF46254B99C01593AB86F /* PhotoError.swift */; }; + DDAD04ECFE1D8DF97690828F849B0DA9 /* PhotoListCameraCellConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8CFC0438D17803CACF407B6EC1F3E92 /* PhotoListCameraCellConfiguration.swift */; }; + DDC4CEDA780C14B21BBC8CC68FBAC6AE /* ProgressHUD.swift in Sources */ = {isa = PBXBuildFile; fileRef = 128913A67D37CFEBC3CC0ED2B96963E4 /* ProgressHUD.swift */; }; + DDFFAFE5E71D9227AB7DEC1FDC2D4A77 /* PhotoEditorDrawView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B15A167734DB17B64D7129AA996428E /* PhotoEditorDrawView.swift */; }; + DEDADC0D1E2A6CDBED553833F39706D9 /* FormatIndicatedCacheSerializer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 120393950CD497675338B3E1C9EB8B4F /* FormatIndicatedCacheSerializer.swift */; }; + DF45457B6F4DF804FE6F4A19E564E7CE /* Kingfisher-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 578326974025F0EA83D68C1CCA4D05D5 /* Kingfisher-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E0D63DDD15325F164E480E0914DC2A41 /* PreviewVideoViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C227B478900D15729E225BE531D8946 /* PreviewVideoViewCell.swift */; }; + E18A42D3B7EEE940FCE6FBFF185EDD0C /* Delegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB65976E1F0710E684127792006DF1D4 /* Delegate.swift */; }; + E249472D07E2AABB662E011A881F3EF4 /* DeniedAuthorizationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C31101F6E37090746349715B96C9ABF5 /* DeniedAuthorizationView.swift */; }; + E4A8B7A0770BE36D5960BFB5190A6FD5 /* ImageDrawing.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF58F49EBCA386B0EF516C3557F8ECA9 /* ImageDrawing.swift */; }; + E537966080A9114A6DE2B4C856BE6339 /* PhotoPickerSelectableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 99BEEBF1C3DC35EAE886EF7A232D3D22 /* PhotoPickerSelectableViewCell.swift */; }; + E5EFFF3D480415F61175DCB4EB5D30E6 /* AssetManager+Authorization.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9EBA2C0E0BA1ED2B1D2424066952CAB /* AssetManager+Authorization.swift */; }; + E90A1A2ACF3F9A80EE087E408A8FDFD4 /* KingfisherManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6FB240C8C04CC2A7F305F6A27A8A9D0C /* KingfisherManager.swift */; }; EACFEF61485455E3DAE8BF5D0568A8DD /* Pods-HXPhotoPickerExample-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C67189919282FF8D227B845A7F079C0 /* Pods-HXPhotoPickerExample-dummy.m */; }; - EADD40946B12E7DC40E47134684B2AC2 /* VideoEditorMusicAnimationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 98E0603A4E03E57E7695F8194AC792B5 /* VideoEditorMusicAnimationView.swift */; }; - EB669B6FD1E2DF2F4C8EC4D461D12928 /* VideoEditorMusicView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 16860602361C1B4B1BC81BA5BC4762F9 /* VideoEditorMusicView.swift */; }; - EBE837C954B7DCC9854B611DB98B38B7 /* Image.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8AD2839A5327532E0A5CAD720F73099 /* Image.swift */; }; - ECFC3E74616084F01177C3B063E03CFD /* LanguageType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 91CE9F7A8548481CF2153C1EE7C28958 /* LanguageType.swift */; }; - ED9DFE874C96389F12E57FF354AEE096 /* Core+URL.swift in Sources */ = {isa = PBXBuildFile; fileRef = ADBCF2C1F6B918828450523DFE5EAA55 /* Core+URL.swift */; }; - F0ECCB476E625BF8D0C1564F1BBB82FE /* Core+Dictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A08AEFD3EF5DD92F1C62C3076F53E31 /* Core+Dictionary.swift */; }; - F248E3555B933BD707D77E0F41046DAD /* PickerCamerViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 230C7F91CA2126BEFA59E947E57E48E9 /* PickerCamerViewCell.swift */; }; - F417FC09ADC8F8F0EBEC002FFF3C17F9 /* PhotoPreviewVideoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC7E51B729C48D2CDC3E3F7D28CB4AA8 /* PhotoPreviewVideoView.swift */; }; - F6C0366EE9B0050741930370C48AE1AF /* PhotoPickerControllerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = C16051339A3ABA4B72958557C53630D5 /* PhotoPickerControllerProtocol.swift */; }; - F7DA6EFBB532EFEEBACD8DA001F463C8 /* Core+UIView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 288B0C38BED59BD62A68D32EEDB6E1D6 /* Core+UIView.swift */; }; - F83E52B5DD84356CC6D381D104E0510C /* AssetManager+Asset.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6FDE1FACC4C252967F8A52F8A003EB75 /* AssetManager+Asset.swift */; }; - F8E53C5DEEB48F76AD3E5196E4F0C8D2 /* HXPHPicker-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = B709B0FBEA1226AA6EEBA1388DD9B359 /* HXPHPicker-dummy.m */; }; - F9B0518B59217A1150BF204041629FCB /* GIFImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FEA9291F441E8AB422086ADED6C80791 /* GIFImageView.swift */; }; - FA0827C8B221F88DED21E0FE23E3AECA /* AlbumTitleArrowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBF7D3D6FDAB3790527AFB5B79178329 /* AlbumTitleArrowView.swift */; }; - FD57AECC2FAE39B6BA653D264D305EA3 /* HXPHPicker-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 765C30F1D982A3BDA6E68508F94E615E /* HXPHPicker-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - FDCB190E9998DB7926E592645867D01A /* Core+UIFont.swift in Sources */ = {isa = PBXBuildFile; fileRef = F034C0845F804BF4035366CBAA8EEF8A /* Core+UIFont.swift */; }; - FE00FFA33CB3D9FF548FC57C9CFCBD9C /* PickerResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DC0FB7A4C3B2FA833748E4B9AF10B48 /* PickerResult.swift */; }; + EC21BCE9E4A66E579EC78AEA6EF67CD7 /* SelectBoxView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE6E57EB6B1E40BA02666FDBF20FD3DA /* SelectBoxView.swift */; }; + EE399BAFD9CD394E74CB51297DF5617B /* ImageView+Kingfisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = A19355BD23C3F1BD773CBCF0894CFD4E /* ImageView+Kingfisher.swift */; }; + EE581CD359FA4922D80C330DE28430A5 /* VideoEditResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9A0461D6318AB717C40D28E6674A988 /* VideoEditResult.swift */; }; + F149395CE971F301575135C68E3494BD /* PhotoEditorBrushColorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A14BE291C734F10CD472BE99346267D /* PhotoEditorBrushColorView.swift */; }; + F16D355B01822A074FFCE4977785DEF6 /* ImagePrefetcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0D1FF42A8AD7FE58E8E8CAA3624C117 /* ImagePrefetcher.swift */; }; + F2C882E6573E0C1322DBD1B40ABAF69A /* AlbumViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17AA31042A2107DB6B14773E3063E3FE /* AlbumViewController.swift */; }; + F30146D4EBB6AE3194F16C8F8D337CF2 /* PhotoEditorViewController+Export.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8372D0B1E8AFE84378987A633F1EB47C /* PhotoEditorViewController+Export.swift */; }; + F32B0F74239E13065E7F9110DDA94BC9 /* Core+CALayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E561675294E9B1E41841D4B69EC2FD4 /* Core+CALayer.swift */; }; + F3F5A6B066F57F049F49FAB3BDEA82C7 /* KFImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012C6C8D971C249854A1F7DD76702EA1 /* KFImage.swift */; }; + F4A42CB969434AD5125AF3243D704561 /* PhotoPreviewVideoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44382226E6FED16ABDF81E709F565C53 /* PhotoPreviewVideoView.swift */; }; + F6CB4D27C12C2592C33AA58DAD4AB2DC /* ImageDataProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = D626DEE33E886F43389E4D4C0C06944C /* ImageDataProvider.swift */; }; + F72FD70375CBD5A1088AE8EEFA44CBE5 /* VideoEditorCropView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2E11EBFC3916F6386F5C5742499E7DBF /* VideoEditorCropView.swift */; }; + F96EC1388FD22C566A553A5F804FDA7C /* PhotoPanGestureRecognizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC6E5B07C8617D54F1595DC8BC675BB2 /* PhotoPanGestureRecognizer.swift */; }; + FA4701AE677FFCB8DDF44E46331E0913 /* Source.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74142C17714428C2B056654FC8480D7E /* Source.swift */; }; + FA4930BAAB6EE6731F2C29AFE16B6EB9 /* AssetManager+Asset.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3108BD33E52BC7B7B8AB07AF906B4917 /* AssetManager+Asset.swift */; }; + FA69C49C73EB1F4F68FB6BC5B5465CA6 /* PhotoEditorFilter.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC1F04C732D001C893508ADDC6B738B5 /* PhotoEditorFilter.swift */; }; + FA93C2DDDBA1D920B5245811377F7919 /* PickerCamerViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5095ACA69E440BD72A1F998B40641A55 /* PickerCamerViewCell.swift */; }; + FC751005943A9ED4A90FDF00AF907CFD /* PhotoPickerBottomView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBB94B8F51309E444091CEF804B142C0 /* PhotoPickerBottomView.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ - 4533786AF807E09F4FACF612EA5DF52C /* PBXContainerItemProxy */ = { + 6887B6F8A5CF3390C190DF5F4BF6A879 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; remoteGlobalIDString = E8022D22FAA6690B5E1C379C1BCE1491; remoteInfo = Kingfisher; }; - BCD11FB170E6E354D421104B062684C6 /* PBXContainerItemProxy */ = { + D084644B558FCD5B70A92660C3FE85F1 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; remoteGlobalIDString = E8022D22FAA6690B5E1C379C1BCE1491; remoteInfo = Kingfisher; }; - FFDE80358A828037A3CB14CF9745101F /* PBXContainerItemProxy */ = { + E75270767A6FEC60E6DD3F56A81217AA /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; @@ -253,279 +264,290 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ - 00CA69F728A555325DA084E0234B3A50 /* SelectBoxView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SelectBoxView.swift; path = Sources/HXPHPicker/Core/View/SelectBoxView.swift; sourceTree = ""; }; 012C6C8D971C249854A1F7DD76702EA1 /* KFImage.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = KFImage.swift; path = Sources/SwiftUI/KFImage.swift; sourceTree = ""; }; + 0662662518A6290FC8C1A722A9CF987A /* HXPHPicker-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "HXPHPicker-dummy.m"; sourceTree = ""; }; + 067D5101BD1A005C8A914F9696E02C12 /* AssetManager+AssetCollection.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "AssetManager+AssetCollection.swift"; path = "Sources/HXPHPicker/Core/Util/AssetManager+AssetCollection.swift"; sourceTree = ""; }; + 06820DCDBB2A25DC1B048442B04CE108 /* CustomLanguage.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CustomLanguage.swift; path = Sources/HXPHPicker/Core/Model/CustomLanguage.swift; sourceTree = ""; }; + 0695CF13DF659A9995256DA724C9F2C5 /* PhotoListConfiguration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoListConfiguration.swift; path = Sources/HXPHPicker/Picker/Config/PhotoListConfiguration.swift; sourceTree = ""; }; + 06F7E3B1CD9CAA408FCF727E7CFFFE8C /* PhotoManager+Language.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "PhotoManager+Language.swift"; path = "Sources/HXPHPicker/Core/Util/PhotoManager+Language.swift"; sourceTree = ""; }; 076583A24FEFF346EEAD16B805234FCB /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.0.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; - 07B5BC0DCE286D3ACA675FCAECE8F641 /* VideoEditorCropView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = VideoEditorCropView.swift; path = Sources/HXPHPicker/Editor/View/Video/VideoEditorCropView.swift; sourceTree = ""; }; - 0A08AEFD3EF5DD92F1C62C3076F53E31 /* Core+Dictionary.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Core+Dictionary.swift"; path = "Sources/HXPHPicker/Core/Extension/Core+Dictionary.swift"; sourceTree = ""; }; - 0A53D58E9CA25D13DD8BF367063D444B /* PickerTypes.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PickerTypes.swift; path = Sources/HXPHPicker/Picker/Model/PickerTypes.swift; sourceTree = ""; }; - 0A7C48AC132FFF36BA1B19AC52457D00 /* PhotoPickerViewCell.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoPickerViewCell.swift; path = Sources/HXPHPicker/Picker/View/Cell/PhotoPickerViewCell.swift; sourceTree = ""; }; - 0AFAA52721AA4872285B203DE209D42A /* DeniedAuthorizationView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = DeniedAuthorizationView.swift; path = Sources/HXPHPicker/Picker/View/DeniedAuthorizationView.swift; sourceTree = ""; }; - 0B3C9D20F25D671AC5B9A148A47154D5 /* NotAuthorizedConfiguration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = NotAuthorizedConfiguration.swift; path = Sources/HXPHPicker/Picker/Config/NotAuthorizedConfiguration.swift; sourceTree = ""; }; - 0BD7BEECB15A0E197A4C7FC3F3536B5E /* PickerConfiguration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PickerConfiguration.swift; path = Sources/HXPHPicker/Picker/Config/PickerConfiguration.swift; sourceTree = ""; }; - 0C446E94E2154761F17EA4E3FC15163D /* PhotoTools.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoTools.swift; path = Sources/HXPHPicker/Core/Util/PhotoTools.swift; sourceTree = ""; }; + 09405FB889DF0D6EB6CFE76DAF940ACE /* Core+UIView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Core+UIView.swift"; path = "Sources/HXPHPicker/Core/Extension/Core+UIView.swift"; sourceTree = ""; }; + 0984B48E1917B8D20588117A5422D7F8 /* EditorController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = EditorController.swift; path = Sources/HXPHPicker/Editor/Controller/EditorController.swift; sourceTree = ""; }; + 0A14BE291C734F10CD472BE99346267D /* PhotoEditorBrushColorView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoEditorBrushColorView.swift; path = Sources/HXPHPicker/Editor/View/Photo/PhotoEditorBrushColorView.swift; sourceTree = ""; }; + 0B1B6DC206B2566D105FADA1EDCCCAB3 /* PhotoManager+Audio.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "PhotoManager+Audio.swift"; path = "Sources/HXPHPicker/Core/Util/PhotoManager+Audio.swift"; sourceTree = ""; }; + 0C227B478900D15729E225BE531D8946 /* PreviewVideoViewCell.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PreviewVideoViewCell.swift; path = Sources/HXPHPicker/Picker/View/Cell/PreviewVideoViewCell.swift; sourceTree = ""; }; 0C67189919282FF8D227B845A7F079C0 /* Pods-HXPhotoPickerExample-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-HXPhotoPickerExample-dummy.m"; sourceTree = ""; }; - 0D9BFD4E9DD6EE91B400C568802A731F /* Editor+UIImageView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Editor+UIImageView.swift"; path = "Sources/HXPHPicker/Editor/Util/Editor+UIImageView.swift"; sourceTree = ""; }; - 0DC0FB7A4C3B2FA833748E4B9AF10B48 /* PickerResult.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PickerResult.swift; path = Sources/HXPHPicker/Picker/PickerResult.swift; sourceTree = ""; }; + 0D5B0AC3D0F8E972EE384C4694E98215 /* EditorToolView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = EditorToolView.swift; path = Sources/HXPHPicker/Editor/View/EditorToolView.swift; sourceTree = ""; }; + 0D97219B6BD6B8164DE061C3150E5DB4 /* PhotoTools+File.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "PhotoTools+File.swift"; path = "Sources/HXPHPicker/Core/Util/PhotoTools+File.swift"; sourceTree = ""; }; 0DFEFB85B8D69EC95DA13127B05085EE /* PhotosUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PhotosUI.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.0.sdk/System/Library/Frameworks/PhotosUI.framework; sourceTree = DEVELOPER_DIR; }; + 0E0F1CF360C4FBD2915F628914AC723C /* HXPHPicker-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "HXPHPicker-umbrella.h"; sourceTree = ""; }; 0E678D061152320522BA2A9B126A6F8C /* Indicator.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Indicator.swift; path = Sources/Views/Indicator.swift; sourceTree = ""; }; 0FCDDCF6D7FC6E41F18B7EEC4FB9F36C /* Kingfisher-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Kingfisher-prefix.pch"; sourceTree = ""; }; - 1064B2319FF1C94864B2CE729285F9B8 /* Picker+UIViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Picker+UIViewController.swift"; path = "Sources/HXPHPicker/Picker/Extension/Picker+UIViewController.swift"; sourceTree = ""; }; + 11529B77A8050B2C53CC45D8075176E9 /* Core+PHAssetCollection.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Core+PHAssetCollection.swift"; path = "Sources/HXPHPicker/Core/Extension/Core+PHAssetCollection.swift"; sourceTree = ""; }; 120393950CD497675338B3E1C9EB8B4F /* FormatIndicatedCacheSerializer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = FormatIndicatedCacheSerializer.swift; path = Sources/Cache/FormatIndicatedCacheSerializer.swift; sourceTree = ""; }; - 1278BEDF9340DEF89E35C3AA316E50B9 /* Picker+PhotoTools.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Picker+PhotoTools.swift"; path = "Sources/HXPHPicker/Picker/Util/Picker+PhotoTools.swift"; sourceTree = ""; }; - 14473A4D04E43FB55A342C3672829644 /* PhotoPreviewSelectedViewCell.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoPreviewSelectedViewCell.swift; path = Sources/HXPHPicker/Picker/View/Cell/PhotoPreviewSelectedViewCell.swift; sourceTree = ""; }; + 128913A67D37CFEBC3CC0ED2B96963E4 /* ProgressHUD.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ProgressHUD.swift; path = Sources/HXPHPicker/Core/View/ProgressHUD.swift; sourceTree = ""; }; + 130F8F4988095CCA5E5073DB439F400A /* LanguageType.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = LanguageType.swift; path = Sources/HXPHPicker/Core/Model/LanguageType.swift; sourceTree = ""; }; + 13C3AA2223DCB5B690D31BDE0E9B10FE /* PhotoPreviewSelectedView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoPreviewSelectedView.swift; path = Sources/HXPHPicker/Picker/View/PhotoPreviewSelectedView.swift; sourceTree = ""; }; 149514E97BAF548B300815CC102F02D3 /* Accelerate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.0.sdk/System/Library/Frameworks/Accelerate.framework; sourceTree = DEVELOPER_DIR; }; - 14EA16CB3672F9ECFC825BFE03542467 /* PhotoEditorContentView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoEditorContentView.swift; path = Sources/HXPHPicker/Editor/View/Photo/PhotoEditorContentView.swift; sourceTree = ""; }; 165B89A1618AD2C9EC3471DF9110D8D6 /* AuthenticationChallengeResponsable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AuthenticationChallengeResponsable.swift; path = Sources/Networking/AuthenticationChallengeResponsable.swift; sourceTree = ""; }; - 16860602361C1B4B1BC81BA5BC4762F9 /* VideoEditorMusicView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = VideoEditorMusicView.swift; path = Sources/HXPHPicker/Editor/View/Video/VideoEditorMusicView.swift; sourceTree = ""; }; + 17AA31042A2107DB6B14773E3063E3FE /* AlbumViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AlbumViewController.swift; path = Sources/HXPHPicker/Picker/Controller/AlbumViewController.swift; sourceTree = ""; }; + 194F9FFAA2823CF7D508CB4DE27E0634 /* EditorStickerTextView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = EditorStickerTextView.swift; path = Sources/HXPHPicker/Editor/View/EditorStickerTextView.swift; sourceTree = ""; }; 1AD4CC80D5778FB3376CF363868F97E9 /* KF.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = KF.swift; path = Sources/General/KF.swift; sourceTree = ""; }; - 1B25A28755D202E5829F73CBBB87EA68 /* PhotoEditorViewController+Animation.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "PhotoEditorViewController+Animation.swift"; path = "Sources/HXPHPicker/Editor/Controller/PhotoEditorViewController+Animation.swift"; sourceTree = ""; }; 1B81DECD774F3D4D9429BE878A52C23E /* NSTextAttachment+Kingfisher.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "NSTextAttachment+Kingfisher.swift"; path = "Sources/Extensions/NSTextAttachment+Kingfisher.swift"; sourceTree = ""; }; 1C68E3B655283C5ADCD7D12044A2BD03 /* KingfisherError.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = KingfisherError.swift; path = Sources/General/KingfisherError.swift; sourceTree = ""; }; - 1C8BEA4AE65FAE282E599E49304003A4 /* AssetManager+Authorization.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "AssetManager+Authorization.swift"; path = "Sources/HXPHPicker/Core/Util/AssetManager+Authorization.swift"; sourceTree = ""; }; - 1DA2046F0F15237DEC99B2E540F33A02 /* PreviewLivePhotoViewCell.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PreviewLivePhotoViewCell.swift; path = Sources/HXPHPicker/Picker/View/Cell/PreviewLivePhotoViewCell.swift; sourceTree = ""; }; 1DB8EED1C5ED86CF23C451AD85D5ACF3 /* ImageDownloaderDelegate.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ImageDownloaderDelegate.swift; path = Sources/Networking/ImageDownloaderDelegate.swift; sourceTree = ""; }; - 204D2FFEE0B3ACCD72F736E5259B4A32 /* HXPHPicker.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = HXPHPicker.modulemap; sourceTree = ""; }; - 2056E7A211D4556EBA9699FB628661B7 /* LivePhotoError.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = LivePhotoError.swift; path = Sources/HXPHPicker/Core/Model/LivePhotoError.swift; sourceTree = ""; }; - 21238D3AD6B82A27C7FDDE411816C9E9 /* PhotoManager.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoManager.swift; path = Sources/HXPHPicker/Core/Util/PhotoManager.swift; sourceTree = ""; }; + 200797C27E58C7EAE62945E52003E6D6 /* PhotoAsset+Request.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "PhotoAsset+Request.swift"; path = "Sources/HXPHPicker/Picker/Model/PhotoAsset+Request.swift"; sourceTree = ""; }; + 2031A7C728C7A69FF24AF9CD69785785 /* Core+PHAsset.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Core+PHAsset.swift"; path = "Sources/HXPHPicker/Core/Extension/Core+PHAsset.swift"; sourceTree = ""; }; + 20C424910C56FC8369CE2F1BB9DD9A99 /* EditorToolOptions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = EditorToolOptions.swift; path = Sources/HXPHPicker/Editor/Model/EditorToolOptions.swift; sourceTree = ""; }; + 20F9D58158F64CD21D168B9BCAB9BBAD /* Core+UIImageView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Core+UIImageView.swift"; path = "Sources/HXPHPicker/Core/Extension/Core+UIImageView.swift"; sourceTree = ""; }; + 20FA873B324A5E85740C531E13CFCFCB /* PhotoAsset+URL.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "PhotoAsset+URL.swift"; path = "Sources/HXPHPicker/Picker/Model/PhotoAsset+URL.swift"; sourceTree = ""; }; 2173C51BCDB3C6409A7A59D6FE7BF621 /* Pods-HXPhotoPickerExample-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-HXPhotoPickerExample-acknowledgements.markdown"; sourceTree = ""; }; - 230C7F91CA2126BEFA59E947E57E48E9 /* PickerCamerViewCell.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PickerCamerViewCell.swift; path = Sources/HXPHPicker/Picker/View/Cell/PickerCamerViewCell.swift; sourceTree = ""; }; + 21CC892E6F1BBE9457A2D7D5F1405A50 /* PhotoAsset.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoAsset.swift; path = Sources/HXPHPicker/Picker/Model/PhotoAsset.swift; sourceTree = ""; }; 235EC98F01016FC89379B96C9A378C02 /* KFImageOptions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = KFImageOptions.swift; path = Sources/SwiftUI/KFImageOptions.swift; sourceTree = ""; }; + 2417C93289DBB418D2664E0013FA0907 /* PickerConfiguration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PickerConfiguration.swift; path = Sources/HXPHPicker/Picker/Config/PickerConfiguration.swift; sourceTree = ""; }; 2502A860F0A5D1C292E6E8F48D02A606 /* Kingfisher.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Kingfisher.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 2572F6B184769B86544433ECB4E7CB07 /* VideoCroppingConfiguration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = VideoCroppingConfiguration.swift; path = Sources/HXPHPicker/Editor/Config/VideoCroppingConfiguration.swift; sourceTree = ""; }; - 274D10D8BF7692BA4FE1A10BDDB40188 /* PhotoPickerViewController+SwipeSelect.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "PhotoPickerViewController+SwipeSelect.swift"; path = "Sources/HXPHPicker/Picker/Controller/PhotoPickerViewController+SwipeSelect.swift"; sourceTree = ""; }; - 28805DA79279D39C9E775A3C83679CEB /* VideoEditorCropViewCell.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = VideoEditorCropViewCell.swift; path = Sources/HXPHPicker/Editor/View/Video/VideoEditorCropViewCell.swift; sourceTree = ""; }; - 288B0C38BED59BD62A68D32EEDB6E1D6 /* Core+UIView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Core+UIView.swift"; path = "Sources/HXPHPicker/Core/Extension/Core+UIView.swift"; sourceTree = ""; }; - 28C3604C69772C27DD79C7BE69E40200 /* AssetManager+VideoURL.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "AssetManager+VideoURL.swift"; path = "Sources/HXPHPicker/Core/Util/AssetManager+VideoURL.swift"; sourceTree = ""; }; - 28E0147A913D85F3F6A23FC33C8FDC32 /* Core+Bundle.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Core+Bundle.swift"; path = "Sources/HXPHPicker/Core/Extension/Core+Bundle.swift"; sourceTree = ""; }; - 29F07941959855158988322CC0B2146B /* PhotoEditorViewController+Request.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "PhotoEditorViewController+Request.swift"; path = "Sources/HXPHPicker/Editor/Controller/PhotoEditorViewController+Request.swift"; sourceTree = ""; }; - 2A676EEE2F99A99BBE1F05A3FEFB6E4F /* Core+String.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Core+String.swift"; path = "Sources/HXPHPicker/Core/Extension/Core+String.swift"; sourceTree = ""; }; - 2A726DE17A03F99C4F2A95D4E7C45FBE /* PhotoAsset+Network.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "PhotoAsset+Network.swift"; path = "Sources/HXPHPicker/Picker/Model/PhotoAsset+Network.swift"; sourceTree = ""; }; - 2B6A3CC5B150A69213DFC957AFBCF1B0 /* PhotoListCameraCellConfiguration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoListCameraCellConfiguration.swift; path = Sources/HXPHPicker/Picker/Config/PhotoListCameraCellConfiguration.swift; sourceTree = ""; }; - 2D1CB169A7364BBE20552451BB7BCCFD /* HXPHPicker.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = HXPHPicker.release.xcconfig; sourceTree = ""; }; - 2D24914BBAD96BEC89719F3CAD50D605 /* Core+PHAsset.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Core+PHAsset.swift"; path = "Sources/HXPHPicker/Core/Extension/Core+PHAsset.swift"; sourceTree = ""; }; - 2DB4BC85761011473A365686A6806B07 /* Core+Data.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Core+Data.swift"; path = "Sources/HXPHPicker/Core/Extension/Core+Data.swift"; sourceTree = ""; }; - 2EC251D36D9079F779067D48D0750946 /* VideoEditorConfiguration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = VideoEditorConfiguration.swift; path = Sources/HXPHPicker/Editor/Config/VideoEditorConfiguration.swift; sourceTree = ""; }; - 2F79F16D3A44897480990D7FF64C5895 /* PhotoAssetCollection.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoAssetCollection.swift; path = Sources/HXPHPicker/Picker/Model/PhotoAssetCollection.swift; sourceTree = ""; }; + 2529D5686E3CA4F08BA564C0D5D71403 /* LivePhotoError.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = LivePhotoError.swift; path = Sources/HXPHPicker/Core/Model/LivePhotoError.swift; sourceTree = ""; }; + 25BDA27B1F9CB254542F4EB05308DDC2 /* AssetManager+LivePhoto.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "AssetManager+LivePhoto.swift"; path = "Sources/HXPHPicker/Core/Util/AssetManager+LivePhoto.swift"; sourceTree = ""; }; + 28B90775923927775FA22268513B4D38 /* Core+String.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Core+String.swift"; path = "Sources/HXPHPicker/Core/Extension/Core+String.swift"; sourceTree = ""; }; + 2A3127A758A3F0C0F5E00C1B60BE235F /* PickerTransition.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PickerTransition.swift; path = Sources/HXPHPicker/Picker/Transition/PickerTransition.swift; sourceTree = ""; }; + 2C9EB2FD1D24644738C1DDDF90C15176 /* EditorChartletView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = EditorChartletView.swift; path = Sources/HXPHPicker/Editor/View/EditorChartletView.swift; sourceTree = ""; }; + 2CCAE54011723B9D1CAC576CB8FAD496 /* AlbumTickView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AlbumTickView.swift; path = Sources/HXPHPicker/Picker/View/AlbumTickView.swift; sourceTree = ""; }; + 2E11EBFC3916F6386F5C5742499E7DBF /* VideoEditorCropView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = VideoEditorCropView.swift; path = Sources/HXPHPicker/Editor/View/Video/VideoEditorCropView.swift; sourceTree = ""; }; + 2FCA564D8B180872B0243FCDF544FDB7 /* PhotoManager.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoManager.swift; path = Sources/HXPHPicker/Core/Util/PhotoManager.swift; sourceTree = ""; }; + 3108BD33E52BC7B7B8AB07AF906B4917 /* AssetManager+Asset.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "AssetManager+Asset.swift"; path = "Sources/HXPHPicker/Core/Util/AssetManager+Asset.swift"; sourceTree = ""; }; 31608F4F2C2474D9D9CA8EC4C9272FE8 /* RedirectHandler.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = RedirectHandler.swift; path = Sources/Networking/RedirectHandler.swift; sourceTree = ""; }; - 32E577CB345214F9D6E8E9AD4CCFC928 /* ProgressImageView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ProgressImageView.swift; path = Sources/HXPHPicker/Core/View/ProgressImageView.swift; sourceTree = ""; }; - 334D1DCE7985A1C03D5E2F8A157E08E0 /* EditorType.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = EditorType.swift; path = Sources/HXPHPicker/Editor/Model/EditorType.swift; sourceTree = ""; }; - 347CBBFB5B67E48EEAB7CF3C25E42653 /* ProgressHUD.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ProgressHUD.swift; path = Sources/HXPHPicker/Core/View/ProgressHUD.swift; sourceTree = ""; }; - 393CD8E55D303D5416D741CEDFC7AE48 /* PhotoEditorMosaicView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoEditorMosaicView.swift; path = Sources/HXPHPicker/Editor/View/Photo/PhotoEditorMosaicView.swift; sourceTree = ""; }; - 39495AB0F9B887AFACB5C7CEE8AFBF53 /* PhotoPickerBottomView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoPickerBottomView.swift; path = Sources/HXPHPicker/Picker/View/PhotoPickerBottomView.swift; sourceTree = ""; }; - 399EF8348A2B332A84400E8075EA42A6 /* AssetManager+AVAsset.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "AssetManager+AVAsset.swift"; path = "Sources/HXPHPicker/Core/Util/AssetManager+AVAsset.swift"; sourceTree = ""; }; - 3A5224346D4E0C403876184DA83D02B2 /* PreviewPhotoViewCell.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PreviewPhotoViewCell.swift; path = Sources/HXPHPicker/Picker/View/Cell/PreviewPhotoViewCell.swift; sourceTree = ""; }; - 3A9209C818ED6E1F1DFCAD317C6FAF7A /* SelectBoxConfiguration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SelectBoxConfiguration.swift; path = Sources/HXPHPicker/Core/Config/SelectBoxConfiguration.swift; sourceTree = ""; }; - 3C3042A1C731FA1D1F809D292A9DCF78 /* PhotoEditorCropToolView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoEditorCropToolView.swift; path = Sources/HXPHPicker/Editor/View/Photo/PhotoEditorCropToolView.swift; sourceTree = ""; }; - 3CB7911DD2178CE74C965635DDCF814C /* AppearanceStyle.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AppearanceStyle.swift; path = Sources/HXPHPicker/Core/Model/AppearanceStyle.swift; sourceTree = ""; }; + 32FBAF8B97108508BBF67F354009C9DD /* AlbumViewCell.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AlbumViewCell.swift; path = Sources/HXPHPicker/Picker/View/Cell/AlbumViewCell.swift; sourceTree = ""; }; + 333194D5139911F72790CE8255D676D2 /* HXPHPicker.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = HXPHPicker.release.xcconfig; sourceTree = ""; }; + 357701EDDEE245E85839081476097A71 /* BaseConfiguration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BaseConfiguration.swift; path = Sources/HXPHPicker/Core/Config/BaseConfiguration.swift; sourceTree = ""; }; + 393D1A2C20CED9E766A07B87F987EF5F /* PhotoEditorViewController+Animation.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "PhotoEditorViewController+Animation.swift"; path = "Sources/HXPHPicker/Editor/Controller/PhotoEditorViewController+Animation.swift"; sourceTree = ""; }; + 3A1A1AD2E31935C4069D180698D4B300 /* NotAuthorizedConfiguration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = NotAuthorizedConfiguration.swift; path = Sources/HXPHPicker/Picker/Config/NotAuthorizedConfiguration.swift; sourceTree = ""; }; + 3A6C56626C1C22322F7454CA10D9D947 /* PickerBottomViewConfiguration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PickerBottomViewConfiguration.swift; path = Sources/HXPHPicker/Picker/Config/PickerBottomViewConfiguration.swift; sourceTree = ""; }; 3DC889CE6056F86A66BF6041B2F2C989 /* ImageFormat.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ImageFormat.swift; path = Sources/Image/ImageFormat.swift; sourceTree = ""; }; - 3DE117DEE9BC8FBEAF25DCC404A55C0D /* EditorImageResizerMaskView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = EditorImageResizerMaskView.swift; path = Sources/HXPHPicker/Editor/View/Photo/EditorImageResizerMaskView.swift; sourceTree = ""; }; - 40565C0E5DF5F1754DDB4BC58488CA8A /* VideoEditorPlayerView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = VideoEditorPlayerView.swift; path = Sources/HXPHPicker/Editor/View/Video/VideoEditorPlayerView.swift; sourceTree = ""; }; - 407AE5F5426D0C24AFEBF692B224F738 /* PhotoPickerBaseViewCell.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoPickerBaseViewCell.swift; path = Sources/HXPHPicker/Picker/View/Cell/PhotoPickerBaseViewCell.swift; sourceTree = ""; }; - 433775A97C99D7EC1558C62FE54DE366 /* PhotoEditorMosaicToolView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoEditorMosaicToolView.swift; path = Sources/HXPHPicker/Editor/View/Photo/PhotoEditorMosaicToolView.swift; sourceTree = ""; }; - 435165BD18BE952E53ED4496283BEA2A /* AlbumTitleView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AlbumTitleView.swift; path = Sources/HXPHPicker/Picker/View/AlbumTitleView.swift; sourceTree = ""; }; + 3DCAC90FCDF67BB7420B528333888A71 /* EditorImageResizerMaskView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = EditorImageResizerMaskView.swift; path = Sources/HXPHPicker/Editor/View/Photo/EditorImageResizerMaskView.swift; sourceTree = ""; }; + 40CEA5DD7A853F6B5BE36A6EA1F48FCD /* VideoEditorMusicAnimationView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = VideoEditorMusicAnimationView.swift; path = Sources/HXPHPicker/Editor/View/Video/VideoEditorMusicAnimationView.swift; sourceTree = ""; }; + 4221C82F020312B9ABABFC4625E574D4 /* PhotoPickerControllerProtocol.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoPickerControllerProtocol.swift; path = Sources/HXPHPicker/Picker/Controller/PhotoPickerControllerProtocol.swift; sourceTree = ""; }; 44057F66C5C77C9B40B6CF9C8BD32AB3 /* AVAssetImageDataProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AVAssetImageDataProvider.swift; path = Sources/General/ImageSource/AVAssetImageDataProvider.swift; sourceTree = ""; }; - 440B4B2232CAD0176D354214FF89F590 /* Editor+PhotoTools.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Editor+PhotoTools.swift"; path = "Sources/HXPHPicker/Editor/Util/Editor+PhotoTools.swift"; sourceTree = ""; }; - 444030316457F4B1626AA794BBFBD0D7 /* HXPHPicker.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = HXPHPicker.debug.xcconfig; sourceTree = ""; }; + 44382226E6FED16ABDF81E709F565C53 /* PhotoPreviewVideoView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoPreviewVideoView.swift; path = Sources/HXPHPicker/Picker/View/PhotoPreviewVideoView.swift; sourceTree = ""; }; + 44A108E31F90D17DD90D02847F4782FE /* HXPHPicker.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = HXPHPicker.modulemap; sourceTree = ""; }; 44EB32C6F0F69E0C6D73EEE192EBEE50 /* MemoryStorage.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MemoryStorage.swift; path = Sources/Cache/MemoryStorage.swift; sourceTree = ""; }; + 44EF4EC7B4D2A8C23F53A251BFF6752F /* GIFImageView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = GIFImageView.swift; path = Sources/HXPHPicker/Picker/View/GIFImageView.swift; sourceTree = ""; }; 455B6FD135B9DBCECA5E79C46697AD33 /* UIButton+Kingfisher.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIButton+Kingfisher.swift"; path = "Sources/Extensions/UIButton+Kingfisher.swift"; sourceTree = ""; }; - 46A41212FDA74FB99EA30F3724F33AF5 /* CameraViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CameraViewController.swift; path = Sources/HXPHPicker/Picker/Controller/CameraViewController.swift; sourceTree = ""; }; - 46AFEFEC9572D73F2670FD1471847EB4 /* VideoEditorMusic.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = VideoEditorMusic.swift; path = Sources/HXPHPicker/Editor/Model/VideoEditorMusic.swift; sourceTree = ""; }; - 4789F562F464012923FC30183A2741A7 /* AssetManager+LivePhoto.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "AssetManager+LivePhoto.swift"; path = "Sources/HXPHPicker/Core/Util/AssetManager+LivePhoto.swift"; sourceTree = ""; }; - 478A78BD12272959D6D0C7C507437A97 /* Core+UIImage.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Core+UIImage.swift"; path = "Sources/HXPHPicker/Core/Extension/Core+UIImage.swift"; sourceTree = ""; }; - 4852514CAA80364B32BE45D4609601D1 /* VideoEditorViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = VideoEditorViewController.swift; path = Sources/HXPHPicker/Editor/Controller/VideoEditorViewController.swift; sourceTree = ""; }; + 46936DB194A78211EACC9434C7564626 /* VideoEditorCropViewCell.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = VideoEditorCropViewCell.swift; path = Sources/HXPHPicker/Editor/View/Video/VideoEditorCropViewCell.swift; sourceTree = ""; }; 49018C17822EDBBF1884E2E006CBF261 /* ImageTransition.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ImageTransition.swift; path = Sources/Image/ImageTransition.swift; sourceTree = ""; }; - 49326A675DE29F1A0F9803D2E75A51F4 /* PhotoEditorViewController+Export.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "PhotoEditorViewController+Export.swift"; path = "Sources/HXPHPicker/Editor/Controller/PhotoEditorViewController+Export.swift"; sourceTree = ""; }; - 4A32037254E41EF30ECF6E30B3B2155F /* PhotoPreviewViewCell.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoPreviewViewCell.swift; path = Sources/HXPHPicker/Picker/View/Cell/PhotoPreviewViewCell.swift; sourceTree = ""; }; 4A600FC003AF50C0E9396D3F32C0DBAE /* ImageBinder.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ImageBinder.swift; path = Sources/SwiftUI/ImageBinder.swift; sourceTree = ""; }; - 4ACC2DF1D1BF3200F0D5D263A1F405DB /* CropConfirmViewConfiguration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CropConfirmViewConfiguration.swift; path = Sources/HXPHPicker/Editor/Config/CropConfirmViewConfiguration.swift; sourceTree = ""; }; + 4B2928135BDA49032CE7C48A71B99AC8 /* Editor+UIImage.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Editor+UIImage.swift"; path = "Sources/HXPHPicker/Editor/Extension/Editor+UIImage.swift"; sourceTree = ""; }; 4C6928EC52A16376108CACDBEBAA774F /* Photos.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Photos.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.0.sdk/System/Library/Frameworks/Photos.framework; sourceTree = DEVELOPER_DIR; }; - 4CE26138680D4ED69EA35BA9E5EDDFDF /* PhotoPickerController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoPickerController.swift; path = Sources/HXPHPicker/Picker/Controller/PhotoPickerController.swift; sourceTree = ""; }; 4CE68A4E643E473D0E784A8FA2A7E71D /* CacheSerializer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CacheSerializer.swift; path = Sources/Cache/CacheSerializer.swift; sourceTree = ""; }; - 4E7ED23FB2F6C711FC0C9A4DA50B8290 /* Core+UIColor.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Core+UIColor.swift"; path = "Sources/HXPHPicker/Core/Extension/Core+UIColor.swift"; sourceTree = ""; }; + 4E342829A41C6362D74A97C7B68E8B3A /* NetworkAsset.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = NetworkAsset.swift; path = Sources/HXPHPicker/Picker/Model/NetworkAsset.swift; sourceTree = ""; }; + 5095ACA69E440BD72A1F998B40641A55 /* PickerCamerViewCell.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PickerCamerViewCell.swift; path = Sources/HXPHPicker/Picker/View/Cell/PickerCamerViewCell.swift; sourceTree = ""; }; + 50A982AD2004E27721F97D1CA59F821E /* PhotoPreviewViewCell.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoPreviewViewCell.swift; path = Sources/HXPHPicker/Picker/View/Cell/PhotoPreviewViewCell.swift; sourceTree = ""; }; 514492DFCF72F9739D746C5072A34165 /* Pods-HXPhotoPickerExample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-HXPhotoPickerExample.release.xcconfig"; sourceTree = ""; }; + 531EEF01BF14E556D3BF4E84DAC9FCB2 /* BaseViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BaseViewController.swift; path = Sources/HXPHPicker/Core/Controller/BaseViewController.swift; sourceTree = ""; }; 534422A92C1F46CD65C44C2AEF7BBF7E /* Pods-HXPHPickerExample-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-HXPHPickerExample-acknowledgements.markdown"; sourceTree = ""; }; - 562321E3DBAA38414FA20AEDF5EA214C /* EditorCropConfirmView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = EditorCropConfirmView.swift; path = Sources/HXPHPicker/Editor/View/EditorCropConfirmView.swift; sourceTree = ""; }; - 563425CB7D1694773F59DCE917385445 /* PhotoPreviewSelectedView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoPreviewSelectedView.swift; path = Sources/HXPHPicker/Picker/View/PhotoPreviewSelectedView.swift; sourceTree = ""; }; + 547272275970D4CE23C428E23093CC37 /* PreviewLivePhotoViewCell.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PreviewLivePhotoViewCell.swift; path = Sources/HXPHPicker/Picker/View/Cell/PreviewLivePhotoViewCell.swift; sourceTree = ""; }; + 55BE8C50DAE322D6879995049D67F0E6 /* EditorToolViewCell.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = EditorToolViewCell.swift; path = Sources/HXPHPicker/Editor/View/EditorToolViewCell.swift; sourceTree = ""; }; + 562873123116F153C238FBC76B789ADC /* AssetManager+Image.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "AssetManager+Image.swift"; path = "Sources/HXPHPicker/Core/Util/AssetManager+Image.swift"; sourceTree = ""; }; 56A1015DE8EF774B9ED548AEA8CBD8AC /* Pods-HXPhotoPickerExample-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-HXPhotoPickerExample-acknowledgements.plist"; sourceTree = ""; }; - 56E702AA502667D742CB245D322D6AD0 /* PickerTransition.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PickerTransition.swift; path = Sources/HXPHPicker/Picker/Transition/PickerTransition.swift; sourceTree = ""; }; 574F83FDDB83A7182533B1D9ABD5CA05 /* TVMonogramView+Kingfisher.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "TVMonogramView+Kingfisher.swift"; path = "Sources/Extensions/TVMonogramView+Kingfisher.swift"; sourceTree = ""; }; 578326974025F0EA83D68C1CCA4D05D5 /* Kingfisher-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Kingfisher-umbrella.h"; sourceTree = ""; }; 59181372FE2D9AA0C9258A82C9B4E08A /* GraphicsContext.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = GraphicsContext.swift; path = Sources/Image/GraphicsContext.swift; sourceTree = ""; }; - 5A29336BB5E87AB2B535EBC9E33BBC28 /* PhotoPickerViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoPickerViewController.swift; path = Sources/HXPHPicker/Picker/Controller/PhotoPickerViewController.swift; sourceTree = ""; }; - 5AB50CCAEE13DBBDE49A969469366978 /* ImageContentType.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ImageContentType.swift; path = Sources/HXPHPicker/Core/Model/ImageContentType.swift; sourceTree = ""; }; - 5C754E497022D097EF2A113AADABDF9B /* PhotoEditorCropToolModel.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoEditorCropToolModel.swift; path = Sources/HXPHPicker/Editor/Model/PhotoEditorCropToolModel.swift; sourceTree = ""; }; - 5CAA1C6552AEAF1E552935EDDF916435 /* PhotoEditorBrushColorView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoEditorBrushColorView.swift; path = Sources/HXPHPicker/Editor/View/Photo/PhotoEditorBrushColorView.swift; sourceTree = ""; }; - 60433D7514CF80497C4891C8F6FA49A6 /* LocalAsset.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = LocalAsset.swift; path = Sources/HXPHPicker/Picker/Model/LocalAsset.swift; sourceTree = ""; }; - 622A7AEEC8EF9858A240F890A5628DF3 /* AlbumViewCell.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AlbumViewCell.swift; path = Sources/HXPHPicker/Picker/View/Cell/AlbumViewCell.swift; sourceTree = ""; }; + 5AE83272ABB8F7BE9A624B5D73185FFA /* EditorConfiguration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = EditorConfiguration.swift; path = Sources/HXPHPicker/Editor/Config/EditorConfiguration.swift; sourceTree = ""; }; + 5B15A167734DB17B64D7129AA996428E /* PhotoEditorDrawView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoEditorDrawView.swift; path = Sources/HXPHPicker/Editor/View/Photo/PhotoEditorDrawView.swift; sourceTree = ""; }; + 5C26BB434BF14419E1286FC52D083D50 /* EditorImageResizerControlView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = EditorImageResizerControlView.swift; path = Sources/HXPHPicker/Editor/View/Photo/EditorImageResizerControlView.swift; sourceTree = ""; }; + 5CDB75D22B5CD9CB120C940FA1417075 /* LocalAsset.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = LocalAsset.swift; path = Sources/HXPHPicker/Picker/Model/LocalAsset.swift; sourceTree = ""; }; + 601E50F79FCB543B83354FEDAC5DD99F /* EditorToolViewConfiguration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = EditorToolViewConfiguration.swift; path = Sources/HXPHPicker/Editor/Config/EditorToolViewConfiguration.swift; sourceTree = ""; }; + 603CD0956C8179CED00CD985F9A76D17 /* VideoEditorFrameMaskView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = VideoEditorFrameMaskView.swift; path = Sources/HXPHPicker/Editor/View/Video/VideoEditorFrameMaskView.swift; sourceTree = ""; }; 636F5C4CDDDCA53B0257D2C60617DCD4 /* KFOptionsSetter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = KFOptionsSetter.swift; path = Sources/General/KFOptionsSetter.swift; sourceTree = ""; }; 63BBAC59CBFA319E7C445BEFF4C3F842 /* Pods-HXPHPickerExample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-HXPHPickerExample.debug.xcconfig"; sourceTree = ""; }; + 640ED6DA1D830AE84C026E59A5A0A089 /* EditorStickerTrashView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = EditorStickerTrashView.swift; path = Sources/HXPHPicker/Editor/View/EditorStickerTrashView.swift; sourceTree = ""; }; 6412FC162B13556AC831867D400FA4D6 /* SessionDataTask.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SessionDataTask.swift; path = Sources/Networking/SessionDataTask.swift; sourceTree = ""; }; 64859EB840E1B0ADB4524B39239AC173 /* Filter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Filter.swift; path = Sources/Image/Filter.swift; sourceTree = ""; }; - 6677C1F9671029C339103F88B6A7518E /* PreviewVideoControlViewCell.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PreviewVideoControlViewCell.swift; path = Sources/HXPHPicker/Picker/View/Cell/PreviewVideoControlViewCell.swift; sourceTree = ""; }; - 67261FF3C5F6BE90491DD8FBEC806B71 /* VideoEditorFrameMaskView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = VideoEditorFrameMaskView.swift; path = Sources/HXPHPicker/Editor/View/Video/VideoEditorFrameMaskView.swift; sourceTree = ""; }; - 6726B45A690D709E558A34EB87B86CC1 /* PhotoEditorView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoEditorView.swift; path = Sources/HXPHPicker/Editor/View/Photo/PhotoEditorView.swift; sourceTree = ""; }; - 68474C198A87E5997989EF6105F7CDA8 /* PickerInteractiveTransition.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PickerInteractiveTransition.swift; path = Sources/HXPHPicker/Picker/Transition/PickerInteractiveTransition.swift; sourceTree = ""; }; + 67C0F210CA2203D043BA26DAAC26B62B /* Core+UIFont.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Core+UIFont.swift"; path = "Sources/HXPHPicker/Core/Extension/Core+UIFont.swift"; sourceTree = ""; }; 685C1A1F8C91B4094AFA8691254D72E5 /* Kingfisher.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Kingfisher.swift; path = Sources/General/Kingfisher.swift; sourceTree = ""; }; - 688A16315FA65A47A86E08E0474EA870 /* Core+PHAssetCollection.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Core+PHAssetCollection.swift"; path = "Sources/HXPHPicker/Core/Extension/Core+PHAssetCollection.swift"; sourceTree = ""; }; - 692781CC1099A4A6F1FE188A1A39EF5B /* HXPHPicker.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = HXPHPicker.swift; path = Sources/HXPHPicker/Core/HXPHPicker.swift; sourceTree = ""; }; + 6864336E8793E888F675FD96FF5EA904 /* VideoCroppingConfiguration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = VideoCroppingConfiguration.swift; path = Sources/HXPHPicker/Editor/Config/VideoCroppingConfiguration.swift; sourceTree = ""; }; 6A396B7E18DCDBD197E7732A0F4FEBA4 /* Resource.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Resource.swift; path = Sources/General/ImageSource/Resource.swift; sourceTree = ""; }; - 6B31C520BDE90F0E4660338BCF321C7D /* CameraConfiguration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CameraConfiguration.swift; path = Sources/HXPHPicker/Picker/Config/CameraConfiguration.swift; sourceTree = ""; }; + 6B431BF357DC6E21D6492CFEA10AB872 /* Core+Dictionary.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Core+Dictionary.swift"; path = "Sources/HXPHPicker/Core/Extension/Core+Dictionary.swift"; sourceTree = ""; }; + 6C5BD47EFE09F886E090A3663AD12226 /* EditorStickerView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = EditorStickerView.swift; path = Sources/HXPHPicker/Editor/View/EditorStickerView.swift; sourceTree = ""; }; 6D23F5862749B590314E57EEAE013E87 /* Pods_HXPHPickerExample.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_HXPHPickerExample.framework; path = "Pods-HXPHPickerExample.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; - 6DD0466B10B0558368BF1C65D70E2EFB /* EditorToolViewCell.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = EditorToolViewCell.swift; path = Sources/HXPHPicker/Editor/View/EditorToolViewCell.swift; sourceTree = ""; }; - 6EB1CEAC38537E23AF5B9EEF4224CC28 /* PhotoManager+Audio.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "PhotoManager+Audio.swift"; path = "Sources/HXPHPicker/Core/Util/PhotoManager+Audio.swift"; sourceTree = ""; }; - 6F3FBB0051619CE6CC673EAD87D1940E /* Picker+PhotoAsset.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Picker+PhotoAsset.swift"; path = "Sources/HXPHPicker/Picker/Extension/Picker+PhotoAsset.swift"; sourceTree = ""; }; + 6D79002CD77B4E701030F2586A87818F /* AssetManager+ImageURL.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "AssetManager+ImageURL.swift"; path = "Sources/HXPHPicker/Core/Util/AssetManager+ImageURL.swift"; sourceTree = ""; }; + 6DDE0043633422897202310C3D628F45 /* PhotoEditorViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoEditorViewController.swift; path = Sources/HXPHPicker/Editor/Controller/PhotoEditorViewController.swift; sourceTree = ""; }; + 6E2B8887898AA7C497D1A6FEAEA2AC8E /* VideoEditorSearchMusicView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = VideoEditorSearchMusicView.swift; path = Sources/HXPHPicker/Editor/View/Video/VideoEditorSearchMusicView.swift; sourceTree = ""; }; + 6E75F2BADFD9C9A1D757BF931E235FAE /* Core+UIColor.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Core+UIColor.swift"; path = "Sources/HXPHPicker/Core/Extension/Core+UIColor.swift"; sourceTree = ""; }; + 6E7B8A98BDCD775D95A65561CB633988 /* PhotoPickerViewController+SwipeSelect.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "PhotoPickerViewController+SwipeSelect.swift"; path = "Sources/HXPHPicker/Picker/Controller/PhotoPickerViewController+SwipeSelect.swift"; sourceTree = ""; }; + 6EE004AFA99195590A76014C2A986081 /* EditorStickerContentView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = EditorStickerContentView.swift; path = Sources/HXPHPicker/Editor/View/EditorStickerContentView.swift; sourceTree = ""; }; 6FB240C8C04CC2A7F305F6A27A8A9D0C /* KingfisherManager.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = KingfisherManager.swift; path = Sources/General/KingfisherManager.swift; sourceTree = ""; }; + 6FB653B8C90C89078F860D375DD46741 /* PhotoPreviewViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoPreviewViewController.swift; path = Sources/HXPHPicker/Picker/Controller/PhotoPreviewViewController.swift; sourceTree = ""; }; 6FC78B1FC94C1B1D29105230125C063E /* SizeExtensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SizeExtensions.swift; path = Sources/Utility/SizeExtensions.swift; sourceTree = ""; }; - 6FDE1FACC4C252967F8A52F8A003EB75 /* AssetManager+Asset.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "AssetManager+Asset.swift"; path = "Sources/HXPHPicker/Core/Util/AssetManager+Asset.swift"; sourceTree = ""; }; - 7378427FDA946DF5B716338C86805FE1 /* AssetManager+ImageURL.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "AssetManager+ImageURL.swift"; path = "Sources/HXPHPicker/Core/Util/AssetManager+ImageURL.swift"; sourceTree = ""; }; + 71812356610599E70B089E7AC48C42B6 /* Core+Bundle.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Core+Bundle.swift"; path = "Sources/HXPHPicker/Core/Extension/Core+Bundle.swift"; sourceTree = ""; }; 74142C17714428C2B056654FC8480D7E /* Source.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Source.swift; path = Sources/General/ImageSource/Source.swift; sourceTree = ""; }; + 75CA110961A55D00B90D2A8C35DFDD67 /* PhotoPickerBaseViewCell.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoPickerBaseViewCell.swift; path = Sources/HXPHPicker/Picker/View/Cell/PhotoPickerBaseViewCell.swift; sourceTree = ""; }; + 75E6A612C39CD25A693B862022E1E861 /* PhotoListCellConfiguration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoListCellConfiguration.swift; path = Sources/HXPHPicker/Picker/Config/PhotoListCellConfiguration.swift; sourceTree = ""; }; 763CEB42B991A31F53E79BAE64BF0D84 /* Pods-HXPHPickerExample-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-HXPHPickerExample-dummy.m"; sourceTree = ""; }; - 765C30F1D982A3BDA6E68508F94E615E /* HXPHPicker-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "HXPHPicker-umbrella.h"; sourceTree = ""; }; 768264B4E12779DA80F11B3651A39E27 /* Kingfisher.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = Kingfisher.modulemap; sourceTree = ""; }; - 7769420A27CAC894C5724E42564AE82F /* PhotoEditorViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoEditorViewController.swift; path = Sources/HXPHPicker/Editor/Controller/PhotoEditorViewController.swift; sourceTree = ""; }; - 77BC73F398E8C855D1B45CB97FDD7BC3 /* PhotoPreviewViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoPreviewViewController.swift; path = Sources/HXPHPicker/Picker/Controller/PhotoPreviewViewController.swift; sourceTree = ""; }; + 7774CD23C7037BD21F3774D56A2CCA08 /* PhotoEditorConfiguration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoEditorConfiguration.swift; path = Sources/HXPHPicker/Editor/Config/PhotoEditorConfiguration.swift; sourceTree = ""; }; + 778C2F66B7672CC04E6C9CF4CD600C1A /* AssetManager+VideoURL.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "AssetManager+VideoURL.swift"; path = "Sources/HXPHPicker/Core/Util/AssetManager+VideoURL.swift"; sourceTree = ""; }; 783EC77C14F4B9C72F5F44509EC897ED /* DiskStorage.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = DiskStorage.swift; path = Sources/Cache/DiskStorage.swift; sourceTree = ""; }; + 78A990770ECD2450090AACF6937A7FC8 /* PhotoAssetCollection.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoAssetCollection.swift; path = Sources/HXPHPicker/Picker/Model/PhotoAssetCollection.swift; sourceTree = ""; }; 79121B0A0E9C0D3A4DEB45D687917CB6 /* Kingfisher.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Kingfisher.debug.xcconfig; sourceTree = ""; }; - 7AE851F339FBCED4B53662017B5E7FC7 /* EmptyViewConfiguration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = EmptyViewConfiguration.swift; path = Sources/HXPHPicker/Picker/Config/EmptyViewConfiguration.swift; sourceTree = ""; }; - 7B0556648367EF7BE0BBDA2C2DE33EB5 /* PhotoEditorConfiguration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoEditorConfiguration.swift; path = Sources/HXPHPicker/Editor/Config/PhotoEditorConfiguration.swift; sourceTree = ""; }; - 7C584C14838C0813940BD3D7437CD6B0 /* PhotoListCellConfiguration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoListCellConfiguration.swift; path = Sources/HXPHPicker/Picker/Config/PhotoListCellConfiguration.swift; sourceTree = ""; }; - 7C5D81B2769F3E2F9633C5F73B50C5F3 /* PhotoTools+File.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "PhotoTools+File.swift"; path = "Sources/HXPHPicker/Core/Util/PhotoTools+File.swift"; sourceTree = ""; }; - 7F1DE1AB74246D67AB35992D09686534 /* EmptyView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = EmptyView.swift; path = Sources/HXPHPicker/Picker/View/EmptyView.swift; sourceTree = ""; }; + 793B46377505158FB3FA3993B1F26B7A /* PhotoPreviewContentView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoPreviewContentView.swift; path = Sources/HXPHPicker/Picker/View/PhotoPreviewContentView.swift; sourceTree = ""; }; + 7A6570757C0042B74807A527EF6D3052 /* PhotoEditorCropToolView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoEditorCropToolView.swift; path = Sources/HXPHPicker/Editor/View/Photo/PhotoEditorCropToolView.swift; sourceTree = ""; }; + 7B05A3B63B09302EC01FD1DB831D63E6 /* HXPHPicker.bundle */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "wrapper.plug-in"; name = HXPHPicker.bundle; path = Sources/HXPHPicker/Resources/HXPHPicker.bundle; sourceTree = ""; }; + 7B18E64A636AF66F9411A62E99C511CB /* PickerResult.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PickerResult.swift; path = Sources/HXPHPicker/Picker/PickerResult.swift; sourceTree = ""; }; + 7BED76A0F3AB74CD3E2060A361D516CC /* Core+DispatchQueue.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Core+DispatchQueue.swift"; path = "Sources/HXPHPicker/Core/Extension/Core+DispatchQueue.swift"; sourceTree = ""; }; + 7C778D7FF696B8B3929C66CF06F93BA9 /* VideoEditorMusicView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = VideoEditorMusicView.swift; path = Sources/HXPHPicker/Editor/View/Video/VideoEditorMusicView.swift; sourceTree = ""; }; + 7D9AEDAEC3BDDD906F5EBABA0945250C /* VideoEditorViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = VideoEditorViewController.swift; path = Sources/HXPHPicker/Editor/Controller/VideoEditorViewController.swift; sourceTree = ""; }; + 7E561675294E9B1E41841D4B69EC2FD4 /* Core+CALayer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Core+CALayer.swift"; path = "Sources/HXPHPicker/Core/Extension/Core+CALayer.swift"; sourceTree = ""; }; 803B9838178D0559BE20DB81795C0379 /* Placeholder.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Placeholder.swift; path = Sources/Image/Placeholder.swift; sourceTree = ""; }; - 81A6AAF0D0AE5FBD7D6F62A2CD11DB9A /* HXPHPicker-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "HXPHPicker-Info.plist"; sourceTree = ""; }; + 8138B689CFE3AFEEEE63A451915B3564 /* PhotoEditorView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoEditorView.swift; path = Sources/HXPHPicker/Editor/View/Photo/PhotoEditorView.swift; sourceTree = ""; }; 82BFE36A1B02653C5120C6BB84EEDF9F /* GIFAnimatedImage.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = GIFAnimatedImage.swift; path = Sources/Image/GIFAnimatedImage.swift; sourceTree = ""; }; - 832E000FACA6AD9958B6822E85D157BC /* AssetManager+ImageData.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "AssetManager+ImageData.swift"; path = "Sources/HXPHPicker/Core/Util/AssetManager+ImageData.swift"; sourceTree = ""; }; + 82F74FDC712BFDE6509B6E79F037D141 /* CropConfirmViewConfiguration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CropConfirmViewConfiguration.swift; path = Sources/HXPHPicker/Editor/Config/CropConfirmViewConfiguration.swift; sourceTree = ""; }; + 8372D0B1E8AFE84378987A633F1EB47C /* PhotoEditorViewController+Export.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "PhotoEditorViewController+Export.swift"; path = "Sources/HXPHPicker/Editor/Controller/PhotoEditorViewController+Export.swift"; sourceTree = ""; }; 83C46EBB94B2DF6B435144D05BF0A331 /* WKInterfaceImage+Kingfisher.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "WKInterfaceImage+Kingfisher.swift"; path = "Sources/Extensions/WKInterfaceImage+Kingfisher.swift"; sourceTree = ""; }; - 85AEE49BE66EE5DDFE7A24DE45426D21 /* VideoEditResult.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = VideoEditResult.swift; path = Sources/HXPHPicker/Editor/VideoEditResult.swift; sourceTree = ""; }; - 85F908541FE319223EEB696EC7130852 /* EditorImageResizerControlView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = EditorImageResizerControlView.swift; path = Sources/HXPHPicker/Editor/View/Photo/EditorImageResizerControlView.swift; sourceTree = ""; }; - 868C8FA5D842678E85DEB2612008F42C /* AssetManager+AVAssetExportSession.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "AssetManager+AVAssetExportSession.swift"; path = "Sources/HXPHPicker/Core/Util/AssetManager+AVAssetExportSession.swift"; sourceTree = ""; }; - 890E7EFC6AF7BBE7960EA22FF17CBC49 /* Core+UIImageView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Core+UIImageView.swift"; path = "Sources/HXPHPicker/Core/Extension/Core+UIImageView.swift"; sourceTree = ""; }; + 85A32ECAB16EB52AFB3B144CBB5CDD1E /* Editor+UIImageView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Editor+UIImageView.swift"; path = "Sources/HXPHPicker/Editor/Util/Editor+UIImageView.swift"; sourceTree = ""; }; + 8A59F7C6F400F5F0199C9DC26E4365DF /* EditorCropConfirmView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = EditorCropConfirmView.swift; path = Sources/HXPHPicker/Editor/View/EditorCropConfirmView.swift; sourceTree = ""; }; 8A5ED54FE8C5DA5F6544AE3D040E27E4 /* Box.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Box.swift; path = Sources/Utility/Box.swift; sourceTree = ""; }; + 8CB4883DF7F4726E4F8552533FCF2D06 /* AppearanceStyle.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AppearanceStyle.swift; path = Sources/HXPHPicker/Core/Model/AppearanceStyle.swift; sourceTree = ""; }; + 8E94E14400898B18B1EB176526DB9420 /* PickerTypes.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PickerTypes.swift; path = Sources/HXPHPicker/Picker/Model/PickerTypes.swift; sourceTree = ""; }; + 8FAC9361D156824AC15428F16BF61EE6 /* PhotoEditorContentView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoEditorContentView.swift; path = Sources/HXPHPicker/Editor/View/Photo/PhotoEditorContentView.swift; sourceTree = ""; }; 91610E715C8B8695F02B8352CC6C1C95 /* ImageModifier.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ImageModifier.swift; path = Sources/Networking/ImageModifier.swift; sourceTree = ""; }; - 91CE9F7A8548481CF2153C1EE7C28958 /* LanguageType.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = LanguageType.swift; path = Sources/HXPHPicker/Core/Model/LanguageType.swift; sourceTree = ""; }; - 92B15CDBEAFF705823B43C168FFC30F6 /* EditorImageResizerView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = EditorImageResizerView.swift; path = Sources/HXPHPicker/Editor/View/Photo/EditorImageResizerView.swift; sourceTree = ""; }; - 930641217CE7625ADB374829A94CCA81 /* EditorConfiguration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = EditorConfiguration.swift; path = Sources/HXPHPicker/Editor/Config/EditorConfiguration.swift; sourceTree = ""; }; + 91FB523C544F0FAE04EE01666E96D5C6 /* Core+URL.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Core+URL.swift"; path = "Sources/HXPHPicker/Core/Extension/Core+URL.swift"; sourceTree = ""; }; + 922AB5F39B78FAE087B4877B51BDD90D /* Picker+PhotoAsset.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Picker+PhotoAsset.swift"; path = "Sources/HXPHPicker/Picker/Extension/Picker+PhotoAsset.swift"; sourceTree = ""; }; + 925AB67D69D139C4CA3936AC6D7CA86C /* AssetManager+LivePhotoURL.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "AssetManager+LivePhotoURL.swift"; path = "Sources/HXPHPicker/Core/Util/AssetManager+LivePhotoURL.swift"; sourceTree = ""; }; 932030BAAFCCE92F8F74AAC8BDE262DA /* CallbackQueue.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CallbackQueue.swift; path = Sources/Utility/CallbackQueue.swift; sourceTree = ""; }; - 93787EA42D0CB0E0DB7D3E5CFC95CCE0 /* AlbumViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AlbumViewController.swift; path = Sources/HXPHPicker/Picker/Controller/AlbumViewController.swift; sourceTree = ""; }; - 93C6D6596A5CE21A3B66EB401BA0787E /* CustomLanguage.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CustomLanguage.swift; path = Sources/HXPHPicker/Core/Model/CustomLanguage.swift; sourceTree = ""; }; - 9508308A31AC567C83718C4F064C5195 /* BaseViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BaseViewController.swift; path = Sources/HXPHPicker/Core/Controller/BaseViewController.swift; sourceTree = ""; }; + 94354ED183F6FDBBAD76319C22F8E0E6 /* HXPHPicker.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = HXPHPicker.swift; path = Sources/HXPHPicker/Core/HXPHPicker.swift; sourceTree = ""; }; + 95834E4813296F15D42AFB5C8FCC36BD /* EmptyView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = EmptyView.swift; path = Sources/HXPHPicker/Picker/View/EmptyView.swift; sourceTree = ""; }; + 964AC6105B2F228667606A7E878EC767 /* VideoEditorMusic.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = VideoEditorMusic.swift; path = Sources/HXPHPicker/Editor/Model/VideoEditorMusic.swift; sourceTree = ""; }; 96EFAC1F171F3535F93EF217583FAF1A /* Pods-HXPhotoPickerExample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-HXPhotoPickerExample.debug.xcconfig"; sourceTree = ""; }; 97F844DC348A2765E002617A3E8219A3 /* AnimatedImageView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AnimatedImageView.swift; path = Sources/Views/AnimatedImageView.swift; sourceTree = ""; }; - 98E0603A4E03E57E7695F8194AC792B5 /* VideoEditorMusicAnimationView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = VideoEditorMusicAnimationView.swift; path = Sources/HXPHPicker/Editor/View/Video/VideoEditorMusicAnimationView.swift; sourceTree = ""; }; - 9941EF650C94303373933DCB0374B042 /* PhotoPreviewContentView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoPreviewContentView.swift; path = Sources/HXPHPicker/Picker/View/PhotoPreviewContentView.swift; sourceTree = ""; }; - 99DA44C4AA4F687FC6AE64DB7411C7BB /* PhotoAsset+Request.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "PhotoAsset+Request.swift"; path = "Sources/HXPHPicker/Picker/Model/PhotoAsset+Request.swift"; sourceTree = ""; }; - 9A98566174094B340F2EED50D8D01CC7 /* EditorToolOptions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = EditorToolOptions.swift; path = Sources/HXPHPicker/Editor/Model/EditorToolOptions.swift; sourceTree = ""; }; + 99B5F52EA74DF46254B99C01593AB86F /* PhotoError.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoError.swift; path = Sources/HXPHPicker/Core/Model/PhotoError.swift; sourceTree = ""; }; + 99BEEBF1C3DC35EAE886EF7A232D3D22 /* PhotoPickerSelectableViewCell.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoPickerSelectableViewCell.swift; path = Sources/HXPHPicker/Picker/View/Cell/PhotoPickerSelectableViewCell.swift; sourceTree = ""; }; 9BD376D40FEDDF1041AD3ED8722D34E6 /* KingfisherOptionsInfo.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = KingfisherOptionsInfo.swift; path = Sources/General/KingfisherOptionsInfo.swift; sourceTree = ""; }; + 9C96763AAEA238547056A5E47A0724E1 /* PhotoEditorCropToolModel.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoEditorCropToolModel.swift; path = Sources/HXPHPicker/Editor/Model/PhotoEditorCropToolModel.swift; sourceTree = ""; }; + 9C9C7812B380470644F66A932626C6A2 /* AlbumView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AlbumView.swift; path = Sources/HXPHPicker/Picker/View/AlbumView.swift; sourceTree = ""; }; 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; 9E8207BE35A27C5F90340C73CB2FD18D /* Pods-HXPHPickerExample-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-HXPHPickerExample-frameworks.sh"; sourceTree = ""; }; + 9F14DE66B4E355A94782F996E6DAFBEB /* EditorImageResizerView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = EditorImageResizerView.swift; path = Sources/HXPHPicker/Editor/View/Photo/EditorImageResizerView.swift; sourceTree = ""; }; + 9FEA074AB7BA3AF49CD342C40DC638CB /* PhotoEditorFilterView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoEditorFilterView.swift; path = Sources/HXPHPicker/Editor/View/Photo/PhotoEditorFilterView.swift; sourceTree = ""; }; A19355BD23C3F1BD773CBCF0894CFD4E /* ImageView+Kingfisher.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "ImageView+Kingfisher.swift"; path = "Sources/Extensions/ImageView+Kingfisher.swift"; sourceTree = ""; }; - A1C97C36F6828D4797C004539D3D31E8 /* PhotoError.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoError.swift; path = Sources/HXPHPicker/Core/Model/PhotoError.swift; sourceTree = ""; }; A312E415AD86071831D098106E1785B9 /* Pods-HXPHPickerExample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-HXPHPickerExample.release.xcconfig"; sourceTree = ""; }; + A4A77CE2F054070C1EC646B504A7E27D /* EditorStickerTextViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = EditorStickerTextViewController.swift; path = Sources/HXPHPicker/Editor/Controller/EditorStickerTextViewController.swift; sourceTree = ""; }; + A5493ECCBC7EE357FB08A312C5187DA7 /* AssetManager.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AssetManager.swift; path = Sources/HXPHPicker/Core/Util/AssetManager.swift; sourceTree = ""; }; + A566C25E75296EF7C4633A6B69326371 /* PhotoManager+Download.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "PhotoManager+Download.swift"; path = "Sources/HXPHPicker/Core/Util/PhotoManager+Download.swift"; sourceTree = ""; }; A62F1D833E4B0698EFC61B95E6A3F744 /* ImageProgressive.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ImageProgressive.swift; path = Sources/Image/ImageProgressive.swift; sourceTree = ""; }; + A65122D5FAF94B582526F068E163CABB /* AssetManager+AVAsset.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "AssetManager+AVAsset.swift"; path = "Sources/HXPHPicker/Core/Util/AssetManager+AVAsset.swift"; sourceTree = ""; }; A76AB1C0CF5D373462D772223F937F5F /* Pods-HXPHPickerExample.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-HXPHPickerExample.modulemap"; sourceTree = ""; }; + A821BDB5B2A2CF8AC91E4F7A59F6089D /* AlbumTitleArrowView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AlbumTitleArrowView.swift; path = Sources/HXPHPicker/Picker/View/AlbumTitleArrowView.swift; sourceTree = ""; }; A91D9D790AADDF14B73DBCAFC93AF139 /* Kingfisher-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Kingfisher-dummy.m"; sourceTree = ""; }; - A96275918A0C8AE4AFDE89364F13CEE7 /* EditorController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = EditorController.swift; path = Sources/HXPHPicker/Editor/Controller/EditorController.swift; sourceTree = ""; }; - AC1D06F8F8A9A5254A84014E10162059 /* Core+UIDevice.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Core+UIDevice.swift"; path = "Sources/HXPHPicker/Core/Extension/Core+UIDevice.swift"; sourceTree = ""; }; - ACF9CEB85ED171BE18D3860150E50D88 /* PhotoEditorFilter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoEditorFilter.swift; path = Sources/HXPHPicker/Editor/Model/PhotoEditorFilter.swift; sourceTree = ""; }; - AD6464CDD2E4B2FAF5661A075B8090EE /* EditorToolView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = EditorToolView.swift; path = Sources/HXPHPicker/Editor/View/EditorToolView.swift; sourceTree = ""; }; - ADBCF2C1F6B918828450523DFE5EAA55 /* Core+URL.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Core+URL.swift"; path = "Sources/HXPHPicker/Core/Extension/Core+URL.swift"; sourceTree = ""; }; - AE155CEA770DE8908844B4751507F566 /* PhotoPickerSelectableViewCell.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoPickerSelectableViewCell.swift; path = Sources/HXPHPicker/Picker/View/Cell/PhotoPickerSelectableViewCell.swift; sourceTree = ""; }; - AF2CE9ADEBD524066BB454888BF5C597 /* AssetManager+Image.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "AssetManager+Image.swift"; path = "Sources/HXPHPicker/Core/Util/AssetManager+Image.swift"; sourceTree = ""; }; + A9401BB7294394D430784BD8A95C19BC /* AlbumListConfiguration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AlbumListConfiguration.swift; path = Sources/HXPHPicker/Picker/Config/AlbumListConfiguration.swift; sourceTree = ""; }; + A9BB05A6E5F210ED0D2F2D9B8618D1AE /* EditorChartlet.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = EditorChartlet.swift; path = Sources/HXPHPicker/Editor/Model/EditorChartlet.swift; sourceTree = ""; }; + A9C4F29EDC2D5EA82CA16D831E0B6F24 /* Core+Data.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Core+Data.swift"; path = "Sources/HXPHPicker/Core/Extension/Core+Data.swift"; sourceTree = ""; }; + ABDE32A6D86C86F774CE63D72A29F33F /* EmptyViewConfiguration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = EmptyViewConfiguration.swift; path = Sources/HXPHPicker/Picker/Config/EmptyViewConfiguration.swift; sourceTree = ""; }; + AC1F04C732D001C893508ADDC6B738B5 /* PhotoEditorFilter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoEditorFilter.swift; path = Sources/HXPHPicker/Editor/Model/PhotoEditorFilter.swift; sourceTree = ""; }; + ACD0ED004361D4FB1A8A3A4C789F9F36 /* PhotoEditResult.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoEditResult.swift; path = Sources/HXPHPicker/Editor/PhotoEditResult.swift; sourceTree = ""; }; AF6CE43DEB87601C10DEB3FFF34A2570 /* Pods-HXPHPickerExample-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-HXPHPickerExample-umbrella.h"; sourceTree = ""; }; AF71B739F7A0F8F1F47C4E6F3C9B945E /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; B0D1FF42A8AD7FE58E8E8CAA3624C117 /* ImagePrefetcher.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ImagePrefetcher.swift; path = Sources/Networking/ImagePrefetcher.swift; sourceTree = ""; }; - B112C5DD2089296DAFD840326F0C85C0 /* Editor+UIImage.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Editor+UIImage.swift"; path = "Sources/HXPHPicker/Editor/Extension/Editor+UIImage.swift"; sourceTree = ""; }; B313762A2C974EF09CE7FBAC374B6DFD /* HXPHPicker.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = HXPHPicker.framework; path = HXPHPicker.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - B709B0FBEA1226AA6EEBA1388DD9B359 /* HXPHPicker-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "HXPHPicker-dummy.m"; sourceTree = ""; }; - B88513158CCCF5FC56759E5802F83DE3 /* PhotoManager+Download.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "PhotoManager+Download.swift"; path = "Sources/HXPHPicker/Core/Util/PhotoManager+Download.swift"; sourceTree = ""; }; + B35583C68EDF828E55A5B909CE97E60C /* AlbumTitleViewConfiguration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AlbumTitleViewConfiguration.swift; path = Sources/HXPHPicker/Picker/Config/AlbumTitleViewConfiguration.swift; sourceTree = ""; }; + B37E34968FF4C9E754E9DBD75F2B1116 /* VideoEditorConfiguration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = VideoEditorConfiguration.swift; path = Sources/HXPHPicker/Editor/Config/VideoEditorConfiguration.swift; sourceTree = ""; }; + B3EEBD8B7D2B99F3EB22F51AF071CE35 /* PhotoEditorViewController+Request.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "PhotoEditorViewController+Request.swift"; path = "Sources/HXPHPicker/Editor/Controller/PhotoEditorViewController+Request.swift"; sourceTree = ""; }; + B502D0AF6DA8DF74CB65F21CA80C095D /* ImageContentType.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ImageContentType.swift; path = Sources/HXPHPicker/Core/Model/ImageContentType.swift; sourceTree = ""; }; + B7D393D34E48D9283DF87A12A2627BF4 /* Core+UIDevice.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Core+UIDevice.swift"; path = "Sources/HXPHPicker/Core/Extension/Core+UIDevice.swift"; sourceTree = ""; }; + B9EBA2C0E0BA1ED2B1D2424066952CAB /* AssetManager+Authorization.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "AssetManager+Authorization.swift"; path = "Sources/HXPHPicker/Core/Util/AssetManager+Authorization.swift"; sourceTree = ""; }; BA5491FE4C2D5C5CECDCECA9AE640584 /* SessionDelegate.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SessionDelegate.swift; path = Sources/Networking/SessionDelegate.swift; sourceTree = ""; }; BAF505057CA7719DD20860C6B607AB19 /* RequestModifier.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = RequestModifier.swift; path = Sources/Networking/RequestModifier.swift; sourceTree = ""; }; BB472E8F2E6A8CC9C84EABA31140924B /* NSButton+Kingfisher.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "NSButton+Kingfisher.swift"; path = "Sources/Extensions/NSButton+Kingfisher.swift"; sourceTree = ""; }; - BDB5B0C5872FE958E4C477AB6D0FA495 /* AlbumTitleViewConfiguration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AlbumTitleViewConfiguration.swift; path = Sources/HXPHPicker/Picker/Config/AlbumTitleViewConfiguration.swift; sourceTree = ""; }; - BFCAF459B63CB461D420ECA303B2D6D9 /* PreviewVideoViewCell.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PreviewVideoViewCell.swift; path = Sources/HXPHPicker/Picker/View/Cell/PreviewVideoViewCell.swift; sourceTree = ""; }; + BC8D0A8FBB166F0B760A03E76DF00CD2 /* EditorType.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = EditorType.swift; path = Sources/HXPHPicker/Editor/Model/EditorType.swift; sourceTree = ""; }; + BDABEFFCBC7D4F3E556B386942CFD67D /* SelectBoxConfiguration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SelectBoxConfiguration.swift; path = Sources/HXPHPicker/Core/Config/SelectBoxConfiguration.swift; sourceTree = ""; }; + BF3616C052A86582F38076ABD8305A20 /* Picker+PhotoTools.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Picker+PhotoTools.swift"; path = "Sources/HXPHPicker/Picker/Util/Picker+PhotoTools.swift"; sourceTree = ""; }; + BF50DEBE3BC46AB48E86E2A87AA8254C /* PickerInteractiveTransition.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PickerInteractiveTransition.swift; path = Sources/HXPHPicker/Picker/Transition/PickerInteractiveTransition.swift; sourceTree = ""; }; BFF2502A4B98F81ED6F67689600B1E81 /* Pods-HXPHPickerExample-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-HXPHPickerExample-Info.plist"; sourceTree = ""; }; + C0D1AEBFA85DFAAE174E81C5C8420FA9 /* AssetManager+ImageData.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "AssetManager+ImageData.swift"; path = "Sources/HXPHPicker/Core/Util/AssetManager+ImageData.swift"; sourceTree = ""; }; C11E0F29122AC9F7339A1462FDD4D9B9 /* ImageCache.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ImageCache.swift; path = Sources/Cache/ImageCache.swift; sourceTree = ""; }; - C16051339A3ABA4B72958557C53630D5 /* PhotoPickerControllerProtocol.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoPickerControllerProtocol.swift; path = Sources/HXPHPicker/Picker/Controller/PhotoPickerControllerProtocol.swift; sourceTree = ""; }; C172736B4D34015D44A89AA2FEFA54FE /* Pods-HXPHPickerExample-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-HXPHPickerExample-acknowledgements.plist"; sourceTree = ""; }; + C21CCC463978FD90835D06157C0F0A41 /* Core+UIImage.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Core+UIImage.swift"; path = "Sources/HXPHPicker/Core/Extension/Core+UIImage.swift"; sourceTree = ""; }; C2A7512ED739726CA517F36C54B774B5 /* ImageProcessor.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ImageProcessor.swift; path = Sources/Image/ImageProcessor.swift; sourceTree = ""; }; C2D1E7C615DDD2B310AED93D3FBB7465 /* Kingfisher-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Kingfisher-Info.plist"; sourceTree = ""; }; + C31101F6E37090746349715B96C9ABF5 /* DeniedAuthorizationView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = DeniedAuthorizationView.swift; path = Sources/HXPHPicker/Picker/View/DeniedAuthorizationView.swift; sourceTree = ""; }; C3F44C782D64D7EB20B61CE3844EBFAD /* Kingfisher.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Kingfisher.framework; path = Kingfisher.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - C4067FCFD0137862596BF9CCCC45B520 /* BaseConfiguration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = BaseConfiguration.swift; path = Sources/HXPHPicker/Core/Config/BaseConfiguration.swift; sourceTree = ""; }; - C813900019839F0CB70608F2F3CDB23C /* PhotoAsset.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoAsset.swift; path = Sources/HXPHPicker/Picker/Model/PhotoAsset.swift; sourceTree = ""; }; + C4EF7C9F1003DF37C35C784CBD74FA4B /* PreviewVideoControlViewCell.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PreviewVideoControlViewCell.swift; path = Sources/HXPHPicker/Picker/View/Cell/PreviewVideoControlViewCell.swift; sourceTree = ""; }; + C53E5416E10DCBD3D144B7B44A217D8F /* HXPHPicker-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "HXPHPicker-prefix.pch"; sourceTree = ""; }; + C5DA54C12769FCD2DD2E24256B7F8F72 /* CameraConfiguration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CameraConfiguration.swift; path = Sources/HXPHPicker/Picker/Config/CameraConfiguration.swift; sourceTree = ""; }; + C70744E46D235762935B383CD84373ED /* VideoPlayerView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = VideoPlayerView.swift; path = Sources/HXPHPicker/Core/View/VideoPlayerView.swift; sourceTree = ""; }; C8AD2839A5327532E0A5CAD720F73099 /* Image.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Image.swift; path = Sources/Image/Image.swift; sourceTree = ""; }; + C8CFC0438D17803CACF407B6EC1F3E92 /* PhotoListCameraCellConfiguration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoListCameraCellConfiguration.swift; path = Sources/HXPHPicker/Picker/Config/PhotoListCameraCellConfiguration.swift; sourceTree = ""; }; + C90D008920575AFDBAB1E440D6846285 /* PhotoAsset+Codable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "PhotoAsset+Codable.swift"; path = "Sources/HXPHPicker/Picker/Model/PhotoAsset+Codable.swift"; sourceTree = ""; }; + C90FD1C9FAB44FCAE623AEE8C235FB05 /* PhotoEditorMosaicView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoEditorMosaicView.swift; path = Sources/HXPHPicker/Editor/View/Photo/PhotoEditorMosaicView.swift; sourceTree = ""; }; CA88A8AF447A5943F95AF07C7654F716 /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.0.sdk/System/Library/Frameworks/CFNetwork.framework; sourceTree = DEVELOPER_DIR; }; CB65976E1F0710E684127792006DF1D4 /* Delegate.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Delegate.swift; path = Sources/Utility/Delegate.swift; sourceTree = ""; }; - CC1D69AE8602A539A85DBDE7AE6CB27B /* PreviewViewConfiguration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PreviewViewConfiguration.swift; path = Sources/HXPHPicker/Picker/Config/PreviewViewConfiguration.swift; sourceTree = ""; }; - CD5233B5ACF9B9672AA3AE6C355FF3E9 /* Core+DispatchQueue.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Core+DispatchQueue.swift"; path = "Sources/HXPHPicker/Core/Extension/Core+DispatchQueue.swift"; sourceTree = ""; }; - D06882E3535F72030E939C29E21B17BF /* PhotoListConfiguration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoListConfiguration.swift; path = Sources/HXPHPicker/Picker/Config/PhotoListConfiguration.swift; sourceTree = ""; }; - D19604CBBDF0009BFE40E3E27679CD24 /* PhotoPanGestureRecognizer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoPanGestureRecognizer.swift; path = Sources/HXPHPicker/Core/Model/PhotoPanGestureRecognizer.swift; sourceTree = ""; }; - D1EE561EF370C515FF47278EE93FD9EE /* Core+CALayer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Core+CALayer.swift"; path = "Sources/HXPHPicker/Core/Extension/Core+CALayer.swift"; sourceTree = ""; }; - D20513BAF16D62230CAE551868C98675 /* AlbumTickView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AlbumTickView.swift; path = Sources/HXPHPicker/Picker/View/AlbumTickView.swift; sourceTree = ""; }; - D21BD73027CF44C6BED97C7AA0D0083F /* AlbumListConfiguration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AlbumListConfiguration.swift; path = Sources/HXPHPicker/Picker/Config/AlbumListConfiguration.swift; sourceTree = ""; }; + CBF965A931D668DD9C27E4D57C9D32DE /* VideoEditorPlayerView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = VideoEditorPlayerView.swift; path = Sources/HXPHPicker/Editor/View/Video/VideoEditorPlayerView.swift; sourceTree = ""; }; + CD19B924DF5EBB6FA318331966BE818B /* ProgressImageView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ProgressImageView.swift; path = Sources/HXPHPicker/Core/View/ProgressImageView.swift; sourceTree = ""; }; + CE6E57EB6B1E40BA02666FDBF20FD3DA /* SelectBoxView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SelectBoxView.swift; path = Sources/HXPHPicker/Core/View/SelectBoxView.swift; sourceTree = ""; }; + CFF9A9F38CE216F9BCAB2468D5D33B2A /* PhotoPickerViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoPickerViewController.swift; path = Sources/HXPHPicker/Picker/Controller/PhotoPickerViewController.swift; sourceTree = ""; }; + D26F48DD9580641912BB27C678E2A07E /* Picker+PhotoManager.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Picker+PhotoManager.swift"; path = "Sources/HXPHPicker/Picker/Util/Picker+PhotoManager.swift"; sourceTree = ""; }; D626DEE33E886F43389E4D4C0C06944C /* ImageDataProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ImageDataProvider.swift; path = Sources/General/ImageSource/ImageDataProvider.swift; sourceTree = ""; }; - D72BAFE08AD4646F7426D9168E57588A /* VideoPlayerView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = VideoPlayerView.swift; path = Sources/HXPHPicker/Core/View/VideoPlayerView.swift; sourceTree = ""; }; - DB5691815F77BF894DB9C887C2F9231F /* PhotoManager+Language.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "PhotoManager+Language.swift"; path = "Sources/HXPHPicker/Core/Util/PhotoManager+Language.swift"; sourceTree = ""; }; + D7556215365F7415A0C3CB7D2340BDB6 /* AssetManager+AVAssetExportSession.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "AssetManager+AVAssetExportSession.swift"; path = "Sources/HXPHPicker/Core/Util/AssetManager+AVAssetExportSession.swift"; sourceTree = ""; }; + D832A474A922ABCB4DD2404EA5BE944A /* Picker+UIImageView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Picker+UIImageView.swift"; path = "Sources/HXPHPicker/Picker/Extension/Picker+UIImageView.swift"; sourceTree = ""; }; + DA8235D2AEA9034EBA2CAB7C44A4C739 /* PhotoAsset+Network.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "PhotoAsset+Network.swift"; path = "Sources/HXPHPicker/Picker/Model/PhotoAsset+Network.swift"; sourceTree = ""; }; DC2A668332C08973296C3E1D60EE54A2 /* Result.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Result.swift; path = Sources/Utility/Result.swift; sourceTree = ""; }; DC6C3EA333162630333FF31E76CDBD0A /* Kingfisher.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Kingfisher.release.xcconfig; sourceTree = ""; }; - DC7E51B729C48D2CDC3E3F7D28CB4AA8 /* PhotoPreviewVideoView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoPreviewVideoView.swift; path = Sources/HXPHPicker/Picker/View/PhotoPreviewVideoView.swift; sourceTree = ""; }; + DC6E5B07C8617D54F1595DC8BC675BB2 /* PhotoPanGestureRecognizer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoPanGestureRecognizer.swift; path = Sources/HXPHPicker/Core/Model/PhotoPanGestureRecognizer.swift; sourceTree = ""; }; DD4AF271F2F5F7E36C3324DBF2EFD73F /* RetryStrategy.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = RetryStrategy.swift; path = Sources/Networking/RetryStrategy.swift; sourceTree = ""; }; - DDAA1BAE55A5E39451124EE003C59D1A /* EditorToolViewConfiguration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = EditorToolViewConfiguration.swift; path = Sources/HXPHPicker/Editor/Config/EditorToolViewConfiguration.swift; sourceTree = ""; }; - DDBA3B9B2A3A5A8429A5E40D8189F85E /* AlbumView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AlbumView.swift; path = Sources/HXPHPicker/Picker/View/AlbumView.swift; sourceTree = ""; }; + DE3F44E74E5B0303460502CCFEB39EE6 /* PhotoPickerController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoPickerController.swift; path = Sources/HXPHPicker/Picker/Controller/PhotoPickerController.swift; sourceTree = ""; }; + DE752415B71C6B20179128E19513AD63 /* PhotoCroppingConfiguration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoCroppingConfiguration.swift; path = Sources/HXPHPicker/Editor/Config/PhotoCroppingConfiguration.swift; sourceTree = ""; }; + DF30C43C9CEC6FD791CA87DE084631BD /* HXPHPicker.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = HXPHPicker.debug.xcconfig; sourceTree = ""; }; DF82715186FC43646CCDE8B5A9B75524 /* Runtime.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Runtime.swift; path = Sources/Utility/Runtime.swift; sourceTree = ""; }; - E08650E661A65D8AFF34727D04C6DD9E /* PhotoEditorFilterView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoEditorFilterView.swift; path = Sources/HXPHPicker/Editor/View/Photo/PhotoEditorFilterView.swift; sourceTree = ""; }; - E09AB868F28C37D80342CD9A8C37C390 /* Picker+UIImageView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Picker+UIImageView.swift"; path = "Sources/HXPHPicker/Picker/Extension/Picker+UIImageView.swift"; sourceTree = ""; }; - E23FF50CBEF9896F69F8C33C30A0109F /* PhotoEditResult.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoEditResult.swift; path = Sources/HXPHPicker/Editor/PhotoEditResult.swift; sourceTree = ""; }; + DFDCB9B82E208AA6A69A9F49DAF14549 /* PreviewPhotoViewCell.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PreviewPhotoViewCell.swift; path = Sources/HXPHPicker/Picker/View/Cell/PreviewPhotoViewCell.swift; sourceTree = ""; }; + E2424CB8B3A8EAD348907F16762FC981 /* PreviewViewConfiguration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PreviewViewConfiguration.swift; path = Sources/HXPHPicker/Picker/Config/PreviewViewConfiguration.swift; sourceTree = ""; }; E4A4E9D17CFB6CD3E87B02CBB62A4B33 /* Storage.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Storage.swift; path = Sources/Cache/Storage.swift; sourceTree = ""; }; - E65DA63DD4AD4E432FAD881813877823 /* AssetManager+LivePhotoURL.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "AssetManager+LivePhotoURL.swift"; path = "Sources/HXPHPicker/Core/Util/AssetManager+LivePhotoURL.swift"; sourceTree = ""; }; + E5BDDEB666AF9858765B4C5C2E03009D /* PhotoTools.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoTools.swift; path = Sources/HXPHPicker/Core/Util/PhotoTools.swift; sourceTree = ""; }; + E7D4BBD8DFCFCEC0DD7436685B346AEE /* Editor+PhotoTools.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Editor+PhotoTools.swift"; path = "Sources/HXPHPicker/Editor/Util/Editor+PhotoTools.swift"; sourceTree = ""; }; E7FACF0656056AFACF2C82D01BD89750 /* libPods-HXPhotoPickerExample.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; name = "libPods-HXPhotoPickerExample.a"; path = "libPods-HXPhotoPickerExample.a"; sourceTree = BUILT_PRODUCTS_DIR; }; - EA4B321A0BB5316F5CC31090FC409B18 /* HXPHPicker-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "HXPHPicker-prefix.pch"; sourceTree = ""; }; - EBF7D3D6FDAB3790527AFB5B79178329 /* AlbumTitleArrowView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AlbumTitleArrowView.swift; path = Sources/HXPHPicker/Picker/View/AlbumTitleArrowView.swift; sourceTree = ""; }; - EC8B9253A80AF8325CA6FB2DECD32CEA /* Picker+PhotoManager.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Picker+PhotoManager.swift"; path = "Sources/HXPHPicker/Picker/Util/Picker+PhotoManager.swift"; sourceTree = ""; }; + EBB94B8F51309E444091CEF804B142C0 /* PhotoPickerBottomView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoPickerBottomView.swift; path = Sources/HXPHPicker/Picker/View/PhotoPickerBottomView.swift; sourceTree = ""; }; + ED56BC152265BC047FBBFF628A7FE04D /* EditorStickerItemView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = EditorStickerItemView.swift; path = Sources/HXPHPicker/Editor/View/EditorStickerItemView.swift; sourceTree = ""; }; ED9410EF4B36DD248DA96CA6179A23C5 /* ImageDataProcessor.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ImageDataProcessor.swift; path = Sources/Networking/ImageDataProcessor.swift; sourceTree = ""; }; - EEEA33EA3D93522BB858E2B400DE568E /* AssetManager.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AssetManager.swift; path = Sources/HXPHPicker/Core/Util/AssetManager.swift; sourceTree = ""; }; EF58F49EBCA386B0EF516C3557F8ECA9 /* ImageDrawing.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ImageDrawing.swift; path = Sources/Image/ImageDrawing.swift; sourceTree = ""; }; - F034C0845F804BF4035366CBAA8EEF8A /* Core+UIFont.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Core+UIFont.swift"; path = "Sources/HXPHPicker/Core/Extension/Core+UIFont.swift"; sourceTree = ""; }; - F1A5151C93FB53BF11EACE400D3A731D /* PhotoEditorDrawView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoEditorDrawView.swift; path = Sources/HXPHPicker/Editor/View/Photo/PhotoEditorDrawView.swift; sourceTree = ""; }; + EFFA27C9ED669FF64D29F60F6B5B0274 /* AlbumTitleView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AlbumTitleView.swift; path = Sources/HXPHPicker/Picker/View/AlbumTitleView.swift; sourceTree = ""; }; + F2032572C9F787B59664C732AF01595D /* PhotoEditorMosaicToolView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoEditorMosaicToolView.swift; path = Sources/HXPHPicker/Editor/View/Photo/PhotoEditorMosaicToolView.swift; sourceTree = ""; }; F26BBE04D00F18EF379EA2D8F3F76ED0 /* ExtensionHelpers.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExtensionHelpers.swift; path = Sources/Utility/ExtensionHelpers.swift; sourceTree = ""; }; F26C814FEFAFBCF3830A5F27E639C958 /* ImageDownloader.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ImageDownloader.swift; path = Sources/Networking/ImageDownloader.swift; sourceTree = ""; }; - F54610899D0457A64E9CF06BD1A9CB13 /* HXPHPicker.bundle */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "wrapper.plug-in"; name = HXPHPicker.bundle; path = Sources/HXPHPicker/Resources/HXPHPicker.bundle; sourceTree = ""; }; - FA94CECB93BDBEC3604957BBD28190C9 /* AssetManager+AssetCollection.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "AssetManager+AssetCollection.swift"; path = "Sources/HXPHPicker/Core/Util/AssetManager+AssetCollection.swift"; sourceTree = ""; }; - FAE7F809DA36DD7EB68C544C3E22811C /* PhotoCroppingConfiguration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoCroppingConfiguration.swift; path = Sources/HXPHPicker/Editor/Config/PhotoCroppingConfiguration.swift; sourceTree = ""; }; - FAF0BE88CF2FD74AF5588F55CD6D76C3 /* NetworkAsset.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = NetworkAsset.swift; path = Sources/HXPHPicker/Picker/Model/NetworkAsset.swift; sourceTree = ""; }; - FB78885389B2F94B85F99BB123138879 /* PickerBottomViewConfiguration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PickerBottomViewConfiguration.swift; path = Sources/HXPHPicker/Picker/Config/PickerBottomViewConfiguration.swift; sourceTree = ""; }; - FEA9291F441E8AB422086ADED6C80791 /* GIFImageView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = GIFImageView.swift; path = Sources/HXPHPicker/Picker/View/GIFImageView.swift; sourceTree = ""; }; + F43676462AFA99D7CA9A029E51372ED1 /* PhotoPickerViewCell.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoPickerViewCell.swift; path = Sources/HXPHPicker/Picker/View/Cell/PhotoPickerViewCell.swift; sourceTree = ""; }; + F5C463BBF002FE01B6CD6FE4CC3D2F84 /* CameraViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CameraViewController.swift; path = Sources/HXPHPicker/Picker/Controller/CameraViewController.swift; sourceTree = ""; }; + F6E753BF4DC689F4ECAEF1290641355D /* PhotoPreviewSelectedViewCell.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PhotoPreviewSelectedViewCell.swift; path = Sources/HXPHPicker/Picker/View/Cell/PhotoPreviewSelectedViewCell.swift; sourceTree = ""; }; + F9A0461D6318AB717C40D28E6674A988 /* VideoEditResult.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = VideoEditResult.swift; path = Sources/HXPHPicker/Editor/VideoEditResult.swift; sourceTree = ""; }; + FE27C9D0A29943792024F87E3844C4E3 /* Picker+UIViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Picker+UIViewController.swift"; path = "Sources/HXPHPicker/Picker/Extension/Picker+UIViewController.swift"; sourceTree = ""; }; + FE76BB39DAEAF02C9EBAD0EBAE9121FF /* HXPHPicker-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "HXPHPicker-Info.plist"; sourceTree = ""; }; FEFDBA477B6F8B96759550E649D020D3 /* String+MD5.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "String+MD5.swift"; path = "Sources/Utility/String+MD5.swift"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ - 11BEC1D9E4A075697EA0F8103D8806B9 /* Frameworks */ = { + 50DA19B5B50EC6355CEF8A539EA79DCA /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 07DDD0CCEBFF49AF76827D9745BD6043 /* Foundation.framework in Frameworks */, - 8FB9A1648EEBA50A101D298EB13ED3E2 /* Kingfisher.framework in Frameworks */, - B9EA11C9E0E9220D95BE1A11D9ACEADE /* Photos.framework in Frameworks */, - 9B8666F269756288DD1240BE7755F523 /* PhotosUI.framework in Frameworks */, - D8A13ADBFBE2CC69B60A9FEB063BC005 /* UIKit.framework in Frameworks */, + 501F87B4507A9D1CFDE79D5C5FE4CCD8 /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 50DA19B5B50EC6355CEF8A539EA79DCA /* Frameworks */ = { + 73B3835300733D94308D4E1282BFF8BF /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 501F87B4507A9D1CFDE79D5C5FE4CCD8 /* Foundation.framework in Frameworks */, + C7600CE2AAB4E8771DFFCAB7D20C107C /* Accelerate.framework in Frameworks */, + 0576490B2BDAD8F6818E31F149021195 /* CFNetwork.framework in Frameworks */, + 2460619C1816BB0715F0CC0D11B44902 /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - CD99B9959AEB9E998B95B7636F9CE3F6 /* Frameworks */ = { + C57A0CCF779214F6A07E08ABE894F1DF /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 8D624ACA08FCB438A9DDEDDE26227601 /* Accelerate.framework in Frameworks */, - E1DBF6743011B7D4D5662ECCBA84A91C /* CFNetwork.framework in Frameworks */, - 4397EA9660E3044D0D85071FF770EA10 /* Foundation.framework in Frameworks */, + 66830060E7340BFC3BBD82B4FBB52FD5 /* Foundation.framework in Frameworks */, + 9E6F7DAF1D8CE6A8B973F1BC17683C7C /* Kingfisher.framework in Frameworks */, + 2D3ECF3256C907C546DA9735039B85A1 /* Photos.framework in Frameworks */, + 33ACFCF442A7FE946AA016BADF1ED725 /* PhotosUI.framework in Frameworks */, + 4705BA3F8B1C39D3468C564612E606EF /* UIKit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -539,6 +561,70 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 0A87C88678C1B052134FD48C4F1AD702 /* Picker */ = { + isa = PBXGroup; + children = ( + A9401BB7294394D430784BD8A95C19BC /* AlbumListConfiguration.swift */, + 2CCAE54011723B9D1CAC576CB8FAD496 /* AlbumTickView.swift */, + A821BDB5B2A2CF8AC91E4F7A59F6089D /* AlbumTitleArrowView.swift */, + EFFA27C9ED669FF64D29F60F6B5B0274 /* AlbumTitleView.swift */, + B35583C68EDF828E55A5B909CE97E60C /* AlbumTitleViewConfiguration.swift */, + 9C9C7812B380470644F66A932626C6A2 /* AlbumView.swift */, + 32FBAF8B97108508BBF67F354009C9DD /* AlbumViewCell.swift */, + 17AA31042A2107DB6B14773E3063E3FE /* AlbumViewController.swift */, + C5DA54C12769FCD2DD2E24256B7F8F72 /* CameraConfiguration.swift */, + F5C463BBF002FE01B6CD6FE4CC3D2F84 /* CameraViewController.swift */, + C31101F6E37090746349715B96C9ABF5 /* DeniedAuthorizationView.swift */, + 95834E4813296F15D42AFB5C8FCC36BD /* EmptyView.swift */, + ABDE32A6D86C86F774CE63D72A29F33F /* EmptyViewConfiguration.swift */, + 44EF4EC7B4D2A8C23F53A251BFF6752F /* GIFImageView.swift */, + 5CDB75D22B5CD9CB120C940FA1417075 /* LocalAsset.swift */, + 4E342829A41C6362D74A97C7B68E8B3A /* NetworkAsset.swift */, + 3A1A1AD2E31935C4069D180698D4B300 /* NotAuthorizedConfiguration.swift */, + 21CC892E6F1BBE9457A2D7D5F1405A50 /* PhotoAsset.swift */, + C90D008920575AFDBAB1E440D6846285 /* PhotoAsset+Codable.swift */, + DA8235D2AEA9034EBA2CAB7C44A4C739 /* PhotoAsset+Network.swift */, + 200797C27E58C7EAE62945E52003E6D6 /* PhotoAsset+Request.swift */, + 20FA873B324A5E85740C531E13CFCFCB /* PhotoAsset+URL.swift */, + 78A990770ECD2450090AACF6937A7FC8 /* PhotoAssetCollection.swift */, + C8CFC0438D17803CACF407B6EC1F3E92 /* PhotoListCameraCellConfiguration.swift */, + 75E6A612C39CD25A693B862022E1E861 /* PhotoListCellConfiguration.swift */, + 0695CF13DF659A9995256DA724C9F2C5 /* PhotoListConfiguration.swift */, + 75CA110961A55D00B90D2A8C35DFDD67 /* PhotoPickerBaseViewCell.swift */, + EBB94B8F51309E444091CEF804B142C0 /* PhotoPickerBottomView.swift */, + DE3F44E74E5B0303460502CCFEB39EE6 /* PhotoPickerController.swift */, + 4221C82F020312B9ABABFC4625E574D4 /* PhotoPickerControllerProtocol.swift */, + 99BEEBF1C3DC35EAE886EF7A232D3D22 /* PhotoPickerSelectableViewCell.swift */, + F43676462AFA99D7CA9A029E51372ED1 /* PhotoPickerViewCell.swift */, + CFF9A9F38CE216F9BCAB2468D5D33B2A /* PhotoPickerViewController.swift */, + 6E7B8A98BDCD775D95A65561CB633988 /* PhotoPickerViewController+SwipeSelect.swift */, + 793B46377505158FB3FA3993B1F26B7A /* PhotoPreviewContentView.swift */, + 13C3AA2223DCB5B690D31BDE0E9B10FE /* PhotoPreviewSelectedView.swift */, + F6E753BF4DC689F4ECAEF1290641355D /* PhotoPreviewSelectedViewCell.swift */, + 44382226E6FED16ABDF81E709F565C53 /* PhotoPreviewVideoView.swift */, + 50A982AD2004E27721F97D1CA59F821E /* PhotoPreviewViewCell.swift */, + 6FB653B8C90C89078F860D375DD46741 /* PhotoPreviewViewController.swift */, + 922AB5F39B78FAE087B4877B51BDD90D /* Picker+PhotoAsset.swift */, + D26F48DD9580641912BB27C678E2A07E /* Picker+PhotoManager.swift */, + BF3616C052A86582F38076ABD8305A20 /* Picker+PhotoTools.swift */, + D832A474A922ABCB4DD2404EA5BE944A /* Picker+UIImageView.swift */, + FE27C9D0A29943792024F87E3844C4E3 /* Picker+UIViewController.swift */, + 3A6C56626C1C22322F7454CA10D9D947 /* PickerBottomViewConfiguration.swift */, + 5095ACA69E440BD72A1F998B40641A55 /* PickerCamerViewCell.swift */, + 2417C93289DBB418D2664E0013FA0907 /* PickerConfiguration.swift */, + BF50DEBE3BC46AB48E86E2A87AA8254C /* PickerInteractiveTransition.swift */, + 7B18E64A636AF66F9411A62E99C511CB /* PickerResult.swift */, + 2A3127A758A3F0C0F5E00C1B60BE235F /* PickerTransition.swift */, + 8E94E14400898B18B1EB176526DB9420 /* PickerTypes.swift */, + 547272275970D4CE23C428E23093CC37 /* PreviewLivePhotoViewCell.swift */, + DFDCB9B82E208AA6A69A9F49DAF14549 /* PreviewPhotoViewCell.swift */, + C4EF7C9F1003DF37C35C784CBD74FA4B /* PreviewVideoControlViewCell.swift */, + 0C227B478900D15729E225BE531D8946 /* PreviewVideoViewCell.swift */, + E2424CB8B3A8EAD348907F16762FC981 /* PreviewViewConfiguration.swift */, + ); + name = Picker; + sourceTree = ""; + }; 0DC869C40B5CC78BC0E81F09322D6298 /* Support Files */ = { isa = PBXGroup; children = ( @@ -554,68 +640,6 @@ path = "../Target Support Files/Kingfisher"; sourceTree = ""; }; - 113214CA64894E92AC559BBFD79A303A /* Editor */ = { - isa = PBXGroup; - children = ( - 4ACC2DF1D1BF3200F0D5D263A1F405DB /* CropConfirmViewConfiguration.swift */, - 440B4B2232CAD0176D354214FF89F590 /* Editor+PhotoTools.swift */, - B112C5DD2089296DAFD840326F0C85C0 /* Editor+UIImage.swift */, - 0D9BFD4E9DD6EE91B400C568802A731F /* Editor+UIImageView.swift */, - 930641217CE7625ADB374829A94CCA81 /* EditorConfiguration.swift */, - A96275918A0C8AE4AFDE89364F13CEE7 /* EditorController.swift */, - 562321E3DBAA38414FA20AEDF5EA214C /* EditorCropConfirmView.swift */, - 85F908541FE319223EEB696EC7130852 /* EditorImageResizerControlView.swift */, - 3DE117DEE9BC8FBEAF25DCC404A55C0D /* EditorImageResizerMaskView.swift */, - 92B15CDBEAFF705823B43C168FFC30F6 /* EditorImageResizerView.swift */, - 9A98566174094B340F2EED50D8D01CC7 /* EditorToolOptions.swift */, - AD6464CDD2E4B2FAF5661A075B8090EE /* EditorToolView.swift */, - 6DD0466B10B0558368BF1C65D70E2EFB /* EditorToolViewCell.swift */, - DDAA1BAE55A5E39451124EE003C59D1A /* EditorToolViewConfiguration.swift */, - 334D1DCE7985A1C03D5E2F8A157E08E0 /* EditorType.swift */, - FAE7F809DA36DD7EB68C544C3E22811C /* PhotoCroppingConfiguration.swift */, - 5CAA1C6552AEAF1E552935EDDF916435 /* PhotoEditorBrushColorView.swift */, - 7B0556648367EF7BE0BBDA2C2DE33EB5 /* PhotoEditorConfiguration.swift */, - 14EA16CB3672F9ECFC825BFE03542467 /* PhotoEditorContentView.swift */, - 5C754E497022D097EF2A113AADABDF9B /* PhotoEditorCropToolModel.swift */, - 3C3042A1C731FA1D1F809D292A9DCF78 /* PhotoEditorCropToolView.swift */, - F1A5151C93FB53BF11EACE400D3A731D /* PhotoEditorDrawView.swift */, - ACF9CEB85ED171BE18D3860150E50D88 /* PhotoEditorFilter.swift */, - E08650E661A65D8AFF34727D04C6DD9E /* PhotoEditorFilterView.swift */, - 433775A97C99D7EC1558C62FE54DE366 /* PhotoEditorMosaicToolView.swift */, - 393CD8E55D303D5416D741CEDFC7AE48 /* PhotoEditorMosaicView.swift */, - 6726B45A690D709E558A34EB87B86CC1 /* PhotoEditorView.swift */, - 7769420A27CAC894C5724E42564AE82F /* PhotoEditorViewController.swift */, - 1B25A28755D202E5829F73CBBB87EA68 /* PhotoEditorViewController+Animation.swift */, - 49326A675DE29F1A0F9803D2E75A51F4 /* PhotoEditorViewController+Export.swift */, - 29F07941959855158988322CC0B2146B /* PhotoEditorViewController+Request.swift */, - E23FF50CBEF9896F69F8C33C30A0109F /* PhotoEditResult.swift */, - 2572F6B184769B86544433ECB4E7CB07 /* VideoCroppingConfiguration.swift */, - 2EC251D36D9079F779067D48D0750946 /* VideoEditorConfiguration.swift */, - 07B5BC0DCE286D3ACA675FCAECE8F641 /* VideoEditorCropView.swift */, - 28805DA79279D39C9E775A3C83679CEB /* VideoEditorCropViewCell.swift */, - 67261FF3C5F6BE90491DD8FBEC806B71 /* VideoEditorFrameMaskView.swift */, - 46AFEFEC9572D73F2670FD1471847EB4 /* VideoEditorMusic.swift */, - 98E0603A4E03E57E7695F8194AC792B5 /* VideoEditorMusicAnimationView.swift */, - 16860602361C1B4B1BC81BA5BC4762F9 /* VideoEditorMusicView.swift */, - 40565C0E5DF5F1754DDB4BC58488CA8A /* VideoEditorPlayerView.swift */, - 4852514CAA80364B32BE45D4609601D1 /* VideoEditorViewController.swift */, - 85AEE49BE66EE5DDFE7A24DE45426D21 /* VideoEditResult.swift */, - ); - name = Editor; - sourceTree = ""; - }; - 167506912D42AAFAACDA3E4C8CC69D81 /* HXPHPicker */ = { - isa = PBXGroup; - children = ( - CA54B90FB21218C183952A9AAD45959C /* Core */, - 113214CA64894E92AC559BBFD79A303A /* Editor */, - 6783BEDDE386EB17D746F1CD1555457F /* Picker */, - BFE22832F6DBD9B29C1FF48ED5612A70 /* Support Files */, - ); - name = HXPHPicker; - path = HXPHPicker; - sourceTree = ""; - }; 298D67ECCBC7D511977640F1C5B4E33A /* Frameworks */ = { isa = PBXGroup; children = ( @@ -628,12 +652,24 @@ 2F796EA87B7915369840043C7C45D3C0 /* Pods */ = { isa = PBXGroup; children = ( - 167506912D42AAFAACDA3E4C8CC69D81 /* HXPHPicker */, + 4199820B9165EF771A386B460E5E9D10 /* HXPHPicker */, 8A4A1DC0AFF8552AB4A122443A336133 /* Kingfisher */, ); name = Pods; sourceTree = ""; }; + 4199820B9165EF771A386B460E5E9D10 /* HXPHPicker */ = { + isa = PBXGroup; + children = ( + E0613EC6B632D1D3A9591E96DCA9641F /* Core */, + B9DCC9461F1C23AD354FA93A72EB448D /* Editor */, + 0A87C88678C1B052134FD48C4F1AD702 /* Picker */, + 5CAD4932264346B0DB587500236DA084 /* Support Files */, + ); + name = HXPHPicker; + path = HXPHPicker; + sourceTree = ""; + }; 4543C0AF3A279A7487E872DAE16FAF61 /* iOS */ = { isa = PBXGroup; children = ( @@ -647,72 +683,25 @@ name = iOS; sourceTree = ""; }; - 6783BEDDE386EB17D746F1CD1555457F /* Picker */ = { + 5CAD4932264346B0DB587500236DA084 /* Support Files */ = { isa = PBXGroup; children = ( - D21BD73027CF44C6BED97C7AA0D0083F /* AlbumListConfiguration.swift */, - D20513BAF16D62230CAE551868C98675 /* AlbumTickView.swift */, - EBF7D3D6FDAB3790527AFB5B79178329 /* AlbumTitleArrowView.swift */, - 435165BD18BE952E53ED4496283BEA2A /* AlbumTitleView.swift */, - BDB5B0C5872FE958E4C477AB6D0FA495 /* AlbumTitleViewConfiguration.swift */, - DDBA3B9B2A3A5A8429A5E40D8189F85E /* AlbumView.swift */, - 622A7AEEC8EF9858A240F890A5628DF3 /* AlbumViewCell.swift */, - 93787EA42D0CB0E0DB7D3E5CFC95CCE0 /* AlbumViewController.swift */, - 6B31C520BDE90F0E4660338BCF321C7D /* CameraConfiguration.swift */, - 46A41212FDA74FB99EA30F3724F33AF5 /* CameraViewController.swift */, - 0AFAA52721AA4872285B203DE209D42A /* DeniedAuthorizationView.swift */, - 7F1DE1AB74246D67AB35992D09686534 /* EmptyView.swift */, - 7AE851F339FBCED4B53662017B5E7FC7 /* EmptyViewConfiguration.swift */, - FEA9291F441E8AB422086ADED6C80791 /* GIFImageView.swift */, - 60433D7514CF80497C4891C8F6FA49A6 /* LocalAsset.swift */, - FAF0BE88CF2FD74AF5588F55CD6D76C3 /* NetworkAsset.swift */, - 0B3C9D20F25D671AC5B9A148A47154D5 /* NotAuthorizedConfiguration.swift */, - C813900019839F0CB70608F2F3CDB23C /* PhotoAsset.swift */, - 2A726DE17A03F99C4F2A95D4E7C45FBE /* PhotoAsset+Network.swift */, - 99DA44C4AA4F687FC6AE64DB7411C7BB /* PhotoAsset+Request.swift */, - 2F79F16D3A44897480990D7FF64C5895 /* PhotoAssetCollection.swift */, - 2B6A3CC5B150A69213DFC957AFBCF1B0 /* PhotoListCameraCellConfiguration.swift */, - 7C584C14838C0813940BD3D7437CD6B0 /* PhotoListCellConfiguration.swift */, - D06882E3535F72030E939C29E21B17BF /* PhotoListConfiguration.swift */, - 407AE5F5426D0C24AFEBF692B224F738 /* PhotoPickerBaseViewCell.swift */, - 39495AB0F9B887AFACB5C7CEE8AFBF53 /* PhotoPickerBottomView.swift */, - 4CE26138680D4ED69EA35BA9E5EDDFDF /* PhotoPickerController.swift */, - C16051339A3ABA4B72958557C53630D5 /* PhotoPickerControllerProtocol.swift */, - AE155CEA770DE8908844B4751507F566 /* PhotoPickerSelectableViewCell.swift */, - 0A7C48AC132FFF36BA1B19AC52457D00 /* PhotoPickerViewCell.swift */, - 5A29336BB5E87AB2B535EBC9E33BBC28 /* PhotoPickerViewController.swift */, - 274D10D8BF7692BA4FE1A10BDDB40188 /* PhotoPickerViewController+SwipeSelect.swift */, - 9941EF650C94303373933DCB0374B042 /* PhotoPreviewContentView.swift */, - 563425CB7D1694773F59DCE917385445 /* PhotoPreviewSelectedView.swift */, - 14473A4D04E43FB55A342C3672829644 /* PhotoPreviewSelectedViewCell.swift */, - DC7E51B729C48D2CDC3E3F7D28CB4AA8 /* PhotoPreviewVideoView.swift */, - 4A32037254E41EF30ECF6E30B3B2155F /* PhotoPreviewViewCell.swift */, - 77BC73F398E8C855D1B45CB97FDD7BC3 /* PhotoPreviewViewController.swift */, - 6F3FBB0051619CE6CC673EAD87D1940E /* Picker+PhotoAsset.swift */, - EC8B9253A80AF8325CA6FB2DECD32CEA /* Picker+PhotoManager.swift */, - 1278BEDF9340DEF89E35C3AA316E50B9 /* Picker+PhotoTools.swift */, - E09AB868F28C37D80342CD9A8C37C390 /* Picker+UIImageView.swift */, - 1064B2319FF1C94864B2CE729285F9B8 /* Picker+UIViewController.swift */, - FB78885389B2F94B85F99BB123138879 /* PickerBottomViewConfiguration.swift */, - 230C7F91CA2126BEFA59E947E57E48E9 /* PickerCamerViewCell.swift */, - 0BD7BEECB15A0E197A4C7FC3F3536B5E /* PickerConfiguration.swift */, - 68474C198A87E5997989EF6105F7CDA8 /* PickerInteractiveTransition.swift */, - 0DC0FB7A4C3B2FA833748E4B9AF10B48 /* PickerResult.swift */, - 56E702AA502667D742CB245D322D6AD0 /* PickerTransition.swift */, - 0A53D58E9CA25D13DD8BF367063D444B /* PickerTypes.swift */, - 1DA2046F0F15237DEC99B2E540F33A02 /* PreviewLivePhotoViewCell.swift */, - 3A5224346D4E0C403876184DA83D02B2 /* PreviewPhotoViewCell.swift */, - 6677C1F9671029C339103F88B6A7518E /* PreviewVideoControlViewCell.swift */, - BFCAF459B63CB461D420ECA303B2D6D9 /* PreviewVideoViewCell.swift */, - CC1D69AE8602A539A85DBDE7AE6CB27B /* PreviewViewConfiguration.swift */, + 44A108E31F90D17DD90D02847F4782FE /* HXPHPicker.modulemap */, + 0662662518A6290FC8C1A722A9CF987A /* HXPHPicker-dummy.m */, + FE76BB39DAEAF02C9EBAD0EBAE9121FF /* HXPHPicker-Info.plist */, + C53E5416E10DCBD3D144B7B44A217D8F /* HXPHPicker-prefix.pch */, + 0E0F1CF360C4FBD2915F628914AC723C /* HXPHPicker-umbrella.h */, + DF30C43C9CEC6FD791CA87DE084631BD /* HXPHPicker.debug.xcconfig */, + 333194D5139911F72790CE8255D676D2 /* HXPHPicker.release.xcconfig */, ); - name = Picker; + name = "Support Files"; + path = "../Target Support Files/HXPHPicker"; sourceTree = ""; }; - 7A6B045FB2F7D4219E2CA0959714F397 /* Resources */ = { + 607EB50A1339D6E73FE8175D804B88C2 /* Resources */ = { isa = PBXGroup; children = ( - F54610899D0457A64E9CF06BD1A9CB13 /* HXPHPicker.bundle */, + 7B05A3B63B09302EC01FD1DB831D63E6 /* HXPHPicker.bundle */, ); name = Resources; sourceTree = ""; @@ -791,19 +780,63 @@ path = Kingfisher; sourceTree = ""; }; - BFE22832F6DBD9B29C1FF48ED5612A70 /* Support Files */ = { + B9DCC9461F1C23AD354FA93A72EB448D /* Editor */ = { isa = PBXGroup; children = ( - 204D2FFEE0B3ACCD72F736E5259B4A32 /* HXPHPicker.modulemap */, - B709B0FBEA1226AA6EEBA1388DD9B359 /* HXPHPicker-dummy.m */, - 81A6AAF0D0AE5FBD7D6F62A2CD11DB9A /* HXPHPicker-Info.plist */, - EA4B321A0BB5316F5CC31090FC409B18 /* HXPHPicker-prefix.pch */, - 765C30F1D982A3BDA6E68508F94E615E /* HXPHPicker-umbrella.h */, - 444030316457F4B1626AA794BBFBD0D7 /* HXPHPicker.debug.xcconfig */, - 2D1CB169A7364BBE20552451BB7BCCFD /* HXPHPicker.release.xcconfig */, + 82F74FDC712BFDE6509B6E79F037D141 /* CropConfirmViewConfiguration.swift */, + E7D4BBD8DFCFCEC0DD7436685B346AEE /* Editor+PhotoTools.swift */, + 4B2928135BDA49032CE7C48A71B99AC8 /* Editor+UIImage.swift */, + 85A32ECAB16EB52AFB3B144CBB5CDD1E /* Editor+UIImageView.swift */, + A9BB05A6E5F210ED0D2F2D9B8618D1AE /* EditorChartlet.swift */, + 2C9EB2FD1D24644738C1DDDF90C15176 /* EditorChartletView.swift */, + 5AE83272ABB8F7BE9A624B5D73185FFA /* EditorConfiguration.swift */, + 0984B48E1917B8D20588117A5422D7F8 /* EditorController.swift */, + 8A59F7C6F400F5F0199C9DC26E4365DF /* EditorCropConfirmView.swift */, + 5C26BB434BF14419E1286FC52D083D50 /* EditorImageResizerControlView.swift */, + 3DCAC90FCDF67BB7420B528333888A71 /* EditorImageResizerMaskView.swift */, + 9F14DE66B4E355A94782F996E6DAFBEB /* EditorImageResizerView.swift */, + 6EE004AFA99195590A76014C2A986081 /* EditorStickerContentView.swift */, + ED56BC152265BC047FBBFF628A7FE04D /* EditorStickerItemView.swift */, + 194F9FFAA2823CF7D508CB4DE27E0634 /* EditorStickerTextView.swift */, + A4A77CE2F054070C1EC646B504A7E27D /* EditorStickerTextViewController.swift */, + 640ED6DA1D830AE84C026E59A5A0A089 /* EditorStickerTrashView.swift */, + 6C5BD47EFE09F886E090A3663AD12226 /* EditorStickerView.swift */, + 20C424910C56FC8369CE2F1BB9DD9A99 /* EditorToolOptions.swift */, + 0D5B0AC3D0F8E972EE384C4694E98215 /* EditorToolView.swift */, + 55BE8C50DAE322D6879995049D67F0E6 /* EditorToolViewCell.swift */, + 601E50F79FCB543B83354FEDAC5DD99F /* EditorToolViewConfiguration.swift */, + BC8D0A8FBB166F0B760A03E76DF00CD2 /* EditorType.swift */, + DE752415B71C6B20179128E19513AD63 /* PhotoCroppingConfiguration.swift */, + 0A14BE291C734F10CD472BE99346267D /* PhotoEditorBrushColorView.swift */, + 7774CD23C7037BD21F3774D56A2CCA08 /* PhotoEditorConfiguration.swift */, + 8FAC9361D156824AC15428F16BF61EE6 /* PhotoEditorContentView.swift */, + 9C96763AAEA238547056A5E47A0724E1 /* PhotoEditorCropToolModel.swift */, + 7A6570757C0042B74807A527EF6D3052 /* PhotoEditorCropToolView.swift */, + 5B15A167734DB17B64D7129AA996428E /* PhotoEditorDrawView.swift */, + AC1F04C732D001C893508ADDC6B738B5 /* PhotoEditorFilter.swift */, + 9FEA074AB7BA3AF49CD342C40DC638CB /* PhotoEditorFilterView.swift */, + F2032572C9F787B59664C732AF01595D /* PhotoEditorMosaicToolView.swift */, + C90FD1C9FAB44FCAE623AEE8C235FB05 /* PhotoEditorMosaicView.swift */, + 8138B689CFE3AFEEEE63A451915B3564 /* PhotoEditorView.swift */, + 6DDE0043633422897202310C3D628F45 /* PhotoEditorViewController.swift */, + 393D1A2C20CED9E766A07B87F987EF5F /* PhotoEditorViewController+Animation.swift */, + 8372D0B1E8AFE84378987A633F1EB47C /* PhotoEditorViewController+Export.swift */, + B3EEBD8B7D2B99F3EB22F51AF071CE35 /* PhotoEditorViewController+Request.swift */, + ACD0ED004361D4FB1A8A3A4C789F9F36 /* PhotoEditResult.swift */, + 6864336E8793E888F675FD96FF5EA904 /* VideoCroppingConfiguration.swift */, + B37E34968FF4C9E754E9DBD75F2B1116 /* VideoEditorConfiguration.swift */, + 2E11EBFC3916F6386F5C5742499E7DBF /* VideoEditorCropView.swift */, + 46936DB194A78211EACC9434C7564626 /* VideoEditorCropViewCell.swift */, + 603CD0956C8179CED00CD985F9A76D17 /* VideoEditorFrameMaskView.swift */, + 964AC6105B2F228667606A7E878EC767 /* VideoEditorMusic.swift */, + 40CEA5DD7A853F6B5BE36A6EA1F48FCD /* VideoEditorMusicAnimationView.swift */, + 7C778D7FF696B8B3929C66CF06F93BA9 /* VideoEditorMusicView.swift */, + CBF965A931D668DD9C27E4D57C9D32DE /* VideoEditorPlayerView.swift */, + 6E2B8887898AA7C497D1A6FEAEA2AC8E /* VideoEditorSearchMusicView.swift */, + 7D9AEDAEC3BDDD906F5EBABA0945250C /* VideoEditorViewController.swift */, + F9A0461D6318AB717C40D28E6674A988 /* VideoEditResult.swift */, ); - name = "Support Files"; - path = "../Target Support Files/HXPHPicker"; + name = Editor; sourceTree = ""; }; C678B7E2CB6AC4321889B3A8C603C8F7 /* Products */ = { @@ -830,62 +863,6 @@ path = "Target Support Files/Pods-HXPhotoPickerExample"; sourceTree = ""; }; - CA54B90FB21218C183952A9AAD45959C /* Core */ = { - isa = PBXGroup; - children = ( - 3CB7911DD2178CE74C965635DDCF814C /* AppearanceStyle.swift */, - EEEA33EA3D93522BB858E2B400DE568E /* AssetManager.swift */, - 6FDE1FACC4C252967F8A52F8A003EB75 /* AssetManager+Asset.swift */, - FA94CECB93BDBEC3604957BBD28190C9 /* AssetManager+AssetCollection.swift */, - 1C8BEA4AE65FAE282E599E49304003A4 /* AssetManager+Authorization.swift */, - 399EF8348A2B332A84400E8075EA42A6 /* AssetManager+AVAsset.swift */, - 868C8FA5D842678E85DEB2612008F42C /* AssetManager+AVAssetExportSession.swift */, - AF2CE9ADEBD524066BB454888BF5C597 /* AssetManager+Image.swift */, - 832E000FACA6AD9958B6822E85D157BC /* AssetManager+ImageData.swift */, - 7378427FDA946DF5B716338C86805FE1 /* AssetManager+ImageURL.swift */, - 4789F562F464012923FC30183A2741A7 /* AssetManager+LivePhoto.swift */, - E65DA63DD4AD4E432FAD881813877823 /* AssetManager+LivePhotoURL.swift */, - 28C3604C69772C27DD79C7BE69E40200 /* AssetManager+VideoURL.swift */, - C4067FCFD0137862596BF9CCCC45B520 /* BaseConfiguration.swift */, - 9508308A31AC567C83718C4F064C5195 /* BaseViewController.swift */, - 28E0147A913D85F3F6A23FC33C8FDC32 /* Core+Bundle.swift */, - D1EE561EF370C515FF47278EE93FD9EE /* Core+CALayer.swift */, - 2DB4BC85761011473A365686A6806B07 /* Core+Data.swift */, - 0A08AEFD3EF5DD92F1C62C3076F53E31 /* Core+Dictionary.swift */, - CD5233B5ACF9B9672AA3AE6C355FF3E9 /* Core+DispatchQueue.swift */, - 2D24914BBAD96BEC89719F3CAD50D605 /* Core+PHAsset.swift */, - 688A16315FA65A47A86E08E0474EA870 /* Core+PHAssetCollection.swift */, - 2A676EEE2F99A99BBE1F05A3FEFB6E4F /* Core+String.swift */, - 4E7ED23FB2F6C711FC0C9A4DA50B8290 /* Core+UIColor.swift */, - AC1D06F8F8A9A5254A84014E10162059 /* Core+UIDevice.swift */, - F034C0845F804BF4035366CBAA8EEF8A /* Core+UIFont.swift */, - 478A78BD12272959D6D0C7C507437A97 /* Core+UIImage.swift */, - 890E7EFC6AF7BBE7960EA22FF17CBC49 /* Core+UIImageView.swift */, - 288B0C38BED59BD62A68D32EEDB6E1D6 /* Core+UIView.swift */, - ADBCF2C1F6B918828450523DFE5EAA55 /* Core+URL.swift */, - 93C6D6596A5CE21A3B66EB401BA0787E /* CustomLanguage.swift */, - 692781CC1099A4A6F1FE188A1A39EF5B /* HXPHPicker.swift */, - 5AB50CCAEE13DBBDE49A969469366978 /* ImageContentType.swift */, - 91CE9F7A8548481CF2153C1EE7C28958 /* LanguageType.swift */, - 2056E7A211D4556EBA9699FB628661B7 /* LivePhotoError.swift */, - A1C97C36F6828D4797C004539D3D31E8 /* PhotoError.swift */, - 21238D3AD6B82A27C7FDDE411816C9E9 /* PhotoManager.swift */, - 6EB1CEAC38537E23AF5B9EEF4224CC28 /* PhotoManager+Audio.swift */, - B88513158CCCF5FC56759E5802F83DE3 /* PhotoManager+Download.swift */, - DB5691815F77BF894DB9C887C2F9231F /* PhotoManager+Language.swift */, - D19604CBBDF0009BFE40E3E27679CD24 /* PhotoPanGestureRecognizer.swift */, - 0C446E94E2154761F17EA4E3FC15163D /* PhotoTools.swift */, - 7C5D81B2769F3E2F9633C5F73B50C5F3 /* PhotoTools+File.swift */, - 347CBBFB5B67E48EEAB7CF3C25E42653 /* ProgressHUD.swift */, - 32E577CB345214F9D6E8E9AD4CCFC928 /* ProgressImageView.swift */, - 3A9209C818ED6E1F1DFCAD317C6FAF7A /* SelectBoxConfiguration.swift */, - 00CA69F728A555325DA084E0234B3A50 /* SelectBoxView.swift */, - D72BAFE08AD4646F7426D9168E57588A /* VideoPlayerView.swift */, - 7A6B045FB2F7D4219E2CA0959714F397 /* Resources */, - ); - name = Core; - sourceTree = ""; - }; CF1408CF629C7361332E53B88F7BD30C = { isa = PBXGroup; children = ( @@ -897,6 +874,62 @@ ); sourceTree = ""; }; + E0613EC6B632D1D3A9591E96DCA9641F /* Core */ = { + isa = PBXGroup; + children = ( + 8CB4883DF7F4726E4F8552533FCF2D06 /* AppearanceStyle.swift */, + A5493ECCBC7EE357FB08A312C5187DA7 /* AssetManager.swift */, + 3108BD33E52BC7B7B8AB07AF906B4917 /* AssetManager+Asset.swift */, + 067D5101BD1A005C8A914F9696E02C12 /* AssetManager+AssetCollection.swift */, + B9EBA2C0E0BA1ED2B1D2424066952CAB /* AssetManager+Authorization.swift */, + A65122D5FAF94B582526F068E163CABB /* AssetManager+AVAsset.swift */, + D7556215365F7415A0C3CB7D2340BDB6 /* AssetManager+AVAssetExportSession.swift */, + 562873123116F153C238FBC76B789ADC /* AssetManager+Image.swift */, + C0D1AEBFA85DFAAE174E81C5C8420FA9 /* AssetManager+ImageData.swift */, + 6D79002CD77B4E701030F2586A87818F /* AssetManager+ImageURL.swift */, + 25BDA27B1F9CB254542F4EB05308DDC2 /* AssetManager+LivePhoto.swift */, + 925AB67D69D139C4CA3936AC6D7CA86C /* AssetManager+LivePhotoURL.swift */, + 778C2F66B7672CC04E6C9CF4CD600C1A /* AssetManager+VideoURL.swift */, + 357701EDDEE245E85839081476097A71 /* BaseConfiguration.swift */, + 531EEF01BF14E556D3BF4E84DAC9FCB2 /* BaseViewController.swift */, + 71812356610599E70B089E7AC48C42B6 /* Core+Bundle.swift */, + 7E561675294E9B1E41841D4B69EC2FD4 /* Core+CALayer.swift */, + A9C4F29EDC2D5EA82CA16D831E0B6F24 /* Core+Data.swift */, + 6B431BF357DC6E21D6492CFEA10AB872 /* Core+Dictionary.swift */, + 7BED76A0F3AB74CD3E2060A361D516CC /* Core+DispatchQueue.swift */, + 2031A7C728C7A69FF24AF9CD69785785 /* Core+PHAsset.swift */, + 11529B77A8050B2C53CC45D8075176E9 /* Core+PHAssetCollection.swift */, + 28B90775923927775FA22268513B4D38 /* Core+String.swift */, + 6E75F2BADFD9C9A1D757BF931E235FAE /* Core+UIColor.swift */, + B7D393D34E48D9283DF87A12A2627BF4 /* Core+UIDevice.swift */, + 67C0F210CA2203D043BA26DAAC26B62B /* Core+UIFont.swift */, + C21CCC463978FD90835D06157C0F0A41 /* Core+UIImage.swift */, + 20F9D58158F64CD21D168B9BCAB9BBAD /* Core+UIImageView.swift */, + 09405FB889DF0D6EB6CFE76DAF940ACE /* Core+UIView.swift */, + 91FB523C544F0FAE04EE01666E96D5C6 /* Core+URL.swift */, + 06820DCDBB2A25DC1B048442B04CE108 /* CustomLanguage.swift */, + 94354ED183F6FDBBAD76319C22F8E0E6 /* HXPHPicker.swift */, + B502D0AF6DA8DF74CB65F21CA80C095D /* ImageContentType.swift */, + 130F8F4988095CCA5E5073DB439F400A /* LanguageType.swift */, + 2529D5686E3CA4F08BA564C0D5D71403 /* LivePhotoError.swift */, + 99B5F52EA74DF46254B99C01593AB86F /* PhotoError.swift */, + 2FCA564D8B180872B0243FCDF544FDB7 /* PhotoManager.swift */, + 0B1B6DC206B2566D105FADA1EDCCCAB3 /* PhotoManager+Audio.swift */, + A566C25E75296EF7C4633A6B69326371 /* PhotoManager+Download.swift */, + 06F7E3B1CD9CAA408FCF727E7CFFFE8C /* PhotoManager+Language.swift */, + DC6E5B07C8617D54F1595DC8BC675BB2 /* PhotoPanGestureRecognizer.swift */, + E5BDDEB666AF9858765B4C5C2E03009D /* PhotoTools.swift */, + 0D97219B6BD6B8164DE061C3150E5DB4 /* PhotoTools+File.swift */, + 128913A67D37CFEBC3CC0ED2B96963E4 /* ProgressHUD.swift */, + CD19B924DF5EBB6FA318331966BE818B /* ProgressImageView.swift */, + BDABEFFCBC7D4F3E556B386942CFD67D /* SelectBoxConfiguration.swift */, + CE6E57EB6B1E40BA02666FDBF20FD3DA /* SelectBoxView.swift */, + C70744E46D235762935B383CD84373ED /* VideoPlayerView.swift */, + 607EB50A1339D6E73FE8175D804B88C2 /* Resources */, + ); + name = Core; + sourceTree = ""; + }; F978745725F9A4E02851D49B2DE19969 /* Pods-HXPHPickerExample */ = { isa = PBXGroup; children = ( @@ -917,27 +950,27 @@ /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ - 3B49E15A347557EF305DF512CCABF936 /* Headers */ = { + 32EE5580ECF63DA428D8A024C581C3F3 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 5F475B0DAE6EF3BA9ADA42B56F37BC72 /* Pods-HXPHPickerExample-umbrella.h in Headers */, + 2BC932D572A7355D9BAAEAA5319D5834 /* HXPHPicker-umbrella.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; - 4C278229DCD33435D3905828596F85B6 /* Headers */ = { + 3B49E15A347557EF305DF512CCABF936 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - DB452964085755719A4EFBC2927740BC /* Kingfisher-umbrella.h in Headers */, + 5F475B0DAE6EF3BA9ADA42B56F37BC72 /* Pods-HXPHPickerExample-umbrella.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; - 64AA897B6D93BCAF7810AEE0257D8514 /* Headers */ = { + 695D43981364C2CD76561E3B90671793 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - FD57AECC2FAE39B6BA653D264D305EA3 /* HXPHPicker-umbrella.h in Headers */, + DF45457B6F4DF804FE6F4A19E564E7CE /* Kingfisher-umbrella.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -963,8 +996,8 @@ buildRules = ( ); dependencies = ( - 6BED7F9EB43CA0985013A6B76DD80D8F /* PBXTargetDependency */, - B4EF0961C34535A7067898ACBFA3D8EA /* PBXTargetDependency */, + F7FC8585F12118A18996FE831F35E03D /* PBXTargetDependency */, + 9384A8B4B11CE8EB86E64A0B42B68221 /* PBXTargetDependency */, ); name = "Pods-HXPHPickerExample"; productName = "Pods-HXPHPickerExample"; @@ -973,17 +1006,17 @@ }; 6968C202A297A606D5EACC3679AAA627 /* HXPHPicker */ = { isa = PBXNativeTarget; - buildConfigurationList = 5731C3B6B9581B1FD1B561BD4DBC53D0 /* Build configuration list for PBXNativeTarget "HXPHPicker" */; + buildConfigurationList = 092BA46F51227E0BD4B5EA8343E380AA /* Build configuration list for PBXNativeTarget "HXPHPicker" */; buildPhases = ( - 64AA897B6D93BCAF7810AEE0257D8514 /* Headers */, - 83F91E708307246893CE47CC5FE84477 /* Sources */, - 11BEC1D9E4A075697EA0F8103D8806B9 /* Frameworks */, - 05C31A491D014E3DCEB71CF6F9E45A8E /* Resources */, + 32EE5580ECF63DA428D8A024C581C3F3 /* Headers */, + 6C3475796489685DE98D9EE8024481FA /* Sources */, + C57A0CCF779214F6A07E08ABE894F1DF /* Frameworks */, + EFC267A2A4E048607402BA590F90738A /* Resources */, ); buildRules = ( ); dependencies = ( - 9496A921918523D53DEC196FB564BB0C /* PBXTargetDependency */, + D47198A142B342C7070C96EF96BAAC6F /* PBXTargetDependency */, ); name = HXPHPicker; productName = HXPHPicker; @@ -1009,12 +1042,12 @@ }; E8022D22FAA6690B5E1C379C1BCE1491 /* Kingfisher */ = { isa = PBXNativeTarget; - buildConfigurationList = 5F86390500197AE0F0D00FAA79B2C2DE /* Build configuration list for PBXNativeTarget "Kingfisher" */; + buildConfigurationList = 061001F00128D631CC242AABFF6E3E78 /* Build configuration list for PBXNativeTarget "Kingfisher" */; buildPhases = ( - 4C278229DCD33435D3905828596F85B6 /* Headers */, - 8444FCF2951DEB16362C03E8FEAA7B0F /* Sources */, - CD99B9959AEB9E998B95B7636F9CE3F6 /* Frameworks */, - A43E9166ECFC9B2044F3F9C854F8C8B3 /* Resources */, + 695D43981364C2CD76561E3B90671793 /* Headers */, + B31233D44EAA9B03D4822661CF303018 /* Sources */, + 73B3835300733D94308D4E1282BFF8BF /* Frameworks */, + B10E9B6FC1AFA8EC1CC3B6B26DF94222 /* Resources */, ); buildRules = ( ); @@ -1056,25 +1089,25 @@ /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ - 05C31A491D014E3DCEB71CF6F9E45A8E /* Resources */ = { + 66508E9454A464EA71020A2D5902BEC2 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - C5D3D6D13C4A496F8AD3086E56071695 /* HXPHPicker.bundle in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 66508E9454A464EA71020A2D5902BEC2 /* Resources */ = { + B10E9B6FC1AFA8EC1CC3B6B26DF94222 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; - A43E9166ECFC9B2044F3F9C854F8C8B3 /* Resources */ = { + EFC267A2A4E048607402BA590F90738A /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + B4F80FA3CF53686695C9A00777FB40BC /* HXPHPicker.bundle in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1097,253 +1130,263 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 83F91E708307246893CE47CC5FE84477 /* Sources */ = { + 6C3475796489685DE98D9EE8024481FA /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 629B919C04E7752CA258929E137EB63B /* AlbumListConfiguration.swift in Sources */, - 9309134E89EC613E07DC68FB303D350C /* AlbumTickView.swift in Sources */, - FA0827C8B221F88DED21E0FE23E3AECA /* AlbumTitleArrowView.swift in Sources */, - E43919F194110BBFD2A02D2A711EA234 /* AlbumTitleView.swift in Sources */, - 1AB945BFDE9B8D1E92B94F368673E48C /* AlbumTitleViewConfiguration.swift in Sources */, - C5EC1C4482BA70E9AD148853BB5DE251 /* AlbumView.swift in Sources */, - 50AFC5402E645D6DD51CF067E1C531CA /* AlbumViewCell.swift in Sources */, - 988AB39B0A4B3979280E04AB36732573 /* AlbumViewController.swift in Sources */, - 97AAFE6AD88A3AF29A42965ECC9A9EAE /* AppearanceStyle.swift in Sources */, - F83E52B5DD84356CC6D381D104E0510C /* AssetManager+Asset.swift in Sources */, - 7A5729A963AE9B96122A0EAAF68312AD /* AssetManager+AssetCollection.swift in Sources */, - DF627F7A09CAD7B64D1FACCFCC4DF3E9 /* AssetManager+Authorization.swift in Sources */, - A54081DDED58482833ADAE0F49F26676 /* AssetManager+AVAsset.swift in Sources */, - DF83E1117DFD6586FA953D88DAEE5D9E /* AssetManager+AVAssetExportSession.swift in Sources */, - 31D16C8DBF9162547C369FD431C49828 /* AssetManager+Image.swift in Sources */, - C28C4720D62A993897AAF4156B6910E3 /* AssetManager+ImageData.swift in Sources */, - A555A68F52A8EAD989E40F5D92D76699 /* AssetManager+ImageURL.swift in Sources */, - 0F382FBE040805464373238F861EF123 /* AssetManager+LivePhoto.swift in Sources */, - A07CB9EBB03F2054E4EB5E91F621A8DE /* AssetManager+LivePhotoURL.swift in Sources */, - C7E1E72828608CA75568B28281B7283D /* AssetManager+VideoURL.swift in Sources */, - 5EB00E4C6D46C1CF6698E8B66E5AAE9B /* AssetManager.swift in Sources */, - 56143A9BB75D3B05B8254DB947DDFE03 /* BaseConfiguration.swift in Sources */, - 5C9D188782C95778B295C4F7DAD533FD /* BaseViewController.swift in Sources */, - 6FDC36915339B16F86D2319C68EF1A1E /* CameraConfiguration.swift in Sources */, - 2E2F7BE1C7A6BBA68DAD48C523D888DC /* CameraViewController.swift in Sources */, - 55D30D05A4C3776DA25A571A09CC0838 /* Core+Bundle.swift in Sources */, - BEC72EA390EBF57606126D2B8694CE66 /* Core+CALayer.swift in Sources */, - 62429E93624E786E3D912A362226477B /* Core+Data.swift in Sources */, - F0ECCB476E625BF8D0C1564F1BBB82FE /* Core+Dictionary.swift in Sources */, - 8D0484E61C49B3CCE8813F74FE24321D /* Core+DispatchQueue.swift in Sources */, - 9BB50D9DEC61DBE55023247658591290 /* Core+PHAsset.swift in Sources */, - 29590F1FFE753B7431DACA250E3B8D57 /* Core+PHAssetCollection.swift in Sources */, - 4593B3CEE4ABA9BC43E4D74C5BEEF7FC /* Core+String.swift in Sources */, - 5524F3DC0630E9DDAB2E1C9966DDA0B1 /* Core+UIColor.swift in Sources */, - 623765696268F7CA1EB22B7CD2E5F0E5 /* Core+UIDevice.swift in Sources */, - FDCB190E9998DB7926E592645867D01A /* Core+UIFont.swift in Sources */, - 3F0860723E69F242FAE43CEFA57B4EFC /* Core+UIImage.swift in Sources */, - 050A5ACCD0D3BE90FD570A7719CFAB3C /* Core+UIImageView.swift in Sources */, - F7DA6EFBB532EFEEBACD8DA001F463C8 /* Core+UIView.swift in Sources */, - ED9DFE874C96389F12E57FF354AEE096 /* Core+URL.swift in Sources */, - 90E11FBF49BCD3B7AEF6C38146817896 /* CropConfirmViewConfiguration.swift in Sources */, - 48326ACE15B73B3BCA0B4FAD506FB971 /* CustomLanguage.swift in Sources */, - 11C6FEEBE6CD821D27005CA24D3D1A99 /* DeniedAuthorizationView.swift in Sources */, - 752D5D109D6ED65AF100DFFE766AA42F /* Editor+PhotoTools.swift in Sources */, - 7AF6771DC3B6CED1CCB3190905EEFCA3 /* Editor+UIImage.swift in Sources */, - A1AEAFB890D9D43080CD9BC9B0400A3B /* Editor+UIImageView.swift in Sources */, - 8E84CC64780B1836225593EE471ECEDA /* EditorConfiguration.swift in Sources */, - 3299ACFF02931BB0B85CAB8D63351C9C /* EditorController.swift in Sources */, - DD3D33CF95D12F03D62901F82EDF6892 /* EditorCropConfirmView.swift in Sources */, - 86C07B02A1195143341C64EEE58A469E /* EditorImageResizerControlView.swift in Sources */, - 1D5BD0A8211247DFA5F45F497EE786ED /* EditorImageResizerMaskView.swift in Sources */, - 06003243D6F2B1B89B59629AD75231A8 /* EditorImageResizerView.swift in Sources */, - A73D0C131526B571A16DFC6AC36719E5 /* EditorToolOptions.swift in Sources */, - 119256589CFF0B98856EA6DBC18B566C /* EditorToolView.swift in Sources */, - 9B73B6FF0FB5382008A957BFA1B7E7B5 /* EditorToolViewCell.swift in Sources */, - 038966D6375558DF19856B155F48AB31 /* EditorToolViewConfiguration.swift in Sources */, - 01B738C1CAB2145CC6C45D95023DA2D9 /* EditorType.swift in Sources */, - 41847DEA614F7FCB9F1853AC6B404C2E /* EmptyView.swift in Sources */, - DE7B9075AE4019B159CF5ED8E3033145 /* EmptyViewConfiguration.swift in Sources */, - F9B0518B59217A1150BF204041629FCB /* GIFImageView.swift in Sources */, - F8E53C5DEEB48F76AD3E5196E4F0C8D2 /* HXPHPicker-dummy.m in Sources */, - 6B328D4292DF38990299F740187F37AF /* HXPHPicker.swift in Sources */, - A8B186222182CBB7F1366BDD4A3116A3 /* ImageContentType.swift in Sources */, - ECFC3E74616084F01177C3B063E03CFD /* LanguageType.swift in Sources */, - 7DD545680D729CFBA70B3A1AA6A57B2D /* LivePhotoError.swift in Sources */, - A4B51104D86C0966893651D23EE761B6 /* LocalAsset.swift in Sources */, - 9E330B945E4A187A39691B93498537ED /* NetworkAsset.swift in Sources */, - 4DCCA9E6EC1C9713C27DBC7E4684C551 /* NotAuthorizedConfiguration.swift in Sources */, - 269DFDEDD6FAF08A53D3F3160B2C1654 /* PhotoAsset+Network.swift in Sources */, - E762932881E044CB4875C358BC1247B3 /* PhotoAsset+Request.swift in Sources */, - C40330052161D5B1451616A0749F40EB /* PhotoAsset.swift in Sources */, - 698619BBABA2BD11360F34EEB88CA956 /* PhotoAssetCollection.swift in Sources */, - 77F039C0975017867D92A5D8965FE34F /* PhotoCroppingConfiguration.swift in Sources */, - 4B734407952D73B98E5C09223D8DAA10 /* PhotoEditorBrushColorView.swift in Sources */, - D3BEFA5551502BB15839DDC4DBB17DA6 /* PhotoEditorConfiguration.swift in Sources */, - C67A799566A361E17C1B001EB35830AC /* PhotoEditorContentView.swift in Sources */, - 0D2A946D1FB48ACE590D624B751E53F6 /* PhotoEditorCropToolModel.swift in Sources */, - B12C803CCE9A970706A690C2741F7F27 /* PhotoEditorCropToolView.swift in Sources */, - 00338F3D5F82E147543464AD98C7F1E2 /* PhotoEditorDrawView.swift in Sources */, - 8635594B8F55BED4205D34314E661FC0 /* PhotoEditorFilter.swift in Sources */, - 23A8196697B18BF780966632E503BEB3 /* PhotoEditorFilterView.swift in Sources */, - 798EE8946BA09D8EEA226D1D3E65B888 /* PhotoEditorMosaicToolView.swift in Sources */, - E7CC9880CD9ABA88C346E93A7AD7F232 /* PhotoEditorMosaicView.swift in Sources */, - 42FEC53E19FBBFAD2193F6A2CD970670 /* PhotoEditorView.swift in Sources */, - 54E8C14F831B4EB36766E8CD80B15897 /* PhotoEditorViewController+Animation.swift in Sources */, - 242ED845EE9F258D178093CFA03A199D /* PhotoEditorViewController+Export.swift in Sources */, - 23CB1CAF9617823EA2BC06204EA3DB37 /* PhotoEditorViewController+Request.swift in Sources */, - E9D17314462863455C45F8019C65CEDA /* PhotoEditorViewController.swift in Sources */, - AFBBE2117422FD49A7AFC14AEDFE217B /* PhotoEditResult.swift in Sources */, - DE982596DE1BF157C1D3E080D908F62E /* PhotoError.swift in Sources */, - 4A90DA3DF1A6ECF2C27EF0C826F24673 /* PhotoListCameraCellConfiguration.swift in Sources */, - 8A35C6B192FB212B16B72BCC9690915A /* PhotoListCellConfiguration.swift in Sources */, - 8ACA0761F20640E1EBEA4DC1FDD48EA7 /* PhotoListConfiguration.swift in Sources */, - AC2E403578F6DAA216520439630EF6D0 /* PhotoManager+Audio.swift in Sources */, - 0BA606564CF9D9788B71FE17B26EE2BA /* PhotoManager+Download.swift in Sources */, - 9074713D3EE739A9759A47516C3388D1 /* PhotoManager+Language.swift in Sources */, - E004165DAADCE810F7DB431BB2DAAC23 /* PhotoManager.swift in Sources */, - 73222682715748539925444A4CC4ED21 /* PhotoPanGestureRecognizer.swift in Sources */, - 76568D0A88C5A37CE292E25C21B2966B /* PhotoPickerBaseViewCell.swift in Sources */, - B57412E02A43D260681220B7CA512831 /* PhotoPickerBottomView.swift in Sources */, - 916846A7516CCA437809B19BA1A91F5B /* PhotoPickerController.swift in Sources */, - F6C0366EE9B0050741930370C48AE1AF /* PhotoPickerControllerProtocol.swift in Sources */, - D71A449EE428E83E0A9929F6298BFA4E /* PhotoPickerSelectableViewCell.swift in Sources */, - 5C276F9FAEEE34773972E39E23BC126C /* PhotoPickerViewCell.swift in Sources */, - 9491BD5BE854440690205764C55AA51A /* PhotoPickerViewController+SwipeSelect.swift in Sources */, - 0CCF4FACECA0A5EE2BA385AF3469C786 /* PhotoPickerViewController.swift in Sources */, - AAA4DEA8A44AB55FA2BD37687E2EFFB6 /* PhotoPreviewContentView.swift in Sources */, - 6DA4B82A9D02428F909B6A962380BC04 /* PhotoPreviewSelectedView.swift in Sources */, - 89388C9A40A7747C4BA50DE00390D086 /* PhotoPreviewSelectedViewCell.swift in Sources */, - F417FC09ADC8F8F0EBEC002FFF3C17F9 /* PhotoPreviewVideoView.swift in Sources */, - 425E8203EA327EB5A495E7F52306CA1B /* PhotoPreviewViewCell.swift in Sources */, - C4B37D549AD8E84B06B0EE2751B4A4AE /* PhotoPreviewViewController.swift in Sources */, - D4BE2BF268794034BC873C5697767581 /* PhotoTools+File.swift in Sources */, - E1CC3B4A5805D447A92D7098653F2A0C /* PhotoTools.swift in Sources */, - 8D8C4F46D776DAB6A3B71DBC71485902 /* Picker+PhotoAsset.swift in Sources */, - 5313F1D73BAA23C8DC8C3C155D0D1D38 /* Picker+PhotoManager.swift in Sources */, - B94506476A9DFD76DA50C057C96E7864 /* Picker+PhotoTools.swift in Sources */, - 311F503D66F657FE86397A5598083374 /* Picker+UIImageView.swift in Sources */, - D8735E1A0E2C163B658452A72C57CBD6 /* Picker+UIViewController.swift in Sources */, - 94B9629812E39F9549BB609CBF716848 /* PickerBottomViewConfiguration.swift in Sources */, - F248E3555B933BD707D77E0F41046DAD /* PickerCamerViewCell.swift in Sources */, - C3B8BB6A464123E12749E41C42CA7A68 /* PickerConfiguration.swift in Sources */, - 3503C7426CCD60FF0172CA645963527B /* PickerInteractiveTransition.swift in Sources */, - FE00FFA33CB3D9FF548FC57C9CFCBD9C /* PickerResult.swift in Sources */, - CE36694881ADED5E8545B2874709B00E /* PickerTransition.swift in Sources */, - B3C775AEB56C0373F519E5AC31495887 /* PickerTypes.swift in Sources */, - 49FCE13B20C3371630371C4F73D9F775 /* PreviewLivePhotoViewCell.swift in Sources */, - 3FD47105E23BDC6628AAF8932B153D15 /* PreviewPhotoViewCell.swift in Sources */, - 7C1072E1FBD4AD209EF77F2DDE97429D /* PreviewVideoControlViewCell.swift in Sources */, - C962F2A83A365AB35DC0A7ECC2E7B144 /* PreviewVideoViewCell.swift in Sources */, - 62576256D25669602C3CFC9153EAED1E /* PreviewViewConfiguration.swift in Sources */, - CC80FE337DD5E8F1C38B6758F81C0567 /* ProgressHUD.swift in Sources */, - A7F8C60F22227E0C42CF7A27EE4656EA /* ProgressImageView.swift in Sources */, - 5CA02BB2CE79B62B480DC7EED795CE29 /* SelectBoxConfiguration.swift in Sources */, - E1EA414B4CB5CAAADAEF1C11B8E7B559 /* SelectBoxView.swift in Sources */, - 19D2F029DA9C548BBF0A0DE4D8ADE39E /* VideoCroppingConfiguration.swift in Sources */, - B1B3C3D647A8DB3D67E961896C61F882 /* VideoEditorConfiguration.swift in Sources */, - A31A83BE603C9622763E0F2B1E0FE292 /* VideoEditorCropView.swift in Sources */, - 07E903EF2CE075711F0ABD6E120F2D4B /* VideoEditorCropViewCell.swift in Sources */, - 7773E7B6D510E7D021CD5FEBB3BB203B /* VideoEditorFrameMaskView.swift in Sources */, - 576116FCC35F47444B869BB6A8ED0B1E /* VideoEditorMusic.swift in Sources */, - EADD40946B12E7DC40E47134684B2AC2 /* VideoEditorMusicAnimationView.swift in Sources */, - EB669B6FD1E2DF2F4C8EC4D461D12928 /* VideoEditorMusicView.swift in Sources */, - ABAFCADF4B1F105DD5F8B478BF8FE299 /* VideoEditorPlayerView.swift in Sources */, - 099A7527DD851CF7B140A722500BED3B /* VideoEditorViewController.swift in Sources */, - 7212066203ADA297D7DCD78D55502CAA /* VideoEditResult.swift in Sources */, - 038F8395233DE0369D8A2BA07F35B6B4 /* VideoPlayerView.swift in Sources */, + 0C873B1DB4912ED36067ABA9848DC56F /* AlbumListConfiguration.swift in Sources */, + 7716A54E234B52A8B1390C028602BF01 /* AlbumTickView.swift in Sources */, + 1D61371A4CA7A1A0F4BFC6720E643373 /* AlbumTitleArrowView.swift in Sources */, + 9A5150B93A7AE324EDFB80D93B95D9D9 /* AlbumTitleView.swift in Sources */, + 7F5CAB06843CFC9E068820A2DC3D10F1 /* AlbumTitleViewConfiguration.swift in Sources */, + 611DA9D55BD6F6B60E240BD7015FE136 /* AlbumView.swift in Sources */, + 5E810323E7C7EBE90591637409BAD8C6 /* AlbumViewCell.swift in Sources */, + F2C882E6573E0C1322DBD1B40ABAF69A /* AlbumViewController.swift in Sources */, + 76D62CF6FC1488EC033801D21940AD21 /* AppearanceStyle.swift in Sources */, + FA4930BAAB6EE6731F2C29AFE16B6EB9 /* AssetManager+Asset.swift in Sources */, + 46C5A5B606303D1200C39860C3CF8C12 /* AssetManager+AssetCollection.swift in Sources */, + E5EFFF3D480415F61175DCB4EB5D30E6 /* AssetManager+Authorization.swift in Sources */, + 4FAC4E007D31FBBEDE104543F5504153 /* AssetManager+AVAsset.swift in Sources */, + A01E4A1EFF57C54F97858659F34904BB /* AssetManager+AVAssetExportSession.swift in Sources */, + B1D7F03D8BE5579DFF61754E0F8D1089 /* AssetManager+Image.swift in Sources */, + 4A8ABF437DBF2C8D3E065C2D49CF4E3E /* AssetManager+ImageData.swift in Sources */, + BFA21F8FC5B7359E415F295D3FC68895 /* AssetManager+ImageURL.swift in Sources */, + 735A5013A2EFAD2E792807C352119A8F /* AssetManager+LivePhoto.swift in Sources */, + BCD566578AF7490F2EA43136342FBF6B /* AssetManager+LivePhotoURL.swift in Sources */, + B2D56AA9B691AEDC91403E0D29EF5873 /* AssetManager+VideoURL.swift in Sources */, + D5B93E117475B4099A3F671B39C40A12 /* AssetManager.swift in Sources */, + 1B42946AAC11291D6EECF38EC980FA70 /* BaseConfiguration.swift in Sources */, + 998C8394F7B6A2A12A721A4296BCA31C /* BaseViewController.swift in Sources */, + DAF0DA7AEB8ADB78DB49460DFEF62EF6 /* CameraConfiguration.swift in Sources */, + 4C9788C77C25FF7A6198A52DC367BC6E /* CameraViewController.swift in Sources */, + D4753539AAA5FF82CC30B50B71497136 /* Core+Bundle.swift in Sources */, + F32B0F74239E13065E7F9110DDA94BC9 /* Core+CALayer.swift in Sources */, + 8648DD1D27BD991CDA555CC605959080 /* Core+Data.swift in Sources */, + 26AEA7767936D23BB69B66F8B802211F /* Core+Dictionary.swift in Sources */, + 81645640A5520231D6E141B11DC71CE1 /* Core+DispatchQueue.swift in Sources */, + 5088AA1470ED6896BF2F1C5C55817247 /* Core+PHAsset.swift in Sources */, + A02F8A13DF9C8952A32C5CBFF4C0E866 /* Core+PHAssetCollection.swift in Sources */, + 1FE1EF5A4CD3B435194947FAE0256F0D /* Core+String.swift in Sources */, + 597E75C47B63A0B5AE12EBFD0E4115E1 /* Core+UIColor.swift in Sources */, + 07FF52EDCE463651E87750F9CB3D7D6D /* Core+UIDevice.swift in Sources */, + BA05DBB552919B860B50815C40A74274 /* Core+UIFont.swift in Sources */, + 8A9AFCA8F716CA06BFB885F9C99E82F2 /* Core+UIImage.swift in Sources */, + 5E3B62C5B99C91608C8385668BC12956 /* Core+UIImageView.swift in Sources */, + 21891499532DFFDF5935C58274F45785 /* Core+UIView.swift in Sources */, + 5250ED6D85FC2A26C30DBA2A4670F841 /* Core+URL.swift in Sources */, + B0DC1E39940C7486F0D596443E8061F7 /* CropConfirmViewConfiguration.swift in Sources */, + A5CE440D715C784A74BEBB5C7AFB3DE2 /* CustomLanguage.swift in Sources */, + E249472D07E2AABB662E011A881F3EF4 /* DeniedAuthorizationView.swift in Sources */, + 460D87AC137DFFD50C2FC22A8BA3A455 /* Editor+PhotoTools.swift in Sources */, + A39F1855BE4B33A5FB3E7D3C138A6326 /* Editor+UIImage.swift in Sources */, + 6E756B256C47C1C5562D0DE860B7D599 /* Editor+UIImageView.swift in Sources */, + 1329C2F3309BB9F7C69E94ED8401D3F0 /* EditorChartlet.swift in Sources */, + 52D86762420BEC903909A5A7CB993033 /* EditorChartletView.swift in Sources */, + 95C5D3C281663A8A34B49D39519F9AC4 /* EditorConfiguration.swift in Sources */, + 4EAEB61C036B7E6C822EFBAB88FDF772 /* EditorController.swift in Sources */, + 68F74C6EE8516D5FCDA949457C85DB35 /* EditorCropConfirmView.swift in Sources */, + 3426E91F4DF25D553C3D8AFA85D0D7E0 /* EditorImageResizerControlView.swift in Sources */, + 84F2219C0F7FACB75AD2B81DEF9768B4 /* EditorImageResizerMaskView.swift in Sources */, + A493E1475E7FBCA4FE3E36712F4EC3D0 /* EditorImageResizerView.swift in Sources */, + 0FDDD131B4E3A69256610F98D3CA35E9 /* EditorStickerContentView.swift in Sources */, + 9D9E6F0413FA459195D0114BB059D721 /* EditorStickerItemView.swift in Sources */, + 32C2F93851943589D3871EFDE3DCA445 /* EditorStickerTextView.swift in Sources */, + CCAD386E55B5A4D7F3C4BAB512CE564B /* EditorStickerTextViewController.swift in Sources */, + 97781F95C4B7FCD9A6B1B623EF70477E /* EditorStickerTrashView.swift in Sources */, + 1587B6C55E51FC011FA32271827825E9 /* EditorStickerView.swift in Sources */, + D56F4F1E6A1B5FB1C4CB93971D0E8EAD /* EditorToolOptions.swift in Sources */, + 5133EC52E4877176301FC6B4C2334A09 /* EditorToolView.swift in Sources */, + 68B1720972180974525033A5907A529D /* EditorToolViewCell.swift in Sources */, + B15D2E8B1EBBFC7CD654E2EE999F857F /* EditorToolViewConfiguration.swift in Sources */, + 6FE901ADBFE3CBB72150D18A9A8D08D1 /* EditorType.swift in Sources */, + 23EA95889A46324844633D170B69C659 /* EmptyView.swift in Sources */, + 8C21DFAE814D3D8525280708E39CBE5B /* EmptyViewConfiguration.swift in Sources */, + 797E1FC177B7F803F8F542F5D0202823 /* GIFImageView.swift in Sources */, + 3FB494D26807423F35FCA1F0A990BC96 /* HXPHPicker-dummy.m in Sources */, + AADCCFAD443D97C1F033E15AED37FE5F /* HXPHPicker.swift in Sources */, + 4FFD67E51C0800E739383F4A42E922DC /* ImageContentType.swift in Sources */, + 380404B9538385ECFB95BE60462EDEF2 /* LanguageType.swift in Sources */, + 984FF16C92999E5E3F1B30B9518FFAC4 /* LivePhotoError.swift in Sources */, + 6C103EA8E1110938A48C5B733704D08A /* LocalAsset.swift in Sources */, + 609456BCB1A76E23B178D2A0C513BBB6 /* NetworkAsset.swift in Sources */, + 7EFDC706CC94DCA239557D732B5AB10A /* NotAuthorizedConfiguration.swift in Sources */, + CD6FE7C22133F548ED833A2F5187F771 /* PhotoAsset+Codable.swift in Sources */, + D8EB3FC1D33F8B83D72FCC30FFBFA074 /* PhotoAsset+Network.swift in Sources */, + 22F0C76165005CA8E322DDF2342B64BE /* PhotoAsset+Request.swift in Sources */, + D0AD2A4EA83479DCA89D922A78EF9E41 /* PhotoAsset+URL.swift in Sources */, + 33604909CF38A6F79153447A3CCEAA72 /* PhotoAsset.swift in Sources */, + 5FC9E13E4BE61D9C6604029F33E8DEB5 /* PhotoAssetCollection.swift in Sources */, + D34EDE04C16DF0F63D25FF04BE074943 /* PhotoCroppingConfiguration.swift in Sources */, + F149395CE971F301575135C68E3494BD /* PhotoEditorBrushColorView.swift in Sources */, + BBD5D0BBBD0B5B7643E342E494F663B2 /* PhotoEditorConfiguration.swift in Sources */, + 96A8E934DCBB01D8C01D52F284CB8A6A /* PhotoEditorContentView.swift in Sources */, + 93368B7B05E3A813F2BD10396B8A66AB /* PhotoEditorCropToolModel.swift in Sources */, + 549802C464729955C5FED1332381DA1E /* PhotoEditorCropToolView.swift in Sources */, + DDFFAFE5E71D9227AB7DEC1FDC2D4A77 /* PhotoEditorDrawView.swift in Sources */, + FA69C49C73EB1F4F68FB6BC5B5465CA6 /* PhotoEditorFilter.swift in Sources */, + 295479D14EC2EB13C7FB5F1503994C40 /* PhotoEditorFilterView.swift in Sources */, + A3425538BB4D35127BEAB4E4345F3BD4 /* PhotoEditorMosaicToolView.swift in Sources */, + 1D45BD4E40C57EDF5DB30981F5681790 /* PhotoEditorMosaicView.swift in Sources */, + 5E4C61C32C2CC97C94F8D436A4CD77AC /* PhotoEditorView.swift in Sources */, + 8D545B568D65C54C7B7D61DD04255637 /* PhotoEditorViewController+Animation.swift in Sources */, + F30146D4EBB6AE3194F16C8F8D337CF2 /* PhotoEditorViewController+Export.swift in Sources */, + 93E69810EE11007048B9D1E26456083D /* PhotoEditorViewController+Request.swift in Sources */, + 6A30F45A3EA2950E78B392E34F4F033C /* PhotoEditorViewController.swift in Sources */, + CF7C19428C8AA00EF5E46953962CD748 /* PhotoEditResult.swift in Sources */, + DB5E17E749AB87855A28F0077FCD5D79 /* PhotoError.swift in Sources */, + DDAD04ECFE1D8DF97690828F849B0DA9 /* PhotoListCameraCellConfiguration.swift in Sources */, + 803C8CE75562090DAE5D7A4CA40E1074 /* PhotoListCellConfiguration.swift in Sources */, + D202DE78FF054C75156FAED3E052DD40 /* PhotoListConfiguration.swift in Sources */, + 6E189CAE53DA9E4F644B7FD70E0EDA1C /* PhotoManager+Audio.swift in Sources */, + D2589DDA1844AEC2442ADEEF1D260FAC /* PhotoManager+Download.swift in Sources */, + 0419619E78C7AA0A03F5F18024F7C182 /* PhotoManager+Language.swift in Sources */, + 08ECFAD1A0CE52199F186F7D8D0947E4 /* PhotoManager.swift in Sources */, + F96EC1388FD22C566A553A5F804FDA7C /* PhotoPanGestureRecognizer.swift in Sources */, + 3E0CD1623DBC41F1E64C3314B545CCBB /* PhotoPickerBaseViewCell.swift in Sources */, + FC751005943A9ED4A90FDF00AF907CFD /* PhotoPickerBottomView.swift in Sources */, + 0BA99B841A76DD1D8076BFB57CC88A89 /* PhotoPickerController.swift in Sources */, + 8C8BDFF216DE12E1D1F6CEE8F74B1E2A /* PhotoPickerControllerProtocol.swift in Sources */, + E537966080A9114A6DE2B4C856BE6339 /* PhotoPickerSelectableViewCell.swift in Sources */, + CFD908027CF25361E3C6B9E8CCE2CEA2 /* PhotoPickerViewCell.swift in Sources */, + C5466E46FC92A6C76FF8BBEFA9B4101B /* PhotoPickerViewController+SwipeSelect.swift in Sources */, + 139D486A1CF941D45083C9C37DB5F155 /* PhotoPickerViewController.swift in Sources */, + 178647C0E3B21871FE0EF850BEF6EE7A /* PhotoPreviewContentView.swift in Sources */, + 17E49A0562A5F422B556E6D0EF9869EB /* PhotoPreviewSelectedView.swift in Sources */, + 43880AA089E44A66789645EC7DF6B0D6 /* PhotoPreviewSelectedViewCell.swift in Sources */, + F4A42CB969434AD5125AF3243D704561 /* PhotoPreviewVideoView.swift in Sources */, + 3876CA6A7E7ABEE8BA4884AE71B26A89 /* PhotoPreviewViewCell.swift in Sources */, + D6FB5258A326AB85E346F5720EA478C6 /* PhotoPreviewViewController.swift in Sources */, + 55AFABF00C90B571211832EBCE00A180 /* PhotoTools+File.swift in Sources */, + 0B6E1F59E3F71B1219E43E78231C0C6A /* PhotoTools.swift in Sources */, + DABA772FDB25ABCF98234C1D56D4A8B6 /* Picker+PhotoAsset.swift in Sources */, + 7807D90D3A02C723B01A456BB724294E /* Picker+PhotoManager.swift in Sources */, + 787AA8408D4903F5615E7FD305C08512 /* Picker+PhotoTools.swift in Sources */, + 781EAB655CA305D4D2462870A8C78CD3 /* Picker+UIImageView.swift in Sources */, + 17A6A1E624415423B39E369F085020EF /* Picker+UIViewController.swift in Sources */, + 93CECEEE40B49CA8E8646BE918495D42 /* PickerBottomViewConfiguration.swift in Sources */, + FA93C2DDDBA1D920B5245811377F7919 /* PickerCamerViewCell.swift in Sources */, + 27FBC4B3C209118DD51E7CB6042270B3 /* PickerConfiguration.swift in Sources */, + 53BF6E1EC42A9598A185AB0AA1494319 /* PickerInteractiveTransition.swift in Sources */, + 3FD784B7FD9790C5F0EB31FEFE32E308 /* PickerResult.swift in Sources */, + 2CB03D5CC83D6C5FDBB0C6F50BB3741A /* PickerTransition.swift in Sources */, + 838217014E56CBF64E6BCF795277C17C /* PickerTypes.swift in Sources */, + D1182ED1DCFD17A68B2CCF423DC166BF /* PreviewLivePhotoViewCell.swift in Sources */, + A9899A068ECD5F3810E6998D3DD415E7 /* PreviewPhotoViewCell.swift in Sources */, + 36F89D0EB2D3F90EC90FB365B7C1312E /* PreviewVideoControlViewCell.swift in Sources */, + E0D63DDD15325F164E480E0914DC2A41 /* PreviewVideoViewCell.swift in Sources */, + 77C8BF6BAD39835741B60C86DDA0BE0D /* PreviewViewConfiguration.swift in Sources */, + DDC4CEDA780C14B21BBC8CC68FBAC6AE /* ProgressHUD.swift in Sources */, + AEC3E6D8E32C26A9DB9AEF427D3425D6 /* ProgressImageView.swift in Sources */, + 105CCB2F2F2B7449F62A5E2D136D9B72 /* SelectBoxConfiguration.swift in Sources */, + EC21BCE9E4A66E579EC78AEA6EF67CD7 /* SelectBoxView.swift in Sources */, + 020EA4A55E4A5EB7ADA799CD1D5AE25E /* VideoCroppingConfiguration.swift in Sources */, + 7759E111BF0FD9A58A76433F9B910F94 /* VideoEditorConfiguration.swift in Sources */, + F72FD70375CBD5A1088AE8EEFA44CBE5 /* VideoEditorCropView.swift in Sources */, + 63EB3DB2B07E78D0D2696E829D2EE89C /* VideoEditorCropViewCell.swift in Sources */, + 7C481630D02964F4A44DDC2647358D17 /* VideoEditorFrameMaskView.swift in Sources */, + 36568CEF9C3DAEDDEE32A5AC99845D81 /* VideoEditorMusic.swift in Sources */, + 9B2BED9A1B5B19576030784EBD528FDD /* VideoEditorMusicAnimationView.swift in Sources */, + 23EAE9B74639B5F473D411B812209423 /* VideoEditorMusicView.swift in Sources */, + 162A9F7C4B470B9536271B0D3E799BFB /* VideoEditorPlayerView.swift in Sources */, + 07A0915E70AD7F2B1637ED67255BC7BA /* VideoEditorSearchMusicView.swift in Sources */, + 4FDE368B5194C5D6FC3FC29CDC8330D8 /* VideoEditorViewController.swift in Sources */, + EE581CD359FA4922D80C330DE28430A5 /* VideoEditResult.swift in Sources */, + 40F945E01879132C571D71E78C345D79 /* VideoPlayerView.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 8444FCF2951DEB16362C03E8FEAA7B0F /* Sources */ = { + B31233D44EAA9B03D4822661CF303018 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - AADC8491F654A9998E5E2614DB583C61 /* AnimatedImageView.swift in Sources */, - 7AC76880EB6A35B97D831A3164A1294D /* AuthenticationChallengeResponsable.swift in Sources */, - 8043324938E91735769B23B4CCA44F77 /* AVAssetImageDataProvider.swift in Sources */, - B0F1C8C1EFCB027EF51F1C90C04A2800 /* Box.swift in Sources */, - 9AB7F1490108CD7240E4D0C4B74F6741 /* CacheSerializer.swift in Sources */, - B0B200F35509242200121DFD8A71A160 /* CallbackQueue.swift in Sources */, - 0443E6EBDAA758C06C04199187F7CA55 /* Delegate.swift in Sources */, - 636D7AF27C42F3F71B4763C2FFA127D8 /* DiskStorage.swift in Sources */, - 5DB4AD89AD4EBECE158AEB87F084547A /* ExtensionHelpers.swift in Sources */, - 316E7A0A8EF75D05D535388D84C7B98A /* Filter.swift in Sources */, - 8BE0629C8F06A5E546E9A0F5A7D2A492 /* FormatIndicatedCacheSerializer.swift in Sources */, - 2A73A7F0B740ABD90B7A825307FAD9E4 /* GIFAnimatedImage.swift in Sources */, - AE05DC1B821550CE78ADF28ABBBA56BC /* GraphicsContext.swift in Sources */, - EBE837C954B7DCC9854B611DB98B38B7 /* Image.swift in Sources */, - 8149F4FE1363F453890D381A8A473737 /* ImageBinder.swift in Sources */, - 005C63FED0B832EFA98EF8CE64BB24FA /* ImageCache.swift in Sources */, - D3504C0066F7E032A4241F9D08EB1191 /* ImageDataProcessor.swift in Sources */, - 29917F619F40E9F8AD6168DE49C6928C /* ImageDataProvider.swift in Sources */, - D14F97AC47A554CC340E97F5EA2870D0 /* ImageDownloader.swift in Sources */, - 715A9D29EB414F1672871AA05928E7BA /* ImageDownloaderDelegate.swift in Sources */, - 052A6FDA74DB688EADBC5EAFC57C0587 /* ImageDrawing.swift in Sources */, - 1E14073745A1038B091A0D7E6004A940 /* ImageFormat.swift in Sources */, - BF2201896CF1479700394E989F728F4A /* ImageModifier.swift in Sources */, - B280C949DDF9D549731AF1C598CCF9F1 /* ImagePrefetcher.swift in Sources */, - 27BFCC56B874A93E895B41B13A2C55F8 /* ImageProcessor.swift in Sources */, - 4AC5D58C33BB3A6CF79E8324B4A613AD /* ImageProgressive.swift in Sources */, - 8CAC5FC27179F135AF242D41132C9EEE /* ImageTransition.swift in Sources */, - 9B395164BC3C685D33B3D75CAB3CAB53 /* ImageView+Kingfisher.swift in Sources */, - E2ABD61C4DD752D58BFA8935294D5FD4 /* Indicator.swift in Sources */, - E00EBD8D05FAEF43E0A635EB513963C1 /* KF.swift in Sources */, - 9E2915E7A13B7C54F557BBCA31D68172 /* KFImage.swift in Sources */, - 227D3540141EE2A6C4626CC945E22DD6 /* KFImageOptions.swift in Sources */, - 0A42EC0D57457C873B3EA264EDD1A65E /* KFOptionsSetter.swift in Sources */, - AED2FEC0F5BFADFB2505CF5B6FE4E0B2 /* Kingfisher-dummy.m in Sources */, - 5C524FF251AD7DE63C583009E78D4475 /* Kingfisher.swift in Sources */, - 842322EE64A7B5EBF89F89332877B817 /* KingfisherError.swift in Sources */, - E64DD7C71134EA792E31F82618B1DB8A /* KingfisherManager.swift in Sources */, - 11A94BB931C8EB4C5F5D364348FDFC40 /* KingfisherOptionsInfo.swift in Sources */, - 590C93F4CCB66C4BB4DC87D09C8C018C /* MemoryStorage.swift in Sources */, - 3157CFBD2D898E8D3D0071024F317DDE /* NSButton+Kingfisher.swift in Sources */, - 45CA29CCB33E113557A6394BE832E145 /* NSTextAttachment+Kingfisher.swift in Sources */, - 05584212F6F2C514D72746FF8B3A331C /* Placeholder.swift in Sources */, - BAB4B5F0F708D8D7A77D65A689F10833 /* RedirectHandler.swift in Sources */, - C009A9CCD79C1C930FCC296B393D8B84 /* RequestModifier.swift in Sources */, - 1C990327AA693C5BAEC2BE121A6F4B6E /* Resource.swift in Sources */, - CFECA6FD0CBE4C2600A054B56342820B /* Result.swift in Sources */, - B5452D06EA8F0FA2B76F4CA5851BD3E0 /* RetryStrategy.swift in Sources */, - 6A95A41A81D05388EDEBB975679874A9 /* Runtime.swift in Sources */, - E97E9A295FE2AE93CBC73A5469390FEF /* SessionDataTask.swift in Sources */, - 703B1B250D62A703F19184829B499696 /* SessionDelegate.swift in Sources */, - 0C5314C5297A558D653F4F2D5EF23F58 /* SizeExtensions.swift in Sources */, - 5134D0BC6B8D169393447A1E0DF30260 /* Source.swift in Sources */, - 994F4E5ADA2D6713741B8F8E02189DF8 /* Storage.swift in Sources */, - 64B8B02A00316C4949CFD39833D283D7 /* String+MD5.swift in Sources */, - 2C30C162FC0BF1C9F940CCECFC1D6561 /* TVMonogramView+Kingfisher.swift in Sources */, - 55AECF7637265A5ED8B04A8F7A58D385 /* UIButton+Kingfisher.swift in Sources */, - CC9BB4E0DB2A96D433EF2D9C558BA694 /* WKInterfaceImage+Kingfisher.swift in Sources */, + 9579D82AE68CC88199FB637E4E662067 /* AnimatedImageView.swift in Sources */, + 5B50F271B7B4D1AD5E9DB4F701ABE32C /* AuthenticationChallengeResponsable.swift in Sources */, + 8B113234FB4A866B9F70D076FFFD3AEA /* AVAssetImageDataProvider.swift in Sources */, + 3B239997D3D87C1DE23EDE2CE6E1EDCA /* Box.swift in Sources */, + B2E52DA137487D10E4D41B8EA2D6839D /* CacheSerializer.swift in Sources */, + D8924C0DA4F8782C016B0EFE494528A5 /* CallbackQueue.swift in Sources */, + E18A42D3B7EEE940FCE6FBFF185EDD0C /* Delegate.swift in Sources */, + 57E8D4367B9289D6280CA613C958FCDE /* DiskStorage.swift in Sources */, + 7544DD93AED9DCD354E9AEE6D9BEE305 /* ExtensionHelpers.swift in Sources */, + 869AF52FE033B5E15C1AF6C6F1CF98F8 /* Filter.swift in Sources */, + DEDADC0D1E2A6CDBED553833F39706D9 /* FormatIndicatedCacheSerializer.swift in Sources */, + 7C50D92E8C8C88C9DD2CF1BF52EA9A76 /* GIFAnimatedImage.swift in Sources */, + B6D60155FC9171F171BDD35D6FFE0430 /* GraphicsContext.swift in Sources */, + 3553408BBB85CC5114B36012B6DF97C3 /* Image.swift in Sources */, + 74B6343C976E88AD7383A63E3DB75647 /* ImageBinder.swift in Sources */, + C0A433620EC92C6C1F2773EF0ADA14C1 /* ImageCache.swift in Sources */, + 9FC6E2CB0A0042958753D6227619ED18 /* ImageDataProcessor.swift in Sources */, + F6CB4D27C12C2592C33AA58DAD4AB2DC /* ImageDataProvider.swift in Sources */, + 4B110EE96D701ABA0AA09D9EFA6106A0 /* ImageDownloader.swift in Sources */, + CD49E913230C9E39E1FB4B3F0924958A /* ImageDownloaderDelegate.swift in Sources */, + E4A8B7A0770BE36D5960BFB5190A6FD5 /* ImageDrawing.swift in Sources */, + C1081D7D2DAFB981699C3FA4445901ED /* ImageFormat.swift in Sources */, + CE73AA7A30E9E144590EB8E4345E760E /* ImageModifier.swift in Sources */, + F16D355B01822A074FFCE4977785DEF6 /* ImagePrefetcher.swift in Sources */, + 7ED480945ED8DA17DBCEAF75DCA0ADA8 /* ImageProcessor.swift in Sources */, + 2633CDECE715E52AD3000C043AA2A1BF /* ImageProgressive.swift in Sources */, + 7A6270C6161816A37F4FF264D73D0EE6 /* ImageTransition.swift in Sources */, + EE399BAFD9CD394E74CB51297DF5617B /* ImageView+Kingfisher.swift in Sources */, + 3B0B1E849C333D90BD1EE7CFC922D3BC /* Indicator.swift in Sources */, + 3FB1C2B6A500E1A1DDE5813482159AC2 /* KF.swift in Sources */, + F3F5A6B066F57F049F49FAB3BDEA82C7 /* KFImage.swift in Sources */, + 24D7330EDBCC0F09B9495782948C9B3C /* KFImageOptions.swift in Sources */, + 37C8BB1D62DF96866B6E452C1076D875 /* KFOptionsSetter.swift in Sources */, + 79FC96B7255860AC96F7673DE7318251 /* Kingfisher-dummy.m in Sources */, + D9E974B9341636BC643C7A8DA173B120 /* Kingfisher.swift in Sources */, + A3BB637A1C697DDD25AE12A979726B8B /* KingfisherError.swift in Sources */, + E90A1A2ACF3F9A80EE087E408A8FDFD4 /* KingfisherManager.swift in Sources */, + 45518BEA82699257CE99C6ACC3A1EB33 /* KingfisherOptionsInfo.swift in Sources */, + 814430C0EE52BD375FF69CC51AA9FEB8 /* MemoryStorage.swift in Sources */, + 1A4EF2979C7AF1FB6F6F6051C3514249 /* NSButton+Kingfisher.swift in Sources */, + C158FFC0DEC9C12B72793335DF68C42C /* NSTextAttachment+Kingfisher.swift in Sources */, + 0E867F4AB19E3B1B1D0F7F45655A2654 /* Placeholder.swift in Sources */, + 088650FE877F96F652722927980C7915 /* RedirectHandler.swift in Sources */, + 974D213654CF414053144CDEB7006DE2 /* RequestModifier.swift in Sources */, + 3E89A7D00E0A4EEB0C6C1D85610F911A /* Resource.swift in Sources */, + 854E8DBC96B7C04F1EDE6F82634EBD6C /* Result.swift in Sources */, + 72E79BD62EC20C38EFDE3773A996C635 /* RetryStrategy.swift in Sources */, + 9B619D7E216337541D6C09858484FD4D /* Runtime.swift in Sources */, + 54643F5F61A6799C89CA19F74199A548 /* SessionDataTask.swift in Sources */, + 1E8743A6E1873A64675E3E53A2FEB4E6 /* SessionDelegate.swift in Sources */, + 8967B1298688386541ADCBED7217CDBC /* SizeExtensions.swift in Sources */, + FA4701AE677FFCB8DDF44E46331E0913 /* Source.swift in Sources */, + 62EA2F1B8672A809B46FA95BF9B5C91B /* Storage.swift in Sources */, + 7BFDCB0AB3C6228163454A0122A67BD6 /* String+MD5.swift in Sources */, + 60E3D7BBC4AB90661AEF25C2651E7698 /* TVMonogramView+Kingfisher.swift in Sources */, + 03D167F5E85EF78ECE38AF54B6673A80 /* UIButton+Kingfisher.swift in Sources */, + A8E7B90F6A6F1E48394B35740B3CCC4B /* WKInterfaceImage+Kingfisher.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - 6BED7F9EB43CA0985013A6B76DD80D8F /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = HXPHPicker; - target = 6968C202A297A606D5EACC3679AAA627 /* HXPHPicker */; - targetProxy = FFDE80358A828037A3CB14CF9745101F /* PBXContainerItemProxy */; - }; - 9496A921918523D53DEC196FB564BB0C /* PBXTargetDependency */ = { + 9384A8B4B11CE8EB86E64A0B42B68221 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = Kingfisher; target = E8022D22FAA6690B5E1C379C1BCE1491 /* Kingfisher */; - targetProxy = BCD11FB170E6E354D421104B062684C6 /* PBXContainerItemProxy */; + targetProxy = 6887B6F8A5CF3390C190DF5F4BF6A879 /* PBXContainerItemProxy */; }; - B4EF0961C34535A7067898ACBFA3D8EA /* PBXTargetDependency */ = { + D47198A142B342C7070C96EF96BAAC6F /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = Kingfisher; target = E8022D22FAA6690B5E1C379C1BCE1491 /* Kingfisher */; - targetProxy = 4533786AF807E09F4FACF612EA5DF52C /* PBXContainerItemProxy */; + targetProxy = D084644B558FCD5B70A92660C3FE85F1 /* PBXContainerItemProxy */; + }; + F7FC8585F12118A18996FE831F35E03D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = HXPHPicker; + target = 6968C202A297A606D5EACC3679AAA627 /* HXPHPicker */; + targetProxy = E75270767A6FEC60E6DD3F56A81217AA /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ - 18E7F97392C9BA3685A879784802E00D /* Release */ = { + 08C76892B21ACD76EF753DC99A0E1313 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = A312E415AD86071831D098106E1785B9 /* Pods-HXPHPickerExample.release.xcconfig */; + baseConfigurationReference = DC6C3EA333162630333FF31E76CDBD0A /* Kingfisher.release.xcconfig */; buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; CLANG_ENABLE_OBJC_WEAK = NO; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; @@ -1353,19 +1396,18 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "Target Support Files/Pods-HXPHPickerExample/Pods-HXPHPickerExample-Info.plist"; + GCC_PREFIX_HEADER = "Target Support Files/Kingfisher/Kingfisher-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/Kingfisher/Kingfisher-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 10.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-HXPHPickerExample/Pods-HXPHPickerExample.modulemap"; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PODS_ROOT = "$(SRCROOT)"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; - PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + MODULEMAP_FILE = "Target Support Files/Kingfisher/Kingfisher.modulemap"; + PRODUCT_MODULE_NAME = Kingfisher; + PRODUCT_NAME = Kingfisher; SDKROOT = iphoneos; SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; @@ -1373,9 +1415,9 @@ }; name = Release; }; - 3FE860561442B35C4A5D0C906E8C7491 /* Release */ = { + 135D0BA1D0172FE80A25414014F8BD2C /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 2D1CB169A7364BBE20552451BB7BCCFD /* HXPHPicker.release.xcconfig */; + baseConfigurationReference = 333194D5139911F72790CE8255D676D2 /* HXPHPicker.release.xcconfig */; buildSettings = { CLANG_ENABLE_OBJC_WEAK = NO; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; @@ -1404,10 +1446,11 @@ }; name = Release; }; - 5FA562A12F011B12F63CA6EC59DF056E /* Release */ = { + 18E7F97392C9BA3685A879784802E00D /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = DC6C3EA333162630333FF31E76CDBD0A /* Kingfisher.release.xcconfig */; + baseConfigurationReference = A312E415AD86071831D098106E1785B9 /* Pods-HXPHPickerExample.release.xcconfig */; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; CLANG_ENABLE_OBJC_WEAK = NO; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; @@ -1417,18 +1460,19 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/Kingfisher/Kingfisher-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/Kingfisher/Kingfisher-Info.plist"; + INFOPLIST_FILE = "Target Support Files/Pods-HXPHPickerExample/Pods-HXPHPickerExample-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 10.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/Kingfisher/Kingfisher.modulemap"; - PRODUCT_MODULE_NAME = Kingfisher; - PRODUCT_NAME = Kingfisher; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-HXPHPickerExample/Pods-HXPHPickerExample.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SDKROOT = iphoneos; SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; - SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; @@ -1436,36 +1480,6 @@ }; name = Release; }; - 657223C113BA1FE01E876ABADFF1DEC0 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 444030316457F4B1626AA794BBFBD0D7 /* HXPHPicker.debug.xcconfig */; - buildSettings = { - CLANG_ENABLE_OBJC_WEAK = NO; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/HXPHPicker/HXPHPicker-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/HXPHPicker/HXPHPicker-Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/HXPHPicker/HXPHPicker.modulemap"; - PRODUCT_MODULE_NAME = HXPHPicker; - PRODUCT_NAME = HXPHPicker; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_VERSION = 5.3; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Debug; - }; 6D42DC62C4F2E194221DF89C48496C98 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { @@ -1528,9 +1542,9 @@ }; name = Release; }; - 80FB31C7B8B5C3A6963AF0308AAEB879 /* Debug */ = { + 8A7C8D1987F212C0F70794767B5DD6A3 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 79121B0A0E9C0D3A4DEB45D687917CB6 /* Kingfisher.debug.xcconfig */; + baseConfigurationReference = DF30C43C9CEC6FD791CA87DE084631BD /* HXPHPicker.debug.xcconfig */; buildSettings = { CLANG_ENABLE_OBJC_WEAK = NO; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; @@ -1541,18 +1555,17 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/Kingfisher/Kingfisher-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/Kingfisher/Kingfisher-Info.plist"; + GCC_PREFIX_HEADER = "Target Support Files/HXPHPicker/HXPHPicker-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/HXPHPicker/HXPHPicker-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 10.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/Kingfisher/Kingfisher.modulemap"; - PRODUCT_MODULE_NAME = Kingfisher; - PRODUCT_NAME = Kingfisher; + MODULEMAP_FILE = "Target Support Files/HXPHPicker/HXPHPicker.modulemap"; + PRODUCT_MODULE_NAME = HXPHPicker; + PRODUCT_NAME = HXPHPicker; SDKROOT = iphoneos; SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; - SWIFT_VERSION = 5.0; + SWIFT_VERSION = 5.3; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; @@ -1658,6 +1671,37 @@ }; name = Debug; }; + E644EA62D1AA430BCB44D1F94309E342 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 79121B0A0E9C0D3A4DEB45D687917CB6 /* Kingfisher.debug.xcconfig */; + buildSettings = { + CLANG_ENABLE_OBJC_WEAK = NO; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/Kingfisher/Kingfisher-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/Kingfisher/Kingfisher-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/Kingfisher/Kingfisher.modulemap"; + PRODUCT_MODULE_NAME = Kingfisher; + PRODUCT_NAME = Kingfisher; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; E69B514E4C9B310D5677572459F3B3DA /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 96EFAC1F171F3535F93EF217583FAF1A /* Pods-HXPhotoPickerExample.debug.xcconfig */; @@ -1704,38 +1748,38 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 2008B28C7E39B3A1B49B079FB51B4D24 /* Build configuration list for PBXNativeTarget "Pods-HXPHPickerExample" */ = { + 061001F00128D631CC242AABFF6E3E78 /* Build configuration list for PBXNativeTarget "Kingfisher" */ = { isa = XCConfigurationList; buildConfigurations = ( - D1FF9DDDB513F222824E2C58F824C4B1 /* Debug */, - 18E7F97392C9BA3685A879784802E00D /* Release */, + E644EA62D1AA430BCB44D1F94309E342 /* Debug */, + 08C76892B21ACD76EF753DC99A0E1313 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */ = { + 092BA46F51227E0BD4B5EA8343E380AA /* Build configuration list for PBXNativeTarget "HXPHPicker" */ = { isa = XCConfigurationList; buildConfigurations = ( - E4D0D44B090D4284607EBBC4E71A96C1 /* Debug */, - 6D42DC62C4F2E194221DF89C48496C98 /* Release */, + 8A7C8D1987F212C0F70794767B5DD6A3 /* Debug */, + 135D0BA1D0172FE80A25414014F8BD2C /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 5731C3B6B9581B1FD1B561BD4DBC53D0 /* Build configuration list for PBXNativeTarget "HXPHPicker" */ = { + 2008B28C7E39B3A1B49B079FB51B4D24 /* Build configuration list for PBXNativeTarget "Pods-HXPHPickerExample" */ = { isa = XCConfigurationList; buildConfigurations = ( - 657223C113BA1FE01E876ABADFF1DEC0 /* Debug */, - 3FE860561442B35C4A5D0C906E8C7491 /* Release */, + D1FF9DDDB513F222824E2C58F824C4B1 /* Debug */, + 18E7F97392C9BA3685A879784802E00D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 5F86390500197AE0F0D00FAA79B2C2DE /* Build configuration list for PBXNativeTarget "Kingfisher" */ = { + 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */ = { isa = XCConfigurationList; buildConfigurations = ( - 80FB31C7B8B5C3A6963AF0308AAEB879 /* Debug */, - 5FA562A12F011B12F63CA6EC59DF056E /* Release */, + E4D0D44B090D4284607EBBC4E71A96C1 /* Debug */, + 6D42DC62C4F2E194221DF89C48496C98 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; diff --git a/Pods/Target Support Files/HXPHPicker/HXPHPicker-Info.plist b/Pods/Target Support Files/HXPHPicker/HXPHPicker-Info.plist index bfb89879..c243c020 100644 --- a/Pods/Target Support Files/HXPHPicker/HXPHPicker-Info.plist +++ b/Pods/Target Support Files/HXPHPicker/HXPHPicker-Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 1.1.3 + 1.1.6 CFBundleSignature ???? CFBundleVersion diff --git a/Pods/Target Support Files/Kingfisher/Kingfisher-Info.plist b/Pods/Target Support Files/Kingfisher/Kingfisher-Info.plist index 64061506..e9068b0f 100644 --- a/Pods/Target Support Files/Kingfisher/Kingfisher-Info.plist +++ b/Pods/Target Support Files/Kingfisher/Kingfisher-Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 6.3.0 + 6.3.1 CFBundleSignature ???? CFBundleVersion diff --git a/Swift/Assets.xcassets/camera_overturn.imageset/Contents.json b/Swift/Assets.xcassets/camera_overturn.imageset/Contents.json new file mode 100644 index 00000000..bc1fb2d3 --- /dev/null +++ b/Swift/Assets.xcassets/camera_overturn.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "camera_overturn@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "camera_overturn@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Swift/Assets.xcassets/camera_overturn.imageset/camera_overturn@2x.png b/Swift/Assets.xcassets/camera_overturn.imageset/camera_overturn@2x.png new file mode 100644 index 00000000..d65fb8f8 Binary files /dev/null and b/Swift/Assets.xcassets/camera_overturn.imageset/camera_overturn@2x.png differ diff --git a/Swift/Assets.xcassets/camera_overturn.imageset/camera_overturn@3x.png b/Swift/Assets.xcassets/camera_overturn.imageset/camera_overturn@3x.png new file mode 100644 index 00000000..ea736dd2 Binary files /dev/null and b/Swift/Assets.xcassets/camera_overturn.imageset/camera_overturn@3x.png differ diff --git a/Swift/Assets.xcassets/hx_photo_edit_tools_clip.imageset/Contents.json b/Swift/Assets.xcassets/hx_photo_edit_tools_clip.imageset/Contents.json new file mode 100644 index 00000000..5b1f9345 --- /dev/null +++ b/Swift/Assets.xcassets/hx_photo_edit_tools_clip.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "hx_photo_edit_tools_clip@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "hx_photo_edit_tools_clip@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Swift/Assets.xcassets/hx_photo_edit_tools_clip.imageset/hx_photo_edit_tools_clip@2x.png b/Swift/Assets.xcassets/hx_photo_edit_tools_clip.imageset/hx_photo_edit_tools_clip@2x.png new file mode 100644 index 00000000..61adf7a0 Binary files /dev/null and b/Swift/Assets.xcassets/hx_photo_edit_tools_clip.imageset/hx_photo_edit_tools_clip@2x.png differ diff --git a/Swift/Assets.xcassets/hx_photo_edit_tools_clip.imageset/hx_photo_edit_tools_clip@3x.png b/Swift/Assets.xcassets/hx_photo_edit_tools_clip.imageset/hx_photo_edit_tools_clip@3x.png new file mode 100644 index 00000000..29ea7d3b Binary files /dev/null and b/Swift/Assets.xcassets/hx_photo_edit_tools_clip.imageset/hx_photo_edit_tools_clip@3x.png differ diff --git a/Swift/Assets.xcassets/hx_photo_edit_tools_emoji.imageset/Contents.json b/Swift/Assets.xcassets/hx_photo_edit_tools_emoji.imageset/Contents.json new file mode 100644 index 00000000..a660f055 --- /dev/null +++ b/Swift/Assets.xcassets/hx_photo_edit_tools_emoji.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "hx_photo_edit_tools_emoji@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "hx_photo_edit_tools_emoji@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Swift/Assets.xcassets/hx_photo_edit_tools_emoji.imageset/hx_photo_edit_tools_emoji@2x.png b/Swift/Assets.xcassets/hx_photo_edit_tools_emoji.imageset/hx_photo_edit_tools_emoji@2x.png new file mode 100644 index 00000000..e8db5edd Binary files /dev/null and b/Swift/Assets.xcassets/hx_photo_edit_tools_emoji.imageset/hx_photo_edit_tools_emoji@2x.png differ diff --git a/Swift/Assets.xcassets/hx_photo_edit_tools_emoji.imageset/hx_photo_edit_tools_emoji@3x.png b/Swift/Assets.xcassets/hx_photo_edit_tools_emoji.imageset/hx_photo_edit_tools_emoji@3x.png new file mode 100644 index 00000000..fbec5936 Binary files /dev/null and b/Swift/Assets.xcassets/hx_photo_edit_tools_emoji.imageset/hx_photo_edit_tools_emoji@3x.png differ diff --git a/Swift/Assets.xcassets/hx_photo_edit_tools_graffiti.imageset/Contents.json b/Swift/Assets.xcassets/hx_photo_edit_tools_graffiti.imageset/Contents.json new file mode 100644 index 00000000..ba6bf5e0 --- /dev/null +++ b/Swift/Assets.xcassets/hx_photo_edit_tools_graffiti.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "hx_photo_edit_tools_graffiti@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "hx_photo_edit_tools_graffiti@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Swift/Assets.xcassets/hx_photo_edit_tools_graffiti.imageset/hx_photo_edit_tools_graffiti@2x.png b/Swift/Assets.xcassets/hx_photo_edit_tools_graffiti.imageset/hx_photo_edit_tools_graffiti@2x.png new file mode 100644 index 00000000..8c1cf689 Binary files /dev/null and b/Swift/Assets.xcassets/hx_photo_edit_tools_graffiti.imageset/hx_photo_edit_tools_graffiti@2x.png differ diff --git a/Swift/Assets.xcassets/hx_photo_edit_tools_graffiti.imageset/hx_photo_edit_tools_graffiti@3x.png b/Swift/Assets.xcassets/hx_photo_edit_tools_graffiti.imageset/hx_photo_edit_tools_graffiti@3x.png new file mode 100644 index 00000000..4e5632a0 Binary files /dev/null and b/Swift/Assets.xcassets/hx_photo_edit_tools_graffiti.imageset/hx_photo_edit_tools_graffiti@3x.png differ diff --git a/Swift/Assets.xcassets/hx_photo_edit_tools_mosaic.imageset/Contents.json b/Swift/Assets.xcassets/hx_photo_edit_tools_mosaic.imageset/Contents.json new file mode 100644 index 00000000..c3db2319 --- /dev/null +++ b/Swift/Assets.xcassets/hx_photo_edit_tools_mosaic.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "hx_photo_edit_tools_mosaic@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "hx_photo_edit_tools_mosaic@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Swift/Assets.xcassets/hx_photo_edit_tools_mosaic.imageset/hx_photo_edit_tools_mosaic@2x.png b/Swift/Assets.xcassets/hx_photo_edit_tools_mosaic.imageset/hx_photo_edit_tools_mosaic@2x.png new file mode 100644 index 00000000..6576fc20 Binary files /dev/null and b/Swift/Assets.xcassets/hx_photo_edit_tools_mosaic.imageset/hx_photo_edit_tools_mosaic@2x.png differ diff --git a/Swift/Assets.xcassets/hx_photo_edit_tools_mosaic.imageset/hx_photo_edit_tools_mosaic@3x.png b/Swift/Assets.xcassets/hx_photo_edit_tools_mosaic.imageset/hx_photo_edit_tools_mosaic@3x.png new file mode 100644 index 00000000..c6e1b5ba Binary files /dev/null and b/Swift/Assets.xcassets/hx_photo_edit_tools_mosaic.imageset/hx_photo_edit_tools_mosaic@3x.png differ diff --git a/Swift/Assets.xcassets/hx_photo_edit_tools_text.imageset/Contents.json b/Swift/Assets.xcassets/hx_photo_edit_tools_text.imageset/Contents.json new file mode 100644 index 00000000..b7a2a225 --- /dev/null +++ b/Swift/Assets.xcassets/hx_photo_edit_tools_text.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "hx_photo_edit_tools_text@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "hx_photo_edit_tools_text@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Swift/Assets.xcassets/hx_photo_edit_tools_text.imageset/hx_photo_edit_tools_text@2x.png b/Swift/Assets.xcassets/hx_photo_edit_tools_text.imageset/hx_photo_edit_tools_text@2x.png new file mode 100644 index 00000000..bbb226ca Binary files /dev/null and b/Swift/Assets.xcassets/hx_photo_edit_tools_text.imageset/hx_photo_edit_tools_text@2x.png differ diff --git a/Swift/Assets.xcassets/hx_photo_edit_tools_text.imageset/hx_photo_edit_tools_text@3x.png b/Swift/Assets.xcassets/hx_photo_edit_tools_text.imageset/hx_photo_edit_tools_text@3x.png new file mode 100644 index 00000000..31fbef4c Binary files /dev/null and b/Swift/Assets.xcassets/hx_photo_edit_tools_text.imageset/hx_photo_edit_tools_text@3x.png differ diff --git a/Swift/Assets.xcassets/hx_sticker_chongya.imageset/Contents.json b/Swift/Assets.xcassets/hx_sticker_chongya.imageset/Contents.json new file mode 100644 index 00000000..f47b5b4c --- /dev/null +++ b/Swift/Assets.xcassets/hx_sticker_chongya.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "hx_sticker_chongya.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Swift/Assets.xcassets/hx_sticker_chongya.imageset/hx_sticker_chongya.png b/Swift/Assets.xcassets/hx_sticker_chongya.imageset/hx_sticker_chongya.png new file mode 100644 index 00000000..c9c1d818 Binary files /dev/null and b/Swift/Assets.xcassets/hx_sticker_chongya.imageset/hx_sticker_chongya.png differ diff --git a/Swift/Assets.xcassets/hx_sticker_cover.imageset/Contents.json b/Swift/Assets.xcassets/hx_sticker_cover.imageset/Contents.json new file mode 100644 index 00000000..736624cf --- /dev/null +++ b/Swift/Assets.xcassets/hx_sticker_cover.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "hx_sticker_cover@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "hx_sticker_cover@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Swift/Assets.xcassets/hx_sticker_cover.imageset/hx_sticker_cover@2x.png b/Swift/Assets.xcassets/hx_sticker_cover.imageset/hx_sticker_cover@2x.png new file mode 100644 index 00000000..bb22f258 Binary files /dev/null and b/Swift/Assets.xcassets/hx_sticker_cover.imageset/hx_sticker_cover@2x.png differ diff --git a/Swift/Assets.xcassets/hx_sticker_cover.imageset/hx_sticker_cover@3x.png b/Swift/Assets.xcassets/hx_sticker_cover.imageset/hx_sticker_cover@3x.png new file mode 100644 index 00000000..455f8406 Binary files /dev/null and b/Swift/Assets.xcassets/hx_sticker_cover.imageset/hx_sticker_cover@3x.png differ diff --git a/Swift/Assets.xcassets/hx_sticker_haoxinqing.imageset/Contents.json b/Swift/Assets.xcassets/hx_sticker_haoxinqing.imageset/Contents.json new file mode 100644 index 00000000..080e0f5c --- /dev/null +++ b/Swift/Assets.xcassets/hx_sticker_haoxinqing.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "hx_sticker_haoxinqing.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Swift/Assets.xcassets/hx_sticker_haoxinqing.imageset/hx_sticker_haoxinqing.png b/Swift/Assets.xcassets/hx_sticker_haoxinqing.imageset/hx_sticker_haoxinqing.png new file mode 100644 index 00000000..3cb0b1cb Binary files /dev/null and b/Swift/Assets.xcassets/hx_sticker_haoxinqing.imageset/hx_sticker_haoxinqing.png differ diff --git a/Swift/Assets.xcassets/hx_sticker_housailei.imageset/Contents.json b/Swift/Assets.xcassets/hx_sticker_housailei.imageset/Contents.json new file mode 100644 index 00000000..2dce98a5 --- /dev/null +++ b/Swift/Assets.xcassets/hx_sticker_housailei.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "hx_sticker_housailei.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Swift/Assets.xcassets/hx_sticker_housailei.imageset/hx_sticker_housailei.png b/Swift/Assets.xcassets/hx_sticker_housailei.imageset/hx_sticker_housailei.png new file mode 100644 index 00000000..167a29f8 Binary files /dev/null and b/Swift/Assets.xcassets/hx_sticker_housailei.imageset/hx_sticker_housailei.png differ diff --git a/Swift/Assets.xcassets/hx_sticker_jintianfenkeai.imageset/Contents.json b/Swift/Assets.xcassets/hx_sticker_jintianfenkeai.imageset/Contents.json new file mode 100644 index 00000000..ac465ce2 --- /dev/null +++ b/Swift/Assets.xcassets/hx_sticker_jintianfenkeai.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "hx_sticker_jintianfenkeai.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Swift/Assets.xcassets/hx_sticker_jintianfenkeai.imageset/hx_sticker_jintianfenkeai.png b/Swift/Assets.xcassets/hx_sticker_jintianfenkeai.imageset/hx_sticker_jintianfenkeai.png new file mode 100644 index 00000000..c88fdbf3 Binary files /dev/null and b/Swift/Assets.xcassets/hx_sticker_jintianfenkeai.imageset/hx_sticker_jintianfenkeai.png differ diff --git a/Swift/Assets.xcassets/hx_sticker_keaibiaoq.imageset/Contents.json b/Swift/Assets.xcassets/hx_sticker_keaibiaoq.imageset/Contents.json new file mode 100644 index 00000000..07e5af26 --- /dev/null +++ b/Swift/Assets.xcassets/hx_sticker_keaibiaoq.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "hx_sticker_keaibiaoq.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Swift/Assets.xcassets/hx_sticker_keaibiaoq.imageset/hx_sticker_keaibiaoq.png b/Swift/Assets.xcassets/hx_sticker_keaibiaoq.imageset/hx_sticker_keaibiaoq.png new file mode 100644 index 00000000..53979c24 Binary files /dev/null and b/Swift/Assets.xcassets/hx_sticker_keaibiaoq.imageset/hx_sticker_keaibiaoq.png differ diff --git a/Swift/Assets.xcassets/hx_sticker_kehaixing.imageset/Contents.json b/Swift/Assets.xcassets/hx_sticker_kehaixing.imageset/Contents.json new file mode 100644 index 00000000..d7cadb6a --- /dev/null +++ b/Swift/Assets.xcassets/hx_sticker_kehaixing.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "hx_sticker_kehaixing.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Swift/Assets.xcassets/hx_sticker_kehaixing.imageset/hx_sticker_kehaixing.png b/Swift/Assets.xcassets/hx_sticker_kehaixing.imageset/hx_sticker_kehaixing.png new file mode 100644 index 00000000..895649ce Binary files /dev/null and b/Swift/Assets.xcassets/hx_sticker_kehaixing.imageset/hx_sticker_kehaixing.png differ diff --git a/Swift/Assets.xcassets/hx_sticker_saihong.imageset/Contents.json b/Swift/Assets.xcassets/hx_sticker_saihong.imageset/Contents.json new file mode 100644 index 00000000..49a56d75 --- /dev/null +++ b/Swift/Assets.xcassets/hx_sticker_saihong.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "hx_sticker_saihong.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Swift/Assets.xcassets/hx_sticker_saihong.imageset/hx_sticker_saihong.png b/Swift/Assets.xcassets/hx_sticker_saihong.imageset/hx_sticker_saihong.png new file mode 100644 index 00000000..78851ce0 Binary files /dev/null and b/Swift/Assets.xcassets/hx_sticker_saihong.imageset/hx_sticker_saihong.png differ diff --git a/Swift/Assets.xcassets/hx_sticker_wow.imageset/Contents.json b/Swift/Assets.xcassets/hx_sticker_wow.imageset/Contents.json new file mode 100644 index 00000000..3d00703d --- /dev/null +++ b/Swift/Assets.xcassets/hx_sticker_wow.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "hx_sticker_wow.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Swift/Assets.xcassets/hx_sticker_wow.imageset/hx_sticker_wow.png b/Swift/Assets.xcassets/hx_sticker_wow.imageset/hx_sticker_wow.png new file mode 100644 index 00000000..b11af528 Binary files /dev/null and b/Swift/Assets.xcassets/hx_sticker_wow.imageset/hx_sticker_wow.png differ diff --git a/Swift/Assets.xcassets/hx_sticker_woxiangfazipai.imageset/Contents.json b/Swift/Assets.xcassets/hx_sticker_woxiangfazipai.imageset/Contents.json new file mode 100644 index 00000000..1e1f78d0 --- /dev/null +++ b/Swift/Assets.xcassets/hx_sticker_woxiangfazipai.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "hx_sticker_woxiangfazipai.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Swift/Assets.xcassets/hx_sticker_woxiangfazipai.imageset/hx_sticker_woxiangfazipai.png b/Swift/Assets.xcassets/hx_sticker_woxiangfazipai.imageset/hx_sticker_woxiangfazipai.png new file mode 100644 index 00000000..ed43f607 Binary files /dev/null and b/Swift/Assets.xcassets/hx_sticker_woxiangfazipai.imageset/hx_sticker_woxiangfazipai.png differ diff --git a/Swift/Assets.xcassets/hx_sticker_xiaochuzhujiao.imageset/Contents.json b/Swift/Assets.xcassets/hx_sticker_xiaochuzhujiao.imageset/Contents.json new file mode 100644 index 00000000..0947512f --- /dev/null +++ b/Swift/Assets.xcassets/hx_sticker_xiaochuzhujiao.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "hx_sticker_xiaochuzhujiao.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Swift/Assets.xcassets/hx_sticker_xiaochuzhujiao.imageset/hx_sticker_xiaochuzhujiao.png b/Swift/Assets.xcassets/hx_sticker_xiaochuzhujiao.imageset/hx_sticker_xiaochuzhujiao.png new file mode 100644 index 00000000..35334983 Binary files /dev/null and b/Swift/Assets.xcassets/hx_sticker_xiaochuzhujiao.imageset/hx_sticker_xiaochuzhujiao.png differ diff --git a/Swift/Assets.xcassets/hx_sticker_yuanqimanman.imageset/Contents.json b/Swift/Assets.xcassets/hx_sticker_yuanqimanman.imageset/Contents.json new file mode 100644 index 00000000..4f9105ad --- /dev/null +++ b/Swift/Assets.xcassets/hx_sticker_yuanqimanman.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "hx_sticker_yuanqimanman.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Swift/Assets.xcassets/hx_sticker_yuanqimanman.imageset/hx_sticker_yuanqimanman.png b/Swift/Assets.xcassets/hx_sticker_yuanqimanman.imageset/hx_sticker_yuanqimanman.png new file mode 100644 index 00000000..ede0ab6e Binary files /dev/null and b/Swift/Assets.xcassets/hx_sticker_yuanqimanman.imageset/hx_sticker_yuanqimanman.png differ diff --git a/Swift/Assets.xcassets/hx_sticker_yuanqishaonv.imageset/Contents.json b/Swift/Assets.xcassets/hx_sticker_yuanqishaonv.imageset/Contents.json new file mode 100644 index 00000000..b28d3401 --- /dev/null +++ b/Swift/Assets.xcassets/hx_sticker_yuanqishaonv.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "hx_sticker_yuanqishaonv.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Swift/Assets.xcassets/hx_sticker_yuanqishaonv.imageset/hx_sticker_yuanqishaonv.png b/Swift/Assets.xcassets/hx_sticker_yuanqishaonv.imageset/hx_sticker_yuanqishaonv.png new file mode 100644 index 00000000..ac35240e Binary files /dev/null and b/Swift/Assets.xcassets/hx_sticker_yuanqishaonv.imageset/hx_sticker_yuanqishaonv.png differ diff --git a/Swift/Assets.xcassets/hx_sticker_zaizaijia.imageset/Contents.json b/Swift/Assets.xcassets/hx_sticker_zaizaijia.imageset/Contents.json new file mode 100644 index 00000000..c43e4891 --- /dev/null +++ b/Swift/Assets.xcassets/hx_sticker_zaizaijia.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "hx_sticker_zaizaijia.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Swift/Assets.xcassets/hx_sticker_zaizaijia.imageset/hx_sticker_zaizaijia.png b/Swift/Assets.xcassets/hx_sticker_zaizaijia.imageset/hx_sticker_zaizaijia.png new file mode 100644 index 00000000..acb8a6cf Binary files /dev/null and b/Swift/Assets.xcassets/hx_sticker_zaizaijia.imageset/hx_sticker_zaizaijia.png differ diff --git a/Swift/Classes/Controller/AvatarPickerConfigurationViewController.swift b/Swift/Classes/Controller/AvatarPickerConfigurationViewController.swift index 818bba98..bfbbf733 100644 --- a/Swift/Classes/Controller/AvatarPickerConfigurationViewController.swift +++ b/Swift/Classes/Controller/AvatarPickerConfigurationViewController.swift @@ -18,9 +18,9 @@ class AvatarPickerConfigurationViewController: UITableViewController { config.selectOptions = .photo config.photoSelectionTapAction = .openEditor config.photoEditor.fixedCropState = true - config.photoEditor.cropConfig.isRoundCrop = true - config.photoEditor.cropConfig.aspectRatioType = .ratio_1x1 - config.photoEditor.cropConfig.fixedRatio = true + config.photoEditor.cropping.isRoundCrop = true + config.photoEditor.cropping.aspectRatioType = .ratio_1x1 + config.photoEditor.cropping.fixedRatio = true tableView.cellLayoutMarginsFollowReadableWidth = true tableView.register(ConfigurationViewCell.self, forCellReuseIdentifier: ConfigurationViewCell.reuseIdentifier) @@ -96,13 +96,13 @@ extension AvatarPickerConfigurationViewController { case .fixedCropState: return config.photoEditor.fixedCropState ? "true" : "false" case .isRoundCrop: - return config.photoEditor.cropConfig.isRoundCrop ? "true" : "false" + return config.photoEditor.cropping.isRoundCrop ? "true" : "false" case .fixedRatio: - return config.photoEditor.cropConfig.fixedRatio ? "true" : "false" + return config.photoEditor.cropping.fixedRatio ? "true" : "false" case .aspectRatioType: - return config.photoEditor.cropConfig.aspectRatioType.title + return config.photoEditor.cropping.aspectRatioType.title case .maskType: - switch config.photoEditor.cropConfig.maskType { + switch config.photoEditor.cropping.maskType { case .blackColor: return "blackColor" case .darkBlurEffect: @@ -155,11 +155,11 @@ extension AvatarPickerConfigurationViewController { tableView.reloadRows(at: [indexPath], with: .fade) } func isRoundCropAction(_ indexPath: IndexPath) { - config.photoEditor.cropConfig.isRoundCrop = !config.photoEditor.cropConfig.isRoundCrop + config.photoEditor.cropping.isRoundCrop = !config.photoEditor.cropping.isRoundCrop tableView.reloadRows(at: [indexPath], with: .fade) } func fixedRatioAction(_ indexPath: IndexPath) { - config.photoEditor.cropConfig.fixedRatio = !config.photoEditor.cropConfig.fixedRatio + config.photoEditor.cropping.fixedRatio = !config.photoEditor.cropping.fixedRatio tableView.reloadRows(at: [indexPath], with: .fade) } func aspectRatioTypeAction(_ indexPath: IndexPath) { @@ -179,7 +179,7 @@ extension AvatarPickerConfigurationViewController { let heightTextFiled = alert.textFields?.last let heightRatioStr = heightTextFiled?.text ?? "0" let heightRatio = Int(heightRatioStr.count == 0 ? "0" : heightRatioStr)! - self.config.photoEditor.cropConfig.aspectRatioType = .custom(CGSize(width: widthRatio, height: heightRatio)) + self.config.photoEditor.cropping.aspectRatioType = .custom(CGSize(width: widthRatio, height: heightRatio)) self.tableView.reloadRows(at: [indexPath], with: .fade) })) alert.addAction(UIAlertAction.init(title: "取消", style: .cancel, handler: nil)) @@ -193,11 +193,11 @@ extension AvatarPickerConfigurationViewController { let index = titles.firstIndex(of: action.title!)! switch index { case 0: - self.config.photoEditor.cropConfig.maskType = .blackColor + self.config.photoEditor.cropping.maskType = .blackColor case 1: - self.config.photoEditor.cropConfig.maskType = .darkBlurEffect + self.config.photoEditor.cropping.maskType = .darkBlurEffect case 2: - self.config.photoEditor.cropConfig.maskType = .lightBlurEffect + self.config.photoEditor.cropping.maskType = .lightBlurEffect default: break } @@ -290,7 +290,7 @@ extension AvatarPickerConfigurationViewController { if self == .fixedCropState { return "." + rawValue } - return ".cropConfig." + rawValue + return ".cropping." + rawValue } func getFunction(_ controller: T) -> ((IndexPath) -> Void) where T : UIViewController { guard let controller = controller as? AvatarPickerConfigurationViewController else { diff --git a/Swift/Classes/Controller/AvatarPickerResultViewController.swift b/Swift/Classes/Controller/AvatarPickerResultViewController.swift deleted file mode 100644 index 60556db7..00000000 --- a/Swift/Classes/Controller/AvatarPickerResultViewController.swift +++ /dev/null @@ -1,8 +0,0 @@ -// -// AvatarPickerResultViewController.swift -// Example -// -// Created by Slience on 2021/5/19. -// - -import Foundation diff --git a/Swift/Classes/Controller/EditorConfigurationViewController.swift b/Swift/Classes/Controller/EditorConfigurationViewController.swift index 10f118cd..18e815b5 100644 --- a/Swift/Classes/Controller/EditorConfigurationViewController.swift +++ b/Swift/Classes/Controller/EditorConfigurationViewController.swift @@ -20,7 +20,7 @@ class EditorConfigurationViewController: UITableViewController { override func viewDidLoad() { super.viewDidLoad() navigationItem.title = "Editor" -// videoConfig.musicConfig.infos = musics +// videoConfig.music = .init(infos: musics) tableView.cellLayoutMarginsFollowReadableWidth = true tableView.register(ConfigurationViewCell.self, forCellReuseIdentifier: ConfigurationViewCell.reuseIdentifier) @@ -125,7 +125,7 @@ extension EditorConfigurationViewController: PhotoEditorViewControllerDelegate { pickerConfig.photoEditor = photoConfig pickerResultVC.config = pickerConfig - switch photoEditorViewController.assetType { + switch photoEditorViewController.sourceType { case .local: let localImageAsset = LocalImageAsset.init(image: photoEditorViewController.image) let photoAsset = PhotoAsset.init(localImageAsset: localImageAsset) @@ -148,7 +148,7 @@ extension EditorConfigurationViewController: PhotoEditorViewControllerDelegate { let pickerConfig = PickerConfiguration.init() pickerConfig.photoEditor = photoConfig pickerResultVC.config = pickerConfig - switch photoEditorViewController.assetType { + switch photoEditorViewController.sourceType { case .local: let localImageAsset = LocalImageAsset.init(image: photoEditorViewController.image) let photoAsset = PhotoAsset.init(localImageAsset: localImageAsset) @@ -166,61 +166,84 @@ extension EditorConfigurationViewController: PhotoEditorViewControllerDelegate { } } extension EditorConfigurationViewController: VideoEditorViewControllerDelegate { + func getMusicInfos() -> [VideoEditorMusicInfo] { + var musics: [VideoEditorMusicInfo] = [] +// let audioUrl1 = Bundle.main.url(forResource: "天外来物", withExtension: "mp3")! + let lyricUrl1 = Bundle.main.url(forResource: "天外来物", withExtension: nil)! + let lrc1 = try! String(contentsOfFile: lyricUrl1.path) + let music1 = VideoEditorMusicInfo.init(audioURL: URL(string: "http://tsnrhapp.oss-cn-hangzhou.aliyuncs.com/chartle/%E5%A4%A9%E5%A4%96%E6%9D%A5%E7%89%A9.mp3")!, + lrc: lrc1) + musics.append(music1) + let audioUrl2 = Bundle.main.url(forResource: "嘉宾", withExtension: "mp3")! + let lyricUrl2 = Bundle.main.url(forResource: "嘉宾", withExtension: nil)! + let lrc2 = try! String(contentsOfFile: lyricUrl2.path) + let music2 = VideoEditorMusicInfo.init(audioURL: audioUrl2, + lrc: lrc2) + musics.append(music2) + let audioUrl3 = Bundle.main.url(forResource: "少女的祈祷", withExtension: "mp3")! + let lyricUrl3 = Bundle.main.url(forResource: "少女的祈祷", withExtension: nil)! + let lrc3 = try! String(contentsOfFile: lyricUrl3.path) + let music3 = VideoEditorMusicInfo.init(audioURL: audioUrl3, + lrc: lrc3) + musics.append(music3) + let audioUrl4 = Bundle.main.url(forResource: "野孩子", withExtension: "mp3")! + let lyricUrl4 = Bundle.main.url(forResource: "野孩子", withExtension: nil)! + let lrc4 = try! String(contentsOfFile: lyricUrl4.path) + let music4 = VideoEditorMusicInfo.init(audioURL: audioUrl4, + lrc: lrc4) + musics.append(music4) + let audioUrl5 = Bundle.main.url(forResource: "无赖", withExtension: "mp3")! + let lyricUrl5 = Bundle.main.url(forResource: "无赖", withExtension: nil)! + let lrc5 = try! String(contentsOfFile: lyricUrl5.path) + let music5 = VideoEditorMusicInfo.init(audioURL: audioUrl5, + lrc: lrc5) + musics.append(music5) + let audioUrl6 = Bundle.main.url(forResource: "时光正好", withExtension: "mp3")! + let lyricUrl6 = Bundle.main.url(forResource: "时光正好", withExtension: nil)! + let lrc6 = try! String(contentsOfFile: lyricUrl6.path) + let music6 = VideoEditorMusicInfo.init(audioURL: audioUrl6, + lrc: lrc6) + musics.append(music6) + let audioUrl7 = Bundle.main.url(forResource: "世间美好与你环环相扣", withExtension: "mp3")! + let lyricUrl7 = Bundle.main.url(forResource: "世间美好与你环环相扣", withExtension: nil)! + let lrc7 = try! String(contentsOfFile: lyricUrl7.path) + let music7 = VideoEditorMusicInfo.init(audioURL: audioUrl7, + lrc: lrc7) + musics.append(music7) + let audioUrl8 = Bundle.main.url(forResource: "爱你", withExtension: "mp3")! + let lyricUrl8 = Bundle.main.url(forResource: "爱你", withExtension: nil)! + let lrc8 = try! String(contentsOfFile: lyricUrl8.path) + let music8 = VideoEditorMusicInfo.init(audioURL: audioUrl8, + lrc: lrc8) + musics.append(music8) + return musics + } func videoEditorViewController(_ videoEditorViewController: VideoEditorViewController, loadMusic completionHandler: @escaping ([VideoEditorMusicInfo]) -> Void) -> Bool { // 模仿延迟加加载数据 DispatchQueue.main.asyncAfter(deadline: .now() + 1) { - var musics: [VideoEditorMusicInfo] = [] - let audioUrl1 = Bundle.main.url(forResource: "天外来物", withExtension: "mp3")! - let lyricUrl1 = Bundle.main.url(forResource: "天外来物", withExtension: nil)! - let music1 = VideoEditorMusicInfo.init(audioPath: audioUrl1.path, - lrcPath: lyricUrl1.path) - musics.append(music1) - let audioUrl2 = Bundle.main.url(forResource: "嘉宾", withExtension: "mp3")! - let lyricUrl2 = Bundle.main.url(forResource: "嘉宾", withExtension: nil)! - let music2 = VideoEditorMusicInfo.init(audioPath: audioUrl2.path, - lrcPath: lyricUrl2.path) - musics.append(music2) - let audioUrl3 = Bundle.main.url(forResource: "少女的祈祷", withExtension: "mp3")! - let lyricUrl3 = Bundle.main.url(forResource: "少女的祈祷", withExtension: nil)! - let music3 = VideoEditorMusicInfo.init(audioPath: audioUrl3.path, - lrcPath: lyricUrl3.path) - musics.append(music3) - let audioUrl4 = Bundle.main.url(forResource: "野孩子", withExtension: "mp3")! - let lyricUrl4 = Bundle.main.url(forResource: "野孩子", withExtension: nil)! - let music4 = VideoEditorMusicInfo.init(audioPath: audioUrl4.path, - lrcPath: lyricUrl4.path) - musics.append(music4) - let audioUrl5 = Bundle.main.url(forResource: "无赖", withExtension: "mp3")! - let lyricUrl5 = Bundle.main.url(forResource: "无赖", withExtension: nil)! - let music5 = VideoEditorMusicInfo.init(audioPath: audioUrl5.path, - lrcPath: lyricUrl5.path) - musics.append(music5) - let audioUrl6 = Bundle.main.url(forResource: "时光正好", withExtension: "mp3")! - let lyricUrl6 = Bundle.main.url(forResource: "时光正好", withExtension: nil)! - let music6 = VideoEditorMusicInfo.init(audioPath: audioUrl6.path, - lrcPath: lyricUrl6.path) - musics.append(music6) - let audioUrl7 = Bundle.main.url(forResource: "世间美好与你环环相扣", withExtension: "mp3")! - let lyricUrl7 = Bundle.main.url(forResource: "世间美好与你环环相扣", withExtension: nil)! - let music7 = VideoEditorMusicInfo.init(audioPath: audioUrl7.path, - lrcPath: lyricUrl7.path) - musics.append(music7) - let audioUrl8 = Bundle.main.url(forResource: "爱你", withExtension: "mp3")! - let lyricUrl8 = Bundle.main.url(forResource: "爱你", withExtension: nil)! - let music8 = VideoEditorMusicInfo.init(audioPath: audioUrl8.path, - lrcPath: lyricUrl8.path) - musics.append(music8) - completionHandler(musics) + completionHandler(self.getMusicInfos()) } return true } + func videoEditorViewController(_ videoEditorViewController: VideoEditorViewController, didSearch text: String?, completionHandler: @escaping ([VideoEditorMusicInfo], Bool) -> Void) { + // 模仿延迟加加载数据 + DispatchQueue.main.asyncAfter(deadline: .now() + 1) { + completionHandler(self.getMusicInfos(), true) + } + } + func videoEditorViewController(_ videoEditorViewController: VideoEditorViewController, loadMore text: String?, completionHandler: @escaping ([VideoEditorMusicInfo], Bool) -> Void) { + DispatchQueue.main.asyncAfter(deadline: .now() + 1) { + completionHandler(self.getMusicInfos(), false) + } + } + func videoEditorViewController(_ videoEditorViewController: VideoEditorViewController, didFinish result: VideoEditResult) { let pickerResultVC = PickerResultViewController.init() let pickerConfig = PickerConfiguration.init() pickerConfig.videoEditor = videoConfig pickerResultVC.config = pickerConfig - switch videoEditorViewController.assetType { + switch videoEditorViewController.sourceType { case .local: let photoAsset = PhotoAsset.init(localVideoAsset: .init(videoURL: videoURL)) photoAsset.videoEdit = result @@ -239,7 +262,7 @@ extension EditorConfigurationViewController: VideoEditorViewControllerDelegate { let pickerConfig = PickerConfiguration.init() pickerConfig.videoEditor = videoConfig pickerResultVC.config = pickerConfig - switch videoEditorViewController.assetType { + switch videoEditorViewController.sourceType { case .local: let photoAsset = PhotoAsset.init(localVideoAsset: .init(videoURL: videoURL)) pickerResultVC.selectedAssets = [photoAsset] @@ -269,13 +292,13 @@ extension EditorConfigurationViewController { case .fixedCropState: return photoConfig.fixedCropState ? "true" : "false" case .isRoundCrop: - return photoConfig.cropConfig.isRoundCrop ? "true" : "false" + return photoConfig.cropping.isRoundCrop ? "true" : "false" case .fixedRatio: - return photoConfig.cropConfig.fixedRatio ? "true" : "false" + return photoConfig.cropping.fixedRatio ? "true" : "false" case .aspectRatioType: - return photoConfig.cropConfig.aspectRatioType.title + return photoConfig.cropping.aspectRatioType.title case .maskType: - switch photoConfig.cropConfig.maskType { + switch photoConfig.cropping.maskType { case .blackColor: return "blackColor" case .darkBlurEffect: @@ -341,11 +364,11 @@ extension EditorConfigurationViewController { tableView.reloadRows(at: [indexPath], with: .fade) } func isRoundCropAction(_ indexPath: IndexPath) { - photoConfig.cropConfig.isRoundCrop = !photoConfig.cropConfig.isRoundCrop + photoConfig.cropping.isRoundCrop = !photoConfig.cropping.isRoundCrop tableView.reloadRows(at: [indexPath], with: .fade) } func fixedRatioAction(_ indexPath: IndexPath) { - photoConfig.cropConfig.fixedRatio = !photoConfig.cropConfig.fixedRatio + photoConfig.cropping.fixedRatio = !photoConfig.cropping.fixedRatio tableView.reloadRows(at: [indexPath], with: .fade) } func aspectRatioTypeAction(_ indexPath: IndexPath) { @@ -365,7 +388,7 @@ extension EditorConfigurationViewController { let heightTextFiled = alert.textFields?.last let heightRatioStr = heightTextFiled?.text ?? "0" let heightRatio = Int(heightRatioStr.count == 0 ? "0" : heightRatioStr)! - self.photoConfig.cropConfig.aspectRatioType = .custom(CGSize(width: widthRatio, height: heightRatio)) + self.photoConfig.cropping.aspectRatioType = .custom(CGSize(width: widthRatio, height: heightRatio)) self.tableView.reloadRows(at: [indexPath], with: .fade) })) alert.addAction(UIAlertAction.init(title: "取消", style: .cancel, handler: nil)) @@ -379,11 +402,11 @@ extension EditorConfigurationViewController { let index = titles.firstIndex(of: action.title!)! switch index { case 0: - self.photoConfig.cropConfig.maskType = .blackColor + self.photoConfig.cropping.maskType = .blackColor case 1: - self.photoConfig.cropConfig.maskType = .darkBlurEffect + self.photoConfig.cropping.maskType = .darkBlurEffect case 2: - self.photoConfig.cropConfig.maskType = .lightBlurEffect + self.photoConfig.cropping.maskType = .lightBlurEffect default: break } @@ -554,7 +577,7 @@ extension EditorConfigurationViewController { return "." + rawValue default: break } - return ".cropConfig." + rawValue + return ".cropping." + rawValue } func getFunction(_ controller: T) -> ((IndexPath) -> Void) where T : UIViewController { guard let controller = controller as? EditorConfigurationViewController else { diff --git a/Swift/Classes/Controller/HomeViewController.swift b/Swift/Classes/Controller/HomeViewController.swift index c0665b6d..7fabe0bc 100644 --- a/Swift/Classes/Controller/HomeViewController.swift +++ b/Swift/Classes/Controller/HomeViewController.swift @@ -10,15 +10,33 @@ import HXPHPicker class HomeViewController: UITableViewController { + var reachability: Reachability? + override func viewDidLoad() { super.viewDidLoad() navigationItem.title = "Photo Kit" - + reachability = try? .init() + reachability?.whenReachable = { reachability in + if reachability.connection != .unavailable { + print("网络连接:可用") + if reachability.connection == .wifi { + print("连接类型:WiFi") + } else { + print("连接类型:移动网络") + } + } else { + print("网络连接:不可用") + } + } + do{ + try reachability?.startNotifier() + }catch { + print("could not start reachability notifier") + } tableView.cellLayoutMarginsFollowReadableWidth = true tableView.register(UITableViewCell.self, forCellReuseIdentifier: UITableViewCell.reuseIdentifier) tableView.tableFooterView = UIView(frame: .zero) } - // MARK: - Table view data source override func numberOfSections(in tableView: UITableView) -> Int { @@ -115,6 +133,7 @@ extension HomeViewController { case preselectAsset case collectionView case customCell + case weChatMoment var title: String { switch self { @@ -126,6 +145,8 @@ extension HomeViewController { return "Picker+UICollectionView" case .customCell: return "Picker+CustomCell" + case .weChatMoment: + return "WeChat-Moment" } } @@ -145,14 +166,20 @@ extension HomeViewController { case .collectionView: return PickerResultViewController() case .customCell: - let config: PickerConfiguration = PhotoTools.getWXPickerConfig(isMoment: false) + let config: PickerConfiguration = PhotoTools.getWXPickerConfig( + isMoment: false + ) config.photoSelectionTapAction = .quickSelect config.videoSelectionTapAction = .quickSelect config.photoList.cell.customSingleCellClass = CustomPickerViewCell.self config.photoList.cell.customSelectableCellClass = CustomPickerViewCell.self - let pickerController = PhotoPickerController.init(config: config) + let pickerController = PhotoPickerController( + config: config + ) pickerController.autoDismiss = false return pickerController + case .weChatMoment: + return WeChatMometViewController() } } } diff --git a/Swift/Classes/Controller/PickerColorConfigurationViewController.swift b/Swift/Classes/Controller/PickerColorConfigurationViewController.swift index e8e547a3..381b3f82 100644 --- a/Swift/Classes/Controller/PickerColorConfigurationViewController.swift +++ b/Swift/Classes/Controller/PickerColorConfigurationViewController.swift @@ -129,17 +129,17 @@ extension PickerColorConfigurationViewController { case .backgroundDarkColor: return config.photoList.backgroundDarkColor case .titleViewBackgroundColor: - return config.photoList.titleViewConfig.backgroundColor + return config.photoList.titleView.backgroundColor case .titleViewBackgroundDarkColor: - return config.photoList.titleViewConfig.backgroudDarkColor + return config.photoList.titleView.backgroudDarkColor case .titleViewArrowBackgroundColor: - return config.photoList.titleViewConfig.arrowBackgroundColor + return config.photoList.titleView.arrowBackgroundColor case .titleViewArrowBackgroudDarkColor: - return config.photoList.titleViewConfig.arrowBackgroudDarkColor + return config.photoList.titleView.arrowBackgroudDarkColor case .titleViewArrowColor: - return config.photoList.titleViewConfig.arrowColor + return config.photoList.titleView.arrowColor case .titleViewArrowDarkColor: - return config.photoList.titleViewConfig.arrowDarkColor + return config.photoList.titleView.arrowDarkColor case .cellTitleColor: return config.photoList.cell.selectBox.titleColor case .cellTitleDarkColor: @@ -257,17 +257,17 @@ extension PickerColorConfigurationViewController: UIColorPickerViewControllerDel case .backgroundDarkColor: config.photoList.backgroundDarkColor = color case .titleViewBackgroundColor: - config.photoList.titleViewConfig.backgroundColor = color + config.photoList.titleView.backgroundColor = color case .titleViewBackgroundDarkColor: - config.photoList.titleViewConfig.backgroudDarkColor = color + config.photoList.titleView.backgroudDarkColor = color case .titleViewArrowBackgroundColor: - config.photoList.titleViewConfig.arrowBackgroundColor = color + config.photoList.titleView.arrowBackgroundColor = color case .titleViewArrowBackgroudDarkColor: - config.photoList.titleViewConfig.arrowBackgroudDarkColor = color + config.photoList.titleView.arrowBackgroudDarkColor = color case .titleViewArrowColor: - config.photoList.titleViewConfig.arrowColor = color + config.photoList.titleView.arrowColor = color case .titleViewArrowDarkColor: - config.photoList.titleViewConfig.arrowDarkColor = color + config.photoList.titleView.arrowDarkColor = color case .cellTitleColor: config.photoList.cell.selectBox.titleColor = color case .cellTitleDarkColor: diff --git a/Swift/Classes/Controller/PickerConfigurationViewController.swift b/Swift/Classes/Controller/PickerConfigurationViewController.swift index c0b57ee6..5e6b1da5 100644 --- a/Swift/Classes/Controller/PickerConfigurationViewController.swift +++ b/Swift/Classes/Controller/PickerConfigurationViewController.swift @@ -126,43 +126,51 @@ extension PickerConfigurationViewController: PhotoPickerControllerDelegate { var musics: [VideoEditorMusicInfo] = [] let audioUrl1 = Bundle.main.url(forResource: "天外来物", withExtension: "mp3")! let lyricUrl1 = Bundle.main.url(forResource: "天外来物", withExtension: nil)! - let music1 = VideoEditorMusicInfo.init(audioPath: audioUrl1.path, - lrcPath: lyricUrl1.path) + let lrc1 = try! String(contentsOfFile: lyricUrl1.path) + let music1 = VideoEditorMusicInfo.init(audioURL: audioUrl1, + lrc: lrc1) musics.append(music1) let audioUrl2 = Bundle.main.url(forResource: "嘉宾", withExtension: "mp3")! let lyricUrl2 = Bundle.main.url(forResource: "嘉宾", withExtension: nil)! - let music2 = VideoEditorMusicInfo.init(audioPath: audioUrl2.path, - lrcPath: lyricUrl2.path) + let lrc2 = try! String(contentsOfFile: lyricUrl2.path) + let music2 = VideoEditorMusicInfo.init(audioURL: audioUrl2, + lrc: lrc2) musics.append(music2) let audioUrl3 = Bundle.main.url(forResource: "少女的祈祷", withExtension: "mp3")! let lyricUrl3 = Bundle.main.url(forResource: "少女的祈祷", withExtension: nil)! - let music3 = VideoEditorMusicInfo.init(audioPath: audioUrl3.path, - lrcPath: lyricUrl3.path) + let lrc3 = try! String(contentsOfFile: lyricUrl3.path) + let music3 = VideoEditorMusicInfo.init(audioURL: audioUrl3, + lrc: lrc3) musics.append(music3) let audioUrl4 = Bundle.main.url(forResource: "野孩子", withExtension: "mp3")! let lyricUrl4 = Bundle.main.url(forResource: "野孩子", withExtension: nil)! - let music4 = VideoEditorMusicInfo.init(audioPath: audioUrl4.path, - lrcPath: lyricUrl4.path) + let lrc4 = try! String(contentsOfFile: lyricUrl4.path) + let music4 = VideoEditorMusicInfo.init(audioURL: audioUrl4, + lrc: lrc4) musics.append(music4) let audioUrl5 = Bundle.main.url(forResource: "无赖", withExtension: "mp3")! let lyricUrl5 = Bundle.main.url(forResource: "无赖", withExtension: nil)! - let music5 = VideoEditorMusicInfo.init(audioPath: audioUrl5.path, - lrcPath: lyricUrl5.path) + let lrc5 = try! String(contentsOfFile: lyricUrl5.path) + let music5 = VideoEditorMusicInfo.init(audioURL: audioUrl5, + lrc: lrc5) musics.append(music5) let audioUrl6 = Bundle.main.url(forResource: "时光正好", withExtension: "mp3")! let lyricUrl6 = Bundle.main.url(forResource: "时光正好", withExtension: nil)! - let music6 = VideoEditorMusicInfo.init(audioPath: audioUrl6.path, - lrcPath: lyricUrl6.path) + let lrc6 = try! String(contentsOfFile: lyricUrl6.path) + let music6 = VideoEditorMusicInfo.init(audioURL: audioUrl6, + lrc: lrc6) musics.append(music6) let audioUrl7 = Bundle.main.url(forResource: "世间美好与你环环相扣", withExtension: "mp3")! let lyricUrl7 = Bundle.main.url(forResource: "世间美好与你环环相扣", withExtension: nil)! - let music7 = VideoEditorMusicInfo.init(audioPath: audioUrl7.path, - lrcPath: lyricUrl7.path) + let lrc7 = try! String(contentsOfFile: lyricUrl7.path) + let music7 = VideoEditorMusicInfo.init(audioURL: audioUrl7, + lrc: lrc7) musics.append(music7) let audioUrl8 = Bundle.main.url(forResource: "爱你", withExtension: "mp3")! let lyricUrl8 = Bundle.main.url(forResource: "爱你", withExtension: nil)! - let music8 = VideoEditorMusicInfo.init(audioPath: audioUrl8.path, - lrcPath: lyricUrl8.path) + let lrc8 = try! String(contentsOfFile: lyricUrl8.path) + let music8 = VideoEditorMusicInfo.init(audioURL: audioUrl8, + lrc: lrc8) musics.append(music8) completionHandler(musics) return false diff --git a/Swift/Classes/Controller/PickerResultViewController.swift b/Swift/Classes/Controller/PickerResultViewController.swift index 22ae5ff0..1a975241 100644 --- a/Swift/Classes/Controller/PickerResultViewController.swift +++ b/Swift/Classes/Controller/PickerResultViewController.swift @@ -10,6 +10,7 @@ import UIKit import Photos import HXPHPicker +import Kingfisher class PickerResultViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate,UICollectionViewDragDelegate, UICollectionViewDropDelegate, ResultViewCellDelegate { @@ -49,6 +50,18 @@ class PickerResultViewController: UIViewController, UICollectionViewDataSource, var localAssetArray: [PhotoAsset] = [] var preselect: Bool = false + var isPublish: Bool = false + + var localCachePath: String { + var cachePath = PhotoTools.getSystemCacheFolderPath() + cachePath.append(contentsOf: "/com.silence.WeChat_Moment") + return cachePath + } + var localURL: URL { + var cachePath = localCachePath + cachePath.append(contentsOf: "/PhotoAssets") + return URL.init(fileURLWithPath: cachePath) + } weak var previewTitleLabel: UILabel? weak var currentPickerController: PhotoPickerController? @@ -74,9 +87,32 @@ class PickerResultViewController: UIViewController, UICollectionViewDataSource, collectionView.addGestureRecognizer(longGestureRecognizer) } view.backgroundColor = UIColor.white - navigationItem.rightBarButtonItem = UIBarButtonItem.init(title: "设置", style: .done, target: self, action: #selector(didSettingButtonClick)) + if isPublish { + title = "Moment" + let publishBtn = UIBarButtonItem.init(title: "发布", style: .done, target: self, action: #selector(didPublishBtnClick)) + + navigationItem.rightBarButtonItems = [publishBtn] + navigationItem.leftBarButtonItem = UIBarButtonItem(title: "取消", style: .done, target: self, action: #selector(didCancelButtonClick)) + + if let localData = FileManager.default.contents(atPath: localURL.path), + let datas = try? JSONDecoder().decode([Data].self, from: localData) { + var photoAssets: [PhotoAsset] = [] + for data in datas { + if let photoAsset = PhotoAsset.decoder(data: data) { + photoAssets.append(photoAsset) + } + } + selectedAssets = photoAssets + } + }else { + let settingBtn = UIBarButtonItem.init(title: "设置", style: .done, target: self, action: #selector(didSettingButtonClick)) + let clearBtn = UIBarButtonItem.init(title: "清空缓存", style: .done, target: self, action: #selector(didClearButtonClick)) + + navigationItem.rightBarButtonItems = [settingBtn, clearBtn] + } if preselect { + config.previewView.loadNetworkVideoMode = .play config.maximumSelectedVideoDuration = 0 config.maximumSelectedVideoCount = 0 let networkVideoURL = URL.init(string: "http://tsnrhapp.oss-cn-hangzhou.aliyuncs.com/picker_examle_video.mp4")! @@ -102,7 +138,7 @@ class PickerResultViewController: UIViewController, UICollectionViewDataSource, localAssetArray.append(videoAsset) } - let networkVideoURL1 = URL.init(string: "http://tsnrhapp.oss-cn-hangzhou.aliyuncs.com/picker_examle_tiantaichuifeng.mp4")! + let networkVideoURL1 = URL.init(string: "https://sf1-ttcdn-tos.pstatp.com/obj/tos-cn-v-0004/471d1136b00141f5a9ddf81e461547fd")! let networkVideoAsset1 = PhotoAsset.init(networkVideoAsset: .init(videoURL: networkVideoURL1)) selectedAssets.append(networkVideoAsset1) localAssetArray.append(networkVideoAsset1) @@ -186,6 +222,50 @@ class PickerResultViewController: UIViewController, UICollectionViewDataSource, pickerConfigVC.config = config present(UINavigationController.init(rootViewController: pickerConfigVC), animated: true, completion: nil) } + @objc func didClearButtonClick() { + PhotoTools.removeCache() + ImageCache.default.clearCache() + } + func removeLocalPhotoAssetFile() { + if FileManager.default.fileExists(atPath: localURL.path) { + try? FileManager.default.removeItem(at: localURL) + } + } + @objc func didPublishBtnClick() { + removeLocalPhotoAssetFile() + dismiss(animated: true, completion: nil) + } + @objc func didCancelButtonClick() { + if selectedAssets.isEmpty { + removeLocalPhotoAssetFile() + dismiss(animated: true, completion: nil) + return + } + PhotoTools.showAlert(viewController: self, title: "是否将此次编辑保留?", message: nil, leftActionTitle: "不保留", leftHandler: { _ in + self.removeLocalPhotoAssetFile() + self.dismiss(animated: true, completion: nil) + }, rightActionTitle: "保留") { _ in + var datas: [Data] = [] + for photoAsset in self.selectedAssets { + if let data = photoAsset.encode() { + datas.append(data) + } + } + do { + if !FileManager.default.fileExists(atPath: self.localCachePath) { + try FileManager.default.createDirectory(atPath: self.localCachePath, withIntermediateDirectories: true, attributes: nil) + } + if FileManager.default.fileExists(atPath: self.localURL.path) { + try FileManager.default.removeItem(at: self.localURL) + } + let data = try JSONEncoder().encode(datas) + try data.write(to: self.localURL) + } catch { + print(error) + } + self.dismiss(animated: true, completion: nil) + } + } /// 跳转选择资源界面 @IBAction func selectButtonClick(_ sender: UIButton) { @@ -211,86 +291,30 @@ class PickerResultViewController: UIViewController, UICollectionViewDataSource, ProgressHUD.showWarning(addedTo: self.view, text: "请先选择资源", animated: true, delay: 1.5) return } - var count = 0 - for photoAsset in selectedAssets { - if photoAsset.mediaType == .photo { - if photoAsset.isNetworkAsset { - #if canImport(Kingfisher) - photoAsset.getNetworkImageURL { (url, isNetwork) in - count += 1 - print(isNetwork ? "网络图片:" : "编辑后的网络图片", url!) - if count == total { - ProgressHUD.hide(forView: self.view, animated: false) - ProgressHUD.showSuccess(addedTo: self.view, text: "获取完成", animated: true, delay: 1.5) - } - } - continue - #endif - } - if photoAsset.mediaSubType == .livePhoto { - var imageURL: URL? - var videoURL: URL? - AssetManager.requestLivePhoto(contentURL: photoAsset.phAsset!) { (url) in - imageURL = url - } videoHandler: { (url) in - videoURL = url - } completionHandler: { [weak self] (error) in - count += 1 - if error == nil { - let image = UIImage.init(contentsOfFile: imageURL!.path) - print("LivePhoto中的图片:\(String(describing: image!))") - print("LivePhoto中的视频地址:\(videoURL!)") - }else { - print("LivePhoto中的内容获取失败\(error!)") - } - if count == total { - ProgressHUD.hide(forView: self?.view, animated: false) - ProgressHUD.showSuccess(addedTo: self?.view, text: "获取完成", animated: true, delay: 1.5) - } - } - }else { - count += 1 - photoAsset.requestImageURL { [weak self] (imageURL) in - if imageURL != nil { - print("图片地址:\(imageURL!)") - }else { - print("图片地址获取失败") - } - if count == total { - ProgressHUD.hide(forView: self?.view, animated: false) - ProgressHUD.showSuccess(addedTo: self?.view, text: "获取完成", animated: true, delay: 1.5) - } - } -// print("图片:\(photoAsset.originalImage!)") -// if count == total { -// ProgressHUD.hide(forView: weakSelf?.navigationController?.view, animated: true) -// } - } - }else { - if photoAsset.isNetworkAsset { - photoAsset.getNetworkVideoURL { (videoURL, isNetwork) in - count += 1 - print(isNetwork ? "网络视频:" : "编辑后的网络视频", videoURL!) - if count == total { - ProgressHUD.hide(forView: self.view, animated: false) - ProgressHUD.showSuccess(addedTo: self.view, text: "获取完成", animated: true, delay: 1.5) - } - } - continue - } - photoAsset.requestVideoURL { [weak self] (videoURL) in - count += 1 - if videoURL == nil { - print("视频地址获取失败") - }else { - print("视频地址:\(videoURL!)") - } - if count == total { - ProgressHUD.hide(forView: self?.view, animated: false) - ProgressHUD.showSuccess(addedTo: self?.view, text: "获取完成", animated: true, delay: 1.5) - } + ProgressHUD.showLoading(addedTo: self.view, animated: true) + let result = PickerResult(photoAssets: selectedAssets, isOriginal: false) + result.getURLs { result, photoAsset, index in + print("第" + String(index + 1) + "个") + switch result { + case .success(let response): + if let livePhoto = response.livePhoto { + print("LivePhoto里的图片地址:", livePhoto.imageURL) + print("LivePhoto里的视频地址:", livePhoto.videoURL) + return } + print(response.urlType == .network ? + response.mediaType == .photo ? + "网络图片地址:" : "网络视频地址:" : + response.mediaType == .photo ? + "本地图片地址" : "本地视频地址", + response.url) + case .failure(let error): + print("地址获取失败", error) + break } + } completionHandler: { urls in + ProgressHUD.hide(forView: self.view, animated: false) + ProgressHUD.showSuccess(addedTo: self.view, text: "获取完成", animated: true, delay: 1.5) } } @@ -340,6 +364,9 @@ class PickerResultViewController: UIViewController, UICollectionViewDataSource, // modalPresentationStyle = .custom 会使用框架自带的动画效果 // 预览时可以重新初始化一个config设置单独的颜色或其他配置 let previewConfig = PhotoTools.getWXPickerConfig() + if preselect { + previewConfig.previewView.loadNetworkVideoMode = .play + } // 编辑器配置保持一致 previewConfig.photoEditor = config.photoEditor @@ -460,7 +487,7 @@ extension PickerResultViewController: PhotoPickerControllerDelegate { isOriginal = result.isOriginal collectionView.reloadData() updateCollectionViewHeight() - + // result.getImage { (image, photoAsset, index) in // if let image = image { // print("success", image) @@ -469,11 +496,6 @@ extension PickerResultViewController: PhotoPickerControllerDelegate { // } // } completionHandler: { (images) in // print(images) -// } -// result.getURLs { (url, isNetwork, index, type) in -// print(type == .photo ? isNetwork ? "网络图片:" : "图片:" : isNetwork ? "网络视频" : "视频:", url! , "index:" , index) -// } completionHandler: { (urls) in -// // } pickerController.dismiss(animated: true, completion: nil) } @@ -498,13 +520,82 @@ extension PickerResultViewController: PhotoPickerControllerDelegate { } } func pickerController(_ pickerController: PhotoPickerController, previewUpdateCurrentlyDisplayedAsset photoAsset: PhotoAsset, atIndex: Int) { - previewTitleLabel?.text = String(atIndex + 1) + "/" + String(selectedAssets.count) + if pickerController.isPreviewAsset { + previewTitleLabel?.text = String(atIndex + 1) + "/" + String(selectedAssets.count) + } } func pickerController(_ pickerController: PhotoPickerController, previewSingleClick photoAsset: PhotoAsset, atIndex: Int) { if pickerController.isPreviewAsset && photoAsset.mediaType == .photo { pickerController.dismiss(animated: true, completion: nil) } } + func pickerController(_ pickerController: PhotoPickerController, previewLongPressClick photoAsset: PhotoAsset, atIndex: Int) { + if pickerController.isPreviewAsset { + let alert = UIAlertController(title: "长按事件", message: nil, preferredStyle: .actionSheet) + alert.addAction(.init(title: "保存", style: .default, handler: { alertAction in + ProgressHUD.showLoading(addedTo: pickerController.view, animated: true) + func saveImage(_ image: UIImage) { + AssetManager.saveSystemAlbum(forImage: image) { phAsset in + if phAsset != nil { + ProgressHUD.showSuccess(addedTo: pickerController.view, text: "保存成功", animated: true, delay: 1.5) + }else { + ProgressHUD.showWarning(addedTo: pickerController.view, text: "保存失败", animated: true, delay: 1.5) + } + } + } + func saveVideo(_ videoURL: URL) { + AssetManager.saveSystemAlbum(forVideoURL: videoURL) { phAsset in + if phAsset != nil { + ProgressHUD.showSuccess(addedTo: pickerController.view, text: "保存成功", animated: true, delay: 1.5) + }else { + ProgressHUD.showWarning(addedTo: pickerController.view, text: "保存失败", animated: true, delay: 1.5) + } + } + } + photoAsset.getAssetURL { result in + switch result { + case .success(let response): + if response.mediaType == .photo { + if response.urlType == .network { + PhotoTools.downloadNetworkImage(with: response.url, options: [], completionHandler: { image in + ProgressHUD.hide(forView: pickerController.view, animated: true) + if let image = image { + saveImage(image) + }else { + ProgressHUD.showWarning(addedTo: pickerController.view, text: "保存失败", animated: true, delay: 1.5) + } + }) + }else { + let image = UIImage(contentsOfFile: response.url.path)! + saveImage(image) + } + }else { + if response.urlType == .network { + PhotoManager.shared.downloadTask(with: response.url, progress: nil) { videoURL, error, _ in + ProgressHUD.hide(forView: pickerController.view, animated: true) + if let videoURL = videoURL { + saveVideo(videoURL) + }else { + ProgressHUD.showWarning(addedTo: pickerController.view, text: "保存失败", animated: true, delay: 1.5) + } + } + }else { + saveVideo(response.url) + } + } + case .failure(_): + ProgressHUD.hide(forView: pickerController.view, animated: true) + ProgressHUD.showWarning(addedTo: pickerController.view, text: "保存失败", animated: true, delay: 1.5) + } + } + })) + alert.addAction(.init(title: "删除", style: .destructive, handler: { alertAction in + pickerController.deleteCurrentPreviewPhotoAsset() + })) + alert.addAction(.init(title: "取消", style: .cancel, handler: nil)) + pickerController.present(alert, animated: true, completion: nil) + } + } func pickerController(_ pickerController: PhotoPickerController, previewDidDeleteAsset photoAsset: PhotoAsset, atIndex: Int) { let isFull = selectedAssets.count == config.maximumSelectedCount selectedAssets.remove(at: atIndex) @@ -536,48 +627,84 @@ extension PickerResultViewController: PhotoPickerControllerDelegate { } } } - + func pickerController(_ pickerController: PhotoPickerController, loadTitleChartlet photoEditorViewController: PhotoEditorViewController, response: @escaping ([EditorChartlet]) -> Void) { + // 模仿延迟加加载数据 + DispatchQueue.main.asyncAfter(deadline: .now() + 1) { + var titles = PhotoTools.defaultTitleChartlet() + let localTitleChartlet = EditorChartlet(image: UIImage(named: "hx_sticker_cover")) + titles.append(localTitleChartlet) + response(titles) + } + } + func pickerController(_ pickerController: PhotoPickerController, loadChartletList photoEditorViewController: PhotoEditorViewController, titleChartlet: EditorChartlet, titleIndex: Int, response: @escaping (Int, [EditorChartlet]) -> Void) { + if titleIndex == 0 { + response(titleIndex, PhotoTools.defaultNetworkChartlet()) + }else { + let chartlet1 = EditorChartlet(image: UIImage(named: "hx_sticker_chongya")) + let chartlet2 = EditorChartlet(image: UIImage(named: "hx_sticker_haoxinqing")) + let chartlet3 = EditorChartlet(image: UIImage(named: "hx_sticker_housailei")) + let chartlet4 = EditorChartlet(image: UIImage(named: "hx_sticker_jintianfenkeai")) + let chartlet5 = EditorChartlet(image: UIImage(named: "hx_sticker_keaibiaoq")) + let chartlet6 = EditorChartlet(image: UIImage(named: "hx_sticker_kehaixing")) + let chartlet7 = EditorChartlet(image: UIImage(named: "hx_sticker_saihong")) + let chartlet8 = EditorChartlet(image: UIImage(named: "hx_sticker_wow")) + let chartlet9 = EditorChartlet(image: UIImage(named: "hx_sticker_woxiangfazipai")) + let chartlet10 = EditorChartlet(image: UIImage(named: "hx_sticker_xiaochuzhujiao")) + let chartlet11 = EditorChartlet(image: UIImage(named: "hx_sticker_yuanqimanman")) + let chartlet12 = EditorChartlet(image: UIImage(named: "hx_sticker_yuanqishaonv")) + let chartlet13 = EditorChartlet(image: UIImage(named: "hx_sticker_zaizaijia")) + response(titleIndex, [chartlet1, chartlet2, chartlet3, chartlet4, chartlet5, chartlet6, chartlet7, chartlet8, chartlet9, chartlet10, chartlet11, chartlet12, chartlet13]) + } + } func pickerController(_ pickerController: PhotoPickerController, videoEditor videoEditorViewController: VideoEditorViewController, loadMusic completionHandler: @escaping ([VideoEditorMusicInfo]) -> Void) -> Bool { var musics: [VideoEditorMusicInfo] = [] let audioUrl1 = Bundle.main.url(forResource: "天外来物", withExtension: "mp3")! let lyricUrl1 = Bundle.main.url(forResource: "天外来物", withExtension: nil)! - let music1 = VideoEditorMusicInfo.init(audioPath: audioUrl1.path, - lrcPath: lyricUrl1.path) + let lrc1 = try! String(contentsOfFile: lyricUrl1.path) + let music1 = VideoEditorMusicInfo.init(audioURL: audioUrl1, + lrc: lrc1) musics.append(music1) let audioUrl2 = Bundle.main.url(forResource: "嘉宾", withExtension: "mp3")! let lyricUrl2 = Bundle.main.url(forResource: "嘉宾", withExtension: nil)! - let music2 = VideoEditorMusicInfo.init(audioPath: audioUrl2.path, - lrcPath: lyricUrl2.path) + let lrc2 = try! String(contentsOfFile: lyricUrl2.path) + let music2 = VideoEditorMusicInfo.init(audioURL: audioUrl2, + lrc: lrc2) musics.append(music2) let audioUrl3 = Bundle.main.url(forResource: "少女的祈祷", withExtension: "mp3")! let lyricUrl3 = Bundle.main.url(forResource: "少女的祈祷", withExtension: nil)! - let music3 = VideoEditorMusicInfo.init(audioPath: audioUrl3.path, - lrcPath: lyricUrl3.path) + let lrc3 = try! String(contentsOfFile: lyricUrl3.path) + let music3 = VideoEditorMusicInfo.init(audioURL: audioUrl3, + lrc: lrc3) musics.append(music3) let audioUrl4 = Bundle.main.url(forResource: "野孩子", withExtension: "mp3")! let lyricUrl4 = Bundle.main.url(forResource: "野孩子", withExtension: nil)! - let music4 = VideoEditorMusicInfo.init(audioPath: audioUrl4.path, - lrcPath: lyricUrl4.path) + let lrc4 = try! String(contentsOfFile: lyricUrl4.path) + let music4 = VideoEditorMusicInfo.init(audioURL: audioUrl4, + lrc: lrc4) musics.append(music4) let audioUrl5 = Bundle.main.url(forResource: "无赖", withExtension: "mp3")! let lyricUrl5 = Bundle.main.url(forResource: "无赖", withExtension: nil)! - let music5 = VideoEditorMusicInfo.init(audioPath: audioUrl5.path, - lrcPath: lyricUrl5.path) + let lrc5 = try! String(contentsOfFile: lyricUrl5.path) + let music5 = VideoEditorMusicInfo.init(audioURL: audioUrl5, + lrc: lrc5) musics.append(music5) let audioUrl6 = Bundle.main.url(forResource: "时光正好", withExtension: "mp3")! let lyricUrl6 = Bundle.main.url(forResource: "时光正好", withExtension: nil)! - let music6 = VideoEditorMusicInfo.init(audioPath: audioUrl6.path, - lrcPath: lyricUrl6.path) + let lrc6 = try! String(contentsOfFile: lyricUrl6.path) + let music6 = VideoEditorMusicInfo.init(audioURL: audioUrl6, + lrc: lrc6) musics.append(music6) let audioUrl7 = Bundle.main.url(forResource: "世间美好与你环环相扣", withExtension: "mp3")! let lyricUrl7 = Bundle.main.url(forResource: "世间美好与你环环相扣", withExtension: nil)! - let music7 = VideoEditorMusicInfo.init(audioPath: audioUrl7.path, - lrcPath: lyricUrl7.path) + let lrc7 = try! String(contentsOfFile: lyricUrl7.path) + let music7 = VideoEditorMusicInfo.init(audioURL: audioUrl7, + lrc: lrc7) musics.append(music7) let audioUrl8 = Bundle.main.url(forResource: "爱你", withExtension: "mp3")! let lyricUrl8 = Bundle.main.url(forResource: "爱你", withExtension: nil)! - let music8 = VideoEditorMusicInfo.init(audioPath: audioUrl8.path, - lrcPath: lyricUrl8.path) + let lrc8 = try! String(contentsOfFile: lyricUrl8.path) + let music8 = VideoEditorMusicInfo.init(audioURL: audioUrl8, + lrc: lrc8) musics.append(music8) completionHandler(musics) return false @@ -605,6 +732,12 @@ class ResultViewCell: PhotoPickerViewCell { deleteButton.addTarget(self, action: #selector(didDeleteButtonClick), for: .touchUpInside) return deleteButton }() + override var photoAsset: PhotoAsset! { + didSet { + // 隐藏被编辑过的标示 + assetEditMarkIcon.isHidden = true + } + } override func requestThumbnailImage() { // 因为这里的cell不会很多,重新设置 targetWidth,使图片更加清晰 super.requestThumbnailImage(targetWidth: width * UIScreen.main.scale) diff --git a/Swift/Classes/Controller/WeChatMometViewController.swift b/Swift/Classes/Controller/WeChatMometViewController.swift new file mode 100644 index 00000000..194abd5e --- /dev/null +++ b/Swift/Classes/Controller/WeChatMometViewController.swift @@ -0,0 +1,98 @@ +// +// WeChatMometViewController.swift +// Example +// +// Created by Slience on 2021/7/28. +// + +import UIKit +import HXPHPicker + +class WeChatMometViewController: UIViewController, PhotoPickerControllerDelegate { + var isImage = false + lazy var imageView: UIImageView = { + let view = UIImageView(image: .init(named: "wx_head_icon")) + view.contentMode = .scaleAspectFill + view.clipsToBounds = true + view.isUserInteractionEnabled = true + view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(didImageViewClick))) + view.backgroundColor = .systemYellow + return view + }() + @objc func didImageViewClick() { + isImage = true + let config = PhotoTools.getWXPickerConfig(isMoment: true) + config.selectOptions = .photo + config.selectMode = .single + config.photoSelectionTapAction = .openEditor + config.photoEditor.cropping.aspectRatioType = .ratio_1x1 + config.photoEditor.cropping.fixedRatio = true + config.photoEditor.fixedCropState = true + + let pickerController = PhotoPickerController( + picker: config, + delegate: self + ) + + present(pickerController, animated: true, completion: nil) + } + + func pickerController(_ pickerController: PhotoPickerController, + didFinishSelection result: PickerResult) { + if isImage { + imageView.image = result.photoAssets.first?.originalImage + }else { + pickerController.dismiss(animated: true) { + let vc = PickerResultViewController() + vc.isPublish = true + vc.selectedAssets = result.photoAssets + vc.isOriginal = result.isOriginal + let nav = UINavigationController(rootViewController: vc) + nav.modalPresentationStyle = .fullScreen + self.present(nav, animated: true, completion: nil) + } + } + } + func pickerController(didCancel pickerController: PhotoPickerController) { + pickerController.dismiss(animated: true, completion: nil) + } + var localCachePath: String { + var cachePath = PhotoTools.getSystemCacheFolderPath() + cachePath.append(contentsOf: "/com.silence.WeChat_Moment") + return cachePath + } + var localURL: URL { + var cachePath = localCachePath + cachePath.append(contentsOf: "/PhotoAssets") + return URL.init(fileURLWithPath: cachePath) + } + + override func viewDidLoad() { + super.viewDidLoad() + title = "Moment" + view.backgroundColor = .white + view.addSubview(imageView) + navigationItem.rightBarButtonItem = UIBarButtonItem(image: UIImage(named: "camera_overturn"), style: .done, target: self, action: #selector(didPublishClick)) + } + + @objc func didPublishClick() { + if FileManager.default.fileExists(atPath: localURL.path) { + let vc = PickerResultViewController() + vc.isPublish = true + let nav = UINavigationController(rootViewController: vc) + nav.modalPresentationStyle = .fullScreen + self.present(nav, animated: true, completion: nil) + return + } + isImage = false + let config = PhotoTools.getWXPickerConfig(isMoment: true) + config.maximumSelectedVideoDuration = 60 + let pickerController = PhotoPickerController(picker: config, delegate: self) + pickerController.autoDismiss = false + present(pickerController, animated: true, completion: nil) + } + override func viewDidLayoutSubviews() { + super.viewDidLayoutSubviews() + imageView.frame = CGRect(x: 0, y: navigationController?.navigationBar.frame.maxY ?? 0, width: view.width, height: view.width) + } +} diff --git a/Swift/Reachability.swift b/Swift/Reachability.swift new file mode 100644 index 00000000..2f693736 --- /dev/null +++ b/Swift/Reachability.swift @@ -0,0 +1,405 @@ +/* +Copyright (c) 2014, Ashley Mills +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + +import SystemConfiguration +import Foundation + +public enum ReachabilityError: Error { + case failedToCreateWithAddress(sockaddr, Int32) + case failedToCreateWithHostname(String, Int32) + case unableToSetCallback(Int32) + case unableToSetDispatchQueue(Int32) + case unableToGetFlags(Int32) +} + +@available(*, unavailable, renamed: "Notification.Name.reachabilityChanged") +public let ReachabilityChangedNotification = NSNotification.Name("ReachabilityChangedNotification") + +public extension Notification.Name { + static let reachabilityChanged = Notification.Name("reachabilityChanged") +} + +public class Reachability { + + public typealias NetworkReachable = (Reachability) -> () + public typealias NetworkUnreachable = (Reachability) -> () + + @available(*, unavailable, renamed: "Connection") + public enum NetworkStatus: CustomStringConvertible { + case notReachable, reachableViaWiFi, reachableViaWWAN + public var description: String { + switch self { + case .reachableViaWWAN: return "Cellular" + case .reachableViaWiFi: return "WiFi" + case .notReachable: return "No Connection" + } + } + } + + public enum Connection: CustomStringConvertible { + case unavailable, wifi, cellular + public var description: String { + switch self { + case .cellular: return "Cellular" + case .wifi: return "WiFi" + case .unavailable: return "No Connection" + } + } + + @available(*, deprecated, renamed: "unavailable") + public static let none: Connection = .unavailable + } + + public var whenReachable: NetworkReachable? + public var whenUnreachable: NetworkUnreachable? + + @available(*, deprecated, renamed: "allowsCellularConnection") + public let reachableOnWWAN: Bool = true + + /// Set to `false` to force Reachability.connection to .none when on cellular connection (default value `true`) + public var allowsCellularConnection: Bool + + // The notification center on which "reachability changed" events are being posted + public var notificationCenter: NotificationCenter = NotificationCenter.default + + @available(*, deprecated, renamed: "connection.description") + public var currentReachabilityString: String { + return "\(connection)" + } + + @available(*, unavailable, renamed: "connection") + public var currentReachabilityStatus: Connection { + return connection + } + + public var connection: Connection { + if flags == nil { + try? setReachabilityFlags() + } + + switch flags?.connection { + case .unavailable?, nil: return .unavailable + case .cellular?: return allowsCellularConnection ? .cellular : .unavailable + case .wifi?: return .wifi + } + } + + fileprivate var isRunningOnDevice: Bool = { + #if targetEnvironment(simulator) + return false + #else + return true + #endif + }() + + fileprivate(set) var notifierRunning = false + fileprivate let reachabilityRef: SCNetworkReachability + fileprivate let reachabilitySerialQueue: DispatchQueue + fileprivate let notificationQueue: DispatchQueue? + fileprivate(set) var flags: SCNetworkReachabilityFlags? { + didSet { + guard flags != oldValue else { return } + notifyReachabilityChanged() + } + } + + required public init(reachabilityRef: SCNetworkReachability, + queueQoS: DispatchQoS = .default, + targetQueue: DispatchQueue? = nil, + notificationQueue: DispatchQueue? = .main) { + self.allowsCellularConnection = true + self.reachabilityRef = reachabilityRef + self.reachabilitySerialQueue = DispatchQueue(label: "uk.co.ashleymills.reachability", qos: queueQoS, target: targetQueue) + self.notificationQueue = notificationQueue + } + + public convenience init(hostname: String, + queueQoS: DispatchQoS = .default, + targetQueue: DispatchQueue? = nil, + notificationQueue: DispatchQueue? = .main) throws { + guard let ref = SCNetworkReachabilityCreateWithName(nil, hostname) else { + throw ReachabilityError.failedToCreateWithHostname(hostname, SCError()) + } + self.init(reachabilityRef: ref, queueQoS: queueQoS, targetQueue: targetQueue, notificationQueue: notificationQueue) + } + + public convenience init(queueQoS: DispatchQoS = .default, + targetQueue: DispatchQueue? = nil, + notificationQueue: DispatchQueue? = .main) throws { + var zeroAddress = sockaddr() + zeroAddress.sa_len = UInt8(MemoryLayout.size) + zeroAddress.sa_family = sa_family_t(AF_INET) + + guard let ref = SCNetworkReachabilityCreateWithAddress(nil, &zeroAddress) else { + throw ReachabilityError.failedToCreateWithAddress(zeroAddress, SCError()) + } + + self.init(reachabilityRef: ref, queueQoS: queueQoS, targetQueue: targetQueue, notificationQueue: notificationQueue) + } + + deinit { + stopNotifier() + } +} + +public extension Reachability { + + // MARK: - *** Notifier methods *** + func startNotifier() throws { + guard !notifierRunning else { return } + + let callback: SCNetworkReachabilityCallBack = { (reachability, flags, info) in + guard let info = info else { return } + + // `weakifiedReachability` is guaranteed to exist by virtue of our + // retain/release callbacks which we provided to the `SCNetworkReachabilityContext`. + let weakifiedReachability = Unmanaged.fromOpaque(info).takeUnretainedValue() + + // The weak `reachability` _may_ no longer exist if the `Reachability` + // object has since been deallocated but a callback was already in flight. + weakifiedReachability.reachability?.flags = flags + } + + let weakifiedReachability = ReachabilityWeakifier(reachability: self) + let opaqueWeakifiedReachability = Unmanaged.passUnretained(weakifiedReachability).toOpaque() + + var context = SCNetworkReachabilityContext( + version: 0, + info: UnsafeMutableRawPointer(opaqueWeakifiedReachability), + retain: { (info: UnsafeRawPointer) -> UnsafeRawPointer in + let unmanagedWeakifiedReachability = Unmanaged.fromOpaque(info) + _ = unmanagedWeakifiedReachability.retain() + return UnsafeRawPointer(unmanagedWeakifiedReachability.toOpaque()) + }, + release: { (info: UnsafeRawPointer) -> Void in + let unmanagedWeakifiedReachability = Unmanaged.fromOpaque(info) + unmanagedWeakifiedReachability.release() + }, + copyDescription: { (info: UnsafeRawPointer) -> Unmanaged in + let unmanagedWeakifiedReachability = Unmanaged.fromOpaque(info) + let weakifiedReachability = unmanagedWeakifiedReachability.takeUnretainedValue() + let description = weakifiedReachability.reachability?.description ?? "nil" + return Unmanaged.passRetained(description as CFString) + } + ) + + if !SCNetworkReachabilitySetCallback(reachabilityRef, callback, &context) { + stopNotifier() + throw ReachabilityError.unableToSetCallback(SCError()) + } + + if !SCNetworkReachabilitySetDispatchQueue(reachabilityRef, reachabilitySerialQueue) { + stopNotifier() + throw ReachabilityError.unableToSetDispatchQueue(SCError()) + } + + // Perform an initial check + try setReachabilityFlags() + + notifierRunning = true + } + + func stopNotifier() { + defer { notifierRunning = false } + + SCNetworkReachabilitySetCallback(reachabilityRef, nil, nil) + SCNetworkReachabilitySetDispatchQueue(reachabilityRef, nil) + } + + // MARK: - *** Connection test methods *** + @available(*, deprecated, message: "Please use `connection != .none`") + var isReachable: Bool { + return connection != .unavailable + } + + @available(*, deprecated, message: "Please use `connection == .cellular`") + var isReachableViaWWAN: Bool { + // Check we're not on the simulator, we're REACHABLE and check we're on WWAN + return connection == .cellular + } + + @available(*, deprecated, message: "Please use `connection == .wifi`") + var isReachableViaWiFi: Bool { + return connection == .wifi + } + + var description: String { + return flags?.description ?? "unavailable flags" + } +} + +fileprivate extension Reachability { + + func setReachabilityFlags() throws { + try reachabilitySerialQueue.sync { [unowned self] in + var flags = SCNetworkReachabilityFlags() + if !SCNetworkReachabilityGetFlags(self.reachabilityRef, &flags) { + self.stopNotifier() + throw ReachabilityError.unableToGetFlags(SCError()) + } + + self.flags = flags + } + } + + + func notifyReachabilityChanged() { + let notify = { [weak self] in + guard let self = self else { return } + self.connection != .unavailable ? self.whenReachable?(self) : self.whenUnreachable?(self) + self.notificationCenter.post(name: .reachabilityChanged, object: self) + } + + // notify on the configured `notificationQueue`, or the caller's (i.e. `reachabilitySerialQueue`) + notificationQueue?.async(execute: notify) ?? notify() + } +} + +extension SCNetworkReachabilityFlags { + + typealias Connection = Reachability.Connection + + var connection: Connection { + guard isReachableFlagSet else { return .unavailable } + + // If we're reachable, but not on an iOS device (i.e. simulator), we must be on WiFi + #if targetEnvironment(simulator) + return .wifi + #else + var connection = Connection.unavailable + + if !isConnectionRequiredFlagSet { + connection = .wifi + } + + if isConnectionOnTrafficOrDemandFlagSet { + if !isInterventionRequiredFlagSet { + connection = .wifi + } + } + + if isOnWWANFlagSet { + connection = .cellular + } + + return connection + #endif + } + + var isOnWWANFlagSet: Bool { + #if os(iOS) + return contains(.isWWAN) + #else + return false + #endif + } + var isReachableFlagSet: Bool { + return contains(.reachable) + } + var isConnectionRequiredFlagSet: Bool { + return contains(.connectionRequired) + } + var isInterventionRequiredFlagSet: Bool { + return contains(.interventionRequired) + } + var isConnectionOnTrafficFlagSet: Bool { + return contains(.connectionOnTraffic) + } + var isConnectionOnDemandFlagSet: Bool { + return contains(.connectionOnDemand) + } + var isConnectionOnTrafficOrDemandFlagSet: Bool { + return !intersection([.connectionOnTraffic, .connectionOnDemand]).isEmpty + } + var isTransientConnectionFlagSet: Bool { + return contains(.transientConnection) + } + var isLocalAddressFlagSet: Bool { + return contains(.isLocalAddress) + } + var isDirectFlagSet: Bool { + return contains(.isDirect) + } + var isConnectionRequiredAndTransientFlagSet: Bool { + return intersection([.connectionRequired, .transientConnection]) == [.connectionRequired, .transientConnection] + } + + var description: String { + let W = isOnWWANFlagSet ? "W" : "-" + let R = isReachableFlagSet ? "R" : "-" + let c = isConnectionRequiredFlagSet ? "c" : "-" + let t = isTransientConnectionFlagSet ? "t" : "-" + let i = isInterventionRequiredFlagSet ? "i" : "-" + let C = isConnectionOnTrafficFlagSet ? "C" : "-" + let D = isConnectionOnDemandFlagSet ? "D" : "-" + let l = isLocalAddressFlagSet ? "l" : "-" + let d = isDirectFlagSet ? "d" : "-" + + return "\(W)\(R) \(c)\(t)\(i)\(C)\(D)\(l)\(d)" + } +} + +/** + `ReachabilityWeakifier` weakly wraps the `Reachability` class + in order to break retain cycles when interacting with CoreFoundation. + + CoreFoundation callbacks expect a pair of retain/release whenever an + opaque `info` parameter is provided. These callbacks exist to guard + against memory management race conditions when invoking the callbacks. + + #### Race Condition + + If we passed `SCNetworkReachabilitySetCallback` a direct reference to our + `Reachability` class without also providing corresponding retain/release + callbacks, then a race condition can lead to crashes when: + - `Reachability` is deallocated on thread X + - A `SCNetworkReachability` callback(s) is already in flight on thread Y + + #### Retain Cycle + + If we pass `Reachability` to CoreFoundtion while also providing retain/ + release callbacks, we would create a retain cycle once CoreFoundation + retains our `Reachability` class. This fixes the crashes and his how + CoreFoundation expects the API to be used, but doesn't play nicely with + Swift/ARC. This cycle would only be broken after manually calling + `stopNotifier()` — `deinit` would never be called. + + #### ReachabilityWeakifier + + By providing both retain/release callbacks and wrapping `Reachability` in + a weak wrapper, we: + - interact correctly with CoreFoundation, thereby avoiding a crash. + See "Memory Management Programming Guide for Core Foundation". + - don't alter the public API of `Reachability.swift` in any way + - still allow for automatic stopping of the notifier on `deinit`. + */ +private class ReachabilityWeakifier { + weak var reachability: Reachability? + init(reachability: Reachability) { + self.reachability = reachability + } +}