mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-10-09 03:20:48 +00:00
Various UI fixes
This commit is contained in:
parent
a1bd27dcf3
commit
fd76dcbd46
@ -402,7 +402,7 @@ private class ChatListStatusFailedNode: ChatListStatusContentNode {
|
||||
}
|
||||
|
||||
let diameter: CGFloat = 14.0
|
||||
let rect = CGRect(origin: CGPoint(x: floor((bounds.width - diameter) / 2.0), y: floor((bounds.height - diameter) / 2.0)), size: CGSize(width: diameter, height: diameter)).offsetBy(dx: 1.0, dy: 1.0)
|
||||
let rect = CGRect(origin: CGPoint(x: floor((bounds.width - diameter) / 2.0), y: floor((bounds.height - diameter) / 2.0)), size: CGSize(width: diameter, height: diameter)).offsetBy(dx: 1.0, dy: UIScreenPixel)
|
||||
|
||||
context.setFillColor(parameters.fill.cgColor)
|
||||
context.fillEllipse(in: rect)
|
||||
@ -412,7 +412,7 @@ private class ChatListStatusFailedNode: ChatListStatusContentNode {
|
||||
let stringRect = string.boundingRect(with: rect.size, options: .usesLineFragmentOrigin, context: nil)
|
||||
|
||||
UIGraphicsPushContext(context)
|
||||
string.draw(at: CGPoint(x: rect.minX + floor((rect.width - stringRect.width) / 2.0), y: 1.0 + rect.minY + floor((rect.height - stringRect.height) / 2.0)))
|
||||
string.draw(at: CGPoint(x: rect.minX + floor((rect.width - stringRect.width) / 2.0), y: 1.0 - UIScreenPixel + rect.minY + floor((rect.height - stringRect.height) / 2.0)))
|
||||
UIGraphicsPopContext()
|
||||
}
|
||||
|
||||
|
@ -147,7 +147,7 @@
|
||||
UIImpactFeedbackGenerator *generator = [[UIImpactFeedbackGenerator alloc] initWithStyle:UIImpactFeedbackStyleMedium];
|
||||
[generator impactOccurred];
|
||||
|
||||
TGMediaPickerSendActionSheetController *controller = [[TGMediaPickerSendActionSheetController alloc] initWithContext:strongSelf->_context sendButtonFrame:strongSelf.galleryModel.interfaceView.doneButtonFrame canSendSilently:hasSilentPosting];
|
||||
TGMediaPickerSendActionSheetController *controller = [[TGMediaPickerSendActionSheetController alloc] initWithContext:strongSelf->_context sendButtonFrame:strongSelf.galleryModel.interfaceView.doneButtonFrame canSendSilently:hasSilentPosting canSchedule:hasSchedule];
|
||||
controller.send = ^{
|
||||
__strong TGMediaPickerModernGalleryMixin *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
|
@ -8,7 +8,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
@property (nonatomic, copy) void (^sendSilently)(void);
|
||||
@property (nonatomic, copy) void (^schedule)(void);
|
||||
|
||||
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context sendButtonFrame:(CGRect)sendButtonFrame canSendSilently:(bool)canSendSilently;
|
||||
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context sendButtonFrame:(CGRect)sendButtonFrame canSendSilently:(bool)canSendSilently canSchedule:(bool)canSchedule;
|
||||
|
||||
@end
|
||||
|
||||
|
@ -75,6 +75,7 @@
|
||||
|
||||
CGRect _sendButtonFrame;
|
||||
bool _canSendSilently;
|
||||
bool _canSchedule;
|
||||
bool _autorotationWasEnabled;
|
||||
bool _dismissed;
|
||||
|
||||
@ -90,12 +91,13 @@
|
||||
|
||||
@implementation TGMediaPickerSendActionSheetController
|
||||
|
||||
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context sendButtonFrame:(CGRect)sendButtonFrame canSendSilently:(bool)canSendSilently {
|
||||
- (instancetype)initWithContext:(id<LegacyComponentsContext>)context sendButtonFrame:(CGRect)sendButtonFrame canSendSilently:(bool)canSendSilently canSchedule:(bool)canSchedule {
|
||||
self = [super initWithContext:context];
|
||||
if (self != nil) {
|
||||
_context = context;
|
||||
_sendButtonFrame = sendButtonFrame;
|
||||
_canSendSilently = canSendSilently;
|
||||
_canSchedule = canSchedule;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@ -125,12 +127,14 @@
|
||||
[_containerView addSubview:_sendSilentlyButton];
|
||||
}
|
||||
|
||||
_scheduleButton = [[TGMediaPickerSendActionSheetItemView alloc] initWithTitle:TGLocalized(@"Conversation.SendMessage.ScheduleMessage") icon:TGComponentsImageNamed(@"MediaSchedule")];
|
||||
_scheduleButton.pressed = ^{
|
||||
__strong TGMediaPickerSendActionSheetController *strongSelf = weakSelf;
|
||||
[strongSelf schedulePressed];
|
||||
};
|
||||
[_containerView addSubview:_scheduleButton];
|
||||
if (_canSchedule) {
|
||||
_scheduleButton = [[TGMediaPickerSendActionSheetItemView alloc] initWithTitle:TGLocalized(@"Conversation.SendMessage.ScheduleMessage") icon:TGComponentsImageNamed(@"MediaSchedule")];
|
||||
_scheduleButton.pressed = ^{
|
||||
__strong TGMediaPickerSendActionSheetController *strongSelf = weakSelf;
|
||||
[strongSelf schedulePressed];
|
||||
};
|
||||
[_containerView addSubview:_scheduleButton];
|
||||
}
|
||||
|
||||
TGMediaAssetsPallete *pallete = nil;
|
||||
if ([[LegacyComponentsGlobals provider] respondsToSelector:@selector(mediaAssetsPallete)])
|
||||
@ -238,7 +242,7 @@
|
||||
|
||||
CGFloat itemHeight = 44.0;
|
||||
CGFloat containerWidth = 240.0;
|
||||
CGFloat containerHeight = _canSendSilently ? itemHeight * 2.0 : itemHeight;
|
||||
CGFloat containerHeight = _canSendSilently && _canSchedule ? itemHeight * 2.0 : itemHeight;
|
||||
containerWidth = MAX(containerWidth, MAX(_sendSilentlyButton.buttonLabel.frame.size.width, _scheduleButton.buttonLabel.frame.size.width) + 84.0);
|
||||
if (!_dismissed) {
|
||||
_containerView.frame = CGRectMake(CGRectGetMaxX(_sendButtonFrame) - containerWidth - 8.0, _sendButtonFrame.origin.y - containerHeight - 4.0, containerWidth, containerHeight);
|
||||
|
@ -20,7 +20,7 @@ public struct LegacyAttachmentMenuMediaEditing: OptionSet {
|
||||
public static let imageOrVideo = LegacyAttachmentMenuMediaEditing(rawValue: 1 << 0)
|
||||
}
|
||||
|
||||
public func legacyAttachmentMenu(context: AccountContext, peer: Peer, editMediaOptions: LegacyAttachmentMenuMediaEditing?, saveEditedPhotos: Bool, allowGrouping: Bool, theme: PresentationTheme, strings: PresentationStrings, parentController: LegacyController, recentlyUsedInlineBots: [Peer], initialCaption: String, 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, presentScheduleController: @escaping (@escaping (Int32) -> Void) -> Void, sendMessagesWithSignals: @escaping ([Any]?, Bool, Int32) -> Void, selectRecentlyUsedInlineBot: @escaping (Peer) -> Void) -> TGMenuSheetController {
|
||||
public func legacyAttachmentMenu(context: AccountContext, peer: Peer, editMediaOptions: LegacyAttachmentMenuMediaEditing?, saveEditedPhotos: Bool, allowGrouping: Bool, hasSchedule: Bool, theme: PresentationTheme, strings: PresentationStrings, parentController: LegacyController, recentlyUsedInlineBots: [Peer], initialCaption: String, 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, presentSchedulePicker: @escaping (@escaping (Int32) -> Void) -> Void, sendMessagesWithSignals: @escaping ([Any]?, Bool, Int32) -> Void, selectRecentlyUsedInlineBot: @escaping (Peer) -> Void) -> TGMenuSheetController {
|
||||
let isSecretChat = peer.id.namespace == Namespaces.Peer.SecretChat
|
||||
|
||||
let controller = TGMenuSheetController(context: parentController.context, dark: false)!
|
||||
@ -72,13 +72,13 @@ public func legacyAttachmentMenu(context: AccountContext, peer: Peer, editMediaO
|
||||
}
|
||||
if peer.id != context.account.peerId {
|
||||
if peer is TelegramUser {
|
||||
carouselItem.hasTimer = true
|
||||
carouselItem.hasTimer = !hasSchedule
|
||||
}
|
||||
carouselItem.hasSilentPosting = !isSecretChat
|
||||
}
|
||||
carouselItem.hasSchedule = !isSecretChat
|
||||
carouselItem.hasSchedule = hasSchedule
|
||||
carouselItem.presentScheduleController = { done in
|
||||
presentScheduleController { time in
|
||||
presentSchedulePicker { time in
|
||||
done?(time)
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ public func guessMimeTypeByFileExtension(_ ext: String) -> String {
|
||||
return TGMimeTypeMap.mimeType(forExtension: ext) ?? "application/binary"
|
||||
}
|
||||
|
||||
public func configureLegacyAssetPicker(_ controller: TGMediaAssetsController, context: AccountContext, peer: Peer, captionsEnabled: Bool = true, storeCreatedAssets: Bool = true, showFileTooltip: Bool = false, initialCaption: String, presentWebSearch: (() -> Void)?, presentSelectionLimitExceeded: @escaping () -> Void, presentScheduleController: @escaping (@escaping (Int32) -> Void) -> Void) {
|
||||
public func configureLegacyAssetPicker(_ controller: TGMediaAssetsController, context: AccountContext, peer: Peer, captionsEnabled: Bool = true, storeCreatedAssets: Bool = true, showFileTooltip: Bool = false, initialCaption: String, hasSchedule: Bool, presentWebSearch: (() -> Void)?, presentSelectionLimitExceeded: @escaping () -> Void, presentSchedulePicker: @escaping (@escaping (Int32) -> Void) -> Void) {
|
||||
let isSecretChat = peer.id.namespace == Namespaces.Peer.SecretChat
|
||||
|
||||
controller.captionsEnabled = captionsEnabled
|
||||
@ -25,13 +25,13 @@ public func configureLegacyAssetPicker(_ controller: TGMediaAssetsController, co
|
||||
controller.suggestionContext = legacySuggestionContext(account: context.account, peerId: peer.id)
|
||||
if peer.id != context.account.peerId {
|
||||
if peer is TelegramUser {
|
||||
controller.hasTimer = true
|
||||
controller.hasTimer = !hasSchedule
|
||||
}
|
||||
controller.hasSilentPosting = !isSecretChat
|
||||
}
|
||||
controller.hasSchedule = !isSecretChat
|
||||
controller.hasSchedule = hasSchedule
|
||||
controller.presentScheduleController = { done in
|
||||
presentScheduleController { time in
|
||||
presentSchedulePicker { time in
|
||||
done?(time)
|
||||
}
|
||||
}
|
||||
|
@ -35,6 +35,7 @@ private final class ProxySettingsControllerArguments {
|
||||
private enum ProxySettingsControllerSection: Int32 {
|
||||
case enabled
|
||||
case servers
|
||||
case share
|
||||
case calls
|
||||
}
|
||||
|
||||
@ -68,8 +69,10 @@ private enum ProxySettingsControllerEntry: ItemListNodeEntry {
|
||||
switch self {
|
||||
case .enabled:
|
||||
return ProxySettingsControllerSection.enabled.rawValue
|
||||
case .serversHeader, .addServer, .server, .shareProxyList:
|
||||
case .serversHeader, .addServer, .server:
|
||||
return ProxySettingsControllerSection.servers.rawValue
|
||||
case .shareProxyList:
|
||||
return ProxySettingsControllerSection.share.rawValue
|
||||
case .useForCalls, .useForCallsInfo:
|
||||
return ProxySettingsControllerSection.calls.rawValue
|
||||
}
|
||||
|
@ -1230,10 +1230,11 @@ public func settingsController(context: AccountContext, accountManager: AccountM
|
||||
} else {
|
||||
return Signal { subscriber in
|
||||
let size = CGSize(width: 31.0, height: 31.0)
|
||||
let inset: CGFloat = 3.0
|
||||
let image = generateImage(size, rotatedContext: { size, context in
|
||||
context.clear(CGRect(origin: CGPoint(), size: size))
|
||||
context.translateBy(x: 3.0, y: 3.0)
|
||||
drawPeerAvatarLetters(context: context, size: size, font: avatarFont, letters: primary.1.displayLetters, accountPeerId: primary.1.id, peerId: primary.1.id)
|
||||
context.translateBy(x: inset, y: inset)
|
||||
drawPeerAvatarLetters(context: context, size: CGSize(width: size.width - inset * 2.0, height: size.height - inset * 2.0), font: avatarFont, letters: primary.1.displayLetters, accountPeerId: primary.1.id, peerId: primary.1.id)
|
||||
})?.withRenderingMode(.alwaysOriginal)
|
||||
subscriber.putNext(image)
|
||||
subscriber.putCompletion()
|
||||
|
@ -919,9 +919,9 @@ public final class AccountViewTracker {
|
||||
}
|
||||
}
|
||||
|
||||
public func scheduledMessagesViewForLocation(_ chatLocation: ChatLocation) -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> {
|
||||
public func scheduledMessagesViewForLocation(_ chatLocation: ChatLocation, additionalData: [AdditionalMessageHistoryViewData] = []) -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> {
|
||||
if let account = self.account {
|
||||
let signal = account.postbox.aroundMessageHistoryViewForLocation(chatLocation, anchor: .upperBound, count: 200, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: [], tagMask: nil, namespaces: .just(Namespaces.Message.allScheduled), orderStatistics: [], additionalData: [])
|
||||
let signal = account.postbox.aroundMessageHistoryViewForLocation(chatLocation, anchor: .upperBound, count: 200, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: [], tagMask: nil, namespaces: .just(Namespaces.Message.allScheduled), orderStatistics: [], additionalData: additionalData)
|
||||
return withState(signal, { [weak self] () -> Int32 in
|
||||
if let strongSelf = self {
|
||||
return OSAtomicIncrement32(&strongSelf.nextViewId)
|
||||
|
@ -632,7 +632,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
return false
|
||||
}
|
||||
|
||||
if let _ = strongSelf.presentationInterfaceState.slowmodeState {
|
||||
if let _ = strongSelf.presentationInterfaceState.slowmodeState, !strongSelf.presentationInterfaceState.isScheduledMessages {
|
||||
strongSelf.interfaceInteraction?.displaySlowmodeTooltip(sourceNode, sourceRect)
|
||||
return false
|
||||
}
|
||||
@ -663,7 +663,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
return true
|
||||
}, sendGif: { [weak self] fileReference, sourceNode, sourceRect in
|
||||
if let strongSelf = self {
|
||||
if let _ = strongSelf.presentationInterfaceState.slowmodeState {
|
||||
if let _ = strongSelf.presentationInterfaceState.slowmodeState, !strongSelf.presentationInterfaceState.isScheduledMessages {
|
||||
strongSelf.interfaceInteraction?.displaySlowmodeTooltip(sourceNode, sourceRect)
|
||||
return false
|
||||
}
|
||||
@ -1342,45 +1342,83 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
let _ = (strongSelf.context.account.postbox.transaction { transaction -> [Message] in
|
||||
return transaction.getMessageFailedGroup(id) ?? []
|
||||
} |> deliverOnMainQueue).start(next: { messages in
|
||||
guard let strongSelf = self, !messages.isEmpty else {
|
||||
return
|
||||
}
|
||||
let actionSheet = ActionSheetController(presentationTheme: strongSelf.presentationData.theme)
|
||||
var items: [ActionSheetItem] = []
|
||||
items.append(ActionSheetButtonItem(title: strongSelf.presentationData.strings.Conversation_MessageDialogRetry, color: .accent, action: { [weak actionSheet] in
|
||||
actionSheet?.dismissAnimated()
|
||||
guard let strongSelf = self else {
|
||||
if id.namespace == Namespaces.Message.ScheduledCloud {
|
||||
let _ = (strongSelf.context.account.postbox.transaction { transaction -> [Message] in
|
||||
return transaction.getMessageGroup(id) ?? []
|
||||
} |> deliverOnMainQueue).start(next: { messages in
|
||||
guard let strongSelf = self, let message = messages.filter({ $0.id == id }).first else {
|
||||
return
|
||||
}
|
||||
let _ = resendMessages(account: strongSelf.context.account, messageIds: [id]).start()
|
||||
}))
|
||||
if messages.count != 1 {
|
||||
items.append(ActionSheetButtonItem(title: strongSelf.presentationData.strings.Conversation_MessageDialogRetryAll(messages.count).0, color: .accent, action: { [weak actionSheet] in
|
||||
actionSheet?.dismissAnimated()
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
|
||||
var actions: [ContextMenuItem] = []
|
||||
actions.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.ScheduledMessages_SendNow, icon: { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Resend"), color: theme.actionSheet.primaryTextColor)
|
||||
}, action: { [weak self] _, f in
|
||||
if let strongSelf = self {
|
||||
strongSelf.controllerInteraction?.sendScheduledMessagesNow(messages.map { $0.id })
|
||||
}
|
||||
let _ = resendMessages(account: strongSelf.context.account, messageIds: messages.map({ $0.id })).start()
|
||||
}))
|
||||
}
|
||||
items.append(ActionSheetButtonItem(title: strongSelf.presentationData.strings.Conversation_MessageDialogDelete, color: .destructive, action: { [weak actionSheet] in
|
||||
actionSheet?.dismissAnimated()
|
||||
guard let strongSelf = self else {
|
||||
f(.dismissWithoutContent)
|
||||
})))
|
||||
actions.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.ScheduledMessages_EditTime, icon: { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Schedule"), color: theme.actionSheet.primaryTextColor)
|
||||
}, action: { [weak self] _, f in
|
||||
if let strongSelf = self {
|
||||
strongSelf.controllerInteraction?.editScheduledMessagesTime(messages.map { $0.id })
|
||||
}
|
||||
f(.dismissWithoutContent)
|
||||
})))
|
||||
actions.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.Conversation_ContextMenuDelete, textColor: .destructive, icon: { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Delete"), color: theme.actionSheet.destructiveActionTextColor)
|
||||
}, action: { [weak self] controller, f in
|
||||
if let strongSelf = self {
|
||||
strongSelf.interfaceInteraction?.deleteMessages(messages, controller, f)
|
||||
}
|
||||
})))
|
||||
|
||||
let controller = ContextController(account: strongSelf.context.account, theme: strongSelf.presentationData.theme, strings: strongSelf.presentationData.strings, source: ChatMessageContextControllerContentSource(chatNode: strongSelf.chatDisplayNode, message: message), items: actions, reactionItems: [], recognizer: nil)
|
||||
strongSelf.currentContextController = controller
|
||||
strongSelf.window?.presentInGlobalOverlay(controller)
|
||||
})
|
||||
} else {
|
||||
let _ = (strongSelf.context.account.postbox.transaction { transaction -> [Message] in
|
||||
return transaction.getMessageFailedGroup(id) ?? []
|
||||
} |> deliverOnMainQueue).start(next: { messages in
|
||||
guard let strongSelf = self, let message = messages.filter({ $0.id == id }).first else {
|
||||
return
|
||||
}
|
||||
let _ = deleteMessagesInteractively(postbox: strongSelf.context.account.postbox, messageIds: [id], type: .forLocalPeer).start()
|
||||
}))
|
||||
actionSheet.setItemGroups([ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [
|
||||
ActionSheetButtonItem(title: strongSelf.presentationData.strings.Common_Cancel, color: .accent, action: { [weak actionSheet] in
|
||||
actionSheet?.dismissAnimated()
|
||||
})
|
||||
])])
|
||||
strongSelf.chatDisplayNode.dismissInput()
|
||||
strongSelf.present(actionSheet, in: .window(.root))
|
||||
})
|
||||
|
||||
var actions: [ContextMenuItem] = []
|
||||
actions.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.Conversation_MessageDialogRetry, icon: { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Resend"), color: theme.actionSheet.primaryTextColor)
|
||||
}, action: { [weak self] _, f in
|
||||
if let strongSelf = self {
|
||||
let _ = resendMessages(account: strongSelf.context.account, messageIds: [id]).start()
|
||||
}
|
||||
f(.dismissWithoutContent)
|
||||
})))
|
||||
if messages.count != 1 {
|
||||
actions.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.Conversation_MessageDialogRetryAll(messages.count).0, icon: { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Resend"), color: theme.actionSheet.primaryTextColor)
|
||||
}, action: { [weak self] _, f in
|
||||
if let strongSelf = self {
|
||||
let _ = resendMessages(account: strongSelf.context.account, messageIds: messages.map({ $0.id })).start()
|
||||
}
|
||||
f(.dismissWithoutContent)
|
||||
})))
|
||||
}
|
||||
actions.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.Conversation_ContextMenuDelete, textColor: .destructive, icon: { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Delete"), color: theme.actionSheet.destructiveActionTextColor)
|
||||
}, action: { [weak self] controller, f in
|
||||
if let strongSelf = self {
|
||||
let _ = deleteMessagesInteractively(postbox: strongSelf.context.account.postbox, messageIds: [id], type: .forLocalPeer).start()
|
||||
}
|
||||
})))
|
||||
|
||||
let controller = ContextController(account: strongSelf.context.account, theme: strongSelf.presentationData.theme, strings: strongSelf.presentationData.strings, source: ChatMessageContextControllerContentSource(chatNode: strongSelf.chatDisplayNode, message: message), items: actions, reactionItems: [], recognizer: nil)
|
||||
strongSelf.currentContextController = controller
|
||||
strongSelf.window?.presentInGlobalOverlay(controller)
|
||||
})
|
||||
}
|
||||
}, addContact: { [weak self] phoneNumber in
|
||||
if let strongSelf = self {
|
||||
strongSelf.context.sharedContext.openAddContact(context: strongSelf.context, firstName: "", lastName: "", phoneNumber: phoneNumber, label: defaultContactLabel, present: { [weak self] controller, arguments in
|
||||
@ -1488,14 +1526,15 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
}
|
||||
}
|
||||
}, scheduleCurrentMessage: { [weak self] in
|
||||
if let strongSelf = self {
|
||||
if let strongSelf = self, let peer = strongSelf.presentationInterfaceState.renderedPeer?.peer {
|
||||
let mode: ChatScheduleTimeControllerMode
|
||||
if case let .peer(peerId) = strongSelf.presentationInterfaceState.chatLocation, peerId == strongSelf.context.account.peerId {
|
||||
if peer.id == strongSelf.context.account.peerId {
|
||||
mode = .reminders
|
||||
} else {
|
||||
mode = .scheduledMessages
|
||||
}
|
||||
let controller = ChatScheduleTimeController(context: strongSelf.context, mode: mode, completion: { [weak self] scheduleTime in
|
||||
|
||||
let controller = ChatScheduleTimeController(context: strongSelf.context, mode: mode, minimalTime: strongSelf.presentationInterfaceState.slowmodeState?.timeout, completion: { [weak self] scheduleTime in
|
||||
if let strongSelf = self {
|
||||
strongSelf.chatDisplayNode.sendCurrentMessage(scheduleTime: scheduleTime)
|
||||
if !strongSelf.presentationInterfaceState.isScheduledMessages {
|
||||
@ -1509,12 +1548,19 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
}
|
||||
}, sendScheduledMessagesNow: { [weak self] messageIds in
|
||||
if let strongSelf = self {
|
||||
let _ = sendScheduledMessageNowInteractively(postbox: strongSelf.context.account.postbox, messageId: messageIds.first!).start()
|
||||
if let _ = strongSelf.presentationInterfaceState.slowmodeState {
|
||||
if let rect = strongSelf.chatDisplayNode.frameForInputActionButton() {
|
||||
strongSelf.interfaceInteraction?.displaySlowmodeTooltip(strongSelf.chatDisplayNode, rect)
|
||||
}
|
||||
return
|
||||
} else {
|
||||
let _ = sendScheduledMessageNowInteractively(postbox: strongSelf.context.account.postbox, messageId: messageIds.first!).start()
|
||||
}
|
||||
}
|
||||
}, editScheduledMessagesTime: { [weak self] messageIds in
|
||||
if let strongSelf = self, let messageId = messageIds.first {
|
||||
if let strongSelf = self, let messageId = messageIds.first, let peer = strongSelf.presentationInterfaceState.renderedPeer?.peer {
|
||||
let mode: ChatScheduleTimeControllerMode
|
||||
if case let .peer(peerId) = strongSelf.presentationInterfaceState.chatLocation, peerId == strongSelf.context.account.peerId {
|
||||
if peer.id == strongSelf.context.account.peerId {
|
||||
mode = .reminders
|
||||
} else {
|
||||
mode = .scheduledMessages
|
||||
@ -1526,7 +1572,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
guard let strongSelf = self, let message = message else {
|
||||
return
|
||||
}
|
||||
let controller = ChatScheduleTimeController(context: strongSelf.context, mode: mode, currentTime: message.timestamp, completion: { [weak self] scheduleTime in
|
||||
let controller = ChatScheduleTimeController(context: strongSelf.context, mode: mode, currentTime: message.timestamp, minimalTime: strongSelf.presentationInterfaceState.slowmodeState?.timeout, completion: { [weak self] scheduleTime in
|
||||
if let strongSelf = self {
|
||||
var entities: TextEntitiesMessageAttribute?
|
||||
for attribute in message.attributes {
|
||||
@ -2253,7 +2299,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
var slowmodeState: ChatSlowmodeState?
|
||||
if let cachedData = combinedInitialData.cachedData as? CachedChannelData {
|
||||
pinnedMessageId = cachedData.pinnedMessageId
|
||||
if let channel = combinedInitialData.initialData?.peer as? TelegramChannel, channel.isRestrictedBySlowmode, let timeout = cachedData.slowModeTimeout, !strongSelf.presentationInterfaceState.isScheduledMessages {
|
||||
if let channel = combinedInitialData.initialData?.peer as? TelegramChannel, channel.isRestrictedBySlowmode, let timeout = cachedData.slowModeTimeout {
|
||||
if let slowmodeUntilTimestamp = calculateSlowmodeActiveUntilTimestamp(account: strongSelf.context.account, untilTimestamp: cachedData.slowModeValidUntilTimestamp) {
|
||||
slowmodeState = ChatSlowmodeState(timeout: timeout, variant: .timestamp(slowmodeUntilTimestamp))
|
||||
}
|
||||
@ -2659,7 +2705,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
if strongSelf.presentationInterfaceState.interfaceState.editMessage == nil, let _ = strongSelf.presentationInterfaceState.slowmodeState {
|
||||
if strongSelf.presentationInterfaceState.interfaceState.editMessage == nil, let _ = strongSelf.presentationInterfaceState.slowmodeState, !strongSelf.presentationInterfaceState.isScheduledMessages {
|
||||
if let rect = strongSelf.chatDisplayNode.frameForAttachmentButton() {
|
||||
strongSelf.interfaceInteraction?.displaySlowmodeTooltip(strongSelf.chatDisplayNode, rect)
|
||||
}
|
||||
@ -3168,7 +3214,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
guard let strongSelf = self else {
|
||||
return false
|
||||
}
|
||||
if let _ = strongSelf.presentationInterfaceState.slowmodeState {
|
||||
if let _ = strongSelf.presentationInterfaceState.slowmodeState, !strongSelf.presentationInterfaceState.isScheduledMessages {
|
||||
strongSelf.interfaceInteraction?.displaySlowmodeTooltip(node, rect)
|
||||
return false
|
||||
}
|
||||
@ -4921,7 +4967,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
}
|
||||
return result
|
||||
}
|
||||
let controller = legacyAttachmentMenu(context: strongSelf.context, peer: peer, editMediaOptions: menuEditMediaOptions, saveEditedPhotos: settings.storeEditedPhotos, allowGrouping: true, theme: strongSelf.presentationData.theme, strings: strongSelf.presentationData.strings, parentController: legacyController, recentlyUsedInlineBots: strongSelf.recentlyUsedInlineBotsValue, initialCaption: inputText.string, openGallery: {
|
||||
|
||||
let controller = legacyAttachmentMenu(context: strongSelf.context, peer: peer, editMediaOptions: menuEditMediaOptions, saveEditedPhotos: settings.storeEditedPhotos, allowGrouping: true, hasSchedule: !strongSelf.presentationInterfaceState.isScheduledMessages && peer.id.namespace != Namespaces.Peer.SecretChat, theme: strongSelf.presentationData.theme, strings: strongSelf.presentationData.strings, parentController: legacyController, recentlyUsedInlineBots: strongSelf.recentlyUsedInlineBotsValue, initialCaption: inputText.string, openGallery: {
|
||||
self?.presentMediaPicker(fileMode: false, editingMedia: editMediaOptions != nil, completion: { signals, silentPosting, scheduleTime in
|
||||
if !inputText.string.isEmpty {
|
||||
//strongSelf.clearInputText()
|
||||
@ -4934,7 +4981,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
})
|
||||
}, openCamera: { [weak self] cameraView, menuController in
|
||||
if let strongSelf = self, let peer = strongSelf.presentationInterfaceState.renderedPeer?.peer {
|
||||
presentedLegacyCamera(context: strongSelf.context, peer: peer, cameraView: cameraView, menuController: menuController, parentController: strongSelf, editingMedia: editMediaOptions != nil, saveCapturedPhotos: settings.storeEditedPhotos, mediaGrouping: true, initialCaption: inputText.string, sendMessagesWithSignals: { [weak self] signals in
|
||||
presentedLegacyCamera(context: strongSelf.context, peer: peer, cameraView: cameraView, menuController: menuController, parentController: strongSelf, editingMedia: editMediaOptions != nil, saveCapturedPhotos: settings.storeEditedPhotos, mediaGrouping: true, initialCaption: inputText.string, hasSchedule: !strongSelf.presentationInterfaceState.isScheduledMessages && peer.id.namespace != Namespaces.Peer.SecretChat, sendMessagesWithSignals: { [weak self] signals in
|
||||
if let strongSelf = self {
|
||||
if editMediaOptions != nil {
|
||||
strongSelf.editMessageMediaWithLegacySignals(signals!)
|
||||
@ -4949,17 +4996,17 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
if let strongSelf = self, let (host, port, username, password, secret) = parseProxyUrl(code) {
|
||||
strongSelf.openResolved(ResolvedUrl.proxy(host: host, port: port, username: username, password: password, secret: secret))
|
||||
}
|
||||
}, presentScheduleController: { [weak self] done in
|
||||
}, presentSchedulePicker: { [weak self] done in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
let mode: ChatScheduleTimeControllerMode
|
||||
if case let .peer(peerId) = strongSelf.presentationInterfaceState.chatLocation, peerId == strongSelf.context.account.peerId {
|
||||
if peer.id == strongSelf.context.account.peerId {
|
||||
mode = .reminders
|
||||
} else {
|
||||
mode = .scheduledMessages
|
||||
}
|
||||
let controller = ChatScheduleTimeController(context: strongSelf.context, mode: mode, completion: { [weak self] time in
|
||||
let controller = ChatScheduleTimeController(context: strongSelf.context, mode: mode, minimalTime: strongSelf.presentationInterfaceState.slowmodeState?.timeout, completion: { [weak self] time in
|
||||
if let strongSelf = self {
|
||||
done(time)
|
||||
if !strongSelf.presentationInterfaceState.isScheduledMessages {
|
||||
@ -4991,17 +5038,17 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
return
|
||||
}
|
||||
strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationTheme: strongSelf.presentationData.theme), title: nil, text: strongSelf.presentationData.strings.Chat_AttachmentMultipleFilesDisabled, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root))
|
||||
}, presentScheduleController: { [weak self] done in
|
||||
guard let strongSelf = self else {
|
||||
}, presentSchedulePicker: { [weak self] done in
|
||||
guard let strongSelf = self, let peer = strongSelf.presentationInterfaceState.renderedPeer?.peer else {
|
||||
return
|
||||
}
|
||||
let mode: ChatScheduleTimeControllerMode
|
||||
if case let .peer(peerId) = strongSelf.presentationInterfaceState.chatLocation, peerId == strongSelf.context.account.peerId {
|
||||
if peer.id == strongSelf.context.account.peerId {
|
||||
mode = .reminders
|
||||
} else {
|
||||
mode = .scheduledMessages
|
||||
}
|
||||
let controller = ChatScheduleTimeController(context: strongSelf.context, mode: mode, completion: { [weak self] time in
|
||||
let controller = ChatScheduleTimeController(context: strongSelf.context, mode: mode, minimalTime: strongSelf.presentationInterfaceState.slowmodeState?.timeout, completion: { [weak self] time in
|
||||
if let strongSelf = self {
|
||||
done(time)
|
||||
if !strongSelf.presentationInterfaceState.isScheduledMessages {
|
||||
@ -5153,7 +5200,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
legacyController.bind(controller: controller)
|
||||
legacyController.deferScreenEdgeGestures = [.top]
|
||||
|
||||
configureLegacyAssetPicker(controller, context: strongSelf.context, peer: peer, initialCaption: inputText.string, presentWebSearch: { [weak self, weak legacyController] in
|
||||
configureLegacyAssetPicker(controller, context: strongSelf.context, peer: peer, initialCaption: inputText.string, hasSchedule: !strongSelf.presentationInterfaceState.isScheduledMessages && peer.id.namespace != Namespaces.Peer.SecretChat, presentWebSearch: { [weak self, weak legacyController] in
|
||||
if let strongSelf = self {
|
||||
let controller = WebSearchController(context: strongSelf.context, peer: peer, configuration: searchBotsConfiguration, mode: .media(completion: { results, selectionState, editingState, silentPosting in
|
||||
if let legacyController = legacyController {
|
||||
@ -5176,17 +5223,17 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
return
|
||||
}
|
||||
strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationTheme: strongSelf.presentationData.theme), title: nil, text: strongSelf.presentationData.strings.Chat_AttachmentLimitReached, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root))
|
||||
}, presentScheduleController: { [weak self] done in
|
||||
guard let strongSelf = self else {
|
||||
}, presentSchedulePicker: { [weak self] done in
|
||||
guard let strongSelf = self, let peer = strongSelf.presentationInterfaceState.renderedPeer?.peer else {
|
||||
return
|
||||
}
|
||||
let mode: ChatScheduleTimeControllerMode
|
||||
if case let .peer(peerId) = strongSelf.presentationInterfaceState.chatLocation, peerId == strongSelf.context.account.peerId {
|
||||
if peer.id == strongSelf.context.account.peerId {
|
||||
mode = .reminders
|
||||
} else {
|
||||
mode = .scheduledMessages
|
||||
}
|
||||
let controller = ChatScheduleTimeController(context: strongSelf.context, mode: mode, completion: { [weak self] time in
|
||||
let controller = ChatScheduleTimeController(context: strongSelf.context, mode: mode, minimalTime: strongSelf.presentationInterfaceState.slowmodeState?.timeout, completion: { [weak self] time in
|
||||
if let strongSelf = self {
|
||||
done(time)
|
||||
if !strongSelf.presentationInterfaceState.isScheduledMessages {
|
||||
@ -5245,9 +5292,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private func presentMapPicker(editingMessage: Bool) {
|
||||
guard let peer = self.presentationInterfaceState.renderedPeer?.peer else {
|
||||
return
|
||||
@ -5468,7 +5513,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
} else {
|
||||
mode = .scheduledMessages
|
||||
}
|
||||
let controller = ChatScheduleTimeController(context: self.context, mode: mode, dismissByTapOutside: false, completion: { [weak self] time in
|
||||
let controller = ChatScheduleTimeController(context: self.context, mode: mode, minimalTime: self.presentationInterfaceState.slowmodeState?.timeout, dismissByTapOutside: false, completion: { [weak self] time in
|
||||
if let strongSelf = self {
|
||||
strongSelf.sendMessages(strongSelf.transformEnqueueMessages(messages, silentPosting: false, scheduleTime: time), commit: true)
|
||||
}
|
||||
@ -5640,7 +5685,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
self.recorderFeedback?.prepareImpact(.light)
|
||||
}
|
||||
|
||||
self.videoRecorder.set(.single(legacyInstantVideoController(theme: self.presentationData.theme, panelFrame: currentInputPanelFrame, context: self.context, peerId: peerId, slowmodeState: self.presentationInterfaceState.slowmodeState, send: { [weak self] message in
|
||||
self.videoRecorder.set(.single(legacyInstantVideoController(theme: self.presentationData.theme, panelFrame: currentInputPanelFrame, context: self.context, peerId: peerId, slowmodeState: !self.presentationInterfaceState.isScheduledMessages ? self.presentationInterfaceState.slowmodeState : nil, send: { [weak self] message in
|
||||
if let strongSelf = self {
|
||||
let replyMessageId = strongSelf.presentationInterfaceState.interfaceState.replyMessageId
|
||||
strongSelf.chatDisplayNode.setupSendActionOnViewUpdate({
|
||||
@ -5662,7 +5707,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
|
||||
private func dismissMediaRecorder(_ action: ChatFinishMediaRecordingAction) {
|
||||
var updatedAction = action
|
||||
if let _ = self.presentationInterfaceState.slowmodeState {
|
||||
if let _ = self.presentationInterfaceState.slowmodeState, !self.presentationInterfaceState.isScheduledMessages {
|
||||
updatedAction = .preview
|
||||
}
|
||||
|
||||
@ -5786,7 +5831,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
|
||||
private func sendMediaRecording() {
|
||||
if let recordedMediaPreview = self.presentationInterfaceState.recordedMediaPreview {
|
||||
if let _ = self.presentationInterfaceState.slowmodeState {
|
||||
if let _ = self.presentationInterfaceState.slowmodeState, !self.presentationInterfaceState.isScheduledMessages {
|
||||
if let rect = self.chatDisplayNode.frameForInputActionButton() {
|
||||
self.interfaceInteraction?.displaySlowmodeTooltip(self.chatDisplayNode, rect)
|
||||
}
|
||||
@ -7157,7 +7202,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
if options.contains(.deleteLocally) {
|
||||
var localOptionText = self.presentationData.strings.Conversation_DeleteMessagesForMe
|
||||
if self.presentationInterfaceState.isScheduledMessages {
|
||||
localOptionText = self.presentationData.strings.ScheduledMessages_Delete
|
||||
localOptionText = messageIds.count > 1 ? self.presentationData.strings.ScheduledMessages_DeleteMany : self.presentationData.strings.ScheduledMessages_Delete
|
||||
} else {
|
||||
if options.contains(.unsendPersonal) {
|
||||
localOptionText = self.presentationData.strings.Chat_DeleteMessagesConfirmation(Int32(messageIds.count))
|
||||
|
@ -2041,7 +2041,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
if let _ = effectivePresentationInterfaceState.interfaceState.editMessage {
|
||||
self.interfaceInteraction?.editMessage()
|
||||
} else {
|
||||
if let _ = effectivePresentationInterfaceState.slowmodeState {
|
||||
if let _ = effectivePresentationInterfaceState.slowmodeState, !effectivePresentationInterfaceState.isScheduledMessages && scheduleTime == nil {
|
||||
if let rect = self.frameForInputActionButton() {
|
||||
self.interfaceInteraction?.displaySlowmodeTooltip(self, rect)
|
||||
}
|
||||
|
@ -490,6 +490,11 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
||||
|
||||
let fixedCombinedReadStates = Atomic<MessageHistoryViewReadState?>(value: nil)
|
||||
|
||||
var scheduled = false
|
||||
if let subject = subject, case .scheduledMessages = subject {
|
||||
scheduled = true
|
||||
}
|
||||
|
||||
var additionalData: [AdditionalMessageHistoryViewData] = []
|
||||
if case let .peer(peerId) = chatLocation {
|
||||
additionalData.append(.cachedPeerData(peerId))
|
||||
@ -503,13 +508,10 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
||||
additionalData.append(.peerIsContact(peerId))
|
||||
}
|
||||
}
|
||||
additionalData.append(.totalUnreadState)
|
||||
|
||||
var scheduled = false
|
||||
if let subject = subject, case .scheduledMessages = subject {
|
||||
scheduled = true
|
||||
if !scheduled {
|
||||
additionalData.append(.totalUnreadState)
|
||||
}
|
||||
|
||||
|
||||
let currentViewVersion = Atomic<Int?>(value: nil)
|
||||
|
||||
let historyViewUpdate = self.chatHistoryLocationPromise.get()
|
||||
|
@ -33,7 +33,7 @@ func chatHistoryViewForLocation(_ location: ChatHistoryLocationInput, account: A
|
||||
let directionHint: ListViewScrollToItemDirectionHint = sourceIndex > index ? .Down : .Up
|
||||
chatScrollPosition = .index(index: index, position: position, directionHint: directionHint, animated: animated)
|
||||
}
|
||||
return account.viewTracker.scheduledMessagesViewForLocation(chatLocation)
|
||||
return account.viewTracker.scheduledMessagesViewForLocation(chatLocation, additionalData: additionalData)
|
||||
|> map { view, updateType, initialData -> ChatHistoryViewUpdate in
|
||||
let (cachedData, cachedDataMessages, readStateData) = extractAdditionalData(view: view, chatLocation: chatLocation)
|
||||
|
||||
|
@ -149,7 +149,7 @@ final class ChatRecordingPreviewInputPanelNode: ChatInputPanelNode {
|
||||
transition.updateFrame(node: self.deleteButton, frame: CGRect(origin: CGPoint(x: leftInset, y: -1.0), size: CGSize(width: 48.0, height: panelHeight)))
|
||||
transition.updateFrame(node: self.sendButton, frame: CGRect(origin: CGPoint(x: width - rightInset - 43.0 - UIScreenPixel, y: -UIScreenPixel), size: CGSize(width: 44.0, height: panelHeight)))
|
||||
|
||||
if let slowmodeState = interfaceState.slowmodeState {
|
||||
if let slowmodeState = interfaceState.slowmodeState, !interfaceState.isScheduledMessages {
|
||||
let sendButtonRadialStatusNode: ChatSendButtonRadialStatusNode
|
||||
if let current = self.sendButtonRadialStatusNode {
|
||||
sendButtonRadialStatusNode = current
|
||||
|
@ -22,15 +22,17 @@ final class ChatScheduleTimeController: ViewController {
|
||||
private let context: AccountContext
|
||||
private let mode: ChatScheduleTimeControllerMode
|
||||
private let currentTime: Int32?
|
||||
private let minimalTime: Int32?
|
||||
private let dismissByTapOutside: Bool
|
||||
private let completion: (Int32) -> Void
|
||||
|
||||
private var presentationDataDisposable: Disposable?
|
||||
|
||||
init(context: AccountContext, mode: ChatScheduleTimeControllerMode, currentTime: Int32? = nil, dismissByTapOutside: Bool = true, completion: @escaping (Int32) -> Void) {
|
||||
init(context: AccountContext, mode: ChatScheduleTimeControllerMode, currentTime: Int32? = nil, minimalTime: Int32? = nil, dismissByTapOutside: Bool = true, completion: @escaping (Int32) -> Void) {
|
||||
self.context = context
|
||||
self.mode = mode
|
||||
self.currentTime = currentTime
|
||||
self.minimalTime = minimalTime
|
||||
self.dismissByTapOutside = dismissByTapOutside
|
||||
self.completion = completion
|
||||
|
||||
@ -55,7 +57,7 @@ final class ChatScheduleTimeController: ViewController {
|
||||
}
|
||||
|
||||
override public func loadDisplayNode() {
|
||||
self.displayNode = ChatScheduleTimeControllerNode(context: self.context, mode: self.mode, currentTime: self.currentTime, dismissByTapOutside: self.dismissByTapOutside)
|
||||
self.displayNode = ChatScheduleTimeControllerNode(context: self.context, mode: self.mode, currentTime: self.currentTime, minimalTime: self.minimalTime, dismissByTapOutside: self.dismissByTapOutside)
|
||||
self.controllerNode.completion = { [weak self] time in
|
||||
self?.completion(time + 5)
|
||||
self?.dismiss()
|
||||
|
@ -15,6 +15,7 @@ class ChatScheduleTimeControllerNode: ViewControllerTracingNode, UIScrollViewDel
|
||||
private let mode: ChatScheduleTimeControllerMode
|
||||
private var presentationData: PresentationData
|
||||
private let dismissByTapOutside: Bool
|
||||
private let minimalTime: Int32?
|
||||
|
||||
private let dimNode: ASDisplayNode
|
||||
private let wrappingScrollNode: ASScrollNode
|
||||
@ -33,11 +34,12 @@ class ChatScheduleTimeControllerNode: ViewControllerTracingNode, UIScrollViewDel
|
||||
var dismiss: (() -> Void)?
|
||||
var cancel: (() -> Void)?
|
||||
|
||||
init(context: AccountContext, mode: ChatScheduleTimeControllerMode, currentTime: Int32?, dismissByTapOutside: Bool) {
|
||||
init(context: AccountContext, mode: ChatScheduleTimeControllerMode, currentTime: Int32?, minimalTime: Int32?, dismissByTapOutside: Bool) {
|
||||
self.context = context
|
||||
self.mode = mode
|
||||
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
self.dismissByTapOutside = dismissByTapOutside
|
||||
self.minimalTime = minimalTime
|
||||
|
||||
self.wrappingScrollNode = ASScrollNode()
|
||||
self.wrappingScrollNode.view.alwaysBounceVertical = true
|
||||
@ -131,6 +133,17 @@ class ChatScheduleTimeControllerNode: ViewControllerTracingNode, UIScrollViewDel
|
||||
self.titleNode.attributedText = NSAttributedString(string: self.titleNode.attributedText?.string ?? "", font: Font.bold(17.0), textColor: self.presentationData.theme.actionSheet.primaryTextColor)
|
||||
self.pickerView.setValue(self.presentationData.theme.actionSheet.primaryTextColor, forKey: "textColor")
|
||||
|
||||
func updatePickerViewSubviews(_ subviews: [UIView]) {
|
||||
for view in subviews {
|
||||
if let label = view as? UILabel {
|
||||
label.textColor = self.presentationData.theme.actionSheet.primaryTextColor
|
||||
} else {
|
||||
updatePickerViewSubviews(view.subviews)
|
||||
}
|
||||
}
|
||||
}
|
||||
updatePickerViewSubviews(self.pickerView.subviews)
|
||||
|
||||
self.cancelButton.setTitle(self.presentationData.strings.Common_Cancel, with: Font.regular(17.0), with: self.presentationData.theme.actionSheet.controlAccentColor, for: .normal)
|
||||
self.doneButton.updateTheme(self.presentationData.theme)
|
||||
}
|
||||
@ -152,8 +165,9 @@ class ChatScheduleTimeControllerNode: ViewControllerTracingNode, UIScrollViewDel
|
||||
}
|
||||
|
||||
if let next1MinDate = next1MinDate, let next5MinDate = next5MinDate {
|
||||
self.pickerView.minimumDate = next1MinDate
|
||||
if let currentTime = currentTime, Double(currentTime) > currentDate.timeIntervalSince1970 {
|
||||
let minimalTime = self.minimalTime.flatMap(Double.init) ?? 0.0
|
||||
self.pickerView.minimumDate = max(next1MinDate, Date(timeIntervalSince1970: minimalTime))
|
||||
if let currentTime = currentTime, Double(currentTime) > max(currentDate.timeIntervalSince1970, minimalTime) {
|
||||
self.pickerView.date = Date(timeIntervalSince1970: Double(currentTime))
|
||||
} else {
|
||||
self.pickerView.date = next5MinDate
|
||||
|
@ -114,10 +114,10 @@ final class ChatSearchInputPanelNode: ChatInputPanelNode {
|
||||
panelHeight = 45.0
|
||||
}
|
||||
|
||||
transition.updateFrame(node: self.downButton, frame: CGRect(origin: CGPoint(x: leftInset + 12.0, y: 0.0), size: CGSize(width: 40.0, height: panelHeight)))
|
||||
transition.updateFrame(node: self.upButton, frame: CGRect(origin: CGPoint(x: leftInset + 12.0 + 43.0, y: 0.0), size: CGSize(width: 40.0, height: panelHeight)))
|
||||
transition.updateFrame(node: self.calendarButton, frame: CGRect(origin: CGPoint(x: width - rightInset - 60.0, y: 0.0), size: CGSize(width: 60.0, height: panelHeight)))
|
||||
transition.updateFrame(node: self.membersButton, frame: CGRect(origin: CGPoint(x: width - rightInset - 60.0 * 2.0, y: 0.0), size: CGSize(width: 60.0, height: panelHeight)))
|
||||
transition.updateFrame(node: self.downButton, frame: CGRect(origin: CGPoint(x: width - rightInset - 48.0, y: 0.0), size: CGSize(width: 40.0, height: panelHeight)))
|
||||
transition.updateFrame(node: self.upButton, frame: CGRect(origin: CGPoint(x: width - rightInset - 48.0 - 43.0, y: 0.0), size: CGSize(width: 40.0, height: panelHeight)))
|
||||
transition.updateFrame(node: self.calendarButton, frame: CGRect(origin: CGPoint(x: leftInset, y: 0.0), size: CGSize(width: 60.0, height: panelHeight)))
|
||||
transition.updateFrame(node: self.membersButton, frame: CGRect(origin: CGPoint(x: leftInset + 43.0, y: 0.0), size: CGSize(width: 60.0, height: panelHeight)))
|
||||
|
||||
var resultIndex: Int?
|
||||
var resultCount: Int?
|
||||
|
@ -89,7 +89,7 @@ final class ChatTextInputActionButtonsNode: ASDisplayNode {
|
||||
|
||||
transition.updateFrame(layer: self.sendButton.layer, frame: CGRect(origin: CGPoint(), size: size))
|
||||
|
||||
if let slowmodeState = interfaceState.slowmodeState, interfaceState.editMessageState == nil {
|
||||
if let slowmodeState = interfaceState.slowmodeState, !interfaceState.isScheduledMessages && interfaceState.editMessageState == nil {
|
||||
let sendButtonRadialStatusNode: ChatSendButtonRadialStatusNode
|
||||
if let current = self.sendButtonRadialStatusNode {
|
||||
sendButtonRadialStatusNode = current
|
||||
|
@ -654,7 +654,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
|
||||
}
|
||||
}
|
||||
var isSlowmodeActive = false
|
||||
if interfaceState.slowmodeState != nil {
|
||||
if interfaceState.slowmodeState != nil && !interfaceState.isScheduledMessages {
|
||||
isSlowmodeActive = true
|
||||
if !isEditingMedia {
|
||||
isMediaEnabled = false
|
||||
@ -1098,7 +1098,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
if interfaceState.slowmodeState == nil, let contextPlaceholder = interfaceState.inputTextPanelState.contextPlaceholder {
|
||||
if interfaceState.slowmodeState == nil || interfaceState.isScheduledMessages, let contextPlaceholder = interfaceState.inputTextPanelState.contextPlaceholder {
|
||||
let placeholderLayout = TextNode.asyncLayout(self.contextPlaceholderNode)
|
||||
let (placeholderSize, placeholderApply) = placeholderLayout(TextNodeLayoutArguments(attributedString: contextPlaceholder, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: width - leftInset - rightInset - textFieldInsets.left - textFieldInsets.right - self.textInputViewInternalInsets.left - self.textInputViewInternalInsets.right - accessoryButtonsWidth, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
let contextPlaceholderNode = placeholderApply()
|
||||
@ -1123,7 +1123,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
|
||||
self.textPlaceholderNode.alpha = 1.0
|
||||
}
|
||||
|
||||
if let slowmodeState = interfaceState.slowmodeState {
|
||||
if let slowmodeState = interfaceState.slowmodeState, !interfaceState.isScheduledMessages {
|
||||
let slowmodePlaceholderNode: ChatTextInputSlowmodePlaceholderNode
|
||||
if let current = self.slowmodePlaceholderNode {
|
||||
slowmodePlaceholderNode = current
|
||||
@ -1146,7 +1146,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
|
||||
inputHasText = true
|
||||
}
|
||||
|
||||
if (interfaceState.slowmodeState != nil && interfaceState.editMessageState == nil) || interfaceState.inputTextPanelState.contextPlaceholder != nil {
|
||||
if (interfaceState.slowmodeState != nil && !interfaceState.isScheduledMessages && interfaceState.editMessageState == nil) || interfaceState.inputTextPanelState.contextPlaceholder != nil {
|
||||
self.textPlaceholderNode.isHidden = true
|
||||
self.slowmodePlaceholderNode?.isHidden = inputHasText
|
||||
} else {
|
||||
@ -1237,7 +1237,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
|
||||
}
|
||||
|
||||
if let interfaceState = self.presentationInterfaceState {
|
||||
if (interfaceState.slowmodeState != nil && interfaceState.editMessageState == nil) || interfaceState.inputTextPanelState.contextPlaceholder != nil {
|
||||
if (interfaceState.slowmodeState != nil && !interfaceState.isScheduledMessages && interfaceState.editMessageState == nil) || interfaceState.inputTextPanelState.contextPlaceholder != nil {
|
||||
self.textPlaceholderNode.isHidden = true
|
||||
self.slowmodePlaceholderNode?.isHidden = inputHasText
|
||||
} else {
|
||||
|
@ -10,7 +10,7 @@ import ShareController
|
||||
import LegacyUI
|
||||
import LegacyMediaPickerUI
|
||||
|
||||
func presentedLegacyCamera(context: AccountContext, peer: Peer, cameraView: TGAttachmentCameraView?, menuController: TGMenuSheetController?, parentController: ViewController, editingMedia: Bool, saveCapturedPhotos: Bool, mediaGrouping: Bool, initialCaption: String, sendMessagesWithSignals: @escaping ([Any]?) -> Void, recognizedQRCode: @escaping (String) -> Void = { _ in }, presentScheduleController: @escaping (@escaping (Int32) -> Void) -> Void) {
|
||||
func presentedLegacyCamera(context: AccountContext, peer: Peer, cameraView: TGAttachmentCameraView?, menuController: TGMenuSheetController?, parentController: ViewController, editingMedia: Bool, saveCapturedPhotos: Bool, mediaGrouping: Bool, initialCaption: String, hasSchedule: Bool, sendMessagesWithSignals: @escaping ([Any]?) -> Void, recognizedQRCode: @escaping (String) -> Void = { _ in }, presentSchedulePicker: @escaping (@escaping (Int32) -> Void) -> Void) {
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
let legacyController = LegacyController(presentation: .custom, theme: presentationData.theme)
|
||||
legacyController.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .portrait, compactSize: .portrait)
|
||||
@ -61,11 +61,11 @@ func presentedLegacyCamera(context: AccountContext, peer: Peer, cameraView: TGAt
|
||||
controller.recipientName = peer.displayTitle
|
||||
if peer.id != context.account.peerId {
|
||||
if peer is TelegramUser {
|
||||
controller.hasTimer = true
|
||||
controller.hasTimer = !hasSchedule
|
||||
}
|
||||
controller.hasSilentPosting = !isSecretChat
|
||||
}
|
||||
controller.hasSchedule = !isSecretChat
|
||||
controller.hasSchedule = hasSchedule
|
||||
|
||||
let screenSize = parentController.view.bounds.size
|
||||
var startFrame = CGRect(x: 0, y: screenSize.height, width: screenSize.width, height: screenSize.height)
|
||||
|
Loading…
x
Reference in New Issue
Block a user