From d55c2019c18133c9d884f0f078d8103d8f641aec Mon Sep 17 00:00:00 2001 From: Lev Poznyakov Date: Sun, 12 Apr 2026 16:45:31 +0400 Subject: [PATCH 1/9] flag --- Swiftgram/SGSettingsUI/Sources/SGSettingsController.swift | 4 ++++ Swiftgram/SGSimpleSettings/Sources/SimpleSettings.swift | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/Swiftgram/SGSettingsUI/Sources/SGSettingsController.swift b/Swiftgram/SGSettingsUI/Sources/SGSettingsController.swift index da487fa1c9..63123511ed 100644 --- a/Swiftgram/SGSettingsUI/Sources/SGSettingsController.swift +++ b/Swiftgram/SGSettingsUI/Sources/SGSettingsController.swift @@ -96,6 +96,7 @@ private enum SGBoolSetting: String { case defaultEmojisFirst case messageDoubleTapActionOutgoingEdit case wideChannelPosts + case wideGlass case forceEmojiTab case forceBuiltInMic case secondsInMessages @@ -309,6 +310,7 @@ private func SGControllerEntries(presentationData: PresentationData, callListSet entries.append(.notice(id: id.count, section: .other, text: i18n("Settings.swipeForVideoPIP.Notice", lang))) entries.append(.toggle(id: id.count, section: .other, settingName: .hideChannelBottomButton, value: !SGSimpleSettings.shared.hideChannelBottomButton, text: i18n("Settings.showChannelBottomButton", lang), enabled: true)) entries.append(.toggle(id: id.count, section: .other, settingName: .wideChannelPosts, value: SGSimpleSettings.shared.wideChannelPosts, text: i18n("Settings.wideChannelPosts", lang), enabled: true)) + entries.append(.toggle(id: id.count, section: .other, settingName: .wideGlass, value: SGSimpleSettings.shared.wideGlass, text: i18n("Settings.wideGlass", lang), enabled: true)) entries.append(.toggle(id: id.count, section: .other, settingName: .secondsInMessages, value: SGSimpleSettings.shared.secondsInMessages, text: i18n("Settings.secondsInMessages", lang), enabled: true)) entries.append(.toggle(id: id.count, section: .other, settingName: .messageDoubleTapActionOutgoingEdit, value: SGSimpleSettings.shared.messageDoubleTapActionOutgoing == SGSimpleSettings.MessageDoubleTapAction.edit.rawValue, text: i18n("Settings.messageDoubleTapActionOutgoingEdit", lang), enabled: true)) entries.append(.toggle(id: id.count, section: .other, settingName: .hideRecordingButton, value: !SGSimpleSettings.shared.hideRecordingButton, text: i18n("Settings.RecordingButton", lang), enabled: true)) @@ -494,6 +496,8 @@ public func sgSettingsController(context: AccountContext/*, focusOnItemTag: Int? SGSimpleSettings.shared.messageDoubleTapActionOutgoing = value ? SGSimpleSettings.MessageDoubleTapAction.edit.rawValue : SGSimpleSettings.MessageDoubleTapAction.default.rawValue case .wideChannelPosts: SGSimpleSettings.shared.wideChannelPosts = value + case .wideGlass: + SGSimpleSettings.shared.wideGlass = value case .forceEmojiTab: SGSimpleSettings.shared.forceEmojiTab = value case .forceBuiltInMic: diff --git a/Swiftgram/SGSimpleSettings/Sources/SimpleSettings.swift b/Swiftgram/SGSimpleSettings/Sources/SimpleSettings.swift index 2db47deb51..30a146ede8 100644 --- a/Swiftgram/SGSimpleSettings/Sources/SimpleSettings.swift +++ b/Swiftgram/SGSimpleSettings/Sources/SimpleSettings.swift @@ -149,6 +149,7 @@ public class SGSimpleSettings { case defaultEmojisFirst case messageDoubleTapActionOutgoing case wideChannelPosts + case wideGlass case forceEmojiTab case forceBuiltInMic case secondsInMessages @@ -307,6 +308,7 @@ public class SGSimpleSettings { Keys.defaultEmojisFirst.rawValue: false, Keys.messageDoubleTapActionOutgoing.rawValue: MessageDoubleTapAction.default.rawValue, Keys.wideChannelPosts.rawValue: false, + Keys.wideGlass.rawValue: false, Keys.forceEmojiTab.rawValue: false, Keys.hideChannelBottomButton.rawValue: false, Keys.secondsInMessages.rawValue: false, @@ -518,6 +520,9 @@ public class SGSimpleSettings { @UserDefault(key: Keys.wideChannelPosts.rawValue) public var wideChannelPosts: Bool + + @UserDefault(key: Keys.wideGlass.rawValue) + public var wideGlass: Bool @UserDefault(key: Keys.forceEmojiTab.rawValue) public var forceEmojiTab: Bool From 0280ba3ee5eb91f5c6c3e17f41a2f75b7d99e09c Mon Sep 17 00:00:00 2001 From: Lev Poznyakov Date: Sun, 12 Apr 2026 17:47:03 +0400 Subject: [PATCH 2/9] wip --- .../ChatTextInputActionButtonsNode.swift | 6 +- .../Sources/ChatTextInputPanelNode.swift | 262 +++++++++++++++--- 2 files changed, 228 insertions(+), 40 deletions(-) diff --git a/submodules/TelegramUI/Components/Chat/ChatTextInputActionButtonsNode/Sources/ChatTextInputActionButtonsNode.swift b/submodules/TelegramUI/Components/Chat/ChatTextInputActionButtonsNode/Sources/ChatTextInputActionButtonsNode.swift index 123c96a69f..cb674423fe 100644 --- a/submodules/TelegramUI/Components/Chat/ChatTextInputActionButtonsNode/Sources/ChatTextInputActionButtonsNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatTextInputActionButtonsNode/Sources/ChatTextInputActionButtonsNode.swift @@ -303,7 +303,7 @@ public final class ChatTextInputActionButtonsNode: ASDisplayNode, ChatSendMessag } } - public func updateLayout(size: CGSize, isMediaInputExpanded: Bool, showTitle: Bool, currentMessageEffectId: Int64?, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState) -> CGSize { + public func updateLayout(size: CGSize, isMediaInputExpanded: Bool, showTitle: Bool, currentMessageEffectId: Int64?, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, mergeBackgroundIntoInputField: Bool = false) -> CGSize { self.validLayout = size var innerSize = size @@ -365,7 +365,7 @@ public final class ChatTextInputActionButtonsNode: ASDisplayNode, ChatSendMessag } transition.updateFrame(view: self.micButtonBackgroundView, frame: CGRect(origin: CGPoint(), size: size)) - self.micButtonBackgroundView.update(size: size, cornerRadius: size.height * 0.5, isDark: interfaceState.theme.overallDarkAppearance, tintColor: defaultGlassTintColor, isInteractive: true, transition: ComponentTransition(transition)) + self.micButtonBackgroundView.update(size: size, cornerRadius: size.height * 0.5, isDark: interfaceState.theme.overallDarkAppearance, tintColor: defaultGlassTintColor, isInteractive: true, isVisible: !mergeBackgroundIntoInputField, transition: ComponentTransition(transition)) transition.updatePosition(layer: self.micButton.layer, position: CGRect(origin: CGPoint(), size: size).center) transition.updateBounds(layer: self.micButton.layer, bounds: CGRect(origin: CGPoint(), size: size)) @@ -504,7 +504,7 @@ public final class ChatTextInputActionButtonsNode: ASDisplayNode, ChatSendMessag transition.updateFrame(view: self.expandMediaInputButton, frame: CGRect(origin: CGPoint(), size: size)) transition.updateFrame(view: self.expandMediaInputButtonBackgroundView, frame: CGRect(origin: CGPoint(), size: size)) - self.expandMediaInputButtonBackgroundView.update(size: size, cornerRadius: size.height * 0.5, isDark: interfaceState.theme.overallDarkAppearance, tintColor: defaultGlassTintColor, isInteractive: true, transition: ComponentTransition(transition)) + self.expandMediaInputButtonBackgroundView.update(size: size, cornerRadius: size.height * 0.5, isDark: interfaceState.theme.overallDarkAppearance, tintColor: defaultGlassTintColor, isInteractive: true, isVisible: !mergeBackgroundIntoInputField, transition: ComponentTransition(transition)) if let image = self.expandMediaInputButtonIcon.image { let expandIconFrame = CGRect(origin: CGPoint(x: floor((size.width - image.size.width) * 0.5), y: floor((size.height - image.size.height) * 0.5)), size: image.size) self.expandMediaInputButtonIcon.center = expandIconFrame.center diff --git a/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/ChatTextInputPanelNode.swift b/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/ChatTextInputPanelNode.swift index cf02dbb0ef..03d258eb44 100644 --- a/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/ChatTextInputPanelNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/ChatTextInputPanelNode.swift @@ -308,7 +308,7 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg private var validLayout: (CGFloat, CGFloat, CGFloat, CGFloat, UIEdgeInsets, CGFloat, CGFloat, LayoutMetrics, Bool, Bool, DeviceMetrics)? private var leftMenuInset: CGFloat = 0.0 private var rightSlowModeInset: CGFloat = 0.0 - private var currentTextInputBackgroundWidthOffset: CGFloat = 0.0 + private var currentWideGlassLayout: WideGlassLayout = .disabled private var enableBounceAnimations: Bool = false @@ -415,6 +415,28 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg case stars(count: Int, isFilled: Bool, action: (UIView) -> Void, longPressAction: ((UIView) -> Void)?) case liveMicrophone(call: AnyObject?, action: (UIView) -> Void) } + + private struct WideGlassLayout { + static let slotWidth: CGFloat = 40.0 + 6.0 + + let mergeLeftSlot: Bool + let integrateRightSlot: Bool + let mergeRightSlot: Bool + let leftExtension: CGFloat + let rightExtension: CGFloat + + static let disabled = WideGlassLayout( + mergeLeftSlot: false, + integrateRightSlot: false, + mergeRightSlot: false, + leftExtension: 0.0, + rightExtension: 0.0 + ) + + var totalWidthExtension: CGFloat { + return self.leftExtension + self.rightExtension + } + } public var customPlaceholder: String? public var customIsDisabled: Bool = false @@ -1216,7 +1238,7 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg return max(33.0, maxHeight - (textFieldInsets.top + textFieldInsets.bottom + self.textInputViewInternalInsets.top + self.textInputViewInternalInsets.bottom)) } - private func calculateTextFieldMetrics(width: CGFloat, sendActionControlsWidth: CGFloat, maxHeight: CGFloat, metrics: LayoutMetrics, bottomInset: CGFloat, interfaceState: ChatPresentationInterfaceState) -> (accessoryButtonsWidth: CGFloat, textFieldHeight: CGFloat, isOverflow: Bool) { + private func calculateTextFieldMetrics(width: CGFloat, sendActionControlsWidth: CGFloat, maxHeight: CGFloat, metrics: LayoutMetrics, bottomInset: CGFloat, interfaceState: ChatPresentationInterfaceState, wideGlassLayout: WideGlassLayout) -> (accessoryButtonsWidth: CGFloat, textFieldHeight: CGFloat, isOverflow: Bool) { let maxHeight = max(maxHeight, 40.0) let textFieldInsets = self.textFieldInsets(metrics: metrics, bottomInset: bottomInset) @@ -1264,10 +1286,7 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg hasSendAsButton = true } - var actualTextInputViewInternalInsets = self.textInputViewInternalInsets - if hasSendAsButton { - actualTextInputViewInternalInsets.left += 31.0 - } + let actualTextInputViewInternalInsets = self.adjustedTextInputViewInternalInsets(hasSendAsButton: hasSendAsButton, wideGlassLayout: wideGlassLayout) var textFieldHeight: CGFloat var isOverflow = false @@ -1312,6 +1331,92 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg let result = textFieldHeight + textFieldInsets.top + textFieldInsets.bottom + self.textInputViewInternalInsets.top + self.textInputViewInternalInsets.bottom return result } + + private func adjustedTextInputViewInternalInsets(hasSendAsButton: Bool, wideGlassLayout: WideGlassLayout) -> UIEdgeInsets { + var actualTextInputViewInternalInsets = self.textInputViewInternalInsets + if hasSendAsButton { + actualTextInputViewInternalInsets.left += 35.0 + } + if wideGlassLayout.leftExtension > 0.0 { + actualTextInputViewInternalInsets.left += 30.0 + } + if wideGlassLayout.rightExtension > 0.0 { + actualTextInputViewInternalInsets.right += 32.0 + } + return actualTextInputViewInternalInsets + } + + private func calculateWideGlassLayout(interfaceState: ChatPresentationInterfaceState, displayMediaButton: Bool, hasMediaRecording: Bool, inputHasText: Bool, hasForward: Bool, hasMediaDraft: Bool, hasSlowmodeButton: Bool, isEditingMedia: Bool) -> WideGlassLayout { + guard SGSimpleSettings.shared.wideGlass else { + return .disabled + } + + let mergeLeftSlot: Bool + if !displayMediaButton || hasMediaRecording { + mergeLeftSlot = false + } else if let customLeftAction = self.customLeftAction { + switch customLeftAction { + case .empty, .toggleExpanded(false, _, _): + mergeLeftSlot = false + default: + mergeLeftSlot = true + } + } else { + mergeLeftSlot = true + } + + var mediaInputIsActive = false + if case .media = interfaceState.inputMode { + mediaInputIsActive = true + } + + var keepSendButtonEnabled = self.keepSendButtonEnabled + if case let .customChatContents(customChatContents) = interfaceState.subject { + switch customChatContents.kind { + case .businessLinkSetup: + keepSendButtonEnabled = true + default: + break + } + } + if hasMediaDraft || hasForward { + keepSendButtonEnabled = true + } + + var hideMicButton = SGSimpleSettings.shared.hideRecordingButton + if mediaInputIsActive { + hideMicButton = true + } + if case let .customChatContents(customChatContents) = interfaceState.subject { + switch customChatContents.kind { + case .businessLinkSetup: + hideMicButton = true + default: + break + } + } + + let sendButtonConsumesRightSlot = inputHasText || hasMediaDraft || hasForward || isEditingMedia || (keepSendButtonEnabled && !mediaInputIsActive && !hasSlowmodeButton) + let hasStandardRightSlot = self.customRightAction == nil && self.customSecondaryRightAction == nil && !hasSlowmodeButton && !self.extendedSearchLayout + let integrateRightSlot = hasStandardRightSlot && !hasMediaRecording && (!SGSimpleSettings.shared.hideRecordingButton || mediaInputIsActive || sendButtonConsumesRightSlot) + let rightExtension: CGFloat + if integrateRightSlot { + rightExtension = WideGlassLayout.slotWidth + } else { + rightExtension = 0.0 + } + + let showExpandMediaInput = integrateRightSlot && mediaInputIsActive + let showMicButton = integrateRightSlot && !mediaInputIsActive && !hideMicButton && !sendButtonConsumesRightSlot + + return WideGlassLayout( + mergeLeftSlot: mergeLeftSlot, + integrateRightSlot: integrateRightSlot, + mergeRightSlot: showMicButton || showExpandMediaInput, + leftExtension: mergeLeftSlot ? WideGlassLayout.slotWidth : 0.0, + rightExtension: rightExtension + ) + } override public func minimalHeight(interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics) -> CGFloat { let textFieldMinHeight = calclulateTextFieldMinHeight(interfaceState, metrics: metrics) @@ -2272,7 +2377,6 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg let originalLeftInset = leftInset // - let textInputBackgroundWidthOffset: CGFloat = 0.0 var attachmentButtonX: CGFloat = hideOffset.x + leftInset + leftMenuInset + 8.0 var leftButtonsWidth: CGFloat = 40.0 + 6.0 @@ -2320,6 +2424,18 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg attachmentButtonX = -8.0 - leftButtonsWidth } + let wideGlassLayout = self.calculateWideGlassLayout( + interfaceState: interfaceState, + displayMediaButton: displayMediaButton, + hasMediaRecording: mediaRecordingState != nil, + inputHasText: inputHasText, + hasForward: hasForward, + hasMediaDraft: hasMediaDraft, + hasSlowmodeButton: hasSlowmodeButton, + isEditingMedia: isEditingMedia + ) + self.currentWideGlassLayout = wideGlassLayout + self.mediaActionButtons.micButton.updateMode(mode: interfaceState.interfaceState.mediaRecordingMode, animated: transition.isAnimated) self.updateActionButtons(hasText: inputHasText, transition: transition) @@ -2338,9 +2454,8 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg } } } - - sendActionButtonsSize = self.sendActionButtons.updateLayout(size: CGSize(width: 40.0, height: minimalHeight), isMediaInputExpanded: isMediaInputExpanded, showTitle: showTitle, currentMessageEffectId: presentationInterfaceState.interfaceState.sendMessageEffect, transition: transition, interfaceState: presentationInterfaceState) - mediaActionButtonsSize = self.mediaActionButtons.updateLayout(size: CGSize(width: 40.0, height: minimalHeight), isMediaInputExpanded: isMediaInputExpanded, showTitle: false, currentMessageEffectId: presentationInterfaceState.interfaceState.sendMessageEffect, transition: transition, interfaceState: presentationInterfaceState) + sendActionButtonsSize = self.sendActionButtons.updateLayout(size: CGSize(width: 40.0, height: minimalHeight), isMediaInputExpanded: isMediaInputExpanded, showTitle: showTitle, currentMessageEffectId: presentationInterfaceState.interfaceState.sendMessageEffect, transition: transition, interfaceState: presentationInterfaceState, mergeBackgroundIntoInputField: wideGlassLayout.integrateRightSlot) + mediaActionButtonsSize = self.mediaActionButtons.updateLayout(size: CGSize(width: 40.0, height: minimalHeight), isMediaInputExpanded: isMediaInputExpanded, showTitle: false, currentMessageEffectId: presentationInterfaceState.interfaceState.sendMessageEffect, transition: transition, interfaceState: presentationInterfaceState, mergeBackgroundIntoInputField: wideGlassLayout.integrateRightSlot) } var starReactionButtonSize: CGSize? @@ -2413,7 +2528,7 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg } let baseWidth = width - leftInset - leftMenuInset - rightInset - rightSlowModeInset - let (accessoryButtonsWidth, textFieldHeight, isTextFieldOverflow) = self.calculateTextFieldMetrics(width: baseWidth, sendActionControlsWidth: sendActionButtonsSize.width, maxHeight: maxHeight, metrics: metrics, bottomInset: bottomInset, interfaceState: interfaceState) + let (accessoryButtonsWidth, textFieldHeight, isTextFieldOverflow) = self.calculateTextFieldMetrics(width: baseWidth + wideGlassLayout.totalWidthExtension, sendActionControlsWidth: sendActionButtonsSize.width, maxHeight: maxHeight, metrics: metrics, bottomInset: bottomInset, interfaceState: interfaceState, wideGlassLayout: wideGlassLayout) var panelHeight = self.panelHeight(textFieldHeight: textFieldHeight, metrics: metrics, bottomInset: bottomInset) if displayBotStartButton { panelHeight += 27.0 @@ -2481,6 +2596,18 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg break } } + if wideGlassLayout.integrateRightSlot { + textFieldInsets.right = max(textFieldInsets.right, 54.0) + } + + let resolvedWideGlassLayout = WideGlassLayout( + mergeLeftSlot: wideGlassLayout.mergeLeftSlot, + integrateRightSlot: wideGlassLayout.integrateRightSlot, + mergeRightSlot: wideGlassLayout.mergeRightSlot, + leftExtension: wideGlassLayout.leftExtension, + rightExtension: wideGlassLayout.rightExtension + ) + self.currentWideGlassLayout = resolvedWideGlassLayout var audioRecordingItemsAlpha: CGFloat = 1.0 if interfaceState.interfaceState.mediaDraftState != nil { @@ -2848,7 +2975,7 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg } } - let textInputWidth = baseWidth - textFieldInsets.left - textFieldInsets.right + let textInputWidth = baseWidth - textFieldInsets.left - textFieldInsets.right + resolvedWideGlassLayout.totalWidthExtension let textInputHeight = panelHeight - textFieldInsets.top - textFieldInsets.bottom if let accessoryPanel { @@ -2947,7 +3074,7 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg contentHeight += textFieldInsets.bottom let previousTextInputContainerBackgroundFrame = self.textInputContainerBackgroundView.frame - let textInputContainerBackgroundFrame = CGRect(x: hideOffset.x + leftInset + textFieldInsets.left, y: hideOffset.y + textFieldInsets.top, width: textInputWidth, height: contentHeight) + let textInputContainerBackgroundFrame = CGRect(x: hideOffset.x + leftInset + textFieldInsets.left - resolvedWideGlassLayout.leftExtension, y: hideOffset.y + textFieldInsets.top, width: textInputWidth, height: contentHeight) let textInputFrame = textInputContainerBackgroundFrame transition.updateFrame(view: self.accessoryPanelContainer, frame: CGRect(origin: CGPoint(), size: textInputContainerBackgroundFrame.size)) @@ -2980,10 +3107,7 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg hasSendAsButton = true } - var actualTextInputViewInternalInsets = self.textInputViewInternalInsets - if hasSendAsButton { - actualTextInputViewInternalInsets.left += 31.0 - } + let actualTextInputViewInternalInsets = self.adjustedTextInputViewInternalInsets(hasSendAsButton: hasSendAsButton, wideGlassLayout: resolvedWideGlassLayout) let textFieldFrame = CGRect(origin: CGPoint(x: actualTextInputViewInternalInsets.left, y: actualTextInputViewInternalInsets.top + textFieldTopContentOffset), size: CGSize(width: textInputFrame.size.width - (actualTextInputViewInternalInsets.left + actualTextInputViewInternalInsets.right), height: textInputHeight - actualTextInputViewInternalInsets.top - actualTextInputViewInternalInsets.bottom)) let textInputNodeClippingContainerFrame = CGRect(origin: CGPoint(x: textFieldFrame.minX - actualTextInputViewInternalInsets.left, y: textFieldFrame.minY - actualTextInputViewInternalInsets.top), size: CGSize(width: textFieldFrame.width + actualTextInputViewInternalInsets.left + actualTextInputViewInternalInsets.right, height: textFieldFrame.height + actualTextInputViewInternalInsets.top + actualTextInputViewInternalInsets.bottom)) @@ -3011,7 +3135,7 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg let placeholderLayout = TextNode.asyncLayout(self.contextPlaceholderNode) let contextPlaceholder = NSMutableAttributedString(attributedString: contextPlaceholder) contextPlaceholder.addAttribute(.foregroundColor, value: placeholderColor.withAlphaComponent(1.0), range: NSRange(location: 0, length: contextPlaceholder.length)) - let (placeholderSize, placeholderApply) = placeholderLayout(TextNodeLayoutArguments(attributedString: contextPlaceholder, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: width - leftInset - rightInset - textFieldInsets.left - textFieldInsets.right - actualTextInputViewInternalInsets.left - actualTextInputViewInternalInsets.right - accessoryButtonsWidth, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets())) + let (placeholderSize, placeholderApply) = placeholderLayout(TextNodeLayoutArguments(attributedString: contextPlaceholder, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: textInputWidth - actualTextInputViewInternalInsets.left - actualTextInputViewInternalInsets.right - accessoryButtonsWidth, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets())) let tintContextPlaceholder = NSMutableAttributedString(attributedString: contextPlaceholder) tintContextPlaceholder.addAttribute(.foregroundColor, value: UIColor.black, range: NSRange(location: 0, length: tintContextPlaceholder.length)) let contextPlaceholderNode = placeholderApply() @@ -3055,7 +3179,7 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg self.slowmodePlaceholderNode = slowmodePlaceholderNode self.textInputContainerBackgroundView.contentView.insertSubview(slowmodePlaceholderNode.view, aboveSubview: self.textPlaceholderNode.view) } - let placeholderFrame = CGRect(origin: CGPoint(x: actualTextInputViewInternalInsets.left, y: textFieldInsets.top + actualTextInputViewInternalInsets.top + textInputViewRealInsets.top + UIScreenPixel + textFieldTopContentOffset), size: CGSize(width: width - leftInset - rightInset - textFieldInsets.left - textFieldInsets.right - actualTextInputViewInternalInsets.left - actualTextInputViewInternalInsets.right - accessoryButtonsWidth, height: 30.0)) + let placeholderFrame = CGRect(origin: CGPoint(x: actualTextInputViewInternalInsets.left, y: textFieldInsets.top + actualTextInputViewInternalInsets.top + textInputViewRealInsets.top + UIScreenPixel + textFieldTopContentOffset), size: CGSize(width: textInputWidth - actualTextInputViewInternalInsets.left - actualTextInputViewInternalInsets.right - accessoryButtonsWidth, height: 30.0)) slowmodePlaceholderNode.updateState(slowmodeState) if slowmodePlaceholderNode.bounds.isEmpty { slowmodePlaceholderNode.frame = placeholderFrame @@ -3077,10 +3201,13 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg self.slowmodePlaceholderNode?.isHidden = true } + let actionButtonContentSpacing = max(0.0, actualTextInputViewInternalInsets.right - 40.0) var nextButtonTopRight = CGPoint(x: textInputContainerBackgroundFrame.width - accessoryButtonInset, y: textInputContainerBackgroundFrame.height - minimalInputHeight) if self.extendedSearchLayout { nextButtonTopRight.x -= 46.0 } else if hasSlowmodeButton { + } else if resolvedWideGlassLayout.integrateRightSlot { + nextButtonTopRight.x = textInputContainerBackgroundFrame.width - 40.0 - actionButtonContentSpacing } else if inputHasText || hasMediaDraft || hasForward || isEditingMedia { nextButtonTopRight.x -= sendActionButtonsSize.width } @@ -3110,8 +3237,6 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg } } - self.currentTextInputBackgroundWidthOffset = textInputBackgroundWidthOffset - let textPlaceholderSize: CGSize let textPlaceholderMaxWidth: CGFloat = max(1.0, nextButtonTopRight.x - 12.0) @@ -3182,7 +3307,7 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg transition.updateFrame(node: self.textPlaceholderNode, frame: textPlaceholderFrame) - let sendAsButtonFrame = CGRect(origin: CGPoint(x: 3.0, y: textInputContainerBackgroundFrame.height - 3.0 - 34.0), size: CGSize(width: 34.0, height: 34.0)) + let sendAsButtonFrame = CGRect(origin: CGPoint(x: max(3.0, actualTextInputViewInternalInsets.left - 40.0), y: textInputContainerBackgroundFrame.height - 3.0 - 34.0), size: CGSize(width: 34.0, height: 34.0)) let sendAsAvatarButtonAlpha: CGFloat = audioRecordingItemsAlpha * (displaySendAsAvatarButton ? 1.0 : 0.0) transition.updatePosition(node: self.sendAsAvatarButtonNode, position: sendAsButtonFrame.center) transition.updateBounds(node: self.sendAsAvatarButtonNode, bounds: CGRect(origin: CGPoint(), size: sendAsButtonFrame.size)) @@ -3231,10 +3356,27 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg } var mediaActionButtonsFrame = CGRect(origin: CGPoint(x: textInputContainerBackgroundFrame.maxX + 6.0, y: textInputContainerBackgroundFrame.maxY - mediaActionButtonsSize.height), size: mediaActionButtonsSize) + if resolvedWideGlassLayout.integrateRightSlot { + mediaActionButtonsFrame.origin.x = textInputContainerBackgroundFrame.maxX - mediaActionButtonsSize.width + } if inputHasText || self.extendedSearchLayout || hasMediaDraft || interfaceState.interfaceState.forwardMessageIds != nil || hasSlowmodeButton || isEditingMedia { - mediaActionButtonsFrame.origin.x = width + 8.0 + if !resolvedWideGlassLayout.integrateRightSlot { + mediaActionButtonsFrame.origin.x = width + 8.0 + } + } + let mediaActionButtonsDisplayFrame: CGRect + if resolvedWideGlassLayout.integrateRightSlot { + mediaActionButtonsDisplayFrame = mediaActionButtonsFrame.offsetBy(dx: -textInputContainerBackgroundFrame.minX, dy: -textInputContainerBackgroundFrame.minY) + } else { + mediaActionButtonsDisplayFrame = mediaActionButtonsFrame + } + let mediaActionButtonsParentView = resolvedWideGlassLayout.integrateRightSlot ? self.textInputContainerBackgroundView.contentView : self.glassBackgroundContainer.contentView + if self.mediaActionButtons.view.superview !== mediaActionButtonsParentView { + self.mediaActionButtons.view.layer.removeAllAnimations() + self.mediaActionButtons.view.frame = mediaActionButtonsDisplayFrame + mediaActionButtonsParentView.addSubview(self.mediaActionButtons.view) } - transition.updateFrame(node: self.mediaActionButtons, frame: mediaActionButtonsFrame) + transition.updateFrame(node: self.mediaActionButtons, frame: mediaActionButtonsDisplayFrame) if let (rect, containerSize) = self.absoluteRect { self.mediaActionButtons.updateAbsoluteRect(CGRect(x: rect.origin.x + mediaActionButtonsFrame.origin.x, y: rect.origin.y + mediaActionButtonsFrame.origin.y, width: mediaActionButtonsFrame.width, height: mediaActionButtonsFrame.height), within: containerSize, transition: transition) } @@ -3286,10 +3428,26 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg sendActionButtonsFrame.origin.x += (sendActionButtonsSize.width - 3.0 * 2.0) * 0.5 - 3.0 } + let sendActionButtonsDisplayFrame: CGRect + if resolvedWideGlassLayout.integrateRightSlot { + sendActionButtonsDisplayFrame = sendActionButtonsFrame.offsetBy(dx: -textInputContainerBackgroundFrame.minX, dy: -textInputContainerBackgroundFrame.minY) + } else { + sendActionButtonsDisplayFrame = sendActionButtonsFrame + } + let sendActionButtonsParentView = resolvedWideGlassLayout.integrateRightSlot ? self.textInputContainerBackgroundView.contentView : self.glassBackgroundContainer.contentView + if self.sendActionButtons.view.superview !== sendActionButtonsParentView { + self.sendActionButtons.view.layer.removeAllAnimations() + self.sendActionButtons.view.frame = sendActionButtonsDisplayFrame + sendActionButtonsParentView.addSubview(self.sendActionButtons.view) + } + if resolvedWideGlassLayout.integrateRightSlot { + sendActionButtonsParentView.bringSubviewToFront(self.sendActionButtons.view) + } + transition.updateTransformScale(node: self.sendActionButtons, scale: CGPoint(x: sendActionsScale, y: sendActionsScale)) - transition.updatePosition(node: self.sendActionButtons, position: sendActionButtonsFrame.center) + transition.updatePosition(node: self.sendActionButtons, position: sendActionButtonsDisplayFrame.center) - transition.updateBounds(node: self.sendActionButtons, bounds: CGRect(origin: CGPoint(), size: sendActionButtonsFrame.size)) + transition.updateBounds(node: self.sendActionButtons, bounds: CGRect(origin: CGPoint(), size: sendActionButtonsDisplayFrame.size)) if let (rect, containerSize) = self.absoluteRect { self.sendActionButtons.updateAbsoluteRect(CGRect(x: rect.origin.x + sendActionButtonsFrame.origin.x, y: rect.origin.y + sendActionButtonsFrame.origin.y, width: sendActionButtonsFrame.width, height: sendActionButtonsFrame.height), within: containerSize, transition: transition) } @@ -3300,6 +3458,7 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg if let _ = interfaceState.inputTextPanelState.mediaRecordingState { let text: String = interfaceState.strings.VoiceOver_MessageContextSend let mediaRecordingAccessibilityArea: AccessibilityAreaNode + let mediaRecordingAccessibilityParentView = self.mediaActionButtons.view.superview ?? self.glassBackgroundContainer.contentView var added = false if let current = self.mediaRecordingAccessibilityArea { mediaRecordingAccessibilityArea = current @@ -3315,11 +3474,20 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg } return true } - self.glassBackgroundContainer.contentView.insertSubview(mediaRecordingAccessibilityArea.view, aboveSubview: self.mediaActionButtons.view) + } + if mediaRecordingAccessibilityArea.view.superview !== mediaRecordingAccessibilityParentView { + if mediaRecordingAccessibilityArea.view.superview != nil { + mediaRecordingAccessibilityArea.view.removeFromSuperview() + } + if self.mediaActionButtons.view.superview === mediaRecordingAccessibilityParentView { + mediaRecordingAccessibilityParentView.insertSubview(mediaRecordingAccessibilityArea.view, aboveSubview: self.mediaActionButtons.view) + } else { + mediaRecordingAccessibilityParentView.addSubview(mediaRecordingAccessibilityArea.view) + } } self.mediaActionButtons.isAccessibilityElement = false let size: CGFloat = 120.0 - mediaRecordingAccessibilityArea.frame = CGRect(origin: CGPoint(x: mediaActionButtonsFrame.midX - size / 2.0, y: mediaActionButtonsFrame.midY - size / 2.0), size: CGSize(width: size, height: size)) + mediaRecordingAccessibilityArea.frame = CGRect(origin: CGPoint(x: mediaActionButtonsDisplayFrame.midX - size / 2.0, y: mediaActionButtonsDisplayFrame.midY - size / 2.0), size: CGSize(width: size, height: size)) if added { DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.4, execute: { [weak mediaRecordingAccessibilityArea] in @@ -3348,11 +3516,24 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg let attachmentButtonFrame = CGRect(origin: CGPoint(x: attachmentButtonX, y: textInputFrame.maxY - 40.0), size: CGSize(width: 40.0, height: 40.0)) attachmentButtonX += 40.0 + 6.0 - self.attachmentButtonBackground.update(size: attachmentButtonFrame.size, cornerRadius: attachmentButtonFrame.height * 0.5, isDark: interfaceState.theme.overallDarkAppearance, tintColor: defaultGlassTintColor, isInteractive: true, transition: ComponentTransition(transition)) + let attachmentButtonParentView = resolvedWideGlassLayout.mergeLeftSlot ? self.textInputContainerBackgroundView.contentView : self.glassBackgroundContainer.contentView + if self.attachmentButtonBackground.superview !== attachmentButtonParentView { + attachmentButtonParentView.addSubview(self.attachmentButtonBackground) + } + if self.attachmentButtonDisabledNode.view.superview !== attachmentButtonParentView { + attachmentButtonParentView.addSubview(self.attachmentButtonDisabledNode.view) + } + let attachmentButtonDisplayFrame: CGRect + if resolvedWideGlassLayout.mergeLeftSlot { + attachmentButtonDisplayFrame = attachmentButtonFrame.offsetBy(dx: -textInputContainerBackgroundFrame.minX, dy: -textInputContainerBackgroundFrame.minY) + } else { + attachmentButtonDisplayFrame = attachmentButtonFrame + } + self.attachmentButtonBackground.update(size: attachmentButtonFrame.size, cornerRadius: attachmentButtonFrame.height * 0.5, isDark: interfaceState.theme.overallDarkAppearance, tintColor: defaultGlassTintColor, isInteractive: true, isVisible: !resolvedWideGlassLayout.mergeLeftSlot, transition: ComponentTransition(transition)) - transition.updateFrame(layer: self.attachmentButtonBackground.layer, frame: attachmentButtonFrame) + transition.updateFrame(layer: self.attachmentButtonBackground.layer, frame: attachmentButtonDisplayFrame) transition.updateFrame(layer: self.attachmentButton.layer, frame: CGRect(origin: CGPoint(), size: attachmentButtonFrame.size)) - transition.updateFrame(node: self.attachmentButtonDisabledNode, frame: self.attachmentButtonBackground.frame) + transition.updateFrame(node: self.attachmentButtonDisabledNode, frame: attachmentButtonDisplayFrame) if let image = self.attachmentButtonIcon.image { let attachmentButtonIconFrame = CGRect(origin: CGPoint(x: floor((attachmentButtonFrame.width - image.size.width) * 0.5), y: floor((attachmentButtonFrame.height - image.size.height) * 0.5)), size: image.size) @@ -4727,8 +4908,8 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg leftInset += compactBottomSideInset rightInset += compactBottomSideInset - let baseWidth = width - leftInset - self.leftMenuInset - rightInset - self.rightSlowModeInset + self.currentTextInputBackgroundWidthOffset - additionalSideInsets.right - let (_, textFieldHeight, _) = self.calculateTextFieldMetrics(width: baseWidth, sendActionControlsWidth: self.sendActionButtons.bounds.width, maxHeight: maxHeight, metrics: metrics, bottomInset: bottomInset, interfaceState: interfaceState) + let baseWidth = width - leftInset - self.leftMenuInset - rightInset - self.rightSlowModeInset - additionalSideInsets.right + let (_, textFieldHeight, _) = self.calculateTextFieldMetrics(width: baseWidth + self.currentWideGlassLayout.totalWidthExtension, sendActionControlsWidth: self.sendActionButtons.bounds.width, maxHeight: maxHeight, metrics: metrics, bottomInset: bottomInset, interfaceState: interfaceState, wideGlassLayout: self.currentWideGlassLayout) let panelHeight = self.panelHeight(textFieldHeight: textFieldHeight, metrics: metrics, bottomInset: bottomInset) if !self.bounds.size.height.isEqual(to: panelHeight) { self.updateHeight(animated) @@ -5675,10 +5856,17 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg public func getAttachmentButton() -> UIView { return self.attachmentButton } + + private func frameInPanelCoordinates(for view: UIView) -> CGRect? { + guard let superview = view.superview else { + return nil + } + return self.view.convert(view.frame, from: superview) + } public func frameForAttachmentButton() -> CGRect? { - if !self.attachmentButtonBackground.alpha.isZero { - return self.attachmentButtonBackground.frame.insetBy(dx: 0.0, dy: -4.0).offsetBy(dx: 0.0, dy: 0.0) + if !self.attachmentButtonBackground.alpha.isZero, let frame = self.frameInPanelCoordinates(for: self.attachmentButtonBackground) { + return frame.insetBy(dx: 0.0, dy: -4.0).offsetBy(dx: 0.0, dy: 0.0) } return nil } @@ -5691,8 +5879,8 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg } public func frameForInputActionButton() -> CGRect? { - if !self.mediaActionButtons.alpha.isZero && self.mediaActionButtons.frame.minX < self.bounds.width { - return self.mediaActionButtons.frame.insetBy(dx: 0.0, dy: -4.0).offsetBy(dx: -3.0, dy: 0.0) + if !self.mediaActionButtons.alpha.isZero, let frame = self.frameInPanelCoordinates(for: self.mediaActionButtons.view), frame.minX < self.bounds.width { + return frame.insetBy(dx: 0.0, dy: -4.0).offsetBy(dx: -3.0, dy: 0.0) } return nil } From ea972dd79e4cc57474330de4ec5cb234871364aa Mon Sep 17 00:00:00 2001 From: Lev Poznyakov Date: Sun, 12 Apr 2026 17:53:57 +0400 Subject: [PATCH 3/9] simplify --- .../Sources/ChatTextInputPanelNode.swift | 92 ++++++------------- 1 file changed, 30 insertions(+), 62 deletions(-) diff --git a/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/ChatTextInputPanelNode.swift b/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/ChatTextInputPanelNode.swift index 03d258eb44..317e91802e 100644 --- a/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/ChatTextInputPanelNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/ChatTextInputPanelNode.swift @@ -420,18 +420,20 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg static let slotWidth: CGFloat = 40.0 + 6.0 let mergeLeftSlot: Bool - let integrateRightSlot: Bool let mergeRightSlot: Bool - let leftExtension: CGFloat - let rightExtension: CGFloat static let disabled = WideGlassLayout( mergeLeftSlot: false, - integrateRightSlot: false, - mergeRightSlot: false, - leftExtension: 0.0, - rightExtension: 0.0 + mergeRightSlot: false ) + + var leftExtension: CGFloat { + return self.mergeLeftSlot ? Self.slotWidth : 0.0 + } + + var rightExtension: CGFloat { + return self.mergeRightSlot ? Self.slotWidth : 0.0 + } var totalWidthExtension: CGFloat { return self.leftExtension + self.rightExtension @@ -1337,10 +1339,10 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg if hasSendAsButton { actualTextInputViewInternalInsets.left += 35.0 } - if wideGlassLayout.leftExtension > 0.0 { + if wideGlassLayout.mergeLeftSlot { actualTextInputViewInternalInsets.left += 30.0 } - if wideGlassLayout.rightExtension > 0.0 { + if wideGlassLayout.mergeRightSlot { actualTextInputViewInternalInsets.right += 32.0 } return actualTextInputViewInternalInsets @@ -1383,38 +1385,13 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg keepSendButtonEnabled = true } - var hideMicButton = SGSimpleSettings.shared.hideRecordingButton - if mediaInputIsActive { - hideMicButton = true - } - if case let .customChatContents(customChatContents) = interfaceState.subject { - switch customChatContents.kind { - case .businessLinkSetup: - hideMicButton = true - default: - break - } - } - let sendButtonConsumesRightSlot = inputHasText || hasMediaDraft || hasForward || isEditingMedia || (keepSendButtonEnabled && !mediaInputIsActive && !hasSlowmodeButton) let hasStandardRightSlot = self.customRightAction == nil && self.customSecondaryRightAction == nil && !hasSlowmodeButton && !self.extendedSearchLayout - let integrateRightSlot = hasStandardRightSlot && !hasMediaRecording && (!SGSimpleSettings.shared.hideRecordingButton || mediaInputIsActive || sendButtonConsumesRightSlot) - let rightExtension: CGFloat - if integrateRightSlot { - rightExtension = WideGlassLayout.slotWidth - } else { - rightExtension = 0.0 - } - - let showExpandMediaInput = integrateRightSlot && mediaInputIsActive - let showMicButton = integrateRightSlot && !mediaInputIsActive && !hideMicButton && !sendButtonConsumesRightSlot + let mergeRightSlot = hasStandardRightSlot && !hasMediaRecording && (!SGSimpleSettings.shared.hideRecordingButton || mediaInputIsActive || sendButtonConsumesRightSlot) return WideGlassLayout( mergeLeftSlot: mergeLeftSlot, - integrateRightSlot: integrateRightSlot, - mergeRightSlot: showMicButton || showExpandMediaInput, - leftExtension: mergeLeftSlot ? WideGlassLayout.slotWidth : 0.0, - rightExtension: rightExtension + mergeRightSlot: mergeRightSlot ) } @@ -2454,8 +2431,8 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg } } } - sendActionButtonsSize = self.sendActionButtons.updateLayout(size: CGSize(width: 40.0, height: minimalHeight), isMediaInputExpanded: isMediaInputExpanded, showTitle: showTitle, currentMessageEffectId: presentationInterfaceState.interfaceState.sendMessageEffect, transition: transition, interfaceState: presentationInterfaceState, mergeBackgroundIntoInputField: wideGlassLayout.integrateRightSlot) - mediaActionButtonsSize = self.mediaActionButtons.updateLayout(size: CGSize(width: 40.0, height: minimalHeight), isMediaInputExpanded: isMediaInputExpanded, showTitle: false, currentMessageEffectId: presentationInterfaceState.interfaceState.sendMessageEffect, transition: transition, interfaceState: presentationInterfaceState, mergeBackgroundIntoInputField: wideGlassLayout.integrateRightSlot) + sendActionButtonsSize = self.sendActionButtons.updateLayout(size: CGSize(width: 40.0, height: minimalHeight), isMediaInputExpanded: isMediaInputExpanded, showTitle: showTitle, currentMessageEffectId: presentationInterfaceState.interfaceState.sendMessageEffect, transition: transition, interfaceState: presentationInterfaceState, mergeBackgroundIntoInputField: wideGlassLayout.mergeRightSlot) + mediaActionButtonsSize = self.mediaActionButtons.updateLayout(size: CGSize(width: 40.0, height: minimalHeight), isMediaInputExpanded: isMediaInputExpanded, showTitle: false, currentMessageEffectId: presentationInterfaceState.interfaceState.sendMessageEffect, transition: transition, interfaceState: presentationInterfaceState, mergeBackgroundIntoInputField: wideGlassLayout.mergeRightSlot) } var starReactionButtonSize: CGSize? @@ -2596,19 +2573,10 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg break } } - if wideGlassLayout.integrateRightSlot { + if wideGlassLayout.mergeRightSlot { textFieldInsets.right = max(textFieldInsets.right, 54.0) } - let resolvedWideGlassLayout = WideGlassLayout( - mergeLeftSlot: wideGlassLayout.mergeLeftSlot, - integrateRightSlot: wideGlassLayout.integrateRightSlot, - mergeRightSlot: wideGlassLayout.mergeRightSlot, - leftExtension: wideGlassLayout.leftExtension, - rightExtension: wideGlassLayout.rightExtension - ) - self.currentWideGlassLayout = resolvedWideGlassLayout - var audioRecordingItemsAlpha: CGFloat = 1.0 if interfaceState.interfaceState.mediaDraftState != nil { audioRecordingItemsAlpha = 0.0 @@ -2975,7 +2943,7 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg } } - let textInputWidth = baseWidth - textFieldInsets.left - textFieldInsets.right + resolvedWideGlassLayout.totalWidthExtension + let textInputWidth = baseWidth - textFieldInsets.left - textFieldInsets.right + wideGlassLayout.totalWidthExtension let textInputHeight = panelHeight - textFieldInsets.top - textFieldInsets.bottom if let accessoryPanel { @@ -3074,7 +3042,7 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg contentHeight += textFieldInsets.bottom let previousTextInputContainerBackgroundFrame = self.textInputContainerBackgroundView.frame - let textInputContainerBackgroundFrame = CGRect(x: hideOffset.x + leftInset + textFieldInsets.left - resolvedWideGlassLayout.leftExtension, y: hideOffset.y + textFieldInsets.top, width: textInputWidth, height: contentHeight) + let textInputContainerBackgroundFrame = CGRect(x: hideOffset.x + leftInset + textFieldInsets.left - wideGlassLayout.leftExtension, y: hideOffset.y + textFieldInsets.top, width: textInputWidth, height: contentHeight) let textInputFrame = textInputContainerBackgroundFrame transition.updateFrame(view: self.accessoryPanelContainer, frame: CGRect(origin: CGPoint(), size: textInputContainerBackgroundFrame.size)) @@ -3107,7 +3075,7 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg hasSendAsButton = true } - let actualTextInputViewInternalInsets = self.adjustedTextInputViewInternalInsets(hasSendAsButton: hasSendAsButton, wideGlassLayout: resolvedWideGlassLayout) + let actualTextInputViewInternalInsets = self.adjustedTextInputViewInternalInsets(hasSendAsButton: hasSendAsButton, wideGlassLayout: wideGlassLayout) let textFieldFrame = CGRect(origin: CGPoint(x: actualTextInputViewInternalInsets.left, y: actualTextInputViewInternalInsets.top + textFieldTopContentOffset), size: CGSize(width: textInputFrame.size.width - (actualTextInputViewInternalInsets.left + actualTextInputViewInternalInsets.right), height: textInputHeight - actualTextInputViewInternalInsets.top - actualTextInputViewInternalInsets.bottom)) let textInputNodeClippingContainerFrame = CGRect(origin: CGPoint(x: textFieldFrame.minX - actualTextInputViewInternalInsets.left, y: textFieldFrame.minY - actualTextInputViewInternalInsets.top), size: CGSize(width: textFieldFrame.width + actualTextInputViewInternalInsets.left + actualTextInputViewInternalInsets.right, height: textFieldFrame.height + actualTextInputViewInternalInsets.top + actualTextInputViewInternalInsets.bottom)) @@ -3206,7 +3174,7 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg if self.extendedSearchLayout { nextButtonTopRight.x -= 46.0 } else if hasSlowmodeButton { - } else if resolvedWideGlassLayout.integrateRightSlot { + } else if wideGlassLayout.mergeRightSlot { nextButtonTopRight.x = textInputContainerBackgroundFrame.width - 40.0 - actionButtonContentSpacing } else if inputHasText || hasMediaDraft || hasForward || isEditingMedia { nextButtonTopRight.x -= sendActionButtonsSize.width @@ -3356,21 +3324,21 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg } var mediaActionButtonsFrame = CGRect(origin: CGPoint(x: textInputContainerBackgroundFrame.maxX + 6.0, y: textInputContainerBackgroundFrame.maxY - mediaActionButtonsSize.height), size: mediaActionButtonsSize) - if resolvedWideGlassLayout.integrateRightSlot { + if wideGlassLayout.mergeRightSlot { mediaActionButtonsFrame.origin.x = textInputContainerBackgroundFrame.maxX - mediaActionButtonsSize.width } if inputHasText || self.extendedSearchLayout || hasMediaDraft || interfaceState.interfaceState.forwardMessageIds != nil || hasSlowmodeButton || isEditingMedia { - if !resolvedWideGlassLayout.integrateRightSlot { + if !wideGlassLayout.mergeRightSlot { mediaActionButtonsFrame.origin.x = width + 8.0 } } let mediaActionButtonsDisplayFrame: CGRect - if resolvedWideGlassLayout.integrateRightSlot { + if wideGlassLayout.mergeRightSlot { mediaActionButtonsDisplayFrame = mediaActionButtonsFrame.offsetBy(dx: -textInputContainerBackgroundFrame.minX, dy: -textInputContainerBackgroundFrame.minY) } else { mediaActionButtonsDisplayFrame = mediaActionButtonsFrame } - let mediaActionButtonsParentView = resolvedWideGlassLayout.integrateRightSlot ? self.textInputContainerBackgroundView.contentView : self.glassBackgroundContainer.contentView + let mediaActionButtonsParentView = wideGlassLayout.mergeRightSlot ? self.textInputContainerBackgroundView.contentView : self.glassBackgroundContainer.contentView if self.mediaActionButtons.view.superview !== mediaActionButtonsParentView { self.mediaActionButtons.view.layer.removeAllAnimations() self.mediaActionButtons.view.frame = mediaActionButtonsDisplayFrame @@ -3429,18 +3397,18 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg } let sendActionButtonsDisplayFrame: CGRect - if resolvedWideGlassLayout.integrateRightSlot { + if wideGlassLayout.mergeRightSlot { sendActionButtonsDisplayFrame = sendActionButtonsFrame.offsetBy(dx: -textInputContainerBackgroundFrame.minX, dy: -textInputContainerBackgroundFrame.minY) } else { sendActionButtonsDisplayFrame = sendActionButtonsFrame } - let sendActionButtonsParentView = resolvedWideGlassLayout.integrateRightSlot ? self.textInputContainerBackgroundView.contentView : self.glassBackgroundContainer.contentView + let sendActionButtonsParentView = wideGlassLayout.mergeRightSlot ? self.textInputContainerBackgroundView.contentView : self.glassBackgroundContainer.contentView if self.sendActionButtons.view.superview !== sendActionButtonsParentView { self.sendActionButtons.view.layer.removeAllAnimations() self.sendActionButtons.view.frame = sendActionButtonsDisplayFrame sendActionButtonsParentView.addSubview(self.sendActionButtons.view) } - if resolvedWideGlassLayout.integrateRightSlot { + if wideGlassLayout.mergeRightSlot { sendActionButtonsParentView.bringSubviewToFront(self.sendActionButtons.view) } @@ -3516,7 +3484,7 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg let attachmentButtonFrame = CGRect(origin: CGPoint(x: attachmentButtonX, y: textInputFrame.maxY - 40.0), size: CGSize(width: 40.0, height: 40.0)) attachmentButtonX += 40.0 + 6.0 - let attachmentButtonParentView = resolvedWideGlassLayout.mergeLeftSlot ? self.textInputContainerBackgroundView.contentView : self.glassBackgroundContainer.contentView + let attachmentButtonParentView = wideGlassLayout.mergeLeftSlot ? self.textInputContainerBackgroundView.contentView : self.glassBackgroundContainer.contentView if self.attachmentButtonBackground.superview !== attachmentButtonParentView { attachmentButtonParentView.addSubview(self.attachmentButtonBackground) } @@ -3524,12 +3492,12 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg attachmentButtonParentView.addSubview(self.attachmentButtonDisabledNode.view) } let attachmentButtonDisplayFrame: CGRect - if resolvedWideGlassLayout.mergeLeftSlot { + if wideGlassLayout.mergeLeftSlot { attachmentButtonDisplayFrame = attachmentButtonFrame.offsetBy(dx: -textInputContainerBackgroundFrame.minX, dy: -textInputContainerBackgroundFrame.minY) } else { attachmentButtonDisplayFrame = attachmentButtonFrame } - self.attachmentButtonBackground.update(size: attachmentButtonFrame.size, cornerRadius: attachmentButtonFrame.height * 0.5, isDark: interfaceState.theme.overallDarkAppearance, tintColor: defaultGlassTintColor, isInteractive: true, isVisible: !resolvedWideGlassLayout.mergeLeftSlot, transition: ComponentTransition(transition)) + self.attachmentButtonBackground.update(size: attachmentButtonFrame.size, cornerRadius: attachmentButtonFrame.height * 0.5, isDark: interfaceState.theme.overallDarkAppearance, tintColor: defaultGlassTintColor, isInteractive: true, isVisible: !wideGlassLayout.mergeLeftSlot, transition: ComponentTransition(transition)) transition.updateFrame(layer: self.attachmentButtonBackground.layer, frame: attachmentButtonDisplayFrame) transition.updateFrame(layer: self.attachmentButton.layer, frame: CGRect(origin: CGPoint(), size: attachmentButtonFrame.size)) From a9eac7237e2481c346f5d92dd6ed367048f97cbd Mon Sep 17 00:00:00 2001 From: Lev Poznyakov Date: Sun, 12 Apr 2026 18:05:48 +0400 Subject: [PATCH 4/9] wideGlassTextField --- Swiftgram/SGSettingsUI/Sources/SGSettingsController.swift | 8 ++++---- Swiftgram/SGSimpleSettings/Sources/SimpleSettings.swift | 8 ++++---- .../Sources/ChatTextInputPanelNode.swift | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Swiftgram/SGSettingsUI/Sources/SGSettingsController.swift b/Swiftgram/SGSettingsUI/Sources/SGSettingsController.swift index 63123511ed..d8f906c05d 100644 --- a/Swiftgram/SGSettingsUI/Sources/SGSettingsController.swift +++ b/Swiftgram/SGSettingsUI/Sources/SGSettingsController.swift @@ -96,7 +96,7 @@ private enum SGBoolSetting: String { case defaultEmojisFirst case messageDoubleTapActionOutgoingEdit case wideChannelPosts - case wideGlass + case wideGlassTextField case forceEmojiTab case forceBuiltInMic case secondsInMessages @@ -310,7 +310,7 @@ private func SGControllerEntries(presentationData: PresentationData, callListSet entries.append(.notice(id: id.count, section: .other, text: i18n("Settings.swipeForVideoPIP.Notice", lang))) entries.append(.toggle(id: id.count, section: .other, settingName: .hideChannelBottomButton, value: !SGSimpleSettings.shared.hideChannelBottomButton, text: i18n("Settings.showChannelBottomButton", lang), enabled: true)) entries.append(.toggle(id: id.count, section: .other, settingName: .wideChannelPosts, value: SGSimpleSettings.shared.wideChannelPosts, text: i18n("Settings.wideChannelPosts", lang), enabled: true)) - entries.append(.toggle(id: id.count, section: .other, settingName: .wideGlass, value: SGSimpleSettings.shared.wideGlass, text: i18n("Settings.wideGlass", lang), enabled: true)) + entries.append(.toggle(id: id.count, section: .other, settingName: .wideGlassTextField, value: SGSimpleSettings.shared.wideGlassTextField, text: i18n("Settings.wideGlassTextField", lang), enabled: true)) entries.append(.toggle(id: id.count, section: .other, settingName: .secondsInMessages, value: SGSimpleSettings.shared.secondsInMessages, text: i18n("Settings.secondsInMessages", lang), enabled: true)) entries.append(.toggle(id: id.count, section: .other, settingName: .messageDoubleTapActionOutgoingEdit, value: SGSimpleSettings.shared.messageDoubleTapActionOutgoing == SGSimpleSettings.MessageDoubleTapAction.edit.rawValue, text: i18n("Settings.messageDoubleTapActionOutgoingEdit", lang), enabled: true)) entries.append(.toggle(id: id.count, section: .other, settingName: .hideRecordingButton, value: !SGSimpleSettings.shared.hideRecordingButton, text: i18n("Settings.RecordingButton", lang), enabled: true)) @@ -496,8 +496,8 @@ public func sgSettingsController(context: AccountContext/*, focusOnItemTag: Int? SGSimpleSettings.shared.messageDoubleTapActionOutgoing = value ? SGSimpleSettings.MessageDoubleTapAction.edit.rawValue : SGSimpleSettings.MessageDoubleTapAction.default.rawValue case .wideChannelPosts: SGSimpleSettings.shared.wideChannelPosts = value - case .wideGlass: - SGSimpleSettings.shared.wideGlass = value + case .wideGlassTextField: + SGSimpleSettings.shared.wideGlassTextField = value case .forceEmojiTab: SGSimpleSettings.shared.forceEmojiTab = value case .forceBuiltInMic: diff --git a/Swiftgram/SGSimpleSettings/Sources/SimpleSettings.swift b/Swiftgram/SGSimpleSettings/Sources/SimpleSettings.swift index 30a146ede8..bbb9d20517 100644 --- a/Swiftgram/SGSimpleSettings/Sources/SimpleSettings.swift +++ b/Swiftgram/SGSimpleSettings/Sources/SimpleSettings.swift @@ -149,7 +149,7 @@ public class SGSimpleSettings { case defaultEmojisFirst case messageDoubleTapActionOutgoing case wideChannelPosts - case wideGlass + case wideGlassTextField case forceEmojiTab case forceBuiltInMic case secondsInMessages @@ -308,7 +308,7 @@ public class SGSimpleSettings { Keys.defaultEmojisFirst.rawValue: false, Keys.messageDoubleTapActionOutgoing.rawValue: MessageDoubleTapAction.default.rawValue, Keys.wideChannelPosts.rawValue: false, - Keys.wideGlass.rawValue: false, + Keys.wideGlassTextField.rawValue: false, Keys.forceEmojiTab.rawValue: false, Keys.hideChannelBottomButton.rawValue: false, Keys.secondsInMessages.rawValue: false, @@ -521,8 +521,8 @@ public class SGSimpleSettings { @UserDefault(key: Keys.wideChannelPosts.rawValue) public var wideChannelPosts: Bool - @UserDefault(key: Keys.wideGlass.rawValue) - public var wideGlass: Bool + @UserDefault(key: Keys.wideGlassTextField.rawValue) + public var wideGlassTextField: Bool @UserDefault(key: Keys.forceEmojiTab.rawValue) public var forceEmojiTab: Bool diff --git a/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/ChatTextInputPanelNode.swift b/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/ChatTextInputPanelNode.swift index 317e91802e..123e8d5087 100644 --- a/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/ChatTextInputPanelNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/ChatTextInputPanelNode.swift @@ -1349,7 +1349,7 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg } private func calculateWideGlassLayout(interfaceState: ChatPresentationInterfaceState, displayMediaButton: Bool, hasMediaRecording: Bool, inputHasText: Bool, hasForward: Bool, hasMediaDraft: Bool, hasSlowmodeButton: Bool, isEditingMedia: Bool) -> WideGlassLayout { - guard SGSimpleSettings.shared.wideGlass else { + guard SGSimpleSettings.shared.wideGlassTextField else { return .disabled } From 87d2f40c33dc2ffc98c82e4fb7dd6c05b0774273 Mon Sep 17 00:00:00 2001 From: Lev Poznyakov Date: Sun, 12 Apr 2026 18:06:01 +0400 Subject: [PATCH 5/9] ai translations --- Swiftgram/SGStrings/Strings/af.lproj/SGLocalizable.strings | 1 + Swiftgram/SGStrings/Strings/ar.lproj/SGLocalizable.strings | 1 + Swiftgram/SGStrings/Strings/ca.lproj/SGLocalizable.strings | 1 + Swiftgram/SGStrings/Strings/cs.lproj/SGLocalizable.strings | 1 + Swiftgram/SGStrings/Strings/da.lproj/SGLocalizable.strings | 1 + Swiftgram/SGStrings/Strings/de.lproj/SGLocalizable.strings | 1 + Swiftgram/SGStrings/Strings/el.lproj/SGLocalizable.strings | 1 + Swiftgram/SGStrings/Strings/en.lproj/SGLocalizable.strings | 1 + Swiftgram/SGStrings/Strings/es.lproj/SGLocalizable.strings | 1 + Swiftgram/SGStrings/Strings/fa.lproj/SGLocalizable.strings | 2 ++ Swiftgram/SGStrings/Strings/fi.lproj/SGLocalizable.strings | 1 + Swiftgram/SGStrings/Strings/fr.lproj/SGLocalizable.strings | 1 + Swiftgram/SGStrings/Strings/he.lproj/SGLocalizable.strings | 1 + Swiftgram/SGStrings/Strings/hi.lproj/SGLocalizable.strings | 1 + Swiftgram/SGStrings/Strings/hu.lproj/SGLocalizable.strings | 1 + Swiftgram/SGStrings/Strings/id.lproj/SGLocalizable.strings | 1 + Swiftgram/SGStrings/Strings/it.lproj/SGLocalizable.strings | 1 + Swiftgram/SGStrings/Strings/ja.lproj/SGLocalizable.strings | 1 + Swiftgram/SGStrings/Strings/km.lproj/SGLocalizable.strings | 2 ++ Swiftgram/SGStrings/Strings/ko.lproj/SGLocalizable.strings | 1 + Swiftgram/SGStrings/Strings/ku.lproj/SGLocalizable.strings | 2 ++ Swiftgram/SGStrings/Strings/nl.lproj/SGLocalizable.strings | 1 + Swiftgram/SGStrings/Strings/no.lproj/SGLocalizable.strings | 1 + Swiftgram/SGStrings/Strings/pl.lproj/SGLocalizable.strings | 1 + Swiftgram/SGStrings/Strings/pt.lproj/SGLocalizable.strings | 1 + Swiftgram/SGStrings/Strings/ro.lproj/SGLocalizable.strings | 1 + Swiftgram/SGStrings/Strings/ru.lproj/SGLocalizable.strings | 1 + Swiftgram/SGStrings/Strings/si.lproj/SGLocalizable.strings | 2 ++ Swiftgram/SGStrings/Strings/sk.lproj/SGLocalizable.strings | 2 ++ Swiftgram/SGStrings/Strings/sr.lproj/SGLocalizable.strings | 1 + Swiftgram/SGStrings/Strings/sv.lproj/SGLocalizable.strings | 1 + Swiftgram/SGStrings/Strings/tr.lproj/SGLocalizable.strings | 1 + Swiftgram/SGStrings/Strings/uk.lproj/SGLocalizable.strings | 1 + Swiftgram/SGStrings/Strings/uz.lproj/SGLocalizable.strings | 1 + Swiftgram/SGStrings/Strings/vi.lproj/SGLocalizable.strings | 1 + Swiftgram/SGStrings/Strings/zh-hans.lproj/SGLocalizable.strings | 1 + Swiftgram/SGStrings/Strings/zh-hant.lproj/SGLocalizable.strings | 1 + 37 files changed, 42 insertions(+) diff --git a/Swiftgram/SGStrings/Strings/af.lproj/SGLocalizable.strings b/Swiftgram/SGStrings/Strings/af.lproj/SGLocalizable.strings index 5acfe970d5..99d35dc827 100644 --- a/Swiftgram/SGStrings/Strings/af.lproj/SGLocalizable.strings +++ b/Swiftgram/SGStrings/Strings/af.lproj/SGLocalizable.strings @@ -130,6 +130,7 @@ "Settings.messageDoubleTapActionOutgoingEdit" = "Dubbelklik om boodskap te wysig"; "Settings.wideChannelPosts" = "Wye pos in kanale"; +"Settings.wideGlassTextField" = "Wye glas teksveld"; "Settings.ForceEmojiTab" = "Emoji klawerbord standaard"; "Settings.forceBuiltInMic" = "Kragtoestel Mikrofoon"; diff --git a/Swiftgram/SGStrings/Strings/ar.lproj/SGLocalizable.strings b/Swiftgram/SGStrings/Strings/ar.lproj/SGLocalizable.strings index 41f1168454..9f2acff409 100644 --- a/Swiftgram/SGStrings/Strings/ar.lproj/SGLocalizable.strings +++ b/Swiftgram/SGStrings/Strings/ar.lproj/SGLocalizable.strings @@ -130,6 +130,7 @@ "Settings.messageDoubleTapActionOutgoingEdit" = "اضغط مزدوجًا لتحرير الرسالة"; "Settings.wideChannelPosts" = "المشاركات الواسعة في القنوات"; +"Settings.wideGlassTextField" = "حقل نص زجاجي واسع"; "Settings.ForceEmojiTab" = "لوحة مفاتيح الرموز التعبيرية افتراضيًا"; "Settings.forceBuiltInMic" = "قوة ميكروفون الجهاز"; diff --git a/Swiftgram/SGStrings/Strings/ca.lproj/SGLocalizable.strings b/Swiftgram/SGStrings/Strings/ca.lproj/SGLocalizable.strings index a48c45fa92..5798f6f39c 100644 --- a/Swiftgram/SGStrings/Strings/ca.lproj/SGLocalizable.strings +++ b/Swiftgram/SGStrings/Strings/ca.lproj/SGLocalizable.strings @@ -130,6 +130,7 @@ "Settings.messageDoubleTapActionOutgoingEdit" = "Toqueu dues vegades per editar el missatge"; "Settings.wideChannelPosts" = "Entrades àmplies als canals"; +"Settings.wideGlassTextField" = "Camp de text de vidre ampli"; "Settings.ForceEmojiTab" = "Teclat d'emojis per defecte"; "Settings.forceBuiltInMic" = "Força el Micròfon del Dispositiu"; diff --git a/Swiftgram/SGStrings/Strings/cs.lproj/SGLocalizable.strings b/Swiftgram/SGStrings/Strings/cs.lproj/SGLocalizable.strings index 05cf6ed482..cf723d7fe9 100644 --- a/Swiftgram/SGStrings/Strings/cs.lproj/SGLocalizable.strings +++ b/Swiftgram/SGStrings/Strings/cs.lproj/SGLocalizable.strings @@ -130,6 +130,7 @@ "Settings.messageDoubleTapActionOutgoingEdit" = "Dvojitým klepnutím upravte zprávu"; "Settings.wideChannelPosts" = "Široké příspěvky ve skupinách"; +"Settings.wideGlassTextField" = "Široké skleněné textové pole"; "Settings.ForceEmojiTab" = "Emoji klávesnice ve výchozím nastavení"; "Settings.forceBuiltInMic" = "Vynutit vestavěný mikrofon zařízení"; diff --git a/Swiftgram/SGStrings/Strings/da.lproj/SGLocalizable.strings b/Swiftgram/SGStrings/Strings/da.lproj/SGLocalizable.strings index cb0c4174db..cb5d7906af 100644 --- a/Swiftgram/SGStrings/Strings/da.lproj/SGLocalizable.strings +++ b/Swiftgram/SGStrings/Strings/da.lproj/SGLocalizable.strings @@ -130,6 +130,7 @@ "Settings.messageDoubleTapActionOutgoingEdit" = "Dobbelt tryk for at redigere besked"; "Settings.wideChannelPosts" = "Brede indlæg i kanaler"; +"Settings.wideGlassTextField" = "Bredt tekstfelt i glas"; "Settings.ForceEmojiTab" = "Emoji-tastatur som standard"; "Settings.forceBuiltInMic" = "Tving enhedsmikrofon"; diff --git a/Swiftgram/SGStrings/Strings/de.lproj/SGLocalizable.strings b/Swiftgram/SGStrings/Strings/de.lproj/SGLocalizable.strings index 726e485dcf..d93d144ded 100644 --- a/Swiftgram/SGStrings/Strings/de.lproj/SGLocalizable.strings +++ b/Swiftgram/SGStrings/Strings/de.lproj/SGLocalizable.strings @@ -130,6 +130,7 @@ "Settings.messageDoubleTapActionOutgoingEdit" = "Doppeltippen, um Nachricht zu bearbeiten"; "Settings.wideChannelPosts" = "Breite Beiträge in Kanälen"; +"Settings.wideGlassTextField" = "Breites Glas-Textfeld"; "Settings.ForceEmojiTab" = "Emoji-Tastatur standardmäßig"; "Settings.forceBuiltInMic" = "Erzwinge Geräte-Mikrofon"; diff --git a/Swiftgram/SGStrings/Strings/el.lproj/SGLocalizable.strings b/Swiftgram/SGStrings/Strings/el.lproj/SGLocalizable.strings index 010c2fd7ed..a505177648 100644 --- a/Swiftgram/SGStrings/Strings/el.lproj/SGLocalizable.strings +++ b/Swiftgram/SGStrings/Strings/el.lproj/SGLocalizable.strings @@ -130,6 +130,7 @@ "Settings.messageDoubleTapActionOutgoingEdit" = "Διπλό Πάτημα για Επεξεργασία Μηνύματος"; "Settings.wideChannelPosts" = "Πλατείες αναρτήσεις στα κανάλια"; +"Settings.wideGlassTextField" = "Ευρύ γυάλινο πεδίο κειμένου"; "Settings.ForceEmojiTab" = "Πληκτρολόγιο Emoji από προεπιλογή"; "Settings.forceBuiltInMic" = "Εξαναγκασμός Μικροφώνου Συσκευής"; diff --git a/Swiftgram/SGStrings/Strings/en.lproj/SGLocalizable.strings b/Swiftgram/SGStrings/Strings/en.lproj/SGLocalizable.strings index 0383460b65..0a753b5f86 100644 --- a/Swiftgram/SGStrings/Strings/en.lproj/SGLocalizable.strings +++ b/Swiftgram/SGStrings/Strings/en.lproj/SGLocalizable.strings @@ -156,6 +156,7 @@ "Settings.messageDoubleTapActionOutgoingEdit" = "Double-tap to edit message"; "Settings.wideChannelPosts" = "Wide posts in channels"; +"Settings.wideGlassTextField" = "Wide glass text field"; "Settings.ForceEmojiTab" = "Emoji tab first"; "Settings.forceBuiltInMic" = "Force Device Microphone"; diff --git a/Swiftgram/SGStrings/Strings/es.lproj/SGLocalizable.strings b/Swiftgram/SGStrings/Strings/es.lproj/SGLocalizable.strings index 4fcb6aee08..e0c232998f 100644 --- a/Swiftgram/SGStrings/Strings/es.lproj/SGLocalizable.strings +++ b/Swiftgram/SGStrings/Strings/es.lproj/SGLocalizable.strings @@ -130,6 +130,7 @@ "Settings.messageDoubleTapActionOutgoingEdit" = "Doble toque para editar mensaje"; "Settings.wideChannelPosts" = "Publicaciones amplias en canales"; +"Settings.wideGlassTextField" = "Campo de texto de cristal ancho"; "Settings.ForceEmojiTab" = "Teclado de emojis por defecto"; "Settings.forceBuiltInMic" = "Forzar Micrófono del Dispositivo"; diff --git a/Swiftgram/SGStrings/Strings/fa.lproj/SGLocalizable.strings b/Swiftgram/SGStrings/Strings/fa.lproj/SGLocalizable.strings index 1581d63536..2f36db8ae6 100644 --- a/Swiftgram/SGStrings/Strings/fa.lproj/SGLocalizable.strings +++ b/Swiftgram/SGStrings/Strings/fa.lproj/SGLocalizable.strings @@ -7,3 +7,5 @@ "Settings.ShowProfileID" = "نمایش ایدی پروفایل"; "Settings.Translation.QuickTranslateButton" = "دکمه ترجمه سریع"; "ContextMenu.SaveToCloud" = "ذخیره در فضای ابری"; + +"Settings.wideGlassTextField" = "کادر متنی شیشه‌ای عریض"; diff --git a/Swiftgram/SGStrings/Strings/fi.lproj/SGLocalizable.strings b/Swiftgram/SGStrings/Strings/fi.lproj/SGLocalizable.strings index 3e7ea96fbf..511e4c679e 100644 --- a/Swiftgram/SGStrings/Strings/fi.lproj/SGLocalizable.strings +++ b/Swiftgram/SGStrings/Strings/fi.lproj/SGLocalizable.strings @@ -132,6 +132,7 @@ "Settings.messageDoubleTapActionOutgoingEdit" = "Paina kahdesti muokataksesi viestiä"; "Settings.wideChannelPosts" = "Leveitä viestejä kanavissa"; +"Settings.wideGlassTextField" = "Leveä lasinen tekstikenttä"; "Settings.ForceEmojiTab" = "Emojivälilehti ensin"; "Settings.forceBuiltInMic" = "Pakota laitteen mikrofoni"; diff --git a/Swiftgram/SGStrings/Strings/fr.lproj/SGLocalizable.strings b/Swiftgram/SGStrings/Strings/fr.lproj/SGLocalizable.strings index adc9a1b3d3..93cf062510 100644 --- a/Swiftgram/SGStrings/Strings/fr.lproj/SGLocalizable.strings +++ b/Swiftgram/SGStrings/Strings/fr.lproj/SGLocalizable.strings @@ -129,6 +129,7 @@ "Settings.messageDoubleTapActionOutgoingEdit" = "Appuyez deux fois pour modifier le message"; "Settings.wideChannelPosts" = "Messages larges dans les canaux"; +"Settings.wideGlassTextField" = "Champ de texte large en verre"; "Settings.ForceEmojiTab" = "Clavier emoji par défaut"; "Settings.forceBuiltInMic" = "Forcer le microphone de l'appareil"; diff --git a/Swiftgram/SGStrings/Strings/he.lproj/SGLocalizable.strings b/Swiftgram/SGStrings/Strings/he.lproj/SGLocalizable.strings index eb4562b7c8..0fa22090b8 100644 --- a/Swiftgram/SGStrings/Strings/he.lproj/SGLocalizable.strings +++ b/Swiftgram/SGStrings/Strings/he.lproj/SGLocalizable.strings @@ -130,6 +130,7 @@ "Settings.messageDoubleTapActionOutgoingEdit" = "לחץ פעמיים לעריכת הודעה"; "Settings.wideChannelPosts" = "פוסטים רחבים בערוצים"; +"Settings.wideGlassTextField" = "שדה טקסט מזכוכית רחב"; "Settings.ForceEmojiTab" = "מקלדת Emoji כברירת מחדל"; "Settings.forceBuiltInMic" = "כוח מיקרופון המכשיר"; diff --git a/Swiftgram/SGStrings/Strings/hi.lproj/SGLocalizable.strings b/Swiftgram/SGStrings/Strings/hi.lproj/SGLocalizable.strings index 6adc148a1d..e8bb8a6ef3 100644 --- a/Swiftgram/SGStrings/Strings/hi.lproj/SGLocalizable.strings +++ b/Swiftgram/SGStrings/Strings/hi.lproj/SGLocalizable.strings @@ -130,6 +130,7 @@ "Settings.messageDoubleTapActionOutgoingEdit" = "संदेश संपादित करने के लिए दो बार टैप करें"; "Settings.wideChannelPosts" = "चैनल में चौड़े पोस्ट"; +"Settings.wideGlassTextField" = "चौड़ा ग्लास टेक्स्ट फ़ील्ड"; "Settings.ForceEmojiTab" = "डिफ़ॉल्ट ईमोजी कुंजीपटल"; "Settings.forceBuiltInMic" = "फ़ोर्स डिवाइस माइक्रोफ़ोन"; diff --git a/Swiftgram/SGStrings/Strings/hu.lproj/SGLocalizable.strings b/Swiftgram/SGStrings/Strings/hu.lproj/SGLocalizable.strings index d357bb69b6..bece6f4288 100644 --- a/Swiftgram/SGStrings/Strings/hu.lproj/SGLocalizable.strings +++ b/Swiftgram/SGStrings/Strings/hu.lproj/SGLocalizable.strings @@ -130,6 +130,7 @@ "Settings.messageDoubleTapActionOutgoingEdit" = "Dupla koppintás a üzenet szerkesztéséhez"; "Settings.wideChannelPosts" = "Széles posztok csatornákban"; +"Settings.wideGlassTextField" = "Széles üveg szövegmező"; "Settings.ForceEmojiTab" = "Alapértelmezett Emoji billentyűzet"; "Settings.forceBuiltInMic" = "Eszköz mikrofonjának kényszerítése"; diff --git a/Swiftgram/SGStrings/Strings/id.lproj/SGLocalizable.strings b/Swiftgram/SGStrings/Strings/id.lproj/SGLocalizable.strings index 44ba7a11a2..c1246dfd9b 100644 --- a/Swiftgram/SGStrings/Strings/id.lproj/SGLocalizable.strings +++ b/Swiftgram/SGStrings/Strings/id.lproj/SGLocalizable.strings @@ -130,6 +130,7 @@ "Settings.messageDoubleTapActionOutgoingEdit" = "Ketuk dua kali untuk mengedit pesan"; "Settings.wideChannelPosts" = "Pos Luas di Saluran"; +"Settings.wideGlassTextField" = "Kolom teks kaca lebar"; "Settings.ForceEmojiTab" = "Papan emoji secara default"; "Settings.forceBuiltInMic" = "Paksa Mikrofon Perangkat"; diff --git a/Swiftgram/SGStrings/Strings/it.lproj/SGLocalizable.strings b/Swiftgram/SGStrings/Strings/it.lproj/SGLocalizable.strings index ca32eafb8c..b795c32eeb 100644 --- a/Swiftgram/SGStrings/Strings/it.lproj/SGLocalizable.strings +++ b/Swiftgram/SGStrings/Strings/it.lproj/SGLocalizable.strings @@ -130,6 +130,7 @@ "Settings.messageDoubleTapActionOutgoingEdit" = "Doppio tap per modificare il messaggio"; "Settings.wideChannelPosts" = "Ampie colonne nei canali"; +"Settings.wideGlassTextField" = "Ampio campo di testo in vetro"; "Settings.ForceEmojiTab" = "Tastiera emoji predefinita"; "Settings.forceBuiltInMic" = "Forza Microfono Dispositivo"; diff --git a/Swiftgram/SGStrings/Strings/ja.lproj/SGLocalizable.strings b/Swiftgram/SGStrings/Strings/ja.lproj/SGLocalizable.strings index afe45d6566..586ff1cddf 100644 --- a/Swiftgram/SGStrings/Strings/ja.lproj/SGLocalizable.strings +++ b/Swiftgram/SGStrings/Strings/ja.lproj/SGLocalizable.strings @@ -133,6 +133,7 @@ "Settings.messageDoubleTapActionOutgoingEdit" = "メッセージを編集するにはタップをダブルタップ"; "Settings.wideChannelPosts" = "チャンネル内の幅広い投稿"; +"Settings.wideGlassTextField" = "幅広のガラステキストフィールド"; "Settings.ForceEmojiTab" = "デフォルトで絵文字キーボード"; "Settings.forceBuiltInMic" = "デバイスのマイクを強制"; diff --git a/Swiftgram/SGStrings/Strings/km.lproj/SGLocalizable.strings b/Swiftgram/SGStrings/Strings/km.lproj/SGLocalizable.strings index 928cf393a6..e13d80c675 100644 --- a/Swiftgram/SGStrings/Strings/km.lproj/SGLocalizable.strings +++ b/Swiftgram/SGStrings/Strings/km.lproj/SGLocalizable.strings @@ -6,3 +6,5 @@ "Settings.HidePhoneInSettingsUI" = "លាក់លេខទូរសព្ទក្នុងការកំណត់"; "Settings.Folders.BottomTab" = "ថតឯបាត"; "ContextMenu.SaveToCloud" = "រក្សាទុកទៅពពក"; + +"Settings.wideGlassTextField" = "ប្រអប់អត្ថបទកញ្ចក់ទូលាយ"; diff --git a/Swiftgram/SGStrings/Strings/ko.lproj/SGLocalizable.strings b/Swiftgram/SGStrings/Strings/ko.lproj/SGLocalizable.strings index 501a5f64b4..249a9f31f3 100644 --- a/Swiftgram/SGStrings/Strings/ko.lproj/SGLocalizable.strings +++ b/Swiftgram/SGStrings/Strings/ko.lproj/SGLocalizable.strings @@ -130,6 +130,7 @@ "Settings.messageDoubleTapActionOutgoingEdit" = "메시지 수정을 위해 두 번 탭"; "Settings.wideChannelPosts" = "채널의 넓은 게시물"; +"Settings.wideGlassTextField" = "넓은 유리 텍스트 필드"; "Settings.ForceEmojiTab" = "기본으로 이모티콘 키보드"; "Settings.forceBuiltInMic" = "장치 마이크 강제"; diff --git a/Swiftgram/SGStrings/Strings/ku.lproj/SGLocalizable.strings b/Swiftgram/SGStrings/Strings/ku.lproj/SGLocalizable.strings index 62ac20a89c..5a8fafd644 100644 --- a/Swiftgram/SGStrings/Strings/ku.lproj/SGLocalizable.strings +++ b/Swiftgram/SGStrings/Strings/ku.lproj/SGLocalizable.strings @@ -8,3 +8,5 @@ "Settings.Translation.QuickTranslateButton" = "دوگمەی وەرگێڕانی خێرا"; "Settings.Folders.BottomTab" = "بوخچەکان لە خوارەوە"; "ContextMenu.SaveToCloud" = "هەڵگرتن لە کڵاود"; + +"Settings.wideGlassTextField" = "خانەی دەقی شوشەیی فراوان"; diff --git a/Swiftgram/SGStrings/Strings/nl.lproj/SGLocalizable.strings b/Swiftgram/SGStrings/Strings/nl.lproj/SGLocalizable.strings index d80e6ca49e..fcfed3bb25 100644 --- a/Swiftgram/SGStrings/Strings/nl.lproj/SGLocalizable.strings +++ b/Swiftgram/SGStrings/Strings/nl.lproj/SGLocalizable.strings @@ -130,6 +130,7 @@ "Settings.messageDoubleTapActionOutgoingEdit" = "Dubbelklik om bericht te bewerken"; "Settings.wideChannelPosts" = "Brede berichten in kanalen"; +"Settings.wideGlassTextField" = "Breed glazen tekstveld"; "Settings.ForceEmojiTab" = "Emoji-toetsenbord standaard"; "Settings.forceBuiltInMic" = "Forceer Apparaatmicrofoon"; diff --git a/Swiftgram/SGStrings/Strings/no.lproj/SGLocalizable.strings b/Swiftgram/SGStrings/Strings/no.lproj/SGLocalizable.strings index 5fd16d5c62..0d5e6ea2db 100644 --- a/Swiftgram/SGStrings/Strings/no.lproj/SGLocalizable.strings +++ b/Swiftgram/SGStrings/Strings/no.lproj/SGLocalizable.strings @@ -130,6 +130,7 @@ "Settings.messageDoubleTapActionOutgoingEdit" = "Dobbelttrykk for å redigere meldingen"; "Settings.wideChannelPosts" = "Brede innlegg i kanaler"; +"Settings.wideGlassTextField" = "Bredt tekstfelt i glass"; "Settings.ForceEmojiTab" = "Emoji-tastatur som standard"; "Settings.forceBuiltInMic" = "Tving Mikrofon på enheten"; diff --git a/Swiftgram/SGStrings/Strings/pl.lproj/SGLocalizable.strings b/Swiftgram/SGStrings/Strings/pl.lproj/SGLocalizable.strings index 9efb5c2247..263e115d66 100644 --- a/Swiftgram/SGStrings/Strings/pl.lproj/SGLocalizable.strings +++ b/Swiftgram/SGStrings/Strings/pl.lproj/SGLocalizable.strings @@ -132,6 +132,7 @@ "Settings.messageDoubleTapActionOutgoingEdit" = "Podwójne stuknięcie, aby edytować wiadomość"; "Settings.wideChannelPosts" = "Szerokie wpisy w kanałach"; +"Settings.wideGlassTextField" = "Szerokie szklane pole tekstowe"; "Settings.ForceEmojiTab" = "Klawiatura emoji domyślnie"; "Settings.forceBuiltInMic" = "Wymuś mikrofon urządzenia"; diff --git a/Swiftgram/SGStrings/Strings/pt.lproj/SGLocalizable.strings b/Swiftgram/SGStrings/Strings/pt.lproj/SGLocalizable.strings index a45973f988..686bd378b3 100644 --- a/Swiftgram/SGStrings/Strings/pt.lproj/SGLocalizable.strings +++ b/Swiftgram/SGStrings/Strings/pt.lproj/SGLocalizable.strings @@ -151,6 +151,7 @@ "Settings.messageDoubleTapActionOutgoingEdit" = "Toque duplo para editar mensagem"; "Settings.wideChannelPosts" = "Postagens amplas nos canais"; +"Settings.wideGlassTextField" = "Campo de texto de vidro amplo"; "Settings.ForceEmojiTab" = "Teclado de emojis por padrão"; "Settings.forceBuiltInMic" = "Forçar Microfone do Dispositivo"; diff --git a/Swiftgram/SGStrings/Strings/ro.lproj/SGLocalizable.strings b/Swiftgram/SGStrings/Strings/ro.lproj/SGLocalizable.strings index ccb2ad1e46..fda96e6bbf 100644 --- a/Swiftgram/SGStrings/Strings/ro.lproj/SGLocalizable.strings +++ b/Swiftgram/SGStrings/Strings/ro.lproj/SGLocalizable.strings @@ -130,6 +130,7 @@ "Settings.messageDoubleTapActionOutgoingEdit" = "Apăsați de două ori pentru a edita mesajul"; "Settings.wideChannelPosts" = "Postări late în canale"; +"Settings.wideGlassTextField" = "Câmp text lat din sticlă"; "Settings.ForceEmojiTab" = "Tastatură emoji implicită"; "Settings.forceBuiltInMic" = "Forțează Microfon Dispozitiv"; diff --git a/Swiftgram/SGStrings/Strings/ru.lproj/SGLocalizable.strings b/Swiftgram/SGStrings/Strings/ru.lproj/SGLocalizable.strings index 0488ecf5f3..3bae725089 100644 --- a/Swiftgram/SGStrings/Strings/ru.lproj/SGLocalizable.strings +++ b/Swiftgram/SGStrings/Strings/ru.lproj/SGLocalizable.strings @@ -151,6 +151,7 @@ "Settings.messageDoubleTapActionOutgoingEdit" = "Редактирование двойным тапом"; "Settings.wideChannelPosts" = "Широкие посты в каналах"; +"Settings.wideGlassTextField" = "Широкое стеклянное поле ввода"; "Settings.ForceEmojiTab" = "Сначала вкладка смайлов"; "Settings.forceBuiltInMic" = "Микрофон устройства"; diff --git a/Swiftgram/SGStrings/Strings/si.lproj/SGLocalizable.strings b/Swiftgram/SGStrings/Strings/si.lproj/SGLocalizable.strings index 869c70ba7e..3539670a5b 100644 --- a/Swiftgram/SGStrings/Strings/si.lproj/SGLocalizable.strings +++ b/Swiftgram/SGStrings/Strings/si.lproj/SGLocalizable.strings @@ -1,2 +1,4 @@ "Settings.Tabs.Header" = "පටිති"; "ContextMenu.SaveToCloud" = "මේඝයට සුරකින්න"; + +"Settings.wideGlassTextField" = "පුළුල් වීදුරු පෙළ ක්ෂේත්‍රය"; diff --git a/Swiftgram/SGStrings/Strings/sk.lproj/SGLocalizable.strings b/Swiftgram/SGStrings/Strings/sk.lproj/SGLocalizable.strings index 77376339e3..684f16d60d 100644 --- a/Swiftgram/SGStrings/Strings/sk.lproj/SGLocalizable.strings +++ b/Swiftgram/SGStrings/Strings/sk.lproj/SGLocalizable.strings @@ -2,3 +2,5 @@ "Settings.Tabs.ShowContacts" = "Zobraziť kontakty"; "Settings.Tabs.ShowNames" = "Zobraziť názvy záložiek"; "ContextMenu.SaveToCloud" = "Uložiť na Cloud"; + +"Settings.wideGlassTextField" = "Široké sklenené textové pole"; diff --git a/Swiftgram/SGStrings/Strings/sr.lproj/SGLocalizable.strings b/Swiftgram/SGStrings/Strings/sr.lproj/SGLocalizable.strings index c71efa9f16..8d5df111ea 100644 --- a/Swiftgram/SGStrings/Strings/sr.lproj/SGLocalizable.strings +++ b/Swiftgram/SGStrings/Strings/sr.lproj/SGLocalizable.strings @@ -130,6 +130,7 @@ "Settings.messageDoubleTapActionOutgoingEdit" = "Двоструки додир за уређивање поруке"; "Settings.wideChannelPosts" = "Широки постови у каналима"; +"Settings.wideGlassTextField" = "Широко стаклено поље за текст"; "Settings.ForceEmojiTab" = "Емоџи тастатура по подразумеваној подешавања"; "Settings.forceBuiltInMic" = "Наметни микрофон уређаја"; diff --git a/Swiftgram/SGStrings/Strings/sv.lproj/SGLocalizable.strings b/Swiftgram/SGStrings/Strings/sv.lproj/SGLocalizable.strings index de9ed08295..4c6a7609a0 100644 --- a/Swiftgram/SGStrings/Strings/sv.lproj/SGLocalizable.strings +++ b/Swiftgram/SGStrings/Strings/sv.lproj/SGLocalizable.strings @@ -130,6 +130,7 @@ "Settings.messageDoubleTapActionOutgoingEdit" = "Dubbeltryck för att redigera meddelandet"; "Settings.wideChannelPosts" = "Bredda inlägg i kanaler"; +"Settings.wideGlassTextField" = "Brett glastextfält"; "Settings.ForceEmojiTab" = "Emoji-tangentbord som standard"; "Settings.forceBuiltInMic" = "Tvinga enhetsmikrofonen"; diff --git a/Swiftgram/SGStrings/Strings/tr.lproj/SGLocalizable.strings b/Swiftgram/SGStrings/Strings/tr.lproj/SGLocalizable.strings index 7f1b643ec7..0e0fcd3ea1 100644 --- a/Swiftgram/SGStrings/Strings/tr.lproj/SGLocalizable.strings +++ b/Swiftgram/SGStrings/Strings/tr.lproj/SGLocalizable.strings @@ -130,6 +130,7 @@ "Settings.messageDoubleTapActionOutgoingEdit" = "Mesajı düzenlemek için çift dokunun"; "Settings.wideChannelPosts" = "Kanallardaki geniş gönderiler"; +"Settings.wideGlassTextField" = "Geniş cam metin alanı"; "Settings.ForceEmojiTab" = "Varsayılan olarak Emoji klavyesi"; "Settings.forceBuiltInMic" = "Cihaz Mikrofonunu Zorla"; diff --git a/Swiftgram/SGStrings/Strings/uk.lproj/SGLocalizable.strings b/Swiftgram/SGStrings/Strings/uk.lproj/SGLocalizable.strings index 405fcfb869..d67d241315 100644 --- a/Swiftgram/SGStrings/Strings/uk.lproj/SGLocalizable.strings +++ b/Swiftgram/SGStrings/Strings/uk.lproj/SGLocalizable.strings @@ -132,6 +132,7 @@ "Settings.messageDoubleTapActionOutgoingEdit" = "Ред. повідомлення подвійним дотиком"; "Settings.wideChannelPosts" = "Широкі пости в каналах"; +"Settings.wideGlassTextField" = "Широке скляне поле вводу"; "Settings.ForceEmojiTab" = "Клавіатура емодзі за замовчуванням"; "Settings.forceBuiltInMic" = "Використовувати мікрофон пристрою"; diff --git a/Swiftgram/SGStrings/Strings/uz.lproj/SGLocalizable.strings b/Swiftgram/SGStrings/Strings/uz.lproj/SGLocalizable.strings index cfab47bc31..6707cf10db 100644 --- a/Swiftgram/SGStrings/Strings/uz.lproj/SGLocalizable.strings +++ b/Swiftgram/SGStrings/Strings/uz.lproj/SGLocalizable.strings @@ -130,6 +130,7 @@ "Settings.messageDoubleTapActionOutgoingEdit" = "Xabarni tahrirlash uchun ikki marta bosing"; "Settings.wideChannelPosts" = "Keng postlar kanallarda"; +"Settings.wideGlassTextField" = "Keng shishali matn maydoni"; "Settings.ForceEmojiTab" = "Emoji klaviatura sukutiga"; "Settings.forceBuiltInMic" = "Qurilma Mikrofonini Kuchaytirish"; diff --git a/Swiftgram/SGStrings/Strings/vi.lproj/SGLocalizable.strings b/Swiftgram/SGStrings/Strings/vi.lproj/SGLocalizable.strings index 8878463be8..9f10ec8526 100644 --- a/Swiftgram/SGStrings/Strings/vi.lproj/SGLocalizable.strings +++ b/Swiftgram/SGStrings/Strings/vi.lproj/SGLocalizable.strings @@ -130,6 +130,7 @@ "Settings.messageDoubleTapActionOutgoingEdit" = "Double-tap để chỉnh sửa tin nhắn"; "Settings.wideChannelPosts" = "Bài đăng rộng trong các kênh"; +"Settings.wideGlassTextField" = "Trường văn bản kính rộng"; "Settings.ForceEmojiTab" = "Bàn phím Emoji mặc định"; "Settings.forceBuiltInMic" = "Buộc Micro Điện Thoại"; diff --git a/Swiftgram/SGStrings/Strings/zh-hans.lproj/SGLocalizable.strings b/Swiftgram/SGStrings/Strings/zh-hans.lproj/SGLocalizable.strings index 460aabbfaa..66adfcac06 100644 --- a/Swiftgram/SGStrings/Strings/zh-hans.lproj/SGLocalizable.strings +++ b/Swiftgram/SGStrings/Strings/zh-hans.lproj/SGLocalizable.strings @@ -136,6 +136,7 @@ "Settings.messageDoubleTapActionOutgoingEdit" = "双击编辑消息"; "Settings.wideChannelPosts" = "在频道中以更宽的版面显示消息"; +"Settings.wideGlassTextField" = "宽玻璃文本框"; "Settings.ForceEmojiTab" = "默认展示表情符号"; "Settings.forceBuiltInMic" = "强制使用设备麦克风"; diff --git a/Swiftgram/SGStrings/Strings/zh-hant.lproj/SGLocalizable.strings b/Swiftgram/SGStrings/Strings/zh-hant.lproj/SGLocalizable.strings index cc3963ac1f..2f21d3d145 100644 --- a/Swiftgram/SGStrings/Strings/zh-hant.lproj/SGLocalizable.strings +++ b/Swiftgram/SGStrings/Strings/zh-hant.lproj/SGLocalizable.strings @@ -136,6 +136,7 @@ "Settings.messageDoubleTapActionOutgoingEdit" = "雙擊以編輯訊息"; "Settings.wideChannelPosts" = "在頻道中以更寬的樣式顯示訊息"; +"Settings.wideGlassTextField" = "寬玻璃文字欄"; "Settings.ForceEmojiTab" = "預設表情符號鍵盤"; "Settings.forceBuiltInMic" = "強制使用裝置麥克風"; From 9cb6c89a56b363ca357f63d7086cb62d2a00ea43 Mon Sep 17 00:00:00 2001 From: Lev Poznyakov Date: Sat, 18 Apr 2026 22:11:50 +0400 Subject: [PATCH 6/9] fix: sendActionButtons.view not in liquid glass background --- .../Sources/ChatTextInputPanelNode.swift | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/ChatTextInputPanelNode.swift b/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/ChatTextInputPanelNode.swift index 123e8d5087..549f904f5e 100644 --- a/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/ChatTextInputPanelNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/ChatTextInputPanelNode.swift @@ -3396,21 +3396,14 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg sendActionButtonsFrame.origin.x += (sendActionButtonsSize.width - 3.0 * 2.0) * 0.5 - 3.0 } - let sendActionButtonsDisplayFrame: CGRect - if wideGlassLayout.mergeRightSlot { - sendActionButtonsDisplayFrame = sendActionButtonsFrame.offsetBy(dx: -textInputContainerBackgroundFrame.minX, dy: -textInputContainerBackgroundFrame.minY) - } else { - sendActionButtonsDisplayFrame = sendActionButtonsFrame - } - let sendActionButtonsParentView = wideGlassLayout.mergeRightSlot ? self.textInputContainerBackgroundView.contentView : self.glassBackgroundContainer.contentView + let sendActionButtonsDisplayFrame = sendActionButtonsFrame.offsetBy(dx: -textInputContainerBackgroundFrame.minX, dy: -textInputContainerBackgroundFrame.minY) + let sendActionButtonsParentView = self.textInputContainerBackgroundView.contentView if self.sendActionButtons.view.superview !== sendActionButtonsParentView { self.sendActionButtons.view.layer.removeAllAnimations() self.sendActionButtons.view.frame = sendActionButtonsDisplayFrame sendActionButtonsParentView.addSubview(self.sendActionButtons.view) } - if wideGlassLayout.mergeRightSlot { - sendActionButtonsParentView.bringSubviewToFront(self.sendActionButtons.view) - } + sendActionButtonsParentView.bringSubviewToFront(self.sendActionButtons.view) transition.updateTransformScale(node: self.sendActionButtons, scale: CGPoint(x: sendActionsScale, y: sendActionsScale)) transition.updatePosition(node: self.sendActionButtons, position: sendActionButtonsDisplayFrame.center) From a839f3d635e9b8e432b4a5c3a538b2a78870b080 Mon Sep 17 00:00:00 2001 From: Lev Poznyakov Date: Sat, 20 Jun 2026 23:48:25 +0400 Subject: [PATCH 7/9] simplify attempt --- .../Sources/ChatTextInputPanelNode.swift | 264 ++++++++---------- 1 file changed, 122 insertions(+), 142 deletions(-) diff --git a/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/ChatTextInputPanelNode.swift b/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/ChatTextInputPanelNode.swift index 549f904f5e..754c5a13c9 100644 --- a/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/ChatTextInputPanelNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/ChatTextInputPanelNode.swift @@ -308,7 +308,9 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg private var validLayout: (CGFloat, CGFloat, CGFloat, CGFloat, UIEdgeInsets, CGFloat, CGFloat, LayoutMetrics, Bool, Bool, DeviceMetrics)? private var leftMenuInset: CGFloat = 0.0 private var rightSlowModeInset: CGFloat = 0.0 - private var currentWideGlassLayout: WideGlassLayout = .disabled + private var currentTextInputBackgroundWidthOffset: CGFloat = 0.0 + // MARK: Swiftgram + private var currentTextInputViewInternalInsetsOffset = UIEdgeInsets() private var enableBounceAnimations: Bool = false @@ -415,30 +417,6 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg case stars(count: Int, isFilled: Bool, action: (UIView) -> Void, longPressAction: ((UIView) -> Void)?) case liveMicrophone(call: AnyObject?, action: (UIView) -> Void) } - - private struct WideGlassLayout { - static let slotWidth: CGFloat = 40.0 + 6.0 - - let mergeLeftSlot: Bool - let mergeRightSlot: Bool - - static let disabled = WideGlassLayout( - mergeLeftSlot: false, - mergeRightSlot: false - ) - - var leftExtension: CGFloat { - return self.mergeLeftSlot ? Self.slotWidth : 0.0 - } - - var rightExtension: CGFloat { - return self.mergeRightSlot ? Self.slotWidth : 0.0 - } - - var totalWidthExtension: CGFloat { - return self.leftExtension + self.rightExtension - } - } public var customPlaceholder: String? public var customIsDisabled: Bool = false @@ -1240,7 +1218,7 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg return max(33.0, maxHeight - (textFieldInsets.top + textFieldInsets.bottom + self.textInputViewInternalInsets.top + self.textInputViewInternalInsets.bottom)) } - private func calculateTextFieldMetrics(width: CGFloat, sendActionControlsWidth: CGFloat, maxHeight: CGFloat, metrics: LayoutMetrics, bottomInset: CGFloat, interfaceState: ChatPresentationInterfaceState, wideGlassLayout: WideGlassLayout) -> (accessoryButtonsWidth: CGFloat, textFieldHeight: CGFloat, isOverflow: Bool) { + private func calculateTextFieldMetrics(width: CGFloat, sendActionControlsWidth: CGFloat, maxHeight: CGFloat, metrics: LayoutMetrics, bottomInset: CGFloat, interfaceState: ChatPresentationInterfaceState) -> (accessoryButtonsWidth: CGFloat, textFieldHeight: CGFloat, isOverflow: Bool) { let maxHeight = max(maxHeight, 40.0) let textFieldInsets = self.textFieldInsets(metrics: metrics, bottomInset: bottomInset) @@ -1288,7 +1266,13 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg hasSendAsButton = true } - let actualTextInputViewInternalInsets = self.adjustedTextInputViewInternalInsets(hasSendAsButton: hasSendAsButton, wideGlassLayout: wideGlassLayout) + var actualTextInputViewInternalInsets = self.textInputViewInternalInsets + if hasSendAsButton { + actualTextInputViewInternalInsets.left += 31.0 + } + // MARK: Swiftgram + actualTextInputViewInternalInsets.left += self.currentTextInputViewInternalInsetsOffset.left + actualTextInputViewInternalInsets.right += self.currentTextInputViewInternalInsetsOffset.right var textFieldHeight: CGFloat var isOverflow = false @@ -1333,67 +1317,6 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg let result = textFieldHeight + textFieldInsets.top + textFieldInsets.bottom + self.textInputViewInternalInsets.top + self.textInputViewInternalInsets.bottom return result } - - private func adjustedTextInputViewInternalInsets(hasSendAsButton: Bool, wideGlassLayout: WideGlassLayout) -> UIEdgeInsets { - var actualTextInputViewInternalInsets = self.textInputViewInternalInsets - if hasSendAsButton { - actualTextInputViewInternalInsets.left += 35.0 - } - if wideGlassLayout.mergeLeftSlot { - actualTextInputViewInternalInsets.left += 30.0 - } - if wideGlassLayout.mergeRightSlot { - actualTextInputViewInternalInsets.right += 32.0 - } - return actualTextInputViewInternalInsets - } - - private func calculateWideGlassLayout(interfaceState: ChatPresentationInterfaceState, displayMediaButton: Bool, hasMediaRecording: Bool, inputHasText: Bool, hasForward: Bool, hasMediaDraft: Bool, hasSlowmodeButton: Bool, isEditingMedia: Bool) -> WideGlassLayout { - guard SGSimpleSettings.shared.wideGlassTextField else { - return .disabled - } - - let mergeLeftSlot: Bool - if !displayMediaButton || hasMediaRecording { - mergeLeftSlot = false - } else if let customLeftAction = self.customLeftAction { - switch customLeftAction { - case .empty, .toggleExpanded(false, _, _): - mergeLeftSlot = false - default: - mergeLeftSlot = true - } - } else { - mergeLeftSlot = true - } - - var mediaInputIsActive = false - if case .media = interfaceState.inputMode { - mediaInputIsActive = true - } - - var keepSendButtonEnabled = self.keepSendButtonEnabled - if case let .customChatContents(customChatContents) = interfaceState.subject { - switch customChatContents.kind { - case .businessLinkSetup: - keepSendButtonEnabled = true - default: - break - } - } - if hasMediaDraft || hasForward { - keepSendButtonEnabled = true - } - - let sendButtonConsumesRightSlot = inputHasText || hasMediaDraft || hasForward || isEditingMedia || (keepSendButtonEnabled && !mediaInputIsActive && !hasSlowmodeButton) - let hasStandardRightSlot = self.customRightAction == nil && self.customSecondaryRightAction == nil && !hasSlowmodeButton && !self.extendedSearchLayout - let mergeRightSlot = hasStandardRightSlot && !hasMediaRecording && (!SGSimpleSettings.shared.hideRecordingButton || mediaInputIsActive || sendButtonConsumesRightSlot) - - return WideGlassLayout( - mergeLeftSlot: mergeLeftSlot, - mergeRightSlot: mergeRightSlot - ) - } override public func minimalHeight(interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics) -> CGFloat { let textFieldMinHeight = calclulateTextFieldMinHeight(interfaceState, metrics: metrics) @@ -2354,6 +2277,7 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg let originalLeftInset = leftInset // + var textInputBackgroundWidthOffset: CGFloat = 0.0 var attachmentButtonX: CGFloat = hideOffset.x + leftInset + leftMenuInset + 8.0 var leftButtonsWidth: CGFloat = 40.0 + 6.0 @@ -2401,17 +2325,57 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg attachmentButtonX = -8.0 - leftButtonsWidth } - let wideGlassLayout = self.calculateWideGlassLayout( - interfaceState: interfaceState, - displayMediaButton: displayMediaButton, - hasMediaRecording: mediaRecordingState != nil, - inputHasText: inputHasText, - hasForward: hasForward, - hasMediaDraft: hasMediaDraft, - hasSlowmodeButton: hasSlowmodeButton, - isEditingMedia: isEditingMedia - ) - self.currentWideGlassLayout = wideGlassLayout + var textInputBackgroundLeftOffset: CGFloat = 0.0 + var textInputViewInternalInsetsOffset = UIEdgeInsets() + var mergeLeftSlot = false + var mergeRightSlot = false + // MARK: Swiftgram + if SGSimpleSettings.shared.wideGlassTextField { + if !displayMediaButton || mediaRecordingState != nil { + } else if let customLeftAction = self.customLeftAction { + switch customLeftAction { + case .empty, .toggleExpanded(false, _, _): + break + default: + mergeLeftSlot = true + } + } else { + mergeLeftSlot = true + } + + var mediaInputIsActive = false + if case .media = interfaceState.inputMode { + mediaInputIsActive = true + } + + var keepSendButtonEnabled = self.keepSendButtonEnabled + if case let .customChatContents(customChatContents) = interfaceState.subject { + switch customChatContents.kind { + case .businessLinkSetup: + keepSendButtonEnabled = true + default: + break + } + } + if hasMediaDraft || hasForward { + keepSendButtonEnabled = true + } + + let sendButtonConsumesRightSlot = inputHasText || hasMediaDraft || hasForward || isEditingMedia || (keepSendButtonEnabled && !mediaInputIsActive && !hasSlowmodeButton) + let hasStandardRightSlot = self.customRightAction == nil && self.customSecondaryRightAction == nil && !hasSlowmodeButton && !self.extendedSearchLayout + mergeRightSlot = hasStandardRightSlot && mediaRecordingState == nil && (!SGSimpleSettings.shared.hideRecordingButton || mediaInputIsActive || sendButtonConsumesRightSlot) + + if mergeLeftSlot { + textInputBackgroundWidthOffset += 40.0 + 6.0 + textInputBackgroundLeftOffset = 40.0 + 6.0 + textInputViewInternalInsetsOffset.left += 30.0 + } + if mergeRightSlot { + textInputBackgroundWidthOffset += 40.0 + 6.0 + textInputViewInternalInsetsOffset.right += 32.0 + } + } + self.currentTextInputViewInternalInsetsOffset = textInputViewInternalInsetsOffset self.mediaActionButtons.micButton.updateMode(mode: interfaceState.interfaceState.mediaRecordingMode, animated: transition.isAnimated) @@ -2431,8 +2395,9 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg } } } - sendActionButtonsSize = self.sendActionButtons.updateLayout(size: CGSize(width: 40.0, height: minimalHeight), isMediaInputExpanded: isMediaInputExpanded, showTitle: showTitle, currentMessageEffectId: presentationInterfaceState.interfaceState.sendMessageEffect, transition: transition, interfaceState: presentationInterfaceState, mergeBackgroundIntoInputField: wideGlassLayout.mergeRightSlot) - mediaActionButtonsSize = self.mediaActionButtons.updateLayout(size: CGSize(width: 40.0, height: minimalHeight), isMediaInputExpanded: isMediaInputExpanded, showTitle: false, currentMessageEffectId: presentationInterfaceState.interfaceState.sendMessageEffect, transition: transition, interfaceState: presentationInterfaceState, mergeBackgroundIntoInputField: wideGlassLayout.mergeRightSlot) + + sendActionButtonsSize = self.sendActionButtons.updateLayout(size: CGSize(width: 40.0, height: minimalHeight), isMediaInputExpanded: isMediaInputExpanded, showTitle: showTitle, currentMessageEffectId: presentationInterfaceState.interfaceState.sendMessageEffect, transition: transition, interfaceState: presentationInterfaceState, mergeBackgroundIntoInputField: mergeRightSlot) // MARK: Swiftgram + mediaActionButtonsSize = self.mediaActionButtons.updateLayout(size: CGSize(width: 40.0, height: minimalHeight), isMediaInputExpanded: isMediaInputExpanded, showTitle: false, currentMessageEffectId: presentationInterfaceState.interfaceState.sendMessageEffect, transition: transition, interfaceState: presentationInterfaceState, mergeBackgroundIntoInputField: mergeRightSlot) // MARK: Swiftgram } var starReactionButtonSize: CGSize? @@ -2505,7 +2470,7 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg } let baseWidth = width - leftInset - leftMenuInset - rightInset - rightSlowModeInset - let (accessoryButtonsWidth, textFieldHeight, isTextFieldOverflow) = self.calculateTextFieldMetrics(width: baseWidth + wideGlassLayout.totalWidthExtension, sendActionControlsWidth: sendActionButtonsSize.width, maxHeight: maxHeight, metrics: metrics, bottomInset: bottomInset, interfaceState: interfaceState, wideGlassLayout: wideGlassLayout) + let (accessoryButtonsWidth, textFieldHeight, isTextFieldOverflow) = self.calculateTextFieldMetrics(width: baseWidth + textInputBackgroundWidthOffset, sendActionControlsWidth: sendActionButtonsSize.width, maxHeight: maxHeight, metrics: metrics, bottomInset: bottomInset, interfaceState: interfaceState) // MARK: Swiftgram var panelHeight = self.panelHeight(textFieldHeight: textFieldHeight, metrics: metrics, bottomInset: bottomInset) if displayBotStartButton { panelHeight += 27.0 @@ -2573,7 +2538,7 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg break } } - if wideGlassLayout.mergeRightSlot { + if mergeRightSlot { // MARK: Swiftgram textFieldInsets.right = max(textFieldInsets.right, 54.0) } @@ -2943,7 +2908,7 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg } } - let textInputWidth = baseWidth - textFieldInsets.left - textFieldInsets.right + wideGlassLayout.totalWidthExtension + let textInputWidth = baseWidth - textFieldInsets.left - textFieldInsets.right + textInputBackgroundWidthOffset // MARK: Swiftgram let textInputHeight = panelHeight - textFieldInsets.top - textFieldInsets.bottom if let accessoryPanel { @@ -3042,7 +3007,7 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg contentHeight += textFieldInsets.bottom let previousTextInputContainerBackgroundFrame = self.textInputContainerBackgroundView.frame - let textInputContainerBackgroundFrame = CGRect(x: hideOffset.x + leftInset + textFieldInsets.left - wideGlassLayout.leftExtension, y: hideOffset.y + textFieldInsets.top, width: textInputWidth, height: contentHeight) + let textInputContainerBackgroundFrame = CGRect(x: hideOffset.x + leftInset + textFieldInsets.left - textInputBackgroundLeftOffset, y: hideOffset.y + textFieldInsets.top, width: textInputWidth, height: contentHeight) // MARK: Swiftgram let textInputFrame = textInputContainerBackgroundFrame transition.updateFrame(view: self.accessoryPanelContainer, frame: CGRect(origin: CGPoint(), size: textInputContainerBackgroundFrame.size)) @@ -3075,7 +3040,13 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg hasSendAsButton = true } - let actualTextInputViewInternalInsets = self.adjustedTextInputViewInternalInsets(hasSendAsButton: hasSendAsButton, wideGlassLayout: wideGlassLayout) + var actualTextInputViewInternalInsets = self.textInputViewInternalInsets + if hasSendAsButton { + actualTextInputViewInternalInsets.left += 31.0 + } + // MARK: Swiftgram + actualTextInputViewInternalInsets.left += textInputViewInternalInsetsOffset.left + actualTextInputViewInternalInsets.right += textInputViewInternalInsetsOffset.right let textFieldFrame = CGRect(origin: CGPoint(x: actualTextInputViewInternalInsets.left, y: actualTextInputViewInternalInsets.top + textFieldTopContentOffset), size: CGSize(width: textInputFrame.size.width - (actualTextInputViewInternalInsets.left + actualTextInputViewInternalInsets.right), height: textInputHeight - actualTextInputViewInternalInsets.top - actualTextInputViewInternalInsets.bottom)) let textInputNodeClippingContainerFrame = CGRect(origin: CGPoint(x: textFieldFrame.minX - actualTextInputViewInternalInsets.left, y: textFieldFrame.minY - actualTextInputViewInternalInsets.top), size: CGSize(width: textFieldFrame.width + actualTextInputViewInternalInsets.left + actualTextInputViewInternalInsets.right, height: textFieldFrame.height + actualTextInputViewInternalInsets.top + actualTextInputViewInternalInsets.bottom)) @@ -3103,7 +3074,7 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg let placeholderLayout = TextNode.asyncLayout(self.contextPlaceholderNode) let contextPlaceholder = NSMutableAttributedString(attributedString: contextPlaceholder) contextPlaceholder.addAttribute(.foregroundColor, value: placeholderColor.withAlphaComponent(1.0), range: NSRange(location: 0, length: contextPlaceholder.length)) - let (placeholderSize, placeholderApply) = placeholderLayout(TextNodeLayoutArguments(attributedString: contextPlaceholder, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: textInputWidth - actualTextInputViewInternalInsets.left - actualTextInputViewInternalInsets.right - accessoryButtonsWidth, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets())) + let (placeholderSize, placeholderApply) = placeholderLayout(TextNodeLayoutArguments(attributedString: contextPlaceholder, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: width - leftInset - rightInset - textFieldInsets.left - textFieldInsets.right + textInputBackgroundWidthOffset - actualTextInputViewInternalInsets.left - actualTextInputViewInternalInsets.right - accessoryButtonsWidth, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets())) // MARK: Swiftgram let tintContextPlaceholder = NSMutableAttributedString(attributedString: contextPlaceholder) tintContextPlaceholder.addAttribute(.foregroundColor, value: UIColor.black, range: NSRange(location: 0, length: tintContextPlaceholder.length)) let contextPlaceholderNode = placeholderApply() @@ -3147,7 +3118,7 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg self.slowmodePlaceholderNode = slowmodePlaceholderNode self.textInputContainerBackgroundView.contentView.insertSubview(slowmodePlaceholderNode.view, aboveSubview: self.textPlaceholderNode.view) } - let placeholderFrame = CGRect(origin: CGPoint(x: actualTextInputViewInternalInsets.left, y: textFieldInsets.top + actualTextInputViewInternalInsets.top + textInputViewRealInsets.top + UIScreenPixel + textFieldTopContentOffset), size: CGSize(width: textInputWidth - actualTextInputViewInternalInsets.left - actualTextInputViewInternalInsets.right - accessoryButtonsWidth, height: 30.0)) + let placeholderFrame = CGRect(origin: CGPoint(x: actualTextInputViewInternalInsets.left, y: textFieldInsets.top + actualTextInputViewInternalInsets.top + textInputViewRealInsets.top + UIScreenPixel + textFieldTopContentOffset), size: CGSize(width: width - leftInset - rightInset - textFieldInsets.left - textFieldInsets.right + textInputBackgroundWidthOffset - actualTextInputViewInternalInsets.left - actualTextInputViewInternalInsets.right - accessoryButtonsWidth, height: 30.0)) // MARK: Swiftgram slowmodePlaceholderNode.updateState(slowmodeState) if slowmodePlaceholderNode.bounds.isEmpty { slowmodePlaceholderNode.frame = placeholderFrame @@ -3174,7 +3145,7 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg if self.extendedSearchLayout { nextButtonTopRight.x -= 46.0 } else if hasSlowmodeButton { - } else if wideGlassLayout.mergeRightSlot { + } else if mergeRightSlot { // MARK: Swiftgram nextButtonTopRight.x = textInputContainerBackgroundFrame.width - 40.0 - actionButtonContentSpacing } else if inputHasText || hasMediaDraft || hasForward || isEditingMedia { nextButtonTopRight.x -= sendActionButtonsSize.width @@ -3205,6 +3176,8 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg } } + self.currentTextInputBackgroundWidthOffset = textInputBackgroundWidthOffset + let textPlaceholderSize: CGSize let textPlaceholderMaxWidth: CGFloat = max(1.0, nextButtonTopRight.x - 12.0) @@ -3275,7 +3248,7 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg transition.updateFrame(node: self.textPlaceholderNode, frame: textPlaceholderFrame) - let sendAsButtonFrame = CGRect(origin: CGPoint(x: max(3.0, actualTextInputViewInternalInsets.left - 40.0), y: textInputContainerBackgroundFrame.height - 3.0 - 34.0), size: CGSize(width: 34.0, height: 34.0)) + let sendAsButtonFrame = CGRect(origin: CGPoint(x: max(3.0, actualTextInputViewInternalInsets.left - 40.0), y: textInputContainerBackgroundFrame.height - 3.0 - 34.0), size: CGSize(width: 34.0, height: 34.0)) // MARK: Swiftgram let sendAsAvatarButtonAlpha: CGFloat = audioRecordingItemsAlpha * (displaySendAsAvatarButton ? 1.0 : 0.0) transition.updatePosition(node: self.sendAsAvatarButtonNode, position: sendAsButtonFrame.center) transition.updateBounds(node: self.sendAsAvatarButtonNode, bounds: CGRect(origin: CGPoint(), size: sendAsButtonFrame.size)) @@ -3324,27 +3297,26 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg } var mediaActionButtonsFrame = CGRect(origin: CGPoint(x: textInputContainerBackgroundFrame.maxX + 6.0, y: textInputContainerBackgroundFrame.maxY - mediaActionButtonsSize.height), size: mediaActionButtonsSize) - if wideGlassLayout.mergeRightSlot { + if mergeRightSlot { // MARK: Swiftgram mediaActionButtonsFrame.origin.x = textInputContainerBackgroundFrame.maxX - mediaActionButtonsSize.width } if inputHasText || self.extendedSearchLayout || hasMediaDraft || interfaceState.interfaceState.forwardMessageIds != nil || hasSlowmodeButton || isEditingMedia { - if !wideGlassLayout.mergeRightSlot { + if !mergeRightSlot { // MARK: Swiftgram mediaActionButtonsFrame.origin.x = width + 8.0 } } - let mediaActionButtonsDisplayFrame: CGRect - if wideGlassLayout.mergeRightSlot { - mediaActionButtonsDisplayFrame = mediaActionButtonsFrame.offsetBy(dx: -textInputContainerBackgroundFrame.minX, dy: -textInputContainerBackgroundFrame.minY) + let mediaActionButtonsFrameInParent: CGRect + if mergeRightSlot { // MARK: Swiftgram + mediaActionButtonsFrameInParent = mediaActionButtonsFrame.offsetBy(dx: -textInputContainerBackgroundFrame.minX, dy: -textInputContainerBackgroundFrame.minY) } else { - mediaActionButtonsDisplayFrame = mediaActionButtonsFrame + mediaActionButtonsFrameInParent = mediaActionButtonsFrame } - let mediaActionButtonsParentView = wideGlassLayout.mergeRightSlot ? self.textInputContainerBackgroundView.contentView : self.glassBackgroundContainer.contentView + let mediaActionButtonsParentView = mergeRightSlot ? self.textInputContainerBackgroundView.contentView : self.glassBackgroundContainer.contentView // MARK: Swiftgram if self.mediaActionButtons.view.superview !== mediaActionButtonsParentView { - self.mediaActionButtons.view.layer.removeAllAnimations() - self.mediaActionButtons.view.frame = mediaActionButtonsDisplayFrame + self.mediaActionButtons.view.frame = mediaActionButtonsFrameInParent mediaActionButtonsParentView.addSubview(self.mediaActionButtons.view) } - transition.updateFrame(node: self.mediaActionButtons, frame: mediaActionButtonsDisplayFrame) + transition.updateFrame(node: self.mediaActionButtons, frame: mediaActionButtonsFrameInParent) if let (rect, containerSize) = self.absoluteRect { self.mediaActionButtons.updateAbsoluteRect(CGRect(x: rect.origin.x + mediaActionButtonsFrame.origin.x, y: rect.origin.y + mediaActionButtonsFrame.origin.y, width: mediaActionButtonsFrame.width, height: mediaActionButtonsFrame.height), within: containerSize, transition: transition) } @@ -3396,19 +3368,18 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg sendActionButtonsFrame.origin.x += (sendActionButtonsSize.width - 3.0 * 2.0) * 0.5 - 3.0 } - let sendActionButtonsDisplayFrame = sendActionButtonsFrame.offsetBy(dx: -textInputContainerBackgroundFrame.minX, dy: -textInputContainerBackgroundFrame.minY) - let sendActionButtonsParentView = self.textInputContainerBackgroundView.contentView + let sendActionButtonsFrameInParent = sendActionButtonsFrame.offsetBy(dx: -textInputContainerBackgroundFrame.minX, dy: -textInputContainerBackgroundFrame.minY) // MARK: Swiftgram + let sendActionButtonsParentView = self.textInputContainerBackgroundView.contentView // MARK: Swiftgram if self.sendActionButtons.view.superview !== sendActionButtonsParentView { - self.sendActionButtons.view.layer.removeAllAnimations() - self.sendActionButtons.view.frame = sendActionButtonsDisplayFrame + self.sendActionButtons.view.frame = sendActionButtonsFrameInParent sendActionButtonsParentView.addSubview(self.sendActionButtons.view) } sendActionButtonsParentView.bringSubviewToFront(self.sendActionButtons.view) transition.updateTransformScale(node: self.sendActionButtons, scale: CGPoint(x: sendActionsScale, y: sendActionsScale)) - transition.updatePosition(node: self.sendActionButtons, position: sendActionButtonsDisplayFrame.center) + transition.updatePosition(node: self.sendActionButtons, position: sendActionButtonsFrameInParent.center) - transition.updateBounds(node: self.sendActionButtons, bounds: CGRect(origin: CGPoint(), size: sendActionButtonsDisplayFrame.size)) + transition.updateBounds(node: self.sendActionButtons, bounds: CGRect(origin: CGPoint(), size: sendActionButtonsFrameInParent.size)) if let (rect, containerSize) = self.absoluteRect { self.sendActionButtons.updateAbsoluteRect(CGRect(x: rect.origin.x + sendActionButtonsFrame.origin.x, y: rect.origin.y + sendActionButtonsFrame.origin.y, width: sendActionButtonsFrame.width, height: sendActionButtonsFrame.height), within: containerSize, transition: transition) } @@ -3419,7 +3390,7 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg if let _ = interfaceState.inputTextPanelState.mediaRecordingState { let text: String = interfaceState.strings.VoiceOver_MessageContextSend let mediaRecordingAccessibilityArea: AccessibilityAreaNode - let mediaRecordingAccessibilityParentView = self.mediaActionButtons.view.superview ?? self.glassBackgroundContainer.contentView + let mediaRecordingAccessibilityParentView = self.mediaActionButtons.view.superview ?? self.glassBackgroundContainer.contentView // MARK: Swiftgram var added = false if let current = self.mediaRecordingAccessibilityArea { mediaRecordingAccessibilityArea = current @@ -3436,7 +3407,7 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg return true } } - if mediaRecordingAccessibilityArea.view.superview !== mediaRecordingAccessibilityParentView { + if mediaRecordingAccessibilityArea.view.superview !== mediaRecordingAccessibilityParentView { // MARK: Swiftgram if mediaRecordingAccessibilityArea.view.superview != nil { mediaRecordingAccessibilityArea.view.removeFromSuperview() } @@ -3448,7 +3419,7 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg } self.mediaActionButtons.isAccessibilityElement = false let size: CGFloat = 120.0 - mediaRecordingAccessibilityArea.frame = CGRect(origin: CGPoint(x: mediaActionButtonsDisplayFrame.midX - size / 2.0, y: mediaActionButtonsDisplayFrame.midY - size / 2.0), size: CGSize(width: size, height: size)) + mediaRecordingAccessibilityArea.frame = CGRect(origin: CGPoint(x: mediaActionButtonsFrameInParent.midX - size / 2.0, y: mediaActionButtonsFrameInParent.midY - size / 2.0), size: CGSize(width: size, height: size)) // MARK: Swiftgram if added { DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.4, execute: { [weak mediaRecordingAccessibilityArea] in @@ -3477,24 +3448,24 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg let attachmentButtonFrame = CGRect(origin: CGPoint(x: attachmentButtonX, y: textInputFrame.maxY - 40.0), size: CGSize(width: 40.0, height: 40.0)) attachmentButtonX += 40.0 + 6.0 - let attachmentButtonParentView = wideGlassLayout.mergeLeftSlot ? self.textInputContainerBackgroundView.contentView : self.glassBackgroundContainer.contentView + let attachmentButtonParentView = mergeLeftSlot ? self.textInputContainerBackgroundView.contentView : self.glassBackgroundContainer.contentView // MARK: Swiftgram if self.attachmentButtonBackground.superview !== attachmentButtonParentView { attachmentButtonParentView.addSubview(self.attachmentButtonBackground) } if self.attachmentButtonDisabledNode.view.superview !== attachmentButtonParentView { attachmentButtonParentView.addSubview(self.attachmentButtonDisabledNode.view) } - let attachmentButtonDisplayFrame: CGRect - if wideGlassLayout.mergeLeftSlot { - attachmentButtonDisplayFrame = attachmentButtonFrame.offsetBy(dx: -textInputContainerBackgroundFrame.minX, dy: -textInputContainerBackgroundFrame.minY) + let attachmentButtonFrameInParent: CGRect + if mergeLeftSlot { // MARK: Swiftgram + attachmentButtonFrameInParent = attachmentButtonFrame.offsetBy(dx: -textInputContainerBackgroundFrame.minX, dy: -textInputContainerBackgroundFrame.minY) } else { - attachmentButtonDisplayFrame = attachmentButtonFrame + attachmentButtonFrameInParent = attachmentButtonFrame } - self.attachmentButtonBackground.update(size: attachmentButtonFrame.size, cornerRadius: attachmentButtonFrame.height * 0.5, isDark: interfaceState.theme.overallDarkAppearance, tintColor: defaultGlassTintColor, isInteractive: true, isVisible: !wideGlassLayout.mergeLeftSlot, transition: ComponentTransition(transition)) + self.attachmentButtonBackground.update(size: attachmentButtonFrame.size, cornerRadius: attachmentButtonFrame.height * 0.5, isDark: interfaceState.theme.overallDarkAppearance, tintColor: defaultGlassTintColor, isInteractive: true, isVisible: !mergeLeftSlot, transition: ComponentTransition(transition)) // MARK: Swiftgram - transition.updateFrame(layer: self.attachmentButtonBackground.layer, frame: attachmentButtonDisplayFrame) + transition.updateFrame(layer: self.attachmentButtonBackground.layer, frame: attachmentButtonFrameInParent) transition.updateFrame(layer: self.attachmentButton.layer, frame: CGRect(origin: CGPoint(), size: attachmentButtonFrame.size)) - transition.updateFrame(node: self.attachmentButtonDisabledNode, frame: attachmentButtonDisplayFrame) + transition.updateFrame(node: self.attachmentButtonDisabledNode, frame: attachmentButtonFrameInParent) if let image = self.attachmentButtonIcon.image { let attachmentButtonIconFrame = CGRect(origin: CGPoint(x: floor((attachmentButtonFrame.width - image.size.width) * 0.5), y: floor((attachmentButtonFrame.height - image.size.height) * 0.5)), size: image.size) @@ -4869,8 +4840,8 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg leftInset += compactBottomSideInset rightInset += compactBottomSideInset - let baseWidth = width - leftInset - self.leftMenuInset - rightInset - self.rightSlowModeInset - additionalSideInsets.right - let (_, textFieldHeight, _) = self.calculateTextFieldMetrics(width: baseWidth + self.currentWideGlassLayout.totalWidthExtension, sendActionControlsWidth: self.sendActionButtons.bounds.width, maxHeight: maxHeight, metrics: metrics, bottomInset: bottomInset, interfaceState: interfaceState, wideGlassLayout: self.currentWideGlassLayout) + let baseWidth = width - leftInset - self.leftMenuInset - rightInset - self.rightSlowModeInset + self.currentTextInputBackgroundWidthOffset - additionalSideInsets.right + let (_, textFieldHeight, _) = self.calculateTextFieldMetrics(width: baseWidth, sendActionControlsWidth: self.sendActionButtons.bounds.width, maxHeight: maxHeight, metrics: metrics, bottomInset: bottomInset, interfaceState: interfaceState) let panelHeight = self.panelHeight(textFieldHeight: textFieldHeight, metrics: metrics, bottomInset: bottomInset) if !self.bounds.size.height.isEqual(to: panelHeight) { self.updateHeight(animated) @@ -5817,7 +5788,8 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg public func getAttachmentButton() -> UIView { return self.attachmentButton } - + + // MARK: Swiftgram private func frameInPanelCoordinates(for view: UIView) -> CGRect? { guard let superview = view.superview else { return nil @@ -5826,9 +5798,13 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg } public func frameForAttachmentButton() -> CGRect? { - if !self.attachmentButtonBackground.alpha.isZero, let frame = self.frameInPanelCoordinates(for: self.attachmentButtonBackground) { + // MARK: Swiftgram + if SGSimpleSettings.shared.wideGlassTextField, !self.attachmentButtonBackground.alpha.isZero, let frame = self.frameInPanelCoordinates(for: self.attachmentButtonBackground) { return frame.insetBy(dx: 0.0, dy: -4.0).offsetBy(dx: 0.0, dy: 0.0) } + if !self.attachmentButtonBackground.alpha.isZero { + return self.attachmentButtonBackground.frame.insetBy(dx: 0.0, dy: -4.0).offsetBy(dx: 0.0, dy: 0.0) + } return nil } @@ -5840,9 +5816,13 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg } public func frameForInputActionButton() -> CGRect? { - if !self.mediaActionButtons.alpha.isZero, let frame = self.frameInPanelCoordinates(for: self.mediaActionButtons.view), frame.minX < self.bounds.width { + // MARK: Swiftgram + if SGSimpleSettings.shared.wideGlassTextField, !self.mediaActionButtons.alpha.isZero, let frame = self.frameInPanelCoordinates(for: self.mediaActionButtons.view), frame.minX < self.bounds.width { return frame.insetBy(dx: 0.0, dy: -4.0).offsetBy(dx: -3.0, dy: 0.0) } + if !self.mediaActionButtons.alpha.isZero && self.mediaActionButtons.frame.minX < self.bounds.width { + return self.mediaActionButtons.frame.insetBy(dx: 0.0, dy: -4.0).offsetBy(dx: -3.0, dy: 0.0) + } return nil } From 5308074cbbdf83c83241205f7c161cd37f20cab6 Mon Sep 17 00:00:00 2001 From: Lev Poznyakov Date: Mon, 22 Jun 2026 22:52:19 +0400 Subject: [PATCH 8/9] Fix wide glass text field layout --- .../Sources/ChatTextInputPanelNode.swift | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/ChatTextInputPanelNode.swift b/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/ChatTextInputPanelNode.swift index 754c5a13c9..e44eb4042a 100644 --- a/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/ChatTextInputPanelNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/ChatTextInputPanelNode.swift @@ -2469,8 +2469,10 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg effectiveActionButtonsSize.width += 6.0 + liveMicrophoneButtonSize.width } + let textFieldActionControlsWidth: CGFloat = mergeRightSlot ? 0.0 : sendActionButtonsSize.width // MARK: Swiftgram + let textFieldMeasurementWidthOffset = textInputBackgroundWidthOffset - (mergeRightSlot ? 40.0 + 6.0 : 0.0) // MARK: Swiftgram let baseWidth = width - leftInset - leftMenuInset - rightInset - rightSlowModeInset - let (accessoryButtonsWidth, textFieldHeight, isTextFieldOverflow) = self.calculateTextFieldMetrics(width: baseWidth + textInputBackgroundWidthOffset, sendActionControlsWidth: sendActionButtonsSize.width, maxHeight: maxHeight, metrics: metrics, bottomInset: bottomInset, interfaceState: interfaceState) // MARK: Swiftgram + let (accessoryButtonsWidth, textFieldHeight, isTextFieldOverflow) = self.calculateTextFieldMetrics(width: baseWidth + textFieldMeasurementWidthOffset, sendActionControlsWidth: textFieldActionControlsWidth, maxHeight: maxHeight, metrics: metrics, bottomInset: bottomInset, interfaceState: interfaceState) // MARK: Swiftgram var panelHeight = self.panelHeight(textFieldHeight: textFieldHeight, metrics: metrics, bottomInset: bottomInset) if displayBotStartButton { panelHeight += 27.0 @@ -2888,7 +2890,7 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg var textInputViewRealInsets = UIEdgeInsets() if let presentationInterfaceState = self.presentationInterfaceState { - textInputViewRealInsets = calculateTextFieldRealInsets(presentationInterfaceState: presentationInterfaceState, accessoryButtonsWidth: accessoryButtonsWidth, actionControlsWidth: effectiveActionButtonsSize.width) + textInputViewRealInsets = calculateTextFieldRealInsets(presentationInterfaceState: presentationInterfaceState, accessoryButtonsWidth: accessoryButtonsWidth, actionControlsWidth: mergeRightSlot ? 0.0 : effectiveActionButtonsSize.width) // MARK: Swiftgram } var contentHeight: CGFloat = 0.0 @@ -3062,6 +3064,7 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg if let textInputNode = self.textInputNode { textInputNode.textContainerInset = textInputViewRealInsets + textInputNode.textView.scrollIndicatorInsets = UIEdgeInsets(top: 9.0, left: 0.0, bottom: 9.0, right: mergeRightSlot ? -(actualTextInputViewInternalInsets.right + 2.0) : -13.0) // MARK: Swiftgram textInputNode.frame = actualTextFieldFrame textInputNode.updateLayout(size: textFieldFrame.size) self.updateInputField(textInputFrame: textFieldFrame, transition: ComponentTransition(transition)) @@ -4840,8 +4843,10 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg leftInset += compactBottomSideInset rightInset += compactBottomSideInset - let baseWidth = width - leftInset - self.leftMenuInset - rightInset - self.rightSlowModeInset + self.currentTextInputBackgroundWidthOffset - additionalSideInsets.right - let (_, textFieldHeight, _) = self.calculateTextFieldMetrics(width: baseWidth, sendActionControlsWidth: self.sendActionButtons.bounds.width, maxHeight: maxHeight, metrics: metrics, bottomInset: bottomInset, interfaceState: interfaceState) + let hasMergedRightSlot = !self.currentTextInputViewInternalInsetsOffset.right.isZero // MARK: Swiftgram + let textFieldMeasurementWidthOffset = self.currentTextInputBackgroundWidthOffset - (hasMergedRightSlot ? 40.0 + 6.0 : 0.0) // MARK: Swiftgram + let baseWidth = width - leftInset - self.leftMenuInset - rightInset - self.rightSlowModeInset + textFieldMeasurementWidthOffset - additionalSideInsets.right + let (_, textFieldHeight, _) = self.calculateTextFieldMetrics(width: baseWidth, sendActionControlsWidth: hasMergedRightSlot ? 0.0 : self.sendActionButtons.bounds.width, maxHeight: maxHeight, metrics: metrics, bottomInset: bottomInset, interfaceState: interfaceState) // MARK: Swiftgram let panelHeight = self.panelHeight(textFieldHeight: textFieldHeight, metrics: metrics, bottomInset: bottomInset) if !self.bounds.size.height.isEqual(to: panelHeight) { self.updateHeight(animated) From 57729d60267cc5787885d4f562116de8031409ab Mon Sep 17 00:00:00 2001 From: Lev Poznyakov Date: Tue, 23 Jun 2026 16:43:15 +0400 Subject: [PATCH 9/9] Fix wide glass text field send transition --- .../Sources/ChatTextInputPanelNode.swift | 31 ++++++++++++++++--- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/ChatTextInputPanelNode.swift b/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/ChatTextInputPanelNode.swift index e44eb4042a..59bdd1cbae 100644 --- a/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/ChatTextInputPanelNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/ChatTextInputPanelNode.swift @@ -310,6 +310,7 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg private var rightSlowModeInset: CGFloat = 0.0 private var currentTextInputBackgroundWidthOffset: CGFloat = 0.0 // MARK: Swiftgram + private var currentTextInputBackgroundLeftOffset: CGFloat = 0.0 private var currentTextInputViewInternalInsetsOffset = UIEdgeInsets() private var enableBounceAnimations: Bool = false @@ -3180,6 +3181,7 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg } self.currentTextInputBackgroundWidthOffset = textInputBackgroundWidthOffset + self.currentTextInputBackgroundLeftOffset = textInputBackgroundLeftOffset // MARK: Swiftgram let textPlaceholderSize: CGSize let textPlaceholderMaxWidth: CGFloat = max(1.0, nextButtonTopRight.x - 12.0) @@ -5864,7 +5866,22 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg } let backgroundView = UIImageView() - backgroundView.frame = self.textInputBackgroundNode.view.convert(self.textInputBackgroundNode.bounds, to: self.view) + let backgroundFrame = self.textInputBackgroundNode.view.convert(self.textInputBackgroundNode.bounds, to: self.view) + backgroundView.frame = backgroundFrame + var sourceRect = self.view.convert(self.bounds, to: nil) + + // MARK: Swiftgram + let transitionBackgroundLeftOffset = max(0.0, min(self.currentTextInputBackgroundLeftOffset, backgroundFrame.width)) + if !transitionBackgroundLeftOffset.isZero { + let transitionBackgroundFrame = CGRect( + x: backgroundFrame.minX + transitionBackgroundLeftOffset, + y: backgroundFrame.minY, + width: backgroundFrame.width - transitionBackgroundLeftOffset, + height: backgroundFrame.height + ) + backgroundView.frame = CGRect(origin: CGPoint(), size: transitionBackgroundFrame.size) + sourceRect = self.view.convert(transitionBackgroundFrame, to: nil) + } let caretColor = textInputNode.textView.tintColor textInputNode.textView.tintColor = .clear @@ -5876,15 +5893,19 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg textInputNode.textView.tintColor = caretColor - if let textInputNodeSuperview = textInputNode.view.superview { - let _ = textInputNodeSuperview - contentView.frame = textInputNode.frame.offsetBy(dx: 0.0, dy: self.textInputNodeClippingContainer.frame.minY) + if textInputNode.view.superview != nil { + var contentFrame = textInputNode.frame.offsetBy(dx: 0.0, dy: self.textInputNodeClippingContainer.frame.minY) + // MARK: Swiftgram + if !transitionBackgroundLeftOffset.isZero { + contentFrame.origin.x -= max(0.0, min(self.currentTextInputViewInternalInsetsOffset.left, contentFrame.minX)) + } + contentView.frame = contentFrame } return ( backgroundView: backgroundView, contentView: contentView, - sourceRect: self.view.convert(self.bounds, to: nil), + sourceRect: sourceRect, scrollOffset: textInputNode.textView.contentOffset.y ) }