mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-23 22:55:00 +00:00
Various improvements
This commit is contained in:
@@ -161,6 +161,7 @@ public final class MediaPickerScreenImpl: ViewController, MediaPickerScreen, Att
|
||||
case story
|
||||
case addImage
|
||||
case createSticker
|
||||
case createAvatar
|
||||
}
|
||||
|
||||
case assets(PHAssetCollection?, AssetsMode)
|
||||
@@ -183,8 +184,11 @@ public final class MediaPickerScreenImpl: ViewController, MediaPickerScreen, Att
|
||||
private let canBoostToUnrestrict: Bool
|
||||
fileprivate let paidMediaAllowed: Bool
|
||||
private let subject: Subject
|
||||
fileprivate let forCollage: Bool
|
||||
private let saveEditedPhotos: Bool
|
||||
|
||||
private var explicitMultipleSelection = false
|
||||
|
||||
private let titleView: MediaPickerTitleView
|
||||
private let cancelButtonNode: WebAppCancelButtonNode
|
||||
private let moreButtonNode: MoreButtonNode
|
||||
@@ -203,6 +207,7 @@ public final class MediaPickerScreenImpl: ViewController, MediaPickerScreen, Att
|
||||
|
||||
public var createFromScratch: () -> Void = {}
|
||||
public var presentFilePicker: () -> Void = {}
|
||||
public var openAvatarEditor: () -> Void = {}
|
||||
|
||||
private var completed = false
|
||||
public var legacyCompletion: (_ signals: [Any], _ silently: Bool, _ scheduleTime: Int32?, ChatSendMessageActionSheetController.SendParameters?, @escaping (String) -> UIView?, @escaping () -> Void) -> Void = { _, _, _, _, _, _ in }
|
||||
@@ -260,6 +265,8 @@ public final class MediaPickerScreenImpl: ViewController, MediaPickerScreen, Att
|
||||
fileprivate var modernCameraView: CameraSimplePreviewView?
|
||||
fileprivate var modernCameraTapGestureRecognizer: UITapGestureRecognizer?
|
||||
|
||||
fileprivate var avatarEditorPreviewView: AvatarEditorPreviewView?
|
||||
|
||||
private var cameraActivateAreaNode: AccessibilityAreaNode
|
||||
private var placeholderNode: MediaPickerPlaceholderNode?
|
||||
private var manageNode: MediaPickerManageNode?
|
||||
@@ -271,7 +278,7 @@ public final class MediaPickerScreenImpl: ViewController, MediaPickerScreen, Att
|
||||
private var nextStableId: Int = 1
|
||||
private var currentEntries: [MediaPickerGridEntry] = []
|
||||
private var enqueuedTransactions: [MediaPickerGridTransaction] = []
|
||||
private var state: State?
|
||||
fileprivate var state: State?
|
||||
|
||||
private var preloadPromise = ValuePromise<Bool>(true)
|
||||
|
||||
@@ -515,7 +522,7 @@ public final class MediaPickerScreenImpl: ViewController, MediaPickerScreen, Att
|
||||
self.gridNode.scrollView.alwaysBounceVertical = true
|
||||
self.gridNode.scrollView.showsVerticalScrollIndicator = false
|
||||
|
||||
if case let .assets(_, mode) = controller.subject, [.wallpaper, .story, .addImage, .createSticker].contains(mode) {
|
||||
if case let .assets(_, mode) = controller.subject, [.wallpaper, .story, .addImage, .createSticker, .createAvatar].contains(mode) {
|
||||
|
||||
} else {
|
||||
let selectionGesture = MediaPickerGridSelectionGesture<TGMediaSelectableItem>()
|
||||
@@ -602,7 +609,24 @@ public final class MediaPickerScreenImpl: ViewController, MediaPickerScreen, Att
|
||||
}
|
||||
})
|
||||
|
||||
if let controller = self.controller, case .assets(nil, .default) = controller.subject {
|
||||
if case .assets(nil, .createAvatar) = controller.subject {
|
||||
let avatarEditorPreviewView = AvatarEditorPreviewView(context: controller.context)
|
||||
avatarEditorPreviewView.tapped = { [weak self] in
|
||||
self?.controller?.openAvatarEditor()
|
||||
}
|
||||
self.gridNode.view.addSubview(avatarEditorPreviewView)
|
||||
self.avatarEditorPreviewView = avatarEditorPreviewView
|
||||
}
|
||||
|
||||
var useLegacyCamera = false
|
||||
var useModernCamera = false
|
||||
if case .assets(nil, .default) = controller.subject {
|
||||
useLegacyCamera = true
|
||||
} else if case .assets(nil, let mode) = controller.subject, [.createSticker, .createAvatar].contains(mode) {
|
||||
useModernCamera = true
|
||||
}
|
||||
|
||||
if useLegacyCamera {
|
||||
let enableAnimations = self.controller?.context.sharedContext.energyUsageSettings.fullTranslucency ?? true
|
||||
|
||||
let cameraView = TGAttachmentCameraView(forSelfPortrait: false, videoModeByDefault: controller.bannedSendPhotos != nil && controller.bannedSendVideos == nil)!
|
||||
@@ -626,9 +650,14 @@ public final class MediaPickerScreenImpl: ViewController, MediaPickerScreen, Att
|
||||
|
||||
self.gridNode.scrollView.addSubview(cameraView)
|
||||
self.gridNode.addSubnode(self.cameraActivateAreaNode)
|
||||
} else if let controller = self.controller, case .assets(nil, .createSticker) = controller.subject, !Camera.isIpad {
|
||||
} else if useModernCamera, !Camera.isIpad {
|
||||
var cameraPosition: Camera.Position = .back
|
||||
if case .assets(nil, .createAvatar) = controller.subject {
|
||||
cameraPosition = .front
|
||||
}
|
||||
|
||||
let cameraPreviewView = CameraSimplePreviewView(frame: .zero, main: true)
|
||||
cameraPreviewView.resetPlaceholder(front: false)
|
||||
cameraPreviewView.resetPlaceholder(front: cameraPosition == .front)
|
||||
self.modernCameraView = cameraPreviewView
|
||||
|
||||
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.cameraTapped))
|
||||
@@ -650,21 +679,30 @@ public final class MediaPickerScreenImpl: ViewController, MediaPickerScreen, Att
|
||||
|
||||
self.cameraWrapperView.addSubview(cameraPreviewView)
|
||||
|
||||
let camera = Camera(
|
||||
configuration: Camera.Configuration(
|
||||
preset: .hd1920x1080,
|
||||
position: .back,
|
||||
isDualEnabled: false,
|
||||
audio: false,
|
||||
photo: true,
|
||||
metadata: false
|
||||
),
|
||||
previewView: cameraPreviewView,
|
||||
secondaryPreviewView: nil
|
||||
)
|
||||
self.modernCamera = camera
|
||||
let setupCamera = {
|
||||
let camera = Camera(
|
||||
configuration: Camera.Configuration(
|
||||
preset: .hd1920x1080,
|
||||
position: cameraPosition,
|
||||
isDualEnabled: false,
|
||||
audio: false,
|
||||
photo: true,
|
||||
metadata: false
|
||||
),
|
||||
previewView: cameraPreviewView,
|
||||
secondaryPreviewView: nil
|
||||
)
|
||||
self.modernCamera = camera
|
||||
camera.startCapture()
|
||||
}
|
||||
|
||||
camera.startCapture()
|
||||
if case .assets(nil, .createAvatar) = controller.subject {
|
||||
Queue.mainQueue().after(0.4, {
|
||||
setupCamera()
|
||||
})
|
||||
} else {
|
||||
setupCamera()
|
||||
}
|
||||
} else {
|
||||
self.containerNode.clipsToBounds = true
|
||||
}
|
||||
@@ -767,7 +805,7 @@ public final class MediaPickerScreenImpl: ViewController, MediaPickerScreen, Att
|
||||
}
|
||||
|
||||
fileprivate var resetOnUpdate = false
|
||||
private func updateState(_ state: State) {
|
||||
fileprivate func updateState(_ state: State) {
|
||||
guard let controller = self.controller, let interaction = controller.interaction else {
|
||||
return
|
||||
}
|
||||
@@ -783,7 +821,7 @@ public final class MediaPickerScreenImpl: ViewController, MediaPickerScreen, Att
|
||||
var stories = false
|
||||
var selectable = true
|
||||
if case let .assets(_, mode) = controller.subject, mode != .default {
|
||||
selectable = false
|
||||
selectable = controller.explicitMultipleSelection
|
||||
if mode == .story {
|
||||
stories = true
|
||||
}
|
||||
@@ -1114,6 +1152,15 @@ public final class MediaPickerScreenImpl: ViewController, MediaPickerScreen, Att
|
||||
Queue.mainQueue().justDispatch {
|
||||
self.dismissInput()
|
||||
}
|
||||
|
||||
if controller.explicitMultipleSelection {
|
||||
let asset = fetchResult[index]
|
||||
if let selectableItem = TGMediaAsset(phAsset: asset), let selectionContext = interaction.selectionState {
|
||||
let value = !selectionContext.isIdentifierSelected(selectableItem.uniqueIdentifier)
|
||||
let _ = interaction.toggleSelection(selectableItem, value, false)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if let customSelection = controller.customSelection {
|
||||
self.openingMedia = true
|
||||
@@ -1489,11 +1536,15 @@ public final class MediaPickerScreenImpl: ViewController, MediaPickerScreen, Att
|
||||
let itemSpacing: CGFloat = 1.0
|
||||
let itemWidth = floorToScreenPixels((width - itemSpacing * CGFloat(itemsPerRow - 1)) / CGFloat(itemsPerRow))
|
||||
|
||||
var cutoutRect: CGRect?
|
||||
var cameraRect: CGRect? = CGRect(origin: CGPoint(x: layout.safeInsets.left, y: 0.0), size: CGSize(width: itemWidth, height: itemWidth * 2.0 + 1.0))
|
||||
if case .assets(nil, .createAvatar) = controller.subject {
|
||||
cameraRect = CGRect(origin: CGPoint(x: layout.safeInsets.left, y: 0.0), size: CGSize(width: itemWidth, height: itemWidth))
|
||||
}
|
||||
if self.cameraView == nil && self.modernCameraView == nil {
|
||||
cameraRect = nil
|
||||
}
|
||||
|
||||
|
||||
var manageHeight: CGFloat = 0.0
|
||||
if case let .assets(_, _, _, mediaAccess, cameraAccess) = self.state {
|
||||
if cameraAccess == nil {
|
||||
@@ -1578,7 +1629,7 @@ public final class MediaPickerScreenImpl: ViewController, MediaPickerScreen, Att
|
||||
} else {
|
||||
cameraRect = nil
|
||||
}
|
||||
|
||||
|
||||
let cleanGridInsets = UIEdgeInsets(top: insets.top, left: layout.safeInsets.left, bottom: layout.intrinsicInsets.bottom, right: layout.safeInsets.right)
|
||||
let gridInsets = UIEdgeInsets(top: insets.top + manageHeight, left: layout.safeInsets.left, bottom: layout.intrinsicInsets.bottom, right: layout.safeInsets.right)
|
||||
transition.updateFrame(node: self.gridNode, frame: innerBounds)
|
||||
@@ -1589,13 +1640,17 @@ public final class MediaPickerScreenImpl: ViewController, MediaPickerScreen, Att
|
||||
|
||||
transition.updateFrame(node: self.containerNode, frame: CGRect(origin: CGPoint(), size: CGSize(width: bounds.width, height: bounds.height)))
|
||||
|
||||
cutoutRect = cameraRect
|
||||
if let _ = self.avatarEditorPreviewView {
|
||||
cutoutRect = CGRect(origin: CGPoint(x: layout.safeInsets.left, y: 0.0), size: CGSize(width: cameraRect != nil ? itemWidth * 2.0 : itemWidth, height: itemWidth))
|
||||
}
|
||||
|
||||
var itemHeight = itemWidth
|
||||
if case let .assets(_, mode) = controller.subject, case .story = mode {
|
||||
itemHeight = floor(itemWidth * 1.227)
|
||||
}
|
||||
|
||||
let preloadSize: CGFloat = itemHeight// * 3.0
|
||||
self.gridNode.transaction(GridNodeTransaction(deleteItems: [], insertItems: [], updateItems: [], scrollToItem: nil, updateLayout: GridNodeUpdateLayout(layout: GridNodeLayout(size: bounds.size, insets: gridInsets, scrollIndicatorInsets: nil, preloadSize: preloadSize, type: .fixed(itemSize: CGSize(width: itemWidth, height: itemHeight), fillWidth: true, lineSpacing: itemSpacing, itemSpacing: itemSpacing), cutout: cameraRect), transition: transition), itemTransition: .immediate, stationaryItems: .none, updateFirstIndexInSectionOffset: nil, updateOpaqueState: nil, synchronousLoads: false), completion: { [weak self] _ in
|
||||
self.gridNode.transaction(GridNodeTransaction(deleteItems: [], insertItems: [], updateItems: [], scrollToItem: nil, updateLayout: GridNodeUpdateLayout(layout: GridNodeLayout(size: bounds.size, insets: gridInsets, scrollIndicatorInsets: nil, preloadSize: preloadSize, type: .fixed(itemSize: CGSize(width: itemWidth, height: itemHeight), fillWidth: true, lineSpacing: itemSpacing, itemSpacing: itemSpacing), cutout: cutoutRect), transition: transition), itemTransition: .immediate, stationaryItems: .none, updateFirstIndexInSectionOffset: nil, updateOpaqueState: nil, synchronousLoads: false), completion: { [weak self] _ in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
@@ -1612,6 +1667,14 @@ public final class MediaPickerScreenImpl: ViewController, MediaPickerScreen, Att
|
||||
}
|
||||
})
|
||||
|
||||
if let avatarEditorPreviewView = self.avatarEditorPreviewView {
|
||||
avatarEditorPreviewView.frame = CGRect(origin: CGPoint(x: cameraRect != nil ? cameraRect!.maxX + itemSpacing : layout.safeInsets.left, y: 0.0), size: CGSize(width: itemWidth, height: itemWidth))
|
||||
avatarEditorPreviewView.updateLayout(size: CGSize(width: itemWidth, height: itemWidth))
|
||||
if self.gridNode.view.subviews.last !== avatarEditorPreviewView {
|
||||
self.gridNode.view.bringSubviewToFront(avatarEditorPreviewView)
|
||||
}
|
||||
}
|
||||
|
||||
if let selectionNode = self.selectionNode, let controller = self.controller {
|
||||
let selectedItems = controller.interaction?.selectionState?.selectedItems() as? [TGMediaSelectableItem] ?? []
|
||||
let updateSelectionNode = {
|
||||
@@ -1642,7 +1705,7 @@ public final class MediaPickerScreenImpl: ViewController, MediaPickerScreen, Att
|
||||
|
||||
let screenWidth = min(layout.deviceMetrics.screenSize.width, layout.deviceMetrics.screenSize.height)
|
||||
let cameraFullSize = CGSize(width: screenWidth, height: floorToScreenPixels(layout.size.width * 1.77778))
|
||||
let cameraScale = cameraRect.height / cameraFullSize.height
|
||||
let cameraScale = max(cameraRect.width / cameraFullSize.width, cameraRect.height / cameraFullSize.height)
|
||||
|
||||
cameraView.bounds = CGRect(origin: .zero, size: cameraFullSize)
|
||||
cameraView.center = CGPoint(x: cameraRect.size.width / 2.0, y: cameraRect.size.height / 2.0)
|
||||
@@ -1681,6 +1744,8 @@ public final class MediaPickerScreenImpl: ViewController, MediaPickerScreen, Att
|
||||
self.controller?.navigationItem.rightBarButtonItem = nil
|
||||
} else if case .assets(_, .createSticker) = subject {
|
||||
hasCamera = false
|
||||
} else if case .assets(_, .createAvatar) = subject {
|
||||
hasCamera = false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1743,7 +1808,8 @@ public final class MediaPickerScreenImpl: ViewController, MediaPickerScreen, Att
|
||||
|
||||
private var isDismissing = false
|
||||
|
||||
fileprivate let mainButtonState: AttachmentMainButtonState?
|
||||
fileprivate let mainButtonStatePromise = Promise<AttachmentMainButtonState?>(nil)
|
||||
|
||||
private let mainButtonAction: (() -> Void)?
|
||||
|
||||
public init(
|
||||
@@ -1758,6 +1824,7 @@ public final class MediaPickerScreenImpl: ViewController, MediaPickerScreen, Att
|
||||
canBoostToUnrestrict: Bool = false,
|
||||
paidMediaAllowed: Bool = false,
|
||||
subject: Subject,
|
||||
forCollage: Bool = false,
|
||||
editingContext: TGMediaEditingContext? = nil,
|
||||
selectionContext: TGMediaSelectionContext? = nil,
|
||||
saveEditedPhotos: Bool = false,
|
||||
@@ -1778,8 +1845,9 @@ public final class MediaPickerScreenImpl: ViewController, MediaPickerScreen, Att
|
||||
self.canBoostToUnrestrict = canBoostToUnrestrict
|
||||
self.paidMediaAllowed = paidMediaAllowed
|
||||
self.subject = subject
|
||||
self.forCollage = forCollage
|
||||
self.saveEditedPhotos = saveEditedPhotos
|
||||
self.mainButtonState = mainButtonState
|
||||
self.mainButtonStatePromise.set(.single(mainButtonState))
|
||||
self.mainButtonAction = mainButtonAction
|
||||
|
||||
let selectionContext = selectionContext ?? TGMediaSelectionContext()
|
||||
@@ -1798,6 +1866,11 @@ public final class MediaPickerScreenImpl: ViewController, MediaPickerScreen, Att
|
||||
self.titleView.title = presentationData.strings.MediaPicker_Recents
|
||||
self.titleView.subtitle = presentationData.strings.MediaPicker_CreateSticker
|
||||
self.titleView.isEnabled = true
|
||||
case .createAvatar:
|
||||
//TODO:localize
|
||||
self.titleView.title = presentationData.strings.MediaPicker_Recents
|
||||
self.titleView.subtitle = "Set new profile photo"
|
||||
self.titleView.isEnabled = true
|
||||
case .story:
|
||||
self.titleView.title = presentationData.strings.MediaPicker_Recents
|
||||
self.titleView.isEnabled = true
|
||||
@@ -1823,7 +1896,7 @@ public final class MediaPickerScreenImpl: ViewController, MediaPickerScreen, Att
|
||||
super.init(navigationBarPresentationData: NavigationBarPresentationData(presentationData: presentationData))
|
||||
|
||||
self.statusBar.statusBarStyle = .Ignore
|
||||
|
||||
|
||||
selectionContext.attemptSelectingItem = { [weak self] item in
|
||||
guard let self else {
|
||||
return false
|
||||
@@ -1908,10 +1981,14 @@ public final class MediaPickerScreenImpl: ViewController, MediaPickerScreen, Att
|
||||
} else if collection == nil {
|
||||
self.navigationItem.leftBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Cancel, style: .plain, target: self, action: #selector(self.cancelPressed))
|
||||
|
||||
if [.createSticker].contains(mode) {
|
||||
self.navigationItem.rightBarButtonItem = UIBarButtonItem(customDisplayNode: self.moreButtonNode)
|
||||
self.navigationItem.rightBarButtonItem?.action = #selector(self.rightButtonPressed)
|
||||
self.navigationItem.rightBarButtonItem?.target = self
|
||||
if forCollage {
|
||||
self.navigationItem.rightBarButtonItem = UIBarButtonItem(backButtonAppearanceWithTitle: self.presentationData.strings.Common_Select, target: self, action: #selector(self.selectPressed))
|
||||
} else {
|
||||
if [.createSticker].contains(mode) {
|
||||
self.navigationItem.rightBarButtonItem = UIBarButtonItem(customDisplayNode: self.moreButtonNode)
|
||||
self.navigationItem.rightBarButtonItem?.action = #selector(self.rightButtonPressed)
|
||||
self.navigationItem.rightBarButtonItem?.target = self
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.navigationItem.leftBarButtonItem = UIBarButtonItem(backButtonAppearanceWithTitle: self.presentationData.strings.Common_Back, target: self, action: #selector(self.backPressed))
|
||||
@@ -1923,8 +2000,6 @@ public final class MediaPickerScreenImpl: ViewController, MediaPickerScreen, Att
|
||||
self.navigationItem.leftBarButtonItem = UIBarButtonItem(customDisplayNode: self.cancelButtonNode)
|
||||
self.navigationItem.leftBarButtonItem?.action = #selector(self.cancelPressed)
|
||||
self.navigationItem.leftBarButtonItem?.target = self
|
||||
|
||||
// self.navigationItem.leftBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Cancel, style: .plain, target: self, action: #selector(self.cancelPressed))
|
||||
}
|
||||
|
||||
if self.bannedSendPhotos != nil && self.bannedSendVideos != nil {
|
||||
@@ -2286,6 +2361,11 @@ public final class MediaPickerScreenImpl: ViewController, MediaPickerScreen, Att
|
||||
|
||||
transition.updateAlpha(node: self.moreButtonNode.iconNode, alpha: moreIsVisible ? 1.0 : 0.0)
|
||||
transition.updateTransformScale(node: self.moreButtonNode.iconNode, scale: moreIsVisible ? 1.0 : 0.1)
|
||||
|
||||
//if self. {
|
||||
//TODO:localize
|
||||
self.mainButtonStatePromise.set(.single(AttachmentMainButtonState(text: "Add", badge: "\(count)", font: .bold, background: .color(self.presentationData.theme.actionSheet.controlAccentColor), textColor: self.presentationData.theme.list.itemCheckColors.foregroundColor, isVisible: count > 0, progress: .none, isEnabled: true, hasShimmer: false)))
|
||||
//}
|
||||
}
|
||||
|
||||
private func updateThemeAndStrings() {
|
||||
@@ -2458,6 +2538,15 @@ public final class MediaPickerScreenImpl: ViewController, MediaPickerScreen, Att
|
||||
}
|
||||
}
|
||||
|
||||
@objc private func selectPressed() {
|
||||
self.navigationItem.setRightBarButton(nil, animated: true)
|
||||
self.explicitMultipleSelection = true
|
||||
|
||||
if let state = self.controllerNode.state {
|
||||
self.controllerNode.updateState(state)
|
||||
}
|
||||
}
|
||||
|
||||
@objc private func selectedPressed() {
|
||||
self.controllerNode.updateDisplayMode(.selected, animated: true)
|
||||
}
|
||||
@@ -2689,14 +2778,18 @@ final class MediaPickerContext: AttachmentMediaPickerContext {
|
||||
private weak var controller: MediaPickerScreenImpl?
|
||||
|
||||
var selectionCount: Signal<Int, NoError> {
|
||||
return Signal { [weak self] subscriber in
|
||||
let disposable = self?.controller?.interaction?.selectionState?.selectionChangedSignal().start(next: { [weak self] value in
|
||||
subscriber.putNext(Int(self?.controller?.interaction?.selectionState?.count() ?? 0))
|
||||
}, error: { _ in }, completed: { })
|
||||
return ActionDisposable {
|
||||
disposable?.dispose()
|
||||
}
|
||||
}
|
||||
//if self.controller?.forCollage == true {
|
||||
return .single(0)
|
||||
// } else {
|
||||
// return Signal { [weak self] subscriber in
|
||||
// let disposable = self?.controller?.interaction?.selectionState?.selectionChangedSignal().start(next: { [weak self] value in
|
||||
// subscriber.putNext(Int(self?.controller?.interaction?.selectionState?.count() ?? 0))
|
||||
// }, error: { _ in }, completed: { })
|
||||
// return ActionDisposable {
|
||||
// disposable?.dispose()
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
var caption: Signal<NSAttributedString?, NoError> {
|
||||
@@ -2820,7 +2913,7 @@ final class MediaPickerContext: AttachmentMediaPickerContext {
|
||||
}
|
||||
|
||||
public var mainButtonState: Signal<AttachmentMainButtonState?, NoError> {
|
||||
return .single(self.controller?.mainButtonState)
|
||||
return self.controller?.mainButtonStatePromise.get() ?? .single(nil)
|
||||
}
|
||||
|
||||
init(controller: MediaPickerScreenImpl) {
|
||||
@@ -3026,8 +3119,10 @@ public func storyMediaPickerController(
|
||||
context: AccountContext,
|
||||
isDark: Bool,
|
||||
forCollage: Bool,
|
||||
selectionLimit: Int?,
|
||||
getSourceRect: @escaping () -> CGRect,
|
||||
completion: @escaping (Any, UIView, CGRect, UIImage?, @escaping (Bool?) -> (UIView, CGRect)?, @escaping () -> Void) -> Void,
|
||||
multipleCompletion: @escaping ([Any]) -> Void,
|
||||
dismissed: @escaping () -> Void,
|
||||
groupsPresented: @escaping () -> Void
|
||||
) -> ViewController {
|
||||
@@ -3036,13 +3131,46 @@ public func storyMediaPickerController(
|
||||
presentationData = presentationData.withUpdated(theme: defaultDarkColorPresentationTheme)
|
||||
}
|
||||
let updatedPresentationData: (PresentationData, Signal<PresentationData, NoError>) = (presentationData, .single(presentationData))
|
||||
|
||||
var selectionContext: TGMediaSelectionContext?
|
||||
if let selectionLimit {
|
||||
selectionContext = TGMediaSelectionContext()
|
||||
selectionContext?.selectionLimit = Int32(selectionLimit)
|
||||
selectionContext?.selectionLimitExceeded = {
|
||||
HapticFeedback().error()
|
||||
}
|
||||
}
|
||||
|
||||
let controller = AttachmentController(context: context, updatedPresentationData: updatedPresentationData, chatLocation: nil, buttons: [.standalone], initialButton: .standalone, fromMenu: false, hasTextInput: false, makeEntityInputView: {
|
||||
return nil
|
||||
})
|
||||
controller.forceSourceRect = true
|
||||
controller.getSourceRect = getSourceRect
|
||||
controller.requestController = { _, present in
|
||||
let mediaPickerController = MediaPickerScreenImpl(context: context, updatedPresentationData: updatedPresentationData, peer: nil, threadTitle: nil, chatLocation: nil, bannedSendPhotos: nil, bannedSendVideos: nil, subject: .assets(nil, .story), mainButtonState: nil, mainButtonAction: nil)
|
||||
let mediaPickerController = MediaPickerScreenImpl(
|
||||
context: context,
|
||||
updatedPresentationData: updatedPresentationData,
|
||||
peer: nil,
|
||||
threadTitle: nil,
|
||||
chatLocation: nil,
|
||||
bannedSendPhotos: nil,
|
||||
bannedSendVideos: nil,
|
||||
subject: .assets(nil, .story),
|
||||
forCollage: forCollage,
|
||||
selectionContext: selectionContext,
|
||||
mainButtonState: nil,
|
||||
mainButtonAction: { [weak selectionContext] in
|
||||
if let selectionContext, let selectedItems = selectionContext.selectedItems() {
|
||||
var results: [Any] = []
|
||||
for item in selectedItems {
|
||||
if let item = item as? TGMediaAsset, let asset = item.backingAsset {
|
||||
results.append(asset)
|
||||
}
|
||||
}
|
||||
multipleCompletion(results)
|
||||
}
|
||||
}
|
||||
)
|
||||
mediaPickerController.groupsPresented = groupsPresented
|
||||
mediaPickerController.customSelection = { controller, result in
|
||||
if let result = result as? MediaEditorDraft {
|
||||
@@ -3093,8 +3221,9 @@ public func storyMediaPickerController(
|
||||
}
|
||||
present(mediaPickerController, mediaPickerController.mediaPickerContext)
|
||||
}
|
||||
controller.willDismiss = {
|
||||
controller.willDismiss = { [weak selectionContext] in
|
||||
dismissed()
|
||||
selectionContext?.clear()
|
||||
}
|
||||
controller.navigationPresentation = .flatModal
|
||||
controller.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .all, compactSize: .portrait)
|
||||
@@ -3228,6 +3357,124 @@ public func stickerMediaPickerController(
|
||||
return controller
|
||||
}
|
||||
|
||||
public func avatarMediaPickerController(
|
||||
context: AccountContext,
|
||||
getSourceRect: @escaping () -> CGRect?,
|
||||
canDelete: Bool,
|
||||
performDelete: @escaping () -> Void,
|
||||
completion: @escaping (Any?, UIView?, CGRect, UIImage?, Bool, @escaping (Bool?) -> (UIView, CGRect)?, @escaping () -> Void) -> Void,
|
||||
dismissed: @escaping () -> Void
|
||||
) -> ViewController {
|
||||
let presentationData = context.sharedContext.currentPresentationData.with({ $0 })
|
||||
let updatedPresentationData: (PresentationData, Signal<PresentationData, NoError>) = (presentationData, .single(presentationData))
|
||||
let controller = AttachmentController(context: context, updatedPresentationData: updatedPresentationData, chatLocation: nil, buttons: [.standalone], initialButton: .standalone, fromMenu: false, hasTextInput: false, makeEntityInputView: {
|
||||
return nil
|
||||
})
|
||||
controller.forceSourceRect = true
|
||||
controller.getSourceRect = getSourceRect
|
||||
controller.requestController = { [weak controller] _, present in
|
||||
|
||||
var mainButtonState: AttachmentMainButtonState?
|
||||
|
||||
if canDelete {
|
||||
//TODO:localize
|
||||
mainButtonState = AttachmentMainButtonState(text: "Remove Photo", font: .regular, background: .color(.clear), textColor: presentationData.theme.actionSheet.destructiveActionTextColor, isVisible: true, progress: .none, isEnabled: true, hasShimmer: false)
|
||||
}
|
||||
|
||||
let mediaPickerController = MediaPickerScreenImpl(
|
||||
context: context,
|
||||
updatedPresentationData: updatedPresentationData,
|
||||
peer: nil,
|
||||
threadTitle: nil,
|
||||
chatLocation: nil,
|
||||
bannedSendPhotos: nil,
|
||||
bannedSendVideos: nil,
|
||||
subject: .assets(nil, .createAvatar),
|
||||
mainButtonState: mainButtonState,
|
||||
mainButtonAction: { [weak controller] in
|
||||
controller?.dismiss(animated: true)
|
||||
performDelete()
|
||||
}
|
||||
)
|
||||
mediaPickerController.customSelection = { controller, result in
|
||||
if let result = result as? PHAsset {
|
||||
controller.updateHiddenMediaId(result.localIdentifier)
|
||||
if let transitionView = controller.transitionView(for: result.localIdentifier, snapshot: false) {
|
||||
let transitionOut: (Bool?) -> (UIView, CGRect)? = { isNew in
|
||||
if let isNew {
|
||||
if isNew {
|
||||
controller.updateHiddenMediaId(nil)
|
||||
if let transitionView = controller.defaultTransitionView() {
|
||||
return (transitionView, transitionView.bounds)
|
||||
}
|
||||
} else if let transitionView = controller.transitionView(for: result.localIdentifier, snapshot: false) {
|
||||
return (transitionView, transitionView.bounds)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
completion(result, transitionView, transitionView.bounds, controller.transitionImage(for: result.localIdentifier), false, transitionOut, { [weak controller] in
|
||||
controller?.updateHiddenMediaId(nil)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
mediaPickerController.openAvatarEditor = { [weak controller] in
|
||||
completion(nil, nil, .zero, nil, false, { _ in return nil }, {
|
||||
})
|
||||
controller?.dismiss(animated: true)
|
||||
}
|
||||
mediaPickerController.openCamera = { [weak controller] cameraHolder in
|
||||
guard let cameraHolder = cameraHolder as? CameraHolder else {
|
||||
return
|
||||
}
|
||||
|
||||
var returnToCameraImpl: (() -> Void)?
|
||||
let cameraScreen = CameraScreenImpl(
|
||||
context: context,
|
||||
mode: .avatar,
|
||||
holder: cameraHolder,
|
||||
transitionIn: CameraScreenImpl.TransitionIn(
|
||||
sourceView: cameraHolder.parentView,
|
||||
sourceRect: cameraHolder.parentView.bounds,
|
||||
sourceCornerRadius: 0.0
|
||||
),
|
||||
transitionOut: { _ in
|
||||
return CameraScreenImpl.TransitionOut(
|
||||
destinationView: cameraHolder.parentView,
|
||||
destinationRect: cameraHolder.parentView.bounds,
|
||||
destinationCornerRadius: 0.0
|
||||
)
|
||||
},
|
||||
completion: { result, _, commit in
|
||||
completion(result, nil, .zero, nil, true, { _ in return nil }, {
|
||||
returnToCameraImpl?()
|
||||
})
|
||||
}
|
||||
)
|
||||
cameraScreen.transitionedOut = { [weak cameraHolder] in
|
||||
if let cameraHolder {
|
||||
cameraHolder.restore()
|
||||
}
|
||||
}
|
||||
controller?.push(cameraScreen)
|
||||
|
||||
returnToCameraImpl = { [weak cameraScreen] in
|
||||
if let cameraScreen {
|
||||
cameraScreen.returnFromEditor()
|
||||
}
|
||||
}
|
||||
}
|
||||
present(mediaPickerController, mediaPickerController.mediaPickerContext)
|
||||
}
|
||||
controller.willDismiss = {
|
||||
dismissed()
|
||||
}
|
||||
controller.navigationPresentation = .flatModal
|
||||
controller.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .all, compactSize: .portrait)
|
||||
return controller
|
||||
}
|
||||
|
||||
private class SelectedButtonNode: HighlightableButtonNode {
|
||||
private let background = ASImageNode()
|
||||
private let icon = ASImageNode()
|
||||
|
||||
Reference in New Issue
Block a user