mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Invite Links Fixes
This commit is contained in:
parent
a59f9e1969
commit
426e8724dc
@ -5892,3 +5892,5 @@ Sorry for the inconvenience.";
|
||||
"Conversation.ChecksTooltip.Read" = "Read";
|
||||
|
||||
"DialogList.MultipleTypingPair" = "%@ and %@ are typing";
|
||||
|
||||
"Common.Save" = "Save";
|
||||
|
@ -50,7 +50,7 @@ func isValidNumberOfUsers(_ number: String) -> Bool {
|
||||
private enum InviteLinksEditEntry: ItemListNodeEntry {
|
||||
case timeHeader(PresentationTheme, String)
|
||||
case timePicker(PresentationTheme, InviteLinkTimeLimit)
|
||||
case timeExpiryDate(PresentationTheme, Int32?)
|
||||
case timeExpiryDate(PresentationTheme, Int32?, Bool)
|
||||
case timeCustomPicker(PresentationTheme, Int32?)
|
||||
case timeInfo(PresentationTheme, String)
|
||||
|
||||
@ -111,8 +111,8 @@ private enum InviteLinksEditEntry: ItemListNodeEntry {
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .timeExpiryDate(lhsTheme, lhsDate):
|
||||
if case let .timeExpiryDate(rhsTheme, rhsDate) = rhs, lhsTheme === rhsTheme, lhsDate == rhsDate {
|
||||
case let .timeExpiryDate(lhsTheme, lhsDate, lhsActive):
|
||||
if case let .timeExpiryDate(rhsTheme, rhsDate, rhsActive) = rhs, lhsTheme === rhsTheme, lhsDate == rhsDate, lhsActive == rhsActive {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
@ -182,14 +182,14 @@ private enum InviteLinksEditEntry: ItemListNodeEntry {
|
||||
return updatedState
|
||||
})
|
||||
})
|
||||
case let .timeExpiryDate(_, value):
|
||||
case let .timeExpiryDate(theme, value, active):
|
||||
let text: String
|
||||
if let value = value {
|
||||
text = stringForFullDate(timestamp: value, strings: presentationData.strings, dateTimeFormat: PresentationDateTimeFormat(timeFormat: .regular, dateFormat: .monthFirst, dateSeparator: ".", decimalSeparator: ".", groupingSeparator: "."))
|
||||
} else {
|
||||
text = presentationData.strings.InviteLink_Create_TimeLimitExpiryDateNever
|
||||
}
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: presentationData.strings.InviteLink_Create_TimeLimitExpiryDate, label: text, sectionId: self.section, style: .blocks, disclosureStyle: .none, action: {
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: presentationData.strings.InviteLink_Create_TimeLimitExpiryDate, label: text, labelStyle: active ? .coloredText(theme.list.itemAccentColor) : .text, sectionId: self.section, style: .blocks, disclosureStyle: .none, action: {
|
||||
arguments.dismissInput()
|
||||
arguments.updateState { state in
|
||||
var updatedState = state
|
||||
@ -276,7 +276,7 @@ private func inviteLinkEditControllerEntries(invite: ExportedInvitation?, state:
|
||||
} else if let value = state.time.value {
|
||||
time = currentTime + value
|
||||
}
|
||||
entries.append(.timeExpiryDate(presentationData.theme, time))
|
||||
entries.append(.timeExpiryDate(presentationData.theme, time, state.pickingTimeLimit))
|
||||
if state.pickingTimeLimit {
|
||||
entries.append(.timeCustomPicker(presentationData.theme, time ?? currentTime))
|
||||
}
|
||||
@ -327,7 +327,7 @@ public func inviteLinkEditController(context: AccountContext, peerId: PeerId, in
|
||||
|
||||
initialState = InviteLinkEditControllerState(usage: InviteLinkUsageLimit(value: usageLimit), time: timeLimit, pickingTimeLimit: false, pickingUsageLimit: false)
|
||||
} else {
|
||||
initialState = InviteLinkEditControllerState(usage: .medium, time: .week, pickingTimeLimit: false, pickingUsageLimit: false)
|
||||
initialState = InviteLinkEditControllerState(usage: .unlimited, time: .unlimited, pickingTimeLimit: false, pickingUsageLimit: false)
|
||||
}
|
||||
|
||||
let statePromise = ValuePromise(initialState, ignoreRepeated: true)
|
||||
@ -376,7 +376,7 @@ public func inviteLinkEditController(context: AccountContext, peerId: PeerId, in
|
||||
dismissImpl?()
|
||||
})
|
||||
|
||||
let rightNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Done), style: .bold, enabled: true, action: {
|
||||
let rightNavigationButton = ItemListNavigationButton(content: .text(invite == nil ? presentationData.strings.Common_Create : presentationData.strings.Common_Save), style: .bold, enabled: true, action: {
|
||||
let expireDate: Int32?
|
||||
if case let .custom(value) = state.time {
|
||||
expireDate = value
|
||||
|
@ -139,7 +139,9 @@ private enum InviteLinkInviteEntry: Comparable, Identifiable {
|
||||
case let .header(theme, title, text):
|
||||
return InviteLinkInviteHeaderItem(theme: theme, title: title, text: text)
|
||||
case let .mainLink(_, invite):
|
||||
return ItemListPermanentInviteLinkItem(context: interaction.context, presentationData: ItemListPresentationData(presentationData), invite: invite, peers: [], displayButton: true, displayImporters: false, buttonColor: nil, sectionId: 0, style: .plain, shareAction: {
|
||||
return ItemListPermanentInviteLinkItem(context: interaction.context, presentationData: ItemListPresentationData(presentationData), invite: invite, peers: [], displayButton: true, displayImporters: false, buttonColor: nil, sectionId: 0, style: .plain, copyAction: {
|
||||
interaction.copyLink(invite)
|
||||
}, shareAction: {
|
||||
interaction.shareLink(invite)
|
||||
}, contextAction: { node in
|
||||
interaction.mainLinkContextAction(invite, node, nil)
|
||||
@ -371,7 +373,7 @@ public final class InviteLinkInviteController: ViewController {
|
||||
ActionSheetButtonItem(title: presentationData.strings.GroupInfo_InviteLink_RevokeLink, color: .destructive, action: {
|
||||
dismissAction()
|
||||
|
||||
self?.revokeDisposable.set((ensuredExistingPeerExportedInvitation(account: context.account, peerId: peerId, revokeExisted: true) |> deliverOnMainQueue).start(completed: {
|
||||
self?.revokeDisposable.set((revokePersistentPeerExportedInvitation(account: context.account, peerId: peerId) |> deliverOnMainQueue).start(completed: {
|
||||
|
||||
}))
|
||||
})
|
||||
@ -585,11 +587,6 @@ public final class InviteLinkInviteController: ViewController {
|
||||
if result === self.headerNode.view {
|
||||
return self.view
|
||||
}
|
||||
|
||||
if result === self.headerNode.view {
|
||||
return self.view
|
||||
}
|
||||
|
||||
if !self.bounds.contains(point) {
|
||||
return nil
|
||||
}
|
||||
@ -615,8 +612,6 @@ public final class InviteLinkInviteController: ViewController {
|
||||
case .changed:
|
||||
var translation = recognizer.translation(in: self.contentNode.view).y
|
||||
if let currentPanOffset = self.panGestureArguments {
|
||||
|
||||
|
||||
if case let .known(value) = contentOffset, value <= 0.5 {
|
||||
} else {
|
||||
translation = currentPanOffset
|
||||
|
@ -22,18 +22,20 @@ import ShareController
|
||||
|
||||
private final class InviteLinkListControllerArguments {
|
||||
let context: AccountContext
|
||||
let shareMainLink: (ExportedInvitation?) -> Void
|
||||
let openMainLink: (ExportedInvitation?) -> Void
|
||||
let shareMainLink: (ExportedInvitation) -> Void
|
||||
let openMainLink: (ExportedInvitation) -> Void
|
||||
let copyLink: (ExportedInvitation) -> Void
|
||||
let mainLinkContextAction: (ExportedInvitation?, ASDisplayNode, ContextGesture?) -> Void
|
||||
let createLink: () -> Void
|
||||
let openLink: (ExportedInvitation) -> Void
|
||||
let linkContextAction: (ExportedInvitation?, ASDisplayNode, ContextGesture?) -> Void
|
||||
let deleteAllRevokedLinks: () -> Void
|
||||
|
||||
init(context: AccountContext, shareMainLink: @escaping (ExportedInvitation?) -> Void, openMainLink: @escaping (ExportedInvitation?) -> Void, mainLinkContextAction: @escaping (ExportedInvitation?, ASDisplayNode, ContextGesture?) -> Void, createLink: @escaping () -> Void, openLink: @escaping (ExportedInvitation?) -> Void, linkContextAction: @escaping (ExportedInvitation?, ASDisplayNode, ContextGesture?) -> Void, deleteAllRevokedLinks: @escaping () -> Void) {
|
||||
init(context: AccountContext, shareMainLink: @escaping (ExportedInvitation) -> Void, openMainLink: @escaping (ExportedInvitation) -> Void, copyLink: @escaping (ExportedInvitation) -> Void, mainLinkContextAction: @escaping (ExportedInvitation?, ASDisplayNode, ContextGesture?) -> Void, createLink: @escaping () -> Void, openLink: @escaping (ExportedInvitation?) -> Void, linkContextAction: @escaping (ExportedInvitation?, ASDisplayNode, ContextGesture?) -> Void, deleteAllRevokedLinks: @escaping () -> Void) {
|
||||
self.context = context
|
||||
self.shareMainLink = shareMainLink
|
||||
self.openMainLink = openMainLink
|
||||
self.copyLink = copyLink
|
||||
self.mainLinkContextAction = mainLinkContextAction
|
||||
self.createLink = createLink
|
||||
self.openLink = openLink
|
||||
@ -178,8 +180,14 @@ private enum InviteLinksListEntry: ItemListNodeEntry {
|
||||
case let .mainLinkHeader(_, text):
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
||||
case let .mainLink(_, invite, peers):
|
||||
return ItemListPermanentInviteLinkItem(context: arguments.context, presentationData: presentationData, invite: invite, peers: peers, displayButton: true, displayImporters: true, buttonColor: nil, sectionId: self.section, style: .blocks, shareAction: {
|
||||
arguments.shareMainLink(invite)
|
||||
return ItemListPermanentInviteLinkItem(context: arguments.context, presentationData: presentationData, invite: invite, peers: peers, displayButton: true, displayImporters: true, buttonColor: nil, sectionId: self.section, style: .blocks, copyAction: {
|
||||
if let invite = invite {
|
||||
arguments.copyLink(invite)
|
||||
}
|
||||
}, shareAction: {
|
||||
if let invite = invite {
|
||||
arguments.shareMainLink(invite)
|
||||
}
|
||||
}, contextAction: { node in
|
||||
arguments.mainLinkContextAction(invite, node, nil)
|
||||
}, viewAction: {
|
||||
@ -298,14 +306,7 @@ public func inviteLinkListController(context: AccountContext, peerId: PeerId) ->
|
||||
|
||||
let deleteAllRevokedLinksDisposable = MetaDisposable()
|
||||
actionsDisposable.add(deleteAllRevokedLinksDisposable)
|
||||
|
||||
actionsDisposable.add((context.account.viewTracker.peerView(peerId) |> filter { $0.cachedData != nil } |> take(1) |> mapToSignal { view -> Signal<String?, NoError> in
|
||||
return ensuredExistingPeerExportedInvitation(account: context.account, peerId: peerId)
|
||||
|> mapToSignal { _ -> Signal<String?, NoError> in
|
||||
return .complete()
|
||||
}
|
||||
}).start())
|
||||
|
||||
|
||||
var getControllerImpl: (() -> ViewController?)?
|
||||
|
||||
let invitesPromise = Promise<ExportedInvitations?>()
|
||||
@ -317,15 +318,15 @@ public func inviteLinkListController(context: AccountContext, peerId: PeerId) ->
|
||||
|> then(peerExportedInvitations(account: context.account, peerId: peerId, revoked: true)))
|
||||
|
||||
let arguments = InviteLinkListControllerArguments(context: context, shareMainLink: { invite in
|
||||
if let invite = invite {
|
||||
let shareController = ShareController(context: context, subject: .url(invite.link))
|
||||
presentControllerImpl?(shareController, nil)
|
||||
}
|
||||
let shareController = ShareController(context: context, subject: .url(invite.link))
|
||||
presentControllerImpl?(shareController, nil)
|
||||
}, openMainLink: { invite in
|
||||
if let invite = invite {
|
||||
let controller = InviteLinkViewController(context: context, peerId: peerId, invite: invite, importersContext: nil)
|
||||
pushControllerImpl?(controller)
|
||||
}
|
||||
let controller = InviteLinkViewController(context: context, peerId: peerId, invite: invite, importersContext: nil)
|
||||
pushControllerImpl?(controller)
|
||||
}, copyLink: { invite in
|
||||
UIPasteboard.general.string = invite.link
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
presentControllerImpl?(OverlayStatusController(theme: presentationData.theme, type: .genericSuccess(presentationData.strings.Username_LinkCopied, false)), nil)
|
||||
}, mainLinkContextAction: { invite, node, gesture in
|
||||
guard let node = node as? ContextExtractedContentContainingNode, let controller = getControllerImpl?() else {
|
||||
return
|
||||
@ -383,7 +384,7 @@ public func inviteLinkListController(context: AccountContext, peerId: PeerId) ->
|
||||
}
|
||||
}
|
||||
if revoke {
|
||||
revokeLinkDisposable.set((ensuredExistingPeerExportedInvitation(account: context.account, peerId: peerId, revokeExisted: true) |> deliverOnMainQueue).start(completed: {
|
||||
revokeLinkDisposable.set((revokePersistentPeerExportedInvitation(account: context.account, peerId: peerId) |> deliverOnMainQueue).start(completed: {
|
||||
updateState { state in
|
||||
var updatedState = state
|
||||
updatedState.revokingPrivateLink = false
|
||||
|
@ -24,12 +24,14 @@ import DirectionalPanGesture
|
||||
class InviteLinkViewInteraction {
|
||||
let context: AccountContext
|
||||
let openPeer: (PeerId) -> Void
|
||||
let copyLink: (ExportedInvitation) -> Void
|
||||
let shareLink: (ExportedInvitation) -> Void
|
||||
let contextAction: (ExportedInvitation, ASDisplayNode, ContextGesture?) -> Void
|
||||
|
||||
init(context: AccountContext, openPeer: @escaping (PeerId) -> Void, shareLink: @escaping (ExportedInvitation) -> Void, contextAction: @escaping (ExportedInvitation, ASDisplayNode, ContextGesture?) -> Void) {
|
||||
init(context: AccountContext, openPeer: @escaping (PeerId) -> Void, copyLink: @escaping (ExportedInvitation) -> Void, shareLink: @escaping (ExportedInvitation) -> Void, contextAction: @escaping (ExportedInvitation, ASDisplayNode, ContextGesture?) -> Void) {
|
||||
self.context = context
|
||||
self.openPeer = openPeer
|
||||
self.copyLink = copyLink
|
||||
self.shareLink = shareLink
|
||||
self.contextAction = contextAction
|
||||
}
|
||||
@ -169,7 +171,9 @@ private enum InviteLinkViewEntry: Comparable, Identifiable {
|
||||
case let .link(_, invite):
|
||||
let buttonColor = color(for: invite)
|
||||
let availability = invitationAvailability(invite)
|
||||
return ItemListPermanentInviteLinkItem(context: interaction.context, presentationData: ItemListPresentationData(presentationData), invite: invite, peers: [], displayButton: !invite.isRevoked && !availability.isZero, displayImporters: false, buttonColor: buttonColor, sectionId: 0, style: .plain, shareAction: {
|
||||
return ItemListPermanentInviteLinkItem(context: interaction.context, presentationData: ItemListPresentationData(presentationData), invite: invite, peers: [], displayButton: !invite.isRevoked && !availability.isZero, displayImporters: false, buttonColor: buttonColor, sectionId: 0, style: .plain, copyAction: {
|
||||
interaction.copyLink(invite)
|
||||
}, shareAction: {
|
||||
interaction.shareLink(invite)
|
||||
}, contextAction: { node in
|
||||
interaction.contextAction(invite, node, nil)
|
||||
@ -383,6 +387,10 @@ public final class InviteLinkViewController: ViewController {
|
||||
if let strongSelf = self, let navigationController = strongSelf.controller?.navigationController as? NavigationController {
|
||||
context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peerId), keepStack: .always))
|
||||
}
|
||||
}, copyLink: { [weak self] invite in
|
||||
UIPasteboard.general.string = invite.link
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
self?.controller?.present(OverlayStatusController(theme: presentationData.theme, type: .genericSuccess(presentationData.strings.Username_LinkCopied, false)), in: .window(.root))
|
||||
}, shareLink: { [weak self] invite in
|
||||
let shareController = ShareController(context: context, subject: .url(invite.link))
|
||||
self?.controller?.present(shareController, in: .window(.root))
|
||||
@ -655,11 +663,6 @@ public final class InviteLinkViewController: ViewController {
|
||||
if result === self.headerNode.view {
|
||||
return self.view
|
||||
}
|
||||
|
||||
if result === self.headerNode.view {
|
||||
return self.view
|
||||
}
|
||||
|
||||
if !self.bounds.contains(point) {
|
||||
return nil
|
||||
}
|
||||
|
@ -35,6 +35,7 @@ public class ItemListPermanentInviteLinkItem: ListViewItem, ItemListItem {
|
||||
let buttonColor: UIColor?
|
||||
public let sectionId: ItemListSectionId
|
||||
let style: ItemListStyle
|
||||
let copyAction: (() -> Void)?
|
||||
let shareAction: (() -> Void)?
|
||||
let contextAction: ((ASDisplayNode) -> Void)?
|
||||
let viewAction: (() -> Void)?
|
||||
@ -50,6 +51,7 @@ public class ItemListPermanentInviteLinkItem: ListViewItem, ItemListItem {
|
||||
buttonColor: UIColor?,
|
||||
sectionId: ItemListSectionId,
|
||||
style: ItemListStyle,
|
||||
copyAction: (() -> Void)?,
|
||||
shareAction: (() -> Void)?,
|
||||
contextAction: ((ASDisplayNode) -> Void)?,
|
||||
viewAction: (() -> Void)?,
|
||||
@ -64,6 +66,7 @@ public class ItemListPermanentInviteLinkItem: ListViewItem, ItemListItem {
|
||||
self.buttonColor = buttonColor
|
||||
self.sectionId = sectionId
|
||||
self.style = style
|
||||
self.copyAction = copyAction
|
||||
self.shareAction = shareAction
|
||||
self.contextAction = contextAction
|
||||
self.viewAction = viewAction
|
||||
@ -114,6 +117,7 @@ public class ItemListPermanentInviteLinkItemNode: ListViewItemNode, ItemListItem
|
||||
|
||||
private let fieldNode: ASImageNode
|
||||
private let addressNode: TextNode
|
||||
private let fieldButtonNode: HighlightTrackingButtonNode
|
||||
private let extractedContainerNode: ContextExtractedContentContainingNode
|
||||
private let containerNode: ContextControllerSourceNode
|
||||
private let addressButtonNode: HighlightTrackingButtonNode
|
||||
@ -157,6 +161,8 @@ public class ItemListPermanentInviteLinkItemNode: ListViewItemNode, ItemListItem
|
||||
|
||||
self.addressNode = TextNode()
|
||||
self.addressNode.isUserInteractionEnabled = false
|
||||
|
||||
self.fieldButtonNode = HighlightTrackingButtonNode()
|
||||
|
||||
self.addressButtonNode = HighlightTrackingButtonNode()
|
||||
self.extractedContainerNode = ContextExtractedContentContainingNode()
|
||||
@ -177,6 +183,7 @@ public class ItemListPermanentInviteLinkItemNode: ListViewItemNode, ItemListItem
|
||||
|
||||
self.addSubnode(self.fieldNode)
|
||||
self.addSubnode(self.addressNode)
|
||||
self.addSubnode(self.fieldButtonNode)
|
||||
self.addSubnode(self.avatarsNode)
|
||||
self.addSubnode(self.invitedPeersNode)
|
||||
self.addSubnode(self.avatarsButtonNode)
|
||||
@ -189,6 +196,19 @@ public class ItemListPermanentInviteLinkItemNode: ListViewItemNode, ItemListItem
|
||||
|
||||
self.addSubnode(self.activateArea)
|
||||
|
||||
self.fieldButtonNode.highligthedChanged = { [weak self] highlighted in
|
||||
if let strongSelf = self {
|
||||
if highlighted {
|
||||
strongSelf.addressNode.layer.removeAnimation(forKey: "opacity")
|
||||
strongSelf.addressNode.alpha = 0.4
|
||||
} else {
|
||||
strongSelf.addressNode.alpha = 1.0
|
||||
strongSelf.addressNode.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2)
|
||||
}
|
||||
}
|
||||
}
|
||||
self.fieldButtonNode.addTarget(self, action: #selector(self.fieldButtonPressed), forControlEvents: .touchUpInside)
|
||||
|
||||
self.addressButtonNode.addTarget(self, action: #selector(self.addressButtonPressed), forControlEvents: .touchUpInside)
|
||||
self.addressButtonNode.highligthedChanged = { [weak self] highlighted in
|
||||
if let strongSelf = self {
|
||||
@ -224,6 +244,12 @@ public class ItemListPermanentInviteLinkItemNode: ListViewItemNode, ItemListItem
|
||||
self.avatarsButtonNode.addTarget(self, action: #selector(self.avatarsButtonPressed), forControlEvents: .touchUpInside)
|
||||
}
|
||||
|
||||
@objc private func fieldButtonPressed() {
|
||||
if let item = self.item {
|
||||
item.copyAction?()
|
||||
}
|
||||
}
|
||||
|
||||
@objc private func addressButtonPressed() {
|
||||
if let item = self.item {
|
||||
item.contextAction?(self.extractedContainerNode)
|
||||
@ -393,6 +419,7 @@ public class ItemListPermanentInviteLinkItemNode: ListViewItemNode, ItemListItem
|
||||
|
||||
let fieldFrame = CGRect(origin: CGPoint(x: leftInset, y: verticalInset), size: CGSize(width: params.width - leftInset - rightInset, height: fieldHeight))
|
||||
strongSelf.fieldNode.frame = fieldFrame
|
||||
strongSelf.fieldButtonNode.frame = fieldFrame
|
||||
|
||||
strongSelf.addressNode.frame = CGRect(origin: CGPoint(x: fieldFrame.minX + floorToScreenPixels((fieldFrame.width - addressLayout.size.width) / 2.0), y: fieldFrame.minY + floorToScreenPixels((fieldFrame.height - addressLayout.size.height) / 2.0) + 1.0), size: addressLayout.size)
|
||||
|
||||
|
@ -18,6 +18,7 @@ public enum ItemListDisclosureStyle {
|
||||
public enum ItemListDisclosureLabelStyle {
|
||||
case text
|
||||
case detailText
|
||||
case coloredText(UIColor)
|
||||
case multilineDetailText
|
||||
case badge(UIColor)
|
||||
case color(UIColor)
|
||||
@ -277,6 +278,9 @@ public class ItemListDisclosureItemNode: ListViewItemNode, ItemListItemNode {
|
||||
labelBadgeColor = item.presentationData.theme.list.itemSecondaryTextColor
|
||||
labelFont = detailFont
|
||||
labelConstrain = params.width - params.rightInset - 40.0 - leftInset
|
||||
case let .coloredText(color):
|
||||
labelBadgeColor = color
|
||||
labelFont = titleFont
|
||||
default:
|
||||
labelBadgeColor = item.presentationData.theme.list.itemSecondaryTextColor
|
||||
labelFont = titleFont
|
||||
|
@ -30,11 +30,12 @@ private final class ChannelVisibilityControllerArguments {
|
||||
let displayPrivateLinkMenu: (String) -> Void
|
||||
let setPeerIdWithRevealedOptions: (PeerId?, PeerId?) -> Void
|
||||
let revokePeerId: (PeerId) -> Void
|
||||
let shareLink: () -> Void
|
||||
let copyLink: (ExportedInvitation) -> Void
|
||||
let shareLink: (ExportedInvitation) -> Void
|
||||
let linkContextAction: (ASDisplayNode) -> Void
|
||||
let manageInviteLinks: () -> Void
|
||||
|
||||
init(context: AccountContext, updateCurrentType: @escaping (CurrentChannelType) -> Void, updatePublicLinkText: @escaping (String?, String) -> Void, scrollToPublicLinkText: @escaping () -> Void, displayPrivateLinkMenu: @escaping (String) -> Void, setPeerIdWithRevealedOptions: @escaping (PeerId?, PeerId?) -> Void, revokePeerId: @escaping (PeerId) -> Void, shareLink: @escaping () -> Void, linkContextAction: @escaping (ASDisplayNode) -> Void, manageInviteLinks: @escaping () -> Void) {
|
||||
init(context: AccountContext, updateCurrentType: @escaping (CurrentChannelType) -> Void, updatePublicLinkText: @escaping (String?, String) -> Void, scrollToPublicLinkText: @escaping () -> Void, displayPrivateLinkMenu: @escaping (String) -> Void, setPeerIdWithRevealedOptions: @escaping (PeerId?, PeerId?) -> Void, revokePeerId: @escaping (PeerId) -> Void, copyLink: @escaping (ExportedInvitation) -> Void, shareLink: @escaping (ExportedInvitation) -> Void, linkContextAction: @escaping (ASDisplayNode) -> Void, manageInviteLinks: @escaping () -> Void) {
|
||||
self.context = context
|
||||
self.updateCurrentType = updateCurrentType
|
||||
self.updatePublicLinkText = updatePublicLinkText
|
||||
@ -42,6 +43,7 @@ private final class ChannelVisibilityControllerArguments {
|
||||
self.displayPrivateLinkMenu = displayPrivateLinkMenu
|
||||
self.setPeerIdWithRevealedOptions = setPeerIdWithRevealedOptions
|
||||
self.revokePeerId = revokePeerId
|
||||
self.copyLink = copyLink
|
||||
self.shareLink = shareLink
|
||||
self.linkContextAction = linkContextAction
|
||||
self.manageInviteLinks = manageInviteLinks
|
||||
@ -291,8 +293,14 @@ private enum ChannelVisibilityEntry: ItemListNodeEntry {
|
||||
case let .privateLinkHeader(_, title):
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: title, sectionId: self.section)
|
||||
case let .privateLink(_, invite):
|
||||
return ItemListPermanentInviteLinkItem(context: arguments.context, presentationData: presentationData, invite: invite, peers: [], displayButton: true, displayImporters: true, buttonColor: nil, sectionId: self.section, style: .blocks, shareAction: {
|
||||
arguments.shareLink()
|
||||
return ItemListPermanentInviteLinkItem(context: arguments.context, presentationData: presentationData, invite: invite, peers: [], displayButton: true, displayImporters: true, buttonColor: nil, sectionId: self.section, style: .blocks, copyAction: {
|
||||
if let invite = invite {
|
||||
arguments.copyLink(invite)
|
||||
}
|
||||
}, shareAction: {
|
||||
if let invite = invite {
|
||||
arguments.shareLink(invite)
|
||||
}
|
||||
}, contextAction: { node in
|
||||
arguments.linkContextAction(node)
|
||||
}, viewAction: {
|
||||
@ -835,14 +843,7 @@ public func channelVisibilityController(context: AccountContext, peerId: PeerId,
|
||||
|
||||
let revokeLinkDisposable = MetaDisposable()
|
||||
actionsDisposable.add(revokeLinkDisposable)
|
||||
|
||||
actionsDisposable.add((context.account.viewTracker.peerView(peerId) |> filter { $0.cachedData != nil } |> take(1) |> mapToSignal { view -> Signal<String?, NoError> in
|
||||
return ensuredExistingPeerExportedInvitation(account: context.account, peerId: peerId)
|
||||
|> mapToSignal { _ -> Signal<String?, NoError> in
|
||||
return .complete()
|
||||
}
|
||||
}).start())
|
||||
|
||||
|
||||
let arguments = ChannelVisibilityControllerArguments(context: context, updateCurrentType: { type in
|
||||
updateState { state in
|
||||
return state.withUpdatedSelectedType(type)
|
||||
@ -898,22 +899,13 @@ public func channelVisibilityController(context: AccountContext, peerId: PeerId,
|
||||
}
|
||||
})
|
||||
}))
|
||||
}, shareLink: {
|
||||
let _ = (context.account.postbox.transaction { transaction -> String? in
|
||||
if let cachedData = transaction.getPeerCachedData(peerId: peerId) {
|
||||
if let cachedData = cachedData as? CachedChannelData {
|
||||
return cachedData.exportedInvitation?.link
|
||||
} else if let cachedData = cachedData as? CachedGroupData {
|
||||
return cachedData.exportedInvitation?.link
|
||||
}
|
||||
}
|
||||
return nil
|
||||
} |> deliverOnMainQueue).start(next: { link in
|
||||
if let link = link {
|
||||
let shareController = ShareController(context: context, subject: .url(link))
|
||||
presentControllerImpl?(shareController, nil)
|
||||
}
|
||||
})
|
||||
}, copyLink: { invite in
|
||||
UIPasteboard.general.string = invite.link
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
presentControllerImpl?(OverlayStatusController(theme: presentationData.theme, type: .genericSuccess(presentationData.strings.Username_LinkCopied, false)), nil)
|
||||
}, shareLink: { invite in
|
||||
let shareController = ShareController(context: context, subject: .url(invite.link))
|
||||
presentControllerImpl?(shareController, nil)
|
||||
}, linkContextAction: { node in
|
||||
guard let node = node as? ContextExtractedContentContainingNode, let controller = getControllerImpl?() else {
|
||||
return
|
||||
@ -991,7 +983,7 @@ public func channelVisibilityController(context: AccountContext, peerId: PeerId,
|
||||
}
|
||||
}
|
||||
if revoke {
|
||||
revokeLinkDisposable.set((ensuredExistingPeerExportedInvitation(account: context.account, peerId: peerId, revokeExisted: true) |> deliverOnMainQueue).start(completed: {
|
||||
revokeLinkDisposable.set((revokePersistentPeerExportedInvitation(account: context.account, peerId: peerId) |> deliverOnMainQueue).start(completed: {
|
||||
updateState {
|
||||
$0.withUpdatedRevokingPrivateLink(false)
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[-457104426] = { return Api.InputGeoPoint.parse_inputGeoPointEmpty($0) }
|
||||
dict[1210199983] = { return Api.InputGeoPoint.parse_inputGeoPoint($0) }
|
||||
dict[-784000893] = { return Api.payments.ValidatedRequestedInfo.parse_validatedRequestedInfo($0) }
|
||||
dict[231260545] = { return Api.ChatFull.parse_chatFull($0) }
|
||||
dict[-213431562] = { return Api.ChatFull.parse_chatFull($0) }
|
||||
dict[2055070967] = { return Api.ChatFull.parse_channelFull($0) }
|
||||
dict[-1159937629] = { return Api.PollResults.parse_pollResults($0) }
|
||||
dict[-925415106] = { return Api.ChatParticipant.parse_chatParticipant($0) }
|
||||
|
@ -2206,14 +2206,14 @@ public extension Api {
|
||||
|
||||
}
|
||||
public enum ChatFull: TypeConstructorDescription {
|
||||
case chatFull(flags: Int32, id: Int32, about: String, participants: Api.ChatParticipants, chatPhoto: Api.Photo?, notifySettings: Api.PeerNotifySettings, exportedInvite: Api.ExportedChatInvite, botInfo: [Api.BotInfo]?, pinnedMsgId: Int32?, folderId: Int32?, call: Api.InputGroupCall?)
|
||||
case chatFull(flags: Int32, id: Int32, about: String, participants: Api.ChatParticipants, chatPhoto: Api.Photo?, notifySettings: Api.PeerNotifySettings, exportedInvite: Api.ExportedChatInvite?, botInfo: [Api.BotInfo]?, pinnedMsgId: Int32?, folderId: Int32?, call: Api.InputGroupCall?)
|
||||
case channelFull(flags: Int32, id: Int32, about: String, participantsCount: Int32?, adminsCount: Int32?, kickedCount: Int32?, bannedCount: Int32?, onlineCount: Int32?, readInboxMaxId: Int32, readOutboxMaxId: Int32, unreadCount: Int32, chatPhoto: Api.Photo, notifySettings: Api.PeerNotifySettings, exportedInvite: Api.ExportedChatInvite?, botInfo: [Api.BotInfo], migratedFromChatId: Int32?, migratedFromMaxId: Int32?, pinnedMsgId: Int32?, stickerset: Api.StickerSet?, availableMinId: Int32?, folderId: Int32?, linkedChatId: Int32?, location: Api.ChannelLocation?, slowmodeSeconds: Int32?, slowmodeNextSendDate: Int32?, statsDc: Int32?, pts: Int32, call: Api.InputGroupCall?)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .chatFull(let flags, let id, let about, let participants, let chatPhoto, let notifySettings, let exportedInvite, let botInfo, let pinnedMsgId, let folderId, let call):
|
||||
if boxed {
|
||||
buffer.appendInt32(231260545)
|
||||
buffer.appendInt32(-213431562)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeInt32(id, buffer: buffer, boxed: false)
|
||||
@ -2221,7 +2221,7 @@ public extension Api {
|
||||
participants.serialize(buffer, true)
|
||||
if Int(flags) & Int(1 << 2) != 0 {chatPhoto!.serialize(buffer, true)}
|
||||
notifySettings.serialize(buffer, true)
|
||||
exportedInvite.serialize(buffer, true)
|
||||
if Int(flags) & Int(1 << 13) != 0 {exportedInvite!.serialize(buffer, true)}
|
||||
if Int(flags) & Int(1 << 3) != 0 {buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(botInfo!.count))
|
||||
for item in botInfo! {
|
||||
@ -2300,9 +2300,9 @@ public extension Api {
|
||||
_6 = Api.parse(reader, signature: signature) as? Api.PeerNotifySettings
|
||||
}
|
||||
var _7: Api.ExportedChatInvite?
|
||||
if let signature = reader.readInt32() {
|
||||
if Int(_1!) & Int(1 << 13) != 0 {if let signature = reader.readInt32() {
|
||||
_7 = Api.parse(reader, signature: signature) as? Api.ExportedChatInvite
|
||||
}
|
||||
} }
|
||||
var _8: [Api.BotInfo]?
|
||||
if Int(_1!) & Int(1 << 3) != 0 {if let _ = reader.readInt32() {
|
||||
_8 = Api.parseVector(reader, elementSignature: 0, elementType: Api.BotInfo.self)
|
||||
@ -2321,13 +2321,13 @@ public extension Api {
|
||||
let _c4 = _4 != nil
|
||||
let _c5 = (Int(_1!) & Int(1 << 2) == 0) || _5 != nil
|
||||
let _c6 = _6 != nil
|
||||
let _c7 = _7 != nil
|
||||
let _c7 = (Int(_1!) & Int(1 << 13) == 0) || _7 != nil
|
||||
let _c8 = (Int(_1!) & Int(1 << 3) == 0) || _8 != nil
|
||||
let _c9 = (Int(_1!) & Int(1 << 6) == 0) || _9 != nil
|
||||
let _c10 = (Int(_1!) & Int(1 << 11) == 0) || _10 != nil
|
||||
let _c11 = (Int(_1!) & Int(1 << 12) == 0) || _11 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 {
|
||||
return Api.ChatFull.chatFull(flags: _1!, id: _2!, about: _3!, participants: _4!, chatPhoto: _5, notifySettings: _6!, exportedInvite: _7!, botInfo: _8, pinnedMsgId: _9, folderId: _10, call: _11)
|
||||
return Api.ChatFull.chatFull(flags: _1!, id: _2!, about: _3!, participants: _4!, chatPhoto: _5, notifySettings: _6!, exportedInvite: _7, botInfo: _8, pinnedMsgId: _9, folderId: _10, call: _11)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
|
@ -1060,25 +1060,7 @@ public final class VoiceChatController: ViewController {
|
||||
if !strongSelf.didSetDataReady {
|
||||
strongSelf.accountPeer = accountPeer
|
||||
strongSelf.updateMembers(muteState: strongSelf.effectiveMuteState, callMembers: strongSelf.currentCallMembers ?? [], invitedPeers: strongSelf.currentInvitedPeers ?? [], speakingPeers: strongSelf.currentSpeakingPeers ?? Set())
|
||||
|
||||
if let peer = peerViewMainPeer(view) {
|
||||
if let channel = peer as? TelegramChannel {
|
||||
let addressName = channel.addressName ?? ""
|
||||
if channel.flags.contains(.isCreator) || channel.hasPermission(.inviteMembers) {
|
||||
if addressName.isEmpty {
|
||||
let _ = ensuredExistingPeerExportedInvitation(account: strongSelf.context.account, peerId: call.peerId).start()
|
||||
}
|
||||
}
|
||||
} else if let group = peer as? TelegramGroup {
|
||||
switch group.role {
|
||||
case .creator, .admin:
|
||||
let _ = ensuredExistingPeerExportedInvitation(account: strongSelf.context.account, peerId: call.peerId).start()
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
strongSelf.didSetDataReady = true
|
||||
strongSelf.controller?.dataReady.set(true)
|
||||
}
|
||||
|
@ -6,53 +6,45 @@ import MtProtoKit
|
||||
|
||||
import SyncCore
|
||||
|
||||
public func ensuredExistingPeerExportedInvitation(account: Account, peerId: PeerId, revokeExisted: Bool = false) -> Signal<ExportedInvitation?, NoError> {
|
||||
public func revokePersistentPeerExportedInvitation(account: Account, peerId: PeerId) -> Signal<ExportedInvitation?, NoError> {
|
||||
return account.postbox.transaction { transaction -> Signal<ExportedInvitation?, NoError> in
|
||||
if let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) {
|
||||
let flags: Int32 = (1 << 2)
|
||||
if let _ = peer as? TelegramChannel {
|
||||
if let cachedData = transaction.getPeerCachedData(peerId: peerId) as? CachedChannelData, cachedData.exportedInvitation != nil && !revokeExisted {
|
||||
return .single(cachedData.exportedInvitation)
|
||||
} else {
|
||||
return account.network.request(Api.functions.messages.exportChatInvite(flags: flags, peer: inputPeer, expireDate: nil, usageLimit: nil))
|
||||
|> retryRequest
|
||||
|> mapToSignal { result -> Signal<ExportedInvitation?, NoError> in
|
||||
return account.postbox.transaction { transaction -> ExportedInvitation? in
|
||||
if let invitation = ExportedInvitation(apiExportedInvite: result) {
|
||||
transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, current in
|
||||
if let current = current as? CachedChannelData {
|
||||
return current.withUpdatedExportedInvitation(invitation)
|
||||
} else {
|
||||
return CachedChannelData().withUpdatedExportedInvitation(invitation)
|
||||
}
|
||||
})
|
||||
return invitation
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
return account.network.request(Api.functions.messages.exportChatInvite(flags: flags, peer: inputPeer, expireDate: nil, usageLimit: nil))
|
||||
|> retryRequest
|
||||
|> mapToSignal { result -> Signal<ExportedInvitation?, NoError> in
|
||||
return account.postbox.transaction { transaction -> ExportedInvitation? in
|
||||
if let invitation = ExportedInvitation(apiExportedInvite: result) {
|
||||
transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, current in
|
||||
if let current = current as? CachedChannelData {
|
||||
return current.withUpdatedExportedInvitation(invitation)
|
||||
} else {
|
||||
return CachedChannelData().withUpdatedExportedInvitation(invitation)
|
||||
}
|
||||
})
|
||||
return invitation
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if let _ = peer as? TelegramGroup {
|
||||
if let cachedData = transaction.getPeerCachedData(peerId: peerId) as? CachedGroupData, cachedData.exportedInvitation != nil && !revokeExisted {
|
||||
return .complete()
|
||||
} else {
|
||||
return account.network.request(Api.functions.messages.exportChatInvite(flags: flags, peer: inputPeer, expireDate: nil, usageLimit: nil))
|
||||
|> retryRequest
|
||||
|> mapToSignal { result -> Signal<ExportedInvitation?, NoError> in
|
||||
return account.postbox.transaction { transaction -> ExportedInvitation? in
|
||||
if let invitation = ExportedInvitation(apiExportedInvite: result) {
|
||||
transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, current in
|
||||
if let current = current as? CachedGroupData {
|
||||
return current.withUpdatedExportedInvitation(invitation)
|
||||
} else {
|
||||
return current
|
||||
}
|
||||
})
|
||||
return invitation
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
return account.network.request(Api.functions.messages.exportChatInvite(flags: flags, peer: inputPeer, expireDate: nil, usageLimit: nil))
|
||||
|> retryRequest
|
||||
|> mapToSignal { result -> Signal<ExportedInvitation?, NoError> in
|
||||
return account.postbox.transaction { transaction -> ExportedInvitation? in
|
||||
if let invitation = ExportedInvitation(apiExportedInvite: result) {
|
||||
transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, current in
|
||||
if let current = current as? CachedGroupData {
|
||||
return current.withUpdatedExportedInvitation(invitation)
|
||||
} else {
|
||||
return current
|
||||
}
|
||||
})
|
||||
return invitation
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -257,7 +257,7 @@ func fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPeerId: PeerI
|
||||
|
||||
let photo: TelegramMediaImage? = chatFull.chatPhoto.flatMap(telegramMediaImageFromApiPhoto)
|
||||
|
||||
let exportedInvitation = ExportedInvitation(apiExportedInvite: chatFull.exportedInvite)
|
||||
let exportedInvitation = chatFull.exportedInvite.flatMap { ExportedInvitation(apiExportedInvite: $0) }
|
||||
let pinnedMessageId = chatFull.pinnedMsgId.flatMap({ MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: $0) })
|
||||
|
||||
var peers: [Peer] = []
|
||||
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user