mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Various fixes
This commit is contained in:
parent
38c7c7e0a6
commit
45de8cbbd9
@ -8102,7 +8102,7 @@ Sorry for the inconvenience.";
|
||||
"Username.ActivateAlertShow" = "Show";
|
||||
|
||||
"Username.DeactivateAlertTitle" = "Deativate Username";
|
||||
"Username.DeactivateAlertText" = "Do you want to hode this link from your info page?";
|
||||
"Username.DeactivateAlertText" = "Do you want to hide this link from your info page?";
|
||||
"Username.DeactivateAlertHide" = "Hide";
|
||||
|
||||
"Profile.AdditionalUsernames" = "also %@";
|
||||
@ -8111,3 +8111,6 @@ Sorry for the inconvenience.";
|
||||
"EmojiSearch.SearchReactionsEmptyResult" = "No emoji found";
|
||||
"EmojiSearch.SearchStatusesPlaceholder" = "Search Statuses";
|
||||
"EmojiSearch.SearchStatusesEmptyResult" = "No emoji found";
|
||||
|
||||
"ChatList.StartAction" = "Start";
|
||||
"ChatList.CloseAction" = "Close";
|
||||
|
@ -826,7 +826,17 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
||||
})
|
||||
|
||||
if !previewing {
|
||||
self.searchContentNode = NavigationBarSearchContentNode(theme: self.presentationData.theme, placeholder: self.presentationData.strings.DialogList_SearchLabel, compactPlaceholder: self.presentationData.strings.DialogList_SearchLabelCompact, activate: { [weak self] in
|
||||
let placeholder: String
|
||||
let compactPlaceholder: String
|
||||
if case .forum = location {
|
||||
placeholder = self.presentationData.strings.Common_Search
|
||||
compactPlaceholder = self.presentationData.strings.Common_Search
|
||||
} else {
|
||||
placeholder = self.presentationData.strings.DialogList_SearchLabel
|
||||
compactPlaceholder = self.presentationData.strings.DialogList_SearchLabelCompact
|
||||
}
|
||||
|
||||
self.searchContentNode = NavigationBarSearchContentNode(theme: self.presentationData.theme, placeholder: placeholder, compactPlaceholder: compactPlaceholder, activate: { [weak self] in
|
||||
self?.activateSearch()
|
||||
})
|
||||
self.searchContentNode?.updateExpansionProgress(0.0)
|
||||
@ -2436,6 +2446,8 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
||||
}
|
||||
|
||||
public static func openMoreMenu(context: AccountContext, peerId: EnginePeer.Id, sourceController: ViewController, isViewingAsTopics: Bool, sourceView: UIView, gesture: ContextGesture?) {
|
||||
let strings = context.sharedContext.currentPresentationData.with { $0 }.strings
|
||||
|
||||
var items: [ContextMenuItem] = []
|
||||
|
||||
items.append(.action(ContextMenuActionItem(text: "View as Topics", icon: { theme in
|
||||
@ -2506,24 +2518,34 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
||||
|
||||
items.append(.separator)
|
||||
|
||||
//TODO:localize
|
||||
items.append(.action(ContextMenuActionItem(text: "New Topic", icon: { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Edit"), color: theme.contextMenu.primaryColor)
|
||||
}, action: { action in
|
||||
action.dismissWithResult(.default)
|
||||
|
||||
let controller = ForumCreateTopicScreen(context: context, peerId: peerId, mode: .create)
|
||||
controller.navigationPresentation = .modal
|
||||
controller.completion = { title, fileId in
|
||||
let _ = (context.engine.peers.createForumChannelTopic(id: peerId, title: title, iconFileId: fileId)
|
||||
|> deliverOnMainQueue).start(next: { topicId in
|
||||
if let navigationController = (sourceController.navigationController as? NavigationController) {
|
||||
let _ = context.sharedContext.navigateToForumThread(context: context, peerId: peerId, threadId: topicId, navigationController: navigationController, activateInput: .text).start()
|
||||
}
|
||||
})
|
||||
}
|
||||
sourceController.push(controller)
|
||||
})))
|
||||
if let sourceController = sourceController as? ChatController {
|
||||
items.append(.action(ContextMenuActionItem(text: strings.Conversation_Search, icon: { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Search"), color: theme.contextMenu.primaryColor)
|
||||
}, action: { [weak sourceController] action in
|
||||
action.dismissWithResult(.default)
|
||||
|
||||
sourceController?.beginMessageSearch("")
|
||||
})))
|
||||
} else {
|
||||
//TODO:localize
|
||||
items.append(.action(ContextMenuActionItem(text: "New Topic", icon: { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Edit"), color: theme.contextMenu.primaryColor)
|
||||
}, action: { action in
|
||||
action.dismissWithResult(.default)
|
||||
|
||||
let controller = ForumCreateTopicScreen(context: context, peerId: peerId, mode: .create)
|
||||
controller.navigationPresentation = .modal
|
||||
controller.completion = { title, fileId in
|
||||
let _ = (context.engine.peers.createForumChannelTopic(id: peerId, title: title, iconFileId: fileId)
|
||||
|> deliverOnMainQueue).start(next: { topicId in
|
||||
if let navigationController = (sourceController.navigationController as? NavigationController) {
|
||||
let _ = context.sharedContext.navigateToForumThread(context: context, peerId: peerId, threadId: topicId, navigationController: navigationController, activateInput: .text).start()
|
||||
}
|
||||
})
|
||||
}
|
||||
sourceController.push(controller)
|
||||
})))
|
||||
}
|
||||
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
let contextController = ContextController(account: context.account, presentationData: presentationData, source: .reference(HeaderContextReferenceContentSource(controller: sourceController, sourceView: sourceView)), items: .single(ContextController.Items(content: .list(items))), gesture: gesture)
|
||||
|
@ -226,6 +226,8 @@ private let archiveIcon = ItemListRevealOptionIcon.animation(animation: "anim_ar
|
||||
private let unarchiveIcon = ItemListRevealOptionIcon.animation(animation: "anim_unarchive", scale: 0.642, offset: -9.0, replaceColors: [0xa9a9ad], flip: false)
|
||||
private let hideIcon = ItemListRevealOptionIcon.animation(animation: "anim_hide", scale: 1.0, offset: 2.0, replaceColors: [0xbdbdc2], flip: false)
|
||||
private let unhideIcon = ItemListRevealOptionIcon.animation(animation: "anim_hide", scale: 1.0, offset: -20.0, replaceColors: [0xbdbdc2], flip: true)
|
||||
private let startIcon = ItemListRevealOptionIcon.animation(animation: "anim_pin", scale: 1.0, offset: 0.0, replaceColors: [0xbdbdc2], flip: false)
|
||||
private let closeIcon = ItemListRevealOptionIcon.animation(animation: "anim_pin", scale: 1.0, offset: 0.0, replaceColors: [0xbdbdc2], flip: false)
|
||||
|
||||
private enum RevealOptionKey: Int32 {
|
||||
case pin
|
||||
@ -241,6 +243,8 @@ private enum RevealOptionKey: Int32 {
|
||||
case hide
|
||||
case unhide
|
||||
case hidePsa
|
||||
case open
|
||||
case close
|
||||
}
|
||||
|
||||
private func canArchivePeer(id: EnginePeer.Id, accountPeerId: EnginePeer.Id) -> Bool {
|
||||
@ -264,8 +268,7 @@ public struct ChatListItemFilterData: Equatable {
|
||||
private func revealOptions(strings: PresentationStrings, theme: PresentationTheme, isPinned: Bool, isMuted: Bool?, location: ChatListControllerLocation, peerId: EnginePeer.Id, accountPeerId: EnginePeer.Id, canDelete: Bool, isEditing: Bool, filterData: ChatListItemFilterData?) -> [ItemListRevealOption] {
|
||||
var options: [ItemListRevealOption] = []
|
||||
if !isEditing {
|
||||
if case .forum = location {
|
||||
} else if case .chatList(.archive) = location {
|
||||
if case .chatList(.archive) = location {
|
||||
if isPinned {
|
||||
options.append(ItemListRevealOption(key: RevealOptionKey.unpin.rawValue, title: strings.DialogList_Unpin, icon: unpinIcon, color: theme.list.itemDisclosureActions.constructive.fillColor, textColor: theme.list.itemDisclosureActions.constructive.foregroundColor))
|
||||
} else {
|
||||
@ -323,6 +326,26 @@ private func groupReferenceRevealOptions(strings: PresentationStrings, theme: Pr
|
||||
return options
|
||||
}
|
||||
|
||||
private func forumRevealOptions(strings: PresentationStrings, theme: PresentationTheme, isMuted: Bool?, isEditing: Bool, canDelete: Bool) -> [ItemListRevealOption] {
|
||||
var options: [ItemListRevealOption] = []
|
||||
if !isEditing {
|
||||
if let isMuted = isMuted {
|
||||
if isMuted {
|
||||
options.append(ItemListRevealOption(key: RevealOptionKey.unmute.rawValue, title: strings.ChatList_Unmute, icon: unmuteIcon, color: theme.list.itemDisclosureActions.neutral2.fillColor, textColor: theme.list.itemDisclosureActions.neutral2.foregroundColor))
|
||||
} else {
|
||||
options.append(ItemListRevealOption(key: RevealOptionKey.mute.rawValue, title: strings.ChatList_Mute, icon: muteIcon, color: theme.list.itemDisclosureActions.neutral2.fillColor, textColor: theme.list.itemDisclosureActions.neutral2.foregroundColor))
|
||||
}
|
||||
}
|
||||
}
|
||||
if canDelete {
|
||||
options.append(ItemListRevealOption(key: RevealOptionKey.delete.rawValue, title: strings.Common_Delete, icon: deleteIcon, color: theme.list.itemDisclosureActions.destructive.fillColor, textColor: theme.list.itemDisclosureActions.destructive.foregroundColor))
|
||||
}
|
||||
if !isEditing {
|
||||
options.append(ItemListRevealOption(key: RevealOptionKey.close.rawValue, title: strings.ChatList_CloseAction, icon: closeIcon, color: theme.list.itemDisclosureActions.inactive.fillColor, textColor: theme.list.itemDisclosureActions.inactive.foregroundColor))
|
||||
}
|
||||
return options
|
||||
}
|
||||
|
||||
private func leftRevealOptions(strings: PresentationStrings, theme: PresentationTheme, isUnread: Bool, isEditing: Bool, isPinned: Bool, isSavedMessages: Bool, location: ChatListControllerLocation, peer: EnginePeer, filterData: ChatListItemFilterData?) -> [ItemListRevealOption] {
|
||||
guard case .chatList(.root) = location else {
|
||||
return []
|
||||
@ -1150,7 +1173,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
|
||||
let avatarLeftInset: CGFloat
|
||||
if case .forum = item.index {
|
||||
avatarLeftInset = 56.0
|
||||
avatarLeftInset = 50.0
|
||||
} else {
|
||||
avatarLeftInset = 18.0 + avatarDiameter
|
||||
}
|
||||
@ -1518,10 +1541,12 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
if hasFailedMessages {
|
||||
statusState = .failed(item.presentationData.theme.chatList.failedFillColor, item.presentationData.theme.chatList.failedForegroundColor)
|
||||
} else {
|
||||
if let combinedReadState = combinedReadState, combinedReadState.isOutgoingMessageIndexRead(message.index) {
|
||||
statusState = .read(item.presentationData.theme.chatList.checkmarkColor)
|
||||
} else {
|
||||
statusState = .delivered(item.presentationData.theme.chatList.checkmarkColor)
|
||||
if case .chatList = item.chatListLocation {
|
||||
if let combinedReadState = combinedReadState, combinedReadState.isOutgoingMessageIndexRead(message.index) {
|
||||
statusState = .read(item.presentationData.theme.chatList.checkmarkColor)
|
||||
} else {
|
||||
statusState = .delivered(item.presentationData.theme.chatList.checkmarkColor)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1764,7 +1789,10 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
}
|
||||
|
||||
if item.enableContextActions {
|
||||
if case .psa = promoInfo {
|
||||
if case .forum = item.chatListLocation {
|
||||
peerRevealOptions = forumRevealOptions(strings: item.presentationData.strings, theme: item.presentationData.theme, isMuted: (currentMutedIconImage != nil), isEditing: item.editing, canDelete: true)
|
||||
peerLeftRevealOptions = []
|
||||
} else if case .psa = promoInfo {
|
||||
peerRevealOptions = [
|
||||
ItemListRevealOption(key: RevealOptionKey.hidePsa.rawValue, title: item.presentationData.strings.ChatList_HideAction, icon: deleteIcon, color: item.presentationData.theme.list.itemDisclosureActions.inactive.fillColor, textColor: item.presentationData.theme.list.itemDisclosureActions.neutral1.foregroundColor)
|
||||
]
|
||||
@ -1929,9 +1957,9 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
|
||||
let avatarIconContent: EmojiStatusComponent.Content
|
||||
if let fileId = threadInfo.info.icon {
|
||||
avatarIconContent = .animation(content: .customEmoji(fileId: fileId), size: CGSize(width: 40.0, height: 40.0), placeholderColor: item.presentationData.theme.list.mediaPlaceholderColor, themeColor: nil, loopMode: .forever)
|
||||
avatarIconContent = .animation(content: .customEmoji(fileId: fileId), size: CGSize(width: 48.0, height: 48.0), placeholderColor: item.presentationData.theme.list.mediaPlaceholderColor, themeColor: nil, loopMode: .forever)
|
||||
} else {
|
||||
avatarIconContent = .topic(title: String(threadInfo.info.title.prefix(1)), colorIndex: Int(clamping: abs(threadInfo.id)))
|
||||
avatarIconContent = .topic(title: String(threadInfo.info.title.prefix(1)), colorIndex: Int(clamping: abs(threadInfo.id)), size: CGSize(width: 32.0, height: 32.0))
|
||||
}
|
||||
|
||||
let avatarIconComponent = EmojiStatusComponent(
|
||||
@ -1948,9 +1976,9 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
transition: .immediate,
|
||||
component: AnyComponent(avatarIconComponent),
|
||||
environment: {},
|
||||
containerSize: CGSize(width: 40.0, height: 40.0)
|
||||
containerSize: CGSize(width: 32.0, height: 32.0)
|
||||
)
|
||||
transition.updateFrame(view: avatarIconView, frame: CGRect(origin: CGPoint(x: params.leftInset + floor((leftInset - params.leftInset - iconSize.width) / 2.0), y: contentRect.origin.y + 2.0), size: iconSize))
|
||||
transition.updateFrame(view: avatarIconView, frame: CGRect(origin: CGPoint(x: params.leftInset + floor((leftInset - params.leftInset - iconSize.width) / 2.0) + revealOffset, y: contentRect.origin.y + 2.0), size: iconSize))
|
||||
} else if let avatarIconView = strongSelf.avatarIconView {
|
||||
strongSelf.avatarIconView = nil
|
||||
avatarIconView.removeFromSuperview()
|
||||
@ -2429,7 +2457,13 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
}
|
||||
|
||||
let avatarDiameter = min(60.0, floor(item.presentationData.fontSize.baseDisplaySize * 60.0 / 17.0))
|
||||
let avatarLeftInset = 18.0 + avatarDiameter
|
||||
|
||||
let avatarLeftInset: CGFloat
|
||||
if case .forum = item.index {
|
||||
avatarLeftInset = 50.0
|
||||
} else {
|
||||
avatarLeftInset = 18.0 + avatarDiameter
|
||||
}
|
||||
|
||||
let leftInset: CGFloat = params.leftInset + avatarLeftInset
|
||||
|
||||
@ -2445,6 +2479,12 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
transition.updateFrame(node: videoNode, frame: CGRect(origin: .zero, size: avatarFrame.size))
|
||||
}
|
||||
|
||||
if let avatarIconView = self.avatarIconView {
|
||||
var avatarIconFrame = avatarIconView.frame
|
||||
avatarIconFrame.origin.x = params.leftInset + floor((leftInset - params.leftInset - avatarIconFrame.width) / 2.0) + offset
|
||||
transition.updateFrame(view: avatarIconView, frame: avatarIconFrame)
|
||||
}
|
||||
|
||||
var onlineFrame = self.onlineNode.frame
|
||||
if self.onlineIsVoiceChat {
|
||||
onlineFrame.origin.x = avatarFrame.maxX - onlineFrame.width + 1.0 - UIScreenPixel
|
||||
@ -2633,6 +2673,10 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
self.animateRevealOptionsFill {
|
||||
self.revealOptionsInteractivelyClosed()
|
||||
}
|
||||
case RevealOptionKey.open.rawValue:
|
||||
break
|
||||
case RevealOptionKey.close.rawValue:
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
@ -66,10 +66,6 @@ public final class CodeInputView: ASDisplayNode, UITextFieldDelegate {
|
||||
self.borderColorValue = borderColor
|
||||
|
||||
let previousColor = self.backgroundView.layer.borderColor
|
||||
self.backgroundView.layer.cornerRadius = 15.0
|
||||
if #available(iOS 13.0, *) {
|
||||
self.backgroundView.layer.cornerCurve = .continuous
|
||||
}
|
||||
self.backgroundView.layer.borderColor = UIColor(argb: borderColor).cgColor
|
||||
self.backgroundView.layer.borderWidth = 1.0 + UIScreenPixel
|
||||
if let previousColor = previousColor {
|
||||
@ -98,6 +94,11 @@ public final class CodeInputView: ASDisplayNode, UITextFieldDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
self.backgroundView.layer.cornerRadius = size.height == 28.0 ? 12.0 : 15.0
|
||||
if #available(iOS 13.0, *) {
|
||||
self.backgroundView.layer.cornerCurve = .continuous
|
||||
}
|
||||
|
||||
if #available(iOS 13.0, *) {
|
||||
self.textNode.attributedText = NSAttributedString(string: text, font: UIFont.monospacedSystemFont(ofSize: fontSize, weight: .regular), textColor: UIColor(argb: textColor))
|
||||
} else {
|
||||
|
@ -974,9 +974,17 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
|
||||
if let _ = self.presentationNode {
|
||||
self.currentPresentationStateTransition = .animateOut(result: initialResult, completion: completion)
|
||||
if let validLayout = self.validLayout {
|
||||
self.delayLayoutUpdate = true
|
||||
Queue.mainQueue().after(0.05) {
|
||||
self.delayLayoutUpdate = false
|
||||
if case .custom = initialResult {
|
||||
self.delayLayoutUpdate = true
|
||||
Queue.mainQueue().after(0.05) {
|
||||
self.delayLayoutUpdate = false
|
||||
self.updateLayout(
|
||||
layout: validLayout,
|
||||
transition: .animated(duration: 0.35, curve: .easeInOut),
|
||||
previousActionsContainerNode: nil
|
||||
)
|
||||
}
|
||||
} else {
|
||||
self.updateLayout(
|
||||
layout: validLayout,
|
||||
transition: .animated(duration: 0.35, curve: .easeInOut),
|
||||
|
@ -222,7 +222,9 @@ public enum DeviceMetrics: CaseIterable, Equatable {
|
||||
|
||||
var statusBarHeight: CGFloat {
|
||||
switch self {
|
||||
case .iPhoneX, .iPhoneXSMax, .iPhoneXr, .iPhone12Mini, .iPhone12, .iPhone12ProMax, .iPhone13Mini, .iPhone13, .iPhone13Pro, .iPhone13ProMax, .iPhone14Pro, .iPhone14ProMax:
|
||||
case .iPhone14Pro, .iPhone14ProMax:
|
||||
return 54.0
|
||||
case .iPhoneX, .iPhoneXSMax, .iPhoneXr, .iPhone12Mini, .iPhone12, .iPhone12ProMax, .iPhone13Mini, .iPhone13, .iPhone13Pro, .iPhone13ProMax:
|
||||
return 44.0
|
||||
case .iPadPro11Inch, .iPadPro3rdGen, .iPadMini, .iPadMini6thGen:
|
||||
return 24.0
|
||||
|
@ -2723,13 +2723,13 @@ static CGPoint TGCameraControllerClampPointToScreenSize(__unused id self, __unus
|
||||
default:
|
||||
{
|
||||
if (widescreenWidth == 932.0f)
|
||||
return CGRectMake(0, 121, screenSize.width, screenSize.height - 121 - 234);
|
||||
if (widescreenWidth == 926.0f)
|
||||
return CGRectMake(0, 136, screenSize.width, screenSize.height - 136 - 223);
|
||||
else if (widescreenWidth == 926.0f)
|
||||
return CGRectMake(0, 121, screenSize.width, screenSize.height - 121 - 234);
|
||||
else if (widescreenWidth == 896.0f)
|
||||
return CGRectMake(0, 121, screenSize.width, screenSize.height - 121 - 223);
|
||||
if (widescreenWidth == 852.0f)
|
||||
return CGRectMake(0, 121, screenSize.width, screenSize.height - 121 - 234);
|
||||
return CGRectMake(0, 136, screenSize.width, screenSize.height - 136 - 192);
|
||||
else if (widescreenWidth == 844.0f)
|
||||
return CGRectMake(0, 77, screenSize.width, screenSize.height - 77 - 191);
|
||||
else if (widescreenWidth == 812.0f)
|
||||
|
@ -115,16 +115,16 @@
|
||||
CGFloat widescreenWidth = MAX(screenSize.width, screenSize.height);
|
||||
if (widescreenWidth == 932.0f)
|
||||
{
|
||||
_topPanelOffset = 34.0f;
|
||||
_topPanelOffset = 48.0f;
|
||||
_topPanelHeight = 48.0f;
|
||||
_bottomPanelOffset = 94.0f;
|
||||
_bottomPanelOffset = 83.0f;
|
||||
_bottomPanelHeight = 140.0f;
|
||||
_modeControlOffset = -2.0f;
|
||||
_modeControlOffset = -1.0f;
|
||||
_modeControlHeight = 66.0f;
|
||||
_counterOffset = 7.0f;
|
||||
shutterButtonWidth = 72.0f;
|
||||
}
|
||||
if (widescreenWidth == 926.0f)
|
||||
else if (widescreenWidth == 926.0f)
|
||||
{
|
||||
_topPanelOffset = 34.0f;
|
||||
_topPanelHeight = 48.0f;
|
||||
@ -148,14 +148,14 @@
|
||||
}
|
||||
else if (widescreenWidth == 852.0f)
|
||||
{
|
||||
_topPanelOffset = 33.0f;
|
||||
_topPanelOffset = 48.0f;
|
||||
_topPanelHeight = 44.0f;
|
||||
_bottomPanelOffset = 63.0f;
|
||||
_bottomPanelHeight = 128.0f;
|
||||
_modeControlOffset = 3.0f;
|
||||
_modeControlHeight = 40.0f;
|
||||
_modeControlOffset = -1.0f;
|
||||
_modeControlHeight = 51.0f;
|
||||
_counterOffset = 7.0f;
|
||||
shutterButtonWidth = 70.0f;
|
||||
shutterButtonWidth = 72.0f;
|
||||
}
|
||||
else if (widescreenWidth == 844.0f)
|
||||
{
|
||||
|
@ -25,6 +25,8 @@ func cloudChatAddClearHistoryOperation(transaction: Transaction, peerId: PeerId,
|
||||
}
|
||||
if let topMessageId = topMessageId {
|
||||
transaction.operationLogAddEntry(peerId: peerId, tag: OperationLogTags.CloudChatRemoveMessages, tagLocalIndex: .automatic, tagMergedIndex: .automatic, contents: CloudChatClearHistoryOperation(peerId: peerId, topMessageId: topMessageId, minTimestamp: minTimestamp, maxTimestamp: maxTimestamp, type: type))
|
||||
} else if case .forEveryone = type {
|
||||
transaction.operationLogAddEntry(peerId: peerId, tag: OperationLogTags.CloudChatRemoveMessages, tagLocalIndex: .automatic, tagMergedIndex: .automatic, contents: CloudChatClearHistoryOperation(peerId: peerId, topMessageId: MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: .max), minTimestamp: minTimestamp, maxTimestamp: maxTimestamp, type: type))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ public final class EmojiStatusComponent: Component {
|
||||
case verified(fillColor: UIColor, foregroundColor: UIColor, sizeType: SizeType)
|
||||
case text(color: UIColor, string: String)
|
||||
case animation(content: AnimationContent, size: CGSize, placeholderColor: UIColor, themeColor: UIColor?, loopMode: LoopMode)
|
||||
case topic(title: String, colorIndex: Int)
|
||||
case topic(title: String, colorIndex: Int, size: CGSize)
|
||||
}
|
||||
|
||||
public let context: AccountContext
|
||||
@ -223,15 +223,16 @@ public final class EmojiStatusComponent: Component {
|
||||
} else {
|
||||
iconImage = nil
|
||||
}
|
||||
case let .topic(title, colorIndex):
|
||||
case let .topic(title, colorIndex, size):
|
||||
func generateTopicIcon(backgroundColors: [UIColor], strokeColors: [UIColor]) -> UIImage? {
|
||||
return generateImage(CGSize(width: 44.0, height: 44.0), rotatedContext: { size, context in
|
||||
return generateImage(size, rotatedContext: { size, context in
|
||||
context.clear(CGRect(origin: .zero, size: size))
|
||||
|
||||
|
||||
context.saveGState()
|
||||
|
||||
let scale: CGFloat = size.width / 32.0
|
||||
context.translateBy(x: size.width / 2.0, y: size.height / 2.0)
|
||||
context.scaleBy(x: 1.333, y: 1.333)
|
||||
context.scaleBy(x: scale, y: scale)
|
||||
context.translateBy(x: -14.0 - UIScreenPixel, y: -14.0 - UIScreenPixel)
|
||||
|
||||
let _ = try? drawSvgPath(context, path: "M24.1835,4.71703 C21.7304,2.42169 18.2984,0.995605 14.5,0.995605 C7.04416,0.995605 1.0,6.49029 1.0,13.2683 C1.0,17.1341 2.80572,20.3028 5.87839,22.5523 C6.27132,22.84 6.63324,24.4385 5.75738,25.7811 C5.39922,26.3301 5.00492,26.7573 4.70138,27.0861 C4.26262,27.5614 4.01347,27.8313 4.33716,27.967 C4.67478,28.1086 6.66968,28.1787 8.10952,27.3712 C9.23649,26.7392 9.91903,26.1087 10.3787,25.6842 C10.7588,25.3331 10.9864,25.1228 11.187,25.1688 C11.9059,25.3337 12.6478,25.4461 13.4075,25.5015 C13.4178,25.5022 13.4282,25.503 13.4386,25.5037 C13.7888,25.5284 14.1428,25.5411 14.5,25.5411 C21.9558,25.5411 28.0,20.0464 28.0,13.2683 C28.0,9.94336 26.5455,6.92722 24.1835,4.71703 ")
|
||||
@ -248,7 +249,7 @@ public final class EmojiStatusComponent: Component {
|
||||
let _ = try? drawSvgPath(context, path: "M24.1835,4.71703 C21.7304,2.42169 18.2984,0.995605 14.5,0.995605 C7.04416,0.995605 1.0,6.49029 1.0,13.2683 C1.0,17.1341 2.80572,20.3028 5.87839,22.5523 C6.27132,22.84 6.63324,24.4385 5.75738,25.7811 C5.39922,26.3301 5.00492,26.7573 4.70138,27.0861 C4.26262,27.5614 4.01347,27.8313 4.33716,27.967 C4.67478,28.1086 6.66968,28.1787 8.10952,27.3712 C9.23649,26.7392 9.91903,26.1087 10.3787,25.6842 C10.7588,25.3331 10.9864,25.1228 11.187,25.1688 C11.9059,25.3337 12.6478,25.4461 13.4075,25.5015 C13.4178,25.5022 13.4282,25.503 13.4386,25.5037 C13.7888,25.5284 14.1428,25.5411 14.5,25.5411 C21.9558,25.5411 28.0,20.0464 28.0,13.2683 C28.0,9.94336 26.5455,6.92722 24.1835,4.71703 ")
|
||||
context.closePath()
|
||||
if let path = context.path {
|
||||
let strokePath = path.copy(strokingWithWidth: 1.0, lineCap: .round, lineJoin: .round, miterLimit: 0.0)
|
||||
let strokePath = path.copy(strokingWithWidth: 1.0 + UIScreenPixel, lineCap: .round, lineJoin: .round, miterLimit: 0.0)
|
||||
context.beginPath()
|
||||
context.addPath(strokePath)
|
||||
context.clip()
|
||||
@ -261,13 +262,16 @@ public final class EmojiStatusComponent: Component {
|
||||
|
||||
context.restoreGState()
|
||||
|
||||
let attributedString = NSAttributedString(string: title, attributes: [NSAttributedString.Key.font: Font.with(size: 19.0, design: .round, weight: .bold), NSAttributedString.Key.foregroundColor: UIColor.white])
|
||||
let fontSize = round(15.0 * scale)
|
||||
|
||||
let attributedString = NSAttributedString(string: title, attributes: [NSAttributedString.Key.font: Font.with(size: fontSize, design: .round, weight: .bold), NSAttributedString.Key.foregroundColor: UIColor.white])
|
||||
|
||||
let line = CTLineCreateWithAttributedString(attributedString)
|
||||
let lineBounds = CTLineGetBoundsWithOptions(line, .useGlyphPathBounds)
|
||||
|
||||
let lineOffset = CGPoint(x: title == "B" ? 1.0 : 0.0, y: 0.0)
|
||||
let lineOrigin = CGPoint(x: floorToScreenPixels(-lineBounds.origin.x + (size.width - lineBounds.size.width) / 2.0) + lineOffset.x, y: floorToScreenPixels(-lineBounds.origin.y + (size.height - lineBounds.size.height) / 2.0) + 2.0)
|
||||
|
||||
let lineOffset = CGPoint(x: title == "B" ? 1.0 : 0.0, y: floorToScreenPixels(0.67 * scale))
|
||||
let lineOrigin = CGPoint(x: floorToScreenPixels(-lineBounds.origin.x + (size.width - lineBounds.size.width) / 2.0) + lineOffset.x, y: floorToScreenPixels(-lineBounds.origin.y + (size.height - lineBounds.size.height) / 2.0) + lineOffset.y)
|
||||
|
||||
context.translateBy(x: size.width / 2.0, y: size.height / 2.0)
|
||||
context.scaleBy(x: 1.0, y: -1.0)
|
||||
|
@ -106,9 +106,9 @@ private final class TitleFieldComponent: Component {
|
||||
|
||||
let iconContent: EmojiStatusComponent.Content
|
||||
if component.fileId == 0 {
|
||||
iconContent = .topic(title: String(component.text.prefix(1)), colorIndex: 0)
|
||||
iconContent = .topic(title: String(component.text.prefix(1)), colorIndex: 0, size: CGSize(width: 32.0, height: 32.0))
|
||||
} else {
|
||||
iconContent = .animation(content: .customEmoji(fileId: component.fileId), size: CGSize(width: 32.0, height: 32.0), placeholderColor: component.placeholderColor, themeColor: component.accentColor, loopMode: .count(2))
|
||||
iconContent = .animation(content: .customEmoji(fileId: component.fileId), size: CGSize(width: 48.0, height: 48.0), placeholderColor: component.placeholderColor, themeColor: component.accentColor, loopMode: .count(2))
|
||||
}
|
||||
|
||||
let iconSize = self.iconView.update(
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 5.0 KiB |
@ -836,13 +836,13 @@ final class ChatEmptyNodeTopicChatContent: ASDisplayNode, ChatEmptyNodeContent,
|
||||
let title = ""
|
||||
let iconContent: EmojiStatusComponent.Content
|
||||
if let fileId = self.fileId {
|
||||
iconContent = .animation(content: .customEmoji(fileId: fileId), size: CGSize(width: 32.0, height: 32.0), placeholderColor: .clear, themeColor: serviceColor.primaryText, loopMode: .count(2))
|
||||
iconContent = .animation(content: .customEmoji(fileId: fileId), size: CGSize(width: 54.0, height: 54.0), placeholderColor: .clear, themeColor: serviceColor.primaryText, loopMode: .count(2))
|
||||
} else {
|
||||
var colorIndex: Int = 0
|
||||
if case let .replyThread(replyThreadMessage) = interfaceState.chatLocation {
|
||||
colorIndex = Int(clamping: abs(replyThreadMessage.effectiveTopId.id))
|
||||
}
|
||||
iconContent = .topic(title: String(title.prefix(1)), colorIndex: colorIndex)
|
||||
iconContent = .topic(title: String(title.prefix(1)), colorIndex: colorIndex, size: CGSize(width: 64.0, height: 64.0))
|
||||
}
|
||||
|
||||
let insets = UIEdgeInsets(top: inset, left: inset, bottom: inset, right: inset)
|
||||
|
@ -7,7 +7,7 @@ import AccountContext
|
||||
import ChatPresentationInterfaceState
|
||||
|
||||
func inputNodeForChatPresentationIntefaceState(_ chatPresentationInterfaceState: ChatPresentationInterfaceState, context: AccountContext, currentNode: ChatInputNode?, interfaceInteraction: ChatPanelInterfaceInteraction?, inputMediaNode: ChatMediaInputNode?, controllerInteraction: ChatControllerInteraction, inputPanelNode: ChatInputPanelNode?, makeMediaInputNode: () -> ChatInputNode?) -> ChatInputNode? {
|
||||
if !(inputPanelNode is ChatTextInputPanelNode) {
|
||||
if let inputPanelNode = inputPanelNode, !(inputPanelNode is ChatTextInputPanelNode) {
|
||||
return nil
|
||||
}
|
||||
switch chatPresentationInterfaceState.inputMode {
|
||||
|
@ -4427,6 +4427,75 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
|
||||
})))
|
||||
}
|
||||
|
||||
if canSetupAutoremoveTimeout {
|
||||
let strings = strongSelf.presentationData.strings
|
||||
items.append(.action(ContextMenuActionItem(text: currentAutoremoveTimeout == nil ? strongSelf.presentationData.strings.PeerInfo_EnableAutoDelete : strongSelf.presentationData.strings.PeerInfo_AdjustAutoDelete, icon: { theme in
|
||||
if let currentAutoremoveTimeout = currentAutoremoveTimeout {
|
||||
let text = NSAttributedString(string: shortTimeIntervalString(strings: strings, value: currentAutoremoveTimeout), font: Font.regular(14.0), textColor: theme.contextMenu.primaryColor)
|
||||
let bounds = text.boundingRect(with: CGSize(width: 100.0, height: 100.0), options: .usesLineFragmentOrigin, context: nil)
|
||||
return generateImage(bounds.size.integralFloor, rotatedContext: { size, context in
|
||||
context.clear(CGRect(origin: CGPoint(), size: size))
|
||||
UIGraphicsPushContext(context)
|
||||
text.draw(in: bounds)
|
||||
UIGraphicsPopContext()
|
||||
})
|
||||
} else {
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Timer"), color: theme.contextMenu.primaryColor)
|
||||
}
|
||||
}, action: { [weak self] c, _ in
|
||||
var subItems: [ContextMenuItem] = []
|
||||
|
||||
subItems.append(.action(ContextMenuActionItem(text: strings.Common_Back, icon: { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Back"), color: theme.contextMenu.primaryColor)
|
||||
}, action: { c, _ in
|
||||
c.popItems()
|
||||
})))
|
||||
subItems.append(.separator)
|
||||
|
||||
let presetValues: [Int32] = [
|
||||
1 * 24 * 60 * 60,
|
||||
7 * 24 * 60 * 60,
|
||||
31 * 24 * 60 * 60
|
||||
]
|
||||
|
||||
for value in presetValues {
|
||||
subItems.append(.action(ContextMenuActionItem(text: timeIntervalString(strings: strings, value: value), icon: { _ in
|
||||
return nil
|
||||
}, action: { _, f in
|
||||
f(.default)
|
||||
|
||||
self?.setAutoremove(timeInterval: value)
|
||||
})))
|
||||
}
|
||||
|
||||
subItems.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.PeerInfo_AutoDeleteSettingOther, icon: { _ in
|
||||
return nil
|
||||
}, action: { _, f in
|
||||
f(.default)
|
||||
|
||||
self?.openAutoremove(currentValue: currentAutoremoveTimeout)
|
||||
})))
|
||||
|
||||
if let _ = currentAutoremoveTimeout {
|
||||
subItems.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.PeerInfo_AutoDeleteDisable, textColor: .destructive, icon: { _ in
|
||||
return nil
|
||||
}, action: { _, f in
|
||||
f(.default)
|
||||
|
||||
self?.setAutoremove(timeInterval: nil)
|
||||
})))
|
||||
}
|
||||
|
||||
subItems.append(.separator)
|
||||
|
||||
subItems.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.PeerInfo_AutoDeleteInfo, textLayout: .multiline, textFont: .small, icon: { _ in
|
||||
return nil
|
||||
}, action: nil as ((ContextControllerProtocol, @escaping (ContextMenuActionResult) -> Void) -> Void)?)))
|
||||
|
||||
c.pushItems(items: .single(ContextController.Items(content: .list(subItems))))
|
||||
})))
|
||||
}
|
||||
|
||||
let clearPeerHistory = ClearPeerHistory(context: strongSelf.context, peer: channel, chatPeer: channel, cachedData: strongSelf.data?.cachedData)
|
||||
if clearPeerHistory.canClearForMyself != nil || clearPeerHistory.canClearForEveryone != nil {
|
||||
items.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.PeerInfo_ClearMessages, icon: { theme in
|
||||
@ -4474,6 +4543,75 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
|
||||
}
|
||||
}
|
||||
} else if let group = peer as? TelegramGroup {
|
||||
if canSetupAutoremoveTimeout {
|
||||
let strings = strongSelf.presentationData.strings
|
||||
items.append(.action(ContextMenuActionItem(text: currentAutoremoveTimeout == nil ? strongSelf.presentationData.strings.PeerInfo_EnableAutoDelete : strongSelf.presentationData.strings.PeerInfo_AdjustAutoDelete, icon: { theme in
|
||||
if let currentAutoremoveTimeout = currentAutoremoveTimeout {
|
||||
let text = NSAttributedString(string: shortTimeIntervalString(strings: strings, value: currentAutoremoveTimeout), font: Font.regular(14.0), textColor: theme.contextMenu.primaryColor)
|
||||
let bounds = text.boundingRect(with: CGSize(width: 100.0, height: 100.0), options: .usesLineFragmentOrigin, context: nil)
|
||||
return generateImage(bounds.size.integralFloor, rotatedContext: { size, context in
|
||||
context.clear(CGRect(origin: CGPoint(), size: size))
|
||||
UIGraphicsPushContext(context)
|
||||
text.draw(in: bounds)
|
||||
UIGraphicsPopContext()
|
||||
})
|
||||
} else {
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Timer"), color: theme.contextMenu.primaryColor)
|
||||
}
|
||||
}, action: { [weak self] c, _ in
|
||||
var subItems: [ContextMenuItem] = []
|
||||
|
||||
subItems.append(.action(ContextMenuActionItem(text: strings.Common_Back, icon: { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Back"), color: theme.contextMenu.primaryColor)
|
||||
}, action: { c, _ in
|
||||
c.popItems()
|
||||
})))
|
||||
subItems.append(.separator)
|
||||
|
||||
let presetValues: [Int32] = [
|
||||
1 * 24 * 60 * 60,
|
||||
7 * 24 * 60 * 60,
|
||||
31 * 24 * 60 * 60
|
||||
]
|
||||
|
||||
for value in presetValues {
|
||||
subItems.append(.action(ContextMenuActionItem(text: timeIntervalString(strings: strings, value: value), icon: { _ in
|
||||
return nil
|
||||
}, action: { _, f in
|
||||
f(.default)
|
||||
|
||||
self?.setAutoremove(timeInterval: value)
|
||||
})))
|
||||
}
|
||||
|
||||
subItems.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.PeerInfo_AutoDeleteSettingOther, icon: { _ in
|
||||
return nil
|
||||
}, action: { _, f in
|
||||
f(.default)
|
||||
|
||||
self?.openAutoremove(currentValue: currentAutoremoveTimeout)
|
||||
})))
|
||||
|
||||
if let _ = currentAutoremoveTimeout {
|
||||
subItems.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.PeerInfo_AutoDeleteDisable, textColor: .destructive, icon: { _ in
|
||||
return nil
|
||||
}, action: { _, f in
|
||||
f(.default)
|
||||
|
||||
self?.setAutoremove(timeInterval: nil)
|
||||
})))
|
||||
}
|
||||
|
||||
subItems.append(.separator)
|
||||
|
||||
subItems.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.PeerInfo_AutoDeleteInfo, textLayout: .multiline, textFont: .small, icon: { _ in
|
||||
return nil
|
||||
}, action: nil as ((ContextControllerProtocol, @escaping (ContextMenuActionResult) -> Void) -> Void)?)))
|
||||
|
||||
c.pushItems(items: .single(ContextController.Items(content: .list(subItems))))
|
||||
})))
|
||||
}
|
||||
|
||||
let clearPeerHistory = ClearPeerHistory(context: strongSelf.context, peer: group, chatPeer: group, cachedData: strongSelf.data?.cachedData)
|
||||
if clearPeerHistory.canClearForMyself != nil || clearPeerHistory.canClearForEveryone != nil {
|
||||
items.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.PeerInfo_ClearMessages, icon: { theme in
|
||||
|
Loading…
x
Reference in New Issue
Block a user