Fix various send when online cases

This commit is contained in:
Ilya Laktyushin 2019-11-19 07:11:02 +04:00
parent 2b4ade57fb
commit bab231a71f
3 changed files with 118 additions and 92 deletions

View File

@ -31,12 +31,36 @@ private func makeDarkPresentationTheme(accentColor: UIColor, bubbleColors: (UICo
let mainFreeTextColor = accentColor.withMultiplied(hue: 1.019, saturation: 0.097, brightness: 0.56)
var outgoingBubbleFillColor = accentColor.withMultiplied(hue: 1.019, saturation: 0.731, brightness: 0.59)
var outgoingBubbleFillGradientColor = outgoingBubbleFillColor
let outgoingBubbleFillColor: UIColor
let outgoingBubbleFillGradientColor: UIColor
let outgoingBubbleHighlightedFillColor: UIColor
let outgoingScamColor: UIColor
let outgoingPrimaryTextColor: UIColor
let outgoingSecondaryTextColor: UIColor
let outgoingLinkTextColor: UIColor
let outgoingCheckColor: UIColor
if let bubbleColors = bubbleColors {
outgoingBubbleFillColor = bubbleColors.0
outgoingBubbleFillGradientColor = bubbleColors.1 ?? bubbleColors.0
} else {
outgoingBubbleFillGradientColor = accentColor.withMultiplied(hue: 1.019, saturation: 0.731, brightness: 0.59)
outgoingBubbleFillColor = outgoingBubbleFillGradientColor.withMultiplied(hue: 0.966, saturation: 0.61, brightness: 0.98)
}
let outgoingBubbleLightnessColor = outgoingBubbleFillColor.mixedWith(outgoingBubbleFillGradientColor, alpha: 0.5)
if outgoingBubbleLightnessColor.lightness > 0.7 {
outgoingScamColor = UIColor(rgb: 0x000000)
outgoingPrimaryTextColor = UIColor(rgb: 0x000000)
outgoingSecondaryTextColor = UIColor(rgb: 0x000000, alpha: 0.5)
outgoingLinkTextColor = UIColor(rgb: 0x000000)
outgoingCheckColor = UIColor(rgb: 0x000000, alpha: 0.5)
} else {
outgoingScamColor = UIColor(rgb: 0xffffff)
outgoingPrimaryTextColor = UIColor(rgb: 0xffffff)
outgoingSecondaryTextColor = UIColor(rgb: 0xffffff, alpha: 0.5)
outgoingLinkTextColor = UIColor(rgb: 0xffffff)
outgoingCheckColor = UIColor(rgb: 0xffffff, alpha: 0.5)
}
let highlightedIncomingBubbleColor = accentColor.withMultiplied(hue: 1.03, saturation: 0.463, brightness: 0.29)
@ -206,13 +230,13 @@ private func makeDarkPresentationTheme(accentColor: UIColor, bubbleColors: (UICo
let message = PresentationThemeChatMessage(
incoming: PresentationThemePartedColors(bubble: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: mainBackgroundColor, highlightedFill: highlightedIncomingBubbleColor, stroke: mainBackgroundColor), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: mainBackgroundColor, highlightedFill: highlightedIncomingBubbleColor, stroke: mainBackgroundColor)), primaryTextColor: .white, secondaryTextColor: mainSecondaryTextColor.withAlphaComponent(0.5), linkTextColor: accentColor, linkHighlightColor: accentColor.withAlphaComponent(0.5), scamColor: destructiveColor, textHighlightColor: UIColor(rgb: 0xf5c038), accentTextColor: accentColor, accentControlColor: accentColor, mediaActiveControlColor: accentColor, mediaInactiveControlColor: accentColor.withAlphaComponent(0.5), mediaControlInnerBackgroundColor: mainBackgroundColor, pendingActivityColor: mainSecondaryTextColor.withAlphaComponent(0.5), fileTitleColor: accentColor, fileDescriptionColor: mainSecondaryTextColor.withAlphaComponent(0.5), fileDurationColor: mainSecondaryTextColor.withAlphaComponent(0.5), mediaPlaceholderColor: accentColor.withMultiplied(hue: 1.019, saturation: 0.585, brightness: 0.23), polls: PresentationThemeChatBubblePolls(radioButton: accentColor.withMultiplied(hue: 0.995, saturation: 0.317, brightness: 0.51), radioProgress: accentColor, highlight: accentColor.withAlphaComponent(0.12), separator: mainSeparatorColor, bar: accentColor), actionButtonsFillColor: PresentationThemeVariableColor(withWallpaper: additionalBackgroundColor.withAlphaComponent(0.5), withoutWallpaper: additionalBackgroundColor.withAlphaComponent(0.5)), actionButtonsStrokeColor: PresentationThemeVariableColor(color: buttonStrokeColor), actionButtonsTextColor: PresentationThemeVariableColor(color: .white), textSelectionColor: accentColor.withAlphaComponent(0.2), textSelectionKnobColor: accentColor),
outgoing: PresentationThemePartedColors(bubble: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: outgoingBubbleFillColor, gradientFill: outgoingBubbleFillGradientColor, highlightedFill: highlightedOutgoingBubbleColor, stroke: outgoingBubbleFillColor), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: outgoingBubbleFillColor, gradientFill: outgoingBubbleFillGradientColor, highlightedFill: highlightedOutgoingBubbleColor, stroke: outgoingBubbleFillColor)), primaryTextColor: .white, secondaryTextColor: mainSecondaryTextColor.withAlphaComponent(0.5), linkTextColor: accentColor, linkHighlightColor: accentColor.withAlphaComponent(0.5), scamColor: destructiveColor, textHighlightColor: UIColor(rgb: 0xf5c038), accentTextColor: .white, accentControlColor: .white, mediaActiveControlColor: .white, mediaInactiveControlColor: UIColor(rgb: 0xffffff, alpha: 0.5), mediaControlInnerBackgroundColor: outgoingBubbleFillColor, pendingActivityColor: mainSecondaryTextColor.withAlphaComponent(0.5), fileTitleColor: .white, fileDescriptionColor: mainSecondaryTextColor.withAlphaComponent(0.5), fileDurationColor: mainSecondaryTextColor.withAlphaComponent(0.5), mediaPlaceholderColor: accentColor.withMultiplied(hue: 1.019, saturation: 0.804, brightness: 0.51), polls: PresentationThemeChatBubblePolls(radioButton: .white, radioProgress: accentColor.withMultiplied(hue: 0.99, saturation: 0.56, brightness: 1.0), highlight: accentColor.withMultiplied(hue: 0.99, saturation: 0.56, brightness: 1.0).withAlphaComponent(0.12), separator: mainSeparatorColor, bar: .white), actionButtonsFillColor: PresentationThemeVariableColor(withWallpaper: additionalBackgroundColor.withAlphaComponent(0.5), withoutWallpaper: additionalBackgroundColor.withAlphaComponent(0.5)), actionButtonsStrokeColor: PresentationThemeVariableColor(color: buttonStrokeColor), actionButtonsTextColor: PresentationThemeVariableColor(color: .white), textSelectionColor: UIColor.white.withAlphaComponent(0.2), textSelectionKnobColor: UIColor.white),
outgoing: PresentationThemePartedColors(bubble: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: outgoingBubbleFillColor, gradientFill: outgoingBubbleFillGradientColor, highlightedFill: highlightedOutgoingBubbleColor, stroke: outgoingBubbleFillColor), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: outgoingBubbleFillColor, gradientFill: outgoingBubbleFillGradientColor, highlightedFill: highlightedOutgoingBubbleColor, stroke: outgoingBubbleFillColor)), primaryTextColor: outgoingPrimaryTextColor, secondaryTextColor: outgoingSecondaryTextColor, linkTextColor: outgoingLinkTextColor, linkHighlightColor: UIColor.white.withAlphaComponent(0.5), scamColor: outgoingScamColor, textHighlightColor: UIColor(rgb: 0xf5c038), accentTextColor: outgoingPrimaryTextColor, accentControlColor: outgoingPrimaryTextColor, mediaActiveControlColor: outgoingPrimaryTextColor, mediaInactiveControlColor: outgoingSecondaryTextColor, mediaControlInnerBackgroundColor: outgoingBubbleFillColor, pendingActivityColor: outgoingSecondaryTextColor, fileTitleColor: outgoingPrimaryTextColor, fileDescriptionColor: outgoingSecondaryTextColor, fileDurationColor: outgoingSecondaryTextColor, mediaPlaceholderColor: accentColor.withMultiplied(hue: 1.019, saturation: 0.804, brightness: 0.51), polls: PresentationThemeChatBubblePolls(radioButton: outgoingPrimaryTextColor, radioProgress: accentColor.withMultiplied(hue: 0.99, saturation: 0.56, brightness: 1.0), highlight: accentColor.withMultiplied(hue: 0.99, saturation: 0.56, brightness: 1.0).withAlphaComponent(0.12), separator: mainSeparatorColor, bar: outgoingPrimaryTextColor), actionButtonsFillColor: PresentationThemeVariableColor(withWallpaper: additionalBackgroundColor.withAlphaComponent(0.5), withoutWallpaper: additionalBackgroundColor.withAlphaComponent(0.5)), actionButtonsStrokeColor: PresentationThemeVariableColor(color: buttonStrokeColor), actionButtonsTextColor: PresentationThemeVariableColor(color: .white), textSelectionColor: UIColor.white.withAlphaComponent(0.2), textSelectionKnobColor: UIColor.white),
freeform: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: mainBackgroundColor, highlightedFill: highlightedIncomingBubbleColor, stroke: mainBackgroundColor), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: mainBackgroundColor, highlightedFill: highlightedIncomingBubbleColor, stroke: mainBackgroundColor)),
infoPrimaryTextColor: UIColor(rgb: 0xffffff),
infoLinkTextColor: accentColor,
outgoingCheckColor: accentColor.withMultiplied(hue: 0.99, saturation: 0.743, brightness: 1.0),
outgoingCheckColor: outgoingCheckColor,
mediaDateAndStatusFillColor: UIColor(white: 0.0, alpha: 0.5),
mediaDateAndStatusTextColor: .white,
mediaDateAndStatusTextColor: UIColor(rgb: 0xffffff),
shareButtonFillColor: PresentationThemeVariableColor(color: additionalBackgroundColor.withAlphaComponent(0.5)),
shareButtonStrokeColor: PresentationThemeVariableColor(color: buttonStrokeColor),
shareButtonForegroundColor: PresentationThemeVariableColor(color: UIColor(rgb: 0xb2b2b2)),

