mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-22 14:20:20 +00:00
[WIP] Story collage
This commit is contained in:
@@ -27,6 +27,7 @@ import MediaEditor
|
||||
import ImageObjectSeparation
|
||||
import ChatSendMessageActionUI
|
||||
import AnimatedCountLabelNode
|
||||
import MediaAssetsContext
|
||||
|
||||
final class MediaPickerInteraction {
|
||||
let downloadManager: AssetDownloadManager
|
||||
@@ -40,16 +41,7 @@ final class MediaPickerInteraction {
|
||||
let selectionState: TGMediaSelectionContext?
|
||||
let editingState: TGMediaEditingContext
|
||||
var hiddenMediaId: String?
|
||||
|
||||
var captionIsAboveMedia: Bool = false {
|
||||
didSet {
|
||||
if self.captionIsAboveMedia != oldValue {
|
||||
self.captionIsAboveMediaValue.set(self.captionIsAboveMedia)
|
||||
}
|
||||
}
|
||||
}
|
||||
let captionIsAboveMediaValue = ValuePromise<Bool>(false)
|
||||
|
||||
|
||||
init(downloadManager: AssetDownloadManager, openMedia: @escaping (PHFetchResult<PHAsset>, Int, UIImage?) -> Void, openSelectedMedia: @escaping (TGMediaSelectableItem, UIImage?) -> Void, openDraft: @escaping (MediaEditorDraft, UIImage?) -> Void, toggleSelection: @escaping (TGMediaSelectableItem, Bool, Bool) -> Bool, sendSelected: @escaping (TGMediaSelectableItem?, Bool, Int32?, Bool, ChatSendMessageActionSheetController.SendParameters?, @escaping () -> Void) -> Void, schedule: @escaping (ChatSendMessageActionSheetController.SendParameters?) -> Void, dismissInput: @escaping () -> Void, selectionState: TGMediaSelectionContext?, editingState: TGMediaEditingContext) {
|
||||
self.downloadManager = downloadManager
|
||||
self.openMedia = openMedia
|
||||
@@ -138,7 +130,7 @@ struct Month: Equatable {
|
||||
|
||||
private var savedStoriesContentOffset: CGFloat?
|
||||
|
||||
public final class MediaPickerScreen: ViewController, AttachmentContainable {
|
||||
public final class MediaPickerScreenImpl: ViewController, MediaPickerScreen, AttachmentContainable {
|
||||
public enum Subject {
|
||||
public enum Media: Equatable {
|
||||
case image(UIImage)
|
||||
@@ -207,7 +199,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
|
||||
public var getCaptionPanelView: () -> TGCaptionPanelView? = { return nil }
|
||||
public var openBoost: () -> Void = { }
|
||||
|
||||
public var customSelection: ((MediaPickerScreen, Any) -> Void)? = nil
|
||||
public var customSelection: ((MediaPickerScreenImpl, Any) -> Void)? = nil
|
||||
|
||||
public var createFromScratch: () -> Void = {}
|
||||
public var presentFilePicker: () -> Void = {}
|
||||
@@ -250,7 +242,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
|
||||
case media([Subject.Media])
|
||||
}
|
||||
|
||||
private weak var controller: MediaPickerScreen?
|
||||
private weak var controller: MediaPickerScreenImpl?
|
||||
private var presentationData: PresentationData
|
||||
fileprivate let mediaAssetsContext: MediaAssetsContext
|
||||
|
||||
@@ -307,7 +299,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
|
||||
|
||||
private var validLayout: (ContainerViewLayout, CGFloat)?
|
||||
|
||||
init(controller: MediaPickerScreen) {
|
||||
init(controller: MediaPickerScreenImpl) {
|
||||
self.controller = controller
|
||||
self.presentationData = controller.presentationData
|
||||
|
||||
@@ -1255,7 +1247,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
|
||||
if parameters == nil {
|
||||
var textIsAboveMedia = false
|
||||
if let interaction = controller.interaction {
|
||||
textIsAboveMedia = interaction.captionIsAboveMedia
|
||||
textIsAboveMedia = interaction.editingState.isCaptionAbove()
|
||||
}
|
||||
parameters = ChatSendMessageActionSheetController.SendParameters(
|
||||
effect: nil,
|
||||
@@ -2311,7 +2303,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
|
||||
} else {
|
||||
self.updateNavigationStack { current in
|
||||
var mediaPickerContext: AttachmentMediaPickerContext?
|
||||
if let first = current.first as? MediaPickerScreen {
|
||||
if let first = current.first as? MediaPickerScreenImpl {
|
||||
mediaPickerContext = first.webSearchController?.mediaPickerContext ?? first.mediaPickerContext
|
||||
}
|
||||
return (current.filter { $0 !== self }, mediaPickerContext)
|
||||
@@ -2417,7 +2409,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
|
||||
var updateNavigationStackImpl: ((AttachmentContainable) -> Void)?
|
||||
let groupsController = MediaGroupsScreen(context: self.context, updatedPresentationData: self.updatedPresentationData, mediaAssetsContext: self.controllerNode.mediaAssetsContext, embedded: embedded, openGroup: { [weak self] collection in
|
||||
if let strongSelf = self {
|
||||
let mediaPicker = MediaPickerScreen(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, peer: strongSelf.peer, threadTitle: strongSelf.threadTitle, chatLocation: strongSelf.chatLocation, isScheduledMessages: strongSelf.isScheduledMessages, bannedSendPhotos: strongSelf.bannedSendPhotos, bannedSendVideos: strongSelf.bannedSendVideos, subject: .assets(collection, mode), editingContext: strongSelf.interaction?.editingState, selectionContext: strongSelf.interaction?.selectionState)
|
||||
let mediaPicker = MediaPickerScreenImpl(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, peer: strongSelf.peer, threadTitle: strongSelf.threadTitle, chatLocation: strongSelf.chatLocation, isScheduledMessages: strongSelf.isScheduledMessages, bannedSendPhotos: strongSelf.bannedSendPhotos, bannedSendVideos: strongSelf.bannedSendVideos, subject: .assets(collection, mode), editingContext: strongSelf.interaction?.editingState, selectionContext: strongSelf.interaction?.selectionState)
|
||||
|
||||
mediaPicker.presentSchedulePicker = strongSelf.presentSchedulePicker
|
||||
mediaPicker.presentTimerPicker = strongSelf.presentTimerPicker
|
||||
@@ -2576,7 +2568,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
|
||||
if isCaptionAboveMediaAvailable {
|
||||
var mediaCaptionIsAbove = false
|
||||
if let interaction = self.interaction {
|
||||
mediaCaptionIsAbove = interaction.captionIsAboveMedia
|
||||
mediaCaptionIsAbove = interaction.editingState.isCaptionAbove()
|
||||
}
|
||||
|
||||
items.append(.action(ContextMenuActionItem(text: mediaCaptionIsAbove ? strings.Chat_SendMessageMenu_MoveCaptionDown : strings.Chat_SendMessageMenu_MoveCaptionUp, icon: { _ in return nil }, iconAnimation: ContextMenuActionItem.IconAnimation(
|
||||
@@ -2588,7 +2580,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
|
||||
}
|
||||
|
||||
if let interaction = strongSelf.interaction {
|
||||
interaction.captionIsAboveMedia = !interaction.captionIsAboveMedia
|
||||
interaction.editingState.setCaptionAbove(!interaction.editingState.isCaptionAbove())
|
||||
}
|
||||
})))
|
||||
}
|
||||
@@ -2684,13 +2676,17 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
|
||||
self.selectedButtonNode.frame = CGRect(origin: CGPoint(x: self.view.bounds.width - 54.0 - self.selectedButtonNode.frame.width - safeInset, y: floorToScreenPixels((navigationHeight - self.selectedButtonNode.frame.height) / 2.0) + 1.0), size: self.selectedButtonNode.frame.size)
|
||||
}
|
||||
|
||||
public func dismissAnimated() {
|
||||
self.requestDismiss(completion: {})
|
||||
}
|
||||
|
||||
public var mediaPickerContext: AttachmentMediaPickerContext? {
|
||||
return MediaPickerContext(controller: self)
|
||||
}
|
||||
}
|
||||
|
||||
final class MediaPickerContext: AttachmentMediaPickerContext {
|
||||
private weak var controller: MediaPickerScreen?
|
||||
private weak var controller: MediaPickerScreenImpl?
|
||||
|
||||
var selectionCount: Signal<Int, NoError> {
|
||||
return Signal { [weak self] subscriber in
|
||||
@@ -2791,23 +2787,32 @@ final class MediaPickerContext: AttachmentMediaPickerContext {
|
||||
|
||||
var captionIsAboveMedia: Signal<Bool, NoError> {
|
||||
return Signal { [weak self] subscriber in
|
||||
guard let interaction = self?.controller?.interaction else {
|
||||
guard let self else {
|
||||
subscriber.putNext(false)
|
||||
subscriber.putCompletion()
|
||||
|
||||
return EmptyDisposable
|
||||
}
|
||||
let disposable = interaction.captionIsAboveMediaValue.get().start(next: { value in
|
||||
subscriber.putNext(value)
|
||||
guard let captionAbove = self.controller?.interaction?.editingState.captionAbove() else {
|
||||
subscriber.putNext(false)
|
||||
subscriber.putCompletion()
|
||||
return EmptyDisposable
|
||||
}
|
||||
|
||||
let disposable = captionAbove.start(next: { caption in
|
||||
if let caption = caption as? NSNumber {
|
||||
subscriber.putNext(caption.boolValue)
|
||||
} else {
|
||||
subscriber.putNext(false)
|
||||
}
|
||||
}, error: { _ in }, completed: { })
|
||||
return ActionDisposable {
|
||||
disposable.dispose()
|
||||
disposable?.dispose()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func setCaptionIsAboveMedia(_ captionIsAboveMedia: Bool) -> Void {
|
||||
self.controller?.interaction?.captionIsAboveMedia = captionIsAboveMedia
|
||||
self.controller?.interaction?.editingState.setCaptionAbove(captionIsAboveMedia)
|
||||
}
|
||||
|
||||
public var loadingProgress: Signal<CGFloat?, NoError> {
|
||||
@@ -2818,7 +2823,7 @@ final class MediaPickerContext: AttachmentMediaPickerContext {
|
||||
return .single(self.controller?.mainButtonState)
|
||||
}
|
||||
|
||||
init(controller: MediaPickerScreen) {
|
||||
init(controller: MediaPickerScreenImpl) {
|
||||
self.controller = controller
|
||||
}
|
||||
|
||||
@@ -2954,7 +2959,7 @@ public func wallpaperMediaPickerController(
|
||||
updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil,
|
||||
peer: EnginePeer,
|
||||
animateAppearance: Bool,
|
||||
completion: @escaping (MediaPickerScreen, Any) -> Void = { _, _ in },
|
||||
completion: @escaping (MediaPickerScreenImpl, Any) -> Void = { _, _ in },
|
||||
openColors: @escaping () -> Void
|
||||
) -> ViewController {
|
||||
let controller = AttachmentController(context: context, updatedPresentationData: updatedPresentationData, chatLocation: nil, buttons: [.standalone], initialButton: .standalone, fromMenu: false, hasTextInput: false, makeEntityInputView: {
|
||||
@@ -2963,7 +2968,7 @@ public func wallpaperMediaPickerController(
|
||||
controller.animateAppearance = animateAppearance
|
||||
controller.requestController = { [weak controller] _, present in
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
let mediaPickerController = MediaPickerScreen(context: context, updatedPresentationData: updatedPresentationData, peer: nil, threadTitle: nil, chatLocation: nil, bannedSendPhotos: nil, bannedSendVideos: nil, subject: .assets(nil, .wallpaper), mainButtonState: AttachmentMainButtonState(text: presentationData.strings.Conversation_Theme_SetColorWallpaper, font: .regular, background: .color(.clear), textColor: presentationData.theme.actionSheet.controlAccentColor, isVisible: true, progress: .none, isEnabled: true, hasShimmer: false), mainButtonAction: {
|
||||
let mediaPickerController = MediaPickerScreenImpl(context: context, updatedPresentationData: updatedPresentationData, peer: nil, threadTitle: nil, chatLocation: nil, bannedSendPhotos: nil, bannedSendVideos: nil, subject: .assets(nil, .wallpaper), mainButtonState: AttachmentMainButtonState(text: presentationData.strings.Conversation_Theme_SetColorWallpaper, font: .regular, background: .color(.clear), textColor: presentationData.theme.actionSheet.controlAccentColor, isVisible: true, progress: .none, isEnabled: true, hasShimmer: false), mainButtonAction: {
|
||||
controller?.dismiss(animated: true)
|
||||
openColors()
|
||||
})
|
||||
@@ -2985,7 +2990,7 @@ public func mediaPickerController(
|
||||
return nil
|
||||
})
|
||||
controller.requestController = { _, present in
|
||||
let mediaPickerController = MediaPickerScreen(context: context, updatedPresentationData: updatedPresentationData, peer: nil, threadTitle: nil, chatLocation: nil, bannedSendPhotos: nil, bannedSendVideos: nil, subject: .assets(nil, .addImage), mainButtonState: nil, mainButtonAction: nil)
|
||||
let mediaPickerController = MediaPickerScreenImpl(context: context, updatedPresentationData: updatedPresentationData, peer: nil, threadTitle: nil, chatLocation: nil, bannedSendPhotos: nil, bannedSendVideos: nil, subject: .assets(nil, .addImage), mainButtonState: nil, mainButtonAction: nil)
|
||||
mediaPickerController.customSelection = { controller, result in
|
||||
completion(result)
|
||||
controller.dismiss(animated: true)
|
||||
@@ -3020,6 +3025,7 @@ public func mediaPickerController(
|
||||
public func storyMediaPickerController(
|
||||
context: AccountContext,
|
||||
isDark: Bool,
|
||||
forCollage: Bool,
|
||||
getSourceRect: @escaping () -> CGRect,
|
||||
completion: @escaping (Any, UIView, CGRect, UIImage?, @escaping (Bool?) -> (UIView, CGRect)?, @escaping () -> Void) -> Void,
|
||||
dismissed: @escaping () -> Void,
|
||||
@@ -3036,7 +3042,7 @@ public func storyMediaPickerController(
|
||||
controller.forceSourceRect = true
|
||||
controller.getSourceRect = getSourceRect
|
||||
controller.requestController = { _, present in
|
||||
let mediaPickerController = MediaPickerScreen(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), mainButtonState: nil, mainButtonAction: nil)
|
||||
mediaPickerController.groupsPresented = groupsPresented
|
||||
mediaPickerController.customSelection = { controller, result in
|
||||
if let result = result as? MediaEditorDraft {
|
||||
@@ -3062,7 +3068,9 @@ public func storyMediaPickerController(
|
||||
})
|
||||
}
|
||||
} else if let result = result as? PHAsset {
|
||||
controller.updateHiddenMediaId(result.localIdentifier)
|
||||
if !forCollage {
|
||||
controller.updateHiddenMediaId(result.localIdentifier)
|
||||
}
|
||||
if let transitionView = controller.transitionView(for: result.localIdentifier, snapshot: false) {
|
||||
let transitionOut: (Bool?) -> (UIView, CGRect)? = { isNew in
|
||||
if let isNew {
|
||||
@@ -3107,7 +3115,7 @@ public func stickerMediaPickerController(
|
||||
controller.forceSourceRect = true
|
||||
controller.getSourceRect = getSourceRect
|
||||
controller.requestController = { [weak controller] _, present in
|
||||
let mediaPickerController = MediaPickerScreen(context: context, updatedPresentationData: updatedPresentationData, peer: nil, threadTitle: nil, chatLocation: nil, bannedSendPhotos: nil, bannedSendVideos: nil, subject: .assets(nil, .createSticker), mainButtonState: nil, mainButtonAction: nil)
|
||||
let mediaPickerController = MediaPickerScreenImpl(context: context, updatedPresentationData: updatedPresentationData, peer: nil, threadTitle: nil, chatLocation: nil, bannedSendPhotos: nil, bannedSendVideos: nil, subject: .assets(nil, .createSticker), mainButtonState: nil, mainButtonAction: nil)
|
||||
mediaPickerController.customSelection = { controller, result in
|
||||
if let result = result as? PHAsset {
|
||||
controller.updateHiddenMediaId(result.localIdentifier)
|
||||
@@ -3175,17 +3183,17 @@ public func stickerMediaPickerController(
|
||||
}
|
||||
|
||||
var returnToCameraImpl: (() -> Void)?
|
||||
let cameraScreen = CameraScreen(
|
||||
let cameraScreen = CameraScreenImpl(
|
||||
context: context,
|
||||
mode: .sticker,
|
||||
holder: cameraHolder,
|
||||
transitionIn: CameraScreen.TransitionIn(
|
||||
transitionIn: CameraScreenImpl.TransitionIn(
|
||||
sourceView: cameraHolder.parentView,
|
||||
sourceRect: cameraHolder.parentView.bounds,
|
||||
sourceCornerRadius: 0.0
|
||||
),
|
||||
transitionOut: { _ in
|
||||
return CameraScreen.TransitionOut(
|
||||
return CameraScreenImpl.TransitionOut(
|
||||
destinationView: cameraHolder.parentView,
|
||||
destinationRect: cameraHolder.parentView.bounds,
|
||||
destinationCornerRadius: 0.0
|
||||
|
||||
Reference in New Issue
Block a user