diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index d502eee560..48b9d6f194 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -15891,6 +15891,8 @@ Error: %8$@"; "GroupInfo.ActionSend" = "Send Message"; "GroupInfo.ActionEditRank" = "Edit Member Tag"; +"GroupInfo.ActionEditAdminRank" = "Edit Admin Tag"; +"GroupInfo.ActionEditAdmin" = "Edit Admin Rights"; "GroupInfo.ActionRemove" = "Remove"; "PeerInfo.EnableSharing" = "Enable Sharing"; diff --git a/submodules/ChatListUI/Sources/ChatListFilterPresetListController.swift b/submodules/ChatListUI/Sources/ChatListFilterPresetListController.swift index d8dbb29e6a..2d595caf56 100644 --- a/submodules/ChatListUI/Sources/ChatListFilterPresetListController.swift +++ b/submodules/ChatListUI/Sources/ChatListFilterPresetListController.swift @@ -810,13 +810,23 @@ public func chatListFilterPresetListController(context: AccountContext, mode: Ch var didFocusOnItem = false controller.afterTransactionCompleted = { [weak controller] in + guard let controller else { + return + } + + if let focusOnItemTag, !didFocusOnItem { + controller.forEachItemNode { itemNode in + if let itemNode = itemNode as? ItemListItemNode, let tag = itemNode.tag, tag.isEqual(to: focusOnItemTag) { + didFocusOnItem = true + itemNode.displayHighlight() + } + } + } + guard let toggleDirection = animateNextShowHideTagsTransition.swap(nil) else { return } - guard let controller else { - return - } var presetItemNodes: [ChatListFilterPresetListItemNode] = [] controller.forEachItemNode { itemNode in if let itemNode = itemNode as? ChatListFilterPresetListItemNode { @@ -831,15 +841,6 @@ public func chatListFilterPresetListController(context: AccountContext, mode: Ch } delay += 0.02 } - - if let focusOnItemTag, !didFocusOnItem { - controller.forEachItemNode { itemNode in - if let itemNode = itemNode as? ItemListItemNode, let tag = itemNode.tag, tag.isEqual(to: focusOnItemTag) { - didFocusOnItem = true - itemNode.displayHighlight() - } - } - } } return controller diff --git a/submodules/PeerInfoUI/Sources/ChannelPermissionsController.swift b/submodules/PeerInfoUI/Sources/ChannelPermissionsController.swift index bd04ccb360..d03290333d 100644 --- a/submodules/PeerInfoUI/Sources/ChannelPermissionsController.swift +++ b/submodules/PeerInfoUI/Sources/ChannelPermissionsController.swift @@ -610,6 +610,7 @@ public func allGroupPermissionList(peer: EnginePeer, expandMedia: Bool) -> [(Tel (.banSendMedia, .banMembers), (.banAddMembers, .banMembers), (.banPinMessages, .pinMessages), + (.banEditRank, .editRank), (.banManageTopics, .manageTopics), (.banChangeInfo, .changeInfo) ] diff --git a/submodules/PremiumUI/Sources/PremiumDemoScreen.swift b/submodules/PremiumUI/Sources/PremiumDemoScreen.swift index f77c5ed42a..ddd15e4f70 100644 --- a/submodules/PremiumUI/Sources/PremiumDemoScreen.swift +++ b/submodules/PremiumUI/Sources/PremiumDemoScreen.swift @@ -1307,6 +1307,8 @@ private final class DemoSheetContent: CombinedComponent { buttonAnimationName = "premium_unlock" case .todo: buttonText = strings.Premium_PaidMessages_Proceed + case .copyProtection: + buttonText = strings.Premium_PaidMessages_Proceed default: buttonText = strings.Common_OK } diff --git a/submodules/SettingsUI/Sources/Data and Storage/ProxySettingsActionItem.swift b/submodules/SettingsUI/Sources/Data and Storage/ProxySettingsActionItem.swift index a35d7821f9..2f7c2b0a88 100644 --- a/submodules/SettingsUI/Sources/Data and Storage/ProxySettingsActionItem.swift +++ b/submodules/SettingsUI/Sources/Data and Storage/ProxySettingsActionItem.swift @@ -81,6 +81,7 @@ final class ProxySettingsActionItem: ListViewItem, ItemListItem { private final class ProxySettingsActionItemNode: ListViewItemNode, ItemListItemNode { private let backgroundNode: ASDisplayNode + private let highlightNode: ASDisplayNode private let topStripeNode: ASDisplayNode private let bottomStripeNode: ASDisplayNode private let highlightedBackgroundNode: ASDisplayNode @@ -99,6 +100,9 @@ private final class ProxySettingsActionItemNode: ListViewItemNode, ItemListItemN self.backgroundNode = ASDisplayNode() self.backgroundNode.isLayerBacked = true + self.highlightNode = ASDisplayNode() + self.highlightNode.isLayerBacked = true + self.topStripeNode = ASDisplayNode() self.topStripeNode.isLayerBacked = true @@ -128,6 +132,20 @@ private final class ProxySettingsActionItemNode: ListViewItemNode, ItemListItemN self.addSubnode(self.titleNode) } + public func displayHighlight() { + if self.backgroundNode.supernode != nil { + self.insertSubnode(self.highlightNode, aboveSubnode: self.backgroundNode) + } else { + self.insertSubnode(self.highlightNode, at: 0) + } + + Queue.mainQueue().after(1.2, { + self.highlightNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { _ in + self.highlightNode.removeFromSupernode() + }) + }) + } + func asyncLayout() -> (_ item: ProxySettingsActionItem, _ params: ListViewItemLayoutParams, _ neighbors: ItemListNeighbors) -> (ListViewItemNodeLayout, (Bool) -> Void) { let makeTitleLayout = TextNode.asyncLayout(self.titleNode) @@ -177,6 +195,7 @@ private final class ProxySettingsActionItemNode: ListViewItemNode, ItemListItemN strongSelf.bottomStripeNode.backgroundColor = item.presentationData.theme.list.itemBlocksSeparatorColor strongSelf.backgroundNode.backgroundColor = item.presentationData.theme.list.itemBlocksBackgroundColor strongSelf.highlightedBackgroundNode.backgroundColor = item.presentationData.theme.list.itemHighlightedBackgroundColor + strongSelf.highlightNode.backgroundColor = item.presentationData.theme.list.itemSearchHighlightColor } let _ = titleApply() @@ -234,6 +253,7 @@ private final class ProxySettingsActionItemNode: ListViewItemNode, ItemListItemN strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.presentationData.theme, top: hasTopCorners, bottom: hasBottomCorners, glass: item.systemStyle == .glass) : nil strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight))) + strongSelf.highlightNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight))) strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0) strongSelf.topStripeNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: layoutSize.width, height: separatorHeight)) transition.updateFrame(node: strongSelf.bottomStripeNode, frame: CGRect(origin: CGPoint(x: bottomStripeInset, y: contentSize.height + bottomStripeOffset), size: CGSize(width: layoutSize.width - bottomStripeInset - params.rightInset - separatorRightInset, height: separatorHeight))) diff --git a/submodules/SettingsUI/Sources/Search/SettingsSearchableItems.swift b/submodules/SettingsUI/Sources/Search/SettingsSearchableItems.swift index 67ef6d1348..a32bbf65d0 100644 --- a/submodules/SettingsUI/Sources/Search/SettingsSearchableItems.swift +++ b/submodules/SettingsUI/Sources/Search/SettingsSearchableItems.swift @@ -1422,7 +1422,7 @@ private func stickerSearchableItems(context: AccountContext, archivedStickerPack } items.append( SettingsSearchableItem( - id: "appearance/stickers-and-emoji/large", + id: "appearance/stickers-and-emoji/large-emoji", title: strings.Appearance_LargeEmoji, alternate: synonyms(strings.SettingsSearch_Synonyms_Appearance_LargeEmoji), icon: icon, @@ -1474,7 +1474,7 @@ private func stickerSearchableItems(context: AccountContext, archivedStickerPack icon: icon, breadcrumbs: [strings.StickerPacksSettings_Emoji], present: { context, _, present in - presentStickerSettings(context, present, .emoji, .suggestOptions) + presentStickerSettings(context, present, .emoji, .suggestAnimatedEmoji) } ) ) @@ -3621,7 +3621,7 @@ private func dataSearchableItems(context: AccountContext) -> [SettingsSearchable } ), SettingsSearchableItem( - id: "data/use-less-data", + id: "data/less-data-calls", title: strings.CallSettings_UseLessData, alternate: synonyms(strings.SettingsSearch_Synonyms_Data_CallsUseLessData), icon: icon, @@ -3754,7 +3754,7 @@ private func proxySearchableItems(context: AccountContext, servers: [ProxyServer ) items.append( SettingsSearchableItem( - id: "data/use-proxy", + id: "data/proxy/use-proxy", icon: icon, isVisible: false, present: { context, _, present in @@ -4388,17 +4388,7 @@ func settingsSearchableItems( let activeWebSessionsContext = webSessionsContext |> mapToSignal { webSessionsContext -> Signal in if let webSessionsContext = webSessionsContext { - return webSessionsContext.state - |> map { state -> WebSessionsContext? in - if !state.sessions.isEmpty { - return webSessionsContext - } else { - return nil - } - } - |> distinctUntilChanged(isEqual: { lhs, rhs in - return lhs !== rhs - }) + return .single(webSessionsContext) } else { return .single(nil) } @@ -4417,6 +4407,7 @@ func settingsSearchableItems( activeSessionsContext, activeWebSessionsContext ) + |> deliverOnMainQueue |> map { canAddAccount, localizations, @@ -4615,7 +4606,20 @@ func searchSettingsItems(items: [SettingsSearchableItem], query: String) -> [Set } public func handleSettingsPathUrl(context: AccountContext, path: String, navigationController: NavigationController) { - let _ = (settingsSearchableItems(context: context) + var activeSessionsContext: Signal = .single(nil) + var webSessionsContext: Signal = .single(nil) + + if path.hasPrefix("devices") { + activeSessionsContext = .single(context.engine.privacy.activeSessions()) + } else if path.hasPrefix("privacy/active-websites") { + webSessionsContext = .single(context.engine.privacy.webSessions()) + } + + let _ = (settingsSearchableItems( + context: context, + activeSessionsContext: activeSessionsContext, + webSessionsContext: webSessionsContext + ) |> take(1) |> deliverOnMainQueue).start(next: { items in guard let item = items.first(where: { $0.id == AnyHashable(path) }) else { diff --git a/submodules/SettingsUI/Sources/Stickers/InstalledStickerPacksController.swift b/submodules/SettingsUI/Sources/Stickers/InstalledStickerPacksController.swift index 00dbd99fc1..02355eb3f1 100644 --- a/submodules/SettingsUI/Sources/Stickers/InstalledStickerPacksController.swift +++ b/submodules/SettingsUI/Sources/Stickers/InstalledStickerPacksController.swift @@ -71,6 +71,7 @@ public enum InstalledStickerPacksEntryTag: ItemListItemTag { case suggestOptions case largeEmoji case dynamicOrder + case suggestAnimatedEmoji public func isEqual(to other: ItemListItemTag) -> Bool { if let other = other as? InstalledStickerPacksEntryTag, self == other { @@ -430,7 +431,7 @@ private indirect enum InstalledStickerPacksEntry: ItemListNodeEntry { case let .suggestAnimatedEmoji(text, value): return ItemListSwitchItem(presentationData: presentationData, systemStyle: .glass, title: text, value: value, sectionId: self.section, style: .blocks, updated: { value in arguments.toggleSuggestAnimatedEmoji(value) - }) + }, tag: InstalledStickerPacksEntryTag.suggestAnimatedEmoji) case let .suggestAnimatedEmojiInfo(_, text): return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section) case let .packsTitle(_, text): diff --git a/submodules/SettingsUI/Sources/ThemePickerController.swift b/submodules/SettingsUI/Sources/ThemePickerController.swift index 475bd10a4a..b6cef5f11d 100644 --- a/submodules/SettingsUI/Sources/ThemePickerController.swift +++ b/submodules/SettingsUI/Sources/ThemePickerController.swift @@ -1326,7 +1326,7 @@ private final class ContextControllerContentSourceImpl: ContextControllerContent } private func iconColors(theme: PresentationTheme) -> [String: UIColor] { - let accentColor = theme.actionSheet.controlAccentColor + let accentColor = theme.chat.inputPanel.panelControlColor var colors: [String: UIColor] = [:] colors["Sunny.Path 14.Path.Stroke 1"] = accentColor colors["Sunny.Path 15.Path.Stroke 1"] = accentColor diff --git a/submodules/TelegramUI/Components/MinimizedContainer/Sources/MinimizedHeaderNode.swift b/submodules/TelegramUI/Components/MinimizedContainer/Sources/MinimizedHeaderNode.swift index 65e25bff1b..b8fde11302 100644 --- a/submodules/TelegramUI/Components/MinimizedContainer/Sources/MinimizedHeaderNode.swift +++ b/submodules/TelegramUI/Components/MinimizedContainer/Sources/MinimizedHeaderNode.swift @@ -311,13 +311,13 @@ final class MinimizedHeaderNode: ASDisplayNode { transition.updateFrame(view: view, frame: closeButtonFrame) } - transition.updateFrame(view: self.backgroundView, frame: CGRect(origin: .zero, size: CGSize(width: size.width, height: 243.0))) + transition.updateFrame(view: self.backgroundView, frame: CGRect(origin: .zero, size: CGSize(width: size.width, height: 246.0))) //self.backgroundView.update(size: CGSize(width: size.width, height: 243.0), color: self.theme.navigationBar.opaqueBackgroundColor, topCornerRadius: 25.0, bottomCornerRadius: 62.0, transition: .immediate) transition.updateAlpha(layer: self.progressView.layer, alpha: isExpanded && self.progress != nil ? 1.0 : 0.0) if let progress = self.progress { - self.progressView.frame = CGRect(origin: .zero, size: CGSize(width: size.width * CGFloat(progress), height: 243.0)) + self.progressView.frame = CGRect(origin: .zero, size: CGSize(width: size.width * CGFloat(progress), height: 246.0)) } } } diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreenOpenMember.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreenOpenMember.swift index 8046ae477c..f5536517ec 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreenOpenMember.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreenOpenMember.swift @@ -31,7 +31,11 @@ extension PeerInfoScreenNode { } if actions.contains(.editRank) { - items.append(.action(ContextMenuActionItem(text: self.presentationData.strings.GroupInfo_ActionEditRank, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Tag"), color: theme.contextMenu.primaryColor) }, action: { [weak self] c, _ in + var actionTitle: String = self.presentationData.strings.GroupInfo_ActionEditRank + if case .admin = member.role { + actionTitle = self.presentationData.strings.GroupInfo_ActionEditAdminRank + } + items.append(.action(ContextMenuActionItem(text: actionTitle, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Tag"), color: theme.contextMenu.primaryColor) }, action: { [weak self] c, _ in c?.dismiss { guard let self else { return @@ -42,7 +46,11 @@ extension PeerInfoScreenNode { } if actions.contains(.promote) && enclosingPeer is TelegramChannel { - items.append(.action(ContextMenuActionItem(text: self.presentationData.strings.GroupInfo_ActionPromote, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Promote"), color: theme.contextMenu.primaryColor) }, action: { [weak self] c, _ in + var actionTitle: String = self.presentationData.strings.GroupInfo_ActionPromote + if case .admin = member.role { + actionTitle = self.presentationData.strings.GroupInfo_ActionEditAdmin + } + items.append(.action(ContextMenuActionItem(text: actionTitle, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Promote"), color: theme.contextMenu.primaryColor) }, action: { [weak self] c, _ in c?.dismiss { guard let self else { return diff --git a/submodules/TelegramUI/Sources/OpenUrl.swift b/submodules/TelegramUI/Sources/OpenUrl.swift index 6b42e1a50a..57e4b54d36 100644 --- a/submodules/TelegramUI/Sources/OpenUrl.swift +++ b/submodules/TelegramUI/Sources/OpenUrl.swift @@ -951,20 +951,24 @@ func openExternalUrlImpl(context: AccountContext, urlContext: OpenURLContext, ur handleResolvedUrl(.postStory(section)) case "settings": if let lastComponent = parsedUrl.pathComponents.last { + let fullPath = parsedUrl.pathComponents.joined(separator: "/").replacingOccurrences(of: "//", with: "") var section: ResolvedUrl.SettingsSection? - switch lastComponent { - case "themes": - section = .legacy(.theme) - case "devices": - section = .legacy(.devices) - case "enable_log": - section = .legacy(.enableLog) - case "phone_privacy": - section = .legacy(.phonePrivacy) - case "login_email": - section = .legacy(.loginEmail) - default: - let fullPath = parsedUrl.pathComponents.joined(separator: "/").replacingOccurrences(of: "//", with: "") + if parsedUrl.pathComponents.count == 2 { + switch lastComponent { + case "themes": + section = .legacy(.theme) + case "devices": + section = .legacy(.devices) + case "enable_log": + section = .legacy(.enableLog) + case "phone_privacy": + section = .legacy(.phonePrivacy) + case "login_email": + section = .legacy(.loginEmail) + default: + section = .path(fullPath) + } + } else { section = .path(fullPath) } if let section { diff --git a/submodules/UrlHandling/Sources/UrlHandling.swift b/submodules/UrlHandling/Sources/UrlHandling.swift index b2469ebd3f..a86210a23f 100644 --- a/submodules/UrlHandling/Sources/UrlHandling.swift +++ b/submodules/UrlHandling/Sources/UrlHandling.swift @@ -270,6 +270,18 @@ public func parseInternalUrl(sharedContext: SharedAccountContext, context: Accou return .peer(.id(peerId), .boost) } } + } else if peerName == "oauth" { + var token: String? + for queryItem in queryItems { + if let value = queryItem.value { + if queryItem.name == "startapp" { + token = value + } + } + } + if let token { + return .externalUrl(url: "tg://oauth?token=\(token)") + } } else { for queryItem in queryItems { if let value = queryItem.value {