mirror of
https://github.com/TelegramMessenger/Telegram-iOS.git
synced 2026-07-06 03:33:41 +02:00
Business fixes
This commit is contained in:
parent
cbb9d42744
commit
8446fd3ab1
35 changed files with 448 additions and 171 deletions
|
|
@ -618,6 +618,7 @@ public class BrowserScreen: ViewController {
|
|||
bottom: layout.intrinsicInsets.bottom + layout.safeInsets.bottom,
|
||||
right: layout.safeInsets.right
|
||||
),
|
||||
additionalInsets: layout.additionalInsets,
|
||||
inputHeight: layout.inputHeight ?? 0.0,
|
||||
metrics: layout.metrics,
|
||||
deviceMetrics: layout.deviceMetrics,
|
||||
|
|
|
|||
|
|
@ -411,13 +411,17 @@ private final class ChatListFilterPresetListItemNode: ItemListRevealOptionsItemN
|
|||
strongSelf.arrowNode.isHidden = item.isAllChats
|
||||
|
||||
if let sharedIconImage = strongSelf.sharedIconNode.image {
|
||||
strongSelf.sharedIconNode.frame = CGRect(origin: CGPoint(x: strongSelf.arrowNode.frame.minX + 2.0 - sharedIconImage.size.width, y: floorToScreenPixels((layout.contentSize.height - sharedIconImage.size.height) / 2.0) + 1.0), size: sharedIconImage.size)
|
||||
var sharedIconFrame = CGRect(origin: CGPoint(x: strongSelf.arrowNode.frame.minX + 2.0 - sharedIconImage.size.width, y: floorToScreenPixels((layout.contentSize.height - sharedIconImage.size.height) / 2.0) + 1.0), size: sharedIconImage.size)
|
||||
if item.tagColor != nil {
|
||||
sharedIconFrame.origin.x -= 34.0
|
||||
}
|
||||
strongSelf.sharedIconNode.frame = sharedIconFrame
|
||||
}
|
||||
var isShared = false
|
||||
if case let .filter(_, _, _, data) = item.preset, data.isShared {
|
||||
isShared = true
|
||||
}
|
||||
strongSelf.sharedIconNode.isHidden = !isShared || item.tagColor != nil
|
||||
strongSelf.sharedIconNode.isHidden = !isShared
|
||||
|
||||
if let tagColor = item.tagColor {
|
||||
let tagIconView: UIImageView
|
||||
|
|
@ -534,6 +538,9 @@ private final class ChatListFilterPresetListItemNode: ItemListRevealOptionsItemN
|
|||
|
||||
var sharedIconFrame = self.sharedIconNode.frame
|
||||
sharedIconFrame.origin.x = arrowFrame.minX + 2.0 - sharedIconFrame.width
|
||||
if self.item?.tagColor != nil {
|
||||
sharedIconFrame.origin.x -= 34.0
|
||||
}
|
||||
transition.updateFrame(node: self.sharedIconNode, frame: sharedIconFrame)
|
||||
|
||||
if let tagIconView = self.tagIconView {
|
||||
|
|
|
|||
|
|
@ -2270,11 +2270,19 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
|||
}
|
||||
} else if inlineAuthorPrefix == nil, let draftState = draftState {
|
||||
hasDraft = true
|
||||
authorAttributedString = NSAttributedString(string: item.presentationData.strings.DialogList_Draft, font: textFont, textColor: theme.messageDraftTextColor)
|
||||
|
||||
let draftText = stringWithAppliedEntities(draftState.text, entities: draftState.entities, baseColor: theme.messageTextColor, linkColor: theme.messageTextColor, baseFont: textFont, linkFont: textFont, boldFont: textFont, italicFont: textFont, boldItalicFont: textFont, fixedFont: textFont, blockQuoteFont: textFont, message: nil)
|
||||
|
||||
attributedText = foldLineBreaks(draftText)
|
||||
if !itemTags.isEmpty {
|
||||
let tempAttributedText = foldLineBreaks(draftText)
|
||||
let attributedTextWithDraft = NSMutableAttributedString()
|
||||
attributedTextWithDraft.append(NSAttributedString(string: item.presentationData.strings.DialogList_Draft + ": ", font: textFont, textColor: theme.messageDraftTextColor))
|
||||
attributedTextWithDraft.append(tempAttributedText)
|
||||
attributedText = attributedTextWithDraft
|
||||
} else {
|
||||
authorAttributedString = NSAttributedString(string: item.presentationData.strings.DialogList_Draft, font: textFont, textColor: theme.messageDraftTextColor)
|
||||
|
||||
attributedText = foldLineBreaks(draftText)
|
||||
}
|
||||
} else if let message = messages.first {
|
||||
var composedString: NSMutableAttributedString
|
||||
|
||||
|
|
@ -3856,7 +3864,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
|||
|
||||
var badgeFrame: CGRect
|
||||
if textLayout.numberOfLines > 1 {
|
||||
badgeFrame = CGRect(origin: CGPoint(x: textLayout.trailingLineWidth, y: textNodeFrame.height - 3.0 - badgeSize.height), size: badgeSize)
|
||||
badgeFrame = CGRect(origin: CGPoint(x: textLayout.trailingLineWidth + 4.0, y: textNodeFrame.height - 3.0 - badgeSize.height), size: badgeSize)
|
||||
} else {
|
||||
let firstLineFrame = textLayout.linesRects().first ?? CGRect(origin: CGPoint(), size: textNodeFrame.size)
|
||||
badgeFrame = CGRect(origin: CGPoint(x: 0.0, y: firstLineFrame.height + 5.0), size: badgeSize)
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ open class ViewControllerComponentContainer: ViewController {
|
|||
public let statusBarHeight: CGFloat
|
||||
public let navigationHeight: CGFloat
|
||||
public let safeInsets: UIEdgeInsets
|
||||
public let additionalInsets: UIEdgeInsets
|
||||
public let inputHeight: CGFloat
|
||||
public let metrics: LayoutMetrics
|
||||
public let deviceMetrics: DeviceMetrics
|
||||
|
|
@ -60,6 +61,7 @@ open class ViewControllerComponentContainer: ViewController {
|
|||
statusBarHeight: CGFloat,
|
||||
navigationHeight: CGFloat,
|
||||
safeInsets: UIEdgeInsets,
|
||||
additionalInsets: UIEdgeInsets,
|
||||
inputHeight: CGFloat,
|
||||
metrics: LayoutMetrics,
|
||||
deviceMetrics: DeviceMetrics,
|
||||
|
|
@ -73,6 +75,7 @@ open class ViewControllerComponentContainer: ViewController {
|
|||
self.statusBarHeight = statusBarHeight
|
||||
self.navigationHeight = navigationHeight
|
||||
self.safeInsets = safeInsets
|
||||
self.additionalInsets = additionalInsets
|
||||
self.inputHeight = inputHeight
|
||||
self.metrics = metrics
|
||||
self.deviceMetrics = deviceMetrics
|
||||
|
|
@ -98,6 +101,9 @@ open class ViewControllerComponentContainer: ViewController {
|
|||
if lhs.safeInsets != rhs.safeInsets {
|
||||
return false
|
||||
}
|
||||
if lhs.additionalInsets != rhs.additionalInsets {
|
||||
return false
|
||||
}
|
||||
if lhs.inputHeight != rhs.inputHeight {
|
||||
return false
|
||||
}
|
||||
|
|
@ -167,6 +173,7 @@ open class ViewControllerComponentContainer: ViewController {
|
|||
statusBarHeight: layout.statusBarHeight ?? 0.0,
|
||||
navigationHeight: navigationHeight,
|
||||
safeInsets: UIEdgeInsets(top: layout.intrinsicInsets.top + layout.safeInsets.top, left: layout.safeInsets.left, bottom: layout.intrinsicInsets.bottom + layout.safeInsets.bottom, right: layout.safeInsets.right),
|
||||
additionalInsets: layout.additionalInsets,
|
||||
inputHeight: layout.inputHeight ?? 0.0,
|
||||
metrics: layout.metrics,
|
||||
deviceMetrics: layout.deviceMetrics,
|
||||
|
|
|
|||
|
|
@ -2634,6 +2634,7 @@ public class DrawingScreen: ViewController, TGPhotoDrawingInterfaceController, U
|
|||
bottom: layout.intrinsicInsets.bottom + layout.safeInsets.bottom,
|
||||
right: layout.safeInsets.right
|
||||
),
|
||||
additionalInsets: layout.additionalInsets,
|
||||
inputHeight: layout.inputHeight ?? 0.0,
|
||||
metrics: layout.metrics,
|
||||
deviceMetrics: layout.deviceMetrics,
|
||||
|
|
|
|||
|
|
@ -236,6 +236,11 @@ public func chatMessageGalleryControllerData(context: AccountContext, chatLocati
|
|||
}*/
|
||||
}
|
||||
|
||||
var source = source
|
||||
if standalone {
|
||||
source = .standaloneMessage(message)
|
||||
}
|
||||
|
||||
if internalDocumentItemSupportsMimeType(file.mimeType, fileName: file.fileName ?? "file") {
|
||||
let gallery = GalleryController(context: context, source: source ?? .peerMessagesAtId(messageId: message.id, chatLocation: chatLocation ?? .peer(id: message.id.peerId), customTag: chatFilterTag, chatLocationContextHolder: chatLocationContextHolder ?? Atomic<ChatLocationContextHolder?>(value: nil)), invertItemOrder: reverseMessageGalleryOrder, streamSingleVideo: stream, fromPlayingVideo: autoplayingVideo, landscape: landscape, timecode: timecode, synchronousLoad: synchronousLoad, replaceRootController: { [weak navigationController] controller, ready in
|
||||
navigationController?.replaceTopController(controller, animated: false, ready: ready)
|
||||
|
|
|
|||
|
|
@ -822,7 +822,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
|
|||
}
|
||||
|
||||
var canDelete: Bool
|
||||
var canShare = !message.containsSecretMedia
|
||||
var canShare = !message.containsSecretMedia && !Namespaces.Message.allNonRegular.contains(message.id.namespace)
|
||||
|
||||
var canFullscreen = false
|
||||
|
||||
|
|
|
|||
|
|
@ -248,13 +248,18 @@ public func galleryItemForEntry(
|
|||
if let result = addLocallyGeneratedEntities(text, enabledTypes: [.timecode], entities: entities, mediaDuration: file.duration.flatMap(Double.init)) {
|
||||
entities = result
|
||||
}
|
||||
|
||||
var originData = GalleryItemOriginData(title: message.effectiveAuthor.flatMap(EnginePeer.init)?.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), timestamp: message.timestamp)
|
||||
if Namespaces.Message.allNonRegular.contains(message.id.namespace) {
|
||||
originData = GalleryItemOriginData(title: nil, timestamp: nil)
|
||||
}
|
||||
|
||||
let caption = galleryCaptionStringWithAppliedEntities(context: context, text: text, entities: entities, message: message)
|
||||
return UniversalVideoGalleryItem(
|
||||
context: context,
|
||||
presentationData: presentationData,
|
||||
content: content,
|
||||
originData: GalleryItemOriginData(title: message.effectiveAuthor.flatMap(EnginePeer.init)?.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), timestamp: message.timestamp),
|
||||
originData: originData,
|
||||
indexData: location.flatMap { GalleryItemIndexData(position: Int32($0.index), totalCount: Int32($0.count)) },
|
||||
contentInfo: .message(message),
|
||||
caption: caption,
|
||||
|
|
@ -348,11 +353,17 @@ public func galleryItemForEntry(
|
|||
}
|
||||
description = galleryCaptionStringWithAppliedEntities(context: context, text: descriptionText, entities: entities, message: message)
|
||||
}
|
||||
|
||||
var originData = GalleryItemOriginData(title: message.effectiveAuthor.flatMap(EnginePeer.init)?.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), timestamp: message.timestamp)
|
||||
if Namespaces.Message.allNonRegular.contains(message.id.namespace) {
|
||||
originData = GalleryItemOriginData(title: nil, timestamp: nil)
|
||||
}
|
||||
|
||||
return UniversalVideoGalleryItem(
|
||||
context: context,
|
||||
presentationData: presentationData,
|
||||
content: content,
|
||||
originData: GalleryItemOriginData(title: message.effectiveAuthor.flatMap(EnginePeer.init)?.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), timestamp: message.timestamp),
|
||||
originData: originData,
|
||||
indexData: location.flatMap { GalleryItemIndexData(position: Int32($0.index), totalCount: Int32($0.count)) },
|
||||
contentInfo: .message(message),
|
||||
caption: NSAttributedString(string: ""),
|
||||
|
|
|
|||
|
|
@ -20,12 +20,12 @@ public final class ItemListAddressItem: ListViewItem, ItemListItem {
|
|||
let style: ItemListStyle
|
||||
let displayDecorations: Bool
|
||||
let action: (() -> Void)?
|
||||
let longTapAction: (() -> Void)?
|
||||
let longTapAction: ((ASDisplayNode, String) -> Void)?
|
||||
let linkItemAction: ((TextLinkItemActionType, TextLinkItem) -> Void)?
|
||||
|
||||
public let tag: Any?
|
||||
|
||||
public init(theme: PresentationTheme, label: String, text: String, imageSignal: Signal<(TransformImageArguments) -> DrawingContext?, NoError>?, selected: Bool? = nil, sectionId: ItemListSectionId, style: ItemListStyle, displayDecorations: Bool = true, action: (() -> Void)?, longTapAction: (() -> Void)? = nil, linkItemAction: ((TextLinkItemActionType, TextLinkItem) -> Void)? = nil, tag: Any? = nil) {
|
||||
public init(theme: PresentationTheme, label: String, text: String, imageSignal: Signal<(TransformImageArguments) -> DrawingContext?, NoError>?, selected: Bool? = nil, sectionId: ItemListSectionId, style: ItemListStyle, displayDecorations: Bool = true, action: (() -> Void)?, longTapAction: ((ASDisplayNode, String) -> Void)? = nil, linkItemAction: ((TextLinkItemActionType, TextLinkItem) -> Void)? = nil, tag: Any? = nil) {
|
||||
self.theme = theme
|
||||
self.label = label
|
||||
self.text = text
|
||||
|
|
@ -396,7 +396,10 @@ public class ItemListAddressItemNode: ListViewItemNode {
|
|||
}
|
||||
|
||||
override public func longTapped() {
|
||||
self.item?.longTapAction?()
|
||||
guard let item = self.item else {
|
||||
return
|
||||
}
|
||||
item.longTapAction?(self, item.text)
|
||||
}
|
||||
|
||||
public var tag: Any? {
|
||||
|
|
|
|||
|
|
@ -222,7 +222,7 @@ public func legacyMediaEditor(context: AccountContext, peer: Peer, threadTitle:
|
|||
})
|
||||
}
|
||||
|
||||
public func legacyAttachmentMenu(context: AccountContext, peer: Peer, threadTitle: String?, chatLocation: ChatLocation, editMediaOptions: LegacyAttachmentMenuMediaEditing?, saveEditedPhotos: Bool, allowGrouping: Bool, hasSchedule: Bool, canSendPolls: Bool, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>), parentController: LegacyController, recentlyUsedInlineBots: [Peer], initialCaption: NSAttributedString, openGallery: @escaping () -> Void, openCamera: @escaping (TGAttachmentCameraView?, TGMenuSheetController?) -> Void, openFileGallery: @escaping () -> Void, openWebSearch: @escaping () -> Void, openMap: @escaping () -> Void, openContacts: @escaping () -> Void, openPoll: @escaping () -> Void, presentSelectionLimitExceeded: @escaping () -> Void, presentCantSendMultipleFiles: @escaping () -> Void, presentJpegConversionAlert: @escaping (@escaping (Bool) -> Void) -> Void, presentSchedulePicker: @escaping (Bool, @escaping (Int32) -> Void) -> Void, presentTimerPicker: @escaping (@escaping (Int32) -> Void) -> Void, sendMessagesWithSignals: @escaping ([Any]?, Bool, Int32, ((String) -> UIView?)?, @escaping () -> Void) -> Void, selectRecentlyUsedInlineBot: @escaping (Peer) -> Void, getCaptionPanelView: @escaping () -> TGCaptionPanelView?, present: @escaping (ViewController, Any?) -> Void) -> TGMenuSheetController {
|
||||
public func legacyAttachmentMenu(context: AccountContext, peer: Peer?, threadTitle: String?, chatLocation: ChatLocation, editMediaOptions: LegacyAttachmentMenuMediaEditing?, saveEditedPhotos: Bool, allowGrouping: Bool, hasSchedule: Bool, canSendPolls: Bool, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>), parentController: LegacyController, recentlyUsedInlineBots: [Peer], initialCaption: NSAttributedString, openGallery: @escaping () -> Void, openCamera: @escaping (TGAttachmentCameraView?, TGMenuSheetController?) -> Void, openFileGallery: @escaping () -> Void, openWebSearch: @escaping () -> Void, openMap: @escaping () -> Void, openContacts: @escaping () -> Void, openPoll: @escaping () -> Void, presentSelectionLimitExceeded: @escaping () -> Void, presentCantSendMultipleFiles: @escaping () -> Void, presentJpegConversionAlert: @escaping (@escaping (Bool) -> Void) -> Void, presentSchedulePicker: @escaping (Bool, @escaping (Int32) -> Void) -> Void, presentTimerPicker: @escaping (@escaping (Int32) -> Void) -> Void, sendMessagesWithSignals: @escaping ([Any]?, Bool, Int32, ((String) -> UIView?)?, @escaping () -> Void) -> Void, selectRecentlyUsedInlineBot: @escaping (Peer) -> Void, getCaptionPanelView: @escaping () -> TGCaptionPanelView?, present: @escaping (ViewController, Any?) -> Void) -> TGMenuSheetController {
|
||||
let defaultVideoPreset = defaultVideoPresetForContext(context)
|
||||
UserDefaults.standard.set(defaultVideoPreset.rawValue as NSNumber, forKey: "TG_preferredVideoPreset_v0")
|
||||
|
||||
|
|
@ -230,18 +230,20 @@ public func legacyAttachmentMenu(context: AccountContext, peer: Peer, threadTitl
|
|||
let recipientName: String
|
||||
if let threadTitle {
|
||||
recipientName = threadTitle
|
||||
} else {
|
||||
} else if let peer {
|
||||
if peer.id == context.account.peerId {
|
||||
recipientName = presentationData.strings.DialogList_SavedMessages
|
||||
} else {
|
||||
recipientName = EnginePeer(peer).displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
|
||||
}
|
||||
} else {
|
||||
recipientName = ""
|
||||
}
|
||||
|
||||
let actionSheetTheme = ActionSheetControllerTheme(presentationData: presentationData)
|
||||
let fontSize = floor(actionSheetTheme.baseFontSize * 20.0 / 17.0)
|
||||
|
||||
let isSecretChat = peer.id.namespace == Namespaces.Peer.SecretChat
|
||||
let isSecretChat = peer?.id.namespace == Namespaces.Peer.SecretChat
|
||||
|
||||
let controller = TGMenuSheetController(context: parentController.context, dark: false)!
|
||||
controller.dismissesByOutsideTap = true
|
||||
|
|
@ -314,14 +316,14 @@ public func legacyAttachmentMenu(context: AccountContext, peer: Peer, threadTitl
|
|||
carouselItem.selectionLimitExceeded = {
|
||||
presentSelectionLimitExceeded()
|
||||
}
|
||||
if peer.id != context.account.peerId {
|
||||
if let peer, peer.id != context.account.peerId {
|
||||
if peer is TelegramUser {
|
||||
carouselItem.hasTimer = hasSchedule
|
||||
}
|
||||
carouselItem.hasSilentPosting = true
|
||||
}
|
||||
carouselItem.hasSchedule = hasSchedule
|
||||
carouselItem.reminder = peer.id == context.account.peerId
|
||||
carouselItem.reminder = peer?.id == context.account.peerId
|
||||
carouselItem.presentScheduleController = { media, done in
|
||||
presentSchedulePicker(media, { time in
|
||||
done?(time)
|
||||
|
|
@ -449,7 +451,12 @@ public func legacyAttachmentMenu(context: AccountContext, peer: Peer, threadTitl
|
|||
navigationController.setNavigationBarHidden(true, animated: false)
|
||||
legacyController.bind(controller: navigationController)
|
||||
|
||||
let recipientName = EnginePeer(peer).displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
|
||||
let recipientName: String
|
||||
if let peer {
|
||||
recipientName = EnginePeer(peer).displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
|
||||
} else {
|
||||
recipientName = ""
|
||||
}
|
||||
|
||||
legacyController.enableSizeClassSignal = true
|
||||
|
||||
|
|
@ -489,12 +496,14 @@ public func legacyAttachmentMenu(context: AccountContext, peer: Peer, threadTitl
|
|||
itemViews.append(locationItem)
|
||||
|
||||
var peerSupportsPolls = false
|
||||
if peer is TelegramGroup || peer is TelegramChannel {
|
||||
peerSupportsPolls = true
|
||||
} else if let user = peer as? TelegramUser, let _ = user.botInfo {
|
||||
peerSupportsPolls = true
|
||||
if let peer {
|
||||
if peer is TelegramGroup || peer is TelegramChannel {
|
||||
peerSupportsPolls = true
|
||||
} else if let user = peer as? TelegramUser, let _ = user.botInfo {
|
||||
peerSupportsPolls = true
|
||||
}
|
||||
}
|
||||
if peerSupportsPolls && canSendMessagesToPeer(peer) && canSendPolls {
|
||||
if let peer, peerSupportsPolls, canSendMessagesToPeer(peer) && canSendPolls {
|
||||
let pollItem = TGMenuSheetButtonItemView(title: presentationData.strings.AttachmentMenu_Poll, type: TGMenuSheetButtonTypeDefault, fontSize: fontSize, action: { [weak controller] in
|
||||
controller?.dismiss(animated: true)
|
||||
openPoll()
|
||||
|
|
|
|||
|
|
@ -224,7 +224,7 @@ func presentLegacyMediaPickerGallery(context: AccountContext, peer: EnginePeer?,
|
|||
})
|
||||
}
|
||||
}
|
||||
if !isScheduledMessages {
|
||||
if !isScheduledMessages && peer != nil {
|
||||
model.interfaceView.doneLongPressed = { [weak selectionContext, weak editingContext, weak legacyController, weak model] item in
|
||||
if let legacyController = legacyController, let item = item as? TGMediaPickerGalleryItem, let model = model, let selectionContext = selectionContext {
|
||||
var effectiveHasSchedule = hasSchedule
|
||||
|
|
@ -269,8 +269,8 @@ func presentLegacyMediaPickerGallery(context: AccountContext, peer: EnginePeer?,
|
|||
}
|
||||
|
||||
let _ = (sendWhenOnlineAvailable
|
||||
|> take(1)
|
||||
|> deliverOnMainQueue).start(next: { sendWhenOnlineAvailable in
|
||||
|> 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: hasTimer)
|
||||
let dismissImpl = { [weak model] in
|
||||
|
|
|
|||
|
|
@ -510,7 +510,7 @@ private enum DeviceContactInfoEntry: ItemListNodeEntry {
|
|||
} else {
|
||||
arguments.openAddress(value)
|
||||
}
|
||||
}, longTapAction: {
|
||||
}, longTapAction: { _, _ in
|
||||
if selected == nil {
|
||||
arguments.displayCopyContextMenu(.info(index), string)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -477,6 +477,7 @@ public class ReplaceBoostScreen: ViewController {
|
|||
statusBarHeight: 0.0,
|
||||
navigationHeight: navigationHeight,
|
||||
safeInsets: UIEdgeInsets(top: layout.intrinsicInsets.top + layout.safeInsets.top, left: layout.safeInsets.left, bottom: layout.intrinsicInsets.bottom + layout.safeInsets.bottom, right: layout.safeInsets.right),
|
||||
additionalInsets: layout.additionalInsets,
|
||||
inputHeight: layout.inputHeight ?? 0.0,
|
||||
metrics: layout.metrics,
|
||||
deviceMetrics: layout.deviceMetrics,
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import Foundation
|
|||
import TelegramPresentationData
|
||||
import TelegramUIPreferences
|
||||
|
||||
public func stringForShortTimestamp(hours: Int32, minutes: Int32, dateTimeFormat: PresentationDateTimeFormat) -> String {
|
||||
public func stringForShortTimestamp(hours: Int32, minutes: Int32, dateTimeFormat: PresentationDateTimeFormat, formatAsPlainText: Bool = false) -> String {
|
||||
switch dateTimeFormat.timeFormat {
|
||||
case .regular:
|
||||
let hourString: String
|
||||
|
|
@ -20,10 +20,18 @@ public func stringForShortTimestamp(hours: Int32, minutes: Int32, dateTimeFormat
|
|||
} else {
|
||||
periodString = "AM"
|
||||
}
|
||||
if minutes >= 10 {
|
||||
return "\(hourString):\(minutes)\u{00a0}\(periodString)"
|
||||
|
||||
let spaceCharacter: String
|
||||
if formatAsPlainText {
|
||||
spaceCharacter = " "
|
||||
} else {
|
||||
return "\(hourString):0\(minutes)\u{00a0}\(periodString)"
|
||||
spaceCharacter = "\u{00a0}"
|
||||
}
|
||||
|
||||
if minutes >= 10 {
|
||||
return "\(hourString):\(minutes)\(spaceCharacter)\(periodString)"
|
||||
} else {
|
||||
return "\(hourString):0\(minutes)\(spaceCharacter)\(periodString)"
|
||||
}
|
||||
case .military:
|
||||
return String(format: "%02d:%02d", arguments: [Int(hours), Int(minutes)])
|
||||
|
|
|
|||
|
|
@ -2384,6 +2384,7 @@ public class CameraScreen: ViewController {
|
|||
bottom: bottomInset,
|
||||
right: layout.safeInsets.right
|
||||
),
|
||||
additionalInsets: layout.additionalInsets,
|
||||
inputHeight: layout.inputHeight ?? 0.0,
|
||||
metrics: layout.metrics,
|
||||
deviceMetrics: layout.deviceMetrics,
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import ShareController
|
|||
import LegacyUI
|
||||
import LegacyMediaPickerUI
|
||||
|
||||
public func presentedLegacyCamera(context: AccountContext, peer: Peer, chatLocation: ChatLocation, cameraView: TGAttachmentCameraView?, menuController: TGMenuSheetController?, parentController: ViewController, attachmentController: ViewController? = nil, editingMedia: Bool, saveCapturedPhotos: Bool, mediaGrouping: Bool, initialCaption: NSAttributedString, hasSchedule: Bool, enablePhoto: Bool, enableVideo: Bool, sendMessagesWithSignals: @escaping ([Any]?, Bool, Int32) -> Void, recognizedQRCode: @escaping (String) -> Void = { _ in }, presentSchedulePicker: @escaping (Bool, @escaping (Int32) -> Void) -> Void, presentTimerPicker: @escaping (@escaping (Int32) -> Void) -> Void, getCaptionPanelView: @escaping () -> TGCaptionPanelView?, dismissedWithResult: @escaping () -> Void = {}, finishedTransitionIn: @escaping () -> Void = {}) {
|
||||
public func presentedLegacyCamera(context: AccountContext, peer: Peer?, chatLocation: ChatLocation, cameraView: TGAttachmentCameraView?, menuController: TGMenuSheetController?, parentController: ViewController, attachmentController: ViewController? = nil, editingMedia: Bool, saveCapturedPhotos: Bool, mediaGrouping: Bool, initialCaption: NSAttributedString, hasSchedule: Bool, enablePhoto: Bool, enableVideo: Bool, sendMessagesWithSignals: @escaping ([Any]?, Bool, Int32) -> Void, recognizedQRCode: @escaping (String) -> Void = { _ in }, presentSchedulePicker: @escaping (Bool, @escaping (Int32) -> Void) -> Void, presentTimerPicker: @escaping (@escaping (Int32) -> Void) -> Void, getCaptionPanelView: @escaping () -> TGCaptionPanelView?, dismissedWithResult: @escaping () -> Void = {}, finishedTransitionIn: @escaping () -> Void = {}) {
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
let legacyController = LegacyController(presentation: .custom, theme: presentationData.theme)
|
||||
legacyController.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .portrait, compactSize: .portrait)
|
||||
|
|
@ -18,7 +18,7 @@ public func presentedLegacyCamera(context: AccountContext, peer: Peer, chatLocat
|
|||
|
||||
legacyController.deferScreenEdgeGestures = [.top]
|
||||
|
||||
let isSecretChat = peer.id.namespace == Namespaces.Peer.SecretChat
|
||||
let isSecretChat = peer?.id.namespace == Namespaces.Peer.SecretChat
|
||||
|
||||
let controller: TGCameraController
|
||||
if let cameraView = cameraView, let previewView = cameraView.previewView() {
|
||||
|
|
@ -87,15 +87,18 @@ public func presentedLegacyCamera(context: AccountContext, peer: Peer, chatLocat
|
|||
controller.allowCaptionEntities = true
|
||||
controller.allowGrouping = mediaGrouping
|
||||
controller.inhibitDocumentCaptions = false
|
||||
controller.recipientName = EnginePeer(peer).displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
|
||||
if peer.id != context.account.peerId {
|
||||
if peer is TelegramUser {
|
||||
controller.hasTimer = hasSchedule
|
||||
|
||||
if let peer {
|
||||
controller.recipientName = EnginePeer(peer).displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
|
||||
if peer.id != context.account.peerId {
|
||||
if peer is TelegramUser {
|
||||
controller.hasTimer = hasSchedule
|
||||
}
|
||||
controller.hasSilentPosting = true
|
||||
}
|
||||
controller.hasSilentPosting = true
|
||||
}
|
||||
controller.hasSchedule = hasSchedule
|
||||
controller.reminder = peer.id == context.account.peerId
|
||||
controller.reminder = peer?.id == context.account.peerId
|
||||
|
||||
let screenSize = parentController.view.bounds.size
|
||||
var startFrame = CGRect(x: 0, y: screenSize.height, width: screenSize.width, height: screenSize.height)
|
||||
|
|
|
|||
|
|
@ -267,6 +267,7 @@ public final class MediaCutoutScreen: ViewController {
|
|||
bottom: bottomInset,
|
||||
right: layout.safeInsets.right
|
||||
),
|
||||
additionalInsets: layout.additionalInsets,
|
||||
inputHeight: layout.inputHeight ?? 0.0,
|
||||
metrics: layout.metrics,
|
||||
deviceMetrics: layout.deviceMetrics,
|
||||
|
|
|
|||
|
|
@ -3998,6 +3998,7 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
|
|||
bottom: bottomInset,
|
||||
right: layout.safeInsets.right
|
||||
),
|
||||
additionalInsets: layout.additionalInsets,
|
||||
inputHeight: layoutInputHeight,
|
||||
metrics: layout.metrics,
|
||||
deviceMetrics: layout.deviceMetrics,
|
||||
|
|
|
|||
|
|
@ -1031,6 +1031,7 @@ public final class MediaToolsScreen: ViewController {
|
|||
bottom: bottomInset,
|
||||
right: layout.safeInsets.right
|
||||
),
|
||||
additionalInsets: layout.additionalInsets,
|
||||
inputHeight: layout.inputHeight ?? 0.0,
|
||||
metrics: layout.metrics,
|
||||
deviceMetrics: layout.deviceMetrics,
|
||||
|
|
|
|||
|
|
@ -448,6 +448,7 @@ public final class SaveProgressScreen: ViewController {
|
|||
bottom: topInset,
|
||||
right: layout.safeInsets.right
|
||||
),
|
||||
additionalInsets: layout.additionalInsets,
|
||||
inputHeight: layout.inputHeight ?? 0.0,
|
||||
metrics: layout.metrics,
|
||||
deviceMetrics: layout.deviceMetrics,
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ final class PeerInfoScreenAddressItem: PeerInfoScreenItem {
|
|||
let text: String
|
||||
let imageSignal: Signal<(TransformImageArguments) -> DrawingContext?, NoError>?
|
||||
let action: (() -> Void)?
|
||||
let longTapAction: (() -> Void)?
|
||||
let longTapAction: ((ASDisplayNode, String) -> Void)?
|
||||
let linkItemAction: ((TextLinkItemActionType, TextLinkItem) -> Void)?
|
||||
|
||||
init(
|
||||
|
|
@ -22,7 +22,7 @@ final class PeerInfoScreenAddressItem: PeerInfoScreenItem {
|
|||
text: String,
|
||||
imageSignal: Signal<(TransformImageArguments) -> DrawingContext?, NoError>?,
|
||||
action: (() -> Void)?,
|
||||
longTapAction: (() -> Void)? = nil,
|
||||
longTapAction: ((ASDisplayNode, String) -> Void)? = nil,
|
||||
linkItemAction: ((TextLinkItemActionType, TextLinkItem) -> Void)? = nil
|
||||
) {
|
||||
self.id = id
|
||||
|
|
@ -66,6 +66,16 @@ private final class PeerInfoScreenAddressItemNode: PeerInfoScreenItemNode {
|
|||
self.addSubnode(self.bottomSeparatorNode)
|
||||
self.addSubnode(self.selectionNode)
|
||||
self.addSubnode(self.maskNode)
|
||||
|
||||
self.view.addGestureRecognizer(UILongPressGestureRecognizer(target: self, action: #selector(self.longPressGesture(_:))))
|
||||
}
|
||||
|
||||
@objc private func longPressGesture(_ recognizer: UILongPressGestureRecognizer) {
|
||||
if case .began = recognizer.state {
|
||||
if let item = self.item {
|
||||
item.longTapAction?(self, item.text)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override func update(width: CGFloat, safeInsets: UIEdgeInsets, presentationData: PresentationData, item: PeerInfoScreenItem, topItem: PeerInfoScreenItem?, bottomItem: PeerInfoScreenItem?, hasCorners: Bool, transition: ContainedViewLayoutTransition) -> CGFloat {
|
||||
|
|
@ -81,7 +91,7 @@ private final class PeerInfoScreenAddressItemNode: PeerInfoScreenItemNode {
|
|||
|
||||
self.bottomSeparatorNode.backgroundColor = presentationData.theme.list.itemBlocksSeparatorColor
|
||||
|
||||
let addressItem = ItemListAddressItem(theme: presentationData.theme, label: item.label, text: item.text, imageSignal: item.imageSignal, sectionId: 0, style: .blocks, displayDecorations: false, action: nil, longTapAction: item.longTapAction, linkItemAction: item.linkItemAction)
|
||||
let addressItem = ItemListAddressItem(theme: presentationData.theme, label: item.label, text: item.text, imageSignal: item.imageSignal, sectionId: 0, style: .blocks, displayDecorations: false, action: nil, longTapAction: nil, linkItemAction: item.linkItemAction)
|
||||
|
||||
let params = ListViewItemLayoutParams(width: width, leftInset: safeInsets.left, rightInset: safeInsets.right, availableHeight: 1000.0)
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import MultilineTextComponent
|
|||
import BundleIconComponent
|
||||
import PlainButtonComponent
|
||||
|
||||
private func dayBusinessHoursText(_ day: TelegramBusinessHours.WeekDay, offsetMinutes: Int) -> String {
|
||||
private func dayBusinessHoursText(presentationData: PresentationData, day: TelegramBusinessHours.WeekDay, offsetMinutes: Int, formatAsPlainText: Bool = false) -> String {
|
||||
var businessHoursText: String = ""
|
||||
switch day {
|
||||
case .open:
|
||||
|
|
@ -30,14 +30,18 @@ private func dayBusinessHoursText(_ day: TelegramBusinessHours.WeekDay, offsetMi
|
|||
let range = TelegramBusinessHours.WorkingTimeInterval(startMinute: range.startMinute + offsetMinutes, endMinute: range.endMinute + offsetMinutes)
|
||||
|
||||
if !resultText.isEmpty {
|
||||
resultText.append("\n")
|
||||
if formatAsPlainText {
|
||||
resultText.append(", ")
|
||||
} else {
|
||||
resultText.append("\n")
|
||||
}
|
||||
}
|
||||
let startHours = clipMinutes(range.startMinute) / 60
|
||||
let startMinutes = clipMinutes(range.startMinute) % 60
|
||||
let startText = stringForShortTimestamp(hours: Int32(startHours), minutes: Int32(startMinutes), dateTimeFormat: PresentationDateTimeFormat())
|
||||
let startText = stringForShortTimestamp(hours: Int32(startHours), minutes: Int32(startMinutes), dateTimeFormat: presentationData.dateTimeFormat, formatAsPlainText: formatAsPlainText)
|
||||
let endHours = clipMinutes(range.endMinute) / 60
|
||||
let endMinutes = clipMinutes(range.endMinute) % 60
|
||||
let endText = stringForShortTimestamp(hours: Int32(endHours), minutes: Int32(endMinutes), dateTimeFormat: PresentationDateTimeFormat())
|
||||
let endText = stringForShortTimestamp(hours: Int32(endHours), minutes: Int32(endMinutes), dateTimeFormat: presentationData.dateTimeFormat, formatAsPlainText: formatAsPlainText)
|
||||
resultText.append("\(startText) - \(endText)")
|
||||
}
|
||||
businessHoursText += resultText
|
||||
|
|
@ -51,17 +55,20 @@ final class PeerInfoScreenBusinessHoursItem: PeerInfoScreenItem {
|
|||
let label: String
|
||||
let businessHours: TelegramBusinessHours
|
||||
let requestLayout: (Bool) -> Void
|
||||
let longTapAction: (ASDisplayNode, String) -> Void
|
||||
|
||||
init(
|
||||
id: AnyHashable,
|
||||
label: String,
|
||||
businessHours: TelegramBusinessHours,
|
||||
requestLayout: @escaping (Bool) -> Void
|
||||
requestLayout: @escaping (Bool) -> Void,
|
||||
longTapAction: @escaping (ASDisplayNode, String) -> Void
|
||||
) {
|
||||
self.id = id
|
||||
self.label = label
|
||||
self.businessHours = businessHours
|
||||
self.requestLayout = requestLayout
|
||||
self.longTapAction = longTapAction
|
||||
}
|
||||
|
||||
func node() -> PeerInfoScreenItemNode {
|
||||
|
|
@ -92,6 +99,7 @@ private final class PeerInfoScreenBusinessHoursItemNode: PeerInfoScreenItemNode
|
|||
private let activateArea: AccessibilityAreaNode
|
||||
|
||||
private var item: PeerInfoScreenBusinessHoursItem?
|
||||
private var presentationData: PresentationData?
|
||||
private var theme: PresentationTheme?
|
||||
|
||||
private var currentTimezone: TimeZone
|
||||
|
|
@ -168,8 +176,8 @@ private final class PeerInfoScreenBusinessHoursItemNode: PeerInfoScreenItemNode
|
|||
super.didLoad()
|
||||
|
||||
let recognizer = TapLongTapOrDoubleTapGestureRecognizer(target: self, action: #selector(self.tapLongTapOrDoubleTapGesture(_:)))
|
||||
recognizer.tapActionAtPoint = { point in
|
||||
return .keepWithSingleTap
|
||||
recognizer.tapActionAtPoint = { _ in
|
||||
return .waitForSingleTap
|
||||
}
|
||||
recognizer.highlight = { [weak self] point in
|
||||
guard let strongSelf = self else {
|
||||
|
|
@ -185,9 +193,55 @@ private final class PeerInfoScreenBusinessHoursItemNode: PeerInfoScreenItemNode
|
|||
case .ended:
|
||||
if let (gesture, _) = recognizer.lastRecognizedGestureAndLocation {
|
||||
switch gesture {
|
||||
case .tap, .longTap:
|
||||
case .tap:
|
||||
self.isExpanded = !self.isExpanded
|
||||
self.item?.requestLayout(true)
|
||||
case .longTap:
|
||||
if let item = self.item, let presentationData = self.presentationData {
|
||||
var text = ""
|
||||
|
||||
var timezoneOffsetMinutes: Int = 0
|
||||
if self.displayLocalTimezone {
|
||||
var currentCalendar = Calendar(identifier: .gregorian)
|
||||
currentCalendar.timeZone = TimeZone(identifier: item.businessHours.timezoneId) ?? TimeZone.current
|
||||
|
||||
timezoneOffsetMinutes = (self.currentTimezone.secondsFromGMT() - currentCalendar.timeZone.secondsFromGMT()) / 60
|
||||
}
|
||||
|
||||
let businessDays: [TelegramBusinessHours.WeekDay] = self.cachedDays
|
||||
|
||||
for i in 0 ..< businessDays.count {
|
||||
let dayTitleValue: String
|
||||
//TODO:localize
|
||||
switch i {
|
||||
case 0:
|
||||
dayTitleValue = "Monday"
|
||||
case 1:
|
||||
dayTitleValue = "Tuesday"
|
||||
case 2:
|
||||
dayTitleValue = "Wednesday"
|
||||
case 3:
|
||||
dayTitleValue = "Thursday"
|
||||
case 4:
|
||||
dayTitleValue = "Friday"
|
||||
case 5:
|
||||
dayTitleValue = "Saturday"
|
||||
case 6:
|
||||
dayTitleValue = "Sunday"
|
||||
default:
|
||||
dayTitleValue = " "
|
||||
}
|
||||
|
||||
let businessHoursText = dayBusinessHoursText(presentationData: presentationData, day: businessDays[i], offsetMinutes: timezoneOffsetMinutes, formatAsPlainText: true)
|
||||
|
||||
if !text.isEmpty {
|
||||
text.append("\n")
|
||||
}
|
||||
text.append("\(dayTitleValue): \(businessHoursText)")
|
||||
}
|
||||
|
||||
item.longTapAction(self, text)
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
|
@ -212,6 +266,7 @@ private final class PeerInfoScreenBusinessHoursItemNode: PeerInfoScreenItemNode
|
|||
}
|
||||
|
||||
self.item = item
|
||||
self.presentationData = presentationData
|
||||
self.theme = presentationData.theme
|
||||
|
||||
let sideInset: CGFloat = 16.0 + safeInsets.left
|
||||
|
|
@ -272,7 +327,7 @@ private final class PeerInfoScreenBusinessHoursItemNode: PeerInfoScreenItemNode
|
|||
//TODO:localize
|
||||
let openStatusText = isOpen ? "Open" : "Closed"
|
||||
|
||||
var currentDayStatusText = currentDayIndex >= 0 && currentDayIndex < businessDays.count ? dayBusinessHoursText(businessDays[currentDayIndex], offsetMinutes: timezoneOffsetMinutes) : " "
|
||||
var currentDayStatusText = currentDayIndex >= 0 && currentDayIndex < businessDays.count ? dayBusinessHoursText(presentationData: presentationData, day: businessDays[currentDayIndex], offsetMinutes: timezoneOffsetMinutes) : " "
|
||||
|
||||
if !isOpen {
|
||||
for range in self.cachedWeekMinuteSet.rangeView {
|
||||
|
|
@ -465,7 +520,7 @@ private final class PeerInfoScreenBusinessHoursItemNode: PeerInfoScreenItemNode
|
|||
dayTitleValue = " "
|
||||
}
|
||||
|
||||
let businessHoursText = dayBusinessHoursText(businessDays[i], offsetMinutes: timezoneOffsetMinutes)
|
||||
let businessHoursText = dayBusinessHoursText(presentationData: presentationData, day: businessDays[i], offsetMinutes: timezoneOffsetMinutes)
|
||||
|
||||
let dayTitleSize = dayTitle.update(
|
||||
transition: .immediate,
|
||||
|
|
|
|||
|
|
@ -481,6 +481,8 @@ private enum PeerInfoContextSubject {
|
|||
case bio
|
||||
case phone(String)
|
||||
case link(customLink: String?)
|
||||
case businessHours(String)
|
||||
case businessLocation(String)
|
||||
}
|
||||
|
||||
private enum PeerInfoSettingsSection {
|
||||
|
|
@ -1168,6 +1170,10 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese
|
|||
//TODO:localize
|
||||
items[.peerInfo]!.append(PeerInfoScreenBusinessHoursItem(id: 300, label: "business hours", businessHours: businessHours, requestLayout: { animated in
|
||||
interaction.requestLayout(animated)
|
||||
}, longTapAction: { sourceNode, text in
|
||||
if !text.isEmpty {
|
||||
interaction.openPeerInfoContextMenu(.businessHours(text), sourceNode, nil)
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
|
|
@ -1182,6 +1188,11 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese
|
|||
imageSignal: imageSignal,
|
||||
action: {
|
||||
interaction.openLocation()
|
||||
},
|
||||
longTapAction: { sourceNode, text in
|
||||
if !text.isEmpty {
|
||||
interaction.openPeerInfoContextMenu(.businessLocation(text), sourceNode, nil)
|
||||
}
|
||||
}
|
||||
))
|
||||
} else {
|
||||
|
|
@ -1190,7 +1201,12 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese
|
|||
label: "location",
|
||||
text: businessLocation.address,
|
||||
imageSignal: nil,
|
||||
action: nil
|
||||
action: nil,
|
||||
longTapAction: { sourceNode, text in
|
||||
if !text.isEmpty {
|
||||
interaction.openPeerInfoContextMenu(.businessLocation(text), sourceNode, nil)
|
||||
}
|
||||
}
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
@ -7879,6 +7895,27 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
|||
return nil
|
||||
}
|
||||
}))
|
||||
case .businessHours(let text), .businessLocation(let text):
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
|
||||
let actions: [ContextMenuAction] = [ContextMenuAction(content: .text(title: presentationData.strings.Conversation_ContextMenuCopy, accessibilityLabel: presentationData.strings.Conversation_ContextMenuCopy), action: { [weak self] in
|
||||
UIPasteboard.general.string = text
|
||||
|
||||
self?.controller?.present(UndoOverlayController(presentationData: presentationData, content: .copy(text: presentationData.strings.Conversation_TextCopied), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), in: .current)
|
||||
})]
|
||||
|
||||
let contextMenuController = makeContextMenuController(actions: actions)
|
||||
controller.present(contextMenuController, in: .window(.root), with: ContextMenuControllerPresentationArguments(sourceNodeAndRect: { [weak self, weak sourceNode] in
|
||||
if let controller = self?.controller, let sourceNode = sourceNode {
|
||||
var rect = sourceNode.bounds.insetBy(dx: 0.0, dy: 2.0)
|
||||
if let sourceRect = sourceRect {
|
||||
rect = sourceRect.insetBy(dx: 0.0, dy: 2.0)
|
||||
}
|
||||
return (sourceNode, rect, controller.displayNode, controller.view.bounds)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -154,6 +154,7 @@ final class AutomaticBusinessMessageSetupChatContents: ChatCustomContentsProtoco
|
|||
}
|
||||
|
||||
func quickReplyUpdateShortcut(value: String) {
|
||||
self.shortcut = value
|
||||
if let shortcutId = self.shortcutId {
|
||||
self.context.engine.accountData.editMessageShortcut(id: shortcutId, shortcut: value)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -188,6 +188,53 @@ final class AutomaticBusinessMessageSetupScreenComponent: Component {
|
|||
return true
|
||||
}
|
||||
|
||||
let presentationData = component.context.sharedContext.currentPresentationData.with { $0 }
|
||||
|
||||
if self.isOn {
|
||||
if self.hasAccessToAllChatsByDefault && self.additionalPeerList.categories.isEmpty && self.additionalPeerList.peers.isEmpty {
|
||||
//TODO:localize
|
||||
self.environment?.controller()?.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: nil, text: "No recipients selected. Reset?", actions: [
|
||||
TextAlertAction(type: .genericAction, title: "Cancel", action: {
|
||||
}),
|
||||
TextAlertAction(type: .defaultAction, title: "Reset", action: {
|
||||
complete()
|
||||
})
|
||||
]), in: .window(.root))
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
if case .away = component.mode, case .custom = self.schedule {
|
||||
//TODO:localize
|
||||
var errorText: String?
|
||||
if let customScheduleStart = self.customScheduleStart, let customScheduleEnd = self.customScheduleEnd {
|
||||
if customScheduleStart >= customScheduleEnd {
|
||||
errorText = "Custom schedule end time must be larger than start time."
|
||||
}
|
||||
} else {
|
||||
if self.customScheduleStart == nil && self.customScheduleEnd == nil {
|
||||
errorText = "Custom schedule time is missing."
|
||||
} else if self.customScheduleStart == nil {
|
||||
errorText = "Custom schedule start time is missing."
|
||||
} else {
|
||||
errorText = "Custom schedule end time is missing."
|
||||
}
|
||||
}
|
||||
|
||||
if let errorText {
|
||||
//TODO:localize
|
||||
self.environment?.controller()?.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: nil, text: errorText, actions: [
|
||||
TextAlertAction(type: .genericAction, title: "Cancel", action: {
|
||||
}),
|
||||
TextAlertAction(type: .defaultAction, title: "Reset", action: {
|
||||
complete()
|
||||
})
|
||||
]), in: .window(.root))
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var mappedCategories: TelegramBusinessRecipients.Categories = []
|
||||
if self.additionalPeerList.categories.contains(.existingChats) {
|
||||
mappedCategories.insert(.existingChats)
|
||||
|
|
@ -555,6 +602,21 @@ final class AutomaticBusinessMessageSetupScreenComponent: Component {
|
|||
if let awayMessage = component.initialData.awayMessage {
|
||||
self.isOn = true
|
||||
initialRecipients = awayMessage.recipients
|
||||
|
||||
switch awayMessage.schedule {
|
||||
case .always:
|
||||
self.schedule = .always
|
||||
case let .custom(beginTimestamp, endTimestamp):
|
||||
self.schedule = .custom
|
||||
self.customScheduleStart = Date(timeIntervalSince1970: Double(beginTimestamp))
|
||||
self.customScheduleEnd = Date(timeIntervalSince1970: Double(endTimestamp))
|
||||
case .outsideWorkingHours:
|
||||
if component.initialData.businessHours != nil {
|
||||
self.schedule = .outsideBusinessHours
|
||||
} else {
|
||||
self.schedule = .always
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -839,7 +901,7 @@ final class AutomaticBusinessMessageSetupScreenComponent: Component {
|
|||
if case .away = component.mode {
|
||||
//TODO:localize
|
||||
var scheduleSectionItems: [AnyComponentWithIdentity<Empty>] = []
|
||||
for i in 0 ..< 3 {
|
||||
optionLoop: for i in 0 ..< 3 {
|
||||
let title: String
|
||||
let schedule: Schedule
|
||||
switch i {
|
||||
|
|
@ -847,6 +909,10 @@ final class AutomaticBusinessMessageSetupScreenComponent: Component {
|
|||
title = "Always Send"
|
||||
schedule = .always
|
||||
case 1:
|
||||
if component.initialData.businessHours == nil {
|
||||
continue optionLoop
|
||||
}
|
||||
|
||||
title = "Outside of Business Hours"
|
||||
schedule = .outsideBusinessHours
|
||||
default:
|
||||
|
|
@ -1396,19 +1462,22 @@ public final class AutomaticBusinessMessageSetupScreen: ViewControllerComponentC
|
|||
fileprivate let greetingMessage: TelegramBusinessGreetingMessage?
|
||||
fileprivate let awayMessage: TelegramBusinessAwayMessage?
|
||||
fileprivate let additionalPeers: [EnginePeer.Id: AutomaticBusinessMessageSetupScreenComponent.AdditionalPeerList.Peer]
|
||||
fileprivate let businessHours: TelegramBusinessHours?
|
||||
|
||||
fileprivate init(
|
||||
accountPeer: EnginePeer?,
|
||||
shortcutMessageList: ShortcutMessageList,
|
||||
greetingMessage: TelegramBusinessGreetingMessage?,
|
||||
awayMessage: TelegramBusinessAwayMessage?,
|
||||
additionalPeers: [EnginePeer.Id: AutomaticBusinessMessageSetupScreenComponent.AdditionalPeerList.Peer]
|
||||
additionalPeers: [EnginePeer.Id: AutomaticBusinessMessageSetupScreenComponent.AdditionalPeerList.Peer],
|
||||
businessHours: TelegramBusinessHours?
|
||||
) {
|
||||
self.accountPeer = accountPeer
|
||||
self.shortcutMessageList = shortcutMessageList
|
||||
self.greetingMessage = greetingMessage
|
||||
self.awayMessage = awayMessage
|
||||
self.additionalPeers = additionalPeers
|
||||
self.businessHours = businessHours
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1468,13 +1537,14 @@ public final class AutomaticBusinessMessageSetupScreen: ViewControllerComponentC
|
|||
context.engine.data.get(
|
||||
TelegramEngine.EngineData.Item.Peer.Peer(id: context.account.peerId),
|
||||
TelegramEngine.EngineData.Item.Peer.BusinessGreetingMessage(id: context.account.peerId),
|
||||
TelegramEngine.EngineData.Item.Peer.BusinessAwayMessage(id: context.account.peerId)
|
||||
TelegramEngine.EngineData.Item.Peer.BusinessAwayMessage(id: context.account.peerId),
|
||||
TelegramEngine.EngineData.Item.Peer.BusinessHours(id: context.account.peerId)
|
||||
),
|
||||
context.engine.accountData.shortcutMessageList()
|
||||
|> take(1)
|
||||
)
|
||||
|> mapToSignal { data, shortcutMessageList -> Signal<AutomaticBusinessMessageSetupScreenInitialData, NoError> in
|
||||
let (accountPeer, greetingMessage, awayMessage) = data
|
||||
let (accountPeer, greetingMessage, awayMessage, businessHours) = data
|
||||
|
||||
var additionalPeerIds = Set<EnginePeer.Id>()
|
||||
if let greetingMessage {
|
||||
|
|
@ -1505,7 +1575,8 @@ public final class AutomaticBusinessMessageSetupScreen: ViewControllerComponentC
|
|||
shortcutMessageList: shortcutMessageList,
|
||||
greetingMessage: greetingMessage,
|
||||
awayMessage: awayMessage,
|
||||
additionalPeers: additionalPeers
|
||||
additionalPeers: additionalPeers,
|
||||
businessHours: businessHours
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ final class QuickReplyEmptyStateComponent: Component {
|
|||
transition: .immediate,
|
||||
component: AnyComponent(LottieComponent(
|
||||
content: LottieComponent.AppBundleContent(name: "WriteEmoji"),
|
||||
loop: true
|
||||
loop: false
|
||||
)),
|
||||
environment: {},
|
||||
containerSize: CGSize(width: 120.0, height: 120.0)
|
||||
|
|
@ -144,9 +144,11 @@ final class QuickReplyEmptyStateComponent: Component {
|
|||
var centralContentsY: CGFloat = topInset + floor((buttonFrame.minY - topInset - centralContentsHeight) * 0.426)
|
||||
|
||||
let iconFrame = CGRect(origin: CGPoint(x: floor((availableSize.width - iconSize.width) * 0.5), y: centralContentsY), size: iconSize)
|
||||
if let iconView = self.icon.view {
|
||||
|
||||
if let iconView = self.icon.view as? LottieComponent.View {
|
||||
if iconView.superview == nil {
|
||||
self.addSubview(iconView)
|
||||
iconView.playOnce()
|
||||
}
|
||||
transition.setFrame(view: iconView, frame: iconFrame)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -590,6 +590,7 @@ final class QuickReplySetupScreenComponent: Component {
|
|||
return
|
||||
}
|
||||
|
||||
alertController?.view.endEditing(true)
|
||||
alertController?.dismissAnimated()
|
||||
self.openQuickReplyChat(shortcut: value, shortcutId: nil)
|
||||
}
|
||||
|
|
@ -638,6 +639,7 @@ final class QuickReplySetupScreenComponent: Component {
|
|||
} else {
|
||||
component.context.engine.accountData.editMessageShortcut(id: id, shortcut: value)
|
||||
|
||||
alertController?.view.endEditing(true)
|
||||
alertController?.dismissAnimated()
|
||||
}
|
||||
}
|
||||
|
|
@ -923,7 +925,7 @@ final class QuickReplySetupScreenComponent: Component {
|
|||
component: AnyComponent(QuickReplyEmptyStateComponent(
|
||||
theme: environment.theme,
|
||||
strings: environment.strings,
|
||||
insets: UIEdgeInsets(top: environment.navigationHeight, left: environment.safeInsets.left, bottom: environment.safeInsets.bottom, right: environment.safeInsets.right),
|
||||
insets: UIEdgeInsets(top: environment.navigationHeight, left: environment.safeInsets.left, bottom: environment.safeInsets.bottom + environment.additionalInsets.bottom, right: environment.safeInsets.right),
|
||||
action: { [weak self] in
|
||||
guard let self else {
|
||||
return
|
||||
|
|
@ -955,7 +957,7 @@ final class QuickReplySetupScreenComponent: Component {
|
|||
statusBarHeight = max(statusBarHeight, 1.0)
|
||||
}
|
||||
|
||||
var listBottomInset = environment.safeInsets.bottom
|
||||
var listBottomInset = environment.safeInsets.bottom + environment.additionalInsets.bottom
|
||||
let navigationHeight = self.updateNavigationBar(
|
||||
component: component,
|
||||
theme: environment.theme,
|
||||
|
|
@ -1090,12 +1092,13 @@ final class QuickReplySetupScreenComponent: Component {
|
|||
animateScale: false,
|
||||
animateContents: false
|
||||
))),
|
||||
insets: UIEdgeInsets(top: 4.0, left: environment.safeInsets.left, bottom: environment.safeInsets.bottom, right: environment.safeInsets.right)
|
||||
insets: UIEdgeInsets(top: 4.0, left: environment.safeInsets.left, bottom: environment.safeInsets.bottom + environment.additionalInsets.bottom, right: environment.safeInsets.right)
|
||||
)),
|
||||
environment: {},
|
||||
containerSize: availableSize
|
||||
)
|
||||
let selectionPanelFrame = CGRect(origin: CGPoint(x: 0.0, y: availableSize.height - selectionPanelSize.height), size: selectionPanelSize)
|
||||
print("selectionPanelFrame: \(selectionPanelFrame.minY)")
|
||||
listBottomInset = selectionPanelSize.height
|
||||
if let selectionPanelView = selectionPanel.view {
|
||||
var animateIn = false
|
||||
|
|
|
|||
|
|
@ -304,9 +304,7 @@ final class BusinessHoursSetupScreenComponent: Component {
|
|||
let businessHours = try self.daysState.asBusinessHours()
|
||||
let _ = component.context.engine.accountData.updateAccountBusinessHours(businessHours: businessHours).startStandalone()
|
||||
return true
|
||||
} catch let error {
|
||||
let _ = error
|
||||
|
||||
} catch _ {
|
||||
let presentationData = component.context.sharedContext.currentPresentationData.with { $0 }
|
||||
//TODO:localize
|
||||
self.environment?.controller()?.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: nil, text: "Business hours are intersecting. Reset?", actions: [
|
||||
|
|
|
|||
|
|
@ -225,11 +225,7 @@ public final class QuickReplyNameAlertContentNode: AlertContentNode {
|
|||
|
||||
private let hapticFeedback = HapticFeedback()
|
||||
|
||||
var complete: (() -> Void)? {
|
||||
didSet {
|
||||
self.inputFieldNode.complete = self.complete
|
||||
}
|
||||
}
|
||||
var complete: (() -> Void)?
|
||||
|
||||
override public var dismissOnOutsideTap: Bool {
|
||||
return self.isUserInteractionEnabled
|
||||
|
|
@ -295,6 +291,15 @@ public final class QuickReplyNameAlertContentNode: AlertContentNode {
|
|||
}
|
||||
|
||||
self.updateTheme(theme)
|
||||
|
||||
self.inputFieldNode.complete = { [weak self] in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
if let lastNode = self.actionNodes.last, lastNode.actionEnabled {
|
||||
self.complete?()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
deinit {
|
||||
|
|
|
|||
|
|
@ -1094,6 +1094,7 @@ public class VideoMessageCameraScreen: ViewController {
|
|||
bottom: 44.0,
|
||||
right: layout.safeInsets.right
|
||||
),
|
||||
additionalInsets: layout.additionalInsets,
|
||||
inputHeight: layout.inputHeight ?? 0.0,
|
||||
metrics: layout.metrics,
|
||||
deviceMetrics: layout.deviceMetrics,
|
||||
|
|
|
|||
|
|
@ -9494,15 +9494,16 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||
return
|
||||
}
|
||||
|
||||
self.updateChatPresentationInterfaceState(animated: true, interactive: false, {
|
||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil).withUpdatedComposeInputState(ChatTextInputState(inputText: NSAttributedString(string: ""))).withUpdatedComposeDisableUrlPreviews([]) }
|
||||
})
|
||||
|
||||
if !self.presentationInterfaceState.isPremium {
|
||||
let controller = PremiumIntroScreen(context: self.context, source: .settings)
|
||||
self.push(controller)
|
||||
return
|
||||
}
|
||||
|
||||
self.updateChatPresentationInterfaceState(animated: true, interactive: false, {
|
||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil).withUpdatedComposeInputState(ChatTextInputState(inputText: NSAttributedString(string: ""))).withUpdatedComposeDisableUrlPreviews([]) }
|
||||
})
|
||||
self.context.engine.accountData.sendMessageShortcut(peerId: peerId, id: shortcutId)
|
||||
|
||||
/*self.chatDisplayNode.setupSendActionOnViewUpdate({ [weak self] in
|
||||
|
|
@ -9906,37 +9907,36 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
guard let peer = strongSelf.presentationInterfaceState.renderedPeer?.peer else {
|
||||
return
|
||||
}
|
||||
|
||||
var bannedMediaInput = false
|
||||
if let channel = peer as? TelegramChannel {
|
||||
if channel.hasBannedPermission(.banSendVoice) != nil && channel.hasBannedPermission(.banSendInstantVideos) != nil {
|
||||
bannedMediaInput = true
|
||||
} else if channel.hasBannedPermission(.banSendVoice) != nil {
|
||||
if channel.hasBannedPermission(.banSendInstantVideos) == nil {
|
||||
strongSelf.displayMediaRecordingTooltip()
|
||||
return
|
||||
if let peer = strongSelf.presentationInterfaceState.renderedPeer?.peer {
|
||||
if let channel = peer as? TelegramChannel {
|
||||
if channel.hasBannedPermission(.banSendVoice) != nil && channel.hasBannedPermission(.banSendInstantVideos) != nil {
|
||||
bannedMediaInput = true
|
||||
} else if channel.hasBannedPermission(.banSendVoice) != nil {
|
||||
if channel.hasBannedPermission(.banSendInstantVideos) == nil {
|
||||
strongSelf.displayMediaRecordingTooltip()
|
||||
return
|
||||
}
|
||||
} else if channel.hasBannedPermission(.banSendInstantVideos) != nil {
|
||||
if channel.hasBannedPermission(.banSendVoice) == nil {
|
||||
strongSelf.displayMediaRecordingTooltip()
|
||||
return
|
||||
}
|
||||
}
|
||||
} else if channel.hasBannedPermission(.banSendInstantVideos) != nil {
|
||||
if channel.hasBannedPermission(.banSendVoice) == nil {
|
||||
strongSelf.displayMediaRecordingTooltip()
|
||||
return
|
||||
}
|
||||
}
|
||||
} else if let group = peer as? TelegramGroup {
|
||||
if group.hasBannedPermission(.banSendVoice) && group.hasBannedPermission(.banSendInstantVideos) {
|
||||
bannedMediaInput = true
|
||||
} else if group.hasBannedPermission(.banSendVoice) {
|
||||
if !group.hasBannedPermission(.banSendInstantVideos) {
|
||||
strongSelf.displayMediaRecordingTooltip()
|
||||
return
|
||||
}
|
||||
} else if group.hasBannedPermission(.banSendInstantVideos) {
|
||||
if !group.hasBannedPermission(.banSendVoice) {
|
||||
strongSelf.displayMediaRecordingTooltip()
|
||||
return
|
||||
} else if let group = peer as? TelegramGroup {
|
||||
if group.hasBannedPermission(.banSendVoice) && group.hasBannedPermission(.banSendInstantVideos) {
|
||||
bannedMediaInput = true
|
||||
} else if group.hasBannedPermission(.banSendVoice) {
|
||||
if !group.hasBannedPermission(.banSendInstantVideos) {
|
||||
strongSelf.displayMediaRecordingTooltip()
|
||||
return
|
||||
}
|
||||
} else if group.hasBannedPermission(.banSendInstantVideos) {
|
||||
if !group.hasBannedPermission(.banSendVoice) {
|
||||
strongSelf.displayMediaRecordingTooltip()
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -14202,10 +14202,6 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||
}
|
||||
|
||||
func requestVideoRecorder() {
|
||||
guard let peerId = self.chatLocation.peerId else {
|
||||
return
|
||||
}
|
||||
|
||||
if self.videoRecorderValue == nil {
|
||||
if let currentInputPanelFrame = self.chatDisplayNode.currentInputPanelFrame() {
|
||||
if self.recorderFeedback == nil {
|
||||
|
|
@ -14219,6 +14215,16 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||
}
|
||||
|
||||
var isBot = false
|
||||
|
||||
var allowLiveUpload = false
|
||||
var viewOnceAvailable = false
|
||||
if let peerId = self.chatLocation.peerId {
|
||||
allowLiveUpload = peerId.namespace != Namespaces.Peer.SecretChat
|
||||
viewOnceAvailable = !isScheduledMessages && peerId.namespace == Namespaces.Peer.CloudUser && peerId != self.context.account.peerId && !isBot
|
||||
} else if case .customChatContents = self.chatLocation {
|
||||
allowLiveUpload = true
|
||||
}
|
||||
|
||||
if let user = self.presentationInterfaceState.renderedPeer?.peer as? TelegramUser, user.botInfo != nil {
|
||||
isBot = true
|
||||
}
|
||||
|
|
@ -14226,8 +14232,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||
let controller = VideoMessageCameraScreen(
|
||||
context: self.context,
|
||||
updatedPresentationData: self.updatedPresentationData,
|
||||
allowLiveUpload: peerId.namespace != Namespaces.Peer.SecretChat,
|
||||
viewOnceAvailable: !isScheduledMessages && peerId.namespace == Namespaces.Peer.CloudUser && peerId != self.context.account.peerId && !isBot,
|
||||
allowLiveUpload: allowLiveUpload,
|
||||
viewOnceAvailable: viewOnceAvailable,
|
||||
inputPanelFrame: (currentInputPanelFrame, self.chatDisplayNode.inputNode != nil),
|
||||
chatNode: self.chatDisplayNode.historyNode,
|
||||
completion: { [weak self] message, silentPosting, scheduleTime in
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ extension ChatControllerImpl {
|
|||
}
|
||||
} else {
|
||||
self.chatTitleView?.titleContent = .custom("\(value)", nil, false)
|
||||
alertController?.view.endEditing(true)
|
||||
alertController?.dismissAnimated()
|
||||
|
||||
if case let .customChatContents(customChatContents) = self.subject {
|
||||
|
|
|
|||
|
|
@ -320,16 +320,12 @@ extension ChatControllerImpl {
|
|||
attachmentController?.dismiss(animated: true)
|
||||
self?.presentICloudFileGallery()
|
||||
}, send: { [weak self] mediaReference in
|
||||
guard let strongSelf = self, let peerId = strongSelf.chatLocation.peerId else {
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
|
||||
let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: mediaReference, threadId: strongSelf.chatLocation.threadId, replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])
|
||||
let _ = (enqueueMessages(account: strongSelf.context.account, peerId: peerId, messages: strongSelf.transformEnqueueMessages([message]))
|
||||
|> deliverOnMainQueue).startStandalone(next: { [weak self] _ in
|
||||
if let strongSelf = self, strongSelf.presentationInterfaceState.subject != .scheduledMessages {
|
||||
strongSelf.chatDisplayNode.historyNode.scrollToEndOfHistory()
|
||||
}
|
||||
})
|
||||
strongSelf.sendMessages([message], media: true)
|
||||
})
|
||||
if let controller = controller as? AttachmentFileControllerImpl {
|
||||
let _ = currentFilesController.swap(controller)
|
||||
|
|
@ -684,26 +680,28 @@ extension ChatControllerImpl {
|
|||
return entry ?? GeneratedMediaStoreSettings.defaultSettings
|
||||
}
|
||||
|> deliverOnMainQueue).startStandalone(next: { [weak self] settings in
|
||||
guard let strongSelf = self, let peer = strongSelf.presentationInterfaceState.renderedPeer?.peer else {
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
strongSelf.chatDisplayNode.dismissInput()
|
||||
|
||||
var bannedSendMedia: (Int32, Bool)?
|
||||
var canSendPolls = true
|
||||
if let channel = peer as? TelegramChannel {
|
||||
if let value = channel.hasBannedPermission(.banSendMedia) {
|
||||
bannedSendMedia = value
|
||||
}
|
||||
if channel.hasBannedPermission(.banSendPolls) != nil {
|
||||
canSendPolls = false
|
||||
}
|
||||
} else if let group = peer as? TelegramGroup {
|
||||
if group.hasBannedPermission(.banSendMedia) {
|
||||
bannedSendMedia = (Int32.max, false)
|
||||
}
|
||||
if group.hasBannedPermission(.banSendPolls) {
|
||||
canSendPolls = false
|
||||
if let peer = strongSelf.presentationInterfaceState.renderedPeer?.peer {
|
||||
if let channel = peer as? TelegramChannel {
|
||||
if let value = channel.hasBannedPermission(.banSendMedia) {
|
||||
bannedSendMedia = value
|
||||
}
|
||||
if channel.hasBannedPermission(.banSendPolls) != nil {
|
||||
canSendPolls = false
|
||||
}
|
||||
} else if let group = peer as? TelegramGroup {
|
||||
if group.hasBannedPermission(.banSendMedia) {
|
||||
bannedSendMedia = (Int32.max, false)
|
||||
}
|
||||
if group.hasBannedPermission(.banSendPolls) {
|
||||
canSendPolls = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -771,11 +769,15 @@ extension ChatControllerImpl {
|
|||
}
|
||||
|
||||
var slowModeEnabled = false
|
||||
if let channel = peer as? TelegramChannel, channel.isRestrictedBySlowmode {
|
||||
slowModeEnabled = true
|
||||
var hasSchedule = false
|
||||
if let peer = strongSelf.presentationInterfaceState.renderedPeer?.peer {
|
||||
if let channel = peer as? TelegramChannel, channel.isRestrictedBySlowmode {
|
||||
slowModeEnabled = true
|
||||
}
|
||||
hasSchedule = strongSelf.presentationInterfaceState.subject != .scheduledMessages && peer.id.namespace != Namespaces.Peer.SecretChat
|
||||
}
|
||||
|
||||
let controller = legacyAttachmentMenu(context: strongSelf.context, peer: peer, threadTitle: strongSelf.threadInfo?.title, chatLocation: strongSelf.chatLocation, editMediaOptions: menuEditMediaOptions, saveEditedPhotos: settings.storeEditedPhotos, allowGrouping: true, hasSchedule: strongSelf.presentationInterfaceState.subject != .scheduledMessages && peer.id.namespace != Namespaces.Peer.SecretChat, canSendPolls: canSendPolls, updatedPresentationData: strongSelf.updatedPresentationData, parentController: legacyController, recentlyUsedInlineBots: strongSelf.recentlyUsedInlineBotsValue, initialCaption: inputText, openGallery: {
|
||||
let controller = legacyAttachmentMenu(context: strongSelf.context, peer: strongSelf.presentationInterfaceState.renderedPeer?.peer, threadTitle: strongSelf.threadInfo?.title, chatLocation: strongSelf.chatLocation, editMediaOptions: menuEditMediaOptions, saveEditedPhotos: settings.storeEditedPhotos, allowGrouping: true, hasSchedule: hasSchedule, canSendPolls: canSendPolls, updatedPresentationData: strongSelf.updatedPresentationData, parentController: legacyController, recentlyUsedInlineBots: strongSelf.recentlyUsedInlineBotsValue, initialCaption: inputText, openGallery: {
|
||||
self?.presentOldMediaPicker(fileMode: false, editingMedia: editMediaOptions != nil, completion: { signals, silentPosting, scheduleTime in
|
||||
if !inputText.string.isEmpty {
|
||||
strongSelf.clearInputText()
|
||||
|
|
@ -787,7 +789,7 @@ extension ChatControllerImpl {
|
|||
}
|
||||
})
|
||||
}, openCamera: { [weak self] cameraView, menuController in
|
||||
if let strongSelf = self, let peer = strongSelf.presentationInterfaceState.renderedPeer?.peer {
|
||||
if let strongSelf = self {
|
||||
var enablePhoto = true
|
||||
var enableVideo = true
|
||||
|
||||
|
|
@ -798,19 +800,21 @@ extension ChatControllerImpl {
|
|||
var bannedSendPhotos: (Int32, Bool)?
|
||||
var bannedSendVideos: (Int32, Bool)?
|
||||
|
||||
if let channel = peer as? TelegramChannel {
|
||||
if let value = channel.hasBannedPermission(.banSendPhotos) {
|
||||
bannedSendPhotos = value
|
||||
}
|
||||
if let value = channel.hasBannedPermission(.banSendVideos) {
|
||||
bannedSendVideos = value
|
||||
}
|
||||
} else if let group = peer as? TelegramGroup {
|
||||
if group.hasBannedPermission(.banSendPhotos) {
|
||||
bannedSendPhotos = (Int32.max, false)
|
||||
}
|
||||
if group.hasBannedPermission(.banSendVideos) {
|
||||
bannedSendVideos = (Int32.max, false)
|
||||
if let peer = strongSelf.presentationInterfaceState.renderedPeer?.peer {
|
||||
if let channel = peer as? TelegramChannel {
|
||||
if let value = channel.hasBannedPermission(.banSendPhotos) {
|
||||
bannedSendPhotos = value
|
||||
}
|
||||
if let value = channel.hasBannedPermission(.banSendVideos) {
|
||||
bannedSendVideos = value
|
||||
}
|
||||
} else if let group = peer as? TelegramGroup {
|
||||
if group.hasBannedPermission(.banSendPhotos) {
|
||||
bannedSendPhotos = (Int32.max, false)
|
||||
}
|
||||
if group.hasBannedPermission(.banSendVideos) {
|
||||
bannedSendVideos = (Int32.max, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -821,7 +825,15 @@ extension ChatControllerImpl {
|
|||
enableVideo = false
|
||||
}
|
||||
|
||||
presentedLegacyCamera(context: strongSelf.context, peer: peer, chatLocation: strongSelf.chatLocation, cameraView: cameraView, menuController: menuController, parentController: strongSelf, editingMedia: editMediaOptions != nil, saveCapturedPhotos: peer.id.namespace != Namespaces.Peer.SecretChat, mediaGrouping: true, initialCaption: inputText, hasSchedule: strongSelf.presentationInterfaceState.subject != .scheduledMessages && peer.id.namespace != Namespaces.Peer.SecretChat, enablePhoto: enablePhoto, enableVideo: enableVideo, sendMessagesWithSignals: { [weak self] signals, silentPosting, scheduleTime in
|
||||
var storeCapturedPhotos = false
|
||||
var hasSchedule = false
|
||||
if let peer = strongSelf.presentationInterfaceState.renderedPeer?.peer {
|
||||
storeCapturedPhotos = peer.id.namespace != Namespaces.Peer.SecretChat
|
||||
|
||||
hasSchedule = strongSelf.presentationInterfaceState.subject != .scheduledMessages && peer.id.namespace != Namespaces.Peer.SecretChat
|
||||
}
|
||||
|
||||
presentedLegacyCamera(context: strongSelf.context, peer: strongSelf.presentationInterfaceState.renderedPeer?.peer, chatLocation: strongSelf.chatLocation, cameraView: cameraView, menuController: menuController, parentController: strongSelf, editingMedia: editMediaOptions != nil, saveCapturedPhotos: storeCapturedPhotos, mediaGrouping: true, initialCaption: inputText, hasSchedule: hasSchedule, enablePhoto: enablePhoto, enableVideo: enableVideo, sendMessagesWithSignals: { [weak self] signals, silentPosting, scheduleTime in
|
||||
if let strongSelf = self {
|
||||
if editMediaOptions != nil {
|
||||
strongSelf.editMessageMediaWithLegacySignals(signals!)
|
||||
|
|
@ -979,7 +991,7 @@ extension ChatControllerImpl {
|
|||
|
||||
func presentICloudFileGallery(editingMessage: Bool = false) {
|
||||
let _ = (self.context.engine.data.get(
|
||||
TelegramEngine.EngineData.Item.Peer.Peer(id: context.account.peerId),
|
||||
TelegramEngine.EngineData.Item.Peer.Peer(id: self.context.account.peerId),
|
||||
TelegramEngine.EngineData.Item.Configuration.UserLimits(isPremium: false),
|
||||
TelegramEngine.EngineData.Item.Configuration.UserLimits(isPremium: true)
|
||||
)
|
||||
|
|
@ -1610,17 +1622,12 @@ extension ChatControllerImpl {
|
|||
}
|
||||
|
||||
func openCamera(cameraView: TGAttachmentCameraView? = nil) {
|
||||
guard let peer = self.presentationInterfaceState.renderedPeer?.peer else {
|
||||
return
|
||||
}
|
||||
let _ = peer
|
||||
|
||||
let _ = (self.context.sharedContext.accountManager.transaction { transaction -> GeneratedMediaStoreSettings in
|
||||
let entry = transaction.getSharedData(ApplicationSpecificSharedDataKeys.generatedMediaStoreSettings)?.get(GeneratedMediaStoreSettings.self)
|
||||
return entry ?? GeneratedMediaStoreSettings.defaultSettings
|
||||
}
|
||||
|> deliverOnMainQueue).startStandalone(next: { [weak self] settings in
|
||||
guard let strongSelf = self, let peer = strongSelf.presentationInterfaceState.renderedPeer?.peer else {
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -1634,19 +1641,21 @@ extension ChatControllerImpl {
|
|||
var bannedSendPhotos: (Int32, Bool)?
|
||||
var bannedSendVideos: (Int32, Bool)?
|
||||
|
||||
if let channel = peer as? TelegramChannel {
|
||||
if let value = channel.hasBannedPermission(.banSendPhotos) {
|
||||
bannedSendPhotos = value
|
||||
}
|
||||
if let value = channel.hasBannedPermission(.banSendVideos) {
|
||||
bannedSendVideos = value
|
||||
}
|
||||
} else if let group = peer as? TelegramGroup {
|
||||
if group.hasBannedPermission(.banSendPhotos) {
|
||||
bannedSendPhotos = (Int32.max, false)
|
||||
}
|
||||
if group.hasBannedPermission(.banSendVideos) {
|
||||
bannedSendVideos = (Int32.max, false)
|
||||
if let peer = strongSelf.presentationInterfaceState.renderedPeer?.peer {
|
||||
if let channel = peer as? TelegramChannel {
|
||||
if let value = channel.hasBannedPermission(.banSendPhotos) {
|
||||
bannedSendPhotos = value
|
||||
}
|
||||
if let value = channel.hasBannedPermission(.banSendVideos) {
|
||||
bannedSendVideos = value
|
||||
}
|
||||
} else if let group = peer as? TelegramGroup {
|
||||
if group.hasBannedPermission(.banSendPhotos) {
|
||||
bannedSendPhotos = (Int32.max, false)
|
||||
}
|
||||
if group.hasBannedPermission(.banSendVideos) {
|
||||
bannedSendVideos = (Int32.max, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1657,10 +1666,15 @@ extension ChatControllerImpl {
|
|||
enableVideo = false
|
||||
}
|
||||
|
||||
let storeCapturedMedia = peer.id.namespace != Namespaces.Peer.SecretChat
|
||||
var storeCapturedMedia = false
|
||||
var hasSchedule = false
|
||||
if let peer = strongSelf.presentationInterfaceState.renderedPeer?.peer {
|
||||
storeCapturedMedia = peer.id.namespace != Namespaces.Peer.SecretChat
|
||||
hasSchedule = strongSelf.presentationInterfaceState.subject != .scheduledMessages && peer.id.namespace != Namespaces.Peer.SecretChat
|
||||
}
|
||||
let inputText = strongSelf.presentationInterfaceState.interfaceState.effectiveInputState.inputText
|
||||
|
||||
presentedLegacyCamera(context: strongSelf.context, peer: peer, chatLocation: strongSelf.chatLocation, cameraView: cameraView, menuController: nil, parentController: strongSelf, attachmentController: self?.attachmentController, editingMedia: false, saveCapturedPhotos: storeCapturedMedia, mediaGrouping: true, initialCaption: inputText, hasSchedule: strongSelf.presentationInterfaceState.subject != .scheduledMessages && peer.id.namespace != Namespaces.Peer.SecretChat, enablePhoto: enablePhoto, enableVideo: enableVideo, sendMessagesWithSignals: { [weak self] signals, silentPosting, scheduleTime in
|
||||
presentedLegacyCamera(context: strongSelf.context, peer: strongSelf.presentationInterfaceState.renderedPeer?.peer, chatLocation: strongSelf.chatLocation, cameraView: cameraView, menuController: nil, parentController: strongSelf, attachmentController: self?.attachmentController, editingMedia: false, saveCapturedPhotos: storeCapturedMedia, mediaGrouping: true, initialCaption: inputText, hasSchedule: hasSchedule, enablePhoto: enablePhoto, enableVideo: enableVideo, sendMessagesWithSignals: { [weak self] signals, silentPosting, scheduleTime in
|
||||
if let strongSelf = self {
|
||||
strongSelf.enqueueMediaMessages(signals: signals, silentPosting: silentPosting, scheduleTime: scheduleTime > 0 ? scheduleTime : nil)
|
||||
if !inputText.string.isEmpty {
|
||||
|
|
|
|||
|
|
@ -243,8 +243,11 @@ private func updatedContextQueryResultStateForQuery(context: AccountContext, pee
|
|||
return false
|
||||
}
|
||||
var sortedCommands = filteredCommands.map(ChatInputTextCommand.command)
|
||||
for shortcut in shortcuts {
|
||||
sortedCommands.append(.shortcut(shortcut))
|
||||
if !shortcuts.isEmpty {
|
||||
sortedCommands.removeAll()
|
||||
for shortcut in shortcuts {
|
||||
sortedCommands.append(.shortcut(shortcut))
|
||||
}
|
||||
}
|
||||
return { _ in return .commands(ChatInputQueryCommandsResult(
|
||||
commands: sortedCommands,
|
||||
|
|
|
|||
|
|
@ -720,6 +720,7 @@ public class TranslateScreen: ViewController {
|
|||
statusBarHeight: 0.0,
|
||||
navigationHeight: navigationHeight,
|
||||
safeInsets: UIEdgeInsets(top: layout.intrinsicInsets.top + layout.safeInsets.top, left: layout.safeInsets.left, bottom: layout.intrinsicInsets.bottom + layout.safeInsets.bottom, right: layout.safeInsets.right),
|
||||
additionalInsets: layout.additionalInsets,
|
||||
inputHeight: layout.inputHeight ?? 0.0,
|
||||
metrics: layout.metrics,
|
||||
deviceMetrics: layout.deviceMetrics,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue