mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Various fixes
This commit is contained in:
parent
29a1d4ed2f
commit
fed488a806
@ -12542,3 +12542,7 @@ Sorry for the inconvenience.";
|
||||
"WebBrowser.LinkForwardTooltip.TwoChats.One" = "Link forwarded to **%@** and **%@**";
|
||||
"WebBrowser.LinkForwardTooltip.ManyChats.One" = "Link forwarded to **%@** and %@ others";
|
||||
"WebBrowser.LinkForwardTooltip.SavedMessages.One" = "Link forwarded to **Saved Messages**";
|
||||
|
||||
"Stars.Intro.StarsSent_1" = "%@ Star sent.";
|
||||
"Stars.Intro.StarsSent_any" = "%@ Stars sent.";
|
||||
"Stars.Intro.StarsSent.ViewChat" = "View Chat";
|
||||
|
@ -614,102 +614,6 @@ public enum ContactListActionItemIcon : Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
public struct ContactListAdditionalOption: Equatable {
|
||||
public let title: String
|
||||
public let icon: ContactListActionItemIcon
|
||||
public let action: () -> Void
|
||||
public let clearHighlightAutomatically: Bool
|
||||
|
||||
public init(title: String, icon: ContactListActionItemIcon, action: @escaping () -> Void, clearHighlightAutomatically: Bool = false) {
|
||||
self.title = title
|
||||
self.icon = icon
|
||||
self.action = action
|
||||
self.clearHighlightAutomatically = clearHighlightAutomatically
|
||||
}
|
||||
|
||||
public static func ==(lhs: ContactListAdditionalOption, rhs: ContactListAdditionalOption) -> Bool {
|
||||
return lhs.title == rhs.title && lhs.icon == rhs.icon
|
||||
}
|
||||
}
|
||||
|
||||
public enum ContactListPeerId: Hashable {
|
||||
case peer(PeerId)
|
||||
case deviceContact(DeviceContactStableId)
|
||||
}
|
||||
|
||||
public enum ContactListAction: Equatable {
|
||||
case generic
|
||||
case voiceCall
|
||||
case videoCall
|
||||
case more
|
||||
}
|
||||
|
||||
public enum ContactListPeer: Equatable {
|
||||
case peer(peer: Peer, isGlobal: Bool, participantCount: Int32?)
|
||||
case deviceContact(DeviceContactStableId, DeviceContactBasicData)
|
||||
|
||||
public var id: ContactListPeerId {
|
||||
switch self {
|
||||
case let .peer(peer, _, _):
|
||||
return .peer(peer.id)
|
||||
case let .deviceContact(id, _):
|
||||
return .deviceContact(id)
|
||||
}
|
||||
}
|
||||
|
||||
public var indexName: PeerIndexNameRepresentation {
|
||||
switch self {
|
||||
case let .peer(peer, _, _):
|
||||
return peer.indexName
|
||||
case let .deviceContact(_, contact):
|
||||
return .personName(first: contact.firstName, last: contact.lastName, addressNames: [], phoneNumber: "")
|
||||
}
|
||||
}
|
||||
|
||||
public static func ==(lhs: ContactListPeer, rhs: ContactListPeer) -> Bool {
|
||||
switch lhs {
|
||||
case let .peer(lhsPeer, lhsIsGlobal, lhsParticipantCount):
|
||||
if case let .peer(rhsPeer, rhsIsGlobal, rhsParticipantCount) = rhs, lhsPeer.isEqual(rhsPeer), lhsIsGlobal == rhsIsGlobal, lhsParticipantCount == rhsParticipantCount {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .deviceContact(id, contact):
|
||||
if case .deviceContact(id, contact) = rhs {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public final class ContactSelectionControllerParams {
|
||||
public let context: AccountContext
|
||||
public let updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)?
|
||||
public let autoDismiss: Bool
|
||||
public let title: (PresentationStrings) -> String
|
||||
public let options: [ContactListAdditionalOption]
|
||||
public let displayDeviceContacts: Bool
|
||||
public let displayCallIcons: Bool
|
||||
public let multipleSelection: Bool
|
||||
public let requirePhoneNumbers: Bool
|
||||
public let confirmation: (ContactListPeer) -> Signal<Bool, NoError>
|
||||
|
||||
public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil, autoDismiss: Bool = true, title: @escaping (PresentationStrings) -> String, options: [ContactListAdditionalOption] = [], displayDeviceContacts: Bool = false, displayCallIcons: Bool = false, multipleSelection: Bool = false, requirePhoneNumbers: Bool = false, confirmation: @escaping (ContactListPeer) -> Signal<Bool, NoError> = { _ in .single(true) }) {
|
||||
self.context = context
|
||||
self.updatedPresentationData = updatedPresentationData
|
||||
self.autoDismiss = autoDismiss
|
||||
self.title = title
|
||||
self.options = options
|
||||
self.displayDeviceContacts = displayDeviceContacts
|
||||
self.displayCallIcons = displayCallIcons
|
||||
self.multipleSelection = multipleSelection
|
||||
self.requirePhoneNumbers = requirePhoneNumbers
|
||||
self.confirmation = confirmation
|
||||
}
|
||||
}
|
||||
|
||||
public enum ChatListSearchFilter: Equatable {
|
||||
case chats
|
||||
case topics
|
||||
|
@ -1,6 +1,9 @@
|
||||
import Foundation
|
||||
import Display
|
||||
import SwiftSignalKit
|
||||
import Postbox
|
||||
import TelegramCore
|
||||
import TelegramPresentationData
|
||||
|
||||
public protocol ContactSelectionController: ViewController {
|
||||
var result: Signal<([ContactListPeer], ContactListAction, Bool, Int32?, NSAttributedString?, ChatSendMessageActionSheetController.SendParameters?)?, NoError> { get }
|
||||
@ -10,3 +13,106 @@ public protocol ContactSelectionController: ViewController {
|
||||
|
||||
func dismissSearch()
|
||||
}
|
||||
|
||||
public enum ContactSelectionControllerMode {
|
||||
case generic
|
||||
case starsGifting(birthdays: [EnginePeer.Id: TelegramBirthday]?, hasActions: Bool)
|
||||
}
|
||||
|
||||
public struct ContactListAdditionalOption: Equatable {
|
||||
public let title: String
|
||||
public let icon: ContactListActionItemIcon
|
||||
public let action: () -> Void
|
||||
public let clearHighlightAutomatically: Bool
|
||||
|
||||
public init(title: String, icon: ContactListActionItemIcon, action: @escaping () -> Void, clearHighlightAutomatically: Bool = false) {
|
||||
self.title = title
|
||||
self.icon = icon
|
||||
self.action = action
|
||||
self.clearHighlightAutomatically = clearHighlightAutomatically
|
||||
}
|
||||
|
||||
public static func ==(lhs: ContactListAdditionalOption, rhs: ContactListAdditionalOption) -> Bool {
|
||||
return lhs.title == rhs.title && lhs.icon == rhs.icon
|
||||
}
|
||||
}
|
||||
|
||||
public enum ContactListPeerId: Hashable {
|
||||
case peer(PeerId)
|
||||
case deviceContact(DeviceContactStableId)
|
||||
}
|
||||
|
||||
public enum ContactListAction: Equatable {
|
||||
case generic
|
||||
case voiceCall
|
||||
case videoCall
|
||||
case more
|
||||
}
|
||||
|
||||
public enum ContactListPeer: Equatable {
|
||||
case peer(peer: Peer, isGlobal: Bool, participantCount: Int32?)
|
||||
case deviceContact(DeviceContactStableId, DeviceContactBasicData)
|
||||
|
||||
public var id: ContactListPeerId {
|
||||
switch self {
|
||||
case let .peer(peer, _, _):
|
||||
return .peer(peer.id)
|
||||
case let .deviceContact(id, _):
|
||||
return .deviceContact(id)
|
||||
}
|
||||
}
|
||||
|
||||
public var indexName: PeerIndexNameRepresentation {
|
||||
switch self {
|
||||
case let .peer(peer, _, _):
|
||||
return peer.indexName
|
||||
case let .deviceContact(_, contact):
|
||||
return .personName(first: contact.firstName, last: contact.lastName, addressNames: [], phoneNumber: "")
|
||||
}
|
||||
}
|
||||
|
||||
public static func ==(lhs: ContactListPeer, rhs: ContactListPeer) -> Bool {
|
||||
switch lhs {
|
||||
case let .peer(lhsPeer, lhsIsGlobal, lhsParticipantCount):
|
||||
if case let .peer(rhsPeer, rhsIsGlobal, rhsParticipantCount) = rhs, lhsPeer.isEqual(rhsPeer), lhsIsGlobal == rhsIsGlobal, lhsParticipantCount == rhsParticipantCount {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .deviceContact(id, contact):
|
||||
if case .deviceContact(id, contact) = rhs {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public final class ContactSelectionControllerParams {
|
||||
public let context: AccountContext
|
||||
public let updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)?
|
||||
public let mode: ContactSelectionControllerMode
|
||||
public let autoDismiss: Bool
|
||||
public let title: (PresentationStrings) -> String
|
||||
public let options: Signal<[ContactListAdditionalOption], NoError>
|
||||
public let displayDeviceContacts: Bool
|
||||
public let displayCallIcons: Bool
|
||||
public let multipleSelection: Bool
|
||||
public let requirePhoneNumbers: Bool
|
||||
public let confirmation: (ContactListPeer) -> Signal<Bool, NoError>
|
||||
|
||||
public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil, mode: ContactSelectionControllerMode = .generic, autoDismiss: Bool = true, title: @escaping (PresentationStrings) -> String, options: Signal<[ContactListAdditionalOption], NoError> = .single([]), displayDeviceContacts: Bool = false, displayCallIcons: Bool = false, multipleSelection: Bool = false, requirePhoneNumbers: Bool = false, confirmation: @escaping (ContactListPeer) -> Signal<Bool, NoError> = { _ in .single(true) }) {
|
||||
self.context = context
|
||||
self.updatedPresentationData = updatedPresentationData
|
||||
self.mode = mode
|
||||
self.autoDismiss = autoDismiss
|
||||
self.title = title
|
||||
self.options = options
|
||||
self.displayDeviceContacts = displayDeviceContacts
|
||||
self.displayCallIcons = displayCallIcons
|
||||
self.multipleSelection = multipleSelection
|
||||
self.requirePhoneNumbers = requirePhoneNumbers
|
||||
self.confirmation = confirmation
|
||||
}
|
||||
}
|
||||
|
@ -857,8 +857,13 @@ public final class StarsTransactionsScreen: ViewControllerComponentContainer {
|
||||
return
|
||||
}
|
||||
|
||||
if let navigationController = self.navigationController as? NavigationController {
|
||||
var controllers = navigationController.viewControllers
|
||||
controllers = controllers.filter { !($0 is ContactSelectionController) }
|
||||
navigationController.setViewControllers(controllers, animated: true)
|
||||
}
|
||||
|
||||
Queue.mainQueue().after(2.0) {
|
||||
//TODO:localize
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
let resultController = UndoOverlayController(
|
||||
presentationData: presentationData,
|
||||
@ -867,8 +872,8 @@ public final class StarsTransactionsScreen: ViewControllerComponentContainer {
|
||||
scale: 0.066,
|
||||
colors: [:],
|
||||
title: nil,
|
||||
text: "\(stars) Stars sent.",
|
||||
customUndoText: "View Chat",
|
||||
text: presentationData.strings.Stars_Intro_StarsSent(Int32(stars)),
|
||||
customUndoText: presentationData.strings.Stars_Intro_StarsSent_ViewChat,
|
||||
timeout: nil
|
||||
),
|
||||
elevatedLayout: false,
|
||||
|
@ -17,6 +17,7 @@ import ChatSendMessageActionUI
|
||||
|
||||
class ContactSelectionControllerImpl: ViewController, ContactSelectionController, PresentableController, AttachmentContainable {
|
||||
private let context: AccountContext
|
||||
private let mode: ContactSelectionControllerMode
|
||||
private let autoDismiss: Bool
|
||||
|
||||
fileprivate var contactsNode: ContactSelectionControllerNode {
|
||||
@ -35,7 +36,7 @@ class ContactSelectionControllerImpl: ViewController, ContactSelectionController
|
||||
|
||||
private let index: PeerNameIndex = .lastNameFirst
|
||||
private let titleProducer: (PresentationStrings) -> String
|
||||
private let options: [ContactListAdditionalOption]
|
||||
private let options: Signal<[ContactListAdditionalOption], NoError>
|
||||
private let displayDeviceContacts: Bool
|
||||
private let displayCallIcons: Bool
|
||||
private let multipleSelection: Bool
|
||||
@ -94,6 +95,7 @@ class ContactSelectionControllerImpl: ViewController, ContactSelectionController
|
||||
|
||||
init(_ params: ContactSelectionControllerParams) {
|
||||
self.context = params.context
|
||||
self.mode = params.mode
|
||||
self.autoDismiss = params.autoDismiss
|
||||
self.titleProducer = params.title
|
||||
self.options = params.options
|
||||
@ -207,7 +209,7 @@ class ContactSelectionControllerImpl: ViewController, ContactSelectionController
|
||||
}
|
||||
|
||||
override func loadDisplayNode() {
|
||||
self.displayNode = ContactSelectionControllerNode(context: self.context, presentationData: self.presentationData, options: self.options, displayDeviceContacts: self.displayDeviceContacts, displayCallIcons: self.displayCallIcons, multipleSelection: self.multipleSelection, requirePhoneNumbers: self.requirePhoneNumbers)
|
||||
self.displayNode = ContactSelectionControllerNode(context: self.context, mode: self.mode, presentationData: self.presentationData, options: self.options, displayDeviceContacts: self.displayDeviceContacts, displayCallIcons: self.displayCallIcons, multipleSelection: self.multipleSelection, requirePhoneNumbers: self.requirePhoneNumbers)
|
||||
self._ready.set(self.contactsNode.contactListNode.ready)
|
||||
|
||||
self.contactsNode.navigationBar = self.navigationBar
|
||||
|
@ -55,7 +55,7 @@ final class ContactSelectionControllerNode: ASDisplayNode {
|
||||
|
||||
var searchContainerNode: ContactsSearchContainerNode?
|
||||
|
||||
init(context: AccountContext, presentationData: PresentationData, options: [ContactListAdditionalOption], displayDeviceContacts: Bool, displayCallIcons: Bool, multipleSelection: Bool, requirePhoneNumbers: Bool) {
|
||||
init(context: AccountContext, mode: ContactSelectionControllerMode, presentationData: PresentationData, options: Signal<[ContactListAdditionalOption], NoError>, displayDeviceContacts: Bool, displayCallIcons: Bool, multipleSelection: Bool, requirePhoneNumbers: Bool) {
|
||||
self.context = context
|
||||
self.presentationData = presentationData
|
||||
self.displayDeviceContacts = displayDeviceContacts
|
||||
@ -67,8 +67,50 @@ final class ContactSelectionControllerNode: ASDisplayNode {
|
||||
}
|
||||
self.filters = filters
|
||||
|
||||
let displayTopPeers: ContactListPresentation.TopPeers
|
||||
if case let .starsGifting(birthdays, hasActions) = mode {
|
||||
if let birthdays {
|
||||
let today = Calendar(identifier: .gregorian).component(.day, from: Date())
|
||||
var sections: [(String, [EnginePeer.Id], Bool)] = []
|
||||
var todayPeers: [EnginePeer.Id] = []
|
||||
var yesterdayPeers: [EnginePeer.Id] = []
|
||||
var tomorrowPeers: [EnginePeer.Id] = []
|
||||
|
||||
for (peerId, birthday) in birthdays {
|
||||
if birthday.day == today {
|
||||
todayPeers.append(peerId)
|
||||
} else if birthday.day == today - 1 || birthday.day > today + 5 {
|
||||
yesterdayPeers.append(peerId)
|
||||
} else if birthday.day == today + 1 || birthday.day < today + 5 {
|
||||
tomorrowPeers.append(peerId)
|
||||
}
|
||||
}
|
||||
|
||||
if !todayPeers.isEmpty {
|
||||
sections.append((presentationData.strings.Premium_Gift_ContactSelection_BirthdayToday, todayPeers, hasActions))
|
||||
}
|
||||
if !yesterdayPeers.isEmpty {
|
||||
sections.append((presentationData.strings.Premium_Gift_ContactSelection_BirthdayYesterday, yesterdayPeers, hasActions))
|
||||
}
|
||||
if !tomorrowPeers.isEmpty {
|
||||
sections.append((presentationData.strings.Premium_Gift_ContactSelection_BirthdayTomorrow, tomorrowPeers, hasActions))
|
||||
}
|
||||
|
||||
displayTopPeers = .custom(sections)
|
||||
} else {
|
||||
displayTopPeers = .recent
|
||||
}
|
||||
} else {
|
||||
displayTopPeers = .none
|
||||
}
|
||||
|
||||
let presentation: Signal<ContactListPresentation, NoError> = options
|
||||
|> map { options in
|
||||
return .natural(options: options, includeChatList: false, topPeers: displayTopPeers)
|
||||
}
|
||||
|
||||
var contextActionImpl: ((EnginePeer, ASDisplayNode, ContextGesture?, CGPoint?) -> Void)?
|
||||
self.contactListNode = ContactListNode(context: context, updatedPresentationData: (presentationData, self.presentationDataPromise.get()), presentation: .single(.natural(options: options, includeChatList: false, topPeers: .none)), filters: filters, onlyWriteable: false, isGroupInvitation: false, displayCallIcons: displayCallIcons, contextAction: multipleSelection ? { peer, node, gesture, _, _ in
|
||||
self.contactListNode = ContactListNode(context: context, updatedPresentationData: (presentationData, self.presentationDataPromise.get()), presentation: presentation, filters: filters, onlyWriteable: false, isGroupInvitation: false, displayCallIcons: displayCallIcons, contextAction: multipleSelection ? { peer, node, gesture, _, _ in
|
||||
contextActionImpl?(peer, node, gesture, nil)
|
||||
} : nil, multipleSelection: multipleSelection)
|
||||
|
||||
|
@ -2192,6 +2192,7 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
||||
var reachedLimitImpl: ((Int32) -> Void)?
|
||||
var presentBirthdayPickerImpl: (() -> Void)?
|
||||
let mode: ContactMultiselectionControllerMode
|
||||
var starsMode: ContactSelectionControllerMode = .generic
|
||||
var currentBirthdays: [EnginePeer.Id: TelegramBirthday]?
|
||||
if case let .chatList(birthdays) = source, let birthdays, !birthdays.isEmpty {
|
||||
mode = .premiumGifting(birthdays: birthdays, selectToday: true, hasActions: true)
|
||||
@ -2201,6 +2202,7 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
||||
currentBirthdays = birthdays
|
||||
} else if case let .stars(birthdays) = source {
|
||||
mode = .premiumGifting(birthdays: birthdays, selectToday: false, hasActions: false)
|
||||
starsMode = .starsGifting(birthdays: birthdays, hasActions: false)
|
||||
currentBirthdays = birthdays
|
||||
} else {
|
||||
mode = .premiumGifting(birthdays: nil, selectToday: false, hasActions: true)
|
||||
@ -2237,7 +2239,10 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
||||
options.set(context.engine.payments.starsGiftOptions(peerId: nil))
|
||||
let contactsController = context.sharedContext.makeContactSelectionController(ContactSelectionControllerParams(
|
||||
context: context,
|
||||
title: { strings in return strings.Stars_Purchase_GiftStars }
|
||||
mode: starsMode,
|
||||
autoDismiss: false,
|
||||
title: { strings in return strings.Stars_Purchase_GiftStars },
|
||||
options: contactOptions
|
||||
))
|
||||
let _ = (contactsController.result
|
||||
|> deliverOnMainQueue).start(next: { result in
|
||||
|
Loading…
x
Reference in New Issue
Block a user