From 2bbbc85093d00ede465d56e3fb197a4ace827092 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Tue, 26 Feb 2019 23:37:09 +0400 Subject: [PATCH] Various UI fixes --- TelegramUI/CallFeedbackController.swift | 2 +- TelegramUI/CallListCallItem.swift | 6 +-- .../ChatPlayingActivityContentNode.swift | 7 +-- ...hatRecordingVideoActivityContentNode.swift | 7 +-- ...hatRecordingVoiceActivityContentNode.swift | 7 +-- TelegramUI/ChatTitleActivityNode.swift | 17 +++++-- TelegramUI/ChatTitleView.swift | 26 +++++------ .../ChatTypingActivityContentNode.swift | 7 +-- .../ChatUploadingActivityContentNode.swift | 19 ++++---- TelegramUI/InstantPageController.swift | 13 +++++- TelegramUI/InstantPageControllerNode.swift | 9 ++-- TelegramUI/InstantPageTheme.swift | 16 +++++-- TelegramUI/InviteContactsControllerNode.swift | 16 ++++++- TelegramUI/ItemListRevealOptionsNode.swift | 44 +++++++++++++++++-- TelegramUI/PhotoResources.swift | 24 +++++----- TelegramUI/PresentationData.swift | 2 +- TelegramUI/SearchBarPlaceholderNode.swift | 2 +- 17 files changed, 155 insertions(+), 69 deletions(-) diff --git a/TelegramUI/CallFeedbackController.swift b/TelegramUI/CallFeedbackController.swift index 126936dfd8..314036ced2 100644 --- a/TelegramUI/CallFeedbackController.swift +++ b/TelegramUI/CallFeedbackController.swift @@ -234,7 +234,7 @@ public func callFeedbackController(sharedContext: SharedAccountContext, account: let signal = combineLatest(sharedContext.presentationData, statePromise.get()) |> deliverOnMainQueue |> map { presentationData, state -> (ItemListControllerState, (ItemListNodeState, CallFeedbackControllerEntry.ItemGenerationArguments)) in - let leftNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Cancel), style: .bold, enabled: true, action: { + let leftNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Cancel), style: .regular, enabled: true, action: { dismissImpl?() }) let rightNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.CallFeedback_Send), style: .bold, enabled: true, action: { diff --git a/TelegramUI/CallListCallItem.swift b/TelegramUI/CallListCallItem.swift index d7e9334a72..575a30b129 100644 --- a/TelegramUI/CallListCallItem.swift +++ b/TelegramUI/CallListCallItem.swift @@ -628,11 +628,11 @@ class CallListCallItemNode: ItemListRevealOptionsItemNode { infoIconRightInset -= 36.0 } - transition.updateFrame(node: self.avatarNode, frame: CGRect(origin: CGPoint(x: revealOffset + leftInset - 52.0, y: 8.0), size: CGSize(width: 40.0, height: 40.0))) + transition.updateFrame(node: self.avatarNode, frame: CGRect(origin: CGPoint(x: revealOffset + leftInset - 52.0, y: 5.0), size: CGSize(width: 40.0, height: 40.0))) - transition.updateFrame(node: self.titleNode, frame: CGRect(origin: CGPoint(x: revealOffset + leftInset, y: 8.0), size: self.titleNode.bounds.size)) + transition.updateFrame(node: self.titleNode, frame: CGRect(origin: CGPoint(x: revealOffset + leftInset, y: 6.0), size: self.titleNode.bounds.size)) - transition.updateFrame(node: self.statusNode, frame: CGRect(origin: CGPoint(x: revealOffset + leftInset, y: 30.0), size: self.statusNode.bounds.size)) + transition.updateFrame(node: self.statusNode, frame: CGRect(origin: CGPoint(x: revealOffset + leftInset, y: 27.0), size: self.statusNode.bounds.size)) transition.updateFrame(node: self.dateNode, frame: CGRect(origin: CGPoint(x: editingOffset + revealOffset + self.bounds.size.width - dateRightInset - self.dateNode.bounds.size.width, y: self.dateNode.frame.minY), size: self.dateNode.bounds.size)) diff --git a/TelegramUI/ChatPlayingActivityContentNode.swift b/TelegramUI/ChatPlayingActivityContentNode.swift index 98d4b4c370..95c322359a 100644 --- a/TelegramUI/ChatPlayingActivityContentNode.swift +++ b/TelegramUI/ChatPlayingActivityContentNode.swift @@ -102,12 +102,13 @@ class ChatPlayingActivityContentNode: ChatTitleActivityContentNode { override func updateLayout(_ constrainedSize: CGSize, alignment: NSTextAlignment) -> CGSize { let size = self.textNode.updateLayout(constrainedSize) let indicatorSize = CGSize(width: 24.0, height: 16.0) - self.textNode.bounds = CGRect(origin: CGPoint(), size: size) + let originX: CGFloat if case .center = alignment { - self.textNode.position = CGPoint(x: indicatorSize.width / 2.0, y: size.height / 2.0) + originX = floorToScreenPixels((indicatorSize.width - size.width) / 2.0) } else { - self.textNode.position = CGPoint(x: indicatorSize.width + size.width / 2.0, y: size.height / 2.0) + originX = indicatorSize.width } + self.textNode.frame = CGRect(origin: CGPoint(x: originX, y: 0.0), size: size) self.indicatorNode.frame = CGRect(origin: CGPoint(x: self.textNode.frame.minX - indicatorSize.width, y: 0.0), size: indicatorSize) return CGSize(width: size.width + indicatorSize.width, height: size.height) } diff --git a/TelegramUI/ChatRecordingVideoActivityContentNode.swift b/TelegramUI/ChatRecordingVideoActivityContentNode.swift index db23ccf050..add3cc25c5 100644 --- a/TelegramUI/ChatRecordingVideoActivityContentNode.swift +++ b/TelegramUI/ChatRecordingVideoActivityContentNode.swift @@ -74,12 +74,13 @@ class ChatRecordingVideoActivityContentNode: ChatTitleActivityContentNode { override func updateLayout(_ constrainedSize: CGSize, alignment: NSTextAlignment) -> CGSize { let size = self.textNode.updateLayout(constrainedSize) let indicatorSize = CGSize(width: 24.0, height: 16.0) - self.textNode.bounds = CGRect(origin: CGPoint(), size: size) + let originX: CGFloat if case .center = alignment { - self.textNode.position = CGPoint(x: indicatorSize.width / 2.0, y: size.height / 2.0) + originX = floorToScreenPixels((indicatorSize.width - size.width) / 2.0) } else { - self.textNode.position = CGPoint(x: indicatorSize.width + size.width / 2.0, y: size.height / 2.0) + originX = indicatorSize.width } + self.textNode.frame = CGRect(origin: CGPoint(x: originX, y: 0.0), size: size) self.indicatorNode.frame = CGRect(origin: CGPoint(x: self.textNode.frame.minX - indicatorSize.width, y: 0.0), size: indicatorSize) return CGSize(width: size.width + indicatorSize.width, height: size.height) } diff --git a/TelegramUI/ChatRecordingVoiceActivityContentNode.swift b/TelegramUI/ChatRecordingVoiceActivityContentNode.swift index bb379a2928..e3e96471c3 100644 --- a/TelegramUI/ChatRecordingVoiceActivityContentNode.swift +++ b/TelegramUI/ChatRecordingVoiceActivityContentNode.swift @@ -92,12 +92,13 @@ class ChatRecordingVoiceActivityContentNode: ChatTitleActivityContentNode { override func updateLayout(_ constrainedSize: CGSize, alignment: NSTextAlignment) -> CGSize { let size = self.textNode.updateLayout(constrainedSize) let indicatorSize = CGSize(width: 24.0, height: 16.0) - self.textNode.bounds = CGRect(origin: CGPoint(), size: size) + let originX: CGFloat if case .center = alignment { - self.textNode.position = CGPoint(x: indicatorSize.width / 2.0, y: size.height / 2.0) + originX = floorToScreenPixels((indicatorSize.width - size.width) / 2.0) } else { - self.textNode.position = CGPoint(x: indicatorSize.width + size.width / 2.0, y: size.height / 2.0) + originX = indicatorSize.width } + self.textNode.frame = CGRect(origin: CGPoint(x: originX, y: 0.0), size: size) self.indicatorNode.frame = CGRect(origin: CGPoint(x: self.textNode.frame.minX - indicatorSize.width, y: 0.0), size: indicatorSize) return CGSize(width: size.width + indicatorSize.width, height: size.height) } diff --git a/TelegramUI/ChatTitleActivityNode.swift b/TelegramUI/ChatTitleActivityNode.swift index 2b09f0f181..1dfe5c82e6 100644 --- a/TelegramUI/ChatTitleActivityNode.swift +++ b/TelegramUI/ChatTitleActivityNode.swift @@ -8,9 +8,15 @@ public enum ChatTitleActivityAnimationStyle { case slide } +public enum ChatTitleActivityInfoType { + case online + case lastSeenTime + case generic +} + public enum ChatTitleActivityNodeState: Equatable { case none - case info(NSAttributedString) + case info(NSAttributedString, ChatTitleActivityInfoType) case typingText(NSAttributedString, UIColor) case uploading(NSAttributedString, UIColor) case recordingVoice(NSAttributedString, UIColor) @@ -21,7 +27,7 @@ public enum ChatTitleActivityNodeState: Equatable { switch self { case .none: return nil - case let .info(text): + case let .info(text, _): return ChatTitleActivityContentNode(text: text) case let .typingText(text, color): return ChatTypingActivityContentNode(text: text, color: color) @@ -37,7 +43,7 @@ public enum ChatTitleActivityNodeState: Equatable { } var string: String? { - if case let .info(text) = self { + if case let .info(text, _) = self { return text.string } return nil @@ -76,6 +82,11 @@ class ChatTitleActivityNode: ASDisplayNode { self.addSubnode(contentNode) } } else { + var animation = animation + if case let .info(_, fromType) = fromState, case let .info(_, toType) = state, fromType == toType { + animation = .none + } + self.contentNode = node if let contentNode = self.contentNode { self.addSubnode(contentNode) diff --git a/TelegramUI/ChatTitleView.swift b/TelegramUI/ChatTitleView.swift index be981038b6..5213ef7d35 100644 --- a/TelegramUI/ChatTitleView.swift +++ b/TelegramUI/ChatTitleView.swift @@ -301,21 +301,21 @@ final class ChatTitleView: UIView, NavigationBarTitleView { if let peer = peerViewMainPeer(peerView) { if peer.id == self.account.peerId { let string = NSAttributedString(string: "", font: Font.regular(13.0), textColor: self.theme.rootController.navigationBar.secondaryTextColor) - state = .info(string) + state = .info(string, .generic) } else if let user = peer as? TelegramUser { if user.id.namespace == Namespaces.Peer.CloudUser && user.id.id == 777000 { let string = NSAttributedString(string: "", font: Font.regular(13.0), textColor: self.theme.rootController.navigationBar.secondaryTextColor) - state = .info(string) + state = .info(string, .generic) } else if user.flags.contains(.isSupport) { let statusText = self.strings.Bot_GenericSupportStatus let string = NSAttributedString(string: statusText, font: Font.regular(13.0), textColor: self.theme.rootController.navigationBar.secondaryTextColor) - state = .info(string) + state = .info(string, .generic) } else if let _ = user.botInfo { let statusText = self.strings.Bot_GenericBotStatus let string = NSAttributedString(string: statusText, font: Font.regular(13.0), textColor: self.theme.rootController.navigationBar.secondaryTextColor) - state = .info(string) + state = .info(string, .generic) } else if let peer = peerViewMainPeer(peerView) { let timestamp = CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970 let userPresence: TelegramUserPresence @@ -327,10 +327,10 @@ final class ChatTitleView: UIView, NavigationBarTitleView { } let (string, activity) = stringAndActivityForUserPresence(strings: self.strings, dateTimeFormat: self.dateTimeFormat, presence: userPresence, relativeTo: Int32(timestamp)) let attributedString = NSAttributedString(string: string, font: Font.regular(13.0), textColor: activity ? self.theme.rootController.navigationBar.accentTextColor : self.theme.rootController.navigationBar.secondaryTextColor) - state = .info(attributedString) + state = .info(attributedString, activity ? .online : .lastSeenTime) } else { let string = NSAttributedString(string: "", font: Font.regular(13.0), textColor: self.theme.rootController.navigationBar.secondaryTextColor) - state = .info(string) + state = .info(string, .generic) } } else if let group = peer as? TelegramGroup { var onlineCount = 0 @@ -353,10 +353,10 @@ final class ChatTitleView: UIView, NavigationBarTitleView { string.append(NSAttributedString(string: "\(strings.Conversation_StatusMembers(Int32(group.participantCount))), ", font: Font.regular(13.0), textColor: self.theme.rootController.navigationBar.secondaryTextColor)) string.append(NSAttributedString(string: strings.Conversation_StatusOnline(Int32(onlineCount)), font: Font.regular(13.0), textColor: self.theme.rootController.navigationBar.secondaryTextColor)) - state = .info(string) + state = .info(string, .generic) } else { let string = NSAttributedString(string: strings.Conversation_StatusMembers(Int32(group.participantCount)), font: Font.regular(13.0), textColor: self.theme.rootController.navigationBar.secondaryTextColor) - state = .info(string) + state = .info(string, .generic) } } else if let channel = peer as? TelegramChannel { if let cachedChannelData = peerView.cachedData as? CachedChannelData, let memberCount = cachedChannelData.participantsSummary.memberCount { @@ -367,14 +367,14 @@ final class ChatTitleView: UIView, NavigationBarTitleView { } else { string = NSAttributedString(string: strings.Channel_Status, font: Font.regular(13.0), textColor: self.theme.rootController.navigationBar.secondaryTextColor) } - state = .info(string) + state = .info(string, .generic) } else { if case .group = channel.info, let onlineMemberCount = onlineMemberCount, onlineMemberCount > 1 { let string = NSMutableAttributedString() string.append(NSAttributedString(string: "\(strings.Conversation_StatusMembers(Int32(memberCount))), ", font: Font.regular(13.0), textColor: self.theme.rootController.navigationBar.secondaryTextColor)) string.append(NSAttributedString(string: strings.Conversation_StatusOnline(Int32(onlineMemberCount)), font: Font.regular(13.0), textColor: self.theme.rootController.navigationBar.secondaryTextColor)) - state = .info(string) + state = .info(string, .generic) } else { let membersString: String if case .group = channel.info { @@ -383,17 +383,17 @@ final class ChatTitleView: UIView, NavigationBarTitleView { membersString = strings.Conversation_StatusSubscribers(memberCount) } let string = NSAttributedString(string: membersString, font: Font.regular(13.0), textColor: self.theme.rootController.navigationBar.secondaryTextColor) - state = .info(string) + state = .info(string, .generic) } } } else { switch channel.info { case .group: let string = NSAttributedString(string: strings.Group_Status, font: Font.regular(13.0), textColor: self.theme.rootController.navigationBar.secondaryTextColor) - state = .info(string) + state = .info(string, .generic) case .broadcast: let string = NSAttributedString(string: strings.Channel_Status, font: Font.regular(13.0), textColor: self.theme.rootController.navigationBar.secondaryTextColor) - state = .info(string) + state = .info(string, .generic) } } } diff --git a/TelegramUI/ChatTypingActivityContentNode.swift b/TelegramUI/ChatTypingActivityContentNode.swift index b89300385e..0f33646368 100644 --- a/TelegramUI/ChatTypingActivityContentNode.swift +++ b/TelegramUI/ChatTypingActivityContentNode.swift @@ -109,12 +109,13 @@ class ChatTypingActivityContentNode: ChatTitleActivityContentNode { override func updateLayout(_ constrainedSize: CGSize, alignment: NSTextAlignment) -> CGSize { let size = self.textNode.updateLayout(constrainedSize) let indicatorSize = CGSize(width: 24.0, height: 16.0) - self.textNode.bounds = CGRect(origin: CGPoint(), size: size) + let originX: CGFloat if case .center = alignment { - self.textNode.position = CGPoint(x: indicatorSize.width / 2.0, y: size.height / 2.0) + originX = floorToScreenPixels((indicatorSize.width - size.width) / 2.0) } else { - self.textNode.position = CGPoint(x: indicatorSize.width + size.width / 2.0, y: size.height / 2.0) + originX = indicatorSize.width } + self.textNode.frame = CGRect(origin: CGPoint(x: originX, y: 0.0), size: size) self.indicatorNode.frame = CGRect(origin: CGPoint(x: self.textNode.frame.minX - indicatorSize.width, y: floorToScreenPixels((size.height - indicatorSize.height) / 2.0)), size: indicatorSize) return CGSize(width: size.width + indicatorSize.width, height: size.height) } diff --git a/TelegramUI/ChatUploadingActivityContentNode.swift b/TelegramUI/ChatUploadingActivityContentNode.swift index bf04d79d40..2a8084059e 100644 --- a/TelegramUI/ChatUploadingActivityContentNode.swift +++ b/TelegramUI/ChatUploadingActivityContentNode.swift @@ -47,20 +47,18 @@ private class ChatUploadingActivityIndicatorNode: ChatTitleActivityIndicatorNode return } - let origin = CGPoint(x: 11.0 / 2.0 - 1.0, y: 21.0 / 2.0 + 1.0) - let size = CGSize(width: 26.0 / 2.0, height: 8.0 / 2.0) + let origin = CGPoint(x: 4.0 + UIScreenPixel, y: 7.0) + let size = CGSize(width: 13.0, height: 4.0) let radius: CGFloat = 1.25 - var dotsColor = parameters.color + var dotsColor = parameters.color.withAlphaComponent(0.3) context.setFillColor(dotsColor.cgColor) var path = UIBezierPath(roundedRect: CGRect(origin: origin, size: size), cornerRadius: radius) path.fill(with: .normal, alpha: 1.0) + path.addClip() - dotsColor = parameters.color.withAlphaComponent(0.3) - context.setFillColor(dotsColor.cgColor) - - let progress = interpolate(from: 0.0, to: size.width, value: parameters.progress) + let progress = interpolate(from: 0.0, to: size.width * 2.0, value: parameters.progress) dotsColor = parameters.color context.setFillColor(dotsColor.cgColor) @@ -84,12 +82,13 @@ class ChatUploadingActivityContentNode: ChatTitleActivityContentNode { override func updateLayout(_ constrainedSize: CGSize, alignment: NSTextAlignment) -> CGSize { let size = self.textNode.updateLayout(constrainedSize) let indicatorSize = CGSize(width: 24.0, height: 16.0) - self.textNode.bounds = CGRect(origin: CGPoint(), size: size) + let originX: CGFloat if case .center = alignment { - self.textNode.position = CGPoint(x: indicatorSize.width / 2.0, y: size.height / 2.0) + originX = floorToScreenPixels((indicatorSize.width - size.width) / 2.0) } else { - self.textNode.position = CGPoint(x: indicatorSize.width + size.width / 2.0, y: size.height / 2.0) + originX = indicatorSize.width } + self.textNode.frame = CGRect(origin: CGPoint(x: originX, y: 0.0), size: size) self.indicatorNode.frame = CGRect(origin: CGPoint(x: self.textNode.frame.minX - indicatorSize.width, y: 0.0), size: indicatorSize) return CGSize(width: size.width + indicatorSize.width, height: size.height) } diff --git a/TelegramUI/InstantPageController.swift b/TelegramUI/InstantPageController.swift index 8057c0f4be..a410a4d90e 100644 --- a/TelegramUI/InstantPageController.swift +++ b/TelegramUI/InstantPageController.swift @@ -24,6 +24,7 @@ final class InstantPageController: ViewController { private var settings: InstantPagePresentationSettings? private var settingsDisposable: Disposable? + private var themeSettings: PresentationThemeSettings? init(context: AccountContext, webPage: TelegramMediaWebpage, anchor: String? = nil) { self.context = context @@ -45,7 +46,7 @@ final class InstantPageController: ViewController { } }) - self.settingsDisposable = (self.context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.instantPagePresentationSettings]) + self.settingsDisposable = (self.context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.instantPagePresentationSettings, ApplicationSpecificSharedDataKeys.presentationThemeSettings]) |> deliverOnMainQueue).start(next: { [weak self] sharedData in if let strongSelf = self { let settings: InstantPagePresentationSettings @@ -54,7 +55,15 @@ final class InstantPageController: ViewController { } else { settings = InstantPagePresentationSettings.defaultSettings } + let themeSettings: PresentationThemeSettings + if let current = sharedData.entries[ApplicationSpecificSharedDataKeys.presentationThemeSettings] as? PresentationThemeSettings { + themeSettings = current + } else { + themeSettings = PresentationThemeSettings.defaultSettings + } + strongSelf.settings = settings + strongSelf.themeSettings = themeSettings if strongSelf.isNodeLoaded { strongSelf.controllerNode.update(settings: settings, strings: strongSelf.presentationData.strings) } @@ -76,7 +85,7 @@ final class InstantPageController: ViewController { } override public func loadDisplayNode() { - self.displayNode = InstantPageControllerNode(context: self.context, settings: self.settings, presentationTheme: self.presentationData.theme, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, statusBar: self.statusBar, getNavigationController: { [weak self] in + self.displayNode = InstantPageControllerNode(context: self.context, settings: self.settings, themeSettings: self.themeSettings, presentationTheme: self.presentationData.theme, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, statusBar: self.statusBar, getNavigationController: { [weak self] in return self?.navigationController as? NavigationController }, present: { [weak self] c, a in self?.present(c, in: .window(.root), with: a) diff --git a/TelegramUI/InstantPageControllerNode.swift b/TelegramUI/InstantPageControllerNode.swift index 0ff812d50e..cf40e779d6 100644 --- a/TelegramUI/InstantPageControllerNode.swift +++ b/TelegramUI/InstantPageControllerNode.swift @@ -9,6 +9,7 @@ import SafariServices final class InstantPageControllerNode: ASDisplayNode, UIScrollViewDelegate { private let context: AccountContext private var settings: InstantPagePresentationSettings? + private var themeSettings: PresentationThemeSettings? private var presentationTheme: PresentationTheme private var strings: PresentationStrings private var dateTimeFormat: PresentationDateTimeFormat @@ -73,7 +74,7 @@ final class InstantPageControllerNode: ASDisplayNode, UIScrollViewDelegate { return InstantPageStoredState(contentOffset: Double(self.scrollNode.view.contentOffset.y), details: details) } - init(context: AccountContext, settings: InstantPagePresentationSettings?, presentationTheme: PresentationTheme, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, statusBar: StatusBar, getNavigationController: @escaping () -> NavigationController?, present: @escaping (ViewController, Any?) -> Void, pushController: @escaping (ViewController) -> Void, openPeer: @escaping (PeerId) -> Void, navigateBack: @escaping () -> Void) { + init(context: AccountContext, settings: InstantPagePresentationSettings?, themeSettings: PresentationThemeSettings?, presentationTheme: PresentationTheme, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, statusBar: StatusBar, getNavigationController: @escaping () -> NavigationController?, present: @escaping (ViewController, Any?) -> Void, pushController: @escaping (ViewController) -> Void, openPeer: @escaping (PeerId) -> Void, navigateBack: @escaping () -> Void) { self.context = context self.presentationTheme = presentationTheme self.dateTimeFormat = dateTimeFormat @@ -82,7 +83,7 @@ final class InstantPageControllerNode: ASDisplayNode, UIScrollViewDelegate { let themeReferenceDate = Date() self.themeReferenceDate = themeReferenceDate self.theme = settings.flatMap { settings in - return instantPageThemeForType(instantPageThemeTypeForSettingsAndTime(presentationTheme: presentationTheme, settings: settings, time: themeReferenceDate), settings: settings) + return instantPageThemeForType(instantPageThemeTypeForSettingsAndTime(themeSettings: themeSettings, settings: settings, time: themeReferenceDate), settings: settings) } self.statusBar = statusBar @@ -159,7 +160,7 @@ final class InstantPageControllerNode: ASDisplayNode, UIScrollViewDelegate { } self.settings = settings - let themeType = instantPageThemeTypeForSettingsAndTime(presentationTheme: self.presentationTheme, settings: settings, time: self.themeReferenceDate) + let themeType = instantPageThemeTypeForSettingsAndTime(themeSettings: self.themeSettings, settings: settings, time: self.themeReferenceDate) let theme = instantPageThemeForType(themeType, settings: settings) self.theme = theme self.strings = strings @@ -1304,7 +1305,7 @@ final class InstantPageControllerNode: ASDisplayNode, UIScrollViewDelegate { return } if self.settingsNode == nil { - let settingsNode = InstantPageSettingsNode(strings: self.strings, settings: settings, currentThemeType: instantPageThemeTypeForSettingsAndTime(presentationTheme: self.presentationTheme, settings: settings, time: self.themeReferenceDate), applySettings: { [weak self] settings in + let settingsNode = InstantPageSettingsNode(strings: self.strings, settings: settings, currentThemeType: instantPageThemeTypeForSettingsAndTime(themeSettings: self.themeSettings, settings: settings, time: self.themeReferenceDate), applySettings: { [weak self] settings in if let strongSelf = self { strongSelf.update(settings: settings, strings: strongSelf.strings) let _ = updateInstantPagePresentationSettingsInteractively(accountManager: strongSelf.context.sharedContext.accountManager, { _ in diff --git a/TelegramUI/InstantPageTheme.swift b/TelegramUI/InstantPageTheme.swift index e4142f9046..397037994b 100644 --- a/TelegramUI/InstantPageTheme.swift +++ b/TelegramUI/InstantPageTheme.swift @@ -274,14 +274,22 @@ private func fontSizeMultiplierForVariant(_ variant: InstantPagePresentationFont } } -func instantPageThemeTypeForSettingsAndTime(presentationTheme: PresentationTheme, settings: InstantPagePresentationSettings, time: Date?) -> InstantPageThemeType { +func instantPageThemeTypeForSettingsAndTime(themeSettings: PresentationThemeSettings?, settings: InstantPagePresentationSettings, time: Date?) -> InstantPageThemeType { if settings.autoNightMode { switch settings.themeType { case .light, .sepia, .gray: var useDarkTheme = false - if let time = time { - let calendar = Calendar.current - let hour = calendar.component(.hour, from: time) + + var fallback = true + if let themeSettings = themeSettings { + if case .none = themeSettings.automaticThemeSwitchSetting.trigger { + } else { + fallback = false + useDarkTheme = automaticThemeShouldSwitchNow(themeSettings.automaticThemeSwitchSetting, currentTheme: themeSettings.theme) + } + } + if fallback, let time = time { + let hour = Calendar.current.component(.hour, from: time) if hour <= 8 || hour >= 22 { useDarkTheme = true } diff --git a/TelegramUI/InviteContactsControllerNode.swift b/TelegramUI/InviteContactsControllerNode.swift index 37ef5ba284..a9ba3ce78f 100644 --- a/TelegramUI/InviteContactsControllerNode.swift +++ b/TelegramUI/InviteContactsControllerNode.swift @@ -182,6 +182,16 @@ struct InviteContactsGroupSelectionState: Equatable { } } + func withSelectedContactId(_ contactId: String) -> InviteContactsGroupSelectionState { + var updatedIndices = self.selectedContactIndices + if let _ = updatedIndices[contactId] { + return self + } else { + updatedIndices[contactId] = self.nextSelectionIndex + return InviteContactsGroupSelectionState(selectedContactIndices: updatedIndices, nextSelectionIndex: self.nextSelectionIndex + 1) + } + } + func withClearedSelection() -> InviteContactsGroupSelectionState { return InviteContactsGroupSelectionState(selectedContactIndices: [:], nextSelectionIndex: self.nextSelectionIndex) } @@ -519,7 +529,11 @@ final class InviteContactsControllerNode: ASDisplayNode { return } - self.searchDisplayController = SearchDisplayController(presentationData: self.presentationData, contentNode: ContactsSearchContainerNode(context: self.context, onlyWriteable: false, categories: [.deviceContacts], openPeer: { _ in + self.searchDisplayController = SearchDisplayController(presentationData: self.presentationData, contentNode: ContactsSearchContainerNode(context: self.context, onlyWriteable: false, categories: [.deviceContacts], openPeer: { [weak self] peer in + if let strongSelf = self, case let .deviceContact(id, _) = peer { + strongSelf.selectionState = strongSelf.selectionState.withSelectedContactId(id) + strongSelf.requestDeactivateSearch?() + } }), cancel: { [weak self] in if let requestDeactivateSearch = self?.requestDeactivateSearch { requestDeactivateSearch() diff --git a/TelegramUI/ItemListRevealOptionsNode.swift b/TelegramUI/ItemListRevealOptionsNode.swift index 2fcc439bc8..d0d04ccd63 100644 --- a/TelegramUI/ItemListRevealOptionsNode.swift +++ b/TelegramUI/ItemListRevealOptionsNode.swift @@ -121,12 +121,15 @@ private enum ItemListRevealOptionAlignment { } private final class ItemListRevealOptionNode: ASDisplayNode { + private let highlightNode: ASDisplayNode private let titleNode: ASTextNode private let iconNode: ASImageNode? private let animationNode: ItemListRevealAnimationNode? var alignment: ItemListRevealOptionAlignment? init(title: String, icon: ItemListRevealOptionIcon, color: UIColor, textColor: UIColor) { + self.highlightNode = ASDisplayNode() + self.titleNode = ASTextNode() self.titleNode.attributedText = NSAttributedString(string: title, font: icon == .none ? titleFontWithoutIcon : titleFontWithIcon, textColor: textColor) @@ -156,9 +159,23 @@ private final class ItemListRevealOptionNode: ASDisplayNode { self.addSubnode(animationNode) } self.backgroundColor = color + self.highlightNode.backgroundColor = color.withMultipliedBrightnessBy(0.9) + } + + func setHighlighted(_ highlighted: Bool) { + if highlighted { + self.insertSubnode(self.highlightNode, at: 0) + self.highlightNode.layer.animate(from: 0.0 as NSNumber, to: 1.0 as NSNumber, keyPath: "opacity", timingFunction: kCAMediaTimingFunctionEaseInEaseOut, duration: 0.3) + self.highlightNode.alpha = 1.0 + } else { + self.highlightNode.removeFromSupernode() + self.highlightNode.alpha = 0.0 + } } func updateLayout(baseSize: CGSize, alignment: ItemListRevealOptionAlignment, extendedWidth: CGFloat, sideInset: CGFloat, transition: ContainedViewLayoutTransition, revealFactor: CGFloat) { + self.highlightNode.frame = CGRect(origin: CGPoint(), size: baseSize) + var animateAdditive = false if transition.isAnimated, self.alignment != alignment { animateAdditive = true @@ -229,7 +246,22 @@ final class ItemListRevealOptionsNode: ASDisplayNode { override func didLoad() { super.didLoad() - self.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:)))) + let gestureRecognizer = TapLongTapOrDoubleTapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:))) + gestureRecognizer.highlight = { [weak self] location in + guard let strongSelf = self, let location = location else { + return + } + for node in strongSelf.optionNodes { + if node.frame.contains(location) { + node.setHighlighted(true) + break + } + } + } + gestureRecognizer.tapActionAtPoint = { _ in + return .waitForSingleTap + } + self.view.addGestureRecognizer(gestureRecognizer) } func setOptions(_ options: [ItemListRevealOption]) { @@ -302,15 +334,19 @@ final class ItemListRevealOptionsNode: ASDisplayNode { } } - @objc func tapGesture(_ recognizer: UITapGestureRecognizer) { + @objc func tapGesture(_ recognizer: TapLongTapOrDoubleTapGestureRecognizer) { if case .ended = recognizer.state { let location = recognizer.location(in: self.view) + var selectedOption: Int? for i in 0 ..< self.optionNodes.count { + self.optionNodes[i].setHighlighted(false) if self.optionNodes[i].frame.contains(location) { - self.optionSelected(self.options[i]) - break + selectedOption = i } } + if let selectedOption = selectedOption { + self.optionSelected(self.options[selectedOption]) + } } } diff --git a/TelegramUI/PhotoResources.swift b/TelegramUI/PhotoResources.swift index 76f4693f47..6bb4918544 100644 --- a/TelegramUI/PhotoResources.swift +++ b/TelegramUI/PhotoResources.swift @@ -1002,7 +1002,7 @@ public func chatMessagePhotoThumbnail(account: Account, photoReference: ImageMed } public func chatMessageVideoThumbnail(account: Account, fileReference: FileMediaReference) -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> { - let signal = chatMessageVideoDatas(postbox: account.postbox, fileReference: fileReference, thumbnailSize: true) + let signal = chatMessageVideoDatas(postbox: account.postbox, fileReference: fileReference, thumbnailSize: true, autoFetchFullSizeThumbnail: true) return signal |> map { (thumbnailData, fullSizeData, fullSizeComplete) in @@ -1055,16 +1055,20 @@ public func chatMessageVideoThumbnail(account: Account, fileReference: FileMedia var blurredThumbnailImage: UIImage? if let thumbnailImage = thumbnailImage { - let thumbnailSize = CGSize(width: thumbnailImage.width, height: thumbnailImage.height) - let thumbnailContextSize = thumbnailSize.aspectFitted(CGSize(width: 150.0, height: 150.0)) - let thumbnailContext = DrawingContext(size: thumbnailContextSize, scale: 1.0) - thumbnailContext.withFlippedContext { c in - c.interpolationQuality = .none - c.draw(thumbnailImage, in: CGRect(origin: CGPoint(), size: thumbnailContextSize)) + if max(thumbnailImage.width, thumbnailImage.height) > 200 { + blurredThumbnailImage = UIImage(cgImage: thumbnailImage) + } else { + let thumbnailSize = CGSize(width: thumbnailImage.width, height: thumbnailImage.height) + let thumbnailContextSize = thumbnailSize.aspectFitted(CGSize(width: 150.0, height: 150.0)) + let thumbnailContext = DrawingContext(size: thumbnailContextSize, scale: 1.0) + thumbnailContext.withFlippedContext { c in + c.interpolationQuality = .none + c.draw(thumbnailImage, in: CGRect(origin: CGPoint(), size: thumbnailContextSize)) + } + telegramFastBlur(Int32(thumbnailContextSize.width), Int32(thumbnailContextSize.height), Int32(thumbnailContext.bytesPerRow), thumbnailContext.bytes) + + blurredThumbnailImage = thumbnailContext.generateImage() } - telegramFastBlur(Int32(thumbnailContextSize.width), Int32(thumbnailContextSize.height), Int32(thumbnailContext.bytesPerRow), thumbnailContext.bytes) - - blurredThumbnailImage = thumbnailContext.generateImage() } context.withFlippedContext { c in diff --git a/TelegramUI/PresentationData.swift b/TelegramUI/PresentationData.swift index c257767295..5aeacf7334 100644 --- a/TelegramUI/PresentationData.swift +++ b/TelegramUI/PresentationData.swift @@ -286,7 +286,7 @@ private func roundTimeToDay(_ timestamp: Int32) -> Int32 { return Int32(components.hour! * 60 * 60 + components.minute! * 60 + components.second!) } -private func automaticThemeShouldSwitchNow(_ settings: AutomaticThemeSwitchSetting, currentTheme: PresentationThemeReference) -> Bool { +func automaticThemeShouldSwitchNow(_ settings: AutomaticThemeSwitchSetting, currentTheme: PresentationThemeReference) -> Bool { switch currentTheme { case let .builtin(builtin): switch builtin { diff --git a/TelegramUI/SearchBarPlaceholderNode.swift b/TelegramUI/SearchBarPlaceholderNode.swift index ab4e3d1a14..f1af3640b5 100644 --- a/TelegramUI/SearchBarPlaceholderNode.swift +++ b/TelegramUI/SearchBarPlaceholderNode.swift @@ -159,7 +159,7 @@ class SearchBarPlaceholderNode: ASDisplayNode { } } - @objc private func backgroundTap(_ recognizer: UITapGestureRecognizer) { + @objc private func backgroundTap(_ recognizer: TapLongTapOrDoubleTapGestureRecognizer) { if case .ended = recognizer.state { self.backgroundNode.layer.animate(from: (self.backgroundNode.backgroundColor ?? self.foregroundColor).cgColor, to: self.foregroundColor.cgColor, keyPath: "backgroundColor", timingFunction: kCAMediaTimingFunctionEaseInEaseOut, duration: 0.2, completion: { _ in self.backgroundNode.backgroundColor = self.foregroundColor