mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios
This commit is contained in:
commit
d66a80670a
@ -55,7 +55,7 @@ private enum InviteLinkInviteEntry: Comparable, Identifiable {
|
|||||||
case header(PresentationTheme, String, String)
|
case header(PresentationTheme, String, String)
|
||||||
case mainLink(PresentationTheme, ExportedInvitation)
|
case mainLink(PresentationTheme, ExportedInvitation)
|
||||||
case links(Int32, PresentationTheme, [ExportedInvitation])
|
case links(Int32, PresentationTheme, [ExportedInvitation])
|
||||||
case manage(PresentationTheme, String)
|
case manage(PresentationTheme, String, Bool)
|
||||||
|
|
||||||
var stableId: InviteLinkInviteEntryId {
|
var stableId: InviteLinkInviteEntryId {
|
||||||
switch self {
|
switch self {
|
||||||
@ -90,8 +90,8 @@ private enum InviteLinkInviteEntry: Comparable, Identifiable {
|
|||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
case let .manage(lhsTheme, lhsText):
|
case let .manage(lhsTheme, lhsText, lhsStandalone):
|
||||||
if case let .manage(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
|
if case let .manage(rhsTheme, rhsText, rhsStandalone) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsStandalone == rhsStandalone {
|
||||||
return true
|
return true
|
||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
@ -148,13 +148,13 @@ private enum InviteLinkInviteEntry: Comparable, Identifiable {
|
|||||||
}, viewAction: {
|
}, viewAction: {
|
||||||
})
|
})
|
||||||
case let .links(_, _, invites):
|
case let .links(_, _, invites):
|
||||||
return ItemListInviteLinkGridItem(presentationData: ItemListPresentationData(presentationData), invites: invites, share: true, sectionId: 0, style: .plain, tapAction: { invite in
|
return ItemListInviteLinkGridItem(presentationData: ItemListPresentationData(presentationData), invites: invites, share: true, sectionId: 1, style: .plain, tapAction: { invite in
|
||||||
interaction.copyLink(invite)
|
interaction.copyLink(invite)
|
||||||
}, contextAction: { invite, _ in
|
}, contextAction: { invite, _ in
|
||||||
interaction.shareLink(invite)
|
interaction.shareLink(invite)
|
||||||
})
|
})
|
||||||
case let .manage(theme, text):
|
case let .manage(theme, text, standalone):
|
||||||
return InviteLinkInviteManageItem(theme: theme, text: text, action: {
|
return InviteLinkInviteManageItem(theme: theme, text: text, standalone: standalone, action: {
|
||||||
interaction.manageLinks()
|
interaction.manageLinks()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -257,6 +257,7 @@ public final class InviteLinkInviteController: ViewController {
|
|||||||
|
|
||||||
private let context: AccountContext
|
private let context: AccountContext
|
||||||
private let peerId: PeerId
|
private let peerId: PeerId
|
||||||
|
private let invitesContext: PeerExportedInvitationsContext
|
||||||
|
|
||||||
private var interaction: InviteLinkInviteInteraction?
|
private var interaction: InviteLinkInviteInteraction?
|
||||||
|
|
||||||
@ -290,6 +291,8 @@ public final class InviteLinkInviteController: ViewController {
|
|||||||
self.presentationDataPromise = Promise(self.presentationData)
|
self.presentationDataPromise = Promise(self.presentationData)
|
||||||
self.controller = controller
|
self.controller = controller
|
||||||
|
|
||||||
|
self.invitesContext = PeerExportedInvitationsContext(account: context.account, peerId: peerId, revoked: false, forceUpdate: false)
|
||||||
|
|
||||||
self.dimNode = ASDisplayNode()
|
self.dimNode = ASDisplayNode()
|
||||||
self.dimNode.backgroundColor = UIColor(white: 0.0, alpha: 0.5)
|
self.dimNode.backgroundColor = UIColor(white: 0.0, alpha: 0.5)
|
||||||
|
|
||||||
@ -386,8 +389,9 @@ public final class InviteLinkInviteController: ViewController {
|
|||||||
let contextController = ContextController(account: context.account, presentationData: presentationData, source: .extracted(InviteLinkContextExtractedContentSource(controller: controller, sourceNode: node)), items: .single(items), reactionItems: [], gesture: gesture)
|
let contextController = ContextController(account: context.account, presentationData: presentationData, source: .extracted(InviteLinkContextExtractedContentSource(controller: controller, sourceNode: node)), items: .single(items), reactionItems: [], gesture: gesture)
|
||||||
self?.controller?.presentInGlobalOverlay(contextController)
|
self?.controller?.presentInGlobalOverlay(contextController)
|
||||||
}, copyLink: { [weak self] invite in
|
}, copyLink: { [weak self] invite in
|
||||||
let shareController = ShareController(context: context, subject: .url(invite.link))
|
UIPasteboard.general.string = invite.link
|
||||||
self?.controller?.present(shareController, in: .window(.root))
|
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
|
}, shareLink: { [weak self] invite in
|
||||||
let shareController = ShareController(context: context, subject: .url(invite.link))
|
let shareController = ShareController(context: context, subject: .url(invite.link))
|
||||||
self?.controller?.present(shareController, in: .window(.root))
|
self?.controller?.present(shareController, in: .window(.root))
|
||||||
@ -400,20 +404,38 @@ public final class InviteLinkInviteController: ViewController {
|
|||||||
let previousEntries = Atomic<[InviteLinkInviteEntry]?>(value: nil)
|
let previousEntries = Atomic<[InviteLinkInviteEntry]?>(value: nil)
|
||||||
|
|
||||||
let peerView = context.account.postbox.peerView(id: peerId)
|
let peerView = context.account.postbox.peerView(id: peerId)
|
||||||
self.disposable = (combineLatest(self.presentationDataPromise.get(), peerView)
|
self.disposable = (combineLatest(self.presentationDataPromise.get(), peerView, self.invitesContext.state)
|
||||||
|> deliverOnMainQueue).start(next: { [weak self] presentationData, view in
|
|> deliverOnMainQueue).start(next: { [weak self] presentationData, view, invites in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
var entries: [InviteLinkInviteEntry] = []
|
var entries: [InviteLinkInviteEntry] = []
|
||||||
|
|
||||||
entries.append(.header(presentationData.theme, presentationData.strings.InviteLink_InviteLink, presentationData.strings.InviteLink_CreatePrivateLinkHelp))
|
entries.append(.header(presentationData.theme, presentationData.strings.InviteLink_InviteLink, presentationData.strings.InviteLink_CreatePrivateLinkHelp))
|
||||||
|
|
||||||
|
let mainInvite: ExportedInvitation?
|
||||||
if let cachedData = view.cachedData as? CachedGroupData, let invite = cachedData.exportedInvitation {
|
if let cachedData = view.cachedData as? CachedGroupData, let invite = cachedData.exportedInvitation {
|
||||||
entries.append(.mainLink(presentationData.theme, invite))
|
mainInvite = invite
|
||||||
} else if let cachedData = view.cachedData as? CachedChannelData, let invite = cachedData.exportedInvitation {
|
} else if let cachedData = view.cachedData as? CachedChannelData, let invite = cachedData.exportedInvitation {
|
||||||
entries.append(.mainLink(presentationData.theme, invite))
|
mainInvite = invite
|
||||||
|
} else {
|
||||||
|
mainInvite = nil
|
||||||
|
}
|
||||||
|
if let mainInvite = mainInvite {
|
||||||
|
entries.append(.mainLink(presentationData.theme, mainInvite))
|
||||||
}
|
}
|
||||||
|
|
||||||
entries.append(.manage(presentationData.theme, presentationData.strings.InviteLink_Manage))
|
let additionalInvites = invites.invitations.filter { $0.link != mainInvite?.link }
|
||||||
|
var index: Int32 = 0
|
||||||
|
for i in stride(from: 0, to: additionalInvites.endIndex, by: 2) {
|
||||||
|
var invitesPair: [ExportedInvitation] = []
|
||||||
|
invitesPair.append(additionalInvites[i])
|
||||||
|
if i + 1 < additionalInvites.count {
|
||||||
|
invitesPair.append(additionalInvites[i + 1])
|
||||||
|
}
|
||||||
|
entries.append(.links(index, presentationData.theme, invitesPair))
|
||||||
|
index += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
entries.append(.manage(presentationData.theme, presentationData.strings.InviteLink_Manage, additionalInvites.isEmpty))
|
||||||
|
|
||||||
let previousEntries = previousEntries.swap(entries)
|
let previousEntries = previousEntries.swap(entries)
|
||||||
|
|
||||||
|
@ -14,12 +14,13 @@ class InviteLinkInviteManageItem: ListViewItem, ItemListItem {
|
|||||||
|
|
||||||
let theme: PresentationTheme
|
let theme: PresentationTheme
|
||||||
let text: String
|
let text: String
|
||||||
|
let standalone: Bool
|
||||||
let action: () -> Void
|
let action: () -> Void
|
||||||
|
|
||||||
init(theme: PresentationTheme, text: String, action: @escaping () -> Void) {
|
init(theme: PresentationTheme, text: String, standalone: Bool, action: @escaping () -> Void) {
|
||||||
self.theme = theme
|
self.theme = theme
|
||||||
self.text = text
|
self.text = text
|
||||||
|
self.standalone = standalone
|
||||||
self.action = action
|
self.action = action
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,8 +95,12 @@ class InviteLinkInviteManageItemNode: ListViewItemNode {
|
|||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
strongSelf.item = item
|
strongSelf.item = item
|
||||||
|
|
||||||
|
strongSelf.backgroundNode.backgroundColor = item.standalone ? .clear : item.theme.list.blocksBackgroundColor
|
||||||
|
|
||||||
strongSelf.buttonNode.setTitle(item.text, with: Font.regular(17.0), with: item.theme.actionSheet.controlAccentColor, for: .normal)
|
strongSelf.buttonNode.setTitle(item.text, with: Font.regular(17.0), with: item.theme.actionSheet.controlAccentColor, for: .normal)
|
||||||
|
|
||||||
|
strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: params.width, height: 1000.0))
|
||||||
|
|
||||||
let size = strongSelf.buttonNode.measure(layout.contentSize)
|
let size = strongSelf.buttonNode.measure(layout.contentSize)
|
||||||
strongSelf.buttonNode.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((layout.contentSize.width - size.width) / 2.0), y: floorToScreenPixels((layout.contentSize.height - size.height) / 2.0)), size: size)
|
strongSelf.buttonNode.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((layout.contentSize.width - size.width) / 2.0), y: floorToScreenPixels((layout.contentSize.height - size.height) / 2.0)), size: size)
|
||||||
}
|
}
|
||||||
|
@ -316,7 +316,7 @@ public func inviteLinkListController(context: AccountContext, peerId: PeerId) ->
|
|||||||
let shareController = ShareController(context: context, subject: .url(invite.link))
|
let shareController = ShareController(context: context, subject: .url(invite.link))
|
||||||
presentControllerImpl?(shareController, nil)
|
presentControllerImpl?(shareController, nil)
|
||||||
}, openMainLink: { invite in
|
}, openMainLink: { invite in
|
||||||
let controller = InviteLinkViewController(context: context, peerId: peerId, invite: invite, invitationsContext: nil, importersContext: nil)
|
let controller = InviteLinkViewController(context: context, peerId: peerId, invite: invite, invitationsContext: nil, revokedInvitationsContext: revokedInvitesContext, importersContext: nil)
|
||||||
pushControllerImpl?(controller)
|
pushControllerImpl?(controller)
|
||||||
}, copyLink: { invite in
|
}, copyLink: { invite in
|
||||||
UIPasteboard.general.string = invite.link
|
UIPasteboard.general.string = invite.link
|
||||||
@ -409,7 +409,7 @@ public func inviteLinkListController(context: AccountContext, peerId: PeerId) ->
|
|||||||
pushControllerImpl?(controller)
|
pushControllerImpl?(controller)
|
||||||
}, openLink: { invite in
|
}, openLink: { invite in
|
||||||
if let invite = invite {
|
if let invite = invite {
|
||||||
let controller = InviteLinkViewController(context: context, peerId: peerId, invite: invite, invitationsContext: invitesContext, importersContext: nil)
|
let controller = InviteLinkViewController(context: context, peerId: peerId, invite: invite, invitationsContext: invitesContext, revokedInvitationsContext: revokedInvitesContext, importersContext: nil)
|
||||||
pushControllerImpl?(controller)
|
pushControllerImpl?(controller)
|
||||||
}
|
}
|
||||||
}, linkContextAction: { invite, node, gesture in
|
}, linkContextAction: { invite, node, gesture in
|
||||||
@ -449,7 +449,7 @@ public func inviteLinkListController(context: AccountContext, peerId: PeerId) ->
|
|||||||
if let invite = invite {
|
if let invite = invite {
|
||||||
if invite.isRevoked {
|
if invite.isRevoked {
|
||||||
invitesContext.remove(invite)
|
invitesContext.remove(invite)
|
||||||
revokedInvitesContext.add(invite)
|
revokedInvitesContext.add(invite.withUpdated(isRevoked: true))
|
||||||
} else {
|
} else {
|
||||||
invitesContext.update(invite)
|
invitesContext.update(invite)
|
||||||
}
|
}
|
||||||
@ -508,7 +508,7 @@ public func inviteLinkListController(context: AccountContext, peerId: PeerId) ->
|
|||||||
}))
|
}))
|
||||||
|
|
||||||
invitesContext.remove(invite)
|
invitesContext.remove(invite)
|
||||||
revokedInvitesContext.add(invite)
|
revokedInvitesContext.add(invite.withUpdated(isRevoked: true))
|
||||||
})
|
})
|
||||||
]),
|
]),
|
||||||
ActionSheetItemGroup(items: [ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, action: { dismissAction() })])
|
ActionSheetItemGroup(items: [ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, action: { dismissAction() })])
|
||||||
|
@ -218,15 +218,17 @@ public final class InviteLinkViewController: ViewController {
|
|||||||
private let peerId: PeerId
|
private let peerId: PeerId
|
||||||
private let invite: ExportedInvitation
|
private let invite: ExportedInvitation
|
||||||
private let invitationsContext: PeerExportedInvitationsContext?
|
private let invitationsContext: PeerExportedInvitationsContext?
|
||||||
|
private let revokedInvitationsContext: PeerExportedInvitationsContext?
|
||||||
private let importersContext: PeerInvitationImportersContext?
|
private let importersContext: PeerInvitationImportersContext?
|
||||||
|
|
||||||
private var presentationDataDisposable: Disposable?
|
private var presentationDataDisposable: Disposable?
|
||||||
|
|
||||||
public init(context: AccountContext, peerId: PeerId, invite: ExportedInvitation, invitationsContext: PeerExportedInvitationsContext?, importersContext: PeerInvitationImportersContext?) {
|
public init(context: AccountContext, peerId: PeerId, invite: ExportedInvitation, invitationsContext: PeerExportedInvitationsContext?, revokedInvitationsContext: PeerExportedInvitationsContext?, importersContext: PeerInvitationImportersContext?) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.peerId = peerId
|
self.peerId = peerId
|
||||||
self.invite = invite
|
self.invite = invite
|
||||||
self.invitationsContext = invitationsContext
|
self.invitationsContext = invitationsContext
|
||||||
|
self.revokedInvitationsContext = revokedInvitationsContext
|
||||||
self.importersContext = importersContext
|
self.importersContext = importersContext
|
||||||
|
|
||||||
super.init(navigationBarPresentationData: nil)
|
super.init(navigationBarPresentationData: nil)
|
||||||
@ -299,12 +301,16 @@ public final class InviteLinkViewController: ViewController {
|
|||||||
private let peerId: PeerId
|
private let peerId: PeerId
|
||||||
private let invite: ExportedInvitation
|
private let invite: ExportedInvitation
|
||||||
|
|
||||||
|
private let importersContext: PeerInvitationImportersContext
|
||||||
|
|
||||||
private var interaction: InviteLinkViewInteraction?
|
private var interaction: InviteLinkViewInteraction?
|
||||||
|
|
||||||
private var presentationData: PresentationData
|
private var presentationData: PresentationData
|
||||||
private let presentationDataPromise: Promise<PresentationData>
|
private let presentationDataPromise: Promise<PresentationData>
|
||||||
|
private var presentationDataDisposable: Disposable?
|
||||||
|
|
||||||
private var disposable: Disposable?
|
private var disposable: Disposable?
|
||||||
|
private let actionDisposable = MetaDisposable()
|
||||||
|
|
||||||
private let dimNode: ASDisplayNode
|
private let dimNode: ASDisplayNode
|
||||||
private let contentNode: ASDisplayNode
|
private let contentNode: ASDisplayNode
|
||||||
@ -323,10 +329,6 @@ public final class InviteLinkViewController: ViewController {
|
|||||||
|
|
||||||
private var validLayout: ContainerViewLayout?
|
private var validLayout: ContainerViewLayout?
|
||||||
|
|
||||||
private var presentationDataDisposable: Disposable?
|
|
||||||
|
|
||||||
private let importersContext: PeerInvitationImportersContext
|
|
||||||
|
|
||||||
init(context: AccountContext, peerId: PeerId, invite: ExportedInvitation, importersContext: PeerInvitationImportersContext?, controller: InviteLinkViewController) {
|
init(context: AccountContext, peerId: PeerId, invite: ExportedInvitation, importersContext: PeerInvitationImportersContext?, controller: InviteLinkViewController) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.peerId = peerId
|
self.peerId = peerId
|
||||||
@ -420,7 +422,24 @@ public final class InviteLinkViewController: ViewController {
|
|||||||
}, action: { [weak self] _, f in
|
}, action: { [weak self] _, f in
|
||||||
f(.dismissWithoutContent)
|
f(.dismissWithoutContent)
|
||||||
|
|
||||||
let controller = InviteLinkQRCodeController(context: context, invite: invite)
|
let controller = ActionSheetController(presentationData: presentationData)
|
||||||
|
let dismissAction: () -> Void = { [weak controller] in
|
||||||
|
controller?.dismissAnimated()
|
||||||
|
}
|
||||||
|
controller.setItemGroups([
|
||||||
|
ActionSheetItemGroup(items: [
|
||||||
|
ActionSheetTextItem(title: presentationData.strings.InviteLink_DeleteLinkAlert_Text),
|
||||||
|
ActionSheetButtonItem(title: presentationData.strings.InviteLink_DeleteLinkAlert_Action, color: .destructive, action: {
|
||||||
|
dismissAction()
|
||||||
|
|
||||||
|
self?.actionDisposable.set((deletePeerExportedInvitation(account: context.account, peerId: peerId, link: invite.link) |> deliverOnMainQueue).start(completed: {
|
||||||
|
}))
|
||||||
|
|
||||||
|
self?.controller?.revokedInvitationsContext?.remove(invite)
|
||||||
|
})
|
||||||
|
]),
|
||||||
|
ActionSheetItemGroup(items: [ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, action: { dismissAction() })])
|
||||||
|
])
|
||||||
self?.controller?.present(controller, in: .window(.root))
|
self?.controller?.present(controller, in: .window(.root))
|
||||||
})))
|
})))
|
||||||
} else {
|
} else {
|
||||||
|
@ -63,11 +63,36 @@ private enum ItemBackgroundColor: Equatable {
|
|||||||
case .red:
|
case .red:
|
||||||
return (UIColor(rgb: 0xf2656a), UIColor(rgb: 0xf25f65), UIColor(rgb: 0xffd3de))
|
return (UIColor(rgb: 0xf2656a), UIColor(rgb: 0xf25f65), UIColor(rgb: 0xffd3de))
|
||||||
case .gray:
|
case .gray:
|
||||||
return (UIColor(rgb: 0xd4d8db), UIColor(rgb: 0xced2d5), UIColor(rgb: 0xf8f9f9))
|
return (UIColor(rgb: 0xa8b2bb), UIColor(rgb: 0xa2abb4), UIColor(rgb: 0xe3e6e8))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private let moreIcon = generateImage(CGSize(width: 26.0, height: 26.0), contextGenerator: { size, context in
|
||||||
|
context.clear(CGRect(origin: CGPoint(), size: size))
|
||||||
|
|
||||||
|
context.setFillColor(UIColor.white.cgColor)
|
||||||
|
context.fillEllipse(in: CGRect(origin: CGPoint(), size: size))
|
||||||
|
|
||||||
|
context.setBlendMode(.clear)
|
||||||
|
context.fillEllipse(in: CGRect(origin: CGPoint(x: 4.0, y: 11.0), size: CGSize(width: 4.0, height: 4.0)))
|
||||||
|
context.fillEllipse(in: CGRect(origin: CGPoint(x: 11.0, y: 11.0), size: CGSize(width: 4.0, height: 4.0)))
|
||||||
|
context.fillEllipse(in: CGRect(origin: CGPoint(x: 18.0, y: 11.0), size: CGSize(width: 4.0, height: 4.0)))
|
||||||
|
})
|
||||||
|
|
||||||
|
private let shareIcon = generateImage(CGSize(width: 26.0, height: 26.0), contextGenerator: { size, context in
|
||||||
|
context.clear(CGRect(origin: CGPoint(), size: size))
|
||||||
|
|
||||||
|
context.setFillColor(UIColor.white.cgColor)
|
||||||
|
context.fillEllipse(in: CGRect(origin: CGPoint(), size: size))
|
||||||
|
|
||||||
|
if let maskImage = UIImage(bundleImageName: "Chat/Links/Share") {
|
||||||
|
context.clip(to: CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - maskImage.size.width) / 2.0), y: floorToScreenPixels((size.height - maskImage.size.height) / 2.0)), size: maskImage.size), mask: maskImage.cgImage!)
|
||||||
|
context.setBlendMode(.clear)
|
||||||
|
context.fillEllipse(in: CGRect(origin: CGPoint(), size: size))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
private class ItemNode: ASDisplayNode {
|
private class ItemNode: ASDisplayNode {
|
||||||
private let selectionNode: HighlightTrackingButtonNode
|
private let selectionNode: HighlightTrackingButtonNode
|
||||||
private let wrapperNode: ASDisplayNode
|
private let wrapperNode: ASDisplayNode
|
||||||
@ -114,17 +139,6 @@ private class ItemNode: ASDisplayNode {
|
|||||||
self.buttonIconNode = ASImageNode()
|
self.buttonIconNode = ASImageNode()
|
||||||
self.buttonIconNode.displaysAsynchronously = false
|
self.buttonIconNode.displaysAsynchronously = false
|
||||||
self.buttonIconNode.displayWithoutProcessing = true
|
self.buttonIconNode.displayWithoutProcessing = true
|
||||||
self.buttonIconNode.image = generateImage(CGSize(width: 26.0, height: 26.0), contextGenerator: { size, context in
|
|
||||||
context.clear(CGRect(origin: CGPoint(), size: size))
|
|
||||||
|
|
||||||
context.setFillColor(UIColor.white.cgColor)
|
|
||||||
context.fillEllipse(in: CGRect(origin: CGPoint(), size: size))
|
|
||||||
|
|
||||||
context.setBlendMode(.clear)
|
|
||||||
context.fillEllipse(in: CGRect(origin: CGPoint(x: 4.0, y: 11.0), size: CGSize(width: 4.0, height: 4.0)))
|
|
||||||
context.fillEllipse(in: CGRect(origin: CGPoint(x: 11.0, y: 11.0), size: CGSize(width: 4.0, height: 4.0)))
|
|
||||||
context.fillEllipse(in: CGRect(origin: CGPoint(x: 18.0, y: 11.0), size: CGSize(width: 4.0, height: 4.0)))
|
|
||||||
})
|
|
||||||
|
|
||||||
self.titleNode = ImmediateTextNode()
|
self.titleNode = ImmediateTextNode()
|
||||||
self.titleNode.maximumNumberOfLines = 2
|
self.titleNode.maximumNumberOfLines = 2
|
||||||
@ -264,6 +278,8 @@ private class ItemNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
self.titleNode.attributedText = title
|
self.titleNode.attributedText = title
|
||||||
|
|
||||||
|
self.buttonIconNode.image = share ? shareIcon : moreIcon
|
||||||
|
|
||||||
var subtitleText: String = ""
|
var subtitleText: String = ""
|
||||||
if let count = invite.count {
|
if let count = invite.count {
|
||||||
subtitleText = presentationData.strings.InviteLink_PeopleJoinedShort(count)
|
subtitleText = presentationData.strings.InviteLink_PeopleJoinedShort(count)
|
||||||
@ -282,7 +298,11 @@ private class ItemNode: ASDisplayNode {
|
|||||||
if !subtitleText.isEmpty {
|
if !subtitleText.isEmpty {
|
||||||
subtitleText += " • "
|
subtitleText += " • "
|
||||||
}
|
}
|
||||||
|
if share {
|
||||||
|
subtitleText = presentationData.strings.InviteLink_Expired
|
||||||
|
} else {
|
||||||
subtitleText += presentationData.strings.InviteLink_Expired
|
subtitleText += presentationData.strings.InviteLink_Expired
|
||||||
|
}
|
||||||
self.iconNode.image = generateTintedImage(image: UIImage(bundleImageName: "Chat/Links/Expired"), color: .white)
|
self.iconNode.image = generateTintedImage(image: UIImage(bundleImageName: "Chat/Links/Expired"), color: .white)
|
||||||
self.timerNode?.removeFromSupernode()
|
self.timerNode?.removeFromSupernode()
|
||||||
self.timerNode = nil
|
self.timerNode = nil
|
||||||
@ -290,7 +310,11 @@ private class ItemNode: ASDisplayNode {
|
|||||||
if !subtitleText.isEmpty {
|
if !subtitleText.isEmpty {
|
||||||
subtitleText += " • "
|
subtitleText += " • "
|
||||||
}
|
}
|
||||||
|
if share {
|
||||||
|
subtitleText = presentationData.strings.InviteLink_UsageLimitReached
|
||||||
|
} else {
|
||||||
subtitleText += presentationData.strings.InviteLink_UsageLimitReached
|
subtitleText += presentationData.strings.InviteLink_UsageLimitReached
|
||||||
|
}
|
||||||
self.iconNode.image = generateTintedImage(image: UIImage(bundleImageName: "Chat/Links/Expired"), color: .white)
|
self.iconNode.image = generateTintedImage(image: UIImage(bundleImageName: "Chat/Links/Expired"), color: .white)
|
||||||
self.timerNode?.removeFromSupernode()
|
self.timerNode?.removeFromSupernode()
|
||||||
self.timerNode = nil
|
self.timerNode = nil
|
||||||
@ -306,10 +330,16 @@ private class ItemNode: ASDisplayNode {
|
|||||||
self.addSubnode(timerNode)
|
self.addSubnode(timerNode)
|
||||||
}
|
}
|
||||||
timerNode.update(color: UIColor.white, creationTimestamp: invite.date, deadlineTimestamp: expireDate)
|
timerNode.update(color: UIColor.white, creationTimestamp: invite.date, deadlineTimestamp: expireDate)
|
||||||
|
if share {
|
||||||
|
subtitleText = presentationData.strings.InviteLink_TapToCopy
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
self.iconNode.image = generateTintedImage(image: UIImage(bundleImageName: "Chat/Links/Link"), color: .white)
|
self.iconNode.image = generateTintedImage(image: UIImage(bundleImageName: "Chat/Links/Link"), color: .white)
|
||||||
self.timerNode?.removeFromSupernode()
|
self.timerNode?.removeFromSupernode()
|
||||||
self.timerNode = nil
|
self.timerNode = nil
|
||||||
|
if share {
|
||||||
|
subtitleText = presentationData.strings.InviteLink_TapToCopy
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.iconNode.frame = CGRect(x: 10.0, y: 10.0, width: 30.0, height: 30.0)
|
self.iconNode.frame = CGRect(x: 10.0, y: 10.0, width: 30.0, height: 30.0)
|
||||||
|
@ -130,14 +130,21 @@ public class ItemListInviteLinkGridItemNode: ListViewItemNode, ItemListItemNode
|
|||||||
let itemSeparatorColor: UIColor
|
let itemSeparatorColor: UIColor
|
||||||
|
|
||||||
let leftInset = 16.0 + params.leftInset
|
let leftInset = 16.0 + params.leftInset
|
||||||
|
let topInset: CGFloat
|
||||||
|
if case .plain = item.style, case .otherSection = neighbors.top {
|
||||||
|
topInset = 16.0
|
||||||
|
} else {
|
||||||
|
topInset = 4.0
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
var height: CGFloat
|
var height: CGFloat
|
||||||
let count = item.invites?.count ?? 0
|
let count = item.invites?.count ?? 0
|
||||||
if count > 0 {
|
if count > 0 {
|
||||||
if count % 2 == 0 {
|
if count % 2 == 0 {
|
||||||
height = 4.0 + 122.0 + 6.0
|
height = topInset + 122.0 + 6.0
|
||||||
} else {
|
} else {
|
||||||
height = 4.0 + 102.0 + 6.0
|
height = topInset + 102.0 + 6.0
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
height = 0.001
|
height = 0.001
|
||||||
@ -145,9 +152,9 @@ public class ItemListInviteLinkGridItemNode: ListViewItemNode, ItemListItemNode
|
|||||||
|
|
||||||
switch item.style {
|
switch item.style {
|
||||||
case .plain:
|
case .plain:
|
||||||
itemBackgroundColor = item.presentationData.theme.list.plainBackgroundColor
|
itemBackgroundColor = item.presentationData.theme.list.blocksBackgroundColor
|
||||||
itemSeparatorColor = item.presentationData.theme.list.itemPlainSeparatorColor
|
itemSeparatorColor = item.presentationData.theme.list.blocksBackgroundColor
|
||||||
insets = itemListNeighborsPlainInsets(neighbors)
|
insets = UIEdgeInsets()
|
||||||
case .blocks:
|
case .blocks:
|
||||||
itemBackgroundColor = item.presentationData.theme.list.itemBlocksBackgroundColor
|
itemBackgroundColor = item.presentationData.theme.list.itemBlocksBackgroundColor
|
||||||
itemSeparatorColor = item.presentationData.theme.list.itemBlocksSeparatorColor
|
itemSeparatorColor = item.presentationData.theme.list.itemBlocksSeparatorColor
|
||||||
@ -155,7 +162,7 @@ public class ItemListInviteLinkGridItemNode: ListViewItemNode, ItemListItemNode
|
|||||||
}
|
}
|
||||||
if case .sameSection(false) = neighbors.bottom {
|
if case .sameSection(false) = neighbors.bottom {
|
||||||
} else {
|
} else {
|
||||||
height += 6.0
|
height += 10.0
|
||||||
}
|
}
|
||||||
contentSize = CGSize(width: params.width, height: height)
|
contentSize = CGSize(width: params.width, height: height)
|
||||||
|
|
||||||
@ -170,7 +177,7 @@ public class ItemListInviteLinkGridItemNode: ListViewItemNode, ItemListItemNode
|
|||||||
}
|
}
|
||||||
|
|
||||||
let gridSize = strongSelf.gridNode.update(size: contentSize, safeInset: params.leftInset, items: item.invites ?? [], share: item.share, presentationData: item.presentationData, transition: .immediate)
|
let gridSize = strongSelf.gridNode.update(size: contentSize, safeInset: params.leftInset, items: item.invites ?? [], share: item.share, presentationData: item.presentationData, transition: .immediate)
|
||||||
strongSelf.gridNode.frame = CGRect(origin: CGPoint(), size: gridSize)
|
strongSelf.gridNode.frame = CGRect(origin: CGPoint(x: 0.0, y: topInset - 4.0), size: gridSize)
|
||||||
strongSelf.gridNode.action = { invite in
|
strongSelf.gridNode.action = { invite in
|
||||||
item.tapAction?(invite)
|
item.tapAction?(invite)
|
||||||
}
|
}
|
||||||
@ -180,18 +187,19 @@ public class ItemListInviteLinkGridItemNode: ListViewItemNode, ItemListItemNode
|
|||||||
|
|
||||||
switch item.style {
|
switch item.style {
|
||||||
case .plain:
|
case .plain:
|
||||||
if strongSelf.backgroundNode.supernode != nil {
|
if strongSelf.backgroundNode.supernode == nil {
|
||||||
strongSelf.backgroundNode.removeFromSupernode()
|
strongSelf.insertSubnode(strongSelf.backgroundNode, at: 0)
|
||||||
}
|
}
|
||||||
if strongSelf.topStripeNode.supernode != nil {
|
if strongSelf.topStripeNode.supernode != nil {
|
||||||
strongSelf.topStripeNode.removeFromSupernode()
|
strongSelf.topStripeNode.removeFromSupernode()
|
||||||
}
|
}
|
||||||
if strongSelf.bottomStripeNode.supernode == nil {
|
if strongSelf.bottomStripeNode.supernode != nil {
|
||||||
strongSelf.insertSubnode(strongSelf.bottomStripeNode, at: 0)
|
strongSelf.bottomStripeNode.removeFromSupernode()
|
||||||
}
|
}
|
||||||
if strongSelf.maskNode.supernode != nil {
|
if strongSelf.maskNode.supernode != nil {
|
||||||
strongSelf.maskNode.removeFromSupernode()
|
strongSelf.maskNode.removeFromSupernode()
|
||||||
}
|
}
|
||||||
|
strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: params.width, height: contentSize.height))
|
||||||
strongSelf.bottomStripeNode.frame = CGRect(origin: CGPoint(x: leftInset, y: contentSize.height - separatorHeight), size: CGSize(width: params.width - leftInset, height: separatorHeight))
|
strongSelf.bottomStripeNode.frame = CGRect(origin: CGPoint(x: leftInset, y: contentSize.height - separatorHeight), size: CGSize(width: params.width - leftInset, height: separatorHeight))
|
||||||
case .blocks:
|
case .blocks:
|
||||||
if strongSelf.backgroundNode.supernode == nil {
|
if strongSelf.backgroundNode.supernode == nil {
|
||||||
|
@ -169,6 +169,7 @@ public class ItemListPermanentInviteLinkItemNode: ListViewItemNode, ItemListItem
|
|||||||
self.containerNode = ContextControllerSourceNode()
|
self.containerNode = ContextControllerSourceNode()
|
||||||
self.containerNode.isGestureEnabled = false
|
self.containerNode.isGestureEnabled = false
|
||||||
self.addressButtonIconNode = ASImageNode()
|
self.addressButtonIconNode = ASImageNode()
|
||||||
|
self.addressButtonIconNode.contentMode = .center
|
||||||
self.addressButtonIconNode.displaysAsynchronously = false
|
self.addressButtonIconNode.displaysAsynchronously = false
|
||||||
self.addressButtonIconNode.displayWithoutProcessing = true
|
self.addressButtonIconNode.displayWithoutProcessing = true
|
||||||
|
|
||||||
@ -423,7 +424,7 @@ public class ItemListPermanentInviteLinkItemNode: ListViewItemNode, ItemListItem
|
|||||||
|
|
||||||
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)
|
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)
|
||||||
|
|
||||||
strongSelf.addressButtonNode.frame = CGRect(origin: CGPoint(x: params.width - rightInset - 38.0, y: verticalInset + 14.0), size: CGSize(width: 24.0, height: 24.0))
|
strongSelf.addressButtonNode.frame = CGRect(origin: CGPoint(x: params.width - rightInset - 38.0 - 14.0, y: verticalInset), size: CGSize(width: 52.0, height: 52.0))
|
||||||
strongSelf.extractedContainerNode.frame = strongSelf.addressButtonNode.bounds
|
strongSelf.extractedContainerNode.frame = strongSelf.addressButtonNode.bounds
|
||||||
strongSelf.extractedContainerNode.contentRect = strongSelf.addressButtonNode.bounds
|
strongSelf.extractedContainerNode.contentRect = strongSelf.addressButtonNode.bounds
|
||||||
strongSelf.addressButtonIconNode.frame = strongSelf.addressButtonNode.bounds
|
strongSelf.addressButtonIconNode.frame = strongSelf.addressButtonNode.bounds
|
||||||
|
@ -125,18 +125,18 @@ private enum ChannelVisibilityEntry: ItemListNodeEntry {
|
|||||||
return 8
|
return 8
|
||||||
case .privateLinkInfo:
|
case .privateLinkInfo:
|
||||||
return 9
|
return 9
|
||||||
case .privateLinkManage:
|
|
||||||
return 10
|
|
||||||
case .privateLinkManageInfo:
|
|
||||||
return 11
|
|
||||||
case .publicLinkStatus:
|
case .publicLinkStatus:
|
||||||
return 12
|
return 10
|
||||||
case .publicLinkInfo:
|
case .publicLinkInfo:
|
||||||
return 13
|
return 11
|
||||||
case .existingLinksInfo:
|
case .existingLinksInfo:
|
||||||
return 14
|
return 12
|
||||||
case let .existingLinkPeerItem(index, _, _, _, _, _, _, _):
|
case let .existingLinkPeerItem(index, _, _, _, _, _, _, _):
|
||||||
return 15 + index
|
return 13 + index
|
||||||
|
case .privateLinkManage:
|
||||||
|
return 1000
|
||||||
|
case .privateLinkManageInfo:
|
||||||
|
return 1001
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -598,6 +598,13 @@ private func channelVisibilityControllerEntries(presentationData: PresentationDa
|
|||||||
} else {
|
} else {
|
||||||
entries.append(.publicLinkInfo(presentationData.theme, presentationData.strings.Channel_Username_CreatePublicLinkHelp))
|
entries.append(.publicLinkInfo(presentationData.theme, presentationData.strings.Channel_Username_CreatePublicLinkHelp))
|
||||||
}
|
}
|
||||||
|
switch mode {
|
||||||
|
case .initialSetup:
|
||||||
|
break
|
||||||
|
case .generic, .privateLink:
|
||||||
|
entries.append(.privateLinkManage(presentationData.theme, presentationData.strings.InviteLink_Manage))
|
||||||
|
entries.append(.privateLinkManageInfo(presentationData.theme, presentationData.strings.InviteLink_CreateInfo))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
case .privateChannel:
|
case .privateChannel:
|
||||||
let invite = (view.cachedData as? CachedChannelData)?.exportedInvitation
|
let invite = (view.cachedData as? CachedChannelData)?.exportedInvitation
|
||||||
|
@ -66,4 +66,8 @@ public struct ExportedInvitation: PostboxCoding, Equatable {
|
|||||||
public static func ==(lhs: ExportedInvitation, rhs: ExportedInvitation) -> Bool {
|
public static func ==(lhs: ExportedInvitation, rhs: ExportedInvitation) -> Bool {
|
||||||
return lhs.link == rhs.link && lhs.isPermanent == rhs.isPermanent && lhs.isRevoked == rhs.isRevoked && lhs.adminId == rhs.adminId && lhs.date == rhs.date && lhs.startDate == rhs.startDate && lhs.expireDate == rhs.expireDate && lhs.usageLimit == rhs.usageLimit && lhs.count == rhs.count
|
return lhs.link == rhs.link && lhs.isPermanent == rhs.isPermanent && lhs.isRevoked == rhs.isRevoked && lhs.adminId == rhs.adminId && lhs.date == rhs.date && lhs.startDate == rhs.startDate && lhs.expireDate == rhs.expireDate && lhs.usageLimit == rhs.usageLimit && lhs.count == rhs.count
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func withUpdated(isRevoked: Bool) -> ExportedInvitation {
|
||||||
|
return ExportedInvitation(link: self.link, isPermanent: self.isPermanent, isRevoked: isRevoked, adminId: self.adminId, date: self.date, startDate: self.startDate, expireDate: self.expireDate, usageLimit: self.usageLimit, count: self.count)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -3942,15 +3942,16 @@ public extension Api {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func getExportedChatInvites(flags: Int32, peer: Api.InputPeer, adminId: Api.InputUser?, offsetLink: String?, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.messages.ExportedChatInvites>) {
|
public static func getExportedChatInvites(flags: Int32, peer: Api.InputPeer, adminId: Api.InputUser?, offsetDate: Int32?, offsetLink: String?, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.messages.ExportedChatInvites>) {
|
||||||
let buffer = Buffer()
|
let buffer = Buffer()
|
||||||
buffer.appendInt32(1838984707)
|
buffer.appendInt32(1785900140)
|
||||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||||
peer.serialize(buffer, true)
|
peer.serialize(buffer, true)
|
||||||
if Int(flags) & Int(1 << 0) != 0 {adminId!.serialize(buffer, true)}
|
if Int(flags) & Int(1 << 0) != 0 {adminId!.serialize(buffer, true)}
|
||||||
|
if Int(flags) & Int(1 << 2) != 0 {serializeInt32(offsetDate!, buffer: buffer, boxed: false)}
|
||||||
if Int(flags) & Int(1 << 2) != 0 {serializeString(offsetLink!, buffer: buffer, boxed: false)}
|
if Int(flags) & Int(1 << 2) != 0 {serializeString(offsetLink!, buffer: buffer, boxed: false)}
|
||||||
serializeInt32(limit, buffer: buffer, boxed: false)
|
serializeInt32(limit, buffer: buffer, boxed: false)
|
||||||
return (FunctionDescription(name: "messages.getExportedChatInvites", parameters: [("flags", flags), ("peer", peer), ("adminId", adminId), ("offsetLink", offsetLink), ("limit", limit)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.ExportedChatInvites? in
|
return (FunctionDescription(name: "messages.getExportedChatInvites", parameters: [("flags", flags), ("peer", peer), ("adminId", adminId), ("offsetDate", offsetDate), ("offsetLink", offsetLink), ("limit", limit)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.ExportedChatInvites? in
|
||||||
let reader = BufferReader(buffer)
|
let reader = BufferReader(buffer)
|
||||||
var result: Api.messages.ExportedChatInvites?
|
var result: Api.messages.ExportedChatInvites?
|
||||||
if let signature = reader.readInt32() {
|
if let signature = reader.readInt32() {
|
||||||
|
@ -88,58 +88,6 @@ public func createPeerExportedInvitation(account: Account, peerId: PeerId, expir
|
|||||||
|> switchToLatest
|
|> switchToLatest
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct ExportedInvitations : Equatable {
|
|
||||||
public let list: [ExportedInvitation]?
|
|
||||||
public let totalCount: Int32
|
|
||||||
}
|
|
||||||
|
|
||||||
public func peerExportedInvitations(account: Account, peerId: PeerId, revoked: Bool, offsetLink: String? = nil) -> Signal<ExportedInvitations?, NoError> {
|
|
||||||
return account.postbox.transaction { transaction -> Signal<ExportedInvitations?, NoError> in
|
|
||||||
if let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) {
|
|
||||||
var flags: Int32 = 0
|
|
||||||
if let _ = offsetLink {
|
|
||||||
flags |= (1 << 2)
|
|
||||||
}
|
|
||||||
if revoked {
|
|
||||||
flags |= (1 << 3)
|
|
||||||
}
|
|
||||||
return account.network.request(Api.functions.messages.getExportedChatInvites(flags: flags, peer: inputPeer, adminId: nil, offsetLink: offsetLink, limit: 50))
|
|
||||||
|> map(Optional.init)
|
|
||||||
|> `catch` { _ -> Signal<Api.messages.ExportedChatInvites?, NoError> in
|
|
||||||
return .single(nil)
|
|
||||||
}
|
|
||||||
|> mapToSignal { result -> Signal<ExportedInvitations?, NoError> in
|
|
||||||
return account.postbox.transaction { transaction -> ExportedInvitations? in
|
|
||||||
if let result = result, case let .exportedChatInvites(count, apiInvites, users) = result {
|
|
||||||
var peers: [Peer] = []
|
|
||||||
var peersMap: [PeerId: Peer] = [:]
|
|
||||||
for user in users {
|
|
||||||
let telegramUser = TelegramUser(user: user)
|
|
||||||
peers.append(telegramUser)
|
|
||||||
peersMap[telegramUser.id] = telegramUser
|
|
||||||
}
|
|
||||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in
|
|
||||||
return updated
|
|
||||||
})
|
|
||||||
|
|
||||||
var invites: [ExportedInvitation] = []
|
|
||||||
for apiInvite in apiInvites {
|
|
||||||
if let invite = ExportedInvitation(apiExportedInvite: apiInvite) {
|
|
||||||
invites.append(invite)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ExportedInvitations(list: invites, totalCount: count)
|
|
||||||
} else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return .single(nil)
|
|
||||||
}
|
|
||||||
} |> switchToLatest
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum EditPeerExportedInvitationError {
|
public enum EditPeerExportedInvitationError {
|
||||||
case generic
|
case generic
|
||||||
}
|
}
|
||||||
@ -375,6 +323,7 @@ private final class PeerExportedInvitationsContextImpl {
|
|||||||
|> mapToSignal { inputPeer -> Signal<([ExportedInvitation], Int32), NoError> in
|
|> mapToSignal { inputPeer -> Signal<([ExportedInvitation], Int32), NoError> in
|
||||||
if let inputPeer = inputPeer {
|
if let inputPeer = inputPeer {
|
||||||
let offsetLink = lastResult?.link
|
let offsetLink = lastResult?.link
|
||||||
|
let offsetDate = lastResult?.date
|
||||||
var flags: Int32 = 0
|
var flags: Int32 = 0
|
||||||
if let _ = offsetLink {
|
if let _ = offsetLink {
|
||||||
flags |= (1 << 2)
|
flags |= (1 << 2)
|
||||||
@ -382,7 +331,7 @@ private final class PeerExportedInvitationsContextImpl {
|
|||||||
if revoked {
|
if revoked {
|
||||||
flags |= (1 << 3)
|
flags |= (1 << 3)
|
||||||
}
|
}
|
||||||
let signal = account.network.request(Api.functions.messages.getExportedChatInvites(flags: flags, peer: inputPeer, adminId: nil, offsetLink: offsetLink, limit: lastResult == nil ? 50 : 100))
|
let signal = account.network.request(Api.functions.messages.getExportedChatInvites(flags: flags, peer: inputPeer, adminId: nil, offsetDate: offsetDate, offsetLink: offsetLink, limit: lastResult == nil ? 50 : 100))
|
||||||
|> map(Optional.init)
|
|> map(Optional.init)
|
||||||
|> `catch` { _ -> Signal<Api.messages.ExportedChatInvites?, NoError> in
|
|> `catch` { _ -> Signal<Api.messages.ExportedChatInvites?, NoError> in
|
||||||
return .single(nil)
|
return .single(nil)
|
||||||
|
12
submodules/TelegramUI/Images.xcassets/Chat/Links/Share.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Chat/Links/Share.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "ic_sharelink.pdf",
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
BIN
submodules/TelegramUI/Images.xcassets/Chat/Links/Share.imageset/ic_sharelink.pdf
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Chat/Links/Share.imageset/ic_sharelink.pdf
vendored
Normal file
Binary file not shown.
@ -615,7 +615,7 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
|
|||||||
case .channel:
|
case .channel:
|
||||||
let status = context.account.viewTracker.peerView(peerId, updateData: false)
|
let status = context.account.viewTracker.peerView(peerId, updateData: false)
|
||||||
|> map { peerView -> PeerInfoStatusData? in
|
|> map { peerView -> PeerInfoStatusData? in
|
||||||
guard let channel = peerView.peers[peerId] as? TelegramChannel else {
|
guard let _ = peerView.peers[peerId] as? TelegramChannel else {
|
||||||
return PeerInfoStatusData(text: strings.Channel_Status, isActivity: false)
|
return PeerInfoStatusData(text: strings.Channel_Status, isActivity: false)
|
||||||
}
|
}
|
||||||
if let cachedChannelData = peerView.cachedData as? CachedChannelData, let memberCount = cachedChannelData.participantsSummary.memberCount, memberCount != 0 {
|
if let cachedChannelData = peerView.cachedData as? CachedChannelData, let memberCount = cachedChannelData.participantsSummary.memberCount, memberCount != 0 {
|
||||||
@ -654,11 +654,17 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
|
|||||||
discussionPeer = peer
|
discussionPeer = peer
|
||||||
}
|
}
|
||||||
|
|
||||||
if let channel = peerViewMainPeer(peerView) as? TelegramChannel, let cachedData = peerView.cachedData as? CachedChannelData, channel.flags.contains(.isCreator) || ((channel.adminRights != nil && channel.hasPermission(.pinMessages)) && cachedData.flags.contains(.canChangeUsername)), currentInvitationsContext == nil {
|
if currentInvitationsContext == nil {
|
||||||
|
var canManageInvitations = false
|
||||||
|
if let channel = peerViewMainPeer(peerView) as? TelegramChannel, let cachedData = peerView.cachedData as? CachedChannelData, channel.flags.contains(.isCreator) || ((channel.adminRights != nil && channel.hasPermission(.pinMessages)) && cachedData.flags.contains(.canChangeUsername)) {
|
||||||
|
canManageInvitations = true
|
||||||
|
}
|
||||||
|
if canManageInvitations {
|
||||||
let invitationsContext = PeerExportedInvitationsContext(account: context.account, peerId: peerId, revoked: false, forceUpdate: true)
|
let invitationsContext = PeerExportedInvitationsContext(account: context.account, peerId: peerId, revoked: false, forceUpdate: true)
|
||||||
invitationsContextPromise.set(.single(invitationsContext))
|
invitationsContextPromise.set(.single(invitationsContext))
|
||||||
invitationsStatePromise.set(invitationsContext.state |> map(Optional.init))
|
invitationsStatePromise.set(invitationsContext.state |> map(Optional.init))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return PeerInfoScreenData(
|
return PeerInfoScreenData(
|
||||||
peer: peerView.peers[peerId],
|
peer: peerView.peers[peerId],
|
||||||
@ -805,11 +811,19 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let group = peerViewMainPeer(peerView) as? TelegramGroup, case .creator = group.role, currentInvitationsContext == nil {
|
if currentInvitationsContext == nil {
|
||||||
|
var canManageInvitations = false
|
||||||
|
if let group = peerViewMainPeer(peerView) as? TelegramGroup, case .creator = group.role {
|
||||||
|
canManageInvitations = true
|
||||||
|
} else if let channel = peerViewMainPeer(peerView) as? TelegramChannel, let cachedData = peerView.cachedData as? CachedChannelData, channel.flags.contains(.isCreator) || ((channel.adminRights != nil && channel.hasPermission(.pinMessages)) && cachedData.flags.contains(.canChangeUsername)) {
|
||||||
|
canManageInvitations = true
|
||||||
|
}
|
||||||
|
if canManageInvitations {
|
||||||
let invitationsContext = PeerExportedInvitationsContext(account: context.account, peerId: peerId, revoked: false, forceUpdate: true)
|
let invitationsContext = PeerExportedInvitationsContext(account: context.account, peerId: peerId, revoked: false, forceUpdate: true)
|
||||||
invitationsContextPromise.set(.single(invitationsContext))
|
invitationsContextPromise.set(.single(invitationsContext))
|
||||||
invitationsStatePromise.set(invitationsContext.state |> map(Optional.init))
|
invitationsStatePromise.set(invitationsContext.state |> map(Optional.init))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return PeerInfoScreenData(
|
return PeerInfoScreenData(
|
||||||
peer: peerView.peers[groupId],
|
peer: peerView.peers[groupId],
|
||||||
|
@ -1185,6 +1185,17 @@ private func editingItems(data: PeerInfoScreenData?, context: AccountContext, pr
|
|||||||
discussionGroupTitle = "..."
|
discussionGroupTitle = "..."
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let invitesText: String
|
||||||
|
if let count = data.invitations?.count, count > 0 {
|
||||||
|
invitesText = "\(count)"
|
||||||
|
} else {
|
||||||
|
invitesText = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
items[.peerSettings]!.append(PeerInfoScreenDisclosureItem(id: ItemInviteLinks, label: .text(invitesText), text: presentationData.strings.GroupInfo_InviteLinks, action: {
|
||||||
|
interaction.editingOpenInviteLinksSetup()
|
||||||
|
}))
|
||||||
|
|
||||||
items[.peerSettings]!.append(PeerInfoScreenDisclosureItem(id: ItemDiscussionGroup, label: .text(discussionGroupTitle), text: presentationData.strings.Channel_DiscussionGroup, action: {
|
items[.peerSettings]!.append(PeerInfoScreenDisclosureItem(id: ItemDiscussionGroup, label: .text(discussionGroupTitle), text: presentationData.strings.Channel_DiscussionGroup, action: {
|
||||||
interaction.editingOpenDiscussionGroupSetup()
|
interaction.editingOpenDiscussionGroupSetup()
|
||||||
}))
|
}))
|
||||||
@ -4559,16 +4570,8 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
strongSelf.view.endEditing(true)
|
strongSelf.view.endEditing(true)
|
||||||
let mode: ChannelVisibilityControllerMode
|
|
||||||
if groupPeer.addressName != nil {
|
|
||||||
let visibilityController = channelVisibilityController(context: strongSelf.context, peerId: groupPeer.id, mode: .generic, upgradedToSupergroup: { _, f in f() }, onDismissRemoveController: contactsController)
|
|
||||||
//visibilityController.navigationPresentation = .modal
|
|
||||||
|
|
||||||
contactsController?.push(visibilityController)
|
|
||||||
} else {
|
|
||||||
contactsController?.present(InviteLinkInviteController(context: context, peerId: groupPeer.id, parentNavigationController: contactsController?.navigationController as? NavigationController), in: .window(.root))
|
contactsController?.present(InviteLinkInviteController(context: context, peerId: groupPeer.id, parentNavigationController: contactsController?.navigationController as? NavigationController), in: .window(.root))
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
strongSelf.controller?.push(contactsController)
|
strongSelf.controller?.push(contactsController)
|
||||||
let selectAddMemberDisposable = strongSelf.selectAddMemberDisposable
|
let selectAddMemberDisposable = strongSelf.selectAddMemberDisposable
|
||||||
|
Loading…
x
Reference in New Issue
Block a user