Various fixes

This commit is contained in:
Ilya Laktyushin 2022-10-07 23:02:02 +03:00
parent 38c7c7e0a6
commit 45de8cbbd9
15 changed files with 290 additions and 66 deletions

View File

@ -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";

View File

@ -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)

View File

@ -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
}

View File

@ -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 {

View File

@ -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),

View File

@ -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

View File

@ -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)

View File

@ -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)
{

View File

@ -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))
}
}
}

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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 {

View File

@ -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