mirror of
https://github.com/TelegramMessenger/Telegram-iOS.git
synced 2026-07-06 03:33:41 +02:00
Merge commit 'd8d68722ae'
This commit is contained in:
commit
9b49738353
18 changed files with 401 additions and 81 deletions
|
|
@ -12535,3 +12535,5 @@ Sorry for the inconvenience.";
|
|||
"Stars.Transaction.FragmentUnknown_URL" = "https://fragment.com/stars";
|
||||
"Conversation.StatusBotSubscribers_1" = "1 user";
|
||||
"Conversation.StatusBotSubscribers_any" = "%d users";
|
||||
|
||||
"Story.Editor.Add" = "Add";
|
||||
|
|
|
|||
|
|
@ -1060,10 +1060,12 @@ public protocol SharedAccountContext: AnyObject {
|
|||
|
||||
func makeMediaPickerScreen(context: AccountContext, hasSearch: Bool, completion: @escaping (Any) -> Void) -> ViewController
|
||||
|
||||
func makeBotPreviewEditorScreen(context: AccountContext, source: Any?, target: Stories.PendingTarget, transitionArguments: (UIView, CGRect, UIImage?)?, externalState: MediaEditorTransitionOutExternalState, completion: @escaping (MediaEditorScreenResult, @escaping (@escaping () -> Void) -> Void) -> Void, cancelled: @escaping () -> Void) -> ViewController
|
||||
|
||||
func makeStickerEditorScreen(context: AccountContext, source: Any?, intro: Bool, transitionArguments: (UIView, CGRect, UIImage?)?, completion: @escaping (TelegramMediaFile, [String], @escaping () -> Void) -> Void, cancelled: @escaping () -> Void) -> ViewController
|
||||
|
||||
func makeStickerMediaPickerScreen(context: AccountContext, getSourceRect: @escaping () -> CGRect?, completion: @escaping (Any?, UIView?, CGRect, UIImage?, Bool, @escaping (Bool?) -> (UIView, CGRect)?, @escaping () -> Void) -> Void, dismissed: @escaping () -> Void) -> ViewController
|
||||
func makeStoryMediaPickerScreen(context: AccountContext, getSourceRect: @escaping () -> CGRect, completion: @escaping (Any, UIView, CGRect, UIImage?, @escaping (Bool?) -> (UIView, CGRect)?, @escaping () -> Void) -> Void, dismissed: @escaping () -> Void, groupsPresented: @escaping () -> Void) -> ViewController
|
||||
func makeStoryMediaPickerScreen(context: AccountContext, isDark: Bool, getSourceRect: @escaping () -> CGRect, completion: @escaping (Any, UIView, CGRect, UIImage?, @escaping (Bool?) -> (UIView, CGRect)?, @escaping () -> Void) -> Void, dismissed: @escaping () -> Void, groupsPresented: @escaping () -> Void) -> ViewController
|
||||
|
||||
func makeStickerPickerScreen(context: AccountContext, inputData: Promise<StickerPickerInput>, completion: @escaping (FileMediaReference) -> Void) -> ViewController
|
||||
|
||||
|
|
|
|||
|
|
@ -153,6 +153,7 @@ protocol BrowserContent: UIView {
|
|||
var getNavigationController: () -> NavigationController? { get set }
|
||||
|
||||
var minimize: () -> Void { get set }
|
||||
var close: () -> Void { get set }
|
||||
|
||||
var onScrollingUpdate: (ContentScrollingUpdate) -> Void { get set }
|
||||
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ final class BrowserInstantPageContent: UIView, BrowserContent, UIScrollViewDeleg
|
|||
var pushContent: (BrowserScreen.Subject) -> Void = { _ in }
|
||||
var onScrollingUpdate: (ContentScrollingUpdate) -> Void = { _ in }
|
||||
var minimize: () -> Void = { }
|
||||
var close: () -> Void = { }
|
||||
|
||||
var openPeer: (EnginePeer) -> Void = { _ in }
|
||||
|
||||
|
|
|
|||
|
|
@ -521,6 +521,16 @@ public class BrowserScreen: ViewController, MinimizableController {
|
|||
}
|
||||
self.minimize()
|
||||
}
|
||||
browserContent.close = { [weak self] in
|
||||
guard let self, let controller = self.controller else {
|
||||
return
|
||||
}
|
||||
if controller.isMinimized {
|
||||
|
||||
} else {
|
||||
controller.dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
self.content.append(browserContent)
|
||||
self.requestLayout(transition: transition)
|
||||
|
|
@ -952,6 +962,9 @@ public class BrowserScreen: ViewController, MinimizableController {
|
|||
private let context: AccountContext
|
||||
private let subject: Subject
|
||||
|
||||
|
||||
var openPreviousOnClose = false
|
||||
|
||||
public init(context: AccountContext, subject: Subject) {
|
||||
self.context = context
|
||||
self.subject = subject
|
||||
|
|
|
|||
|
|
@ -140,6 +140,7 @@ final class BrowserWebContent: UIView, BrowserContent, WKNavigationDelegate, WKU
|
|||
var pushContent: (BrowserScreen.Subject) -> Void = { _ in }
|
||||
var onScrollingUpdate: (ContentScrollingUpdate) -> Void = { _ in }
|
||||
var minimize: () -> Void = { }
|
||||
var close: () -> Void = { }
|
||||
var present: (ViewController, Any?) -> Void = { _, _ in }
|
||||
var presentInGlobalOverlay: (ViewController) -> Void = { _ in }
|
||||
var getNavigationController: () -> NavigationController? = { return nil }
|
||||
|
|
@ -191,6 +192,9 @@ final class BrowserWebContent: UIView, BrowserContent, WKNavigationDelegate, WKU
|
|||
if #available(iOS 15.0, *) {
|
||||
self.webView.underPageBackgroundColor = presentationData.theme.list.plainBackgroundColor
|
||||
}
|
||||
if #available(iOS 16.4, *) {
|
||||
self.webView.isInspectable = true
|
||||
}
|
||||
self.addSubview(self.webView)
|
||||
}
|
||||
|
||||
|
|
@ -217,35 +221,54 @@ final class BrowserWebContent: UIView, BrowserContent, WKNavigationDelegate, WKU
|
|||
self.updateLayout(size: size, insets: insets, transition: .immediate)
|
||||
}
|
||||
}
|
||||
|
||||
private let setupFontFunctions = """
|
||||
(function() {
|
||||
const styleId = 'telegram-font-overrides';
|
||||
|
||||
function setTelegramFontOverrides(font, textSizeAdjust) {
|
||||
let style = document.getElementById(styleId);
|
||||
|
||||
if (!style) {
|
||||
style = document.createElement('style');
|
||||
style.id = styleId;
|
||||
document.head.appendChild(style);
|
||||
}
|
||||
|
||||
let cssRules = '* {';
|
||||
if (font !== null) {
|
||||
cssRules += `
|
||||
font-family: ${font} !important;
|
||||
`;
|
||||
}
|
||||
if (textSizeAdjust !== null) {
|
||||
cssRules += `
|
||||
-webkit-text-size-adjust: ${textSizeAdjust} !important;
|
||||
`;
|
||||
}
|
||||
cssRules += '}';
|
||||
|
||||
style.innerHTML = cssRules;
|
||||
|
||||
if (font === null && textSizeAdjust === null) {
|
||||
style.parentNode.removeChild(style);
|
||||
}
|
||||
}
|
||||
window.setTelegramFontOverrides = setTelegramFontOverrides;
|
||||
})();
|
||||
"""
|
||||
|
||||
var currentFontState = BrowserPresentationState.FontState(size: 100, isSerif: false)
|
||||
func updateFontState(_ state: BrowserPresentationState.FontState) {
|
||||
self.updateFontState(state, force: false)
|
||||
}
|
||||
func updateFontState(_ state: BrowserPresentationState.FontState, force: Bool) {
|
||||
if self.currentFontState.size != state.size || (force && self.currentFontState.size != 100) {
|
||||
self.setFontSize(state.size)
|
||||
}
|
||||
if self.currentFontState.isSerif != state.isSerif || (force && self.currentFontState.isSerif) {
|
||||
self.setFontSerif(state.isSerif)
|
||||
}
|
||||
self.currentFontState = state
|
||||
}
|
||||
|
||||
private func setFontSize(_ fontSize: Int32) {
|
||||
let js = "document.getElementsByTagName('body')[0].style.webkitTextSizeAdjust='\(fontSize)%'"
|
||||
self.webView.evaluateJavaScript(js, completionHandler: nil)
|
||||
}
|
||||
|
||||
private func setFontSerif(_ force: Bool) {
|
||||
let js: String
|
||||
if force {
|
||||
js = "document.getElementsByTagName(\'body\')[0].style.fontFamily = 'Georgia, serif';"
|
||||
} else {
|
||||
js = "document.getElementsByTagName(\'body\')[0].style.fontFamily = '\"Lucida Grande\", \"Lucida Sans Unicode\", Arial, Helvetica, Verdana, sans-serif';"
|
||||
}
|
||||
self.webView.evaluateJavaScript(js) { _, _ in
|
||||
}
|
||||
|
||||
let fontFamily = state.isSerif ? "'Georgia, serif'" : "null"
|
||||
let textSizeAdjust = state.size != 100 ? "'\(state.size)%'" : "null"
|
||||
let js = "\(setupFontFunctions) setTelegramFontOverrides(\(fontFamily), \(textSizeAdjust))";
|
||||
self.webView.evaluateJavaScript(js) { _, _ in }
|
||||
}
|
||||
|
||||
private var didSetupSearch = false
|
||||
|
|
@ -513,6 +536,19 @@ final class BrowserWebContent: UIView, BrowserContent, WKNavigationDelegate, WKU
|
|||
}
|
||||
}
|
||||
|
||||
func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
|
||||
if navigationAction.targetFrame == nil {
|
||||
if let url = navigationAction.request.url?.absoluteString {
|
||||
self.open(url: url, new: true)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func webViewDidClose(_ webView: WKWebView) {
|
||||
self.close()
|
||||
}
|
||||
|
||||
@available(iOSApplicationExtension 15.0, iOS 15.0, *)
|
||||
func webView(_ webView: WKWebView, requestMediaCapturePermissionFor origin: WKSecurityOrigin, initiatedByFrame frame: WKFrameInfo, type: WKMediaCaptureType, decisionHandler: @escaping (WKPermissionDecision) -> Void) {
|
||||
decisionHandler(.prompt)
|
||||
|
|
@ -619,8 +655,10 @@ final class BrowserWebContent: UIView, BrowserContent, WKNavigationDelegate, WKU
|
|||
private func open(url: String, new: Bool) {
|
||||
let subject: BrowserScreen.Subject = .webPage(url: url)
|
||||
if new, let navigationController = self.getNavigationController() {
|
||||
navigationController._keepModalDismissProgress = true
|
||||
self.minimize()
|
||||
let controller = BrowserScreen(context: self.context, subject: subject)
|
||||
navigationController._keepModalDismissProgress = true
|
||||
navigationController.pushViewController(controller)
|
||||
} else {
|
||||
self.pushContent(subject)
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
|
|||
private let context: AccountContext
|
||||
private let peersFilter: ChatListNodePeersFilter
|
||||
private let requestPeerType: [ReplyMarkupButtonRequestPeerType]?
|
||||
private let location: ChatListControllerLocation
|
||||
private var location: ChatListControllerLocation
|
||||
private let displaySearchFilters: Bool
|
||||
private let hasDownloads: Bool
|
||||
private var interaction: ChatListSearchInteraction?
|
||||
|
|
@ -577,6 +577,12 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
|
|||
for token in tokens {
|
||||
tokensIdSet.insert(token.id)
|
||||
}
|
||||
|
||||
if case .chatList(.archive) = self.location, !tokens.contains(where: { $0.id == AnyHashable(ChatListTokenId.archive.rawValue) }) {
|
||||
self.location = .chatList(groupId: .root)
|
||||
self.paneContainerNode.location = self.location
|
||||
}
|
||||
|
||||
if !tokensIdSet.contains(ChatListTokenId.date.rawValue) && updatedOptions?.date != nil {
|
||||
updatedOptions = updatedOptions?.withUpdatedDate(nil)
|
||||
}
|
||||
|
|
@ -590,7 +596,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
|
|||
var options = options
|
||||
var tokens: [SearchBarToken] = []
|
||||
if case .chatList(.archive) = self.location {
|
||||
tokens.append(SearchBarToken(id: ChatListTokenId.archive.rawValue, icon: UIImage(bundleImageName: "Chat List/Search/Archive"), iconOffset: -1.0, title: self.presentationData.strings.ChatList_Archive, permanent: true))
|
||||
tokens.append(SearchBarToken(id: ChatListTokenId.archive.rawValue, icon: UIImage(bundleImageName: "Chat List/Search/Archive"), iconOffset: -1.0, title: self.presentationData.strings.ChatList_Archive, permanent: false))
|
||||
} else if case .forum = self.location, let forumPeer = self.forumPeer {
|
||||
tokens.append(SearchBarToken(id: ChatListTokenId.forum.rawValue, icon: nil, iconOffset: -1.0, peer: (forumPeer, self.context, self.presentationData.theme), title: self.presentationData.strings.ChatList_Archive, permanent: true))
|
||||
}
|
||||
|
|
@ -670,7 +676,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
|
|||
|
||||
var tokens: [SearchBarToken] = []
|
||||
if case .chatList(.archive) = self.location {
|
||||
tokens.append(SearchBarToken(id: ChatListTokenId.archive.rawValue, icon: UIImage(bundleImageName: "Chat List/Search/Archive"), iconOffset: -1.0, title: self.presentationData.strings.ChatList_Archive, permanent: true))
|
||||
tokens.append(SearchBarToken(id: ChatListTokenId.archive.rawValue, icon: UIImage(bundleImageName: "Chat List/Search/Archive"), iconOffset: -1.0, title: self.presentationData.strings.ChatList_Archive, permanent: false))
|
||||
} else if case .forum = self.location, let forumPeer = self.forumPeer {
|
||||
tokens.append(SearchBarToken(id: ChatListTokenId.forum.rawValue, icon: nil, iconOffset: -1.0, peer: (forumPeer, self.context, self.presentationData.theme), title: self.presentationData.strings.ChatList_Archive, permanent: true))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -159,7 +159,7 @@ final class ChatListSearchPaneContainerNode: ASDisplayNode, ASGestureRecognizerD
|
|||
private let updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)?
|
||||
private let peersFilter: ChatListNodePeersFilter
|
||||
private let requestPeerType: [ReplyMarkupButtonRequestPeerType]?
|
||||
private let location: ChatListControllerLocation
|
||||
var location: ChatListControllerLocation
|
||||
private let searchQuery: Signal<String?, NoError>
|
||||
private let searchOptions: Signal<ChatListSearchOptions?, NoError>
|
||||
private let globalPeerSearchContext: GlobalPeerSearchContext
|
||||
|
|
|
|||
|
|
@ -512,6 +512,10 @@ open class GalleryControllerNode: ASDisplayNode, ASScrollViewDelegate, ASGesture
|
|||
}
|
||||
} else {
|
||||
self.scrollView.setContentOffset(CGPoint(x: 0.0, y: self.scrollView.contentSize.height / 3.0), animated: true)
|
||||
|
||||
if let chatController = self.baseNavigationController()?.topViewController as? ChatController {
|
||||
chatController.updatePushedTransition(1.0, transition: .animated(duration: 0.45, curve: .customSpring(damping: 180.0, initialVelocity: 0.0)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2982,12 +2982,16 @@ public func mediaPickerController(
|
|||
|
||||
public func storyMediaPickerController(
|
||||
context: AccountContext,
|
||||
isDark: Bool,
|
||||
getSourceRect: @escaping () -> CGRect,
|
||||
completion: @escaping (Any, UIView, CGRect, UIImage?, @escaping (Bool?) -> (UIView, CGRect)?, @escaping () -> Void) -> Void,
|
||||
dismissed: @escaping () -> Void,
|
||||
groupsPresented: @escaping () -> Void
|
||||
) -> ViewController {
|
||||
let presentationData = context.sharedContext.currentPresentationData.with({ $0 }).withUpdated(theme: defaultDarkColorPresentationTheme)
|
||||
var presentationData = context.sharedContext.currentPresentationData.with({ $0 })
|
||||
if isDark {
|
||||
presentationData = presentationData.withUpdated(theme: defaultDarkColorPresentationTheme)
|
||||
}
|
||||
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
|
||||
|
|
|
|||
|
|
@ -2986,7 +2986,7 @@ public class CameraScreen: ViewController {
|
|||
if let current = self.galleryController {
|
||||
controller = current
|
||||
} else {
|
||||
controller = self.context.sharedContext.makeStoryMediaPickerScreen(context: self.context, getSourceRect: { [weak self] in
|
||||
controller = self.context.sharedContext.makeStoryMediaPickerScreen(context: self.context, isDark: true, getSourceRect: { [weak self] in
|
||||
if let self {
|
||||
if let galleryButton = self.node.componentHost.findTaggedView(tag: galleryButtonTag) {
|
||||
return galleryButton.convert(galleryButton.bounds, to: self.view).offsetBy(dx: 0.0, dy: -15.0)
|
||||
|
|
|
|||
|
|
@ -1543,7 +1543,14 @@ public final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTr
|
|||
}
|
||||
}
|
||||
|
||||
let arguments = TransformImageArguments(corners: corners, imageSize: drawingSize, boundingSize: boundingSize, intrinsicInsets: UIEdgeInsets(), resizeMode: isInlinePlayableVideo ? .fill(.black) : .blurBackground, emptyColor: emptyColor, custom: patternArguments)
|
||||
var videoCorners = corners
|
||||
var imageCorners = corners
|
||||
if let file = media as? TelegramMediaFile, file.isInstantVideo {
|
||||
videoCorners = ImageCorners(radius: boundingSize.width / 2.0)
|
||||
imageCorners = ImageCorners(radius: 0.0)
|
||||
}
|
||||
|
||||
let arguments = TransformImageArguments(corners: imageCorners, imageSize: drawingSize, boundingSize: boundingSize, intrinsicInsets: UIEdgeInsets(), resizeMode: isInlinePlayableVideo ? .fill(.black) : .blurBackground, emptyColor: emptyColor, custom: patternArguments)
|
||||
|
||||
let imageFrame = CGRect(origin: CGPoint(x: -arguments.insets.left, y: -arguments.insets.top), size: arguments.drawingSize).ensuredValid
|
||||
let cleanImageFrame = CGRect(origin: imageFrame.origin, size: CGSize(width: imageFrame.width - arguments.corners.extendedEdges.right, height: imageFrame.height))
|
||||
|
|
@ -1563,7 +1570,7 @@ public final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTr
|
|||
strongSelf.automaticPlayback = automaticPlayback
|
||||
strongSelf.automaticDownload = automaticDownload
|
||||
strongSelf.preferredStoryHighQuality = associatedData.preferredStoryHighQuality
|
||||
|
||||
|
||||
if let previousArguments = strongSelf.currentImageArguments {
|
||||
if previousArguments.imageSize == arguments.imageSize {
|
||||
strongSelf.pinchContainerNode.frame = imageFrame
|
||||
|
|
@ -1616,7 +1623,7 @@ public final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTr
|
|||
statusFrame.origin.y = floor(imageFrame.height / 2.0 - statusFrame.height / 2.0)
|
||||
statusNode.frame = statusFrame
|
||||
}
|
||||
|
||||
|
||||
var updatedVideoNodeReadySignal: Signal<Void, NoError>?
|
||||
var updatedPlayerStatusSignal: Signal<MediaPlayerStatus?, NoError>?
|
||||
if let currentReplaceVideoNode = replaceVideoNode {
|
||||
|
|
@ -1628,7 +1635,7 @@ public final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTr
|
|||
}
|
||||
|
||||
if currentReplaceVideoNode, let updatedVideoFile = updateVideoFile {
|
||||
let decoration = ChatBubbleVideoDecoration(corners: arguments.corners, nativeSize: nativeSize, contentMode: contentMode.bubbleVideoDecorationContentMode, backgroundColor: arguments.emptyColor ?? .black)
|
||||
let decoration = ChatBubbleVideoDecoration(corners: videoCorners, nativeSize: nativeSize, contentMode: contentMode.bubbleVideoDecorationContentMode, backgroundColor: arguments.emptyColor ?? .black)
|
||||
strongSelf.videoNodeDecoration = decoration
|
||||
let mediaManager = context.sharedContext.mediaManager
|
||||
|
||||
|
|
@ -1700,10 +1707,17 @@ public final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTr
|
|||
if message.attributes.contains(where: { $0 is MediaSpoilerMessageAttribute }), strongSelf.extendedMediaOverlayNode == nil {
|
||||
strongSelf.internallyVisible = false
|
||||
}
|
||||
|
||||
|
||||
if let videoNode = strongSelf.videoNode {
|
||||
if !(replaceVideoNode ?? false), let decoration = videoNode.decoration as? ChatBubbleVideoDecoration, decoration.corners != corners {
|
||||
decoration.updateCorners(corners)
|
||||
if !(replaceVideoNode ?? false), let decoration = videoNode.decoration as? ChatBubbleVideoDecoration, decoration.corners != videoCorners {
|
||||
decoration.updateCorners(videoCorners)
|
||||
}
|
||||
|
||||
if !videoCorners.isEmpty && imageCorners.isEmpty {
|
||||
strongSelf.imageNode.clipsToBounds = true
|
||||
strongSelf.imageNode.cornerRadius = videoCorners.topLeft.radius
|
||||
} else {
|
||||
strongSelf.imageNode.cornerRadius = 0.0
|
||||
}
|
||||
|
||||
videoNode.updateLayout(size: arguments.drawingSize, transition: .immediate)
|
||||
|
|
|
|||
|
|
@ -818,7 +818,7 @@ final class MediaEditorScreenComponent: Component {
|
|||
}
|
||||
|
||||
var doneButtonTitle: String?
|
||||
var doneButtonIcon: UIImage
|
||||
var doneButtonIcon: UIImage?
|
||||
switch controller.mode {
|
||||
case .storyEditor:
|
||||
doneButtonTitle = isEditingStory ? environment.strings.Story_Editor_Done.uppercased() : environment.strings.Story_Editor_Next.uppercased()
|
||||
|
|
@ -826,6 +826,10 @@ final class MediaEditorScreenComponent: Component {
|
|||
case .stickerEditor:
|
||||
doneButtonTitle = nil
|
||||
doneButtonIcon = generateTintedImage(image: UIImage(bundleImageName: "Media Editor/Apply"), color: .white)!
|
||||
case .botPreview:
|
||||
//TODO:localize
|
||||
doneButtonTitle = environment.strings.Story_Editor_Add
|
||||
doneButtonIcon = nil
|
||||
}
|
||||
|
||||
let doneButtonSize = self.doneButton.update(
|
||||
|
|
@ -859,6 +863,8 @@ final class MediaEditorScreenComponent: Component {
|
|||
}
|
||||
case .stickerEditor:
|
||||
controller.requestStickerCompletion(animated: true)
|
||||
case .botPreview:
|
||||
controller.requestStoryCompletion(animated: true)
|
||||
}
|
||||
}
|
||||
)),
|
||||
|
|
@ -2415,6 +2421,7 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
|
|||
|
||||
case storyEditor
|
||||
case stickerEditor(mode: StickerEditorMode)
|
||||
case botPreview
|
||||
}
|
||||
|
||||
public enum TransitionIn {
|
||||
|
|
@ -2873,7 +2880,7 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
|
|||
let mediaEntity = DrawingMediaEntity(size: fittedSize)
|
||||
mediaEntity.position = CGPoint(x: storyDimensions.width / 2.0, y: storyDimensions.height / 2.0)
|
||||
switch controller.mode {
|
||||
case .storyEditor:
|
||||
case .storyEditor, .botPreview:
|
||||
if fittedSize.height > fittedSize.width {
|
||||
mediaEntity.scale = max(storyDimensions.width / fittedSize.width, storyDimensions.height / fittedSize.height)
|
||||
} else {
|
||||
|
|
@ -3626,7 +3633,7 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
|
|||
transitionInView.contentMode = .scaleAspectFill
|
||||
var initialScale: CGFloat
|
||||
switch controller.mode {
|
||||
case .storyEditor:
|
||||
case .storyEditor, .botPreview:
|
||||
if image.size.height > image.size.width {
|
||||
initialScale = max(self.previewContainerView.bounds.width / image.size.width, self.previewContainerView.bounds.height / image.size.height)
|
||||
} else {
|
||||
|
|
@ -4784,12 +4791,17 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
|
|||
mediaEditor.maybePauseVideo()
|
||||
|
||||
var hasInteractiveStickers = true
|
||||
if let controller = self.controller, case .stickerEditor = controller.mode {
|
||||
hasInteractiveStickers = false
|
||||
if let controller = self.controller {
|
||||
switch controller.mode {
|
||||
case .stickerEditor, .botPreview:
|
||||
hasInteractiveStickers = false
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
var weatherSignal: Signal<StickerPickerScreen.Weather, NoError>
|
||||
if "".isEmpty {
|
||||
if hasInteractiveStickers {
|
||||
let weatherPromise: Promise<StickerPickerScreen.Weather>
|
||||
if let current = self.weatherPromise {
|
||||
weatherPromise = current
|
||||
|
|
@ -6101,7 +6113,7 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
|
|||
save = presentationData.strings.Story_Editor_DraftKeepMedia
|
||||
}
|
||||
text = presentationData.strings.Story_Editor_DraftDiscaedText
|
||||
case .stickerEditor:
|
||||
case .stickerEditor, .botPreview:
|
||||
title = presentationData.strings.Story_Editor_DraftDiscardMedia
|
||||
text = presentationData.strings.Story_Editor_DiscardText
|
||||
}
|
||||
|
|
@ -7440,12 +7452,12 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
|
|||
|
||||
private final class DoneButtonContentComponent: CombinedComponent {
|
||||
let backgroundColor: UIColor
|
||||
let icon: UIImage
|
||||
let icon: UIImage?
|
||||
let title: String?
|
||||
|
||||
init(
|
||||
backgroundColor: UIColor,
|
||||
icon: UIImage,
|
||||
icon: UIImage?,
|
||||
title: String?
|
||||
) {
|
||||
self.backgroundColor = backgroundColor
|
||||
|
|
@ -7469,12 +7481,14 @@ private final class DoneButtonContentComponent: CombinedComponent {
|
|||
let text = Child(Text.self)
|
||||
|
||||
return { context in
|
||||
let iconSize = context.component.icon.size
|
||||
let icon = icon.update(
|
||||
component: Image(image: context.component.icon, tintColor: .white, size: iconSize),
|
||||
availableSize: CGSize(width: 180.0, height: 100.0),
|
||||
transition: .immediate
|
||||
)
|
||||
var iconChild: _UpdatedChildComponent?
|
||||
if let iconImage = context.component.icon {
|
||||
iconChild = icon.update(
|
||||
component: Image(image: iconImage, tintColor: .white, size: iconImage.size),
|
||||
availableSize: CGSize(width: 180.0, height: 100.0),
|
||||
transition: .immediate
|
||||
)
|
||||
}
|
||||
|
||||
let backgroundHeight: CGFloat = 33.0
|
||||
var backgroundSize = CGSize(width: backgroundHeight, height: backgroundHeight)
|
||||
|
|
@ -7494,7 +7508,10 @@ private final class DoneButtonContentComponent: CombinedComponent {
|
|||
transition: .immediate
|
||||
)
|
||||
|
||||
let updatedBackgroundWidth = backgroundSize.width + textSpacing + title!.size.width
|
||||
var updatedBackgroundWidth = backgroundSize.width + title!.size.width
|
||||
if let _ = iconChild {
|
||||
updatedBackgroundWidth += textSpacing
|
||||
}
|
||||
if updatedBackgroundWidth < 126.0 {
|
||||
backgroundSize.width = updatedBackgroundWidth
|
||||
} else {
|
||||
|
|
@ -7514,16 +7531,22 @@ private final class DoneButtonContentComponent: CombinedComponent {
|
|||
)
|
||||
|
||||
if let title {
|
||||
var titlePosition = backgroundSize.width / 2.0
|
||||
if let _ = iconChild {
|
||||
titlePosition = title.size.width / 2.0 + 15.0
|
||||
}
|
||||
context.add(title
|
||||
.position(CGPoint(x: title.size.width / 2.0 + 15.0, y: backgroundHeight / 2.0))
|
||||
.position(CGPoint(x: titlePosition, y: backgroundHeight / 2.0))
|
||||
.opacity(hideTitle ? 0.0 : 1.0)
|
||||
)
|
||||
}
|
||||
|
||||
context.add(icon
|
||||
.position(CGPoint(x: background.size.width - 16.0, y: backgroundSize.height / 2.0))
|
||||
)
|
||||
|
||||
if let iconChild {
|
||||
context.add(iconChild
|
||||
.position(CGPoint(x: background.size.width - 16.0, y: backgroundSize.height / 2.0))
|
||||
)
|
||||
}
|
||||
|
||||
return backgroundSize
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,9 +58,10 @@ func getWeather(context: AccountContext) -> Signal<StickerPickerScreen.Weather,
|
|||
return getWeatherData(context: context, location: location)
|
||||
|> mapToSignal { weather in
|
||||
if let weather {
|
||||
if let match = context.animatedEmojiStickersValue[weather.emoji.strippedEmoji]?.first {
|
||||
let effectiveEmoji = emojiFor(for: weather.emoji.strippedEmoji, date: Date(), location: location)
|
||||
if let match = context.animatedEmojiStickersValue[effectiveEmoji]?.first {
|
||||
return .single(.loaded(StickerPickerScreen.Weather.LoadedWeather(
|
||||
emoji: weather.emoji.strippedEmoji,
|
||||
emoji: effectiveEmoji,
|
||||
emojiFile: match.file,
|
||||
temperature: weather.temperature
|
||||
)))
|
||||
|
|
@ -97,3 +98,123 @@ private struct WeatherBotConfiguration {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private let J1970: Double = 2440588.0
|
||||
private let moonEmojis = ["🌑", "🌒", "🌓", "🌔", "🌕", "🌖", "🌗", "🌘", "🌑"]
|
||||
|
||||
private func emojiFor(for emoji: String, date: Date, location: CLLocationCoordinate2D) -> String {
|
||||
var emoji = emoji
|
||||
if !"".isEmpty, ["☀️", "🌤️"].contains(emoji) && !isDay(latitude: location.latitude, longitude: location.longitude, dateTime: date) {
|
||||
emoji = moonPhaseEmoji(for: date)
|
||||
}
|
||||
return emoji
|
||||
}
|
||||
|
||||
private func moonPhaseEmoji(for date: Date) -> String {
|
||||
let julianDate = toJulianDate(date: date)
|
||||
|
||||
let referenceNewMoon: Double = 2451550.1
|
||||
let synodicMonth: Double = 29.53058867
|
||||
|
||||
let daysSinceNewMoon = julianDate - referenceNewMoon
|
||||
let newMoons = daysSinceNewMoon / synodicMonth
|
||||
let currentMoonPhase = (newMoons - floor(newMoons)) * synodicMonth
|
||||
|
||||
switch currentMoonPhase {
|
||||
case 0..<1.84566:
|
||||
return moonEmojis[0]
|
||||
case 1.84566..<5.53699:
|
||||
return moonEmojis[1]
|
||||
case 5.53699..<9.22831:
|
||||
return moonEmojis[2]
|
||||
case 9.22831..<12.91963:
|
||||
return moonEmojis[3]
|
||||
case 12.91963..<16.61096:
|
||||
return moonEmojis[4]
|
||||
case 16.61096..<20.30228:
|
||||
return moonEmojis[5]
|
||||
case 20.30228..<23.99361:
|
||||
return moonEmojis[6]
|
||||
case 23.99361..<27.68493:
|
||||
return moonEmojis[7]
|
||||
default:
|
||||
return moonEmojis[8]
|
||||
}
|
||||
}
|
||||
|
||||
private func isDay(latitude: Double, longitude: Double, dateTime: Date) -> Bool {
|
||||
let calendar = Calendar.current
|
||||
let date = calendar.startOfDay(for: dateTime)
|
||||
let time = dateTime.timeIntervalSince(date)
|
||||
|
||||
let sunrise = calculateSunrise(latitude: latitude, longitude: longitude, date: date)
|
||||
let sunset = calculateSunset(latitude: latitude, longitude: longitude, date: date)
|
||||
|
||||
return time >= sunrise * 3600 && time <= sunset * 3600
|
||||
}
|
||||
|
||||
private func calculateSunrise(latitude: Double, longitude: Double, date: Date) -> Double {
|
||||
return calculateSunTime(latitude: latitude, longitude: longitude, date: date, isSunrise: true)
|
||||
}
|
||||
|
||||
private func calculateSunset(latitude: Double, longitude: Double, date: Date) -> Double {
|
||||
return calculateSunTime(latitude: latitude, longitude: longitude, date: date, isSunrise: false)
|
||||
}
|
||||
|
||||
private func calculateSunTime(latitude: Double, longitude: Double, date: Date, isSunrise: Bool) -> Double {
|
||||
let calendar = Calendar.current
|
||||
let dayOfYear = calendar.ordinality(of: .day, in: .year, for: date)!
|
||||
let zenith = 90.833
|
||||
|
||||
let D2R = Double.pi / 180.0
|
||||
let R2D = 180.0 / Double.pi
|
||||
|
||||
let lngHour = longitude / 15.0
|
||||
let t = Double(dayOfYear) + ((isSunrise ? 6.0 : 18.0) - lngHour) / 24.0
|
||||
|
||||
let M = (0.9856 * t) - 3.289
|
||||
var L = M + (1.916 * sin(M * D2R)) + (0.020 * sin(2 * M * D2R)) + 282.634
|
||||
|
||||
if L > 360.0 {
|
||||
L -= 360.0
|
||||
} else if L < 0.0 {
|
||||
L += 360.0
|
||||
}
|
||||
|
||||
var RA = R2D * atan(0.91764 * tan(L * D2R))
|
||||
if RA > 360.0 {
|
||||
RA -= 360.0
|
||||
} else if RA < 0.0 {
|
||||
RA += 360.0
|
||||
}
|
||||
|
||||
let Lquadrant = (floor(L / 90.0)) * 90.0
|
||||
let RAquadrant = (floor(RA / 90.0)) * 90.0
|
||||
RA += (Lquadrant - RAquadrant)
|
||||
RA /= 15.0
|
||||
|
||||
let sinDec = 0.39782 * sin(L * D2R)
|
||||
let cosDec = cos(asin(sinDec))
|
||||
|
||||
let cosH = (cos(zenith * D2R) - (sinDec * sin(latitude * D2R))) / (cosDec * cos(latitude * D2R))
|
||||
if cosH > 1.0 || cosH < -1.0 {
|
||||
return -1
|
||||
}
|
||||
|
||||
var H = isSunrise ? (360.0 - R2D * acos(cosH)) : R2D * acos(cosH)
|
||||
H /= 15.0
|
||||
|
||||
let T = H + RA - (0.06571 * t) - 6.622
|
||||
var UT = T - lngHour
|
||||
|
||||
if UT > 24.0 {
|
||||
UT -= 24.0
|
||||
} else if UT < 0.0 {
|
||||
UT += 24.0
|
||||
}
|
||||
return UT
|
||||
}
|
||||
|
||||
private func toJulianDate(date: Date) -> Double {
|
||||
return date.timeIntervalSince1970 / 86400.0 + J1970 - 0.5
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9801,6 +9801,36 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
|||
self.controller?.push(controller)
|
||||
}
|
||||
|
||||
private func openBotPreviewEditor(target: Stories.PendingTarget, source: Any, transitionIn: (UIView, CGRect, UIImage?)?) {
|
||||
let context = self.context
|
||||
|
||||
let externalState = MediaEditorTransitionOutExternalState(
|
||||
storyTarget: target,
|
||||
isForcedTarget: false,
|
||||
isPeerArchived: false,
|
||||
transitionOut: nil
|
||||
)
|
||||
|
||||
let controller = context.sharedContext.makeBotPreviewEditorScreen(
|
||||
context: context,
|
||||
source: source,
|
||||
target: target,
|
||||
transitionArguments: transitionIn,
|
||||
externalState: externalState,
|
||||
completion: { result, commit in
|
||||
if let rootController = context.sharedContext.mainWindow?.viewController as? TelegramRootControllerInterface {
|
||||
var viewControllers = rootController.viewControllers
|
||||
viewControllers = viewControllers.filter { !($0 is AttachmentController)}
|
||||
rootController.setViewControllers(viewControllers, animated: false)
|
||||
|
||||
rootController.proceedWithStoryUpload(target: target, result: result, existingMedia: nil, forwardInfo: nil, externalState: externalState, commit: commit)
|
||||
}
|
||||
},
|
||||
cancelled: {}
|
||||
)
|
||||
self.controller?.push(controller)
|
||||
}
|
||||
|
||||
private func openPostStory(sourceFrame: CGRect?) {
|
||||
self.postingAvailabilityDisposable?.dispose()
|
||||
|
||||
|
|
@ -9808,12 +9838,20 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
|||
if !botInfo.flags.contains(.canEdit) {
|
||||
return
|
||||
}
|
||||
let cameraTransitionIn: StoryCameraTransitionIn? = nil
|
||||
|
||||
if let rootController = self.context.sharedContext.mainWindow?.viewController as? TelegramRootControllerInterface {
|
||||
let coordinator = rootController.openStoryCamera(customTarget: .botPreview(self.peerId), transitionIn: cameraTransitionIn, transitionedIn: {}, transitionOut: self.storyCameraTransitionOut())
|
||||
coordinator?.animateIn()
|
||||
}
|
||||
let controller = self.context.sharedContext.makeStoryMediaPickerScreen(
|
||||
context: self.context,
|
||||
isDark: false,
|
||||
getSourceRect: { return .zero },
|
||||
completion: { [weak self] result, transitionView, transitionRect, transitionImage, transitionOut, dismissed in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
self.openBotPreviewEditor(target: .botPreview(self.peerId), source: result, transitionIn: (transitionView, transitionRect, transitionImage))
|
||||
},
|
||||
dismissed: {},
|
||||
groupsPresented: {}
|
||||
)
|
||||
self.controller?.push(controller)
|
||||
} else {
|
||||
let canPostStatus: Signal<StoriesUploadAvailability, NoError>
|
||||
canPostStatus = self.context.engine.messages.checkStoriesUploadAvailability(target: .peer(self.peerId))
|
||||
|
|
|
|||
|
|
@ -567,11 +567,7 @@ final class StoryItemOverlaysView: UIView {
|
|||
size: CGSize,
|
||||
cornerRadius: CGFloat,
|
||||
isActive: Bool
|
||||
) {
|
||||
self.backgroundView.backgroundColor = flags.contains(.isDark) ? UIColor(rgb: 0x000000) : UIColor(rgb: 0xffffff)
|
||||
self.backgroundView.frame = CGRect(origin: .zero, size: size)
|
||||
self.backgroundView.layer.cornerRadius = cornerRadius
|
||||
|
||||
) -> CGSize {
|
||||
let itemSize = CGSize(width: floor(size.height * 0.71), height: floor(size.height * 0.71))
|
||||
|
||||
if self.file?.fileId != emojiFile?.fileId, let file = emojiFile {
|
||||
|
|
@ -615,14 +611,19 @@ final class StoryItemOverlaysView: UIView {
|
|||
MultilineTextComponent(text: .plain(string))
|
||||
),
|
||||
environment: {},
|
||||
containerSize: size
|
||||
containerSize: CGSize(width: .greatestFiniteMagnitude, height: size.height)
|
||||
)
|
||||
|
||||
let leftInset = size.height * 0.058
|
||||
let rightInset = size.height * 0.2
|
||||
let spacing = size.height * 0.205
|
||||
let contentWidth: CGFloat = leftInset + itemSize.width + spacing + textSize.width + rightInset
|
||||
|
||||
if let view = self.text.view {
|
||||
if view.superview == nil {
|
||||
self.addSubview(view)
|
||||
}
|
||||
let textFrame = CGRect(origin: CGPoint(x: size.width - textSize.width - size.height * 0.2, y: floorToScreenPixels((size.height - textSize.height) / 2.0)), size: textSize)
|
||||
let textFrame = CGRect(origin: CGPoint(x: contentWidth - textSize.width - rightInset, y: floorToScreenPixels((size.height - textSize.height) / 2.0)), size: textSize)
|
||||
let textTransition = ComponentTransition.immediate
|
||||
textTransition.setFrame(view: view, frame: textFrame)
|
||||
}
|
||||
|
|
@ -632,7 +633,7 @@ final class StoryItemOverlaysView: UIView {
|
|||
self.addSubview(directStickerView)
|
||||
}
|
||||
|
||||
let stickerFrame = itemSize.centered(around: CGPoint(x: size.height * 0.5 + size.height * 0.058, y: size.height * 0.5))
|
||||
let stickerFrame = itemSize.centered(around: CGPoint(x: size.height * 0.5 + leftInset, y: size.height * 0.5))
|
||||
|
||||
let stickerTransition = ComponentTransition.immediate
|
||||
stickerTransition.setPosition(view: directStickerView, position: stickerFrame.center)
|
||||
|
|
@ -640,6 +641,14 @@ final class StoryItemOverlaysView: UIView {
|
|||
|
||||
directStickerView.externalShouldPlay = isActive
|
||||
}
|
||||
|
||||
let contentSize = CGSize(width: contentWidth, height: size.height)
|
||||
|
||||
self.backgroundView.backgroundColor = flags.contains(.isDark) ? UIColor(rgb: 0x000000) : UIColor(rgb: 0xffffff)
|
||||
self.backgroundView.frame = CGRect(origin: .zero, size: contentSize)
|
||||
self.backgroundView.layer.cornerRadius = cornerRadius
|
||||
|
||||
return contentSize
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -754,15 +763,12 @@ final class StoryItemOverlaysView: UIView {
|
|||
itemView = current
|
||||
} else {
|
||||
itemView = WeatherView(frame: CGRect())
|
||||
itemView.isUserInteractionEnabled = false
|
||||
self.itemViews[itemId] = itemView
|
||||
self.addSubview(itemView)
|
||||
}
|
||||
|
||||
transition.setPosition(view: itemView, position: itemFrame.center)
|
||||
transition.setBounds(view: itemView, bounds: CGRect(origin: CGPoint(), size: itemFrame.size))
|
||||
transition.setTransform(view: itemView, transform: CATransform3DMakeRotation(itemRotation, 0.0, 0.0, 1.0))
|
||||
|
||||
itemView.update(
|
||||
|
||||
let itemSize = itemView.update(
|
||||
context: context,
|
||||
emoji: emoji,
|
||||
emojiFile: context.animatedEmojiStickersValue[emoji]?.first?.file,
|
||||
|
|
@ -774,6 +780,10 @@ final class StoryItemOverlaysView: UIView {
|
|||
isActive: isActive
|
||||
)
|
||||
|
||||
transition.setPosition(view: itemView, position: itemFrame.center)
|
||||
transition.setBounds(view: itemView, bounds: CGRect(origin: CGPoint(), size: itemSize))
|
||||
transition.setTransform(view: itemView, transform: CATransform3DMakeRotation(itemRotation, 0.0, 0.0, 1.0))
|
||||
|
||||
nextId += 1
|
||||
default:
|
||||
break
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ import ChatMessageNotificationItem
|
|||
import PhoneNumberFormat
|
||||
import AttachmentUI
|
||||
import MinimizedContainer
|
||||
import BrowserUI
|
||||
|
||||
final class UnauthorizedApplicationContext {
|
||||
let sharedContext: SharedAccountContextImpl
|
||||
|
|
@ -445,6 +446,8 @@ final class AuthorizedApplicationContext {
|
|||
minimizedContainer.collapse()
|
||||
} else if let topContoller = strongSelf.rootController.topViewController as? AttachmentController {
|
||||
topContoller.minimizeIfNeeded()
|
||||
} else if let topContoller = strongSelf.rootController.topViewController as? BrowserScreen {
|
||||
topContoller.requestMinimize(topEdgeOffset: nil, initialVelocity: nil)
|
||||
}
|
||||
|
||||
for controller in strongSelf.rootController.viewControllers {
|
||||
|
|
|
|||
|
|
@ -2533,6 +2533,46 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
|||
})
|
||||
}
|
||||
|
||||
public func makeBotPreviewEditorScreen(context: AccountContext, source: Any?, target: Stories.PendingTarget, transitionArguments: (UIView, CGRect, UIImage?)?, externalState: MediaEditorTransitionOutExternalState, completion: @escaping (MediaEditorScreenResult, @escaping (@escaping () -> Void) -> Void) -> Void, cancelled: @escaping () -> Void) -> ViewController {
|
||||
let subject: Signal<MediaEditorScreen.Subject?, NoError>
|
||||
if let asset = source as? PHAsset {
|
||||
subject = .single(.asset(asset))
|
||||
} else if let image = source as? UIImage {
|
||||
subject = .single(.image(image, PixelDimensions(image.size), nil, .bottomRight))
|
||||
} else {
|
||||
subject = .single(.empty(PixelDimensions(width: 1080, height: 1920)))
|
||||
}
|
||||
let editorController = MediaEditorScreen(
|
||||
context: context,
|
||||
mode: .botPreview,
|
||||
subject: subject,
|
||||
customTarget: nil,
|
||||
transitionIn: transitionArguments.flatMap { .gallery(
|
||||
MediaEditorScreen.TransitionIn.GalleryTransitionIn(
|
||||
sourceView: $0.0,
|
||||
sourceRect: $0.1,
|
||||
sourceImage: $0.2
|
||||
)
|
||||
) },
|
||||
transitionOut: { finished, isNew in
|
||||
if !finished, let transitionArguments {
|
||||
return MediaEditorScreen.TransitionOut(
|
||||
destinationView: transitionArguments.0,
|
||||
destinationRect: transitionArguments.0.bounds,
|
||||
destinationCornerRadius: 0.0
|
||||
)
|
||||
}
|
||||
return nil
|
||||
}, completion: { result, commit in
|
||||
completion(result, commit)
|
||||
} as (MediaEditorScreen.Result, @escaping (@escaping () -> Void) -> Void) -> Void
|
||||
)
|
||||
editorController.cancelled = { _ in
|
||||
cancelled()
|
||||
}
|
||||
return editorController
|
||||
}
|
||||
|
||||
public func makeStickerEditorScreen(context: AccountContext, source: Any?, intro: Bool, transitionArguments: (UIView, CGRect, UIImage?)?, completion: @escaping (TelegramMediaFile, [String], @escaping () -> Void) -> Void, cancelled: @escaping () -> Void) -> ViewController {
|
||||
let subject: Signal<MediaEditorScreen.Subject?, NoError>
|
||||
var mode: MediaEditorScreen.Mode.StickerEditorMode
|
||||
|
|
@ -2605,8 +2645,8 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
|||
return mediaPickerController(context: context, hasSearch: hasSearch, completion: completion)
|
||||
}
|
||||
|
||||
public func makeStoryMediaPickerScreen(context: AccountContext, getSourceRect: @escaping () -> CGRect, completion: @escaping (Any, UIView, CGRect, UIImage?, @escaping (Bool?) -> (UIView, CGRect)?, @escaping () -> Void) -> Void, dismissed: @escaping () -> Void, groupsPresented: @escaping () -> Void) -> ViewController {
|
||||
return storyMediaPickerController(context: context, getSourceRect: getSourceRect, completion: completion, dismissed: dismissed, groupsPresented: groupsPresented)
|
||||
public func makeStoryMediaPickerScreen(context: AccountContext, isDark: Bool, getSourceRect: @escaping () -> CGRect, completion: @escaping (Any, UIView, CGRect, UIImage?, @escaping (Bool?) -> (UIView, CGRect)?, @escaping () -> Void) -> Void, dismissed: @escaping () -> Void, groupsPresented: @escaping () -> Void) -> ViewController {
|
||||
return storyMediaPickerController(context: context, isDark: isDark, getSourceRect: getSourceRect, completion: completion, dismissed: dismissed, groupsPresented: groupsPresented)
|
||||
}
|
||||
|
||||
public func makeStickerMediaPickerScreen(context: AccountContext, getSourceRect: @escaping () -> CGRect?, completion: @escaping (Any?, UIView?, CGRect, UIImage?, Bool, @escaping (Bool?) -> (UIView, CGRect)?, @escaping () -> Void) -> Void, dismissed: @escaping () -> Void) -> ViewController {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue