mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-03 13:13:55 +00:00
Various UI fixes
This commit is contained in:
parent
c3373cc263
commit
2bbbc85093
@ -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: {
|
||||
|
||||
@ -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))
|
||||
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user