mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-01 12:17:53 +00:00
Fix RTL in polls
Fix percentages in polls
This commit is contained in:
parent
ea4b62939b
commit
3302f0ab4f
@ -400,7 +400,7 @@ func contextMenuForChatPresentationIntefaceState(chatPresentationInterfaceState:
|
|||||||
|
|
||||||
var activePoll: TelegramMediaPoll?
|
var activePoll: TelegramMediaPoll?
|
||||||
for media in message.media {
|
for media in message.media {
|
||||||
if let poll = media as? TelegramMediaPoll, !poll.isClosed {
|
if let poll = media as? TelegramMediaPoll, !poll.isClosed, message.id.namespace == Namespaces.Message.Cloud, poll.pollId.namespace == Namespaces.Media.CloudPoll {
|
||||||
activePoll = poll
|
activePoll = poll
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -429,8 +429,34 @@ func contextMenuForChatPresentationIntefaceState(chatPresentationInterfaceState:
|
|||||||
interfaceInteraction.unpinMessage()
|
interfaceInteraction.unpinMessage()
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if let _ = activePoll, messages[0].forwardInfo == nil, !messages[0].flags.contains(.Incoming) {
|
if let _ = activePoll, messages[0].forwardInfo == nil {
|
||||||
|
var canStopPoll = false
|
||||||
|
if !messages[0].flags.contains(.Incoming) {
|
||||||
|
canStopPoll = true
|
||||||
|
} else {
|
||||||
|
var hasEditRights = false
|
||||||
|
if messages[0].id.namespace == Namespaces.Message.Cloud {
|
||||||
|
if message.id.peerId.namespace == Namespaces.Peer.SecretChat {
|
||||||
|
hasEditRights = false
|
||||||
|
} else if let author = message.author, author.id == account.peerId {
|
||||||
|
hasEditRights = true
|
||||||
|
} else if message.author?.id == message.id.peerId, let peer = message.peers[message.id.peerId] {
|
||||||
|
if let peer = peer as? TelegramChannel, case .broadcast = peer.info {
|
||||||
|
if peer.hasAdminRights(.canEditMessages) {
|
||||||
|
hasEditRights = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if hasEditRights {
|
||||||
|
canStopPoll = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if canStopPoll {
|
||||||
actions.append(.sheet(ChatMessageContextMenuSheetAction(color: .accent, title: chatPresentationInterfaceState.strings.Conversation_StopPoll, action: {
|
actions.append(.sheet(ChatMessageContextMenuSheetAction(color: .accent, title: chatPresentationInterfaceState.strings.Conversation_StopPoll, action: {
|
||||||
interfaceInteraction.requestStopPollInMessage(messages[0].id)
|
interfaceInteraction.requestStopPollInMessage(messages[0].id)
|
||||||
})))
|
})))
|
||||||
|
|||||||
@ -203,13 +203,13 @@ private final class ChatMessagePollOptionRadioNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private let percentageFont = Font.bold(14.0)
|
private let percentageFont = Font.bold(14.5)
|
||||||
|
|
||||||
private func generatePercentageImage(presentationData: ChatPresentationData, incoming: Bool, value: CGFloat) -> UIImage {
|
private func generatePercentageImage(presentationData: ChatPresentationData, incoming: Bool, value: CGFloat) -> UIImage {
|
||||||
return generateImage(CGSize(width: 42.0, height: 20.0), rotatedContext: { size, context in
|
return generateImage(CGSize(width: 42.0, height: 20.0), rotatedContext: { size, context in
|
||||||
UIGraphicsPushContext(context)
|
UIGraphicsPushContext(context)
|
||||||
context.clear(CGRect(origin: CGPoint(), size: size))
|
context.clear(CGRect(origin: CGPoint(), size: size))
|
||||||
let percents = Int(value * 100.0)
|
let percents = Int(round(value * 100.0))
|
||||||
let string = NSAttributedString(string: "\(percents)%", font: percentageFont, textColor: incoming ? presentationData.theme.theme.chat.bubble.incomingPrimaryTextColor : presentationData.theme.theme.chat.bubble.outgoingPrimaryTextColor, paragraphAlignment: .right)
|
let string = NSAttributedString(string: "\(percents)%", font: percentageFont, textColor: incoming ? presentationData.theme.theme.chat.bubble.incomingPrimaryTextColor : presentationData.theme.theme.chat.bubble.outgoingPrimaryTextColor, paragraphAlignment: .right)
|
||||||
string.draw(in: CGRect(origin: CGPoint(x: 0.0, y: 2.0), size: size))
|
string.draw(in: CGRect(origin: CGPoint(x: 0.0, y: 2.0), size: size))
|
||||||
UIGraphicsPopContext()
|
UIGraphicsPopContext()
|
||||||
@ -300,7 +300,7 @@ private final class ChatMessagePollOptionNode: ASDisplayNode {
|
|||||||
|
|
||||||
return { accountPeerId, presentationData, message, option, optionResult, constrainedWidth in
|
return { accountPeerId, presentationData, message, option, optionResult, constrainedWidth in
|
||||||
let leftInset: CGFloat = 50.0
|
let leftInset: CGFloat = 50.0
|
||||||
let rightInset: CGFloat = 18.0
|
let rightInset: CGFloat = 12.0
|
||||||
|
|
||||||
let incoming = message.effectivelyIncoming(accountPeerId)
|
let incoming = message.effectivelyIncoming(accountPeerId)
|
||||||
|
|
||||||
@ -336,7 +336,11 @@ private final class ChatMessagePollOptionNode: ASDisplayNode {
|
|||||||
node.addSubnode(titleNode)
|
node.addSubnode(titleNode)
|
||||||
titleNode.isUserInteractionEnabled = false
|
titleNode.isUserInteractionEnabled = false
|
||||||
}
|
}
|
||||||
|
if titleLayout.hasRTL {
|
||||||
|
titleNode.frame = CGRect(origin: CGPoint(x: width - rightInset - titleLayout.size.width, y: 11.0), size: titleLayout.size)
|
||||||
|
} else {
|
||||||
titleNode.frame = CGRect(origin: CGPoint(x: leftInset, y: 11.0), size: titleLayout.size)
|
titleNode.frame = CGRect(origin: CGPoint(x: leftInset, y: 11.0), size: titleLayout.size)
|
||||||
|
}
|
||||||
|
|
||||||
if shouldHaveRadioNode {
|
if shouldHaveRadioNode {
|
||||||
let radioNode: ChatMessagePollOptionRadioNode
|
let radioNode: ChatMessagePollOptionRadioNode
|
||||||
@ -368,11 +372,12 @@ private final class ChatMessagePollOptionNode: ASDisplayNode {
|
|||||||
if let image = node.percentageImage {
|
if let image = node.percentageImage {
|
||||||
node.percentageNode.frame = CGRect(origin: CGPoint(x: leftInset - 7.0 - image.size.width, y: 12.0), size: image.size)
|
node.percentageNode.frame = CGRect(origin: CGPoint(x: leftInset - 7.0 - image.size.width, y: 12.0), size: image.size)
|
||||||
if animated, let optionResult = optionResult {
|
if animated, let optionResult = optionResult {
|
||||||
let images = generatePercentageAnimationImages(presentationData: presentationData, incoming: incoming, from: previousResult?.absolute ?? 0.0, to: optionResult.absolute, duration: 0.4)
|
let percentageDuration = 0.27
|
||||||
|
let images = generatePercentageAnimationImages(presentationData: presentationData, incoming: incoming, from: previousResult?.absolute ?? 0.0, to: optionResult.absolute, duration: percentageDuration)
|
||||||
if !images.isEmpty {
|
if !images.isEmpty {
|
||||||
let animation = CAKeyframeAnimation(keyPath: "contents")
|
let animation = CAKeyframeAnimation(keyPath: "contents")
|
||||||
animation.values = images.map { $0.cgImage! }
|
animation.values = images.map { $0.cgImage! }
|
||||||
animation.duration = 0.4 * UIView.animationDurationFactor()
|
animation.duration = percentageDuration * UIView.animationDurationFactor()
|
||||||
animation.calculationMode = kCAAnimationDiscrete
|
animation.calculationMode = kCAAnimationDiscrete
|
||||||
node.percentageNode.layer.add(animation, forKey: "image")
|
node.percentageNode.layer.add(animation, forKey: "image")
|
||||||
}
|
}
|
||||||
@ -776,7 +781,11 @@ class ChatMessagePollBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
strongSelf.statusNode.removeFromSupernode()
|
strongSelf.statusNode.removeFromSupernode()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if textLayout.hasRTL {
|
||||||
|
strongSelf.textNode.frame = CGRect(origin: CGPoint(x: resultSize.width - textFrame.size.width - textInsets.left - layoutConstants.text.bubbleInsets.right, y: textFrame.origin.y), size: textFrame.size)
|
||||||
|
} else {
|
||||||
strongSelf.textNode.frame = textFrame
|
strongSelf.textNode.frame = textFrame
|
||||||
|
}
|
||||||
strongSelf.typeNode.frame = CGRect(origin: CGPoint(x: textFrame.minX, y: textFrame.maxY + titleTypeSpacing), size: typeLayout.size)
|
strongSelf.typeNode.frame = CGRect(origin: CGPoint(x: textFrame.minX, y: textFrame.maxY + titleTypeSpacing), size: typeLayout.size)
|
||||||
|
|
||||||
let _ = votersApply()
|
let _ = votersApply()
|
||||||
|
|||||||
@ -101,7 +101,7 @@ func legacyAttachmentMenu(account: Account, peer: Peer, editMediaOptions: Messag
|
|||||||
})!
|
})!
|
||||||
itemViews.append(locationItem)
|
itemViews.append(locationItem)
|
||||||
|
|
||||||
if !(peer is TelegramSecretChat) && canSendMessagesToPeer(peer) {
|
if (peer is TelegramGroup || peer is TelegramChannel) && canSendMessagesToPeer(peer) {
|
||||||
let pollItem = TGMenuSheetButtonItemView(title: strings.AttachmentMenu_Poll, type: TGMenuSheetButtonTypeDefault, action: { [weak controller] in
|
let pollItem = TGMenuSheetButtonItemView(title: strings.AttachmentMenu_Poll, type: TGMenuSheetButtonTypeDefault, action: { [weak controller] in
|
||||||
controller?.dismiss(animated: true)
|
controller?.dismiss(animated: true)
|
||||||
openPoll()
|
openPoll()
|
||||||
|
|||||||
@ -79,7 +79,7 @@ private struct CollectableExternalShareItem {
|
|||||||
let mediaReference: AnyMediaReference?
|
let mediaReference: AnyMediaReference?
|
||||||
}
|
}
|
||||||
|
|
||||||
private func collectExternalShareItems(postbox: Postbox, collectableItems: [CollectableExternalShareItem]) -> Signal<ExternalShareItemsState, NoError> {
|
private func collectExternalShareItems(strings: PresentationStrings, postbox: Postbox, collectableItems: [CollectableExternalShareItem]) -> Signal<ExternalShareItemsState, NoError> {
|
||||||
var signals: [Signal<ExternalShareItemStatus, NoError>] = []
|
var signals: [Signal<ExternalShareItemStatus, NoError>] = []
|
||||||
for item in collectableItems {
|
for item in collectableItems {
|
||||||
if let mediaReference = item.mediaReference, let file = mediaReference.media as? TelegramMediaFile {
|
if let mediaReference = item.mediaReference, let file = mediaReference.media as? TelegramMediaFile {
|
||||||
@ -135,6 +135,19 @@ private func collectExternalShareItems(postbox: Postbox, collectableItems: [Coll
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
} else if let mediaReference = item.mediaReference, let poll = mediaReference.media as? TelegramMediaPoll {
|
||||||
|
var text = "📊 \(poll.text)"
|
||||||
|
text.append("\n\(strings.MessagePoll_LabelAnonymous)")
|
||||||
|
for option in poll.options {
|
||||||
|
text.append("\n— \(option.text)")
|
||||||
|
}
|
||||||
|
let totalVoters = poll.results.totalVoters ?? 0
|
||||||
|
if totalVoters == 0 {
|
||||||
|
text.append("\n\(strings.MessagePoll_NoVotes)")
|
||||||
|
} else {
|
||||||
|
text.append("\n\(strings.MessagePoll_VotedCount(totalVoters))")
|
||||||
|
}
|
||||||
|
signals.append(.single(.done(.text(text))))
|
||||||
}
|
}
|
||||||
if let url = item.url, let parsedUrl = URL(string: url) {
|
if let url = item.url, let parsedUrl = URL(string: url) {
|
||||||
if signals.isEmpty {
|
if signals.isEmpty {
|
||||||
@ -454,6 +467,9 @@ public final class ShareController: ViewController {
|
|||||||
selectedMedia = image
|
selectedMedia = image
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case let _ as TelegramMediaPoll:
|
||||||
|
selectedMedia = media
|
||||||
|
break loop
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -468,7 +484,7 @@ public final class ShareController: ViewController {
|
|||||||
case .fromExternal:
|
case .fromExternal:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
return (collectExternalShareItems(postbox: strongSelf.account.postbox, collectableItems: collectableItems) |> deliverOnMainQueue) |> map { state in
|
return (collectExternalShareItems(strings: strongSelf.presentationData.strings, postbox: strongSelf.account.postbox, collectableItems: collectableItems) |> deliverOnMainQueue) |> map { state in
|
||||||
switch state {
|
switch state {
|
||||||
case .progress:
|
case .progress:
|
||||||
return .preparing
|
return .preparing
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user