Permission management updates

This commit is contained in:
Peter 2019-01-03 19:52:46 +01:00
parent d81b5b8950
commit 71385c916f
34 changed files with 2248 additions and 2237 deletions

View File

@ -1013,7 +1013,6 @@
D0EC6E521EB9F58900EBF1C3 /* ChannelInfoController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0613FC71E5F8AB100202CDB /* ChannelInfoController.swift */; };
D0EC6E531EB9F58900EBF1C3 /* ChannelMembersController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0613FCC1E60482300202CDB /* ChannelMembersController.swift */; };
D0EC6E541EB9F58900EBF1C3 /* ConvertToSupergroupController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0613FD41E6064D200202CDB /* ConvertToSupergroupController.swift */; };
D0EC6E551EB9F58900EBF1C3 /* GroupAdminsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D033FEAA1E61BFC100644997 /* GroupAdminsController.swift */; };
D0EC6E561EB9F58900EBF1C3 /* UserInfoController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0528E621E65BECA00E2FEF5 /* UserInfoController.swift */; };
D0EC6E571EB9F58900EBF1C3 /* GroupsInCommonController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D099261E1E69791E00D95539 /* GroupsInCommonController.swift */; };
D0EC6E581EB9F58900EBF1C3 /* PeerSelectionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D07CFF731DCA207200761F81 /* PeerSelectionController.swift */; };
@ -1401,7 +1400,6 @@
D02F4AE81FCF370B004DFBAE /* ChatMessageInteractiveMediaBadge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatMessageInteractiveMediaBadge.swift; sourceTree = "<group>"; };
D02F4AEF1FD4C46D004DFBAE /* SystemVideoContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SystemVideoContent.swift; sourceTree = "<group>"; };
D03120F51DA534C1006A2A60 /* ItemListActionItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ItemListActionItem.swift; sourceTree = "<group>"; };
D033FEAA1E61BFC100644997 /* GroupAdminsController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GroupAdminsController.swift; sourceTree = "<group>"; };
D0380DA8204E9C81000414AB /* SecretMediaPreviewFooterContentNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecretMediaPreviewFooterContentNode.swift; sourceTree = "<group>"; };
D0380DAA204EA72F000414AB /* RadialStatusSecretTimeoutContentNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadialStatusSecretTimeoutContentNode.swift; sourceTree = "<group>"; };
D0380DAC204ED434000414AB /* LegacyLiveUploadInterface.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LegacyLiveUploadInterface.swift; sourceTree = "<group>"; };
@ -4104,7 +4102,6 @@
D0613FCC1E60482300202CDB /* ChannelMembersController.swift */,
D0613FD41E6064D200202CDB /* ConvertToSupergroupController.swift */,
D08984ED2114964700918162 /* GroupPreHistorySetupController.swift */,
D033FEAA1E61BFC100644997 /* GroupAdminsController.swift */,
D0528E621E65BECA00E2FEF5 /* UserInfoController.swift */,
D099261E1E69791E00D95539 /* GroupsInCommonController.swift */,
D0F67FEF1EE6B8A8000E5906 /* ChannelMembersSearchController.swift */,
@ -5891,7 +5888,6 @@
D093D7E72063E57F00BC3599 /* BotPaymentActionItemNode.swift in Sources */,
D01C06BA1FBBB076001561AB /* ItemListSelectableControlNode.swift in Sources */,
D0EC6E541EB9F58900EBF1C3 /* ConvertToSupergroupController.swift in Sources */,
D0EC6E551EB9F58900EBF1C3 /* GroupAdminsController.swift in Sources */,
D0EC6E561EB9F58900EBF1C3 /* UserInfoController.swift in Sources */,
D0EC6E571EB9F58900EBF1C3 /* GroupsInCommonController.swift in Sources */,
D0AB262F21C3D3DE008F6685 /* CreatePollController.swift in Sources */,

View File

@ -678,16 +678,6 @@ public func channelAdminController(account: Account, peerId: PeerId, adminId: Pe
}
if let updateFlags = updateFlags, updateFlags != defaultFlags {
let presentationData = account.telegramApplicationContext.currentPresentationData.with { $0 }
let controller = ActionSheetController(presentationTheme: presentationData.theme)
let dismissAction: () -> Void = { [weak controller] in
controller?.dismissAnimated()
}
controller.setItemGroups([
ActionSheetItemGroup(items: [
ActionSheetTextItem(title: presentationData.strings.Group_AdvanceUpgradeText),
ActionSheetButtonItem(title: presentationData.strings.Group_AdvanceUpgradeApply, color: .destructive, action: {
dismissAction()
let signal = convertGroupToSupergroup(account: account, peerId: peerId)
|> map(Optional.init)
|> `catch` { _ -> Signal<PeerId?, NoError> in
@ -719,11 +709,6 @@ public func channelAdminController(account: Account, peerId: PeerId, adminId: Pe
return current.withUpdatedUpdating(false)
}
}))
})
]),
ActionSheetItemGroup(items: [ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, action: { dismissAction() })])
])
presentControllerImpl?(controller, ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
} else {
dismissImpl?()
}

View File

