Various fixes

This commit is contained in:
Ilya Laktyushin
2023-07-25 22:37:45 +02:00
parent f4fc72b762
commit ab6b0140cd
17 changed files with 379 additions and 77 deletions

View File

@@ -307,6 +307,10 @@ final class ShareWithPeersScreenComponent: Component {
private var savedSelectedPeers: [EnginePeer.Id] = []
private var selectedPeers: [EnginePeer.Id] = []
private var selectedGroups: [EnginePeer.Id] = []
private var peersMap: [EnginePeer.Id: EnginePeer] = [:]
private var selectedCategories = Set<CategoryId>()
private var selectedOptions = Set<OptionId>()
@@ -557,6 +561,119 @@ final class ShareWithPeersScreenComponent: Component {
controller.present(tooltipScreen, in: .window(.root))
}
private func toggleGroupPeer(_ peer: EnginePeer) {
guard let component = self.component, let environment = self.environment, let controller = self.environment?.controller() else {
return
}
var groupTooLarge = false
if case let .legacyGroup(group) = peer, group.participantCount > 200 {
groupTooLarge = true
} else if let stateValue = self.effectiveStateValue, let count = stateValue.participants[peer.id], count > 200 {
groupTooLarge = true
}
if groupTooLarge {
let alertController = textAlertController(
context: component.context,
forceTheme: defaultDarkColorPresentationTheme,
title: environment.strings.Story_Privacy_GroupTooLarge,
text: environment.strings.Story_Privacy_GroupParticipantsLimit,
actions: [
TextAlertAction(type: .defaultAction, title: "OK", action: {})
],
actionLayout: .vertical
)
controller.present(alertController, in: .window(.root))
return
}
var append = false
if let index = self.selectedGroups.firstIndex(of: peer.id) {
self.selectedGroups.remove(at: index)
} else {
self.selectedGroups.append(peer.id)
append = true
}
let context = component.context
if peer.id.namespace == Namespaces.Peer.CloudGroup {
let _ = (context.engine.data.subscribe(
TelegramEngine.EngineData.Item.Peer.LegacyGroupParticipants(id: peer.id)
)
|> mapToSignal { participants -> Signal<[EnginePeer], NoError> in
if case let .known(participants) = participants {
return context.engine.data.get(
EngineDataMap(participants.map { TelegramEngine.EngineData.Item.Peer.Peer(id: $0.peerId) })
)
|> map { peers in
var result: [EnginePeer] = []
for participant in participants {
if let peer = peers[participant.peerId], let peer, peer.id != context.account.peerId {
result.append(peer)
}
}
return result
}
} else {
let _ = context.engine.peers.fetchAndUpdateCachedPeerData(peerId: peer.id).start()
return .complete()
}
}
|> take(1)
|> deliverOnMainQueue).start(next: { [weak self] peers in
guard let self else {
return
}
var peerIds = Set<EnginePeer.Id>()
for peer in peers {
self.peersMap[peer.id] = peer
peerIds.insert(peer.id)
}
if append {
self.selectedPeers.append(contentsOf: peers.map { $0.id })
} else {
self.selectedPeers = self.selectedPeers.filter { !peerIds.contains($0) }
}
let transition = Transition(animation: .curve(duration: 0.35, curve: .spring))
self.state?.updated(transition: transition)
})
} else if peer.id.namespace == Namespaces.Peer.CloudChannel {
let participants: Signal<[EnginePeer], NoError> = Signal { subscriber in
let (disposable, _) = context.peerChannelMemberCategoriesContextsManager.recent(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peer.id, requestUpdate: true, updated: { list in
var peers: [EnginePeer] = []
for item in list.list {
peers.append(EnginePeer(item.peer))
}
if !peers.isEmpty {
subscriber.putNext(peers)
subscriber.putCompletion()
}
})
return disposable
}
|> take(1)
let _ = (participants
|> deliverOnMainQueue).start(next: { [weak self] peers in
guard let self else {
return
}
var peerIds = Set<EnginePeer.Id>()
for peer in peers {
self.peersMap[peer.id] = peer
peerIds.insert(peer.id)
}
if append {
self.selectedPeers.append(contentsOf: peers.map { $0.id })
} else {
self.selectedPeers = self.selectedPeers.filter { !peerIds.contains($0) }
}
let transition = Transition(animation: .curve(duration: 0.35, curve: .spring))
self.state?.updated(transition: transition)
})
}
}
private func updateScrolling(transition: Transition) {
guard let component = self.component, let environment = self.environment, let itemLayout = self.itemLayout else {
return
@@ -665,14 +782,22 @@ final class ShareWithPeersScreenComponent: Component {
component: AnyComponent(SectionHeaderComponent(
theme: environment.theme,
style: itemLayout.style,
title: sectionTitle
title: sectionTitle,
actionTitle: (section.id == 1 && !self.selectedPeers.isEmpty) ? environment.strings.Contacts_DeselectAll : nil,
action: { [weak self] in
if let self {
self.selectedPeers = []
self.selectedGroups = []
let transition = Transition(animation: .curve(duration: 0.35, curve: .spring))
self.state?.updated(transition: transition)
}
}
)),
environment: {},
containerSize: sectionHeaderFrame.size
)
if let sectionHeaderView = sectionHeader.view {
if sectionHeaderView.superview == nil {
sectionHeaderView.isUserInteractionEnabled = false
self.scrollContentClippingView.addSubview(sectionHeaderView)
}
if minSectionHeader == nil {
@@ -736,7 +861,8 @@ final class ShareWithPeersScreenComponent: Component {
self.selectedCategories.removeAll()
self.selectedCategories.insert(categoryId)
if self.selectedPeers.isEmpty && categoryId == .selectedContacts {
let closeFriends = self.component?.stateContext.stateValue?.closeFriendsPeers ?? []
if categoryId == .selectedContacts && self.selectedPeers.isEmpty {
component.editCategory(
EngineStoryPrivacy(base: .nobody, additionallyIncludePeers: []),
self.selectedOptions.contains(.screenshot),
@@ -744,6 +870,14 @@ final class ShareWithPeersScreenComponent: Component {
)
controller.dismissAllTooltips()
controller.dismiss()
} else if categoryId == .closeFriends && closeFriends.isEmpty {
component.editCategory(
EngineStoryPrivacy(base: .closeFriends, additionallyIncludePeers: []),
self.selectedOptions.contains(.screenshot),
self.selectedOptions.contains(.pin)
)
controller.dismissAllTooltips()
controller.dismiss()
}
}
self.state?.updated(transition: Transition(animation: .curve(duration: 0.35, curve: .spring)))
@@ -811,6 +945,20 @@ final class ShareWithPeersScreenComponent: Component {
self.visibleItems[itemId] = visibleItem
}
let subtitle: String?
if case let .legacyGroup(group) = peer {
subtitle = environment.strings.Conversation_StatusMembers(Int32(group.participantCount))
} else if case .channel = peer {
if let count = stateValue.participants[peer.id] {
subtitle = environment.strings.Conversation_StatusMembers(Int32(count))
} else {
subtitle = nil
}
} else {
subtitle = nil
}
let isSelected = self.selectedPeers.contains(peer.id) || self.selectedGroups.contains(peer.id)
let _ = visibleItem.update(
transition: itemTransition,
component: AnyComponent(PeerListItemComponent(
@@ -821,19 +969,23 @@ final class ShareWithPeersScreenComponent: Component {
sideInset: itemLayout.sideInset,
title: peer.displayTitle(strings: environment.strings, displayOrder: .firstLast),
peer: peer,
subtitle: nil,
subtitle: subtitle,
subtitleAccessory: .none,
presence: stateValue.presences[peer.id],
selectionState: .editing(isSelected: self.selectedPeers.contains(peer.id), isTinted: false),
selectionState: .editing(isSelected: isSelected, isTinted: false),
hasNext: true,
action: { [weak self] peer in
guard let self else {
return
}
if let index = self.selectedPeers.firstIndex(of: peer.id) {
self.selectedPeers.remove(at: index)
if peer.id.isGroupOrChannel {
self.toggleGroupPeer(peer)
} else {
self.selectedPeers.append(peer.id)
if let index = self.selectedPeers.firstIndex(of: peer.id) {
self.selectedPeers.remove(at: index)
} else {
self.selectedPeers.append(peer.id)
}
}
let transition = Transition(animation: .curve(duration: 0.35, curve: .spring))
@@ -1244,9 +1396,20 @@ final class ShareWithPeersScreenComponent: Component {
var tokens: [TokenListTextField.Token] = []
for peerId in self.selectedPeers {
guard let stateValue = self.defaultStateValue, let peer = stateValue.peers.first(where: { $0.id == peerId }) else {
guard let stateValue = self.defaultStateValue else {
continue
}
var peer: EnginePeer?
if let peerValue = self.peersMap[peerId] {
peer = peerValue
} else if let peerValue = stateValue.peers.first(where: { $0.id == peerId }) {
peer = peerValue
}
guard let peer else {
continue
}
tokens.append(TokenListTextField.Token(
id: AnyHashable(peerId),
title: peer.compactDisplayTitle,
@@ -1440,7 +1603,7 @@ final class ShareWithPeersScreenComponent: Component {
actionButtonTitle = environment.strings.Story_Privacy_PostStory
}
case .chats:
title = ""
title = environment.strings.Story_Privacy_CategorySelectedContacts
case let .contacts(category):
switch category {
case .closeFriends:
@@ -1507,6 +1670,13 @@ final class ShareWithPeersScreenComponent: Component {
transition.setFrame(layer: self.navigationSeparatorLayer, frame: CGRect(origin: CGPoint(x: containerSideInset, y: navigationHeight), size: CGSize(width: containerWidth, height: UIScreenPixel)))
let badge: Int
if case .stories = component.stateContext.subject {
badge = 0
} else {
badge = self.selectedPeers.count
}
let actionButtonSize = self.actionButton.update(
transition: transition,
component: AnyComponent(ButtonComponent(
@@ -1519,7 +1689,7 @@ final class ShareWithPeersScreenComponent: Component {
id: actionButtonTitle,
component: AnyComponent(ButtonTextContentComponent(
text: actionButtonTitle,
badge: 0,
badge: badge,
textColor: environment.theme.list.itemCheckColors.foregroundColor,
badgeBackground: environment.theme.list.itemCheckColors.foregroundColor,
badgeForeground: environment.theme.list.itemCheckColors.fillColor
@@ -1755,15 +1925,18 @@ public class ShareWithPeersScreen: ViewControllerComponentContainer {
public final class State {
let peers: [EnginePeer]
let presences: [EnginePeer.Id: EnginePeer.Presence]
let participants: [EnginePeer.Id: Int]
let closeFriendsPeers: [EnginePeer]
fileprivate init(
peers: [EnginePeer],
presences: [EnginePeer.Id: EnginePeer.Presence],
participants: [EnginePeer.Id: Int],
closeFriendsPeers: [EnginePeer]
) {
self.peers = peers
self.presences = presences
self.participants = participants
self.closeFriendsPeers = closeFriendsPeers
}
}
@@ -1820,6 +1993,7 @@ public class ShareWithPeersScreen: ViewControllerComponentContainer {
let state = State(
peers: peers.compactMap { $0 },
presences: [:],
participants: [:],
closeFriendsPeers: closeFriends
)
self.stateValue = state
@@ -1828,16 +2002,36 @@ public class ShareWithPeersScreen: ViewControllerComponentContainer {
self.readySubject.set(true)
})
case .chats:
self.stateDisposable = (context.engine.messages.chatList(group: .root, count: 200)
|> deliverOnMainQueue).start(next: { [weak self] chatList in
self.stateDisposable = (combineLatest(
context.engine.messages.chatList(group: .root, count: 200) |> take(1),
context.engine.data.get(TelegramEngine.EngineData.Item.Contacts.List(includePresences: true))
)
|> mapToSignal { chatList, contacts -> Signal<(EngineChatList, EngineContactList, [EnginePeer.Id: Optional<Int>]), NoError> in
return context.engine.data.get(
EngineDataMap(chatList.items.map(\.renderedPeer.peerId).map(TelegramEngine.EngineData.Item.Peer.ParticipantCount.init))
)
|> map { participantCountMap -> (EngineChatList, EngineContactList, [EnginePeer.Id: Optional<Int>]) in
return (chatList, contacts, participantCountMap)
}
}
|> deliverOnMainQueue).start(next: { [weak self] chatList, contacts, participantCounts in
guard let self else {
return
}
var participants: [EnginePeer.Id: Int] = [:]
for (key, value) in participantCounts {
if let value {
participants[key] = value
}
}
var existingIds = Set<EnginePeer.Id>()
var selectedPeers: [EnginePeer] = []
for item in chatList.items.reversed() {
if self.initialPeerIds.contains(item.renderedPeer.peerId), let peer = item.renderedPeer.peer {
selectedPeers.append(peer)
existingIds.insert(peer.id)
}
}
@@ -1847,12 +2041,39 @@ public class ShareWithPeersScreen: ViewControllerComponentContainer {
}
var peers: [EnginePeer] = []
peers = chatList.items.filter { !self.initialPeerIds.contains($0.renderedPeer.peerId) && $0.renderedPeer.peerId != context.account.peerId }.reversed().compactMap { $0.renderedPeer.peer }
peers = chatList.items.filter { peer in
if let peer = peer.renderedPeer.peer {
if self.initialPeerIds.contains(peer.id) {
return false
}
if peer.id == context.account.peerId {
return false
}
if peer.isService {
return false
}
if case let .channel(channel) = peer {
if channel.isForum {
return false
}
if case .broadcast = channel.info {
return false
}
}
return true
} else {
return false
}
}.reversed().compactMap { $0.renderedPeer.peer }
for peer in peers {
existingIds.insert(peer.id)
}
peers.insert(contentsOf: selectedPeers, at: 0)
let state = State(
peers: peers,
presences: presences,
participants: participants,
closeFriendsPeers: []
)
self.stateValue = state
@@ -1908,6 +2129,7 @@ public class ShareWithPeersScreen: ViewControllerComponentContainer {
let state = State(
peers: peers,
presences: contactList.presences,
participants: [:],
closeFriendsPeers: []
)
@@ -1946,11 +2168,20 @@ public class ShareWithPeersScreen: ViewControllerComponentContainer {
} else {
return true
}
} else if case let .channel(channel) = peer {
if channel.isForum {
return false
}
if case .broadcast = channel.info {
return false
}
return true
} else {
return false
return true
}
},
presences: [:],
participants: [:],
closeFriendsPeers: []
)
self.stateValue = state