View File

@ -1610,25 +1610,16 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}
}
}, scheduleCurrentMessage: { [weak self] in
if let strongSelf = self, let peer = strongSelf.presentationInterfaceState.renderedPeer?.peer {
let mode: ChatScheduleTimeControllerMode
if peer.id == strongSelf.context.account.peerId {
mode = .reminders
} else {
mode = .scheduledMessages(sendWhenOnlineAvailable: peer.id.namespace == Namespaces.Peer.CloudUser)
}
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, completion: { [weak self] in
strongSelf.presentScheduleTimePicker(completion: { [weak self] time in
if let strongSelf = self {
strongSelf.chatDisplayNode.sendCurrentMessage(scheduleTime: time, completion: { [weak self] in
if let strongSelf = self, !strongSelf.presentationInterfaceState.isScheduledMessages {
strongSelf.openScheduledMessages()
}
})
}
})
strongSelf.chatDisplayNode.dismissInput()
strongSelf.present(controller, in: .window(.root))
}
}, sendScheduledMessagesNow: { [weak self] messageIds in
if let strongSelf = self {
@ -1642,21 +1633,14 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}
}
}, editScheduledMessagesTime: { [weak self] messageIds in
if let strongSelf = self, let messageId = messageIds.first, let peer = strongSelf.presentationInterfaceState.renderedPeer?.peer {
let mode: ChatScheduleTimeControllerMode
if peer.id == strongSelf.context.account.peerId {
mode = .reminders
} else {
mode = .scheduledMessages(sendWhenOnlineAvailable: peer.id.namespace == Namespaces.Peer.CloudUser)
}
if let strongSelf = self, let messageId = messageIds.first {
let _ = (strongSelf.context.account.postbox.transaction { transaction -> Message? in
return transaction.getMessage(messageId)
} |> deliverOnMainQueue).start(next: { [weak self] message in
guard let strongSelf = self, let message = message else {
return
}
let controller = ChatScheduleTimeController(context: strongSelf.context, mode: mode, currentTime: message.timestamp, minimalTime: strongSelf.presentationInterfaceState.slowmodeState?.timeout, completion: { [weak self] scheduleTime in
strongSelf.presentScheduleTimePicker(selectedTime: message.timestamp, completion: { [weak self] time in
if let strongSelf = self {
var entities: TextEntitiesMessageAttribute?
for attribute in message.attributes {
@ -1665,14 +1649,12 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
break
}
}
let signal = requestEditMessage(account: strongSelf.context.account, messageId: messageId, text: message.text, media: .keep, entities: entities, disableUrlPreview: false, scheduleTime: scheduleTime)
let signal = requestEditMessage(account: strongSelf.context.account, messageId: messageId, text: message.text, media: .keep, entities: entities, disableUrlPreview: false, scheduleTime: time)
strongSelf.editMessageDisposable.set((signal |> deliverOnMainQueue).start(next: { result in
}, error: { error in
}))
}
})
strongSelf.chatDisplayNode.dismissInput()
strongSelf.present(controller, in: .window(.root))
})
}
}, performTextSelectionAction: { [weak self] _, text, action in
@ -5513,16 +5495,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}
}
}, presentSchedulePicker: { [weak self] done in
guard let strongSelf = self else {
return
}
let mode: ChatScheduleTimeControllerMode
if peer.id == strongSelf.context.account.peerId {
mode = .reminders
} else {
mode = .scheduledMessages(sendWhenOnlineAvailable: peer.id.namespace == Namespaces.Peer.CloudUser)
}
let controller = ChatScheduleTimeController(context: strongSelf.context, mode: mode, minimalTime: strongSelf.presentationInterfaceState.slowmodeState?.timeout, completion: { [weak self] time in
if let strongSelf = self {
strongSelf.presentScheduleTimePicker(completion: { [weak self] time in
if let strongSelf = self {
done(time)
if !strongSelf.presentationInterfaceState.isScheduledMessages {
@ -5530,7 +5504,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}
}
})
strongSelf.present(controller, in: .window(.root))
}
})
}
}, openFileGallery: {
@ -5560,16 +5534,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}
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))
}, presentSchedulePicker: { [weak self] done in
guard let strongSelf = self, let peer = strongSelf.presentationInterfaceState.renderedPeer?.peer else {
return
}
let mode: ChatScheduleTimeControllerMode
if peer.id == strongSelf.context.account.peerId {
mode = .reminders
} else {
mode = .scheduledMessages(sendWhenOnlineAvailable: peer.id.namespace == Namespaces.Peer.CloudUser)
}
let controller = ChatScheduleTimeController(context: strongSelf.context, mode: mode, minimalTime: strongSelf.presentationInterfaceState.slowmodeState?.timeout, completion: { [weak self] time in
if let strongSelf = self {
strongSelf.presentScheduleTimePicker(completion: { [weak self] time in
if let strongSelf = self {
done(time)
if !strongSelf.presentationInterfaceState.isScheduledMessages {
@ -5577,7 +5543,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}
}
})
strongSelf.present(controller, in: .window(.root))
}
}, sendMessagesWithSignals: { [weak self] signals, silentPosting, scheduleTime in
if !inputText.string.isEmpty {
//strongSelf.clearInputText()
@ -5760,16 +5726,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationTheme: strongSelf.presentationData.theme), title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root))
}, presentSchedulePicker: { [weak self] done in
guard let strongSelf = self, let peer = strongSelf.presentationInterfaceState.renderedPeer?.peer else {
return
}
let mode: ChatScheduleTimeControllerMode
if peer.id == strongSelf.context.account.peerId {
mode = .reminders
} else {
mode = .scheduledMessages(sendWhenOnlineAvailable: peer.id.namespace == Namespaces.Peer.CloudUser)
}
let controller = ChatScheduleTimeController(context: strongSelf.context, mode: mode, minimalTime: strongSelf.presentationInterfaceState.slowmodeState?.timeout, completion: { [weak self] time in
if let strongSelf = self {
strongSelf.presentScheduleTimePicker(completion: { [weak self] time in
if let strongSelf = self {
done(time)
if !strongSelf.presentationInterfaceState.isScheduledMessages {
@ -5777,7 +5735,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}
}
})
strongSelf.present(controller, in: .window(.root))
}
})
controller.descriptionGenerator = legacyAssetPickerItemGenerator()
controller.completionBlock = { [weak legacyController] signals, silentPosting, scheduleTime in
@ -6050,19 +6008,11 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
donateSendMessageIntent(account: self.context.account, sharedContext: self.context.sharedContext, peerIds: [peerId])
} else {
let mode: ChatScheduleTimeControllerMode
if peerId == self.context.account.peerId {
mode = .reminders
} else {
mode = .scheduledMessages(sendWhenOnlineAvailable: peerId.namespace == Namespaces.Peer.CloudUser)
}
let controller = ChatScheduleTimeController(context: self.context, mode: mode, minimalTime: self.presentationInterfaceState.slowmodeState?.timeout, dismissByTapOutside: false, completion: { [weak self] time in
self.presentScheduleTimePicker(dismissByTapOutside: false, completion: { [weak self] time in
if let strongSelf = self {
strongSelf.sendMessages(strongSelf.transformEnqueueMessages(messages, silentPosting: false, scheduleTime: time), commit: true)
}
})
self.chatDisplayNode.dismissInput()
self.present(controller, in: .window(.root))
}
}
@ -8184,6 +8134,35 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
self.effectiveNavigationController?.pushViewController(controller)
}
private func presentScheduleTimePicker(selectedTime: Int32? = nil, dismissByTapOutside: Bool = true, completion: @escaping (Int32) -> Void) {
guard case let .peer(peerId) = self.chatLocation else {
return
}
let _ = (self.context.account.viewTracker.peerView(peerId)
|> take(1)
|> deliverOnMainQueue).start(next: { [weak self] peerView in
guard let strongSelf = self, let peer = peerViewMainPeer(peerView) else {
return
}
var sendWhenOnlineAvailable = false
if let presence = peerView.peerPresences[peer.id] as? TelegramUserPresence, case .present = presence.status {
sendWhenOnlineAvailable = true
}
let mode: ChatScheduleTimeControllerMode
if peerId == strongSelf.context.account.peerId {
mode = .reminders
} else {
mode = .scheduledMessages(sendWhenOnlineAvailable: sendWhenOnlineAvailable)
}
let controller = ChatScheduleTimeController(context: strongSelf.context, peerId: peerId, mode: mode, currentTime: selectedTime, minimalTime: strongSelf.presentationInterfaceState.slowmodeState?.timeout, dismissByTapOutside: dismissByTapOutside, completion: { time in
completion(time)
})
strongSelf.chatDisplayNode.dismissInput()
strongSelf.present(controller, in: .window(.root))
})
}
private var effectiveNavigationController: NavigationController? {
if let navigationController = self.navigationController as? NavigationController {
return navigationController

View File

@ -21,7 +21,9 @@ final class ChatScheduleTimeController: ViewController {
private var animatedIn = false
private let context: AccountContext
private let peerId: PeerId
private let mode: ChatScheduleTimeControllerMode
private let editingTime: Bool
private let currentTime: Int32?
private let minimalTime: Int32?
private let dismissByTapOutside: Bool
@ -29,9 +31,11 @@ final class ChatScheduleTimeController: ViewController {
private var presentationDataDisposable: Disposable?
init(context: AccountContext, mode: ChatScheduleTimeControllerMode, currentTime: Int32? = nil, minimalTime: Int32? = nil, dismissByTapOutside: Bool = true, completion: @escaping (Int32) -> Void) {
init(context: AccountContext, peerId: PeerId, mode: ChatScheduleTimeControllerMode, currentTime: Int32? = nil, minimalTime: Int32? = nil, dismissByTapOutside: Bool = true, completion: @escaping (Int32) -> Void) {
self.context = context
self.peerId = peerId
self.mode = mode
self.editingTime = currentTime != nil
self.currentTime = currentTime != scheduleWhenOnlineTimestamp ? currentTime : nil
self.minimalTime = minimalTime
self.dismissByTapOutside = dismissByTapOutside
@ -64,8 +68,27 @@ final class ChatScheduleTimeController: ViewController {
override public func loadDisplayNode() {
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 != scheduleWhenOnlineTimestamp ? time + 5 : time)
self?.dismiss()
guard let strongSelf = self else {
return
}
if time == scheduleWhenOnlineTimestamp {
let _ = (strongSelf.context.account.viewTracker.peerView(strongSelf.peerId)
|> take(1)
|> deliverOnMainQueue).start(next: { [weak self] peerView in
guard let strongSelf = self, let peer = peerViewMainPeer(peerView) else {
return
}
let timestamp = Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970)
if !strongSelf.editingTime, let presence = peerView.peerPresences[peer.id] as? TelegramUserPresence, case let .present(statusTimestamp) = presence.status, statusTimestamp >= timestamp {
strongSelf.completion(0)
} else {
strongSelf.completion(time)
}
})
} else {
strongSelf.completion(time + 5)
}
strongSelf.dismiss()
}
self.controllerNode.dismiss = { [weak self] in
self?.presentingViewController?.dismiss(animated: false, completion: nil)