@ -387,7 +387,7 @@ private func channelAdminsControllerEntries(presentationData: PresentationData,
}
} else if let peer = view.peers[view.peerId] as? TelegramGroup {
let isGroup = true
entries.append(.recentActions(presentationData.theme, presentationData.strings.Group_Info_AdminLog))
//entries.append(.recentActions(presentationData.theme, presentationData.strings.Group_Info_AdminLog))
if let participants = participants {
entries.append(.adminsHeader(presentationData.theme, presentationData.strings.ChannelMembers_GroupAdminsTitle))
@ -486,37 +486,6 @@ public func channelAdminsController(account: Account, peerId: PeerId, loadComple
var upgradedToSupergroupImpl: ((PeerId, @escaping () -> Void) -> Void)?
let presentUpgradeOption: () -> Void = {
let presentationData = account.telegramApplicationContext.currentPresentationData.with { $0 }
let controller = ActionSheetController(presentationTheme: presentationData.theme)
let dismissAction: () -> Void = { [weak controller] in
controller?.dismissAnimated()
}
controller.setItemGroups([
ActionSheetItemGroup(items: [
ActionSheetTextItem(title: presentationData.strings.Group_AdvanceUpgradeText),
ActionSheetButtonItem(title: presentationData.strings.Group_AdvanceUpgradeApply, color: .destructive, action: {
dismissAction()
let presentationData = account.telegramApplicationContext.currentPresentationData.with { $0 }
let progress = OverlayStatusController(theme: presentationData.theme, strings: presentationData.strings, type: .loading(cancelled: nil))
presentControllerImpl?(progress, nil)
upgradeDisposable.set((convertGroupToSupergroup(account: account, peerId: peerId)
|> afterDisposed { [weak progress] in
Queue.mainQueue().async {
progress?.dismiss()
}
}
|> deliverOnMainQueue).start(next: { upgradedPeerId in
upgradedToSupergroupImpl?(upgradedPeerId, {})
}))
})
]),
ActionSheetItemGroup(items: [ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, action: { dismissAction() })])
])
presentControllerImpl?(controller, ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
}
let upgradedToSupergroup: (PeerId, @escaping () -> Void) -> Void = { upgradedPeerId, f in
upgradedToSupergroupImpl?(upgradedPeerId, f)
}
@ -525,7 +494,6 @@ public func channelAdminsController(account: Account, peerId: PeerId, loadComple
let _ = (account.postbox.loadedPeerWithId(peerId)
|> deliverOnMainQueue).start(next: { peer in
if peer is TelegramGroup {
presentUpgradeOption()
} else {
pushControllerImpl?(ChatRecentActionsController(account: account, peer: peer))
}

View File

@ -264,7 +264,51 @@ private func completeRights(_ flags: TelegramChatBannedRightsFlags) -> TelegramC
private func channelBannedMemberControllerEntries(presentationData: PresentationData, state: ChannelBannedMemberControllerState, accountPeerId: PeerId, channelView: PeerView, memberView: PeerView, initialParticipant: ChannelParticipant?, initialBannedBy: Peer?) -> [ChannelBannedMemberEntry] {
var entries: [ChannelBannedMemberEntry] = []
if let _ = channelView.peers[channelView.peerId] as? TelegramChannel, let cachedData = channelView.cachedData as? CachedChannelData, let defaultBannedRights = cachedData.defaultBannedRights, let member = memberView.peers[memberView.peerId] {
if let channel = channelView.peers[channelView.peerId] as? TelegramChannel, let _ = channelView.cachedData as? CachedChannelData, let defaultBannedRights = channel.defaultBannedRights, let member = memberView.peers[memberView.peerId] {
entries.append(.info(presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, member, memberView.peerPresences[member.id] as? TelegramUserPresence))
let currentRightsFlags: TelegramChatBannedRightsFlags
if let updatedFlags = state.updatedFlags {
currentRightsFlags = updatedFlags
} else if let initialParticipant = initialParticipant, case let .member(_, _, _, maybeBanInfo) = initialParticipant, let banInfo = maybeBanInfo {
currentRightsFlags = banInfo.rights.flags
} else {
currentRightsFlags = defaultBannedRights.flags
}
let currentTimeout: Int32
if let updatedTimeout = state.updatedTimeout {
currentTimeout = updatedTimeout
} else if let initialParticipant = initialParticipant, case let .member(_, _, _, maybeBanInfo) = initialParticipant, let banInfo = maybeBanInfo {
currentTimeout = banInfo.rights.untilDate
} else {
currentTimeout = Int32.max
}
let currentTimeoutString: String
if currentTimeout == 0 || currentTimeout == Int32.max {
currentTimeoutString = presentationData.strings.MessageTimer_Forever
} else {
let remainingTimeout = currentTimeout - state.referenceTimestamp
currentTimeoutString = timeIntervalString(strings: presentationData.strings, value: remainingTimeout)
}
entries.append(.rightsHeader(presentationData.theme, presentationData.strings.GroupPermission_SectionTitle))
var index = 0
for right in allGroupPermissionList {
let defaultEnabled = !defaultBannedRights.flags.contains(right)
entries.append(.rightItem(presentationData.theme, index, stringForGroupPermission(strings: presentationData.strings, right: right), right, defaultEnabled && !currentRightsFlags.contains(right), defaultEnabled && !state.updating))
index += 1
}
entries.append(.timeout(presentationData.theme, presentationData.strings.GroupPermission_Duration, currentTimeoutString))
if let initialParticipant = initialParticipant, case let .member(member) = initialParticipant, let banInfo = member.banInfo, let initialBannedBy = initialBannedBy {
entries.append(.exceptionInfo(presentationData.theme, presentationData.strings.GroupPermission_AddedInfo(initialBannedBy.displayTitle, stringForRelativeSymbolicTimestamp(strings: presentationData.strings, relativeTimestamp: banInfo.timestamp, relativeTo: state.referenceTimestamp, dateTimeFormat: presentationData.dateTimeFormat)).0))
entries.append(.delete(presentationData.theme, presentationData.strings.GroupPermission_Delete))
}
} else if let group = channelView.peers[channelView.peerId] as? TelegramGroup, let defaultBannedRights = group.defaultBannedRights, let member = memberView.peers[memberView.peerId] {
entries.append(.info(presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, member, memberView.peerPresences[member.id] as? TelegramUserPresence))
let currentRightsFlags: TelegramChatBannedRightsFlags
@ -313,7 +357,7 @@ private func channelBannedMemberControllerEntries(presentationData: Presentation
return entries
}
public func channelBannedMemberController(account: Account, peerId: PeerId, memberId: PeerId, initialParticipant: ChannelParticipant?, updated: @escaping (TelegramChatBannedRights?) -> Void) -> ViewController {
public func channelBannedMemberController(account: Account, peerId: PeerId, memberId: PeerId, initialParticipant: ChannelParticipant?, updated: @escaping (TelegramChatBannedRights?) -> Void, upgradedToSupergroup: @escaping (PeerId, @escaping () -> Void) -> Void) -> ViewController {
let initialState = ChannelBannedMemberControllerState(referenceTimestamp: Int32(Date().timeIntervalSince1970), updatedFlags: nil, updatedTimeout: nil, updating: false)
let statePromise = ValuePromise(initialState, ignoreRepeated: true)
let stateValue = Atomic(value: initialState)
@ -336,7 +380,19 @@ public func channelBannedMemberController(account: Account, peerId: PeerId, memb
let _ = (peerView.get()
|> take(1)
|> deliverOnMainQueue).start(next: { view in
if let cachedData = view.cachedData as? CachedChannelData {
var defaultBannedRightsFlagsValue: TelegramChatBannedRightsFlags?
guard let peer = view.peers[peerId] else {
return
}
if let channel = peer as? TelegramChannel, let initialRightFlags = channel.defaultBannedRights?.flags {
defaultBannedRightsFlagsValue = initialRightFlags
} else if let group = peer as? TelegramGroup, let initialRightFlags = group.defaultBannedRights?.flags {
defaultBannedRightsFlagsValue = initialRightFlags
}
guard let defaultBannedRightsFlags = defaultBannedRightsFlagsValue else {
return
}
updateState { state in
var state = state
var effectiveRightsFlags: TelegramChatBannedRightsFlags
@ -344,10 +400,8 @@ public func channelBannedMemberController(account: Account, peerId: PeerId, memb
effectiveRightsFlags = updatedFlags
} else if let initialParticipant = initialParticipant, case let .member(member) = initialParticipant, let banInfo = member.banInfo {
effectiveRightsFlags = banInfo.rights.flags
} else if let defaultBannedRightsFlags = cachedData.defaultBannedRights?.flags {
effectiveRightsFlags = defaultBannedRightsFlags
} else {
effectiveRightsFlags = TelegramChatBannedRightsFlags()
effectiveRightsFlags = defaultBannedRightsFlags
}
if value {
effectiveRightsFlags.remove(rights)
@ -363,7 +417,6 @@ public func channelBannedMemberController(account: Account, peerId: PeerId, memb
state.updatedFlags = effectiveRightsFlags
return state
}
}
})
}, openTimeout: {
let presentationData = account.telegramApplicationContext.currentPresentationData.with { $0 }
@ -461,9 +514,20 @@ public func channelBannedMemberController(account: Account, peerId: PeerId, memb
let _ = (peerView.get()
|> take(1)
|> deliverOnMainQueue).start(next: { view in
guard let channel = view.peers[peerId] as? TelegramChannel, let cachedData = view.cachedData as? CachedChannelData, let initialRightFlags = cachedData.defaultBannedRights?.flags else {
var defaultBannedRightsFlagsValue: TelegramChatBannedRightsFlags?
guard let peer = view.peers[peerId] else {
return
}
if let channel = peer as? TelegramChannel, let initialRightFlags = channel.defaultBannedRights?.flags {
defaultBannedRightsFlagsValue = initialRightFlags
} else if let group = peer as? TelegramGroup, let initialRightFlags = group.defaultBannedRights?.flags {
defaultBannedRightsFlagsValue = initialRightFlags
}
guard let defaultBannedRightsFlags = defaultBannedRightsFlagsValue else {
return
}
var resolvedRights: TelegramChatBannedRights?
if let initialParticipant = initialParticipant {
var updateFlags: TelegramChatBannedRightsFlags?
@ -477,7 +541,7 @@ public func channelBannedMemberController(account: Account, peerId: PeerId, memb
if updateFlags == nil && updateTimeout == nil {
if case let .member(_, _, _, maybeBanInfo) = initialParticipant {
if maybeBanInfo == nil {
updateFlags = initialRightFlags
updateFlags = defaultBannedRightsFlags
updateTimeout = Int32.max
}
}
@ -490,7 +554,7 @@ public func channelBannedMemberController(account: Account, peerId: PeerId, memb
} else if case let .member(_, _, _, maybeBanInfo) = initialParticipant, let banInfo = maybeBanInfo {
currentRightsFlags = banInfo.rights.flags
} else {
currentRightsFlags = initialRightFlags
currentRightsFlags = defaultBannedRightsFlags
}
let currentTimeout: Int32
@ -502,7 +566,7 @@ public func channelBannedMemberController(account: Account, peerId: PeerId, memb
currentTimeout = Int32.max
}
resolvedRights = TelegramChatBannedRights(flags: completeRights(currentRightsFlags), personal: false, untilDate: currentTimeout)
resolvedRights = TelegramChatBannedRights(flags: completeRights(currentRightsFlags), untilDate: currentTimeout)
}
} else if canEdit, let _ = channelView.peers[channelView.peerId] as? TelegramChannel {
var updateFlags: TelegramChatBannedRightsFlags?
@ -516,14 +580,14 @@ public func channelBannedMemberController(account: Account, peerId: PeerId, memb
}
if updateFlags == nil {
updateFlags = initialRightFlags
updateFlags = defaultBannedRightsFlags
}
if updateTimeout == nil {
updateTimeout = Int32.max
}
if let updateFlags = updateFlags, let updateTimeout = updateTimeout {
resolvedRights = TelegramChatBannedRights(flags: completeRights(updateFlags), personal: false, untilDate: updateTimeout)
resolvedRights = TelegramChatBannedRights(flags: completeRights(updateFlags), untilDate: updateTimeout)
}
}
@ -533,8 +597,8 @@ public func channelBannedMemberController(account: Account, peerId: PeerId, memb
}
if let resolvedRights = resolvedRights, previousRights != resolvedRights {
let cleanResolvedRightsFlags = resolvedRights.flags.union(initialRightFlags)
let cleanResolvedRights = TelegramChatBannedRights(flags: cleanResolvedRightsFlags, personal: false, untilDate: resolvedRights.untilDate)
let cleanResolvedRightsFlags = resolvedRights.flags.union(defaultBannedRightsFlags)
let cleanResolvedRights = TelegramChatBannedRights(flags: cleanResolvedRightsFlags, untilDate: resolvedRights.untilDate)
if cleanResolvedRights.flags.isEmpty && previousRights == nil {
dismissImpl?()
@ -545,6 +609,44 @@ public func channelBannedMemberController(account: Account, peerId: PeerId, memb
state.updating = true
return state
}
if peerId.namespace == Namespaces.Peer.CloudGroup {
let signal = convertGroupToSupergroup(account: account, peerId: peerId)
|> map(Optional.init)
|> `catch` { _ -> Signal<PeerId?, NoError> in
return .single(nil)
}
|> mapToSignal { upgradedPeerId -> Signal<PeerId?, NoError> in
guard let upgradedPeerId = upgradedPeerId else {
return .single(nil)
}
return account.telegramApplicationContext.peerChannelMemberCategoriesContextsManager.updateMemberBannedRights(account: account, peerId: upgradedPeerId, memberId: memberId, bannedRights: cleanResolvedRights)
|> mapToSignal { _ -> Signal<PeerId?, NoError> in
return .complete()
}
|> then(.single(upgradedPeerId))
}
|> deliverOnMainQueue
updateState { current in
var current = current
current.updating = true
return current
}
updateRightsDisposable.set(signal.start(next: { upgradedPeerId in
if let upgradedPeerId = upgradedPeerId {
upgradedToSupergroup(upgradedPeerId, {
dismissImpl?()
})
}
}, error: { _ in
updateState { current in
var current = current
current.updating = false
return current
}
}))
} else {
updateRightsDisposable.set((account.telegramApplicationContext.peerChannelMemberCategoriesContextsManager.updateMemberBannedRights(account: account, peerId: peerId, memberId: memberId, bannedRights: cleanResolvedRights)
|> deliverOnMainQueue).start(error: { _ in
@ -557,13 +659,12 @@ public func channelBannedMemberController(account: Account, peerId: PeerId, memb
dismissImpl?()
}))
}
if false && previousRights == nil {
applyRights()
} else {
}
let presentationData = account.telegramApplicationContext.currentPresentationData.with { $0 }
let actionSheet = ActionSheetController(presentationTheme: presentationData.theme)
var items: [ActionSheetItem] = []
items.append(ActionSheetTextItem(title: presentationData.strings.GroupPermission_ApplyAlertText(channel.displayTitle).0))
items.append(ActionSheetTextItem(title: presentationData.strings.GroupPermission_ApplyAlertText(peer.displayTitle).0))
items.append(ActionSheetButtonItem(title: presentationData.strings.GroupPermission_ApplyAlertAction, color: .accent, font: .default, enabled: true, action: { [weak actionSheet] in
actionSheet?.dismissAnimated()
applyRights()
@ -575,7 +676,6 @@ public func channelBannedMemberController(account: Account, peerId: PeerId, memb
])])
presentControllerImpl?(actionSheet, nil)
}
}
} else {
dismissImpl?()
}

View File

@ -310,7 +310,7 @@ public func channelBlacklistController(account: Account, peerId: PeerId) -> View
let presentationData = account.telegramApplicationContext.currentPresentationData.with { $0 }
let progress = OverlayStatusController(theme: presentationData.theme, strings: presentationData.strings, type: .loading(cancelled: nil))
presentControllerImpl?(progress, nil)
removePeerDisposable.set((account.telegramApplicationContext.peerChannelMemberCategoriesContextsManager.updateMemberBannedRights(account: account, peerId: peerId, memberId: peer.id, bannedRights: TelegramChatBannedRights(flags: [.banReadMessages], personal: false, untilDate: Int32.max))
removePeerDisposable.set((account.telegramApplicationContext.peerChannelMemberCategoriesContextsManager.updateMemberBannedRights(account: account, peerId: peerId, memberId: peer.id, bannedRights: TelegramChatBannedRights(flags: [.banReadMessages], untilDate: Int32.max))
|> deliverOnMainQueue).start(error: { [weak progress] _ in
progress?.dismiss()
dismissController?()

View File

@ -686,7 +686,7 @@ public func channelInfoController(account: Account, peerId: PeerId) -> ViewContr
return state
}
}, openChannelTypeSetup: {
presentControllerImpl?(channelVisibilityController(account: account, peerId: peerId, mode: .generic), ViewControllerPresentationArguments(presentationAnimation: ViewControllerPresentationAnimation.modalSheet))
presentControllerImpl?(channelVisibilityController(account: account, peerId: peerId, mode: .generic, upgradedToSupergroup: { _, f in f() }), ViewControllerPresentationArguments(presentationAnimation: ViewControllerPresentationAnimation.modalSheet))
}, changeNotificationMuteSettings: {
let presentationData = account.telegramApplicationContext.currentPresentationData.with { $0 }
let _ = (account.postbox.transaction { transaction -> (TelegramPeerNotificationSettings, GlobalNotificationSettings) in

View File

@ -387,7 +387,7 @@ public func channelMembersController(account: Account, peerId: PeerId) -> ViewCo
return $0.withUpdatedRemovingPeerId(memberId)
}
removePeerDisposable.set((account.telegramApplicationContext.peerChannelMemberCategoriesContextsManager.updateMemberBannedRights(account: account, peerId: peerId, memberId: memberId, bannedRights: TelegramChatBannedRights(flags: [.banReadMessages], personal: false, untilDate: Int32.max))
removePeerDisposable.set((account.telegramApplicationContext.peerChannelMemberCategoriesContextsManager.updateMemberBannedRights(account: account, peerId: peerId, memberId: memberId, bannedRights: TelegramChatBannedRights(flags: [.banReadMessages], untilDate: Int32.max))
|> deliverOnMainQueue).start(completed: {
updateState {
return $0.withUpdatedRemovingPeerId(nil)
@ -398,7 +398,7 @@ public func channelMembersController(account: Account, peerId: PeerId) -> ViewCo
pushControllerImpl?(controller)
}
}, inviteViaLink: {
presentControllerImpl?(channelVisibilityController(account: account, peerId: peerId, mode: .privateLink), ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
presentControllerImpl?(channelVisibilityController(account: account, peerId: peerId, mode: .privateLink, upgradedToSupergroup: { _, f in f() }), ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
})
let peerView = account.viewTracker.peerView(peerId)

View File

@ -242,7 +242,7 @@ final class ChannelMembersSearchContainerNode: SearchDisplayControllerContentNod
}, upgradedToSupergroup: { _, f in f() }), ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
}, restrictPeer: { participant in
present(channelBannedMemberController(account: account, peerId: peerId, memberId: participant.peer.id, initialParticipant: participant.participant, updated: { _ in
}), ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
}, upgradedToSupergroup: { _, f in f() }), ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
}, removePeer: { memberId in
let signal = account.postbox.loadedPeerWithId(memberId)
|> deliverOnMainQueue
@ -260,7 +260,7 @@ final class ChannelMembersSearchContainerNode: SearchDisplayControllerContentNod
}
if peerId.namespace == Namespaces.Peer.CloudChannel {
return account.telegramApplicationContext.peerChannelMemberCategoriesContextsManager.updateMemberBannedRights(account: account, peerId: peerId, memberId: memberId, bannedRights: TelegramChatBannedRights(flags: [.banReadMessages], personal: false, untilDate: Int32.max))
return account.telegramApplicationContext.peerChannelMemberCategoriesContextsManager.updateMemberBannedRights(account: account, peerId: peerId, memberId: memberId, bannedRights: TelegramChatBannedRights(flags: [.banReadMessages], untilDate: Int32.max))
|> afterDisposed {
Queue.mainQueue().async {
updateState { state in

View File

@ -325,7 +325,7 @@ private func completeRights(_ flags: TelegramChatBannedRightsFlags) -> TelegramC
private func channelPermissionsControllerEntries(presentationData: PresentationData, view: PeerView, state: ChannelPermissionsControllerState, participants: [RenderedChannelParticipant]?) -> [ChannelPermissionsEntry] {
var entries: [ChannelPermissionsEntry] = []
if let _ = view.peers[view.peerId] as? TelegramChannel, let participants = participants, let cachedData = view.cachedData as? CachedChannelData, let defaultBannedRights = cachedData.defaultBannedRights {
if let channel = view.peers[view.peerId] as? TelegramChannel, let participants = participants, let cachedData = view.cachedData as? CachedChannelData, let defaultBannedRights = channel.defaultBannedRights {
let effectiveRightsFlags: TelegramChatBannedRightsFlags
if let modifiedRightsFlags = state.modifiedRightsFlags {
effectiveRightsFlags = modifiedRightsFlags
@ -349,7 +349,7 @@ private func channelPermissionsControllerEntries(presentationData: PresentationD
entries.append(.peerItem(presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, presentationData.nameDisplayOrder, index, participant, ItemListPeerItemEditing(editable: true, editing: false, revealed: participant.peer.id == state.peerIdWithRevealedOptions), state.removingPeerId != participant.peer.id, true, effectiveRightsFlags))
index += 1
}
} else if let _ = view.peers[view.peerId] as? TelegramGroup, let cachedData = view.cachedData as? CachedGroupData, let defaultBannedRights = cachedData.defaultBannedRights {
} else if let group = view.peers[view.peerId] as? TelegramGroup, let cachedData = view.cachedData as? CachedGroupData, let defaultBannedRights = group.defaultBannedRights {
let effectiveRightsFlags: TelegramChatBannedRightsFlags
if let modifiedRightsFlags = state.modifiedRightsFlags {
effectiveRightsFlags = modifiedRightsFlags
@ -363,12 +363,15 @@ private func channelPermissionsControllerEntries(presentationData: PresentationD
entries.append(.permission(presentationData.theme, rightIndex, stringForGroupPermission(strings: presentationData.strings, right: rights), !effectiveRightsFlags.contains(rights), rights))
rightIndex += 1
}
entries.append(.exceptionsHeader(presentationData.theme, presentationData.strings.GroupInfo_Permissions_Exceptions))
entries.append(.add(presentationData.theme, presentationData.strings.GroupInfo_Permissions_AddException))
}
return entries
}
public func channelPermissionsController(account: Account, peerId: PeerId) -> ViewController {
public func channelPermissionsController(account: Account, peerId: PeerId, loadCompleted: @escaping () -> Void = {}) -> ViewController {
let statePromise = ValuePromise(ChannelPermissionsControllerState(), ignoreRepeated: true)
let stateValue = Atomic(value: ChannelPermissionsControllerState())
let updateState: ((ChannelPermissionsControllerState) -> ChannelPermissionsControllerState) -> Void = { f in
@ -389,11 +392,21 @@ public func channelPermissionsController(account: Account, peerId: PeerId) -> Vi
let peersPromise = Promise<[RenderedChannelParticipant]?>(nil)
let disposableAndLoadMoreControl: (Disposable, PeerChannelMemberCategoryControl?)
if peerId.namespace == Namespaces.Peer.CloudGroup {
loadCompleted()
disposableAndLoadMoreControl = (EmptyDisposable, nil)
peersPromise.set(.single(nil))
} else {
var loadCompletedCalled = false
disposableAndLoadMoreControl = account.telegramApplicationContext.peerChannelMemberCategoriesContextsManager.restricted(postbox: account.postbox, network: account.network, accountPeerId: account.peerId, peerId: peerId, updated: { state in
if case .loading(true) = state.loadingState {
peersPromise.set(.single(nil))
} else {
if !loadCompletedCalled {
loadCompletedCalled = true
loadCompleted()
}
peersPromise.set(.single(state.list))
}
})
}
actionsDisposable.add(disposableAndLoadMoreControl.0)
@ -404,17 +417,23 @@ public func channelPermissionsController(account: Account, peerId: PeerId) -> Vi
let peerView = Promise<PeerView>()
peerView.set(account.viewTracker.peerView(peerId))
var upgradedToSupergroupImpl: ((PeerId, @escaping () -> Void) -> Void)?
let upgradedToSupergroup: (PeerId, @escaping () -> Void) -> Void = { upgradedPeerId, f in
upgradedToSupergroupImpl?(upgradedPeerId, f)
}
let arguments = ChannelPermissionsControllerArguments(account: account, updatePermission: { rights, value in
let _ = (peerView.get()
|> take(1)
|> deliverOnMainQueue).start(next: { view in
if let cachedData = view.cachedData as? CachedChannelData {
if let channel = view.peers[peerId] as? TelegramChannel, let cachedData = view.cachedData as? CachedChannelData {
updateState { state in
var state = state
var effectiveRightsFlags: TelegramChatBannedRightsFlags
if let modifiedRightsFlags = state.modifiedRightsFlags {
effectiveRightsFlags = modifiedRightsFlags
} else if let defaultBannedRightsFlags = cachedData.defaultBannedRights?.flags {
} else if let defaultBannedRightsFlags = channel.defaultBannedRights?.flags {
effectiveRightsFlags = defaultBannedRightsFlags
} else {
effectiveRightsFlags = TelegramChatBannedRightsFlags()
@ -435,16 +454,16 @@ public func channelPermissionsController(account: Account, peerId: PeerId) -> Vi
}
let state = stateValue.with { $0 }
if let modifiedRightsFlags = state.modifiedRightsFlags {
updateDefaultRightsDisposable.set((updateDefaultChannelMemberBannedRights(account: account, peerId: peerId, rights: TelegramChatBannedRights(flags: completeRights(modifiedRightsFlags), personal: false, untilDate: Int32.max))
updateDefaultRightsDisposable.set((updateDefaultChannelMemberBannedRights(account: account, peerId: peerId, rights: TelegramChatBannedRights(flags: completeRights(modifiedRightsFlags), untilDate: Int32.max))
|> deliverOnMainQueue).start())
}
} else if let cachedData = view.cachedData as? CachedGroupData {
} else if let group = view.peers[peerId] as? TelegramGroup, let cachedData = view.cachedData as? CachedGroupData {
updateState { state in
var state = state
var effectiveRightsFlags: TelegramChatBannedRightsFlags
if let modifiedRightsFlags = state.modifiedRightsFlags {
effectiveRightsFlags = modifiedRightsFlags
} else if let defaultBannedRightsFlags = cachedData.defaultBannedRights?.flags {
} else if let defaultBannedRightsFlags = group.defaultBannedRights?.flags {
effectiveRightsFlags = defaultBannedRightsFlags
} else {
effectiveRightsFlags = TelegramChatBannedRightsFlags()
@ -465,7 +484,7 @@ public func channelPermissionsController(account: Account, peerId: PeerId) -> Vi
}
let state = stateValue.with { $0 }
if let modifiedRightsFlags = state.modifiedRightsFlags {
updateDefaultRightsDisposable.set((updateDefaultChannelMemberBannedRights(account: account, peerId: peerId, rights: TelegramChatBannedRights(flags: completeRights(modifiedRightsFlags), personal: false, untilDate: Int32.max))
updateDefaultRightsDisposable.set((updateDefaultChannelMemberBannedRights(account: account, peerId: peerId, rights: TelegramChatBannedRights(flags: completeRights(modifiedRightsFlags), untilDate: Int32.max))
|> deliverOnMainQueue).start())
}
}
@ -496,10 +515,9 @@ public func channelPermissionsController(account: Account, peerId: PeerId) -> Vi
let _ = (account.postbox.loadedPeerWithId(peerId)
|> deliverOnMainQueue).start(next: { channel in
dismissController?()
guard let _ = channel as? TelegramChannel else {
return
}
presentControllerImpl?(channelBannedMemberController(account: account, peerId: peerId, memberId: peer.id, initialParticipant: participant?.participant, updated: { _ in
}, upgradedToSupergroup: { upgradedPeerId, f in
upgradedToSupergroupImpl?(upgradedPeerId, f)
}), ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
})
})
@ -530,6 +548,8 @@ public func channelPermissionsController(account: Account, peerId: PeerId) -> Vi
}))
}, openPeer: { participant in
presentControllerImpl?(channelBannedMemberController(account: account, peerId: peerId, memberId: participant.peerId, initialParticipant: participant, updated: { _ in
}, upgradedToSupergroup: { upgradedPeerId, f in
upgradedToSupergroupImpl?(upgradedPeerId, f)
}), ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
}, openPeerInfo: { peer in
if let controller = peerInfoController(account: account, peer: peer) {
@ -578,6 +598,8 @@ public func channelPermissionsController(account: Account, peerId: PeerId) -> Vi
return state
}
presentControllerImpl?(channelBannedMemberController(account: account, peerId: peerId, memberId: participant.peerId, initialParticipant: participant, updated: { _ in
}, upgradedToSupergroup: { upgradedPeerId, f in
upgradedToSupergroupImpl?(upgradedPeerId, f)
}), ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
}
}, present: { c, a in
@ -607,6 +629,16 @@ public func channelPermissionsController(account: Account, peerId: PeerId) -> Vi
(controller.navigationController as? NavigationController)?.pushViewController(c)
}
}
upgradedToSupergroupImpl = { [weak controller] upgradedPeerId, f in
guard let controller = controller, let navigationController = controller.navigationController as? NavigationController else {
return
}
navigateToChatController(navigationController: navigationController, account: account, chatLocation: .peer(upgradedPeerId), keepStack: .never, animated: false, completion: {
navigationController.pushViewController(channelPermissionsController(account: account, peerId: upgradedPeerId, loadCompleted: {
f()
}), animated: false)
})
}
if peerId.namespace == Namespaces.Peer.CloudChannel {
controller.visibleBottomContentOffsetChanged = { offset in
if case let .known(value) = offset, value < 40.0 {

View File

@ -571,6 +571,8 @@ private func channelVisibilityControllerEntries(presentationData: PresentationDa
}
}
} else if let _ = view.peers[view.peerId] as? TelegramGroup {
switch mode {
case .privateLink:
let link = (view.cachedData as? CachedGroupData)?.exportedInvitation?.link
let text: String
if let link = link {
@ -588,6 +590,109 @@ private func channelVisibilityControllerEntries(presentationData: PresentationDa
entries.append(.privateLinkRevoke(presentationData.theme, presentationData.strings.GroupInfo_InviteLink_RevokeLink))
entries.append(.privateLinkShare(presentationData.theme, presentationData.strings.GroupInfo_InviteLink_ShareLink))
}
case .generic, .initialSetup:
let isGroup = true
let selectedType: CurrentChannelType
if let current = state.selectedType {
selectedType = current
} else {
selectedType = .privateChannel
}
let currentAddressName: String
if let current = state.editingPublicLinkText {
currentAddressName = current
} else {
currentAddressName = ""
}
entries.append(.typeHeader(presentationData.theme, presentationData.strings.Group_Setup_TypeHeader))
entries.append(.typePublic(presentationData.theme, presentationData.strings.Channel_Setup_TypePublic, selectedType == .publicChannel))
entries.append(.typePrivate(presentationData.theme, presentationData.strings.Channel_Setup_TypePrivate, selectedType == .privateChannel))
entries.append(.typeInfo(presentationData.theme, presentationData.strings.Group_Setup_TypePublicHelp))
switch selectedType {
case .publicChannel:
let displayAvailability = publicChannelsToRevoke == nil || !(publicChannelsToRevoke!.isEmpty)
if displayAvailability {
if let publicChannelsToRevoke = publicChannelsToRevoke {
entries.append(.publicLinkAvailability(presentationData.theme, presentationData.strings.Group_Username_RemoveExistingUsernamesInfo, false))
var index: Int32 = 0
for peer in publicChannelsToRevoke.sorted(by: { lhs, rhs in
var lhsDate: Int32 = 0
var rhsDate: Int32 = 0
if let lhs = lhs as? TelegramChannel {
lhsDate = lhs.creationDate
}
if let rhs = rhs as? TelegramChannel {
rhsDate = rhs.creationDate
}
return lhsDate > rhsDate
}) {
entries.append(.existingLinkPeerItem(index, presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, presentationData.nameDisplayOrder, peer, ItemListPeerItemEditing(editable: true, editing: true, revealed: state.revealedRevokePeerId == peer.id), state.revokingPeerId == nil))
index += 1
}
} else {
entries.append(.publicLinkAvailability(presentationData.theme, presentationData.strings.Group_Username_CreatePublicLinkHelp, true))
}
} else {
entries.append(.editablePublicLink(presentationData.theme, currentAddressName))
if let status = state.addressNameValidationStatus {
let text: String
switch status {
case let .invalidFormat(error):
switch error {
case .startsWithDigit:
text = presentationData.strings.Group_Username_InvalidStartsWithNumber
case .startsWithUnderscore:
text = presentationData.strings.Channel_Username_InvalidCharacters
case .endsWithUnderscore:
text = presentationData.strings.Channel_Username_InvalidCharacters
case .tooShort:
text = presentationData.strings.Group_Username_InvalidTooShort
case .invalidCharacters:
text = presentationData.strings.Channel_Username_InvalidCharacters
}
case let .availability(availability):
switch availability {
case .available:
text = presentationData.strings.Channel_Username_UsernameIsAvailable(currentAddressName).0
case .invalid:
text = presentationData.strings.Channel_Username_InvalidCharacters
case .taken:
text = presentationData.strings.Channel_Username_InvalidTaken
}
case .checking:
text = presentationData.strings.Channel_Username_CheckingUsername
}
entries.append(.publicLinkStatus(presentationData.theme, text, status))
}
entries.append(.publicLinkInfo(presentationData.theme, presentationData.strings.Group_Username_CreatePublicLinkHelp))
}
case .privateChannel:
let link = (view.cachedData as? CachedGroupData)?.exportedInvitation?.link
let text: String
if let link = link {
text = link
} else {
text = presentationData.strings.Channel_NotificationLoading
}
entries.append(.privateLink(presentationData.theme, text, link))
entries.append(.privateLinkInfo(presentationData.theme, presentationData.strings.Group_Username_CreatePrivateLinkHelp))
switch mode {
case .initialSetup:
break
case .generic, .privateLink:
entries.append(.privateLinkCopy(presentationData.theme, presentationData.strings.GroupInfo_InviteLink_CopyLink))
entries.append(.privateLinkRevoke(presentationData.theme, presentationData.strings.GroupInfo_InviteLink_RevokeLink))
entries.append(.privateLinkShare(presentationData.theme, presentationData.strings.GroupInfo_InviteLink_ShareLink))
}
}
}
}
return entries
@ -606,7 +711,8 @@ private func effectiveChannelType(state: ChannelVisibilityControllerState, peer:
return selectedType
}
private func updatedAddressName(state: ChannelVisibilityControllerState, peer: TelegramChannel) -> String? {
private func updatedAddressName(state: ChannelVisibilityControllerState, peer: Peer) -> String? {
if let peer = peer as? TelegramChannel {
let selectedType = effectiveChannelType(state: state, peer: peer)
let currentAddressName: String
@ -637,6 +743,16 @@ private func updatedAddressName(state: ChannelVisibilityControllerState, peer: T
} else {
return nil
}
} else if let _ = peer as? TelegramGroup {
let currentAddressName = state.editingPublicLinkText ?? ""
if !currentAddressName.isEmpty {
return currentAddressName
} else {
return nil
}
} else {
return nil
}
}
public enum ChannelVisibilityControllerMode {
@ -645,7 +761,7 @@ public enum ChannelVisibilityControllerMode {
case privateLink
}
public func channelVisibilityController(account: Account, peerId: PeerId, mode: ChannelVisibilityControllerMode) -> ViewController {
public func channelVisibilityController(account: Account, peerId: PeerId, mode: ChannelVisibilityControllerMode, upgradedToSupergroup: @escaping (PeerId, @escaping () -> Void) -> Void) -> ViewController {
let statePromise = ValuePromise(ChannelVisibilityControllerState(), ignoreRepeated: true)
let stateValue = Atomic(value: ChannelVisibilityControllerState())
let updateState: ((ChannelVisibilityControllerState) -> ChannelVisibilityControllerState) -> Void = { f in
@ -684,7 +800,7 @@ public func channelVisibilityController(account: Account, peerId: PeerId, mode:
actionsDisposable.add( (account.viewTracker.peerView(peerId) |> filter { $0.cachedData != nil } |> take(1) |> mapToSignal { view -> Signal<Void, NoError> in
return ensuredExistingPeerExportedInvitation(account: account, peerId: peerId)
} ).start())
}).start())
let arguments = ChannelVisibilityControllerArguments(account: account, updateCurrentType: { type in
updateState { state in
@ -849,7 +965,7 @@ public func channelVisibilityController(account: Account, peerId: PeerId, mode:
}
if let updatedAddressNameValue = updatedAddressNameValue {
let invokeAction: ()->Void = {
let invokeAction: () -> Void = {
updateState { state in
return state.withUpdatedUpdatingAddressName(true)
}
@ -877,6 +993,96 @@ public func channelVisibilityController(account: Account, peerId: PeerId, mode:
}
_ = (ApplicationSpecificNotice.getSetPublicChannelLink(postbox: account.postbox) |> deliverOnMainQueue).start(next: { showAlert in
if showAlert {
let confirm = standardTextAlertController(theme: AlertControllerTheme(presentationTheme: presentationData.theme), title: nil, text: presentationData.strings.Channel_Edit_PrivatePublicLinkAlert, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_Cancel, action: {}), TextAlertAction(type: .genericAction, title: presentationData.strings.Common_OK, action: invokeAction)])
presentControllerImpl?(confirm, nil)
} else {
invokeAction()
}
})
} else {
switch mode {
case .initialSetup:
nextImpl?()
case .generic, .privateLink:
dismissImpl?()
}
}
})
} else if let peer = peer as? TelegramGroup {
var doneEnabled = true
if let selectedType = state.selectedType {
switch selectedType {
case .privateChannel:
break
case .publicChannel:
if let addressNameValidationStatus = state.addressNameValidationStatus {
switch addressNameValidationStatus {
case .availability(.available):
break
default:
doneEnabled = false
}
} else {
doneEnabled = !(peer.addressName?.isEmpty ?? true)
}
}
}
rightNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Done), style: state.updatingAddressName ? .activity : .bold, enabled: doneEnabled, action: {
var updatedAddressNameValue: String?
updateState { state in
updatedAddressNameValue = updatedAddressName(state: state, peer: peer)
return state
}
if let updatedAddressNameValue = updatedAddressNameValue {
let invokeAction: () -> Void = {
updateState { state in
return state.withUpdatedUpdatingAddressName(true)
}
_ = ApplicationSpecificNotice.markAsSeenSetPublicChannelLink(postbox: account.postbox).start()
let signal = convertGroupToSupergroup(account: account, peerId: peerId)
|> map(Optional.init)
|> `catch` { _ -> Signal<PeerId?, NoError> in
return .single(nil)
}
|> mapToSignal { upgradedPeerId -> Signal<PeerId?, NoError> in
guard let upgradedPeerId = upgradedPeerId else {
return .single(nil)
}
return updateAddressName(account: account, domain: .peer(upgradedPeerId), name: updatedAddressNameValue.isEmpty ? nil : updatedAddressNameValue)
|> `catch` { _ -> Signal<Void, NoError> in
return .complete()
}
|> mapToSignal { _ -> Signal<PeerId?, NoError> in
return .complete()
}
|> then(.single(upgradedPeerId))
}
|> deliverOnMainQueue
updateAddressNameDisposable.set((signal
|> deliverOnMainQueue).start(next: { updatedPeerId in
if let updatedPeerId = updatedPeerId {
upgradedToSupergroup(updatedPeerId, {
dismissImpl?()
})
} else {
dismissImpl?()
}
}, error: { _ in
updateState { state in
return state.withUpdatedUpdatingAddressName(false)
}
presentControllerImpl?(standardTextAlertController(theme: AlertControllerTheme(presentationTheme: presentationData.theme), title: nil, text: presentationData.strings.Login_UnknownError, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), nil)
}))
}
_ = (ApplicationSpecificNotice.getSetPublicChannelLink(postbox: account.postbox) |> deliverOnMainQueue).start(next: { showAlert in
if showAlert {
let confirm = standardTextAlertController(theme: AlertControllerTheme(presentationTheme: presentationData.theme), title: nil, text: presentationData.strings.Channel_Edit_PrivatePublicLinkAlert, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_Cancel, action: {}), TextAlertAction(type: .genericAction, title: presentationData.strings.Common_OK, action: invokeAction)])
@ -906,6 +1112,8 @@ public func channelVisibilityController(account: Account, peerId: PeerId, mode:
if case .group = peer.info {
isGroup = true
}
} else if let _ = peer as? TelegramGroup {
isGroup = true
}
let leftNavigationButton: ItemListNavigationButton?

View File

@ -2550,19 +2550,43 @@ public final class ChatController: TelegramController, KeyShortcutResponder, Gal
}, sendRecordedMedia: { [weak self] in
self?.sendMediaRecording()
}, displayRestrictedInfo: { [weak self] subject in
if let strongSelf = self, let peer = strongSelf.presentationInterfaceState.renderedPeer?.peer, let bannedRights = (peer as? TelegramChannel)?.bannedRights {
guard let strongSelf = self else {
return
}
let subjectFlags: TelegramChatBannedRightsFlags
switch subject {
case .stickers:
subjectFlags = .banSendStickers
case .mediaRecording:
subjectFlags = .banSendMedia
}
let bannedPermission: (Int32, Bool)?
if let channel = strongSelf.presentationInterfaceState.renderedPeer?.peer as? TelegramChannel {
bannedPermission = channel.hasBannedPermission(subjectFlags)
} else if let group = strongSelf.presentationInterfaceState.renderedPeer?.peer as? TelegramGroup {
if group.hasBannedPermission(subjectFlags) {
bannedPermission = (Int32.max, false)
} else {
bannedPermission = nil
}
} else {
bannedPermission = nil
}
if let (untilDate, personal) = bannedPermission {
let banDescription: String
switch subject {
case .stickers:
if bannedRights.personal {
if personal {
banDescription = strongSelf.presentationInterfaceState.strings.Group_ErrorSendRestrictedStickers
} else {
banDescription = strongSelf.presentationInterfaceState.strings.Conversation_DefaultRestrictedStickers
}
case .mediaRecording:
if bannedRights.untilDate != 0 && bannedRights.untilDate != Int32.max {
banDescription = strongSelf.presentationInterfaceState.strings.Conversation_RestrictedMediaTimed(stringForFullDate(timestamp: bannedRights.untilDate, strings: strongSelf.presentationInterfaceState.strings, dateTimeFormat: strongSelf.presentationInterfaceState.dateTimeFormat)).0
} else if bannedRights.personal {
if untilDate != 0 && untilDate != Int32.max {
banDescription = strongSelf.presentationInterfaceState.strings.Conversation_RestrictedMediaTimed(stringForFullDate(timestamp: untilDate, strings: strongSelf.presentationInterfaceState.strings, dateTimeFormat: strongSelf.presentationInterfaceState.dateTimeFormat)).0
} else if personal {
banDescription = strongSelf.presentationInterfaceState.strings.Conversation_RestrictedMedia
} else {
banDescription = strongSelf.presentationInterfaceState.strings.Conversation_DefaultRestrictedMedia
@ -2672,16 +2696,16 @@ public final class ChatController: TelegramController, KeyShortcutResponder, Gal
if let channel = peer as? TelegramChannel {
canManagePin = channel.hasPermission(.pinMessages)
} else if let group = peer as? TelegramGroup {
if group.flags.contains(.adminsEnabled) {
switch group.role {
case .creator, .admin:
canManagePin = true
default:
canManagePin = false
}
if let defaultBannedRights = group.defaultBannedRights {
canManagePin = !defaultBannedRights.flags.contains(.banPinMessages)
} else {
canManagePin = true
}
}
} else if let _ = peer as? TelegramUser, strongSelf.presentationInterfaceState.explicitelyCanPinMessages {
canManagePin = true
}
@ -2732,16 +2756,16 @@ public final class ChatController: TelegramController, KeyShortcutResponder, Gal
if let channel = peer as? TelegramChannel {
canManagePin = channel.hasPermission(.pinMessages)
} else if let group = peer as? TelegramGroup {
if group.flags.contains(.adminsEnabled) {
switch group.role {
case .creator, .admin:
canManagePin = true
default:
canManagePin = false
}
if let defaultBannedRights = group.defaultBannedRights {
canManagePin = !defaultBannedRights.flags.contains(.banPinMessages)
} else {
canManagePin = true
}
}
} else if let _ = peer as? TelegramUser, strongSelf.presentationInterfaceState.explicitelyCanPinMessages {
canManagePin = true
}
@ -3436,7 +3460,13 @@ public final class ChatController: TelegramController, KeyShortcutResponder, Gal
}
})
} else {
if let bannedRights = (self.presentationInterfaceState.renderedPeer?.peer as? TelegramChannel)?.bannedRights, bannedRights.flags.contains(.banEmbedLinks) {
var bannedEmbedLinks = false
if let channel = self.presentationInterfaceState.renderedPeer?.peer as? TelegramChannel, channel.hasBannedPermission(.banEmbedLinks) != nil {
bannedEmbedLinks = true
} else if let group = self.presentationInterfaceState.renderedPeer?.peer as? TelegramGroup, group.hasBannedPermission(.banEmbedLinks) {
bannedEmbedLinks = true
}
if bannedEmbedLinks {
linkPreviews = .single(false)
} else {
linkPreviews = .single(true)
@ -3708,11 +3738,18 @@ public final class ChatController: TelegramController, KeyShortcutResponder, Gal
}
strongSelf.chatDisplayNode.dismissInput()
if editMediaOptions == nil, let bannedRights = (peer as? TelegramChannel)?.bannedRights, bannedRights.flags.contains(.banSendMedia) {
var bannedSendMedia: (Int32, Bool)?
if let channel = peer as? TelegramChannel, let value = channel.hasBannedPermission(.banSendMedia) {
bannedSendMedia = value
} else if let group = peer as? TelegramGroup, group.hasBannedPermission(.banSendMedia) {
bannedSendMedia = (Int32.max, false)
}
if editMediaOptions == nil, let (untilDate, personal) = bannedSendMedia {
let banDescription: String
if bannedRights.untilDate != 0 && bannedRights.untilDate != Int32.max {
banDescription = strongSelf.presentationInterfaceState.strings.Conversation_RestrictedMediaTimed(stringForFullDate(timestamp: bannedRights.untilDate, strings: strongSelf.presentationInterfaceState.strings, dateTimeFormat: strongSelf.presentationInterfaceState.dateTimeFormat)).0
} else if bannedRights.personal {
if untilDate != 0 && untilDate != Int32.max {
banDescription = strongSelf.presentationInterfaceState.strings.Conversation_RestrictedMediaTimed(stringForFullDate(timestamp: untilDate, strings: strongSelf.presentationInterfaceState.strings, dateTimeFormat: strongSelf.presentationInterfaceState.dateTimeFormat)).0
} else if personal {
banDescription = strongSelf.presentationInterfaceState.strings.Conversation_RestrictedMedia
} else {
banDescription = strongSelf.presentationInterfaceState.strings.Conversation_DefaultRestrictedMedia

View File

@ -52,7 +52,14 @@ func inputContextPanelForChatPresentationIntefaceState(_ chatPresentationInterfa
return nil
}
if let bannedRights = (chatPresentationInterfaceState.renderedPeer?.peer as? TelegramChannel)?.bannedRights, bannedRights.flags.contains(.banSendInline) {
var hasBannedInlineContent = false
if let channel = chatPresentationInterfaceState.renderedPeer?.peer as? TelegramChannel, channel.hasBannedPermission(.banSendInline) != nil {
hasBannedInlineContent = true
} else if let group = chatPresentationInterfaceState.renderedPeer?.peer as? TelegramGroup, group.hasBannedPermission(.banSendInline) {
hasBannedInlineContent = true
}
if hasBannedInlineContent {
switch inputQueryResult {
case .stickers, .contextRequestResult:
if let currentPanel = currentPanel as? DisabledContextResultsChatInputContextPanelNode {

View File

@ -264,7 +264,11 @@ func inputTextPanelStateForChatPresentationInterfaceState(_ chatPresentationInte
if case .broadcast = peer.info, canSendMessagesToPeer(peer) {
accessoryItems.append(.silentPost(chatPresentationInterfaceState.interfaceState.silentPosting))
}
if let bannedRights = peer.bannedRights, bannedRights.flags.contains(.banSendStickers) {
if peer.hasBannedPermission(.banSendStickers) != nil {
stickersEnabled = false
}
} else if let peer = chatPresentationInterfaceState.renderedPeer?.peer as? TelegramGroup {
if peer.hasBannedPermission(.banSendStickers) {
stickersEnabled = false
}
}

View File

@ -207,17 +207,17 @@ func contextMenuForChatPresentationIntefaceState(chatPresentationInterfaceState:
}
} else if let group = messages[0].peers[messages[0].id.peerId] as? TelegramGroup {
if !isAction {
if group.flags.contains(.adminsEnabled) {
switch group.role {
case .creator, .admin:
canPin = true
default:
canPin = false
}
if let defaultBannedRights = group.defaultBannedRights {
canPin = !defaultBannedRights.flags.contains(.banPinMessages)
} else {
canPin = true
}
}
}
} else if let _ = messages[0].peers[messages[0].id.peerId] as? TelegramUser, chatPresentationInterfaceState.explicitelyCanPinMessages {
if !isAction {
canPin = true

View File

@ -99,7 +99,7 @@ func inputPanelForChatPresentationIntefaceState(_ chatPresentationInterfaceState
break
}
} else if let channel = peer as? TelegramChannel {
if let bannedRights = channel.bannedRights, bannedRights.flags.contains(.banSendMessages) {
if channel.hasBannedPermission(.banSendMessages) != nil {
if let currentPanel = currentPanel as? ChatRestrictedInputPanelNode {
return currentPanel
} else {
@ -164,6 +164,17 @@ func inputPanelForChatPresentationIntefaceState(_ chatPresentationInterfaceState
case .Member:
break
}
if group.hasBannedPermission(.banSendMessages) {
if let currentPanel = currentPanel as? ChatRestrictedInputPanelNode {
return currentPanel
} else {
let panel = ChatRestrictedInputPanelNode()
panel.account = account
panel.interfaceInteraction = interfaceInteraction
return panel
}
}
}
var displayBotStartPanel = false

View File

@ -172,7 +172,17 @@ private func mappedInsertEntries(account: Account, nodeInteraction: ChatListNode
}
if filter.contains(.onlyManageable) {
if let peer = peer.peers[peer.peerId] {
if let peer = peer as? TelegramGroup, peer.role == .creator || peer.role == .admin {
var canManage = false
if let peer = peer as? TelegramGroup {
switch peer.role {
case .creator, .admin:
canManage = true
default:
break
}
}
if canManage {
} else if let peer = peer as? TelegramChannel, case .group = peer.info, peer.hasPermission(.inviteMembers) {
} else {
enabled = false

View File

@ -684,7 +684,7 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode {
strongSelf.banDisposables.set((fetchChannelParticipant(account: strongSelf.account, peerId: strongSelf.peer.id, participantId: author.id)
|> deliverOnMainQueue).start(next: { participant in
if let strongSelf = self {
strongSelf.presentController(channelBannedMemberController(account: strongSelf.account, peerId: strongSelf.peer.id, memberId: author.id, initialParticipant: participant, updated: { _ in }), ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
strongSelf.presentController(channelBannedMemberController(account: strongSelf.account, peerId: strongSelf.peer.id, memberId: author.id, initialParticipant: participant, updated: { _ in }, upgradedToSupergroup: { _, f in f() }), ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
}
}), forKey: author.id)
}

View File

@ -66,7 +66,7 @@ private func filterOriginalMessageFlags(_ message: Message) -> Message {
private func filterMessageChannelPeer(_ peer: Peer) -> Peer {
if let peer = peer as? TelegramChannel {
return TelegramChannel(id: peer.id, accessHash: peer.accessHash, title: peer.title, username: peer.username, photo: peer.photo, creationDate: peer.creationDate, version: peer.version, participationStatus: peer.participationStatus, info: .group(TelegramChannelGroupInfo(flags: [])), flags: peer.flags, restrictionInfo: peer.restrictionInfo, adminRights: peer.adminRights, bannedRights: peer.bannedRights, peerGroupId: peer.peerGroupId)
return TelegramChannel(id: peer.id, accessHash: peer.accessHash, title: peer.title, username: peer.username, photo: peer.photo, creationDate: peer.creationDate, version: peer.version, participationStatus: peer.participationStatus, info: .group(TelegramChannelGroupInfo(flags: [])), flags: peer.flags, restrictionInfo: peer.restrictionInfo, adminRights: peer.adminRights, bannedRights: peer.bannedRights, defaultBannedRights: peer.defaultBannedRights, peerGroupId: peer.peerGroupId)
}
return peer
}

View File

@ -25,10 +25,23 @@ final class ChatRestrictedInputPanelNode: ChatInputPanelNode {
self.presentationInterfaceState = interfaceState
}
if let renderedPeer = interfaceState.renderedPeer, let channel = renderedPeer.peer as? TelegramChannel, let bannedRights = channel.bannedRights {
if bannedRights.untilDate != 0 && bannedRights.untilDate != Int32.max {
self.textNode.attributedText = NSAttributedString(string: interfaceState.strings.Conversation_RestrictedTextTimed(stringForFullDate(timestamp: bannedRights.untilDate, strings: interfaceState.strings, dateTimeFormat: interfaceState.dateTimeFormat)).0, font: Font.regular(13.0), textColor: interfaceState.theme.chat.inputPanel.secondaryTextColor)
} else if bannedRights.personal {
let bannedPermission: (Int32, Bool)?
if let channel = interfaceState.renderedPeer?.peer as? TelegramChannel {
bannedPermission = channel.hasBannedPermission(.banSendMessages)
} else if let group = interfaceState.renderedPeer?.peer as? TelegramGroup {
if group.hasBannedPermission(.banSendMessages) {
bannedPermission = (Int32.max, false)
} else {
bannedPermission = nil
}
} else {
bannedPermission = nil
}
if let (untilDate, personal) = bannedPermission {
if personal && untilDate != 0 && untilDate != Int32.max {
self.textNode.attributedText = NSAttributedString(string: interfaceState.strings.Conversation_RestrictedTextTimed(stringForFullDate(timestamp: untilDate, strings: interfaceState.strings, dateTimeFormat: interfaceState.dateTimeFormat)).0, font: Font.regular(13.0), textColor: interfaceState.theme.chat.inputPanel.secondaryTextColor)
} else if personal {
self.textNode.attributedText = NSAttributedString(string: interfaceState.strings.Conversation_RestrictedText, font: Font.regular(13.0), textColor: interfaceState.theme.chat.inputPanel.secondaryTextColor)
} else {
self.textNode.attributedText = NSAttributedString(string: interfaceState.strings.Conversation_DefaultRestrictedText, font: Font.regular(13.0), textColor: interfaceState.theme.chat.inputPanel.secondaryTextColor)

View File

@ -1022,7 +1022,9 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate {
}
let mediaInputDisabled: Bool
if let bannedRights = (interfaceState.renderedPeer?.peer as? TelegramChannel)?.bannedRights, bannedRights.flags.contains(.banSendMedia) {
if let channel = interfaceState.renderedPeer?.peer as? TelegramChannel, channel.hasBannedPermission(.banSendMedia) != nil {
mediaInputDisabled = true
} else if let group = interfaceState.renderedPeer?.peer as? TelegramGroup, group.hasBannedPermission(.banSendMedia) {
mediaInputDisabled = true
} else {
mediaInputDisabled = false

View File

@ -174,7 +174,7 @@ private func CreateChannelEntries(presentationData: PresentationData, state: Cre
let groupInfoState = ItemListAvatarAndNameInfoItemState(editingName: state.editingName, updatingName: nil)
let peer = TelegramGroup(id: PeerId(namespace: -1, id: 0), title: state.editingName.composedTitle, photo: [], participantCount: 0, role: .creator, membership: .Member, flags: [], migrationReference: nil, creationDate: 0, version: 0)
let peer = TelegramGroup(id: PeerId(namespace: -1, id: 0), title: state.editingName.composedTitle, photo: [], participantCount: 0, role: .creator, membership: .Member, flags: [], defaultBannedRights: nil, migrationReference: nil, creationDate: 0, version: 0)
entries.append(.channelInfo(presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, peer, groupInfoState, state.avatar))
entries.append(.setProfilePhoto(presentationData.theme, presentationData.strings.Channel_UpdatePhotoItem))
@ -250,7 +250,7 @@ public func createChannelController(account: Account) -> ViewController {
let _ = updatePeerPhoto(postbox: account.postbox, network: account.network, stateManager: account.stateManager, accountPeerId: account.peerId, peerId: peerId, photo: uploadedAvatar.get()).start()
}
let controller = channelVisibilityController(account: account, peerId: peerId, mode: .initialSetup)
let controller = channelVisibilityController(account: account, peerId: peerId, mode: .initialSetup, upgradedToSupergroup: { _, f in f() })
replaceControllerImpl?(controller)
}
}, error: { _ in

View File

@ -180,7 +180,7 @@ private func createGroupEntries(presentationData: PresentationData, state: Creat
let groupInfoState = ItemListAvatarAndNameInfoItemState(editingName: state.editingName, updatingName: nil)
let peer = TelegramGroup(id: PeerId(namespace: -1, id: 0), title: state.editingName.composedTitle, photo: [], participantCount: 0, role: .creator, membership: .Member, flags: [], migrationReference: nil, creationDate: 0, version: 0)
let peer = TelegramGroup(id: PeerId(namespace: -1, id: 0), title: state.editingName.composedTitle, photo: [], participantCount: 0, role: .creator, membership: .Member, flags: [], defaultBannedRights: nil, migrationReference: nil, creationDate: 0, version: 0)
entries.append(.groupInfo(presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, peer, groupInfoState, state.avatar))
entries.append(.setProfilePhoto(presentationData.theme, presentationData.strings.GroupInfo_SetGroupPhoto))

View File

@ -35,13 +35,13 @@ final class DisabledContextResultsChatInputContextPanelNode: ChatInputContextPan
self.containerNode.backgroundColor = interfaceState.theme.list.plainBackgroundColor
self.separatorNode.backgroundColor = interfaceState.theme.list.itemPlainSeparatorColor
guard let bannedRights = (interfaceState.renderedPeer?.peer as? TelegramChannel)?.bannedRights else {
guard let (untilDate, personal) = (interfaceState.renderedPeer?.peer as? TelegramChannel)?.hasBannedPermission(.banSendInline) else {
return
}
let banDescription: String
if bannedRights.untilDate != 0 && bannedRights.untilDate != Int32.max {
banDescription = interfaceState.strings.Conversation_RestrictedInlineTimed(stringForFullDate(timestamp: bannedRights.untilDate, strings: interfaceState.strings, dateTimeFormat: interfaceState.dateTimeFormat)).0
} else if bannedRights.personal {
if untilDate != 0 && untilDate != Int32.max {
banDescription = interfaceState.strings.Conversation_RestrictedInlineTimed(stringForFullDate(timestamp: untilDate, strings: interfaceState.strings, dateTimeFormat: interfaceState.dateTimeFormat)).0
} else if personal {
banDescription = interfaceState.strings.Conversation_RestrictedInline
} else {
banDescription = interfaceState.strings.Conversation_DefaultRestrictedInline

View File

@ -1,384 +0,0 @@
import Foundation
import Display
import SwiftSignalKit
import Postbox
import TelegramCore
private final class GroupAdminsControllerArguments {
let account: Account
let updateAllAreAdmins: (Bool) -> Void
let updatePeerIsAdmin: (PeerId, Bool) -> Void
init(account: Account, updateAllAreAdmins: @escaping (Bool) -> Void, updatePeerIsAdmin: @escaping (PeerId, Bool) -> Void) {
self.account = account
self.updateAllAreAdmins = updateAllAreAdmins
self.updatePeerIsAdmin = updatePeerIsAdmin
}
}
private enum GroupAdminsSection: Int32 {
case allAdmins
case peers
}
private enum GroupAdminsEntryStableId: Hashable {
case index(Int32)
case peer(PeerId)
var hashValue: Int {
switch self {
case let .index(index):
return index.hashValue
case let .peer(peerId):
return peerId.hashValue
}
}
static func ==(lhs: GroupAdminsEntryStableId, rhs: GroupAdminsEntryStableId) -> Bool {
switch lhs {
case let .index(index):
if case .index(index) = rhs {
return true
} else {
return false
}
case let .peer(peerId):
if case .peer(peerId) = rhs {
return true
} else {
return false
}
}
}
}
private enum GroupAdminsEntry: ItemListNodeEntry {
case allAdmins(PresentationTheme, String, Bool)
case allAdminsInfo(PresentationTheme, String)
case peerItem(Int32, PresentationTheme, PresentationStrings, PresentationDateTimeFormat, PresentationPersonNameOrder, Peer, String, Bool, Bool)
var section: ItemListSectionId {
switch self {
case .allAdmins, .allAdminsInfo:
return GroupAdminsSection.allAdmins.rawValue
case .peerItem:
return GroupAdminsSection.peers.rawValue
}
}
var stableId: GroupAdminsEntryStableId {
switch self {
case .allAdmins:
return .index(0)
case .allAdminsInfo:
return .index(1)
case let .peerItem(_, _, _, _, _, peer, _, _, _):
return .peer(peer.id)
}
}
static func ==(lhs: GroupAdminsEntry, rhs: GroupAdminsEntry) -> Bool {
switch lhs {
case let .allAdmins(lhsTheme, lhsText, lhsValue):
if case let .allAdmins(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue {
return true
} else {
return false
}
case let .allAdminsInfo(lhsTheme, lhsText):
if case let .allAdminsInfo(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
return true
} else {
return false
}
case let .peerItem(lhsIndex, lhsTheme, lhsStrings, lhsDateTimeFormat, lhsNameOrder, lhsPeer, lhsLabel, lhsToggled, lhsEnabled):
if case let .peerItem(rhsIndex, rhsTheme, rhsStrings, rhsDateTimeFormat, rhsNameOrder, rhsPeer, rhsLabel, rhsToggled, rhsEnabled) = rhs {
if lhsIndex != rhsIndex {
return false
}
if lhsTheme !== rhsTheme {
return false
}
if lhsStrings !== rhsStrings {
return false
}
if lhsDateTimeFormat != rhsDateTimeFormat {
return false
}
if lhsNameOrder != rhsNameOrder {
return false
}
if !lhsPeer.isEqual(rhsPeer) {
return false
}
if lhsLabel != rhsLabel {
return false
}
if lhsToggled != rhsToggled {
return false
}
if lhsEnabled != rhsEnabled {
return false
}
return true
} else {
return false
}
}
}
static func <(lhs: GroupAdminsEntry, rhs: GroupAdminsEntry) -> Bool {
switch lhs {
case .allAdmins:
return true
case .allAdminsInfo:
switch rhs {
case .allAdmins:
return false
default:
return true
}
case let .peerItem(index, _, _, _, _, _, _, _, _):
switch rhs {
case let .peerItem(rhsIndex, _, _, _, _, _, _, _, _):
return index < rhsIndex
case .allAdmins, .allAdminsInfo:
return false
}
}
}
func item(_ arguments: GroupAdminsControllerArguments) -> ListViewItem {
switch self {
case let .allAdmins(theme, text, value):
return ItemListSwitchItem(theme: theme, title: text, value: value, sectionId: self.section, style: .blocks, updated: { updatedValue in
arguments.updateAllAreAdmins(updatedValue)
})
case let .allAdminsInfo(theme, text):
return ItemListTextItem(theme: theme, text: .plain(text), sectionId: self.section)
case let .peerItem(_, theme, strings, dateTimeFormat, nameDisplayOrder, peer, label, toggled, enabled):
return ItemListPeerItem(theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, account: arguments.account, peer: peer, presence: nil, text: .none, label: .none, editing: ItemListPeerItemEditing(editable: false, editing: false, revealed: false), switchValue: ItemListPeerItemSwitch(value: toggled, style: .standard), enabled: enabled, sectionId: self.section, action: nil, setPeerIdWithRevealedOptions: { _, _ in }, removePeer: { _ in }, toggleUpdated: { value in
arguments.updatePeerIsAdmin(peer.id, value)
})
}
}
}
private struct GroupAdminsControllerState: Equatable {
let updatingAllAdminsValue: Bool?
let updatedAllAdminsValue: Bool?
let updatingAdminValue: [PeerId: Bool]
init() {
self.updatingAllAdminsValue = nil
self.updatedAllAdminsValue = nil
self.updatingAdminValue = [:]
}
init(updatingAllAdminsValue: Bool?, updatedAllAdminsValue: Bool?, updatingAdminValue: [PeerId: Bool]) {
self.updatingAllAdminsValue = updatingAllAdminsValue
self.updatedAllAdminsValue = updatedAllAdminsValue
self.updatingAdminValue = updatingAdminValue
}
static func ==(lhs: GroupAdminsControllerState, rhs: GroupAdminsControllerState) -> Bool {
if lhs.updatingAllAdminsValue != rhs.updatingAllAdminsValue {
return false
}
if lhs.updatedAllAdminsValue != rhs.updatedAllAdminsValue {
return false
}
if lhs.updatingAdminValue != rhs.updatingAdminValue {
return false
}
return true
}
func withUpdatedUpdatingAllAdminsValue(_ updatingAllAdminsValue: Bool?) -> GroupAdminsControllerState {
return GroupAdminsControllerState(updatingAllAdminsValue: updatingAllAdminsValue, updatedAllAdminsValue: self.updatedAllAdminsValue, updatingAdminValue: self.updatingAdminValue)
}
func withUpdatedUpdatedAllAdminsValue(_ updatedAllAdminsValue: Bool?) -> GroupAdminsControllerState {
return GroupAdminsControllerState(updatingAllAdminsValue: self.updatingAllAdminsValue, updatedAllAdminsValue: updatedAllAdminsValue, updatingAdminValue: self.updatingAdminValue)
}
func withUpdatedUpdatingAdminValue(_ updatingAdminValue: [PeerId: Bool]) -> GroupAdminsControllerState {
return GroupAdminsControllerState(updatingAllAdminsValue: self.updatingAllAdminsValue, updatedAllAdminsValue: self.updatedAllAdminsValue, updatingAdminValue: updatingAdminValue)
}
}
private func groupAdminsControllerEntries(account: Account, presentationData: PresentationData, view: PeerView, state: GroupAdminsControllerState) -> [GroupAdminsEntry] {
var entries: [GroupAdminsEntry] = []
if let peer = view.peers[view.peerId] as? TelegramGroup, let cachedData = view.cachedData as? CachedGroupData, let participants = cachedData.participants {
let effectiveAdminsEnabled: Bool
if let updatingAllAdminsValue = state.updatingAllAdminsValue {
effectiveAdminsEnabled = updatingAllAdminsValue
} else {
effectiveAdminsEnabled = peer.flags.contains(.adminsEnabled)
}
entries.append(.allAdmins(presentationData.theme, presentationData.strings.ChatAdmins_AllMembersAreAdmins, !effectiveAdminsEnabled))
if effectiveAdminsEnabled {
entries.append(.allAdminsInfo(presentationData.theme, presentationData.strings.ChatAdmins_AllMembersAreAdminsOnHelp))
} else {
entries.append(.allAdminsInfo(presentationData.theme, presentationData.strings.ChatAdmins_AllMembersAreAdminsOffHelp))
}
let sortedParticipants = participants.participants.sorted(by: { lhs, rhs in
let lhsInvitedAt: Int32
switch lhs {
case let .admin(_, _, invitedAt):
lhsInvitedAt = invitedAt
case .creator(_):
lhsInvitedAt = Int32.max
case let .member(_, _, invitedAt):
lhsInvitedAt = invitedAt
}
let rhsInvitedAt: Int32
switch rhs {
case let .admin(_, _, invitedAt):
rhsInvitedAt = invitedAt
case .creator(_):
rhsInvitedAt = Int32.max
case let .member(_, _, invitedAt):
rhsInvitedAt = invitedAt
}
return lhsInvitedAt > rhsInvitedAt
})
var index: Int32 = 0
for participant in sortedParticipants {
if let peer = view.peers[participant.peerId] {
var isAdmin = false
var isEnabled = true
let label = ""
if !effectiveAdminsEnabled {
isAdmin = true
isEnabled = false
} else {
switch participant {
case .creator:
isAdmin = true
isEnabled = false
case .admin:
if let value = state.updatingAdminValue[peer.id] {
isAdmin = value
} else {
isAdmin = true
}
case .member:
if let value = state.updatingAdminValue[peer.id] {
isAdmin = value
} else {
isAdmin = false
}
}
}
entries.append(.peerItem(index, presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, presentationData.nameDisplayOrder, peer, label, isAdmin, isEnabled))
index += 1
}
}
}
return entries
}
public func groupAdminsController(account: Account, peerId: PeerId) -> ViewController {
let statePromise = ValuePromise(GroupAdminsControllerState(), ignoreRepeated: true)
let stateValue = Atomic(value: GroupAdminsControllerState())
let updateState: ((GroupAdminsControllerState) -> GroupAdminsControllerState) -> Void = { f in
statePromise.set(stateValue.modify { f($0) })
}
let actionsDisposable = DisposableSet()
let toggleAllAdminsDisposable = MetaDisposable()
actionsDisposable.add(toggleAllAdminsDisposable)
let toggleAdminsDisposables = DisposableDict<PeerId>()
actionsDisposable.add(toggleAdminsDisposables)
let arguments = GroupAdminsControllerArguments(account: account, updateAllAreAdmins: { value in
updateState { state in
return state.withUpdatedUpdatingAllAdminsValue(value)
}
toggleAllAdminsDisposable.set((updateGroupManagementType(account: account, peerId: peerId, type: value ? .unrestricted : .restrictedToAdmins)
|> deliverOnMainQueue).start(error: { _ in
updateState { state in
return state.withUpdatedUpdatingAllAdminsValue(nil)
}
}, completed: {
updateState { state in
return state.withUpdatedUpdatingAllAdminsValue(nil).withUpdatedUpdatedAllAdminsValue(value)
}
}))
}, updatePeerIsAdmin: { memberId, value in
updateState { state in
var updatingAdminValue = state.updatingAdminValue
updatingAdminValue[memberId] = value
return state.withUpdatedUpdatingAdminValue(updatingAdminValue)
}
if value {
toggleAdminsDisposables.set((addGroupAdmin(account: account, peerId: peerId, adminId: memberId) |> deliverOnMainQueue).start(error: { _ in
updateState { state in
var updatingAdminValue = state.updatingAdminValue
updatingAdminValue.removeValue(forKey: memberId)
return state.withUpdatedUpdatingAdminValue(updatingAdminValue)
}
}, completed: {
updateState { state in
var updatingAdminValue = state.updatingAdminValue
updatingAdminValue.removeValue(forKey: memberId)
return state.withUpdatedUpdatingAdminValue(updatingAdminValue)
}
}), forKey: memberId)
} else {
toggleAdminsDisposables.set((removeGroupAdmin(account: account, peerId: peerId, adminId: memberId) |> deliverOnMainQueue).start(error: { _ in
updateState { state in
var updatingAdminValue = state.updatingAdminValue
updatingAdminValue.removeValue(forKey: memberId)
return state.withUpdatedUpdatingAdminValue(updatingAdminValue)
}
}, completed: {
updateState { state in
var updatingAdminValue = state.updatingAdminValue
updatingAdminValue.removeValue(forKey: memberId)
return state.withUpdatedUpdatingAdminValue(updatingAdminValue)
}
}), forKey: memberId)
}
})
let peerView = account.viewTracker.peerView(peerId)
let signal = combineLatest((account.applicationContext as! TelegramApplicationContext).presentationData, statePromise.get() |> deliverOnMainQueue, peerView |> deliverOnMainQueue)
|> deliverOnMainQueue
|> map { presentationData, state, view -> (ItemListControllerState, (ItemListNodeState<GroupAdminsEntry>, GroupAdminsEntry.ItemGenerationArguments)) in
var emptyStateItem: ItemListControllerEmptyStateItem?
if view.cachedData == nil {
emptyStateItem = ItemListLoadingIndicatorEmptyStateItem(theme: presentationData.theme)
}
var rightNavigationButton: ItemListNavigationButton?
if !state.updatingAdminValue.isEmpty || state.updatingAllAdminsValue != nil {
rightNavigationButton = ItemListNavigationButton(content: .none, style: .activity, enabled: true, action: {})
}
let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(presentationData.strings.ChatAdmins_Title), leftNavigationButton: nil, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: true)
let listState = ItemListNodeState(entries: groupAdminsControllerEntries(account: account, presentationData: presentationData, view: view, state: state), style: .blocks, emptyStateItem: emptyStateItem, animateChanges: true)
return (controllerState, (listState, arguments))
} |> afterDisposed {
actionsDisposable.dispose()
}
let controller = ItemListController(account: account, state: signal)
return controller
}

View File

@ -35,8 +35,9 @@ private final class GroupInfoArguments {
let displayAboutContextMenu: (String) -> Void
let aboutLinkAction: (TextLinkItemActionType, TextLinkItem) -> Void
let openStickerPackSetup: () -> Void
let openGroupTypeSetup: () -> Void
init(account: Account, peerId: PeerId, avatarAndNameInfoContext: ItemListAvatarAndNameInfoItemContext, tapAvatarAction: @escaping () -> Void, changeProfilePhoto: @escaping () -> Void, pushController: @escaping (ViewController) -> Void, presentController: @escaping (ViewController, ViewControllerPresentationArguments) -> Void, changeNotificationMuteSettings: @escaping () -> Void, openPreHistory: @escaping () -> Void, openSharedMedia: @escaping () -> Void, openAdministrators: @escaping () -> Void, openPermissions: @escaping () -> Void, updateEditingName: @escaping (ItemListAvatarAndNameInfoItemName) -> Void, updateEditingDescriptionText: @escaping (String) -> Void, setPeerIdWithRevealedOptions: @escaping (PeerId?, PeerId?) -> Void, addMember: @escaping () -> Void, promotePeer: @escaping (RenderedChannelParticipant) -> Void, restrictPeer: @escaping (RenderedChannelParticipant) -> Void, removePeer: @escaping (PeerId) -> Void, convertToSupergroup: @escaping () -> Void, leave: @escaping () -> Void, displayUsernameShareMenu: @escaping (String) -> Void, displayUsernameContextMenu: @escaping (String) -> Void, displayAboutContextMenu: @escaping (String) -> Void, aboutLinkAction: @escaping (TextLinkItemActionType, TextLinkItem) -> Void, openStickerPackSetup: @escaping () -> Void) {
init(account: Account, peerId: PeerId, avatarAndNameInfoContext: ItemListAvatarAndNameInfoItemContext, tapAvatarAction: @escaping () -> Void, changeProfilePhoto: @escaping () -> Void, pushController: @escaping (ViewController) -> Void, presentController: @escaping (ViewController, ViewControllerPresentationArguments) -> Void, changeNotificationMuteSettings: @escaping () -> Void, openPreHistory: @escaping () -> Void, openSharedMedia: @escaping () -> Void, openAdministrators: @escaping () -> Void, openPermissions: @escaping () -> Void, updateEditingName: @escaping (ItemListAvatarAndNameInfoItemName) -> Void, updateEditingDescriptionText: @escaping (String) -> Void, setPeerIdWithRevealedOptions: @escaping (PeerId?, PeerId?) -> Void, addMember: @escaping () -> Void, promotePeer: @escaping (RenderedChannelParticipant) -> Void, restrictPeer: @escaping (RenderedChannelParticipant) -> Void, removePeer: @escaping (PeerId) -> Void, convertToSupergroup: @escaping () -> Void, leave: @escaping () -> Void, displayUsernameShareMenu: @escaping (String) -> Void, displayUsernameContextMenu: @escaping (String) -> Void, displayAboutContextMenu: @escaping (String) -> Void, aboutLinkAction: @escaping (TextLinkItemActionType, TextLinkItem) -> Void, openStickerPackSetup: @escaping () -> Void, openGroupTypeSetup: @escaping () -> Void) {
self.account = account
self.peerId = peerId
self.avatarAndNameInfoContext = avatarAndNameInfoContext
@ -63,6 +64,7 @@ private final class GroupInfoArguments {
self.displayAboutContextMenu = displayAboutContextMenu
self.aboutLinkAction = aboutLinkAction
self.openStickerPackSetup = openStickerPackSetup
self.openGroupTypeSetup = openGroupTypeSetup
}
}
@ -71,7 +73,6 @@ private enum GroupInfoSection: ItemListSectionId {
case about
case infoManagement
case sharedMediaAndNotifications
case stickerPack
case memberManagement
case members
case leave
@ -155,12 +156,10 @@ private enum GroupInfoEntry: ItemListNodeEntry {
return GroupInfoSection.info.rawValue
case .aboutHeader, .about, .link:
return GroupInfoSection.about.rawValue
case .groupTypeSetup, .preHistory:
case .groupTypeSetup, .preHistory, .stickerPack:
return GroupInfoSection.infoManagement.rawValue
case .sharedMedia, .notifications:
return GroupInfoSection.sharedMediaAndNotifications.rawValue
case .stickerPack:
return GroupInfoSection.stickerPack.rawValue
case .permissions, .administrators:
return GroupInfoSection.memberManagement.rawValue
case .addMember, .member:
@ -394,10 +393,10 @@ private enum GroupInfoEntry: ItemListNodeEntry {
return 8
case .preHistory:
return 9
case .notifications:
return 10
case .stickerPack:
return 12
return 10
case .notifications:
return 11
case .sharedMedia:
return 13
case .permissions:
@ -467,7 +466,7 @@ private enum GroupInfoEntry: ItemListNodeEntry {
})
case let .groupTypeSetup(theme, title, text):
return ItemListDisclosureItem(theme: theme, title: title, label: text, sectionId: self.section, style: .blocks, action: {
arguments.presentController(channelVisibilityController(account: arguments.account, peerId: arguments.peerId, mode: .generic), ViewControllerPresentationArguments(presentationAnimation: ViewControllerPresentationAnimation.modalSheet))
arguments.openGroupTypeSetup()
})
case let .groupDescriptionSetup(theme, placeholder, text):
return ItemListMultilineInputItem(theme: theme, text: text, placeholder: placeholder, maxLength: ItemListMultilineInputItemTextLimit(value: 255, display: true), sectionId: self.section, style: .blocks, textUpdated: { updatedText in
@ -705,7 +704,6 @@ private func groupInfoEntries(account: Account, presentationData: PresentationDa
if case .creator = group.role {
isCreator = true
}
if group.flags.contains(.adminsEnabled) {
highlightAdmins = true
switch group.role {
case .admin, .creator:
@ -715,16 +713,6 @@ private func groupInfoEntries(account: Account, presentationData: PresentationDa
case .member:
break
}
} else {
canEditGroupInfo = true
canAddMembers = true
switch group.role {
case .admin, .creator:
canEditMembers = true
case .member:
break
}
}
} else if let channel = view.peers[view.peerId] as? TelegramChannel {
if case .group = channel.info {
isGroup = true
@ -770,8 +758,12 @@ private func groupInfoEntries(account: Account, presentationData: PresentationDa
if let group = view.peers[view.peerId] as? TelegramGroup, let cachedGroupData = view.cachedData as? CachedGroupData {
if case .creator = group.role {
if cachedGroupData.flags.contains(.canChangeUsername) {
entries.append(GroupInfoEntry.groupTypeSetup(presentationData.theme, presentationData.strings.GroupInfo_GroupType, presentationData.strings.Channel_Setup_TypePrivate))
}
var activePermissionCount: Int?
if let defaultBannedRights = cachedGroupData.defaultBannedRights {
if let defaultBannedRights = group.defaultBannedRights {
var count = 0
for right in allGroupPermissionList {
if !defaultBannedRights.flags.contains(right) {
@ -783,11 +775,13 @@ private func groupInfoEntries(account: Account, presentationData: PresentationDa
entries.append(GroupInfoEntry.permissions(presentationData.theme, presentationData.strings.GroupInfo_Permissions, activePermissionCount.flatMap({ "\($0)/\(allGroupPermissionList.count)" }) ?? ""))
entries.append(.administrators(presentationData.theme, presentationData.strings.GroupInfo_Administrators, ""))
}
} else if let cachedChannelData = view.cachedData as? CachedChannelData {
} else if let channel = view.peers[view.peerId] as? TelegramChannel, let cachedChannelData = view.cachedData as? CachedChannelData {
if isCreator {
if cachedChannelData.flags.contains(.canChangeUsername) {
entries.append(GroupInfoEntry.groupTypeSetup(presentationData.theme, presentationData.strings.GroupInfo_GroupType, isPublic ? presentationData.strings.Channel_Setup_TypePublic : presentationData.strings.Channel_Setup_TypePrivate))
if !isPublic, let cachedData = view.cachedData as? CachedChannelData {
entries.append(GroupInfoEntry.preHistory(presentationData.theme, presentationData.strings.GroupInfo_GroupHistory, cachedData.flags.contains(.preHistoryEnabled) ? presentationData.strings.GroupInfo_GroupHistoryVisible : presentationData.strings.GroupInfo_GroupHistoryHidden))
}
if !isPublic {
entries.append(GroupInfoEntry.preHistory(presentationData.theme, presentationData.strings.GroupInfo_GroupHistory, cachedChannelData.flags.contains(.preHistoryEnabled) ? presentationData.strings.GroupInfo_GroupHistoryVisible : presentationData.strings.GroupInfo_GroupHistoryHidden))
}
}
@ -806,7 +800,7 @@ private func groupInfoEntries(account: Account, presentationData: PresentationDa
if canViewAdminsAndBanned {
var activePermissionCount: Int?
if let defaultBannedRights = cachedChannelData.defaultBannedRights {
if let defaultBannedRights = channel.defaultBannedRights {
var count = 0
for right in allGroupPermissionList {
if !defaultBannedRights.flags.contains(right) {
@ -1171,6 +1165,9 @@ public func groupInfoController(account: Account, peerId: PeerId) -> ViewControl
let navigateDisposable = MetaDisposable()
actionsDisposable.add(navigateDisposable)
let upgradeDisposable = MetaDisposable()
actionsDisposable.add(upgradeDisposable)
var avatarGalleryTransitionArguments: ((AvatarGalleryEntry) -> GalleryTransitionArguments?)?
let avatarAndNameInfoContext = ItemListAvatarAndNameInfoItemContext()
var updateHiddenAvatarImpl: (() -> Void)?
@ -1178,6 +1175,8 @@ public func groupInfoController(account: Account, peerId: PeerId) -> ViewControl
var displayCopyContextMenuImpl: ((String, GroupInfoEntryTag) -> Void)?
var aboutLinkActionImpl: ((TextLinkItemActionType, TextLinkItem) -> Void)?
var upgradedToSupergroupImpl: ((PeerId, @escaping () -> Void) -> Void)?
let arguments = GroupInfoArguments(account: account, peerId: peerId, avatarAndNameInfoContext: avatarAndNameInfoContext, tapAvatarAction: {
let _ = (account.postbox.loadedPeerWithId(peerId) |> take(1) |> deliverOnMainQueue).start(next: { peer in
if peer.profileImageRepresentations.isEmpty {
@ -1526,7 +1525,9 @@ public func groupInfoController(account: Account, peerId: PeerId) -> ViewControl
inviteByLinkImpl = { [weak contactsController] in
contactsController?.dismiss()
presentControllerImpl?(channelVisibilityController(account: account, peerId: peerId, mode: .privateLink), ViewControllerPresentationArguments(presentationAnimation: ViewControllerPresentationAnimation.modalSheet))
presentControllerImpl?(channelVisibilityController(account: account, peerId: peerId, mode: .privateLink, upgradedToSupergroup: { updatedPeerId, f in
upgradedToSupergroupImpl?(updatedPeerId, f)
}), ViewControllerPresentationArguments(presentationAnimation: ViewControllerPresentationAnimation.modalSheet))
}
presentControllerImpl?(contactsController, ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
@ -1583,6 +1584,8 @@ public func groupInfoController(account: Account, peerId: PeerId) -> ViewControl
}, upgradedToSupergroup: { _, f in f() }), ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
}, restrictPeer: { participant in
presentControllerImpl?(channelBannedMemberController(account: account, peerId: peerId, memberId: participant.peer.id, initialParticipant: participant.participant, updated: { _ in
}, upgradedToSupergroup: { upgradedPeerId, f in
upgradedToSupergroupImpl?(upgradedPeerId, f)
}), ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
}, removePeer: { memberId in
let signal = account.postbox.loadedPeerWithId(memberId)
@ -1612,7 +1615,7 @@ public func groupInfoController(account: Account, peerId: PeerId) -> ViewControl
}
if peerId.namespace == Namespaces.Peer.CloudChannel {
return account.telegramApplicationContext.peerChannelMemberCategoriesContextsManager.updateMemberBannedRights(account: account, peerId: peerId, memberId: memberId, bannedRights: TelegramChatBannedRights(flags: [.banReadMessages], personal: false, untilDate: Int32.max))
return account.telegramApplicationContext.peerChannelMemberCategoriesContextsManager.updateMemberBannedRights(account: account, peerId: peerId, memberId: memberId, bannedRights: TelegramChatBannedRights(flags: [.banReadMessages], untilDate: Int32.max))
|> afterDisposed {
Queue.mainQueue().async {
updateState { state in
@ -1681,6 +1684,10 @@ public func groupInfoController(account: Account, peerId: PeerId) -> ViewControl
|> deliverOnMainQueue).start(next: { stickerPack in
presentControllerImpl?(groupStickerPackSetupController(account: account, peerId: peerId, currentPackInfo: stickerPack), ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
})
}, openGroupTypeSetup: {
presentControllerImpl?(channelVisibilityController(account: account, peerId: peerId, mode: .generic, upgradedToSupergroup: { updatedPeerId, f in
upgradedToSupergroupImpl?(updatedPeerId, f)
}), ViewControllerPresentationArguments(presentationAnimation: ViewControllerPresentationAnimation.modalSheet))
})
var loadMoreControl: PeerChannelMemberCategoryControl?
@ -1854,6 +1861,23 @@ public func groupInfoController(account: Account, peerId: PeerId) -> ViewControl
controller?.view.endEditing(true)
controller?.present(value, in: .window(.root), with: presentationArguments)
}
upgradedToSupergroupImpl = { [weak controller] upgradedPeerId, f in
let _ = (account.postbox.transaction { transaction -> Peer? in
return transaction.getPeer(upgradedPeerId)
}
|> deliverOnMainQueue).start(next: { peer in
guard let peer = peer, let infoController = peerInfoController(account: account, peer: peer) else {
return
}
guard let controller = controller, let navigationController = controller.navigationController as? NavigationController else {
return
}
navigateToChatController(navigationController: navigationController, account: account, chatLocation: .peer(upgradedPeerId), keepStack: .never, animated: false, completion: {
f()
navigationController.pushViewController(infoController, animated: false)
})
})
}
popToRootImpl = { [weak controller] in
(controller?.navigationController as? NavigationController)?.popToRoot(animated: true)
}

View File

@ -56,7 +56,7 @@ final class JoinLinkPreviewPeerContentNode: ASDisplayNode, ShareContentContainer
super.init()
let peer = TelegramGroup(id: PeerId(namespace: 0, id: 0), title: title, photo: image.flatMap { [$0] } ?? [], participantCount: Int(memberCount), role: .member, membership: .Left, flags: [], migrationReference: nil, creationDate: 0, version: 0)
let peer = TelegramGroup(id: PeerId(namespace: 0, id: 0), title: title, photo: image.flatMap { [$0] } ?? [], participantCount: Int(memberCount), role: .member, membership: .Left, flags: [], defaultBannedRights: nil, migrationReference: nil, creationDate: 0, version: 0)
self.addSubnode(self.avatarNode)
self.avatarNode.setPeer(account: account, peer: peer, emptyColor: theme.list.mediaPlaceholderColor)

File diff suppressed because it is too large Load Diff

View File

@ -145,12 +145,12 @@ final class ThemeGridControllerNode: ASDisplayNode {
let entries = previousEntries.with { $0 }
if let entries = entries, !entries.isEmpty {
let wallpapers = entries.map { $0.wallpaper }
let controller = WallpaperListPreviewController(account: account, source: .list(wallpapers: wallpapers, central: wallpaper))
strongSelf.present(controller, nil)
/*let controller = ThemeGalleryController(account: account, wallpapers: wallpapers, at: wallpaper)
/*let controller = WallpaperListPreviewController(account: account, source: .list(wallpapers: wallpapers, central: wallpaper))
strongSelf.present(controller, nil)*/
let controller = ThemeGalleryController(account: account, wallpapers: wallpapers, at: wallpaper)
strongSelf.present(controller, ThemePreviewControllerPresentationArguments(transitionArguments: { entry -> GalleryTransitionArguments? in
return nil
}))*/
}))
}
}
})