mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Refactoring
This commit is contained in:
parent
42314cbbd3
commit
679a10cbdf
@ -38,6 +38,7 @@ swift_library(
|
|||||||
"//submodules/TelegramUI/Components/Chat/ChatMessageInteractiveMediaNode",
|
"//submodules/TelegramUI/Components/Chat/ChatMessageInteractiveMediaNode",
|
||||||
"//submodules/TelegramUI/Components/WallpaperPreviewMedia",
|
"//submodules/TelegramUI/Components/WallpaperPreviewMedia",
|
||||||
"//submodules/TelegramUI/Components/Chat/ChatMessageAttachedContentButtonNode",
|
"//submodules/TelegramUI/Components/Chat/ChatMessageAttachedContentButtonNode",
|
||||||
|
"//submodules/TelegramUI/Components/Chat/ChatMessagePollBubbleContentNode",
|
||||||
],
|
],
|
||||||
visibility = [
|
visibility = [
|
||||||
"//visibility:public",
|
"//visibility:public",
|
||||||
|
@ -8,6 +8,7 @@ swift_library(
|
|||||||
]),
|
]),
|
||||||
copts = [
|
copts = [
|
||||||
"-warnings-as-errors",
|
"-warnings-as-errors",
|
||||||
|
#"-Xfrontend", "-debug-time-function-bodies"
|
||||||
],
|
],
|
||||||
deps = [
|
deps = [
|
||||||
"//submodules/AsyncDisplayKit",
|
"//submodules/AsyncDisplayKit",
|
||||||
|
@ -324,8 +324,8 @@ public class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
|||||||
|
|
||||||
let bubbleEdgeInset: CGFloat = 4.0
|
let bubbleEdgeInset: CGFloat = 4.0
|
||||||
let bubbleContentInsetsLeft: CGFloat = 6.0
|
let bubbleContentInsetsLeft: CGFloat = 6.0
|
||||||
let availableWidth = max(60.0, width - 210.0 - bubbleEdgeInset * 2.0 - bubbleContentInsetsLeft - 20.0)
|
let availableWidth: CGFloat = max(60.0, width - 210.0 - bubbleEdgeInset * 2.0 - bubbleContentInsetsLeft - 20.0)
|
||||||
let availableContentWidth = width - bubbleEdgeInset * 2.0 - bubbleContentInsetsLeft - 20.0
|
let availableContentWidth: CGFloat = width - bubbleEdgeInset * 2.0 - bubbleContentInsetsLeft - 20.0
|
||||||
|
|
||||||
if !ignoreHeaders {
|
if !ignoreHeaders {
|
||||||
var replyMessage: Message?
|
var replyMessage: Message?
|
||||||
@ -430,7 +430,7 @@ public class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
|||||||
forwardAuthorSignature = forwardInfo.authorSignature
|
forwardAuthorSignature = forwardInfo.authorSignature
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let availableWidth = max(60.0, availableContentWidth - 210.0 + 6.0)
|
let availableWidth: CGFloat = max(60.0, availableContentWidth - 210.0 + 6.0)
|
||||||
forwardInfoSizeApply = makeForwardInfoLayout(item.presentationData, item.presentationData.strings, .standalone, forwardSource, forwardAuthorSignature, forwardPsaType, nil, CGSize(width: availableWidth, height: CGFloat.greatestFiniteMagnitude))
|
forwardInfoSizeApply = makeForwardInfoLayout(item.presentationData, item.presentationData.strings, .standalone, forwardSource, forwardAuthorSignature, forwardPsaType, nil, CGSize(width: availableWidth, height: CGFloat.greatestFiniteMagnitude))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -222,3 +222,11 @@ public func transcribedText(message: Message) -> TranscribedText? {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func isPollEffectivelyClosed(message: Message, poll: TelegramMediaPoll) -> Bool {
|
||||||
|
if poll.isClosed {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -0,0 +1,32 @@
|
|||||||
|
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
|
||||||
|
|
||||||
|
swift_library(
|
||||||
|
name = "ChatMessagePollBubbleContentNode",
|
||||||
|
module_name = "ChatMessagePollBubbleContentNode",
|
||||||
|
srcs = glob([
|
||||||
|
"Sources/**/*.swift",
|
||||||
|
]),
|
||||||
|
copts = [
|
||||||
|
"-warnings-as-errors",
|
||||||
|
],
|
||||||
|
deps = [
|
||||||
|
"//submodules/AsyncDisplayKit",
|
||||||
|
"//submodules/Display",
|
||||||
|
"//submodules/TelegramCore",
|
||||||
|
"//submodules/Postbox",
|
||||||
|
"//submodules/TextFormat",
|
||||||
|
"//submodules/UrlEscaping",
|
||||||
|
"//submodules/SSignalKit/SwiftSignalKit",
|
||||||
|
"//submodules/AccountContext",
|
||||||
|
"//submodules/AvatarNode",
|
||||||
|
"//submodules/TelegramPresentationData",
|
||||||
|
"//submodules/ChatMessageBackground",
|
||||||
|
"//submodules/TelegramUI/Components/Chat/ChatMessageDateAndStatusNode",
|
||||||
|
"//submodules/TelegramUI/Components/Chat/ChatMessageBubbleContentNode",
|
||||||
|
"//submodules/TelegramUI/Components/Chat/ChatMessageItemCommon",
|
||||||
|
"//submodules/TelegramUI/Components/Chat/PollBubbleTimerNode",
|
||||||
|
],
|
||||||
|
visibility = [
|
||||||
|
"//visibility:public",
|
||||||
|
],
|
||||||
|
)
|
@ -14,103 +14,7 @@ import ChatMessageBackground
|
|||||||
import ChatMessageDateAndStatusNode
|
import ChatMessageDateAndStatusNode
|
||||||
import ChatMessageBubbleContentNode
|
import ChatMessageBubbleContentNode
|
||||||
import ChatMessageItemCommon
|
import ChatMessageItemCommon
|
||||||
|
import PollBubbleTimerNode
|
||||||
func isPollEffectivelyClosed(message: Message, poll: TelegramMediaPoll) -> Bool {
|
|
||||||
if poll.isClosed {
|
|
||||||
return true
|
|
||||||
}/* else if let deadlineTimeout = poll.deadlineTimeout, message.id.namespace == Namespaces.Message.Cloud {
|
|
||||||
let startDate: Int32
|
|
||||||
if let forwardInfo = message.forwardInfo {
|
|
||||||
startDate = forwardInfo.date
|
|
||||||
} else {
|
|
||||||
startDate = message.timestamp
|
|
||||||
}
|
|
||||||
|
|
||||||
let timestamp = Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970)
|
|
||||||
if timestamp >= startDate + deadlineTimeout {
|
|
||||||
return true
|
|
||||||
} else {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}*/ else {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private struct PercentCounterItem: Comparable {
|
|
||||||
var index: Int = 0
|
|
||||||
var percent: Int = 0
|
|
||||||
var remainder: Int = 0
|
|
||||||
|
|
||||||
static func <(lhs: PercentCounterItem, rhs: PercentCounterItem) -> Bool {
|
|
||||||
if lhs.remainder > rhs.remainder {
|
|
||||||
return true
|
|
||||||
} else if lhs.remainder < rhs.remainder {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return lhs.percent < rhs.percent
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private func adjustPercentCount(_ items: [PercentCounterItem], left: Int) -> [PercentCounterItem] {
|
|
||||||
var left = left
|
|
||||||
var items = items.sorted(by: <)
|
|
||||||
var i:Int = 0
|
|
||||||
while i != items.count {
|
|
||||||
let item = items[i]
|
|
||||||
var j = i + 1
|
|
||||||
loop: while j != items.count {
|
|
||||||
if items[j].percent != item.percent || items[j].remainder != item.remainder {
|
|
||||||
break loop
|
|
||||||
}
|
|
||||||
j += 1
|
|
||||||
}
|
|
||||||
if items[i].remainder == 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
let equal = j - i
|
|
||||||
if equal <= left {
|
|
||||||
left -= equal
|
|
||||||
while i != j {
|
|
||||||
items[i].percent += 1
|
|
||||||
i += 1
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
i = j
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return items
|
|
||||||
}
|
|
||||||
|
|
||||||
func countNicePercent(votes: [Int], total: Int) -> [Int] {
|
|
||||||
var result:[Int] = []
|
|
||||||
var items:[PercentCounterItem] = []
|
|
||||||
for _ in votes {
|
|
||||||
result.append(0)
|
|
||||||
items.append(PercentCounterItem())
|
|
||||||
}
|
|
||||||
|
|
||||||
let count = votes.count
|
|
||||||
|
|
||||||
var left:Int = 100
|
|
||||||
for i in 0 ..< votes.count {
|
|
||||||
let votes = votes[i]
|
|
||||||
items[i].index = i
|
|
||||||
items[i].percent = Int((Float(votes) * 100) / Float(total))
|
|
||||||
items[i].remainder = (votes * 100) - (items[i].percent * total)
|
|
||||||
left -= items[i].percent
|
|
||||||
}
|
|
||||||
|
|
||||||
if left > 0 && left <= count {
|
|
||||||
items = adjustPercentCount(items, left: left)
|
|
||||||
}
|
|
||||||
for item in items {
|
|
||||||
result[item.index] = item.percent
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
private final class ChatMessagePollOptionRadioNodeParameters: NSObject {
|
private final class ChatMessagePollOptionRadioNodeParameters: NSObject {
|
||||||
let timestamp: Double
|
let timestamp: Double
|
||||||
@ -867,7 +771,7 @@ private final class SolutionButtonNode: HighlightableButtonNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ChatMessagePollBubbleContentNode: ChatMessageBubbleContentNode {
|
public class ChatMessagePollBubbleContentNode: ChatMessageBubbleContentNode {
|
||||||
private let textNode: TextNode
|
private let textNode: TextNode
|
||||||
private let typeNode: TextNode
|
private let typeNode: TextNode
|
||||||
private var timerNode: PollBubbleTimerNode?
|
private var timerNode: PollBubbleTimerNode?
|
||||||
@ -883,11 +787,11 @@ class ChatMessagePollBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
|
|
||||||
private var poll: TelegramMediaPoll?
|
private var poll: TelegramMediaPoll?
|
||||||
|
|
||||||
var solutionTipSourceNode: ASDisplayNode {
|
public var solutionTipSourceNode: ASDisplayNode {
|
||||||
return self.solutionButtonNode
|
return self.solutionButtonNode
|
||||||
}
|
}
|
||||||
|
|
||||||
required init() {
|
required public init() {
|
||||||
self.textNode = TextNode()
|
self.textNode = TextNode()
|
||||||
self.textNode.isUserInteractionEnabled = false
|
self.textNode.isUserInteractionEnabled = false
|
||||||
self.textNode.contentMode = .topLeft
|
self.textNode.contentMode = .topLeft
|
||||||
@ -978,7 +882,7 @@ class ChatMessagePollBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
required init?(coder aDecoder: NSCoder) {
|
required public init?(coder aDecoder: NSCoder) {
|
||||||
fatalError("init(coder:) has not been implemented")
|
fatalError("init(coder:) has not been implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1008,7 +912,7 @@ class ChatMessagePollBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize, _ avatarInset: CGFloat) -> (ChatMessageBubbleContentProperties, CGSize?, CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) {
|
override public func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize, _ avatarInset: CGFloat) -> (ChatMessageBubbleContentProperties, CGSize?, CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) {
|
||||||
let makeTextLayout = TextNode.asyncLayout(self.textNode)
|
let makeTextLayout = TextNode.asyncLayout(self.textNode)
|
||||||
let makeTypeLayout = TextNode.asyncLayout(self.typeNode)
|
let makeTypeLayout = TextNode.asyncLayout(self.typeNode)
|
||||||
let makeVotersLayout = TextNode.asyncLayout(self.votersNode)
|
let makeVotersLayout = TextNode.asyncLayout(self.votersNode)
|
||||||
@ -1681,22 +1585,22 @@ class ChatMessagePollBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
self.avatarsNode.isUserInteractionEnabled = !self.buttonViewResultsTextNode.isHidden
|
self.avatarsNode.isUserInteractionEnabled = !self.buttonViewResultsTextNode.isHidden
|
||||||
}
|
}
|
||||||
|
|
||||||
override func animateInsertion(_ currentTimestamp: Double, duration: Double) {
|
override public func animateInsertion(_ currentTimestamp: Double, duration: Double) {
|
||||||
self.textNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
self.textNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
||||||
self.statusNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
self.statusNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
||||||
}
|
}
|
||||||
|
|
||||||
override func animateAdded(_ currentTimestamp: Double, duration: Double) {
|
override public func animateAdded(_ currentTimestamp: Double, duration: Double) {
|
||||||
self.textNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
self.textNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
||||||
self.statusNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
self.statusNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
||||||
}
|
}
|
||||||
|
|
||||||
override func animateRemoved(_ currentTimestamp: Double, duration: Double) {
|
override public func animateRemoved(_ currentTimestamp: Double, duration: Double) {
|
||||||
self.textNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false)
|
self.textNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false)
|
||||||
self.statusNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false)
|
self.statusNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
override func tapActionAtPoint(_ point: CGPoint, gesture: TapLongTapOrDoubleTapGesture, isEstimating: Bool) -> ChatMessageBubbleContentTapAction {
|
override public func tapActionAtPoint(_ point: CGPoint, gesture: TapLongTapOrDoubleTapGesture, isEstimating: Bool) -> ChatMessageBubbleContentTapAction {
|
||||||
let textNodeFrame = self.textNode.frame
|
let textNodeFrame = self.textNode.frame
|
||||||
if let (index, attributes) = self.textNode.attributesAtPoint(CGPoint(x: point.x - textNodeFrame.minX, y: point.y - textNodeFrame.minY)) {
|
if let (index, attributes) = self.textNode.attributesAtPoint(CGPoint(x: point.x - textNodeFrame.minX, y: point.y - textNodeFrame.minY)) {
|
||||||
if let url = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.URL)] as? String {
|
if let url = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.URL)] as? String {
|
||||||
@ -1778,7 +1682,7 @@ class ChatMessagePollBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func updatePollTooltipMessageState(animated: Bool) {
|
public func updatePollTooltipMessageState(animated: Bool) {
|
||||||
guard let item = self.item else {
|
guard let item = self.item else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -1795,7 +1699,7 @@ class ChatMessagePollBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override func reactionTargetView(value: MessageReaction.Reaction) -> UIView? {
|
override public func reactionTargetView(value: MessageReaction.Reaction) -> UIView? {
|
||||||
if !self.statusNode.isHidden {
|
if !self.statusNode.isHidden {
|
||||||
return self.statusNode.reactionView(value: value)
|
return self.statusNode.reactionView(value: value)
|
||||||
}
|
}
|
||||||
@ -1849,7 +1753,7 @@ private let defaultBorderWidth: CGFloat = 1.0
|
|||||||
|
|
||||||
private let avatarFont = avatarPlaceholderFont(size: 8.0)
|
private let avatarFont = avatarPlaceholderFont(size: 8.0)
|
||||||
|
|
||||||
final class MergedAvatarsNode: ASDisplayNode {
|
public final class MergedAvatarsNode: ASDisplayNode {
|
||||||
private var peers: [PeerAvatarReference] = []
|
private var peers: [PeerAvatarReference] = []
|
||||||
private var images: [PeerId: UIImage] = [:]
|
private var images: [PeerId: UIImage] = [:]
|
||||||
private var disposables: [PeerId: Disposable] = [:]
|
private var disposables: [PeerId: Disposable] = [:]
|
||||||
@ -1858,9 +1762,9 @@ final class MergedAvatarsNode: ASDisplayNode {
|
|||||||
private var imageSpacing: CGFloat = defaultMergedImageSpacing
|
private var imageSpacing: CGFloat = defaultMergedImageSpacing
|
||||||
private var borderWidthValue: CGFloat = defaultBorderWidth
|
private var borderWidthValue: CGFloat = defaultBorderWidth
|
||||||
|
|
||||||
var pressed: (() -> Void)?
|
public var pressed: (() -> Void)?
|
||||||
|
|
||||||
override init() {
|
override public init() {
|
||||||
self.buttonNode = HighlightTrackingButtonNode()
|
self.buttonNode = HighlightTrackingButtonNode()
|
||||||
|
|
||||||
super.init()
|
super.init()
|
||||||
@ -1881,11 +1785,11 @@ final class MergedAvatarsNode: ASDisplayNode {
|
|||||||
self.pressed?()
|
self.pressed?()
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateLayout(size: CGSize) {
|
public func updateLayout(size: CGSize) {
|
||||||
self.buttonNode.frame = CGRect(origin: CGPoint(), size: size)
|
self.buttonNode.frame = CGRect(origin: CGPoint(), size: size)
|
||||||
}
|
}
|
||||||
|
|
||||||
func update(context: AccountContext, peers: [Peer], synchronousLoad: Bool, imageSize: CGFloat, imageSpacing: CGFloat, borderWidth: CGFloat) {
|
public func update(context: AccountContext, peers: [Peer], synchronousLoad: Bool, imageSize: CGFloat, imageSpacing: CGFloat, borderWidth: CGFloat) {
|
||||||
self.imageSize = imageSize
|
self.imageSize = imageSize
|
||||||
self.imageSpacing = imageSpacing
|
self.imageSpacing = imageSpacing
|
||||||
self.borderWidthValue = borderWidth
|
self.borderWidthValue = borderWidth
|
||||||
@ -1949,11 +1853,11 @@ final class MergedAvatarsNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override func drawParameters(forAsyncLayer layer: _ASDisplayLayer) -> NSObjectProtocol {
|
override public func drawParameters(forAsyncLayer layer: _ASDisplayLayer) -> NSObjectProtocol {
|
||||||
return MergedAvatarsNodeArguments(peers: self.peers, images: self.images, imageSize: self.imageSize, imageSpacing: self.imageSpacing, borderWidth: self.borderWidthValue)
|
return MergedAvatarsNodeArguments(peers: self.peers, images: self.images, imageSize: self.imageSize, imageSpacing: self.imageSpacing, borderWidth: self.borderWidthValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc override class func draw(_ bounds: CGRect, withParameters parameters: Any?, isCancelled: () -> Bool, isRasterizing: Bool) {
|
@objc override public class func draw(_ bounds: CGRect, withParameters parameters: Any?, isCancelled: () -> Bool, isRasterizing: Bool) {
|
||||||
assertNotOnMainThread()
|
assertNotOnMainThread()
|
||||||
|
|
||||||
let context = UIGraphicsGetCurrentContext()!
|
let context = UIGraphicsGetCurrentContext()!
|
@ -0,0 +1,19 @@
|
|||||||
|
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
|
||||||
|
|
||||||
|
swift_library(
|
||||||
|
name = "PollBubbleTimerNode",
|
||||||
|
module_name = "PollBubbleTimerNode",
|
||||||
|
srcs = glob([
|
||||||
|
"Sources/**/*.swift",
|
||||||
|
]),
|
||||||
|
copts = [
|
||||||
|
"-warnings-as-errors",
|
||||||
|
],
|
||||||
|
deps = [
|
||||||
|
"//submodules/AsyncDisplayKit",
|
||||||
|
"//submodules/Display",
|
||||||
|
],
|
||||||
|
visibility = [
|
||||||
|
"//visibility:public",
|
||||||
|
],
|
||||||
|
)
|
@ -39,7 +39,7 @@ private struct ContentParticle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final class PollBubbleTimerNode: ASDisplayNode {
|
public final class PollBubbleTimerNode: ASDisplayNode {
|
||||||
private struct Params: Equatable {
|
private struct Params: Equatable {
|
||||||
var regularColor: UIColor
|
var regularColor: UIColor
|
||||||
var proximityColor: UIColor
|
var proximityColor: UIColor
|
||||||
@ -58,9 +58,9 @@ final class PollBubbleTimerNode: ASDisplayNode {
|
|||||||
|
|
||||||
private var currentParams: Params?
|
private var currentParams: Params?
|
||||||
|
|
||||||
var reachedTimeout: (() -> Void)?
|
public var reachedTimeout: (() -> Void)?
|
||||||
|
|
||||||
override init() {
|
override public init() {
|
||||||
var updateInHierarchy: ((Bool) -> Void)?
|
var updateInHierarchy: ((Bool) -> Void)?
|
||||||
self.hierarchyTrackingNode = HierarchyTrackingNode({ value in
|
self.hierarchyTrackingNode = HierarchyTrackingNode({ value in
|
||||||
updateInHierarchy?(value)
|
updateInHierarchy?(value)
|
||||||
@ -89,7 +89,7 @@ final class PollBubbleTimerNode: ASDisplayNode {
|
|||||||
self.animator?.invalidate()
|
self.animator?.invalidate()
|
||||||
}
|
}
|
||||||
|
|
||||||
func update(regularColor: UIColor, proximityColor: UIColor, timeout: Int32, deadlineTimestamp: Int32?) {
|
public func update(regularColor: UIColor, proximityColor: UIColor, timeout: Int32, deadlineTimestamp: Int32?) {
|
||||||
let params = Params(
|
let params = Params(
|
||||||
regularColor: regularColor,
|
regularColor: regularColor,
|
||||||
proximityColor: proximityColor,
|
proximityColor: proximityColor,
|
@ -106,6 +106,7 @@ import SaveToCameraRoll
|
|||||||
import ChatMessageDateAndStatusNode
|
import ChatMessageDateAndStatusNode
|
||||||
import ReplyAccessoryPanelNode
|
import ReplyAccessoryPanelNode
|
||||||
import TextSelectionNode
|
import TextSelectionNode
|
||||||
|
import ChatMessagePollBubbleContentNode
|
||||||
|
|
||||||
public enum ChatControllerPeekActions {
|
public enum ChatControllerPeekActions {
|
||||||
case standard
|
case standard
|
||||||
|
@ -33,6 +33,7 @@ import SettingsUI
|
|||||||
import PremiumUI
|
import PremiumUI
|
||||||
import TextNodeWithEntities
|
import TextNodeWithEntities
|
||||||
import ChatControllerInteraction
|
import ChatControllerInteraction
|
||||||
|
import ChatMessageItemCommon
|
||||||
|
|
||||||
private struct MessageContextMenuData {
|
private struct MessageContextMenuData {
|
||||||
let starStatus: Bool?
|
let starStatus: Bool?
|
||||||
|
@ -40,6 +40,7 @@ import ChatMessageCallBubbleContentNode
|
|||||||
import ChatMessageInteractiveFileNode
|
import ChatMessageInteractiveFileNode
|
||||||
import ChatMessageFileBubbleContentNode
|
import ChatMessageFileBubbleContentNode
|
||||||
import ChatMessageWebpageBubbleContentNode
|
import ChatMessageWebpageBubbleContentNode
|
||||||
|
import ChatMessagePollBubbleContentNode
|
||||||
|
|
||||||
enum InternalBubbleTapAction {
|
enum InternalBubbleTapAction {
|
||||||
case action(() -> Void)
|
case action(() -> Void)
|
||||||
|
@ -12,6 +12,7 @@ import TelegramPresentationData
|
|||||||
import SwiftSignalKit
|
import SwiftSignalKit
|
||||||
import ChatControllerInteraction
|
import ChatControllerInteraction
|
||||||
import ChatMessageItemCommon
|
import ChatMessageItemCommon
|
||||||
|
import TextFormat
|
||||||
|
|
||||||
func chatMessageItemLayoutConstants(_ constants: (ChatMessageItemLayoutConstants, ChatMessageItemLayoutConstants), params: ListViewItemLayoutParams, presentationData: ChatPresentationData) -> ChatMessageItemLayoutConstants {
|
func chatMessageItemLayoutConstants(_ constants: (ChatMessageItemLayoutConstants, ChatMessageItemLayoutConstants), params: ListViewItemLayoutParams, presentationData: ChatPresentationData) -> ChatMessageItemLayoutConstants {
|
||||||
var result: ChatMessageItemLayoutConstants
|
var result: ChatMessageItemLayoutConstants
|
||||||
|
@ -7,6 +7,7 @@ import ItemListUI
|
|||||||
import Display
|
import Display
|
||||||
import ItemListPeerItem
|
import ItemListPeerItem
|
||||||
import ItemListPeerActionItem
|
import ItemListPeerActionItem
|
||||||
|
import TextFormat
|
||||||
|
|
||||||
private let collapsedResultCount: Int = 10
|
private let collapsedResultCount: Int = 10
|
||||||
private let collapsedInitialLimit: Int = 10
|
private let collapsedInitialLimit: Int = 10
|
||||||
@ -425,4 +426,3 @@ public func pollResultsController(context: AccountContext, messageId: EngineMess
|
|||||||
|
|
||||||
return controller
|
return controller
|
||||||
}
|
}
|
||||||
|
|
||||||
|
77
submodules/TextFormat/Sources/CountNicePercent.swift
Normal file
77
submodules/TextFormat/Sources/CountNicePercent.swift
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
import Foundation
|
||||||
|
import TelegramCore
|
||||||
|
|
||||||
|
private struct PercentCounterItem: Comparable {
|
||||||
|
var index: Int = 0
|
||||||
|
var percent: Int = 0
|
||||||
|
var remainder: Int = 0
|
||||||
|
|
||||||
|
static func <(lhs: PercentCounterItem, rhs: PercentCounterItem) -> Bool {
|
||||||
|
if lhs.remainder > rhs.remainder {
|
||||||
|
return true
|
||||||
|
} else if lhs.remainder < rhs.remainder {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return lhs.percent < rhs.percent
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private func adjustPercentCount(_ items: [PercentCounterItem], left: Int) -> [PercentCounterItem] {
|
||||||
|
var left = left
|
||||||
|
var items = items.sorted(by: <)
|
||||||
|
var i:Int = 0
|
||||||
|
while i != items.count {
|
||||||
|
let item = items[i]
|
||||||
|
var j = i + 1
|
||||||
|
loop: while j != items.count {
|
||||||
|
if items[j].percent != item.percent || items[j].remainder != item.remainder {
|
||||||
|
break loop
|
||||||
|
}
|
||||||
|
j += 1
|
||||||
|
}
|
||||||
|
if items[i].remainder == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
let equal = j - i
|
||||||
|
if equal <= left {
|
||||||
|
left -= equal
|
||||||
|
while i != j {
|
||||||
|
items[i].percent += 1
|
||||||
|
i += 1
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
i = j
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return items
|
||||||
|
}
|
||||||
|
|
||||||
|
public func countNicePercent(votes: [Int], total: Int) -> [Int] {
|
||||||
|
var result: [Int] = []
|
||||||
|
var items: [PercentCounterItem] = []
|
||||||
|
for _ in votes {
|
||||||
|
result.append(0)
|
||||||
|
items.append(PercentCounterItem())
|
||||||
|
}
|
||||||
|
|
||||||
|
let count = votes.count
|
||||||
|
|
||||||
|
var left:Int = 100
|
||||||
|
for i in 0 ..< votes.count {
|
||||||
|
let votes = votes[i]
|
||||||
|
items[i].index = i
|
||||||
|
items[i].percent = Int((Float(votes) * 100) / Float(total))
|
||||||
|
items[i].remainder = (votes * 100) - (items[i].percent * total)
|
||||||
|
left -= items[i].percent
|
||||||
|
}
|
||||||
|
|
||||||
|
if left > 0 && left <= count {
|
||||||
|
items = adjustPercentCount(items, left: left)
|
||||||
|
}
|
||||||
|
for item in items {
|
||||||
|
result[item.index] = item.percent
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
@ -1,19 +0,0 @@
|
|||||||
//
|
|
||||||
// TextFormat.h
|
|
||||||
// TextFormat
|
|
||||||
//
|
|
||||||
// Created by Peter on 8/1/19.
|
|
||||||
// Copyright © 2019 Telegram Messenger LLP. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#import <UIKit/UIKit.h>
|
|
||||||
|
|
||||||
//! Project version number for TextFormat.
|
|
||||||
FOUNDATION_EXPORT double TextFormatVersionNumber;
|
|
||||||
|
|
||||||
//! Project version string for TextFormat.
|
|
||||||
FOUNDATION_EXPORT const unsigned char TextFormatVersionString[];
|
|
||||||
|
|
||||||
// In this header, you should import all the public headers of your framework using statements like #import <TextFormat/PublicHeader.h>
|
|
||||||
|
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user