mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Various fixes
This commit is contained in:
parent
1e49c24614
commit
de61740a73
@ -4980,3 +4980,9 @@ Any member of this group will be able to see messages in the channel.";
|
|||||||
"ClearCache.FreeSpaceDescription" = "If you want to save space on your device, you don't need to delete anything.\n\nYou can use cache settings to remove unnecessary media — and re-download files if you need them again.";
|
"ClearCache.FreeSpaceDescription" = "If you want to save space on your device, you don't need to delete anything.\n\nYou can use cache settings to remove unnecessary media — and re-download files if you need them again.";
|
||||||
"ClearCache.FreeSpace" = "Free Space";
|
"ClearCache.FreeSpace" = "Free Space";
|
||||||
"ClearCache.Success" = "**%@** freed on your phone!";
|
"ClearCache.Success" = "**%@** freed on your phone!";
|
||||||
|
|
||||||
|
"Conversation.ScheduleMessage.SendWhenOnline" = "Send When Online";
|
||||||
|
"ScheduledMessages.ScheduledOnline" = "Scheduled until online";
|
||||||
|
|
||||||
|
"Conversation.SwipeToReplyHintTitle" = "Swipe To Reply";
|
||||||
|
"Conversation.SwipeToReplyHintText" = "Swipe left on any message to reply to it.";
|
||||||
|
@ -333,7 +333,7 @@ private final class WalletContextImpl: NSObject, WalletContext, UIImagePickerCon
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func pickImage(completion: @escaping (UIImage) -> Void) {
|
func pickImage(present: @escaping (ViewController) -> Void, completion: @escaping (UIImage) -> Void) {
|
||||||
self.currentImagePickerCompletion = completion
|
self.currentImagePickerCompletion = completion
|
||||||
|
|
||||||
let pickerController = UIImagePickerController()
|
let pickerController = UIImagePickerController()
|
||||||
|
@ -389,6 +389,11 @@
|
|||||||
completionBlock();
|
completionBlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSArray<NSString *> *)suggestionsForResponseToActionWithIdentifier:(NSString *)identifier forNotification:(UNNotification *)notification inputLanguage:(NSString *)inputLanguage
|
||||||
|
{
|
||||||
|
return [TGInputController suggestionsForText:nil];
|
||||||
|
}
|
||||||
|
|
||||||
- (NSArray<NSString *> *)suggestionsForResponseToActionWithIdentifier:(NSString *)identifier forLocalNotification:(UILocalNotification *)localNotification inputLanguage:(NSString *)inputLanguage
|
- (NSArray<NSString *> *)suggestionsForResponseToActionWithIdentifier:(NSString *)identifier forLocalNotification:(UILocalNotification *)localNotification inputLanguage:(NSString *)inputLanguage
|
||||||
{
|
{
|
||||||
return [TGInputController suggestionsForText:nil];
|
return [TGInputController suggestionsForText:nil];
|
||||||
|
@ -413,7 +413,9 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
|
|||||||
self.requestLayout?(.immediate)
|
self.requestLayout?(.immediate)
|
||||||
}
|
}
|
||||||
|
|
||||||
self.deleteButton.isHidden = origin == nil
|
if origin == nil {
|
||||||
|
self.deleteButton.isHidden = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func setMessage(_ message: Message) {
|
func setMessage(_ message: Message) {
|
||||||
@ -830,7 +832,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
|
|||||||
if !ask && items.count == 1 {
|
if !ask && items.count == 1 {
|
||||||
let _ = deleteMessagesInteractively(postbox: strongSelf.context.account.postbox, messageIds: messages.map { $0.id }, type: .forEveryone).start()
|
let _ = deleteMessagesInteractively(postbox: strongSelf.context.account.postbox, messageIds: messages.map { $0.id }, type: .forEveryone).start()
|
||||||
strongSelf.controllerInteraction?.dismissController()
|
strongSelf.controllerInteraction?.dismissController()
|
||||||
} else {
|
} else if !items.isEmpty {
|
||||||
actionSheet.setItemGroups([ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [
|
actionSheet.setItemGroups([ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [
|
||||||
ActionSheetButtonItem(title: strongSelf.strings.Common_Cancel, color: .accent, action: { [weak actionSheet] in
|
ActionSheetButtonItem(title: strongSelf.strings.Common_Cancel, color: .accent, action: { [weak actionSheet] in
|
||||||
actionSheet?.dismissAnimated()
|
actionSheet?.dismissAnimated()
|
||||||
|
@ -45,29 +45,29 @@ public func qrCode(string: String, color: UIColor, backgroundColor: UIColor? = n
|
|||||||
|> map { data, size, bytesPerRow in
|
|> map { data, size, bytesPerRow in
|
||||||
return { arguments in
|
return { arguments in
|
||||||
let context = DrawingContext(size: arguments.drawingSize, scale: arguments.scale ?? 0.0, clear: true)
|
let context = DrawingContext(size: arguments.drawingSize, scale: arguments.scale ?? 0.0, clear: true)
|
||||||
|
let side = floorToScreenPixels(arguments.drawingSize.width / CGFloat(size))
|
||||||
|
let padding: CGFloat = floor((arguments.drawingSize.width - CGFloat(side * CGFloat(size))) / 2.0)
|
||||||
|
|
||||||
|
let drawingRect = arguments.drawingRect
|
||||||
|
let fittedSize = arguments.imageSize.aspectFilled(arguments.boundingSize).fitted(arguments.imageSize)
|
||||||
|
let fittedRect = CGRect(origin: CGPoint(x: drawingRect.origin.x + (drawingRect.size.width - fittedSize.width) / 2.0, y: drawingRect.origin.y + (drawingRect.size.height - fittedSize.height) / 2.0), size: fittedSize)
|
||||||
|
|
||||||
|
let codeScale: CGFloat = 1.10256
|
||||||
|
let clipSide = fittedRect.width * 0.23124
|
||||||
|
let clipRect = CGRect(x: fittedRect.midX - clipSide / 2.0, y: fittedRect.midY - clipSide / 2.0, width: clipSide, height: clipSide)
|
||||||
|
|
||||||
let cutout: (Int, Int)?
|
let cutout: (Int, Int)?
|
||||||
if case .none = icon {
|
if case .none = icon {
|
||||||
cutout = nil
|
cutout = nil
|
||||||
} else {
|
} else {
|
||||||
switch size {
|
var cutoutSize = Int(ceil((clipSide + side * 2.0) / side))
|
||||||
case 39:
|
if size == 39 {
|
||||||
cutout = (14, 24)
|
cutoutSize = 11
|
||||||
case 43:
|
} else if cutoutSize % 2 == 0 {
|
||||||
cutout = (15, 27)
|
cutoutSize += 1
|
||||||
case 47:
|
|
||||||
cutout = (17, 29)
|
|
||||||
case 51:
|
|
||||||
cutout = (19, 31)
|
|
||||||
case 55:
|
|
||||||
cutout = (21, 33)
|
|
||||||
case 59:
|
|
||||||
cutout = (22, 36)
|
|
||||||
case 63:
|
|
||||||
cutout = (23, 39)
|
|
||||||
default:
|
|
||||||
cutout = (16, 26)
|
|
||||||
}
|
}
|
||||||
|
let start = (size - cutoutSize) / 2
|
||||||
|
cutout = (start, start + cutoutSize - 1)
|
||||||
}
|
}
|
||||||
func valueAt(x: Int, y: Int) -> Bool {
|
func valueAt(x: Int, y: Int) -> Bool {
|
||||||
if x >= 0 && x < size && y >= 0 && y < size {
|
if x >= 0 && x < size && y >= 0 && y < size {
|
||||||
@ -87,9 +87,6 @@ public func qrCode(string: String, color: UIColor, backgroundColor: UIColor? = n
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let side = floorToScreenPixels(arguments.drawingSize.width / CGFloat(size))
|
|
||||||
let padding: CGFloat = floor((arguments.drawingSize.width - CGFloat(side * CGFloat(size))) / 2.0)
|
|
||||||
|
|
||||||
let squareSize = CGSize(width: side, height: side)
|
let squareSize = CGSize(width: side, height: side)
|
||||||
let tmpContext = DrawingContext(size: CGSize(width: squareSize.width * 4.0, height: squareSize.height), scale: arguments.scale ?? 0.0, clear: true)
|
let tmpContext = DrawingContext(size: CGSize(width: squareSize.width * 4.0, height: squareSize.height), scale: arguments.scale ?? 0.0, clear: true)
|
||||||
tmpContext.withContext { c in
|
tmpContext.withContext { c in
|
||||||
@ -233,13 +230,6 @@ public func qrCode(string: String, color: UIColor, backgroundColor: UIColor? = n
|
|||||||
|
|
||||||
c.translateBy(x: -padding, y: -padding)
|
c.translateBy(x: -padding, y: -padding)
|
||||||
|
|
||||||
let drawingRect = arguments.drawingRect
|
|
||||||
let fittedSize = arguments.imageSize.aspectFilled(arguments.boundingSize).fitted(arguments.imageSize)
|
|
||||||
let fittedRect = CGRect(origin: CGPoint(x: drawingRect.origin.x + (drawingRect.size.width - fittedSize.width) / 2.0, y: drawingRect.origin.y + (drawingRect.size.height - fittedSize.height) / 2.0), size: fittedSize)
|
|
||||||
|
|
||||||
let codeScale: CGFloat = 43.0 / 39.0
|
|
||||||
let clipSide = 56.0 * fittedRect.width / 267.0 * codeScale
|
|
||||||
let clipRect = CGRect(x: fittedRect.midX - clipSide / 2.0, y: fittedRect.midY - clipSide / 2.0, width: clipSide, height: clipSide)
|
|
||||||
|
|
||||||
switch icon {
|
switch icon {
|
||||||
case .proxy:
|
case .proxy:
|
||||||
|
@ -193,7 +193,7 @@ public extension Message {
|
|||||||
func effectivelyFailed(timestamp: Int32) -> Bool {
|
func effectivelyFailed(timestamp: Int32) -> Bool {
|
||||||
if self.flags.contains(.Failed) {
|
if self.flags.contains(.Failed) {
|
||||||
return true
|
return true
|
||||||
} else if self.id.namespace == Namespaces.Message.ScheduledCloud {
|
} else if self.id.namespace == Namespaces.Message.ScheduledCloud && self.timestamp != 0x7FFFFFFE {
|
||||||
return timestamp > self.timestamp + 60
|
return timestamp > self.timestamp + 60
|
||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1689,6 +1689,10 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
strongSelf.present(MessageReactionListController(context: strongSelf.context, messageId: message.id, initialReactions: initialReactions), in: .window(.root))
|
strongSelf.present(MessageReactionListController(context: strongSelf.context, messageId: message.id, initialReactions: initialReactions), in: .window(.root))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
}, displaySwipeToReplyHint: { [weak self] in
|
||||||
|
if let strongSelf = self {
|
||||||
|
strongSelf.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: .swipeToReply(title: strongSelf.presentationData.strings.Conversation_SwipeToReplyHintTitle, text: strongSelf.presentationData.strings.Conversation_SwipeToReplyHintText), elevatedLayout: true, action: { _ in }), in: .window(.root))
|
||||||
|
}
|
||||||
}, requestMessageUpdate: { [weak self] id in
|
}, requestMessageUpdate: { [weak self] id in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
strongSelf.chatDisplayNode.historyNode.requestMessageUpdate(id)
|
strongSelf.chatDisplayNode.historyNode.requestMessageUpdate(id)
|
||||||
@ -5073,7 +5077,6 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
self.dismiss()
|
self.dismiss()
|
||||||
case .clearCache:
|
case .clearCache:
|
||||||
let clearDisposable = MetaDisposable()
|
let clearDisposable = MetaDisposable()
|
||||||
self.updateChatPresentationInterfaceState(animated: true, interactive: true, { $0.updatedInterfaceState({ $0.withoutSelectionState() }) })
|
|
||||||
|
|
||||||
switch self.chatLocationInfoData {
|
switch self.chatLocationInfoData {
|
||||||
case let .peer(peerView):
|
case let .peer(peerView):
|
||||||
@ -5244,13 +5247,15 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
clearDisposable.set(nil)
|
clearDisposable.set(nil)
|
||||||
}
|
}
|
||||||
clearDisposable.set((signal
|
clearDisposable.set((signal
|
||||||
|> deliverOnMainQueue).start(completed: {
|
|> deliverOnMainQueue).start(completed: { [weak self] in
|
||||||
|
if let strongSelf = self {
|
||||||
|
strongSelf.present(UndoOverlayController(presentationData: presentationData, content: .succeed(text: presentationData.strings.ClearCache_Success("\(dataSizeString(totalSize, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator))").0), elevatedLayout: true, action: { _ in }), in: .window(.root))
|
||||||
strongSelf.present(UndoOverlayController(presentationData: presentationData, content: .succeed(text: presentationData.strings.ClearCache_Success("\(dataSizeString(totalSize, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator))").0), elevatedLayout: false, action: { _ in }), in: .window(.root))
|
}
|
||||||
}))
|
}))
|
||||||
|
|
||||||
dismissAction()
|
dismissAction()
|
||||||
|
|
||||||
|
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { $0.updatedInterfaceState({ $0.withoutSelectionState() }) })
|
||||||
}))
|
}))
|
||||||
|
|
||||||
controller.setItemGroups([
|
controller.setItemGroups([
|
||||||
|
@ -99,6 +99,7 @@ public final class ChatControllerInteraction {
|
|||||||
let performTextSelectionAction: (UInt32, String, TextSelectionAction) -> Void
|
let performTextSelectionAction: (UInt32, String, TextSelectionAction) -> Void
|
||||||
let updateMessageReaction: (MessageId, String) -> Void
|
let updateMessageReaction: (MessageId, String) -> Void
|
||||||
let openMessageReactions: (MessageId) -> Void
|
let openMessageReactions: (MessageId) -> Void
|
||||||
|
let displaySwipeToReplyHint: () -> Void
|
||||||
|
|
||||||
let requestMessageUpdate: (MessageId) -> Void
|
let requestMessageUpdate: (MessageId) -> Void
|
||||||
let cancelInteractiveKeyboardGestures: () -> Void
|
let cancelInteractiveKeyboardGestures: () -> Void
|
||||||
@ -113,7 +114,7 @@ public final class ChatControllerInteraction {
|
|||||||
var searchTextHighightState: (String, [MessageIndex])?
|
var searchTextHighightState: (String, [MessageIndex])?
|
||||||
var seenOneTimeAnimatedMedia = Set<MessageId>()
|
var seenOneTimeAnimatedMedia = Set<MessageId>()
|
||||||
|
|
||||||
init(openMessage: @escaping (Message, ChatControllerInteractionOpenMessageMode) -> Bool, openPeer: @escaping (PeerId?, ChatControllerInteractionNavigateToPeer, Message?) -> Void, openPeerMention: @escaping (String) -> Void, openMessageContextMenu: @escaping (Message, Bool, ASDisplayNode, CGRect, TapLongTapOrDoubleTapGestureRecognizer?) -> Void, openMessageContextActions: @escaping (Message, ASDisplayNode, CGRect, ContextGesture?) -> Void, navigateToMessage: @escaping (MessageId, MessageId) -> Void, clickThroughMessage: @escaping () -> Void, toggleMessagesSelection: @escaping ([MessageId], Bool) -> Void, sendCurrentMessage: @escaping (Bool) -> Void, sendMessage: @escaping (String) -> Void, sendSticker: @escaping (FileMediaReference, Bool, ASDisplayNode, CGRect) -> Bool, sendGif: @escaping (FileMediaReference, ASDisplayNode, CGRect) -> Bool, requestMessageActionCallback: @escaping (MessageId, MemoryBuffer?, Bool) -> Void, requestMessageActionUrlAuth: @escaping (String, MessageId, Int32) -> Void, activateSwitchInline: @escaping (PeerId?, String) -> Void, openUrl: @escaping (String, Bool, Bool?) -> Void, shareCurrentLocation: @escaping () -> Void, shareAccountContact: @escaping () -> Void, sendBotCommand: @escaping (MessageId?, String) -> Void, openInstantPage: @escaping (Message, ChatMessageItemAssociatedData?) -> Void, openWallpaper: @escaping (Message) -> Void, openTheme: @escaping (Message) -> Void, openHashtag: @escaping (String?, String) -> Void, updateInputState: @escaping ((ChatTextInputState) -> ChatTextInputState) -> Void, updateInputMode: @escaping ((ChatInputMode) -> ChatInputMode) -> Void, openMessageShareMenu: @escaping (MessageId) -> Void, presentController: @escaping (ViewController, Any?) -> Void, navigationController: @escaping () -> NavigationController?, chatControllerNode: @escaping () -> ASDisplayNode?, reactionContainerNode: @escaping () -> ReactionSelectionParentNode?, presentGlobalOverlayController: @escaping (ViewController, Any?) -> Void, callPeer: @escaping (PeerId) -> Void, longTap: @escaping (ChatControllerInteractionLongTapAction, Message?) -> Void, openCheckoutOrReceipt: @escaping (MessageId) -> Void, openSearch: @escaping () -> Void, setupReply: @escaping (MessageId) -> Void, canSetupReply: @escaping (Message) -> Bool, navigateToFirstDateMessage: @escaping(Int32) ->Void, requestRedeliveryOfFailedMessages: @escaping (MessageId) -> Void, addContact: @escaping (String) -> Void, rateCall: @escaping (Message, CallId) -> Void, requestSelectMessagePollOption: @escaping (MessageId, Data) -> Void, openAppStorePage: @escaping () -> Void, displayMessageTooltip: @escaping (MessageId, String, ASDisplayNode?, CGRect?) -> Void, seekToTimecode: @escaping (Message, Double, Bool) -> Void, scheduleCurrentMessage: @escaping () -> Void, sendScheduledMessagesNow: @escaping ([MessageId]) -> Void, editScheduledMessagesTime: @escaping ([MessageId]) -> Void, performTextSelectionAction: @escaping (UInt32, String, TextSelectionAction) -> Void, updateMessageReaction: @escaping (MessageId, String) -> Void, openMessageReactions: @escaping (MessageId) -> Void, requestMessageUpdate: @escaping (MessageId) -> Void, cancelInteractiveKeyboardGestures: @escaping () -> Void, automaticMediaDownloadSettings: MediaAutoDownloadSettings, pollActionState: ChatInterfacePollActionState, stickerSettings: ChatInterfaceStickerSettings) {
|
init(openMessage: @escaping (Message, ChatControllerInteractionOpenMessageMode) -> Bool, openPeer: @escaping (PeerId?, ChatControllerInteractionNavigateToPeer, Message?) -> Void, openPeerMention: @escaping (String) -> Void, openMessageContextMenu: @escaping (Message, Bool, ASDisplayNode, CGRect, TapLongTapOrDoubleTapGestureRecognizer?) -> Void, openMessageContextActions: @escaping (Message, ASDisplayNode, CGRect, ContextGesture?) -> Void, navigateToMessage: @escaping (MessageId, MessageId) -> Void, clickThroughMessage: @escaping () -> Void, toggleMessagesSelection: @escaping ([MessageId], Bool) -> Void, sendCurrentMessage: @escaping (Bool) -> Void, sendMessage: @escaping (String) -> Void, sendSticker: @escaping (FileMediaReference, Bool, ASDisplayNode, CGRect) -> Bool, sendGif: @escaping (FileMediaReference, ASDisplayNode, CGRect) -> Bool, requestMessageActionCallback: @escaping (MessageId, MemoryBuffer?, Bool) -> Void, requestMessageActionUrlAuth: @escaping (String, MessageId, Int32) -> Void, activateSwitchInline: @escaping (PeerId?, String) -> Void, openUrl: @escaping (String, Bool, Bool?) -> Void, shareCurrentLocation: @escaping () -> Void, shareAccountContact: @escaping () -> Void, sendBotCommand: @escaping (MessageId?, String) -> Void, openInstantPage: @escaping (Message, ChatMessageItemAssociatedData?) -> Void, openWallpaper: @escaping (Message) -> Void, openTheme: @escaping (Message) -> Void, openHashtag: @escaping (String?, String) -> Void, updateInputState: @escaping ((ChatTextInputState) -> ChatTextInputState) -> Void, updateInputMode: @escaping ((ChatInputMode) -> ChatInputMode) -> Void, openMessageShareMenu: @escaping (MessageId) -> Void, presentController: @escaping (ViewController, Any?) -> Void, navigationController: @escaping () -> NavigationController?, chatControllerNode: @escaping () -> ASDisplayNode?, reactionContainerNode: @escaping () -> ReactionSelectionParentNode?, presentGlobalOverlayController: @escaping (ViewController, Any?) -> Void, callPeer: @escaping (PeerId) -> Void, longTap: @escaping (ChatControllerInteractionLongTapAction, Message?) -> Void, openCheckoutOrReceipt: @escaping (MessageId) -> Void, openSearch: @escaping () -> Void, setupReply: @escaping (MessageId) -> Void, canSetupReply: @escaping (Message) -> Bool, navigateToFirstDateMessage: @escaping(Int32) ->Void, requestRedeliveryOfFailedMessages: @escaping (MessageId) -> Void, addContact: @escaping (String) -> Void, rateCall: @escaping (Message, CallId) -> Void, requestSelectMessagePollOption: @escaping (MessageId, Data) -> Void, openAppStorePage: @escaping () -> Void, displayMessageTooltip: @escaping (MessageId, String, ASDisplayNode?, CGRect?) -> Void, seekToTimecode: @escaping (Message, Double, Bool) -> Void, scheduleCurrentMessage: @escaping () -> Void, sendScheduledMessagesNow: @escaping ([MessageId]) -> Void, editScheduledMessagesTime: @escaping ([MessageId]) -> Void, performTextSelectionAction: @escaping (UInt32, String, TextSelectionAction) -> Void, updateMessageReaction: @escaping (MessageId, String) -> Void, openMessageReactions: @escaping (MessageId) -> Void, displaySwipeToReplyHint: @escaping () -> Void, requestMessageUpdate: @escaping (MessageId) -> Void, cancelInteractiveKeyboardGestures: @escaping () -> Void, automaticMediaDownloadSettings: MediaAutoDownloadSettings, pollActionState: ChatInterfacePollActionState, stickerSettings: ChatInterfaceStickerSettings) {
|
||||||
self.openMessage = openMessage
|
self.openMessage = openMessage
|
||||||
self.openPeer = openPeer
|
self.openPeer = openPeer
|
||||||
self.openPeerMention = openPeerMention
|
self.openPeerMention = openPeerMention
|
||||||
@ -165,6 +166,7 @@ public final class ChatControllerInteraction {
|
|||||||
self.performTextSelectionAction = performTextSelectionAction
|
self.performTextSelectionAction = performTextSelectionAction
|
||||||
self.updateMessageReaction = updateMessageReaction
|
self.updateMessageReaction = updateMessageReaction
|
||||||
self.openMessageReactions = openMessageReactions
|
self.openMessageReactions = openMessageReactions
|
||||||
|
self.displaySwipeToReplyHint = displaySwipeToReplyHint
|
||||||
|
|
||||||
self.requestMessageUpdate = requestMessageUpdate
|
self.requestMessageUpdate = requestMessageUpdate
|
||||||
self.cancelInteractiveKeyboardGestures = cancelInteractiveKeyboardGestures
|
self.cancelInteractiveKeyboardGestures = cancelInteractiveKeyboardGestures
|
||||||
@ -201,6 +203,7 @@ public final class ChatControllerInteraction {
|
|||||||
}, performTextSelectionAction: { _, _, _ in
|
}, performTextSelectionAction: { _, _, _ in
|
||||||
}, updateMessageReaction: { _, _ in
|
}, updateMessageReaction: { _, _ in
|
||||||
}, openMessageReactions: { _ in
|
}, openMessageReactions: { _ in
|
||||||
|
}, displaySwipeToReplyHint: {
|
||||||
}, requestMessageUpdate: { _ in
|
}, requestMessageUpdate: { _ in
|
||||||
}, cancelInteractiveKeyboardGestures: {
|
}, cancelInteractiveKeyboardGestures: {
|
||||||
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings,
|
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings,
|
||||||
|
@ -2121,6 +2121,19 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var forwardingToSameChat = false
|
||||||
|
if case let .peer(id) = self.chatPresentationInterfaceState.chatLocation, id.namespace == Namespaces.Peer.CloudUser, id != self.context.account.peerId, let forwardMessageIds = self.chatPresentationInterfaceState.interfaceState.forwardMessageIds {
|
||||||
|
for messageId in forwardMessageIds {
|
||||||
|
if messageId.peerId == id {
|
||||||
|
forwardingToSameChat = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !messages.isEmpty && forwardingToSameChat {
|
||||||
|
//self.controllerInteraction.displaySwipeToReplyHint()
|
||||||
|
}
|
||||||
|
|
||||||
if !messages.isEmpty || self.chatPresentationInterfaceState.interfaceState.forwardMessageIds != nil {
|
if !messages.isEmpty || self.chatPresentationInterfaceState.interfaceState.forwardMessageIds != nil {
|
||||||
self.setupSendActionOnViewUpdate({ [weak self] in
|
self.setupSendActionOnViewUpdate({ [weak self] in
|
||||||
if let strongSelf = self, let textInputPanelNode = strongSelf.inputPanelNode as? ChatTextInputPanelNode {
|
if let strongSelf = self, let textInputPanelNode = strongSelf.inputPanelNode as? ChatTextInputPanelNode {
|
||||||
|
@ -32,7 +32,9 @@ final class ChatMessageDateHeader: ListViewItemHeader {
|
|||||||
self.presentationData = presentationData
|
self.presentationData = presentationData
|
||||||
self.context = context
|
self.context = context
|
||||||
self.action = action
|
self.action = action
|
||||||
if timestamp == Int32.max {
|
if timestamp == 0x7FFFFFFE {
|
||||||
|
self.roundedTimestamp = 0x7FFFFFFE
|
||||||
|
} else if timestamp == Int32.max {
|
||||||
self.roundedTimestamp = timestamp / (granularity) * (granularity)
|
self.roundedTimestamp = timestamp / (granularity) * (granularity)
|
||||||
} else {
|
} else {
|
||||||
self.roundedTimestamp = ((timestamp + timezoneOffset) / (granularity)) * (granularity)
|
self.roundedTimestamp = ((timestamp + timezoneOffset) / (granularity)) * (granularity)
|
||||||
@ -151,7 +153,9 @@ final class ChatMessageDateHeaderNode: ListViewItemHeaderNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if scheduled {
|
if scheduled {
|
||||||
if timeinfo.tm_year == timeinfoNow.tm_year && timeinfo.tm_yday == timeinfoNow.tm_yday {
|
if localTimestamp == 0x7FFFFFFE {
|
||||||
|
text = presentationData.strings.ScheduledMessages_ScheduledOnline
|
||||||
|
} else if timeinfo.tm_year == timeinfoNow.tm_year && timeinfo.tm_yday == timeinfoNow.tm_yday {
|
||||||
text = presentationData.strings.ScheduledMessages_ScheduledToday
|
text = presentationData.strings.ScheduledMessages_ScheduledToday
|
||||||
} else {
|
} else {
|
||||||
text = presentationData.strings.ScheduledMessages_ScheduledDate(text).0
|
text = presentationData.strings.ScheduledMessages_ScheduledDate(text).0
|
||||||
|
@ -415,6 +415,7 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode {
|
|||||||
}, performTextSelectionAction: { _, _, _ in
|
}, performTextSelectionAction: { _, _, _ in
|
||||||
}, updateMessageReaction: { _, _ in
|
}, updateMessageReaction: { _, _ in
|
||||||
}, openMessageReactions: { _ in
|
}, openMessageReactions: { _ in
|
||||||
|
}, displaySwipeToReplyHint: {
|
||||||
}, requestMessageUpdate: { _ in
|
}, requestMessageUpdate: { _ in
|
||||||
}, cancelInteractiveKeyboardGestures: {
|
}, cancelInteractiveKeyboardGestures: {
|
||||||
}, automaticMediaDownloadSettings: self.automaticMediaDownloadSettings,
|
}, automaticMediaDownloadSettings: self.automaticMediaDownloadSettings,
|
||||||
|
@ -63,7 +63,7 @@ final class ChatScheduleTimeController: ViewController {
|
|||||||
override public func loadDisplayNode() {
|
override public func loadDisplayNode() {
|
||||||
self.displayNode = ChatScheduleTimeControllerNode(context: self.context, mode: self.mode, currentTime: self.currentTime, minimalTime: self.minimalTime, 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.controllerNode.completion = { [weak self] time in
|
||||||
self?.completion(time + 5)
|
self?.completion(time != 0x7FFFFFFE ? time + 5 : time)
|
||||||
self?.dismiss()
|
self?.dismiss()
|
||||||
}
|
}
|
||||||
self.controllerNode.dismiss = { [weak self] in
|
self.controllerNode.dismiss = { [weak self] in
|
||||||
|
@ -25,6 +25,7 @@ class ChatScheduleTimeControllerNode: ViewControllerTracingNode, UIScrollViewDel
|
|||||||
private let titleNode: ASTextNode
|
private let titleNode: ASTextNode
|
||||||
private let cancelButton: HighlightableButtonNode
|
private let cancelButton: HighlightableButtonNode
|
||||||
private let doneButton: SolidRoundedButtonNode
|
private let doneButton: SolidRoundedButtonNode
|
||||||
|
private let onlineButton: HighlightableButtonNode
|
||||||
|
|
||||||
private var pickerView: UIDatePicker?
|
private var pickerView: UIDatePicker?
|
||||||
private let dateFormatter: DateFormatter
|
private let dateFormatter: DateFormatter
|
||||||
@ -75,6 +76,9 @@ class ChatScheduleTimeControllerNode: ViewControllerTracingNode, UIScrollViewDel
|
|||||||
|
|
||||||
self.doneButton = SolidRoundedButtonNode(theme: SolidRoundedButtonTheme(theme: self.presentationData.theme), height: 52.0, cornerRadius: 11.0, gloss: false)
|
self.doneButton = SolidRoundedButtonNode(theme: SolidRoundedButtonTheme(theme: self.presentationData.theme), height: 52.0, cornerRadius: 11.0, gloss: false)
|
||||||
|
|
||||||
|
self.onlineButton = HighlightableButtonNode()
|
||||||
|
self.onlineButton.setTitle(self.presentationData.strings.Conversation_ScheduleMessage_SendWhenOnline, with: Font.regular(17.0), with: self.presentationData.theme.actionSheet.controlAccentColor, for: .normal)
|
||||||
|
|
||||||
self.dateFormatter = DateFormatter()
|
self.dateFormatter = DateFormatter()
|
||||||
self.dateFormatter.timeStyle = .none
|
self.dateFormatter.timeStyle = .none
|
||||||
self.dateFormatter.dateStyle = .short
|
self.dateFormatter.dateStyle = .short
|
||||||
@ -97,6 +101,7 @@ class ChatScheduleTimeControllerNode: ViewControllerTracingNode, UIScrollViewDel
|
|||||||
self.contentContainerNode.addSubnode(self.titleNode)
|
self.contentContainerNode.addSubnode(self.titleNode)
|
||||||
self.contentContainerNode.addSubnode(self.cancelButton)
|
self.contentContainerNode.addSubnode(self.cancelButton)
|
||||||
self.contentContainerNode.addSubnode(self.doneButton)
|
self.contentContainerNode.addSubnode(self.doneButton)
|
||||||
|
//self.contentContainerNode.addSubnode(self.onlineButton)
|
||||||
|
|
||||||
self.cancelButton.addTarget(self, action: #selector(self.cancelButtonPressed), forControlEvents: .touchUpInside)
|
self.cancelButton.addTarget(self, action: #selector(self.cancelButtonPressed), forControlEvents: .touchUpInside)
|
||||||
self.doneButton.pressed = { [weak self] in
|
self.doneButton.pressed = { [weak self] in
|
||||||
@ -111,6 +116,7 @@ class ChatScheduleTimeControllerNode: ViewControllerTracingNode, UIScrollViewDel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
self.onlineButton.addTarget(self, action: #selector(self.onlineButtonPressed), forControlEvents: .touchUpInside)
|
||||||
|
|
||||||
self.setupPickerView(currentTime: currentTime)
|
self.setupPickerView(currentTime: currentTime)
|
||||||
self.updateButtonTitle()
|
self.updateButtonTitle()
|
||||||
@ -130,7 +136,7 @@ class ChatScheduleTimeControllerNode: ViewControllerTracingNode, UIScrollViewDel
|
|||||||
pickerView.timeZone = TimeZone.current
|
pickerView.timeZone = TimeZone.current
|
||||||
pickerView.minuteInterval = 1
|
pickerView.minuteInterval = 1
|
||||||
pickerView.setValue(self.presentationData.theme.actionSheet.primaryTextColor, forKey: "textColor")
|
pickerView.setValue(self.presentationData.theme.actionSheet.primaryTextColor, forKey: "textColor")
|
||||||
contentContainerNode.view.addSubview(pickerView)
|
self.contentContainerNode.view.addSubview(pickerView)
|
||||||
pickerView.addTarget(self, action: #selector(self.datePickerUpdated), for: .valueChanged)
|
pickerView.addTarget(self, action: #selector(self.datePickerUpdated), for: .valueChanged)
|
||||||
self.pickerView = pickerView
|
self.pickerView = pickerView
|
||||||
|
|
||||||
@ -154,6 +160,7 @@ class ChatScheduleTimeControllerNode: ViewControllerTracingNode, UIScrollViewDel
|
|||||||
|
|
||||||
self.cancelButton.setTitle(self.presentationData.strings.Common_Cancel, with: Font.regular(17.0), with: self.presentationData.theme.actionSheet.controlAccentColor, for: .normal)
|
self.cancelButton.setTitle(self.presentationData.strings.Common_Cancel, with: Font.regular(17.0), with: self.presentationData.theme.actionSheet.controlAccentColor, for: .normal)
|
||||||
self.doneButton.updateTheme(SolidRoundedButtonTheme(theme: self.presentationData.theme))
|
self.doneButton.updateTheme(SolidRoundedButtonTheme(theme: self.presentationData.theme))
|
||||||
|
self.onlineButton.setTitle(self.presentationData.strings.Conversation_ScheduleMessage_SendWhenOnline, with: Font.regular(17.0), with: self.presentationData.theme.actionSheet.controlAccentColor, for: .normal)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func updateMinimumDate(currentTime: Int32? = nil) {
|
private func updateMinimumDate(currentTime: Int32? = nil) {
|
||||||
@ -233,6 +240,10 @@ class ChatScheduleTimeControllerNode: ViewControllerTracingNode, UIScrollViewDel
|
|||||||
self.cancel?()
|
self.cancel?()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@objc func onlineButtonPressed() {
|
||||||
|
self.completion?(0x7FFFFFFE)
|
||||||
|
}
|
||||||
|
|
||||||
@objc func dimTapGesture(_ recognizer: UITapGestureRecognizer) {
|
@objc func dimTapGesture(_ recognizer: UITapGestureRecognizer) {
|
||||||
if self.dismissByTapOutside, case .ended = recognizer.state {
|
if self.dismissByTapOutside, case .ended = recognizer.state {
|
||||||
self.cancelButtonPressed()
|
self.cancelButtonPressed()
|
||||||
@ -299,10 +310,12 @@ class ChatScheduleTimeControllerNode: ViewControllerTracingNode, UIScrollViewDel
|
|||||||
let cleanInsets = layout.insets(options: [.statusBar])
|
let cleanInsets = layout.insets(options: [.statusBar])
|
||||||
insets.top = max(10.0, insets.top)
|
insets.top = max(10.0, insets.top)
|
||||||
|
|
||||||
|
var buttonOffset: CGFloat = 0.0 //44.0
|
||||||
|
|
||||||
let bottomInset: CGFloat = 10.0 + cleanInsets.bottom
|
let bottomInset: CGFloat = 10.0 + cleanInsets.bottom
|
||||||
let titleHeight: CGFloat = 54.0
|
let titleHeight: CGFloat = 54.0
|
||||||
var contentHeight = titleHeight + bottomInset + 52.0 + 17.0
|
var contentHeight = titleHeight + bottomInset + 52.0 + 17.0 + buttonOffset
|
||||||
let pickerHeight: CGFloat = min(216.0, layout.size.height - contentHeight)
|
let pickerHeight: CGFloat = min(216.0, layout.size.height - contentHeight - buttonOffset)
|
||||||
contentHeight = titleHeight + bottomInset + 52.0 + 17.0 + pickerHeight
|
contentHeight = titleHeight + bottomInset + 52.0 + 17.0 + pickerHeight
|
||||||
|
|
||||||
let width = horizontalContainerFillingSizeForLayout(layout: layout, sideInset: layout.safeInsets.left)
|
let width = horizontalContainerFillingSizeForLayout(layout: layout, sideInset: layout.safeInsets.left)
|
||||||
@ -329,7 +342,11 @@ class ChatScheduleTimeControllerNode: ViewControllerTracingNode, UIScrollViewDel
|
|||||||
|
|
||||||
let buttonInset: CGFloat = 16.0
|
let buttonInset: CGFloat = 16.0
|
||||||
let buttonHeight = self.doneButton.updateLayout(width: contentFrame.width - buttonInset * 2.0, transition: transition)
|
let buttonHeight = self.doneButton.updateLayout(width: contentFrame.width - buttonInset * 2.0, transition: transition)
|
||||||
transition.updateFrame(node: self.doneButton, frame: CGRect(x: buttonInset, y: contentHeight - buttonHeight - insets.bottom - 10.0, width: contentFrame.width, height: buttonHeight))
|
transition.updateFrame(node: self.doneButton, frame: CGRect(x: buttonInset, y: contentHeight - buttonHeight - insets.bottom - 10.0 - buttonOffset, width: contentFrame.width, height: buttonHeight))
|
||||||
|
|
||||||
|
let onlineSize = self.onlineButton.measure(CGSize(width: width, height: titleHeight))
|
||||||
|
let onlineFrame = CGRect(origin: CGPoint(x: ceil((layout.size.width - onlineSize.width) / 2.0), y: contentHeight - 36.0 - insets.bottom), size: onlineSize)
|
||||||
|
transition.updateFrame(node: self.onlineButton, frame: onlineFrame)
|
||||||
|
|
||||||
self.pickerView?.frame = CGRect(origin: CGPoint(x: 0.0, y: 54.0), size: CGSize(width: contentFrame.width, height: pickerHeight))
|
self.pickerView?.frame = CGRect(origin: CGPoint(x: 0.0, y: 54.0), size: CGSize(width: contentFrame.width, height: pickerHeight))
|
||||||
|
|
||||||
|
@ -116,6 +116,7 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, UIGestu
|
|||||||
}, performTextSelectionAction: { _, _, _ in
|
}, performTextSelectionAction: { _, _, _ in
|
||||||
}, updateMessageReaction: { _, _ in
|
}, updateMessageReaction: { _, _ in
|
||||||
}, openMessageReactions: { _ in
|
}, openMessageReactions: { _ in
|
||||||
|
}, displaySwipeToReplyHint: {
|
||||||
}, requestMessageUpdate: { _ in
|
}, requestMessageUpdate: { _ in
|
||||||
}, cancelInteractiveKeyboardGestures: {
|
}, cancelInteractiveKeyboardGestures: {
|
||||||
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings, pollActionState: ChatInterfacePollActionState(), stickerSettings: ChatInterfaceStickerSettings(loopAnimatedStickers: false))
|
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings, pollActionState: ChatInterfacePollActionState(), stickerSettings: ChatInterfaceStickerSettings(loopAnimatedStickers: false))
|
||||||
|
@ -404,6 +404,7 @@ public class PeerMediaCollectionController: TelegramBaseController {
|
|||||||
}, performTextSelectionAction: { _, _, _ in
|
}, performTextSelectionAction: { _, _, _ in
|
||||||
}, updateMessageReaction: { _, _ in
|
}, updateMessageReaction: { _, _ in
|
||||||
}, openMessageReactions: { _ in
|
}, openMessageReactions: { _ in
|
||||||
|
}, displaySwipeToReplyHint: {
|
||||||
}, requestMessageUpdate: { _ in
|
}, requestMessageUpdate: { _ in
|
||||||
}, cancelInteractiveKeyboardGestures: {
|
}, cancelInteractiveKeyboardGestures: {
|
||||||
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings,
|
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings,
|
||||||
|
File diff suppressed because one or more lines are too long
Binary file not shown.
@ -19,6 +19,9 @@ func stringForMessageTimestampStatus(accountPeerId: PeerId, message: Message, da
|
|||||||
timestamp = message.timestamp
|
timestamp = message.timestamp
|
||||||
}
|
}
|
||||||
var dateText = stringForMessageTimestamp(timestamp: timestamp, dateTimeFormat: dateTimeFormat)
|
var dateText = stringForMessageTimestamp(timestamp: timestamp, dateTimeFormat: dateTimeFormat)
|
||||||
|
if timestamp == 0x7FFFFFFE {
|
||||||
|
dateText = " "
|
||||||
|
}
|
||||||
|
|
||||||
var authorTitle: String?
|
var authorTitle: String?
|
||||||
if let author = message.author as? TelegramUser {
|
if let author = message.author as? TelegramUser {
|
||||||
|
@ -243,11 +243,11 @@ final class WalletContextImpl: WalletContext {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func pickImage(completion: @escaping (UIImage) -> Void) {
|
func pickImage(present: @escaping (ViewController) -> Void, completion: @escaping (UIImage) -> Void) {
|
||||||
self.context.sharedContext.openImagePicker(context: self.context, completion: { image in
|
self.context.sharedContext.openImagePicker(context: self.context, completion: { image in
|
||||||
completion(image)
|
completion(image)
|
||||||
}, present: { [weak self] controller in
|
}, present: { [weak self] controller in
|
||||||
self?.context.sharedContext.mainWindow?.present(controller, on: .root)
|
present(controller)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ public enum UndoOverlayContent {
|
|||||||
case revealedArchive(title: String, text: String, undo: Bool)
|
case revealedArchive(title: String, text: String, undo: Bool)
|
||||||
case succeed(text: String)
|
case succeed(text: String)
|
||||||
case emoji(path: String, text: String)
|
case emoji(path: String, text: String)
|
||||||
|
case swipeToReply(title: String, text: String)
|
||||||
}
|
}
|
||||||
|
|
||||||
public final class UndoOverlayController: ViewController {
|
public final class UndoOverlayController: ViewController {
|
||||||
|
@ -137,6 +137,16 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
|
|||||||
self.textNode.maximumNumberOfLines = 2
|
self.textNode.maximumNumberOfLines = 2
|
||||||
displayUndo = false
|
displayUndo = false
|
||||||
self.originalRemainingSeconds = 5
|
self.originalRemainingSeconds = 5
|
||||||
|
case let .swipeToReply(title, text):
|
||||||
|
self.iconNode = nil
|
||||||
|
self.iconCheckNode = nil
|
||||||
|
self.animationNode = AnimationNode(animation: "anim_swipereply", colors: [:], scale: 1.0)
|
||||||
|
self.animatedStickerNode = nil
|
||||||
|
self.titleNode.attributedText = NSAttributedString(string: title, font: Font.semibold(14.0), textColor: .white)
|
||||||
|
self.textNode.attributedText = NSAttributedString(string: text, font: Font.regular(14.0), textColor: .white)
|
||||||
|
self.textNode.maximumNumberOfLines = 2
|
||||||
|
displayUndo = false
|
||||||
|
self.originalRemainingSeconds = 5
|
||||||
}
|
}
|
||||||
|
|
||||||
self.remainingSeconds = self.originalRemainingSeconds
|
self.remainingSeconds = self.originalRemainingSeconds
|
||||||
@ -168,7 +178,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
|
|||||||
case .removedChat:
|
case .removedChat:
|
||||||
self.panelWrapperNode.addSubnode(self.timerTextNode)
|
self.panelWrapperNode.addSubnode(self.timerTextNode)
|
||||||
self.panelWrapperNode.addSubnode(self.statusNode)
|
self.panelWrapperNode.addSubnode(self.statusNode)
|
||||||
case .archivedChat, .hidArchive, .revealedArchive, .succeed, .emoji:
|
case .archivedChat, .hidArchive, .revealedArchive, .succeed, .emoji, .swipeToReply:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
self.iconNode.flatMap(self.panelWrapperNode.addSubnode)
|
self.iconNode.flatMap(self.panelWrapperNode.addSubnode)
|
||||||
|
@ -65,15 +65,20 @@ class WalletAmountItem: ListViewItem, ItemListItem {
|
|||||||
private let integralFont = Font.medium(48.0)
|
private let integralFont = Font.medium(48.0)
|
||||||
private let fractionalFont = Font.medium(24.0)
|
private let fractionalFont = Font.medium(24.0)
|
||||||
|
|
||||||
|
private let iconSize = CGSize(width: 50.0, height: 50.0)
|
||||||
|
private let verticalOffset: CGFloat = -10.0
|
||||||
|
|
||||||
class WalletAmountItemNode: ListViewItemNode, UITextFieldDelegate, ItemListItemNode, ItemListItemFocusableNode {
|
class WalletAmountItemNode: ListViewItemNode, UITextFieldDelegate, ItemListItemNode, ItemListItemFocusableNode {
|
||||||
private let backgroundNode: ASDisplayNode
|
private let backgroundNode: ASDisplayNode
|
||||||
private let bottomStripeNode: ASDisplayNode
|
private let bottomStripeNode: ASDisplayNode
|
||||||
|
|
||||||
|
private let containerNode: ASDisplayNode
|
||||||
private let textNode: TextFieldNode
|
private let textNode: TextFieldNode
|
||||||
private let iconNode: AnimatedStickerNode
|
private let iconNode: AnimatedStickerNode
|
||||||
private let measureNode: TextNode
|
private let measureNode: TextNode
|
||||||
|
|
||||||
private var item: WalletAmountItem?
|
private var item: WalletAmountItem?
|
||||||
|
private var validLayout: (CGFloat, CGFloat, CGFloat)?
|
||||||
|
|
||||||
var tag: ItemListItemTag? {
|
var tag: ItemListItemTag? {
|
||||||
return self.item?.tag
|
return self.item?.tag
|
||||||
@ -86,6 +91,8 @@ class WalletAmountItemNode: ListViewItemNode, UITextFieldDelegate, ItemListItemN
|
|||||||
self.bottomStripeNode = ASDisplayNode()
|
self.bottomStripeNode = ASDisplayNode()
|
||||||
self.bottomStripeNode.isLayerBacked = true
|
self.bottomStripeNode.isLayerBacked = true
|
||||||
|
|
||||||
|
self.containerNode = ASDisplayNode()
|
||||||
|
|
||||||
self.textNode = TextFieldNode()
|
self.textNode = TextFieldNode()
|
||||||
|
|
||||||
self.iconNode = AnimatedStickerNode()
|
self.iconNode = AnimatedStickerNode()
|
||||||
@ -100,8 +107,9 @@ class WalletAmountItemNode: ListViewItemNode, UITextFieldDelegate, ItemListItemN
|
|||||||
|
|
||||||
self.clipsToBounds = false
|
self.clipsToBounds = false
|
||||||
|
|
||||||
self.addSubnode(self.textNode)
|
self.addSubnode(self.containerNode)
|
||||||
self.addSubnode(self.iconNode)
|
self.containerNode.addSubnode(self.textNode)
|
||||||
|
self.containerNode.addSubnode(self.iconNode)
|
||||||
}
|
}
|
||||||
|
|
||||||
override func didLoad() {
|
override func didLoad() {
|
||||||
@ -122,9 +130,49 @@ class WalletAmountItemNode: ListViewItemNode, UITextFieldDelegate, ItemListItemN
|
|||||||
self.textNode.hitTestSlop = UIEdgeInsets(top: -5.0, left: -5.0, bottom: -5.0, right: -5.0)
|
self.textNode.hitTestSlop = UIEdgeInsets(top: -5.0, left: -5.0, bottom: -5.0, right: -5.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func inputFieldAsyncLayout() -> (_ item: WalletAmountItem, _ params: ListViewItemLayoutParams) -> (NSAttributedString, NSAttributedString, () -> Void) {
|
||||||
|
let makeMeasureLayout = TextNode.asyncLayout(self.measureNode)
|
||||||
|
|
||||||
|
return { item, params in
|
||||||
|
let contentSize = CGSize(width: params.width, height: 100.0)
|
||||||
|
let layout = ListViewItemNodeLayout(contentSize: contentSize, insets: UIEdgeInsets())
|
||||||
|
|
||||||
|
let attributedPlaceholderText = NSAttributedString(string: "0", font: integralFont, textColor: item.theme.list.itemPlaceholderTextColor)
|
||||||
|
let attributedAmountText = amountAttributedString(item.amount, integralFont: integralFont, fractionalFont: fractionalFont, color: item.theme.list.itemPrimaryTextColor)
|
||||||
|
|
||||||
|
let (measureLayout, _) = makeMeasureLayout(TextNodeLayoutArguments(attributedString: item.amount.isEmpty ? attributedPlaceholderText : attributedAmountText, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||||
|
|
||||||
|
return (attributedPlaceholderText, attributedAmountText, { [weak self] in
|
||||||
|
if let strongSelf = self {
|
||||||
|
let iconFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - max(31.0, measureLayout.size.width)) / 2.0 - 28.0), y: floor((layout.contentSize.height - iconSize.height) / 2.0) - 3.0 + verticalOffset), size: iconSize)
|
||||||
|
strongSelf.iconNode.updateLayout(size: iconFrame.size)
|
||||||
|
strongSelf.iconNode.frame = iconFrame
|
||||||
|
|
||||||
|
let totalWidth = measureLayout.size.width + iconSize.width + 6.0
|
||||||
|
let paddedWidth = layout.size.width - 32.0
|
||||||
|
if totalWidth > paddedWidth {
|
||||||
|
let scale = paddedWidth / totalWidth
|
||||||
|
strongSelf.containerNode.transform = CATransform3DMakeScale(scale, scale, 1.0)
|
||||||
|
} else {
|
||||||
|
strongSelf.containerNode.transform = CATransform3DIdentity
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func updateInputField() {
|
||||||
|
guard let item = self.item, let validLayout = self.validLayout else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let makeInputFieldLayout = self.inputFieldAsyncLayout()
|
||||||
|
let (_, _, inputFieldApply) = makeInputFieldLayout(item, ListViewItemLayoutParams(width: validLayout.0, leftInset: validLayout.1, rightInset: validLayout.2))
|
||||||
|
inputFieldApply()
|
||||||
|
}
|
||||||
|
|
||||||
func asyncLayout() -> (_ item: WalletAmountItem, _ params: ListViewItemLayoutParams, _ neighbors: ItemListNeighbors) -> (ListViewItemNodeLayout, () -> Void) {
|
func asyncLayout() -> (_ item: WalletAmountItem, _ params: ListViewItemLayoutParams, _ neighbors: ItemListNeighbors) -> (ListViewItemNodeLayout, () -> Void) {
|
||||||
let currentItem = self.item
|
let currentItem = self.item
|
||||||
let makeMeasureLayout = TextNode.asyncLayout(self.measureNode)
|
let makeInputFieldLayout = self.inputFieldAsyncLayout()
|
||||||
|
|
||||||
return { item, params, neighbors in
|
return { item, params, neighbors in
|
||||||
var updatedTheme: WalletTheme?
|
var updatedTheme: WalletTheme?
|
||||||
@ -143,16 +191,12 @@ class WalletAmountItemNode: ListViewItemNode, UITextFieldDelegate, ItemListItemN
|
|||||||
insets.top = 0.0
|
insets.top = 0.0
|
||||||
|
|
||||||
let layout = ListViewItemNodeLayout(contentSize: contentSize, insets: insets)
|
let layout = ListViewItemNodeLayout(contentSize: contentSize, insets: insets)
|
||||||
let layoutSize = layout.size
|
let (attributedPlaceholderText, attributedAmountText, inputFieldApply) = makeInputFieldLayout(item, params)
|
||||||
|
|
||||||
let attributedPlaceholderText = NSAttributedString(string: "0", font: integralFont, textColor: item.theme.list.itemPlaceholderTextColor)
|
|
||||||
let attributedAmountText = amountAttributedString(item.amount, integralFont: integralFont, fractionalFont: fractionalFont, color: item.theme.list.itemPrimaryTextColor)
|
|
||||||
|
|
||||||
let (measureLayout, _) = makeMeasureLayout(TextNodeLayoutArguments(attributedString: item.amount.isEmpty ? attributedPlaceholderText : attributedAmountText, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - params.rightInset - leftInset * 2.0, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
|
||||||
|
|
||||||
return (layout, { [weak self] in
|
return (layout, { [weak self] in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
strongSelf.item = item
|
strongSelf.item = item
|
||||||
|
strongSelf.validLayout = (params.width, params.leftInset, params.rightInset)
|
||||||
|
|
||||||
if let _ = updatedTheme {
|
if let _ = updatedTheme {
|
||||||
strongSelf.bottomStripeNode.backgroundColor = item.theme.list.itemBlocksSeparatorColor
|
strongSelf.bottomStripeNode.backgroundColor = item.theme.list.itemBlocksSeparatorColor
|
||||||
@ -185,10 +229,7 @@ class WalletAmountItemNode: ListViewItemNode, UITextFieldDelegate, ItemListItemN
|
|||||||
strongSelf.textNode.textField.attributedText = attributedAmountText
|
strongSelf.textNode.textField.attributedText = attributedAmountText
|
||||||
}
|
}
|
||||||
|
|
||||||
let iconSize = CGSize(width: 50.0, height: 50.0)
|
strongSelf.textNode.frame = CGRect(origin: CGPoint(x: leftInset - 67.0, y: floor((layout.contentSize.height - 48.0) / 2.0) + verticalOffset), size: CGSize(width: max(1.0, params.width + iconSize.width - 5.0 + 100.0), height: 48.0))
|
||||||
let verticalOffset: CGFloat = -10.0
|
|
||||||
|
|
||||||
strongSelf.textNode.frame = CGRect(origin: CGPoint(x: leftInset, y: floor((layout.contentSize.height - 48.0) / 2.0) + verticalOffset), size: CGSize(width: max(1.0, params.width - (leftInset + rightInset) + iconSize.width - 5.0), height: 48.0))
|
|
||||||
|
|
||||||
if strongSelf.backgroundNode.supernode == nil {
|
if strongSelf.backgroundNode.supernode == nil {
|
||||||
strongSelf.insertSubnode(strongSelf.backgroundNode, at: 0)
|
strongSelf.insertSubnode(strongSelf.backgroundNode, at: 0)
|
||||||
@ -207,16 +248,15 @@ class WalletAmountItemNode: ListViewItemNode, UITextFieldDelegate, ItemListItemN
|
|||||||
}
|
}
|
||||||
|
|
||||||
strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight)))
|
strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight)))
|
||||||
strongSelf.bottomStripeNode.frame = CGRect(origin: CGPoint(x: bottomStripeInset, y: contentSize.height - UIScreenPixel), size: CGSize(width: layoutSize.width - bottomStripeInset, height: separatorHeight))
|
strongSelf.bottomStripeNode.frame = CGRect(origin: CGPoint(x: bottomStripeInset, y: contentSize.height - UIScreenPixel), size: CGSize(width: layout.size.width - bottomStripeInset, height: separatorHeight))
|
||||||
|
strongSelf.containerNode.frame = CGRect(origin: CGPoint(), size: contentSize)
|
||||||
|
|
||||||
if strongSelf.textNode.textField.attributedPlaceholder == nil || !strongSelf.textNode.textField.attributedPlaceholder!.isEqual(to: attributedPlaceholderText) {
|
if strongSelf.textNode.textField.attributedPlaceholder == nil || !strongSelf.textNode.textField.attributedPlaceholder!.isEqual(to: attributedPlaceholderText) {
|
||||||
strongSelf.textNode.textField.attributedPlaceholder = attributedPlaceholderText
|
strongSelf.textNode.textField.attributedPlaceholder = attributedPlaceholderText
|
||||||
strongSelf.textNode.textField.accessibilityHint = attributedPlaceholderText.string
|
strongSelf.textNode.textField.accessibilityHint = attributedPlaceholderText.string
|
||||||
}
|
}
|
||||||
|
|
||||||
let iconFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - max(31.0, measureLayout.size.width)) / 2.0 - 28.0), y: floor((layout.contentSize.height - iconSize.height) / 2.0) - 3.0 + verticalOffset), size: iconSize)
|
inputFieldApply()
|
||||||
strongSelf.iconNode.updateLayout(size: iconFrame.size)
|
|
||||||
strongSelf.iconNode.frame = iconFrame
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -232,6 +272,7 @@ class WalletAmountItemNode: ListViewItemNode, UITextFieldDelegate, ItemListItemN
|
|||||||
|
|
||||||
@objc private func textFieldTextChanged(_ textField: UITextField) {
|
@objc private func textFieldTextChanged(_ textField: UITextField) {
|
||||||
self.textUpdated(self.textNode.textField.text ?? "")
|
self.textUpdated(self.textNode.textField.text ?? "")
|
||||||
|
self.updateInputField()
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc private func clearButtonPressed() {
|
@objc private func clearButtonPressed() {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import UIKit
|
import UIKit
|
||||||
import SwiftSignalKit
|
import SwiftSignalKit
|
||||||
|
import Display
|
||||||
import WalletCore
|
import WalletCore
|
||||||
|
|
||||||
public enum WalletContextGetServerSaltError {
|
public enum WalletContextGetServerSaltError {
|
||||||
@ -24,5 +25,5 @@ public protocol WalletContext {
|
|||||||
func shareUrl(_ url: String)
|
func shareUrl(_ url: String)
|
||||||
func openPlatformSettings()
|
func openPlatformSettings()
|
||||||
func authorizeAccessToCamera(completion: @escaping () -> Void)
|
func authorizeAccessToCamera(completion: @escaping () -> Void)
|
||||||
func pickImage(completion: @escaping (UIImage) -> Void)
|
func pickImage(present: @escaping (ViewController) -> Void, completion: @escaping (UIImage) -> Void)
|
||||||
}
|
}
|
||||||
|
@ -118,7 +118,9 @@ public final class WalletQrScanScreen: ViewController {
|
|||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
strongSelf.context.pickImage(completion: { image in
|
strongSelf.context.pickImage(present: { c in
|
||||||
|
strongSelf.push(c)
|
||||||
|
}, completion: { image in
|
||||||
let detector = CIDetector(ofType: CIDetectorTypeQRCode, context: nil, options: [CIDetectorAccuracy: CIDetectorAccuracyHigh])!
|
let detector = CIDetector(ofType: CIDetectorTypeQRCode, context: nil, options: [CIDetectorAccuracy: CIDetectorAccuracyHigh])!
|
||||||
if let ciImage = CIImage(image: image) {
|
if let ciImage = CIImage(image: image) {
|
||||||
var options: [String: Any]
|
var options: [String: Any]
|
||||||
|
@ -311,6 +311,7 @@ private final class WalletTransactionInfoScreenNode: ViewControllerTracingNode,
|
|||||||
self.navigationBackgroundNode.alpha = 0.0
|
self.navigationBackgroundNode.alpha = 0.0
|
||||||
self.navigationSeparatorNode = ASDisplayNode()
|
self.navigationSeparatorNode = ASDisplayNode()
|
||||||
self.navigationSeparatorNode.backgroundColor = self.presentationData.theme.navigationBar.separatorColor
|
self.navigationSeparatorNode.backgroundColor = self.presentationData.theme.navigationBar.separatorColor
|
||||||
|
self.navigationSeparatorNode.alpha = 0.0
|
||||||
|
|
||||||
self.scrollNode = ASScrollNode()
|
self.scrollNode = ASScrollNode()
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user