mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-10-09 03:20:48 +00:00
Poll UI improvements
This commit is contained in:
parent
2a6f1f811b
commit
6d5bfe1f1e
@ -396,7 +396,7 @@ private func createPollControllerEntries(presentationData: PresentationData, pee
|
||||
}
|
||||
|
||||
var canBePublic = true
|
||||
if let channel = peer as? TelegramChannel, case .broadcast = channel.info, let username = channel.username, !username.isEmpty {
|
||||
if let channel = peer as? TelegramChannel, case .broadcast = channel.info {
|
||||
canBePublic = false
|
||||
}
|
||||
|
||||
|
@ -3049,7 +3049,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
||||
stickLocationDistanceFactor = max(0.0, min(1.0, stickLocationDistance / itemHeaderHeight))
|
||||
case .topEdge:
|
||||
headerFrame = CGRect(origin: CGPoint(x: 0.0, y: min(max(upperDisplayBound, upperBoundEdge - itemHeaderHeight), lowerBound - itemHeaderHeight)), size: CGSize(width: self.visibleSize.width, height: itemHeaderHeight))
|
||||
stickLocationDistance = headerFrame.maxY - upperBoundEdge - itemHeaderHeight
|
||||
stickLocationDistance = headerFrame.minY - upperBoundEdge + itemHeaderHeight
|
||||
stickLocationDistanceFactor = max(0.0, min(1.0, stickLocationDistance / itemHeaderHeight))
|
||||
case .bottom:
|
||||
headerFrame = CGRect(origin: CGPoint(x: 0.0, y: max(upperBound, min(lowerBound, lowerDisplayBound) - itemHeaderHeight)), size: CGSize(width: self.visibleSize.width, height: itemHeaderHeight))
|
||||
|
@ -66,7 +66,7 @@ private final class ShimmerEffectNode: ASDisplayNode {
|
||||
self.currentBackgroundColor = backgroundColor
|
||||
self.currentForegroundColor = foregroundColor
|
||||
|
||||
self.imageNode.image = generateImage(CGSize(width: 8.0, height: 100.0), opaque: true, scale: 1.0, rotatedContext: { size, context in
|
||||
self.imageNode.image = generateImage(CGSize(width: 4.0, height: 320.0), opaque: true, scale: 1.0, rotatedContext: { size, context in
|
||||
context.setFillColor(backgroundColor.cgColor)
|
||||
context.fill(CGRect(origin: CGPoint(), size: size))
|
||||
|
||||
@ -1288,7 +1288,7 @@ public final class ItemListPeerItemHeaderNode: ListViewItemHeaderNode {
|
||||
private let actionTextNode: ImmediateTextNode
|
||||
private let actionButton: HighlightableButtonNode
|
||||
|
||||
private var stickDistanceFactor: CGFloat = 0.0
|
||||
private var stickDistanceFactor: CGFloat?
|
||||
|
||||
public init(theme: PresentationTheme, strings: PresentationStrings, text: String, actionTitle: String?, action: (() -> Void)?) {
|
||||
self.theme = theme
|
||||
@ -1305,6 +1305,7 @@ public final class ItemListPeerItemHeaderNode: ListViewItemHeaderNode {
|
||||
|
||||
self.separatorNode = ASDisplayNode()
|
||||
self.separatorNode.backgroundColor = theme.list.itemBlocksSeparatorColor
|
||||
self.separatorNode.alpha = 0.0
|
||||
|
||||
let titleFont = Font.regular(13.0)
|
||||
|
||||
@ -1391,6 +1392,20 @@ public final class ItemListPeerItemHeaderNode: ListViewItemHeaderNode {
|
||||
}
|
||||
|
||||
override public func updateStickDistanceFactor(_ factor: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||
if self.stickDistanceFactor == factor {
|
||||
return
|
||||
}
|
||||
self.stickDistanceFactor = factor
|
||||
if let (size, leftInset, _) = self.validLayout {
|
||||
if leftInset.isZero {
|
||||
transition.updateAlpha(node: self.separatorNode, alpha: 1.0)
|
||||
transition.updateAlpha(node: self.snappedBackgroundNode, alpha: (1.0 - factor) * 0.0 + factor * 1.0)
|
||||
} else {
|
||||
let distance = factor * size.height
|
||||
let alpha = abs(distance) / 16.0
|
||||
transition.updateAlpha(node: self.separatorNode, alpha: max(0.0, min(1.0, alpha)))
|
||||
transition.updateAlpha(node: self.snappedBackgroundNode, alpha: 0.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -116,8 +116,7 @@ public class ItemListTextItemNode: ListViewItemNode, ItemListItemNode {
|
||||
var bottomInset: CGFloat = 7.0
|
||||
|
||||
let titleFont = Font.regular(item.presentationData.fontSize.itemListBaseHeaderFontSize)
|
||||
let largeTitleFont = Font.semibold(floor(item.presentationData.fontSize.itemListBaseHeaderFontSize * 2.0))
|
||||
let semiLargeTitleFont = Font.semibold(floor(item.presentationData.fontSize.itemListBaseHeaderFontSize * 1.2))
|
||||
let largeTitleFont = Font.semibold(floor(item.presentationData.fontSize.itemListBaseFontSize))
|
||||
let titleBoldFont = Font.semibold(item.presentationData.fontSize.itemListBaseHeaderFontSize)
|
||||
|
||||
let attributedText: NSAttributedString
|
||||
@ -125,13 +124,7 @@ public class ItemListTextItemNode: ListViewItemNode, ItemListItemNode {
|
||||
case let .plain(text):
|
||||
attributedText = NSAttributedString(string: text, font: titleFont, textColor: item.presentationData.theme.list.freeTextColor)
|
||||
case let .large(text):
|
||||
let font: UIFont
|
||||
if params.width >= 330.0 {
|
||||
font = largeTitleFont
|
||||
} else {
|
||||
font = semiLargeTitleFont
|
||||
}
|
||||
attributedText = NSAttributedString(string: text, font: font, textColor: item.presentationData.theme.list.itemPrimaryTextColor)
|
||||
attributedText = NSAttributedString(string: text, font: largeTitleFont, textColor: item.presentationData.theme.list.itemPrimaryTextColor)
|
||||
case let .markdown(text):
|
||||
attributedText = parseMarkdownIntoAttributedString(text, attributes: MarkdownAttributes(body: MarkdownAttributeSet(font: titleFont, textColor: item.presentationData.theme.list.freeTextColor), bold: MarkdownAttributeSet(font: titleBoldFont, textColor: item.presentationData.theme.list.freeTextColor), link: MarkdownAttributeSet(font: titleFont, textColor: item.presentationData.theme.list.itemAccentColor), linkAttribute: { contents in
|
||||
return (TelegramTextAttributes.URL, contents)
|
||||
|
@ -38,6 +38,13 @@ public struct ValueBoxKey: Equatable, Hashable, CustomStringConvertible, Compara
|
||||
memcpy(self.memory, buffer.memory, buffer.length)
|
||||
}
|
||||
|
||||
public func setData(_ offset: Int, value: Data) {
|
||||
let valueLength = value.count
|
||||
value.withUnsafeBytes { (bytes: UnsafePointer<UInt8>) -> Void in
|
||||
memcpy(self.memory + offset, bytes, valueLength)
|
||||
}
|
||||
}
|
||||
|
||||
public func setInt32(_ offset: Int, value: Int32) {
|
||||
var bigEndianValue = Int32(bigEndian: value)
|
||||
memcpy(self.memory + offset, &bigEndianValue, 4)
|
||||
|
@ -67,7 +67,8 @@ public struct Namespaces {
|
||||
public static let cachedStickerQueryResults: Int8 = 5
|
||||
public static let cachedSecureIdConfiguration: Int8 = 6
|
||||
public static let cachedWallpapersConfiguration: Int8 = 7
|
||||
public static let cachedThemesConfiguration: Int8 = 7
|
||||
public static let cachedThemesConfiguration: Int8 = 8
|
||||
public static let cachedPollResults: Int8 = 9
|
||||
}
|
||||
|
||||
public struct UnorderedItemList {
|
||||
|
@ -151,6 +151,7 @@ private var declaredEncodables: Void = {
|
||||
declareEncodable(WalletCollection.self, f: { WalletCollection(decoder: $0) })
|
||||
declareEncodable(EmbeddedMediaStickersMessageAttribute.self, f: { EmbeddedMediaStickersMessageAttribute(decoder: $0) })
|
||||
declareEncodable(TelegramMediaWebpageAttribute.self, f: { TelegramMediaWebpageAttribute(decoder: $0) })
|
||||
declareEncodable(CachedPollOptionResult.self, f: { CachedPollOptionResult(decoder: $0) })
|
||||
|
||||
return
|
||||
}()
|
||||
|
@ -124,9 +124,40 @@ public func requestClosePoll(postbox: Postbox, network: Network, stateManager: A
|
||||
}
|
||||
}
|
||||
|
||||
private let cachedPollResultsCollectionSpec = ItemCacheCollectionSpec(lowWaterItemCount: 20, highWaterItemCount: 40)
|
||||
|
||||
final class CachedPollOptionResult: PostboxCoding {
|
||||
let peerIds: [PeerId]
|
||||
let count: Int32
|
||||
|
||||
public static func key(pollId: MediaId, optionOpaqueIdentifier: Data) -> ValueBoxKey {
|
||||
let key = ValueBoxKey(length: 4 + 8 + optionOpaqueIdentifier.count)
|
||||
key.setInt32(0, value: pollId.namespace)
|
||||
key.setInt64(4, value: pollId.id)
|
||||
key.setData(4 + 8, value: optionOpaqueIdentifier)
|
||||
return key
|
||||
}
|
||||
|
||||
public init(peerIds: [PeerId], count: Int32) {
|
||||
self.peerIds = peerIds
|
||||
self.count = count
|
||||
}
|
||||
|
||||
public init(decoder: PostboxDecoder) {
|
||||
self.peerIds = decoder.decodeInt64ArrayForKey("peerIds").map(PeerId.init)
|
||||
self.count = decoder.decodeInt32ForKey("count", orElse: 0)
|
||||
}
|
||||
|
||||
public func encode(_ encoder: PostboxEncoder) {
|
||||
encoder.encodeInt64Array(self.peerIds.map { $0.toInt64() }, forKey: "peerIds")
|
||||
encoder.encodeInt32(self.count, forKey: "count")
|
||||
}
|
||||
}
|
||||
|
||||
private final class PollResultsOptionContext {
|
||||
private let queue: Queue
|
||||
private let account: Account
|
||||
private let pollId: MediaId
|
||||
private let messageId: MessageId
|
||||
private let opaqueIdentifier: Data
|
||||
private let disposable = MetaDisposable()
|
||||
@ -136,15 +167,46 @@ private final class PollResultsOptionContext {
|
||||
private var nextOffset: String?
|
||||
private var results: [RenderedPeer] = []
|
||||
private var count: Int
|
||||
private var populateCache: Bool = true
|
||||
|
||||
let state = Promise<PollResultsOptionState>()
|
||||
|
||||
init(queue: Queue, account: Account, messageId: MessageId, opaqueIdentifier: Data, count: Int) {
|
||||
init(queue: Queue, account: Account, pollId: MediaId, messageId: MessageId, opaqueIdentifier: Data, count: Int) {
|
||||
self.queue = queue
|
||||
self.account = account
|
||||
self.pollId = pollId
|
||||
self.messageId = messageId
|
||||
self.opaqueIdentifier = opaqueIdentifier
|
||||
self.count = count
|
||||
|
||||
self.isLoadingMore = true
|
||||
self.disposable.set((account.postbox.transaction { transaction -> [RenderedPeer]? in
|
||||
let cachedResult = transaction.retrieveItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedPollResults, key: CachedPollOptionResult.key(pollId: pollId, optionOpaqueIdentifier: opaqueIdentifier))) as? CachedPollOptionResult
|
||||
if let cachedResult = cachedResult, Int(cachedResult.count) == count {
|
||||
var result: [RenderedPeer] = []
|
||||
for peerId in cachedResult.peerIds {
|
||||
if let peer = transaction.getPeer(peerId) {
|
||||
result.append(RenderedPeer(peer: peer))
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return result
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|> deliverOn(self.queue)).start(next: { [weak self] cachedPeers in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
strongSelf.isLoadingMore = false
|
||||
if let cachedPeers = cachedPeers {
|
||||
strongSelf.results = cachedPeers
|
||||
strongSelf.hasLoadedOnce = true
|
||||
}
|
||||
strongSelf.loadMore()
|
||||
}))
|
||||
}
|
||||
|
||||
deinit {
|
||||
@ -156,10 +218,12 @@ private final class PollResultsOptionContext {
|
||||
return
|
||||
}
|
||||
self.isLoadingMore = true
|
||||
let pollId = self.pollId
|
||||
let messageId = self.messageId
|
||||
let opaqueIdentifier = self.opaqueIdentifier
|
||||
let account = self.account
|
||||
let nextOffset = self.nextOffset
|
||||
let populateCache = self.populateCache
|
||||
self.disposable.set((self.account.postbox.transaction { transaction -> Api.InputPeer? in
|
||||
return transaction.getPeer(messageId.peerId).flatMap(apiInputPeer)
|
||||
}
|
||||
@ -193,12 +257,15 @@ private final class PollResultsOptionContext {
|
||||
}
|
||||
}
|
||||
}
|
||||
if populateCache {
|
||||
transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedPollResults, key: CachedPollOptionResult.key(pollId: pollId, optionOpaqueIdentifier: opaqueIdentifier)), entry: CachedPollOptionResult(peerIds: resultPeers.map { $0.peerId }, count: count), collectionSpec: cachedPollResultsCollectionSpec)
|
||||
}
|
||||
return (resultPeers, Int(count), nextOffset)
|
||||
}
|
||||
}
|
||||
}
|
||||
#if DEBUG
|
||||
return signal |> delay(4.0, queue: .concurrentDefaultQueue())
|
||||
//return signal |> delay(4.0, queue: .concurrentDefaultQueue())
|
||||
#endif
|
||||
return signal
|
||||
} else {
|
||||
@ -209,6 +276,10 @@ private final class PollResultsOptionContext {
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
if strongSelf.populateCache {
|
||||
strongSelf.populateCache = false
|
||||
strongSelf.results.removeAll()
|
||||
}
|
||||
var existingIds = Set(strongSelf.results.map { $0.peerId })
|
||||
for peer in peers {
|
||||
if !existingIds.contains(peer.peerId) {
|
||||
@ -266,7 +337,7 @@ private final class PollResultsContextImpl {
|
||||
}
|
||||
}
|
||||
}
|
||||
self.optionContexts[option.opaqueIdentifier] = PollResultsOptionContext(queue: self.queue, account: account, messageId: messageId, opaqueIdentifier: option.opaqueIdentifier, count: count)
|
||||
self.optionContexts[option.opaqueIdentifier] = PollResultsOptionContext(queue: self.queue, account: account, pollId: poll.pollId, messageId: messageId, opaqueIdentifier: option.opaqueIdentifier, count: count)
|
||||
}
|
||||
|
||||
self.state.set(combineLatest(queue: self.queue, self.optionContexts.map { (opaqueIdentifier, context) -> Signal<(Data, PollResultsOptionState), NoError> in
|
||||
|
@ -343,7 +343,7 @@ public func makeDefaultDarkPresentationTheme(extendingThemeReference: Presentati
|
||||
primaryColor: UIColor(rgb: 0xffffff),
|
||||
controlColor: UIColor(rgb: 0x4d4d4d)
|
||||
),
|
||||
mediaPlaceholderColor: UIColor(rgb: 0xffffff).withMultipliedBrightnessBy(0.1),
|
||||
mediaPlaceholderColor: UIColor(rgb: 0xffffff).withMultipliedBrightnessBy(0.05),
|
||||
scrollIndicatorColor: UIColor(rgb: 0xffffff, alpha: 0.3),
|
||||
pageIndicatorInactiveColor: UIColor(white: 1.0, alpha: 0.3),
|
||||
inputClearButtonColor: UIColor(rgb: 0x8b9197),
|
||||
|
@ -644,7 +644,7 @@ public func makeDefaultDarkTintedPresentationTheme(extendingThemeReference: Pres
|
||||
|
||||
let message = PresentationThemeChatMessage(
|
||||
incoming: PresentationThemePartedColors(bubble: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: mainBackgroundColor, highlightedFill: highlightedIncomingBubbleColor, stroke: mainBackgroundColor), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: mainBackgroundColor, highlightedFill: highlightedIncomingBubbleColor, stroke: mainBackgroundColor)), primaryTextColor: .white, secondaryTextColor: mainSecondaryTextColor.withAlphaComponent(0.5), linkTextColor: accentColor, linkHighlightColor: accentColor.withAlphaComponent(0.5), scamColor: UIColor(rgb: 0xff6767), textHighlightColor: UIColor(rgb: 0xf5c038), accentTextColor: accentColor, accentControlColor: accentColor, accentControlDisabledColor: mainSecondaryTextColor.withAlphaComponent(0.5), mediaActiveControlColor: accentColor, mediaInactiveControlColor: accentColor.withAlphaComponent(0.5), mediaControlInnerBackgroundColor: mainBackgroundColor, pendingActivityColor: mainSecondaryTextColor.withAlphaComponent(0.5), fileTitleColor: accentColor, fileDescriptionColor: mainSecondaryTextColor.withAlphaComponent(0.5), fileDurationColor: mainSecondaryTextColor.withAlphaComponent(0.5), mediaPlaceholderColor: accentColor.withMultiplied(hue: 1.019, saturation: 0.585, brightness: 0.23), polls: PresentationThemeChatBubblePolls(radioButton: accentColor.withMultiplied(hue: 0.995, saturation: 0.317, brightness: 0.51), radioProgress: accentColor, highlight: accentColor.withAlphaComponent(0.12), separator: mainSeparatorColor, bar: accentColor, barIconForeground: .white, barPositive: UIColor(rgb: 0x00A700), barNegative: UIColor(rgb: 0xFE3824)), actionButtonsFillColor: PresentationThemeVariableColor(withWallpaper: additionalBackgroundColor.withAlphaComponent(0.5), withoutWallpaper: additionalBackgroundColor.withAlphaComponent(0.5)), actionButtonsStrokeColor: PresentationThemeVariableColor(color: buttonStrokeColor), actionButtonsTextColor: PresentationThemeVariableColor(color: .white), textSelectionColor: accentColor.withAlphaComponent(0.2), textSelectionKnobColor: accentColor),
|
||||
outgoing: PresentationThemePartedColors(bubble: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: outgoingBubbleFillColor, gradientFill: outgoingBubbleFillGradientColor, highlightedFill: highlightedOutgoingBubbleColor, stroke: outgoingBubbleFillColor), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: outgoingBubbleFillColor, gradientFill: outgoingBubbleFillGradientColor, highlightedFill: highlightedOutgoingBubbleColor, stroke: outgoingBubbleFillColor)), primaryTextColor: outgoingPrimaryTextColor, secondaryTextColor: outgoingSecondaryTextColor, linkTextColor: outgoingLinkTextColor, linkHighlightColor: UIColor.white.withAlphaComponent(0.5), scamColor: outgoingScamColor, textHighlightColor: UIColor(rgb: 0xf5c038), accentTextColor: outgoingPrimaryTextColor, accentControlColor: outgoingPrimaryTextColor, accentControlDisabledColor: mainSecondaryTextColor.withAlphaComponent(0.5), mediaActiveControlColor: outgoingPrimaryTextColor, mediaInactiveControlColor: outgoingSecondaryTextColor, mediaControlInnerBackgroundColor: outgoingBubbleFillColor, pendingActivityColor: outgoingSecondaryTextColor, fileTitleColor: outgoingPrimaryTextColor, fileDescriptionColor: outgoingSecondaryTextColor, fileDurationColor: outgoingSecondaryTextColor, mediaPlaceholderColor: accentColor.withMultiplied(hue: 1.019, saturation: 0.804, brightness: 0.51), polls: PresentationThemeChatBubblePolls(radioButton: outgoingPrimaryTextColor, radioProgress: accentColor.withMultiplied(hue: 0.99, saturation: 0.56, brightness: 1.0), highlight: accentColor.withMultiplied(hue: 0.99, saturation: 0.56, brightness: 1.0).withAlphaComponent(0.12), separator: mainSeparatorColor, bar: outgoingPrimaryTextColor, barIconForeground: .white, barPositive: outgoingPrimaryTextColor, barNegative: outgoingPrimaryTextColor), actionButtonsFillColor: PresentationThemeVariableColor(withWallpaper: additionalBackgroundColor.withAlphaComponent(0.5), withoutWallpaper: additionalBackgroundColor.withAlphaComponent(0.5)), actionButtonsStrokeColor: PresentationThemeVariableColor(color: buttonStrokeColor), actionButtonsTextColor: PresentationThemeVariableColor(color: .white), textSelectionColor: UIColor.white.withAlphaComponent(0.2), textSelectionKnobColor: UIColor.white),
|
||||
outgoing: PresentationThemePartedColors(bubble: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: outgoingBubbleFillColor, gradientFill: outgoingBubbleFillGradientColor, highlightedFill: highlightedOutgoingBubbleColor, stroke: outgoingBubbleFillColor), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: outgoingBubbleFillColor, gradientFill: outgoingBubbleFillGradientColor, highlightedFill: highlightedOutgoingBubbleColor, stroke: outgoingBubbleFillColor)), primaryTextColor: outgoingPrimaryTextColor, secondaryTextColor: outgoingSecondaryTextColor, linkTextColor: outgoingLinkTextColor, linkHighlightColor: UIColor.white.withAlphaComponent(0.5), scamColor: outgoingScamColor, textHighlightColor: UIColor(rgb: 0xf5c038), accentTextColor: outgoingPrimaryTextColor, accentControlColor: outgoingPrimaryTextColor, accentControlDisabledColor: mainSecondaryTextColor.withAlphaComponent(0.5), mediaActiveControlColor: outgoingPrimaryTextColor, mediaInactiveControlColor: outgoingSecondaryTextColor, mediaControlInnerBackgroundColor: outgoingBubbleFillColor, pendingActivityColor: outgoingSecondaryTextColor, fileTitleColor: outgoingPrimaryTextColor, fileDescriptionColor: outgoingSecondaryTextColor, fileDurationColor: outgoingSecondaryTextColor, mediaPlaceholderColor: accentColor.withMultiplied(hue: 1.019, saturation: 0.804, brightness: 0.51), polls: PresentationThemeChatBubblePolls(radioButton: outgoingPrimaryTextColor, radioProgress: accentColor.withMultiplied(hue: 0.99, saturation: 0.56, brightness: 1.0), highlight: accentColor.withMultiplied(hue: 0.99, saturation: 0.56, brightness: 1.0).withAlphaComponent(0.12), separator: mainSeparatorColor, bar: outgoingPrimaryTextColor, barIconForeground: .clear, barPositive: outgoingPrimaryTextColor, barNegative: outgoingPrimaryTextColor), actionButtonsFillColor: PresentationThemeVariableColor(withWallpaper: additionalBackgroundColor.withAlphaComponent(0.5), withoutWallpaper: additionalBackgroundColor.withAlphaComponent(0.5)), actionButtonsStrokeColor: PresentationThemeVariableColor(color: buttonStrokeColor), actionButtonsTextColor: PresentationThemeVariableColor(color: .white), textSelectionColor: UIColor.white.withAlphaComponent(0.2), textSelectionKnobColor: UIColor.white),
|
||||
freeform: PresentationThemeBubbleColor(withWallpaper: PresentationThemeBubbleColorComponents(fill: mainBackgroundColor, highlightedFill: highlightedIncomingBubbleColor, stroke: mainBackgroundColor), withoutWallpaper: PresentationThemeBubbleColorComponents(fill: mainBackgroundColor, highlightedFill: highlightedIncomingBubbleColor, stroke: mainBackgroundColor)),
|
||||
infoPrimaryTextColor: UIColor(rgb: 0xffffff),
|
||||
infoLinkTextColor: accentColor,
|
||||
|
@ -1550,12 +1550,20 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
strongSelf.chatDisplayNode.historyNode.forEachVisibleItemNode { itemNode in
|
||||
if !found, let itemNode = itemNode as? ChatMessageBubbleItemNode, itemNode.item?.message.id == id {
|
||||
found = true
|
||||
if strongSelf.selectPollOptionFeedback == nil {
|
||||
strongSelf.selectPollOptionFeedback = HapticFeedback()
|
||||
}
|
||||
strongSelf.selectPollOptionFeedback?.error()
|
||||
itemNode.animateQuizInvalidOptionSelected()
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
if false {
|
||||
if strongSelf.selectPollOptionFeedback == nil {
|
||||
strongSelf.selectPollOptionFeedback = HapticFeedback()
|
||||
}
|
||||
strongSelf.selectPollOptionFeedback?.success()
|
||||
strongSelf.chatDisplayNode.animateQuizCorrectOptionSelected()
|
||||
return;
|
||||
}
|
||||
@ -1582,18 +1590,31 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
|
||||
switch resultPoll.kind {
|
||||
case .poll:
|
||||
break
|
||||
if strongSelf.selectPollOptionFeedback == nil {
|
||||
strongSelf.selectPollOptionFeedback = HapticFeedback()
|
||||
}
|
||||
strongSelf.selectPollOptionFeedback?.success()
|
||||
case .quiz:
|
||||
if let voters = resultPoll.results.voters {
|
||||
for voter in voters {
|
||||
if voter.selected {
|
||||
if voter.isCorrect {
|
||||
if strongSelf.selectPollOptionFeedback == nil {
|
||||
strongSelf.selectPollOptionFeedback = HapticFeedback()
|
||||
}
|
||||
strongSelf.selectPollOptionFeedback?.success()
|
||||
|
||||
strongSelf.chatDisplayNode.animateQuizCorrectOptionSelected()
|
||||
} else {
|
||||
var found = false
|
||||
strongSelf.chatDisplayNode.historyNode.forEachVisibleItemNode { itemNode in
|
||||
if !found, let itemNode = itemNode as? ChatMessageBubbleItemNode, itemNode.item?.message.id == id {
|
||||
found = true
|
||||
if strongSelf.selectPollOptionFeedback == nil {
|
||||
strongSelf.selectPollOptionFeedback = HapticFeedback()
|
||||
}
|
||||
strongSelf.selectPollOptionFeedback?.error()
|
||||
|
||||
itemNode.animateQuizInvalidOptionSelected()
|
||||
}
|
||||
}
|
||||
@ -1617,10 +1638,6 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
if controllerInteraction.pollActionState.pollMessageIdsInProgress.removeValue(forKey: id) != nil {
|
||||
strongSelf.chatDisplayNode.historyNode.requestMessageUpdate(id)
|
||||
}
|
||||
if strongSelf.selectPollOptionFeedback == nil {
|
||||
strongSelf.selectPollOptionFeedback = HapticFeedback()
|
||||
}
|
||||
strongSelf.selectPollOptionFeedback?.success()
|
||||
}), forKey: id)
|
||||
}
|
||||
}, requestOpenMessagePollResults: { [weak self] messageId, pollId in
|
||||
|
@ -1260,9 +1260,18 @@ class ChatMessagePollBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
}
|
||||
|
||||
var hasResults = false
|
||||
if let totalVoters = poll.results.totalVoters, totalVoters != 0 {
|
||||
if let _ = poll.results.voters {
|
||||
if poll.isClosed {
|
||||
hasResults = true
|
||||
} else {
|
||||
if let totalVoters = poll.results.totalVoters, totalVoters != 0 {
|
||||
if let voters = poll.results.voters {
|
||||
for voter in voters {
|
||||
if voter.selected {
|
||||
hasResults = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user