mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Web app improvements
This commit is contained in:
parent
3881bdff70
commit
ada47a4be5
@ -9915,7 +9915,9 @@ Sorry for the inconvenience.";
|
|||||||
"Gallery.ViewOnceVideoTooltip" = "This video can only be viewed once.";
|
"Gallery.ViewOnceVideoTooltip" = "This video can only be viewed once.";
|
||||||
|
|
||||||
"WebApp.DisclaimerTitle" = "Warning";
|
"WebApp.DisclaimerTitle" = "Warning";
|
||||||
"WebApp.DisclaimerText" = "You are about to use a mini app operated by an independent party not affiliated with Telegram. You must agree to the Terms of Use of mini apps to continue.\n\n**%@** shortcuts will be added in your attachment menu and Settings.";
|
"WebApp.DisclaimerText" = "You are about to use a mini app operated by an independent party not affiliated with Telegram. You must agree to the Terms of Use of mini apps to continue.";
|
||||||
|
"WebApp.DisclaimerShortcutsText" = "**%@** shortcuts will be added in your attachment menu.";
|
||||||
|
"WebApp.DisclaimerShortcutsSettingsText" = "**%@** shortcuts will be added in your attachment menu and Settings.";
|
||||||
"WebApp.DisclaimerAgree" = "I agree to the [Terms of Use]()";
|
"WebApp.DisclaimerAgree" = "I agree to the [Terms of Use]()";
|
||||||
"WebApp.DisclaimerContinue" = "Continue";
|
"WebApp.DisclaimerContinue" = "Continue";
|
||||||
"WebApp.Disclaimer_URL" = "https://telegram.org/tos/mini-apps";
|
"WebApp.Disclaimer_URL" = "https://telegram.org/tos/mini-apps";
|
||||||
|
@ -869,7 +869,7 @@ public protocol SharedAccountContext: AnyObject {
|
|||||||
func makeSetupTwoFactorAuthController(context: AccountContext) -> ViewController
|
func makeSetupTwoFactorAuthController(context: AccountContext) -> ViewController
|
||||||
func makeStorageManagementController(context: AccountContext) -> ViewController
|
func makeStorageManagementController(context: AccountContext) -> ViewController
|
||||||
func makeAttachmentFileController(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)?, bannedSendMedia: (Int32, Bool)?, presentGallery: @escaping () -> Void, presentFiles: @escaping () -> Void, send: @escaping (AnyMediaReference) -> Void) -> AttachmentFileController
|
func makeAttachmentFileController(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)?, bannedSendMedia: (Int32, Bool)?, presentGallery: @escaping () -> Void, presentFiles: @escaping () -> Void, send: @escaping (AnyMediaReference) -> Void) -> AttachmentFileController
|
||||||
func makeGalleryCaptionPanelView(context: AccountContext, chatLocation: ChatLocation, customEmojiAvailable: Bool, present: @escaping (ViewController) -> Void, presentInGlobalOverlay: @escaping (ViewController) -> Void) -> NSObject?
|
func makeGalleryCaptionPanelView(context: AccountContext, chatLocation: ChatLocation, isScheduledMessages: Bool, customEmojiAvailable: Bool, present: @escaping (ViewController) -> Void, presentInGlobalOverlay: @escaping (ViewController) -> Void) -> NSObject?
|
||||||
func makeHashtagSearchController(context: AccountContext, peer: EnginePeer?, query: String, all: Bool) -> ViewController
|
func makeHashtagSearchController(context: AccountContext, peer: EnginePeer?, query: String, all: Bool) -> ViewController
|
||||||
func makeMyStoriesController(context: AccountContext, isArchive: Bool) -> ViewController
|
func makeMyStoriesController(context: AccountContext, isArchive: Bool) -> ViewController
|
||||||
func makeArchiveSettingsController(context: AccountContext) -> ViewController
|
func makeArchiveSettingsController(context: AccountContext) -> ViewController
|
||||||
|
@ -82,6 +82,7 @@ final class AttachmentTextInputActionButtonsNode: ASDisplayNode {
|
|||||||
super.didLoad()
|
super.didLoad()
|
||||||
|
|
||||||
let gestureRecognizer = ContextGesture(target: nil, action: nil)
|
let gestureRecognizer = ContextGesture(target: nil, action: nil)
|
||||||
|
gestureRecognizer.isEnabled = self.sendButtonLongPressEnabled
|
||||||
self.gestureRecognizer = gestureRecognizer
|
self.gestureRecognizer = gestureRecognizer
|
||||||
self.sendButton.view.addGestureRecognizer(gestureRecognizer)
|
self.sendButton.view.addGestureRecognizer(gestureRecognizer)
|
||||||
gestureRecognizer.activated = { [weak self] recognizer, _ in
|
gestureRecognizer.activated = { [weak self] recognizer, _ in
|
||||||
|
@ -327,7 +327,7 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS
|
|||||||
|
|
||||||
private var maxCaptionLength: Int32?
|
private var maxCaptionLength: Int32?
|
||||||
|
|
||||||
public init(context: AccountContext, presentationInterfaceState: ChatPresentationInterfaceState, isCaption: Bool = false, isAttachment: Bool = false, presentController: @escaping (ViewController) -> Void, makeEntityInputView: @escaping () -> AttachmentTextInputPanelInputView?) {
|
public init(context: AccountContext, presentationInterfaceState: ChatPresentationInterfaceState, isCaption: Bool = false, isAttachment: Bool = false, isScheduledMessages: Bool = false, presentController: @escaping (ViewController) -> Void, makeEntityInputView: @escaping () -> AttachmentTextInputPanelInputView?) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.presentationInterfaceState = presentationInterfaceState
|
self.presentationInterfaceState = presentationInterfaceState
|
||||||
self.isCaption = isCaption
|
self.isCaption = isCaption
|
||||||
@ -374,8 +374,13 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS
|
|||||||
|
|
||||||
super.init()
|
super.init()
|
||||||
|
|
||||||
self.actionButtons.sendButtonLongPressed = { [weak self] node, gesture in
|
if !isScheduledMessages {
|
||||||
self?.interfaceInteraction?.displaySendMessageOptions(node, gesture)
|
self.actionButtons.sendButtonLongPressed = { [weak self] node, gesture in
|
||||||
|
self?.interfaceInteraction?.displaySendMessageOptions(node, gesture)
|
||||||
|
}
|
||||||
|
self.actionButtons.sendButtonLongPressEnabled = true
|
||||||
|
} else {
|
||||||
|
self.actionButtons.sendButtonLongPressEnabled = false
|
||||||
}
|
}
|
||||||
|
|
||||||
self.actionButtons.sendButton.addTarget(self, action: #selector(self.sendButtonPressed), forControlEvents: .touchUpInside)
|
self.actionButtons.sendButton.addTarget(self, action: #selector(self.sendButtonPressed), forControlEvents: .touchUpInside)
|
||||||
@ -727,8 +732,6 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS
|
|||||||
}
|
}
|
||||||
self.textPlaceholderNode.frame = CGRect(origin: self.textPlaceholderNode.frame.origin, size: placeholderSize)
|
self.textPlaceholderNode.frame = CGRect(origin: self.textPlaceholderNode.frame.origin, size: placeholderSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
self.actionButtons.sendButtonLongPressEnabled = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let sendButtonHasApplyIcon = self.isCaption || interfaceState.interfaceState.editMessage != nil
|
let sendButtonHasApplyIcon = self.isCaption || interfaceState.interfaceState.editMessage != nil
|
||||||
|
@ -179,6 +179,7 @@ public class AttachmentController: ViewController {
|
|||||||
private let context: AccountContext
|
private let context: AccountContext
|
||||||
private let updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)?
|
private let updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)?
|
||||||
private let chatLocation: ChatLocation?
|
private let chatLocation: ChatLocation?
|
||||||
|
private let isScheduledMessages: Bool
|
||||||
private let buttons: [AttachmentButtonType]
|
private let buttons: [AttachmentButtonType]
|
||||||
private let initialButton: AttachmentButtonType
|
private let initialButton: AttachmentButtonType
|
||||||
private let fromMenu: Bool
|
private let fromMenu: Bool
|
||||||
@ -294,7 +295,7 @@ public class AttachmentController: ViewController {
|
|||||||
|
|
||||||
self.container = AttachmentContainer()
|
self.container = AttachmentContainer()
|
||||||
self.container.canHaveKeyboardFocus = true
|
self.container.canHaveKeyboardFocus = true
|
||||||
self.panel = AttachmentPanel(context: controller.context, chatLocation: controller.chatLocation, updatedPresentationData: controller.updatedPresentationData, makeEntityInputView: makeEntityInputView)
|
self.panel = AttachmentPanel(context: controller.context, chatLocation: controller.chatLocation, isScheduledMessages: controller.isScheduledMessages, updatedPresentationData: controller.updatedPresentationData, makeEntityInputView: makeEntityInputView)
|
||||||
self.panel.fromMenu = controller.fromMenu
|
self.panel.fromMenu = controller.fromMenu
|
||||||
self.panel.isStandalone = controller.isStandalone
|
self.panel.isStandalone = controller.isStandalone
|
||||||
|
|
||||||
@ -907,10 +908,11 @@ public class AttachmentController: ViewController {
|
|||||||
|
|
||||||
public var getSourceRect: (() -> CGRect?)?
|
public var getSourceRect: (() -> CGRect?)?
|
||||||
|
|
||||||
public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil, chatLocation: ChatLocation?, buttons: [AttachmentButtonType], initialButton: AttachmentButtonType = .gallery, fromMenu: Bool = false, hasTextInput: Bool = true, makeEntityInputView: @escaping () -> AttachmentTextInputPanelInputView? = { return nil}) {
|
public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil, chatLocation: ChatLocation?, isScheduledMessages: Bool = false, buttons: [AttachmentButtonType], initialButton: AttachmentButtonType = .gallery, fromMenu: Bool = false, hasTextInput: Bool = true, makeEntityInputView: @escaping () -> AttachmentTextInputPanelInputView? = { return nil}) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.updatedPresentationData = updatedPresentationData
|
self.updatedPresentationData = updatedPresentationData
|
||||||
self.chatLocation = chatLocation
|
self.chatLocation = chatLocation
|
||||||
|
self.isScheduledMessages = isScheduledMessages
|
||||||
self.buttons = buttons
|
self.buttons = buttons
|
||||||
self.initialButton = initialButton
|
self.initialButton = initialButton
|
||||||
self.fromMenu = fromMenu
|
self.fromMenu = fromMenu
|
||||||
|
@ -725,6 +725,7 @@ private final class MainButtonNode: HighlightTrackingButtonNode {
|
|||||||
|
|
||||||
final class AttachmentPanel: ASDisplayNode, UIScrollViewDelegate {
|
final class AttachmentPanel: ASDisplayNode, UIScrollViewDelegate {
|
||||||
private let context: AccountContext
|
private let context: AccountContext
|
||||||
|
private let isScheduledMessages: Bool
|
||||||
private var presentationData: PresentationData
|
private var presentationData: PresentationData
|
||||||
private var presentationDataDisposable: Disposable?
|
private var presentationDataDisposable: Disposable?
|
||||||
|
|
||||||
@ -775,9 +776,10 @@ final class AttachmentPanel: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
|
|
||||||
var mainButtonPressed: () -> Void = { }
|
var mainButtonPressed: () -> Void = { }
|
||||||
|
|
||||||
init(context: AccountContext, chatLocation: ChatLocation?, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)?, makeEntityInputView: @escaping () -> AttachmentTextInputPanelInputView?) {
|
init(context: AccountContext, chatLocation: ChatLocation?, isScheduledMessages: Bool, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)?, makeEntityInputView: @escaping () -> AttachmentTextInputPanelInputView?) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.presentationData = updatedPresentationData?.initial ?? context.sharedContext.currentPresentationData.with { $0 }
|
self.presentationData = updatedPresentationData?.initial ?? context.sharedContext.currentPresentationData.with { $0 }
|
||||||
|
self.isScheduledMessages = isScheduledMessages
|
||||||
|
|
||||||
self.makeEntityInputView = makeEntityInputView
|
self.makeEntityInputView = makeEntityInputView
|
||||||
|
|
||||||
@ -1248,7 +1250,7 @@ final class AttachmentPanel: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
private func loadTextNodeIfNeeded() {
|
private func loadTextNodeIfNeeded() {
|
||||||
if let _ = self.textInputPanelNode {
|
if let _ = self.textInputPanelNode {
|
||||||
} else {
|
} else {
|
||||||
let textInputPanelNode = AttachmentTextInputPanelNode(context: self.context, presentationInterfaceState: self.presentationInterfaceState, isAttachment: true, presentController: { [weak self] c in
|
let textInputPanelNode = AttachmentTextInputPanelNode(context: self.context, presentationInterfaceState: self.presentationInterfaceState, isAttachment: true, isScheduledMessages: self.isScheduledMessages, presentController: { [weak self] c in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
strongSelf.present(c)
|
strongSelf.present(c)
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@ public final class ChatSendMessageActionSheetController: ViewController {
|
|||||||
private let context: AccountContext
|
private let context: AccountContext
|
||||||
|
|
||||||
private let peerId: EnginePeer.Id?
|
private let peerId: EnginePeer.Id?
|
||||||
|
private let isScheduledMessages: Bool
|
||||||
private let forwardMessageIds: [EngineMessage.Id]?
|
private let forwardMessageIds: [EngineMessage.Id]?
|
||||||
private let hasEntityKeyboard: Bool
|
private let hasEntityKeyboard: Bool
|
||||||
|
|
||||||
@ -45,9 +46,10 @@ public final class ChatSendMessageActionSheetController: ViewController {
|
|||||||
|
|
||||||
public var emojiViewProvider: ((ChatTextInputTextCustomEmojiAttribute) -> UIView)?
|
public var emojiViewProvider: ((ChatTextInputTextCustomEmojiAttribute) -> UIView)?
|
||||||
|
|
||||||
public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil, peerId: EnginePeer.Id?, forwardMessageIds: [EngineMessage.Id]?, hasEntityKeyboard: Bool, gesture: ContextGesture, sourceSendButton: ASDisplayNode, textInputNode: EditableTextNode, attachment: Bool = false, canSendWhenOnline: Bool, completion: @escaping () -> Void, sendMessage: @escaping (SendMode) -> Void, schedule: @escaping () -> Void) {
|
public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil, peerId: EnginePeer.Id?, isScheduledMessages: Bool = false, forwardMessageIds: [EngineMessage.Id]?, hasEntityKeyboard: Bool, gesture: ContextGesture, sourceSendButton: ASDisplayNode, textInputNode: EditableTextNode, attachment: Bool = false, canSendWhenOnline: Bool, completion: @escaping () -> Void, sendMessage: @escaping (SendMode) -> Void, schedule: @escaping () -> Void) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.peerId = peerId
|
self.peerId = peerId
|
||||||
|
self.isScheduledMessages = isScheduledMessages
|
||||||
self.forwardMessageIds = forwardMessageIds
|
self.forwardMessageIds = forwardMessageIds
|
||||||
self.hasEntityKeyboard = hasEntityKeyboard
|
self.hasEntityKeyboard = hasEntityKeyboard
|
||||||
self.gesture = gesture
|
self.gesture = gesture
|
||||||
@ -101,6 +103,9 @@ public final class ChatSendMessageActionSheetController: ViewController {
|
|||||||
isSecret = peerId.namespace == Namespaces.Peer.SecretChat
|
isSecret = peerId.namespace == Namespaces.Peer.SecretChat
|
||||||
canSchedule = !isSecret
|
canSchedule = !isSecret
|
||||||
}
|
}
|
||||||
|
if self.isScheduledMessages {
|
||||||
|
canSchedule = false
|
||||||
|
}
|
||||||
|
|
||||||
self.displayNode = ChatSendMessageActionSheetControllerNode(context: self.context, presentationData: self.presentationData, reminders: reminders, gesture: gesture, sourceSendButton: self.sourceSendButton, textInputNode: self.textInputNode, attachment: self.attachment, canSendWhenOnline: self.canSendWhenOnline, forwardedCount: forwardedCount, hasEntityKeyboard: self.hasEntityKeyboard, emojiViewProvider: self.emojiViewProvider, send: { [weak self] in
|
self.displayNode = ChatSendMessageActionSheetControllerNode(context: self.context, presentationData: self.presentationData, reminders: reminders, gesture: gesture, sourceSendButton: self.sourceSendButton, textInputNode: self.textInputNode, attachment: self.attachment, canSendWhenOnline: self.canSendWhenOnline, forwardedCount: forwardedCount, hasEntityKeyboard: self.hasEntityKeyboard, emojiViewProvider: self.emojiViewProvider, send: { [weak self] in
|
||||||
self?.sendMessage(.generic)
|
self?.sendMessage(.generic)
|
||||||
|
@ -100,7 +100,7 @@ enum LegacyMediaPickerGallerySource {
|
|||||||
case selection(item: TGMediaSelectableItem)
|
case selection(item: TGMediaSelectableItem)
|
||||||
}
|
}
|
||||||
|
|
||||||
func presentLegacyMediaPickerGallery(context: AccountContext, peer: EnginePeer?, threadTitle: String?, chatLocation: ChatLocation?, presentationData: PresentationData, source: LegacyMediaPickerGallerySource, immediateThumbnail: UIImage?, selectionContext: TGMediaSelectionContext?, editingContext: TGMediaEditingContext, hasSilentPosting: Bool, hasSchedule: Bool, hasTimer: Bool, updateHiddenMedia: @escaping (String?) -> Void, initialLayout: ContainerViewLayout?, transitionHostView: @escaping () -> UIView?, transitionView: @escaping (String) -> UIView?, completed: @escaping (TGMediaSelectableItem & TGMediaEditableItem, Bool, Int32?, @escaping () -> Void) -> Void, presentSchedulePicker: @escaping (Bool, @escaping (Int32) -> Void) -> Void, presentTimerPicker: @escaping (@escaping (Int32) -> Void) -> Void, getCaptionPanelView: @escaping () -> TGCaptionPanelView?, present: @escaping (ViewController, Any?) -> Void, finishedTransitionIn: @escaping () -> Void, willTransitionOut: @escaping () -> Void, dismissAll: @escaping () -> Void) -> TGModernGalleryController {
|
func presentLegacyMediaPickerGallery(context: AccountContext, peer: EnginePeer?, threadTitle: String?, chatLocation: ChatLocation?, isScheduledMessages: Bool, presentationData: PresentationData, source: LegacyMediaPickerGallerySource, immediateThumbnail: UIImage?, selectionContext: TGMediaSelectionContext?, editingContext: TGMediaEditingContext, hasSilentPosting: Bool, hasSchedule: Bool, hasTimer: Bool, updateHiddenMedia: @escaping (String?) -> Void, initialLayout: ContainerViewLayout?, transitionHostView: @escaping () -> UIView?, transitionView: @escaping (String) -> UIView?, completed: @escaping (TGMediaSelectableItem & TGMediaEditableItem, Bool, Int32?, @escaping () -> Void) -> Void, presentSchedulePicker: @escaping (Bool, @escaping (Int32) -> Void) -> Void, presentTimerPicker: @escaping (@escaping (Int32) -> Void) -> Void, getCaptionPanelView: @escaping () -> TGCaptionPanelView?, present: @escaping (ViewController, Any?) -> Void, finishedTransitionIn: @escaping () -> Void, willTransitionOut: @escaping () -> Void, dismissAll: @escaping () -> Void) -> TGModernGalleryController {
|
||||||
let reminder = peer?.id == context.account.peerId
|
let reminder = peer?.id == context.account.peerId
|
||||||
let hasSilentPosting = hasSilentPosting && peer?.id != context.account.peerId
|
let hasSilentPosting = hasSilentPosting && peer?.id != context.account.peerId
|
||||||
|
|
||||||
@ -224,103 +224,105 @@ func presentLegacyMediaPickerGallery(context: AccountContext, peer: EnginePeer?,
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
model.interfaceView.doneLongPressed = { [weak selectionContext, weak editingContext, weak legacyController, weak model] item in
|
if !isScheduledMessages {
|
||||||
if let legacyController = legacyController, let item = item as? TGMediaPickerGalleryItem, let model = model, let selectionContext = selectionContext {
|
model.interfaceView.doneLongPressed = { [weak selectionContext, weak editingContext, weak legacyController, weak model] item in
|
||||||
var effectiveHasSchedule = hasSchedule
|
if let legacyController = legacyController, let item = item as? TGMediaPickerGalleryItem, let model = model, let selectionContext = selectionContext {
|
||||||
|
var effectiveHasSchedule = hasSchedule
|
||||||
if let editingContext = editingContext {
|
|
||||||
if let timer = editingContext.timer(for: item.asset)?.intValue, timer > 0 {
|
if let editingContext = editingContext {
|
||||||
effectiveHasSchedule = false
|
if let timer = editingContext.timer(for: item.asset)?.intValue, timer > 0 {
|
||||||
}
|
|
||||||
for item in selectionContext.selectedItems() {
|
|
||||||
if let editableItem = item as? TGMediaEditableItem, let timer = editingContext.timer(for: editableItem)?.intValue, timer > 0 {
|
|
||||||
effectiveHasSchedule = false
|
effectiveHasSchedule = false
|
||||||
break
|
|
||||||
}
|
}
|
||||||
}
|
for item in selectionContext.selectedItems() {
|
||||||
}
|
if let editableItem = item as? TGMediaEditableItem, let timer = editingContext.timer(for: editableItem)?.intValue, timer > 0 {
|
||||||
|
effectiveHasSchedule = false
|
||||||
let sendWhenOnlineAvailable: Signal<Bool, NoError>
|
break
|
||||||
if let peer {
|
|
||||||
if case .secretChat = peer {
|
|
||||||
effectiveHasSchedule = false
|
|
||||||
}
|
|
||||||
sendWhenOnlineAvailable = context.account.viewTracker.peerView(peer.id)
|
|
||||||
|> take(1)
|
|
||||||
|> map { peerView -> Bool in
|
|
||||||
guard let peer = peerViewMainPeer(peerView) else {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
var sendWhenOnlineAvailable = false
|
|
||||||
if let presence = peerView.peerPresences[peer.id] as? TelegramUserPresence, case let .present(until) = presence.status {
|
|
||||||
let currentTime = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970)
|
|
||||||
if currentTime > until {
|
|
||||||
sendWhenOnlineAvailable = true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if peer.id.namespace == Namespaces.Peer.CloudUser && peer.id.id._internalGetInt64Value() == 777000 {
|
}
|
||||||
sendWhenOnlineAvailable = false
|
|
||||||
|
let sendWhenOnlineAvailable: Signal<Bool, NoError>
|
||||||
|
if let peer {
|
||||||
|
if case .secretChat = peer {
|
||||||
|
effectiveHasSchedule = false
|
||||||
}
|
}
|
||||||
return sendWhenOnlineAvailable
|
sendWhenOnlineAvailable = context.account.viewTracker.peerView(peer.id)
|
||||||
}
|
|> take(1)
|
||||||
} else {
|
|> map { peerView -> Bool in
|
||||||
sendWhenOnlineAvailable = .single(false)
|
guard let peer = peerViewMainPeer(peerView) else {
|
||||||
}
|
return false
|
||||||
|
|
||||||
let _ = (sendWhenOnlineAvailable
|
|
||||||
|> take(1)
|
|
||||||
|> deliverOnMainQueue).start(next: { sendWhenOnlineAvailable in
|
|
||||||
let legacySheetController = LegacyController(presentation: .custom, theme: presentationData.theme, initialLayout: nil)
|
|
||||||
let sheetController = TGMediaPickerSendActionSheetController(context: legacyController.context, isDark: true, sendButtonFrame: model.interfaceView.doneButtonFrame, canSendSilently: hasSilentPosting, canSendWhenOnline: sendWhenOnlineAvailable && effectiveHasSchedule, canSchedule: effectiveHasSchedule, reminder: reminder, hasTimer: false)
|
|
||||||
let dismissImpl = { [weak model] in
|
|
||||||
model?.dismiss(true, false)
|
|
||||||
dismissAll()
|
|
||||||
}
|
|
||||||
sheetController.send = {
|
|
||||||
completed(item.asset, false, nil, {
|
|
||||||
dismissImpl()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
sheetController.sendSilently = {
|
|
||||||
completed(item.asset, true, nil, {
|
|
||||||
dismissImpl()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
sheetController.sendWhenOnline = {
|
|
||||||
completed(item.asset, false, scheduleWhenOnlineTimestamp, {
|
|
||||||
dismissImpl()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
sheetController.schedule = {
|
|
||||||
presentSchedulePicker(true, { time in
|
|
||||||
completed(item.asset, false, time, {
|
|
||||||
dismissImpl()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
sheetController.sendWithTimer = {
|
|
||||||
presentTimerPicker { time in
|
|
||||||
var items = selectionContext.selectedItems() ?? []
|
|
||||||
items.append(item.asset as Any)
|
|
||||||
|
|
||||||
for case let item as TGMediaEditableItem in items {
|
|
||||||
editingContext?.setTimer(time as NSNumber, for: item)
|
|
||||||
}
|
}
|
||||||
|
var sendWhenOnlineAvailable = false
|
||||||
|
if let presence = peerView.peerPresences[peer.id] as? TelegramUserPresence, case let .present(until) = presence.status {
|
||||||
|
let currentTime = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970)
|
||||||
|
if currentTime > until {
|
||||||
|
sendWhenOnlineAvailable = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if peer.id.namespace == Namespaces.Peer.CloudUser && peer.id.id._internalGetInt64Value() == 777000 {
|
||||||
|
sendWhenOnlineAvailable = false
|
||||||
|
}
|
||||||
|
return sendWhenOnlineAvailable
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sendWhenOnlineAvailable = .single(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
let _ = (sendWhenOnlineAvailable
|
||||||
|
|> take(1)
|
||||||
|
|> deliverOnMainQueue).start(next: { sendWhenOnlineAvailable in
|
||||||
|
let legacySheetController = LegacyController(presentation: .custom, theme: presentationData.theme, initialLayout: nil)
|
||||||
|
let sheetController = TGMediaPickerSendActionSheetController(context: legacyController.context, isDark: true, sendButtonFrame: model.interfaceView.doneButtonFrame, canSendSilently: hasSilentPosting, canSendWhenOnline: sendWhenOnlineAvailable && effectiveHasSchedule, canSchedule: effectiveHasSchedule, reminder: reminder, hasTimer: false)
|
||||||
|
let dismissImpl = { [weak model] in
|
||||||
|
model?.dismiss(true, false)
|
||||||
|
dismissAll()
|
||||||
|
}
|
||||||
|
sheetController.send = {
|
||||||
completed(item.asset, false, nil, {
|
completed(item.asset, false, nil, {
|
||||||
dismissImpl()
|
dismissImpl()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
sheetController.sendSilently = {
|
||||||
sheetController.customDismissBlock = { [weak legacySheetController] in
|
completed(item.asset, true, nil, {
|
||||||
legacySheetController?.dismiss()
|
dismissImpl()
|
||||||
}
|
})
|
||||||
legacySheetController.bind(controller: sheetController)
|
}
|
||||||
present(legacySheetController, nil)
|
sheetController.sendWhenOnline = {
|
||||||
|
completed(item.asset, false, scheduleWhenOnlineTimestamp, {
|
||||||
let hapticFeedback = HapticFeedback()
|
dismissImpl()
|
||||||
hapticFeedback.impact()
|
})
|
||||||
})
|
}
|
||||||
|
sheetController.schedule = {
|
||||||
|
presentSchedulePicker(true, { time in
|
||||||
|
completed(item.asset, false, time, {
|
||||||
|
dismissImpl()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
sheetController.sendWithTimer = {
|
||||||
|
presentTimerPicker { time in
|
||||||
|
var items = selectionContext.selectedItems() ?? []
|
||||||
|
items.append(item.asset as Any)
|
||||||
|
|
||||||
|
for case let item as TGMediaEditableItem in items {
|
||||||
|
editingContext?.setTimer(time as NSNumber, for: item)
|
||||||
|
}
|
||||||
|
|
||||||
|
completed(item.asset, false, nil, {
|
||||||
|
dismissImpl()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sheetController.customDismissBlock = { [weak legacySheetController] in
|
||||||
|
legacySheetController?.dismiss()
|
||||||
|
}
|
||||||
|
legacySheetController.bind(controller: sheetController)
|
||||||
|
present(legacySheetController, nil)
|
||||||
|
|
||||||
|
let hapticFeedback = HapticFeedback()
|
||||||
|
hapticFeedback.impact()
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
model.interfaceView.setThumbnailSignalForItem { item in
|
model.interfaceView.setThumbnailSignalForItem { item in
|
||||||
|
@ -169,6 +169,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
|
|||||||
fileprivate var interaction: MediaPickerInteraction?
|
fileprivate var interaction: MediaPickerInteraction?
|
||||||
|
|
||||||
private let peer: EnginePeer?
|
private let peer: EnginePeer?
|
||||||
|
private let isScheduledMessages: Bool
|
||||||
private let threadTitle: String?
|
private let threadTitle: String?
|
||||||
private let chatLocation: ChatLocation?
|
private let chatLocation: ChatLocation?
|
||||||
private let bannedSendPhotos: (Int32, Bool)?
|
private let bannedSendPhotos: (Int32, Bool)?
|
||||||
@ -970,7 +971,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
|
|||||||
|
|
||||||
self.openingMedia = true
|
self.openingMedia = true
|
||||||
|
|
||||||
self.currentGalleryController = presentLegacyMediaPickerGallery(context: controller.context, peer: controller.peer, threadTitle: controller.threadTitle, chatLocation: controller.chatLocation, presentationData: self.presentationData, source: .fetchResult(fetchResult: fetchResult, index: index, reversed: reversed), immediateThumbnail: immediateThumbnail, selectionContext: interaction.selectionState, editingContext: interaction.editingState, hasSilentPosting: true, hasSchedule: hasSchedule, hasTimer: hasTimer, updateHiddenMedia: { [weak self] id in
|
self.currentGalleryController = presentLegacyMediaPickerGallery(context: controller.context, peer: controller.peer, threadTitle: controller.threadTitle, chatLocation: controller.chatLocation, isScheduledMessages: controller.isScheduledMessages, presentationData: self.presentationData, source: .fetchResult(fetchResult: fetchResult, index: index, reversed: reversed), immediateThumbnail: immediateThumbnail, selectionContext: interaction.selectionState, editingContext: interaction.editingState, hasSilentPosting: true, hasSchedule: hasSchedule, hasTimer: hasTimer, updateHiddenMedia: { [weak self] id in
|
||||||
self?.hiddenMediaId.set(.single(id))
|
self?.hiddenMediaId.set(.single(id))
|
||||||
}, initialLayout: layout, transitionHostView: { [weak self] in
|
}, initialLayout: layout, transitionHostView: { [weak self] in
|
||||||
return self?.gridNode.view
|
return self?.gridNode.view
|
||||||
@ -1009,7 +1010,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.openingMedia = true
|
self.openingMedia = true
|
||||||
self.currentGalleryController = presentLegacyMediaPickerGallery(context: controller.context, peer: controller.peer, threadTitle: controller.threadTitle, chatLocation: controller.chatLocation, presentationData: self.presentationData, source: .selection(item: item), immediateThumbnail: immediateThumbnail, selectionContext: interaction.selectionState, editingContext: interaction.editingState, hasSilentPosting: true, hasSchedule: true, hasTimer: hasTimer, updateHiddenMedia: { [weak self] id in
|
self.currentGalleryController = presentLegacyMediaPickerGallery(context: controller.context, peer: controller.peer, threadTitle: controller.threadTitle, chatLocation: controller.chatLocation, isScheduledMessages: controller.isScheduledMessages, presentationData: self.presentationData, source: .selection(item: item), immediateThumbnail: immediateThumbnail, selectionContext: interaction.selectionState, editingContext: interaction.editingState, hasSilentPosting: true, hasSchedule: true, hasTimer: hasTimer, updateHiddenMedia: { [weak self] id in
|
||||||
self?.hiddenMediaId.set(.single(id))
|
self?.hiddenMediaId.set(.single(id))
|
||||||
}, initialLayout: layout, transitionHostView: { [weak self] in
|
}, initialLayout: layout, transitionHostView: { [weak self] in
|
||||||
return self?.selectionNode?.view
|
return self?.selectionNode?.view
|
||||||
@ -1524,6 +1525,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
|
|||||||
peer: EnginePeer?,
|
peer: EnginePeer?,
|
||||||
threadTitle: String?,
|
threadTitle: String?,
|
||||||
chatLocation: ChatLocation?,
|
chatLocation: ChatLocation?,
|
||||||
|
isScheduledMessages: Bool = false,
|
||||||
bannedSendPhotos: (Int32, Bool)?,
|
bannedSendPhotos: (Int32, Bool)?,
|
||||||
bannedSendVideos: (Int32, Bool)?,
|
bannedSendVideos: (Int32, Bool)?,
|
||||||
subject: Subject,
|
subject: Subject,
|
||||||
@ -1541,6 +1543,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
|
|||||||
self.peer = peer
|
self.peer = peer
|
||||||
self.threadTitle = threadTitle
|
self.threadTitle = threadTitle
|
||||||
self.chatLocation = chatLocation
|
self.chatLocation = chatLocation
|
||||||
|
self.isScheduledMessages = isScheduledMessages
|
||||||
self.bannedSendPhotos = bannedSendPhotos
|
self.bannedSendPhotos = bannedSendPhotos
|
||||||
self.bannedSendVideos = bannedSendVideos
|
self.bannedSendVideos = bannedSendVideos
|
||||||
self.subject = subject
|
self.subject = subject
|
||||||
@ -2104,7 +2107,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
|
|||||||
var updateNavigationStackImpl: ((AttachmentContainable) -> Void)?
|
var updateNavigationStackImpl: ((AttachmentContainable) -> Void)?
|
||||||
let groupsController = MediaGroupsScreen(context: self.context, updatedPresentationData: self.updatedPresentationData, mediaAssetsContext: self.controllerNode.mediaAssetsContext, embedded: embedded, openGroup: { [weak self] collection in
|
let groupsController = MediaGroupsScreen(context: self.context, updatedPresentationData: self.updatedPresentationData, mediaAssetsContext: self.controllerNode.mediaAssetsContext, embedded: embedded, openGroup: { [weak self] collection in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
let mediaPicker = MediaPickerScreen(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, peer: strongSelf.peer, threadTitle: strongSelf.threadTitle, chatLocation: strongSelf.chatLocation, bannedSendPhotos: strongSelf.bannedSendPhotos, bannedSendVideos: strongSelf.bannedSendVideos, subject: .assets(collection, mode), editingContext: strongSelf.interaction?.editingState, selectionContext: strongSelf.interaction?.selectionState)
|
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)
|
||||||
|
|
||||||
mediaPicker.presentSchedulePicker = strongSelf.presentSchedulePicker
|
mediaPicker.presentSchedulePicker = strongSelf.presentSchedulePicker
|
||||||
mediaPicker.presentTimerPicker = strongSelf.presentTimerPicker
|
mediaPicker.presentTimerPicker = strongSelf.presentTimerPicker
|
||||||
|
@ -191,6 +191,10 @@ public final class AttachMenuBots: Equatable, Codable {
|
|||||||
|
|
||||||
try container.encode(Int32(self.flags.rawValue), forKey: .flags)
|
try container.encode(Int32(self.flags.rawValue), forKey: .flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func withUpdatedFlags(_ flags: Flags) -> Bot {
|
||||||
|
return Bot(peerId: self.peerId, name: self.name, icons: self.icons, peerTypes: self.peerTypes, flags: flags)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private enum CodingKeys: String, CodingKey {
|
private enum CodingKeys: String, CodingKey {
|
||||||
@ -442,6 +446,23 @@ func _internal_removeBotFromAttachMenu(accountPeerId: PeerId, postbox: Postbox,
|
|||||||
|> switchToLatest
|
|> switchToLatest
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func _internal_acceptAttachMenuBotDisclaimer(postbox: Postbox, botId: PeerId) -> Signal<Never, NoError> {
|
||||||
|
return postbox.transaction { transaction in
|
||||||
|
if let attachMenuBots = cachedAttachMenuBots(transaction: transaction) {
|
||||||
|
var updatedAttachMenuBots = attachMenuBots
|
||||||
|
if let index = attachMenuBots.bots.firstIndex(where: { $0.peerId == botId }) {
|
||||||
|
var updatedFlags = attachMenuBots.bots[index].flags
|
||||||
|
updatedFlags.remove(.showInSettingsDisclaimer)
|
||||||
|
let updatedBot = attachMenuBots.bots[index].withUpdatedFlags(updatedFlags)
|
||||||
|
var updatedBots = attachMenuBots.bots
|
||||||
|
updatedBots[index] = updatedBot
|
||||||
|
updatedAttachMenuBots = AttachMenuBots(hash: attachMenuBots.hash, bots: updatedBots)
|
||||||
|
}
|
||||||
|
setCachedAttachMenuBots(transaction: transaction, attachMenuBots: updatedAttachMenuBots)
|
||||||
|
}
|
||||||
|
} |> ignoreValues
|
||||||
|
}
|
||||||
|
|
||||||
public struct AttachMenuBot {
|
public struct AttachMenuBot {
|
||||||
public let peer: EnginePeer
|
public let peer: EnginePeer
|
||||||
public let shortName: String
|
public let shortName: String
|
||||||
@ -449,7 +470,7 @@ public struct AttachMenuBot {
|
|||||||
public let peerTypes: AttachMenuBots.Bot.PeerFlags
|
public let peerTypes: AttachMenuBots.Bot.PeerFlags
|
||||||
public let flags: AttachMenuBots.Bot.Flags
|
public let flags: AttachMenuBots.Bot.Flags
|
||||||
|
|
||||||
init(peer: EnginePeer, shortName: String, icons: [AttachMenuBots.Bot.IconName: TelegramMediaFile], peerTypes: AttachMenuBots.Bot.PeerFlags, flags: AttachMenuBots.Bot.Flags) {
|
public init(peer: EnginePeer, shortName: String, icons: [AttachMenuBots.Bot.IconName: TelegramMediaFile], peerTypes: AttachMenuBots.Bot.PeerFlags, flags: AttachMenuBots.Bot.Flags) {
|
||||||
self.peer = peer
|
self.peer = peer
|
||||||
self.shortName = shortName
|
self.shortName = shortName
|
||||||
self.icons = icons
|
self.icons = icons
|
||||||
|
@ -531,6 +531,10 @@ public extension TelegramEngine {
|
|||||||
return _internal_removeBotFromAttachMenu(accountPeerId: self.account.peerId, postbox: self.account.postbox, network: self.account.network, botId: botId)
|
return _internal_removeBotFromAttachMenu(accountPeerId: self.account.peerId, postbox: self.account.postbox, network: self.account.network, botId: botId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func acceptAttachMenuBotDisclaimer(botId: PeerId) -> Signal<Never, NoError> {
|
||||||
|
return _internal_acceptAttachMenuBotDisclaimer(postbox: self.account.postbox, botId: botId)
|
||||||
|
}
|
||||||
|
|
||||||
public func getAttachMenuBot(botId: PeerId, cached: Bool = false) -> Signal<AttachMenuBot, GetAttachMenuBotError> {
|
public func getAttachMenuBot(botId: PeerId, cached: Bool = false) -> Signal<AttachMenuBot, GetAttachMenuBotError> {
|
||||||
return _internal_getAttachMenuBot(accountPeerId: self.account.peerId, postbox: self.account.postbox, network: self.account.network, botId: botId, cached: cached)
|
return _internal_getAttachMenuBot(accountPeerId: self.account.peerId, postbox: self.account.postbox, network: self.account.network, botId: botId, cached: cached)
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ import TooltipUI
|
|||||||
public class LegacyMessageInputPanelNode: ASDisplayNode, TGCaptionPanelView {
|
public class LegacyMessageInputPanelNode: ASDisplayNode, TGCaptionPanelView {
|
||||||
private let context: AccountContext
|
private let context: AccountContext
|
||||||
private let chatLocation: ChatLocation
|
private let chatLocation: ChatLocation
|
||||||
|
private let isScheduledMessages: Bool
|
||||||
private let present: (ViewController) -> Void
|
private let present: (ViewController) -> Void
|
||||||
private let presentInGlobalOverlay: (ViewController) -> Void
|
private let presentInGlobalOverlay: (ViewController) -> Void
|
||||||
|
|
||||||
@ -35,11 +36,13 @@ public class LegacyMessageInputPanelNode: ASDisplayNode, TGCaptionPanelView {
|
|||||||
public init(
|
public init(
|
||||||
context: AccountContext,
|
context: AccountContext,
|
||||||
chatLocation: ChatLocation,
|
chatLocation: ChatLocation,
|
||||||
|
isScheduledMessages: Bool,
|
||||||
present: @escaping (ViewController) -> Void,
|
present: @escaping (ViewController) -> Void,
|
||||||
presentInGlobalOverlay: @escaping (ViewController) -> Void
|
presentInGlobalOverlay: @escaping (ViewController) -> Void
|
||||||
) {
|
) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.chatLocation = chatLocation
|
self.chatLocation = chatLocation
|
||||||
|
self.isScheduledMessages = isScheduledMessages
|
||||||
self.present = present
|
self.present = present
|
||||||
self.presentInGlobalOverlay = presentInGlobalOverlay
|
self.presentInGlobalOverlay = presentInGlobalOverlay
|
||||||
|
|
||||||
@ -164,7 +167,7 @@ public class LegacyMessageInputPanelNode: ASDisplayNode, TGCaptionPanelView {
|
|||||||
strings: presentationData.strings,
|
strings: presentationData.strings,
|
||||||
style: .media,
|
style: .media,
|
||||||
placeholder: .plain(presentationData.strings.MediaPicker_AddCaption),
|
placeholder: .plain(presentationData.strings.MediaPicker_AddCaption),
|
||||||
maxLength: 1024,
|
maxLength: Int(self.context.userLimits.maxCaptionLength),
|
||||||
queryTypes: [.mention],
|
queryTypes: [.mention],
|
||||||
alwaysDarkWhenHasText: false,
|
alwaysDarkWhenHasText: false,
|
||||||
resetInputContents: resetInputContents,
|
resetInputContents: resetInputContents,
|
||||||
@ -191,7 +194,7 @@ public class LegacyMessageInputPanelNode: ASDisplayNode, TGCaptionPanelView {
|
|||||||
likeAction: nil,
|
likeAction: nil,
|
||||||
likeOptionsAction: nil,
|
likeOptionsAction: nil,
|
||||||
inputModeAction: nil,
|
inputModeAction: nil,
|
||||||
timeoutAction: self.chatLocation.peerId?.namespace == Namespaces.Peer.CloudUser ? { [weak self] sourceView, gesture in
|
timeoutAction: self.chatLocation.peerId?.namespace == Namespaces.Peer.CloudUser && !self.isScheduledMessages ? { [weak self] sourceView, gesture in
|
||||||
if let self {
|
if let self {
|
||||||
self.presentTimeoutSetup(sourceView: sourceView, gesture: gesture)
|
self.presentTimeoutSetup(sourceView: sourceView, gesture: gesture)
|
||||||
}
|
}
|
||||||
|
@ -2301,7 +2301,7 @@ final class StoryItemSetContainerSendMessage {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
//TODO:self.presentationInterfaceState.customEmojiAvailable
|
//TODO:self.presentationInterfaceState.customEmojiAvailable
|
||||||
return component.context.sharedContext.makeGalleryCaptionPanelView(context: component.context, chatLocation: .peer(id: peer.id), customEmojiAvailable: true, present: { [weak view] c in
|
return component.context.sharedContext.makeGalleryCaptionPanelView(context: component.context, chatLocation: .peer(id: peer.id), isScheduledMessages: false, customEmojiAvailable: true, present: { [weak view] c in
|
||||||
guard let view else {
|
guard let view else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -13012,7 +13012,11 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func getCaptionPanelView() -> TGCaptionPanelView? {
|
private func getCaptionPanelView() -> TGCaptionPanelView? {
|
||||||
return self.context.sharedContext.makeGalleryCaptionPanelView(context: self.context, chatLocation: self.presentationInterfaceState.chatLocation, customEmojiAvailable: self.presentationInterfaceState.customEmojiAvailable, present: { [weak self] c in
|
var isScheduledMessages = false
|
||||||
|
if case .scheduledMessages = self.presentationInterfaceState.subject {
|
||||||
|
isScheduledMessages = true
|
||||||
|
}
|
||||||
|
return self.context.sharedContext.makeGalleryCaptionPanelView(context: self.context, chatLocation: self.presentationInterfaceState.chatLocation, isScheduledMessages: isScheduledMessages, customEmojiAvailable: self.presentationInterfaceState.customEmojiAvailable, present: { [weak self] c in
|
||||||
self?.present(c, in: .window(.root))
|
self?.present(c, in: .window(.root))
|
||||||
}, presentInGlobalOverlay: { [weak self] c in
|
}, presentInGlobalOverlay: { [weak self] c in
|
||||||
guard let self else {
|
guard let self else {
|
||||||
@ -13443,7 +13447,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
|
|
||||||
strongSelf.canReadHistory.set(false)
|
strongSelf.canReadHistory.set(false)
|
||||||
|
|
||||||
let attachmentController = AttachmentController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, chatLocation: strongSelf.chatLocation, buttons: buttons, initialButton: initialButton, makeEntityInputView: { [weak self] in
|
let attachmentController = AttachmentController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, chatLocation: strongSelf.chatLocation, isScheduledMessages: isScheduledMessages, buttons: buttons, initialButton: initialButton, makeEntityInputView: { [weak self] in
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -14230,7 +14234,11 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
guard let peer = self.presentationInterfaceState.renderedPeer?.peer else {
|
guard let peer = self.presentationInterfaceState.renderedPeer?.peer else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let controller = MediaPickerScreen(context: self.context, updatedPresentationData: self.updatedPresentationData, peer: EnginePeer(peer), threadTitle: self.threadInfo?.title, chatLocation: self.chatLocation, bannedSendPhotos: bannedSendPhotos, bannedSendVideos: bannedSendVideos, subject: subject, saveEditedPhotos: saveEditedPhotos)
|
var isScheduledMessages = false
|
||||||
|
if case .scheduledMessages = self.presentationInterfaceState.subject {
|
||||||
|
isScheduledMessages = true
|
||||||
|
}
|
||||||
|
let controller = MediaPickerScreen(context: self.context, updatedPresentationData: self.updatedPresentationData, peer: EnginePeer(peer), threadTitle: self.threadInfo?.title, chatLocation: self.chatLocation, isScheduledMessages: isScheduledMessages, bannedSendPhotos: bannedSendPhotos, bannedSendVideos: bannedSendVideos, subject: subject, saveEditedPhotos: saveEditedPhotos)
|
||||||
let mediaPickerContext = controller.mediaPickerContext
|
let mediaPickerContext = controller.mediaPickerContext
|
||||||
controller.openCamera = { [weak self] cameraView in
|
controller.openCamera = { [weak self] cameraView in
|
||||||
self?.openCamera(cameraView: cameraView)
|
self?.openCamera(cameraView: cameraView)
|
||||||
|
@ -489,6 +489,25 @@ func peerInfoScreenSettingsData(context: AccountContext, peerId: EnginePeer.Id,
|
|||||||
}
|
}
|
||||||
|> distinctUntilChanged
|
|> distinctUntilChanged
|
||||||
|
|
||||||
|
let botsKey = ValueBoxKey(length: 8)
|
||||||
|
botsKey.setInt64(0, value: 0)
|
||||||
|
let bots = context.engine.data.subscribe(TelegramEngine.EngineData.Item.ItemCache.Item(collectionId: Namespaces.CachedItemCollection.attachMenuBots, id: botsKey))
|
||||||
|
|> mapToSignal { entry -> Signal<[AttachMenuBot], NoError> in
|
||||||
|
let bots: [AttachMenuBots.Bot] = entry?.get(AttachMenuBots.self)?.bots ?? []
|
||||||
|
return context.engine.data.subscribe(
|
||||||
|
EngineDataMap(bots.map(\.peerId).map(TelegramEngine.EngineData.Item.Peer.Peer.init))
|
||||||
|
)
|
||||||
|
|> map { peersMap -> [AttachMenuBot] in
|
||||||
|
var result: [AttachMenuBot] = []
|
||||||
|
for bot in bots {
|
||||||
|
if let maybePeer = peersMap[bot.peerId], let peer = maybePeer {
|
||||||
|
result.append(AttachMenuBot(peer: peer, shortName: bot.name, icons: bot.icons, peerTypes: bot.peerTypes, flags: bot.flags))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return combineLatest(
|
return combineLatest(
|
||||||
context.account.viewTracker.peerView(peerId, updateData: true),
|
context.account.viewTracker.peerView(peerId, updateData: true),
|
||||||
accountsAndPeers,
|
accountsAndPeers,
|
||||||
@ -512,7 +531,7 @@ func peerInfoScreenSettingsData(context: AccountContext, peerId: EnginePeer.Id,
|
|||||||
}
|
}
|
||||||
|> distinctUntilChanged,
|
|> distinctUntilChanged,
|
||||||
hasStories,
|
hasStories,
|
||||||
context.engine.messages.attachMenuBots()
|
bots
|
||||||
)
|
)
|
||||||
|> map { peerView, accountsAndPeers, accountSessions, privacySettings, sharedPreferences, notifications, stickerPacks, hasPassport, hasWatchApp, accountPreferences, suggestions, limits, hasPassword, isPowerSavingEnabled, hasStories, bots -> PeerInfoScreenData in
|
|> map { peerView, accountsAndPeers, accountSessions, privacySettings, sharedPreferences, notifications, stickerPacks, hasPassport, hasWatchApp, accountPreferences, suggestions, limits, hasPassword, isPowerSavingEnabled, hasStories, bots -> PeerInfoScreenData in
|
||||||
let (notificationExceptions, notificationsAuthorizationStatus, notificationsWarningSuppressed) = notifications
|
let (notificationExceptions, notificationsAuthorizationStatus, notificationsWarningSuppressed) = notifications
|
||||||
|
@ -4640,10 +4640,29 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
|||||||
guard let self else {
|
guard let self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
self.openBotAppDisposable.set(((self.context.engine.messages.requestSimpleWebView(botId: bot.peer.id, url: nil, source: .settings, themeParams: generateWebAppThemeParams(self.presentationData.theme))
|
|
||||||
|
let presentationData = self.presentationData
|
||||||
|
let progressSignal = Signal<Never, NoError> { [weak self] subscriber in
|
||||||
|
let controller = OverlayStatusController(theme: presentationData.theme, type: .loading(cancelled: nil))
|
||||||
|
self?.controller?.present(controller, in: .window(.root))
|
||||||
|
return ActionDisposable { [weak controller] in
|
||||||
|
Queue.mainQueue().async() {
|
||||||
|
controller?.dismiss()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|> runOn(Queue.mainQueue())
|
||||||
|
|> delay(0.35, queue: Queue.mainQueue())
|
||||||
|
let progressDisposable = progressSignal.start()
|
||||||
|
|
||||||
|
let signal: Signal<String, RequestSimpleWebViewError> = self.context.engine.messages.requestSimpleWebView(botId: bot.peer.id, url: nil, source: .settings, themeParams: generateWebAppThemeParams(self.presentationData.theme))
|
||||||
|> afterDisposed {
|
|> afterDisposed {
|
||||||
// updateProgress()
|
Queue.mainQueue().async {
|
||||||
})
|
progressDisposable.dispose()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.openBotAppDisposable.set((signal
|
||||||
|> deliverOnMainQueue).start(next: { [weak self] url in
|
|> deliverOnMainQueue).start(next: { [weak self] url in
|
||||||
guard let self else {
|
guard let self else {
|
||||||
return
|
return
|
||||||
@ -4670,6 +4689,9 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
|||||||
guard let self else {
|
guard let self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if bot.flags.contains(.showInSettingsDisclaimer) {
|
||||||
|
let _ = self.context.engine.messages.acceptAttachMenuBotDisclaimer(botId: bot.peer.id).start()
|
||||||
|
}
|
||||||
if bot.flags.contains(.notActivated) {
|
if bot.flags.contains(.notActivated) {
|
||||||
let _ = (self.context.engine.messages.addBotToAttachMenu(botId: bot.peer.id, allowWrite: allowWrite)
|
let _ = (self.context.engine.messages.addBotToAttachMenu(botId: bot.peer.id, allowWrite: allowWrite)
|
||||||
|> deliverOnMainQueue).start(error: { _ in
|
|> deliverOnMainQueue).start(error: { _ in
|
||||||
|
@ -1627,109 +1627,14 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
|||||||
return makeAttachmentFileControllerImpl(context: context, updatedPresentationData: updatedPresentationData, bannedSendMedia: bannedSendMedia, presentGallery: presentGallery, presentFiles: presentFiles, send: send)
|
return makeAttachmentFileControllerImpl(context: context, updatedPresentationData: updatedPresentationData, bannedSendMedia: bannedSendMedia, presentGallery: presentGallery, presentFiles: presentFiles, send: send)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func makeGalleryCaptionPanelView(context: AccountContext, chatLocation: ChatLocation, customEmojiAvailable: Bool, present: @escaping (ViewController) -> Void, presentInGlobalOverlay: @escaping (ViewController) -> Void) -> NSObject? {
|
public func makeGalleryCaptionPanelView(context: AccountContext, chatLocation: ChatLocation, isScheduledMessages: Bool, customEmojiAvailable: Bool, present: @escaping (ViewController) -> Void, presentInGlobalOverlay: @escaping (ViewController) -> Void) -> NSObject? {
|
||||||
// var presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
|
||||||
// presentationData = presentationData.withUpdated(theme: defaultDarkColorPresentationTheme)
|
|
||||||
//
|
|
||||||
// var presentationInterfaceState = ChatPresentationInterfaceState(chatWallpaper: .builtin(WallpaperSettings()), theme: presentationData.theme, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, limitsConfiguration: context.currentLimitsConfiguration.with { $0 }, fontSize: presentationData.chatFontSize, bubbleCorners: presentationData.chatBubbleCorners, accountPeerId: context.account.peerId, mode: .standard(previewing: false), chatLocation: chatLocation, subject: nil, peerNearbyData: nil, greetingData: nil, pendingUnpinnedAllMessages: false, activeGroupCallInfo: nil, hasActiveGroupCall: false, importState: nil, threadData: nil, isGeneralThreadClosed: nil)
|
|
||||||
//
|
|
||||||
// var updateChatPresentationInterfaceStateImpl: (((ChatPresentationInterfaceState) -> ChatPresentationInterfaceState) -> Void)?
|
|
||||||
// var ensureFocusedImpl: (() -> Void)?
|
|
||||||
//
|
|
||||||
// let interfaceInteraction = ChatPanelInterfaceInteraction(updateTextInputStateAndMode: { f in
|
|
||||||
// updateChatPresentationInterfaceStateImpl?({
|
|
||||||
// let (updatedState, updatedMode) = f($0.interfaceState.effectiveInputState, $0.inputMode)
|
|
||||||
// return $0.updatedInterfaceState { interfaceState in
|
|
||||||
// return interfaceState.withUpdatedEffectiveInputState(updatedState)
|
|
||||||
// }.updatedInputMode({ _ in updatedMode })
|
|
||||||
// })
|
|
||||||
// }, updateInputModeAndDismissedButtonKeyboardMessageId: { f in
|
|
||||||
// updateChatPresentationInterfaceStateImpl?({
|
|
||||||
// let (updatedInputMode, updatedClosedButtonKeyboardMessageId) = f($0)
|
|
||||||
// return $0.updatedInputMode({ _ in return updatedInputMode }).updatedInterfaceState({
|
|
||||||
// $0.withUpdatedMessageActionsState({ value in
|
|
||||||
// var value = value
|
|
||||||
// value.closedButtonKeyboardMessageId = updatedClosedButtonKeyboardMessageId
|
|
||||||
// return value
|
|
||||||
// })
|
|
||||||
// })
|
|
||||||
// })
|
|
||||||
// }, openLinkEditing: {
|
|
||||||
// var selectionRange: Range<Int>?
|
|
||||||
// var text: NSAttributedString?
|
|
||||||
// var inputMode: ChatInputMode?
|
|
||||||
// updateChatPresentationInterfaceStateImpl?({ state in
|
|
||||||
// selectionRange = state.interfaceState.effectiveInputState.selectionRange
|
|
||||||
// if let selectionRange = selectionRange {
|
|
||||||
// text = state.interfaceState.effectiveInputState.inputText.attributedSubstring(from: NSRange(location: selectionRange.startIndex, length: selectionRange.count))
|
|
||||||
// }
|
|
||||||
// inputMode = state.inputMode
|
|
||||||
// return state
|
|
||||||
// })
|
|
||||||
//
|
|
||||||
// var link: String?
|
|
||||||
// if let text {
|
|
||||||
// text.enumerateAttributes(in: NSMakeRange(0, text.length)) { attributes, _, _ in
|
|
||||||
// if let linkAttribute = attributes[ChatTextInputAttributes.textUrl] as? ChatTextInputTextUrlAttribute {
|
|
||||||
// link = linkAttribute.url
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// let controller = chatTextLinkEditController(sharedContext: context.sharedContext, updatedPresentationData: (presentationData, .never()), account: context.account, text: text?.string ?? "", link: link, apply: { link in
|
|
||||||
// if let inputMode = inputMode, let selectionRange = selectionRange {
|
|
||||||
// if let link = link {
|
|
||||||
// updateChatPresentationInterfaceStateImpl?({
|
|
||||||
// return $0.updatedInterfaceState({
|
|
||||||
// $0.withUpdatedEffectiveInputState(chatTextInputAddLinkAttribute($0.effectiveInputState, selectionRange: selectionRange, url: link))
|
|
||||||
// })
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
// ensureFocusedImpl?()
|
|
||||||
// updateChatPresentationInterfaceStateImpl?({
|
|
||||||
// return $0.updatedInputMode({ _ in return inputMode }).updatedInterfaceState({
|
|
||||||
// $0.withUpdatedEffectiveInputState(ChatTextInputState(inputText: $0.effectiveInputState.inputText, selectionRange: selectionRange.endIndex ..< selectionRange.endIndex))
|
|
||||||
// })
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
// present(controller)
|
|
||||||
// })
|
|
||||||
//
|
|
||||||
// let inputPanelNode = AttachmentTextInputPanelNode(context: context, presentationInterfaceState: presentationInterfaceState, isCaption: true, presentController: { c in
|
|
||||||
// presentInGlobalOverlay(c)
|
|
||||||
// }, makeEntityInputView: {
|
|
||||||
// return EntityInputView(context: context, isDark: true, areCustomEmojiEnabled: customEmojiAvailable)
|
|
||||||
// })
|
|
||||||
// inputPanelNode.interfaceInteraction = interfaceInteraction
|
|
||||||
// inputPanelNode.effectivePresentationInterfaceState = {
|
|
||||||
// return presentationInterfaceState
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// updateChatPresentationInterfaceStateImpl = { [weak inputPanelNode] f in
|
|
||||||
// let updatedPresentationInterfaceState = f(presentationInterfaceState)
|
|
||||||
// let updateInputTextState = presentationInterfaceState.interfaceState.effectiveInputState != updatedPresentationInterfaceState.interfaceState.effectiveInputState
|
|
||||||
//
|
|
||||||
// presentationInterfaceState = updatedPresentationInterfaceState
|
|
||||||
//
|
|
||||||
// if let inputPanelNode = inputPanelNode, updateInputTextState {
|
|
||||||
// inputPanelNode.updateInputTextState(updatedPresentationInterfaceState.interfaceState.effectiveInputState, animated: true)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// ensureFocusedImpl = { [weak inputPanelNode] in
|
|
||||||
// inputPanelNode?.ensureFocused()
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return inputPanelNode
|
|
||||||
|
|
||||||
let inputPanelNode = LegacyMessageInputPanelNode(
|
let inputPanelNode = LegacyMessageInputPanelNode(
|
||||||
context: context,
|
context: context,
|
||||||
chatLocation: chatLocation,
|
chatLocation: chatLocation,
|
||||||
|
isScheduledMessages: isScheduledMessages,
|
||||||
present: present,
|
present: present,
|
||||||
presentInGlobalOverlay: presentInGlobalOverlay
|
presentInGlobalOverlay: presentInGlobalOverlay
|
||||||
)
|
)
|
||||||
|
|
||||||
return inputPanelNode
|
return inputPanelNode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,9 +25,11 @@ private final class WebAppTermsAlertContentNode: AlertContentNode, UIGestureReco
|
|||||||
private let strings: PresentationStrings
|
private let strings: PresentationStrings
|
||||||
private let title: String
|
private let title: String
|
||||||
private let text: String
|
private let text: String
|
||||||
|
private let additionalText: String?
|
||||||
|
|
||||||
private let titleNode: ImmediateTextNode
|
private let titleNode: ImmediateTextNode
|
||||||
private let textNode: ImmediateTextNode
|
private let textNode: ImmediateTextNode
|
||||||
|
private let additionalTextNode: ImmediateTextNode
|
||||||
|
|
||||||
private let acceptTermsCheckNode: InteractiveCheckNode
|
private let acceptTermsCheckNode: InteractiveCheckNode
|
||||||
private let acceptTermsLabelNode: ImmediateTextNode
|
private let acceptTermsLabelNode: ImmediateTextNode
|
||||||
@ -53,10 +55,11 @@ private final class WebAppTermsAlertContentNode: AlertContentNode, UIGestureReco
|
|||||||
|
|
||||||
var openTerms: () -> Void = {}
|
var openTerms: () -> Void = {}
|
||||||
|
|
||||||
init(context: AccountContext, theme: AlertControllerTheme, ptheme: PresentationTheme, strings: PresentationStrings, title: String, text: String, actions: [TextAlertAction]) {
|
init(context: AccountContext, theme: AlertControllerTheme, ptheme: PresentationTheme, strings: PresentationStrings, title: String, text: String, additionalText: String?, actions: [TextAlertAction]) {
|
||||||
self.strings = strings
|
self.strings = strings
|
||||||
self.title = title
|
self.title = title
|
||||||
self.text = text
|
self.text = text
|
||||||
|
self.additionalText = additionalText
|
||||||
|
|
||||||
self.titleNode = ImmediateTextNode()
|
self.titleNode = ImmediateTextNode()
|
||||||
self.titleNode.displaysAsynchronously = false
|
self.titleNode.displaysAsynchronously = false
|
||||||
@ -69,6 +72,12 @@ private final class WebAppTermsAlertContentNode: AlertContentNode, UIGestureReco
|
|||||||
self.textNode.lineSpacing = 0.1
|
self.textNode.lineSpacing = 0.1
|
||||||
self.textNode.textAlignment = .center
|
self.textNode.textAlignment = .center
|
||||||
|
|
||||||
|
self.additionalTextNode = ImmediateTextNode()
|
||||||
|
self.additionalTextNode.maximumNumberOfLines = 0
|
||||||
|
self.additionalTextNode.displaysAsynchronously = false
|
||||||
|
self.additionalTextNode.lineSpacing = 0.1
|
||||||
|
self.additionalTextNode.textAlignment = .center
|
||||||
|
|
||||||
self.acceptTermsCheckNode = InteractiveCheckNode(theme: CheckNodeTheme(backgroundColor: theme.accentColor, strokeColor: theme.contrastColor, borderColor: theme.controlBorderColor, overlayBorder: false, hasInset: false, hasShadow: false))
|
self.acceptTermsCheckNode = InteractiveCheckNode(theme: CheckNodeTheme(backgroundColor: theme.accentColor, strokeColor: theme.contrastColor, borderColor: theme.controlBorderColor, overlayBorder: false, hasInset: false, hasShadow: false))
|
||||||
self.acceptTermsLabelNode = ImmediateTextNode()
|
self.acceptTermsLabelNode = ImmediateTextNode()
|
||||||
self.acceptTermsLabelNode.maximumNumberOfLines = 4
|
self.acceptTermsLabelNode.maximumNumberOfLines = 4
|
||||||
@ -94,6 +103,7 @@ private final class WebAppTermsAlertContentNode: AlertContentNode, UIGestureReco
|
|||||||
|
|
||||||
self.addSubnode(self.titleNode)
|
self.addSubnode(self.titleNode)
|
||||||
self.addSubnode(self.textNode)
|
self.addSubnode(self.textNode)
|
||||||
|
self.addSubnode(self.additionalTextNode)
|
||||||
|
|
||||||
self.addSubnode(self.acceptTermsCheckNode)
|
self.addSubnode(self.acceptTermsCheckNode)
|
||||||
self.addSubnode(self.acceptTermsLabelNode)
|
self.addSubnode(self.acceptTermsLabelNode)
|
||||||
@ -179,6 +189,11 @@ private final class WebAppTermsAlertContentNode: AlertContentNode, UIGestureReco
|
|||||||
override func updateTheme(_ theme: AlertControllerTheme) {
|
override func updateTheme(_ theme: AlertControllerTheme) {
|
||||||
self.titleNode.attributedText = NSAttributedString(string: self.title, font: Font.semibold(17.0), textColor: theme.primaryColor, paragraphAlignment: .center)
|
self.titleNode.attributedText = NSAttributedString(string: self.title, font: Font.semibold(17.0), textColor: theme.primaryColor, paragraphAlignment: .center)
|
||||||
self.textNode.attributedText = formattedText(self.text, fontSize: 13.0, color: theme.primaryColor, linkColor: theme.accentColor, textAlignment: .center)
|
self.textNode.attributedText = formattedText(self.text, fontSize: 13.0, color: theme.primaryColor, linkColor: theme.accentColor, textAlignment: .center)
|
||||||
|
if let additionalText = self.additionalText {
|
||||||
|
self.additionalTextNode.attributedText = formattedText(additionalText, fontSize: 13.0, color: theme.primaryColor, linkColor: theme.accentColor, textAlignment: .center)
|
||||||
|
} else {
|
||||||
|
self.additionalTextNode.attributedText = nil
|
||||||
|
}
|
||||||
|
|
||||||
let attributedAgreeText = parseMarkdownIntoAttributedString(
|
let attributedAgreeText = parseMarkdownIntoAttributedString(
|
||||||
self.strings.WebApp_DisclaimerAgree,
|
self.strings.WebApp_DisclaimerAgree,
|
||||||
@ -242,6 +257,14 @@ private final class WebAppTermsAlertContentNode: AlertContentNode, UIGestureReco
|
|||||||
transition.updateFrame(node: self.acceptTermsLabelNode, frame: CGRect(origin: CGPoint(x: acceptTermsOriginX + checkSize.width + spacing, y: origin.y), size: acceptTermsSize))
|
transition.updateFrame(node: self.acceptTermsLabelNode, frame: CGRect(origin: CGPoint(x: acceptTermsOriginX + checkSize.width + spacing, y: origin.y), size: acceptTermsSize))
|
||||||
origin.y += acceptTermsSize.height
|
origin.y += acceptTermsSize.height
|
||||||
entriesHeight += acceptTermsSize.height
|
entriesHeight += acceptTermsSize.height
|
||||||
|
origin.y += 21.0
|
||||||
|
}
|
||||||
|
|
||||||
|
let additionalTextSize = self.additionalTextNode.updateLayout(CGSize(width: size.width - 48.0, height: size.height))
|
||||||
|
transition.updateFrame(node: self.additionalTextNode, frame: CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - additionalTextSize.width) / 2.0), y: origin.y), size: additionalTextSize))
|
||||||
|
origin.y += additionalTextSize.height
|
||||||
|
if additionalTextSize.height > 0.0 {
|
||||||
|
entriesHeight += 20.0
|
||||||
}
|
}
|
||||||
|
|
||||||
let actionButtonHeight: CGFloat = 44.0
|
let actionButtonHeight: CGFloat = 44.0
|
||||||
@ -275,7 +298,7 @@ private final class WebAppTermsAlertContentNode: AlertContentNode, UIGestureReco
|
|||||||
actionsHeight = actionButtonHeight * CGFloat(self.actionNodes.count)
|
actionsHeight = actionButtonHeight * CGFloat(self.actionNodes.count)
|
||||||
}
|
}
|
||||||
|
|
||||||
let resultSize = CGSize(width: contentWidth, height: titleSize.height + textSize.height + entriesHeight + actionsHeight + 3.0 + insets.top + insets.bottom)
|
let resultSize = CGSize(width: contentWidth, height: titleSize.height + textSize.height + additionalTextSize.height + entriesHeight + actionsHeight + 3.0 + insets.top + insets.bottom)
|
||||||
|
|
||||||
transition.updateFrame(node: self.actionNodesSeparator, frame: CGRect(origin: CGPoint(x: 0.0, y: resultSize.height - actionsHeight - UIScreenPixel), size: CGSize(width: resultSize.width, height: UIScreenPixel)))
|
transition.updateFrame(node: self.actionNodesSeparator, frame: CGRect(origin: CGPoint(x: 0.0, y: resultSize.height - actionsHeight - UIScreenPixel), size: CGSize(width: resultSize.width, height: UIScreenPixel)))
|
||||||
|
|
||||||
@ -350,9 +373,17 @@ public func webAppTermsAlertController(
|
|||||||
})]
|
})]
|
||||||
|
|
||||||
let title = presentationData.strings.WebApp_DisclaimerTitle
|
let title = presentationData.strings.WebApp_DisclaimerTitle
|
||||||
let text = presentationData.strings.WebApp_DisclaimerText(bot.peer.compactDisplayTitle).string
|
let text = presentationData.strings.WebApp_DisclaimerText
|
||||||
|
let additionalText: String?
|
||||||
|
if bot.flags.contains(.showInSettings) {
|
||||||
|
additionalText = presentationData.strings.WebApp_DisclaimerShortcutsSettingsText(bot.peer.compactDisplayTitle).string
|
||||||
|
} else if bot.flags.contains(.showInAttachMenu) {
|
||||||
|
additionalText = presentationData.strings.WebApp_DisclaimerShortcutsText(bot.peer.compactDisplayTitle).string
|
||||||
|
} else {
|
||||||
|
additionalText = nil
|
||||||
|
}
|
||||||
|
|
||||||
let contentNode = WebAppTermsAlertContentNode(context: context, theme: AlertControllerTheme(presentationData: presentationData), ptheme: theme, strings: strings, title: title, text: text, actions: actions)
|
let contentNode = WebAppTermsAlertContentNode(context: context, theme: AlertControllerTheme(presentationData: presentationData), ptheme: theme, strings: strings, title: title, text: text, additionalText: additionalText, actions: actions)
|
||||||
contentNode.openTerms = {
|
contentNode.openTerms = {
|
||||||
context.sharedContext.openExternalUrl(context: context, urlContext: .generic, url: presentationData.strings.WebApp_Disclaimer_URL, forceExternal: true, presentationData: context.sharedContext.currentPresentationData.with { $0 }, navigationController: nil, dismissInput: {
|
context.sharedContext.openExternalUrl(context: context, urlContext: .generic, url: presentationData.strings.WebApp_Disclaimer_URL, forceExternal: true, presentationData: context.sharedContext.currentPresentationData.with { $0 }, navigationController: nil, dismissInput: {
|
||||||
})
|
})
|
||||||
|
Loading…
x
Reference in New Issue
Block a user