mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-23 06:35:51 +00:00
[WIP] MultiScaleTextNode
This commit is contained in:
@@ -19,11 +19,16 @@ private final class MultiScaleTextStateNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final class MultiScaleTextState {
|
final class MultiScaleTextState {
|
||||||
let attributedText: NSAttributedString
|
struct Attributes {
|
||||||
|
var font: UIFont
|
||||||
|
var color: UIColor
|
||||||
|
}
|
||||||
|
|
||||||
|
let attributes: Attributes
|
||||||
let constrainedSize: CGSize
|
let constrainedSize: CGSize
|
||||||
|
|
||||||
init(attributedText: NSAttributedString, constrainedSize: CGSize) {
|
init(attributes: Attributes, constrainedSize: CGSize) {
|
||||||
self.attributedText = attributedText
|
self.attributes = attributes
|
||||||
self.constrainedSize = constrainedSize
|
self.constrainedSize = constrainedSize
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -49,7 +54,7 @@ final class MultiScaleTextNode: ASDisplayNode {
|
|||||||
return self.stateNodes[key]?.textNode
|
return self.stateNodes[key]?.textNode
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateLayout(states: [AnyHashable: MultiScaleTextState], mainState: AnyHashable) -> [AnyHashable: MultiScaleTextLayout] {
|
func updateLayout(text: String, states: [AnyHashable: MultiScaleTextState], mainState: AnyHashable) -> [AnyHashable: MultiScaleTextLayout] {
|
||||||
assert(Set(states.keys) == Set(self.stateNodes.keys))
|
assert(Set(states.keys) == Set(self.stateNodes.keys))
|
||||||
assert(states[mainState] != nil)
|
assert(states[mainState] != nil)
|
||||||
|
|
||||||
@@ -57,7 +62,7 @@ final class MultiScaleTextNode: ASDisplayNode {
|
|||||||
var mainLayout: MultiScaleTextLayout?
|
var mainLayout: MultiScaleTextLayout?
|
||||||
for (key, state) in states {
|
for (key, state) in states {
|
||||||
if let node = self.stateNodes[key] {
|
if let node = self.stateNodes[key] {
|
||||||
node.textNode.attributedText = state.attributedText
|
node.textNode.attributedText = NSAttributedString(string: text, font: state.attributes.font, textColor: state.attributes.color)
|
||||||
let nodeSize = node.textNode.updateLayout(state.constrainedSize)
|
let nodeSize = node.textNode.updateLayout(state.constrainedSize)
|
||||||
let nodeLayout = MultiScaleTextLayout(size: nodeSize)
|
let nodeLayout = MultiScaleTextLayout(size: nodeSize)
|
||||||
if key == mainState {
|
if key == mainState {
|
||||||
|
|||||||
@@ -2645,14 +2645,16 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||||||
var isPremium = false
|
var isPremium = false
|
||||||
var isVerified = false
|
var isVerified = false
|
||||||
var isFake = false
|
var isFake = false
|
||||||
let smallTitleString: NSAttributedString
|
let titleStringText: String
|
||||||
let titleString: NSAttributedString
|
let smallTitleAttributes: MultiScaleTextState.Attributes
|
||||||
let smallSubtitleString: NSAttributedString
|
let titleAttributes: MultiScaleTextState.Attributes
|
||||||
let subtitleString: NSAttributedString
|
let subtitleStringText: String
|
||||||
|
let smallSubtitleAttributes: MultiScaleTextState.Attributes
|
||||||
|
let subtitleAttributes: MultiScaleTextState.Attributes
|
||||||
var subtitleIsButton: Bool = false
|
var subtitleIsButton: Bool = false
|
||||||
var panelSubtitleString: NSAttributedString?
|
var panelSubtitleString: (text: String, attributes: MultiScaleTextState.Attributes)?
|
||||||
var nextPanelSubtitleString: NSAttributedString?
|
var nextPanelSubtitleString: (text: String, attributes: MultiScaleTextState.Attributes)?
|
||||||
let usernameString: NSAttributedString
|
let usernameString: (text: String, attributes: MultiScaleTextState.Attributes)
|
||||||
if let peer = peer {
|
if let peer = peer {
|
||||||
isPremium = peer.isPremium
|
isPremium = peer.isPremium
|
||||||
isVerified = peer.isVerified
|
isVerified = peer.isVerified
|
||||||
@@ -2681,17 +2683,21 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
titleString = NSAttributedString(string: title, font: Font.regular(30.0), textColor: presentationData.theme.list.itemPrimaryTextColor)
|
titleStringText = title
|
||||||
smallTitleString = NSAttributedString(string: title, font: Font.regular(30.0), textColor: .white)
|
titleAttributes = MultiScaleTextState.Attributes(font: Font.regular(30.0), color: presentationData.theme.list.itemPrimaryTextColor)
|
||||||
|
smallTitleAttributes = MultiScaleTextState.Attributes(font: Font.regular(30.0), color: .white)
|
||||||
|
|
||||||
if self.isSettings, let user = peer as? TelegramUser {
|
if self.isSettings, let user = peer as? TelegramUser {
|
||||||
var subtitle = formatPhoneNumber(context: self.context, number: user.phone ?? "")
|
var subtitle = formatPhoneNumber(context: self.context, number: user.phone ?? "")
|
||||||
|
|
||||||
if let mainUsername = user.addressName, !mainUsername.isEmpty {
|
if let mainUsername = user.addressName, !mainUsername.isEmpty {
|
||||||
subtitle = "\(subtitle) • @\(mainUsername)"
|
subtitle = "\(subtitle) • @\(mainUsername)"
|
||||||
}
|
}
|
||||||
smallSubtitleString = NSAttributedString(string: subtitle, font: Font.regular(15.0), textColor: UIColor(rgb: 0xffffff, alpha: 0.7))
|
subtitleStringText = subtitle
|
||||||
subtitleString = NSAttributedString(string: subtitle, font: Font.regular(17.0), textColor: presentationData.theme.list.itemSecondaryTextColor)
|
subtitleAttributes = MultiScaleTextState.Attributes(font: Font.regular(17.0), color: presentationData.theme.list.itemSecondaryTextColor)
|
||||||
usernameString = NSAttributedString(string: "", font: Font.regular(15.0), textColor: presentationData.theme.list.itemSecondaryTextColor)
|
smallSubtitleAttributes = MultiScaleTextState.Attributes(font: Font.regular(15.0), color: presentationData.theme.list.itemSecondaryTextColor)
|
||||||
|
|
||||||
|
usernameString = ("", MultiScaleTextState.Attributes(font: Font.regular(15.0), color: presentationData.theme.list.itemSecondaryTextColor))
|
||||||
} else if let _ = threadData {
|
} else if let _ = threadData {
|
||||||
let subtitleColor: UIColor
|
let subtitleColor: UIColor
|
||||||
subtitleColor = presentationData.theme.list.itemAccentColor
|
subtitleColor = presentationData.theme.list.itemAccentColor
|
||||||
@@ -2699,9 +2705,11 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||||||
let statusText: String
|
let statusText: String
|
||||||
statusText = peer.debugDisplayTitle
|
statusText = peer.debugDisplayTitle
|
||||||
|
|
||||||
smallSubtitleString = NSAttributedString(string: statusText, font: Font.regular(15.0), textColor: UIColor(rgb: 0xffffff, alpha: 0.7))
|
subtitleStringText = statusText
|
||||||
subtitleString = NSAttributedString(string: statusText, font: Font.semibold(15.0), textColor: subtitleColor)
|
subtitleAttributes = MultiScaleTextState.Attributes(font: Font.semibold(15.0), color: subtitleColor)
|
||||||
usernameString = NSAttributedString(string: "", font: Font.regular(15.0), textColor: presentationData.theme.list.itemSecondaryTextColor)
|
smallSubtitleAttributes = MultiScaleTextState.Attributes(font: Font.regular(15.0), color: UIColor(white: 1.0, alpha: 0.7))
|
||||||
|
|
||||||
|
usernameString = ("", MultiScaleTextState.Attributes(font: Font.regular(15.0), color: presentationData.theme.list.itemSecondaryTextColor))
|
||||||
|
|
||||||
subtitleIsButton = true
|
subtitleIsButton = true
|
||||||
|
|
||||||
@@ -2713,10 +2721,10 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||||||
} else {
|
} else {
|
||||||
subtitleColor = presentationData.theme.list.itemSecondaryTextColor
|
subtitleColor = presentationData.theme.list.itemSecondaryTextColor
|
||||||
}
|
}
|
||||||
panelSubtitleString = NSAttributedString(string: panelStatusData.text, font: Font.regular(17.0), textColor: subtitleColor)
|
panelSubtitleString = (panelStatusData.text, MultiScaleTextState.Attributes(font: Font.regular(17.0), color: subtitleColor))
|
||||||
}
|
}
|
||||||
if let nextPanelStatusData = maybeNextPanelStatusData {
|
if let nextPanelStatusData = maybeNextPanelStatusData {
|
||||||
nextPanelSubtitleString = NSAttributedString(string: nextPanelStatusData.text, font: Font.regular(17.0), textColor: presentationData.theme.list.itemSecondaryTextColor)
|
nextPanelSubtitleString = (nextPanelStatusData.text, MultiScaleTextState.Attributes(font: Font.regular(17.0), color: presentationData.theme.list.itemSecondaryTextColor))
|
||||||
}
|
}
|
||||||
} else if let statusData = statusData {
|
} else if let statusData = statusData {
|
||||||
let subtitleColor: UIColor
|
let subtitleColor: UIColor
|
||||||
@@ -2725,9 +2733,12 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||||||
} else {
|
} else {
|
||||||
subtitleColor = presentationData.theme.list.itemSecondaryTextColor
|
subtitleColor = presentationData.theme.list.itemSecondaryTextColor
|
||||||
}
|
}
|
||||||
smallSubtitleString = NSAttributedString(string: statusData.text, font: Font.regular(15.0), textColor: UIColor(rgb: 0xffffff, alpha: 0.7))
|
|
||||||
subtitleString = NSAttributedString(string: statusData.text, font: Font.regular(17.0), textColor: subtitleColor)
|
subtitleStringText = statusData.text
|
||||||
usernameString = NSAttributedString(string: "", font: Font.regular(15.0), textColor: presentationData.theme.list.itemSecondaryTextColor)
|
subtitleAttributes = MultiScaleTextState.Attributes(font: Font.regular(17.0), color: subtitleColor)
|
||||||
|
smallSubtitleAttributes = MultiScaleTextState.Attributes(font: Font.regular(15.0), color: UIColor(white: 1.0, alpha: 0.7))
|
||||||
|
|
||||||
|
usernameString = ("", MultiScaleTextState.Attributes(font: Font.regular(15.0), color: presentationData.theme.list.itemSecondaryTextColor))
|
||||||
|
|
||||||
let (maybePanelStatusData, maybeNextPanelStatusData, _) = panelStatusData
|
let (maybePanelStatusData, maybeNextPanelStatusData, _) = panelStatusData
|
||||||
if let panelStatusData = maybePanelStatusData {
|
if let panelStatusData = maybePanelStatusData {
|
||||||
@@ -2737,22 +2748,28 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||||||
} else {
|
} else {
|
||||||
subtitleColor = presentationData.theme.list.itemSecondaryTextColor
|
subtitleColor = presentationData.theme.list.itemSecondaryTextColor
|
||||||
}
|
}
|
||||||
panelSubtitleString = NSAttributedString(string: panelStatusData.text, font: Font.regular(17.0), textColor: subtitleColor)
|
panelSubtitleString = (panelStatusData.text, MultiScaleTextState.Attributes(font: Font.regular(17.0), color: subtitleColor))
|
||||||
}
|
}
|
||||||
if let nextPanelStatusData = maybeNextPanelStatusData {
|
if let nextPanelStatusData = maybeNextPanelStatusData {
|
||||||
nextPanelSubtitleString = NSAttributedString(string: nextPanelStatusData.text, font: Font.regular(17.0), textColor: presentationData.theme.list.itemSecondaryTextColor)
|
nextPanelSubtitleString = (nextPanelStatusData.text, MultiScaleTextState.Attributes(font: Font.regular(17.0), color: presentationData.theme.list.itemSecondaryTextColor))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
subtitleString = NSAttributedString(string: " ", font: Font.regular(15.0), textColor: presentationData.theme.list.itemSecondaryTextColor)
|
subtitleStringText = " "
|
||||||
smallSubtitleString = subtitleString
|
subtitleAttributes = MultiScaleTextState.Attributes(font: Font.regular(15.0), color: presentationData.theme.list.itemSecondaryTextColor)
|
||||||
usernameString = NSAttributedString(string: "", font: Font.regular(15.0), textColor: presentationData.theme.list.itemSecondaryTextColor)
|
smallSubtitleAttributes = MultiScaleTextState.Attributes(font: Font.regular(15.0), color: presentationData.theme.list.itemSecondaryTextColor)
|
||||||
|
|
||||||
|
usernameString = ("", MultiScaleTextState.Attributes(font: Font.regular(15.0), color: presentationData.theme.list.itemSecondaryTextColor))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
titleString = NSAttributedString(string: " ", font: Font.semibold(24.0), textColor: presentationData.theme.list.itemPrimaryTextColor)
|
titleStringText = " "
|
||||||
smallTitleString = titleString
|
titleAttributes = MultiScaleTextState.Attributes(font: Font.regular(24.0), color: presentationData.theme.list.itemPrimaryTextColor)
|
||||||
subtitleString = NSAttributedString(string: " ", font: Font.regular(15.0), textColor: presentationData.theme.list.itemSecondaryTextColor)
|
smallTitleAttributes = MultiScaleTextState.Attributes(font: Font.regular(24.0), color: .white)
|
||||||
smallSubtitleString = subtitleString
|
|
||||||
usernameString = NSAttributedString(string: "", font: Font.regular(15.0), textColor: presentationData.theme.list.itemSecondaryTextColor)
|
subtitleStringText = " "
|
||||||
|
subtitleAttributes = MultiScaleTextState.Attributes(font: Font.regular(15.0), color: presentationData.theme.list.itemSecondaryTextColor)
|
||||||
|
smallSubtitleAttributes = MultiScaleTextState.Attributes(font: Font.regular(15.0), color: presentationData.theme.list.itemSecondaryTextColor)
|
||||||
|
|
||||||
|
usernameString = ("", MultiScaleTextState.Attributes(font: Font.regular(15.0), color: presentationData.theme.list.itemSecondaryTextColor))
|
||||||
}
|
}
|
||||||
|
|
||||||
let textSideInset: CGFloat = 36.0
|
let textSideInset: CGFloat = 36.0
|
||||||
@@ -2760,17 +2777,17 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||||||
|
|
||||||
let titleConstrainedSize = CGSize(width: width - textSideInset * 2.0 - (isPremium || isVerified || isFake ? 20.0 : 0.0), height: .greatestFiniteMagnitude)
|
let titleConstrainedSize = CGSize(width: width - textSideInset * 2.0 - (isPremium || isVerified || isFake ? 20.0 : 0.0), height: .greatestFiniteMagnitude)
|
||||||
|
|
||||||
let titleNodeLayout = self.titleNode.updateLayout(states: [
|
let titleNodeLayout = self.titleNode.updateLayout(text: titleStringText, states: [
|
||||||
TitleNodeStateRegular: MultiScaleTextState(attributedText: titleString, constrainedSize: titleConstrainedSize),
|
TitleNodeStateRegular: MultiScaleTextState(attributes: titleAttributes, constrainedSize: titleConstrainedSize),
|
||||||
TitleNodeStateExpanded: MultiScaleTextState(attributedText: smallTitleString, constrainedSize: titleConstrainedSize)
|
TitleNodeStateExpanded: MultiScaleTextState(attributes: smallTitleAttributes, constrainedSize: titleConstrainedSize)
|
||||||
], mainState: TitleNodeStateRegular)
|
], mainState: TitleNodeStateRegular)
|
||||||
self.titleNode.accessibilityLabel = titleString.string
|
self.titleNode.accessibilityLabel = titleStringText
|
||||||
|
|
||||||
let subtitleNodeLayout = self.subtitleNode.updateLayout(states: [
|
let subtitleNodeLayout = self.subtitleNode.updateLayout(text: subtitleStringText, states: [
|
||||||
TitleNodeStateRegular: MultiScaleTextState(attributedText: subtitleString, constrainedSize: titleConstrainedSize),
|
TitleNodeStateRegular: MultiScaleTextState(attributes: subtitleAttributes, constrainedSize: titleConstrainedSize),
|
||||||
TitleNodeStateExpanded: MultiScaleTextState(attributedText: smallSubtitleString, constrainedSize: titleConstrainedSize)
|
TitleNodeStateExpanded: MultiScaleTextState(attributes: smallSubtitleAttributes, constrainedSize: titleConstrainedSize)
|
||||||
], mainState: TitleNodeStateRegular)
|
], mainState: TitleNodeStateRegular)
|
||||||
self.subtitleNode.accessibilityLabel = subtitleString.string
|
self.subtitleNode.accessibilityLabel = subtitleStringText
|
||||||
|
|
||||||
if subtitleIsButton {
|
if subtitleIsButton {
|
||||||
let subtitleBackgroundNode: ASDisplayNode
|
let subtitleBackgroundNode: ASDisplayNode
|
||||||
@@ -2863,25 +2880,25 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let panelSubtitleNodeLayout = self.panelSubtitleNode.updateLayout(states: [
|
let panelSubtitleNodeLayout = self.panelSubtitleNode.updateLayout(text: panelSubtitleString?.text ?? subtitleStringText, states: [
|
||||||
TitleNodeStateRegular: MultiScaleTextState(attributedText: panelSubtitleString ?? subtitleString, constrainedSize: titleConstrainedSize),
|
TitleNodeStateRegular: MultiScaleTextState(attributes: panelSubtitleString?.attributes ?? subtitleAttributes, constrainedSize: titleConstrainedSize),
|
||||||
TitleNodeStateExpanded: MultiScaleTextState(attributedText: panelSubtitleString ?? subtitleString, constrainedSize: titleConstrainedSize)
|
TitleNodeStateExpanded: MultiScaleTextState(attributes: panelSubtitleString?.attributes ?? subtitleAttributes, constrainedSize: titleConstrainedSize)
|
||||||
], mainState: TitleNodeStateRegular)
|
], mainState: TitleNodeStateRegular)
|
||||||
self.panelSubtitleNode.accessibilityLabel = (panelSubtitleString ?? subtitleString).string
|
self.panelSubtitleNode.accessibilityLabel = panelSubtitleString?.text ?? subtitleStringText
|
||||||
|
|
||||||
let nextPanelSubtitleNodeLayout = self.nextPanelSubtitleNode.updateLayout(states: [
|
let nextPanelSubtitleNodeLayout = self.nextPanelSubtitleNode.updateLayout(text: nextPanelSubtitleString?.text ?? subtitleStringText, states: [
|
||||||
TitleNodeStateRegular: MultiScaleTextState(attributedText: nextPanelSubtitleString ?? subtitleString, constrainedSize: titleConstrainedSize),
|
TitleNodeStateRegular: MultiScaleTextState(attributes: nextPanelSubtitleString?.attributes ?? subtitleAttributes, constrainedSize: titleConstrainedSize),
|
||||||
TitleNodeStateExpanded: MultiScaleTextState(attributedText: nextPanelSubtitleString ?? subtitleString, constrainedSize: titleConstrainedSize)
|
TitleNodeStateExpanded: MultiScaleTextState(attributes: nextPanelSubtitleString?.attributes ?? subtitleAttributes, constrainedSize: titleConstrainedSize)
|
||||||
], mainState: TitleNodeStateRegular)
|
], mainState: TitleNodeStateRegular)
|
||||||
if let _ = nextPanelSubtitleString {
|
if let _ = nextPanelSubtitleString {
|
||||||
self.nextPanelSubtitleNode.isHidden = false
|
self.nextPanelSubtitleNode.isHidden = false
|
||||||
}
|
}
|
||||||
|
|
||||||
let usernameNodeLayout = self.usernameNode.updateLayout(states: [
|
let usernameNodeLayout = self.usernameNode.updateLayout(text: usernameString.text, states: [
|
||||||
TitleNodeStateRegular: MultiScaleTextState(attributedText: usernameString, constrainedSize: CGSize(width: titleConstrainedSize.width, height: titleConstrainedSize.height)),
|
TitleNodeStateRegular: MultiScaleTextState(attributes: usernameString.attributes, constrainedSize: CGSize(width: titleConstrainedSize.width, height: titleConstrainedSize.height)),
|
||||||
TitleNodeStateExpanded: MultiScaleTextState(attributedText: usernameString, constrainedSize: CGSize(width: width - titleNodeLayout[TitleNodeStateExpanded]!.size.width - 8.0, height: titleConstrainedSize.height))
|
TitleNodeStateExpanded: MultiScaleTextState(attributes: usernameString.attributes, constrainedSize: CGSize(width: width - titleNodeLayout[TitleNodeStateExpanded]!.size.width - 8.0, height: titleConstrainedSize.height))
|
||||||
], mainState: TitleNodeStateRegular)
|
], mainState: TitleNodeStateRegular)
|
||||||
self.usernameNode.accessibilityLabel = usernameString.string
|
self.usernameNode.accessibilityLabel = usernameString.text
|
||||||
|
|
||||||
let avatarCenter: CGPoint
|
let avatarCenter: CGPoint
|
||||||
if let transitionSourceAvatarFrame = transitionSourceAvatarFrame {
|
if let transitionSourceAvatarFrame = transitionSourceAvatarFrame {
|
||||||
@@ -2987,7 +3004,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||||||
subtitleAlpha = 1.0 - titleCollapseFraction
|
subtitleAlpha = 1.0 - titleCollapseFraction
|
||||||
panelSubtitleAlpha = 0.0
|
panelSubtitleAlpha = 0.0
|
||||||
} else {
|
} else {
|
||||||
if (panelSubtitleString ?? subtitleString).string != subtitleString.string {
|
if (panelSubtitleString?.text ?? subtitleStringText) != subtitleStringText {
|
||||||
subtitleAlpha = 1.0 - effectiveAreaExpansionFraction
|
subtitleAlpha = 1.0 - effectiveAreaExpansionFraction
|
||||||
panelSubtitleAlpha = effectiveAreaExpansionFraction
|
panelSubtitleAlpha = effectiveAreaExpansionFraction
|
||||||
subtitleOffset = -effectiveAreaExpansionFraction * 5.0
|
subtitleOffset = -effectiveAreaExpansionFraction * 5.0
|
||||||
|
|||||||
Reference in New Issue
Block a user