Various UI fixes

This commit is contained in:
Ilya Laktyushin 2019-02-26 23:37:09 +04:00
parent c3373cc263
commit 2bbbc85093
17 changed files with 155 additions and 69 deletions

View File

@ -234,7 +234,7 @@ public func callFeedbackController(sharedContext: SharedAccountContext, account:
let signal = combineLatest(sharedContext.presentationData, statePromise.get())
|> deliverOnMainQueue
|> map { presentationData, state -> (ItemListControllerState, (ItemListNodeState<CallFeedbackControllerEntry>, 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: {

View File

@ -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))

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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)

View File

@ -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)
}
}
}

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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)

View File

@ -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

View File

@ -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
}

View File

@ -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()

View File

@ -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])
}
}
}

View File

@ -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,6 +1055,9 @@ public func chatMessageVideoThumbnail(account: Account, fileReference: FileMedia
var blurredThumbnailImage: UIImage?
if let thumbnailImage = thumbnailImage {
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)
@ -1066,6 +1069,7 @@ public func chatMessageVideoThumbnail(account: Account, fileReference: FileMedia
blurredThumbnailImage = thumbnailContext.generateImage()
}
}
context.withFlippedContext { c in
c.setBlendMode(.copy)

View File

@ -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 {

View File

@ -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