From a81db7f96cc2158d63b2b224920a54e97cee2878 Mon Sep 17 00:00:00 2001 From: overtake <> Date: Fri, 31 Aug 2018 20:25:37 +0300 Subject: [PATCH 1/3] - channel admin bug fixes --- TelegramUI/ChangePhoneNumberController.swift | 1 + TelegramUI/ChannelInfoController.swift | 139 +++++++++++++----- TelegramUI/ChannelMembersController.swift | 68 +++++++-- TelegramUI/ChannelVisibilityController.swift | 63 ++++---- TelegramUI/ChatController.swift | 2 +- TelegramUI/ChatControllerNode.swift | 4 +- .../ChatInterfaceStateContextMenus.swift | 56 +++++-- TelegramUI/ChatListItem.swift | 4 +- TelegramUI/ChatMessageActionItemNode.swift | 50 ++++++- ...atMessageInteractiveInstantVideoNode.swift | 20 +-- .../ChatRecentActionsControllerNode.swift | 9 +- .../ChatRecentActionsHistoryTransition.swift | 1 + TelegramUI/ItemListActivityTextItem.swift | 7 +- TelegramUI/ItemListMultilineInputItem.swift | 2 +- TelegramUI/ItemListTextItem.swift | 13 +- TelegramUI/PresentationStrings.swift | 7 + TelegramUI/StickerResources.swift | 4 +- 17 files changed, 338 insertions(+), 112 deletions(-) diff --git a/TelegramUI/ChangePhoneNumberController.swift b/TelegramUI/ChangePhoneNumberController.swift index 5df48e9f47..7654b7c525 100644 --- a/TelegramUI/ChangePhoneNumberController.swift +++ b/TelegramUI/ChangePhoneNumberController.swift @@ -114,6 +114,7 @@ final class ChangePhoneNumberController: ViewController { let text: String switch error { + //TODO case .limitExceeded: text = "You have requested authorization code too many times. Please try again later." case .invalidPhoneNumber: diff --git a/TelegramUI/ChannelInfoController.swift b/TelegramUI/ChannelInfoController.swift index 9e04b0fff5..48153cca1c 100644 --- a/TelegramUI/ChannelInfoController.swift +++ b/TelegramUI/ChannelInfoController.swift @@ -25,8 +25,8 @@ private final class ChannelInfoControllerArguments { let displayAddressNameContextMenu: (String) -> Void let displayContextMenu: (ChannelInfoEntryTag, String) -> Void let aboutLinkAction: (TextLinkItemActionType, TextLinkItem) -> Void - - init(account: Account, avatarAndNameInfoContext: ItemListAvatarAndNameInfoItemContext, tapAvatarAction: @escaping () -> Void, changeProfilePhoto: @escaping () -> Void, updateEditingName: @escaping (ItemListAvatarAndNameInfoItemName) -> Void, updateEditingDescriptionText: @escaping (String) -> Void, openChannelTypeSetup: @escaping () -> Void, changeNotificationMuteSettings: @escaping () -> Void, changeNotificationSoundSettings: @escaping () -> Void, openSharedMedia: @escaping () -> Void, openAdmins: @escaping () -> Void, openMembers: @escaping () -> Void, openBanned: @escaping () -> Void, reportChannel: @escaping () -> Void, leaveChannel: @escaping () -> Void, deleteChannel: @escaping () -> Void, displayAddressNameContextMenu: @escaping (String) -> Void, displayContextMenu: @escaping (ChannelInfoEntryTag, String) -> Void, aboutLinkAction: @escaping (TextLinkItemActionType, TextLinkItem) -> Void) { + let toggleSignatures:(Bool) -> Void + init(account: Account, avatarAndNameInfoContext: ItemListAvatarAndNameInfoItemContext, tapAvatarAction: @escaping () -> Void, changeProfilePhoto: @escaping () -> Void, updateEditingName: @escaping (ItemListAvatarAndNameInfoItemName) -> Void, updateEditingDescriptionText: @escaping (String) -> Void, openChannelTypeSetup: @escaping () -> Void, changeNotificationMuteSettings: @escaping () -> Void, changeNotificationSoundSettings: @escaping () -> Void, openSharedMedia: @escaping () -> Void, openAdmins: @escaping () -> Void, openMembers: @escaping () -> Void, openBanned: @escaping () -> Void, reportChannel: @escaping () -> Void, leaveChannel: @escaping () -> Void, deleteChannel: @escaping () -> Void, displayAddressNameContextMenu: @escaping (String) -> Void, displayContextMenu: @escaping (ChannelInfoEntryTag, String) -> Void, aboutLinkAction: @escaping (TextLinkItemActionType, TextLinkItem) -> Void, toggleSignatures: @escaping(Bool)->Void) { self.account = account self.avatarAndNameInfoContext = avatarAndNameInfoContext self.tapAvatarAction = tapAvatarAction @@ -46,12 +46,15 @@ private final class ChannelInfoControllerArguments { self.displayAddressNameContextMenu = displayAddressNameContextMenu self.displayContextMenu = displayContextMenu self.aboutLinkAction = aboutLinkAction + self.toggleSignatures = toggleSignatures } } private enum ChannelInfoSection: ItemListSectionId { case info + case discriptionAndType case sharedMediaAndNotifications + case signMessages case members case reportOrLeave } @@ -68,24 +71,31 @@ private enum ChannelInfoEntry: ItemListNodeEntry { case channelPhotoSetup(theme: PresentationTheme, text: String) case channelTypeSetup(theme: PresentationTheme, text: String, value: String) case channelDescriptionSetup(theme: PresentationTheme, placeholder: String, value: String) + case channelDescriptionSetupInfo(theme: PresentationTheme, text: String) case admins(theme: PresentationTheme, text: String, value: String) case members(theme: PresentationTheme, text: String, value: String) case banned(theme: PresentationTheme, text: String, value: String) case notifications(theme: PresentationTheme, text: String, value: String) case notificationSound(theme: PresentationTheme, text: String, value: String) case sharedMedia(theme: PresentationTheme, text: String) + case signMessages(theme: PresentationTheme, text: String, value: Bool) + case signInfo(theme: PresentationTheme, text: String) case report(theme: PresentationTheme, text: String) case leave(theme: PresentationTheme, text: String) case deleteChannel(theme: PresentationTheme, text: String) var section: ItemListSectionId { switch self { - case .info, .about, .addressName, .channelPhotoSetup, .channelTypeSetup, .channelDescriptionSetup: + case .info, .about, .addressName, .channelPhotoSetup: return ChannelInfoSection.info.rawValue + case .channelDescriptionSetup, .channelDescriptionSetupInfo, .channelTypeSetup: + return ChannelInfoSection.discriptionAndType.rawValue case .admins, .members, .banned: return ChannelInfoSection.members.rawValue case .sharedMedia, .notifications, .notificationSound: return ChannelInfoSection.sharedMediaAndNotifications.rawValue + case .signMessages, .signInfo: + return ChannelInfoSection.signMessages.rawValue case .report, .leave, .deleteChannel: return ChannelInfoSection.reportOrLeave.rawValue } @@ -95,34 +105,40 @@ private enum ChannelInfoEntry: ItemListNodeEntry { switch self { case .info: return 0 - case .about: - return 1 case .addressName: + return 1 + case .about: return 2 case .channelPhotoSetup: return 3 - case .channelDescriptionSetup: - return 4 case .channelTypeSetup: + return 4 + case .channelDescriptionSetup: return 5 - case .admins: + case .channelDescriptionSetupInfo: return 6 - case .members: + case .admins: return 7 case .banned: return 8 - case .notifications: + case .members: return 9 - case .notificationSound: + case .signMessages: return 10 - case .sharedMedia: + case .signInfo: return 11 - case .report: + case .notifications: return 12 - case .leave: + case .notificationSound: return 13 - case .deleteChannel: + case .sharedMedia: return 14 + case .report: + return 15 + case .leave: + return 16 + case .deleteChannel: + return 17 } } @@ -166,6 +182,7 @@ private enum ChannelInfoEntry: ItemListNodeEntry { } else { return false } + case let .addressName(lhsTheme, lhsText, lhsValue): if case let .addressName(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue { return true @@ -190,6 +207,12 @@ private enum ChannelInfoEntry: ItemListNodeEntry { } else { return false } + case let .channelDescriptionSetupInfo(lhsTheme, lhsText): + if case let .channelDescriptionSetupInfo(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText { + return true + } else { + return false + } case let .admins(lhsTheme, lhsText, lhsValue): if case let .admins(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue { return true @@ -208,6 +231,18 @@ private enum ChannelInfoEntry: ItemListNodeEntry { } else { return false } + case let .signMessages(lhsTheme, lhsText, lhsValue): + if case let .signMessages(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue { + return true + } else { + return false + } + case let .signInfo(lhsTheme, lhsText): + if case let .signInfo(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText { + return true + } else { + return false + } case let .sharedMedia(lhsTheme, lhsText): if case let .sharedMedia(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText { return true @@ -285,6 +320,8 @@ private enum ChannelInfoEntry: ItemListNodeEntry { }, action: { }) + case let .channelDescriptionSetupInfo(theme, text): + return ItemListTextItem(theme: theme, text: .plain(text), sectionId: self.section, style: .plain) case let .admins(theme, text, value): return ItemListDisclosureItem(theme: theme, title: text, label: value, sectionId: self.section, style: .plain, action: { arguments.openAdmins() @@ -297,6 +334,12 @@ private enum ChannelInfoEntry: ItemListNodeEntry { return ItemListDisclosureItem(theme: theme, title: text, label: value, sectionId: self.section, style: .plain, action: { arguments.openBanned() }) + case let .signMessages(theme, text, value): + return ItemListSwitchItem(theme: theme, title: text, value: value, sectionId: self.section, style: .plain, updated: { updated in + arguments.toggleSignatures(updated) + }) + case let .signInfo(theme, text): + return ItemListTextItem(theme: theme, text: .plain(text), sectionId: self.section, style: .plain) case let .sharedMedia(theme, text): return ItemListDisclosureItem(theme: theme, title: text, label: "", sectionId: self.section, style: .plain, action: { arguments.openSharedMedia() @@ -401,16 +444,6 @@ private func channelInfoEntries(account: Account, presentationData: Presentation entries.append(.channelPhotoSetup(theme: presentationData.theme, text: presentationData.strings.Channel_UpdatePhotoItem)) } - if let cachedChannelData = view.cachedData as? CachedChannelData { - if let editingState = state.editingState, canEditChannel { - entries.append(.channelDescriptionSetup(theme: presentationData.theme, placeholder: presentationData.strings.Channel_Edit_AboutItem, value: editingState.editingDescriptionText)) - } else { - if let about = cachedChannelData.about, !about.isEmpty { - entries.append(.about(theme: presentationData.theme, text: presentationData.strings.Channel_AboutItem, value: about)) - } - } - } - if state.editingState != nil && peer.flags.contains(.isCreator) { let linkText: String if let username = peer.username { @@ -419,23 +452,51 @@ private func channelInfoEntries(account: Account, presentationData: Presentation linkText = presentationData.strings.Channel_Setup_TypePrivate } entries.append(.channelTypeSetup(theme: presentationData.theme, text: presentationData.strings.Channel_Edit_LinkItem, value: linkText)) + + } else if let username = peer.username, !username.isEmpty { entries.append(.addressName(theme: presentationData.theme, text: presentationData.strings.Channel_LinkItem, value: username)) } if let cachedChannelData = view.cachedData as? CachedChannelData { - if state.editingState != nil && canEditMembers { - if let kickedCount = cachedChannelData.participantsSummary.kickedCount { - entries.append(.banned(theme: presentationData.theme, text: presentationData.strings.Channel_Info_Banned, value: "\(kickedCount)")) + if let editingState = state.editingState, canEditChannel { + entries.append(.channelDescriptionSetup(theme: presentationData.theme, placeholder: presentationData.strings.Channel_Edit_AboutItem, value: editingState.editingDescriptionText)) + entries.append(.channelDescriptionSetupInfo(theme: presentationData.theme, text: presentationData.strings.Channel_About_Help)) + + let messagesShouldHaveSignatures:Bool + switch peer.info { + case let .broadcast(info): + messagesShouldHaveSignatures = info.flags.contains(.messagesShouldHaveSignatures) + default: + messagesShouldHaveSignatures = false } + + entries.append(.signMessages(theme: presentationData.theme, text: presentationData.strings.Channel_SignMessages, value: messagesShouldHaveSignatures)) + entries.append(.signInfo(theme: presentationData.theme, text: presentationData.strings.Channel_SignMessages_Help)) + } else { + if let about = cachedChannelData.about, !about.isEmpty { + entries.append(.about(theme: presentationData.theme, text: presentationData.strings.Channel_AboutItem, value: about)) + } + } + + + } + + + + if let cachedChannelData = view.cachedData as? CachedChannelData { + if state.editingState == nil && canEditMembers { if peer.adminRights != nil || peer.flags.contains(.isCreator) { - if let adminCount = cachedChannelData.participantsSummary.adminCount { - entries.append(.admins(theme: presentationData.theme, text: presentationData.strings.Channel_Info_Management, value: "\(adminCount)")) - } - if let memberCount = cachedChannelData.participantsSummary.memberCount { - entries.append(.members(theme: presentationData.theme, text: presentationData.strings.Channel_Info_Members, value: "\(memberCount)")) - } + let adminCount = cachedChannelData.participantsSummary.adminCount ?? 0 + entries.append(.admins(theme: presentationData.theme, text: presentationData.strings.Channel_Info_Management, value: "\(adminCount == 0 ? "" : "\(adminCount)")")) + + let bannedCount = cachedChannelData.participantsSummary.kickedCount ?? 0 + entries.append(.banned(theme: presentationData.theme, text: presentationData.strings.Channel_Info_Banned, value: "\(bannedCount == 0 ? "" : "\(bannedCount)")")) + + let memberCount = cachedChannelData.participantsSummary.memberCount ?? 0 + entries.append(.members(theme: presentationData.theme, text: presentationData.strings.Channel_Info_Members, value: "\(memberCount == 0 ? "" : "\(memberCount)")")) + } } } @@ -461,9 +522,9 @@ private func channelInfoEntries(account: Account, presentationData: Presentation } if peer.flags.contains(.isCreator) { - if state.editingState != nil { - entries.append(ChannelInfoEntry.deleteChannel(theme: presentationData.theme, text: presentationData.strings.ChannelInfo_DeleteChannel)) - } + //if state.editingState != nil { + entries.append(ChannelInfoEntry.deleteChannel(theme: presentationData.theme, text: presentationData.strings.ChannelInfo_DeleteChannel)) + //} } else { entries.append(ChannelInfoEntry.report(theme: presentationData.theme, text: presentationData.strings.ReportPeer_Report)) if peer.participationStatus == .member { @@ -762,7 +823,7 @@ public func channelInfoController(account: Account, peerId: PeerId) -> ViewContr ActionSheetItemGroup(items: [ ActionSheetTextItem(title: presentationData.strings.ChannelInfo_DeleteChannelConfirmation), ActionSheetButtonItem(title: presentationData.strings.ChannelInfo_DeleteChannel, color: .destructive, action: { - actionsDisposable.add((deleteChannel(account: account, peerId: peerId) + actionsDisposable.add((removePeerChat(postbox: account.postbox, peerId: peerId, reportChatSpam: false) |> deliverOnMainQueue).start(completed: { popToRootControllerImpl?() })) @@ -779,6 +840,8 @@ public func channelInfoController(account: Account, peerId: PeerId) -> ViewContr displayContextMenuImpl?(tag, text) }, aboutLinkAction: { action, itemLink in aboutLinkActionImpl?(action, itemLink) + }, toggleSignatures: { enabled in + actionsDisposable.add(toggleShouldChannelMessagesSignatures(account: account, peerId: peerId, enabled: enabled).start()) }) let globalNotificationsKey: PostboxViewKey = .preferences(keys: Set([PreferencesKeys.globalNotifications])) diff --git a/TelegramUI/ChannelMembersController.swift b/TelegramUI/ChannelMembersController.swift index bc0adce059..95273a6a4d 100644 --- a/TelegramUI/ChannelMembersController.swift +++ b/TelegramUI/ChannelMembersController.swift @@ -11,13 +11,14 @@ private final class ChannelMembersControllerArguments { let setPeerIdWithRevealedOptions: (PeerId?, PeerId?) -> Void let removePeer: (PeerId) -> Void let openPeer: (Peer) -> Void - - init(account: Account, addMember: @escaping () -> Void, setPeerIdWithRevealedOptions: @escaping (PeerId?, PeerId?) -> Void, removePeer: @escaping (PeerId) -> Void, openPeer: @escaping (Peer) -> Void) { + let inviteViaLink:()->Void + init(account: Account, addMember: @escaping () -> Void, setPeerIdWithRevealedOptions: @escaping (PeerId?, PeerId?) -> Void, removePeer: @escaping (PeerId) -> Void, openPeer: @escaping (Peer) -> Void, inviteViaLink:@escaping()->Void) { self.account = account self.addMember = addMember self.setPeerIdWithRevealedOptions = setPeerIdWithRevealedOptions self.removePeer = removePeer self.openPeer = openPeer + self.inviteViaLink = inviteViaLink } } @@ -60,11 +61,12 @@ private enum ChannelMembersEntryStableId: Hashable { private enum ChannelMembersEntry: ItemListNodeEntry { case addMember(PresentationTheme, String) case addMemberInfo(PresentationTheme, String) + case inviteLink(PresentationTheme, String) case peerItem(Int32, PresentationTheme, PresentationStrings, RenderedChannelParticipant, ItemListPeerItemEditing, Bool) var section: ItemListSectionId { switch self { - case .addMember, .addMemberInfo: + case .addMember, .addMemberInfo, .inviteLink: return ChannelMembersSection.addMembers.rawValue case .peerItem: return ChannelMembersSection.peers.rawValue @@ -77,6 +79,8 @@ private enum ChannelMembersEntry: ItemListNodeEntry { return .index(0) case .addMemberInfo: return .index(1) + case .inviteLink: + return .index(2) case let .peerItem(_, _, _, participant, _, _): return .peer(participant.peer.id) } @@ -96,6 +100,12 @@ private enum ChannelMembersEntry: ItemListNodeEntry { } else { return false } + case let .inviteLink(lhsTheme, lhsText): + if case let .inviteLink(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText { + return true + } else { + return false + } case let .peerItem(lhsIndex, lhsTheme, lhsStrings, lhsParticipant, lhsEditing, lhsEnabled): if case let .peerItem(rhsIndex, rhsTheme, rhsStrings, rhsParticipant, rhsEditing, rhsEnabled) = rhs { if lhsIndex != rhsIndex { @@ -127,18 +137,26 @@ private enum ChannelMembersEntry: ItemListNodeEntry { switch lhs { case .addMember: return true + case .inviteLink: + switch rhs { + case .addMember: + return false + default: + return true + } case .addMemberInfo: switch rhs { - case .addMember: + case .addMember, .inviteLink: return false default: return true } + case let .peerItem(index, _, _, _, _, _): switch rhs { case let .peerItem(rhsIndex, _, _, _, _, _): return index < rhsIndex - case .addMember, .addMemberInfo: + case .addMember, .addMemberInfo, .inviteLink: return false } } @@ -150,6 +168,10 @@ private enum ChannelMembersEntry: ItemListNodeEntry { return ItemListActionItem(theme: theme, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: { arguments.addMember() }) + case let .inviteLink(theme, text): + return ItemListActionItem(theme: theme, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: { + arguments.inviteViaLink() + }) case let .addMemberInfo(theme, text): return ItemListTextItem(theme: theme, text: .plain(text), sectionId: self.section) case let .peerItem(_, theme, strings, participant, editing, enabled): @@ -212,8 +234,18 @@ private func ChannelMembersControllerEntries(account: Account, presentationData: var entries: [ChannelMembersEntry] = [] if let participants = participants { - entries.append(.addMember(presentationData.theme, presentationData.strings.Channel_Members_AddMembers)) - entries.append(.addMemberInfo(presentationData.theme, presentationData.strings.Channel_Members_AddMembersHelp)) + + var canAddMember: Bool = false + if let peer = view.peers[view.peerId] as? TelegramChannel { + canAddMember = peer.hasAdminRights(.canInviteUsers) + } + + if canAddMember { + entries.append(.addMember(presentationData.theme, presentationData.strings.Channel_Members_AddMembers)) + entries.append(.inviteLink(presentationData.theme, presentationData.strings.Channel_Members_InviteLink)) + entries.append(.addMemberInfo(presentationData.theme, presentationData.strings.Channel_Members_AddMembersHelp)) + } + var index: Int32 = 0 for participant in participants.sorted(by: { lhs, rhs in @@ -286,14 +318,26 @@ public func channelMembersController(account: Account, peerId: PeerId) -> ViewCo return .single(false) } }) - confirmationImpl = { [weak contactsController] peerId in - return account.postbox.loadedPeerWithId(peerId) + confirmationImpl = { [weak contactsController] selectedId in + return combineLatest(account.postbox.loadedPeerWithId(selectedId), account.postbox.loadedPeerWithId(peerId)) |> deliverOnMainQueue - |> mapToSignal { peer in + |> mapToSignal { peer, channelPeer in let result = ValuePromise() + if let contactsController = contactsController { let presentationData = account.telegramApplicationContext.currentPresentationData.with { $0 } - let alertController = standardTextAlertController(theme: AlertControllerTheme(presentationTheme: presentationData.theme), title: nil, text: presentationData.strings.GroupInfo_AddParticipantConfirmation(peer.displayTitle).0, actions: [ + let confirmationText: String + if let channel = channelPeer as? TelegramChannel { + switch channel.info { + case .broadcast: + confirmationText = presentationData.strings.ChannelInfo_AddParticipantConfirmation(peer.displayTitle).0 + case .group: + confirmationText = presentationData.strings.GroupInfo_AddParticipantConfirmation(peer.displayTitle).0 + } + } else { + confirmationText = presentationData.strings.GroupInfo_AddParticipantConfirmation(peer.displayTitle).0 + } + let alertController = standardTextAlertController(theme: AlertControllerTheme(presentationTheme: presentationData.theme), title: nil, text: confirmationText, actions: [ TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: { result.set(false) }), @@ -397,6 +441,8 @@ public func channelMembersController(account: Account, peerId: PeerId) -> ViewCo if let controller = peerInfoController(account: account, peer: peer) { pushControllerImpl?(controller) } + }, inviteViaLink: { + presentControllerImpl?(channelVisibilityController(account: account, peerId: peerId, mode: .privateLink), ViewControllerPresentationArguments(presentationAnimation: .modalSheet)) }) let peerView = account.viewTracker.peerView(peerId) diff --git a/TelegramUI/ChannelVisibilityController.swift b/TelegramUI/ChannelVisibilityController.swift index 3aa547062f..a68c7c0dce 100644 --- a/TelegramUI/ChannelVisibilityController.swift +++ b/TelegramUI/ChannelVisibilityController.swift @@ -239,7 +239,9 @@ private enum ChannelVisibilityEntry: ItemListNodeEntry { case let .typeInfo(theme, text): return ItemListTextItem(theme: theme, text: .plain(text), sectionId: self.section) case let .publicLinkAvailability(theme, text, value): - return ItemListActivityTextItem(displayActivity: value, theme: theme, text: NSAttributedString(string: text, textColor: value ? theme.list.freeTextColor : theme.list.freeTextErrorColor), sectionId: self.section) + let attr = NSMutableAttributedString(string: text, textColor: value ? theme.list.freeTextColor : theme.list.freeTextErrorColor) + attr.addAttribute(.font, value: Font.regular(13), range: NSMakeRange(0, attr.length)) + return ItemListActivityTextItem(displayActivity: value, theme: theme, text: attr, sectionId: self.section) case let .privateLink(theme, text, value): return ItemListActionItem(theme: theme, title: text, kind: value != nil ? .neutral : .disabled, alignment: .natural, sectionId: self.section, style: .blocks, action: { if let value = value { @@ -710,10 +712,11 @@ public func channelVisibilityController(account: Account, peerId: PeerId, mode: return state.withUpdatedRevokingPeerId(nil) } }, completed: { - updateState { state in - return state.withUpdatedRevokingPeerId(nil) - } - peersDisablingAddressNameAssignment.set(.single([])) + peersDisablingAddressNameAssignment.set(.single([]) |> delay(0.2, queue: Queue.mainQueue()) |> afterNext { _ in + updateState { state in + return state.withUpdatedRevokingPeerId(nil) + } + }) })) }, copyPrivateLink: { let _ = (account.postbox.transaction { transaction -> String? in @@ -816,32 +819,42 @@ public func channelVisibilityController(account: Account, peerId: PeerId, mode: var updatedAddressNameValue: String? updateState { state in updatedAddressNameValue = updatedAddressName(state: state, peer: peer) - - if updatedAddressNameValue != nil { - return state.withUpdatedUpdatingAddressName(true) - } else { - return state - } + return state } if let updatedAddressNameValue = updatedAddressNameValue { - updateAddressNameDisposable.set((updateAddressName(account: account, domain: .peer(peerId), name: updatedAddressNameValue.isEmpty ? nil : updatedAddressNameValue) - |> deliverOnMainQueue).start(error: { _ in + + 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: { + updateState { state in - return state.withUpdatedUpdatingAddressName(false) - } - }, completed: { - updateState { state in - return state.withUpdatedUpdatingAddressName(false) + return state.withUpdatedUpdatingAddressName(true) } - switch mode { - case .initialSetup: - nextImpl?() - case .generic, .privateLink: - dismissImpl?() - } - })) + updateAddressNameDisposable.set((updateAddressName(account: account, domain: .peer(peerId), name: updatedAddressNameValue.isEmpty ? nil : updatedAddressNameValue) |> timeout(10, queue: Queue.mainQueue(), alternate: .fail(.generic)) + |> deliverOnMainQueue).start(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) + + }, completed: { + updateState { state in + return state.withUpdatedUpdatingAddressName(false) + } + + switch mode { + case .initialSetup: + nextImpl?() + case .generic, .privateLink: + dismissImpl?() + } + })) + + })]) + + presentControllerImpl?(confirm, nil) + + } else { switch mode { case .initialSetup: diff --git a/TelegramUI/ChatController.swift b/TelegramUI/ChatController.swift index aa05cfb169..c8db2e7ecd 100644 --- a/TelegramUI/ChatController.swift +++ b/TelegramUI/ChatController.swift @@ -4564,7 +4564,7 @@ public final class ChatController: TelegramController, UIViewControllerPreviewin if options.contains(.deleteGlobally) { let globalTitle: String if isChannel { - globalTitle = self.presentationData.strings.Common_Delete + globalTitle = self.presentationData.strings.Conversation_DeleteMessagesForEveryone } else if let personalPeerName = personalPeerName { globalTitle = self.presentationData.strings.Conversation_DeleteMessagesFor(personalPeerName).0 } else { diff --git a/TelegramUI/ChatControllerNode.swift b/TelegramUI/ChatControllerNode.swift index c65976f92f..73b84f5a1e 100644 --- a/TelegramUI/ChatControllerNode.swift +++ b/TelegramUI/ChatControllerNode.swift @@ -1620,7 +1620,9 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { contextMenuController?.dismiss() }) self.messageActionSheetController = (controller, stableId) - self.controllerInteraction.presentGlobalOverlayController(controller, nil) + if let sheetActions = sheetActions, !sheetActions.isEmpty { + self.controllerInteraction.presentGlobalOverlayController(controller, nil) + } animateIn = true } } diff --git a/TelegramUI/ChatInterfaceStateContextMenus.swift b/TelegramUI/ChatInterfaceStateContextMenus.swift index cd27eceb2e..75a93bc21e 100644 --- a/TelegramUI/ChatInterfaceStateContextMenus.swift +++ b/TelegramUI/ChatInterfaceStateContextMenus.swift @@ -11,6 +11,8 @@ private struct MessageContextMenuData { let canReply: Bool let canPin: Bool let canEdit: Bool + let canSelect: Bool + let canContextDelete: Bool let resourceStatus: MediaResourceStatus? let messageActions: ChatAvailableMessageActions } @@ -32,7 +34,7 @@ func canReplyInChat(_ chatPresentationInterfaceState: ChatPresentationInterfaceS case .broadcast: canReply = channel.hasAdminRights([.canPostMessages]) case .group: - canReply = true + canReply = !channel.hasBannedRights(.banSendMessages) } } } else if let group = peer as? TelegramGroup { @@ -176,30 +178,49 @@ func contextMenuForChatPresentationIntefaceState(chatPresentationInterfaceState: } } - var canReply = false + var canReply = canReplyInChat(chatPresentationInterfaceState) var canPin = false + let canSelect = !isAction + + var canDeleteMessage: Bool = false + + let message = messages[0] + if let channel = message.peers[message.id.peerId] as? TelegramChannel { + if case .broadcast = channel.info { + if !message.flags.contains(.Incoming) { + canDeleteMessage = channel.hasAdminRights(.canPostMessages) + } + canDeleteMessage = channel.hasAdminRights(.canDeleteMessages) + } + canDeleteMessage = channel.hasAdminRights(.canDeleteMessages) || !message.flags.contains(.Incoming) + } else if message.peers[message.id.peerId] is TelegramSecretChat { + canDeleteMessage = true + } else { + canDeleteMessage = account.peerId == message.author?.id + } + + let canContextDelete = isAction && canDeleteMessage if messages[0].flags.intersection([.Failed, .Unsent]).isEmpty { switch chatPresentationInterfaceState.chatLocation { case .peer: if let channel = messages[0].peers[messages[0].id.peerId] as? TelegramChannel { switch channel.info { case .broadcast: - canReply = channel.hasAdminRights([.canPostMessages]) if !isAction { canPin = channel.hasAdminRights([.canEditMessages]) } case .group: - canReply = true if !isAction { canPin = channel.hasAdminRights([.canPinMessages]) } } - } else { - canReply = true } case .group: break } + } else { + canReply = false + canPin = false } var loadStickerSaveStatusSignal: Signal = .single(nil) @@ -284,7 +305,7 @@ func contextMenuForChatPresentationIntefaceState(chatPresentationInterfaceState: } } - return MessageContextMenuData(starStatus: stickerSaveStatus, canReply: canReply, canPin: canPin, canEdit: canEdit, resourceStatus: resourceStatus, messageActions: messageActions) + return MessageContextMenuData(starStatus: stickerSaveStatus, canReply: canReply, canPin: canPin, canEdit: canEdit, canSelect: canSelect, canContextDelete: canContextDelete, resourceStatus: resourceStatus, messageActions: messageActions) } return dataSignal |> deliverOnMainQueue |> map { data -> [ChatMessageContextMenuAction] in @@ -362,7 +383,7 @@ func contextMenuForChatPresentationIntefaceState(chatPresentationInterfaceState: } } - if let message = messages.first, message.id.namespace == Namespaces.Message.Cloud, let channel = message.peers[message.id.peerId] as? TelegramChannel, let addressName = channel.addressName { + if let message = messages.first, message.id.namespace == Namespaces.Message.Cloud, let channel = message.peers[message.id.peerId] as? TelegramChannel, let addressName = channel.addressName, !(message.media.first is TelegramMediaAction) { actions.append(.sheet(ChatMessageContextMenuSheetAction(color: .accent, title: chatPresentationInterfaceState.strings.Conversation_ContextMenuCopyLink, action: { UIPasteboard.general.string = "https://t.me/\(addressName)/\(message.id.id)" }))) @@ -398,9 +419,17 @@ func contextMenuForChatPresentationIntefaceState(chatPresentationInterfaceState: } } } - actions.append(.context(ContextMenuAction(content: .text(chatPresentationInterfaceState.strings.Conversation_ContextMenuMore), action: { - interfaceInteraction.beginMessageSelection(messages.map { $0.id }) - }))) + if data.canSelect { + actions.append(.context(ContextMenuAction(content: .text(chatPresentationInterfaceState.strings.Conversation_ContextMenuMore), action: { + interfaceInteraction.beginMessageSelection(messages.map { $0.id }) + }))) + } + if data.canContextDelete { + actions.append(.context(ContextMenuAction(content: .text(chatPresentationInterfaceState.strings.Conversation_ContextMenuDelete), action: { + interfaceInteraction.deleteMessages(messages) + }))) + } + if data.messageActions.options.contains(.forward) { actions.append(.sheet(ChatMessageContextMenuSheetAction(color: .accent, title: chatPresentationInterfaceState.strings.Conversation_ContextMenuForward, action: { @@ -534,9 +563,14 @@ func chatAvailableMessageActions(postbox: Postbox, accountPeerId: PeerId, messag } else { assertionFailure() } + if message.media.first is TelegramMediaAction { + optionsMap[id] = [] + } } else { optionsMap[id]!.insert(.deleteLocally) } + + } if !optionsMap.isEmpty { diff --git a/TelegramUI/ChatListItem.swift b/TelegramUI/ChatListItem.swift index db64d94b15..b4a9637885 100644 --- a/TelegramUI/ChatListItem.swift +++ b/TelegramUI/ChatListItem.swift @@ -1085,7 +1085,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { let authorFrame = self.authorNode.frame transition.updateFrame(node: self.authorNode, frame: CGRect(origin: CGPoint(x: contentRect.origin.x - 1.0, y: authorFrame.origin.y), size: authorFrame.size)) - transition.updateFrame(node: self.inputActivitiesNode, frame: CGRect(origin: CGPoint(x: authorFrame.minX + 1.0, y: self.inputActivitiesNode.frame.minY), size: self.inputActivitiesNode.bounds.size)) + transition.updateFrame(node: self.inputActivitiesNode, frame: CGRect(origin: CGPoint(x: contentRect.origin.x, y: self.inputActivitiesNode.frame.minY), size: self.inputActivitiesNode.bounds.size)) let textFrame = self.textNode.frame transition.updateFrame(node: self.textNode, frame: CGRect(origin: CGPoint(x: contentRect.origin.x - 1.0, y: textFrame.origin.y), size: textFrame.size)) @@ -1096,6 +1096,8 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { let statusFrame = self.statusNode.frame transition.updateFrame(node: self.statusNode, frame: CGRect(origin: CGPoint(x: contentRect.origin.x + contentRect.size.width - dateFrame.size.width - 2.0 - statusFrame.size.width, y: statusFrame.minY), size: statusFrame.size)) + + var nextTitleIconOrigin: CGFloat = contentRect.origin.x + titleFrame.size.width + 3.0 + titleOffset if let verificationIconNode = self.verificationIconNode { diff --git a/TelegramUI/ChatMessageActionItemNode.swift b/TelegramUI/ChatMessageActionItemNode.swift index 8d65a5e54b..4f9175df12 100644 --- a/TelegramUI/ChatMessageActionItemNode.swift +++ b/TelegramUI/ChatMessageActionItemNode.swift @@ -431,7 +431,7 @@ class ChatMessageActionBubbleContentNode: ChatMessageBubbleContentNode { let labelNode: TextNode let filledBackgroundNode: LinkHighlightingNode var linkHighlightingNode: LinkHighlightingNode? - + fileprivate var imageNode: TransformImageNode? private let fetchDisposable = MetaDisposable() required init() { @@ -470,6 +470,22 @@ class ChatMessageActionBubbleContentNode: ChatMessageBubbleContentNode { return (contentProperties, nil, CGFloat.greatestFiniteMagnitude, { constrainedSize, position in let attributedString = attributedServiceMessageString(theme: item.presentationData.theme.theme, strings: item.presentationData.strings, message: item.message, accountPeerId: item.account.peerId) + var image: TelegramMediaImage? + for media in item.message.media { + if let action = media as? TelegramMediaAction { + switch action.action { + case let .photoUpdated(img): + image = img + default: + break + } + } + } + + + + let imageSize = CGSize(width: 70.0, height: 70.0) + let (labelLayout, apply) = makeLabelLayout(TextNodeLayoutArguments(attributedString: attributedString, backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: constrainedSize.width - 32.0, height: CGFloat.greatestFiniteMagnitude), alignment: .center, cutout: nil, insets: UIEdgeInsets())) var labelRects = labelLayout.linesRects() @@ -494,18 +510,46 @@ class ChatMessageActionBubbleContentNode: ChatMessageBubbleContentNode { let backgroundApply = backgroundLayout(item.presentationData.theme.theme.chat.serviceMessage.serviceMessageFillColor, labelRects, 10.0, 10.0, 0.0) - let backgroundSize = CGSize(width: labelLayout.size.width + 8.0 + 8.0, height: labelLayout.size.height + 4.0) + var backgroundSize = CGSize(width: labelLayout.size.width + 8.0 + 8.0, height: labelLayout.size.height + 4.0) let layoutInsets = UIEdgeInsets(top: 4.0, left: 0.0, bottom: 4.0, right: 0.0) + + if let _ = image { + backgroundSize.height += imageSize.height + 10 + } + return (backgroundSize.width, { boundingWidth in return (backgroundSize, { [weak self] animation in if let strongSelf = self { strongSelf.item = item + if let image = image { + let imageNode: TransformImageNode + if let current = strongSelf.imageNode { + imageNode = current + } else { + imageNode = TransformImageNode() + strongSelf.imageNode = imageNode + strongSelf.insertSubnode(imageNode, at: 0) + let arguments = TransformImageArguments(corners: ImageCorners(radius: imageSize.width / 2), imageSize: imageSize, boundingSize: imageSize, intrinsicInsets: UIEdgeInsets()) + let apply = imageNode.asyncLayout()(arguments) + apply() + } + let updateImageSignal = chatMessagePhoto(postbox: item.account.postbox, photoReference: ImageMediaReference.message(message: MessageReference(item.message), media: image)) + strongSelf.fetchDisposable.set(chatMessagePhotoInteractiveFetched(account: item.account, photoReference: .message(message: MessageReference(item.message), media: image)).start()) + + imageNode.setSignal(updateImageSignal) + + imageNode.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((backgroundSize.width - imageSize.width) / 2.0), y: labelLayout.size.height + 10 + 2), size: imageSize) + } else if let imageNode = strongSelf.imageNode { + imageNode.removeFromSupernode() + strongSelf.imageNode = nil + } + let _ = apply() let _ = backgroundApply() - let labelFrame = CGRect(origin: CGPoint(x: 8.0, y: floorToScreenPixels((backgroundSize.height - labelLayout.size.height) / 2.0) - 1.0), size: labelLayout.size) + let labelFrame = CGRect(origin: CGPoint(x: 8.0, y: image != nil ? 2 : floorToScreenPixels((backgroundSize.height - labelLayout.size.height) / 2.0) - 1.0), size: labelLayout.size) strongSelf.labelNode.frame = labelFrame strongSelf.filledBackgroundNode.frame = labelFrame.offsetBy(dx: 0.0, dy: -11.0) } diff --git a/TelegramUI/ChatMessageInteractiveInstantVideoNode.swift b/TelegramUI/ChatMessageInteractiveInstantVideoNode.swift index d1114ad363..f764a9afb2 100644 --- a/TelegramUI/ChatMessageInteractiveInstantVideoNode.swift +++ b/TelegramUI/ChatMessageInteractiveInstantVideoNode.swift @@ -226,21 +226,21 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode { let edited = false let sentViaBot = false - let viewCount: Int? = nil - /*for attribute in item.message.attributes { + var viewCount: Int? = nil + for attribute in item.message.attributes { if let _ = attribute as? EditedMessageAttribute { - edited = true + // edited = true } else if let attribute = attribute as? ViewCountMessageAttribute { viewCount = attribute.count - } else if let _ = attribute as? InlineBotMessageAttribute { - sentViaBot = true - } + }// else if let _ = attribute as? InlineBotMessageAttribute { + // sentViaBot = true + // } } - if let author = item.message.author as? TelegramUser, author.botInfo != nil { - sentViaBot = true - }*/ + // if let author = item.message.author as? TelegramUser, author.botInfo != nil { + // sentViaBot = true + // } - let dateText = stringForMessageTimestampStatus(message: item.message, timeFormat: item.presentationData.timeFormat, strings: item.presentationData.strings, format: .minimal) + let dateText = stringForMessageTimestampStatus(message: item.message, timeFormat: item.presentationData.timeFormat, strings: item.presentationData.strings, format: .regular) let (dateAndStatusSize, dateAndStatusApply) = makeDateAndStatusLayout(item.presentationData.theme, item.presentationData.strings, edited && !sentViaBot, viewCount, dateText, statusType, CGSize(width: width, height: CGFloat.greatestFiniteMagnitude)) diff --git a/TelegramUI/ChatRecentActionsControllerNode.swift b/TelegramUI/ChatRecentActionsControllerNode.swift index be5b540722..4e61d92100 100644 --- a/TelegramUI/ChatRecentActionsControllerNode.swift +++ b/TelegramUI/ChatRecentActionsControllerNode.swift @@ -542,14 +542,17 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode { strongSelf.emptyNode.alpha = displayEmptyNode ? 1.0 : 0.0 strongSelf.emptyNode.layer.animateAlpha(from: displayEmptyNode ? 0.0 : 1.0, to: displayEmptyNode ? 1.0 : 0.0, duration: 0.25) + + let hasFilter: Bool = strongSelf.filter.events != .all || strongSelf.filter.query != nil + if displayEmptyNode { var text: String = "" - if let query = strongSelf.filter.query { + if let query = strongSelf.filter.query, hasFilter { text = strongSelf.presentationData.strings.Channel_AdminLog_EmptyFilterQueryText(query).0 } else { - text = strongSelf.presentationData.strings.Channel_AdminLog_EmptyFilterText + text = strongSelf.presentationData.strings.Channel_AdminLog_EmptyText } - strongSelf.emptyNode.setup(title: strongSelf.presentationData.strings.Channel_AdminLog_EmptyFilterTitle, text: text) + strongSelf.emptyNode.setup(title: hasFilter ? strongSelf.presentationData.strings.Channel_AdminLog_EmptyFilterTitle : strongSelf.presentationData.strings.Channel_AdminLog_EmptyTitle, text: text) } } let isLoading = !displayingResults diff --git a/TelegramUI/ChatRecentActionsHistoryTransition.swift b/TelegramUI/ChatRecentActionsHistoryTransition.swift index c346f42bd2..0f1bb6a08a 100644 --- a/TelegramUI/ChatRecentActionsHistoryTransition.swift +++ b/TelegramUI/ChatRecentActionsHistoryTransition.swift @@ -475,6 +475,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable { for (_, peer) in participant.peers { peers[peer.id] = peer } + peers[participant.peer.id] = participant.peer let action: TelegramMediaActionType action = TelegramMediaActionType.addedMembers(peerIds: [participant.peer.id]) diff --git a/TelegramUI/ItemListActivityTextItem.swift b/TelegramUI/ItemListActivityTextItem.swift index 9f8f1cf91d..86738628a2 100644 --- a/TelegramUI/ItemListActivityTextItem.swift +++ b/TelegramUI/ItemListActivityTextItem.swift @@ -88,8 +88,11 @@ class ItemListActivityTextItemNode: ListViewItemNode { } let titleString = NSMutableAttributedString(attributedString: item.text) - titleString.removeAttribute(NSAttributedStringKey.font, range: NSMakeRange(0, titleString.length)) - titleString.addAttributes([NSAttributedStringKey.font: titleFont], range: NSMakeRange(0, titleString.length)) + let hasFont = titleString.attribute(.font, at: 0, effectiveRange: nil) != nil + if !hasFont { + titleString.removeAttribute(NSAttributedStringKey.font, range: NSMakeRange(0, titleString.length)) + titleString.addAttributes([NSAttributedStringKey.font: titleFont], range: NSMakeRange(0, titleString.length)) + } let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: titleString, backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: params.width - params.rightInset - 20.0 - 22.0, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: TextNodeCutout(position: .TopLeft, size: CGSize(width: activityWidth, height: 4.0)), insets: UIEdgeInsets())) diff --git a/TelegramUI/ItemListMultilineInputItem.swift b/TelegramUI/ItemListMultilineInputItem.swift index 18370e3b66..77d00355fa 100644 --- a/TelegramUI/ItemListMultilineInputItem.swift +++ b/TelegramUI/ItemListMultilineInputItem.swift @@ -216,7 +216,7 @@ class ItemListMultilineInputItemNode: ListViewItemNode, ASEditableTextNodeDelega } let bottomStripeInset: CGFloat switch neighbors.bottom { - case .sameSection(false): + case .sameSection(true): bottomStripeInset = leftInset default: bottomStripeInset = 0.0 diff --git a/TelegramUI/ItemListTextItem.swift b/TelegramUI/ItemListTextItem.swift index e3213b8b71..a40aa84099 100644 --- a/TelegramUI/ItemListTextItem.swift +++ b/TelegramUI/ItemListTextItem.swift @@ -17,14 +17,15 @@ class ItemListTextItem: ListViewItem, ItemListItem { let text: ItemListTextItemText let sectionId: ItemListSectionId let linkAction: ((ItemListTextItemLinkAction) -> Void)? - + let style: ItemListStyle let isAlwaysPlain: Bool = true - init(theme: PresentationTheme, text: ItemListTextItemText, sectionId: ItemListSectionId, linkAction: ((ItemListTextItemLinkAction) -> Void)? = nil) { + init(theme: PresentationTheme, text: ItemListTextItemText, sectionId: ItemListSectionId, linkAction: ((ItemListTextItemLinkAction) -> Void)? = nil, style: ItemListStyle = .blocks) { self.theme = theme self.text = text self.sectionId = sectionId self.linkAction = linkAction + self.style = style } func nodeConfiguredForParams(async: @escaping (@escaping () -> Void) -> Void, params: ListViewItemLayoutParams, previousItem: ListViewItem?, nextItem: ListViewItem?, completion: @escaping (ListViewItemNode, @escaping () -> (Signal?, () -> Void)) -> Void) { @@ -95,7 +96,13 @@ class ItemListTextItemNode: ListViewItemNode { let makeTitleLayout = TextNode.asyncLayout(self.titleNode) return { item, params, neighbors in - let leftInset: CGFloat = 15.0 + params.leftInset + var leftInset: CGFloat = 15.0 + params.leftInset + switch item.style { + case .plain: + leftInset += 20 + case .blocks: + break + } let verticalInset: CGFloat = 7.0 let attributedText: NSAttributedString diff --git a/TelegramUI/PresentationStrings.swift b/TelegramUI/PresentationStrings.swift index 8fef993e4f..a9d549a2fd 100644 --- a/TelegramUI/PresentationStrings.swift +++ b/TelegramUI/PresentationStrings.swift @@ -3273,6 +3273,11 @@ public final class PresentationStrings { public func ChannelInfo_ChannelForbidden(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(_ChannelInfo_ChannelForbidden, self._ChannelInfo_ChannelForbidden_r, [_0]) } + private let _ChannelInfo_AddParticipantConfirmation: String + private let _ChannelInfo_AddParticipantConfirmation_r: [(Int, NSRange)] + public func ChannelInfo_AddParticipantConfirmation(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(_ChannelInfo_AddParticipantConfirmation, self._ChannelInfo_AddParticipantConfirmation_r, [_0]) + } public let Conversation_ShareMyContactInfo: String public let SocksProxySetup_UsernamePlaceholder: String private let _CHANNEL_MESSAGE_GEO: String @@ -7732,6 +7737,8 @@ public final class PresentationStrings { self._PINNED_ROUND_r = extractArgumentRanges(self._PINNED_ROUND) self._ChannelInfo_ChannelForbidden = getValue(dict, "ChannelInfo.ChannelForbidden") self._ChannelInfo_ChannelForbidden_r = extractArgumentRanges(self._ChannelInfo_ChannelForbidden) + self._ChannelInfo_AddParticipantConfirmation = getValue(dict, "ChannelInfo.AddParticipantConfirmation") + self._ChannelInfo_AddParticipantConfirmation_r = extractArgumentRanges(self._ChannelInfo_AddParticipantConfirmation) self.Conversation_ShareMyContactInfo = getValue(dict, "Conversation.ShareMyContactInfo") self.SocksProxySetup_UsernamePlaceholder = getValue(dict, "SocksProxySetup.UsernamePlaceholder") self._CHANNEL_MESSAGE_GEO = getValue(dict, "CHANNEL_MESSAGE_GEO") diff --git a/TelegramUI/StickerResources.swift b/TelegramUI/StickerResources.swift index 242fdfe4a3..8e6d46923a 100644 --- a/TelegramUI/StickerResources.swift +++ b/TelegramUI/StickerResources.swift @@ -43,7 +43,7 @@ private func chatMessageStickerDatas(account: Account, file: TelegramMediaFile, return .single((nil, loadedData, true)) } else { - let fullSizeData = account.postbox.mediaBox.cachedResourceRepresentation(file.resource, representation: CachedStickerAJpegRepresentation(size: small ? CGSize(width: 160.0, height: 160.0) : nil), complete: false) |> map { next in + let fullSizeData = account.postbox.mediaBox.cachedResourceRepresentation(file.resource, representation: CachedStickerAJpegRepresentation(size: small ? CGSize(width: 160.0, height: 160.0) : nil), complete: true) |> map { next in return (next.size == 0 ? nil : try? Data(contentsOf: URL(fileURLWithPath: next.path), options: .mappedIfSafe), next.complete) } @@ -187,7 +187,7 @@ func chatMessageSticker(account: Account, file: TelegramMediaFile, small: Bool, let mask = CGImage(maskWidth: cgImageAlpha.width, height: cgImageAlpha.height, bitsPerComponent: cgImageAlpha.bitsPerComponent, bitsPerPixel: cgImageAlpha.bitsPerPixel, bytesPerRow: cgImageAlpha.bytesPerRow, provider: cgImageAlpha.dataProvider!, decode: nil, shouldInterpolate: true) c.draw(cgImage.masking(mask!)!, in: fittedRect) - } + } } return context From fb786425badde70ee82adea6d63560ad49879f54 Mon Sep 17 00:00:00 2001 From: overtake <> Date: Sat, 1 Sep 2018 00:07:02 +0300 Subject: [PATCH 2/3] some fixes --- .../ArhivedStickerPacksController.swift | 4 +- TelegramUI/ChatMessageActionItemNode.swift | 36 +++++++++------ .../ChatMessageInteractiveMediaNode.swift | 6 +++ TelegramUI/ChatMessageStickerItemNode.swift | 6 +-- .../InstalledStickerPacksController.swift | 44 ++++++++++++------- TelegramUI/SettingsController.swift | 25 ++++++----- TelegramUI/StickerResources.swift | 4 +- 7 files changed, 75 insertions(+), 50 deletions(-) diff --git a/TelegramUI/ArhivedStickerPacksController.swift b/TelegramUI/ArhivedStickerPacksController.swift index e61af6e165..ecc80c2344 100644 --- a/TelegramUI/ArhivedStickerPacksController.swift +++ b/TelegramUI/ArhivedStickerPacksController.swift @@ -221,7 +221,7 @@ private func archivedStickerPacksControllerEntries(presentationData: Presentatio return entries } -public func archivedStickerPacksController(account: Account) -> ViewController { +public func archivedStickerPacksController(account: Account, archived: [ArchivedStickerPackItem]?) -> ViewController { let statePromise = ValuePromise(ArchivedStickerPacksControllerState(), ignoreRepeated: true) let stateValue = Atomic(value: ArchivedStickerPacksControllerState()) let updateState: ((ArchivedStickerPacksControllerState) -> ArchivedStickerPacksControllerState) -> Void = { f in @@ -239,7 +239,7 @@ public func archivedStickerPacksController(account: Account) -> ViewController { actionsDisposable.add(removePackDisposables) let stickerPacks = Promise<[ArchivedStickerPackItem]?>() - stickerPacks.set(.single(nil) |> then(archivedStickerPacks(account: account) |> map(Optional.init))) + stickerPacks.set(.single(archived) |> then(archivedStickerPacks(account: account) |> map(Optional.init))) let installedStickerPacks = Promise() installedStickerPacks.set(account.postbox.combinedView(keys: [.itemCollectionIds(namespaces: [Namespaces.ItemCollection.CloudStickerPacks])])) diff --git a/TelegramUI/ChatMessageActionItemNode.swift b/TelegramUI/ChatMessageActionItemNode.swift index 4f9175df12..ced7ac821d 100644 --- a/TelegramUI/ChatMessageActionItemNode.swift +++ b/TelegramUI/ChatMessageActionItemNode.swift @@ -114,6 +114,7 @@ private func universalServiceMessageString(theme: PresentationTheme?, strings: P case .pinnedMessageUpdated: enum PinnnedMediaType { case text(String) + case game case photo case video case round @@ -137,6 +138,10 @@ private func universalServiceMessageString(theme: PresentationTheme?, strings: P if let pinnedMessage = pinnedMessage { type = .text(pinnedMessage.text) inner: for media in pinnedMessage.media { + if media is TelegramMediaGame { + type = .game + break inner + } if let _ = media as? TelegramMediaImage { type = .photo } else if let file = media as? TelegramMediaFile { @@ -157,19 +162,19 @@ private func universalServiceMessageString(theme: PresentationTheme?, strings: P if isVoice { type = .audio } else { - let descriptionString: String - if let title = title, let performer = performer, !title.isEmpty, !performer.isEmpty { - descriptionString = title + " — " + performer - } else if let title = title, !title.isEmpty { - descriptionString = title - } else if let performer = performer, !performer.isEmpty { - descriptionString = performer - } else if let fileName = file.fileName { - descriptionString = fileName - } else { - descriptionString = strings.Message_Audio - } - type = .text(descriptionString) +// let descriptionString: String +// if let title = title, let performer = performer, !title.isEmpty, !performer.isEmpty { +// descriptionString = title + " — " + performer +// } else if let title = title, !title.isEmpty { +// descriptionString = title +// } else if let performer = performer, !performer.isEmpty { +// descriptionString = performer +// } else if let fileName = file.fileName { +// descriptionString = strings.Message_File +// } else { +// descriptionString = strings.Message_Audio +// } + type = .file } break inner case .Sticker: @@ -199,6 +204,8 @@ private func universalServiceMessageString(theme: PresentationTheme?, strings: P clippedText = "\(clippedText[...clippedText.index(clippedText.startIndex, offsetBy: 14)])..." } attributedString = addAttributesToStringWithRanges(strings.Notification_PinnedTextMessage(authorName, clippedText), body: bodyAttributes, argumentAttributes: peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: [(0, message.author?.id)])) + case .game: + attributedString = addAttributesToStringWithRanges(strings.PINNED_GAME(authorName), body: bodyAttributes, argumentAttributes: peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: [(0, message.author?.id)])) case .photo: attributedString = addAttributesToStringWithRanges(strings.Notification_PinnedPhotoMessage(authorName), body: bodyAttributes, argumentAttributes: peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: [(0, message.author?.id)])) case .video: @@ -534,9 +541,10 @@ class ChatMessageActionBubbleContentNode: ChatMessageBubbleContentNode { let arguments = TransformImageArguments(corners: ImageCorners(radius: imageSize.width / 2), imageSize: imageSize, boundingSize: imageSize, intrinsicInsets: UIEdgeInsets()) let apply = imageNode.asyncLayout()(arguments) apply() + + strongSelf.fetchDisposable.set(chatMessagePhotoInteractiveFetched(account: item.account, photoReference: .message(message: MessageReference(item.message), media: image)).start()) } let updateImageSignal = chatMessagePhoto(postbox: item.account.postbox, photoReference: ImageMediaReference.message(message: MessageReference(item.message), media: image)) - strongSelf.fetchDisposable.set(chatMessagePhotoInteractiveFetched(account: item.account, photoReference: .message(message: MessageReference(item.message), media: image)).start()) imageNode.setSignal(updateImageSignal) diff --git a/TelegramUI/ChatMessageInteractiveMediaNode.swift b/TelegramUI/ChatMessageInteractiveMediaNode.swift index 4526c4b590..06fe787150 100644 --- a/TelegramUI/ChatMessageInteractiveMediaNode.swift +++ b/TelegramUI/ChatMessageInteractiveMediaNode.swift @@ -88,6 +88,12 @@ final class ChatMessageInteractiveMediaNode: ASTransformNode { let _ = account.postbox.transaction({ transaction -> Void in deleteMessages(transaction: transaction, mediaBox: account.postbox.mediaBox, ids: [message.id]) }).start() + } else if let media = media, let account = self.account, let message = message { + if let media = media as? TelegramMediaFile { + messageMediaFileCancelInteractiveFetch(account: account, messageId: message.id, file: media) + } else if let media = media as? TelegramMediaImage, let resource = largestImageRepresentation(media.representations)?.resource { + messageMediaImageCancelInteractiveFetch(account: account, messageId: message.id, image: media, resource: resource) + } } if let cancel = self.fetchControls.with({ return $0?.cancel }) { cancel() diff --git a/TelegramUI/ChatMessageStickerItemNode.swift b/TelegramUI/ChatMessageStickerItemNode.swift index b9f2975f8c..ca924cb2e3 100644 --- a/TelegramUI/ChatMessageStickerItemNode.swift +++ b/TelegramUI/ChatMessageStickerItemNode.swift @@ -78,14 +78,12 @@ class ChatMessageStickerItemNode: ChatMessageItemView { for media in item.message.media { if let telegramFile = media as? TelegramMediaFile { - if self.telegramFile != telegramFile { - self.telegramFile = telegramFile - + if self.telegramFile == nil || !telegramFile.isSemanticallyEqual(to: self.telegramFile!) { let signal = chatMessageSticker(account: item.account, file: telegramFile, small: false) self.imageNode.setSignal(signal) self.fetchDisposable.set(freeMediaFileInteractiveFetched(account: item.account, fileReference: .message(message: MessageReference(item.message), media: telegramFile)).start()) } - + self.telegramFile = telegramFile break } } diff --git a/TelegramUI/InstalledStickerPacksController.swift b/TelegramUI/InstalledStickerPacksController.swift index 533121fd1a..98c1a0a0a1 100644 --- a/TelegramUI/InstalledStickerPacksController.swift +++ b/TelegramUI/InstalledStickerPacksController.swift @@ -13,10 +13,10 @@ private final class InstalledStickerPacksControllerArguments { let openStickersBot: () -> Void let openMasks: () -> Void let openFeatured: () -> Void - let openArchived: () -> Void + let openArchived: ([ArchivedStickerPackItem]?) -> Void let openSuggestOptions: () -> Void - init(account: Account, openStickerPack: @escaping (StickerPackCollectionInfo) -> Void, setPackIdWithRevealedOptions: @escaping (ItemCollectionId?, ItemCollectionId?) -> Void, removePack: @escaping (ItemCollectionId) -> Void, openStickersBot: @escaping () -> Void, openMasks: @escaping () -> Void, openFeatured: @escaping () -> Void, openArchived: @escaping () -> Void, openSuggestOptions: @escaping () -> Void) { + init(account: Account, openStickerPack: @escaping (StickerPackCollectionInfo) -> Void, setPackIdWithRevealedOptions: @escaping (ItemCollectionId?, ItemCollectionId?) -> Void, removePack: @escaping (ItemCollectionId) -> Void, openStickersBot: @escaping () -> Void, openMasks: @escaping () -> Void, openFeatured: @escaping () -> Void, openArchived: @escaping ([ArchivedStickerPackItem]?) -> Void, openSuggestOptions: @escaping () -> Void) { self.account = account self.openStickerPack = openStickerPack self.setPackIdWithRevealedOptions = setPackIdWithRevealedOptions @@ -68,7 +68,7 @@ private enum InstalledStickerPacksEntryId: Hashable { private enum InstalledStickerPacksEntry: ItemListNodeEntry { case suggestOptions(PresentationTheme, String, String) case trending(PresentationTheme, String, Int32) - case archived(PresentationTheme, String) + case archived(PresentationTheme, String, Int32, [ArchivedStickerPackItem]?) case masks(PresentationTheme, String) case packsTitle(PresentationTheme, String) case pack(Int32, PresentationTheme, PresentationStrings, StickerPackCollectionInfo, StickerPackItem?, String, Bool, ItemListStickerPackItemEditing) @@ -122,8 +122,8 @@ private enum InstalledStickerPacksEntry: ItemListNodeEntry { } else { return false } - case let .archived(lhsTheme, lhsCount): - if case let .archived(rhsTheme, rhsCount) = rhs, lhsTheme === rhsTheme, lhsCount == rhsCount { + case let .archived(lhsTheme, lhsText, lhsCount, _): + if case let .archived(rhsTheme, rhsText, rhsCount, _) = rhs, lhsTheme === rhsTheme, lhsCount == rhsCount, lhsText == rhsText { return true } else { return false @@ -243,9 +243,9 @@ private enum InstalledStickerPacksEntry: ItemListNodeEntry { return ItemListDisclosureItem(theme: theme, title: text, label: "", sectionId: self.section, style: .blocks, action: { arguments.openMasks() }) - case let .archived(theme, text): - return ItemListDisclosureItem(theme: theme, title: text, label: "", sectionId: self.section, style: .blocks, action: { - arguments.openArchived() + case let .archived(theme, text, count, archived): + return ItemListDisclosureItem(theme: theme, title: text, label: count == 0 ? "" : "\(count)", sectionId: self.section, style: .blocks, action: { + arguments.openArchived(archived) }) case let .packsTitle(theme, text): return ItemListSectionHeaderItem(theme: theme, text: text, sectionId: self.section) @@ -309,7 +309,7 @@ private func namespaceForMode(_ mode: InstalledStickerPacksControllerMode) -> It } } -private func installedStickerPacksControllerEntries(presentationData: PresentationData, state: InstalledStickerPacksControllerState, mode: InstalledStickerPacksControllerMode, view: CombinedView, featured: [FeaturedStickerPackItem], stickerSettings: StickerSettings) -> [InstalledStickerPacksEntry] { +private func installedStickerPacksControllerEntries(presentationData: PresentationData, state: InstalledStickerPacksControllerState, mode: InstalledStickerPacksControllerMode, view: CombinedView, featured: [FeaturedStickerPackItem], archived: [ArchivedStickerPackItem]?, stickerSettings: StickerSettings) -> [InstalledStickerPacksEntry] { var entries: [InstalledStickerPacksEntry] = [] switch mode { @@ -334,7 +334,9 @@ private func installedStickerPacksControllerEntries(presentationData: Presentati } entries.append(.trending(presentationData.theme, presentationData.strings.StickerPacksSettings_FeaturedPacks, unreadCount)) } - entries.append(.archived(presentationData.theme, presentationData.strings.StickerPacksSettings_ArchivedPacks)) + if let archived = archived, !archived.isEmpty { + entries.append(.archived(presentationData.theme, presentationData.strings.StickerPacksSettings_ArchivedPacks, Int32(archived.count), archived)) + } entries.append(.masks(presentationData.theme, presentationData.strings.MaskStickerSettings_Title)) entries.append(.packsTitle(presentationData.theme, presentationData.strings.StickerPacksSettings_StickerPacksSection)) case .masks: @@ -376,7 +378,7 @@ public enum InstalledStickerPacksControllerMode { case masks } -public func installedStickerPacksController(account: Account, mode: InstalledStickerPacksControllerMode) -> ViewController { +public func installedStickerPacksController(account: Account, mode: InstalledStickerPacksControllerMode, archivedPacks:[ArchivedStickerPackItem]? = nil) -> ViewController { let initialState = InstalledStickerPacksControllerState().withUpdatedEditing(mode == .modal) let statePromise = ValuePromise(initialState, ignoreRepeated: true) let stateValue = Atomic(value: initialState) @@ -434,11 +436,11 @@ public func installedStickerPacksController(account: Account, mode: InstalledSti } })) }, openMasks: { - pushControllerImpl?(installedStickerPacksController(account: account, mode: .masks)) + pushControllerImpl?(installedStickerPacksController(account: account, mode: .masks, archivedPacks: archivedPacks)) }, openFeatured: { pushControllerImpl?(featuredStickerPacksController(account: account)) - }, openArchived: { - pushControllerImpl?(archivedStickerPacksController(account: account)) + }, openArchived: { archived in + pushControllerImpl?(archivedStickerPacksController(account: account, archived: archived)) }, openSuggestOptions: { let presentationData = account.telegramApplicationContext.currentPresentationData.with { $0 } let controller = ActionSheetController(presentationTheme: presentationData.theme) @@ -482,22 +484,30 @@ public func installedStickerPacksController(account: Account, mode: InstalledSti stickerPacks.set(account.postbox.combinedView(keys: [.itemCollectionInfos(namespaces: [namespaceForMode(mode)])])) let featured = Promise<[FeaturedStickerPackItem]>() + let archivedPromise = Promise<[ArchivedStickerPackItem]?>() + switch mode { case .general, .modal: featured.set(account.viewTracker.featuredStickerPacks()) + archivedPromise.set(.single(archivedPacks) |> then(archivedStickerPacks(account: account) |> map(Optional.init))) case .masks: featured.set(.single([])) + archivedPromise.set(.single(nil)) } + var previousPackCount: Int? let stickerSettingsKey = ApplicationSpecificPreferencesKeys.stickerSettings let preferencesKey: PostboxViewKey = .preferences(keys: Set([stickerSettingsKey])) let preferencesView = account.postbox.combinedView(keys: [preferencesKey]) - let signal = combineLatest((account.applicationContext as! TelegramApplicationContext).presentationData, statePromise.get() |> deliverOnMainQueue, stickerPacks.get() |> deliverOnMainQueue, featured.get() |> deliverOnMainQueue, preferencesView |> deliverOnMainQueue) + + + let signal = combineLatest((account.applicationContext as! TelegramApplicationContext).presentationData, statePromise.get() |> deliverOnMainQueue, stickerPacks.get() |> deliverOnMainQueue, combineLatest(featured.get() |> deliverOnMainQueue, archivedPromise.get() |> deliverOnMainQueue), preferencesView |> deliverOnMainQueue) |> deliverOnMainQueue - |> map { presentationData, state, view, featured, preferencesView -> (ItemListControllerState, (ItemListNodeState, InstalledStickerPacksEntry.ItemGenerationArguments)) in + |> map { presentationData, state, view, featuredAndArchived, preferencesView -> (ItemListControllerState, (ItemListNodeState, InstalledStickerPacksEntry.ItemGenerationArguments)) in + var stickerSettings = StickerSettings.defaultSettings if let view = preferencesView.views[preferencesKey] as? PreferencesView { if let value = view.values[stickerSettingsKey] as? StickerSettings { @@ -554,7 +564,7 @@ public func installedStickerPacksController(account: Account, mode: InstalledSti let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(title), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: true) - let listState = ItemListNodeState(entries: installedStickerPacksControllerEntries(presentationData: presentationData, state: state, mode: mode, view: view, featured: featured, stickerSettings: stickerSettings), style: .blocks, animateChanges: previous != nil && packCount != nil && (previous! != 0 && previous! >= packCount! - 10)) + let listState = ItemListNodeState(entries: installedStickerPacksControllerEntries(presentationData: presentationData, state: state, mode: mode, view: view, featured: featuredAndArchived.0, archived: featuredAndArchived.1, stickerSettings: stickerSettings), style: .blocks, animateChanges: previous != nil && packCount != nil && (previous! != 0 && previous! >= packCount! - 10)) return (controllerState, (listState, arguments)) } |> afterDisposed { actionsDisposable.dispose() diff --git a/TelegramUI/SettingsController.swift b/TelegramUI/SettingsController.swift index 0bae4bc1aa..cc3ba26bba 100644 --- a/TelegramUI/SettingsController.swift +++ b/TelegramUI/SettingsController.swift @@ -65,7 +65,7 @@ private enum SettingsEntry: ItemListNodeEntry { case savedMessages(PresentationTheme, UIImage?, String) case recentCalls(PresentationTheme, UIImage?, String) - case stickers(PresentationTheme, UIImage?, String, String) + case stickers(PresentationTheme, UIImage?, String, String, [ArchivedStickerPackItem]?) case notificationsAndSounds(PresentationTheme, UIImage?, String) case privacyAndSecurity(PresentationTheme, UIImage?, String) @@ -193,8 +193,8 @@ private enum SettingsEntry: ItemListNodeEntry { } else { return false } - case let .stickers(lhsTheme, lhsImage, lhsText, lhsValue): - if case let .stickers(rhsTheme, rhsImage, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsImage === rhsImage, lhsText == rhsText, lhsValue == rhsValue { + case let .stickers(lhsTheme, lhsImage, lhsText, lhsValue, _): + if case let .stickers(rhsTheme, rhsImage, rhsText, rhsValue, _) = rhs, lhsTheme === rhsTheme, lhsImage === rhsImage, lhsText == rhsText, lhsValue == rhsValue { return true } else { return false @@ -283,9 +283,9 @@ private enum SettingsEntry: ItemListNodeEntry { return ItemListDisclosureItem(theme: theme, icon: image, title: text, label: "", sectionId: ItemListSectionId(self.section), style: .blocks, action: { arguments.openRecentCalls() }) - case let .stickers(theme, image, text, value): + case let .stickers(theme, image, text, value, archivedPacks): return ItemListDisclosureItem(theme: theme, icon: image, title: text, label: value, sectionId: ItemListSectionId(self.section), style: .blocks, action: { - arguments.pushController(installedStickerPacksController(account: arguments.account, mode: .general)) + arguments.pushController(installedStickerPacksController(account: arguments.account, mode: .general, archivedPacks: archivedPacks)) }) case let .notificationsAndSounds(theme, image, text): return ItemListDisclosureItem(theme: theme, icon: image, title: text, label: "", sectionId: ItemListSectionId(self.section), style: .blocks, action: { @@ -342,7 +342,7 @@ private struct SettingsState: Equatable { } } -private func settingsEntries(presentationData: PresentationData, state: SettingsState, view: PeerView, proxySettings: ProxySettings, unreadTrendingStickerPacks: Int) -> [SettingsEntry] { +private func settingsEntries(presentationData: PresentationData, state: SettingsState, view: PeerView, proxySettings: ProxySettings, unreadTrendingStickerPacks: Int, archivedPacks: [ArchivedStickerPackItem]?) -> [SettingsEntry] { var entries: [SettingsEntry] = [] if let peer = peerViewMainPeer(view) as? TelegramUser { @@ -372,7 +372,7 @@ private func settingsEntries(presentationData: PresentationData, state: Settings entries.append(.savedMessages(presentationData.theme, SettingsItemIcons.savedMessages, presentationData.strings.Settings_SavedMessages)) entries.append(.recentCalls(presentationData.theme, SettingsItemIcons.recentCalls, presentationData.strings.CallSettings_RecentCalls)) - entries.append(.stickers(presentationData.theme, SettingsItemIcons.stickers, presentationData.strings.ChatSettings_Stickers, unreadTrendingStickerPacks == 0 ? "" : "\(unreadTrendingStickerPacks)")) + entries.append(.stickers(presentationData.theme, SettingsItemIcons.stickers, presentationData.strings.ChatSettings_Stickers, unreadTrendingStickerPacks == 0 ? "" : "\(unreadTrendingStickerPacks)", archivedPacks)) entries.append(.notificationsAndSounds(presentationData.theme, SettingsItemIcons.notifications, presentationData.strings.Settings_NotificationsAndSounds)) entries.append(.privacyAndSecurity(presentationData.theme, SettingsItemIcons.security, presentationData.strings.Settings_PrivacySettings)) @@ -601,8 +601,11 @@ public func settingsController(account: Account, accountManager: AccountManager) let peerView = account.viewTracker.peerView(account.peerId) - let signal = combineLatest((account.applicationContext as! TelegramApplicationContext).presentationData, statePromise.get(), peerView, account.postbox.preferencesView(keys: [PreferencesKeys.proxySettings]), account.viewTracker.featuredStickerPacks()) - |> map { presentationData, state, view, preferences, featuredStickerPacks -> (ItemListControllerState, (ItemListNodeState, SettingsEntry.ItemGenerationArguments)) in + let archivedPacks = Promise<[ArchivedStickerPackItem]?>() + archivedPacks.set(.single(nil) |> then(archivedStickerPacks(account: account) |> map(Optional.init))) + + let signal = combineLatest((account.applicationContext as! TelegramApplicationContext).presentationData, statePromise.get(), peerView, account.postbox.preferencesView(keys: [PreferencesKeys.proxySettings]), combineLatest(account.viewTracker.featuredStickerPacks(), archivedPacks.get())) + |> map { presentationData, state, view, preferences, featuredAndArchived -> (ItemListControllerState, (ItemListNodeState, SettingsEntry.ItemGenerationArguments)) in let proxySettings: ProxySettings if let value = preferences.values[PreferencesKeys.proxySettings] as? ProxySettings { proxySettings = value @@ -620,13 +623,13 @@ public func settingsController(account: Account, accountManager: AccountManager) let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(presentationData.strings.Settings_Title), leftNavigationButton: nil, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back)) var unreadTrendingStickerPacks = 0 - for item in featuredStickerPacks { + for item in featuredAndArchived.0 { if item.unread { unreadTrendingStickerPacks += 1 } } - let listState = ItemListNodeState(entries: settingsEntries(presentationData: presentationData, state: state, view: view, proxySettings: proxySettings, unreadTrendingStickerPacks: unreadTrendingStickerPacks), style: .blocks) + let listState = ItemListNodeState(entries: settingsEntries(presentationData: presentationData, state: state, view: view, proxySettings: proxySettings, unreadTrendingStickerPacks: unreadTrendingStickerPacks, archivedPacks: featuredAndArchived.1), style: .blocks) return (controllerState, (listState, arguments)) } |> afterDisposed { diff --git a/TelegramUI/StickerResources.swift b/TelegramUI/StickerResources.swift index 8e6d46923a..242fdfe4a3 100644 --- a/TelegramUI/StickerResources.swift +++ b/TelegramUI/StickerResources.swift @@ -43,7 +43,7 @@ private func chatMessageStickerDatas(account: Account, file: TelegramMediaFile, return .single((nil, loadedData, true)) } else { - let fullSizeData = account.postbox.mediaBox.cachedResourceRepresentation(file.resource, representation: CachedStickerAJpegRepresentation(size: small ? CGSize(width: 160.0, height: 160.0) : nil), complete: true) |> map { next in + let fullSizeData = account.postbox.mediaBox.cachedResourceRepresentation(file.resource, representation: CachedStickerAJpegRepresentation(size: small ? CGSize(width: 160.0, height: 160.0) : nil), complete: false) |> map { next in return (next.size == 0 ? nil : try? Data(contentsOf: URL(fileURLWithPath: next.path), options: .mappedIfSafe), next.complete) } @@ -187,7 +187,7 @@ func chatMessageSticker(account: Account, file: TelegramMediaFile, small: Bool, let mask = CGImage(maskWidth: cgImageAlpha.width, height: cgImageAlpha.height, bitsPerComponent: cgImageAlpha.bitsPerComponent, bitsPerPixel: cgImageAlpha.bitsPerPixel, bytesPerRow: cgImageAlpha.bytesPerRow, provider: cgImageAlpha.dataProvider!, decode: nil, shouldInterpolate: true) c.draw(cgImage.masking(mask!)!, in: fittedRect) - } + } } return context From 25cb418eb3e1bef98f90d5c77c42de1d3f27d0e2 Mon Sep 17 00:00:00 2001 From: overtake <> Date: Sat, 1 Sep 2018 22:28:37 +0300 Subject: [PATCH 3/3] tos and scroll to date first message --- ...orizationSequenceCodeEntryController.swift | 2 +- TelegramUI/ChatController.swift | 21 ++++++++-- TelegramUI/ChatControllerInteraction.swift | 4 +- TelegramUI/ChatHistoryGridNode.swift | 2 +- TelegramUI/ChatHistoryListNode.swift | 4 +- TelegramUI/ChatMessageDateHeader.swift | 21 +++++++--- TelegramUI/ChatMessageItem.swift | 31 +++++++++++++- .../ChatRecentActionsControllerNode.swift | 2 + TelegramUI/OverlayPlayerControllerNode.swift | 1 + .../PeerMediaCollectionController.swift | 1 + TelegramUI/PresentationStrings.swift | 7 ++++ TelegramUI/TermsOfServiceController.swift | 12 ++++-- TelegramUI/TermsOfServiceControllerNode.swift | 42 ++++++------------- TelegramUI/ThemeSettingsChatPreviewItem.swift | 1 + 14 files changed, 102 insertions(+), 49 deletions(-) diff --git a/TelegramUI/AuthorizationSequenceCodeEntryController.swift b/TelegramUI/AuthorizationSequenceCodeEntryController.swift index 45f6e59f25..eef0423adf 100644 --- a/TelegramUI/AuthorizationSequenceCodeEntryController.swift +++ b/TelegramUI/AuthorizationSequenceCodeEntryController.swift @@ -127,7 +127,7 @@ final class AuthorizationSequenceCodeEntryController: ViewController { if let termsOfService = self.termsOfService { var acceptImpl: (() -> Void)? var declineImpl: (() -> Void)? - let controller = TermsOfServiceController(theme: TermsOfServiceControllerTheme(authTheme: self.theme), strings: self.strings, text: termsOfService.text, entities: termsOfService.entities, ageConfirmation: termsOfService.ageConfirmation, signingUp: true, accept: { + let controller = TermsOfServiceController(theme: TermsOfServiceControllerTheme(authTheme: self.theme), strings: self.strings, text: termsOfService.text, entities: termsOfService.entities, ageConfirmation: termsOfService.ageConfirmation, signingUp: true, accept: { _ in acceptImpl?() }, decline: { declineImpl?() diff --git a/TelegramUI/ChatController.swift b/TelegramUI/ChatController.swift index c8db2e7ecd..fe7984db7f 100644 --- a/TelegramUI/ChatController.swift +++ b/TelegramUI/ChatController.swift @@ -814,6 +814,19 @@ public final class ChatController: TelegramController, UIViewControllerPreviewin return canReplyInChat(strongSelf.presentationInterfaceState) } return false + }, navigateToFirstDateMessage: { [weak self] timestamp in + guard let `self` = self else {return} + switch self.chatLocation { + case let .peer(peerId): + self.messageIndexDisposable.set((searchMessageIdByTimestamp(account: self.account, peerId: peerId, timestamp: timestamp - Int32(NSTimeZone.local.secondsFromGMT())) |> deliverOnMainQueue).start(next: { [weak self] messageId in + guard let `self` = self else {return} + if let messageId = messageId { + self.navigateToMessage(from: nil, to: .id(messageId), scrollPosition: .bottom(0)) + } + })) + default: + break + } }, requestMessageUpdate: { [weak self] id in if let strongSelf = self { strongSelf.chatDisplayNode.historyNode.requestMessageUpdate(id) @@ -3750,7 +3763,7 @@ public final class ChatController: TelegramController, UIViewControllerPreviewin self.navigateToMessage(from: nil, to: messageLocation, rememberInStack: false, animated: animated, completion: completion) } - private func navigateToMessage(from fromId: MessageId?, to messageLocation: NavigateToMessageLocation, rememberInStack: Bool = true, animated: Bool = true, completion: (() -> Void)? = nil) { + private func navigateToMessage(from fromId: MessageId?, to messageLocation: NavigateToMessageLocation, scrollPosition: ListViewScrollPosition = .center(.bottom), rememberInStack: Bool = true, animated: Bool = true, completion: (() -> Void)? = nil) { if self.isNodeLoaded { var fromIndex: MessageIndex? @@ -3771,7 +3784,7 @@ public final class ChatController: TelegramController, UIViewControllerPreviewin if let message = self.chatDisplayNode.historyNode.messageInCurrentHistoryView(messageLocation.messageId) { self.loadingMessage.set(false) self.messageIndexDisposable.set(nil) - self.chatDisplayNode.historyNode.scrollToMessage(from: fromIndex, to: MessageIndex(message), animated: animated) + self.chatDisplayNode.historyNode.scrollToMessage(from: fromIndex, to: MessageIndex(message), animated: animated, scrollPosition: scrollPosition) completion?() } else { self.loadingMessage.set(true) @@ -3802,7 +3815,7 @@ public final class ChatController: TelegramController, UIViewControllerPreviewin |> take(1) self.messageIndexDisposable.set((signal |> deliverOnMainQueue).start(next: { [weak self] index in if let strongSelf = self, let index = index { - strongSelf.chatDisplayNode.historyNode.scrollToMessage(from: fromIndex, to: index, animated: animated) + strongSelf.chatDisplayNode.historyNode.scrollToMessage(from: fromIndex, to: index, animated: animated, scrollPosition: scrollPosition) completion?() } }, completed: { [weak self] in @@ -3849,7 +3862,7 @@ public final class ChatController: TelegramController, UIViewControllerPreviewin self.messageIndexDisposable.set((signal |> deliverOnMainQueue).start(next: { [weak self] index in if let strongSelf = self { if let index = index { - strongSelf.chatDisplayNode.historyNode.scrollToMessage(from: fromIndex, to: index, animated: animated) + strongSelf.chatDisplayNode.historyNode.scrollToMessage(from: fromIndex, to: index, animated: animated, scrollPosition: scrollPosition) completion?() } else { (strongSelf.navigationController as? NavigationController)?.pushViewController(ChatController(account: strongSelf.account, chatLocation: .peer(messageLocation.messageId.peerId), messageId: messageLocation.messageId)) diff --git a/TelegramUI/ChatControllerInteraction.swift b/TelegramUI/ChatControllerInteraction.swift index 056558924b..28e931a8ea 100644 --- a/TelegramUI/ChatControllerInteraction.swift +++ b/TelegramUI/ChatControllerInteraction.swift @@ -67,6 +67,7 @@ public final class ChatControllerInteraction { let openSearch: () -> Void let setupReply: (MessageId) -> Void let canSetupReply: (Message) -> Bool + let navigateToFirstDateMessage:(Int32)->Void let requestMessageUpdate: (MessageId) -> Void let cancelInteractiveKeyboardGestures: () -> Void @@ -77,7 +78,7 @@ public final class ChatControllerInteraction { var contextHighlightedState: ChatInterfaceHighlightedState? var automaticMediaDownloadSettings: AutomaticMediaDownloadSettings - init(openMessage: @escaping (Message) -> Bool, openPeer: @escaping (PeerId?, ChatControllerInteractionNavigateToPeer, Message?) -> Void, openPeerMention: @escaping (String) -> Void, openMessageContextMenu: @escaping (Message, ASDisplayNode, CGRect) -> Void, navigateToMessage: @escaping (MessageId, MessageId) -> Void, clickThroughMessage: @escaping () -> Void, toggleMessagesSelection: @escaping ([MessageId], Bool) -> Void, sendMessage: @escaping (String) -> Void, sendSticker: @escaping (FileMediaReference) -> Void, sendGif: @escaping (FileMediaReference) -> Void, requestMessageActionCallback: @escaping (MessageId, MemoryBuffer?, Bool) -> Void, activateSwitchInline: @escaping (PeerId?, String) -> Void, openUrl: @escaping (String, Bool) -> Void, shareCurrentLocation: @escaping () -> Void, shareAccountContact: @escaping () -> Void, sendBotCommand: @escaping (MessageId?, String) -> Void, openInstantPage: @escaping (Message) -> Void, openHashtag: @escaping (String?, String) -> Void, updateInputState: @escaping ((ChatTextInputState) -> ChatTextInputState) -> Void, updateInputMode: @escaping ((ChatInputMode) -> ChatInputMode) -> Void, openMessageShareMenu: @escaping (MessageId) -> Void, presentController: @escaping (ViewController, Any?) -> Void, navigationController: @escaping () -> NavigationController?, presentGlobalOverlayController: @escaping (ViewController, Any?) -> Void, callPeer: @escaping (PeerId) -> Void, longTap: @escaping (ChatControllerInteractionLongTapAction) -> Void, openCheckoutOrReceipt: @escaping (MessageId) -> Void, openSearch: @escaping () -> Void, setupReply: @escaping (MessageId) -> Void, canSetupReply: @escaping (Message) -> Bool, requestMessageUpdate: @escaping (MessageId) -> Void, cancelInteractiveKeyboardGestures: @escaping () -> Void, automaticMediaDownloadSettings: AutomaticMediaDownloadSettings) { + init(openMessage: @escaping (Message) -> Bool, openPeer: @escaping (PeerId?, ChatControllerInteractionNavigateToPeer, Message?) -> Void, openPeerMention: @escaping (String) -> Void, openMessageContextMenu: @escaping (Message, ASDisplayNode, CGRect) -> Void, navigateToMessage: @escaping (MessageId, MessageId) -> Void, clickThroughMessage: @escaping () -> Void, toggleMessagesSelection: @escaping ([MessageId], Bool) -> Void, sendMessage: @escaping (String) -> Void, sendSticker: @escaping (FileMediaReference) -> Void, sendGif: @escaping (FileMediaReference) -> Void, requestMessageActionCallback: @escaping (MessageId, MemoryBuffer?, Bool) -> Void, activateSwitchInline: @escaping (PeerId?, String) -> Void, openUrl: @escaping (String, Bool) -> Void, shareCurrentLocation: @escaping () -> Void, shareAccountContact: @escaping () -> Void, sendBotCommand: @escaping (MessageId?, String) -> Void, openInstantPage: @escaping (Message) -> Void, openHashtag: @escaping (String?, String) -> Void, updateInputState: @escaping ((ChatTextInputState) -> ChatTextInputState) -> Void, updateInputMode: @escaping ((ChatInputMode) -> ChatInputMode) -> Void, openMessageShareMenu: @escaping (MessageId) -> Void, presentController: @escaping (ViewController, Any?) -> Void, navigationController: @escaping () -> NavigationController?, presentGlobalOverlayController: @escaping (ViewController, Any?) -> Void, callPeer: @escaping (PeerId) -> Void, longTap: @escaping (ChatControllerInteractionLongTapAction) -> Void, openCheckoutOrReceipt: @escaping (MessageId) -> Void, openSearch: @escaping () -> Void, setupReply: @escaping (MessageId) -> Void, canSetupReply: @escaping (Message) -> Bool, navigateToFirstDateMessage: @escaping(Int32)->Void, requestMessageUpdate: @escaping (MessageId) -> Void, cancelInteractiveKeyboardGestures: @escaping () -> Void, automaticMediaDownloadSettings: AutomaticMediaDownloadSettings) { self.openMessage = openMessage self.openPeer = openPeer self.openPeerMention = openPeerMention @@ -108,6 +109,7 @@ public final class ChatControllerInteraction { self.openSearch = openSearch self.setupReply = setupReply self.canSetupReply = canSetupReply + self.navigateToFirstDateMessage = navigateToFirstDateMessage self.requestMessageUpdate = requestMessageUpdate self.cancelInteractiveKeyboardGestures = cancelInteractiveKeyboardGestures diff --git a/TelegramUI/ChatHistoryGridNode.swift b/TelegramUI/ChatHistoryGridNode.swift index 614409fcac..1f9f6b86cb 100644 --- a/TelegramUI/ChatHistoryGridNode.swift +++ b/TelegramUI/ChatHistoryGridNode.swift @@ -301,7 +301,7 @@ public final class ChatHistoryGridNode: GridNode, ChatHistoryNode { self._chatHistoryLocation.set(ChatHistoryLocation.Scroll(index: .upperBound, anchorIndex: .upperBound, sourceIndex: .lowerBound, scrollPosition: .top(0.0), animated: true)) } - public func scrollToMessage(from fromIndex: MessageIndex, to toIndex: MessageIndex) { + public func scrollToMessage(from fromIndex: MessageIndex, to toIndex: MessageIndex, scrollPosition: ListViewScrollPosition = .center(.bottom)) { self._chatHistoryLocation.set(ChatHistoryLocation.Scroll(index: .message(toIndex), anchorIndex: .message(toIndex), sourceIndex: .message(fromIndex), scrollPosition: .center(.bottom), animated: true)) } diff --git a/TelegramUI/ChatHistoryListNode.swift b/TelegramUI/ChatHistoryListNode.swift index 453aad28e1..44faf0b9bd 100644 --- a/TelegramUI/ChatHistoryListNode.swift +++ b/TelegramUI/ChatHistoryListNode.swift @@ -774,8 +774,8 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode { } } - public func scrollToMessage(from fromIndex: MessageIndex, to toIndex: MessageIndex, animated: Bool, highlight: Bool = true) { - self._chatHistoryLocation.set(ChatHistoryLocation.Scroll(index: .message(toIndex), anchorIndex: .message(toIndex), sourceIndex: .message(fromIndex), scrollPosition: .center(.bottom), animated: animated)) + public func scrollToMessage(from fromIndex: MessageIndex, to toIndex: MessageIndex, animated: Bool, highlight: Bool = true, scrollPosition: ListViewScrollPosition = .center(.bottom)) { + self._chatHistoryLocation.set(ChatHistoryLocation.Scroll(index: .message(toIndex), anchorIndex: .message(toIndex), sourceIndex: .message(fromIndex), scrollPosition: scrollPosition, animated: animated)) } public func anchorMessageInCurrentHistoryView() -> Message? { diff --git a/TelegramUI/ChatMessageDateHeader.swift b/TelegramUI/ChatMessageDateHeader.swift index e00e26f352..19f4315a9a 100644 --- a/TelegramUI/ChatMessageDateHeader.swift +++ b/TelegramUI/ChatMessageDateHeader.swift @@ -19,12 +19,12 @@ final class ChatMessageDateHeader: ListViewItemHeader { let id: Int64 let theme: ChatPresentationThemeData let strings: PresentationStrings - - init(timestamp: Int32, theme: ChatPresentationThemeData, strings: PresentationStrings) { + let action:((Int32)->Void)? + init(timestamp: Int32, theme: ChatPresentationThemeData, strings: PresentationStrings, action:((Int32)->Void)? = nil) { self.timestamp = timestamp self.theme = theme self.strings = strings - + self.action = action if timestamp == Int32.max { self.roundedTimestamp = timestamp / (granularity) * (granularity) } else { @@ -38,7 +38,7 @@ final class ChatMessageDateHeader: ListViewItemHeader { let height: CGFloat = 34.0 func node() -> ListViewItemHeaderNode { - return ChatMessageDateHeaderNode(localTimestamp: self.roundedTimestamp, theme: self.theme, strings: self.strings) + return ChatMessageDateHeaderNode(localTimestamp: self.roundedTimestamp, theme: self.theme, strings: self.strings, action: self.action) } } @@ -86,11 +86,13 @@ final class ChatMessageDateHeaderNode: ListViewItemHeaderNode { private var flashingOnScrolling = false private var stickDistanceFactor: CGFloat = 0.0 + private var action:((Int32)->Void)? = nil - init(localTimestamp: Int32, theme: ChatPresentationThemeData, strings: PresentationStrings) { + init(localTimestamp: Int32, theme: ChatPresentationThemeData, strings: PresentationStrings, action:((Int32)->Void)? = nil) { self.localTimestamp = localTimestamp self.theme = theme self.strings = strings + self.action = action self.labelNode = TextNode() self.labelNode.isLayerBacked = true @@ -158,7 +160,10 @@ final class ChatMessageDateHeaderNode: ListViewItemHeaderNode { print("position \(position.x), \(position.y)") } }*/ + + } + override func didLoad() { super.didLoad() @@ -229,6 +234,8 @@ final class ChatMessageDateHeaderNode: ListViewItemHeaderNode { } } } + + override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { if !self.bounds.contains(point) { @@ -243,13 +250,15 @@ final class ChatMessageDateHeaderNode: ListViewItemHeaderNode { return nil } + + override func touchesCancelled(_ touches: Set?, with event: UIEvent?) { super.touchesCancelled(touches, with: event) } @objc func tapGesture(_ recognizer: UITapGestureRecognizer) { if case .ended = recognizer.state { - + action?(self.localTimestamp) } } } diff --git a/TelegramUI/ChatMessageItem.swift b/TelegramUI/ChatMessageItem.swift index 9dfb97b459..449a753bb3 100644 --- a/TelegramUI/ChatMessageItem.swift +++ b/TelegramUI/ChatMessageItem.swift @@ -278,7 +278,35 @@ public final class ChatMessageItem: ListViewItem, CustomStringConvertible { self.effectiveAuthorId = effectiveAuthor?.id - self.header = ChatMessageDateHeader(timestamp: content.index.timestamp, theme: presentationData.theme, strings: presentationData.strings) + + self.header = ChatMessageDateHeader(timestamp: content.index.timestamp, theme: presentationData.theme, strings: presentationData.strings, action: { timestamp in + +// + var calendar = NSCalendar.current + + calendar.timeZone = TimeZone(abbreviation: "UTC")! + let date = Date(timeIntervalSince1970: TimeInterval(timestamp)) + let components = calendar.dateComponents([.year, .month, .day], from: date) + + if let date = calendar.date(from: components) { + controllerInteraction.navigateToFirstDateMessage(Int32(date.timeIntervalSince1970)) + } + + + /* + unsigned unitFlags = NSCalendarUnitDay| NSCalendarUnitYear | NSCalendarUnitMonth; + NSDateComponents *components = [cal components:unitFlags fromDate:date]; + NSDateComponents *comps = [[NSDateComponents alloc] init]; + comps.day = day; + comps.year = components.year; + comps.month = components.month; + return [cal dateFromComponents:comps]; + */ + + // item.chatInteraction?.jumpToDate(CalendarUtils.monthDay(components.day!, date: date)) + + + }) if displayAuthorInfo { let message = content.firstMessage @@ -302,6 +330,7 @@ public final class ChatMessageItem: ListViewItem, CustomStringConvertible { } } self.accessoryItem = accessoryItem + } public func nodeConfiguredForParams(async: @escaping (@escaping () -> Void) -> Void, params: ListViewItemLayoutParams, previousItem: ListViewItem?, nextItem: ListViewItem?, completion: @escaping (ListViewItemNode, @escaping () -> (Signal?, () -> Void)) -> Void) { diff --git a/TelegramUI/ChatRecentActionsControllerNode.swift b/TelegramUI/ChatRecentActionsControllerNode.swift index 4e61d92100..139192f767 100644 --- a/TelegramUI/ChatRecentActionsControllerNode.swift +++ b/TelegramUI/ChatRecentActionsControllerNode.swift @@ -363,6 +363,8 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode { }, openCheckoutOrReceipt: { _ in }, openSearch: { }, setupReply: { _ in }, canSetupReply: { _ in return false + }, navigateToFirstDateMessage: { _ in + }, requestMessageUpdate: { _ in }, cancelInteractiveKeyboardGestures: { }, automaticMediaDownloadSettings: self.automaticMediaDownloadSettings) diff --git a/TelegramUI/OverlayPlayerControllerNode.swift b/TelegramUI/OverlayPlayerControllerNode.swift index 8c9320911a..ba4f626f0a 100644 --- a/TelegramUI/OverlayPlayerControllerNode.swift +++ b/TelegramUI/OverlayPlayerControllerNode.swift @@ -65,6 +65,7 @@ final class OverlayPlayerControllerNode: ViewControllerTracingNode, UIGestureRec }, setupReply: { _ in }, canSetupReply: { _ in return false + }, navigateToFirstDateMessage: { _ in }, requestMessageUpdate: { _ in }, cancelInteractiveKeyboardGestures: { }, automaticMediaDownloadSettings: AutomaticMediaDownloadSettings.defaultSettings) diff --git a/TelegramUI/PeerMediaCollectionController.swift b/TelegramUI/PeerMediaCollectionController.swift index 114dc59432..e9e20c2757 100644 --- a/TelegramUI/PeerMediaCollectionController.swift +++ b/TelegramUI/PeerMediaCollectionController.swift @@ -212,6 +212,7 @@ public class PeerMediaCollectionController: TelegramController { }, setupReply: { _ in }, canSetupReply: { _ in return false + }, navigateToFirstDateMessage: { _ in }, requestMessageUpdate: { _ in }, cancelInteractiveKeyboardGestures: { }, automaticMediaDownloadSettings: AutomaticMediaDownloadSettings.defaultSettings) diff --git a/TelegramUI/PresentationStrings.swift b/TelegramUI/PresentationStrings.swift index a9d549a2fd..3969cbe54c 100644 --- a/TelegramUI/PresentationStrings.swift +++ b/TelegramUI/PresentationStrings.swift @@ -222,6 +222,11 @@ public final class PresentationStrings { public func PrivacyPolicy_AgeVerificationMessage(_ _0: String) -> (String, [(Int, NSRange)]) { return formatWithArgumentRanges(_PrivacyPolicy_AgeVerificationMessage, self._PrivacyPolicy_AgeVerificationMessage_r, [_0]) } + private let _Login_TermsOfService_ProceedBot: String + private let _Login_TermsOfService_ProceedBot_r: [(Int, NSRange)] + public func Login_TermsOfService_ProceedBot(_ _0: String) -> (String, [(Int, NSRange)]) { + return formatWithArgumentRanges(_Login_TermsOfService_ProceedBot, self._Login_TermsOfService_ProceedBot_r, [_0]) + } public let NotificationsSound_None: String public let Channel_AdminLog_CanEditMessages: String private let _MESSAGE_CONTACT: String @@ -5541,6 +5546,8 @@ public final class PresentationStrings { self.SocksProxySetup_Hostname = getValue(dict, "SocksProxySetup.Hostname") self._PrivacyPolicy_AgeVerificationMessage = getValue(dict, "PrivacyPolicy.AgeVerificationMessage") self._PrivacyPolicy_AgeVerificationMessage_r = extractArgumentRanges(self._PrivacyPolicy_AgeVerificationMessage) + self._Login_TermsOfService_ProceedBot = getValue(dict, "Login.TermsOfService.ProceedBot") + self._Login_TermsOfService_ProceedBot_r = extractArgumentRanges(self._Login_TermsOfService_ProceedBot) self.NotificationsSound_None = getValue(dict, "NotificationsSound.None") self.Channel_AdminLog_CanEditMessages = getValue(dict, "Channel.AdminLog.CanEditMessages") self._MESSAGE_CONTACT = getValue(dict, "MESSAGE_CONTACT") diff --git a/TelegramUI/TermsOfServiceController.swift b/TelegramUI/TermsOfServiceController.swift index 9e6ba80589..a5fdc0016d 100644 --- a/TelegramUI/TermsOfServiceController.swift +++ b/TelegramUI/TermsOfServiceController.swift @@ -48,9 +48,10 @@ public class TermsOfServiceController: ViewController { private let entities: [MessageTextEntity] private let ageConfirmation: Int32? private let signingUp: Bool - private let accept: () -> Void + private let accept: (String?) -> Void private let decline: () -> Void private let openUrl: (String) -> Void + private var proccessBotNameAfterAccept: String? = nil private var didPlayPresentationAnimation = false @@ -66,7 +67,7 @@ public class TermsOfServiceController: ViewController { } } - public init(theme: TermsOfServiceControllerTheme, strings: PresentationStrings, text: String, entities: [MessageTextEntity], ageConfirmation: Int32?, signingUp: Bool, accept: @escaping () -> Void, decline: @escaping () -> Void, openUrl: @escaping (String) -> Void) { + public init(theme: TermsOfServiceControllerTheme, strings: PresentationStrings, text: String, entities: [MessageTextEntity], ageConfirmation: Int32?, signingUp: Bool, accept: @escaping (String?) -> Void, decline: @escaping () -> Void, openUrl: @escaping (String) -> Void) { self.theme = theme self.strings = strings self.text = text @@ -135,18 +136,21 @@ public class TermsOfServiceController: ViewController { theme = defaultDarkPresentationTheme } strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationTheme: theme), title: strongSelf.strings.PrivacyPolicy_AgeVerificationTitle, text: strongSelf.strings.PrivacyPolicy_AgeVerificationMessage("\(ageConfirmation)").0, actions: [TextAlertAction(type: .genericAction, title: strongSelf.strings.Common_Cancel, action: {}), TextAlertAction(type: .defaultAction, title: strongSelf.strings.PrivacyPolicy_AgeVerificationAgree, action: { - self?.accept() + self?.accept(self?.proccessBotNameAfterAccept) })]), in: .window(.root)) } else { - strongSelf.accept() + strongSelf.accept(self?.proccessBotNameAfterAccept) } }, openUrl: self.openUrl, present: { [weak self] c, a in self?.present(c, in: .window(.root), with: a) + }, setToProcceedBot: { [weak self] botName in + self?.proccessBotNameAfterAccept = botName }) self.displayNodeDidLoad() } + override public func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) { super.containerLayoutUpdated(layout, transition: transition) diff --git a/TelegramUI/TermsOfServiceControllerNode.swift b/TelegramUI/TermsOfServiceControllerNode.swift index 53c164d712..425c3cdfbb 100644 --- a/TelegramUI/TermsOfServiceControllerNode.swift +++ b/TelegramUI/TermsOfServiceControllerNode.swift @@ -39,7 +39,7 @@ final class TermsOfServiceControllerNode: ViewControllerTracingNode { } } - init(theme: TermsOfServiceControllerTheme, strings: PresentationStrings, text: String, entities: [MessageTextEntity], ageConfirmation: Int32?, leftAction: @escaping () -> Void, rightAction: @escaping () -> Void, openUrl: @escaping (String) -> Void, present: @escaping (ViewController, Any?) -> Void) { + init(theme: TermsOfServiceControllerTheme, strings: PresentationStrings, text: String, entities: [MessageTextEntity], ageConfirmation: Int32?, leftAction: @escaping () -> Void, rightAction: @escaping () -> Void, openUrl: @escaping (String) -> Void, present: @escaping (ViewController, Any?) -> Void, setToProcceedBot:@escaping(String)->Void) { self.theme = theme self.strings = strings self.text = text @@ -142,14 +142,10 @@ final class TermsOfServiceControllerNode: ViewControllerTracingNode { } let actionSheet = ActionSheetController(presentationTheme: theme) actionSheet.setItemGroups([ActionSheetItemGroup(items: [ - ActionSheetTextItem(title: mention.mention), - ActionSheetButtonItem(title: strongSelf.strings.Conversation_LinkDialogCopy, color: .accent, action: { [weak actionSheet] in - actionSheet?.dismissAnimated() - UIPasteboard.general.string = mention.mention - }) - ]), ActionSheetItemGroup(items: [ - ActionSheetButtonItem(title: strongSelf.strings.Common_Cancel, color: .accent, action: { [weak actionSheet] in + ActionSheetTextItem(title: strongSelf.strings.Login_TermsOfService_ProceedBot(mention.mention).0), + ActionSheetButtonItem(title: strongSelf.strings.Common_OK, color: .accent, action: { [weak actionSheet] in actionSheet?.dismissAnimated() + setToProcceedBot(mention.mention) }) ])]) strongSelf.present(actionSheet, nil) @@ -162,14 +158,10 @@ final class TermsOfServiceControllerNode: ViewControllerTracingNode { } let actionSheet = ActionSheetController(presentationTheme: theme) actionSheet.setItemGroups([ActionSheetItemGroup(items: [ - ActionSheetTextItem(title: mention), - ActionSheetButtonItem(title: strongSelf.strings.Conversation_LinkDialogCopy, color: .accent, action: { [weak actionSheet] in - actionSheet?.dismissAnimated() - UIPasteboard.general.string = mention - }) - ]), ActionSheetItemGroup(items: [ - ActionSheetButtonItem(title: strongSelf.strings.Common_Cancel, color: .accent, action: { [weak actionSheet] in + ActionSheetTextItem(title: strongSelf.strings.Login_TermsOfService_ProceedBot(mention).0), + ActionSheetButtonItem(title: strongSelf.strings.Common_OK, color: .accent, action: { [weak actionSheet] in actionSheet?.dismissAnimated() + setToProcceedBot(mention) }) ])]) strongSelf.present(actionSheet, nil) @@ -212,14 +204,10 @@ final class TermsOfServiceControllerNode: ViewControllerTracingNode { } let actionSheet = ActionSheetController(presentationTheme: theme) actionSheet.setItemGroups([ActionSheetItemGroup(items: [ - ActionSheetTextItem(title: mention.mention), - ActionSheetButtonItem(title: strongSelf.strings.Conversation_LinkDialogCopy, color: .accent, action: { [weak actionSheet] in - actionSheet?.dismissAnimated() - UIPasteboard.general.string = mention.mention - }) - ]), ActionSheetItemGroup(items: [ - ActionSheetButtonItem(title: strongSelf.strings.Common_Cancel, color: .accent, action: { [weak actionSheet] in + ActionSheetTextItem(title: strongSelf.strings.Login_TermsOfService_ProceedBot(mention.mention).0), + ActionSheetButtonItem(title: strongSelf.strings.Common_OK, color: .accent, action: { [weak actionSheet] in actionSheet?.dismissAnimated() + setToProcceedBot(mention.mention) }) ])]) strongSelf.present(actionSheet, nil) @@ -232,14 +220,10 @@ final class TermsOfServiceControllerNode: ViewControllerTracingNode { } let actionSheet = ActionSheetController(presentationTheme: theme) actionSheet.setItemGroups([ActionSheetItemGroup(items: [ - ActionSheetTextItem(title: mention), - ActionSheetButtonItem(title: strongSelf.strings.Conversation_LinkDialogCopy, color: .accent, action: { [weak actionSheet] in - actionSheet?.dismissAnimated() - UIPasteboard.general.string = mention - }) - ]), ActionSheetItemGroup(items: [ - ActionSheetButtonItem(title: strongSelf.strings.Common_Cancel, color: .accent, action: { [weak actionSheet] in + ActionSheetTextItem(title: strongSelf.strings.Login_TermsOfService_ProceedBot(mention).0), + ActionSheetButtonItem(title: strongSelf.strings.Common_OK, color: .accent, action: { [weak actionSheet] in actionSheet?.dismissAnimated() + setToProcceedBot(mention) }) ])]) strongSelf.present(actionSheet, nil) diff --git a/TelegramUI/ThemeSettingsChatPreviewItem.swift b/TelegramUI/ThemeSettingsChatPreviewItem.swift index 8373d032eb..6e4832b7fb 100644 --- a/TelegramUI/ThemeSettingsChatPreviewItem.swift +++ b/TelegramUI/ThemeSettingsChatPreviewItem.swift @@ -95,6 +95,7 @@ class ThemeSettingsChatPreviewItemNode: ListViewItemNode { }, presentGlobalOverlayController: { _, _ in }, callPeer: { _ in }, longTap: { _ in }, openCheckoutOrReceipt: { _ in }, openSearch: { }, setupReply: { _ in }, canSetupReply: { _ in return false + }, navigateToFirstDateMessage: { _ in }, requestMessageUpdate: { _ in }, cancelInteractiveKeyboardGestures: { }, automaticMediaDownloadSettings: AutomaticMediaDownloadSettings.defaultSettings)