diff --git a/submodules/ChatListUI/Sources/Node/ChatListItem.swift b/submodules/ChatListUI/Sources/Node/ChatListItem.swift index 1fb071c560..e6664f5767 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListItem.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListItem.swift @@ -774,7 +774,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { return } if case let .peer(_, peer, _, _, _, _, _, _, promoInfo, _, _, _) = item.content { - if promoInfo == nil, let mainPeer = peer.chatMainPeer { + if promoInfo == nil, let mainPeer = peer.peer { item.interaction.togglePeerSelected(mainPeer) } } diff --git a/submodules/ChatListUI/Sources/Node/ChatListItemStrings.swift b/submodules/ChatListUI/Sources/Node/ChatListItemStrings.swift index 8cf12f0f1a..975abd65a2 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListItemStrings.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListItemStrings.swift @@ -100,7 +100,15 @@ public func chatListItemStrings(strings: PresentationStrings, nameDisplayOrder: textIsReady = true } case .generic: - break + var messageTypes = Set() + for message in messages { + messageTypes.insert(singleMessageType(message: message)) + } + if messageTypes.count == 2 && messageTypes.contains(.photos) && messageTypes.contains(.videos) { + if !messageText.isEmpty { + textIsReady = true + } + } } } diff --git a/submodules/Display/Source/TextNode.swift b/submodules/Display/Source/TextNode.swift index 3d36be6ece..a27360933f 100644 --- a/submodules/Display/Source/TextNode.swift +++ b/submodules/Display/Source/TextNode.swift @@ -6,9 +6,11 @@ import CoreText private let defaultFont = UIFont.systemFont(ofSize: 15.0) private final class TextNodeStrikethrough { + let range: NSRange let frame: CGRect - init(frame: CGRect) { + init(range: NSRange, frame: CGRect) { + self.range = range self.frame = frame } } @@ -990,7 +992,7 @@ public class TextNode: ASDisplayNode { let lowerX = floor(CTLineGetOffsetForStringIndex(coreTextLine, range.location, nil)) let upperX = ceil(CTLineGetOffsetForStringIndex(coreTextLine, range.location + range.length, nil)) let x = lowerX < upperX ? lowerX : upperX - strikethroughs.append(TextNodeStrikethrough(frame: CGRect(x: x, y: 0.0, width: abs(upperX - lowerX), height: fontLineHeight))) + strikethroughs.append(TextNodeStrikethrough(range: range, frame: CGRect(x: x, y: 0.0, width: abs(upperX - lowerX), height: fontLineHeight))) } else if let paragraphStyle = attributes[NSAttributedString.Key.paragraphStyle] as? NSParagraphStyle { headIndent = paragraphStyle.headIndent @@ -1042,7 +1044,7 @@ public class TextNode: ASDisplayNode { let lowerX = floor(CTLineGetOffsetForStringIndex(coreTextLine, range.location, nil)) let upperX = ceil(CTLineGetOffsetForStringIndex(coreTextLine, range.location + range.length, nil)) let x = lowerX < upperX ? lowerX : upperX - strikethroughs.append(TextNodeStrikethrough(frame: CGRect(x: x, y: 0.0, width: abs(upperX - lowerX), height: fontLineHeight))) + strikethroughs.append(TextNodeStrikethrough(range: range, frame: CGRect(x: x, y: 0.0, width: abs(upperX - lowerX), height: fontLineHeight))) } else if let paragraphStyle = attributes[NSAttributedString.Key.paragraphStyle] as? NSParagraphStyle { headIndent = paragraphStyle.headIndent } @@ -1190,6 +1192,15 @@ public class TextNode: ASDisplayNode { if !line.strikethroughs.isEmpty { for strikethrough in line.strikethroughs { + var textColor: UIColor? + layout.attributedString?.enumerateAttributes(in: NSMakeRange(line.range.location, line.range.length), options: []) { attributes, range, _ in + if range == strikethrough.range, let color = attributes[NSAttributedString.Key.foregroundColor] as? UIColor { + textColor = color + } + } + if let textColor = textColor { + context.setFillColor(textColor.cgColor) + } let frame = strikethrough.frame.offsetBy(dx: lineFrame.minX, dy: lineFrame.minY) context.fill(CGRect(x: frame.minX, y: frame.minY - 5.0, width: frame.width, height: 1.0)) } diff --git a/submodules/GalleryUI/Sources/ChatItemGalleryFooterContentNode.swift b/submodules/GalleryUI/Sources/ChatItemGalleryFooterContentNode.swift index 208f1af5e9..670d8c3af9 100644 --- a/submodules/GalleryUI/Sources/ChatItemGalleryFooterContentNode.swift +++ b/submodules/GalleryUI/Sources/ChatItemGalleryFooterContentNode.swift @@ -587,8 +587,12 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll } else if let media = media as? TelegramMediaFile, !media.isAnimated { for attribute in media.attributes { switch attribute { - case .Video: - canFullscreen = true + case let .Video(_, dimensions, _): + if dimensions.height > 0 { + if CGFloat(dimensions.width) / CGFloat(dimensions.height) > 1.33 { + canFullscreen = true + } + } default: break } @@ -1114,7 +1118,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll } var preferredAction = ShareControllerPreferredAction.default - var actionCompletionText: String = "" + var actionCompletionText: String? if let generalMessageContentKind = generalMessageContentKind { switch generalMessageContentKind { case .image: @@ -1164,6 +1168,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll } else if let image = content.image { subject = .media(.webPage(webPage: WebpageReference(webpage), media: image)) preferredAction = .saveToCameraRoll + actionCompletionText = strongSelf.presentationData.strings.Gallery_ImageSaved } } } else if let file = m as? TelegramMediaFile { @@ -1185,7 +1190,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll self?.interacting?(false) } shareController.actionCompleted = { [weak self] in - if let strongSelf = self { + if let strongSelf = self, let actionCompletionText = actionCompletionText { let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 } strongSelf.controllerInteraction?.presentController(UndoOverlayController(presentationData: presentationData, content: .mediaSaved(text: actionCompletionText), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), nil) } diff --git a/submodules/ListMessageItem/Sources/ListMessageFileItemNode.swift b/submodules/ListMessageItem/Sources/ListMessageFileItemNode.swift index e1cd8a7656..5abb11c1c7 100644 --- a/submodules/ListMessageItem/Sources/ListMessageFileItemNode.swift +++ b/submodules/ListMessageItem/Sources/ListMessageFileItemNode.swift @@ -899,6 +899,8 @@ public final class ListMessageFileItemNode: ListMessageNode { if isVoice { iconStatusBackgroundColor = item.presentationData.theme.theme.list.itemAccentColor iconStatusForegroundColor = item.presentationData.theme.theme.list.itemCheckColors.foregroundColor + } else if isAudio { + iconStatusForegroundColor = item.presentationData.theme.theme.list.itemCheckColors.foregroundColor } if !isAudio && !isInstantVideo { @@ -929,6 +931,7 @@ public final class ListMessageFileItemNode: ListMessageNode { } self.iconStatusNode.backgroundNodeColor = iconStatusBackgroundColor self.iconStatusNode.foregroundNodeColor = iconStatusForegroundColor + self.iconStatusNode.overlayForegroundNodeColor = .white self.iconStatusNode.transitionToState(iconStatusState) } diff --git a/submodules/PeerInfoUI/Sources/ChannelDiscussionGroupSetupController.swift b/submodules/PeerInfoUI/Sources/ChannelDiscussionGroupSetupController.swift index d0c546daef..a0102114e3 100644 --- a/submodules/PeerInfoUI/Sources/ChannelDiscussionGroupSetupController.swift +++ b/submodules/PeerInfoUI/Sources/ChannelDiscussionGroupSetupController.swift @@ -151,10 +151,10 @@ private enum ChannelDiscussionGroupSetupControllerEntry: ItemListNodeEntry { let text: String if let peer = peer as? TelegramChannel, let addressName = peer.addressName, !addressName.isEmpty { text = "@\(addressName)" - } else if let peer = peer as? TelegramChannel, case .group = peer.info { - text = strings.Channel_DiscussionGroup_PrivateGroup - } else { + } else if let peer = peer as? TelegramChannel, case .broadcast = peer.info { text = strings.Channel_DiscussionGroup_PrivateChannel + } else { + text = strings.Channel_DiscussionGroup_PrivateGroup } return ItemListPeerItem(presentationData: presentationData, dateTimeFormat: PresentationDateTimeFormat(), nameDisplayOrder: nameOrder, context: arguments.context, peer: peer, aliasHandling: .standard, nameStyle: .plain, presence: nil, text: .text(text, .secondary), label: .none, editing: ItemListPeerItemEditing(editable: false, editing: false, revealed: false), revealOptions: nil, switchValue: nil, enabled: true, selectable: true, sectionId: self.section, action: { arguments.selectGroup(peer.id) diff --git a/submodules/PhoneInputNode/Sources/PhoneInputNode.swift b/submodules/PhoneInputNode/Sources/PhoneInputNode.swift index 6d9662852b..ed3a8fd7ba 100644 --- a/submodules/PhoneInputNode/Sources/PhoneInputNode.swift +++ b/submodules/PhoneInputNode/Sources/PhoneInputNode.swift @@ -280,6 +280,9 @@ public final class PhoneInputNode: ASDisplayNode, UITextFieldDelegate { if !realRegionPrefix.hasPrefix("+") { realRegionPrefix = "+" + realRegionPrefix } + if !text.hasPrefix("+") { + text = "+" + text + } numberText = cleanPrefix(String(text[realRegionPrefix.endIndex...])) } else { realRegionPrefix = text diff --git a/submodules/SettingsUI/Sources/Themes/ThemeAccentColorController.swift b/submodules/SettingsUI/Sources/Themes/ThemeAccentColorController.swift index d701488a1f..bd212a9528 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeAccentColorController.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeAccentColorController.swift @@ -436,7 +436,7 @@ final class ThemeAccentColorController: ViewController { if case let .colors(initialThemeReference, true) = strongSelf.mode { let themeSpecificAccentColor = settings.themeSpecificAccentColors[themeReference.index] var customAccentColor: UIColor? - if let color = themeSpecificAccentColor?.color { + if let color = themeSpecificAccentColor?.color, color != .clear { accentColor = color customAccentColor = accentColor } else if case let .cloud(cloudTheme) = initialThemeReference, let settings = cloudTheme.theme.settings { diff --git a/submodules/ShareController/Sources/ShareController.swift b/submodules/ShareController/Sources/ShareController.swift index e917287c86..19c3b9effb 100644 --- a/submodules/ShareController/Sources/ShareController.swift +++ b/submodules/ShareController/Sources/ShareController.swift @@ -892,7 +892,7 @@ public final class ShareController: ViewController { } else { context = self.sharedContext.makeTempAccountContext(account: self.currentAccount) } - self.controllerNode.transitionToProgressWithValue(signal: SaveToCameraRoll.saveToCameraRoll(context: context, postbox: context.account.postbox, mediaReference: mediaReference) |> map(Optional.init)) + self.controllerNode.transitionToProgressWithValue(signal: SaveToCameraRoll.saveToCameraRoll(context: context, postbox: context.account.postbox, mediaReference: mediaReference) |> map(Optional.init), dismissImmediately: true) } private func switchToAccount(account: Account, animateIn: Bool) { diff --git a/submodules/TelegramCallsUI/Sources/VoiceChatController.swift b/submodules/TelegramCallsUI/Sources/VoiceChatController.swift index f2a5171029..82adac7ae7 100644 --- a/submodules/TelegramCallsUI/Sources/VoiceChatController.swift +++ b/submodules/TelegramCallsUI/Sources/VoiceChatController.swift @@ -1851,7 +1851,7 @@ public final class VoiceChatController: ViewController { self.listContainer.addSubnode(self.topCornersNode) self.contentContainer.addSubnode(self.bottomGradientNode) self.contentContainer.addSubnode(self.bottomPanelBackgroundNode) - self.contentContainer.addSubnode(self.participantsNode) +// self.contentContainer.addSubnode(self.participantsNode) self.contentContainer.addSubnode(self.tileGridNode) self.contentContainer.addSubnode(self.mainStageContainerNode) self.contentContainer.addSubnode(self.transitionContainerNode) @@ -1975,7 +1975,6 @@ public final class VoiceChatController: ViewController { } }) - let titleAndRecording: Signal<(String?, Bool), NoError> = self.call.state |> map { state -> (String?, Bool) in return (state.title, state.recordingStartTimestamp != nil) @@ -1993,7 +1992,7 @@ public final class VoiceChatController: ViewController { } else { isLivestream = false } - strongSelf.participantsNode.isHidden = !isLivestream + strongSelf.participantsNode.isHidden = !isLivestream || strongSelf.isScheduled strongSelf.peer = peer strongSelf.currentTitleIsCustom = title != nil @@ -5020,12 +5019,12 @@ public final class VoiceChatController: ViewController { displayPanelVideos = self.displayPanelVideos } - let isLivestream: Bool - if let channel = self.peer as? TelegramChannel, case .broadcast = channel.info { - isLivestream = true - } else { - isLivestream = false - } +// let isLivestream: Bool +// if let channel = self.peer as? TelegramChannel, case .broadcast = channel.info { +// isLivestream = true +// } else { +// isLivestream = false +// } let canManageCall = self.callState?.canManageCall ?? false @@ -5042,9 +5041,9 @@ public final class VoiceChatController: ViewController { let memberState: VoiceChatPeerEntry.State var memberMuteState: GroupCallParticipantsContext.Participant.MuteState? if member.hasRaiseHand && !(member.muteState?.canUnmute ?? true) { - if isLivestream && !canManageCall { - continue - } +// if isLivestream && !canManageCall { +// continue +// } memberState = .raisedHand memberMuteState = member.muteState @@ -5081,9 +5080,9 @@ public final class VoiceChatController: ViewController { self.raisedHandDisplayDisposables[member.peer.id] = nil } - if isLivestream && !(memberMuteState?.canUnmute ?? true) { - continue - } +// if isLivestream && !(memberMuteState?.canUnmute ?? true) { +// continue +// } } var memberPeer = member.peer diff --git a/submodules/TelegramCore/Sources/Utils/CanSendMessagesToPeer.swift b/submodules/TelegramCore/Sources/Utils/CanSendMessagesToPeer.swift index ce09be6037..d47364a00b 100644 --- a/submodules/TelegramCore/Sources/Utils/CanSendMessagesToPeer.swift +++ b/submodules/TelegramCore/Sources/Utils/CanSendMessagesToPeer.swift @@ -7,7 +7,9 @@ private final class LinkHelperClass: NSObject { } public func canSendMessagesToPeer(_ peer: Peer) -> Bool { - if peer is TelegramUser || peer is TelegramGroup { + if let peer = peer as? TelegramUser, peer.username == "replies" { + return false + } else if peer is TelegramUser || peer is TelegramGroup { return !peer.isDeleted } else if let peer = peer as? TelegramSecretChat { return peer.embeddedState == .active diff --git a/submodules/TelegramPresentationData/Sources/DefaultDarkPresentationTheme.swift b/submodules/TelegramPresentationData/Sources/DefaultDarkPresentationTheme.swift index ada7119ead..3f546a860d 100644 --- a/submodules/TelegramPresentationData/Sources/DefaultDarkPresentationTheme.swift +++ b/submodules/TelegramPresentationData/Sources/DefaultDarkPresentationTheme.swift @@ -59,6 +59,11 @@ public func customizeDefaultDarkPresentationTheme(theme: PresentationTheme, edit } else { bubbleColors = [accentColor.withMultiplied(hue: 0.966, saturation: 0.61, brightness: 0.98).rgb, accentColor.rgb] } + } else { + let accentColor = accentColor ?? UIColor(rgb: 0xffffff) + if accentColor.rgb == 0xffffff { + monochrome = true + } } var badgeFillColor: UIColor? diff --git a/submodules/TelegramPresentationData/Sources/MakePresentationTheme.swift b/submodules/TelegramPresentationData/Sources/MakePresentationTheme.swift index 6c2104cde2..61cbbd19d9 100644 --- a/submodules/TelegramPresentationData/Sources/MakePresentationTheme.swift +++ b/submodules/TelegramPresentationData/Sources/MakePresentationTheme.swift @@ -47,6 +47,10 @@ public func makePresentationTheme(cloudTheme: TelegramTheme) -> PresentationThem } public func makePresentationTheme(mediaBox: MediaBox, themeReference: PresentationThemeReference, extendingThemeReference: PresentationThemeReference? = nil, accentColor: UIColor? = nil, outgoingAccentColor: UIColor? = nil, backgroundColors: [UInt32] = [], bubbleColors: [UInt32] = [], animateBubbleColors: Bool? = nil, wallpaper: TelegramWallpaper? = nil, baseColor: PresentationThemeBaseColor? = nil, serviceBackgroundColor: UIColor? = nil, preview: Bool = false) -> PresentationTheme? { + var accentColor = accentColor + if accentColor == .clear { + accentColor = nil + } let theme: PresentationTheme switch themeReference { case let .builtin(reference): diff --git a/submodules/TelegramStringFormatting/Sources/ServiceMessageStrings.swift b/submodules/TelegramStringFormatting/Sources/ServiceMessageStrings.swift index 38f10a80b6..a5fe448ce0 100644 --- a/submodules/TelegramStringFormatting/Sources/ServiceMessageStrings.swift +++ b/submodules/TelegramStringFormatting/Sources/ServiceMessageStrings.swift @@ -281,12 +281,20 @@ public func universalServiceMessageString(presentationData: (PresentationTheme, string = strings.Conversation_AutoremoveTimerSetUser(authorString, timeValue).string } } else if let _ = messagePeer as? TelegramGroup { - string = strings.Conversation_AutoremoveTimerSetGroup(timeValue).string - } else if let channel = messagePeer as? TelegramChannel { - if case .group = channel.info { - string = strings.Conversation_AutoremoveTimerSetGroup(timeValue).string + if message.author?.id == accountPeerId { + string = strings.Conversation_AutoremoveTimerSetUserYou(timeValue).string } else { - string = strings.Conversation_AutoremoveTimerSetChannel(timeValue).string + string = strings.Conversation_AutoremoveTimerSetGroup(timeValue).string + } + } else if let channel = messagePeer as? TelegramChannel { + if message.author?.id == accountPeerId { + string = strings.Conversation_AutoremoveTimerSetUserYou(timeValue).string + } else { + if case .group = channel.info { + string = strings.Conversation_AutoremoveTimerSetGroup(timeValue).string + } else { + string = strings.Conversation_AutoremoveTimerSetChannel(timeValue).string + } } } else { if message.author?.id == accountPeerId { diff --git a/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift index 83a217fa33..0b7bc0e661 100644 --- a/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift @@ -797,6 +797,10 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { isMediaEnabled = false } } + var isRecording = false + if let _ = interfaceState.inputTextPanelState.mediaRecordingState { + isRecording = true + } var isScheduledMessages = false if case .scheduledMessages = interfaceState.subject { @@ -811,7 +815,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { } } transition.updateAlpha(layer: self.attachmentButton.layer, alpha: isMediaEnabled ? 1.0 : 0.4) - self.attachmentButton.isEnabled = isMediaEnabled + self.attachmentButton.isEnabled = isMediaEnabled && !isRecording self.attachmentButton.accessibilityTraits = (!isSlowmodeActive || isMediaEnabled) ? [.button] : [.button, .notEnabled] self.attachmentButtonDisabledNode.isHidden = !isSlowmodeActive || isMediaEnabled @@ -840,6 +844,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { if self.theme == nil || !self.theme!.chat.inputPanel.inputTextColor.isEqual(interfaceState.theme.chat.inputPanel.inputTextColor) { let textColor = interfaceState.theme.chat.inputPanel.inputTextColor + let tintColor = interfaceState.theme.list.itemAccentColor let baseFontSize = max(minInputFontSize, interfaceState.fontSize.baseDisplaySize) if let textInputNode = self.textInputNode { @@ -849,6 +854,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { textInputNode.selectedRange = range } textInputNode.typingAttributes = [NSAttributedString.Key.font.rawValue: Font.regular(baseFontSize), NSAttributedString.Key.foregroundColor.rawValue: textColor] + textInputNode.tintColor = tintColor } } diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoHeaderNode.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoHeaderNode.swift index 758a112568..2816c073f6 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoHeaderNode.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoHeaderNode.swift @@ -2009,13 +2009,25 @@ final class PeerInfoHeaderNode: ASDisplayNode { } if let peer = peer { + var title: String if peer.id == self.context.account.peerId && !self.isSettings { - titleString = NSAttributedString(string: presentationData.strings.Conversation_SavedMessages, font: Font.semibold(24.0), textColor: presentationData.theme.list.itemPrimaryTextColor) + title = presentationData.strings.Conversation_SavedMessages } else if peer.id == self.context.account.peerId && !self.isSettings { - titleString = NSAttributedString(string: presentationData.strings.DialogList_Replies, font: Font.semibold(24.0), textColor: presentationData.theme.list.itemPrimaryTextColor) + title = presentationData.strings.DialogList_Replies } else { - titleString = NSAttributedString(string: peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), font: Font.semibold(24.0), textColor: presentationData.theme.list.itemPrimaryTextColor) + title = peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder) } + title = title.replacingOccurrences(of: "\u{1160}", with: "").replacingOccurrences(of: "\u{3164}", with: "") + if title.isEmpty { + if let peer = peer as? TelegramUser, let phone = peer.phone { + title = formatPhoneNumber(phone) + } else if let addressName = peer.addressName { + title = "@\(addressName)" + } else { + title = " " + } + } + titleString = NSAttributedString(string: title, font: Font.semibold(24.0), textColor: presentationData.theme.list.itemPrimaryTextColor) if self.isSettings, let user = peer as? TelegramUser { let formattedPhone = formatPhoneNumber(user.phone ?? "")